TrackEntry gets a QueueID generated once when a track is queued and kept for its whole life there, and musicrepo.ReplaceQueue now upserts by that ID instead of deleting and reinserting the whole queue on every sync (which churned every track's database id constantly, even ones that hadn't moved, and would've made remove/reorder commands target the wrong track). RemoveFromQueue and Reorder are new Manager functions built on top of that stable identity. Also adds repeat_song/ repeat_queue to the persisted now-playing state, and makes the two existing toggle functions actually sync it, they never did before.
179 lines
5.1 KiB
SQL
179 lines
5.1 KiB
SQL
-- PostgreSQL schema for Velox
|
|
-- Use BIGINT for Discord snowflakes, INT for smaller counters, BOOLEAN properly.
|
|
|
|
CREATE TABLE IF NOT EXISTS levels (
|
|
guild BIGINT NOT NULL,
|
|
user_id BIGINT NOT NULL,
|
|
level INT NOT NULL DEFAULT 0,
|
|
xp BIGINT NOT NULL DEFAULT 0,
|
|
PRIMARY KEY (guild, user_id)
|
|
);
|
|
|
|
CREATE TABLE IF NOT EXISTS twitch (
|
|
twitch_user TEXT NOT NULL,
|
|
guild_id BIGINT NOT NULL,
|
|
status TEXT NOT NULL DEFAULT 'not live',
|
|
PRIMARY KEY (twitch_user, guild_id)
|
|
);
|
|
|
|
CREATE TABLE IF NOT EXISTS levelsettings (
|
|
guild_id BIGINT PRIMARY KEY,
|
|
levelsys BOOLEAN NOT NULL DEFAULT FALSE,
|
|
message TEXT
|
|
);
|
|
|
|
-- Role rewards per level (supports multiple rewards per guild)
|
|
CREATE TABLE IF NOT EXISTS levelrewards (
|
|
guild_id BIGINT NOT NULL,
|
|
levelreq INT NOT NULL,
|
|
role BIGINT NOT NULL,
|
|
PRIMARY KEY (guild_id, levelreq)
|
|
);
|
|
|
|
CREATE TABLE IF NOT EXISTS welcome (
|
|
guild_id BIGINT PRIMARY KEY,
|
|
welcome_channel_id BIGINT,
|
|
welcome_message TEXT,
|
|
welcome_dm TEXT,
|
|
welcome_gif_url TEXT
|
|
);
|
|
|
|
CREATE TABLE IF NOT EXISTS levelup (
|
|
guild_id BIGINT PRIMARY KEY,
|
|
levelup_channel_id BIGINT
|
|
);
|
|
|
|
CREATE TABLE IF NOT EXISTS twitch_config (
|
|
guild_id BIGINT PRIMARY KEY,
|
|
twitch_channel_id BIGINT,
|
|
enabled BOOLEAN NOT NULL DEFAULT TRUE
|
|
);
|
|
|
|
CREATE TABLE IF NOT EXISTS rps (
|
|
guild_id BIGINT NOT NULL,
|
|
user_id BIGINT NOT NULL,
|
|
score INT NOT NULL DEFAULT 0,
|
|
PRIMARY KEY (guild_id, user_id)
|
|
);
|
|
|
|
CREATE TABLE IF NOT EXISTS defaultrole (
|
|
guild_id BIGINT PRIMARY KEY,
|
|
role_id BIGINT
|
|
);
|
|
|
|
CREATE TABLE IF NOT EXISTS logsettings (
|
|
guild_id BIGINT PRIMARY KEY,
|
|
log_channel_id BIGINT,
|
|
is_enabled BOOLEAN NOT NULL DEFAULT FALSE
|
|
);
|
|
|
|
-- Meeting rooms (voice lobby -> auto-created temporary voice channels)
|
|
CREATE TABLE IF NOT EXISTS meeting_settings (
|
|
guild_id BIGINT PRIMARY KEY,
|
|
lobby_channel_id BIGINT
|
|
);
|
|
|
|
CREATE TABLE IF NOT EXISTS meeting_temp_channels (
|
|
guild_id BIGINT NOT NULL,
|
|
channel_id BIGINT NOT NULL,
|
|
created_by BIGINT NOT NULL,
|
|
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
PRIMARY KEY (guild_id, channel_id)
|
|
);
|
|
|
|
-- Projects & members
|
|
CREATE TABLE IF NOT EXISTS projects (
|
|
id BIGSERIAL PRIMARY KEY,
|
|
guild_id BIGINT NOT NULL,
|
|
name TEXT NOT NULL,
|
|
description TEXT,
|
|
is_active BOOLEAN NOT NULL DEFAULT TRUE,
|
|
created_by BIGINT NOT NULL,
|
|
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
|
);
|
|
|
|
CREATE TABLE IF NOT EXISTS project_members (
|
|
project_id BIGINT NOT NULL REFERENCES projects(id) ON DELETE CASCADE,
|
|
user_id BIGINT NOT NULL,
|
|
is_creator BOOLEAN NOT NULL DEFAULT FALSE,
|
|
PRIMARY KEY (project_id, user_id)
|
|
);
|
|
|
|
--
|
|
-- Scheduling (one-to-one sessions)
|
|
--
|
|
CREATE TABLE IF NOT EXISTS schedules (
|
|
id BIGSERIAL PRIMARY KEY,
|
|
guild_id BIGINT NOT NULL,
|
|
requester_id BIGINT NOT NULL,
|
|
invitee_id BIGINT NOT NULL,
|
|
scheduled_at TIMESTAMPTZ NOT NULL,
|
|
status TEXT NOT NULL DEFAULT 'pending', -- pending, accepted, declined, reschedule_requested
|
|
description TEXT,
|
|
reminder_sent BOOLEAN NOT NULL DEFAULT FALSE,
|
|
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
-- Reschedule negotiation: a proposed new time awaiting the counterpart's
|
|
-- response, kept separate from scheduled_at until accepted.
|
|
proposed_at TIMESTAMPTZ,
|
|
proposed_by BIGINT,
|
|
-- Snapshot of status before entering reschedule_requested, so a decline
|
|
-- knows whether to revert to 'pending' or 'accepted'.
|
|
pre_reschedule_status TEXT
|
|
);
|
|
|
|
CREATE TABLE IF NOT EXISTS schedule_messages (
|
|
schedule_id BIGINT NOT NULL REFERENCES schedules(id) ON DELETE CASCADE,
|
|
message_id BIGINT NOT NULL,
|
|
channel_id BIGINT NOT NULL,
|
|
is_dm BOOLEAN NOT NULL DEFAULT TRUE,
|
|
PRIMARY KEY (schedule_id, message_id)
|
|
);
|
|
|
|
CREATE TABLE IF NOT EXISTS user_settings (
|
|
user_id BIGINT PRIMARY KEY,
|
|
timezone TEXT NOT NULL
|
|
);
|
|
|
|
--
|
|
-- Music (dashboard queue view/control - see velox-dashboard-api's
|
|
-- 000010_music migration, this file mirrors it)
|
|
--
|
|
CREATE TABLE IF NOT EXISTS music_settings (
|
|
guild_id BIGINT PRIMARY KEY,
|
|
is_enabled BOOLEAN NOT NULL DEFAULT FALSE
|
|
);
|
|
|
|
CREATE TABLE IF NOT EXISTS music_now_playing (
|
|
guild_id BIGINT PRIMARY KEY,
|
|
track_title TEXT NOT NULL,
|
|
track_url TEXT NOT NULL,
|
|
duration_seconds INT NOT NULL,
|
|
started_at TIMESTAMPTZ NOT NULL,
|
|
paused BOOLEAN NOT NULL DEFAULT FALSE,
|
|
volume INT NOT NULL DEFAULT 100,
|
|
repeat_song BOOLEAN NOT NULL DEFAULT FALSE,
|
|
repeat_queue BOOLEAN NOT NULL DEFAULT FALSE
|
|
);
|
|
|
|
CREATE TABLE IF NOT EXISTS music_queue (
|
|
id BIGSERIAL PRIMARY KEY,
|
|
guild_id BIGINT NOT NULL,
|
|
position INT NOT NULL,
|
|
track_title TEXT NOT NULL,
|
|
track_url TEXT NOT NULL,
|
|
requested_by BIGINT NOT NULL,
|
|
added_at TIMESTAMPTZ DEFAULT NOW(),
|
|
client_id UUID NOT NULL DEFAULT gen_random_uuid(),
|
|
UNIQUE (guild_id, client_id)
|
|
);
|
|
|
|
CREATE TABLE IF NOT EXISTS music_commands (
|
|
id BIGSERIAL PRIMARY KEY,
|
|
guild_id BIGINT NOT NULL,
|
|
command_type TEXT NOT NULL CHECK (command_type IN ('skip', 'pause', 'resume', 'set_volume', 'remove_track', 'reorder', 'repeat_song', 'repeat_queue')),
|
|
payload JSONB,
|
|
requested_by BIGINT NOT NULL,
|
|
created_at TIMESTAMPTZ DEFAULT NOW(),
|
|
processed_at TIMESTAMPTZ
|
|
);
|