Sam & Max » multiboards http://sametmax.com Du code, du cul Sat, 07 Nov 2015 10:56:13 +0000 en-US hourly 1 http://wordpress.org/?v=4.1 Multiboards Customizable – Le retour de la mort de la peur de mourir 18 http://sametmax.com/multiboards-customizable-le-retour-de-la-mort-de-la-peur-de-mourir/ http://sametmax.com/multiboards-customizable-le-retour-de-la-mort-de-la-peur-de-mourir/#comments Tue, 18 Aug 2015 11:46:48 +0000 http://sametmax.com/?p=16741 Pour ceux qui ont suivi la lamentable mais néanmoins poilante mise en prod de la nouvelle version buggée de MB j’ai du reporter un rendez-vous avec mon escort pour réparer le bébé.

Normalement ça devrait marcher (ça valait pas un post mais c’est pour remplir un peu plus les BAL des abonnés…)

Rendez-vous ici ou ou encore et donnez-moi vos impressions si comme moi vous n’avez pas d’ami et passez votre temps à la maison devant l’ordi au lieu de vous dorer la pilule entouré de femmes fontaines sur une île déserte.

Une source de flux RSS pas mal ici.

PS: Normalement dans l’onglet en haut à droite il devrait y avoir la liste des boards populaires, on calcule ça en fonction du nombre de visiteurs en ligne en temps réel, Sam avait fait un article dessus.

Et une bonne fin qui pourrait faire brève de comptoir:
“Tant que le board n’est pas populaire il reste anonyme” (et donc ne s’affiche pas dans l’onglet) ^^

]]>
http://sametmax.com/multiboards-customizable-le-retour-de-la-mort-de-la-peur-de-mourir/feed/ 18
cd multiboards; git checkout versionquimarche 6 http://sametmax.com/cd-multiboards-git-checkout-versionquimarche/ http://sametmax.com/cd-multiboards-git-checkout-versionquimarche/#comments Tue, 28 Jul 2015 16:21:20 +0000 http://sametmax.com/?p=16706 Il y a des mises en prod heureuses. Et d’autres non.

Là c’est non.

Je rollback jusqu’à ce qu’on répare tout ça.

]]>
http://sametmax.com/cd-multiboards-git-checkout-versionquimarche/feed/ 6
Multiboards est désormais customisable 22 http://sametmax.com/multiboards-est-desormais-customisable/ http://sametmax.com/multiboards-est-desormais-customisable/#comments Sun, 26 Jul 2015 19:23:54 +0000 http://sametmax.com/?p=16696 J’avais pensé à un titre du genre: “Vous aussi, créez votre propre Multiboards et devenez riche” mais ça risquait de faire légèrement pompeux. On garde donc un titre simple.

Pour ceux qui ne connaissaient pas, Multiboards est une simple page web qui affiche les flux rss de certains sites sélectionnés par nos soins. Après quelques années de service on s’est aperçu que pas mal de monde l’utilisait, on a même eu des suggestions d’améliorations (merci Nain Genieu) et des demandes de libération du code source.
Bon le code c’est pas pour tout de suite car il est super crade et que Sam acceptera jamais de laisser ça sans passer un bon coup de balais factoriseur XR-2200. Mais en attendant vous pouvez créer vos pages d’agrégation de flux persos et les partager avec le monde entier ou votre voisine de palier (celle qui a d’énormes nibards).

Pour créer son board on va sur http://multiboards.net/build et on ajoute ses flux RSS, on peut déplacer les flux dans la grille à sa convenance s’ils n’ont pas été rentrés dans le bon ordre. Lorsque l’on est satisfait avec sa page, on clique sur le bouton vert et on peut voir le mimi, le rara le miracle apparaître sous nos yeux ébahis !

mb_custo

Pour le moment vu que ça a été fait à l’arrache dans les chiottes de l’aéroport de Manille y a pas bcp de fonctionnalités marrantes mais lorsque le code sera libéré on espère avoir de jolies contribs ^^.

