Trollgorithm Theme Song Booth - customer-facing request form, admin dashboard, kiosk queue, and delivery pipeline for AI-generated theme songs.
This repository has been archived on 2026-09-04. You can view files and clone it, but you cannot make any changes to it's state, such as pushing and creating new issues, pull requests or comments.
Find a file
2026-08-04 01:20:56 +00:00
static feat: add booth open/closed toggle on settings page 2026-08-02 18:17:59 +00:00
templates Add admin Sales report page 2026-08-04 01:20:56 +00:00
.env.example feat: Hermes prompt callback endpoint + API key management 2026-08-03 17:16:56 +00:00
.gitignore Initial prototype for theme song booth 2026-07-31 19:47:52 +00:00
app.py Add admin Sales report page 2026-08-04 01:20:56 +00:00
config.py feat: Hermes prompt callback endpoint + API key management 2026-08-03 17:16:56 +00:00
docker-compose.yml feat: Hermes prompt callback endpoint + API key management 2026-08-03 17:16:56 +00:00
Dockerfile docs: update comments, docstrings, README, REVIEW, and env docs to match current features 2026-08-03 00:11:41 +00:00
init_db.py docs: update comments, docstrings, README, REVIEW, and env docs to match current features 2026-08-03 00:11:41 +00:00
models.py Add stems_link support for Pingvin-Share-X delivery 2026-08-04 01:10:15 +00:00
README.md feat: Hermes prompt callback endpoint + API key management 2026-08-03 17:16:56 +00:00
requirements.txt docs: update comments and README to reflect current feature set 2026-08-02 00:07:24 +00:00
REVIEW.md feat: Hermes prompt callback endpoint + API key management 2026-08-03 17:16:56 +00:00

Theme Song Booth

A Flask web app for a convention booth where visitors request a custom AI-generated theme song, the operator manages the queue, and the final MP3(s) are delivered by email after payment.

Features

Customer-facing

  • Request form (/request) — visitors enter name, email, hobbies, notable facts, preferred style/genre, vocal gender preference, and extra requests. A branded banner image is shown. The email field is validated to reduce delivery problems. If the operator marks the booth as closed, this page shows a closed banner and message instead.
  • Closed page (/request) — when the booth is marked closed from /admin/settings, visitors see the closed banner and a friendly "goblin engineers are on a break" message.
  • Order status lookup (/status) — customers enter their email to see all their requests, current status, and the private player link once songs are uploaded.
  • Confirmation page (/thanks/<id>) — shows the request number after submission.
  • FAQ page (/faq) — answers common customer questions.
  • Private player page (/play/<token>) — customer receives an email with a unique link. They can stream Version A and Version B, pick one (or both), or request a limited number of revisions.
  • Revision workflow — when a customer asks for changes, the current MP3s are archived and the operator sees the request as "Revisions Requested" in the dashboard.
  • Rate limiting — the public request form is capped at 5 submissions per minute per IP.

Operator/admin

  • Admin login (/admin/login) — simple session-based login protected by ADMIN_PASSWORD.
  • Dashboard queue (/admin) — filter by status (All, Pending, Needs Upload, Awaiting Payment, Delivered) and auto-refresh at a configurable interval.
  • Per-request detail page (/admin/request/<id>):
    • Generate and save a Suno prompt from customer info.
    • One-click copy of request details + a signed callback URL for Hermes.
    • Hermes POSTs back the generated Title/Style/Lyrics; status becomes Prompt Ready automatically.
    • Edit the customer's email address if they mistyped it.
    • Upload Version A and Version B MP3s (with automatic ID3 metadata tagging).
    • Send a preview email with a private player link.
    • Mark paid, enter a Square payment reference, and deliver selected MP3 attachments.
  • Settings / maintenance page (/admin/settings):
    • Database health check with optional schema repair.
    • Database statistics, size, upload counts.
    • Configure customer revision limit.
    • Configure dashboard auto-refresh interval.
    • Configure SMTP host/port/user/from; store the SMTP password encrypted.
    • Configure default MP3 metadata tags (artist, album, year, comment).
    • Generate/regenerate the Hermes API key used by the prompt callback endpoint (shown once, otherwise masked).
    • Send a test email.
    • Download or restore the SQLite database backup.
    • Reset the entire system for a new event.
  • Per-request delete and system reset — remove requests and uploaded files; reset auto-increment back to 1.

Status flow

pending → prompt_ready → songs_uploaded → awaiting_payment → paid → delivered
Status Meaning
pending Customer submitted a request; operator has not saved a prompt yet.
prompt_ready Hermes POSTed back the generated Suno prompt, or the operator saved it manually.
songs_uploaded Both MP3s uploaded; preview link can be sent. Dashboard filter label: Needs Upload (shown for this state when filtering).
revisions_requested Customer asked for changes; current files were archived.
awaiting_payment Customer approved a version; waiting for operator to collect payment and deliver.
paid Payment recorded (used internally).
delivered MP3 attachment(s) emailed to the customer.

File layout

