/* eslint-disable no-console */ import { isExtensionActive } from "@/backend/extension/messaging"; import { proxiedFetch } from "@/backend/helpers/fetch"; import { makeExtensionFetcher } from "@/backend/providers/fetchers"; import { useAuthStore } from "@/stores/auth"; import { useLanguageStore } from "@/stores/language"; import { getTmdbLanguageCode } from "./language"; // IMDb language code mapping (differs from TMDB format) // Map from ISO language code to IMDb language parameter const imdbLanguageMap: Record = { "en-US": "en-US", "es-ES": "es-ES", "fr-FR": "fr-FR", "de-DE": "de-DE", "it-IT": "it-IT", "pt-PT": "pt-PT", "ru-RU": "ru-RU", "ja-JP": "ja-JP", "zh-CN": "zh-CN", "ko-KR": "ko-KR", "ar-SA": "ar-SA", "hi-IN": "hi-IN", "el-GR": "el-GR", // Add more mappings as needed }; /** * Convert a TMDB-style language code to an IMDb language code * @param language TMDB-style language code (e.g., "en-US") * @returns IMDb language code or default "en-US" */ function getImdbLanguageCode(language: string): string { // If we have a direct mapping, use it if (imdbLanguageMap[language]) return imdbLanguageMap[language]; // Otherwise default to English return "en-US"; } interface IMDbMetadata { title?: string; original_title?: string; title_type?: string; year?: number | null; end_year?: number | null; day?: number | null; month?: number | null; date?: string; runtime?: number | null; age_rating?: string; imdb_rating?: number | null; votes?: number | null; plot?: string; poster_url?: string; trailer_url?: string; trailer_thumbnail?: string; url?: string; genre?: string[]; cast?: string[]; directors?: string[]; writers?: string[]; keywords?: string[]; countries?: string[]; languages?: string[]; locations?: string[]; season?: number; episode?: number; episode_title?: string; episode_plot?: string; episode_rating?: number; episode_votes?: number; } const months = [ "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December", ]; const userAgents = [ "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36", "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:89.0) Gecko/20100101 Firefox/89.0", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.1.1 Safari/605.1.15", ]; function getRandomUserAgent(): string { return userAgents[Math.floor(Math.random() * userAgents.length)]; } export async function scrapeIMDb( imdbId: string, season?: number, episode?: number, language?: string, type?: "movie" | "show", ): Promise { // Check if we have a proxy or extension const hasExtension = await isExtensionActive(); const hasProxy = Boolean(useAuthStore.getState().proxySet); if (!hasExtension && !hasProxy) { // Custom API for trailers: const trailerResponse = await fetch( `https://fed-trailers.pstream.mov/${type === "movie" ? "movie" : "tv"}/${imdbId}`, ).then((res) => res.json()); if (trailerResponse.trailer?.embed_url) { return { trailer_url: trailerResponse.trailer.embed_url, }; } // END CUSTOM API throw new Error( "IMDb scraping requires either the browser extension or a custom proxy to be set up. " + "Please install the extension or set up a proxy in the settings.", ); } console.log( `[IMDb Scraper] Using ${hasExtension ? "browser extension" : "custom proxy"} for requests`, ); // Get user language if not provided if (!language) { const userLanguage = useLanguageStore.getState().language; language = getTmdbLanguageCode(userLanguage); } // Get IMDb language format const imdbLanguage = getImdbLanguageCode(language); // Construct IMDb URL with language parameter let imdbUrl = `https://www.imdb.com/title/${imdbId}/`; if (season && episode) { imdbUrl += `episodes?season=${season}`; } // Add language parameter to URL const separator = imdbUrl.includes("?") ? "&" : "?"; imdbUrl += `${separator}locale=${imdbLanguage}`; // Add random delay to avoid rate limiting const delay = Math.floor(Math.random() * (197 - 69) + 69); await new Promise((resolve) => { setTimeout(resolve, delay); }); // Fetch IMDb page using appropriate fetcher let response: string; if (hasExtension) { const extensionFetcher = makeExtensionFetcher(); const result = await extensionFetcher(imdbUrl, { headers: { "User-Agent": getRandomUserAgent(), "Accept-Language": imdbLanguage, }, method: "GET", query: {}, readHeaders: [], }); response = result.body as string; } else { response = await proxiedFetch(imdbUrl, { headers: { "User-Agent": getRandomUserAgent(), "Accept-Language": imdbLanguage, }, }); } // Extract JSON data from the page const jsonMatch = response.match( /