Files
velox-bot/schema.sql
T
FernandoJVideiraandClaude Opus 5.5 7ae1fa5747 Add /tldr: a private overview of what you missed in a channel
/tldr [since] summarizes the messages in the channel it is run in that the
caller has not been summarized yet, using a small local model on Ollama, and
replies ephemerally. The answer streams into the reply as it is written.

- Per-user, per-channel cursor (tldr_cursors) so each run picks up where the
  last left off; `since:` (e.g. 6h, 2d, max 7d) peeks without moving it.
  First use covers the last 24h, and a stale cursor never reaches back more
  than 7 days.
- Only summarizes channels both the caller and the bot can read.
- The transcript drops bots, system messages, reactions and filler, turns
  links, GIFs, images and files into short tags ([link: site], [image],
  [file: name], preview titles), marks replies, and writes a date marker
  where the chat paused for 3h or more so the model can keep topics apart.
- The prompt asks for one bullet per conversation, oldest first, with a
  worked example; it was tuned against a synthetic chat and a real export
  with qwen3:4b-instruct-2507 (the default model).
- One model call at a time across the bot, one /tldr per user.
- docker-compose: Ollama service (CPU only, 8g memory cap: 6g killed the
  runner mid-request), model pull on startup.

Needs the tldr_cursors migration (velox-dashboard-api 000016).

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-20 18:46:18 +01:00

192 lines
5.6 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', 'add_song', 'stop')),
payload JSONB,
requested_by BIGINT NOT NULL,
created_at TIMESTAMPTZ DEFAULT NOW(),
processed_at TIMESTAMPTZ
);
-- /tldr: the last message each user has already been summarized up to, per
-- channel (000016_tldr_cursors migration, this file mirrors it)
CREATE TABLE IF NOT EXISTS tldr_cursors (
user_id BIGINT NOT NULL,
channel_id BIGINT NOT NULL,
guild_id BIGINT NOT NULL,
last_message_id BIGINT NOT NULL,
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
PRIMARY KEY (user_id, channel_id)
);
CREATE INDEX IF NOT EXISTS tldr_cursors_guild_user_idx ON tldr_cursors (guild_id, user_id);