diff --git a/app/db_engine.py b/app/db_engine.py index 307be64..b27cfcf 100644 --- a/app/db_engine.py +++ b/app/db_engine.py @@ -2438,8 +2438,7 @@ class Decision(BaseModel): class CustomCommandCreator(BaseModel): """Model for custom command creators.""" - - discord_id = CharField(max_length=20, unique=True) # Discord snowflake ID as string + discord_id = BigIntegerField(unique=True) username = CharField(max_length=32) display_name = CharField(max_length=32, null=True) created_at = DateTimeField() diff --git a/app/routers_v3/custom_commands.py b/app/routers_v3/custom_commands.py index c398589..617cebf 100644 --- a/app/routers_v3/custom_commands.py +++ b/app/routers_v3/custom_commands.py @@ -175,7 +175,7 @@ def delete_custom_command(command_id: int): def get_creator_by_discord_id(discord_id: int): """Get a creator by Discord ID""" creator = CustomCommandCreator.get_or_none( - CustomCommandCreator.discord_id == str(discord_id) + CustomCommandCreator.discord_id == discord_id ) if creator: return model_to_dict(creator) @@ -273,7 +273,10 @@ async def get_custom_commands( sql = f""" SELECT cc.*, creator.discord_id as creator_discord_id, creator.username as creator_username, - creator.display_name as creator_display_name + creator.display_name as creator_display_name, + creator.created_at as creator_created_at, + creator.total_commands as creator_total_commands, + creator.active_commands as creator_active_commands FROM custom_commands cc LEFT JOIN custom_command_creators creator ON cc.creator_id = creator.id {where_clause} @@ -298,24 +301,23 @@ async def get_custom_commands( command_dict["tags"] = json.loads(command_dict["tags"]) except Exception: command_dict["tags"] = [] - # Get full creator information - creator_id = command_dict["creator_id"] - creator_cursor = db.execute_sql( - "SELECT * FROM custom_command_creators WHERE id = %s", (creator_id,) - ) - creator_result = creator_cursor.fetchone() - if creator_result: - # Create complete creator object - creator_columns = [desc[0] for desc in creator_cursor.description] - creator_dict = dict(zip(creator_columns, creator_result)) - # Convert datetime to ISO string - if creator_dict.get("created_at") and hasattr( - creator_dict["created_at"], "isoformat" - ): - creator_dict["created_at"] = creator_dict[ - "created_at" - ].isoformat() + # Build creator object from joined data (avoids N+1 queries) + if command_dict.get("creator_discord_id") is not None: + creator_created_at = command_dict.get("creator_created_at") + if creator_created_at and hasattr(creator_created_at, "isoformat"): + creator_created_at = creator_created_at.isoformat() + creator_dict = { + "id": command_dict["creator_id"], + "discord_id": command_dict["creator_discord_id"], + "username": command_dict["creator_username"], + "display_name": command_dict.get("creator_display_name"), + "created_at": creator_created_at, + "total_commands": command_dict.get("creator_total_commands", 0), + "active_commands": command_dict.get( + "creator_active_commands", 0 + ), + } try: creator_model = CustomCommandCreatorModel(**creator_dict) command_dict["creator"] = creator_model @@ -325,13 +327,15 @@ async def get_custom_commands( ) command_dict["creator"] = None else: - # No creator found, set to None command_dict["creator"] = None - # Remove the individual creator fields now that we have the creator object + # Remove joined creator fields before building the command model command_dict.pop("creator_discord_id", None) command_dict.pop("creator_username", None) command_dict.pop("creator_display_name", None) + command_dict.pop("creator_created_at", None) + command_dict.pop("creator_total_commands", None) + command_dict.pop("creator_active_commands", None) # Convert datetime fields to ISO strings for field in ["created_at", "updated_at", "last_used"]: @@ -1055,3 +1059,4 @@ async def get_custom_command(command_id: int): except Exception as e: logger.error(f"Error getting custom command {command_id}: {e}") raise HTTPException(status_code=500, detail=str(e)) +