// ==UserScript==
// @name M3u8
// @description 在线播放器 和 在线接口 和 野鸡网站 通用过滤 采集资源 插播广告
// @version 20240911
// @author 江小白
// @match https://v.68sou.com/
// @match *://nnyy.in/*/*.html
// @include /\/[pP]lay(?:\/|\?id=\d)/
// @include /(?:lay|ideo).*?\.html/
// @include /^https?:\/\/kimivod.com/vod/323/1-52.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 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, gggzdp, 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|png|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 = tyad1 + '\\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)|' + tyad3 + ')'
, tyad1010 = '^\\s*?#EXTM3U\\s*?'
, tyad1011 = hhzz + '+?' + bhhzz + '+?'
, tyad1012 = tyad1011 + hhzz + '+?'
, tyad1013 = tyad104 + tyad1012 + ')'
, tyad1014 = tyad3 + '+?'
, tyad1015 = tyad104 + hhzz + '+?'
, tyad1016 = '\\.(?:' + ggzlhx + ')' + hhzz + '+?'
, tyad1017 = bhhzz + '+?' + hhzz + '+?'
, tyad1018 = hhzz + '+?' + bhhzz + '+?'
, tyad1019 = tyad1018 + hhzz + '+?'
, tyad1020 = tyad104 + tyad1019
, tyad1021 = '#EXT-X-KEY\\s*?:\\s*?METHOD=NONE'
, tyad1022 = '(?<=' + hhzz + '+)' + bhhzz + '+?\\.(?:' + ggzlhx + ')'
, itemsdpgza = '(?<=' + hhzz + '+)' + tyad3 + '+?' + tyad1 + '(?<!0)(3)\\.\\1(?:((?<!0)\\d)\\2){2,}\\d+?,' + hhzz + '+?' + tyad105 + tyad1017 + '(?:' + tyad104 + hhzz + '+?' + tyad105 + tyad1017 + '){0,}' + tyad109
, itemspdgza = '(?:' + tyad1015 + '[a-z\\d]{10,}0{2}\\d+?' + tyad1016 + '){5,}'
, itemstygza = '(?<=(?:' + tyad1015 + tyad108 + '(?:' + ggzlhx + ')' + hhzz + '+?){1,})' + tyad1014 + '(?:' + tyad1015 + '(?!' + tyad108 + '(?:' + ggzlhx + '))' + tyada + '?){1,}' + tyad109
, itemstygza1 = '(?<=' + tyad1020 + ')' + tyad1014 + tyadb + tyad1017 + tyad1 + '3\\.3{3,}\\s*?,' + hhzz + '+?' + tyad1017 + '(?:' + tyadb + tyad1017 + '){0,}' + tyad1 + '\\d+?\\.3{3,}\\s*?,' + hhzz + '+?' + tyad1017 + tyad109
, itemsPaichu = [/*动态排除指定资源 正规则表达式,以达到智能删除插播广告的效果*/
new RegExp(tyad1010 + hhzz + '+?(?![\\S\\s]*?(?:' + tyad1015 + '[a-z\\d]{10,}0{2}\\d+?' + tyad1016 + '){2,})[\\S\\s]*?' + tyad1014 + '(?:' + tyad1015 + '(?:[a-z]+?\\d+?|\\d+?[a-z]+?){10,}' + tyad1016 + '){2,}','i')]
, itemsHandle = [{
reUrl: wzm3u8,
reAds: [new RegExp(itemsdpgza,'gim'), new RegExp(itemstygza,'gim'), new RegExp(itemstygza1,'gim'), /*动态拼接采集资源 正规则表达式,以达到智能删除插播广告的效果*/
new RegExp('(?<=' + tyad1015 + tyad105 + bhhzz + tyad106 + hhzz + '+?(?:' + tyad3 + '+?){0,})' + tyad3 + '+?(?:' + tyad104 + hhzz + tyad105 + bhhzz + '+?\\\/\\w{50,}\\.ts' + hhzz + '+?){1,}' + tyad3 + '+?(?=' + tyad1015 + tyad105 + bhhzz + tyad106 + hhzz + ')','gim'), new RegExp(tyadf + '(?:' + tyad100 + '?' + bhhzz + '+?' + tyad103 + '+?){0,})' + tyad102 + '+?' + bhhzz + '+?-' + bhhzz + '+?\\d' + tyad1016 + '(?=' + tyad1 + ')','gim'), new RegExp(tyadf + bhhzz + '+?' + tyad103 + '+){0,})(?:' + tyad3 + '+?)?' + tyad102 + '+?[a-z\\d]+?0{4,}' + tyad1016 + '[\\s\\S]+?' + hhzz + '+[a-z\\d]+?0{2,}\\d' + tyad1016 + '(?<![\\s\\S]+?10\\.(?:' + ggzlhx + ')\\n*?[\\s\\S]*?' + hhzz + '+)(?=(?:' + tyad3 + '+|' + tyad1 + '\\d+(?:\\.\\d+)?\\s*?,' + hhzz + '+?[a-z\\d]+?10' + tyad1016 + '))','gi'), ],
}]
, itemsHandleby = [/*播放黑木耳采集资源的时候,额外增加该数组规则,避免其他的误杀*/
{
reUrl: /^https?:\/\/(?:[^\/]+?\.)?(?:hmr|heimuer)/i,
reAds: [new RegExp('(?<=' + hhzz + '+)' + tyad3 + '+?' + tyad1 + '(\\d+?(?:\\.\\d+?)?),' + hhzz + '+?' + tyad105 + tyad1017 + '(?:' + tyad1 + '\\1,' + hhzz + '+?' + tyad105 + tyad1017 + '){1,}' + tyad109,'gim'), ]
}, /*播放华为采集资源的时候,额外增加该数组规则,避免其他资源误杀*/
{
reUrl: /^https?:\/\/(?:[^\/]+?\.)?nikanba/i,
reAds: [new RegExp('(?<=' + tyad2 + ')' + hhzz + '+?' + tyad1 + '10,' + hhzz + '+?' + tyad105 + tyada + '?' + tyad2 + '(?=' + hhzz + ')','gim'), new RegExp(tyad1014 + '' + tyad1 + '2,' + tyad1011 + tyad1016 + '' + tyad1 + '3,' + tyad1011 + tyad1016 + '' + tyad1 + '1,' + tyad1011 + tyad1016 + '(?:' + tyad104 + tyad1011 + '\\.(' + ggzlhx + ')' + hhzz + '+?){0,}' + tyad3 + '+','gim'), ]
}, ];
/*以上是核心代码不懂勿动*/
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 (new RegExp(tyad1022,'i').test(text)) {
if (!new RegExp('\\.(' + ggzlhx + ')\\?','i').test(text)) {
if (new RegExp('\\.(' + ggzlhx + ')' + hhzz,'i').test(text)) {
if (!jxbgzd) {
jxbgzd = /^\s*?(?:[a-z]+?\s*?-\s*?)?\d+?\s*?$/i;
} else if (jxbgzd == '空') {
jxbgzd = /^\s*?空\s*?$/;
}
try {
const rgtya = tyad1015
, rgtyb = jxbgza + tyad1016
, regex = '(?<=' + rgtya + ')(' + jxbgzb + ')(?=' + rgtyb + ')'
, regexx = new RegExp(regex,'gi')
, tsPaths = text.match(new RegExp('(?:(?<=' + tyad1015 + '))?' + bhhzz + '+?(?=' + tyad1016 + ')','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(tyad1022,'gi'), 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 {
try {
if ((!(new RegExp(itemsdpgza,'i').test(text) && ggljdmb.test(text))) && !new RegExp(tyad3 + '+?' + tyad1021,'i').test(text)) {
gggzdp = true;
} else {
try {
itemsHandle.forEach(item=>{
item.reAds = item.reAds.filter(re=>re.source !== itemsdpgza);
}
);
} catch (e) {}
gggzdp = false;
}
} catch (e) {
gggzdp = false;
}
if (ggljdmb.test(text) || !!gggzdp) {
try {
if (!gggzpd) {
gggzpd = true;
try {
if (new RegExp(itemspdgza,'i').test(text) && new RegExp(itemstygza1,'i').test(text)) {
itemsHandle.forEach(item=>{
item.reAds = item.reAds.filter(re=>re.source !== itemstygza1);
}
);
}
} catch (e) {}
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 {
if (new RegExp(tyadb + bhhzz + '+?\\.(?:' + ggzlhx + ')\\?' + tyad1017,'i').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(tyad1022,'gi'), 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) {}
}
)();