Skip to content

Commit

Permalink
Replacement now takes resolution into account
Browse files Browse the repository at this point in the history
  • Loading branch information
younesaassila committed Dec 22, 2023
1 parent d87d42c commit d125d4b
Show file tree
Hide file tree
Showing 4 changed files with 159 additions and 34 deletions.
78 changes: 77 additions & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,8 @@
"license": "GPL-3.0",
"dependencies": {
"bowser": "^2.11.0",
"ip": "^1.1.8"
"ip": "^1.1.8",
"m3u8-parser": "^7.1.0"
},
"devDependencies": {
"@parcel/config-webextension": "^2.10.3",
Expand Down
41 changes: 41 additions & 0 deletions src/m3u8-parser.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
declare module "m3u8-parser" {
export class Parser {
constructor();
push(chunk: string): void;
end(): void;
manifest: Manifest;
}
}

interface Manifest {
allowCache: boolean;
discontinuityStarts: any[];
dateRanges: any[];
segments: any[];
mediaGroups?: {
AUDIO: {};
VIDEO: {};
"CLOSED-CAPTIONS": {};
SUBTITLES: {};
};
playlists?: Playlist[];
}

interface Playlist {
attributes: Attributes;
uri: string;
timeline: number;
}

interface Attributes {
"FRAME-RATE": number;
VIDEO: string;
CODECS: string;
RESOLUTION: Resolution;
BANDWIDTH: number;
}

interface Resolution {
width: number;
height: number;
}
71 changes: 39 additions & 32 deletions src/page/getFetch.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import * as m3u8Parser from "m3u8-parser";
import acceptFlag from "../common/ts/acceptFlag";
import findChannelFromTwitchTvUrl from "../common/ts/findChannelFromTwitchTvUrl";
import findChannelFromUsherUrl from "../common/ts/findChannelFromUsherUrl";
Expand Down Expand Up @@ -44,8 +45,23 @@ export function getFetch(options: FetchOptions): typeof fetch {
let cachedPlaybackTokenRequestHeaders: Map<string, string> | null = null;
let cachedPlaybackTokenRequestBody: string | null = null;
let cachedUsherRequestUrl: string | null = null;
let currentVideoWeaverUrls: string[] | null = null;
let replacementVideoWeaverUrls: string[] | null = null;

let currentVideoWeaversMap: Map<string, string> | null = null;
let replacementVideoWeaversMap: Map<string, string> | null = null;

function usherResponseToMap(response: string): Map<string, string> | null {
const parser = new m3u8Parser.Parser();
parser.push(response);
parser.end();
const parsedManifest = parser.manifest;
if (parsedManifest.playlists == null) return null;
return new Map(
parsedManifest.playlists.map(playlist => [
playlist.attributes.VIDEO,
playlist.uri,
])
);
}

if (options.shouldWaitForStore) {
setTimeout(() => {
Expand Down Expand Up @@ -76,17 +92,17 @@ export function getFetch(options: FetchOptions): typeof fetch {
setTimeout(async () => {
try {
console.log("[TTV LOL PRO] 🔄 Checking for new Video Weaver URLs…");
const newVideoWeaverUrls = await fetchReplacementVideoWeaverUrls(
const newUsherManifest = await fetchReplacementUsherManifest(
cachedUsherRequestUrl
);
if (newVideoWeaverUrls == null) {
if (newUsherManifest == null) {
console.log("[TTV LOL PRO] 🔄 No new Video Weaver URLs found.");
return;
}
replacementVideoWeaverUrls = newVideoWeaverUrls;
replacementVideoWeaversMap = usherResponseToMap(newUsherManifest);
console.log(
"[TTV LOL PRO] 🔄 Found new Video Weaver URLs:",
replacementVideoWeaverUrls
Object.fromEntries(replacementVideoWeaversMap?.entries() ?? [])
);
} catch (error) {
console.error(
Expand Down Expand Up @@ -212,22 +228,18 @@ export function getFetch(options: FetchOptions): typeof fetch {
console.debug(`[TTV LOL PRO] 🥅 Caught Video Weaver request '${url}'.`);
// TODO: Implement replacement limit if the ad is a preroll to avoid infinite loops.
let videoWeaverUrl = url;
if (replacementVideoWeaverUrls != null) {
// const index = currentVideoWeaverUrls?.findIndex(
// url =>
// url.split("playlist/")[1] === videoWeaverUrl.split("playlist/")[1]
// );
// console.log("index = ", index);
// if (index != null && index >= 0) {
// videoWeaverUrl =
// replacementVideoWeaverUrls[
// Math.min(index, replacementVideoWeaverUrls.length - 1)
// ];
// console.log(
// `[TTV LOL PRO] 🔄 Replaced Video Weaver URL '${url}' with '${videoWeaverUrl}'.`
// );
// }
videoWeaverUrl = replacementVideoWeaverUrls[0];
if (
replacementVideoWeaversMap != null &&
replacementVideoWeaversMap.size > 0
) {
const video = [...(currentVideoWeaversMap?.entries() ?? [])].find(
([key, value]) => value === url
)?.[0];
if (video != null && replacementVideoWeaversMap.has(video)) {
videoWeaverUrl = replacementVideoWeaversMap.get(video)!;
} else {
videoWeaverUrl = [...replacementVideoWeaversMap.values()][0];
}
console.log(
`[TTV LOL PRO] 🔄 Replaced Video Weaver URL '${url}' with '${videoWeaverUrl}'.`
);
Expand Down Expand Up @@ -279,11 +291,9 @@ export function getFetch(options: FetchOptions): typeof fetch {
// Usher responses.
if (host != null && usherHostRegex.test(host)) {
responseBody = await readResponseBody();
currentVideoWeaverUrls = responseBody
.split("\n")
.filter(line => videoWeaverUrlRegex.test(line));
replacementVideoWeaverUrls = null;
console.debug("[TTV LOL PRO] 🥅 Caught Usher response.");
currentVideoWeaversMap = usherResponseToMap(responseBody);
replacementVideoWeaversMap = null;
const videoWeaverUrls = responseBody
.split("\n")
.filter(line => videoWeaverUrlRegex.test(line));
Expand Down Expand Up @@ -552,9 +562,9 @@ function getReplacementUsherUrl(
}
}

async function fetchReplacementVideoWeaverUrls(
async function fetchReplacementUsherManifest(
cachedUsherRequestUrl: string | null
): Promise<string[] | null> {
): Promise<string | null> {
if (cachedUsherRequestUrl == null) return null;
try {
const newPlaybackAccessToken = await sendMessageToPageScript({
Expand All @@ -574,10 +584,7 @@ async function fetchReplacementVideoWeaverUrls(
}
const response = await NATIVE_FETCH(newUsherUrl);
const text = await response.text();
const videoWeaverUrls = text
.split("\n")
.filter(line => videoWeaverUrlRegex.test(line));
return videoWeaverUrls;
return text;
} catch {
return null;
}
Expand Down

0 comments on commit d125d4b

Please sign in to comment.