commit 8bd6ff6ba499702b2ef1a305595e999f8d7e5ea6 Author: Ben Date: Wed Jun 11 20:15:21 2025 -0700 Fully functional and tested diff --git a/base-config.yaml b/base-config.yaml new file mode 100644 index 0000000..b7631ed --- /dev/null +++ b/base-config.yaml @@ -0,0 +1,33 @@ +# Command prefix to listen to +# DO NOT CHANGE THIS UNLESS YOU KNOW WHAT YOU ARE DOING +command_prefix: report + +# Whether or not the bot should pay attention to only specific state/territory designators +# This bot will include the designator in the pushed notificaion if this is disabled, +# or if the allowed_locations contains multiple strings +allowed_locations_enabled: false +allowed_locations: + - arizona + - california + +# Which accounts should be paid attention to on a state/territory-by-state/territory basis. +# If the state/territory is not in allowed_senders, then the bot will allow all senders +# Otherwise only listed senders +allowed_senders: + foo: + - "@reports:fiftyfiftyonerarizona.org" + bar: + - "@reports:example.org" + - "@reports:example.com" + +# Where and how the plugin will send the data to +server_url: "https://ntfy.sh" +server_topic: "changeMe" + +# If the plugin should use a username and password to send notifications +server_use_authentication: false +server_username: "foo" +server_password: "bar" + +# If this bot should send a reaction to the message if the notification was successful +send_reaction: true \ No newline at end of file diff --git a/consumerntfy.py b/consumerntfy.py new file mode 100644 index 0000000..964fbcc --- /dev/null +++ b/consumerntfy.py @@ -0,0 +1,80 @@ +from maubot import Plugin, MessageEvent +from maubot.handlers import command + +# Needed for configuration +from typing import Type +from mautrix.util.config import BaseProxyConfig, ConfigUpdateHelper + +import aiohttp + +# Ensures a running instance gets an updated config from the Maubot interface +class Config(BaseProxyConfig): + def do_update(self, helper: ConfigUpdateHelper) -> None: + helper.copy("command_prefix") + helper.copy("allowed_locations_enabled") + helper.copy("allowed_locations") + helper.copy("allowed_senders") + helper.copy("server_url") + helper.copy("server_topic") + helper.copy("command_prefix") + helper.copy("server_use_authentication") + helper.copy("server_username") + helper.copy("server_password") + helper.copy("send_reaction") + +class ConsumerNTFY(Plugin): + # Get configuration at startup + async def start(self) -> None: + self.config.load_and_update() + + # Get config + @classmethod + def get_config_class(cls) -> Type[BaseProxyConfig]: + return Config + + # Get !command_name setting from config to register it + def get_command_name(self) -> str: + return self.config["command_prefix"] + + # What gets called when !command_name message is sent + @command.new(name=get_command_name, help="Report Something") + @command.argument("message", pass_raw=True) + async def report(self, evt: MessageEvent, message: str) -> None: + # Split command (minus !command_name) into tokens + tokens = message.split() + + # Each command must have a state/territory designation and a message + if len(tokens) < 2: return + + # Check locations whitelist + if self.config["allowed_locations_enabled"]: + if not tokens[0].lower() in self.config["allowed_locations"]: + return + + # Check allowed senders + allowed_senders = self.config["allowed_senders." + tokens[0]] + if allowed_senders and not evt.sender in allowed_senders: + return + + # Sending notification to NTFY + + url = self.config["server_url"] + "/" + self.config["server_topic"] + body = ' '.join(tokens[1:]) + if len(self.config["allowed_locations"]) > 1: + body = tokens[0] + ": " + body + + # Consider authentication + authentication = None + if self.config["server_use_authentication"]: + authentication = aiohttp.BasicAuth(self.config["server_username"], self.config["server_password"]) + + # Send notification + for trash in range(3): # Try to send 3 times + async with self.http.post(url, data=body, auth=authentication) as response: + if response.status == 200: + await evt.react("👍") + return + + + +# That's all, folks \ No newline at end of file diff --git a/maubot.yaml b/maubot.yaml new file mode 100644 index 0000000..daf2dfb --- /dev/null +++ b/maubot.yaml @@ -0,0 +1,10 @@ +maubot: 0.1.0 +id: org.fiftyfiftyonearizona.reports.consumerntfy +version: 1.0.0 +license: MIT +modules: + - consumerntfy +main_class: ConsumerNTFY +config: true +extra_files: + - base-config.yaml \ No newline at end of file diff --git a/readme.md b/readme.md new file mode 100644 index 0000000..48b4eed --- /dev/null +++ b/readme.md @@ -0,0 +1,5 @@ +# FiftyFiftyOneArizona's Matrix-Based Reporting System, NTFY Consumer + +Please see https://git.fiftyfiftyonearizona.org/webmaster/matrix-report-documentation + +This plugin supports whitelisting state/territory designators, allowed senders, and authenticated NTFY posting. \ No newline at end of file