diff --git a/.github/workflows/editors-picks.yml b/.github/workflows/editors-picks.yml new file mode 100644 index 0000000..fa294f0 --- /dev/null +++ b/.github/workflows/editors-picks.yml @@ -0,0 +1,95 @@ +name: Update Editors Picks + +on: + push: + branches: [main] + paths: + - 'editors-picks-input.txt' + +jobs: + update: + runs-on: ubuntu-latest + permissions: + contents: write + + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + fetch-depth: 1 + + - name: Check for backoff condition + id: backoff + run: | + CHANGED=$(git diff-tree --no-commit-id -r --name-only HEAD) + echo "Files changed in this commit:" + echo "$CHANGED" + if echo "$CHANGED" | grep -qE '^public/editors-picks\.json$|^public/editors-picks-old/'; then + echo "Detected changes to generated files in this commit — backing off to avoid overwriting manual edits." + echo "skip=true" >> "$GITHUB_OUTPUT" + else + echo "skip=false" >> "$GITHUB_OUTPUT" + fi + + - name: Setup Python + if: steps.backoff.outputs.skip == 'false' + uses: actions/setup-python@v5 + with: + python-version: '3.x' + + - name: Archive current editors picks + if: steps.backoff.outputs.skip == 'false' + run: | + python3 - << 'EOF' + import json, re + from datetime import date + + today = date.today() + # Filename uses non-padded month/day to match existing convention + filename = f"{today.year}-{today.month}-{today.day}.json" + # Date field uses ISO format (zero-padded) + iso_date = today.strftime("%Y-%m-%d") + archive_path = f"public/editors-picks-old/{filename}" + + # Read optional label from input file + label = iso_date + with open("editors-picks-input.txt") as f: + for line in f: + m = re.match(r"^#\s*label:\s*(.+)", line.strip()) + if m: + label = m.group(1).strip() + break + + # Copy current picks to archive + with open("public/editors-picks.json") as f: + current = json.load(f) + with open(archive_path, "w") as f: + json.dump(current, f, indent=4) + + # Prepend to index so newest archived version appears first + with open("public/editors-picks-old/index.json") as f: + index = json.load(f) + index.insert(0, { + "file": filename, + "label": label, + "date": iso_date, + }) + with open("public/editors-picks-old/index.json", "w") as f: + json.dump(index, f, indent=4) + + print(f"Archived to {archive_path} with label '{label}'") + EOF + + - name: Generate new editors picks + if: steps.backoff.outputs.skip == 'false' + run: python3 gen-editors-picks.py + + - name: Commit and push + if: steps.backoff.outputs.skip == 'false' + run: | + git config user.name "github-actions[bot]" + git config user.email "github-actions[bot]@users.noreply.github.com" + git add public/editors-picks.json public/editors-picks-old/ + git diff --staged --quiet && echo "No changes to commit." && exit 0 + git commit -m "chore: update editors picks [skip ci]" + git push diff --git a/editors-picks-input.txt b/editors-picks-input.txt new file mode 100644 index 0000000..bdfb599 --- /dev/null +++ b/editors-picks-input.txt @@ -0,0 +1,17 @@ +# Editors Picks — album IDs (one per line) +# Optional: add a label for this set with "# label: ..." +# Lines starting with # are ignored. +# label: Spring 2026 + +324660713 +15427733 +464178301 +75115890 +410197513 +418729278 +504004321 +510893864 +325723583 +336178142 +106369871 +423471869 diff --git a/gen-editors-picks.py b/gen-editors-picks.py index eb3a8e4..2d05e72 100644 --- a/gen-editors-picks.py +++ b/gen-editors-picks.py @@ -2,22 +2,10 @@ import urllib.request import json +import re import sys -ALBUMS = [ - 324660713, - 15427733, - 464178301, - 75115890, - 410197513, - 418729278, - 504004321, - 510893864, - 325723583, - 336178142, - 106369871, - 423471869, -] +INPUT_FILE = "editors-picks-input.txt" TOKEN = "eyJraWQiOiJ2OU1GbFhqWSIsImFsZyI6IkVTMjU2In0.eyJ0eXBlIjoibzJfYWNjZXNzIiwic2NvcGUiOiIiLCJnVmVyIjowLCJzVmVyIjowLCJjaWQiOjEzNTU3LCJhdCI6IklOVEVSTkFMIiwiZXhwIjoxNzc1MTI4ODUzLCJpc3MiOiJodHRwczovL2F1dGgudGlkYWwuY29tL3YxIn0.qRoN8BRLM3R5WAXM3kS2hkWyaGk5tWF0FaHWJmkrWNvI48hKyS9lhVOTSnP1XkFEfdXv6aTzGUNUewyp-O_d3w" @@ -26,6 +14,19 @@ HEADERS = { "authorization": f"Bearer {TOKEN}", } +def read_album_ids(path): + ids = [] + with open(path) as f: + for line in f: + line = line.strip() + if not line or line.startswith("#"): + continue + try: + ids.append(int(line)) + except ValueError: + print(f"Skipping invalid ID: {line!r}", file=sys.stderr) + return ids + def fetch_album(album_id): url = f"https://api.tidal.com/v1/albums/{album_id}?countryCode=US" req = urllib.request.Request(url, headers=HEADERS) @@ -52,8 +53,10 @@ def transform_album(api_data): "mediaMetadata": api_data.get("mediaMetadata"), } +albums = read_album_ids(INPUT_FILE) + picks = [] -for album_id in ALBUMS: +for album_id in albums: data = fetch_album(album_id) if data: picks.append(transform_album(data))