🏗️ Migrate usenet resume to tRPC

This commit is contained in:
Meier Lukas
2023-06-10 17:43:10 +02:00
parent 7f39accf4b
commit 1632bdec39
3 changed files with 77 additions and 50 deletions

View File

@@ -1,9 +1,8 @@
import { useMutation, useQuery } from '@tanstack/react-query'; import { useQuery } from '@tanstack/react-query';
import axios from 'axios'; import axios from 'axios';
import { Results } from 'sabnzbd-api';
import { useConfigContext } from '~/config/provider'; import { useConfigContext } from '~/config/provider';
import { RouterInputs, api } from '~/utils/api'; import { RouterInputs, api } from '~/utils/api';
import { UsenetInfoRequestParams, UsenetInfoResponse } from '../../../pages/api/modules/usenet'; import { UsenetInfoRequestParams } from '../../../pages/api/modules/usenet';
import type { UsenetHistoryRequestParams } from '../../../pages/api/modules/usenet/history'; import type { UsenetHistoryRequestParams } from '../../../pages/api/modules/usenet/history';
import { UsenetPauseRequestParams } from '../../../pages/api/modules/usenet/pause'; import { UsenetPauseRequestParams } from '../../../pages/api/modules/usenet/pause';
import type { import type {
@@ -11,7 +10,6 @@ import type {
UsenetQueueResponse, UsenetQueueResponse,
} from '../../../pages/api/modules/usenet/queue'; } from '../../../pages/api/modules/usenet/queue';
import { UsenetResumeRequestParams } from '../../../pages/api/modules/usenet/resume'; import { UsenetResumeRequestParams } from '../../../pages/api/modules/usenet/resume';
import { queryClient } from '../../../tools/server/configurations/tanstack/queryClient.tool';
const POLLING_INTERVAL = 2000; const POLLING_INTERVAL = 2000;
@@ -65,7 +63,7 @@ export const useGetUsenetHistory = (params: UsenetHistoryRequestParams) => {
export const usePauseUsenetQueueMutation = (params: UsenetPauseRequestParams) => { export const usePauseUsenetQueueMutation = (params: UsenetPauseRequestParams) => {
const { name: configName } = useConfigContext(); const { name: configName } = useConfigContext();
const { mutateAsync, mutate, ...mutation } = api.usenet.pause.useMutation(); const { mutateAsync } = api.usenet.pause.useMutation();
const utils = api.useContext(); const utils = api.useContext();
return async (variables: Omit<RouterInputs['usenet']['pause'], 'configName'>) => { return async (variables: Omit<RouterInputs['usenet']['pause'], 'configName'>) => {
await mutateAsync( await mutateAsync(
@@ -82,46 +80,21 @@ export const usePauseUsenetQueueMutation = (params: UsenetPauseRequestParams) =>
}; };
}; };
export const useResumeUsenetQueue = (params: UsenetResumeRequestParams) => export const useResumeUsenetQueueMutation = (params: UsenetResumeRequestParams) => {
useMutation( const { name: configName } = useConfigContext();
['usenetResume', ...Object.values(params)], const { mutateAsync } = api.usenet.resume.useMutation();
async () => const utils = api.useContext();
( return async (variables: Omit<RouterInputs['usenet']['resume'], 'configName'>) => {
await axios.post<Results>( await mutateAsync(
'/api/modules/usenet/resume',
{},
{ {
params, configName: configName!,
} ...variables,
) },
).data,
{ {
async onMutate() {
await queryClient.cancelQueries(['usenetInfo', params.appId]);
const previousInfo = queryClient.getQueryData<UsenetInfoResponse>([
'usenetInfo',
params.appId,
]);
if (previousInfo) {
queryClient.setQueryData<UsenetInfoResponse>(['usenetInfo', params.appId], {
...previousInfo,
paused: false,
});
}
return { previousInfo };
},
onError(err, _, context) {
if (context?.previousInfo) {
queryClient.setQueryData<UsenetInfoResponse>(
['usenetInfo', params.appId],
context.previousInfo
);
}
},
onSettled() { onSettled() {
queryClient.invalidateQueries(['usenetInfo', params.appId]); utils.usenet.info.invalidate({ appId: params.appId });
}, },
} }
); );
};
};

View File

@@ -216,6 +216,53 @@ export const usenetRouter = createTRPCRouter({
return new Client(origin, apiKey).queuePause(); return new Client(origin, apiKey).queuePause();
}), }),
resume: publicProcedure
.input(
z.object({
configName: z.string(),
appId: z.string(),
})
)
.mutation(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);
return new Promise((resolve, reject) => {
nzbGet.resumeDownload(false, (err: any, result: any) => {
if (!err) {
resolve(result);
} else {
reject(err);
}
});
});
}
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 { origin } = new URL(app.url);
return new Client(origin, apiKey).queueResume();
}),
}); });
export interface UsenetInfoResponse { export interface UsenetInfoResponse {

View File

@@ -11,7 +11,7 @@ import { MIN_WIDTH_MOBILE } from '../../constants/constants';
import { import {
useGetUsenetInfo, useGetUsenetInfo,
usePauseUsenetQueueMutation, usePauseUsenetQueueMutation,
useResumeUsenetQueue, useResumeUsenetQueueMutation,
} from '../../hooks/widgets/dashDot/api'; } from '../../hooks/widgets/dashDot/api';
import { humanFileSize } from '../../tools/humanFileSize'; import { humanFileSize } from '../../tools/humanFileSize';
import { AppIntegrationType } from '../../types/app'; import { AppIntegrationType } from '../../types/app';
@@ -61,7 +61,7 @@ function UseNetTile({ widget }: UseNetTileProps) {
}, [downloadApps, selectedAppId]); }, [downloadApps, selectedAppId]);
const pauseAsync = usePauseUsenetQueueMutation({ appId: selectedAppId! }); const pauseAsync = usePauseUsenetQueueMutation({ appId: selectedAppId! });
const { mutate: resume } = useResumeUsenetQueue({ appId: selectedAppId! }); const resumeAsync = useResumeUsenetQueueMutation({ appId: selectedAppId! });
if (downloadApps.length === 0) { if (downloadApps.length === 0) {
return ( return (
@@ -107,7 +107,14 @@ function UseNetTile({ widget }: UseNetTileProps) {
<Tabs.Panel value="queue"> <Tabs.Panel value="queue">
<UsenetQueueList appId={selectedAppId} /> <UsenetQueueList appId={selectedAppId} />
{!data ? null : data.paused ? ( {!data ? null : data.paused ? (
<Button uppercase onClick={() => resume()} radius="xl" size="xs" fullWidth mt="sm"> <Button
uppercase
onClick={async () => resumeAsync({ appId: selectedAppId })}
radius="xl"
size="xs"
fullWidth
mt="sm"
>
<IconPlayerPlay size={12} style={{ marginRight: 5 }} /> {t('info.paused')} <IconPlayerPlay size={12} style={{ marginRight: 5 }} /> {t('info.paused')}
</Button> </Button>
) : ( ) : (