File Purpose
app.py Flask routes, helpers, email layer, runtime settings, MP3 tagging, rate limiting, DB maintenance, and Hermes callback endpoint.
config.py Environment-variable based configuration; defines defaults for DB, uploads, SMTP, secrets, and HERMES_API_KEY.
models.py SQLite schema + CRUD. player_token is a secret URL-safe token.
init_db.py Run once after deploy: python init_db.py.
templates/admin/request.html Biggest template; prompt copy helpers and JS live here. Customer email and operator notes are editable here.
templates/admin/dashboard.html Queue table + filters + auto-refresh + topbar Reset System button.
templates/admin/settings.html Maintenance, settings, backup/restore, reset, and Hermes API key management.
templates/status.html Customer order status lookup.
templates/faq.html Customer FAQ page.
templates/player.html Customer audio player, approval, and revision form.
templates/admin/login.html Admin login page.
templates/admin/dashboard.html Operator queue with filters and auto-refresh.
templates/admin/request.html Single-request detail / prompt / upload / delivery page. Customer email and operator notes are editable here.
templates/admin/settings.html Maintenance, settings, backup/restore, and reset page.
static/Trollgorithm_booth.jpg Banner image on the request page.
static/DM-Logo_email.png Inline Dionysis Media logo attached to emails.
static/Booth_closed.png Banner shown when the booth is marked closed.
Dockerfile Production container image.
docker-compose.yml Portainer stack definition.
requirements.txt Python dependencies.
.env.example Template for local environment variables.
REVIEW.md Quick-reference for returning to this project.

Local development

cd /home/jess/workspace/theme-song-booth
python3 -m venv .venv
.venv/bin/pip install -r requirements.txt
cp .env.example .env
# Edit .env and set APP_SECRET_KEY, ADMIN_PASSWORD, SMTP_PASS, PUBLIC_BASE_URL
.venv/bin/python init_db.py
.venv/bin/python -m flask --app app run --host=0.0.0.0

Visit:

Deployment with Portainer

  1. Log in to Portainer.
  2. Go to StacksAdd stack.
  3. Choose Repository:
    • URL: https://gitlab.hallsworth.ca/yrtria/theme-song-booth.git
    • Branch: main
    • Compose path: docker-compose.yml
  4. Add environment variables:
Variable Required Purpose
APP_SECRET_KEY Yes Long random string for Flask sessions and to encrypt stored SMTP password. Generate with python3 -c "import secrets; print(secrets.token_hex(32))".
ADMIN_PASSWORD Yes Password for /admin.
SMTP_PASS Yes Password for the SMTP account.
PUBLIC_BASE_URL Yes Public HTTPS URL, e.g. https://booth.dionysismedia.ca.
HOST_PORT No Host-side port mapping, default 127.0.0.1:8000.
INTERNAL_PORT No Port gunicorn binds inside container, default 8000.
BOOTH_NAME No
PRICE_PER_VERSION No
CURRENCY No
MAX_REVISIONS No
HERMES_API_KEY No
  1. Deploy the stack.
  2. Open a console in the theme-song-booth container and run once:
python init_db.py
  1. Point your reverse proxy at the HOST_PORT you chose.
  2. Visit /admin/settings and click Regenerate API Key to create the Hermes callback key.
  3. Update your Hermes skill or config with the new key and the booth public URL.
  4. Print or display a QR code pointing to https://your-domain/request.

Updating the deployment

After each push to GitLab, go to Portainer → Stackstheme-song-boothPull and redeploy to rebuild from the repo.

Important notes

  • No .env file in production. docker-compose.yml passes variables directly from Portainer. This avoids Portainer's env_file not found error.
  • Runtime settings persist. SMTP config, revision limit, auto-refresh interval, booth open/closed state, Hermes API key, and MP3 metadata defaults are stored in booth_settings.json inside the persistent uploads volume. They survive redeploys.
  • Booth open/closed switch. Operators can flip the booth status from /admin/settings. When closed, /request shows a closed banner and message instead of the form.
  • Payments are manual. The app records a Square payment reference but does not integrate with Square's API. Use a Square Terminal/Reader at the booth.
  • Operator queue is the dashboard. No operator email alerts are sent; approvals and revision notes appear as status changes in /admin.
  • Hermes callback workflow. Operators copy request details + a signed callback URL from /admin/request/<id>. Hermes POSTs back Title/Style/Lyrics; the record becomes prompt_ready.
  • MP3 metadata. Uploaded files are tagged with title (from the saved prompt), plus configured artist/album/year/comment values.
  • Email logo. static/DM-Logo_email.png is attached inline to all customer emails as the Dionysis Media signature.
  • Security: the repo is public on GitLab. No secrets are committed. Admin password is plain text in the Portainer environment. The Hermes API key is stored encrypted in booth_settings.json and masked in the admin UI.

Common troubleshooting

Problem Cause Fix
"Send Preview Link" does nothing Form tags were unbalanced (now fixed). Redeploy the latest commit.
Emails not arriving SMTP settings wrong or messages in spam. Use Send Test Email on /admin/settings; verify host/port/password.
Can't reach app through domain Reverse proxy points to wrong host port. Match HOST_PORT to your proxy upstream.
Static banner not showing Browser cached old image. Hard-refresh or redeploy stack.
Logo missing from email Logo file missing from static/. Ensure static/DM-Logo_email.png is in the container.
Database schema mismatch New column added but old DB not migrated. Go to /admin/settings and click Fix Missing Columns, or run python init_db.py.

License / ownership

Built for Jess's Trollgorithm theme-song booth. All code and assets are private to that project.