diff --git a/etc/sldl.tpl.conf b/etc/sldl.tpl.conf index 2b76dd3..1721f93 100644 --- a/etc/sldl.tpl.conf +++ b/etc/sldl.tpl.conf @@ -1,7 +1,7 @@ -path = "/data" -index-path = "/data/_metadata/index.sldl.csv" -username = "${SLDL_USER}" -password = "${SLDL_PASS}" +path = "${SOCKSEEK_DATA}" +index-path = "${SOCKSEEK_DATA}/_metadata/index.sldl.csv" +username = "${SOCKSEEK_USER}" +password = "${SOCKSEEK_PASS}" name-format = "{artist(/)album(/)track( )title|(_missing_tags/)slsk-foldername(/)slsk-filename}" diff --git a/justfile b/justfile index 41a1b2b..cd1d5e0 100644 --- a/justfile +++ b/justfile @@ -32,6 +32,10 @@ link plist dir: spotify ids="7f5tPIfj21UJI4zfDmH4rx 6sAl8LhU6ediFNJRuQQIQX": cd maple-py && uv run src/spotify.py {{ids}} --csv +# Download via sockseek (csv path, url, search string, ...) using sldl.tpl.conf settings +sockseek input: + cd maple-py && uv run src/sockseek.py {{input}} + sync args: s5cmd {{args}} diff --git a/maple-py/src/sockseek.py b/maple-py/src/sockseek.py new file mode 100644 index 0000000..72ac915 --- /dev/null +++ b/maple-py/src/sockseek.py @@ -0,0 +1,73 @@ +#!/usr/bin/env -S uv run --script +# /// script +# requires-python = ">=3.14" +# dependencies = [] +# /// +"""Thin binding around the `sockseek` CLI. + +Creates the data directories and invokes sockseek with the CLI-argument +equivalents of etc/sldl.tpl.conf, so the two stay in sync without rendering a +config file. Reads SOCKSEEK_DATA / SOCKSEEK_USER / SOCKSEEK_PASS from the +environment (loaded from .env by just). + + just sockseek # csv path, url, search string, ... + just sockseek "tracks.csv -a" # extra flags pass through / override + +Any args after the input are forwarded to sockseek verbatim, placed after the +defaults so they win on conflict. +""" +import os +import subprocess +import sys +from pathlib import Path + +# Mirror of etc/sldl.tpl.conf. Keep these in sync with that file. +NAME_FORMAT = "{artist(/)album(/)track( )title|(_missing_tags/)slsk-foldername(/)slsk-filename}" + + +def env(key): + val = os.environ.get(key) + if not val: + sys.exit(f"missing env var: {key}") + return val + + +def config_args(data, user, password): + """CLI equivalents of etc/sldl.tpl.conf (no-progress has no sockseek flag).""" + return [ + "--path", data, + "--index-path", f"{data}/_metadata/index.sldl.csv", + "--user", user, + "--pass", password, + "--name-format", NAME_FORMAT, + "--pref-format", "flac,mp3", + "--pref-min-bitrate", "200", + "--pref-max-bitrate", "2500", + "--strict-conditions", + "--fast-search", + "--concurrent-jobs", "4", + ] + + +def main(): + if not sys.argv[1:]: + sys.exit("usage: sockseek.py [extra sockseek args...]") + inp, *extra = sys.argv[1:] + + data = env("SOCKSEEK_DATA") + user = env("SOCKSEEK_USER") + password = env("SOCKSEEK_PASS") + + Path(data, "_metadata").mkdir(parents=True, exist_ok=True) + + args = config_args(data, user, password) + cmd = ["sockseek", inp, *args, *extra] + + masked = ["***" if a == password else a for a in cmd] + print(" ".join(masked), file=sys.stderr) + + raise SystemExit(subprocess.run(cmd).returncode) + + +if __name__ == "__main__": + main() diff --git a/maple-py/src/spotify.py b/maple-py/src/spotify.py index e678f32..5dddc54 100644 --- a/maple-py/src/spotify.py +++ b/maple-py/src/spotify.py @@ -157,10 +157,6 @@ def main(): write_csv(playlists, sys.stdout) return - if as_json: - print(json.dumps(playlists, indent=2, ensure_ascii=False)) - return - for pl in playlists: print(f"\n=== {pl['name']} ({len(pl['tracks'])} tracks) ===") for n, t in enumerate(pl["tracks"], 1):