Construire avec l'API Twitter Tweet Storms

Ce que vous allez créer

En avril, l'investisseur et fondateur de Netscape, Marc Andreessen, a commencé à étendre les limites naturelles de Twitter à 140 caractères en publiant ses pensées sous forme de séquences de tweets, que certains ont surnommés les tweet storms (l'entrepreneur Yvo Schaap les a compilées sur son site Web).. 

Cela n'a pas pris longtemps avant que BuzzFeed (le débutant du listicule qui doit être stoppé) ne se soit opposé à cette pratique: Pourquoi la dernière tendance de Twitter sur Twitter ™ doit être stoppée. Personnellement, je suis probablement pour tout ce que BuzzFeed est contre.

Quelques services sont apparus pour aider les simples mortels comme nous à publier plus facilement des tweet storms, mais ils semblaient un peu peu fiables et incohérents. J'ai décidé de créer la fonctionnalité moi-même et je pense qu'il est utile de le faire avec votre propre application..

Dans ce didacticiel, je vais vous expliquer comment créer votre propre fonctionnalité de tempête de tweet à l'aide de l'API Twitter. Ceci est la suite de ma série de tutoriels API Twitter sur Tuts +; vous pouvez trouver un lien vers tous sur la page de mon auteur.

Fonctionnalités requises pour Tweet Storm

Tout d'abord, décidons de ce que nous avons besoin de notre fonctionnalité TweetStorm pour accomplir. 

  • Créer un groupe de tweets.
  • Les numéroter dans l'ordre.
  • Publiez-les dans un ordre séquentiel sur Twitter.
  • Fournir une page Web publique permettant aux gens de les lire ensemble.
  • Publier le lien vers cette page dans un dernier tweet.

Les résultats devraient ressembler à ceci:

Je présume que vous connaissez mon précédent tutoriel Birdcage et que vous avez déjà un code qui authentifie votre compte via OAuth avec l'API Twitter.

Le modèle de base de données

Birdcage utilise une table d'état pour les tweets. Tout d'abord, nous allons étendre cette table avec une migration Yii ActiveRecord afin d'inclure des champs pour la séquence numérique tweet_id publiée et la séquence numérique de tempête de tweet. 

L'extension de notre modèle de base de données existant est assez facile avec les migrations YR ActiveRecord:

./ app / protected / yiic migrate create extend_status_table

Voici le code de migration:

