Compare commits
2
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
514bfdcf87 | ||
|
|
5ec38d6136 |
No files matched your search
@@ -0,0 +1,42 @@
|
|||||||
|
---
|
||||||
|
title: 'Pushover'
|
||||||
|
description: "Pushover is a service for receiving real-time push notifications on your Android, iPhone, iPad, and Desktop devices."
|
||||||
|
hide_title: true
|
||||||
|
---
|
||||||
|
|
||||||
|
import { notificationsWidget } from '@site/docs/widgets/notifications';
|
||||||
|
import { AddingIntegration } from '@site/src/components/integrations/adding';
|
||||||
|
import { IntegrationHeader } from '@site/src/components/integrations/header';
|
||||||
|
import { IntegrationSecrets } from '@site/src/components/integrations/secrets';
|
||||||
|
import { IntegrationCapabilites } from '@site/src/components/integrations/widgets';
|
||||||
|
import { pushoverIntegration } from '.';
|
||||||
|
|
||||||
|
<IntegrationHeader
|
||||||
|
integration={pushoverIntegration}
|
||||||
|
categories={['Notifications', 'Messaging']}
|
||||||
|
/>
|
||||||
|
|
||||||
|
### Widgets & Capabilities
|
||||||
|
<IntegrationCapabilites
|
||||||
|
items={[{
|
||||||
|
widget: notificationsWidget
|
||||||
|
}]}
|
||||||
|
/>
|
||||||
|
|
||||||
|
### Adding the integration
|
||||||
|
<AddingIntegration />
|
||||||
|
|
||||||
|
### Secrets
|
||||||
|
<IntegrationSecrets secrets={[{
|
||||||
|
credentials: ['apiKey', 'userKey'],
|
||||||
|
steps: [
|
||||||
|
{
|
||||||
|
title: 'API Token (Application Key)',
|
||||||
|
description: 'Register your application on the [Pushover website](https://pushover.net/apps) and copy the API token/application key.'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'User Key',
|
||||||
|
description: 'Your user key is viewable on the [Pushover dashboard](https://pushover.net/) when logged in. It is a 30-character string (e.g. `uQiRzpo4DXghDmr9QzzfQu27cmVRsG`).'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}]} />
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
import { IntegrationDefinition } from "@site/src/types";
|
||||||
|
|
||||||
|
export const pushoverIntegration: IntegrationDefinition = {
|
||||||
|
name: "Pushover",
|
||||||
|
description: "Pushover is a service for receiving real-time push notifications on your devices.",
|
||||||
|
iconUrl: "https://cdn.jsdelivr.net/gh/homarr-labs/dashboard-icons/svg/pushover.svg",
|
||||||
|
path: "../../integrations/pushover",
|
||||||
|
};
|
||||||
@@ -15,6 +15,7 @@ import { notificationsWidget } from '.';
|
|||||||
import { ntfyIntegration } from '@site/docs/integrations/ntfy';
|
import { ntfyIntegration } from '@site/docs/integrations/ntfy';
|
||||||
import { nextcloudIntegration } from '@site/docs/integrations/nextcloud';
|
import { nextcloudIntegration } from '@site/docs/integrations/nextcloud';
|
||||||
import { gotifyIntegration } from '@site/docs/integrations/gotify';
|
import { gotifyIntegration } from '@site/docs/integrations/gotify';
|
||||||
|
import { pushoverIntegration } from '@site/docs/integrations/pushover';
|
||||||
|
|
||||||
<WidgetHeader
|
<WidgetHeader
|
||||||
widget={notificationsWidget}
|
widget={notificationsWidget}
|
||||||
@@ -35,7 +36,8 @@ import notificationsScreenshot from './img/notifications.png';
|
|||||||
items={[
|
items={[
|
||||||
{ integration: ntfyIntegration },
|
{ integration: ntfyIntegration },
|
||||||
{ integration: nextcloudIntegration },
|
{ integration: nextcloudIntegration },
|
||||||
{ integration: gotifyIntegration }
|
{ integration: gotifyIntegration },
|
||||||
|
{ integration: pushoverIntegration }
|
||||||
]}
|
]}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
|||||||
@@ -326,6 +326,7 @@ export type HomarrDocumentationPath =
|
|||||||
| "/docs/integrations/quay"
|
| "/docs/integrations/quay"
|
||||||
| "/docs/integrations/ntfy"
|
| "/docs/integrations/ntfy"
|
||||||
| "/docs/integrations/gotify"
|
| "/docs/integrations/gotify"
|
||||||
|
| "/docs/integrations/pushover"
|
||||||
| "/docs/integrations/ical"
|
| "/docs/integrations/ical"
|
||||||
| "/docs/integrations/anchor"
|
| "/docs/integrations/anchor"
|
||||||
| "/docs/integrations/truenas"
|
| "/docs/integrations/truenas"
|
||||||
|
|||||||
@@ -41,6 +41,7 @@ export const integrationDocSlugs: Record<IntegrationKind, string | null> = {
|
|||||||
quay: "quay",
|
quay: "quay",
|
||||||
ntfy: "ntfy",
|
ntfy: "ntfy",
|
||||||
gotify: "gotify",
|
gotify: "gotify",
|
||||||
|
pushover: "pushover",
|
||||||
ical: "ical",
|
ical: "ical",
|
||||||
anchor: "anchor",
|
anchor: "anchor",
|
||||||
truenas: "truenas",
|
truenas: "truenas",
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ export const integrationSecretKindObject = {
|
|||||||
githubAppId: { isPublic: true, multiline: false },
|
githubAppId: { isPublic: true, multiline: false },
|
||||||
githubInstallationId: { isPublic: true, multiline: false },
|
githubInstallationId: { isPublic: true, multiline: false },
|
||||||
slug: { isPublic: true, multiline: false },
|
slug: { isPublic: true, multiline: false },
|
||||||
|
userKey: { isPublic: false, multiline: false },
|
||||||
} satisfies Record<string, { isPublic: boolean; multiline: boolean }>;
|
} satisfies Record<string, { isPublic: boolean; multiline: boolean }>;
|
||||||
|
|
||||||
export const integrationSecretKinds = objectKeys(integrationSecretKindObject);
|
export const integrationSecretKinds = objectKeys(integrationSecretKindObject);
|
||||||
@@ -362,6 +363,14 @@ export const integrationDefs = {
|
|||||||
category: ["notifications"],
|
category: ["notifications"],
|
||||||
documentationUrl: createDocumentationLink("/docs/integrations/gotify"),
|
documentationUrl: createDocumentationLink("/docs/integrations/gotify"),
|
||||||
},
|
},
|
||||||
|
pushover: {
|
||||||
|
name: "Pushover",
|
||||||
|
secretKinds: [["apiKey", "userKey"]],
|
||||||
|
iconUrl: "https://cdn.jsdelivr.net/gh/homarr-labs/dashboard-icons@master/svg/pushover.svg",
|
||||||
|
category: ["notifications"],
|
||||||
|
defaultUrl: "https://api.pushover.net",
|
||||||
|
documentationUrl: createDocumentationLink("/docs/integrations/pushover"),
|
||||||
|
},
|
||||||
ical: {
|
ical: {
|
||||||
name: "iCal",
|
name: "iCal",
|
||||||
secretKinds: [["url"]],
|
secretKinds: [["url"]],
|
||||||
|
|||||||
@@ -39,6 +39,7 @@ import { NextcloudIntegration } from "../nextcloud/nextcloud.integration";
|
|||||||
import { NPMIntegration } from "../npm/npm-integration";
|
import { NPMIntegration } from "../npm/npm-integration";
|
||||||
import { GotifyIntegration } from "../gotify/gotify-integration";
|
import { GotifyIntegration } from "../gotify/gotify-integration";
|
||||||
import { NTFYIntegration } from "../ntfy/ntfy-integration";
|
import { NTFYIntegration } from "../ntfy/ntfy-integration";
|
||||||
|
import { PushoverIntegration } from "../pushover/pushover-integration";
|
||||||
import { OpenMediaVaultIntegration } from "../openmediavault/openmediavault-integration";
|
import { OpenMediaVaultIntegration } from "../openmediavault/openmediavault-integration";
|
||||||
import { OPNsenseIntegration } from "../opnsense/opnsense-integration";
|
import { OPNsenseIntegration } from "../opnsense/opnsense-integration";
|
||||||
import { OverseerrIntegration } from "../overseerr/overseerr-integration";
|
import { OverseerrIntegration } from "../overseerr/overseerr-integration";
|
||||||
@@ -125,6 +126,7 @@ export const integrationCreators = {
|
|||||||
quay: QuayIntegration,
|
quay: QuayIntegration,
|
||||||
ntfy: NTFYIntegration,
|
ntfy: NTFYIntegration,
|
||||||
gotify: GotifyIntegration,
|
gotify: GotifyIntegration,
|
||||||
|
pushover: PushoverIntegration,
|
||||||
mock: MockIntegration,
|
mock: MockIntegration,
|
||||||
truenas: TrueNasIntegration,
|
truenas: TrueNasIntegration,
|
||||||
unraid: UnraidIntegration,
|
unraid: UnraidIntegration,
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ export { ReadarrIntegration } from "./media-organizer/readarr/readarr-integratio
|
|||||||
export { SonarrIntegration } from "./media-organizer/sonarr/sonarr-integration";
|
export { SonarrIntegration } from "./media-organizer/sonarr/sonarr-integration";
|
||||||
export { NextcloudIntegration } from "./nextcloud/nextcloud.integration";
|
export { NextcloudIntegration } from "./nextcloud/nextcloud.integration";
|
||||||
export { GotifyIntegration } from "./gotify/gotify-integration";
|
export { GotifyIntegration } from "./gotify/gotify-integration";
|
||||||
|
export { PushoverIntegration } from "./pushover/pushover-integration";
|
||||||
export { NTFYIntegration } from "./ntfy/ntfy-integration";
|
export { NTFYIntegration } from "./ntfy/ntfy-integration";
|
||||||
export { OpenMediaVaultIntegration } from "./openmediavault/openmediavault-integration";
|
export { OpenMediaVaultIntegration } from "./openmediavault/openmediavault-integration";
|
||||||
export { GlancesIntegration } from "./glances/glances-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(),
|
||||||
|
});
|
||||||
Reference in new issue
Block a user