Files
GmRelayBot/src/GmRelay.Bot/Migrations/V001__initial_schema.sql
T

71 lines
3.3 KiB
SQL

CREATE EXTENSION IF NOT EXISTS "pgcrypto";
-- =============================================================
-- Players: all known Telegram users who interact with the bot
-- =============================================================
CREATE TABLE players (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
telegram_id BIGINT NOT NULL UNIQUE,
display_name VARCHAR(255) NOT NULL,
telegram_username VARCHAR(255),
created_at TIMESTAMPTZ NOT NULL DEFAULT now()
);
-- =============================================================
-- Game groups: Telegram group chats where games are organized
-- =============================================================
CREATE TABLE game_groups (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
telegram_chat_id BIGINT NOT NULL UNIQUE,
name VARCHAR(255) NOT NULL,
gm_telegram_id BIGINT NOT NULL,
created_at TIMESTAMPTZ NOT NULL DEFAULT now()
);
-- =============================================================
-- Group membership: which players belong to which groups
-- =============================================================
CREATE TABLE game_group_members (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
group_id UUID NOT NULL REFERENCES game_groups(id) ON DELETE CASCADE,
player_id UUID NOT NULL REFERENCES players(id) ON DELETE CASCADE,
is_gm BOOLEAN NOT NULL DEFAULT false,
joined_at TIMESTAMPTZ NOT NULL DEFAULT now(),
UNIQUE (group_id, player_id)
);
-- =============================================================
-- Sessions: individual game sessions with scheduling
-- =============================================================
CREATE TABLE sessions (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
group_id UUID NOT NULL REFERENCES game_groups(id) ON DELETE CASCADE,
title VARCHAR(500) NOT NULL,
join_link TEXT NOT NULL,
scheduled_at TIMESTAMPTZ NOT NULL,
status VARCHAR(50) NOT NULL DEFAULT 'Planned'
CHECK (status IN ('Planned','ConfirmationSent','Confirmed','Cancelled')),
confirmation_message_id INTEGER,
link_message_id INTEGER,
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT now()
);
-- Partial index: only scan sessions that still need processing
CREATE INDEX ix_sessions_pending ON sessions (scheduled_at)
WHERE status IN ('Planned', 'ConfirmationSent', 'Confirmed');
-- =============================================================
-- Session participants: per-session RSVP tracking
-- =============================================================
CREATE TABLE session_participants (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
session_id UUID NOT NULL REFERENCES sessions(id) ON DELETE CASCADE,
player_id UUID NOT NULL REFERENCES players(id) ON DELETE CASCADE,
is_gm BOOLEAN NOT NULL DEFAULT false,
rsvp_status VARCHAR(50) NOT NULL DEFAULT 'Pending'
CHECK (rsvp_status IN ('Pending','Confirmed','Declined')),
responded_at TIMESTAMPTZ,
UNIQUE (session_id, player_id)
);