From be85a885438bd86d8eda18e93cd02a51edef671e Mon Sep 17 00:00:00 2001 From: "Troll (Hermes Agent)" Date: Sun, 20 Sep 2026 02:49:01 +0000 Subject: [PATCH] feat: add per-song MP3 download buttons to admin request page Adds an admin download route (/admin/request//download-song/) and Download buttons next to Version A and Version B in section 2 (Songs), shown only when the MP3 exists on disk. Bumps version to 0.9.2. --- README.md | 4 ++-- VERSION | 2 +- app.py | 18 ++++++++++++++++++ static/css/booth.css | 7 +++++++ templates/admin/request.html | 6 ++++++ 5 files changed, 34 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index b265cae..fc42295 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # Theme Song Booth (MusicGPT Edition) -![Version](https://img.shields.io/badge/version-v0.9.1-blue) +![Version](https://img.shields.io/badge/version-v0.9.2-blue) A Flask web application for running a convention booth where visitors request a custom AI-generated theme song. Operators manage the queue from an admin dashboard, generate prompts via Hermes, queue generations through the MusicGPT API, and deliver final songs by email. @@ -78,7 +78,7 @@ The selected pronouns are stored in the `pronouns` column and included in confir |------|------|---------| | Login | `/admin/login` | Simple session-based login. Password comes from the `ADMIN_PASSWORD` environment variable. | | Dashboard | `/admin` | Main queue. Filter by status and auto-refresh at a configurable interval. Includes a **Refresh MusicGPT Status** button to manually poll all in-flight tasks. | -| Request detail | `/admin/request/` | Full control of one request: edit customer info, save prompt, copy Hermes callback, queue MusicGPT generation, poll a single MusicGPT task, view status/cost, view revision history, upload MP3 overrides, send preview, record payment, deliver files (MP3/WAV/cover), add operator notes, cancel generation, and generate STEMS. | +| Request detail | `/admin/request/` | Full control of one request: edit customer info, save prompt, copy Hermes callback, queue MusicGPT generation, poll a single MusicGPT task, view status/cost, view revision history, upload MP3 overrides, download individual Version A/B MP3s, send preview, record payment, deliver files (MP3/WAV/cover), add operator notes, cancel generation, and generate STEMS. | | Pricing | `/admin/pricing` | Configure fixed prices and up to 5 custom items. Also shows running MusicGPT cost totals in USD. | | Sales | `/admin/sales` | Report of all delivered requests with customer details and Square payment references. | | Settings | `/admin/settings` | Database health, backups, SMTP config, MP3 metadata defaults, revision limit, auto-refresh interval, kiosk mode, booth open/closed switch, Hermes API key management, MusicGPT webhook URL, album cover delivery toggle, automatic MusicGPT polling toggle, and system reset. | diff --git a/VERSION b/VERSION index f374f66..2003b63 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -0.9.1 +0.9.2 diff --git a/app.py b/app.py index 8c97daf..1a2f120 100644 --- a/app.py +++ b/app.py @@ -922,6 +922,24 @@ def admin_download_stems(rid): return send_file(buf, mimetype='application/zip', as_attachment=True, download_name=download_name) +@app.route('/admin/request//download-song/') +def admin_download_song(rid, version): + """Download a single song MP3 (Version A or B) for a request.""" + redir = require_admin() + if redir: + return redir + req = get_request_by_id(rid) + if not req: + abort(404) + if version not in ('a', 'b'): + abort(404) + path = req.get('song_a_path') if version == 'a' else req.get('song_b_path') + if not path or not Path(path).exists(): + flash('Song file not found.', 'error') + return redirect(url_for('admin_request', rid=rid)) + return send_file(path, as_attachment=True, download_name=Path(path).name) + + # --------------------------------------------------------------------------- # Admin routes # --------------------------------------------------------------------------- diff --git a/static/css/booth.css b/static/css/booth.css index 56b5d48..63d995e 100644 --- a/static/css/booth.css +++ b/static/css/booth.css @@ -558,6 +558,13 @@ flex: 1; } +.booth-page .song-download { + flex: 0 0 auto; + align-self: center; + font-size: 0.85rem; + padding: var(--space-1) var(--space-3); +} + .booth-page .file-select { background: var(--bg-input); border: 1px solid var(--border); diff --git a/templates/admin/request.html b/templates/admin/request.html index ccbaf9a..8f8f976 100644 --- a/templates/admin/request.html +++ b/templates/admin/request.html @@ -313,6 +313,9 @@ Not ready {% endif %} + {% if req.song_a_path and file_exists(req.song_a_path) %} + ⬇ Download + {% endif %}
@@ -326,6 +329,9 @@ Not ready {% endif %} + {% if req.song_b_path and file_exists(req.song_b_path) %} + ⬇ Download + {% endif %}
-- 2.49.1