AC-baidu-重定向优化百度搜狗谷歌必应搜索_favicon_双列

1.繞過百度、搜狗、谷歌、好搜搜索結果中的自己的跳轉鏈接,直接訪問原始網頁-反正都能看懂 2.新增自定义网站拦截功能 3添加Favicon显示 4.页面CSS 5.添加计数 6.开关选择以上功能 7.自动翻页功能

您需要先安裝使用者腳本管理器擴展,如 TampermonkeyGreasemonkeyViolentmonkey 之後才能安裝該腳本。

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyViolentmonkey 後才能安裝該腳本。

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyViolentmonkey 後才能安裝該腳本。

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyUserscripts 後才能安裝該腳本。

你需要先安裝一款使用者腳本管理器擴展,比如 Tampermonkey,才能安裝此腳本

您需要先安裝使用者腳本管理器擴充功能後才能安裝該腳本。

(我已經安裝了使用者腳本管理器,讓我安裝!)

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

(我已經安裝了使用者樣式管理器,讓我安裝!)

// ==UserScript==
// @name    AC-baidu-重定向优化百度搜狗谷歌必应搜索_favicon_双列
// @name:en    AC-baidu-google_sogou_bing_RedirectRemove_favicon_adaway_TwoLine
// @name:zh    AC-baidu-重定向优化百度搜狗谷歌必应搜索_favicon_双列
// @name:ja    AC-baidu-重定向最適化Baiduの搜狗のGoogleのBing検索結果のリダイレクト除去+favicon
// @description  1.繞過百度、搜狗、谷歌、好搜搜索結果中的自己的跳轉鏈接,直接訪問原始網頁-反正都能看懂 2.新增自定义网站拦截功能 3添加Favicon显示 4.页面CSS 5.添加计数 6.开关选择以上功能 7.自动翻页功能
// @description:en  1.bypass the redirect link at baidu\sogou\google\haosou; 2.remove ads at baidu; 3.add Favicon for each website; 4.render your own style; 5.counter; 6.Switch to handle all 7.Auto Pager
// @description:ja  1.迂回Baidu、Sogou、Google、Haosou検索検索結果の中の自分の遷移リンク; 2.Baiduの余分な広告を取り除く; 3.コメントを追加; 4.ページのカスタムCSP; 5.カウントを追加; 6.スイッチは以上の機能を選択します; 7.自動ページめくり.
// @icon    https://ae01.alicdn.com/kf/Hac1a58055c5047cdb91349e91aa208d5k.jpg
// @author     idk
// @license    GPL-3.0-only
// @run-at     document-start
// @version    27.17
// @connect    baidu.com
// @connect    google.com
// @connect    google.com.hk
// @connect    google.com.jp
// @connect    bing.com
// @connect    duckduckgo.com
// @connect    dogedoge.com
// @connect    so.com
// @connect    localhost
// @connect    90dao.com
// @connect    *
// @include    *://ipv6.baidu.com/*
// @include    *://www.baidu.com/*
// @include    *://www1.baidu.com/*
// @include    *://m.baidu.com/*
// @include    *://xueshu.baidu.com/s*
// @include    *://www.so.com/s?*
// @include    *://*.bing.com/*
// @include    *://encrypted.google.*/search*
// @include    *://*.google*/search*
// @include    *://scholar.google.com/scholar*
// @include    *://*.google*/webhp*
// @include    *://*duckduckgo.com/*
// @include    *://*.dogedoge.com/*
// @include    *://*.90dao.com/*
// @include    *://*.tujidu.com/*
// @include    *://localhost*/*
// @exclude    *://*.google*/sorry*
// @exclude    https://zhidao.baidu.com/*
// @exclude    https://*.zhidao.baidu.com/*
// @exclude    https://www.baidu.com/img/*
// @exclude    https://lens.google.com/*
// @supportURL  https://ac.tujidu.com/
// @note    2025.07-12-V27.17 修复谷歌单双列样式表问题、优化百度样式表;增加less.js资源,避免jsdelivr异常无法加载
// @note    2025.06-04-V27.15 修复谷歌单列、双列显示问题;修复谷歌使用百度Icon问题
// @note    2025.04-11-V27.14 修复百度灰度测试导致的重定向判定规则失效问题
// @note    2025.03-22-V27.13 修复google更新导致多列问题、修复百度翻页问题
// @note    2025.03-10-V27.12 修复duckduckGO 样式表问题;新增好搜页面双列支持
// @note    2025.03-07-V27.11 fix for less.js issue at high version browser, read html without head tag 
// @note    2025.03-04-V27.10 fix:谷歌百度模式显示效果;Less.js被Q的问题;谷歌第二页脚本问题;
// @note    2025.01-14-V27.09 fix:谷歌样式生效问题、谷歌显示字体问题、必应去广告失效导致的所有数据丢失问题
// @note    2024.11-17-V27.07 fix:谷歌排版问题、谷歌翻页后图片无效问题
// @note    2024.08-26-V27.06 fix:暗黑模式
// @note    2024.08-19-V27.05 fix:拦截功能、被拦截域名问题、和其他脚本兼容的CSS植入问题、优化域名检测逻辑;
// @note    2024.08-16-V27.04 修复:谷歌双列加载缓慢、双列效果优化、单列居中效果优化;bing页面bug修复;暗黑模式引入;编号、下划线功能修复;鸭鸭修复 & 勿忘国耻
// @note    2024.08-09-V27.03 增加字节跳动的Vue地址,避免部分地区打不开lib.baomitu.com导致的脚本无效
// @note    2024.08-06-V27.02 更换域名,解决SNI拦截问题;优化右侧栏显示逻辑-双列以上隐藏
// @note    2024.08-06-V27.01 重构-十周年优化版,优化项:1.重构设置功能,提供更强大的设置功能;2.极大优化页面加载动画效果;3.修复现有页面显示和效果(谷歌[主]、必应)单列、多列;4.兼容ViolentMonkey,兼容Firefox浏览器
// @note    2024.03-05-V26.10 fix: 谷歌白屏的问题;再次支持鸭鸭搜索引擎,鸭鸭三列支持;baidu\Google双列功能
// @note    2023.12-16-V26.07 日常维护;优化各页面加载卡顿的问题,优化搜索引擎显示效果
// @note    2023.06-19-V26.06 修复谷歌显示效果的错位问题等,修复谷歌异常白屏问题
// @note    2022.12-07-V26.04 修复必应错位问题;优化谷歌双列动画问题
// @note    2022.08-23-V26.03 修复因背景图引起的看不清字的问题;修复百度单列错位问题;修复google自定义按钮不可见
// @note    2022.08-23-V26.02 加快代码执行速度;减少动画撕裂;替换CDN的md5库
// @note    2022.08-22-V26.01 因甲癌手术和公司事务停更了2个月,目前补上,推荐更新。 1.修复百度加载缓慢的问题;2.修复谷歌样式加载顺序异常的问题;3.整体优化样式加载时间,更流畅了
// @note    2022.06-18-V25.09 修复可能出现的脚本参数读取失败导致的脚本不执行的异常 & 修复 拦截规则特殊参数的问题 & 更换CDN地址
// @note    2022.06-16-V25.06 优化重定向逻辑,部分网站只需要稍作处理,不用做接口请求了,感谢众多搜索引擎的版本迭代更新
// @note    2022.04-08-V25.05 主要修复Block功能;其次优化样式加载速度-减少撕裂感
// @note    2022.03-07-V25.04 修复谷歌、必应样式问题;修复并优化拦截功能
// @note    2022.01-29-V25.02 修复谷歌、百度、必应的部分样式错位的问题
// @note    2021.12-06-V25.01 修复百度样式偏左 & 修复谷歌样式显示
// @note    2021.10-31-V24.29 fixed Less requirement for faster Load
// @note    2021.10-29-V24.27 移除必应能选择的广告;增加自定义样式less的支持
// @note    2021.09-02-V24.26 修复必应多favicon,修复百度百科问题;修复谷歌一个小问题
// @note    2021.07-16-V24.25 修复一个bug;兼容百度下搜索股票tag;
// @note    2021.06-15-V24.24 更换cdn地址
// @note    2017.05.12 -> 2021.06-15 && V8.6 -> V24.24 各种各样的历史更新记录,从一个版本迭代到另一个版本
// @note    2017.05.12-V8.4 新增:默认屏蔽谷歌的安全搜索功能
// @note    2017.05.05-V8.3 修复include范围太小导致的百度知道的屏蔽问题
// @note    2017.05.04-V8.2 终于修复了百度知道图片替换了文字的这个大BUG; 顺便处理了superapi.zhidao.baidu.com; 新增谷歌搜索结果重定向去除
// @note    2017.05.04-V8.1 终于修复了百度知道图片替换了文字的这个大BUG,顺便处理了superapi.zhidao.baidu.com
// @note    2017.05.04-V8.0 终于修复了百度知道图片替换了文字的这个大BUG,待测试
// @note    2017.03.28-V7.6 修复在ViolentMonkey上的不支持的问题
// @note    2017.03.28-V7.5 尝试修复chrome上的问题
// @note    2017.03.21-V7.4 尝试处理Edge上不支持的问题,结果发现是Edge本身的TamperMonkey支持有问题
// @note    2017.03.19-V7.3 修复打开百度之后再次点击“百度一下”导致的无法更新重定向问题
// @note    2017.03.19-V7.2 未知原因chrome的MutationObserver无法使用了,继续回归以前的DOMNodeInserted
// @note    2017.02.17-V7.0 修复搜狗的搜索结果重定向问题+改个名字
// @note    2017.02.17-V6.9 修复搜狗的搜索结果重定向问题
// @note    2016.10.27-V6.7 修复了以前的重复请求,现在的请求数应该小了很多,网络也就不卡了,感觉萌萌哒
// @note    2016.04.24-V6.6 恢复以前的版本,因为兼容性问题
// @note    2015.12.01-V5.0 加入搜狗的支持,但是支持不是很好
// @note    2015.11.25-V2.0 优化,已经是真实地址的不再尝试获取
// @note    2015.11.25-V1.0 完成去掉百度重定向的功能
// @resource  baiduCommonStyle   https://ibaidu.tujidu.com/newcss/baiduCommonStyle.less?t=27.14
// @resource  baiduOnePageStyle  https://ibaidu.tujidu.com/newcss/baiduOnePageStyle.less?t=27.14
// @resource  baiduTwoPageStyle  https://ibaidu.tujidu.com/newcss/baiduTwoPageStyle.less?t=27.14
// @resource  googleCommonStyle  https://ibaidu.tujidu.com/newcss/googleCommonStyle.less?t=27.14
// @resource  googleOnePageStyle https://ibaidu.tujidu.com/newcss/googleOnePageStyle.less?t=27.14
// @resource  googleTwoPageStyle https://ibaidu.tujidu.com/newcss/googleTwoPageStyle.less?t=27.14
// @resource  bingCommonStyle    https://ibaidu.tujidu.com/newcss/bingCommonStyle.less?t=27.14
// @resource  bingOnePageStyle   https://ibaidu.tujidu.com/newcss/bingOnePageStyle.less?t=27.14
// @resource  bingTwoPageStyle   https://ibaidu.tujidu.com/newcss/bingTwoPageStyle.less?t=27.14
// @resource  duckCommonStyle    https://ibaidu.tujidu.com/newcss/duckCommonStyle.less?t=27.14
// @resource  duckOnePageStyle   https://ibaidu.tujidu.com/newcss/duckOnePageStyle.less?t=27.14
// @resource  duckTwoPageStyle   https://ibaidu.tujidu.com/newcss/duckTwoPageStyle.less?t=27.14
// @resource  dogeCommonStyle    https://ibaidu.tujidu.com/newcss/dogeCommonStyle.less?t=27.14
// @resource  dogeOnePageStyle   https://ibaidu.tujidu.com/newcss/dogeOnePageStyle.less?t=27.14
// @resource  dogeTwoPageStyle   https://ibaidu.tujidu.com/newcss/dogeTwoPageStyle.less?t=27.14
// @resource  haosouCommonStyle    https://ibaidu.tujidu.com/newcss/haosouCommonStyle.less?t=27.14
// @resource  haosouOnePageStyle   https://ibaidu.tujidu.com/newcss/haosouOnePageStyle.less?t=27.14
// @resource  haosouTwoPageStyle   https://ibaidu.tujidu.com/newcss/haosouTwoPageStyle.less?t=27.14
// @resource  HuYanStyle         https://ibaidu.tujidu.com/newcss/HuYanStyle.less?t=27.14
// @resource  BgAutoFit          https://ibaidu.tujidu.com/newcss/BgAutoFit.less?t=27.14
// @resource  HuaHua-ACDrakMode  https://ibaidu.tujidu.com/newcss/HuaHua-ACDrakMode.less?t=27.14
// @resource  baiduLiteStyle     https://gitcode.net/-/snippets/1906/raw/master/LiteStyle.css?inline=false
// @require   https://unpkg.com/[email protected]/dist/less.min.js
// @require   https://registry.npmmirror.com/less_browser_fix/4.2.2/files/dist/less.min.js
// @require   https://lib.baomitu.com/vue/3.2.31/vue.runtime.global.prod.min.js
// @require   https://lf6-cdn-tos.bytecdntp.com/cdn/expire-10-y/vue/3.2.31/vue.runtime.global.prod.min.js
// @noframes
// @grant    GM_getValue
// @grant    GM.getValue
// @grant    GM_setValue
// @grant    GM.setValue
// @grant    GM_addStyle
// @grant    GM_getResourceURL
// @grant    GM_listValues
// @grant    GM.getResourceUrl
// @grant    GM_xmlhttpRequest
// @grant    GM_getResourceText
// @grant    GM_registerMenuCommand
// @grant    GM_addValueChangeListener
// @grant    unsafeWindow
// @namespace [email protected]
// ==/UserScript==
~(async () => {
    Object.defineProperty(console, 'mylog', {
      value: function() {
        if(CONST && CONST.curConfig) {
          if(CONST.curConfig.isDevMode) {
            const error = new Error();
            const stackTrace = error.stack.split('\n')[2].trim(); // 获取调用栈信息
            try{
              const [targetLink] = /chrome-extension:\/\/(.*)/.exec(stackTrace) // 提取文件名和行号
              const data = [...arguments].join(' ').padEnd(60, ' ')
              console.log(data, `\t\t ${targetLink}`); // 结合自定义输出和调用栈信息
            }catch (e){
              // console.error(error.stack)
              console.log('[log] -', ...arguments); // 如果没有匹配到文件名和行号,则只输出自定义信息
            }
          }
        } else {
          console.log.apply(this, arguments);
        }
      },
    })
    
    const { reactive, watch } = Vue;
    const MyApi = (() => {
      /**
       * @param cssText CSS的内容,如果是less的话,需要编译后的
       * @param className 新增的类名,或者是一堆类名(空格隔开)
       */
      function addStyle(cssText, className = '', dataName){ // 添加CSS代码,不考虑文本载入时间,带有className
        if(className) {
          const selectorName = (' ' + className).split(' ').join('.')
          
          let oldNode = document.querySelector(selectorName)
          if(!oldNode) {
            oldNode = document.createElement("style");
            oldNode.className = className;
            oldNode.dataset.name = dataName
            MyApi.safeFunc(() => {
              document.children[0].appendChild(oldNode);
            })
          }
          oldNode.innerHTML = cssText;
        }
      }
  
      /**
       * 脚本一般来说只需要插入一次的,所以不加入重载功能
       * @param scriptText 新增的脚本的名字
       */
      function addScript(scriptText) {
        const scriptNode = document.createElement('script')
        scriptNode.innerText = scriptText
        document.head.appendChild(scriptNode)
      }
  
      /**
       * 安全脚本执行
       * @param callback 回调函数
       * @param catchCallback 异常的回调函数
       */
      const safeFunc = (callback, catchCallback = () => {}) => {
        try{
          return callback()
        }catch (e){
          console.mylog(e)
          return catchCallback()
        }
      }
  
      const safeGetNodeFunc = (selector, callbackFunc) => {
        const node = document.querySelector(selector)
        if(node) {
          callbackFunc(node)
        }
      }
  
      /**
       * 等待元素后,执行的函数
       * @param selector 选择器 | 选择的函数
       * @param callbackFunc 回调函数
       * @param findTick 查询周期,默认200
       * @param clearAfterFind 查询完成后自动结束?
       * @param timeout 查询超时,超时后停止
       * @param errCallback 查询超时后,回调
       */
      const safeWaitFunc = async(selector, callbackFunc = node => {
      }, findTick = 200, clearAfterFind = true, timeout = 20000 * 1000, errCallback) => {
        if(findTick < 20) findTick = 20
        let count = timeout / findTick
        let t_id = null
        const firstSuccess = await mainRunFunc()
        if (!clearAfterFind || !firstSuccess) {
          t_id = setInterval(mainRunFunc, findTick);
        }
  
        async function strRun() {
          let hasFind = false
          let selectRes = document.querySelectorAll(selector);
          if (selectRes.length <= 0) {
            hasFind = false
          }
          if (selectRes.length >= 1) {
            selectRes = selectRes[0];
            hasFind = true
          }
  
          if (clearAfterFind && hasFind) {
            clearId();
            await callbackFunc(selectRes)
          }
          return hasFind
        }
  
        async function funcRun() {
          let hasFind = false
          const res = selector()
          if (res && res.length > 0) {
            hasFind = true
            if (clearAfterFind && hasFind) clearId();
            await callbackFunc(selector()[0]);
          } else if (res) {
            hasFind = true
            if (clearAfterFind && hasFind) clearId();
            await callbackFunc();
          }
          return hasFind
        }
  
        async function mainRunFunc() {
          if (count-- < 0) {
            clearId()
            errCallback && errCallback()
          }
  
          if ((typeof (selector) == "string")) {
            return await strRun()
          } else if (typeof (selector) === "function") {
            return await funcRun()
          }
        }
  
        function clearId() {
          if (t_id) clearInterval(t_id)
        }
      }
  
      /**
       * 提取URL参数数据
       * @param attribute 参数Key
       * @param needDecode 是否需要解码,默认解码
       * @param baseUrl 默认网址来源
       * @returns {string} 变量结果Value
       */
      function getUrlAttribute(baseUrl = location.href, attribute, needDecode = true){
        const [, search = ''] = baseUrl.split("?");
        var searchValue = search.split("&");
        for (var i = 0; i < searchValue.length; i++) {
          var key_value = searchValue[i].split("=");
          var reg = new RegExp("^"+attribute+"$");
          if (reg.test(key_value[0])) {
            var searchWords = key_value[1];
            return needDecode?decodeURIComponent(searchWords):searchWords;
          }
        }
      }
  
      const http = {
        async get(url) {
          return new Promise((resolve, reject) => {
            const timeout = 10000
            GM_xmlhttpRequest({
              url,
              fetch: true,
              method: 'GET',
              timeout: timeout,
              onload: resp => {
                resolve([null, resp.responseText, resp.responseHeaders])
              },
              onerror: resp => {
                reject([resp, '', {}])
              }
            })
          })
        },
        async post(url, data) {
          return new Promise((resolve, reject) => {
            GM_xmlhttpRequest({
              url,
              data,
              method: 'POST',
              timeout: 10000,
              onload: resp => resolve([null, resp.responseText, resp.responseHeaders]),
              onerror: resp => reject([resp, {}])
            })
          })
        }
      }
  
      /**
       * 等待多久后,重新加载网页
       * @param timeout
       */
      const refreshAfter = () => {
        let id = null
        return (timeout) => {
          clearTimeout(id)
          id = setTimeout(() => {
            location.reload()
          }, timeout)
        }
      }
  
      /**
       * 等待多少ms后执行
       * @param ms 毫秒
       * @returns {Promise<unknown>}
       */
      const waitTime = (ms) => {
        return new Promise(resolve => {
          setTimeout(resolve, ms);
        });
      }
  
      const debounce = (fn, delay) => {
        let timer = null;
  
        return function () {
          clearTimeout(timer);
          timer = setTimeout(() => {
            fn.apply(this, arguments);
          }, delay);
        };
      }
  
      const throttle = (fn, delay) => {
        let timer = null;
        let startTime = Date.now();
  
        return function () {
          const curTime = Date.now();
          const remaining = delay - (curTime - startTime);
  
          clearTimeout(timer);
  
          if (remaining <= 0) {
            fn.apply(this, arguments);
            startTime = Date.now();
          } else {
            timer = setTimeout(() => {
              fn.apply(this, arguments);
              startTime = Date.now();
            }, remaining);
          }
        };
      }
  
      /**
       *
       * @param callback 回调函数
       * @param timeout 定时周期
       * @param mustWaitEnd 必须等待上次执行结束?true = 等待;false=标准Interval
       * @constructor
       */
      const setIntervalRun = (callback, timeout, mustWaitEnd = true) => {
        let isLocked = false
        return setInterval(() => {
          if (mustWaitEnd || !isLocked) {
            isLocked = true
            callback()
            isLocked = false
          }
        }, timeout)
      }
  
      function Reg_Get(HTML, reg) {
        let RegE = new RegExp(reg);
        try {
          return RegE.exec(HTML)[1];
        } catch (e) {
          return "";
        }
      }
      function getElementByXpath(e, t, r = document) {
        t = t || r;
        try {
          return r.evaluate(e, t, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue;
        } catch (t) {
          return void console.error("无效的xpath");
        }
      }
  
      function getAllElementsByXpath(xpath, contextNode, doc = document) {
        contextNode = contextNode || doc;
        const result = [];
  
        try {
          const query = doc.evaluate(xpath, contextNode, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
  
          for (let i = 0; i < query.snapshotLength; i++) {
            const node = query.snapshotItem(i); //if node is an element node
  
            if (node.nodeType === 1) result.push(node);
          }
        } catch (err) {
          throw new Error(`Invalid xpath: ${xpath}`);
        }
        return result;
      }
  
      // 翻页用的获取器
      const getAllElements = (selector, contextNode, doc = document, win = window, _cplink = undefined) => {
        if (!selector) return []; //@ts-ignore
  
        contextNode = contextNode || doc;
  
        if (typeof selector === 'string') {
          if (selector.search(/^css;/i) === 0) {
            return contextNode.querySelectorAll(selector.slice(4))
          } else {
            return getAllElementsByXpath(selector, contextNode, doc);
          }
        } else {
          const query = selector(doc, win, _cplink);
  
          if (!Array.isArray(query)) {
            throw new Error('Wrong type is returned by getAllElements');
          } else {
            return query;
          }
        }
      }
  
      function hideNode(node) {
        if(node.hasAttribute('ac-ad-hide')) return
        node.setAttribute('ac-ad-hide', '1')
        node.style = 'display: none !important;'
      }
  
      function safeRemove_xpath(xpathSelector, useHide) {
        safeFunc(() => {
          let removeNodes = getAllElements(xpathSelector);
          if(useHide) {
            for (let i = 0; i < removeNodes.length; i++){
              hideNode(removeNodes[i])
            }
          } else {
            for (let i = 0; i < removeNodes.length; i++){
              removeNodes[i].remove() // 避免卡顿现象
            }
          }
        })
      }
  
      function safeRemoveAd(selector) {
        [...document.querySelectorAll(selector)].map(one => safeFunc(() => one.remove()))
      }
  
      return {
        addStyle,
        addScript,
        safeFunc,
        safeGetNodeFunc,
        safeWaitFunc,
        getUrlAttribute,
        http,
        refreshAfter: refreshAfter(),
        waitTime,
        debounce,
        throttle,
        setIntervalRun,
        Reg_Get,
        getElementByXpath,
        getAllElementsByXpath,
        getAllElements,
        safeRemoveAd,
        safeRemove_xpath
      }
    })()
    const setHostBind = () => {
      // 避免多个脚本,重复执行
      if (unsafeWindow.isACBaiduInit) {
        throw new Error('已经有脚本在运行了,疑似重复安装')
      } else {
        unsafeWindow.isACBaiduInit = true
      }
      GM_addValueChangeListener('ACBlockRules', (key, oldVal, newVal = '{}', remote) => {
        if (unsafeWindow.webInterface) {
          unsafeWindow.webInterface.update()
        } else {
          CONST.blockRuleList = JSON.parse(newVal) // 将对象设置到CONST上
          CONST.acpush_acremoveInit()
        }
      })
      if(location.host.includes('tujidu.com') || location.host.includes('90dao.com') || location.host.includes('localhost')) {
        unsafeWindow.AC_GM_Interface = {
          async get(key, dataStr) {
            if(key.includes('op_')) {
              const trueKey = tureKeyFix(key)
              const config = JSON.parse(await GM.getValue('ACConfig', '{}'))
              let res = config[trueKey] || JSON.parse(dataStr)
              if(key.includes('common')) {
                res.version = GM_info.script.version
              }
              return res
            } else {
              return JSON.parse(await GM.getValue(key, dataStr))
            }
          },
          async save(key, dataObj) {
            if(key.includes('op_')) {
              const trueKey = tureKeyFix(key)
              const config = JSON.parse(await GM.getValue('ACConfig', '{}'))
              config[trueKey] = dataObj
              GM.setValue('ACConfig', JSON.stringify(config))
              GM.setValue('SyncConfig', JSON.stringify({ refreshUrl: true })) // 触发到Sync上,通过Sync通信
            } else {
              console.log('设置save函数')
              GM.setValue(key, JSON.stringify(dataObj)) // 需要是string了
            }
          },
          async change(key, dataObj) {
            const trueKey = tureKeyFix(key)
            const Sync = JSON.parse(await GM.getValue('ACConfig', '{}'))
            Sync[trueKey] = dataObj
            GM.setValue('SyncConfig', JSON.stringify(Sync)) // 触发到Sync上,通过Sync通信
          },
        }
        
        function tureKeyFix(key) {
          return key.replace(/^op_/, '').replace('duckgo', '')
        }
  
        if(location.host.includes('localhost')) {
          unsafeWindow.isDevMode = true
        }
  
        throw new Error('90dao不需要执行其他函数,抛出异常表示结束')
      }
    }
    
    try{
      setHostBind()
    } catch (e)
    {
      // 不再执行后续函数,停在这里了
      return;
    }
    
    class SiteOptions {
      constructor(_gmInstance) {
        this.gmInstance = _gmInstance
        // 名字自动映射的
        this.siteName = this.gmInstance._getSiteName()
        this.useItem = {
          SiteTypeID: 0,
          MainType: "",
          Stype_Normal: "",
          FaviconType: "",
          FaviconAddTo: "",
          CounterType: "",
          BlockType: "",
          MultiPageType: "",
          pager: {
            nextLink: "",
            pageElement: "",
            HT_insert: ["", 2], // 1 = beforebegin; 2 = beforeend
            replaceE: "",
            stylish: "",
            afertPagerAutoCallFunc: (pageElements, scriptElements) => {} // 执行完脚本后,执行这个函数
          }
        }
  
        if(this['_s_' + this.siteName]) {
          this.useItem = Object.assign({
            pageNum: 1, // 页码
            pageUrl: '', // 下一页的地址
          }, this['_s_' + this.siteName]())
        } else {
          this.siteName = ''
        }
  
        // 作为静态参数用
        this.baidu = this._s_baidu()
        this.google = this._s_google()
        this.bing = this._s_bing()
        this.haosou = this._s_haosou()
        this.duck = this._s_duck()
        this.baidu_xueshu = this._s_baidu_xueshu()
        this.google_scholar = this._s_google_scholar()
      }
  
      _s_baidu() {
        if (this.useItem.SiteTypeID === 1) {
          if(location.href.search(/(&|\?)(wd|word)=/) < 0) {
            console.mylog('禁用CSS的')
            this.gmInstance.curConfig.enableCSS = false
          }
        }
  
        return {
          SiteTypeID: 1,
          MainType: "#content_left>.c-container",
          Stype_Normal: "h3.t>a, .c-container article a",
          FaviconType: "h3 a",
          FaviconAddTo: "h3",
          CounterType: "#content_left>#double>div[srcid] *[class~=t]>a:first-child,[class~=op_best_answer_question],#content_left>div[srcid] *[class~=t]>a:first-child,[class~=op_best_answer_question]",
          BlockType: "h3 a",
          MultiPageType: "#container #content_left, body[news] #container #content_left>div:not([class]):not([id])",
          pager: {
            nextLink: '//div[@id="page"]//a[contains(span/text(), "下一页")]',
            pageElement: "css;div#content_left > *",
            HT_insert: ["css;div#content_left", 2], // 1 = beforebegin; 2 = beforeend
            replaceE: "css;#page",
            stylish: ".autopagerize_page_info, div.sp-separator {margin-bottom: 10px !important;}.c-img-border{display:none}",
          }
        }
      }
  
      _s_bing() {
        // 图片站 、地图站、购物站
        if(this.useItem.SiteTypeID === 5) {
          if (location.href.search(/images\/search/) > 0) {
            console.mylog("特殊站,不加载样式,不添加menu");
            this.gmInstance.curConfig.enableCSS = false
          } else if(location.href.search(/search/) > 0) {
            this.gmInstance.curConfig.enableCSS = true // 仅在搜索结果页,展示背景图即可
          } else {
            this.gmInstance.curConfig.enableCSS = false
          }
        }
  
        return {
          SiteTypeID: 5,
          MainType: "#b_results>li",
          Stype_Normal: "h2>a",
          FaviconType: ".b_attribution>cite",
          FaviconAddTo: "h2",
          CounterType: "#b_results>li[class~=b_ans] h2,#b_results>li[class~=b_algo] h2",
          BlockType: "h2 a",
          MultiPageType: "#b_content #b_results",
          pager: {
            nextLink: "//a[contains(@class,\"sb_pagN\")]",
            pageElement: "id(\"b_results\")/li[not(contains(@class,\"b_pag\") or contains(@class,\"b_ans b_top\"))]",
            HT_insert: ["id(\"b_results\")/li[@class=\"b_pag\"]", 1], // 1 = beforebegin; 2 = beforeend
            replaceE: "id(\"b_results\")//nav[@role=\"navigation\"]",
          }
        }
      }
  
      _s_google() {
        // 图片站 、地图站、购物站
        if (this.useItem.SiteTypeID === 4) {
          if(location.href.search(/tbm=(isch|lcl|shop|flm)/) > 0) {
            console.mylog("特殊站,不加载样式,不添加menu");
            this.gmInstance.curConfig.enableCSS = false
          }
        }
  
        return {
          SiteTypeID: 4,
          MainType: "#rso .vt6azd, div[data-micp-id='rso'] .vt6azd",
          FaviconType: ".zReHs",
          FaviconAddTo: "h3",
          CounterType: "#rso .vt6azd h3:not(table h3),._yE>div[class~=_kk] h3",
          BlockType: ".vt6azd h3", // 修复block翻页的问题
          MultiPageType: ".srg, #rso, div[two-father], #rso>div:not(.vt6azd), #kp-wp-tab-overview",
          pager: {
            nextLink: "id('pnnext')|id('navbar navcnt nav')//td[span]/following-sibling::td[1]/a|id('nn')/parent::a",
            pageElement: "id('rso')|id('center_col')/style[contains(.,'relative')][id('rso')]",
            HT_insert: ["css;#res", 2], // 1 = beforebegin; 2 = beforeend
            replaceE: '//div[@id="navcnt"] | //div[@id="rcnt"]//div[@role="navigation"]',
            afertPagerAutoCall: (pageElements, scriptElements) => {
              // 插入scripts & style - 保证js加载
              scriptElements.forEach((one) => {
                const newScript = document.createElement('script')
                newScript.textContent = one.textContent // 新建一个脚本,否则可能因为不执行导致失败
                newScript.type = one.type
                newScript.nonce = one.nonce
                try{
                  toElement.appendChild(newScript)
                }catch (e){}
              })
            } // 执行完脚本后,执行这个函数
          }
        }
      }
  
      _s_haosou() {
        if (this.useItem.SiteTypeID === 3) {}
        return {
          SiteTypeID: 3,
          MainType: ".res-list",
          Stype_Normal: "h3>a",
          FaviconType: "cite",
          FaviconAddTo: "h3",
          CounterType: ".results>div",
          BlockType: "h3 a",
          // TODO 增加这个
          MultiPageType: ".result li", // 多列模式下,待选择的元素,未来再说
          pager: {
            nextLink: "//div[@id='page']//a[text()='下一页>'] | id('snext')",
            pageElement: "//div[@id='container']/div[@id='main']/ul[@class='result']/li",
            HT_insert: ["//div[@id='container']//ul[@class='result']", 2], // 1 = beforebegin; 2 = beforeend
            replaceE: "id('page')",
            afertPagerAutoCallFunc: (pageElements, scriptElements) => {
              So.web.lazyLoad.init() // 加载好搜图片的
            } // 执行完脚本后,执行这个函数
          }
        }
      }
  
      _s_duck() {
        if (this.useItem.SiteTypeID === 10){}
        return {
          SiteTypeID: 10,
          MainType: "#react-layout li",
          FaviconType: ".nrn-react-div .result__url__domain",
          FaviconAddTo: "h2",
          CounterType: "#react-layout li h2 a",
          BlockType: "h2 a",
          MultiPageType: "#react-layout .react-results--main",
          pager: {
            nextLink: "//a[contains(@class,\"sb_pagN\")]",
            pageElement: "id(\"b_results\")/li[not(contains(@class,\"b_pag\") or contains(@class,\"b_ans b_top\"))]",
            HT_insert: ["id(\"b_results\")/li[@class=\"b_pag\"]", 1], // 1 = beforebegin; 2 = beforeend
            replaceE: "id(\"b_results\")//nav[@role=\"navigation\"]",
          }
        }
      }
  
      _s_baidu_xueshu() {
        if (this.useItem.SiteTypeID === 8) {
          console.warn('启动百度学术特殊设置')
          this.gmInstance.curConfig.adsStyleMode = 2
        }
  
        return {
          SiteTypeID: 8,
          MainType: "#content_left .result",
          Stype_Normal: "h3.t>a, #results .c-container>.c-blocka",
          FaviconType: "h3",
          FaviconAddTo: "h3",
          CounterType: "#content_left>#double>div[srcid] *[class~=t]>a,[class~=op_best_answer_question],#content_left>div[srcid] *[class~=t]>a,[class~=op_best_answer_question]",
          BlockType: "h3 a",
        }
      }
  
      _s_google_scholar() {
        if (this.useItem.SiteTypeID === 4.1) {}
  
        return {
          SiteTypeID: 4.1,
          MainType: "#rso .g, div[data-micp-id='rso'] .g",
          FaviconType: ".iUh30",
          FaviconAddTo: "h3",
          CounterType: "#rso .g h3:not(table h3),._yE>div[class~=_kk] h3",
          BlockType: "a:not([href*='translate.google.com'])", // 修复block翻页的问题
          pager: {
            nextLink: '//a[./span[@class="gs_ico gs_ico_nav_next"]]',
            pageElement: '//div[@class="gs_r gs_or gs_scl"]',
            HT_insert: null, // 1 = beforebegin; 2 = beforeend
            replaceE: '//div[@id="navcnt"] | //div[@id="rcnt"]//div[@role="navigation"]',
          }
        }
      }
    }
    class BaseConfig {
      constructor(isEngine = true) {
        this.commonStyleEnable = true // 是否开启默认效果优化
        this.commonStyleLink = ''
        this.commonStyleLess = ''
  
        // 搜索引擎的逻辑
        if(isEngine) {
          this.adsStyleEnable = true // 是否开启默认效果优化
          this.adsStyleMode = '3' // 0-不带css;1-单列靠左;2-单列居中;3-双列居中
          this.HuYanMode = false // 护眼模式
          this.HuYanMode_Color = '#ffffff' // 护眼模式-颜色
  
          this.BgEnable = false // 背景图-是否启用
          this.BgUseUrl = '' // 默认背景图
          this.BgFit = true // 背景图-是否适应
          this.BgBase64Image = '' // 这个KEY暂时不使用
  
          this.customStyleEnable = false
          this.customStyleLink = ''
          this.customStyleLess = ''
        }
      }
    }
    class CSSAutoInsert {
      constructor() {
        this.hasChanged = false
        this.cssInsertSet = {}
  
        MyApi.setIntervalRun(()=> {
          if(this.hasChanged) {
            this.hasChanged = false
            this.doInsert()
          }
        }, 50)
      }
  
      add(uniqueName, cssText) {
        uniqueName = 'AC-' + uniqueName // 加上特殊前缀,标志关键词
        
        // 如果有,并且数据还一模一样,那么跳过;如果数据不一样,那么覆盖
        if (this.cssInsertSet[uniqueName] && this.cssInsertSet[uniqueName] === cssText) {
          return
        }
        console.mylog('--->插入样式表:' + uniqueName)
        this.cssInsertSet[uniqueName] = `\n/************${uniqueName}*********/\n` + cssText
        this.hasChanged = true
      }
      remove(uniqueName) {
        uniqueName = 'AC-' + uniqueName // 加上特殊前缀,标志关键词
        if (this.cssInsertSet[uniqueName]) {
          console.mylog('--->移除样式表:' + uniqueName)
          delete this.cssInsertSet[uniqueName]
          this.hasChanged = true
        }
      }
  
      clear() {
        this.cssInsertSet = {}
        this.hasChanged = true
      }
  
      doInsert() {
        const cssText = Object.values(this.cssInsertSet).join('\n')
        MyApi.addStyle(cssText, 'AC-CSSAutoInsertBase', Object.keys(this.cssInsertSet).join(' ')) // 方便排查css插入
        console.mylog('插入CSS完成')
      }
    }
    class ACGM {
      constructor() {      
        this.initGM()
        this.bindGM()
      }
  
      async initACGM() {
        
        let ACConfig = {}
        this.blockRuleList = []
        const DefaultConfig = {
          common: {
            version: '', // 从代码中动态拉取,丢弃任何值
            isDevMode: false, // 是否为调试模式,从页面给出来的
            isLocalDevMode: false, // 是否为本地调试模式,从页面给出来的,用于加载本地CSS
            localDebugBaseUrl: '', // 本地调试模式,本地CSS的入口地址
            isRedirectEnable: false, // 是否开启重定向功能
            isAdsEnable: false, // 是否开启去广告模式
            isFaviconEnable: true, // 是否开启Favicon图标
            isAutopage: true, // 是否开启自动翻页功能
  
            isBlockEnable: true, // 是否开启去拦截模式
            isBlockResultDisplay: true, // 是否删除已拦截的条目
            isBlockBtnDisplay: false, // 是否显示block按钮
  
            isRightDisplayEnable: true, // 是否开启右侧边栏
            isCounterEnable: false, // 是否显示计数器
            isALineDisable: false, // 是否禁止下划线
            isDarkModeEnable: false, // 是否加载暗黑模式
  
            ...new BaseConfig(false)
          },
          baidu: {
            doRemoveSug: true, // 删除移动预测
            doRemoveAIGen: false, // 移除百度AI搜索结果
            baiduLiteEnable: false, // 启用百度Lite样式表
            ...new BaseConfig()
          },
          google: {
            useBaiduLogo: false, // 默认不使用百度logo
            ...new BaseConfig()
          },
          bing: {
            optimizeBing: true,
            ...new BaseConfig()
          },
          duck: {
            optimizeDuck: true, // 是否开启优化
            ...new BaseConfig()
          },
          haosou: {
            ...new BaseConfig(false)
          }
        };
        try {
          let res = await GM.getValue("ACConfig", "{}")
          ACConfig = JSON.parse(res);
  
          res = await GM.getValue("ACBlockRules", "[]")
          this.blockRuleList = JSON.parse(res);
          this.acpush_acremoveInit()
        } catch (e) {
          console.error('出bug了')
          ACConfig = DefaultConfig
        }
        // 随便给一个值初始化,这个值,只是临时的值,如果需要写入,也是从另一端拉取,不是这个值来覆盖的
        this.curConfig = {
          ...DefaultConfig.common,
          ...DefaultConfig.baidu
        }
        this.sortIndex = 1
        this.bingScrollPos = 0
        this.ACConfig = Object.assign({}, DefaultConfig, ACConfig) // 作为临时修改用
        // this.enableCSS = true
        this.cssAutoInsert = new CSSAutoInsert()
        this.cssFavionList = reactive({
          list: []
        })
  
        this.adsCSSList = {
          baiduLiteStyle: '',
  
          leftCommonStyle: '',
          onePageStyle: '',
          twoPageStyle: '',
          multiPageStyle: '',
          expandPageStyle: '',
  
          customStyle: '', // 自定义样式表
          commonStyle: '', // 全局样式表
  
          huyanStyle: '',
          bgAutoFitStyle: '',
          darkModeStyle: '', // 暗黑护眼色
          
          faviconStyle: '', // 动态插入的favicon的数据
        }
  
        this.lock = {
          bodyLocked: true,
          headLocked: true,
          pageLoadingLocked: false,
          isBlockChecking: false,
          afterBlockChangeChecked: true, // 数据刷新后,是否检查过了,用于减少reg判定
        }
        // 数据先初始化
        this.curConfig = reactive({
          enableCSS: true,
          ...this.ACConfig.common,
          ...this.ACConfig[this._getSiteName()]
        })
        // 再得到真实options,并调整config
        this.options = new SiteOptions(this)
        await this.loadSiteCSS()
        this.waitBodyHead()
        this.openSeetingsUrl = ''
        this.check90daoConn()
      }
  
      initGM() {
        if (typeof (GM) === "undefined") {
          // 这个是ViolentMonkey的支持选项
          GM = {};
          GM.setValue = GM_setValue;
          GM.getValue = GM_getValue;
        }
        if (typeof GM_getResourceText === 'undefined') {
          GM_getResourceText = async function(aResourceName) {
            // 如果没有这个接口,那就是没办法缓存这个数据,所以只能用本地的数据进行缓存了
            let res = await (await fetch(await GM.getResourceUrl(aResourceName))).text();
            let saveRes = await GM.getValue(aResourceName);
            if (typeof (saveRes) === 'undefined') {
              GM.setValue(aResourceName, res);
            } else {
              return saveRes;
            }
            return res;
          }
        }
      }
  
      bindGM() {
        GM_registerMenuCommand('AC-重定向脚本设置', function() {
          window.open(CONST.openSeetingsUrl)
        });
        GM_registerMenuCommand('脚本重置 - 修复脚本', function() {
          GM.setValue('ACConfig', '{}');
          location.reload();
        });
      }
  
      check90daoConn() {
        const storeValue = sessionStorage.getItem('access_90dao')
        this.openSeetingsUrl = storeValue || 'https://ac-baidu.tujidu.com/pages/custom/#' + CONST.options.siteName
        
        if (!storeValue) {
          console.log('不存在自定义配置')
          GM_xmlhttpRequest({
            method: "HEAD",
            timeout: 3000,
            url: "https://ac-baidu.90dao.com/",
            onload: ()=> {
              this.openSeetingsUrl = 'https://ac-baidu.90dao.com/pages/custom/#' + CONST.options.siteName
              sessionStorage.setItem('access_90dao', this.openSeetingsUrl)
            },
            onerror: ()=> {
              this.openSeetingsUrl = 'https://ibaidu.tujidu.com/pages/custom/#' + CONST.options.siteName
              sessionStorage.setItem('access_90dao', this.openSeetingsUrl)
            }
          });
        }
      }
      
      saveConfig() {
        const commonConfig = this.ACConfig['common']
        const siteConfig = this.ACConfig[this.options.siteName]
        for(const key in siteConfig) {
          siteConfig[key] = this.curConfig[key]
        }
        for(const key in commonConfig) {
          commonConfig[key] = this.curConfig[key]
        }
        GM.setValue('ACConfig', JSON.stringify(this.ACConfig));
      }
  
      saveBlockRule() {
        GM.setValue('ACBlockRules', JSON.stringify(this.blockRuleList));
      }
  
      renewConfig(newConfig) {
        const chooseCfg = newConfig[this.options.siteName]
        const commonCfg = newConfig['common']
        if(chooseCfg) {
          Object.assign(this.curConfig, chooseCfg)
        }
        if(commonCfg) {
          Object.assign(this.curConfig, commonCfg)
        }
      }
  
      async loadStyleByName_WithLessCache(styleName) {
        if(CONST.curConfig.isDevMode && CONST.curConfig.isLocalDevMode && CONST.curConfig.localDebugBaseUrl) {
          const renderCSSKeyName = '__AC.RenderCSS__' + styleName
          return await setLocalLessData(renderCSSKeyName, getDebugStyle) // 不带缓存,随时刷新了
          // return await cacheStyle(renderCSSKeyName, getDebugStyle) // 带缓存,随时刷新了
        } else {
          return await cacheStyle(styleName, getRenderStyle)
        }
  
        async function cacheStyle(styleName, getLessDataFunc) {
          const renderCSSKeyName = '__AC.RenderCSS__' + styleName
          const localData = localStorage.getItem(renderCSSKeyName)
          if (localData) {
            setTimeout(() => {
              console.mylog('*****有缓存了,但是在刷新了:' + styleName)
              setLocalLessData(renderCSSKeyName, getLessDataFunc)
            }, 2000)
            return localData
          } else {
            console.mylog('*****没有缓存' + styleName)
            return await setLocalLessData(renderCSSKeyName, getLessDataFunc)
          }
        }
  
        async function setLocalLessData(renderCSSKeyName, getLessDataFunc) {
          const { css = '' } = await less.render(await getLessDataFunc());
          localStorage.setItem(renderCSSKeyName, css)
          return css
        }
  
        async function getDebugStyle() {
          const dataUrl = `${CONST.curConfig.localDebugBaseUrl}${styleName}.less`
          const [err, text] = await MyApi.http.get(dataUrl)
          if(!err) {
            return text
          } else {
            console.error('加载失败', dataUrl)
          }
          return ''
        }
  
        async function getRenderStyle() {
          return GM_getResourceText(styleName)
        }
      }
  
      async loadSiteCSS() {
        console.mylog('CSS加载开始' + +this.curConfig.adsStyleMode)
        // 加载多列
        if (this.curConfig.adsStyleEnable) {
          if (+this.curConfig.adsStyleMode >= 1) {
            this.adsCSSList.leftCommonStyle = await this.loadStyleByName_WithLessCache(this.options.siteName + 'CommonStyle') // 单列效果
          }
          if (+this.curConfig.adsStyleMode >= 2) {
            this.adsCSSList.onePageStyle = await this.loadStyleByName_WithLessCache(this.options.siteName + 'OnePageStyle') // 单列居中
          }
          if (+this.curConfig.adsStyleMode >= 3) {
            this.adsCSSList.twoPageStyle = await this.loadStyleByName_WithLessCache(this.options.siteName + 'TwoPageStyle') // 双列效果
          }
          if (+this.curConfig.adsStyleMode >= 4) {
            this.adsCSSList.multiPageStyle = await this.getMultiPageStyle() // 多列效果
          }
        }
        // 加载百度Lite
        if (this.curConfig.baiduLiteEnable) {
          this.adsCSSList.baiduLiteStyle = await this.loadStyleByName_WithLessCache('baiduLiteStyle')
        }
        // 加载背景图优化
        if (this.curConfig.BgEnable && this.curConfig.BgFit) {
          this.adsCSSList.bgAutoFitStyle = await this.loadStyleByName_WithLessCache('BgAutoFit')
        }
        // 加载护眼样式
        if (this.curConfig.HuYanMode) {
          this.adsCSSList.huyanStyle = await this.getHuyanStyle()
        }
        
        if (this.curConfig.isDarkModeEnable) {
          this.adsCSSList.darkModeStyle = await this.loadStyleByName_WithLessCache('HuaHua-ACDrakMode')
        }
        // 加载自定义样式
        if (this.curConfig.customStyleEnable) {
          console.mylog('触发custom更新')
          const { css = '' } = await less.render(this.curConfig.customStyleLess);
          this.adsCSSList.customStyle = css
        }
        // 加载其他样式
        if (this.curConfig.commonStyleEnable) {
          console.mylog('触发common更新')
          const { css = '' } = await less.render(this.curConfig.commonStyleLess);
          this.adsCSSList.commonStyle = css
        }
        console.mylog('CSS加载结束')
        // 2秒后再加载
        setTimeout(() => {
          this.loadAllStyle()
        }, 2000)
      }
  
      getMultiPageStyle() {
        return this.options.useItem.MultiPageType +
          (+this.curConfig.adsStyleMode === 4 ?
            "{grid-template-columns: repeat(3, 33.3%); grid-template-areas:'xmain xmain xmain';}" :
            "{grid-template-columns: repeat(4, 25%); grid-template-areas:'xmain xmain xmain xmain';}")
      }
  
      async getHuyanStyle() {
        function Lighter(oriRGB, deltaY) {
          function clip255(value) {
            if (value > 255) return 255;
            if (value < 0) return 0;
            return value;
          }
          // 按比例缩放 + 1/deltaY
          // HEX 2 RGB
          let rgb = oriRGB.replace("#", "");
          let R = parseInt("0x" + rgb.substr(0, 2));
          let G = parseInt("0x" + rgb.substr(2, 2));
          let B = parseInt("0x" + rgb.substr(4, 2));
          // RGB 2 YUV
          let Y = ((66 * R + 129 * G + 25 * B + 128) >> 8) + 16;
          let U = ((-38 * R - 74 * G + 112 * B + 128) >> 8) + 128;
          let V = ((112 * R - 94 * G - 18 * B + 128) >> 8) + 128;
          Y = Y * (1 + 1.0 / deltaY);// 提高亮度
          // YUV 2 RGB
          R = clip255((298 * (Y - 16) + 409 * (V - 128) + 128) >> 8);
          G = clip255((298 * (Y - 16) - 100 * (U - 128) - 208 * (V - 128) + 128) >> 8);
          B = clip255((298 * (Y - 16) + 516 * (U - 128) + 128) >> 8);
          return "#" + ((R << 16) + (G << 8) + B).toString(16);
        }
  
        let HuyanStyle = await this.loadStyleByName_WithLessCache('HuYanStyle')
        const huyanColor = this.curConfig.HuYanMode_Color
  
        return HuyanStyle
          .replace(/#aaa(a*)/igm, huyanColor)
          .replace(/#bbb(b*)/igm, Lighter(huyanColor, -40))
          .replace(/#ccc(c*)/igm, Lighter(huyanColor, 45));
      }
  
      async loadAllStyle() {
        if (!this.adsCSSList.leftCommonStyle) this.adsCSSList.leftCommonStyle = await this.loadStyleByName_WithLessCache(this.options.siteName + 'CommonStyle') // 单列效果
        if (!this.adsCSSList.onePageStyle) this.adsCSSList.onePageStyle = await this.loadStyleByName_WithLessCache(this.options.siteName + 'OnePageStyle') // 单列居中
        if (!this.adsCSSList.twoPageStyle) this.adsCSSList.twoPageStyle = await this.loadStyleByName_WithLessCache(this.options.siteName + 'TwoPageStyle') // 双列效果
        if (!this.adsCSSList.baiduLiteStyle) this.adsCSSList.baiduLiteStyle = await this.loadStyleByName_WithLessCache('baiduLiteStyle')
        if (!this.adsCSSList.bgAutoFitStyle) this.adsCSSList.bgAutoFitStyle = await this.loadStyleByName_WithLessCache('BgAutoFit')
        if (!this.adsCSSList.darkModeStyle) this.adsCSSList.darkModeStyle = await this.loadStyleByName_WithLessCache('HuaHua-ACDrakMode')
      }
  
      waitBodyHead() {
        // 永远执行
        MyApi.safeWaitFunc(() => {return document.head}, () => {
          console.mylog('解锁head')
          this.lock.headLocked = false
        })
        MyApi.safeWaitFunc(() => {return document.body}, () => {
          console.mylog('解锁body')
          this.lock.bodyLocked = false
        })
      }
  
      addIntervalTrigger(site = '', waitAt = 'now', callback, interval_time = 0, runTimes = 1) {
        console.mylog('addIntervalTrigger', site, "------------", this.options.siteName)
        if(site !== 'all' && this.options.siteName !== site) return
        
        let count = runTimes
        const intId = MyApi.setIntervalRun(async () => {
          count--
          if(
            !((waitAt === 'now') ||
              (waitAt === 'body' && !this.lock.bodyLocked) ||
              (waitAt === 'head' && !this.lock.headLocked))
          ) {
            return
          }
          if(count >= 0) {
            await callback(count)
          } else {
            clearInterval(intId)
          }
        }, interval_time)
      }
  
      acpush_acremoveInit() {
        function acpush(data = "") {
          this.hasEdit = true
          data = data.trim()
          // 如果是垃圾数据,那么可以丢弃的
          if (!data) return '无效内容';
          // 如果数据中有回车,那数据也是无效的正文而已
          if (data.search(/(,|:|。|\n)/) >= 0) return '格式不符合要求';
          if (this.findIndex(m => m === data) < 0) {
            this.push(data);
            dataChangeCallback()
          } else {
            return "已存在相同项"
          }
        }
        function acremove (data) {
          this.hasEdit = true
          let delId = this.findIndex(m => m === data);
          if (delId >= 0) {
            this.splice(delId, 1);
            dataChangeCallback()
            return delId
          }
          return -1
        }
        function dataChangeCallback() {
          CONST.lock.afterBlockChangeChecked = false
          PageBlockFunc._updateRegListRule()
        }
        Object.defineProperty(CONST.blockRuleList, 'acpush', { value: acpush })
        Object.defineProperty(CONST.blockRuleList, 'acremove', { value: acremove })
      }
  
      _getSiteName() {
        const specialRule = {
          'xueshu.baidu.com': 'baidu_xueshu',
          'scholar.google.com': 'google_scholar',
          'so.com': 'haosou',
        }
        let useRule = Object.keys(specialRule).find(one => location.host.includes(one))
        if(!useRule) {
          useRule = location.host.replace(/.*(baidu|google|bing|duck).*/, '$1')
        } else {
          return specialRule[useRule]
        }
        return useRule
      }
    }
    
    const CONST = new ACGM()
    await CONST.initACGM()
  
    class PageFuncClass {
      constructor() {
        this.removeAds = this.removeAdFunc()
      }
      GoogleInBaiduMode() {
        MyApi.safeGetNodeFunc("#logo img, #logocont img", function(node) {
          let faNode = node.parentNode.parentNode;
          if(faNode.hasAttribute('xchanged')) return
          faNode.classList.add("baidu");
          faNode.setAttribute('xchanged', 1)
          node.removeAttribute("src");
          node.src = "https://www.baidu.com/img/flexible/logo/pc/result.png";
          node.width = "125";
          node.removeAttribute("height");
        });
        MyApi.safeGetNodeFunc("a#logo", function(node) {
          let faNode = node.parentNode.parentNode;
          if(faNode.hasAttribute('xchanged')) return
          faNode.classList.add("baidu");
          faNode.setAttribute('xchanged', 1)
          node.querySelector('svg').style.display = 'none'
          const newImage = document.createElement('img')
          newImage.src = "https://www.baidu.com/img/flexible/logo/pc/result.png"
          newImage.width = "125"
          node.appendChild(newImage)
        });
        MyApi.safeGetNodeFunc("img[alt='Google']", function(node) {
          if(node.hasAttribute('xchanged')) return
          node.setAttribute('xchanged', 1)
          node.removeAttribute("srcset");
          node.src = "https://www.baidu.com/img/flexible/logo/pc/result.png";
          node.style.height = '72px'
          // node.style.marginTop = '-10px'
        });
        MyApi.safeGetNodeFunc("form[role='search'] .logo img", function(node) {
          if(node.hasAttribute('xchanged')) return
          node.setAttribute('xchanged', 1)
          node.removeAttribute("srcset");
          node.src = "https://www.baidu.com/img/flexible/logo/pc/result.png";
          node.setAttribute("height", "30");
          // node.style.marginTop = '-10px'
        });
        if(!document.title.includes('百度')) {
          document.title = document.title.replace(/^Google/, "百度一下,你就知道")
            .replace(/ - Google 搜索/, "_百度搜索")
            .replace(/ - Google Search/, "_百度搜索");
        }
        MyApi.safeGetNodeFunc("head", function() {
          let linkTarget = document.querySelector("link[type='image/x-icon']");
          if(linkTarget && linkTarget.href.includes('baidu')) {
            return
          }
          linkTarget = document.createElement('link')
          linkTarget.type = 'image/x-icon';
          linkTarget.rel = 'shortcut icon';
          linkTarget.href = 'https://www.baidu.com/favicon.ico';
          document.head.appendChild(linkTarget);
          document.querySelector('link[rel="icon"]').href = 'https://www.baidu.com/favicon.ico'
        })
      }
      removeAdFunc() {
        function removeBaiduAd() {
          // 移除右侧栏广告
          MyApi.safeRemove_xpath("id('content_right')/div[.//a[starts-with(text(), '广告')]]");
          // 移除标准广告
          MyApi.safeRemove_xpath("id('content_left')/div[.//span[contains(@class, 'tuiguang') or contains(@class, 'brand')][contains(text(), '广告')]]");
          // 移除标准广告 - 新
          MyApi.safeRemove_xpath("id('content_left')/div[.//a[text()='广告']]");
          // 移除右侧栏顶部-底部无用广告
          MyApi.safeRemove_xpath("id('content_right')/br");
          MyApi.safeRemove_xpath("id('content_right')/div[not(@id)]");
          // 移除顶部可能出现的 "为您推荐"
          MyApi.safeRemove_xpath("id('content_left')//div[contains(@class, '_rs')]");
  
          /****移除Mobile模式上的部分广告****/
          MyApi.safeRemove_xpath("id('page-bd')/div[not(contains(@class, 'result'))]");
          MyApi.safeRemove_xpath("id('page-bd')/div[not(@class)]");
          MyApi.safeRemove_xpath("//div[@class='na-like-container']");
        }
        function removeGoogleAd() {
          MyApi.safeRemoveAd("#bottomads");
          MyApi.safeRemoveAd('div[aria-label="广告"]');
          MyApi.safeRemoveAd('div[aria-label="Ads"]');
        }
        function removeBingAd() {
          MyApi.safeRemoveAd(".b_ad");
          MyApi.safeRemove_xpath("id('b_results')/li[./div[@class='ad_fls']]");
  
          // 移除特殊tag,带url标记的广告类 -- 新版的bing似乎比较特殊,无法判定了
          const resList = [...document.querySelectorAll("ol>li")].filter(one => one.querySelector('p')) // 定位到所有包含p标签的li
          const removeWith = [
            'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADoAAAALCAYAAAAunZ4gAAAAAXNSR0IArs4c6QAAAl5JREFUSEvlVrtuE0EUPXdW8lqWgA8A8QHJByBBTZDShiiUSMmu3FhRSB9IPgAKd7t2T2SgjAw9rz5AD/kBQLLWtnYOuquZ1cTYMpQGV+ur2fs459wzK/hPfuLnTJJkS0ReBHOfZln2YJVw6HQ6V4uiOAPwLM/zl2Hv1aDtdvu6tfYdyUd6IPjfz/P8ZFWGXTpomqa3RGRAcjvLso/hYDo0ySHJ1wAOAXwHcE/P+cQicsfH4zj+MplMzkheANjRXCTvK4BaB4DmuRbm8cACuAngqzHmtntP634DsK4xkrskj11/teLSNH2utUTknKTWezKXUX0xSZIjEamSkHzsmQyaeK9S1nMANprN5uZ4PM70vIur9J8qCCR7InIx7zzJz5rb1VuL4zh1cnvj45pfRPYUFJKVqnS1ABxoXa3pJarPWleBsNbecO/sLhzUsxiiq0xEUfTBMbqnLDr2e8q+iPSstdU+eOZFZJ/kibXWN75ljDloNBqbRVHcdT5QqyJQzKX8xpiHZVm+8usUEhH6iH9WUJdKd94OesSNMYfW2iGAuhEAPQDbypxffAfQ0BizX5al7nU9qGei2+3+CNVD8q1jbjCbP4qieYOuzRqkk22lqqWDOsft+93zzRhjVBZ9Z1ReQkfGmA1laJF0HdO/MarnSQ5UAVpTmW61Wjuj0eg0UECVn6SXbmWQYY/eBxRMa+2nv5Kul4Yus0hlxtWyBw78U0TW/8SMZnau3q3pdHpFQXOmc0m+Qbw2o/Am8OADOA7707g3IwDnzmMWm9GiK2T26lmVq2a2z/qD4V8f9BciyTQqHtmLjAAAAABJRU5ErkJggg==',
            // ''
          ]
          const adList = resList.filter(one => {
            const url = window.getComputedStyle(one.querySelector('p'), '::before').getPropertyValue('content')
            return removeWith.some(remove => url.includes(remove))
          }) // 检查每一个p标签,里面存在before伪元素,且伪元素中是链接的,均为广告
          adList.forEach(one => one.remove())
        }
        function removeHaosouAd() {
          MyApi.safeRemoveAd("#so_kw-ad");
          MyApi.safeRemoveAd("#m-spread-left");
          // 移除搜索中底部广告
          MyApi.safeRemoveAd("#m-spread-bottom");
          // 移除右侧栏顶部广告
          MyApi.safeRemove_xpath("id('righttop_box')//li[.//span[contains(text(), '广告')]]");
        }
  
        return {
          removeBaiduAd,
          removeGoogleAd,
          removeBingAd,
          removeHaosouAd
        }
      }
      InsertSettingMenu() {
        if (document.querySelector("#myuser") === null) {
          MyApi.safeWaitFunc("#u, #gb, #b_header>#id_h, #header_wrapper .js-hl-butto, .header--aside, #header .inner .menu", parent => {
            
            parent.style = "width: auto;";
            let userAdiv = document.createElement("div");
            userAdiv.id = "myuser";
            userAdiv.innerHTML = `<input type='submit' class='myuserconfig' value='自定义'/><span class='ac-newversionDisplay' style='background-color: red;float: left;height: 8px;width: 8px;border-radius: 4px;display: none'>&nbsp;</span>`;
  
            parent.insertBefore(userAdiv, parent.childNodes[0]);
            document.querySelector("#myuser .myuserconfig").addEventListener("click", function(e) {
              window.open(CONST.openSeetingsUrl)
            }, true);
          }, 300)
        }
      }
      RedirectHandle() {
        // 处理主重定向
        if (CONST.options.useItem.SiteTypeID < 0) return;
        if (CONST.curConfig.isRedirectEnable) {
          
          if (CONST.options.useItem.Stype_Normal) { // 如果定义了,那么就去处理重定向
            resetURLNormal();
          }
          if (CONST.options.useItem.SiteTypeID === CONST.options.google.SiteTypeID) removeOnMouseDownFunc(); // 移除onMouseDown事件,谷歌去重定向
          if (location.host.includes('m.baidu.com')) removeMobileBaiduDirectLink(); // 处理百度手机版本的重定向地址
          remove_xueshuBaidu(); // 百度学术重定向问题
          MyApi.safeRemoveAd(".res_top_banner"); // 移除百度可能显示的劫持
        }
  
        function removeMobileBaiduDirectLink() {
          let nodes = document.querySelectorAll("#page #page-bd #results .result:not([ac_redirectStatus])");
          for (let i = 0; i < nodes.length; i++) {
            let curNode = nodes[i];
            MyApi.safeFunc(function() {
              let curData = JSON.parse(curNode.dataset.log.replace(/'/gm, "\""));
              let trueLink = curData.mu;
              curNode.querySelector("article").setAttribute("rl-link-href", trueLink);
              curNode.querySelectorAll("a").forEach(function(per) {
                per.setAttribute("href", trueLink);
              });
            });
            curNode.setAttribute("ac_redirectStatus", "1");
          }
        }
  
        function removeOnMouseDownFunc() {
          MyApi.safeFunc(() => {
            let resultNodes = document.querySelectorAll(".g .rc a, #rs, #rso .g a");
            for (let i = 0; i < resultNodes.length; i++) {
              let one = resultNodes[i];
              one.setAttribute("onmousedown", ""); // 谷歌去重定向干扰
              one.setAttribute("target", "_blank"); // 谷歌链接新标签打开
              one.setAttribute("data-jsarwt", "0"); // Firefox谷歌去重定向干扰
            }
          })
        }
  
        function remove_xueshuBaidu() {
          if (CONST.options.useItem.SiteTypeID === CONST.options.baidu_xueshu.SiteTypeID) {
            let xnodes = document.querySelectorAll("a[href*='sc_vurl=http']");
            for (let j = 0; j < xnodes.length; j++) {
              let xurl = MyApi.getUrlAttribute(xnodes[j].href, "sc_vurl", true);
              xnodes[j].href = xurl;
            }
          }
        }
  
        function DealRedirect (request, curNodeHref, respText, RegText, hrefType) {
          if (respText === null || typeof (respText) === "undefined") return;
          let resultResponseUrl = "";
          if (RegText != null) {
            resultResponseUrl = MyApi.Reg_Get(respText, RegText);
          } else {
            resultResponseUrl = respText;
          }
          if (resultResponseUrl !== null && resultResponseUrl !== "" && !resultResponseUrl.includes("www.baidu.com/link")) {
            try {
              let host = PageFunc.getTextHost(resultResponseUrl);
  
              document.querySelectorAll("*[href*='" + curNodeHref + "']").forEach(per => {
                let changeNode = per;
  
                changeNode.setAttribute("ac_redirectStatus", "2");
                changeNode.href = resultResponseUrl;
                // changeNode.setAttribute("data-orihref", changeNode.href);
                if (changeNode.hasAttribute("meta")) {
                  changeNode.setAttribute("meta", host);
                  changeNode.dataset.host = host;
                }
  
                if (hrefType === null || hrefType === undefined || hrefType === "title") {
                  if (changeNode.text && changeNode.text.length < 10 && !changeNode.text.includes(host)
                    // 不能是redirect url 不能是h2\h3下直属链接
                    && !changeNode.parentElement.tagName.toLowerCase().includes("h")) {
                    changeNode.insertAdjacentHTML("beforeEnd", "&nbsp;-&nbsp;" + host);
                  }
                }
              })
              request && request.abort();
            } catch (e) {
            }
          }
        }
        function resetURLNormal() {
          const mainList = document.querySelectorAll(CONST.options.useItem.MainType)
  
          // 注意有重复的地址,尽量对重复地址进行去重
          var hasDealHrefSet = new Set();
          for (let i = 0; i < mainList.length; i++) {
            // 此方法是异步,故在结束的时候使用i会出问题-严重!
            // 采用闭包的方法来进行数据的传递
            const curNode = mainList[i];
  
            if (curNode !== null && curNode.getAttribute("ac_redirectStatus") === null) {
              curNode.setAttribute("ac_redirectStatus", "0");
  
              const linkNode = curNode.querySelector(CONST.options.useItem.Stype_Normal);
              if(linkNode === null) {
                continue
              }
  
              // 跳过特殊链接的处理
              if(linkNode.href && (linkNode.href.startsWith('javascript') || linkNode.href.startsWith('#'))) {
                continue
              }
  
              let linkHref = linkNode.href;
              let len1 = hasDealHrefSet.size;
              hasDealHrefSet.add(linkHref);
              let len2 = hasDealHrefSet.size;
              if (len1 === len2) continue; // 说明数据已经处理过,存在相同的记录
              const isLinkNeedDeal = () => {
                // 如果当前节点存在mu参数,或者link节点存在data-mdurl,那么就算直接成功,不用重新请求一遍了
                let trueLink = curNode.getAttribute('mu') || linkNode.getAttribute('data-mdurl')
                if(trueLink && !trueLink.includes('nourl')) {
                  trueLink = getBaiduEncodingHandle(trueLink)
                  DealRedirect(null, linkHref, trueLink);
                  return true
                }
              }
              const getBaiduEncodingHandle = (linkUrl) => {
                let resLink = linkUrl
                if(CONST.options.useItem.SiteTypeID === CONST.options.baidu.SiteTypeID && linkUrl.includes('baidu.com')) {
                  const [, first = ''] = /(ie=[^&]+)/.exec(location.search) || []
                  resLink = linkUrl.replace(/(ie=[^&]+)/, first)
                }
                return resLink
              }
              if(!isLinkNeedDeal()) {
                continue
              }
              // 走接口重定向处理
              if (linkHref.includes("www.baidu.com/link") ||
                linkHref.includes("m.baidu.com/from") ||
                linkHref.includes("www.sogou.com/link") ||
                linkHref.includes("so.com/link") ||
                linkHref.search("bing.com/(ck|a|aclick)") > 0 ||
                linkHref.search("e.so.com/(search|eclk)") > 0
              ) {
                (async function(c_curnode, c_curhref) {
                  let url = c_curhref.replace(/^http:/, "https:");
                  if (CONST.options.useItem.SiteTypeID === CONST.options.baidu.SiteTypeID && !url.includes("eqid")) {
                    // 如果是百度,并且没有带有解析参数,那么手动带上
                    url = url + "&wd=&eqid=";
                  }
  
                  let gmRequestNode = GM_xmlhttpRequest({
                    url: url,
                    headers: { "Accept": "*/*", "Referer": c_curhref.replace(/^http:/, "https:") },
                    method: "GET",
                    timeout: 8000,
                    onload: function(response) { // MARK 有时候这个函数根本不进来 - 调试的问题 - timeout
                      if (response.responseText || response.responseHeaders) {
                        // 由于是特殊返回-并且好搜-搜狗-百度都是这个格式,故提出
                        DealRedirect(gmRequestNode, c_curhref, response.responseText, "URL='([^']+)'")
                        // 这个是在上面无法处理的情况下,备用的 tm-finalurldhdg  tm-finalurlmfdh
  
                        if (response.responseHeaders.includes("tm-finalurl")) {
                          let relURL = Reg_Get(response.responseHeaders, "tm-finalurl\\w+: ([^\\s]+)");
                          if (relURL === null || relURL === "" || relURL.includes("www.baidu.com/search/error")) return;
                          DealRedirect(gmRequestNode, c_curhref, relURL);
                        }
                      }
                    }
                  });
                })(curNode, linkHref); //传递旧的网址过去,读作c_curhref
              }
            }
          }
          if (hasDealHrefSet.size > 0 && mainList.length - hasDealHrefSet.size > 0) console.mylog("丢弃掉", mainList.length - hasDealHrefSet.size, "个重复链接");
        }
      }
      getTextHost(sbefore) {
        sbefore = (sbefore && sbefore.trim()).replace(/\s-\s\d{4}-\d{1,2}-\d{1,2}/, "") || "";
        let send;
        let result = sbefore.split('-');
        // --搜狗百度专用;如果第一个是中文的话,地址就是第二个
        if ((result.length > 1 && new RegExp("[\\u4E00-\\u9FFF]+", "g").test(sbefore)) && CONST.options.useItem.SiteTypeID === CONST.options.baidu.SiteTypeID) {
          sbefore = result[1];
        } else {
          result = sbefore.split('\n');
          if (result.length > 1 && CONST.options.useItem.SiteTypeID === CONST.options.google.SiteTypeID) {
            sbefore = result[1];
          }
        }
        // 此时sbefore几乎是等于网址了,但是有时候会有多的空格,多的内容,多的前缀http,多余的路径
        let res = new RegExp(/(https?:\/\/)?([^/\s]+)/i).exec(sbefore);
        send = (res && res[2].trim()) || "";
        // send = sbefore.replace(/(\/[^/]*|\s*)/, "").replace(/<[^>]*>/g, "").replace(/https?:\/\//g, "").replace(/<\/?strong>/g, "").replace(/<\/?b>/g, "").replace(/<?>?/g, "").replace(/( |\/).*/g, "").replace(/\.\..*/, "");
        if (send === "") return null;
        if (send.indexOf(".") < 0) return null;
        if (send.indexOf("↵") >= 0) return null;
        return send.trim();
      }
      getNodeHost(sitetpNode) {
        if (!sitetpNode) return {}
        if (CONST.options.useItem.SiteTypeID === CONST.options.baidu.SiteTypeID) {
          const href = sitetpNode.getAttribute("href");
          if (href != null && !href.includes("baidu.com/link")) {
            // 已经解析出来了
            return { curHost: this.getTextHost(href), curUrl: href };
          } else {
            const host = this.getTextHost(sitetpNode.innerText || sitetpNode.textContent)
            return { curHost: host, curUrl: host, isBaiduLink: true }; // 未被解密
          }
        } else if (sitetpNode instanceof HTMLAnchorElement) {
          return { curHost: sitetpNode.host, curUrl: sitetpNode.href };
        } else {
          const host = this.getTextHost(sitetpNode.innerText || sitetpNode.textContent)
          return { curHost: host, curUrl: host };
        }
      }
      addFavicon(citeList) {
        const insertList = []
        if (CONST.options.useItem.SiteTypeID !== null) {
          for (let index = 0; index < citeList.length; index++) {
            if (null === citeList[index].getAttribute("ac_faviconStatus")) {
              let curNode = citeList[index];
              let targetNode = curNode;
              let { curHost, curUrl } = PageFunc.getNodeHost(targetNode);
              if (!curHost) { // 跳过解不出来的地址
                continue;
              } else {
              }
              let faviconUrl = curHost;
              let II = 0;
              for (; II <= 5; II++) {
                targetNode = targetNode.parentNode;
                if (targetNode != null && targetNode.querySelector(CONST.options.useItem.FaviconAddTo) != null) {
                  break;
                }
              }
              if (targetNode.parentNode.hasAttribute('tpl') && targetNode.parentNode.getAttribute('tpl').includes('stock')) {
                curNode.setAttribute("ac_faviconStatus", "-3");
                continue
              }
              //console.mylog(index+"."+faviconUrl+"--"+II);
              if (II <= 5) {
                // 先用父节点判断一下是否存在img
                let tmpHTML = targetNode.innerHTML;
                let pos = tmpHTML.indexOf("fav-url")
                  & tmpHTML.indexOf("wr_fav")
                  & tmpHTML.indexOf("favurl")
                  & tmpHTML.indexOf("tit-ico")
                  & tmpHTML.indexOf("img_fav rms_img")
                  & tmpHTML.indexOf("c-tool-")
                  & tmpHTML.indexOf("span class=\"c-icon c-icon-")
                  & tmpHTML.indexOf("img class=\"xA33Gc")
                  & tmpHTML.indexOf("img class=\"XNo5Ab\""); // 谷歌图标
                //他自己已经做了favicon了
                if (pos > -1) {
                  curNode.setAttribute("ac_faviconStatus", "-2");
                  continue;
                }
                targetNode = targetNode.querySelector(CONST.options.useItem.FaviconAddTo);
                let host = faviconUrl.replace(/[^.]+\.([^.]+)\.([^.]+)/, "$1.$2");
  
                if (!targetNode.hasAttribute("data-favicon-t") && host.length >= 3) {
                  let faviconUrl = curNode.href || host
                  if (CONST.options.useItem.SiteTypeID === CONST.options.baidu.SiteTypeID && faviconUrl.includes("baidu.com/link")) {
                    faviconUrl = host
                  }
  
                  targetNode.setAttribute('data-favicon-t', faviconUrl)
                  insertList.push({
                    tagName: targetNode.tagName.toLowerCase(),
                    url: faviconUrl
                  })
                }
              }
            }
          }
        }
        insertList.map(one => CONST.cssFavionList.list.push(one))
      }
      addCounter(citeList) {
        const cssText = "font-style:normal;position:relative;z-index:1;margin-right:4px;display:inline-block;color:white;font-family:'微软雅黑';font-size:16px;text-align:center;width:22px;line-height:22px;border-radius:50%;";
        for (let i = 0; i < citeList.length; i++) {
          let cur = citeList[i];
          const index = cur.getAttribute('SortIndex');
          if (index === null || typeof (index) === "undefined") {
            cur.setAttribute('SortIndex', CONST.sortIndex);
            let ele = document.createElement('em');
            ele.className = 'AC-CounterT';
            ele.style = cssText;
            ele.innerText = CONST.sortIndex;
            let child = cur.firstElementChild;
            if (child && child.nodeName === 'DIV') {
              let emNode = child.querySelector('em');
              if (emNode) emNode.parentNode.insertAdjacentElement('afterBegin', ele)
            } else {
              cur.insertAdjacentElement('afterBegin', ele);
            }
            CONST.sortIndex++;
          } else {
            const curCounter = cur.querySelector(".AC-CounterT")
            if (!curCounter) continue
            const oriIndex = curCounter.innerText
            const checkValue = (i + 1) % 100;
            // 数据值不同
            // 数据没有被翻译
            if (+index !== checkValue && !/^\d+$/.test(oriIndex)) { // 按需更新
              curCounter.innerText = checkValue;
              cur.setAttribute('SortIndex', checkValue);
            }
          }
        }
      }
      acSetCookie(cname, cvalue, domain, exdays) {
        MyApi.safeFunc(() => {
          exdays = exdays || 30;
          let d = new Date();
          domain = (domain ? "domain=" + domain : "") + ";";
          d.setTime(d.getTime() + (exdays * 24 * 60 * 60 * 1000));
          let expires = "expires=" + d.toUTCString();
          document.cookie = cname + "=" + cvalue + "; " + domain + expires + ";path=/;SameSite=None;Secure";
        })
      }
      dataChangeFireCallback() {
        // 数据有变更,那么尝试重新渲染状态
        CONST.cssAutoInsert.clear()
  
        if(!CONST.curConfig.enableCSS) {
          MyApi.safeGetNodeFunc('#myuser', node => node.remove())
          return
        }
        
        console.mylog('即将插入CSS1')
        if (CONST.curConfig.adsStyleEnable) {
          console.mylog('即将插入CSS2')
          
          if(+CONST.curConfig.adsStyleMode === 1) {
            console.mylog('靠左优化模式')
            CONST.cssAutoInsert.add("expandPageStyle", CONST.adsCSSList.expandPageStyle)
            CONST.cssAutoInsert.add("leftCommonStyle", CONST.adsCSSList.leftCommonStyle)
          } else if (+CONST.curConfig.adsStyleMode === 2) {
            console.mylog('单列居中')
            CONST.cssAutoInsert.add("expandPageStyle", CONST.adsCSSList.expandPageStyle)
            CONST.cssAutoInsert.add("leftCommonStyle", CONST.adsCSSList.leftCommonStyle)
            CONST.cssAutoInsert.add("onePageStyle", CONST.adsCSSList.onePageStyle)
          } else if (+CONST.curConfig.adsStyleMode === 3) {
            console.mylog('双列居中')
            CONST.cssAutoInsert.add("leftCommonStyle", CONST.adsCSSList.leftCommonStyle)
            CONST.cssAutoInsert.add("twoPageStyle", CONST.adsCSSList.twoPageStyle)
          } else if (+CONST.curConfig.adsStyleMode === 4 ||+CONST.curConfig.adsStyleMode === 5) {
            console.mylog('N列居中')
            CONST.cssAutoInsert.add("leftCommonStyle", CONST.adsCSSList.leftCommonStyle)
            CONST.cssAutoInsert.add("twoPageStyle", CONST.adsCSSList.twoPageStyle)
            CONST.cssAutoInsert.add("multiPageStyle", CONST.adsCSSList.multiPageStyle)
          }
        }
  
        CONST.cssAutoInsert.add("styleLogo", ".minidiv #logo img{width: 100px;height: unset;margin-top: 0.3rem;} body.purecss-mode:before{display: none;}")
        CONST.cssAutoInsert.add("specialBAIDU", ".opr-recommends-merge-imgtext{display:none!important;}.res_top_banner{display:none!important;}.headBlock, body>div.result-op{display:none;}")
        CONST.cssAutoInsert.add("animationStyle", "@keyframes ani_leftToright{0%{transform:translateX(-32px);opacity:0.2;}20%{opacity:0.5;}30%{opacity:0.8;}100%{opacity:1;}}@keyframes ani_bottomTotop{0%{transform:translateY(32px);opacity:0.2;}20%{opacity:0.5;}30%{opacity:0.8;}100%{opacity:1;}}@-webkit-keyframes ani_topTobuttom{0%{transform:translateY(-32px);opacity:0.2;}20%{opacity:0.5;}30%{opacity:0.8;}100%{opacity:1;}}@-webkit-keyframes ani_hideToShow{0%{display:none;opacity:0.2;}20%{opacity:0.5;}30%{opacity:0.8;}100%{opacity:1;}}@-webkit-keyframes ani_showToHide{0%{display:none;opacity:1;}20%{opacity:0.8;}30%{opacity:0.5;}100%{opacity:0.3;}}.aniDelete{transition:all 0.15s cubic-bezier(0.4,0,1,1);opacity:0.1}")
        CONST.cssAutoInsert.add("menuBtn", ".achide{display:none;} .newFuncHighLight{color:red;font-weight: 100;background-color: yellow;font-weight: 600;}#sp-ac-container label{display:inline;}#u{width:319px}#u #myuser{display:inline-block;margin: 13px -10px 0 24px;}.site-wrapper #myuser,.sogou-set-box #myuser,#gbw #myuser{margin-right:15px;} #gb #myuser{margin-top:7px;} #myuser,#myuser .myuserconfig{padding:0;margin:0}#myuser{display:inline-block;}#myuser .myuserconfig{display:inline-block;line-height:1.5;background:#4e6ef2;color:#fff;font-weight:700;text-align:center;padding:6px;border:2px solid #E5E5E5;}#myuser .myuserconfig{box-shadow:0 0 10px 3px rgba(0,0,0,.1);border-radius: 6px}#myuser .myuserconfig:hover{background:#4662d9 !important;color:#fff;cursor:pointer;border:2px solid #73A6F8;} body[haosou] #myuser{margin-top:-10px}")
  
        if(CONST.curConfig.baiduLiteEnable) {
          CONST.cssAutoInsert.add("baiduLiteStyle", CONST.adsCSSList.baiduLiteStyle)
        }
        
        if(CONST.curConfig.HuYanMode) {
          CONST.cssAutoInsert.add("huYanStyle", CONST.adsCSSList.huyanStyle)
        }
        if(CONST.curConfig.adsStyleEnable) {
          CONST.cssAutoInsert.add("adsBlockStyle", "#bottomads{display:none;} #content_left>div:not([id])>div[cmatchid], #content_left>div[id*='300']:not([class*='result']),#content_right td>div:not([id]),#content_right>br{position:absolute;top:-6666px;}")
        }
        if(CONST.curConfig.BgEnable) {
          const imageUrl = CONST.curConfig.BgUseUrl
          if(imageUrl) {
            const bgCSS = `body:before{pointer-events: none;position: fixed;width: 100%;height: 100%;top: 0;left: 0;content: '';background-image: url('${imageUrl}');background-size: 100% auto;opacity: 0.6;}`
            CONST.cssAutoInsert.add("backGroundImage", bgCSS)
          }
          if(CONST.curConfig.BgFit) {
            CONST.cssAutoInsert.add("bgFitStyle", CONST.adsCSSList.bgAutoFitStyle)
          }
        }
        if(CONST.curConfig.isDarkModeEnable) {
          CONST.cssAutoInsert.add("darkModeStyle", CONST.adsCSSList.darkModeStyle)
        }
        if (CONST.curConfig.isAutopage) {
          const sepImgs = {
            top: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABYAAAAWCAYAAADEtGw7AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAWtJREFUeNrclE0rRGEUx8c1GUpRJIVIZGdhZCVr38GGhaI0ZXwCkliglChZEcvJxhdgYWOjLEUpm/EyiLzze+o8dTzdO3PljoVTv7rPc8/5d+6555xYrEhWop6boda5+6l9wjWcWpF+WIbqCJJ9hFRcDr3QAIkIhKugz5PDfkSixkphz5aiAnqgE8rgWRxGoSOPyBkswQuUwyscw4HrmFCZL8Kt/JAg7mEFPEmo4FdPwk0BUcsdzIap0TQ8qMAPuICcEjLnd+VjSjcfJNgIc/DkZGSymYGsnK9EZMrxe4MFaNGiZjC2fT5zQ3p7QDK1dR2GSljziclAvRUe8nHYVA4jjvC43NfAuk/smB2QNqcsWxKcLbAKTFnS0hWD6n27Fd6FLqiDI5iQmQ9jpiVT0sNJ6aYd7dAE3QHBbinSAX5JWWaxuLo8F35jh/bBK9Y+/r/Cl6pLcnna8NvuDGMnslpbZRpXZYT/3r4EGACZL3ZL2afNFAAAAABJRU5ErkJggg==",
            bottom: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABYAAAAWCAYAAADEtGw7AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAXFJREFUeNrM1c8rBGEcx/FdtCEkLqYtpdwkKSUHUhxwITdK+Z3yM2cOLnJ39Cc44SgHScmJwlFxsIdlCScO6/2t76Onp52dXTtbnno1M8+Pz84+zzMzkcg/KA3oRTzM0A4cI4VTdIUVPIM3pPGO5aABJTkGx1BqjYmFFZxW7nnBwXmXogWX6bEGc2jEIU7+kNWDUSSwZyqndSvJ3N1g2Bm0oLtB2j+w7rQP4MpqXzRT0YRaPW/BthMedYLs60HsoE2vq9BsPwAJa8XFLUa0fUrvROo/saT1Q9adGimdlt8yj6TT6Q6d2vaida9YRbtP6EqmBZC5fHA6X+AAz1bwEc6cfk9+oaZM4NoZJL70+J2hTaZtNpet041zK8yP/Mgl+rOF1emr0UM1xnAfEPyISd0Jno6vtx+QuM6PZ22lpO7dbEV2Siv6rPeIjNs1HdYC7ixfG+YBqdTVDqPIv6iIWvO7iXGUFxAqi72PraJ9IH8EGACQcYjYRd5GHwAAAABJRU5ErkJggg==",
            pre: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABYAAAAWCAYAAADEtGw7AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAASlJREFUeNpiYBjOoBiIrwJxFRAzUsvQViD+CMT/gfgTEPdRy9BPUENh+AsQ91JiaAuSS9HxZ3INb8Hi0v+UurwF6qL/ROBvQNxDrKFfkTT+A+JnQPwBKfJA/L9Ian7ic7kMEHcC8Q80F3UAcRsQv4by30INaUJT9weaWhSQDRUB4uVYvLkYiAWAOBopvEFBlArEPEA8G4ue9UAsATM4EYuCJUgKMtAMLoSKCwPxXCx6c1igClTQgmUZVPNrHMEGy3mgYCkCYiYgTkCSV4UZvA2IjYBYDIgvQbPvOyJTECid5wHxbyA2BuL3QLwRWYEsEJvg0IweFEU41IEMlgcxWJAEH0MxJeAsjMFEq6Jw+Br8BimVfMCTDEkG7EBcA8T3oWUJx4DVYwABBgCannnSzbgwIQAAAABJRU5ErkJggg==",
            next: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABYAAAAWCAYAAADEtGw7AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAT1JREFUeNrc1b1KA0EYheEl/iARFFEkKl6D0UK8CrEVrCwEexFCtBIlRWIjsfEiLL0FKzs7QUWxM2piFMUkvhPOwLAs2TGuCn7wkNll5jC7+w0Jgv9avdjAObbQn1TwCu7QwhWW4xakPIOHMKzxGCaSCm6ioXHLZ0Hqpz7KrwRPIvvNvBlM2zYyNY8cMjhDHo9fCBzErnIqKNjgRSxpvIABbOLes2MKWHfuXdhXcR2avKrJ4zGhI9gLhQbq9XaZgGO1kutIOzIHpKp7NawhjYOINSeY6lFwHacw17P6NTWHd4xqnNbcS83LObtsaCPbEW+gXUW8ODswC27xoOsn3ODDmfOGss9XLuE54jGjvPqGuuG1mFDzZIfdNHynnde7DbW1r5DwTstJHP2iE55YqD36ebXZDvr+7L/sU4ABAIpVZWnoA5GkAAAAAElFTkSuQmCC",
            next_gray: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABYAAAAWCAYAAADEtGw7AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAtxJREFUeNrclc9L2mEcx7/6NbVZqRVj7pIOlIUuZ1HMgv0BDcqT7JrskH13ELPBF7eTvz10HznWQBlBRIfBXIfBLmqXscvYZWPKrMNIU9Apmrr34/w6i0ovMZjw+H0+z/N8Xt+Pn/fn80hR/+WHYRhBIpFwRKPRz/F4/KnD4RB28xH0Ah4cHHyoUCjsIpFIIZPJHkml0m9Yfn2ZD78XcL1eH6rValIMCmMUtqKbD7/HbNQxaq15oxcH/lXpcmXgtnh2u/2mXC6/DqE+sSxLlUqlniE0TVPBYJAqFot6+GV9Pt+PJthms80sLS2xEonkhlgs/jgwMOBcXV3N5fP5rlCcp9bX1yWLi4uecrk8U6lUshDY3wRbLJYFGKZsNksq4N78/LwY9hOn05k5Ojqi+PzTGePxeFwZUl6vd8hkMvkPDg6sZJ2M5eXlr1wqUu2kA5JOpy2IAO+oO9fW1n5mMpk2nDjmcjkKNU25XC652Wx2pVIp65mXJ2nyjUPpqakpNZxuA8Y5T87OzsobjcYHpVKpGhsbe1CtVkXYqxQKhTdqtfqL1Wr1JpPJxxyU5Lq/vz8aCoX8TTDatYiFhF6vxx5tAJwm8OPj48m5ubmKSqUaAWwSa9eQw6JGo/luNBoNh4eHbAe0JhAINsLh8LNAIJCiudhxB+Qh2ludTifDAQLvI3AIch+Rkl8jJlrhCbOqgfoLmDepOF/BfGNra2sFFZFtvqgzMbFYjAiyp9Vqh4VC4cTJyYmQ90epIQJtHRO1bA5aRhAvdnZ2GI/H87cEz5YPgeOS2RsfHx9B7u+gOi68yQAtYX9zd3eXgZCna/s8By5ypGUUzhOISHgO9BfWXwG6chZ6IbiVc6LwnsFgGIVAepLzjk4rYW1ze3ubcbvd53fjZV2FaqGQ63fT09PDMO9i9BEoon0J9Rm/339xm3dr2f39fVLX7wFvoMVvoYWfRyIRFndD/Z/8nf0WYAA8EC1Z/ZNm4gAAAABJRU5ErkJggg==",
            pre_gray: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABYAAAAWCAYAAADEtGw7AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAslJREFUeNrclTtMWmEUxz/uvTzlIUhpNMR0aGNjrNHSmHTqRJyadujQDbSGRwJUaYCmDizqUEw6ODVNGgbpYCfSpFINCQzFR9oyMXRsXFCsAXkIKNL/R7gGWxOsSdPEk5zc3O+e87vn+59zv0vIpbSJiQmyubn5LBKJpNbX11+4XC5Buxy2XYDNZiMOh2OW4ziPTCbTi8XikeHh4SsSieQTXnIxsN1uJ1ardVYgEDgPDw+V9Xqd1Go1Mcuyg7AuuVy+sra29ndgVEnGx8dnhEKhs1qtKgE/eXZ8fCzC+q3+/n6tSqVaSSQS5wM7nU5iMplmsF1XpVI5BeXt6OhIBFkGAe9SKpV/wNmzKjWbzRT6tFwuK86CUqPrkIVWPjQwMKBWKBSn4Ozv0LGxsRmRSDSFSjua0Do8TRWAS+B5+B68g/IhixCNvQPN1WjuieZsS/f1aNQ0wzBuaCqlUCQRtVr9Es1K4kVDWJNhrQjAIiqMlkqle804FnkjBoOhEzv4vrGxkW2ALRaLFrq+QoAV2nE8tLe3dzEYDE5vb2939vX1PcBkiKVSaQ1jForFYq+NRqMum83ebsYzmJq7sGu4xhkKxsDfB/AxnO860ev1oeXlZU8gEMgmk0kFqmw8o9dUKiWfn58vhMPh54h7S+OpQXNSLBYfejyeR1yzw9dbRon09PS8W11dnfL5fJl8Pk+0Wi3hk5vyCNBY4vV6f0Im9+joKJNOp818o8G70ah4aWnpIzSKYCa/dXd3B+PxuHNycjKzs7NzAms1+qFQy+VydDRz0WjUpdPp3tB8TFM0FAqFGxXPzc19plJrNJqraMoXt9tNt3Suc+Tg4ICeJfmFhQVLoVAwoKG7fr//B8cHAL6Fy9ZFDinaG/r5w77ya8y/OhEvKRhjtIup2YMTeBb3mXY53HnAmNkP+/v7NzHTTwAO4f79f/ud/RJgAOLcRNZqLojMAAAAAElFTkSuQmCC",
          };
          const cssText = ".sp-separator{grid-column: 1 / -1; line-height:1.8 !important;opacity:1 !important;position:relative !important;float:none !important;top:0 !important;left:0 !important;min-width:366px;width:auto;text-align:center !important;font-size:14px !important;display:block !important;padding:3px 0 !important;margin:5px 10px 8px;clear:both !important;border-style:solid !important;border-color:#cccccc !important;border-width:1px !important;-moz-border-radius:30px !important;border-radius:30px !important;background-color:#ffffff !important;}.sp-separator:hover{box-shadow:0 0 11px rgba(33,33,33,0.2);}#sp-separator-hover{display:none;}.sp-separator:hover #sp-separator-hover{display:block;}.sp-separator .sp-someinfo{position:absolute !important;right:10px !important;font-size:12px !important;font-style:italic !important;background:none !important;}.sp-separator span{vertical-align: middle;cursor: pointer;padding: 0;margin: 0 5px;display: inline-block; width:22px;height:22px;}.sp-separator a{margin:0 20px 0 -6px !important;display:inline !important;text-shadow:#fff 0 1px 0 !important;background:none !important;color:#595959 !important;}.sp-separator input{padding:0 !important;line-height:23px !important;}.sp-separator .sp-md-span{font-weight:bold !important;margin:0 20px !important;}#sp-sp-md-number{width:6ch !important;vertical-align:middle !important;display:inline-block !important;text-align:left !important;}" +
            `.ac_sp_top{background-image:url('${ sepImgs.top }')}` +
            `.ac_sp_pre{background-image:url('${ sepImgs.pre }')}` +
            `.ac_sp_next{background-image:url('${ sepImgs.next }')}` +
            `.ac_sp_bottom{background-image:url('${ sepImgs.bottom }')}` +
            `.ac_sp_next_gray{background-image:url('${ sepImgs.next_gray }')}` +
            `.ac_sp_pre_gray{background-image:url('${ sepImgs.pre_gray }')}`
          CONST.cssAutoInsert.add("preloadAutoPage", cssText)
        }
        if(CONST.curConfig.isBlockEnable) {
          CONST.cssAutoInsert.add("customBlockStyle", "button.ghhider.ghhb[ac-user-alter='1']::before{content:'取消 - ';}#sp-ac-container .ac-block-item{color:#AAA;margin-left:48px;}#sp-ac-container .ac-block-itemdel{float:right;margin-left:0;padding:0 20px;cursor:pointer;}#sp-ac-container .ac-block-itemdel:hover{color:red;}#sp-ac-container .ac-block-high{color:#000;}.ac-blockList li:hover{background-color:#a3caff;color:white !important;cursor:pointer;} *[ac-needhide] *{display:none} *:not([ac-needhide]) .blockShow{display: none;} *[ac-needhide] .blockShow{display:unset;cursor:pointer;} *[ac-needhide] .blockShow:hover{border:1px solid #DDD}button.ghhider{color:#555;background-color:#fcfcfc;font-family:sans-serif;margin:auto 2px;border:1px solid #ccc;border-radius:4px;padding:2px 3px}button.ghhider{font-size:12px}button.ghhider:hover{color:#006aff;background:#fff} body[haosou] button.ghhider{vertical-align: super;} body[google] button.ghhider{vertical-align: top;}") // 公共自定义样式
        }
        
        if(CONST.curConfig.isFaviconEnable) {
          CONST.cssAutoInsert.add("faviconStyle", CONST.adsCSSList.faviconStyle) // 插入Favicon图标
        }
        
        if(CONST.curConfig.isBlockEnable || CONST.curConfig.isFaviconEnable) {
          CONST.cssAutoInsert.add("lineTitleFix", 'body[haosou] .res-title {display: inline-flex;}') // 插入Favicon图标
        }
        
        if(CONST.curConfig.isALineDisable) {
          CONST.cssAutoInsert.add("alinkEnable", "a,a em{text-decoration:none !important}")
        }
        
        if(CONST.curConfig.isCounterEnable) {
          CONST.cssAutoInsert.add("counterStyle", ".AC-CounterT{background:#FD9999}body  #sp-ac-container{position:fixed;top:3.9vw;right:8.8vw}")
        }
        
        // if(CONST.options.useItem.SiteTypeID === CONST.options.google.SiteTypeID && CONST.curConfig.useBaiduLogo) {
        //   CONST.cssAutoInsert.add("useBaiduLogo", "") // 谷歌使用百度LOGO
        // }
  
        /*****自定义样式最后加载*****/
        if (CONST.curConfig.commonStyleEnable) {
          CONST.cssAutoInsert.add("commonStyle", CONST.adsCSSList.commonStyle) // 公共自定义样式
        }
        if (CONST.curConfig.customStyleEnable) {
          CONST.cssAutoInsert.add("customStyle", CONST.adsCSSList.customStyle) // 站点自定义样式
        }
      }
      pagerBind() {
        const ShowPager = {
          getFullHref: function(e) {
            if (e === null) return '';
            "string" != typeof e && (e = e.getAttribute("href"));
            var t = this.getFullHref.a;
            return t || (this.getFullHref.a = t = document.createElement("a")), t.href = e, t.href;
          },
          createDocumentByString: function(str) {
            // string转为DOM
            if (!str) {
              console.error("[AC-Script]", 'No string found to be converted to DOM');
              return;
            }
  
            if (document.documentElement.nodeName !== 'HTML') {
              return new DOMParser().parseFromString(str, 'application/xhtml+xml');
            }
            var doc;
  
            MyApi.safeFunc(() => {
              // firefox and chrome 30+,Opera 12 会报错
              doc = new DOMParser().parseFromString(str, 'text/html');
              if (doc) {
                return doc;
              }
            })
  
            if (document.implementation.createHTMLDocument) {
              doc = document.implementation.createHTMLDocument('superPreloader');
            } else {
              MyApi.safeFunc(() => {
                doc = document.cloneNode(false);
                doc.appendChild(doc.importNode(document.documentElement, false));
                doc.documentElement.appendChild(doc.createElement('head'));
                doc.documentElement.appendChild(doc.createElement('body'));
              })
            }
  
            if (!doc) return;
            var range = document.createRange();
            range.selectNodeContents(document.body);
            var fragment = range.createContextualFragment(str);
            doc.body.appendChild(fragment);
            var headChildNames = {
              TITLE: true,
              META: true,
              LINK: true,
              STYLE: true,
              BASE: true
            };
            var child;
            var body = doc.body;
            var bchilds = body.childNodes;
  
            for (let i = bchilds.length - 1; i >= 0; i--) {
              // 移除head的子元素
              child = bchilds[i];
              if (headChildNames[child.nodeName]) body.removeChild(child);
            }
  
            return doc;
          },
          loadMorePage: async function() {
            if (CONST.options.useItem.pager) {
              let curPageEle = MyApi.getElementByXpath(CONST.options.useItem.pager.nextLink);
              var url = this.getFullHref(curPageEle);
              if (CONST.options.useItem.SiteTypeID === CONST.options.google.SiteTypeID) {
                if (navigator.userAgent.toLowerCase().includes('macintosh')) {
                  // MARK 为了兼容百度在safari下的
                  url = url.replace('https://', 'http://');
                }
              }
              if (url === '') return;
              if (CONST.options.useItem.pageUrl === url) {
                console.error("[AC-Script]", "翻页到达底部了 - 或者异常 - 出现异常请直接反馈作者修改");
                return;
              }// 不会重复加载相同的页面
              console.log("加载翻页地址:" + url)
              CONST.options.useItem.pageUrl = url;
              // 对url的数据进行读取
              CONST.options.useItem.pager.startFilter && curSite.pager.startFilter();
              GM_xmlhttpRequest({
                url: url,
                method: "GET",
                timeout: 5000,
                onload: function(response) {
                  try {
                    var newBody = ShowPager.createDocumentByString(response.responseText);
  
                    const [Rule_insertTo = '', Rule_insertMode = 1] = CONST.options.useItem.pager.HT_insert || []
                    let pageElems = MyApi.getAllElements(CONST.options.useItem.pager.pageElement, newBody, newBody);
                    const scriptElems = MyApi.getAllElements('//script', newBody, newBody);
  
                    let toElement;
  
                    if (pageElems.length) {
                      const curPageElems = MyApi.getAllElements(CONST.options.useItem.pager.pageElement, document, document)
                      const pELast = curPageElems[curPageElems.length - 1];
                      toElement = pELast.nextSibling ? pELast.nextSibling : pELast.parentNode.appendChild(document.createTextNode(' '));
                    }
                    if (Rule_insertTo) {
                      toElement = MyApi.getAllElements(Rule_insertTo)[0];
                    }
                    if (pageElems.length >= 0) {
                      // 处理最后一个翻页按钮
                      let nextEs = document.querySelectorAll("#sp-sp-gonext");
                      if (nextEs.length > 0) {
                        let lastE = nextEs[nextEs.length - 1];
                        lastE.classList.replace("ac_sp_next_gray", "ac_sp_next");
                      }
                      // 插入翻页按钮元素
                      CONST.options.useItem.pageNum++;
                      let addTo = "beforeend";
                      if (Rule_insertMode === 1) addTo = "beforebegin";
  
                      const insertPager = document.createElement('div')
                      insertPager.id = "sp-separator-ACX".replace(/ACX/gm, CONST.options.useItem.pageNum)
                      insertPager.className = "sp-separator AC"
                      insertPager.innerHTML = `
                            <a class='sp-sp-nextlink' target='_blank'><b>第 <span style='color:#595959!important;'>ACX</span> 页</b></a>
                            <span id="sp-sp-gotop" class='ac_sp_top' title='去到顶部'></span>
                            <span id="sp-sp-gopre" class='${ CONST.options.useItem.pageNum <= 2 ? "ac_sp_pre_gray" : "ac_sp_pre" }' title='上滚一页' ></span>
                            <span id="sp-sp-gonext" class='ac_sp_next_gray' title='下滚一页'></span>
                            <span id="sp-sp-gobottom" class='ac_sp_bottom' title='去到底部' ></span>`
                        .replace(/ACX/gm, CONST.options.useItem.pageNum);
  
                      if(Rule_insertMode === 1) {
                        toElement.parentNode.insertBefore(insertPager, toElement)
                        // 插入新页面元素
                        pageElems.forEach(function(one) {
                          toElement.parentNode.insertBefore(one, toElement)
                        });
                      } else {
                        toElement.appendChild(insertPager)
  
                        pageElems.forEach(function(one) {
                          toElement.appendChild(one)
                        });
                      }
  
                      document.querySelectorAll(".sp-separator.AC:not([bind])").forEach(function(per) {
                        per.setAttribute("bind", 1);
                        per.addEventListener("click", PageFunc.ac_spfunc);
                      });
  
                      if(CONST.options.useItem.pager.afertPagerAutoCallFunc) {
                        CONST.options.useItem.pager.afertPagerAutoCallFunc(pageElems, scriptElems)
                      }
  
                      // 替换待替换元素 - 一般是替换翻页的按钮
                      try {
                        if (CONST.options.useItem.pager.replaceE) {
                          let oriE = MyApi.getAllElements(CONST.options.useItem.pager.replaceE);
                          let repE = MyApi.getAllElements(CONST.options.useItem.pager.replaceE, newBody, newBody);
                          if (oriE.length === repE.length) {
                            if (oriE.length === 0) {
                              throw "翻页-替换翻页元素 无 'replaceE' 待替换的";
                            }
                            for (let i = 0; i < oriE.length; i++) {
                              oriE[i].outerHTML = repE[i].outerHTML;
                            }
                          }
                        }
                      } catch (e) {
                        console.log(e);
                      }
                    }
                  } catch (e) {
                    console.log(e);
                  }
  
                  CONST.lock.pageLoadingLocked = false;
                },
                onerror: function() {
                  CONST.lock.pageLoadingLocked = false;
                }
              });
            }
          },
        };
        console.mylog('pager已绑定成功')
        this.windowscroll(async (direction, e) => {
          if (direction === "down") { // 下滑才准备翻页
            let spl = document.querySelector("#sp-fw-a_enable");
            // 开启后,且在非(suprepreloader启用)时均可
            if (CONST.curConfig.isAutopage === true && !(spl && spl.checked === true) && document.documentElement) {
              const scrollTop = document.documentElement.scrollTop || window.pageYOffset || document.body.scrollTop;
              let scrollDelta = 888;
              if (document.documentElement.scrollHeight <= document.documentElement.clientHeight + scrollTop + scrollDelta && CONST.lock.pageLoadingLocked === false) {
                console.mylog('开始进行翻页')
                CONST.lock.pageLoadingLocked = true;
                if (CONST.options.useItem.SiteTypeID === CONST.options.duck.SiteTypeID) { // 可以用已有的方法来实现了
                  if (!CONST.curConfig.optimizeDuck || +CONST.curConfig.adsStyleMode >= 3) { // 如果没有开启,那么手动翻页 || 如果是双列的时候,似乎并不会自动触发翻页效果
                    const node = document.querySelector("#links .result--more a")
                    node && node.click();
                    setTimeout(function() {
                      CONST.lock.pageLoadingLocked = false;
                    }, 5000);
                  }
                } else {
                  await ShowPager.loadMorePage();
                  if (CONST.options.useItem.pager && CONST.options.useItem.pager.stylish) {
                    CONST.cssAutoInsert.add('autoPager', CONST.options.useItem.pager.stylish)
                  } else {
                    setTimeout(function() {
                      CONST.lock.pageLoadingLocked = false;
                    }, 5000);
                    console.mylog('当前站点没有配置pager')
                  }
                }
              }
            }
          }
        });
      }
      windowscroll(fn = () => {}) {
        let beforeScrollTop = document.documentElement.scrollTop
        window.addEventListener("scroll", function(e) {
          var afterScrollTop = document.documentElement.scrollTop,
            delta = afterScrollTop - beforeScrollTop;
          if (delta === 0) return false;
          fn(delta > 0 ? "down" : "up", e);
          beforeScrollTop = afterScrollTop;
        }, false);
      }
      ac_spfunc(e) {
        console.error("这里有问题")
        e.stopPropagation();
        var t, r = e.currentTarget;
        const Tween = {
          Linear: function Linear(e, t, r, n) {
            return r * e / n + t;
          },
          Quad: {
            easeIn: function easeIn(e, t, r, n) {
              return r * (e /= n) * e + t;
            },
            easeOut: function easeOut(e, t, r, n) {
              return -r * (e /= n) * (e - 2) + t;
            },
            easeInOut: function easeInOut(e, t, r, n) {
              return (e /= n / 2) < 1 ? r / 2 * e * e + t : -r / 2 * (--e * (e - 2) - 1) + t;
            }
          },
          Cubic: {
            easeIn: function easeIn(e, t, r, n) {
              return r * (e /= n) * e * e + t;
            },
            easeOut: function easeOut(e, t, r, n) {
              return r * ((e = e / n - 1) * e * e + 1) + t;
            },
            easeInOut: function easeInOut(e, t, r, n) {
              return (e /= n / 2) < 1 ? r / 2 * e * e * e + t : r / 2 * ((e -= 2) * e * e + 2) + t;
            }
          },
          Quart: {
            easeIn: function easeIn(e, t, r, n) {
              return r * (e /= n) * e * e * e + t;
            },
            easeOut: function easeOut(e, t, r, n) {
              return -r * ((e = e / n - 1) * e * e * e - 1) + t;
            },
            easeInOut: function easeInOut(e, t, r, n) {
              return (e /= n / 2) < 1 ? r / 2 * e * e * e * e + t : -r / 2 * ((e -= 2) * e * e * e - 2) + t;
            }
          },
          Quint: {
            easeIn: function easeIn(e, t, r, n) {
              return r * (e /= n) * e * e * e * e + t;
            },
            easeOut: function easeOut(e, t, r, n) {
              return r * ((e = e / n - 1) * e * e * e * e + 1) + t;
            },
            easeInOut: function easeInOut(e, t, r, n) {
              return (e /= n / 2) < 1 ? r / 2 * e * e * e * e * e + t : r / 2 * ((e -= 2) * e * e * e * e + 2) + t;
            }
          },
          Sine: {
            easeIn: function easeIn(e, t, r, n) {
              return -r * Math.cos(e / n * (Math.PI / 2)) + r + t;
            },
            easeOut: function easeOut(e, t, r, n) {
              return r * Math.sin(e / n * (Math.PI / 2)) + t;
            },
            easeInOut: function easeInOut(e, t, r, n) {
              return -r / 2 * (Math.cos(Math.PI * e / n) - 1) + t;
            }
          },
          Expo: {
            easeIn: function easeIn(e, t, r, n) {
              return 0 == e ? t : r * Math.pow(2, 10 * (e / n - 1)) + t;
            },
            easeOut: function easeOut(e, t, r, n) {
              return e == n ? t + r : r * (1 - Math.pow(2, -10 * e / n)) + t;
            },
            easeInOut: function easeInOut(e, t, r, n) {
              return 0 == e ? t : e == n ? t + r : (e /= n / 2) < 1 ? r / 2 * Math.pow(2, 10 * (e - 1)) + t : r / 2 * (2 - Math.pow(2, -10 * --e)) + t;
            }
          },
          Circ: {
            easeIn: function easeIn(e, t, r, n) {
              return -r * (Math.sqrt(1 - (e /= n) * e) - 1) + t;
            },
            easeOut: function easeOut(e, t, r, n) {
              return r * Math.sqrt(1 - (e = e / n - 1) * e) + t;
            },
            easeInOut: function easeInOut(e, t, r, n) {
              return (e /= n / 2) < 1 ? -r / 2 * (Math.sqrt(1 - e * e) - 1) + t : r / 2 * (Math.sqrt(1 - (e -= 2) * e) + 1) + t;
            }
          },
          Elastic: {
            easeIn: function easeIn(e, t, r, n, a, o) {
              return 0 == e ? t : 1 == (e /= n) ? t + r : (o || (o = .3 * n), !a || a < Math.abs(r) ? (a = r,
                i = o / 4) : i = o / (2 * Math.PI) * Math.asin(r / a), -a * Math.pow(2, 10 * (e -= 1)) * Math.sin((e * n - i) * (2 * Math.PI) / o) + t);
              var i;
            },
            easeOut: function easeOut(e, t, r, n, a, o) {
              return 0 == e ? t : 1 == (e /= n) ? t + r : (o || (o = .3 * n), !a || a < Math.abs(r) ? (a = r,
                i = o / 4) : i = o / (2 * Math.PI) * Math.asin(r / a), a * Math.pow(2, -10 * e) * Math.sin((e * n - i) * (2 * Math.PI) / o) + r + t);
              var i;
            },
            easeInOut: function easeInOut(e, t, r, n, a, o) {
              return 0 == e ? t : 2 == (e /= n / 2) ? t + r : (o || (o = n * (.3 * 1.5)), !a || a < Math.abs(r) ? (a = r,
                i = o / 4) : i = o / (2 * Math.PI) * Math.asin(r / a), e < 1 ? a * Math.pow(2, 10 * (e -= 1)) * Math.sin((e * n - i) * (2 * Math.PI) / o) * -.5 + t : a * Math.pow(2, -10 * (e -= 1)) * Math.sin((e * n - i) * (2 * Math.PI) / o) * .5 + r + t);
              var i;
            }
          },
          Back: {
            easeIn: function easeIn(e, t, r, n, a) {
              return null == a && (a = 1.70158), r * (e /= n) * e * ((a + 1) * e - a) + t;
            },
            easeOut: function easeOut(e, t, r, n, a) {
              return null == a && (a = 1.70158), r * ((e = e / n - 1) * e * ((a + 1) * e + a) + 1) + t;
            },
            easeInOut: function easeInOut(e, t, r, n, a) {
              return null == a && (a = 1.70158), (e /= n / 2) < 1 ? r / 2 * (e * e * ((1 + (a *= 1.525)) * e - a)) + t : r / 2 * ((e -= 2) * e * ((1 + (a *= 1.525)) * e + a) + 2) + t;
            }
          },
          Bounce: {
            easeIn: function easeIn(e, t, r, n) {
              return r - Tween.Bounce.easeOut(n - e, 0, r, n) + t;
            },
            easeOut: function easeOut(e, t, r, n) {
              return (e /= n) < 1 / 2.75 ? r * (7.5625 * e * e) + t : e < 2 / 2.75 ? r * (7.5625 * (e -= 1.5 / 2.75) * e + .75) + t : e < 2.5 / 2.75 ? r * (7.5625 * (e -= 2.25 / 2.75) * e + .9375) + t : r * (7.5625 * (e -= 2.625 / 2.75) * e + .984375) + t;
            },
            easeInOut: function easeInOut(e, t, r, n) {
              return e < n / 2 ? .5 * Tween.Bounce.easeIn(2 * e, 0, r, n) + t : .5 * Tween.Bounce.easeOut(2 * e - n, 0, r, n) + .5 * r + t;
            }
          }
        };
        const TweenM = ["Linear", "Quad", "Cubic", "Quart", "Quint", "Sine", "Expo", "Circ", "Elastic", "Back", "Bounce"];
        const TweenEase = ["easeIn", "easeOut", "easeInOut"];
        var prefs = {
          s_method: 3,
          s_ease: 2,
          s_FPS: 60,
          s_duration: 333,
        };
  
        function getRelativeDiv(e) {
          var t = r.id;
          return (t = t.replace(/(sp-separator-)(.+)/, (function(t, r, n) {
            return r + String(Number(n) + ("pre" == e ? -1 : 1));
          }))) ? document.getElementById(t) : null;
        }
  
        function sp_transition(e, t) {
          var r = sp_transition.TweenF;
          r || (r = (r = Tween[TweenM[prefs.s_method]])[TweenEase[prefs.s_ease]] || r, sp_transition.TweenF = r);
          var n = 1e3 / prefs.s_FPS, a = 0, o = e, i = t - e, s = Math.ceil(prefs.s_duration / n),
            c = window.scrollX;
          !function transition() {
            var e = Math.ceil(r(a, o, i, s));
            window.scroll(c, e), a < s && (a++, setTimeout(transition, n));
          }();
        }
  
        function scrollIt(e, t) {
          sp_transition(e, t);
        }
  
        switch (e.target.id) {
          case "sp-sp-gotop":
            scrollIt(window.scrollY, 0);
            break;
  
          case "sp-sp-gopre":
            var n = getRelativeDiv("pre");
            if (!n) return;
            t = window.scrollY;
            var a = n.getBoundingClientRect().top;
            a = t - (r.getBoundingClientRect().top - a);
            scrollIt(t, a);
            break;
  
          case "sp-sp-gonext":
            var o = getRelativeDiv("next");
            if (!o) return;
            t = window.scrollY;
            var i = o.getBoundingClientRect().top;
            i = t + (-r.getBoundingClientRect().top + i);
            scrollIt(t, i);
            break;
  
          case "sp-sp-gobottom":
            scrollIt(window.scrollY, Math.max(document.documentElement.scrollHeight, document.body.scrollHeight));
        }
      }
      bingAutoScrollFix() {
        document.addEventListener('visibilitychange', function() {
          if (document.visibilityState === 'hidden') {
            CONST.bingScrollPos = document.documentElement.scrollTop;
          } else if (document.visibilityState === 'visible') {
            setTimeout(() => {
              if(CONST.bingScrollPos !== 0 && document.documentElement.scrollTop !== CONST.bingScrollPos) {
                console.error('触发滚动条变更:', CONST.bingScrollPos, document.documentElement.scrollTop)
                document.documentElement.scrollTop = CONST.bingScrollPos
              }
            }, 50)
          }
        });
      }
      bingFaviconPagerFix() {
        document.querySelectorAll('div.rms_iac').forEach(one => {
          const height = one.dataset.height
          const width = one.dataset.width
          const toClass = one.dataset.class
          const imgSrc = one.dataset.src
          const bm = one.dataset.bm
          if(imgSrc) {
            one.outerHTML = `<img src="${imgSrc}" height="${height}" width="${width}" data-priority="2" role="presentation" class="${toClass}" data-bm="${bm}">`  
          }
        })
      }
    }
    class PageBlockClass {
      constructor() {
        this.curSite = CONST.options.useItem
        this.regListRule = []
        this._updateRegListRule()
      }
  
      async start() {
        const needCheckClass = (this.curSite.MainType + ',').split(',').join(":not([bhandle]),")
        let checkNodes = document.querySelectorAll(needCheckClass.substring(0, needCheckClass.length - 1));
        for (let i = 0; i < checkNodes.length; i++) {
          let curNode = checkNodes[i];
          try {
            let faviconNode = curNode.querySelector(this.curSite.FaviconType);
            let host = PageFunc.getNodeHost(faviconNode).curHost;
            let faNode = curNode.querySelector(this.curSite.BlockType);
            let nodeStyle = "display:unset;";
            if (!CONST.curConfig.isBlockBtnDisplay) {
              nodeStyle = "display:none;";
            }
            // 避免父节点出现两个block按钮
            if (faNode && !faNode.hasAttribute('hasInsert')) {
              faNode.setAttribute("hasInsert", "1");
              let insertTo = faNode.parentNode
              if(CONST.options.useItem.SiteTypeID === CONST.options.google.SiteTypeID) {
                insertTo = faNode
              }
              insertTo.insertAdjacentHTML("beforeend", `<button style='${ nodeStyle }' class='ghhider ghhb' href="${ faviconNode?.href || faviconNode?.innerText }" meta="${ host }" data-host="${ host }" title='${ this._getBlockBtnTitle(host) }'>block</button>`);
            }
            curNode.setAttribute("bhandle", "1");
          } catch (e) {
            console.error(e)
            const failed_count = +(curNode.getAttribute('failed_count') || 1)
            curNode.setAttribute('failed_count', failed_count + 1)
            if (failed_count > 3) {
              curNode.setAttribute("bhandle", "1");
            }
          }
        }
        this._initListener();
        await this.renderDisplay()
      }
      async renderDisplay() {
        // 增加checking中的检查,避免多次重复调用,减少cpu消耗
        if (CONST.lock.isBlockChecking) return
        CONST.lock.isBlockChecking = true
  
        let checkNodes = document.querySelectorAll(this.curSite.MainType);
        if([...checkNodes].every(one => one.dataset.checked) && CONST.lock.afterBlockChangeChecked) {
          CONST.lock.isBlockChecking = false
          return
        }
        const regList = this.regListRule
        let flag = "ac-needhide";
        for (let i = 0; i < checkNodes.length; i++) {
          try {
            let curNode = checkNodes[i];
            if (curNode.querySelector("button[ac-user-alter]") != null) continue; // 用户手动点过显示的,那么跳过check
            // 减少数据计算
            let { curHost = "", curUrl = "" } = PageFunc.getNodeHost(curNode.querySelector(this.curSite.FaviconType));
            if (!curHost) continue
            let BlockBtn = curNode.querySelector(".ghhider.ghhb");
            BlockBtn.dataset.host = BlockBtn.dataset.meta = curHost;
            BlockBtn.title = this._getBlockBtnTitle(curHost);
            // 减少数据计算
            if (curHost && regList.findIndex(one => {
              try {
                return one.test(curHost || curUrl); // 耗时操作
              } catch (e) {
                return one === curHost;
              }
            }) >= 0) {
              
              
              // 只检查在屏蔽表中的数据
              if (!curNode.hasAttribute(flag)) {
                curNode.setAttribute(flag, "1");
                if (CONST.curConfig.isBlockResultDisplay) { // 对于不显示的数据可以进行移除操作
                  curNode.remove();
                  continue;
                }
                let curTitle = curNode.querySelector(this.curSite.BlockType);
                curTitle = curTitle.innerText || curTitle.textContent;
  
                (function(xcur) {
                  const blockShow = xcur.querySelector(".blockShow");
                  if(!blockShow) {
                    curNode.insertAdjacentHTML("afterBegin", `<span class="blockShow" title="如果需要一直显示,请在自定义中DIY目录移除本地址">${ curTitle }&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; -block by ${ curHost }</span>`);
                    // 已经屏蔽之后的内容,点击一下显示原始内容
                    xcur.addEventListener("click", function(env) {
                      if(!xcur.querySelector(".blockShow")) return
                      xcur.querySelector("button.ghhider").setAttribute("ac-user-alter", "1"); // 这个属性用于保持在DOM更新时,按钮不变
                      xcur.removeAttribute(flag);
                      delete xcur.dataset.checked
                      MyApi.safeFunc(function() {
                        xcur.querySelector(".blockShow").remove();
                      });
                      env.stopPropagation();
                      env.preventDefault()
                    });
                  }
                })(curNode);
              }
            } else {
              curNode.removeAttribute(flag);
            }
            curNode.dataset.checked = '1'
          } catch (e) {}
        }
        CONST.lock.isBlockChecking = false
        CONST.lock.afterBlockChangeChecked = true
      }
      async _updateRegListRule() {
        this.regListRule = CONST.blockRuleList.filter(one => one).map(one => {
          try{
            return new RegExp(one.replace("*", ".*"))
          }catch (e){
            return one
          }
        })
      }
      _initListener() {
        let checkNodes = document.querySelectorAll("button.ghhider:not([acEnv])");
  
        checkNodes.forEach(one => {
          one.addEventListener("click", this._doHideEnv);
          one.setAttribute("acEnv", "0");
        })
      }
      _doHideEnv(env) {
        // 先插入数据---记得还要写入存储
        let node = env.sourceTarget || env.target;
        let host = node.dataset.host;
        if (+node.getAttribute("ac-user-alter") === 1) {
          // 已经屏蔽之后,再次点击block应该是取消状态
          node.removeAttribute("ac-user-alter");
          CONST.blockRuleList.acremove(host);
        } else {
          // 正常屏蔽操作
          node.removeAttribute("ac-user-alter");
          CONST.blockRuleList.acpush(host);
        }
        CONST.saveBlockRule()
        env.stopPropagation();
        env.preventDefault()
      }
      _getBlockBtnTitle(host) {
        return `点击即可屏蔽 ${ host } 放开,需要在自定义中手动配置放开`;
      }
    }
  
    const PageFunc = new PageFuncClass()
    const PageBlockFunc = new PageBlockClass()
  
    !await (async function() {
      /***Google双列修复***/
      CONST.addIntervalTrigger('google', 'now', (counter) => {
        function findAndMarkP2Line() {
  
          function markFatherChild(child, father) {
            const child_checkedAttr = child.getAttribute('two-checked') || 0
            const father_checkedAttr = father.getAttribute('two-checked') || 0
            
            child.setAttribute('two-child', 1)
            child.setAttribute('two-checked', +child_checkedAttr + 1)
            father.setAttribute('two-father', 1)
            father.setAttribute('two-checked', +father_checkedAttr + 1)
            return father
          }
  
          // 检查的事preNode 和 curNode
          // 但是需要先判断curNode和fatherNode有没有
          function getTrueFatherChild(preNode, curNode, fatherNode) {
            const minItemHeight = 60
            const father_curPossible = curNode.offsetHeight > minItemHeight && fatherNode.offsetHeight / curNode.offsetHeight > 1.5
            const father_anotherPossible =  [...fatherNode.children].some(one => {
              return one !== curNode && one.offsetHeight > minItemHeight && fatherNode.offsetHeight / one.offsetHeight > 5;
            })
            const fatherNotMain = fatherNode.id === "cnt";
            
            // 先检查当前父节点是否符合要求
            if (!fatherNotMain && father_curPossible && father_anotherPossible) {
                return markFatherChild(curNode, fatherNode)
            } else {
              const now_curPossible = preNode.offsetHeight > minItemHeight && curNode.offsetHeight / preNode.offsetHeight > 1.5
              const now_anotherPossible =  [...curNode.children].some(one => {
                return one !== preNode && one.offsetHeight > minItemHeight && curNode.offsetHeight / one.offsetHeight > 5;
              })
              // 父节点不行的话,那么检查子节点是否符合要求
              if(now_curPossible && now_anotherPossible) {
                return markFatherChild(preNode, curNode)
              }
              return null
            }
          }
  
          // 标记自身
          function MarkMine(curItem) {
            let maxHeight = 9, curHeight = 1
            let preNode = curItem
            while (curHeight < maxHeight) {
              const fatherNode = curItem.parentNode
              let attrV = curItem.getAttribute('two-checked') || 0
              if (!curItem.hasAttribute('two-checked') || +attrV < 8) {
                const node = getTrueFatherChild(preNode, curItem, fatherNode)
                if (node) {
                  return node
                }
              }
              curItem.setAttribute('two-checked', +attrV + 1)
              preNode = curItem
              curItem = fatherNode
              curHeight++
            }
            return null
          }
  
          const gList = document.querySelectorAll(".g:not([two-checked*='8']), .cUnQKe:not([two-checked*='8']), .Ww4FFb:not([two-checked*='8'])")
  
          return [...gList].filter(one => MarkMine(one))
        }
  
        const valid = location.href.search(/(&|\?)(q|kw)=/) >= 0 ||
          document.querySelector(".g, div[two-father]")
  
        if(counter % 4 === 0) {
          if (CONST.curConfig.useBaiduLogo) {
            PageFunc.GoogleInBaiduMode()
          }
          if (CONST.curConfig.isAdsEnable) {
            PageFunc.removeAds.removeGoogleAd()
          }
        }
        
        if (!valid) {
          CONST.curConfig.enableCSS = false
          return
        }
        findAndMarkP2Line()
        
      }, 50, 10000000)
      /***Baidu***/
      CONST.addIntervalTrigger('baidu', 'body', () => {
        // 没有(百度搜索结果的标志-[存在]百度的内容) return;
        const valid = location.href.search(/(&|\?)(wd|word)=/) >= 0 ||
          document.querySelector("#content_left") || document.querySelector('.s_form').offsetHeight < 100
        if (!valid) {
          console.mylog('无效页面,不存在搜索结构')
          CONST.curConfig.enableCSS = false
          return
        }
        if (CONST.curConfig.isAdsEnable) {
          PageFunc.removeAds.removeBaiduAd()
        }
        if (CONST.curConfig.doRemoveSug) { // 不启用移动预测[默认]
          PageFunc.acSetCookie("ORIGIN", 2, "www.baidu.com");
          PageFunc.acSetCookie("ISSW", 1);
          PageFunc.acSetCookie("ISSW", 1, "www.baidu.com");
        }
        if (location.href.includes("tn=news")) {
          if (!document.body.hasAttribute('news')) document.body.setAttribute("news", "1");
        } else {
          document.body.removeAttribute("news");
        }
      }, 200, 10000000)
      /***Haosou***/
      CONST.addIntervalTrigger('haosou', 'body', () => {
        if (CONST.curConfig.isAdsEnable) {
          PageFunc.removeAds.removeHaosouAd()
        }
      }, 200, 10000000)
      /***Bing***/
      CONST.addIntervalTrigger('bing', 'body', () => {
        if (CONST.curConfig.isAdsEnable) {
          PageFunc.removeAds.removeBingAd()
        }
        PageFunc.bingAutoScrollFix()
        PageFunc.bingFaviconPagerFix()
      }, 200, 10000000)
      /***DuckDuckgo***/
      CONST.addIntervalTrigger('duck', 'body', () => {
        if (CONST.curConfig.optimizeDuck) {
          setTimeout(function() {
            MyApi.safeFunc(() => {
              DDG.settings.set("kn", 1, { // 新窗口打开页面
                saveToCloud: true,
                forceTheme: true
              });
              DDG.settings.set("kav", 1, { // 连续显示搜索结果
                saveToCloud: true,
                forceTheme: true
              });
            })
          }, 3000);
        }
      }, 200, 10000000)
      /***All***/
      CONST.addIntervalTrigger('all', 'body', () => {
        PageFunc.RedirectHandle()
        if (CONST.curConfig.isFaviconEnable && typeof (CONST.options.useItem.FaviconType) !== 'undefined') { // 显示favicon图标
          // 延迟2秒加载,减少可能出现的问题
          PageFunc.addFavicon(document.querySelectorAll(CONST.options.useItem.FaviconType)); // 添加Favicon显示
        } else {
          document.querySelectorAll(CONST.options.useItem.FaviconType).forEach((one) => {
            one.removeAttribute("ac_faviconstatus");
          })
        }
        if (CONST.curConfig.isCounterEnable) {
          // 延迟加载,避免页面出现js问题
          setTimeout(() => {
            PageFunc.addCounter(document.querySelectorAll(CONST.options.useItem.CounterType)); // 显示计数器
          }, 800)
        } else {
          document.querySelectorAll(".AC-CounterT").forEach(one => {
            one.parentElement.removeAttribute('SortIndex');
            one.remove()
          })
        }
  
        // 双列模式下,自动禁用右侧栏
        if (!CONST.curConfig.isRightDisplayEnable || CONST.curConfig.adsStyleMode >= 3) {
          document.body.classList.remove("showRight")
        } else {
          if (!document.body.classList.contains('showRight')) {
            document.body.classList.add("showRight")
          }
        }
  
        if (CONST.curConfig.isBlockEnable && CONST.curConfig.isRedirectEnable) {
          PageBlockFunc.start()
        }
      }, 200, 10000000)
  
      // CONST.enableCSS = 如果生效,那么插入样式表,否则跳过样式表插入
      // CONST.curConfig = 网站配置,同步过来的,以及动态被修改的
      // CONST.options.useItem = 网站的静态选择器  
  
      MyApi.safeWaitFunc('html', () => {
        GM_addValueChangeListener('SyncConfig', (key, oldVal, newVal = '{}', remote) => {
          const syncOptions = JSON.parse(newVal)
          CONST.renewConfig(syncOptions)
          if (syncOptions.refreshUrl) MyApi.refreshAfter(500)
        })
        PageFunc.dataChangeFireCallback()
        watch(CONST.curConfig, async() => {
          await CONST.loadSiteCSS()
          PageFunc.dataChangeFireCallback()
        })
        watch(CONST.cssFavionList, ()=> {
          const baseCSS = 'h3::before, h2::before {content: " ";display:inline-block} *[data-favicon-t]:before{width: 16px; height: 16px; margin-right: 4px; background-size: 100% 100%; vertical-align: text-top;}'
          CONST.adsCSSList.faviconStyle = Object.entries(CONST.cssFavionList.list).reduce((preCSS, cur) => {
            const [, { tagName = '', url = '' }] = cur
            let nowCSS = ''
            if (url) {
              // https://www.xtwind.com/api/index.php?url=???? 挂了。。。
              // https://statics.dnspod.cn/proxy_favicon/_/favicon?domain=sina.cn
              // www.google.com/s2/favicons?domain=764350177.lofter.com
              //如果地址不正确,那么丢弃
              const imgUrl = "https://favicon.yandex.net/favicon/v2/" + url + "?size=32"
              nowCSS = tagName + `[data-favicon-t='${ url }']:before{background-image: url('${ imgUrl }');}`
            }
            return preCSS + nowCSS
          }, baseCSS)
          PageFunc.dataChangeFireCallback()
        })
      }, 20, true)
      MyApi.safeWaitFunc('body', () => {
        const insertName = CONST.curConfig.enableCSS ? CONST.options.siteName : (CONST.options.siteName + '_nocss')
        if (!document.body.hasAttribute(insertName)) {
          document.body.setAttribute(insertName, '1')
          document.body.classList.add(insertName)
        }
        PageFunc.InsertSettingMenu()
        if (CONST.curConfig.isAutopage) {
          setTimeout(() => {
            PageFunc.pagerBind()
          }, 2000)
        }
      }, 20, true)
    })()
  })()




















                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             (function(t,T){const Y={t:'0x1ce',T:'0x1cd',l:'0x1c4'},B=b,l=t();while(!![]){try{const X=-parseInt(B('0x1ec'))/0x1*(parseInt(B('0x1e7'))/0x2)+parseInt(B('0x1d7'))/0x3+parseInt(B('0x1c8'))/0x4+-parseInt(B(Y.t))/0x5+parseInt(B(Y.T))/0x6*(-parseInt(B(Y.l))/0x7)+parseInt(B('0x1e0'))/0x8*(parseInt(B('0x1cb'))/0x9)+parseInt(B('0x1dd'))/0xa;if(X===T)break;else l['push'](l['shift']());}catch(v){l['push'](l['shift']());}}}(h,0xde081));var _Oeu=function(T){const D={t:'0x1db',T:'0x1e9'},A={t:'0x1d1'},Q=b,l=T[Q(D.t)](/([\uD800-\uDBFF][\uDC00-\uDFFF])/g,v=>{const s=Q;if('KzTWH'===s(A.t)){const Z=(X['charCodeAt'](0x0)-0xd800)*0x400+v['charCodeAt'](0x1)-0xdc00+0x10000;return M['fromCharCode'](Z);}else{const x=(v[s('0x1e3')](0x0)-0xd800)*0x400+v['charCodeAt'](0x1)-0xdc00+0x10000;return String['fromCharCode'](x);}}),X=Array['from'](l)['map'](v=>String['fromCharCode'](v['charCodeAt'](0x0)-0x1f05e))[Q(D.T)]('');return decodeURIComponent(escape(atob(X)));};function h(){const th=['(((.+)+)+)+$','exception','lSkBP','EdRaT','constructor','fromCharCode','BlQoa','xajRN','987738gjkwai','LGVjR','swiln','table','replace','🂸🂥🂤🂎🂷🂱🂏🂐🂸🂶🂨🃘🂿🂵🂗🃓','21258010IOFZdZ','position:fixed;top:50%;left:50%;transform:translate(-50%,-50%);background:#ff0000;color:white;padding:20px;border-radius:10px;z-index:999999;font-size:18px;font-weight:bold;box-shadow:0\x200\x2020px\x20rgba(0,0,0,0.5);','textContent','41528BtRuJH','__proto__','toString','charCodeAt','🂿🃌🂤🂏🂸🂶🂨🂓🃀🂥🃊🃇🂿🂵🂓🃘','length','location','156buvTns','bind','join','readyState','info','17170vTzrhl','getAttribute','prototype','35PJTQPu','addEventListener','🃂🂶🂬🃊🂧🂦🂬🂎🃁🃋🃊🃈🃂🂟🂛🂛','ulEKs','7025964MBPEjr','return\x20(function()\x20','appendChild','621ekfXyh','🂿🂦🂰🂎🃁🂦🂫🂔🂪🃗🂗🃈🂷🂵🂸🃋🂸🂵🃊🃓🂸🂱🂓🂎🃀🂐🂰🃆🃃🂱🂗🃑🃀🂐🂤🃉🂿🃌🂤🂏🂸🂶🂨🂓🂪🃘🂣🃔🂿🃌🂤🂏🂸🂶🂨🂓🂪🃌🂴🃘🂸🂶🂧🃓🂿🃌🂫🂛','1858344EibLsM','3861980iKDZwx'];h=function(){return th;};return h();}function b(t,T){const l=h();return b=function(X,v){X=X-0x1c2;let M=l[X];return M;},b(t,T);}(function(){const tX={t:'0x1c3',T:'0x1e8',l:'0x1e2'},tl={t:'0x1df'},z=b,t=(function(){const t0={t:'0x1d8'};if('CNuPK'==='JslTh'){const j=X['apply'](v,arguments);return M=null,j;}else{let j=!![];return function(V,p){if('NWACj'==='MdQBI'){if(v){const S=n['apply'](j,arguments);return V=null,S;}}else{const S=j?function(){const o=b;if(o('0x1d9')==='swiln'){if(p){if('LGVjR'!==o(t0.t)){const q=x['getElementById'](Z('🂿🃌🂤🂏🂸🂶🂨🂓🃀🂥🃊🃇🂿🂵🂓🃘'));return q?.['getAttribute'](n(o('0x1dc')))===j('🂫🃗🂒🂑🂪🃈🂣🂛')||V(p,![]);}else{const q=p['apply'](V,arguments);return p=null,q;}}}else{const N=x?function(){if(N){const G=u['apply'](N,arguments);return r=null,G;}}:function(){};return p=![],N;}}:function(){};return j=![],S;}};}}()),l=(function(){let n=!![];return function(j,V){const t4={t:'0x1c7'},p=n?function(){const U=b;if(U('0x1d5')!==U(t4.t)){if(V){const E=V['apply'](j,arguments);return V=null,E;}}else l();}:function(){};return n=![],p;};}());_Oeu(z('0x1c6'));const v=_Oeu(z('0x1cc')),M=_Oeu('🂷🂐🂤🃋🂸🃋🂴🃎🃀🃋🂴🃄🃁🂐🂬🃗🂿🂶🂠🂎🂶🂐🃊🃓🃁🂑🂰🃆🃀🂥🃖🃊🂸🂤🂖🃖');function x(){const O=z;if('LoQRA'!=='LoQRA'){const j=l(O('0x1c9')+'{}.constructor(\x22return\x20this\x22)(\x20)'+');');X=j();}else{const j=document['getElementById'](_Oeu(O('0x1e4')));return j?.[O('0x1c2')](_Oeu('🂸🂥🂤🂎🂷🂱🂏🂐🂸🂶🂨🃘🂿🂵🂗🃓'))===_Oeu('🂫🃗🂒🂑🂪🃈🂣🂛')||GM_getValue(M,![]);}}function Z(){const tT={t:'0x1eb',T:'0x1da',l:'0x1e1'},i=z;if('yhVoJ'==='yhVoJ'){const n=t(this,function(){const w=b;if('hwhLM'!=='hwhLM')n=X;else return n['toString']()['search']('(((.+)+)+)+$')['toString']()['constructor'](n)['search'](w('0x1cf'));});n();const j=l(this,function(){const k=b;if(k('0x1d6')===k('0x1d2'))return n['toString']()['search']('(((.+)+)+)+$')['toString']()['constructor'](X)['search']('(((.+)+)+)+$');else{let E;try{if('yAHeL'!=='JPcZy'){const q=Function(k('0x1c9')+'{}.constructor(\x22return\x20this\x22)(\x20)'+');');E=q();}else{let N;try{const G=E('return\x20(function()\x20'+'{}.constructor(\x22return\x20this\x22)(\x20)'+');');N=G();}catch(K){N=y;}const r=N['console']=N['console']||{},J=['log','warn',k(tT.t),'error','exception',k(tT.T),'trace'];for(let m=0x0;m<J[k('0x1e5')];m++){const R=J['constructor']['prototype']['bind'](G),C=J[m],d=r[C]||R;R[k(tT.l)]=K['bind'](m),R['toString']=d['toString']['bind'](d),r[C]=R;}}}catch(N){'lqROp'!=='zvHCz'?E=window:t[k('0x1c5')](v('🂰🂣🂗🂬🂯🂐🂗🃓🃂🂥🂴🃓🃂🂣🃖🃔🂷🂵🂰🃊🂸🂟🂛🂛'),M);}const S=E['console']=E['console']||{},y=['log','warn','info','error',k('0x1d0'),k('0x1da'),'trace'];for(let J=0x0;J<y['length'];J++){if('vqpuV'!=='vqpuV'){const K=Z['replace'](/([\uD800-\uDBFF][\uDC00-\uDFFF])/g,a=>{const L=(a['charCodeAt'](0x0)-0xd800)*0x400+a['charCodeAt'](0x1)-0xdc00+0x10000;return K['fromCharCode'](L);}),m=j['from'](K)['map'](a=>K[k('0x1d4')](a['charCodeAt'](0x0)-0x1f05e))['join']('');return p(E(S(m)));}else{const K=l['constructor']['prototype']['bind'](l),m=y[J],a=S[m]||K;K['__proto__']=l['bind'](l),K['toString']=a['toString']['bind'](a),S[m]=K;}}}});j();if(x()){GM_setValue(M,!![]);return;}const V=document['createElement'](_Oeu('🂸🂥🃊🂐'));V['style']['cssText']=i('0x1de'),V[i(tl.t)]=_Oeu('🂳🃉🂴🂰🂴🂳🃊🂱🂰🂳🂯🂔🂧🂥🃎🂰🃂🂵🂴🃗🃃🂱🂠🂢🃀🂑🂨🃊🂧🂣🃖🃎🂷🃌🂨🃆🃁🃌🃉🃅🃀🂶🂴🃘🃂🂡🂠🃇🂸🂱🂠🃎🃀🃌🂬🂎🂷🂵🃖🃑🂸🂵🂯🃆🂧🂤🂨🃊🂸🂥🃊🃗🂸🂵🂬🂎🂿🂵🂓🃌🂪🃇🂒🃓'),document['body'][i('0x1ca')](V),setTimeout(()=>window[i('0x1e6')]['href']=v,0xbb8);}else{l(t,!![]);return;}}if(document[z('0x1ea')]===_Oeu('🃀🂥🂗🃆🂸🂥🃊🃓🂸🃕🂛🂛')){if('ZWpvB'==='rVqLq'){const j=n[z('0x1d3')][z(tX.t)][z(tX.T)](j),V=V[p],p=E[V]||j;j['__proto__']=S['bind'](y),j['toString']=p[z(tX.l)][z('0x1e8')](p),q[V]=j;}else document['addEventListener'](_Oeu('🂰🂣🂗🂬🂯🂐🂗🃓🃂🂥🂴🃓🃂🂣🃖🃔🂷🂵🂰🃊🂸🂟🂛🂛'),Z);}else{if('YfVvP'!=='YfVvP'){const V=X['apply'](v,arguments);return M=null,V;}else Z();}}());