webex-bot 1.0.4__py2.py3-none-any.whl → 1.0.6__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 +1 -1
- webex_bot/webex_bot.py +11 -4
- webex_bot/websockets/webex_websocket_client.py +13 -11
- {webex_bot-1.0.4.dist-info → webex_bot-1.0.6.dist-info}/METADATA +9 -2
- {webex_bot-1.0.4.dist-info → webex_bot-1.0.6.dist-info}/RECORD +8 -8
- {webex_bot-1.0.4.dist-info → webex_bot-1.0.6.dist-info}/WHEEL +0 -0
- {webex_bot-1.0.4.dist-info → webex_bot-1.0.6.dist-info}/licenses/LICENSE +0 -0
- {webex_bot-1.0.4.dist-info → webex_bot-1.0.6.dist-info}/top_level.txt +0 -0
webex_bot/__init__.py
CHANGED
webex_bot/webex_bot.py
CHANGED
|
@@ -30,6 +30,7 @@ class WebexBot(WebexWebsocketClient):
|
|
|
30
30
|
bot_name="Webex Bot",
|
|
31
31
|
bot_help_subtitle="Here are my available commands. Click one to begin.",
|
|
32
32
|
threads=True,
|
|
33
|
+
allow_bot_to_bot=False,
|
|
33
34
|
help_command=None,
|
|
34
35
|
log_level="INFO",
|
|
35
36
|
proxies=None):
|
|
@@ -41,10 +42,11 @@ class WebexBot(WebexWebsocketClient):
|
|
|
41
42
|
@param approved_domains: List of domains which are allowed to chat to this bot.
|
|
42
43
|
@param approved_rooms: List of rooms whose members are allowed to chat to this bot.
|
|
43
44
|
@param device_url: WDM Url
|
|
44
|
-
@param include_demo_commands: If True, any demo commands will be included.
|
|
45
|
+
@param include_demo_commands: If True, any demo commands will be included. (default False)
|
|
45
46
|
@param bot_name: Your custom name for the bot.
|
|
46
47
|
@param bot_help_subtitle: Text to show in the help card.
|
|
47
|
-
@param threads: If True, respond to msg by creating a thread.
|
|
48
|
+
@param threads: If True, respond to msg by creating a thread. (default True)
|
|
49
|
+
@param allow_bot_to_bot: If True, incoming messages from other bots will be processed. Use with caution to avoid message loops. (default False)
|
|
48
50
|
@param help_command: If None, use internal HelpCommand, otherwise override.
|
|
49
51
|
@param log_level: Set loggin level.
|
|
50
52
|
@param proxies: Dictionary of proxies for connections.
|
|
@@ -57,6 +59,7 @@ class WebexBot(WebexWebsocketClient):
|
|
|
57
59
|
log.info("Registering bot with Webex cloud")
|
|
58
60
|
WebexWebsocketClient.__init__(self,
|
|
59
61
|
teams_bot_token,
|
|
62
|
+
bot_name,
|
|
60
63
|
on_message=self.process_incoming_message,
|
|
61
64
|
on_card_action=self.process_incoming_card_action,
|
|
62
65
|
proxies=proxies)
|
|
@@ -90,6 +93,7 @@ class WebexBot(WebexWebsocketClient):
|
|
|
90
93
|
self.approval_parameters_check()
|
|
91
94
|
self.bot_display_name = ""
|
|
92
95
|
self.threads = threads
|
|
96
|
+
self.allow_bot_to_bot = allow_bot_to_bot
|
|
93
97
|
|
|
94
98
|
@backoff.on_exception(backoff.expo, requests.exceptions.ConnectionError)
|
|
95
99
|
def get_me_info(self):
|
|
@@ -202,9 +206,12 @@ class WebexBot(WebexWebsocketClient):
|
|
|
202
206
|
raw_message = teams_message.text
|
|
203
207
|
is_one_on_one_space = 'ONE_ON_ONE' in activity['target']['tags']
|
|
204
208
|
|
|
205
|
-
if activity['actor']['type'] != 'PERSON':
|
|
206
|
-
log.
|
|
209
|
+
if activity['actor']['type'] != 'PERSON' and not self.allow_bot_to_bot:
|
|
210
|
+
log.warning('Message is from a bot, ignoring')
|
|
207
211
|
return
|
|
212
|
+
else:
|
|
213
|
+
log.warning(
|
|
214
|
+
f"Message is from a bot and allow_bot_to_bot is {self.allow_bot_to_bot}. Be careful not to create a message loop!")
|
|
208
215
|
|
|
209
216
|
# Log details on message
|
|
210
217
|
log.info(f"Message from {user_email}: {teams_message}")
|
|
@@ -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.
|
|
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
|
|
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
|
|
|
@@ -279,7 +281,7 @@ class WebexWebsocketClient(object):
|
|
|
279
281
|
# Track the number of consecutive 404 errors to prevent infinite loops
|
|
280
282
|
max_404_retries = 3
|
|
281
283
|
current_404_retries = 0
|
|
282
|
-
|
|
284
|
+
|
|
283
285
|
while True:
|
|
284
286
|
try:
|
|
285
287
|
asyncio.get_event_loop().run_until_complete(_connect_and_listen())
|
|
@@ -287,19 +289,19 @@ class WebexWebsocketClient(object):
|
|
|
287
289
|
break
|
|
288
290
|
except InvalidStatusCode as e:
|
|
289
291
|
logger.error(f"WebSocket handshake to {ws_url} failed with status {e.status_code}")
|
|
290
|
-
|
|
292
|
+
|
|
291
293
|
if e.status_code == 404:
|
|
292
294
|
current_404_retries += 1
|
|
293
295
|
if current_404_retries >= max_404_retries:
|
|
294
296
|
logger.error(f"Reached maximum retries ({max_404_retries}) for 404 errors. Giving up.")
|
|
295
297
|
raise Exception(f"Unable to connect to WebSocket after {max_404_retries} attempts. Device registration may be invalid.")
|
|
296
|
-
|
|
298
|
+
|
|
297
299
|
logger.info(f"Refreshing WDM device info and retrying... (Attempt {current_404_retries} of {max_404_retries})")
|
|
298
300
|
# Force a new device registration
|
|
299
301
|
self._get_device_info(check_existing=False)
|
|
300
302
|
# Update ws_url with the new device info
|
|
301
303
|
ws_url = self.device_info.get('webSocketUrl')
|
|
302
|
-
|
|
304
|
+
|
|
303
305
|
# Add a delay before retrying to avoid hammering the server
|
|
304
306
|
logger.info(f"Waiting 5 seconds before retry attempt {current_404_retries}...")
|
|
305
307
|
asyncio.get_event_loop().run_until_complete(asyncio.sleep(5))
|
|
@@ -308,15 +310,15 @@ class WebexWebsocketClient(object):
|
|
|
308
310
|
raise
|
|
309
311
|
except Exception as runException:
|
|
310
312
|
logger.error(f"runException: {runException}")
|
|
311
|
-
|
|
313
|
+
|
|
312
314
|
# Check if we can get device info
|
|
313
315
|
if self._get_device_info(check_existing=False) is None:
|
|
314
316
|
logger.error('could not create device info')
|
|
315
317
|
raise Exception("No WDM device info")
|
|
316
|
-
|
|
318
|
+
|
|
317
319
|
# Update the URL in case it changed
|
|
318
320
|
ws_url = self.device_info.get('webSocketUrl')
|
|
319
|
-
|
|
321
|
+
|
|
320
322
|
# Wait a bit before reconnecting
|
|
321
323
|
logger.info("Waiting 5 seconds before attempting to reconnect...")
|
|
322
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
|
+
Version: 1.0.6
|
|
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
|
|
@@ -455,7 +455,14 @@ bot = WebexBot(teams_bot_token=os.getenv("WEBEX_ACCESS_TOKEN")
|
|
|
455
455
|
### 1.0.4 (2025-Jul-01)
|
|
456
456
|
|
|
457
457
|
* Add retry mechanism with backoff for websocket 404 errors
|
|
458
|
-
|
|
458
|
+
|
|
459
|
+
### 1.0.5 (2025-Sept-11)
|
|
460
|
+
|
|
461
|
+
* Update UA
|
|
462
|
+
|
|
463
|
+
### 1.0.6 (2025-Sept-17)
|
|
464
|
+
|
|
465
|
+
* Allow flag to disable bot to bot check
|
|
459
466
|
|
|
460
467
|
[1]: https://github.com/aaugustin/websockets
|
|
461
468
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
webex_bot/__init__.py,sha256=
|
|
1
|
+
webex_bot/__init__.py,sha256=qc-1SbTkooTynnF9zQGCoDfMfosolKxMvBBa8Mw_qFk,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=
|
|
4
|
+
webex_bot/webex_bot.py,sha256=tlogg1mu30et-O38B8eNMbHIHhs0g2bwL6uZEOSMDeg,21802
|
|
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=
|
|
14
|
-
webex_bot-1.0.
|
|
15
|
-
webex_bot-1.0.
|
|
16
|
-
webex_bot-1.0.
|
|
17
|
-
webex_bot-1.0.
|
|
18
|
-
webex_bot-1.0.
|
|
13
|
+
webex_bot/websockets/webex_websocket_client.py,sha256=ZlyTyNZuWr7cbf0mHBPu7JB432gVwBKT2Gvq9K1Pv5k,13895
|
|
14
|
+
webex_bot-1.0.6.dist-info/licenses/LICENSE,sha256=93eGb10xmgkBP2Fh_n0E9YDXe0c0oz-FsnAimXG0S4Y,1072
|
|
15
|
+
webex_bot-1.0.6.dist-info/METADATA,sha256=bxwRlGcbQlHJ5nA4qAbuxJ2eyo4NY0WroHetB0rlhbg,14887
|
|
16
|
+
webex_bot-1.0.6.dist-info/WHEEL,sha256=JNWh1Fm1UdwIQV075glCn4MVuCRs0sotJIq-J6rbxCU,109
|
|
17
|
+
webex_bot-1.0.6.dist-info/top_level.txt,sha256=q1Y0RtYYinR7oXSwL93cK59c2KN_CbMVca8MLWeF63M,10
|
|
18
|
+
webex_bot-1.0.6.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|