webex-bot 0.5.0__py2.py3-none-any.whl → 0.5.2__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__ = '0.5.0'
4
+ __version__ = '0.5.2'
@@ -9,8 +9,9 @@ COMMAND_KEYWORD_KEY = "command_keyword"
9
9
 
10
10
  class Command(ABC):
11
11
 
12
- def __init__(self, command_keyword=None, chained_commands=[], card=None, help_message=None,
13
- delete_previous_message=False,
12
+ def __init__(self, command_keyword=None, exact_command_keyword_match=False,
13
+ chained_commands=[], card=None,
14
+ help_message=None, delete_previous_message=False,
14
15
  card_callback_keyword=None, approved_rooms=None):
15
16
  """
16
17
  Create a new bot command.
@@ -25,6 +26,7 @@ class Command(ABC):
25
26
  )
26
27
 
27
28
  @param command_keyword: (optional) Text indicating a phrase to invoke this card.
29
+ @param exact_command_keyword_match: If True, there will be an exact command_keyword match performed. If False, then a sub-string match will be performed. Default: False.
28
30
  @param chained_commands: (optional) List of other commands related
29
31
  to this command. This allows multiple related cards to be added at once.
30
32
  @param card: (deprecated) A dict representation of the JSON card.
@@ -37,6 +39,7 @@ class Command(ABC):
37
39
  @param approved_rooms: If defined, only members of these spaces will be allowed to run this command. Default: None (everyone)
38
40
  """
39
41
  self.command_keyword = command_keyword
42
+ self.exact_command_keyword_match = exact_command_keyword_match
40
43
  self.help_message = help_message
41
44
  self.card = card
42
45
  self.pre_card_callback = self.execute
webex_bot/webex_bot.py CHANGED
@@ -31,7 +31,8 @@ class WebexBot(WebexWebsocketClient):
31
31
  bot_help_subtitle="Here are my available commands. Click one to begin.",
32
32
  threads=True,
33
33
  help_command=None,
34
- log_level="INFO"):
34
+ log_level="INFO",
35
+ proxies=None):
35
36
  """
36
37
  Initialise WebexBot.
37
38
 
@@ -46,7 +47,7 @@ class WebexBot(WebexWebsocketClient):
46
47
  @param threads: If True, respond to msg by creating a thread.
47
48
  @param help_command: If None, use internal HelpCommand, otherwise override.
48
49
  @param log_level: Set loggin level.
49
-
50
+ @param proxies: Dictionary of proxies for connections.
50
51
  """
51
52
 
52
53
  coloredlogs.install(level=os.getenv("LOG_LEVEL", log_level),
@@ -58,7 +59,8 @@ class WebexBot(WebexWebsocketClient):
58
59
  teams_bot_token,
59
60
  on_message=self.process_incoming_message,
60
61
  on_card_action=self.process_incoming_card_action,
61
- device_url=device_url)
62
+ device_url=device_url,
63
+ proxies=proxies)
62
64
 
63
65
  if help_command is None:
64
66
  self.help_command = HelpCommand(
@@ -232,10 +234,21 @@ class WebexBot(WebexWebsocketClient):
232
234
 
233
235
  if not is_card_callback_command and c.command_keyword:
234
236
  log.debug(f"c.command_keyword: {c.command_keyword}")
235
- if user_command.find(c.command_keyword) != -1:
236
- command = c
237
- # If a command was found, stop looking for others
238
- break
237
+ log.info(f"exact_command_keyword_match: {c.exact_command_keyword_match}")
238
+ log.info(f"user_command: {user_command}")
239
+ log.info(f"command_keyword: {c.command_keyword}")
240
+ if c.exact_command_keyword_match: # Check if the "exact_command_keyword_match" flag is set to True
241
+ if user_command == c.command_keyword:
242
+ log.info("Exact match found!")
243
+ command=c
244
+ # If a command was found, stop looking for others
245
+ break
246
+ else: # Enter here if the "exact_command_keyword_match" flag is set to False
247
+ if user_command.find(c.command_keyword) != -1:
248
+ log.info("Sub-string match found!")
249
+ command = c
250
+ # If a command was found, stop looking for others
251
+ break
239
252
  else:
240
253
  log.debug(f"card_callback_keyword: {c.card_callback_keyword}")
241
254
  if user_command == c.command_keyword or user_command == c.card_callback_keyword:
@@ -11,6 +11,12 @@ import requests
11
11
  import websockets
12
12
  from webexteamssdk import WebexTeamsAPI
13
13
 
14
+ try:
15
+ from websockets_proxy import Proxy, proxy_connect
16
+ except ImportError:
17
+ Proxy = None
18
+ proxy_connect = None
19
+
14
20
  logger = logging.getLogger(__name__)
15
21
 
16
22
  DEFAULT_DEVICE_URL = "https://wdm-a.wbx2.com/wdm/api/v1"
@@ -36,16 +42,23 @@ class WebexWebsocketClient(object):
36
42
  access_token,
37
43
  device_url=DEFAULT_DEVICE_URL,
38
44
  on_message=None,
39
- on_card_action=None):
45
+ on_card_action=None,
46
+ proxies=None):
40
47
  self.access_token = access_token
