feat: add pushover integration

This commit is contained in:
Manuel committed 2026-07-01 18:53:07 +02:00
1 parent dd2eb3aa66
commit 5ec38d6136
10 files changed
+115 -1

No files matched your search

@@ -39,6 +39,7 @@ import { NextcloudIntegration } from "../nextcloud/nextcloud.integration";
import { NPMIntegration } from "../npm/npm-integration";
import { GotifyIntegration } from "../gotify/gotify-integration";
import { NTFYIntegration } from "../ntfy/ntfy-integration";
import { PushoverIntegration } from "../pushover/pushover-integration";
import { OpenMediaVaultIntegration } from "../openmediavault/openmediavault-integration";
import { OPNsenseIntegration } from "../opnsense/opnsense-integration";
import { OverseerrIntegration } from "../overseerr/overseerr-integration";
@@ -125,6 +126,7 @@ export const integrationCreators = {
quay: QuayIntegration,
ntfy: NTFYIntegration,
gotify: GotifyIntegration,
pushover: PushoverIntegration,
mock: MockIntegration,
truenas: TrueNasIntegration,
unraid: UnraidIntegration,
+1
View File
@@ -19,6 +19,7 @@ export { ReadarrIntegration } from "./media-organizer/readarr/readarr-integratio
export { SonarrIntegration } from "./media-organizer/sonarr/sonarr-integration";
export { NextcloudIntegration } from "./nextcloud/nextcloud.integration";
export { GotifyIntegration } from "./gotify/gotify-integration";
export { PushoverIntegration } from "./pushover/pushover-integration";
export { NTFYIntegration } from "./ntfy/ntfy-integration";
export { OpenMediaVaultIntegration } from "./openmediavault/openmediavault-integration";
export { GlancesIntegration } from "./glances/glances-integration";
@@ -0,0 +1,38 @@
import { ResponseError } from "@homarr/common/server";
import { fetchWithTrustedCertificatesAsync } from "@homarr/core/infrastructure/http";
import { Integration } from "../base/integration";
import type { IntegrationTestingInput } from "../base/integration";
import type { TestingResult } from "../base/test-connection/test-connection-service";
import type { Notification } from "../interfaces/notifications/notification-types";
import type { INotificationsIntegration } from "../interfaces/notifications/notifications-integration";
import { pushoverLimitsResponseSchema } from "./pushover-schema";
export class PushoverIntegration extends Integration implements INotificationsIntegration {
public async testingAsync(input: IntegrationTestingInput): Promise<TestingResult> {
const token = this.getSecretValue("apiKey");
const url = this.url("/1/apps/limits.json", { token });
const response = await input.fetchAsync(url);
if (!response.ok) throw new ResponseError(response);
const result = await pushoverLimitsResponseSchema.safeParseAsync(await response.json());
if (!result.success) throw new Error(`Failed to parse Pushover response: ${result.error.message}`);
if (result.data.status !== 1) throw new Error("Pushover API returned non-success status");
return { success: true };
}
public async getNotificationsAsync(): Promise<Notification[]> {
const token = this.getSecretValue("apiKey");
const url = this.url("/1/apps/limits.json", { token });
const response = await fetchWithTrustedCertificatesAsync(url);
if (!response.ok) throw new ResponseError(response);
const result = await pushoverLimitsResponseSchema.safeParseAsync(await response.json());
if (!result.success) throw new Error(`Failed to parse Pushover response: ${result.error.message}`);
return [];
}
}
@@ -0,0 +1,9 @@
import { z } from "zod/v4";
export const pushoverLimitsResponseSchema = z.object({
status: z.number(),
request: z.string(),
limit: z.number().optional(),
remaining: z.number().optional(),
reset: z.number().optional(),
});