优雅的搜索引擎助手

“优雅的搜索引擎助手”方便用户在不同的搜索引擎之间跳转;支持自定义常用搜索引擎、关键词高亮渲染;还提供去除搜索链接重定向、屏蔽搜索结果广告、使用关键词过滤搜索结果、和自动更新检测等高级功能;兼容如Baidu、Google、Bing、Duckduckgo、Yandex、Sogou、Qwant、Ecosia、You、Startpage、Brave、Yahoo、Yep、Swisscows、searXNG等多个搜索引擎。

安装此脚本?
作者推荐脚本

您可能也喜欢字体渲染(自用脚本)

安装此脚本
  1. // ==UserScript==
  2. // @name Google & baidu Switcher (ALL in One)
  3. // @name:en Search Engine Assistant
  4. // @name:zh-CN 优雅的搜索引擎助手
  5. // @name:zh-TW 優雅的搜尋引擎助手
  6. // @name:ru помощник поисковых систем
  7. // @name:ja 優雅な検索エンジン助手
  8. // @version 2025.04.05.1
  9. // @author F9y4ng
  10. // @description “Elegant Search Engine Assistant” facilite la navigation entre moteurs de recherche, personnalise les préférences, met en évidence les mots-clés, élimine les redirections et publicités, et filtre les résultats. Compatible avec divers moteurs tels que Baidu, Google, Bing, Duckduckgo, Yandex, Sogou, Qwant, Ecosia, You, Startpage, Brave, etc.
  11. // @description:en "Elegant search engine assistant" allows switching between engines; supports custom engines, keyword highlighting; offers redirect removal, ad blocking, keyword filtering, and auto-updates; compatible with Baidu, Google, Bing, Duckduckgo, Yandex, Sogou, Qwant, Ecosia, You, Startpage, Brave, Yahoo, Yep, Swisscows, searXNG and more.
  12. // @description:zh-CN “优雅的搜索引擎助手”方便用户在不同的搜索引擎之间跳转;支持自定义常用搜索引擎、关键词高亮渲染;还提供去除搜索链接重定向、屏蔽搜索结果广告、使用关键词过滤搜索结果、和自动更新检测等高级功能;兼容如Baidu、Google、Bing、Duckduckgo、Yandex、Sogou、Qwant、Ecosia、You、Startpage、Brave、Yahoo、Yep、Swisscows、searXNG等多个搜索引擎。
  13. // @description:zh-TW 「優雅的搜尋引擎助手」方便使用者在不同的搜尋引擎之間跳轉;支援自定義常用搜尋引擎、關鍵詞高亮渲染;還提供去除搜尋連結重定向、遮蔽搜尋結果廣告、使用關鍵詞過濾搜尋結果、和自動更新檢測等高階功能;相容如Baidu、Google、Bing、Duckduckgo、Yandex、Sogou、Qwant、Ecosia、You、Startpage、Brave、Yahoo、Yep、Swisscows、searXNG等多個搜尋引擎。
  14. // @description:ru “Элегантный помощник поисковых систем” обеспечивает удобное переключение между поисковыми системами, поддерживает настройку, выделение ключевых слов и продвинутые функции. совместим с Baidu, Google, Bing, Duckduckgo, Yandex, Sogou, Qwant, Ecosia, You, Startpage, Brave, Yahoo, Yep, Swisscows, searXNG и другими поисковыми системами.
  15. // @description:ja 「優雅な検索エンジン助手」は、検索エンジン間の切り替えを容易にし、カスタムエンジン、キーワードハイライト、リダイレクト削除、広告ブロック、キーワードフィルタリング、自動更新をサポートし、Baidu、Google、Bing、Duckduckgo、Yandex、Sogou、Qwant、Ecosia、You、Startpage、Brave、Yahoo、Yep、Swisscows、searXNGなどと互換性があります。
  16. // @icon data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAACXBIWXMAAAsTAAALEwEAmpwYAAAFC0lEQVR4nO2WbUxTVxjHj8IMWZbt05Yt28y2D3yQRN0++MVsmXFbNjBixbFpkSGvXUt5GRpkgOCgIsgqOANUQCXYOQUKCMqrtDAmiorSwioIytsoIL3ce1olQ+W/3KsFlYov8yUmPsn/w725J//fec7zPPcQ8jJexoscABwsFosLpfRTq9W6CIDTMzFmWfYjSmkux3EWSilsYll2YnBwsNxsNi99auaUUn+O48ZZlkODrgW7lAVIjM9DWuohHD3yF8xmBhzHTXZ2du4B4PhEzVmWDeZ32nq+AxvESfDekIbwHbUIV51F+E4dAuTZEK2IQU3VKSEjBoNBQwiZ80TMx8bGPuY4buLsGSPc3WIQvKcVYVrMUPChAXh4JKC0uEGAKCsri/pfxgCcKKULKKXVfHo9RfGQ5Brtmk9BFJux0jUGl7r7MTAwMLR48eI3H9nYarW+c7vQrtqKTFOgxXrZ3lnNbfJNqEJq8kFhnVKplD+q+SKO40x8ofHn+dvOQuxIUsPPJwUbdttP/b2Sakbh6ZEgAJSUlPxOCJn7UOYMw7xBKb1sMo1AFrgTP/imI0ypw0+7GhG4+Q/Ij12dMgmpnoC02Axp0RUEl1sQVjc5DVE3iS8/3ygA9PT09HV3dwdbLJa3HghAKY3lF23eqIJ/bKn9HdZNIuhAH2S5fyNNewWqE2OIK+6Fb1Yb5Eett+BqJvDVsk3o7zdhdNRsmxPXurq6tswKwLKs0aC/iFWiBITV3bQLEJB3CcmVJuhHgA5mWkc7JhCkaoO8YhySQyYsWxqG1e5xcP0iEnJJOppPtgkger1+/wxjAPMopdH8ECk6rIXXpsP2K7zcgo3qi2g3321uU2HbOPxyO4VvQ6v/vZ2xm5Bnt0K0Mg5VFSeFQaVWq/3vNH+FUlrJ07WcNWJLVA7WRtgHCFL3ocAwbtec1wUzIM1pR2jtjRlrZQVDcHeNBl9fRqPRQAh5zXbuUbz5vpxyrFn9C8JTqhB8eNAugP++LtRcun5fAF7RBZeFY7C33jtcLbQzy7I35s+f/4kAwLfcuZYLELlvhbzi2qztFXigD0Xts2SAAWR8Bmqu213vta0e6cpCoRbEYvFavuff5h/2ZpfDO77igf0tO8Ih8mA3jKP2AUrPU/jsbkXocfsF/H1sJbIyjwgAy5cv/46f8R/wD9lZ5VgXV/1QQyZgfzeUx0fQdg9E7fkxRCY2Iij1DPyyO2bUQejxSazw2I7Tze0YGhoyOzo6fiZcKhiGYfifjJu7YrpyZ1PdTQTm9yBkvxGZjQz2NVMoyv6BX3oLQuL/RFiMDpLkU/DbY5w+irpJeEaWQiLPEnZfWVlZSghxFmqgv78/lX+5XVkC11VJ8EpqgM+ucw+Ut7IZXtsaIFbo4JVyAusSdfCM0EC2ueYWRMpprE9pgjhRCzfPX+ErycDw8ChMJtOos7OzFyFknq0NnXp7e/U8RK1Oj58TixAQkvNYEvumw+2bGIREVQsQPpIcfLtGgYrac3z/86lnRCJROCHkvbsGUX5+/utNTU0FDMOM33nNehztTiuEx8otiIg+BtmPGVBszRPe19fXV7u4uHgTQt6/3ySes2TJkgURERGBCoUi5nGk1+ubeDNVRilErtEI9EmZuhc4ODh8PZX2pxVardbJYDAcuzMjw8PDY1KpNJYQ8i55RjE3MzPTR6PRqFUqVebChQv5tH9InkPMIYS8+jyMyQsT/wHRI0Gp4kJwPQAAAABJRU5ErkJggg==
  17. // @namespace https://github.com/F9y4ng/GreasyFork-Scripts/
  18. // @homepage https://f9y4ng.github.io/GreasyFork-Scripts/
  19. // @homepageURL https://f9y4ng.github.io/GreasyFork-Scripts/
  20. // @supportURL https://github.com/F9y4ng/GreasyFork-Scripts/issues
  21. // @match *://www.baidu.com/*
  22. // @match *://ipv6.baidu.com/*
  23. // @match *://image.baidu.com/search*
  24. // @match *://kaifa.baidu.com/searchPage*
  25. // @match *://*.bing.com/*search*
  26. // @match *://duckduckgo.com/*
  27. // @match *://*.sogou.com/*
  28. // @match *://www.qwant.com/?*
  29. // @match *://www.so.com/s*
  30. // @match *://image.so.com/*
  31. // @match *://so.toutiao.com/search*
  32. // @match *://yandex.com/*search*
  33. // @match *://yandex.ru/*search*
  34. // @match *://yandex.eu/*search*
  35. // @match *://www.ecosia.org/*
  36. // @match *://*.search.yahoo.com/search*
  37. // @match *://*.images.search.yahoo.com/search*
  38. // @match *://you.com/*
  39. // @match *://www.startpage.com/*
  40. // @match *://search.brave.com/*
  41. // @match *://yep.com/*
  42. // @match *://swisscows.com/*
  43. // @match *://search.inetol.net/search*
  44. // @match *://*.google.com/search*
  45. // @match *://*.google.ad/search*
  46. // @match *://*.google.ae/search*
  47. // @match *://*.google.com.af/search*
  48. // @match *://*.google.com.ag/search*
  49. // @match *://*.google.com.ai/search*
  50. // @match *://*.google.al/search*
  51. // @match *://*.google.am/search*
  52. // @match *://*.google.co.ao/search*
  53. // @match *://*.google.com.ar/search*
  54. // @match *://*.google.as/search*
  55. // @match *://*.google.at/search*
  56. // @match *://*.google.com.au/search*
  57. // @match *://*.google.az/search*
  58. // @match *://*.google.ba/search*
  59. // @match *://*.google.com.bd/search*
  60. // @match *://*.google.be/search*
  61. // @match *://*.google.bf/search*
  62. // @match *://*.google.bg/search*
  63. // @match *://*.google.com.bh/search*
  64. // @match *://*.google.bi/search*
  65. // @match *://*.google.bj/search*
  66. // @match *://*.google.com.bn/search*
  67. // @match *://*.google.com.bo/search*
  68. // @match *://*.google.com.br/search*
  69. // @match *://*.google.bs/search*
  70. // @match *://*.google.bt/search*
  71. // @match *://*.google.co.bw/search*
  72. // @match *://*.google.by/search*
  73. // @match *://*.google.com.bz/search*
  74. // @match *://*.google.ca/search*
  75. // @match *://*.google.cd/search*
  76. // @match *://*.google.cf/search*
  77. // @match *://*.google.cg/search*
  78. // @match *://*.google.ch/search*
  79. // @match *://*.google.ci/search*
  80. // @match *://*.google.co.ck/search*
  81. // @match *://*.google.cl/search*
  82. // @match *://*.google.cm/search*
  83. // @match *://*.google.cn/search*
  84. // @match *://*.google.com.co/search*
  85. // @match *://*.google.co.cr/search*
  86. // @match *://*.google.com.cu/search*
  87. // @match *://*.google.cv/search*
  88. // @match *://*.google.com.cy/search*
  89. // @match *://*.google.cz/search*
  90. // @match *://*.google.de/search*
  91. // @match *://*.google.dj/search*
  92. // @match *://*.google.dk/search*
  93. // @match *://*.google.dm/search*
  94. // @match *://*.google.com.do/search*
  95. // @match *://*.google.dz/search*
  96. // @match *://*.google.com.ec/search*
  97. // @match *://*.google.ee/search*
  98. // @match *://*.google.com.eg/search*
  99. // @match *://*.google.es/search*
  100. // @match *://*.google.com.et/search*
  101. // @match *://*.google.fi/search*
  102. // @match *://*.google.com.fj/search*
  103. // @match *://*.google.fm/search*
  104. // @match *://*.google.fr/search*
  105. // @match *://*.google.ga/search*
  106. // @match *://*.google.ge/search*
  107. // @match *://*.google.gg/search*
  108. // @match *://*.google.com.gh/search*
  109. // @match *://*.google.com.gi/search*
  110. // @match *://*.google.gl/search*
  111. // @match *://*.google.gm/search*
  112. // @match *://*.google.gr/search*
  113. // @match *://*.google.com.gt/search*
  114. // @match *://*.google.gy/search*
  115. // @match *://*.google.hk/search*
  116. // @match *://*.google.com.hk/search*
  117. // @match *://*.google.hn/search*
  118. // @match *://*.google.hr/search*
  119. // @match *://*.google.ht/search*
  120. // @match *://*.google.hu/search*
  121. // @match *://*.google.co.id/search*
  122. // @match *://*.google.ie/search*
  123. // @match *://*.google.co.il/search*
  124. // @match *://*.google.im/search*
  125. // @match *://*.google.co.in/search*
  126. // @match *://*.google.iq/search*
  127. // @match *://*.google.is/search*
  128. // @match *://*.google.it/search*
  129. // @match *://*.google.je/search*
  130. // @match *://*.google.com.jm/search*
  131. // @match *://*.google.jo/search*
  132. // @match *://*.google.jp/search*
  133. // @match *://*.google.co.jp/search*
  134. // @match *://*.google.co.ke/search*
  135. // @match *://*.google.com.kh/search*
  136. // @match *://*.google.ki/search*
  137. // @match *://*.google.kg/search*
  138. // @match *://*.google.co.kr/search*
  139. // @match *://*.google.com.kw/search*
  140. // @match *://*.google.kz/search*
  141. // @match *://*.google.la/search*
  142. // @match *://*.google.com.lb/search*
  143. // @match *://*.google.li/search*
  144. // @match *://*.google.lk/search*
  145. // @match *://*.google.co.ls/search*
  146. // @match *://*.google.lt/search*
  147. // @match *://*.google.lu/search*
  148. // @match *://*.google.lv/search*
  149. // @match *://*.google.com.ly/search*
  150. // @match *://*.google.co.ma/search*
  151. // @match *://*.google.md/search*
  152. // @match *://*.google.me/search*
  153. // @match *://*.google.mg/search*
  154. // @match *://*.google.mk/search*
  155. // @match *://*.google.ml/search*
  156. // @match *://*.google.com.mm/search*
  157. // @match *://*.google.mn/search*
  158. // @match *://*.google.ms/search*
  159. // @match *://*.google.com.mt/search*
  160. // @match *://*.google.mu/search*
  161. // @match *://*.google.mv/search*
  162. // @match *://*.google.mw/search*
  163. // @match *://*.google.com.mx/search*
  164. // @match *://*.google.com.my/search*
  165. // @match *://*.google.co.mz/search*
  166. // @match *://*.google.com.na/search*
  167. // @match *://*.google.com.ng/search*
  168. // @match *://*.google.com.ni/search*
  169. // @match *://*.google.ne/search*
  170. // @match *://*.google.nl/search*
  171. // @match *://*.google.no/search*
  172. // @match *://*.google.com.np/search*
  173. // @match *://*.google.nr/search*
  174. // @match *://*.google.nu/search*
  175. // @match *://*.google.co.nz/search*
  176. // @match *://*.google.com.om/search*
  177. // @match *://*.google.com.pa/search*
  178. // @match *://*.google.com.pe/search*
  179. // @match *://*.google.com.pg/search*
  180. // @match *://*.google.com.ph/search*
  181. // @match *://*.google.com.pk/search*
  182. // @match *://*.google.pl/search*
  183. // @match *://*.google.pn/search*
  184. // @match *://*.google.com.pr/search*
  185. // @match *://*.google.ps/search*
  186. // @match *://*.google.pt/search*
  187. // @match *://*.google.com.py/search*
  188. // @match *://*.google.com.qa/search*
  189. // @match *://*.google.ro/search*
  190. // @match *://*.google.ru/search*
  191. // @match *://*.google.rw/search*
  192. // @match *://*.google.com.sa/search*
  193. // @match *://*.google.com.sb/search*
  194. // @match *://*.google.sc/search*
  195. // @match *://*.google.se/search*
  196. // @match *://*.google.com.sg/search*
  197. // @match *://*.google.sh/search*
  198. // @match *://*.google.si/search*
  199. // @match *://*.google.sk/search*
  200. // @match *://*.google.com.sl/search*
  201. // @match *://*.google.sn/search*
  202. // @match *://*.google.so/search*
  203. // @match *://*.google.sm/search*
  204. // @match *://*.google.sr/search*
  205. // @match *://*.google.st/search*
  206. // @match *://*.google.com.sv/search*
  207. // @match *://*.google.td/search*
  208. // @match *://*.google.tg/search*
  209. // @match *://*.google.co.th/search*
  210. // @match *://*.google.com.tj/search*
  211. // @match *://*.google.tl/search*
  212. // @match *://*.google.tm/search*
  213. // @match *://*.google.tn/search*
  214. // @match *://*.google.to/search*
  215. // @match *://*.google.com.tr/search*
  216. // @match *://*.google.tt/search*
  217. // @match *://*.google.com.tw/search*
  218. // @match *://*.google.co.tz/search*
  219. // @match *://*.google.com.ua/search*
  220. // @match *://*.google.co.ug/search*
  221. // @match *://*.google.co.uk/search*
  222. // @match *://*.google.com.uy/search*
  223. // @match *://*.google.co.uz/search*
  224. // @match *://*.google.com.vc/search*
  225. // @match *://*.google.co.ve/search*
  226. // @match *://*.google.vg/search*
  227. // @match *://*.google.co.vi/search*
  228. // @match *://*.google.com.vn/search*
  229. // @match *://*.google.vu/search*
  230. // @match *://*.google.ws/search*
  231. // @match *://*.google.rs/search*
  232. // @match *://*.google.co.za/search*
  233. // @match *://*.google.co.zm/search*
  234. // @match *://*.google.co.zw/search*
  235. // @match *://*.google.cat/search*
  236. // @exclude *://www.google.com/sorry*
  237. // @exclude *://www.baidu.com/link*
  238. // @exclude *://www.sogou.com/link*
  239. // @exclude *://www.so.com/link*
  240. // @exclude *://so.toutiao.com/search/jump*
  241. // @connect baidu.com
  242. // @connect sogou.com
  243. // @connect so.com
  244. // @connect gf.qytechs.cn
  245. // @connect openuserjs.org
  246. // @connect githubusercontent.com
  247. // @connect favicon.yandex.net
  248. // @grant GM_getValue
  249. // @grant GM.getValue
  250. // @grant GM_setValue
  251. // @grant GM.setValue
  252. // @grant GM_listValues
  253. // @grant GM.listValues
  254. // @grant GM_deleteValue
  255. // @grant GM.deleteValue
  256. // @grant GM_openInTab
  257. // @grant GM.openInTab
  258. // @grant GM_addElement
  259. // @grant GM_registerMenuCommand
  260. // @grant GM.registerMenuCommand
  261. // @grant GM_xmlhttpRequest
  262. // @grant GM.xmlHttpRequest
  263. // @note {"CN":"修复 Baidu 搜索跳转按钮的加载异常。","EN":"Fixed Baidu Search Button Load Exception."}
  264. // @note {"CN":"修复关键词过滤功能在部分站点失效的问题。","EN":"Fixed keyword filter feature fails in some sites."}
  265. // @note {"CN":"优化 You.com 跳转按钮的加载逻辑。","EN":"Improved loading logic of You.com jump button."}
  266. // @note {"CN":"优化 TrustedTypes.createPolicy 的兼容性。","EN":"Optimized TrustedTypes.createPolicy compatibility."}
  267. // @note {"CN":"优化搜索结果广告拦截功能。","EN":"Optimized search results ad blocking features."}
  268. // @note {"CN":"更新 @namespace 源地址。","EN":"Updated @namespace source address."}
  269. // @note {"CN":"修正一些已知问题,优化代码,优化样式。","EN":"Fixed some known issues, optimized code & style."}
  270. // @compatible edge 兼容Tampermonkey, Violentmonkey
  271. // @compatible Chrome 兼容Tampermonkey, Violentmonkey
  272. // @compatible Firefox 兼容Greasemonkey, Tampermonkey, Violentmonkey
  273. // @compatible Opera 兼容Tampermonkey, Violentmonkey
  274. // @compatible Safari 兼容Tampermonkey, Userscripts
  275. // @license GPL-3.0-only
  276. // @create 2015-10-07
  277. // @copyright 2015-2025, F9y4ng
  278. // @run-at document-start
  279. // ==/UserScript==
  280.  
  281. /* jshint esversion: 11 */
  282.  
  283. void (function (ctx, sctx, SearchEngineAssistant, arrayProxy, customFns) {
  284. "use strict";
  285.  
  286. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  287. * CUSTOM SCRIPT DEBUGGING, DO NOT TURN ON FOR DAILY USE. *
  288. * SET TO "TRUE" FOR SCRIPT DEBUGGING, MAY CAUSE THE SCRIPT TO RUN SLOWLY. *
  289. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
  290.  
  291. const IS_OPEN_DEBUG = false;
  292.  
  293. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  294. * LICENSE FOR OPEN SOURCE USE: `GPLv3 ONLY`. *
  295. * THE CODE IS COMPLETELY OPEN AND FREE, AND DOES NOT ACCEPT UNAUTHORIZED *
  296. * DISTRIBUTION AS THIRD-PARTY STANDALONE SCRIPTS. IN CASE OF ERRORS, USAGE *
  297. * PROBLEMS OR NEW FEATURES, PLEASE FEEDBACK IN GITHUB ISSUES, THANK YOU! *
  298. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
  299.  
  300. const wrappedFrom = ctx.wrappedJSObject ? Array.from : sctx.Array.from;
  301. const toolkit = {
  302. debugging: IS_OPEN_DEBUG,
  303. info: GM?.info ?? GM_info,
  304. atob: sctx.atob.bind(sctx),
  305. btoa: sctx.btoa.bind(sctx),
  306. alert: ctx.alert.bind(ctx),
  307. prompt: ctx.prompt.bind(ctx),
  308. confirm: ctx.confirm.bind(ctx),
  309. console: sctx.Object.assign({}, ctx.console),
  310. orginalFns: { oS: sctx.Object.prototype.toString, hP: sctx.Object.prototype.hasOwnProperty, aF: (...args) => sctx.Object.setPrototypeOf(wrappedFrom(...args), arrayProxy) },
  311. };
  312. ["pushState", "replaceState"].forEach(m => void (ctx.history[m] = customFns.eH(m)));
  313. SearchEngineAssistant(ctx, sctx, toolkit, { ...toolkit.orginalFns, ...customFns });
  314. })(
  315. typeof window !== "undefined" ? window : this ?? globalThis,
  316. ((originalWindow, iframe) => {
  317. if (typeof GM_addElement === "undefined") return originalWindow;
  318. try {
  319. const { contentWindow } = (iframe = GM_addElement("iframe", { id: "𝚜𝚊𝚏e.w𝚒𝚗𝚍𝚘𝚠", style: "display:none" }));
  320. if (!originalWindow.wrappedJSObject) iframe.remove();
  321. return contentWindow;
  322. } catch (e) {
  323. return iframe?.remove(), originalWindow;
  324. }
  325. })(typeof window !== "undefined" ? window : this ?? globalThis, null),
  326. function (global, safeWindow, secureVars, customFuntions) {
  327. "use strict";
  328.  
  329. /* PERFECTLY COMPATIBLE FOR GREASEMONKEY, TAMPERMONKEY, VIOLENTMONKEY, USERSCRIPTS 2024-03-15 F9Y4NG */
  330.  
  331. const { atob, btoa, alert, prompt, confirm, console, debugging, info: GMinfo } = secureVars;
  332. const { aF: asArray, oS: getObjectType, hP: hasOwnProperty, lS: localStorages, oC: object } = customFuntions;
  333. const GMversion = GMinfo.version ?? GMinfo.scriptHandlerVersion ?? "unknown";
  334. const GMscriptHandler = GMinfo.scriptHandler;
  335. const GMsetValue = gmSelector("setValue");
  336. const GMgetValue = gmSelector("getValue");
  337. const GMdeleteValue = gmSelector("deleteValue");
  338. const GMlistValues = gmSelector("listValues");
  339. const GMopenInTab = gmSelector("openInTab");
  340. const GMregisterMenuCommand = gmSelector("registerMenuCommand");
  341. const GMxmlhttpRequest = gmSelector("xmlhttpRequest");
  342. const GMunsafeWindow = gmSelector("unsafeWindow");
  343. const GMcontentMode = gmSelector("contentMode");
  344.  
  345. /* INITIALIZE_DEBUG_FUNCTIONS */
  346.  
  347. const IS_CHN = checkLocalChineseLanguage();
  348. const IS_DEBUG = setDebuggerMode() || debugging;
  349. const DEBUG = IS_DEBUG ? __console.bind(console, "log") : () => {};
  350. const ERROR = IS_DEBUG ? __console.bind(console, "error") : () => {};
  351. const COUNT = IS_DEBUG ? __console.bind(console, "count") : () => {};
  352.  
  353. /* INITIALIZE_COMMON_CONSTANTS */
  354.  
  355. const { pT: CUR_PROTOCOL, hN: CUR_HOST_NAME, pN: CUR_PATH_NAME, iT: CUR_WINDOW_TOP } = getLocationInfo();
  356. const def = {
  357. count: { clickTimer: 0, duplicate: 0 },
  358. const: {
  359. raf: Symbol(`פֿ${generateRandomString(8, "hex")}`),
  360. caf: Symbol(`פֿ${generateRandomString(8, "hex")}`),
  361. loading: generateRandomString(6, "char"),
  362. cssAttrName: `gb-css-${generateRandomString(8, "hex")}`,
  363. rndButtonID: generateRandomString(12, "char"),
  364. rndclassName: `SC${generateRandomString(8, "number")}`,
  365. rndstyleName: `SS${generateRandomString(8, "number")}`,
  366. rndadvName: `SA${generateRandomString(8, "number")}`,
  367. leftButton: generateRandomString(6, "mix"),
  368. rightButton: generateRandomString(6, "mix"),
  369. scrollspan: generateRandomString(8, "char"),
  370. scrollspan2: generateRandomString(8, "char"),
  371. scrollbars: generateRandomString(8, "char"),
  372. scrollbars2: generateRandomString(8, "char"),
  373. searchbox: generateRandomString(7, "mix"),
  374. },
  375. var: {
  376. disappear: ${generateRandomString(10, "date")}ͼ`,
  377. translucent: ${generateRandomString(10, "date")}ͽ`,
  378. curVersion: getMetaValue("version") ?? GMinfo.script.version ?? "2025.04.05.0",
  379. scriptName: getMetaValue(`name:${getLocalLanguages()}`) ?? decrypt("U2VhcmNoJTIwRW5naW5lJTIwQXNzaXN0YW50"),
  380. },
  381. url: {
  382. yandexIcon: decrypt("aHR0cHMlM0ElMkYlMkZmYXZpY29uLnlhbmRleC5uZXQlMkZmYXZpY29uJTJGdjI="),
  383. backupIcon: decrypt("aHR0cHMlM0ElMkYlMkZzMjEuYXgxeC5jb20lMkYyMDI0JTJGMDYlMkYzMCUyRnBrY1VWbWoucG5n"),
  384. feedback: getMetaValue("supportURL") ?? GMinfo.script.supportURL ?? decrypt("aHR0cHMlM0ElMkYlMkZnaXRodWIuY29tJTJGRjl5NG5nJTJGR3JlYXN5Rm9yay1TY3JpcHRzJTJGaXNzdWVz"),
  385. homepage: getMetaValue("homepageURL") ?? GMinfo.script.homepage ?? decrypt("aHR0cHMlM0ElMkYlMkZmOXk0bmcuZ2l0aHViLmlvJTJGR3JlYXN5Rm9yay1TY3JpcHRzJTJG"),
  386. },
  387. notice: {
  388. rName: generateRandomString(8, "char"),
  389. random: generateRandomString(5, "char"),
  390. noticeX: generateRandomString(7, "char"),
  391. appear: generateRandomString(6, "char"),
  392. gberror: generateRandomString(6, "mix"),
  393. linkerror: generateRandomString(7, "mix"),
  394. item: generateRandomString(6, "mix"),
  395. close: generateRandomString(6, "mix"),
  396. center: generateRandomString(6, "mix"),
  397. success: generateRandomString(7, "char"),
  398. warning: generateRandomString(7, "char"),
  399. info: generateRandomString(7, "char"),
  400. error: generateRandomString(7, "char"),
  401. checkbox: generateRandomString(6, "char"),
  402. configuration: generateRandomString(7, "char"),
  403. animated: generateRandomString(7, "char"),
  404. stopUpdate: generateRandomString(6, "mix"),
  405. searchButton: generateRandomString(6, "mix"),
  406. favicon: generateRandomString(6, "mix"),
  407. favicons: generateRandomString(6, "mix"),
  408. searchList: generateRandomString(7, "mix"),
  409. fieldset: generateRandomString(6, "char"),
  410. legend: generateRandomString(6, "char"),
  411. settingList: generateRandomString(7, "mix"),
  412. readonly: generateRandomString(8, "mix"),
  413. hk: generateRandomString(5, "mix"),
  414. gj: generateRandomString(5, "mix"),
  415. lw: generateRandomString(5, "mix"),
  416. kh: generateRandomString(5, "mix"),
  417. ar: generateRandomString(5, "mix"),
  418. aa: generateRandomString(5, "mix"),
  419. au: generateRandomString(5, "mix"),
  420. grid: generateRandomString(7, "char"),
  421. card: generateRandomString(7, "char"),
  422. },
  423. };
  424.  
  425. if (checkRedundantScript(GMunsafeWindow)) return;
  426.  
  427. /* INITIALIZE_SETTIMEOUT_AND_SETINTERVAL_FUNCTION_CLASSES */
  428.  
  429. class RAF {
  430. constructor(context) {
  431. if (RAF.instance) return RAF.instance;
  432. safeWindow.Object.assign(this, { context, timerMap: { timeout: {}, interval: {} } });
  433. this._registerAnimationFrame(context);
  434. ["setTimeout", "setInterval", "clearTimeout", "clearInterval"].forEach(method => (this[method] = this[method].bind(this)));
  435. RAF.instance = this;
  436. }
  437. _registerAnimationFrame(scope) {
  438. const vendor = asArray(["ms", "moz", "webkit", "o"]).Find(vendor => scope[`${vendor}RequestAnimationFrame`]);
  439. const raf = scope.requestAnimationFrame ?? scope[`${vendor}RequestAnimationFrame`];
  440. const caf = scope.cancelAnimationFrame ?? (scope[`${vendor}CancelAnimationFrame`] || scope[`${vendor}CancelRequestAnimationFrame`]);
  441. safeWindow.Object.assign(scope, { [def.const.raf]: raf, [def.const.caf]: caf });
  442. }
  443. _ticking(fn, type, interval, ...args) {
  444. let lastTime = performance.now();
  445. const timerSymbol = Symbol(type);
  446. const step = () => {
  447. const currentTime = performance.now();
  448. this._setTimerMap(timerSymbol, type, step);
  449. if (currentTime - lastTime < (Number(interval) || 0)) return;
  450. if (typeof fn === "function") fn(...args);
  451. if (type === "interval") lastTime = currentTime;
  452. else this.clearTimeout(timerSymbol);
  453. };
  454. this._setTimerMap(timerSymbol, type, step);
  455. return timerSymbol;
  456. }
  457. _setTimerMap(timerSymbol, type, step) {
  458. this.timerMap[type][timerSymbol] = this.context[def.const.raf](step);
  459. }
  460. _clearTimerMap(timer, type) {
  461. this.context[def.const.caf](this.timerMap[type][timer]);
  462. delete this.timerMap[type][timer];
  463. }
  464. setTimeout(fn, interval, ...args) {
  465. return this._ticking(fn, "timeout", interval, ...args);
  466. }
  467. clearTimeout(timer) {
  468. this._clearTimerMap(timer, "timeout");
  469. }
  470. setInterval(fn, interval, ...args) {
  471. return this._ticking(fn, "interval", interval, ...args);
  472. }
  473. clearInterval(timer) {
  474. this._clearTimerMap(timer, "interval");
  475. }
  476. }
  477.  
  478. const raf = new RAF(global);
  479.  
  480. /* GLOBAL_GENERAL_FUNCTIONS */
  481.  
  482. function gmSelector(rec) {
  483. const gmFunctions = {
  484. setValue: typeof GM_setValue !== "undefined" ? GM_setValue : GM?.setValue ?? localStorages?.setItem.bind(localStorages),
  485. getValue: typeof GM_getValue !== "undefined" ? GM_getValue : GM?.getValue ?? localStorages?.getItem.bind(localStorages),
  486. deleteValue: typeof GM_deleteValue !== "undefined" ? GM_deleteValue : GM?.deleteValue ?? localStorages?.removeItem.bind(localStorages),
  487. listValues: typeof GM_listValues !== "undefined" ? GM_listValues : GM?.listValues ?? (() => []),
  488. openInTab: typeof GM_openInTab !== "undefined" ? GM_openInTab : GM?.openInTab ?? open.bind(global),
  489. registerMenuCommand: typeof GM_registerMenuCommand !== "undefined" ? GM_registerMenuCommand : GM?.registerMenuCommand,
  490. xmlhttpRequest: typeof GM_xmlhttpRequest !== "undefined" ? GM_xmlhttpRequest : GM?.xmlHttpRequest,
  491. unsafeWindow: typeof unsafeWindow !== "undefined" ? unsafeWindow : global,
  492. contentMode: GMinfo.injectInto === "content" || GMinfo.script["inject-into"] === "content" || ["dom", "js"].includes(GMinfo.sandboxMode),
  493. };
  494. return gmFunctions[rec] ?? __console("warn", `Grant 'GM.${rec}' is not available.`) ?? (() => {});
  495. }
  496.  
  497. function __console(action, message, ...args) {
  498. const consoleMethods = {
  499. log: ["log", "%c\ud83d\udd33 %c", "display:inline-block", "font-family:ui-monospace,monospace"],
  500. error: ["error", "%c\ud83d\udea9 ", "display:inline-block;font-family:ui-monospace,monospace"],
  501. warn: ["warn", "%c\ud83d\udea9 ", "display:inline-block;font-family:ui-monospace,monospace"],
  502. count: ["count", "\ud83d\udd33 "],
  503. };
  504. const [_, msg, consoleMethod] = [this ?? console, message ?? "", consoleMethods[action]];
  505. if (!consoleMethod) return _.log(msg, ...args);
  506. const [method, prefix, ...surfix] = consoleMethod;
  507. return _[method](prefix + msg, ...surfix, ...args);
  508. }
  509.  
  510. function checkLocalChineseLanguage() {
  511. const lang = navigator.language || Intl.DateTimeFormat().resolvedOptions().locale || "en-US";
  512. return lang.startsWith("zh");
  513. }
  514.  
  515. function qS(expr, target = document) {
  516. try {
  517. if (/^#[\w:.-]+$/.test(expr)) return target.getElementById(expr.slice(1));
  518. return target.querySelector(expr);
  519. } catch (e) {
  520. return null;
  521. }
  522. }
  523.  
  524. function qA(expr, target = document) {
  525. try {
  526. return asArray(target.querySelectorAll(expr));
  527. } catch (e) {
  528. return asArray([]);
  529. }
  530. }
  531.  
  532. function toString(value) {
  533. if (typeof value === "symbol") return value.description;
  534. return String(value);
  535. }
  536.  
  537. function cE(nodeName, attributes) {
  538. const el = document.createElement(nodeName);
  539. if (getObjectType.call(attributes) !== "[object Object]") return el;
  540. for (const [key, value] of Object.entries(attributes)) {
  541. if (key === "class") Array.isArray(value) ? el.classList.add(...value) : el.classList.add(value);
  542. else if (["innerHTML", "textContent"].includes(key)) el[key] = value;
  543. else el.setAttribute(key, value);
  544. }
  545. return el;
  546. }
  547.  
  548. function random({ range, count = 1, type = "round" }) {
  549. const typedArray = global.crypto.getRandomValues(new Uint32Array(count));
  550. return count === 1 ? Math[type]((typedArray[0] / 0xffffffff) * range) : typedArray.map(a => Math[type]((a / 0xffffffff) * range));
  551. }
  552.  
  553. function gCS(node, opt = null) {
  554. if (node?.nodeType !== Node.ELEMENT_NODE) return new Proxy(object(), { get: () => NaN });
  555. return global.getComputedStyle(node, opt);
  556. }
  557.  
  558. function capitalize(string) {
  559. string = String(string ?? "").toLowerCase();
  560. return string.replace(/\b[a-z]|\s[a-z]/g, str => str.toUpperCase());
  561. }
  562.  
  563. function encrypt(string, encode = true) {
  564. if (typeof string !== "string") string = toString(string);
  565. try {
  566. const req = encode ? encodeURIComponent(string) : string;
  567. return btoa(req);
  568. } catch (e) {
  569. return "";
  570. }
  571. }
  572.  
  573. function decrypt(string, decode = true) {
  574. if (typeof string !== "string") return "";
  575. try {
  576. const rst = atob(string.replace(/[^A-Za-z0-9+/=]/g, ""));
  577. return decode ? decodeURIComponent(rst) : rst;
  578. } catch (e) {
  579. return "";
  580. }
  581. }
  582.  
  583. function generateRandomString(length, type) {
  584. if (type === "date") return new Date().setHours(20, 30, 40, 50).toString(16);
  585. const charset = {
  586. mix: "w5imkK𝚌ofUeH𝚎tsEcSnJua𝚖hjpV𝚝zgIL8vZlNd𝚡C𝚊324𝚞qMWbr𝚣Y1X0𝚜9OPRA76QTFGy𝚘DBx",
  587. char: "Uo𝚜ALDMRplYc𝚖fsCarEu𝚘ITZyqxwzh𝚊F𝚞iVBNO𝚣eKtJjnQWSH𝚡m𝚎PXGgb𝚌dv𝚝k",
  588. hex: "fc8d6b1e7a9b2a5ec4f0d3",
  589. number: "5039268147",
  590. };
  591. const generator = (v, i) => (type === "mix" && i === 0 ? [...charset.char][random({ range: 62 })] : [...charset[type]][v]);
  592. return asArray(random({ range: [...charset[type]].length, count: length, type: "floor" }), generator).join("");
  593. }
  594.  
  595. function reload() {
  596. return sleep(5e2, { useCachedSetTimeout: true }).then(() => global.location.reload(true));
  597. }
  598.  
  599. function escapeHTML(string) {
  600. if (typeof string !== "string") return "";
  601. const element = cE("gb-escape-html", { textContent: string });
  602. return element.innerHTML;
  603. }
  604.  
  605. function createTrustedTypePolicy() {
  606. const policyOptions = { createHTML: s => s, createScript: s => s, createScriptURL: u => u };
  607. if (!global.trustedTypes?.createPolicy) return policyOptions;
  608. const originalCreatePolicy = global.trustedTypes.createPolicy.bind(global.trustedTypes);
  609. const whitelist = [{ host: "bing.com", policy: "rwflyoutDefault" }];
  610. const policyName = global.trustedTypes.defaultPolicy?.name ?? asArray(whitelist).Find(entry => location.hostname.endsWith(entry.host))?.policy ?? "default";
  611. const defaultPolicy = global.trustedTypes.defaultPolicy ?? originalCreatePolicy(policyName, policyOptions);
  612. global.trustedTypes.createPolicy = (name, options) => (name === policyName ? defaultPolicy : originalCreatePolicy(name, options));
  613. return defaultPolicy;
  614. }
  615.  
  616. function checkRedundantScript(global) {
  617. const redundancyWarning = () => {
  618. const redundanceText = `\ud83d\udea9 [Redundant Scripts]:\r\nFound redundant-installed scripts: ${def.var.scriptName}. please reload to troubleshoot the issue.`;
  619. const troubleshoot = `\ufff8\ud83d\uded1 ${IS_CHN ? "发现冗余安装的脚本,点击排查!" : "Troubleshoot Redundant"}`;
  620. return CUR_WINDOW_TOP && GMregisterMenuCommand(troubleshoot, () => void GMopenInTab(`${def.url.feedback}/117`, false)) && __console("error", redundanceText), true;
  621. };
  622. if (global["gb-init-once"] === true) return redundancyWarning();
  623. if (GMcontentMode && document.documentElement?.hasAttribute("gb-init-once")) return redundancyWarning();
  624. (global["gb-init-once"] = true) && safeWindow.Object.freeze(def.const) && document.documentElement?.setAttribute("gb-init-once", "");
  625. }
  626.  
  627. async function getNavigatorInfo() {
  628. const creditEngine = getRealBrowserEngine(global);
  629. const userAgentData = await getUserAgentDataFromExtension(`${GMscriptHandler} ${GMversion}`);
  630. return userAgentData ? getGlobalInfoFromUAD(userAgentData) : getGlobalInfoFromUA(navigator.userAgent);
  631.  
  632. function getGlobalInfoFromUAD(uad) {
  633. const platform = getFullPlatformName(uad.platform);
  634. const mapBrandPath = ({ brand: b, version: v }) => `${/Not[^a-z]*A[^a-z]*Brand/i.test(b) ? 9 : /^Chrom(?:e|ium)|Firefox|Safari$/i.test(b) ? 5 : 1}${b}\r${v}`;
  635. const [brand, brandVersion] = uad.brands?.map(mapBrandPath).sort()[0]?.slice(1).split("\r") ?? [];
  636. const engineMap = { Chrome: "Blink", Chromium: "Blink", Firefox: "Gecko", Safari: "WebKit" };
  637. const mapEnginePath = ({ brand, version }) => /^(Chrom(?:e|ium)|Firefox|Safari)$/i.test(brand) && `${brand}\r${version}`;
  638. const [engine, engineVersion] = uad.brands?.map(mapEnginePath).filter(Boolean)[0]?.split("\r") ?? [brand, brandVersion];
  639. const engineInfo = { engine: engineMap[capitalize(engine)] ?? getEngineFromUA(navigator.userAgent), engineVersion: parseFloat(engineVersion) || 99, creditEngine };
  640. const browserInfo = { brand: (brand?.split(/\s/) ?? []).slice(-1)[0] ?? "Unknown", brandVersion: formatVersion(brandVersion), platform };
  641. return { ...engineInfo, ...browserInfo, source: uad.source ?? "uad", voucher: uad.voucher ?? null };
  642. }
  643.  
  644. function getGlobalInfoFromUA(ua) {
  645. const checkString = (str, exp = "") => new RegExp(str, exp).test(ua);
  646. const getVersion = (str, offset) => checkString(str) && ua.slice(ua.indexOf(str) + offset).match(/\d+(\.\d+)*/)?.[0];
  647. const { brand, brandVersion, engine, engineVersion } = getBrowserInfoFromUA(ua, checkString, getVersion);
  648. const platform = getOSInfoFromUA(checkString);
  649. return { engine, engineVersion, creditEngine, brand, brandVersion, platform, source: "ua", voucher: null };
  650. }
  651.  
  652. async function getUserAgentDataFromExtension(voucher) {
  653. const getVMUserAgentData = ({ browserName, browserVersion, os, arch }) => {
  654. const [architecture, bitness] = arch?.split("-") ?? [];
  655. let brands = [{ brand: capitalize(browserName), version: browserVersion }];
  656. if (parseFloat(browserVersion) < 78.0 && GMinfo.userAgent) {
  657. const [, brand, version] = GMinfo.userAgent.match(/\s(Chrom(?:e|ium)|Firefox)\/(\d+[.0-9]*)/i) ?? [];
  658. if (brand) brands = [{ brand: capitalize(brand), version }, ...brands];
  659. }
  660. return { bitness, architecture, brands, platform: capitalize(os), source: "ext", voucher };
  661. };
  662. if (voucher.startsWith("Violentmonkey") && GMinfo.platform) return getVMUserAgentData(GMinfo.platform);
  663. const getTMUserAgentData = uad => {
  664. if (creditEngine === "Gecko" && parseFloat(uad.brands[0].version) < 78.0) {
  665. const [, brand, version] = navigator.userAgent.match(/\s(Firefox)\/(\d+[.0-9]*)/i) ?? [];
  666. if (brand) return { ...uad, brands: [{ brand: capitalize(brand), version }, ...uad.brands], source: "ua" };
  667. }
  668. return { ...uad, source: "ext", voucher };
  669. };
  670. if (voucher.startsWith("Tampermonkey") && GMinfo.userAgentData) return getTMUserAgentData(GMinfo.userAgentData);
  671. const getUADHighEntropyValues = async uad =>
  672. await uad.getHighEntropyValues(["bitness", "architecture", "fullVersionList"]).then(rst => {
  673. rst.brands = rst.fullVersionList;
  674. delete rst.fullVersionList;
  675. return rst;
  676. });
  677. if (navigator.userAgentData?.brands?.[0]) return await getUADHighEntropyValues(navigator.userAgentData);
  678. return null;
  679. }
  680.  
  681. function getBrowserInfoFromUA(ua, checkString, getVersion) {
  682. const engine = getEngineFromUA(ua);
  683. const brandMap = {
  684. OPR: { brand: "Opera", engine: "Blink", as: "Chrome" },
  685. YaBrowser: { brand: "Yandex", engine: "Blink", as: "Chrome" },
  686. Edg: { brand: "Edge", engine: "Blink", as: "Chrome" },
  687. Chromium: { brand: "Chromium", engine: "Blink" },
  688. Chrome: { brand: "Chrome", engine: "Blink" },
  689. LibreWolf: { brand: "LibreWolf", engine: "Gecko", as: "Firefox" },
  690. SeaMonkey: { brand: "SeaMonkey", engine: "Gecko", as: "Firefox" },
  691. PaleMoon: { brand: "PaleMoon", engine: "Gecko", as: "Firefox" },
  692. Waterfox: { brand: "Waterfox", engine: "Gecko", as: "Firefox" },
  693. Firefox: { brand: "Firefox", engine: "Gecko" },
  694. Konqueror: { brand: "Konqueror", engine: "webkit" },
  695. Kindle: { brand: "Kindle", engine: "WebKit", as: "Version" },
  696. Safari: { brand: "Safari", engine: "WebKit", as: "Version", verset: ["Version"] },
  697. Trident: { brand: "IE", engine: "Trident", verset: ["MSIE", "rv"] },
  698. Presto: { brand: "Opera", engine: "Presto" },
  699. };
  700. for (const [key, { brand, engine, verset, as }] of Object.entries(brandMap)) {
  701. if (!checkString(key)) continue;
  702. const versionKey = asArray(verset ?? []).Find(k => checkString(k)) || key;
  703. let brandVersion = getVersion(versionKey, versionKey.length + 1);
  704. if (!brandVersion) continue;
  705. const enVersionKey = as || key;
  706. const engineVersion = parseFloat(getVersion(enVersionKey, enVersionKey.length + 1) || 99);
  707. return { brand, brandVersion: formatVersion(brandVersion), engine, engineVersion };
  708. }
  709. const { b: brand, bv: brandVersion, ev: engineVersion } = getUnregisteredBrandAndVersionFromUA(ua);
  710. return { brand, brandVersion, engine, engineVersion };
  711. }
  712.  
  713. function formatVersion(version) {
  714. if (!version) return "0.0.0.0";
  715. const numbers = version.split(".").map(num => parseInt(num) || 0);
  716. while (numbers.length < 4) numbers.push(0);
  717. return numbers.join(".");
  718. }
  719.  
  720. function getFullPlatformName(platform) {
  721. if (!platform) return "Unknown";
  722. const os = capitalize(platform);
  723. return /^(Like Mac|Ios)$/.test(os) ? "iOS" : os === "Cros" ? "Chrome OS" : os.startsWith("Win") ? "Windows" : os.startsWith("Mac") ? "MacOS" : os === "X11" ? "Linux" : os;
  724. }
  725.  
  726. function getRealBrowserEngine(w) {
  727. return w.GestureEvent ? "WebKit" : w.scrollByLines || w.getDefaultComputedStyle ? "Gecko" : w.webkitRequestFileSystem || w.queryLocalFonts ? "Blink" : "Unknown";
  728. }
  729.  
  730. function getEngineFromUA(ua) {
  731. return /Gecko\/|Firefox\/|FxiOS/.test(ua) ? "Gecko" : /Chrom(?:e|ium)\/|CriOS/.test(ua) ? "Blink" : /AppleWebKit\/|Version\//.test(ua) ? "WebKit" : "Unknown";
  732. }
  733.  
  734. function getUnregisteredBrandAndVersionFromUA(ua) {
  735. const [nameOffset, verOffset] = [ua.lastIndexOf(" ") + 1, ua.lastIndexOf("/")];
  736. if (nameOffset === 0 || verOffset === -1 || verOffset < nameOffset) return { b: "Unknown", bv: "0.0.0.0", ev: 99 };
  737. const brand = ua.slice(nameOffset, verOffset).trim();
  738. const brandVersion = formatVersion(ua.slice(verOffset + 1).match(/\d*\.?\d+/)?.[0]);
  739. const engineVersion = parseFloat(ua.match(/(?:Chrom(?:e|ium)|Firefox|Version)\/(\d+[.0-9]*)/i)?.[1] || brandVersion || 99);
  740. const validVersion = (!/version|\/|\(|\)|;/i.test(brand) && brandVersion) || "0.0.0.0";
  741. return { b: brand, bv: validVersion, ev: engineVersion };
  742. }
  743.  
  744. function getOSInfoFromUA(checkString) {
  745. const platforms = ["like Mac", "Mac", "Android", "Debian", "Ubuntu", "Linux", "Win", "CrOS", "X11"];
  746. const platform = asArray(platforms).Find(p => checkString(p, "i")) || "Unknown";
  747. return getFullPlatformName(platform);
  748. }
  749. }
  750.  
  751. function getLocationInfo() {
  752. const { host: h, hostname: hN, pathname: pN, protocol: pT } = global.location;
  753. const iT = global.self === global.top;
  754. return { h, hN, pN, pT, iT };
  755. }
  756.  
  757. function getMetaValue(str) {
  758. const queryReg = new RegExp(`//\\s+@${str}\\s+(.+)`);
  759. const metaValue = (GMinfo.scriptMetaStr || GMinfo.scriptSource)?.match(queryReg);
  760. return metaValue?.[1];
  761. }
  762.  
  763. function getLocalLanguages(lang = navigator.language) {
  764. const languages = new Set(["zh-CN", "zh-TW", "en", "ja", "ko"]);
  765. return languages.has(lang) ? lang : lang.startsWith("zh") ? "zh-CN" : "en";
  766. }
  767.  
  768. function setDebuggerMode() {
  769. const key = decrypt("\u0052\u006a\u006c\u0035\u004e\u0047\u0035\u006e");
  770. const value = new URLSearchParams(global.location.search).get("whoami");
  771. return Object.is(key, value);
  772. }
  773.  
  774. function sleep(delay, { useCachedSetTimeout, instant } = {}) {
  775. const timeoutFunction = useCachedSetTimeout ? setTimeout : raf.setTimeout;
  776. const sleepPromise = new Promise(resolve => {
  777. timeoutFunction(resolve, delay);
  778. });
  779. const promiseFunction = value => sleepPromise.then(() => value);
  780. promiseFunction.then = sleepPromise.then.bind(sleepPromise);
  781. promiseFunction.catch = sleepPromise.catch.bind(sleepPromise);
  782. return instant ? sleepPromise : promiseFunction;
  783. }
  784.  
  785. function deBounce({ fn, timer, delay, immed = false, once = false } = {}) {
  786. if (typeof fn !== "function" || !timer) return () => {};
  787. return function (...args) {
  788. const [name, context] = [Symbol.for(toString(timer)), this];
  789. if (immed === true && typeof def.count[name] === "undefined") {
  790. fn.apply(context, args);
  791. if (once === true) return (def.count[name] = true);
  792. } else if (def.count[name]) {
  793. if (def.count[name] === true) return true;
  794. raf.clearTimeout(def.count[name]);
  795. }
  796. def.count[name] = raf.setTimeout(() => {
  797. fn.apply(context, args);
  798. if (once === true) return (def.count[name] = true);
  799. delete def.count[name];
  800. }, Number(delay) || 0);
  801. };
  802. }
  803.  
  804. function safeRemoveNode(expression, scope) {
  805. if (!expression) return false;
  806. const pendingNodes = Array.isArray(expression) ? expression : typeof expression === "string" ? qA(expression, scope) : expression?.nodeType ? [expression] : [];
  807. return pendingNodes.every(el => el.remove() || el.parentNode === null);
  808. }
  809.  
  810. void (async function (tTP) {
  811. const [CONFIGURE, VERSION, AUTOCHECK, RESULTFILTER, REMOTEICONS] = ["_configures_", "_version_", "_autoupdate_", "_resultFilter_", "_remoteicons_"];
  812. const { engine, creditEngine, brand, voucher } = await getNavigatorInfo();
  813. const [IS_REAL_BLINK, IS_REAL_GECKO, IS_REAL_WEBKIT] = ["Blink", "Gecko", "WebKit"].map(cE => cE === creditEngine);
  814. const IS_CHEAT_UA = voucher === null && (engine !== creditEngine || checkBlinkCheatingUA(navigator.userAgentData));
  815. const IS_GREASEMONKEY = ["Greasemonkey", "Userscripts"].includes(GMscriptHandler);
  816. const createNoticeHTML = html => `<div class="${def.notice.rName}"><dl>${html}</dl></div>`;
  817.  
  818. const cache = {
  819. value: (data, eT = 6048e5) => ({ data, expired: Date.now() + eT }),
  820. set: (key, ...options) => void GMsetValue(key, encrypt(JSON.stringify(cache.value(...options)))),
  821. get: async key => {
  822. try {
  823. const encryptedValue = await GMgetValue(key);
  824. if (!encryptedValue) return;
  825. const current = Date.now();
  826. const { data, expired } = JSON.parse(decrypt(encryptedValue));
  827. if (data && expired > current) return data;
  828. else cache.remove(key);
  829. } catch (e) {
  830. cache.remove(key);
  831. }
  832. },
  833. remove: key => GMdeleteValue(key),
  834. };
  835.  
  836. class NoticeX {
  837. constructor(options = {}) {
  838. const defaultOptions = {
  839. title: "",
  840. text: "",
  841. type: def.notice.success,
  842. position: "bottomRight",
  843. newestOnTop: false,
  844. timeout: 2e3,
  845. progressBar: true,
  846. closeWith: ["button"],
  847. animation: { open: `${def.notice.animated} ${def.notice.random}_fadeIn`, close: `${def.notice.animated} ${def.notice.random}_fadeOut` },
  848. width: 400,
  849. scroll: { maxHeight: 400, showOnHover: false },
  850. callbacks: { beforeShow: [], onShow: [], afterShow: [], beforeClose: [], onClose: [], afterClose: [], onClick: [], onHover: [] },
  851. };
  852. this.options = { ...defaultOptions, ...options };
  853. this._registerCallbacks();
  854. }
  855. static close(item) {
  856. if (!item) return true;
  857. item.classList.add(def.notice.animated, `${def.notice.random}_fadeOut`);
  858. const closetNode = item.closest(`.${def.notice.noticeX}`);
  859. const position = closetNode?.className.match(/\b(\w+-\w+)\b/)?.[1] || `${def.notice.noticeX}-topRight`;
  860. return sleep(3e2)
  861. .then(() => safeRemoveNode(item))
  862. .then(() => qA(`.${position} .${def.notice.item}`).length === 0 && safeRemoveNode(`.${position}`));
  863. }
  864. show() {
  865. this._createContainer();
  866. return this._appendNoticeX(this._createHeader(), this._createBody(), this._createProgressBar());
  867. }
  868. _createContainer() {
  869. const position = `${def.notice.noticeX}-${this.options.position}`;
  870. if (qS(`gb-notice.${position}`)) return;
  871. const container = cE("gb-notice", { class: [def.notice.noticeX, position, def.notice.appear] });
  872. document.documentElement?.appendChild(container);
  873. }
  874. _createHeader() {
  875. if (!this.options.title && !this.options.closeWith.includes("button")) return null;
  876. const header = cE("div", { class: `${def.notice.noticeX}-heading` });
  877. if (this.options.title) header.innerHTML += tTP.createHTML(`<span class="${def.notice.noticeX}-heading-title" title="${this.options.title}">${this.options.title}</span>`);
  878. if (this.options.closeWith.includes("button")) {
  879. const close = cE("div", { class: def.notice.close, innerHTML: tTP.createHTML("&times;") });
  880. header.appendChild(close);
  881. }
  882. return header;
  883. }
  884. _createBody() {
  885. const body = cE("div", { class: `${def.notice.noticeX}-body` });
  886. const content = cE("div", { class: `${def.notice.noticeX}-content`, innerHTML: tTP.createHTML(this.options.text) });
  887. body.appendChild(content);
  888. if (this.options.scroll?.maxHeight) {
  889. body.style.overflowY = "auto";
  890. body.style.maxHeight = `min(calc(92vh - 50px), ${this.options.scroll.maxHeight}px)`;
  891. if (this.options.scroll?.showOnHover) body.style.visibility = "hidden";
  892. }
  893. return body;
  894. }
  895. _createProgressBar() {
  896. const progressBar = cE("div", { class: `${def.notice.noticeX}-progressbar` });
  897. const bar = cE("div", { class: `${def.notice.noticeX}-bar` });
  898. progressBar.appendChild(bar);
  899. if (this.options.progressBar && typeof this.options.timeout === "number") {
  900. progressBar.style.animation = `${def.notice.noticeX}-progress ${this.options.timeout / 1e3}s linear forwards`;
  901. sleep(this.options.timeout, { useCachedSetTimeout: true }).then(() => {
  902. const item = progressBar.closest(`div.${def.notice.item}`);
  903. if (item) this._closeWithAnimation(item);
  904. });
  905. }
  906. return progressBar;
  907. }
  908. _appendNoticeX(header, body, progressBar) {
  909. const targetClass = `.${def.notice.noticeX}-${this.options.position}`;
  910. const noticeItem = cE("div", { class: [def.notice.item, this.options.type] });
  911. if (this.options.width && Number.isInteger(this.options.width)) noticeItem.style.width = `${this.options.width}px`;
  912. [header, body, progressBar].forEach(el => el && noticeItem.appendChild(el));
  913. if (["top", "bottom"].includes(this.options.position)) qS(targetClass).textContent = "";
  914. if (this.options?.animation?.open) noticeItem.className += ` ${this.options.animation.open}`;
  915. this._executeCallbacks("beforeShow");
  916. this._addListeners(noticeItem);
  917. const target = qS(targetClass);
  918. this._executeCallbacks("onShow");
  919. this.options.newestOnTop && target ? target.insertAdjacentElement("afterbegin", noticeItem) : target.appendChild(noticeItem);
  920. this._executeCallbacks("afterShow");
  921. return noticeItem;
  922. }
  923. _closeWithAnimation(item) {
  924. if (this.options.animation?.close) {
  925. item.className += ` ${this.options.animation.close}`;
  926. sleep(5e2).then(() => this._closeItem(item));
  927. } else this._closeItem(item);
  928. }
  929. _addListeners(item) {
  930. const closeBtn = qS(`.${def.notice.close}`, item);
  931. const handleClick = () => this._closeItem(item);
  932. if (this.options.closeWith.includes("button")) closeBtn?.addEventListener("click", handleClick);
  933. if (this.options.closeWith.includes("click")) {
  934. item.style.cursor = "pointer";
  935. item.addEventListener("click", e => {
  936. if (e.target.className === def.notice.close) return;
  937. this._executeCallbacks("onClick");
  938. handleClick();
  939. });
  940. } else item.addEventListener("click", e => e.target.className !== def.notice.close && this._executeCallbacks("onClick"));
  941. item.addEventListener("mouseover", () => this._executeCallbacks("onHover"));
  942. }
  943. _closeItem(item) {
  944. const closetNode = item.closest(`.${def.notice.noticeX}`);
  945. const position = closetNode?.className.match(/\b(\w+-\w+)\b/)?.[1] || `${def.notice.noticeX}-bottomRight`;
  946. this._executeCallbacks("beforeClose");
  947. sleep(3e2)
  948. .then(() => this._executeCallbacks("onClose"))
  949. .then(() => safeRemoveNode(item))
  950. .then(() => qA(`.${position} .${def.notice.item}`).length === 0 && safeRemoveNode(`.${position}`))
  951. .then(() => this._executeCallbacks("afterClose"));
  952. }
  953. _executeCallbacks(eventName) {
  954. this.options.callbacks[eventName]?.forEach(cb => cb?.call(this));
  955. }
  956. _registerCallbacks() {
  957. Object.keys(this.options.callbacks).forEach(eventName => {
  958. const cb = this.options.callbacks[eventName];
  959. if (typeof cb === "function") this._on(eventName, cb);
  960. });
  961. }
  962. _on(eventName, cb = () => {}) {
  963. if (typeof cb === "function" && this.options.callbacks[eventName]) this.options.callbacks[eventName].push(cb);
  964. return this;
  965. }
  966. }
  967.  
  968. function checkBlinkCheatingUA(uad) {
  969. if (!IS_REAL_BLINK) return false;
  970. return (global.isSecureContext && !uad) || (uad && toString(uad) !== "[object NavigatorUAData]");
  971. }
  972.  
  973. function insertAfter(newEl, target) {
  974. if (!newEl || !target) return;
  975. const parent = target.parentNode || document.head;
  976. parent.insertBefore(newEl, target.nextElementSibling);
  977. }
  978.  
  979. function addStyle({ target, styleId, styleContent, media, isOverwrite }) {
  980. if (!target || !styleId || !styleContent || !media) return;
  981. let existingStyles = qA(`#${styleId}`, target);
  982. if (isOverwrite) existingStyles.forEach(style => (style.dataset.frRemoved = true) && safeRemoveNode(style));
  983. else if (existingStyles.length > 0) return true;
  984. try {
  985. const styleElement = cE("style", { id: styleId, media, type: "text/css", textContent: styleContent ?? "", [def.const.cssAttrName]: isOverwrite ?? false });
  986. return target.appendChild(styleElement) && true;
  987. } catch (e) {
  988. ERROR("addStyle:", e.message);
  989. }
  990. }
  991.  
  992. function getUrlParam(parameter) {
  993. try {
  994. switch (getObjectType.call(parameter)) {
  995. case "[object Object]": {
  996. const { split, index } = parameter;
  997. const keyArray = global.location.pathname.split(split);
  998. return keyArray[index] ?? "";
  999. }
  1000. case "[object Array]":
  1001. for (const para of parameter) {
  1002. const value = getUrlParam(para);
  1003. if (value) return value;
  1004. }
  1005. return "";
  1006. case "[object Number]":
  1007. case "[object String]":
  1008. if (!parameter && parameter !== 0) return "";
  1009. return new URLSearchParams(global.location.search).get(parameter) ?? "";
  1010. case "[object Function]":
  1011. return parameter() ?? "";
  1012. default:
  1013. return "";
  1014. }
  1015. } catch (e) {
  1016. ERROR("getUrlParam:", e.message);
  1017. return "";
  1018. }
  1019. }
  1020.  
  1021. function versionCompare(current, compare) {
  1022. const [currentVersion, compareVersion] = [current.split(".").map(Number), compare.split(".").map(Number)];
  1023. if (compareVersion.length !== currentVersion.length) return true;
  1024. for (let i = 0; i < currentVersion.length; i++) if (compareVersion[i] !== currentVersion[i]) return compareVersion[i] > currentVersion[i];
  1025. return false;
  1026. }
  1027.  
  1028. function manageCookies() {
  1029. return {
  1030. getItem: sKey => decodeURIComponent(document.cookie.replace(new RegExp("(?:(?:^|.*;)\\s*" + sKey?.replace(/[-.+*]/g, "\\$&") + "\\s*\\=\\s*([^;]*).*$)|^.*$"), "$1")) || null,
  1031. setItem: function ({ sKey, sValue, sEnd, sPath, sDomain, sSameSite, sSecure }) {
  1032. if (!sKey || /^(?:expires|max-age|path|domain|samesite|secure)$/i.test(sKey)) return false;
  1033. [sDomain, sPath, sSameSite, sSecure] = [sDomain ? `;domain=${sDomain}` : "", sPath ? `;path=${sPath}` : "", sSameSite ? `;SameSite=${sSameSite}` : "", sSecure ? ";secure" : ""];
  1034. const sExpires = typeof sEnd === "number" && sEnd !== Infinity ? `;expires=${new Date(Date.now() + sEnd).toUTCString()}` : `;expires=Fri, 31 Dec 3999 23:59:59 GMT`;
  1035. document.cookie = `${sKey}=${sValue}${sExpires}${sDomain}${sPath}${sSameSite}${sSecure}`;
  1036. return true;
  1037. },
  1038. removeItem: function ({ sKey, sPath, sDomain }) {
  1039. if (!sKey || !new RegExp("(?:^|;\\s*)" + sKey.replace(/[-.+*]/g, "\\$&") + "\\s*\\=").test(document.cookie)) return false;
  1040. document.cookie = `${sKey}=;expires=Thu, 01 Jan 1970 00:00:00 GMT${sDomain ? `;domain=${sDomain}` : ""}${sPath ? `;path=${sPath}` : ""}`;
  1041. return true;
  1042. },
  1043. };
  1044. }
  1045.  
  1046. void (async function (getConfigureData, getResultFilterData, requestRemoteIcon, GMnotification) {
  1047. let [_config_date_, _filter_Data_] = await Promise.all([getConfigureData(), getResultFilterData()]);
  1048. const { trigger: antiResultsFilter, filter: resultFilters } = _filter_Data_;
  1049. const { isAutoUpdate, keywordHighlight, isHotkey, selectedEngine, localWindow, googleJump, antiLinkRedirect, antiAds, customColor } = _config_date_;
  1050. const [gbCookies, cachedRequestLinks, usedFilterWords, selectedSite] = [manageCookies(), antiLinkRedirect ? new Map() : null, antiResultsFilter ? new Set() : null, []];
  1051.  
  1052. /* ANTIREDIRECT_FUNCTIONS */
  1053.  
  1054. function validateOptions(options) {
  1055. return {
  1056. useNewTab: options.useNewTab || false,
  1057. forceSelf: options.forceSelf || false,
  1058. forceNewTab: options.forceNewTab || false,
  1059. cleanAttr: options.cleanAttr || [],
  1060. removeDataSet: options.removeDataSet || false,
  1061. advancedAnti: options.advancedAnti || false,
  1062. };
  1063. }
  1064.  
  1065. function updateNodeAttributes(options, node) {
  1066. if (options.useNewTab) node.setAttribute("target", "_blank");
  1067. if (options.forceSelf) node.setAttribute("target", "_self");
  1068. if (Array.isArray(options.cleanAttr) && options.cleanAttr.length > 0) options.cleanAttr.forEach(item => node.removeAttribute(item));
  1069. if (options.removeDataSet) Object.keys(node.dataset).forEach(ds => delete node.dataset[ds]);
  1070. node.setAttribute("gd-depurate-status", true);
  1071. }
  1072.  
  1073. function stopEventPropagation(event) {
  1074. event.preventDefault();
  1075. event.stopImmediatePropagation();
  1076. }
  1077.  
  1078. function setForceNewTab(options, node) {
  1079. if (!options.forceNewTab) return;
  1080. node.addEventListener("click", e => {
  1081. stopEventPropagation(e);
  1082. GMopenInTab(node.href, false);
  1083. });
  1084. }
  1085.  
  1086. function setAdvancedAntiRedirect(options, node, tasks, siteName) {
  1087. if (!options.advancedAnti) return;
  1088. node.setAttribute("gd-antiredirect-status", "pending");
  1089. const task = advancedAntiRedirection(siteName, node, () => Promise.resolve(NaN));
  1090. if (typeof task === "function") tasks.push(task);
  1091. }
  1092.  
  1093. function parsingAntiRedirect(selectors, siteName, options) {
  1094. if (typeof selectors !== "string" || selectors.trim() === "") return;
  1095. options = validateOptions(options);
  1096. const selectorArray = selectors.split(/,(?![^()]*\))/g);
  1097. const queryString = selectorArray.map(item => `${item}:not([href^='javascript:' i]):not([href^='#']):not([gd-depurate-status],[gd-antiredirect-status])`).join(",");
  1098. const aNodes = qA(queryString);
  1099. if (aNodes.length === 0) return;
  1100. COUNT(`[${siteName}-Anti-Redirect]`);
  1101. const taskList = aNodes.reduce((tasks, node) => {
  1102. updateNodeAttributes(options, node);
  1103. setForceNewTab(options, node);
  1104. setAdvancedAntiRedirect(options, node, tasks, siteName);
  1105. return tasks;
  1106. }, []);
  1107. parallelTasks(taskList, 10);
  1108. }
  1109.  
  1110. function fetchData(url, resolve, reject, readystate, error, timeout) {
  1111. const headers = { Accept: "*/*", Referer: global.location.origin.replace(/^http:/i, "https:") };
  1112. const [onload, onerror, ontimeout] = [readystate(resolve, reject), error(reject, resolve), timeout(reject)];
  1113. GMxmlhttpRequest({ url, headers, method: "GET", timeout: 25e3, onload, onerror, ontimeout });
  1114. }
  1115.  
  1116. async function getRealUrl(url, node, name, { onloadFunc, onerrorFunc, ontimeoutFunc }) {
  1117. try {
  1118. const res = await new Promise((resolve, reject) => {
  1119. if (!cachedRequestLinks.has(url)) {
  1120. cachedRequestLinks.set(url, null);
  1121. fetchData(url, resolve, reject, onloadFunc, onerrorFunc, ontimeoutFunc);
  1122. } else reject(new RangeError("DuplicateLinksError"));
  1123. });
  1124. return handleSuccess(res, url, node);
  1125. } catch (e) {
  1126. return handleError(e, url, node, name);
  1127. }
  1128. }
  1129.  
  1130. function handleSuccess(res, url, node) {
  1131. cachedRequestLinks.set(url, res);
  1132. setRealLink(node, res);
  1133. toggleLoadClass(node)?.remove();
  1134. DEBUG("Parsed link:", { node, parsed: res, origin: url });
  1135. }
  1136.  
  1137. function handleError(e, url, node, name) {
  1138. if (["URLBrokenError", "TimeoutError", "URLNotExistError", "ResponseError"].includes(e?.message)) cachedRequestLinks.set(url, url);
  1139. if (e?.message === "DuplicateLinksError") handleDuplicateLinksError(url, node);
  1140. else {
  1141. setErrorLink(node);
  1142. toggleLoadClass(node)?.remove();
  1143. ERROR("antiRedirect_%s: %s %O", name, e?.message, { Node: node, Text: node.textContent, URL: node.href });
  1144. }
  1145. }
  1146.  
  1147. function handleDuplicateLinksError(url, node) {
  1148. def.count.duplicate++;
  1149. const attemptToFindCacheLink = raf.setInterval(() => {
  1150. const cachedRealLinks = cachedRequestLinks.get(url);
  1151. if (!cachedRealLinks) return;
  1152. if (cachedRealLinks === url) setErrorLink(node);
  1153. else {
  1154. DEBUG("Duplicate link:", { node, url: cachedRealLinks });
  1155. setRealLink(node, cachedRealLinks);
  1156. }
  1157. def.count.duplicate--;
  1158. toggleLoadClass(node)?.remove();
  1159. raf.clearInterval(attemptToFindCacheLink);
  1160. }, 5e2);
  1161. }
  1162.  
  1163. function toggleLoadClass(node) {
  1164. if (node && IS_DEBUG) return { remove: () => node.classList.remove(def.const.loading), add: () => node.classList.add(def.const.loading) };
  1165. }
  1166.  
  1167. function setRealLink(node, url) {
  1168. node.href = url;
  1169. IS_REAL_WEBKIT && node.setAttribute("title", url);
  1170. node.setAttribute("gd-antiredirect-status", "success");
  1171. }
  1172.  
  1173. function setErrorLink(node) {
  1174. node.classList.add(def.notice.linkerror);
  1175. node.setAttribute("gd-antiredirect-status", "failed");
  1176. node.setAttribute("title", `${IS_CHN ? "该链接目前无法正常访问。" : "This link is currently not accessible."}`);
  1177. }
  1178.  
  1179. function handlePageCheck(count) {
  1180. DEBUG(`(${count ?? cachedRequestLinks.size}) Task Done! (${def.count.duplicate}) Dup.Task!`);
  1181. if (antiLinkRedirect && cachedRequestLinks.size > 0 && def.count.duplicate === 0) {
  1182. !cachedRequestLinks.clear() && DEBUG("Task Clear!");
  1183. }
  1184. if (antiResultsFilter && usedFilterWords.size > 0) {
  1185. !usedFilterWords.clear() && DEBUG("Filter Clear!");
  1186. }
  1187. }
  1188.  
  1189. function parallelTasks(tasks, maxCount = 3) {
  1190. const taskLength = tasks.length;
  1191. if (taskLength === 0) return;
  1192. let [currentIndex, finishedCount] = [0, 0];
  1193. const taskCount = Math.min(maxCount, taskLength);
  1194. function nextTask() {
  1195. if (currentIndex >= taskLength) return;
  1196. const task = tasks[currentIndex];
  1197. currentIndex++;
  1198. task().then(result => {
  1199. finishedCount++;
  1200. if (finishedCount === taskLength) deBounce({ fn: handlePageCheck, delay: 1e3, timer: "doTask" })(result);
  1201. else nextTask();
  1202. });
  1203. }
  1204. for (let i = 0; i < taskCount; i++) nextTask();
  1205. }
  1206.  
  1207. function reportIDMHijacking() {
  1208. const IDMText = IS_CHN
  1209. ? "PDF文件下载警告:\r\nInternet Download Manager (IDM) 等下载器的劫持可能会造成文件被直接下载。"
  1210. : "PDF File Download Warning:\r\nHijacking of downloaders such as Internet Download Manager (IDM) may cause files to be downloaded directly.";
  1211. __console("warn", IDMText);
  1212. }
  1213.  
  1214. function rejectResponse(response, resolve, reject, url) {
  1215. const resUrl = response.finalUrl || response.responseURL || url;
  1216. if (/^2\d\d$/.test(response.status)) {
  1217. if (response.statusText === "Intercepted by the IDM Advanced Integration") reportIDMHijacking();
  1218. resolve(resUrl);
  1219. } else if (response.status !== 0) resUrl === url ? reject(new Error("ResponseError")) : resolve(resUrl);
  1220. }
  1221.  
  1222. function getBingDecodeURI(url) {
  1223. const uParam = new URL(url).searchParams.get("u");
  1224. return uParam ? decrypt(uParam.slice(2).replace(/[-_]/g, v => (v === "-" ? "+" : "/"))) : url;
  1225. }
  1226.  
  1227. function getToutiaoDecodeURI(url) {
  1228. return decodeURIComponent(new URL(url).searchParams.get("url") ?? "");
  1229. }
  1230.  
  1231. function getYahooDecodeURI(url) {
  1232. const res = url.match(/\/RU=([^/]+)\//)?.[1];
  1233. return decodeURIComponent(res ?? "");
  1234. }
  1235.  
  1236. async function getNoneXHRDecodeURI(url, node, siteName, decodeUrl) {
  1237. try {
  1238. const d = await new Promise((resolve, reject) => {
  1239. if (!cachedRequestLinks.has(url)) {
  1240. cachedRequestLinks.set(url, null);
  1241. resolve(decodeUrl || url);
  1242. } else reject(new RangeError("DuplicateLinksError"));
  1243. });
  1244. return handleSuccess(d, url, node);
  1245. } catch (e) {
  1246. return handleError(e, url, node, siteName);
  1247. }
  1248. }
  1249.  
  1250. function getXHRDecodeURI(url, node, siteName) {
  1251. return getRealUrl(url, node, siteName, {
  1252. onloadFunc: (resolve, reject) => response => {
  1253. if (response.readyState !== 4) return;
  1254. if (response.status === 200) {
  1255. let resUrl = response.finalUrl || response.responseURL || url;
  1256. if (resUrl === url) {
  1257. const resText = response.responseText || response.response || "";
  1258. const res = resText.match(/URL\s*=\s*'([^']+)'/);
  1259. if (res) resUrl = res[1];
  1260. else reject(new Error("URLNotExistError"));
  1261. }
  1262. resolve(resUrl);
  1263. } else rejectResponse(response, resolve, reject, url);
  1264. },
  1265. onerrorFunc: reject => () => reject(new Error("URLBrokenError")),
  1266. ontimeoutFunc: reject => () => reject(new Error("TimeoutError")),
  1267. });
  1268. }
  1269.  
  1270. function advancedAntiRedirection(siteName, node, task) {
  1271. const url = node?.href?.replace(/^http:/i, "https:");
  1272. if (!url) return;
  1273. const tasks = {
  1274. Baidu: () =>
  1275. getRealUrl(url, node, siteName, {
  1276. onloadFunc: (resolve, reject) => response => {
  1277. if (response.readyState !== 4) return;
  1278. if (response.status === 200 || response.status === 301) {
  1279. let resUrl = response.finalUrl || response.responseURL || url;
  1280. if (resUrl === url) {
  1281. const responseHeader = response.responseHeaders?.match(/Location:\s*([\S]+)/i);
  1282. if (responseHeader) resUrl = responseHeader[1];
  1283. else reject(new Error("URLNotExistError"));
  1284. }
  1285. resolve(resUrl);
  1286. } else rejectResponse(response, resolve, reject, url);
  1287. },
  1288. onerrorFunc: (reject, resolve) => e => {
  1289. if (e.error?.includes("Request was redirected to a not whitelisted URL") || e.error?.includes("This domain is not a part of the @connect list")) {
  1290. const realUrl = e.error?.toString().match(/Refused to connect to "([^"]+)"/)?.[1];
  1291. if (!realUrl || realUrl.includes("/search/error") || realUrl.includes("/static/captcha")) reject(new Error("URLNotExistError"));
  1292. resolve(realUrl);
  1293. } else reject(new Error("URLBrokenError"));
  1294. },
  1295. ontimeoutFunc: reject => () => reject(new Error("TimeoutError")),
  1296. }),
  1297. So360: () => getXHRDecodeURI(url, node, siteName),
  1298. Sogou: () => getXHRDecodeURI(url, node, siteName),
  1299. Bing: () => getNoneXHRDecodeURI(url, node, siteName, getBingDecodeURI(url)),
  1300. Toutiao: () => getNoneXHRDecodeURI(url, node, siteName, getToutiaoDecodeURI(url)),
  1301. Yahoo: () => getNoneXHRDecodeURI(url, node, siteName, getYahooDecodeURI(url)),
  1302. };
  1303. toggleLoadClass(node)?.add();
  1304. return tasks[siteName] ?? task;
  1305. }
  1306.  
  1307. /* ANTIADS_FUNCTIONS */
  1308.  
  1309. const siteAdblockHandlers = {
  1310. Bing: (siteName, clean) => {
  1311. if (!CUR_HOST_NAME.startsWith("cn") || !qA(`:is(#b_results,#b_topw)>li:not(.${def.var.disappear})>div.b_caption>p[class*='b_lineclamp']`).length) return;
  1312. qA(`:is(#b_results,#b_topw)>li:not(.${def.var.disappear})`).forEach(node => {
  1313. const adv = qS("div.b_caption>p[class*='b_lineclamp']", node);
  1314. if (adv && (adv.className.includes("b_lineclamp2") || gCS(adv).getPropertyValue("-webkit-line-clamp") === "2")) {
  1315. COUNT(`[${siteName}-Anti-Ads-Deep-exp]`);
  1316. node.classList.add(def.var.disappear);
  1317. clean === true && safeRemoveNode(node);
  1318. }
  1319. });
  1320. },
  1321. Yandex: (siteName, clean) => {
  1322. const querystring = `.AliceFabPromo-Close,.PopupDesktop-Buttons button.PopupDesktop-Button_type_close`;
  1323. qA(querystring).forEach(item => item.click());
  1324. if (qA("li.serp-item.serp-item_card div.Organic-Subtitle span.organic__advLabel,li[data-cid][class*='_card'] .Organic-Subtitle>.Organic-Path~span").length === 0) return;
  1325. COUNT(`[${siteName}-Anti-Ads-Deep-exp]`);
  1326. qA("li.serp-item.serp-item_card,li[data-cid][class*='_card']").forEach(node => {
  1327. const adsTxtNode = qS(".Organic-Subtitle span.organic__advLabel", node);
  1328. const _moz_adsTxtNode = qS(".Organic-Subtitle>.Organic-Path~span", node);
  1329. if (/^(ad|[РекламPeknam]{7})$/i.test(_moz_adsTxtNode?.textContent || adsTxtNode?.textContent)) {
  1330. node.classList.add(def.var.disappear);
  1331. clean === true && safeRemoveNode(node);
  1332. }
  1333. });
  1334. },
  1335. So360: (siteName, clean) => {
  1336. if (qA("ul.section>li span.txt>s, ul.result>li>div.res-recommend-tag").length === 0) return;
  1337. COUNT(`[${siteName}-Anti-Ads-Deep-exp]`);
  1338. qA("ul.section>li,ul.result>li").forEach(node => {
  1339. const ads = qS("span[class='txt']>s", node);
  1340. if (!ads?.textContent?.includes("\u5e7f\u544a") && !qS("div.res-recommend-tag", node)) return;
  1341. node.classList.add(def.var.disappear);
  1342. clean === true && safeRemoveNode(node);
  1343. });
  1344. },
  1345. Ecosia: () => qS(`button.banner__close[data-test-id="banner-close"][aria-label="Close"]`)?.click(),
  1346. Qwant: () => qS(`button[class][aria-label="close"]:has(svg)`)?.click(),
  1347. Brave: () => qS(`.promo-tooltip>button.btn--icon[aria-label="Close"]`)?.click(),
  1348. Duckduckgo: () => qS(`button[data-testid="serp-popover-promo-close"]`)?.click(),
  1349. Yahoo: () => qS("button.refresh-soft-intro-dismiss-button")?.click(),
  1350. Swisscows: siteName => {
  1351. qS(`.dialog-content[id^="radix-"][role="dialog"][data-state="open"]>.buttons>button.button.button-link`)?.click();
  1352. if (qA(".web-results>article:not([data-ads]) .site>a:is(.policy,.ad)").length === 0) return;
  1353. qA(".web-results>article").forEach(node => {
  1354. if (qS(".site>a:is(.policy,.ad)", node)) {
  1355. node.style.cssText = "height:0;min-height:0;overflow:hidden;margin:0;padding:0";
  1356. node.dataset.ads = COUNT(`[${siteName}-Anti-Ads-Deep-exp]`) || "";
  1357. }
  1358. });
  1359. },
  1360. };
  1361.  
  1362. function parseAntiAdvertising({ selectors, siteName, isRemoveNodes }) {
  1363. if (selectors && typeof selectors === "string") {
  1364. if (!qS(`#${def.const.rndadvName}`)) {
  1365. COUNT(`[${siteName}-Anti-Ads]`);
  1366. const cssText = `:root :is(${selectors}){display:none!important}`;
  1367. addStyle({ target: document.head, styleId: def.const.rndadvName, media: "all", styleContent: cssText });
  1368. }
  1369. isRemoveNodes === true && safeRemoveNode(selectors);
  1370. }
  1371. AdvancedAntiAdvertising(siteName, isRemoveNodes);
  1372. }
  1373.  
  1374. function AdvancedAntiAdvertising(siteName, clean) {
  1375. const AdblockHandler = siteAdblockHandlers[siteName];
  1376. if (typeof AdblockHandler !== "function") return;
  1377. try {
  1378. AdblockHandler.length > 0 ? AdblockHandler(siteName, clean) : AdblockHandler();
  1379. } catch (e) {
  1380. ERROR("AdvancedAntiAdvertising:", e.message);
  1381. }
  1382. }
  1383.  
  1384. /* PRELOAD_FUNCTIONS */
  1385.  
  1386. async function fetchUpdateResponse(url, timeout = 1e4) {
  1387. try {
  1388. return await new Promise((resolve, reject) => {
  1389. const headers = { Accept: "*/*", Referer: url };
  1390. const onload = response => {
  1391. if (response.readyState !== 4) return;
  1392. if (response.status === 200) resolve({ res: response.responseText || response.response, url });
  1393. else if (response.status !== 0) reject(new Error("NoAccessError"));
  1394. };
  1395. const onerror = () => reject(new Error("NetworkError"));
  1396. const ontimeout = () => reject(new Error("TimeoutError"));
  1397. GMxmlhttpRequest({ url, headers, method: "GET", nocache: true, timeout, onload, onerror, ontimeout });
  1398. });
  1399. } catch (e) {
  1400. throw new Error(`fetchUpdateResponse: ${e.message}`);
  1401. }
  1402. }
  1403.  
  1404. async function fetchAndCacheRemoteIcons(remoteURL) {
  1405. if (!CUR_WINDOW_TOP) return;
  1406. let iconDataURL = null;
  1407. try {
  1408. const iconBase64Data = await cache.get(REMOTEICONS);
  1409. if (!iconBase64Data || setDebuggerMode()) {
  1410. DEBUG("%cRequest remote icon data...", "color:#25f");
  1411. iconDataURL = await requestRemoteIcon(remoteURL);
  1412. if (iconDataURL) cache.set(REMOTEICONS, iconDataURL, 2592e6) ?? DEBUG("%cRemote icon data parsed successfully.", "color:#006400");
  1413. else DEBUG("%cRemote icon data parsing failed.", "color:#ff0000");
  1414. } else {
  1415. DEBUG("%cGet local cached icon data.", "color:#006400");
  1416. iconDataURL = iconBase64Data;
  1417. }
  1418. } catch (e) {
  1419. ERROR(`fetchAndCacheRemoteIcons: Can't request the icon data.`, e?.message);
  1420. }
  1421. return iconDataURL;
  1422. }
  1423.  
  1424. void (async function (getUpdateAddress) {
  1425. const listSite = {
  1426. baidu: {
  1427. siteTypeID: 1,
  1428. siteButtonName: IS_CHN ? "百度一下" : "𝐁𝐚𝐢𝐝𝐮",
  1429. siteNickName: IS_CHN ? "百度 搜索" : "𝐁𝐚𝐢𝐝𝐮.𝐜𝐨𝐦",
  1430. siteHostName: "www.baidu.com",
  1431. webURL: "https://www.baidu.com/s?ie=utf-8&rqlang=cn&wd=",
  1432. imageURL: "https://image.baidu.com/search/index?tn=baiduimage&ps=1&ie=utf-8&word=",
  1433. imageType: ["baiduimage", "baiduimagedetail"],
  1434. splitTypeName: "tn",
  1435. mainSelector: ".s_btn_wr,#sugOut,span[class^='submit-btn']",
  1436. buttonCssText: `a,a em{text-decoration:none!important}:not([class^="page-inner"])>a:not(.${def.notice.linkerror}):hover{text-decoration:underline!important}#form{white-space:nowrap}#u{z-index:1!important}#${def.const.rndButtonID}{position:absolute;z-index:1999999995;display:inline-block;margin:0;padding:0;height:40px;vertical-align:top;line-height:40px;right:-210px}#${def.const.rndButtonID} *{-webkit-text-stroke:0 transparent!important}#${def.const.rndButtonID} #${def.const.leftButton}{display:inline-block;margin-left:2px;height:40px}#${def.const.rndButtonID} #${def.const.rightButton}{display:inline-block;margin-left:-1px;height:40px}#${def.const.leftButton} input{margin:0;padding:0 12px 0 18px!important;height:40px;min-width:100px;border:0;border-bottom-left-radius:10px;border-top-left-radius:10px;background:#4e6ef2;color:#fff;vertical-align:top;font-weight:500;font-size:16px!important;line-height:100%;cursor:pointer}#${def.const.rightButton} input{margin:0;padding:0 18px 0 12px!important;height:40px;min-width:100px;border:0;border-top-right-radius:10px;border-bottom-right-radius:10px;background:#4e6ef2;color:#fff;vertical-align:top;font-weight:500;font-size:16px!important;line-height:100%;cursor:pointer}#${def.const.leftButton} input:hover,#${def.const.rightButton} input:hover{background:#4662d9;border:1px solid transparent;}`,
  1437. resultListProp: { qs: `#content_left>div.c-container[tpl]:not([tpl='recommend_list'],[tpl^="rel-"])`, delay: 10 },
  1438. keywords: "#wrapper_wrapper em,.c-gap-top-small b",
  1439. antiRedirectFn: () =>
  1440. deBounce({ fn: parsingAntiRedirect, delay: 20, timer: "baidu_ar" })(".c-container a[href*='//www.baidu.com/link?url=']", "Baidu", {
  1441. useNewTab: true,
  1442. removeDataSet: true,
  1443. advancedAnti: true,
  1444. }),
  1445. antiAdsFn: () =>
  1446. deBounce({ fn: parseAntiAdvertising, delay: 20, timer: "baidu_ad", immed: true })({
  1447. selectors: `#s-hotsearch-wrapper,.result-op[tpl='sp_hot_sale'],.result-op[tpl='b2b_prod'],#content_left>div:not([class]):not([style]),div[data-placeid],[id$='_canvas'],div.result.c-container:not([class~='xpath-log']),.imgpage .imglist>li.newfcImgli,.ec_wise_ad,div[class^='result-op'][tpl='right_tabs'][data-click],div[class^='result-op'][tpl='right_links'][data-click],#searchTag,#content_left>div.c-container[tpl="recommend_list"],#con-ar div[tpl="right_recommends_merge"]`,
  1448. siteName: "Baidu",
  1449. isRemoveNodes: true,
  1450. }),
  1451. },
  1452. google: {
  1453. siteTypeID: 2,
  1454. siteButtonName: "𝐆𝐨𝐨𝐠𝐥𝐞",
  1455. siteNickName: IS_CHN ? "𝐆𝐨𝐨𝐠𝐥𝐞 搜索" : "𝐆𝐨𝐨𝐠𝐥𝐞.𝐜𝐨𝐦",
  1456. siteHostName: "www.google.com",
  1457. webURL: "https://www.google.com/search?newwindow=1&sca_upv=1&source=hp&q=",
  1458. imageURL: "https://www.google.com/search?newwindow=1&sca_upv=1&source=lnms&udm=2&sa=X&q=",
  1459. imageType: ["isch", "2"],
  1460. splitTypeName: ["tbm", "udm"],
  1461. mainSelector: "form button[type='submit']",
  1462. buttonCssText: `#pnnext>span:nth-child(2){clear:left}#${def.const.rndButtonID}{position:relative;z-index:100;display:flex;margin:0 4px 0 -5px;justify-content:center;align-items:center}#${def.const.rndButtonID} *{text-shadow:none!important;-webkit-text-stroke:0 transparent!important}#${def.const.rndButtonID} #${def.const.leftButton}{padding:0 2px 0 8px}.${def.const.scrollspan}{min-height:26px;margin-right:3px!important}.${def.const.scrollbars}{display:inline-block;margin:0;height:26px!important;font-weight:400!important;font-size:13px!important}#${def.const.leftButton} input{margin:0;padding:0 12px 0 18px!important;height:38px;min-width:90px;border:0;border-bottom-left-radius:24px;border-top-left-radius:24px;background:#1a73e8;box-shadow:none;color:#fff;vertical-align:top;font-weight:500;font-size:16px;line-height:100%;cursor:pointer}#${def.const.rightButton} input{margin:0;padding:0 18px 0 12px!important;height:38px;min-width:90px;border:0;border-top-right-radius:24px;border-bottom-right-radius:24px;background:#1a73e8;box-shadow:none;color:#fff;vertical-align:top;font-weight:500;font-size:16px;line-height:100%;cursor:pointer}#${def.const.leftButton} input:hover,#${def.const.rightButton} input:hover{background:#1b66c9;}@media (prefers-color-scheme: dark){#${def.const.leftButton} input,#${def.const.rightButton} input{background:#8ab4f8;box-shadow:0 1px 3px 1px rgba(0, 0, 0, 0.15),0 1px 2px rgba(0, 0, 0, 0.3);color:#202124}#${def.const.leftButton} input:hover,#${def.const.rightButton} input:hover{background:#93baf9}}`,
  1463. resultListProp: { qs: `div.MjjYud div.Ww4FFb.vt6azd[data-hveid^="C"][data-hveid$="AA"]:not(:has(div[jscontroller="TvBckd"]))`, delay: 10 },
  1464. keywords: ".aCOpRe em,.aCOpRe a em,.yXK7lf em,.yXK7lf a em,.st em,.st a em,.c2xzTb b,em.qkunPe",
  1465. antiRedirectFn: () =>
  1466. deBounce({ fn: parsingAntiRedirect, delay: 20, timer: "google_ar" })(
  1467. "#rcnt div[data-hveid^='C'][data-hveid$='AA'] :not(h3.ob5Hkd,.d0fCJc)>a:not(.ngTNl,.oRJe3d,.k8XOCe,[jsname='ZWuC2'],.fl,#pnprev,#pnnext)",
  1468. "Google",
  1469. { useNewTab: true, cleanAttr: ["ping"], removeDataSet: true }
  1470. ),
  1471. antiAdsFn: () =>
  1472. deBounce({ fn: parseAntiAdvertising, delay: 20, timer: "google_ad", immed: true })({
  1473. selectors: `div[aria-label='\u5e7f\u544a'],div[aria-label='Ads' i],#bottomads,#tvcap`,
  1474. siteName: "Google",
  1475. }),
  1476. },
  1477. bing: {
  1478. siteTypeID: 3,
  1479. siteButtonName: "𝐁𝐢𝐧𝐠 ®",
  1480. siteNickName: IS_CHN ? "𝐁𝐢𝐧𝐠 搜索" : "𝐁𝐢𝐧𝐠.𝐜𝐨𝐦",
  1481. siteHostName: "www.bing.com",
  1482. webURL: "https://www.bing.com/search?go=Search&qs=ds&form=QBRE&rdr=1&hta=off&q=",
  1483. imageURL: "https://www.bing.com/images/search?qs=ds&form=QBIR&first=1&q=",
  1484. imageType: ["images"],
  1485. splitTypeName: { split: "/", index: 1 },
  1486. mainSelector: `.b_searchboxForm>input[type="hidden"][name="form"]`,
  1487. buttonCssText: `html{overflow-x:hidden}#sb_form .inline_sb{border-radius:24px}.${def.const.searchbox}{border-radius:8px!important}a,#b_results>li[class] a:not(.wiki_seemore),#b_results .b_no a,#b_context .mediumCardTitle{color:#001ba0}#${def.const.rndButtonID}{position:relative;z-index:0;display:inline-flex;margin:0;padding:0 6px 0 0;width:auto;height:38px;min-width:180px;vertical-align:middle;justify-content:center;flex-wrap:nowrap}#${def.const.rndButtonID} *{text-shadow:none!important;-webkit-text-stroke:0 transparent!important}#${def.const.leftButton},#${def.const.rightButton}{margin:0;padding:0;width:auto}#${def.const.rndButtonID} input{box-sizing:border-box;height:38px;min-width:90px;border:1px solid #174ae4;background-color:#f7faff;color:#174ae4;font-weight:600;font-size:16px;line-height:100%;cursor:pointer}#${def.const.leftButton} input{margin:0;padding:0 12px 0 18px;border-bottom-left-radius:24px;border-top-left-radius:24px}#${def.const.rightButton} input{margin:0 0 0 2px;padding:0 18px 0 12px;border-top-right-radius:24px;border-bottom-right-radius:24px}.${def.const.scrollspan}{/*margin:-14px -3px 0 0!important;max-height:28px*/}.${def.const.scrollbars}{/*max-height:28px;font-size:14px!important*/}.${def.const.scrollspan2}{margin:0!important;padding:4px 4px 0 8px!important;max-height:30px;vertical-align:top!important}.${def.const.scrollbars2}{margin-right:0!important;padding:0 12px!important;max-height:30px;border-radius:4px!important;vertical-align:top!important}#${def.const.leftButton} input:hover,#${def.const.rightButton} input:hover{background-color:#fff;background-color:#f0f3f6;box-shadow:0 0 4px #174ae4;color:#174ae4;transition:border .1s linear,box-shadow .3s linear}.${def.notice.random}_input{width:300px!important}@media (prefers-color-scheme: dark){.b_dark #b_results>li[class] a{color:#7aabeb}#${def.const.leftButton} input,#${def.const.rightButton} input{border:1px solid #a2b7f4;background:transparent;color:#a2b7f4}#${def.const.leftButton} input:hover,#${def.const.rightButton} input:hover{background:#a2b7f4;color:#333}}`,
  1488. resultListProp: {
  1489. qs: `#b_results>li.b_algo:not(.b_algoBorder,.b_topborder),#b_results>li.b_vidAns .mmlist>div[id],#b_results>li.b_mop .b_slidebar>div.slide,#b_topw>li.b_ans,aside>ol#b_context>li.b_algo`,
  1490. delay: 10,
  1491. },
  1492. keywords:
  1493. Number(getUrlParam("ensearch")) || Number(gbCookies.getItem("ENSEARCH")?.match(/[=](\d)/)?.[1])
  1494. ? "strong,.b_no h4,.b_strong,.b_ad .b_adlabel strong,.cbl"
  1495. : "#sp_requery strong,#sp_recourse strong,.sb_adTA_title_link_cn strong,.b_ad .ad_esltitle~div strong,h2 strong,#b_results .b_algo p strong,.b_caption p strong,.b_snippetBigText strong,.recommendationsTableTitle+.b_slideexp strong,.recommendationsTableTitle+table strong,.recommendationsTableTitle+ul strong,.pageRecoContainer .b_module_expansion_control strong,.pageRecoContainer .b_title>strong,.b_rs strong,.b_rrsr strong,.richrswrapper strong,#dict_ans strong,.b_listnav>.b_ans_stamp>strong,#b_content #ans_nws .na_cnt strong,.b_vidAns strong,.adltwrnmsg strong",
  1496. antiRedirectFn: function () {
  1497. safeWindow.Object.assign(GMunsafeWindow, { AwayTimeScrollTopPoleRS: false, AwayTimeThreshold: 864e3 });
  1498. const antiRedirect = () => {
  1499. parsingAntiRedirect("#b_results>li:not(.b_pag,#mfa_root) a:not([role='button']):not([href*='.bing.com/ck/a?'])", "Bing", { useNewTab: true, cleanAttr: ["h"] });
  1500. parsingAntiRedirect("#b_results a.b_widePag:not([href*='.bing.com/ck/a?'])", "Bing", { forceSelf: true, cleanAttr: ["h"] });
  1501. parsingAntiRedirect("#b_content a[href*='.bing.com/ck/a?']:not([role='button'],.b_widePag)", "Bing", { useNewTab: true, cleanAttr: ["h"], advancedAnti: true });
  1502. parsingAntiRedirect("#b_content a.b_widePag[href*='.bing.com/ck/a?']", "Bing", { forceSelf: true, cleanAttr: ["h"], advancedAnti: true });
  1503. };
  1504. deBounce({ fn: antiRedirect, delay: 20, timer: "bing_ar" })();
  1505. },
  1506. antiAdsFn: () =>
  1507. deBounce({ fn: parseAntiAdvertising, delay: 20, timer: "bing_ad", immed: true })({
  1508. selectors: `li.b_ans>div.wpt_bc_container,li.b_ans>#relatedSearchesLGWContainer,li.b_ans>.b_rs,li.b_ad,#b_pole,#b_content .b_underSearchbox,#b_header>div[id^="bnp."][data-vertical],#b_context li.b_ans .b_spa_adblock,.ad_sc,.b_adBottom,.b_adLastChild,.b_adPATitleBlock,.b_spa_adblock,.mapsTextAds,.pa_sb,.productAd,[id$="adsMvCarousel"],a[href*="/aclick?ld="],div.pagereco_anim,#inline_rs,#ev_talkbox_wrapper,#b_content>main[aria-label]>#b_ims_bza_pole,.shop_page .br-poleoffcarousel,#b_content>div#pole>div[class="ra_car_block ra_pole"]>div.ra_car_container,#pole>.productAd[data-ad-carousel],.b_adPATitleBlock+div,a.sb_meta[href^="http://advertise.bingads.microsoft.com"],.promotion-panel-inner,.ins_exp.vsp,li[class="b_algo"]:has(.b_attribution[data-partnertag] + p[class]),.b_ans:has([class^="xm_"][class*="_ansCont"])`,
  1509. siteName: "Bing",
  1510. }),
  1511. },
  1512. duckduckgo: {
  1513. siteTypeID: 4,
  1514. siteButtonName: "𝐃𝐮𝐜𝐤𝐝𝐮𝐜𝐤𝐠𝐨",
  1515. siteNickName: IS_CHN ? "𝐃𝐮𝐜𝐤𝐝𝐮𝐜𝐤𝐠𝐨 搜索" : "𝐃𝐮𝐜𝐤𝐝𝐮𝐜𝐤𝐠𝐨",
  1516. siteHostName: "duckduckgo.com",
  1517. webURL: "https://duckduckgo.com/?k1=-1&kl=wt-wt&kd=-1&ko=1&kn=1&kp=-2&t=h_&ia=web&q=",
  1518. imageURL: "https://duckduckgo.com/?k1=-1&kl=wt-wt&kd=-1&ko=s&kn=1&kp=-2&t=h_&iax=images&ia=images&q=",
  1519. imageType: ["images"],
  1520. splitTypeName: "ia",
  1521. mainSelector: "#search_form",
  1522. buttonCssText: `#${def.const.rndButtonID}{position:absolute;top:0;right:-188px;z-index:1999999995;display:block;height:44px}#${def.const.leftButton}{display:inline-block;height:44px}#${def.const.rightButton}{display:inline-block;margin:0 0 0 -2px;height:44px}#${def.const.leftButton} input{margin:0;padding:1px 10px 1px 15px!important;height:44px;min-width:100px;border:1px solid var(--theme-col-bg-button-secondary-hover);border-bottom-left-radius:var(--default-border-radius);border-top-left-radius:var(--default-border-radius);background:transparent;box-shadow:0 2px 3px rgba(0, 0, 0, 0.06);color:var(--theme-col-txt-button-secondary);vertical-align:top;font-weight:400;font-size:16px;line-height:100%;cursor:pointer}#${def.const.rightButton} input{margin:0;padding:1px 15px 1px 10px!important;height:44px;min-width:100px;border:1px solid var(--theme-col-bg-button-secondary-hover);border-top-right-radius:var(--default-border-radius);border-bottom-right-radius:var(--default-border-radius);background:transparent;box-shadow:0 2px 3px rgba(0, 0, 0, 0.06);color:var(--theme-col-txt-button-secondary);vertical-align:top;font-weight:400;font-size:16px;line-height:100%;cursor:pointer}#${def.const.leftButton} input:hover,#${def.const.rightButton} input:hover{border:1px solid transparent;background-color:#2950bf!important;color:#fff!important}`,
  1523. resultListProp: {
  1524. qs: `ol.react-results--main>li[data-layout="organic"],ol.react-results--main>li[data-layout="videos"] div.module--carousel__item,ol.react-results--main>li:has(div[data-react-module-id="about"])`,
  1525. delay: 10,
  1526. },
  1527. keywords: "strong, b",
  1528. antiRedirectFn: null,
  1529. antiAdsFn: () =>
  1530. deBounce({ fn: parseAntiAdvertising, delay: 20, timer: "ddg_ad", immed: true })({
  1531. selectors: `.footer,.react-results--main>li[data-layout="related_searches"]>div[class]`,
  1532. siteName: "Duckduckgo",
  1533. isRemoveNodes: true,
  1534. }),
  1535. },
  1536. sogou: {
  1537. siteTypeID: 5,
  1538. siteButtonName: IS_CHN ? "搜狗搜索" : "𝐒𝐨𝐠𝐨𝐮",
  1539. siteNickName: IS_CHN ? "搜狗 搜索" : "𝐒𝐨𝐠𝐨𝐮.𝐜𝐨𝐦",
  1540. siteHostName: "www.sogou.com",
  1541. webURL: "https://www.sogou.com/web?query=",
  1542. imageURL: "https://pic.sogou.com/pics?query=",
  1543. imageType: ["pics", "d", "v"],
  1544. splitTypeName: { split: "/", index: 1 },
  1545. mainSelector: "input#searchBtn,input[type='button'][uigs='search_article'],input[type='submit']:is(.search-btn,.sbtn1)",
  1546. buttonCssText: `#${def.const.rndButtonID}{position:absolute;top:0;right:0;z-index:1999999995;margin:-1px 0 0;padding:0;width:auto;height:39px;cursor:pointer;-webkit-appearance:none}#${def.const.rndButtonID} *{-webkit-text-stroke:0 transparent!important}#${def.const.leftButton}{display:inline;height:39px}#${def.const.rightButton}{display:inline;height:39px}#${def.const.leftButton} input{margin:0;padding:0 18px!important;height:39px;min-width:100px;border:2px solid #222;border-radius:12px;background:#f5f5f5;color:#000;vertical-align:top;font-weight:500;font-size:14px!important;line-height:100%;cursor:pointer}#${def.const.rightButton} input{margin:0;padding:0 18px!important;height:39px;min-width:100px;border:2px solid #222;border-radius:12px;background:#f5f5f5;color:#000;vertical-align:top;font-weight:500;font-size:14px!important;line-height:100%;cursor:pointer}#${def.const.leftButton} input:hover,#${def.const.rightButton} input:hover{border:2px solid #205aef;background:#e9f2ff;color:#205aef}.${def.notice.random}_images{height:34px!important;border:1px solid #ababab!important;border-radius:3px!important;background:##fafafa!important}.${def.notice.random}_weixin{height:34px!important;border:1px solid #00a06a!important;border-radius:2px!important;background:#fff!important;color:#00a06a!important;font-size:15px!important}.${def.notice.random}_weixin:hover{background:#f7fffd!important}`,
  1547. resultListProp: { qs: `div.results>div.vrwrap,div.results>div.rb`, delay: 10 },
  1548. keywords: "#wrapper em",
  1549. antiRedirectFn: () =>
  1550. deBounce({ fn: parsingAntiRedirect, delay: 20, timer: "sogou_ar" })("#wrapper a[href^='/link?url=']:not([uigs])", "Sogou", { useNewTab: true, advancedAnti: true }),
  1551. antiAdsFn: () =>
  1552. deBounce({ fn: parseAntiAdvertising, delay: 20, timer: "sogou_ad", immed: true })({
  1553. selectors: `#biz_tip_box_tuiguang_float,.pz_pc_new_container,.share-wrap,.sponsored,.tgad-box,[class~="ext_query"][id*="sq_ext_"],div.top-better-hintBox,#right>div.rvr-model:not([tpl]),.results>.reactResult`,
  1554. siteName: "Sogou",
  1555. isRemoveNodes: true,
  1556. }),
  1557. },
  1558. qwant: {
  1559. siteTypeID: 6,
  1560. siteButtonName: "𝐐𝐰𝐚𝐧𝐭",
  1561. siteNickName: IS_CHN ? "𝐐𝐰𝐚𝐧𝐭 搜索" : "𝐐𝐰𝐚𝐧𝐭.𝐜𝐨𝐦",
  1562. siteHostName: "www.qwant.com",
  1563. webURL: "https://www.qwant.com/?t=web&b=1&q=",
  1564. imageURL: "https://www.qwant.com/?t=images&b=1&q=",
  1565. imageType: ["images"],
  1566. splitTypeName: "t",
  1567. mainSelector: "form[data-testid='mainSearchBar']",
  1568. buttonCssText: `#${def.const.rndButtonID}{position:absolute;top:0;right:0;z-index:1999999995;display:block;height:48px}#${def.const.leftButton}{display:inline-block;height:48px}#${def.const.rightButton}{display:inline-block;margin:0;height:48px}#${def.const.leftButton} input{box-sizing:content-box;margin:1px 0;padding:0 6px 0 12px!important;height:48px;min-width:100px;box-shadow:var(--shadow-searchbar-elevation);transition:box-shadow var(--motion-duration-200) var(--motion-ease), color var(--motion-duration-300) var(--motion-ease), background-color var(--motion-duration-300) var(--motion-ease);border-bottom-left-radius:var(--border-radius-300);border-top-left-radius:var(--border-radius-300);background-color:var(--color-elevation-surface-elevation);color:var(--color-text-primary);vertical-align:top;font-weight:400;font-size:16px;line-height:100%;cursor:pointer}#${def.const.rightButton} input{box-sizing:content-box;margin:1px 0;padding:0 12px 0 6px!important;height:48px;min-width:100px;box-shadow:var(--shadow-searchbar-elevation);transition:box-shadow var(--motion-duration-200) var(--motion-ease), color var(--motion-duration-300) var(--motion-ease), background-color var(--motion-duration-300) var(--motion-ease);border-top-right-radius:var(--border-radius-300);border-bottom-right-radius:var(--border-radius-300);background-color:var(--color-elevation-surface-elevation);color:var(--color-text-primary);vertical-align:top;font-weight:400;font-size:16px;line-height:100%;cursor:pointer}#${def.const.leftButton} input:hover,#${def.const.rightButton} input:hover{background-color:var(--color-elevation-surface-raised);box-shadow:var(--shadow-searchbar-raised);}`,
  1569. resultListProp: { qs: `div[data-testid="containerWeb"] div[data-testid="sectionWeb"]>div>div,.is-sidebar>div>div div[style="display: block;"]`, delay: 50 },
  1570. keywords: "mark",
  1571. antiRedirectFn: null,
  1572. antiAdsFn: () =>
  1573. deBounce({ fn: parseAntiAdvertising, delay: 20, timer: "qwant_ad", immed: true })({
  1574. selectors: `div[data-testid="containerWeb"] section div[style="display: block;"]:has([data-testid="aserpok"]),.is-sidebar>div>div:has([data-testid="aserpok"]),[data-testid="containerWeb"] section>div>div:last-child`,
  1575. siteName: "Qwant",
  1576. removeDataSet: true,
  1577. }),
  1578. },
  1579. yandex: {
  1580. siteTypeID: 7,
  1581. siteButtonName: "𝐘𝐚𝐧𝐝𝐞𝐱",
  1582. siteNickName: IS_CHN ? "𝐘𝐚𝐧𝐝𝐞𝐱 搜索" : "𝐘𝐚𝐧𝐝𝐞𝐱.𝐜𝐨𝐦",
  1583. siteHostName: "yandex.com",
  1584. webURL: `https://yandex.${navigator.language === "ru" ? "ru" : "eu"}/search/?text=`,
  1585. imageURL: `https://yandex.${navigator.language === "ru" ? "ru" : "eu"}/images/search?from=tabbar&family=no&text=`,
  1586. imageType: ["images"],
  1587. splitTypeName: { split: "/", index: 1 },
  1588. mainSelector: "header form.HeaderForm",
  1589. buttonCssText: `#${def.const.rndButtonID}{position:relative;top:0;left:-12px;z-index:1999999995;margin:0;padding:0;width:max-content;height:52px;cursor:pointer;-webkit-appearance:none}#${def.const.leftButton}{display:inline-block;height:52px}#${def.const.rightButton}{display:inline-block;margin:0 0 0 -1px;height:52px}#${def.const.leftButton} input{padding:1px 12px 0 18px!important;height:52px;min-width:100px;border:none;box-shadow:0 0 0 2px inset rgba(0, 0, 0, 0.1);border-bottom-left-radius:28px;border-top-left-radius:28px;background:#fff;color:#00000073;vertical-align:top;font-weight:400;font-size:16px;line-height:100%;cursor:pointer}#${def.const.rightButton} input{padding:1px 18px 0 12px!important;height:52px;min-width:100px;border:none;box-shadow:0 0 0 2px inset rgba(0, 0, 0, .1);border-top-right-radius:28px;border-bottom-right-radius:28px;background:#fff;color:#00000073;vertical-align:top;font-weight:400;font-size:16px;line-height:100%;cursor:pointer}#${def.const.leftButton} input:hover,#${def.const.rightButton} input:hover{background-color:#fbfbfb}@media (prefers-color-scheme: dark){#${def.const.leftButton} input,#${def.const.rightButton} input{color:#eee;background:#18181a;box-shadow:0 0 0 2px inset #3a3a3c;}#${def.const.leftButton} input:hover,#${def.const.rightButton} input:hover{background:#333}}`,
  1590. resultListProp: { qs: "#search-result>li[data-fast]", delay: 10 },
  1591. keywords: ".OrganicTitleContentSpan b,.OrganicTextContentSpan b",
  1592. antiRedirectFn: () => deBounce({ fn: parsingAntiRedirect, delay: 20, timer: "yandex_ar" })("#search-result>li.serp-item a", "Yandex", { useNewTab: true, removeDataSet: true }),
  1593. antiAdsFn: () =>
  1594. deBounce({ fn: parseAntiAdvertising, delay: 20, timer: "yandex_ad", immed: true })({
  1595. selectors: `#distr-pcode-container>div,div.HeaderDesktopActions-Distribution.HeaderDesktopActions-Item,div[tabindex][class*='location_right-bottom'],span.distr-nav,div.market-cart`,
  1596. siteName: "Yandex",
  1597. isRemoveNodes: true,
  1598. }),
  1599. },
  1600. so360: {
  1601. siteTypeID: 8,
  1602. siteButtonName: IS_CHN ? "𝟑𝟔𝟎搜索" : "𝟑𝟔𝟎𝐬𝐨",
  1603. siteNickName: IS_CHN ? "𝟑𝟔𝟎 搜索" : "𝐰𝐰𝐰.𝐬𝐨.𝐜𝐨𝐦",
  1604. siteHostName: "www.so.com",
  1605. webURL: "https://www.so.com/s?ie=utf-8&q=",
  1606. imageURL: "https://image.so.com/i?q=",
  1607. imageType: ["i", "view"],
  1608. splitTypeName: { split: "/", index: 1 },
  1609. mainSelector: "input[type='submit'][value='搜索'],button[type='submit'][class~='so-search__button']",
  1610. buttonCssText: `#${def.const.rndButtonID}{position:relative;top:0;left:0;z-index:199999995;margin:0 0 0 5px;padding:0;width:auto;height:40px;cursor:pointer;-webkit-appearance:none}#${def.const.leftButton}{display:inline-block;padding:0 1px 0 0;height:40px;vertical-align:top}#${def.const.rightButton}{display:inline-block;height:40px;vertical-align:top}#${def.const.leftButton} input{margin:0 -2px 0 0;padding:0 18px!important;height:40px;min-width:100px;border:1px solid #0fb264;border-bottom-left-radius:8px;border-top-left-radius:8px;background:#0fb264;color:#fff;vertical-align:top;font-weight:400;font-size:16px!important;line-height:100%;cursor:pointer}#${def.const.rightButton} input{margin:0;padding:0 18px!important;height:40px;min-width:100px;border:1px solid #0fb264;border-top-right-radius:8px;border-bottom-right-radius:8px;background:#0fb264;color:#fff;vertical-align:top;font-weight:400;font-size:16px!important;line-height:100%;cursor:pointer}#${def.const.leftButton} input:hover,#${def.const.rightButton} input:hover{box-shadow: 0 1px 2px rgba(0,0,0,0.1);background:#2dc471}`,
  1611. resultListProp: { qs: `ul.result>li.res-list`, delay: 10 },
  1612. keywords: "em,#mohe-newdict_dict .mh-exsentence b",
  1613. antiRedirectFn: () =>
  1614. deBounce({ fn: parsingAntiRedirect, delay: 20, timer: "so360_ar" })(".res-list a[href*='//www.so.com/link?m=']", "So360", {
  1615. useNewTab: true,
  1616. cleanAttr: ["e_href", "data-res"],
  1617. advancedAnti: true,
  1618. }),
  1619. antiAdsFn: () =>
  1620. deBounce({ fn: parseAntiAdvertising, delay: 20, timer: "so360_ad", immed: true })({
  1621. selectors: `#so_bd-ad,#e_idea_pp,#righttop_box,[id^='mohe-360pic_ext--'],.res-mediav,.map_business_con,.lianmeng-ad,.res-mediav-right,.atom-adv,.e-buss,.spread,ul[data-so-biz-monitor-so-display],.related_query li.cm,[class='inline-recommend'][data-url],div#so_top,div#so-activity-entry,div.mh-relate-text,.section li[data-id^="related_query_init_"],#mohe-know_side_nlp`,
  1622. siteName: "So360",
  1623. isRemoveNodes: true,
  1624. }),
  1625. },
  1626. toutiao: {
  1627. siteTypeID: 9,
  1628. siteButtonName: IS_CHN ? "搜头条" : "𝐓𝐨𝐮𝐭𝐢𝐚𝐨",
  1629. siteNickName: IS_CHN ? "头条 搜索" : "𝐬𝐨.𝐭𝐨𝐮𝐭𝐢𝐚𝐨.𝐜𝐨𝐦",
  1630. siteHostName: "so.toutiao.com",
  1631. webURL: "https://so.toutiao.com/search?dvpf=pc&keyword=",
  1632. imageURL: "https://so.toutiao.com/search?dvpf=pc&pd=atlas&from=gallery&keyword=",
  1633. imageType: ["atlas"],
  1634. splitTypeName: "pd",
  1635. mainSelector: "div[class^='search'][data-log-click]",
  1636. buttonCssText: `#${def.const.rndButtonID}{position:absolute;top:0;right:-160px;z-index:1999999995;margin:-1px;padding:0;width:auto;height:44px;cursor:pointer;-webkit-appearance:none}#${def.const.leftButton}{display:inline-block;height:44px}#${def.const.rightButton}{display:inline-block;margin:0 0 0 -2px;height:44px}#${def.const.leftButton} input{margin:0;padding:1px 10px 1px 15px!important;height:44px;min-width:100px;border:1px solid transparent;border-bottom-left-radius:8px;border-top-left-radius:8px;background:#f04142;color:#fff;vertical-align:top;font-weight:500;font-size:18px;line-height:100%;cursor:pointer}#${def.const.rightButton} input{margin:0;padding:1px 15px 1px 10px!important;height:44px;min-width:100px;border:1px solid transparent;border-top-right-radius:8px;border-bottom-right-radius:8px;background:#f04142;color:#fff;vertical-align:top;font-weight:500;font-size:18px;line-height:100%;cursor:pointer}#${def.const.leftButton} input:hover,#${def.const.rightButton} input:hover{background-color:rgba(240, 65, 66, 0.7);color:#fff}`,
  1637. resultListProp: { qs: `div.s-result-list:not(.pd-video)>div.result-content[data-i]`, delay: 10 },
  1638. keywords: "em",
  1639. antiRedirectFn: () =>
  1640. deBounce({ fn: parsingAntiRedirect, delay: 20, timer: "toutiao_ar" })(".main a[href*='/search/jump?url=']", "Toutiao", { useNewTab: true, advancedAnti: true }),
  1641. antiAdsFn: null,
  1642. },
  1643. kaifa: {
  1644. siteTypeID: 10,
  1645. siteButtonName: IS_CHN ? "百度开发者" : "𝐃𝐞𝐯.𝐁𝐚𝐢𝐝𝐮",
  1646. siteNickName: IS_CHN ? "百度开发者 搜索" : "𝐃𝐞𝐯.𝐁𝐚𝐢𝐝𝐮",
  1647. siteHostName: "kaifa.baidu.com",
  1648. webURL: "https://kaifa.baidu.com/searchPage?module=SEARCH&wd=",
  1649. imageURL: "https://kaifa.baidu.com/searchPage?module=SUG&wd=",
  1650. imageType: [null],
  1651. splitTypeName: "",
  1652. mainSelector: "div#search-box-container .ant-input-group-addon",
  1653. buttonCssText: `.ant-input-group-addon{background:transparent!important}#${def.const.rndButtonID}{position:relative;z-index:1999999995;display:inline-block;margin-left:4px;height:40px;vertical-align:bottom}#${def.const.rndButtonID} #${def.const.leftButton}{display:inline-block;margin-left:2px;height:40px}#${def.const.rndButtonID} #${def.const.rightButton}{display:inline-block;margin-left:-2px;height:40px}#${def.const.leftButton} input{margin:0;padding:1px 12px 1px 18px!important;height:40px;min-width:100px;border:1px solid var(--ee-brand-6);border-bottom-left-radius:10px;border-top-left-radius:10px;background:var(--ee-brand-6);color:#fff;vertical-align:top;font-weight:500;font-size:16px!important;line-height:100%;cursor:pointer}#${def.const.rightButton} input{margin:0;padding:1px 18px 1px 12px!important;height:40px;min-width:100px;border:1px solid var(--ee-brand-6);border-top-right-radius:10px;border-bottom-right-radius:10px;background:var(--ee-brand-6);color:#fff;vertical-align:top;font-weight:500;font-size:16px!important;line-height:100%;cursor:pointer}#${def.const.leftButton} input:hover,#${def.const.rightButton} input:hover{border:1px solid var(--ee-brand-5);background:var(--ee-brand-5)}`,
  1654. resultListProp: { qs: `ul.ant-list-items>li.ant-list-item`, delay: 10 },
  1655. keywords: "mark",
  1656. antiRedirectFn: null,
  1657. antiAdsFn: () => deBounce({ fn: parseAntiAdvertising, delay: 20, timer: "kaifa_ad", immed: true })({ selectors: `#reward-entry`, siteName: "Kaifa", isRemoveNodes: true }),
  1658. },
  1659. ecosia: {
  1660. siteTypeID: 11,
  1661. siteButtonName: "𝐄𝐜𝐨𝐬𝐢𝐚",
  1662. siteNickName: IS_CHN ? "𝐄𝐜𝐨𝐬𝐢𝐚 搜索" : "𝐄𝐜𝐨𝐬𝐢𝐚.𝐨𝐫𝐠",
  1663. siteHostName: "www.ecosia.org",
  1664. webURL: "https://www.ecosia.org/search?method=index&q=",
  1665. imageURL: "https://www.ecosia.org/images?q=",
  1666. imageType: ["images"],
  1667. splitTypeName: { split: "/", index: 1 },
  1668. mainSelector: "form[role='search'][class~='search-form'][data-test-id='main-header-search-form']",
  1669. buttonCssText: `#${def.const.rndButtonID}{position:relative;z-index:1999999995;display:inline-block;margin-left:4px;height:40px}#${def.const.rndButtonID} #${def.const.leftButton}{display:inline-block;margin-left:2px;height:40px}#${def.const.rndButtonID} #${def.const.rightButton}{display:inline-block;margin-left:-2px;height:40px}#${def.const.leftButton} input{margin:0;padding:1px 12px 1px 18px!important;height:40px;min-width:100px;border:1px solid var(--color-form-border-default);border-bottom-left-radius:20px;border-top-left-radius:20px;background:var(--color-background-primary);box-shadow:0 1px 2px rgba(26,26,26,.18),0 0 8px rgba(26,26,26,.06);color:var(--color-button-content-tertiary);vertical-align:top;font-weight:700;font-size:16px!important;line-height:100%;cursor:pointer}#${def.const.rightButton} input{margin:0;padding:1px 18px 1px 12px!important;height:40px;min-width:100px;border:1px solid var(--color-form-border-default);border-top-right-radius:20px;border-bottom-right-radius:20px;background:var(--color-background-primary);box-shadow:0 1px 2px rgba(26,26,26,.18),0 0 8px rgba(26,26,26,.06);color:var(--color-button-content-tertiary);vertical-align:top;font-weight:700;font-size:16px!important;line-height:100%;cursor:pointer}#${def.const.leftButton} input:hover,#${def.const.rightButton} input:hover{border:1px solid var(--color-button-background-primary-hover);background:var(--color-button-background-primary-hover);color:var(--color-button-content-primary)}`,
  1670. resultListProp: { qs: `.mainline__content>div:not([class])>div[data-test-id="mainline-result-web"],aside>article[position="sidebar"]`, delay: 150 },
  1671. keywords: "",
  1672. antiRedirectFn: function () {
  1673. ["adBlockNoticeDismissed", "personalCounterTooltipSearch"].forEach(item => localStorages?.setItem(item, 1));
  1674. const fn = option => !/:nt=1:/.test(gbCookies.getItem("ECFG")) && gbCookies.setItem(option) && reload();
  1675. const sValue = `a=0:as=1:cs=0:dt=pc:f=i:fr=0:fs=1:l=en:lt=${Date.now()}:mc=zh-cn:nf=1:nt=1:pz=0:t=1:tt=0:tu=auto:wu=auto:ma=1`;
  1676. deBounce({ fn, timer: "ecosia_cookie", immed: true, once: true })({ sKey: "ECFG", sValue, sEnd: Infinity, sDomain: ".ecosia.org", sPath: "/", sSomeSite: "Lax" });
  1677. },
  1678. antiAdsFn: () =>
  1679. deBounce({ fn: parseAntiAdvertising, delay: 20, timer: "ecosia_ad", immed: true })({
  1680. selectors: `div[data-test-id="sidebar-onboarding"][href],div.main-header__install-cta,div.main-footer-visual__cards,div.personal-counter__tooltip,div.cookie-wrapper,div.mainline__footer>a[data-test-id='chat-entry'],[data-test-id="mainline-result-ad"]`,
  1681. siteName: "Ecosia",
  1682. }),
  1683. },
  1684. yahoo: {
  1685. siteTypeID: 12,
  1686. siteButtonName: "𝐘𝐚𝐡𝐨𝐨",
  1687. siteNickName: IS_CHN ? "𝐘𝐚𝐡𝐨𝐨 搜索" : "𝐬𝐞𝐚𝐫𝐜𝐡.𝐘𝐚𝐡𝐨𝐨",
  1688. siteHostName: "search.yahoo.com",
  1689. webURL: "https://search.yahoo.com/search?p=",
  1690. imageURL: "https://images.search.yahoo.com/search/images?p=",
  1691. imageType: ["images"],
  1692. splitTypeName: () => CUR_HOST_NAME.split(".").slice(-4, -3)[0],
  1693. mainSelector: "#hd div.sbx form#sf,header.hd section#sbx form#sf",
  1694. buttonCssText: `#${def.const.rndButtonID}{position:relative;position:absolute;z-index:1999999995;display:inline-block;margin-left:4px;width:max-content;height:44px}#${def.const.rndButtonID} *{text-shadow:none!important;-webkit-text-stroke:0 transparent!important}#${def.const.rndButtonID} #${def.const.leftButton}{display:inline-block;margin-left:2px;height:44px}#${def.const.rndButtonID} #${def.const.rightButton}{display:inline-block;margin-left:-2px;height:44px}#${def.const.leftButton} input{box-sizing:content-box;margin:0;padding:0 12px 0 18px!important;height:44px;min-width:60px;border:1px solid transparent;border-bottom-left-radius:100px;border-top-left-radius:100px;background:#7e1fff;color:#fff;vertical-align:top;font-weight:500;font-size:16px!important;line-height:100%;cursor:pointer}#${def.const.rightButton} input{box-sizing:content-box;margin:0;padding:0 18px 0 12px!important;height:44px;min-width:60px;border:1px solid transparent;border-top-right-radius:100px;border-bottom-right-radius:100px;background:#7e1fff;color:#fff;vertical-align:top;font-weight:500;font-size:16px!important;line-height:100%;cursor:pointer}#${def.const.leftButton} input:hover,#${def.const.rightButton} input:hover{border:1px solid transparent;background:#6001d2;color:#fff}`,
  1695. resultListProp: { qs: `#web>ol>li`, delay: 10 },
  1696. keywords: "strong",
  1697. antiRedirectFn: () =>
  1698. deBounce({ fn: parsingAntiRedirect, delay: 20, timer: "yahoo_ar" })(
  1699. "#main ol a[href^='https://r.search.yahoo.com/_ylt='],#main #results #sres>li>a[href^='https://r.search.yahoo.com/_ylt=']",
  1700. "Yahoo",
  1701. { useNewTab: true, advancedAnti: true }
  1702. ),
  1703. antiAdsFn: () =>
  1704. deBounce({ fn: parseAntiAdvertising, delay: 20, timer: "yahoo_ad", immed: true })({
  1705. selectors: `#main ol.searchCenterBottomAds,#main ol.searchCenterTopAds`,
  1706. siteName: "Yahoo",
  1707. }),
  1708. },
  1709. you: {
  1710. siteTypeID: 13,
  1711. siteButtonName: "𝐘𝐨𝐮 ®",
  1712. siteNickName: IS_CHN ? "𝐘𝐨𝐮 搜索" : "𝐘𝐨𝐮.𝐜𝐨𝐦",
  1713. siteHostName: "you.com",
  1714. webURL: "https://you.com/search?fromSearchBar=true&q=",
  1715. imageURL: "https://you.com/search?fromSearchBar=true&tbm=isch&q=",
  1716. imageType: ["isch"],
  1717. splitTypeName: "tbm",
  1718. mainSelector: "button[data-testid='qb_submit_button']",
  1719. buttonCssText: `#${def.const.rndButtonID}{position:relative;z-index:999;display:inline;margin:0;height:36px}#${def.const.rndButtonID} *{text-shadow:none!important;-webkit-text-stroke:0 transparent!important}#${def.const.rndButtonID} #${def.const.leftButton}{display:inline-block;height:36px}#${def.const.rndButtonID} #${def.const.rightButton}{display:inline-block;margin-left:-2px;height:36px}#${def.const.leftButton} input{margin:0;padding:0 10px;height:36px;min-width:80px;border:1px solid #596ced;border-bottom-left-radius:12px;border-top-left-radius:12px;background-color:#596ced;color:#fff;vertical-align:top;font-weight:400;font-size:16px!important;line-height:100%;cursor:pointer}#${def.const.rightButton} input{margin:0;padding:0 10px;height:36px;min-width:80px;border:1px solid #596ced;border-top-right-radius:12px;border-bottom-right-radius:12px;background-color:#596ced;color:#fff;vertical-align:top;font-weight:400;font-size:16px!important;line-height:100%;cursor:pointer}#${def.const.leftButton} input:hover,#${def.const.rightButton} input:hover{border:1px solid #7a89f0;background-color:#7a89f0;color:#fff}@media (prefers-color-scheme: dark){#${def.const.leftButton} input:hover,#${def.const.rightButton} input:hover{border:1px solid #4d5cc3;background-color:#4d5cc3;}}`,
  1720. resultListProp: {
  1721. qs: `[data-floating-ui-portal]>[role='dialog'][data-open='true'] section>article,div[data-eventappname="web_results"] section>article,div[data-eventappname="web_results"] ul>li`,
  1722. delay: 10,
  1723. },
  1724. keywords: `div[data-testid="app-mainline"] p strong,div[data-testid="app-mainline"] p b`,
  1725. antiRedirectFn: () =>
  1726. deBounce({ fn: parameters => parameters.forEach(item => localStorages?.setItem(item, true)), timer: "you_set", immed: true, once: true })([
  1727. "openLinksInNewTabs",
  1728. "hasSeenP13nAnnouncement",
  1729. "hasUserClosedExtensionModal",
  1730. ]),
  1731. antiAdsFn: null,
  1732. },
  1733. startpage: {
  1734. siteTypeID: 14,
  1735. siteButtonName: "𝐒𝐭𝐚𝐫𝐭𝐩𝐚𝐠𝐞",
  1736. siteNickName: IS_CHN ? "𝐒𝐭𝐚𝐫𝐭𝐩𝐚𝐠𝐞 搜索" : "𝐒𝐭𝐚𝐫𝐭𝐩𝐚𝐠𝐞.𝐜𝐨𝐦",
  1737. siteHostName: "www.startpage.com",
  1738. webURL: `https://www.startpage.com/sp/search?t=device&segment=startpage.${brand.toLowerCase()}&cat=web&query=`,
  1739. imageURL: `https://www.startpage.com/sp/search?t=device&segment=startpage.${brand.toLowerCase()}&cat=images&query=`,
  1740. imageType: ["images"],
  1741. splitTypeName: "cat",
  1742. mainSelector: "#search[role='search'] button.search-btn",
  1743. buttonCssText: `#${def.const.rndButtonID}{position:relative;z-index:999;display:inline-block;margin:-1px 5px 0 0;height:40px}#${def.const.rndButtonID} *{text-shadow:none!important;-webkit-text-stroke:0 transparent!important}#${def.const.rndButtonID} #${def.const.leftButton}{display:inline-block;height:40px}#${def.const.rndButtonID} #${def.const.rightButton}{display:inline-block;margin-left:0;height:40px}#${def.const.leftButton} input{margin:0;padding:0 10px 0 20px!important;height:40px;min-width:95px;border:0 solid transparent;border-bottom-left-radius:2rem;border-top-left-radius:2rem;background:#f1f3ff;box-shadow:0 0 2px #a4a5bb;color:#2e39b3;font-weight:600;font-size:14px!important;line-height:100%;cursor:pointer}#${def.const.rightButton} input{margin:0;padding:0 20px 0 10px!important;height:40px;min-width:95px;border:0 solid transparent;border-top-right-radius:2rem;border-bottom-right-radius:2rem;background:#f1f3ff;box-shadow:0 0 2px #a4a5bb;color:#2e39b3;font-weight:600;font-size:14px!important;line-height:100%;cursor:pointer}#${def.const.leftButton} input:hover,#${def.const.rightButton} input:hover{background:#6573ff;color:#fff}@media (prefers-color-scheme: dark){#${def.const.leftButton} input{border:1px solid #252b3b;background:#252b3b;color:#fff}#${def.const.rightButton} input{border:1px solid #252b3b;background:#252b3b;color:#fff}#${def.const.leftButton} input:hover,#${def.const.rightButton} input:hover{border:1px solid #6573ff;background:#6573ff}}`,
  1744. resultListProp: { qs: `#main>.w-gl>div.result,.wiki-container>div[role="region"]`, delay: 1e2 },
  1745. keywords: `.result b`,
  1746. antiRedirectFn: function () {
  1747. const setGBCookie = option => !/disable_open_in_new_windowEEE0|enable_post_methodEEE0/.test(gbCookies.getItem("preferences")) && gbCookies.setItem(option) && reload();
  1748. const sValue = `date_timeEEEworldN1Ndisable_family_filterEEE0N1Ndisable_open_in_new_windowEEE0N1Nenable_post_methodEEE0N1Nenable_proxy_safety_suggestEEE1N1Nenable_stay_controlEEE0N1Ninstant_answersEEE1N1Nlang_homepageEEEs/device/enN1NlanguageEEEenglishN1Nlanguage_uiEEEenglishN1Nnum_of_resultsEEE20N1Nsearch_results_regionEEEallN1NsuggestionsEEE1N1Nwt_unitEEEcelsius`;
  1749. const option = { sKey: "preferences", sValue, sEnd: Infinity, sDomain: ".startpage.com", sPath: "/", sSecure: true };
  1750. deBounce({ fn: setGBCookie, timer: "startpage_cookie", delay: 20, immed: true, once: true })(option);
  1751. },
  1752. antiAdsFn: () =>
  1753. deBounce({ fn: parseAntiAdvertising, delay: 20, timer: "startpage_ad", immed: true })({
  1754. selectors: `section.a-gl-tp,div.widget-install-legacy,div.mainline-results>div.block-display,.Firefox-promo`,
  1755. siteName: "Startpage",
  1756. }),
  1757. },
  1758. brave: {
  1759. siteTypeID: 15,
  1760. siteButtonName: "𝐁𝐫𝐚𝐯𝐞",
  1761. siteNickName: IS_CHN ? "𝐁𝐫𝐚𝐯𝐞 搜索" : "𝐬𝐞𝐚𝐫𝐜𝐡.𝐁𝐫𝐚𝐯𝐞",
  1762. siteHostName: "search.brave.com",
  1763. webURL: "https://search.brave.com/search?source=web&q=",
  1764. imageURL: "https://search.brave.com/images?source=web&spellcheck=0&q=",
  1765. imageType: ["images"],
  1766. splitTypeName: { split: "/", index: 1 },
  1767. mainSelector: ".searchform-container[data-testid='searchform-container']",
  1768. buttonCssText: `#${def.const.rndButtonID}{position:relative;z-index:999;display:inline;margin:0 0 0 10px;padding:0;width:max-content;height:var(--search-form-height)}.${def.const.scrollspan},.${def.const.scrollbars}{height:var(--search-form-height-compact)!important}.${def.const.scrollbars}{border-radius:var(--border-radius-l)!important;box-shadow:none!important}#${def.const.rndButtonID} *{text-shadow:none!important;-webkit-text-stroke:0 transparent!important}#${def.const.rndButtonID} #${def.const.rightButton},#${def.const.rndButtonID} #${def.const.leftButton}{display:inline-block;height:100%}#${def.const.leftButton} input{margin:0;padding:0 20px!important;height:var(--search-form-height);min-width:95px;border:0;outline:1px solid var(--color-serp-divider-subtle-container);box-shadow:var(--elevation-02);border-bottom-left-radius:var(--border-radius-xl);border-top-left-radius:var(--border-radius-xl);background:var(--color-serp-bar-bg);color:var(--color-text-primary);vertical-align:top;font-weight:600;font-size:16px!important;line-height:16px;box-sizing:border-box;cursor:pointer}#${def.const.rightButton} input{margin:0;padding:0 20px!important;height:var(--search-form-height);min-width:95px;border:0;outline:1px solid var(--color-serp-divider-subtle-container);box-shadow:var(--elevation-02);border-top-right-radius:var(--border-radius-xl);border-bottom-right-radius:var(--border-radius-xl);background:var(--color-serp-bar-bg);color:var(--color-text-primary);vertical-align:top;font-weight:600;font-size:16px!important;line-height:16px;box-sizing:border-box;cursor:pointer}#${def.const.leftButton} input:hover,#${def.const.rightButton} input:hover{color:var(--color-primitive-white, #fff);background:linear-gradient(314deg,#fa7250 8.49%,#ff1893 43.72%,#a78aff 99.51%);}`,
  1769. resultListProp: { qs: `#results>div.snippet[data-type],#results>.standalone>.video-item`, delay: 10 },
  1770. keywords: `.snippet-content strong`,
  1771. antiRedirectFn: function () {
  1772. localStorages?.setItem("app.aiPromoDismissCount", 10);
  1773. const option = { sKey: "olnt", sValue: "1", sEnd: Infinity, sDomain: "search.brave.com", sPath: "/", sSameSite: "Lax", sSecure: true };
  1774. deBounce({ fn: opt => gbCookies.getItem("olnt") !== "1" && gbCookies.setItem(opt) && reload(), timer: "brave_cookie", immed: true, once: true })(option);
  1775. deBounce({ fn: parsingAntiRedirect, delay: 20, timer: "brave_ar" })("#results>div#search-elsewhere a", "Brave", { useNewTab: true, forceNewTab: true, removeDataSet: true });
  1776. },
  1777. antiAdsFn: () => deBounce({ fn: parseAntiAdvertising, delay: 20, timer: "brave_ad" })({ siteName: "Brave" }),
  1778. },
  1779. yep: {
  1780. siteTypeID: 16,
  1781. siteButtonName: "𝐘𝐞𝐩 ®",
  1782. siteNickName: IS_CHN ? "𝐘𝐞𝐩 搜索" : "𝐘𝐞𝐩.𝐜𝐨𝐦",
  1783. siteHostName: "yep.com",
  1784. webURL: "https://yep.com/web?q=",
  1785. imageURL: "https://yep.com/images?q=",
  1786. imageType: ["images"],
  1787. splitTypeName: { split: "/", index: 1 },
  1788. mainSelector: `form div[class$="-addon"]`,
  1789. buttonCssText: `#${def.const.rndButtonID}{position:absolute;top:.5em;z-index:112;display:block;margin:-6px 0 0;padding:0;height:50px}#${def.const.rndButtonID} *{text-shadow:none!important;-webkit-text-stroke:0 transparent!important}#${def.const.rndButtonID} #${def.const.leftButton}{display:inline-block;height:50px}#${def.const.rndButtonID} #${def.const.rightButton}{display:inline-block;margin-left:-1px;height:50px}#${def.const.leftButton} input{margin:0;padding:4px 15px 4px 25px!important;height:50px;min-width:95px;border:1px solid #f1dc1b;border-bottom-left-radius:25px;border-top-left-radius:25px;background:var(--background--brand);color:#333;vertical-align:top;font-weight:600;font-size:16px!important;line-height:16px;cursor:pointer}#${def.const.rightButton} input{margin:0;padding:4px 25px 4px 15px!important;height:50px;min-width:95px;border:1px solid #f1dc1b;border-top-right-radius:25px;border-bottom-right-radius:25px;background:var(--background--brand);color:#333;vertical-align:top;font-weight:600;font-size:16px!important;line-height:16px;cursor:pointer}#${def.const.leftButton} input:hover,#${def.const.rightButton} input:hover{background:var(--background--brandHover)}`,
  1790. resultListProp: { qs: `div[class*='-results']>div>div>div[class*='-card'],div[class*='-sidebar']>div>div>div>div[class*='-stack']`, delay: 20 },
  1791. keywords: ``,
  1792. antiRedirectFn: () =>
  1793. deBounce({ fn: parsingAntiRedirect, delay: 30, timer: "yep_ar", immed: true })(
  1794. "div[class*='-results']>div>div>div[class*='-card'] a,div[class*='-results']>div>div>div[class*='-block'] a,div[class*='-results']>div>div>div[class*='-incut'] div[class*='-newsIncut'] a,div[class*='-results']>div>div>div[class*='-incut'] div[class*='-container'] a",
  1795. "Yep",
  1796. { useNewTab: true, forceNewTab: true, cleanAttr: ["referrerpolicy"] }
  1797. ),
  1798. antiAdsFn: null,
  1799. },
  1800. swisscows: {
  1801. siteTypeID: 17,
  1802. siteButtonName: "𝐒𝐰𝐢𝐬𝐬𝐜𝐨𝐰𝐬",
  1803. siteNickName: IS_CHN ? "𝐒𝐰𝐢𝐬𝐬𝐜𝐨𝐰𝐬 搜索" : "𝐒𝐰𝐢𝐬𝐬𝐜𝐨𝐰𝐬.𝐜𝐨𝐦",
  1804. siteHostName: "swisscows.com",
  1805. webURL: "https://swisscows.com/en/web?query=",
  1806. imageURL: "https://swisscows.com/en/images?query=",
  1807. imageType: ["images"],
  1808. splitTypeName: { split: "/", index: 2 },
  1809. mainSelector: "form>.searchbar>button.erase",
  1810. buttonCssText: `#header .form-search{max-width:35em}#${def.const.rndButtonID}{position:absolute;top:0;z-index:112;display:block;margin:0;padding:0;height:48px}#${def.const.rndButtonID} *{text-shadow:none!important;-webkit-text-stroke:0 transparent!important}#${def.const.rndButtonID} #${def.const.leftButton}{display:inline-block;height:2.5em}#${def.const.rndButtonID} #${def.const.rightButton}{display:inline-block;margin-left:-1px;height:48px}#${def.const.leftButton} input{box-sizing:content-box;margin:0;padding:0 2px 0 4px!important;height:48px;min-width:95px;border-width:0;border-bottom-left-radius:24px;border-top-left-radius:24px;background:var(--button-background);color:var(--button-text-color);vertical-align:top;font-weight:600;font-size:14px!important;line-height:100%;cursor:pointer}#${def.const.rightButton} input{box-sizing:content-box;margin:0;padding:0 4px 0 2px!important;height:48px;min-width:95px;border-width:0;border-top-right-radius:24px;border-bottom-right-radius:24px;background:var(--button-background);color:var(--button-text-color);vertical-align:top;font-weight:600;font-size:14px!important;line-height:100%;cursor:pointer}#${def.const.leftButton} input:hover,#${def.const.rightButton} input:hover{background:var(--button-focus-background);color:var(--button-text-color)}@media (prefers-color-scheme: dark){#${def.const.leftButton} input,#${def.const.rightButton} input{border:1px solid #eee;background:none;color:#eee;height:46px}#${def.const.leftButton} input:hover,#${def.const.rightButton} input:hover{background:var(--button-focus-background);color:var(--button-text-color)}}`,
  1811. resultListProp: { qs: `.web-results>article.item,.web-results>article.widget`, delay: 10 },
  1812. keywords: `.web-results b`,
  1813. antiRedirectFn: () =>
  1814. deBounce({ fn: parsingAntiRedirect, delay: 20, timer: "swisscows_ar" })(".web-results>article.item a,.web-results>div.widget a:not(.widget-button)", "Swisscows", {
  1815. useNewTab: true,
  1816. forceNewTab: true,
  1817. }),
  1818. antiAdsFn: () =>
  1819. deBounce({ fn: parseAntiAdvertising, delay: 50, timer: "swisscows_ad", immed: true })({
  1820. selectors: `header :is(.badge-tg,.badge-vpn,.badge-email,.search-counter,.badge-edelcloud),.web-results>div[class*="-privacy"],.web-results>section.widget.widget-products`,
  1821. siteName: "Swisscows",
  1822. }),
  1823. },
  1824. searxng: {
  1825. siteTypeID: 18,
  1826. siteButtonName: "𝐒𝐞𝐚𝐫𝐗𝐍𝐆",
  1827. siteNickName: IS_CHN ? "𝐒𝐞𝐚𝐫𝐗𝐍𝐆 搜索" : "𝐒𝐞𝐚𝐫𝐗𝐍𝐆 ©",
  1828. siteHostName: "searx.space",
  1829. webURL: "https://search.inetol.net/search?category_general=&language=all&time_range=&safesearch=0&theme=simple&q=",
  1830. imageURL: "https://search.inetol.net/search?category_images=&language=all&time_range=&safesearch=0&theme=simple&q=",
  1831. imageType: ["images"],
  1832. splitTypeName: () => global.location.search.match(/category_([a-z]+)/)?.[1],
  1833. mainSelector: "#search_view>div.search_box",
  1834. buttonCssText: `#${def.const.rndButtonID}{position:relative;top:0;right:-10px;width:0;z-index:199995;display:block;height:45px}#${def.const.leftButton}{display:inline-block;height:45px}#${def.const.rightButton}{display:inline-block;margin:0;height:45px}#${def.const.leftButton} input{margin:0;padding:1px 10px 1px 15px!important;height:45px;min-width:100px;border:0 solid #ccc;border-bottom-left-radius:.8rem;border-top-left-radius:.8rem;background:var(--color-search-background);box-shadow:var(--color-search-shadow);color:var(--color-search-font);vertical-align:top;font-weight:400;font-size:16px;line-height:100%;cursor:pointer}#${def.const.rightButton} input{margin:0;padding:1px 15px 1px 10px!important;height:45px;min-width:100px;border:0;border-top-right-radius:.8rem;border-bottom-right-radius:.8rem;background:var(--color-search-background);box-shadow:var(--color-search-shadow);color:var(--color-search-font);vertical-align:top;font-weight:400;font-size:16px;line-height:100%;cursor:pointer}#${def.const.rndButtonID}:hover #${def.const.leftButton} input,#${def.const.rndButtonID}:hover #${def.const.rightButton} input{background-color:var(--color-search-background);color:var(--color-search-font);}#${def.const.leftButton} input:hover,#${def.const.rightButton} input:hover{border:1px solid transparent;background-color:var(--color-search-background-hover)!important;color:var(--color-search-background)!important}`,
  1835. resultListProp: { qs: `div#urls article.result`, delay: 10 },
  1836. keywords: ".highlight",
  1837. antiRedirectFn: () => deBounce({ fn: parsingAntiRedirect, delay: 20, timer: "searxng_ar" })("div#urls article.result a", "SearXNG", { useNewTab: true }),
  1838. antiAdsFn: null,
  1839. },
  1840. other: { siteTypeID: 0 },
  1841. };
  1842.  
  1843. const newSiteType = {
  1844. BAIDU: listSite.baidu.siteTypeID,
  1845. GOOGLE: listSite.google.siteTypeID,
  1846. BING: listSite.bing.siteTypeID,
  1847. DUCKDUCKGO: listSite.duckduckgo.siteTypeID,
  1848. SOGOU: listSite.sogou.siteTypeID,
  1849. QWANT: listSite.qwant.siteTypeID,
  1850. YANDEX: listSite.yandex.siteTypeID,
  1851. SO360: listSite.so360.siteTypeID,
  1852. TOUTIAO: listSite.toutiao.siteTypeID,
  1853. KAIFA: listSite.kaifa.siteTypeID,
  1854. ECOSIA: listSite.ecosia.siteTypeID,
  1855. YAHOO: listSite.yahoo.siteTypeID,
  1856. YOU: listSite.you.siteTypeID,
  1857. STARTPAGE: listSite.startpage.siteTypeID,
  1858. BRAVE: listSite.brave.siteTypeID,
  1859. YEP: listSite.yep.siteTypeID,
  1860. SWISSCOWS: listSite.swisscows.siteTypeID,
  1861. SEARXNG: listSite.searxng.siteTypeID,
  1862. OTHERS: listSite.other.siteTypeID,
  1863. };
  1864.  
  1865. const engineMap = {
  1866. "^(w+\\.)?google\\.[a-z.]{2,6}$": { siteType: newSiteType.GOOGLE, site: listSite.google },
  1867. "kaifa\\.baidu\\.com$": { siteType: newSiteType.KAIFA, site: listSite.kaifa },
  1868. "\\.baidu\\.com$": { siteType: newSiteType.BAIDU, site: listSite.baidu },
  1869. "\\.bing\\.com$": { siteType: newSiteType.BING, site: listSite.bing },
  1870. "duckduckgo\\.com$": { siteType: newSiteType.DUCKDUCKGO, site: listSite.duckduckgo },
  1871. "\\.sogou\\.com$": { siteType: newSiteType.SOGOU, site: listSite.sogou },
  1872. "www\\.qwant\\.com$": { siteType: newSiteType.QWANT, site: listSite.qwant },
  1873. "yandex\\.(com|ru|eu)$": { siteType: newSiteType.YANDEX, site: listSite.yandex },
  1874. "\\.so\\.com$": { siteType: newSiteType.SO360, site: listSite.so360 },
  1875. "so\\.toutiao\\.com$": { siteType: newSiteType.TOUTIAO, site: listSite.toutiao },
  1876. "www\\.ecosia\\.org$": { siteType: newSiteType.ECOSIA, site: listSite.ecosia },
  1877. "search\\.yahoo\\.com$": { siteType: newSiteType.YAHOO, site: listSite.yahoo },
  1878. "you\\.com$": { siteType: newSiteType.YOU, site: listSite.you },
  1879. "startpage\\.com$": { siteType: newSiteType.STARTPAGE, site: listSite.startpage },
  1880. "search\\.brave\\.com$": { siteType: newSiteType.BRAVE, site: listSite.brave },
  1881. "yep\\.com$": { siteType: newSiteType.YEP, site: listSite.yep },
  1882. "swisscows\\.com$": { siteType: newSiteType.SWISSCOWS, site: listSite.swisscows },
  1883. "search\\.inetol\\.net$": { siteType: newSiteType.SEARXNG, site: listSite.searxng },
  1884. };
  1885.  
  1886. const searchProperties = {
  1887. inputArray: [
  1888. 'input#kw[name^="w"]',
  1889. 'input[name="q"]:not([type="hidden"])',
  1890. 'input[name="text"][type="text"]',
  1891. 'input#q[name="query"]',
  1892. 'input[name="query"][class$="query"]:not([id*="bottom"])',
  1893. 'input.input-search[type="search"]',
  1894. 'input[type="search"][class*="input"]',
  1895. '#search-box-container input[class~="ant-input"]',
  1896. 'input#yschsp[name="p"]',
  1897. 'textarea#sb_form_q[name="q"]',
  1898. 'textarea[jsaction][name="q"]',
  1899. "textarea#search-input-textarea",
  1900. ],
  1901. searchKeys: ["wd", "word", "query", "q", "text", "keyword", "p"],
  1902. };
  1903.  
  1904. const { currentSite = {}, listCurrentSite = {} } = findCurrentSite();
  1905. const { currentSiteName, allSiteURIs } = updateSiteInformation();
  1906. const { backgroundColor: bgcolor, foregroundColor: fgcolor } = customColor;
  1907. const updateDetectionAddress = getUpdateAddress();
  1908. const yandexIconsAPIUrl = `${def.url.yandexIcon}/${allSiteURIs}?size=32&stub=1`;
  1909. const iconBase64Data = await fetchAndCacheRemoteIcons(yandexIconsAPIUrl);
  1910.  
  1911. /* DEFINE_GLOBAL_STYLES */
  1912.  
  1913. def.var.style = String(
  1914. `.${def.notice.noticeX} *,.${def.notice.noticeX} *::after,.${def.notice.noticeX} *::before {box-sizing:content-box;line-height:normal}.${def.notice.animated}{animation-duration:1s;animation-fill-mode:both}@keyframes fadeIn{from{opacity:0}to{opacity:1}}.${def.notice.random}_fadeIn{animation-name:fadeIn}@keyframes fadeOut{from{opacity:1}to{opacity:0}}.${def.notice.random}_fadeOut{animation-name:fadeOut}.${def.notice.appear}{display:block!important}.${def.notice.noticeX},.${def.notice.noticeX} *{text-shadow:none!important;font-family:Microsoft YaHei UI,system-ui,-apple-system,BlinkMacSystemFont,sans-serif!important;-webkit-text-stroke:0 transparent!important}.${def.notice.noticeX}-top{top:0;width:100%}.${def.notice.noticeX}-top .${def.notice.item}{margin:0!important;border-radius:0!important}.${def.notice.noticeX}-topRight{top:10px;right:10px;z-index:2147483647!important}.${def.notice.noticeX}-topLeft{top:10px;left:10px}.${def.notice.noticeX}-topCenter{top:10px;left:50%;transform:translate(-50%)}.${def.notice.noticeX}-middleLeft,.${def.notice.noticeX}-middleRight{right:10px;top:50%;transform:translateY(-50%)}.${def.notice.noticeX}-middleLeft{left:10px}.${def.notice.noticeX}-middleCenter{top:50%;left:50%;transform:translate(-50%,-50%)}.${def.notice.noticeX}-bottom{bottom:0;width:100%}.${def.notice.noticeX}-bottom .${def.notice.item}{border-radius:0!important;margin:0!important}.${def.notice.noticeX}-bottomRight{bottom:10px;right:10px;z-index:2147483646!important}.${def.notice.noticeX}-bottomLeft{bottom:10px;left:10px}.${def.notice.noticeX}-bottomCenter{bottom:10px;left:50%;transform:translate(-50%)}.${def.notice.noticeX} .${def.notice.item}{margin:0 0 10px;border-radius:6px;overflow:hidden}.${def.var.translucent} *{display:none!important}.${def.var.translucent} notice-label{display:block!important}.${def.var.disappear}{display:none!important}[gb-filter-notice]{display:block!important;min-width:430px;margin:18px 0 28px 10px!important;padding:10px 2px!important;font:normal 400 14px/100% 'WenQuanYi Micro Hei','PingFang SC','Microsoft YaHei',sans-serif!important;-webkit-text-stroke:0 transparent!important;color:grey!important;line-height:1!important}gb-filters.code{display:block;margin:20px 0;word-break:break-word;font-size:12px!important}.${def.notice.noticeX} .${def.notice.item} .${def.notice.close}{float:right;margin-right:7px;color:#fff;text-shadow:0 1px 0 #fff;font-weight:700;font-size:18px!important;line-height:1;opacity:1}` +
  1915. `.${def.notice.noticeX} .${def.notice.item} .${def.notice.close}:hover{color:#000;opacity:.5;cursor:pointer}.${def.notice.noticeX} .${def.notice.item} a{border-bottom:1px dashed #fff;color:#fff}.${def.notice.noticeX} .${def.notice.item} a,.${def.notice.noticeX} .${def.notice.item} a:hover{text-decoration:none}.${def.notice.noticeX} .${def.notice.success}{background-color:#64ce83!important}.${def.notice.noticeX} .${def.notice.success} .${def.notice.noticeX}-heading{padding:10px;background-color:#3da95c;color:#fff;font-weight:700;font-size:14px!important}.${def.notice.noticeX} .${def.notice.success} .${def.notice.noticeX}-body{padding:10px!important;color:#fff;}.${def.notice.noticeX} .${def.notice.success} .${def.notice.noticeX}-body:hover{visibility:visible!important}.${def.notice.noticeX} .${def.notice.success} .${def.notice.noticeX}-content{visibility:visible}.${def.notice.noticeX} .${def.notice.info}{background-color:#3ea2ff!important}.${def.notice.noticeX} .${def.notice.info} .${def.notice.noticeX}-heading{padding:10px;background-color:#067cea;color:#fff;font-weight:700;font-size:14px!important}.${def.notice.noticeX} .${def.notice.info} .${def.notice.noticeX}-body{padding:10px!important;color:#fff}.${def.notice.noticeX} .${def.notice.info} .${def.notice.noticeX}-body:hover{visibility:visible!important}.${def.notice.noticeX} .${def.notice.info} .${def.notice.noticeX}-content{visibility:visible}.${def.notice.noticeX} .${def.notice.warning}{background-color:#ff7f48!important}.${def.notice.noticeX} .${def.notice.warning} .${def.notice.noticeX}-heading{padding:10px!important;background-color:#f97038;color:#fff;font-weight:700;font-size:14px!important}.${def.notice.noticeX} .${def.notice.warning} .${def.notice.noticeX}-body{color:#fff;padding:10px}.${def.notice.noticeX} .${def.notice.warning} .${def.notice.noticeX}-body:hover{visibility:visible!important}.${def.notice.noticeX} .${def.notice.warning} .${def.notice.noticeX}-content{visibility:visible}.${def.notice.noticeX} .${def.notice.error}{background-color:#e74c3c!important}.${def.notice.noticeX} .${def.notice.error} .${def.notice.noticeX}-heading{padding:10px!important;background-color:#e93724;color:#fff;font-weight:700;font-size:14px!important}.${def.notice.noticeX} .${def.notice.error} .${def.notice.noticeX}-body{padding:10px;color:#fff}.${def.notice.noticeX} .${def.notice.error} .${def.notice.noticeX}-body:hover{visibility:visible!important}` +
  1916. `.${def.notice.noticeX} .${def.notice.error} .${def.notice.noticeX}-content{visibility:visible}.${def.notice.configuration} input[disabled],.${def.notice.configuration} select[disabled]{color:#bbb;background:linear-gradient(45deg,#ffe9e9 0,#ffe9e9 25%,transparent 25%,transparent 50%,#ffe9e9 50%,#ffe9e9 75%,transparent 75%,transparent)!important;background-size:20px 20px!important;background-color:#fff7f7!important}.${def.notice.noticeX} .${def.notice.configuration}{background:linear-gradient(to right,#fcfcfc,#f2f2f7);background:-webkit-gradient(linear,0 0,0 100%,from(#fcfcfc),to(#f2f2f7));box-shadow:0 0 5px #888}.${def.notice.noticeX} .${def.notice.configuration} .${def.notice.close}{float:right;margin-right:7px;color:#000000;text-shadow:0 1px 0 #aaa;font-weight:700;font-size:18px!important;line-height:1;opacity:1}.${def.notice.noticeX} .${def.notice.configuration} .${def.notice.close}:hover{color:#555;opacity:.5;cursor:pointer}.${def.notice.noticeX} .${def.notice.configuration} .${def.notice.noticeX}-heading{padding:10px!important;background-color:#e7e7e7;color:#333;font-weight:700;font-size:14px!important}.${def.notice.noticeX} .${def.notice.configuration} .${def.notice.noticeX}-body{padding:10px;color:#333333}.${def.notice.noticeX} .${def.notice.configuration} .${def.notice.noticeX}-body:hover{visibility:visible!important}.${def.notice.noticeX} .${def.notice.configuration} .${def.notice.noticeX}-content{visibility:visible}.${def.notice.noticeX} .${def.notice.noticeX}-heading-title{display:inline-block;vertical-align:middle;overflow:hidden;max-width:90%;text-overflow:ellipsis;white-space:nowrap}.${def.notice.noticeX} .${def.notice.success} .${def.notice.noticeX}-progressbar{margin-top:-1px;width:100%;background-color:#64ce83}.${def.notice.noticeX} .${def.notice.success} .${def.notice.noticeX}-progressbar .${def.notice.noticeX}-bar{width:100%;height:5px;background:#3da95c}.${def.notice.noticeX} .${def.notice.info} .${def.notice.noticeX}-progressbar{margin-top:-1px;width:100%;background-color:#3ea2ff}.${def.notice.noticeX} .${def.notice.info} .${def.notice.noticeX}-progressbar .${def.notice.noticeX}-bar{width:100%;height:5px;background:#067cea;}.${def.notice.noticeX} .${def.notice.warning} .${def.notice.noticeX}-progressbar{margin-top:-1px;width:100%;background-color:#ff7f48}.${def.notice.noticeX} .${def.notice.warning} .${def.notice.noticeX}-progressbar .${def.notice.noticeX}-bar{width:100%;height:5px;background:#f44e06}` +
  1917. `.${def.notice.noticeX} .${def.notice.error} .${def.notice.noticeX}-progressbar{margin-top:-1px;width:100%;background-color:#fd5f4e}.${def.notice.noticeX} .${def.notice.error} .${def.notice.noticeX}-progressbar .${def.notice.noticeX}-bar{width:100%;height:5px;background:#ba2c1d}.${def.notice.noticeX} .${def.notice.configuration} .${def.notice.noticeX}-progressbar{margin-top:-1px;width:100%;background-color:#efefef}.${def.notice.noticeX} .${def.notice.configuration} .${def.notice.noticeX}-progressbar .${def.notice.noticeX}-bar{width:100%;height:5px;background:#ccc}@keyframes ${def.notice.noticeX}-progress{0%{width:100%}to{width:0}}@keyframes ${def.notice.noticeX}-fadeOut{0%{opacity:1}to{opacity:0}}.${def.notice.noticeX}-fadeOut{animation-name:${def.notice.noticeX}-fadeOut}.${def.notice.noticeX}{position:fixed;z-index:2147483645}.${def.notice.noticeX} ::-webkit-scrollbar{width:8px}.${def.notice.noticeX} ::-webkit-scrollbar-button{width:8px;height:8px}.${def.notice.noticeX} ::-webkit-scrollbar-track{border-radius:3px}.${def.notice.noticeX} ::-webkit-scrollbar-thumb{background:#e1e1e1;border-radius:3px}.${def.notice.noticeX} ::-webkit-scrollbar-thumb:hover{background:#aaa}.${def.notice.rName}{padding:2px!important}.${def.notice.noticeX} .${def.notice.rName} dl{margin:0!important;padding:1px!important}.${def.notice.noticeX} .${def.notice.rName} dl dt{margin:2px 0 6px!important;font-weight:900!important;font-size:16px!important}.${def.notice.noticeX} .${def.notice.rName} dl dd{margin:2px 2px 0 0!important;font-size:14px!important;line-height:180%!important;margin-inline-start:10px!important}.${def.notice.noticeX} .${def.notice.rName} .${def.notice.center}{width:100%;text-align:center!important}.${def.notice.noticeX} .${def.notice.rName} dl dd em{padding:0 5px;color:#fff;font-style:italic;font-size:24px!important;font-family:Candara,sans-serif!important}.${def.notice.noticeX} .${def.notice.rName} dl dd span{margin-right:8px;font-weight:700;font-size:15px!important}.${def.notice.noticeX} .${def.notice.rName} dl dd i{font-size:20px!important;font-family:Candara,sans-serif!important}.${def.notice.noticeX} .${def.notice.rName} dl dd .im{padding:0 3px;color:gold;font-weight:900;font-size:16px!important}.${def.notice.noticeX} .${def.notice.warning} .${def.notice.rName} ul{display:inline-block;margin:0 0 0 8px;padding:4px 4px 8px;width:95%;color:rgba(255, 255, 255, 0.8);counter-reset:xxx 0;vertical-align:top;text-align:left}` +
  1918. `.${def.notice.noticeX} .${def.notice.warning} .${def.notice.rName} li{position:relative;margin:0 0 0 2px;padding:0 0 2px 2px;list-style:none;font-style:italic!important;line-height:150%;-webkit-transition:.12s;transition:.12s}.${def.notice.noticeX} .${def.notice.warning} .${def.notice.rName} li::before{display:inline-block;margin-left:-1.5em;width:1.5em;content:counter(xxx,decimal) "、";counter-increment:xxx 1;font-size:14px;font-family:Candara,sans-serif;-webkit-transition:.5s;transition:.5s}.${def.notice.noticeX} .${def.notice.warning} .${def.notice.rName} #${def.notice.stopUpdate}{float:right;margin:0 5px!important;font-size:12px!important;cursor:help}.${def.const.loading}{position:relative;}.${def.const.loading}::after{content:" \u21ba";animation:fade 1.25s infinite;}@keyframes fade{0%{opacity:0.1}50%{opacity:0.5}to{opacity:0}}.${def.notice.readonly}{background:linear-gradient(45deg,#ffe9e9,#ffe9e9 25%,transparent 0,transparent 50%,#ffe9e9 0,#ffe9e9 75%,transparent 0,transparent)!important;background-color:#fff7f7!important;background-size:50px 50px!important;color:#999}#${def.notice.stopUpdate} input[type='checkbox']{box-sizing:content-box;margin:2px 4px 0 0;width:14px;height:14px;border:2px solid #fff;border-radius:50%;background:#ffa077;vertical-align:top;cursor:help;-webkit-appearance:none}#${def.notice.stopUpdate}:hover input,#${def.notice.stopUpdate} input:hover{background:#ba2c1d;}.${def.notice.noticeX} .${def.notice.configuration} .${def.notice.checkbox}{display:none!important}.${def.notice.noticeX} .${def.notice.configuration} .${def.notice.checkbox}+label{position:relative;display:inline-block;-webkit-box-sizing:content-box;box-sizing:content-box;margin:0 0 0 25px;padding:11px 9px;width:58px;height:10px;border-radius:7px;background:#f7836d;box-shadow:inset 0 0 20px rgba(0,0,0,.1),0 0 10px rgba(245, 146, 146, 0.4);word-wrap:normal!important;cursor:pointer}.${def.notice.noticeX} .${def.notice.configuration} .${def.notice.checkbox}+label::before{position:absolute;top:0;left:0;z-index:99;width:24px;height:32px;-webkit-border-radius:7px;border-radius:7px;background:#fff;box-shadow:0 0 1px rgba(0, 0, 0, 0.6);color:#fff;content:" "}.${def.notice.noticeX} .${def.notice.configuration} .${def.notice.checkbox}+label::after{position:absolute;top:2px;left:28px;-webkit-box-sizing:content-box;box-sizing:content-box;padding:5px;-webkit-border-radius:100px;border-radius:100px;color:#fff;content:"OFF";font-weight:700;font-size:14px}` +
  1919. `.${def.notice.noticeX} .${def.notice.configuration} .${def.notice.checkbox}:checked+label{-webkit-box-sizing:content-box;box-sizing:content-box;margin:0 0 0 25px;background:#67a5df!important;box-shadow:inset 0 0 20px rgba(0,0,0,.1),0 0 10px rgba(146, 196, 245, 0.4);cursor:pointer}.${def.notice.noticeX} .${def.notice.configuration} .${def.notice.checkbox}:checked+label::after{top:2px;left:10px;content:"ON"}.${def.notice.noticeX} .${def.notice.configuration} .${def.notice.checkbox}:checked+label::before{position:absolute;left:52px;z-index:99;content:" "}.${def.notice.noticeX} .${def.notice.configuration} button.${def.notice.searchButton}{display:flex;margin:0 0 10px;padding:6px 0;width:162px;height:25px;border:2px solid #eee;border-radius:6px;background:#fff;box-shadow:1px 1px 0 1px #aaa;font-size:14px!important;cursor:pointer;align-content:center;justify-content:center;align-items:center}.${def.notice.noticeX} .${def.notice.configuration} button.${def.notice.searchButton}:hover{box-shadow:1px 1px 3px 0 #888;color:#ff0000}.${def.notice.noticeX} .${def.notice.configuration} span.${def.notice.favicon}{margin:0 6px 0 0;width:32px;height:32px}.${def.notice.noticeX} .${def.notice.configuration} ul.${def.notice.searchList}{margin:5px;padding:2px;list-style:none}.${def.notice.noticeX} .${def.notice.configuration} ul.${def.notice.searchList} li{margin:0;list-style:none;font-style:normal}.${def.notice.noticeX} .${def.notice.configuration} .${def.notice.fieldset}{display:block;margin:2px;padding:4px 6px;width:auto;height:auto;border:2px dashed #dfdfdf;border-radius:10px;background:transparent!important;text-align:left}.${def.notice.noticeX} .${def.notice.configuration} .${def.notice.legend}{display:block;margin:0;padding:0 8px;width:auto;color:#8b0000!important;font-weight:900!important;font-size:14px!important;-webkit-user-select:all;user-select:all}.${def.notice.noticeX} .${def.notice.configuration} .${def.notice.settingList}{margin:0;padding:0;background:transparent!important}.${def.notice.noticeX} .${def.notice.configuration} .${def.notice.settingList} li{float:none;display:flex;margin:3px 0;padding:2px 8px 2px 12px;height:36px;border:none;background:transparent!important;list-style:none;cursor:default;-webkit-user-select:none;user-select:none;align-content:center;justify-content:space-between}` +
  1920. `.${def.notice.noticeX} .${def.notice.configuration} .${def.notice.settingList} li div{font:normal 700 14px/150% Microsoft YaHei UI,system-ui,-apple-system,BlinkMacSystemFont,sans-serif!important}.${def.notice.noticeX} .${def.notice.configuration} .${def.notice.settingList} button{box-sizing:border-box;margin:0 0 0 8px;padding:4px 8px;height:36px;min-width:65px;border:1px solid #ccc;border-radius:8px;background:#fafafa;box-shadow:1px 1px 1px 0 #ccc;color:#5e5e5e;font-weight:700;font-size:14px!important}.${def.notice.noticeX} .${def.notice.configuration} .${def.notice.settingList} .${def.notice.random}_filter_info{font-weight:400!important;}.${def.notice.noticeX} .${def.notice.configuration} .${def.notice.settingList} .${def.notice.random}_filter_info em{color:#dc143c!important;font-style:normal;}.${def.notice.noticeX} .${def.notice.configuration} .${def.notice.settingList} .${def.notice.random}_filter_textarea{padding: 6px 0;margin:0}.${def.notice.noticeX} .${def.notice.configuration} .${def.notice.settingList} .${def.notice.random}_filter{display:block;margin:0;height:100%}.${def.notice.random}_filter_textarea textarea::-webkit-scrollbar{width:8px;height:8px}.${def.notice.random}_filter_textarea textarea::-webkit-scrollbar-thumb{border-radius:4px;background:#cfcfcf}.${def.notice.random}_filter_textarea textarea::-webkit-scrollbar-thumb:hover{background:#aaa}.${def.notice.random}_filter_textarea textarea::placeholder{color:#555;font:normal 500 16px/150% ui-monospace,monospace,system-ui,-apple-system,BlinkMacSystemFont!important;opacity:0.85;white-space:break-spaces}.${def.notice.noticeX} .${def.notice.configuration} .${def.notice.settingList} .${def.notice.random}_filter_content{box-sizing:border-box;margin:0;padding:5px;max-height:423px;width:100%;min-height:280px;outline:0!important;border:1px solid #bbb;border-radius:6px;background:#fff;color:#111;white-space:pre;font:normal 400 14px/150% ui-monospace,monospace,sans-serif!important;resize:vertical;overscroll-behavior:contain;word-break:keep-all!important;cursor:auto}.${def.notice.noticeX} .${def.notice.configuration} .${def.notice.settingList} .${def.notice.random}_filter_content::placeholder{font:normal 400 14px/150% ui-monospace,monospace!important}.${def.notice.noticeX} .${def.notice.configuration} #${def.notice.random}_customColor{margin:0;cursor:pointer}.${def.notice.noticeX} .${def.notice.configuration} .${def.notice.settingList} button:hover{background:#fff;cursor:pointer}` +
  1921. `.${def.notice.noticeX} .${def.notice.configuration} .${def.notice.settingList} .${def.notice.random}__content{display:block;margin:0;height:268px}.${def.notice.noticeX} .${def.notice.configuration} .${def.notice.settingList} .${def.notice.grid}{overflow-x:hidden;overflow-y:auto;box-sizing:border-box;margin:4px 0 3px;padding:8px;width:266px;max-height:237px;overscroll-behavior:contain}.${def.notice.card} h2{margin:0;padding:0;border:0;vertical-align:baseline;font:inherit;font-size:100%;line-height:135%;}#${def.notice.random}_help{position:relative;margin:0;padding:4px 15px!important;border:1px solid transparent;background:#f07f6a;box-shadow:0 0 6px 0 #f5846f;color:#fff;cursor:help}#${def.notice.random}_help:hover{background:#ed6248;box-shadow:0 0 6px 0 #f34525;}#${def.notice.random}_clear{margin:0;color:#666;font-weight:500;cursor:pointer}#${def.notice.random}_clear:hover{color:#ff0000}#${def.notice.random}_clear u{padding:0 2px;text-decoration:none}.${def.notice.linkerror},.${def.notice.linkerror}:hover,.${def.notice.linkerror} *,.${def.notice.linkerror} *:hover{color:#a9a9a9!important;text-decoration-line:line-through!important;text-decoration-color:#ff0000!important;text-decoration-style:wavy!important}@-moz-document url-prefix() {.${def.notice.noticeX} *,.${def.notice.noticeX} *::after,.${def.notice.noticeX} *::before,.${def.notice.noticeX} .${def.notice.configuration} .${def.notice.settingList} .${def.notice.random}_filter_content{scrollbar-color:#bbbb #eee1;scrollbar-width:thin}}.${def.notice.card}{margin:0;padding:0;--background:#fff;--background-chackbox:#0082ff;--background-image:#fff,rgba(0, 107, 175, 0.2);--text-color:#666;--text-headline:#000;--card-shadow:#0082ff;--card-height:48px;--card-witght:240px;--card-radius:12px;--header-height:47px;--blend-mode:overlay;--transition:0.15s;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.${def.notice.card}__input{position:absolute;display:none;margin:0;padding:0;outline:none;border:none;background:none;-webkit-appearance:none}.${def.notice.card}__input:checked ~ .${def.notice.card}__body{--shadow:0 0 0 3px var(--card-shadow);}.${def.notice.card}__input:checked ~ .${def.notice.card}__body .${def.notice.card}__body-cover-chackbox{--chack-bg:var(--background-chackbox);--chack-border:#fff;--chack-scale:1;--chack-opacity:1;}` +
  1922. `.${def.notice.card}__input:checked ~ .${def.notice.card}__body .${def.notice.card}__body-cover-chackbox--svg{--stroke-color:#fff;--stroke-dashoffset:0;}.${def.notice.card}__input:checked ~ .${def.notice.card}__body .${def.notice.card}__body-cover:after{--opacity-bg:0;}.${def.notice.random}_iconText{color:#333}.${def.notice.random}_iconText:hover{color:#dc143c}.${def.notice.card}__input:disabled ~ .${def.notice.card}__body{cursor:not-allowed;opacity:0.5;}.${def.notice.card}__input:disabled ~ .${def.notice.card}__body:active{--scale:1;}.${def.notice.card}__body{position:relative;display:grid;overflow:hidden;width:var(--card-witght);height:var(--card-height);border-radius:var(--card-radius);background:var(--background);box-shadow:var(--shadow,1px 1px 3px 1px #ccc);cursor:pointer;-webkit-transition:box-shadow var(--transition),-webkit-transform var(--transition);transition:box-shadow var(--transition),-webkit-transform var(--transition);transition:transform var(--transition),box-shadow var(--transition);transition:transform var(--transition),box-shadow var(--transition),-webkit-transform var(--transition);-webkit-transform:scale(var(--scale,1)) translateZ(0);transform:scale(var(--scale,1)) translateZ(0);grid-auto-rows:calc(var(--card-height) - var(--header-height)) auto}.${def.notice.card}__body:active{--scale:0.96;}.${def.notice.card}__body-cover-image{position:absolute;top:8px;left:10px;z-index:100;width:32px;height:32px}.${def.notice.card}__body-cover-image span.${def.notice.favicons}{display:block;width:32px;height:32px}.${def.notice.card}__body-cover-chackbox{position:absolute;top:10px;right:10px;z-index:1;width:28px;height:28px;border:2px solid var(--chack-border,#fff);border-radius:50%;background:var(--chack-bg,var(--background-chackbox));opacity:var(--chack-opacity,0);transition:transform var(--transition),opacity calc(var(--transition)*1.2) linear,-webkit-transform var(--transition) ease;-webkit-transform:scale(var(--chack-scale,0));transform:scale(var(--chack-scale,0))}.${def.notice.card}__body-cover-chackbox--svg{display:inline-block;visibility:visible!important;margin:8px 0 0 7px;width:13px;height:11px;vertical-align:top;-webkit-transition:stroke-dashoffset .4s ease var(--transition);transition:stroke-dashoffset .4s ease var(--transition);fill:none;stroke:var(--stroke-color,#fff);stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:16px;stroke-dashoffset:var(--stroke-dashoffset,16px)}` +
  1923. `.${def.notice.card}__body-header{padding:4px 10px 6px 50px;height:var(--header-height);background:var(--background)}.${def.notice.card}__body-header-title{margin-bottom:0!important;color:var(--text-headline);font-weight:700!important;font-size:15px!important}.${def.notice.card}__body-header-subtitle{color:var(--text-color);font-weight:500;font-size:13px!important}.${def.notice.noticeX} .${def.notice.configuration} .${def.notice.settingList} .${def.notice.grid}{display:grid;grid-template-columns:repeat(1, 1fr);grid-gap:10px;}.${def.notice.gberror}{display:block;margin:0 0 4px -6px;padding:6px;width:max-content;border:1px dashed #ffb78c;border-radius:4px;color:#ffb78c}`
  1924. );
  1925. def.var.iconbg = iconBase64Data ? `url('${iconBase64Data}')` : `url('${def.url.backupIcon}'),url('${yandexIconsAPIUrl}')`;
  1926. def.var.button = `${currentSite.siteTypeID === newSiteType.GOOGLE ? "<span jsname='s1VaRe' class='ACRAdd M2vV3'></span>" : ""}
  1927. <span id="${def.const.leftButton}" sn="${selectedSite[0].siteTypeID}">
  1928. <input type="button" title="${selectedSite[0].siteNickName}" value="${selectedSite[0].siteButtonName}"/>
  1929. </span>
  1930. <span id="${def.const.rightButton}" sn="${selectedSite[1].siteTypeID}">
  1931. <input type="button" title="${selectedSite[1].siteNickName}" value="${selectedSite[1].siteButtonName}"/>
  1932. </span>`;
  1933. def.var.hlstyle = listCurrentSite.keywords ? `${listCurrentSite.keywords}{background-color:${bgcolor}!important;color:${fgcolor}!important;font-weight:600}` : ``;
  1934. def.var.iconstyle = `.${def.notice.noticeX} .${def.notice.configuration} span.${def.notice.favicon},.${def.notice.card}__body-cover-image span.${def.notice.favicons}{background-color:transparent;background-image:${def.var.iconbg};background-repeat:no-repeat;}`;
  1935.  
  1936. function getQueryString() {
  1937. if (currentSite.siteTypeID === newSiteType.YOU) {
  1938. const textWord = qS(`textarea#search-input-textarea[name='query']`)?.value.trim();
  1939. if (textWord) return encodeURIComponent(textWord);
  1940. const keyNodes = qA(`[data-testid^="youchat-question-turn"] span[class^='sc-']`);
  1941. if (keyNodes.length) return keyNodes[keyNodes.length - 1].textContent;
  1942. }
  1943. const { inputArray, searchKeys } = searchProperties;
  1944. const inputValue = qA(inputArray.join()).Find(item => item.value)?.value;
  1945. if (inputValue) {
  1946. DEBUG("QueryString[INPUT]:", { value: inputValue });
  1947. return encodeURIComponent(inputValue);
  1948. }
  1949. for (const key of searchKeys) {
  1950. const queryString = getUrlParam(key);
  1951. if (!queryString) continue;
  1952. const decodedValue = queryString.replace(/\+/g, " ");
  1953. DEBUG("QueryString[URL]:", { queryKey: key, value: decodedValue });
  1954. return encodeURIComponent(decodedValue);
  1955. }
  1956. return "";
  1957. }
  1958.  
  1959. function checkIndexPage() {
  1960. return [newSiteType.DUCKDUCKGO, newSiteType.QWANT].includes(currentSite.siteTypeID) ? !getUrlParam("q") : location.pathname === "/";
  1961. }
  1962.  
  1963. function getSecurityPolicy() {
  1964. const currentSearchType = getUrlParam(currentSite.splitTypeName);
  1965. return (
  1966. (currentSite.siteTypeID === newSiteType.GOOGLE && (/^fin|26|28$/.test(currentSearchType) || getUrlParam("csui") === "1")) ||
  1967. (currentSite.siteTypeID === newSiteType.BING && /^maps$/.test(currentSearchType)) ||
  1968. (currentSite.siteTypeID === newSiteType.SOGOU && /^(fanyi|hanyu|as)/.test(CUR_HOST_NAME)) ||
  1969. (currentSite.siteTypeID === newSiteType.DUCKDUCKGO && /^maps$/.test(getUrlParam("iaxm"))) ||
  1970. (currentSite.siteTypeID === newSiteType.YANDEX && location.pathname.includes("/direct")) ||
  1971. (currentSite.siteTypeID === newSiteType.YAHOO && CUR_HOST_NAME.search(/news|video/) !== -1) ||
  1972. (currentSite.siteTypeID === newSiteType.SEARXNG && /^map$/.test(currentSearchType))
  1973. );
  1974. }
  1975.  
  1976. function findCurrentSite() {
  1977. for (const regex in engineMap) {
  1978. if (!hasOwnProperty.call(engineMap, regex) || !new RegExp(regex).test(CUR_HOST_NAME)) continue;
  1979. const { siteType, site } = engineMap[regex];
  1980. const currentSite = selectedEngine.includes(siteType) ? site : listSite.other;
  1981. return { currentSite, listCurrentSite: site };
  1982. }
  1983. return {};
  1984. }
  1985.  
  1986. function updateSiteInformation() {
  1987. let [currentSiteName, allSiteURIs] = ["", ""];
  1988. for (let site in listSite) {
  1989. if (!hasOwnProperty.call(listSite, site)) continue;
  1990. if (listSite[site].siteTypeID !== newSiteType.OTHERS) allSiteURIs += listSite[site].siteHostName + ";";
  1991. if (listSite[site].siteTypeID === listCurrentSite.siteTypeID) currentSiteName = site;
  1992. if (listSite[site].siteTypeID !== currentSite.siteTypeID && selectedEngine.includes(Number(listSite[site].siteTypeID))) {
  1993. selectedSite.length < 2 && selectedSite.push(listSite[site]);
  1994. }
  1995. }
  1996. return { currentSiteName, allSiteURIs };
  1997. }
  1998.  
  1999. async function updateToRequestIcon(isReload = true) {
  2000. try {
  2001. const iconDataURL = await requestRemoteIcon(yandexIconsAPIUrl);
  2002. if (iconDataURL) cache.set(REMOTEICONS, iconDataURL, 2592e6) ?? DEBUG("%cRemote icon data parsed successfully.", "color:#006400");
  2003. else DEBUG("%cRemote icon data parsing failed.", "color:#ff0000");
  2004. } catch (e) {
  2005. ERROR("updateToRequestIcon: Can't fetch the iconData.", e.message);
  2006. } finally {
  2007. isReload && reload();
  2008. }
  2009. }
  2010.  
  2011. function openUpdateWindow(url) {
  2012. if (IS_REAL_GECKO || IS_REAL_WEBKIT || (IS_REAL_BLINK && GMscriptHandler === "Tampermonkey" && parseFloat(GMversion) >= 5.2)) {
  2013. def.var.updateWindow = GMopenInTab(IS_GREASEMONKEY ? url.replace(/\?\w+/g, "") : url, false);
  2014. } else global.location.href = url;
  2015. }
  2016.  
  2017. function showUpdateNotify() {
  2018. const title = IS_CHN ? "升级提示" : "Update Tips";
  2019. const loadingTip = IS_REAL_GECKO
  2020. ? `${IS_CHN ? "已经在新窗口打开脚本升级页面,请注意切换!" : "The upgrade page is opened in new window!"}`
  2021. : `${IS_CHN ? "正在申请脚本更新安装页面,请稍后……" : "Installation page is requested, please wait..."}`;
  2022. const okTip = IS_CHN ? "<dd><b>若您已更新完成</b>,请点此刷新页面,以使新版脚本生效!</dd>" : "<dd><b>If updated</b>, click here to make the script effective!</dd>";
  2023. const text = createNoticeHTML(`<dd id="${def.notice.random}_loading" style="color:#ffff00;font-weight:600">${loadingTip}</dd>${okTip}`);
  2024. GMnotification({ title, text, type: def.notice.info, closeWith: ["click"], timeout: false, position: "topRight", callbacks: { onClose: [updateToRequestIcon] } });
  2025. if (def.var.updateWindow) {
  2026. sleep(6e3, { useCachedSetTimeout: true }).then(() => {
  2027. def.var.updateWindow.onclose = () => delete def.var.updateWindow;
  2028. def.var.updateWindow.close?.();
  2029. });
  2030. }
  2031. return qS(`#${def.notice.random}_loading`);
  2032. }
  2033.  
  2034. function removeLoadingElement(node) {
  2035. sleep(4e3, { useCachedSetTimeout: true }).then(() => safeRemoveNode(node));
  2036. }
  2037.  
  2038. function preInstall(url) {
  2039. sleep(5e2)(url.replace(".meta.", ".user."))
  2040. .then(u => openUpdateWindow(u))
  2041. .then(() => showUpdateNotify())
  2042. .then(r => removeLoadingElement(r))
  2043. .catch(e => ERROR("preInstall:", e.message));
  2044. }
  2045.  
  2046. function extractVersion(res) {
  2047. return res.match(/\/\/\s+@version\s+(\S+)/)?.[1]?.trim();
  2048. }
  2049.  
  2050. function extractNotes(res) {
  2051. return res.match(/\/\/\s+@note\s+(.+)/g)?.map(item => escapeHTML(item.replace(/\/\/\s+@note\s+/, "")).trim());
  2052. }
  2053.  
  2054. function generateUpdateList(notes) {
  2055. if (!notes) return `<ol>当前更新源没有更新详情,请访问 <a target="_blank" href="${def.url.homepage}">Github</a> 查看。</ol><ol>&nbsp;</ol>`;
  2056. return notes.reduce((updateInfoList, note) => {
  2057. try {
  2058. const parsedNote = JSON.parse(note);
  2059. updateInfoList += `<li>${IS_CHN ? parsedNote.CN : parsedNote.EN}</li>`;
  2060. } catch (e) {
  2061. updateInfoList += `<li>${note}</li>`;
  2062. }
  2063. return updateInfoList;
  2064. }, "");
  2065. }
  2066.  
  2067. function generateUpdateHTML(version, updateText) {
  2068. const escapedVersion = escapeHTML(version);
  2069. return IS_CHN
  2070. ? `<dd><span>发现新版本</span><i>V${escapedVersion}</i>,点击可自动更新。</dd><dd><ul>${updateText}</ul></dd><dd id="${def.notice.stopUpdate}"><input type="checkbox">一周内不再提醒</dd>`
  2071. : `<dd><span>New Version</span><i>V${escapedVersion}</i>, Click to update.</dd><dd><ul>${updateText}</ul></dd><dd id="${def.notice.stopUpdate}"><input type="checkbox">Don't remind me for <b>7</b> days</dd>`;
  2072. }
  2073.  
  2074. function showNewUpdateNotify(version, newUpdateHTML, url) {
  2075. const [title, text, callbacks] = [IS_CHN ? "发现新更新" : "Found new update", createNoticeHTML(newUpdateHTML), { onClick: [() => preInstall(url)] }];
  2076. const updateInterface = GMnotification({ title, text, type: def.notice.warning, closeWith: ["click"], timeout: 8e3, callbacks });
  2077. qS(`#${def.notice.stopUpdate}`)?.addEventListener("click", event => {
  2078. event.stopPropagation();
  2079. NoticeX.close(updateInterface);
  2080. cache.set(AUTOCHECK, def.var.curVersion);
  2081. });
  2082. const props = ["font-weight:bold;color:#dc143c", "color:0", "color:#dc143c", "color:0"];
  2083. __console("shown_new_update", `%c[GB-Update]%c\r\nWe found a new version: %c${version}%c, which you can update now!`, ...props);
  2084. }
  2085.  
  2086. function showSuccessUpdateNotify() {
  2087. const successHTML = IS_CHN
  2088. ? `<dd style="margin: 10px 0"><span>恭喜!</span>当前版本 <i>${def.var.curVersion}</i> 已为最新!</dd>`
  2089. : `<dd style="margin: 10px 0"><span>Congratulations!</span><br/>The version <i>${def.var.curVersion}</i> is up-to-date!</dd>`;
  2090. const title = IS_CHN ? "更新成功" : "Update Success";
  2091. GMnotification({ title, text: createNoticeHTML(successHTML), timeout: 3e3, closeWith: ["click"] });
  2092. cache.set(AUTOCHECK, def.var.curVersion);
  2093. GMsetValue(VERSION, encrypt(def.var.curVersion));
  2094. const props = ["font-weight:700;color:#008b8b", "color:0", "color:#dc143c", "color:0"];
  2095. __console("shown_update_info", `%c[GB-Update]%c\r\nCurretVersion: %c${def.var.curVersion}%c is up-to-date!`, ...props);
  2096. }
  2097.  
  2098. function showUpdateError() {
  2099. const props = ["font-weight:bold;color:#dc143c", "color:#800000"];
  2100. __console("error", "%c[GB-UpdateError]%c\r\nRefused to connect to 'the UpdateList URLs', Please check your Network or local DNS!", ...props);
  2101. }
  2102.  
  2103. void (async function (getUpdateInformation, parseUpdateInformatio) {
  2104. const addAction = {
  2105. closeConfig: async () => {
  2106. const configureSelector = `.${def.notice.noticeX} .${def.notice.configuration}`;
  2107. return await NoticeX.close(qS(configureSelector));
  2108. },
  2109. listSearchEngine: currentSite => {
  2110. let returnHtml = "";
  2111. for (let site in listSite) {
  2112. if (!hasOwnProperty.call(listSite, site) || listSite[site].siteTypeID === 0 || listSite[site].siteTypeID === currentSite.siteTypeID) continue;
  2113. const iconStyle = `background-position:0 ${(1 - listSite[site].siteTypeID) * 32}px;background-attachment:local;background-size:32px auto;transform:scale(0.75);`;
  2114. const buttonTitle = selectedEngine.includes(listSite[site].siteTypeID) ? `title="${IS_CHN ? "您常用的搜索引擎" : "Commonly used search engine"}"` : ``;
  2115. returnHtml += `<li>
  2116. <button class="${def.notice.searchButton}" id="${listSite[site].siteTypeID}" ${buttonTitle}>
  2117. <span class="${def.notice.favicon} ${def.notice.random}_icon" style="${iconStyle}"></span>
  2118. <span class="${def.notice.random}_iconText">
  2119. ${listSite[site].siteNickName}<sup>${selectedEngine.includes(listSite[site].siteTypeID) ? "\u2726" : "\u0020"}</sup>
  2120. </span>
  2121. </button>
  2122. </li>`;
  2123. }
  2124. return String(`<ul class="${def.notice.searchList}">${returnHtml}</ul>`);
  2125. },
  2126. listSelectSearchEngine: () => {
  2127. let returnHtml = "";
  2128. for (let site in listSite) {
  2129. if (!hasOwnProperty.call(listSite, site) || listSite[site].siteTypeID === 0) continue;
  2130. const iconStyle = `background-position:0 ${(1 - listSite[site].siteTypeID) * 32}px;background-attachment:local;background-size:32px auto;`;
  2131. const inputStatus = selectedEngine.includes(listSite[site].siteTypeID) ? "checked" : "disabled";
  2132. returnHtml += `<label class="${def.notice.card}">
  2133. <input class="${def.notice.card}__input" type="checkbox" name="${def.notice.card}_lists" data-sn="${listSite[site].siteTypeID}" ${inputStatus}/>
  2134. <div class="${def.notice.card}__body">
  2135. <header class="${def.notice.card}__body-header">
  2136. <span class="${def.notice.card}__body-cover-chackbox">
  2137. <svg class="${def.notice.card}__body-cover-chackbox--svg" viewBox="0 0 12 10"><polyline points="1.5 6 4.5 9 10.5 1"></polyline></svg>
  2138. </span>
  2139. <span class="${def.notice.card}__body-cover-image">
  2140. <span class="${def.notice.favicons} ${def.notice.random}_icon" style="${iconStyle}"></span>
  2141. </span>
  2142. <h2 class="${def.notice.card}__body-header-title" fr-fix-stroke="true">${listSite[site].siteNickName}</h2>
  2143. <p class="${def.notice.card}__body-header-subtitle" style="margin:0;padding:0">${listSite[site].siteHostName}</p>
  2144. </header>
  2145. </div>
  2146. </label>`;
  2147. }
  2148. return returnHtml;
  2149. },
  2150. setConfigure: () => {
  2151. sleep(5e2)(addAction.closeConfig()).then(isClosed => {
  2152. if (!isClosed) return;
  2153. const configText = `<fieldset class="${def.notice.fieldset}">
  2154. <legend class="${def.notice.legend}" title="Version ${def.var.curVersion}">
  2155. ${IS_CHN ? "高级功能参数设置" : "Advanced Feature Settings"}
  2156. </legend>
  2157. <ur class="${def.notice.settingList}">
  2158. <li class="${def.notice.random}__content">
  2159. <div><span>${IS_CHN ? "请选择三个最常用的搜索引擎:" : "Choose three search engines:"}</span>
  2160. <span id="${def.notice.random}_clear">[<u>${IS_CHN ? "清除" : "Clear"}</u>]</span></div>
  2161. <div class="${def.notice.grid}">
  2162. ${addAction.listSelectSearchEngine()}
  2163. </div>
  2164. </li>
  2165. <li>
  2166. <div>${IS_CHN ? "键盘快捷键功能开关" : "Keyboard Shortcut"}</div>
  2167. <div style="margin:-2px 2px 0 10px">
  2168. <input type="checkbox" id="${def.notice.hk}" class="${def.notice.checkbox}" ${isHotkey ? "checked" : ""} />
  2169. <label for="${def.notice.hk}"></label>
  2170. </div>
  2171. </li>
  2172. <li>
  2173. <div>${IS_CHN ? "Google 国际站跳转" : "Open Google NCR"}</div>
  2174. <div style="margin:-2px 2px 0 10px">
  2175. <input type="checkbox" id="${def.notice.gj}" class="${def.notice.checkbox}" ${googleJump ? "checked" : ""} />
  2176. <label for="${def.notice.gj}"></label>
  2177. </div>
  2178. </li>
  2179. <li>
  2180. <div>${IS_CHN ? "在当前浏览器窗口跳转" : "Open in Self-window"}</div>
  2181. <div style="margin:-2px 2px 0 10px">
  2182. <input type="checkbox" id="${def.notice.lw}" class="${def.notice.checkbox}" ${localWindow ? "checked" : ""} />
  2183. <label for="${def.notice.lw}"></label>
  2184. </div>
  2185. </li>
  2186. <li>
  2187. <div style="display:flex">${IS_CHN ? "搜索关键词高亮增强" : "Keyword Enhance"}
  2188. <span title="${IS_CHN ? "自定义关键词颜色" : "Custom Keyword Color"}" id="${def.notice.random}_customColor"\
  2189. style="display:${keywordHighlight ? `inline-block` : `none`}">\ud83c\udfa8</span>
  2190. </div>
  2191. <div style="margin:-2px 2px 0 10px">
  2192. <input type="checkbox" id="${def.notice.kh}" class="${def.notice.checkbox}" ${keywordHighlight ? "checked" : ""} />
  2193. <label for="${def.notice.kh}"></label>
  2194. </div>
  2195. </li>
  2196. <li>
  2197. <div>${IS_CHN ? "去除链接重定向跳转" : "Remove Redirection"}</div>
  2198. <div style="margin:-2px 2px 0 10px">
  2199. <input type="checkbox" id="${def.notice.ar}" class="${def.notice.checkbox}" ${antiLinkRedirect ? "checked" : ""} />
  2200. <label for="${def.notice.ar}"></label>
  2201. </div>
  2202. </li>
  2203. <li>
  2204. <div title="${IS_CHN ? "实验性功能" : "Beta Version"}"><span>${IS_CHN ? "去除搜索结果广告" : "Remove Ads"}</span>
  2205. <sup style="padding:0;font-style:italic;color:#dc143c;font-size:10px">Beta!</sup></div>
  2206. <div style="margin:-2px 2px 0 10px">
  2207. <input type="checkbox" id="${def.notice.aa}" class="${def.notice.checkbox}" ${antiAds ? "checked" : ""} />
  2208. <label for="${def.notice.aa}"></label>
  2209. </div>
  2210. </li>
  2211. <li>
  2212. <div title="${IS_CHN ? "关闭更新检测或由扩展自动更新时,您需要到脚本主页查看更新内容。" : "We recommend that you turn on update detection."}">
  2213. ${IS_CHN ? "更新检测(默认:开)" : "Auto Update Detect"}</div>
  2214. <div style="margin:-2px 2px 0 10px">
  2215. <input type="checkbox" id="${def.notice.au}" class="${def.notice.checkbox}" ${isAutoUpdate ? "checked" : ""} />
  2216. <label for="${def.notice.au}"></label>
  2217. </div>
  2218. </li>
  2219. <li style="display:flex;justify-content:space-between;">
  2220. <button id="${def.notice.random}_help" title="${IS_CHN ? "单击查看脚本主页" : "View Homepage"}">
  2221. ${IS_CHN ? "脚本主页" : "Guide!"}
  2222. </button>
  2223. <div style="display:flex">
  2224. <button id="${def.notice.random}_cancel">${IS_CHN ? "取消" : "Cancel"}</button>
  2225. <button id="${def.notice.random}_submit">${IS_CHN ? "保存" : "Save"}</button>
  2226. </div>
  2227. </li>
  2228. </ul>
  2229. </fieldset>`;
  2230. const [title, text, type, scroll] = [`${def.var.scriptName} v${def.var.curVersion}`, configText, def.notice.configuration, { maxHeight: 680, showOnHover: true }];
  2231. const configInterface = GMnotification({ title, text, type, width: 326, closeWith: ["button"], scroll, progressBar: false, timeout: false, position: "topRight" });
  2232. qA(`input[name='${def.notice.card}_lists']`).forEach(node => void addCardClickEvent(node));
  2233. qS(`#${def.notice.random}_clear`)?.addEventListener("click", cleanSelectedCard);
  2234. qS(`#${def.notice.kh}`)?.addEventListener("click", showCustomColor);
  2235. qS(`#${def.notice.random}_customColor`)?.addEventListener("click", submitKeywordColor);
  2236. qS(`#${def.notice.random}_help`)?.addEventListener("click", openHomePage);
  2237. qS(`#${def.notice.random}_cancel`)?.addEventListener("click", () => void NoticeX.close(configInterface));
  2238. qS(`#${def.notice.random}_submit`)?.addEventListener("click", saveConfigureData);
  2239. });
  2240. },
  2241. listEngine: () => {
  2242. sleep(5e2)(addAction.closeConfig()).then(isClosed => {
  2243. if (!isClosed) return;
  2244. const [title, text] = [`\ud83d\udc4b ${IS_CHN ? "你想去哪里吖?" : "Where to visit?"}`, addAction.listSearchEngine(listCurrentSite)];
  2245. const [type, scroll] = [def.notice.configuration, { maxHeight: 565, showOnHover: true }];
  2246. GMnotification({ title, text, type, width: 200, closeWith: ["button"], scroll, timeout: 12e3, position: "topRight" });
  2247. qA(`.${def.notice.noticeX} .${def.notice.configuration} .${def.notice.searchButton}`).forEach(item => setupClickEventOnCard(item));
  2248. });
  2249. },
  2250. filterResult: () => {
  2251. sleep(5e2)(addAction.closeConfig()).then(async isClosed => {
  2252. if (!isClosed) return;
  2253. const _filter_Data_ = await getResultFilterData();
  2254. const { trigger: antiResultsFilter, filter: resultFilters } = _filter_Data_;
  2255. const infoText = IS_CHN
  2256. ? `设置拦截关键词以数组为标准格式,每行一组过滤关键词(注意:非正则语句须转义字符,且最末行尾无逗号),支持高级正则表达式语法,不区分大小写。<em>详细设置规则请查看『设置指引』。</em>`
  2257. : `Filter keyword settings use Array as standard format, one filter keyword per line. Supports regular expressions and is not case-sensitive. <em>See "Guide" for detailed setting rules!</em>`;
  2258. const placeholder = IS_CHN
  2259. ? `设置如下数组格式:\n[\n "任意关键词",\n "任意网址但要注意转义",\n "\\\\/\\\\/test\\\\.cn\\\\/id-\\\\d+",\n "\\\\(\\\\?\\\\=非正则须转义\\\\)",`
  2260. : `Set Array as follows: \n[\n "Any keywords",\n "Any URLs but must be escaped",\n "v\\\\.test\\\\.com\\\\/test\\\\.html",\n \\\\(\\\\?\\\\:Non-regex escaped\\\\)",`;
  2261. const placeholderText = placeholder + `\n "www\\\\.example\\\\.[a-z]{2,3}",\n "(a|b)\\\\.test\\\\.com",\n "keyword1|keyword[2345]",\n "^(?!.*B).*A.*$"\n]`;
  2262. const resultFiltersJSON = resultFilters.length ? JSON.stringify(resultFilters, null, " ") : "";
  2263. const filterHTML = `<fieldset class="${def.notice.fieldset}">
  2264. <legend class="${def.notice.legend}" title="Version ${def.var.curVersion}">
  2265. ${IS_CHN ? "搜索结果拦截关键词设置" : "Search Filter Settings"}
  2266. </legend>
  2267. <ur class="${def.notice.settingList}">
  2268. <li>
  2269. <div>${IS_CHN ? "关键词拦截开关" : "Filter Switches"}</div>
  2270. <div style="margin:-2px 2px 0 10px">
  2271. <input type="checkbox" id="${def.notice.rf}" class="${def.notice.checkbox}" ${antiResultsFilter ? "checked" : ""} />
  2272. <label for="${def.notice.rf}"></label>
  2273. </div>
  2274. </li>
  2275. <li class="${def.notice.random}_filter">
  2276. <div class="${def.notice.random}_filter_info">
  2277. ${infoText}
  2278. </div>
  2279. <div class="${def.notice.random}_filter_textarea">
  2280. <textarea class="${def.notice.random}_filter_content" placeholder='${placeholderText}'>${resultFiltersJSON}</textarea>
  2281. </div>
  2282. <div style="text-align:center;padding:0 0 6px 0">
  2283. ${IS_CHN ? "(程序仅检测搜索结果列表内的可见文字)" : "(ONLY DETECT VISIBLE TEXT IN RESULT)"}
  2284. </div>
  2285. </li>
  2286. <li style="display:flex;justify-content:space-between;">
  2287. <button id="${def.notice.random}_help" title="${IS_CHN ? "查看详细设置规则请单击设置指引!" : "See document for detailed setting rules! (Chinese)"}">
  2288. ${IS_CHN ? "设置指引" : "Guide!"}
  2289. </button>
  2290. <div style="display:flex">
  2291. <button id="${def.notice.random}_cancel">${IS_CHN ? "取消" : "Cancel"}</button>
  2292. <button id="${def.notice.random}_submit">${IS_CHN ? "保存" : "Save"}</button>
  2293. </div>
  2294. </li>
  2295. </ul>
  2296. </fieldset>`;
  2297. const [title, text, type, scroll] = [`${def.var.scriptName} v${def.var.curVersion}`, filterHTML, def.notice.configuration, { maxHeight: 680, showOnHover: true }];
  2298. const filterInterface = GMnotification({ title, text, type, width: 380, closeWith: ["button"], scroll, progressBar: false, timeout: false, position: "topRight" });
  2299. const textarea = qS(`.${def.notice.random}_filter_textarea .${def.notice.random}_filter_content`);
  2300. const tigger = qS(`#${def.notice.rf}`);
  2301. if (tigger && !tigger.checked) {
  2302. textarea.classList.add(def.notice.readonly);
  2303. textarea.setAttribute("readonly", true);
  2304. }
  2305. tigger?.addEventListener("change", changeEventOnTigger);
  2306. textarea?.addEventListener("compositionstart", () => (def.var.composing = true));
  2307. textarea?.addEventListener("compositionend", () => delete def.var.composing);
  2308. textarea?.addEventListener("input", addInputEventOnTextarea);
  2309. qS(`#${def.notice.random}_help`)?.addEventListener("click", () => void GMopenInTab(`${def.url.feedback}/288`, false));
  2310. qS(`#${def.notice.random}_cancel`)?.addEventListener("click", () => void NoticeX.close(filterInterface));
  2311. qS(`#${def.notice.random}_submit`)?.addEventListener("click", saveFilterResultData);
  2312. });
  2313. },
  2314. };
  2315.  
  2316. function changeEventOnTigger() {
  2317. const textarea = qS(`.${def.notice.random}_filter_textarea .${def.notice.random}_filter_content`);
  2318. textarea?.classList.toggle(def.notice.readonly, !this.checked);
  2319. textarea?.toggleAttribute("readonly", !this.checked);
  2320. }
  2321.  
  2322. async function saveFilterResultData() {
  2323. try {
  2324. const filterString = qS(`.${def.notice.random}_filter_textarea .${def.notice.random}_filter_content`).value.trim();
  2325. const filterTrigger = qS(`#${def.notice.rf}`).checked;
  2326. const parsedFilterString = filterString ? JSON.parse(filterString) : [];
  2327. if (!Array.isArray(parsedFilterString) || asArray(parsedFilterString).Some(item => typeof item !== "string")) throw new Error("Format Error");
  2328. const resultFilterData = { filter: [...new Set(parsedFilterString.filter(Boolean))], trigger: filterTrigger };
  2329. GMsetValue(RESULTFILTER, encrypt(JSON.stringify(resultFilterData)));
  2330. const successTitle = IS_CHN ? "保存成功!" : "Success!";
  2331. const successText = IS_CHN ? "<dd>设置参数已成功保存,页面稍后自动刷新!</dd>" : "<dd>The data is saved successfully, Page will refresh!</dd>";
  2332. if (await addAction.closeConfig()) GMnotification({ title: successTitle, text: createNoticeHTML(successText), callbacks: { onClose: [reload] } });
  2333. } catch (error) {
  2334. const errorMessage = IS_CHN ? "设置数据格式有误,请修正后重新提交。" : "The setting data format is incorrect!";
  2335. const errorText = `<dd><e style="font-size:24px;vertical-align:bottom">\ud83d\ude31\u0020</e>${errorMessage}</dd>`;
  2336. GMnotification({ text: createNoticeHTML(errorText), type: def.notice.error, closeWith: ["click"] });
  2337. }
  2338. }
  2339.  
  2340. async function addInputEventOnTextarea(event) {
  2341. const _this = this ?? event.target;
  2342. try {
  2343. if (def.var.composing) return;
  2344. const value = _this.value.trim();
  2345. if (value.length === 0) return _this.setAttribute("style", "border: 1px solid #999");
  2346. const previousCursorPosition = _this.selectionStart;
  2347. const formattedValue = JSON.stringify(JSON.parse(value), null, 2);
  2348. const newCursorPosition = previousCursorPosition + formattedValue.length - _this.value.length;
  2349. const currentScrollTop = _this.scrollTop;
  2350. _this.value = formattedValue;
  2351. _this.setAttribute("style", "border: 1px solid #999");
  2352. await sleep(10, { instant: true });
  2353. _this.scrollTop = currentScrollTop;
  2354. _this.setSelectionRange(newCursorPosition, newCursorPosition);
  2355. } catch (e) {
  2356. _this.setAttribute("style", "border: 2px solid #dc143c");
  2357. }
  2358. }
  2359.  
  2360. function setupClickEventOnCard(item) {
  2361. item?.addEventListener("click", () => {
  2362. const [itemID, queryString] = [Number(item.id), getQueryString()];
  2363. const splitTypeName = getUrlParam(listCurrentSite.splitTypeName).trim();
  2364. const isImageType = listCurrentSite.imageType.includes(splitTypeName);
  2365. for (const [type, typeID] of Object.entries(newSiteType)) {
  2366. if (typeID === itemID) {
  2367. const siteType = type.toLowerCase();
  2368. const url = isImageType ? listSite[siteType].imageURL : listSite[siteType].webURL;
  2369. const fullURL = decodeURI(url + queryString);
  2370. if (localWindow) top.location.href = fullURL;
  2371. else GMopenInTab(fullURL, false);
  2372. break;
  2373. }
  2374. }
  2375. });
  2376. }
  2377.  
  2378. function openHomePage() {
  2379. const hash = IS_CHN ? "#%E4%BC%98%E9%9B%85%E7%9A%84%E6%90%9C%E7%B4%A2%E5%BC%95%E6%93%8E%E5%8A%A9%E6%89%8B" : "index_en.html#search-engine-assistant";
  2380. GMopenInTab(`${def.url.homepage}${hash}-google--baidu-switcheruserjs`, false);
  2381. }
  2382.  
  2383. function addCardClickEvent(node) {
  2384. node.addEventListener("click", () => {
  2385. const input_checked = qA(`input[name='${def.notice.card}_lists']:checked:enabled`).length;
  2386. if (input_checked < 3) {
  2387. qA(`input[name='${def.notice.card}_lists']:disabled`).forEach(item => (item.disabled = false));
  2388. qS(`#${def.notice.random}_clear`).style.display = input_checked === 0 ? "none" : "inline";
  2389. } else {
  2390. qA(`input[name='${def.notice.card}_lists']:not(:checked)`).forEach(item => (item.disabled = true));
  2391. }
  2392. });
  2393. }
  2394.  
  2395. function submitKeywordColor() {
  2396. let inputFgColor, inputBgColor;
  2397. const colorReg =
  2398. /^#[0-9a-f]{3}$|^#[0-9a-f]{6}$|^#[0-9a-f]{8}$|^rgba\(([0-9]|([1-9][0-9])|(1[0-9][0-9])|(2([0-4][0-9]|5[0-5]))),\s*([0-9]|([1-9][0-9])|(1[0-9][0-9])|(2([0-4][0-9]|5[0-5]))),\s*([0-9]|([1-9][0-9])|(1[0-9][0-9])|(2([0-4][0-9]|5[0-5]))),\s*((?!1.[1-9])[0-1]?(\.[0-9]{1,3})?)\)$|^rgb\(((([0-9]|([1-9][0-9])|(1[0-9][0-9])|(2([0-4][0-9]|5[0-5]))),\s*([0-9]|([1-9][0-9])|(1[0-9][0-9])|(2([0-4][0-9]|5[0-5]))),\s*([0-9]|([1-9][0-9])|(1[0-9][0-9])|(2([0-4][0-9]|5[0-5]))))|(([0-9]|([1-9][0-9])|(1[0-9][0-9])|(2([0-4][0-9]|5[0-5])))\s+([0-9]|([1-9][0-9])|(1[0-9][0-9])|(2([0-4][0-9]|5[0-5])))\s+([0-9]|([1-9][0-9])|(1[0-9][0-9])|(2([0-4][0-9]|5[0-5])))(\s+\/\s+((\d+%)|1|(0\.\d+)))?))\)$|^transparent$|^currentcolor$/i;
  2399. const foregroundColorText = IS_CHN
  2400. ? `请输入关键词前景色(字体颜色),默认为“#f73131cd”,支持HEX, HEXA, RGB, RGBA, currentcolor的颜色格式。`
  2401. : `𝐏𝐥𝐞𝐚𝐬𝐞 𝐞𝐧𝐭𝐞𝐫 𝐭𝐡𝐞 𝐤𝐞𝐲𝐰𝐨𝐫𝐝 𝐟𝐨𝐫𝐞𝐠𝐫𝐨𝐮𝐧𝐝-𝐜𝐨𝐥𝐨𝐫 (𝐟𝐨𝐧𝐭 𝐜𝐨𝐥𝐨𝐫):\r\nThe default is "#f73131cd" and supports the color formats of HEX, HEXA, RGB, RGBA and currentcolor.`;
  2402. const backgroundColorText = IS_CHN
  2403. ? `请输入关键词背景色,默认为“#ffff80ad”,支持HEX, HEXA, RGB, RGBA, transparent的颜色格式。`
  2404. : `𝐏𝐥𝐞𝐚𝐬𝐞 𝐞𝐧𝐭𝐞𝐫 𝐭𝐡𝐞 𝐤𝐞𝐲𝐰𝐨𝐫𝐝 𝐛𝐚𝐜𝐤𝐠𝐫𝐨𝐮𝐧𝐝-𝐜𝐨𝐥𝐨𝐫:\r\nThe default is "#ffff80ad" and supports the color formats of HEX, HEXA, RGB, RGBA and transparent.`;
  2405. const confirmColorsText = IS_CHN ? `请确认您输入的颜色代码是否正确?` : `𝐏𝐥𝐞𝐚𝐬𝐞 𝐦𝐚𝐤𝐞 𝐬𝐮𝐫𝐞 𝐭𝐡𝐚𝐭 𝐭𝐡𝐞 𝐜𝐨𝐥𝐨𝐫 𝐜𝐨𝐝𝐞 𝐞𝐧𝐭𝐞𝐫𝐞𝐝 𝐢𝐬 𝐜𝐨𝐫𝐫𝐞𝐜𝐭?`;
  2406. const confirmfgColorText = IS_CHN ? "\r\n前景色代码:" : "\r\n𝐅𝐨𝐫𝐞𝐠𝐫𝐨𝐮𝐧𝐝-𝐂𝐨𝐥𝐨𝐫: ";
  2407. const fonfirmbgColorText = IS_CHN ? "\r\n背景色代码:" : "\r\n𝐁𝐚𝐜𝐤𝐠𝐫𝐨𝐮𝐧𝐝-𝐂𝐨𝐥𝐨𝐫: ";
  2408. const saveData = async () => {
  2409. if (!inputFgColor || !inputBgColor) return;
  2410. const customColor = { foregroundColor: inputFgColor.trim().toLowerCase(), backgroundColor: inputBgColor.trim().toLowerCase() };
  2411. _config_date_ = { ..._config_date_, keywordHighlight: true, customColor };
  2412. GMsetValue(CONFIGURE, encrypt(JSON.stringify(_config_date_)));
  2413. };
  2414. inputFgColor = prompt(foregroundColorText, customColor.foregroundColor);
  2415. if (inputFgColor === null) return;
  2416. else if (colorReg.test(inputFgColor.trim())) {
  2417. inputBgColor = prompt(backgroundColorText, customColor.backgroundColor);
  2418. if (inputBgColor === null) return;
  2419. else if (colorReg.test(inputBgColor.trim())) {
  2420. const confirmForegroundColor = /^#/gi.test(inputFgColor.trim()) ? inputFgColor.trim().toUpperCase() : inputFgColor.trim().toLowerCase();
  2421. const confirmbackgroundColor = /^#/gi.test(inputBgColor.trim()) ? inputBgColor.trim().toUpperCase() : inputBgColor.trim().toLowerCase();
  2422. const confirmText = `${confirmColorsText}${confirmfgColorText}${confirmForegroundColor}${fonfirmbgColorText}${confirmbackgroundColor}`;
  2423. if (confirm(confirmText)) {
  2424. const text = createNoticeHTML(IS_CHN ? "<dd>搜索关键词自定义颜色已保存,当前页面即将刷新!</dd>" : "<dd>Search keywords custom color has been saved!</dd>");
  2425. GMnotification({ title: IS_CHN ? "自定义颜色保存" : "Save Custom Color", text, callbacks: { onShow: [saveData], onClose: [reload] } });
  2426. }
  2427. } else alert(IS_CHN ? "背景色 格式输入错误!" : "Background-color input-format error!");
  2428. } else alert(IS_CHN ? "前景色(字体颜色) 格式输入错误!" : "Foreground-color (font-color) input-format error!");
  2429. }
  2430.  
  2431. function cleanSelectedCard() {
  2432. qA(`input[name='${def.notice.card}_lists']:checked:enabled`).forEach(node => node.click());
  2433. }
  2434.  
  2435. function showCustomColor() {
  2436. qS(`#${def.notice.random}_customColor`).style.display = this.checked ? "inline-block" : "none";
  2437. }
  2438.  
  2439. async function saveConfigureData() {
  2440. const selectEngineList = qA(`input[name='${def.notice.card}_lists']:checked`).map(item => Number(item.dataset.sn));
  2441. if (selectEngineList.length < 3) {
  2442. const noticeText = IS_CHN
  2443. ? `\u0020您需要选择「三个」搜索引擎,还少<em>${3 - selectEngineList.length}</em>个呢!`
  2444. : `\u0020Please select <b>three</b> search engines, still less<em>${3 - selectEngineList.length}</em>`;
  2445. const text = createNoticeHTML(`<dd><e style="font-size:24px;vertical-align:bottom">\ud83d\ude31</e>${noticeText}</dd>`);
  2446. return GMnotification({ text, type: def.notice.error, closeWith: ["click"] });
  2447. }
  2448. const configKeys = ["hk", "gj", "lw", "kh", "ar", "aa", "au"];
  2449. const configValues = configKeys.map(key => qS(`#${def.notice[key]}`).checked);
  2450. const [isHotkey, googleJump, localWindow, keywordHighlight, antiLinkRedirect, antiAds, isAutoUpdate] = configValues;
  2451. const _config_date_ = { isAutoUpdate, keywordHighlight, isHotkey, selectedEngine: selectEngineList, localWindow, googleJump, antiLinkRedirect, antiAds, customColor };
  2452. GMsetValue(CONFIGURE, encrypt(JSON.stringify(_config_date_)));
  2453. if (await addAction.closeConfig()) {
  2454. const text = createNoticeHTML(IS_CHN ? "<dd>设置参数已成功保存,页面稍后自动刷新!</dd>" : "<dd>The data is saved successfully, Page will refresh!</dd>");
  2455. GMnotification({ title: IS_CHN ? "保存成功!" : "Success!", text, callbacks: { onClose: [reload] } });
  2456. }
  2457. }
  2458.  
  2459. function insertMenus() {
  2460. const parameter_Set_Menu = `\ufff0\u2699\ufe0f ${IS_CHN ? "搜索引擎助手高级设置" : "Advanced Feature Settings "}${isHotkey ? "(E)" : ""}`;
  2461. GMregisterMenuCommand(parameter_Set_Menu, addAction.setConfigure) && DEBUG("%cInstalling Parameter_Set_Menu", "color:#808080");
  2462. const filter_Set_Menu = `\ufff2\ud83d\udcdb ${IS_CHN ? "搜索结果拦截词设置" : "SearchResult Filter Settings "}${isHotkey ? "(B)" : ""}`;
  2463. GMregisterMenuCommand(filter_Set_Menu, addAction.filterResult) && DEBUG("%cInstalling Filter_Set_Menu", "color:#808080");
  2464. const engine_List_Menu = `\ufff4\ud83d\udc4b ${IS_CHN ? "嗨,你想去哪里吖?" : "Hi, Where to visit? "} ${isHotkey ? "(V)" : ""}`;
  2465. GMregisterMenuCommand(engine_List_Menu, addAction.listEngine) && DEBUG("%cInstalling Engine_List_Menu", "color:#808080");
  2466. isHotkey ? insertHotkey() : DEBUG("%cNo Hotkey_Setting", "color:#a9a9a9");
  2467. }
  2468.  
  2469. function insertHotkey() {
  2470. document.addEventListener("keydown", e => {
  2471. const ekey = (e.altKey || e.code === "AltRight") && !e.ctrlKey && !e.shiftKey && !e.metaKey;
  2472. if (e.code === "KeyE" && ekey) handleClickEvent("setConfigure", 1e3, e);
  2473. else if (e.code === "KeyV" && ekey) handleClickEvent("listEngine", 1e3, e);
  2474. else if (e.code === "KeyB" && ekey) handleClickEvent("filterResult", 1e3, e);
  2475. }) || DEBUG("%cInstalling Hotkey_Setting", "color:#808080");
  2476. }
  2477.  
  2478. function handleClickEvent(name, time, event) {
  2479. stopEventPropagation(event);
  2480. const currentTime = performance.now();
  2481. currentTime - def.count.clickTimer > time && (def.count.clickTimer = currentTime) && addAction[name]();
  2482. }
  2483.  
  2484. function showSystemInfo() {
  2485. if (CUR_WINDOW_TOP && listCurrentSite.siteTypeID !== newSiteType.OTHERS) {
  2486. const isFavEngine = currentSite.siteTypeID !== newSiteType.OTHERS;
  2487. const securityPolicy = getSecurityPolicy();
  2488. const fontStyle = `text-transform:capitalize;font:italic 16px/130% Candara,'Times New Roman'`;
  2489. __console(
  2490. "shown_system_info",
  2491. `%c${def.var.scriptName}\r\n%cINTRO.URL:\u0020https://f9y4ng.likes.fans/Search-Engine-Assistant\r\n%c%s%cV%s%c%s\r\n%c%s%c%s\r\n%c%s%c%s\r\n%c%s%c%s\r\n%c%s%c%s\r\n%c%s%c%s\r\n%c%s%c%s`,
  2492. "font:normal 700 16px/150% system-ui,-apple-system,BlinkMacSystemFont,sans-serif;color:#dc143c",
  2493. "color:#777;font:italic 400 10px/180% monospace",
  2494. "font-size:12px;font-weight:700;color:#4682b4",
  2495. IS_CHN ? "脚本版本:" : "Version:\u0020",
  2496. "color:#708090;font:italic 600 14px/150% Candara,Times New Roman",
  2497. def.var.curVersion,
  2498. "color:darkred;font:italic 11px/150% Candara,'Times New Roman'",
  2499. IS_CHEAT_UA ? "\u3000(CHEAT-UA)" : "",
  2500. "font-size:12px;font-weight:700;color:#4682b4",
  2501. IS_CHN ? "当前搜索引擎:" : "CurrentEngine:\u0020",
  2502. `color:#dc143c;${fontStyle};font-weight:700`,
  2503. currentSiteName,
  2504. "font-size:12px;font-weight:700;color:#4682b4",
  2505. IS_CHN ? "常用的搜索引擎:" : "YourFavEngine:\u0020",
  2506. `color:${isFavEngine ? "#006400" : "#0000ff"};${fontStyle}`,
  2507. isFavEngine,
  2508. "font-size:12px;font-weight:700;color:#4682b4",
  2509. IS_CHN ? "移除链接重定向:" : "antiRedirectFn:\u0020",
  2510. `color:${antiLinkRedirect ? "#006400" : "#0000ff"};${fontStyle}`,
  2511. antiLinkRedirect,
  2512. "font-size:12px;font-weight:700;color:#4682b4",
  2513. IS_CHN ? "去除搜索结果广告:" : "AntiAdvertising:\u0020",
  2514. `color:${antiAds ? "#006400" : "#0000ff"};${fontStyle}`,
  2515. antiAds,
  2516. "font-size:12px;font-weight:700;color:#4682b4",
  2517. IS_CHN ? "搜索结果关键词过滤:" : "SearchResultFilter:\u0020",
  2518. `color:${antiResultsFilter ? "#006400" : "#0000ff"};${fontStyle}`,
  2519. antiResultsFilter,
  2520. "font-size:12px;font-weight:700;color:#4682b4",
  2521. IS_CHN ? "因安全策略被阻止:" : "SecurityPolicy:\u0020",
  2522. `color:${securityPolicy ? "#006400" : "#0000ff"};${fontStyle}`,
  2523. securityPolicy
  2524. );
  2525. }
  2526. }
  2527.  
  2528. /* SEARCH_ENGINE_ASSISTANT_COMMAND_FUNCTIONS */
  2529.  
  2530. const siteConfigMap = {
  2531. baidu: {
  2532. listTypes: { target: "#content_left", listName: "div", className: "result-op" },
  2533. clear: () => safeRemoveNode("#con-ar"),
  2534. applyButton: ({ buttonSection, buttonID, target }) => {
  2535. insertAfter(buttonSection, target);
  2536. if (!qS(buttonID)) return;
  2537. switch (getUrlParam(currentSite.splitTypeName)) {
  2538. case currentSite.imageType[0]:
  2539. buttonSection.style.right = qS("span[class^='submit-btn']") ? "-210px" : "-220px";
  2540. qS(`#${def.const.rightButton} input`).style.marginLeft = qS("span[class^='submit-btn']") ? "0" : "3px";
  2541. document.body.style.overflowX = "clip";
  2542. break;
  2543. case currentSite.imageType[1]:
  2544. buttonSection.style.height = "34px";
  2545. qA(`${buttonID} input`).forEach(node => {
  2546. node.style.cssText = "min-width:100px;height:34px;padding:0 5px!important;color:#fff;background:#3388ff;border-radius:0;border:1px solid #2d78f4";
  2547. });
  2548. document.body.style.overflowX = "clip";
  2549. break;
  2550. case "news":
  2551. case "vsearch":
  2552. qS(`#${def.const.rightButton} input`).style.marginLeft = "3px";
  2553. break;
  2554. }
  2555. },
  2556. },
  2557. bing: {
  2558. listTypes: { target: "#b_results", listName: "li", className: "b_algo" },
  2559. clear: () => safeRemoveNode("aside>ol#b_context"),
  2560. applyButton: ({ buttonSection, target }) => {
  2561. insertAfter(buttonSection, target);
  2562. const sectionWidth = buttonSection.getBoundingClientRect().width || 2e2;
  2563. const [textarea, formBox, formNode] = [qS(`textarea.b_searchbox[name="q"]`, target.parentNode), qS(".b_searchboxForm"), qS(`form#sb_form`)];
  2564. qA(`#b_header .b_searchbox[name="q"]`).forEach(input => {
  2565. const inputLength = parseFloat(gCS(input).width) || 500;
  2566. input.style.maxWidth = `${inputLength - sectionWidth + 50}px`;
  2567. input.style.overflowY = "auto";
  2568. });
  2569. if (formBox && getUrlParam("view") === "detailV2") {
  2570. formBox.style.cssText += "width:max-content!important;z-index:1000;position:relative;";
  2571. qA(`#${def.const.rndButtonID} input`).forEach(input => {
  2572. input.style.cssText += "height:34px!important;border-radius:6px!important;padding:0 12px!important;margin:0 0 0 2px!important;";
  2573. });
  2574. }
  2575. if (!CUR_HOST_NAME.startsWith("cn")) {
  2576. if (formNode && textarea) {
  2577. const inputs = qA(`#${def.const.rndButtonID} input`);
  2578. const changeTextarea = e => !/b_logoArea|b_phead_chat_link/.test(e.target?.className) && inputs.forEach(input => input.classList.add(def.const.searchbox));
  2579. const recoverTextarea = () => textarea.getAttribute("rows") < 2 && inputs.forEach(input => input.classList.remove(def.const.searchbox));
  2580. textarea.getAttribute("rows") >= 2 && inputs.forEach(input => input.classList.add(def.const.searchbox));
  2581. formNode.addEventListener("focus", changeTextarea, true);
  2582. formNode.addEventListener("blur", recoverTextarea, true);
  2583. }
  2584. new MutationObserver(() => {
  2585. qA(`#b_header .b_searchbox[name="q"]`).forEach(input => {
  2586. input.style.maxWidth = "";
  2587. const inputLength = parseFloat(gCS(input).width) || 500;
  2588. input.style.maxWidth = `${inputLength - sectionWidth + 30}px`;
  2589. input.style.overflowY = "auto";
  2590. });
  2591. }).observe(formNode, { attributeFilter: ["aria-owns"] });
  2592. }
  2593. },
  2594. },
  2595. google: {
  2596. listTypes: { target: "div.MjjYud", listName: "div" },
  2597. applyButton: ({ buttonSection, target }) => {
  2598. getGlobalGoogle("www.google.com", googleJump);
  2599. insertAfter(buttonSection, target);
  2600. },
  2601. },
  2602. duckduckgo: {
  2603. listTypes: { target: "ol.react-results--main", listName: "li" },
  2604. applyButton: ({ buttonSection, target }) => {
  2605. target.parentNode.appendChild(buttonSection);
  2606. sleep(0)(buttonSection.getBoundingClientRect().width || 2e2).then(sectionWidth => (buttonSection.style.right = `-${sectionWidth + 8}px`));
  2607. },
  2608. },
  2609. yandex: {
  2610. listTypes: { target: "#search-result", listName: "li" },
  2611. clear: () => safeRemoveNode("div.content__right>div"),
  2612. applyButton: ({ buttonSection, target }) => {
  2613. insertAfter(buttonSection, target);
  2614. sleep(0)(buttonSection.getBoundingClientRect().width || 2e2).then(sectionWidth => {
  2615. buttonSection.style.width = `${sectionWidth + 12}px`;
  2616. });
  2617. },
  2618. },
  2619. qwant: {
  2620. listTypes: { target: "div[data-testid='containerWeb'] div[data-testid='sectionWeb']>div", listName: "div" },
  2621. applyButton: ({ buttonSection, target }) => {
  2622. target.parentNode.appendChild(buttonSection);
  2623. sleep(0)(buttonSection.getBoundingClientRect().width || 2e2).then(sectionWidth => {
  2624. const llmButtonWidth = qS(`div[data-testid="llm-button-force"][class]`)?.getBoundingClientRect().width || 0;
  2625. buttonSection.style.right = `-${sectionWidth + 10 + llmButtonWidth}px`;
  2626. });
  2627. },
  2628. },
  2629. sogou: {
  2630. listTypes: { target: "div.results", listName: "div", className: "vrwrap" },
  2631. clear: () => safeRemoveNode("#right"),
  2632. applyButton: ({ buttonSection, buttonID, target }) => {
  2633. const currentSearchType = getUrlParam(currentSite.splitTypeName);
  2634. if (currentSite.imageType.includes(currentSearchType)) {
  2635. sleep(4e2).then(() => {
  2636. if (!qS(buttonID) && target) {
  2637. insertAfter(buttonSection, target);
  2638. const sectionWidth = buttonSection.getBoundingClientRect().width;
  2639. buttonSection.style.right = `-${sectionWidth + 10}px`;
  2640. qA(`${buttonID} input`).forEach(node => node.classList.add(`${def.notice.random}_images`));
  2641. addSearchButtonEvent(qA(`${buttonID} span[sn]:not([event-insert])`));
  2642. }
  2643. });
  2644. } else if (currentSearchType === "weixin") {
  2645. insertAfter(buttonSection, target);
  2646. buttonSection.style = "position:relative";
  2647. qA(`${buttonID} input`).forEach(node => node.classList.add(`${def.notice.random}_weixin`));
  2648. } else {
  2649. insertAfter(buttonSection, target);
  2650. safeRemoveNode(qS(`#searchBtn2[value="\u5168\u7f51\u641c\u7d22"]`));
  2651. sleep(0).then(() => {
  2652. const sectionWidth = buttonSection.getBoundingClientRect().width || 2e2;
  2653. buttonSection.style.right = `-${sectionWidth + 10}px`;
  2654. const btn2 = qS(`#searchBtn2`);
  2655. if (btn2) btn2.style.right = `-${sectionWidth + 120}px`;
  2656. });
  2657. }
  2658. },
  2659. },
  2660. toutiao: {
  2661. listTypes: { target: "div.s-result-list", listName: "div", className: "result-content" },
  2662. clear: () => safeRemoveNode(".main>.s-side-list>.result-content"),
  2663. applyButton: ({ buttonSection, target }) => {
  2664. insertAfter(buttonSection, target);
  2665. sleep(0)(buttonSection.getBoundingClientRect().width || 2e2).then(sectionWidth => (buttonSection.style.right = `-${sectionWidth + 10}px`));
  2666. },
  2667. },
  2668. so360: {
  2669. listTypes: { target: "#main>ul.result", listName: "li", className: "res-list" },
  2670. clear: () => safeRemoveNode("#side_wrap"),
  2671. applyButton: ({ buttonSection, buttonID, target }) => {
  2672. insertAfter(buttonSection, target);
  2673. if (currentSite.imageType.includes(getUrlParam(currentSite.splitTypeName))) {
  2674. qA(`${buttonID} input`).forEach(node => (node.style = "margin:0 0 0 1px;"));
  2675. sleep(5e2).then(() => qS("#tools_close")?.click());
  2676. }
  2677. },
  2678. },
  2679. kaifa: {
  2680. listTypes: { target: "ul.ant-list-items", listName: "li", className: "ant-list-item" },
  2681. applyButton: ({ buttonSection, target }) => {
  2682. target.appendChild(buttonSection);
  2683. const input = qS("#search-box-container input[class~='ant-input']");
  2684. if (input) input.style.cssText += `width:580px!important`;
  2685. },
  2686. },
  2687. ecosia: {
  2688. listTypes: { target: ".mainline__content>div:not([class])", listName: "div" },
  2689. clear: () => safeRemoveNode("aside>div[data-test-id='sidebar-web-related-queries']"),
  2690. applyButton: ({ buttonSection, buttonID, target }) => {
  2691. if (IS_GREASEMONKEY) insertAfter(buttonSection, target);
  2692. else {
  2693. sleep(5e2).then(() => {
  2694. if (qS(buttonID) || !target) return;
  2695. insertAfter(buttonSection, target);
  2696. addSearchButtonEvent(qA(`${buttonID} span[sn]:not([event-insert])`));
  2697. });
  2698. }
  2699. },
  2700. },
  2701. yahoo: {
  2702. listTypes: { target: "#web>ol", listName: "li" },
  2703. clear: () => safeRemoveNode("#right>ol"),
  2704. applyButton: ({ buttonSection, target }) => {
  2705. try {
  2706. if (currentSite.imageType.includes(getUrlParam(currentSite.splitTypeName))) target.appendChild(buttonSection);
  2707. else {
  2708. insertAfter(buttonSection, target);
  2709. const sectionWidth = buttonSection.getBoundingClientRect().width ?? 224;
  2710. buttonSection.style.cssText = `position:absolute;top:0;right:-${10 + sectionWidth}px`;
  2711. }
  2712. } catch (e) {
  2713. ERROR("insertButtons.YAHOO:", e.message);
  2714. }
  2715. },
  2716. },
  2717. startpage: {
  2718. listTypes: { target: "#main>div.w-gl", listName: "div", className: "result" },
  2719. applyButton: ({ buttonSection, target }) => {
  2720. insertAfter(buttonSection, target);
  2721. const sectionWidth = buttonSection.getBoundingClientRect().width || 2e2;
  2722. const formSection = qS(`#header-search-form>.search-form-relative-container`);
  2723. formSection.style.cssText = `max-width:${parseFloat(gCS(formSection).getPropertyValue("max-width")) + sectionWidth}px`;
  2724. },
  2725. },
  2726. you: { listTypes: { target: "[data-floating-ui-portal]>[role='dialog'][data-open='true'] div>section", listName: "article" } },
  2727. brave: { listTypes: { target: "#results", listName: "div", className: "snippet" }, clear: () => safeRemoveNode("aside>div") },
  2728. yep: {
  2729. listTypes: { target: "div[class$='-results']>div>div", listName: "div" },
  2730. applyButton: ({ buttonSection, target }) => {
  2731. insertAfter(buttonSection, target);
  2732. const sectionWidth = buttonSection.getBoundingClientRect().width || 2e2;
  2733. buttonSection.style.right = `-${10 + sectionWidth}px`;
  2734. },
  2735. },
  2736. swisscows: {
  2737. listTypes: { target: ".web-results", listName: "article", className: "item-web" },
  2738. applyButton: ({ buttonSection, target }) => {
  2739. insertAfter(buttonSection, target);
  2740. sleep(0)
  2741. .then(() => buttonSection.getBoundingClientRect().width || 2e2)
  2742. .then(sectionWidth => (buttonSection.style.right = `-${10 + sectionWidth}px`));
  2743. },
  2744. },
  2745. searxng: {
  2746. listTypes: { target: "div#urls", listName: "article", className: "result" },
  2747. clear: () => safeRemoveNode("#infoboxes"),
  2748. applyButton: ({ buttonSection, target }) => void target.appendChild(buttonSection),
  2749. },
  2750. };
  2751.  
  2752. function insertCSS(isOverwrite = false) {
  2753. try {
  2754. const buttonCss = currentSite.buttonCssText ? `@charset "UTF-8";` + currentSite.buttonCssText : "";
  2755. addStyle({ target: document.head, styleId: def.const.rndclassName, media: "all", styleContent: buttonCss, isOverwrite });
  2756. } catch (e) {
  2757. ERROR("insertCSS:", e.message);
  2758. }
  2759. }
  2760.  
  2761. function insertStyle() {
  2762. try {
  2763. const noticeStyle = `@charset "UTF-8";` + def.var.style + def.var.iconstyle + String(keywordHighlight ? def.var.hlstyle : "");
  2764. addStyle({ target: document.head, styleId: def.const.rndstyleName, media: "screen", styleContent: noticeStyle, isOverwrite: false });
  2765. } catch (e) {
  2766. ERROR("insertStyle:", e.message);
  2767. }
  2768. }
  2769.  
  2770. async function insertButtons() {
  2771. try {
  2772. const target = qS(currentSite.mainSelector);
  2773. if (checkIndexPage() || !getQueryString() || !target || qS(`#${def.const.rndButtonID}`)) return;
  2774. const buttonSection = cE("gb-button", { id: def.const.rndButtonID, innerHTML: tTP.createHTML(def.var.button) });
  2775. const spans = await applyButtons(buttonSection, target);
  2776. if (!spans) return;
  2777. addSearchButtonEvent(spans);
  2778. scrollDetect();
  2779. } catch (e) {
  2780. ERROR("insertButtons:", e.message);
  2781. }
  2782. }
  2783.  
  2784. async function applyButtons(buttonSection, target) {
  2785. if (currentSite.siteTypeID === newSiteType.OTHERS) return null;
  2786. const [buttonID, applyButtonMethod] = [`#${buttonSection.id}`, siteConfigMap[currentSiteName]?.applyButton];
  2787. if (typeof applyButtonMethod === "function") await applyButtonMethod({ buttonSection, buttonID, target });
  2788. else insertAfter(buttonSection, target);
  2789. return qA(`${buttonID} span[sn]:not([event-insert])`);
  2790. }
  2791.  
  2792. function setupScrollButton(selector, className, scrollOffset) {
  2793. const element = qS(selector);
  2794. if (!element) return;
  2795. const offsetTop = element.getBoundingClientRect().top;
  2796. const toggleClass = () => {
  2797. const scrollTop = global.scrollY || document.documentElement?.scrollTop || 0;
  2798. element.classList.toggle(className, scrollTop > offsetTop + scrollOffset);
  2799. };
  2800. toggleClass();
  2801. document.addEventListener("scroll", toggleClass);
  2802. }
  2803.  
  2804. function scrollDetect() {
  2805. if (checkIndexPage()) return;
  2806. let scrollspan, scrollbars, height, searchType;
  2807. const currentSearchType = getUrlParam(currentSite.splitTypeName);
  2808. switch (currentSite.siteTypeID) {
  2809. case newSiteType.GOOGLE:
  2810. searchType = /^isch|2$/.test(currentSearchType);
  2811. scrollspan = def.const.scrollspan;
  2812. scrollbars = def.const.scrollbars;
  2813. height = searchType ? 100 : 80;
  2814. break;
  2815. case newSiteType.BING:
  2816. searchType = /^(images|videos)$/.test(currentSearchType);
  2817. scrollspan = searchType ? def.const.scrollspan2 : def.const.scrollspan;
  2818. scrollbars = searchType ? def.const.scrollbars2 : def.const.scrollbars;
  2819. height = 50;
  2820. break;
  2821. case newSiteType.BRAVE:
  2822. scrollspan = def.const.scrollspan;
  2823. scrollbars = def.const.scrollbars;
  2824. height = 80;
  2825. break;
  2826. default:
  2827. return;
  2828. }
  2829. setupScrollButton(`#${def.const.rndButtonID}`, scrollspan, height);
  2830. setupScrollButton(`#${def.const.rndButtonID} #${def.const.leftButton} input`, scrollbars, height);
  2831. setupScrollButton(`#${def.const.rndButtonID} #${def.const.rightButton} input`, scrollbars, height);
  2832. }
  2833.  
  2834. function addSearchButtonEvent(nodes) {
  2835. if (!Array.isArray(nodes) || nodes.length === 0) return;
  2836. nodes.forEach(node => {
  2837. node.setAttribute("event-insert", true);
  2838. const inputElement = qS("input", node);
  2839. const siteTypeID = Number(node.getAttribute("sn"));
  2840. inputElement.addEventListener("click", () => {
  2841. const imageSearch = getUrlParam(currentSite.splitTypeName)?.trim();
  2842. let selectedSiteData;
  2843. if (siteTypeID === selectedSite[0].siteTypeID) selectedSiteData = selectedSite[0];
  2844. else if (siteTypeID === selectedSite[1].siteTypeID) selectedSiteData = selectedSite[1];
  2845. else return;
  2846. const isImageSearch = currentSite.imageType.includes(imageSearch);
  2847. const gotoUrl = isImageSearch ? selectedSiteData.imageURL : selectedSiteData.webURL;
  2848. const finalUrl = decodeURI(gotoUrl + getQueryString());
  2849. if (localWindow) top.location.href = finalUrl;
  2850. else GMopenInTab(finalUrl, false);
  2851. });
  2852. });
  2853. }
  2854.  
  2855. function createNotice(listName, className, userdFilter) {
  2856. const listAttrib = className ? ` class="${className}"` : ``;
  2857. const noticeText = IS_CHN ? "本页所有搜索结果均被屏蔽,如异常请检查过滤词。" : "All results are blocked, Check the filters if abnormal.";
  2858. const filterArray = userdFilter ? `<gb-filters class="code">${IS_CHN ? "过滤词:" : "Filter:"} [${userdFilter}]</gb-filters>` : ``;
  2859. const tips = `<br/>✄┏━┓╋┏┓╋╋╋┏━━━┓╋╋╋╋╋╋╋╋┏┓┏┓╋┏┓<br/>✄┃┃┗┓┃┃╋╋╋┃┏━┓┃╋╋╋╋╋╋╋╋┃┣┛┗┓┃┃<br/>✄┃┏┓┗┛┣━━┓┃┗━┛┣━━┳━━┳┓┏┫┣┓┏┛┃┃<br/>✄┃┃┗┓┃┃┏┓┃┃┏┓┏┫┃━┫━━┫┃┃┃┃┃┃╋┗┛<br/>✄┃┃╋┃┃┃┗┛┃┃┃┃┗┫┃━╋━━┃┗┛┃┗┫┗┓┏┓<br/>✄┗┛╋┗━┻━━┛┗┛┗━┻━━┻━━┻━━┻━┻━┛┗┛<br/><br/>`;
  2860. const noticeCode = tTP.createHTML(`<${listName}${listAttrib} gb-filter-notice>${tips}${noticeText} ${def.var.scriptName}${filterArray}</${listName}>`);
  2861. return noticeCode;
  2862. }
  2863.  
  2864. function showEmptyNotice(siteName) {
  2865. const siteConfig = siteConfigMap[siteName];
  2866. if (!siteConfig) return;
  2867. const { target, listName, className } = siteConfig.listTypes;
  2868. const noticeNode = qS(`${target} [gb-filter-notice]`);
  2869. if (noticeNode) return;
  2870. const usedFilterWordsStr = escapeHTML([...usedFilterWords].join(", "));
  2871. const noticeCode = createNotice(listName, className, usedFilterWordsStr);
  2872. const el = qS(target)?.firstElementChild;
  2873. if (el) {
  2874. const position = el.classList.contains(def.var.translucent) || el.classList.contains(def.var.disappear) ? "beforebegin" : "afterend";
  2875. el.insertAdjacentHTML(position, noticeCode);
  2876. }
  2877. usedFilterWords.clear();
  2878. }
  2879.  
  2880. function filterSearchResults(filterObj) {
  2881. if (resultFilters.length === 0) return;
  2882. const { qs, delay } = filterObj ?? {};
  2883. deBounce({ fn: filterSearchResultsProcess, timer: "filterSearchResults", delay: delay || 50 })(qs);
  2884. }
  2885.  
  2886. async function filterSearchResultsProcess(querystring) {
  2887. if (!querystring) return;
  2888. const selectors = buildSelectors(querystring);
  2889. const elements = qA(selectors);
  2890. if (elements.length === 0) return;
  2891. const returnContent = new Map();
  2892. elements.forEach(item => processNode(item, returnContent));
  2893. if (returnContent.size === 0) return;
  2894. returnContent.forEach((content, item) => matchFilters(item, content));
  2895. await sleep(1e2, { instant: true });
  2896. if (usedFilterWords.size > 0 && qA(querystring.split(/,(?![^()]*\))/g)[0]).length >= 2) {
  2897. const remainingResults = qA(selectors.split(/,(?![^()]*\))/g)[0]).length;
  2898. handleRemainingResults(remainingResults);
  2899. }
  2900. }
  2901.  
  2902. function processMatchedItem(item, content, filter) {
  2903. if (IS_DEBUG) addDebugNotice(item, filter);
  2904. usedFilterWords.add(filter);
  2905. item.classList.add(IS_DEBUG ? def.var.translucent : def.var.disappear);
  2906. DEBUG("Filter.match:", { filter, item, content });
  2907. qA("a", item).forEach(node => node.setAttribute("gd-antiredirect-status", "blocked"));
  2908. }
  2909.  
  2910. function addDebugNotice(item, filter) {
  2911. if (qS("notice-label", item)) return;
  2912. const notice = cE("notice-label", { class: "code", textContent: `<![CDATA[ "${filter}" ]]>` });
  2913. item.prepend(notice);
  2914. }
  2915.  
  2916. function adjustUI(siteName) {
  2917. const logicFunction = siteConfigMap[siteName]?.clear;
  2918. if (typeof logicFunction === "function") logicFunction();
  2919. }
  2920.  
  2921. function buildSelectors(querystring) {
  2922. return querystring
  2923. .split(/,(?![^()]*\))/g)
  2924. .map(item => `${item}:not(.${def.var.disappear},.${def.var.translucent},[gb-filter-notice])`)
  2925. .join(",");
  2926. }
  2927.  
  2928. function processNode(item, returnContent) {
  2929. if (item.nodeType !== Node.ELEMENT_NODE) return;
  2930. const href = qS("a:not([data-testid='result-extras-site-search-link']):not([aria-label^='Anonymous']):not([href*='.bing.com/ck/a?'])", item)?.href ?? "";
  2931. const url = [1, 5, 8].includes(listCurrentSite.siteTypeID) ? "" : getDecodeURI(href);
  2932. const content = item.innerText?.replace(/[\t\r\n\ue62b]/g, "").trim() + url;
  2933. if (content) returnContent.set(item, content);
  2934. }
  2935.  
  2936. function matchFilters(item, content) {
  2937. if (item?.nodeType !== Node.ELEMENT_NODE) return;
  2938. try {
  2939. resultFilters.forEach(filter => new RegExp(filter, "i").test(content) && processMatchedItem(item, content, filter));
  2940. } catch (e) {
  2941. ERROR("Filter.match:", e.message);
  2942. }
  2943. }
  2944.  
  2945. function handleRemainingResults(remainingResults) {
  2946. if (remainingResults > 2) return;
  2947. if (remainingResults === 0) showEmptyNotice(currentSiteName);
  2948. else qS(`[gb-filter-notice]`)?.remove();
  2949. adjustUI(currentSiteName);
  2950. }
  2951.  
  2952. function getDecodeURI(href) {
  2953. if (typeof href !== "string" || href.startsWith("javascript:")) return "";
  2954. return `\ue620${decodeURIComponent(href)}\ue620`;
  2955. }
  2956.  
  2957. function getGlobalGoogle(NCRHost, permission) {
  2958. if (!permission || CUR_HOST_NAME === NCRHost) return;
  2959. try {
  2960. const url = `${CUR_PROTOCOL}//${NCRHost}/ncr?prev=${CUR_PATH_NAME}${encodeURIComponent(location.search)}`;
  2961. const text = createNoticeHTML(`<dd class="${def.notice.center}">${IS_CHN ? "即将跳转至 Google.com (NCR)" : "Jump to Google.com (NCR)"}</dd>`);
  2962. GMnotification({ title: "Google NCR", text, type: def.notice.info, callbacks: { beforeClose: [() => top.location.replace(url)] } });
  2963. } catch (e) {
  2964. ERROR("getGlobalGoogle:", e.message);
  2965. }
  2966. }
  2967.  
  2968. function updateIconsForExtension(requestVer) {
  2969. if (decrypt(requestVer) === def.var.curVersion) return;
  2970. DEBUG("%cRequest icon data for extension update...", "color:#25f") ?? updateToRequestIcon(false);
  2971. cache.set(AUTOCHECK, def.var.curVersion);
  2972. GMsetValue(VERSION, encrypt(def.var.curVersion));
  2973. }
  2974.  
  2975. function processMainThreadTasks() {
  2976. const { siteTypeID } = currentSite;
  2977. if (siteTypeID !== newSiteType.OTHERS && !getSecurityPolicy()) {
  2978. if (!qS(`#${def.const.rndclassName}`)) insertCSS();
  2979. if (!qS(`#${def.const.rndButtonID}`)) insertButtons();
  2980. }
  2981. const { siteTypeID: listSiteTypeID, antiAdsFn, resultListProp, antiRedirectFn } = listCurrentSite;
  2982. if (listSiteTypeID !== newSiteType.OTHERS) {
  2983. if (!qS(`#${def.const.rndstyleName}`)) insertStyle();
  2984. if (antiAds) antiAdsFn?.();
  2985. if (antiResultsFilter) filterSearchResults(resultListProp);
  2986. if (antiLinkRedirect && !checkIndexPage()) antiRedirectFn?.();
  2987. }
  2988. }
  2989.  
  2990. function searchButtonAndStylesObserve() {
  2991. const observer = new MutationObserver(deBounce({ fn: processMainThreadTasks, delay: 10, timer: "main" }));
  2992. observer.observe(document, { childList: true, subtree: true });
  2993. ["pushState", "replaceState"].forEach(event => global.addEventListener(event, processMainThreadTasks));
  2994. }
  2995.  
  2996. /* SEARCH_ENGINE_ASSISTANT_MAIN_PROCESS */
  2997.  
  2998. void (function (updateFlag, versionFlag) {
  2999. if (CUR_WINDOW_TOP) {
  3000. const updateInfo = getUpdateInformation(updateFlag);
  3001. parseUpdateInformatio(updateInfo);
  3002. showSystemInfo();
  3003. insertMenus();
  3004. if (updateFlag) updateIconsForExtension(versionFlag);
  3005. }
  3006. searchButtonAndStylesObserve();
  3007. })(await cache.get(AUTOCHECK), await GMgetValue(VERSION));
  3008. })(
  3009. updateFlag => {
  3010. if (CUR_WINDOW_TOP && isAutoUpdate && (!updateFlag || setDebuggerMode())) {
  3011. const updateDetectionResponses = updateDetectionAddress.map(addr => fetchUpdateResponse(addr));
  3012. return Promise.any(updateDetectionResponses).catch(e => ERROR("getUpdateInformation:", e.message));
  3013. }
  3014. },
  3015. async updateResponse => {
  3016. try {
  3017. const response = await updateResponse;
  3018. if (!response) return;
  3019. const { res, url } = response;
  3020. if (!res) return showUpdateError();
  3021. const [version, notes] = [extractVersion(res), extractNotes(res)];
  3022. if (!version) return;
  3023. const newUpdateHTML = generateUpdateHTML(version, generateUpdateList(notes));
  3024. if (versionCompare(def.var.curVersion, version)) showNewUpdateNotify(version, newUpdateHTML, url);
  3025. else showSuccessUpdateNotify();
  3026. } catch (e) {
  3027. ERROR(`parseUpdateInformation: ${e?.message}`);
  3028. }
  3029. }
  3030. );
  3031. })(function () {
  3032. const updateURLArray = [
  3033. `https://update.gf.qytechs.cn/scripts/12909/Google_baidu_Switcher_(ALL_in_One).meta.js`,
  3034. `https://raw.githubusercontent.com/F9y4ng/GreasyFork-Scripts/master/Google%20%26%20Baidu%20Switcher.meta.js`,
  3035. `https://openuserjs.org/install/f9y4ng/Google_baidu_Switcher_(ALL_in_One).meta.js`,
  3036. ];
  3037. return updateURLArray.map(url => `${url}?${generateRandomString(16, "hex")}`);
  3038. });
  3039. })(
  3040. async () => {
  3041. const defaults = {
  3042. isAutoUpdate: true,
  3043. keywordHighlight: false,
  3044. isHotkey: true,
  3045. selectedEngine: [1, 2, 3],
  3046. localWindow: true,
  3047. googleJump: true,
  3048. antiLinkRedirect: true,
  3049. antiAds: false,
  3050. customColor: { foregroundColor: "#f73131cd", backgroundColor: "#ffff80ad" },
  3051. };
  3052. const configure = await GMgetValue(CONFIGURE);
  3053. if (!configure) {
  3054. const values = await GMlistValues();
  3055. values.forEach(key => GMdeleteValue(key));
  3056. GMsetValue(CONFIGURE, encrypt(JSON.stringify(defaults)));
  3057. return defaults;
  3058. }
  3059. try {
  3060. const config_date = JSON.parse(decrypt(configure));
  3061. return { ...defaults, ...config_date, selectedEngine: Array.isArray(config_date.selectedEngine) ? config_date.selectedEngine : defaults.selectedEngine };
  3062. } catch (e) {
  3063. return defaults;
  3064. }
  3065. },
  3066. async () => {
  3067. const defaults = { filter: [], trigger: false };
  3068. try {
  3069. const resultFilter = await GMgetValue(RESULTFILTER);
  3070. if (!resultFilter) return defaults;
  3071. const { filter, trigger } = JSON.parse(decrypt(resultFilter));
  3072. return { filter: Array.isArray(filter) ? filter : [], trigger };
  3073. } catch (e) {
  3074. return defaults;
  3075. }
  3076. },
  3077. url => {
  3078. if (!CUR_WINDOW_TOP || !url) return;
  3079. return new Promise((resolve, reject) => {
  3080. const headers = { Accept: "*/*", Referer: url };
  3081. const onload = response => {
  3082. if (response.readyState !== 4) return;
  3083. if (response.status === 200) {
  3084. const reader = new FileReader();
  3085. reader.onload = () => resolve(reader.result);
  3086. reader.onerror = () => reject(new Error("Convert failed"));
  3087. reader.readAsDataURL(response.response);
  3088. } else if (response.status !== 0) reject(new Error("NoAccessError"));
  3089. };
  3090. const onerror = () => reject(new Error("NetworkError"));
  3091. const ontimeout = () => reject(new Error("TimeoutError"));
  3092. GMxmlhttpRequest({ url, headers, method: "GET", timeout: 5e3, responseType: "blob", onload, onerror, ontimeout });
  3093. }).catch(e => Promise.reject(new Error("requestRemoteIcon: " + e.message)));
  3094. },
  3095. options => {
  3096. try {
  3097. return new NoticeX({ ...options }).show();
  3098. } catch (e) {
  3099. ERROR("GMnotification:", e.message);
  3100. }
  3101. }
  3102. );
  3103. })(createTrustedTypePolicy());
  3104. },
  3105. (object => {
  3106. Object.entries({
  3107. Some(callback, thisArg = this) {
  3108. for (let i = 0; i < this.length; i++) if (callback.call(thisArg, this[i], i, this)) return true;
  3109. },
  3110. Find(callback, thisArg = this) {
  3111. for (let i = 0; i < this.length; i++) if (callback.call(thisArg, this[i], i, this)) return this[i];
  3112. },
  3113. }).forEach(([key, value]) => Reflect.defineProperty(object, key, { value, writable: false, configurable: false, enumerable: false }));
  3114. return object;
  3115. })(Object.create(Array.prototype)),
  3116. (ctx => {
  3117. const oC = ctx.Object.create.bind(null, null);
  3118. const eH = type => {
  3119. const original = ctx.history[type];
  3120. return function () {
  3121. return ctx.dispatchEvent(new CustomEvent(type, { detail: [...arguments] })), original.apply(this, arguments);
  3122. };
  3123. };
  3124. const tS = storageType => {
  3125. try {
  3126. ctx.addEventListener("error", event => event.message.includes("SecurityError") && event.preventDefault(), { once: true });
  3127. return ctx[storageType].setItem("__gb_storage_test__", true), ctx[storageType].removeItem("__gb_storage_test__"), ctx[storageType];
  3128. } catch (e) {
  3129. return null;
  3130. }
  3131. };
  3132. return { oC, eH, lS: tS("localStorage"), sS: tS("sessionStorage") };
  3133. })(typeof window !== "undefined" ? window : this ?? globalThis)
  3134. );

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址