diff --git a/app/client/modules/notifications/components/create-notification-form.tsx b/app/client/modules/notifications/components/create-notification-form.tsx index 712baaa..79b4353 100644 --- a/app/client/modules/notifications/components/create-notification-form.tsx +++ b/app/client/modules/notifications/components/create-notification-form.tsx @@ -64,6 +64,12 @@ const defaultValuesForType = { topic: "", priority: "default" as const, }, + pushover: { + type: "pushover" as const, + userKey: "", + apiToken: "", + priority: 0, + }, custom: { type: "custom" as const, shoutrrrUrl: "", @@ -141,6 +147,7 @@ export const CreateNotificationForm = ({ onSubmit, mode = "create", initialValue Discord Gotify Ntfy + Pushover Custom (Shoutrrr URL) @@ -490,6 +497,80 @@ export const CreateNotificationForm = ({ onSubmit, mode = "create", initialValue )} + {watchedType === "pushover" && ( + <> + ( + + User Key + + + + Your Pushover user key from the dashboard. + + + )} + /> + ( + + API Token + + + + Application API token from your Pushover application. + + + )} + /> + ( + + Devices (Optional) + + + + Comma-separated list of device names. Leave empty for all devices. + + + )} + /> + ( + + Priority + + Message priority level. + + + )} + /> + + )} + {watchedType === "custom" && ( Shoutrrr documentation -   for supported services and URL formats. +  for supported services and URL formats. diff --git a/app/client/modules/notifications/routes/notifications.tsx b/app/client/modules/notifications/routes/notifications.tsx index 546c888..f4497c6 100644 --- a/app/client/modules/notifications/routes/notifications.tsx +++ b/app/client/modules/notifications/routes/notifications.tsx @@ -101,6 +101,7 @@ export default function Notifications({ loaderData }: Route.ComponentProps) { Discord Gotify Ntfy + Pushover Custom diff --git a/app/schemas/notifications.ts b/app/schemas/notifications.ts index da20d15..998675c 100644 --- a/app/schemas/notifications.ts +++ b/app/schemas/notifications.ts @@ -6,6 +6,7 @@ export const NOTIFICATION_TYPES = { discord: "discord", gotify: "gotify", ntfy: "ntfy", + pushover: "pushover", custom: "custom", } as const; @@ -52,6 +53,14 @@ export const ntfyNotificationConfigSchema = type({ priority: "'max' | 'high' | 'default' | 'low' | 'min'", }); +export const pushoverNotificationConfigSchema = type({ + type: "'pushover'", + userKey: "string", + apiToken: "string", + devices: "string?", + priority: "-1 | 0 | 1", +}); + export const customNotificationConfigSchema = type({ type: "'custom'", shoutrrrUrl: "string", @@ -62,6 +71,7 @@ export const notificationConfigSchema = emailNotificationConfigSchema .or(discordNotificationConfigSchema) .or(gotifyNotificationConfigSchema) .or(ntfyNotificationConfigSchema) + .or(pushoverNotificationConfigSchema) .or(customNotificationConfigSchema); export type NotificationConfig = typeof notificationConfigSchema.infer; diff --git a/app/server/modules/notifications/builders/index.ts b/app/server/modules/notifications/builders/index.ts index ffe84c3..a6e125c 100644 --- a/app/server/modules/notifications/builders/index.ts +++ b/app/server/modules/notifications/builders/index.ts @@ -4,6 +4,7 @@ import { buildSlackShoutrrrUrl } from "./slack"; import { buildDiscordShoutrrrUrl } from "./discord"; import { buildGotifyShoutrrrUrl } from "./gotify"; import { buildNtfyShoutrrrUrl } from "./ntfy"; +import { buildPushoverShoutrrrUrl } from "./pushover"; import { buildCustomShoutrrrUrl } from "./custom"; export function buildShoutrrrUrl(config: NotificationConfig): string { @@ -18,6 +19,8 @@ export function buildShoutrrrUrl(config: NotificationConfig): string { return buildGotifyShoutrrrUrl(config); case "ntfy": return buildNtfyShoutrrrUrl(config); + case "pushover": + return buildPushoverShoutrrrUrl(config); case "custom": return buildCustomShoutrrrUrl(config); default: { diff --git a/app/server/modules/notifications/builders/pushover.ts b/app/server/modules/notifications/builders/pushover.ts new file mode 100644 index 0000000..5f735a0 --- /dev/null +++ b/app/server/modules/notifications/builders/pushover.ts @@ -0,0 +1,24 @@ +import type { NotificationConfig } from "~/schemas/notifications"; + +export function buildPushoverShoutrrrUrl( + config: Extract, +): string { + const params = new URLSearchParams(); + + if (config.devices) { + params.append("devices", config.devices); + } + + if (config.priority !== undefined) { + params.append("priority", config.priority.toString()); + } + + const queryString = params.toString(); + let shoutrrrUrl = `pushover://shoutrrr:${config.apiToken}@${config.userKey}/`; + + if (queryString) { + shoutrrrUrl += `?${queryString}`; + } + + return shoutrrrUrl; +} diff --git a/app/server/modules/notifications/notifications.service.ts b/app/server/modules/notifications/notifications.service.ts index 16d6806..8b7d311 100644 --- a/app/server/modules/notifications/notifications.service.ts +++ b/app/server/modules/notifications/notifications.service.ts @@ -60,6 +60,11 @@ async function encryptSensitiveFields(config: NotificationConfig): Promise