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

Вторая часть

Предисловие


Те из вас, кто пользуется социальной сетью ВКонтакте и подписан на официальную страничку Хабры в ней, заметили, что все новые топики с главной появляются на страничке в виде сообщений-ссылок:
vk

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

Реализация


Итак, для работы нам понадобится PHP с подключенным модулем curl. Для взаимодействия с сайтом ВКонтакте нам потребуется проходить авторизацию на нем, а так же получать значение уникальной переменной posthash, которая передается при публикации каждой записи на вашей стенке.

Рассмотрим простейшую функцию авторизации:
function _auth( $cookies ) {
    $e = urlencode('my@email.ru'); //mail
    $p = urlencode('password');    //password
    $c = curl_init();
    $s = 'act=login&q=1&al_frame=1&expire=&captcha_sid=&captcha_key=&from_host=vkontakte.ru&email=' . $e . '&pass=' . $p;
    curl_setopt($c, CURLOPT_URL,'http://login.vk.com/?act=login');
    curl_setopt($c, CURLOPT_RETURNTRANSFER, 1);
    curl_setopt($c, CURLOPT_FOLLOWLOCATION, 1);
    curl_setopt($c, CURLOPT_COOKIEJAR, $cookies);
    curl_setopt($c, CURLOPT_POST, 1);  
    curl_setopt($c, CURLOPT_USERAGENT, 'Mozilla/5.0 (Windows; U; Windows NT 6.1; ru; rv:1.9.2.13) Gecko/20101203 Firefox/3.6.13)');
    curl_setopt($c, CURLOPT_POSTFIELDS, $s);
    $r = curl_exec($c);
    curl_close($c);
  }

В качестве единственной переменной функции мы передаем путь до файла с cookies, где сохраняем данные авторизации. В дальнейшем, при заходе на свою страничку, мы будем проверять авторизованы ли мы и если нет, то повторно запускать данную функцию.

Теперь нам необходима функция для получения id текущего пользователя, значения его posthash переменной, а также значение переменной id из блока handlePageParams, которая определяет какой пользователь в данный момент просматривает страницу — если он равен 0, то значит мы не авторизованы и необходимо обратиться к выше приведенной функции. Итак:
function _params($cookies) {
    $c = curl_init();  
    curl_setopt($c, CURLOPT_HEADER, 1);  
    curl_setopt($c, CURLOPT_RETURNTRANSFER, 1);  
    curl_setopt($c, CURLOPT_REFERER, 'http://vkontakte.ru/settings.php');
    curl_setopt($c, CURLOPT_FOLLOWLOCATION, 1);
    curl_setopt($c, CURLOPT_USERAGENT, 'Mozilla/5.0 (Windows; U; Windows NT 6.1; ru; rv:1.9.2.13) Gecko/20101203 Firefox/3.6.13');  
    curl_setopt($c, CURLOPT_COOKIEJAR, $cookies);
    curl_setopt($c, CURLOPT_COOKIEFILE, $cookies);
    curl_setopt($c, CURLOPT_URL, 'http://vkontakte.ru/');  
    $r = curl_exec($c);
    curl_close($c);
 
    preg_match_all('/"post_hash":"(\w+)"/i', $r, $f1);
    preg_match_all('/"user_id":(\d+),/i', $r, $f2);
    preg_match_all('/handlePageParams\(\{"id":(\d+),/i', $r, $f3);
    return $f = array(
           'post_hash' => $f1[1][0],  
           'user_id'   => $f2[1][0],
           'my_id'     => $f3[1][0]);
  }

В результате мы получим массив с тремя переменными, которые необходимы нам для работы. Теперь осталось реализовать функцию создания сообщения ссылки. За публикацию сообщений на вашей стенке отвечает файл al_wall.php, который имеет множество получаемых параметров и в зависимости от каждого может создавать различные сообщения. Для нас наиболее важными будут следующие параметры:
  • act — собственно action для данного php файла, мы передаем значение post
  • hash — тот самый post_hash, который мы получили ранее
  • message — наше сообщение, не длиннее 255 символов, иначе произойдет создание заметки 
  • note_title — название заметки, если выше вы превысили лимит символов
  • status_export — параметр, определяющий «Экспорт в твиттер», если таковой аккаунт у вас связан с ВКонтакте
  • to_id — id пользователя на чью стенку мы публикуем сообщение
  • type — пока что обнаружены два возможных значения, all — публикация на вашей стенке, feed — публикации в вашем разделе Новости (блок «Что у вас нового») media_type — тип сообщения, ставим share, чтобы получить ссылку
  • url — передаваемый нами url ссылки
  • title — название вашей ссылки, ограничение в 81 символ
  • description — всплывающее описание ссылки, сюда можно передавать, например, первые строчки вашей новости, ограничение в 255 символов


