Ideenquelle

Ideenquelle ou la Source des idées en Français. Il s’agit juste d’un lieu de partage.

Art-toi

Courts exercices/invitations pour décrypter les tableaux (moins) connus.

Hexo-feed

hexo-feed is a plugin for Hexo static site generator that builds RSS, Atom and JSON Feed for your content.

Pensée du jour

Envie de rien, envie de tout. Mais surtout de rien.

L'homme et l'oiseau

Il s’agit du magazine édité par la Ligue Royale Belge pour la Protection des Oiseaux (LRBPO). J’ai reçu un exemplaire lors d’un achat chez eux.

Je ne suis pas assez fan ni convaincu pour m’abonner. Par contre !

Par contre, c’est agréable à lire. Il y a de l’espace, du vide. Les photos sont là pour être vues (en même temps, quand on parle animaux, il vaut mieux avoir de jolies photos). Le texte n’est pas spécialement aéré. La typographie est assez commune.

Ce qu’il y a, c’est du vide. Les marges sont énormes, de l’ordre de 4 à 5 cm. C’est reposant. Vraiment reposant.

Modification hexo

Je viens d’effectuer quelques changements sur le blog, propulsé par hexo. J’avoue que cela m’a pris un peu la tête.

Nouveau layout

Par défaut, hexo prévoit trois layouts.

Il est possible de prévoir de nouveaux layouts. Pour cela, il faut créer un fichier .md dans le dossier /scaffolds. Pour faire simple, un copier/coller de post.md vers link.md permet d’avoir un bon départ :

draft = false
+++
title = '{{ title }}'
date = '{{ date }}'
tags = []
draft = false
+++

Je l’ai modifié pour avoir un champs supplémentaire :

draft = false
+++
title = '{{ title }}'
date = '{{ date }}
layout : {{ layout }}
link = 
draft = false
+++

Rien de bien sorcier en somme.

Maintenant, j’ai modifié mon template /themes/mon-template/layout/_partial/article-excerpt.ejs pour que, lors de la génération de mon résumé d’article, il fasse apparaitre clairement au lecteur qu’il s’agisse d’un lien au moyen d’une icone.

<div class="blog-post">

  <div class="blog-header separate">


    <% if(item.layout == "thought"){ %>
      <blockquote>
        <%- item.content %>
      </blockquote>
    <% } else { %>
      <!-- Title -->
      <h2 class="blog-post-title">
        <% if(item.layout == "link") { %>
          <i data-eva="link-2-outline"></i> <a href="<%- item.link %>"><%- item.title %></a>
        <% } else { %>
          <%- item.title %>
        <% } %>
        </h2>
    <% } %>

Le code n’est pas complet. Il manque la fin de la page. Mais l’idée n’est pas de recréer un tutorial pour créer un thème. L’idée est juste de partager des tips&tricks que je n’ai pas trouvé facilement/simplement.

Article avec une fin de vie

J’ai également créé des posts liés à mon humeur. Toutefois, l’idée n’est pas que ces posts soient éternelles. J’ai envie de leur donner une date limite d’utilisation. J’avoue que j’ai galéré à mettre cela en place. La documentation n’est pas bien faite et il y a peu d’exemples sur ce type de modification. J’ai péché : j’ai fini par utiliser Gemini qui, à mon grand étonnement, a très bien répondu (mieux que ChatGPT sur un autre projet).

Ma première idée était de mettre une variable dans ma configuration indiquant la date limite de vie (30 jours). Lors de la génération des pages, si le layout est d’un type spécifique et si la date est passée, je ne l’affiche pas. Cela se fait dans le template. Il faut gérer la date (et là, j’ai sué, même si c’est affreusement simple rétrospectivement mais la documentation de hexo est trop faible sur ce point-là pour des néophytes) :

<% var diffInDays = (new Date()  - new Date(item.date)) / (1000*60*60*24) %>

<% if(item.layout == "thought" && !(diffInDays > config.lifespan_thought ) ){ %>

<% } else { %>
    <%- partial('_partial/article-excerpt', {item: item, index:true}) %>
<% } %>

