From fc8d1770cd2c906d4f1f604d17735d7646ed1605 Mon Sep 17 00:00:00 2001 From: dmunozv04 <39565245+dmunozv04@users.noreply.github.com> Date: Sat, 3 May 2025 21:42:13 +0200 Subject: [PATCH 1/5] Improve watchdog --- src/iSponsorBlockTV/ytlounge.py | 65 +++++++++++++++++++++++++-------- 1 file changed, 49 insertions(+), 16 deletions(-) diff --git a/src/iSponsorBlockTV/ytlounge.py b/src/iSponsorBlockTV/ytlounge.py index 1830905..0329258 100644 --- a/src/iSponsorBlockTV/ytlounge.py +++ b/src/iSponsorBlockTV/ytlounge.py @@ -30,6 +30,8 @@ class YtLoungeApi(pyytlounge.YtLoungeApi): self.logger = logger self.shorts_disconnected = False self.auto_play = True + self.watchdog_running = False + self.last_event_time = 0 if config: self.mute_ads = config.mute_ads self.skip_ads = config.skip_ads @@ -38,21 +40,56 @@ class YtLoungeApi(pyytlounge.YtLoungeApi): # Ensures that we still are subscribed to the lounge async def _watchdog(self): - await asyncio.sleep( - 35 - ) # YouTube sends at least a message every 30 seconds (no-op or any other) + """ + Continuous watchdog that monitors for connection health. + If no events are received within the expected timeframe, + it cancels the current subscription. + """ + self.watchdog_running = True + self.last_event_time = asyncio.get_event_loop().time() + try: - self.subscribe_task.cancel() - except BaseException: - pass + while self.watchdog_running: + await asyncio.sleep(10) + current_time = asyncio.get_event_loop().time() + time_since_last_event = current_time - self.last_event_time + + # YouTube sends a message at least every 30 seconds + if time_since_last_event > 60: + self.logger.debug(f"Watchdog triggered: No events for {time_since_last_event:.1f} seconds") + + # Cancel current subscription + if self.subscribe_task and not self.subscribe_task.done(): + self.subscribe_task.cancel() + await asyncio.sleep(1) # Give it time to cancel + except asyncio.CancelledError: + self.logger.debug("Watchdog task cancelled") + self.watchdog_running = False + except BaseException as e: + self.logger.error(f"Watchdog error: {e}") + self.watchdog_running = False # Subscribe to the lounge and start the watchdog async def subscribe_monitored(self, callback): self.callback = callback - try: + + # Stop existing watchdog if running + if self.subscribe_task_watchdog and not self.subscribe_task_watchdog.done(): + self.watchdog_running = False self.subscribe_task_watchdog.cancel() - except BaseException: - pass # No watchdog task + try: + await self.subscribe_task_watchdog + except (asyncio.CancelledError, Exception): + pass + + # Start new subscription + if self.subscribe_task and not self.subscribe_task.done(): + self.subscribe_task.cancel() + try: + await self.subscribe_task + except (asyncio.CancelledError, Exception): + pass + self.subscribe_task = asyncio.create_task(super().subscribe(callback)) self.subscribe_task_watchdog = asyncio.create_task(self._watchdog()) return self.subscribe_task @@ -61,13 +98,9 @@ class YtLoungeApi(pyytlounge.YtLoungeApi): # skipcq: PY-R1000 def _process_event(self, event_type: str, args: List[Any]): self.logger.debug(f"process_event({event_type}, {args})") - # (Re)start the watchdog - try: - self.subscribe_task_watchdog.cancel() - except BaseException: - pass - finally: - self.subscribe_task_watchdog = asyncio.create_task(self._watchdog()) + # Update last event time for the watchdog + self.last_event_time = asyncio.get_event_loop().time() + # A bunch of events useful to detect ads playing, # and the next video before it starts playing # (that way we can get the segments) From a9d64af2ac3a0892fb50237567dd3cace4a0eaa8 Mon Sep 17 00:00:00 2001 From: dmunozv04 <39565245+dmunozv04@users.noreply.github.com> Date: Sat, 10 May 2025 18:27:18 +0200 Subject: [PATCH 2/5] Fix muting not working --- src/iSponsorBlockTV/ytlounge.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/iSponsorBlockTV/ytlounge.py b/src/iSponsorBlockTV/ytlounge.py index 0329258..65a1a5c 100644 --- a/src/iSponsorBlockTV/ytlounge.py +++ b/src/iSponsorBlockTV/ytlounge.py @@ -118,7 +118,7 @@ class YtLoungeApi(pyytlounge.YtLoungeApi): create_task(self.mute(False, override=True)) elif event_type == "onAdStateChange": data = args[0] - if data["adState"] == "0": # Ad is not playing + if data["adState"] == "0" and data["currentTime"] != 0: # Ad is not playing self.logger.info("Ad has ended, unmuting") create_task(self.mute(False, override=True)) elif ( From a67e3eb86077493350c07042762205acfce68264 Mon Sep 17 00:00:00 2001 From: dmunozv04 <39565245+dmunozv04@users.noreply.github.com> Date: Sat, 10 May 2025 22:28:01 +0200 Subject: [PATCH 3/5] Compare strings --- src/iSponsorBlockTV/ytlounge.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/iSponsorBlockTV/ytlounge.py b/src/iSponsorBlockTV/ytlounge.py index 65a1a5c..17816f2 100644 --- a/src/iSponsorBlockTV/ytlounge.py +++ b/src/iSponsorBlockTV/ytlounge.py @@ -118,7 +118,7 @@ class YtLoungeApi(pyytlounge.YtLoungeApi): create_task(self.mute(False, override=True)) elif event_type == "onAdStateChange": data = args[0] - if data["adState"] == "0" and data["currentTime"] != 0: # Ad is not playing + if data["adState"] == "0" and data["currentTime"] != "0": # Ad is not playing self.logger.info("Ad has ended, unmuting") create_task(self.mute(False, override=True)) elif ( From a6dacc1d848cfeb0f93e362662b41435d57b23a3 Mon Sep 17 00:00:00 2001 From: dmunozv04 <39565245+dmunozv04@users.noreply.github.com> Date: Sun, 11 May 2025 01:37:28 +0200 Subject: [PATCH 4/5] Fix adPlaying logic --- src/iSponsorBlockTV/ytlounge.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/iSponsorBlockTV/ytlounge.py b/src/iSponsorBlockTV/ytlounge.py index 17816f2..0244039 100644 --- a/src/iSponsorBlockTV/ytlounge.py +++ b/src/iSponsorBlockTV/ytlounge.py @@ -47,7 +47,7 @@ class YtLoungeApi(pyytlounge.YtLoungeApi): """ self.watchdog_running = True self.last_event_time = asyncio.get_event_loop().time() - + try: while self.watchdog_running: await asyncio.sleep(10) @@ -56,7 +56,9 @@ class YtLoungeApi(pyytlounge.YtLoungeApi): # YouTube sends a message at least every 30 seconds if time_since_last_event > 60: - self.logger.debug(f"Watchdog triggered: No events for {time_since_last_event:.1f} seconds") + self.logger.debug( + f"Watchdog triggered: No events for {time_since_last_event:.1f} seconds" + ) # Cancel current subscription if self.subscribe_task and not self.subscribe_task.done(): @@ -147,7 +149,8 @@ class YtLoungeApi(pyytlounge.YtLoungeApi): if vid_id := data["contentVideoId"]: self.logger.info(f"Getting segments for next video: {vid_id}") create_task(self.api_helper.get_segments(vid_id)) - elif ( + + if ( self.skip_ads and data["isSkipEnabled"] == "true" ): # YouTube uses strings for booleans self.logger.info("Ad can be skipped, skipping") From b2dfe3569855f491c0cf85ddad18efca45613371 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Wed, 14 May 2025 21:54:36 +0000 Subject: [PATCH 5/5] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- src/iSponsorBlockTV/ytlounge.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/iSponsorBlockTV/ytlounge.py b/src/iSponsorBlockTV/ytlounge.py index 0244039..c852855 100644 --- a/src/iSponsorBlockTV/ytlounge.py +++ b/src/iSponsorBlockTV/ytlounge.py @@ -53,13 +53,13 @@ class YtLoungeApi(pyytlounge.YtLoungeApi): await asyncio.sleep(10) current_time = asyncio.get_event_loop().time() time_since_last_event = current_time - self.last_event_time - + # YouTube sends a message at least every 30 seconds if time_since_last_event > 60: self.logger.debug( f"Watchdog triggered: No events for {time_since_last_event:.1f} seconds" ) - + # Cancel current subscription if self.subscribe_task and not self.subscribe_task.done(): self.subscribe_task.cancel() @@ -74,7 +74,7 @@ class YtLoungeApi(pyytlounge.YtLoungeApi): # Subscribe to the lounge and start the watchdog async def subscribe_monitored(self, callback): self.callback = callback - + # Stop existing watchdog if running if self.subscribe_task_watchdog and not self.subscribe_task_watchdog.done(): self.watchdog_running = False