Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ POSTGRESQL_PORT=5432
POSTGRESQL_USER=postgres
POSTGRESQL_PASSWORD=postgres
POSTGRESQL_DATABASE=discordbot
POSTGRESQL_SCHEMA=public
POSTGRESQL_SCHEMA=public,gw2
# Session settings
POSTGRESQL_ECHO=false
POSTGRESQL_AUTOFLUSH=false
Expand Down
5 changes: 3 additions & 2 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -33,12 +33,13 @@ dependencies = [
"alembic>=1.18.4",
"beautifulsoup4>=4.14.3",
"better-profanity>=0.7.0",
"ddcdatabases[postgres]>=3.0.10",
"ddcdatabases[postgres]>=3.0.11",
"discord-py>=2.6.4",
"gTTS>=2.5.4",
"openai>=2.24.0",
"PyNaCl>=1.6.2",
"pythonLogs>=6.0.2",
"pythonLogs>=6.0.3",
"uuid-utils>=0.14.1",
]

[dependency-groups]
Expand Down
6 changes: 3 additions & 3 deletions src/database/dal/bot/bot_configs_dal.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,11 @@ def __init__(self, db_session, log):
self.log = log

async def update_bot_prefix(self, prefix: str):
stmt = sa.update(BotConfigs).where(BotConfigs.id == 1).values(prefix=prefix)
stmt = sa.update(BotConfigs).values(prefix=prefix)
await self.db_utils.execute(stmt)

async def update_bot_description(self, description: str):
stmt = sa.update(BotConfigs).where(BotConfigs.id == 1).values(description=description)
stmt = sa.update(BotConfigs).values(description=description)
await self.db_utils.execute(stmt)

async def get_bot_configs(self):
Expand All @@ -24,6 +24,6 @@ async def get_bot_configs(self):
return results

async def get_bot_prefix(self):
stmt = select(BotConfigs.prefix).where(BotConfigs.id == 1)
stmt = select(BotConfigs.prefix)
results = await self.db_utils.fetchvalue(stmt)
return results
47 changes: 23 additions & 24 deletions src/database/dal/gw2/gw2_session_chars_dal.py
Original file line number Diff line number Diff line change
@@ -1,41 +1,40 @@
from ddcDatabases import DBUtilsAsync
from sqlalchemy import delete
from sqlalchemy import update
from sqlalchemy.future import select
from src.database.models.gw2_models import Gw2SessionChars
from src.database.models.gw2_models import Gw2SessionCharDeaths


class Gw2SessionCharsDal:
class Gw2SessionCharDeathsDal:
def __init__(self, db_session, log):
self.columns = list(Gw2SessionChars.__table__.columns.values())
self.columns = list(Gw2SessionCharDeaths.__table__.columns.values())
self.db_utils = DBUtilsAsync(db_session)
self.log = log

