- Fix scalar_first() bug in persistent_conversation.py (use scalars().first()) - Add schema.sql with all 7 tables (users, user_preferences, user_facts, guilds, guild_members, conversations, messages) - Update database.py to run schema.sql on startup - Remove Alembic directory and configuration - Remove alembic from requirements.txt
120 lines
4.4 KiB
SQL
120 lines
4.4 KiB
SQL
-- Daemon Boyfriend Database Schema
|
|
-- Run with: psql -U postgres -d daemon_boyfriend -f schema.sql
|
|
|
|
-- Users table
|
|
CREATE TABLE IF NOT EXISTS users (
|
|
id BIGSERIAL PRIMARY KEY,
|
|
discord_id BIGINT NOT NULL UNIQUE,
|
|
discord_username VARCHAR(255) NOT NULL,
|
|
discord_display_name VARCHAR(255),
|
|
custom_name VARCHAR(255),
|
|
first_seen_at TIMESTAMPTZ DEFAULT NOW(),
|
|
last_seen_at TIMESTAMPTZ DEFAULT NOW(),
|
|
is_active BOOLEAN NOT NULL DEFAULT TRUE,
|
|
created_at TIMESTAMPTZ DEFAULT NOW(),
|
|
updated_at TIMESTAMPTZ DEFAULT NOW()
|
|
);
|
|
|
|
CREATE INDEX IF NOT EXISTS ix_users_discord_id ON users(discord_id);
|
|
CREATE INDEX IF NOT EXISTS ix_users_last_seen_at ON users(last_seen_at);
|
|
|
|
-- User preferences table
|
|
CREATE TABLE IF NOT EXISTS user_preferences (
|
|
id BIGSERIAL PRIMARY KEY,
|
|
user_id BIGINT NOT NULL REFERENCES users(id) ON DELETE CASCADE,
|
|
preference_key VARCHAR(100) NOT NULL,
|
|
preference_value TEXT,
|
|
created_at TIMESTAMPTZ DEFAULT NOW(),
|
|
updated_at TIMESTAMPTZ DEFAULT NOW(),
|
|
UNIQUE(user_id, preference_key)
|
|
);
|
|
|
|
CREATE INDEX IF NOT EXISTS ix_user_preferences_user_id ON user_preferences(user_id);
|
|
|
|
-- User facts table
|
|
CREATE TABLE IF NOT EXISTS user_facts (
|
|
id BIGSERIAL PRIMARY KEY,
|
|
user_id BIGINT NOT NULL REFERENCES users(id) ON DELETE CASCADE,
|
|
fact_type VARCHAR(50) NOT NULL,
|
|
fact_content TEXT NOT NULL,
|
|
confidence FLOAT DEFAULT 1.0,
|
|
source VARCHAR(50) DEFAULT 'conversation',
|
|
is_active BOOLEAN NOT NULL DEFAULT TRUE,
|
|
learned_at TIMESTAMPTZ DEFAULT NOW(),
|
|
last_referenced_at TIMESTAMPTZ,
|
|
created_at TIMESTAMPTZ DEFAULT NOW(),
|
|
updated_at TIMESTAMPTZ DEFAULT NOW()
|
|
);
|
|
|
|
CREATE INDEX IF NOT EXISTS ix_user_facts_user_id ON user_facts(user_id);
|
|
CREATE INDEX IF NOT EXISTS ix_user_facts_fact_type ON user_facts(fact_type);
|
|
CREATE INDEX IF NOT EXISTS ix_user_facts_is_active ON user_facts(is_active);
|
|
|
|
-- Guilds table
|
|
CREATE TABLE IF NOT EXISTS guilds (
|
|
id BIGSERIAL PRIMARY KEY,
|
|
discord_id BIGINT NOT NULL UNIQUE,
|
|
name VARCHAR(255) NOT NULL,
|
|
joined_at TIMESTAMPTZ DEFAULT NOW(),
|
|
is_active BOOLEAN NOT NULL DEFAULT TRUE,
|
|
settings JSONB DEFAULT '{}',
|
|
created_at TIMESTAMPTZ DEFAULT NOW(),
|
|
updated_at TIMESTAMPTZ DEFAULT NOW()
|
|
);
|
|
|
|
CREATE INDEX IF NOT EXISTS ix_guilds_discord_id ON guilds(discord_id);
|
|
|
|
-- Guild members table
|
|
CREATE TABLE IF NOT EXISTS guild_members (
|
|
id BIGSERIAL PRIMARY KEY,
|
|
guild_id BIGINT NOT NULL REFERENCES guilds(id) ON DELETE CASCADE,
|
|
user_id BIGINT NOT NULL REFERENCES users(id) ON DELETE CASCADE,
|
|
guild_nickname VARCHAR(255),
|
|
roles TEXT[],
|
|
joined_guild_at TIMESTAMPTZ,
|
|
created_at TIMESTAMPTZ DEFAULT NOW(),
|
|
updated_at TIMESTAMPTZ DEFAULT NOW(),
|
|
UNIQUE(guild_id, user_id)
|
|
);
|
|
|
|
CREATE INDEX IF NOT EXISTS ix_guild_members_guild_id ON guild_members(guild_id);
|
|
CREATE INDEX IF NOT EXISTS ix_guild_members_user_id ON guild_members(user_id);
|
|
|
|
-- Conversations table
|
|
CREATE TABLE IF NOT EXISTS conversations (
|
|
id BIGSERIAL PRIMARY KEY,
|
|
user_id BIGINT NOT NULL REFERENCES users(id) ON DELETE CASCADE,
|
|
guild_id BIGINT,
|
|
channel_id BIGINT,
|
|
started_at TIMESTAMPTZ DEFAULT NOW(),
|
|
last_message_at TIMESTAMPTZ DEFAULT NOW(),
|
|
message_count INTEGER DEFAULT 0,
|
|
is_active BOOLEAN NOT NULL DEFAULT TRUE,
|
|
created_at TIMESTAMPTZ DEFAULT NOW(),
|
|
updated_at TIMESTAMPTZ DEFAULT NOW()
|
|
);
|
|
|
|
CREATE INDEX IF NOT EXISTS ix_conversations_user_id ON conversations(user_id);
|
|
CREATE INDEX IF NOT EXISTS ix_conversations_channel_id ON conversations(channel_id);
|
|
CREATE INDEX IF NOT EXISTS ix_conversations_last_message_at ON conversations(last_message_at);
|
|
CREATE INDEX IF NOT EXISTS ix_conversations_is_active ON conversations(is_active);
|
|
|
|
-- Messages table
|
|
CREATE TABLE IF NOT EXISTS messages (
|
|
id BIGSERIAL PRIMARY KEY,
|
|
conversation_id BIGINT NOT NULL REFERENCES conversations(id) ON DELETE CASCADE,
|
|
user_id BIGINT NOT NULL REFERENCES users(id) ON DELETE CASCADE,
|
|
discord_message_id BIGINT,
|
|
role VARCHAR(20) NOT NULL,
|
|
content TEXT NOT NULL,
|
|
has_images BOOLEAN NOT NULL DEFAULT FALSE,
|
|
image_urls TEXT[],
|
|
token_count INTEGER,
|
|
created_at TIMESTAMPTZ DEFAULT NOW(),
|
|
updated_at TIMESTAMPTZ DEFAULT NOW()
|
|
);
|
|
|
|
CREATE INDEX IF NOT EXISTS ix_messages_conversation_id ON messages(conversation_id);
|
|
CREATE INDEX IF NOT EXISTS ix_messages_user_id ON messages(user_id);
|
|
CREATE INDEX IF NOT EXISTS ix_messages_created_at ON messages(created_at);
|