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.

update skips!

Pas 5b32daac 02a179b1

+66 -5
+53 -2
src/components/player/hooks/useSkipTime.ts
··· 8 8 import { getTurnstileToken } from "@/utils/turnstile"; 9 9 10 10 // Thanks Nemo for this API 11 + const THE_INTRO_DB_BASE_URL = "https://api.theintrodb.org"; 11 12 const FED_SKIPS_BASE_URL = "https://fed-skips.pstream.mov"; 12 13 // const VELORA_BASE_URL = "https://veloratv.ru/api/intro-end/confirmed"; 13 14 const INTRODB_BASE_URL = "https://api.introdb.app/intro"; 14 15 const MAX_RETRIES = 3; 15 16 17 + // Track the source of the current skip time (for analytics filtering) 18 + let currentSkipTimeSource: "fed-skips" | "introdb" | "theintrodb" | null = null; 19 + 20 + export function useSkipTimeSource(): typeof currentSkipTimeSource { 21 + return currentSkipTimeSource; 22 + } 23 + 16 24 export function useSkipTime() { 17 25 const { playerMeta: meta } = usePlayerMeta(); 18 26 const [skiptime, setSkiptime] = useState<number | null>(null); 19 27 const febboxKey = usePreferencesStore((s) => s.febboxKey); 20 28 21 29 useEffect(() => { 30 + const fetchTheIntroDBTime = async (): Promise<number | null> => { 31 + if (!meta?.imdbId) return null; 32 + 33 + try { 34 + let apiUrl = `${THE_INTRO_DB_BASE_URL}?imdb_id=${meta.imdbId}`; 35 + if ( 36 + meta.type !== "movie" && 37 + meta.season?.number && 38 + meta.episode?.number 39 + ) { 40 + apiUrl += `&season=${meta.season.number}&episode=${meta.episode.number}`; 41 + } 42 + 43 + const data = await proxiedFetch(apiUrl); 44 + 45 + if (data && typeof data.end_ms === "number") { 46 + // Convert milliseconds to seconds 47 + return Math.floor(data.end_ms / 1000); 48 + } 49 + 50 + return null; 51 + } catch (error) { 52 + console.error("Error fetching TIDB time:", error); 53 + return null; 54 + } 55 + }; 56 + 22 57 // const fetchVeloraSkipTime = async (): Promise<number | null> => { 23 58 // if (!meta?.tmdbId) return null; 24 59 ··· 105 140 }; 106 141 107 142 const fetchSkipTime = async (): Promise<void> => { 143 + // Reset source 144 + currentSkipTimeSource = null; 145 + 108 146 // If user has febbox key, prioritize Fed-skips (better quality) 109 - if (febboxKey) { 147 + // Note: Fed-skips only supports TV shows, not movies 148 + if (febboxKey && meta?.type !== "movie") { 110 149 const fedSkipsTime = await fetchFedSkipsTime(); 111 150 if (fedSkipsTime !== null) { 151 + currentSkipTimeSource = "fed-skips"; 112 152 setSkiptime(fedSkipsTime); 113 153 return; 114 154 } 115 155 } 116 156 117 - // Fall back to IntroDB API (available to all users) 157 + // Try TheIntroDB API (supports both movies and TV shows) 158 + const theIntroDBTime = await fetchTheIntroDBTime(); 159 + if (theIntroDBTime !== null) { 160 + currentSkipTimeSource = "theintrodb"; 161 + setSkiptime(theIntroDBTime); 162 + return; 163 + } 164 + 165 + // Fall back to IntroDB API (TV shows only, available to all users) 118 166 const introDBTime = await fetchIntroDBTime(); 167 + if (introDBTime !== null) { 168 + currentSkipTimeSource = "introdb"; 169 + } 119 170 setSkiptime(introDBTime); 120 171 }; 121 172
+13 -3
src/components/player/internals/Backend/SkipTracker.tsx
··· 1 1 import { useCallback, useEffect, useRef, useState } from "react"; 2 2 3 + import { useSkipTimeSource } from "@/components/player/hooks/useSkipTime"; 3 4 import { useSkipTracking } from "@/components/player/hooks/useSkipTracking"; 4 5 import { usePlayerStore } from "@/stores/player/store"; 5 6 ··· 18 19 startTime: number; 19 20 endTime: number; 20 21 hasBackwardMovement: boolean; 22 + skipTimeSource: "fed-skips" | "introdb" | "theintrodb" | null; 21 23 timer: ReturnType<typeof setTimeout>; 22 24 } 23 25 ··· 31 33 const meta = usePlayerStore((s) => s.meta); 32 34 const progress = usePlayerStore((s) => s.progress); 33 35 const turnstileToken = ""; 36 + const skipTimeSource = useSkipTimeSource(); 34 37 35 38 const sendSkipAnalytics = useCallback( 36 39 async (skip: SkipEvent, adjustedConfidence: number) => { ··· 71 74 ? Math.max(0.1, pendingSkip.originalConfidence * 0.5) // Reduce confidence by half if adjusted 72 75 : pendingSkip.originalConfidence; 73 76 74 - // Send analytics 75 - sendSkipAnalytics(pendingSkip.skip, adjustedConfidence); 77 + // Only send analytics if skip time came from fed-skips or introdb (not theintrodb) 78 + if ( 79 + pendingSkip.skipTimeSource === "fed-skips" || 80 + pendingSkip.skipTimeSource === "introdb" 81 + ) { 82 + // Send analytics 83 + sendSkipAnalytics(pendingSkip.skip, adjustedConfidence); 84 + } 76 85 77 86 // Remove from pending 78 87 return prev.filter((p) => p.skip.timestamp !== skip.timestamp); ··· 85 94 startTime: skip.startTime, 86 95 endTime: skip.endTime, 87 96 hasBackwardMovement: false, 97 + skipTimeSource, 88 98 timer, 89 99 }; 90 100 }, 91 - [sendSkipAnalytics], 101 + [sendSkipAnalytics, skipTimeSource], 92 102 ); 93 103 94 104 useEffect(() => {