-
Notifications
You must be signed in to change notification settings - Fork 0
Development #35
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Development #35
Changes from all commits
56e44f8
82db2b0
579683d
fad6d1a
a12de82
5d79afe
0f3af89
d5d90f6
cbf5fcd
5a5d1d5
207ba9b
76b9912
366b640
ebc7bb7
be9a086
3fc9146
914b789
938886f
7737a2f
3ea0d45
ee4de2a
3ae0527
25dc303
730dc88
bb266bd
7d70a13
d1f450d
5436727
d8c850e
1405787
1ad53b1
3956aed
a0b1f82
a2d0cea
6adf5b1
57df8ef
6bbabff
7672520
d56e12e
5aca8cf
f0cb455
dd0ffab
4f534c8
9095db5
979acca
008f0e0
c09bdcc
1cb53f6
ee60426
56967e2
cfcf2dd
1aa6813
5844084
4a6a8e5
693bfbc
326928e
a80e583
69800d3
365ef8e
61d9dcf
046c52f
7b33d13
638fb4e
59a7722
4a09f0b
99b9642
15efb3c
6ca3832
08355e7
0d7bb86
484caaf
a45dcfc
478e8ea
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -488,6 +488,11 @@ async def restart_twitch_if_needed(settings: Dict[str, Any]): | |
|
|
||
| # Start new task if enabled | ||
| if run_twitch_bot and settings.get("twitch", {}).get("enabled"): | ||
| # Double-check no task is still running (prevent duplicate starts) | ||
| if TwitchTask and not TwitchTask.done(): | ||
| logger.warning("Twitch bot task still running, skipping restart") | ||
| return | ||
|
|
||
| logger.info("Restarting Twitch bot with new settings") | ||
|
|
||
| # Get OAuth token from database | ||
|
|
@@ -508,8 +513,12 @@ async def restart_twitch_if_needed(settings: Dict[str, Any]): | |
| TwitchTask = None | ||
| return | ||
|
|
||
| # Give the test connection time to fully release the EventSub server port | ||
| await asyncio.sleep(0.3) | ||
|
|
||
| # Event router to handle different event types | ||
| async def route_twitch_event(e): | ||
| logger.info(f"[EVENT ROUTER] Received event: type={e.get('type')}, user={e.get('user')}, text={e.get('text', '')[:50]}") | ||
| event_type = e.get("type", "") | ||
| if event_type == "moderation": | ||
| await handle_moderation_event(e) | ||
|
|
@@ -1532,6 +1541,12 @@ def custom_exception_handler(loop, context): | |
| # This is an expected error during TwitchIO bot shutdown - don't log it | ||
| return | ||
|
|
||
| # Suppress port binding errors from duplicate bot starts (Errno 10048) | ||
| if isinstance(exception, OSError): | ||
| if "10048" in str(exception) or "address already in use" in str(exception).lower(): | ||
| # Port conflict from duplicate bot start - already logged elsewhere | ||
| return | ||
|
|
||
| # For all other exceptions, use the default handler | ||
| loop.default_exception_handler(context) | ||
|
|
||
|
|
@@ -1553,64 +1568,71 @@ async def startup(): | |
| logger.info(f"Settings loaded, Twitch enabled: {settings.get('twitch', {}).get('enabled')}") | ||
|
|
||
| if run_twitch_bot and settings.get("twitch", {}).get("enabled"): | ||
| logger.info("Starting Twitch bot...") | ||
|
|
||
| # Get OAuth token from database (with automatic refresh if needed) | ||
| token_info = await get_twitch_token_for_bot() | ||
| if not token_info: | ||
| # Check if auth exists at all to provide better error message | ||
| from modules.persistent_data import get_auth | ||
| existing_auth = get_auth() | ||
| # Check if bot is already running (prevent duplicate starts) | ||
| global TwitchTask | ||
| if TwitchTask and not TwitchTask.done(): | ||
| logger.warning("Twitch bot already running, skipping startup initialization") | ||
| else: | ||
| logger.info("Starting Twitch bot...") | ||
|
|
||
| if existing_auth: | ||
| # Auth exists but token refresh failed or token expired without refresh token | ||
| logger.error("Twitch token expired and could not be refreshed. Please reconnect your Twitch account.") | ||
| # Get OAuth token from database (with automatic refresh if needed) | ||
| token_info = await get_twitch_token_for_bot() | ||
| if not token_info: | ||
| # Check if auth exists at all to provide better error message | ||
| from modules.persistent_data import get_auth | ||
| existing_auth = get_auth() | ||
|
|
||
| # Broadcast error to frontend | ||
| global twitch_auth_error | ||
| twitch_auth_error = { | ||
| "type": "twitch_auth_error", | ||
| "message": "Your Twitch connection has expired. Please reconnect your account in settings.", | ||
| "error": "Token expired and refresh failed" | ||
| } | ||
| await hub.broadcast(twitch_auth_error) | ||
| else: | ||
| # No auth exists at all | ||
| logger.warning("No Twitch OAuth token found. Please connect your Twitch account.") | ||
| return | ||
| if existing_auth: | ||
| # Auth exists but token refresh failed or token expired without refresh token | ||
| logger.error("Twitch token expired and could not be refreshed. Please reconnect your Twitch account.") | ||
|
|
||
| # Broadcast error to frontend | ||
| global twitch_auth_error | ||
| twitch_auth_error = { | ||
| "type": "twitch_auth_error", | ||
| "message": "Your Twitch connection has expired. Please reconnect your account in settings.", | ||
| "error": "Token expired and refresh failed" | ||
| } | ||
| await hub.broadcast(twitch_auth_error) | ||
| else: | ||
| # No auth exists at all | ||
| logger.warning("No Twitch OAuth token found. Please connect your Twitch account.") | ||
| return | ||
|
|
||
| twitch_config = settings.get("twitch", {}) | ||
| channel = twitch_config.get("channel") or token_info["username"] | ||
|
|
||
| twitch_config = settings.get("twitch", {}) | ||
| channel = twitch_config.get("channel") or token_info["username"] | ||
|
|
||
| logger.info(f"Twitch config: channel={channel}, nick={token_info['username']} (displayed as Chat Yapper), token={'***' if token_info['token'] else 'None'}") | ||
|
|
||
| # Test Twitch connection first to detect auth issues early | ||
| connection_test_passed = await test_twitch_connection(token_info) | ||
|
|
||
| if not connection_test_passed: | ||
| logger.warning("Twitch connection test failed - not starting full bot") | ||
| # Don't return here, let the auth error be handled by the test function | ||
| # The error will already be broadcast to clients | ||
| return | ||
|
|
||
| # Event router to handle different event types | ||
| async def route_twitch_event(e): | ||
| event_type = e.get("type", "") | ||
| if event_type == "moderation": | ||
| await handle_moderation_event(e) | ||
| else: | ||
| # Default to chat event handler | ||
| await handle_event(e) | ||
|
|
||
| global TwitchTask | ||
|
|
||
| # Create Twitch bot task with shared error handling | ||
| TwitchTask = await create_twitch_bot_task( | ||
| token_info=token_info, | ||
| channel=channel, | ||
| route_twitch_event=route_twitch_event, | ||
| context_name="startup" | ||
| ) | ||
| logger.info(f"Twitch config: channel={channel}, nick={token_info['username']} (displayed as Chat Yapper), token={'***' if token_info['token'] else 'None'}") | ||
|
|
||
| # Test Twitch connection first to detect auth issues early | ||
| connection_test_passed = await test_twitch_connection(token_info) | ||
|
|
||
| if not connection_test_passed: | ||
| logger.warning("Twitch connection test failed - not starting full bot") | ||
| # Don't return here, let the auth error be handled by the test function | ||
| # The error will already be broadcast to clients | ||
| return | ||
|
|
||
| # Give the test connection time to fully release the EventSub server port | ||
| await asyncio.sleep(0.3) | ||
|
Comment on lines
+1616
to
+1617
|
||
|
|
||
| # Event router to handle different event types | ||
| async def route_twitch_event(e): | ||
| logger.info(f"[EVENT ROUTER] Received event: type={e.get('type')}, user={e.get('user')}, text={e.get('text', '')[:50]}") | ||
| event_type = e.get("type", "") | ||
| if event_type == "moderation": | ||
| await handle_moderation_event(e) | ||
| else: | ||
| # Default to chat event handler | ||
| await handle_event(e) | ||
|
|
||
| # Create Twitch bot task with shared error handling | ||
| TwitchTask = await create_twitch_bot_task( | ||
| token_info=token_info, | ||
| channel=channel, | ||
| route_twitch_event=route_twitch_event, | ||
| context_name="startup" | ||
| ) | ||
| else: | ||
| if not run_twitch_bot: | ||
| logger.warning("Twitch bot not available (import failed)") | ||
|
|
||
| Original file line number | Diff line number | Diff line change | ||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -331,8 +331,11 @@ async def event_ready(self): | |||||||||||||||
| who = getattr(self, "nick", None) or self._nick or "unknown" | ||||||||||||||||
| try: | ||||||||||||||||
| logger.info(f"Twitch bot ready as {who}, listening to {self.channel_name}") | ||||||||||||||||
| except Exception: | ||||||||||||||||
| pass | ||||||||||||||||
| # Join the channel to start receiving messages (required in TwitchIO 3.x) | ||||||||||||||||
| await self.join_channels([self.channel_name]) | ||||||||||||||||
| logger.info(f"Joined channel: {self.channel_name}") | ||||||||||||||||
|
Comment on lines
+334
to
+336
|
||||||||||||||||
| # Join the channel to start receiving messages (required in TwitchIO 3.x) | |
| await self.join_channels([self.channel_name]) | |
| logger.info(f"Joined channel: {self.channel_name}") | |
| # Only join manually for TwitchIO 3.x; 2.x and earlier join via initial_channels | |
| if self._major == 3: | |
| await self.join_channels([self.channel_name]) | |
| logger.info(f"Joined channel: {self.channel_name}") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Magic number: The sleep duration
0.3seconds lacks explanation. Consider adding a comment explaining why this specific duration is needed for port release, or extract it as a named constant (e.g.,PORT_RELEASE_DELAY = 0.3) to improve maintainability.