mirror of
https://github.com/TehPeGaSuS/GitBot.git
synced 2026-06-27 10:05:46 +02:00
202 lines
6.2 KiB
Python
202 lines
6.2 KiB
Python
"""Gitea webhook payload parser."""
|
|
|
|
from irc_format import (
|
|
color, bold,
|
|
COLOR_BRANCH, COLOR_ID, COLOR_POSITIVE, COLOR_NEGATIVE,
|
|
LIGHTBLUE,
|
|
)
|
|
|
|
COMMENT_ACTIONS = {
|
|
"created": "commented",
|
|
"edited": "edited a comment",
|
|
"deleted": "deleted a comment",
|
|
}
|
|
RELEASE_ACTIONS = {
|
|
"updated": "published",
|
|
"published": "published",
|
|
"deleted": "deleted",
|
|
}
|
|
|
|
EVENT_CATEGORIES = {
|
|
"ping": ["ping"],
|
|
"code": ["push"],
|
|
"pr-minimal": [
|
|
"pull_request/opened", "pull_request/closed", "pull_request/reopened",
|
|
],
|
|
"pr": [
|
|
"pull_request/opened", "pull_request/closed", "pull_request/reopened",
|
|
"pull_request/edited", "pull_request/assigned", "pull_request/unassigned",
|
|
],
|
|
"pr-all": ["pull_request"],
|
|
"issue-minimal": [
|
|
"issues/opened", "issues/closed", "issues/reopened", "issues/deleted",
|
|
],
|
|
"issue": [
|
|
"issues/opened", "issues/closed", "issues/reopened", "issues/deleted",
|
|
"issues/edited", "issues/assigned", "issues/unassigned", "issue_comment",
|
|
],
|
|
"issue-all": ["issues", "issue_comment"],
|
|
"repo": ["create", "delete", "release", "fork", "repository"],
|
|
}
|
|
|
|
|
|
def _short(h):
|
|
return h[:7]
|
|
|
|
|
|
def names(data, headers):
|
|
full_name = repo_user = repo_name = organisation = None
|
|
if "repository" in data:
|
|
full_name = data["repository"]["full_name"]
|
|
repo_user, repo_name = full_name.split("/", 1)
|
|
if "organization" in data:
|
|
organisation = data["organization"]["login"]
|
|
return full_name, repo_user, repo_name, organisation
|
|
|
|
|
|
def branch(data, headers):
|
|
if "ref" in data:
|
|
return data["ref"].rpartition("/")[2]
|
|
return None
|
|
|
|
|
|
def is_private(data, headers):
|
|
return data.get("repository", {}).get("private", False)
|
|
|
|
|
|
def event(data, headers):
|
|
ev = headers.get("X-Gitea-Event", "")
|
|
action = data.get("action")
|
|
parts = [ev]
|
|
if action:
|
|
parts.append(f"{ev}/{action}")
|
|
return parts
|
|
|
|
|
|
def event_categories(ev):
|
|
return EVENT_CATEGORIES.get(ev, [ev])
|
|
|
|
|
|
def parse(full_name, ev, data, headers, commit_limit=3):
|
|
dispatch = {
|
|
"push": lambda fn, d: _push(fn, d, commit_limit),
|
|
"pull_request": _pull_request,
|
|
"issues": _issues,
|
|
"issue_comment": _issue_comment,
|
|
"create": _create,
|
|
"delete": _delete,
|
|
"repository": lambda fn, d: [],
|
|
"release": _release,
|
|
"fork": _fork,
|
|
"ping": lambda fn, d: [("Received new webhook", None)],
|
|
}
|
|
fn = dispatch.get(ev)
|
|
if fn:
|
|
return fn(full_name, data)
|
|
return []
|
|
|
|
|
|
def _push(full_name, data, commit_limit=3):
|
|
branch_str = color(data["ref"].rpartition("/")[2], COLOR_BRANCH)
|
|
author = bold(data["pusher"]["login"])
|
|
commits = data.get("commits", [])
|
|
range_url = data.get("compare_url")
|
|
n = len(commits)
|
|
|
|
if not commits:
|
|
return [(f"{author} pushed to {branch_str}", None)]
|
|
|
|
# Single commit: one clean line
|
|
if n == 1:
|
|
c = commits[0]
|
|
h = color(_short(c["id"]), COLOR_ID)
|
|
msg = c["message"].split("\n")[0].strip()
|
|
return [(f"{author} pushed {h} to {branch_str}: {msg}", c.get("url"))]
|
|
|
|
# Multiple commits
|
|
outputs = [(f"{author} pushed {n} commits to {branch_str}", range_url)]
|
|
shown = commits[:commit_limit]
|
|
for c in shown:
|
|
msg = c["message"].split("\n")[0].strip()
|
|
outputs.append((f"{author} {_short(c['id'])} - {msg}", None))
|
|
hidden = n - len(shown)
|
|
if hidden > 0:
|
|
outputs.append((f"(+{hidden} hidden commit{'s' if hidden != 1 else ''})", None))
|
|
return outputs
|
|
|
|
|
|
def _pull_request(full_name, data):
|
|
pr = data["pull_request"]
|
|
num = color(f"#{pr['number']}", COLOR_ID)
|
|
action = data["action"]
|
|
branch_str = color(pr["base"]["ref"], COLOR_BRANCH)
|
|
author = bold(data["sender"]["login"])
|
|
title = pr["title"]
|
|
url = pr["html_url"]
|
|
|
|
if action == "opened":
|
|
desc = f"requested {num} merge into {branch_str}"
|
|
elif action == "closed":
|
|
if pr.get("merged"):
|
|
desc = f"{color('merged', COLOR_POSITIVE)} {num} into {branch_str}"
|
|
else:
|
|
desc = f"{color('closed', COLOR_NEGATIVE)} {num}"
|
|
elif action == "ready_for_review":
|
|
desc = f"marked {num} ready for review"
|
|
elif action == "synchronize":
|
|
desc = f"committed to {num}"
|
|
else:
|
|
desc = f"{action} {num}"
|
|
|
|
return [(f"[PR] {author} {desc}: {title}", url)]
|
|
|
|
|
|
def _issues(full_name, data):
|
|
num = color(f"#{data['issue']['number']}", COLOR_ID)
|
|
action = data["action"]
|
|
title = data["issue"]["title"]
|
|
author = bold(data["sender"]["login"])
|
|
url = f"{data['repository']['html_url']}/issues/{data['issue']['number']}"
|
|
return [(f"[issue] {author} {action} {num}: {title}", url)]
|
|
|
|
|
|
def _issue_comment(full_name, data):
|
|
if "changes" in data:
|
|
if data["changes"].get("body", {}).get("from") == data["comment"]["body"]:
|
|
return []
|
|
num = color(f"#{data['issue']['number']}", COLOR_ID)
|
|
action = data["action"]
|
|
title = data["issue"]["title"]
|
|
type_ = "PR" if data["issue"].get("pull_request") else "issue"
|
|
commenter = bold(data["sender"]["login"])
|
|
url = data["comment"]["html_url"]
|
|
return [(f"[{type_}] {commenter} {COMMENT_ACTIONS[action]} on {num}: {title}", url)]
|
|
|
|
|
|
def _create(full_name, data):
|
|
ref = color(data["ref"], COLOR_BRANCH)
|
|
sender = bold(data["sender"]["login"])
|
|
return [(f"{sender} created a {data['ref_type']}: {ref}", None)]
|
|
|
|
|
|
def _delete(full_name, data):
|
|
ref = color(data["ref"], COLOR_BRANCH)
|
|
sender = bold(data["sender"]["login"])
|
|
return [(f"{sender} deleted a {data['ref_type']}: {ref}", None)]
|
|
|
|
|
|
def _release(full_name, data):
|
|
action = RELEASE_ACTIONS.get(data["action"], data["action"])
|
|
name = data["release"].get("name") or ""
|
|
if name:
|
|
name = f": {name}"
|
|
author = bold(data["release"]["author"]["login"])
|
|
return [(f"{author} {action} a release{name}", None)]
|
|
|
|
|
|
def _fork(full_name, data):
|
|
forker = bold(data["sender"]["login"])
|
|
fork_name = color(data["repository"]["full_name"], LIGHTBLUE)
|
|
url = data["repository"]["html_url"]
|
|
return [(f"{forker} forked into {fork_name}", url)]
|