If you are developing anything with an API there is one thing you have come across for sure: Webhooks.
Webhooks are callbacks that you can specify inside an API. Every time a certain event (i.e. the creation of a message) occurs a url specified in the web hook will be called with additional information about the event (i.e the message id and the sender). This concept allows a developer to just react to a new message coming in instead of having to constantly poll the server for new messages and keep track of which messages the bot has already seen and which he hasn’t.
This concept is also implemented in Webex Teams and it’s great. However it can be a bit of a hassle to setup these web hooks. Especially in a development environment where your public address might constantly change. This is where WebhookSimple comes into play.
WebhookSimple is a simple (and open source) python framework/command line tool that allows you to quickly describe your desired Webex Teams web hooks and then creates or synchronizes them for you.
Lets dive into it
WebhookSimple requires two files from you. vars.yml and hooks.yml
vars.yml specifies the different variables while hooks.yml lets you specify the web hooks itself.
A web hook always looks like this (in hooks.yml)
---
hooks:
- name: test hook 1
resource: "messages"
event: "created"
target_url: "https://your_url_here"
Make sure that the name
of your web hook is always unique since this is what webhookSimple will use to identify and synchronize your webhooks. Your vars.yml must include an adapter that specifies the kind of api we are interacting with as well as the authentication details. Leave this to the provided parser.WebexTeamsWebhookManager
for now and add the access token in the correct spot.
vars.yml
adapter: parser.WebexTeamsWebhookManager
- authentication:
- access_token: add_your_access_token_here
You can now setup
, purge
, list
, export
or sync
your webhooks.
* setup
will delete all webhooks currently present for this bot and create new ones based on the hooks.yml file.
* sync
will update all existing webhooks based on the name
attribute and create those not present. It will not delete webhooks that are registered on the server.
* purge
will delete all webhooks without creating new ones
* list
will list all webhooks currently registered
* export
will save all your currently active webhooks to a .yml file
Invoke the module by running
$ ls
hooks.yml vars.yml
$ python3 -m webhooksimple setup
Taking it one step further
Setting up web hook from a command line and based of a configuration file is already pretty cool and convenient. But what if we have ten webhooks and need to update the target_url on all of them? We’d have to manually edit all the web hook entries in hooks.yml. This is where the vars.yml file comes into play. hooks.yml is not a simple configuration file but rather a Jinja2 template of a configuration file. What you can do is this:
vars.yml
---
url_prefix: https://my_url_base
hooks.yml
---
access_token: add_webex_access_token_here
hooks:
- name: test hook 1
resource: "messages"
event: "created"
target_url: "https://{{ url_prefix }}/messages"
But this is not all. Those that worked with jinja2 before probably already know what is coming next. You can also add some (generator) logic here. Lets say we want to create a debug and a production version of our web hook. We can do this by doing the following:
vars.yml
---
envs:
- name: production
url: https://my_production_prefix
- name: development
url: https://my_development_prefix
hooks.yml
---
hooks:
{% for env in envs %}
- name: {{ env.name }} message hook
resource: "message"
event: "created"
target_url: {{ env.url }}/messages
{% endfor %}
Or you want to setup the same web hook for different urls. This would look something like this
vars.yml
---
urls:
- https://url_number_1
- https://url_number_2
- https://url_number_3
hooks.yml
---
hooks:
{% for url in urls %}
- name: "hook for {{ url }}"
resource: "message"
event: "created"
target_url: {{ url }}
{% endfor %}
Happy programming! You can get WebhookSimple by running
$ pip3 install webhooksimple
You can find the code here.
Next time: How to extend WebhookSimple to include other formats then YAML
Some answers
You might have some questions. So let me provide some answers.
Why isn’t this called WebexTeamsWebhookSimple
Well, first of all that name is just too long and second this project is not necessarily restricted to the Webex Teams API. While the current implementation only provides an adapter to Webex Teams it is easily extendable to other (Cisco) APIs. If you have a cool API to implement let me know on twitter @squ4rks.
You want to do it yourself? Have a look into the webhooksimple.manager
file. You need to specify a class that inherits from the abstract webhooksimple.manager.WebhookManager
class and provides all the functionality listed there. Take a look at webhooksimple.manager.WebexTeamsWebhookManager
for inspiration.
Why oh why did you use YAML
Because I like it. I like it more than JSON/XML. But fear not: The parser is modular in the sense that you can easily create your own version that takes JSON or whatever you like. Have a look into the webhooksimple.parser
module. Specifically you need to extend webhooksimple.parser.Parser
and implement the abilities the same way that webhooksimple.parser.YAMLParser
does it for YAML.