openvibers/openvibe.live Commits
N-1 fixtures re-recorded from 8654ef6, the release now in production (npm run n-1:record).
Changes
@@@ -1,13 +1,13 @@{"service": "live",-- "release": "8cead3637816b496cbd5657753a8ca8e8555a1e8",-- "recorded_at": "2026-09-29T16:51:44.167Z",++ "release": "8654ef6b86143d4117ff010ce19aa0124a6bcd57",++ "recorded_at": "2026-09-29T17:33:21.954Z","note": "N-1 fixture: written by `npm run n-1:record`, replayed by test/n-1.test.js","manifest": {"service": "live",-- "release": "8cead3637816",-- "released_at": "2026-09-29T15:31:20.000Z",-- "booted_at": "2026-09-29T16:51:37.750Z",++ "release": "8654ef6b8614",++ "released_at": "2026-09-29T17:32:19.000Z",++ "booted_at": "2026-09-29T17:33:19.050Z","contracts_version": "0.71.0","packages": {"openvibe-shared": "1.30.1",@@@ -22,11 +22,11 @@},"shell": {"kind": "script",-- "version": "680853c062b9"++ "version": "a1a892dca8f8"},"server": {"kind": "server",-- "version": "83b6fbd34fe3"++ "version": "ac8c4a25efa6"}},"assets": {@@@ -1043,95 +1043,19 @@},{"method": "GET",-- "path": "/api/channels/moderation/mine",++ "path": "/api/chat-ai/live-captions/n1star?after=0","auth": "anon",-- "status": 401,-- "kind": "json",-- "from": [-- "public/js/app-channel.js"-- ]-- },-- {-- "method": "GET",-- "path": "/api/channels/moderation/mine",-- "auth": "user","status": 200,"kind": "json","reads": {-- "channels": "array",-- "channels[]": "object",-- "channels[].id": "number",-- "channels[].user_id": "number",-- "channels[].title": "string",-- "channels[].description": "string",-- "channels[].category": "null",-- "channels[].tags": "string",-- "channels[].protocol": "string",-- "channels[].is_nsfw": "number",-- "channels[].panels": "string",-- "channels[].default_vod_visibility": "string",-- "channels[].default_clip_visibility": "string",-- "channels[].weather_zip": "null",-- "channels[].weather_detail": "string",-- "channels[].weather_show_location": "number",-- "channels[].control_mode": "string",-- "channels[].anon_controls_enabled": "number",-- "channels[].control_rate_limit_ms": "number",-- "channels[].video_click_enabled": "number",-- "channels[].video_click_rate_limit_ms": "number",-- "channels[].active_control_config_id": "null",-- "channels[].created_at": "string",-- "channels[].updated_at": "string",-- "channels[].clips_allow_creator_delete": "number",-- "channels[].hide_ai_overview": "number",-- "channels[].ai_overview_pref": "string",-- "channels[].ai_derivation_enabled": "number",-- "channels[].ai_category": "null",-- "channels[].offline_screen_type": "string",-- "channels[].offline_screen_url": "null",-- "channels[].offline_html": "null",-- "channels[].offline_css": "null",-- "channels[].social_links": "null",-- "channels[].moderation_settings": "object",-- "channels[].moderation_settings.channel_id": "number",-- "channels[].moderation_settings.slow_mode_seconds": "number",-- "channels[].moderation_settings.followers_only": "number",-- "channels[].moderation_settings.allow_anonymous": "number",-- "channels[].moderation_settings.links_allowed": "number",-- "channels[].moderation_settings.gifs_enabled": "number",-- "channels[].moderation_settings.account_age_gate_hours": "number",-- "channels[].moderation_settings.caps_percentage_limit": "number",-- "channels[].moderation_settings.aggressive_filter": "number",-- "channels[].moderation_settings.max_message_length": "number",-- "channels[].moderation_settings.tts_max_length": "number",-- "channels[].moderation_settings.slur_filter_enabled": "number",-- "channels[].moderation_settings.slur_filter_use_builtin": "number",-- "channels[].moderation_settings.slur_filter_terms": "string",-- "channels[].moderation_settings.slur_filter_regexes": "string",-- "channels[].moderation_settings.slur_filter_nudge_message": "string",-- "channels[].moderation_settings.slur_filter_disabled_categories": "string",-- "channels[].moderation_settings.ip_approval_mode": "number",-- "channels[].moderation_settings.soundboard_enabled": "number",-- "channels[].moderation_settings.soundboard_allow_pitch": "number",-- "channels[].moderation_settings.soundboard_allow_speed": "number",-- "channels[].moderation_settings.soundboard_banned_ids": "string",-- "channels[].moderation_settings.viewer_auto_delete_enabled": "number",-- "channels[].moderation_settings.viewer_delete_all_enabled": "number",-- "channels[].moderation_settings.custom_emotes_enabled": "number",-- "channels[].moderation_settings.custom_sounds_enabled": "number",-- "channels[].moderation_settings.max_sound_seconds": "number",-- "channels[].moderation_settings.uploads_mods_only": "number",-- "channels[].moderation_settings.mods_can_edit_about": "number",-- "channels[].moderation_settings.emote_scale": "number",-- "channels[].moderation_settings.emote_size_min": "number",-- "channels[].moderation_settings.emote_size_max": "number",-- "channels[].moderation_settings.sounds_mods_only": "number",-- "channels[].moderation_settings.sound_min_speed": "number",-- "channels[].moderation_settings.sound_max_speed": "number",-- "channels[].moderation_settings.sound_min_pitch_cents": "number",-- "channels[].moderation_settings.sound_max_pitch_cents": "number",-- "channels[].moderation_settings.sub_only": "number",-- "channels[].moderators": "array"++ "language": "object",++ "language.code": "string",++ "language.name": "string",++ "language.flag": "string",++ "available": "boolean",++ "live": "boolean",++ "stream_id": "number",++ "lines": "array"},"from": ["public/js/app-channel.js"@@@ -1140,7 +1064,7 @@{"method": "GET","path": "/api/chat-ai/live-captions/n1star?after=0",-- "auth": "anon",++ "auth": "user","status": 200,"kind": "json","reads": {@@@ -1159,19 +1083,95 @@},{"method": "GET",-- "path": "/api/chat-ai/live-captions/n1star?after=0",++ "path": "/api/chat-ai/timeline/n1star?offset=0&limit=5",++ "auth": "anon",++ "status": 200,++ "kind": "json",++ "reads": {++ "username": "string",++ "display_name": "string",++ "overview": "null",++ "chatInsight": "null",++ "combinedOverview": "null",++ "sessionCount": "number",++ "momentCount": "number",++ "index": "array",++ "sessions": "array",++ "offset": "number",++ "limit": "number",++ "hasMore": "boolean"++ },++ "from": [++ "public/js/app-channel.js"++ ]++ },++ {++ "method": "GET",++ "path": "/api/chat-ai/timeline/n1star?offset=0&limit=5","auth": "user","status": 200,"kind": "json","reads": {-- "language": "object",-- "language.code": "string",-- "language.name": "string",-- "language.flag": "string",-- "available": "boolean",-- "live": "boolean",-- "stream_id": "number",-- "lines": "array"++ "username": "string",++ "display_name": "string",++ "overview": "null",++ "chatInsight": "null",++ "combinedOverview": "null",++ "sessionCount": "number",++ "momentCount": "number",++ "index": "array",++ "sessions": "array",++ "offset": "number",++ "limit": "number",++ "hasMore": "boolean"++ },++ "from": [++ "public/js/app-channel.js"++ ]++ },++ {++ "method": "GET",++ "path": "/api/chat-ai/timeline/n1star?offset=0&limit=12",++ "auth": "anon",++ "status": 200,++ "kind": "json",++ "reads": {++ "username": "string",++ "display_name": "string",++ "overview": "null",++ "chatInsight": "null",++ "combinedOverview": "null",++ "sessionCount": "number",++ "momentCount": "number",++ "index": "array",++ "sessions": "array",++ "offset": "number",++ "limit": "number",++ "hasMore": "boolean"++ },++ "from": [++ "public/js/app-channel.js"++ ]++ },++ {++ "method": "GET",++ "path": "/api/chat-ai/timeline/n1star?offset=0&limit=12",++ "auth": "user",++ "status": 200,++ "kind": "json",++ "reads": {++ "username": "string",++ "display_name": "string",++ "overview": "null",++ "chatInsight": "null",++ "combinedOverview": "null",++ "sessionCount": "number",++ "momentCount": "number",++ "index": "array",++ "sessions": "array",++ "offset": "number",++ "limit": "number",++ "hasMore": "boolean"},"from": ["public/js/app-channel.js"@@@ -1909,202 +1909,6 @@"public/js/app-home.js"]},-- {-- "method": "GET",-- "path": "/api/emotes/all/1",-- "auth": "anon",-- "status": 200,-- "kind": "json",-- "reads": {-- "defaults": "array",-- "defaults[]": "object",-- "defaults[].id": "string",-- "defaults[].code": "string",-- "defaults[].url": "string",-- "defaults[].source": "string",-- "defaults[].animated": "boolean",-- "defaults[].width": "number",-- "defaults[].height": "number",-- "channel": "array",-- "global": "array",-- "ffz": "array",-- "bttv": "array",-- "sources": "object",-- "sources.defaults": "boolean",-- "sources.custom": "boolean",-- "sources.ffz": "boolean",-- "sources.bttv": "boolean",-- "emote_scale": "number"-- },-- "from": [-- "public/js/emotes.js"-- ]-- },-- {-- "method": "GET",-- "path": "/api/emotes/all/1",-- "auth": "user",-- "status": 200,-- "kind": "json",-- "reads": {-- "defaults": "array",-- "defaults[]": "object",-- "defaults[].id": "string",-- "defaults[].code": "string",-- "defaults[].url": "string",-- "defaults[].source": "string",-- "defaults[].animated": "boolean",-- "defaults[].width": "number",-- "defaults[].height": "number",-- "channel": "array",-- "global": "array",-- "ffz": "array",-- "bttv": "array",-- "sources": "object",-- "sources.defaults": "boolean",-- "sources.custom": "boolean",-- "sources.ffz": "boolean",-- "sources.bttv": "boolean",-- "emote_scale": "number"-- },-- "from": [-- "public/js/emotes.js"-- ]-- },-- {-- "method": "GET",-- "path": "/api/emotes/all/1?channel=n1star",-- "auth": "anon",-- "status": 200,-- "kind": "json",-- "reads": {-- "defaults": "array",-- "defaults[]": "object",-- "defaults[].id": "string",-- "defaults[].code": "string",-- "defaults[].url": "string",-- "defaults[].source": "string",-- "defaults[].animated": "boolean",-- "defaults[].width": "number",-- "defaults[].height": "number",-- "channel": "array",-- "global": "array",-- "ffz": "array",-- "bttv": "array",-- "sources": "object",-- "sources.defaults": "boolean",-- "sources.custom": "boolean",-- "sources.ffz": "boolean",-- "sources.bttv": "boolean",-- "emote_scale": "number"-- },-- "from": [-- "public/obs/chat.html"-- ]-- },-- {-- "method": "GET",-- "path": "/api/emotes/all/1?channel=n1star",-- "auth": "user",-- "status": 200,-- "kind": "json",-- "reads": {-- "defaults": "array",-- "defaults[]": "object",-- "defaults[].id": "string",-- "defaults[].code": "string",-- "defaults[].url": "string",-- "defaults[].source": "string",-- "defaults[].animated": "boolean",-- "defaults[].width": "number",-- "defaults[].height": "number",-- "channel": "array",-- "global": "array",-- "ffz": "array",-- "bttv": "array",-- "sources": "object",-- "sources.defaults": "boolean",-- "sources.custom": "boolean",-- "sources.ffz": "boolean",-- "sources.bttv": "boolean",-- "emote_scale": "number"-- },-- "from": [-- "public/obs/chat.html"-- ]-- },-- {-- "method": "GET",-- "path": "/api/emotes/mine",-- "auth": "anon",-- "status": 401,-- "kind": "json",-- "from": [-- "public/js/emotes.js"-- ]-- },-- {-- "method": "GET",-- "path": "/api/emotes/mine",-- "auth": "user",-- "status": 200,-- "kind": "json",-- "reads": {-- "emotes": "array",-- "count": "number",-- "max": "number"-- },-- "from": [-- "public/js/emotes.js"-- ]-- },-- {-- "method": "GET",-- "path": "/api/emotes/search?q=n1",-- "auth": "anon",-- "status": 502,-- "kind": "json",-- "from": [-- "public/js/emotes.js"-- ]-- },-- {-- "method": "GET",-- "path": "/api/emotes/search?q=n1",-- "auth": "user",-- "status": 502,-- "kind": "json",-- "from": [-- "public/js/emotes.js"-- ]-- },-- {-- "method": "GET",-- "path": "/api/emotes/sources",-- "auth": "anon",-- "status": 401,-- "kind": "json",-- "from": [-- "public/js/emotes.js"-- ]-- },-- {-- "method": "GET",-- "path": "/api/emotes/sources",-- "auth": "user",-- "status": 200,-- "kind": "json",-- "reads": {-- "sources": "object",-- "sources.defaults": "boolean",-- "sources.custom": "boolean",-- "sources.ffz": "boolean",-- "sources.bttv": "boolean"-- },-- "from": [-- "public/js/emotes.js"-- ]-- },{"method": "GET","path": "/api/funds/balance",@@@ -7295,7 +7099,7 @@},{"method": "GET",-- "path": "/js/app.js?v=533fb6104669",++ "path": "/js/app.js?v=4d24e4b46d7b","auth": "anon","accept": "html","status": 200,@@@ -7669,7 +7473,7 @@},{"method": "GET",-- "path": "/js/app-channel.js?v=24bb1b7828ce",++ "path": "/js/app-channel.js?v=c148cdba2aee","auth": "anon","accept": "html","status": 200,@@@ -8181,48 +7985,6 @@"public/js/app-home.js"]},-- {-- "method": "POST",-- "path": "/api/emotes",-- "auth": "anon",-- "status": 401,-- "kind": "json",-- "from": [-- "public/js/channel-uploads.js",-- "public/js/emotes.js"-- ]-- },-- {-- "method": "PUT",-- "path": "/api/emotes/sources",-- "auth": "anon",-- "status": 401,-- "kind": "json",-- "from": [-- "public/js/emotes.js"-- ]-- },-- {-- "method": "DELETE",-- "path": "/api/emotes/1",-- "auth": "anon",-- "status": 401,-- "kind": "json",-- "from": [-- "public/js/channel-uploads.js",-- "public/js/emotes.js"-- ]-- },-- {-- "method": "PATCH",-- "path": "/api/emotes/1",-- "auth": "anon",-- "status": 401,-- "kind": "json",-- "from": [-- "public/js/channel-uploads.js"-- ]-- },{"method": "POST","path": "/api/funds/cashout",@@@ -1,7 +1,7 @@{"service": "live",-- "release": "8cead3637816b496cbd5657753a8ca8e8555a1e8",-- "recorded_at": "2026-09-29T16:51:44.167Z",++ "release": "8654ef6b86143d4117ff010ce19aa0124a6bcd57",++ "recorded_at": "2026-09-29T17:33:21.954Z","note": "N-1 fixture: written by `npm run n-1:record`, replayed by test/n-1.test.js","user_version": 0,"schema": [@@@ -35,7 +35,9 @@"CREATE TABLE channel_sounds (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n channel_owner_id INTEGER NOT NULL, -- streamer whose channel this sound belongs to\n command TEXT NOT NULL, -- trigger word (without leading '!'), lowercased\n url TEXT NOT NULL, -- served path of the audio file on disk\n mime TEXT DEFAULT 'audio/mpeg',\n duration_seconds REAL DEFAULT 0,\n created_by INTEGER, -- uploader user id (NULL if removed user)\n created_by_name TEXT DEFAULT '',\n is_approved INTEGER DEFAULT 1,\n created_at DATETIME DEFAULT CURRENT_TIMESTAMP, emote_code TEXT DEFAULT '',\n -- Multiple sounds may share a command; playback picks one at random.\n FOREIGN KEY (channel_owner_id) REFERENCES users(id) ON DELETE CASCADE\n)","CREATE TABLE channels (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n user_id INTEGER NOT NULL UNIQUE,\n title TEXT DEFAULT 'Untitled Channel',\n description TEXT DEFAULT '',\n category TEXT DEFAULT 'irl',\n tags TEXT DEFAULT '[]',\n protocol TEXT DEFAULT 'webrtc' CHECK(protocol IN ('jsmpeg', 'webrtc', 'rtmp')),\n is_nsfw INTEGER DEFAULT 0,\n auto_record INTEGER DEFAULT 0,\n offline_banner_url TEXT,\n panels TEXT DEFAULT '[]', -- JSON array of info panels\n emote_sources TEXT DEFAULT '{\"defaults\":true,\"custom\":true,\"ffz\":true,\"bttv\":true,\"7tv\":true}',\n default_vod_visibility TEXT DEFAULT 'public' CHECK(default_vod_visibility IN ('public', 'unlisted', 'private')),\n default_clip_visibility TEXT DEFAULT 'public' CHECK(default_clip_visibility IN ('public', 'unlisted', 'private')),\n vod_recording_enabled INTEGER DEFAULT 1,\n force_vod_recording_disabled INTEGER DEFAULT 0,\n weather_zip TEXT DEFAULT NULL,\n weather_detail TEXT DEFAULT 'basic' CHECK(weather_detail IN ('off', 'basic', 'hourly', 'detailed')),\n weather_show_location INTEGER DEFAULT 0,\n control_mode TEXT DEFAULT 'open' CHECK(control_mode IN ('open','whitelist','disabled')),\n anon_controls_enabled INTEGER DEFAULT 1,\n control_rate_limit_ms INTEGER DEFAULT 100,\n video_click_enabled INTEGER DEFAULT 0,\n video_click_rate_limit_ms INTEGER DEFAULT 0,\n active_control_config_id INTEGER,\n created_at DATETIME DEFAULT CURRENT_TIMESTAMP,\n updated_at DATETIME DEFAULT CURRENT_TIMESTAMP, chat_language TEXT DEFAULT 'auto', cp_name TEXT DEFAULT 'Channel Points', cp_icon TEXT DEFAULT 'fa-coins', cp_watch_interval_min INTEGER DEFAULT 5, cp_watch_amount INTEGER DEFAULT 10, cp_game_interval_min INTEGER DEFAULT 0, clips_allow_creator_delete INTEGER DEFAULT 0, hide_ai_overview INTEGER DEFAULT 0, ai_overview_pref TEXT DEFAULT 'auto', ai_derivation_enabled INTEGER DEFAULT 1, ai_category TEXT, force_nsfw INTEGER DEFAULT 0, offline_screen_type TEXT DEFAULT 'none', offline_screen_url TEXT, offline_html TEXT, offline_css TEXT, social_links TEXT,\n FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE\n)","CREATE TABLE chat_ai_summaries (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n scope TEXT NOT NULL,\n subject_id INTEGER NOT NULL DEFAULT 0,\n window TEXT NOT NULL,\n overview TEXT DEFAULT '',\n memory_json TEXT DEFAULT '',\n timeline_json TEXT DEFAULT '[]',\n message_count INTEGER DEFAULT 0,\n window_message_count INTEGER DEFAULT 0,\n last_message_id INTEGER DEFAULT 0,\n window_label TEXT DEFAULT '',\n window_start DATETIME,\n window_end DATETIME,\n updated_at DATETIME DEFAULT CURRENT_TIMESTAMP,\n UNIQUE(scope, subject_id, window)\n )",++ "CREATE TABLE chat_dual_read_stats (\n tbl TEXT PRIMARY KEY,\n compared INTEGER NOT NULL DEFAULT 0,\n matched INTEGER NOT NULL DEFAULT 0,\n mismatched INTEGER NOT NULL DEFAULT 0,\n inconclusive INTEGER NOT NULL DEFAULT 0,\n errors INTEGER NOT NULL DEFAULT 0,\n last_mismatch_at DATETIME,\n last_mismatch TEXT,\n since DATETIME DEFAULT CURRENT_TIMESTAMP\n)","CREATE TABLE \"chat_messages\" (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n stream_id INTEGER,\n user_id INTEGER, -- NULL for anon\n anon_id TEXT, -- 'anon12345' format\n username TEXT,\n message TEXT NOT NULL,\n message_type TEXT DEFAULT 'chat' CHECK(message_type IN ('chat', 'system', 'donation', 'command', 'tts', 'channel-sound', 'soundboard', 'clip')),\n metadata TEXT, -- JSON sidecar for rich events (donation/goal-reached)\n is_global INTEGER DEFAULT 0,\n is_deleted INTEGER DEFAULT 0,\n is_filtered INTEGER DEFAULT 0,\n reply_to_id INTEGER REFERENCES chat_messages(id) ON DELETE SET NULL,\n source_platform TEXT,\n deleted_by INTEGER,\n deleted_at DATETIME,\n auto_delete_at DATETIME,\n timestamp DATETIME DEFAULT CURRENT_TIMESTAMP, channel_user_id INTEGER,\n FOREIGN KEY (stream_id) REFERENCES streams(id) ON DELETE CASCADE,\n FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE SET NULL\n)",++ "CREATE TABLE chat_staged_outbox (\n seq INTEGER PRIMARY KEY AUTOINCREMENT,\n tbl TEXT NOT NULL,\n op TEXT NOT NULL,\n pk TEXT NOT NULL,\n created_at DATETIME DEFAULT CURRENT_TIMESTAMP\n)","CREATE TABLE chat_timeline_events (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n scope TEXT NOT NULL DEFAULT 'global',\n subject_id INTEGER NOT NULL DEFAULT 0,\n ts DATETIME NOT NULL,\n label TEXT NOT NULL,\n detail TEXT DEFAULT '',\n created_at DATETIME DEFAULT CURRENT_TIMESTAMP\n )","CREATE TABLE clip_ai_state (\n clip_id INTEGER PRIMARY KEY,\n ai_overview_short TEXT,\n ai_transcript_json TEXT,\n transcript_status TEXT,\n transcript_attempts INTEGER DEFAULT 0,\n transcript_error TEXT,\n transcript_next_at DATETIME,\n clip_notified INTEGER DEFAULT 0,\n clip_notify_at DATETIME\n , ai_overview TEXT, transcript_partial_json TEXT, transcript_progress_sec INTEGER DEFAULT 0)","CREATE TABLE clips (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n vod_id INTEGER,\n stream_id INTEGER,\n user_id INTEGER NOT NULL,\n title TEXT DEFAULT 'Untitled Clip',\n description TEXT DEFAULT '',\n file_path TEXT,\n thumbnail_url TEXT,\n start_time REAL NOT NULL DEFAULT 0,\n end_time REAL NOT NULL DEFAULT 0,\n duration_seconds REAL DEFAULT 0,\n is_public INTEGER DEFAULT 1,\n view_count INTEGER DEFAULT 0,\n created_at DATETIME DEFAULT CURRENT_TIMESTAMP, storage_provider TEXT DEFAULT 'local', storage_key TEXT, ai_overview TEXT, ai_transcript TEXT, ai_analyzed_at DATETIME, clip_notified INTEGER DEFAULT 0, clip_notify_at DATETIME, visibility TEXT DEFAULT 'public', auto_generated INTEGER DEFAULT 0,\n FOREIGN KEY (vod_id) REFERENCES vods(id) ON DELETE SET NULL,\n FOREIGN KEY (stream_id) REFERENCES streams(id) ON DELETE SET NULL,\n FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE\n)",@@@ -257,19 +259,19 @@"schema_migrations": [{"id": "001_vibes_decimal_to_bits",-- "applied_at": "2026-09-29 16:51:35",++ "applied_at": "2026-09-29 17:33:17","mode": "adopted","duration_ms": 0},{"id": "002_pastes_ai_columns",-- "applied_at": "2026-09-29 16:51:35",++ "applied_at": "2026-09-29 17:33:17","mode": "applied",-- "duration_ms": 13++ "duration_ms": 8},{"id": "004_hot_path_indexes",-- "applied_at": "2026-09-29 16:51:35",++ "applied_at": "2026-09-29 17:33:17","mode": "applied","duration_ms": 1}@@@ -283,8 +285,6 @@"CREATE TABLE IF NOT EXISTS subject_projection ( subject_id TEXT PRIMARY KEY, network_user_id INTEGER, revision INTEGER NOT NULL, username TEXT NOT NULL, display_name TEXT, avatar_url TEXT, profile_color TEXT, role TEXT NOT NULL, banned INTEGER NOT NULL DEFAULT 0, updated_at DATETIME DEFAULT CURRENT_TIMESTAMP )","CREATE TABLE IF NOT EXISTS username_history ( id INTEGER PRIMARY KEY AUTOINCREMENT, user_id INTEGER NOT NULL, old_username TEXT NOT NULL, new_username TEXT NOT NULL, changed_at DATETIME DEFAULT CURRENT_TIMESTAMP )","CREATE TABLE IF NOT EXISTS chat_bridge_outbox ( id INTEGER PRIMARY KEY AUTOINCREMENT, boot TEXT NOT NULL, ref INTEGER, op TEXT NOT NULL, args TEXT NOT NULL, created_at DATETIME DEFAULT CURRENT_TIMESTAMP )",-- "CREATE TABLE IF NOT EXISTS chat_staged_outbox ( seq INTEGER PRIMARY KEY AUTOINCREMENT, tbl TEXT NOT NULL, op TEXT NOT NULL, pk TEXT NOT NULL, created_at DATETIME DEFAULT CURRENT_TIMESTAMP )",-- "CREATE TABLE IF NOT EXISTS chat_dual_read_stats ( tbl TEXT PRIMARY KEY, compared INTEGER NOT NULL DEFAULT 0, matched INTEGER NOT NULL DEFAULT 0, mismatched INTEGER NOT NULL DEFAULT 0, inconclusive INTEGER NOT NULL DEFAULT 0, errors INTEGER NOT NULL DEFAULT 0, last_mismatch_at DATETIME, last_mismatch TEXT, since DATETIME DEFAULT CURRENT_TIMESTAMP )","CREATE TABLE IF NOT EXISTS comment_thread_refs ( content_type TEXT NOT NULL, content_id INTEGER NOT NULL, thread_id INTEGER NOT NULL, access_id TEXT NOT NULL, created_at DATETIME DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (content_type, content_id) )","CREATE TABLE IF NOT EXISTS search_doc_pushes ( user_id INTEGER PRIMARY KEY, hash TEXT NOT NULL, revision INTEGER NOT NULL, deleted INTEGER NOT NULL DEFAULT 0, pushed_at DATETIME DEFAULT CURRENT_TIMESTAMP )","CREATE TABLE IF NOT EXISTS search_media_pushes ( kind TEXT NOT NULL, media_id INTEGER NOT NULL, hash TEXT NOT NULL, revision INTEGER NOT NULL, deleted INTEGER NOT NULL DEFAULT 0, pushed_at DATETIME DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (kind, media_id) )",@@@ -311,12 +311,10 @@"DELETE FROM camera_presets WHERE id = ?","DELETE FROM camera_profiles WHERE id = ?","DELETE FROM channel_ai_bots WHERE id = ?",-- "DELETE FROM channel_moderators WHERE channel_id = ? AND user_id = ?","DELETE FROM channel_points WHERE user_id = ? AND streamer_id = ?","DELETE FROM channel_sounds WHERE id = ?","DELETE FROM chat_bridge_outbox","DELETE FROM chat_bridge_outbox WHERE id = ?",-- "DELETE FROM chat_dual_read_stats WHERE tbl = ?","DELETE FROM clip_ai_state WHERE clip_id = ?","DELETE FROM coin_rewards WHERE id = ?","DELETE FROM content_views WHERE content_type = ? AND content_id = ?",@@@ -328,7 +326,6 @@"DELETE FROM dm_messages WHERE id = ?","DELETE FROM dm_participants WHERE conversation_id = ? AND user_id = ?","DELETE FROM donation_goals WHERE id = ? AND user_id = ?",-- "DELETE FROM emotes WHERE id = ?","DELETE FROM follows WHERE follower_id = ? AND streamer_id = ?","DELETE FROM follows WHERE id = ?","DELETE FROM hidden_relay_users WHERE id = ?",@@@ -388,13 +385,10 @@"INSERT INTO cameras (stream_id, camera_index, label, protocol) VALUES (?, 0, 'Main', ?)","INSERT INTO channel_ai_bots (channel_user_id, username, display_name, avatar_color, source, cloned_from_kind, cloned_from_ref, persona_json, brain_json) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)","INSERT INTO channel_ai_config (user_id, enabled, num_ambient_bots, pacing_seconds, persona, transcribe_enabled, vision_enabled, use_shared_key, daily_budget_cents, byo_key, byo_base_url, byo_model) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)",-- "INSERT INTO channel_moderation_settings ( channel_id, slow_mode_seconds, followers_only, emote_only, allow_anonymous, links_allowed, gifs_enabled, account_age_gate_hours, caps_percentage_limit, aggressive_filter, max_message_length, slur_filter_enabled, slur_filter_use_builtin, slur_filter_terms, slur_filter_regexes, slur_filter_nudge_message, slur_filter_disabled_categories, ip_approval_mode, soundboard_enabled, soundboard_allow_pitch, soundboard_allow_speed, soundboard_banned_ids, viewer_auto_delete_enabled, viewer_delete_all_enabled, custom_emotes_enabled, custom_sounds_enabled, max_sound_seconds, uploads_mods_only, emote_scale, emote_size_min, emote_size_max, sounds_mods_only, mods_can_edit_about ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)",-- "INSERT INTO channel_moderation_settings (channel_id) VALUES (?)","INSERT INTO channel_points (user_id, streamer_id, balance) VALUES (?, ?, ?)","INSERT INTO channel_points (user_id, streamer_id, balance, updated_at) VALUES (?, ?, ?, CURRENT_TIMESTAMP) ON CONFLICT(user_id, streamer_id) DO UPDATE SET balance = balance + excluded.balance, updated_at = CURRENT_TIMESTAMP","INSERT INTO channel_points_log (idempotency_key, user_id, streamer_id, delta, reason) VALUES (?, ?, ?, ?, ?)","INSERT INTO channel_sounds (channel_owner_id, command, url, mime, duration_seconds, created_by, created_by_name, emote_code) VALUES (?, ?, ?, ?, ?, ?, ?, ?)",-- "INSERT INTO chat_ai_summaries (scope, subject_id, window, overview, memory_json, timeline_json, message_count, window_message_count, last_message_id, window_label, window_start, window_end, updated_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, CURRENT_TIMESTAMP) ON CONFLICT(scope, subject_id, window) DO UPDATE SET overview = excluded.overview, memory_json = excluded.memory_json, timeline_json = excluded.timeline_json, message_count = excluded.message_count, window_message_count = excluded.window_message_count, last_message_id = excluded.last_message_id, window_label = excluded.window_label, window_start = excluded.window_start, window_end = excluded.window_end, updated_at = CURRENT_TIMESTAMP","INSERT INTO chat_bridge_outbox (boot, ref, op, args) VALUES (?, ?, ?, ?)","INSERT INTO chat_messages (stream_id, channel_user_id, user_id, anon_id, username, message, message_type, is_global, reply_to_id, source_platform, auto_delete_at, metadata) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)","INSERT INTO coin_redemptions (reward_id, user_id, stream_id, user_input) VALUES (?, ?, ?, ?)",@@@ -407,7 +401,6 @@"INSERT INTO dm_messages (conversation_id, sender_id, message) VALUES (?, ?, ?)","INSERT INTO donation_goals (user_id, title, target_amount) VALUES (?, ?, ?)","INSERT INTO donation_goals (user_id, title, target_amount, image_url, media_type, sort_order) VALUES (?, ?, ?, ?, ?, ?)",-- "INSERT INTO emotes (user_id, code, url, animated, width, height, is_global, channel_owner_id, size) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)","INSERT INTO follow_projection_revisions (follower_subject, target_subject, revision) VALUES (?, ?, ?) ON CONFLICT (follower_subject, target_subject) DO UPDATE SET revision = excluded.revision","INSERT INTO ip_log (user_id, anon_id, ip_address, action, geo_country, geo_region, geo_city, geo_isp, geo_org, geo_ll, user_agent) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)","INSERT INTO kick_channel_cache (slug, chatroom_id, kick_channel_id, updated_at) VALUES (?, ?, ?, CURRENT_TIMESTAMP) ON CONFLICT(slug) DO UPDATE SET chatroom_id = excluded.chatroom_id, kick_channel_id = COALESCE(excluded.kick_channel_id, kick_channel_cache.kick_channel_id), updated_at = CURRENT_TIMESTAMP",@@@ -460,10 +453,8 @@"INSERT OR IGNORE INTO arena_beef_hype (beef_id, side, voter_key) VALUES (?, ?, ?)","INSERT OR IGNORE INTO billing_actions (action, idempotency_key, live_user_id, live_ref, method, path, request_json) VALUES (?, ?, ?, ?, ?, ?, ?)","INSERT OR IGNORE INTO channel_ai_config (user_id, enabled, num_ambient_bots, pacing_seconds, persona, transcribe_enabled, vision_enabled, use_shared_key, daily_budget_cents, byo_key, byo_base_url, byo_model) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)",-- "INSERT OR IGNORE INTO channel_moderators (channel_id, user_id, added_by) VALUES (?, ?, ?)","INSERT OR IGNORE INTO channel_points_log (idempotency_key, user_id, streamer_id, delta, reason) VALUES (?, ?, ?, ?, ?)","INSERT OR IGNORE INTO channels (user_id, title, description, category, protocol) VALUES (?, ?, ?, ?, ?)",-- "INSERT OR IGNORE INTO chat_timeline_events (scope, subject_id, ts, label, detail) VALUES (?, ?, ?, ?, ?)","INSERT OR IGNORE INTO clip_ai_state (clip_id) VALUES (?)","INSERT OR IGNORE INTO comment_thread_refs (content_type, content_id, thread_id, access_id) VALUES (?, ?, ?, ?)","INSERT OR IGNORE INTO content_views (content_type, content_id, ip) VALUES (?, ?, ?)",@@@ -533,15 +524,12 @@"SELECT * FROM channel_ai_bots WHERE channel_user_id = ? ORDER BY last_active_at DESC, created_at ASC","SELECT * FROM channel_ai_bots WHERE id = ?","SELECT * FROM channel_ai_config WHERE user_id = ?",-- "SELECT * FROM channel_moderation_settings WHERE channel_id = ?","SELECT * FROM channel_sounds WHERE channel_owner_id = ? AND command = ? AND is_approved = 1 ORDER BY RANDOM() LIMIT 1","SELECT * FROM channel_sounds WHERE channel_owner_id = ? AND is_approved = 1 ORDER BY command","SELECT * FROM channel_sounds WHERE id = ?","SELECT * FROM channels WHERE id = ?","SELECT * FROM channels WHERE user_id = ?","SELECT * FROM channels WHERE user_id IN (?)",-- "SELECT * FROM chat_ai_summaries WHERE scope = ? AND subject_id = ? AND window = ?",-- "SELECT * FROM chat_ai_summaries WHERE scope = ? AND subject_id = ? ORDER BY window","SELECT * FROM chat_messages WHERE id = ?","SELECT * FROM clip_ai_state WHERE clip_id = ?","SELECT * FROM coin_rewards WHERE id = ?",@@@ -559,9 +547,6 @@"SELECT * FROM donation_goals WHERE user_id = ? AND is_active = 1 ORDER BY created_at","SELECT * FROM donation_goals WHERE user_id = ? AND is_active = 1 ORDER BY sort_order ASC, created_at ASC","SELECT * FROM donation_goals WHERE user_id = ? ORDER BY is_active DESC, sort_order ASC, created_at ASC",-- "SELECT * FROM emotes WHERE code = ? AND ((channel_owner_id = ?) OR (channel_owner_id IS NULL AND user_id = ?)) LIMIT 1",-- "SELECT * FROM emotes WHERE code = ? AND (user_id = ? OR is_global = 1) AND is_approved = 1 ORDER BY is_global ASC LIMIT 1",-- "SELECT * FROM emotes WHERE user_id = ? ORDER BY code","SELECT * FROM kick_channel_cache WHERE slug = ?","SELECT * FROM lineage_unresolved ORDER BY last_at DESC LIMIT ?","SELECT * FROM lineage_unresolved WHERE reason = ? ORDER BY last_at DESC LIMIT ?",@@@ -638,8 +623,6 @@"SELECT 1 FROM ai_chatbot_configs WHERE user_id = ?","SELECT 1 FROM approved_ips WHERE channel_id = ? AND ip_address = ?","SELECT 1 FROM channel_ai_config WHERE user_id = ?",-- "SELECT 1 FROM channel_moderation_settings WHERE channel_id = ?",-- "SELECT 1 FROM channel_moderators WHERE user_id = ? AND channel_id = ?","SELECT 1 FROM channel_points WHERE user_id = ? AND streamer_id = ?","SELECT 1 FROM chat_messages cm JOIN streams s ON cm.stream_id = s.id WHERE s.channel_id = ? AND cm.is_deleted = 0 AND (cm.user_id = ? OR cm.anon_id = ?) LIMIT 1","SELECT 1 FROM control_whitelist WHERE channel_id = ? AND user_id = ?",@@@ -756,8 +739,6 @@"SELECT COUNT(*) AS n FROM channel_sounds WHERE channel_owner_id = ?","SELECT COUNT(*) AS n FROM chat_messages WHERE stream_id = ? AND message_type = 'soundboard'","SELECT COUNT(*) AS n FROM chat_messages WHERE timestamp >= ? AND COALESCE(is_deleted, 0) = 0",-- "SELECT COUNT(*) AS n FROM chat_staged_outbox",-- "SELECT COUNT(*) AS n FROM chat_staged_outbox WHERE tbl = ?","SELECT COUNT(*) AS n FROM control_configs WHERE user_id = ?","SELECT COUNT(*) AS n FROM donation_goals WHERE user_id = ? AND is_active = 1","SELECT COUNT(*) AS n FROM easter_egg_solves WHERE egg_date = ?",@@@ -807,8 +788,6 @@"SELECT COUNT(*) as cnt FROM streams WHERE user_id = ? AND duration_seconds > 0","SELECT COUNT(*) as count FROM channel_sounds WHERE channel_owner_id = ?","SELECT COUNT(*) as count FROM channel_sounds WHERE channel_owner_id = ? AND created_by = ?",-- "SELECT COUNT(*) as count FROM emotes WHERE (channel_owner_id = ?) OR (channel_owner_id IS NULL AND user_id = ?)",-- "SELECT COUNT(*) as count FROM emotes WHERE user_id = ?","SELECT COUNT(*) as count FROM follows WHERE streamer_id = ?","SELECT COUNT(*) as total_streams, SUM(duration_seconds) as total_duration, MAX(peak_viewers) as peak_viewers FROM streams WHERE user_id = ? AND duration_seconds > 0","SELECT COUNT(*) as total_streams, SUM(s.duration_seconds) as total_duration, MAX(s.peak_viewers) as all_time_peak, AVG(sa.avg_viewers) as avg_viewers_per_stream, SUM(sa.total_messages) as total_messages, SUM(sa.unique_chatters) as total_unique_chatters, SUM(sa.total_watch_minutes) as total_watch_minutes, SUM(sa.new_followers) as total_new_followers, SUM(sa.clips_created) as total_clips FROM streams s LEFT JOIN stream_analytics sa ON sa.stream_id = s.id WHERE s.user_id = ? AND s.started_at >= ? AND s.duration_seconds > 0",@@@ -831,7 +810,6 @@"SELECT DISTINCT user_id FROM linked_accounts WHERE service = 'network' AND subject_id = ?","SELECT MAX(anon_num) as m FROM anon_ip_mappings","SELECT MAX(id) AS id FROM chat_messages",-- "SELECT MAX(id) AS m FROM chat_messages","SELECT MAX(queue_position) AS max_pos FROM media_requests WHERE streamer_id = ? AND status = 'pending'","SELECT MIN(timestamp) AS t FROM chat_messages WHERE anon_id = ? AND user_id IS NULL AND is_deleted = 0","SELECT ROUND(AVG(viewer_count), 1) AS a, COUNT(*) AS k FROM viewer_snapshots WHERE stream_id = ?",@@@ -870,10 +848,7 @@"SELECT cm.*, u.avatar_url, u.profile_color, u.role, u.display_name, u.username AS core_username, COALESCE(su.username, cu.username) AS stream_channel, s.is_live AS source_is_live, s.managed_stream_id AS source_managed_id, COALESCE(ms.title, s.title) AS source_stream_title, ms.slug AS source_slug FROM chat_messages cm LEFT JOIN users u ON cm.user_id = u.id LEFT JOIN streams s ON cm.stream_id = s.id LEFT JOIN users su ON s.user_id = su.id LEFT JOIN users cu ON cm.channel_user_id = cu.id LEFT JOIN managed_streams ms ON s.managed_stream_id = ms.id WHERE cm.is_deleted = 0 AND cm.message_type IN ('chat', 'system', 'channel-sound', 'soundboard', 'donation') AND (cm.auto_delete_at IS NULL OR datetime(cm.auto_delete_at) > CURRENT_TIMESTAMP)","SELECT cm.*, u.avatar_url, u.profile_color, u.role, u.display_name, u.username AS core_username, s.title AS source_stream_title, s.managed_stream_id AS source_managed_id, s.is_live AS source_is_live, ms.slug AS source_slug, COALESCE(bu.username, cu.username) AS source_channel FROM chat_messages cm LEFT JOIN users u ON cm.user_id = u.id LEFT JOIN streams s ON cm.stream_id = s.id LEFT JOIN managed_streams ms ON s.managed_stream_id = ms.id LEFT JOIN users bu ON s.user_id = bu.id LEFT JOIN users cu ON cm.channel_user_id = cu.id WHERE cm.channel_user_id = ? AND cm.is_deleted = 0 AND (cm.auto_delete_at IS NULL OR datetime(cm.auto_delete_at) > CURRENT_TIMESTAMP)","SELECT cm.*, u.display_name, u.username as u_username, u.role, u.avatar_url, u.profile_color FROM chat_messages cm LEFT JOIN users u ON cm.user_id = u.id WHERE cm.is_deleted = 0 AND (cm.auto_delete_at IS NULL OR datetime(cm.auto_delete_at) > CURRENT_TIMESTAMP)",-- "SELECT cm.channel_id, c.title, c.user_id, u.username as owner_username FROM channel_moderators cm JOIN channels c ON cm.channel_id = c.id JOIN users u ON c.user_id = u.id WHERE cm.user_id = ?",-- "SELECT cm.id, cm.user_id, cm.added_by, cm.created_at, u.username, u.display_name, u.avatar_url, a.username as added_by_username FROM channel_moderators cm JOIN users u ON cm.user_id = u.id LEFT JOIN users a ON cm.added_by = a.id WHERE cm.channel_id = ? ORDER BY cm.created_at ASC","SELECT cm.user_id, cm.username, COUNT(*) as message_count FROM chat_messages cm JOIN streams s ON cm.stream_id = s.id WHERE s.user_id = ? AND cm.timestamp >= ? AND cm.is_deleted = 0 AND cm.is_global = 0 AND cm.message_type = 'chat' AND cm.user_id IS NOT NULL GROUP BY cm.user_id ORDER BY message_count DESC LIMIT 20",-- "SELECT compared, matched, mismatched, inconclusive, errors, last_mismatch_at, last_mismatch, since FROM chat_dual_read_stats WHERE tbl = ?","SELECT consecutive_failures FROM restream_destinations WHERE id = ?","SELECT created_at FROM anon_ip_mappings WHERE anon_num = ?","SELECT created_at FROM anon_ip_mappings WHERE ip = ?",@@@ -885,10 +860,6 @@"SELECT default_vod_visibility FROM managed_streams WHERE id = ?","SELECT description FROM stream_memories WHERE user_id = ? ORDER BY captured_at DESC LIMIT 4","SELECT description, category, chat_language FROM channels WHERE user_id = ?",-- "SELECT donation_sound_url, donation_sound_mime, goal_sound_url, goal_sound_mime FROM channel_moderation_settings WHERE channel_id = ?",-- "SELECT e.*, u.username FROM emotes e JOIN users u ON e.user_id = u.id WHERE e.id = ?",-- "SELECT e.*, u.username FROM emotes e JOIN users u ON e.user_id = u.id WHERE e.is_global = 1 AND e.is_approved = 1 ORDER BY code",-- "SELECT e.*, u.username, up.username AS uploader_username, up.display_name AS uploader_display_name FROM emotes e JOIN users u ON e.user_id = u.id LEFT JOIN users up ON e.user_id = up.id WHERE ((e.channel_owner_id = ?) OR (e.channel_owner_id IS NULL AND e.user_id = ?)) AND e.is_approved = 1 ORDER BY code","SELECT e.id, e.stream_id, e.vod_id, e.start_sec, e.end_sec, e.text, s.started_at FROM stream_timeline_events e LEFT JOIN streams s ON s.id = e.stream_id WHERE e.user_id = ? AND e.kind = 'speech' AND e.id > ? AND e.created_at >= datetime('now', ?) AND NOT EXISTS (SELECT 1 FROM streams l WHERE l.id = e.stream_id AND l.is_live = 1) ORDER BY e.stream_id, e.start_sec LIMIT 4000","SELECT enabled FROM news_settings WHERE scope = 'global' AND source_id = '_master'","SELECT enabled FROM news_settings WHERE scope = 'user' AND scope_id = ? AND source_id = '_master'",@@@ -904,7 +875,6 @@"SELECT id FROM billing_actions WHERE idempotency_key = ?","SELECT id FROM channels WHERE user_id = ?","SELECT id FROM coin_transactions WHERE user_id = ? AND type = 'follow_bonus' AND message LIKE '%streamer:' || ? || '%'",-- "SELECT id FROM emotes WHERE user_id = ? AND code = ? AND channel_owner_id IS NULL","SELECT id FROM follows WHERE follower_id = ? AND streamer_id = ?","SELECT id FROM managed_streams WHERE user_id = ? AND slug = ? COLLATE NOCASE","SELECT id FROM managed_streams WHERE user_id = ? ORDER BY created_at",@@@ -995,7 +965,6 @@"SELECT powerchat_username FROM powerchat_connections WHERE user_id = ?","SELECT r.*, cr.streamer_id FROM coin_redemptions r JOIN coin_rewards cr ON r.reward_id = cr.id WHERE r.id = ?","SELECT r.*, cr.title as reward_title, cr.cost, cr.icon, cr.color, u.username, u.display_name, u.avatar_url FROM coin_redemptions r JOIN coin_rewards cr ON r.reward_id = cr.id JOIN users u ON r.user_id = u.id WHERE cr.streamer_id = ? AND r.status = 'pending' ORDER BY r.created_at ASC",-- "SELECT r.rowid AS id, r.platform, r.username, r.display_name, r.message_count, r.last_seen, cs.updated_at AS last_update FROM relay_users r LEFT JOIN chat_ai_summaries cs ON cs.scope = 'relay' AND cs.window = 'rolling' AND cs.subject_id = r.rowid WHERE r.last_seen >= ? AND r.message_count >= ? AND (cs.updated_at IS NULL OR cs.updated_at < r.last_seen) ORDER BY (cs.updated_at IS NULL) DESC, r.last_seen DESC LIMIT ?","SELECT r.stream_id FROM stream_recaps r JOIN streams s ON s.id = r.stream_id WHERE r.user_id = ? AND s.started_at >= ? ORDER BY r.created_at DESC LIMIT 1","SELECT r.stream_id, r.json, r.created_at, u.username, u.display_name, u.avatar_url, u.profile_color FROM stream_recaps r JOIN users u ON u.id = r.user_id WHERE (? IS NULL OR r.user_id != ?) AND COALESCE(u.is_banned, 0) = 0 ORDER BY r.created_at DESC LIMIT ?","SELECT r.stream_id, r.user_id, r.json, r.created_at FROM stream_recaps r JOIN users u ON u.id = r.user_id WHERE r.ai = 1 AND COALESCE(u.is_banned, 0) = 0 ORDER BY r.created_at DESC, r.stream_id DESC LIMIT ? OFFSET ?",@@@ -1029,8 +998,6 @@"SELECT s.id, s.user_id, s.started_at FROM streams s WHERE s.is_live = 1 AND EXISTS (SELECT 1 FROM stream_timeline_events e WHERE e.stream_id = s.id AND e.kind = 'speech' AND e.created_at >= datetime('now', '-30 minutes'))","SELECT s.id, s.user_id, s.title, s.category, s.protocol, s.is_nsfw, s.started_at, s.ended_at, s.duration_seconds, s.managed_stream_id, u.username, u.display_name FROM streams s JOIN users u ON u.id = s.user_id WHERE s.id = ?","SELECT s.id, u.stream_key FROM streams s JOIN users u ON s.user_id = u.id WHERE s.is_live = 1 AND s.protocol = 'jsmpeg'",-- "SELECT seq, tbl, op, pk FROM chat_staged_outbox ORDER BY seq LIMIT ?",-- "SELECT seq, tbl, op, pk FROM chat_staged_outbox WHERE tbl = ? ORDER BY seq LIMIT ?","SELECT service_user_id FROM linked_accounts WHERE service = 'network' AND user_id = ?","SELECT session_id, managed_stream_id, stream_id, state, confirmed_at FROM openre_sessions WHERE state = 'live'","SELECT slot, item_id FROM user_equipped WHERE user_id = ?",@@@ -1142,8 +1109,6 @@"UPDATE billing_actions SET status = ?, http_status = ?, error = ?, updated_at = CURRENT_TIMESTAMP WHERE id = ?","UPDATE camera_profiles SET name = ?, onvif_url = ?, username = ?, password_hash = ?, pan_speed = ?, tilt_speed = ?, zoom_speed = ?, is_active = ?, last_connected = ?, updated_at = CURRENT_TIMESTAMP WHERE id = ?","UPDATE channel_ai_bots SET msg_count = msg_count + 1, last_active_at = CURRENT_TIMESTAMP WHERE id = ?",-- "UPDATE channel_moderation_settings SET sub_only = ? WHERE channel_id = ?",-- "UPDATE channel_moderation_settings SET tts_max_length = ? WHERE channel_id = ?","UPDATE channel_points SET balance = balance + ?, updated_at = CURRENT_TIMESTAMP WHERE user_id = ? AND streamer_id = ?","UPDATE channel_points SET balance = balance + ?, updated_at = CURRENT_TIMESTAMP WHERE user_id = ? AND streamer_id = ? AND balance >= ?","UPDATE channel_sounds SET command = ? WHERE channel_owner_id = ? AND command = ?",@@@ -1152,7 +1117,6 @@"UPDATE channels SET ai_category = ? WHERE user_id = ?","UPDATE channels SET ai_overview_pref = 'hide' WHERE hide_ai_overview = 1 AND (ai_overview_pref IS NULL OR ai_overview_pref = 'auto')","UPDATE channels SET clips_allow_creator_delete = ? WHERE id = ?",-- "UPDATE chat_dual_read_stats SET last_mismatch_at = CURRENT_TIMESTAMP, last_mismatch = ? WHERE tbl = ?","UPDATE chat_messages SET channel_user_id = (SELECT s.user_id FROM streams s WHERE s.id = chat_messages.stream_id) WHERE stream_id IS NOT NULL AND channel_user_id IS NULL","UPDATE chat_messages SET is_deleted = 1, deleted_by = ?, deleted_at = CURRENT_TIMESTAMP WHERE id = ?","UPDATE chat_messages SET is_deleted = 1, deleted_by = ?, deleted_at = CURRENT_TIMESTAMP WHERE is_global = 1 AND timestamp >= datetime(?) AND timestamp <= datetime(?) AND is_deleted = 0",
@@ -1,13 +1,13 @@
@@ -1,13 +1,13 @@
{
{
"service": "live",
"service": "live",
- "release": "8cead3637816b496cbd5657753a8ca8e8555a1e8",
- "recorded_at": "2026-09-29T16:51:44.167Z",
+ "release": "8654ef6b86143d4117ff010ce19aa0124a6bcd57",
+ "recorded_at": "2026-09-29T17:33:21.954Z",
"note": "N-1 fixture: written by `npm run n-1:record`, replayed by test/n-1.test.js",
"note": "N-1 fixture: written by `npm run n-1:record`, replayed by test/n-1.test.js",
"manifest": {
"manifest": {
"service": "live",
"service": "live",
- "release": "8cead3637816",
- "released_at": "2026-09-29T15:31:20.000Z",
- "booted_at": "2026-09-29T16:51:37.750Z",
+ "release": "8654ef6b8614",
+ "released_at": "2026-09-29T17:32:19.000Z",
+ "booted_at": "2026-09-29T17:33:19.050Z",
"contracts_version": "0.71.0",
"contracts_version": "0.71.0",
"packages": {
"packages": {
"openvibe-shared": "1.30.1",
"openvibe-shared": "1.30.1",
@@ -22,11 +22,11 @@
@@ -22,11 +22,11 @@
},
},
"shell": {
"shell": {
"kind": "script",
"kind": "script",
- "version": "680853c062b9"
+ "version": "a1a892dca8f8"
},
},
"server": {
"server": {
"kind": "server",
"kind": "server",
- "version": "83b6fbd34fe3"
+ "version": "ac8c4a25efa6"
}
}
},
},
"assets": {
"assets": {
@@ -1043,95 +1043,19 @@
@@ -1043,95 +1043,19 @@
},
},
{
{
"method": "GET",
"method": "GET",
- "path": "/api/channels/moderation/mine",
+ "path": "/api/chat-ai/live-captions/n1star?after=0",
"auth": "anon",
"auth": "anon",
- "status": 401,
- "kind": "json",
- "from": [
- "public/js/app-channel.js"
- ]
- },
- {
- "method": "GET",
- "path": "/api/channels/moderation/mine",
- "auth": "user",
"status": 200,
"status": 200,
"kind": "json",
"kind": "json",
"reads": {
"reads": {
- "channels": "array",
- "channels[]": "object",
- "channels[].id": "number",
- "channels[].user_id": "number",
- "channels[].title": "string",
- "channels[].description": "string",
- "channels[].category": "null",
- "channels[].tags": "string",
- "channels[].protocol": "string",
- "channels[].is_nsfw": "number",
- "channels[].panels": "string",
- "channels[].default_vod_visibility": "string",
- "channels[].default_clip_visibility": "string",
- "channels[].weather_zip": "null",
- "channels[].weather_detail": "string",
- "channels[].weather_show_location": "number",
- "channels[].control_mode": "string",
- "channels[].anon_controls_enabled": "number",
- "channels[].control_rate_limit_ms": "number",
- "channels[].video_click_enabled": "number",
- "channels[].video_click_rate_limit_ms": "number",
- "channels[].active_control_config_id": "null",
- "channels[].created_at": "string",
- "channels[].updated_at": "string",
- "channels[].clips_allow_creator_delete": "number",
- "channels[].hide_ai_overview": "number",
- "channels[].ai_overview_pref": "string",
- "channels[].ai_derivation_enabled": "number",
- "channels[].ai_category": "null",
- "channels[].offline_screen_type": "string",
- "channels[].offline_screen_url": "null",
- "channels[].offline_html": "null",
- "channels[].offline_css": "null",
- "channels[].social_links": "null",
- "channels[].moderation_settings": "object",
- "channels[].moderation_settings.channel_id": "number",
- "channels[].moderation_settings.slow_mode_seconds": "number",
- "channels[].moderation_settings.followers_only": "number",
- "channels[].moderation_settings.allow_anonymous": "number",
- "channels[].moderation_settings.links_allowed": "number",
- "channels[].moderation_settings.gifs_enabled": "number",
- "channels[].moderation_settings.account_age_gate_hours": "number",
- "channels[].moderation_settings.caps_percentage_limit": "number",
- "channels[].moderation_settings.aggressive_filter": "number",
- "channels[].moderation_settings.max_message_length": "number",
- "channels[].moderation_settings.tts_max_length": "number",
- "channels[].moderation_settings.slur_filter_enabled": "number",
- "channels[].moderation_settings.slur_filter_use_builtin": "number",
- "channels[].moderation_settings.slur_filter_terms": "string",
- "channels[].moderation_settings.slur_filter_regexes": "string",
- "channels[].moderation_settings.slur_filter_nudge_message": "string",
- "channels[].moderation_settings.slur_filter_disabled_categories": "string",
- "channels[].moderation_settings.ip_approval_mode": "number",
- "channels[].moderation_settings.soundboard_enabled": "number",
- "channels[].moderation_settings.soundboard_allow_pitch": "number",
- "channels[].moderation_settings.soundboard_allow_speed": "number",
- "channels[].moderation_settings.soundboard_banned_ids": "string",
- "channels[].moderation_settings.viewer_auto_delete_enabled": "number",
- "channels[].moderation_settings.viewer_delete_all_enabled": "number",
- "channels[].moderation_settings.custom_emotes_enabled": "number",
- "channels[].moderation_settings.custom_sounds_enabled": "number",
- "channels[].moderation_settings.max_sound_seconds": "number",
- "channels[].moderation_settings.uploads_mods_only": "number",
- "channels[].moderation_settings.mods_can_edit_about": "number",
- "channels[].moderation_settings.emote_scale": "number",
- "channels[].moderation_settings.emote_size_min": "number",
- "channels[].moderation_settings.emote_size_max": "number",
- "channels[].moderation_settings.sounds_mods_only": "number",
- "channels[].moderation_settings.sound_min_speed": "number",
- "channels[].moderation_settings.sound_max_speed": "number",
- "channels[].moderation_settings.sound_min_pitch_cents": "number",
- "channels[].moderation_settings.sound_max_pitch_cents": "number",
- "channels[].moderation_settings.sub_only": "number",
- "channels[].moderators": "array"
+ "language": "object",
+ "language.code": "string",
+ "language.name": "string",
+ "language.flag": "string",
+ "available": "boolean",
+ "live": "boolean",
+ "stream_id": "number",
+ "lines": "array"
},
},
"from": [
"from": [
"public/js/app-channel.js"
"public/js/app-channel.js"
@@ -1140,7 +1064,7 @@
@@ -1140,7 +1064,7 @@
{
{
"method": "GET",
"method": "GET",
"path": "/api/chat-ai/live-captions/n1star?after=0",
"path": "/api/chat-ai/live-captions/n1star?after=0",
- "auth": "anon",
+ "auth": "user",
"status": 200,
"status": 200,
"kind": "json",
"kind": "json",
"reads": {
"reads": {
@@ -1159,19 +1083,95 @@
@@ -1159,19 +1083,95 @@
},
},
{
{
"method": "GET",
"method": "GET",
- "path": "/api/chat-ai/live-captions/n1star?after=0",
+ "path": "/api/chat-ai/timeline/n1star?offset=0&limit=5",
+ "auth": "anon",
+ "status": 200,
+ "kind": "json",
+ "reads": {
+ "username": "string",
+ "display_name": "string",
+ "overview": "null",
+ "chatInsight": "null",
+ "combinedOverview": "null",
+ "sessionCount": "number",
+ "momentCount": "number",
+ "index": "array",
+ "sessions": "array",
+ "offset": "number",
+ "limit": "number",
+ "hasMore": "boolean"
+ },
+ "from": [
+ "public/js/app-channel.js"
+ ]
+ },
+ {
+ "method": "GET",
+ "path": "/api/chat-ai/timeline/n1star?offset=0&limit=5",
"auth": "user",
"auth": "user",
"status": 200,
"status": 200,
"kind": "json",
"kind": "json",
"reads": {
"reads": {
- "language": "object",
- "language.code": "string",
- "language.name": "string",
- "language.flag": "string",
- "available": "boolean",
- "live": "boolean",
- "stream_id": "number",
- "lines": "array"
+ "username": "string",
+ "display_name": "string",
+ "overview": "null",
+ "chatInsight": "null",
+ "combinedOverview": "null",
+ "sessionCount": "number",
+ "momentCount": "number",
+ "index": "array",
+ "sessions": "array",
+ "offset": "number",
+ "limit": "number",
+ "hasMore": "boolean"
+ },
+ "from": [
+ "public/js/app-channel.js"
+ ]
+ },
+ {
+ "method": "GET",
+ "path": "/api/chat-ai/timeline/n1star?offset=0&limit=12",
+ "auth": "anon",
+ "status": 200,
+ "kind": "json",
+ "reads": {
+ "username": "string",
+ "display_name": "string",
+ "overview": "null",
+ "chatInsight": "null",
+ "combinedOverview": "null",
+ "sessionCount": "number",
+ "momentCount": "number",
+ "index": "array",
+ "sessions": "array",
+ "offset": "number",
+ "limit": "number",
+ "hasMore": "boolean"
+ },
+ "from": [
+ "public/js/app-channel.js"
+ ]
+ },
+ {
+ "method": "GET",
+ "path": "/api/chat-ai/timeline/n1star?offset=0&limit=12",
+ "auth": "user",
+ "status": 200,
+ "kind": "json",
+ "reads": {
+ "username": "string",
+ "display_name": "string",
+ "overview": "null",
+ "chatInsight": "null",
+ "combinedOverview": "null",
+ "sessionCount": "number",
+ "momentCount": "number",
+ "index": "array",
+ "sessions": "array",
+ "offset": "number",
+ "limit": "number",
+ "hasMore": "boolean"
},
},
"from": [
"from": [
"public/js/app-channel.js"
"public/js/app-channel.js"
@@ -1909,202 +1909,6 @@
@@ -1909,202 +1909,6 @@
"public/js/app-home.js"
"public/js/app-home.js"
]
]
},
},
- {
- "method": "GET",
- "path": "/api/emotes/all/1",
- "auth": "anon",
- "status": 200,
- "kind": "json",
- "reads": {
- "defaults": "array",
- "defaults[]": "object",
- "defaults[].id": "string",
- "defaults[].code": "string",
- "defaults[].url": "string",
- "defaults[].source": "string",
- "defaults[].animated": "boolean",
- "defaults[].width": "number",
- "defaults[].height": "number",
- "channel": "array",
- "global": "array",
- "ffz": "array",
- "bttv": "array",
- "sources": "object",
- "sources.defaults": "boolean",
- "sources.custom": "boolean",
- "sources.ffz": "boolean",
- "sources.bttv": "boolean",
- "emote_scale": "number"
- },
- "from": [
- "public/js/emotes.js"
- ]
- },
- {
- "method": "GET",
- "path": "/api/emotes/all/1",
- "auth": "user",
- "status": 200,
- "kind": "json",
- "reads": {
- "defaults": "array",
- "defaults[]": "object",
- "defaults[].id": "string",
- "defaults[].code": "string",
- "defaults[].url": "string",
- "defaults[].source": "string",
- "defaults[].animated": "boolean",
- "defaults[].width": "number",
- "defaults[].height": "number",
- "channel": "array",
- "global": "array",
- "ffz": "array",
- "bttv": "array",
- "sources": "object",
- "sources.defaults": "boolean",
- "sources.custom": "boolean",
- "sources.ffz": "boolean",
- "sources.bttv": "boolean",
- "emote_scale": "number"
- },
- "from": [
- "public/js/emotes.js"
- ]
- },
- {
- "method": "GET",
- "path": "/api/emotes/all/1?channel=n1star",
- "auth": "anon",
- "status": 200,
- "kind": "json",
- "reads": {
- "defaults": "array",
- "defaults[]": "object",
- "defaults[].id": "string",
- "defaults[].code": "string",
- "defaults[].url": "string",
- "defaults[].source": "string",
- "defaults[].animated": "boolean",
- "defaults[].width": "number",
- "defaults[].height": "number",
- "channel": "array",
- "global": "array",
- "ffz": "array",
- "bttv": "array",
- "sources": "object",
- "sources.defaults": "boolean",
- "sources.custom": "boolean",
- "sources.ffz": "boolean",
- "sources.bttv": "boolean",
- "emote_scale": "number"
- },
- "from": [
- "public/obs/chat.html"
- ]
- },
- {
- "method": "GET",
- "path": "/api/emotes/all/1?channel=n1star",
- "auth": "user",
- "status": 200,
- "kind": "json",
- "reads": {
- "defaults": "array",
- "defaults[]": "object",
- "defaults[].id": "string",
- "defaults[].code": "string",
- "defaults[].url": "string",
- "defaults[].source": "string",
- "defaults[].animated": "boolean",
- "defaults[].width": "number",
- "defaults[].height": "number",
- "channel": "array",
- "global": "array",
- "ffz": "array",
- "bttv": "array",
- "sources": "object",
- "sources.defaults": "boolean",
- "sources.custom": "boolean",
- "sources.ffz": "boolean",
- "sources.bttv": "boolean",
- "emote_scale": "number"
- },
- "from": [
- "public/obs/chat.html"
- ]
- },
- {
- "method": "GET",
- "path": "/api/emotes/mine",
- "auth": "anon",
- "status": 401,
- "kind": "json",
- "from": [
- "public/js/emotes.js"
- ]
- },
- {
- "method": "GET",
- "path": "/api/emotes/mine",
- "auth": "user",
- "status": 200,
- "kind": "json",
- "reads": {
- "emotes": "array",
- "count": "number",
- "max": "number"
- },
- "from": [
- "public/js/emotes.js"
- ]
- },
- {
- "method": "GET",
- "path": "/api/emotes/search?q=n1",
- "auth": "anon",
- "status": 502,
- "kind": "json",
- "from": [
- "public/js/emotes.js"
- ]
- },
- {
- "method": "GET",
- "path": "/api/emotes/search?q=n1",
- "auth": "user",
- "status": 502,
- "kind": "json",
- "from": [
- "public/js/emotes.js"
- ]
- },
- {
- "method": "GET",
- "path": "/api/emotes/sources",
- "auth": "anon",
- "status": 401,
- "kind": "json",
- "from": [
- "public/js/emotes.js"
- ]
- },
- {
- "method": "GET",
- "path": "/api/emotes/sources",
- "auth": "user",
- "status": 200,
- "kind": "json",
- "reads": {
- "sources": "object",
- "sources.defaults": "boolean",
- "sources.custom": "boolean",
- "sources.ffz": "boolean",
- "sources.bttv": "boolean"
- },
- "from": [
- "public/js/emotes.js"
- ]
- },
{
{
"method": "GET",
"method": "GET",
"path": "/api/funds/balance",
"path": "/api/funds/balance",
@@ -7295,7 +7099,7 @@
@@ -7295,7 +7099,7 @@
},
},
{
{
"method": "GET",
"method": "GET",
- "path": "/js/app.js?v=533fb6104669",
+ "path": "/js/app.js?v=4d24e4b46d7b",
"auth": "anon",
"auth": "anon",
"accept": "html",
"accept": "html",
"status": 200,
"status": 200,
@@ -7669,7 +7473,7 @@
@@ -7669,7 +7473,7 @@
},
},
{
{
"method": "GET",
"method": "GET",
- "path": "/js/app-channel.js?v=24bb1b7828ce",
+ "path": "/js/app-channel.js?v=c148cdba2aee",
"auth": "anon",
"auth": "anon",
"accept": "html",
"accept": "html",
"status": 200,
"status": 200,
@@ -8181,48 +7985,6 @@
@@ -8181,48 +7985,6 @@
"public/js/app-home.js"
"public/js/app-home.js"
]
]
},
},
- {
- "method": "POST",
- "path": "/api/emotes",
- "auth": "anon",
- "status": 401,
- "kind": "json",
- "from": [
- "public/js/channel-uploads.js",
- "public/js/emotes.js"
- ]
- },
- {
- "method": "PUT",
- "path": "/api/emotes/sources",
- "auth": "anon",
- "status": 401,
- "kind": "json",
- "from": [
- "public/js/emotes.js"
- ]
- },
- {
- "method": "DELETE",
- "path": "/api/emotes/1",
- "auth": "anon",
- "status": 401,
- "kind": "json",
- "from": [
- "public/js/channel-uploads.js",
- "public/js/emotes.js"
- ]
- },
- {
- "method": "PATCH",
- "path": "/api/emotes/1",
- "auth": "anon",
- "status": 401,
- "kind": "json",
- "from": [
- "public/js/channel-uploads.js"
- ]
- },
{
{
"method": "POST",
"method": "POST",
"path": "/api/funds/cashout",
"path": "/api/funds/cashout",
@@ -1,7 +1,7 @@
@@ -1,7 +1,7 @@
{
{
"service": "live",
"service": "live",
- "release": "8cead3637816b496cbd5657753a8ca8e8555a1e8",
- "recorded_at": "2026-09-29T16:51:44.167Z",
+ "release": "8654ef6b86143d4117ff010ce19aa0124a6bcd57",
+ "recorded_at": "2026-09-29T17:33:21.954Z",
"note": "N-1 fixture: written by `npm run n-1:record`, replayed by test/n-1.test.js",
"note": "N-1 fixture: written by `npm run n-1:record`, replayed by test/n-1.test.js",
"user_version": 0,
"user_version": 0,
"schema": [
"schema": [
@@ -35,7 +35,9 @@
@@ -35,7 +35,9 @@
"CREATE TABLE channel_sounds (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n channel_owner_id INTEGER NOT NULL, -- streamer whose channel this sound belongs to\n command TEXT NOT NULL, -- trigger word (without leading '!'), lowercased\n url TEXT NOT NULL, -- served path of the audio file on disk\n mime TEXT DEFAULT 'audio/mpeg',\n duration_seconds REAL DEFAULT 0,\n created_by INTEGER, -- uploader user id (NULL if removed user)\n created_by_name TEXT DEFAULT '',\n is_approved INTEGER DEFAULT 1,\n created_at DATETIME DEFAULT CURRENT_TIMESTAMP, emote_code TEXT DEFAULT '',\n -- Multiple sounds may share a command; playback picks one at random.\n FOREIGN KEY (channel_owner_id) REFERENCES users(id) ON DELETE CASCADE\n)",
"CREATE TABLE channel_sounds (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n channel_owner_id INTEGER NOT NULL, -- streamer whose channel this sound belongs to\n command TEXT NOT NULL, -- trigger word (without leading '!'), lowercased\n url TEXT NOT NULL, -- served path of the audio file on disk\n mime TEXT DEFAULT 'audio/mpeg',\n duration_seconds REAL DEFAULT 0,\n created_by INTEGER, -- uploader user id (NULL if removed user)\n created_by_name TEXT DEFAULT '',\n is_approved INTEGER DEFAULT 1,\n created_at DATETIME DEFAULT CURRENT_TIMESTAMP, emote_code TEXT DEFAULT '',\n -- Multiple sounds may share a command; playback picks one at random.\n FOREIGN KEY (channel_owner_id) REFERENCES users(id) ON DELETE CASCADE\n)",
"CREATE TABLE channels (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n user_id INTEGER NOT NULL UNIQUE,\n title TEXT DEFAULT 'Untitled Channel',\n description TEXT DEFAULT '',\n category TEXT DEFAULT 'irl',\n tags TEXT DEFAULT '[]',\n protocol TEXT DEFAULT 'webrtc' CHECK(protocol IN ('jsmpeg', 'webrtc', 'rtmp')),\n is_nsfw INTEGER DEFAULT 0,\n auto_record INTEGER DEFAULT 0,\n offline_banner_url TEXT,\n panels TEXT DEFAULT '[]', -- JSON array of info panels\n emote_sources TEXT DEFAULT '{\"defaults\":true,\"custom\":true,\"ffz\":true,\"bttv\":true,\"7tv\":true}',\n default_vod_visibility TEXT DEFAULT 'public' CHECK(default_vod_visibility IN ('public', 'unlisted', 'private')),\n default_clip_visibility TEXT DEFAULT 'public' CHECK(default_clip_visibility IN ('public', 'unlisted', 'private')),\n vod_recording_enabled INTEGER DEFAULT 1,\n force_vod_recording_disabled INTEGER DEFAULT 0,\n weather_zip TEXT DEFAULT NULL,\n weather_detail TEXT DEFAULT 'basic' CHECK(weather_detail IN ('off', 'basic', 'hourly', 'detailed')),\n weather_show_location INTEGER DEFAULT 0,\n control_mode TEXT DEFAULT 'open' CHECK(control_mode IN ('open','whitelist','disabled')),\n anon_controls_enabled INTEGER DEFAULT 1,\n control_rate_limit_ms INTEGER DEFAULT 100,\n video_click_enabled INTEGER DEFAULT 0,\n video_click_rate_limit_ms INTEGER DEFAULT 0,\n active_control_config_id INTEGER,\n created_at DATETIME DEFAULT CURRENT_TIMESTAMP,\n updated_at DATETIME DEFAULT CURRENT_TIMESTAMP, chat_language TEXT DEFAULT 'auto', cp_name TEXT DEFAULT 'Channel Points', cp_icon TEXT DEFAULT 'fa-coins', cp_watch_interval_min INTEGER DEFAULT 5, cp_watch_amount INTEGER DEFAULT 10, cp_game_interval_min INTEGER DEFAULT 0, clips_allow_creator_delete INTEGER DEFAULT 0, hide_ai_overview INTEGER DEFAULT 0, ai_overview_pref TEXT DEFAULT 'auto', ai_derivation_enabled INTEGER DEFAULT 1, ai_category TEXT, force_nsfw INTEGER DEFAULT 0, offline_screen_type TEXT DEFAULT 'none', offline_screen_url TEXT, offline_html TEXT, offline_css TEXT, social_links TEXT,\n FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE\n)",
"CREATE TABLE channels (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n user_id INTEGER NOT NULL UNIQUE,\n title TEXT DEFAULT 'Untitled Channel',\n description TEXT DEFAULT '',\n category TEXT DEFAULT 'irl',\n tags TEXT DEFAULT '[]',\n protocol TEXT DEFAULT 'webrtc' CHECK(protocol IN ('jsmpeg', 'webrtc', 'rtmp')),\n is_nsfw INTEGER DEFAULT 0,\n auto_record INTEGER DEFAULT 0,\n offline_banner_url TEXT,\n panels TEXT DEFAULT '[]', -- JSON array of info panels\n emote_sources TEXT DEFAULT '{\"defaults\":true,\"custom\":true,\"ffz\":true,\"bttv\":true,\"7tv\":true}',\n default_vod_visibility TEXT DEFAULT 'public' CHECK(default_vod_visibility IN ('public', 'unlisted', 'private')),\n default_clip_visibility TEXT DEFAULT 'public' CHECK(default_clip_visibility IN ('public', 'unlisted', 'private')),\n vod_recording_enabled INTEGER DEFAULT 1,\n force_vod_recording_disabled INTEGER DEFAULT 0,\n weather_zip TEXT DEFAULT NULL,\n weather_detail TEXT DEFAULT 'basic' CHECK(weather_detail IN ('off', 'basic', 'hourly', 'detailed')),\n weather_show_location INTEGER DEFAULT 0,\n control_mode TEXT DEFAULT 'open' CHECK(control_mode IN ('open','whitelist','disabled')),\n anon_controls_enabled INTEGER DEFAULT 1,\n control_rate_limit_ms INTEGER DEFAULT 100,\n video_click_enabled INTEGER DEFAULT 0,\n video_click_rate_limit_ms INTEGER DEFAULT 0,\n active_control_config_id INTEGER,\n created_at DATETIME DEFAULT CURRENT_TIMESTAMP,\n updated_at DATETIME DEFAULT CURRENT_TIMESTAMP, chat_language TEXT DEFAULT 'auto', cp_name TEXT DEFAULT 'Channel Points', cp_icon TEXT DEFAULT 'fa-coins', cp_watch_interval_min INTEGER DEFAULT 5, cp_watch_amount INTEGER DEFAULT 10, cp_game_interval_min INTEGER DEFAULT 0, clips_allow_creator_delete INTEGER DEFAULT 0, hide_ai_overview INTEGER DEFAULT 0, ai_overview_pref TEXT DEFAULT 'auto', ai_derivation_enabled INTEGER DEFAULT 1, ai_category TEXT, force_nsfw INTEGER DEFAULT 0, offline_screen_type TEXT DEFAULT 'none', offline_screen_url TEXT, offline_html TEXT, offline_css TEXT, social_links TEXT,\n FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE\n)",
"CREATE TABLE chat_ai_summaries (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n scope TEXT NOT NULL,\n subject_id INTEGER NOT NULL DEFAULT 0,\n window TEXT NOT NULL,\n overview TEXT DEFAULT '',\n memory_json TEXT DEFAULT '',\n timeline_json TEXT DEFAULT '[]',\n message_count INTEGER DEFAULT 0,\n window_message_count INTEGER DEFAULT 0,\n last_message_id INTEGER DEFAULT 0,\n window_label TEXT DEFAULT '',\n window_start DATETIME,\n window_end DATETIME,\n updated_at DATETIME DEFAULT CURRENT_TIMESTAMP,\n UNIQUE(scope, subject_id, window)\n )",
"CREATE TABLE chat_ai_summaries (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n scope TEXT NOT NULL,\n subject_id INTEGER NOT NULL DEFAULT 0,\n window TEXT NOT NULL,\n overview TEXT DEFAULT '',\n memory_json TEXT DEFAULT '',\n timeline_json TEXT DEFAULT '[]',\n message_count INTEGER DEFAULT 0,\n window_message_count INTEGER DEFAULT 0,\n last_message_id INTEGER DEFAULT 0,\n window_label TEXT DEFAULT '',\n window_start DATETIME,\n window_end DATETIME,\n updated_at DATETIME DEFAULT CURRENT_TIMESTAMP,\n UNIQUE(scope, subject_id, window)\n )",
+ "CREATE TABLE chat_dual_read_stats (\n tbl TEXT PRIMARY KEY,\n compared INTEGER NOT NULL DEFAULT 0,\n matched INTEGER NOT NULL DEFAULT 0,\n mismatched INTEGER NOT NULL DEFAULT 0,\n inconclusive INTEGER NOT NULL DEFAULT 0,\n errors INTEGER NOT NULL DEFAULT 0,\n last_mismatch_at DATETIME,\n last_mismatch TEXT,\n since DATETIME DEFAULT CURRENT_TIMESTAMP\n)",
"CREATE TABLE \"chat_messages\" (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n stream_id INTEGER,\n user_id INTEGER, -- NULL for anon\n anon_id TEXT, -- 'anon12345' format\n username TEXT,\n message TEXT NOT NULL,\n message_type TEXT DEFAULT 'chat' CHECK(message_type IN ('chat', 'system', 'donation', 'command', 'tts', 'channel-sound', 'soundboard', 'clip')),\n metadata TEXT, -- JSON sidecar for rich events (donation/goal-reached)\n is_global INTEGER DEFAULT 0,\n is_deleted INTEGER DEFAULT 0,\n is_filtered INTEGER DEFAULT 0,\n reply_to_id INTEGER REFERENCES chat_messages(id) ON DELETE SET NULL,\n source_platform TEXT,\n deleted_by INTEGER,\n deleted_at DATETIME,\n auto_delete_at DATETIME,\n timestamp DATETIME DEFAULT CURRENT_TIMESTAMP, channel_user_id INTEGER,\n FOREIGN KEY (stream_id) REFERENCES streams(id) ON DELETE CASCADE,\n FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE SET NULL\n)",
"CREATE TABLE \"chat_messages\" (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n stream_id INTEGER,\n user_id INTEGER, -- NULL for anon\n anon_id TEXT, -- 'anon12345' format\n username TEXT,\n message TEXT NOT NULL,\n message_type TEXT DEFAULT 'chat' CHECK(message_type IN ('chat', 'system', 'donation', 'command', 'tts', 'channel-sound', 'soundboard', 'clip')),\n metadata TEXT, -- JSON sidecar for rich events (donation/goal-reached)\n is_global INTEGER DEFAULT 0,\n is_deleted INTEGER DEFAULT 0,\n is_filtered INTEGER DEFAULT 0,\n reply_to_id INTEGER REFERENCES chat_messages(id) ON DELETE SET NULL,\n source_platform TEXT,\n deleted_by INTEGER,\n deleted_at DATETIME,\n auto_delete_at DATETIME,\n timestamp DATETIME DEFAULT CURRENT_TIMESTAMP, channel_user_id INTEGER,\n FOREIGN KEY (stream_id) REFERENCES streams(id) ON DELETE CASCADE,\n FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE SET NULL\n)",
+ "CREATE TABLE chat_staged_outbox (\n seq INTEGER PRIMARY KEY AUTOINCREMENT,\n tbl TEXT NOT NULL,\n op TEXT NOT NULL,\n pk TEXT NOT NULL,\n created_at DATETIME DEFAULT CURRENT_TIMESTAMP\n)",
"CREATE TABLE chat_timeline_events (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n scope TEXT NOT NULL DEFAULT 'global',\n subject_id INTEGER NOT NULL DEFAULT 0,\n ts DATETIME NOT NULL,\n label TEXT NOT NULL,\n detail TEXT DEFAULT '',\n created_at DATETIME DEFAULT CURRENT_TIMESTAMP\n )",
"CREATE TABLE chat_timeline_events (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n scope TEXT NOT NULL DEFAULT 'global',\n subject_id INTEGER NOT NULL DEFAULT 0,\n ts DATETIME NOT NULL,\n label TEXT NOT NULL,\n detail TEXT DEFAULT '',\n created_at DATETIME DEFAULT CURRENT_TIMESTAMP\n )",
"CREATE TABLE clip_ai_state (\n clip_id INTEGER PRIMARY KEY,\n ai_overview_short TEXT,\n ai_transcript_json TEXT,\n transcript_status TEXT,\n transcript_attempts INTEGER DEFAULT 0,\n transcript_error TEXT,\n transcript_next_at DATETIME,\n clip_notified INTEGER DEFAULT 0,\n clip_notify_at DATETIME\n , ai_overview TEXT, transcript_partial_json TEXT, transcript_progress_sec INTEGER DEFAULT 0)",
"CREATE TABLE clip_ai_state (\n clip_id INTEGER PRIMARY KEY,\n ai_overview_short TEXT,\n ai_transcript_json TEXT,\n transcript_status TEXT,\n transcript_attempts INTEGER DEFAULT 0,\n transcript_error TEXT,\n transcript_next_at DATETIME,\n clip_notified INTEGER DEFAULT 0,\n clip_notify_at DATETIME\n , ai_overview TEXT, transcript_partial_json TEXT, transcript_progress_sec INTEGER DEFAULT 0)",
"CREATE TABLE clips (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n vod_id INTEGER,\n stream_id INTEGER,\n user_id INTEGER NOT NULL,\n title TEXT DEFAULT 'Untitled Clip',\n description TEXT DEFAULT '',\n file_path TEXT,\n thumbnail_url TEXT,\n start_time REAL NOT NULL DEFAULT 0,\n end_time REAL NOT NULL DEFAULT 0,\n duration_seconds REAL DEFAULT 0,\n is_public INTEGER DEFAULT 1,\n view_count INTEGER DEFAULT 0,\n created_at DATETIME DEFAULT CURRENT_TIMESTAMP, storage_provider TEXT DEFAULT 'local', storage_key TEXT, ai_overview TEXT, ai_transcript TEXT, ai_analyzed_at DATETIME, clip_notified INTEGER DEFAULT 0, clip_notify_at DATETIME, visibility TEXT DEFAULT 'public', auto_generated INTEGER DEFAULT 0,\n FOREIGN KEY (vod_id) REFERENCES vods(id) ON DELETE SET NULL,\n FOREIGN KEY (stream_id) REFERENCES streams(id) ON DELETE SET NULL,\n FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE\n)",
"CREATE TABLE clips (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n vod_id INTEGER,\n stream_id INTEGER,\n user_id INTEGER NOT NULL,\n title TEXT DEFAULT 'Untitled Clip',\n description TEXT DEFAULT '',\n file_path TEXT,\n thumbnail_url TEXT,\n start_time REAL NOT NULL DEFAULT 0,\n end_time REAL NOT NULL DEFAULT 0,\n duration_seconds REAL DEFAULT 0,\n is_public INTEGER DEFAULT 1,\n view_count INTEGER DEFAULT 0,\n created_at DATETIME DEFAULT CURRENT_TIMESTAMP, storage_provider TEXT DEFAULT 'local', storage_key TEXT, ai_overview TEXT, ai_transcript TEXT, ai_analyzed_at DATETIME, clip_notified INTEGER DEFAULT 0, clip_notify_at DATETIME, visibility TEXT DEFAULT 'public', auto_generated INTEGER DEFAULT 0,\n FOREIGN KEY (vod_id) REFERENCES vods(id) ON DELETE SET NULL,\n FOREIGN KEY (stream_id) REFERENCES streams(id) ON DELETE SET NULL,\n FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE\n)",
@@ -257,19 +259,19 @@
@@ -257,19 +259,19 @@
"schema_migrations": [
"schema_migrations": [
{
{
"id": "001_vibes_decimal_to_bits",
"id": "001_vibes_decimal_to_bits",
- "applied_at": "2026-09-29 16:51:35",
+ "applied_at": "2026-09-29 17:33:17",
"mode": "adopted",
"mode": "adopted",
"duration_ms": 0
"duration_ms": 0
},
},
{
{
"id": "002_pastes_ai_columns",
"id": "002_pastes_ai_columns",
- "applied_at": "2026-09-29 16:51:35",
+ "applied_at": "2026-09-29 17:33:17",
"mode": "applied",
"mode": "applied",
- "duration_ms": 13
+ "duration_ms": 8
},
},
{
{
"id": "004_hot_path_indexes",
"id": "004_hot_path_indexes",
- "applied_at": "2026-09-29 16:51:35",
+ "applied_at": "2026-09-29 17:33:17",
"mode": "applied",
"mode": "applied",
"duration_ms": 1
"duration_ms": 1
}
}
@@ -283,8 +285,6 @@
@@ -283,8 +285,6 @@
"CREATE TABLE IF NOT EXISTS subject_projection ( subject_id TEXT PRIMARY KEY, network_user_id INTEGER, revision INTEGER NOT NULL, username TEXT NOT NULL, display_name TEXT, avatar_url TEXT, profile_color TEXT, role TEXT NOT NULL, banned INTEGER NOT NULL DEFAULT 0, updated_at DATETIME DEFAULT CURRENT_TIMESTAMP )",
"CREATE TABLE IF NOT EXISTS subject_projection ( subject_id TEXT PRIMARY KEY, network_user_id INTEGER, revision INTEGER NOT NULL, username TEXT NOT NULL, display_name TEXT, avatar_url TEXT, profile_color TEXT, role TEXT NOT NULL, banned INTEGER NOT NULL DEFAULT 0, updated_at DATETIME DEFAULT CURRENT_TIMESTAMP )",
"CREATE TABLE IF NOT EXISTS username_history ( id INTEGER PRIMARY KEY AUTOINCREMENT, user_id INTEGER NOT NULL, old_username TEXT NOT NULL, new_username TEXT NOT NULL, changed_at DATETIME DEFAULT CURRENT_TIMESTAMP )",
"CREATE TABLE IF NOT EXISTS username_history ( id INTEGER PRIMARY KEY AUTOINCREMENT, user_id INTEGER NOT NULL, old_username TEXT NOT NULL, new_username TEXT NOT NULL, changed_at DATETIME DEFAULT CURRENT_TIMESTAMP )",
"CREATE TABLE IF NOT EXISTS chat_bridge_outbox ( id INTEGER PRIMARY KEY AUTOINCREMENT, boot TEXT NOT NULL, ref INTEGER, op TEXT NOT NULL, args TEXT NOT NULL, created_at DATETIME DEFAULT CURRENT_TIMESTAMP )",
"CREATE TABLE IF NOT EXISTS chat_bridge_outbox ( id INTEGER PRIMARY KEY AUTOINCREMENT, boot TEXT NOT NULL, ref INTEGER, op TEXT NOT NULL, args TEXT NOT NULL, created_at DATETIME DEFAULT CURRENT_TIMESTAMP )",
- "CREATE TABLE IF NOT EXISTS chat_staged_outbox ( seq INTEGER PRIMARY KEY AUTOINCREMENT, tbl TEXT NOT NULL, op TEXT NOT NULL, pk TEXT NOT NULL, created_at DATETIME DEFAULT CURRENT_TIMESTAMP )",
- "CREATE TABLE IF NOT EXISTS chat_dual_read_stats ( tbl TEXT PRIMARY KEY, compared INTEGER NOT NULL DEFAULT 0, matched INTEGER NOT NULL DEFAULT 0, mismatched INTEGER NOT NULL DEFAULT 0, inconclusive INTEGER NOT NULL DEFAULT 0, errors INTEGER NOT NULL DEFAULT 0, last_mismatch_at DATETIME, last_mismatch TEXT, since DATETIME DEFAULT CURRENT_TIMESTAMP )",
"CREATE TABLE IF NOT EXISTS comment_thread_refs ( content_type TEXT NOT NULL, content_id INTEGER NOT NULL, thread_id INTEGER NOT NULL, access_id TEXT NOT NULL, created_at DATETIME DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (content_type, content_id) )",
"CREATE TABLE IF NOT EXISTS comment_thread_refs ( content_type TEXT NOT NULL, content_id INTEGER NOT NULL, thread_id INTEGER NOT NULL, access_id TEXT NOT NULL, created_at DATETIME DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (content_type, content_id) )",
"CREATE TABLE IF NOT EXISTS search_doc_pushes ( user_id INTEGER PRIMARY KEY, hash TEXT NOT NULL, revision INTEGER NOT NULL, deleted INTEGER NOT NULL DEFAULT 0, pushed_at DATETIME DEFAULT CURRENT_TIMESTAMP )",
"CREATE TABLE IF NOT EXISTS search_doc_pushes ( user_id INTEGER PRIMARY KEY, hash TEXT NOT NULL, revision INTEGER NOT NULL, deleted INTEGER NOT NULL DEFAULT 0, pushed_at DATETIME DEFAULT CURRENT_TIMESTAMP )",
"CREATE TABLE IF NOT EXISTS search_media_pushes ( kind TEXT NOT NULL, media_id INTEGER NOT NULL, hash TEXT NOT NULL, revision INTEGER NOT NULL, deleted INTEGER NOT NULL DEFAULT 0, pushed_at DATETIME DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (kind, media_id) )",
"CREATE TABLE IF NOT EXISTS search_media_pushes ( kind TEXT NOT NULL, media_id INTEGER NOT NULL, hash TEXT NOT NULL, revision INTEGER NOT NULL, deleted INTEGER NOT NULL DEFAULT 0, pushed_at DATETIME DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (kind, media_id) )",
@@ -311,12 +311,10 @@
@@ -311,12 +311,10 @@
"DELETE FROM camera_presets WHERE id = ?",
"DELETE FROM camera_presets WHERE id = ?",
"DELETE FROM camera_profiles WHERE id = ?",
"DELETE FROM camera_profiles WHERE id = ?",
"DELETE FROM channel_ai_bots WHERE id = ?",
"DELETE FROM channel_ai_bots WHERE id = ?",
- "DELETE FROM channel_moderators WHERE channel_id = ? AND user_id = ?",
"DELETE FROM channel_points WHERE user_id = ? AND streamer_id = ?",
"DELETE FROM channel_points WHERE user_id = ? AND streamer_id = ?",
"DELETE FROM channel_sounds WHERE id = ?",
"DELETE FROM channel_sounds WHERE id = ?",
"DELETE FROM chat_bridge_outbox",
"DELETE FROM chat_bridge_outbox",
"DELETE FROM chat_bridge_outbox WHERE id = ?",
"DELETE FROM chat_bridge_outbox WHERE id = ?",
- "DELETE FROM chat_dual_read_stats WHERE tbl = ?",
"DELETE FROM clip_ai_state WHERE clip_id = ?",
"DELETE FROM clip_ai_state WHERE clip_id = ?",
"DELETE FROM coin_rewards WHERE id = ?",
"DELETE FROM coin_rewards WHERE id = ?",
"DELETE FROM content_views WHERE content_type = ? AND content_id = ?",
"DELETE FROM content_views WHERE content_type = ? AND content_id = ?",
@@ -328,7 +326,6 @@
@@ -328,7 +326,6 @@
"DELETE FROM dm_messages WHERE id = ?",
"DELETE FROM dm_messages WHERE id = ?",
"DELETE FROM dm_participants WHERE conversation_id = ? AND user_id = ?",
"DELETE FROM dm_participants WHERE conversation_id = ? AND user_id = ?",
"DELETE FROM donation_goals WHERE id = ? AND user_id = ?",
"DELETE FROM donation_goals WHERE id = ? AND user_id = ?",
- "DELETE FROM emotes WHERE id = ?",
"DELETE FROM follows WHERE follower_id = ? AND streamer_id = ?",
"DELETE FROM follows WHERE follower_id = ? AND streamer_id = ?",
"DELETE FROM follows WHERE id = ?",
"DELETE FROM follows WHERE id = ?",
"DELETE FROM hidden_relay_users WHERE id = ?",
"DELETE FROM hidden_relay_users WHERE id = ?",
@@ -388,13 +385,10 @@
@@ -388,13 +385,10 @@
"INSERT INTO cameras (stream_id, camera_index, label, protocol) VALUES (?, 0, 'Main', ?)",
"INSERT INTO cameras (stream_id, camera_index, label, protocol) VALUES (?, 0, 'Main', ?)",
"INSERT INTO channel_ai_bots (channel_user_id, username, display_name, avatar_color, source, cloned_from_kind, cloned_from_ref, persona_json, brain_json) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)",
"INSERT INTO channel_ai_bots (channel_user_id, username, display_name, avatar_color, source, cloned_from_kind, cloned_from_ref, persona_json, brain_json) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)",
"INSERT INTO channel_ai_config (user_id, enabled, num_ambient_bots, pacing_seconds, persona, transcribe_enabled, vision_enabled, use_shared_key, daily_budget_cents, byo_key, byo_base_url, byo_model) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)",
"INSERT INTO channel_ai_config (user_id, enabled, num_ambient_bots, pacing_seconds, persona, transcribe_enabled, vision_enabled, use_shared_key, daily_budget_cents, byo_key, byo_base_url, byo_model) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)",
- "INSERT INTO channel_moderation_settings ( channel_id, slow_mode_seconds, followers_only, emote_only, allow_anonymous, links_allowed, gifs_enabled, account_age_gate_hours, caps_percentage_limit, aggressive_filter, max_message_length, slur_filter_enabled, slur_filter_use_builtin, slur_filter_terms, slur_filter_regexes, slur_filter_nudge_message, slur_filter_disabled_categories, ip_approval_mode, soundboard_enabled, soundboard_allow_pitch, soundboard_allow_speed, soundboard_banned_ids, viewer_auto_delete_enabled, viewer_delete_all_enabled, custom_emotes_enabled, custom_sounds_enabled, max_sound_seconds, uploads_mods_only, emote_scale, emote_size_min, emote_size_max, sounds_mods_only, mods_can_edit_about ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)",
- "INSERT INTO channel_moderation_settings (channel_id) VALUES (?)",
"INSERT INTO channel_points (user_id, streamer_id, balance) VALUES (?, ?, ?)",
"INSERT INTO channel_points (user_id, streamer_id, balance) VALUES (?, ?, ?)",
"INSERT INTO channel_points (user_id, streamer_id, balance, updated_at) VALUES (?, ?, ?, CURRENT_TIMESTAMP) ON CONFLICT(user_id, streamer_id) DO UPDATE SET balance = balance + excluded.balance, updated_at = CURRENT_TIMESTAMP",
"INSERT INTO channel_points (user_id, streamer_id, balance, updated_at) VALUES (?, ?, ?, CURRENT_TIMESTAMP) ON CONFLICT(user_id, streamer_id) DO UPDATE SET balance = balance + excluded.balance, updated_at = CURRENT_TIMESTAMP",
"INSERT INTO channel_points_log (idempotency_key, user_id, streamer_id, delta, reason) VALUES (?, ?, ?, ?, ?)",
"INSERT INTO channel_points_log (idempotency_key, user_id, streamer_id, delta, reason) VALUES (?, ?, ?, ?, ?)",
"INSERT INTO channel_sounds (channel_owner_id, command, url, mime, duration_seconds, created_by, created_by_name, emote_code) VALUES (?, ?, ?, ?, ?, ?, ?, ?)",
"INSERT INTO channel_sounds (channel_owner_id, command, url, mime, duration_seconds, created_by, created_by_name, emote_code) VALUES (?, ?, ?, ?, ?, ?, ?, ?)",
- "INSERT INTO chat_ai_summaries (scope, subject_id, window, overview, memory_json, timeline_json, message_count, window_message_count, last_message_id, window_label, window_start, window_end, updated_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, CURRENT_TIMESTAMP) ON CONFLICT(scope, subject_id, window) DO UPDATE SET overview = excluded.overview, memory_json = excluded.memory_json, timeline_json = excluded.timeline_json, message_count = excluded.message_count, window_message_count = excluded.window_message_count, last_message_id = excluded.last_message_id, window_label = excluded.window_label, window_start = excluded.window_start, window_end = excluded.window_end, updated_at = CURRENT_TIMESTAMP",
"INSERT INTO chat_bridge_outbox (boot, ref, op, args) VALUES (?, ?, ?, ?)",
"INSERT INTO chat_bridge_outbox (boot, ref, op, args) VALUES (?, ?, ?, ?)",
"INSERT INTO chat_messages (stream_id, channel_user_id, user_id, anon_id, username, message, message_type, is_global, reply_to_id, source_platform, auto_delete_at, metadata) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)",
"INSERT INTO chat_messages (stream_id, channel_user_id, user_id, anon_id, username, message, message_type, is_global, reply_to_id, source_platform, auto_delete_at, metadata) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)",
"INSERT INTO coin_redemptions (reward_id, user_id, stream_id, user_input) VALUES (?, ?, ?, ?)",
"INSERT INTO coin_redemptions (reward_id, user_id, stream_id, user_input) VALUES (?, ?, ?, ?)",
@@ -407,7 +401,6 @@
@@ -407,7 +401,6 @@
"INSERT INTO dm_messages (conversation_id, sender_id, message) VALUES (?, ?, ?)",
"INSERT INTO dm_messages (conversation_id, sender_id, message) VALUES (?, ?, ?)",
"INSERT INTO donation_goals (user_id, title, target_amount) VALUES (?, ?, ?)",
"INSERT INTO donation_goals (user_id, title, target_amount) VALUES (?, ?, ?)",
"INSERT INTO donation_goals (user_id, title, target_amount, image_url, media_type, sort_order) VALUES (?, ?, ?, ?, ?, ?)",
"INSERT INTO donation_goals (user_id, title, target_amount, image_url, media_type, sort_order) VALUES (?, ?, ?, ?, ?, ?)",
- "INSERT INTO emotes (user_id, code, url, animated, width, height, is_global, channel_owner_id, size) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)",
"INSERT INTO follow_projection_revisions (follower_subject, target_subject, revision) VALUES (?, ?, ?) ON CONFLICT (follower_subject, target_subject) DO UPDATE SET revision = excluded.revision",
"INSERT INTO follow_projection_revisions (follower_subject, target_subject, revision) VALUES (?, ?, ?) ON CONFLICT (follower_subject, target_subject) DO UPDATE SET revision = excluded.revision",
"INSERT INTO ip_log (user_id, anon_id, ip_address, action, geo_country, geo_region, geo_city, geo_isp, geo_org, geo_ll, user_agent) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)",
"INSERT INTO ip_log (user_id, anon_id, ip_address, action, geo_country, geo_region, geo_city, geo_isp, geo_org, geo_ll, user_agent) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)",
"INSERT INTO kick_channel_cache (slug, chatroom_id, kick_channel_id, updated_at) VALUES (?, ?, ?, CURRENT_TIMESTAMP) ON CONFLICT(slug) DO UPDATE SET chatroom_id = excluded.chatroom_id, kick_channel_id = COALESCE(excluded.kick_channel_id, kick_channel_cache.kick_channel_id), updated_at = CURRENT_TIMESTAMP",
"INSERT INTO kick_channel_cache (slug, chatroom_id, kick_channel_id, updated_at) VALUES (?, ?, ?, CURRENT_TIMESTAMP) ON CONFLICT(slug) DO UPDATE SET chatroom_id = excluded.chatroom_id, kick_channel_id = COALESCE(excluded.kick_channel_id, kick_channel_cache.kick_channel_id), updated_at = CURRENT_TIMESTAMP",
@@ -460,10 +453,8 @@
@@ -460,10 +453,8 @@
"INSERT OR IGNORE INTO arena_beef_hype (beef_id, side, voter_key) VALUES (?, ?, ?)",
"INSERT OR IGNORE INTO arena_beef_hype (beef_id, side, voter_key) VALUES (?, ?, ?)",
"INSERT OR IGNORE INTO billing_actions (action, idempotency_key, live_user_id, live_ref, method, path, request_json) VALUES (?, ?, ?, ?, ?, ?, ?)",
"INSERT OR IGNORE INTO billing_actions (action, idempotency_key, live_user_id, live_ref, method, path, request_json) VALUES (?, ?, ?, ?, ?, ?, ?)",
"INSERT OR IGNORE INTO channel_ai_config (user_id, enabled, num_ambient_bots, pacing_seconds, persona, transcribe_enabled, vision_enabled, use_shared_key, daily_budget_cents, byo_key, byo_base_url, byo_model) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)",
"INSERT OR IGNORE INTO channel_ai_config (user_id, enabled, num_ambient_bots, pacing_seconds, persona, transcribe_enabled, vision_enabled, use_shared_key, daily_budget_cents, byo_key, byo_base_url, byo_model) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)",
- "INSERT OR IGNORE INTO channel_moderators (channel_id, user_id, added_by) VALUES (?, ?, ?)",
"INSERT OR IGNORE INTO channel_points_log (idempotency_key, user_id, streamer_id, delta, reason) VALUES (?, ?, ?, ?, ?)",
"INSERT OR IGNORE INTO channel_points_log (idempotency_key, user_id, streamer_id, delta, reason) VALUES (?, ?, ?, ?, ?)",
"INSERT OR IGNORE INTO channels (user_id, title, description, category, protocol) VALUES (?, ?, ?, ?, ?)",
"INSERT OR IGNORE INTO channels (user_id, title, description, category, protocol) VALUES (?, ?, ?, ?, ?)",
- "INSERT OR IGNORE INTO chat_timeline_events (scope, subject_id, ts, label, detail) VALUES (?, ?, ?, ?, ?)",
"INSERT OR IGNORE INTO clip_ai_state (clip_id) VALUES (?)",
"INSERT OR IGNORE INTO clip_ai_state (clip_id) VALUES (?)",
"INSERT OR IGNORE INTO comment_thread_refs (content_type, content_id, thread_id, access_id) VALUES (?, ?, ?, ?)",
"INSERT OR IGNORE INTO comment_thread_refs (content_type, content_id, thread_id, access_id) VALUES (?, ?, ?, ?)",
"INSERT OR IGNORE INTO content_views (content_type, content_id, ip) VALUES (?, ?, ?)",
"INSERT OR IGNORE INTO content_views (content_type, content_id, ip) VALUES (?, ?, ?)",
@@ -533,15 +524,12 @@
@@ -533,15 +524,12 @@
"SELECT * FROM channel_ai_bots WHERE channel_user_id = ? ORDER BY last_active_at DESC, created_at ASC",
"SELECT * FROM channel_ai_bots WHERE channel_user_id = ? ORDER BY last_active_at DESC, created_at ASC",
"SELECT * FROM channel_ai_bots WHERE id = ?",
"SELECT * FROM channel_ai_bots WHERE id = ?",
"SELECT * FROM channel_ai_config WHERE user_id = ?",
"SELECT * FROM channel_ai_config WHERE user_id = ?",
- "SELECT * FROM channel_moderation_settings WHERE channel_id = ?",
"SELECT * FROM channel_sounds WHERE channel_owner_id = ? AND command = ? AND is_approved = 1 ORDER BY RANDOM() LIMIT 1",
"SELECT * FROM channel_sounds WHERE channel_owner_id = ? AND command = ? AND is_approved = 1 ORDER BY RANDOM() LIMIT 1",
"SELECT * FROM channel_sounds WHERE channel_owner_id = ? AND is_approved = 1 ORDER BY command",
"SELECT * FROM channel_sounds WHERE channel_owner_id = ? AND is_approved = 1 ORDER BY command",
"SELECT * FROM channel_sounds WHERE id = ?",
"SELECT * FROM channel_sounds WHERE id = ?",
"SELECT * FROM channels WHERE id = ?",
"SELECT * FROM channels WHERE id = ?",
"SELECT * FROM channels WHERE user_id = ?",
"SELECT * FROM channels WHERE user_id = ?",
"SELECT * FROM channels WHERE user_id IN (?)",
"SELECT * FROM channels WHERE user_id IN (?)",
- "SELECT * FROM chat_ai_summaries WHERE scope = ? AND subject_id = ? AND window = ?",
- "SELECT * FROM chat_ai_summaries WHERE scope = ? AND subject_id = ? ORDER BY window",
"SELECT * FROM chat_messages WHERE id = ?",
"SELECT * FROM chat_messages WHERE id = ?",
"SELECT * FROM clip_ai_state WHERE clip_id = ?",
"SELECT * FROM clip_ai_state WHERE clip_id = ?",
"SELECT * FROM coin_rewards WHERE id = ?",
"SELECT * FROM coin_rewards WHERE id = ?",
@@ -559,9 +547,6 @@
@@ -559,9 +547,6 @@
"SELECT * FROM donation_goals WHERE user_id = ? AND is_active = 1 ORDER BY created_at",
"SELECT * FROM donation_goals WHERE user_id = ? AND is_active = 1 ORDER BY created_at",
"SELECT * FROM donation_goals WHERE user_id = ? AND is_active = 1 ORDER BY sort_order ASC, created_at ASC",
"SELECT * FROM donation_goals WHERE user_id = ? AND is_active = 1 ORDER BY sort_order ASC, created_at ASC",
"SELECT * FROM donation_goals WHERE user_id = ? ORDER BY is_active DESC, sort_order ASC, created_at ASC",
"SELECT * FROM donation_goals WHERE user_id = ? ORDER BY is_active DESC, sort_order ASC, created_at ASC",
- "SELECT * FROM emotes WHERE code = ? AND ((channel_owner_id = ?) OR (channel_owner_id IS NULL AND user_id = ?)) LIMIT 1",
- "SELECT * FROM emotes WHERE code = ? AND (user_id = ? OR is_global = 1) AND is_approved = 1 ORDER BY is_global ASC LIMIT 1",
- "SELECT * FROM emotes WHERE user_id = ? ORDER BY code",
"SELECT * FROM kick_channel_cache WHERE slug = ?",
"SELECT * FROM kick_channel_cache WHERE slug = ?",
"SELECT * FROM lineage_unresolved ORDER BY last_at DESC LIMIT ?",
"SELECT * FROM lineage_unresolved ORDER BY last_at DESC LIMIT ?",
"SELECT * FROM lineage_unresolved WHERE reason = ? ORDER BY last_at DESC LIMIT ?",
"SELECT * FROM lineage_unresolved WHERE reason = ? ORDER BY last_at DESC LIMIT ?",
@@ -638,8 +623,6 @@
@@ -638,8 +623,6 @@
"SELECT 1 FROM ai_chatbot_configs WHERE user_id = ?",
"SELECT 1 FROM ai_chatbot_configs WHERE user_id = ?",
"SELECT 1 FROM approved_ips WHERE channel_id = ? AND ip_address = ?",
"SELECT 1 FROM approved_ips WHERE channel_id = ? AND ip_address = ?",
"SELECT 1 FROM channel_ai_config WHERE user_id = ?",
"SELECT 1 FROM channel_ai_config WHERE user_id = ?",
- "SELECT 1 FROM channel_moderation_settings WHERE channel_id = ?",
- "SELECT 1 FROM channel_moderators WHERE user_id = ? AND channel_id = ?",
"SELECT 1 FROM channel_points WHERE user_id = ? AND streamer_id = ?",
"SELECT 1 FROM channel_points WHERE user_id = ? AND streamer_id = ?",
"SELECT 1 FROM chat_messages cm JOIN streams s ON cm.stream_id = s.id WHERE s.channel_id = ? AND cm.is_deleted = 0 AND (cm.user_id = ? OR cm.anon_id = ?) LIMIT 1",
"SELECT 1 FROM chat_messages cm JOIN streams s ON cm.stream_id = s.id WHERE s.channel_id = ? AND cm.is_deleted = 0 AND (cm.user_id = ? OR cm.anon_id = ?) LIMIT 1",
"SELECT 1 FROM control_whitelist WHERE channel_id = ? AND user_id = ?",
"SELECT 1 FROM control_whitelist WHERE channel_id = ? AND user_id = ?",
@@ -756,8 +739,6 @@
@@ -756,8 +739,6 @@
"SELECT COUNT(*) AS n FROM channel_sounds WHERE channel_owner_id = ?",
"SELECT COUNT(*) AS n FROM channel_sounds WHERE channel_owner_id = ?",
"SELECT COUNT(*) AS n FROM chat_messages WHERE stream_id = ? AND message_type = 'soundboard'",
"SELECT COUNT(*) AS n FROM chat_messages WHERE stream_id = ? AND message_type = 'soundboard'",
"SELECT COUNT(*) AS n FROM chat_messages WHERE timestamp >= ? AND COALESCE(is_deleted, 0) = 0",
"SELECT COUNT(*) AS n FROM chat_messages WHERE timestamp >= ? AND COALESCE(is_deleted, 0) = 0",
- "SELECT COUNT(*) AS n FROM chat_staged_outbox",
- "SELECT COUNT(*) AS n FROM chat_staged_outbox WHERE tbl = ?",
"SELECT COUNT(*) AS n FROM control_configs WHERE user_id = ?",
"SELECT COUNT(*) AS n FROM control_configs WHERE user_id = ?",
"SELECT COUNT(*) AS n FROM donation_goals WHERE user_id = ? AND is_active = 1",
"SELECT COUNT(*) AS n FROM donation_goals WHERE user_id = ? AND is_active = 1",
"SELECT COUNT(*) AS n FROM easter_egg_solves WHERE egg_date = ?",
"SELECT COUNT(*) AS n FROM easter_egg_solves WHERE egg_date = ?",
@@ -807,8 +788,6 @@
@@ -807,8 +788,6 @@
"SELECT COUNT(*) as cnt FROM streams WHERE user_id = ? AND duration_seconds > 0",
"SELECT COUNT(*) as cnt FROM streams WHERE user_id = ? AND duration_seconds > 0",
"SELECT COUNT(*) as count FROM channel_sounds WHERE channel_owner_id = ?",
"SELECT COUNT(*) as count FROM channel_sounds WHERE channel_owner_id = ?",
"SELECT COUNT(*) as count FROM channel_sounds WHERE channel_owner_id = ? AND created_by = ?",
"SELECT COUNT(*) as count FROM channel_sounds WHERE channel_owner_id = ? AND created_by = ?",
- "SELECT COUNT(*) as count FROM emotes WHERE (channel_owner_id = ?) OR (channel_owner_id IS NULL AND user_id = ?)",
- "SELECT COUNT(*) as count FROM emotes WHERE user_id = ?",
"SELECT COUNT(*) as count FROM follows WHERE streamer_id = ?",
"SELECT COUNT(*) as count FROM follows WHERE streamer_id = ?",
"SELECT COUNT(*) as total_streams, SUM(duration_seconds) as total_duration, MAX(peak_viewers) as peak_viewers FROM streams WHERE user_id = ? AND duration_seconds > 0",
"SELECT COUNT(*) as total_streams, SUM(duration_seconds) as total_duration, MAX(peak_viewers) as peak_viewers FROM streams WHERE user_id = ? AND duration_seconds > 0",
"SELECT COUNT(*) as total_streams, SUM(s.duration_seconds) as total_duration, MAX(s.peak_viewers) as all_time_peak, AVG(sa.avg_viewers) as avg_viewers_per_stream, SUM(sa.total_messages) as total_messages, SUM(sa.unique_chatters) as total_unique_chatters, SUM(sa.total_watch_minutes) as total_watch_minutes, SUM(sa.new_followers) as total_new_followers, SUM(sa.clips_created) as total_clips FROM streams s LEFT JOIN stream_analytics sa ON sa.stream_id = s.id WHERE s.user_id = ? AND s.started_at >= ? AND s.duration_seconds > 0",
"SELECT COUNT(*) as total_streams, SUM(s.duration_seconds) as total_duration, MAX(s.peak_viewers) as all_time_peak, AVG(sa.avg_viewers) as avg_viewers_per_stream, SUM(sa.total_messages) as total_messages, SUM(sa.unique_chatters) as total_unique_chatters, SUM(sa.total_watch_minutes) as total_watch_minutes, SUM(sa.new_followers) as total_new_followers, SUM(sa.clips_created) as total_clips FROM streams s LEFT JOIN stream_analytics sa ON sa.stream_id = s.id WHERE s.user_id = ? AND s.started_at >= ? AND s.duration_seconds > 0",
@@ -831,7 +810,6 @@
@@ -831,7 +810,6 @@
"SELECT DISTINCT user_id FROM linked_accounts WHERE service = 'network' AND subject_id = ?",
"SELECT DISTINCT user_id FROM linked_accounts WHERE service = 'network' AND subject_id = ?",
"SELECT MAX(anon_num) as m FROM anon_ip_mappings",
"SELECT MAX(anon_num) as m FROM anon_ip_mappings",
"SELECT MAX(id) AS id FROM chat_messages",
"SELECT MAX(id) AS id FROM chat_messages",
- "SELECT MAX(id) AS m FROM chat_messages",
"SELECT MAX(queue_position) AS max_pos FROM media_requests WHERE streamer_id = ? AND status = 'pending'",
"SELECT MAX(queue_position) AS max_pos FROM media_requests WHERE streamer_id = ? AND status = 'pending'",
"SELECT MIN(timestamp) AS t FROM chat_messages WHERE anon_id = ? AND user_id IS NULL AND is_deleted = 0",
"SELECT MIN(timestamp) AS t FROM chat_messages WHERE anon_id = ? AND user_id IS NULL AND is_deleted = 0",
"SELECT ROUND(AVG(viewer_count), 1) AS a, COUNT(*) AS k FROM viewer_snapshots WHERE stream_id = ?",
"SELECT ROUND(AVG(viewer_count), 1) AS a, COUNT(*) AS k FROM viewer_snapshots WHERE stream_id = ?",
@@ -870,10 +848,7 @@
@@ -870,10 +848,7 @@
"SELECT cm.*, u.avatar_url, u.profile_color, u.role, u.display_name, u.username AS core_username, COALESCE(su.username, cu.username) AS stream_channel, s.is_live AS source_is_live, s.managed_stream_id AS source_managed_id, COALESCE(ms.title, s.title) AS source_stream_title, ms.slug AS source_slug FROM chat_messages cm LEFT JOIN users u ON cm.user_id = u.id LEFT JOIN streams s ON cm.stream_id = s.id LEFT JOIN users su ON s.user_id = su.id LEFT JOIN users cu ON cm.channel_user_id = cu.id LEFT JOIN managed_streams ms ON s.managed_stream_id = ms.id WHERE cm.is_deleted = 0 AND cm.message_type IN ('chat', 'system', 'channel-sound', 'soundboard', 'donation') AND (cm.auto_delete_at IS NULL OR datetime(cm.auto_delete_at) > CURRENT_TIMESTAMP)",
"SELECT cm.*, u.avatar_url, u.profile_color, u.role, u.display_name, u.username AS core_username, COALESCE(su.username, cu.username) AS stream_channel, s.is_live AS source_is_live, s.managed_stream_id AS source_managed_id, COALESCE(ms.title, s.title) AS source_stream_title, ms.slug AS source_slug FROM chat_messages cm LEFT JOIN users u ON cm.user_id = u.id LEFT JOIN streams s ON cm.stream_id = s.id LEFT JOIN users su ON s.user_id = su.id LEFT JOIN users cu ON cm.channel_user_id = cu.id LEFT JOIN managed_streams ms ON s.managed_stream_id = ms.id WHERE cm.is_deleted = 0 AND cm.message_type IN ('chat', 'system', 'channel-sound', 'soundboard', 'donation') AND (cm.auto_delete_at IS NULL OR datetime(cm.auto_delete_at) > CURRENT_TIMESTAMP)",
"SELECT cm.*, u.avatar_url, u.profile_color, u.role, u.display_name, u.username AS core_username, s.title AS source_stream_title, s.managed_stream_id AS source_managed_id, s.is_live AS source_is_live, ms.slug AS source_slug, COALESCE(bu.username, cu.username) AS source_channel FROM chat_messages cm LEFT JOIN users u ON cm.user_id = u.id LEFT JOIN streams s ON cm.stream_id = s.id LEFT JOIN managed_streams ms ON s.managed_stream_id = ms.id LEFT JOIN users bu ON s.user_id = bu.id LEFT JOIN users cu ON cm.channel_user_id = cu.id WHERE cm.channel_user_id = ? AND cm.is_deleted = 0 AND (cm.auto_delete_at IS NULL OR datetime(cm.auto_delete_at) > CURRENT_TIMESTAMP)",
"SELECT cm.*, u.avatar_url, u.profile_color, u.role, u.display_name, u.username AS core_username, s.title AS source_stream_title, s.managed_stream_id AS source_managed_id, s.is_live AS source_is_live, ms.slug AS source_slug, COALESCE(bu.username, cu.username) AS source_channel FROM chat_messages cm LEFT JOIN users u ON cm.user_id = u.id LEFT JOIN streams s ON cm.stream_id = s.id LEFT JOIN managed_streams ms ON s.managed_stream_id = ms.id LEFT JOIN users bu ON s.user_id = bu.id LEFT JOIN users cu ON cm.channel_user_id = cu.id WHERE cm.channel_user_id = ? AND cm.is_deleted = 0 AND (cm.auto_delete_at IS NULL OR datetime(cm.auto_delete_at) > CURRENT_TIMESTAMP)",
"SELECT cm.*, u.display_name, u.username as u_username, u.role, u.avatar_url, u.profile_color FROM chat_messages cm LEFT JOIN users u ON cm.user_id = u.id WHERE cm.is_deleted = 0 AND (cm.auto_delete_at IS NULL OR datetime(cm.auto_delete_at) > CURRENT_TIMESTAMP)",
"SELECT cm.*, u.display_name, u.username as u_username, u.role, u.avatar_url, u.profile_color FROM chat_messages cm LEFT JOIN users u ON cm.user_id = u.id WHERE cm.is_deleted = 0 AND (cm.auto_delete_at IS NULL OR datetime(cm.auto_delete_at) > CURRENT_TIMESTAMP)",
- "SELECT cm.channel_id, c.title, c.user_id, u.username as owner_username FROM channel_moderators cm JOIN channels c ON cm.channel_id = c.id JOIN users u ON c.user_id = u.id WHERE cm.user_id = ?",
- "SELECT cm.id, cm.user_id, cm.added_by, cm.created_at, u.username, u.display_name, u.avatar_url, a.username as added_by_username FROM channel_moderators cm JOIN users u ON cm.user_id = u.id LEFT JOIN users a ON cm.added_by = a.id WHERE cm.channel_id = ? ORDER BY cm.created_at ASC",
"SELECT cm.user_id, cm.username, COUNT(*) as message_count FROM chat_messages cm JOIN streams s ON cm.stream_id = s.id WHERE s.user_id = ? AND cm.timestamp >= ? AND cm.is_deleted = 0 AND cm.is_global = 0 AND cm.message_type = 'chat' AND cm.user_id IS NOT NULL GROUP BY cm.user_id ORDER BY message_count DESC LIMIT 20",
"SELECT cm.user_id, cm.username, COUNT(*) as message_count FROM chat_messages cm JOIN streams s ON cm.stream_id = s.id WHERE s.user_id = ? AND cm.timestamp >= ? AND cm.is_deleted = 0 AND cm.is_global = 0 AND cm.message_type = 'chat' AND cm.user_id IS NOT NULL GROUP BY cm.user_id ORDER BY message_count DESC LIMIT 20",
- "SELECT compared, matched, mismatched, inconclusive, errors, last_mismatch_at, last_mismatch, since FROM chat_dual_read_stats WHERE tbl = ?",
"SELECT consecutive_failures FROM restream_destinations WHERE id = ?",
"SELECT consecutive_failures FROM restream_destinations WHERE id = ?",
"SELECT created_at FROM anon_ip_mappings WHERE anon_num = ?",
"SELECT created_at FROM anon_ip_mappings WHERE anon_num = ?",
"SELECT created_at FROM anon_ip_mappings WHERE ip = ?",
"SELECT created_at FROM anon_ip_mappings WHERE ip = ?",
@@ -885,10 +860,6 @@
@@ -885,10 +860,6 @@
"SELECT default_vod_visibility FROM managed_streams WHERE id = ?",
"SELECT default_vod_visibility FROM managed_streams WHERE id = ?",
"SELECT description FROM stream_memories WHERE user_id = ? ORDER BY captured_at DESC LIMIT 4",
"SELECT description FROM stream_memories WHERE user_id = ? ORDER BY captured_at DESC LIMIT 4",
"SELECT description, category, chat_language FROM channels WHERE user_id = ?",
"SELECT description, category, chat_language FROM channels WHERE user_id = ?",
- "SELECT donation_sound_url, donation_sound_mime, goal_sound_url, goal_sound_mime FROM channel_moderation_settings WHERE channel_id = ?",
- "SELECT e.*, u.username FROM emotes e JOIN users u ON e.user_id = u.id WHERE e.id = ?",
- "SELECT e.*, u.username FROM emotes e JOIN users u ON e.user_id = u.id WHERE e.is_global = 1 AND e.is_approved = 1 ORDER BY code",
- "SELECT e.*, u.username, up.username AS uploader_username, up.display_name AS uploader_display_name FROM emotes e JOIN users u ON e.user_id = u.id LEFT JOIN users up ON e.user_id = up.id WHERE ((e.channel_owner_id = ?) OR (e.channel_owner_id IS NULL AND e.user_id = ?)) AND e.is_approved = 1 ORDER BY code",
"SELECT e.id, e.stream_id, e.vod_id, e.start_sec, e.end_sec, e.text, s.started_at FROM stream_timeline_events e LEFT JOIN streams s ON s.id = e.stream_id WHERE e.user_id = ? AND e.kind = 'speech' AND e.id > ? AND e.created_at >= datetime('now', ?) AND NOT EXISTS (SELECT 1 FROM streams l WHERE l.id = e.stream_id AND l.is_live = 1) ORDER BY e.stream_id, e.start_sec LIMIT 4000",
"SELECT e.id, e.stream_id, e.vod_id, e.start_sec, e.end_sec, e.text, s.started_at FROM stream_timeline_events e LEFT JOIN streams s ON s.id = e.stream_id WHERE e.user_id = ? AND e.kind = 'speech' AND e.id > ? AND e.created_at >= datetime('now', ?) AND NOT EXISTS (SELECT 1 FROM streams l WHERE l.id = e.stream_id AND l.is_live = 1) ORDER BY e.stream_id, e.start_sec LIMIT 4000",
"SELECT enabled FROM news_settings WHERE scope = 'global' AND source_id = '_master'",
"SELECT enabled FROM news_settings WHERE scope = 'global' AND source_id = '_master'",
"SELECT enabled FROM news_settings WHERE scope = 'user' AND scope_id = ? AND source_id = '_master'",
"SELECT enabled FROM news_settings WHERE scope = 'user' AND scope_id = ? AND source_id = '_master'",
@@ -904,7 +875,6 @@
@@ -904,7 +875,6 @@
"SELECT id FROM billing_actions WHERE idempotency_key = ?",
"SELECT id FROM billing_actions WHERE idempotency_key = ?",
"SELECT id FROM channels WHERE user_id = ?",
"SELECT id FROM channels WHERE user_id = ?",
"SELECT id FROM coin_transactions WHERE user_id = ? AND type = 'follow_bonus' AND message LIKE '%streamer:' || ? || '%'",
"SELECT id FROM coin_transactions WHERE user_id = ? AND type = 'follow_bonus' AND message LIKE '%streamer:' || ? || '%'",
- "SELECT id FROM emotes WHERE user_id = ? AND code = ? AND channel_owner_id IS NULL",
"SELECT id FROM follows WHERE follower_id = ? AND streamer_id = ?",
"SELECT id FROM follows WHERE follower_id = ? AND streamer_id = ?",
"SELECT id FROM managed_streams WHERE user_id = ? AND slug = ? COLLATE NOCASE",
"SELECT id FROM managed_streams WHERE user_id = ? AND slug = ? COLLATE NOCASE",
"SELECT id FROM managed_streams WHERE user_id = ? ORDER BY created_at",
"SELECT id FROM managed_streams WHERE user_id = ? ORDER BY created_at",
@@ -995,7 +965,6 @@
@@ -995,7 +965,6 @@
"SELECT powerchat_username FROM powerchat_connections WHERE user_id = ?",
"SELECT powerchat_username FROM powerchat_connections WHERE user_id = ?",
"SELECT r.*, cr.streamer_id FROM coin_redemptions r JOIN coin_rewards cr ON r.reward_id = cr.id WHERE r.id = ?",
"SELECT r.*, cr.streamer_id FROM coin_redemptions r JOIN coin_rewards cr ON r.reward_id = cr.id WHERE r.id = ?",
"SELECT r.*, cr.title as reward_title, cr.cost, cr.icon, cr.color, u.username, u.display_name, u.avatar_url FROM coin_redemptions r JOIN coin_rewards cr ON r.reward_id = cr.id JOIN users u ON r.user_id = u.id WHERE cr.streamer_id = ? AND r.status = 'pending' ORDER BY r.created_at ASC",
"SELECT r.*, cr.title as reward_title, cr.cost, cr.icon, cr.color, u.username, u.display_name, u.avatar_url FROM coin_redemptions r JOIN coin_rewards cr ON r.reward_id = cr.id JOIN users u ON r.user_id = u.id WHERE cr.streamer_id = ? AND r.status = 'pending' ORDER BY r.created_at ASC",
- "SELECT r.rowid AS id, r.platform, r.username, r.display_name, r.message_count, r.last_seen, cs.updated_at AS last_update FROM relay_users r LEFT JOIN chat_ai_summaries cs ON cs.scope = 'relay' AND cs.window = 'rolling' AND cs.subject_id = r.rowid WHERE r.last_seen >= ? AND r.message_count >= ? AND (cs.updated_at IS NULL OR cs.updated_at < r.last_seen) ORDER BY (cs.updated_at IS NULL) DESC, r.last_seen DESC LIMIT ?",
"SELECT r.stream_id FROM stream_recaps r JOIN streams s ON s.id = r.stream_id WHERE r.user_id = ? AND s.started_at >= ? ORDER BY r.created_at DESC LIMIT 1",
"SELECT r.stream_id FROM stream_recaps r JOIN streams s ON s.id = r.stream_id WHERE r.user_id = ? AND s.started_at >= ? ORDER BY r.created_at DESC LIMIT 1",
"SELECT r.stream_id, r.json, r.created_at, u.username, u.display_name, u.avatar_url, u.profile_color FROM stream_recaps r JOIN users u ON u.id = r.user_id WHERE (? IS NULL OR r.user_id != ?) AND COALESCE(u.is_banned, 0) = 0 ORDER BY r.created_at DESC LIMIT ?",
"SELECT r.stream_id, r.json, r.created_at, u.username, u.display_name, u.avatar_url, u.profile_color FROM stream_recaps r JOIN users u ON u.id = r.user_id WHERE (? IS NULL OR r.user_id != ?) AND COALESCE(u.is_banned, 0) = 0 ORDER BY r.created_at DESC LIMIT ?",
"SELECT r.stream_id, r.user_id, r.json, r.created_at FROM stream_recaps r JOIN users u ON u.id = r.user_id WHERE r.ai = 1 AND COALESCE(u.is_banned, 0) = 0 ORDER BY r.created_at DESC, r.stream_id DESC LIMIT ? OFFSET ?",
"SELECT r.stream_id, r.user_id, r.json, r.created_at FROM stream_recaps r JOIN users u ON u.id = r.user_id WHERE r.ai = 1 AND COALESCE(u.is_banned, 0) = 0 ORDER BY r.created_at DESC, r.stream_id DESC LIMIT ? OFFSET ?",
@@ -1029,8 +998,6 @@
@@ -1029,8 +998,6 @@
"SELECT s.id, s.user_id, s.started_at FROM streams s WHERE s.is_live = 1 AND EXISTS (SELECT 1 FROM stream_timeline_events e WHERE e.stream_id = s.id AND e.kind = 'speech' AND e.created_at >= datetime('now', '-30 minutes'))",
"SELECT s.id, s.user_id, s.started_at FROM streams s WHERE s.is_live = 1 AND EXISTS (SELECT 1 FROM stream_timeline_events e WHERE e.stream_id = s.id AND e.kind = 'speech' AND e.created_at >= datetime('now', '-30 minutes'))",
"SELECT s.id, s.user_id, s.title, s.category, s.protocol, s.is_nsfw, s.started_at, s.ended_at, s.duration_seconds, s.managed_stream_id, u.username, u.display_name FROM streams s JOIN users u ON u.id = s.user_id WHERE s.id = ?",
"SELECT s.id, s.user_id, s.title, s.category, s.protocol, s.is_nsfw, s.started_at, s.ended_at, s.duration_seconds, s.managed_stream_id, u.username, u.display_name FROM streams s JOIN users u ON u.id = s.user_id WHERE s.id = ?",
"SELECT s.id, u.stream_key FROM streams s JOIN users u ON s.user_id = u.id WHERE s.is_live = 1 AND s.protocol = 'jsmpeg'",
"SELECT s.id, u.stream_key FROM streams s JOIN users u ON s.user_id = u.id WHERE s.is_live = 1 AND s.protocol = 'jsmpeg'",
- "SELECT seq, tbl, op, pk FROM chat_staged_outbox ORDER BY seq LIMIT ?",
- "SELECT seq, tbl, op, pk FROM chat_staged_outbox WHERE tbl = ? ORDER BY seq LIMIT ?",
"SELECT service_user_id FROM linked_accounts WHERE service = 'network' AND user_id = ?",
"SELECT service_user_id FROM linked_accounts WHERE service = 'network' AND user_id = ?",
"SELECT session_id, managed_stream_id, stream_id, state, confirmed_at FROM openre_sessions WHERE state = 'live'",
"SELECT session_id, managed_stream_id, stream_id, state, confirmed_at FROM openre_sessions WHERE state = 'live'",
"SELECT slot, item_id FROM user_equipped WHERE user_id = ?",
"SELECT slot, item_id FROM user_equipped WHERE user_id = ?",
@@ -1142,8 +1109,6 @@
@@ -1142,8 +1109,6 @@
"UPDATE billing_actions SET status = ?, http_status = ?, error = ?, updated_at = CURRENT_TIMESTAMP WHERE id = ?",
"UPDATE billing_actions SET status = ?, http_status = ?, error = ?, updated_at = CURRENT_TIMESTAMP WHERE id = ?",
"UPDATE camera_profiles SET name = ?, onvif_url = ?, username = ?, password_hash = ?, pan_speed = ?, tilt_speed = ?, zoom_speed = ?, is_active = ?, last_connected = ?, updated_at = CURRENT_TIMESTAMP WHERE id = ?",
"UPDATE camera_profiles SET name = ?, onvif_url = ?, username = ?, password_hash = ?, pan_speed = ?, tilt_speed = ?, zoom_speed = ?, is_active = ?, last_connected = ?, updated_at = CURRENT_TIMESTAMP WHERE id = ?",
"UPDATE channel_ai_bots SET msg_count = msg_count + 1, last_active_at = CURRENT_TIMESTAMP WHERE id = ?",
"UPDATE channel_ai_bots SET msg_count = msg_count + 1, last_active_at = CURRENT_TIMESTAMP WHERE id = ?",
- "UPDATE channel_moderation_settings SET sub_only = ? WHERE channel_id = ?",
- "UPDATE channel_moderation_settings SET tts_max_length = ? WHERE channel_id = ?",
"UPDATE channel_points SET balance = balance + ?, updated_at = CURRENT_TIMESTAMP WHERE user_id = ? AND streamer_id = ?",
"UPDATE channel_points SET balance = balance + ?, updated_at = CURRENT_TIMESTAMP WHERE user_id = ? AND streamer_id = ?",
"UPDATE channel_points SET balance = balance + ?, updated_at = CURRENT_TIMESTAMP WHERE user_id = ? AND streamer_id = ? AND balance >= ?",
"UPDATE channel_points SET balance = balance + ?, updated_at = CURRENT_TIMESTAMP WHERE user_id = ? AND streamer_id = ? AND balance >= ?",
"UPDATE channel_sounds SET command = ? WHERE channel_owner_id = ? AND command = ?",
"UPDATE channel_sounds SET command = ? WHERE channel_owner_id = ? AND command = ?",
@@ -1152,7 +1117,6 @@
@@ -1152,7 +1117,6 @@
"UPDATE channels SET ai_category = ? WHERE user_id = ?",
"UPDATE channels SET ai_category = ? WHERE user_id = ?",
"UPDATE channels SET ai_overview_pref = 'hide' WHERE hide_ai_overview = 1 AND (ai_overview_pref IS NULL OR ai_overview_pref = 'auto')",
"UPDATE channels SET ai_overview_pref = 'hide' WHERE hide_ai_overview = 1 AND (ai_overview_pref IS NULL OR ai_overview_pref = 'auto')",
"UPDATE channels SET clips_allow_creator_delete = ? WHERE id = ?",
"UPDATE channels SET clips_allow_creator_delete = ? WHERE id = ?",
- "UPDATE chat_dual_read_stats SET last_mismatch_at = CURRENT_TIMESTAMP, last_mismatch = ? WHERE tbl = ?",
"UPDATE chat_messages SET channel_user_id = (SELECT s.user_id FROM streams s WHERE s.id = chat_messages.stream_id) WHERE stream_id IS NOT NULL AND channel_user_id IS NULL",
"UPDATE chat_messages SET channel_user_id = (SELECT s.user_id FROM streams s WHERE s.id = chat_messages.stream_id) WHERE stream_id IS NOT NULL AND channel_user_id IS NULL",
"UPDATE chat_messages SET is_deleted = 1, deleted_by = ?, deleted_at = CURRENT_TIMESTAMP WHERE id = ?",
"UPDATE chat_messages SET is_deleted = 1, deleted_by = ?, deleted_at = CURRENT_TIMESTAMP WHERE id = ?",
"UPDATE chat_messages SET is_deleted = 1, deleted_by = ?, deleted_at = CURRENT_TIMESTAMP WHERE is_global = 1 AND timestamp >= datetime(?) AND timestamp <= datetime(?) AND is_deleted = 0",
"UPDATE chat_messages SET is_deleted = 1, deleted_by = ?, deleted_at = CURRENT_TIMESTAMP WHERE is_global = 1 AND timestamp >= datetime(?) AND timestamp <= datetime(?) AND is_deleted = 0",