From 98a9b46e0fe501e3ff23017830d8005a341d21fc Mon Sep 17 00:00:00 2001 From: Manuel <30572287+manuel-rw@users.noreply.github.com> Date: Mon, 10 Jun 2024 22:27:13 +0200 Subject: [PATCH] feat: #655 implement jellyfin media server --- .vscode/settings.json | 9 ++++++++- packages/api/src/router/widgets/index.ts | 2 ++ packages/api/src/router/widgets/media-server.ts | 15 +++++++++++++++ packages/definitions/src/widget.ts | 1 + packages/widgets/src/index.tsx | 2 ++ packages/widgets/src/media-server/component.tsx | 5 +++++ packages/widgets/src/media-server/index.ts | 11 +++++++++++ packages/widgets/src/media-server/serverData.ts | 12 ++++++++++++ 8 files changed, 56 insertions(+), 1 deletion(-) create mode 100644 packages/api/src/router/widgets/media-server.ts create mode 100644 packages/widgets/src/media-server/component.tsx create mode 100644 packages/widgets/src/media-server/index.ts create mode 100644 packages/widgets/src/media-server/serverData.ts diff --git a/.vscode/settings.json b/.vscode/settings.json index 94ed7a3fc9..452db1b8f4 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -8,7 +8,14 @@ "typescript.tsdk": "node_modules\\typescript\\lib", "js/ts.implicitProjectConfig.experimentalDecorators": true, "prettier.configPath": "./tooling/prettier/index.mjs", - "cSpell.words": ["cqmin", "homarr", "superjson", "trpc", "Umami"], + "cSpell.words": [ + "cqmin", + "homarr", + "jellyfin", + "superjson", + "trpc", + "Umami" + ], "i18n-ally.dirStructure": "auto", "i18n-ally.enabledFrameworks": ["next-international"], "i18n-ally.localesPaths": ["./packages/translation/src/lang/"], diff --git a/packages/api/src/router/widgets/index.ts b/packages/api/src/router/widgets/index.ts index 7ece7bd623..8e1836bbe3 100644 --- a/packages/api/src/router/widgets/index.ts +++ b/packages/api/src/router/widgets/index.ts @@ -1,6 +1,7 @@ import { createTRPCRouter } from "../../trpc"; import { appRouter } from "./app"; import { dnsHoleRouter } from "./dns-hole"; +import { mediaServerRouter } from "./media-server"; import { notebookRouter } from "./notebook"; import { smartHomeRouter } from "./smart-home"; import { weatherRouter } from "./weather"; @@ -11,4 +12,5 @@ export const widgetRouter = createTRPCRouter({ app: appRouter, dnsHole: dnsHoleRouter, smartHome: smartHomeRouter, + mediaServer: mediaServerRouter }); diff --git a/packages/api/src/router/widgets/media-server.ts b/packages/api/src/router/widgets/media-server.ts new file mode 100644 index 0000000000..7a0b9bc719 --- /dev/null +++ b/packages/api/src/router/widgets/media-server.ts @@ -0,0 +1,15 @@ +import { createCacheChannel } from "@homarr/redis"; +import { z } from "@homarr/validation"; + +import { createManyIntegrationMiddleware } from "../../middlewares/integration"; +import { createTRPCRouter, publicProcedure } from "../../trpc"; + +export const mediaServerRouter = createTRPCRouter({ + getCurrentStreams: publicProcedure + .unstable_concat(createManyIntegrationMiddleware("jellyfin", "plex")) + .query(async ({ ctx, input }) => { + const cache = createCacheChannel("media-server"); + await cache.consumeAsync(async () => {}); + return {}; + }), +}); diff --git a/packages/definitions/src/widget.ts b/packages/definitions/src/widget.ts index d36b936876..cc59d6eda9 100644 --- a/packages/definitions/src/widget.ts +++ b/packages/definitions/src/widget.ts @@ -8,5 +8,6 @@ export const widgetKinds = [ "dnsHoleSummary", "smartHome-entityState", "smartHome-executeAutomation", + "mediaServer" ] as const; export type WidgetKind = (typeof widgetKinds)[number]; diff --git a/packages/widgets/src/index.tsx b/packages/widgets/src/index.tsx index 3049fae66f..3bd48a848c 100644 --- a/packages/widgets/src/index.tsx +++ b/packages/widgets/src/index.tsx @@ -14,6 +14,7 @@ import type { WidgetImportRecord } from "./import"; import * as notebook from "./notebook"; import * as smartHomeEntityState from "./smart-home/entity-state"; import * as smartHomeExecuteAutomation from "./smart-home/execute-automation"; +import * as mediaServer from "./media-server"; import * as video from "./video"; import * as weather from "./weather"; @@ -33,6 +34,7 @@ export const widgetImports = { dnsHoleSummary, "smartHome-entityState": smartHomeEntityState, "smartHome-executeAutomation": smartHomeExecuteAutomation, + mediaServer } satisfies WidgetImportRecord; export type WidgetImports = typeof widgetImports; diff --git a/packages/widgets/src/media-server/component.tsx b/packages/widgets/src/media-server/component.tsx new file mode 100644 index 0000000000..05386fdc9a --- /dev/null +++ b/packages/widgets/src/media-server/component.tsx @@ -0,0 +1,5 @@ +import { WidgetComponentProps } from "../definition"; + +export default function MediaServerWidget({ options }: WidgetComponentProps<"mediaServer">) { + return TEST!! +} \ No newline at end of file diff --git a/packages/widgets/src/media-server/index.ts b/packages/widgets/src/media-server/index.ts new file mode 100644 index 0000000000..4ed5260005 --- /dev/null +++ b/packages/widgets/src/media-server/index.ts @@ -0,0 +1,11 @@ +import { IconVideo } from "@tabler/icons-react"; + +import { createWidgetDefinition } from "../definition"; + +export const { componentLoader, definition } = createWidgetDefinition("mediaServer", { + icon: IconVideo, + options: {}, + supportedIntegrations: ["jellyfin", "plex"], +}) + .withServerData(() => import("./serverData")) + .withDynamicImport(() => import("./component")); diff --git a/packages/widgets/src/media-server/serverData.ts b/packages/widgets/src/media-server/serverData.ts new file mode 100644 index 0000000000..150e405b21 --- /dev/null +++ b/packages/widgets/src/media-server/serverData.ts @@ -0,0 +1,12 @@ +"use server"; + +import { api } from "@homarr/api/server"; +import type { WidgetProps } from "../definition"; + +export default async function getServerDataAsync({ integrationIds }: WidgetProps<"mediaServer">) { + const currentStreams = await api.widget.mediaServer.getCurrentStreams({ + integrationIds + }); + + return currentStreams; +} \ No newline at end of file