tablePrefix = Yii :: app () -> getDb () -> tablePrefix; if ($ this-> tablePrefix <> ") $ this-> tableName = $ this-> tablePrefix.'status '; fonction publique safeUp () $ this-> avant (); $ this-> addColumn ($ this -> nomTable, 'tweet_id', 'BIGINT (20) DEFAULT 0'); $ this-> addColumn ($ this-> nomTable, 'sequence', 'TINYINT DEFAULT 0'); $ this-> addColumn ($ this- > nom_table, 'code_erreur', 'INTEGER DEFAULT 0'); fonction publique safeDown () $ this-> avant (); $ this-> dropColumn ($ this-> nomTable, 'tweet_id'); $ this-> dropColumn ($ this-> nomTable, 'séquence'); $ this-> dropColumn ($ this-> nomTable, 'code_erreur');

Nous utiliserons les tweet_ids pour afficher publiquement l'intégralité du tweet storm sur une page Web après la publication. La séquence numérique déterminera l'ordre des tweets d'état dans notre tempête.

Ensuite, nous devons créer une table pour un conteneur de tweets d’état, essentiellement un conteneur pour la tempête de tweets. Je vais utiliser le terme Groupe, car nous allons le réutiliser pour une autre fonctionnalité de regroupement dans un tutoriel de suivi, des tweets récurrents issus d'un groupe. Visitez ma page d’auteur pour voir quand elle est sortie ou suivez-moi sur Twitter @reifman.

 Créons une nouvelle migration pour créer la table Groupe:

./ app / protected / yiic migrer créer create_group_table

Le code ci-dessous construit le schéma. Notez la relation de clé étrangère pour lier la tempête de tweet à un compte Twitter spécifique:

tablePrefix = Yii :: app () -> getDb () -> tablePrefix; if ($ this-> tablePrefix <> ") $ this-> tableName = $ this-> tablePrefix.'group '; fonction publique safeUp () $ this-> before (); $ this-> createTable ($ this -> tableName, array ('id' => 'pk', 'account_id' => 'entier par défaut 0', 'nom' => 'chaîne par défaut NULL', 'slug' => 'chaîne par défaut NULL', 'type_groupe '=>' tinyint default 0 ',' stage '=>' integer default 0 ',' created_at '=>' DATETIME NOT NULL DEFAULT 0 ',' modified_at '=>' TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP ',), $, this-> MySqlOptions); $ this-> addForeignKey ('fk_group_account', $ this-> tableName, 'account_id', $ this-> tablePrefix.'account ',' id ',' CASCADE ',' CASCADE '); fonction publique safeDown () $ this-> before (); $ this-> dropForeignKey ('fk_group_account', $ this-> nom_table); $ this-> dropTable ($ this-> nom_table);

Nous allons également construire une table relationnelle appelée GroupStatus qui suit les tweets d’état au sein de chaque groupe:

tablePrefix = Yii :: app () -> getDb () -> tablePrefix; if ($ this-> tablePrefix <> ") $ this-> tableName = $ this-> tablePrefix.'stat_groupe '; fonction publique safeUp () $ this-> avant (); $ this-> createTable ($ this -> tableName, array ('id' => 'pk', 'group_id' => 'INTEGER NOT NULL', 'status_id' => 'INTEGER default 0',), $ this-> MySqlOptions); $ this-> addForeignKey ('fk_group_status_group', $ this-> tableName, 'id_groupe', $ this-> préfixe_table.'group ',' id ',' CASCADE ',' CASCADE '); $ this-> addForeignKey (' fk_group_status_status ', $ this-> tableName, 'status_id', $ this-> tablePrefix.'status ',' id ',' CASCADE ',' CASCADE '); public function safeDown () $ this-> avant (); $ this- > dropForeignKey ('fk_group_status_group', $ this-> nomTable); $ this-> dropForeignKey ('fk_group_status_status', $ this-> nomTable); $ this-> dropTable ($ this-> nomTable);

Pour afficher publiquement le tweet storm sur une page Web, nous avons besoin d'une autre table pour mettre en cache le code HTML par twitter_id à partir de la méthode de l'API Oembed de Twitter:

tablePrefix = Yii :: app () -> getDb () -> tablePrefix; if ($ this-> tablePrefix <> ") $ this-> tableName = $ this-> tablePrefix.'embed '; fonction publique safeUp () $ this-> avant (); $ this-> createTable ($ this -> tableName, array ('id' => 'pk', 'tweet_id' => 'bigint (20) unsigned NOT NULL', 'html' => 'text default null', 'created_at' => 'DATETIME NOT NULL DEFAULT 0 ',' modified_at '=>' TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP ',), $ this-> MySqlOptions); $ this-> createIndex (' tweet_id ', $ this-> tableName,' tweet_id, 'tweet_id', false);  fonction publique safeDown () $ this-> before (); $ this-> dropIndex ('tweet_id', $ this-> nom_table); $ this-> dropTable ($ this-> nom_table);

Construire le code

Le contrôleur de groupe et les modèles

Ensuite, nous utiliserons le générateur de code d’échafaudage de Yii, Gii, pour construire le modèle, les contrôleurs et le CRUD. Sur mon environnement local, je visite http: // localhost: 8888 / twitter / app / gii pour accéder à Gii. Tout d'abord, je crée le modèle:

Ensuite, j'utilise le générateur Bootstrap CRUD:

Nous utiliserons également Gii pour créer des modèles par défaut pour les tables GroupStatus et Embed. Ils n'ont pas besoin de contrôleurs et de vues.

Dans la vue de la barre de navigation (/app/protected/views/layouts/main.php), Je vais ajouter une option dans mon menu de composition au groupe de tweets:

 array ('label' => 'Compose', 'items' => array (array ('url' => array ('/ status / compose'), 'label' => 'Planifier un tweet'), array (' url '=> tableau (' / groupe '),' label '=>' Groupe tweets '), tableau (' url '=> tableau (' / status / admin '),' label '=>' Gestion du planning ') , array ('url' => array ('/ statuslog / admin'), 'label' => 'Review Log'),)),

La page Gestion des tweets de groupe ressemble à ceci:

En cliquant sur l'icône la plus à gauche dans chaque ligne, un groupe s'ouvre pour ajouter des tweets et les séquencer..

En cliquant sur le lien ajouter un menu de groupe, vous obtiendrez un formulaire vous permettant de nommer le tweet storm et de choisir un compte Twitter pour celui-ci:

Nous devons étendre le comportement de création par défaut pour compléter le modèle. Je réutilise ma méthode Slugify de Geogram pour créer un slug ressemblant à une URL à partir du nom. Ajouter ceci à Group.php:

/ ** * Modifie une chaîne pour supprimer tous les caractères et espaces non ASCII. * / public function slugify ($ text) //sourcecookbook.com/fr/recipes/8/function-to-so-slugify-strings-in-php // remplace les lettres ou chiffres non par - $ text = preg_replace ('~ [ ^ \\ pL \ d] + ~ u ',' - ', $ text); // trim $ text = trim ($ text, '-'); // transliterate if (function_exists ('iconv')) $ text = iconv ('utf-8', 'us-ascii // TRANSLIT', $ text);  // minuscule $ text = strtolower ($ text); // supprime les caractères indésirables $ text = preg_replace ('~ [^ - \ w] + ~', ", $ text); if (empty ($ text)) return 'error-généré-slug'; return $ text ;

Voici le modifié actionCréer dans GroupController.php:

 fonction publique actionCreate () $ model = new Group; // Décommentez la ligne suivante si la validation AJAX est nécessaire // $ this-> performAjaxValidation ($ model); if (isset ($ _ POST ['Groupe'])) $ modèle-> attributs = $ _ POST ['Groupe']; $ model-> slug = Group :: model () -> slugify ($ model-> nom); $ model-> created_at = new CDbExpression ('NOW ()'); $ model-> modified_at = new CDbExpression ('NOW ()'); if ($ model-> save ()) $ this-> redirect (array ('view', 'id' => $ model-> id));  $ this-> render ('create', array ('model' => $ model,));  

Ajouter des tweets à la tempête

Vous ajoutez ensuite des tweets d’état pour votre tempête et sélectionnez la séquence numérique avec laquelle ils doivent apparaître:

Nous utilisons une forme dérivée de la forme de composition de statut de Birdcage:

breadcrumbs = array ('Statuts' => array ('index'), 'Create',); / * $ this-> menu = array (array ('label' => 'Gérer la planification', 'url' => array ('admin')), array ('label' => 'Journal de révision', 'url' => array ('statuslog / admin')),); * /?> 

Composez un Tweet pour votre groupe

renderPartial ('_ groupform', tableau ('modèle' => $ modèle, 'maxCount' => $ maxCount)); ?>

Voici la _groupform.php Voir la fiche:

baseUrl; $ cs = Yii :: app () -> getClientScript (); $ cs-> registerScriptFile ($ baseUrl. '/ js / jquery.simplyCountable.js'); $ cs-> registerScriptFile ($ baseUrl. '/ js / twitter-text.js'); $ cs-> registerScriptFile ($ baseUrl. '/ js / twitter_count.js'); ?> beginWidget ('bootstrap.widgets.TbActiveForm', array ('id' => 'status-form', 'enableAjaxValidation' => false,)); ?> user-> hasFlash ('no_account')) $ this-> widget ('bootstrap.widgets.TbAlert', array ('alerts' => array (// configurations par type d'alerte 'no_account' => array ('block' => true, 'fade' => true, 'closeText' => '×'),),)); ?> 

Champs avec * sont requis.

errorSummary ($ model); ?> hiddenField ($ model, 'account_id', array ('value' => $ model-> account_id)); ?>
textAreaRow ($ model, 'tweet_text', array ('id' => 'tweet_text', 'rows' => 6, 'cols' => 50, 'class' => 'span8')); ?>

Restant: 0

'Séquence:')); ?> dropDownList ($ modèle, 'séquence', $ modèle-> getSequence ()); ?>
widget ('bootstrap.widgets.TbButton', array ('buttonType' => 'submit', 'type' => 'primaire', 'label' => $ model-> isNewRecord? 'Create': 'Save', ) ?>
endWidget (); ?>

Ici se trouve le getSequence méthode utilisée par le formulaire, de Status.php:

 fonction publique getSequence () $ i = 1; $ seq = array ('default' => 'sélectionnez la séquence ci-dessous'); tandis que ($ i<=99)  $seq[$i]=$i; $i++;  return $seq;  

Les tweets d'état au sein de groupes comportent quatre caractères plus courts que 140 caractères, ce qui permet d'insérer une numérotation de séquence..

Lorsque vous ajoutez des tweets d’état à votre groupe, la page Gérer le groupe ressemblera à ceci:

Les améliorations futures pourraient inclure des commandes de séquence ascendante / descendante pour les éléments d'état ainsi qu'une numérotation automatique lorsque vous ajoutez de nouveaux tweets.

Publier la tempête

Bien que vous puissiez simplement publier les tweets en séquence, il est utile de gérer cela en arrière-plan pour plus de robustesse, en cas d'échec en cours de route..

Étant donné que de nombreuses fonctions de l'API Twitter nécessitent des curseurs ou une pagination, j'ai déjà intégré un modèle de processus en arrière-plan dans mon framework avancé, Birdhouse. Je vais vous montrer les bases de l'ajout de l'édition tempête de tweet à votre application.

Lorsque vous cliquez sur Publier tempête, nous créons une action pour gérer ce processus en arrière-plan:

 fonction publique publish ($ group_id) // crée une action pour publier la tempête en arrière-plan $ gp = Group :: model () -> findByPK ($ group_id); $ check_dup = Action :: model () -> findByAttributes (array ('action' => Action :: ACTION_STORM, 'item_id' => $ group_id, 'status' => Action :: STATUS_ACTIVE)); if (empty ($ check_dup)) $ a = nouvelle action; $ a-> account_id = $ gp-> account_id; $ a-> action = Action :: ACTION_STORM; $ a-> status = Action :: STATUS_ACTIVE; $ a-> item_id = $ group_id; $ a-> created_at = new CDbExpression ('NOW ()'); $ a-> modified_at = new CDbExpression ('NOW ()'); $ a-> save ();  

Ensuite, les tâches d’arrière-plan cron normales gèrent la table Action et appellent Action :: model () -> publishStorm:

fonction publique publishStorm ($ action) // publie un groupe twitter storm $ results = Group :: model () -> publishStormItems ($ action-> account_id, $ action-> item_id); if ($ results) // si true, l'action est terminée $ a = Action :: model () -> findByPk ($ action-> id); $ a-> status = self :: STATUS_COMPLETE; $ a-> save (); 

Cela appelle à son tour le modèle du groupe publishStormItems:

// publie le groupe en tant que tempête sur twitter fonction publique publishStormItems ($ account_id, $ group_id) $ error = false; $ account = Account :: model () -> findByPK ($ account_id); // établit la connexion à Twitter $ twitter = Yii :: app () -> twitter-> getTwitterTokened ($ compte ['oauth_token'], $ compte ['oauth_token_secret']); // récupère les statuts non publiés dans un groupe spécifique $ statuses = Status :: model () -> in_account ($ account_id) -> stage_zero () -> in_specific_group ($ group_id) -> findAll (array ('order' => 'sequence ASC ')); $ tweet_id = 0; foreach ($ statuses as $ status) $ prefix = $ status-> sequence. '. '; // ajouter le nombre de séquences en tant que préfixe echo $ préfixe. $ status-> tweet_text; lb (); $ tweet_id = Status :: model () -> postTweet ($ twitter, $ status, $ préfixe); if ($ tweet_id! = 0) // étape de mise à jour en publication = 1 $ ns = Yii :: app () -> db-> createCommand () -> update (Yii :: app () -> getDb () - > tablePrefix.'status ', array (' stage '=> 1,' tweet_id '=> $ tweet_id),' id =: id ', array (': id '=> $ status-> id));  else $ error = true;  // si vous terminez si (nombre ($ statuses)> 0 et! $ error) // publiez le dernier tweet avec un lien vers la tempête $ groupe = Group :: model () -> findByPk ($ group_id); $ status = 'Lisez ou partagez mon tweet tempête sur'. $ group-> name. ' dans son intégralité ici: '. $ _ SERVER ["SERVER_NAME"].' / storm /'.$ group-> slug; if (strlen ($ status)> 120) $ status = 'Lire ou partager tout mon tweet storm:'. $ _ SERVER ["SERVER_NAME"]. '/ storm /'.$ groupe-> slug;  $ tweet = $ twitter-> post ("statuses / update", tableau ('status' => $ status));  // si c'est le cas, retourne true return! $ error; 

La requête ActiveRecord que nous utilisons pour trouver les tweets d'état dans un groupe non publié est la suivante:

$ statuses = Status :: model () -> in_account ($ account_id) -> stage_zero () -> in_specific_group ($ group_id) -> findAll (array ('order' => 'sequence ASC')); 

Cette requête utilise des étendues définies comme suit dans le modèle Status:

fonction publique scopes () return array (// partie d'un groupe de tweets 'in_group' => array ('condition' => 'status_type ='. self :: STATUS_TYPE_IN_GROUP,), 'stage_zero' => array ('condition '=>' stage = 0 ',),' has_tweet_id '=> array (' condition '=>' tweet_id <> 0 '),);  fonction publique in_specific_group ($ group_id) $ crit = $ this-> getDbCriteria (); $ crit-> addCondition ("id IN (SELECT status_id FROM tw_group_status WHERE group_id =: group_id)"); $ crit-> params [': group_id'] = $ group_id; return $ this;  // champs d'application personnalisés public function in_account ($ account_id = 0) $ this-> getDbCriteria () -> mergeWith (array ('condition' => 'account_id ='. $ account_id,)); return $ this;  

Lorsque nous parcourons chaque statut devant être tweeté, nous ajoutons un préfixe pour le numéro de séquence, par exemple. "1. Mon premier tweet est…":

foreach ($ statuses as $ status) $ prefix = $ status-> sequence. '. '; // ajouter le nombre de séquences en tant que préfixe echo $ préfixe. $ status-> tweet_text; lb (); $ tweet_id = Status :: model () -> postTweet ($ twitter, $ status, $ préfixe); if ($ tweet_id! = 0) // étape de mise à jour en publication = 1 $ ns = Yii :: app () -> db-> createCommand () -> update (Yii :: app () -> getDb () - > tablePrefix.'status ', array (' stage '=> 1,' tweet_id '=> $ tweet_id),' id =: id ', array (': id '=> $ status-> id));  else $ error = true; 

Lorsqu'un statut est publié, l'étape est incrémentée. Les améliorations futures pourraient inclure la possibilité de republier les tempêtes de tweet plusieurs fois. Actuellement, nous n'autorisons qu'une seule publication (de rien, Buzzfeed).

Si tous les tweets ont été postés avec succès, nous publions un dernier tweet avec un lien vers le tweet storm:

 // si finissant si (compte ($ statuses)> 0 et! $ error) // publie le dernier tweet avec un lien vers la tempête $ group = Group :: model () -> findByPk ($ group_id); $ status = 'Lisez ou partagez mon tweet tempête sur'. $ group-> name. ' dans son intégralité ici: '. $ _ SERVER ["SERVER_NAME"].' / storm /'.$ group-> slug; if (strlen ($ status)> 130) $ status = 'Lire ou partager tout mon tweet storm:'. $ _ SERVER ["SERVER_NAME"]. '/ storm /'.$ groupe-> slug;  $ tweet = $ twitter-> post ("statuses / update", tableau ('status' => $ status));  

Voici à quoi ressemble un Tweet Storm lorsqu'il est publié:

Voir la tempête sur le Web

Ainsi, bien que nous puissions afficher publiquement les tempêtes de tweet sur le Web sous forme de texte, comme Yvo Schaap, j’ai pensé qu’il serait préférable d’utiliser des images incorporées sur Twitter avec lesquelles l’utilisateur peut interagir, par exemple. suivre, répondre, retweet et al.

Au départ, je pensais pouvoir utiliser du code HTML statique et remplacer simplement le twitter_id dans la vue, mais Twitter préfère passer un appel OEmbed et mettre en cache le code HTML pour chaque tweet. J'ai créé la table incorporée ci-dessus pour le faire.

Alors, commençons par créer un itinéraire dans UrlManager de Yii afin que le chemin de notre application puisse être redirigé pour afficher les tweetstorms à l'aide du slug convivial pour les URL. Dans /app/protected/config/main.php, ajoutez la redirection de slug de tempête ci-dessous. Cela redirigera les requêtes vers http: // votredomaine / tempête / mes-pensées-sur-twitters-api vers l'action de recherche du contrôleur de groupe avec my-thoughts-on-twitters-api en tant que paramètre:

 'urlManager' => array ('urlFormat' => 'chemin', 'showScriptName' => false, 'caseSensitive' => false, 'rules' => array ('/'=>'/vue', '//'=>'/','/'=>'/',' / hybridauth '=>' / hybridauth ',' / storm /'=>' / group / lookup / ', "=>' site / index '),), 

Grâce aux filtres d'accès au contrôleur de Yii, faisons en sorte que tout visiteur public puisse voir les tempêtes, mais que les actions CRUD ne soient visibles que par les utilisateurs authentifiés. Modifier le règles d'accès dans GroupController.php comme suit:

 fonction publique accessRules () return array (array ('allow', // autorise tous les utilisateurs à effectuer des actions 'tempête' '' => array ('recherche'), 'users' => array ('*'),), array ('allow', // autorise l'utilisateur authentifié à effectuer ces actions 'actions' => array ('index', 'view', 'create', 'update', 'delete'), 'users' => array ( '@'),), array ('allow', // autorise l'utilisateur admin à effectuer 'actions admin' actions '=' array ("), 'users' => array ('admin'),), array ( 'refuser', // refuser à tous les utilisateurs 'utilisateurs' => array ('*'),),); 

Lorsqu'une demande arrive pour http://votredomaine.com/storm/your-storm-name, elle est dirigée vers l'action de recherche du contrôleur de groupe:

fonction publique actionLookup ($ slug) $ success = false; $ this-> layout = 'storm'; // essayer de chercher par slug $ group = Group :: model () -> findByAttributes (array ('slug' => $ slug)); $ embeds = Group :: model () -> fetchEmbeds ($ group-> id); if ($ group! == null) $ success = true; $ this-> render ('lookup', array ('embeds' => $ embeds, 'name' => $ group-> name,)); 

le fetchEmbeds La méthode cherche d’abord dans notre base de données une copie mise en cache, puis vers l’API Twitter pour extraire le code HTML. le fetchEmbeds method construit un tableau de tweets HTML:

 fonction publique fetchEmbeds ($ group_id) $ e = new Embed (); $ group = Group :: model () -> findByPk ($ group_id); $ embed = array (); $ statuses = Status :: model () -> in_account ($ group-> account_id) -> has_tweet_id () -> in_specific_group ($ group_id) -> findAll (array ('order' => 'sequence ASC')); foreach ($ statuses en tant que $ status) $ embed [] = $ e-> fetch ($ groupe-> identifiant_compte, $ status-> tweet_id);  return $ embed;  

Il utilise la méthode d'extraction du modèle Embed:

fonction publique fetch ($ account_id, $ tweet_id) // se trouve-t-il dans la table incorporée $ data = Embed :: model () -> findByAttributes (array ('tweet_id' => $ tweet_id)); if (empty ($ data)) // existe-t-il une connexion if (is_null ($ this-> twitter)) $ account = Account :: model () -> findByPK ($ account_id); // établit la connexion à Twitter $ this-> twitter = Yii :: app () -> twitter-> getTwitterTokened ($ compte ['oauth_token'], $ compte ['oauth_token_secret']);  $ result = $ this-> twitter-> get ("statuses / oembed", array ('id' => $ tweet_id)); $ html = $ result-> html; $ this-> add ($ tweet_id, $ html);  else $ html = $ data-> html;  return $ html;  fonction publique add ($ tweet_id, $ html) $ e = new Embed (); $ e-> html = $ html; $ e-> tweet_id = $ tweet_id; $ e-> modified_at = new CDbExpression ('NOW ()'); $ e-> created_at = new CDbExpression ('NOW ()'); $ e-> save ();  

La connexion OAuth à Twitter n'est initiée que si au moins un tweet_id doit être récupéré, et il ne le fait qu'une fois pour des raisons de performances..

En clôture

J'espère que vous avez trouvé ce tutoriel sur les tempêtes de tweet utile. C'était vraiment une fonctionnalité amusante à construire. N'hésitez pas à poster des corrections, des questions ou des commentaires ci-dessous. J'essaie de suivre le fil de discussion Tuts +. Vous pouvez également me joindre sur Twitter @reifman ou m'envoyer un email directement.

Vous pouvez trouver le tutoriel initial sur les API Twitter pour Birdcage ici, ainsi qu'un lien vers tous mes tutoriels sur les API Twitter sur la page de l'auteur de Tuts + au fur et à mesure de leur publication. Birdcage propose un référentiel Github gratuit et open source pour se familiariser avec les fonctionnalités de base de l'API Twitter..