-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathsync_commands.py
More file actions
133 lines (110 loc) · 4.6 KB
/
Copy pathsync_commands.py
File metadata and controls
133 lines (110 loc) · 4.6 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
"""
Sync Discord slash commands manually.
Run this after making changes to commands or when commands need to be updated in Discord.
"""
import asyncio
import discord
from discord.ext import commands
import logging
from bot.utils.config import Config
# Configure logging
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s'
)
logger = logging.getLogger("CommandSync")
class SyncBot(commands.Bot):
"""Minimal bot for command syncing."""
def __init__(self):
intents = discord.Intents.default()
super().__init__(command_prefix="!", intents=intents)
self.synced = False
async def setup_hook(self):
"""Load all cogs to register commands."""
logger.info("Loading cogs to register commands...")
# Load all active cogs (needed to register commands)
cogs = [
"bot.cogs.setup_gui",
"bot.cogs.server_monitor",
"bot.cogs.chat_relay",
"bot.cogs.help_commands",
"bot.cogs.server_management",
"bot.cogs.rcon_admin",
"bot.cogs.log_viewer",
"bot.cogs.player_management",
"bot.cogs.economy",
"bot.cogs.shop",
"bot.cogs.bot_control",
"bot.cogs.remote_agent", # CRITICAL: Load before remote_agent_gui
"bot.cogs.remote_agent_gui",
"bot.cogs.mod_management",
"bot.cogs.ini_management",
"bot.cogs.ask_phoenix",
"bot.cogs.games",
"bot.cogs.shopcfg_gui",
"bot.cogs.maintenance_gui",
"bot.cogs.subscription",
"bot.cogs.kit_management",
"bot.cogs.kits",
"bot.cogs.analytics_dashboard",
"bot.cogs.server_service", # Phase 16: ARK server service management
]
for cog in cogs:
try:
await self.load_extension(cog)
logger.info(f"Loaded cog: {cog}")
# ANTI-RATE LIMIT: Small pause to let event loop breathe
await asyncio.sleep(0.1)
except Exception as e:
logger.error(f"Failed to load cog {cog}: {e}")
logger.info(f"All cogs loaded. Total commands: {len(self.tree.get_commands())}")
async def on_ready(self):
"""Sync commands when ready."""
if not self.synced:
logger.info(f"Logged in as {self.user}")
logger.info("Starting command sync...")
try:
if Config.DISCORD_GUILD_ID:
guild = discord.Object(id=Config.DISCORD_GUILD_ID)
# Step 1: Sync guild-scoped commands
self.tree.copy_global_to(guild=guild)
synced = await self.tree.sync(guild=guild)
logger.info(f"✅ Synced {len(synced)} commands to guild {Config.DISCORD_GUILD_ID}")
# Step 2: Clear stale global commands (fixes duplicate command issue)
self.tree.clear_commands(guild=None)
await self.tree.sync()
logger.info("✅ Cleared global commands (removes duplicates visible globally)")
else:
# Sync globally (takes up to 1 hour to propagate)
synced = await self.tree.sync()
logger.info(f"✅ Synced {len(synced)} commands globally")
self.synced = True
logger.info("Command sync complete! Bot can now respond to slash commands.")
except discord.HTTPException as e:
if e.status == 429:
logger.error(f"❌ Rate limited! Retry after {e.response.headers.get('Retry-After', 'unknown')} seconds")
else:
logger.error(f"❌ HTTP error during sync: {e}")
except Exception as e:
logger.error(f"❌ Failed to sync commands: {e}")
finally:
# Close after syncing
await asyncio.sleep(2)
await self.close()
async def main():
"""Main sync function."""
logger.info("=" * 60)
logger.info("Discord Command Sync Tool")
logger.info("=" * 60)
bot = SyncBot()
try:
await bot.start(Config.DISCORD_BOT_TOKEN)
except KeyboardInterrupt:
logger.info("Sync cancelled by user")
except Exception as e:
logger.error(f"Error during sync: {e}")
finally:
if not bot.is_closed():
await bot.close()
if __name__ == "__main__":
asyncio.run(main())