Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
71 commits
Select commit Hold shift + click to select a range
56e44f8
pop up mode and chat buble toggle
pladisdev Nov 2, 2025
82db2b0
potential audio fix
pladisdev Nov 2, 2025
579683d
linux sh and better docker support
pladisdev Nov 2, 2025
fad6d1a
fixed linux build?
pladisdev Nov 2, 2025
a12de82
linux fix part 2
pladisdev Nov 2, 2025
5d79afe
docker fix part 1
pladisdev Nov 2, 2025
0f3af89
Initial plan
Copilot Nov 2, 2025
d5d90f6
Initial plan
Copilot Nov 2, 2025
cbf5fcd
Initial plan
Copilot Nov 2, 2025
5a5d1d5
Initial plan
Copilot Nov 2, 2025
207ba9b
Initial plan
Copilot Nov 2, 2025
76b9912
Initial plan
Copilot Nov 2, 2025
366b640
Initial plan
Copilot Nov 2, 2025
ebc7bb7
Update frontend/src/pages/YappersPage.jsx
pladisdev Nov 2, 2025
be9a086
Initial plan
Copilot Nov 2, 2025
3fc9146
Update frontend/src/pages/YappersPage.jsx
pladisdev Nov 2, 2025
914b789
Replace sys.platform with platform.system() for OS detection
Copilot Nov 2, 2025
938886f
Fix race condition in popup avatar lifecycle
Copilot Nov 2, 2025
7737a2f
Extract magic numbers to named constants for better readability
Copilot Nov 2, 2025
3ea0d45
Extract magic number -2.5px into avatarActiveOffset setting
Copilot Nov 2, 2025
ee4de2a
Fix audio cleanup in popup mode when play() fails
Copilot Nov 2, 2025
3ae0527
Merge pull request #17 from pladisdev/copilot/sub-pr-8-bf786502-ac5d-…
pladisdev Nov 2, 2025
25dc303
Extract hex opacity calculation to utility function
Copilot Nov 2, 2025
730dc88
Fix audio error handlers to clean up tracking references
Copilot Nov 2, 2025
bb266bd
Merge pull request #16 from pladisdev/copilot/sub-pr-8-4be2dd0e-06ec-…
pladisdev Nov 2, 2025
7d70a13
Merge pull request #15 from pladisdev/copilot/sub-pr-8-9e407134-0238-…
pladisdev Nov 2, 2025
d1f450d
Merge pull request #14 from pladisdev/copilot/sub-pr-8-please-work
pladisdev Nov 2, 2025
5436727
Merge pull request #13 from pladisdev/copilot/sub-pr-8-one-more-time
pladisdev Nov 2, 2025
d8c850e
Merge pull request #12 from pladisdev/copilot/sub-pr-8-yet-again
pladisdev Nov 2, 2025
1405787
Merge pull request #11 from pladisdev/copilot/sub-pr-8-another-one
pladisdev Nov 2, 2025
1ad53b1
Merge pull request #10 from pladisdev/copilot/sub-pr-8-again
pladisdev Nov 2, 2025
3956aed
Merge branch 'main' into development
pladisdev Nov 2, 2025
a0b1f82
update flow for builds
pladisdev Nov 2, 2025
a2d0cea
Merge branch 'main' into development
pladisdev Nov 2, 2025
6adf5b1
better build and release file
pladisdev Nov 2, 2025
57df8ef
workflow fix
pladisdev Nov 2, 2025
6bbabff
Merge branch 'main' into development
pladisdev Nov 2, 2025
7672520
build fix
pladisdev Nov 2, 2025
d56e12e
Merge branch 'development' of https://github.com/pladisdev/chat-yappe…
pladisdev Nov 2, 2025
5aca8cf
Merge branch 'main' into development
pladisdev Nov 2, 2025
f0cb455
usernames in chat bubbles
pladisdev Nov 6, 2025
dd0ffab
Merge branch 'development' of https://github.com/pladisdev/chat-yappe…
pladisdev Nov 6, 2025
4f534c8
twitch authentifcation
pladisdev Nov 6, 2025
9095db5
Merge branch 'main' into development
pladisdev Nov 6, 2025
979acca
tts limit
pladisdev Nov 22, 2025
008f0e0
notifcation that user needs to click page, quick status
pladisdev Nov 22, 2025
c09bdcc
update readme, version
pladisdev Nov 22, 2025
1cb53f6
Merge branch 'main' into development
pladisdev Nov 22, 2025
ee60426
emergency twitch fix
pladisdev Nov 22, 2025
56967e2
Merge branch 'main' into development
pladisdev Nov 22, 2025
cfcf2dd
Merge branch 'main' into development
pladisdev Nov 22, 2025
1aa6813
yep
pladisdev Nov 22, 2025
5844084
dang
pladisdev Nov 22, 2025
4a6a8e5
better twitch logging
pladisdev Nov 23, 2025
693bfbc
animations and avatar layout editor
pladisdev Nov 23, 2025
326928e
fix spin animation
pladisdev Nov 23, 2025
a80e583
twitch fix part 2
pladisdev Nov 23, 2025
69800d3
Merge branch 'main' into development
pladisdev Nov 23, 2025
365ef8e
twitch fix, better fonts, cleanup
pladisdev Nov 25, 2025
61d9dcf
Merge branch 'main' into development
pladisdev Nov 25, 2025
046c52f
fixed imports
pladisdev Nov 25, 2025
7b33d13
fixed things
pladisdev Nov 25, 2025
638fb4e
Merge branch 'main' into development
pladisdev Nov 25, 2025
59a7722
undefined fix
pladisdev Nov 25, 2025
4a09f0b
twitch test fix
pladisdev Nov 25, 2025
99b9642
another mock fix
pladisdev Nov 25, 2025
15efb3c
another fix for twitch creds tests
pladisdev Nov 25, 2025
6ca3832
better logging
pladisdev Nov 25, 2025
08355e7
twitch fixes?
pladisdev Nov 25, 2025
0d7bb86
another twitch fix
pladisdev Nov 25, 2025
484caaf
Merge branch 'main' into development
pladisdev Nov 25, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
132 changes: 77 additions & 55 deletions backend/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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]}")
Copy link

