marcel neidinger

I ❤️ digital | CS MSc Student @eth | Assosciate Systems Engineer @cisco | 🏊‍♂️🚴‍♂️🏃‍♂️ in between

webhookSimple - Easy-to-use web hook automation for Webex Teams


  • Fr 12 Juli 2019
  • Blog

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 syncyour 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 nameattribute and create those not present. It will not delete webhooks that are registered on the server. purgewill delete all webhooks without creating new ones listwill 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.WebexTeamsWebhookManagerfor 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.parsermodule. Specifically you need to extend webhooksimple.parser.Parserand implement the abilities the same way that webhooksimple.parser.YAMLParserdoes it for YAML.