mirror of
https://github.com/Finsys/dockhand.git
synced 2026-06-17 19:09:33 +03:00
feat(notifications): add Bark push support
Add Bark as a supported Apprise notification protocol. Supported URL formats: - bark://bark_key uses the official Bark server at https://api.day.app/ - bark://host/bark_key uses a custom Bark server over HTTP - barks://host/bark_key uses a custom Bark server over HTTPS Bark notifications are sent with POST JSON payloads containing the device key, title, and body. The notification settings modal now lists Bark examples in the Apprise URL placeholder and support text.
This commit is contained in:
committed by
Jarek Krochmalski
parent
3cbcfa3cdb
commit
b7a8cca387
@@ -129,6 +129,9 @@ async function sendToAppriseUrl(url: string, payload: NotificationPayload): Prom
|
|||||||
case 'ntfy':
|
case 'ntfy':
|
||||||
case 'ntfys':
|
case 'ntfys':
|
||||||
return await sendNtfy(url, payload);
|
return await sendNtfy(url, payload);
|
||||||
|
case 'bark':
|
||||||
|
case 'barks':
|
||||||
|
return await sendBark(url, payload);
|
||||||
case 'pushover':
|
case 'pushover':
|
||||||
return await sendPushover(url, payload);
|
return await sendPushover(url, payload);
|
||||||
case 'json':
|
case 'json':
|
||||||
@@ -435,6 +438,66 @@ async function sendNtfy(appriseUrl: string, payload: NotificationPayload): Promi
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Bark
|
||||||
|
async function sendBark(appriseUrl: string, payload: NotificationPayload): Promise<NotificationResult> {
|
||||||
|
// Supported formats:
|
||||||
|
// bark://device_key (official api.day.app server)
|
||||||
|
// bark://host/device_key (custom server over HTTP)
|
||||||
|
// barks://host/device_key (custom server over HTTPS)
|
||||||
|
const isSecure = appriseUrl.startsWith('barks');
|
||||||
|
const path = appriseUrl.replace(/^barks?:\/\//, '');
|
||||||
|
|
||||||
|
let url: string;
|
||||||
|
let deviceKey: string;
|
||||||
|
|
||||||
|
if (!path.includes('/')) {
|
||||||
|
if (!path) {
|
||||||
|
return { success: false, error: 'Invalid Bark URL format. Expected: bark://device_key, bark://host/device_key, or barks://host/device_key' };
|
||||||
|
}
|
||||||
|
url = 'https://api.day.app/push';
|
||||||
|
deviceKey = path;
|
||||||
|
} else {
|
||||||
|
const parts = path.split('/');
|
||||||
|
if (parts.length !== 2) {
|
||||||
|
return { success: false, error: 'Invalid Bark URL format. Expected: bark://device_key, bark://host/device_key, or barks://host/device_key' };
|
||||||
|
}
|
||||||
|
const [host, key] = parts;
|
||||||
|
deviceKey = key;
|
||||||
|
if (!host || !deviceKey) {
|
||||||
|
return { success: false, error: 'Invalid Bark URL format. Expected: bark://device_key, bark://host/device_key, or barks://host/device_key' };
|
||||||
|
}
|
||||||
|
url = `${isSecure ? 'https' : 'http'}://${host}/push`;
|
||||||
|
}
|
||||||
|
|
||||||
|
const titleWithEnv = payload.environmentName ? `${payload.title} [${payload.environmentName}]` : payload.title;
|
||||||
|
const body: Record<string, string> = {
|
||||||
|
device_key: deviceKey,
|
||||||
|
title: titleWithEnv,
|
||||||
|
body: payload.message
|
||||||
|
};
|
||||||
|
|
||||||
|
if (payload.type === 'error') {
|
||||||
|
body.level = 'timeSensitive';
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const response = await fetch(url, {
|
||||||
|
method: 'POST',
|
||||||
|
headers: { 'Content-Type': 'application/json' },
|
||||||
|
body: JSON.stringify(body)
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!response.ok) {
|
||||||
|
const text = await response.text().catch(() => '');
|
||||||
|
return { success: false, error: `Bark error ${response.status}: ${text || response.statusText}` };
|
||||||
|
}
|
||||||
|
await drainResponse(response);
|
||||||
|
return { success: true };
|
||||||
|
} catch (error) {
|
||||||
|
return { success: false, error: `Bark connection failed: ${error instanceof Error ? error.message : String(error)}` };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Pushover
|
// Pushover
|
||||||
async function sendPushover(appriseUrl: string, payload: NotificationPayload): Promise<NotificationResult> {
|
async function sendPushover(appriseUrl: string, payload: NotificationPayload): Promise<NotificationResult> {
|
||||||
// pushover://user_key/api_token
|
// pushover://user_key/api_token
|
||||||
|
|||||||
@@ -427,11 +427,14 @@ ntfy://host/topic?auth=base64token&priority=3
|
|||||||
ntfys://host/topic?auth=base64token
|
ntfys://host/topic?auth=base64token
|
||||||
pushover://user_key/api_token
|
pushover://user_key/api_token
|
||||||
workflows://hostname/workflow/signature
|
workflows://hostname/workflow/signature
|
||||||
|
bark://bark_key
|
||||||
|
bark://host/bark_key
|
||||||
|
barks://host/bark_key
|
||||||
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, Mattermost (mmost:// or mmosts://), Telegram, ntfy, Pushover, Workflows (for e.g. Microsoft Teams), and generic JSON webhooks.
|
Supports Gotify (gotify:// or gotifys:// for HTTPS), Discord, Slack, Mattermost (mmost:// or mmosts://), Telegram, ntfy, Bark, Pushover, Workflows (for e.g. Microsoft Teams), and generic JSON webhooks.
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Reference in New Issue
Block a user