diff --git a/src/components/player/hooks/useSkipTime.ts b/src/components/player/hooks/useSkipTime.ts index d114775f..334526f6 100644 --- a/src/components/player/hooks/useSkipTime.ts +++ b/src/components/player/hooks/useSkipTime.ts @@ -9,13 +9,19 @@ import { getTurnstileToken } from "@/utils/turnstile"; // Thanks Nemo for this API const THE_INTRO_DB_BASE_URL = "https://api.theintrodb.org/v1"; +const QUICKWATCH_BASE_URL = "https://skips.quickwatch.co"; const FED_SKIPS_BASE_URL = "https://fed-skips.pstream.mov"; // const VELORA_BASE_URL = "https://veloratv.ru/api/intro-end/confirmed"; const INTRODB_BASE_URL = "https://api.introdb.app/intro"; const MAX_RETRIES = 3; // Track the source of the current skip time (for analytics filtering) -let currentSkipTimeSource: "fed-skips" | "introdb" | "theintrodb" | null = null; +let currentSkipTimeSource: + | "fed-skips" + | "introdb" + | "theintrodb" + | "quickwatch" + | null = null; export function useSkipTimeSource(): typeof currentSkipTimeSource { return currentSkipTimeSource; @@ -75,6 +81,47 @@ export function useSkipTime() { // } // }; + const fetchQuickWatchTime = async (): Promise => { + if (!meta?.title || meta.type === "movie") return null; + if (!meta.season?.number || !meta.episode?.number) return null; + + try { + const encodedName = encodeURIComponent(meta.title); + const apiUrl = `${QUICKWATCH_BASE_URL}/api/skip-times?name=${encodedName}&season=${meta.season.number}&episode=${meta.episode.number}`; + + const data = await proxiedFetch(apiUrl); + + if (!Array.isArray(data) || data.length === 0) return null; + + // Find the first result with intro or credits data + for (const item of data) { + if (item.data) { + // Check for intro end time + if ( + item.data.intro?.end && + typeof item.data.intro.end === "number" + ) { + // Convert milliseconds to seconds + return Math.floor(item.data.intro.end / 1000); + } + // Check for credits start time (use as intro end) + if ( + item.data.credits?.start && + typeof item.data.credits.start === "number" + ) { + // Convert milliseconds to seconds + return Math.floor(item.data.credits.start / 1000); + } + } + } + + return null; + } catch (error) { + console.error("Error fetching QuickWatch time:", error); + return null; + } + }; + const fetchFedSkipsTime = async (retries = 0): Promise => { if (!meta?.imdbId || meta.type === "movie") return null; if (!conf().ALLOW_FEBBOX_KEY) return null; @@ -151,7 +198,15 @@ export function useSkipTime() { return; } - // Fall back to Fed-skips if TheIntroDB doesn't have anything + // Try QuickWatch API (TV shows only) + const quickWatchTime = await fetchQuickWatchTime(); + if (quickWatchTime !== null) { + currentSkipTimeSource = "quickwatch"; + setSkiptime(quickWatchTime); + return; + } + + // Fall back to Fed-skips if TheIntroDB and QuickWatch don't have anything // Note: Fed-skips only supports TV shows, not movies if (febboxKey && meta?.type !== "movie") { const fedSkipsTime = await fetchFedSkipsTime(); @@ -174,6 +229,7 @@ export function useSkipTime() { }, [ meta?.tmdbId, meta?.imdbId, + meta?.title, meta?.type, meta?.season?.number, meta?.episode?.number, diff --git a/src/components/player/internals/Backend/SkipTracker.tsx b/src/components/player/internals/Backend/SkipTracker.tsx index 9a9cd335..0cf71f55 100644 --- a/src/components/player/internals/Backend/SkipTracker.tsx +++ b/src/components/player/internals/Backend/SkipTracker.tsx @@ -19,7 +19,7 @@ interface PendingSkip { startTime: number; endTime: number; hasBackwardMovement: boolean; - skipTimeSource: "fed-skips" | "introdb" | "theintrodb" | null; + skipTimeSource: "fed-skips" | "introdb" | "theintrodb" | "quickwatch" | null; timer: ReturnType; } @@ -77,7 +77,8 @@ export function SkipTracker() { // Only send analytics if skip time came from fed-skips or introdb (not theintrodb) if ( pendingSkip.skipTimeSource === "fed-skips" || - pendingSkip.skipTimeSource === "introdb" + pendingSkip.skipTimeSource === "introdb" || + pendingSkip.skipTimeSource === "quickwatch" ) { // Send analytics sendSkipAnalytics(pendingSkip.skip, adjustedConfidence); @@ -113,7 +114,7 @@ export function SkipTracker() { // Create pending skip with 5-second delay const pendingSkip = createPendingSkip(latestSkip); - setPendingSkips((prev) => [...prev, pendingSkip]); + setPendingSkips((prev) => [...prev, pendingSkip as PendingSkip]); lastLoggedSkipRef.current = latestSkip.timestamp; }, [latestSkip, meta, createPendingSkip]);