A castle made of bazaar

I've accumulated quite a lot of nerd automations in my tech stack, I'll try to give an idea of what I've done up to this day

For the Cloudron instance I run

  • A cron job that monitor disk usage, using bash +Cloudron API, it will alert me via email and ntfy when any folder usage > 75%.
  • A cron job that checks if some apps time out and restart them via Cloudron API. In bash too.

DNS Monitoring

  • I take a snapshot of my Hetzner DNS configs every 5 minutes and watch frequently for diffs using Changedetection.

Uptime monitoring

  • I'm using Uptime Kuma to monitor the status pages of several services/APIs I'm relying on (Dropbox, OpenAI, Mistral AI, ...) as well as my own self-hosted apps. I get ntfy alerts in case any is failing.

Feed generators

Files Syncing

  • A cron job syncing my .torrent files from Dropbox to QBittorrent, using rclone
  • A cron job syncing my downloaded audiobooks to AudioBookShelf, using rsync.
  • A cron job syncing my downloaded ebooks to Calibre, by uploading the files to Calibre API, using bash.

Music management

  • A cron job syncing my downloaded music (torrent) to my main Music Library, using rsync.
  • A cron job verifying the quality of my Music Library content using mp3val and reporting for corrupted files via ntfy.
  • A cron job verifying the quality of my Soulseek download folder using mp3val and only moving the verified ones to my Music Library.
  • A user script integrating with ListenBrainz/LastFM scrobbler for when I listen to live radios from RTBF (they use radioplayer technology).
  • A user script to filter automatically the search results within Soulseek (web version running on Cloudron).

Photos management

  • A cron job that syncs my photos library between Dropbox and Immich, using rclone, but only for pics and videos under a certain size.
  • A cron job that generate Immich album only made of pictures of specific persons.
  • Scripts that I run ad-hoc, using ffmpeg, to compress my pictures, videos, fix their EXIF date at need.
  • Scripts that I run ad-hoc, using Syncthing, to remove all pics/videos from my Phone (WhatsApp and Camera folders) and move them to Dropbox, before I compress and triage them. Anything on Dropbox is then sync to Immich, so that's how I keep my phone clean.

Emails management

  • A script which checks for invoices (with attachments or downloadable links) in my emails and sends them to my Dropbox forwarding email, which in turn backups those attachments in a specific folder which can be treated.

Freelancer paperwork management

  • I have several scripts to rename my receipts and invoices with the right date, invoice nr, provider and organize them per year/quarter/month, it's done in PHP.
  • A user script to fill my timesheet automatically based on my declared days off.

Web curation and bookmark management

  • A cron job that will browse my recent Shaarli shares and, when needed, add tags, HN Thread links, Web Archive link, and a summary. It's done in Python.
  • A cron job that will browse my Miniflux unread entries and mark as read the ones that I will probably not care about. using Mistral AI.
  • A cron job that will browse my Miniflux unread entries and send me an email with the unread entries summarized and grouped by feed, a bit like feu Subworthy.com (by Phil Stephens) was doing around 2022.
  • A user script that will add TLDRs buttons at the bottom of my Miniflux entries, so I can get a quick summary generated by Mistral AI, at need.
  • A user script to warn me on any website if there is a Hacker News thread for the page I visit.
  • A user script to highlight and extract all top links from the current Hacker News thread.

LinkedIn management

  • A user script that adds a reply generator in LinkedIn conversations, using Mistral AI.

Obsidian Backups

  • I'm using aicommit2 called from Obsidian Git plugin to generate meaningful commit messages about what is being backed up.

This looks quite a lot, and that's not all.


redacted.sh: share your logs, not your secrets

Quick post. Sometimes it is necessary to share logs on public issue trackers, forums... and wanting to protect secrets, tokens, IPs is normal.

I've cooked my own minimal bash script for this quest, which I've just added to my public shared snippets : https://gitea.zoemp.be/sansguidon/snippets/raw/branch/main/redacted.sh

#!/usr/bin/env bash

default_rules=(
  's/[0-9]\{1,3\}\(\.[0-9]\{1,3\}\)\{3\}/<REDACTED_IP>/g'
  's/\b[a-zA-Z0-9._-]\+\.[a-zA-Z]\{2,\}\b/<REDACTED_DOMAIN>/g'
  's/\b[A-Za-z0-9+\/=]\{20,\}\b/<REDACTED_TOKEN>/g'
  's/\(password=\)\S\+/\1<REDACTED_PASS>/g'
)

rules=()
while [[ $1 =~ ^s/ ]]; do
  rules+=("$1")
  shift
