De la cybersécurité (I’m back. Stronger.)

Enfin j’ai trouvé un peu de temps pour réparer tout mon bourbier.

En effet, depuis 2024, quand on accédait à mes sites wordpress, vous aviez ce message d’accueil fort charmant qui mentionnait un « incident technique ». J’avais dû fermer mes trois sites wordpress …

Pas des moindres. J’avais été piratée de partout ! Mon site d’urbex par exemple redirigeait vers une boutique en ligne. Et paf la cascade, mon site vitrine, mon blog et même un temps mon wiki sur mon jeu Minerland ! Un peu comme un jeu de dominos qu’on fait tomber petit à petit … de quoi être parano.

Il aura fallu attendre 2024 pour que ça se produise, en sachant que mes premiers sites perso remontent à 2000. Depuis, je me disais, tranquille, que je n’avais pas de raisons de me méfier ni de consolider mes iptables bien comme il le faut … voire faire l’impasse sur les mises à jour. L’erreur fatale. La cybersécurité est devenue lame de plus du développeur web qui doit apprendre de ses erreurs.

Intro sur la cybersécurité

En 2026, les petits sites web sont plus que jamais en première ligne.

Les attaques les plus courantes contre les petits sites sont silencieuses, opportunistes et automatisées. Elles défigurent un site, volent des données clients, ou utilisent le serveur pour héberger des contenus illicites, le tout à l’insu du propriétaire.

La grande nouveauté de 2026, c’est l’utilisation de l’IA par les attaquants. Les agents IA autonomes deviennent des outils courants de la cybercriminalité, capables de cartographier une attaque en quelques minutes et de générer des campagnes de phishing ciblées à grande échelle. Les campagnes de phishing générées par IA sont désormais quasiment indétectables — fini les fautes d’orthographe et les formulations bancales.

Plus de 90 % des piratages de sites WordPress exploitent des failles déjà corrigées dans une mise à jour que l’administrateur n’a pas appliquée. Le message est clair : mettre à jour, sécuriser ses accès, surveiller ses logs — ce n’est plus optionnel, même pour un petit blog perso.

Acte I — La découverte

Tout a commencé par un constat simple : mes sites WordPress ne répondaient plus correctement. En fouillant, j’ai découvert l’ampleur des dégâts. Les attaquants avaient réussi à s’introduire dans mes trois sites WordPress et ils s’étaient fait plaisir.

Leur spécialité : injecter du contenu. Des pages de spam, du phishing, et le pompon — un site de commerce en ligne complet, hébergé à mes frais sur mon propre serveur. Sympa.

En analysant les bases de données, j’ai retrouvé leurs traces partout. Dans la base d’amelieonline.net, un webshell — un script PHP qui permet de prendre le contrôle d’un serveur à distance — était planqué dans le fichier functions.php du thème. Du code obfusqué en base64 qui se connectait à des serveurs distants pour exécuter des commandes. Le plugin de sécurité All-In-One Security l’avait détecté et mis en quarantaine, mais le mal était fait.

Dans les fichiers du serveur, les bots avaient déposé des scripts PHP aux noms discrets : x.php, ha.php, gg.php… Des portes dérobées qui leur permettaient de revenir à volonté, même après un changement de mot de passe.

Acte II — Comment ils sont rentrés

La réponse est aussi simple que gênante : mon mot de passe wordpress était devenu trop faible. Ou alors ils se sont fait une joie de l’absence de certificat ssl …

Les bots qui parcourent internet 24h/24 testent des millions de combinaisons sur /wp-login.php et xmlrpc.php (une porte d’entrée WordPress souvent oubliée). Avec un mot de passe simple, il leur faut parfois quelques heures pour entrer.

Mais ce n’est pas tout. Mon serveur cumulait les facteurs aggravants. Ubuntu 18.04 en fin de vie depuis avril 2023, donc plus aucun correctif de sécurité. PHP 7.x, qui n’est plus maintenu depuis fin 2022. Pas de HTTPS — ce qui signifie que chaque fois que je me connectais à l’admin WordPress, mon identifiant et mon mot de passe transitaient en clair sur le réseau. Dans un café, à la gare, à l’hôtel, n’importe qui sur le même Wi-Fi pouvait les intercepter avec un simple outil comme Wireshark.

Et mon certificat SSL ? Expiré depuis des mois. J’avais payé cher pour un certificat classique, il avait expiré, et je n’avais jamais pris le temps de le renouveler. J’étais persuadée qu’il fallait racheter un certificat pour chaque nom de domaine. Trois domaines, trois certificats, une facture qui pique. En fait, non — mais j’y reviendrai.

Acte III — Le grand nettoyage

Le ménage a été méthodique. D’abord, les bases de données : analyser chaque dump SQL à la recherche de contenu injecté — du spam en chinois, en japonais, en cyrillique, des liens vers des boutiques frauduleuses, des webshells en quarantaine. Chaque site a été passé au peigne fin, table par table.

Ensuite, les fichiers du serveur : traquer les scripts PHP malveillants dans les répertoires d’uploads (il ne devrait jamais y avoir de fichier PHP dans wp-content/uploads/), vérifier chaque thème, chaque plugin, identifier les fichiers modifiés récemment.

Et puis la grosse opération : migrer le serveur d’Ubuntu 18.04 vers une version maintenue. Trois sauts successifs — 18.04 vers 20.04, puis 22.04 — chacun avec son lot de surprises. PHP 7 vers PHP 8 a cassé plusieurs choses : des fonctions dépréciées, des syntaxes devenues invalides, des conflits de configuration entre l’ancien PHP-FPM et le nouveau module. À chaque étape, un site qui tombe, un diagnostic, une correction, on repart.

Acte IV — L’horreur des logs

C’est une fois le serveur remis d’aplomb que j’ai vraiment mesuré l’ampleur du problème. En regardant les logs d’authentification SSH :

Failed password for root from 179.111.150.107
Failed password for invalid user adurbex from 172.188.89.41
Failed password for invalid user amelayesbiophp from 59.51.98.254
Failed password for invalid user urbexmarseille from 187.191.48.4
Failed password for invalid user tonwebautableau from 121.78.158.30

Des dizaines de tentatives par heure. Et le plus flippant : les bots n’essayaient pas que des noms génériques comme « admin » ou « root ». Ils testaient adurbex, urbexmarseille, amelayesbiophp etc … — des identifiants dérivés de mes noms de domaines, de mon pseudo, de mes projets.

Quelqu’un — ou plutôt quelque chose — avait scanné mes sites, relevé tous les indices disponibles. Les noms d’auteur WordPress sont exposés par défaut via /?author=1 ou l’API REST (/wp-json/wp/v2/users). Les pages « à propos », les footers, les noms de domaine eux-mêmes : tout est découpé, recombiné, et testé automatiquement.

Les logs Apache racontaient la même histoire côté web : des scans massifs de wlwmanifest.xml (un fichier WordPress utilisé pour détecter les installations), des rafales de requêtes cherchant des webshells PHP à des noms comme x.php, ha.php, gg.php… Un bot a généré des dizaines de 404 en quelques millisecondes, balayant méthodiquement tous les noms de fichiers suspects.

En analysant les adresses IP, un inventaire géographique impressionnant : Brésil, Bulgarie, Chine, Corée du Sud, Russie, Vietnam, Pays-Bas, Ukraine, Singapour, Afrique du Sud… La plupart provenaient de datacenters ou de services cloud comme Microsoft Azure ou Alibaba Cloud. Et l’ironie : l’une des IP attaquantes appartenait à un serveur Kimsufi OVH — un serveur dédié comme le mien, probablement compromis et utilisé comme relais.

Ce ne sont pas de vrais humains derrière un écran. Ce sont des botnets — des réseaux de milliers de machines compromises qui scannent automatiquement toutes les IP du monde, 24 heures sur 24.

Acte V — Pourquoi mon petit serveur ?

C’est la question que je me suis posée. Mes sites ne contiennent rien de sensible. Mais ce n’est pas mes données qui intéressent les attaquants. C’est mon serveur lui-même : sa bande passante pour lancer des attaques vers d’autres cibles ou participer à des attaques DDoS, son processeur pour miner de la cryptomonnaie, son adresse IP pour héberger du phishing ou envoyer des millions de spams, et le fait qu’il tourne 24h/24 en faisant office d’outil gratuit.

Un serveur dédié compromis devient un soldat anonyme dans une armée de machines zombies. Et quand quelqu’un remonte la piste d’une attaque, c’est sur mon Kimsufi qu’il tombe — pas sur le vrai attaquant.

Acte VI — La fortification

La reconstruction s’est faite couche par couche.

Fail2ban, valeur sûre. J’avais fail2ban d’installé, mais sa configuration par défaut était une passoire : 10 minutes de bannissement après 5 échecs. Les bots attendaient tranquillement et revenaient. 4681 tentatives échouées au compteur, 491 IP bannies au total, mais zéro bannie à l’instant T. J’ai durci la config : 3 échecs en une heure, et c’est 24 heures de ban.

Mais le SSH n’était pas le seul front. J’ai ajouté des jails fail2ban pour chaque type d’attaque : les scans WordPress (wlwmanifest), les floods de 404 génériques, les tentatives de brute force sur DokuWiki, les scans de fichiers sensibles. Six jails au total, chacune avec ses propres seuils. Le port 22 quant à lui, exit !

Iptables pour les récidivistes. Pour les IP les plus agressives — celles avec 60, 80, 90 tentatives au compteur — j’ai écrit un script qui les bloque définitivement dans iptables. Ces adresses ne peuvent plus du tout communiquer avec mon serveur, sur aucun port, par aucun protocole.

CrowdSec, la défense collaborative. En plus de fail2ban, j’ai installé CrowdSec — un outil communautaire où les serveurs partagent les IP malveillantes. Quand une IP attaque un serveur du réseau, elle est signalée et bloquée sur tous les autres.

HTTPS avec Let’s Encrypt. Fini les certificats payants. Certbot et Let’s Encrypt m’ont permis de sécuriser mes trois domaines en une seule commande, gratuitement, avec renouvellement automatique tous les 90 jours. Plus jamais de certificat expiré oublié dans un coin. Un timer systemd vérifie deux fois par jour si un renouvellement est nécessaire.

