audio_sync mirrors apple_id ({cc:album_id}) + apple_song_id (kept raw, country preserved).
/shop/audio parses it: AU>US>first → music.apple.com/{cc}/album/{id}, per-track preview array
→ first clean 30s url. Kiosk Listen uses apple_preview + an Apple Music ↗ link.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
81 lines
3.3 KiB
Python
81 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);
|
|
"""
|
|
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()
|