Compare commits

...

5 Commits

Author SHA1 Message Date
dmunozv04
d2a03717be Send a no-op command after the watchdog is triggered 2025-03-07 00:23:05 +01:00
dmunozv04
f486fec0bd Bump version 2025-02-22 00:49:06 +01:00
David
54015cf455 Merge pull request #255 from dmunozv04/fix-add-device
Fix adding devices
2025-02-22 00:48:45 +01:00
pre-commit-ci[bot]
114326e34c [pre-commit.ci] auto fixes from pre-commit.com hooks
for more information, see https://pre-commit.ci
2025-02-21 23:45:26 +00:00
dmunozv04
3797200825 Fix adding devices 2025-02-22 00:44:29 +01:00
5 changed files with 43 additions and 12 deletions

View File

@@ -1,6 +1,6 @@
[project]
name = "iSponsorBlockTV"
version = "2.3.0"
version = "2.3.1"
authors = [
{"name" = "dmunozv04"}
]

View File

@@ -45,9 +45,14 @@ def get_yn_input(prompt):
print("Invalid input. Please enter 'y' or 'n'.")
async def pair_device():
async def create_web_session():
return aiohttp.ClientSession()
async def pair_device(web_session: aiohttp.ClientSession):
try:
lounge_controller = ytlounge.YtLoungeApi("iSponsorBlockTV")
lounge_controller = ytlounge.YtLoungeApi()
await lounge_controller.change_web_session(web_session)
pairing_code = input(PAIRING_CODE_PROMPT)
pairing_code = int(
pairing_code.replace("-", "").replace(" ", "")
@@ -71,7 +76,7 @@ async def pair_device():
def main(config, debug: bool) -> None:
print("Welcome to the iSponsorBlockTV cli setup wizard")
loop = asyncio.get_event_loop_policy().get_event_loop()
web_session = aiohttp.ClientSession()
web_session = loop.run_until_complete(create_web_session())
if debug:
loop.set_debug(True)
asyncio.set_event_loop(loop)
@@ -88,9 +93,7 @@ def main(config, debug: bool) -> None:
devices = config.devices
choice = get_yn_input(ADD_MORE_DEVICES_PROMPT.format(num_devices=len(devices)))
while choice == "y":
task = loop.create_task(pair_device())
loop.run_until_complete(task)
device = task.result()
device = loop.run_until_complete(pair_device(web_session))
if device:
devices.append(device)
choice = get_yn_input(ADD_MORE_DEVICES_PROMPT.format(num_devices=len(devices)))

View File

@@ -29,7 +29,7 @@ class DeviceListener:
self.logger.addHandler(sh)
self.logger.info("Starting device")
self.lounge_controller = ytlounge.YtLoungeApi(
device.screen_id, config, api_helper, self.logger, self.web_session
device.screen_id, config, api_helper, self.logger
)
# Ensures that we have a valid auth token

View File

@@ -340,8 +340,9 @@ class AddDevice(ModalWithClickExit):
async def handle_add_device_pin(self) -> None:
self.query_one("#add-device-pin-add-button").disabled = True
lounge_controller = ytlounge.YtLoungeApi(
"iSponsorBlockTV", web_session=self.web_session
"iSponsorBlockTV",
)
await lounge_controller.change_web_session(self.web_session)
pairing_code = self.query_one("#pairing-code-input").value
pairing_code = int(
pairing_code.replace("-", "").replace(" ", "")

View File

@@ -13,11 +13,10 @@ create_task = asyncio.create_task
class YtLoungeApi(pyytlounge.YtLoungeApi):
def __init__(
self,
screen_id,
screen_id=None,
config=None,
api_helper=None,
logger=None,
web_session: ClientSession = None,
):
super().__init__(
config.join_name if config else "iSponsorBlockTV", logger=logger
@@ -32,6 +31,7 @@ class YtLoungeApi(pyytlounge.YtLoungeApi):
self.logger = logger
self.shorts_disconnected = False
self.auto_play = True
self.noop_attempted = False # Track if we've already tried noop
if config:
self.mute_ads = config.mute_ads
self.skip_ads = config.skip_ads
@@ -43,8 +43,27 @@ class YtLoungeApi(pyytlounge.YtLoungeApi):
await asyncio.sleep(
35
) # YouTube sends at least a message every 30 seconds (no-op or any other)
if not self.noop_attempted:
# First time the watchdog is triggered, try sending a noop to keep connection alive
# YouTube responds with a LoungeStatus event after a noop if it is still connected
self.noop_attempted = True
self.logger.info("Watchdog triggered - sending noop command")
try:
await self.noop()
self.subscribe_task_watchdog = asyncio.create_task(self._watchdog())
except Exception as e:
self.logger.error(f"Error sending noop command: {e}")
self._cancel_subscription()
else:
# If we already tried noop and the watchdog is triggered again, cancel subscription
self.logger.warning("Watchdog triggered again after noop attempt, cancelling subscription")
self._cancel_subscription()
def _cancel_subscription(self):
try:
self.subscribe_task.cancel()
self.noop_attempted = False
except BaseException:
pass
@@ -55,6 +74,8 @@ class YtLoungeApi(pyytlounge.YtLoungeApi):
self.subscribe_task_watchdog.cancel()
except BaseException:
pass # No watchdog task
self.noop_attempted = False
self.subscribe_task = asyncio.create_task(super().subscribe(callback))
self.subscribe_task_watchdog = asyncio.create_task(self._watchdog())
return self.subscribe_task
@@ -62,13 +83,15 @@ class YtLoungeApi(pyytlounge.YtLoungeApi):
# Process a lounge subscription event
def _process_event(self, event_type: str, args: List[Any]):
self.logger.debug(f"process_event({event_type}, {args})")
# (Re)start the watchdog
# (Re)start the watchdog and reset noop attempt flag
try:
self.subscribe_task_watchdog.cancel()
except BaseException:
pass
finally:
self.noop_attempted = False
self.subscribe_task_watchdog = asyncio.create_task(self._watchdog())
# A bunch of events useful to detect ads playing, and the next video before it starts playing (that way we
# can get the segments)
if event_type == "onStateChange":
@@ -199,3 +222,7 @@ class YtLoungeApi(pyytlounge.YtLoungeApi):
if self.conn is not None:
await self.conn.close()
self.session = web_session
async def noop(self):
# No-op command to keep the connection alive
await super()._command("noop")