mirror of
https://github.com/ajnart/homarr.git
synced 2025-11-10 15:35:55 +01:00
🏗️ Migrate overseerr by id to tRPC
This commit is contained in:
@@ -10,6 +10,8 @@ import { useColorTheme } from '../../tools/color';
|
|||||||
import { MovieResult } from './Movie.d';
|
import { MovieResult } from './Movie.d';
|
||||||
import { MediaType, Result } from './SearchResult.d';
|
import { MediaType, Result } from './SearchResult.d';
|
||||||
import { TvShowResult, TvShowResultSeason } from './TvShow.d';
|
import { TvShowResult, TvShowResultSeason } from './TvShow.d';
|
||||||
|
import { api } from '~/utils/api';
|
||||||
|
import { useConfigContext } from '~/config/provider';
|
||||||
|
|
||||||
interface RequestModalProps {
|
interface RequestModalProps {
|
||||||
base: Result;
|
base: Result;
|
||||||
@@ -27,20 +29,22 @@ const useStyles = createStyles((theme) => ({
|
|||||||
}));
|
}));
|
||||||
|
|
||||||
export function RequestModal({ base, opened, setOpened }: RequestModalProps) {
|
export function RequestModal({ base, opened, setOpened }: RequestModalProps) {
|
||||||
const [result, setResult] = useState<MovieResult | TvShowResult>();
|
const { name: configName } = useConfigContext();
|
||||||
const { secondaryColor } = useColorTheme();
|
const { data: result } = api.overseerr.byId.useQuery(
|
||||||
|
{
|
||||||
|
id: base.id,
|
||||||
|
type: base.mediaType,
|
||||||
|
configName: configName!,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
enabled: opened,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
function getResults(base: Result) {
|
|
||||||
axios.get(`/api/modules/overseerr/${base.id}?type=${base.mediaType}`).then((res) => {
|
|
||||||
setResult(res.data);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
if (opened && !result) {
|
|
||||||
getResults(base);
|
|
||||||
}
|
|
||||||
if (!result || !opened) {
|
if (!result || !opened) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
return base.mediaType === 'movie' ? (
|
return base.mediaType === 'movie' ? (
|
||||||
<MovieRequestModal result={result as MovieResult} opened={opened} setOpened={setOpened} />
|
<MovieRequestModal result={result as MovieResult} opened={opened} setOpened={setOpened} />
|
||||||
) : (
|
) : (
|
||||||
@@ -93,7 +97,7 @@ export function MovieRequestModal({
|
|||||||
<Button
|
<Button
|
||||||
variant="outline"
|
variant="outline"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
askForMedia(MediaType.Movie, result.id, result.title, []);
|
askForMedia('movie', result.id, result.title, []);
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{t('popup.item.buttons.request')}
|
{t('popup.item.buttons.request')}
|
||||||
@@ -197,7 +201,7 @@ export function TvRequestModal({
|
|||||||
disabled={selection.length === 0}
|
disabled={selection.length === 0}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
askForMedia(
|
askForMedia(
|
||||||
MediaType.Tv,
|
'tv',
|
||||||
result.id,
|
result.id,
|
||||||
result.name,
|
result.name,
|
||||||
selection.map((s) => s.seasonNumber)
|
selection.map((s) => s.seasonNumber)
|
||||||
|
|||||||
5
src/modules/overseerr/SearchResult.d.ts
vendored
5
src/modules/overseerr/SearchResult.d.ts
vendored
@@ -56,10 +56,7 @@ export interface MediaInfo {
|
|||||||
mediaUrl?: string;
|
mediaUrl?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export enum MediaType {
|
export type MediaType = 'movie' | 'tv';
|
||||||
Movie = 'movie',
|
|
||||||
Tv = 'tv',
|
|
||||||
}
|
|
||||||
|
|
||||||
export enum OriginalLanguage {
|
export enum OriginalLanguage {
|
||||||
En = 'en',
|
En = 'en',
|
||||||
|
|||||||
@@ -1,8 +1,11 @@
|
|||||||
import { TRPCError } from '@trpc/server';
|
import { TRPCError } from '@trpc/server';
|
||||||
import axios from 'axios';
|
import axios from 'axios';
|
||||||
import { z } from 'zod';
|
import { z } from 'zod';
|
||||||
|
import Consola from 'consola';
|
||||||
import { getConfig } from '~/tools/config/getConfig';
|
import { getConfig } from '~/tools/config/getConfig';
|
||||||
import { createTRPCRouter, publicProcedure } from '../trpc';
|
import { createTRPCRouter, publicProcedure } from '../trpc';
|
||||||
|
import { MovieResult } from '~/modules/overseerr/Movie';
|
||||||
|
import { TvShowResult } from '~/modules/overseerr/TvShow';
|
||||||
|
|
||||||
export const overseerrRouter = createTRPCRouter({
|
export const overseerrRouter = createTRPCRouter({
|
||||||
all: publicProcedure
|
all: publicProcedure
|
||||||
@@ -41,4 +44,64 @@ export const overseerrRouter = createTRPCRouter({
|
|||||||
.then((res) => res.data);
|
.then((res) => res.data);
|
||||||
return data;
|
return data;
|
||||||
}),
|
}),
|
||||||
|
byId: publicProcedure
|
||||||
|
.input(
|
||||||
|
z.object({
|
||||||
|
configName: z.string(),
|
||||||
|
id: z.number(),
|
||||||
|
type: z.union([z.literal('movie'), z.literal('tv')]),
|
||||||
|
})
|
||||||
|
)
|
||||||
|
.query(async ({ input }) => {
|
||||||
|
const config = getConfig(input.configName);
|
||||||
|
const app = config.apps.find(
|
||||||
|
(app) => app.integration?.type === 'overseerr' || app.integration?.type === 'jellyseerr'
|
||||||
|
);
|
||||||
|
const apiKey = app?.integration?.properties.find((x) => x.field === 'apiKey')?.value;
|
||||||
|
|
||||||
|
if (!apiKey) {
|
||||||
|
throw new TRPCError({
|
||||||
|
code: 'BAD_REQUEST',
|
||||||
|
message: 'No app found',
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const appUrl = new URL(app.url);
|
||||||
|
|
||||||
|
if (input.type === 'movie') {
|
||||||
|
const movie = await axios
|
||||||
|
.get(`${appUrl.origin}/api/v1/movie/${input.id}`, {
|
||||||
|
headers: {
|
||||||
|
// Set X-Api-Key to the value of the API key
|
||||||
|
'X-Api-Key': apiKey,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
.then((res) => res.data as MovieResult)
|
||||||
|
.catch((err) => {
|
||||||
|
Consola.error(err);
|
||||||
|
throw new TRPCError({
|
||||||
|
code: 'INTERNAL_SERVER_ERROR',
|
||||||
|
message: 'Something went wrong',
|
||||||
|
});
|
||||||
|
});
|
||||||
|
return movie;
|
||||||
|
}
|
||||||
|
|
||||||
|
const tv = await axios
|
||||||
|
.get(`${appUrl.origin}/api/v1/tv/${input.id}`, {
|
||||||
|
headers: {
|
||||||
|
// Set X-Api-Key to the value of the API key
|
||||||
|
'X-Api-Key': apiKey,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
.then((res) => res.data as TvShowResult)
|
||||||
|
.catch((err) => {
|
||||||
|
Consola.error(err);
|
||||||
|
throw new TRPCError({
|
||||||
|
code: 'INTERNAL_SERVER_ERROR',
|
||||||
|
message: 'Something went wrong',
|
||||||
|
});
|
||||||
|
});
|
||||||
|
return tv;
|
||||||
|
}),
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user