1. Code
  2. PHP
  3. Yii

Creación con la API de Twitter: Administración de listas

Esta es la segunda parte de nuestro tutorial sobre la API de Lista de Twitter dentro de nuestra más amplia serie sobre la API de Twitter. En este tutorial, revisaremos la creación de características para listas con la API. Los ejemplos de códigod de este tutorial se proporcionan en el repositorio de Github. Aquí se describen con más detalle las instrucciones de instalación (asegúrate de utilizar el repositorio proporcionado en este tutorial y no el repositorio Birdcage inicial que aparece en esa página).
Scroll to top

Spanish (Español) translation by Eva Collados Pascual (you can also view the original English article)

Final product imageFinal product imageFinal product image
What You'll Be Creating

Esta es la segunda parte de nuestro tutorial sobre la API de Lista de Twitter dentro de nuestra más amplia serie sobre la API de Twitter. En este tutorial, revisaremos la creación de características para listas con la API. Los ejemplos de códigod de este tutorial se proporcionan en el repositorio de Github. Aquí se describen con más detalle las instrucciones de instalación (asegúrate de utilizar el repositorio proporcionado en este tutorial y no el repositorio Birdcage inicial que aparece en esa página).

Descripción general de la API de Lista de Twitter

Una vez más, hay aproximadamente 19 APIs para listas de Twitter, divididas en tres áreas principales:

Comencemos con la integración de algunas de las características básicas del desarrollo de la API de Listas.

Creación de una lista

Cuando cargues Birdcage, verás la página Manage Lists (Administrar listas). Haz clic en la opción Create a List (crear una lista) en el menú de la barra lateral derecha.

Twitter List API Manage Lists emptyTwitter List API Manage Lists emptyTwitter List API Manage Lists empty

Se mostrará el formulario Create a List (crear una lista). Voy a crear una lista para rastrear a los periodistas de Seattle en Twitter:

Twitter List API Create a ListTwitter List API Create a ListTwitter List API Create a List

Aquí tienes el código Create en TwitterlistController.php. Controla el código para mostrar el formulario y, después de que se publique el formulario, el código para el procesamiento:

1
    public function actionCreate()
2
	{
3
		$model=new TwitterList;
4
		$this->performAjaxValidation($model);
5
		if(!isset($_POST['TwitterList'])) {
6
		  // initial load

7
		  // load the current selected account as a default

8
  		$model->account_id = Yii::app()->session['account_id'];
9
  		// display form

10
  		$this->render('create',array(
11
  			'model'=>$model,
12
  		));		  
13
		} else {
14
		  // POSTed - process form

15
			$model->attributes=$_POST['TwitterList'];
16
			// load the account selected

17
		  $account = Account::model()->findByPK($model->account_id);
18
		  // connect to twitter

19
		  $twitter = Yii::app()->twitter->getTwitterTokened($account['oauth_token'], $account['oauth_token_secret']);
20
			// create remotely at Twitter

21
      $new_list= $twitter->post("lists/create",array('name'=>$model->name,'description'=>$model->description,'mode'=>$model->getModeString($model->mode))); 
22
			if (TwitterList::model()->isError($new_list)) {
23
			  // to do - set flash error

24
  			var_dump($new_list);
25
  			yexit();
26
			} else {
27
  			$model->owner_id =$account->twitter_id;
28
  			$model->list_id =$new_list->id_str;
29
  			$model->slug=$new_list->slug;
30
  			$model->full_name=$new_list->full_name;
31
        $model->created_at = date( 'Y-m-d H:i:s', strtotime($new_list->created_at) );
32
        $model->modified_at =new CDbExpression('NOW()');          			
33
  			if($model->save())
34
  				$this->redirect(array('admin'));			  
35
			}
36
		}
37
	}

Puede leer la documentación de la API de Listas de Twitter/Crear aquí.

Una vez enviado el formulario, verás algo como esto:

Twitter List API Manage Twittert Lists after CreateTwitter List API Manage Twittert Lists after CreateTwitter List API Manage Twittert Lists after Create