done
[[ ${#rules[@]} -eq 0 ]] && rules=("${default_rules[@]}")

sed_expr=()
for r in "${rules[@]}"; do
  sed_expr+=( -e "$r" )
done

# If files are passed, process them to stdout.
# If none, read from stdin to stdout.
if [[ $# -gt 0 ]]; then
  sed "${sed_expr[@]}" "$@"
else
  sed "${sed_expr[@]}"
fi

Feel free to reuse, copy, extend, contact me to give feedback! πŸ’š

πŸ’Œ The best way to get in touch is via my email morgan at zoemp dot be. You can also follow me on the Fediverse / Mastodon at @sansguidon@mamot.fr. I speak (a lot) French, English and a bit of Dutch.


Scrobbling RTBF live radios to Last.fm and ListenBrainz with userscripts

Finding a way to scrobble live RTBF radios like Classic 21 and Classic 21 Metal to Last.fm and ListenBrainz was not as straightforward as it should have been.

I've stopped Spotify for a long time and I have switched to Navidrome and Jellyfin/Finamp on Android, which embark scrobblers for Last.fm and ListenBrainz, luckily for me.

However in the universe of music scrobblers, I had yet to find how to scrobble my favorite local radios, RTBF Classic21 and Classic21 Metal (https://www.rtbf.be/radio/liveradio/classic21_metal) πŸŽΈπŸ‡§πŸ‡ͺ.

They integrate a player compatible with an awesome web-scrobbler extension (https://github.com/web-scrobbler) whose purpose is to work for live radios web players. Sadly I couldn't make it work with those radios despite history is showing it is supposed to have worked years ago. There is an integration for RTBF live radios at https://github.com/web-scrobbler/web-scrobbler/pull/2377/files - it was supposed to work for Classic 21 as well, unfortunately the code seems obsolete now and I couldn't ship a working fix for this. So I paused a bit, and gave up, ... not long enough πŸ˜‚.

I had the idea of running Shazam in the background and send it findings to some backend for scrobbling my songs, and I thought it would be very epic and complicated. I did try anyway the Shazam web extension and noticed that it would mismatch the song and artist displayed on the radio website most of the time. This is concerning. Why is that? I do not know yet, so just in doubt I have contacted the website admin for RTBF about this.

Anyway, diving back into the code and opening Dev Tools in Brave, helped me discover an interesting URL: https://core-search.radioplayer.cloud/056/qp/v4/events/?rpId=29 which returns the songs being played for this radio, I mean the recent ones, the next one and the one currently playing!

Then I decided to try hacking my own solution for this problem. It wouldn't work with Navidrome nor with a chrome extension, I wanted a simple minimalist hack. I'm used to tweak websites UX with Tampermonkey and I'd to give a try. The result is https://gitea.zoemp.be/sansguidon/snippets/raw/branch/main/tampermonkey/rtbf_scrobbler.js.

I’ve adopted ListenBrainz as an alternative to Last.FM, but I still can’t fully let go of it. That’s why my userscript supports both, and it's hackable for those who want to extend it πŸ˜‰

I've tested it on:

And it should likely be compatible with most radios at:

My scrobbling profiles are https://www.last.fm/user/SansGUidon and https://listenbrainz.org/user/SansGuidon/.

Feel free to share, copy, reuse and provide feedback! I'll keep this post updated if RTBF radio answers my questions πŸ˜‰ or if I get interesting feedback. I've also mentioned this post in https://github.com/web-scrobbler/web-scrobbler/discussions/5327.

πŸ’Œ The best way to get in touch is via my email morgan at zoemp dot be. You can also follow me on the Fediverse / Mastodon at @sansguidon@mamot.fr. I speak (a lot) French, English and a bit of Dutch.


LLMs – Chat Interfaces vs. Raw APIs: Why I Choose Conversations

I recently read Max Woolf's post on LLM use, where he explains why he rarely uses generative LLMs directly, preferring raw APIs for control. It's an interesting take, but I fundamentally disagree. For me, chat interfaces aren't just convenientβ€”they’re an essential part of understanding.

LLMs are more than code generators. They are interactive partners. When I use ChatGPT, Mistral, or Copilot in chat mode, it's not just about fast results. It's about exploring ideas, challenging my thinking, and refining concepts. The back-and-forth, the debugging, the reflectionβ€”it’s like pair programming with a tireless assistant. If I need to test an idea or explore a concept, the chat interface is perfect for that: it's always available, from any device, no API or IDE needed.

Max argues APIs allow for more fine-tuningβ€”system prompts, temperature control, constraints. Sure. But in a chat session, you can iterate, switch topics, revisit past decisions, and even post-mortem the entire conversation, as a way to learn from it and log your decisions. And yes, I archive everything. I link these sessions to tickets in TickTick to revisit ideas. Try doing that with an API call.

The chat interface is a workspace, not a magic wand. It’s where you can think, break things, fix them, and learn. Isolating interactions to API calls removes that context, those learning moments. To me, that’s missing the point.

APIs are fine for deterministic output. But I prefer the chaos of conversationβ€”it forces me to engage deeper, explore failures, and actually think. That’s why I don’t just use LLMs to generate. I use them to reason. Not just for hard skills, but soft skills too.

Mentioned in https://lukealexdavis.co.uk/posts/apis-vs-chatbots/


Ghost – not fitting as WordPress replacement

I've a Cloudron instance where I experiment various tools. This time, it was Ghost, as a replacement to WordPress, especially as Ghost was acclaimed by some folks I follow.

The good parts

  • Simple and modern.
  • The migration of content from WordPress, works great!

The worst parts

  • I couldn't find a good theme for my taste.
  • Distinct UIs for browsing your blog and quickly editing your posts. Far more complicated than in WordPress. If I want separate tools for editing and browsing content, then I just go with static site generators πŸ™‚
  • The extreme minimalism and simplicity makes it less appealing for me, I like to customize the content and web administration UI, I feel out of control here. For instance I dislike the appearance of my content in Ghost.

Conclusion for now

  • Still looking for alternatives to WordPress. But likely thinking of scripting my own thing.

Mastodon