Quelques idées pour le futur:

  • Ajouter une alerte sur des mots-clef comme… “salope” (c’est important les mots-clef)
  • Lorsque une url a été lu l’indiquer sur la grille en lui attribuant une autre couleur
  • rajouter des radios ou des fonctionnalités au player
  • pouvoir customizer ses radios, les news de bas de page et pourquoi pas d’autres sources d’images à la place d’imgur
  • et plein d’autres choses qui ne devraient pas exister si nous étions dans un monde parfait.

NB:
Le player a été changé aussi, plus de flash et place au HTML5, un petit player maison hyper simple mais qui fait son job.

On attend vos retours, ça doit foisonner de bugs

]]>
http://sametmax.com/multiboards-est-desormais-customisable/feed/ 22
Aux couleurs du site 11 http://sametmax.com/aux-couleurs-du-site/ http://sametmax.com/aux-couleurs-du-site/#comments Wed, 22 Jul 2015 10:41:26 +0000 http://sametmax.com/?p=16645 multiboards.net Max et moi, et il a voulu ajouter un feature rigolote : les flux sont affichés avec une palette de couleur proche de celle du site. ]]> On est en train de tweaker un peu multiboards.net Max et moi, et il a voulu ajouter un feature rigolote : les flux sont affichés avec une palette de couleurs proche de celle du site.

Comme récupérer les couleurs d’un site est compliqué, on s’est rabattus sur les couleurs du favicon, qui en théorie doit résumer l’identité d’un site. Ce n’est pas parfait, mais c’est plus simple à implémenter.

Au début, on avait écrit une solution avec Pillow et numpy. Ça marchait très bien, mais des extensions compilées juste pour faire de la déco c’était un peu lourd, surtout si un jour on libère le code source (mais vu comme les sources sont dégueues et qu’on a pas de doc, pour le moment c’est pas gagné).

On a donc changé notre fusil d’épaule, et on a choisit une nouvelle technique : faire la moitié du taff côté client.

Récupérer le favicon côté serveur

On ne peut pas faire des requêtes cross domain en JS, donc on doit toujours récupérer l’image côté serveur. get_favicon_url() parse le site à coup de regex (c’est mal mais ça évite de rajouter BeautifulSoup en dépendance pour une balise) pour récupérer son URL sur la page donnée, ou à défaut, sur la page à la racine du site. On se donne plusieurs essais en cas d’erreurs de réseau :

 
import urllib
import urlparse 
 
def get_favicon_url(url, retry=3, try_home_page=True):
    """ Try to find a favicon url on the given page """
 
    parsed_url = urlparse.urlparse(url)
    url_root = "%s://%s" % (parsed_url.scheme, parsed_url.netloc)
 
    try:
        # try to get it using a regex on the current URL
        html = fetch_url(url, retry=retry)
        html = html.decode('ascii', errors='ignore')
        pattern = r"""
                               href=(?:"|')\s*
                               (?P<favicon>[^\s'"]*favicon.[a-zA-Z]{3,4})
                               \s*(?:"|')
                          """
 
        match = re.search(pattern, html, re.U|re.VERBOSE)
        favicon_url = match.groups()[0]
 
    except IOError:
        # this is a network error so eventually, let it crash
        if not try_home_page:
            raise
        # try with the home page, maybe this one is accessible
        favicon_url = get_favicon_url(url_root, retry=retry,
                                                       try_home_page=False)
    except (IndexError, AttributeError):
        # url is not on this page, try the home page
        if try_home_page:
            return get_favicon_url(url_root, retry=retry, try_home_page=False)
 
        # can't find the favicon url, default to standard url
        favicon_url = '/favicon.ico'
 
    # make sure to have the domain of the original website in the favicon url
    if url_root not in favicon_url:
        favicon_url = "%s/%s" % (url_root, favicon_url.lstrip('/'))
 
    return favicon_url
 
 
