Greasy Fork

Greasy Fork is available in English.

M3u8

在线播放器 和 在线接口 和 野鸡网站 通用过滤 采集资源 插播广告

目前为 2024-08-23 提交的版本。查看 最新版本

 // ==UserScript==
 // @name M3u8
 // @description 在线播放器 和 在线接口 和 野鸡网站 通用过滤 采集资源 插播广告
 // @version 20240823
 // @author 江小白
 // @match https://v.68sou.com/
 // @match *://nnyy.in/*/*.html
 // @include /\/[pP]lay\//
 // @include /(?:lay|ideo).*?\.html/
 // @include /^https?:\/\/(?:movie\.douban\.com\/subject|m\.douban\.com\/movie)\//
 // @include /^https?:\/\/.+?(?<!refer(?:rer)?)[&#=\?]https?(?::\/\/|:\\\/\\\/|%3A%2F%2F)/
 // @include /^https?:\/\/(?!.+?https?(?::\/\/|:\\\/\\\/|%3A%2F%2F)).+?[\?&](?:url|rul)=(?!http).{5,}/
 // @include /^https?:\/\/[^\/]+?\/(?:play|share)\/[a-z0-9]+?\/?\s*?$/
 // @include /^https?:\/\/(?!.+?https?(?::\/\/|:\\\/\\\/|%3A%2F%2F)).+?\/(?:index\.php\/vod\/detail\/id\/\d+?|p\/\d[^\.]+?\d)\.html/
 // @include /\/\d+?[Kk]b\/hls\/index\.m3u8|\.m3u8\?[^=]+?=[^\/]*?(?:info|llq)|\.m3u8$/
 // @exclude /^https?:\/\/(?:(?:[^\/]+?\/){1,}\w+?\?\w*?id=.+?(?<!refer(?:rer)?)[&#=\?]https?(?::\/\/|:\\\/\\\/|%3A%2F%2F)|(?:[^\/]+?\/(?:proxyhttp|[a-zA-Z]*?kv\?)|.+?\.\w+?\/\d+?)$)/
 // @exclude /(?:^https?:\/\/(?!.+?https?(?::\/\/|:\\\/\\\/|%3A%2F%2F)).+?\.(?:ts|vob|3gp|rmvb|flac|[fh]lv|og[gv]|m(?:3u8|p[34]|kv|4a|ov|pg|idi|peg)|w(?:[am]v|ma|ebm)|a(?:ac|pe|vi|lac))|\.(?:js(?:on)?|rb|swf|png|xml|bmp|pac|gif|apk|exe|zip|txt|aspx|docx|jpe?g|p(?:y|df|ng)|i(?:co|dx)|r(?:ss|ar|[0-9]{2,2})|s(?:h|vg|rt|ub)|(?:c|le)ss|w(?:ebp|off2)))(?:#|\?|\\|&|$)/
 // @run-at document-end