Ce qui m’a entravé l’esprit, c’est que hexo permet d’utiliser les dates via moment.js mais que dans le template, la plupart des méthodes ne fonctionnent pas. Bref, j’ai trouvé une solution.

L’idée est plaisante. Toutefois, le post existe toujours en direct. Donc je veux restreindre la création même. Pour cela, il faut intervenir au niveau de la génération. Cool ! Et je fais comment ? J’ai donc créé un dossier /scripts à la racine du projet puis un fichier unpublish_expired_post.js :

const moment = require('moment')
const fs = require('hexo-fs')
const path = require('path');

'use strict';

function deleteFolderRecursive(folderPath) {
  if (fs.existsSync(folderPath)) {
    fs.readdirSync(folderPath).forEach((file) => {
      const curPath = path.join(folderPath, file);
      if (fs.lstatSync(curPath).isDirectory()) {
        deleteFolderRecursive(curPath);
      } else {
        fs.unlinkSync(curPath);
      }
    });
    fs.rmdirSync(folderPath);
  }
}

// If a Post is expired,
//  - set the parameter punlished to false
//  - delete the public file
//  - remove the Post from the actual generating list

hexo.extend.filter.register('before_generate', function () {
  const Post = hexo.model('Post');
  if (!Post) return;

  const now = new Date();

  // Identify the expired Posts
  const expiredPosts = Post.find({
    end_date = '{ $lt: now } // Warehouse allows the use of query operators.
  });

  if (expiredPosts.length === 0) return;

  expiredPosts.forEach(post => {
    // Safety check for the date
    const endDate = new Date(post.end_date);
    if (isNaN(endDate)) return;

    // Disable the post for the actual generating process.
    post.published = false;

    // Remove it from the model .
    Post.removeById(post._id);

    hexo.log.info(`Post expiré masqué : ${post.title} (expiré le ${moment(post.end_date).format('YYYY-MM-DD')})`);


    // Remove the published file
    try {
      const postFolder = path.join(hexo.public_dir, post.path);

      deleteFolderRecursive(postFolder);
      hexo.log.info(`Post expiré supprimé: ${post.title} `);

    } catch (err) {

      hexo.log.warn(`Impossible de supprimer ${post.path}: ${err.message}`);
    }

    // Full path to the source file (.md)
    const fullPath = path.join(hexo.source_dir, post.source);

    // Set the status to unpublished
    if (fs.existsSync(fullPath)) {
      let content = fs.readFileSync(fullPath);

      // Remplace published: true to false, or add the line if missing
      if (content.includes('published: true')) {
        content = content.replace('published: true', 'published: false');
      } else if (!content.includes('published:')) {
        // Insert after the first "+++"
        content = content.replace('+++', '+++\npublished: false');
      }

      fs.writeFileSync(fullPath, content, 'utf8');
      hexo.log.info(`Fichier source mis à jour (Draft) : ${post.source}`);
    }

  });
});

J’ai sorti l’artillerie lourde :

J’ai également rajouté un autre script (set_endDate.js) pour que certains types d’articles aient automatiquement une date de fin ajustée selon la configuration de hexo:

'use strict';

const moment = require('moment')
const fs = require('hexo-fs')

hexo.on('new', function(data){

    // Retrieve the parameter from _config.yml (or set a default value).
    const settings = hexo.config.lifespan_settings || {}
    const layoutMatch = data.content.match(/layout:\s*(\w+)/);
    const currentLayout = layoutMatch ? layoutMatch[1] : 'post';

    // Verify if the actual layout has a specific lifespan
    if (!settings.hasOwnProperty(currentLayout)) {
        return;
    }

    // Retrieve the lifespan for the layout used for the new post
    const lifespan = settings[currentLayout]


    // calculate the end date of the post
    const endDate = moment().add(lifespan,'days').format('YYYY-MM-DD HH:mm:ss');

    // replace 'end_date' default by the calculated one
    const newContent = data.content.replace(/end_date = '2400-12-31 01\:00\:00/g, 'end_date = ''+endDate);

    // write the change in the file
    fs.writeFile(data.path, newContent, function(err){
        if (err) {
            console.log("Error when writing 'endDate' variable");
        } else {
            console.log("'endDate' variable added");
        }
    });


});

