feat: add Uptime Kuma, Audiobookshelf, Paperless-ngx, and Navidrome integrations (#5910)

This commit is contained in:
Thomas authored and GitHub committed 2026-06-10 18:27:24 +02:00
1 parent a4db9cf0dc
commit d77c6f8d4e
46 files changed
+2994 -16

No files matched your search

@@ -0,0 +1,29 @@
import { audiobookshelfRequestHandler } from "@homarr/request-handler/audiobookshelf";
import { navidromeRequestHandler } from "@homarr/request-handler/navidrome";
import { createOneIntegrationMiddleware } from "../../middlewares/integration";
import { createTRPCRouter, publicProcedure } from "../../trpc";
export const audioStatsRouter = createTRPCRouter({
getStats: publicProcedure
.concat(createOneIntegrationMiddleware("query", "navidrome", "audiobookshelf"))
.query(async ({ ctx }) => {
const { kind } = ctx.integration;
const fetchByKind = {
navidrome: async () => {
const handler = navidromeRequestHandler.handler({ ...ctx.integration, kind: "navidrome" as const }, {});
return (await handler.getCachedOrUpdatedDataAsync({ forceUpdate: false })).data;
},
audiobookshelf: async () => {
const handler = audiobookshelfRequestHandler.handler(
{ ...ctx.integration, kind: "audiobookshelf" as const },
{},
);
return (await handler.getCachedOrUpdatedDataAsync({ forceUpdate: false })).data;
},
} as const;
return { kind, data: await fetchByKind[kind]() };
}),
});
+3
View File
@@ -7,6 +7,7 @@ export const widgetRouter = createTRPCRouter({
anchorNotes: lazy(() => import("./anchor-notes").then((mod) => mod.anchorNotesRouter)),
coolify: lazy(() => import("./coolify").then((mod) => mod.coolifyRouter)),
immich: lazy(() => import("./immich").then((mod) => mod.immichRouter)),
paperlessNgx: lazy(() => import("./paperless-ngx").then((mod) => mod.paperlessNgxRouter)),
notebook: lazy(() => import("./notebook").then((mod) => mod.notebookRouter)),
weather: lazy(() => import("./weather").then((mod) => mod.weatherRouter)),
app: lazy(() => import("./app").then((mod) => mod.appRouter)),
@@ -31,6 +32,8 @@ export const widgetRouter = createTRPCRouter({
timetable: lazy(() => import("./timetable").then((mod) => mod.timetableRouter)),
tracearr: lazy(() => import("./tracearr").then((mod) => mod.tracearrRouter)),
speedtestTracker: lazy(() => import("./speedtest-tracker").then((mod) => mod.speedtestTrackerRouter)),
uptimeKuma: lazy(() => import("./uptime-kuma").then((mod) => mod.uptimeKumaRouter)),
audioStats: lazy(() => import("./audio-stats").then((mod) => mod.audioStatsRouter)),
umami: lazy(() => import("./umami").then((mod) => mod.umamiRouter)),
ups: lazy(() => import("./ups").then((mod) => mod.upsRouter)),
});
@@ -0,0 +1,12 @@
import { paperlessNgxStatsRequestHandler } from "@homarr/request-handler/paperless-ngx";
import { createOneIntegrationMiddleware } from "../../middlewares/integration";
import { createTRPCRouter, publicProcedure } from "../../trpc";
export const paperlessNgxRouter = createTRPCRouter({
getStats: publicProcedure.concat(createOneIntegrationMiddleware("query", "paperlessNgx")).query(async ({ ctx }) => {
const innerHandler = paperlessNgxStatsRequestHandler.handler(ctx.integration, {});
const data = await innerHandler.getCachedOrUpdatedDataAsync({ forceUpdate: false });
return data.data;
}),
});
@@ -0,0 +1,55 @@
import { observable } from "@trpc/server/observable";
import type { UptimeKumaDashboardData } from "@homarr/integrations/types";
import { uptimeKumaRequestHandler } from "@homarr/request-handler/uptime-kuma";
import { createManyIntegrationMiddleware } from "../../middlewares/integration";
import { createTRPCRouter, publicProcedure } from "../../trpc";
export const uptimeKumaRouter = createTRPCRouter({
getDashboard: publicProcedure
.concat(createManyIntegrationMiddleware("query", "uptimeKuma"))
.query(async ({ ctx }) => {
const results = await Promise.all(
ctx.integrations.map(async (integration) => {
const innerHandler = uptimeKumaRequestHandler.handler(integration, {});
const { data, timestamp } = await innerHandler.getCachedOrUpdatedDataAsync({ forceUpdate: false });
return {
integrationId: integration.id,
integrationName: integration.name,
integrationUrl: integration.url,
dashboard: data,
updatedAt: timestamp,
};
}),
);
return results;
}),
subscribeToDashboard: publicProcedure
.concat(createManyIntegrationMiddleware("query", "uptimeKuma"))
.subscription(({ ctx }) => {
return observable<{
integrationId: string;
dashboard: UptimeKumaDashboardData;
timestamp: Date;
}>((emit) => {
const unsubscribes = ctx.integrations.map((integration) => {
const innerHandler = uptimeKumaRequestHandler.handler(integration, {});
return innerHandler.subscribe((dashboard) => {
emit.next({
integrationId: integration.id,
dashboard,
timestamp: new Date(),
});
});
});
return () => {
unsubscribes.forEach((unsubscribe) => unsubscribe());
};
});
}),
});