Le blocage de xmlrpc.php. Ce fichier WordPress est un vecteur classique de brute force. Bloqué.

Les permissions qui vont bien. 644 pour les fichiers, 755 pour wp-content.

La mise à jour de tout. Ubuntu à jour, PHP à jour, WordPress core à jour, plugins à jour, thèmes à jour. Chaque composant obsolète est une porte ouverte.

Ce que j’ai appris

Cette aventure m’a enseigné des leçons que j’aurais aimé connaître plus tôt.

Un mot de passe faible est une porte ouverte. C’est banal à dire, mais c’est la cause numéro un des compromissions WordPress. Aujourd’hui, 20 caractères minimum, générés aléatoirement, et uniques pour chaque site.

Le HTTPS n’est pas optionnel. Même pour un blog perso, chaque page de connexion sans HTTPS est une invitation au vol d’identifiants. Et avec Let’s Encrypt, il n’y a plus aucune excuse financière.

La sécurité par défaut n’existe pas. Fail2ban installé avec sa config d’usine, c’est presque comme s’il n’était pas là. Il faut prendre le temps de configurer chaque outil correctement.

Tout serveur exposé sur internet est une cible. Ce n’est pas une question de « si », mais de « quand ». Les bots ne dorment jamais, et ils sont plus malins qu’on ne le croit — ils analysent vos sites pour en extraire des identifiants potentiels. Les premières tentatives de brute force arrivent dans les minutes qui suivent la mise en ligne d’un serveur.

Un système non maintenu est un système compromis. Ubuntu 18.04 en fin de vie + PHP 7 abandonné = zéro correctif de sécurité depuis des mois. Autant laisser la porte grande ouverte.

Vérifiez vos logs régulièrement. Sans cette habitude, je n’aurais jamais su que mon serveur subissait des milliers de tentatives d’intrusion quotidiennes.

Rien ne dure.

Ces mots martèlent sans arrêt mon crâne, rien ne dure, personne n’est irremplaçable. Mon meilleur ami en est l’auteur original, voulant nous rassurer que la vie en était ainsi, tourmentée de rivières agitées, et que ces eaux se renouvellent sans arrêt.

Un samedi comme un autre, ma mère et ma sœur sont chez moi, nous savourons l’instant présent autour d’un apéritif, étais-je loin de me douter que la Grande Horloge tournait ? Elle tourne, tourne inlassablement, parfois d’une lenteur accablante, parfois d’une rapidité déconcertante. Et à ce moment, là, je n’entendais pas ce tic-tac effroyable. Un tic-tac qui allait bientôt s’arrêter pour quelqu’un.

Ces dernières années, j’ai vu beaucoup de gens partir, des horloges arrêtées, des amis, de la famille, des connaissances, beaucoup trop de départs qui vous mettent au pied du mur.

Rien ne dure.

Nous naissons, nous grandissons, nous évoluons, nous réussissons, nous échouons, nous vieillissons, nous mûrissons, nous expérimentons ce grand manège qu’est la Vie. Nous la chérissons, cette vie, parfois nous la maudissons. Nous nous exerçons à la chasse au Temps, ne voulant pas écouter les aiguilles qui parfois sont trop bruyantes ou trop silencieuses.

Parfois, nous profitons de l’Instant Présent, nous plaisantons, sommes dans la douceur d’un moment joyeux, et puis, d’une seconde à l’autre tout change. Une pause dans ma bulle, un SMS, la violence d’un message qui vous gifle comme jamais, et vous laisse KO, en état de choc. Appuyée contre le mur, les jambes coupées, assise par terre, appelant la clinique. Le cerveau ne répondant plus, le choc coupant les connexions du cerveau limbique.

Mon père venait de décéder.

Un état de non-retour, un état inaliénable, intransigeant, irrévocable. Le temps détruit tout. Rien ne sera plus comme avant. Pourtant, connaissant son âge, je commençais à me préparer à l’inéluctable. Mais en vérité, nous ne sommes jamais prêts.

Rien ne dure. Mais certaines personnes sont irremplaçables. Un parent, on en a qu’un dans la Vie. Parfois, en tant qu’enfant, on le chérit, on le maudit, on aurait volontiers échangé des places, je ne vais pas approfondir cette partie personnelle, le reste nous appartient à lui et moi. Mais on n’a qu’un père, tel qu’il est.

On se retrouve dans un torrent d’émotions, un cheminement du Deuil, ce Styx à traverser, et que je connaissais déjà … le choc, le déni, la colère, la dépression, l’acceptation, tout cela décuplé, le tout parsemé d’une lourde procédure administrative qu’on voudrait aussi courte que possible. On voudrait que tout soit une farce, une mauvaise blague de sa part. Mais non, il était bien parti, emportant avec lui une partie de moi.

On repasse en arrière le film de sa vie, on regarde des photos, des petits films où il était si vivant, un grand sourire aux lèvres. Quand je suis dans sa maison, je m’attends à le voir surgir, ravi « je t’ai préparé une daube ma puce, tu vas te ré-ga-ler !!! ».

On ne profite jamais assez de ces instants, pourtant si banals à priori … le regarder préparer de savoureux repas pour mieux les partager, regarder un film en sa compagnie car il adorait le cinéma, se promener au bord du lac … Il me disait « La vie est un beau film qui se termine mal. ». Il était nerveux de nature, mais si dénué d’anxiété, voyant les choses telles qu’elle étaient mais pas pire, et comme j’ai pu lui envier cette qualité de vivre la vie sans craindre le lendemain, faire des scénarios alambiqués qui font monter le rythme cardiaque et parsemer les nuits d’yeux grands ouverts. A la fin, nous sommes tous logés à la même enseigne, un aller sans retour, ticket simple.

On part, dénué de tout bien matériel, de tout argent, emportant avec soi ses actes, ses pensées, ses missions de vie. On ne laisse que le souvenir de sa présence, en bas, chez les vivants, qui se questionnent. Quand viendra « mon tour » ? Et que se passera-t-il quand la Faucheuse m’aura envoyée en voyage forcé ? Qu’emporterai-je ? Que laisserai-je ?

Je voudrais que l’Univers / Dieu / whatever m’aide à trouver ce Chemin de Vie qui pourra me permettre de donner le meilleur de moi-même, me dire, oui la vie est un beau film qui se terminera mal pour ceux et celles qui m’auront aimée. Je voudrais continuer à frissonner en urbex, donner du positif aux gens, que la vie me donne ce dont j’ai besoin mais pas plus, me retrouver prête à enfin rencontrer l’Amour qui me correspond, voyager, découvrir, expérimenter. Devenir sage et spirituelle, une bonne personne qui toutefois sait dire ses limites, relativiser, prendre du recul. Réaliser par exemple que remplir sa déclaration d’impôts ne vaut pas quinze nuits blanches.

Juste de quoi me dire, à ma dernière seconde « c’était quand même un bon film ».

Nous sommes dans une Société qui veut que nous ayons peur de la Mort, quitte à bannir ce mot des réseaux sociaux …
Nous voulons tant la chasser, provocant des hystéries collectives, des folies générales et protections fallacieuses : « Nous sommes en guerre !!! La Mort tue !!! ».
Parce qu’Elle est là, et fait partie de la Vie. Elle viendra quand même un jour arrêter votre Montre, non pas votre dernière « Smartwatch » qui finira à la poubelle dans 5 ans ou sera dérobée par un individu sans scrupule, mais celle qui vous accompagne depuis toujours, la Votre, qu’on ne pourra jamais voler.

Rien ne dure.

J’ai testé pour vous : l’Italie !!!

Depuis le temps que l’idée me trottait dans la tête, d’autant plus que le pays regorge de magnifiques spots urbex … j’ai fini par me laisser tenter. Laissez-vous guider dans ce premier trip qui ne sera pas le dernier. L’Italie ça se savoure plus d’une semaine. D’ailleurs à propos de savourer …

La gastronomie : OUI, OUI et OUI !

La gourmande que je suis sait qu’elle va dans un pays dont la réputation n’est plus à faire. Je me suis fait une raison au Royaume-Uni (on n’y va pas pour ça, certainement pas, quoique le saumon d’Ecosse est à si bas prix que c’est un crime de s’en priver). J’ai été intriguée positivement par l’Allemagne, déçue par la Tchéquie qui vous concocte des plats trop bourratifs. Mais là on est en Italie. Les pâtes, la pizza sont des valeurs sûres. Les gelati, rien de mieux pour satisfaire un petit creux. Pour les amateurs de vins, le Chianti et le Prosecco sauront amadouer vos papilles. Mais vous découvrirez aussi les caloni, les suppi et autres arancini … Même en détestant le fromage, je n’ai pas hésité à ajouter du parmesan sur mes macaroni !!! Mama miaaaaaa !

Le lèche-vitrines en Italie, où tu as vraiment envie de lécher la vitrine !

Milan : NON, NON et NON.

Milan, c’est la grosse métropole bien corsée, pire que Paris. Nid à touristes bien condensés, c’est compliqué. Les cars de visite sont même les plus désorganisés que je n’ai jamais vus.
Les autochtones y sont revêches, peu avenants, pas souriants.
Les restaurants vous font payer une fortune, et y ajoutent volontiers par-ci par là des taxes venues d’on ne sait où.
Visiter la cathédrale « El Duomo » est un parcours du combattant et on n’est pas mécontent de quitter la ville. Qui a du potentiel, une beauté sûre, mais tout cela est gâché par une agitation permanente. La seule raison pour laquelle j’ai voulu y aller, était pour l’urbex. Vous y trouverez des spots de choix. Mais n’y passez pas votre vie.
Veni, vidi, vici … Arrivederci Milano.

ça grouille, impossible de faire une belle photo.

Rome : Un autre univers …

Ma maman me dit toujours qu’à ses yeux Rome est la plus belle ville du monde, et en parle avec les yeux qui brillent. J’allais tester ça !

Un peu frileuse en embarquant dans le train, pour le coup, je ne voulais pas être déçue. Mais c’est une toute autre atmosphère qui vous attend. Arrivée à Rome, je me promène un peu dans la gare, et ses stands gastronomiques qui n’hésitent pas à vous faire goûter leurs produits. Vous avez déjà un avant-gout de ce qui vous attend : vous allez vous ré-ga-ler !

