webex-bot 1.0.3__py2.py3-none-any.whl → 1.0.5__py2.py3-none-any.whl

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.
webex_bot/__init__.py CHANGED
@@ -1,4 +1,4 @@
1
1
  """Top-level package for Webex Bot."""
2
2
 
3
3
  __author__ = """Finbarr Brady"""
4
- __version__ = '1.0.3'
4
+ __version__ = '1.0.5'
webex_bot/webex_bot.py CHANGED
@@ -57,6 +57,7 @@ class WebexBot(WebexWebsocketClient):
57
57
  log.info("Registering bot with Webex cloud")
58
58
  WebexWebsocketClient.__init__(self,
59
59
  teams_bot_token,
60
+ bot_name,
60
61
  on_message=self.process_incoming_message,
61
62
  on_card_action=self.process_incoming_card_action,
62
63
  proxies=proxies)
@@ -43,6 +43,7 @@ MAX_BACKOFF_TIME = 240
43
43
  class WebexWebsocketClient(object):
44
44
  def __init__(self,
45
45
  access_token,
46
+ bot_name,
46
47
  on_message=None,
47
48
  on_card_action=None,
48
49
  proxies=None):
@@ -50,9 +51,10 @@ class WebexWebsocketClient(object):
50
51
  self.teams = WebexAPI(access_token=access_token, proxies=proxies)
51
52
  self.tracking_id = f"webex-bot_{uuid.uuid4()}"
52
53
  self.session = requests.Session()
53
- self.session.headers = self._get_headers()
54
54
  sdk_ua = self.teams._session.headers["User-Agent"]
55
- self.teams._session.update_headers(self._get_headers(add_to_ua=f" ({sdk_ua})"))
55
+ self.add_to_ua = f" '{bot_name}' ({sdk_ua})"
56
+ self.session.headers = self._get_headers()
57
+ self.teams._session.update_headers(self._get_headers())
56
58
  # log the tracking ID
57
59
  logger.info(f"Tracking ID: {self.tracking_id}")
58
60
  self.device_info = None
@@ -69,11 +71,11 @@ class WebexWebsocketClient(object):
69
71
  if proxy_connect is None:
70
72
  raise ImportError("Failed to load libraries for proxy, maybe forgot [proxy] option during installation.")
71
73
 
72
- def _get_headers(self, add_to_ua=''):
74
+ def _get_headers(self):
73
75
  return {
74
76
  "Authorization": f"Bearer {self.access_token}",
75
77
  "Content-type": "application/json;charset=utf-8",
76
- "User-Agent": f"webex_bot/{__version__}{add_to_ua}",
78
+ "User-Agent": f"webex_bot/{__version__}{self.add_to_ua}",
77
79
  "trackingid": self.tracking_id
78
80
  }
79
81
 
@@ -276,22 +278,47 @@ class WebexWebsocketClient(object):
276
278
  while True:
277
279
  await _websocket_recv()
278
280
 
279
- try:
280
- asyncio.get_event_loop().run_until_complete(_connect_and_listen())
281
- except InvalidStatusCode as e:
282
- logger.error(f"WebSocket handshake to {ws_url} failed with status {e.status_code}")
283
- if e.status_code == 404:
284
- logger.info("Refreshing WDM device info and retrying...")
285
- self._get_device_info(check_existing=False)
286
- # update ws_url before retry
287
- ws_url = self.device_info.get('webSocketUrl')
281
+ # Track the number of consecutive 404 errors to prevent infinite loops
282
+ max_404_retries = 3
283
+ current_404_retries = 0
284
+
285
+ while True:
286
+ try:
288
287
  asyncio.get_event_loop().run_until_complete(_connect_and_listen())
289
- else:
290
- raise
291
- except Exception as runException:
292
- logger.error(f"runException: {runException}")
293
- if self._get_device_info(check_existing=False) is None:
294
- logger.error('could not create device info')
295
- raise Exception("No WDM device info")
296
- # trigger re-connect
297
- asyncio.get_event_loop().run_until_complete(_connect_and_listen())
288
+ # If we get here, the connection was successful, so break out of the loop
289
+ break
290
+ except InvalidStatusCode as e:
291
+ logger.error(f"WebSocket handshake to {ws_url} failed with status {e.status_code}")
292
+
293
+ if e.status_code == 404:
294
+ current_404_retries += 1
295
+ if current_404_retries >= max_404_retries:
296
+ logger.error(f"Reached maximum retries ({max_404_retries}) for 404 errors. Giving up.")
297
+ raise Exception(f"Unable to connect to WebSocket after {max_404_retries} attempts. Device registration may be invalid.")
298
+
299
+ logger.info(f"Refreshing WDM device info and retrying... (Attempt {current_404_retries} of {max_404_retries})")
300
+ # Force a new device registration
301
+ self._get_device_info(check_existing=False)
302
+ # Update ws_url with the new device info
303
+ ws_url = self.device_info.get('webSocketUrl')
304
+
305
+ # Add a delay before retrying to avoid hammering the server
306
+ logger.info(f"Waiting 5 seconds before retry attempt {current_404_retries}...")
307
+ asyncio.get_event_loop().run_until_complete(asyncio.sleep(5))
308
+ else:
309
+ # For non-404 errors, just raise the exception
310
+ raise
311
+ except Exception as runException:
312
+ logger.error(f"runException: {runException}")
313
+
314
+ # Check if we can get device info
315
+ if self._get_device_info(check_existing=False) is None:
316
+ logger.error('could not create device info')
317
+ raise Exception("No WDM device info")
318
+
319
+ # Update the URL in case it changed
320
+ ws_url = self.device_info.get('webSocketUrl')
321
+
322
+ # Wait a bit before reconnecting
323
+ logger.info("Waiting 5 seconds before attempting to reconnect...")
324
+ asyncio.get_event_loop().run_until_complete(asyncio.sleep(5))
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: webex_bot
3
- Version: 1.0.3
3
+ Version: 1.0.5
4
4
  Summary: Python package for a Webex Bot based on websockets.