На основе этих данных напишем функцию создания сообщения:
function _status($cookies, $hash, $url, $message, $title, $descr, $id) {
    $u = urlencode($url);
    $m = urlencode($message);
    $t = urlencode($title);
    $d = urlencode($descr);
    $q = 'act=post&al=1&hash=' . $hash . '&message=' . $m . '¬e_title=&official=&status_export=&to_id=' . $id . '&type=all&media_type=share&url=' . $u . '&title=' . $t . '&description=' . $d;
    $c = curl_init();  
    curl_setopt($c, CURLOPT_HEADER, 0);  
    curl_setopt($c, CURLOPT_HTTPHEADER, array('X-Requested-With: XMLHttpRequest'));
    curl_setopt($c, CURLOPT_RETURNTRANSFER, 1);  
    curl_setopt($c, CURLOPT_POST, 1);  
    curl_setopt($c, CURLOPT_REFERER, 'http://vkontakte.ru/id'.$id);
    curl_setopt($c, CURLOPT_FOLLOWLOCATION, 1);
    curl_setopt($c, CURLOPT_USERAGENT, 'Mozilla/5.0 (Windows; U; Windows NT 6.1; ru; rv:1.9.2.13) Gecko/20101203 Firefox/3.6.13');  
    curl_setopt($c, CURLOPT_POSTFIELDS, $q);
    curl_setopt($c, CURLOPT_COOKIEJAR,  $cookies);
    curl_setopt($c, CURLOPT_COOKIEFILE, $cookies);
    curl_setopt($c, CURLOPT_TIMEOUT, 15);
    curl_setopt($c, CURLOPT_CONNECTTIMEOUT, 15);
    curl_setopt($c, CURLOPT_URL, 'http://vkontakte.ru/al_wall.php');  
    $r = curl_exec($c);
    curl_close($c);
 
    return $r;
}

Функция вернет нам ответ сервера ВКонтакте — это будет либо текст ошибки, либо последние 10 сообщений со стенки, которые можно обработать по своему усмотрению. Собственно работа с сервером ВКонтакте закончена, осталось написать общую функцию, которая будет проверять авторизацию, получать переменные и создавать сообщение.
function vkPost($url='http://habrahabr.ru/', $message='message', $title='title', $descr='descr')  {    
    $o = 'aqwdhfyrfd.txt';
    $h = _params($o, 'http://vkontakte.ru/id1', true);
   
    if($h['my_id'] == 0) {
      _auth($o, $d, true);
      $h = _params($o, 'http://vkontakte.ru/id1', true);
    }
   
    if($h['my_id'] != 0) {
      $r = _status($o, $h['post_hash'], $url, $message, $title, $descr, $h['user_id']);
      $c = preg_match_all('/page_wall_count_all/smi',$r,$f);
      if( $c == 0 ) {
        return false;
      } else {
        return true;
      }
    }
}

Возможности интеграции


Теперь можно использовать ее где угодно, на любом движке. Или же создать отдельный php файл, через который публиковать любые ссылки со своим описанием у себя на стенке. В качестве примера я покажу интеграцию с движком Wordpress, где при публикации записи в блоге, вы автоматически опубликуете ссылку на нее. Итак, необходимо все вышеприведенные функции перенести в functions.php, который находится в каталоге с вашей темой, если его там нет, то создайте его. Затем в него же допишем следующую функцию и определим ее как хук:
function wp_vk_post_add($post_ID) {
        $post  = get_post($post_ID);
        $title = $post->post_title;
        $link  = get_permalink($post_ID);
        $descr = $post->post_content;
  $vkont = get_post_meta($post_ID, 'vkontakte', true);
 
  if(mb_strlen(trim($descr), 'UTF-8') >= 250) {
          $descr = strip_tags($descr);
    $descr = mb_substr($descr,0,250, 'UTF-8').'...';
  }
  $message = 'Текст песни ' . $title;  
  if(mb_strlen(trim($message), 'UTF-8') >= 250) {
    $message = mb_substr($message,0,250, 'UTF-8').'...';
  }  
  if(mb_strlen(trim($title), 'UTF-8') >= 78) {
    $title = mb_substr($title,0,78, 'UTF-8').'...';
  }
  if($vkont != '1') {
          $status = vkPost($link, $message, $title, $descr);
    if($status) {
      update_post_meta($post_ID, 'vkontakte','1');
    } else {
      update_post_meta($post_ID, 'vkontakte','0');
    }
  }
        return $post_ID;
}
add_action('publish_post', 'wp_vk_post_add');

