feat: add dawarich integration

This commit is contained in:
Manuel committed 2026-07-01 11:04:12 +02:00
1 parent b83c8b6546
commit 629f3b0955
4 files changed
+93

No files matched your search

+8
View File
@@ -504,6 +504,13 @@ export const integrationDefs = {
defaultUrl: "http://localhost:8001",
documentationUrl: createDocumentationLink("/docs/integrations/archiveteam-warrior"),
},
dawarich: {
name: "Dawarch",
secretKinds: [["apiKey"]],
iconUrl: "https://cdn.jsdelivr.net/gh/selfhst/icons/png/dawarich.png",
category: ["geolocationTracking"],
documentationUrl: createDocumentationLink("/docs/integrations/dawarich")
},
// This integration only returns mock data, it is used during development (but can also be used in production by directly going to the create page)
mock: {
name: "Mock",
@@ -617,6 +624,7 @@ export const integrationCategories = [
"documents",
"mediaLibrary",
"uptimeMonitoring",
"geolocationTracking"
] as const;
export type IntegrationCategory = (typeof integrationCategories)[number];
@@ -60,6 +60,7 @@ import { UptimeKumaIntegration } from "../uptime-kuma/uptime-kuma-integration";
import { UnifiControllerIntegration } from "../unifi-controller/unifi-controller-integration";
import { UnraidIntegration } from "../unraid/unraid-integration";
import type { Integration, IntegrationInput } from "./integration";
import {DawarichIntegration} from "../dawarich/dawarich-integration";
export const createIntegrationAsync = async <TKind extends keyof typeof integrationCreators>(
integration: IntegrationInput & { kind: TKind },
@@ -143,6 +144,7 @@ export const integrationCreators = {
uptimeKuma: UptimeKumaIntegration,
peaNut: PeaNutIntegration,
beszel: BeszelIntegration,
dawarich: DawarichIntegration
} satisfies Record<IntegrationKind, IntegrationInstance | [(input: IntegrationInput) => Promise<Integration>]>;
type IntegrationInstanceOfKind<TKind extends keyof typeof integrationCreators> = {
@@ -0,0 +1,53 @@
import {fetchWithTrustedCertificatesAsync} from "@homarr/core/infrastructure/http";
import {ResponseError} from "@homarr/common/server";
import {Integration, IntegrationInput, IntegrationTestingInput} from "../base/integration";
import {dawarichPlacesSchema, dawarichStatisticsSchema} from "./dawarich-schemas";
import {z} from "zod/v4";
import {TestingResult} from "../base/test-connection/test-connection-service";
import { TestConnectionError } from "../base/test-connection/test-connection-error";
export class DawarichIntegration extends Integration {
constructor(integration: IntegrationInput) {
super(integration);
}
protected async testingAsync(input: IntegrationTestingInput): Promise<TestingResult> {
const response = await fetchWithTrustedCertificatesAsync(this.url(`/api/v1/users/me`), {
headers: {Authorization: `Bearer ${this.getSecretValue('apiKey')}`},
});
if (response.status === 200) {
return { success: true };
}
return TestConnectionError.StatusResult(response);
}
async getStatisticsAsync(): Promise<{
totalDistanceKm: number,
totalPointsTracked: number,
totalReverseGeocodedPoints: number,
totalCountriesVisited: number,
totalCitiesVisited: number
}> {
const response = await fetchWithTrustedCertificatesAsync(this.url('/api/v1/stats'), {
headers: {Authorization: `Bearer ${this.getSecretValue('apiKey')}`},
});
if (!response.ok)
throw new ResponseError(response);
return dawarichStatisticsSchema.parseAsync(await response.json());
}
async getPlacesAsync(): Promise<z.infer<typeof dawarichPlacesSchema>> {
const response = await fetchWithTrustedCertificatesAsync(this.url('/api/v1/places'), {
headers: {Authorization: `Bearer ${this.getSecretValue('apiKey')}`},
});
if (!response.ok)
throw new ResponseError(response);
return dawarichPlacesSchema.parseAsync(await response.json());
}
}
@@ -0,0 +1,30 @@
import {z} from "zod/v4";
export const dawarichStatisticsSchema = z.object({
"totalDistanceKm": z.number(),
"totalPointsTracked": z.number(),
"totalReverseGeocodedPoints": z.number(),
"totalCountriesVisited": z.number(),
"totalCitiesVisited": z.number()
});
export const dawarichPlacesSchema = z.array(z.object({
"id": z.number(),
"name": z.string(),
"latitude": z.number(),
"longitude": z.number(),
"source": z.string().optional(),
"icon": z.string().nullable(),
"color": z.string().nullable(),
"visits_count": z.number(),
"created_at": "2024-07-29T15:51:28.071Z",
"tags": [
{
"id": z.number(),
"name": z.string(),
"icon": z.string(),
"color": z.string()
}
]
}));