Rome a beaucoup moins ce côté métropole, et pour cause, le centre-ville est parsemé par-ci par là de ruines historiques qui lui donne ce charme tellement typique de la Dolce Vita.

Déjà, les habitants sont beaucoup plus chaleureux. Vraiment, promenez-vous, voire perdez-vous, dans les petites ruelles où les maisons sont orangées, ça sent bon les fleurs et les bons petits plats. Et regardez les gens, ils se voient, ils crient leur amitié et se serrent dans les bras ! On est obligé de visiter avec le sourire, tout est prétexte à la bonne humeur, à l’émerveillement (à part le métro).

Rien à dire, c’est beau. Majestueux. Bellissimo.

N’hésitez pas à vous promener dans le Vieux Rome de nuit, côté Colisée / Forum, c’est tellement magnifique que j’en ai eu les larmes aux yeux, vraiment, j’ai pleuré d’émotion. C’est doux, c’est beau, on s’y sent en sécurité, même en étant une femme seule. C’est la Dolce Vita à l’état pur !

Niveau gastronomie, on retrouve des prix raisonnables. Les restaurants sont bons marché. La pizza est surprenante quand on la compare à celles de chez nous. Elles sont toutes fines, simples, sans chichis, de la tomate, un accompagnement, du fromage, et basta ! Mais molto bene

Buon appetito !!! (Pizza aux pepperoni)

Certains restaurants optent pour l’originalité dans leur design :

Bien entendu, on ne peut visiter Rome sans faire un tour à la Cité du Vatican et au Colisée, ainsi que le Forum, et je ne peux vous recommander que d’utiliser des billets coupe-file car il y a vraiment du monde. Et optez pour des visites guidées pour compléter vos notions d’Histoire. Et y aller tôt le matin, c’est mieux ! Message aux ochlophobes (dont je fais partie) : la Chapelle Sixtine est somptueuse mais oppressante de par la foule, les consignes y sont strictes qui plus est, préparez-vous à dompter votre stress.

Il y a des quartiers où il convient de ne pas circuler après 11 heures, comme du côté du Panthéon, rabattez-vous plutôt dans un des nombreux parcs, qui sont d’une beauté phénoménale (allez jeter un œil au jardin botanique, surtout l’été). Car Rome est immense, vous allez marcher, marcher, pendant des heures, ce qui va vous aider à éliminer les calories de vos pizzas et de vos macaroni al ragu, ce qui tombe bien, car vous n’aurez pas de surprise sur la balance à votre retour (véridique).

Une surprise m’a attendue à la fin du séjour : un trolleybus en gare de Roma Termini.

Mon avis global

Milan, non, vous l’avez compris. Mais Rome m’a enchantée. Il y a tellement de choses à y voir que j’ai manqué beaucoup d’endroits. J’ai eu un pincement au cœur en quittant la ville, mais j’y reviendrai lors d’un prochain trip, qui inclura surement Florence et Venise.
J’ai été tellement conquise que je me suis lancée dans une reproduction du Colisée dans mon serveur Minetest …

Je déclare la guerre aux « lol » !!!

Il fut un temps où je fréquentais les sites de rencontres, cultivant à l’époque l’espoir d’y rencontrer une princesse de contes de fées.

Dans ce contexte, je faisais vite le tri … lire des fautes à chaque mot, désolée je ne peux plus. J’ai déjà eu des histoires avec des gens qui n’étaient pas doués en orthographe, mais j’ai vite fait la corrélation. Ce n’est pas une question d’ouverture d’esprit, car l’ouverture je la faisais, me disant que l’autre avait certainement des qualités qui pouvaient me plaire, mais ces personnes n’étaient pas faites pour moi : impossible de parler de culture, des choses qui me passionnaient, de faire des débats … blocage complet. Les « cc sa va ? » … impossible également.

Bien sûr, il y a des gens qui peuvent être atteints de dyslexie », et autres « dys-« , mais si on va par là, 70% des gens avec qui je communiquais étaient donc atteints d’un trouble ? Je ne suis pas d’accord.

Il faut que je vous avoue quelque chose : je suis phobique des fautes d’orthographe, oui je suis une « pédante grammaticale » assumée, et voir des « er » à la place des « é » ou des « ez » à la place des « er », je ne comprends pas ce qu’il se passe dans cette logique. Et quand je ne comprends pas, ça m’énerve. Pourtant des fautes, j’en fais, et je me suis rendue compte de mes limites lors de mes actuelles révisions pour le « Certificat Voltaire » que je prépare. Ou alors je fourre par-ci par-là quelques fautes d’inattention. Mais les grosses fautes, les crimes contre la langue de Molière comme les « enfaite » me font hurler de douleur, littéralement. Il faut avouer que c’est comme ça, et que je ne peux pas changer cette phobie, tout comme ma misophonie.

Pour citer une anecdote personnelle, il y a un bon paquet d’années de ça, j’avais eu un coup de foudre, un gros. Un jour, après en avoir marre de me poser des questions, je lui ai proposé un verre, qu’elle a décliné, mais le lendemain elle m’a envoyé un mail plus explicatif pour me faire comprendre que ce ne serait pas possible entre nous. Bon, ça arrive, un « non » ce n’est ni le premier ni le dernier, parce que c’est la vie et il faut l’accepter, et ça m’a permis de sortir de ma zone de confort (et de plus tard, entendre des « oui » de la part d’autres personnes). Mais ce qui m’a fait complètement changer d’avis sur cette personne était le contenu même de ce mail, écrit en langage SMS. La personne concernée n’avait plus 20 ans.

Langage SMS ? Mais NEXT, miss, sans regret !!!

Mais un mot me fait encore plus hurler, lors d’une conversation épistolaire.

LOL.

Parce qu’il n’y a rien derrière. On peut jeter un lol, par une phrase qui fait rire, mais parler d’un sujet sérieux, et lire en réponse un « lol » me laisse perplexe, lorsque un processus de « prise de connaissance en vue d’une relation » est entamée.

Lol, oui mais que veux-tu dire par là ? Que veux-tu exprimer ? (Parce que ce mot-là, aujourd’hui veut tout et rien dire, un peu comme un vieux livre qu’on cale sous un meuble, ça meuble une conversation, mais c’est plus de l’Ikea bon marché qu’un fauteuil Louis XIV).

Un exemple : je courtisais sur un site une demoiselle qui avait l’air d’être interessante, il y a quelques années. Nous avons échangé nos numéros, et un soir, alors que je lui partageais ma lecture du moment, j’ai eu une réponse qui là aussi, m’a faite vriller : « lolilollll mdrmdrmdr ».

Mon livre était : « Le pouvoir du moment présent » d’Eckart Tolle.
Donc rien de comique là-dedans.

Perplexe par la teneur de son propos, je lui demande plus d’explications, elle m’a juste répondu que pour elle « c’était pipo ». Okay, donc NEXT, pour le « trolol » et également, parce qu’elle ne partageait pas les mêmes valeurs en termes de spiritualité.

Un autre exemple … cette fois-ci j’étais en « relation sérieuse » avec une femme. Avec le temps, je me demandais vraiment ce que j’avais plus lui trouver, j’aimais discuter de choses intellectuelles, elle préférait les potins, parler des défauts et de la vie des autres, et lire « Closer ». Je n’ai rien contre ces gens-là, mais ce n’est pas mon truc ! Je pense que je l’idéalisais complètement. Je lui envoie un jour un SMS assez alarmant pour lui dire que je craignais qu’une de mes amies se soit enrôlée dans une secte. Là encore, rien de drôle, c’est plutôt grave (et heureusement mes craintes ne sont restées qu’au stade de peur, tout va bien pour elle). Et j’ai eu comme réponse « lol ».

J’imaginais la crédibilité de ses messages écrits, de l’image qu’elle pouvait renvoyer, de la mienne par la même occasion, puisque nous étions ensemble.

Quand j’écris, j’ai besoin de propos riches, j’ai besoin d’en savoir plus sur la personne que j’ai de l’autre côté de l’écran. Et le « lol » a le même effet que « cc sa va », un minimum d’éloquence, que diable, notre langue est riche (quoi que, pas autant que l’Allemand, mais c’est une autre histoire), et derrière se cachent des trésors (ne serait-ce que recevoir de belles lettres d’amour non copiées-collées d’un site … ) !

Et puis surtout : si tu dis LOL, le Bon Dieu il tue des petits chatons mignons. A moins que tu n’aimes pas les chats, un autre motif pour te nexter.

Mes débuts dans le web : j’étais une vraie gamine !

Message préventif

Si vous êtes victime de harcèlement ou de dénigrement sur Internet, parlez-en aux adultes. Si vous êtes un adulte responsable qui entendez de la détresse, appliquez les mesures qui s’imposent pour tempérer les situations, de grâce. Le problème est de nos jours TROP GRAVE.

L’histoire : J’ai crée un site par haine

On a parfois du mal à vouloir s’imposer quand on est jeune, chercher par tous les moyens de satisfaire ses besoins primaires. Grâce au développement personnel, j’ai compris que le besoin de reconnaissance faisait partie de mon identité. Et c’était encore plus le cas sur les bancs de fac.

Remontons le temps. On est en 2000, j’arrive en première année de BTS Assistant de Direction (oui … je me suis suis dit allons là, on verra bien). Mon site amelieonline.net vient tout fraichement de sortir, souvent agrémenté de mises à jour plus ou moins ratées. Mais je venais de découvrir une passion (qui allait devenir vocation), et le soir, à peine rentrée dans mon studio, je me jette sur mon PC pour faire du développement, faire des sites annexes, bref, je m’amuse à découvrir HTML au lieu de faire mes devoirs. Mon cadeau de mes 18 ans, c’était un livre sur Dreamweaver (l’IDE le plus en vogue de l’époque) et sa licence. Oui, donc au moment des faits, j’ai 18-19 ans.

