import logging import re from typing import Any, List, Optional, Tuple import attr from fastapi import Request from fastapi.security import HTTPAuthorizationCredentials, HTTPBasicCredentials from jinja2 import TemplateNotFound from mautrix.types import Format, MessageType, TextMessageEventContent from mautrix.util.formatter import parse_html from ..config import RoutingKey from ..util.template import TemplateManager, TemplateUtil from .types import OTHER_ENUMS, Action, EventParse # type: ignore spaces = re.compile(" +") space = " " messages = TemplateManager("gitlab", "messages") templates = TemplateManager("gitlab", "mixins") async def authorize( route: RoutingKey, request: Request, basic_credentials: Optional[HTTPBasicCredentials], bearer_credentials: Optional[HTTPAuthorizationCredentials], ) -> bool: provided: Optional[str] = request.headers.get("x-gitlab-token") return provided == route.secret_token async def handle_event(x_gitlab_event: str, payload: Any) -> List[Tuple[str, str]]: evt = EventParse[x_gitlab_event].deserialize(payload) try: tpl = messages[evt.template_name] except TemplateNotFound: msg = f"Received unhandled gitlab event type {x_gitlab_event}" logging.error(msg) logging.debug(payload) return [] aborted = False def abort() -> None: nonlocal aborted aborted = True base_args = { **{field.key: field for field in Action if field.key.isupper()}, **OTHER_ENUMS, "util": TemplateUtil, } msgs = [] for subevt in evt.preprocess(): args = { **attr.asdict(subevt, recurse=False), **{key: getattr(subevt, key) for key in subevt.event_properties}, "abort": abort, **base_args, } args["templates"] = templates.proxy(args) html = tpl.render(**args) if not html or aborted: aborted = False continue html = spaces.sub(space, html.strip()) content = TextMessageEventContent( msgtype=MessageType.TEXT, format=Format.HTML, formatted_body=html, body=await parse_html(html), ) content["xyz.maubot.gitlab.webhook"] = { "event_type": x_gitlab_event, **subevt.meta, } msgs.append((content.body, content.formatted_body)) return msgs async def parse_event( route: RoutingKey, payload: Any, request: Request ) -> List[Tuple[str, str]]: x_gitlab_event = request.headers.get("x-gitlab-event") if x_gitlab_event: return await handle_event(x_gitlab_event, payload) return []