Construire une application Web mobile avec l'API Google Reader

Ce didacticiel vous expliquera comment créer une application Web de lecteur de flux d'actualités mobile à l'aide de l'API Google Reader. Cette application sera très "centrée sur les fonctionnalités", mais la base que vous apprendrez ici devrait vous suffire pour que vous développiez vos propres applications. Au moment de la rédaction de ce document, il n’existait pas d’API officielle de Google Reader. Ce didacticiel utilisera donc l’API non officielle couramment utilisée lors de la création d’applications Google Reader..


Étape 1: Concepts et points finaux

Concepts

Google utilise des termes légèrement différents pour certaines des parties principales de l'API de Google Reader. Une partie est liée à leur plate-forme et une autre semble être due à une dérive lorsque l'application a mûri sur le devant. L'un de ces concepts est appelé "flux". Un flux représente un contenu qui est découpé en tranches et en dés ou filtré de différentes manières. Tous les articles d'un flux spécifique font partie d'un flux, de même que tous les articles d'un dossier..
Vous trouverez ci-dessous un tableau présentant les différences entre le jargon client et la terminologie correspondante de l'API Google Reader:

Côté client API
Dossier / Tag Tag / Label
Abonnement Abonnement
Les gens que vous suivez Ami
Étoilé Étoilé
partagé Diffuser

Points de terminaison

Si vous êtes connecté à votre compte Google Reader, essayez de saisir les points de terminaison suivants dans votre navigateur:

Informations de l'utilisateur:
https://www.google.com/reader/api/0/user-info?output=json

Liste des abonnements:
https://www.google.com/reader/api/0/subscription/list?output=json

Liste des dossiers / tags:
https://www.google.com/reader/api/0/tag/list?output=json

Liste des personnes que vous suivez:
https://www.google.com/reader/api/0/friend/list?output=json

Liste des préférences de Google Reader:
https://www.google.com/reader/api/0/preference/stream/list?output=json

Les points de terminaison ci-dessus sont en lecture seule et seront utilisés tout au long de ce tutoriel..


Étape 2: Construire l'interface

Pour accéder à Google Reader, nous allons créer une classe PHP personnalisée. Vous trouverez ci-dessous une liste des fonctions dont cette classe aura besoin (je les détaillerai plus loin):

Fonctions de classe

  • s'identifier - Obtient le code d'authentification Google et le jeton d'édition du lecteur.
  • get_subscriptions - Renvoie une liste de flux abonnés.
  • get_tags - Retourne une liste de dossiers / tags.
  • get_friends - Renvoie une liste des personnes que vous suivez.
  • get_stream_items - Renvoie un article d'un flux.
  • set_article_read - Définit un article comme lu.
  • set_article_starred - Étoiles un article.
  • set_article_broadcast - Ajoute un article à votre liste partagée.
  • set_article_review - Applique le tag "review" à un article.
  • get_url - Requête HTTP GET avec authentification Google.
  • get_anon_url - Requête HTTP GET sans authentification Google.
  • post_url - Requête HTTP POST avec authentification Google.
  • post_anon_url - Requête HTTP POST sans authentification Google.

Propriétés

Notre classe PHP utilisera un certain nombre de propriétés différentes.

Comme vous pouvez le deviner, les propriétés suivantes seront définies pour l'identifiant de messagerie et le mot de passe de votre compte Google Reader:

 public $ grEmail = "; public $ grPasswd =";

Les propriétés suivantes sont utilisées dans les fonctions de classe Curl (consultez le code source de celles-ci):

 public $ userAgent = 'tuts + rss + bot'; public $ proxy = 0; public $ proxyUrl = ";

J'ai inclus la prise en charge du proxy, car mon fournisseur d'accès (Godaddy) a besoin du trafic sortant pour passer par un proxy. Si vous n'avez pas besoin de support proxy, gardez $ proxy à 0 dans gr-config.php.

