Document config vars and rewrite README
- Clarified HERMES_API_KEY and PRICE_PER_VERSION comments in config.py. - Completely rewrote README.md with: - version, overview, and table of contents - page-by-page customer and admin guide - status flow table - detailed /admin/settings section - Docker / Portainer install process - full environment variable table - local development and troubleshooting sections
This commit is contained in:
parent
235507f499
commit
d79c58691a
2 changed files with 199 additions and 130 deletions
321
README.md
321
README.md
|
|
@ -2,52 +2,65 @@
|
||||||
|
|
||||||
**Version:** `v0.4.5`
|
**Version:** `v0.4.5`
|
||||||
|
|
||||||
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.
|
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 Suno prompts, upload MP3 previews, collect payment, and deliver final songs by email.
|
||||||
|
|
||||||
## 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. Email is validated to reduce delivery problems. If the operator marks the booth as closed, this page shows a closed banner and message instead.
|
## Table of contents
|
||||||
- **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
|
1. [What the booth does](#what-the-booth-does)
|
||||||
|
2. [Customer-facing pages](#customer-facing-pages)
|
||||||
|
3. [Operator / admin pages](#operator--admin-pages)
|
||||||
|
4. [Status flow](#status-flow)
|
||||||
|
5. [Settings page explained](#settings-page-explained)
|
||||||
|
6. [Docker installation](#docker-installation)
|
||||||
|
7. [Environment variables](#environment-variables)
|
||||||
|
8. [File layout](#file-layout)
|
||||||
|
9. [Local development](#local-development)
|
||||||
|
10. [Common troubleshooting](#common-troubleshooting)
|
||||||
|
11. [License / ownership](#license--ownership)
|
||||||
|
|
||||||
- **Admin login** (`/admin/login`) — simple session-based login protected by `ADMIN_PASSWORD`.
|
---
|
||||||
- **Dashboard queue** (`/admin`) — filter by status and auto-refresh at a configurable interval.
|
|
||||||
- **Per-request detail page** (`/admin/request/<id>`):
|
## What the booth does
|
||||||
- Generate and save a Suno prompt from customer info.
|
|
||||||
- One-click copy of request details + a signed callback URL for Hermes.
|
1. A visitor fills out a short form at `/request`.
|
||||||
- Hermes POSTs back the generated Title/Style/Lyrics; status becomes **Prompt Ready** automatically.
|
2. The operator reviews the request in the admin dashboard and generates a Suno Custom Mode prompt.
|
||||||
- Edit all customer info fields (name, email, hobbies, notable facts, style/genre, vocal gender, extra requests).
|
3. The operator (or an AI assistant via the `/api/prompt` callback) saves the prompt to the request.
|
||||||
- View revision history for the request.
|
4. The operator creates two song versions in Suno, downloads them, and uploads **Version A** and **Version B** to the request page.
|
||||||
- Mark the request as **Cancelled**.
|
5. The operator sends a preview email; the customer visits their private player page, listens to both versions, and either approves one/both or requests changes.
|
||||||
- Internal operator notes.
|
6. After the customer approves and pays, the operator records the payment reference and delivers the selected MP3(s) by email.
|
||||||
- Upload Version A and Version B MP3s with automatic ID3 metadata tagging.
|
7. Optional stems / extras can be delivered via a share link that appears on the player page after delivery.
|
||||||
- Send a preview email with a private player link.
|
|
||||||
- Mark paid, enter a Square payment reference, and deliver selected MP3 attachments.
|
---
|
||||||
- Save a Stems / Extras share link that appears on the customer player page after delivery.
|
|
||||||
- **Pricing page** (`/admin/pricing`) — configure fixed prices (One Song, Both Songs, WAV per song, STEMs per song) and up to 5 custom named items.
|
## Customer-facing pages
|
||||||
- **Sales report** (`/admin/sales`) — list all delivered requests with customer details and Square payment references.
|
|
||||||
- **Public kiosk** (`/kiosk`) — full-screen display for a booth tablet. Cycles between the request-form QR code and the price list. Banner switches based on booth open/closed state. Slide timing is configurable in settings.
|
| Page | Path | Purpose |
|
||||||
- **Settings / maintenance page** (`/admin/settings`):
|
|------|------|---------|
|
||||||
- Database health check with optional schema repair.
|
| Request form | `/request` | Visitors enter name, email, hobbies, notable facts, preferred style/genre, vocal gender, and extra requests. Rate limited to 5 submissions per minute per IP. |
|
||||||
- Database statistics, size, upload counts.
|
| Closed page | `/request` (when booth is closed) | Shows a friendly closed banner instead of the form when the operator marks the booth closed. |
|
||||||
- Configure customer revision limit.
|
| Thanks | `/thanks/<id>` | Confirmation page shown after a request is submitted. |
|
||||||
- Configure dashboard auto-refresh interval.
|
| Order status | `/status` | Customers enter their email to see all their requests and statuses. |
|
||||||
- Configure public kiosk cycle mode (QR only, pricing only, or N seconds per slide).
|
| FAQ | `/faq` | Answers common customer questions. |
|
||||||
- Configure SMTP host/port/user/from; store the SMTP password encrypted.
|
| Private player | `/play/<token>` | Secret link emailed to the customer. Streams Version A and B, lets them approve or request revisions, and later download delivered files / stems. |
|
||||||
- Configure default MP3 metadata tags (artist, album, year, comment).
|
| Kiosk | `/kiosk` | Public full-screen display for a booth tablet. Cycles between a QR code for `/request` and the configured price list. Updates automatically when pricing or booth state changes. |
|
||||||
- Generate/regenerate the Hermes API key used by the prompt callback endpoint (shown once, otherwise masked).
|
|
||||||
- Download or restore the SQLite database backup.
|
---
|
||||||
- Download all uploaded music files as a ZIP backup.
|
|
||||||
- Send a test email.
|
## Operator / admin pages
|
||||||
- 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.
|
| Page | Path | Purpose |
|
||||||
|
|------|------|---------|
|
||||||
|
| 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. |
|
||||||
|
| Request detail | `/admin/request/<id>` | Full control of one request: edit customer info, save prompt, copy Hermes callback, view revision history, upload MP3s, send preview, record payment, deliver files, add operator notes, and cancel. |
|
||||||
|
| Pricing | `/admin/pricing` | Configure fixed prices (one song, both songs, WAV per song, STEMs per song) and up to 5 custom items. |
|
||||||
|
| 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, and system reset. |
|
||||||
|
| Reset | `/admin/reset` | Clears all requests and uploaded files. Requires admin password confirmation. |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
## Status flow
|
## Status flow
|
||||||
|
|
||||||
|
|
@ -56,43 +69,147 @@ pending → prompt_ready → songs_uploaded → awaiting_payment → paid → de
|
||||||
```
|
```
|
||||||
|
|
||||||
| Status | Meaning |
|
| Status | Meaning |
|
||||||
|---|---|
|
|--------|---------|
|
||||||
| `pending` | Customer submitted a request; operator has not saved a prompt yet. |
|
| `pending` | Customer submitted; waiting for a Suno prompt. |
|
||||||
| `prompt_ready` | Hermes POSTed back the generated Suno prompt, or the operator saved it manually. |
|
| `prompt_ready` | Prompt saved; ready to generate songs. |
|
||||||
| `songs_uploaded` | Both MP3s uploaded; preview link can be sent. |
|
| `songs_uploaded` | Both MP3s uploaded; preview link can be sent. |
|
||||||
| `revisions_requested` | Customer asked for changes; current files were archived. |
|
| `revisions_requested` | Customer asked for changes; current files archived. |
|
||||||
| `awaiting_payment` | Customer approved a version; waiting for operator to collect payment and deliver. |
|
| `awaiting_payment` | Customer approved a version; waiting for payment. |
|
||||||
| `paid` | Payment recorded internally. |
|
| `paid` | Payment recorded. |
|
||||||
| `delivered` | MP3 attachment(s) emailed to the customer. |
|
| `delivered` | Final MP3(s) emailed to the customer. |
|
||||||
| `cancelled` | Request was cancelled by the operator. |
|
| `cancelled` | Request cancelled by the operator. |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Settings page explained
|
||||||
|
|
||||||
|
The `/admin/settings` page is split into functional sections:
|
||||||
|
|
||||||
|
### Booth state
|
||||||
|
- **Booth open / closed** — When closed, `/request` and `/kiosk` show the closed banner.
|
||||||
|
|
||||||
|
### Hermes API key
|
||||||
|
- Displays whether a key is configured.
|
||||||
|
- **Regenerate API Key** creates a new random key stored in runtime settings.
|
||||||
|
- The key is used by the `/api/prompt/<id>` callback and by the `/api/key-test` diagnostic endpoint.
|
||||||
|
- Copy this key into your Hermes skill or AI assistant config.
|
||||||
|
|
||||||
|
### Customer revision limit
|
||||||
|
- Maximum number of times a customer can click **Request Changes** on the player page.
|
||||||
|
- Default is controlled by `MAX_REVISIONS` env var; can be overridden here.
|
||||||
|
|
||||||
|
### Dashboard refresh
|
||||||
|
- How often `/admin` reloads automatically (10, 20, or 30 seconds).
|
||||||
|
|
||||||
|
### Kiosk display
|
||||||
|
- **QR only** — shows the QR code permanently.
|
||||||
|
- **Pricing only** — shows the price list permanently.
|
||||||
|
- **Cycle every N seconds** — alternates between QR and pricing.
|
||||||
|
|
||||||
|
### SMTP settings
|
||||||
|
- Host, port, username, from address, and password for sending customer emails.
|
||||||
|
- The password is encrypted using `APP_SECRET_KEY` before being saved.
|
||||||
|
- **Send Test Email** verifies the configuration.
|
||||||
|
|
||||||
|
### MP3 metadata defaults
|
||||||
|
- Artist, album, year, and comment tags applied automatically to uploaded MP3s.
|
||||||
|
- The title tag is taken from the saved Suno prompt.
|
||||||
|
|
||||||
|
### Database maintenance
|
||||||
|
- **Health Check** — verifies all expected tables and columns exist.
|
||||||
|
- **Fix Database Schema** — adds missing tables/columns without deleting data.
|
||||||
|
- **Download Database Backup** — downloads the SQLite file.
|
||||||
|
- **Restore Database Backup** — replaces the live DB with an uploaded backup.
|
||||||
|
- **Download Uploads Backup** — ZIPs all uploaded MP3s for offline storage.
|
||||||
|
- **System Reset** — deletes all requests and uploaded files for a fresh event.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Docker installation
|
||||||
|
|
||||||
|
### 1. Prepare environment variables
|
||||||
|
|
||||||
|
Generate values for the required secrets:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
python3 -c "import secrets; print(secrets.token_hex(32))"
|
||||||
|
```
|
||||||
|
|
||||||
|
Use the output for `APP_SECRET_KEY`.
|
||||||
|
|
||||||
|
### 2. Deploy with Portainer
|
||||||
|
|
||||||
|
1. Log in to Portainer.
|
||||||
|
2. Go to **Stacks** → **Add stack**.
|
||||||
|
3. Choose **Repository**:
|
||||||
|
- URL: `https://gitlab.hallsworth.ca/yrtria/theme-song-booth.git`
|
||||||
|
- Branch: `main`
|
||||||
|
- Compose path: `docker-compose.yml`
|
||||||
|
4. Add the environment variables listed in the section below.
|
||||||
|
5. Deploy the stack.
|
||||||
|
6. Open a console in the running `theme-song-booth` container and run once:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
python init_db.py
|
||||||
|
```
|
||||||
|
|
||||||
|
7. Point your reverse proxy at the host port you chose (default `127.0.0.1:8000`).
|
||||||
|
8. Visit `/admin/settings` and click **Regenerate API Key**.
|
||||||
|
9. Copy the key to your Hermes skill / AI assistant.
|
||||||
|
10. Print or display a QR code pointing to `https://your-domain/request`.
|
||||||
|
|
||||||
|
### Updating the deployment
|
||||||
|
|
||||||
|
After each push to GitLab:
|
||||||
|
|
||||||
|
```text
|
||||||
|
Portainer → Stacks → theme-song-booth → Pull and redeploy
|
||||||
|
```
|
||||||
|
|
||||||
|
Persistent volumes keep the database and uploads safe across redeploys.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Environment variables
|
||||||
|
|
||||||
|
| Variable | Required | Default | Description |
|
||||||
|
|----------|----------|---------|-------------|
|
||||||
|
| `APP_SECRET_KEY` | Yes | — | Long random string for Flask sessions and for encrypting stored settings such as the SMTP password and legacy stored API key. |
|
||||||
|
| `ADMIN_PASSWORD` | Yes | — | Password used to log in to `/admin`. |
|
||||||
|
| `SMTP_PASS` | Yes | — | Password for the SMTP account used to send customer emails. |
|
||||||
|
| `PUBLIC_BASE_URL` | Yes | — | Public HTTPS URL of the booth, e.g. `https://booth.dionysismedia.ca`. Used in player links, emails, and callback URLs. |
|
||||||
|
| `SMTP_HOST` | No | `mailroot8.namespro.ca` | SMTP server hostname. |
|
||||||
|
| `SMTP_PORT` | No | `465` | SMTP server port. |
|
||||||
|
| `SMTP_USER` | No | `ai@hallsworth.ca` | SMTP username. |
|
||||||
|
| `SMTP_FROM` | No | `ai@hallsworth.ca` | From address for customer emails. |
|
||||||
|
| `BOOTH_NAME` | No | `Trollgorithm Theme Songs` | Display name used in email subjects and page titles. |
|
||||||
|
| `HOST_PORT` | No | `127.0.0.1:8000` | Host-side `ip:port` mapping for the container. |
|
||||||
|
| `INTERNAL_PORT` | No | `8000` | Port gunicorn binds to inside the container. |
|
||||||
|
| `PRICE_PER_VERSION` | No | `10.00` | Legacy price label shown in some templates; current pricing is configured from `/admin/pricing`. |
|
||||||
|
| `CURRENCY` | No | `CAD` | Currency label shown with prices. |
|
||||||
|
| `MAX_REVISIONS` | No | `2` | Default customer revision limit before an operator override. |
|
||||||
|
| `HERMES_API_KEY` | No | — | API key for the `/api/prompt` callback. If omitted, generate one from `/admin/settings`. |
|
||||||
|
| `DATABASE` | No | `/app/data/booth.db` | Path to the SQLite database inside the container. |
|
||||||
|
| `UPLOAD_FOLDER` | No | `/app/uploads` | Path to uploaded MP3 storage inside the container. |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
## File layout
|
## File layout
|
||||||
|
|
||||||
| File | Purpose |
|
| File | Purpose |
|
||||||
|---|---|
|
|------|---------|
|
||||||
| `app.py` | Flask routes, helpers, email layer, runtime settings, MP3 tagging, rate limiting, DB maintenance, Hermes callback endpoint, kiosk route, pricing route, sales report, and ZIP backup. |
|
| `app.py` | Flask routes, helpers, email layer, runtime settings, MP3 tagging, rate limiting, database maintenance, Hermes callback, kiosk, pricing, and sales report. |
|
||||||
| `config.py` | Environment-variable based configuration; defines defaults for DB, uploads, SMTP, secrets, and `HERMES_API_KEY`. |
|
| `config.py` | Environment-variable based configuration with sensible defaults. |
|
||||||
| `models.py` | SQLite schema + CRUD. `player_token` is a secret URL-safe token. Includes revision history table. |
|
| `models.py` | SQLite schema, CRUD helpers, and revision history. |
|
||||||
| `init_db.py` | Run once after deploy: `python init_db.py`. |
|
| `init_db.py` | Standalone script to create or migrate the database. |
|
||||||
| `templates/admin/dashboard.html` | Queue table + filters + auto-refresh + topbar links to Kiosk, Pricing, Sales, Settings. |
|
| `templates/` | Jinja2 templates for customer pages, admin pages, and kiosk display. |
|
||||||
| `templates/admin/request.html` | Single-request detail page: customer info editing, revision history, operator notes, prompt fields, upload/delivery, cancel action. |
|
| `static/` | Banner images, closed banner, email logo, and kiosk QR code. |
|
||||||
| `templates/admin/settings.html` | Maintenance, settings, backup/restore, reset, kiosk mode, Hermes API key display. |
|
| `Dockerfile` | Production container image definition. |
|
||||||
| `templates/admin/pricing.html` | Configure fixed and custom pricing items. |
|
|
||||||
| `templates/admin/sales.html` | Delivered request sales report. |
|
|
||||||
| `templates/status.html` | Customer order status lookup. |
|
|
||||||
| `templates/faq.html` | Customer FAQ page. |
|
|
||||||
| `templates/player.html` | Customer audio player, approval, revision form, stems download button. |
|
|
||||||
| `templates/kiosk.html` | Public full-screen kiosk page with QR/pricing cycling and open/closed banner. |
|
|
||||||
| `templates/admin/login.html` | Admin login page. |
|
|
||||||
| `static/Trollgorithm_booth.jpg` | Banner image shown when booth is open. |
|
|
||||||
| `static/Booth_closed.png` | Banner image shown when booth is closed. |
|
|
||||||
| `static/DM-Logo_email.png` | Inline Dionysis Media logo attached to emails. |
|
|
||||||
| `static/qr-code.png` | QR code displayed on the kiosk page. |
|
|
||||||
| `Dockerfile` | Production container image. |
|
|
||||||
| `docker-compose.yml` | Portainer stack definition. |
|
| `docker-compose.yml` | Portainer stack definition. |
|
||||||
| `requirements.txt` | Python dependencies. |
|
| `requirements.txt` | Python dependencies. |
|
||||||
| `.env.example` | Template for local environment variables. |
|
| `.env.example` | Local development environment template. |
|
||||||
| `REVIEW.md` | Quick-reference for returning to this project. |
|
|
||||||
|
---
|
||||||
|
|
||||||
## Local development
|
## Local development
|
||||||
|
|
||||||
|
|
@ -111,71 +228,21 @@ Visit:
|
||||||
- Admin login: http://127.0.0.1:5000/admin
|
- Admin login: http://127.0.0.1:5000/admin
|
||||||
- Kiosk: http://127.0.0.1:5000/kiosk
|
- Kiosk: http://127.0.0.1:5000/kiosk
|
||||||
|
|
||||||
## Deployment with Portainer
|
---
|
||||||
|
|
||||||
1. Log in to Portainer.
|
|
||||||
2. Go to **Stacks** → **Add 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 | Name used in emails, default `Trollgorithm Theme Songs`. |
|
|
||||||
| `PRICE_PER_VERSION` | No | Shown to the operator/customer, default `10.00`. |
|
|
||||||
| `CURRENCY` | No | Currency label, default `CAD`. |
|
|
||||||
| `MAX_REVISIONS` | No | Default customer revision limit if not changed in settings, default `2`. |
|
|
||||||
| `HERMES_API_KEY` | No | API key for the `/api/prompt` callback. If omitted, generate one from `/admin/settings`. |
|
|
||||||
|
|
||||||
5. Deploy the stack.
|
|
||||||
6. Open a console in the `theme-song-booth` container and run once:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
python init_db.py
|
|
||||||
```
|
|
||||||
|
|
||||||
7. Point your reverse proxy at the `HOST_PORT` you chose.
|
|
||||||
8. Visit `/admin/settings` and click **Regenerate API Key** to create the Hermes callback key.
|
|
||||||
9. Update your Hermes skill or config with the new key and the booth public URL.
|
|
||||||
10. Print or display a QR code pointing to `https://your-domain/request`.
|
|
||||||
|
|
||||||
### Updating the deployment
|
|
||||||
|
|
||||||
After each push to GitLab, go to Portainer → **Stacks** → `theme-song-booth` → **Pull 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, MP3 metadata defaults, pricing, and kiosk cycle mode 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` and `/kiosk` show the closed banner.
|
|
||||||
- **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.
|
|
||||||
- **Stems / Extras delivery.** Operators paste a file-share link from Pingvin Share (or similar) into the request page. The link appears as a download button on the customer player page after delivery.
|
|
||||||
- **Kiosk page.** Public, no login. Shows the open/closed banner, cycles between the request-form QR code and the configured price list, and auto-refreshes so updates to pricing or booth state appear.
|
|
||||||
- **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 in `booth_settings.json` and masked in the admin UI.
|
|
||||||
|
|
||||||
## Common troubleshooting
|
## Common troubleshooting
|
||||||
|
|
||||||
| Problem | Cause | Fix |
|
| 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. |
|
| 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. |
|
| 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. |
|
| 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. |
|
| Logo missing from email | Logo file missing from `static/`. | Ensure `static/DM-Logo_email.png` is in the container. |
|
||||||
| Database schema mismatch | New column/table added but old DB not migrated. | Go to `/admin/settings` and click **Fix Database Schema**, or run `python init_db.py`. |
|
| Database schema mismatch | New column/table added but old DB not migrated. | Go to `/admin/settings` and click **Fix Database Schema**, or run `python init_db.py`. |
|
||||||
| Kiosk shows old prices | Page auto-refreshes every 30s; check `/admin/pricing`. | Verify pricing values and redeploy if templates changed. |
|
| Kiosk shows old prices | Page auto-refreshes every 30s; check `/admin/pricing`. | Verify pricing values and redeploy if templates changed. |
|
||||||
|
| `/api/prompt` returns 401 | Callback token expired or API key mismatch. | Copy a fresh callback URL from `/admin/request/<id>` and verify the key with `/api/key-test`. |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
## License / ownership
|
## License / ownership
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -79,8 +79,9 @@ class Config:
|
||||||
# Default customer revision limit if not overridden in runtime settings.
|
# Default customer revision limit if not overridden in runtime settings.
|
||||||
MAX_REVISIONS = int(os.environ.get('MAX_REVISIONS', '2'))
|
MAX_REVISIONS = int(os.environ.get('MAX_REVISIONS', '2'))
|
||||||
|
|
||||||
# API key used by Hermes to POST generated Suno prompts back to the website.
|
# API key used by Hermes / an AI assistant to POST generated Suno prompts
|
||||||
# Also stored (encrypted) in runtime settings so it can be regenerated from /admin/settings.
|
# back to /api/prompt/<id>. If provided via env var it overrides the value
|
||||||
|
# stored in runtime settings. Stored encrypted when set from /admin/settings.
|
||||||
HERMES_API_KEY = os.environ.get('HERMES_API_KEY', '')
|
HERMES_API_KEY = os.environ.get('HERMES_API_KEY', '')
|
||||||
|
|
||||||
# Booth name used in customer-facing text and email sign-offs.
|
# Booth name used in customer-facing text and email sign-offs.
|
||||||
|
|
@ -89,7 +90,8 @@ class Config:
|
||||||
# Internal port gunicorn listens on inside the container (also exposed in Dockerfile).
|
# Internal port gunicorn listens on inside the container (also exposed in Dockerfile).
|
||||||
INTERNAL_PORT = int(os.environ.get('INTERNAL_PORT', '8000'))
|
INTERNAL_PORT = int(os.environ.get('INTERNAL_PORT', '8000'))
|
||||||
|
|
||||||
# Informational price shown to the operator/customer; actual payment is collected manually (e.g. Square).
|
# Legacy single-price label. Current pricing is configured per-item from
|
||||||
|
# /admin/pricing, but this value is still displayed in a few templates.
|
||||||
PRICE_PER_VERSION = float(os.environ.get('PRICE_PER_VERSION', '10.00'))
|
PRICE_PER_VERSION = float(os.environ.get('PRICE_PER_VERSION', '10.00'))
|
||||||
CURRENCY = os.environ.get('CURRENCY', 'CAD')
|
CURRENCY = os.environ.get('CURRENCY', 'CAD')
|
||||||
|
|
||||||
|
|
|
||||||
Reference in a new issue