Files
OverCooked-Installer/s-migrations/000023_user_engagement_and_bot.up.sql
T

81 lines
4.3 KiB
SQL

CREATE TABLE point_rules (
rule_key text PRIMARY KEY CHECK (rule_key ~ '^[a-z0-9][a-z0-9._-]{0,63}$'),
name text NOT NULL CHECK (char_length(btrim(name)) BETWEEN 1 AND 128),
points integer NOT NULL CHECK (points BETWEEN -100000 AND 100000),
enabled boolean NOT NULL DEFAULT true,
description text NOT NULL DEFAULT '' CHECK (char_length(description) <= 1000),
updated_by uuid REFERENCES users(id) ON DELETE SET NULL,
updated_at timestamptz NOT NULL DEFAULT now()
);
INSERT INTO point_rules(rule_key,name,points,description) VALUES
('playback.completed','有效观看',5,'单次观看达到 10 分钟后奖励,每个播放会话仅奖励一次'),
('feedback.accepted','有效反馈',10,'管理员确认媒体问题后奖励');
CREATE TABLE point_accounts (
user_id uuid PRIMARY KEY REFERENCES users(id) ON DELETE CASCADE,
balance bigint NOT NULL DEFAULT 0 CHECK (balance >= 0),
lifetime_earned bigint NOT NULL DEFAULT 0 CHECK (lifetime_earned >= 0),
lifetime_spent bigint NOT NULL DEFAULT 0 CHECK (lifetime_spent >= 0),
updated_at timestamptz NOT NULL DEFAULT now()
);
CREATE TABLE point_ledger (
id bigserial PRIMARY KEY,
user_id uuid NOT NULL REFERENCES users(id) ON DELETE CASCADE,
delta integer NOT NULL CHECK (delta <> 0 AND delta BETWEEN -100000 AND 100000),
balance_after bigint NOT NULL CHECK (balance_after >= 0),
reason text NOT NULL CHECK (char_length(btrim(reason)) BETWEEN 1 AND 200),
source_type text NOT NULL DEFAULT 'manual' CHECK (source_type IN ('manual','playback_session','media_feedback','redemption')),
source_id text NOT NULL DEFAULT '' CHECK (char_length(source_id) <= 128),
actor_user_id uuid REFERENCES users(id) ON DELETE SET NULL,
created_at timestamptz NOT NULL DEFAULT now(),
UNIQUE(user_id,source_type,source_id)
);
CREATE INDEX point_ledger_user_time_idx ON point_ledger(user_id,created_at DESC,id DESC);
CREATE TABLE media_feedback (
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
user_id uuid NOT NULL REFERENCES users(id) ON DELETE CASCADE,
media_id uuid,
source_id uuid,
playback_session_id uuid REFERENCES playback_sessions(id) ON DELETE SET NULL,
category text NOT NULL CHECK (category IN ('playback','subtitle','audio','metadata','quality','other')),
title text NOT NULL CHECK (char_length(btrim(title)) BETWEEN 1 AND 200),
detail text NOT NULL CHECK (char_length(btrim(detail)) BETWEEN 1 AND 5000),
status text NOT NULL DEFAULT 'submitted' CHECK (status IN ('submitted','reviewing','resolved','rejected')),
priority text NOT NULL DEFAULT 'normal' CHECK (priority IN ('low','normal','high','urgent')),
resolution text NOT NULL DEFAULT '' CHECK (char_length(resolution) <= 5000),
assigned_to uuid REFERENCES users(id) ON DELETE SET NULL,
resolved_by uuid REFERENCES users(id) ON DELETE SET NULL,
resolved_at timestamptz,
created_at timestamptz NOT NULL DEFAULT now(),
updated_at timestamptz NOT NULL DEFAULT now()
);
CREATE INDEX media_feedback_user_time_idx ON media_feedback(user_id,created_at DESC);
CREATE INDEX media_feedback_queue_idx ON media_feedback(status,priority,updated_at DESC);
CREATE TABLE telegram_bot_settings (
singleton boolean PRIMARY KEY DEFAULT true CHECK (singleton),
enabled boolean NOT NULL DEFAULT true,
commands_enabled boolean NOT NULL DEFAULT true,
rate_limit_per_minute integer NOT NULL DEFAULT 12 CHECK (rate_limit_per_minute BETWEEN 1 AND 120),
welcome_message text NOT NULL DEFAULT '欢迎使用站点助手,请先绑定账户。' CHECK (char_length(welcome_message) BETWEEN 1 AND 1000),
maintenance_message text NOT NULL DEFAULT '' CHECK (char_length(maintenance_message) <= 1000),
updated_by uuid REFERENCES users(id) ON DELETE SET NULL,
updated_at timestamptz NOT NULL DEFAULT now()
);
INSERT INTO telegram_bot_settings(singleton) VALUES(true);
CREATE TABLE telegram_command_logs (
id bigserial PRIMARY KEY,
telegram_user_id bigint NOT NULL,
user_id uuid REFERENCES users(id) ON DELETE SET NULL,
command text NOT NULL CHECK (char_length(command) BETWEEN 1 AND 64),
result text NOT NULL CHECK (char_length(result) BETWEEN 1 AND 64),
duration_ms integer NOT NULL DEFAULT 0 CHECK (duration_ms >= 0),
created_at timestamptz NOT NULL DEFAULT now()
);
CREATE INDEX telegram_command_logs_rate_idx ON telegram_command_logs(telegram_user_id,created_at DESC);
CREATE INDEX telegram_command_logs_admin_idx ON telegram_command_logs(created_at DESC,id DESC);