Stage 0: migrate pipeline scripts from /opt/sldl, scaffold repo
Moves all ~30 pipeline scripts, configs, and the vendored sldl binary into this repo (source /opt/sldl left untouched). Removes all docker exec/docker compose dependencies now that beets and sldl run in-process/as a subprocess of this container instead of via soulbeet/on-demand sldl containers. Replaces hardcoded host paths, Navidrome credentials, and Spotify credential sourcing with env-var-driven paths and shared credential loaders. Adds Dockerfile, entrypoint.sh, requirements.txt, docker-compose.snippet.yml, and the initial app DB schema.
This commit is contained in:
@@ -0,0 +1,99 @@
|
||||
#!/bin/bash
|
||||
# ${PIPELINE_DIR:-/app/pipeline}/lib/tag-guard.sh
|
||||
#
|
||||
# Shared helper sourced by run-playlist.sh and import-track.sh.
|
||||
# Moves audio files with missing ARTIST or TITLE tags into a quarantine dir,
|
||||
# so they never reach beets and rot the library as "[Unknown Album]".
|
||||
#
|
||||
# Usage: quarantine_untagged <scan_dir> <quarantine_dir> <log_file>
|
||||
# Returns: number of files moved (via stdout)
|
||||
|
||||
# Separator pattern matching Navidrome's artist split list in navidrome.toml.
|
||||
# Used by set_albumartist_fallback to extract the primary artist from a multi-
|
||||
# artist string. Keep these two lists in sync.
|
||||
#
|
||||
# Only unambiguous separators here. ", " and " & " are NOT included because they
|
||||
# appear inside real band names ("Tyler, The Creator", "Simon & Garfunkel",
|
||||
# "piri & tommy"). For collab strings using those separators, ALBUMARTIST falls
|
||||
# back to the full string — Navidrome will show one combined artist for the album,
|
||||
# which is the lesser of two evils vs. corrupting real band names.
|
||||
_PRIMARY_ARTIST_SEP_PATTERN=' / | feat\. | feat | ft\. | ft |; '
|
||||
|
||||
# For each audio file under $scan_dir that has no ALBUMARTIST tag, set
|
||||
# ALBUMARTIST to the primary artist (everything before the first separator
|
||||
# in the ARTIST tag). Prevents Navidrome from coining ghost album-artists
|
||||
# like "Fred Again, The Blessed Madonna" when a track is a collab.
|
||||
#
|
||||
# Usage: set_albumartist_fallback <scan_dir> <log_file>
|
||||
# Returns: number of files updated (via stdout)
|
||||
set_albumartist_fallback() {
|
||||
local scan_dir="$1"
|
||||
local logfile="$2"
|
||||
local count=0
|
||||
|
||||
while IFS= read -r -d '' file; do
|
||||
case "${file##*.}" in
|
||||
flac|FLAC)
|
||||
local cur_aa artist primary
|
||||
cur_aa=$(metaflac --show-tag=ALBUMARTIST "$file" 2>/dev/null | sed -n 's/^[^=]*=//p' | head -1)
|
||||
[[ -n "$cur_aa" ]] && continue
|
||||
artist=$(metaflac --show-tag=ARTIST "$file" 2>/dev/null | sed -n 's/^[^=]*=//p' | head -1)
|
||||
[[ -z "$artist" ]] && continue
|
||||
primary=$(echo "$artist" | sed -E "s#(${_PRIMARY_ARTIST_SEP_PATTERN}).*##")
|
||||
metaflac --set-tag="ALBUMARTIST=${primary}" "$file" 2>>"$logfile"
|
||||
count=$((count + 1))
|
||||
;;
|
||||
mp3|MP3)
|
||||
local cur_aa artist primary
|
||||
cur_aa=$(id3v2 -l "$file" 2>/dev/null | sed -n 's/^TPE2[^:]*: //p' | head -1)
|
||||
[[ -n "$cur_aa" ]] && continue
|
||||
artist=$(id3v2 -l "$file" 2>/dev/null | sed -n 's/^TPE1[^:]*: //p' | head -1)
|
||||
[[ -z "$artist" ]] && continue
|
||||
primary=$(echo "$artist" | sed -E "s#(${_PRIMARY_ARTIST_SEP_PATTERN}).*##")
|
||||
id3v2 --TPE2 "$primary" "$file" 2>>"$logfile"
|
||||
count=$((count + 1))
|
||||
;;
|
||||
esac
|
||||
done < <(find "$scan_dir" -type f \( -iname "*.flac" -o -iname "*.mp3" \) -print0 2>/dev/null)
|
||||
|
||||
echo "$count"
|
||||
}
|
||||
|
||||
quarantine_untagged() {
|
||||
local scan_dir="$1"
|
||||
local quarantine_dir="$2"
|
||||
local logfile="$3"
|
||||
local moved=0
|
||||
|
||||
mkdir -p "$quarantine_dir"
|
||||
|
||||
_has_flac_tags() {
|
||||
local artist title
|
||||
artist=$(metaflac --show-tag=ARTIST "$1" 2>/dev/null | sed -n 's/^[^=]*=//p' | head -1)
|
||||
title=$(metaflac --show-tag=TITLE "$1" 2>/dev/null | sed -n 's/^[^=]*=//p' | head -1)
|
||||
[[ -n "$artist" && -n "$title" ]]
|
||||
}
|
||||
|
||||
_has_mp3_tags() {
|
||||
local artist title
|
||||
artist=$(id3v2 -l "$1" 2>/dev/null | sed -n 's/^TPE1[^:]*: //p' | head -1)
|
||||
title=$(id3v2 -l "$1" 2>/dev/null | sed -n 's/^TIT2[^:]*: //p' | head -1)
|
||||
[[ -n "$artist" && -n "$title" ]]
|
||||
}
|
||||
|
||||
while IFS= read -r -d '' file; do
|
||||
local ok=1
|
||||
case "${file##*.}" in
|
||||
flac|FLAC) _has_flac_tags "$file" || ok=0 ;;
|
||||
mp3|MP3) _has_mp3_tags "$file" || ok=0 ;;
|
||||
*) ok=0 ;; # unknown format — beets can't handle it anyway
|
||||
esac
|
||||
if [[ $ok -eq 0 ]]; then
|
||||
echo "[$(date -Iseconds)] QUARANTINE: missing artist/title — $(basename "$file")" >> "$logfile"
|
||||
mv -n "$file" "$quarantine_dir/" 2>>"$logfile"
|
||||
moved=$((moved + 1))
|
||||
fi
|
||||
done < <(find "$scan_dir" -type f \( -iname "*.flac" -o -iname "*.mp3" -o -iname "*.m4a" \) -print0 2>/dev/null)
|
||||
|
||||
echo "$moved"
|
||||
}
|
||||
Reference in New Issue
Block a user