def fetch_favicon(url, retry=3):
    """ Returns the bytes of the favicon of this site """
    favicon_url = get_favicon_url(url, retry=retry)
    return fetch_url(favicon_url, retry=retry)

fetch_favicon() télécharge l’image proprement dite et retourne les bits tels quels. Notez que tout ça est synchrone et bloquant, mais heureusement le traffic de multiboards est sans doute trop faible pour poser problème.

Exposer le résultat au client

Ensuite il faut faire le lien entre le client et le serveur. On fait donc un petit routing (c’est du bottle) qui va retourner tout ça en base64 afin qu’on puisse l’utiliser directement dans un objet Image JS :

 
import base64
from bottle import post, HTTPError
 
@post('/favicon')
def fetch_favicon_base64():
    """ Return the favicon URL from a website """
    try:
        url = request.POST['url']
    except KeyError:
        raise HTTPError(400, "You must pass a site URL")
    try:
        # return favicon as base64 url to be easily included in
        # a img tag
        favicon = fetch_favicon(url)
        return b'data:image/x-icon;base64,' + base64.b64encode(favicon)
    except (IOError):
        raise HTTPError(400, "Unable to find any favicon URL")

Récupérer la palette côté client

Avec un peu d’AJAX sur notre vue, on récupère les bits de l’image, et on fout le tout dans un objet Image qu’on passe à la lib ColorThief. Cette dernière nous renvoie un array avec la palette. On convertit tout ça en code hexadécimal, et on diminue la luminosité de certaines couleurs pour rendre le texte plus lisible.

 $.post('/favicon', {url: url}).done(function(data){
 
        // load an image with the base64 data of the favicon
        var image = new Image;
        image.src = data;
        image.onload = function() {
 
            // ask ColorThief for the main favicon colors
            var colorThief = new ColorThief();
            var bc = colorThief.getPalette(image);
 
            // some tools to convert the RGB array into
            // rgb hex string
            function componentToHex(c) {
                var hex = c.toString(16);
                return hex.length == 1 ? "0" + hex : hex;
            }
 
            function rgbToHex(array) {
                return componentToHex(array[0]) + componentToHex(array[1]) + componentToHex(array[2]);
            }
 
            // make the color brigther
            function increase_brightness(hex, percent){
 
                // convert 3 char codes --> 6, e.g. `E0F` --> `EE00FF`
                if(hex.length == 3){
                    hex = hex.replace(/(.)/g, '$1$1');
                }
 
                var r = parseInt(hex.substr(0, 2), 16),
                    g = parseInt(hex.substr(2, 2), 16),
                    b = parseInt(hex.substr(4, 2), 16);
 
                return '' +
                   ((0|(1<<8) + r + (256 - r) * percent / 100).toString(16)).substr(1) +
                   ((0|(1<<8) + g + (256 - g) * percent / 100).toString(16)).substr(1) +
                   ((0|(1<<8) + b + (256 - b) * percent / 100).toString(16)).substr(1);
            }
 
            /* Define board colors */
            var header =  '#' + rgbToHex(bc[0]);
            var odd = '#' + increase_brightness(rgbToHex(bc[1]), 90);
            var even = '#' + increase_brightness(rgbToHex(bc[2]), 90);
 
});

Est-ce que la feature est utile ? Je ne sais pas, c’est un peu gadget, mais c’était marrant à faire, et c’est vrai qu’on identifie bien chaque site sur la page du coup.

L’idée ici est que le serveur et le client travaillent en équipe, et que grâce au navigateur on a une stack de traitement image/audio/video à portée de code. D’ailleurs on a viré le plugin flash des radios pour le remplacer par du chteumeuleu 5.

On peut imaginer la même chose avec tous les outils côtés en JS, ceci incluant les préprocesseurs et minifieurs JS ou CSS : pas besoin d’installer Node pour faire tourner tout ça, il suffit de déléguer le boulot à un tab du browser. Pour améliorer la stack, on pourrait par ailleurs utiliser du RPC avec WAMP et même prévenir le navigateur quand un fichier est prêt avec PUB/SUB afin qu’il le recharge. Vous avez vu comme j’arrive toujours à placer crossbar ?

J’ai un pote qui va venir dans quelques jours pour creuser cette idée qui permettrait d’avoir en pur Python une sorte de livereload sans extension, sans gros GUI, qui transpile tout et rafraichit tout avec un simple fichier de config. Peut être aurons nous le temps de faire un proto.

C’était l’inspiration du jour, passez une excellente canicule !

]]>
http://sametmax.com/aux-couleurs-du-site/feed/ 11
Multiboards a été migré 7 http://sametmax.com/multiboards-a-ete-migre/ http://sametmax.com/multiboards-a-ete-migre/#comments Fri, 26 Sep 2014 07:30:14 +0000 http://sametmax.com/?p=12242 multiboards.net, la page Web qu'on trempe dans son café, a été migrée.]]> multiboards.net, la page Web qu’on trempe dans son café, a été migrée. Comme il n’y a aucune donnée associée, ben, le truc n’a pas bougé, dont vous le retrouverez tel qu’avant.

