
Это вторая часть нашего учебника по API Списка Твиттера в нашей расширенной серии Twitter API . В этом уроке мы рассмотрим создание функций List с помощью API. Примеры кода представлены в репозитории Github. Инструкции по установке описаны здесь более подробно (обязательно используйте репозиторий, представленный в этом руководстве, а не исходный репозиторий Birdcage, указанный на этой странице).
Обзор API Списка Твиттера
Опять же, существует около 19 API для списков Twitter , разделенных на три основные области:
Давайте начнем с интеграции некоторых основных функций разработки List API.
Создание списка
Когда вы загрузите Birdcage, вы увидите страницу управления списками . Выберите опцию « Создать список» в правом боковом меню.

Откроется форма Создать список . Я собираюсь создать список для отслеживания журналистов Сиэтла в Twitter:

Вот код создания в TwitterlistController.php . Он обрабатывает код для отображения формы и после публикации формы код для обработки:
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
|
public function actionCreate()
{
$model=new TwitterList;
$this->performAjaxValidation($model);
if(!isset($_POST[‘TwitterList’])) {
// initial load
// load the current selected account as a default
$model->account_id = Yii::app()->session[‘account_id’];
// display form
$this->render(‘create’,array(
‘model’=>$model,
));
} else {
// POSTed — process form
$model->attributes=$_POST[‘TwitterList’];
// load the account selected
$account = Account::model()->findByPK($model->account_id);
// connect to twitter
$twitter = Yii::app()->twitter->getTwitterTokened($account[‘oauth_token’], $account[‘oauth_token_secret’]);
// create remotely at Twitter
$new_list= $twitter->post(«lists/create»,array(‘name’=>$model->name,’description’=>$model->description,’mode’=>$model->getModeString($model->mode)));
if (TwitterList::model()->isError($new_list)) {
// to do — set flash error
var_dump($new_list);
yexit();
} else {
$model->owner_id =$account->twitter_id;
$model->list_id =$new_list->id_str;
$model->slug=$new_list->slug;
$model->full_name=$new_list->full_name;
$model->created_at = date( ‘Ymd H:i:s’, strtotime($new_list->created_at) );
$model->modified_at =new CDbExpression(‘NOW()’);
if($model->save())
$this->redirect(array(‘admin’));
}
}
}
|
Вы можете прочитать документацию по Twitter Lists / Create API здесь .
После отправки формы вы увидите что-то вроде этого:

Импорт членов в список
Одно из самых неприятных ограничений пользовательского интерфейса в Твиттере — насколько сложно добавлять участников. Вы должны посетить каждого участника и добавить их индивидуально в свои списки — процесс очень запутанный и медленный.
Мы собираемся реализовать функцию подписки через разделенный запятыми список учетных записей Twitter.
В представлении списка, если вы нажмете на значок « Управление списком» справа от « Сиэтлских журналистов» , вы увидите страницу « Просмотр списка» :

Нажмите на Импортировать участников в правом меню. Затем введите список учетных записей Twitter, которые вы хотите добавить в этот список:

Давайте рассмотрим код, который загружает участников в Twitter. Код для отображения формы выше начинается в ListMemberController.php :
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
/**
* Import members to a list
*/
public function actionImport($id)
{
$model = new Import();
$model->list_id = $id;
// Uncomment the following line if AJAX validation is needed
$this->performAjaxValidation($model);
if(isset($_POST[‘Import’]))
{
if($model->save()) {
$result = ListMember::model()->import($id,$_POST[‘Import’][‘member_list’]);
Yii::app()->user->setFlash(‘import_success’,’Thank you! Your members have been added.’);
$this->redirect(array(‘/twitterlist/view’,’id’=>$id));
} // end if save
// end if post
} else {
$this->render(‘import’,array(
‘model’=>$model,’list_id’=>$id,
));
}
}
|
В модели ListMember.php код импорта выглядит следующим образом. Мы используем preg_split для преобразования списка учетных записей в массив. Затем для каждой учетной записи мы извлекаем информацию об учетной записи в Users / Show и публикуем идентификатор Twitter в Списке участников .
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
|
public function import($id,$import_list) {
// retrieve account
$tl = TwitterList::model()->findByAttributes(array(‘id’=>$id));
$list_id = $tl[‘list_id’];
$account = Account::model()->findByPk($tl->account_id);
// retrieve members and add to list
$twitter = Yii::app()->twitter->getTwitterTokened($account[‘oauth_token’], $account[‘oauth_token_secret’]);
// convert post rows to array
$add_list = preg_split («(\r|\n|,)», $import_list, -1, PREG_SPLIT_NO_EMPTY);
$max_count = 0;
foreach ($add_list as $item) {
$item = trim($item);
$user_info= $twitter->get(«users/show»,array(‘screen_name’=>$item));
if (ErrorLog::model()->isError(‘getUserInfo’, $account[‘id’], $user_info)) {
continue;
}
if (ErrorLog::model()->isRateLimited($user_info)) {
continue;
}
// add remotely to list
$people= $twitter->post(«lists/members/create»,array(‘list_id’=>$list_id,’screen_name’=>$item));
// add locally to db
$this->remote_add($list_id,$user_info->id_str,$item);
$max_count+=1;
if ($max_count>=99) break;
}
}
public function remote_add($list_id,$member_id,$screen_name = ‘tbd’) {
TwitterUser::model()->setPlaceholder($member_id,$screen_name);
$lm = ListMember::model()->findByAttributes(array(‘list_id’=>$list_id,’member_id’=>$member_id));
if (empty($lm)) {
$lm = new ListMember;
$lm->list_id=$list_id;
$lm->member_id=$member_id;
$lm->save();
}
}
|
После отправки участников вы увидите что-то вроде этого:

tbd представляет пользователя, которого еще нет в нашей базе данных; информация профиля будет извлечена (гидратирована) в фоновом режиме позже.
В Твиттере вы увидите что-то вроде этого:

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