Немного пояснений. Дело в том, что экшен publish_post в Вордпресс отрабатывается не только когда вы нажимаете кнопку Опубликовать в админке, но и при каждом сохранении записи. Получать каждый раз ссылку, когда вы редактируете свою запись после публикации, конечно же не комильфо. Поэтому при удачной публикации ссылки к нашему посту добавляется пользовательское поле vkontakte со значением 1, а перед публикацией проверяется ее наличие — если оно существует и содержит 1, то функция vkPost пропускается.

Заключение


Вот так мы получили возможность взаимодействовать с ВКонтакте и быть более интерактивными. Конечно же правильнее было бы оформить все служебные функции в отдельный класс, инициализацию curl объединить, а затем просто подключать этот класс в работе, но сделать это самому не сложно, а целью было показать каким образом это можно реализовать. Так же нужно помнить, что ВКонтакте вряд ли пропустит ваш запрос без использования прокси сервера. Позже можно добавить и вставку картинки в данную ссылку, но это уже история другого топика.

Стоит так же заметить, что al_wals.php запросит дополнительный параметр captcha, если ваш скрипт будет слишком усердно посылать статусы или вообще вернет «Ошибка доступа» — поэтому в рассылке спама этот метод вряд ли вам поможет.

А вот и пример:
Торт!
Поделиться публикацией
Реклама помогает поддерживать и развивать наши сервисы