Je suis comme une folle. Je crée des tutoriels pour ma classe, et espère que le site aurait son petit succès. Je ne manque pas, lors de la présentation officielle devant ma classe, face à ma prof principale de parler de mon site. Je reçois des messages sur mon livre d’or, des bonjours, de ma prof et de mes camarades. Mais le site n’est pas trop visité, j’ai du mal à trouver mon style, à la fois sérieux et trop second degré. En même temps, mes camarades ne sont pas « geeks » dans l’âme, pendant que moi, je navigue dans le « Deuxième monde » de Canal+, ancêtre du « métaverse ».

L’affaire de la photo à scandale

Du coup, je balise, et profite du projet « journal des promos AD du lycée » dont j’ai la charge pour écrire un article et faire la pub, venez sur mon site il est cool. Mais il y a un hiatus.

Quelques jours avant la distribution du canard, en fin de page de mon site, je publie une photo accompagnée d’un commentaire, destinée à une personne (hors du lycée et sans la nommer) qui m’avait profondément blessée. Le site ressemblait donc à ça (désolée je n’ai plus d’archive de cette version, la seule trace c’est cette demi-page imprimée toute pixelisée) … j’ai flouté volontairement l’image en question, qui était récupérée sur le web et qui m’avait amusée.

C’était quand même, avec le recul, vraiment osé, je n’aurais jamais dû faire ça, d’autant plus qu’on a du mal à faire le lien entre l’annonce de l’histoire de la « personne dangereuse » et la photo qui l’accompagne. On peut vraiment croire que je me moque de mes lecteurs, que je cherche à les provoquer. Mais on peut se montrer bête quand on a 18 ans.

Et un soir, en rentrant, je reçois un mail de la part des deuxième année, qui me fait part de leur indignation, agrémenté d’un bon « t’as rien compris à la vie et certainement rien au c… ». Je me sens en colère car c’était plus caricatural et vindicatif que pornographique, mais je consens à enlever la photo fissa. Mais le mal était fait. Le week-end arrive, je suis chez maman et … coup de fil.

AIE. Ma prof principale. Donc je lui explique ma version des faits, elle se montre douce et compréhensive, mais qualifie mon acte de « potache » (ce qui en soit est vrai). Ma maman, témoin de la conversation, me donne une bonne engueulade aussitôt raccroché. Le lundi, tout le monde me tombe dessus, camarades et profs : « Vous imaginez demain si ça tombe en conseil de classe ? A l’annonce de votre nom? devant le directeur de l’établissement ? ». Mon moi de l’époque a ressenti pendant longtemps un gros sentiment d’injustice : « Comment, je mets des tutos, des choses utiles sur ce site, et tout ce qu’on retient, c’est cette stupide photo ??? M… alors, allez tous vous faire f…. !!! ». Oui, au lieu de remettre en question mon contenu, je remettais la faute sur les autres, facile.

L’affaire Loft Story

Quelques mois plus tard, nous sommes en 2001 et le Loft apparait. Je demeure toujours une geek asociale et aigrie, même si je fréquente assidument une bande de copines du lycée où j’ai passé le bac, et je communique sur IRC. Mais je n’apprécie pas les filles de ma promo. A l’époque je les jugeais superficielles, et elles me trouvaient trop bizarre (HPI es-tu là ?). D’autant plus que je traversais une période compliquée, je me posais des questions sur mes orientations amoureuses, bref je n’étais pas bien dans mes pompes.

Je progresse dans mes apprentissages du web, je crée une plate-forme accessible par login et mot de passe pour ma promo pour qu’elles aient du contenu un peu fun. Sauf qu’il y a eu un contenu pas du tout fun … sauf pour moi. Je crée pendant l’été un site annexe sur cette plate-forme, parodie du site du Loft, où je mets en scène les filles que j’apprécie le moins. Avec les mêmes graphismes, les mêmes codes de couleur que le site original, je m’amuse de ouf, paf, dans leur tête. Mais je n’en parle pas trop autour de moi, laisse les gens qui veulent bien le découvrir. Je pensais fermer ce site tôt ou tard, parce que certains propos allaient loin. Puis je méconnaissais le droit : même en accès « privé », le droit à l’image s’applique. J’allais même plus loin : mon prof de français, qui avait alors humilié le projet du journal devant la classe, prenait le rôle de Castaldi !

Puis vint le drame, en plein cours d’anglais, alors que je provoquais quelques voisines au lieu d’écouter la leçon, la déléguée souffle à ses voisines l’existence du site parodique. Là je vois les menaces directes des principales concernées. Ce que j’ai fait ? J’ai pris la fuite en plein cours, face à une prof désemparée, et file fissa à mon studio pour effacer toute preuve d’existence ce cette catastrophe qui se préparait. Et j’ai fait la morte pendant plusieurs jours, prétextant être malade auprès de la vie scolaire.

Bien sûr, à mon retour j’ai eu des comptes à rendre. Sincèrement, j’ai regretté ce site. Car entre-temps, nous vivions toutes la catastrophe AZF et ça nous avait rapprochées, et je m’étais montrée assagie dans ma virulence et mes jugements. Ce coup-ci, ma maman n’a eu aucun vent de cette affaire, il vaut mieux, pour elle et pour moi, car elle aurait vraiment été déçue.

Heureusement il y a eu ma prof principale qui a été là, car je suis allée direct lui confesser mes actes, et dans son attitude un peu maternelle envers moi, m’a alors défendue (même si elle ne cautionnait pas du tout mon « œuvre », normal), elle m’a conseillé de travailler sur mon besoin de vengeance, et a tempéré le conflit qui aurait pu aller loin. Beaucoup plus loin. Je l’en remercie encore et passe un bonjour à elle en passant. Nous sommes toujours en contact, des décennies après. Une femme adorable qui a su prendre le temps de m’écouter quand j’en avais besoin.

Pourquoi j’ai fait ça ?

Parce que j’étais une adolescente qui manquait de confiance et d’estime d’elle-même, en mal de reconnaissance et qui ressentait beaucoup d’injustice. Ancienne victime de harcèlement moral au collège et au lycée, je voulais absolument qu’on aime ce que je faisais, qu’on admire mon travail, quitte à basculer dans la provocation. Je subissais en parallèle du cyber-harcèlement sur IRC, des gens qui n’hésitaient pas, par simple gratuité de m’insulter, ce qui m’avait rendue à l’époque aigrie et très anxieuse. Je ne m’en sers pas d’excuse, j’avais tort sur toute la ligne. Mais la haine est un cercle vicieux, quand on est jeune, on a la haine quand on reçoit de la haine.

Le message final de mon moi actuel

Ce post se voulait au départ être une confession, confession de mes bêtises, de mon tempérament, du mal que j’ai pu faire.

De dire aussi que j’ai appris de mes erreurs. Et que la leçon à retenir c’est que tout créateur est responsable de son contenu, et qu’à ce jour, j’y suis très sensible.

Mais au fur et à mesure de l’écriture de ces lignes, j’ai beaucoup réfléchi sur cette histoire et l’actualité. Il y a autre chose à dire.

Aujourd’hui les temps ont changé, et le partage d’infos est plus facile. Il y a vingt ans, transmettre de l’info sur internet devait demander du travail. Il n’y avait pas les réseaux sociaux.

Et c’est ça qui est terrible, car ils sont vecteurs aggravants du harcèlement scolaire. Les jeunes qui ont recours à ces pratiques sont mal dans leur peau et ne se rendent pas compte qu’ils peuvent briser des vies ce faisant. Communiquer derrière un écran est facile, trop facile. Aujourd’hui des jeunes se suicident pour une page en trop, une phrase de trop. Ils n’ont plus de répit, aussitôt sortis du collège/lycée, ça continue sur leur téléphone !

Faites attention aux informations que vous véhiculez, elles peuvent causer beaucoup de mal.

J’ai visité pour vous : Prague !

Enfin ! Merci mon amie la pandémie pour m’avoir permis d’attendre ce voyage pendant deux ans et demi … Oui, j’ai bien attendu pour enfin mettre les pieds dans cette ville. J’imagine que vous souhaitez avoir mon avis, je le donne direct : mi-figue, mi-raisin.

Le voyage : je HAIS Air-France

  • A l’aller, j’ai dû attendre deux heures pour aller à Paris-CDG, bien entendu, il a fallu reporter mon deuxième vol, qui a eu lui aussi du retard. J’ai attendu en tout 6 heures à CDG, je n’en pouvais plus. A lieu d’arriver à 17h15 à Prague, j’ai du arriver à 23h, et donc renoncer à certaines choses que j’avais prévu, pas cool.
  • A retour, un retard de 30 minutes à CDG, suivi d’un embarquement qui n’en finissait pas.

Le peuple de Prague : ça coince !

Avant de partir, j’ai fureté sur les sites et vidéos qui pouvaient m’informer sur les us et coutumes tchèques, je peux vous citer deux sources plutôt intéressantes :

  • Prague secrète, conseils et astuces.
  • The honest guide, qui fait part des lieux intéressants, permet d’éviter les pièges à touristes, et donne des astuces pour éviter de croiser les scammers. Il y décrit son expérience dans la ville avec un grand sourire et une avenance qui donne vraiment envie !

Histoire de me comporter en touriste respectueuse, et pouvoir profiter pleinement de mon séjour. Sauf qu’il y a un hic.

Ma première visite aura été le château de Prague, et là Prague-Secrete a raison, ce n’est pas franchement intéressant de s’y attarder. Pire encore, le personnel y est déplorable, tellement il est désagréable. Quand je dis « Hi ! », les gars qui récupèrent mon ticket me répondent en grognant, et je me fais chasser comme une malpropre à l’entrée de la salle historique parce que j’avais acheté un ticket online !!! Et là je me dis :

« Ils sont sérieux, ils sont comme ça les gens dans cette ville ??? »

Au restaurant Mintcovna, pourtant plébiscité, je me fais recaler parce que je n’avais pas réservé. Je leur explique que je suis seule, il n’y a pas beaucoup de monde dans la salle. Franchement, on peut me caler dans un coin, avec un peu de bonne volonté, et puis zut, c’est mon anniversaire, j’ai 40 ans, on peut se plier à ma volonté !!! Heureusement, un autre français avait fini sa bière, et m’a proposé de prendre sa place. J’ai mangé un goulasch qui m’a vite plombée, limite lancé comme un frisbee par la serveuse, accompagné d’une bière 50% liquide 50% mousse. Je suis restée au moins une bonne heure, durant laquelle j’ai constaté que la salle demeurait toujours à moitié vide. Ils ont sérieux, eux aussi ??? Je suis partie en insultant en français le patron et son air condescendant. N’y allez pas.