Les systèmes avant les outils

Je l’ai lu il y a tellement longtemps. Il attend d’être partagé depuis autant de temps. Pour moi, l’essentiel va aux humains : réaliser des tâches simples (et là, chacun son point de vue) pour créer de la valeur envers les autres (idéalement du bonheur). Tout est important, même si le côté humain, qui arrive en bout de ligne, est primordial.

widefrog

widefrog est un programme permettant de télécharger des vidéos sur des plateformes de streaming. Intrinsèquement, il ne s’agit pas de piratage car widefrog n’outrepasse pas les accès demandés par les services. Autrement dit, si vous souhaitez récupérer des vidéos sur auvio.be (lié à la télévision belge francophone), vous devez avoir un compte sur le site et avoir une IP belge. widefrog permet donc juste de récupérer les vidéos facilement. widefrog est diffusé sur le forum de videohelp.

#Outils préalables Pour utiliser widefrog, il faut quelques outils préalables :

  1. Update/upgrade le système sudo apt-get update && sudo apt-get upgrade

  2. Python, ffmpeg, mkvmerge sudo apt-get install python3 python3-pip unrar zip unzip ffmpeg mkvtoolnix mkvtoolnix-gui mediainfo mediainfo-gui aria2 Dans le guide trouvé sur le forum, il recommande également d’installer curl, git, nano, vlc, mpv et asciinema. Autant les premiers sont déjà installés, autant vlc et mpv sont deux programmes au même usage.

  3. N_m3u8DL-RE

curl -kLO https://github.com/nilaoda/N_m3u8DL-RE/releases/download/v0.3.0-beta/N_m3u8DL-RE_v0.3.0-beta_linux-x64_20241203.tar.gz

## (Debian 13/Trixie does not allow to unpack/untar directly into the "/usr/local/bin/" DIRectory);

# Check the package is OK;
gunzip -tv vimeo-dl_0.2.0_linux_amd64.tar.gz
# Check what is inside the TAR.GZ archive;
tar -tvvf N_m3u8DL-RE_v0.3.0-beta_linux-x64_20241203.tar.gz
# Unpack;
tar -xvf N_m3u8DL-RE_v0.3.0-beta_linux-x64_20241203.tar.gz N_m3u8DL-RE
# Move to "/usr/local/bin/";
sudo mv N_m3u8DL-RE /usr/local/bin/
# Make the BInary file "EXEcutable;
sudo chmod a+rx /usr/local/bin/N_m3u8DL-RE
# List the file;
ls -ilha /usr/local/bin/N*
# Check the version
N_m3u8DL-RE --version
  1. mp4decrypt
curl -kL https://www.bok.net/Bento4/binaries/Bento4-SDK-1-6-0-641.x86_64-unknown-linux.zip -o ~/Downloads/Bento4-SDK-1-6-0-641.x86_64-unknown-linux.zip
sudo unzip -j Bento4-SDK-1-6-0-641.x86_64-unknown-linux.zip 'Bento4-SDK-1-6-0-641.x86_64-unknown-linux/bin/*' -d /usr/local/bin/
ls -ilha /usr/local/bin/
mp4decrypt
mp4info
  1. shaka-packager
sudo curl -kL https://github.com/shaka-project/shaka-packager/releases/download/v2.6.1/packager-linux-x64 -o /usr/local/bin/shaka-packager
sudo chmod a+rx /usr/local/bin/shaka-packager
shaka-packager --version

L’idée est de pouvoir utiliser les programmes directement depuis n’importe quel dossier, juste en les appellant par leur nom.

#Installation de widefrog Quand c’est fait, il faut encore récupérer widefrog. La version à l’heure actuelle est la 3.2. Idéalement, extraire le fichier dans un dossier propre à widefrog. Pour la suite et afin d’éviter les soucis de version de packages Python, on active un environnement de travail :

pip install virtualenv
virtualenv venv
venv\Scripts\activate

On installe les dépendances :

