preliminary refactor

This commit is contained in:
castdrian 2023-06-12 20:17:42 +02:00
parent 40e45ae103
commit dfe67157d4
8 changed files with 332 additions and 329 deletions

View File

@ -1,14 +1,7 @@
import { SimpleCache } from "@/utils/cache"; import { SimpleCache } from "@/utils/cache";
import { import { Trakt, mediaTypeToTTV } from "./trakttv";
JWContentTypes,
JWMediaResult,
JW_API_BASE,
formatJWMeta,
mediaTypeToJW,
} from "./justwatch";
import { MWMediaMeta, MWQuery } from "./types"; import { MWMediaMeta, MWQuery } from "./types";
import { proxiedFetch } from "../helpers/fetch";
const cache = new SimpleCache<MWQuery, MWMediaMeta[]>(); const cache = new SimpleCache<MWQuery, MWMediaMeta[]>();
cache.setCompare((a, b) => { cache.setCompare((a, b) => {
@ -16,44 +9,13 @@ cache.setCompare((a, b) => {
}); });
cache.initialize(); cache.initialize();
type JWSearchQuery = {
content_types: JWContentTypes[];
page: number;
page_size: number;
query: string;
};
type JWPage<T> = {
items: T[];
page: number;
page_size: number;
total_pages: number;
total_results: number;
};
export async function searchForMedia(query: MWQuery): Promise<MWMediaMeta[]> { export async function searchForMedia(query: MWQuery): Promise<MWMediaMeta[]> {
if (cache.has(query)) return cache.get(query) as MWMediaMeta[]; if (cache.has(query)) return cache.get(query) as MWMediaMeta[];
const { searchQuery, type } = query; const { searchQuery, type } = query;
const contentType = mediaTypeToJW(type); const contentType = mediaTypeToTTV(type);
const body: JWSearchQuery = {
content_types: [contentType],
page: 1,
query: searchQuery,
page_size: 40,
};
const data = await proxiedFetch<JWPage<JWMediaResult>>( const results = await Trakt.search(searchQuery, contentType);
"/content/titles/en_US/popular", cache.set(query, results, 3600);
{ return results;
baseURL: JW_API_BASE,
params: {
body: JSON.stringify(body),
},
}
);
const returnData = data.items.map<MWMediaMeta>((v) => formatJWMeta(v));
cache.set(query, returnData, 3600); // cache for an hour
return returnData;
} }

View File

@ -1,21 +0,0 @@
import { SimpleCache } from "@/utils/cache";
import { Trakt, mediaTypeToTTV } from "./trakttv";
import { MWMediaMeta, MWQuery } from "./types";
const cache = new SimpleCache<MWQuery, MWMediaMeta[]>();
cache.setCompare((a, b) => {
return a.type === b.type && a.searchQuery.trim() === b.searchQuery.trim();
});
cache.initialize();
export async function searchForMedia(query: MWQuery): Promise<MWMediaMeta[]> {
if (cache.has(query)) return cache.get(query) as MWMediaMeta[];
const { searchQuery, type } = query;
const contentType = mediaTypeToTTV(type);
const results = await Trakt.search(searchQuery, contentType);
cache.set(query, results, 3600);
return results;
}

View File

@ -0,0 +1,59 @@
import { SimpleCache } from "@/utils/cache";
import {
JWContentTypes,
JWMediaResult,
JW_API_BASE,
formatJWMeta,
mediaTypeToJW,
} from "./justwatch";
import { MWMediaMeta, MWQuery } from "./types_old";
import { proxiedFetch } from "../helpers/fetch";
const cache = new SimpleCache<MWQuery, MWMediaMeta[]>();
cache.setCompare((a, b) => {
return a.type === b.type && a.searchQuery.trim() === b.searchQuery.trim();
});
cache.initialize();
type JWSearchQuery = {
content_types: JWContentTypes[];
page: number;
page_size: number;
query: string;
};
type JWPage<T> = {
items: T[];
page: number;
page_size: number;
total_pages: number;
total_results: number;
};
export async function searchForMedia(query: MWQuery): Promise<MWMediaMeta[]> {
if (cache.has(query)) return cache.get(query) as MWMediaMeta[];
const { searchQuery, type } = query;
const contentType = mediaTypeToJW(type);
const body: JWSearchQuery = {
content_types: [contentType],
page: 1,
query: searchQuery,
page_size: 40,
};
const data = await proxiedFetch<JWPage<JWMediaResult>>(
"/content/titles/en_US/popular",
{
baseURL: JW_API_BASE,
params: {
body: JSON.stringify(body),
},
}
);
const returnData = data.items.map<MWMediaMeta>((v) => formatJWMeta(v));
cache.set(query, returnData, 3600); // cache for an hour
return returnData;
}

View File

@ -1,7 +1,6 @@
import { conf } from "@/setup/config"; import { conf } from "@/setup/config";
import { import {
DetailedMeta,
MWMediaType, MWMediaType,
TMDBMediaStatic, TMDBMediaStatic,
TMDBMovieData, TMDBMovieData,

View File

@ -45,3 +45,220 @@ export interface MWQuery {
searchQuery: string; searchQuery: string;
type: MWMediaType; type: MWMediaType;
} }
export type TTVContentTypes = "movie" | "show";
export type TTVSeasonShort = {
title: string;
id: number;
season_number: number;
};
export type TTVEpisodeShort = {
title: string;
id: number;
episode_number: number;
};
export type TTVMediaResult = {
title: string;
poster?: string;
id: number;
original_release_year?: number;
ttv_entity_id: string;
object_type: TTVContentTypes;
seasons?: TTVSeasonShort[];
};
export type TTVSeasonMetaResult = {
title: string;
id: string;
season_number: number;
episodes: TTVEpisodeShort[];
};
export interface TTVSearchResult {
type: "movie" | "show";
score: number;
movie?: {
title: string;
year: number;
ids: {
trakt: number;
slug: string;
imdb: string;
tmdb: number;
};
};
show?: {
title: string;
year: number;
ids: {
trakt: number;
slug: string;
tvdb: number;
imdb: string;
tmdb: number;
};
};
}
export interface DetailedMeta {
meta: MWMediaMeta;
imdbId?: string;
tmdbId?: string;
}
export interface TMDBShowData {
adult: boolean;
backdrop_path: string | null;
created_by: {
id: number;
credit_id: string;
name: string;
gender: number;
profile_path: string | null;
}[];
episode_run_time: number[];
first_air_date: string;
genres: {
id: number;
name: string;
}[];
homepage: string;
id: number;
in_production: boolean;
languages: string[];
last_air_date: string;
last_episode_to_air: {
id: number;
name: string;
overview: string;
vote_average: number;
vote_count: number;
air_date: string;
episode_number: number;
production_code: string;
runtime: number | null;
season_number: number;
show_id: number;
still_path: string | null;
} | null;
name: string;
next_episode_to_air: {
id: number;
name: string;
overview: string;
vote_average: number;
vote_count: number;
air_date: string;
episode_number: number;
production_code: string;
runtime: number | null;
season_number: number;
show_id: number;
still_path: string | null;
} | null;
networks: {
id: number;
logo_path: string;
name: string;
origin_country: string;
}[];
number_of_episodes: number;
number_of_seasons: number;
origin_country: string[];
original_language: string;
original_name: string;
overview: string;
popularity: number;
poster_path: string | null;
production_companies: {
id: number;
logo_path: string | null;
name: string;
origin_country: string;
}[];
production_countries: {
iso_3166_1: string;
name: string;
}[];
seasons: {
air_date: string;
episode_count: number;
id: number;
name: string;
overview: string;
poster_path: string | null;
season_number: number;
}[];
spoken_languages: {
english_name: string;
iso_639_1: string;
name: string;
}[];
status: string;
tagline: string;
type: string;
vote_average: number;
vote_count: number;
}
export interface TMDBMovieData {
adult: boolean;
backdrop_path: string | null;
belongs_to_collection: {
id: number;
name: string;
poster_path: string | null;
backdrop_path: string | null;
} | null;
budget: number;
genres: {
id: number;
name: string;
}[];
homepage: string | null;
id: number;
imdb_id: string | null;
original_language: string;
original_title: string;
overview: string | null;
popularity: number;
poster_path: string | null;
production_companies: {
id: number;
logo_path: string | null;
name: string;
origin_country: string;
}[];
production_countries: {
iso_3166_1: string;
name: string;
}[];
release_date: string;
revenue: number;
runtime: number | null;
spoken_languages: {
english_name: string;
iso_639_1: string;
name: string;
}[];
status: string;
tagline: string | null;
title: string;
video: boolean;
vote_average: number;
vote_count: number;
}
export type TMDBMediaDetailsPromise = Promise<TMDBShowData | TMDBMovieData>;
export interface TMDBMediaStatic {
getMediaDetails(
id: string,
type: MWMediaType.SERIES
): TMDBMediaDetailsPromise;
getMediaDetails(id: string, type: MWMediaType.MOVIE): TMDBMediaDetailsPromise;
getMediaDetails(id: string, type: MWMediaType): TMDBMediaDetailsPromise;
}

View File

@ -1,264 +0,0 @@
export enum MWMediaType {
MOVIE = "movie",
SERIES = "series",
ANIME = "anime",
}
export type MWSeasonMeta = {
id: string;
number: number;
title: string;
};
export type MWSeasonWithEpisodeMeta = {
id: string;
number: number;
title: string;
episodes: {
id: string;
number: number;
title: string;
}[];
};
type MWMediaMetaBase = {
title: string;
id: string;
year?: string;
poster?: string;
};
type MWMediaMetaSpecific =
| {
type: MWMediaType.MOVIE | MWMediaType.ANIME;
seasons: undefined;
}
| {
type: MWMediaType.SERIES;
seasons: MWSeasonMeta[];
seasonData: MWSeasonWithEpisodeMeta;
};
export type MWMediaMeta = MWMediaMetaBase & MWMediaMetaSpecific;
export interface MWQuery {
searchQuery: string;
type: MWMediaType;
}
export type TTVContentTypes = "movie" | "show";
export type TTVSeasonShort = {
title: string;
id: number;
season_number: number;
};
export type TTVEpisodeShort = {
title: string;
id: number;
episode_number: number;
};
export type TTVMediaResult = {
title: string;
poster?: string;
id: number;
original_release_year?: number;
ttv_entity_id: string;
object_type: TTVContentTypes;
seasons?: TTVSeasonShort[];
};
export type TTVSeasonMetaResult = {
title: string;
id: string;
season_number: number;
episodes: TTVEpisodeShort[];
};
export interface TTVSearchResult {
type: "movie" | "show";
score: number;
movie?: {
title: string;
year: number;
ids: {
trakt: number;
slug: string;
imdb: string;
tmdb: number;
};
};
show?: {
title: string;
year: number;
ids: {
trakt: number;
slug: string;
tvdb: number;
imdb: string;
tmdb: number;
};
};
}
export interface DetailedMeta {
meta: MWMediaMeta;
imdbId?: string;
tmdbId?: string;
}
export interface TMDBShowData {
adult: boolean;
backdrop_path: string | null;
created_by: {
id: number;
credit_id: string;
name: string;
gender: number;
profile_path: string | null;
}[];
episode_run_time: number[];
first_air_date: string;
genres: {
id: number;
name: string;
}[];
homepage: string;
id: number;
in_production: boolean;
languages: string[];
last_air_date: string;
last_episode_to_air: {
id: number;
name: string;
overview: string;
vote_average: number;
vote_count: number;
air_date: string;
episode_number: number;
production_code: string;
runtime: number | null;
season_number: number;
show_id: number;
still_path: string | null;
} | null;
name: string;
next_episode_to_air: {
id: number;
name: string;
overview: string;
vote_average: number;
vote_count: number;
air_date: string;
episode_number: number;
production_code: string;
runtime: number | null;
season_number: number;
show_id: number;
still_path: string | null;
} | null;
networks: {
id: number;
logo_path: string;
name: string;
origin_country: string;
}[];
number_of_episodes: number;
number_of_seasons: number;
origin_country: string[];
original_language: string;
original_name: string;
overview: string;
popularity: number;
poster_path: string | null;
production_companies: {
id: number;
logo_path: string | null;
name: string;
origin_country: string;
}[];
production_countries: {
iso_3166_1: string;
name: string;
}[];
seasons: {
air_date: string;
episode_count: number;
id: number;
name: string;
overview: string;
poster_path: string | null;
season_number: number;
}[];
spoken_languages: {
english_name: string;
iso_639_1: string;
name: string;
}[];
status: string;
tagline: string;
type: string;
vote_average: number;
vote_count: number;
}
export interface TMDBMovieData {
adult: boolean;
backdrop_path: string | null;
belongs_to_collection: {
id: number;
name: string;
poster_path: string | null;
backdrop_path: string | null;
} | null;
budget: number;
genres: {
id: number;
name: string;
}[];
homepage: string | null;
id: number;
imdb_id: string | null;
original_language: string;
original_title: string;
overview: string | null;
popularity: number;
poster_path: string | null;
production_companies: {
id: number;
logo_path: string | null;
name: string;
origin_country: string;
}[];
production_countries: {
iso_3166_1: string;
name: string;
}[];
release_date: string;
revenue: number;
runtime: number | null;
spoken_languages: {
english_name: string;
iso_639_1: string;
name: string;
}[];
status: string;
tagline: string | null;
title: string;
video: boolean;
vote_average: number;
vote_count: number;
}
export type TMDBMediaDetailsPromise = Promise<TMDBShowData | TMDBMovieData>;
export interface TMDBMediaStatic {
getMediaDetails(
id: string,
type: MWMediaType.SERIES
): TMDBMediaDetailsPromise;
getMediaDetails(id: string, type: MWMediaType.MOVIE): TMDBMediaDetailsPromise;
getMediaDetails(id: string, type: MWMediaType): TMDBMediaDetailsPromise;
}

View File

@ -0,0 +1,47 @@
export enum MWMediaType {
MOVIE = "movie",
SERIES = "series",
ANIME = "anime",
}
export type MWSeasonMeta = {
id: string;
number: number;
title: string;
};
export type MWSeasonWithEpisodeMeta = {
id: string;
number: number;
title: string;
episodes: {
id: string;
number: number;
title: string;
}[];
};
type MWMediaMetaBase = {
title: string;
id: string;
year?: string;
poster?: string;
};
type MWMediaMetaSpecific =
| {
type: MWMediaType.MOVIE | MWMediaType.ANIME;
seasons: undefined;
}
| {
type: MWMediaType.SERIES;
seasons: MWSeasonMeta[];
seasonData: MWSeasonWithEpisodeMeta;
};
export type MWMediaMeta = MWMediaMetaBase & MWMediaMetaSpecific;
export interface MWQuery {
searchQuery: string;
type: MWMediaType;
}

View File

@ -8,6 +8,7 @@ interface Config {
TMDB_API_KEY: string; TMDB_API_KEY: string;
CORS_PROXY_URL: string; CORS_PROXY_URL: string;
NORMAL_ROUTER: boolean; NORMAL_ROUTER: boolean;
TRAKT_CLIENT_ID: string;
} }
export interface RuntimeConfig { export interface RuntimeConfig {
@ -18,6 +19,7 @@ export interface RuntimeConfig {
TMDB_API_KEY: string; TMDB_API_KEY: string;
NORMAL_ROUTER: boolean; NORMAL_ROUTER: boolean;
PROXY_URLS: string[]; PROXY_URLS: string[];
TRAKT_CLIENT_ID: string;
} }
const env: Record<keyof Config, undefined | string> = { const env: Record<keyof Config, undefined | string> = {
@ -28,6 +30,7 @@ const env: Record<keyof Config, undefined | string> = {
DISCORD_LINK: undefined, DISCORD_LINK: undefined,
CORS_PROXY_URL: import.meta.env.VITE_CORS_PROXY_URL, CORS_PROXY_URL: import.meta.env.VITE_CORS_PROXY_URL,
NORMAL_ROUTER: import.meta.env.VITE_NORMAL_ROUTER, NORMAL_ROUTER: import.meta.env.VITE_NORMAL_ROUTER,
TRAKT_CLIENT_ID: import.meta.env.VITE_TRAKT_CLIENT_ID,
}; };
const alerts = [] as string[]; const alerts = [] as string[];
@ -62,5 +65,6 @@ export function conf(): RuntimeConfig {
.split(",") .split(",")
.map((v) => v.trim()), .map((v) => v.trim()),
NORMAL_ROUTER: getKey("NORMAL_ROUTER", "false") === "true", NORMAL_ROUTER: getKey("NORMAL_ROUTER", "false") === "true",
TRAKT_CLIENT_ID: getKey("TRAKT_CLIENT_ID"),
}; };
} }