Greasy Fork

Greasy Fork is available in English.

优雅的广告拦截脚本

abp规则转换js脚本

当前为 2022-08-19 提交的版本,查看 最新版本

// ==UserScript==
// @name 优雅的广告拦截脚本
// @author 酷安@耗子Sky
// @description abp规则转换js脚本
// @version 3.2
// @match *://*/*
// @grant GM_setValue
// @grant GM_getValue
// @grant GM_registerMenuCommand
// @grant GM_unregisterMenuCommand
// @grant GM_xmlhttpRequest
// @grant GM_addStyle
// @run-at document-start
// @connect code.gitlink.org.cn
// @namespace http://greasyfork.icu/users/452911
// ==/UserScript==

(function () {
  let rules = `
! 没有两个 # 的行和 开头为 ! 的行会忽略
! baidu.com##.ec_wise_ad
!
! :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://code.gitlink.org.cn/damengzhu/banad/raw/branch/main/jiekouAD.txt",
        "https://code.gitlink.org.cn/damengzhu/abpmerge/raw/branch/main/abpmerge.txt",
    ],
    selarray = [],
    welarray = [],
    seloarray = [],
    menuNum = null,
    valKey = "ajs_disabled_domains",
    disas = GM_getValue(valKey, "").split(",");

  function gmMenuMgmt(disabled) {
    let c = seloarray.length;
    if (menuNum) {
      GM_unregisterMenuCommand(menuNum);
    }
    menuNum = GM_registerMenuCommand(
      disabled
        ? "在此网站启用拦截"
        : `在此网站禁用拦截${c > 0 ? ` (${c})` : ""}`,
      gmValuesMgmt.bind(this, !disabled)
    );
  }

  function gmValuesMgmt(add) {
    if (add) {
      if (!disas.includes(location.hostname)) {
        disas.push(location.hostname);
      }
      GM_setValue(valKey, disas.join(","));
      disas = GM_getValue(valKey, "").split(",");
      gmMenuMgmt(true);
    } else {
      if (disas.includes(location.hostname)) {
        disas.splice(disas.indexOf(location.hostname), 1);
      }
      GM_setValue(valKey, disas.join(","));
      disas = GM_getValue(valKey, "").split(",");
      gmMenuMgmt(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 myfun() {
    let styelem = document.createElement("style");
    gmMenuMgmt(disa);

    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, "#@#");
      } else if (rule.indexOf("#@#") == 0) {
        welarray.push(rule.slice(3));
      } else if (rule.indexOf("##") > 0) {
        parseDomains(rule, "##");
      } else if (rule.indexOf("##") == 0) {
        selarray.push(rule.slice(2));
      }
    });

    selarray.forEach((sel) => {
      if (!welarray.includes(sel)) parseFunc(sel);
    });

    gmMenuMgmt(disa);

    document.documentElement.appendChild(styelem);
    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) {
      styelem.textContent = csel.slice(1) + " {display: none !important;};";
      GM_addStyle(styelem.textContent);
    }
  }

  let disa = disas.includes(location.hostname);
  gmMenuMgmt(disa);
  if (disa) return;

  new Promise((resolve) => {
    let count = 0,
      append = (text) => {
        if (text) rules += `\n${text}\n`;
        count++;
        if (count >= ruleUrls.length) resolve();
      };

      ruleUrls.forEach( url => {
        GM_xmlhttpRequest({
            url: url,
            onload: (r) => {
              append(r.responseText);
            },
            onabort: append.bind(this),
            onerror: append.bind(this),
            ontimeout: append.bind(this),
          });
      })
  }).then(myfun.bind(this));
})();