fix: format notification messages for ntfy, Slack, Discord, Gotify#42
Open
bin101 wants to merge 4 commits into
Open
fix: format notification messages for ntfy, Slack, Discord, Gotify#42bin101 wants to merge 4 commits into
bin101 wants to merge 4 commits into
Conversation
Replace the raw JSON dump with human-readable messages and auto-detect
the target system from the webhook URL.
- detect_system(url) — infers "ntfy" | "slack" | "discord" | "gotify"
| "generic" from URL patterns
- Per-system formatters:
• ntfy: {title, message, priority 1-5, tags [emoji aliases]}
Posted as JSON to https://ntfy.sh/<topic> — ntfy reads these fields
natively when Content-Type is application/json
• Slack: {"text": "*Title*\nMessage"} (Incoming Webhook format)
• Discord: {"embeds": [{title, description, color}]} — indigo for
runs, red for auth errors
• Gotify: {title, message, priority 1-10} (ntfy 1-5 × 2)
• Generic: {title, message} + structured fields (event, given, …)
- build_run_payload() now returns human-readable title + one-line
summary ("97 Aktivitäten geprüft · 0 Kudos simuliert"), icon prefix,
ntfy tags, and priority (2 dry-run / 3 live / 4 error)
- build_auth_error_payload() now has title + ⚠️ message + priority 4
- 28 unit tests (6 new detection + 10 formatting + 12 carried over)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
User can now choose the notification system (ntfy / Slack / Discord / Gotify / Generic) from a dropdown in the Settings UI instead of relying on URL-based heuristics. `notifySystem` is persisted in settings.json and passed directly to `send_notification()`. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
JSON publishing breaks when reverse proxies (nginx, Traefik, Caddy) strip or modify the Content-Type header — ntfy then treats the body as plain text and shows the raw JSON blob as the notification. Switching to the headers API (plain text body + X-Title / X-Priority / X-Tags HTTP headers) is proxy-agnostic and works with all ntfy versions. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
HTTP headers must be ASCII. Titles like "Kudosy — Dry-Run abgeschlossen" contain non-ASCII characters (em dash U+2014) that caused httpx to raise an 'ascii codec' error before the request was even sent. ntfy URL-decodes header values, so quote() is the correct solution — the title arrives intact in the notification. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
The previous implementation sent a raw JSON blob to the webhook URL regardless of the target system. On ntfy this shows up as unformatted JSON text with no title, no emoji, and no priority.
Solution
Auto-detect the notification system from the URL and format the payload accordingly.
ntfy.in hostname{title, message, priority 1-5, tags}JSON — ntfy reads these nativelyhooks.slack.com{"text": "*Title*\nMessage"}Incoming Webhookdiscord.com/api/webhooks{"embeds": [{title, description, color}]}— indigo for runs, red for auth errors/messagepath{title, message, priority 1-10}{title, message}+ structured fieldsExample — ntfy now receives:
{ "title": "Kudosy — Dry-Run abgeschlossen", "message": "🔍 97 Aktivitäten geprüft · 0 Kudos simuliert", "priority": 2, "tags": ["mag"] }Test plan
ruff,mypy,pytestall green)🤖 Generated with Claude Code