Source code for law.contrib.mattermost.notification
# coding: utf-8
"""
Mattermost notifications.
"""
from __future__ import annotations
__all__ = ["notify_mattermost"]
import threading
import traceback
from law.config import Config
from law.util import escape_markdown
from law.logger import get_logger
from law._types import Any
logger = get_logger(__name__)
[docs]
def notify_mattermost(
title: str,
content: str | dict[str, Any],
hook_url: str | None = None,
channel: str | None = None,
user: str | None = None,
mention_user: str | None = None,
icon_url: str | None = None,
icon_emoji: str | None = None,
**kwargs,
) -> bool:
"""
Sends a mattermost notification and returns *True* on success. The communication with the
mattermost API might have some delays and is therefore handled by a thread. The format of the
notification depends on *content*. If it is a string, a simple text notification is sent.
Otherwise, it should be a dictionary whose fields are formatted as key-value pairs.
"""
cfg = Config.instance()
# get default settings
if not hook_url:
hook_url = cfg.get_expanded("notifications", "mattermost_hook_url", default=None)
if not channel:
channel = cfg.get_expanded("notifications", "mattermost_channel", default=None)
if not user:
user = cfg.get_expanded("notifications", "mattermost_user", default=None)
if not mention_user:
mention_user = cfg.get_expanded("notifications", "mattermost_mention_user", default=None)
if not icon_url:
icon_url = cfg.get_expanded("notifications", "mattermost_icon_url", default=None)
if not icon_emoji:
icon_emoji = cfg.get_expanded("notifications", "mattermost_icon_emoji", default=None)
if not hook_url:
logger.warning(f"cannot send Mattermost notification, hook_url ({hook_url}) empty")
return False
# append the user to mention to the title
# unless explicitly set to empty string
mention_text = ""
if mention_user:
mention_text = " (@{})".format(escape_markdown(mention_user.lstrip("@")))
# request data for the API call
request_data = {}
if channel:
request_data["channel"] = channel
if user:
request_data["username"] = user
if icon_url:
request_data["icon_url"] = icon_url
if icon_emoji:
request_data["icon_emoji"] = icon_emoji
# standard or attachment content?
request_data["text"] = f"{title}{mention_text}\n\n"
if isinstance(content, str):
request_data["text"] += content
else:
for k, v in content.items():
request_data["text"] += f"{k}: {v}\n"
# extend by arbitrary kwargs
request_data.update(kwargs)
# threaded, non-blocking API communication
thread = threading.Thread(target=_notify_mattermost, args=(hook_url, request_data))
thread.start()
return True
def _notify_mattermost(hook_url: str, request_data: dict[str, Any]) -> None:
import requests # type: ignore[import-untyped]
try:
res = requests.post(hook_url, json=request_data)
if not res.ok:
logger.warning(f"unsuccessful Mattermost API call: {res.text}")
except Exception as e:
t = traceback.format_exc()
logger.warning(f"could not send Mattermost notification: {e}\n{t}")