From d12196f53ac1ba5bfef4ffbd783d00995f8da34e Mon Sep 17 00:00:00 2001 From: Aaron Bird Date: Wed, 28 Jan 2026 01:12:23 +0000 Subject: [PATCH] feat: add Mattermost notification support Add mmost:// and mmosts:// (secure) Apprise URL support for Mattermost incoming webhooks. Supports optional botname override and custom paths. - Add sendMattermost() function following existing notification patterns - Update NotificationModal with Mattermost in examples and description --- src/lib/server/notifications.ts | 51 +++++++++++++++++++ .../notifications/NotificationModal.svelte | 9 ++-- 2 files changed, 56 insertions(+), 4 deletions(-) diff --git a/src/lib/server/notifications.ts b/src/lib/server/notifications.ts index 904c89d..2168cba 100644 --- a/src/lib/server/notifications.ts +++ b/src/lib/server/notifications.ts @@ -121,6 +121,9 @@ async function sendToAppriseUrl(url: string, payload: NotificationPayload): Prom case 'slack': case 'slacks': return await sendSlack(url, payload); + case 'mmost': + case 'mmosts': + return await sendMattermost(url, payload); case 'tgram': return await sendTelegram(url, payload); case 'gotify': @@ -207,6 +210,54 @@ async function sendSlack(appriseUrl: string, payload: NotificationPayload): Prom } } +// Mattermost webhook +async function sendMattermost(appriseUrl: string, payload: NotificationPayload): Promise { + // mmost://[botname@]hostname[:port][/path]/token or mmosts://... + const isSecure = appriseUrl.startsWith('mmosts'); + const protocol = isSecure ? 'https' : 'http'; + + // Remove the scheme + let urlPart = appriseUrl.replace(/^mmosts?:\/\//, ''); + + // Check for botname (username@hostname format) + let username: string | undefined; + const atIndex = urlPart.indexOf('@'); + if (atIndex !== -1) { + username = urlPart.substring(0, atIndex); + urlPart = urlPart.substring(atIndex + 1); + } + + // The token is the last segment, everything else is hostname[:port][/path] + const lastSlashIndex = urlPart.lastIndexOf('/'); + if (lastSlashIndex === -1) { + console.error('[Notifications] Invalid Mattermost URL format. Expected: mmost://[botname@]hostname[:port][/path]/token'); + return false; + } + + const token = urlPart.substring(lastSlashIndex + 1); + const hostAndPath = urlPart.substring(0, lastSlashIndex); + + // Build the webhook URL: {protocol}://{hostname}[:{port}][/{path}]/hooks/{token} + const url = `${protocol}://${hostAndPath}/hooks/${token}`; + + const envTag = payload.environmentName ? ` \`${payload.environmentName}\`` : ''; + const body: Record = { + text: `*${payload.title}*${envTag}\n${payload.message}` + }; + + if (username) { + body.username = username; + } + + const response = await fetch(url, { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify(body) + }); + + return response.ok; +} + // Telegram async function sendTelegram(appriseUrl: string, payload: NotificationPayload): Promise { // tgram://bot_token/chat_id diff --git a/src/routes/settings/notifications/NotificationModal.svelte b/src/routes/settings/notifications/NotificationModal.svelte index 3c193df..92fe057 100644 --- a/src/routes/settings/notifications/NotificationModal.svelte +++ b/src/routes/settings/notifications/NotificationModal.svelte @@ -414,14 +414,15 @@ placeholder="gotify://hostname/app-token discord://webhook_id/webhook_token slack://token_a/token_b/token_c +mmost://hostname/webhook-token tgram://bot_token/chat_id ntfy://my-topic pushover://user_key/api_token jsons://hostname/webhook/path" - class="flex min-h-[220px] w-full rounded-md border border-input bg-transparent px-3 py-2 text-sm shadow-sm placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring" - > -

- Supports Gotify (gotify:// or gotifys:// for HTTPS), Discord, Slack, Telegram, ntfy, Pushover, and generic JSON webhooks. + class="flex min-h-[220px] w-full rounded-md border border-input bg-transparent px-3 py-2 text-sm shadow-sm placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring" + > +

+ Supports Gotify (gotify:// or gotifys:// for HTTPS), Discord, Slack, Mattermost (mmost:// or mmosts://), Telegram, ntfy, Pushover, and generic JSON webhooks.