Comme vous le voyez, ils mettent même pas le pain.

Franchement, je ne relate que deux histoires, mais il y en a d’autres. Qu’est-ce qu’ils ont ces gens, contre les touristes ! Je ne suis pas responsable du triste passé de ce pays, bon sang !

Heureusement, j’ai eu affaire à des personnes aimables, et je les en remercie. Parmi elles :

Une partie de Bohnice qui a viré un peu urbex 🙂

Trop de touristes, et de magasins

J’me suis faite avoir :'(

Évitez à tout prix le Pont Charles la journée, ainsi que la rue Karlova qui sont infestées de touristes qui se déplacent en troupeaux, sauf le matin, avant 9 heures.

Le centre de Prague est très joli, mais regorge d’attrape-touristes :

  • Des pseudo-boutiques de cannabis
  • Des boutiques à « souvenirs », qui vendent des chapkas et poupées russes, reliques d’un passé que les Tchèques aimeraient bien oublier.
  • Des vendeurs de Trdelník ou « Chminey cake » … ne croyez pas qu’il s’agisse d’une vraie spécialité … c’est JUSTE une gourmandise Praguoise « spécialité » … depuis que les touristes affluent. J’ai goûté, ce n’est pas mauvais, mais c’est du sucre, sur du sucre, avec encore plus de sucre (attention aux attaques de guêpes) !
  • Les promenades en calèche … sauf que les poneys ont l’air au bout de leur vie. Même si le concept peut paraître sympa, épargnez-leur ces trottes forcées.

Une jolie ville

Un patrimoine non égalé certes. Il y a une visite à faire à tout prix : le Monastère de Strahov, et sa légendaire librairie, c’est un pur bijou !

C’est une splendeur.

N’hésitez pas à vous perdre dans les galeries, vous pourrez avoir des surprises ! Tip : dans la galerie Lucerna, il y a un paternhoster !

Entrée du cinéma de la Galerie Lucerna

La gastronomie : oui mais …

Mais rien n’égalera la gastronomie Française, en fin de compte. J’avoue que l’idée de manger du porc rôti ou des plats mijotés avec un bock de bière m’enchantait pas mal. Mais en fait c’est HYPER bourratif, je n’arrivais pas à terminer mes assiettes, et il m’est arrivé de sauter des repas, parce que justement, je n’avais pas faim, et que le repas précédent m’avait bien rassasiée.

Et puis la bière, je finis par m’en lasser, au point que je finissais par trouver qu’elles avaient toutes le même goût. A vrai dire, j’ai l’impression que dans cette ville, c’est plus facile de trouver de la bière que de l’eau, à croire qu’ils ne connaissent QUE ça, et que dans la Vlatva (prononcez « Voltava »), c’est de la bière qui y coule. Franchement.

Mais des surprises …

  • J’ai fêté mon anniversaire au U Pavouka, repas gargantuesque dans une ambiance sertie de spectacles médiévaux. J’ai bien aimé (surtout les danseuses du ventre 😎 ).
  • Les galeries … furetez bien, des surprises architecturales mais aussi vous y trouverez des FLIPPERS. Oui, des FLIPPERS !!!
Des FLIPPERS !!!
  • Faites-vous servir par des petits trains au Vytopna.
  • Vous aimez les papillons, et vous voulez en voir de jolis de près ? Passez à la Butterfly House, avec un peu de chance vous ferez ami-ami avec un de ces lépidoptères.
Oui, j’ai un papillon sur la tête.

Pour conclure, que dire ?

Je suis venue. J’ai vu. Je n’y reviendrai plus. Parce que j’aimerais découvrir de nouveaux confins, et je n’ai pas eu le coup de foudre. Mais aucun regret, à part un, j’aurais aimé faire une vraie sortie urbex, mais pour cela, il faut connaitre des gens, et tous les lieux connus ont été réhabilités (dont ceux-ci). Dommage.

Migration du serveur Minetest (en PostgreSQL !)

Le moment était venu. Le serveur qui hébergeait jusqu’alors mon jeu Minetest « Amelaye in Minerland » commençait à souffrir, tant la base de données tendait à être énorme (33 Go, vous voyez un peu …). Difficile de dire aux joueurs d’arrêter d’explorer, de creuser, bref de tirer la plus-value du monde qu’ils aimaient modifier. D’autant plus que j’avais bien envie d’installer de nouveaux mods. Et puis surtout, le serveur qui héberge le jeu est une machine perso, qui sert également pour pas mal de choses.

Alors j’ai décidé d’une part de louer un nouveau serveur Kimsufi, une machine assez robuste pour cet usage exclusif, et d’autre part, de migrer la base de données Minetest, à l’origine en SQLite vers PostgreSQL. Pourquoi ? Parce que si on regarde bien, c’est plutôt vivement recommandé.

Documentation des backends Minetest

Tout est dit, ne plus rester sous SQLite implique de limiter les lags, et également de réduire les risques de corruption de la base de données (ma plus grande crainte !). Et ça, c’est tout bénéf’ !

Allons-y. Ma nouvelle machine arrive toute fraiche avec la dernière version d’Ubuntu. Déjà, je m’enlève de la tête qu’on n’installe pas Minetest avec un simple apt-get dans mon cas de figure, ce serait trop simple. Car la version déjà compilée ne supporte pas PostgreSQL. Il va falloir compiler les sources. Je relève le défi.

On prépare le terrain

J’installe la matière première, les librairies qui me seront utiles …

sudo apt install wget postgresql 
postgresql-contrib g++ make libc6-dev libirrlicht-dev cmake 
libbz2-dev libpng-dev libjpeg-dev libxxf86vm-dev libgl1-mesa-dev 
libsqlite3-dev libogg-dev libvorbis-dev libopenal-dev 
libcurl4-gnutls-dev libfreetype6-dev zlib1g-dev libgmp-dev 
libjsoncpp-dev libpq-dev libpqtypes-dev doxygen 
libluajit-5.1-dev libspatialindex-dev libncurses-dev

Comme ça, c’est fait. Je me crée un utilisateur minetest :

sudo useradd -mU minetest

Et je me logue sur le compte, comme ça :

sudo -i -u minetest

Puis je télécharge les sources de Minetest. Important : téléchargez la DERNIERE VERSION stable qui correspond à celle que vous utilisiez, sinon ça peut engendrer des bugs. Dans mon cas, c’est la 5.5.1 :

git clone https://github.com/minetest/minetest.git
git checkout 5.5.1
cd minetest/games/
git clone https://github.com/minetest/minetest_game.git
git checkout 5.5.1
cd ..

Ok, c’est facile. Maintenant, je passe à la pré-compilation (et je croise les doigts) :

cmake . -DRUN_IN_PLACE=TRUE 
-DBUILD_CLIENT=FALSE 
-DBUILD_SERVER=TRUE 
-DCMAKE_BUILD_TYPE=Release 
-DBUILD_UNITTESTS=FALSE 
-DENABLE_POSTGRESQL=TRUE 
-DVERSION_EXTRA=postgresql 
-DPostgreSQL_INCLUDE_DIR=/usr/include/postgresql 
-DPostgreSQL_TYPE_INCLUDE_DIR=/usr/include/postgresql 
-DPostgreSQL_LIBRARY=/usr/lib/x86_64-linux-gnu/libpq.so

Et là … ça plante.

CMake Error at CMakeLists.txt:110 (message):
IrrlichtMt headers are required to build the server, but none found.
The Minetest team has forked Irrlicht to make their own customizations.
It can be found here: https://github.com/minetest/irrlicht
For example use: 
git clone --depth=1 https://github.com/minetest/irrlicht lib/irrlichtmt

On sent bien les origines allemandes du jeu, tiens. Il a besoin d’une librairie « Irrlicht » pour pouvoir compiler. Mais pourtant, je l’ai apt-getté, celui-là … bon, on va là aussi compiler les sources avec l’adresse GIT qui est fournie alors.

Installation d’Irrlicht

Donc, on récupère Irrlicht dans le répertoire minetest pour pouvoir faire en sorte que l’include dans les sources trouve ses petits. Il est très important d’installer Irrlicht dans lib/irrlichtmt

git clone --depth=1 https://github.com/minetest/irrlicht lib/irrlichtmt

On va dans le répertoire et on compile :

cd lib/irrlichtmt
cmake . -DBUILD_SHARED_LIBS=OFF
make -j$(nproc)

Normalement on s’en sort avec juste quelques warnings.

Compilation réussie !

Je reviens deux répertoires en arrière, relance la pré-compilation de Minetest, et … mince encore des erreurs.

CMake Error at /usr/share/cmake-3.22/Modules/FindPackageHandleStandardArgs.cmake:230 (message):
Could NOT find Zstd (missing: ZSTD_LIBRARY ZSTD_INCLUDE_DIR)
Call Stack (most recent call first):
/usr/share/cmake-3.22/Modules/FindPackageHandleStandardArgs.cmake:594 (_FPHSA_FAILURE_MESSAGE)
cmake/Modules/FindZstd.cmake:24 (find_package_handle_standard_args)
src/CMakeLists.txt:228 (find_package)

Bon, certainement une lib qui manque, ce ne sera pas la mer à boire. Je reviens dans mon compte utilisateur et je fais un petit :

sudo apt install -y libzstd-dev

Je reviens dans mon compte minetest et mon répertoire minetest, je relance la pré-compilation. Cool, ça a marché. Maintenant je lance la compilation :

make -j$(nproc)

Okay, le terminal m’indique que minetestserver a été compilé avec succès.

Je lance le binaire :

cd ..
./minetest/bin/minetestserver

Et je lance mon jeu depuis Minetest en spécifiant l’adresse IP du serveur. Tout se lance, génial. J’éteins le serveur, le plus complexe reste à venir.

Configuration du serveur PostgreSQL

