Автоматическое оповещение читателей о новостях с помощью ВКонтакте. Часть 4

    На хабре уже было несколько статей о работе с вконтактом (раз, два, три), однако оно производилось через простые запросы на страницы с последующим ее парсингом. Это ужасно неправильно, так как если верстка страницы либо порядок запросов поменяется — скрипт перестанет работать. Кроме того, если не ошибаюсь, это запрещено правилами сайта.
    Для этого есть официальный API от вконтакте.


    Для начала определим нашу задачу. На серверной стороне нам необходимо работать с данными ВК, например автоматически оповещать читателей о новостях, искать видео, аудио и т.д. Поэтому у нас будет происходить работа через одного пользователя — администратора приложения.

    Начнем с регистрации приложения
    На странице для разработчиков выбираем «Подключить сайт».

    Тип приложения — Standalone. С ним у нас будет доступно больше методов, которые не доступны если подключать просто веб-сайт.


    Дальше мы видим страницу управления приложением:


    Вы можете подробнее прочитать о авторизации приложений в документации.

    После регистрации для работы нам необходимо получить access token.
    Для этого, и остальной работы с API будем использовать написанный мною класс.

    В классе нужно прописать client_id:


    Выполняем метод авторизации:
    VkApi::auth(array('offline', 'wall'));
    

    В метод auth() можно указать массив прав приложения. Весь список можно посмотреть в документации.
    Хочу заметить, что полученный в итоге access token мы будем прописывать в тело класса. А так как обычная сессия живет не долго — нам придется постоянно обновлять токен. Есть выход — добавить в список необходимых прав offline-право. Тогда мы получим долгоживущую сессию, которая собъется только если будет сменен пароль текущего пользователя.

    Запускаем скрипт в браузере и видим страницу авторизации:


    Дальше запрос доступа приложения:


    После разрешения на выходе нам дают все необходимые параметры:
    access_token=%access_token%&expires_in=0&user_id=%userid%

    Прописываем access token внутрь класса:


    Всё! Готово, теперь мы можем использовать методы API.
    В документации есть список и описание методов.

    Например, отправляем сообщение на стену. Если отправляем на страницу или группу, в owner_id нужно добавить минус перед номером страницы. Чтобы писать от имени страницы указывается from_group.
    VkApi::invoke('wall.post', array(
        'owner_id' => '%id%',
        'message' => '%message%',
        'from_group' => 1
    ));
    

    Осталось соорудить скрипт получения необходимых новостей, отправлять их с помощью метода написанного выше, и повесить скрипт в cron. Но это зависит от вашего приложения и целей.

    UPD Обновил класс и примеры.
    AdBlock has stolen the banner, but banners are not teeth — they will be back

    More
    Ads

    Comments 43

    • UFO just landed and posted this here
        –5
        Ох. Неожидал вас увидеть в своем топике :)
        Спасибо, за такой подробный комментарий.
        Код в статье был для примера, если кому-то нужно — он исправит его под себя. Я не стал оформлять все по стандартам, с документацией, потому что для примера это не нужно. Важно увидеть как оно работает.
          0
          *не ожидал, конечно же
          +2
          А где тут синглтон?
            –1
            > Выполняем метод авторизации:
            > Vkapi::factory()->auth();
              –3
              Нет, технически не синглтон. Но класс, имеющий только приватные поля, которые не изменяются — по духу и поведению настоящий синглтон.
                0
                У синглона вполне могут меняться поля.
                Если у класса может быть лишь один экземпляр в приложении — вот его дух :)
                  –2
                  > У синглона вполне могут меняться поля.
                  А я наверное сказал, что не могут?
                    0
                    А я сказал, что вы сказали, что не могут?
                    Какой вы зануда.
                +1
                И? Синглтон гарантирует что у класса будет только один экземпляр, доступный из любого места приложения. Код, который вы процитировали, всегда будет возвращать новый объект класса Vkapi. Где синглтон то? Я бы еще мог предположить что этим кодом реализуется синглтон, если бы увидел Vkapi::instance();, пока не заглянул бы в этот метод.

                Еще не совсем понимаю зачем автор попытался изобразить factory. factory method все равно не получился (да он тут и не нужен), а в заблуждение ввести может.

                И конструкции типа Vkapi::factory()->auth(); я бы поостерегся использовать, есть вероятность словить unexpected T_PAAMAYIM_NEKUDOTAYIM, зато
                $vk = Vkapi::factory();
                $vk->auth();
                

                будет работать везде.
                  +1
                  Ааа, попутал насчет T_PAAMAYIM_NEKUDOTAYIM. Ну да ладно.
            +2
            Правильно я понимаю, что это годится только для «себя, любимого»? То есть токен связан с конкретным user_id?
              –3
              Да, именно так. В этом и была начальная задача. Можно изменить код под многопользовательскую работу.
                +2
                Зачем выкладывать на хабр такие вот, сделанные только под «себя», неконфигурируемые, недопиленные для общего использования вещи?
                Какой вообще в этом смысл?
                  0
                  Была задача использовать api исключительно на стороне сервера. С одного пользователя. Посмотрите предыдущий топик на эту тему.
                    +2
                    Затем, что аудитория хабра — это не одни гики и кармадрочеры. Есть еще так называемый «средний слой», состоящий из людей вроде меня, которые что-то могут, но им нужна простая и понятная инструкция, а не наброски под общим заголовком «кто знает, тот разберется, а остальным не надо». Я по этой инструкции решил для себя вопрос публикации статей вконтакте из Жумлы, чего не смог сделать по другим, таким «допиленным» и «высококонфигурируемым».

                    Вот уж что, а допилить я смогу и сам. Мне с нуля сложно разобраться, как и многим. Так что, не стоит по себе, такому умному и «допиленному», мерять всех.
                      +1
                      Тут вопрос скорее в том, что вы этот же вопрос могли решить парой-тройкой строк кода и этот код выглядел бы куда как понятнее и нагляднее.
                      А тут получается ООП ради ООП и паттерны (вернее попытка их имитации) ради паттернов.

                      А насчет надо ли оно на хабре… ну не знаю. Судя по тому, что топик добавляют в избранное — наверное надо. Но тогда и реализация не должна быть такой хромой.
                        0
                        Я не вижу ничего непонятного в этом коде. Он короткий, и я даже не знаю, что в нем можно сократить. По крайней мере, по этому коду я понял, что к чему, а кроме него тут только весьма громоздкий и шаткий пример с курлом, да задротское объяснение из вышеупомянутой категории «для тех, кто понимает».

                        Суть, повторюсь, в том, чтобы стало понятно. Дальше если есть мозги и желание — человек сам доделает, нет мозгов — ну, будет ждать готового решения, на что тоже имеет право. Так что, повторюсь, из всех имеющихся примеров этот пока наиболее просто и понятен. Можете сделать еще проще и понятнее унд избавить от необходимости получать токен через браузер — буду вам весьма признателен. Необходимость получения токена — единственное, что грустит слегка.
                          0
                          Токен получать придется в любом случае, но в вашей ситуации это разовая операция.
                          А для публикации достаточно:
                          $data = array(
                                  'owner_id'        => ид_юзера,
                                  'message'        => 'сообщение',
                                  'from_group'    => 1,
                                  'access_token' => 'токен',
                              );
                          $content = file_get_contents('https://api.vkontakte.ru/method/wall.post?'.http_build_query($data));
                          
                            0
                            Токен я давно уже получил, не в этом проблема совершенно. Я просто пишу плагин для кроспосстинга статей из жумлы, и не очень понимаю, как реализовать вот такое получение токена. Плагин я потом выложу в репозиторий жумлы, и писать в инструкции, мол, запустите ручками плагин таким-то образом, чтобы получить токен — это моветон. Вот потому и хочется этот момент реализовать более человечно.
                              0
                              clck.ru/W2MJ
                              client_secret заберите на странице настройки приложения.
                                +1
                                Выглядит красиво, но на деле выдает ошибку «User authorization failed: method is unavailable with server auth». Пишут, что с сервера такие запросы не обрабатываются — только со стороны клиента. Уберглупо, конечно.
                                  0
                                  Тогда только с разрешением юзера.
                                    0
                                    Ну да, других вариантов нет, получается. То есть в «тихом» режиме никак не реализовать.
                                0
                                >писать в инструкции, мол, запустите ручками плагин таким-то образом, чтобы получить токен — это моветон.

                                При использовании сторонних сервисов типа Google Analytics, AdSense, Akismet, Loginza(?), FB, VK и т. п. — это не моветон, а норма написать «зайдите на сайт по этой ссылке и получите такой-то ключ/id, который введите в это поле», а то и вообще «в строчку такую-то файла такого-то». Альтернатива сообщить плагину свой логин и пароль, чтобы он сам сделал запрос и распарсил результат, очень небезопасна — может плагин ещё сделает этот запрос на coolhacker.example.com.
                                  0
                                  Ну, я в теории понимаю, что это с токи зрения безопасности правильно, но в плане удобстве — далеко не супер. В общем, реализовал это дело через колорбокс — вроде работает.
                  +2
                  А зачем тут фабрика?
                    0
                    И я о том же, Vk::factory() выглядит вообще абсурдно, оно понятно если Vk::getInstance(), чтобы не вызывать auth каждый раз, нам нужен один экземпляр.
                      0
                      Для того, что бы не использовать new и писать в одну строчку. В 5.4 это можно будет заменить через (new Vkapi)->auth();
                        0
                        У factory method есть своя область применения и свои цели. Он оперирует подклассами.
                        В данном случае он называется factory, а фабрикой не является. Зачем?

                        $api = Vkapi::init();
                        $api->auth();
                        $api->wall_post($message);
                        
                          0
                          Согласен, как-то не подумал. Заменил на статические функции. По сути объект не меняется, а класс служит лишь оберткой для обычных функций, с хранением параметров авторизации.
                      +1
                      Код скриншотами… У хабра ведь есть прекраснейший тег <source lang=''..">
                        0
                        Все работает, спасибо. Только не нашел, как решить проблему со ссылками. Добавил к массиву переменную 'attachment', подсунул ей адрес сайта, так вместо красивой ссылки, как у новостей в той же группе хабра, он подсовывает еще и картинку с описанием. Как это убрать в данном случае — ума не приложу. Все это можно получить по методу wall.getById, но что потом с этим делать — неизвестно. Там есть переменная noparse, но она используется, когда делишься ссылками. Вот бы что-то подобное подсовывать и тут, потому что ну совсем не нужны эти описалова с картинками в данном случае. Ну, мне не нужны, скажем так :-)
                        • UFO just landed and posted this here
                            0
                            Если запрашивать с офлайн-доступом, то не временный. Я говорил об этом в статье.
                            0
                            Это работает только для приложений, которые юзер должен эксплицитно установить. Для «сайтов» оповещения, стена и прочие методы, изменяющие данные, не работают. Поправьте меня, если это не так. Я пробовал неделю назад, но, может быть, не очень дотошно.
                              +1
                              В статье описан совершенно другой случай. Вы — сам себе единственный юзер, которому нужно выполнять на сервере запросы к апи.
                                0
                                Понятно. Просто называется «автоматическое оповещение читателей...», называть себя-самого-себе-единственного-юзера «читателями» как-то странно.
                                  0
                                  Скрипт отправляет новости на публичную страницу или группу в контакте, на которую могут быть подписаны любое количество читателей.
                              0
                              Надо, наверное, классы и примеры обновить исходя из того что домен уже сменили на vk.com
                                0
                                Написали уже что-нибудь подобное для wordpress?
                                  0
                                  Автор, возможно, я где-то это упустил в ваших постах, но почему вы решили не пользоваться стандартным php-классом ВКонтакте? vk.com/page-1_2369497 — внизу ссылка на архив APIServerPHPClass.zip.
                                    0
                                    Потому что тот класс отправляет запросы на api.vk.com/api.php, и соответственно там нужен весь этот расчет подписей, секретных кодов и т.д. А я использую более простое выполнение запросов, через api.vk.com/method/, подробнее в документации. Нужен только access_token.

                                  Only users with full accounts can post comments. Log in, please.