""" discord webhook reformat proxy drop-in for discord.com: swap the hostname on a gitea (discord-type) webhook so it points here, e.g. https://discord.com/api/webhooks// becomes https://proxy.example.com/api/webhooks// the proxy receives gitea's native discord embed, rewrites only the embed `description` into github's `[`hash`](url)` backtick style (hash backticked, commit message collapsed to its first line, author kept), and forwards the otherwise-untouched payload to the real discord webhook. everything gitea already handled (title, branches, multiple commits, tags, colors) passes through as-is. run: pip install fastapi httpx uvicorn uvicorn discord_reformat_proxy:app --host 127.0.0.1 --port 8000 then set a gitea webhook (type: discord) to: http://127.0.0.1:8000/api/webhooks// """ import re import logging import httpx from fastapi import FastAPI, Request, Response log = logging.getLogger(__name__) app = FastAPI() DISCORD_BASE = "https://discord.com" TIMEOUT = 10 # gitea commit line: [hash](url) - author # github commit line: [`hash`](url) - author # match a hash-link, then the message up to an optional trailing " - author", # stopping at the next commit line or end of string. _COMMIT = re.compile( r"\[`?([0-9a-f]{6,40})`?\]\((https?://[^)]+)\)" r"\s+(.*?)" r"(\s-\s[^\n]+?)?" r"(?=\n\[|\Z)", re.DOTALL, ) def _commit_sub(m: "re.Match") -> str: """rebuild one commit line github-style: backtick hash, first message line only""" short, url, message, author = m.group(1), m.group(2), m.group(3), m.group(4) or "" first_line = message.strip().split("\n", 1)[0].strip() return f"[`{short}`]({url}) {first_line}{author}" def _reformat(description: str) -> str: """rewrite gitea commit lines into github-style (backtick hash, one line each)""" return _COMMIT.sub(_commit_sub, description) @app.get("/healthz") async def healthz(): """liveness probe""" return {"ok": True} @app.post("/api/webhooks/{webhook_id}/{token}") async def proxy(webhook_id: str, token: str, request: Request): """reformat embed descriptions and forward to the real discord webhook""" try: payload = await request.json() except Exception: body = await request.body() async with httpx.AsyncClient(timeout=TIMEOUT) as client: resp = await client.post( f"{DISCORD_BASE}/api/webhooks/{webhook_id}/{token}", content=body, params=dict(request.query_params), headers={"content-type": request.headers.get("content-type", "application/json")}, ) return _passthrough(resp) if isinstance(payload, dict): for embed in payload.get("embeds") or []: if isinstance(embed, dict) and embed.get("description"): embed["description"] = _reformat(embed["description"]) async with httpx.AsyncClient(timeout=TIMEOUT) as client: resp = await client.post( f"{DISCORD_BASE}/api/webhooks/{webhook_id}/{token}", json=payload, params=dict(request.query_params), ) return _passthrough(resp) def _passthrough(resp: httpx.Response) -> Response: """return discord's response verbatim, preserving rate-limit headers""" forward = { k: v for k, v in resp.headers.items() if k.lower().startswith("x-ratelimit") or k.lower() == "retry-after" } return Response( content=resp.content, status_code=resp.status_code, media_type=resp.headers.get("content-type"), headers=forward, )