Importación de miembros a una lista

Una de las limitaciones más frustrantes de la interfaz de usuario de las listas de Twitter es lo difícil que resulta añadir nuevos miembros. Tienes que visitar el perfil de cada miembro y añadirlos individualmente a tus listas: el proceso es muy complicado y lento.

Vamos a implementar una función para suscribir un listado separado por comas de una serie de cuentas de Twitter.

En la vista de lista, si haces clic en el icono Administrar lista a la derecha de Journalists Seattle, verás la página Ver lista:

Twitter List API View List Members emptyTwitter List API View List Members emptyTwitter List API View List Members empty

Haz clic sobre Importar miembros en el menú de la barra lateral derecha. A continuación, escribe la lista de cuentas de Twitter que desees añadir a este listado:

Twitter List API Import Twitter Accounts to ListTwitter List API Import Twitter Accounts to ListTwitter List API Import Twitter Accounts to List

Revisemos el código que sube los miembros a Twitter. El código para mostrar el formulario anterior comienza en ListMemberController.php:

1
    /**

2
	 * Import members to a list

3
	 */
4
	public function actionImport($id)
5
	{
6
	      $model = new Import();
7
    		$model->list_id = $id;
8
    		// Uncomment the following line if AJAX validation is needed

9
    		$this->performAjaxValidation($model);
10
    		if(isset($_POST['Import']))
11
    		{
12
    			if($model->save()) {
13
    			  $result = ListMember::model()->import($id,$_POST['Import']['member_list']);
14
            Yii::app()->user->setFlash('import_success','Thank you! Your members have been added.');
15
        		$this->redirect(array('/twitterlist/view','id'=>$id));
16
            } // end if save

17
    			 // end if post

18
  			} else {
19
      		$this->render('import',array(
20
      			'model'=>$model,'list_id'=>$id,
21
      		));  			  
22
  			}	
23
  	}

En el modelo ListMember.php, el código de importación tiene el siguiente aspecto. Usamos preg_split para convertir la lista de cuentas en una matriz. Luego, para cada cuenta, obtenemos información sobre la cuenta en Users/Show y publicamos el ID de Twitter en Lists Member Create (Listas de creación de miembros).

1
public function import($id,$import_list) { 
2
      // retrieve account

3
	  $tl = TwitterList::model()->findByAttributes(array('id'=>$id));
4
	  $list_id = $tl['list_id'];
5
	  $account = Account::model()->findByPk($tl->account_id);
6
    // retrieve members and add to list

7
    $twitter = Yii::app()->twitter->getTwitterTokened($account['oauth_token'], $account['oauth_token_secret']);
8
    // convert post rows to array

9
    $add_list = preg_split ("(\r|\n|,)", $import_list, -1, PREG_SPLIT_NO_EMPTY);
10
    $max_count = 0;
11
    foreach ($add_list as $item) {
12
        $item = trim($item);
13
        $user_info= $twitter->get("users/show",array('screen_name'=>$item)); 
14
        if (ErrorLog::model()->isError('getUserInfo', $account['id'], $user_info)) {
15
          continue;
16
        }            
17
        if (ErrorLog::model()->isRateLimited($user_info)) {
18
          continue;
19
        }
20
          // add remotely to list

21
        $people= $twitter->post("lists/members/create",array('list_id'=>$list_id,'screen_name'=>$item)); 
22
        // add locally to db

23
        $this->remote_add($list_id,$user_info->id_str,$item);
24
        $max_count+=1;
25
        if ($max_count>=99) break; 
26
    }
27
	}
28
29
  	public function remote_add($list_id,$member_id,$screen_name = 'tbd') {
30
      TwitterUser::model()->setPlaceholder($member_id,$screen_name); 
31
      $lm = ListMember::model()->findByAttributes(array('list_id'=>$list_id,'member_id'=>$member_id));
32
      if (empty($lm)) {
33
    	  $lm = new ListMember;
34
    	  $lm->list_id=$list_id;
35
    	  $lm->member_id=$member_id;
36
    	  $lm->save();
37
    	}
38
  	}