Ensuite, nous avons beaucoup de points de départ pour l'API disponibles:

 protected $ _urlBase = 'https://www.google.com'; protected $ _urlApi = 'https://www.google.com/reader/api/0'; protected $ _urlAuth = 'https://www.google.com/accounts/ClientLogin'; protected $ _urlToken = 'https://www.google.com/reader/api/0/token'; protected $ _urlUserInfo = 'https://www.google.com/reader/api/0/user-info'; protected $ _urlTag = 'https://www.google.com/reader/api/0/tag'; protected $ _urlSubscription = 'https://www.google.com/reader/api/0/subscription'; protected $ _urlStream = 'https://www.google.com/reader/api/0/stream'; protected $ _urlFriend = 'https://www.google.com/reader/api/0/friend';

Les trois propriétés suivantes stockent les informations collectées au cours du processus d'authentification:

 public $ userInfo = "; protected $ auth ="; protected $ token = ";

Dans la section application, nous allons définir ces sessions sur les sessions PHP afin que nous n'ayons pas à nous connecter à chaque demande..


Étape 3: Étoffer les fonctions de la classe

Les fonctions suivantes feront le gros du travail pour notre application.

Fonction de connexion

Nous devons utiliser l'API d'authentification Google pour commencer:

 $ data = '& Email ='. $ this-> grEmail. '& Passwd ='. $ this-> grPasswd. '& service = reader & source ='. $ this-> userAgent. '& continue = http: //www.google.com '; $ result = $ this-> post_anon_url ($ this -> _ urlAuth, $ data);

Après avoir interrogé l'API d'authentification, la première chose à collecter est la chaîne $ auth. Cette chaîne fournit nos informations d'identification à la couche d'authentification de Google. Obtenir le $ auth est utile pour presque tous les services Google.

 preg_match ('/ Auth = (\ S *) /', $ result, $ match); $ this-> auth = $ match [1];

Vient ensuite le jeton $ et nous devrons utiliser un autre noeud final pour cela. Le jeton est spécifique à Google Reader et est requis pour les demandes d’écriture ou de changement d’état..

 $ this-> token = $ this-> get_url ($ this -> _ urlToken);

Le troisième est un objet d'informations utilisateur, nous aurons besoin de la partie userId. Certaines des options de l'API nécessitent votre identifiant utilisateur google, qui est un grand nombre qui représente votre compte et non l'ID de messagerie que vous utilisez pour les connexions. Les informations utilisateur contiennent également le grand nombre utilisé pour accéder à votre flux partagé..

 $ this-> userInfo = json_decode ($ this-> get_url ($ this -> _ urlUserInfo));

Fonctions de liste

Ce sont des fonctions simples pour récupérer une liste de vos flux de différentes manières..

get_subscriptions renvoie une liste de tous les flux auxquels vous êtes abonné:

 function get_subscriptions () $ result = $ this-> get_url ($ this -> _ urlSubscription. '/ list? output = json'); return json_decode ($ result); 

get_tags retourne une liste de tous les dossiers et tags:

 function get_tags () $ result = $ this-> get_url ($ this -> _ urlTag. '/ list? output = json'); return json_decode ($ result); 

get_friends renvoie une liste des personnes que vous suivez:

 function get_friends () $ result = $ this-> get_url ($ this -> _ urlFriend. '/ list? output = json'); return json_decode ($ result); 

Fonction Items

Ceci est la viande de la classe et à quoi tout le reste conduit. Avec cette fonction, nous renvoyons les articles individuels en fonction des critères spécifiés. le $ stream est extraite des résultats des fonctions de la liste et il peut s'agir d'un flux provenant d'un ami, d'un dossier entier ou d'un flux spécifique. $ n est le nombre d'articles à retourner en même temps. Pour l'application, je l'ai limitée à 20, mais si vous réutilisez ceci pour autre chose qu'un affichage en temps réel, vous pouvez le placer à 1000. Après 1000, vous devez utiliser l'option de continuation, ce qui est hors de portée pour cela. article.

