I Has A Bug (le blog de jye)

Rechercher

Archives

Nombre de visiteurs*

* Visiteurs uniques : une (1) visite par IP.

La gestion des données chez Google

Jeudi 17 avril 2008 à 15 h 24
Tout d'abord. Je précise que ce billet n'est que le fruit d'une réflexion personnelle et basé sur les discussions que j'ai pu avoir avec des personnes travaillant chez Google. Je ne peux garantir à 100% la véracité de mes propos. Aussi cette discussion sera principalement basée sur Google Apps pour les entreprises, le cas des particuliers sera discuté très rapidement en fin de l'article.

Le premier argument qui revient à l'opposition d'opter pour la solution Google Apps est la gestion des données. En effet, comme tout service de type SaaS (Software as a Service), tout est hébergé chez Google, vos mails, vos documents, tout. Et c'est normal quand on est du milieu professionnel (c'est aussi valable pour le milieu personnel bien sur) de se poser des questions sur la gestion de ses propres données chez Google. En effet dans le milieu professionnel, on peut rapidement avoir des informations très importantes et confidentielles qui circulent par mail ou dans des documents. Contrairement aux structures habituelles qui permettent de poser des limites comme par exemple l'accessibilité de vos mails seulement via un intranet et par internet via un protocole lourd et complexe nécessitant 50 identifications (quand l'entreprise met ça en place, ce qui n'est pas le cas partout, croyez-moi), avec Google Apps, et c'est un des arguments de ventes, vous accédez simplement à vos mails qu'importent ou vous êtes et en toute sécurité.



Forcement, il y a des secteurs et des entreprises qui par conséquent ne peuvent choisir cette solution, car nécessitant un niveau de sécurité très supérieur à la normale, et ce n'est pas le cœur de cible de Google Apps. Mais pour les autres, Google doit forcement s'engager car il est hors de question que des données stockées via Google Apps soient facilement accessibles. De
plus, il est bon de noter que Google, comme toute entreprise basée aux Etats-Unis est soumise au Patriot Act, qui permet aux services des renseignements américains de réclamer et de récupérer sans que l'entreprise puisse broncher les données qu'elle souhaite pour des besoins d'enquêtes etc (qui a dit espionnage industriel ?). Google s'est déjà permis à plusieurs reprises de refuser de donner ses données et est actuellement en train de mettre en place différentes solutions lui permettant de passer outre ce Patriot Act pour tous les utilisateurs de ces services en dehors des Etats-Unis.

A ce niveau là, il est normal de penser qu'il n'y a donc aucun intérêt à utiliser la suite Google Apps. Je vais donc citer quelques arguments qui font l'intérêt de cette solution. Bien sur, on ne peut pas dire que Google Apps est le produit idéal pour toutes les entreprises, tout comme on ne peut pas dire que c'est la pire solution existante.

Contrairement à un hébergement classique des informations (au sein par exemple d'un seul serveur), ici l'information est stockée partout et plusieurs fois. Qu'est ce que ça signifie ? S il existe une faille sur votre serveur. Une personne malintentionnée peut alors tout récupérer. Avec les produits Google, elle ne sera en mesure de récupérer qu'un morceau de l'information car les informations sont stockés sur différents Datacenter, elles sont dupliquées à différents endroits. Il est beaucoup plus compliqué de retrouvé une information contrairement à une solution de stockage sur un Datacenter précis (attention bien sur, si on vole les accès d'un compte, c'est une autre histoire - que ça soit pour la solution Google ou non)

Les applications de Google sont déjà mises à rude épreuve tous les jours, qui ne rêvent pas de publier LA faille de sécurité sur un produit Google ? Par conséquent si le système était non sécurisé on serait rapidement au courant. Et je ne parle pas de la réactivité et de l'efficacité des développeurs chez Google qui n'est plus à prouver.

Enfin, bien sur, on peut se dire que la faille se situe au niveau de Google tout simplement. Et si Google décide d'accéder à vos données et de les fournir à un tiers ? Mais il faut faire preuve de bon sens pour comprendre certains points. Google souhaite s'implanter sur le long terme au sein des entreprises avec Google Apps ce qui n'est pas du tout le cas pour le moment. Ils n'ont strictement AUCUN intérêt à faire ce genre de choses, aussi découvert (et ça ne mettrait pas longtemps), Google aurait une tel mauvaise pub que le marché des entreprises leur serait fermé. Et quand on sait que le marché des pubs sur internet arrive à saturation – et puis Google devra bien trouver un autre moyen pour continuer sa progression - Google n'a vraiment aucun intérêt à se tirer une balle dans le pied. Aucun intérêt.

Et pour les particuliers, il faut savoir qu'en Europe Google a déjà baissé la durée de stockage d'informations privées (sur les recherches) à 18 mois bien que la CNIL et ses équivalents Européens demande encore une baisse à 6 mois. La demande est compréhensible, mais d'un point de vue développeur, je comprends aussi qu'il soit important de stocker certaines informations afin d'améliorer par la suite les algorithmes de recherche. Enfin il y a une derrière chose, on a souvent peur de stocker toutes nos informations chez Google. Peur de se dire qu'ils possèdent toutes nos données, alors on préfère en semer un peu partout et c'est compréhensible.

Bien sur, il y a un facteur de poids qui doit jouer dans une décision comme celle de choisir Google Apps pour son entreprise ou bien de stocker toutes ses données sur les différents services de Google : c'est la confiance, et Google le sait :

« Nous reconnaissons que la confiance de l'utilisateur est un élément-clé de notre activité [...]» Nicole Wong - Avocat général de Google.
9 commentaires, dernier de .

Google AppEngine

Lundi 14 avril 2008 à 17 h 34
Le 8 Avril dernier, Google a lancé son nouveau service, Google AppEngine. Ce service a pour but de vous proposer une solution d'hébergement pour vos applications web. L'avantage d'AppEngine se situe au niveau de la scalabilité (capacité d'un système à évoluer en puissance) de votre architecture web. Pour que vous compreniez mieux, voici un petit exemple. Imaginez que vous développiez une petite application web dans votre coin. Vous êtes une dizaine de personne à vous en servir et vous avez donc un serveur qui est calibré pour ce nombre d'utilisateurs. Du jour au lendemain, un site populaire fait une news sur votre système, ou votre site est "diggué" et donc par conséquent le trafic augmente brutalement. Votre serveur va se retrouver dans les choux et les utilisateurs ne manqueront pas de lâcher un "bouh c'est nul ça marche pas de toute façon". Avec AppEngine, votre architecture web s'adapte à vos besoins (à votre trafic donc), votre serveur devrait donc tenir la charge sans soucis.