Je relance par sécurité le service :

sudo systemctl restart postgresql.service

Et puis je lance mon interface PostgreSQL

sudo -u postgres psql 
CREATE USER monuser WITH PASSWORD '*****';
CREATE DATABASE adventure OWNER monuser;
GRANT ALL PRIVILEGES ON DATABASE adventure TO monuser;

Je vérifie avec /l que tout est ok et je sors

La migration de l’ancien serveur

Là, je suis obligée de dire à mes joueurs que le serveur doit être fermé pour la migration. J’éteins mon ancien serveur et je fais une copie de mon monde vers le nouveau. Je ne cache pas que ça prend du temps, vu le nombre de gigaoctets de mon map.sqlite.

Pour vous situer, il faut copier deux répertoires :
– celui des mods : .minetest/mods vers minetest/mods
– celui du monde, dans mon cas : .minetest/worlds/adventure vers minetest/worlds/adventure

Je tremble un peu durant ce transfert et prie pour que tout se passe bien. Je relance après cette étape en spécifiant mon monde et … ça se lance ! Tout va bien, je souffle un peu ! Maintenant passons aux choses sérieuses !

J’édite mon fichier world.mt du monde adventure pour y ajouter mes identifiants de connexion PostgreSQL. On ne touche à rien d’autre, notamment la configuration des backends en SQLite. Ce sera fait automatiquement.

pgsql_connection = host=127.0.0.1 port=5432 user=monuser password=***** dbname=adventure
pgsql_auth_connection = host=127.0.0.1 port=5432 user=monuser password=***** dbname=adventure
pgsql_player_connection = host=127.0.0.1 port=5432 user=monuser password=***** dbname=adventure

Et je lance ma première migration, celle du monde, et j’attends. Ce qui est sympa, c’est que l’avancée de la migration s’affiche :

./minetest/bin/minetestserver --migrate postgresql --world minetest/worlds/adventure

Si vous avez comme moi une base de données énorme, ne faites pas l’erreur que j’ai faite, de lancer le script dans un terminal et le laisser juste agir comme ça (sincèrement, je ne pensais pas que ça prendrait tant de temps !). Je suis partie me coucher, le lendemain mon ordi avait rebooté tout seul, interrompant le process (que j’avais lancé la veille à 15h30), et que j’ai dû relancer cette fois dans un screen (ou faites un nohup … &, bref, permettez au script de le laisser exécuté même si il y a une coupure.). Bref, une bonne vingtaine d’heures plus tard (oui, une VINGTAINE d’heures !!!) après le deuxième lancement, la base des blocs est migrée !

Regardons le fichier world.mt. Il a changé automatiquement le backend correspondant à la base des blocs. Nickel. Faisons la suite. Les autres bases de données migrent très vite.

./minetest/bin/minetestserver --migrate-auth postgresql --world minetest/worlds/adventure
./minetest/bin/minetestserver --migrate-players postgresql --world minetest/worlds/adventure

L’heure de vérité à sonné. Je vérifie que mes backends ont bien été modifiés et que tout pointe sur ma base PostgreSQL. Mieux que ça, je convertis mes fichiers map.sqlite, auth.sqlite et players.sqlite en map.old, auth.old et players.old. Je lance le jeu, et super, tout marche et je retrouve mon monde tel que je l’avais laissé …

Reste à remettre dans mon minetest.conf les paramètres de l’ancien serveur, sauf l’adresse, qui change.

Pour terminer, augmentez la mémoire allouée pour les requêtes PostgreSQL, sinon vous allez vous retrouver avec des plantages core dumped. Donc dans /etc/postgresql/potgresql.conf, changez la valeur du paramètre shared_buffer pour qu’il ait au moins une valeur supérieure à 512Mo. Chez moi, j’ai affecté 1024Mo.

Il ne reste plus qu’à profiter du jeu maintenant !

Mes notes du Symfony Live – Jour 2

Vous avez dit Symfony 6.1? – Nicolas Grekas

Ici, un autre « core dev » de Symfony pour cette première conférence, qui nous rappelle qu’au sein même d’une même version majeure, il y a promesse de rétrocompatibilité … D’une version majeure à une autre, le chemin de migration continue. Il est conseillé de faire un composer update tous les mois; et tous les 6 mois, un composer update pour passer en version mineure suivante, pour corriger les dépréciations.
Il est déconseillé de commencer ou rester sur une version LTS, pour ne pas rester « lent » ou « stable ».
En 6.1 on a droit à :
– une modernisation du code via nouvelles syntaxes / fonctions
– une meilleure description des types natifs et génériques
– une simplification par abandon : SwiftMailer, Twig, FlexServer
– une revisitation des classiques : composer runtime, symfony new (l’option –-full pour le website skeleton devient –website)
– des serveurs à longue durée d’exécutions
– une performance accrue.
Retour sur le nombre de PR : 6PR/jour en 12 mois soit 2000PR : 400 features, 700 bugs, +900 mineures)
Je vous laisse le loisir de regarder la rediffusion de la conférence pour avoir l’aperçu complet, et non exhaustif de cette mise à jour !

Mon avis : un bon tour de découverte de cette nouvelle version de SF, bien hâte de la tester en fait !

Code asynchrone dans une application Symfony synchrone – Jérôme Tamarelle

Petit rappel : Composer utilise depuis la version 2 des composants de ReactPHP, et peu de gens le savent.
Il est question de ces différents concepts :
1. I/O non bloquants
Fonctions natives de PHP pour les flux non-bloquants : stream_select, curl_multi_select, Symfony HTTPClient est non-bloquant.
2. Délégation de traitement à des processus parallèles
Effectuer des traitements en parallèle sans bloquer le processus courant, avec Sf Process ou encore Messenger
3. Branches de code concurrentes dans un même thread
Ici , on parle de promesses, coroutine, et fibers pour exécuter plusieurs branches de code en concurrence, sur le même thread.
A retenir :
– Une fonction synchrone peut appeler une fonction synchrone mais pas une fonction asynchrone.
– Une fonction asynchrone peut appeler une fonction synchrone et une fonction asynchrone.

Mon avis : je suis peu familiarisée avec ces concepts. Intéressant à découvrir par la pratique, peut-être avec un projet futur.                                     

Développer une application web décentralisée avec Symfony et API Platform – Kevin Dunglas

SAUVONS LE WEB !!! DECENTRALISONS !!! Tel est le message de cette conférence de Dunglas, connu de tous pour être un des core devs de Api Platform.
Les GAFAM représentent 57% de tout le trafic mondial, la majorité de l’usage du web passe par ces quelques acteurs-là, et leur donne un contrôle quasi total des contenus des internautes. Ce qui était à des milliards de lieues de la volonté de Tim Berners-Lee quand il a crée le web ! Au départ il voulait vraiment créer un espace de libre expression pour les gens qui ne pouvaient pas le faire … le Web devait donner une voie aux personnes marginalisées, les autres médias étant réellement contrôlés, tous ceux qui avaient quelque chose à dire pouvaient le faire, via les URL, qui relient les sources les unes aux autres (on a donc un graphe de connaissances). Or les GAFAM donnent donc pas mal de problèmes de démocratie, vu qu’ils censurent à tout-va.
Aux origines, le Web 1.0, tout était décentralisé.
Puis le Web 2.0 (terme marketing) est arrivé, permettant aux utilisateurs de bénéficier des formulaires pour publier du contenu, créer des mixs de communautés. On a vu apparaitre les API web, ainsi qu’un mix d’acteurs non-commerciaux et commerciaux, ça se passait plutôt bien. Mais l’argent est entré en jeu.
Puis on voit naitre le Web 3, la promesse : re-décentraliser le web, casser le pouvoir des états surveillants. On propose d’utiliser la blockchain d’Ethereum et d’exécuter ce code sur les ordinateurs du réseau pour faire des sites web. Donc base sur les cryptomonnaies, trustless et permissionless. Sauf que des problèmes se posent : consommation énergétique (Ethereum toujours en POW), d’énormes structures américaines sont intéressées par le concept, chaine de Ponzi.
Donc, voici le concept du Web 3.0, apparu avec le web sémantique, crée par Tim Berners-Lee, qui consiste à utiliser le web comme immense base de données, le web est donc considéré comme base de connaissances, les opérations auraient une grande interopérabilité.
Pour cela on utilise un modèles de données abstrait pour représenter n’importe quel set de données : RDF. Mais on a d’autres formats : tableau HTML, N-Tuple dans un fichier texte, Turtle, JSON-LD.
Tim Berners-Lee présente son projet : SOLID. Les considérations physiques, politiques, etc … dont détaillées dans des documents émis en dur. Solid Toolkit permet de créer des application décentralisées et interopérables, la décentralisation des données personnelles, etc …
A mentionner qu’on peut construire une application Symfony avec Solid. Dunglas propose son bundle.

Mon avis : je suis TRES sensibilisée sur sujet, et j'avais envie, avant la pandémie de faire un gros projet lié au web, son évolution et sa centralisation, hélas remis à plus tard. L'idée est interessante et je vais me pencher sur le sujet, et regarder Solid d'un peu plus près ... mais toutefois, je me pose des questions. N'est-il pas mieux de sensibiliser les gens à faire leur propre site internet, comme avant ? et de créer l'arborescence de leur communauté à cet effet ? Leur faire comprendre ce qu'est le logiciel libre ? Si Dunglas passe par là, je serai ravie qu'il puisse répondre à mon interrogation ;) !

Mon avis global sur le séminaire

Une joie de retrouver tout ce beau monde et l’ambiance des séminaires sans entendre les mots maske aubligatouar, pace vaksinale et tout le toutim. J’aspire vraiment à retrouver la vie active d’avant que je menais sur ce point-là. Les différents stands étaient attractifs, et je suis bien contente d’avoir eu un beau t-shirt en cadeau, et un autre gagné sur le stand des Tilleuls.coop. Il faut juste que je pense la prochaine fois à imprimer mon badge avant de venir ! Les thèmes des conférences étaient variées, et la plupart étaient bien intéressantes et donnent envie de creuser le sujet abordé.
Sinon … gros bémol pour les déjeuners. J’adorais le concept du buffet proposé lors de ma dernière venue, qui permettait un éventail varié. Je fais très attention à ce que je mange, surtout quand je ne trouve pas le temps de faire du sport, que je mange au resto le soir avec ma chérie + les copains que je n’ai pas revus depuis un bail, et que j’ai de gros problèmes avec certains aliments (comme le fromage). Là c’était vraiment bourratif, trop riche et pas varié (sérieux les gars, un gâteau au Daim ? Pas un seul fruit !). Le souci c’est que le tarif du SfLive est plutôt conséquent, et pour moi chaque centime compte, la nourriture en fait partie. Et qu’on ne me parle pas de « raisons sanitaires », vu qu’on reste toujours tous mélangés dans les différentes salles … mais bon, on va me répondre qu’on n’a pas eu le choix, c’est ça ou rien … Oui, je suis exigeante 😀 !

Mes notes du Symfony Live – Jour 1

Quelle joie pour moi de revenir à cette vie d’avant qui m’avait tant manquée … Il s’agit ici du deuxième Symfony Live auquel j’assiste, et comme bien des séminaires, j’ai appris pas mal de choses, que j’ai notées, remises au propre, et vous fais partager !

La keynote de Fabien Potencier

Fabien est en forme pour cette nouvelle session ! Pour démarrer le show, il nous fait un retour d’expérience sur un bug qu’il a eu avec Twig. Après une mise à jour des tests des selectors css, il y a eu un problème de « match » avec une expression qui devait figurer dans le code, via preg_match(). Il commence alors une session de debug, pour avoir un détail plus explicite de la source du bug.
S’inclut alors un petit speech sur l’open source, qui consiste à contribuer pour :
– éviter aux autres ou à soi de refaire la même erreur
– éviter à quelqu’un, voire des centaines de gens de réfléchir de nouveau à un problème
Du coup, quick fix, on fork, on ouvre le code, on essaye de faire le changement, on écrit les tests, on les exécute, on pull request et on croise les doigts 🙂 …
Quand il s’agit d’un package, on peut aussi modifier le code et faire un link dans les vendors pour pouvoir tester plus efficacement.
Cependant, ici il s’agit d’une modification dans ExpressionLangage, qui est une sous-partie de Twig. On peut faire mieux que simplement corriger, ou faire une fonctionnalité qui peut poser problème avec d’autres cas de figure. Du coup, Fabien a poussé la réflexion plus loin … On est en PHP8.1 et on supporte PHP7 dans Twig, ce qui pose problème pour la contribution. La solution : travailler sur Twig4 pour moderniser le code. On ouvre les issues, entre autres : résolution des mismatches camelcase vs. snake_case, ne plus avoir de fonctions globales, analyse syntaxique …
En fin de compte : Twig sera intégré en tant que composant de Symfony, Twig4 sera alors nommé Twig6.2 en parallèle à la nouvelle version de Symfony, et changera de namespace.

Mon avis : une bonne mise en bouche, qui m'a poussée à la réflexion quand à certains de mes side projects.

Comment valider de la donnée – Marion Horteau

Ici, Marion nous fait un parallèle avec l’univers de Pokémon. Personnellement, je ne suis pas du tout fan, mais je me suis laissée tenter.
Pour rappel, un validateur est composé d’une contrainte, qui est appliquée à un objet, et elle est appliquée à un validateur. nativement, il y en a une bonne dizaine (que j’ai du bûcher par cœur pour ma certif …).
Mais certaines contraintes ne sont pas forcément liées à un validateur, comme UniqueEntity dans Doctrine.
On valide sur une propriété, dans un formulaire, dans une méthode (getter ou autre), ou sur une classe entière, et soit dans le code, soit lors d’un submit dans un formulaire.
Mais ici on veut faire de la validation dynamique …
Marion propose donc une solution basée sur une API avec des paramètres qui varient.
Dans le contrôleur, on alimente un objet Evolution, avec un attribut Callback. Comme les contraintes sont différentes, on peut en ajouter avec Assert\Collection. InContext permet de rendre la validation récursive.
Pour externaliser les contraintes, elle crée une interface pour les différents types de contraintes. Elle ajoute des tags dans la définition des services. La persistance se fait soit par Doctrine, soit par Json.

Mon avis : dommage que le contexte Pokémon me rebute, mais il s'agit ici d'un avis personnel. L'introduction sur les validateurs natifs est toutefois un peu longuette, j'aurais aimé qu'elle détaille plus en détails cette validation dynamique. Mais intéressant.

Du DDD avec API Platform – Mathias Arlaud, Robin Chalas

Rappelons-le, ce pattern permet une conception tactique et architecturale. le DDD ce n’est pas du RAD, la conception est pilotée par le métier, et ça ne permet pas de développer rapidement.
Petit rappel de l’archi hexagonale : les layers sont des couches où on écrit du code, ils obéissent à la règle des dépendances.
– Couche basse : domaine (models, events, repo, services …)
– Couche application : contient les services applicatifs pour traiter les use-case métier
– Couche infrastructure : porte vers le monde extérieur (controllers, bases de données, caches, vendors …), c’est la SEULE qui aura accès à du code tiers.
Les avantages :
– on préserve l’intégrité de notre domaine,
– le code est d’avantage testable,
– on est capable de repousser les décisions technologiques,
– le domaine est agnostique du contexte utilisé (ligne de commande, terminal, navigateur …)
Dans Api Platform, on peut configurer via ApiResource les opérations, via new Get() et new Post(). Mais ce n’est pas la bonne approche.
Le pattern command bus va nous permettre de reprendre complètement le main sur nos use case métier en faisant appel à nos domaines. Ça implique : Notion de commande (objet PHP) + un handler (service applicatif) + bus (trouver le bon handler pour une commande données) + deuxième bus (query) pour nous permettre de contrôler la manière dont on interagit avec notre domaine.
On manipule entre autres :
ItemOperations
CollectionOperations (ça dépend si on a un id dans le chemin) – supprimée dans ApiP3, tout est operation
– Notion de ChainProvide qui fait appel aux autres providers
– On peut créer nos propres providers, qui auront d’autres priorités
– Création de DataTransformers

Mon avis :  Haaa ! API Platform ! J'adooore ce framework, et je voulais vraiment en savoir plus sur le Domain Design Development. Je comprends ici que je n'ai pas fait le tour de ce framework, je pense à certains side projects que je définis en DDD, qui font appel à une API crée par ApiP, mais j'ai envie de remanier tout ça. Conférence très interessante qui m'a remise en question. Merci :D !

Doctrine, objet typé, et colonne JSON – Grégoire Pineau

Ici, on parle CMS, notamment celui utilisé par JoliCode. Composé de blocs, qui représentent chacun un objet.
L’objectif de ces blocs :
– éviter la duplication de code
– pouvoir stocker les blocs en BDD
– avoir un maximum d’objets PHP
– et si possible, un objet par type de bloc
Pour ce faire, deux solutions : utiliser l’héritage Doctrine, et stocker du PHP sérialisé.
Les options :
MappedSuperClass : Doctrine ne sait pas gérer les relations avec
Single Table (genre une première classe) avec une entité. On aura une entité mais la deuxième classe sera vide, si la première est remplie.
Class Table : crée une table par type de bloc, pas très pratique à administrer.
On rejette d’emblée le PHP sérialisé via serialize() et unserialize(), non interopérable ! Quand à l’objet stocké en JSON, c’est « so 2013 » …
La solution proposée c’est le Concept Unit Of Work, la donnée est encapsulée via l’EntityManger qui :
– contient le cache de toutes les entitées passées
– gère les écritures en BDD,
– gère les transactions,
– s’occupe de quel objet doit être insert / delete / update
– s’occupe de gérer les dépendances entre les objets
– fait des snapshots des objets qu’il rencontre pour faire un diff au moment du flush.
On utilise alors les event Doctrine, qu’on hooke dans notre code, avec un listener Doctrine.

Mon avis : Je vais me faire taper sur les doigts, mais je vais être franche. C'est assez pénible quand les slides sont passées vite-vite quand on ne connait pas vraiment le sujet (qui ici est spécifique, puisque retour d'expérience). J'ai eu beaucoup de mal à suivre. Personnellement, j'aurais préféré moins de contenu, mais peut-être plus d'explications.

Connaissez-vous vraiment JWT ? – Karim Pinchon

Pour rappel, JWT (prononcé abusivement « jot ») = Json Web Token.
C’est une solution simple et sécurisée, qui a une référence et une valeur.
La cryto, ça obéit à des régles : c’est mathématique, c’est de confiance, ça communique, ça passe sur un canal non sûr, et c’est CAIN.
ça implique :
– la signature numérique
– le chiffrement
– le hachage (intégrité et sens unique)
– Mac / HMac (intégrité et authentification)
– encodage (chaine de caractères)
Pour voir à quoi ça ressemble, il existe les outils token.dev et jwt.io
Après un tour des tokens existants (JWE, JOSE …), quelques conseils :
– attention à ne pas tout accepter côté serveur
– valider les claims
– préférer l’asymétrique
– utiliser une librairie existante et éprouvée
– ne vous battez pas pour révoquer les JWT (ça doit avoir un cycle de vie)
– éviter de logger les jetons (pour la confidentialité)

Mon avis : je suis peu familière avec le cryptage des données, car je n'en ai fait que rarement dans ma carrière, mais c'est bon à savoir.

Des composants Symfony méconnus qui valent le détour – Alexandre Daubois

  • HTMLSanitizer : prévu pour SF 6.1, expérimental.
    HTMLPurifier : garde au mieux l’arborescence des noeuds, supprime les données potentiellement dangereuses.
    Le Sanitizer reconstruit les données du HTML en extrayant les données safe de l’input, la structure de base peut être perdue. Le comportement est défini par HTMLSanitizerConfig. Il peut forcer les https pour les URL, autorise les Schemes, autorise les media hosts.
  • STRING : arrivé en SF 5.0, il permet de faire de la manipulation simplifiée de codepoints, par exemple des emojis : combinaisons possibles pour faire des couleurs de peau, crée des chaines par contructeur (CodePointString, UnicodeString, ByteCodeString …), crée des chaines par factories.
  • OptionsResolver (remplace SPL) : valeurs obligatoires, callbacks, etc … , normalisation pour résoudre les options.
  • L’internationalisation : ce n’est pas seulement de la traduction (dates, nombres, monnaies, etc …), INTL depuis SF 2.3 (mai 2013).
    International Component For Unicode : quelques entreprises bien connues l’utilisent. Permet de formater : les langues, les locales, les monnaies, les timezones (reprises par les forms, qui vont puiser dans ce composant.)
