908c37f73f
Module manages PostgreSQL (both databases + schema init), qBittorrent (VPN-confined via VPN-Confinement), Jackett, metadata-agregator, musicfs, and the main orchestrator. All services are independently enableable with auto-wired inter-service configuration. Includes NixOS VM test validating PostgreSQL setup, schema initialization, service startup, and directory creation. Ultraworked with [Sisyphus](https://github.com/code-yeongyu/claude-agent) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
167 lines
6.3 KiB
SQL
167 lines
6.3 KiB
SQL
CREATE TYPE monitor_state AS ENUM ('monitored', 'unmonitored', 'excluded');
|
|
|
|
CREATE TABLE artists (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
external_id VARCHAR(255) NOT NULL UNIQUE,
|
|
name VARCHAR(500) NOT NULL,
|
|
artist_type VARCHAR(50),
|
|
country VARCHAR(10),
|
|
genres TEXT[],
|
|
image_url TEXT,
|
|
monitor_state monitor_state NOT NULL DEFAULT 'unmonitored',
|
|
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
|
);
|
|
|
|
CREATE TABLE albums (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
external_id VARCHAR(255) NOT NULL UNIQUE,
|
|
artist_id UUID NOT NULL REFERENCES artists(id) ON DELETE CASCADE,
|
|
title VARCHAR(500) NOT NULL,
|
|
album_type VARCHAR(50),
|
|
release_date DATE,
|
|
total_tracks INT,
|
|
total_discs INT DEFAULT 1,
|
|
label VARCHAR(255),
|
|
genres TEXT[],
|
|
cover_url TEXT,
|
|
monitor_state monitor_state NOT NULL DEFAULT 'unmonitored',
|
|
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
|
);
|
|
|
|
CREATE INDEX idx_albums_artist ON albums(artist_id);
|
|
CREATE INDEX idx_albums_monitored ON albums(monitor_state) WHERE monitor_state = 'monitored';
|
|
|
|
CREATE TABLE tracks (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
external_id VARCHAR(255) NOT NULL UNIQUE,
|
|
album_id UUID NOT NULL REFERENCES albums(id) ON DELETE CASCADE,
|
|
title VARCHAR(500) NOT NULL,
|
|
duration_ms INT,
|
|
isrc VARCHAR(20),
|
|
disc_number INT DEFAULT 1,
|
|
track_number INT NOT NULL,
|
|
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
|
);
|
|
|
|
CREATE INDEX idx_tracks_album ON tracks(album_id);
|
|
|
|
CREATE TABLE torrents (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
album_id UUID NOT NULL REFERENCES albums(id) ON DELETE CASCADE,
|
|
info_hash VARCHAR(40) NOT NULL UNIQUE,
|
|
tracker VARCHAR(100) NOT NULL,
|
|
title TEXT NOT NULL,
|
|
format VARCHAR(20) NOT NULL,
|
|
quality VARCHAR(20),
|
|
source VARCHAR(20),
|
|
bit_depth INT,
|
|
sample_rate INT,
|
|
seeders INT DEFAULT 0,
|
|
peers INT DEFAULT 0,
|
|
size BIGINT,
|
|
track_count INT,
|
|
has_cover_art BOOLEAN DEFAULT FALSE,
|
|
has_cue_sheet BOOLEAN DEFAULT FALSE,
|
|
has_rip_log BOOLEAN DEFAULT FALSE,
|
|
download_link TEXT,
|
|
torrent_file BYTEA,
|
|
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
|
);
|
|
|
|
CREATE INDEX idx_torrents_album ON torrents(album_id);
|
|
CREATE INDEX idx_torrents_album_format ON torrents(album_id, format);
|
|
|
|
CREATE TYPE download_state AS ENUM (
|
|
'pending', 'downloading', 'completed', 'failed', 'seeding', 'paused'
|
|
);
|
|
|
|
CREATE TABLE downloads (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
torrent_id UUID NOT NULL REFERENCES torrents(id) ON DELETE CASCADE,
|
|
album_id UUID NOT NULL,
|
|
format VARCHAR(20) NOT NULL,
|
|
quality VARCHAR(20),
|
|
state download_state NOT NULL DEFAULT 'pending',
|
|
qbit_hash VARCHAR(64),
|
|
save_path TEXT,
|
|
error_message TEXT,
|
|
queued_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
started_at TIMESTAMPTZ,
|
|
completed_at TIMESTAMPTZ,
|
|
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
|
);
|
|
|
|
CREATE UNIQUE INDEX idx_unique_active_torrent
|
|
ON downloads(torrent_id)
|
|
WHERE state NOT IN ('failed');
|
|
|
|
CREATE UNIQUE INDEX idx_unique_owned_album_quality
|
|
ON downloads(album_id, format, quality)
|
|
WHERE state IN ('completed', 'seeding');
|
|
|
|
CREATE INDEX idx_downloads_state ON downloads(state);
|
|
CREATE INDEX idx_downloads_album ON downloads(album_id);
|
|
|
|
CREATE TABLE download_files (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
download_id UUID NOT NULL REFERENCES downloads(id) ON DELETE CASCADE,
|
|
track_id UUID REFERENCES tracks(id),
|
|
file_path TEXT NOT NULL,
|
|
file_size BIGINT NOT NULL,
|
|
file_type VARCHAR(20) NOT NULL,
|
|
sha256_hash VARCHAR(64),
|
|
verified_at TIMESTAMPTZ,
|
|
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
|
);
|
|
|
|
CREATE INDEX idx_download_files_download ON download_files(download_id);
|
|
CREATE INDEX idx_download_files_hash ON download_files(sha256_hash) WHERE sha256_hash IS NOT NULL;
|
|
|
|
CREATE TABLE album_releases (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
album_id UUID NOT NULL REFERENCES albums(id) ON DELETE CASCADE,
|
|
download_id UUID NOT NULL REFERENCES downloads(id) ON DELETE CASCADE,
|
|
format VARCHAR(20) NOT NULL,
|
|
bit_depth INT,
|
|
sample_rate INT,
|
|
channels INT DEFAULT 2,
|
|
is_lossless BOOLEAN NOT NULL DEFAULT FALSE,
|
|
source VARCHAR(20),
|
|
total_size BIGINT NOT NULL DEFAULT 0,
|
|
total_duration_ms INT NOT NULL DEFAULT 0,
|
|
track_count INT NOT NULL DEFAULT 0,
|
|
has_cover_art BOOLEAN DEFAULT FALSE,
|
|
has_cue_sheet BOOLEAN DEFAULT FALSE,
|
|
has_rip_log BOOLEAN DEFAULT FALSE,
|
|
path TEXT NOT NULL,
|
|
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
|
);
|
|
|
|
CREATE INDEX idx_album_releases_album ON album_releases(album_id);
|
|
CREATE UNIQUE INDEX idx_album_releases_download ON album_releases(download_id);
|
|
|
|
CREATE TABLE track_releases (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
album_release_id UUID NOT NULL REFERENCES album_releases(id) ON DELETE CASCADE,
|
|
track_id UUID REFERENCES tracks(id),
|
|
download_file_id UUID REFERENCES download_files(id),
|
|
title VARCHAR(500) NOT NULL,
|
|
track_number INT NOT NULL DEFAULT 1,
|
|
disc_number INT NOT NULL DEFAULT 1,
|
|
duration_ms INT,
|
|
format VARCHAR(20) NOT NULL,
|
|
bit_depth INT,
|
|
sample_rate INT,
|
|
channels INT DEFAULT 2,
|
|
bitrate_kbps INT,
|
|
file_size BIGINT NOT NULL DEFAULT 0,
|
|
file_path TEXT NOT NULL,
|
|
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
|
);
|
|
|
|
CREATE INDEX idx_track_releases_album_release ON track_releases(album_release_id);
|