Voilà pour la théorie, en pratique, le service vient d'être lancé et il est encore très limité, la partie payante du service n'a pas encore été dévoilé. Pour le moment chaque développeur bénéficie de 500Mo de stockage pour son application et de 5 millions de pages vues par mois. Le dépassement de ces limites entraînera une charge financière pour le développeur mais pour le moment cela bloque juste l'accès à l'application. Je ne m'attarderais donc pas sur ce point. Je vais plutôt vous parler du coté technique.



Un des premiers points négatif tombe directement. Un seul langage supporté (pour le moment). Le Python. Les développeurs PHP, RoR et autres sont donc dans l'impossibilité de déposer leurs applications existantes. Il en est de même pour le système de base de données. Pas de MySQL ou autres, un seul système, BigTable, système interne créé par Google pour leur besoin. On est donc dans l'obligation de se mettre au Python si l'on souhaite créer son application web, forcement l'accessibilité aux services en est réduite. On a donc un premier frein qui va rebuter pas mal de développeur malgré le fait que le Python soit un langage assez simple à comprendre et à utiliser.

A l'ouverture de ce service, je n'ai pas pu récupérer une des 10000 premières invitations. Je me suis donc contenter de récupérer le SDK AppEngine qui permet de travailler en local. Comme d'habitude, Google fait bien les choses puisqu'une doc complète et des tutoriaux viennent illustrer le SDK et ses quelques APIs. On se retrouve très vite avec un "Hello World" qui tourne sur son serveur local. Le principe est très simple. On dispose de deux exécutables pour uploader sur l'AppEngine ainsi que pour tester en local en lançant un serveur web très rapidement.

Après avoir testé un peu plus en profondeur de mon côté, voilà ce que l'on peut reprocher à l'AppEngine :


* Les timezones : Toutes les dates et heures sont basées sur l'heure UTC. Par conséquent il faut insérer des traitements supplémentaires pour recaler les dates et heures au timezone français par exemple. C’est un traitement qui alourdit le temps d’exécution.

* Backup de BDD : Il n'est pas possible à ma connaissance de récupérer un back-up de sa base de données en ligne. On ne peut donc pas non plus faire des traitements de masses sur sa base, si par exemple on souhaite modifier la structure ou faire un import de masse sans passer par l'application web.

* Exécution de tache à heure fixe (CRON par exemple) : La encore on ne peut pas programmer des traitements à heure fixe. Bon ce n'est pas un souci pour la majorité des gens et ça n'est pas dispo' sur la majorité des serveurs web de base non plus.

* Une BDD un peu lente : Quand on commence à pousser un peu niveau requêtes/analyses sur la base (récupérer plus de 2000 lignes par exemple). On se rend compte que BigTable galère un peu et c'est bien dommage.

* Gestion des données en base complexe : Les IDs de lignes ne sont pas accessibles, on est obligé de récupérer l'id après un insert pour ensuite mettre à jour sa colonne perso ID avec le même. Ce qui fait qu'on se retrouve avec deux colonnes représentant la même information, une accessible seulement par BigTable et une autre identique fait par nos soins. D'un fait général, s'aventurer vers une base de données avancée me parait dès lors très complexe.


Mais il ne faut pas oublier que l'AppEngine est tout jeune et comme tout produit Google il est voué à évoluer très rapidement. Les développeurs parlent déjà de supporter plus de langages (ce qui n’est pas forcement une bonne nouvelle, je préfère personnellement cent fois le Python au PHP). Il n'est pas destiné à n'importe qui, mais il offre quelques avantages non négligeables. Comme par exemple l'intégration du SSO Google via l'API. C'est à dire que l'utilisateur s'identifiera avec son compte Google pour se loguer à votre application, en contrepartie vous accéderez à son email, login et autres infos du compte (pas tout bien entendu) alors que vous auriez du coder tout ça -compte et sa gestion- par vous même auparavant.

Il faut donc laisser du temps à l'AppEngine pour murir un peu. Mais nul doute que le produit est intéressant, en particulier si son intégration à Google Apps est possible.

Et vous, vous avez testé ? Ça vous inspire quoi ? Ça vous passe au dessus du cigare ?
20 commentaires, dernier de ap0.

jQuery, Mootools... les librairies JavaScript

Jeudi 3 avril 2008 à 01 h 12
Aujourd'hui je vais vous parler des librairies JavaScript. Tout bon informaticien qui se respecte est un gros fainéant qui a encore des morceaux de chips bolognaise dans sa barbe, composée de poils durs mais aussi de ceux de la puberté, vous savez, ceux qu'on a jamais vraiment voulu couper. Bref, il est tout à fait normal de ne pas vouloir refaire ce que des personnes ont déjà codé. C'est un fait (si bien sur ça ne vous apporte rien de plus qu'une perte de temps). Il arrive donc fréquemment lors de la conception d'un site Internet que l'on souhaite intégrer une fonctionnalité qui nous parait cool (en ce moment, il y a souvent le mot Ajax/Web2 qui traine a coté du nom de cette fonctionnalité) mais qui est franchement casse-couille à mettre en place. Heureusement pour vous, des librairies JavaScript sont là pour vous faire gagner un temps fou.

