From 9cefe5d3a388fcb7fcf91cc0336fefc281e8123b Mon Sep 17 00:00:00 2001 From: Meier Lukas Date: Sat, 10 Jun 2023 17:25:36 +0200 Subject: [PATCH] =?UTF-8?q?=F0=9F=8F=97=EF=B8=8F=20Migrate=20usenet=20hist?= =?UTF-8?q?ory=20to=20tRPC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/hooks/widgets/dashDot/api.ts | 32 +++++----- src/server/api/routers/usenet/route.ts | 81 +++++++++++++++++++++++++- 2 files changed, 94 insertions(+), 19 deletions(-) diff --git a/src/hooks/widgets/dashDot/api.ts b/src/hooks/widgets/dashDot/api.ts index 5edca276e..6c9b5380e 100644 --- a/src/hooks/widgets/dashDot/api.ts +++ b/src/hooks/widgets/dashDot/api.ts @@ -1,20 +1,17 @@ import { useMutation, useQuery } from '@tanstack/react-query'; import axios from 'axios'; import { Results } from 'sabnzbd-api'; +import { useConfigContext } from '~/config/provider'; +import { api } from '~/utils/api'; +import { UsenetInfoRequestParams, UsenetInfoResponse } from '../../../pages/api/modules/usenet'; +import type { UsenetHistoryRequestParams } from '../../../pages/api/modules/usenet/history'; +import { UsenetPauseRequestParams } from '../../../pages/api/modules/usenet/pause'; import type { UsenetQueueRequestParams, UsenetQueueResponse, } from '../../../pages/api/modules/usenet/queue'; -import type { - UsenetHistoryRequestParams, - UsenetHistoryResponse, -} from '../../../pages/api/modules/usenet/history'; -import { UsenetInfoRequestParams, UsenetInfoResponse } from '../../../pages/api/modules/usenet'; -import { UsenetPauseRequestParams } from '../../../pages/api/modules/usenet/pause'; -import { queryClient } from '../../../tools/server/configurations/tanstack/queryClient.tool'; import { UsenetResumeRequestParams } from '../../../pages/api/modules/usenet/resume'; -import { api } from '~/utils/api'; -import { useConfigContext } from '~/config/provider'; +import { queryClient } from '../../../tools/server/configurations/tanstack/queryClient.tool'; const POLLING_INTERVAL = 2000; @@ -51,21 +48,20 @@ export const useGetUsenetDownloads = (params: UsenetQueueRequestParams) => } ); -export const useGetUsenetHistory = (params: UsenetHistoryRequestParams) => - useQuery( - ['usenetHistory', ...Object.values(params)], - async () => - ( - await axios.get('/api/modules/usenet/history', { - params, - }) - ).data, +export const useGetUsenetHistory = (params: UsenetHistoryRequestParams) => { + const { name: configName } = useConfigContext(); + return api.usenet.history.useQuery( + { + configName: configName!, + ...params, + }, { refetchInterval: POLLING_INTERVAL, keepPreviousData: true, retry: 2, } ); +}; export const usePauseUsenetQueue = (params: UsenetPauseRequestParams) => useMutation( diff --git a/src/server/api/routers/usenet/route.ts b/src/server/api/routers/usenet/route.ts index 5c824a8f9..914a4dfe7 100644 --- a/src/server/api/routers/usenet/route.ts +++ b/src/server/api/routers/usenet/route.ts @@ -2,10 +2,11 @@ import dayjs from 'dayjs'; import { Client } from 'sabnzbd-api'; import { z } from 'zod'; import { TRPCError } from '@trpc/server'; -import { NzbgetStatus } from '~/server/api/routers/usenet/nzbget/types'; +import { NzbgetHistoryItem, NzbgetStatus } from '~/server/api/routers/usenet/nzbget/types'; import { getConfig } from '~/tools/config/getConfig'; import { createTRPCRouter, publicProcedure } from '../../trpc'; import { NzbgetClient } from './nzbget/nzbget-client'; +import { UsenetHistoryItem } from '~/widgets/useNet/types'; export const usenetRouter = createTRPCRouter({ info: publicProcedure @@ -91,6 +92,84 @@ export const usenetRouter = createTRPCRouter({ eta: eta.asSeconds(), }; }), + history: publicProcedure + .input( + z.object({ + configName: z.string(), + appId: z.string(), + limit: z.number(), + offset: z.number(), + }) + ) + .query(async ({ input }) => { + const config = getConfig(input.configName); + + const app = config.apps.find((x) => x.id === input.appId); + + if (!app || (app.integration?.type !== 'nzbGet' && app.integration?.type !== 'sabnzbd')) { + throw new Error(`App with ID "${input.appId}" could not be found.`); + } + + if (app.integration?.type === 'nzbGet') { + const url = new URL(app.url); + const options = { + host: url.hostname, + port: url.port || (url.protocol === 'https:' ? '443' : '80'), + login: app.integration.properties.find((x) => x.field === 'username')?.value ?? undefined, + hash: app.integration.properties.find((x) => x.field === 'password')?.value ?? undefined, + }; + + const nzbGet = NzbgetClient(options); + + const nzbgetHistory: NzbgetHistoryItem[] = await new Promise((resolve, reject) => { + nzbGet.history(false, (err: any, result: NzbgetHistoryItem[]) => { + if (!err) { + resolve(result); + } else { + reject(err); + } + }); + }); + + if (!nzbgetHistory) { + throw new Error('Error while getting NZBGet history'); + } + + const nzbgetItems: UsenetHistoryItem[] = nzbgetHistory.map((item: NzbgetHistoryItem) => ({ + id: item.NZBID.toString(), + name: item.Name, + // Convert from MB to bytes + size: item.DownloadedSizeMB * 1000000, + time: item.DownloadTimeSec, + })); + + return { + items: nzbgetItems, + total: nzbgetItems.length, + }; + } + + const { origin } = new URL(app.url); + + const apiKey = app.integration.properties.find((x) => x.field === 'apiKey')?.value; + if (!apiKey) { + throw new Error(`API Key for app "${app.name}" is missing`); + } + + const history = await new Client(origin, apiKey).history(input.offset, input.limit); + + const items: UsenetHistoryItem[] = history.slots.map((slot) => ({ + id: slot.nzo_id, + name: slot.name, + size: slot.bytes, + time: slot.download_time, + })); + + return { + items, + total: history.noofslots, + }; + }), }); export interface UsenetInfoResponse {