Mon avis : je connaissais déjà OptionsResolver, mais c'est bien sympa d'en connaitre d'autres ! :D ...

Un fabuleux mapping avec Leaflet.js !

Aujourd’hui, pour changer, je vous parlerai de … front-end ! Bien que plus dévolue back, j’avais envie de faire d’une pierre deux-coups et de réaliser un joli mapping de mon monde Minetest.

Avec Minetest, c’est assez facile de générer des fichiers image qui retracent en 2D l’univers généré dans le jeu, avec minetestmapper. A partir de là, les plus créatifs peuvent s’amuser.

Pour la petite histoire, je suis en fait tombée sur le plan interactif du serveur Minetest LinuxForks, qui est juste splendide, et j’ai eu vraiment envie de me lancer ce défi.

Au commencement, une map qui rame à mort !

Du coup, j’ai intégré ce fichier dans une carte de base. Le code est simple, j’intègre Leaflet.js dans ma page web, et j’y intègre quelques markers. La bibliothèque, je la connaissais déjà, car je l’avais déjà intégrée pour l’outil d’un de mes clients BTP, pour y localiser les chantiers en cours. Mais Leaflet, c’est vraiment l’outil qui permet de créer des cartes, sans forcément qu’elle soit « terrestre », une « mappemonde ». Donc pas mal privilégiée par les geeks gamers.
Voilà grosso modo le code de base du premier jet que j’ai intégré dans mon index (j’y ai intégré après un div vide appelé map, bien entendu):

var map = L.map('map', {
    crs: L.CRS.Simple,
    center: [500, 500],
    scale: function (zoom) {
        return Math.pow(2, zoom);
    },
    zoom: function (scale) {
        return Math.log(scale / 256) / Math.LN2;
    },
});
 
var bounds = [[0,0], [2000,2000]];
var image = L.imageOverlay('map.png', bounds).addTo(map);
// Spawn
var spawn = L.latLng([971.5, 1156.5]);
L.marker(spawn).addTo(map).bindTooltip('Spawn Station', {sticky: false, direction: 'top'});
// Maison de Jym
var jymHome = L.latLng([972, 1137]);
L.marker(jymHome).addTo(map).bindTooltip('Maison de Jym', {sticky: false, direction: 'top'});
 
map.setView( [971.5, 1156.5], 3);

C’est déjà pas mal. La définition de la map en crs permet de générer une map personnalisable, le niveau de zoom est correct, on peut naviguer pépère. Sauf que la carte, qui est grande, met pas mal de secondes à charger, c’est lourd, très lourd. Et ça, c’est un gros souci. Sans compter que la map devient floue à un certain niveau de zoom avancé. A revoir, donc !

Le tiling, solution miracle !

Et puis j’apprends que Leaflet intègre très bien des briques d’images. A la base, on peut sans souci utiliser un coup d’imagemagick pour ce faire et recoller les morceaux, chose que la bibliothèque fait très bien. Donc pile ce dont j’ai besoin !

Pour créer les briques, il y a un script existant qui gère Leaflet. Il est en Python et s’appelle gdal2tiles-leaflet. Ne pas oublier avant de faire un petit sudo apt install python-gdal (pour les utilisateurs d’Ubuntu) et éventuellement installer python si ce n’est déjà fait, juste avant de l’utiliser.

Voici la commande que j’ai lancée :
./gdal2tiles.py -l -p raster -z 0-10 -w none ../map.png ../tiles
Et j’ai attendu quelques bonnes minutes pour que toutes les briques soient générées. C’est un peu long mais ça vaut le coup. Ne pas oublier l’option -p raster car on en aura besoin par la suite, et surtout l’option -l qui définit spécialement des briques adaptées pour leaflet. J’ai demandé un niveau de zoom variable de 0 à 10, pour bien pouvoir avoir chaque détail de ma carte.

Gérer le tiling dans Leaflet

Maintenant qu’on a généré les briques, il faut pouvoir les assembler. Là encore, après pas mal de recherches, j’ai pu trouver de quoi satisfaire ma faim.

Bien avant, il faut intégrer la librairie rastercoords, pour pouvoir faire la correspondance des briques au format « raster » (l’option que nous avions vu plus haut). Et ainsi, avec ce code, vous pouvez déjà disposer d’une map sympa :

;(function (window) {
    function init (mapid) {
        var minZoom = 0
        var maxZoom = 9
        var img = [
            38192, // original width of image
            29792  // original height of image
       ]
    // create the map
    var map = L.map(mapid, {
       minZoom: minZoom,
       maxZoom: maxZoom
    })
 
    var rc = new L.RasterCoords(map, img)
    map.setView(rc.unproject([22000, 15450]), 9)
    L.control.layers({}, {
        //@todo
    }).addTo(map)
 
    L.tileLayer('./tiles/{z}/{x}/{y}.png', {
        noWrap: true,
        attribution: 'Creation Amelie DUVERNET aka Amelaye <a href="http://minetest.amelieonline.net">Projet Amelaye In Minerland</a>'
        }).addTo(map)
    }
 
    init('map')
}(window))

Des markers jolis et dynamiques

Nous avons la carte, il faut maintenant y ajouter les markers. Pour ce faire, vous avez besoin de :
– La librairie font-awesome (on en a besoin pour extra-markers)
– La librairie leaflet-extra-markers

J’ai crée deux fonctions, la première, layerGeo qui permet de récupérer les points définis dans mon fichier geojson.js

function layerGeo (map, rc) {
  var layerGeo = L.geoJson(window.geoInfo, {
    // correctly map the geojson coordinates on the image
    coordsToLatLng: function (coords) {
      return rc.unproject(coords)
    },
    // add a popup content to the marker
    onEachFeature: function (feature, layer) {
      if (feature.properties &amp;&amp; feature.properties.name) {
        layer.bindPopup(feature.properties.name)
      }
    },
    pointToLayer: function (feature, latlng) {
      return L.marker(latlng, {
        icon: feature.properties.id
      })
    }
  })
  map.addLayer(layerGeo)
  return layerGeo
}

Ainsi qu’une autre, qui permet de trouver les « frontières » de la carte, et également d’afficher les coordonnées d’un emplacement au hasard cliqué :

function layerBounds (map, rc, img) {
  // set marker at the image bound edges
  var layerBounds = L.layerGroup([
    L.marker(rc.unproject([0, 0])).bindPopup('[0,0]'),
    L.marker(rc.unproject(img)).bindPopup(JSON.stringify(img))
  ])
  map.addLayer(layerBounds)
 
  // set markers on click events in the map
  map.on('click', function (event) {
    // to obtain raster coordinates from the map use `project`
    var coord = rc.project(event.latlng)
    // to set a marker, ... in raster coordinates in the map use `unproject`
    var marker = L.marker(rc.unproject(coord)).addTo(layerBounds)
    marker.bindPopup('[' + Math.floor(coord.x) + ',' + Math.floor(coord.y) + ']').openPopup()
  })
  return layerBounds
}

Du coup, on revient sur notre code qui affiche la map et on corrige la ligne L.control.layers pour appeler nos fonctions :

L.control.layers({}, {
  'Bounds': layerBounds(map, rc, img),
  'Info': layerGeo(map, rc)
}).addTo(map)

Maintenant passons aux choses sérieuses, la définition de nos coordonnées. Et là, on va passer nos jolis markers, ainsi que les points qui nous intéressent, et tout ceci va se passer au niveau d’un nouveau fichier geojson.js :

;(function (window) {
    // Markers
    var spawnStation = L.ExtraMarkers.icon({
        icon: 'fa-anchor',
        markerColor: 'red',
        shape: 'star',
        prefix: 'fa'
    });
 
    var metroStation = L.ExtraMarkers.icon({
        icon: 'fa-subway',
        markerColor: 'blue',
        shape: 'circle',
        prefix: 'fa'
    });
 
    var castle = L.ExtraMarkers.icon({
        icon: 'fa-dungeon',
        markerColor: 'violet',
        shape: 'square',
        prefix: 'fa'
    });
 
    // etc ...
 
    // geoJson definitions
    window.geoInfo = [
        {
            'type': 'Feature',
            'properties': {
                'name': 'Spawn Station',
                'id': spawnStation
            },
            'geometry': {
                'type': 'Point',
                'coordinates': [22087, 15321]
            }
        },
        // Castles
        {
            'type': 'Feature',
            'properties': {
                'name': 'Chateau dans le ciel',
                'id': castle
            },
            'geometry': {
                'type': 'Point',
                'coordinates': [22088,14112]
            }
        },
        {
            'type': 'Feature',
            'properties': {
                'name': 'Chateau Royal',
                'id': castle
            },
            'geometry': {
                'type': 'Point',
                'coordinates': [22229,15299]
            }
        },
        {
            'type': 'Feature',
            'properties': {
                'name': 'Chateau Amelaye',
                'id': castle
            },
            'geometry': {
                'type': 'Point',
                'coordinates': [22060,15402]
            }
        }, // etc ...
    ]
}(window))

Là, j’ai pas mal galéré car il faut injecter les markers personnalisés dans un fichier qui doit être scrupuleusement rigoureux, car geojson est une norme. J’ai donc passé les variables qui correspondent à la définition des « templates de markers » dans la propriété id. C’est caduque, bricolé, mais ça marche.

Et voilà le résultat (disponible en ligne) :

Nous voici maintenant avec une map rapide à charger, qui intègre pas mal de points personnalisables. Il reste pas mal de choses à faire, j’ai bien envie d’utiliser une base de données pour créer une API, voire une base ElasticSearch qui se chargera de générer le fichier geojson, mais pour l’instant je n’ai pas décidé de la suite. Qu’en pensez-vous ?

Voici pour plus de détails le rendu final sur mon Github.