prim-ctrl 0.6.2__tar.gz → 0.6.4__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: prim-ctrl
3
- Version: 0.6.2
3
+ Version: 0.6.4
4
4
  Summary: Primitive Ctrl - Remote control of your phone's Primitive FTPd Android SFTP server and optionally Tailscale VPN.
5
5
  Home-page: https://github.com/lmagyar/prim-ctrl
6
6
  License: Apache-2.0
@@ -13,6 +13,7 @@ Classifier: License :: OSI Approved :: Apache Software License
13
13
  Classifier: Operating System :: OS Independent
14
14
  Classifier: Programming Language :: Python :: 3
15
15
  Classifier: Programming Language :: Python :: 3.12
16
+ Classifier: Programming Language :: Python :: 3.13
16
17
  Requires-Dist: aiohttp (>=3.11.10,<4.0.0)
17
18
  Requires-Dist: dnspython (>=2.7.0,<3.0.0)
18
19
  Requires-Dist: platformdirs (>=4.3.6,<5.0.0)
@@ -648,6 +648,25 @@ class AutomateTailscaleManager(Manager):
648
648
  async def stop(self):
649
649
  await self.automate.send_message('stop-tailscale')
650
650
 
651
+ class WebhookPing(Pingable):
652
+ def __init__(self, session: aiohttp.ClientSession, webhooks: Webhooks, funnel: Funnel):
653
+ self.session = session
654
+ self.webhooks = webhooks
655
+ self.funnel = funnel
656
+ self.ping_url = f'{self.funnel.external_url}{Webhooks.get_ping_path()}'
657
+ self.__qualname__ = "Webhooks"
658
+
659
+ async def ping(self, availability_hint: bool | None = None):
660
+ logger.debug("Calling url %s", self.ping_url)
661
+ try:
662
+ async with self.session.get(self.ping_url, timeout=ClientTimeout(total=1)) as response:
663
+ return 'pong' == await response.text()
664
+ except Exception:
665
+ return False
666
+
667
+ async def _sleep_while_wait(self, available: bool):
668
+ await asyncio.sleep(1)
669
+
651
670
  class AutomatePhoneState(PhoneState):
652
671
  VARIABLE_STATE = 'state'
653
672
 
@@ -656,6 +675,7 @@ class AutomatePhoneState(PhoneState):
656
675
  self.webhooks = webhooks
657
676
  self.automate = automate
658
677
  self.funnel = funnel
678
+ self.webhook_ping = WebhookPing(session, webhooks, funnel)
659
679
 
660
680
  async def get(self, repeat: float, timeout: float):
661
681
  logger.info("Getting Phone state...")
@@ -665,9 +685,7 @@ class AutomatePhoneState(PhoneState):
665
685
  test_timeout = 10.0
666
686
  logger.debug("Testing Funnel with calling local webhook (timeout is %ds)", int(test_timeout))
667
687
  try:
668
- async with self.session.get(f'{self.funnel.external_url}{Webhooks.get_ping_path()}', timeout=ClientTimeout(total=test_timeout)) as response:
669
- if await response.text() != 'pong':
670
- raise Exception()
688
+ await self.webhook_ping.wait_for(True, test_timeout)
671
689
  except Exception as e:
672
690
  raise RuntimeError(f"Local Funnel is not configured properly for {self.funnel.external_url}") from e
673
691
 
@@ -804,7 +822,8 @@ class Control:
804
822
  state[Control.LOCAL_VPN] = local_vpn_state
805
823
 
806
824
  # start changing local state - we need a local vpn to be able to access the state of the remote vpn and optionally the phone
807
- await local.vpn.start(10, 30)
825
+ if not state[Control.LOCAL_VPN]:
826
+ await local.vpn.start(10, 30)
808
827
 
809
828
  zeroconf_accessible = False
810
829
  remote_accessible = False
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "prim-ctrl"
3
- version = "0.6.2"
3
+ version = "0.6.4"
4
4
  description = "Primitive Ctrl - Remote control of your phone's Primitive FTPd Android SFTP server and optionally Tailscale VPN."
5
5
  license = "Apache-2.0"
6
6
  authors = ["Laszlo Magyar <lmagyar1973@gmail.com>"]
File without changes
File without changes