Spaces:
Sleeping
Sleeping
File size: 4,693 Bytes
d9a03db | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 | -- SQL Script to initialize the Supabase PostgreSQL database
-- Copy and paste this into the Supabase SQL Editor (SQL Editor -> New Query)
-- 1. STREAMS TABLE
CREATE TABLE IF NOT EXISTS streams (
id SERIAL PRIMARY KEY,
start_time TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
end_time TIMESTAMP WITH TIME ZONE,
title TEXT,
twitch_stream_id TEXT UNIQUE,
category TEXT,
backfill_status TEXT DEFAULT 'pending',
twitch_vod_id TEXT
);
-- 2. MESSAGES TABLE
CREATE TABLE IF NOT EXISTS messages (
id TEXT PRIMARY KEY, -- Twitch Message ID (UUID-like from tags)
stream_id INTEGER REFERENCES streams(id) ON DELETE SET NULL,
username TEXT NOT NULL,
display_name TEXT,
message TEXT NOT NULL,
timestamp TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
is_streamer BOOLEAN DEFAULT FALSE,
is_mod BOOLEAN DEFAULT FALSE,
is_sub BOOLEAN DEFAULT FALSE
);
-- Create indexes for fast querying and statistics aggregation
CREATE INDEX IF NOT EXISTS idx_messages_stream_id ON messages(stream_id);
CREATE INDEX IF NOT EXISTS idx_messages_username ON messages(username);
CREATE INDEX IF NOT EXISTS idx_messages_timestamp ON messages(timestamp);
-- 2.5 STREAM VIEWERS TABLE
CREATE TABLE IF NOT EXISTS stream_viewers (
stream_id INTEGER REFERENCES streams(id) ON DELETE CASCADE,
username TEXT NOT NULL,
display_name TEXT,
has_chatted BOOLEAN DEFAULT FALSE,
is_mod BOOLEAN DEFAULT FALSE,
is_sub BOOLEAN DEFAULT FALSE,
first_seen TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (stream_id, username)
);
CREATE INDEX IF NOT EXISTS idx_stream_viewers_stream_id ON stream_viewers(stream_id);
-- 3. VOICE WORDS TABLE (transcribed spoken words from streamer)
CREATE TABLE IF NOT EXISTS voice_words (
id SERIAL PRIMARY KEY,
stream_id INTEGER REFERENCES streams(id) ON DELETE CASCADE,
word TEXT NOT NULL,
timestamp TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP
);
CREATE INDEX IF NOT EXISTS idx_voice_words_stream_id ON voice_words(stream_id);
CREATE INDEX IF NOT EXISTS idx_voice_words_word ON voice_words(word);
-- 4. MOD ACTIONS TABLE (from EventSub: bans, timeouts, message deletions)
CREATE TABLE IF NOT EXISTS mod_actions (
id SERIAL PRIMARY KEY,
stream_id INTEGER REFERENCES streams(id) ON DELETE SET NULL,
action_type TEXT NOT NULL, -- 'ban', 'timeout', 'unban', 'delete'
moderator TEXT NOT NULL, -- Moderator's username
target_user TEXT, -- Banned/timed out user's username
duration INTEGER, -- Timeout duration in seconds (NULL for bans/deletions)
reason TEXT, -- Reason provided
message_text TEXT, -- Text of deleted message (for 'delete' action)
timestamp TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
reaction_time REAL
);
CREATE INDEX IF NOT EXISTS idx_mod_actions_stream_id ON mod_actions(stream_id);
CREATE INDEX IF NOT EXISTS idx_mod_actions_timestamp ON mod_actions(timestamp);
-- 5. SETTINGS TABLE (for persistent oauth tokens, etc.)
CREATE TABLE IF NOT EXISTS settings (
key TEXT PRIMARY KEY,
value TEXT NOT NULL,
updated_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP
);
-- A trigger to automatically update updated_at in settings table
CREATE OR REPLACE FUNCTION update_modified_column()
RETURNS TRIGGER AS $$
BEGIN
NEW.updated_at = now();
RETURN NEW;
END;
$$ language 'plpgsql';
CREATE OR REPLACE TRIGGER update_settings_modtime
BEFORE UPDATE ON settings
FOR EACH ROW
EXECUTE FUNCTION update_modified_column();
-- =========================================================================
-- HELPER VIEWS FOR STATISTICS
-- =========================================================================
-- View for chatter statistics per stream
CREATE OR REPLACE VIEW stream_chatter_stats AS
SELECT
stream_id,
username,
max(display_name) as display_name,
bool_or(is_mod) as is_mod,
bool_or(is_sub) as is_sub,
count(*) as message_count
FROM messages
GROUP BY stream_id, username;
-- View for chatter statistics overall (all-time)
CREATE OR REPLACE VIEW global_chatter_stats AS
SELECT
username,
max(display_name) as display_name,
bool_or(is_mod) as is_mod,
bool_or(is_sub) as is_sub,
count(*) as message_count
FROM messages
GROUP BY username;
-- View for spoken word statistics per stream
CREATE OR REPLACE VIEW stream_voice_word_stats AS
SELECT
stream_id,
word,
count(*) as word_count
FROM voice_words
GROUP BY stream_id, word;
-- View for spoken word statistics overall (all-time)
CREATE OR REPLACE VIEW global_voice_word_stats AS
SELECT
word,
count(*) as word_count
FROM voice_words
GROUP BY word;
|