Package: webex-bot
IntroductionBy using this module, you can create aWebex Teamsmessaging bot quickly in just a couple of lines of code.This module does not require you to set up an ngrok tunnel to receive incoming messages when behind a firewall or
inside a LAN. This package instead uses a websocket to receive messages from the Webex cloud.FeaturesUses thewebsocketsmodule to receive incoming messages, thus avoiding the need to have a public IP or use
incoming webhooks.Simply add 'commands' which are just strings which instruct the bot to perform some action and reply with some result.Allows for single or multi-post responses. This is useful if you want to reply with a lot of data, but it won't all
fit in a single response.Restrict bot to certain users or domains.Uses thewebexteamssdkpackage to send back replies from the bot.🚀 Getting started✨ Sample ProjectYou can find a sample project, using OpenAI/ChatGPT with this library here:https://github.com/fbradyirl/openai_botOnly Python 3.9 is tested at this time.Install this module from pypi:pip install webex_botOn the Webex Developer portal, create a newbot tokenand expose it as an environment variable.exportWEBEX_TEAMS_ACCESS_TOKEN=<yourbotstoken>Run your script:python example.pySeeexample.pyfor details:importosfromwebex_bot.commands.echoimportEchoCommandfromwebex_bot.webex_botimportWebexBot# Create a Bot Objectbot=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)# Add new commands for the bot to listen out for.bot.add_command(EchoCommand())# Call `run` for the bot to wait for incoming messages.bot.run()where EchoCommand is defined as:importloggingfromwebexteamssdk.models.cardsimportColors,TextBlock,FontWeight,FontSize,Column,AdaptiveCard,ColumnSet,\Text,Image,HorizontalAlignmentfromwebexteamssdk.models.cards.actionsimportSubmitfromwebex_bot.formattingimportquote_infofromwebex_bot.models.commandimportCommandfromwebex_bot.models.responseimportresponse_from_adaptive_cardlog=logging.getLogger(__name__)classEchoCommand(Command):def__init__(self):super().__init__(command_keyword="echo",help_message="Echo Words Back to You!",chained_commands=[EchoCallback()])defpre_execute(self,message,attachment_actions,activity):"""(optional function).Reply before running the execute function.Useful to indicate the bot is handling it if it is a long running task.:return: a string or Response object (or a list of either). Use Response if you want to return another card."""image=Image(url="https://i.postimg.cc/2jMv5kqt/AS89975.jpg")text1=TextBlock("Working on it....",weight=FontWeight.BOLDER,wrap=True,size=FontSize.DEFAULT,horizontalAlignment=HorizontalAlignment.CENTER,color=Colors.DARK)text2=TextBlock("I am busy working on your request. Please continue to look busy while I do your work.",wrap=True,color=Colors.DARK)card=AdaptiveCard(body=[ColumnSet(columns=[Column(items=[image],width=2)]),ColumnSet(columns=[Column(items=[text1,text2])]),])returnresponse_from_adaptive_card(card)defexecute(self,message,attachment_actions,activity):"""If you want to respond to a submit operation on the card, youwould write code here!You can return text string here or even another card (Response).This sample command function simply echos back the sent message.:param message: message with command already stripped:param attachment_actions: attachment_actions object:param activity: activity object:return: a string or Response object (or a list of either). Use Response if you want to return another card."""text1=TextBlock("Echo",weight=FontWeight.BOLDER,size=FontSize.MEDIUM)text2=TextBlock("Type in something here and it will be echo'd back to you. How useful is that!",wrap=True,isSubtle=True)input_text=Text(id="message_typed",placeholder="Type something here",maxLength=30)input_column=Column(items=[input_text],width=2)submit=Submit(title="Submit",data={"callback_keyword":"echo_callback"})card=AdaptiveCard(body=[ColumnSet(columns=[Column(items=[text1,text2],width=2)]),ColumnSet(columns=[input_column]),],actions=[submit])returnresponse_from_adaptive_card(card)classEchoCallback(Command):def__init__(self):super().__init__(card_callback_keyword="echo_callback",delete_previous_message=True)defexecute(self,message,attachment_actions,activity):returnquote_info(attachment_actions.inputs.get("message_typed"))Now, just interact 1-1 with the bot. Send it a message with the text:echoand off you go!HelpIf you are a Cisco employee, you can join thediscussion space here.Alternatively, open an issue or PR with a question on usage.History0.1.2 (2021-03-15)First release on PyPI.0.1.4 (2021-03-23)Better retry on websocket connection failureAdded support for approved domainsOther cleanup0.1.5 (2021-03-23)Retry websocket connection on socket.gaierror. (#1)0.1.6 (2021-03-25)Send ack on websocket message received. (#2)0.1.7 (2021-03-26)Minor cleanup.Log bot email on startup.0.1.8 (2021-05-04)Fetch incoming message ID as base64.0.2.0 (2021-05-07)Switch format entirely to use cards.0.2.1 (2021-05-07)Import fix0.2.2 (2021-05-08)Typo fix0.2.3 (2021-05-10)Fix no module found error0.2.5 (2021-05-10)Pin websockets version0.2.6 (2021-05-21)Couple of bug fixes and support python 3.8 fully0.2.7 (2021-09-27)Fix for #11 server rejected WebSocket connection: HTTP 4040.2.8 (2022-01-06)Breaking change for existing cards:Pass activity down to execute function so attibutes such as email can be fetched from card actions.Update your existingexecutefunctions to include the extraactivityparameter.defexecute(self,message,attachment_actions,activity):log.info(f"activity={activity}")email=activity["actor"]['emailAddress']returnquote_info(f"person email is '{email}'")0.2.9 (2022-03-03)Fixes for #14 & #160.2.10 (2022-03-03)Add new workflow for Github releases.0.2.11 (2022-03-08)Addpre_executefunction to Command. (optional function to overide). Reply before running the execute function.
Useful to indicate the bot is handling it if it is a long running task.See echo.py for example usage.0.2.12 (2022-03-09)Check for duplicate card callback keywords and raise exception if one exists.0.2.13 (2022-03-09)add support forpre_card_load_replyoveride. Reply before sending the initial card. Useful if it takes a long time
for the card to load.0.2.14 (2022-03-09)add support for deleting previous card in a chain.0.2.15 (2022-03-09)Support for chained cards0.2.16 (2022-03-10)Add support for approved rooms.0.2.17 (2022-03-11)Add support for usingpyadaptivecards0.2.18 (2022-03-11)Remove pyadaptivecards as it is actually built intowebexteamssdkAdd options for bot name, help message etc.0.2.19 (2022-03-14)Bug fix Thanks @muhammad-rafi0.2.20 (2022-04-07)Fix for#6Fix for#20Use system SSL context when connecting websocket.0.2.21 (2022-04-07)Fix for#13- Update websockets lib to latest.0.2.22 (2022-04-11)Allow for commands to only respond if you are in the approved space.0.3.0 (2022-04-26)Addchained_commandsas a parameter of Command. This allows multiple related cards to be added at once.Updated Echo to use Adaptive Card objects (instead of JSON/Dict blob)Added docs for some function params.0.3.1 (2022-04-26)Fix old school dict cards0.3.3 (2022-06-07)Updatewebexteamssdkto latest release.0.3.4 (2022-11-01)Auto re-connect on websockets.exceptions.ConnectionClosedOK0.4.0 (2023-April-03)Bot will reply in response to the original message via the thread ID. This is not always possible in the case of a
card action response due to some server side issue.0.4.1 (2023-Sept-07)Always ensure there is a thread ID in the Activity before accessing it