Files
alembic/pipeline/lib/gen-djmix-playlist.sh
T
andrew 41ef26a40b Harden gen-djmix, gen-vgm, strip-mb-tags, notify-telegram under set -euo pipefail (R1)
Adds strict mode to four maintenance scripts, with guards so expected non-zero
exits (empty beet queries, a missing config, a curl timeout) log/skip instead
of aborting: gen-djmix bails cleanly if djmix-albums.txt is absent and tolerates
a bad single query; gen-vgm tolerates an empty query; strip-mb-tags quotes its
path arg and best-efforts the trailing beet update; notify-telegram guards curl
so a network error still reaches its explicit "send failed" branch.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-10 10:43:37 -06:00

69 lines
2.1 KiB
Bash
Executable File

#!/bin/bash
# gen-djmix-playlist.sh — regenerate djmix.m3u8 from the configured album list.
#
# Reads ${ALEMBIC_CONFIG_DIR:-/config}/pipeline/djmix-albums.txt (one beets query per line),
# collects all matching track paths, deduplicates, and writes
# ${MUSIC_DATA_DIR:-/data/music}/playlists/djmix.m3u8.
#
# Azuracast imports this playlist so DJ mixes can be excluded from general
# rotation. Navidrome also picks it up as a regular playlist.
#
# Runs daily from cron. Safe to run manually anytime.
set -euo pipefail
CONFIG=${ALEMBIC_CONFIG_DIR:-/config}/pipeline/djmix-albums.txt
PLAYLIST_DIR=${MUSIC_DATA_DIR:-/data/music}/playlists
OUT="${PLAYLIST_DIR}/djmix.m3u8"
LOG_DIR=${ALEMBIC_CONFIG_DIR:-/config}/logs
LOG="${LOG_DIR}/djmix-$(date +%Y%m%d).log"
mkdir -p "$LOG_DIR" "$PLAYLIST_DIR"
log() { echo "[$(date -Iseconds)] $*" | tee -a "$LOG"; }
log "=== Regenerating djmix.m3u8 ==="
if [[ ! -f "$CONFIG" ]]; then
log "no djmix-albums.txt at $CONFIG — nothing to generate"
exit 0
fi
TRACKS=$(mktemp)
while IFS= read -r query; do
[[ -z "$query" || "$query" == "#"* ]] && continue
# Split on | to support multi-field queries (e.g. "albumartist::Foo | album:Bar").
# Each |-separated part becomes a separate beet query term (ANDed together).
# Single-field lines (no |) are passed as one arg so commas in album names
# don't get misinterpreted by beet's query parser.
IFS='|' read -ra _terms <<< "$query"
_args=()
for _t in "${_terms[@]}"; do
# strip leading/trailing whitespace
_t="${_t#"${_t%%[![:space:]]*}"}"
_t="${_t%"${_t##*[![:space:]]}"}"
[[ -n "$_t" ]] && _args+=("$_t")
done
# `|| true`: a malformed single query shouldn't abort the whole regen.
beet ls -f '$path' "${_args[@]}" 2>>"$LOG" >> "$TRACKS" || true
done < "$CONFIG"
# Deduplicate and sort
SORTED=$(sort -u "$TRACKS")
rm -f "$TRACKS"
COUNT=$(echo -n "$SORTED" | grep -c '^' || true)
if [[ "$COUNT" -gt 0 ]]; then
{
echo "#EXTM3U"
echo "$SORTED"
} > "$OUT"
log "djmix.m3u8 updated with $COUNT tracks"
else
log "WARNING: no tracks found — djmix.m3u8 not updated"
fi
log "=== Finished ==="