Plusieurs personnes nous ont demandé le code source. La raison pour laquelle il n’est pas publié, c’est que c’est un amas de code vraiment peu ragoutant, et qu’il faudrait vraiment le nettoyer pour éviter que la honte ne s’abatte sur nous.

Max voudrait en faire un truc personnalisable, avec des widgets, et tout, à la netwibes mais en plus simple. Je pense que ça n’arrivera jamais :)

]]>
http://sametmax.com/multiboards-a-ete-migre/feed/ 7
Le meilleur de l’actu IT fr, le temps d’un café: le multiboards 25 http://sametmax.com/le-meilleur-de-lactu-it-le-temps-dun-cafe-le-multiboards/ http://sametmax.com/le-meilleur-de-lactu-it-le-temps-dun-cafe-le-multiboards/#comments Tue, 14 Aug 2012 19:49:10 +0000 http://sametmax.com/?p=1697 Dans son tuto sur bottle, Max vous disait qu’il avait concocté un exemple de ce qu’on peut faire rapidement avec cette lib.

Ainsi est né multiboards.net.

C’est très simple: il déteste les flux RSS, et veut juste rapidement avoir toutes les infos intéressantes sur l’actu informatique en buvant son kawa le matin, sans se fouler.

Le multiboards répond simplissimement à ce besoin en offrant sur une page qui s’auto refresh :

  • les actus des meilleurs blogs (sélectionnés par le dictateur Max) IT;
  • les actus des meilleurs sites généralistes IT;
  • les offres d’emplois IT en France, principalement Python;
  • des actus plus générales de Google news;
  • tout ça enrobé de conneries pour le lulz venant de imgur, bashfr et vdm;
  • et une radio intégrée dans le menu en haut qui vous diffuse de la zik si vous êtes d’humeur à cliquer dessus.
Capture d'écran du multiboards

Des articles, des news, de bêtises, en un coup d'oeil

C’est du bottle, donc du Python, et massivement du jQuery, avec un petit peut de Redis mais alors vraiment pour la couleur. Car en fait, quasiment tout se passe côté client et ne tape quasiment pas notre serveur. Très KISS.

Il n’y aura pas de version qu’on peut customiser par user, qui demande une registration ou quoique ce soit. Le multiboard, c’est ça, et juste ça.

Maintenant chers amis, il va falloir tous spammer de commentaires ce post pour motiver l’auteur afin qu’il mette le code source sous licence libre. Parceque c’est une feignasse, le Max, je vous le rappelle, et que ça voudrait dire qu’il devrait écrire une doc et nettoyer le random.randint() qu’il a mis pour le compteur de visiteurs.

Ah oui, on a rajouté le lien dans le menu.

 

]]>
http://sametmax.com/le-meilleur-de-lactu-it-le-temps-dun-cafe-le-multiboards/feed/ 25