|
1 | 1 | import os |
2 | | -import shlex |
3 | | -import subprocess |
4 | 2 | import base64 |
5 | 3 | import json |
6 | 4 | import datetime |
|
37 | 35 |
|
38 | 36 | WEBHOOK_URL = os.environ.get("SLACK_WEBHOOK_URL") |
39 | 37 | DEFAULT_CHANNEL = os.environ.get("SLACK_DEFAULT_CHANNEL", "C08NTG6CXL5") |
40 | | -AGENT_PAYLOAD_PATH = Path(os.environ.get("AGENT_PAYLOAD_PATH", "agent_payload.txt")) |
41 | | -AGENT_TRIGGER_COMMAND = os.environ.get("AGENT_TRIGGER_COMMAND") |
42 | 38 | CODE_GENERATOR_URL = os.environ.get("CODE_GENERATOR_URL", "http://code-generator:3030") |
43 | | -DEFAULT_AGENT_COMMAND = [ |
44 | | - "python3", |
45 | | - "-c", |
46 | | - "print('Agent trigger placeholder executed')", |
47 | | -] |
48 | | -AGENT_COMMAND = shlex.split(AGENT_TRIGGER_COMMAND) if AGENT_TRIGGER_COMMAND else DEFAULT_AGENT_COMMAND |
49 | 39 |
|
50 | 40 |
|
51 | 41 | # --- Public helper functions --- |
@@ -308,78 +298,94 @@ def handle_help(user, thread_ts=None, channel=None): |
308 | 298 |
|
309 | 299 | # --- Event Processing Logic --- |
310 | 300 | def process_events(client: SocketModeClient, req: SocketModeRequest): |
311 | | - if req.type != "events_api": |
312 | | - return |
313 | | - |
314 | | - client.send_socket_mode_response(SocketModeResponse(envelope_id=req.envelope_id)) |
315 | | - event = req.payload.get("event", {}) |
316 | | - if event.get("type") != "message" or event.get("subtype") is not None: |
317 | | - return |
318 | | - |
319 | | - # Get channel type - check if it's a DM or the default channel |
320 | | - channel = event.get("channel") |
321 | | - channel_type = event.get("channel_type") |
322 | | - |
323 | | - # Allow messages from default channel or DMs (im = direct message) |
324 | | - is_dm = channel_type == "im" |
325 | | - is_default_channel = channel == DEFAULT_CHANNEL |
326 | | - |
327 | | - if not (is_dm or is_default_channel): |
328 | | - return |
329 | | - |
330 | | - msg_ts = event.get("ts") |
331 | | - if msg_ts in processed_messages: |
332 | | - print(f"Skipping already processed message: {msg_ts}") |
333 | | - return |
334 | | - |
335 | | - processed_messages.add(msg_ts) |
336 | | - if len(processed_messages) > 1000: |
337 | | - oldest_ts = sorted(processed_messages)[0] |
338 | | - processed_messages.remove(oldest_ts) |
339 | | - |
340 | | - user = event.get("user") |
341 | | - bot_user_id = os.environ.get("SLACK_BOT_USER_ID", "U08P8KS8K25") |
342 | | - if user == bot_user_id: |
343 | | - print(f"Skipping message from bot itself ({bot_user_id}).") |
344 | | - return |
345 | | - |
346 | | - text = event.get("text", "").strip() |
347 | | - if not text.startswith("!"): |
348 | | - return |
349 | | - |
350 | | - command_full = text[1:] |
351 | | - command_parts = command_full.split() |
352 | | - main_command = command_parts[0] if command_parts else "" |
| 301 | + try: |
| 302 | + if req.type != "events_api": |
| 303 | + return |
353 | 304 |
|
354 | | - print( |
355 | | - f"Received command: '{command_full}' from user {user} " |
356 | | - f"in {'DM' if is_dm else f'channel {channel}'}" |
357 | | - ) |
| 305 | + client.send_socket_mode_response(SocketModeResponse(envelope_id=req.envelope_id)) |
| 306 | + event = req.payload.get("event", {}) |
| 307 | + if event.get("type") != "message" or event.get("subtype") is not None: |
| 308 | + return |
358 | 309 |
|
359 | | - # Get thread_ts - use the message timestamp to create/reply to thread |
360 | | - # For DMs, thread_ts is the same as msg_ts |
361 | | - thread_ts = event.get("thread_ts") or msg_ts |
362 | | - |
363 | | - # For DM responses, use the DM channel; otherwise use DEFAULT_CHANNEL |
364 | | - response_channel = channel if is_dm else DEFAULT_CHANNEL |
365 | | - |
366 | | - if main_command == "location": |
367 | | - handle_location(user, thread_ts, response_channel) |
368 | | - elif main_command == "testimage": |
369 | | - handle_testimage(user, thread_ts, response_channel) |
370 | | - elif main_command == "agent": |
371 | | - handle_agent(user, command_full, thread_ts, timeout=120, channel=response_channel) |
372 | | - elif main_command == "agent-debug": |
373 | | - handle_agent(user, command_full, thread_ts, timeout=1200, channel=response_channel) |
374 | | - elif main_command == "help": |
375 | | - handle_help(user, thread_ts, response_channel) |
376 | | - else: |
377 | | - send_slack_message( |
378 | | - response_channel, |
379 | | - text=f"❓ <@{user}> Unknown command: `{text}`. Try `!help`.", |
380 | | - thread_ts=thread_ts, |
| 310 | + # Get channel type - check if it's a DM or the default channel |
| 311 | + channel = event.get("channel") |
| 312 | + channel_type = event.get("channel_type") |
| 313 | + |
| 314 | + # Allow messages from default channel or DMs (im = direct message) |
| 315 | + is_dm = channel_type == "im" |
| 316 | + is_default_channel = channel == DEFAULT_CHANNEL |
| 317 | + |
| 318 | + if not (is_dm or is_default_channel): |
| 319 | + return |
| 320 | + |
| 321 | + msg_ts = event.get("ts") |
| 322 | + if msg_ts in processed_messages: |
| 323 | + print(f"Skipping already processed message: {msg_ts}") |
| 324 | + return |
| 325 | + |
| 326 | + processed_messages.add(msg_ts) |
| 327 | + if len(processed_messages) > 1000: |
| 328 | + oldest_ts = sorted(processed_messages)[0] |
| 329 | + processed_messages.remove(oldest_ts) |
| 330 | + |
| 331 | + user = event.get("user") |
| 332 | + bot_user_id = os.environ.get("SLACK_BOT_USER_ID", "U08P8KS8K25") |
| 333 | + if user == bot_user_id: |
| 334 | + print(f"Skipping message from bot itself ({bot_user_id}).") |
| 335 | + return |
| 336 | + |
| 337 | + text = event.get("text", "").strip() |
| 338 | + if not text.startswith("!"): |
| 339 | + return |
| 340 | + |
| 341 | + command_full = text[1:] |
| 342 | + command_parts = command_full.split() |
| 343 | + main_command = command_parts[0] if command_parts else "" |
| 344 | + |
| 345 | + print( |
| 346 | + f"Received command: '{command_full}' from user {user} " |
| 347 | + f"in {'DM' if is_dm else f'channel {channel}'}" |
381 | 348 | ) |
382 | 349 |
|
| 350 | + # Get thread_ts - use the message timestamp to create/reply to thread |
| 351 | + # For DMs, thread_ts is the same as msg_ts |
| 352 | + thread_ts = event.get("thread_ts") or msg_ts |
| 353 | + |
| 354 | + # For DM responses, use the DM channel; otherwise use DEFAULT_CHANNEL |
| 355 | + response_channel = channel if is_dm else DEFAULT_CHANNEL |
| 356 | + |
| 357 | + if main_command == "location": |
| 358 | + handle_location(user, thread_ts, response_channel) |
| 359 | + elif main_command == "testimage": |
| 360 | + handle_testimage(user, thread_ts, response_channel) |
| 361 | + elif main_command == "agent": |
| 362 | + handle_agent(user, command_full, thread_ts, timeout=120, channel=response_channel) |
| 363 | + elif main_command == "agent-debug": |
| 364 | + handle_agent(user, command_full, thread_ts, timeout=1200, channel=response_channel) |
| 365 | + elif main_command == "help": |
| 366 | + handle_help(user, thread_ts, response_channel) |
| 367 | + else: |
| 368 | + send_slack_message( |
| 369 | + response_channel, |
| 370 | + text=f"❓ <@{user}> Unknown command: `{text}`. Try `!help`.", |
| 371 | + thread_ts=thread_ts, |
| 372 | + ) |
| 373 | + except Exception as e: |
| 374 | + import traceback |
| 375 | + print(f"❌ Error processing event: {e}") |
| 376 | + traceback.print_exc() |
| 377 | + try: |
| 378 | + # Try to notify the user about the error |
| 379 | + if 'user' in locals() and 'response_channel' in locals(): |
| 380 | + send_slack_message( |
| 381 | + response_channel, |
| 382 | + text=f"❌ <@{user}> An error occurred while processing your command. Please try again later.", |
| 383 | + thread_ts=locals().get('thread_ts') |
| 384 | + ) |
| 385 | + except: |
| 386 | + # If even error notification fails, just log it |
| 387 | + print("Failed to send error notification to Slack") |
| 388 | + |
383 | 389 |
|
384 | 390 | # --- Main Execution --- |
385 | 391 | if __name__ == "__main__": |
|
0 commit comments