🏗️ Migrate usenet pause to tRPC

This commit is contained in:
Meier Lukas
2023-06-10 17:38:57 +02:00
parent 9cefe5d3a3
commit 7f39accf4b
3 changed files with 74 additions and 46 deletions

View File

@@ -2,7 +2,7 @@ import { useMutation, useQuery } from '@tanstack/react-query';
import axios from 'axios'; import axios from 'axios';
import { Results } from 'sabnzbd-api'; import { Results } from 'sabnzbd-api';
import { useConfigContext } from '~/config/provider'; import { useConfigContext } from '~/config/provider';
import { api } from '~/utils/api'; import { RouterInputs, api } from '~/utils/api';
import { UsenetInfoRequestParams, UsenetInfoResponse } from '../../../pages/api/modules/usenet'; import { UsenetInfoRequestParams, UsenetInfoResponse } 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';
@@ -63,49 +63,24 @@ export const useGetUsenetHistory = (params: UsenetHistoryRequestParams) => {
); );
}; };
export const usePauseUsenetQueue = (params: UsenetPauseRequestParams) => export const usePauseUsenetQueueMutation = (params: UsenetPauseRequestParams) => {
useMutation( const { name: configName } = useConfigContext();
['usenetPause', ...Object.values(params)], const { mutateAsync, mutate, ...mutation } = api.usenet.pause.useMutation();
async () => const utils = api.useContext();
( return async (variables: Omit<RouterInputs['usenet']['pause'], 'configName'>) => {
await axios.post<Results>( await mutateAsync(
'/api/modules/usenet/pause', {
{}, configName: configName!,
{ ...variables,
params,
}
)
).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: true,
});
}
return { previousInfo };
}, },
onError(err, _, context) { {
if (context?.previousInfo) { onSettled() {
queryClient.setQueryData<UsenetInfoResponse>( utils.usenet.info.invalidate({ appId: params.appId });
['usenetInfo', params.appId], },
context.previousInfo }
); );
} };
}, };
onSettled() {
queryClient.invalidateQueries(['usenetInfo', params.appId]);
},
}
);
export const useResumeUsenetQueue = (params: UsenetResumeRequestParams) => export const useResumeUsenetQueue = (params: UsenetResumeRequestParams) =>
useMutation( useMutation(

View File

@@ -170,6 +170,52 @@ export const usenetRouter = createTRPCRouter({
total: history.noofslots, total: history.noofslots,
}; };
}), }),
pause: 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.pauseDownload(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).queuePause();
}),
}); });
export interface UsenetInfoResponse { export interface UsenetInfoResponse {

View File

@@ -10,7 +10,7 @@ import { useConfigContext } from '../../config/provider';
import { MIN_WIDTH_MOBILE } from '../../constants/constants'; import { MIN_WIDTH_MOBILE } from '../../constants/constants';
import { import {
useGetUsenetInfo, useGetUsenetInfo,
usePauseUsenetQueue, usePauseUsenetQueueMutation,
useResumeUsenetQueue, useResumeUsenetQueue,
} from '../../hooks/widgets/dashDot/api'; } from '../../hooks/widgets/dashDot/api';
import { humanFileSize } from '../../tools/humanFileSize'; import { humanFileSize } from '../../tools/humanFileSize';
@@ -60,7 +60,7 @@ function UseNetTile({ widget }: UseNetTileProps) {
} }
}, [downloadApps, selectedAppId]); }, [downloadApps, selectedAppId]);
const { mutate: pause } = usePauseUsenetQueue({ appId: selectedAppId! }); const pauseAsync = usePauseUsenetQueueMutation({ appId: selectedAppId! });
const { mutate: resume } = useResumeUsenetQueue({ appId: selectedAppId! }); const { mutate: resume } = useResumeUsenetQueue({ appId: selectedAppId! });
if (downloadApps.length === 0) { if (downloadApps.length === 0) {
@@ -111,7 +111,14 @@ function UseNetTile({ widget }: UseNetTileProps) {
<IconPlayerPlay size={12} style={{ marginRight: 5 }} /> {t('info.paused')} <IconPlayerPlay size={12} style={{ marginRight: 5 }} /> {t('info.paused')}
</Button> </Button>
) : ( ) : (
<Button uppercase onClick={() => pause()} radius="xl" size="xs" fullWidth mt="sm"> <Button
uppercase
onClick={async () => pauseAsync({ appId: selectedAppId })}
radius="xl"
size="xs"
fullWidth
mt="sm"
>
<IconPlayerPause size={12} style={{ marginRight: 5 }} />{' '} <IconPlayerPause size={12} style={{ marginRight: 5 }} />{' '}
{dayjs.duration(data.eta, 's').format('HH:mm')} {dayjs.duration(data.eta, 's').format('HH:mm')}
</Button> </Button>