Skip to main content

Stumbling upon your article probably saved me a lot of frustration since I was trying to do the exact same thing today.

Since a year and a half has passed since you wrote this, i wonder if you did find another solution to automatically post bookmarks to your Known website? Maybe something based on microformats?





@mobilevikingsBE Après relecture j'ai l'impression que vous avez seulement vu mon tweet et pas l'article de blog qui l'accompagnait. A toutes fins utiles, le voici : https://cedric.io/2019/passer-une-journ%C3%A9e-en-suisse-se-faire-d%C3%A9pouiller-de-300

Passer une journée en Suisse & se faire dépouiller de 300€ par @mobilevikingsBE et @proximus

7 min read

Début juillet, je suis parti quelques jours en vacances du côté de lac de Constance. Puisqu'on était à un jet de pierre de la Suisse, nous avions décidé d'aller passer une journée à Zurich. L'idée semblait bonne, sauf que Mobile Viking et Proximus nous ont conjointement dépouillé de presque 300€ pour quelques malheureux méga de data.

Constance est située sur la frontière entre l'Allemagne et la Suisse. Au départ de l'hôtel, je lance Waze et Spotify comme a mon habitude, et nous nous mettons en routes. A peine avais-je traversé la frontière que mon écran s'allume sur un SMS reçu :

"Infos Mobile Vikings: A propos de votre abonnement : ce mois-ci, vous avez déjà utilisé EUR 2,97 hors forfait. Ces couts seront disponibles sur votre prochain(e) relevé de compte."

Oups, my bad, j'avais oublié qu'en entrant en Suisse je sortais de l'Union Européenne. 2.97€ me semble être un montant un peu exagéré, mais je ne sais pas depuis combien de temps mon téléphone a basculé sur le réseau suisse et, après tout, j'ai Waze et Spotify qui tournent. Rapide comme un ninja, je scroll vers le bas et passe en mode avion. Ouf, le pire a été évité.

Arrivé a Zurich, nous discutons de la situation : dans l'autre voiture, ma belle-mère a eu le même soucis avec son opérateur (Proximus), a l'exception que celle-ci a reçu un SMS l'informant que le montant de ses dépenses avait atteint 60€ et que, en conséquence, Proximus bloquait son accès data depuis l'étranger pour éviter de mauvaise surprise (comme si 60€ pour quelques minutes d'utilisation n'était pas déjà une mauvaise surprise en soit). Vu l'infortune de ma belle-mère, je me considère encore chanceux avec mes trois petits euros de dépenses hors-forfait. Oui, mais non.

Arrivés à la gare de Zurich, je veux me connecter au Wi-Fi gratuit afin de trouver quelques informations sur les environs. Bien mal m'en a pris : pour activer le réseaux Wi-Fi, il faut désactiver le mode avion de l’appareil, ce qui déclenche quasi immédiatement le débarquement des cavaliers de l'apocalypse :

Quatre SMS de Mobile Viking, reçus dans un ordre apparemment aléatoire, précisant que mes dépenses s'élèvent respectivement à 48€, puis 49.99€. Finalement non, 32.22€. Ou bien peut-être seulement 13.65€?

Mais ce n'est pas bien grave, on m'informe dans le premier SMS que mes données mobiles hors forfait seront bloquées quand j'atteindrais 60€ de dépenses ✌️

Deuxième victime de la journée, je prend à mon tour 60€ de dépenses dans les dents. Perplexe, je consulte en vitesse l'application "My Viking" pour essayer de comprendre ce qu'il s'est passé :

3Mb (ou plus exactement 3123kb) consommés pour un total de 49.99€. Y en a un peu plus, je vous le met quand même?

Au cours de la journée, mon épouse, sa sœur, et son père, recevront également le même genre de SMS (bien tard par rapport à la consommation puisque nous avions tous passé nos appareils en mode avion après les premiers indices).

Total des dépenses téléphoniques de la journée :

  • Proximus : 4x60€ = 240€
  • Mobile Viking : 60€

Plus tard, je recevrais même un dernier SMS m'informant des tarifs en application hors UE. Dommage, un peu trop tard.

Informer ses clients des tarifs en application après leur avoir vidé les poches, c'est toujours très classe.

J'entend déjà d'ici certain d'entre vous crier au scandale, que je tente de mettre les deux opérateurs au pilori, et qu'il s'agit d'un minable procès d'intention : je savais que je sortais de l'UE et que des tarifs moins avantageux allaient être d'application. Oui, j'ai merdé, j'ai complètement oublié ce détail et, passant régulièrement les frontières françaises et luxembourgeoises, il y a bien longtemps que ça ne m'avait plus tracassé.

