123
This commit is contained in:
parent
fb2278e986
commit
4c2cbc636f
@ -231,6 +231,22 @@ except ImportError as e:
|
|||||||
log.error(f"Could not import dashboard API endpoints: {e}")
|
log.error(f"Could not import dashboard API endpoints: {e}")
|
||||||
log.error("Dashboard API endpoints will not be available")
|
log.error("Dashboard API endpoints will not be available")
|
||||||
|
|
||||||
|
# Import command customization models and endpoints
|
||||||
|
try:
|
||||||
|
# Try relative import first
|
||||||
|
try:
|
||||||
|
from .command_customization_endpoints import router as customization_router
|
||||||
|
except ImportError:
|
||||||
|
# Fall back to absolute import
|
||||||
|
from command_customization_endpoints import router as customization_router
|
||||||
|
|
||||||
|
# Add the command customization router to the dashboard API app
|
||||||
|
dashboard_api_app.include_router(customization_router, prefix="/commands", tags=["Command Customization"])
|
||||||
|
log.info("Command customization endpoints loaded successfully")
|
||||||
|
except ImportError as e:
|
||||||
|
log.error(f"Could not import command customization endpoints: {e}")
|
||||||
|
log.error("Command customization endpoints will not be available")
|
||||||
|
|
||||||
# Mount the API apps at their respective paths
|
# Mount the API apps at their respective paths
|
||||||
app.mount("/api", api_app)
|
app.mount("/api", api_app)
|
||||||
app.mount("/discordapi", discordapi_app)
|
app.mount("/discordapi", discordapi_app)
|
||||||
|
324
api_service/command_customization_endpoints.py
Normal file
324
api_service/command_customization_endpoints.py
Normal file
@ -0,0 +1,324 @@
|
|||||||
|
"""
|
||||||
|
Command customization API endpoints for the bot dashboard.
|
||||||
|
These endpoints provide functionality for customizing command names and groups.
|
||||||
|
"""
|
||||||
|
|
||||||
|
import logging
|
||||||
|
from typing import List, Dict, Optional
|
||||||
|
from fastapi import APIRouter, Depends, HTTPException, status
|
||||||
|
from pydantic import BaseModel
|
||||||
|
|
||||||
|
# Import the dependencies from api_server.py
|
||||||
|
try:
|
||||||
|
# Try relative import first
|
||||||
|
from .api_server import (
|
||||||
|
get_dashboard_user,
|
||||||
|
verify_dashboard_guild_admin,
|
||||||
|
CommandCustomizationResponse,
|
||||||
|
CommandCustomizationUpdate,
|
||||||
|
GroupCustomizationUpdate,
|
||||||
|
CommandAliasAdd,
|
||||||
|
CommandAliasRemove
|
||||||
|
)
|
||||||
|
except ImportError:
|
||||||
|
# Fall back to absolute import
|
||||||
|
from api_server import (
|
||||||
|
get_dashboard_user,
|
||||||
|
verify_dashboard_guild_admin,
|
||||||
|
CommandCustomizationResponse,
|
||||||
|
CommandCustomizationUpdate,
|
||||||
|
GroupCustomizationUpdate,
|
||||||
|
CommandAliasAdd,
|
||||||
|
CommandAliasRemove
|
||||||
|
)
|
||||||
|
|
||||||
|
# Import settings_manager for database access
|
||||||
|
try:
|
||||||
|
from discordbot import settings_manager
|
||||||
|
except ImportError:
|
||||||
|
# Try relative import
|
||||||
|
import sys
|
||||||
|
import os
|
||||||
|
sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), '../..')))
|
||||||
|
from discordbot import settings_manager
|
||||||
|
|
||||||
|
log = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
# Create the router
|
||||||
|
router = APIRouter()
|
||||||
|
|
||||||
|
# --- Command Customization Endpoints ---
|
||||||
|
|
||||||
|
@router.get("/customizations/{guild_id}", response_model=CommandCustomizationResponse)
|
||||||
|
async def get_command_customizations(
|
||||||
|
guild_id: int,
|
||||||
|
_user: dict = Depends(get_dashboard_user),
|
||||||
|
_admin: bool = Depends(verify_dashboard_guild_admin)
|
||||||
|
):
|
||||||
|
"""Get all command customizations for a guild."""
|
||||||
|
try:
|
||||||
|
# Check if settings_manager is available
|
||||||
|
if not settings_manager or not settings_manager.pg_pool:
|
||||||
|
raise HTTPException(
|
||||||
|
status_code=status.HTTP_503_SERVICE_UNAVAILABLE,
|
||||||
|
detail="Settings manager not available"
|
||||||
|
)
|
||||||
|
|
||||||
|
# Get command customizations
|
||||||
|
command_customizations = await settings_manager.get_all_command_customizations(guild_id)
|
||||||
|
if command_customizations is None:
|
||||||
|
raise HTTPException(
|
||||||
|
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
||||||
|
detail="Failed to get command customizations"
|
||||||
|
)
|
||||||
|
|
||||||
|
# Get group customizations
|
||||||
|
group_customizations = await settings_manager.get_all_group_customizations(guild_id)
|
||||||
|
if group_customizations is None:
|
||||||
|
raise HTTPException(
|
||||||
|
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
||||||
|
detail="Failed to get group customizations"
|
||||||
|
)
|
||||||
|
|
||||||
|
# Get command aliases
|
||||||
|
command_aliases = await settings_manager.get_all_command_aliases(guild_id)
|
||||||
|
if command_aliases is None:
|
||||||
|
raise HTTPException(
|
||||||
|
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
||||||
|
detail="Failed to get command aliases"
|
||||||
|
)
|
||||||
|
|
||||||
|
return CommandCustomizationResponse(
|
||||||
|
command_customizations=command_customizations,
|
||||||
|
group_customizations=group_customizations,
|
||||||
|
command_aliases=command_aliases
|
||||||
|
)
|
||||||
|
except HTTPException:
|
||||||
|
# Re-raise HTTP exceptions
|
||||||
|
raise
|
||||||
|
except Exception as e:
|
||||||
|
log.error(f"Error getting command customizations for guild {guild_id}: {e}")
|
||||||
|
raise HTTPException(
|
||||||
|
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
||||||
|
detail=f"Error getting command customizations: {str(e)}"
|
||||||
|
)
|
||||||
|
|
||||||
|
@router.post("/customizations/{guild_id}/commands", status_code=status.HTTP_200_OK)
|
||||||
|
async def set_command_customization(
|
||||||
|
guild_id: int,
|
||||||
|
customization: CommandCustomizationUpdate,
|
||||||
|
_user: dict = Depends(get_dashboard_user),
|
||||||
|
_admin: bool = Depends(verify_dashboard_guild_admin)
|
||||||
|
):
|
||||||
|
"""Set a custom name for a command in a guild."""
|
||||||
|
try:
|
||||||
|
# Check if settings_manager is available
|
||||||
|
if not settings_manager or not settings_manager.pg_pool:
|
||||||
|
raise HTTPException(
|
||||||
|
status_code=status.HTTP_503_SERVICE_UNAVAILABLE,
|
||||||
|
detail="Settings manager not available"
|
||||||
|
)
|
||||||
|
|
||||||
|
# Validate custom name format if provided
|
||||||
|
if customization.custom_name is not None:
|
||||||
|
if not customization.custom_name.islower() or not customization.custom_name.replace('_', '').isalnum():
|
||||||
|
raise HTTPException(
|
||||||
|
status_code=status.HTTP_400_BAD_REQUEST,
|
||||||
|
detail="Custom command names must be lowercase and contain only letters, numbers, and underscores"
|
||||||
|
)
|
||||||
|
|
||||||
|
if len(customization.custom_name) < 1 or len(customization.custom_name) > 32:
|
||||||
|
raise HTTPException(
|
||||||
|
status_code=status.HTTP_400_BAD_REQUEST,
|
||||||
|
detail="Custom command names must be between 1 and 32 characters long"
|
||||||
|
)
|
||||||
|
|
||||||
|
# Set the custom command name
|
||||||
|
success = await settings_manager.set_custom_command_name(
|
||||||
|
guild_id,
|
||||||
|
customization.command_name,
|
||||||
|
customization.custom_name
|
||||||
|
)
|
||||||
|
|
||||||
|
if not success:
|
||||||
|
raise HTTPException(
|
||||||
|
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
||||||
|
detail="Failed to set custom command name"
|
||||||
|
)
|
||||||
|
|
||||||
|
return {"message": "Command customization updated successfully"}
|
||||||
|
except HTTPException:
|
||||||
|
# Re-raise HTTP exceptions
|
||||||
|
raise
|
||||||
|
except Exception as e:
|
||||||
|
log.error(f"Error setting command customization for guild {guild_id}: {e}")
|
||||||
|
raise HTTPException(
|
||||||
|
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
||||||
|
detail=f"Error setting command customization: {str(e)}"
|
||||||
|
)
|
||||||
|
|
||||||
|
@router.post("/customizations/{guild_id}/groups", status_code=status.HTTP_200_OK)
|
||||||
|
async def set_group_customization(
|
||||||
|
guild_id: int,
|
||||||
|
customization: GroupCustomizationUpdate,
|
||||||
|
_user: dict = Depends(get_dashboard_user),
|
||||||
|
_admin: bool = Depends(verify_dashboard_guild_admin)
|
||||||
|
):
|
||||||
|
"""Set a custom name for a command group in a guild."""
|
||||||
|
try:
|
||||||
|
# Check if settings_manager is available
|
||||||
|
if not settings_manager or not settings_manager.pg_pool:
|
||||||
|
raise HTTPException(
|
||||||
|
status_code=status.HTTP_503_SERVICE_UNAVAILABLE,
|
||||||
|
detail="Settings manager not available"
|
||||||
|
)
|
||||||
|
|
||||||
|
# Validate custom name format if provided
|
||||||
|
if customization.custom_name is not None:
|
||||||
|
if not customization.custom_name.islower() or not customization.custom_name.replace('_', '').isalnum():
|
||||||
|
raise HTTPException(
|
||||||
|
status_code=status.HTTP_400_BAD_REQUEST,
|
||||||
|
detail="Custom group names must be lowercase and contain only letters, numbers, and underscores"
|
||||||
|
)
|
||||||
|
|
||||||
|
if len(customization.custom_name) < 1 or len(customization.custom_name) > 32:
|
||||||
|
raise HTTPException(
|
||||||
|
status_code=status.HTTP_400_BAD_REQUEST,
|
||||||
|
detail="Custom group names must be between 1 and 32 characters long"
|
||||||
|
)
|
||||||
|
|
||||||
|
# Set the custom group name
|
||||||
|
success = await settings_manager.set_custom_group_name(
|
||||||
|
guild_id,
|
||||||
|
customization.group_name,
|
||||||
|
customization.custom_name
|
||||||
|
)
|
||||||
|
|
||||||
|
if not success:
|
||||||
|
raise HTTPException(
|
||||||
|
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
||||||
|
detail="Failed to set custom group name"
|
||||||
|
)
|
||||||
|
|
||||||
|
return {"message": "Group customization updated successfully"}
|
||||||
|
except HTTPException:
|
||||||
|
# Re-raise HTTP exceptions
|
||||||
|
raise
|
||||||
|
except Exception as e:
|
||||||
|
log.error(f"Error setting group customization for guild {guild_id}: {e}")
|
||||||
|
raise HTTPException(
|
||||||
|
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
||||||
|
detail=f"Error setting group customization: {str(e)}"
|
||||||
|
)
|
||||||
|
|
||||||
|
@router.post("/customizations/{guild_id}/aliases", status_code=status.HTTP_200_OK)
|
||||||
|
async def add_command_alias(
|
||||||
|
guild_id: int,
|
||||||
|
alias: CommandAliasAdd,
|
||||||
|
_user: dict = Depends(get_dashboard_user),
|
||||||
|
_admin: bool = Depends(verify_dashboard_guild_admin)
|
||||||
|
):
|
||||||
|
"""Add an alias for a command in a guild."""
|
||||||
|
try:
|
||||||
|
# Check if settings_manager is available
|
||||||
|
if not settings_manager or not settings_manager.pg_pool:
|
||||||
|
raise HTTPException(
|
||||||
|
status_code=status.HTTP_503_SERVICE_UNAVAILABLE,
|
||||||
|
detail="Settings manager not available"
|
||||||
|
)
|
||||||
|
|
||||||
|
# Validate alias format
|
||||||
|
if not alias.alias_name.islower() or not alias.alias_name.replace('_', '').isalnum():
|
||||||
|
raise HTTPException(
|
||||||
|
status_code=status.HTTP_400_BAD_REQUEST,
|
||||||
|
detail="Aliases must be lowercase and contain only letters, numbers, and underscores"
|
||||||
|
)
|
||||||
|
|
||||||
|
if len(alias.alias_name) < 1 or len(alias.alias_name) > 32:
|
||||||
|
raise HTTPException(
|
||||||
|
status_code=status.HTTP_400_BAD_REQUEST,
|
||||||
|
detail="Aliases must be between 1 and 32 characters long"
|
||||||
|
)
|
||||||
|
|
||||||
|
# Add the command alias
|
||||||
|
success = await settings_manager.add_command_alias(
|
||||||
|
guild_id,
|
||||||
|
alias.command_name,
|
||||||
|
alias.alias_name
|
||||||
|
)
|
||||||
|
|
||||||
|
if not success:
|
||||||
|
raise HTTPException(
|
||||||
|
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
||||||
|
detail="Failed to add command alias"
|
||||||
|
)
|
||||||
|
|
||||||
|
return {"message": "Command alias added successfully"}
|
||||||
|
except HTTPException:
|
||||||
|
# Re-raise HTTP exceptions
|
||||||
|
raise
|
||||||
|
except Exception as e:
|
||||||
|
log.error(f"Error adding command alias for guild {guild_id}: {e}")
|
||||||
|
raise HTTPException(
|
||||||
|
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
||||||
|
detail=f"Error adding command alias: {str(e)}"
|
||||||
|
)
|
||||||
|
|
||||||
|
@router.delete("/customizations/{guild_id}/aliases", status_code=status.HTTP_200_OK)
|
||||||
|
async def remove_command_alias(
|
||||||
|
guild_id: int,
|
||||||
|
alias: CommandAliasRemove,
|
||||||
|
_user: dict = Depends(get_dashboard_user),
|
||||||
|
_admin: bool = Depends(verify_dashboard_guild_admin)
|
||||||
|
):
|
||||||
|
"""Remove an alias for a command in a guild."""
|
||||||
|
try:
|
||||||
|
# Check if settings_manager is available
|
||||||
|
if not settings_manager or not settings_manager.pg_pool:
|
||||||
|
raise HTTPException(
|
||||||
|
status_code=status.HTTP_503_SERVICE_UNAVAILABLE,
|
||||||
|
detail="Settings manager not available"
|
||||||
|
)
|
||||||
|
|
||||||
|
# Remove the command alias
|
||||||
|
success = await settings_manager.remove_command_alias(
|
||||||
|
guild_id,
|
||||||
|
alias.command_name,
|
||||||
|
alias.alias_name
|
||||||
|
)
|
||||||
|
|
||||||
|
if not success:
|
||||||
|
raise HTTPException(
|
||||||
|
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
||||||
|
detail="Failed to remove command alias"
|
||||||
|
)
|
||||||
|
|
||||||
|
return {"message": "Command alias removed successfully"}
|
||||||
|
except HTTPException:
|
||||||
|
# Re-raise HTTP exceptions
|
||||||
|
raise
|
||||||
|
except Exception as e:
|
||||||
|
log.error(f"Error removing command alias for guild {guild_id}: {e}")
|
||||||
|
raise HTTPException(
|
||||||
|
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
||||||
|
detail=f"Error removing command alias: {str(e)}"
|
||||||
|
)
|
||||||
|
|
||||||
|
@router.post("/customizations/{guild_id}/sync", status_code=status.HTTP_200_OK)
|
||||||
|
async def sync_guild_commands(
|
||||||
|
guild_id: int,
|
||||||
|
_user: dict = Depends(get_dashboard_user),
|
||||||
|
_admin: bool = Depends(verify_dashboard_guild_admin)
|
||||||
|
):
|
||||||
|
"""Sync commands for a guild to apply customizations."""
|
||||||
|
try:
|
||||||
|
# This endpoint would trigger a command sync for the guild
|
||||||
|
# In a real implementation, this would communicate with the bot to sync commands
|
||||||
|
# For now, we'll just return a success message
|
||||||
|
return {"message": "Command sync requested. This may take a moment to complete."}
|
||||||
|
except Exception as e:
|
||||||
|
log.error(f"Error syncing commands for guild {guild_id}: {e}")
|
||||||
|
raise HTTPException(
|
||||||
|
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
||||||
|
detail=f"Error syncing commands: {str(e)}"
|
||||||
|
)
|
@ -2,6 +2,7 @@ import discord
|
|||||||
from discord.ext import commands
|
from discord.ext import commands
|
||||||
import logging
|
import logging
|
||||||
from discordbot import settings_manager # Assuming settings_manager is accessible
|
from discordbot import settings_manager # Assuming settings_manager is accessible
|
||||||
|
from discordbot import command_customization # Import command customization utilities
|
||||||
from typing import Optional
|
from typing import Optional
|
||||||
|
|
||||||
log = logging.getLogger(__name__)
|
log = logging.getLogger(__name__)
|
||||||
@ -385,11 +386,18 @@ class SettingsCog(commands.Cog, name="Settings"):
|
|||||||
guild = ctx.guild
|
guild = ctx.guild
|
||||||
await ctx.send("Syncing commands with Discord... This may take a moment.")
|
await ctx.send("Syncing commands with Discord... This may take a moment.")
|
||||||
|
|
||||||
# Sync commands for this guild specifically
|
# Use the command_customization module to sync commands with customizations
|
||||||
synced = await self.bot.tree.sync(guild=guild)
|
try:
|
||||||
|
synced = await command_customization.register_guild_commands(self.bot, guild)
|
||||||
|
|
||||||
await ctx.send(f"Successfully synced {len(synced)} commands for this server.")
|
await ctx.send(f"Successfully synced {len(synced)} commands for this server with customizations.")
|
||||||
log.info(f"Commands synced for guild {guild.id} by {ctx.author.name}")
|
log.info(f"Commands synced with customizations for guild {guild.id} by {ctx.author.name}")
|
||||||
|
except Exception as e:
|
||||||
|
log.error(f"Failed to sync commands with customizations: {e}")
|
||||||
|
# Fall back to regular sync if customization sync fails
|
||||||
|
synced = await self.bot.tree.sync(guild=guild)
|
||||||
|
await ctx.send(f"Failed to apply customizations, but synced {len(synced)} commands for this server.")
|
||||||
|
log.info(f"Commands synced (without customizations) for guild {guild.id} by {ctx.author.name}")
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
await ctx.send(f"Failed to sync commands: {str(e)}")
|
await ctx.send(f"Failed to sync commands: {str(e)}")
|
||||||
log.error(f"Failed to sync commands for guild {ctx.guild.id}: {e}")
|
log.error(f"Failed to sync commands for guild {ctx.guild.id}: {e}")
|
||||||
|
@ -7,7 +7,7 @@ from discord import app_commands
|
|||||||
import logging
|
import logging
|
||||||
from typing import Dict, List, Optional, Tuple, Any, Callable, Awaitable
|
from typing import Dict, List, Optional, Tuple, Any, Callable, Awaitable
|
||||||
import asyncio
|
import asyncio
|
||||||
from . import settings_manager
|
from discordbot import settings_manager
|
||||||
|
|
||||||
log = logging.getLogger(__name__)
|
log = logging.getLogger(__name__)
|
||||||
|
|
||||||
@ -20,7 +20,7 @@ class GuildCommandTransformer(app_commands.Transformer):
|
|||||||
"""Transform the command name based on guild settings."""
|
"""Transform the command name based on guild settings."""
|
||||||
if not interaction.guild:
|
if not interaction.guild:
|
||||||
return value # No customization in DMs
|
return value # No customization in DMs
|
||||||
|
|
||||||
guild_id = interaction.guild.id
|
guild_id = interaction.guild.id
|
||||||
custom_name = await settings_manager.get_custom_command_name(guild_id, value)
|
custom_name = await settings_manager.get_custom_command_name(guild_id, value)
|
||||||
return custom_name if custom_name else value
|
return custom_name if custom_name else value
|
||||||
@ -34,7 +34,7 @@ class GuildCommandSyncer:
|
|||||||
self.bot = bot
|
self.bot = bot
|
||||||
self._command_cache = {} # Cache of original commands
|
self._command_cache = {} # Cache of original commands
|
||||||
self._customized_commands = {} # Guild ID -> {original_name: custom_command}
|
self._customized_commands = {} # Guild ID -> {original_name: custom_command}
|
||||||
|
|
||||||
async def load_guild_customizations(self, guild_id: int) -> Dict[str, str]:
|
async def load_guild_customizations(self, guild_id: int) -> Dict[str, str]:
|
||||||
"""
|
"""
|
||||||
Load command customizations for a specific guild.
|
Load command customizations for a specific guild.
|
||||||
@ -42,16 +42,16 @@ class GuildCommandSyncer:
|
|||||||
"""
|
"""
|
||||||
cmd_customizations = await settings_manager.get_all_command_customizations(guild_id)
|
cmd_customizations = await settings_manager.get_all_command_customizations(guild_id)
|
||||||
group_customizations = await settings_manager.get_all_group_customizations(guild_id)
|
group_customizations = await settings_manager.get_all_group_customizations(guild_id)
|
||||||
|
|
||||||
if cmd_customizations is None or group_customizations is None:
|
if cmd_customizations is None or group_customizations is None:
|
||||||
log.error(f"Failed to load command customizations for guild {guild_id}")
|
log.error(f"Failed to load command customizations for guild {guild_id}")
|
||||||
return {}
|
return {}
|
||||||
|
|
||||||
# Combine command and group customizations
|
# Combine command and group customizations
|
||||||
customizations = {**cmd_customizations, **group_customizations}
|
customizations = {**cmd_customizations, **group_customizations}
|
||||||
log.info(f"Loaded {len(customizations)} command customizations for guild {guild_id}")
|
log.info(f"Loaded {len(customizations)} command customizations for guild {guild_id}")
|
||||||
return customizations
|
return customizations
|
||||||
|
|
||||||
async def prepare_guild_commands(self, guild_id: int) -> List[app_commands.Command]:
|
async def prepare_guild_commands(self, guild_id: int) -> List[app_commands.Command]:
|
||||||
"""
|
"""
|
||||||
Prepare guild-specific commands with customized names.
|
Prepare guild-specific commands with customized names.
|
||||||
@ -59,16 +59,16 @@ class GuildCommandSyncer:
|
|||||||
"""
|
"""
|
||||||
# Get all global commands
|
# Get all global commands
|
||||||
global_commands = self.bot.tree.get_commands()
|
global_commands = self.bot.tree.get_commands()
|
||||||
|
|
||||||
# Cache original commands if not already cached
|
# Cache original commands if not already cached
|
||||||
if not self._command_cache:
|
if not self._command_cache:
|
||||||
self._command_cache = {cmd.name: cmd for cmd in global_commands}
|
self._command_cache = {cmd.name: cmd for cmd in global_commands}
|
||||||
|
|
||||||
# Load customizations for this guild
|
# Load customizations for this guild
|
||||||
customizations = await self.load_guild_customizations(guild_id)
|
customizations = await self.load_guild_customizations(guild_id)
|
||||||
if not customizations:
|
if not customizations:
|
||||||
return global_commands # No customizations, use global commands
|
return global_commands # No customizations, use global commands
|
||||||
|
|
||||||
# Create guild-specific commands with custom names
|
# Create guild-specific commands with custom names
|
||||||
guild_commands = []
|
guild_commands = []
|
||||||
for cmd in global_commands:
|
for cmd in global_commands:
|
||||||
@ -80,15 +80,15 @@ class GuildCommandSyncer:
|
|||||||
else:
|
else:
|
||||||
# Use the original command
|
# Use the original command
|
||||||
guild_commands.append(cmd)
|
guild_commands.append(cmd)
|
||||||
|
|
||||||
# Store customized commands for this guild
|
# Store customized commands for this guild
|
||||||
self._customized_commands[guild_id] = {
|
self._customized_commands[guild_id] = {
|
||||||
cmd.name: custom_cmd for cmd, custom_cmd in zip(global_commands, guild_commands)
|
cmd.name: custom_cmd for cmd, custom_cmd in zip(global_commands, guild_commands)
|
||||||
if cmd.name in customizations
|
if cmd.name in customizations
|
||||||
}
|
}
|
||||||
|
|
||||||
return guild_commands
|
return guild_commands
|
||||||
|
|
||||||
def _create_custom_command(self, original_cmd: app_commands.Command, custom_name: str) -> app_commands.Command:
|
def _create_custom_command(self, original_cmd: app_commands.Command, custom_name: str) -> app_commands.Command:
|
||||||
"""
|
"""
|
||||||
Create a copy of a command with a custom name.
|
Create a copy of a command with a custom name.
|
||||||
@ -101,13 +101,13 @@ class GuildCommandSyncer:
|
|||||||
description=original_cmd.description,
|
description=original_cmd.description,
|
||||||
callback=original_cmd.callback
|
callback=original_cmd.callback
|
||||||
)
|
)
|
||||||
|
|
||||||
# Copy options, if any
|
# Copy options, if any
|
||||||
if hasattr(original_cmd, 'options'):
|
if hasattr(original_cmd, 'options'):
|
||||||
custom_cmd._params = original_cmd._params.copy()
|
custom_cmd._params = original_cmd._params.copy()
|
||||||
|
|
||||||
return custom_cmd
|
return custom_cmd
|
||||||
|
|
||||||
async def sync_guild_commands(self, guild: discord.Guild) -> List[app_commands.Command]:
|
async def sync_guild_commands(self, guild: discord.Guild) -> List[app_commands.Command]:
|
||||||
"""
|
"""
|
||||||
Sync commands for a specific guild with customizations.
|
Sync commands for a specific guild with customizations.
|
||||||
@ -116,10 +116,10 @@ class GuildCommandSyncer:
|
|||||||
try:
|
try:
|
||||||
# Prepare guild-specific commands
|
# Prepare guild-specific commands
|
||||||
guild_commands = await self.prepare_guild_commands(guild.id)
|
guild_commands = await self.prepare_guild_commands(guild.id)
|
||||||
|
|
||||||
# Sync commands with Discord
|
# Sync commands with Discord
|
||||||
synced = await self.bot.tree.sync(guild=guild)
|
synced = await self.bot.tree.sync(guild=guild)
|
||||||
|
|
||||||
log.info(f"Synced {len(synced)} commands for guild {guild.id}")
|
log.info(f"Synced {len(synced)} commands for guild {guild.id}")
|
||||||
return synced
|
return synced
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
@ -132,22 +132,22 @@ def guild_command(name: str, description: str, **kwargs):
|
|||||||
"""
|
"""
|
||||||
Decorator for registering commands with guild-specific name customization.
|
Decorator for registering commands with guild-specific name customization.
|
||||||
Usage:
|
Usage:
|
||||||
|
|
||||||
@guild_command(name="mycommand", description="My command description")
|
@guild_command(name="mycommand", description="My command description")
|
||||||
async def my_command(interaction: discord.Interaction):
|
async def my_command(interaction: discord.Interaction):
|
||||||
...
|
...
|
||||||
"""
|
"""
|
||||||
def decorator(func: Callable[[discord.Interaction, ...], Awaitable[Any]]):
|
def decorator(func: Callable[[discord.Interaction], Awaitable[Any]]):
|
||||||
# Create the app command
|
# Create the app command
|
||||||
@app_commands.command(name=name, description=description, **kwargs)
|
@app_commands.command(name=name, description=description, **kwargs)
|
||||||
async def wrapper(interaction: discord.Interaction, *args, **kwargs):
|
async def wrapper(interaction: discord.Interaction, *args, **kwargs):
|
||||||
return await func(interaction, *args, **kwargs)
|
return await func(interaction, *args, **kwargs)
|
||||||
|
|
||||||
# Store the original name for reference
|
# Store the original name for reference
|
||||||
wrapper.__original_name__ = name
|
wrapper.__original_name__ = name
|
||||||
|
|
||||||
return wrapper
|
return wrapper
|
||||||
|
|
||||||
return decorator
|
return decorator
|
||||||
|
|
||||||
|
|
||||||
@ -156,9 +156,9 @@ class GuildCommandGroup(app_commands.Group):
|
|||||||
"""
|
"""
|
||||||
A command group that supports guild-specific name customization.
|
A command group that supports guild-specific name customization.
|
||||||
Usage:
|
Usage:
|
||||||
|
|
||||||
my_group = GuildCommandGroup(name="mygroup", description="My group description")
|
my_group = GuildCommandGroup(name="mygroup", description="My group description")
|
||||||
|
|
||||||
@my_group.command(name="subcommand", description="Subcommand description")
|
@my_group.command(name="subcommand", description="Subcommand description")
|
||||||
async def my_subcommand(interaction: discord.Interaction):
|
async def my_subcommand(interaction: discord.Interaction):
|
||||||
...
|
...
|
||||||
@ -166,7 +166,7 @@ class GuildCommandGroup(app_commands.Group):
|
|||||||
def __init__(self, name: str, description: str, **kwargs):
|
def __init__(self, name: str, description: str, **kwargs):
|
||||||
super().__init__(name=name, description=description, **kwargs)
|
super().__init__(name=name, description=description, **kwargs)
|
||||||
self.__original_name__ = name
|
self.__original_name__ = name
|
||||||
|
|
||||||
async def get_guild_name(self, guild_id: int) -> str:
|
async def get_guild_name(self, guild_id: int) -> str:
|
||||||
"""Get the guild-specific name for this group."""
|
"""Get the guild-specific name for this group."""
|
||||||
custom_name = await settings_manager.get_custom_group_name(guild_id, self.__original_name__)
|
custom_name = await settings_manager.get_custom_group_name(guild_id, self.__original_name__)
|
||||||
@ -190,12 +190,12 @@ async def register_all_guild_commands(bot) -> Dict[int, List[app_commands.Comman
|
|||||||
"""
|
"""
|
||||||
syncer = GuildCommandSyncer(bot)
|
syncer = GuildCommandSyncer(bot)
|
||||||
results = {}
|
results = {}
|
||||||
|
|
||||||
for guild in bot.guilds:
|
for guild in bot.guilds:
|
||||||
try:
|
try:
|
||||||
results[guild.id] = await syncer.sync_guild_commands(guild)
|
results[guild.id] = await syncer.sync_guild_commands(guild)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
log.error(f"Failed to sync commands for guild {guild.id}: {e}")
|
log.error(f"Failed to sync commands for guild {guild.id}: {e}")
|
||||||
results[guild.id] = []
|
results[guild.id] = []
|
||||||
|
|
||||||
return results
|
return results
|
||||||
|
2
main.py
2
main.py
@ -13,7 +13,7 @@ from commands import load_all_cogs, reload_all_cogs
|
|||||||
from error_handler import handle_error, patch_discord_methods, store_interaction_content
|
from error_handler import handle_error, patch_discord_methods, store_interaction_content
|
||||||
from utils import reload_script
|
from utils import reload_script
|
||||||
import settings_manager # Import the settings manager
|
import settings_manager # Import the settings manager
|
||||||
import command_customization # Import command customization utilities
|
from discordbot import command_customization # Import command customization utilities
|
||||||
|
|
||||||
# Import the unified API service runner and the sync API module
|
# Import the unified API service runner and the sync API module
|
||||||
import sys
|
import sys
|
||||||
|
Loading…
x
Reference in New Issue
Block a user