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.

Version checking + preparing streams

mrjvs 421186cb f70d13f2

+68 -4
+5
src/backend/extension/compatibility.ts
··· 1 + const allowedExtensionVersion = ["0.0.1"]; 2 + 3 + export function isAllowedExtensionVersion(version: string): boolean { 4 + return allowedExtensionVersion.includes(version); 5 + }
+15 -2
src/backend/extension/messaging.ts
··· 3 3 sendToBackgroundViaRelay, 4 4 } from "@plasmohq/messaging"; 5 5 6 + import { isAllowedExtensionVersion } from "@/backend/extension/compatibility"; 7 + 6 8 let activeExtension = false; 7 9 8 10 export interface ExtensionHello { ··· 35 37 url: string, 36 38 ops: any, 37 39 ): Promise<ExtensionHello | null> { 38 - return sendMessage("proxy-request", { url, ...ops }); 40 + return sendMessage("make-request", { url, ...ops }); 41 + } 42 + 43 + export async function setDomainRule( 44 + domains: string[], 45 + headers: Record<string, string>, 46 + ): Promise<ExtensionHello | null> { 47 + return sendMessage("prepare-stream", { domains, headers }); 39 48 } 40 49 41 50 export async function extensionInfo(): Promise<ExtensionHello | null> { ··· 47 56 } 48 57 49 58 export async function isExtensionActive(): Promise<boolean> { 50 - return !!(await extensionInfo()); 59 + const info = await extensionInfo(); 60 + if (!info) return false; 61 + const allowedVersion = isAllowedExtensionVersion(info.version); 62 + if (!allowedVersion) return false; 63 + return true; 51 64 }
+2 -2
src/backend/extension/plasmo.ts
··· 20 20 }; 21 21 22 22 interface MmMetadata { 23 - "declarative-net-request": { 23 + "prepare-stream": { 24 24 req: PlasmoRequestBody; 25 25 res: ExtensionRequestReply; 26 26 }; 27 - "proxy-request": { 27 + "make-request": { 28 28 req: PlasmoRequestBody; 29 29 res: ExtensionRequestReply; 30 30 };
+40
src/backend/extension/streams.ts
··· 1 + import { Stream } from "@movie-web/providers"; 2 + 3 + import { setDomainRule } from "@/backend/extension/messaging"; 4 + 5 + function extractDomain(url: string): string { 6 + try { 7 + const u = new URL(url); 8 + return u.hostname; 9 + } catch { 10 + return url; 11 + } 12 + } 13 + 14 + function extractDomainsFromStream(stream: Stream): string[] { 15 + if (stream.type === "hls") { 16 + return [extractDomain(stream.playlist)]; 17 + } 18 + if (stream.type === "file") { 19 + return Object.values(stream.qualities).map((v) => extractDomain(v.url)); 20 + } 21 + return []; 22 + } 23 + 24 + function buildHeadersFromStream(stream: Stream): Record<string, string> { 25 + const headers: Record<string, string> = {}; 26 + Object.entries(stream.headers ?? {}).forEach((entry) => { 27 + headers[entry[0]] = entry[1]; 28 + }); 29 + Object.entries(stream.preferredHeaders ?? {}).forEach((entry) => { 30 + headers[entry[0]] = entry[1]; 31 + }); 32 + return headers; 33 + } 34 + 35 + export async function prepareStream(stream: Stream) { 36 + await setDomainRule( 37 + extractDomainsFromStream(stream), 38 + buildHeadersFromStream(stream), 39 + ); 40 + }
+3
src/components/player/hooks/useSourceSelection.ts
··· 5 5 } from "@movie-web/providers"; 6 6 import { useAsyncFn } from "react-use"; 7 7 8 + import { prepareStream } from "@/backend/extension/streams"; 8 9 import { 9 10 connectServerSideEvents, 10 11 makeProviderUrl, ··· 131 132 ]); 132 133 133 134 if (result.stream) { 135 + await prepareStream(result.stream[0]); 134 136 setCaption(null); 135 137 setSource( 136 138 convertRunoutputToSource({ stream: result.stream[0] }), ··· 187 189 ]); 188 190 setSourceId(sourceId); 189 191 setCaption(null); 192 + await prepareStream(embedResult.stream[0]); 190 193 setSource( 191 194 convertRunoutputToSource({ stream: embedResult.stream[0] }), 192 195 convertProviderCaption(embedResult.stream[0].captions),
+3
src/hooks/useProviderScrape.tsx
··· 5 5 } from "@movie-web/providers"; 6 6 import { RefObject, useCallback, useEffect, useRef, useState } from "react"; 7 7 8 + import { prepareStream } from "@/backend/extension/streams"; 8 9 import { 9 10 connectServerSideEvents, 10 11 getCachedMetadata, ··· 169 170 conn.on("update", updateEvent); 170 171 conn.on("discoverEmbeds", discoverEmbedsEvent); 171 172 const sseOutput = await conn.promise(); 173 + if (sseOutput) await prepareStream(sseOutput.stream); 172 174 173 175 return getResult(sseOutput === "" ? null : sseOutput); 174 176 } ··· 184 186 discoverEmbeds: discoverEmbedsEvent, 185 187 }, 186 188 }); 189 + if (output) await prepareStream(output.stream); 187 190 return getResult(output); 188 191 }, 189 192 [