From 7748e55a715afa2b3255bba57b9d7f4734f53cb1 Mon Sep 17 00:00:00 2001 From: ramforth Date: Tue, 18 Nov 2025 01:53:39 +0100 Subject: [PATCH] sdfghb --- filename | 75 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 75 insertions(+) create mode 100644 filename diff --git a/filename b/filename new file mode 100644 index 0000000..f2f4abf --- /dev/null +++ b/filename @@ -0,0 +1,75 @@ +import asyncio +from typing import Dict + +from chat_listener import TwitchBot +import security # To decrypt tokens +from config import settings # To get client_id and client_secret + +class ListenerManager: + def __init__(self): + # This dictionary will hold our running listener tasks. + # The key will be the user_id and the value will be the asyncio.Task. + self.active_listeners: Dict[int, Dict] = {} + print("ListenerManager initialized.") + + async def start_listener_for_user(self, user, websocket_manager): + """ + Starts a chat listener for a given user if one isn't already running. + """ + if user.id in self.active_listeners: + print(f"Listener for user {user.id} is already running.") + return + + # Guard Clause: Ensure the user has a valid platform ID required by twitchio. + if not user.platform_user_id: + print(f"ERROR: Cannot start listener for user {user.id}. Missing platform_user_id.") + return + + print(f"Starting listener for user {user.id} ({user.username})...") + + try: + tokens = security.decrypt_tokens(user.encrypted_tokens) + access_token = tokens['access_token'] + refresh_token = tokens['refresh_token'] + + # Initialize the bot object without credentials first. + bot = TwitchBot( + websocket_manager=websocket_manager, + db_user_id=user.id + ) + + # Create a task that runs our new start method with all credentials. + # If super().__init__ fails inside bot.start(), the exception will be + # caught by our try/except block here. + task = asyncio.create_task(bot.start( + access_token=access_token, refresh_token=refresh_token, + client_id=settings.TWITCH_CLIENT_ID, client_secret=settings.TWITCH_CLIENT_SECRET, + channel_name=user.username + )) + # Store both the task and the bot instance for graceful shutdown + self.active_listeners[user.id] = {"task": task, "bot": bot} + except Exception as e: + # This will catch errors during bot instantiation (e.g., bad token) + print(f"ERROR: Failed to instantiate or start listener for user {user.id}: {e}") + + async def stop_listener_for_user(self, user_id: int): + """Stops a chat listener for a given user.""" + if user_id not in self.active_listeners: + print(f"No active listener found for user {user_id}.") + return + + print(f"Stopping listener for user {user_id}...") + listener_info = self.active_listeners.pop(user_id) + task = listener_info["task"] + bot = listener_info["bot"] + + # Gracefully close the bot's connection + if bot and not bot.is_closed(): + await bot.close() + + # Cancel the asyncio task + task.cancel() + try: + await task + except asyncio.CancelledError: + print(f"Listener for user {user_id} successfully stopped.") \ No newline at end of file