Pushover notifications can target specific devices
This commit is contained in:
5 files changed
+104
-12
No files matched your search
@@ -108,6 +108,7 @@ async function sendToAppriseUrl(url: string, payload: NotificationPayload): Prom
|
||||
case 'apprises':
|
||||
return await sendApprise(url, payload);
|
||||
case 'pushover':
|
||||
case 'pover':
|
||||
return await sendPushover(url, payload);
|
||||
case 'json':
|
||||
case 'jsons':
|
||||
|
||||
@@ -1,13 +1,14 @@
|
||||
/** Pushover. pushover://user_key/api_token. */
|
||||
/** Pushover. pushover://user_key/api_token[/device...] or pover://user_key@api_token[/device...]. */
|
||||
import { notificationFetch, drainResponse, type NotificationPayload, type NotificationResult } from './shared';
|
||||
import { parsePushoverUrl } from '$lib/utils/notification-parsers';
|
||||
|
||||
export async function sendPushover(appriseUrl: string, payload: NotificationPayload): Promise<NotificationResult> {
|
||||
const match = appriseUrl.match(/^pushover:\/\/([^/]+)\/(.+)/);
|
||||
if (!match) {
|
||||
return { success: false, error: 'Invalid Pushover URL format. Expected: pushover://user_key/api_token' };
|
||||
const parsed = parsePushoverUrl(appriseUrl);
|
||||
if (!parsed) {
|
||||
return { success: false, error: 'Invalid Pushover URL format. Expected: pushover://user_key/api_token[/device]' };
|
||||
}
|
||||
|
||||
const [, userKey, apiToken] = match;
|
||||
const { userKey, apiToken, device } = parsed;
|
||||
const url = 'https://api.pushover.net/1/messages.json';
|
||||
const titleWithEnv = payload.environmentName ? `${payload.title} [${payload.environmentName}]` : payload.title;
|
||||
|
||||
@@ -20,7 +21,9 @@ export async function sendPushover(appriseUrl: string, payload: NotificationPayl
|
||||
user: userKey,
|
||||
title: titleWithEnv,
|
||||
message: payload.message,
|
||||
priority: payload.type === 'error' ? 1 : 0
|
||||
priority: payload.type === 'error' ? 1 : 0,
|
||||
// Optional: a comma-separated device list restricts delivery; omit to reach all devices.
|
||||
...(device ? { device } : {})
|
||||
})
|
||||
});
|
||||
|
||||
|
||||
@@ -53,6 +53,38 @@ export function buildGotifyUrl(appriseUrl: string): { url: string; priority?: nu
|
||||
};
|
||||
}
|
||||
|
||||
// --- Pushover ---
|
||||
|
||||
/**
|
||||
* Parse a Pushover apprise URL into its parts. Two accepted schemes, both with
|
||||
* an OPTIONAL trailing device list (backward compatible - existing
|
||||
* pushover://user/token URLs parse with device undefined):
|
||||
* pushover://user_key/api_token[/device1[/device2...]]
|
||||
* pover://user_key@api_token[/device1[/device2...]] (Apprise-native form)
|
||||
* The Pushover API `device` field is a comma-separated list, so multiple path
|
||||
* segments are joined with commas. Returns null on a malformed URL.
|
||||
*/
|
||||
export function parsePushoverUrl(
|
||||
url: string
|
||||
): { userKey: string; apiToken: string; device?: string } | null {
|
||||
let userKey: string;
|
||||
let apiToken: string;
|
||||
let rest: string;
|
||||
|
||||
const pover = url.match(/^pover:\/\/([^/@]+)@([^/]+)(?:\/(.*))?$/);
|
||||
if (pover) {
|
||||
[, userKey, apiToken, rest = ''] = pover;
|
||||
} else {
|
||||
const push = url.match(/^pushover:\/\/([^/]+)\/([^/]+)(?:\/(.*))?$/);
|
||||
if (!push) return null;
|
||||
[, userKey, apiToken, rest = ''] = push;
|
||||
}
|
||||
|
||||
if (!userKey || !apiToken) return null;
|
||||
const devices = rest.split('/').map((d) => d.trim()).filter(Boolean);
|
||||
return { userKey, apiToken, device: devices.length ? devices.join(',') : undefined };
|
||||
}
|
||||
|
||||
// --- Workflows (Microsoft Power Automate) ---
|
||||
|
||||
export function parseWorkflowsUrl(appriseUrl: string): { hostname: string; workflow: string; signature: string } | null {
|
||||
|
||||
Reference in new issue
Block a user