41
- self.teams = WebexTeamsAPI(access_token=access_token)
48
+ self.teams = WebexTeamsAPI(access_token=access_token, proxies=proxies)
42
49
  self.device_url = device_url
43
50
  self.device_info = None
44
51
  self.on_message = on_message
45
52
  self.on_card_action = on_card_action
53
+ self.proxies = proxies
46
54
  self.websocket = None
47
55
  self.share_id = None
48
56
 
57
+ if self.proxies:
58
+ # Connecting through a proxy
59
+ if proxy_connect is None:
60
+ raise ImportError("Failed to load libraries for proxy, maybe forgot [proxy] option during installation.")
61
+
49
62
  def _process_incoming_websocket_message(self, msg):
50
63
  """
51
64
  Handle websocket data.
@@ -124,7 +137,8 @@ class WebexWebsocketClient(object):
124
137
  f"{verb}/{activity_id}")
125
138
  headers = {"Authorization": f"Bearer {self.access_token}"}
126
139
  conversation_message = requests.get(conversation_message_url,
127
- headers=headers).json()
140
+ headers=headers,
141
+ proxies=self.proxies).json()
128
142
  logger.debug(f"conversation_message={conversation_message}")
129
143
  return conversation_message['id']
130
144
 
@@ -197,7 +211,20 @@ class WebexWebsocketClient(object):
197
211
  async def _connect_and_listen():
198
212
  ws_url = self.device_info['webSocketUrl']
199
213
  logger.info(f"Opening websocket connection to {ws_url}")
200
- async with websockets.connect(ws_url, ssl=ssl_context) as _websocket:
214
+
215
+ if self.proxies and "wss" in self.proxies:
216
+ logger.info(f"Using proxy for websocket connection: {self.proxies['wss']}")
217
+ proxy = Proxy.from_url(self.proxies["wss"])
218
+ connect = proxy_connect(ws_url, ssl=ssl_context, proxy=proxy)
219
+ elif self.proxies and "https" in self.proxies:
220
+ logger.info(f"Using proxy for websocket connection: {self.proxies['https']}")
221
+ proxy = Proxy.from_url(self.proxies["https"])
222
+ connect = proxy_connect(ws_url, ssl=ssl_context, proxy=proxy)
223
+ else:
224
+ logger.debug(f"Not using proxy for websocket connection.")
225
+ connect = websockets.connect(ws_url, ssl=ssl_context)
226
+
227
+ async with connect as _websocket:
201
228
  self.websocket = _websocket
202
229
  logger.info("WebSocket Opened.")
203
230
  msg = {'id': str(uuid.uuid4()),
@@ -216,4 +243,4 @@ class WebexWebsocketClient(object):
216
243
  logger.error('could not create device info')
217
244
  raise Exception("No WDM device info")
218
245
  # trigger re-connect
219
- asyncio.get_event_loop().run_until_complete(_connect_and_listen())
246
+ asyncio.get_event_loop().run_until_complete(_connect_and_listen())
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: webex-bot
3
- Version: 0.5.0
3
+ Version: 0.5.2
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
@@ -17,15 +17,25 @@ Classifier: Programming Language :: Python :: 3.9
17
17
  Requires-Python: >=3.8
18
18
  Description-Content-Type: text/markdown
19
19
  License-File: LICENSE
20
- Requires-Dist: webexteamssdk ==1.6.1
20
+ Requires-Dist: webexteamssdk==1.6.1
21
21
  Requires-Dist: coloredlogs
22
- Requires-Dist: websockets ==11.0.3
22
+ Requires-Dist: websockets==11.0.3
23
23
  Requires-Dist: backoff
24
+ Provides-Extra: proxy
25
+ Requires-Dist: websockets-proxy>=0.1.1; extra == "proxy"
24
26
 
25
27
  # Introduction
26
28
 
27
29
  [![Pypi](https://img.shields.io/pypi/v/webex_bot.svg)](https://pypi.python.org/pypi/webex_bot) [![Build Status](https://github.com/fbradyirl/webex_bot/workflows/Python%20package/badge.svg)](https://github.com/fbradyirl/webex_bot/actions)
28
30
 
31
+ > [!IMPORTANT]
32
+ > This repository is only sporadically maintained. Breaking API changes will be maintained on a best efforts basis.
33
+ >
34
+ > Collaborators are welcome, as are PRs for enhancements.
35
+ >
36
+ > Bug reports unrelated to API changes may not get the attention you want.
37
+
38
+
29
39
  By using this module, you can create a [Webex Teams][5] messaging bot quickly in just a couple of lines of code.
30
40
 
31
41
  This module does not require you to set up an ngrok tunnel to receive incoming messages when behind a firewall or
@@ -57,6 +67,10 @@ You can find a sample project, using OpenAI/ChatGPT with this library here: http
57
67
 
58
68
  `pip install webex_bot`
59
69
 
70
+ If you need optional proxy support, use this command instead:
71
+
72
+ `pip install webex_bot[proxy]`
73
+
60
74
  2. On the Webex Developer portal, create a new [bot token][3] and expose it as an environment variable.
61
75
 
62
76
  ```sh
@@ -75,11 +89,19 @@ import os
75
89
  from webex_bot.commands.echo import EchoCommand
76
90
  from webex_bot.webex_bot import WebexBot
77
91
 
92
+ # (Optional) Proxy configuration
93
+ # Supports https or wss proxy, wss prioritized.
94
+ proxies = {
95
+ 'https': 'http://proxy.esl.example.com:80',
96
+ 'wss': 'socks5://proxy.esl.example.com:1080'
97
+ }
98
+
78
99
  # Create a Bot Object
79
100
  bot = WebexBot(teams_bot_token=os.getenv("WEBEX_TEAMS_ACCESS_TOKEN"),
80
101
  approved_rooms=['06586d8d-6aad-4201-9a69-0bf9eeb5766e'],
81
102
  bot_name="My Teams Ops Bot",
82
- include_demo_commands=True)
103
+ include_demo_commands=True,
104
+ proxies=proxies)
83
105
 
84
106
  # Add new commands for the bot to listen out for.
85
107
  bot.add_command(EchoCommand())
@@ -357,13 +379,20 @@ and off you go!
357
379
 
358
380
  ### 0.5.0 (2024-Apr-25)
359
381
 
360
- * Add max backoff time (#55)
361
- * Attached files. Help, threading and log level overrides. (#54)
362
- * add stop() call to gracefully exit the bot (#42)
363
- * feat(20231212): add help image size parameter (#46)
364
- * update websockets to 11.0.3 (#43)
382
+ * Add max backoff time ([#55][pr55])
383
+ * Attached files. Help, threading and log level overrides. ([#54][pr54])
384
+ * add stop() call to gracefully exit the bot ([#42][pr42])
385
+ * feat(20231212): add help image size parameter ([#46][pr46])
386
+ * update websockets to 11.0.3 ([#43][pr43])
365
387
  * Fix for help_command syntax issue
366
388
 
389
+ ### 0.5.1 (2024-Apr-25)
390
+
391
+ * Add Proxy Support. ([#56][pr56])
392
+
393
+ ### 0.5.2 (2024-Aug-21)
394
+
395
+ * Introduce exact_command_keyword_match feature ([#59][pr59])
367
396
 
368
397
  [1]: https://github.com/aaugustin/websockets
369
398
 
@@ -379,6 +408,20 @@ and off you go!
379
408
 
380
409
  [7]: https://eurl.io/#TeBLqZjLs
381
410
 
411
+ [pr43]: https://github.com/fbradyirl/webex_bot/pull/43
412
+
413
+ [pr46]: https://github.com/fbradyirl/webex_bot/pull/46
414
+
415
+ [pr42]: https://github.com/fbradyirl/webex_bot/pull/42
416
+
417
+ [pr54]: https://github.com/fbradyirl/webex_bot/pull/54
418
+
419
+ [pr55]: https://github.com/fbradyirl/webex_bot/pull/55
420
+
421
+ [pr56]: https://github.com/fbradyirl/webex_bot/pull/56
422
+
423
+ [pr59]: https://github.com/fbradyirl/webex_bot/pull/59
424
+
382
425
  [i1]: https://github.com/fbradyirl/webex_bot/issues/1
383
426
 
384
427
  [i2]: https://github.com/fbradyirl/webex_bot/issues/2
@@ -1,18 +1,18 @@
1
- webex_bot/__init__.py,sha256=o9hxpp3-rpiFtnd86lMQGKVy9tWQAb1JazWjTWECDtA,95
1
+ webex_bot/__init__.py,sha256=JfFcRVsDoAtttzwsMUmplNDZyvQ4gsjzQH9P1fx6XRo,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=Fvga8PUgBtFkdkYirDpNU35uRkfhdIRPUrFj6z6amYo,20325
4
+ webex_bot/webex_bot.py,sha256=fUGMMIJVcwoP4fIaIyvvpSxoaMAl34dXSk0_QX44VGo,21222
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=YmeRVh56pzsj0_lRHDvgyrv6YqQQdRiusG65dHTh9qU,3397
8
8
  webex_bot/commands/help.py,sha256=s4buQxnmHijkqWiYs8RZ_H-yzi3EhAffSozPCGNndD0,3468
9
9
  webex_bot/models/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
10
- webex_bot/models/command.py,sha256=Rok661eZM2Mg465CZ4GgctWi1RD-BD5Bruq0FsJ8GDQ,5023
10
+ webex_bot/models/command.py,sha256=HyZqS3oIEiWpHIEq8UvXPDHwd-opB-VWZxf2M3HKgvM,5325
11
11
  webex_bot/models/response.py,sha256=1U0EQv8O5R3-demaumxMExn278DG4AeQHhXP_g4xndk,2544
12
12
  webex_bot/websockets/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
13
- webex_bot/websockets/webex_websocket_client.py,sha256=uBpvpRLmfhgtfDr0Yomg6FNei9CIsCEigNsAEu5c5iY,9427
14
- webex_bot-0.5.0.dist-info/LICENSE,sha256=93eGb10xmgkBP2Fh_n0E9YDXe0c0oz-FsnAimXG0S4Y,1072
15
- webex_bot-0.5.0.dist-info/METADATA,sha256=RqiYq2AdWfRXMD9x0h4DoQIXEh764hWry7rBb7zbc-U,11154
16
- webex_bot-0.5.0.dist-info/WHEEL,sha256=DZajD4pwLWue70CAfc7YaxT1wLUciNBvN_TTcvXpltE,110
17
- webex_bot-0.5.0.dist-info/top_level.txt,sha256=q1Y0RtYYinR7oXSwL93cK59c2KN_CbMVca8MLWeF63M,10
18
- webex_bot-0.5.0.dist-info/RECORD,,
13
+ webex_bot/websockets/webex_websocket_client.py,sha256=QUTQUWgnBYg3bSZ857m_vM49Ns9GWHWT69TYP4U6R9I,10627
14
+ webex_bot-0.5.2.dist-info/LICENSE,sha256=93eGb10xmgkBP2Fh_n0E9YDXe0c0oz-FsnAimXG0S4Y,1072
15
+ webex_bot-0.5.2.dist-info/METADATA,sha256=-GLfltxFyjZyDkIUgN7BDZAyjSSzqMhmF4yWxiwxn2o,12401
16
+ webex_bot-0.5.2.dist-info/WHEEL,sha256=fS9sRbCBHs7VFcwJLnLXN1MZRR0_TVTxvXKzOnaSFs8,110
17
+ webex_bot-0.5.2.dist-info/top_level.txt,sha256=q1Y0RtYYinR7oXSwL93cK59c2KN_CbMVca8MLWeF63M,10
18
+ webex_bot-0.5.2.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: bdist_wheel (0.43.0)
2
+ Generator: bdist_wheel (0.44.0)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py2-none-any
5
5
  Tag: py3-none-any