Skip to content

Instantly share code, notes, and snippets.

@Nezteb
Created October 31, 2023 22:58
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Nezteb/92b231003c3e4dc03d9566f62173a2ce to your computer and use it in GitHub Desktop.
Save Nezteb/92b231003c3e4dc03d9566f62173a2ce to your computer and use it in GitHub Desktop.
// ==UserScript==
// @name Intercept m3u8 streams
// @description Intercept XHR/fetch requests involving m3u8 stream identifiers
// @namespace Violentmonkey Scripts
// @match *://*/*
// @version 0.1
// @author Noah Betzen
// @grant none
// ==/UserScript==
const STORAGE_KEY = `seenm3u8streams`;
(function() {
`use strict`;
const seenString = localStorage.getItem(STORAGE_KEY);
const seen = seenString ? JSON.parse(seenString) : {};
const count = Object.keys(seen).length;
if (count > 0) {
console.log(`Seen m3u8 streams: ${count}`, seen);
}
const originalFetch = fetch;
const originalXMLHttpRequest = window.XMLHttpRequest;
window.fetch = async function(...args) {
const response = await originalFetch.apply(this, args);
if (JSON.stringify(args).includes(`m3u8`)) {
// This is async but we don`t await it on purpose so that the response returns quickly
processFetch(response.clone(), seen);
}
return response;
};
window.XMLHttpRequest = function(...args) {
const xhr = new originalXMLHttpRequest(...args);
xhr.addEventListener(`readystatechange`, function() {
if (xhr.readyState === 4 && xhr.status === 200) {
const lines = xhr.responseText.split(`\n`);
lines.forEach((line, index) => {
if (line.includes(`m3u8`)) {
processXHR(line, seen);
}
});
}
});
return xhr;
};
})();
async function processFetch(resp, seen) {
const responseData = await resp.json();
console.log(`Fetch m3u8 discovered`, responseData)
// TODO: Finish fetch implementation (only need XHR currently)
return responseData;
}
async function processXHR(line, seen) {
// Key url is stripped of query/hash params
const url = new URL(line);
const keyUrl = url.origin + url.pathname;
if (!seen[keyUrl]) {
console.log(`Unseen URL: ${keyUrl}`)
// TODO: No easy way to download the thing, use CLI tool on collected URLs
seen[keyUrl] = line;
localStorage.setItem(STORAGE_KEY, JSON.stringify(seen));
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment