diff --git a/infra/docker/Dockerfile.discord-gateway b/infra/docker/Dockerfile.discord-gateway index b970789..c18e8db 100644 --- a/infra/docker/Dockerfile.discord-gateway +++ b/infra/docker/Dockerfile.discord-gateway @@ -16,6 +16,9 @@ COPY vendor/discord.js-selfbot-v13 ./vendor/discord.js-selfbot-v13 # Copy service COPY services/discord-gateway ./services/discord-gateway +# Copy Drizzle migrations (relative path used by migrator) +COPY services/discord-gateway/drizzle ./drizzle + # Install dependencies RUN pnpm install --frozen-lockfile diff --git a/services/discord-gateway/drizzle.config.ts b/services/discord-gateway/drizzle.config.ts new file mode 100644 index 0000000..1585f0d --- /dev/null +++ b/services/discord-gateway/drizzle.config.ts @@ -0,0 +1,10 @@ +import { defineConfig } from "drizzle-kit"; + +export default defineConfig({ + schema: "./src/shared/database/schema.ts", + out: "./drizzle/migrations", + dialect: "postgresql", + dbCredentials: { + url: process.env.DATABASE_URL || "postgresql://postgres:postgres@localhost:5432/bete", + }, +}); diff --git a/services/discord-gateway/drizzle/migrations/0000_tricky_mysterio.sql b/services/discord-gateway/drizzle/migrations/0000_tricky_mysterio.sql new file mode 100644 index 0000000..e67b19e --- /dev/null +++ b/services/discord-gateway/drizzle/migrations/0000_tricky_mysterio.sql @@ -0,0 +1,176 @@ +CREATE TABLE "ai_analysis_runs" ( + "id" text PRIMARY KEY NOT NULL, + "conversation_key" text NOT NULL, + "target_message_ids" text NOT NULL, + "model" text NOT NULL, + "request_tokens_estimate" integer, + "response_raw" text, + "status" text DEFAULT 'pending' NOT NULL, + "error" text, + "created_at" bigint NOT NULL, + "completed_at" bigint +); +--> statement-breakpoint +CREATE TABLE "attachments" ( + "id" text PRIMARY KEY NOT NULL, + "message_id" text NOT NULL, + "guild_id" text NOT NULL, + "channel_id" text NOT NULL, + "thread_id" text, + "user_id" text NOT NULL, + "filename" text NOT NULL, + "size" integer NOT NULL, + "type" text NOT NULL, + "discord_url" text NOT NULL, + "uploaded_url" text, + "upload_status" text DEFAULT 'pending' NOT NULL, + "upload_error" text, + "created_at" bigint NOT NULL, + "uploaded_at" bigint +); +--> statement-breakpoint +CREATE TABLE "message_reviews" ( + "id" text PRIMARY KEY NOT NULL, + "message_id" text NOT NULL, + "guild_id" text NOT NULL, + "channel_id" text NOT NULL, + "reviewer_id" text, + "status" text DEFAULT 'pending' NOT NULL, + "notes" text, + "created_at" bigint NOT NULL, + "reviewed_at" bigint +); +--> statement-breakpoint +CREATE TABLE "messages" ( + "id" text PRIMARY KEY NOT NULL, + "guild_id" text NOT NULL, + "channel_id" text NOT NULL, + "thread_id" text, + "user_id" text NOT NULL, + "username" text NOT NULL, + "avatar_url" text, + "content" text NOT NULL, + "edited_content" text, + "created_at" bigint NOT NULL, + "edited_at" bigint, + "deleted_at" bigint, + "type" text DEFAULT 'text' NOT NULL, + "metadata" text, + "ai_status" text DEFAULT 'pending' NOT NULL, + "ai_moderation_flags" text, + "ai_moderation_score" real, + "ai_analysis" text, + "ai_categories" text, + "ai_severity" text, + "ai_confidence" real, + "ai_recommended_action" text, + "ai_analyzed_at" bigint, + "ai_error" text +); +--> statement-breakpoint +CREATE TABLE "moderation_actions" ( + "id" text PRIMARY KEY NOT NULL, + "message_id" text, + "user_id" text, + "guild_id" text NOT NULL, + "action_type" text NOT NULL, + "reason" text, + "executed_by" text, + "status" text DEFAULT 'pending' NOT NULL, + "error" text, + "created_at" bigint NOT NULL, + "executed_at" bigint +); +--> statement-breakpoint +CREATE TABLE "muxer_jobs" ( + "id" text PRIMARY KEY NOT NULL, + "data" text NOT NULL, + "status" text DEFAULT 'pending' NOT NULL, + "attempts" integer DEFAULT 0 NOT NULL, + "maxAttempts" integer DEFAULT 3 NOT NULL, + "createdAt" bigint NOT NULL, + "updatedAt" bigint NOT NULL, + "error" text +); +--> statement-breakpoint +CREATE TABLE "retention_policies" ( + "id" text PRIMARY KEY NOT NULL, + "guild_id" text NOT NULL, + "channel_id" text, + "retention_days" integer DEFAULT 90 NOT NULL, + "apply_to_media" boolean DEFAULT true NOT NULL, + "apply_to_voice" boolean DEFAULT true NOT NULL, + "enabled" boolean DEFAULT true NOT NULL, + "created_at" bigint NOT NULL, + "updated_at" bigint NOT NULL +); +--> statement-breakpoint +CREATE TABLE "text_analysis_cache" ( + "text" text PRIMARY KEY NOT NULL, + "flags" text DEFAULT '[]' NOT NULL, + "source" text DEFAULT 'local' NOT NULL, + "analyzed_at" bigint NOT NULL, + "expires_at" bigint NOT NULL, + "hit_count" integer DEFAULT 0 NOT NULL +); +--> statement-breakpoint +CREATE TABLE "ui_state" ( + "key" text PRIMARY KEY NOT NULL, + "value" text NOT NULL, + "updated_at" bigint NOT NULL +); +--> statement-breakpoint +CREATE TABLE "voice_recordings" ( + "id" text PRIMARY KEY NOT NULL, + "user_id" text NOT NULL, + "username" text NOT NULL, + "avatar_url" text, + "guild_id" text, + "channel_id" text, + "channel_name" text, + "filename" text NOT NULL, + "size_bytes" integer NOT NULL, + "download_url" text, + "upload_status" text DEFAULT 'pending' NOT NULL, + "upload_error" text, + "created_at" bigint NOT NULL, + "uploaded_at" bigint +); +--> statement-breakpoint +ALTER TABLE "attachments" ADD CONSTRAINT "fk_attachments_message_id" FOREIGN KEY ("message_id") REFERENCES "public"."messages"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint +CREATE INDEX "idx_ai_analysis_runs_conversation_key" ON "ai_analysis_runs" USING btree ("conversation_key");--> statement-breakpoint +CREATE INDEX "idx_ai_analysis_runs_status" ON "ai_analysis_runs" USING btree ("status");--> statement-breakpoint +CREATE INDEX "idx_ai_analysis_runs_created_at" ON "ai_analysis_runs" USING btree ("created_at");--> statement-breakpoint +CREATE INDEX "idx_attachments_channel" ON "attachments" USING btree ("channel_id");--> statement-breakpoint +CREATE INDEX "idx_attachments_message" ON "attachments" USING btree ("message_id");--> statement-breakpoint +CREATE INDEX "idx_attachments_status" ON "attachments" USING btree ("upload_status");--> statement-breakpoint +CREATE INDEX "idx_attachments_channel_created" ON "attachments" USING btree ("channel_id","created_at","id");--> statement-breakpoint +CREATE INDEX "idx_attachments_thread_created" ON "attachments" USING btree ("thread_id","created_at","id");--> statement-breakpoint +CREATE INDEX "idx_message_reviews_message_id" ON "message_reviews" USING btree ("message_id");--> statement-breakpoint +CREATE INDEX "idx_message_reviews_status" ON "message_reviews" USING btree ("status");--> statement-breakpoint +CREATE INDEX "idx_message_reviews_created_at" ON "message_reviews" USING btree ("created_at");--> statement-breakpoint +CREATE INDEX "idx_message_reviews_guild_status" ON "message_reviews" USING btree ("guild_id","status","created_at");--> statement-breakpoint +CREATE INDEX "idx_messages_channel" ON "messages" USING btree ("channel_id");--> statement-breakpoint +CREATE INDEX "idx_messages_user" ON "messages" USING btree ("user_id");--> statement-breakpoint +CREATE INDEX "idx_messages_created" ON "messages" USING btree ("created_at");--> statement-breakpoint +CREATE INDEX "idx_messages_thread" ON "messages" USING btree ("thread_id");--> statement-breakpoint +CREATE INDEX "idx_messages_channel_created" ON "messages" USING btree ("channel_id","created_at","id");--> statement-breakpoint +CREATE INDEX "idx_messages_thread_created" ON "messages" USING btree ("thread_id","created_at","id");--> statement-breakpoint +CREATE INDEX "idx_messages_ai_status_created" ON "messages" USING btree ("ai_status","created_at","id");--> statement-breakpoint +CREATE INDEX "idx_messages_guild_ai_status_created" ON "messages" USING btree ("guild_id","ai_status","created_at","id");--> statement-breakpoint +CREATE INDEX "idx_messages_guild_created_deleted" ON "messages" USING btree ("guild_id","created_at","deleted_at","id");--> statement-breakpoint +CREATE INDEX "idx_messages_channel_ai_status_created" ON "messages" USING btree ("channel_id","ai_status","created_at","id");--> statement-breakpoint +CREATE INDEX "idx_messages_thread_ai_status_created" ON "messages" USING btree ("thread_id","ai_status","created_at","id");--> statement-breakpoint +CREATE INDEX "idx_moderation_actions_message_id" ON "moderation_actions" USING btree ("message_id");--> statement-breakpoint +CREATE INDEX "idx_moderation_actions_user_id" ON "moderation_actions" USING btree ("user_id");--> statement-breakpoint +CREATE INDEX "idx_moderation_actions_status" ON "moderation_actions" USING btree ("status");--> statement-breakpoint +CREATE INDEX "idx_moderation_actions_guild_status" ON "moderation_actions" USING btree ("guild_id","status","created_at");--> statement-breakpoint +CREATE INDEX "idx_muxer_jobs_status" ON "muxer_jobs" USING btree ("status");--> statement-breakpoint +CREATE INDEX "idx_muxer_jobs_createdAt" ON "muxer_jobs" USING btree ("createdAt");--> statement-breakpoint +CREATE INDEX "idx_retention_policies_guild_id" ON "retention_policies" USING btree ("guild_id");--> statement-breakpoint +CREATE INDEX "idx_retention_policies_enabled" ON "retention_policies" USING btree ("enabled");--> statement-breakpoint +CREATE INDEX "idx_text_analysis_cache_expires_at" ON "text_analysis_cache" USING btree ("expires_at");--> statement-breakpoint +CREATE INDEX "idx_text_analysis_cache_source" ON "text_analysis_cache" USING btree ("source");--> statement-breakpoint +CREATE INDEX "idx_voice_recordings_user_id" ON "voice_recordings" USING btree ("user_id");--> statement-breakpoint +CREATE INDEX "idx_voice_recordings_channel_id" ON "voice_recordings" USING btree ("channel_id");--> statement-breakpoint +CREATE INDEX "idx_voice_recordings_created_at" ON "voice_recordings" USING btree ("created_at"); \ No newline at end of file diff --git a/services/discord-gateway/drizzle/migrations/meta/0000_snapshot.json b/services/discord-gateway/drizzle/migrations/meta/0000_snapshot.json new file mode 100644 index 0000000..3c7644e --- /dev/null +++ b/services/discord-gateway/drizzle/migrations/meta/0000_snapshot.json @@ -0,0 +1,1539 @@ +{ + "id": "6d3a997f-5cf4-4a45-91fc-f70ada241c61", + "prevId": "00000000-0000-0000-0000-000000000000", + "version": "7", + "dialect": "postgresql", + "tables": { + "public.ai_analysis_runs": { + "name": "ai_analysis_runs", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "conversation_key": { + "name": "conversation_key", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "target_message_ids": { + "name": "target_message_ids", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "model": { + "name": "model", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "request_tokens_estimate": { + "name": "request_tokens_estimate", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "response_raw": { + "name": "response_raw", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "status": { + "name": "status", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'pending'" + }, + "error": { + "name": "error", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "bigint", + "primaryKey": false, + "notNull": true + }, + "completed_at": { + "name": "completed_at", + "type": "bigint", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "idx_ai_analysis_runs_conversation_key": { + "name": "idx_ai_analysis_runs_conversation_key", + "columns": [ + { + "expression": "conversation_key", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_ai_analysis_runs_status": { + "name": "idx_ai_analysis_runs_status", + "columns": [ + { + "expression": "status", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_ai_analysis_runs_created_at": { + "name": "idx_ai_analysis_runs_created_at", + "columns": [ + { + "expression": "created_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.attachments": { + "name": "attachments", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "message_id": { + "name": "message_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "guild_id": { + "name": "guild_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "channel_id": { + "name": "channel_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "thread_id": { + "name": "thread_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "filename": { + "name": "filename", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "size": { + "name": "size", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "type": { + "name": "type", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "discord_url": { + "name": "discord_url", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "uploaded_url": { + "name": "uploaded_url", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "upload_status": { + "name": "upload_status", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'pending'" + }, + "upload_error": { + "name": "upload_error", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "bigint", + "primaryKey": false, + "notNull": true + }, + "uploaded_at": { + "name": "uploaded_at", + "type": "bigint", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "idx_attachments_channel": { + "name": "idx_attachments_channel", + "columns": [ + { + "expression": "channel_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_attachments_message": { + "name": "idx_attachments_message", + "columns": [ + { + "expression": "message_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_attachments_status": { + "name": "idx_attachments_status", + "columns": [ + { + "expression": "upload_status", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_attachments_channel_created": { + "name": "idx_attachments_channel_created", + "columns": [ + { + "expression": "channel_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "created_at", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_attachments_thread_created": { + "name": "idx_attachments_thread_created", + "columns": [ + { + "expression": "thread_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "created_at", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "fk_attachments_message_id": { + "name": "fk_attachments_message_id", + "tableFrom": "attachments", + "tableTo": "messages", + "columnsFrom": [ + "message_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.message_reviews": { + "name": "message_reviews", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "message_id": { + "name": "message_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "guild_id": { + "name": "guild_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "channel_id": { + "name": "channel_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "reviewer_id": { + "name": "reviewer_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "status": { + "name": "status", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'pending'" + }, + "notes": { + "name": "notes", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "bigint", + "primaryKey": false, + "notNull": true + }, + "reviewed_at": { + "name": "reviewed_at", + "type": "bigint", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "idx_message_reviews_message_id": { + "name": "idx_message_reviews_message_id", + "columns": [ + { + "expression": "message_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_message_reviews_status": { + "name": "idx_message_reviews_status", + "columns": [ + { + "expression": "status", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_message_reviews_created_at": { + "name": "idx_message_reviews_created_at", + "columns": [ + { + "expression": "created_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_message_reviews_guild_status": { + "name": "idx_message_reviews_guild_status", + "columns": [ + { + "expression": "guild_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "status", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "created_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.messages": { + "name": "messages", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "guild_id": { + "name": "guild_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "channel_id": { + "name": "channel_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "thread_id": { + "name": "thread_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "username": { + "name": "username", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "avatar_url": { + "name": "avatar_url", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "content": { + "name": "content", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "edited_content": { + "name": "edited_content", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "bigint", + "primaryKey": false, + "notNull": true + }, + "edited_at": { + "name": "edited_at", + "type": "bigint", + "primaryKey": false, + "notNull": false + }, + "deleted_at": { + "name": "deleted_at", + "type": "bigint", + "primaryKey": false, + "notNull": false + }, + "type": { + "name": "type", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'text'" + }, + "metadata": { + "name": "metadata", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "ai_status": { + "name": "ai_status", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'pending'" + }, + "ai_moderation_flags": { + "name": "ai_moderation_flags", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "ai_moderation_score": { + "name": "ai_moderation_score", + "type": "real", + "primaryKey": false, + "notNull": false + }, + "ai_analysis": { + "name": "ai_analysis", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "ai_categories": { + "name": "ai_categories", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "ai_severity": { + "name": "ai_severity", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "ai_confidence": { + "name": "ai_confidence", + "type": "real", + "primaryKey": false, + "notNull": false + }, + "ai_recommended_action": { + "name": "ai_recommended_action", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "ai_analyzed_at": { + "name": "ai_analyzed_at", + "type": "bigint", + "primaryKey": false, + "notNull": false + }, + "ai_error": { + "name": "ai_error", + "type": "text", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "idx_messages_channel": { + "name": "idx_messages_channel", + "columns": [ + { + "expression": "channel_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_messages_user": { + "name": "idx_messages_user", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_messages_created": { + "name": "idx_messages_created", + "columns": [ + { + "expression": "created_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_messages_thread": { + "name": "idx_messages_thread", + "columns": [ + { + "expression": "thread_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_messages_channel_created": { + "name": "idx_messages_channel_created", + "columns": [ + { + "expression": "channel_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "created_at", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_messages_thread_created": { + "name": "idx_messages_thread_created", + "columns": [ + { + "expression": "thread_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "created_at", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_messages_ai_status_created": { + "name": "idx_messages_ai_status_created", + "columns": [ + { + "expression": "ai_status", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "created_at", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_messages_guild_ai_status_created": { + "name": "idx_messages_guild_ai_status_created", + "columns": [ + { + "expression": "guild_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "ai_status", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "created_at", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_messages_guild_created_deleted": { + "name": "idx_messages_guild_created_deleted", + "columns": [ + { + "expression": "guild_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "created_at", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "deleted_at", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_messages_channel_ai_status_created": { + "name": "idx_messages_channel_ai_status_created", + "columns": [ + { + "expression": "channel_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "ai_status", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "created_at", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_messages_thread_ai_status_created": { + "name": "idx_messages_thread_ai_status_created", + "columns": [ + { + "expression": "thread_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "ai_status", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "created_at", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.moderation_actions": { + "name": "moderation_actions", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "message_id": { + "name": "message_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "guild_id": { + "name": "guild_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "action_type": { + "name": "action_type", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "reason": { + "name": "reason", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "executed_by": { + "name": "executed_by", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "status": { + "name": "status", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'pending'" + }, + "error": { + "name": "error", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "bigint", + "primaryKey": false, + "notNull": true + }, + "executed_at": { + "name": "executed_at", + "type": "bigint", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "idx_moderation_actions_message_id": { + "name": "idx_moderation_actions_message_id", + "columns": [ + { + "expression": "message_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_moderation_actions_user_id": { + "name": "idx_moderation_actions_user_id", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_moderation_actions_status": { + "name": "idx_moderation_actions_status", + "columns": [ + { + "expression": "status", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_moderation_actions_guild_status": { + "name": "idx_moderation_actions_guild_status", + "columns": [ + { + "expression": "guild_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "status", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "created_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.muxer_jobs": { + "name": "muxer_jobs", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "data": { + "name": "data", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "status": { + "name": "status", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'pending'" + }, + "attempts": { + "name": "attempts", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "maxAttempts": { + "name": "maxAttempts", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 3 + }, + "createdAt": { + "name": "createdAt", + "type": "bigint", + "primaryKey": false, + "notNull": true + }, + "updatedAt": { + "name": "updatedAt", + "type": "bigint", + "primaryKey": false, + "notNull": true + }, + "error": { + "name": "error", + "type": "text", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "idx_muxer_jobs_status": { + "name": "idx_muxer_jobs_status", + "columns": [ + { + "expression": "status", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_muxer_jobs_createdAt": { + "name": "idx_muxer_jobs_createdAt", + "columns": [ + { + "expression": "createdAt", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.retention_policies": { + "name": "retention_policies", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "guild_id": { + "name": "guild_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "channel_id": { + "name": "channel_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "retention_days": { + "name": "retention_days", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 90 + }, + "apply_to_media": { + "name": "apply_to_media", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": true + }, + "apply_to_voice": { + "name": "apply_to_voice", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": true + }, + "enabled": { + "name": "enabled", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": true + }, + "created_at": { + "name": "created_at", + "type": "bigint", + "primaryKey": false, + "notNull": true + }, + "updated_at": { + "name": "updated_at", + "type": "bigint", + "primaryKey": false, + "notNull": true + } + }, + "indexes": { + "idx_retention_policies_guild_id": { + "name": "idx_retention_policies_guild_id", + "columns": [ + { + "expression": "guild_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_retention_policies_enabled": { + "name": "idx_retention_policies_enabled", + "columns": [ + { + "expression": "enabled", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.text_analysis_cache": { + "name": "text_analysis_cache", + "schema": "", + "columns": { + "text": { + "name": "text", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "flags": { + "name": "flags", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'[]'" + }, + "source": { + "name": "source", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'local'" + }, + "analyzed_at": { + "name": "analyzed_at", + "type": "bigint", + "primaryKey": false, + "notNull": true + }, + "expires_at": { + "name": "expires_at", + "type": "bigint", + "primaryKey": false, + "notNull": true + }, + "hit_count": { + "name": "hit_count", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + } + }, + "indexes": { + "idx_text_analysis_cache_expires_at": { + "name": "idx_text_analysis_cache_expires_at", + "columns": [ + { + "expression": "expires_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_text_analysis_cache_source": { + "name": "idx_text_analysis_cache_source", + "columns": [ + { + "expression": "source", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.ui_state": { + "name": "ui_state", + "schema": "", + "columns": { + "key": { + "name": "key", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "value": { + "name": "value", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "updated_at": { + "name": "updated_at", + "type": "bigint", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.voice_recordings": { + "name": "voice_recordings", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "username": { + "name": "username", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "avatar_url": { + "name": "avatar_url", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "guild_id": { + "name": "guild_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "channel_id": { + "name": "channel_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "channel_name": { + "name": "channel_name", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "filename": { + "name": "filename", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "size_bytes": { + "name": "size_bytes", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "download_url": { + "name": "download_url", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "upload_status": { + "name": "upload_status", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'pending'" + }, + "upload_error": { + "name": "upload_error", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "bigint", + "primaryKey": false, + "notNull": true + }, + "uploaded_at": { + "name": "uploaded_at", + "type": "bigint", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "idx_voice_recordings_user_id": { + "name": "idx_voice_recordings_user_id", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_voice_recordings_channel_id": { + "name": "idx_voice_recordings_channel_id", + "columns": [ + { + "expression": "channel_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_voice_recordings_created_at": { + "name": "idx_voice_recordings_created_at", + "columns": [ + { + "expression": "created_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + } + }, + "enums": {}, + "schemas": {}, + "sequences": {}, + "roles": {}, + "policies": {}, + "views": {}, + "_meta": { + "columns": {}, + "schemas": {}, + "tables": {} + } +} \ No newline at end of file diff --git a/services/discord-gateway/drizzle/migrations/meta/_journal.json b/services/discord-gateway/drizzle/migrations/meta/_journal.json new file mode 100644 index 0000000..3b9162b --- /dev/null +++ b/services/discord-gateway/drizzle/migrations/meta/_journal.json @@ -0,0 +1,13 @@ +{ + "version": "7", + "dialect": "postgresql", + "entries": [ + { + "idx": 0, + "version": "7", + "when": 1780329073891, + "tag": "0000_tricky_mysterio", + "breakpoints": true + } + ] +} \ No newline at end of file