// @namespace http://greasyfork.icu/users/769699
 // ==/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, wzm3u8, mp4wz, flvwz, tswz, playsharewz, ggbmd, shouldStopExecution, 打印, ggtspd, gggzpd, ggsjgg, ggzlhx, ggljbmd, ggljdmb, hhzz, bhhzz, dypd, m3u8gglj, m3u8ggljdypd, m3u8bflj;
             urlvip = location.href;
             m3u8gglj = '';
             m3u8bflj = '';
             hhzz = '[\\n\\r\\u0085\\u2028\\u2029]';
             bhhzz = '[^\\n\\r\\u0085\\u2028\\u2029]';
             wzm3u8 = /\/\d+?kb\/hls\/index\.m3u8|\.m3u8$/i;
             m3u8wz = /\.(?:m3u8|png|css)(?:#|\?|\\|&|$)|(?<!thread|forum|read)\.php(?!(?:[a-z0-9\/]|\?\w+?=.+?\.(?:m(?:p4|kv)|flv|ts)(?:#|\?|\\|&|$)))|\/(?!.+?\.m(?:3u8|p4)(?:#|\?|\\|&|$)).+?(?<![a-z0-9])m(?:3u8|p4)(?![a-z0-9])/i;
             mp4wz = /\.m(?:p4|kv)(?:#|\?|\\|&|$)|^https?:\/\/(?:[^\/]+?\.)?pstatp.+?\/obj\/[^\.]+?$|type=video_mp4&(?!.+\.[a-z]{2,5}(?:#|\?|\\|&|$))|\.php\?\w+?=.+?\.mp4/i;
             flvwz = /\.flv(?:#|\?|\\|&|$)/i;
             tswz = /\.ts(?:#|\?|\\|&|$)/i;
             playsharewz = /^https?:\/\/[^\/]+?\/{1,}(?:play|share)\/{1,}[a-zA-Z0-9]+?(?:\/{1,})?$/i;
             dypd = /^\s*?(?:[0关]\s*?)?$/;
             打印 = '开';
             ggsjgg = '4|20';
             ggzlhx = 'ts|jpg';
             ggljbmd = /&[a-z]*?(?:sign|token|version)=|\.(?:png|css|jpeg)(?:#|\?|\\|&|$|[\n\r\u0085\u2028\u2029])/i;
             ggbmd = /(?:\.php|\_(?:ts|mp4)\/.+?\.m3u8)(?:#|\?|\\|&|$)/i;
             ggljdmb = new RegExp('\\.(?:' + ggzlhx + ')' + hhzz + '+?#EXTINF','i');
             /*以下是核心代码不懂勿动*/
             try {
                 if (!shouldStopExecution) {
                     const tyad1 = '#EXTINF\\s*?:\\s*?'
                       , tyad2 = '#EXT-X-DISCONTINUITY'
                       , tyad3 = tyad2 + hhzz
                       , tyada = bhhzz + '+?\\.(?:' + ggzlhx + ')' + hhzz + '+'
                       , tyadb = tyad1 + '\\d+(?:\\.\\d+)?\\s*?,' + hhzz + '+?'
                       , tyadc = tyad3 + '+'
                       , tyadd = tyadc + '?' + tyadb
                       , tyade = tyada + '?[\\s\\S]*?' + tyadc
                       , tyadf = '(?<=#EXT-X-TARGETDURATION\\s*?:\\s*?'
                       , tyadg = ')(?:\\.0{1,})?\\s*?,'
                       , tyadh = '(?:#EXT-X-[^:]+?:\\s*?'
                       , tyad100 = ggsjgg + tyadg
                       , tyad101 = hhzz + '+?' + tyadh + bhhzz
                       , tyad102 = tyad1 + '(?:' + tyad100 + hhzz
                       , tyad103 = tyad101 + '+?' + hhzz
                       , tyad104 = '#EXTINF:\\d+?(?:\\.\\d+?)?,'
                       , tyad105 = 'https?:\\\/\\\/'
                       , tyad106 = '+?\\\/\\d+?_\\w{1,10}\\.ts'
                       , tyad107 = /^\s*#EXTM3U/i
                       , tyad108 = '[a-z\\d]{10,}0{2}\\d+?\\.'
                       , tyad109 = '(?:(?=#EXT-X-ENDLIST)|' + tyad2 + hhzz + ')'
                       , tyad1010 = '^\\s*?#EXTM3U\\s*?'
                       , itemspdgza = '(?:' + tyad104 + hhzz + '+?[a-z\\d]{10,}0{2}\\d+?\\.(?:' + ggzlhx + ')' + hhzz + '+?){5,}'
                       , itemstygza = '(?<=(?:' + tyad104 + hhzz + '+?' + tyad108 + '(?:' + ggzlhx + ')' + hhzz + '+?){1,})' + tyad2 + hhzz + '+?(?:' + tyad104 + hhzz + '+?(?!' + tyad108 + '(?:' + ggzlhx + '))' + bhhzz + '+?\\.(?:' + ggzlhx + ')' + hhzz + '+?){1,}' + tyad109
                       , itemsPaichu = [new RegExp(tyad1010 + hhzz + '+?(?![\\S\\s]*?(?:' + tyad104 + hhzz + '+?[a-z\\d]{10,}0{2}\\d+?\\.(?:' + ggzlhx + ')' + hhzz + '+?){2,})[\\S\\s]*?' + tyad2 + hhzz + '+?(?:' + tyad104 + hhzz + '+?(?:[a-z]+?\\d+?|\\d+?[a-z]+?){10,}\\.(?:' + ggzlhx + ')' + hhzz + '+?){2,}','i')]
                       , itemsHandle = [{
                         reUrl: wzm3u8,
                         reAds: [new RegExp('(?<=' + tyad104 + hhzz + '+?' + bhhzz + '+?' + hhzz + '+?)' + tyad2 + hhzz + '+?(?:#EXTINF:\\d+?\\.([1-9])\\1\\d+?\\s*?,' + hhzz + '+?' + bhhzz + '+?' + hhzz + '+?){1,}' + tyad2 + hhzz + '+?','gmi'), new RegExp(itemstygza,'gmi'), new RegExp('(?<=' + tyad104 + hhzz + '+?' + tyad105 + bhhzz + tyad106 + hhzz + '+?(?:' + tyad2 + '' + hhzz + '+?){0,})' + tyad2 + '' + hhzz + '+?(?:' + tyad104 + hhzz + tyad105 + bhhzz + '+?\\\/\\w{50,}\\.ts' + hhzz + '+?){1,}' + tyad2 + '' + hhzz + '+?(?=' + tyad104 + hhzz + '+?' + tyad105 + bhhzz + tyad106 + hhzz + ')','gmi'), new RegExp(tyadf + '(?:' + tyad100 + '?' + bhhzz + '+?' + tyad103 + '+?){0,})' + tyad102 + '+?' + bhhzz + '+?-' + bhhzz + '+?\\d\\.(?:' + ggzlhx + ')' + hhzz + '+(?=' + tyad1 + ')','gmi'), new RegExp(tyadf + bhhzz + '+?' + tyad103 + '+){0,})(?:' + tyad3 + '+?)?' + tyad102 + '+?[a-z\\d]+?0{4,}\\.(?:' + ggzlhx + ')' + hhzz + '+[\\s\\S]+?' + hhzz + '+[a-z\\d]+?0{2,}\\d\\.(?:' + ggzlhx + ')' + hhzz + '+?(?<![\\s\\S]+?10\\.(?:' + ggzlhx + ')\\n*?[\\s\\S]*?' + hhzz + '+)(?=(?:' + tyad3 + '+|' + tyad1 + '\\d+(?:\\.\\d+)?\\s*?,' + hhzz + '+?[a-z\\d]+?10\\.(?:' + ggzlhx + ')' + hhzz + '+))','gi'), new RegExp('(?<=' + tyad1010 + hhzz + '+?(?:#EXT-X-' + bhhzz + '+?' + hhzz + '+?){0,}(#EXT-X-KEY\\s*?:\\s*?' + bhhzz + '+?key\\.key' + bhhzz + '+?)' + hhzz + '[\\S\\s]+?' + hhzz + ')' + tyad2 + hhzz + '+?#EXT-X-KEY\\s*?:\\s*?METHOD=NONE' + hhzz + '+?(?:' + tyad104 + hhzz + '+?' + bhhzz + '+?\\.ts' + hhzz + '+?){0,}' + tyad2 + hhzz + '+?\\1' + hhzz + '+','gmi')],
                     }]
                       , itemsHandleby = [{
                         reUrl: /^https?:\/\/m3u\.nikanba\.live\//i,
                         reAds: [new RegExp('(?<=' + tyad2 + ')' + hhzz + '+?#EXTINF:10,' + hhzz + '+?https?:\\\/\\\/' + bhhzz + '+?\\.(?:' + ggzlhx + ')' + hhzz + '+?' + tyad2 + '(?=' + hhzz + ')','gmi'), new RegExp(tyad2 + hhzz + '+?#EXTINF:2,' + hhzz + '+?' + bhhzz + '+?\\.(?:' + ggzlhx + ')' + hhzz + '+?#EXTINF:3,' + hhzz + '+?' + bhhzz + '+?\\.(?:' + ggzlhx + ')' + hhzz + '+?#EXTINF:1,' + hhzz + '+?' + bhhzz + '+?\\.(?:' + ggzlhx + ')' + hhzz + '+?(?:' + tyad104 + hhzz + '+?' + bhhzz + '+?\\.(' + ggzlhx + ')' + hhzz + '+?){0,}' + tyad2 + '' + hhzz + '+','gmi'), ]
                     }];
                     const urlFromArg = arg=>typeof arg === 'string' ? arg : arg instanceof Request ? arg.url : String(arg);
                     const matchM3u = url=>{
                         const matchedItem = itemsHandle.find(item=>item.reUrl.test(url) && !mp4wz.test(url) && !flvwz.test(url) && !tswz.test(url) && !playsharewz.test(url) && !ggbmd.test(url));
                         itemsHandleby.forEach(byItem=>byItem.reUrl.test(url) && byItem.reAds.forEach(newReAd=>matchedItem.reAds.find(ad=>ad.source === newReAd.source && ad.flags === newReAd.flags) || matchedItem.reAds.push(newReAd)));
                         return matchedItem;
                     }
                     ;
                     const deleteAbnormalTs = (text,jxbgza,jxbgzb,jxbgzc,jxbgzd,jxbgze)=>{
                         try {
                             if (!shouldStopExecution) {
                                 if (!tyad107.test(text) || text.length < 122) {
                                     return text;
                                 } else {
                                     if (ggljbmd.test(text)) {
                                         shouldStopExecution = true;
                                         return text;
                                     } else {
                                         if (ggljdmb.test(text)) {
                                             if (!jxbgzd) {
                                                 jxbgzd = /^\s*?(?:[a-z]+?\s*?-\s*?)?\d+?\s*?$/i;
                                             } else if (jxbgzd == '空') {
                                                 jxbgzd = /^\s*?空\s*?$/;
                                             }
                                             try {
                                                 const rgtya = tyad104 + hhzz + '+?'
                                                   , rgtyb = jxbgza + '\\.(?:' + ggzlhx + ')' + hhzz + '+'
                                                   , regex = '(?<=' + rgtya + ')(' + jxbgzb + ')(?=' + rgtyb + ')'
                                                   , regexx = new RegExp(regex,'gi')
                                                   , tsPaths = text.match(new RegExp('(?:(?<=' + tyad104 + hhzz + '+?))?' + bhhzz + '+?(?=\\.(?:' + ggzlhx + ')' + hhzz + '+)','gi'))
                                                   , matches = text.match(regexx)
                                                   , paths = {};
                                                 if (!jxbgze || jxbgze == '空' || (Number.isInteger(Number(jxbgze)) && tsPaths && tsPaths.length < jxbgze)) {
                                                     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=>{
                                                                 /*console.log("排除测试:\n"+p);*/
                                                                 if (!jxbgzd.test(p)) {
                                                                     text = text.replace(new RegExp(rgtya + p + rgtyb,'gi'), (match)=>{
                                                                         try {
                                                                             if (!dypd.test(打印)) {
                                                                                 try {
                                                                                     console.log("%c[江小白-广告资源-已经发现] ✂\n%c对比" + jxbgzc + "的广告正则:\n%c" + regexx + "\n%c已经删除的广告内容:\n%c" + match.replace(new RegExp('(?<=' + hhzz + '+)' + bhhzz + '+?\\.(?:' + ggzlhx + ')','g'), tsLink=>{
                                                                                         if (!tsLink.startsWith('http')) {
                                                                                             if (m3u8gglj) {
                                                                                                 return new URL(tsLink,m3u8gglj).href;
                                                                                             } else {
                                                                                                 return tsLink;
                                                                                             }
                                                                                         } else {
                                                                                             return tsLink;
                                                                                         }
                                                                                     }
                                                                                     ), "border-left:5px solid #A0B;color:#A0B;padding:3px", "color:blue;", "color:red;", "color:blue;", "color:black;");
                                                                                 } catch (e) {
                                                                                     try {
                                                                                         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;");
                                                                                     } catch (e) {}
                                                                                 }
                                                                             }
                                                                         } catch (e) {}
                                                                         try {
                                                                             if (!ggtspd) {
                                                                                 ggtspd = true;
                                                                             }
                                                                         } catch (e) {}
                                                                         return '';
                                                                     }
                                                                     );
                                                                 }
                                                             }
                                                             );
                                                         }
                                                     }
                                                 }
                                             } catch (e) {}
                                             return text;
                                         } else {
                                             return text;
                                         }
                                     }
                                 }
                             } else {
                                 return text;
                             }
                         } catch (e) {
                             return text;
                         }
                     }
                     ;
                     const pruner = (text,item)=>{
                         try {
                             if (!shouldStopExecution) {
                                 if (!tyad107.test(text) || text.length < 122) {
                                     return text;
                                 } else {
                                     if (ggljbmd.test(text)) {
                                         shouldStopExecution = true;
                                         return text;
                                     } else {
                                         if (ggljdmb.test(text)) {
                                             try {
                                                 if (!gggzpd) {
                                                     gggzpd = true;
                                                     try {
                                                         if (!(new RegExp(itemspdgza,'i').test(text) && new RegExp(itemstygza,'i').test(text))) {
                                                             itemsHandle.forEach(item=>{
                                                                 item.reAds = item.reAds.filter(re=>re.source !== itemstygza);
                                                             }
                                                             );
                                                         }
                                                     } catch (e) {}
                                                     if (!/^\s*[0关]?\s*?$/.test(打印)) {
                                                         console.table(itemsPaichu);
                                                         console.table(itemsHandle);
                                                     }
                                                 }
                                             } catch (e) {}
                                             let modifiedText;
                                             try {
                                                 if (itemsPaichu.some(regex=>regex.test(text))) {
                                                     modifiedText = text;
                                                 } else {
                                                     modifiedText = deleteAbnormalTs(text, '[^\\.]+?', '(?:' + bhhzz + '+\\\/|\\b)', '路径');
                                                     try {
                                                         modifiedText = deleteAbnormalTs(modifiedText, '(?:\\d+?|[a-z]+?)', '\\w+?(?:[^\\d]\\d{2})?', '名称');
                                                     } catch (e) {}
                                                     try {
                                                         modifiedText = deleteAbnormalTs(modifiedText, '\\d+?', '\\w+(?=\\d{3})', '名称', '空', 100);
                                                     } 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=>{
                                                         try {
                                                             if (!dypd.test(打印)) {
                                                                 try {
                                                                     console.log("%c[江小白-资源广告-已经发现] ✂\n%c已经生效的广告正则:\n%c" + reAd + "\n%c已经删除的广告内容:\n%c" + match.replace(new RegExp('(?<=' + hhzz + '+)' + bhhzz + '+?\\.(?:' + ggzlhx + ')','g'), tsLink=>{
                                                                         if (!tsLink.startsWith('http')) {
                                                                             if (m3u8gglj) {
                                                                                 return new URL(tsLink,m3u8gglj).href;
                                                                             } else {
                                                                                 return tsLink;
                                                                             }
                                                                         } else {
                                                                             return tsLink;
                                                                         }
                                                                     }
                                                                     ), "border-left:5px solid #A0B;color:#A0B;padding:3px", "color:blue;", "color:red;", "color:blue;", "color:black;");
                                                                 } catch (e) {
                                                                     try {
                                                                         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;");
                                                                     } catch (e) {}
                                                                 }
                                                             }
                                                         } catch (e) {}
                                                     }
                                                     );
                                                     try {
                                                         if (!ggtspd) {
                                                             ggtspd = true;
                                                         }
                                                     } catch (e) {}
                                                 }
                                                 modifiedText = modifiedText.replace(reAd, "");
                                             }
                                             if (modifiedText.length < text.length) {
                                                 return modifiedText;
                                             }
                                             return text;
                                         } else {
                                             return text;
                                         }
                                     }
                                 }
                             } else {
                                 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);
                             }
                             if (!shouldStopExecution) {
                                 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
                                     });
                                 }
                                 ));
                             } else {
                                 return Reflect.apply(target, thisArg, args);
                             }
                         }
                     });
                     self.XMLHttpRequest.prototype.open = new Proxy(self.XMLHttpRequest.prototype.open,{
                         apply: async(target,thisArg,args)=>{
                             try {
                                 if (!shouldStopExecution) {
                                     const urlFromArgBy = urlFromArg(args[1])
                                       , item = matchM3u(urlFromArgBy);
                                     if (ggljbmd.test(urlFromArgBy)) {
                                         shouldStopExecution = true;
                                     } else {
                                         m3u8gglj = urlFromArgBy;
                                         try {
                                             if (wzm3u8.test(m3u8gglj) && !mp4wz.test(m3u8gglj) && !flvwz.test(m3u8gglj) && !tswz.test(m3u8gglj) && !playsharewz.test(m3u8gglj)) {
                                                 m3u8bflj = m3u8gglj;
                                             }
                                         } catch (e) {}
                                     }
                                     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) {}
 }
 )();