From 1a4ea9dd7651a042742a2131210cdb1d4168130c Mon Sep 17 00:00:00 2001 From: SeDemal Date: Wed, 11 Sep 2024 23:43:00 +0200 Subject: [PATCH 1/3] feat: Remove typed-rpc dependency and used fetch instead --- packages/integrations/package.json | 3 +- .../nzbget/nzbget-integration.ts | 52 ++++++++++++------- .../download-client/nzbget/nzbget-types.ts | 17 ++---- packages/widgets/src/downloads/component.tsx | 1 + pnpm-lock.yaml | 8 --- 5 files changed, 37 insertions(+), 44 deletions(-) diff --git a/packages/integrations/package.json b/packages/integrations/package.json index 206b71a33..9df797fc8 100644 --- a/packages/integrations/package.json +++ b/packages/integrations/package.json @@ -33,8 +33,7 @@ "@homarr/log": "workspace:^0.1.0", "@homarr/translation": "workspace:^0.1.0", "@homarr/validation": "workspace:^0.1.0", - "@jellyfin/sdk": "^0.10.0", - "typed-rpc": "^5.1.0" + "@jellyfin/sdk": "^0.10.0" }, "devDependencies": { "@homarr/eslint-config": "workspace:^0.2.0", diff --git a/packages/integrations/src/download-client/nzbget/nzbget-integration.ts b/packages/integrations/src/download-client/nzbget/nzbget-integration.ts index 824a47a9c..8ccf6d468 100644 --- a/packages/integrations/src/download-client/nzbget/nzbget-integration.ts +++ b/packages/integrations/src/download-client/nzbget/nzbget-integration.ts @@ -1,24 +1,21 @@ import dayjs from "dayjs"; -import { rpcClient } from "typed-rpc"; import type { DownloadClientJobsAndStatus } from "../../interfaces/downloads/download-client-data"; import { DownloadClientIntegration } from "../../interfaces/downloads/download-client-integration"; import type { DownloadClientItem } from "../../interfaces/downloads/download-client-items"; import type { DownloadClientStatus } from "../../interfaces/downloads/download-client-status"; -import type { NzbGetClient } from "./nzbget-types"; +import type { NzbGetGroup, NzbGetHistory, NzbGetStatus } from "./nzbget-types"; export class NzbGetIntegration extends DownloadClientIntegration { public async testConnectionAsync(): Promise { - const client = this.getClient(); - await client.version(); + await this.nzbGetApiCallAsync("version"); } public async getClientJobsAndStatusAsync(): Promise { const type = "usenet"; - const nzbGetClient = this.getClient(); - const queue = await nzbGetClient.listgroups(); - const history = await nzbGetClient.history(); - const nzbGetStatus = await nzbGetClient.status(); + const queue = (await this.nzbGetApiCallAsync("listgroups")) as NzbGetGroup[]; + const history = (await this.nzbGetApiCallAsync("history")) as NzbGetHistory[]; + const nzbGetStatus = (await this.nzbGetApiCallAsync("status")) as NzbGetStatus; const status: DownloadClientStatus = { paused: nzbGetStatus.DownloadPaused, rates: { down: nzbGetStatus.DownloadRate }, @@ -64,39 +61,54 @@ export class NzbGetIntegration extends DownloadClientIntegration { } public async pauseQueueAsync() { - await this.getClient().pausedownload(); + await this.nzbGetApiCallAsync("pausedownload"); } public async pauseItemAsync({ id }: DownloadClientItem): Promise { - await this.getClient().editqueue("GroupPause", "", [Number(id)]); + await this.nzbGetApiCallAsync("editqueue", "GroupPause", "", [Number(id)]); } public async resumeQueueAsync() { - await this.getClient().resumedownload(); + await this.nzbGetApiCallAsync("resumedownload"); } public async resumeItemAsync({ id }: DownloadClientItem): Promise { - await this.getClient().editqueue("GroupResume", "", [Number(id)]); + await this.nzbGetApiCallAsync("editqueue", "GroupResume", "", [Number(id)]); } public async deleteItemAsync({ id, progress }: DownloadClientItem, fromDisk: boolean): Promise { - const client = this.getClient(); if (fromDisk) { - const filesIds = (await client.listfiles(0, 0, Number(id))).map((value) => value.ID); - await this.getClient().editqueue("FileDelete", "", filesIds); + const filesIds = ((await this.nzbGetApiCallAsync("listfiles", 0, 0, Number(id))) as { ID: number }[]).map( + (file) => file.ID, + ); + await this.nzbGetApiCallAsync("editqueue", "FileDelete", "", filesIds); } - if (progress !== 1) { - await client.editqueue("GroupFinalDelete", "", [Number(id)]); + if (progress === 1) { + await this.nzbGetApiCallAsync("editqueue", "GroupFinalDelete", "", [Number(id)]); } else { - await client.editqueue("HistoryFinalDelete", "", [Number(id)]); + await this.nzbGetApiCallAsync("editqueue", "HistoryFinalDelete", "", [Number(id)]); } } - private getClient() { + private async nzbGetApiCallAsync(method: string, ...params: unknown[]): Promise { const url = new URL(this.integration.url); url.pathname += `${this.getSecretValue("username")}:${this.getSecretValue("password")}`; url.pathname += url.pathname.endsWith("/") ? "jsonrpc" : "/jsonrpc"; - return rpcClient(url.toString()); + const body = JSON.stringify({ method, params }); + return await fetch(url, { method: "POST", body }) + .then(async (response) => { + if (!response.ok) { + throw new Error(response.statusText); + } + return ((await response.json()) as { result: unknown }).result as Promise; + }) + .catch((error) => { + if (error instanceof Error) { + throw new Error(error.message); + } else { + throw new Error("Error communicating with SABnzbd"); + } + }); } private static getUsenetQueueState(status: string): DownloadClientItem["state"] { diff --git a/packages/integrations/src/download-client/nzbget/nzbget-types.ts b/packages/integrations/src/download-client/nzbget/nzbget-types.ts index 436db45a7..95c739527 100644 --- a/packages/integrations/src/download-client/nzbget/nzbget-types.ts +++ b/packages/integrations/src/download-client/nzbget/nzbget-types.ts @@ -1,20 +1,9 @@ -export interface NzbGetClient { - version: () => string; - status: () => NzbGetStatus; - listgroups: () => NzbGetGroup[]; - history: () => NzbGetHistory[]; - pausedownload: () => void; - resumedownload: () => void; - editqueue: (Command: string, Param: string, IDs: number[]) => void; - listfiles: (IDFrom: number, IDTo: number, NZBID: number) => { ID: number }[]; -} - -interface NzbGetStatus { +export interface NzbGetStatus { DownloadPaused: boolean; DownloadRate: number; } -interface NzbGetGroup { +export interface NzbGetGroup { Status: string; NZBID: number; MaxPriority: number; @@ -30,7 +19,7 @@ interface NzbGetGroup { FileSizeMB: number; } -interface NzbGetHistory { +export interface NzbGetHistory { ScriptStatus: string; NZBID: number; Name: string; diff --git a/packages/widgets/src/downloads/component.tsx b/packages/widgets/src/downloads/component.tsx index 5fae5bce5..afd8be9cc 100644 --- a/packages/widgets/src/downloads/component.tsx +++ b/packages/widgets/src/downloads/component.tsx @@ -831,6 +831,7 @@ const ClientsControl = ({ clients, style }: ClientsControlProps) => { px="calc(var(--space-size)*2)" fw="500" onClick={open} + styles={{ label: { height: "fit-content", paddingBottom: "calc(var(--space-size)*0.75)" } }} > {totalSpeed} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 2397b8fa1..c003c5b2b 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -986,9 +986,6 @@ importers: '@jellyfin/sdk': specifier: ^0.10.0 version: 0.10.0(axios@1.7.2) - typed-rpc: - specifier: ^5.1.0 - version: 5.1.0 devDependencies: '@homarr/eslint-config': specifier: workspace:^0.2.0 @@ -7204,9 +7201,6 @@ packages: resolution: {integrity: sha512-/OxDN6OtAk5KBpGb28T+HZc2M+ADtvRxXrKKbUwtsLgdoxgX13hyy7ek6bFRl5+aBs2yZzB0c4CnQfAtVypW/g==} engines: {node: '>= 0.4'} - typed-rpc@5.1.0: - resolution: {integrity: sha512-qPWUQrLye3Z5kQ8GuVLIURIUNPaDrKgBBts5nXVjR87j8+4sva/sw7lmaBfOw+7m/S4F9jplkv9XZl0hUDUHZg==} - typedarray-to-buffer@3.1.5: resolution: {integrity: sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==} @@ -13992,8 +13986,6 @@ snapshots: is-typed-array: 1.1.13 possible-typed-array-names: 1.0.0 - typed-rpc@5.1.0: {} - typedarray-to-buffer@3.1.5: dependencies: is-typedarray: 1.0.0 From af5432dccfc214fcf1ac5f398820c9b568b6c632 Mon Sep 17 00:00:00 2001 From: SeDemal Date: Thu, 12 Sep 2024 01:14:55 +0200 Subject: [PATCH 2/3] fix: tests --- packages/integrations/test/nzbget.spec.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/integrations/test/nzbget.spec.ts b/packages/integrations/test/nzbget.spec.ts index a23f081c7..b19b39d71 100644 --- a/packages/integrations/test/nzbget.spec.ts +++ b/packages/integrations/test/nzbget.spec.ts @@ -125,7 +125,7 @@ describe("Nzbget integration", () => { // Act const getAsync = async () => await nzbGetIntegration.getClientJobsAndStatusAsync(); - const actAsync = async () => await nzbGetIntegration.deleteItemAsync(item, false); + const actAsync = async () => await nzbGetIntegration.deleteItemAsync(item, true); // Assert await expect(actAsync()).resolves.not.toThrow(); From 4d310020b141b1742265aa45af25c37d9e101f18 Mon Sep 17 00:00:00 2001 From: SeDemal Date: Sun, 15 Sep 2024 14:29:59 +0200 Subject: [PATCH 3/3] fix: typing --- .../nzbget/nzbget-integration.ts | 21 ++++++++++--------- .../download-client/nzbget/nzbget-types.ts | 17 ++++++++++++--- 2 files changed, 25 insertions(+), 13 deletions(-) diff --git a/packages/integrations/src/download-client/nzbget/nzbget-integration.ts b/packages/integrations/src/download-client/nzbget/nzbget-integration.ts index 8ccf6d468..5e91f393b 100644 --- a/packages/integrations/src/download-client/nzbget/nzbget-integration.ts +++ b/packages/integrations/src/download-client/nzbget/nzbget-integration.ts @@ -4,7 +4,7 @@ import type { DownloadClientJobsAndStatus } from "../../interfaces/downloads/dow import { DownloadClientIntegration } from "../../interfaces/downloads/download-client-integration"; import type { DownloadClientItem } from "../../interfaces/downloads/download-client-items"; import type { DownloadClientStatus } from "../../interfaces/downloads/download-client-status"; -import type { NzbGetGroup, NzbGetHistory, NzbGetStatus } from "./nzbget-types"; +import type { NzbGetClient } from "./nzbget-types"; export class NzbGetIntegration extends DownloadClientIntegration { public async testConnectionAsync(): Promise { @@ -13,9 +13,9 @@ export class NzbGetIntegration extends DownloadClientIntegration { public async getClientJobsAndStatusAsync(): Promise { const type = "usenet"; - const queue = (await this.nzbGetApiCallAsync("listgroups")) as NzbGetGroup[]; - const history = (await this.nzbGetApiCallAsync("history")) as NzbGetHistory[]; - const nzbGetStatus = (await this.nzbGetApiCallAsync("status")) as NzbGetStatus; + const queue = await this.nzbGetApiCallAsync("listgroups"); + const history = await this.nzbGetApiCallAsync("history"); + const nzbGetStatus = await this.nzbGetApiCallAsync("status"); const status: DownloadClientStatus = { paused: nzbGetStatus.DownloadPaused, rates: { down: nzbGetStatus.DownloadRate }, @@ -78,9 +78,7 @@ export class NzbGetIntegration extends DownloadClientIntegration { public async deleteItemAsync({ id, progress }: DownloadClientItem, fromDisk: boolean): Promise { if (fromDisk) { - const filesIds = ((await this.nzbGetApiCallAsync("listfiles", 0, 0, Number(id))) as { ID: number }[]).map( - (file) => file.ID, - ); + const filesIds = (await this.nzbGetApiCallAsync("listfiles", 0, 0, Number(id))).map((file) => file.ID); await this.nzbGetApiCallAsync("editqueue", "FileDelete", "", filesIds); } if (progress === 1) { @@ -90,7 +88,10 @@ export class NzbGetIntegration extends DownloadClientIntegration { } } - private async nzbGetApiCallAsync(method: string, ...params: unknown[]): Promise { + private async nzbGetApiCallAsync( + method: CallType, + ...params: Parameters + ): Promise> { const url = new URL(this.integration.url); url.pathname += `${this.getSecretValue("username")}:${this.getSecretValue("password")}`; url.pathname += url.pathname.endsWith("/") ? "jsonrpc" : "/jsonrpc"; @@ -100,13 +101,13 @@ export class NzbGetIntegration extends DownloadClientIntegration { if (!response.ok) { throw new Error(response.statusText); } - return ((await response.json()) as { result: unknown }).result as Promise; + return ((await response.json()) as { result: ReturnType }).result; }) .catch((error) => { if (error instanceof Error) { throw new Error(error.message); } else { - throw new Error("Error communicating with SABnzbd"); + throw new Error("Error communicating with NzbGet"); } }); } diff --git a/packages/integrations/src/download-client/nzbget/nzbget-types.ts b/packages/integrations/src/download-client/nzbget/nzbget-types.ts index 95c739527..436db45a7 100644 --- a/packages/integrations/src/download-client/nzbget/nzbget-types.ts +++ b/packages/integrations/src/download-client/nzbget/nzbget-types.ts @@ -1,9 +1,20 @@ -export interface NzbGetStatus { +export interface NzbGetClient { + version: () => string; + status: () => NzbGetStatus; + listgroups: () => NzbGetGroup[]; + history: () => NzbGetHistory[]; + pausedownload: () => void; + resumedownload: () => void; + editqueue: (Command: string, Param: string, IDs: number[]) => void; + listfiles: (IDFrom: number, IDTo: number, NZBID: number) => { ID: number }[]; +} + +interface NzbGetStatus { DownloadPaused: boolean; DownloadRate: number; } -export interface NzbGetGroup { +interface NzbGetGroup { Status: string; NZBID: number; MaxPriority: number; @@ -19,7 +30,7 @@ export interface NzbGetGroup { FileSizeMB: number; } -export interface NzbGetHistory { +interface NzbGetHistory { ScriptStatus: string; NZBID: number; Name: string;