Skip to main content

Python package for a Webex Bot based on websockets.

Project description

Introduction

Pypi Build Status

By using this module, you can create a Webex Teams messaging 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.

Features

  • Uses the websockets module 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 the webexteamssdk package to send back replies from the bot.

Getting started

Only Python 3.9 is tested at this time.

  1. Install this module from pypi:

pip install webex_bot

  1. On the Webex Developer portal, create a new bot token and expose it as an environment variable.
export WEBEX_TEAMS_ACCESS_TOKEN=<your bots token>
  1. Run your script:

python example.py

See example.py for details:

import os

from webex_bot.commands.echo import EchoCommand
from webex_bot.webex_bot import WebexBot

# 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)

# 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:

import logging

from webexteamssdk.models.cards import Colors, TextBlock, FontWeight, FontSize, Column, AdaptiveCard, ColumnSet, \
    Text, Image, HorizontalAlignment
from webexteamssdk.models.cards.actions import Submit

from webex_bot.formatting import quote_info
from webex_bot.models.command import Command
from webex_bot.models.response import response_from_adaptive_card

log = logging.getLogger(__name__)


class EchoCommand(Command):

    def __init__(self):
        super().__init__(
            command_keyword="echo",
            help_message="Echo Words Back to You!",
            chained_commands=[EchoCallback()])

    def pre_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])]),
                  ])

        return response_from_adaptive_card(card)

    def execute(self, message, attachment_actions, activity):
        """
        If you want to respond to a submit operation on the card, you
        would 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])

        return response_from_adaptive_card(card)


class EchoCallback(Command):

    def __init__(self):
        super().__init__(
            card_callback_keyword="echo_callback",
            delete_previous_message=True)

    def execute(self, message, attachment_actions, activity):
        return quote_info(attachment_actions.inputs.get("message_typed"))
  1. Now, just interact 1-1 with the bot. Send it a message with the text:

echo

and off you go!

Help

  • If you are a Cisco employee, you can join the discussion space here.
  • Alternatively, open an issue or PR with a question on usage.

History

0.1.2 (2021-03-15)

  • First release on PyPI.

0.1.4 (2021-03-23)

  • Better retry on websocket connection failure
  • Added support for approved domains
  • Other cleanup

0.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 fix

0.2.2 (2021-05-08)

  • Typo fix

0.2.3 (2021-05-10)

  • Fix no module found error

0.2.5 (2021-05-10)

  • Pin websockets version

0.2.6 (2021-05-21)

  • Couple of bug fixes and support python 3.8 fully

0.2.7 (2021-09-27)

  • Fix for #11 server rejected WebSocket connection: HTTP 404

0.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 existing execute functions to include the extra activity parameter.
    def execute(self, message, attachment_actions, activity):
        log.info(
            f"activity={activity} ")
        email = activity["actor"]['emailAddress']
        return quote_info(f"person email is '{email}'")

0.2.9 (2022-03-03)

  • Fixes for #14 & #16

0.2.10 (2022-03-03)

  • Add new workflow for Github releases.

0.2.11 (2022-03-08)

  • Add pre_execute function 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 for pre_card_load_reply overide. 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 cards

0.2.16 (2022-03-10)

  • Add support for approved rooms.

0.2.17 (2022-03-11)

0.2.18 (2022-03-11)

  • Remove pyadaptivecards as it is actually built into webexteamssdk
  • Add options for bot name, help message etc.

0.2.19 (2022-03-14)

  • Bug fix Thanks @muhammad-rafi

0.2.20 (2022-04-07)

  • Fix for #6
  • Fix for #20
  • Use 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)

  • Add chained_commands as 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 cards

0.3.3 (2022-06-07)

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

webex_bot-0.3.3.tar.gz (24.7 kB view details)

Uploaded Source

Built Distribution

webex_bot-0.3.3-py2.py3-none-any.whl (18.8 kB view details)

Uploaded Python 2 Python 3

File details

Details for the file webex_bot-0.3.3.tar.gz.

File metadata

  • Download URL: webex_bot-0.3.3.tar.gz
  • Upload date:
  • Size: 24.7 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/4.0.1 CPython/3.8.13

File hashes

Hashes for webex_bot-0.3.3.tar.gz
Algorithm Hash digest
SHA256 b5d05fe761f13b4f98587c801e2ccc686f30c3d75344c8ca6eff782f078817d6
MD5 6aaa0250deeafc7f31c2c0daa0d827dd
BLAKE2b-256 e195496191e3d46f20b10fcd98bfd5fc0f434e6fb224c0ba89c0bf3d43c2b810

See more details on using hashes here.

File details

Details for the file webex_bot-0.3.3-py2.py3-none-any.whl.

File metadata

  • Download URL: webex_bot-0.3.3-py2.py3-none-any.whl
  • Upload date:
  • Size: 18.8 kB
  • Tags: Python 2, Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/4.0.1 CPython/3.8.13

File hashes

Hashes for webex_bot-0.3.3-py2.py3-none-any.whl
Algorithm Hash digest
SHA256 d329a17e719f03066cf14cd4f4872d9e65a1d3c3ed9856aabf35eda846c6ee9e
MD5 11910cda1a17355d11d1ffd0257910a4
BLAKE2b-256 3d7880687a1c7eb5c90e0bf76eaa905a4553767fa34cb5e9ab9111a3b32bd826

See more details on using hashes here.

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page