// ==UserScript==
// @name 优雅的广告拦截脚本.轻量版
// @author Lemon399
// @description abp隐藏元素规则转换为css使用以及添加模拟点击功能点击关闭广告按钮
// @version 6.108
// @match *://*/*
// @grant GM_setValue
// @grant GM_getValue
// @grant GM_registerMenuCommand
// @grant GM_unregisterMenuCommand
// @grant GM_xmlhttpRequest
// @grant GM_addStyle
// @grant GM_deleteValue
// @run-at document-start
// @connect slink.ltd
// @namespace https://greasyfork.org/users/452911
// ==/UserScript==
(function () {
let rules = `
! 没有两个 # 的行和 开头为 ! 的行会忽略
! baidu.com##.ec_wise_ad
qq.com##A[dt-eid^='em_item_ad']
//电影天堂
www.dy2018.com##DIV.nfbClose[onclick='closeNoticeFixedBox()']:click()(300, 5, 300)
//飞极速
feijisu20.com,feijisu21.com,feijisu22.com##[style$='!important; background-size: 405px 120px !important;']
www.pianbus.com##P[style$='-10000px !important;']
//阿虚同学
axutongxue.com##body > div[id] > ul[class] > li > A[href^='http'],body > div[id] > ul[class] > li > img.icon
axutongxue.com##BUTTON#btnClose:click()(500, 10, 500)
//禁漫天堂
18comic.org,18comic.vip,jmcomic1.city,jmcomic1.win,jmcomic1.group##.fas.fa-times:click()(1500, 5, 900)
//努努影院
##body.searchon.m-nav-full IMG[src*='png;base64']
##body.searchon.m-nav-full [style$=' !important; background-size: 400px 120px !important;']
##body.searchon.m-nav-full > [id][class][classname]
##body.searchon.m-nav-full A[id][class][href^='http'][target='_blank'][style]
##body.searchon.m-nav-full > [style^='background-image: url("http']
//啵乐
mybl.xyz##DIV.tool_item.disable_ad
mybl.xyz##[style$='width: 100%; position: fixed; left: 0px; bottom: 133px; height: 62px;']
mybl.xyz##[style='display: block; width: 100%; height: 133px;']
mybl.xyz##[style$='; background-size: 400px 133px !important;']
mybl.xyz##body > [id*='_'][class*='_']
mybl.xyz##svg[viewBox][version]
//樱花动漫
##strong > EM[style='display: inline-block;']
dmh8.me,dm88.me##[onclick='this.parentNode.style.display='none';']:click()(700, 5, 800)
m.dmh8.me,dm88.me##[style^='cursor: pointer; position: absolute;']:click()(700, 5, 800)
dmh8.me,dm88.me##IMG[onclick='funclose()'][style^='display:block;width:11px;height:11px;position:absolute;]:click()(700, 5, 800)
dmh8.me,dm88.me##[style^='background-image: url("http'][style*='png"); background-size: ']:click()(700, 5, 800)
//通用
!
! :remove() 会用 js 移除元素,:remove() 必须放在行尾
! baidu.com###ad:remove()
! :click() 会用 js 模拟点击元素,必须放在行尾
! baidu.com###btn:click()
! 上面两个可以带参数,格式
! remove(100, 4, 200)
! 代表 首先延时 100 ms,然后执行 4 次,两次间隔 200 ms
!
! 由于语法限制,一个反斜杠需要改成两个,像这样 \\
!
! 脚本会首先尝试从下面的地址数组获取规则
! 获取到的规则将会与内置规则合并
! 所有规则获取完毕以后才会应用规则
!
! 若要修改地址,请注意同步修改头部的 @connect 的域名
`,
ruleUrls = [
"https://slink.ltd/https://raw.githubusercontent.com/damengzhu/banad/main/jiekouAD.txt",
],
selarray = [],
welarray = [],
seloarray = [],
gmMenuId = [],
disaKey = "ajs_disabled_domains",
rulesKey = "ajs_saved_rules",
updTimeKey = "ajs_rules_ver",
savedRules = GM_getValue(rulesKey, undefined),
disas = GM_getValue(disaKey, "").split(","),
disa = disas.includes(location.hostname),
styelem = document.createElement("style"),
hideCss = " {display: none !important;visibility: hidden; opacity: 0; z-index: -999; width: 0; height: 0; pointer-events: none; position: absolute; left: -9999px; top: -9999px;}";
function gmDisaMenuMgmt(disabled) {
if (gmMenuId[0]) {
GM_unregisterMenuCommand(gmMenuId[0]);
}
gmMenuId[0] = GM_registerMenuCommand(
disabled ? "在此网站启用拦截" : "在此网站禁用拦截",
gmValuesMgmt.bind(this, !disabled)
);
}
function gmUpdMenuMgmt(start) {
if (gmMenuId[1]) {
GM_unregisterMenuCommand(gmMenuId[1]);
}
gmMenuId[1] = GM_registerMenuCommand(
start
? "正在更新..."
: "规则更新于 " + GM_getValue(updTimeKey, "未知时间"),
fetchRules.bind(this, false, gmUpdMenuMgmt.bind(this, false))
);
}
function gmValuesMgmt(add) {
if (add) {
if (!disas.includes(location.hostname)) {
disas.push(location.hostname);
}
GM_setValue(disaKey, disas.join(","));
disas = GM_getValue(disaKey, "").split(",");
gmDisaMenuMgmt(true);
} else {
if (disas.includes(location.hostname)) {
disas.splice(disas.indexOf(location.hostname), 1);
}
GM_setValue(disaKey, disas.join(","));
disas = GM_getValue(disaKey, "").split(",");
gmDisaMenuMgmt(false);
}
}
function execOperation(sel, param, click) {
setTimeout(() => {
for (let c = parseInt(param[1]); c >= 1; --c) {
setTimeout(() => {
document
.querySelectorAll(sel)
.forEach((a) => (click ? a.click() : a.remove()));
}, parseInt(param[2]) * (c - 1));
}
}, parseInt(param[0]));
}
function pushOperation(sel, op, type) {
let tempParamArray = ["0", "1", "0"];
if (sel.split(op)[1].indexOf(",") > 0) {
tempParamArray = sel.split(op)[1].slice(0, -1).split(",");
}
seloarray.push({
sel: sel.split(op)[0],
type: type,
param: tempParamArray,
});
}
function parseFunc(sel) {
if (sel.indexOf(":remove(") > 0) {
pushOperation(sel, ":remove(", 1);
} else if (sel.indexOf(":click(") > 0) {
pushOperation(sel, ":click(", 2);
} else {
seloarray.push({ sel: sel, type: 0 });
}
}
function parseDomains(rule, sep) {
let domains = rule.split(sep)[0].split(","),
selector = rule.split(sep)[1];
domains.forEach((domain) => {
if (domain.slice(0, 1) == "~") {
if (location.hostname.indexOf(domain.slice(1)) >= 0) return;
} else {
if (location.hostname.indexOf(domain) < 0 && domain !== "*") return;
}
if (sep == "#@#") {
welarray.push(selector);
} else {
selarray.push(selector);
}
});
}
function fetchRules(first, callback) {
savedRules = "";
gmUpdMenuMgmt(true);
new Promise((resolve) => {
let count = 0,
append = (text) => {
if (text) savedRules += `\n${text}\n`;
count++;
if (count >= ruleUrls.length) {
GM_setValue(rulesKey, savedRules);
if (first) rules += savedRules;
GM_setValue(updTimeKey, new Date().toLocaleString());
resolve();
}
};
ruleUrls.forEach((url) => {
GM_xmlhttpRequest({
method: "GET",
url: url,
onload: (r) => {
append(r.responseText);
},
onabort: append.bind(this),
onerror: append.bind(this),
ontimeout: append.bind(this),
});
});
}).then(callback);
}
function myfun() {
if (
parseInt(
GM_getValue(updTimeKey, "0/0/0 0:0:0").split(" ")[0].split("/")[2]
) !== new Date().getDate()
) {
fetchRules(false, gmUpdMenuMgmt.bind(this, false));
}
gmUpdMenuMgmt(false);
let availCount = 0;
rules.split("\n").forEach((rule) => {
if (rule.indexOf("!") == 0) {
return;
} else if (rule.indexOf("[") == 0) {
return;
} else if (rule.indexOf("##+js") >= 0) {
return;
} else if (rule.indexOf("##^") >= 0) {
return;
} else if (rule.indexOf("#@#") > 0) {
parseDomains(rule, "#@#");
availCount++;
} else if (rule.indexOf("#@#") == 0) {
welarray.push(rule.slice(3));
availCount++;
} else if (rule.indexOf("##") > 0) {
parseDomains(rule, "##");
availCount++;
} else if (rule.indexOf("##") == 0) {
selarray.push(rule.slice(2));
availCount++;
}
});
gmMenuId[3] = GM_registerMenuCommand(
`有效规则: ${availCount} / ${rules.split("\n").length}`,
() => {
gmMenuId.forEach((i) => GM_unregisterMenuCommand(i));
GM_deleteValue(rulesKey);
GM_deleteValue(disaKey);
GM_deleteValue(updTimeKey);
}
);
selarray.forEach((sel) => {
if (!welarray.includes(sel)) parseFunc(sel);
});
let csel = "";
seloarray.forEach((selo) => {
switch (selo.type) {
case 0:
csel += `,${selo.sel}`;
break;
case 1:
execOperation(selo.sel, selo.param, 0);
break;
case 2:
execOperation(selo.sel, selo.param, 1);
break;
}
});
if (csel.length >= 2) {
let crule = csel.slice(1) + hideCss;
document.documentElement.appendChild(styelem);
styelem.textContent = crule;
GM_addStyle(crule);
gmMenuId[2] = GM_registerMenuCommand(
`应用规则: ${seloarray.length} 选择器: ${
csel.slice(1).split(",").length
}`,
() => {
alert("##" + csel.slice(1).split(",").join("\n##"));
}
);
}
}
gmDisaMenuMgmt(disa);
if (disa) return;
if (typeof savedRules !== "string") {
fetchRules(true, myfun);
} else {
rules += savedRules;
myfun();
}
})();