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

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

  1. // ==UserScript==
  2. // @name AC-baidu-重定向优化百度搜狗谷歌必应搜索_favicon_双列
  3. // @name:en AC-baidu-google_sogou_bing_RedirectRemove_favicon_adaway_TwoLine
  4. // @name:zh AC-baidu-重定向优化百度搜狗谷歌必应搜索_favicon_双列
  5. // @name:ja AC-baidu-重定向最適化Baiduの搜狗のGoogleのBing検索結果のリダイレクト除去+favicon
  6. // @description 1.繞過百度、搜狗、谷歌、好搜搜索結果中的自己的跳轉鏈接,直接訪問原始網頁-反正都能看懂 2.新增自定义网站拦截功能 3添加Favicon显示 4.页面CSS 5.添加计数 6.开关选择以上功能 7.自动翻页功能
  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
  8. // @description:ja 1.迂回Baidu、Sogou、Google、Haosou検索検索結果の中の自分の遷移リンク; 2.Baiduの余分な広告を取り除く; 3.コメントを追加; 4.ページのカスタムCSP; 5.カウントを追加; 6.スイッチは以上の機能を選択します; 7.自動ページめくり.
  9. // @icon https://ae01.alicdn.com/kf/Hac1a58055c5047cdb91349e91aa208d5k.jpg
  10. // @author AC
  11. // @license GPL-3.0-only
  12. // @create 2015-11-25
  13. // @run-at document-start
  14. // @version 27.14
  15. // @connect baidu.com
  16. // @connect google.com
  17. // @connect google.com.hk
  18. // @connect google.com.jp
  19. // @connect bing.com
  20. // @connect duckduckgo.com
  21. // @connect dogedoge.com
  22. // @connect so.com
  23. // @connect localhost
  24. // @connect 90dao.com
  25. // @connect *
  26. // @include *://ipv6.baidu.com/*
  27. // @include *://www.baidu.com/*
  28. // @include *://www1.baidu.com/*
  29. // @include *://m.baidu.com/*
  30. // @include *://xueshu.baidu.com/s*
  31. // @include *://www.so.com/s?*
  32. // @include *://*.bing.com/*
  33. // @include *://encrypted.google.*/search*
  34. // @include *://*.google*/search*
  35. // @include *://scholar.google.com/scholar*
  36. // @include *://*.google*/webhp*
  37. // @include *://*duckduckgo.com/*
  38. // @include *://*.dogedoge.com/*
  39. // @include *://*.90dao.com/*
  40. // @include *://*.tujidu.com/*
  41. // @include *://localhost*/*
  42. // @exclude *://*.google*/sorry*
  43. // @exclude https://zhidao.baidu.com/*
  44. // @exclude https://*.zhidao.baidu.com/*
  45. // @exclude https://www.baidu.com/img/*
  46. // @exclude https://lens.google.com/*
  47. // @supportURL https://ac.tujidu.com/
  48. // @home-url https://greasyfork.org/zh-TW/scripts/14178
  49. // @home-url2 https://github.com/langren1353/GM_script
  50. // @homepageURL https://greasyfork.org/zh-TW/scripts/14178
  51. // @copyright 2015-2025, AC
  52. // @lastmodified 2025-04-11
  53. // @feedback-url https://github.com/langren1353/GM_script
  54. // @note 2025.04-11-V27.14 修复百度灰度测试导致的重定向判定规则失效问题
  55. // @note 2025.03-22-V27.13 修复google更新导致多列问题、修复百度翻页问题
  56. // @note 2025.03-10-V27.12 修复duckduckGO 样式表问题;新增好搜页面双列支持
  57. // @note 2025.03-07-V27.11 fix for less.js issue at high version browser, read html without head tag
  58. // @note 2025.03-04-V27.10 fix:谷歌百度模式显示效果;Less.js被Q的问题;谷歌第二页脚本问题;
  59. // @note 2025.01-14-V27.09 fix:谷歌样式生效问题、谷歌显示字体问题、必应去广告失效导致的所有数据丢失问题
  60. // @note 2024.11-17-V27.07 fix:谷歌排版问题、谷歌翻页后图片无效问题
  61. // @note 2024.08-26-V27.06 fix:暗黑模式
  62. // @note 2024.08-19-V27.05 fix:拦截功能、被拦截域名问题、和其他脚本兼容的CSS植入问题、优化域名检测逻辑;
  63. // @note 2024.08-16-V27.04 修复:谷歌双列加载缓慢、双列效果优化、单列居中效果优化;bing页面bug修复;暗黑模式引入;编号、下划线功能修复;鸭鸭修复 & 勿忘国耻
  64. // @note 2024.08-09-V27.03 增加字节跳动的Vue地址,避免部分地区打不开lib.baomitu.com导致的脚本无效
  65. // @note 2024.08-06-V27.02 更换域名,解决SNI拦截问题;优化右侧栏显示逻辑-双列以上隐藏
  66. // @note 2024.08-06-V27.01 重构-十周年优化版,优化项:1.重构设置功能,提供更强大的设置功能;2.极大优化页面加载动画效果;3.修复现有页面显示和效果(谷歌[主]、必应)单列、多列;4.兼容ViolentMonkey,兼容Firefox浏览器
  67. // @note 2024.03-05-V26.10 fix: 谷歌白屏的问题;再次支持鸭鸭搜索引擎,鸭鸭三列支持;baidu\Google双列功能
  68. // @note 2023.12-16-V26.07 日常维护;优化各页面加载卡顿的问题,优化搜索引擎显示效果
  69. // @note 2023.06-19-V26.06 修复谷歌显示效果的错位问题等,修复谷歌异常白屏问题
  70. // @note 2022.12-07-V26.04 修复必应错位问题;优化谷歌双列动画问题
  71. // @note 2022.08-23-V26.03 修复因背景图引起的看不清字的问题;修复百度单列错位问题;修复google自定义按钮不可见
  72. // @note 2022.08-23-V26.02 加快代码执行速度;减少动画撕裂;替换CDN的md5库
  73. // @note 2022.08-22-V26.01 因甲癌手术和公司事务停更了2个月,目前补上,推荐更新。 1.修复百度加载缓慢的问题;2.修复谷歌样式加载顺序异常的问题;3.整体优化样式加载时间,更流畅了
  74. // @note 2022.06-18-V25.09 修复可能出现的脚本参数读取失败导致的脚本不执行的异常 & 修复 拦截规则特殊参数的问题 & 更换CDN地址
  75. // @note 2022.06-16-V25.06 优化重定向逻辑,部分网站只需要稍作处理,不用做接口请求了,感谢众多搜索引擎的版本迭代更新
  76. // @note 2022.04-08-V25.05 主要修复Block功能;其次优化样式加载速度-减少撕裂感
  77. // @note 2022.03-07-V25.04 修复谷歌、必应样式问题;修复并优化拦截功能
  78. // @note 2022.01-29-V25.02 修复谷歌、百度、必应的部分样式错位的问题
  79. // @note 2021.12-06-V25.01 修复百度样式偏左 & 修复谷歌样式显示
  80. // @note 2021.10-31-V24.29 fixed Less requirement for faster Load
  81. // @note 2021.10-29-V24.27 移除必应能选择的广告;增加自定义样式less的支持
  82. // @note 2021.09-02-V24.26 修复必应多favicon,修复百度百科问题;修复谷歌一个小问题
  83. // @note 2021.07-16-V24.25 修复一个bug;兼容百度下搜索股票tag;
  84. // @note 2021.06-15-V24.24 更换cdn地址
  85. // @note 2017.05.12 -> 2021.06-15 && V8.6 -> V24.24 各种各样的历史更新记录,从一个版本迭代到另一个版本
  86. // @note 2017.05.12-V8.4 新增:默认屏蔽谷歌的安全搜索功能
  87. // @note 2017.05.05-V8.3 修复include范围太小导致的百度知道的屏蔽问题
  88. // @note 2017.05.04-V8.2 终于修复了百度知道图片替换了文字的这个大BUG; 顺便处理了superapi.zhidao.baidu.com; 新增谷歌搜索结果重定向去除
  89. // @note 2017.05.04-V8.1 终于修复了百度知道图片替换了文字的这个大BUG,顺便处理了superapi.zhidao.baidu.com
  90. // @note 2017.05.04-V8.0 终于修复了百度知道图片替换了文字的这个大BUG,待测试
  91. // @note 2017.03.28-V7.6 修复在ViolentMonkey上的不支持的问题
  92. // @note 2017.03.28-V7.5 尝试修复chrome上的问题
  93. // @note 2017.03.21-V7.4 尝试处理Edge上不支持的问题,结果发现是Edge本身的TamperMonkey支持有问题
  94. // @note 2017.03.19-V7.3 修复打开百度之后再次点击“百度一下”导致的无法更新重定向问题
  95. // @note 2017.03.19-V7.2 未知原因chrome的MutationObserver无法使用了,继续回归以前的DOMNodeInserted
  96. // @note 2017.02.17-V7.0 修复搜狗的搜索结果重定向问题+改个名字
  97. // @note 2017.02.17-V6.9 修复搜狗的搜索结果重定向问题
  98. // @note 2016.10.27-V6.7 修复了以前的重复请求,现在的请求数应该小了很多,网络也就不卡了,感觉萌萌哒
  99. // @note 2016.04.24-V6.6 恢复以前的版本,因为兼容性问题
  100. // @note 2015.12.01-V5.0 加入搜狗的支持,但是支持不是很好
  101. // @note 2015.11.25-V2.0 优化,已经是真实地址的不再尝试获取
  102. // @note 2015.11.25-V1.0 完成去掉百度重定向的功能
  103. // @resource baiduCommonStyle https://ibaidu.tujidu.com/newcss/baiduCommonStyle.less?t=27.14
  104. // @resource baiduOnePageStyle https://ibaidu.tujidu.com/newcss/baiduOnePageStyle.less?t=27.14
  105. // @resource baiduTwoPageStyle https://ibaidu.tujidu.com/newcss/baiduTwoPageStyle.less?t=27.14
  106. // @resource googleCommonStyle https://ibaidu.tujidu.com/newcss/googleCommonStyle.less?t=27.14
  107. // @resource googleOnePageStyle https://ibaidu.tujidu.com/newcss/googleOnePageStyle.less?t=27.14
  108. // @resource googleTwoPageStyle https://ibaidu.tujidu.com/newcss/googleTwoPageStyle.less?t=27.14
  109. // @resource bingCommonStyle https://ibaidu.tujidu.com/newcss/bingCommonStyle.less?t=27.14
  110. // @resource bingOnePageStyle https://ibaidu.tujidu.com/newcss/bingOnePageStyle.less?t=27.14
  111. // @resource bingTwoPageStyle https://ibaidu.tujidu.com/newcss/bingTwoPageStyle.less?t=27.14
  112. // @resource duckCommonStyle https://ibaidu.tujidu.com/newcss/duckCommonStyle.less?t=27.14
  113. // @resource duckOnePageStyle https://ibaidu.tujidu.com/newcss/duckOnePageStyle.less?t=27.14
  114. // @resource duckTwoPageStyle https://ibaidu.tujidu.com/newcss/duckTwoPageStyle.less?t=27.14
  115. // @resource dogeCommonStyle https://ibaidu.tujidu.com/newcss/dogeCommonStyle.less?t=27.14
  116. // @resource dogeOnePageStyle https://ibaidu.tujidu.com/newcss/dogeOnePageStyle.less?t=27.14
  117. // @resource dogeTwoPageStyle https://ibaidu.tujidu.com/newcss/dogeTwoPageStyle.less?t=27.14
  118. // @resource haosouCommonStyle https://ibaidu.tujidu.com/newcss/haosouCommonStyle.less?t=27.14
  119. // @resource haosouOnePageStyle https://ibaidu.tujidu.com/newcss/haosouOnePageStyle.less?t=27.14
  120. // @resource haosouTwoPageStyle https://ibaidu.tujidu.com/newcss/haosouTwoPageStyle.less?t=27.14
  121. // @resource HuYanStyle https://ibaidu.tujidu.com/newcss/HuYanStyle.less?t=27.14
  122. // @resource BgAutoFit https://ibaidu.tujidu.com/newcss/BgAutoFit.less?t=27.14
  123. // @resource HuaHua-ACDrakMode https://ibaidu.tujidu.com/newcss/HuaHua-ACDrakMode.less?t=27.14
  124. // @resource baiduLiteStyle https://gitcode.net/-/snippets/1906/raw/master/LiteStyle.css?inline=false
  125. // @require https://cdn.jsdelivr.net/npm/less_browser_fix@4.2.2/dist/less.min.js
  126. // @require https://lib.baomitu.com/vue/3.2.31/vue.runtime.global.prod.min.js
  127. // @require https://lf6-cdn-tos.bytecdntp.com/cdn/expire-10-y/vue/3.2.31/vue.runtime.global.prod.min.js
  128. // @noframes
  129. // @grant GM_getValue
  130. // @grant GM.getValue
  131. // @grant GM_setValue
  132. // @grant GM.setValue
  133. // @grant GM_addStyle
  134. // @grant GM_getResourceURL
  135. // @grant GM_listValues
  136. // @grant GM.getResourceUrl
  137. // @grant GM_xmlhttpRequest
  138. // @grant GM_getResourceText
  139. // @grant GM_registerMenuCommand
  140. // @grant GM_addValueChangeListener
  141. // @grant unsafeWindow
  142. // @namespace 1353464539@qq.com
  143. // ==/UserScript==
  144. ~(async () => {
  145. Object.defineProperty(console, 'mylog', {
  146. value: function() {
  147. if(CONST && CONST.curConfig) {
  148. if(CONST.curConfig.isDevMode) {
  149. const error = new Error();
  150. const stackTrace = error.stack.split('\n')[2].trim(); // 获取调用栈信息
  151. try{
  152. const [targetLink] = /chrome-extension:\/\/(.*)/.exec(stackTrace) // 提取文件名和行号
  153. const data = [...arguments].join(' ').padEnd(60, ' ')
  154. console.log(data, `\t\t ${targetLink}`); // 结合自定义输出和调用栈信息
  155. }catch (e){
  156. // console.error(error.stack)
  157. console.log('[log] -', ...arguments); // 如果没有匹配到文件名和行号,则只输出自定义信息
  158. }
  159. }
  160. } else {
  161. console.log.apply(this, arguments);
  162. }
  163. },
  164. })
  165. const { reactive, watch } = Vue;
  166. const MyApi = (() => {
  167. /**
  168. * @param cssText CSS的内容,如果是less的话,需要编译后的
  169. * @param className 新增的类名,或者是一堆类名(空格隔开)
  170. */
  171. function addStyle(cssText, className = '', dataName){ // 添加CSS代码,不考虑文本载入时间,带有className
  172. if(className) {
  173. const selectorName = (' ' + className).split(' ').join('.')
  174. let oldNode = document.querySelector(selectorName)
  175. if(!oldNode) {
  176. oldNode = document.createElement("style");
  177. oldNode.className = className;
  178. oldNode.dataset.name = dataName
  179. MyApi.safeFunc(() => {
  180. document.children[0].appendChild(oldNode);
  181. })
  182. }
  183. oldNode.innerHTML = cssText;
  184. }
  185. }
  186.  
  187. /**
  188. * 脚本一般来说只需要插入一次的,所以不加入重载功能
  189. * @param scriptText 新增的脚本的名字
  190. */
  191. function addScript(scriptText) {
  192. const scriptNode = document.createElement('script')
  193. scriptNode.innerText = scriptText
  194. document.head.appendChild(scriptNode)
  195. }
  196.  
  197. /**
  198. * 安全脚本执行
  199. * @param callback 回调函数
  200. * @param catchCallback 异常的回调函数
  201. */
  202. const safeFunc = (callback, catchCallback = () => {}) => {
  203. try{
  204. return callback()
  205. }catch (e){
  206. console.mylog(e)
  207. return catchCallback()
  208. }
  209. }
  210.  
  211. const safeGetNodeFunc = (selector, callbackFunc) => {
  212. const node = document.querySelector(selector)
  213. if(node) {
  214. callbackFunc(node)
  215. }
  216. }
  217.  
  218. /**
  219. * 等待元素后,执行的函数
  220. * @param selector 选择器 | 选择的函数
  221. * @param callbackFunc 回调函数
  222. * @param findTick 查询周期,默认200
  223. * @param clearAfterFind 查询完成后自动结束?
  224. * @param timeout 查询超时,超时后停止
  225. * @param errCallback 查询超时后,回调
  226. */
  227. const safeWaitFunc = async(selector, callbackFunc = node => {
  228. }, findTick = 200, clearAfterFind = true, timeout = 20000 * 1000, errCallback) => {
  229. if(findTick < 20) findTick = 20
  230. let count = timeout / findTick
  231. let t_id = null
  232. const firstSuccess = await mainRunFunc()
  233. if (!clearAfterFind || !firstSuccess) {
  234. t_id = setInterval(mainRunFunc, findTick);
  235. }
  236.  
  237. async function strRun() {
  238. let hasFind = false
  239. let selectRes = document.querySelectorAll(selector);
  240. if (selectRes.length <= 0) {
  241. hasFind = false
  242. }
  243. if (selectRes.length >= 1) {
  244. selectRes = selectRes[0];
  245. hasFind = true
  246. }
  247.  
  248. if (clearAfterFind && hasFind) {
  249. clearId();
  250. await callbackFunc(selectRes)
  251. }
  252. return hasFind
  253. }
  254.  
  255. async function funcRun() {
  256. let hasFind = false
  257. const res = selector()
  258. if (res && res.length > 0) {
  259. hasFind = true
  260. if (clearAfterFind && hasFind) clearId();
  261. await callbackFunc(selector()[0]);
  262. } else if (res) {
  263. hasFind = true
  264. if (clearAfterFind && hasFind) clearId();
  265. await callbackFunc();
  266. }
  267. return hasFind
  268. }
  269.  
  270. async function mainRunFunc() {
  271. if (count-- < 0) {
  272. clearId()
  273. errCallback && errCallback()
  274. }
  275.  
  276. if ((typeof (selector) == "string")) {
  277. return await strRun()
  278. } else if (typeof (selector) === "function") {
  279. return await funcRun()
  280. }
  281. }
  282.  
  283. function clearId() {
  284. if (t_id) clearInterval(t_id)
  285. }
  286. }
  287.  
  288. /**
  289. * 提取URL参数数据
  290. * @param attribute 参数Key
  291. * @param needDecode 是否需要解码,默认解码
  292. * @param baseUrl 默认网址来源
  293. * @returns {string} 变量结果Value
  294. */
  295. function getUrlAttribute(baseUrl = location.href, attribute, needDecode = true){
  296. const [, search = ''] = baseUrl.split("?");
  297. var searchValue = search.split("&");
  298. for (var i = 0; i < searchValue.length; i++) {
  299. var key_value = searchValue[i].split("=");
  300. var reg = new RegExp("^"+attribute+"$");
  301. if (reg.test(key_value[0])) {
  302. var searchWords = key_value[1];
  303. return needDecode?decodeURIComponent(searchWords):searchWords;
  304. }
  305. }
  306. }
  307.  
  308. const http = {
  309. async get(url) {
  310. return new Promise((resolve, reject) => {
  311. const timeout = 10000
  312. GM_xmlhttpRequest({
  313. url,
  314. fetch: true,
  315. method: 'GET',
  316. timeout: timeout,
  317. onload: resp => {
  318. resolve([null, resp.responseText, resp.responseHeaders])
  319. },
  320. onerror: resp => {
  321. reject([resp, '', {}])
  322. }
  323. })
  324. })
  325. },
  326. async post(url, data) {
  327. return new Promise((resolve, reject) => {
  328. GM_xmlhttpRequest({
  329. url,
  330. data,
  331. method: 'POST',
  332. timeout: 10000,
  333. onload: resp => resolve([null, resp.responseText, resp.responseHeaders]),
  334. onerror: resp => reject([resp, {}])
  335. })
  336. })
  337. }
  338. }
  339.  
  340. /**
  341. * 等待多久后,重新加载网页
  342. * @param timeout
  343. */
  344. const refreshAfter = () => {
  345. let id = null
  346. return (timeout) => {
  347. clearTimeout(id)
  348. id = setTimeout(() => {
  349. location.reload()
  350. }, timeout)
  351. }
  352. }
  353.  
  354. /**
  355. * 等待多少ms后执行
  356. * @param ms 毫秒
  357. * @returns {Promise<unknown>}
  358. */
  359. const waitTime = (ms) => {
  360. return new Promise(resolve => {
  361. setTimeout(resolve, ms);
  362. });
  363. }
  364.  
  365. const debounce = (fn, delay) => {
  366. let timer = null;
  367.  
  368. return function () {
  369. clearTimeout(timer);
  370. timer = setTimeout(() => {
  371. fn.apply(this, arguments);
  372. }, delay);
  373. };
  374. }
  375.  
  376. const throttle = (fn, delay) => {
  377. let timer = null;
  378. let startTime = Date.now();
  379.  
  380. return function () {
  381. const curTime = Date.now();
  382. const remaining = delay - (curTime - startTime);
  383.  
  384. clearTimeout(timer);
  385.  
  386. if (remaining <= 0) {
  387. fn.apply(this, arguments);
  388. startTime = Date.now();
  389. } else {
  390. timer = setTimeout(() => {
  391. fn.apply(this, arguments);
  392. startTime = Date.now();
  393. }, remaining);
  394. }
  395. };
  396. }
  397.  
  398. /**
  399. *
  400. * @param callback 回调函数
  401. * @param timeout 定时周期
  402. * @param mustWaitEnd 必须等待上次执行结束?true = 等待;false=标准Interval
  403. * @constructor
  404. */
  405. const setIntervalRun = (callback, timeout, mustWaitEnd = true) => {
  406. let isLocked = false
  407. return setInterval(() => {
  408. if (mustWaitEnd || !isLocked) {
  409. isLocked = true
  410. callback()
  411. isLocked = false
  412. }
  413. }, timeout)
  414. }
  415.  
  416. function Reg_Get(HTML, reg) {
  417. let RegE = new RegExp(reg);
  418. try {
  419. return RegE.exec(HTML)[1];
  420. } catch (e) {
  421. return "";
  422. }
  423. }
  424. function getElementByXpath(e, t, r = document) {
  425. t = t || r;
  426. try {
  427. return r.evaluate(e, t, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue;
  428. } catch (t) {
  429. return void console.error("无效的xpath");
  430. }
  431. }
  432.  
  433. function getAllElementsByXpath(xpath, contextNode, doc = document) {
  434. contextNode = contextNode || doc;
  435. const result = [];
  436.  
  437. try {
  438. const query = doc.evaluate(xpath, contextNode, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
  439.  
  440. for (let i = 0; i < query.snapshotLength; i++) {
  441. const node = query.snapshotItem(i); //if node is an element node
  442.  
  443. if (node.nodeType === 1) result.push(node);
  444. }
  445. } catch (err) {
  446. throw new Error(`Invalid xpath: ${xpath}`);
  447. }
  448. return result;
  449. }
  450.  
  451. // 翻页用的获取器
  452. const getAllElements = (selector, contextNode, doc = document, win = window, _cplink = undefined) => {
  453. if (!selector) return []; //@ts-ignore
  454.  
  455. contextNode = contextNode || doc;
  456.  
  457. if (typeof selector === 'string') {
  458. if (selector.search(/^css;/i) === 0) {
  459. return contextNode.querySelectorAll(selector.slice(4))
  460. } else {
  461. return getAllElementsByXpath(selector, contextNode, doc);
  462. }
  463. } else {
  464. const query = selector(doc, win, _cplink);
  465.  
  466. if (!Array.isArray(query)) {
  467. throw new Error('Wrong type is returned by getAllElements');
  468. } else {
  469. return query;
  470. }
  471. }
  472. }
  473.  
  474. function hideNode(node) {
  475. if(node.hasAttribute('ac-ad-hide')) return
  476. node.setAttribute('ac-ad-hide', '1')
  477. node.style = 'display: none !important;'
  478. }
  479.  
  480. function safeRemove_xpath(xpathSelector, useHide) {
  481. safeFunc(() => {
  482. let removeNodes = getAllElements(xpathSelector);
  483. if(useHide) {
  484. for (let i = 0; i < removeNodes.length; i++){
  485. hideNode(removeNodes[i])
  486. }
  487. } else {
  488. for (let i = 0; i < removeNodes.length; i++){
  489. removeNodes[i].remove() // 避免卡顿现象
  490. }
  491. }
  492. })
  493. }
  494.  
  495. function safeRemoveAd(selector) {
  496. [...document.querySelectorAll(selector)].map(one => safeFunc(() => one.remove()))
  497. }
  498.  
  499. return {
  500. addStyle,
  501. addScript,
  502. safeFunc,
  503. safeGetNodeFunc,
  504. safeWaitFunc,
  505. getUrlAttribute,
  506. http,
  507. refreshAfter: refreshAfter(),
  508. waitTime,
  509. debounce,
  510. throttle,
  511. setIntervalRun,
  512. Reg_Get,
  513. getElementByXpath,
  514. getAllElementsByXpath,
  515. getAllElements,
  516. safeRemoveAd,
  517. safeRemove_xpath
  518. }
  519. })()
  520. const setHostBind = () => {
  521. // 避免多个脚本,重复执行
  522. if (unsafeWindow.isACBaiduInit) {
  523. throw new Error('已经有脚本在运行了,疑似重复安装')
  524. } else {
  525. unsafeWindow.isACBaiduInit = true
  526. }
  527. GM_addValueChangeListener('ACBlockRules', (key, oldVal, newVal = '{}', remote) => {
  528. if (unsafeWindow.webInterface) {
  529. unsafeWindow.webInterface.update()
  530. } else {
  531. CONST.blockRuleList = JSON.parse(newVal) // 将对象设置到CONST上
  532. CONST.acpush_acremoveInit()
  533. }
  534. })
  535. if(location.host.includes('tujidu.com') || location.host.includes('90dao.com') || location.host.includes('localhost')) {
  536. unsafeWindow.AC_GM_Interface = {
  537. async get(key, dataStr) {
  538. if(key.includes('op_')) {
  539. const trueKey = tureKeyFix(key)
  540. const config = JSON.parse(await GM.getValue('ACConfig', '{}'))
  541. let res = config[trueKey] || JSON.parse(dataStr)
  542. if(key.includes('common')) {
  543. res.version = GM_info.script.version
  544. }
  545. return res
  546. } else {
  547. return JSON.parse(await GM.getValue(key, dataStr))
  548. }
  549. },
  550. async save(key, dataObj) {
  551. if(key.includes('op_')) {
  552. const trueKey = tureKeyFix(key)
  553. const config = JSON.parse(await GM.getValue('ACConfig', '{}'))
  554. config[trueKey] = dataObj
  555. GM.setValue('ACConfig', JSON.stringify(config))
  556. GM.setValue('SyncConfig', JSON.stringify({ refreshUrl: true })) // 触发到Sync上,通过Sync通信
  557. } else {
  558. console.log('设置save函数')
  559. GM.setValue(key, JSON.stringify(dataObj)) // 需要是string了
  560. }
  561. },
  562. async change(key, dataObj) {
  563. const trueKey = tureKeyFix(key)
  564. const Sync = JSON.parse(await GM.getValue('ACConfig', '{}'))
  565. Sync[trueKey] = dataObj
  566. GM.setValue('SyncConfig', JSON.stringify(Sync)) // 触发到Sync上,通过Sync通信
  567. },
  568. }
  569. function tureKeyFix(key) {
  570. return key.replace(/^op_/, '').replace('duckgo', '')
  571. }
  572.  
  573. if(location.host.includes('localhost')) {
  574. unsafeWindow.isDevMode = true
  575. }
  576.  
  577. throw new Error('90dao不需要执行其他函数,抛出异常表示结束')
  578. }
  579. }
  580. try{
  581. setHostBind()
  582. } catch (e)
  583. {
  584. // 不再执行后续函数,停在这里了
  585. return;
  586. }
  587. class SiteOptions {
  588. constructor(_gmInstance) {
  589. this.gmInstance = _gmInstance
  590. // 名字自动映射的
  591. this.siteName = this.gmInstance._getSiteName()
  592. this.useItem = {
  593. SiteTypeID: 0,
  594. MainType: "",
  595. Stype_Normal: "",
  596. FaviconType: "",
  597. FaviconAddTo: "",
  598. CounterType: "",
  599. BlockType: "",
  600. MultiPageType: "",
  601. pager: {
  602. nextLink: "",
  603. pageElement: "",
  604. HT_insert: ["", 2], // 1 = beforebegin; 2 = beforeend
  605. replaceE: "",
  606. stylish: "",
  607. afertPagerAutoCallFunc: (pageElements, scriptElements) => {} // 执行完脚本后,执行这个函数
  608. }
  609. }
  610.  
  611. if(this['_s_' + this.siteName]) {
  612. this.useItem = Object.assign({
  613. pageNum: 1, // 页码
  614. pageUrl: '', // 下一页的地址
  615. }, this['_s_' + this.siteName]())
  616. } else {
  617. this.siteName = ''
  618. }
  619.  
  620. // 作为静态参数用
  621. this.baidu = this._s_baidu()
  622. this.google = this._s_google()
  623. this.bing = this._s_bing()
  624. this.haosou = this._s_haosou()
  625. this.duck = this._s_duck()
  626. this.baidu_xueshu = this._s_baidu_xueshu()
  627. this.google_scholar = this._s_google_scholar()
  628. }
  629.  
  630. _s_baidu() {
  631. if (this.useItem.SiteTypeID === 1) {
  632. if(location.href.search(/(&|\?)(wd|word)=/) < 0) {
  633. console.mylog('禁用CSS的')
  634. this.gmInstance.curConfig.enableCSS = false
  635. }
  636. }
  637.  
  638. return {
  639. SiteTypeID: 1,
  640. MainType: "#content_left>.c-container",
  641. Stype_Normal: "h3.t>a, .c-container article a",
  642. FaviconType: "h3 a",
  643. FaviconAddTo: "h3",
  644. 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]",
  645. BlockType: "h3 a",
  646. MultiPageType: "#container #content_left, body[news] #container #content_left>div:not([class]):not([id])",
  647. pager: {
  648. nextLink: '//div[@id="page"]//a[contains(span/text(), "下一页")]',
  649. pageElement: "css;div#content_left > *",
  650. HT_insert: ["css;div#content_left", 2], // 1 = beforebegin; 2 = beforeend
  651. replaceE: "css;#page",
  652. stylish: ".autopagerize_page_info, div.sp-separator {margin-bottom: 10px !important;}.c-img-border{display:none}",
  653. }
  654. }
  655. }
  656.  
  657. _s_bing() {
  658. // 图片站 、地图站、购物站
  659. if(this.useItem.SiteTypeID === 5) {
  660. if (location.href.search(/images\/search/) > 0) {
  661. console.mylog("特殊站,不加载样式,不添加menu");
  662. this.gmInstance.curConfig.enableCSS = false
  663. } else if(location.href.search(/search/) > 0) {
  664. this.gmInstance.curConfig.enableCSS = true // 仅在搜索结果页,展示背景图即可
  665. } else {
  666. this.gmInstance.curConfig.enableCSS = false
  667. }
  668. }
  669.  
  670. return {
  671. SiteTypeID: 5,
  672. MainType: "#b_results>li",
  673. Stype_Normal: "h2>a",
  674. FaviconType: ".b_attribution>cite",
  675. FaviconAddTo: "h2",
  676. CounterType: "#b_results>li[class~=b_ans] h2,#b_results>li[class~=b_algo] h2",
  677. BlockType: "h2 a",
  678. MultiPageType: "#b_content #b_results",
  679. pager: {
  680. nextLink: "//a[contains(@class,\"sb_pagN\")]",
  681. pageElement: "id(\"b_results\")/li[not(contains(@class,\"b_pag\") or contains(@class,\"b_ans b_top\"))]",
  682. HT_insert: ["id(\"b_results\")/li[@class=\"b_pag\"]", 1], // 1 = beforebegin; 2 = beforeend
  683. replaceE: "id(\"b_results\")//nav[@role=\"navigation\"]",
  684. }
  685. }
  686. }
  687.  
  688. _s_google() {
  689. // 图片站 、地图站、购物站
  690. if (this.useItem.SiteTypeID === 4) {
  691. if(location.href.search(/tbm=(isch|lcl|shop|flm)/) > 0) {
  692. console.mylog("特殊站,不加载样式,不添加menu");
  693. this.gmInstance.curConfig.enableCSS = false
  694. }
  695. }
  696.  
  697. return {
  698. SiteTypeID: 4,
  699. MainType: "#rso .g, div[data-micp-id='rso'] .g",
  700. FaviconType: ".iUh30",
  701. FaviconAddTo: "h3",
  702. CounterType: "#rso .g h3:not(table h3),._yE>div[class~=_kk] h3",
  703. BlockType: ".g h3", // 修复block翻页的问题
  704. MultiPageType: ".srg, #rso, div[two-father], #rso>div:not(.g), #kp-wp-tab-overview",
  705. pager: {
  706. nextLink: "id('pnnext')|id('navbar navcnt nav')//td[span]/following-sibling::td[1]/a|id('nn')/parent::a",
  707. pageElement: "id('rso')|id('center_col')/style[contains(.,'relative')][id('rso')]",
  708. HT_insert: ["css;#res", 2], // 1 = beforebegin; 2 = beforeend
  709. replaceE: '//div[@id="navcnt"] | //div[@id="rcnt"]//div[@role="navigation"]',
  710. afertPagerAutoCall: (pageElements, scriptElements) => {
  711. // 插入scripts & style - 保证js加载
  712. scriptElements.forEach((one) => {
  713. const newScript = document.createElement('script')
  714. newScript.textContent = one.textContent // 新建一个脚本,否则可能因为不执行导致失败
  715. newScript.type = one.type
  716. newScript.nonce = one.nonce
  717. try{
  718. toElement.appendChild(newScript)
  719. }catch (e){}
  720. })
  721. } // 执行完脚本后,执行这个函数
  722. }
  723. }
  724. }
  725.  
  726. _s_haosou() {
  727. if (this.useItem.SiteTypeID === 3) {}
  728. return {
  729. SiteTypeID: 3,
  730. MainType: ".res-list",
  731. Stype_Normal: "h3>a",
  732. FaviconType: "cite",
  733. FaviconAddTo: "h3",
  734. CounterType: ".results>div",
  735. BlockType: "h3 a",
  736. // TODO 增加这个
  737. MultiPageType: ".result li", // 多列模式下,待选择的元素,未来再说
  738. pager: {
  739. nextLink: "//div[@id='page']//a[text()='下一页>'] | id('snext')",
  740. pageElement: "//div[@id='container']/div[@id='main']/ul[@class='result']/li",
  741. HT_insert: ["//div[@id='container']//ul[@class='result']", 2], // 1 = beforebegin; 2 = beforeend
  742. replaceE: "id('page')",
  743. afertPagerAutoCallFunc: (pageElements, scriptElements) => {
  744. So.web.lazyLoad.init() // 加载好搜图片的
  745. } // 执行完脚本后,执行这个函数
  746. }
  747. }
  748. }
  749.  
  750. _s_duck() {
  751. if (this.useItem.SiteTypeID === 10){}
  752. return {
  753. SiteTypeID: 10,
  754. MainType: "#react-layout li",
  755. FaviconType: ".nrn-react-div .result__url__domain",
  756. FaviconAddTo: "h2",
  757. CounterType: "#react-layout li h2 a",
  758. BlockType: "h2 a",
  759. MultiPageType: "#react-layout .react-results--main",
  760. pager: {
  761. nextLink: "//a[contains(@class,\"sb_pagN\")]",
  762. pageElement: "id(\"b_results\")/li[not(contains(@class,\"b_pag\") or contains(@class,\"b_ans b_top\"))]",
  763. HT_insert: ["id(\"b_results\")/li[@class=\"b_pag\"]", 1], // 1 = beforebegin; 2 = beforeend
  764. replaceE: "id(\"b_results\")//nav[@role=\"navigation\"]",
  765. }
  766. }
  767. }
  768.  
  769. _s_baidu_xueshu() {
  770. if (this.useItem.SiteTypeID === 8) {
  771. console.warn('启动百度学术特殊设置')
  772. this.gmInstance.curConfig.adsStyleMode = 2
  773. }
  774.  
  775. return {
  776. SiteTypeID: 8,
  777. MainType: "#content_left .result",
  778. Stype_Normal: "h3.t>a, #results .c-container>.c-blocka",
  779. FaviconType: "h3",
  780. FaviconAddTo: "h3",
  781. 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]",
  782. BlockType: "h3 a",
  783. }
  784. }
  785.  
  786. _s_google_scholar() {
  787. if (this.useItem.SiteTypeID === 4.1) {}
  788.  
  789. return {
  790. SiteTypeID: 4.1,
  791. MainType: "#rso .g, div[data-micp-id='rso'] .g",
  792. FaviconType: ".iUh30",
  793. FaviconAddTo: "h3",
  794. CounterType: "#rso .g h3:not(table h3),._yE>div[class~=_kk] h3",
  795. BlockType: "a:not([href*='translate.google.com'])", // 修复block翻页的问题
  796. pager: {
  797. nextLink: '//a[./span[@class="gs_ico gs_ico_nav_next"]]',
  798. pageElement: '//div[@class="gs_r gs_or gs_scl"]',
  799. HT_insert: null, // 1 = beforebegin; 2 = beforeend
  800. replaceE: '//div[@id="navcnt"] | //div[@id="rcnt"]//div[@role="navigation"]',
  801. }
  802. }
  803. }
  804. }
  805. class BaseConfig {
  806. constructor(isEngine = true) {
  807. this.commonStyleEnable = true // 是否开启默认效果优化
  808. this.commonStyleLink = ''
  809. this.commonStyleLess = ''
  810.  
  811. // 搜索引擎的逻辑
  812. if(isEngine) {
  813. this.adsStyleEnable = true // 是否开启默认效果优化
  814. this.adsStyleMode = '3' // 0-不带css;1-单列靠左;2-单列居中;3-双列居中
  815. this.HuYanMode = false // 护眼模式
  816. this.HuYanMode_Color = '#ffffff' // 护眼模式-颜色
  817.  
  818. this.BgEnable = false // 背景图-是否启用
  819. this.BgUseUrl = '' // 默认背景图
  820. this.BgFit = true // 背景图-是否适应
  821. this.BgBase64Image = '' // 这个KEY暂时不使用
  822.  
  823. this.customStyleEnable = false
  824. this.customStyleLink = ''
  825. this.customStyleLess = ''
  826. }
  827. }
  828. }
  829. class CSSAutoInsert {
  830. constructor() {
  831. this.hasChanged = false
  832. this.cssInsertSet = {}
  833.  
  834. MyApi.setIntervalRun(()=> {
  835. if(this.hasChanged) {
  836. this.hasChanged = false
  837. this.doInsert()
  838. }
  839. }, 50)
  840. }
  841.  
  842. add(uniqueName, cssText) {
  843. uniqueName = 'AC-' + uniqueName // 加上特殊前缀,标志关键词
  844. // 如果有,并且数据还一模一样,那么跳过;如果数据不一样,那么覆盖
  845. if (this.cssInsertSet[uniqueName] && this.cssInsertSet[uniqueName] === cssText) {
  846. return
  847. }
  848. console.mylog('--->插入样式表:' + uniqueName)
  849. this.cssInsertSet[uniqueName] = `\n/************${uniqueName}*********/\n` + cssText
  850. this.hasChanged = true
  851. }
  852. remove(uniqueName) {
  853. uniqueName = 'AC-' + uniqueName // 加上特殊前缀,标志关键词
  854. if (this.cssInsertSet[uniqueName]) {
  855. console.mylog('--->移除样式表:' + uniqueName)
  856. delete this.cssInsertSet[uniqueName]
  857. this.hasChanged = true
  858. }
  859. }
  860.  
  861. clear() {
  862. this.cssInsertSet = {}
  863. this.hasChanged = true
  864. }
  865.  
  866. doInsert() {
  867. const cssText = Object.values(this.cssInsertSet).join('\n')
  868. MyApi.addStyle(cssText, 'AC-CSSAutoInsertBase', Object.keys(this.cssInsertSet).join(' ')) // 方便排查css插入
  869. console.mylog('插入CSS完成')
  870. }
  871. }
  872. class ACGM {
  873. constructor() {
  874. this.initGM()
  875. this.bindGM()
  876. }
  877.  
  878. async initACGM() {
  879. let ACConfig = {}
  880. this.blockRuleList = []
  881. const DefaultConfig = {
  882. common: {
  883. version: '', // 从代码中动态拉取,丢弃任何值
  884. isDevMode: false, // 是否为调试模式,从页面给出来的
  885. isLocalDevMode: false, // 是否为本地调试模式,从页面给出来的,用于加载本地CSS
  886. localDebugBaseUrl: '', // 本地调试模式,本地CSS的入口地址
  887. isRedirectEnable: false, // 是否开启重定向功能
  888. isAdsEnable: false, // 是否开启去广告模式
  889. isFaviconEnable: true, // 是否开启Favicon图标
  890. isAutopage: true, // 是否开启自动翻页功能
  891.  
  892. isBlockEnable: true, // 是否开启去拦截模式
  893. isBlockResultDisplay: true, // 是否删除已拦截的条目
  894. isBlockBtnDisplay: false, // 是否显示block按钮
  895.  
  896. isRightDisplayEnable: true, // 是否开启右侧边栏
  897. isCounterEnable: false, // 是否显示计数器
  898. isALineDisable: false, // 是否禁止下划线
  899. isDarkModeEnable: false, // 是否加载暗黑模式
  900.  
  901. ...new BaseConfig(false)
  902. },
  903. baidu: {
  904. doRemoveSug: true, // 删除移动预测
  905. doRemoveAIGen: false, // 移除百度AI搜索结果
  906. baiduLiteEnable: false, // 启用百度Lite样式表
  907. ...new BaseConfig()
  908. },
  909. google: {
  910. useBaiduLogo: false, // 默认不使用百度logo
  911. ...new BaseConfig()
  912. },
  913. bing: {
  914. optimizeBing: true,
  915. ...new BaseConfig()
  916. },
  917. duck: {
  918. optimizeDuck: true, // 是否开启优化
  919. ...new BaseConfig()
  920. },
  921. haosou: {
  922. ...new BaseConfig(false)
  923. }
  924. };
  925. try {
  926. let res = await GM.getValue("ACConfig", "{}")
  927. ACConfig = JSON.parse(res);
  928.  
  929. res = await GM.getValue("ACBlockRules", "[]")
  930. this.blockRuleList = JSON.parse(res);
  931. this.acpush_acremoveInit()
  932. } catch (e) {
  933. console.error('出bug了')
  934. ACConfig = DefaultConfig
  935. }
  936. // 随便给一个值初始化,这个值,只是临时的值,如果需要写入,也是从另一端拉取,不是这个值来覆盖的
  937. this.curConfig = {
  938. ...DefaultConfig.common,
  939. ...DefaultConfig.baidu
  940. }
  941. this.sortIndex = 1
  942. this.bingScrollPos = 0
  943. this.ACConfig = Object.assign({}, DefaultConfig, ACConfig) // 作为临时修改用
  944. // this.enableCSS = true
  945. this.cssAutoInsert = new CSSAutoInsert()
  946. this.cssFavionList = reactive({
  947. list: []
  948. })
  949.  
  950. this.adsCSSList = {
  951. baiduLiteStyle: '',
  952.  
  953. leftCommonStyle: '',
  954. onePageStyle: '',
  955. twoPageStyle: '',
  956. multiPageStyle: '',
  957. expandPageStyle: '',
  958.  
  959. customStyle: '', // 自定义样式表
  960. commonStyle: '', // 全局样式表
  961.  
  962. huyanStyle: '',
  963. bgAutoFitStyle: '',
  964. darkModeStyle: '', // 暗黑护眼色
  965. faviconStyle: '', // 动态插入的favicon的数据
  966. }
  967.  
  968. this.lock = {
  969. bodyLocked: true,
  970. headLocked: true,
  971. pageLoadingLocked: false,
  972. isBlockChecking: false,
  973. afterBlockChangeChecked: true, // 数据刷新后,是否检查过了,用于减少reg判定
  974. }
  975. // 数据先初始化
  976. this.curConfig = reactive({
  977. enableCSS: true,
  978. ...this.ACConfig.common,
  979. ...this.ACConfig[this._getSiteName()]
  980. })
  981. // 再得到真实options,并调整config
  982. this.options = new SiteOptions(this)
  983. await this.loadSiteCSS()
  984. this.waitBodyHead()
  985. this.openSeetingsUrl = ''
  986. this.check90daoConn()
  987. }
  988.  
  989. initGM() {
  990. if (typeof (GM) === "undefined") {
  991. // 这个是ViolentMonkey的支持选项
  992. GM = {};
  993. GM.setValue = GM_setValue;
  994. GM.getValue = GM_getValue;
  995. }
  996. if (typeof GM_getResourceText === 'undefined') {
  997. GM_getResourceText = async function(aResourceName) {
  998. // 如果没有这个接口,那就是没办法缓存这个数据,所以只能用本地的数据进行缓存了
  999. let res = await (await fetch(await GM.getResourceUrl(aResourceName))).text();
  1000. let saveRes = await GM.getValue(aResourceName);
  1001. if (typeof (saveRes) === 'undefined') {
  1002. GM.setValue(aResourceName, res);
  1003. } else {
  1004. return saveRes;
  1005. }
  1006. return res;
  1007. }
  1008. }
  1009. }
  1010.  
  1011. bindGM() {
  1012. GM_registerMenuCommand('AC-重定向脚本设置', function() {
  1013. window.open(CONST.openSeetingsUrl)
  1014. });
  1015. GM_registerMenuCommand('脚本重置 - 修复脚本', function() {
  1016. GM.setValue('ACConfig', '{}');
  1017. location.reload();
  1018. });
  1019. }
  1020.  
  1021. check90daoConn() {
  1022. const storeValue = sessionStorage.getItem('access_90dao')
  1023. this.openSeetingsUrl = storeValue || 'https://ac-baidu.tujidu.com/pages/custom/#' + CONST.options.siteName
  1024. if (!storeValue) {
  1025. console.log('不存在自定义配置')
  1026. GM_xmlhttpRequest({
  1027. method: "HEAD",
  1028. timeout: 3000,
  1029. url: "https://ac-baidu.90dao.com/",
  1030. onload: ()=> {
  1031. this.openSeetingsUrl = 'https://ac-baidu.90dao.com/pages/custom/#' + CONST.options.siteName
  1032. sessionStorage.setItem('access_90dao', this.openSeetingsUrl)
  1033. },
  1034. onerror: ()=> {
  1035. this.openSeetingsUrl = 'https://ibaidu.tujidu.com/pages/custom/#' + CONST.options.siteName
  1036. sessionStorage.setItem('access_90dao', this.openSeetingsUrl)
  1037. }
  1038. });
  1039. }
  1040. }
  1041. saveConfig() {
  1042. const commonConfig = this.ACConfig['common']
  1043. const siteConfig = this.ACConfig[this.options.siteName]
  1044. for(const key in siteConfig) {
  1045. siteConfig[key] = this.curConfig[key]
  1046. }
  1047. for(const key in commonConfig) {
  1048. commonConfig[key] = this.curConfig[key]
  1049. }
  1050. GM.setValue('ACConfig', JSON.stringify(this.ACConfig));
  1051. }
  1052.  
  1053. saveBlockRule() {
  1054. GM.setValue('ACBlockRules', JSON.stringify(this.blockRuleList));
  1055. }
  1056.  
  1057. renewConfig(newConfig) {
  1058. const chooseCfg = newConfig[this.options.siteName]
  1059. const commonCfg = newConfig['common']
  1060. if(chooseCfg) {
  1061. Object.assign(this.curConfig, chooseCfg)
  1062. }
  1063. if(commonCfg) {
  1064. Object.assign(this.curConfig, commonCfg)
  1065. }
  1066. }
  1067.  
  1068. async loadStyleByName_WithLessCache(styleName) {
  1069. if(CONST.curConfig.isDevMode && CONST.curConfig.isLocalDevMode && CONST.curConfig.localDebugBaseUrl) {
  1070. const renderCSSKeyName = '__AC.RenderCSS__' + styleName
  1071. return await setLocalLessData(renderCSSKeyName, getDebugStyle) // 不带缓存,随时刷新了
  1072. // return await cacheStyle(renderCSSKeyName, getDebugStyle) // 带缓存,随时刷新了
  1073. } else {
  1074. return await cacheStyle(styleName, getRenderStyle)
  1075. }
  1076.  
  1077. async function cacheStyle(styleName, getLessDataFunc) {
  1078. const renderCSSKeyName = '__AC.RenderCSS__' + styleName
  1079. const localData = localStorage.getItem(renderCSSKeyName)
  1080. if (localData) {
  1081. setTimeout(() => {
  1082. console.mylog('*****有缓存了,但是在刷新了:' + styleName)
  1083. setLocalLessData(renderCSSKeyName, getLessDataFunc)
  1084. }, 2000)
  1085. return localData
  1086. } else {
  1087. console.mylog('*****没有缓存' + styleName)
  1088. return await setLocalLessData(renderCSSKeyName, getLessDataFunc)
  1089. }
  1090. }
  1091.  
  1092. async function setLocalLessData(renderCSSKeyName, getLessDataFunc) {
  1093. const { css = '' } = await less.render(await getLessDataFunc());
  1094. localStorage.setItem(renderCSSKeyName, css)
  1095. return css
  1096. }
  1097.  
  1098. async function getDebugStyle() {
  1099. const dataUrl = `${CONST.curConfig.localDebugBaseUrl}${styleName}.less`
  1100. const [err, text] = await MyApi.http.get(dataUrl)
  1101. if(!err) {
  1102. return text
  1103. } else {
  1104. console.error('加载失败', dataUrl)
  1105. }
  1106. return ''
  1107. }
  1108.  
  1109. async function getRenderStyle() {
  1110. return GM_getResourceText(styleName)
  1111. }
  1112. }
  1113.  
  1114. async loadSiteCSS() {
  1115. console.mylog('CSS加载开始' + +this.curConfig.adsStyleMode)
  1116. // 加载多列
  1117. if (this.curConfig.adsStyleEnable) {
  1118. if (+this.curConfig.adsStyleMode >= 1) {
  1119. this.adsCSSList.leftCommonStyle = await this.loadStyleByName_WithLessCache(this.options.siteName + 'CommonStyle') // 单列效果
  1120. }
  1121. if (+this.curConfig.adsStyleMode >= 2) {
  1122. this.adsCSSList.onePageStyle = await this.loadStyleByName_WithLessCache(this.options.siteName + 'OnePageStyle') // 单列居中
  1123. }
  1124. if (+this.curConfig.adsStyleMode >= 3) {
  1125. this.adsCSSList.twoPageStyle = await this.loadStyleByName_WithLessCache(this.options.siteName + 'TwoPageStyle') // 双列效果
  1126. }
  1127. if (+this.curConfig.adsStyleMode >= 4) {
  1128. this.adsCSSList.multiPageStyle = await this.getMultiPageStyle() // 多列效果
  1129. }
  1130. }
  1131. // 加载百度Lite
  1132. if (this.curConfig.baiduLiteEnable) {
  1133. this.adsCSSList.baiduLiteStyle = await this.loadStyleByName_WithLessCache('baiduLiteStyle')
  1134. }
  1135. // 加载背景图优化
  1136. if (this.curConfig.BgEnable && this.curConfig.BgFit) {
  1137. this.adsCSSList.bgAutoFitStyle = await this.loadStyleByName_WithLessCache('BgAutoFit')
  1138. }
  1139. // 加载护眼样式
  1140. if (this.curConfig.HuYanMode) {
  1141. this.adsCSSList.huyanStyle = await this.getHuyanStyle()
  1142. }
  1143. if (this.curConfig.isDarkModeEnable) {
  1144. this.adsCSSList.darkModeStyle = await this.loadStyleByName_WithLessCache('HuaHua-ACDrakMode')
  1145. }
  1146. // 加载自定义样式
  1147. if (this.curConfig.customStyleEnable) {
  1148. console.mylog('触发custom更新')
  1149. const { css = '' } = await less.render(this.curConfig.customStyleLess);
  1150. this.adsCSSList.customStyle = css
  1151. }
  1152. // 加载其他样式
  1153. if (this.curConfig.commonStyleEnable) {
  1154. console.mylog('触发common更新')
  1155. const { css = '' } = await less.render(this.curConfig.commonStyleLess);
  1156. this.adsCSSList.commonStyle = css
  1157. }
  1158. console.mylog('CSS加载结束')
  1159. // 2秒后再加载
  1160. setTimeout(() => {
  1161. this.loadAllStyle()
  1162. }, 2000)
  1163. }
  1164.  
  1165. getMultiPageStyle() {
  1166. return this.options.useItem.MultiPageType +
  1167. (+this.curConfig.adsStyleMode === 4 ?
  1168. "{grid-template-columns: repeat(3, 33.3%); grid-template-areas:'xmain xmain xmain';}" :
  1169. "{grid-template-columns: repeat(4, 25%); grid-template-areas:'xmain xmain xmain xmain';}")
  1170. }
  1171.  
  1172. async getHuyanStyle() {
  1173. function Lighter(oriRGB, deltaY) {
  1174. function clip255(value) {
  1175. if (value > 255) return 255;
  1176. if (value < 0) return 0;
  1177. return value;
  1178. }
  1179. // 按比例缩放 + 1/deltaY
  1180. // HEX 2 RGB
  1181. let rgb = oriRGB.replace("#", "");
  1182. let R = parseInt("0x" + rgb.substr(0, 2));
  1183. let G = parseInt("0x" + rgb.substr(2, 2));
  1184. let B = parseInt("0x" + rgb.substr(4, 2));
  1185. // RGB 2 YUV
  1186. let Y = ((66 * R + 129 * G + 25 * B + 128) >> 8) + 16;
  1187. let U = ((-38 * R - 74 * G + 112 * B + 128) >> 8) + 128;
  1188. let V = ((112 * R - 94 * G - 18 * B + 128) >> 8) + 128;
  1189. Y = Y * (1 + 1.0 / deltaY);// 提高亮度
  1190. // YUV 2 RGB
  1191. R = clip255((298 * (Y - 16) + 409 * (V - 128) + 128) >> 8);
  1192. G = clip255((298 * (Y - 16) - 100 * (U - 128) - 208 * (V - 128) + 128) >> 8);
  1193. B = clip255((298 * (Y - 16) + 516 * (U - 128) + 128) >> 8);
  1194. return "#" + ((R << 16) + (G << 8) + B).toString(16);
  1195. }
  1196.  
  1197. let HuyanStyle = await this.loadStyleByName_WithLessCache('HuYanStyle')
  1198. const huyanColor = this.curConfig.HuYanMode_Color
  1199.  
  1200. return HuyanStyle
  1201. .replace(/#aaa(a*)/igm, huyanColor)
  1202. .replace(/#bbb(b*)/igm, Lighter(huyanColor, -40))
  1203. .replace(/#ccc(c*)/igm, Lighter(huyanColor, 45));
  1204. }
  1205.  
  1206. async loadAllStyle() {
  1207. if (!this.adsCSSList.leftCommonStyle) this.adsCSSList.leftCommonStyle = await this.loadStyleByName_WithLessCache(this.options.siteName + 'CommonStyle') // 单列效果
  1208. if (!this.adsCSSList.onePageStyle) this.adsCSSList.onePageStyle = await this.loadStyleByName_WithLessCache(this.options.siteName + 'OnePageStyle') // 单列居中
  1209. if (!this.adsCSSList.twoPageStyle) this.adsCSSList.twoPageStyle = await this.loadStyleByName_WithLessCache(this.options.siteName + 'TwoPageStyle') // 双列效果
  1210. if (!this.adsCSSList.baiduLiteStyle) this.adsCSSList.baiduLiteStyle = await this.loadStyleByName_WithLessCache('baiduLiteStyle')
  1211. if (!this.adsCSSList.bgAutoFitStyle) this.adsCSSList.bgAutoFitStyle = await this.loadStyleByName_WithLessCache('BgAutoFit')
  1212. if (!this.adsCSSList.darkModeStyle) this.adsCSSList.darkModeStyle = await this.loadStyleByName_WithLessCache('HuaHua-ACDrakMode')
  1213. }
  1214.  
  1215. waitBodyHead() {
  1216. // 永远执行
  1217. MyApi.safeWaitFunc(() => {return document.head}, () => {
  1218. console.mylog('解锁head')
  1219. this.lock.headLocked = false
  1220. })
  1221. MyApi.safeWaitFunc(() => {return document.body}, () => {
  1222. console.mylog('解锁body')
  1223. this.lock.bodyLocked = false
  1224. })
  1225. }
  1226.  
  1227. addIntervalTrigger(site = '', waitAt = 'now', callback, interval_time = 0, runTimes = 1) {
  1228. console.mylog('addIntervalTrigger', site, "------------", this.options.siteName)
  1229. if(site !== 'all' && this.options.siteName !== site) return
  1230. let count = runTimes
  1231. const intId = MyApi.setIntervalRun(async () => {
  1232. count--
  1233. if(
  1234. !((waitAt === 'now') ||
  1235. (waitAt === 'body' && !this.lock.bodyLocked) ||
  1236. (waitAt === 'head' && !this.lock.headLocked))
  1237. ) {
  1238. return
  1239. }
  1240. if(count >= 0) {
  1241. await callback(count)
  1242. } else {
  1243. clearInterval(intId)
  1244. }
  1245. }, interval_time)
  1246. }
  1247.  
  1248. acpush_acremoveInit() {
  1249. function acpush(data = "") {
  1250. this.hasEdit = true
  1251. data = data.trim()
  1252. // 如果是垃圾数据,那么可以丢弃的
  1253. if (!data) return '无效内容';
  1254. // 如果数据中有回车,那数据也是无效的正文而已
  1255. if (data.search(/(,|:|。|\n)/) >= 0) return '格式不符合要求';
  1256. if (this.findIndex(m => m === data) < 0) {
  1257. this.push(data);
  1258. dataChangeCallback()
  1259. } else {
  1260. return "已存在相同项"
  1261. }
  1262. }
  1263. function acremove (data) {
  1264. this.hasEdit = true
  1265. let delId = this.findIndex(m => m === data);
  1266. if (delId >= 0) {
  1267. this.splice(delId, 1);
  1268. dataChangeCallback()
  1269. return delId
  1270. }
  1271. return -1
  1272. }
  1273. function dataChangeCallback() {
  1274. CONST.lock.afterBlockChangeChecked = false
  1275. PageBlockFunc._updateRegListRule()
  1276. }
  1277. Object.defineProperty(CONST.blockRuleList, 'acpush', { value: acpush })
  1278. Object.defineProperty(CONST.blockRuleList, 'acremove', { value: acremove })
  1279. }
  1280.  
  1281. _getSiteName() {
  1282. const specialRule = {
  1283. 'xueshu.baidu.com': 'baidu_xueshu',
  1284. 'scholar.google.com': 'google_scholar',
  1285. 'so.com': 'haosou',
  1286. }
  1287. let useRule = Object.keys(specialRule).find(one => location.host.includes(one))
  1288. if(!useRule) {
  1289. useRule = location.host.replace(/.*(baidu|google|bing|duck).*/, '$1')
  1290. } else {
  1291. return specialRule[useRule]
  1292. }
  1293. return useRule
  1294. }
  1295. }
  1296. const CONST = new ACGM()
  1297. await CONST.initACGM()
  1298.  
  1299. class PageFuncClass {
  1300. constructor() {
  1301. this.removeAds = this.removeAdFunc()
  1302. }
  1303. GoogleInBaiduMode() {
  1304. MyApi.safeGetNodeFunc("#logo img, #logocont img", function(node) {
  1305. let faNode = node.parentNode.parentNode;
  1306. if(faNode.hasAttribute('xchanged')) return
  1307. faNode.classList.add("baidu");
  1308. faNode.setAttribute('xchanged', 1)
  1309. node.removeAttribute("src");
  1310. node.src = "https://www.baidu.com/img/flexible/logo/pc/result.png";
  1311. node.width = "125";
  1312. node.removeAttribute("height");
  1313. });
  1314. MyApi.safeGetNodeFunc("a#logo", function(node) {
  1315. let faNode = node.parentNode.parentNode;
  1316. if(faNode.hasAttribute('xchanged')) return
  1317. faNode.classList.add("baidu");
  1318. faNode.setAttribute('xchanged', 1)
  1319. node.querySelector('svg').style.display = 'none'
  1320. const newImage = document.createElement('img')
  1321. newImage.src = "https://www.baidu.com/img/flexible/logo/pc/result.png"
  1322. newImage.width = "125"
  1323. node.appendChild(newImage)
  1324. });
  1325. MyApi.safeGetNodeFunc("img[alt='Google']", function(node) {
  1326. if(node.hasAttribute('xchanged')) return
  1327. node.setAttribute('xchanged', 1)
  1328. node.removeAttribute("srcset");
  1329. node.src = "https://www.baidu.com/img/flexible/logo/pc/result.png";
  1330. node.style.height = '72px'
  1331. // node.style.marginTop = '-10px'
  1332. });
  1333. MyApi.safeGetNodeFunc("form[role='search'] .logo img", function(node) {
  1334. if(node.hasAttribute('xchanged')) return
  1335. node.setAttribute('xchanged', 1)
  1336. node.removeAttribute("srcset");
  1337. node.src = "https://www.baidu.com/img/flexible/logo/pc/result.png";
  1338. node.setAttribute("height", "30");
  1339. // node.style.marginTop = '-10px'
  1340. });
  1341. if(!document.title.includes('百度')) {
  1342. document.title = document.title.replace(/^Google/, "百度一下,你就知道")
  1343. .replace(/ - Google 搜索/, "_百度搜索")
  1344. .replace(/ - Google Search/, "_百度搜索");
  1345. }
  1346. MyApi.safeGetNodeFunc("head", function() {
  1347. let linkTarget = document.querySelector("link[type='image/x-icon']") || document.createElement('link');
  1348. if(!linkTarget.href.includes('baidu')) return
  1349. linkTarget.type = 'image/x-icon';
  1350. linkTarget.rel = 'shortcut icon';
  1351. linkTarget.href = 'https://www.baidu.com/favicon.ico';
  1352. document.head.appendChild(linkTarget);
  1353. })
  1354. }
  1355. removeAdFunc() {
  1356. function removeBaiduAd() {
  1357. // 移除右侧栏广告
  1358. MyApi.safeRemove_xpath("id('content_right')/div[.//a[starts-with(text(), '广告')]]");
  1359. // 移除标准广告
  1360. MyApi.safeRemove_xpath("id('content_left')/div[.//span[contains(@class, 'tuiguang') or contains(@class, 'brand')][contains(text(), '广告')]]");
  1361. // 移除标准广告 - 新
  1362. MyApi.safeRemove_xpath("id('content_left')/div[.//a[text()='广告']]");
  1363. // 移除右侧栏顶部-底部无用广告
  1364. MyApi.safeRemove_xpath("id('content_right')/br");
  1365. MyApi.safeRemove_xpath("id('content_right')/div[not(@id)]");
  1366. // 移除顶部可能出现的 "为您推荐"
  1367. MyApi.safeRemove_xpath("id('content_left')//div[contains(@class, '_rs')]");
  1368.  
  1369. /****移除Mobile模式上的部分广告****/
  1370. MyApi.safeRemove_xpath("id('page-bd')/div[not(contains(@class, 'result'))]");
  1371. MyApi.safeRemove_xpath("id('page-bd')/div[not(@class)]");
  1372. MyApi.safeRemove_xpath("//div[@class='na-like-container']");
  1373. }
  1374. function removeGoogleAd() {
  1375. MyApi.safeRemoveAd("#bottomads");
  1376. MyApi.safeRemoveAd('div[aria-label="广告"]');
  1377. MyApi.safeRemoveAd('div[aria-label="Ads"]');
  1378. }
  1379. function removeBingAd() {
  1380. MyApi.safeRemoveAd(".b_ad");
  1381. MyApi.safeRemove_xpath("id('b_results')/li[./div[@class='ad_fls']]");
  1382.  
  1383. // 移除特殊tag,带url标记的广告类 -- 新版的bing似乎比较特殊,无法判定了
  1384. const resList = [...document.querySelectorAll("ol>li")].filter(one => one.querySelector('p')) // 定位到所有包含p标签的li
  1385. const removeWith = [
  1386. '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==',
  1387. // ''
  1388. ]
  1389. const adList = resList.filter(one => {
  1390. const url = window.getComputedStyle(one.querySelector('p'), '::before').getPropertyValue('content')
  1391. return removeWith.some(remove => url.includes(remove))
  1392. }) // 检查每一个p标签,里面存在before伪元素,且伪元素中是链接的,均为广告
  1393. adList.forEach(one => one.remove())
  1394. }
  1395. function removeHaosouAd() {
  1396. MyApi.safeRemoveAd("#so_kw-ad");
  1397. MyApi.safeRemoveAd("#m-spread-left");
  1398. // 移除搜索中底部广告
  1399. MyApi.safeRemoveAd("#m-spread-bottom");
  1400. // 移除右侧栏顶部广告
  1401. MyApi.safeRemove_xpath("id('righttop_box')//li[.//span[contains(text(), '广告')]]");
  1402. }
  1403.  
  1404. return {
  1405. removeBaiduAd,
  1406. removeGoogleAd,
  1407. removeBingAd,
  1408. removeHaosouAd
  1409. }
  1410. }
  1411. InsertSettingMenu() {
  1412. if (document.querySelector("#myuser") === null) {
  1413. MyApi.safeWaitFunc("#u, #gb, #b_header>#id_h, #header_wrapper .js-hl-butto, .header--aside, #header .inner .menu", parent => {
  1414. parent.style = "width: auto;";
  1415. let userAdiv = document.createElement("div");
  1416. userAdiv.id = "myuser";
  1417. 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>`;
  1418.  
  1419. parent.insertBefore(userAdiv, parent.childNodes[0]);
  1420. document.querySelector("#myuser .myuserconfig").addEventListener("click", function(e) {
  1421. window.open(CONST.openSeetingsUrl)
  1422. }, true);
  1423. }, 300)
  1424. }
  1425. }
  1426. RedirectHandle() {
  1427. // 处理主重定向
  1428. if (CONST.options.useItem.SiteTypeID < 0) return;
  1429. if (CONST.curConfig.isRedirectEnable) {
  1430. if (CONST.options.useItem.Stype_Normal) { // 如果定义了,那么就去处理重定向
  1431. resetURLNormal();
  1432. }
  1433. if (CONST.options.useItem.SiteTypeID === CONST.options.google.SiteTypeID) removeOnMouseDownFunc(); // 移除onMouseDown事件,谷歌去重定向
  1434. if (location.host.includes('m.baidu.com')) removeMobileBaiduDirectLink(); // 处理百度手机版本的重定向地址
  1435. remove_xueshuBaidu(); // 百度学术重定向问题
  1436. MyApi.safeRemoveAd(".res_top_banner"); // 移除百度可能显示的劫持
  1437. }
  1438.  
  1439. function removeMobileBaiduDirectLink() {
  1440. let nodes = document.querySelectorAll("#page #page-bd #results .result:not([ac_redirectStatus])");
  1441. for (let i = 0; i < nodes.length; i++) {
  1442. let curNode = nodes[i];
  1443. MyApi.safeFunc(function() {
  1444. let curData = JSON.parse(curNode.dataset.log.replace(/'/gm, "\""));
  1445. let trueLink = curData.mu;
  1446. curNode.querySelector("article").setAttribute("rl-link-href", trueLink);
  1447. curNode.querySelectorAll("a").forEach(function(per) {
  1448. per.setAttribute("href", trueLink);
  1449. });
  1450. });
  1451. curNode.setAttribute("ac_redirectStatus", "1");
  1452. }
  1453. }
  1454.  
  1455. function removeOnMouseDownFunc() {
  1456. MyApi.safeFunc(() => {
  1457. let resultNodes = document.querySelectorAll(".g .rc a, #rs, #rso .g a");
  1458. for (let i = 0; i < resultNodes.length; i++) {
  1459. let one = resultNodes[i];
  1460. one.setAttribute("onmousedown", ""); // 谷歌去重定向干扰
  1461. one.setAttribute("target", "_blank"); // 谷歌链接新标签打开
  1462. one.setAttribute("data-jsarwt", "0"); // Firefox谷歌去重定向干扰
  1463. }
  1464. })
  1465. }
  1466.  
  1467. function remove_xueshuBaidu() {
  1468. if (CONST.options.useItem.SiteTypeID === CONST.options.baidu_xueshu.SiteTypeID) {
  1469. let xnodes = document.querySelectorAll("a[href*='sc_vurl=http']");
  1470. for (let j = 0; j < xnodes.length; j++) {
  1471. let xurl = MyApi.getUrlAttribute(xnodes[j].href, "sc_vurl", true);
  1472. xnodes[j].href = xurl;
  1473. }
  1474. }
  1475. }
  1476.  
  1477. function DealRedirect (request, curNodeHref, respText, RegText, hrefType) {
  1478. if (respText === null || typeof (respText) === "undefined") return;
  1479. let resultResponseUrl = "";
  1480. if (RegText != null) {
  1481. resultResponseUrl = MyApi.Reg_Get(respText, RegText);
  1482. } else {
  1483. resultResponseUrl = respText;
  1484. }
  1485. if (resultResponseUrl !== null && resultResponseUrl !== "" && !resultResponseUrl.includes("www.baidu.com/link")) {
  1486. try {
  1487. let host = PageFunc.getTextHost(resultResponseUrl);
  1488.  
  1489. document.querySelectorAll("*[href*='" + curNodeHref + "']").forEach(per => {
  1490. let changeNode = per;
  1491.  
  1492. changeNode.setAttribute("ac_redirectStatus", "2");
  1493. changeNode.href = resultResponseUrl;
  1494. // changeNode.setAttribute("data-orihref", changeNode.href);
  1495. if (changeNode.hasAttribute("meta")) {
  1496. changeNode.setAttribute("meta", host);
  1497. changeNode.dataset.host = host;
  1498. }
  1499.  
  1500. if (hrefType === null || hrefType === undefined || hrefType === "title") {
  1501. if (changeNode.text && changeNode.text.length < 10 && !changeNode.text.includes(host)
  1502. // 不能是redirect url 不能是h2\h3下直属链接
  1503. && !changeNode.parentElement.tagName.toLowerCase().includes("h")) {
  1504. changeNode.insertAdjacentHTML("beforeEnd", "&nbsp;-&nbsp;" + host);
  1505. }
  1506. }
  1507. })
  1508. request && request.abort();
  1509. } catch (e) {
  1510. }
  1511. }
  1512. }
  1513. function resetURLNormal() {
  1514. const mainList = document.querySelectorAll(CONST.options.useItem.MainType)
  1515.  
  1516. // 注意有重复的地址,尽量对重复地址进行去重
  1517. var hasDealHrefSet = new Set();
  1518. for (let i = 0; i < mainList.length; i++) {
  1519. // 此方法是异步,故在结束的时候使用i会出问题-严重!
  1520. // 采用闭包的方法来进行数据的传递
  1521. const curNode = mainList[i];
  1522.  
  1523. if (curNode !== null && curNode.getAttribute("ac_redirectStatus") === null) {
  1524. curNode.setAttribute("ac_redirectStatus", "0");
  1525.  
  1526. const linkNode = curNode.querySelector(CONST.options.useItem.Stype_Normal);
  1527. if(linkNode === null) {
  1528. continue
  1529. }
  1530.  
  1531. // 跳过特殊链接的处理
  1532. if(linkNode.href && (linkNode.href.startsWith('javascript') || linkNode.href.startsWith('#'))) {
  1533. continue
  1534. }
  1535.  
  1536. let linkHref = linkNode.href;
  1537. let len1 = hasDealHrefSet.size;
  1538. hasDealHrefSet.add(linkHref);
  1539. let len2 = hasDealHrefSet.size;
  1540. if (len1 === len2) continue; // 说明数据已经处理过,存在相同的记录
  1541. const isLinkNeedDeal = () => {
  1542. // 如果当前节点存在mu参数,或者link节点存在data-mdurl,那么就算直接成功,不用重新请求一遍了
  1543. let trueLink = curNode.getAttribute('mu') || linkNode.getAttribute('data-mdurl')
  1544. if(trueLink && !trueLink.includes('nourl')) {
  1545. trueLink = getBaiduEncodingHandle(trueLink)
  1546. DealRedirect(null, linkHref, trueLink);
  1547. return true
  1548. }
  1549. }
  1550. const getBaiduEncodingHandle = (linkUrl) => {
  1551. let resLink = linkUrl
  1552. if(CONST.options.useItem.SiteTypeID === CONST.options.baidu.SiteTypeID && linkUrl.includes('baidu.com')) {
  1553. const [, first = ''] = /(ie=[^&]+)/.exec(location.search) || []
  1554. resLink = linkUrl.replace(/(ie=[^&]+)/, first)
  1555. }
  1556. return resLink
  1557. }
  1558. if(!isLinkNeedDeal()) {
  1559. continue
  1560. }
  1561. // 走接口重定向处理
  1562. if (linkHref.includes("www.baidu.com/link") ||
  1563. linkHref.includes("m.baidu.com/from") ||
  1564. linkHref.includes("www.sogou.com/link") ||
  1565. linkHref.includes("so.com/link") ||
  1566. linkHref.search("bing.com/(ck|a|aclick)") > 0 ||
  1567. linkHref.search("e.so.com/(search|eclk)") > 0
  1568. ) {
  1569. (async function(c_curnode, c_curhref) {
  1570. let url = c_curhref.replace(/^http:/, "https:");
  1571. if (CONST.options.useItem.SiteTypeID === CONST.options.baidu.SiteTypeID && !url.includes("eqid")) {
  1572. // 如果是百度,并且没有带有解析参数,那么手动带上
  1573. url = url + "&wd=&eqid=";
  1574. }
  1575.  
  1576. let gmRequestNode = GM_xmlhttpRequest({
  1577. url: url,
  1578. headers: { "Accept": "*/*", "Referer": c_curhref.replace(/^http:/, "https:") },
  1579. method: "GET",
  1580. timeout: 8000,
  1581. onload: function(response) { // MARK 有时候这个函数根本不进来 - 调试的问题 - timeout
  1582. if (response.responseText || response.responseHeaders) {
  1583. // 由于是特殊返回-并且好搜-搜狗-百度都是这个格式,故提出
  1584. DealRedirect(gmRequestNode, c_curhref, response.responseText, "URL='([^']+)'")
  1585. // 这个是在上面无法处理的情况下,备用的 tm-finalurldhdg tm-finalurlmfdh
  1586.  
  1587. if (response.responseHeaders.includes("tm-finalurl")) {
  1588. let relURL = Reg_Get(response.responseHeaders, "tm-finalurl\\w+: ([^\\s]+)");
  1589. if (relURL === null || relURL === "" || relURL.includes("www.baidu.com/search/error")) return;
  1590. DealRedirect(gmRequestNode, c_curhref, relURL);
  1591. }
  1592. }
  1593. }
  1594. });
  1595. })(curNode, linkHref); //传递旧的网址过去,读作c_curhref
  1596. }
  1597. }
  1598. }
  1599. if (hasDealHrefSet.size > 0 && mainList.length - hasDealHrefSet.size > 0) console.mylog("丢弃掉", mainList.length - hasDealHrefSet.size, "个重复链接");
  1600. }
  1601. }
  1602. getTextHost(sbefore) {
  1603. sbefore = (sbefore && sbefore.trim()).replace(/\s-\s\d{4}-\d{1,2}-\d{1,2}/, "") || "";
  1604. let send;
  1605. let result = sbefore.split('-');
  1606. // --搜狗百度专用;如果第一个是中文的话,地址就是第二个
  1607. if ((result.length > 1 && new RegExp("[\\u4E00-\\u9FFF]+", "g").test(sbefore)) && CONST.options.useItem.SiteTypeID === CONST.options.baidu.SiteTypeID) {
  1608. sbefore = result[1];
  1609. } else {
  1610. result = sbefore.split('\n');
  1611. if (result.length > 1 && CONST.options.useItem.SiteTypeID === CONST.options.google.SiteTypeID) {
  1612. sbefore = result[1];
  1613. }
  1614. }
  1615. // 此时sbefore几乎是等于网址了,但是有时候会有多的空格,多的内容,多的前缀http,多余的路径
  1616. let res = new RegExp(/(https?:\/\/)?([^/\s]+)/i).exec(sbefore);
  1617. send = (res && res[2].trim()) || "";
  1618. // send = sbefore.replace(/(\/[^/]*|\s*)/, "").replace(/<[^>]*>/g, "").replace(/https?:\/\//g, "").replace(/<\/?strong>/g, "").replace(/<\/?b>/g, "").replace(/<?>?/g, "").replace(/( |\/).*/g, "").replace(/\.\..*/, "");
  1619. if (send === "") return null;
  1620. if (send.indexOf(".") < 0) return null;
  1621. if (send.indexOf("↵") >= 0) return null;
  1622. return send.trim();
  1623. }
  1624. getNodeHost(sitetpNode) {
  1625. if (!sitetpNode) return {}
  1626. if (CONST.options.useItem.SiteTypeID === CONST.options.baidu.SiteTypeID) {
  1627. const href = sitetpNode.getAttribute("href");
  1628. if (href != null && !href.includes("baidu.com/link")) {
  1629. // 已经解析出来了
  1630. return { curHost: this.getTextHost(href), curUrl: href };
  1631. } else {
  1632. const host = this.getTextHost(sitetpNode.innerText || sitetpNode.textContent)
  1633. return { curHost: host, curUrl: host, isBaiduLink: true }; // 未被解密
  1634. }
  1635. } else if (sitetpNode instanceof HTMLAnchorElement) {
  1636. return { curHost: sitetpNode.host, curUrl: sitetpNode.href };
  1637. } else {
  1638. const host = this.getTextHost(sitetpNode.innerText || sitetpNode.textContent)
  1639. return { curHost: host, curUrl: host };
  1640. }
  1641. }
  1642. addFavicon(citeList) {
  1643. const insertList = []
  1644. if (CONST.options.useItem.SiteTypeID !== null) {
  1645. for (let index = 0; index < citeList.length; index++) {
  1646. if (null === citeList[index].getAttribute("ac_faviconStatus")) {
  1647. let curNode = citeList[index];
  1648. let targetNode = curNode;
  1649. let { curHost, curUrl } = PageFunc.getNodeHost(targetNode);
  1650. if (!curHost) { // 跳过解不出来的地址
  1651. continue;
  1652. } else {
  1653. }
  1654. let faviconUrl = curHost;
  1655. let II = 0;
  1656. for (; II <= 5; II++) {
  1657. targetNode = targetNode.parentNode;
  1658. if (targetNode != null && targetNode.querySelector(CONST.options.useItem.FaviconAddTo) != null) {
  1659. break;
  1660. }
  1661. }
  1662. if (targetNode.parentNode.hasAttribute('tpl') && targetNode.parentNode.getAttribute('tpl').includes('stock')) {
  1663. curNode.setAttribute("ac_faviconStatus", "-3");
  1664. continue
  1665. }
  1666. //console.mylog(index+"."+faviconUrl+"--"+II);
  1667. if (II <= 5) {
  1668. // 先用父节点判断一下是否存在img
  1669. let tmpHTML = targetNode.innerHTML;
  1670. let pos = tmpHTML.indexOf("fav-url")
  1671. & tmpHTML.indexOf("wr_fav")
  1672. & tmpHTML.indexOf("favurl")
  1673. & tmpHTML.indexOf("tit-ico")
  1674. & tmpHTML.indexOf("img_fav rms_img")
  1675. & tmpHTML.indexOf("c-tool-")
  1676. & tmpHTML.indexOf("span class=\"c-icon c-icon-")
  1677. & tmpHTML.indexOf("img class=\"xA33Gc")
  1678. & tmpHTML.indexOf("img class=\"XNo5Ab\""); // 谷歌图标
  1679. //他自己已经做了favicon了
  1680. if (pos > -1) {
  1681. curNode.setAttribute("ac_faviconStatus", "-2");
  1682. continue;
  1683. }
  1684. targetNode = targetNode.querySelector(CONST.options.useItem.FaviconAddTo);
  1685. let host = faviconUrl.replace(/[^.]+\.([^.]+)\.([^.]+)/, "$1.$2");
  1686.  
  1687. if (!targetNode.hasAttribute("data-favicon-t") && host.length >= 3) {
  1688. let faviconUrl = curNode.href || host
  1689. if (CONST.options.useItem.SiteTypeID === CONST.options.baidu.SiteTypeID && faviconUrl.includes("baidu.com/link")) {
  1690. faviconUrl = host
  1691. }
  1692.  
  1693. targetNode.setAttribute('data-favicon-t', faviconUrl)
  1694. insertList.push({
  1695. tagName: targetNode.tagName.toLowerCase(),
  1696. url: faviconUrl
  1697. })
  1698. }
  1699. }
  1700. }
  1701. }
  1702. }
  1703. insertList.map(one => CONST.cssFavionList.list.push(one))
  1704. }
  1705. addCounter(citeList) {
  1706. 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%;";
  1707. for (let i = 0; i < citeList.length; i++) {
  1708. let cur = citeList[i];
  1709. const index = cur.getAttribute('SortIndex');
  1710. if (index === null || typeof (index) === "undefined") {
  1711. cur.setAttribute('SortIndex', CONST.sortIndex);
  1712. let ele = document.createElement('em');
  1713. ele.className = 'AC-CounterT';
  1714. ele.style = cssText;
  1715. ele.innerText = CONST.sortIndex;
  1716. let child = cur.firstElementChild;
  1717. if (child && child.nodeName === 'DIV') {
  1718. let emNode = child.querySelector('em');
  1719. if (emNode) emNode.parentNode.insertAdjacentElement('afterBegin', ele)
  1720. } else {
  1721. cur.insertAdjacentElement('afterBegin', ele);
  1722. }
  1723. CONST.sortIndex++;
  1724. } else {
  1725. const curCounter = cur.querySelector(".AC-CounterT")
  1726. if (!curCounter) continue
  1727. const oriIndex = curCounter.innerText
  1728. const checkValue = (i + 1) % 100;
  1729. // 数据值不同
  1730. // 数据没有被翻译
  1731. if (+index !== checkValue && !/^\d+$/.test(oriIndex)) { // 按需更新
  1732. curCounter.innerText = checkValue;
  1733. cur.setAttribute('SortIndex', checkValue);
  1734. }
  1735. }
  1736. }
  1737. }
  1738. acSetCookie(cname, cvalue, domain, exdays) {
  1739. MyApi.safeFunc(() => {
  1740. exdays = exdays || 30;
  1741. let d = new Date();
  1742. domain = (domain ? "domain=" + domain : "") + ";";
  1743. d.setTime(d.getTime() + (exdays * 24 * 60 * 60 * 1000));
  1744. let expires = "expires=" + d.toUTCString();
  1745. document.cookie = cname + "=" + cvalue + "; " + domain + expires + ";path=/;SameSite=None;Secure";
  1746. })
  1747. }
  1748. dataChangeFireCallback() {
  1749. // 数据有变更,那么尝试重新渲染状态
  1750. CONST.cssAutoInsert.clear()
  1751.  
  1752. if(!CONST.curConfig.enableCSS) {
  1753. MyApi.safeGetNodeFunc('#myuser', node => node.remove())
  1754. return
  1755. }
  1756. console.mylog('即将插入CSS1')
  1757. if (CONST.curConfig.adsStyleEnable) {
  1758. console.mylog('即将插入CSS2')
  1759. if(+CONST.curConfig.adsStyleMode === 1) {
  1760. console.mylog('靠左优化模式')
  1761. CONST.cssAutoInsert.add("expandPageStyle", CONST.adsCSSList.expandPageStyle)
  1762. CONST.cssAutoInsert.add("leftCommonStyle", CONST.adsCSSList.leftCommonStyle)
  1763. } else if (+CONST.curConfig.adsStyleMode === 2) {
  1764. console.mylog('单列居中')
  1765. CONST.cssAutoInsert.add("expandPageStyle", CONST.adsCSSList.expandPageStyle)
  1766. CONST.cssAutoInsert.add("leftCommonStyle", CONST.adsCSSList.leftCommonStyle)
  1767. CONST.cssAutoInsert.add("onePageStyle", CONST.adsCSSList.onePageStyle)
  1768. } else if (+CONST.curConfig.adsStyleMode === 3) {
  1769. console.mylog('双列居中')
  1770. CONST.cssAutoInsert.add("leftCommonStyle", CONST.adsCSSList.leftCommonStyle)
  1771. CONST.cssAutoInsert.add("twoPageStyle", CONST.adsCSSList.twoPageStyle)
  1772. } else if (+CONST.curConfig.adsStyleMode === 4 ||+CONST.curConfig.adsStyleMode === 5) {
  1773. console.mylog('N列居中')
  1774. CONST.cssAutoInsert.add("leftCommonStyle", CONST.adsCSSList.leftCommonStyle)
  1775. CONST.cssAutoInsert.add("twoPageStyle", CONST.adsCSSList.twoPageStyle)
  1776. CONST.cssAutoInsert.add("multiPageStyle", CONST.adsCSSList.multiPageStyle)
  1777. }
  1778. }
  1779.  
  1780. CONST.cssAutoInsert.add("styleLogo", ".minidiv #logo img{width: 100px;height: unset;margin-top: 0.3rem;} body.purecss-mode:before{display: none;}")
  1781. CONST.cssAutoInsert.add("specialBAIDU", ".opr-recommends-merge-imgtext{display:none!important;}.res_top_banner{display:none!important;}.headBlock, body>div.result-op{display:none;}")
  1782. 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}")
  1783. 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}")
  1784.  
  1785. if(CONST.curConfig.baiduLiteEnable) {
  1786. CONST.cssAutoInsert.add("baiduLiteStyle", CONST.adsCSSList.baiduLiteStyle)
  1787. }
  1788. if(CONST.curConfig.HuYanMode) {
  1789. CONST.cssAutoInsert.add("huYanStyle", CONST.adsCSSList.huyanStyle)
  1790. }
  1791. if(CONST.curConfig.adsStyleEnable) {
  1792. 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;}")
  1793. }
  1794. if(CONST.curConfig.BgEnable) {
  1795. const imageUrl = CONST.curConfig.BgUseUrl
  1796. if(imageUrl) {
  1797. 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;}`
  1798. CONST.cssAutoInsert.add("backGroundImage", bgCSS)
  1799. }
  1800. if(CONST.curConfig.BgFit) {
  1801. CONST.cssAutoInsert.add("bgFitStyle", CONST.adsCSSList.bgAutoFitStyle)
  1802. }
  1803. }
  1804. if(CONST.curConfig.isDarkModeEnable) {
  1805. CONST.cssAutoInsert.add("darkModeStyle", CONST.adsCSSList.darkModeStyle)
  1806. }
  1807. if (CONST.curConfig.isAutopage) {
  1808. const sepImgs = {
  1809. top: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABYAAAAWCAYAAADEtGw7AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAWtJREFUeNrclE0rRGEUx8c1GUpRJIVIZGdhZCVr38GGhaI0ZXwCkliglChZEcvJxhdgYWOjLEUpm/EyiLzze+o8dTzdO3PljoVTv7rPc8/5d+6555xYrEhWop6boda5+6l9wjWcWpF+WIbqCJJ9hFRcDr3QAIkIhKugz5PDfkSixkphz5aiAnqgE8rgWRxGoSOPyBkswQuUwyscw4HrmFCZL8Kt/JAg7mEFPEmo4FdPwk0BUcsdzIap0TQ8qMAPuICcEjLnd+VjSjcfJNgIc/DkZGSymYGsnK9EZMrxe4MFaNGiZjC2fT5zQ3p7QDK1dR2GSljziclAvRUe8nHYVA4jjvC43NfAuk/smB2QNqcsWxKcLbAKTFnS0hWD6n27Fd6FLqiDI5iQmQ9jpiVT0sNJ6aYd7dAE3QHBbinSAX5JWWaxuLo8F35jh/bBK9Y+/r/Cl6pLcnna8NvuDGMnslpbZRpXZYT/3r4EGACZL3ZL2afNFAAAAABJRU5ErkJggg==",
  1810. bottom: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABYAAAAWCAYAAADEtGw7AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAXFJREFUeNrM1c8rBGEcx/FdtCEkLqYtpdwkKSUHUhxwITdK+Z3yM2cOLnJ39Cc44SgHScmJwlFxsIdlCScO6/2t76Onp52dXTtbnno1M8+Pz84+zzMzkcg/KA3oRTzM0A4cI4VTdIUVPIM3pPGO5aABJTkGx1BqjYmFFZxW7nnBwXmXogWX6bEGc2jEIU7+kNWDUSSwZyqndSvJ3N1g2Bm0oLtB2j+w7rQP4MpqXzRT0YRaPW/BthMedYLs60HsoE2vq9BsPwAJa8XFLUa0fUrvROo/saT1Q9adGimdlt8yj6TT6Q6d2vaida9YRbtP6EqmBZC5fHA6X+AAz1bwEc6cfk9+oaZM4NoZJL70+J2hTaZtNpet041zK8yP/Mgl+rOF1emr0UM1xnAfEPyISd0Jno6vtx+QuM6PZ22lpO7dbEV2Siv6rPeIjNs1HdYC7ixfG+YBqdTVDqPIv6iIWvO7iXGUFxAqi72PraJ9IH8EGACQcYjYRd5GHwAAAABJRU5ErkJggg==",
  1811. pre: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABYAAAAWCAYAAADEtGw7AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAASlJREFUeNpiYBjOoBiIrwJxFRAzUsvQViD+CMT/gfgTEPdRy9BPUENh+AsQ91JiaAuSS9HxZ3INb8Hi0v+UurwF6qL/ROBvQNxDrKFfkTT+A+JnQPwBKfJA/L9Ian7ic7kMEHcC8Q80F3UAcRsQv4by30INaUJT9weaWhSQDRUB4uVYvLkYiAWAOBopvEFBlArEPEA8G4ue9UAsATM4EYuCJUgKMtAMLoSKCwPxXCx6c1igClTQgmUZVPNrHMEGy3mgYCkCYiYgTkCSV4UZvA2IjYBYDIgvQbPvOyJTECid5wHxbyA2BuL3QLwRWYEsEJvg0IweFEU41IEMlgcxWJAEH0MxJeAsjMFEq6Jw+Br8BimVfMCTDEkG7EBcA8T3oWUJx4DVYwABBgCannnSzbgwIQAAAABJRU5ErkJggg==",
  1812. next: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABYAAAAWCAYAAADEtGw7AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAT1JREFUeNrc1b1KA0EYheEl/iARFFEkKl6D0UK8CrEVrCwEexFCtBIlRWIjsfEiLL0FKzs7QUWxM2piFMUkvhPOwLAs2TGuCn7wkNll5jC7+w0Jgv9avdjAObbQn1TwCu7QwhWW4xakPIOHMKzxGCaSCm6ioXHLZ0Hqpz7KrwRPIvvNvBlM2zYyNY8cMjhDHo9fCBzErnIqKNjgRSxpvIABbOLes2MKWHfuXdhXcR2avKrJ4zGhI9gLhQbq9XaZgGO1kutIOzIHpKp7NawhjYOINSeY6lFwHacw17P6NTWHd4xqnNbcS83LObtsaCPbEW+gXUW8ODswC27xoOsn3ODDmfOGss9XLuE54jGjvPqGuuG1mFDzZIfdNHynnde7DbW1r5DwTstJHP2iE55YqD36ebXZDvr+7L/sU4ABAIpVZWnoA5GkAAAAAElFTkSuQmCC",
  1813. 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==",
  1814. 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",
  1815. };
  1816. 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;}" +
  1817. `.ac_sp_top{background-image:url('${ sepImgs.top }')}` +
  1818. `.ac_sp_pre{background-image:url('${ sepImgs.pre }')}` +
  1819. `.ac_sp_next{background-image:url('${ sepImgs.next }')}` +
  1820. `.ac_sp_bottom{background-image:url('${ sepImgs.bottom }')}` +
  1821. `.ac_sp_next_gray{background-image:url('${ sepImgs.next_gray }')}` +
  1822. `.ac_sp_pre_gray{background-image:url('${ sepImgs.pre_gray }')}`
  1823. CONST.cssAutoInsert.add("preloadAutoPage", cssText)
  1824. }
  1825. if(CONST.curConfig.isBlockEnable) {
  1826. 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;}") // 公共自定义样式
  1827. }
  1828. if(CONST.curConfig.isFaviconEnable) {
  1829. CONST.cssAutoInsert.add("faviconStyle", CONST.adsCSSList.faviconStyle) // 插入Favicon图标
  1830. }
  1831. if(CONST.curConfig.isBlockEnable || CONST.curConfig.isFaviconEnable) {
  1832. CONST.cssAutoInsert.add("lineTitleFix", 'body[haosou] .res-title {display: inline-flex;}') // 插入Favicon图标
  1833. }
  1834. if(CONST.curConfig.isALineDisable) {
  1835. CONST.cssAutoInsert.add("alinkEnable", "a,a em{text-decoration:none !important}")
  1836. }
  1837. if(CONST.curConfig.isCounterEnable) {
  1838. CONST.cssAutoInsert.add("counterStyle", ".AC-CounterT{background:#FD9999}body #sp-ac-container{position:fixed;top:3.9vw;right:8.8vw}")
  1839. }
  1840. // if(CONST.options.useItem.SiteTypeID === CONST.options.google.SiteTypeID && CONST.curConfig.useBaiduLogo) {
  1841. // CONST.cssAutoInsert.add("useBaiduLogo", "") // 谷歌使用百度LOGO
  1842. // }
  1843.  
  1844. /*****自定义样式最后加载*****/
  1845. if (CONST.curConfig.commonStyleEnable) {
  1846. CONST.cssAutoInsert.add("commonStyle", CONST.adsCSSList.commonStyle) // 公共自定义样式
  1847. }
  1848. if (CONST.curConfig.customStyleEnable) {
  1849. CONST.cssAutoInsert.add("customStyle", CONST.adsCSSList.customStyle) // 站点自定义样式
  1850. }
  1851. }
  1852. pagerBind() {
  1853. const ShowPager = {
  1854. getFullHref: function(e) {
  1855. if (e === null) return '';
  1856. "string" != typeof e && (e = e.getAttribute("href"));
  1857. var t = this.getFullHref.a;
  1858. return t || (this.getFullHref.a = t = document.createElement("a")), t.href = e, t.href;
  1859. },
  1860. createDocumentByString: function(str) {
  1861. // string转为DOM
  1862. if (!str) {
  1863. console.error("[AC-Script]", 'No string found to be converted to DOM');
  1864. return;
  1865. }
  1866.  
  1867. if (document.documentElement.nodeName !== 'HTML') {
  1868. return new DOMParser().parseFromString(str, 'application/xhtml+xml');
  1869. }
  1870. var doc;
  1871.  
  1872. MyApi.safeFunc(() => {
  1873. // firefox and chrome 30+,Opera 12 会报错
  1874. doc = new DOMParser().parseFromString(str, 'text/html');
  1875. if (doc) {
  1876. return doc;
  1877. }
  1878. })
  1879.  
  1880. if (document.implementation.createHTMLDocument) {
  1881. doc = document.implementation.createHTMLDocument('superPreloader');
  1882. } else {
  1883. MyApi.safeFunc(() => {
  1884. doc = document.cloneNode(false);
  1885. doc.appendChild(doc.importNode(document.documentElement, false));
  1886. doc.documentElement.appendChild(doc.createElement('head'));
  1887. doc.documentElement.appendChild(doc.createElement('body'));
  1888. })
  1889. }
  1890.  
  1891. if (!doc) return;
  1892. var range = document.createRange();
  1893. range.selectNodeContents(document.body);
  1894. var fragment = range.createContextualFragment(str);
  1895. doc.body.appendChild(fragment);
  1896. var headChildNames = {
  1897. TITLE: true,
  1898. META: true,
  1899. LINK: true,
  1900. STYLE: true,
  1901. BASE: true
  1902. };
  1903. var child;
  1904. var body = doc.body;
  1905. var bchilds = body.childNodes;
  1906.  
  1907. for (let i = bchilds.length - 1; i >= 0; i--) {
  1908. // 移除head的子元素
  1909. child = bchilds[i];
  1910. if (headChildNames[child.nodeName]) body.removeChild(child);
  1911. }
  1912.  
  1913. return doc;
  1914. },
  1915. loadMorePage: async function() {
  1916. if (CONST.options.useItem.pager) {
  1917. let curPageEle = MyApi.getElementByXpath(CONST.options.useItem.pager.nextLink);
  1918. var url = this.getFullHref(curPageEle);
  1919. if (CONST.options.useItem.SiteTypeID === CONST.options.google.SiteTypeID) {
  1920. if (navigator.userAgent.toLowerCase().includes('macintosh')) {
  1921. // MARK 为了兼容百度在safari下的
  1922. url = url.replace('https://', 'http://');
  1923. }
  1924. }
  1925. if (url === '') return;
  1926. if (CONST.options.useItem.pageUrl === url) {
  1927. console.error("[AC-Script]", "翻页到达底部了 - 或者异常 - 出现异常请直接反馈作者修改");
  1928. return;
  1929. }// 不会重复加载相同的页面
  1930. console.log("加载翻页地址:" + url)
  1931. CONST.options.useItem.pageUrl = url;
  1932. // 对url的数据进行读取
  1933. CONST.options.useItem.pager.startFilter && curSite.pager.startFilter();
  1934. GM_xmlhttpRequest({
  1935. url: url,
  1936. method: "GET",
  1937. timeout: 5000,
  1938. onload: function(response) {
  1939. try {
  1940. var newBody = ShowPager.createDocumentByString(response.responseText);
  1941.  
  1942. const [Rule_insertTo = '', Rule_insertMode = 1] = CONST.options.useItem.pager.HT_insert || []
  1943. let pageElems = MyApi.getAllElements(CONST.options.useItem.pager.pageElement, newBody, newBody);
  1944. const scriptElems = MyApi.getAllElements('//script', newBody, newBody);
  1945.  
  1946. let toElement;
  1947.  
  1948. if (pageElems.length) {
  1949. const curPageElems = MyApi.getAllElements(CONST.options.useItem.pager.pageElement, document, document)
  1950. const pELast = curPageElems[curPageElems.length - 1];
  1951. toElement = pELast.nextSibling ? pELast.nextSibling : pELast.parentNode.appendChild(document.createTextNode(' '));
  1952. }
  1953. if (Rule_insertTo) {
  1954. toElement = MyApi.getAllElements(Rule_insertTo)[0];
  1955. }
  1956. if (pageElems.length >= 0) {
  1957. // 处理最后一个翻页按钮
  1958. let nextEs = document.querySelectorAll("#sp-sp-gonext");
  1959. if (nextEs.length > 0) {
  1960. let lastE = nextEs[nextEs.length - 1];
  1961. lastE.classList.replace("ac_sp_next_gray", "ac_sp_next");
  1962. }
  1963. // 插入翻页按钮元素
  1964. CONST.options.useItem.pageNum++;
  1965. let addTo = "beforeend";
  1966. if (Rule_insertMode === 1) addTo = "beforebegin";
  1967.  
  1968. const insertPager = document.createElement('div')
  1969. insertPager.id = "sp-separator-ACX".replace(/ACX/gm, CONST.options.useItem.pageNum)
  1970. insertPager.className = "sp-separator AC"
  1971. insertPager.innerHTML = `
  1972. <a class='sp-sp-nextlink' target='_blank'><b>第 <span style='color:#595959!important;'>ACX</span> 页</b></a>
  1973. <span id="sp-sp-gotop" class='ac_sp_top' title='去到顶部'></span>
  1974. <span id="sp-sp-gopre" class='${ CONST.options.useItem.pageNum <= 2 ? "ac_sp_pre_gray" : "ac_sp_pre" }' title='上滚一页' ></span>
  1975. <span id="sp-sp-gonext" class='ac_sp_next_gray' title='下滚一页'></span>
  1976. <span id="sp-sp-gobottom" class='ac_sp_bottom' title='去到底部' ></span>`
  1977. .replace(/ACX/gm, CONST.options.useItem.pageNum);
  1978.  
  1979. if(Rule_insertMode === 1) {
  1980. toElement.parentNode.insertBefore(insertPager, toElement)
  1981. // 插入新页面元素
  1982. pageElems.forEach(function(one) {
  1983. toElement.parentNode.insertBefore(one, toElement)
  1984. });
  1985. } else {
  1986. toElement.appendChild(insertPager)
  1987.  
  1988. pageElems.forEach(function(one) {
  1989. toElement.appendChild(one)
  1990. });
  1991. }
  1992.  
  1993. document.querySelectorAll(".sp-separator.AC:not([bind])").forEach(function(per) {
  1994. per.setAttribute("bind", 1);
  1995. per.addEventListener("click", PageFunc.ac_spfunc);
  1996. });
  1997.  
  1998. if(CONST.options.useItem.pager.afertPagerAutoCallFunc) {
  1999. CONST.options.useItem.pager.afertPagerAutoCallFunc(pageElems, scriptElems)
  2000. }
  2001.  
  2002. // 替换待替换元素 - 一般是替换翻页的按钮
  2003. try {
  2004. if (CONST.options.useItem.pager.replaceE) {
  2005. let oriE = MyApi.getAllElements(CONST.options.useItem.pager.replaceE);
  2006. let repE = MyApi.getAllElements(CONST.options.useItem.pager.replaceE, newBody, newBody);
  2007. if (oriE.length === repE.length) {
  2008. if (oriE.length === 0) {
  2009. throw "翻页-替换翻页元素 无 'replaceE' 待替换的";
  2010. }
  2011. for (let i = 0; i < oriE.length; i++) {
  2012. oriE[i].outerHTML = repE[i].outerHTML;
  2013. }
  2014. }
  2015. }
  2016. } catch (e) {
  2017. console.log(e);
  2018. }
  2019. }
  2020. } catch (e) {
  2021. console.log(e);
  2022. }
  2023.  
  2024. CONST.lock.pageLoadingLocked = false;
  2025. },
  2026. onerror: function() {
  2027. CONST.lock.pageLoadingLocked = false;
  2028. }
  2029. });
  2030. }
  2031. },
  2032. };
  2033. console.mylog('pager已绑定成功')
  2034. this.windowscroll(async (direction, e) => {
  2035. if (direction === "down") { // 下滑才准备翻页
  2036. let spl = document.querySelector("#sp-fw-a_enable");
  2037. // 开启后,且在非(suprepreloader启用)时均可
  2038. if (CONST.curConfig.isAutopage === true && !(spl && spl.checked === true) && document.documentElement) {
  2039. const scrollTop = document.documentElement.scrollTop || window.pageYOffset || document.body.scrollTop;
  2040. let scrollDelta = 888;
  2041. if (document.documentElement.scrollHeight <= document.documentElement.clientHeight + scrollTop + scrollDelta && CONST.lock.pageLoadingLocked === false) {
  2042. console.mylog('开始进行翻页')
  2043. CONST.lock.pageLoadingLocked = true;
  2044. if (CONST.options.useItem.SiteTypeID === CONST.options.duck.SiteTypeID) { // 可以用已有的方法来实现了
  2045. if (!CONST.curConfig.optimizeDuck || +CONST.curConfig.adsStyleMode >= 3) { // 如果没有开启,那么手动翻页 || 如果是双列的时候,似乎并不会自动触发翻页效果
  2046. const node = document.querySelector("#links .result--more a")
  2047. node && node.click();
  2048. setTimeout(function() {
  2049. CONST.lock.pageLoadingLocked = false;
  2050. }, 5000);
  2051. }
  2052. } else {
  2053. await ShowPager.loadMorePage();
  2054. if (CONST.options.useItem.pager && CONST.options.useItem.pager.stylish) {
  2055. CONST.cssAutoInsert.add('autoPager', CONST.options.useItem.pager.stylish)
  2056. } else {
  2057. setTimeout(function() {
  2058. CONST.lock.pageLoadingLocked = false;
  2059. }, 5000);
  2060. console.mylog('当前站点没有配置pager')
  2061. }
  2062. }
  2063. }
  2064. }
  2065. }
  2066. });
  2067. }
  2068. windowscroll(fn = () => {}) {
  2069. let beforeScrollTop = document.documentElement.scrollTop
  2070. window.addEventListener("scroll", function(e) {
  2071. var afterScrollTop = document.documentElement.scrollTop,
  2072. delta = afterScrollTop - beforeScrollTop;
  2073. if (delta === 0) return false;
  2074. fn(delta > 0 ? "down" : "up", e);
  2075. beforeScrollTop = afterScrollTop;
  2076. }, false);
  2077. }
  2078. ac_spfunc(e) {
  2079. console.error("这里有问题")
  2080. e.stopPropagation();
  2081. var t, r = e.currentTarget;
  2082. const Tween = {
  2083. Linear: function Linear(e, t, r, n) {
  2084. return r * e / n + t;
  2085. },
  2086. Quad: {
  2087. easeIn: function easeIn(e, t, r, n) {
  2088. return r * (e /= n) * e + t;
  2089. },
  2090. easeOut: function easeOut(e, t, r, n) {
  2091. return -r * (e /= n) * (e - 2) + t;
  2092. },
  2093. easeInOut: function easeInOut(e, t, r, n) {
  2094. return (e /= n / 2) < 1 ? r / 2 * e * e + t : -r / 2 * (--e * (e - 2) - 1) + t;
  2095. }
  2096. },
  2097. Cubic: {
  2098. easeIn: function easeIn(e, t, r, n) {
  2099. return r * (e /= n) * e * e + t;
  2100. },
  2101. easeOut: function easeOut(e, t, r, n) {
  2102. return r * ((e = e / n - 1) * e * e + 1) + t;
  2103. },
  2104. easeInOut: function easeInOut(e, t, r, n) {
  2105. return (e /= n / 2) < 1 ? r / 2 * e * e * e + t : r / 2 * ((e -= 2) * e * e + 2) + t;
  2106. }
  2107. },
  2108. Quart: {
  2109. easeIn: function easeIn(e, t, r, n) {
  2110. return r * (e /= n) * e * e * e + t;
  2111. },
  2112. easeOut: function easeOut(e, t, r, n) {
  2113. return -r * ((e = e / n - 1) * e * e * e - 1) + t;
  2114. },
  2115. easeInOut: function easeInOut(e, t, r, n) {
  2116. return (e /= n / 2) < 1 ? r / 2 * e * e * e * e + t : -r / 2 * ((e -= 2) * e * e * e - 2) + t;
  2117. }
  2118. },
  2119. Quint: {
  2120. easeIn: function easeIn(e, t, r, n) {
  2121. return r * (e /= n) * e * e * e * e + t;
  2122. },
  2123. easeOut: function easeOut(e, t, r, n) {
  2124. return r * ((e = e / n - 1) * e * e * e * e + 1) + t;
  2125. },
  2126. easeInOut: function easeInOut(e, t, r, n) {
  2127. return (e /= n / 2) < 1 ? r / 2 * e * e * e * e * e + t : r / 2 * ((e -= 2) * e * e * e * e + 2) + t;
  2128. }
  2129. },
  2130. Sine: {
  2131. easeIn: function easeIn(e, t, r, n) {
  2132. return -r * Math.cos(e / n * (Math.PI / 2)) + r + t;
  2133. },
  2134. easeOut: function easeOut(e, t, r, n) {
  2135. return r * Math.sin(e / n * (Math.PI / 2)) + t;
  2136. },
  2137. easeInOut: function easeInOut(e, t, r, n) {
  2138. return -r / 2 * (Math.cos(Math.PI * e / n) - 1) + t;
  2139. }
  2140. },
  2141. Expo: {
  2142. easeIn: function easeIn(e, t, r, n) {
  2143. return 0 == e ? t : r * Math.pow(2, 10 * (e / n - 1)) + t;
  2144. },
  2145. easeOut: function easeOut(e, t, r, n) {
  2146. return e == n ? t + r : r * (1 - Math.pow(2, -10 * e / n)) + t;
  2147. },
  2148. easeInOut: function easeInOut(e, t, r, n) {
  2149. 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;
  2150. }
  2151. },
  2152. Circ: {
  2153. easeIn: function easeIn(e, t, r, n) {
  2154. return -r * (Math.sqrt(1 - (e /= n) * e) - 1) + t;
  2155. },
  2156. easeOut: function easeOut(e, t, r, n) {
  2157. return r * Math.sqrt(1 - (e = e / n - 1) * e) + t;
  2158. },
  2159. easeInOut: function easeInOut(e, t, r, n) {
  2160. return (e /= n / 2) < 1 ? -r / 2 * (Math.sqrt(1 - e * e) - 1) + t : r / 2 * (Math.sqrt(1 - (e -= 2) * e) + 1) + t;
  2161. }
  2162. },
  2163. Elastic: {
  2164. easeIn: function easeIn(e, t, r, n, a, o) {
  2165. return 0 == e ? t : 1 == (e /= n) ? t + r : (o || (o = .3 * n), !a || a < Math.abs(r) ? (a = r,
  2166. 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);
  2167. var i;
  2168. },
  2169. easeOut: function easeOut(e, t, r, n, a, o) {
  2170. return 0 == e ? t : 1 == (e /= n) ? t + r : (o || (o = .3 * n), !a || a < Math.abs(r) ? (a = r,
  2171. 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);
  2172. var i;
  2173. },
  2174. easeInOut: function easeInOut(e, t, r, n, a, o) {
  2175. return 0 == e ? t : 2 == (e /= n / 2) ? t + r : (o || (o = n * (.3 * 1.5)), !a || a < Math.abs(r) ? (a = r,
  2176. 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);
  2177. var i;
  2178. }
  2179. },
  2180. Back: {
  2181. easeIn: function easeIn(e, t, r, n, a) {
  2182. return null == a && (a = 1.70158), r * (e /= n) * e * ((a + 1) * e - a) + t;
  2183. },
  2184. easeOut: function easeOut(e, t, r, n, a) {
  2185. return null == a && (a = 1.70158), r * ((e = e / n - 1) * e * ((a + 1) * e + a) + 1) + t;
  2186. },
  2187. easeInOut: function easeInOut(e, t, r, n, a) {
  2188. 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;
  2189. }
  2190. },
  2191. Bounce: {
  2192. easeIn: function easeIn(e, t, r, n) {
  2193. return r - Tween.Bounce.easeOut(n - e, 0, r, n) + t;
  2194. },
  2195. easeOut: function easeOut(e, t, r, n) {
  2196. 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;
  2197. },
  2198. easeInOut: function easeInOut(e, t, r, n) {
  2199. 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;
  2200. }
  2201. }
  2202. };
  2203. const TweenM = ["Linear", "Quad", "Cubic", "Quart", "Quint", "Sine", "Expo", "Circ", "Elastic", "Back", "Bounce"];
  2204. const TweenEase = ["easeIn", "easeOut", "easeInOut"];
  2205. var prefs = {
  2206. s_method: 3,
  2207. s_ease: 2,
  2208. s_FPS: 60,
  2209. s_duration: 333,
  2210. };
  2211.  
  2212. function getRelativeDiv(e) {
  2213. var t = r.id;
  2214. return (t = t.replace(/(sp-separator-)(.+)/, (function(t, r, n) {
  2215. return r + String(Number(n) + ("pre" == e ? -1 : 1));
  2216. }))) ? document.getElementById(t) : null;
  2217. }
  2218.  
  2219. function sp_transition(e, t) {
  2220. var r = sp_transition.TweenF;
  2221. r || (r = (r = Tween[TweenM[prefs.s_method]])[TweenEase[prefs.s_ease]] || r, sp_transition.TweenF = r);
  2222. var n = 1e3 / prefs.s_FPS, a = 0, o = e, i = t - e, s = Math.ceil(prefs.s_duration / n),
  2223. c = window.scrollX;
  2224. !function transition() {
  2225. var e = Math.ceil(r(a, o, i, s));
  2226. window.scroll(c, e), a < s && (a++, setTimeout(transition, n));
  2227. }();
  2228. }
  2229.  
  2230. function scrollIt(e, t) {
  2231. sp_transition(e, t);
  2232. }
  2233.  
  2234. switch (e.target.id) {
  2235. case "sp-sp-gotop":
  2236. scrollIt(window.scrollY, 0);
  2237. break;
  2238.  
  2239. case "sp-sp-gopre":
  2240. var n = getRelativeDiv("pre");
  2241. if (!n) return;
  2242. t = window.scrollY;
  2243. var a = n.getBoundingClientRect().top;
  2244. a = t - (r.getBoundingClientRect().top - a);
  2245. scrollIt(t, a);
  2246. break;
  2247.  
  2248. case "sp-sp-gonext":
  2249. var o = getRelativeDiv("next");
  2250. if (!o) return;
  2251. t = window.scrollY;
  2252. var i = o.getBoundingClientRect().top;
  2253. i = t + (-r.getBoundingClientRect().top + i);
  2254. scrollIt(t, i);
  2255. break;
  2256.  
  2257. case "sp-sp-gobottom":
  2258. scrollIt(window.scrollY, Math.max(document.documentElement.scrollHeight, document.body.scrollHeight));
  2259. }
  2260. }
  2261. bingAutoScrollFix() {
  2262. document.addEventListener('visibilitychange', function() {
  2263. if (document.visibilityState === 'hidden') {
  2264. CONST.bingScrollPos = document.documentElement.scrollTop;
  2265. } else if (document.visibilityState === 'visible') {
  2266. setTimeout(() => {
  2267. if(CONST.bingScrollPos !== 0 && document.documentElement.scrollTop !== CONST.bingScrollPos) {
  2268. console.error('触发滚动条变更:', CONST.bingScrollPos, document.documentElement.scrollTop)
  2269. document.documentElement.scrollTop = CONST.bingScrollPos
  2270. }
  2271. }, 50)
  2272. }
  2273. });
  2274. }
  2275. bingFaviconPagerFix() {
  2276. document.querySelectorAll('div.rms_iac').forEach(one => {
  2277. const height = one.dataset.height
  2278. const width = one.dataset.width
  2279. const toClass = one.dataset.class
  2280. const imgSrc = one.dataset.src
  2281. const bm = one.dataset.bm
  2282. if(imgSrc) {
  2283. one.outerHTML = `<img src="${imgSrc}" height="${height}" width="${width}" data-priority="2" role="presentation" class="${toClass}" data-bm="${bm}">`
  2284. }
  2285. })
  2286. }
  2287. }
  2288. class PageBlockClass {
  2289. constructor() {
  2290. this.curSite = CONST.options.useItem
  2291. this.regListRule = []
  2292. this._updateRegListRule()
  2293. }
  2294.  
  2295. async start() {
  2296. const needCheckClass = (this.curSite.MainType + ',').split(',').join(":not([bhandle]),")
  2297. let checkNodes = document.querySelectorAll(needCheckClass.substring(0, needCheckClass.length - 1));
  2298. for (let i = 0; i < checkNodes.length; i++) {
  2299. let curNode = checkNodes[i];
  2300. try {
  2301. let faviconNode = curNode.querySelector(this.curSite.FaviconType);
  2302. let host = PageFunc.getNodeHost(faviconNode).curHost;
  2303. let faNode = curNode.querySelector(this.curSite.BlockType);
  2304. let nodeStyle = "display:unset;";
  2305. if (!CONST.curConfig.isBlockBtnDisplay) {
  2306. nodeStyle = "display:none;";
  2307. }
  2308. // 避免父节点出现两个block按钮
  2309. if (faNode && !faNode.hasAttribute('hasInsert')) {
  2310. faNode.setAttribute("hasInsert", "1");
  2311. let insertTo = faNode.parentNode
  2312. if(CONST.options.useItem.SiteTypeID === CONST.options.google.SiteTypeID) {
  2313. insertTo = faNode
  2314. }
  2315. 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>`);
  2316. }
  2317. curNode.setAttribute("bhandle", "1");
  2318. } catch (e) {
  2319. console.error(e)
  2320. const failed_count = +(curNode.getAttribute('failed_count') || 1)
  2321. curNode.setAttribute('failed_count', failed_count + 1)
  2322. if (failed_count > 3) {
  2323. curNode.setAttribute("bhandle", "1");
  2324. }
  2325. }
  2326. }
  2327. this._initListener();
  2328. await this.renderDisplay()
  2329. }
  2330. async renderDisplay() {
  2331. // 增加checking中的检查,避免多次重复调用,减少cpu消耗
  2332. if (CONST.lock.isBlockChecking) return
  2333. CONST.lock.isBlockChecking = true
  2334.  
  2335. let checkNodes = document.querySelectorAll(this.curSite.MainType);
  2336. if([...checkNodes].every(one => one.dataset.checked) && CONST.lock.afterBlockChangeChecked) {
  2337. CONST.lock.isBlockChecking = false
  2338. return
  2339. }
  2340. const regList = this.regListRule
  2341. let flag = "ac-needhide";
  2342. for (let i = 0; i < checkNodes.length; i++) {
  2343. try {
  2344. let curNode = checkNodes[i];
  2345. if (curNode.querySelector("button[ac-user-alter]") != null) continue; // 用户手动点过显示的,那么跳过check
  2346. // 减少数据计算
  2347. let { curHost = "", curUrl = "" } = PageFunc.getNodeHost(curNode.querySelector(this.curSite.FaviconType));
  2348. if (!curHost) continue
  2349. let BlockBtn = curNode.querySelector(".ghhider.ghhb");
  2350. BlockBtn.dataset.host = BlockBtn.dataset.meta = curHost;
  2351. BlockBtn.title = this._getBlockBtnTitle(curHost);
  2352. // 减少数据计算
  2353. if (curHost && regList.findIndex(one => {
  2354. try {
  2355. return one.test(curHost || curUrl); // 耗时操作
  2356. } catch (e) {
  2357. return one === curHost;
  2358. }
  2359. }) >= 0) {
  2360. // 只检查在屏蔽表中的数据
  2361. if (!curNode.hasAttribute(flag)) {
  2362. curNode.setAttribute(flag, "1");
  2363. if (CONST.curConfig.isBlockResultDisplay) { // 对于不显示的数据可以进行移除操作
  2364. curNode.remove();
  2365. continue;
  2366. }
  2367. let curTitle = curNode.querySelector(this.curSite.BlockType);
  2368. curTitle = curTitle.innerText || curTitle.textContent;
  2369.  
  2370. (function(xcur) {
  2371. const blockShow = xcur.querySelector(".blockShow");
  2372. if(!blockShow) {
  2373. curNode.insertAdjacentHTML("afterBegin", `<span class="blockShow" title="如果需要一直显示,请在自定义中DIY目录移除本地址">${ curTitle }&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; -block by ${ curHost }</span>`);
  2374. // 已经屏蔽之后的内容,点击一下显示原始内容
  2375. xcur.addEventListener("click", function(env) {
  2376. if(!xcur.querySelector(".blockShow")) return
  2377. xcur.querySelector("button.ghhider").setAttribute("ac-user-alter", "1"); // 这个属性用于保持在DOM更新时,按钮不变
  2378. xcur.removeAttribute(flag);
  2379. delete xcur.dataset.checked
  2380. MyApi.safeFunc(function() {
  2381. xcur.querySelector(".blockShow").remove();
  2382. });
  2383. env.stopPropagation();
  2384. env.preventDefault()
  2385. });
  2386. }
  2387. })(curNode);
  2388. }
  2389. } else {
  2390. curNode.removeAttribute(flag);
  2391. }
  2392. curNode.dataset.checked = '1'
  2393. } catch (e) {}
  2394. }
  2395. CONST.lock.isBlockChecking = false
  2396. CONST.lock.afterBlockChangeChecked = true
  2397. }
  2398. async _updateRegListRule() {
  2399. this.regListRule = CONST.blockRuleList.filter(one => one).map(one => {
  2400. try{
  2401. return new RegExp(one.replace("*", ".*"))
  2402. }catch (e){
  2403. return one
  2404. }
  2405. })
  2406. }
  2407. _initListener() {
  2408. let checkNodes = document.querySelectorAll("button.ghhider:not([acEnv])");
  2409.  
  2410. checkNodes.forEach(one => {
  2411. one.addEventListener("click", this._doHideEnv);
  2412. one.setAttribute("acEnv", "0");
  2413. })
  2414. }
  2415. _doHideEnv(env) {
  2416. // 先插入数据---记得还要写入存储
  2417. let node = env.sourceTarget || env.target;
  2418. let host = node.dataset.host;
  2419. if (+node.getAttribute("ac-user-alter") === 1) {
  2420. // 已经屏蔽之后,再次点击block应该是取消状态
  2421. node.removeAttribute("ac-user-alter");
  2422. CONST.blockRuleList.acremove(host);
  2423. } else {
  2424. // 正常屏蔽操作
  2425. node.removeAttribute("ac-user-alter");
  2426. CONST.blockRuleList.acpush(host);
  2427. }
  2428. CONST.saveBlockRule()
  2429. env.stopPropagation();
  2430. }
  2431. _getBlockBtnTitle(host) {
  2432. return `点击即可屏蔽 ${ host } 放开,需要在自定义中手动配置放开`;
  2433. }
  2434. }
  2435.  
  2436. const PageFunc = new PageFuncClass()
  2437. const PageBlockFunc = new PageBlockClass()
  2438.  
  2439. !await (async function() {
  2440. /***Google双列修复***/
  2441. CONST.addIntervalTrigger('google', 'now', (counter) => {
  2442. function findAndMarkP2Line() {
  2443.  
  2444. function markFatherChild(child, father) {
  2445. const child_checkedAttr = child.getAttribute('two-checked') || 0
  2446. const father_checkedAttr = father.getAttribute('two-checked') || 0
  2447. child.setAttribute('two-child', 1)
  2448. child.setAttribute('two-checked', +child_checkedAttr + 1)
  2449. father.setAttribute('two-father', 1)
  2450. father.setAttribute('two-checked', +father_checkedAttr + 1)
  2451. return father
  2452. }
  2453.  
  2454. // 检查的事preNode 和 curNode
  2455. // 但是需要先判断curNode和fatherNode有没有
  2456. function getTrueFatherChild(preNode, curNode, fatherNode) {
  2457. const minItemHeight = 60
  2458. const father_curPossible = curNode.offsetHeight > minItemHeight && fatherNode.offsetHeight / curNode.offsetHeight > 1.5
  2459. const father_anotherPossible = [...fatherNode.children].some(one => {
  2460. return one !== curNode && one.offsetHeight > minItemHeight && fatherNode.offsetHeight / one.offsetHeight > 5;
  2461. })
  2462. const fatherNotMain = fatherNode.id === "cnt";
  2463. // 先检查当前父节点是否符合要求
  2464. if (!fatherNotMain && father_curPossible && father_anotherPossible) {
  2465. return markFatherChild(curNode, fatherNode)
  2466. } else {
  2467. const now_curPossible = preNode.offsetHeight > minItemHeight && curNode.offsetHeight / preNode.offsetHeight > 1.5
  2468. const now_anotherPossible = [...curNode.children].some(one => {
  2469. return one !== preNode && one.offsetHeight > minItemHeight && curNode.offsetHeight / one.offsetHeight > 5;
  2470. })
  2471. // 父节点不行的话,那么检查子节点是否符合要求
  2472. if(now_curPossible && now_anotherPossible) {
  2473. return markFatherChild(preNode, curNode)
  2474. }
  2475. return null
  2476. }
  2477. }
  2478.  
  2479. // 标记自身
  2480. function MarkMine(curItem) {
  2481. let maxHeight = 9, curHeight = 1
  2482. let preNode = curItem
  2483. while (curHeight < maxHeight) {
  2484. const fatherNode = curItem.parentNode
  2485. let attrV = curItem.getAttribute('two-checked') || 0
  2486. if (!curItem.hasAttribute('two-checked') || +attrV < 8) {
  2487. const node = getTrueFatherChild(preNode, curItem, fatherNode)
  2488. if (node) {
  2489. return node
  2490. }
  2491. }
  2492. curItem.setAttribute('two-checked', +attrV + 1)
  2493. preNode = curItem
  2494. curItem = fatherNode
  2495. curHeight++
  2496. }
  2497. return null
  2498. }
  2499.  
  2500. const gList = document.querySelectorAll(".g:not([two-checked*='8']), .cUnQKe:not([two-checked*='8']), .Ww4FFb:not([two-checked*='8'])")
  2501.  
  2502. return [...gList].filter(one => MarkMine(one))
  2503. }
  2504.  
  2505. const valid = location.href.search(/(&|\?)(q|kw)=/) >= 0 ||
  2506. document.querySelector(".g, div[two-father]")
  2507.  
  2508. if(counter % 4 === 0) {
  2509. if (CONST.curConfig.useBaiduLogo) {
  2510. PageFunc.GoogleInBaiduMode()
  2511. }
  2512. if (CONST.curConfig.isAdsEnable) {
  2513. PageFunc.removeAds.removeGoogleAd()
  2514. }
  2515. }
  2516. if (!valid) {
  2517. CONST.curConfig.enableCSS = false
  2518. return
  2519. }
  2520. findAndMarkP2Line()
  2521. }, 50, 10000000)
  2522. /***Baidu***/
  2523. CONST.addIntervalTrigger('baidu', 'body', () => {
  2524. // 没有(百度搜索结果的标志-[存在]百度的内容) return;
  2525. const valid = location.href.search(/(&|\?)(wd|word)=/) >= 0 ||
  2526. document.querySelector("#content_left") || document.querySelector('.s_form').offsetHeight < 100
  2527. if (!valid) {
  2528. console.mylog('无效页面,不存在搜索结构')
  2529. CONST.curConfig.enableCSS = false
  2530. return
  2531. }
  2532. if (CONST.curConfig.isAdsEnable) {
  2533. PageFunc.removeAds.removeBaiduAd()
  2534. }
  2535. if (CONST.curConfig.doRemoveSug) { // 不启用移动预测[默认]
  2536. PageFunc.acSetCookie("ORIGIN", 2, "www.baidu.com");
  2537. PageFunc.acSetCookie("ISSW", 1);
  2538. PageFunc.acSetCookie("ISSW", 1, "www.baidu.com");
  2539. }
  2540. if (location.href.includes("tn=news")) {
  2541. if (!document.body.hasAttribute('news')) document.body.setAttribute("news", "1");
  2542. } else {
  2543. document.body.removeAttribute("news");
  2544. }
  2545. }, 200, 10000000)
  2546. /***Haosou***/
  2547. CONST.addIntervalTrigger('haosou', 'body', () => {
  2548. if (CONST.curConfig.isAdsEnable) {
  2549. PageFunc.removeAds.removeHaosouAd()
  2550. }
  2551. }, 200, 10000000)
  2552. /***Bing***/
  2553. CONST.addIntervalTrigger('bing', 'body', () => {
  2554. if (CONST.curConfig.isAdsEnable) {
  2555. PageFunc.removeAds.removeBingAd()
  2556. }
  2557. PageFunc.bingAutoScrollFix()
  2558. PageFunc.bingFaviconPagerFix()
  2559. }, 200, 10000000)
  2560. /***DuckDuckgo***/
  2561. CONST.addIntervalTrigger('duck', 'body', () => {
  2562. if (CONST.curConfig.optimizeDuck) {
  2563. setTimeout(function() {
  2564. MyApi.safeFunc(() => {
  2565. DDG.settings.set("kn", 1, { // 新窗口打开页面
  2566. saveToCloud: true,
  2567. forceTheme: true
  2568. });
  2569. DDG.settings.set("kav", 1, { // 连续显示搜索结果
  2570. saveToCloud: true,
  2571. forceTheme: true
  2572. });
  2573. })
  2574. }, 3000);
  2575. }
  2576. }, 200, 10000000)
  2577. /***All***/
  2578. CONST.addIntervalTrigger('all', 'body', () => {
  2579. PageFunc.RedirectHandle()
  2580. if (CONST.curConfig.isFaviconEnable && typeof (CONST.options.useItem.FaviconType) !== 'undefined') { // 显示favicon图标
  2581. // 延迟2秒加载,减少可能出现的问题
  2582. PageFunc.addFavicon(document.querySelectorAll(CONST.options.useItem.FaviconType)); // 添加Favicon显示
  2583. } else {
  2584. document.querySelectorAll(CONST.options.useItem.FaviconType).forEach((one) => {
  2585. one.removeAttribute("ac_faviconstatus");
  2586. })
  2587. }
  2588. if (CONST.curConfig.isCounterEnable) {
  2589. // 延迟加载,避免页面出现js问题
  2590. setTimeout(() => {
  2591. PageFunc.addCounter(document.querySelectorAll(CONST.options.useItem.CounterType)); // 显示计数器
  2592. }, 800)
  2593. } else {
  2594. document.querySelectorAll(".AC-CounterT").forEach(one => {
  2595. one.parentElement.removeAttribute('SortIndex');
  2596. one.remove()
  2597. })
  2598. }
  2599.  
  2600. // 双列模式下,自动禁用右侧栏
  2601. if (!CONST.curConfig.isRightDisplayEnable || CONST.curConfig.adsStyleMode >= 3) {
  2602. document.body.classList.remove("showRight")
  2603. } else {
  2604. if (!document.body.classList.contains('showRight')) {
  2605. document.body.classList.add("showRight")
  2606. }
  2607. }
  2608.  
  2609. if (CONST.curConfig.isBlockEnable && CONST.curConfig.isRedirectEnable) {
  2610. PageBlockFunc.start()
  2611. }
  2612. }, 200, 10000000)
  2613.  
  2614. // CONST.enableCSS = 如果生效,那么插入样式表,否则跳过样式表插入
  2615. // CONST.curConfig = 网站配置,同步过来的,以及动态被修改的
  2616. // CONST.options.useItem = 网站的静态选择器
  2617.  
  2618. MyApi.safeWaitFunc('html', () => {
  2619. GM_addValueChangeListener('SyncConfig', (key, oldVal, newVal = '{}', remote) => {
  2620. const syncOptions = JSON.parse(newVal)
  2621. CONST.renewConfig(syncOptions)
  2622. if (syncOptions.refreshUrl) MyApi.refreshAfter(500)
  2623. })
  2624. PageFunc.dataChangeFireCallback()
  2625. watch(CONST.curConfig, async() => {
  2626. await CONST.loadSiteCSS()
  2627. PageFunc.dataChangeFireCallback()
  2628. })
  2629. watch(CONST.cssFavionList, ()=> {
  2630. 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;}'
  2631. CONST.adsCSSList.faviconStyle = Object.entries(CONST.cssFavionList.list).reduce((preCSS, cur) => {
  2632. const [, { tagName = '', url = '' }] = cur
  2633. let nowCSS = ''
  2634. if (url) {
  2635. // https://www.xtwind.com/api/index.php?url=???? 挂了。。。
  2636. // https://statics.dnspod.cn/proxy_favicon/_/favicon?domain=sina.cn
  2637. // www.google.com/s2/favicons?domain=764350177.lofter.com
  2638. //如果地址不正确,那么丢弃
  2639. const imgUrl = "https://favicon.yandex.net/favicon/v2/" + url + "?size=32"
  2640. nowCSS = tagName + `[data-favicon-t='${ url }']:before{background-image: url('${ imgUrl }');}`
  2641. }
  2642. return preCSS + nowCSS
  2643. }, baseCSS)
  2644. PageFunc.dataChangeFireCallback()
  2645. })
  2646. }, 20, true)
  2647. MyApi.safeWaitFunc('body', () => {
  2648. const insertName = CONST.curConfig.enableCSS ? CONST.options.siteName : (CONST.options.siteName + '_nocss')
  2649. if (!document.body.hasAttribute(insertName)) {
  2650. document.body.setAttribute(insertName, '1')
  2651. document.body.classList.add(insertName)
  2652. }
  2653. PageFunc.InsertSettingMenu()
  2654. if (CONST.curConfig.isAutopage) {
  2655. setTimeout(() => {
  2656. PageFunc.pagerBind()
  2657. }, 2000)
  2658. }
  2659. }, 20, true)
  2660. })()
  2661. })()