async def insert_session_char(self, characters_data: list[dict], insert_args: dict):
async def insert_start_char_deaths(self, session_id, user_id: int, characters_data: list[dict]):
for char in characters_data:
stmt = Gw2SessionChars(
session_id=insert_args["session_id"],
user_id=insert_args["user_id"],
stmt = Gw2SessionCharDeaths(
session_id=session_id,
user_id=user_id,
name=char["name"],
profession=char["profession"],
deaths=char["deaths"],
start=insert_args["start"],
end=insert_args["end"],
start=char["deaths"],
end=None,
)
await self.db_utils.insert(stmt)

async def delete_end_characters(self, session_id: int):
stmt = delete(Gw2SessionChars).where(
Gw2SessionChars.session_id == session_id,
Gw2SessionChars.end.is_(True),
)
await self.db_utils.execute(stmt)

async def get_all_start_characters(self, user_id: int):
stmt = select(*self.columns).where(Gw2SessionChars.user_id == user_id, Gw2SessionChars.start.is_(True))
results = await self.db_utils.fetchall(stmt, True)
return results
async def update_end_char_deaths(self, session_id, user_id: int, characters_data: list[dict]):
for char in characters_data:
stmt = (
update(Gw2SessionCharDeaths)
.where(
Gw2SessionCharDeaths.session_id == session_id,
Gw2SessionCharDeaths.name == char["name"],
)
.values(end=char["deaths"])
)
await self.db_utils.execute(stmt)

async def get_all_end_characters(self, user_id: int):
stmt = select(*self.columns).where(Gw2SessionChars.user_id == user_id, Gw2SessionChars.end.is_(True))
async def get_char_deaths(self, user_id: int):
stmt = select(*self.columns).where(Gw2SessionCharDeaths.user_id == user_id)
results = await self.db_utils.fetchall(stmt, True)
return results
6 changes: 3 additions & 3 deletions src/database/dal/gw2/gw2_sessions_dal.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import sqlalchemy as sa
from ddcDatabases import DBUtilsAsync
from sqlalchemy.future import select
from src.database.models.gw2_models import Gw2SessionChars, Gw2Sessions
from src.database.models.gw2_models import Gw2SessionCharDeaths, Gw2Sessions


class Gw2SessionsDal:
Expand All @@ -11,8 +11,8 @@ def __init__(self, db_session, log):
self.log = log

async def insert_start_session(self, session: dict):
stmt = sa.delete(Gw2SessionChars).where(
Gw2SessionChars.user_id == session["user_id"],
stmt = sa.delete(Gw2SessionCharDeaths).where(
Gw2SessionCharDeaths.user_id == session["user_id"],
)
await self.db_utils.execute(stmt)

Expand Down
26 changes: 18 additions & 8 deletions src/database/migrations/env.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@
)
config.set_main_option("sqlalchemy.url", _conn_url)

_schemas = {s.strip() for s in (_postgres_settings.schema or "public").split(",")}


def _include_object(
obj: SchemaItem,
Expand All @@ -38,10 +40,13 @@ def _include_object(
_compare_to: SchemaItem | None,
) -> bool | None:
"""
Filter to only include objects from our target schema.
Filter to only include objects from our target schemas.
This prevents Alembic from trying to manage tables in other schemas.
"""
if type_ == "table" and hasattr(obj, "schema") and obj.schema != _postgres_settings.schema: # type: ignore[attr-defined]
if type_ == "table" and hasattr(obj, "schema"):
obj_schema = obj.schema # type: ignore[attr-defined]
if obj_schema is None or obj_schema in _schemas:
return True
return False
return True

Expand All @@ -57,6 +62,9 @@ def _process_revision_directives(ctx: Any, revision: Any, directives: Any) -> No
migration_script.rev_id = f"{new_rev_id:04}"


_version_table_schema = "public" if len(_schemas) > 1 else next(iter(_schemas))


def run_migrations_offline() -> None:
"""Run migrations in 'offline' mode.

Expand All @@ -77,15 +85,16 @@ def run_migrations_offline() -> None:
literal_binds=True,
dialect_opts={"paramstyle": "named"},
process_revision_directives=_process_revision_directives,
version_table_schema=_postgres_settings.schema,
version_table_schema=_version_table_schema,
version_table=_project_settings.alembic_version_table_name,
include_schemas=True,
include_object=_include_object,
)

with context.begin_transaction():
# Ensure the schema exists before Alembic tries to create its version table
context.execute(f"CREATE SCHEMA IF NOT EXISTS {_postgres_settings.schema}")
for s in _schemas:
if s != "public":
context.execute(f"CREATE SCHEMA IF NOT EXISTS {s}")
context.run_migrations()


Expand All @@ -103,15 +112,16 @@ def run_migrations_online() -> None:
)

with connectable.connect() as connection:
# Ensure the schema exists before Alembic tries to create its version table
connection.execute(text(f"CREATE SCHEMA IF NOT EXISTS {_postgres_settings.schema}"))
for s in _schemas:
if s != "public":
connection.execute(text(f"CREATE SCHEMA IF NOT EXISTS {s}"))
connection.commit()

context.configure(
connection=connection,
target_metadata=target_metadata,
process_revision_directives=_process_revision_directives,
version_table_schema=_postgres_settings.schema,
version_table_schema=_version_table_schema,
version_table=_project_settings.alembic_version_table_name,
include_schemas=True,
include_object=_include_object,
Expand Down
11 changes: 8 additions & 3 deletions src/database/migrations/versions/0001_create_functions.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
branch_labels: str | Sequence[str] | None = None
depends_on: str | Sequence[str] | None = None
db_schema = get_postgresql_settings().schema
_schemas = [s.strip() for s in (db_schema or "public").split(",")]


def upgrade() -> None:
Expand All @@ -27,10 +28,14 @@ def upgrade() -> None:
return NEW;
END $$;
""")
# This function is responsible for schema creation
op.execute(f"CREATE SCHEMA IF NOT EXISTS {db_schema}")
# Create each non-public schema
for s in _schemas:
if s != "public":
op.execute(f"CREATE SCHEMA IF NOT EXISTS {s}")


def downgrade() -> None:
op.execute("DROP FUNCTION IF EXISTS updated_at_column_func")
op.execute(f"DROP SCHEMA IF EXISTS {db_schema} CASCADE")
for s in _schemas:
if s != "public":
op.execute(f"DROP SCHEMA IF EXISTS {s} CASCADE")
15 changes: 6 additions & 9 deletions src/database/migrations/versions/0002_bot_configs.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
from alembic import op
from collections.abc import Sequence
from src.bot.constants import variables
from src.database.models.bot_models import BotConfigs

# revision identifiers, used by Alembic.
revision: str = "0002"
Expand All @@ -20,10 +19,9 @@


def upgrade() -> None:
# ### commands auto generated by Alembic - please adjust! ###
op.create_table(
"bot_configs",
sa.Column("id", sa.BigInteger(), autoincrement=True, nullable=False),
sa.Column("id", sa.Uuid(), nullable=False, server_default=sa.text("gen_random_uuid()")),
sa.Column("prefix", sa.CHAR(length=1), server_default=variables.PREFIX, nullable=False),
sa.Column("author_id", sa.BigInteger(), server_default=variables.AUTHOR_ID, nullable=False),
sa.Column("url", sa.String(), server_default=variables.BOT_WEBPAGE_URL, nullable=False),
Expand All @@ -34,10 +32,12 @@ def upgrade() -> None:
sa.UniqueConstraint("id"),
)
op.execute(
sa.insert(BotConfigs).values(
id=1,
sa.text(
"INSERT INTO bot_configs (prefix, author_id, url, description) "
"VALUES (:prefix, :author_id, :url, :description)"
).bindparams(
prefix=variables.PREFIX,
author_id=variables.AUTHOR_ID,
author_id=int(variables.AUTHOR_ID),
url=variables.BOT_WEBPAGE_URL,
description=variables.DESCRIPTION,
)
Expand All @@ -48,11 +48,8 @@ def upgrade() -> None:
FOR EACH ROW
EXECUTE PROCEDURE updated_at_column_func();
""")
# ### end Alembic commands ###


def downgrade() -> None:
# ### commands auto generated by Alembic - please adjust! ###
op.execute("DROP TRIGGER IF EXISTS before_update_bot_configs_tr ON bot_configs")
op.drop_table("bot_configs")
# ### end Alembic commands ###
4 changes: 0 additions & 4 deletions src/database/migrations/versions/0003_servers.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@


def upgrade() -> None:
# ### commands auto generated by Alembic - please adjust! ###
op.create_table(
"servers",
sa.Column("id", sa.BigInteger(), autoincrement=True, nullable=False),
Expand All @@ -42,12 +41,9 @@ def upgrade() -> None:
FOR EACH ROW
EXECUTE PROCEDURE updated_at_column_func();
""")
# ### end Alembic commands ###


def downgrade() -> None:
# ### commands auto generated by Alembic - please adjust! ###
op.execute("DROP TRIGGER IF EXISTS before_update_servers_tr ON servers")
op.drop_index(op.f("ix_servers_id"), table_name="servers")
op.drop_table("servers")
# ### end Alembic commands ###
6 changes: 1 addition & 5 deletions src/database/migrations/versions/0004_custom_commands.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,9 @@


def upgrade() -> None:
# ### commands auto generated by Alembic - please adjust! ###
op.create_table(
"custom_commands",
sa.Column("id", sa.BigInteger(), autoincrement=True, nullable=False),
sa.Column("id", sa.Uuid(), nullable=False, server_default=sa.text("gen_random_uuid()")),
sa.Column("server_id", sa.BigInteger(), nullable=False),
sa.Column("name", sa.String(), nullable=False),
sa.Column("description", sa.String(), nullable=False),
Expand All @@ -40,12 +39,9 @@ def upgrade() -> None:
FOR EACH ROW
EXECUTE PROCEDURE updated_at_column_func();
""")
# ### end Alembic commands ###


def downgrade() -> None:
# ### commands auto generated by Alembic - please adjust! ###
op.execute("DROP TRIGGER IF EXISTS before_update_custom_commands_tr ON custom_commands")
op.drop_index(op.f("ix_custom_commands_server_id"), table_name="custom_commands")
op.drop_table("custom_commands")
# ### end Alembic commands ###
6 changes: 1 addition & 5 deletions src/database/migrations/versions/0005_profanity_filters.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,9 @@


def upgrade() -> None:
# ### commands auto generated by Alembic - please adjust! ###
op.create_table(
"profanity_filters",
sa.Column("id", sa.BigInteger(), autoincrement=True, nullable=False),
sa.Column("id", sa.Uuid(), nullable=False, server_default=sa.text("gen_random_uuid()")),
sa.Column("server_id", sa.BigInteger(), nullable=False),
sa.Column("channel_id", sa.BigInteger(), nullable=False),
sa.Column("channel_name", sa.String(), nullable=False),
Expand All @@ -39,12 +38,9 @@ def upgrade() -> None:
FOR EACH ROW
EXECUTE PROCEDURE updated_at_column_func();
""")
# ### end Alembic commands ###


def downgrade() -> None:
# ### commands auto generated by Alembic - please adjust! ###
op.execute("DROP TRIGGER IF EXISTS before_update_profanity_filters_tr ON profanity_filters")
op.drop_index(op.f("ix_profanity_filters_server_id"), table_name="profanity_filters")
op.drop_table("profanity_filters")
# ### end Alembic commands ###
6 changes: 1 addition & 5 deletions src/database/migrations/versions/0006_dice_rolls.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,9 @@


def upgrade() -> None:
# ### commands auto generated by Alembic - please adjust! ###
op.create_table(
"dice_rolls",
sa.Column("id", sa.BigInteger(), autoincrement=True, nullable=False),
sa.Column("id", sa.Uuid(), nullable=False, server_default=sa.text("gen_random_uuid()")),
sa.Column("server_id", sa.BigInteger(), nullable=False),
sa.Column("user_id", sa.BigInteger(), nullable=False),
sa.Column("roll", sa.Integer(), nullable=False),
Expand All @@ -40,13 +39,10 @@ def upgrade() -> None:
FOR EACH ROW
EXECUTE PROCEDURE updated_at_column_func();
""")
# ### end Alembic commands ###


def downgrade() -> None:
# ### commands auto generated by Alembic - please adjust! ###
op.execute("DROP TRIGGER IF EXISTS before_update_dice_rolls_tr ON dice_rolls")
op.drop_index(op.f("ix_dice_rolls_user_id"), table_name="dice_rolls")
op.drop_index(op.f("ix_dice_rolls_server_id"), table_name="dice_rolls")
op.drop_table("dice_rolls")
# ### end Alembic commands ###
Loading