Copilot AI Nov 25, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Debug logging statement appears to be left in production code. The "[EVENT ROUTER]" prefix and verbose logging suggest this was added for debugging. Consider removing this line or reducing its log level to logger.debug() if it's intended for troubleshooting purposes only.

Suggested change
logger.info(f"[EVENT ROUTER] Received event: type={e.get('type')}, user={e.get('user')}, text={e.get('text', '')[:50]}")
logger.debug(f"[EVENT ROUTER] Received event: type={e.get('type')}, user={e.get('user')}, text={e.get('text', '')[:50]}")

Copilot uses AI. Check for mistakes.
event_type = e.get("type", "")
if event_type == "moderation":
await handle_moderation_event(e)
Expand Down Expand Up @@ -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)

Expand All @@ -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)

# 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]}")
Copy link

Copilot AI Nov 25, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Duplicate debug logging statement. This appears to be the same debug log as line 521 in the restart function. Consider removing this line or reducing its log level to logger.debug() if it's intended for troubleshooting purposes only.

Suggested change
logger.info(f"[EVENT ROUTER] Received event: type={e.get('type')}, user={e.get('user')}, text={e.get('text', '')[:50]}")
logger.debug(f"[EVENT ROUTER] Received event: type={e.get('type')}, user={e.get('user')}, text={e.get('text', '')[:50]}")

Copilot uses AI. Check for mistakes.
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)")
Expand Down
2 changes: 1 addition & 1 deletion deployment/ChatYapper.wxs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
<!-- Product Definition -->
<Package Name="Chat Yapper"
Manufacturer="Pladis Development"
Version="1.3.0"
Version="1.3.1"
UpgradeCode="A1B2C3D4-E5F6-7890-ABCD-EF1234567890"
Language="1033"
Compressed="yes"
Expand Down
Loading