Greasy Fork is available in English.

M3u8

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

// ==UserScript==
// @name M3u8
// @description 在线播放器 和 在线接口 和 野鸡网站 通用过滤 采集资源 插播广告
// @version 20240701
// @author 江小白
// @match *://nnyy.in/*/*.html
// @include /(?:lay|ideo).*?\.html/
// @include /^https?:\/\/(?:movie\.douban\.com\/subject|m\.douban\.com\/movie)\//
// @include /^https?:\/\/.+?(?<!refer(?:rer)?)[&#=\?]https?(?::\/\/|:\\\/\\\/|%3A%2F%2F)/
// @include /\/\d+?kb\/hls\/index\.m3u8|\.m3u8$/
// @exclude /^https?:\/\/(?:[^\/]+?\/){1,}\w+?\?\w*?id=.+?[&#=\?]https?(?::\/\/|:\\\/\\\/|%3A%2F%2F)/
// @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|rb|swf|png|xml|bmp|pac|gif|apk|exe|zip|txt|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 https://greasyfork.org/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$/;
            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]{50,}\.ts)(?:#|\?|\\|&|$|[\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
                      , itemsHandle = [{
                        reUrl: wzm3u8,
                        reAds: [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('(?<=^\\s*?#EXTM3U' + 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 + '+?(?:#EXTINF:\\d+?(?:\\.\\d+?)?,' + hhzz + '+?' + bhhzz + '+?\\.ts' + hhzz + '+?){0,}' + tyad2 + hhzz + '+?\\1' + hhzz + '+','gmi')],
                    }];
                    const urlFromArg = arg=>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)=>{
                        try {
                            if (!/^\s*#EXTM3U/i.test(text) || text.length < 122) {
                                return text;
                            } else {
                                if (ggljbmd.test(text)) {
                                    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 = '#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 (!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) {}
                                                                    }
                                                                }
                                                                try {
                                                                    if (!ggtspd) {
                                                                        ggtspd = true;
                                                                    }
                                                                } catch (e) {}
                                                                return '';
                                                            }
                                                            );
                                                        }
                                                    }
                                                    );
                                                }
                                            }
                                        } catch (e) {}
                                        return text;
                                    } else {
                                        return text;
                                    }
                                }
                            }
                        } catch (e) {
                            return text;
                        }
                    }
                    ;
                    const pruner = (text,item)=>{
                        try {
                            if (!/^\s*#EXTM3U/i.test(text) || text.length < 122) {
                                return text;
                            } else {
                                if (ggljbmd.test(text)) {
                                    return text;
                                } else {
                                    if (ggljdmb.test(text)) {
                                        try {
                                            if (!gggzpd) {
                                                gggzpd = true;
                                                if (!/^\s*[0关]?\s*?$/.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 (!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) {}
                                                        }
                                                    }
                                                }
                                                );
                                                try {
                                                    if (!ggtspd) {
                                                        ggtspd = true;
                                                    }
                                                } catch (e) {}
                                            }
                                            modifiedText = modifiedText.replace(reAd, "");
                                        }
                                        if (modifiedText.length < text.length) {
                                            return modifiedText;
                                        }
                                        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);
                            }
                            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) {
                                    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) {}
}
)();