diff --git a/README.md b/README.md index d60a7c0..badb350 100644 --- a/README.md +++ b/README.md @@ -38,7 +38,13 @@ The default values are below. "ping": false, "userPing": "@someone", "userPingServer": "matrix.org" - } + }, + "ntfy": { + "enable": False, + "auth": "user:password", + "server": "ntfy.example.com", + "topic": "Alerts" + } } ``` `configTime` (seconds) is the time between each check of all the PR. @@ -48,6 +54,10 @@ The default values are below. `matrix.room` (string) Matrix room to send the notifications. `matrix.ping` (boolean) Pings a user in the notification messages. `matrix.userPing` and `matrix.userPingServer` (strings) are the required information for the ping. +`ntfy.enable` (boolean) Enable ntfy notifications. +`ntfy.auth` (string of form user:password) Credentials. If you use a token, please let user empty and put the token in password. An empty auth header will skip auth. +`ntfy.server` (string url) Ntfy server to use. +`ntfy.topic` (string) Ntfy topic for the notification. ### Usage diff --git a/nixpkgs_notifier.py b/nixpkgs_notifier.py index 8e1ad98..f8f1c90 100644 --- a/nixpkgs_notifier.py +++ b/nixpkgs_notifier.py @@ -35,6 +35,12 @@ DEFAULT_CONFIG = { "ping": False, "userPing": "@someone", "userPingServer": "matrix.org" + }, + "ntfy": { + "enable": False, + "auth": "user:password", + "server": "ntfy.example.com", + "topic": "Alerts" } } @@ -147,6 +153,53 @@ def matrixNotify(PRnumber): capture_output=True, text=True ) + +def ntfyNotify(PRnumber): + message = ( + f"PR #{PRnumber} {getPRTitle(PRnumber)} " + "is now available in nixos-unstable.\n" + f"https://nixpk.gs/pr-tracker.html?pr={PRnumber}" + ) + + buf = io.BytesIO() + + c = pycurl.Curl() + + c.setopt( + c.URL, + f"https://{ntfyServer}/{ntfyTopic}" + ) + + headers = [ + "Title: nixpkgs PR merged", + "Priority: default", + "Tags: white_check_mark" + ] + + c.setopt(c.HTTPHEADER, headers) + + if ntfyAuth: + c.setopt(c.USERPWD, ntfyAuth) + + c.setopt(c.POST, True) + c.setopt(c.POSTFIELDS, message) + c.setopt(c.WRITEDATA, buf) + + try: + c.perform() + + if c.getinfo(c.RESPONSE_CODE) != 200: + print( + f"ntfy notification failed: " + f"HTTP {c.getinfo(c.RESPONSE_CODE)}" + ) + + except Exception as e: + print(f"ntfy notification error: {e}") + + finally: + c.close() + def fetchStatus(PRnumber): buf = io.BytesIO() @@ -194,6 +247,10 @@ def main(): global matrixPing global matrixUserToPing global matrixUserServer + global shouldNtfyNotify + global ntfyServer + global ntfyTopic + global ntfyAuth configTime = cfg["configTime"] configFetchTime = cfg["configFetchTime"] @@ -203,6 +260,10 @@ def main(): matrixPing = cfg["matrix"]["ping"] matrixUserToPing = cfg["matrix"]["userPing"] matrixUserServer = cfg["matrix"]["userPingServer"] + shouldNtfyNotify = cfg["ntfy"]["enable"] + ntfyServer = cfg["ntfy"]["server"] + ntfyTopic = cfg["ntfy"]["topic"] + ntfyAuth = cfg["ntfy"]["auth"] if len(sys.argv) < 2: @@ -267,6 +328,8 @@ def main(): localNotify(PR) if shouldMatrixNotify: matrixNotify(PR) + if shouldNtfyNotify: + ntfyNotify(PR) removeTracker(PR) print(f"Removed PR #{PR} from tracking")