From 91dbd6078192e017b88bf061bb730e9d16ed5088 Mon Sep 17 00:00:00 2001 From: Robin Jarry Date: Sun, 25 Jun 2023 13:33:44 +0200 Subject: contrib: add irc bot stuff Add a small script to install a sourcehut webhook that triggers on patchset reception. Add a limnoria (supybot fork) plugin to receive the webhook requests and send IRC NOTICE messages on the proper channels. Signed-off-by: Robin Jarry Acked-by: Bence Ferdinandy --- contrib/ircbot/Sourcehut/README.md | 1 + contrib/ircbot/Sourcehut/__init__.py | 21 ++++++++ contrib/ircbot/Sourcehut/config.py | 14 ++++++ contrib/ircbot/Sourcehut/local/__init__.py | 1 + contrib/ircbot/Sourcehut/plugin.py | 80 ++++++++++++++++++++++++++++++ contrib/ircbot/Sourcehut/setup.py | 3 ++ contrib/ircbot/install-webhook.sh | 36 ++++++++++++++ contrib/ircbot/nginx.conf | 36 ++++++++++++++ contrib/ircbot/supybot.conf | 40 +++++++++++++++ contrib/ircbot/supybot.service | 19 +++++++ 10 files changed, 251 insertions(+) create mode 100644 contrib/ircbot/Sourcehut/README.md create mode 100644 contrib/ircbot/Sourcehut/__init__.py create mode 100644 contrib/ircbot/Sourcehut/config.py create mode 100644 contrib/ircbot/Sourcehut/local/__init__.py create mode 100644 contrib/ircbot/Sourcehut/plugin.py create mode 100644 contrib/ircbot/Sourcehut/setup.py create mode 100755 contrib/ircbot/install-webhook.sh create mode 100644 contrib/ircbot/nginx.conf create mode 100644 contrib/ircbot/supybot.conf create mode 100644 contrib/ircbot/supybot.service (limited to 'contrib') diff --git a/contrib/ircbot/Sourcehut/README.md b/contrib/ircbot/Sourcehut/README.md new file mode 100644 index 00000000..dbc4311d --- /dev/null +++ b/contrib/ircbot/Sourcehut/README.md @@ -0,0 +1 @@ +Supybot plugin to receive Sourcehut webhooks diff --git a/contrib/ircbot/Sourcehut/__init__.py b/contrib/ircbot/Sourcehut/__init__.py new file mode 100644 index 00000000..39a9beef --- /dev/null +++ b/contrib/ircbot/Sourcehut/__init__.py @@ -0,0 +1,21 @@ +""" +Sourcehut: Supybot plugin to receive Sourcehut webhooks +""" + +import sys +import supybot + +__version__ = "0.1" +__author__ = supybot.authors.unknown +__contributors__ = {} +__url__ = '' + +from . import config +from . import plugin +from importlib import reload + +reload(config) +reload(plugin) + +Class = plugin.Class +configure = config.configure diff --git a/contrib/ircbot/Sourcehut/config.py b/contrib/ircbot/Sourcehut/config.py new file mode 100644 index 00000000..38e55427 --- /dev/null +++ b/contrib/ircbot/Sourcehut/config.py @@ -0,0 +1,14 @@ +from supybot import conf, registry +try: + from supybot.i18n import PluginInternationalization + _ = PluginInternationalization('Sourcehut') +except: + _ = lambda x: x + + +def configure(advanced): + from supybot.questions import expect, anything, something, yn + conf.registerPlugin('Sourcehut', True) + + +Sourcehut = conf.registerPlugin('Sourcehut') diff --git a/contrib/ircbot/Sourcehut/local/__init__.py b/contrib/ircbot/Sourcehut/local/__init__.py new file mode 100644 index 00000000..e86e97b8 --- /dev/null +++ b/contrib/ircbot/Sourcehut/local/__init__.py @@ -0,0 +1 @@ +# Stub so local is a module, used for third-party modules diff --git a/contrib/ircbot/Sourcehut/plugin.py b/contrib/ircbot/Sourcehut/plugin.py new file mode 100644 index 00000000..d66c1029 --- /dev/null +++ b/contrib/ircbot/Sourcehut/plugin.py @@ -0,0 +1,80 @@ +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) + submitter = patchset["submitter"]["canonicalName"] + 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 diff --git a/contrib/ircbot/Sourcehut/setup.py b/contrib/ircbot/Sourcehut/setup.py new file mode 100644 index 00000000..11ba8772 --- /dev/null +++ b/contrib/ircbot/Sourcehut/setup.py @@ -0,0 +1,3 @@ +from supybot.setup import plugin_setup + +plugin_setup('Sourcehut') diff --git a/contrib/ircbot/install-webhook.sh b/contrib/ircbot/install-webhook.sh new file mode 100755 index 00000000..4d737f5b --- /dev/null +++ b/contrib/ircbot/install-webhook.sh @@ -0,0 +1,36 @@ +#!/bin/sh + +set -xe + +hut lists webhook create "https://lists.sr.ht/~rjarry/aerc-devel" \ + --stdin -e patchset_received \ + -u https://bot.diabeteman.com/sourcehut/ <