5
5
  Home-page: https://github.com/fbradyirl/webex_bot
6
6
  Author: Finbarr Brady
@@ -452,6 +452,15 @@ bot = WebexBot(teams_bot_token=os.getenv("WEBEX_ACCESS_TOKEN")
452
452
  * Add connection headers to requests.
453
453
  * Only call me people API once per run.
454
454
 
455
+ ### 1.0.4 (2025-Jul-01)
456
+
457
+ * Add retry mechanism with backoff for websocket 404 errors
458
+
459
+ ### 1.0.5 (2025-Sept-11)
460
+
461
+ * Update UA
462
+
463
+
455
464
  [1]: https://github.com/aaugustin/websockets
456
465
 
457
466
  [2]: https://github.com/WebexCommunity/WebexPythonSDK
@@ -1,7 +1,7 @@
1
- webex_bot/__init__.py,sha256=wj46dBgRfdEfusELHz-gJWhMLFfmxqYol-gbZF8c9qY,95
1
+ webex_bot/__init__.py,sha256=IPyvDdIw3m6Lu8TVS_YxA3iHXq4JSYGSWnVi6l5QE0c,95
2
2
  webex_bot/exceptions.py,sha256=qs9yVitfJtvxwBMC8uCvTDOxUQ_oZjWFf1dU8Oaue14,740
3
3
  webex_bot/formatting.py,sha256=jvPKym-z8CIJygpPVTVbt6vFXQo9_HQHpRDJB-nh-SI,382
4
- webex_bot/webex_bot.py,sha256=QRia8QBXnWNt6iwj1kfpcWgPi7RT_DoQfqtdUUbsUTo,21278
4
+ webex_bot/webex_bot.py,sha256=GRgUNK0XgfnsO3PcA_h9n4vLWdGV6keMAdpBznwU0Uk,21326
5
5
  webex_bot/cards/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
6
6
  webex_bot/commands/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
7
7
  webex_bot/commands/echo.py,sha256=STY-MikBRjUteDK-g8G4GPB0V-Yi7siPN1DRMXrT-QU,3399
@@ -10,9 +10,9 @@ webex_bot/models/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,
10
10
  webex_bot/models/command.py,sha256=MyThlDaEkGlj1fDE_i_wr79O3QboakimRme8yI744yo,5327
11
11
  webex_bot/models/response.py,sha256=d4k2ohR5SUVzvuQzcnm7jQQVTMB0gH9Kz9y09vkoAaU,2545
12
12
  webex_bot/websockets/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
13
- webex_bot/websockets/webex_websocket_client.py,sha256=9V5y6yFSoXggaDVjCU6UfQjQKDNLsk6c1vhN8At-2as,12513
14
- webex_bot-1.0.3.dist-info/licenses/LICENSE,sha256=93eGb10xmgkBP2Fh_n0E9YDXe0c0oz-FsnAimXG0S4Y,1072
15
- webex_bot-1.0.3.dist-info/METADATA,sha256=zyqdimzCG4GD9BHKkbnsDkZ9Q6VE_JCWE8-34mt4Dq4,14694
16
- webex_bot-1.0.3.dist-info/WHEEL,sha256=JNWh1Fm1UdwIQV075glCn4MVuCRs0sotJIq-J6rbxCU,109
17
- webex_bot-1.0.3.dist-info/top_level.txt,sha256=q1Y0RtYYinR7oXSwL93cK59c2KN_CbMVca8MLWeF63M,10
18
- webex_bot-1.0.3.dist-info/RECORD,,
13
+ webex_bot/websockets/webex_websocket_client.py,sha256=ZlyTyNZuWr7cbf0mHBPu7JB432gVwBKT2Gvq9K1Pv5k,13895
14
+ webex_bot-1.0.5.dist-info/licenses/LICENSE,sha256=93eGb10xmgkBP2Fh_n0E9YDXe0c0oz-FsnAimXG0S4Y,1072
15
+ webex_bot-1.0.5.dist-info/METADATA,sha256=UglwdJNjf7QwkOaY-pnfhCuQpbg0o1NucZ1ljSoW3rc,14820
16
+ webex_bot-1.0.5.dist-info/WHEEL,sha256=JNWh1Fm1UdwIQV075glCn4MVuCRs0sotJIq-J6rbxCU,109
17
+ webex_bot-1.0.5.dist-info/top_level.txt,sha256=q1Y0RtYYinR7oXSwL93cK59c2KN_CbMVca8MLWeF63M,10
18
+ webex_bot-1.0.5.dist-info/RECORD,,