Skip to content

Commit 0231d01

Browse files
committed
Refactor Discord bot to use slash commands and added ephemeral messages
Migrates Discord bot commands from legacy prefix-based to modern slash commands using discord.py app_commands. Refactors DevRelCommands cog to use slash commands, improves token cleanup task management, and updates verification flows for ephemeral responses. Discord bot now loads cogs dynamically during async startup, and the Discord dependency is added to pyproject.toml.
1 parent 1356976 commit 0231d01

File tree

4 files changed

+102
-223
lines changed

4 files changed

+102
-223
lines changed

backend/integrations/discord/bot.py

Lines changed: 28 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -18,16 +18,14 @@ def __init__(self, queue_manager: AsyncQueueManager, **kwargs):
1818
intents.dm_messages = True
1919

2020
super().__init__(
21-
command_prefix="!",
21+
command_prefix=None,
2222
intents=intents,
2323
**kwargs
2424
)
2525

2626
self.queue_manager = queue_manager
2727
self.classifier = ClassificationRouter()
28-
self.active_threads: Dict[str, str] = {} # user_id -> thread_id mapping
29-
30-
# Register queue handlers
28+
self.active_threads: Dict[str, str] = {}
3129
self._register_queue_handlers()
3230

3331
def _register_queue_handlers(self):
@@ -38,16 +36,18 @@ async def on_ready(self):
3836
"""Bot ready event"""
3937
logger.info(f'Enhanced Discord bot logged in as {self.user}')
4038
print(f'Bot is ready! Logged in as {self.user}')
39+
try:
40+
synced = await self.tree.sync()
41+
print(f"Synced {len(synced)} slash command(s)")
42+
except Exception as e:
43+
print(f"Failed to sync slash commands: {e}")
4144

4245
async def on_message(self, message):
43-
"""Enhanced message handling with classification"""
46+
"""Handles regular chat messages, but ignores slash commands."""
4447
if message.author == self.user:
4548
return
4649

47-
# if message is a command (starts with !)
48-
ctx = await self.get_context(message)
49-
if ctx.command is not None:
50-
await self.invoke(ctx)
50+
if message.interaction_metadata is not None:
5151
return
5252

5353
try:
@@ -60,23 +60,18 @@ async def on_message(self, message):
6060
}
6161
)
6262

63-
logger.info(f"Message triage result: {triage_result}")
64-
6563
if triage_result.get("needs_devrel", False):
6664
await self._handle_devrel_message(message, triage_result)
6765

6866
except Exception as e:
6967
logger.error(f"Error processing message: {str(e)}")
70-
68+
7169
async def _handle_devrel_message(self, message, triage_result: Dict[str, Any]):
72-
"""Handle messages that need DevRel intervention"""
70+
"""This now handles both new requests and follow-ups in threads."""
7371
try:
7472
user_id = str(message.author.id)
75-
76-
# Get or create thread for this user
7773
thread_id = await self._get_or_create_thread(message, user_id)
78-
79-
# Prepare message for agent processing
74+
8075
agent_message = {
8176
"type": "devrel_request",
8277
"id": f"discord_{message.id}",
@@ -93,93 +88,55 @@ async def _handle_devrel_message(self, message, triage_result: Dict[str, Any]):
9388
"display_name": message.author.display_name
9489
}
9590
}
96-
97-
# Determine priority based on triage
98-
priority_map = {
99-
"high": QueuePriority.HIGH,
100-
"medium": QueuePriority.MEDIUM,
101-
"low": QueuePriority.LOW
91+
priority_map = {"high": QueuePriority.HIGH,
92+
"medium": QueuePriority.MEDIUM,
93+
"low": QueuePriority.LOW
10294
}
10395
priority = priority_map.get(triage_result.get("priority"), QueuePriority.MEDIUM)
104-
105-
# Enqueue for agent processing
10696
await self.queue_manager.enqueue(agent_message, priority)
10797

108-
# Send acknowledgment in thread
98+
# --- "PROCESSING" MESSAGE RESTORED ---
10999
if thread_id:
110100
thread = self.get_channel(int(thread_id))
111101
if thread:
112102
await thread.send("I'm processing your request, please hold on...")
113-
103+
# ------------------------------------
104+
114105
except Exception as e:
115106
logger.error(f"Error handling DevRel message: {str(e)}")
116107

117108
async def _get_or_create_thread(self, message, user_id: str) -> Optional[str]:
118-
"""Get existing thread or create new one for user"""
119109
try:
120-
# Check if user already has an active thread
121110
if user_id in self.active_threads:
122111
thread_id = self.active_threads[user_id]
123112
thread = self.get_channel(int(thread_id))
124-
125-
# Verify thread still exists and is active
126113
if thread and not thread.archived:
127114
return thread_id
128115
else:
129116
del self.active_threads[user_id]
130-
logger.info(f"Cleaned up archived thread for user {user_id}")
131-
132-
# Create new thread
133-
thread_name = f"DevRel Chat - {message.author.display_name}"
134-
117+
118+
# This part only runs if it's not a follow-up message in an active thread.
135119
if isinstance(message.channel, discord.TextChannel):
136-
thread = await message.create_thread(
137-
name=thread_name,
138-
auto_archive_duration=60 # 1 hour
139-
)
140-
141-
# Store thread mapping
120+
thread_name = f"DevRel Chat - {message.author.display_name}"
121+
thread = await message.create_thread(name=thread_name, auto_archive_duration=60)
142122
self.active_threads[user_id] = str(thread.id)
143-
144-
# Send welcome message
145-
await thread.send(
146-
f"Hello {message.author.mention}! 👋\n"
147-
f"I'm your DevRel assistant. I can help you with:\n"
148-
f"• Technical questions about Devr.AI\n"
149-
f"• Getting started and onboarding\n"
150-
f"• Searching for information on the web\n"
151-
f"• General developer support\n\n"
152-
f"This thread keeps our conversation organized!"
153-
)
154-
123+
await thread.send(f"Hello {message.author.mention}! I've created this thread to help you. How can I assist?")
155124
return str(thread.id)
156-
157125
except Exception as e:
158-
logger.error(f"Failed to create thread: {str(e)}")
159-
160-
return str(message.channel.id) # Fallback to original channel
126+
logger.error(f"Failed to create thread: {e}")
127+
return str(message.channel.id)
161128

162129
async def _handle_agent_response(self, response_data: Dict[str, Any]):
163-
"""Handle response from DevRel agent"""
164130
try:
165131
thread_id = response_data.get("thread_id")
166132
response_text = response_data.get("response", "")
167-
168133
if not thread_id or not response_text:
169-
logger.warning("Invalid agent response data")
170134
return
171-
172135
thread = self.get_channel(int(thread_id))
173136
if thread:
174-
# Split long responses into multiple messages
175-
if len(response_text) > 2000:
176-
chunks = [response_text[i:i+2000] for i in range(0, len(response_text), 2000)]
177-
for chunk in chunks:
178-
await thread.send(chunk)
179-
else:
180-
await thread.send(response_text)
137+
for i in range(0, len(response_text), 2000):
138+
await thread.send(response_text[i:i+2000])
181139
else:
182140
logger.error(f"Thread {thread_id} not found for agent response")
183-
184141
except Exception as e:
185-
logger.error(f"Error handling agent response: {str(e)}")
142+
logger.error(f"Error handling agent response: {str(e)}")

0 commit comments

Comments
 (0)