Действие синхронизации закодировано в TwitterlistController.php :
|
1
2
3
4
5
|
public function actionSync()
{
TwitterList::model()->sync();
$this->redirect(array(‘admin’));
}
|
TwitterList.php синхронизации модели TwitterList.php является относительно сложной, как показано ниже. Во-первых, модель синхронизации проходит по всем настроенным вами учетным записям и вызывает syncOne запись syncOne для получения списков.
SyncOne вызывает выборку списков / владельцев в API, чтобы найти все списки, принадлежащие каждой учетной записи.
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
|
public function sync() {
$users = User::model()->findAll();
foreach ($users as $user) {
$user_id = $user[‘id’];
$accounts = Account::model()->findAllByAttributes(array(‘user_id’=>$user_id));
// loop through Twitter accounts (may be multiple)
foreach ($accounts as $account) {
$this->syncOne($account[‘id’]);
} // end account loop
} // end user loop
}
public function syncOne($account_id) {
$account=Account::model()->findByPk($account_id);
$twitter = Yii::app()->twitter->getTwitterTokened($account[‘oauth_token’], $account[‘oauth_token_secret’]);
// fetch lists owned by this account
$twitter_lists= $twitter->get(«lists/ownerships»,array(‘count’=>100,’cursor’=>-1));
//print_r($twitter_lists);
if (count($twitter_lists->lists)==0) return;
foreach ($twitter_lists->lists as $tl) {
//echo $tl->id_str.’
$this->remote_add($account_id,$tl);
// spawn action to get list members
$this->addMembershipAction($account_id,$tl->id_str);
} // end loop of lists
}
|
Однако вместо того, чтобы пытаться извлекать участников для списка в режиме реального времени, что, вероятно, приведет к истечению времени ожидания, он создает фоновое действие для извлечения членов для данного списка.
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
|
public function addMembershipAction($account_id,$item_id) {
// adds a background task action to retrieve memberships for a list id
$check_dup = Action::model()->findByAttributes(array(‘account_id’=>$account_id,’action’=>Action::ACTION_MEMBERSHIPS,’status’=>Action::STATUS_ACTIVE,’item_id’=>$item_id));
if (empty($check_dup)) {
$a = new Action();
$a->account_id = $account_id;
$a->action = Action::ACTION_MEMBERSHIPS;
$a->item_id = $item_id;
$a->last_tweet_id = 0;
$a->status = Action::STATUS_ACTIVE;
$a->created_at =new CDbExpression(‘NOW()’);
$a->modified_at =new CDbExpression(‘NOW()’);
$a->save();
}
}
|
Фоновая задача cron вызывает модель Action.php которая вызывает getListMembership для одного списка за раз.
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
|
public function getListMembership($action,$limit = 50) {
// collect next $limit members of list
$account = Account::model()->findByPk($action->account_id);
// last_tweet_id is the cursor
$cursor = $action->last_tweet_id;
if ($cursor ==0 ) $cursor =-1;
$result = TwitterList::model()->getMemberships($account, $action->item_id, $cursor , $limit);
$a = Action::model()->findByPk($action->id);
if ($result->rateLimit) {
return false;
} else if ($result->complete) {
$a->status=self::STATUS_COMPLETE;
$a->save();
} else {
// set lowest cursor
$a->last_tweet_id = $result->cursor;
$a->save();
}
}
|
Когда задача выполняется, она вызывает метод TwitterList.php модели getMemberships . Этот метод использует курсоры для пролистывания записей участников без истечения времени ожидания или ограничения скорости. Последний курсор хранится в таблице действий, так что следующий фоновый вызов может продолжить добавление элементов, где он был остановлен ранее.
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
|
public function getMemberships($account,$list_id, $cursor =-1,$limit = 200) {
echo ‘entering getMemberships: account_id:’.$account[‘id’].’
$result = new StdClass;
$result->cursor = -1;
$result->count =0;
$result->error =false;
$result->complete = false;
$result->rateLimit = false;
$count_people = 0;
// retrieve members and add to list
$twitter = Yii::app()->twitter->getTwitterTokened($account[‘oauth_token’], $account[‘oauth_token_secret’]);
echo ‘here’.$cursor;lb();
while ($cursor <>0 ) {
echo ‘inside’;lb();
$people= $twitter->get(«lists/members»,array(‘list_id’=>$list_id,’cursor’=>$cursor,’skip_status’=>true,’include_entities’=>false));
if (ErrorLog::model()->isError(‘getMemberships’, $account[‘id’], $people)) {
$result->error =false;
return $result;
}
if (ErrorLog::model()->isRateLimited($people)) {
$result->rateLimit = true;
return $result;
}
if (isset($people->next_cursor))
$cursor = $people->next_cursor;
else
$cursor = 0;
$result->cursor = $cursor;
$count_people+=count($people->users);
echo ‘Count people: ‘.count($people->users);lb();
foreach ($people->users as $u) {
//var_dump($u);lb();
echo ‘Member:’.$u->screen_name;lb();
if (isset($u->screen_name))
$screen_name = $u->screen_name;
else
$screen_name = ‘tbd’;
ListMember::model()->remote_add($list_id,$u->id_str,$screen_name);
}
if (count($people->users)==0 or $cursor==0) {
$result->complete = true;
return $result;
}
} // end while loop
echo ‘exiting getMemberships’;lb();
return $result;
}
|
Вы должны увидеть что-то вроде этого, когда операция завершится:

После завершения фоновых задач вы увидите участников для каждого списка, например:

Что дальше?
Надеюсь, вам понравилась эта серия API Twitter List. Я хотел бы услышать ваши предложения по поводу любимых сценариев API и запросов функций; пожалуйста, оставьте их в комментариях.
Если у вас есть какие-либо вопросы или предложения, пожалуйста, оставьте их в комментариях. Если вы хотите следить за моими будущими уроками Tuts + и другими сериями, пожалуйста, посетите мою страницу инструктора или следуйте @reifman .