// ==UserScript== // @name AdBlock Script for WebView // @name:zh-CN 套壳油猴的广告拦截脚本 // @author Lemon399 // @version 2.0 // @description Parse ABP Cosmetic rules to CSS and apply it. // @description:zh-CN 将 ABP 元素隐藏规则转换为 CSS 并且应用 // @require https://greasyfork.org/scripts/452263-extended-css/code/extended-css.js?version=1099366 // @match *://*/* // @run-at document-start // @grant GM_getValue // @grant GM_deleteValue // @grant GM_setValue // @grant GM_registerMenuCommand // @grant GM_unregisterMenuCommand // @grant GM_xmlhttpRequest // @grant GM_addStyle // @namespace https://lemon399-bitbucket-io.vercel.app/ // @source https://gitee.com/lemon399/tampermonkey-cli/tree/master/projects/abp_parse // @connect code.gitlink.org.cn // @copyright GPL-3.0 // @license GPL-3.0 // @downloadURL none // ==/UserScript== (function (tm, ExtendedCss) { "use strict"; function _interopDefaultLegacy(e) { return e && typeof e === "object" && "default" in e ? e : { default: e, }; } var ExtendedCss__default = _interopDefaultLegacy(ExtendedCss); var __assign = function () { __assign = Object.assign || function __assign(t) { for (var s, i = 1, n = arguments.length; i < n; i++) { s = arguments[i]; for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p]; } return t; }; return __assign.apply(this, arguments); }; function __awaiter(thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); } function __generator(thisArg, body) { var _ = { label: 0, sent: function () { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [], }, f, y, t, g; return ( (g = { next: verb(0), throw: verb(1), return: verb(2), }), typeof Symbol === "function" && (g[Symbol.iterator] = function () { return this; }), g ); function verb(n) { return function (v) { return step([n, v]); }; } function step(op) { if (f) throw new TypeError("Generator is already executing."); while (_) try { if ( ((f = 1), y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) ) return t; if (((y = 0), t)) op = [op[0] & 2, t.value]; switch (op[0]) { case 0: case 1: t = op; break; case 4: _.label++; return { value: op[1], done: false, }; case 5: _.label++; y = op[1]; op = [0]; continue; case 7: op = _.ops.pop(); _.trys.pop(); continue; default: if ( !((t = _.trys), (t = t.length > 0 && t[t.length - 1])) && (op[0] === 6 || op[0] === 2) ) { _ = 0; continue; } if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } if (t[2]) _.ops.pop(); _.trys.pop(); continue; } op = body.call(thisArg, _); } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true, }; } } var onlineRules = [ "https://code.gitlink.org.cn/damengzhu/banad/raw/branch/main/jiekouAD.txt", "https://code.gitlink.org.cn/damengzhu/abpmerge/raw/branch/main/abpmerge.txt", ], defaultRules = '\n! \u6CA1\u6709\u4E24\u4E2A # \u7684\u884C\u548C \u5F00\u5934\u4E3A ! \u7684\u884C\u4F1A\u5FFD\u7565\n! baidu.com##.ec_wise_ad\n!\n! :remove() \u4F1A\u7528 js \u79FB\u9664\u5143\u7D20\uFF0C:remove() \u5FC5\u987B\u653E\u5728\u884C\u5C3E\n! baidu.com###ad:remove()\n!\n! \u7531\u4E8E\u8BED\u6CD5\u9650\u5236\uFF0C\u5185\u7F6E\u89C4\u5219\u4E2D\n! \u4E00\u4E2A\u53CD\u659C\u6760\u9700\u8981\u6539\u6210\u4E24\u4E2A\uFF0C\u50CF\u8FD9\u6837 \\\n!\n! \u811A\u672C\u4F1A\u9996\u5148\u5C1D\u8BD5\u4ECE\u4E0A\u9762\u7684\u5730\u5740\u6570\u7EC4\u83B7\u53D6\u89C4\u5219\n! \u83B7\u53D6\u5230\u7684\u89C4\u5219\u5C06\u4F1A\u4E0E\u5185\u7F6E\u89C4\u5219\u5408\u5E76\n! \u6240\u6709\u89C4\u5219\u83B7\u53D6\u5B8C\u6BD5\u4EE5\u540E\u624D\u4F1A\u5E94\u7528\u89C4\u5219\n!\n! \u82E5\u8981\u4FEE\u6539\u5730\u5740\uFF0C\u8BF7\u6CE8\u610F\u540C\u6B65\u4FEE\u6539\u5934\u90E8\u7684 @connect \u7684\u57DF\u540D\n!2.3.1\nvercel.app#?#blockquote:has(.mymoney)\nvercel.app#?#blockquote:-abp-has(.myhoney)\nvercel.app#?#blockquote[-ext-has=".mytony"]\n!2.3.2\nvercel.app#?#blockquote:has-text(\u70E6\u607C)\nvercel.app#?#blockquote:has-text(/\u533A\u5206\\d/)\nvercel.app#?#blockquote:contains(\u6ED1\u5757)\nvercel.app#?#blockquote:-abp-contains(\u7EA2\u65E5)\nvercel.app#?#blockquote[-ext-contains="\u5A92\u4F53"]\n!2.3.3\nvercel.app#?#blockquote:matches-css(background-color: rgb\\(135, 206, 235\\))\nvercel.app#?#blockquote:matches-css(background-color: rgb\\(200, 206, 214\\))\nvercel.app#?#blockquote[-ext-matches-css="background-color: rgb\\(240, 255, 240\\)"]\nvercel.app#?#blockquote:matches-css(background-color: /^rgb\\(255,/)\n!2.3.4\nvercel.app#?#blockquote:matches-css-before(content: \u6211\u662F\u5E7F\u544A\u554A)\nvercel.app#?#blockquote[-ext-matches-css-before="content: \u6211\u662F\u5E7F\u544A\u5462"]\n!2.3.5\nvercel.app#?#blockquote:matches-css-after(content: \u6211\u662F\u5E7F\u544A\u54DF)\nvercel.app#?#blockquote[-ext-matches-css-after="content: \u6211\u662F\u5E7F\u544A\u54E6"]\n!2.3.6\nvercel.app#?#[type=range]:matches-attr("disabled")\nvercel.app#?#[type=range]:matches-attr("min"="5")\nvercel.app#?#[type=range]:matches-attr("max"="/^3/")\n!2.3.9\nvercel.app#?#[src$="up.gif"]:nth-ancestor(2)\n!2.3.10\nvercel.app#?#[src$="up2.gif"]:upward(2)\nvercel.app#?#p > em:upward(.box)\n!2.3.12\nvercel.app#?##close:xpath(../../*[1])\n!2.3.13\nvercel.app#?##remo:remove()\n!2.3.15\nvercel.app#?##not > blockquote:not(:has(.ok))\nvercel.app#?##abpnot > blockquote:not(:-abp-has(.ok))\n!2.3.16\nvercel.app#?##ifnot > blockquote:if-not(.ok)\n!2.2.4\nvercel.app#?#blockquote:has(.yes)\nvercel.app#@?#blockquote:has(.yes)\n!2.2.10\nvercel.app#$##turq { color: turquoise !important }\n!2.2.10@\nvercel.app#$##seag { color: seagreen !important }\nvercel.app#@$##seag { color: seagreen !important }\n!2.2.11\nvercel.app#$?#span:contains(\u771F\u7684\u662F) { display: none!important; }\n!2.2.11@\nvercel.app#$?#span:contains(\u771F\u4E0D\u662F) { display: none!important; }\nvercel.app#@$?#span:contains(\u771F\u4E0D\u662F) { display: none!important; }\n'; const id = "placeholder"; function isObj(o) { return ( typeof o == "object" && (o === null || o === void 0 ? void 0 : o.toString()) === "[object Object]" ); } function runNeed(condition, fn, option, ...args) { let ok = false, sleep = (time) => { return new Promise((r) => setTimeout(r, time)); }, defaultOption = { count: 20, delay: 200, failFn: () => null, }; if (isObj(option)) Object.assign(defaultOption, option); new Promise(async (resolve, reject) => { for (let c = 0; !ok && c < defaultOption.count; c++) { await sleep(defaultOption.delay); ok = condition.call(null, c + 1); } ok ? resolve() : reject(); }).then(fn.bind(null, ...args), defaultOption.failFn); } `BEXT_LAST_CHECK_KEY_${id}`; function getName(path) { var reer = /\/([^\/]+)$/.exec(path); return reer ? reer[1] : null; } function getEtag(header) { var reer = /etag: \"(\w+)\"/.exec(header); return reer ? reer[1] : null; } function getDay(date) { var reer = /\/(\d{1,2}) /.exec(date); return reer ? parseInt(reer[1]) : 0; } function makeRuleBox() { return { black: [], white: [], apply: "", }; } function domainChecker(domains) { var results = [], hasTLD = /\.+?[\w-]+$/, urlSuffix = hasTLD.exec(location.hostname); var invert = false, result = false, mostMatch = { long: 0, result: undefined, }; domains.forEach(function (domain) { if (domain.endsWith(".*") && Array.isArray(urlSuffix)) { domain = domain.replace(".*", urlSuffix[0]); } if (domain.startsWith("~")) { invert = true; domain = domain.slice(1); } else invert = false; result = location.hostname.endsWith(domain); results.push(result !== invert); if (result) { if (domain.length > mostMatch.long) { mostMatch = { long: domain.length, result: result !== invert, }; } } }); return mostMatch.long > 0 ? mostMatch.result : results.includes(true); } function ruleChecker(matches) { var index = matches.findIndex(function (i) { return i !== null; }); if ( index >= 0 && (!matches[index][1] || domainChecker(matches[index][1].split(","))) ) { return [index % 2 == 0, Math.floor(index / 2), matches[index].pop()]; } } function ruleSpliter(rule) { var result = ruleChecker([ rule.match( /^(~?[\w-]+\.([\w-]+|\*)(,~?[\w-]+\.([\w-]+|\*))*)?##([^\s^+].*)/ ), rule.match( /^(~?[\w-]+\.([\w-]+|\*)(,~?[\w-]+\.([\w-]+|\*))*)?#@#([^\s^+].*)/ ), rule.match( /^(~?[\w-]+\.([\w-]+|\*)(,~?[\w-]+\.([\w-]+|\*))*)?#\?#([^\s^+].*)/ ), rule.match( /^(~?[\w-]+\.([\w-]+|\*)(,~?[\w-]+\.([\w-]+|\*))*)?#@\?#([^\s^+].*)/ ), rule.match( /^(~?[\w-]+\.([\w-]+|\*)(,~?[\w-]+\.([\w-]+|\*))*)?#\$#([^\s^+].*)/ ), rule.match( /^(~?[\w-]+\.([\w-]+|\*)(,~?[\w-]+\.([\w-]+|\*))*)?#@\$#([^\s^+].*)/ ), rule.match( /^(~?[\w-]+\.([\w-]+|\*)(,~?[\w-]+\.([\w-]+|\*))*)?#\$\?#([^\s^+].*)/ ), rule.match( /^(~?[\w-]+\.([\w-]+|\*)(,~?[\w-]+\.([\w-]+|\*))*)?#@\$\?#([^\s^+].*)/ ), ]); if (result && result[2]) { return { black: result[0], type: result[1], sel: result[2], }; } } var selectors = makeRuleBox(), extSelectors = makeRuleBox(), styles = makeRuleBox(), extStyles = makeRuleBox(), values = { get black() { var v = tm.GM_getValue("ajs_disabled_domains", ""); return typeof v == "string" ? v : ""; }, set black(v) { v === null ? tm.GM_deleteValue("ajs_disabled_domains") : tm.GM_setValue("ajs_disabled_domains", v); }, get rules() { var v = tm.GM_getValue("ajs_saved_abprules", "{}"); return typeof v == "string" ? JSON.parse(v) : {}; }, set rules(v) { v === null ? tm.GM_deleteValue("ajs_saved_abprules") : tm.GM_setValue("ajs_saved_abprules", JSON.stringify(v)); }, get time() { var v = tm.GM_getValue("ajs_rules_ver", "0/0/0 0:0:0"); return typeof v == "string" ? v : "0/0/0 0:0:0"; }, set time(v) { v === null ? tm.GM_deleteValue("ajs_rules_ver") : tm.GM_setValue("ajs_rules_ver", v); }, get etags() { var v = tm.GM_getValue("ajs_rules_etags", "{}"); return typeof v == "string" ? JSON.parse(v) : {}; }, set etags(v) { v === null ? tm.GM_deleteValue("ajs_rules_etags") : tm.GM_setValue("ajs_rules_etags", JSON.stringify(v)); }, }, data = { disabled: false, updating: false, receivedRules: "", allRules: "", genericStyle: document.createElement("style"), presetCss: " {display: none !important;width: 0 !important;height: 0 !important;} ", supportedCount: 0, appliedCount: 0, }, menus = { disable: { id: undefined, get text() { return data.disabled ? "在此网站启用拦截" : "在此网站禁用拦截"; }, }, update: { id: undefined, get text() { var time = values.time; return data.updating ? "正在更新..." : "\u70B9\u51FB\u66F4\u65B0: ".concat( time.slice(0, 1) === "0" ? "未知时间" : time ); }, }, count: { id: undefined, get text() { return "\u70B9\u51FB\u6E05\u7A7A: " .concat(data.appliedCount, " / ") .concat(data.supportedCount, " / ") .concat(data.allRules.split("\n").length); }, }, }; function gmMenu(name, cb) { if ( typeof tm.GM_registerMenuCommand !== "function" || typeof tm.GM_unregisterMenuCommand !== "function" || window.self !== window.top ) return false; var id = menus[name].id; if (typeof id !== "undefined") { menus[name].id = tm.GM_unregisterMenuCommand(id); } if (typeof cb == "function") { menus[name].id = tm.GM_registerMenuCommand(menus[name].text, cb); } return typeof menus[name].id !== "undefined"; } function promiseXhr(details) { return new Promise(function (resolve, reject) { tm.GM_xmlhttpRequest( __assign( { onload: function (e) { resolve(e); }, onabort: reject.bind(null), onerror: reject.bind(null), ontimeout: reject.bind(null), }, details ) ); }); } function storeRule(name, resp) { var savedRules = values.rules, savedEtags = values.etags; if (resp.responseHeaders) { var etag = getEtag(resp.responseHeaders); if (etag) { savedEtags[name] = etag; values.etags = savedEtags; } } if (resp.responseText) { savedRules[name] = resp.responseText; values.rules = savedRules; } } function fetchRule(url) { var _this = this; var _a; var name = (_a = getName(url)) !== null && _a !== void 0 ? _a : "".concat(url.length, ".").concat(url.slice(-5)); return new Promise(function (resolve, reject) { return __awaiter(_this, void 0, void 0, function () { var headResp, etag, savedEtags, _a, _b; return __generator(this, function (_c) { switch (_c.label) { case 0: if (!name) reject(); return [ 4, promiseXhr({ method: "HEAD", responseType: "text", url: url, }), ]; case 1: headResp = _c.sent(); if (!headResp.responseText) return [3, 2]; storeRule(name, headResp); resolve(); return [3, 5]; case 2: if (!headResp.responseHeaders) return [3, 5]; (etag = getEtag(headResp.responseHeaders)), (savedEtags = values.etags); if (!(etag !== savedEtags[name])) return [3, 4]; _a = storeRule; _b = [name]; return [ 4, promiseXhr({ method: "GET", responseType: "text", url: url, }), ]; case 3: _a.apply(void 0, _b.concat([_c.sent()])); resolve(); return [3, 5]; case 4: reject(); _c.label = 5; case 5: return [2]; } }); }); }); } function fetchRules() { return __awaiter(this, void 0, void 0, function () { var pArray; return __generator(this, function (_a) { switch (_a.label) { case 0: pArray = []; data.updating = true; gmMenu("update", fetchRules); onlineRules.forEach(function (url) { pArray.push(fetchRule(url)); }); return [4, Promise.allSettled(pArray)]; case 1: _a.sent(); values.time = new Date().toLocaleString("zh-CN"); initRules(); return [2]; } }); }); } function performUpdate(force) { if (force) { return fetchRules(); } else { return getDay(values.time) !== new Date().getDate() ? fetchRules() : Promise.resolve(); } } function switchDisabledStat() { var disaList = values.black.split(","), disaResult = disaList.includes(location.hostname); data.disabled = !disaResult; if (data.disabled) { disaList.push(location.hostname); } else { disaList.splice(disaList.indexOf(location.hostname), 1); } values.black = disaList.join(","); gmMenu("disable", switchDisabledStat); } function checkDisableStat() { var disaResult = values.black.split(",").includes(location.hostname); data.disabled = disaResult; gmMenu("disable", switchDisabledStat); return disaResult; } function initRules() { var abpRules = values.rules, abpKeys = Object.keys(abpRules); abpKeys.forEach(function (name) { data.receivedRules += "\n" + abpRules[name] + "\n"; }); data.allRules = defaultRules + data.receivedRules; if (abpKeys.length !== 0) { data.updating = false; gmMenu("update", fetchRules); } return data.receivedRules.length; } function styleApply() { var css = styles.apply + (selectors.apply.length > 0 ? selectors.apply + data.presetCss : ""), ecss = extStyles.apply + (extSelectors.apply.length > 0 ? extSelectors.apply + data.presetCss : ""); if (css.length > 0) { if (typeof tm.GM_addStyle == "function") { tm.GM_addStyle(css); } else { runNeed( function () { return !!document.documentElement; }, function () { data.genericStyle.textContent = css; document.documentElement.appendChild(data.genericStyle); } ); } } if (ecss.length > 0) new ExtendedCss__default.default({ styleSheet: ecss, }).apply(); } function parseRules() { var _this = this; [selectors, extSelectors].forEach(function (obj) { obj.black .filter(function (v) { return !obj.white.includes(v); }) .forEach(function (sel) { obj.apply += "".concat(obj.apply.length == 0 ? "" : ",").concat(sel); data.appliedCount++; }); }); [styles, extStyles].forEach(function (obj) { obj.black .filter(function (v) { return !obj.white.includes(v); }) .forEach(function (sel) { obj.apply += " ".concat(sel); data.appliedCount++; }); }); gmMenu("count", function () { if (confirm("是否清空存储规则 ?")) { values.rules = {}; values.time = "0/0/0 0:0:0"; values.etags = {}; gmMenu("update", performUpdate.bind(_this, true)); } }); styleApply(); } function main() { return __awaiter(this, void 0, void 0, function () { return __generator(this, function (_a) { switch (_a.label) { case 0: if (checkDisableStat()) return [2]; if (!(initRules() === 0)) return [3, 2]; return [4, performUpdate(true)]; case 1: _a.sent(); _a.label = 2; case 2: data.allRules.split("\n").forEach(function (rule) { var ruleObj = ruleSpliter(rule); var arr = ""; if (typeof ruleObj !== "undefined") { arr = ruleObj.black ? "black" : "white"; switch (ruleObj.type) { case 0: selectors[arr].push(ruleObj.sel); break; case 1: extSelectors[arr].push(ruleObj.sel); break; case 2: styles[arr].push(ruleObj.sel); break; case 3: extStyles[arr].push(ruleObj.sel); break; } data.supportedCount++; } }); parseRules(); performUpdate(false); return [2]; } }); }); } main(); })(self, ExtendedCss);