Después de enviar los miembros, verás algo como esto:

Twitter List API View List MembersTwitter List API View List MembersTwitter List API View List Members

El tbd representa un usuario que aún no está en nuestra base de datos; la información del perfil se obtendrá (hidratará) en segundo plano más adelante.

En Twitter, verás algo como esto:

Twitter List API List Member View at TwitterTwitter List API List Member View at TwitterTwitter List API List Member View at Twitter

Sincronización de listas

Ahora que hemos creado una lista, vamos a buscar las listas que ya existen en nuestra cuenta para poder administrarlas desde nuestra consola. De nuevo, en el menú Administrar listas, haz clic en Sincronizar listas.

Twitter List API Manage Lists Twitter List API Manage Lists Twitter List API Manage Lists

La acción de sincronización está codificada en TwitterlistController.php:

1
    public function actionSync()
2
	{
3
	  TwitterList::model()->sync();
4
		$this->redirect(array('admin'));
5
	}

La operación de sincronización del modelo TwitterList.php es relativamente sofisticada, como se muestra a continuación. En primer lugar, el modelo de sincronización recorre todas las cuentas que hayas configurado y llama a la cuenta syncOne para las listas.

SyncOne llama a fetch Lists/Ownerships en la API para buscar todas las listas propiedad de cada cuenta.

1
    public function sync() {
2
	  $users = User::model()->findAll();
3
    foreach ($users as $user) {
4
      $user_id = $user['id'];
5
      $accounts = Account::model()->findAllByAttributes(array('user_id'=>$user_id));      
6
      // loop through Twitter accounts (may be multiple)

7
      foreach ($accounts as $account) {
8
        $this->syncOne($account['id']);
9
      } // end account loop

10
    } // end user loop  

11
	}
12
	
13
	public function syncOne($account_id) {
14
	  $account=Account::model()->findByPk($account_id);
15
    $twitter = Yii::app()->twitter->getTwitterTokened($account['oauth_token'], $account['oauth_token_secret']);
16
    // fetch lists owned by this account

17
    $twitter_lists= $twitter->get("lists/ownerships",array('count'=>100,'cursor'=>-1)); 
18
    //print_r($twitter_lists);

19
    if (count($twitter_lists->lists)==0) return;
20
    foreach ($twitter_lists->lists as $tl) {
21
      //echo $tl->id_str.' '.$tl->slug.' '.$tl->member_count;lb();

22
      $this->remote_add($account_id,$tl);
23
      // spawn action to get list members

24
      $this->addMembershipAction($account_id,$tl->id_str);
25
    }	 // end loop of lists  

26
	}

Sin embargo, en lugar de intentar capturar los miembros de la lista en tiempo real, lo que probablemente agotaría el tiempo de espera, crea una acción en segundo plano para capturar los miembros de una lista determinada.

1
    public function addMembershipAction($account_id,$item_id) {
2
	  // adds a background task action to retrieve memberships for a list id

3
     $check_dup = Action::model()->findByAttributes(array('account_id'=>$account_id,'action'=>Action::ACTION_MEMBERSHIPS,'status'=>Action::STATUS_ACTIVE,'item_id'=>$item_id));
4
     if (empty($check_dup)) {
5
        $a = new Action();
6
        $a->account_id = $account_id;
7
        $a->action = Action::ACTION_MEMBERSHIPS;
8
        $a->item_id = $item_id;
9
        $a->last_tweet_id = 0; // set cursor

10
        $a->status = Action::STATUS_ACTIVE;
11
        $a->created_at =new CDbExpression('NOW()');          
12
        $a->modified_at =new CDbExpression('NOW()');          
13
     	  $a->save();   
14
     	}
15
	}

La tarea cron en segundo plano invoca el modelo Action.php que llama a getListMembership para una lista cada vez.

