aboutsummaryrefslogtreecommitdiff
path: root/contrib/ircbot/Sourcehut/plugin.py
blob: 50128d797e9bf902623daddf64997bdd59a195e2 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
import json

from supybot import ircmsgs, callbacks, httpserver, log, world
from supybot.ircutils import bold, italic, underline


class Sourcehut(callbacks.Plugin):
    """
    Supybot plugin to receive Sourcehut webhooks
    """

    def __init__(self, irc):
        super().__init__(irc)
        httpserver.hook("sourcehut", SourcehutServerCallback(self))

    def die(self):
        httpserver.unhook("sourcehut")
        super().die()

    def announce(self, channel, message):
        libera = world.getIrc("libera")
        if libera is None:
            print("error: no irc libera")
            return
        if channel not in libera.state.channels:
            print(f"error: not in {channel} channel")
            return
        libera.sendMsg(ircmsgs.notice(channel, message))


class SourcehutServerCallback(httpserver.SupyHTTPServerCallback):
    name = "Sourcehut"
    defaultResponse = "Bad request\n"

    def __init__(self, plugin: Sourcehut):
        super().__init__()
        self.plugin = plugin

    SUBJECT = "[PATCH {prefix} v{version}] {subject}"
    URL = "https://lists.sr.ht/{list[owner][canonicalName]}/{list[name]}/patches/{id}"
    CHANS = {
        "#public-inbox": "##rjarry",
        "#aerc-devel": "#aerc",
    }

    def doPost(self, handler, path, form=None):
        if hasattr(form, "decode"):
            form = form.decode("utf-8")
        print(f"POST {path} {form}")
        try:
            body = json.loads(form)
            hook = body["data"]["webhook"]
            if hook["event"] == "PATCHSET_RECEIVED":
                patchset = hook["patchset"]
                subject = self.SUBJECT.format(**patchset)
                url = self.URL.format(**patchset)
                if not url.startswith("https://lists.sr.ht/~rjarry/"):
                    raise ValueError("unknown list")
                channel = f"#{patchset['list']['name']}"
                channel = self.CHANS.get(channel, channel)
                try:
                    submitter = patchset["submitter"]["canonicalName"]
                except KeyError:
                    try:
                        submitter = patchset["submitter"]["username"]
                    except KeyError:
                        submitter = patchset["submitter"]["email"]
                msg = f"received {bold(subject)} from {italic(submitter)}: {underline(url)}"
                self.plugin.announce(channel, msg)
                handler.send_response(200)
                handler.end_headers()
                handler.wfile.write(b"")
                return

            raise ValueError("unsupported webhook: %r" % hook)

        except Exception as e:
            print("ERROR", e)
            handler.send_response(400)
            handler.end_headers()
            handler.wfile.write(b"Bad request\n")

    def log_message(self, format, *args):
        pass


Class = Sourcehut