diff --git a/base-config.yaml b/base-config.yaml index 2279dc1..e8b8b24 100644 --- a/base-config.yaml +++ b/base-config.yaml @@ -2,9 +2,12 @@ # DO NOT CHANGE THIS UNLESS YOU KNOW WHAT YOU ARE DOING command_prefix: report -# Which reigons the bot should pay attention to -# Additionally, optionally whitelist specific accounts for each reigon -allowed_reigons: +# Which regions the bot should pay attention to. +# Pass through empty list to allow all senders for a region. +# Add a list of MatrixIDs to whitelist senders for a region. +# Use __global__ to refer to all regions. +# Code looks to see if a sender is allowed for either a specific region or __global__. +allowed_regions: foo: - "@reports:fiftyfiftyonerarizona.org" bar: @@ -13,18 +16,22 @@ allowed_reigons: buzz: aaa: -# Bot-specific configurations per reigon -reigon_configs: +# Bot-specific configurations per region +# Code will assume no authentication if either username or password are missing. +# Use __global__ to specify an endpoint for all regions. +# Code will push to both __global__ and region-specific endpoint. +region_configs: arizona: # 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: true - server_username: "no" - server_password: "way" + username: "no" + password: "way" # If this bot should send a reaction to the message -# if the notification was successful +# Will send 👍 on successful POST to NTFY, and 👎 on failiure. +# Failiure to post to either the region specific, or __global__ endpoint is +# considered complete failiure. send_reaction: true \ No newline at end of file diff --git a/compile.bash b/compile.bash new file mode 100644 index 0000000..66c85a3 --- /dev/null +++ b/compile.bash @@ -0,0 +1,9 @@ +#!/bin/bash + +# Get filename +id=$(cat maubot.yaml | grep "id:" | tr ' ' '\n' | tail -n1) +version=$(cat maubot.yaml | grep "version:" | tr ' ' '\n' | tail -n1) +filename="$id-$version.mbp" + +# Compress to zip +zip $filename * \ No newline at end of file diff --git a/consumerntfy.py b/consumerntfy.py index aed95b1..5bce54e 100644 --- a/consumerntfy.py +++ b/consumerntfy.py @@ -11,8 +11,8 @@ import aiohttp class Config(BaseProxyConfig): def do_update(self, helper: ConfigUpdateHelper) -> None: helper.copy("command_prefix") - helper.copy("allowed_reigons") - helper.copy("reigon_configs") + helper.copy("allowed_regions") + helper.copy("region_configs") helper.copy("send_reaction") class ConsumerNTFY(Plugin): @@ -29,40 +29,45 @@ class ConsumerNTFY(Plugin): def get_command_name(self) -> str: return self.config["command_prefix"] - # Checks if a sender if allowed to send for a particular reigon - def validateSender(self, reigon: str, sender: str): - # Check that config value exists - if not self.config["allowed_reigons"]: return False - # Check that reigon is allowed - if not self.config["allowed_reigons"][reigon]: return False - # All senders allowed for this reigon - if len(self.config["allowed_reigons"][reigon]) == 0: return True - # Check that sender is allowed for reigon - if not sender in self.config["allowed_reigons"][reigon]: return False - return True + # Checks if a sender if allowed to send for a particular region + def validate_sender(self, region: str, sender: str): + # Mautrix isn't documented, like at all, so I'm just gonna catch the + # error because IDK how to see if a map is inside a map. + try: allowed_list = self.config["allowed_regions"][region] + except: return False + + if allowed_list is None: return True # Empty list + if sender in allowed_list: return True + + # Sender not allowed in region config + return False - # Does the necesary config checks for the given event - # Returns list of reigons to process (strings) - # Currently just the specified reigon and "__global__" - def validateReport(self, evt: MessageEvent, message: str): + # Does the necessary config checks for the given event + # Returns list of recursive configs to process + def validate_report(self, evt: MessageEvent, message: str): # Split command (minus !command_name) into tokens tokens = message.split() - reigon = tokens[0].lower() + region = tokens[0].lower() # Each command must have a state/territory designation and a message - if len(tokens) < 2: return None + if len(tokens) < 2: return [] + # And we must have self.config["region_configs"] + try: trashvariable = self.config["region_configs"] + except: return [] - self.log.debug(reigon) + configs = [] # To be returned - # This is a list of reigons to process for this specific message - # This is only used to consider __global__ - reigons_to_process = [] - if (self.validateSender("__global__", evt.sender)): - reigons_to_process.append("__global__") - if (self.validateSender(reigon, evt.sender)): - reigons_to_process.append(reigon) + allowed_globally = self.validate_sender("__global__", evt.sender) + allowed_region = self.validate_sender(region, evt.sender) - return reigons_to_process + # If user is allowed globally and/or for a region, + # the plugin should process both the region and __global__ configs + if allowed_globally or allowed_region: + for i in ["__global__", region]: + try: configs.append(self.config["region_configs"][i]) + except: trashvariable = None + + return configs # What gets called when !command_name message is sent @command.new(name=get_command_name, help="Report Something") @@ -73,27 +78,26 @@ class ConsumerNTFY(Plugin): # Iterate through each endpoint that the message should be pushed to # (if any) - for reigon in self.validateReport(evt, message): - # Detect no reigons in reaction + for region_config in self.validate_report(evt, message): + # Detect no regions in reaction if ntfy_posts_passed is None: ntfy_posts_passed = True - # Grab reigon-specific conrfig - reigon_config = self.config["reigon_configs"][reigon] + self.log.debug(region_config) # Create notification text split_message = message.split() text = "[" + split_message[0] + "] " + ' '.join(message.split()[1:]) # Build URL - url = reigon_config["server_url"] + "/" + reigon_config["server_topic"] + url = region_config["server_url"] + "/" + region_config["server_topic"] # Consider authentication - authentication = None - if reigon_config["server_use_authentication"]: - authentication = aiohttp.BasicAuth(reigon_config["server_username"], reigon_config["server_password"]) + auth = None + if "username" in region_config and "password" in region_config: + auth = aiohttp.BasicAuth(region_config["username"], region_config["password"]) # Send notification - async with self.http.post(url, data=text, auth=authentication) as response: + async with self.http.post(url, data=text, auth=auth) as response: if not response.status == 200: ntfy_posts_passed = False diff --git a/maubot.yaml b/maubot.yaml index 899e4fe..d040b22 100644 --- a/maubot.yaml +++ b/maubot.yaml @@ -1,6 +1,6 @@ maubot: 0.1.0 id: org.fiftyfiftyonearizona.reports.consumerntfy -version: 1.1.0 +version: 1.2.0 license: MIT modules: - consumerntfy diff --git a/readme.md b/readme.md index 4b621b7..5b3d88d 100644 --- a/readme.md +++ b/readme.md @@ -2,4 +2,12 @@ Please see https://git.fiftyfiftyonearizona.org/webmaster/matrix-report-documentation -This plugin supports whitelisting state/territory designators, allowed senders, reaction receipt, and authenticated NTFY posting. \ No newline at end of file +This plugin supports the following: + +* whitelisting regions, or allowing all regions. +* allowed senders per region, or all regions. +* reaction receipt upon successful POST to NTFY. +* authenticated NTFY POSTing. +* Different NTFY endpoint, topic, and authentication per region. + +Please see [base-config.yaml](base-config.yaml) for explanation of behavior. \ No newline at end of file