webex-bot 0.6.1__tar.gz → 1.0.0__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.
Files changed (35) hide show
  1. {webex_bot-0.6.1/webex_bot.egg-info → webex_bot-1.0.0}/PKG-INFO +10 -1
  2. {webex_bot-0.6.1 → webex_bot-1.0.0}/README.md +9 -0
  3. {webex_bot-0.6.1 → webex_bot-1.0.0}/setup.cfg +1 -1
  4. {webex_bot-0.6.1 → webex_bot-1.0.0}/setup.py +1 -1
  5. {webex_bot-0.6.1 → webex_bot-1.0.0}/webex_bot/__init__.py +1 -1
  6. {webex_bot-0.6.1 → webex_bot-1.0.0}/webex_bot/webex_bot.py +2 -4
  7. {webex_bot-0.6.1 → webex_bot-1.0.0}/webex_bot/websockets/webex_websocket_client.py +44 -17
  8. {webex_bot-0.6.1 → webex_bot-1.0.0/webex_bot.egg-info}/PKG-INFO +10 -1
  9. {webex_bot-0.6.1 → webex_bot-1.0.0}/CONTRIBUTING.rst +0 -0
  10. {webex_bot-0.6.1 → webex_bot-1.0.0}/LICENSE +0 -0
  11. {webex_bot-0.6.1 → webex_bot-1.0.0}/MANIFEST.in +0 -0
  12. {webex_bot-0.6.1 → webex_bot-1.0.0}/docs/Makefile +0 -0
  13. {webex_bot-0.6.1 → webex_bot-1.0.0}/docs/conf.py +0 -0
  14. {webex_bot-0.6.1 → webex_bot-1.0.0}/docs/contributing.rst +0 -0
  15. {webex_bot-0.6.1 → webex_bot-1.0.0}/docs/index.rst +0 -0
  16. {webex_bot-0.6.1 → webex_bot-1.0.0}/docs/installation.rst +0 -0
  17. {webex_bot-0.6.1 → webex_bot-1.0.0}/docs/make.bat +0 -0
  18. {webex_bot-0.6.1 → webex_bot-1.0.0}/docs/usage.rst +0 -0
  19. {webex_bot-0.6.1 → webex_bot-1.0.0}/tests/__init__.py +0 -0
  20. {webex_bot-0.6.1 → webex_bot-1.0.0}/tests/test_webex_bot.py +0 -0
  21. {webex_bot-0.6.1 → webex_bot-1.0.0}/webex_bot/cards/__init__.py +0 -0
  22. {webex_bot-0.6.1 → webex_bot-1.0.0}/webex_bot/commands/__init__.py +0 -0
  23. {webex_bot-0.6.1 → webex_bot-1.0.0}/webex_bot/commands/echo.py +0 -0
  24. {webex_bot-0.6.1 → webex_bot-1.0.0}/webex_bot/commands/help.py +0 -0
  25. {webex_bot-0.6.1 → webex_bot-1.0.0}/webex_bot/exceptions.py +0 -0
  26. {webex_bot-0.6.1 → webex_bot-1.0.0}/webex_bot/formatting.py +0 -0
  27. {webex_bot-0.6.1 → webex_bot-1.0.0}/webex_bot/models/__init__.py +0 -0
  28. {webex_bot-0.6.1 → webex_bot-1.0.0}/webex_bot/models/command.py +0 -0
  29. {webex_bot-0.6.1 → webex_bot-1.0.0}/webex_bot/models/response.py +0 -0
  30. {webex_bot-0.6.1 → webex_bot-1.0.0}/webex_bot/websockets/__init__.py +0 -0
  31. {webex_bot-0.6.1 → webex_bot-1.0.0}/webex_bot.egg-info/SOURCES.txt +0 -0
  32. {webex_bot-0.6.1 → webex_bot-1.0.0}/webex_bot.egg-info/dependency_links.txt +0 -0
  33. {webex_bot-0.6.1 → webex_bot-1.0.0}/webex_bot.egg-info/not-zip-safe +0 -0
  34. {webex_bot-0.6.1 → webex_bot-1.0.0}/webex_bot.egg-info/requires.txt +0 -0
  35. {webex_bot-0.6.1 → webex_bot-1.0.0}/webex_bot.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: webex_bot
