Статьи

Создание с помощью API Twitter: управление списками

Конечный продукт
Что вы будете создавать

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

Опять же, существует около 19 API для списков Twitter , разделенных на три основные области:

Давайте начнем с интеграции некоторых основных функций разработки List API.

Когда вы загрузите Birdcage, вы увидите страницу управления списками . Выберите опцию « Создать список» в правом боковом меню.

API Списка Твиттера Управление списками пусто

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

Twitter List API Создать список

Вот код создания в 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 здесь .

После отправки формы вы увидите что-то вроде этого:

API списков Twitter Управление списками Twittert после создания

Одно из самых неприятных ограничений пользовательского интерфейса в Твиттере — насколько сложно добавлять участников. Вы должны посетить каждого участника и добавить их индивидуально в свои списки — процесс очень запутанный и медленный.

Мы собираемся реализовать функцию подписки через разделенный запятыми список учетных записей Twitter.

В представлении списка, если вы нажмете на значок « Управление списком» справа от « Сиэтлских журналистов» , вы увидите страницу « Просмотр списка» :

Twitter List API Просмотреть список Участники пусто

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

Twitter List API Импорт учетных записей 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();
       }
   }

После отправки участников вы увидите что-то вроде этого:

Twitter List API Просмотреть список пользователей

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

В Твиттере вы увидите что-то вроде этого:

Twitter List API List Список участников на Twitter

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

API списков Twitter Управление списками

Действие синхронизации закодировано в 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 Управление списками

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

Twitter List API Просмотреть список пользователей

Надеюсь, вам понравилась эта серия API Twitter List. Я хотел бы услышать ваши предложения по поводу любимых сценариев API и запросов функций; пожалуйста, оставьте их в комментариях.

Если у вас есть какие-либо вопросы или предложения, пожалуйста, оставьте их в комментариях. Если вы хотите следить за моими будущими уроками Tuts + и другими сериями, пожалуйста, посетите мою страницу инструктора или следуйте @reifman .