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
This commit is contained in:
1 parent
ef26d38fce
commit
d12196f53a
2 files changed
+56
-4
No files matched your search
@@ -121,6 +121,9 @@ async function sendToAppriseUrl(url: string, payload: NotificationPayload): Prom
|
|||||||
case 'slack':
|
case 'slack':
|
||||||
case 'slacks':
|
case 'slacks':
|
||||||
return await sendSlack(url, payload);
|
return await sendSlack(url, payload);
|
||||||
|
case 'mmost':
|
||||||
|
case 'mmosts':
|
||||||
|
return await sendMattermost(url, payload);
|
||||||
case 'tgram':
|
case 'tgram':
|
||||||
return await sendTelegram(url, payload);
|
return await sendTelegram(url, payload);
|
||||||
case 'gotify':
|
case 'gotify':
|
||||||
@@ -207,6 +210,54 @@ async function sendSlack(appriseUrl: string, payload: NotificationPayload): Prom
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Mattermost webhook
|
||||||
|
async function sendMattermost(appriseUrl: string, payload: NotificationPayload): Promise<boolean> {
|
||||||
|
// 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<string, string> = {
|
||||||
|
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
|
// Telegram
|
||||||
async function sendTelegram(appriseUrl: string, payload: NotificationPayload): Promise<NotificationResult> {
|
async function sendTelegram(appriseUrl: string, payload: NotificationPayload): Promise<NotificationResult> {
|
||||||
// tgram://bot_token/chat_id
|
// tgram://bot_token/chat_id
|
||||||
|
|||||||
@@ -414,14 +414,15 @@
|
|||||||
placeholder="gotify://hostname/app-token
|
placeholder="gotify://hostname/app-token
|
||||||
discord://webhook_id/webhook_token
|
discord://webhook_id/webhook_token
|
||||||
slack://token_a/token_b/token_c
|
slack://token_a/token_b/token_c
|
||||||
|
mmost://hostname/webhook-token
|
||||||
tgram://bot_token/chat_id
|
tgram://bot_token/chat_id
|
||||||
ntfy://my-topic
|
ntfy://my-topic
|
||||||
pushover://user_key/api_token
|
pushover://user_key/api_token
|
||||||
jsons://hostname/webhook/path"
|
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"
|
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"
|
||||||
></textarea>
|
></textarea>
|
||||||
<p class="text-xs text-muted-foreground">
|
<p class="text-xs text-muted-foreground">
|
||||||
Supports Gotify (gotify:// or gotifys:// for HTTPS), Discord, Slack, Telegram, ntfy, Pushover, and generic JSON webhooks.
|
Supports Gotify (gotify:// or gotifys:// for HTTPS), Discord, Slack, Mattermost (mmost:// or mmosts://), Telegram, ntfy, Pushover, and generic JSON webhooks.
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Reference in new issue
Block a user