get_stream_items accepte un certain nombre de paramètres et avec les valeurs par défaut, vous devez seulement lui fournir un flux:

 function get_stream_items ($ stream = ", $ xt_a = array ('utilisateur / - / state / com.google / read'), $ daysago = 3, $ n = 20, $ magic = True) 

$ ot est utilisé pour indiquer à Google Reader que vous ne souhaitez pas renvoyer les articles les plus anciens cette fois-ci. Google Reader va à l'époque, mais j'aime bien utiliser $ daysago parce que c'est plus facile de passer par jours plutôt que par secondes. À partir de là, on peut calculer $ ot à partir de l'heure actuelle. $ ck C'est important, mais je n'ai jamais reçu de bonne explication à ce sujet. Sans une API officielle de Google Reader, cela pourrait rester un mystère. Je l'ai réglé sur time () * 1000 et cela fonctionne, alors que time () * 100 ne fonctionne pas.

 $ ot = time () - ($ daysago * 86400); $ ck = time () * 1000;

$ magie est un booléen pour renvoyer les articles en utilisant le classement "magique" de Google Reader ou, si faux, par le plus récent en premier. Vous pouvez également trier les plus vieux en commençant par $ r = 'o' si vous le souhaitez.

 if ($ magic == True) $ r = 'a';  else $ r = 'n'; 

$ xt_a est utilisé pour exclure les articles d'un flux basé sur certaines métadonnées liées à l'état de l'article. Par défaut, la fonction ne renvoie que les messages non lus car elle exclut les articles marqués comme lus..

 $ xt = "; foreach ($ xt_a as $ key => $ value) $ xt. = '& xt ='. $ value;

Nous transmettons l'URL finale à Google Reader et renvoyons les résultats une fois les paramètres définis:

 $ url = $ this -> _ urlStream. '/ contents /'.$ stream.'? ot = '. $ ot.' & r = '. $ r. $ xt.' & n = '. $ n.' & ck = ' . $ ck. '& client ='. $ this-> userAgent; $ result = $ this-> get_url ($ url); return json_decode ($ result); 

Définir la fonction

Trois de ces fonctions permettent d'écrire dans Google Reader et de marquer des articles dans un certain état. Le dernier est utilisé pour définir une balise. Vous pouvez facilement condenser les quatre fonctions en une seule fonction et passer le "a =" comme paramètre de fonction. Cette configuration est juste ma préférence, je la préfère ainsi afin que le code utilisant la classe soit plus propre et plus facile à lire. Si vous envisagez de créer votre propre fonction, vous pouvez soumettre plusieurs "a =" à la fois. En outre, vous pouvez passer plusieurs options "i =" et "s =", il vous suffit de passer un montant égal et dans le bon ordre. Je passe généralement 10 à la fois en marquant beaucoup d'articles comme lus.

Définissez l'article à l'état "lu":

 fonction set_article_read ($ id, $ stream) $ url = $ this -> _ urlApi. '/ edit-tag? pos = 0 & client ='. $ this-> userAgent; $ data = 'a = utilisateur / - / state / com.google / read & async = true & s ='. $ stream. '& i ='. $ id. '& T ='. $ this-> jeton; return $ this-> post_url ($ url, $ data); 

Star l'article:

 fonction set_article_starred ($ id, $ stream) $ url = $ this -> _ urlApi. '/ edit-tag? pos = 0 & client ='. $ this-> userAgent; $ data = 'a = utilisateur / - / state / com.google / starred & async = true & s ='. $ stream. '& i ='. $ id. '& T ='. $ this-> token; return $ this-> post_url ($ url, $ data); 

Partagez l'article avec ceux qui vous suivent:

 fonction set_article_broadcast ($ id, $ stream) $ url = $ this -> _ urlApi. '/ edit-tag? pos = 0 & client ='. $ this-> userAgent; $ data = 'a = utilisateur / - / state / com.google / broadcast & async = true & s ='. $ stream. '& i ='. $ id. '& T ='. $ this-> jeton; return $ this-> post_url ($ url, $ data); 

Ce dernier applique une balise review:

 fonction set_article_review ($ id, $ stream) $ url = $ this -> _ urlApi. '/ edit-tag? pos = 0 & client ='. $ this-> userAgent; $ data = 'a = utilisateur /'.$ this-> userInfo-> userId.' / label / Review & async = true & s = '. $ stream.' & i = '. $ id.' & T = '. $ this-> jeton ; return $ this-> post_url ($ url, $ data); 

Ce qui précède devrait être utilisé dans l'application pour que vous puissiez marquer quelque chose à réviser lors de la prochaine utilisation d'un navigateur classique..


Étape 4: à l'application

L’interface de l’application est construite sur la base de l’excellent HTML5 HTML5, à l’adresse http://html5boilerplate.com/. J'ai pris le fichier index.php de la passe-partout et je l'ai divisé en fichiers d'en-tête et de pied de page. La page principale est index.php et acceptera un &liste valeur de chaîne de requête indiquant quelle liste afficher. La valeur par défaut est la liste des dossiers. Tout élément de la liste ira à articles.php avec le &courant et &liste passé. La classe est placée dans un fichier gr.php. Gr-config.php est en fait le fichier qui l'inclut dans les autres. Cela peut sembler évident, mais dans gr-config.php, nous allons également définir les options de configuration pour la classe. Le dernier fichier php est set_article.php. Il sera appelé avec une requête AJAX de articles.php et est responsable de l'appel des fonctions de l'ensemble.

J'ai inclus les deux balises ci-dessous dans le fichier d'entête header.php mais elles ont été commentées:

  

Ils font en sorte que l'application Web fonctionne davantage comme une application normale lorsque vous ajoutez le site sur l'écran d'accueil iOS.. apple-touch-startup-image fournit une image à afficher pendant le chargement de la page principale. apple-mobile-web-app-capable fait que le site s'exécute sur sa propre instance Safari plutôt que dans l'instance générale Safari. La seule chose qui pose problème est qu'avec apple-mobile-web-app-capable Si vous définissez ce paramètre sur Oui, le fait de cliquer sur un lien vers un autre domaine ouvre le lien dans l'instance principale de Safari, ce qui vous oblige à effectuer plusieurs tâches en même temps dans l'application de lecture..


Étape 5: Construction de la page principale

Pour cette application, nous allons construire une page principale qui affichera une liste de Dossiers (par défaut), Amis ou Abonnements.

Capture d'écran

La mise en place

Voici la configuration au début des pages index.php, articles.php et set_article.php:

 session_set_cookie_params (300); session_start (); include_once ('gr-config.php'); include_once ('header.php');

Le menu

Le menu est une simple liste HTML qui peut être utilisée pour récupérer les différentes listes d’abonnements:

 

Le menu utilise un sprite pour les boutons basé sur le jeu d’icônes sympa Glyphish.

Le code

Passons maintenant à la première utilisation réelle de la classe. Fondamentalement, nous allons vérifier si &liste est défini et, dans le cas contraire, par défaut sur la vue des étiquettes Ensuite, il suffit d’une instruction switch pour savoir quelle liste construire et quelle fonction utiliser.

Tout d'abord, nous par défaut $ liste aux balises si rien n'est passé puis passe $ liste à un commutateur. Quand $ liste correspond aux sous-marins que nous venons de produire une liste assez simple de tous les abonnements retournés. Cela peut être très difficile pour les gros utilisateurs, c’est pourquoi le mode tags est le mode par défaut..

 if (isset ($ _GET ['liste'])) $ list = $ _GET ['liste'];  else $ list = 'tags';  switch ($ list) case 'subs': $ subs = $ gr-> get_subscriptions (); foreach ($ subs-> abonnements sous forme de $ sub) echo '
  • ', $ sub-> titre,'
  • '; Pause;

    Les données sont renvoyées avec la chaîne d'étiquette complète plutôt que simplement le nom du dossier. Configurer $ remove nous permettra de nous débarrasser des parties inutiles de la chaîne d'étiquette et d'afficher simplement le nom du dossier. Malheureusement, il n’existe aucun moyen d’exclure Review des étiquettes renvoyées, il a donc fallu gérer le problème avec PHP. Je vérifie également que nous affichons uniquement les étiquettes:

     case 'tags': $ tags = $ gr-> get_tags (); $ remove = 'user /'.$ gr-> userInfo-> userId.' / label / '; foreach ($ tags-> tags en tant que $ tag) if (strpos ($ tag-> id, '/ label /')> 0 && strpos ($ tag-> id, '/ Review') == 0) $ title = str_replace ($ remove, ", $ tag-> id); echo '
  • ', $ title,'
  • '; Pause;

    L'URL des amis contient cependant beaucoup d'informations supplémentaires issues du profil de l'utilisateur. Une bonne chose que nous pouvons utiliser est la photo de profil et l’inclure en tant qu’image de 32 pixels:

     case 'friends': $ friends = $ gr-> get_friends (); foreach ($ amis-> amis comme $ ami) if ($ ami-> contactId! = -1) echo '
  • ', $ friend-> displayName, '
  • '; Pause;

    Étape 6: Construction de la page d'article

    Cette page est l'endroit où vous allez voir les articles, les marquer comme lus, les définir pour une relecture ultérieure, les marquer comme favoris ou les partager avec vos amis..

    Capture d'écran

    La mise en place

    Identique à la page principale.

    Le menu

    Une autre liste HTML simple. Je ne suis pas fan de l'utilisation de window.history pour un bouton de retour, donc pour le retour, je les renvoie à la liste qu'ils visionnaient.

     

    Le code

    le get_stream_items La fonction de notre classe est le pilote principal de la page et la plupart des valeurs par défaut sont bonnes pour cela. Par défaut, les éléments marqués comme lus sont exclus, mais j'ai étendu la $ xt_a array pour exclure également les articles marqués du libellé "review". De cette façon, les éléments que nous marquons pour révision ne figurent jamais sur cette liste même si nous ne les avons pas encore lus. Nous allons charger les articles cachés div balises et seulement montrer la :premier enfant, puis manipuler les autres via JavaScript.

     $ stream = $ _GET ['stream']; $ articles = $ gr-> get_stream_items ($ stream, array ('utilisateur / - / état / com.google / read', 'utilisateur /'.$ gr-> utilisateurInfo-> utilisateurId.' / label / Review ')) ; if (count ($ articles-> items)> 0) foreach ($ articles-> items en tant que $ article) 

    Au lieu d'essayer de conserver l'état dans une session ou un tableau en JavaScript, j'utilise simplement les éléments de données les plus récents en tant qu'attributs du div de l'emballage de chaque article..

     écho '
    '; echo'
    substitute [0] -> href, '">', $ article-> titre, '
    ';

    Le contenu peut revenir sous forme de résumé ou non en fonction du flux. Puisque nous sommes mobiles, nous essaierons d’obtenir un résumé, mais retomberons au contenu complet s’il n’est pas disponible. Nous allons également faire apparaître les liens de l'article dans une nouvelle fenêtre..

     if (isset ($ article-> summary-> content)) $ content = str_replace ('href =', 'target = "_ blank" href = ", $ article-> summary-> content); else $ content = str_replace ("href = ',' target =" _ blank "href = ', $ article-> contenu-> contenu); 

    Enfin, affichez ce que nous avons:

     écho '
    ', $ content,'
    '; écho '
    ';

    Étape 7: JavaScript pour les actions d'article

    JavaScript est fortement dépendant de jQuery. Les appels de menu article.php set_article () lorsque vous cliquez sur une action et appelez set_article.php pour traiter cette action. set_article () va d'abord saisir l'identifiant et le flux de l'article que nous regardons div étiquette. Il va ensuite récupérer le total pour déclencher un rechargement si nous atteignons la fin des articles disponibles. Le script set_article.php renverra 1 si l'action effectuée doit être déplacée vers le prochain article. Sinon, il vérifie l'action effectuée et allume l'icône Étoile ou Partager. C'est en utilisant $ .eq () et la variable tranche énumérer les articles retournés.

    Réglage total variable dynamiquement plutôt que d'utiliser simplement '20':

     var total = $ ('. article'). size (); fonction set_article (action) 

    Ajout d'attributs à l'emballage de l'article div étiquette:

     id = $ ('. article'). eq (slice) .attr ('id'); stream = $ ('. article'). eq (slice) .attr ('stream');

    Ici, nous passons l'id et le flux à la page set_article.php et récupérons un 1 ou un 0. Le 1 signifie que l'action nécessite la suppression de l'article de la vue et le 0 signifie qu'il ne s'agit que d'un changement d'état..

     $ .get ('/ set_article.php? action =' + action + '& id =' + id + '& stream =' + flux, fonction (données) if (data == "1") $ ('. article') .eq (slice) .hide (); slice + = 1; $ ('. article'). eq (slice) .show (); $ ('. starred'). css (backgroundPosition: '-62px -31px '); $ ('. broadcast '). css (backgroundPosition:' -93px -31px '); else 

    S'il renvoie 0, nous devons voir quelle action a été entreprise pour que l'état d'icône approprié soit également activé:

     if (action == 'starred') $ ('. starred'). css (backgroundPosition: '-62px 0px');  else $ ('. broadcast'). css (backgroundPosition: '-93px 0px');  if (slice> = total) window.location.reload (true); ); 

    Étape 8: Application d'actions à des articles

    Ceci est le dernier morceau de PHP qui nous permettra de manipuler l'article.

    La mise en place

    Identique à la page principale.

    Le code

    Le travail acharné est effectué dans la classe. Cette page est donc simplement un commutateur permettant d’exécuter la fonction de classe qui correspond à l’action. Vous pourriez vous demander pourquoi Google exige la $ stream variable. D'après ce que je peux dire, tout dépend de la manière dont Google stocke toutes les données du lecteur et réduit le temps de transaction lors du traitement de ces fonctions d'édition.

     if (isset ($ _GET ['action']))) $ action = $ _GET ['action']; $ id = $ _GET ['id']; $ stream = $ _GET ['stream']; switch ($ action) case 'read': $ r = $ gr-> set_article_read ($ id, $ stream); echo '1'; Pause; case 'starred': $ r = $ gr-> set_article_starred ($ id, $ stream); echo '0'; Pause; case 'broadcast': $ r = $ gr-> set_article_broadcast ($ id, $ stream); echo '0'; Pause; case 'review': $ r = $ gr-> set_article_review ($ id, $ stream); echo '1'; Pause; 

    Étape 9: Arrondir avec CSS

    La plupart des CSS n’ont rien de trop spécial. J'ai les deux styles principaux inclus ci-dessous:

     .résumé de l'article img, .article-résumé embed max-height: 50%; largeur maximale: 50%;  .article: premier-enfant display: block; 

    le hauteur maximale: 50% et largeur maximale: 50% les déclarations sont très utiles lors de la réaffectation de HTML pouvant contenir des images et des incorporations. Il empêche les images et YouTube de surcharger l'écran du mobile.


    Étape 10: En savoir plus

    Jusqu'à ce qu'il y ait une API officielle, ces emplacements sont parfaits pour obtenir des informations supplémentaires sur la création d'applications avec Google Reader:

    • Amis de l’API non officielle de Google Reader: un groupe de discussion riche en informations et en contacts intéressants.
    • Niall Kennedy: l'un des premiers à jouer avec l'API.
    • Dépassement de pile: questions avec le tag google-reader-api (j'ai commencé à répondre à certaines d'entre elles).
    • pyrfeed: le wiki de cette classe python a beaucoup d’informations.
    • Martin Doms: Bravo pour la ventilation des URL utilisées dans l'API.