Greasy Fork

Greasy Fork is available in English.

M3u8

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

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

// ==UserScript==
// @name M3u8
// @description 在线播放器 和 在线接口 和 野鸡网站 通用过滤 采集资源 插播广告
// @version 20240824
// @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\?[^=]+?=[^\/]*?(?:info|llq)|\.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) {}
}
)();