Source code for herostools.actor.webhook

import json
from typing import Any

import requests
from jinja2 import Template

from .archiver.base import HERODataArchiver


[docs] class HEROWebhookSender(HERODataArchiver): """HERODataArchiver that renders metadata and payload into a JSON template and posts them to an arbitrary incoming-webhook endpoint. Works with any webhook-compatible platform (Slack, Mattermost, Discord, MS Teams, ...) since the payload format is fully defined by the template. Args: object_selector: Zenoh object selector for the devices to subscribe to. event_name: Name of the event. webhook_url: Full URL of the incoming webhook endpoint. default_metadata: Default metadata merged with every incoming payload's metadata. body_template: Template for POST message body as JSON string rendered with Jinja2, using the payload and metadata as template variables (e.g. ``'{"text": {{ payload.value | tojson }}}'``). Rendering payload only works, if it is json serializable. max_retries: Number of times to retry a failed delivery before dropping the item. request_timeout: Timeout in seconds for the POST request to the webhook endpoint. """ def __init__( self, webhook_url: str, body_template: str, request_timeout: float = 10, *args, **kwargs, ): # compile the template up front to fail early on template syntax errors self._payload_in_template = "payload" in body_template self._webhook_url = webhook_url self._template = Template(body_template) self.request_timeout = request_timeout HERODataArchiver.__init__(self, *args, **kwargs) # If the template wants to insert the payload add a marker to insert later on
[docs] def _store(self, source_name: str, payload: Any, metadata: dict) -> None: """Send the payload array as webhook. Args: source_name: Name of the event source (the HERO). payload: Incoming data. metadata: Incoming metadata merged with ``default_metadata``. """ # Allow to send json serialized payload, if wanted. # May fail if payload is not serializable if self._payload_in_template: metadata["payload"] = payload if isinstance(payload, dict) else json.dumps(payload) message = self._template.render(metadata) body = json.loads(message) response = requests.post(self._webhook_url, json=body, timeout=self.request_timeout) response.raise_for_status()