RECORDGOD/audio_sync.py
type-two 988e6437cb feat(shop): per-track Apple previews (lazy iTunes) + jog mini-player + dead-YouTube check
/shop/audio-tracks/{id}: resolves each track's preview from its Apple song id via iTunes lookup
(au), cached in disc_release_track.apple_preview. /shop/audio validates YouTube via oembed (200=live),
caches dead in disc_release_video.dead, returns one live id. release.html + kiosk.html get a per-track
▶ on each tracklist row feeding a mini-player with a jog/seek bar (falls back to a single Listen).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-23 23:44:17 +10:00

82 lines
3.3 KiB
Python

#!/usr/bin/env python3
"""Mirror WowPlatter's audio/video link tables → RecordGod Postgres (for kiosk/storefront previews).
python3 audio_sync.py | ssh -C root@100.94.195.115 \
'docker exec -i recordgod-db psql -U recordgod -d recordgod -q -v ON_ERROR_STOP=1'
disc_release_audio = one wide row per release (apple_preview_url = a direct 30s preview, beatport_embed,
bandcamp, spotify…); disc_release_video = YouTube clips per release/track. All rows mirrored — the JOIN to
disc_release naturally filters to what the shop stocks. Re-run after a fresh Beatport/Apple enrich.
"""
import re
import pathlib
import sys
import pymysql
WP_CONFIG = "/opt/homebrew/var/www/monsterrobot.localsite/wp-config.php"
SOCK = "/opt/homebrew/var/mysql/mysql.sock"
SCHEMA = """
SET synchronous_commit = off;
DROP TABLE IF EXISTS disc_release_audio, disc_release_video CASCADE;
CREATE TABLE disc_release_audio (
release_id bigint PRIMARY KEY, apple_id text, apple_song_id text, apple_url text, apple_preview_url text,
beatport_id text, beatport_url text, beatport_embed text, beatport_genre text,
spotify_id text, tidal_id text, deezer_id text,
bandcamp_url text, bandcamp_embed text, soundcloud_url text, allmusic_url text, local_url text);
CREATE TABLE disc_release_video (
release_id bigint, track_id text, title text, uri text, embed int, duration int,
dead boolean, checked_at timestamptz);
"""
INDEXES = "CREATE INDEX ON disc_release_video (release_id);\nANALYZE disc_release_audio;\n"
# apple_id = country-scoped {"<cc>": "<album_id>"} (essential: country + the id; single-vs-album = the
# Discogs release itself, via format). apple_song_id = song-level. Both kept RAW so nothing's lost.
A_COLS = ["release_id", "apple_id", "apple_song_id", "apple_url", "apple_preview_url", "beatport_id",
"beatport_url", "beatport_embed", "beatport_genre", "spotify_id", "tidal_id", "deezer_id",
"bandcamp_url", "bandcamp_embed", "soundcloud_url", "allmusic_url", "local_url"]
V_COLS = ["release_id", "track_id", "title", "uri", "embed", "duration"]
def creds():
t = pathlib.Path(WP_CONFIG).read_text()
g = lambda k: re.search(rf"'{k}',\s*'([^']*)'", t).group(1)
return g("DB_NAME"), g("DB_USER"), g("DB_PASSWORD")
def cp(v):
if v is None or v == "":
return r"\N"
return (str(v).replace("\\", "\\\\").replace("\t", "\\t")
.replace("\n", "\\n").replace("\r", "\\r"))
def copy_block(out, table, cols, rows):
out.write(f"COPY {table} ({','.join(cols)}) FROM stdin;\n")
for r in rows:
out.write("\t".join(cp(r[c]) for c in cols) + "\n")
out.write("\\.\n\n")
print(f" {table:22} {len(rows):>7,}", file=sys.stderr)
def main():
name, user, pw = creds()
my = pymysql.connect(unix_socket=SOCK, user=user, password=pw, database=name,
cursorclass=pymysql.cursors.DictCursor)
c = my.cursor()
P = "wp_rmp_disc_"
out = sys.stdout
out.write(SCHEMA)
print("emitting audio/video:", file=sys.stderr)
c.execute(f"SELECT {','.join(A_COLS)} FROM {P}release_audio")
copy_block(out, "disc_release_audio", A_COLS, c.fetchall())
c.execute(f"SELECT {','.join(V_COLS)} FROM {P}release_video WHERE uri IS NOT NULL AND uri <> ''")
copy_block(out, "disc_release_video", V_COLS, c.fetchall())
out.write(INDEXES)
print("done", file=sys.stderr)
if __name__ == "__main__":
main()