1
    public function getListMembership($action,$limit = 50) {
2
      // collect next $limit members of list

3
      $account = Account::model()->findByPk($action->account_id);
4
      // last_tweet_id is the cursor 

5
      $cursor = $action->last_tweet_id;
6
      if ($cursor ==0 ) $cursor =-1; // since last_tweet_id is unsigned, can't store -1 start	    

7
      $result = TwitterList::model()->getMemberships($account, $action->item_id, $cursor , $limit);
8
      $a = Action::model()->findByPk($action->id);
9
      if ($result->rateLimit) {
10
        return false;
11
      } else if ($result->complete) {
12
        $a->status=self::STATUS_COMPLETE;
13
        $a->save();
14
      } else {
15
          // set lowest cursor

16
          $a->last_tweet_id = $result->cursor;
17
          $a->save();
18
      } 
19
	}

Cuando se ejecuta la tarea, invoca el método getMemberships del modelo TwitterList.php. Este método utiliza la cursorización para paginar a través de los registros de miembro sin agotar el tiempo de espera o alcanzar los límites de velocidad. El último cursor se almacena en la tabla Action para que la siguiente invocación en segundo plano pueda continuar añadiendo miembros donde lo dejó anteriormente.

1
    public function getMemberships($account,$list_id, $cursor =-1,$limit = 200) {
2
	    echo 'entering getMemberships: account_id:'.$account['id'].' list_id:'.$list_id.' cursor: '.$cursor;lb();
3
      $result = new StdClass;
4
      $result->cursor = -1;
5
      $result->count =0;
6
      $result->error =false;
7
      $result->complete = false;
8
      $result->rateLimit = false;
9
      $count_people = 0;
10
      // retrieve members and add to list

11
      $twitter = Yii::app()->twitter->getTwitterTokened($account['oauth_token'], $account['oauth_token_secret']);
12
      echo 'here'.$cursor;lb();
13
      while ($cursor <>0 ) {
14
        echo 'inside';lb();
15
        $people= $twitter->get("lists/members",array('list_id'=>$list_id,'cursor'=>$cursor,'skip_status'=>true,'include_entities'=>false)); 
16
        if (ErrorLog::model()->isError('getMemberships', $account['id'], $people)) {
17
          $result->error =false;
18
          return $result;
19
        }              
20
        if (ErrorLog::model()->isRateLimited($people)) {
21
         $result->rateLimit = true;
22
         return $result;
23
        }
24
        if (isset($people->next_cursor))
25
          $cursor = $people->next_cursor;
26
        else
27
          $cursor = 0;
28
        $result->cursor = $cursor;
29
        $count_people+=count($people->users);
30
        echo 'Count people: '.count($people->users);lb();
31
        foreach ($people->users as $u) {
32
          //var_dump($u);lb();

33
          echo 'Member:'.$u->screen_name;lb();
34
          if (isset($u->screen_name))
35
            $screen_name = $u->screen_name;
36
          else
37
            $screen_name = 'tbd';
38
          ListMember::model()->remote_add($list_id,$u->id_str,$screen_name);
39
        }        
40
        if (count($people->users)==0 or $cursor==0) {
41
          $result->complete = true;      
42
          return $result;
43
        }
44
      } // end while loop

45
      echo 'exiting getMemberships';lb();	    
46
      return $result;        
47
	}

Cuando se complete la operación deberías ver algo como esto:

Twitter List API Manage ListsTwitter List API Manage ListsTwitter List API Manage Lists

Una vez completadas las tareas en segundo plano, verás miembros para cada lista como en la siguiente imagen:

Twitter List API View List MembersTwitter List API View List MembersTwitter List API View List Members

¿Qué viene a continuación?

Espero que hayas disfrutado de esta serie sobre la API List de Twitter hasta ahora. Me gustaría escuchar tus sugerencias sobre tus escenarios de uso de la API favoritos y solicitudes de características; por favor, publícalos a través de la sección de comentarios.

Si tienes alguna pregunta o sugerencia, por favor publícala a través de un comentario. Si deseas mantenerte al día sobre mis próximos tutoriales y otras series en Tuts+, por favor visita mi página de instructor o sígueme en Twitter, @reifman.

Enlaces relacionados