Je soulève simplement ici les points suivants :

  • Les informations concernant les tarifs en application sont arrivé très tard (trop tard a vrai dire puisque mon accès avait déjà été bloqué)
  • Le prix au méga est parfaitement ridicule : 13€. Je répète : treize euros! Pour un minuscule méga de donnée. Vous savez ce que vous faites avec 1Mb? Rien. Télécharger une minute de chanson sur Spotify, tout au plus. C'est un prix ridiculement élevé pour une quantité si petite d'information. Dans le tas je me demande qui se taille la plus grosse part du gâteau : les réseaux belges ou suisses? J'ai bien ma petite idée sur la question mais sans preuve j'éviterais de la partager.
  • Que ça soit Proximus ou Mobile Viking : tout deux nous prouvent qu'ils ont la capacité technique de bloquer cet accès hors-UE (pour nous éviter de grosses dépenses par inadvertance), cependant, ils choisissent sciemment de ne bloquer le client qu'une fois 60€ de dépenses atteintes. Cela ressemble plus à une taxe pour les distraits qu'à une réelle inquiétude que le client ne dépense trop, ils connaissent le prix au méga et sont parfaitement conscient qu'on ne peut rien faire avec à peine 4.6Mb (60/13). En quelques secondes a peine, le quota est remplit, et leurs poches aussi.

    Ce comportement ne m'étonne pas de la part de Proximus, qui n'a jamais cherché a passer pour le plus éthique des opérateurs; par contre, il m’écœure totalement de la part de Mobile Viking, dont l'image tend a vouloir faire croire qu'ils sont du côté du client (en proposant des offres pay-as-you-go, pay-what-you-need à l'inverse des opérateurs qui tentent de vous saucissonner à votre contrat pour 24 ou 48 mois). Cette pratique tend a prouver qu'il s'agit la d'une campagne marketing et pas d'un réel soucis du client.

Que ma mésaventure vous serve de leçon : faite gaffe si vous sortez de l'UE cet été.

Cet article a été partagé sur les communautés Reddit r/Wallonia et r/belgium ainsi que sur Twitter.

Edit: [16:48] après quelques échanges sur Twitter avec Mobile Viking, on me confirme qu'un dossier a été ouvert pour "contrôler la situation et (de) voir si il y a une possibilité d'annuler ces coûts supplémentaires dans ce cas-ci".

Edit: [31/07] on me signale que déshormais, Mobile Viking désactive l'accès aux data en dehors de l'UE par défaut. Le geste mérite d'être signalé, au moins plus personne ne se fera avoir par erreur.

How to install Solargraph with Sublime Text LSP

1 min read

Solargraph is a Ruby Language Server. It's meant to add code completion and inline documentation onto IDEs.

We have to install the gem first

gem install solargraph

Within Sublime Text Control Panel (CTRL+Shift+P) :

  1. Find Package Control: Install Package
  2. Then LSP
  3. Hit enter

By default, the ST plugin will look for rvm, not rbenv. We have to force the settings Preferences > Package Settings > LSP > Settings, and paste this :

https://gist.github.com/cedricbousmanne/099bccef4472912aba61545d0c31d5ec

Note : you need to adjust the value of the path on line 8. You can find the exact installation path of solargraph on your system with the following command

which solargraph

Finally we can enable the server via the Sublime Text Control Panel (CTRL+Shift+P)

6W7tjXLl.png

Ton premier jour d'école

3 min read

C'était ton premier jour d'école, aujourd'hui. Je n'aurais manqué ça pour rien au monde.

J'ai mal dormi cette nuit, remplis de doutes, d'incertitudes et de questions. Jusqu'à présent, nous t'avions gardé rien que pour nous, et désormais, tu aurais ta propre petite vie, en dehors de la maison. J'ai passé une bonne partie de la nuit à me demander si nous t'avions bien préparé.

Tu t'es réveillé de bonne humeur ce matin, tu as pris ton lait, tes céréales, et regardé un épisode des Pyjamasques. Je t'ai encore expliqué ce qui allait se passer, ta maman aussi. Je n'étais pas tout à fait sûr que tu comprenais bien toutes les implications que ça avait, mais tu es resté stoïque.

Quand l'heure de partir est arrivée, je n'en menais pas large. Toi par contre, tu as été brave. Très brave. Bien plus que je ne pouvais l'être. Dans la voiture, tu m'as demandé la vraie chanson. Tu parlais bien sûr de Californication. La vraie chanson, pas la berceuse que je te fais écouter le soir avant de dormir.

Nous sommes arrivés à l'école, ton petit cartable sur le dos, tu as traversé la cours en regardant tout autour de toi. Calme et silencieux, comme souvent, tu te contentais d'observer ce qui t'entourait. A l'intérieur, nous t'avons montré ton porte-manteau, ton prénom y était écrit à côté d'un dessin de petite voiture. Tu as déposé tes affaires avant de me montrer la petite cuisine, dans le couloir.

Enfin nous sommes entrés en classe. Tu as déposé ta collation et ta gourde dans le tiroir à ton nom, puis tu t'es précipité vers le garage des petites voitures. Tu étais à la fête : plein de jouets dans une salle remplie d'enfants. Intérieurement, je fondais en larmes de voir mon petit bonhomme devenir un grand, mais il ne fallait rien laisser transparaître.

Alors je me suis tu. Je t'ai souris, je me suis accroupi pour regarder de plus près le jouet que tu me montrais. Quand vint l'heure de partir, maman t'as expliqué que nous te laissions là, jouer avec tes nouveaux amis, mais qu'elle viendrait te rechercher un peu plus tard. Tu as hoché la tête, en disant "oui". Tu nous a pris dans tes bras, fait un bisou, puis tu t'es dirigé vers la fenêtre pour nous faire "coucou".

Nous nous sommes éloignés sans pour autant quitter l'école tout de suite. Je t'ai vu revenir à la fenêtre quelques minutes plus tard. Tu as regardé un petit moment, puis, ne nous voyant pas, tu es retourné dans l'espace de jeu.

C'était un moment dur pour ta maman et moi, mais bien heureusement, il a semblé bien plus facile pour toi. J'ai hâte de rentrer à la maison, ce soir, et de t'entendre me raconter ta journée.

 

How to install Rubocop for Sublime Text with rbenv

1 min read

Rubocop is a static code analyzer and formatter for Ruby. Long story short : it helps you to write better code.

Installing it pretty straight-forward :

gem install rubocop

Within Sublime Text Control Panel (CTRL+Shift+P) :

  1. Find Package Control: Install Package
  2. Then Rubocop (currently v2018.12.05.18.01.20)
  3. Hit enter

By default, the ST plugin will look for rvm, not rbenv. We have to force the settings Preferences > Package Settings > Rubocop > Settings - Users, and paste this :

https://gist.github.com/cedricbousmanne/2c89bf83de175f6fa6fe8dea9b7724b7

Now we can have a list of the available options by typing rubocop withing the Control Panel (CTRL+Shift+P).

RVV9n3B.png

Noah, 3 ans, devant sa bibliothèque, choisis son livre du soir :

- Papa, on a pas le livre Tar Wars? <p>#article </p>

Accélérer l'exécution de la commande bundle et l'installation des gems

2 min read

Il y a quelques jours, j'ai travaillé sur une mise à jour majeure d'une application écrite en Ruby on Rails. L'application tournait sur la version 3.2 du framework, et celle-ci étant dépréciée depuis longtemps, il était largement temps de la faire passer en version 5.2.

Cela signifie donc deux passages de versions majeures et 4 passages de versions mineures. Avec, pour chaque saut de version, la nécessité de mettre à jour les versions des gems utilisées. Autant dire que la commande bundle a été sollicitée.

Le point de frustration était l'approche itérative de bundle (la première dépendance est vérifiée et mise à jour, puis on passe à la seconde, etc) dans un fichier qui comptait pas moins de 137 dépendances. Ce qui m'a poussé à fouiller la documentation de bundle pour y découvrir l'option --jobs qui permet de définir un nombre de processus concurrentiels.

Pour lancer 4 jobs en parallèle, on peut donc lancer la commande comme ceci :

bundle install --jobs=4

Il est également possible de définir cette configuration par défaut pour ne plus avoir à s'en soucier à l'avenir :

bundle config --global jobs 4

En bonus, on peut également demander à ne plus installer les documentations par défaut (soyons francs, tout le monde va chercher la documentation sur Internet, il est inutile d'avoir une version locale). Pour ce faire, il est nécessaire de créer un fichier ~/.gemrc et d'y inclure :

gem: --no-rdoc --no-ri

Mutt + ProtonMail

4 min read

Il y a maintenant plusieurs semaines que j'utilise ProtonMail. Bien que rassembler mes 7 adresses précédentes sur une seule m'a grandement simplifié la vie, je ne suis toujours pas satisfait des clients disponibles. Sous Linux, seul Thunderbird est actuellement disponible, à moins d'utiliser de webmail - ce que je fais pour l'instant.

Il y a quelques années, j'avais testé Mutt un peu comme un jeu. La raison pour laquelle j'avais arrêté de l'utiliser était justement le nombre d'adresse que je devais gérer : l'outil était certes intéressant, mais difficile à utiliser avec autant de compte.

Maintenant que j'ai résolu ce problème, j'avais envie de redonner une chance à ce client minimaliste et, par la même occasion, voir s'il était possible de faire cohabiter Mutt et ProtonMail.

Installation et premier lancement

Pour installer mutt, il suffit d'installer le paquet du même nom :

sudo apt install mutt

En lancant pour la première fois la commande mutt, je reçois une erreur :

/var/mail/cedric: Aucun fichier ou dossier de ce type (errno = 2)

Je crée le fichier en question et je lui donne les permissions nécessaire à mon utilisateur :

sudo mkdir -p /var/mail/$(whoami)
sudo chown $(whoami):$(whoami) /var/mail/$(whoami)

J'en profite pour initialiser le fichier de configuration .muttrc

vim ~/.muttrc
set realname = "Your Name"
set header_cache =~/.mutt/cache/headers
set certificate_file =~/.mutt/certificates
set message_cachedir =~/.mutt/cache/bodies

Lancer une nouvelle fois la commande mutt, ne donne plus d'erreur.

[caption id="attachment_4409" align="alignnone" width="1024"] Premier écran du logiciel Mutt - un client mail en ligne de commande. Au moins, c'est épuré :-)[/caption]

Configuration de mutt

Note : je pars du principe que le Bridge pour Linux est installé et lancé.

J'ajoute au fichier de configuration .muttrc les lignes suivantes:

# "+" substitutes for `folder`
set mbox_type=Maildir
set folder=/var/mail/cedric/
set spoolfile=+INBOX
set record=+Sent
set postponed=+Drafts
set trash=+Trash
set mail_check=2 # seconds

# smtp
source ~/docs/keys/mail
set smtp_url=smtp://$my_user:$my_pass@127.0.0.1:1025
set ssl_force_tls
set ssl_starttls

Et dans le fichier ~/docs/keys/mail:

set my_user=EMAIL
set my_pass=MOT_DE_PASSE_DU_BRIDGE

Installation et configuration de OfflineIMAP

J'installe OfflineIMAP :

sudo pip install offlineimap

Puis je crée un fichier de configuration .offlineimaprc :

[general]
accounts = main

[Account main]
localrepository = main-local
remoterepository = main-remote

# full refresh, in min
autorefresh = 0.2

# quick refreshs between each full refresh
quick = 10

# update notmuch index after sync
postsynchook = notmuch new


[Repository main-local]
type = Maildir
localfolders = /var/mail/cedric

# delete remote mails that were deleted locally
sync_deletes = yes


[Repository main-remote]
type = IMAP
remoteport = 1143
remotehost = 127.0.0.1
remoteuser = EMAIL
remotepass = MOT_DE_PASSE_DU_BRIDGE
keepalive = 60
holdconnectionopen = yes

# delete local mails that were deleted on the remote server
expunge = yes

# sync only these folders
folderfilter = lambda foldername: foldername in ['INBOX', 'Archive', 'Sent']

# is broken, but connecting locally to bridge so should be ok
ssl = no

On lance la commande offlineimap, et, si tout s'est bien passé, on peut commencer à voir la progression de la synchronisation avec ProtonMail :

OfflineIMAP 7.2.1
  Licensed under the GNU GPL v2 or any later version (with an OpenSSL exception)
imaplib2 v2.57 (bundled), Python v2.7.14, OpenSSL 1.0.2g  1 Mar 2016
Account sync main:
 *** Processing account main
 Establishing connection to 127.0.0.1:1143 (main-remote)
 Creating folder INBOX[main-local]
 Creating new Local Status db for main-local:INBOX
 Creating folder Archive[main-local]
 Creating new Local Status db for main-local:Archive
 Creating folder Sent[main-local]
 Creating new Local Status db for main-local:Sent
Folder Archive [acc: main]:
 Syncing Archive: IMAP -> Maildir
Folder INBOX [acc: main]:
 Syncing INBOX: IMAP -> Maildir
Folder Archive [acc: main]:
 Copy message UID 1 (1/263) main-remote:Archive -> main-local:Archive
Folder INBOX [acc: main]:
 Copy message UID 1 (1/49) main-remote:INBOX -> main-local:INBOX
Folder Archive [acc: main]:
 Copy message UID 2 (2/263) main-remote:Archive -> main-local:Archive
Folder INBOX [acc: main]:
 Copy message UID 2 (2/49) main-remote:INBOX -> main-local:INBOX

Il ne reste plus maintenant qu'à relancer la commande mutt pour visualiser ses mails.

[caption id="attachment_4413" align="alignnone" width="1024"]Mutt est maintenant configuré pour fonctionner avec ProtonMail L'interface de Mutt une fois la configuration terminée[/caption]

Identifier une régression grâce à git-bisect

3 min read

Enfer et damnation, vous venez de constater un bug dans votre code. Évidemment, il est difficile de savoir à quel moment cette régression est apparue et en trouver l'origine pourrait nous permettre de comprendre et donc de résoudre le bug.

Heureusement, git-bisect vient à votre secours, pour peu de savoir l'utiliser.

On commence donc par signifier à git que nous sommes dans un état "mauvais" du code :

git bisect bad

Vous devez démarrer avec "git bisect start"
Souhaitez-vous que je le fasse pour vous [Y/n] ? y

Il faut maintenant remonter suffisamment longtemps dans l'historique dans l'objectif de trouver l'état du code ou la régression constatée n'existait pas. Un petit git log devrait suffire à identifier le commit-id correspondant.

git checkout <commit-id>

Après avoir vérifié que la régression n'existait pas dans cet état du code, on signifie à git-bisect qu'on a une sous la main une version du code correcte.

git bisect good
Bissection : 132 révisions à tester après cette (à peu près 7 étapes)
[<commit-id>] <commit-message>

En retour, git-bisect nous donne le nombre de révisions à tester (ici : 132), et le nombre d'étapes estimées avant d'obtenir le nom du coupable (ici : 7). Enfin, git-bisect à effectué un checkout automatique sur un autre <commit-id> et attend vos instructions.

Il ne reste qu'a tester le code et à donner comme instruction soit un git bisect good, soit un git bisect bad en fonction du résultat observé. L'opération sera plus ou moins longue en fonction du nombre de commits à tester.

➜  webapp git:(6ae90d246) git bisect good
Bissection : 132 révisions à tester après cette (à peu près 7 étapes)
[49cbe40d5cb63b9f2a036560190983b2848d6df0] Merge branch 'master' into deploy/staging
➜  webapp git:(49cbe40d5) ✗ git bisect good
Bissection : 66 révisions à tester après cette (à peu près 6 étapes)
[dc9c093633ca9af720ae560b01ff455d4bd4fb51] <commit-message>
➜  webapp git:(dc9c09363) ✗ git bisect good
Bissection : 33 révisions à tester après cette (à peu près 5 étapes)
[4f8b4fd5f7ecb71141510823e89f3d941f6d892b] <commit-message>
➜  webapp git:(4f8b4fd5f) git bisect bad
Bissection : 16 révisions à tester après cette (à peu près 4 étapes)
[0e5acfb262de5f692f8383cd51fe5c4bed729b92] <commit-message>
➜  webapp git:(0e5acfb26) git bisect good
Bissection : 7 révisions à tester après cette (à peu près 3 étapes)
[7623848ffee8d72429623e3b5fb8fb1a8040aeed] <commit-message>
➜  webapp git:(7623848ff) ✗ git bisect good
Bissection : 4 révisions à tester après cette (à peu près 2 étapes)
[50f6b9ebf42ff5cda83d33d4489e944829f87c56] <commit-message>
➜  webapp git:(50f6b9ebf) ✗ git bisect good
Bissection : 2 révisions à tester après cette (à peu près 1 étape)
[d763c0336e13cbc91befbe853194dd077775e6cd] <commit-message>
➜  webapp git:(d763c0336) git bisect good
Bissection : 0 révision à tester après cette (à peu près 1 étape)
[c1af98fc24e031d0d87a567caa7615c0c2c3d66c] <commit-message>
➜  webapp git:(c1af98fc2) git bisect bad
Bissection : 0 révision à tester après cette (à peu près 0 étape)
[026f9bf37555815c0efc9dfb16e90473faacf48f] <commit-message>

Une fois la dernière étape passé, git-bisect vous donne l'identité du coupable :

git bisect bad
026f9bf37555815c0efc9dfb16e90473faacf48f is the first bad commit

Pour terminer, nous pouvons revenir à l'état initial du code (HEAD)

git bisect reset