Elles ont pour but de vous faciliter la vie avec le JavaScript qui est par défaut un langage vraiment indigeste. Elles vous permettront avec une syntaxe facile et surtout en étant cross-browser (c'est à dire que le code produit le même résultat sur tous les navigateurs) de gérer vos pages HTML. Elles permettent d'accéder facilement à des éléments div, tableau, etc et entre autres d'y appliquer des effets pour les afficher, cacher, faire glisser de droite à gauche ou encore de les faire disparaitre avec un fondu des plus coquet. On peut aussi utiliser les fonctions d'XMLHttpRequest plus connu sous le doux nom d'Ajax pour pouvoir modifier votre page en interogeant des pages distances sans recharger toute votre page. Elles permettent aussi d'utiliser pas mal de fonctions qui vous faciliteront la tache tout au long de vos développements JavaScript. De quoi vous évitez beaucoup de boulot. Reste à décider lequel choisir.



jQuery (site officiel) : Surement le plus populaire. Il est facile à prendre en main et une des fonctionnalités que j'apprécie énormément c'est la possibilité d'enchainer les fonctions. Tester certaines fonctions ici mais la page et les démos ne montrent pas vraiment toutes les possibilités de ce framework.

Prototype (site officiel) : Très connu lui aussi et traine souvent avec script.aculo.us. C'est d'ailleurs son principal intérêt car il est à mon gout un peu moins bien que jQuery bien que mieux commenté. On se retrouve vite à faire en plusieurs lignes ce qu'on aurait fait en une seule avec jQuery. Vous pouvez voir des démos ici.

Mootools (site officiel) : Celui que j'utilise en ce moment. Je l'ai rajouté aussi sur Carrefour.fr par exemple, c'est un peu mon petit protégé du moment. Il dispose de très jolies animations, et possède une doc' agréable à lire et plutôt complète. De nombreux exemple sont disponible ici.

Dojo (site officiel) : je vous parle de celui là mais je ne l'ai pas encore testé. Il semble disposer d'énormément de fonctionnalité (mail, fisheye, etc) et à première vue dispose d'une documentation assez impressionnante. Par ici pour les démos.

Voilà, je n'ai pas parlé de Yahoo User Interface Librairy (YUI) que je ne connais pas du tout, ni de plusieurs autres frameworks. Bien sur la question que vous devez vous poser (si tout cela vous intéresse) c'est "lequel dois-je choisir ?" Et bien il n'y a pas vraiment de réponse. Certains framework sont plus rapide que d'autres. Certains offrent des fonctionnalités plus exotiques. C'est à vous de vous faire votre idée en fonction de vos besoins !
16 commentaires, dernier de bosam.

Le Web2.0 -français- se prend une gifle.

Jeudi 27 mars 2008 à 14 h 56
Voilà un billet très rapide.

Vous n'avez peut être pas suivit l'affaire Fuzz vs Oliver Martinez, alors voici un petit résumé :

Fuzz est un service similaire à Digg (je crois). On "Fuzz" un contenu et il est publié en home du site si le nombre de Fuzz est important (je garantie pas la description exacte, je n'utilisais pas ce service). Un jour Fuzz a agrégé un lien pointant vers une news people merdique mettant en scène Oliver Martinez. Le 12 Mars dernier, le responsable de Fuzz, Eric Dupin, est attaqué par Oliver Martinez pour avoir publier ce lien dans Fuzz.

Et le verdict vient de tomber, Eric Dupin vient d'être condamné à 1000 euros de dommages et intérêts et 1500 euros de frais. L'amende n'est pas énormément grosse. Mais ce qui est important c'est qu'une personne a gagné un procès contre un site qui a publié un lien vers une news people (pas de résumé de l'article, pas de preview de l'article, un lien url + texte). Je trouve ça assez fou. On sait tous qu'on est responsable de notre contenu que l'on rédige et des commentaires qui sont sous notre responsabilité. Mais si on ne peut plus publier un simple lien, ça devient problématique, enfin pas tellement. Pour un blog, ça demande encore plus de modération.

Mais à l'heure des RSS/agrégateurs/site web so 2.0, ça devient difficile à gérer.

Et si vous n'avez rien compris, Generation-Nt s'exprime surement mieux que moi.

TV Shows : Mon module Netvibes - Release!

Vendredi 29 février 2008 à 18 h 46
Précédemment sur ce blog:

Le widget est donc prêt en beta : rendez-vous à cette adresse pour le tester en standalone. Vous pouvez aussi directement l'ajouter à vos Netvibes/iGoogle respectif via les boutons en dessous du widget. Pour tester le tout sous Windows Live/Vista/Mac/ et iPhone/iPod Touch il faudra attendre un peu. N'hésitez pas à me soumettre vos idées ! La prochaine fois je détaillerai le code javascript UWA du widget en lui-même et ça sera probablement le dernier billet pour ce widget qui devrait être terminé.



Comme promis, mais avec un peu de retard voici la dernière partie. Actuellement le widget fonctionne correctement sous Netvibes mais je n'ai pas encore testé ailleurs. Je vais ci-dessous détaillé le fonctionnement Javascript du widget :

Petit rappel pour avoir un widget Netvibes, il faut inclure ces deux lignes :

<script type="text/javascript" src="http://www.netvibes.com/js/UWA/load.js.php?env=Standalone"></script>
<link rel="stylesheet" type="text/css" href="http://www.netvibes.com/themes/uwa/style.css" />

Pour que votre widget dispose d'icône, à la fois pour le web et les OS, intégrer ces deux lignes :

/* Web Icon */
<link rel="icon" href="http://jeremyselier.com/netvibes/tvshows.png" type="image/x-icon" />
/* Rich Icon */
<link rel="rich-icon" type="image/png" href="http://jeremyselier.com/netvibes/richicon-tvshows.png"/>

Regardons tout d'abord la partie "préférences" :

<widget:preferences>
<preference name="period" type="list" label="Période" defaultValue="7" onchange="refresh">
<option value="7" label="Les 7 prochains jours" />
<option value="15" label="Les 15 prochains jours" />
<option value="-7" label="Les 7 derniers et prochains jours" />
<option value="-15" label="Les 15 derniers et prochains jours" />
<option value="x" label="Les X prochains jours" />
<option value="-x" label="Les X derniers et prochains jours" />
</preference>
<preference name="x" type="range" label="Nombre de jours (si choisit dans période)" onchange="refresh" defaultValue="1" step="1" min="1" max="100" />
<preference name="number" type="range" label="Nombre d'épisodes par page" onchange="refresh" defaultValue="10" step="1" min="1" max="30" />
<preference name="query" type="text" label="Recherche ($QUERY$ représente les mots clefs) " defaultValue="http://www.google.com/search?q=$QUERY$" />
<preference name="shows" type="hidden" defaultValue="" />
<preference name="showsTxt" type="hidden" defaultValue="" />

<!--
<preference name="hideSeen" type="boolean" label="Caché quand marqué comme Vu?" onchange="refresh" defaultValue="true" />
<preference name="seens" type="hidden" defaultValue="" />
-->

</widget:preferences>

Je définie dans cette partie toutes les options que je souhaite afficher dans ma partie "édition" de mon widget. J'ajoute aussi deux champs Hidden qui vont me permettre de stocker les séries sélectionnés par le user, une version affichable et l'autre destiné à mon API de récupération des données. En commentaire vous pouvez voir deux champs non-implémenté pour le moment qui me permettront d'ajouter la feature Vu/Non vu auquel je réfléchis encore.

Au niveau du code HTML, vous pouvez constater qu'il n'y a rien :

<body>
<p>Loading...</p>
</body>

En effet tout doit être gérer dans le code Javascript.

On passe donc au gros morceau, le code UWA de mon widget. Je vais détailler seulement les fonctions importantes, je passerais sur les fonctions qui me permettent de cacher/afficher du contenu. Tout d'abord le "main" qui est exécuté à la fin du chargement de la page :

widget.onLoad = function() {



var body = 'Code HTML comprenant un petit gif qui simule un loader [...]';
/* Permet d'insérer entre les balises <body> le contenu de la variable body */
widget.setBody(body);

/*Logger - Affiche dans Firebug (Firefox seulement) si <meta name="debugMode" content="true" /> est spécifié*/
widget.log('Updating shows list...');
/*Récupération d'un fichier XML contenant la liste des séries existantes via mon API PHP qui sera en fourni à la fonction ShowsReader.display pour insertion au sein du widget*/
UWA.Data.getXml("http://jeremyselier.com/apis/getShows.php", ShowsReader.display);

widget.log('Getting users shows and preferences...');
/*Récupération des séries ainsi que de différentes options de l'utilisateur*/
var shows = widget.getValue('shows');
var period = widget.getValue('period');
var x = widget.getValue('x');
var number = widget.getValue('number');

/*Logging*/
widget.log('Shows : '+shows);
widget.log('Period : '+period);
widget.log('X : '+x);
widget.log('Number : '+number);

/*Traitement avant appel du webservice qui récupérera le code HTML à afficher*/
if(period == "x" || period == "-x") {
period = period + "&x=" + x;
}

/*Demande via l'API de récupérer sous forme de texte (code html) le contenu du widget en fonction de ses préférences d'affichage et de sa liste de séries suivies.*/
var url = "http://jeremyselier.com/apis/getEpisodeList.php?shows="+shows+"&period="+period+"&number="+number;
widget.log('Get episodes list... '+url);
/* Appel de l'url, le résultat sera fournis à Episodes.display qui se chargera d'injecter dans mon widget la réponse de l'url.*/
UWA.Data.getText(url, Episodes.display);

/*Fonction permettant de remplir le panneau qui permet de supprimer des séries de sa liste*/
widget.log('Get selected show list...');
fillSelectedShows();


}

/* Petite indication pour préciser de faire le même comportement qu'au chargement lors d'un refresh du widget*/
widget.onRefresh = widget.onLoad;

Le plus important dans cette partie est l'utilisation des fonction UWA.Data qui sont des fonctions Ajax permettant d'interroger une URL et dans récupérer le contenu. Il y a plus d'infos ici. La fonction getXML permettra de récupérer un contenu formaté en XML alors que getText récupérera un contenu basic. Cela permet de fournir de l'html qui sera interprété lors de l'injection dans le widget. Sachez qu'il existe aussi la fonction getFeed permettant de récupérer un flux RSS et de parser très facilement son contenu par la suite.

La fonction ShowsReader.display ci-dessous, se contente de parcourir mon flux XML reçu en paramètre et de l'injecter dans ma liste déroulante.

var ShowsReader = {}

ShowsReader.display = function(xml) {

widget.log('ShowsReader.display : getting shows list');
/* On récupère l'élément HTML et on le cache pour la durée du traitement. */
showlist = widget.body.getElementsByClassName("showlist")[0];
showlist.style.display = 'none';

/* On récupère la liste des séries dans le fichier XML. */
var shows = xml.documentElement.getElementsByTagName("show");

/* On spécifie la taille du select. Puis on parcourt la liste des séries afin de les insérer dans le select.*/
showlist.options.length = shows.length;
for (var i = 0; i < shows.length; i++) {
showlist.options[i].text = shows[i].getElementsByTagName('title')[0].firstChild.nodeValue;
showlist.options[i].value = shows[i].getElementsByTagName('description')[0].firstChild.nodeValue;
}

/* Fin du traitement, on re-affiche le select.*/
showlist.style.display = 'block';

widget.log('end ShowsReader.display');
}

La fonction Episodes.display injecte dans mon DIV principal le code HTML renvoyé par mon webservice. En effet mon webservice renvoi un code HTML adapté à mon widget :

var Episodes = {}

Episodes.display = function(content) {

widget.log('Episodes.display');
widget.body.getElementById('tv_tbl').innerHTML = content;
widget.log('end Episodes.display');
}

Enfin la dernière fonction que je vais vous détaillé n'est pas non plus très complexe. Je récupère les séries de l'utilisateur et construit le panneau qui lui permettra d'afficher toutes les séries qu'il suit et de les supprimer s'il le souhaite.

function fillSelectedShows() {
widget.log('fillSelectedShows');

/* Récupération des préférences utilisateurs (shows : Liste des séries au format de l'API; showsTxt : Liste des séries au format affichable) */
var shows = widget.getValue('shows');
var showsTxt = widget.getValue('showsTxt');

/* Construction des tableaux contenant les séries. */
var shows_array = {};
var showsTxt_array = {};

if(shows != null) {
var shows_array = shows.split("-");
var showsTxt_array = showsTxt.split("-");
}

/* Début d'implémentation de l'affichage du panneau suppression */
var str_tab = "Code HTML [...]";

/* Parcours du tableau et construction de l'affichage */
var found = false;
for(i = 0; i < shows_array.length; i++){
if(shows_array[i] != "") {
found = true;
str_tab = str_tab + "Code HTML [...]";
}
}

/* Si on est pas passé dans le tableau, l'utilisateur ne suit donc aucune série */
if(found == false) {
str_tab = str_tab + "Vous ne suivez pas de séries.";
}

/* Fin de construction de l'affichage et insertion dans le widget */
str_tab = str_tab + "Code HTML [...]";
widget.body.getElementsByClassName("tab_del")[0].innerHTML = str_tab;

widget.log('end fillSelectedShows');
}

Je n'ai pas tout détaillé, en regardant la source vous verrez d'autres fonctions qui me permettent d'ajouter une série/supprimer une série (en gros le fonctionnement consiste juste à insérer la série choisie dans mon champ Hidden de préférence user et recharger le widget; idem pour la suppression), afficher/masquer des informations comme le résumé de l'épisode, les panneaux d'ajouts et de suppressions de séries, le petit bloc qui permet d'accéder à la fiche TV/Recherche, et enfin la pagination.

Voilà pour les explications de mon widget. Si vous avez des questions n'hésitez pas et si vous voulez voir la totalité du code UWA, il suffit de jeter un oeil à la source de cette page. Je le considère comme terminé. Je reviendrais dessus pour rajouter la fonction Vu/Non vu, ainsi que l'internationalisation du widget mais l'essentiel est là. Par rapport aux versions précédentes, celle-ci permet de lire le résumé en anglais en cliquant sur le titre de l'épisode. On obtient aussi la chaîne ainsi que l'heure US (que je dois retravailler). Le widget fonctionne parfaitement en mode StandAlone, sur iGoogle et Netvibes. N'ayant plus Vista je ne peux garantir son fonctionnement, de même pour OS X. Si des gens peuvent tester sur ces OS et me faire un retour, ça serait niquel! Je testerais/débuggerais bientôt sous Opera qui de mémoire fout en l'air l'interface.

Autre info, dans le cadre de cette série de billets et de mes widgets; j'ai été interviewé sur le blog des developpeur de Netvibes (cliquez sur le lien pour la lire). Désolé pour la longueur du billet (comme d'hab) et merci à DjMerguez pour le tip CSS pour faire une simili balise [code].
7 commentaires, dernier de jye.

Nouvelle CSS & Nouveau flux RSS blogs.nofrag

Jeudi 31 janvier 2008 à 02 h 14
Un billet rapide pour avoir un petit retour sur ma nouvelle feuille de style. Je l'ai réalisé ce soir avec l'aide de la CSS de McChicken et pour le template, celui d'un blog wordpress : Black Minimalist. Il est fort probable que ma css ne soit pas compatible avec tout les navigateurs, il est trop tard pour que je teste, n'hésitez pas à me lister ce qui ne va pas chez vous, je corrigerais demain !

Je change totalement de sujet pour vous mettre à disposition un moyen de récupérer des flux RSS pour les blogs NoFrag plus complet. Actuellement, on a que le titre et la date de parution. J'ai donc voulu rajouter le contenu du billet et accessoirement le lien vers les commentaires. Je trouve ça beaucoup plus pratique.

Pour pouvoir lire un flux des blogs NF, entrez cette adresse dans votre agregateur préféré :

http://jeremyselier.com/apis/nofrag-rss/getRss.php?user=$USER$
ou $USER$ représente le pseudo de l'auteur du blog.

Bien entendu, si les administrateurs de NoFrag ne souhaitent pas que l'on puisse récuperer le contenu des billets via RSS, je retirerai ce passage de mon billet et j'enleverai les fichiers de mon serveur.
15 commentaires, dernier de jye.

TV Shows : Mon module Netvibes - Beta Test! (4ème partie)

Mercredi 16 janvier 2008 à 23 h 30
Précédemment sur ce blog:

La fonction "Vu/Non vu" n'est pas encore mise en place car je ne sais pas encore comment l'implémenter (des idées ?). La prochaine fois, j'expliquerais comment je récupère la liste des épisodes qui m'intéresse et le fonctionnement de mon widget en UWA. Et vous pourrez normalement commencer à beta-tester le widget pour m'aider à le debugger. Si vous avez des choses à me dire afin d'améliorer ce widget, n'hésitez pas !



Dans le billet précédent vous avez compris comment je récupérais la liste des séries. Je ne vais pas réexpliquer comment je récupère la liste des épisodes pour chaque série car le fonctionnement est identique. Cependant pour représenter la liste des épisodes d'une série, je formate mon document sous un format XML qui à cet aspect :

<?xml version='1.0' standalone='yes'?>
<episodes>
<show>
<title>Nom de la série</title>
<idshow>id epguides.com pour savoir l'url</idshow>
</show>

<episode number="numéro de l'épisode">
<season>numéro de la saison</season>
<date>date de diffusion de l'épisode</date>
<title>titre de l'épisode</title>
<url>url fiche tv.com</url>
</episode>

etc. etc. pour chaque épisode

</episodes>

Le fichier XML tient compte de la période demandée, c'est à dire que si on souhaite voir les épisodes des 7 prochains jours seulement, le fichier XML retournera seulement les épisodes à venir dans les 7 prochains jours.

Malheureusement avec un nombre conséquent de série suivie. Les performances ont vite chutée. J'ai donc mis en place un système de cache tout simple afin de ne pas refaire le parsing à chaque refresh. J'ai appliqué ce système de cache à la fois pour la récupération des séries et pour les épisodes. Le temps de refresh est paramétrable, j'ai pour l'instant fixé celui-ci à :

- refresh toutes les 5 heures pour récupérer la liste des séries existantes.
- refresh toutes les 2 heures pour récupérer la liste des épisodes.

Mais on sait que des nouvelles séries n'arrivent pas tous les jours, je pourrais pousser le système de refresh à une semaine, voire deux. Pour la liste des épisodes je pense qu'un refresh toutes les semaines sera suffisant aussi. J'aimerais avoir votre avis sur ce point donc n'hésitez pas à vous exprimez en commentaire.

Le widget est donc prêt en beta : rendez-vous à cette adresse pour le tester en standalone. Vous pouvez aussi directement l'ajouter à vos Netvibes/iGoogle respectif via les boutons en dessous du widget. Pour tester le tout sous Windows Live/Vista/Mac/Opera et iPhone/iPod Touch il faudra attendre un peu. N'hésitez pas à me soumettre vos idées ! La prochaine fois je détaillerai le code javascript UWA du widget en lui-même et ça sera probablement le dernier billet pour ce widget qui devrait être terminé.
17 commentaires, dernier de PoFzz.

TV Shows : Mon module Netvibes (3ème partie)

Lundi 14 janvier 2008 à 14 h 25
Précédemment sur ce blog:

Nous avons donc deux types de données à récupérer :

- La liste des séries actuelles qui est disponible sur cette page : http://epguides.com/menu/current.shtml.
- La liste des épisodes pour une série : http://epguides.com/Lost/.

Le traitement des données se fera donc en PHP. J’expliquerai sur mon prochain billet comment je récupère ces données (terminé) et on se penchera sur le design du widget (en cours).




Nous allons d'abord nous pencher sur la récupération des séries actuelles. J'ai décidé (ce n'est pas forcement le meilleur choix, à vrai dire, il serait plus logique de récupérer cette liste avec un fichier XML, mais je voulais tester le getFeed de l'UWA) de récupérer la liste des séries en cours via un fichier RSS. Tout d'abord pour récupérer une page distante via mon serveur, je dois passer par un proxy. J'ai donc choisit de récupérer sur le net une classe PHP gérant déjà ça : Class_Http et Proxy de Troy Wolf.

La première étape est d'ouvrir la page distante en lecture :

$dataFile = fopen("http://domain.com/proxy.php?proxy_url=http://epguides.com/menu/current.shtml", "r");

Etant donné que je souhaite produire un fichier RSS au final, j'indique les informations nécessaires afin que mon navigateur comprenne bien qu'il lit un fichier RSS :

header('Content-type: application/rss+xml');

echo "<?xml version=\"1.0\" encoding=\"ISO-8859-1\" ?>
<rss version=\"2.0\" xmlns:atom=\"http://www.w3.org/2005/Atom\">
<channel>
<title>epguides.com - Current US TV Shows</title>
<description>Current US TV Shows from epguides.com RSS feed</description>
<language>en-us</language>
<ttl>60</ttl>
<link>http://domain.com</link>
<atom:link href=\"http://domain.com/getShows.php\" rel=\"self\" type=\"application/rss+xml\" />";

Une fois le début de fichier déclaré, on passe au listing d'items en soi. Je vais donc parcourir ma page html et récupérer les informations qui m'intéressent afin de les injecter dans mon flux RSS.

/** On vérifie l'ouverture du fichier **/
if ( $dataFile )
{
/** On indique que le parsing ne doit pas encore commencer **/
$parsing = false;

/** On lit le fichier jusqu'au bout **/
while (!feof($dataFile))
{
/** On récupère ligne par ligne **/
/** Exemple : <li><b><a href="../Lost/">Lost</a></b> [on hiatus] <span class='red'>returns Jan 31</span></li> **/
$buffer = fgets($dataFile, 4096);

/** Si le parsing est enclenché **/
if($parsing) {
/** On check la présence de "<li><b>" présentes avant chaque titre de série **/
if(stripos($buffer, '<li><b>')!== false) {

/** On récupère dans la ligne $buffer le contenu de <li><b> à la fin de la ligne **/
/** $tvshow = <li><b><a href="../Lost/">Lost</a></b> [on hiatus] <span class='red'>returns Jan 31</span></li> **/
$tvshow = strstr($buffer, '<li><b>');

/** Tableau des string à supprimer **/
$delete = array("<li><b><a href=\"../", "/\">");

/** On supprime <li><b><a href=\"../ de la ligne **/
$toprint = str_replace($delete[0], "", $tvshow);
/** On supprime /\"> de la ligne **/
$toprint = str_replace($delete[1], " - ", $toprint);

/** $toprint = Lost - Lost</a></b> [on hiatus] <span class='red'>returns Jan 31</span></li> **/

/** On récupère la position de </a></b> afin de récupérer seulement ce qui se trouve avant **/
/** Après exécution du substr $toprint = Lost - Lost **/
$pos = stripos($toprint, "</a></b>");
$toprint = substr($toprint, 0, $pos);

/** On génère l'item RSS avec : **/
/** - pour lien http://jeremyselier.com/apis/getEpisodes.php?show=Lost (id série pour epguides.com) qui me permet de récupérer la liste des épisodes **/
/** - pour titre Lost (ce qui se situe après " - ") **/
/** - pour lien guid (id unique) domain.com-Lost **/
/** - pour description l'id série d'epguides.com : Lost **/
echo "\n<item>\n\t<link>http://jeremyselier.com/apis/getEpisodes.php?show=".substr($toprint, 0, strpos($toprint, " - "))."</link>\n\t<title>".substr($toprint, strpos($toprint, " - ")+3)."</title>\n\t<guid>domain.com-".substr($toprint, 0, strpos($toprint, " - "))."</guid>\n\t<description>".substr($toprint, 0, strpos($toprint, " - "))."</description>\n</item>";
}
}

/** Lorsqu'on trouve la phrase 'Shortcuts to sections of this page:' on indique que le parsing peut commencer **/
if(stripos($buffer, 'Shortcuts to sections of this page:')!== false) $parsing = true;

}

echo "\n";

/** On ferme le fichier **/
fclose($dataFile);
}
else
{
die( "fopen failed" ) ;
}


Et voilà le résultat : getShows.php. Cela va me permettre, dans mon widget, de remplir un select qui contiendra toutes les séries actuelles. Le site étant fiable, si une série vient à être créée ou supprimée, il en sera de même automatiquement dans ma liste.

Penchons-nous maintenant sur le design du widget : Celui est assez basique, voici une liste de screenshots :



La fonction "Vu/Non vu" n'est pas encore mise en place car je ne sais pas encore comment l'implémenter (des idées ?). La prochaine fois, j'expliquerais comment je récupère la liste des épisodes qui m'intéresse et le fonctionnement de mon widget en UWA. Et vous pourrez normalement commencer à beta-tester le widget pour m'aider à le debugger. Si vous avez des choses à me dire afin d'améliorer ce widget, n'hésitez pas !
14 commentaires, dernier de jye.

TV Shows : Mon module Netvibes (2ème partie)

Jeudi 10 janvier 2008 à 10 h 40
Précédemment sur ce blog :

Parmi tous les widgets que j'utilise, mon préféré est celui de ben, TV Series qui permet de consulter les prochains épisodes à venir des séries que l'on suit. Le souci ? Réalisé depuis la vieille API Netvibes, celui-ci n'est pas fait en UWA. Du coup ma copine ne peut pas le rajouter à son iGoogle, et moi je ne peux pas le rajouter à mon Vista. J'ai donc décidé de créer mon propre module qui fera probablement la même chose que celui de ben, sauf que le miens sera fait en UWA et offrira donc une portabilité intéressante.



Histoire de délimiter les choses et de ne pas partir n'importe comment, voici un très léger cahier des charges :

- Le widget TV Shows sera automatique. Une fois terminé il récupérera tout seul les nouvelles séries, et enlèvera tout seul les séries terminées/annulées/whatever.
- Il permettra d'ajouter un nombre infini de série à sa liste de suivi.
- L'utilisateur pourra décider d'afficher les séries à venir des 7 ou 15 prochains jours ainsi les 7 et 15 jours passés.
- L'utilisateur pourra supprimer des séries de sa liste (obviously).

Voilà pour les fonctionnalités de base (indispensable à mon gout). Et voici quelques fonctionnalités bonus :

Pour chaque série, vous pourrez :
- Marquer comme Vu (je ne sais pas comment gérer cette feature)
- Rechercher sur un moteur de recherche personnalisable via les préférences
- Consulter la ficher TV.com

Il est aussi probable qu'un clic sur le titre de l'épisode affiche son résumé TV.com (en anglais malheureusement, si vous savez ou trouver en français, pourquoi pas).

Voilà, le widget est maintenant défini. Le plus dur maintenant est de récupérer toutes les informations liées aux séries et de façon automatique. C'est à dire, quelle sont les séries actuellement en cours. Comment récupérer la liste des épisodes à venir d'une série avec leur date, numéro d'épisode etc. Pour cela, on n'a pas d'autres choix que de trouver un site de qualité qui met à jour constamment ses informations. TV.com est très complet mais totalement ingérable. J'ai donc mis de côté ce site pour récupérer les informations (cependant j'irais récupérer le résumé de l'épisode sur ce site). J'ai par contre trouvé le site epguides.com qui lui, est, complet et à jour très rapidement.

A partir de ce site, je peux donc consulter les séries en cours et pour chaque série, je peux avoir la liste des épisodes (et donc la liste des épisodes à venir pour ceux qui ont été annoncés). Malheureusement, aucun flux RSS n'est mis à disposition par le site epguides.com. Je vais donc devoir extraire les données qui m'intéressent.

Nous avons donc deux types de données à récupérer :

- La liste des séries actuelles qui est disponible sur cette page : http://epguides.com/menu/current.shtml.
- La liste des épisodes pour une série : http://epguides.com/Lost/.

Le traitement des données se fera donc en PHP. J’expliquerai sur mon prochain billet comment je récupère ces données (terminé) et on se penchera sur le design du widget (en cours). N’hésitez pas à me donner vos suggestions pour ce widget !
3 commentaires, dernier de jye.

Mon module Netvibes (1ère partie)

Mercredi 9 janvier 2008 à 00 h 25


Tout d'abord au cas où vous ne connaîtriez pas Netvibes : Netvibes est un portail Web français personnalisable, représentatif de ce qu'on appelle le Web 2.0. Netvibes offre à ses utilisateurs un site web personnel constitué par des pages onglets. Ce site est, à toute fin pratique, un portail web individuel qui donne accès à une multitude de services. Chaque service se présente comme un bloc. La page d'accueil de ce site se décompose en modules, représentés graphiquement par des blocs (rectangles). Grâce à l'utilisation d'AJAX, l'utilisateur peut très simplement réorganiser sa page en déplaçant, supprimant ou ajoutant des blocs.




Voilà pour la définition de Netvibes selon Wikipedia. Maintenant que vous y voyez un peu plus clair, je vais vous parler de l'UWA. L'UWA, pour Universal Widget API (titre pompeux je vous l'accorde), est donc une interface de programmation (API pour Application Programming Interface). Les widgets conçus avec fonctionnent non-seulement sur Netvibes, mais également d'autres plates-formes, parmi lesquelles iGoogle, Apple Dashboard, Opera, Windows Live et Windows Vista... Et c'est là tout l'intérêt de l'UWA. On conçoit un widget qui, par la suite, tournera sur toutes les plates-formes du genre (iPod Touch et iPhone compris).

J'utilisais au début iGoogle étant friand des services de google (docs/reader/notebook principalement). Je ne me rappelle plus vraiment comment je suis passé à Netvibes. Ce que je sais, c'est que j'y suis toujours, sûrement pour la variété des widgets et la rapidité du site. J'ai toujours trouvé les widgets qui m'intéressaient jusque là. Mais dernièrement, j'ai voulu ajouter un widget tout simple qui me permettrait d'afficher un compte à rebours suivant une date donnée. J'ai bien sur trouvé quelques widgets fonctionnant selon mes désirs mais l'affichage trop complexe ne me satisfaisait pas. Devant la simplicité du widget à concevoir je me suis lancé dans la réalisation de mon tout premier module pour Netvibes.

Bien sur, il a fallu bien potassé la maigre documentation fournit par Netvibes et pas mal creuser du coté du forum. Une fois assimilé dans les grandes lignes le fonctionnement de l'UWA - voici un PDF résumant bien les fonctions principales - je me suis lancé un peu à l'arrache. Au final ça donne ça (lien direct), et vous il suffit d'afficher la source pour voir la totalité du code source :



On ne peut pas dire que cela soit un très gros module. Ce n'est pas non plus très compliqué. Il faut d'abord inclure deux lignes, en gros, la librairie UWA et sa feuille de style :

<script type="text/javascript" src="http://www.netvibes.com/js/UWA/load.js.php?env=Standalone"></script>
<link rel="stylesheet" type="text/css" href="http://www.netvibes.com/themes/uwa/style.css" />

Une partie <widget:preferences> qui définie littéralement les préférences du widget. Ici :

<widget:preferences>
<preference name="title" type="text" label="Title"
defaultValue="Name of your countdown" />
<preference name="month" type="range" label="Month"
defaultValue="1" step="1" min="1" max="12" />
<preference name="day" type="range" label="Day"
defaultValue="1" step="1" min="1" max="31" />
<preference name="year" type="range" label="Year"
defaultValue="2007" step="1" min="2007" max="2100" />
<preference name="hour" type="range" label="Hour"
defaultValue="0" step="1" min="0" max="23" />
<preference name="minute" type="range" label="Minute"
defaultValue="0" step="1" min="0" max="59" />
</widget:preferences>

Puis un code javascript :

function countdown() { ... }

widget.onLoad = function() {

var title = widget.getValue('title');

widget.setTitle(title);

widget.setPeriodical('updateTime', countdown, 1000);
}

Tout con. Je vous avais prévenu. Je récupère le titre de l'événement dans les préférences et l'insère pour titre de mon widget. Puis j'indique au widget de lancer toutes les secondes la fonction countdown. Je vous passe les détails sur celle-ci. Elles récupèrent les préférences du widget puis calcul les jours, heures, minutes et secondes restantes avant l'événement. Une fois le temps calculé, on insère dynamiquement le texte dans le widget à l'aide de :
widget.setBody('<div class="countdown">'+nb_jour+ ':'+nb_heure+':'+nb_mois+':'+nb_secondes+'</div>');
Et voilà, on a un widget qui tourne sur toutes les plates-formes. Avouez que ça n'a pas l'air très compliqué ? Le plus dur étant de trouver les bonnes fonctions (ici setPeriodical) étant donné que leur doc est... vide.

Parmi tous les widgets que j'utilise, mon préféré est celui de ben, TV Series qui permet de consulter les prochains épisodes à venir des séries que l'on suit. Le souci ? Réalisé depuis la vieille API Netvibes, celui-ci n'est pas fait en UWA. Du coup ma copine ne peut pas le rajouter à son iGoogle, et moi je ne peux pas le rajouter à mon Vista. J'ai donc décidé de créer mon propre module qui fera probablement la même chose que celui de ben, sauf que le miens sera fait en UWA et offrira donc une portabilité intéressante.

Dans mon prochain billet j'aborderais plus en détails la conception de ce module que j'ai décidé d'appeler TV Shows (oui je tape dans l'original).

Edit : Tags autorisés : [ b] [ /b], [ i] [ /i], [ u] [ /u], [ code] [ /code] : On m'aurait menti ?
10 commentaires, dernier de .