refactor and improve legacy redirect

This commit is contained in:
adrifcastr 2023-06-21 18:16:41 +02:00
parent f5f69ca7d4
commit 394271857f
4 changed files with 145 additions and 81 deletions

View File

@ -8,6 +8,7 @@ import {
getExternalIds, getExternalIds,
getMediaDetails, getMediaDetails,
getMediaPoster, getMediaPoster,
getMovieFromExternalId,
mediaTypeToTMDB, mediaTypeToTMDB,
} from "./tmdb"; } from "./tmdb";
import { import {
@ -206,11 +207,23 @@ export async function convertLegacyUrl(
if (url.startsWith("/media/JW")) { if (url.startsWith("/media/JW")) {
const urlParts = url.split("/").slice(2); const urlParts = url.split("/").slice(2);
const [, type, id] = urlParts[0].split("-", 3); const [, type, id] = urlParts[0].split("-", 3);
const meta = await getLegacyMetaFromId(TMDBMediaToMediaType(type), id);
const mediaType = TMDBMediaToMediaType(type);
const meta = await getLegacyMetaFromId(mediaType, id);
if (!meta) return undefined; if (!meta) return undefined;
const tmdbId = meta.tmdbId; const { tmdbId, imdbId } = meta;
if (!tmdbId) return undefined; if (!tmdbId && !imdbId) return undefined;
return `/media/tmdb-${type}-${tmdbId}`;
// movies always have an imdb id on tmdb
if (imdbId && mediaType === MWMediaType.MOVIE) {
const movieId = await getMovieFromExternalId(imdbId);
if (movieId) return `/media/tmdb-movie-${movieId}`;
}
if (tmdbId) {
return `/media/tmdb-${type}-${tmdbId}`;
}
} }
return undefined; return undefined;
} }

View File

@ -2,6 +2,7 @@ import { conf } from "@/setup/config";
import { MWMediaMeta, MWMediaType, MWSeasonMeta } from "./types/mw"; import { MWMediaMeta, MWMediaType, MWSeasonMeta } from "./types/mw";
import { import {
ExternalIdMovieSearchResult,
TMDBContentTypes, TMDBContentTypes,
TMDBEpisodeShort, TMDBEpisodeShort,
TMDBExternalIds, TMDBExternalIds,
@ -195,6 +196,19 @@ export async function getExternalIds(
return data; return data;
} }
export async function getMovieFromExternalId(
imdbId: string
): Promise<string | undefined> {
const data = await get<ExternalIdMovieSearchResult>(`/find/${imdbId}`, {
external_source: "imdb_id",
});
const movie = data.movie_results[0];
if (!movie) return undefined;
return movie.id.toString();
}
export function formatTMDBSearchResult( export function formatTMDBSearchResult(
result: TMDBShowResult | TMDBMovieResult, result: TMDBShowResult | TMDBMovieResult,
mediatype: TMDBContentTypes mediatype: TMDBContentTypes

View File

@ -282,3 +282,27 @@ export interface TMDBMovieExternalIds {
} }
export type TMDBExternalIds = TMDBShowExternalIds | TMDBMovieExternalIds; export type TMDBExternalIds = TMDBShowExternalIds | TMDBMovieExternalIds;
export interface ExternalIdMovieSearchResult {
movie_results: {
adult: boolean;
backdrop_path: string;
id: number;
title: string;
original_language: string;
original_title: string;
overview: string;
poster_path: string;
media_type: string;
genre_ids: number[];
popularity: number;
release_date: string;
video: boolean;
vote_average: number;
vote_count: number;
}[];
person_results: any[];
tv_results: any[];
tv_episode_results: any[];
tv_season_results: any[];
}

View File

@ -1,11 +1,5 @@
import { lazy } from "react"; import { lazy, useEffect, useState } from "react";
import { import { Redirect, Route, Switch, useLocation } from "react-router-dom";
Redirect,
Route,
Switch,
useHistory,
useLocation,
} from "react-router-dom";
import { convertLegacyUrl } from "@/backend/metadata/getmeta"; import { convertLegacyUrl } from "@/backend/metadata/getmeta";
import { MWMediaType } from "@/backend/metadata/types/mw"; import { MWMediaType } from "@/backend/metadata/types/mw";
@ -19,86 +13,105 @@ import { NotFoundPage } from "@/views/notfound/NotFoundView";
import { V2MigrationView } from "@/views/other/v2Migration"; import { V2MigrationView } from "@/views/other/v2Migration";
import { SearchView } from "@/views/search/SearchView"; import { SearchView } from "@/views/search/SearchView";
function App() { // eslint-disable-next-line react/function-component-definition, react/prop-types
const LegacyUrlView: React.FC = ({ children }) => {
const location = useLocation(); const location = useLocation();
const history = useHistory(); const [redirectUrl, setRedirectUrl] = useState<string | null>(null);
// Call the conversion function and redirect if necessary useEffect(() => {
convertLegacyUrl(location.pathname).then((convertedUrl) => { // Call the conversion function and set the redirect URL if necessary
if (convertedUrl) { convertLegacyUrl(location.pathname).then((convertedUrl) => {
history.replace(convertedUrl); if (convertedUrl) {
} setRedirectUrl(convertedUrl);
}); }
});
}, [location.pathname]);
if (redirectUrl) {
return <Redirect to={redirectUrl} />;
}
// eslint-disable-next-line react/jsx-no-useless-fragment
return <>{children}</>;
};
function App() {
return ( return (
<SettingsProvider> <SettingsProvider>
<WatchedContextProvider> <WatchedContextProvider>
<BookmarkContextProvider> <BookmarkContextProvider>
<BannerContextProvider> <BannerContextProvider>
<Layout> <Layout>
<Switch> <LegacyUrlView>
{/* functional routes */} <Switch>
<Route exact path="/v2-migration" component={V2MigrationView} /> {/* functional routes */}
<Route exact path="/"> <Route
<Redirect to={`/search/${MWMediaType.MOVIE}`} /> exact
</Route> path="/v2-migration"
component={V2MigrationView}
/>
<Route exact path="/">
<Redirect to={`/search/${MWMediaType.MOVIE}`} />
</Route>
{/* pages */} {/* pages */}
<Route exact path="/media/:media" component={MediaView} /> <Route exact path="/media/:media" component={MediaView} />
<Route <Route
exact exact
path="/media/:media/:season/:episode" path="/media/:media/:season/:episode"
component={MediaView} component={MediaView}
/> />
<Route <Route
exact exact
path="/search/:type/:query?" path="/search/:type/:query?"
component={SearchView} component={SearchView}
/> />
{/* other */} {/* other */}
<Route <Route
exact exact
path="/dev" path="/dev"
component={lazy( component={lazy(
() => import("@/views/developer/DeveloperView") () => import("@/views/developer/DeveloperView")
)} )}
/> />
<Route <Route
exact exact
path="/dev/video" path="/dev/video"
component={lazy( component={lazy(
() => import("@/views/developer/VideoTesterView") () => import("@/views/developer/VideoTesterView")
)} )}
/> />
{/* developer routes that can abuse workers are disabled in production */} {/* developer routes that can abuse workers are disabled in production */}
{process.env.NODE_ENV === "development" ? ( {process.env.NODE_ENV === "development" ? (
<> <>
<Route <Route
exact exact
path="/dev/test" path="/dev/test"
component={lazy( component={lazy(
() => import("@/views/developer/TestView") () => import("@/views/developer/TestView")
)} )}
/> />
<Route <Route
exact exact
path="/dev/providers" path="/dev/providers"
component={lazy( component={lazy(
() => import("@/views/developer/ProviderTesterView") () => import("@/views/developer/ProviderTesterView")
)} )}
/> />
<Route <Route
exact exact
path="/dev/embeds" path="/dev/embeds"
component={lazy( component={lazy(
() => import("@/views/developer/EmbedTesterView") () => import("@/views/developer/EmbedTesterView")
)} )}
/> />
</> </>
) : null} ) : null}
<Route path="*" component={NotFoundPage} /> <Route path="*" component={NotFoundPage} />
</Switch> </Switch>
</LegacyUrlView>
</Layout> </Layout>
</BannerContextProvider> </BannerContextProvider>
</BookmarkContextProvider> </BookmarkContextProvider>