// ==UserScript== // @name M3u8 // @description m3u8去插播广告 // @version 20240511 // @author 江小白 // @include /(?:lay|ideo).*?\.html/ // @include /^https?:\/\/(?:movie\.douban\.com\/subject|m\.douban\.com\/movie)\// // @include /\.(?:m3u8|png|css)(?:#|\?|\\|&|$)|(? typeof arg === "string" ? arg : arg instanceof Request ? arg.url : String(arg); const matchM3u = (url) => itemsHandle.find( (item) => item.reUrl.test(url) && !mp4wz.test(url) && !flvwz.test(url) && !tswz.test(url) && !playsharewz.test(url) && !ggbmd.test(url), ); const deleteAbnormalTs = (text, jxbgza, jxbgzb, jxbgzc, jxbgzd) => { if (!jxbgzd) { jxbgzd = /^\s*?(?:[a-z]+?\s*?-\s*?)?\d+?\s*?$/i; } else if (jxbgzd == "空") { jxbgzd = /^\s*?空\s*?$/; } try { const rgtya = "#EXTINF:\\d+?(?:\\.\\d+?)?," + hhzz + "+?", rgtyb = jxbgza + "\\.(?:" + ggzlhx + ")" + hhzz + "+", regex = "(?<=" + rgtya + ")(" + jxbgzb + ")(?=" + rgtyb + ")", regexx = new RegExp(regex, "gi"), matches = text.match(regexx), paths = {}; for (let i = 0; i < matches.length; i++) { const path = matches[i]; if (!paths[path]) { paths[path] = []; } paths[path].push(path); } let maxCount = 0, maxPath = ""; for (const path in paths) { if (paths[path].length > maxCount) { maxCount = paths[path].length; maxPath = path; } } for (const path in paths) { if (path !== maxPath) { paths[path].forEach((p) => { if (!jxbgzd.test(p)) { text = text.replace( new RegExp(rgtya + p + rgtyb, "gi"), (match) => { if (!/^\s*[0关]?\s*?$/i.test(打印)) { console.log( "%c[江小白-广告资源-已经发现] ✂\n%c对比" + jxbgzc + "的广告正则:\n%c" + regexx + "\n%c已经删除的广告内容:\n%c" + match, "border-left:5px solid #A0B;color:#A0B;padding:3px", "color:blue;", "color:red;", "color:blue;", "color:black;", ); } try { if (!ggtspd) { ggtspd = true; } } catch (e) {} return ""; }, ); } }); } } } catch (e) {} return text; }; const pruner = (text, item) => { try { if (!/^\s*#EXTM3U/i.test(text)) { return text; } else { try { if (!gggzpd) { gggzpd = true; if (!/^\s*[0关]?\s*?$/i.test(打印)) { console.table(itemsHandle); } } } catch (e) {} let modifiedText; try { modifiedText = deleteAbnormalTs( text, "[^\\.]+?", "(?:" + bhhzz + "+\\/|\\b)", "路径", ); try { modifiedText = deleteAbnormalTs( modifiedText, "\\d+?", "\\w+?(?:[^\\d]\\d{2})?", "名称", ); } catch (e) {} try { modifiedText = deleteAbnormalTs( modifiedText, "\\d+?", "\\w+(?=\\d{4})", "名称", "空", ); } catch (e) {} try { modifiedText = deleteAbnormalTs( modifiedText, "\\d+?", "[^0]\\d+[^0]0{2,}\\d0", "名称", /(?<=[^0]0{3,})\d+$/, ); } catch (e) {} } catch (e) { modifiedText = text; } for (const reAd of item.reAds) { const matches = modifiedText.match(reAd); if (matches) { matches.forEach((match) => { if (!/^\s*[0关]?\s*?$/i.test(打印)) { console.log( "%c[江小白-资源广告-已经发现] ✂\n%c已经生效的广告正则:\n%c" + reAd + "\n%c已经删除的广告内容:\n%c" + match, "border-left:5px solid #A0B;color:#A0B;padding:3px", "color:blue;", "color:red;", "color:blue;", "color:black;", ); } }); try { if (!ggtspd) { ggtspd = true; } } catch (e) {} } modifiedText = modifiedText.replace(reAd, ""); } if (modifiedText.length < text.length) { return modifiedText; } return text; } } catch (e) { return text; } }; const realFetch = self.fetch; self.fetch = new Proxy(self.fetch, { apply(target, thisArg, args) { const item = matchM3u(urlFromArg(args[0])); if (!item) { return Reflect.apply(target, thisArg, args); } return realFetch(...args).then((realResponse) => realResponse.text().then((text) => { const modifiedText = pruner(text, item); return new Response(modifiedText, { status: realResponse.status, statusText: realResponse.statusText, headers: realResponse.headers, }); }), ); }, }); self.XMLHttpRequest.prototype.open = new Proxy( self.XMLHttpRequest.prototype.open, { apply: async (target, thisArg, args) => { try { if (!shouldStopExecution) { urlFromArgBy = urlFromArg(args[1]); const item = matchM3u(urlFromArgBy); if (ggljbmd.test(urlFromArgBy)) { shouldStopExecution = true; } else { m3u8gglj = urlFromArgBy; } if (item) { thisArg.addEventListener( "readystatechange", async function () { if (thisArg.readyState !== 4) { return; } const type = thisArg.responseType; if (type !== "" && type !== "text") { return; } const textin = thisArg.responseText; const textout = pruner(textin, item); if (textout !== textin) { Reflect.defineProperty(thisArg, "response", { value: textout, }); Reflect.defineProperty(thisArg, "responseText", { value: textout, }); } }, ); } return Reflect.apply(target, thisArg, args); } else { return Reflect.apply(target, thisArg, args); } } catch (e) { return Reflect.apply(target, thisArg, args); } }, }, ); } } catch (e) {} } } catch (e) {} })();