Category Archives: twitter

Седлаем Twitter API 1.1

История темы

Как-то для одного из моих прожектов мне понадобилось автоматически размещение твиттеров из моей базы данных.

Помню года 3-4 назад это можно было делать через простые GET-запросы, но сегодня ситуация кардинально изменилась – видимо, спамеры Twitter достали всё-таки.

И в августе 2010 Твиттер представило новый API 1.0 на замену старому, где для изменения данных в аккаунте требовалась уже более серьёзная аутентификация, но для чтения опять же было достаточно простых запросов с именем-паролем.

И вот Twitter созрел – он представил версию своего API 1.1, основные моменты которого таковы (https://dev.twitter.com/docs/api/1.1/overview)

  • JSON support only – да, теперь Twitter API  поддерживает только формат JSON, они окончательно отказались от таких форматов, как, например XML и RSS.
  • Authentication required on all endpoints – теперь для работы с API для любых запросов (и чтение и изменение) требуется полная аутентификация через Twitter-приложения

Начинаем!

Итак, краткий курс в историю нас немного позабавил, но что нам теперь делать? Гуглить! Немного погуглив, я в одном из форумов наткнулся на фразу (в ответ на вопрос типа “Как мне публиковать твиттеры автоматически?”) одного человека – он просто написал – посмотри эту книгу, там всё написано. И дал ссылку – http://140dev.com/download/get_file.php?file=single-user-oauth&type=pdf

Я скачал эту PDF книгу (это книга Адама Грина (by Adam Green) называется Single-User Twitter OAuth Programming, что в моём вольном переводе может означать “Однопользовательское программирование Twitter через OAuth“) – она бесплатна сейчас, Адам выложил её (и ещё пару своих e-книг) в свободный доступ на своём сайте здесь – http://140dev.com/member.

Поначалу я ничего не понял, но, вчитываясь и осмысливая куски кода в ней, я начал просвещаться! И нашёл решение своей задачи -публикация хотя бы одного поста в день из своей БД в мой твиттер. Вот как это делать:

Создаём приложение Twitter

Это сейчас обязательно. Это все делают, и facebook, и vk. Придумали свои приложения.

Заходим на https://dev.twitter.com

В правом верхнем углу нажимаем ссылку Sign in – вводим свои логин/пароль, затем в правом верхнем углу видим свой аватарчик – наводим на него курсор мыши, из pop-up меню выбираем My applications (Мои приложения), в итоге оказываемся здесь – https://dev.twitter.com/apps

Нажимаем ссылку (опять же справа) – Create application (Создать приложение), заполняем поля по своему выбору – Name (Имя), Description (описание), Website (сайт)  и Callback URL (Адам Грин советует обязательно заполнить это последнее поле) – можно заполнить его так же как и поле Website.

Скроллим вниз, нажимаем галку Yes, I agree под кабальным договором (шутка), заполняем captcha (блин, как слово captcha перевести на русский без извращений?), сабмит формы и наше приложение создано.

Далее его надо ещё донастроить немного, прежде чем мы будем пользовать его в наших корыстных целях.

Итак, на странице настройки приложения (нас сюда перекидывает сразу после создания, сюда же можно вернуться в любой момент из основной страницы https://dev.twitter.com/apps) – выбираем вкладку Setting (Настройки), скроллим вниз и меняем в разделе Application type радио-кнопку на Read and Write (Чтение/запись) – если мы планируем через это приложение менять что-то на нашем аккаунте или публиковать посты – а мы планируем это делать!

Итак, внизу сабмитим форму (Update this Twitter application’s settings), потом ждём пару минут и перезагружаем страничку – здесь Твиттер что-то тормозит и не сразу меняет статус нашего приложения на Чтение/Запись. Но теперь всё в порядке, убеждаемся, что после перезагрузки странички галка стоит на Read and Write, и переходим на вкладку Details (Детали).

Скроллим вниз и щёлкаем на Create my access token кнопку. И опять ждём пару минут и перегружаем страницу, чтобы увидеть свои новые данные для доступа (access token).

Они состоят из Access token и Access Token secret. что они означают, я особо не вникал, да нам это и не нужно. Всё, что нам теперь нужно, это запомнить свои (и публичные) данные доступа – можно сразу же в своём скрипте, где-нибудь в константах.

Я давний поклонник PHP, поэтому буду приводить код далее именно для этого языка, но для любого другого серверного языка (ASP, JSP, Ruby и т.д.) всё делаем аналогично, только конечно используем родной синтаксис этих языков.

Итак, в итоге для дальнейшего пользования этим приложением нам надо сформировать четыре константы – consumer_key, consumer_secret – два пользовательских ключа, они сразу определяются для приложения, и видимо, больше не меняются – это одноименные поля в разделе OAuth settings, и пара констант, назовём их как в книге Адама Грина – user_token и user_secret – это поля созданные нами Access token и Access token secret.

Копируем их в такой примерно скриптик (PHP):

// OAuth tokens для моего приложения Twitter
$consumer_key = 'c67WBeewX54ZJnHK';
$consumer_secret = 'bw1pZZa2ouYRW76Zg5TV0dxI07t0gY6EU';
$user_token = '133245413-whyvteXFhyAr764DFV0DTgmRsIZuF';
$user_secret = 'hRsL2MYAxOmsXBm0mUmIzW8eMpYOqgMut';

(я скопировал эти ключи из книги Адама Грина, он пишет, что они более не валидные, но вы можете проверить, так ли это).

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

Всё, на этом заканчиваем с приложением и переходим к самому вкусному – постим твиты автоматом, а также читаем любые данные и твиты любого twitter-аккаунта (общедоступные, конечно, то есть те, что мы и так можем прочитать, используя свой любимый браузер Firefox/Chrome/Safari и т.п.)

Укрощаем Twitter API 1.1

Итак, для того чтобы выполнить нужное действие с Twiiter’ом, надо создать соединение, послать запрос и получить ответ. Twitter работает по собственному протоколу, вникать во все тонкости которого мы не будем (для особо пытливых ссылка эта – https://dev.twitter.com/docs/auth/authorizing-request) , а воспользуемся рекомендованной Адамом библиотекой – tmhOAuth library Мэта Харриса (by  Matt Harris) (https://github.com/themattharris/tmhOAuth)

Для справки – другие библиотеки можно выбрать и попробовать здесь – https://dev.twitter.com/docs/twitter-libraries

Итак, что мы делаем? Скачиваем библотеку Мэта – файл tmhOAuth.php и в придачу к нему скачаем файл cacert.pem – это файл с сертификаторами, необходим для работы этой библиотеки. Учтите, что этот файл по умолчанию (если вы не будете залазить в код этой либы и менять там что-то) должен находиться в одной папке с самомй библиотекой (то есть файлом tmhOAuth.php)

Размещаем эти два файла на нашем сервере и пишем скрипт, которые авто-постит наши посты в Твиттер в нужное нам время:

 
// подключаем библиотеку Мэта Харриса 
// - путь может быть другим, где вы её положили
require_once("inc/lib/tmhOAuth.php");
 
// я всегда веду лог своих крон-задач, чтобы видеть
// что они вытворяют без меня там
$ff = fopen("log/tweet_log.html",'ab');
 
// OAuth-данные для нашего Twitter-приложения
// как добыть эти секретные данные - 
// смотрите выше в этом посте
$consumer_key = 'ключ приложения';
$consumer_secret = 'пароль к нему';
$user_token = 'пользовательский ключ';
$user_secret = 'пароль и к нему';
 
// Создаём OAuth соединение к Twitter API
$connection = new tmhOAuth(array(
                         'consumer_key'=> $consumer_key,
                         'consumer_secret' => $consumer_secret,
                         'user_token'=> $user_token,
                         'user_secret'=> $user_secret)
);
 
// Выберем случайную книгу из последних 10-ти
// (используем PDO, подключение к БД уже сделано ранее)
$r = $db->query("SELECT id,title,author FROM books ORDER BY id DESC LIMIT 10");
$cyc = rand(1,10);
for($i = 1; $i <= $cyc; $i++)
  list($id,$title,$author) = $r->fetch(PDO::FETCH_NUM);
 
// формируем твит по своему вкусу -
// я решил давать описание, ссылку на свой сайт и имя автора
$tweet = "{$title}- http://myproject-books.ru/download/{$id} ({$author})";
 
// иногда твиты получаются неуклюжими, но меня это не волнует
// если вам нужна более строгая проверка - делайте её сами
if(strlen($tweet)>140)
  $tweet = substr($tweet,0,140);
// логгируем его
fwrite($ff,'['.date('Y-m-d H:i:s').'] TWEET: '.$tweet);
 
// Мой сайт к моему стыду ещё в cp1251 кодировке,
// Twitter же конечно как всякий уважающий себя сайт
// работает в utf-8 кодировке, поэтому перекодируем
$tweet = iconv('windows-1251','utf-8',$tweet);
 
// и шлём его!
$code = $connection->request('POST',$connection->url('1.1/statuses/update'),
                                     array('status' => $tweet));
 
// Если полученный код равен 200 - всё нормально
if ($code == 200)
  fwrite($ff," *--* OK!\r\n");
else
  fwrite($ff," *--* ERR\r\n");
 
fclose($ff);

В этом скрипте мы выбираем последние десять записей из нашей БД, и публикуем случайную из них. Я закронил этот скрипт на один раз в сутки, и теперь каждый день в моём твиттере за чашкой утреннего кофе я читаю свежий твит, опубликованный этим моим гениальным скриптом. А что вы хотели – всё гениальное – просто, и это не пустые слова.

Здесь самая важная и нужная часть – сформировать верный запрос.
Twitter API поддерживает десятки разных запросов, нам для реальной работы необходимо лишь два-три.

Запрос состоит из следующей части –

  1. request('POST',
  2.          $connection->url('1.1/statuses/update'),                           
  3.          array('status' => $tweet));

Первая строка в запросе (POST) – тип запроса GET/POST, для чтения будем использовать GET, для записи – POST. Так как мы публикуем новый твит, мы здесь используем именно POST (использование GET смотрите ниже).

Вторая строка в скобках (‘1.1/statuses/update’) – указание ресурса для действия (все доступные для данного API 1.1 ресурсы смотрите здесь – https://dev.twitter.com/docs/api/1.1). В него входит следующее:

1.1 – видимо, версия используемого API
statuses/update – название ресурса для действия, в данном случае мы просим твиттер опубликовать новый твит.

Третья строка – массив необходимых параметров (да, каждый параметр у нас должен быть элементом ассоциативного массива). В данном случае мы передаём один параметр с именем status и со значением строки нашего твита. Дополнительные параметры могут указываться здесь же, через запятую (так формируются несколько элементов массива в PHP).

Пример с несколькими параметрами смотрите ниже, где мы будем читать твиты! И выводить их на нашей страничке.

Читаем свои твиты и выводим их

А что далеко ходить – я сделал это для этого блога – http://atzar.ru/my_tweets/

Вот код чтения и вывода твиттеров из одного из моих твиитер-аккаунтов:

// подключаем библиотеку Мэта Харриса 
// ваш путь может быть другим,
// я предпочитаю использовать папки
// типа lib или inc/lib в корне сайтов
require_once("lib/tmhOAuth.php");
 
// OAuth-данные для нашего Twitter-приложения
// как добыть эти секретные данные - 
// смотрите выше в этом посте
$consumer_key = 'ключ приложения';
$consumer_secret = 'пароль к нему';
$user_token = 'пользовательский ключ';
$user_secret = 'пароль и к нему';
 
// Создаём OAuth соединение к Twitter API
$connection = new tmhOAuth(array(
                         'consumer_key'=> $consumer_key,
                         'consumer_secret' => $consumer_secret,
                         'user_token'=> $user_token,
                         'user_secret'=> $user_secret)
);
$code = $connection->request('GET',$connection->url('1.1/statuses/user_timeline'),
			array('screen_name' => 'PHPJSDoca', 'count' => 200)); 
 
// декодируем полученные данные из JSON-объекта в PHP-массив
$tweet_data = json_decode($connection->response['response'],true); 
 
// Ответный код 200 ? Да - всё в порядке
if ($code == 200) {
   // соберём твиты и сформируем из них
   // HTML-код для вывода на нашей странице
   $tweet_stream = '';
   foreach($tweet_data as $tweet) { 
          // SYS: JS:  etc. get in bold
     $t = preg_replace('/^(.*?):/',"<b>$1</b>: ",$tweet['text']);
     $tweet_stream .= $t . '<br/><br/>'; 
   } 
 
   // Выведем их в браузер
   echo $tweet_stream; 
}
else {
	// Тут можно обработать ошибки
        // я просто вывожу её как есть
	echo "<strong>Code:</strong> $code<br>";
	// Выводим запрос как массив для разбора
	echo "<strong>Response:</strong><br><br>";
		print_r($tweet_data);
	echo "<br><br>";
}

Здесь мы используем следующий запрос:

  1. $code = $connection->request('GET',
  2.                 $connection->url('1.1/statuses/user_timeline'),
  3. 		array('screen_name' => 'PHPJSDoca', 'count' => 200));

Опять же, первая строка – метод запроса, GET в основном используется для чтения данных.

Вторая строка – ресурс запроса, мы используем ресурс statuses/user_timeline, возвращающий последние опубликованные твиты нужного пользователя (эти твиты должны быть нам доступны). Какого именно пользователя мы хотим – указываем далее, в параметрах.

Третья строка – параметры запроса в ассоциативном массиве PHP.
scrren_name – имя твиттер-пользователя, чьи твиты мы хотим получить (PHPJSDoca для нашего случая).
count – максимальное число твитов. Я указал 200, документация утверждает, что мы можем получить вплоть до 3200 последних твитов пользователя.

Описание остальных параметров вы можете найти в документации к этому ресурсу – https://dev.twitter.com/docs/api/1.1/get/statuses/user_timeline

Итак, после отправки запроса мы должны разобрать полученный от Twitter-сервера ответ. Как это сделать можно узнать, либо изучив его (предварительно залоггировав в каком-нибудь текстовом файлике), либо прочитать о нём в документации к нужному ресурсу, в данном случае здесь же – https://dev.twitter.com/docs/api/1.1/get/statuses/user_timeline

В каждом ответе Twitter API послыает довольно много информации, даже с избытком имхо, нам же зачастую нужно всего одно-два поля из неё.

Заключение

Мы выполнили поставленную задачу – укротили Twitter API 1.1 буквально менее чем за час, и теперь можем использовать его на благо наших ресурсов.

Удачи, крепкого чая в бокале, хорошего настроения и любви.