Skip to content

Commit

Permalink
Add support for proxies (#56)
Browse files Browse the repository at this point in the history

---------

Co-authored-by: Tagawa, Masaki <[email protected]>
Co-authored-by: David Hoy <[email protected]>
  • Loading branch information
3 people authored Apr 25, 2024
1 parent bf65f10 commit ea14d87
Show file tree
Hide file tree
Showing 5 changed files with 65 additions and 11 deletions.
16 changes: 14 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,10 @@ You can find a sample project, using OpenAI/ChatGPT with this library here: http

`pip install webex_bot`

If you need optional proxy support, use this command instead:

`pip install webex_bot[proxy]`

2. On the Webex Developer portal, create a new [bot token][3] and expose it as an environment variable.

```sh
Expand All @@ -51,11 +55,19 @@ import os
from webex_bot.commands.echo import EchoCommand
from webex_bot.webex_bot import WebexBot

# (Optional) Proxy configuration
# Supports https or wss proxy, wss prioritized.
proxies = {
'https': 'http://proxy.esl.example.com:80',
'wss': 'socks5://proxy.esl.example.com:1080'
}

# Create a Bot Object
bot = WebexBot(teams_bot_token=os.getenv("WEBEX_TEAMS_ACCESS_TOKEN"),
approved_rooms=['06586d8d-6aad-4201-9a69-0bf9eeb5766e'],
bot_name="My Teams Ops Bot",
include_demo_commands=True)
include_demo_commands=True,
proxies=proxies)

# Add new commands for the bot to listen out for.
bot.add_command(EchoCommand())
Expand Down Expand Up @@ -363,4 +375,4 @@ and off you go!

[i13]: https://github.com/fbradyirl/webex_bot/issues/13

[i20]: https://github.com/fbradyirl/webex_bot/issues/20
[i20]: https://github.com/fbradyirl/webex_bot/issues/20
10 changes: 9 additions & 1 deletion example.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,19 @@
from webex_bot.commands.echo import EchoCommand
from webex_bot.webex_bot import WebexBot

# (Optional) Proxy configuration
# Supports https or wss proxy, wss prioritized.
proxies = {
'https': 'http://proxy.esl.example.com:80',
'wss': 'socks5://proxy.esl.example.com:1080'
}

# Create a Bot Object
bot = WebexBot(teams_bot_token=os.getenv("WEBEX_TEAMS_ACCESS_TOKEN"),
approved_rooms=['06586d8d-6aad-4201-9a69-0bf9eeb5766e'],
bot_name="My Teams Ops Bot",
include_demo_commands=True)
include_demo_commands=True,
proxies=proxies)

# Add new commands for the bot to listen out for.
bot.add_command(EchoCommand())
Expand Down
5 changes: 5 additions & 0 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,10 @@

test_requirements = ['pytest>=3', ]

extras_requirements = {
"proxy": ["websockets_proxy>=0.1.1"]
}

setup(
author="Finbarr Brady",
author_email='[email protected]',
Expand All @@ -26,6 +30,7 @@
'Programming Language :: Python :: 3.9',
],
description="Python package for a Webex Bot based on websockets.",
extras_require=extras_requirements,
install_requires=requirements,
license="MIT license",
long_description=readme,
Expand Down
8 changes: 5 additions & 3 deletions webex_bot/webex_bot.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,8 @@ def __init__(self,
bot_help_subtitle="Here are my available commands. Click one to begin.",
threads=True,
help_command=None,
log_level="INFO"):
log_level="INFO",
proxies=None):
"""
Initialise WebexBot.
Expand All @@ -46,7 +47,7 @@ def __init__(self,
@param threads: If True, respond to msg by creating a thread.
@param help_command: If None, use internal HelpCommand, otherwise override.
@param log_level: Set loggin level.
@param proxies: Dictionary of proxies for connections.
"""

coloredlogs.install(level=os.getenv("LOG_LEVEL", log_level),
Expand All @@ -58,7 +59,8 @@ def __init__(self,
teams_bot_token,
on_message=self.process_incoming_message,
on_card_action=self.process_incoming_card_action,
device_url=device_url)
device_url=device_url,
proxies=proxies)

if help_command is None:
self.help_command = HelpCommand(
Expand Down
37 changes: 32 additions & 5 deletions webex_bot/websockets/webex_websocket_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,12 @@
import websockets
from webexteamssdk import WebexTeamsAPI

try:
from websockets_proxy import Proxy, proxy_connect
except ImportError:
Proxy = None
proxy_connect = None

logger = logging.getLogger(__name__)

DEFAULT_DEVICE_URL = "https://wdm-a.wbx2.com/wdm/api/v1"
Expand All @@ -36,16 +42,23 @@ def __init__(self,
access_token,
device_url=DEFAULT_DEVICE_URL,
on_message=None,
on_card_action=None):
on_card_action=None,
proxies=None):
self.access_token = access_token
self.teams = WebexTeamsAPI(access_token=access_token)
self.teams = WebexTeamsAPI(access_token=access_token, proxies=proxies)
self.device_url = device_url
self.device_info = None
self.on_message = on_message
self.on_card_action = on_card_action
self.proxies = proxies
self.websocket = None
self.share_id = None

if self.proxies:
# Connecting through a proxy
if proxy_connect is None:
raise ImportError("Failed to load libraries for proxy, maybe forgot [proxy] option during installation.")

def _process_incoming_websocket_message(self, msg):
"""
Handle websocket data.
Expand Down Expand Up @@ -124,7 +137,8 @@ def _get_base64_message_id(self, activity):
f"{verb}/{activity_id}")
headers = {"Authorization": f"Bearer {self.access_token}"}
conversation_message = requests.get(conversation_message_url,
headers=headers).json()
headers=headers,
proxies=self.proxies).json()
logger.debug(f"conversation_message={conversation_message}")
return conversation_message['id']

Expand Down Expand Up @@ -197,7 +211,20 @@ async def _websocket_recv():
async def _connect_and_listen():
ws_url = self.device_info['webSocketUrl']
logger.info(f"Opening websocket connection to {ws_url}")
async with websockets.connect(ws_url, ssl=ssl_context) as _websocket:

if self.proxies and "wss" in self.proxies:
logger.info(f"Using proxy for websocket connection: {self.proxies['wss']}")
proxy = Proxy.from_url(self.proxies["wss"])
connect = proxy_connect(ws_url, ssl=ssl_context, proxy=proxy)
elif self.proxies and "https" in self.proxies:
logger.info(f"Using proxy for websocket connection: {self.proxies['https']}")
proxy = Proxy.from_url(self.proxies["https"])
connect = proxy_connect(ws_url, ssl=ssl_context, proxy=proxy)
else:
logger.debug(f"Not using proxy for websocket connection.")
connect = websockets.connect(ws_url, ssl=ssl_context)

async with connect as _websocket:
self.websocket = _websocket
logger.info("WebSocket Opened.")
msg = {'id': str(uuid.uuid4()),
Expand All @@ -216,4 +243,4 @@ async def _connect_and_listen():
logger.error('could not create device info')
raise Exception("No WDM device info")
# trigger re-connect
asyncio.get_event_loop().run_until_complete(_connect_and_listen())
asyncio.get_event_loop().run_until_complete(_connect_and_listen())

0 comments on commit ea14d87

Please sign in to comment.