Created
October 31, 2023 22:58
-
-
Save Nezteb/92b231003c3e4dc03d9566f62173a2ce to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// ==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