// ==UserScript== // @name M3u8 // @description 在线播放器 和 野鸡网站 通用过滤 采集资源 插播广告 // @version 20240526 // @author 江小白 // @include /(?:lay|ideo).*?\.html/ // @include /^https?:\/\/(?:movie\.douban\.com\/subject|m\.douban\.com\/movie)\// // @include /\.(?:m3u8|png|css)(?:#|\?|\\|&|$)/ // @run-at document-body // @namespace https://greasyfork.org/users/769699 // @downloadURL none // ==/UserScript== (function() { try { if (typeof location['m3u8去插播广告'] === 'undefined') { try { Object.defineProperty(location, 'm3u8去插播广告', { value: 'm3u8去插播广告', writable: false, enumerable: false, configurable: false }); } catch (e) {} let urlvip, m3u8wz, mp4wz, flvwz, tswz, playsharewz, ggbmd, shouldStopExecution, 打印, ggtspd, gggzpd, ggsjgg, ggzlhx, ggljbmd, hhzz, bhhzz, m3u8gglj; urlvip = location.href; m3u8gglj = ''; hhzz = '[\\n\\r\\u0085\\u2028\\u2029]'; bhhzz = '[^\\n\\r\\u0085\\u2028\\u2029]'; m3u8wz = /\.(?: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) {} })();