From c6f9711fe6a68ed03f62370aafd4b6125b64c263 Mon Sep 17 00:00:00 2001 From: Thies Mueller Date: Fri, 12 Jun 2026 17:10:59 +0200 Subject: [PATCH] initial commit --- .gitignore | 1 + README.md | 41 +++++++++++ app.py | 164 ++++++++++++++++++++++++++++++++++++++++++++ config.example.yaml | 10 +++ requirements.txt | 4 ++ 5 files changed, 220 insertions(+) create mode 100644 .gitignore create mode 100644 README.md create mode 100644 app.py create mode 100644 config.example.yaml create mode 100644 requirements.txt diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..a539470 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +config.yaml \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..6f709fd --- /dev/null +++ b/README.md @@ -0,0 +1,41 @@ + +## Beispiel Request + +```bash +curl -X POST http://127.0.0.1:5501/notify \ + -H "Authorization: Bearer super-secret-token" \ + -H "Content-Type: application/json" \ + -d '{ + "type": "warning", + "title": "3. Lauf verschiebt sich", + "message": "Der 3. Lauf verschiebt sich um wenige Minuten." + }' +``` + +### API Call firebase + +```json +{ + "type": "info", + "title": "⚠️ 3. Lauf verschiebt sicht", + "message": "Der 3. Lauf verschiebt sich um wenige Minuten." +} +``` + +#### API Call APNS2 + +```json +{ + "severity": "warning", + "notification": "3. Lauf verschiebt sicht\nDer 3. Lauf verschiebt sich um wenige Minuten" +} +``` + +# Ausführen + +```bash +python3 -m venv .venv +source .venv/bin/activate +pip3 install -r requirements.txt +python3 app.py +``` \ No newline at end of file diff --git a/app.py b/app.py new file mode 100644 index 0000000..747e510 --- /dev/null +++ b/app.py @@ -0,0 +1,164 @@ +from flask import Flask, request, jsonify +import requests +import yaml + +app = Flask(__name__) + +with open("config.yaml", "r") as f: + config = yaml.safe_load(f) + +SERVER_TOKEN = config["server"]["bearer_token"] + +APNS2_CONFIG = config["apns2"] +FIREBASE_CONFIG = config["firebase"] + + +PREFIX_MAP = { + "warning": "⚠️ ", + "urgent": "❗️ ", + "danger": "‼️ ", +} + + +def check_auth(req): + auth = req.headers.get("Authorization", "") + + if not auth.startswith("Bearer "): + return False + + token = auth.replace("Bearer ", "", 1) + + return token == SERVER_TOKEN + + +def build_firebase_title(notification_type, title): + prefix = PREFIX_MAP.get(notification_type, "") + return f"{prefix}{title}" + + +def send_to_apns2(notification_type, title, message): + payload = { + "severity": notification_type, + "notification": f"{title}\n{message}" + } + + headers = { + "Authorization": f"Bearer {APNS2_CONFIG['bearer_token']}", + "Content-Type": "application/json" + } + + response = requests.post( + APNS2_CONFIG["url"], + json=payload, + headers=headers, + timeout=10 + ) + + return { + "status_code": response.status_code, + "body": response.text + } + + +def send_to_firebase(notification_type, title, message): + firebase_title = build_firebase_title(notification_type, title) + + payload = { + "type": "info", + "title": firebase_title, + "message": message + } + + headers = { + "Authorization": f"Bearer {FIREBASE_CONFIG['bearer_token']}", + "Content-Type": "application/json" + } + + response = requests.post( + FIREBASE_CONFIG["url"], + json=payload, + headers=headers, + timeout=10 + ) + + return { + "status_code": response.status_code, + "body": response.text + } + +@app.route("/notify", methods=["POST"]) +def notify(): + if not check_auth(request): + return jsonify({ + "error": "Unauthorized" + }), 401 + + data = request.get_json(silent=True) + + if not data: + return jsonify({ + "error": "Invalid JSON" + }), 400 + + required_fields = ["type", "title", "message"] + + for field in required_fields: + if field not in data: + return jsonify({ + "error": f"Missing field: {field}" + }), 400 + + notification_type = data["type"] + + allowed_types = ["info", "warning", "urgent", "danger"] + + if notification_type not in allowed_types: + return jsonify({ + "error": "Invalid type" + }), 400 + + title = data["title"] + message = data["message"] + + results = {} + + try: + apns_result = send_to_apns2( + notification_type, + title, + message + ) + + results["apns2"] = apns_result + + except Exception as e: + results["apns2"] = { + "error": str(e) + } + + try: + firebase_result = send_to_firebase( + notification_type, + title, + message + ) + + results["firebase"] = firebase_result + + except Exception as e: + results["firebase"] = { + "error": str(e) + } + + return jsonify({ + "success": True, + "results": results + }) + + +if __name__ == "__main__": + app.run( + host="0.0.0.0", + port=5501, + debug=False + ) \ No newline at end of file diff --git a/config.example.yaml b/config.example.yaml new file mode 100644 index 0000000..0f583d9 --- /dev/null +++ b/config.example.yaml @@ -0,0 +1,10 @@ +server: + bearer_token: "super-secret-token" + +apns2: + url: "https://apns.example.com/api/customnotify" + bearer_token: "apns2-token" + +firebase: + url: "https://firebase.example.com/push" + bearer_token: "firebase-token" \ No newline at end of file diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..2435e0d --- /dev/null +++ b/requirements.txt @@ -0,0 +1,4 @@ +Flask +PyYAML +requests +gunicorn \ No newline at end of file