Подробнее
Реклама
Комментарии 57
  • 0
    Fatal error: Call to undefined function _hash()
  • –14
    Слоупок!
    • –1
      Как раз думал о чём то подобном.
      • 0
        Я давно реализовал это на одном из сайтов, после нормального использования решил поделиться. Теперь в планах расширить функционал с возможностью публикации статусов-ссылок с картинками.
      • +1
        Для чего это может понадобиться?
        • 0
          Приведу конкретный пример, допустим, Вы — блогер, который время от времени публикует интересные статьи у себя на сайте и имеет профиль ВКонтакте. Если реализовать указанный выше механизм, то у подписчиков Вашей страницы ВКонтакте будут появляться оповещения в новостях о новых записях у вас в блоге — этакий вариант урезанной RSS-подписки :).
          • 0
            Если действительно интересные новости и не в промышленных масштабах, то это конечно на пользу.
            Главное чтоб в итоге френдлента и новости не превращались с сплошную полосу спама и репостинга.
            • 0
              В этом случае всегда можно скрыть новости определенного человека, если спамит ваш друг или же отписаться от страницы вообще, если спамит она.
          • 0
            Дублировать новости еще и во ВКонтакте.
            • –3
              Ничего с ног сшибательного и архиполезного. Например тут(ни коим образом не реклама) человек одновременно транслирует хабр, башорг, ixbt и другие IT ресурсы.
              • 0
                И каким образом это связано с ВКонтакте? ;)
                • 0
                  Ни коим, я просто привел пример того, для чего это может понадобиться.
                  • 0
                    Вы кардинально путаете принцип работы. Тут мы отправляем данные на ВК, а ваш пример демонстрирует противоположное, он забирает с сайтов (парсит).

                    Оффтоп: каким боком башорг IT ресурс? :)
                    • 0
                      Да, тут я не много запутался, каюсь.
                      Насчет баша — хорошо :) он был когда давным давно IT ресурсом.
            • –2
              Хабр — он.
              • +1
                Не понимаю, почему VK не сделали для этого API до сих пор.
                • 0
                  Если судить по официальной страничке Хабра — сделали, просто общего доступа к нему нет.
                • +1
                  А почему хук в функциях темы, а не плагином?
                  Вот тема обновится — и нету хука. А если делать чтоб был — надо Child делать. А чтобы в другой теме работало — туда тоже надо дописать. Плагином бы вышло лучше.
                  • 0
                    Когда-нибудь кто-нибудь напишет, не переживайте.
                    • 0
                      Не переживаю, меня не особо волнует кросспост во вконтакте. Просто меня удивило, что если идет интеграция с WordPress, то почему она идет именно так…
                      • 0
                        Ничего противозаконного тут нет, хочешь — пиши плагин, хочешь добавляй в свою тему, никто ж не указывает. Но я вот сейчас думаю как раз о том, чтобы закончить один плагин для WP, следующим пойдёт наверное, реализация этого плагина.
                        • 0
                          При чем здесь противозаконность?:)
                          Обычно на Хабр постят хорошие, правильные решения. А это — костыль фактически. Я ничего не скажу насчет внутреннего функционала взаимодействия с API (не работал с вконтакте), но меня удивляет, почему автор сделал это, но не оформил это нормально. Или хабр уже не тот?
                          • 0
                            Нда. )
                            Лучше бы авто вообще не касался вордпресса тогда.
                            Суть его статьи — не в том как сделать надстройку к WP — а в том, чтобы показать постинг на сайт вконтакте ж.
                            • 0
                              Лучше бы не касался, да :)
                              Я не ищу к чему придраться, а просто спросил почему. Дальше можно было вообще не спорить.
                              P.S. Надеюсь, ваш плагин с этим функционалом окажется в официальном репозитории WP.
                    • 0
                      Согласен, но пока что это наброски общей функциональности и говорить о плагине рано, да и Wordpress-реализация в статье — лишь небольшой пример возможности использования
                    • +2
                      Вы уверены что для этого нельзя использовать API? Вот например vkontakte.ru/developers.php?o=-1&p=wall.post
                      А так изменит вконтакт дизайн или какие-то внутренности и все отвалится…
                      • 0
                        Можно, однако, как я понял, для этого придется реализовывать приложение ВКонтакте или нет?
                        • 0
                          Эти методы для приложений. Сам был удивлен, что нет инструментов для импорта RSS во вконтакте, или же API для импорта новостей в группы и т.д.
                          • 0
                            Ну я этим методом пользовался когда писал плагин к Gwibber для поддержки вконтакта.

                            Единственное серьезное препятствие которое я заметил — сессионный токен привязан к IP адресу, поэтому получить сессию на домашнем компьютере и потом пользоваться ей на сервере не получится и это печально. Например в API Facebook можно получить так называемый «Оффлайн токен» и пользоваться им откуда угодно. Вконтакте такой штуки не нашел и это сильно ограничивает возможности применения API.
                            • 0
                              Если описанное в статье можно реализовать проще, то буду очень рад прочитать статью от Вас как это сделать :).
                        • НЛО прилетело и опубликовало эту надпись здесь
                          • –2
                            А знали ли вы, что подобные действия запрещены правилами сайта.
                            • 0
                              Как и запрещено правилами 99% контента ВКонтакте? Да, знал :) Вообще там есть оговорка, что можно получить разрешение администрации, так что ничего невозможного я не вижу ;)
                            • 0
                              Хотел сделать подобное на своем проекте. Что бы «действие» пользователя появлялось у него на страничке. Остановила капча, с большим количеством людей им постоянно придется ее водить, а мне надо было автоматизировать. (попутно вопрос, ограничение на ресурс или на пользователя ВК?)

                              Было бы не плохо, чтоб когда будет полноценная апи, была возможность добавить сайт в разрешенные.
                              • 0
                                Тут без приложения и ВКонтакте API Вам не обойтись, там можно реализовать все функции без ограничения, если пользователя разрешит доступ к своей стенке приложению Вашего сайта
                                • 0
                                  Спасибо. Своего рода костыль. Подожду немного, если нечего лучше не появится, так и сделаю. Надо написать в ВК, что бы они присмотрелись к твиттеру. Сам ВК это большая содранная идея, так почему бы не содрать и там :)
                                  • 0
                                    Доверять сайту со стороны ВКонтакте тоже просто так не будет, а с помощью приложения он сможет контролировать действия сайта и доступ к данным пользователей или их стенке.
                                    • 0
                                      Насколько я знаю, любой подключенный к ВК сайт может пользоваться теми же методами, что и flash и iframe приложения.

                                      Через штуку, которая у них называет OpenAPI. Причем как с клиента, так и с сервера.
                                      И премодерации нет никакой.

                                      Единственное ограничение — он спрашивает у пользователя доступ к данным, стенке и т.д.
                                    • 0
                                      Если действие пользователя появляется на его же странице, то использование API вконтакта — это не костыль, а наоборот верное решение.

                                      Видал я одну онлайн-игрушку, про мафию вроде, авторизовавшись в которой через Тви, сильно пожалел: эта дрянь заспамила мне всю ленту, 30+ постов. Задолбался потом удалять это гавно из ленты, и извинятся перед фоловерами.
                                      • 0
                                        Кажется многие через это прошли… )
                                • 0
                                  Как раз недавно завел страничку компании. Группа как-то не совсем то, что нужно для присутствия в соц.сети и от нее наверно откажусь в пользу странички. Теперь с помощью вашего топика, думаю, окончательно автоматизирую постинг новостей (main_site → rss & twitter & vkontakte).
                                  • 0
                                    опробовала, занятно! теперь в мою группу Вконтакте вступает намного больше людей, чем обычно. Спасибо!
                                    • НЛО прилетело и опубликовало эту надпись здесь
                                      • 0
                                        старенькая статья, уже ничего не пашет :(((
                                        • 0
                                          не знаю, с момента написания этой статьи не менял в своих скриптах ничего — пока на всех сайтах работает как часы :)
                                          • 0
                                            Извините, наверное что-то применил не так, но вот переписав ф-ю авторизации, все вышло, на всякий случай приведу свой пример:
                                            function _auth( $cookies ) {
                                            $data=array(
                                            'act'=>'',
                                            'login'=>'',
                                            'q'=>'1',
                                            'al_frame'=>'1',
                                            'captcha_sid'=>'',
                                            'captcha_key'=>'',
                                            'from_host'=>'vkontakte.ru',
                                            'expire'=>'',
                                            'email'=>'---YOU E-mail---',
                                            'pass'=>'---YOU PASS---',
                                            'success_url'=>'',
                                            'fail_url'=>'',
                                            'try_to_login'=>'',
                                            'to'=>'',
                                            'vk'=>'',
                                            'al_test'=>'3'
                                            );
                                            $c = curl_init();
                                            curl_setopt($c, CURLOPT_URL, 'http://vkontakte.ru/login.php'); // login.vk.com/?act=login
                                            curl_setopt($c, CURLOPT_RETURNTRANSFER, 1);
                                            curl_setopt($c, CURLOPT_FOLLOWLOCATION, 1);
                                            curl_setopt($c, CURLOPT_COOKIEJAR, $cookies);
                                            curl_setopt($c, CURLOPT_POST, 1);
                                            curl_setopt($c, CURLOPT_USERAGENT, 'Mozilla/5.0 (Windows; U; Windows NT 6.1; ru; rv:1.9.2.13) Gecko/20101203 Firefox/3.6.13)');
                                            curl_setopt($c, CURLOPT_POSTFIELDS, $data);
                                            $r = curl_exec($c);
                                            curl_close($c);
                                            }
                                            _auth('/home/lebnik/data/www/site.ru/cookies/cookies.txt');

                                            Далее проверял не все функции, но переписал на свой лад _status() и все работает, поэтому спасибо за статью, сразу не въехал.
                                        • +1
                                          Подтверждаю все работает
                                          • 0
                                            А можно аналогичное реализовать для жумлы? Я не суперический программер совсем, но если меня в нужные места потыкать носом, то осилю. Уж больно хочется на сохранение статей повесить публикацию ссылок на них в группу. В идеале было бы здорово создавать отдельное обсуждение с текстом материала, но пусть хотя бы ссылка будет на стене.
                                            • 0
                                              Подскажите, пожалуйста, в чем может быть проблема: все публикуется, если указать стену пользователя, а если указать ID оф.страницы (ID с минусом), то выдает «Ошибка доступа»?
                                              • 0
                                                а post_hash какой используется?
                                                • 0
                                                  да-да, в нем дело. Спасибо, я уже разобрался
                                              • 0
                                                Скрипт постит ко мне на страницу, а как его заставить постит в группу, в которой я являюсь админом?
                                                Или я невнимателен?
                                                • 0
                                                  Чтобы постить в группу нужно:
                                                  1. Быть админом
                                                  2. Записать ID группы
                                                  3. В параметрах вместо ID страницы друга указать ID группы, но со знаком "-", например, -1234
                                                • 0
                                                  У меня вроде логин проходит, но эта маразматическая безопасность через мобильный телефон достает уже. Требует ввести последние 4 цифры после входа через курл, и как ему их подсунуть, я не очень понимаю пока.
                                                  • 0
                                                    А что передается в соответствующем POST запросе, когда вы ввели последние четыре цифры? Какой то хеш или цифры в прямом виде?
                                                    • 0
                                                      Да передавалось все нормально. Я нашел уже решение, где подсовывается этот код (в третьей части этой же серии статей). Но в итоге, продолбавшись целый вечер с курлом, все сделал через API ;-)

                                                  Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.