#windows
FOR /F %k in (requirements.txt) DO ( if NOT # == %k ( pip install %k ) )
#linux
grep -v '^#' requirements.txt | xargs -n 1 pip install
#macos
grep -v '^#' requirements.txt | xargs -n 1 pip3 install

Et on peut également mettre à jour urllib3 (pas certain que ce soit utile):

pip install urllib3 --upgrade

On octroye des droits d’exécution aux parties de widefrog :

sudo chmod +x "terminal/*"

L’installation est normalement finie.

#Utilisation de widefrog Pour utiliser widefrog, il faut veiller à avoir l’environnement actif. Pour cela, quand nous sommes dans le dossier de widefrog, il faut utiliser la commande source myvenv/bin/activate. Pour sortir de l’environnement, il faut utiliser : deactivate

Première utilisation

Pour la première utilisation, il faut créer la configuration via

python widefrog.py
[INFO] The app_files\config.json file was created. Edit the file and run the program.

Avant d’éditer la configuration, vous pouvez utiliser les commandes suivantes pour en savoir plus :

python widefrog.py --help
python widefrog.py --config

Utilisation

Je reprends ici l’utilisation dont j’ai besoin, càd pour le site auvio. Une IP belge est nécessaire ainsi qu’un compte au service auvio. Je recopie les exemples données sur le forum qui permettent de comprendre comment cela fonctionne. :

#video
python widefrog.py "https://auvio.rtbf.be/media/attraction-attraction-s01-3018437"
python widefrog.py "https://auvio.rtbf.be/emission/titane-27377"
#audio
python widefrog.py "https://auvio.rtbf.be/media/un-jour-dans-le-sport-14-aout-2004-3164197"
#livestream video
python widefrog.py "https://auvio.rtbf.be/live/roland-garros-2024-31-mai-direct-tipik-526661"
#livestream audio
python widefrog.py "https://auvio.rtbf.be/chaine/classic-21-5" --query=:2::2
#list
python widefrog.py "https://auvio.rtbf.be/widget/19164" --query=:5::7
python widefrog.py "https://auvio.rtbf.be/widget/22508?context%5BprogramId%5D=8340" --query=:2::4
python widefrog.py "https://auvio.rtbf.be/emission/la-theorie-du-y-11043/bonus" --query=:6::7
python widefrog.py "https://auvio.rtbf.be/emission/pandore-20618" --query=:5::8
python widefrog.py "https://auvio.rtbf.be/chaine/musiq3-7" --query=:2::3
#series
python widefrog.py "https://auvio.rtbf.be/emission/le-cactus-4043" --query=2017:180:2018:5
python widefrog.py "https://auvio.rtbf.be/emission/l-art-du-crime-27164" --query=3:2:4:2

Il faut savoir que widefrog accepte également les fichiers en entrée. Les fichiers seront composés pour chaque ligne du lien à télécharger.

NativeMindExtension, LLM maison

NativeMind est une extension pour Chrome & Firefox qui permet d’utiliser Ollama dans son navigateur. L’avantage : tout est dans le navigateur. Rien ne passe par le cloud.

Naturellement, la rapidité dépend du modèle de Ollama qui est pris et de votre machine.

On n’a rien sans rien.

goaway, alternative à PiHole

Juste pour information : il existe une alternative à PiHole : goaway. C’est écrit en Go, récent et graphiquement très similaire à PiHole (du moins la page de garde).

Deployer hexo en FTP

J’utilise le moteur hexo pour mon blog statique. Je n’ai pas d’avis sur le côté NPM (si ce n’est que c’est encore un truc à maintenir à jour). Je ne l’utilise pas ailleurs.

hexo propose une ligne de commande pour déployer le blog sur Git, Heroku, Netlify, via Rsync, … et FTP. Mon hébergeur propose cette solution (oui, c’est un module de base que j’ai actuellement).

La documention présente comment faire. Les données doivent bien être rajoutées dans votre _config.yml. A priori, c’est tout en bas). Vous pouvez après générer et déployer en une commande : hexo generate --deploy ou hexo deploy --generate. Si vous êtes un gros flemmard (comme moi), vous pouvez également rajouter une ligne dans votre crontab (pour rappel, crontab -e pour le modifier):

0 3 * * 0 cd /votredossieravecvotrehexo/ && hexo generate --deploy

Personnellement, j’ai mis une mise à jour une fois par semaine pendant la nuit.