Files
MusicServer/internal/db/migrations/000006_add_fingerprint_and_queue.up.sql
T
SansanandClaude Opus 5.5 bb8de5548d
CI / docker (push) Failing after 22s
CI / integration (push) Successful in 26s
CI / test (push) Successful in 26s
CI / publish (push) Skipped
Add alternative names and cover art for soundtracks
Alternative names (#32):
- PUT /api/v1/soundtracks/{uuid}/alternative-names replaces a soundtrack's
  alternative names (trimmed, deduplicated, without the soundtrack's own name).
- alternative_names is in the soundtrack and statistics responses.
- /find matches them too and shows which name matched.

Covers (#12), stored in COVERS_PATH and off when it is not set:
- GET, PUT (upload) and DELETE /api/v1/soundtracks/{uuid}/cover, and
  PUT .../cover/source to pick a SteamGridDB game or AniList anime by ID.
  Uploaded and picked covers are never replaced automatically.
- With STEAMGRIDDB_API_KEY, a background job searches SteamGridDB, then
  AniList, by name, alternative names and the name without bracketed parts,
  at startup, after a sync and after names change. Search results are ranked
  by matching words, so "Civilization IV" gets "Sid Meier's Civilization IV".
- cover_modified (Unix seconds) is in the soundtrack and statistics responses,
  so clients can cache covers.

The new columns are added to migration 000006, which is not released yet.

Closes #12, closes #32

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 21:57:18 +02:00

44 lines
2.1 KiB
SQL

-- Cheap fingerprint (file names, sizes and modification times) used to skip
-- content hashing of soundtracks that have not changed since the last sync.
ALTER TABLE soundtrack ADD COLUMN fingerprint TEXT NOT NULL DEFAULT '';
-- Play queues. Every client has its own queue, identified by the queue's UUID.
-- Ended queues are kept as history.
CREATE TABLE queue (
uuid UUID PRIMARY KEY DEFAULT gen_random_uuid(),
current_song INT4 NOT NULL DEFAULT -1,
-- The last random song, added to the queue by /music/addQue, and how it was picked.
last_fetched_song_uuid UUID NULL,
last_fetched_mode VARCHAR(10) NULL,
started_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
ended_at TIMESTAMPTZ NULL
);
CREATE INDEX idx_queue_active ON queue(uuid) WHERE ended_at IS NULL;
-- song_uuid has no foreign key: a sync can delete songs. The names are kept for the history.
CREATE TABLE queue_song (
queue_uuid UUID NOT NULL REFERENCES queue(uuid) ON DELETE CASCADE,
song_no INT4 NOT NULL,
song_uuid UUID NOT NULL,
soundtrack_name VARCHAR NOT NULL,
song_name VARCHAR NOT NULL,
-- How the song was picked: random, low or classic.
mode VARCHAR(10) NOT NULL,
added_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
PRIMARY KEY (queue_uuid, song_no)
);
-- Other names a soundtrack is known by, for search and the cover search.
ALTER TABLE soundtrack ADD COLUMN alternative_names TEXT[] NOT NULL DEFAULT '{}';
-- Cover art. cover_file is the image's file name in COVERS_PATH, NULL when there is no
-- cover. Manual covers (uploaded or picked) are never replaced by the background job.
-- cover_checked is when the job last searched, so soundtracks without a match are not
-- searched again for a while.
ALTER TABLE soundtrack ADD COLUMN cover_file TEXT NULL;
ALTER TABLE soundtrack ADD COLUMN cover_source VARCHAR(20) NULL;
ALTER TABLE soundtrack ADD COLUMN cover_external_id TEXT NULL;
ALTER TABLE soundtrack ADD COLUMN cover_manual BOOLEAN NOT NULL DEFAULT false;
ALTER TABLE soundtrack ADD COLUMN cover_modified TIMESTAMPTZ NULL;
ALTER TABLE soundtrack ADD COLUMN cover_checked TIMESTAMPTZ NULL;