pstream is dead; long live pstream taciturnaxolotl.github.io/pstream-ng/
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

add quickwatch skip source

Pas 0b253648 7532184f

+62 -5
+58 -2
src/components/player/hooks/useSkipTime.ts
··· 9 9 10 10 // Thanks Nemo for this API 11 11 const THE_INTRO_DB_BASE_URL = "https://api.theintrodb.org/v1"; 12 + const QUICKWATCH_BASE_URL = "https://skips.quickwatch.co"; 12 13 const FED_SKIPS_BASE_URL = "https://fed-skips.pstream.mov"; 13 14 // const VELORA_BASE_URL = "https://veloratv.ru/api/intro-end/confirmed"; 14 15 const INTRODB_BASE_URL = "https://api.introdb.app/intro"; 15 16 const MAX_RETRIES = 3; 16 17 17 18 // Track the source of the current skip time (for analytics filtering) 18 - let currentSkipTimeSource: "fed-skips" | "introdb" | "theintrodb" | null = null; 19 + let currentSkipTimeSource: 20 + | "fed-skips" 21 + | "introdb" 22 + | "theintrodb" 23 + | "quickwatch" 24 + | null = null; 19 25 20 26 export function useSkipTimeSource(): typeof currentSkipTimeSource { 21 27 return currentSkipTimeSource; ··· 75 81 // } 76 82 // }; 77 83 84 + const fetchQuickWatchTime = async (): Promise<number | null> => { 85 + if (!meta?.title || meta.type === "movie") return null; 86 + if (!meta.season?.number || !meta.episode?.number) return null; 87 + 88 + try { 89 + const encodedName = encodeURIComponent(meta.title); 90 + const apiUrl = `${QUICKWATCH_BASE_URL}/api/skip-times?name=${encodedName}&season=${meta.season.number}&episode=${meta.episode.number}`; 91 + 92 + const data = await proxiedFetch(apiUrl); 93 + 94 + if (!Array.isArray(data) || data.length === 0) return null; 95 + 96 + // Find the first result with intro or credits data 97 + for (const item of data) { 98 + if (item.data) { 99 + // Check for intro end time 100 + if ( 101 + item.data.intro?.end && 102 + typeof item.data.intro.end === "number" 103 + ) { 104 + // Convert milliseconds to seconds 105 + return Math.floor(item.data.intro.end / 1000); 106 + } 107 + // Check for credits start time (use as intro end) 108 + if ( 109 + item.data.credits?.start && 110 + typeof item.data.credits.start === "number" 111 + ) { 112 + // Convert milliseconds to seconds 113 + return Math.floor(item.data.credits.start / 1000); 114 + } 115 + } 116 + } 117 + 118 + return null; 119 + } catch (error) { 120 + console.error("Error fetching QuickWatch time:", error); 121 + return null; 122 + } 123 + }; 124 + 78 125 const fetchFedSkipsTime = async (retries = 0): Promise<number | null> => { 79 126 if (!meta?.imdbId || meta.type === "movie") return null; 80 127 if (!conf().ALLOW_FEBBOX_KEY) return null; ··· 151 198 return; 152 199 } 153 200 154 - // Fall back to Fed-skips if TheIntroDB doesn't have anything 201 + // Try QuickWatch API (TV shows only) 202 + const quickWatchTime = await fetchQuickWatchTime(); 203 + if (quickWatchTime !== null) { 204 + currentSkipTimeSource = "quickwatch"; 205 + setSkiptime(quickWatchTime); 206 + return; 207 + } 208 + 209 + // Fall back to Fed-skips if TheIntroDB and QuickWatch don't have anything 155 210 // Note: Fed-skips only supports TV shows, not movies 156 211 if (febboxKey && meta?.type !== "movie") { 157 212 const fedSkipsTime = await fetchFedSkipsTime(); ··· 174 229 }, [ 175 230 meta?.tmdbId, 176 231 meta?.imdbId, 232 + meta?.title, 177 233 meta?.type, 178 234 meta?.season?.number, 179 235 meta?.episode?.number,
+4 -3
src/components/player/internals/Backend/SkipTracker.tsx
··· 19 19 startTime: number; 20 20 endTime: number; 21 21 hasBackwardMovement: boolean; 22 - skipTimeSource: "fed-skips" | "introdb" | "theintrodb" | null; 22 + skipTimeSource: "fed-skips" | "introdb" | "theintrodb" | "quickwatch" | null; 23 23 timer: ReturnType<typeof setTimeout>; 24 24 } 25 25 ··· 77 77 // Only send analytics if skip time came from fed-skips or introdb (not theintrodb) 78 78 if ( 79 79 pendingSkip.skipTimeSource === "fed-skips" || 80 - pendingSkip.skipTimeSource === "introdb" 80 + pendingSkip.skipTimeSource === "introdb" || 81 + pendingSkip.skipTimeSource === "quickwatch" 81 82 ) { 82 83 // Send analytics 83 84 sendSkipAnalytics(pendingSkip.skip, adjustedConfidence); ··· 113 114 114 115 // Create pending skip with 5-second delay 115 116 const pendingSkip = createPendingSkip(latestSkip); 116 - setPendingSkips((prev) => [...prev, pendingSkip]); 117 + setPendingSkips((prev) => [...prev, pendingSkip as PendingSkip]); 117 118 118 119 lastLoggedSkipRef.current = latestSkip.timestamp; 119 120 }, [latestSkip, meta, createPendingSkip]);