3
- Version: 0.6.1
3
+ Version: 1.0.0
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
@@ -443,6 +443,13 @@ bot = WebexBot(teams_bot_token=os.getenv("WEBEX_ACCESS_TOKEN")
443
443
 
444
444
  * Handle and retry on InvalidStatusCode in Websocket loop
445
445
 
446
+ ### 0.6.2 (2025-May-23)
447
+
448
+ * Fix for [issue #48][i48] - Fix for `Commands not being received` issue.
449
+
450
+ ### 0.7.0 (2025-Jun-04)
451
+
452
+ * Add connection headers to requests.
446
453
 
447
454
  [1]: https://github.com/aaugustin/websockets
448
455
 
@@ -489,3 +496,5 @@ bot = WebexBot(teams_bot_token=os.getenv("WEBEX_ACCESS_TOKEN")
489
496
  [i13]: https://github.com/fbradyirl/webex_bot/issues/13
490
497
 
491
498
  [i20]: https://github.com/fbradyirl/webex_bot/issues/20
499
+
500
+ [i48]: https://github.com/fbradyirl/webex_bot/issues/48
@@ -403,6 +403,13 @@ bot = WebexBot(teams_bot_token=os.getenv("WEBEX_ACCESS_TOKEN")
403
403
 
404
404
  * Handle and retry on InvalidStatusCode in Websocket loop
405
405
 
406
+ ### 0.6.2 (2025-May-23)
407
+
408
+ * Fix for [issue #48][i48] - Fix for `Commands not being received` issue.
409
+
410
+ ### 0.7.0 (2025-Jun-04)
411
+
412
+ * Add connection headers to requests.
406
413
 
407
414
  [1]: https://github.com/aaugustin/websockets
408
415
 
@@ -449,3 +456,5 @@ bot = WebexBot(teams_bot_token=os.getenv("WEBEX_ACCESS_TOKEN")
449
456
  [i13]: https://github.com/fbradyirl/webex_bot/issues/13
450
457
 
451
458
  [i20]: https://github.com/fbradyirl/webex_bot/issues/20
459
+
460
+ [i48]: https://github.com/fbradyirl/webex_bot/issues/48
@@ -1,5 +1,5 @@
1
1
  [bumpversion]
2
- current_version = 0.6.1
2
+ current_version = 1.0.0
3
3
  commit = True
4
4
  tag = True
5
5
 
@@ -45,6 +45,6 @@ setup(
45
45
  test_suite='tests',
46
46
  tests_require=test_requirements,
47
47
  url='https://github.com/fbradyirl/webex_bot',
48
- version='0.6.1',
48
+ version='1.0.0',
49
49
  zip_safe=False,
50
50
  )
@@ -1,4 +1,4 @@
1
1
  """Top-level package for Webex Bot."""
2
2
 
3
3
  __author__ = """Finbarr Brady"""
4
- __version__ = '0.6.1'
4
+ __version__ = '1.0.0'
@@ -1,8 +1,8 @@
1
1
  """Main module."""
2
2
  import logging
3
3
  import os
4
-
5
4
  import types
5
+
6
6
  import backoff
7
7
  import coloredlogs
8
8
  import requests
@@ -14,7 +14,7 @@ from webex_bot.exceptions import BotException
14
14
  from webex_bot.formatting import quote_info
15
15
  from webex_bot.models.command import CALLBACK_KEYWORD_KEY, Command, COMMAND_KEYWORD_KEY
16
16
  from webex_bot.models.response import Response
17
- from webex_bot.websockets.webex_websocket_client import WebexWebsocketClient, DEFAULT_DEVICE_URL
17
+ from webex_bot.websockets.webex_websocket_client import WebexWebsocketClient
18
18
 
19
19
  log = logging.getLogger(__name__)
20
20
 
@@ -26,7 +26,6 @@ class WebexBot(WebexWebsocketClient):
26
26
  approved_users=[],
27
27
  approved_domains=[],
28
28
  approved_rooms=[],
29
- device_url=DEFAULT_DEVICE_URL,
30
29
  include_demo_commands=False,
31
30
  bot_name="Webex Bot",
32
31
  bot_help_subtitle="Here are my available commands. Click one to begin.",
@@ -60,7 +59,6 @@ class WebexBot(WebexWebsocketClient):
60
59
  teams_bot_token,
61
60
  on_message=self.process_incoming_message,
62
61
  on_card_action=self.process_incoming_card_action,
63
- device_url=device_url,
64
62
  proxies=proxies)
65
63
 
66
64
  if help_command is None:
@@ -12,6 +12,8 @@ import websockets
12
12
  from webexpythonsdk import WebexAPI
13
13
  from websockets.exceptions import InvalidStatusCode
14
14
 
15
+ from webex_bot import __version__
16
+
15
17
  try:
16
18
  from websockets_proxy import Proxy, proxy_connect
17
19
  except ImportError:
@@ -20,7 +22,7 @@ except ImportError:
20
22
 
21
23
  logger = logging.getLogger(__name__)
22
24
 
23
- DEFAULT_DEVICE_URL = "https://wdm-a.wbx2.com/wdm/api/v1"
25
+ DEFAULT_U2C_URL = "https://u2c.wbx2.com/u2c/api/v1/catalog"
24
26
 
25
27
  DEVICE_DATA = {
26
28
  "deviceName": "pywebsocket-client",
@@ -41,25 +43,37 @@ MAX_BACKOFF_TIME = 240
41
43
  class WebexWebsocketClient(object):
42
44
  def __init__(self,
43
45
  access_token,
44
- device_url=DEFAULT_DEVICE_URL,
45
46
  on_message=None,
46
47
  on_card_action=None,
47
48
  proxies=None):
48
49
  self.access_token = access_token
49
50
  self.teams = WebexAPI(access_token=access_token, proxies=proxies)
50
- self.device_url = device_url
51
+ self.tracking_id = f"webex-bot_{uuid.uuid4()}"
52
+ self.session = requests.Session()
53
+ self.session.headers = self._get_headers()
54
+ # log the tracking ID
55
+ logger.info(f"Tracking ID: {self.tracking_id}")
51
56
  self.device_info = None
57
+ self.device_url = self._get_device_url()
52
58
  self.on_message = on_message
53
59
  self.on_card_action = on_card_action
54
60
  self.proxies = proxies
55
61
  self.websocket = None
56
62
  self.share_id = None
57
-
63
+ if self.proxies:
64
+ self.session.proxies = proxies
58
65
  if self.proxies:
59
66
  # Connecting through a proxy
60
67
  if proxy_connect is None:
61
68
  raise ImportError("Failed to load libraries for proxy, maybe forgot [proxy] option during installation.")
62
69
 
70
+ def _get_headers(self):
71
+ return {
72
+ "Authorization": f"Bearer {self.access_token}",
73
+ "User-Agent": f"webex_bot/{__version__}",
74
+ "trackingid": self.tracking_id
75
+ }
76
+
63
77
  def _process_incoming_websocket_message(self, msg):
64
78
  """
65
79
  Handle websocket data.
@@ -136,10 +150,7 @@ class WebexWebsocketClient(object):
136
150
  logger.debug(f"activity_id={activity_id}")
137
151
  conversation_message_url = conversation_url.replace(f"conversations/{conv_target_id}",
138
152
  f"{verb}/{activity_id}")
139
- headers = {"Authorization": f"Bearer {self.access_token}"}
140
- conversation_message = requests.get(conversation_message_url,
141
- headers=headers,
142
- proxies=self.proxies).json()
153
+ conversation_message = self.session.get(conversation_message_url).json()
143
154
  logger.debug(f"conversation_message={conversation_message}")
144
155
  return conversation_message['id']
145
156
 
@@ -155,6 +166,22 @@ class WebexWebsocketClient(object):
155
166
  asyncio.run(self.websocket.send(json.dumps(ack_message)))
156
167
  logger.info(f"WebSocket ack message with id={message_id}. Complete.")
157
168
 
169
+ def _get_device_url(self):
170
+ params = {"format": "hostmap"}
171
+ response = self.session.get(DEFAULT_U2C_URL, params=params)
172
+
173
+ # check for 401 Unauthorized
174
+ if response.status_code == 401:
175
+ logger.error("Unauthorized access. Please check your access token.")
176
+ raise Exception("Unauthorized access. Please check your access token.")
177
+
178
+ data = response.json()
179
+
180
+ wdm_url = data["serviceLinks"].get("wdm") # or whatever key your hostmap uses
181
+ logging.info(f"wdm url: {wdm_url}")
182
+ return wdm_url
183
+
184
+
158
185
  def _get_device_info(self, check_existing=True):
159
186
  """
160
187
  Get device info from Webex Cloud.
@@ -164,8 +191,8 @@ class WebexWebsocketClient(object):
164
191
  if check_existing:
165
192
  logger.debug('Getting device list')
166
193
  try:
167
- resp = self.teams._session.get(f"{self.device_url}/devices")
168
- for device in resp['devices']:
194
+ resp = self.session.get(f"{self.device_url}/devices")
195
+ for device in resp.json()['devices']:
169
196
  if device['name'] == DEVICE_DATA['name']:
170
197
  self.device_info = device
171
198
  logger.debug(f"device_info: {self.device_info}")
@@ -175,12 +202,12 @@ class WebexWebsocketClient(object):
175
202
 
176
203
  logger.info('Device does not exist, creating')
177
204
 
178
- resp = self.teams._session.post(f"{self.device_url}/devices", json=DEVICE_DATA)
205
+ resp = self.session.post(f"{self.device_url}/devices", json=DEVICE_DATA)
179
206
  if resp is None:
180
207
  raise Exception("could not create WDM device")
181
- self.device_info = resp
208
+ self.device_info = resp.json()
182
209
  logger.debug(f"self.device_info: {self.device_info}")
183
- return resp
210
+ return self.device_info
184
211
 
185
212
  def stop(self):
186
213
  def terminate():
@@ -226,14 +253,14 @@ class WebexWebsocketClient(object):
226
253
  if self.proxies and "wss" in self.proxies:
227
254
  logger.info(f"Using proxy for websocket connection: {self.proxies['wss']}")
228
255
  proxy = Proxy.from_url(self.proxies["wss"])
229
- connect = proxy_connect(ws_url, ssl=ssl_context, proxy=proxy)
256
+ connect = proxy_connect(ws_url, ssl=ssl_context, proxy=proxy, extra_headers=self._get_headers())
230
257
  elif self.proxies and "https" in self.proxies:
231
258
  logger.info(f"Using proxy for websocket connection: {self.proxies['https']}")
232
259
  proxy = Proxy.from_url(self.proxies["https"])
233
- connect = proxy_connect(ws_url, ssl=ssl_context, proxy=proxy)
260
+ connect = proxy_connect(ws_url, ssl=ssl_context, proxy=proxy, extra_headers=self._get_headers())
234
261
  else:
235
262
  logger.debug(f"Not using proxy for websocket connection.")
236
- connect = websockets.connect(ws_url, ssl=ssl_context)
263
+ connect = websockets.connect(ws_url, ssl=ssl_context, extra_headers=self._get_headers())
237
264
 
238
265
  async with connect as _websocket:
239
266
  self.websocket = _websocket
@@ -264,4 +291,4 @@ class WebexWebsocketClient(object):
264
291
  logger.error('could not create device info')
265
292
  raise Exception("No WDM device info")
266
293
  # trigger re-connect
267
- asyncio.get_event_loop().run_until_complete(_connect_and_listen())
294
+ asyncio.get_event_loop().run_until_complete(_connect_and_listen())
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: webex_bot
3
- Version: 0.6.1
3
+ Version: 1.0.0
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
@@ -443,6 +443,13 @@ bot = WebexBot(teams_bot_token=os.getenv("WEBEX_ACCESS_TOKEN")
443
443
 
444
444
  * Handle and retry on InvalidStatusCode in Websocket loop
445
445
 
446
+ ### 0.6.2 (2025-May-23)
447
+
448
+ * Fix for [issue #48][i48] - Fix for `Commands not being received` issue.
449
+
450
+ ### 0.7.0 (2025-Jun-04)
451
+
452
+ * Add connection headers to requests.
446
453
 
447
454
  [1]: https://github.com/aaugustin/websockets
448
455
 
@@ -489,3 +496,5 @@ bot = WebexBot(teams_bot_token=os.getenv("WEBEX_ACCESS_TOKEN")
489
496
  [i13]: https://github.com/fbradyirl/webex_bot/issues/13
490
497
 
491
498
  [i20]: https://github.com/fbradyirl/webex_bot/issues/20
499
+
500
+ [i48]: https://github.com/fbradyirl/webex_bot/issues/48
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes