优雅的搜索引擎助手

“优雅的搜索引擎助手”方便用户在不同的搜索引擎之间跳转;支持自定义常用搜索引擎、关键词高亮渲染效果;还提供去除搜索链接重定向、屏蔽搜索结果广告、可视化参数设置、及自动更新检测等高级功能;兼容多个知名搜索引擎,如Baidu、Google、Bing、Duckduckgo、Yandex、Sogou、Ecosia、You、Startpage、Brave等。

当前为 2024-05-04 提交的版本,查看 最新版本

  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 2024.05.04.1
  9. // @author F9y4ng
  10. // @description "Elegant Search Engine Assistant" facilite le passage d'un moteur de recherche à l'autre, prend en charge la personnalisation des moteurs de recherche couramment utilisés, la mise en évidence des mots-clés, la suppression de la redirection des liens de recherche, la protection des publicités des résultats de recherche, le réglage des paramètres visuels, Duckduckgo, Yandex, Sogou, Ecosia, You, Startpage, Brave, etc.
  11. // @description:en "Elegant search engine assistant" facilitates users to jump between different search engines; supports custom commonly used search engines and search keyword highlighting effects; provides advanced functions such as removing search link redirection, blocking search results advertisements, etc.; it is compatible with well-known search engines such as Baidu, Google, Bing, Duckduckgo, Yandex, Sogou, Ecosia, You, Startpage, Brave, etc.
  12. // @description:zh-CN “优雅的搜索引擎助手”方便用户在不同的搜索引擎之间跳转;支持自定义常用搜索引擎、关键词高亮渲染效果;还提供去除搜索链接重定向、屏蔽搜索结果广告、可视化参数设置、及自动更新检测等高级功能;兼容多个知名搜索引擎,如Baidu、Google、Bing、Duckduckgo、Yandex、Sogou、Ecosia、You、Startpage、Brave等。
  13. // @description:zh-TW 「優雅的搜索引擎助手」方便用戶在不同的搜索引擎之間跳轉;支持自定義常用搜索引擎、關鍵詞高亮渲染效果;還提供去除搜索鏈接重定嚮、屏蔽搜索結果廣告、可視化參數設置、及自動更新檢測等高級功能;兼容多個知名搜索引擎,如Baidu、Google、Bing、Duckduckgo、Yandex、Sogou、Ecosia、You、Startpage、Brave等。
  14. // @description:ru "Поисковый помощник" облегчает пользователям переход между различными поисковыми системами; поддерживает пользовательские широко используемые поисковые системы и эффекты подсветки ключевых слов; предоставляет расширенные функции, такие как удаление перенаправления поисковых ссылок, блокирование рекламы результатов поиска и т.д.; он совместим с известными поисковыми системами, такими как Baidu, Google, Bing, Duckduckgo, Yandex, Sogou, Ecosia, You, Startpage, brave и т.д.
  15. // @description:ja “優雅な検索エンジン助手”は、ユーザが異なる検索エンジン間でジャンプすることを容易にし、カスタム常用検索エンジン、検索キーワードのハイライト効果をサポートし、検索リンクのリダイレクト除去、検索結果広告の遮蔽、可視化パラメータ設定、自動更新検出などの高度な機能を提供し、Baidu、Google、Bing、Duckduckgo、Yandex、Sogou、Ecosia、You、Startpage、Braveなどの複数の有名な検索エンジンに対応する。
  16. // @namespace https://openuserjs.org/scripts/f9y4ng/Google_baidu_Switcher_(ALL_in_One)
  17. // @icon https://img.icons8.com/stickers/48/search-in-cloud.png
  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. // @require https://update.greasyfork.org/scripts/460897/1277476/gbCookies.js?SRI#sha256-Sv+EuBerch8z/6LvAU0m/ufvjmqB1Q/kbQrX7zAvOPk=
  22. // @match *://www.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.wuzhuiso.com/s*
  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 *://www.ecosia.org/*
  35. // @match *://search.yahoo.com/search*
  36. // @match *://images.search.yahoo.com/search*
  37. // @match *://you.com/search*
  38. // @match *://www.startpage.com/*
  39. // @match *://search.brave.com/*
  40. // @match *://yep.com/*
  41. // @match *://swisscows.com/*
  42. // @include *://*.google.*/search*
  43. // @exclude *://www.google.com/sorry*
  44. // @exclude *://www.baidu.com/link*
  45. // @exclude *://www.sogou.com/link*
  46. // @exclude *://www.so.com/link*
  47. // @exclude *://so.toutiao.com/search/jump*
  48. // @connect baidu.com
  49. // @connect bing.com
  50. // @connect sogou.com
  51. // @connect so.com
  52. // @connect search.yahoo.com
  53. // @connect greasyfork.org
  54. // @connect openuserjs.org
  55. // @connect githubusercontent.com
  56. // @connect favicon.yandex.net
  57. // @compatible edge 兼容Tampermonkey, Violentmonkey
  58. // @compatible Chrome 兼容Tampermonkey, Violentmonkey
  59. // @compatible Firefox 兼容Greasemonkey, Tampermonkey, Violentmonkey
  60. // @compatible Opera 兼容Tampermonkey, Violentmonkey
  61. // @compatible Safari 兼容Tampermonkey, Userscripts
  62. // @note 重构代码,修复一些深藏不露的BUG,优化样式。 (Refactor the code, fix some hidden bugs, optimize style.)
  63. // @grant GM_getValue
  64. // @grant GM.getValue
  65. // @grant GM_setValue
  66. // @grant GM.setValue
  67. // @grant GM_listValues
  68. // @grant GM.listValues
  69. // @grant GM_deleteValue
  70. // @grant GM.deleteValue
  71. // @grant GM_openInTab
  72. // @grant GM.openInTab
  73. // @grant GM_registerMenuCommand
  74. // @grant GM.registerMenuCommand
  75. // @grant GM_unregisterMenuCommand
  76. // @grant GM_xmlhttpRequest
  77. // @grant GM.xmlHttpRequest
  78. // @license GPL-3.0-only
  79. // @create 2015-10-07
  80. // @copyright 2015-2024, F9y4ng
  81. // @run-at document-start
  82. // ==/UserScript==
  83.  
  84. /* jshint esversion: 11 */
  85.  
  86. void (function (ctx, SearchEngineAssistant, proxyArrayMethods) {
  87. "use strict";
  88.  
  89. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  90. * CUSTOM SCRIPT DEBUGGING, DO NOT TURN ON FOR DAILY USE. *
  91. * SET TO "TRUE" FOR SCRIPT DEBUGGING, MAY CAUSE THE SCRIPT TO RUN SLOWLY. *
  92. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
  93.  
  94. const IS_OPEN_DEBUG = false;
  95.  
  96. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  97. * LICENSE FOR OPEN SOURCE USE: `GPLv3 ONLY`. *
  98. * THE CODE IS COMPLETELY OPEN AND FREE, AND DOES NOT ACCEPT UNAUTHORIZED *
  99. * DISTRIBUTION AS THIRD-PARTY STANDALONE SCRIPTS. IF ERRORS OCCUR OR USAGE *
  100. * ISSUES OR NEW FEATURE, PLEASE FEEDBACK ON GITHUB ISSUES, THANK YOU! *
  101. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
  102.  
  103. const { __protos__, defineMethod, ArrayMethods } = proxyArrayMethods;
  104. const utils = {
  105. gm: GM?.info ?? GM_info,
  106. debugging: IS_OPEN_DEBUG,
  107. atob: atob.bind(ctx),
  108. btoa: btoa.bind(ctx),
  109. alert: alert.bind(ctx),
  110. prompt: prompt.bind(ctx),
  111. confirm: confirm.bind(ctx),
  112. console: Object.assign({}, ctx.console),
  113. };
  114. ctx.history.pushState = enhanceHistory("pushState");
  115. ctx.history.replaceState = enhanceHistory("replaceState");
  116. ArrayMethods.forEach(method => void defineMethod(...method));
  117. SearchEngineAssistant(ctx, utils, __protos__);
  118.  
  119. function enhanceHistory(type) {
  120. const original = ctx.history[type];
  121. const event = new Event(type);
  122. return function () {
  123. const fn = original.apply(this, arguments);
  124. event.arguments = arguments;
  125. ctx.dispatchEvent(event);
  126. return fn;
  127. };
  128. }
  129. })(
  130. typeof window !== "undefined" ? window : this,
  131. function (w, secures, protoMethods) {
  132. "use strict";
  133.  
  134. const { atob, btoa, alert, prompt, confirm, console, debugging, gm: GMinfo } = secures;
  135. const { a: arrSlice, s: objToString, h: hasOwnProp } = protoMethods;
  136. const GMversion = GMinfo.version ?? GMinfo.scriptHandlerVersion ?? "unknown";
  137. const GMscriptHandler = GMinfo.scriptHandler;
  138. const GMsetValue = gmSelector("setValue");
  139. const GMgetValue = gmSelector("getValue");
  140. const GMdeleteValue = gmSelector("deleteValue");
  141. const GMlistValues = gmSelector("listValues");
  142. const GMopenInTab = gmSelector("openInTab");
  143. const GMregisterMenuCommand = gmSelector("registerMenuCommand");
  144. const GMunregisterMenuCommand = gmSelector("unregisterMenuCommand");
  145. const GMxmlhttpRequest = gmSelector("xmlhttpRequest");
  146. const GMunsafeWindow = gmSelector("unsafeWindow");
  147. const GMcontentMode = gmSelector("contentMode");
  148.  
  149. /* INITIALIZE_DEBUG_FUNCTIONS */
  150.  
  151. const IS_CHN = checkLocalChineseLanguage();
  152. const IS_DEBUG = setDebuggerMode() || debugging;
  153. const DEBUG = IS_DEBUG ? __console.bind(console, "log") : () => {};
  154. const ERROR = IS_DEBUG ? __console.bind(console, "error") : () => {};
  155. const COUNT = IS_DEBUG ? __console.bind(console, "count") : () => {};
  156.  
  157. /* INITIALIZE_COMMON_CONSTANTS */
  158.  
  159. const def = {
  160. count: { clickTimer: 0 },
  161. const: {
  162. raf: Symbol(`פֿ${generateRandomString(8, "hex")}`),
  163. caf: Symbol(`פֿ${generateRandomString(8, "hex")}`),
  164. loading: generateRandomString(6, "char"),
  165. cssAttrName: `gb-css-${generateRandomString(8, "hex")}`,
  166. rndButtonID: generateRandomString(12, "char"),
  167. rndclassName: `SC${generateRandomString(8, "digit")}`,
  168. rndstyleName: `SS${generateRandomString(8, "digit")}`,
  169. rndadvName: `SA${generateRandomString(8, "digit")}`,
  170. leftButton: generateRandomString(6, "mix"),
  171. rightButton: generateRandomString(6, "mix"),
  172. scrollspan: generateRandomString(8, "char"),
  173. scrollspan2: generateRandomString(8, "char"),
  174. scrollbars: generateRandomString(8, "char"),
  175. scrollbars2: generateRandomString(8, "char"),
  176. },
  177. var: {
  178. undef: void 0,
  179. disappear: "ͽZ2tB4nͼ",
  180. translucent: "ͼX5b8Zqͽ",
  181. securityPolicy: false,
  182. curVersion: getMetaValue("version") ?? GMinfo.script.version ?? "2024.05.04.0",
  183. scriptName: getMetaValue(`name:${navigator.language ?? "zh-CN"}`) ?? decrypt("U2VhcmNoJTIwRW5naW5lJTIwQXNzaXN0YW50"),
  184. },
  185. url: {
  186. yandexIcon: decrypt("aHR0cHMlM0ElMkYlMkZmYXZpY29uLnlhbmRleC5uZXQlMkZmYXZpY29uJTJGdjI="),
  187. backupIcon: decrypt("aHR0cHMlM0ElMkYlMkZ6MS5heDF4LmNvbSUyRjIwMjMlMkYxMSUyRjMwJTJGcGlyTTFTZy5wbmc="),
  188. feedback: getMetaValue("supportURL") ?? GMinfo.script.supportURL ?? decrypt("aHR0cHMlM0ElMkYlMkZmOXk0bmcubGlrZXMuZmFucyUyRnN1cHBvcnQ="),
  189. homepage: getMetaValue("homepage") ?? getMetaValue("homepageURL") ?? decrypt("aHR0cHMlM0ElMkYlMkZmOXk0bmcuZ2l0aHViLmlvJTJGR3JlYXN5Rm9yay1TY3JpcHRzJTJG"),
  190. },
  191. notice: {
  192. rName: generateRandomString(8, "char"),
  193. random: generateRandomString(5, "char"),
  194. noticeX: generateRandomString(7, "char"),
  195. appear: generateRandomString(6, "char"),
  196. gberror: generateRandomString(6, "mix"),
  197. linkerror: generateRandomString(7, "mix"),
  198. item: generateRandomString(6, "mix"),
  199. close: generateRandomString(6, "mix"),
  200. center: generateRandomString(6, "mix"),
  201. success: generateRandomString(7, "char"),
  202. warning: generateRandomString(7, "char"),
  203. info: generateRandomString(7, "char"),
  204. error: generateRandomString(7, "char"),
  205. checkbox: generateRandomString(6, "char"),
  206. configuration: generateRandomString(7, "char"),
  207. animated: generateRandomString(7, "char"),
  208. stopUpdate: generateRandomString(6, "mix"),
  209. searchButton: generateRandomString(6, "mix"),
  210. favicon: generateRandomString(6, "mix"),
  211. favicons: generateRandomString(6, "mix"),
  212. searchList: generateRandomString(7, "mix"),
  213. fieldset: generateRandomString(6, "char"),
  214. legend: generateRandomString(6, "char"),
  215. settingList: generateRandomString(7, "mix"),
  216. readonly: generateRandomString(8, "mix"),
  217. hk: generateRandomString(5, "mix"),
  218. gj: generateRandomString(5, "mix"),
  219. lw: generateRandomString(5, "mix"),
  220. kh: generateRandomString(5, "mix"),
  221. ar: generateRandomString(5, "mix"),
  222. aa: generateRandomString(5, "mix"),
  223. au: generateRandomString(5, "mix"),
  224. grid: generateRandomString(7, "char"),
  225. card: generateRandomString(7, "char"),
  226. },
  227. };
  228.  
  229. if (checkRedundantScript(GMunsafeWindow)) return;
  230.  
  231. /* INITIALIZE_SETTIMEOUT_AND_SETINTERVAL_FUNCTION_CLASSES */
  232.  
  233. class RAF {
  234. constructor(global) {
  235. if (RAF.instance) return RAF.instance;
  236. this._registerAnimationFrame(global);
  237. this.timerMap = { timeout: {}, interval: {} };
  238. this.setTimeout = this.setTimeout.bind(this);
  239. this.global = global;
  240. RAF.instance = this;
  241. }
  242. _registerAnimationFrame(scope) {
  243. scope[def.const.raf] =
  244. scope.requestAnimationFrame ||
  245. scope.webkitRequestAnimationFrame ||
  246. scope.mozRequestAnimationFrame ||
  247. scope.oRequestAnimationFrame ||
  248. void (function () {
  249. const animationStartTime = Date.now();
  250. let previousCallTime = animationStartTime;
  251. return function requestAnimationFrame(callback) {
  252. const requestTime = Date.now();
  253. const timeout = Math.max(0, 16.7 - (requestTime - previousCallTime));
  254. const timeToCall = requestTime + timeout;
  255. previousCallTime = timeToCall;
  256. return setTimeout(function onAnimationFrame() {
  257. callback(timeToCall - animationStartTime);
  258. }, timeout);
  259. };
  260. })();
  261. scope[def.const.caf] =
  262. scope.cancelAnimationFrame ||
  263. scope.webkitCancelAnimationFrame ||
  264. scope.mozCancelAnimationFrame ||
  265. scope.oCancelAnimationFrame ||
  266. scope.cancelRequestAnimationFrame ||
  267. scope.webkitCancelRequestAnimationFrame ||
  268. scope.mozCancelRequestAnimationFrame ||
  269. scope.oCancelRequestAnimationFrame ||
  270. function cancelAnimationFrame(id) {
  271. clearTimeout(id);
  272. };
  273. }
  274. _ticking(fn, type, interval, lastTime = Date.now()) {
  275. const timerSymbol = Symbol(type);
  276. const step = () => {
  277. this._setTimerMap(timerSymbol, type, step);
  278. if (interval < 16.7 || Date.now() - lastTime >= interval) {
  279. if (typeof fn === "function") fn();
  280. if (type === "interval") lastTime = Date.now();
  281. else this.clearTimeout(timerSymbol);
  282. }
  283. };
  284. this._setTimerMap(timerSymbol, type, step);
  285. return timerSymbol;
  286. }
  287. _setTimerMap(timerSymbol, type, step) {
  288. this.timerMap[type][timerSymbol] = this.global[def.const.raf](step);
  289. }
  290. _clearTimerMap(timer, type) {
  291. this.global[def.const.caf](this.timerMap[type][timer]);
  292. delete this.timerMap[type][timer];
  293. }
  294. setTimeout(fn, interval) {
  295. return this._ticking(fn, "timeout", interval);
  296. }
  297. clearTimeout(timer) {
  298. this._clearTimerMap(timer, "timeout");
  299. }
  300. setInterval(fn, interval) {
  301. return this._ticking(fn, "interval", interval);
  302. }
  303. clearInterval(timer) {
  304. this._clearTimerMap(timer, "interval");
  305. }
  306. }
  307.  
  308. const raf = new RAF(w);
  309.  
  310. /* GLOBAL_GENERAL_FUNCTIONS */
  311.  
  312. function gmSelector(rec) {
  313. const gmFunctions = {
  314. setValue: typeof GM_setValue !== "undefined" ? GM_setValue : GM?.setValue ?? localStorage.setItem.bind(localStorage),
  315. getValue: typeof GM_getValue !== "undefined" ? GM_getValue : GM?.getValue ?? localStorage.getItem.bind(localStorage),
  316. deleteValue: typeof GM_deleteValue !== "undefined" ? GM_deleteValue : GM?.deleteValue ?? localStorage.removeItem.bind(localStorage),
  317. listValues: typeof GM_listValues !== "undefined" ? GM_listValues : GM?.listValues ?? (() => []),
  318. openInTab: typeof GM_openInTab !== "undefined" ? GM_openInTab : GM?.openInTab ?? open.bind(w),
  319. registerMenuCommand: typeof GM_registerMenuCommand !== "undefined" ? GM_registerMenuCommand : GM?.registerMenuCommand ?? (() => {}),
  320. unregisterMenuCommand: typeof GM_unregisterMenuCommand !== "undefined" ? GM_unregisterMenuCommand : GM?.unregisterMenuCommand ?? (() => {}),
  321. xmlhttpRequest: typeof GM_xmlhttpRequest !== "undefined" ? GM_xmlhttpRequest : GM?.xmlHttpRequest ?? (() => Promise.resolve()),
  322. unsafeWindow: typeof unsafeWindow !== "undefined" ? unsafeWindow : w,
  323. contentMode: GMinfo.injectInto === "content" || GMinfo.script["inject-into"] === "content" || ["dom", "js"].includes(GMinfo.sandboxMode),
  324. };
  325. return gmFunctions[rec] ?? (() => {});
  326. }
  327.  
  328. function __console(act, message, ...args) {
  329. const _ = console;
  330. const _message = message ?? "";
  331. switch (act) {
  332. case "log":
  333. return _[act](`%c\ud83d\udd33 %c${_message}`, "display:inline-block", "font-family:monospace", ...args);
  334. case "error":
  335. case "warn":
  336. return _[act](`%c\ud83d\udea9 ${_message}`, "display:inline-block;font-family:monospace", ...args);
  337. case "count":
  338. return _[act](`\ud83d\udd33 ${_message}`);
  339. default:
  340. return _.log(_message, ...args);
  341. }
  342. }
  343.  
  344. function checkLocalChineseLanguage() {
  345. const chineseLanguages = ["zh", "zh-CN", "zh-HK", "zh-TW", "zh-MO", "zh-SG", "zh-MY"];
  346. const lang = navigator.language || navigator.userLanguage || "en-US";
  347. return chineseLanguages.includes(lang);
  348. }
  349.  
  350. function qS(expr, target = document) {
  351. try {
  352. if (/^#[\w:-]+$/.test(expr)) return target.getElementById(expr.slice(1));
  353. return target.querySelector(expr);
  354. } catch (e) {
  355. return null;
  356. }
  357. }
  358.  
  359. function qA(expr, target = document) {
  360. try {
  361. return arrSlice.call(target.querySelectorAll(expr), 0);
  362. } catch (e) {
  363. return [];
  364. }
  365. }
  366.  
  367. function cE(nodeName) {
  368. return document.createElement(nodeName);
  369. }
  370.  
  371. function random(range, type = "round") {
  372. return Math[type]((w.crypto.getRandomValues(new Uint32Array(1))[0] / (0xffffffff + 1)) * range);
  373. }
  374.  
  375. function capitalize(string) {
  376. string = String(string ?? "").toLowerCase();
  377. return string.replace(/\b[a-z]|\s[a-z]/g, str => str.toUpperCase());
  378. }
  379.  
  380. function encrypt(string, encode = true) {
  381. if (typeof string !== "string") return "";
  382. try {
  383. const req = encode ? encodeURIComponent(string) : string;
  384. return btoa(req);
  385. } catch (e) {
  386. return "";
  387. }
  388. }
  389.  
  390. function decrypt(string, decode = true) {
  391. if (typeof string !== "string") return "";
  392. try {
  393. const rst = atob(string.replace(/[^A-Za-z0-9+/=]/g, ""));
  394. return decode ? decodeURIComponent(rst) : rst;
  395. } catch (e) {
  396. return "";
  397. }
  398. }
  399.  
  400. function compareArray(array1, array2) {
  401. if (!Array.isArray(array1) || !Array.isArray(array2) || array1.length !== array2.length) return false;
  402. const sortedArray1 = array1.slice().sort();
  403. const sortedArray2 = array2.slice().sort();
  404. return sortedArray1.every((element, index) => element === sortedArray2[index]);
  405. }
  406.  
  407. function uniq(array) {
  408. if (!Array.isArray(array)) return [];
  409. return Array.from(new Set(array)).filter(Boolean);
  410. }
  411.  
  412. function generateRandomString(length, type) {
  413. const characters = {
  414. mix: "mYsTBgpkwNcGzFJdOMrt8n2jUC3fWRlKVA5y16oLxIXQE7Z9buvqie4PahH0SD",
  415. char: "zkDcUGopOvHJLfIZdPqEeRmyCSNYwrgbsFQuBXxnVWiltjMhaATK",
  416. hex: "a62f8bc07bd15c9ad3efe4",
  417. digit: "3927154680",
  418. };
  419. const prefix = "UKZJHQTRCSBFAYDMEVPXNWG".split("");
  420. const charactersArray = characters[type].split("");
  421. const randomString = Array.from({ length }, () => charactersArray[random(charactersArray.length, "floor")]).join("");
  422. return type === "mix" ? prefix[random(prefix.length, "floor")] + randomString : randomString;
  423. }
  424.  
  425. function refresh() {
  426. w.location.reload(true);
  427. }
  428.  
  429. function escapeHTML(string) {
  430. if (typeof string !== "string") return "";
  431. const element = cE("gb-escape-html");
  432. element.textContent = string;
  433. return element.innerHTML;
  434. }
  435.  
  436. function createTrustedTypePolicy() {
  437. const policy = { createHTML: string => string };
  438. if (!w.trustedTypes?.createPolicy) return policy;
  439. return w.trustedTypes.createPolicy("default", policy);
  440. }
  441.  
  442. function checkRedundantScript(global) {
  443. const { isTop: CUR_WINDOW_TOP } = getLocationInfo();
  444. const redundantScripts = global["gb-init-redundantcheck"];
  445. if (redundantScripts === true) return scriptRedundancyWarning();
  446. global["gb-init-redundantcheck"] = true;
  447. if (GMcontentMode) {
  448. const redundantScriptsInfo = document.documentElement?.getAttribute("gb-init-rc");
  449. if (redundantScriptsInfo === "true") return scriptRedundancyWarning();
  450. }
  451. document.documentElement?.setAttribute("gb-init-rc", true);
  452. return false;
  453.  
  454. function scriptRedundancyWarning() {
  455. if (!CUR_WINDOW_TOP) return true;
  456. __console("error", `\ud83d\udea9 [Redundant Scripts]:\r\nFound redundant-installed scripts: ${def.var.scriptName}. please reload to troubleshoot the issue.`);
  457. return GMregisterMenuCommand("\ufff8\ud83d\uded1 Found redundant scripts, reload!", refresh) || true;
  458. }
  459. }
  460.  
  461. async function getNavigatorInfo() {
  462. const certificate = `${GMscriptHandler} ${GMversion}`;
  463. const uad = await getUserAgentDataFromExtension(certificate);
  464. const trustEngine = getRealBrowserEngine();
  465. let engine = "Unknown";
  466. let brand = "Unknown";
  467. let brandVersion = "0.0.0.0";
  468. if (uad) {
  469. const os = getFullPlatformName(uad.platform);
  470. const brandMap = {
  471. SAFARI: { engine: "WebKit", brand: "Safari" },
  472. FIREFOX: { engine: "Gecko", brand: "Firefox" },
  473. EDGE: { engine: "Blink", brand: "Edge" },
  474. CHROME: { engine: "Blink", brand: "Chrome" },
  475. OPERA: { engine: "Blink", brand: "Opera" },
  476. BRAVE: { engine: "Blink", brand: "Brave" },
  477. YANDEX: { engine: "Blink", brand: "Yandex" },
  478. CATSXP: { engine: "Blink", brand: "Catsxp" },
  479. "MICROSOFT EDGE": { engine: "Blink", brand: "Edge" },
  480. "GOOGLE CHROME": { engine: "Blink", brand: "Chrome" },
  481. };
  482. uad.brands.Some(b => {
  483. const reqBrand = b.brand.toUpperCase();
  484. const brandInfo = brandMap[reqBrand];
  485. if (brandInfo) {
  486. engine = brandInfo.engine;
  487. brand = brandInfo.brand;
  488. brandVersion = b.version;
  489. return true;
  490. } else if (reqBrand === "CHROMIUM") {
  491. engine = "Blink";
  492. brand = "Chromium";
  493. brandVersion = b.version;
  494. }
  495. });
  496. return { engine, brand, brandVersion: formatVersion(brandVersion), os, trustEngine, credit: uad.credit ?? null };
  497. } else {
  498. const ua = navigator.userAgent;
  499. const checkString = str => new RegExp(str).test(ua);
  500. const getVersion = (str, offset) => checkString(str) && ua.substring(ua.indexOf(str) + offset).match(/\d+(\.\d+)*/)?.[0];
  501. const { brand, engine, brandVersion } = getBrowserInfoFromUA(ua, checkString, getVersion);
  502. const os = getOSInfoFromUA(checkString);
  503. return { engine, brand, brandVersion, os, trustEngine, credit: null };
  504. }
  505.  
  506. async function getUserAgentDataFromExtension(cert) {
  507. const vmuad = (uad => {
  508. if (!uad) return;
  509. const archs = uad.arch?.split("-") ?? [];
  510. const brand = capitalize(uad.browserBrand || uad.browserName);
  511. return {
  512. brands: [{ brand, version: uad.browserVersion }],
  513. platform: capitalize(uad.os),
  514. bitness: archs[1] ?? "unknown",
  515. architecture: archs[0] ?? "unknown",
  516. credit: cert,
  517. };
  518. })(GMinfo.platform);
  519. const tmuad = (uad => {
  520. if (!uad) return;
  521. uad.credit = cert;
  522. return uad;
  523. })(GMinfo.userAgentData);
  524. const uad =
  525. navigator.userAgentData &&
  526. (await navigator.userAgentData.getHighEntropyValues(["architecture", "fullVersionList"]).then(rst => {
  527. rst.brands = rst.fullVersionList;
  528. delete rst.fullVersionList;
  529. return rst;
  530. }));
  531. return vmuad ?? tmuad ?? uad;
  532. }
  533.  
  534. function getBrowserInfoFromUA(ua, checkString, getVersion) {
  535. const engine = getEngineFromUA(ua);
  536. const brandMap = {
  537. OPR: { brand: "Opera", engine: "Blink", as: "Chrome" },
  538. QQBrowser: { brand: "QQBrowser", engine: "Blink", as: "Chrome" },
  539. YaBrowser: { brand: "Yandex", engine, as: "Chrome" },
  540. Brave: { brand: "Brave", engine: "Blink" },
  541. Edg: { brand: "Edge", engine: "Blink" },
  542. Maxthon: { brand: "Maxthon", engine: "Blink", as: "Chrome" },
  543. CriOS: { brand: "Chrome", engine: "Blink" },
  544. Chromium: { brand: "Chromium", engine: "Blink" },
  545. Chrome: { brand: "Chrome", engine: "Blink" },
  546. FxiOS: { brand: "Firefox", engine: "Gecko" },
  547. Waterfox: { brand: "Waterfox", engine: "Gecko" },
  548. PaleMoon: { brand: "PaleMoon", engine: "Gecko", as: "Firefox" },
  549. Firefox: { brand: "Firefox", engine: "Gecko" },
  550. Safari: { brand: "Safari", engine: "WebKit", verset: ["Version"] },
  551. Trident: { brand: "IE", engine: "Trident", verset: ["MSIE", "rv"] },
  552. };
  553. for (const key of Object.keys(brandMap)) {
  554. if (!checkString(key)) continue;
  555. const { brand: _brand, engine, verset, as } = brandMap[key];
  556. const _verset = verset?.Find(k => checkString(k)) ?? verset?.[0];
  557. const _key = _verset ?? as ?? key;
  558. const _brandversion = formatVersion(getVersion(_key, _key.length + 1));
  559. return { brand: _brandversion ? _brand : brand, engine, brandVersion: _brandversion ?? brandVersion };
  560. }
  561. const { _brand, _brandversion } = getUnregisteredBrandAndVersionFromUA(ua);
  562. return { brand: _brand, engine, brandVersion: _brandversion };
  563. }
  564.  
  565. function formatVersion(version) {
  566. if (!version) return "0.0.0.0";
  567. const numbers = version.split(".").map(num => parseInt(num) || 0);
  568. while (numbers.length < 4) numbers.push(0);
  569. return numbers.join(".");
  570. }
  571.  
  572. function getFullPlatformName(platform) {
  573. if (!platform) return "Unknown";
  574. const os = capitalize(platform);
  575. return /^(Like Mac|Ios)$/.test(os) ? "iOS" : os === "Cros" ? "Chrome OS" : os.startsWith("Win") ? "Windows" : os.startsWith("Mac") ? "MacOS" : os === "X11" ? "Unix" : os;
  576. }
  577.  
  578. function getRealBrowserEngine() {
  579. return w.webkitRequestFileSystem ? "Blink" : !isNaN(parseFloat(w.mozInnerScreenX)) ? "Gecko" : w.GestureEvent ? "WebKit" : "Unknown";
  580. }
  581.  
  582. function getEngineFromUA(ua) {
  583. return /Gecko\/|FxiOS/.test(ua) ? "Gecko" : /Chrom(e|ium)\/|CriOS/.test(ua) ? "Blink" : /AppleWebKit\//.test(ua) ? "WebKit" : "Unknown";
  584. }
  585.  
  586. function getUnregisteredBrandAndVersionFromUA(ua) {
  587. const nameOffset = ua.lastIndexOf(" ") + 1;
  588. const verOffset = ua.lastIndexOf("/");
  589. const brand = ua.substring(nameOffset, verOffset);
  590. const brandVersion = formatVersion(ua.substring(verOffset + 1).match(/\d+(\.\d+)*/)?.[0]);
  591. const isValidValue = !/version|\/|\(|\)|;/i.test(brand) && brandVersion;
  592. return { _brand: isValidValue ? brand : "Unknown", _brandversion: isValidValue ? brandVersion : "Unknown" };
  593. }
  594.  
  595. function getOSInfoFromUA(checkString) {
  596. const platforms = ["like Mac", "Mac", "Android", "Debian", "Ubuntu", "Linux", "Win", "CrOS", "X11"];
  597. const platform = platforms.Find(p => checkString(p)) || "Unknown";
  598. return getFullPlatformName(platform);
  599. }
  600. }
  601.  
  602. function getLocationInfo() {
  603. const { pathname, host, hostname, protocol } = w.location;
  604. const isTop = w.self === w.top;
  605. const parentHost = w.parent !== w.self ? getParentHost() : host;
  606. return { host, hostname, pathname, protocol, parentHost, isTop };
  607.  
  608. function getParentHost() {
  609. try {
  610. return w.parent.location.host;
  611. } catch (e) {
  612. return new URL(document.referrer || w.location).host;
  613. }
  614. }
  615. }
  616.  
  617. function getMetaValue(str) {
  618. const queryReg = new RegExp(`//\\s+@${str}\\s+(.+)`);
  619. const metaValue = (GMinfo.scriptMetaStr || GMinfo.scriptSource)?.match(queryReg);
  620. return metaValue?.[1];
  621. }
  622.  
  623. function setDebuggerMode() {
  624. const key = decrypt("\u0052\u006a\u006c\u0035\u004e\u0047\u0035\u006e");
  625. const value = new URLSearchParams(w.location.search).get("whoami");
  626. return Object.is(key, value);
  627. }
  628.  
  629. function sleep(delay, { useCachedSetTimeout } = {}) {
  630. const timeoutFunction = useCachedSetTimeout ? setTimeout : raf.setTimeout;
  631. const sleepPromise = new Promise(resolve => {
  632. timeoutFunction(resolve, delay);
  633. });
  634. const promiseFunction = value => sleepPromise.then(() => value);
  635. promiseFunction.then = (...args) => sleepPromise.then(...args);
  636. promiseFunction.catch = Promise.resolve().catch;
  637. return promiseFunction;
  638. }
  639.  
  640. function deBounce({ fn, delay, timer, immed, once } = {}) {
  641. if (typeof fn !== "function" || !timer) return () => {};
  642. let caller = 0;
  643. const threshold = Number(Boolean(immed));
  644. return function () {
  645. const context = this;
  646. const args = arguments;
  647. const name = Symbol.for(String(timer));
  648. if (typeof def.count[name] === "undefined") {
  649. if (immed === true) {
  650. fn.apply(context, args);
  651. if (once === true) return (def.count[name] = true);
  652. }
  653. } else {
  654. if (once === true && def.count[name] === true) return true;
  655. raf.clearTimeout(def.count[name]);
  656. caller++;
  657. }
  658. def.count[name] = raf.setTimeout(() => {
  659. if (caller >= threshold) {
  660. fn.apply(context, args);
  661. if (once === true) return (def.count[name] = true);
  662. }
  663. delete def.count[name];
  664. }, Number(delay) || 0);
  665. };
  666. }
  667.  
  668. function safeRemove(expr, scope) {
  669. let removedNodes = [];
  670. let pendingNodes = [];
  671. switch (typeof expr) {
  672. case "string":
  673. if (!expr) return false;
  674. pendingNodes = qA(expr, scope);
  675. pendingNodes.forEach(item => void removeNode(item));
  676. break;
  677. case "object":
  678. if (expr?.nodeType !== Node.ELEMENT_NODE) return false;
  679. pendingNodes.push(expr);
  680. removeNode(expr);
  681. break;
  682. default:
  683. ERROR("Element not exist!");
  684. return false;
  685. }
  686. return compareArray(removedNodes, pendingNodes);
  687.  
  688. function removeNode(item) {
  689. try {
  690. removedNodes.push(item.parentNode.removeChild(item));
  691. } catch (e) {
  692. removedNodes.push(item);
  693. item.remove();
  694. }
  695. }
  696. }
  697.  
  698. function createNoticeHTML(html) {
  699. return `<div class="${def.notice.rName}"><dl>${html}</dl></div>`;
  700. }
  701.  
  702. void (async function (tTP, requestEnvironmentConstants) {
  703. const { navigatorInfo, locationInfo } = await requestEnvironmentConstants();
  704. const { engine, brand, trustEngine, credit } = navigatorInfo;
  705. const { protocol: CUR_PROTOCOL, hostname: CUR_HOST_NAME, pathname: CUR_PATH_NAME, isTop: CUR_WINDOW_TOP } = locationInfo;
  706. const IS_REAL_GECKO = trustEngine === "Gecko";
  707. const IS_REAL_WEBKIT = trustEngine === "WebKit";
  708. const IS_CHEAT_UA = !credit && (engine !== trustEngine || checkBlinkCheatingUA());
  709. const IS_GREASEMONKEY = GMscriptHandler === "Greasemonkey";
  710.  
  711. const cache = {
  712. value: (data, eT = 6048e5) => ({ data, expired: Date.now() + eT }),
  713. set: (key, ...options) => GMsetValue(key, encrypt(JSON.stringify(cache.value(...options)))),
  714. get: async key => {
  715. const obj = await GMgetValue(key);
  716. if (!obj) return;
  717. try {
  718. const value = JSON.parse(decrypt(obj));
  719. const { data, expired } = value;
  720. if (expired > Date.now() && data) return data;
  721. else return cache.remove(key);
  722. } catch (e) {
  723. ERROR("Cache.get:", e.message);
  724. return cache.remove(key);
  725. }
  726. },
  727. remove: key => void GMdeleteValue(key),
  728. };
  729.  
  730. class NoticeX {
  731. constructor(options = {}) {
  732. this.defaultOptions = {
  733. title: "",
  734. text: "",
  735. type: def.notice.success,
  736. position: "bottomRight",
  737. newestOnTop: false,
  738. timeout: 2e3,
  739. progressBar: true,
  740. closeWith: ["button"],
  741. animation: { open: `${def.notice.animated} ${def.notice.random}_fadeIn`, close: `${def.notice.animated} ${def.notice.random}_fadeOut` },
  742. width: 400,
  743. scroll: { maxHeight: 400, showOnHover: false },
  744. callbacks: { beforeShow: [], onShow: [], afterShow: [], beforeClose: [], onClose: [], afterClose: [], onClick: [], onHover: [] },
  745. };
  746. this.options = { ...this.defaultOptions, ...options };
  747. this._registerCallbacks();
  748. }
  749. static close(item) {
  750. if (!item) return true;
  751. item.classList.add(def.notice.animated, `${def.notice.random}_fadeOut`);
  752. const closetNode = item.closest(`.${def.notice.noticeX}`);
  753. const position = closetNode?.className.match(/\b(\w+-\w+)\b/)?.[1] || `${def.notice.noticeX}-topRight`;
  754. return sleep(3e2)
  755. .then(() => safeRemove(item))
  756. .then(() => qA(`.${position} .${def.notice.item}`).length === 0 && safeRemove(qS(`.${position}`)));
  757. }
  758. show() {
  759. this._createContainer();
  760. const noticeX = this._appendNoticeX(this._createHeader(), this._createBody(), this._createProgressBar());
  761. return noticeX;
  762. }
  763. _createContainer() {
  764. const position = `${def.notice.noticeX}-${this.options.position}`;
  765. if (qS(`gb-notice.${position}`)) return;
  766. const container = cE("gb-notice");
  767. container.classList.add(def.notice.noticeX, position, def.notice.appear);
  768. document.documentElement.appendChild(container);
  769. }
  770. _createHeader() {
  771. let header = null;
  772. if (this.options.title) {
  773. header = cE("div");
  774. header.classList.add(`${def.notice.noticeX}-heading`);
  775. header.innerHTML = tTP.createHTML(`<span class="${def.notice.noticeX}-heading-title" title="${this.options.title}">${this.options.title}</span>`);
  776. }
  777. if (this.options.closeWith.includes("button")) {
  778. const close = cE("div");
  779. close.classList.add(def.notice.close);
  780. close.innerHTML = tTP.createHTML("&times;");
  781. header = header ? header.appendChild(close) && header : close;
  782. }
  783. return header;
  784. }
  785. _createBody() {
  786. const body = cE("div");
  787. body.classList.add(`${def.notice.noticeX}-body`);
  788. const content = cE("div");
  789. content.classList.add(`${def.notice.noticeX}-content`);
  790. content.innerHTML = tTP.createHTML(this.options.text);
  791. body.appendChild(content);
  792. if (this.options.scroll?.maxHeight) {
  793. body.style.overflowY = "auto";
  794. body.style.maxHeight = `min(calc(95vh - 100px), ${this.options.scroll.maxHeight}px)`;
  795. if (this.options.scroll?.showOnHover) body.style.visibility = "hidden";
  796. }
  797. return body;
  798. }
  799. _createProgressBar() {
  800. const progressBar = cE("div");
  801. progressBar.classList.add(`${def.notice.noticeX}-progressbar`);
  802. const bar = cE("div");
  803. bar.classList.add(`${def.notice.noticeX}-bar`);
  804. progressBar.appendChild(bar);
  805. if (this.options.progressBar && typeof this.options.timeout === "number") {
  806. progressBar.style.animation = `${def.notice.noticeX}-progress ${this.options.timeout / 1e3}s linear forwards`;
  807. sleep(this.options.timeout, { useCachedSetTimeout: true }).then(item => {
  808. if (!(item = progressBar.closest(`div.${def.notice.item}`))) return;
  809. if (this.options.animation?.close) {
  810. const remaining = item.className.replace(new RegExp("(?:^|\\s)" + this.options.animation.open + "(?:\\s|$)"), " ");
  811. item.className = `${remaining} ${this.options.animation.close}`;
  812. sleep(5e2).then(() => this._closeItem(item));
  813. } else this._closeItem(item);
  814. });
  815. }
  816. return progressBar;
  817. }
  818. _appendNoticeX(noticeXHeader, noticeXBody, noticeXProgressBar) {
  819. const targetClass = `.${def.notice.noticeX}-${this.options.position}`;
  820. const noticeItem = cE("div");
  821. noticeItem.classList.add(def.notice.item, this.options.type);
  822. if (this.options.width && Number.isInteger(this.options.width)) noticeItem.style.width = `${this.options.width}px`;
  823. if (noticeXHeader) noticeItem.appendChild(noticeXHeader);
  824. if (noticeXBody) noticeItem.appendChild(noticeXBody);
  825. if (noticeXProgressBar) noticeItem.appendChild(noticeXProgressBar);
  826. if (["top", "bottom"].includes(this.options.position)) qS(targetClass).textContent = "";
  827. if (this.options?.animation?.open) noticeItem.className += ` ${this.options.animation.open}`;
  828. this._getCallback("beforeShow");
  829. this._addListener(noticeItem);
  830. const target = qS(targetClass);
  831. this._getCallback("onShow");
  832. this.options.newestOnTop && target ? target.insertAdjacentElement("afterbegin", noticeItem) : target.appendChild(noticeItem);
  833. this._getCallback("afterShow");
  834. return noticeItem;
  835. }
  836. _addListener(item) {
  837. const closeBtn = qS(`.${def.notice.close}`, item);
  838. const handleClick = () => this._closeItem(item);
  839. if (this.options.closeWith.includes("button")) closeBtn?.addEventListener("click", handleClick);
  840. if (this.options.closeWith.includes("click")) {
  841. item.style.cursor = "pointer";
  842. item.addEventListener("click", e => {
  843. if (e.target.className !== def.notice.close) {
  844. this._getCallback("onClick");
  845. handleClick();
  846. }
  847. });
  848. } else item.addEventListener("click", e => e.target.className !== def.notice.close && this._getCallback("onClick"));
  849. item.addEventListener("mouseover", () => this._getCallback("onHover"));
  850. }
  851. _closeItem(item) {
  852. if (this.options.animation?.close) item.className += ` ${this.options.animation.close}`;
  853. const closetNode = item.closest(`.${def.notice.noticeX}`);
  854. const position = closetNode?.className.match(/\b(\w+-\w+)\b/)?.[1] || `${def.notice.noticeX}-bottomRight`;
  855. this._getCallback("beforeClose");
  856. sleep(3e2)
  857. .then(() => this._getCallback("onClose"))
  858. .then(() => safeRemove(item))
  859. .then(() => qA(`.${position} .${def.notice.item}`).length === 0 && safeRemove(qS(`.${position}`)))
  860. .then(() => this._getCallback("afterClose"));
  861. }
  862. _getCallback(eventName) {
  863. if (this.options.callbacks[eventName]) {
  864. this.options.callbacks[eventName].forEach(cb => {
  865. if (typeof cb === "function") cb.call(this);
  866. });
  867. }
  868. }
  869. _registerCallbacks() {
  870. Object.keys(this.options.callbacks).forEach(eventName => {
  871. const cb = this.options.callbacks[eventName];
  872. if (typeof cb === "function") this._on(eventName, cb);
  873. });
  874. }
  875. _on(eventName, cb = () => {}) {
  876. if (typeof cb === "function" && this.options.callbacks[eventName]) {
  877. this.options.callbacks[eventName].push(cb);
  878. }
  879. return this;
  880. }
  881. }
  882.  
  883. function checkBlinkCheatingUA() {
  884. if (typeof NavigatorUAData === "undefined") return false;
  885. if (CUR_PROTOCOL === "https:" && !navigator.userAgentData) return true;
  886. return Boolean(navigator.userAgentData) && !(navigator.userAgentData instanceof NavigatorUAData);
  887. }
  888.  
  889. function insertAfter(newElement, targetElement) {
  890. if (!newElement || !targetElement) return;
  891. const parent = targetElement.parentNode || document.head;
  892. if (parent.lastChild === targetElement) parent.appendChild(newElement);
  893. else parent.insertBefore(newElement, targetElement.nextSibling);
  894. }
  895.  
  896. function addStyle({ target, styleId, styleContent, media, isOverwrite }) {
  897. if (!target || !styleId || !styleContent || !media) return;
  898. let existingStyles = qA(`#${styleId}`, target);
  899. if (existingStyles.length > 0) {
  900. if (isOverwrite === true) existingStyles.forEach(style => void safeRemove(style));
  901. else return true;
  902. }
  903. try {
  904. const styleElement = cE("style");
  905. styleElement.setAttribute(def.const.cssAttrName, isOverwrite ?? false);
  906. styleElement.id = styleId;
  907. styleElement.media = media;
  908. styleElement.type = "text/css";
  909. styleElement.textContent = styleContent ?? "";
  910. target.appendChild(styleElement);
  911. return true;
  912. } catch (e) {
  913. ERROR("addStyle:", e.message);
  914. return false;
  915. }
  916. }
  917.  
  918. function getUrlParam(parameter) {
  919. try {
  920. switch (objToString.call(parameter)) {
  921. case "[object Object]": {
  922. const { split, index } = parameter;
  923. const keyArray = w.location.pathname.split(split);
  924. return keyArray[index] ?? "";
  925. }
  926. case "[object Array]":
  927. for (const para of parameter) {
  928. const value = getUrlParam(para);
  929. if (value) return value;
  930. }
  931. return "";
  932. case "[object Number]":
  933. case "[object String]":
  934. if (!parameter && parameter !== 0) return "";
  935. return new URLSearchParams(w.location.search).get(parameter) ?? "";
  936. case "[object Function]":
  937. return parameter() ?? "";
  938. default:
  939. return "";
  940. }
  941. } catch (e) {
  942. ERROR("getUrlParam:", e.message);
  943. return "";
  944. }
  945. }
  946.  
  947. function versionCompare(current, compare) {
  948. try {
  949. const compareVersion = compare.split(".");
  950. const currentVersion = current.split(".");
  951. if (compareVersion.length !== currentVersion.length) return true;
  952. for (let i = 0; i < compareVersion.length; i++) {
  953. if (parseInt(compareVersion[i]) < parseInt(currentVersion[i])) return false;
  954. else if (parseInt(compareVersion[i]) > parseInt(currentVersion[i])) return true;
  955. }
  956. return false;
  957. } catch (e) {
  958. return true;
  959. }
  960. }
  961.  
  962. function convertBlobToDataURL(blob, resolve, reject) {
  963. let oFileReader = new FileReader();
  964. oFileReader.onloadend = e => resolve(e.target.result);
  965. oFileReader.onerror = reject;
  966. oFileReader.readAsDataURL(blob);
  967. }
  968.  
  969. void (async function (getConfigureData, getResultFilterData, requestRemoteIcon, GMnotification) {
  970. let parameter_Set, engine_List, filter_Set;
  971. let [_config_date_, _filter_Data_] = await Promise.all([getConfigureData(), getResultFilterData()]);
  972. let { isAutoUpdate, keywordHighlight, isHotkey, selectedEngine, localWindow, googleJump, antiLinkRedirect, antiAds, customColor } = _config_date_;
  973. const { trigger: antiResultsFilter, filter: resultFilters } = _filter_Data_;
  974. const cachedRequestLinks = antiLinkRedirect ? new Map() : null;
  975. const usedFilterWords = antiResultsFilter ? new Set() : null;
  976. const selectedSite = [];
  977.  
  978. /* ANTIREDIRECT_FUNCTIONS */
  979.  
  980. function validateOptions(options) {
  981. return {
  982. useNewTab: options.useNewTab || false,
  983. forceNewTab: options.forceNewTab || false,
  984. cleanAttributes: options.cleanAttributes || [],
  985. removeDataSet: options.removeDataSet || false,
  986. useAdvancedAntiRedirect: options.useAdvancedAntiRedirect || false,
  987. };
  988. }
  989.  
  990. function updateNodeAttributes(node, options) {
  991. if (options.useNewTab) node.setAttribute("target", "_blank");
  992. if (Array.isArray(options.cleanAttributes) && options.cleanAttributes.length > 0) options.cleanAttributes.forEach(item => node.removeAttribute(item));
  993. if (options.removeDataSet) Object.keys(node.dataset).forEach(ds => delete node.dataset[ds]);
  994. node.setAttribute("gd-depurate-status", true);
  995. }
  996.  
  997. function parsingAntiRedirect(selectors, siteName, options) {
  998. if (typeof selectors !== "string" || selectors.trim() === "") return;
  999. options = validateOptions(options);
  1000. const selectorArray = selectors.split(/,(?![^()]*\))/g);
  1001. const queryString = selectorArray.map(item => `${item}:not([href^='javascript:' i]):not([href^='#']):not([gd-depurate-status],[gd-antiredirect-status])`).join(",");
  1002. const aNodes = qA(queryString);
  1003. if (aNodes.length === 0) return;
  1004. COUNT(`[${siteName}-Anti-Redirect]`);
  1005. let taskList = [];
  1006. aNodes.forEach(node => {
  1007. if (options.useAdvancedAntiRedirect) {
  1008. node.setAttribute("gd-antiredirect-status", "pending");
  1009. const task = advancedAntiRedirection(siteName, node, () => Promise.resolve(NaN));
  1010. if (typeof task === "function") taskList.push(task);
  1011. }
  1012. updateNodeAttributes(node, options);
  1013. if (options.forceNewTab) {
  1014. node.onclick = e => {
  1015. e.preventDefault();
  1016. e.stopImmediatePropagation();
  1017. GMopenInTab(node.href, false);
  1018. };
  1019. }
  1020. });
  1021. parallelTasks(taskList, 6);
  1022. }
  1023.  
  1024. function fetchData(url, resolve, reject, readystate, error, timeout) {
  1025. GMxmlhttpRequest({
  1026. url: url,
  1027. headers: { Accept: "*/*", Referer: w.location.origin.replace(/^http:/i, "https:") },
  1028. method: "GET",
  1029. timeout: 25e3,
  1030. onreadystatechange: readystate(resolve, reject),
  1031. onerror: error(reject, resolve),
  1032. ontimeout: timeout(reject),
  1033. });
  1034. }
  1035.  
  1036. function getRealUrl(url, node, name, { onreadystatechangeFunc, onerrorFunc, ontimeoutFunc }) {
  1037. return new Promise((resolve, reject) => {
  1038. if (!cachedRequestLinks.has(url)) {
  1039. cachedRequestLinks.set(url, null);
  1040. fetchData(url, resolve, reject, onreadystatechangeFunc, onerrorFunc, ontimeoutFunc);
  1041. } else reject(new RangeError("DuplicateLinksError"));
  1042. })
  1043. .then(res => handleSuccess(res, url, node))
  1044. .catch(e => handleError(e, url, node, name));
  1045. }
  1046.  
  1047. function handleSuccess(res, url, node) {
  1048. DEBUG("Parsed link:", { node, parsed: res, origin: url });
  1049. cachedRequestLinks.set(url, res);
  1050. setRealLink(node, res);
  1051. toggleLoadClass(node).remove();
  1052. }
  1053.  
  1054. function handleError(e, url, node, name) {
  1055. if (["URLBrokenError", "TimeoutError", "URLNotExistError", "ResponseError"].includes(e?.message)) cachedRequestLinks.set(url, url);
  1056. if (e?.message === "DuplicateLinksError") handleDuplicateLinksError(url, node);
  1057. else {
  1058. setErrorLink(node);
  1059. toggleLoadClass(node).remove();
  1060. ERROR("antiRedirect_%s: %s %O", name, e?.message, { Node: node, Text: node.textContent, URL: node.href });
  1061. }
  1062. }
  1063.  
  1064. function handleDuplicateLinksError(url, node) {
  1065. const attemptToFindCacheLink = setInterval(() => {
  1066. const cachedRealLinks = cachedRequestLinks.get(url);
  1067. if (cachedRealLinks === null) return;
  1068. if (cachedRealLinks === url) {
  1069. setErrorLink(node);
  1070. toggleLoadClass(node).remove();
  1071. } else {
  1072. DEBUG("Duplicate link:", { node });
  1073. setRealLink(node, cachedRealLinks);
  1074. toggleLoadClass(node).remove();
  1075. }
  1076. clearInterval(attemptToFindCacheLink);
  1077. }, 5e2);
  1078. }
  1079.  
  1080. function toggleLoadClass(node) {
  1081. return { remove: () => IS_DEBUG && node.classList.remove(def.const.loading), add: () => IS_DEBUG && node.classList.add(def.const.loading) };
  1082. }
  1083.  
  1084. function setRealLink(node, url) {
  1085. node.href = url;
  1086. IS_REAL_WEBKIT && node.setAttribute("title", url);
  1087. node.setAttribute("gd-antiredirect-status", "success");
  1088. }
  1089.  
  1090. function setErrorLink(node) {
  1091. node.classList.add(def.notice.linkerror);
  1092. node.setAttribute("gd-antiredirect-status", "failed");
  1093. node.setAttribute("title", `${IS_CHN ? "目前来看,此链接已无法正常访问。" : "At present, this link is no longer accessible."}`);
  1094. }
  1095.  
  1096. function parallelTasks(tasks, maxCount = 3) {
  1097. const taskLength = tasks.length;
  1098. if (taskLength === 0) return;
  1099. let currentIndex = 0;
  1100. let finishedCount = 0;
  1101. const taskCount = Math.min(maxCount, taskLength);
  1102. function executeNextTask() {
  1103. if (currentIndex >= taskLength) return;
  1104. const task = tasks[currentIndex];
  1105. currentIndex++;
  1106. task().then(result => {
  1107. finishedCount++;
  1108. if (finishedCount === taskLength) IS_DEBUG && deBounce({ fn: __console, delay: 1e3, timer: "doTask" })(`doTask`, `(${result ?? cachedRequestLinks.size}) Task Done!`);
  1109. else executeNextTask();
  1110. });
  1111. }
  1112. for (let i = 0; i < taskCount; i++) executeNextTask();
  1113. }
  1114.  
  1115. function reportIDMHijacking() {
  1116. const IDMText = IS_CHN
  1117. ? "PDF文件下载警告:\r\nInternet Download Manager (IDM) 等下载器的劫持可能会造成文件被直接下载。"
  1118. : "PDF File Download Warning:\r\nHijacking of downloaders such as Internet Download Manager (IDM) may cause files to be downloaded directly.";
  1119. __console("warn", IDMText);
  1120. }
  1121.  
  1122. function rejectResponse(response, resolve, reject, url) {
  1123. const resUrl = response.finalUrl || response.responseURL || url;
  1124. if (/^2\d\d$/.test(response.status)) {
  1125. if (response.statusText === "Intercepted by the IDM Advanced Integration") reportIDMHijacking();
  1126. resolve(resUrl);
  1127. } else if (response.status !== 0) {
  1128. if (resUrl === url) reject(new Error("ResponseError"));
  1129. else resolve(resUrl);
  1130. }
  1131. }
  1132.  
  1133. function advancedAntiRedirection(siteName, node, task) {
  1134. const url = node?.href?.replace(/^http:/i, "https:");
  1135. if (!url) return;
  1136. const tasks = {
  1137. Baidu: () =>
  1138. getRealUrl(url, node, siteName, {
  1139. onreadystatechangeFunc: (resolve, reject) => response => {
  1140. if (response.readyState !== 4) return;
  1141. if (response.status === 200) {
  1142. const resUrl = response.finalUrl || response.responseURL || url;
  1143. resolve(resUrl);
  1144. } else rejectResponse(response, resolve, reject, url);
  1145. },
  1146. onerrorFunc: (reject, resolve) => e => {
  1147. if (e.error?.includes("Request was redirected to a not whitelisted URL")) {
  1148. const realUrl = e.error?.toString().match(/Refused to connect to "([^"]*)"/)?.[1];
  1149. if (!realUrl || realUrl.includes("www.baidu.com/search/error")) reject(new Error("URLNotExistError"));
  1150. if (realUrl.toUpperCase().endsWith(".PDF")) reportIDMHijacking();
  1151. resolve(realUrl);
  1152. } else {
  1153. const responseHeader = e.responseHeaders?.match(/Location:\s*([\S]+)/);
  1154. if (responseHeader) resolve(responseHeader[1]);
  1155. else {
  1156. const realURL = e.finalUrl;
  1157. if (realURL && realURL !== url) resolve(realURL);
  1158. else reject(new Error("URLBrokenError"));
  1159. }
  1160. }
  1161. },
  1162. ontimeoutFunc: reject => () => reject(new Error("TimeoutError")),
  1163. }),
  1164. Bing: () =>
  1165. getRealUrl(url, node, siteName, {
  1166. onreadystatechangeFunc: (resolve, reject) => response => {
  1167. if (response.readyState !== 4) return;
  1168. if (response.status === 200) {
  1169. const resText = response.responseText || response.response || "";
  1170. const resUrl = response.finalUrl || response.responseURL || url;
  1171. let res = resText.match(/var\s+u\s*=\s*"([^"]+)"\s*;\s*\r\n/i);
  1172. res = res ? res[1] : resUrl;
  1173. resolve(res);
  1174. } else rejectResponse(response, resolve, reject, url);
  1175. },
  1176. onerrorFunc: reject => () => reject(new Error("URLBrokenError")),
  1177. ontimeoutFunc: reject => () => reject(new Error("TimeoutError")),
  1178. }),
  1179. Sogou: () =>
  1180. getRealUrl(url, node, siteName, {
  1181. onreadystatechangeFunc: (resolve, reject) => response => {
  1182. if (response.readyState !== 4) return;
  1183. if (response.status === 200) {
  1184. const resText = response.responseText || response.response || "";
  1185. const resUrl = response.finalUrl || response.responseURL || url;
  1186. let res = resText.match(/URL\s*=\s*'([^']+)'/);
  1187. res = res ? res[1] : resUrl;
  1188. resolve(res);
  1189. } else rejectResponse(response, resolve, reject, url);
  1190. },
  1191. onerrorFunc: reject => () => reject(new Error("URLBrokenError")),
  1192. ontimeoutFunc: reject => () => reject(new Error("TimeoutError")),
  1193. }),
  1194. So360: () =>
  1195. getRealUrl(url, node, "So360", {
  1196. onreadystatechangeFunc: (resolve, reject) => response => {
  1197. if (response.readyState !== 4) return;
  1198. if (response.status === 200) {
  1199. const resText = response.responseText || response.response || "";
  1200. const resUrl = response.finalUrl || response.responseURL || url;
  1201. let res = resText.match(/URL\s*=\s*'([^']+)'/);
  1202. res = res ? res[1] : resUrl;
  1203. resolve(res);
  1204. } else rejectResponse(response, resolve, reject, url);
  1205. },
  1206. onerrorFunc: reject => () => reject(new Error("URLBrokenError")),
  1207. ontimeoutFunc: reject => () => reject(new Error("TimeoutError")),
  1208. }),
  1209. Toutiao: () =>
  1210. new Promise((resolve, reject) => {
  1211. if (!cachedRequestLinks.has(url)) {
  1212. cachedRequestLinks.set(url, null);
  1213. const parseURL = url.match(/\/search\/jump\?url=([^&]+)&/)?.[1];
  1214. const decodeURL = decodeURI(decodeURIComponent(parseURL ?? "")) || url;
  1215. resolve(decodeURL);
  1216. } else reject(new RangeError("DuplicateLinksError"));
  1217. })
  1218. .then(d => handleSuccess(d, url, node))
  1219. .catch(e => handleError(e, url, node, siteName)),
  1220. Yahoo: () =>
  1221. getRealUrl(url, node, siteName, {
  1222. onreadystatechangeFunc: (resolve, reject) => response => {
  1223. if (response.readyState !== 4) return;
  1224. if (response.status === 200) {
  1225. const resText = response.responseText || response.response || "";
  1226. let res = resText.match(/URL\s*=\s*'([^']+)'/);
  1227. resolve(res?.[1] ?? url);
  1228. } else rejectResponse(response, resolve, reject, url);
  1229. },
  1230. onerrorFunc: reject => () => reject(new Error("URLBrokenError")),
  1231. ontimeoutFunc: reject => () => reject(new Error("TimeoutError")),
  1232. }),
  1233. };
  1234. toggleLoadClass(node).add();
  1235. return tasks[siteName] ?? task;
  1236. }
  1237.  
  1238. /* ANTIADS_FUNCTIONS */
  1239.  
  1240. const siteAdblockHandlers = {
  1241. Google: (siteName, clean) => {
  1242. if (qA("div[class='Z26q7c UK95Uc']:not([data-content-feature])>div[id^='eob']").length > 0) {
  1243. COUNT(`[${siteName}-Anti-Ads-Deep-exp]`);
  1244. qA("div[class='Z26q7c UK95Uc']:not([data-content-feature])").forEach(node => {
  1245. if (qS("div[id^='eob']", node)) {
  1246. node.classList.add(def.var.disappear);
  1247. clean === true && safeRemove(node);
  1248. }
  1249. });
  1250. }
  1251. },
  1252. Bing: (siteName, clean) => {
  1253. if (CUR_HOST_NAME.startsWith("www.")) return;
  1254. if (qA("li.b_algo:not([style*='display:none']) .b_caption>div.b_attribution:not([u])+p[class]").length > 0) {
  1255. COUNT(`[${siteName}-Anti-Ads-Deep-exp]`);
  1256. qA("li.b_algo").forEach(node => {
  1257. if (qS(".b_caption>div.b_attribution:not([u])+p[class]", node)) {
  1258. node.classList.add(def.var.disappear);
  1259. clean === true && safeRemove(node);
  1260. }
  1261. });
  1262. }
  1263. },
  1264. Yandex: (siteName, clean) => {
  1265. const querystring = `.AliceFabPromo-Close,.PopupDesktop-Buttons button.PopupDesktop-Button_type_close`;
  1266. qA(querystring).forEach(item => item.click());
  1267. 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) {
  1268. COUNT(`[${siteName}-Anti-Ads-Deep-exp]`);
  1269. qA("li.serp-item.serp-item_card,li[data-cid][class*='_card']").forEach(node => {
  1270. const adsTxtNode = qS(".Organic-Subtitle span.organic__advLabel", node);
  1271. const _moz_adsTxtNode = qS(".Organic-Subtitle>.Organic-Path~span", node);
  1272. if (["Реклaма", "Ad"].includes(_moz_adsTxtNode?.textContent || adsTxtNode?.textContent)) {
  1273. node.classList.add(def.var.disappear);
  1274. clean === true && safeRemove(node);
  1275. }
  1276. });
  1277. }
  1278. },
  1279. So360: (siteName, clean) => {
  1280. if (qA("ul.section>li span.txt>s, ul.result>li>div.res-recommend-tag").length > 0) {
  1281. COUNT(`[${siteName}-Anti-Ads-Deep-exp]`);
  1282. qA("ul.section>li,ul.result>li").forEach(node => {
  1283. const ads = qS("span[class='txt']>s", node);
  1284. if (!ads?.textContent?.includes("\u5e7f\u544a") && !qS("div.res-recommend-tag", node)) return;
  1285. node.classList.add(def.var.disappear);
  1286. clean === true && safeRemove(node);
  1287. });
  1288. }
  1289. },
  1290. You: (siteName, clean) => {
  1291. if (qA("ul[data-testid='web-results']>li div>div>span[class^='sc-']").length > 0) {
  1292. COUNT(`[${siteName}-Anti-Ads-Deep-exp]`);
  1293. qA("ul[data-testid='web-results']>li").forEach(node => {
  1294. const ads = qS("div>div>span[class^='sc-']", node);
  1295. if (!ads?.textContent?.toLowerCase().includes("ad")) return;
  1296. node.classList.add(def.var.disappear);
  1297. clean === true && safeRemove(node);
  1298. });
  1299. }
  1300. },
  1301. Duckduckgo: () => qS(`button[data-testid="serp-popover-promotion-close"]`)?.click(),
  1302. Yahoo: () => qS(".browserExtensionPromotionWrapper a.btn.notnow")?.click(),
  1303. Ecosia: () => qS("button.banner__close[data-test-id='banner-close'][aria-label='Close']")?.click(),
  1304. };
  1305.  
  1306. function parseAntiAdvertising({ selectors, siteName, isRemoveNodes }) {
  1307. if (selectors && typeof selectors === "string") {
  1308. if (!qS(`#${def.const.rndadvName}`)) {
  1309. COUNT(`[${siteName}-Anti-Ads]`);
  1310. const cssText = `:root :is(${selectors}){display:none!important}`;
  1311. addStyle({ target: document.head, styleId: def.const.rndadvName, media: "all", styleContent: cssText });
  1312. }
  1313. isRemoveNodes === true && qA(selectors).forEach(node => safeRemove(node));
  1314. }
  1315. AdvancedAntiAdvertising(siteName, isRemoveNodes);
  1316. }
  1317.  
  1318. function AdvancedAntiAdvertising(siteName, clean) {
  1319. const AdblockHandler = siteAdblockHandlers[siteName];
  1320. if (typeof AdblockHandler !== "function") return;
  1321. try {
  1322. if (AdblockHandler.length > 0) AdblockHandler(siteName, clean);
  1323. else AdblockHandler();
  1324. } catch (e) {
  1325. ERROR("AdvancedAntiAdvertising:", e.message);
  1326. }
  1327. }
  1328.  
  1329. /* PRELOAD_FUNCTIONS */
  1330.  
  1331. function fetchUpdateResponse(url) {
  1332. return new Promise((resolve, reject) => {
  1333. GMxmlhttpRequest({
  1334. url: url,
  1335. nocache: true,
  1336. headers: { Accept: "*/*", Referer: url },
  1337. method: "GET",
  1338. timeout: 1e4,
  1339. onreadystatechange: response => {
  1340. if (response.readyState !== 4) return;
  1341. if (response.status === 200) {
  1342. const res = response.responseText || response.response;
  1343. resolve({ res, url });
  1344. } else reject();
  1345. },
  1346. onerror: () => reject(),
  1347. ontimeout: () => reject(),
  1348. });
  1349. }).catch(e => Promise.reject(ERROR("fetchUpdateResponse:", e.message)));
  1350. }
  1351.  
  1352. async function fetchAndCacheRemoteIcons(remoteURL) {
  1353. if (!CUR_WINDOW_TOP) return;
  1354. let iconDataURL;
  1355. const iconBase64Data = await cache.get("_remoteicons_");
  1356. try {
  1357. if (!iconBase64Data || setDebuggerMode()) {
  1358. DEBUG("%cRequest remote icon data.", "color:crimson");
  1359. iconDataURL = await requestRemoteIcon(remoteURL);
  1360. iconDataURL && cache.set("_remoteicons_", iconDataURL, 2592e6);
  1361. } else {
  1362. DEBUG("%cGet localCache icon data.", "color:green");
  1363. iconDataURL = iconBase64Data;
  1364. }
  1365. } catch (e) {
  1366. ERROR(`Error: Can't request the icon data.`);
  1367. }
  1368. return iconDataURL;
  1369. }
  1370.  
  1371. function setupScrollButton(selector, className, scrollSize) {
  1372. const targetElement = qS(selector);
  1373. if (!targetElement) return;
  1374. let targetOffsetTop = 0;
  1375. let currentElement = targetElement;
  1376. while (currentElement) {
  1377. targetOffsetTop += currentElement.offsetTop;
  1378. currentElement = currentElement.offsetParent;
  1379. }
  1380. document.addEventListener("scroll", () => {
  1381. const scrollTop = document.documentElement.scrollTop || document.body.scrollTop;
  1382. if (scrollTop > targetOffsetTop + scrollSize) targetElement.classList.add(className);
  1383. else targetElement.classList.remove(className);
  1384. });
  1385. }
  1386.  
  1387. void (async function (getUpdateAddress) {
  1388. const listSite = {
  1389. baidu: {
  1390. siteTypeID: 1,
  1391. siteButtonName: IS_CHN ? "百度一下" : "𝐁𝐚𝐢𝐝𝐮",
  1392. siteNickName: IS_CHN ? "百度 搜索" : "𝐁𝐚𝐢𝐝𝐮.𝐜𝐨𝐦",
  1393. siteHostName: "www.baidu.com",
  1394. webURL: "https://www.baidu.com/s?ie=utf-8&rqlang=cn&wd=",
  1395. imageURL: "https://image.baidu.com/search/index?tn=baiduimage&ps=1&ie=utf-8&word=",
  1396. imageType: ["baiduimage", "baiduimagedetail"],
  1397. splitTypeName: "tn",
  1398. mainSelector: ".s_btn_wr,#sugOut",
  1399. 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:relative;z-index:1999999995;display:inline-block;margin:0 0 0 4px;padding:0;height:40px;vertical-align:top;line-height:40px}#${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;}`,
  1400. resultListProp: { qs: `#content_left>div.c-container[tpl]:not([tpl='recommend_list'],[tpl^="rel-"])`, delay: 10 },
  1401. keywords: "#wrapper_wrapper em,.c-gap-top-small b",
  1402. antiRedirectFn: function () {
  1403. deBounce({ fn: parsingAntiRedirect, delay: 20, timer: "baidu_ar" })(".c-container a[href*='//www.baidu.com/link?url=']", "Baidu", {
  1404. useNewTab: true,
  1405. removeDataSet: true,
  1406. useAdvancedAntiRedirect: true,
  1407. });
  1408. },
  1409. antiAdsFn: function () {
  1410. deBounce({ fn: parseAntiAdvertising, delay: 1e2, timer: "baidu_ad", immed: true })({
  1411. 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"]`,
  1412. siteName: "Baidu",
  1413. isRemoveNodes: true,
  1414. });
  1415. },
  1416. },
  1417. google: {
  1418. siteTypeID: 2,
  1419. siteButtonName: "𝐆𝐨𝐨𝐠𝐥𝐞",
  1420. siteNickName: IS_CHN ? "𝐆𝐨𝐨𝐠𝐥𝐞 搜索" : "𝐆𝐨𝐨𝐠𝐥𝐞.𝐜𝐨𝐦",
  1421. siteHostName: "www.google.com",
  1422. webURL: "https://www.google.com/search?newwindow=1&sca_upv=1&source=hp&q=",
  1423. imageURL: "https://www.google.com/search?newwindow=1&sca_upv=1&source=lnms&udm=2&sa=X&q=",
  1424. imageType: ["isch", "2"],
  1425. splitTypeName: ["tbm", "udm"],
  1426. mainSelector: "form button[type='submit']",
  1427. buttonCssText: `#${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}.${def.const.scrollspan2}{min-height:26px;margin-top:0!important}.${def.const.scrollbars}{display:inline-block;margin:0;height:26px!important;font-weight:400!important;font-size:13px!important}.${def.const.scrollbars2}{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,.15),0 1px 2px rgba(0,0,0,.3);color:#202124}#${def.const.leftButton} input:hover,#${def.const.rightButton} input:hover{background:#93baf9}}`,
  1428. resultListProp: {
  1429. qs: `div.cLjAic.K7khPe[data-hveid^="C"][data-hveid$="AA"],div.g[data-hveid^="C"][data-hveid$="AA"],div.g div[data-hveid^="C"][data-hveid$="AA"]`,
  1430. delay: 10,
  1431. },
  1432. keywords: ".aCOpRe em,.aCOpRe a em,.yXK7lf em,.yXK7lf a em,.st em,.st a em,.c2xzTb b,em.qkunPe",
  1433. antiRedirectFn: function () {
  1434. deBounce({ fn: parsingAntiRedirect, delay: 20, timer: "google_ar" })("#rcnt div[data-hveid^='C'][data-hveid$='AA'] :not(h3.ob5Hkd)>a:not(.k8XOCe)", "Google", {
  1435. useNewTab: true,
  1436. cleanAttributes: ["ping", "onmouseover"],
  1437. removeDataSet: true,
  1438. });
  1439. },
  1440. antiAdsFn: function () {
  1441. deBounce({ fn: parseAntiAdvertising, delay: 1e2, timer: "google_ad", immed: true })({
  1442. selectors: `div[aria-label='\u5e7f\u544a'],div[aria-label='Ads' i],#bottomads,#tvcap`,
  1443. siteName: "Google",
  1444. });
  1445. },
  1446. },
  1447. bing: {
  1448. siteTypeID: 3,
  1449. siteButtonName: "𝐁𝐢𝐧𝐠 ®",
  1450. siteNickName: IS_CHN ? "𝐁𝐢𝐧𝐠 搜索" : "𝐁𝐢𝐧𝐠.𝐜𝐨𝐦",
  1451. siteHostName: "www.bing.com",
  1452. webURL: "https://www.bing.com/search?hta=off&rdr=1&q=",
  1453. imageURL: "https://www.bing.com/images/search?hta=off&first=1&tsc=ImageBasicHover&q=",
  1454. imageType: ["images"],
  1455. splitTypeName: { split: "/", index: 1 },
  1456. mainSelector: `.b_searchboxForm>input[type="hidden"][name="form"]`,
  1457. buttonCssText: `#miniheader #miniheader_searchbox #sb_form_q{width:400px}a,#b_results>li[class] a,#b_results .b_no a{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}}`,
  1458. resultListProp: {
  1459. 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`,
  1460. delay: 10,
  1461. },
  1462. keywords: String(
  1463. Number(getUrlParam("ensearch")) || Number(w.gbCookies.getItem("ENSEARCH")?.match(/[=](\d)/)?.[1])
  1464. ? "strong,.b_no h4,.b_strong,.b_ad .b_adlabel strong,.cbl"
  1465. : "#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"
  1466. ),
  1467. antiRedirectFn: function () {
  1468. GMunsafeWindow.AwayTimeScrollTopPoleRS = false;
  1469. GMunsafeWindow.AwayTimeThreshold = 864000;
  1470. deBounce({ fn: parsingAntiRedirect, delay: 20, timer: "bing_ar" })("#b_content a[href*='.bing.com/ck/a?']:not([role='button'])", "Bing", {
  1471. useNewTab: true,
  1472. cleanAttributes: ["h"],
  1473. useAdvancedAntiRedirect: true,
  1474. });
  1475. deBounce({ fn: parsingAntiRedirect, delay: 30, timer: "bing_ar_cn" })("#b_results>li:not(.b_pag,#mfa_root) a:not([role='button']):not([href*='.bing.com/ck/a?'])", "Bing", {
  1476. useNewTab: true,
  1477. cleanAttributes: ["h"],
  1478. });
  1479. },
  1480. antiAdsFn: function () {
  1481. deBounce({ fn: parseAntiAdvertising, delay: 1e2, timer: "bing_ad", immed: true })({
  1482. 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`,
  1483. siteName: "Bing",
  1484. isRemoveNodes: true,
  1485. });
  1486. },
  1487. },
  1488. duckduckgo: {
  1489. siteTypeID: 4,
  1490. siteButtonName: "𝐃𝐮𝐜𝐤𝐝𝐮𝐜𝐤𝐠𝐨",
  1491. siteNickName: IS_CHN ? "𝐃𝐮𝐜𝐤𝐝𝐮𝐜𝐤𝐠𝐨 搜索" : "𝐃𝐮𝐜𝐤𝐝𝐮𝐜𝐤𝐠𝐨",
  1492. siteHostName: "duckduckgo.com",
  1493. webURL: "https://duckduckgo.com/?k1=-1&kl=wt-wt&kd=-1&ko=1&kn=1&kp=-2&t=h_&ia=web&q=",
  1494. imageURL: "https://duckduckgo.com/?k1=-1&kl=wt-wt&kd=-1&ko=s&kn=1&kp=-2&t=h_&iax=images&ia=images&q=",
  1495. imageType: ["images"],
  1496. splitTypeName: "ia",
  1497. mainSelector: "#search_form",
  1498. 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 rgb(0 0 0/6%);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 rgb(0 0 0/6%);color:var(--theme-col-txt-button-secondary);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(--theme-col-bg-button-secondary-hover);color:var(--theme-col-txt-button-secondary);}#${def.const.leftButton} input:hover,#${def.const.rightButton} input:hover{border:1px solid transparent;background-color:#2950bf!important;color:#fff!important}`,
  1499. resultListProp: { qs: `ol.react-results--main>li[data-layout="organic"],ol.react-results--main>li[data-layout="videos"] div.module--carousel__item`, delay: 10 },
  1500. keywords: "strong, b",
  1501. antiRedirectFn: null,
  1502. antiAdsFn: function () {
  1503. deBounce({ fn: parseAntiAdvertising, delay: 1e2, timer: "ddg_ad", immed: true })({ selectors: `.footer`, siteName: "Duckduckgo", isRemoveNodes: true });
  1504. },
  1505. },
  1506. sogou: {
  1507. siteTypeID: 5,
  1508. siteButtonName: IS_CHN ? "搜狗搜索" : "𝐒𝐨𝐠𝐨𝐮",
  1509. siteNickName: IS_CHN ? "搜狗 搜索" : "𝐒𝐨𝐠𝐨𝐮.𝐜𝐨𝐦",
  1510. siteHostName: "www.sogou.com",
  1511. webURL: "https://www.sogou.com/web?query=",
  1512. imageURL: "https://pic.sogou.com/pics?query=",
  1513. imageType: ["pics", "d"],
  1514. splitTypeName: { split: "/", index: 1 },
  1515. mainSelector: "input[type='submit'].sbtn1,input[type='button'][uigs='search_article'],input[type='submit'].search-btn",
  1516. buttonCssText: `#${def.const.rndButtonID}{position:absolute;top:0;right:0;z-index:1999999995;margin:-1px 0 0;padding:0;width:auto;height:34px;cursor:pointer;-webkit-appearance:none}#${def.const.rndButtonID} *{-webkit-text-stroke:0 transparent!important}#${def.const.leftButton}{display:inline;height:34px}#${def.const.rightButton}{display:inline;height:34px}#${def.const.leftButton} input{margin:0;padding:0 18px!important;height:34px;min-width:100px;border:1px solid #ababab;border-radius:3px;background:#fafafa;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:34px;min-width:100px;border:1px solid #ababab;border-radius:3px;background:#fafafa;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:1px solid #7a7a7a;background:#f2f2f2}.${def.notice.random}_weixin{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}`,
  1517. resultListProp: { qs: `div.results>div.vrwrap,div.results>div.rb`, delay: 10 },
  1518. keywords: "#wrapper em",
  1519. antiRedirectFn: function () {
  1520. deBounce({ fn: parsingAntiRedirect, delay: 20, timer: "sogou_ar" })("#wrapper a[href^='/link?url=']:not([uigs])", "Sogou", {
  1521. useNewTab: true,
  1522. useAdvancedAntiRedirect: true,
  1523. });
  1524. },
  1525. antiAdsFn: function () {
  1526. deBounce({ fn: parseAntiAdvertising, delay: 1e2, timer: "sogou_ad", immed: true })({
  1527. 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])`,
  1528. siteName: "Sogou",
  1529. isRemoveNodes: true,
  1530. });
  1531. },
  1532. },
  1533. wuzhuiso: {
  1534. siteTypeID: 6,
  1535. siteButtonName: IS_CHN ? "无追搜索" : "𝐖𝐮𝐳𝐡𝐮𝐢𝐬𝐨",
  1536. siteNickName: IS_CHN ? "无追 搜索" : "𝐖𝐮𝐳𝐡𝐮𝐢𝐬𝐨.𝐜𝐨𝐦",
  1537. siteHostName: "www.wuzhuiso.com",
  1538. webURL: "https://www.wuzhuiso.com/s?src=tab_www&fr=none&q=",
  1539. imageURL: "https://www.wuzhuiso.com/s?a=image&src=tab_www&fr=none&q=",
  1540. imageType: ["image"],
  1541. splitTypeName: "a",
  1542. mainSelector: "#searchbox span.round>input[type='submit']",
  1543. buttonCssText: `#${def.const.rndButtonID}{position:absolute;left:100%;z-index:1999999995;display:inline-flex;margin:0 0 0 8px;height:46px;justify-content:center;align-items:center}#${def.const.rightButton}{padding:0 0 0 2px}#${def.const.leftButton} input{padding:1px 12px 1px 18px!important;height:46px;min-width:100px;border:1px solid transparent;border-bottom-left-radius:23px;border-top-left-radius:23px;background:linear-gradient(270deg,#2a8cf5,#3f69fd);box-shadow:none;color:#fff;vertical-align:top;font-weight:500;font-size:17px;line-height:100%;cursor:pointer}#${def.const.rightButton} input{padding:1px 18px 1px 12px!important;height:46px;min-width:100px;border:1px solid transparent;border-top-right-radius:23px;border-bottom-right-radius:23px;background:linear-gradient(270deg,#3f69fd,#2a8cf5);box-shadow:none;color:#fff;vertical-align:top;font-weight:500;font-size:17px;line-height:100%;cursor:pointer}#${def.const.leftButton} input:hover,#${def.const.rightButton} input:hover{background:#2d52d1}`,
  1544. resultListProp: { qs: `#main ul.result>li.res-list`, delay: 10 },
  1545. keywords: ".result em,.res-list .g-linkinfo b",
  1546. antiRedirectFn: function () {
  1547. deBounce({ fn: parsingAntiRedirect, delay: 50, timer: "wuzhuiso_ar" })("ul.result>li.res-list a", "Wuzhuiso", { removeDataSet: true });
  1548. },
  1549. antiAdsFn: function () {
  1550. deBounce({ fn: parseAntiAdvertising, delay: 1e2, timer: "wuzhuiso_ad", immed: true })({
  1551. selectors: `#header div.holder>div.tools,ul.result>li.extension-tip,#side>div.right-tip,#side>div.download-browser`,
  1552. siteName: "Wuzhuiso",
  1553. isRemoveNodes: true,
  1554. });
  1555. },
  1556. },
  1557. yandex: {
  1558. siteTypeID: 7,
  1559. siteButtonName: "𝐘𝐚𝐧𝐝𝐞𝐱",
  1560. siteNickName: IS_CHN ? "𝐘𝐚𝐧𝐝𝐞𝐱 搜索" : "𝐘𝐚𝐧𝐝𝐞𝐱.𝐜𝐨𝐦",
  1561. siteHostName: "yandex.com",
  1562. webURL: `https://yandex.${navigator.language === "ru" ? "ru" : "com"}/search/?text=`,
  1563. imageURL: `https://yandex.${navigator.language === "ru" ? "ru" : "com"}/images/search?from=tabbar&family=no&text=`,
  1564. imageType: ["images"],
  1565. splitTypeName: { split: "/", index: 1 },
  1566. mainSelector: "form>div.search2__input,form>div.HeaderDesktopForm-InputWrapper",
  1567. buttonCssText: `#${def.const.rndButtonID}{position:absolute;top:0;right:0;z-index:1999999995;margin:0;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{padding:1px 12px 0 18px!important;height:44px;min-width:100px;border:1px solid transparent;border-bottom-left-radius:10px;border-top-left-radius:10px;background:#fc0;box-shadow:none;color:#000;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:44px;min-width:100px;border:1px solid transparent;border-top-right-radius:10px;border-bottom-right-radius:10px;background:#fc0;box-shadow:none;color:#000;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:#ffd633}@media (prefers-color-scheme: dark){#${def.const.leftButton} input,#${def.const.rightButton} input{background-color:#fdde55}#${def.const.leftButton} input:hover,#${def.const.rightButton} input:hover{background-color:#fdc93d}}`,
  1568. resultListProp: { qs: "#search-result>li[class*='_card'][data-cid]", delay: 10 },
  1569. keywords: ".OrganicTitleContentSpan b,.OrganicTextContentSpan b",
  1570. antiRedirectFn: function () {
  1571. deBounce({ fn: parsingAntiRedirect, delay: 20, timer: "yandex_ar" })("#search-result>li.serp-item a", "Yandex", {
  1572. useNewTab: true,
  1573. removeDataSet: true,
  1574. });
  1575. },
  1576. antiAdsFn: function () {
  1577. deBounce({ fn: parseAntiAdvertising, delay: 1e2, timer: "yandex_ad", immed: true })({
  1578. selectors: `#distr-pcode-container>div,div.HeaderDesktopActions-Distribution.HeaderDesktopActions-Item,div[tabindex][class*='location_right-bottom'],a.HeaderDesktopActions-MarketCart,span.distr-nav,div.market-cart`,
  1579. siteName: "Yandex",
  1580. isRemoveNodes: true,
  1581. });
  1582. },
  1583. },
  1584. so360: {
  1585. siteTypeID: 8,
  1586. siteButtonName: IS_CHN ? "𝟑𝟔𝟎搜索" : "𝟑𝟔𝟎𝐬𝐨",
  1587. siteNickName: IS_CHN ? "𝟑𝟔𝟎 搜索" : "𝐰𝐰𝐰.𝐬𝐨.𝐜𝐨𝐦",
  1588. siteHostName: "www.so.com",
  1589. webURL: "https://www.so.com/s?ie=utf-8&q=",
  1590. imageURL: "https://image.so.com/i?q=",
  1591. imageType: ["i", "view"],
  1592. splitTypeName: { split: "/", index: 1 },
  1593. mainSelector: "input[type='submit'][value='搜索'],button[type='submit'][class~='so-search__button']",
  1594. 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}`,
  1595. resultListProp: { qs: `ul.result>li.res-list`, delay: 10 },
  1596. keywords: "em,#mohe-newdict_dict .mh-exsentence b",
  1597. antiRedirectFn: function () {
  1598. deBounce({ fn: parsingAntiRedirect, delay: 20, timer: "so360_ar" })(".res-list a[href*='//www.so.com/link?m=']", "So360", {
  1599. useNewTab: true,
  1600. removeDataSet: true,
  1601. useAdvancedAntiRedirect: true,
  1602. });
  1603. },
  1604. antiAdsFn: function () {
  1605. deBounce({ fn: parseAntiAdvertising, delay: 1e2, timer: "so360_ad", immed: true })({
  1606. 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_"]`,
  1607. siteName: "So360",
  1608. isRemoveNodes: true,
  1609. });
  1610. },
  1611. },
  1612. toutiao: {
  1613. siteTypeID: 9,
  1614. siteButtonName: IS_CHN ? "搜头条" : "𝐓𝐨𝐮𝐭𝐢𝐚𝐨",
  1615. siteNickName: IS_CHN ? "头条 搜索" : "𝐬𝐨.𝐭𝐨𝐮𝐭𝐢𝐚𝐨.𝐜𝐨𝐦",
  1616. siteHostName: "so.toutiao.com",
  1617. webURL: "https://so.toutiao.com/search?dvpf=pc&keyword=",
  1618. imageURL: "https://so.toutiao.com/search?dvpf=pc&pd=atlas&from=gallery&keyword=",
  1619. imageType: ["atlas"],
  1620. splitTypeName: "pd",
  1621. mainSelector: "div[class^='search'][data-log-click]",
  1622. 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,.7);color:#fff}`,
  1623. resultListProp: { qs: `div.s-result-list>div.result-content[data-i]`, delay: 10 },
  1624. keywords: "em",
  1625. antiRedirectFn: function () {
  1626. deBounce({ fn: parsingAntiRedirect, delay: 20, timer: "toutiao_ar" })(".main a[href*='/search/jump?url=']", "Toutiao", {
  1627. useNewTab: true,
  1628. useAdvancedAntiRedirect: true,
  1629. });
  1630. },
  1631. antiAdsFn: null,
  1632. },
  1633. kaifa: {
  1634. siteTypeID: 10,
  1635. siteButtonName: IS_CHN ? "百度开发者" : "𝐃𝐞𝐯.𝐁𝐚𝐢𝐝𝐮",
  1636. siteNickName: IS_CHN ? "百度开发者 搜索" : "𝐃𝐞𝐯.𝐁𝐚𝐢𝐝𝐮",
  1637. siteHostName: "kaifa.baidu.com",
  1638. webURL: "https://kaifa.baidu.com/searchPage?module=SEARCH&wd=",
  1639. imageURL: "https://kaifa.baidu.com/searchPage?module=SUG&wd=",
  1640. imageType: [null],
  1641. splitTypeName: "",
  1642. mainSelector: "div#search-box-container .ant-input-group-addon",
  1643. 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)}`,
  1644. resultListProp: { qs: `ul.ant-list-items>li.ant-list-item`, delay: 10 },
  1645. keywords: "mark",
  1646. antiRedirectFn: null,
  1647. antiAdsFn: function () {
  1648. deBounce({ fn: parseAntiAdvertising, delay: 1e2, timer: "kaifa_ad", immed: true })({
  1649. selectors: `#reward-entry`,
  1650. siteName: "Kaifa",
  1651. isRemoveNodes: true,
  1652. });
  1653. },
  1654. },
  1655. ecosia: {
  1656. siteTypeID: 11,
  1657. siteButtonName: "𝐄𝐜𝐨𝐬𝐢𝐚",
  1658. siteNickName: IS_CHN ? "𝐄𝐜𝐨𝐬𝐢𝐚 搜索" : "𝐄𝐜𝐨𝐬𝐢𝐚.𝐨𝐫𝐠",
  1659. siteHostName: "www.ecosia.org",
  1660. webURL: "https://www.ecosia.org/search?method=index&q=",
  1661. imageURL: "https://www.ecosia.org/images?q=",
  1662. imageType: ["images"],
  1663. splitTypeName: { split: "/", index: 1 },
  1664. mainSelector: "form[role='search'][class~='search-form'][data-test-id='main-header-search-form']",
  1665. buttonCssText: `#${def.const.rndButtonID}{position:relative;z-index:1999999995;display:inline-block;margin-left:-12px;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)}`,
  1666. resultListProp: {
  1667. qs: `section.mainline>div>div[data-test-id="mainline-result-web"],div.mainline__result[data-test-id="videos-snippet"] ul>li[data-test-id="videos-snippet-item"]`,
  1668. delay: Infinity,
  1669. },
  1670. keywords: "",
  1671. antiRedirectFn: function () {
  1672. ["adBlockNoticeDismissed", "personalCounterTooltipSearch"].forEach(item => w.localStorage.setItem(item, 1));
  1673. deBounce({
  1674. fn: option => {
  1675. if (w.gbCookies.getItem("ECFG")?.includes(":nt=1:")) return;
  1676. w.gbCookies.setItem(option);
  1677. refresh();
  1678. },
  1679. timer: "ecosia_cookie",
  1680. immed: true,
  1681. once: true,
  1682. })({
  1683. sKey: "ECFG",
  1684. 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`,
  1685. sEnd: Infinity,
  1686. sDomain: ".ecosia.org",
  1687. sPath: "/",
  1688. sSomeSite: "Lax",
  1689. });
  1690. },
  1691. antiAdsFn: function () {
  1692. deBounce({ fn: parseAntiAdvertising, delay: 20, timer: "ecosia_ad", immed: true })({
  1693. selectors: `div.main-header__install-cta,div.main-footer__card-container,div.personal-counter__tooltip,div.cookie-wrapper,div.mainline__footer>a[data-test-id='chat-entry']`,
  1694. siteName: "Ecosia",
  1695. });
  1696. },
  1697. },
  1698. yahoo: {
  1699. siteTypeID: 12,
  1700. siteButtonName: "𝐘𝐚𝐡𝐨𝐨",
  1701. siteNickName: IS_CHN ? "𝐘𝐚𝐡𝐨𝐨 搜索" : "𝐬𝐞𝐚𝐫𝐜𝐡.𝐘𝐚𝐡𝐨𝐨",
  1702. siteHostName: "search.yahoo.com",
  1703. webURL: "https://search.yahoo.com/search?p=",
  1704. imageURL: "https://images.search.yahoo.com/search/images?p=",
  1705. imageType: ["images"],
  1706. splitTypeName: () => w.location.hostname.split(".")[0],
  1707. mainSelector: "#hd div.sbx form#sf,header.hd form#sf #sh section#sbx",
  1708. 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{margin:2px 0;padding:1px 12px 1px 18px!important;height:44px;min-width:100px;border:2px solid transparent;border-bottom-left-radius:100px;border-top-left-radius:100px;background:#4285f5;color:#fff;vertical-align:top;font-weight:500;font-size:16px!important;line-height:100%;cursor:pointer}#${def.const.rightButton} input{margin:2px 0;padding:1px 18px 1px 12px!important;height:44px;min-width:100px;border:2px solid transparent;border-top-right-radius:100px;border-bottom-right-radius:100px;background:#4285f5;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:2px solid transparent;background:#1967d2;color:#fff}`,
  1709. resultListProp: { qs: `#web>ol>li`, delay: 10 },
  1710. keywords: "strong",
  1711. antiRedirectFn: function () {
  1712. deBounce({ fn: parsingAntiRedirect, delay: 20, timer: "yahoo_ar" })("#main ol a[href^='https://r.search.yahoo.com/_ylt=']", "Yahoo", {
  1713. useNewTab: true,
  1714. useAdvancedAntiRedirect: true,
  1715. });
  1716. },
  1717. antiAdsFn: function () {
  1718. deBounce({ fn: parseAntiAdvertising, delay: 1e2, timer: "yahoo_ad", immed: true })({
  1719. selectors: `#main ol.searchCenterBottomAds,#main ol.searchCenterTopAds`,
  1720. siteName: "Yahoo",
  1721. });
  1722. },
  1723. },
  1724. you: {
  1725. siteTypeID: 13,
  1726. siteButtonName: "𝐘𝐨𝐮 ®",
  1727. siteNickName: IS_CHN ? "𝐘𝐨𝐮 搜索" : "𝐘𝐨𝐮.𝐜𝐨𝐦",
  1728. siteHostName: "you.com",
  1729. webURL: "https://you.com/search?fromSearchBar=true&q=",
  1730. imageURL: "https://you.com/search?fromSearchBar=true&tbm=isch&q=",
  1731. imageType: ["isch"],
  1732. splitTypeName: "tbm",
  1733. mainSelector: "button[data-testid='qb_submit_button']",
  1734. buttonCssText: `#${def.const.rndButtonID}{position:relative;z-index:999;display:inline;margin:-8px 0 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:44px}#${def.const.rndButtonID} #${def.const.rightButton}{display:inline-block;margin-left:-2px;height:44px}#${def.const.leftButton} input{margin:0;padding:0;height:44px;min-width:110px;border:1px solid #4a72f5;border-bottom-left-radius:12px;border-top-left-radius:12px;background-color:#4a72f5;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;height:44px;min-width:110px;border:1px solid #4a72f5;border-top-right-radius:12px;border-bottom-right-radius:12px;background-color:#4a72f5;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 #7897fc;background-color:#7897fc;color:#fff}@media (prefers-color-scheme: dark){#${def.const.leftButton} input,#${def.const.rightButton} input{border:1px solid #668aff;background-color:#668aff}#${def.const.leftButton} input:hover,#${def.const.rightButton} input:hover{background:#7897fc;color:#3c3c3e;font-weight:600}}`,
  1735. resultListProp: {
  1736. qs: `div[data-testid="app-mainline"]>div[data-eventappname][data-testid]>ul[data-testid="web-results"],div[data-testid="Github Issues-app"]>ul>li`,
  1737. delay: 10,
  1738. },
  1739. keywords: `div[data-testid="app-mainline"] p strong,div[data-testid="app-mainline"] p b`,
  1740. antiRedirectFn: function () {
  1741. deBounce({
  1742. fn: parameters => parameters.forEach(item => localStorage.setItem(item, true)),
  1743. timer: "you_set",
  1744. immed: true,
  1745. once: true,
  1746. })(["openLinksInNewTabs", "hasSeenP13nAnnouncement", "hasUserClosedExtensionModal"]);
  1747. },
  1748. antiAdsFn: function () {
  1749. deBounce({ fn: parseAntiAdvertising, delay: 1e2, timer: "you_ad", immed: true })({ siteName: "You" });
  1750. },
  1751. },
  1752. startpage: {
  1753. siteTypeID: 14,
  1754. siteButtonName: "𝐒𝐭𝐚𝐫𝐭𝐩𝐚𝐠𝐞",
  1755. siteNickName: IS_CHN ? "𝐒𝐭𝐚𝐫𝐭𝐩𝐚𝐠𝐞 搜索" : "𝐒𝐭𝐚𝐫𝐭𝐩𝐚𝐠𝐞.𝐜𝐨𝐦",
  1756. siteHostName: "www.startpage.com",
  1757. webURL: `https://www.startpage.com/sp/search?t=device&segment=startpage.${brand.toLowerCase()}&cat=web&query=`,
  1758. imageURL: `https://www.startpage.com/sp/search?t=device&segment=startpage.${brand.toLowerCase()}&cat=images&query=`,
  1759. imageType: ["images"],
  1760. splitTypeName: "cat",
  1761. mainSelector: "#search[role='search'] button.search-btn",
  1762. buttonCssText: `#${def.const.rndButtonID}{position:relative;z-index:999;display:inline-block;margin:-11px 4px 0 .5rem;height:20px}#${def.const.rndButtonID} *{text-shadow:none!important;-webkit-text-stroke:0 transparent!important}#${def.const.rndButtonID} #${def.const.leftButton}{display:inline-block;height:30px}#${def.const.rndButtonID} #${def.const.rightButton}{display:inline-block;margin-left:0;height:30px}#${def.const.leftButton} input{margin:0;padding:1px 10px 1px 20px!important;height:30px;min-width:85px;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:1px 20px 1px 10px!important;height:30px;min-width:85px;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}}`,
  1763. resultListProp: { qs: `#main>.w-gl>div.result`, delay: Infinity },
  1764. keywords: `.result b`,
  1765. antiRedirectFn: function () {
  1766. deBounce({
  1767. fn: option => {
  1768. const cookies = w.gbCookies.getItem("preferences");
  1769. if (cookies?.includes("disable_open_in_new_windowEEE0") && cookies?.includes("enable_post_methodEEE0")) return;
  1770. w.gbCookies.setItem(option);
  1771. refresh();
  1772. },
  1773. timer: "startpage_cookie",
  1774. immed: true,
  1775. once: true,
  1776. })({
  1777. sKey: "preferences",
  1778. sValue: `connect_to_serverEEE0N1Ndate_timeEEEworldN1Ndisable_family_filterEEE1N1Ndisable_open_in_new_windowEEE0N1Nenable_post_methodEEE0N1Nenable_proxy_safety_suggestEEE1N1Nenable_stay_controlEEE0N1Ninstant_answersEEE1N1Nlang_homepageEEEs/device/enN1NlanguageEEEenglishN1Nlanguage_uiEEEenglishN1Nnum_of_resultsEEE10N1Nsearch_results_regionEEEallN1NsuggestionsEEE1N1Nwt_unitEEEcelsius`,
  1779. sEnd: Infinity,
  1780. sDomain: ".startpage.com",
  1781. sPath: "/",
  1782. sSecure: true,
  1783. });
  1784. deBounce({ fn: parsingAntiRedirect, timer: "startpage_ar", delay: 50 })("section.w-gl>div.w-gl__result a", "Startpage", { removeDataSet: true });
  1785. },
  1786. antiAdsFn: function () {
  1787. deBounce({ fn: parseAntiAdvertising, delay: 1e2, timer: "startpage_ad", immed: true })({
  1788. selectors: `section.a-gl-tp,div.widget-install-legacy,div.mainline-results>div.block-display`,
  1789. siteName: "Startpage",
  1790. });
  1791. },
  1792. },
  1793. brave: {
  1794. siteTypeID: 15,
  1795. siteButtonName: "𝐁𝐫𝐚𝐯𝐞",
  1796. siteNickName: IS_CHN ? "𝐁𝐫𝐚𝐯𝐞 搜索" : "𝐬𝐞𝐚𝐫𝐜𝐡.𝐁𝐫𝐚𝐯𝐞",
  1797. siteHostName: "search.brave.com",
  1798. webURL: "https://search.brave.com/search?source=web&q=",
  1799. imageURL: "https://search.brave.com/images?source=web&spellcheck=0&q=",
  1800. imageType: ["images"],
  1801. splitTypeName: { split: "/", index: 1 },
  1802. mainSelector: "#submit-button",
  1803. buttonCssText: `#${def.const.rndButtonID}{position:relative;z-index:999;display:inline;margin:0 -3px 0 3px;padding:4px 0px;width:max-content;height:100%;order:6}#${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:4px 10px!important;height:38px;min-width:85px;border:1px solid var(--color-gray-20);border-bottom-left-radius:12px;border-top-left-radius:12px;background:var(--search-bgd-04);color:var(--color-primary);vertical-align:top;font-weight:600;font-size:14px!important;line-height:14px;cursor:pointer}#${def.const.rightButton} input{margin:0;padding:4px 10px!important;height:38px;min-width:85px;border:1px solid var(--color-gray-20);border-top-right-radius:12px;border-bottom-right-radius:12px;background:var(--search-bgd-04);color:var(--color-primary);vertical-align:top;font-weight:600;font-size:14px!important;line-height:14px;cursor:pointer}#${def.const.leftButton} input:hover,#${def.const.rightButton} input:hover{box-shadow:0 0 1px #a4a5bb;color:var(--color-text-secondary,#fff);background:rgba(164, 165, 187, 0.2);}`,
  1804. resultListProp: { qs: `#results>div.snippet[data-type="web"]`, delay: 10 },
  1805. keywords: `.snippet-content strong`,
  1806. antiRedirectFn: function () {
  1807. localStorage.setItem("app.discussionsIntroduced", true);
  1808. deBounce({
  1809. fn: option => {
  1810. if (w.gbCookies.getItem("olnt") === "1") return;
  1811. w.gbCookies.setItem(option);
  1812. refresh();
  1813. },
  1814. timer: "brave_cookie",
  1815. immed: true,
  1816. once: true,
  1817. })({ sKey: "olnt", sValue: "1", sEnd: Infinity, sDomain: "search.brave.com", sPath: "/", sSameSite: "Lax", sSecure: true });
  1818. deBounce({ fn: parsingAntiRedirect, delay: 20, timer: "brave_ar" })("#results>div#search-elsewhere a", "Brave", {
  1819. useNewTab: true,
  1820. forceNewTab: true,
  1821. removeDataSet: true,
  1822. });
  1823. },
  1824. antiAdsFn: null,
  1825. },
  1826. yep: {
  1827. siteTypeID: 16,
  1828. siteButtonName: "𝐘𝐞𝐩 ®",
  1829. siteNickName: IS_CHN ? "𝐘𝐞𝐩 搜索" : "𝐘𝐞𝐩.𝐜𝐨𝐦",
  1830. siteHostName: "yep.com",
  1831. webURL: "https://yep.com/web?q=",
  1832. imageURL: "https://yep.com/images?q=",
  1833. imageType: ["images"],
  1834. splitTypeName: { split: "/", index: 1 },
  1835. mainSelector: `form div[class$="-addon"]`,
  1836. 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:-2px;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)}`,
  1837. resultListProp: { qs: `div[class*='-results']>div>div>div[class*='-card']`, delay: 10 },
  1838. keywords: ``,
  1839. antiRedirectFn: function () {
  1840. deBounce({ fn: parsingAntiRedirect, delay: 20, timer: "yep_ar" })(
  1841. "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",
  1842. "Yep",
  1843. { useNewTab: true, forceNewTab: true, cleanAttributes: ["referrerpolicy"] }
  1844. );
  1845. },
  1846. antiAdsFn: null,
  1847. },
  1848. swisscows: {
  1849. siteTypeID: 17,
  1850. siteButtonName: "𝐒𝐰𝐢𝐬𝐬𝐜𝐨𝐰𝐬",
  1851. siteNickName: IS_CHN ? "𝐒𝐰𝐢𝐬𝐬𝐜𝐨𝐰𝐬 搜索" : "𝐒𝐰𝐢𝐬𝐬𝐜𝐨𝐰𝐬.𝐜𝐨𝐦",
  1852. siteHostName: "swisscows.com",
  1853. webURL: "https://swisscows.com/en/web?query=",
  1854. imageURL: "https://swisscows.com/en/images?query=",
  1855. imageType: ["images"],
  1856. splitTypeName: { split: "/", index: 2 },
  1857. mainSelector: "form.form-search>button.search-submit",
  1858. buttonCssText: `#header .form-search{max-width:35em}#${def.const.rndButtonID}{position:absolute;top:0;z-index:112;display:block;margin:0;padding:0;height:2.8em}#${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:-2px;height:2.5em}#${def.const.leftButton} input{margin:0;padding:4px 12px!important;height:2.8em;min-width:95px;border:1px solid #bfc8cd;border-bottom-left-radius:1.25em;border-top-left-radius:1.25em;background:transparent;box-shadow:0 0 2px #a4a5bb;color:#252b3b;vertical-align:middle;font-weight:600;font-size:14px!important;line-height:100%;cursor:pointer}#${def.const.rightButton} input{margin:0;padding:4px 12px!important;height:2.8em;min-width:95px;border:1px solid #bfc8cd;border-top-right-radius:1.25em;border-bottom-right-radius:1.25em;background:transparent;box-shadow:0 0 2px #a4a5bb;color:#252b3b;vertical-align:middle;font-weight:600;font-size:14px!important;line-height:100%;cursor:pointer}#${def.const.leftButton} input:hover,#${def.const.rightButton} input:hover{background:#edf0f3;color:#df5d5d}@media (prefers-color-scheme: dark){#${def.const.leftButton} input,#${def.const.rightButton} input{border:1px solid #99a4ab;background:#252b3b;color:#99a4ab}#${def.const.leftButton} input:hover,#${def.const.rightButton} input:hover{background:#353b3e;color:#df5d5d}}`,
  1859. resultListProp: { qs: `.web-results>article.item-web`, delay: 10 },
  1860. keywords: `.web-results b`,
  1861. antiRedirectFn: function () {
  1862. deBounce({ fn: parsingAntiRedirect, delay: 20, timer: "swisscows_ar" })(".web-results>article.item-web a,.web-results>div.widget a:not(.widget-button)", "Swisscows", {
  1863. useNewTab: true,
  1864. forceNewTab: true,
  1865. });
  1866. },
  1867. antiAdsFn: function () {
  1868. deBounce({ fn: parseAntiAdvertising, delay: 1e2, timer: "swisscows_ad", immed: true })({
  1869. selectors: `#header :is(.badge-tg,.badge-vpn,.badge-email)`,
  1870. siteName: "Swisscows",
  1871. });
  1872. },
  1873. },
  1874. other: { siteTypeID: 0 },
  1875. };
  1876.  
  1877. const newSiteType = {
  1878. BAIDU: listSite.baidu.siteTypeID,
  1879. GOOGLE: listSite.google.siteTypeID,
  1880. BING: listSite.bing.siteTypeID,
  1881. DUCKDUCKGO: listSite.duckduckgo.siteTypeID,
  1882. SOGOU: listSite.sogou.siteTypeID,
  1883. WUZHUISO: listSite.wuzhuiso.siteTypeID,
  1884. YANDEX: listSite.yandex.siteTypeID,
  1885. SO360: listSite.so360.siteTypeID,
  1886. TOUTIAO: listSite.toutiao.siteTypeID,
  1887. KAIFA: listSite.kaifa.siteTypeID,
  1888. ECOSIA: listSite.ecosia.siteTypeID,
  1889. YAHOO: listSite.yahoo.siteTypeID,
  1890. YOU: listSite.you.siteTypeID,
  1891. STARTPAGE: listSite.startpage.siteTypeID,
  1892. BRAVE: listSite.brave.siteTypeID,
  1893. YEP: listSite.yep.siteTypeID,
  1894. SWISSCOWS: listSite.swisscows.siteTypeID,
  1895. OTHERS: listSite.other.siteTypeID,
  1896. };
  1897.  
  1898. const engineMap = {
  1899. "^(w+\\.)?google\\.[a-z.]{2,6}$": { siteType: newSiteType.GOOGLE, site: listSite.google },
  1900. "kaifa\\.baidu\\.com$": { siteType: newSiteType.KAIFA, site: listSite.kaifa },
  1901. "\\.baidu\\.com$": { siteType: newSiteType.BAIDU, site: listSite.baidu },
  1902. "\\.bing\\.com$": { siteType: newSiteType.BING, site: listSite.bing },
  1903. "duckduckgo\\.com$": { siteType: newSiteType.DUCKDUCKGO, site: listSite.duckduckgo },
  1904. "\\.sogou\\.com$": { siteType: newSiteType.SOGOU, site: listSite.sogou },
  1905. "www\\.wuzhuiso\\.com$": { siteType: newSiteType.WUZHUISO, site: listSite.wuzhuiso },
  1906. "yandex\\.com$": { siteType: newSiteType.YANDEX, site: listSite.yandex },
  1907. "yandex\\.ru$": { siteType: newSiteType.YANDEX, site: listSite.yandex },
  1908. "\\.so\\.com$": { siteType: newSiteType.SO360, site: listSite.so360 },
  1909. "so\\.toutiao\\.com$": { siteType: newSiteType.TOUTIAO, site: listSite.toutiao },
  1910. "www\\.ecosia\\.org$": { siteType: newSiteType.ECOSIA, site: listSite.ecosia },
  1911. "search\\.yahoo\\.com$": { siteType: newSiteType.YAHOO, site: listSite.yahoo },
  1912. "you\\.com$": { siteType: newSiteType.YOU, site: listSite.you },
  1913. "startpage\\.com$": { siteType: newSiteType.STARTPAGE, site: listSite.startpage },
  1914. "search\\.brave\\.com$": { siteType: newSiteType.BRAVE, site: listSite.brave },
  1915. "yep\\.com$": { siteType: newSiteType.YEP, site: listSite.yep },
  1916. "swisscows\\.com$": { siteType: newSiteType.SWISSCOWS, site: listSite.swisscows },
  1917. };
  1918.  
  1919. const searchProperties = {
  1920. inputArray: [
  1921. 'input#kw[name^="w"]',
  1922. 'input[name="q"]:not([type="hidden"])',
  1923. 'input[name="text"][type="text"]',
  1924. 'input#q[name="query"]',
  1925. 'input[name="query"][class$="query"]:not([id*="bottom"])',
  1926. 'input.input-search[type="search"]',
  1927. 'input[type="search"][class*="input"]',
  1928. '#search-box-container input[class~="ant-input"]',
  1929. 'input#yschsp[name="p"]',
  1930. 'textarea[jsaction][name="q"]',
  1931. "textarea#search-input-textarea",
  1932. ],
  1933. searchKeys: ["wd", "word", "query", "q", "text", "keyword", "p"],
  1934. };
  1935.  
  1936. const { currentSite, listCurrentSite } = findCurrentSite();
  1937. const { currentSiteName, allSiteURIs } = updateSiteInformation();
  1938. const { backgroundColor: bgc, foregroundColor: fgc } = customColor;
  1939. const updateDetectionAddress = getGlobalParameter() && getUpdateAddress();
  1940. const yandexIconsAPIUrl = `${def.url.yandexIcon}/${allSiteURIs}?size=32&stub=1`;
  1941. const iconBase64Data = await fetchAndCacheRemoteIcons(yandexIconsAPIUrl);
  1942.  
  1943. /* DEFINE_GLOBAL_STYLES */
  1944.  
  1945. def.const.style = String(
  1946. `.${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:10000059!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:10000055!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;margin:18px 0 28px 10px!important;padding:10px 2px!important;font:normal 400 14px/100% 'Times New Roman',system-ui,-apple-system,BlinkMacSystemFont,serif!important;-webkit-text-stroke:0 transparent!important;line-height:100%!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}` +
  1947. `.${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;}.${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;}.${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;}.${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}.${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}` +
  1948. `.${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}` +
  1949. `.${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:10000051}.${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}` +
  1950. `.${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,.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,.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}` +
  1951. `.${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:red}.${def.notice.noticeX} .${def.notice.configuration} span.${def.notice.favicon}{margin:0 6px 0 0;width:24px;height:24px}.${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}` +
  1952. `.${def.notice.noticeX} .${def.notice.configuration} .${def.notice.settingList} li>div{font:normal 700 14px/150% 'Microsoft YaHei UI',Helvetica Neue,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:crimson!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!important;padding:5px!important;max-height:423px;width:100%;min-height:280px;outline:0!important;border:1px solid #bbb;border-radius:6px;white-space:pre;font:normal 400 14px/150% monospace,system-ui,-apple-system,BlinkMacSystemFont,sans-serif!important;resize:vertical;overscroll-behavior:contain;word-break:keep-all!important;cursor:auto}.${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}` +
  1953. `.${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 0 0 10px;color:#666;font-weight:500;cursor:pointer}#${def.notice.random}_clear:hover{color:red}#${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:grey!important;text-decoration-line:line-through!important;text-decoration-color:red!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}` +
  1954. `.${def.notice.card}__input{position:absolute;display:block;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;}.${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:crimson}.${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}` +
  1955. `.${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)}.${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}`
  1956. );
  1957.  
  1958. def.const.iconbg = iconBase64Data ? `url('${iconBase64Data}')` : `url('${def.url.backupIcon}'),url('${yandexIconsAPIUrl}')`;
  1959. def.const.button = `${currentSite.siteTypeID === newSiteType.GOOGLE ? "<span jsname='s1VaRe' class='ACRAdd M2vV3'></span>" : ""}
  1960. <span id="${def.const.leftButton}" sn="${selectedSite[0].siteTypeID}">
  1961. <input type="button" title="${selectedSite[0].siteNickName}" value="${selectedSite[0].siteButtonName}"/>
  1962. </span>
  1963. <span id="${def.const.rightButton}" sn="${selectedSite[1].siteTypeID}">
  1964. <input type="button" title="${selectedSite[1].siteNickName}" value="${selectedSite[1].siteButtonName}"/>
  1965. </span>`;
  1966. def.const.hlstyle = listCurrentSite.keywords ? `${listCurrentSite.keywords}{background-color:${bgc}!important;color:${fgc}!important;font-weight:600!important}` : ``;
  1967. def.const.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.const.iconbg};background-repeat:no-repeat;}`;
  1968.  
  1969. function getQueryString() {
  1970. let returnValue;
  1971. const { inputArray, searchKeys } = searchProperties;
  1972. const checkResult = qA(inputArray.join()).Some((item, index) => {
  1973. returnValue = item.value;
  1974. DEBUG("QueryString[INPUT]:", { current: returnValue, index });
  1975. return returnValue;
  1976. });
  1977. if (!checkResult) {
  1978. for (let i = 0; i < searchKeys.length; i++) {
  1979. const queryString = getUrlParam(searchKeys[i]);
  1980. if (!queryString) continue;
  1981. returnValue = queryString.replace(/\+/g, " ");
  1982. DEBUG("QueryString[URL]:", { queryKey: searchKeys[i], returnValue });
  1983. break;
  1984. }
  1985. }
  1986. return encodeURIComponent(returnValue ?? "");
  1987. }
  1988.  
  1989. function checkIndexPage() {
  1990. return currentSite.siteTypeID === newSiteType.DUCKDUCKGO ? !getUrlParam("q") : w.location.pathname === "/";
  1991. }
  1992.  
  1993. function getSecurityPolicy() {
  1994. return (
  1995. (currentSite.siteTypeID === newSiteType.GOOGLE && (/^(lcl|flm|fin)$/.test(def.var.searchType) || getUrlParam("csui") === "1")) ||
  1996. (currentSite.siteTypeID === newSiteType.BING && (/^maps$/.test(def.var.searchType) || getQueryString("showconv") === "1")) ||
  1997. (currentSite.siteTypeID === newSiteType.BAIDU && /^(news|vsearch)$/.test(def.var.searchType)) ||
  1998. (currentSite.siteTypeID === newSiteType.SOGOU && /^(fanyi|hanyu|as)/.test(w.location.hostname)) ||
  1999. (currentSite.siteTypeID === newSiteType.DUCKDUCKGO && /^maps$/.test(getUrlParam("iaxm"))) ||
  2000. (currentSite.siteTypeID === newSiteType.YANDEX && w.location.pathname.includes("/direct")) ||
  2001. (currentSite.siteTypeID === newSiteType.YOU && /^youchat$/.test(def.var.searchType))
  2002. );
  2003. }
  2004.  
  2005. function findCurrentSite() {
  2006. let currentSite, listCurrentSite;
  2007. const hostname = w.location.hostname;
  2008. for (const regex in engineMap) {
  2009. if (hasOwnProp.call(engineMap, regex) && new RegExp(regex).test(hostname)) {
  2010. const { siteType, site } = engineMap[regex];
  2011. currentSite = selectedEngine.includes(siteType) ? site : listSite.other;
  2012. listCurrentSite = site;
  2013. break;
  2014. }
  2015. }
  2016. return { currentSite, listCurrentSite };
  2017. }
  2018.  
  2019. function updateSiteInformation() {
  2020. let currentSiteName = "";
  2021. let allSiteURIs = "";
  2022. for (let site in listSite) {
  2023. if (hasOwnProp.call(listSite, site)) {
  2024. if (listSite[site].siteTypeID !== newSiteType.OTHERS) {
  2025. allSiteURIs += listSite[site].siteHostName + ";";
  2026. }
  2027. if (listSite[site].siteTypeID === listCurrentSite.siteTypeID) {
  2028. currentSiteName = site;
  2029. }
  2030. if (listSite[site].siteTypeID !== currentSite.siteTypeID && selectedEngine.includes(Number(listSite[site].siteTypeID))) {
  2031. selectedSite.length < 2 && selectedSite.push(listSite[site]);
  2032. }
  2033. }
  2034. }
  2035. return { currentSiteName, allSiteURIs };
  2036. }
  2037.  
  2038. function getGlobalParameter() {
  2039. def.var.indexPage = checkIndexPage();
  2040. def.var.queryString = getQueryString();
  2041. def.var.searchType = getUrlParam(currentSite.splitTypeName);
  2042. def.var.securityPolicy = getSecurityPolicy();
  2043. if (antiLinkRedirect && cachedRequestLinks.size > 0) {
  2044. cachedRequestLinks.clear();
  2045. DEBUG("Task Clear!");
  2046. }
  2047. if (antiResultsFilter && usedFilterWords.size > 0) {
  2048. usedFilterWords.clear();
  2049. DEBUG("Filter Clear!");
  2050. }
  2051. return true;
  2052. }
  2053.  
  2054. function setupGlobalParameterListener() {
  2055. if (GMcontentMode && document.body) {
  2056. const observer = new MutationObserver(getGlobalParameter);
  2057. observer.observe(document.body, { childList: true, subtree: true });
  2058. } else {
  2059. w.addEventListener("pushState", getGlobalParameter);
  2060. w.addEventListener("replaceState", getGlobalParameter);
  2061. w.addEventListener("popstate", getGlobalParameter);
  2062. }
  2063. }
  2064.  
  2065. async function updateToRequestIcon() {
  2066. try {
  2067. const iconDataURL = await requestRemoteIcon(yandexIconsAPIUrl);
  2068. if (iconDataURL) cache.set("_remoteicons_", iconDataURL, 2592e6);
  2069. } catch (e) {
  2070. ERROR("updateToRequestIcon: Can't fetch the iconData.");
  2071. } finally {
  2072. refresh();
  2073. }
  2074. }
  2075.  
  2076. function openUpdateWindow(url) {
  2077. if (IS_REAL_GECKO) {
  2078. def.const.updateWindow = GMopenInTab(IS_GREASEMONKEY ? url.replace(/\?\w+/g, "") : url, false);
  2079. } else {
  2080. w.location.href = url;
  2081. }
  2082. }
  2083.  
  2084. function showNotification() {
  2085. const loadingTip = IS_REAL_GECKO
  2086. ? `${IS_CHN ? "已经在新窗口打开脚本升级页面,请注意切换!" : "The upgrade page is opened in new window!"}`
  2087. : `${IS_CHN ? "正在申请脚本更新安装页面,请稍后……" : "Installation page is requested, please wait..."}`;
  2088. const okTip = IS_CHN ? "<dd><b>若您已更新完成</b>,请点此刷新页面,以使新版脚本生效!</dd>" : "<dd><b>If updated</b>, click here to make the script effective!</dd>";
  2089. GMnotification({
  2090. title: IS_CHN ? "升级提示" : "Update Tips",
  2091. text: createNoticeHTML(`<dd id="${def.notice.random}_loading" style="color:yellow;font-weight:600">${loadingTip}</dd><dd id="${def.notice.random}_error"></dd>${okTip}`),
  2092. type: def.notice.info,
  2093. closeWith: ["click"],
  2094. timeout: false,
  2095. position: "topRight",
  2096. callbacks: { onClose: [updateToRequestIcon] },
  2097. });
  2098. if (def.const.updateWindow) {
  2099. sleep(6e3, { useCachedSetTimeout: true }).then(() => {
  2100. def.const.updateWindow.close?.();
  2101. delete def.const.updateWindow;
  2102. const errorText = IS_CHN ? "如果升级窗口没有出现(网络问题),请点此重试!" : "If no upgrade window appears, click here to retry!";
  2103. const errorHTML = `<gb-error class="${def.notice.gberror}">${errorText}</gb-error>`;
  2104. const errorNode = qS(`#${def.notice.random}_error`);
  2105. if (errorNode) errorNode.innerHTML = tTP.createHTML(errorHTML);
  2106. });
  2107. }
  2108. return qS(`#${def.notice.random}_loading`);
  2109. }
  2110.  
  2111. async function removeLoadingElement(node) {
  2112. await sleep(4e3, { useCachedSetTimeout: true });
  2113. safeRemove(node);
  2114. }
  2115.  
  2116. function preInstall(url) {
  2117. sleep(5e2)(url.replace(".meta.", ".user."))
  2118. .then(u => openUpdateWindow(u))
  2119. .then(() => showNotification())
  2120. .then(r => removeLoadingElement(r))
  2121. .catch(e => ERROR("preInstall:", e.message));
  2122. }
  2123.  
  2124. void (async function (getUpdateInformation, parseUpdateInformatio) {
  2125. const addAction = {
  2126. closeConfig: async () => {
  2127. const configureSelector = `.${def.notice.noticeX} .${def.notice.configuration}`;
  2128. return await NoticeX.close(qS(configureSelector));
  2129. },
  2130. listSearchEngine: currentSite => {
  2131. let returnHtml = "";
  2132. for (let site in listSite) {
  2133. if (hasOwnProp.call(listSite, site) && listSite[site].siteTypeID !== 0 && listSite[site].siteTypeID !== currentSite.siteTypeID) {
  2134. const iconStyle = `background-position:0 ${(1 - listSite[site].siteTypeID) * 24}px;background-attachment:local;background-size:cover;`;
  2135. const buttonTitle = selectedEngine.includes(listSite[site].siteTypeID) ? `title="${IS_CHN ? "您常用的搜索引擎" : "Commonly used search engine"}"` : ``;
  2136. returnHtml += String(
  2137. `<li>
  2138. <button class="${def.notice.searchButton}" id="${listSite[site].siteTypeID}" ${buttonTitle}>
  2139. <span class="${def.notice.favicon} ${def.notice.random}_icon" style="${iconStyle}"></span>
  2140. <span class="${def.notice.random}_iconText">
  2141. ${listSite[site].siteNickName}<sup>${selectedEngine.includes(listSite[site].siteTypeID) ? "\u2726" : "\u0020"}</sup>
  2142. </span>
  2143. </button>
  2144. </li>`
  2145. );
  2146. }
  2147. }
  2148. return String(`<ul class="${def.notice.searchList}">${returnHtml}</ul>`);
  2149. },
  2150. listSelectSearchEngine: () => {
  2151. let returnHtml = "";
  2152. for (let site in listSite) {
  2153. if (hasOwnProp.call(listSite, site) && listSite[site].siteTypeID !== 0) {
  2154. const iconStyle = `background-position:0 ${(1 - listSite[site].siteTypeID) * 32}px;background-attachment:local;background-size:32px auto;`;
  2155. const inputStatus = selectedEngine.includes(listSite[site].siteTypeID) ? "checked" : "disabled";
  2156. returnHtml += String(
  2157. `<label class="${def.notice.card}">
  2158. <input class="${def.notice.card}__input" type="checkbox" name="${def.notice.card}_lists" data-sn="${listSite[site].siteTypeID}" ${inputStatus}/>
  2159. <div class="${def.notice.card}__body">
  2160. <header class="${def.notice.card}__body-header">
  2161. <span class="${def.notice.card}__body-cover-chackbox">
  2162. <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>
  2163. </span>
  2164. <span class="${def.notice.card}__body-cover-image">
  2165. <span class="${def.notice.favicons} ${def.notice.random}_icon" style="${iconStyle}"></span>
  2166. </span>
  2167. <h2 class="${def.notice.card}__body-header-title" fr-fix-stroke="true">${listSite[site].siteNickName}</h2>
  2168. <p class="${def.notice.card}__body-header-subtitle" style="margin:0;padding:0">${listSite[site].siteHostName}</p>
  2169. </header>
  2170. </div>
  2171. </label>`
  2172. );
  2173. }
  2174. }
  2175. return returnHtml;
  2176. },
  2177. setConfigure: () => {
  2178. sleep(5e2)(addAction.closeConfig()).then(isClosed => {
  2179. if (!isClosed) return;
  2180. const configText = String(
  2181. `<fieldset class="${def.notice.fieldset}">
  2182. <legend class="${def.notice.legend}" title="Version ${def.var.curVersion}">
  2183. ${IS_CHN ? "高级功能参数设置" : "Advanced Feature Settings"}
  2184. </legend>
  2185. <ur class="${def.notice.settingList}">
  2186. <li class="${def.notice.random}__content">
  2187. <div>${IS_CHN ? "请选择三个最常用的搜索引擎:" : "Choose three of your favs:"}
  2188. <span id="${def.notice.random}_clear">[<u>${IS_CHN ? "清除" : "Clear"}</u>]</span></div>
  2189. <div class="${def.notice.grid}">
  2190. ${addAction.listSelectSearchEngine()}
  2191. </div>
  2192. </li>
  2193. <li>
  2194. <div>${IS_CHN ? "键盘快捷键功能开关" : "Keyboard Shortcut"}</div>
  2195. <div style="margin:-2px 2px 0 10px">
  2196. <input type="checkbox" id="${def.notice.hk}" class="${def.notice.checkbox}" ${isHotkey ? "checked" : ""} />
  2197. <label for="${def.notice.hk}"></label>
  2198. </div>
  2199. </li>
  2200. <li>
  2201. <div>${IS_CHN ? "Google 国际站跳转" : "Open Google NCR"}</div>
  2202. <div style="margin:-2px 2px 0 10px">
  2203. <input type="checkbox" id="${def.notice.gj}" class="${def.notice.checkbox}" ${googleJump ? "checked" : ""} />
  2204. <label for="${def.notice.gj}"></label>
  2205. </div>
  2206. </li>
  2207. <li>
  2208. <div>${IS_CHN ? "在当前浏览器窗口跳转" : "Open in Self-window"}</div>
  2209. <div style="margin:-2px 2px 0 10px">
  2210. <input type="checkbox" id="${def.notice.lw}" class="${def.notice.checkbox}" ${localWindow ? "checked" : ""} />
  2211. <label for="${def.notice.lw}"></label>
  2212. </div>
  2213. </li>
  2214. <li>
  2215. <div>${IS_CHN ? "搜索关键词高亮增强" : "Keyword Enhance"}
  2216. <span title="${IS_CHN ? "自定义关键词颜色" : "Custom Keyword Color"}" id="${def.notice.random}_customColor"\
  2217. style="display:${keywordHighlight ? `inline-block` : `none`}">\ud83c\udfa8</span>
  2218. </div>
  2219. <div style="margin:-2px 2px 0 10px">
  2220. <input type="checkbox" id="${def.notice.kh}" class="${def.notice.checkbox}" ${keywordHighlight ? "checked" : ""} />
  2221. <label for="${def.notice.kh}"></label>
  2222. </div>
  2223. </li>
  2224. <li>
  2225. <div>${IS_CHN ? "去除链接重定向跳转" : "Remove Redirection"}</div>
  2226. <div style="margin:-2px 2px 0 10px">
  2227. <input type="checkbox" id="${def.notice.ar}" class="${def.notice.checkbox}" ${antiLinkRedirect ? "checked" : ""} />
  2228. <label for="${def.notice.ar}"></label>
  2229. </div>
  2230. </li>
  2231. <li>
  2232. <div title="${IS_CHN ? "实验性功能" : "Beta Version"}">${IS_CHN ? "去除搜索结果广告" : "Remove Ads"}
  2233. <sup style="padding:0;font-style:italic;color:crimson;font-size:11px">Beta!</sup></div>
  2234. <div style="margin:-2px 2px 0 10px">
  2235. <input type="checkbox" id="${def.notice.aa}" class="${def.notice.checkbox}" ${antiAds ? "checked" : ""} />
  2236. <label for="${def.notice.aa}"></label>
  2237. </div>
  2238. </li>
  2239. <li>
  2240. <div title="${IS_CHN ? "关闭更新检测或由扩展自动更新时,您需要到脚本主页查看更新内容。" : "We recommend that you turn on update detection."}">
  2241. ${IS_CHN ? "更新检测(默认:开)" : "Auto Update Detect"}</div>
  2242. <div style="margin:-2px 2px 0 10px">
  2243. <input type="checkbox" id="${def.notice.au}" class="${def.notice.checkbox}" ${isAutoUpdate ? "checked" : ""} />
  2244. <label for="${def.notice.au}"></label>
  2245. </div>
  2246. </li>
  2247. <li style="display:flex;justify-content:space-between;">
  2248. <button id="${def.notice.random}_help" title="${IS_CHN ? "单击查看脚本主页" : "View Homepage"}">
  2249. ${IS_CHN ? "脚本主页" : "Guide!"}
  2250. </button>
  2251. <div>
  2252. <button id="${def.notice.random}_cancel">${IS_CHN ? "取消" : "Cancel"}</button>
  2253. <button id="${def.notice.random}_submit">${IS_CHN ? "保存" : "Save"}</button>
  2254. </div>
  2255. </li>
  2256. </ul>
  2257. </fieldset>`
  2258. );
  2259. const configInterface = GMnotification({
  2260. title: `${def.var.scriptName} v${def.var.curVersion}`,
  2261. text: configText,
  2262. type: def.notice.configuration,
  2263. width: 326,
  2264. closeWith: ["button"],
  2265. scroll: { maxHeight: 680, showOnHover: true },
  2266. progressBar: false,
  2267. timeout: false,
  2268. position: "topRight",
  2269. });
  2270. qA(`input[name='${def.notice.card}_lists']`).forEach(node => void addCardClickEvent(node));
  2271. qS(`#${def.notice.random}_clear`)?.addEventListener("click", cleanSelectedCard);
  2272. qS(`#${def.notice.kh}`)?.addEventListener("click", showCustomColor);
  2273. qS(`#${def.notice.random}_customColor`)?.addEventListener("click", submitKeywordColor);
  2274. qS(`#${def.notice.random}_help`)?.addEventListener("click", openHomePage);
  2275. qS(`#${def.notice.random}_cancel`)?.addEventListener("click", () => void NoticeX.close(configInterface));
  2276. qS(`#${def.notice.random}_submit`)?.addEventListener("click", saveConfigureData);
  2277. });
  2278. },
  2279. listEngine: () => {
  2280. sleep(5e2)(addAction.closeConfig()).then(isClosed => {
  2281. if (!isClosed) return;
  2282. GMnotification({
  2283. title: `\ud83d\udc4b ${IS_CHN ? "你想去哪里吖?" : "Where to visit?"}`,
  2284. text: addAction.listSearchEngine(listCurrentSite),
  2285. type: def.notice.configuration,
  2286. width: 200,
  2287. closeWith: ["button"],
  2288. scroll: { maxHeight: 565, showOnHover: true },
  2289. timeout: 12e3,
  2290. position: "topRight",
  2291. });
  2292. qA(`.${def.notice.noticeX} .${def.notice.configuration} .${def.notice.searchButton}`).forEach(item => setupClickEventOnCard(item));
  2293. });
  2294. },
  2295. filterResult: () => {
  2296. sleep(5e2)(addAction.closeConfig()).then(async isClosed => {
  2297. if (!isClosed) return;
  2298. const _filter_Data_ = await getResultFilterData();
  2299. const { trigger: antiResultsFilter, filter: resultFilters } = _filter_Data_;
  2300. const infoText = IS_CHN
  2301. ? `设置拦截关键词以数组为标准格式,每行一组过滤关键词(注意:非正则语句须转义字符,且最末行尾无逗号),支持高级正则表达式语法,不区分大小写。<em>详细设置规则请查看『设置指引』。</em>`
  2302. : `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>`;
  2303. const placeholder = IS_CHN
  2304. ? `设置如下数组格式:\n[\n "任意关键词",\n "任意网址但要注意转义",\n "http:\\\\/\\\\/test\\\\.cn\\\\/id-.*",\n "\\\\(\\\\?\\\\=非正则须转义\\\\)",`
  2305. : `Set Array as follows: \n[\n "Any keyword",\n "Any URL but must be escaped",\n "example\\\\.com\\\\/test\\\\.html",\n \\\\(\\\\?\\\\:Non-regex escaped\\\\)",`;
  2306. const placeholderText = placeholder + `\n "www\\\\.example\\\\.[a-z]{2,3}",\n "(a|b)\\\\.test\\\\.com",\n "keyword1|keyword[2345]",\n "^(?!.*B).*A.*$"\n]`;
  2307. const resultFiltersJSON = resultFilters.length ? JSON.stringify(resultFilters, null, " ") : "";
  2308. const filterHTML = String(
  2309. `<fieldset class="${def.notice.fieldset}">
  2310. <legend class="${def.notice.legend}" title="Version ${def.var.curVersion}">
  2311. ${IS_CHN ? "搜索结果拦截关键词设置" : "Search Filter Settings"}
  2312. </legend>
  2313. <ur class="${def.notice.settingList}">
  2314. <li>
  2315. <div>${IS_CHN ? "关键词拦截开关" : "Filter Switches"}</div>
  2316. <div style="margin:-2px 2px 0 10px">
  2317. <input type="checkbox" id="${def.notice.rf}" class="${def.notice.checkbox}" ${antiResultsFilter ? "checked" : ""} />
  2318. <label for="${def.notice.rf}"></label>
  2319. </div>
  2320. </li>
  2321. <li class="${def.notice.random}_filter">
  2322. <div class="${def.notice.random}_filter_info">
  2323. ${infoText}
  2324. </div>
  2325. <div class="${def.notice.random}_filter_textarea">
  2326. <textarea class="${def.notice.random}_filter_content" placeholder='${placeholderText}'>${resultFiltersJSON}</textarea>
  2327. </div>
  2328. <div style="text-align:center;padding:0 0 6px 0">
  2329. ${IS_CHN ? "(程序仅检测搜索结果列表内的可见文字)" : "(ONLY DETECT VISIBLE TEXT IN RESULT)"}
  2330. </div>
  2331. </li>
  2332. <li style="display:flex;justify-content:space-between;">
  2333. <button id="${def.notice.random}_help" title="${IS_CHN ? "查看详细设置规则请单击设置指引!" : "See document for detailed setting rules! (Chinese)"}">
  2334. ${IS_CHN ? "设置指引" : "Guide!"}
  2335. </button>
  2336. <div>
  2337. <button id="${def.notice.random}_cancel">${IS_CHN ? "取消" : "Cancel"}</button>
  2338. <button id="${def.notice.random}_submit">${IS_CHN ? "保存" : "Save"}</button>
  2339. </div>
  2340. </li>
  2341. </ul>
  2342. </fieldset>`
  2343. );
  2344. const filterInterface = GMnotification({
  2345. title: `${def.var.scriptName} v${def.var.curVersion}`,
  2346. text: filterHTML,
  2347. type: def.notice.configuration,
  2348. width: 380,
  2349. closeWith: ["button"],
  2350. scroll: { maxHeight: 680, showOnHover: true },
  2351. progressBar: false,
  2352. timeout: false,
  2353. position: "topRight",
  2354. });
  2355. const textarea = qS(`.${def.notice.random}_filter_textarea .${def.notice.random}_filter_content`);
  2356. const tigger = qS(`#${def.notice.rf}`);
  2357. if (!tigger?.checked) {
  2358. textarea.classList.add(def.notice.readonly);
  2359. textarea.setAttribute("readonly", true);
  2360. }
  2361. tigger?.addEventListener("change", changeEventOnTigger);
  2362. textarea?.addEventListener("compositionstart", () => (def.var.composing = true));
  2363. textarea?.addEventListener("compositionend", () => void delete def.var.composing);
  2364. textarea?.addEventListener("input", addInputEventOnTextarea);
  2365. qS(`#${def.notice.random}_help`)?.addEventListener("click", () => void GMopenInTab(`${def.url.feedback}/288`, false));
  2366. qS(`#${def.notice.random}_cancel`)?.addEventListener("click", () => void NoticeX.close(filterInterface));
  2367. qS(`#${def.notice.random}_submit`)?.addEventListener("click", savefilterResultData);
  2368. });
  2369. },
  2370. };
  2371.  
  2372. function changeEventOnTigger() {
  2373. const textarea = qS(`.${def.notice.random}_filter_textarea .${def.notice.random}_filter_content`);
  2374. if (this.checked) {
  2375. textarea.classList.remove(def.notice.readonly);
  2376. textarea.removeAttribute("readonly", true);
  2377. } else {
  2378. textarea.classList.add(def.notice.readonly);
  2379. textarea.setAttribute("readonly", true);
  2380. }
  2381. }
  2382.  
  2383. async function savefilterResultData() {
  2384. const filter_String = qS(`.${def.notice.random}_filter_textarea .${def.notice.random}_filter_content`).value.trim();
  2385. const fitler_Trigger = qS(`#${def.notice.rf}`).checked;
  2386. try {
  2387. const _filter_String = filter_String ? JSON.parse(filter_String) : [];
  2388. if (!Array.isArray(_filter_String) || _filter_String.Some(item => typeof item !== "string")) throw new Error("Format Error");
  2389. const _resultFilter_Data = { filter: uniq(_filter_String), trigger: fitler_Trigger };
  2390. GMsetValue("_resultFilter_", encrypt(JSON.stringify(_resultFilter_Data)));
  2391. (await addAction.closeConfig()) &&
  2392. GMnotification({
  2393. title: IS_CHN ? "保存成功!" : "Success!",
  2394. text: createNoticeHTML(IS_CHN ? "<dd>设置参数已成功保存,页面稍后自动刷新!</dd>" : "<dd>The data is saved successfully, Page will refresh!</dd>"),
  2395. callbacks: { onClose: [refresh] },
  2396. });
  2397. } catch (e) {
  2398. const noticeText = IS_CHN ? "设置数据格式有误,请修正后重新提交。" : "The setting data format is incorrect!";
  2399. GMnotification({
  2400. text: createNoticeHTML(`<dd><e style="font-size:24px;vertical-align:bottom">\ud83d\ude31\u0020</e>${noticeText}</dd>`),
  2401. type: def.notice.error,
  2402. closeWith: ["click"],
  2403. });
  2404. }
  2405. }
  2406.  
  2407. function addInputEventOnTextarea() {
  2408. try {
  2409. if (def.var.composing) return;
  2410. if (this.value === "") {
  2411. this.style.border = "1px solid #999";
  2412. return;
  2413. }
  2414. let previousCursorPosition = this.selectionStart;
  2415. const formattedValue = JSON.stringify(JSON.parse(this.value.trim()), null, " ");
  2416. const diff = formattedValue.length - this.value.length;
  2417. const newCursorPosition = previousCursorPosition + diff;
  2418. const currentScrollTop = this.scrollTop;
  2419. this.value = formattedValue;
  2420. this.style.border = "1px solid #999";
  2421. sleep(0)([currentScrollTop, newCursorPosition]).then(([top, pos]) => {
  2422. this.scrollTop = top;
  2423. this.setSelectionRange(pos, pos);
  2424. });
  2425. } catch (e) {
  2426. this.style.border = "2px solid #dc143c";
  2427. }
  2428. }
  2429.  
  2430. function setupClickEventOnCard(item) {
  2431. item.addEventListener(
  2432. "click",
  2433. function (listCurrentSite, localWindow) {
  2434. let url;
  2435. for (let type in newSiteType) {
  2436. if (hasOwnProp.call(newSiteType, type) && newSiteType[type] === Number(item.id)) {
  2437. const isImageType = listCurrentSite.imageType.includes(getUrlParam(listCurrentSite.splitTypeName).trim());
  2438. url = isImageType ? listSite[type.toLowerCase()].imageURL : listSite[type.toLowerCase()].webURL;
  2439. break;
  2440. }
  2441. }
  2442. if (localWindow) top.location.href = decodeURI(url + getQueryString());
  2443. else GMopenInTab(decodeURI(url + getQueryString()), false);
  2444. }.bind(this, listCurrentSite, localWindow)
  2445. );
  2446. }
  2447.  
  2448. function openHomePage() {
  2449. 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#searchengine-assistants";
  2450. GMopenInTab(`${def.url.homepage}${hash}-google--baidu-switcheruserjs`, false);
  2451. }
  2452.  
  2453. function addCardClickEvent(node) {
  2454. node.addEventListener("click", () => {
  2455. const input_checked = qA(`input[name='${def.notice.card}_lists']:checked:enabled`).length;
  2456. if (input_checked < 3) {
  2457. qA(`input[name='${def.notice.card}_lists']:disabled`).forEach(item => (item.disabled = false));
  2458. qS(`#${def.notice.random}_clear`).style.display = input_checked === 0 ? "none" : "inline";
  2459. } else {
  2460. qA(`input[name='${def.notice.card}_lists']:not(:checked)`).forEach(item => (item.disabled = true));
  2461. }
  2462. });
  2463. }
  2464.  
  2465. function submitKeywordColor() {
  2466. let inputFgColor, inputBgColor;
  2467. const colorReg =
  2468. /^#[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;
  2469. const foregroundColorText = IS_CHN
  2470. ? `请输入关键词前景色(字体颜色),默认为“#f73131cd”,支持HEX, HEXA, RGB, RGBA, currentcolor的颜色格式。`
  2471. : `𝐏𝐥𝐞𝐚𝐬𝐞 𝐞𝐧𝐭𝐞𝐫 𝐭𝐡𝐞 𝐤𝐞𝐲𝐰𝐨𝐫𝐝 𝐟𝐨𝐫𝐞𝐠𝐫𝐨𝐮𝐧𝐝-𝐜𝐨𝐥𝐨𝐫 (𝐟𝐨𝐧𝐭 𝐜𝐨𝐥𝐨𝐫):\r\nThe default is "#f73131cd" and supports the color formats of HEX, HEXA, RGB, RGBA and currentcolor.`;
  2472. const backgroundColorText = IS_CHN
  2473. ? `请输入关键词背景色,默认为“#ffff80ad”,支持HEX, HEXA, RGB, RGBA, transparent的颜色格式。`
  2474. : `𝐏𝐥𝐞𝐚𝐬𝐞 𝐞𝐧𝐭𝐞𝐫 𝐭𝐡𝐞 𝐤𝐞𝐲𝐰𝐨𝐫𝐝 𝐛𝐚𝐜𝐤𝐠𝐫𝐨𝐮𝐧𝐝-𝐜𝐨𝐥𝐨𝐫:\r\nThe default is "#ffff80ad" and supports the color formats of HEX, HEXA, RGB, RGBA and transparent.`;
  2475. const confirmColorsText = IS_CHN ? `请确认您输入的颜色代码是否正确?` : `𝐏𝐥𝐞𝐚𝐬𝐞 𝐦𝐚𝐤𝐞 𝐬𝐮𝐫𝐞 𝐭𝐡𝐚𝐭 𝐭𝐡𝐞 𝐜𝐨𝐥𝐨𝐫 𝐜𝐨𝐝𝐞 𝐞𝐧𝐭𝐞𝐫𝐞𝐝 𝐢𝐬 𝐜𝐨𝐫𝐫𝐞𝐜𝐭?`;
  2476. const confirmfgColorText = IS_CHN ? "\r\n前景色代码:" : "\r\n𝐅𝐨𝐫𝐞𝐠𝐫𝐨𝐮𝐧𝐝-𝐂𝐨𝐥𝐨𝐫: ";
  2477. const fonfirmbgColorText = IS_CHN ? "\r\n背景色代码:" : "\r\n𝐁𝐚𝐜𝐤𝐠𝐫𝐨𝐮𝐧𝐝-𝐂𝐨𝐥𝐨𝐫: ";
  2478. const saveData = async () => {
  2479. if (!inputFgColor || !inputBgColor) return;
  2480. customColor = { foregroundColor: inputFgColor.trim().toLowerCase(), backgroundColor: inputBgColor.trim().toLowerCase() };
  2481. _config_date_ = { isAutoUpdate, keywordHighlight: true, isHotkey, selectedEngine, localWindow, googleJump, antiLinkRedirect, antiAds, customColor };
  2482. GMsetValue("_configures_", encrypt(JSON.stringify(_config_date_)));
  2483. };
  2484. inputFgColor = prompt(foregroundColorText, customColor.foregroundColor);
  2485. if (inputFgColor === null) return;
  2486. else if (colorReg.test(inputFgColor.trim())) {
  2487. inputBgColor = prompt(backgroundColorText, customColor.backgroundColor);
  2488. if (inputBgColor === null) return;
  2489. else if (colorReg.test(inputBgColor.trim())) {
  2490. const confirmForegroundColor = /^#/gi.test(inputFgColor.trim()) ? inputFgColor.trim().toUpperCase() : inputFgColor.trim().toLowerCase();
  2491. const confirmbackgroundColor = /^#/gi.test(inputBgColor.trim()) ? inputBgColor.trim().toUpperCase() : inputBgColor.trim().toLowerCase();
  2492. const confirmText = `${confirmColorsText}${confirmfgColorText}${confirmForegroundColor}${fonfirmbgColorText}${confirmbackgroundColor}`;
  2493. if (!confirm(confirmText)) return;
  2494. GMnotification({
  2495. title: IS_CHN ? "自定义颜色保存" : "Save Custom Color",
  2496. text: createNoticeHTML(IS_CHN ? "<dd>搜索关键词自定义颜色已保存,当前页面即将刷新!</dd>" : "<dd>Search keywords custom color has been saved!</dd>"),
  2497. callbacks: { onShow: [saveData], onClose: [refresh] },
  2498. });
  2499. } else alert(IS_CHN ? "背景色 格式输入错误!" : "Background-color input-format error!");
  2500. } else alert(IS_CHN ? "前景色(字体颜色) 格式输入错误!" : "Foreground-color (font-color) input-format error!");
  2501. }
  2502.  
  2503. function cleanSelectedCard() {
  2504. qA(`input[name='${def.notice.card}_lists']:checked:enabled`).forEach(node => node.click());
  2505. }
  2506.  
  2507. function showCustomColor() {
  2508. qS(`#${def.notice.random}_customColor`).style.display = this.checked ? "inline-block" : "none";
  2509. }
  2510.  
  2511. async function saveConfigureData() {
  2512. let selectEngineList = [];
  2513. qA(`input[name='${def.notice.card}_lists']:checked`).forEach(item => selectEngineList.push(Number(item.dataset.sn)));
  2514. if (selectEngineList.length < 3) {
  2515. const noticeText = IS_CHN
  2516. ? `\u0020您需要选择「三个」搜索引擎,还少<em>${3 - selectEngineList.length}</em>个呢!`
  2517. : `\u0020Please select <b>three</b> search engines, still less<em>${3 - selectEngineList.length}</em>`;
  2518. return void GMnotification({
  2519. text: createNoticeHTML(`<dd><e style="font-size:24px;vertical-align:bottom">\ud83d\ude31</e>${noticeText}</dd>`),
  2520. type: def.notice.error,
  2521. closeWith: ["click"],
  2522. });
  2523. }
  2524. selectedEngine = selectEngineList;
  2525. isHotkey = qS(`#${def.notice.hk}`).checked;
  2526. googleJump = qS(`#${def.notice.gj}`).checked;
  2527. localWindow = qS(`#${def.notice.lw}`).checked;
  2528. keywordHighlight = qS(`#${def.notice.kh}`).checked;
  2529. antiLinkRedirect = qS(`#${def.notice.ar}`).checked;
  2530. antiAds = qS(`#${def.notice.aa}`).checked;
  2531. isAutoUpdate = qS(`#${def.notice.au}`).checked;
  2532. _config_date_ = { isAutoUpdate, keywordHighlight, isHotkey, selectedEngine, localWindow, googleJump, antiLinkRedirect, antiAds, customColor };
  2533. GMsetValue("_configures_", encrypt(JSON.stringify(_config_date_)));
  2534. (await addAction.closeConfig()) &&
  2535. GMnotification({
  2536. title: IS_CHN ? "保存成功!" : "Success!",
  2537. text: createNoticeHTML(IS_CHN ? "<dd>设置参数已成功保存,页面稍后自动刷新!</dd>" : "<dd>The data is saved successfully, Page will refresh!</dd>"),
  2538. callbacks: { onClose: [refresh] },
  2539. });
  2540. }
  2541.  
  2542. function insertMenus() {
  2543. const parameter_Set_Menu = `\ufff0\u2699\ufe0f ${IS_CHN ? "搜索引擎助手高级设置" : "Advanced Feature Settings "}${isHotkey ? "(E)" : ""}`;
  2544. parameter_Set ? GMunregisterMenuCommand(parameter_Set) : DEBUG("%cInstalling Parameter_Set_Menu", "color:gray");
  2545. parameter_Set = GMregisterMenuCommand(parameter_Set_Menu, addAction.setConfigure);
  2546. const filter_Set_Menu = `\ufff2\ud83d\udcdb ${IS_CHN ? "搜索结果拦截词设置" : "Search Filter Settings "}${isHotkey ? "(B)" : ""}`;
  2547. filter_Set ? GMunregisterMenuCommand(filter_Set) : DEBUG("%cInstalling Filter_Set_Menu", "color:gray");
  2548. filter_Set = GMregisterMenuCommand(filter_Set_Menu, addAction.filterResult);
  2549. const engine_List_Menu = `\ufff4\ud83d\udc4b ${IS_CHN ? "嗨,你想去哪里吖?" : "Hi, Where to visit? "} ${isHotkey ? "(V)" : ""}`;
  2550. engine_List ? GMunregisterMenuCommand(engine_List) : DEBUG("%cInstalling Engine_List_Menu", "color:gray");
  2551. engine_List = GMregisterMenuCommand(engine_List_Menu, addAction.listEngine);
  2552. }
  2553.  
  2554. function insertHotkey() {
  2555. sleep(1e2, { useCachedSetTimeout: true })
  2556. .then(() => {
  2557. if (!isHotkey) return DEBUG("%cNo Hotkey_Setting", "color:grey");
  2558. document.addEventListener("keydown", event => void (event.code === "AltRight" && (def.const.AltGraph = true)));
  2559. document.addEventListener("keyup", event => void (event.code === "AltRight" && delete def.const.AltGraph));
  2560. return !DEBUG("%cInstalling Hotkey_Setting", "color:gray");
  2561. })
  2562. .then(isDeplayed => {
  2563. if (!isDeplayed) return;
  2564. document.addEventListener("keydown", e => {
  2565. const ekey = (e.altKey || def.const.AltGraph === true) && !e.ctrlKey && !e.shiftKey && !e.metaKey;
  2566. if (e.code === "KeyE" && ekey) {
  2567. e.preventDefault();
  2568. e.stopImmediatePropagation();
  2569. if (Date.now() - def.count.clickTimer > 1e3) {
  2570. def.count.clickTimer = Date.now();
  2571. addAction.setConfigure();
  2572. }
  2573. }
  2574. if (e.code === "KeyV" && ekey) {
  2575. e.preventDefault();
  2576. e.stopImmediatePropagation();
  2577. if (Date.now() - def.count.clickTimer > 1e3) {
  2578. def.count.clickTimer = Date.now();
  2579. addAction.listEngine();
  2580. }
  2581. }
  2582. if (e.code === "KeyB" && ekey) {
  2583. e.preventDefault();
  2584. e.stopImmediatePropagation();
  2585. if (Date.now() - def.count.clickTimer > 1e3) {
  2586. def.count.clickTimer = Date.now();
  2587. addAction.filterResult();
  2588. }
  2589. }
  2590. });
  2591. });
  2592. }
  2593.  
  2594. function showSystemInfo() {
  2595. if (CUR_WINDOW_TOP && listCurrentSite.siteTypeID !== newSiteType.OTHERS) {
  2596. const isFavEngine = currentSite.siteTypeID !== newSiteType.OTHERS;
  2597. const fontStyle = `text-transform:capitalize;font:italic 16px/130% Candara,'Times New Roman'`;
  2598. __console(
  2599. "shown_system_info",
  2600. `%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`,
  2601. "font:normal 700 16px/150% system-ui,-apple-system,BlinkMacSystemFont,sans-serif;color:crimson",
  2602. "color:#777;font:italic 400 10px/180% monospace",
  2603. "font-size:12px;font-weight:700;color:steelblue",
  2604. IS_CHN ? "脚本版本:" : "Version:\u0020",
  2605. "color:#708090;font:italic 600 14px/150% Candara,Times New Roman",
  2606. def.var.curVersion,
  2607. "color:darkred;font:italic 11px/150% Candara,'Times New Roman'",
  2608. IS_CHEAT_UA ? "\u3000(CHEAT-UA)" : "",
  2609. "font-size:12px;font-weight:700;color:steelblue",
  2610. IS_CHN ? "当前搜索引擎:" : "CurrentEngine:\u0020",
  2611. `color:crimson;${fontStyle};font-weight:700`,
  2612. currentSiteName,
  2613. "font-size:12px;font-weight:700;color:steelblue",
  2614. IS_CHN ? "常用的搜索引擎:" : "YourFavEngine:\u0020",
  2615. `color:${isFavEngine ? "green" : "blue"};${fontStyle}`,
  2616. isFavEngine,
  2617. "font-size:12px;font-weight:700;color:steelblue",
  2618. IS_CHN ? "移除链接重定向:" : "antiRedirectFn:\u0020",
  2619. `color:${antiLinkRedirect ? "green" : "blue"};${fontStyle}`,
  2620. antiLinkRedirect,
  2621. "font-size:12px;font-weight:700;color:steelblue",
  2622. IS_CHN ? "去除搜索结果广告:" : "AntiAdvertising:\u0020",
  2623. `color:${antiAds ? "green" : "blue"};${fontStyle}`,
  2624. antiAds,
  2625. "font-size:12px;font-weight:700;color:steelblue",
  2626. IS_CHN ? "搜索结果关键词过滤:" : "SearchResultFilter:\u0020",
  2627. `color:${antiResultsFilter ? "green" : "blue"};${fontStyle}`,
  2628. antiResultsFilter
  2629. );
  2630. }
  2631. }
  2632.  
  2633. /* SEARCH_ENGINE_ASSISTANT_COMMAND_FUNCTIONS */
  2634.  
  2635. const siteConfigMap = {
  2636. baidu: {
  2637. listTypes: { target: "#content_left", listName: "div", className: "result-op" },
  2638. clear: () => safeRemove("#con-ar"),
  2639. applyButton: ({ buttonSection, buttonID, target }) => {
  2640. insertAfter(buttonSection, target);
  2641. if (!qS(buttonID)) return;
  2642. switch (def.var.searchType) {
  2643. case currentSite.imageType[0]:
  2644. buttonSection.style.marginLeft = "16px";
  2645. qS(`#${def.const.rightButton} input`).style.marginLeft = "3px";
  2646. document.body.style.overflowX = "clip";
  2647. break;
  2648. case currentSite.imageType[1]:
  2649. buttonSection.style.height = "34px";
  2650. qA(`${buttonID} input`).forEach(node => {
  2651. node.style.cssText = "min-width:100px;height:34px;padding:0 5px!important;color:#fff;background:#3388ff;border-radius:0;border:1px solid #2d78f4";
  2652. });
  2653. document.body.style.overflowX = "clip";
  2654. break;
  2655. }
  2656. },
  2657. },
  2658. bing: {
  2659. listTypes: { target: "#b_results", listName: "li", className: "b_algo" },
  2660. clear: () => safeRemove("aside>ol#b_context"),
  2661. applyButton: ({ buttonSection, target }) => {
  2662. insertAfter(buttonSection, target);
  2663. qA(`#b_header .b_searchbox`).forEach(item => (item.style.maxWidth = "666px"));
  2664. qS(`textarea.b_searchbox[name="q"]`, target.parentNode)?.getAttribute("rows") >= 2 &&
  2665. qA(`#${def.const.rndButtonID} input`).forEach(input => (input.style.cssText += "border-radius:8px"));
  2666. const form = qS(".b_searchboxForm");
  2667. if (form && getUrlParam("view") === "detailV2") {
  2668. form.style.cssText += "width:max-content!important;z-index:1000;position:relative;";
  2669. qA(`#${def.const.rndButtonID} input`).forEach(
  2670. input => (input.style.cssText += "height:34px!important;border-radius:6px!important;padding:0 12px!important;argin:0 0 0 2px!important;")
  2671. );
  2672. }
  2673. },
  2674. },
  2675. google: {
  2676. listTypes: { target: "div[eid][data-async-context]", listName: "div", className: "MjjYud" },
  2677. applyButton: ({ buttonSection, buttonID, target }) => {
  2678. getGlobalGoogle("www.google.com", googleJump);
  2679. insertAfter(buttonSection, target);
  2680. if (!qS(buttonID)) return;
  2681. buttonSection.parentNode.style.width = "fit-content";
  2682. buttonSection.parentNode.style.minWidth = "100%";
  2683. buttonSection.parentNode.parentNode.style.width = "100%";
  2684. buttonSection.parentNode.parentNode.parentNode.style.width = "95%";
  2685. if (currentSite.imageType.includes(def.var.searchType)) {
  2686. buttonSection.parentNode.firstElementChild.style.width = "400px";
  2687. }
  2688. },
  2689. },
  2690. duckduckgo: {
  2691. listTypes: { target: "ol.react-results--main", listName: "li" },
  2692. applyButton: ({ buttonSection, target }) => {
  2693. target.parentNode.appendChild(buttonSection);
  2694. sleep(0)(buttonSection.getBoundingClientRect().width || 2e2).then(sectionWidth => (buttonSection.style.right = `-${sectionWidth + 8}px`));
  2695. },
  2696. },
  2697. yandex: {
  2698. listTypes: { target: "#search-result", listName: "li" },
  2699. clear: () => safeRemove("div.content__right>div"),
  2700. applyButton: ({ buttonSection, target }) => {
  2701. insertAfter(buttonSection, target);
  2702. sleep(0)(buttonSection.getBoundingClientRect().width || 2e2).then(sectionWidth => {
  2703. buttonSection.style.right = `-${sectionWidth + 10}px`;
  2704. if (currentSite.imageType.includes(def.var.searchType)) {
  2705. const actionNode = qS(`div.HeaderDesktopActions.HeaderDesktop-Actions`);
  2706. if (actionNode) actionNode.style.cssText = `position:relative;right:-${sectionWidth - 10}px;margin-right:${sectionWidth}px`;
  2707. } else {
  2708. const actionNode = qS(`div.HeaderDesktopActions`);
  2709. const voiceButton = qS(`button.voice-search-button.input__voice-search`);
  2710. if (actionNode) actionNode.style.cssText = `position:relative;right:-${sectionWidth - 10}px;margin-right:${sectionWidth}px`;
  2711. if (voiceButton) voiceButton.style.right = `-${sectionWidth + 190}px`;
  2712. }
  2713. });
  2714. },
  2715. },
  2716. sogou: {
  2717. listTypes: { target: "div.results", listName: "div", className: "vrwrap" },
  2718. clear: () => safeRemove("#right"),
  2719. applyButton: ({ resolve, buttonSection, buttonID, target }) => {
  2720. if (currentSite.imageType.includes(def.var.searchType)) {
  2721. sleep(4e2)(resolve()).then(() => {
  2722. if (!qS(buttonID) && target) {
  2723. insertAfter(buttonSection, target);
  2724. const sectionWidth = buttonSection.getBoundingClientRect().width;
  2725. buttonSection.style.right = `-${sectionWidth + 10}px`;
  2726. addSearchButtonEvent(qA(`${buttonID} span[sn]:not([event-insert])`));
  2727. }
  2728. });
  2729. } else if (def.var.searchType === "weixin") {
  2730. insertAfter(buttonSection, target);
  2731. buttonSection.style = "position:relative";
  2732. qA(`${buttonID} input`).forEach(node => node.classList.add(`${def.notice.random}_weixin`));
  2733. } else {
  2734. insertAfter(buttonSection, target);
  2735. const btn = qS(`#searchBtn2[value="\u5168\u7f51\u641c\u7d22"]`);
  2736. sleep(0)(safeRemove(btn)).then(() => {
  2737. const sectionWidth = buttonSection.getBoundingClientRect().width || 2e2;
  2738. buttonSection.style.right = `-${sectionWidth + 10}px`;
  2739. const btn2 = qS(`#searchBtn2`);
  2740. if (btn2) btn2.style.right = `-${sectionWidth + 120}px`;
  2741. });
  2742. }
  2743. },
  2744. },
  2745. toutiao: {
  2746. listTypes: { target: "div.s-result-list", listName: "div" },
  2747. clear: () => safeRemove(".main>.s-side-list>.result-content"),
  2748. applyButton: ({ buttonSection, target }) => {
  2749. insertAfter(buttonSection, target);
  2750. sleep(0)(buttonSection.getBoundingClientRect().width || 2e2).then(sectionWidth => (buttonSection.style.right = `-${sectionWidth + 10}px`));
  2751. },
  2752. },
  2753. wuzhuiso: { listTypes: { target: "#main ul.result", listName: "li", className: "res-list" }, clear: () => safeRemove("#side>#so_ob") },
  2754. so360: {
  2755. listTypes: { target: "#main>ul.result", listName: "li", className: "res-list" },
  2756. clear: () => safeRemove("#side_wrap"),
  2757. applyButton: ({ buttonSection, buttonID, target }) => {
  2758. insertAfter(buttonSection, target);
  2759. if (currentSite.imageType.includes(def.var.searchType)) {
  2760. qA(`${buttonID} input`).forEach(node => (node.style = "margin:0 0 0 1px;"));
  2761. sleep(5e2).then(() => qS("#tools_close")?.click());
  2762. }
  2763. },
  2764. },
  2765. kaifa: {
  2766. listTypes: { target: "ul.ant-list-items", listName: "li", className: "ant-list-item" },
  2767. applyButton: ({ buttonSection, target }) => {
  2768. target.appendChild(buttonSection);
  2769. const input = qS("#search-box-container input[class~='ant-input']");
  2770. if (input) input.style.cssText += `width:580px!important`;
  2771. },
  2772. },
  2773. ecosia: {
  2774. listTypes: { target: "section.mainline>div:not([class])", listName: "div", className: "mainline__result-wrapper" },
  2775. applyButton: ({ resolve, buttonSection, buttonID, target }) => {
  2776. let isLoadEventAttached = false;
  2777. const handleLoadEvent = () => {
  2778. if (!qS(buttonID) && target) insertAfter(buttonSection, target);
  2779. addSearchButtonEvent(qA(`${buttonID} span[sn]:not([event-insert])`));
  2780. w.removeEventListener("load", handleLoadEvent);
  2781. isLoadEventAttached = false;
  2782. };
  2783. if (!isLoadEventAttached) {
  2784. w.addEventListener("load", handleLoadEvent);
  2785. isLoadEventAttached = true;
  2786. }
  2787. resolve();
  2788. },
  2789. },
  2790. yahoo: {
  2791. listTypes: { target: "#web>ol", listName: "li" },
  2792. clear: () => safeRemove("#right>ol"),
  2793. applyButton: ({ buttonSection, target }) => {
  2794. try {
  2795. insertAfter(buttonSection, target);
  2796. if (currentSite.imageType.includes(def.var.searchType)) {
  2797. const sectionRect = qS("#sbx")?.getBoundingClientRect() ?? { width: 656, left: 2e2 };
  2798. buttonSection.style.cssText = `position:absolute;left:${sectionRect.width + sectionRect.left}px`;
  2799. } else {
  2800. const sectionWidth = buttonSection.getBoundingClientRect().width ?? 224;
  2801. buttonSection.style.cssText = `position:absolute;top:0;right:-${10 + sectionWidth}px`;
  2802. }
  2803. } catch (e) {
  2804. ERROR("insertButtons.YAHOO:", e.message);
  2805. }
  2806. },
  2807. },
  2808. you: { listTypes: { target: "div[data-testid='app-mainline']>div[data-eventappname][data-testid]", listName: "ul" } },
  2809. startpage: { listTypes: { target: "#main>div.w-gl", listName: "div", className: "result" } },
  2810. brave: { listTypes: { target: "#results", listName: "div", className: "snippet" }, clear: () => safeRemove("aside>div") },
  2811. yep: {
  2812. listTypes: { target: "div[class$='-results']>div>div", listName: "div" },
  2813. applyButton: ({ buttonSection, target }) => {
  2814. insertAfter(buttonSection, target);
  2815. const sectionWidth = buttonSection.getBoundingClientRect().width || 2e2;
  2816. buttonSection.style.right = `-${10 + sectionWidth}px`;
  2817. },
  2818. },
  2819. swisscows: {
  2820. listTypes: { target: ".web-results", listName: "article", className: "item-web" },
  2821. applyButton: ({ buttonSection, target }) => {
  2822. insertAfter(buttonSection, target);
  2823. sleep(0)
  2824. .then(() => buttonSection.getBoundingClientRect().width || 2e2)
  2825. .then(sectionWidth => (buttonSection.style.right = `-${10 + sectionWidth}px`));
  2826. },
  2827. },
  2828. };
  2829.  
  2830. function insertCSS(isOverwrite = false) {
  2831. try {
  2832. const buttonCss = currentSite.buttonCssText ? `@charset "UTF-8";` + currentSite.buttonCssText : "";
  2833. addStyle({ target: document.head, styleId: def.const.rndclassName, media: "all", styleContent: buttonCss, isOverwrite });
  2834. } catch (e) {
  2835. ERROR("insertCSS:", e.message);
  2836. }
  2837. }
  2838.  
  2839. function insertStyle() {
  2840. try {
  2841. const noticeStyle = `@charset "UTF-8";` + def.const.style + def.const.iconstyle + String(keywordHighlight ? def.const.hlstyle : "");
  2842. addStyle({ target: document.head, styleId: def.const.rndstyleName, media: "screen", styleContent: noticeStyle, isOverwrite: false });
  2843. } catch (e) {
  2844. ERROR("insertStyle:", e.message);
  2845. }
  2846. }
  2847.  
  2848. function insertButtons() {
  2849. try {
  2850. const targetSelector = currentSite.mainSelector;
  2851. const buttonSection = cE("gb-button");
  2852. buttonSection.id = def.const.rndButtonID;
  2853. buttonSection.innerHTML = tTP.createHTML(def.const.button);
  2854. const buttonID = `#${buttonSection.id}`;
  2855. const target = qS(targetSelector);
  2856. if (def.var.indexPage || !target || !def.var.queryString || qS(buttonID)) return;
  2857. return new Promise(resolve => {
  2858. applyButtons(resolve, buttonSection, target, buttonID);
  2859. resolve(qA(`${buttonID} span[sn]:not([event-insert])`));
  2860. })
  2861. .then(response => {
  2862. if (!response) return;
  2863. addSearchButtonEvent(response);
  2864. scrollDetect();
  2865. })
  2866. .catch(e => ERROR("applyButtons:", e.message));
  2867. } catch (e) {
  2868. ERROR("insertButtons:", e.message);
  2869. }
  2870. }
  2871.  
  2872. function applyButtons(resolve, buttonSection, target, buttonID) {
  2873. if (currentSite.siteTypeID === newSiteType.OTHERS) return;
  2874. const methodToCall = siteConfigMap[currentSiteName]?.applyButton;
  2875. if (typeof methodToCall === "function") methodToCall({ resolve, buttonSection, buttonID, target });
  2876. else insertAfter(buttonSection, target);
  2877. }
  2878.  
  2879. function scrollDetect() {
  2880. if (def.var.indexPage) return;
  2881. let scrollspan, scrollbars, height;
  2882. if (currentSite.siteTypeID === newSiteType.GOOGLE) {
  2883. let isImageSearch = /^isch$/.test(def.var.searchType);
  2884. scrollspan = isImageSearch ? def.const.scrollspan2 : def.const.scrollspan;
  2885. scrollbars = isImageSearch ? def.const.scrollbars2 : def.const.scrollbars;
  2886. height = isImageSearch ? 0 : 35;
  2887. } else if (currentSite.siteTypeID === newSiteType.BING) {
  2888. let isImageOrVideo = /^(images|videos)$/.test(def.var.searchType);
  2889. scrollspan = isImageOrVideo ? def.const.scrollspan2 : def.const.scrollspan;
  2890. scrollbars = isImageOrVideo ? def.const.scrollbars2 : def.const.scrollbars;
  2891. height = 50;
  2892. } else return;
  2893. setupScrollButton(`#${def.const.rndButtonID}`, scrollspan, height);
  2894. setupScrollButton(`#${def.const.rndButtonID} #${def.const.leftButton} input`, scrollbars, height);
  2895. setupScrollButton(`#${def.const.rndButtonID} #${def.const.rightButton} input`, scrollbars, height);
  2896. }
  2897.  
  2898. function addSearchButtonEvent(nodes) {
  2899. if (!Array.isArray(nodes) || nodes.length === 0) return;
  2900. let gotoUrl = "about:blank";
  2901. nodes.forEach(node => {
  2902. node.setAttribute("event-insert", true);
  2903. qS("input", node).addEventListener("click", () => {
  2904. const imageSearch = getUrlParam(currentSite.splitTypeName)?.trim();
  2905. switch (Number(node.getAttribute("sn"))) {
  2906. case selectedSite[0].siteTypeID:
  2907. gotoUrl = currentSite.imageType.includes(imageSearch) ? selectedSite[0].imageURL : selectedSite[0].webURL;
  2908. break;
  2909. case selectedSite[1].siteTypeID:
  2910. gotoUrl = currentSite.imageType.includes(imageSearch) ? selectedSite[1].imageURL : selectedSite[1].webURL;
  2911. break;
  2912. }
  2913. const finalUrl = decodeURI(gotoUrl + getQueryString());
  2914. if (localWindow) top.location.href = finalUrl;
  2915. else GMopenInTab(finalUrl, false);
  2916. });
  2917. });
  2918. }
  2919.  
  2920. function createNotice(listName, className, userdFilter) {
  2921. const listAttrib = className ? ` class="${className}"` : ``;
  2922. const noticeText = IS_CHN ? "本页所有搜索结果均被屏蔽,如异常请检查过滤词。" : "All results are blocked, Check the filters if abnormal.";
  2923. const filterArray = userdFilter ? `<gb-filters class="code">${IS_CHN ? "过滤词:" : "Filter:"} [${userdFilter}]</gb-filters>` : ``;
  2924. const tips = `<br/>✄┏━┓╋┏┓╋╋╋┏━━━┓╋╋╋╋╋╋╋╋┏┓┏┓╋┏┓<br/>✄┃┃┗┓┃┃╋╋╋┃┏━┓┃╋╋╋╋╋╋╋╋┃┣┛┗┓┃┃<br/>✄┃┏┓┗┛┣━━┓┃┗━┛┣━━┳━━┳┓┏┫┣┓┏┛┃┃<br/>✄┃┃┗┓┃┃┏┓┃┃┏┓┏┫┃━┫━━┫┃┃┃┃┃┃╋┗┛<br/>✄┃┃╋┃┃┃┗┛┃┃┃┃┗┫┃━╋━━┃┗┛┃┗┫┗┓┏┓<br/>✄┗┛╋┗━┻━━┛┗┛┗━┻━━┻━━┻━━┻━┻━┛┗┛<br/><br/>`;
  2925. const noticeCode = tTP.createHTML(`<${listName}${listAttrib} gb-filter-notice>${tips}${noticeText} ${def.var.scriptName}${filterArray}</${listName}>`);
  2926. return noticeCode;
  2927. }
  2928.  
  2929. function showEmptyNotice(siteName) {
  2930. if (!siteConfigMap[siteName]) return;
  2931. const { target, listName, className } = siteConfigMap[siteName].listTypes;
  2932. const noticeNode = qS(`${target} ${listName}[gb-filter-notice]`);
  2933. if (noticeNode) return;
  2934. const usedFilterWordsStr = escapeHTML([...usedFilterWords].join(", "));
  2935. const noticeCode = createNotice(listName, className, usedFilterWordsStr);
  2936. qS(listCurrentSite.resultListProp.qs)?.insertAdjacentHTML("beforebegin", noticeCode);
  2937. usedFilterWords.clear();
  2938. }
  2939.  
  2940. function filterSearchResults(filterObj) {
  2941. if (resultFilters.length === 0) return;
  2942. const { qs, delay } = filterObj;
  2943. let timeout = Number.parseInt(delay);
  2944. if (isNaN(timeout) && !def.const.infinityFilterTimeInitiated) {
  2945. if (typeof def.const.infinityFilterTimeInitiated === "boolean") return;
  2946. w.addEventListener("load", () => {
  2947. def.const.infinityFilterTimeInitiated = true;
  2948. filterSearchResultsProcess(qs);
  2949. });
  2950. def.const.infinityFilterTimeInitiated = false;
  2951. } else deBounce({ fn: filterSearchResultsProcess, timer: "filterSearchResults", delay: timeout || 50 })(qs);
  2952. }
  2953.  
  2954. function filterSearchResultsProcess(querystring) {
  2955. if (!querystring) return;
  2956. const returnContent = new Map();
  2957. const selectors = buildSelectors(querystring);
  2958. return new Promise(resolve => {
  2959. qA(`${selectors}`).forEach(item => processNode(item, returnContent));
  2960. resolve(returnContent);
  2961. })
  2962. .then(rtst => {
  2963. if (!rtst || rtst.size === 0) return;
  2964. rtst.forEach((content, item) => matchFilters(item, content));
  2965. rtst.clear();
  2966. })
  2967. .then(() => sleep(1e2))
  2968. .then(() => {
  2969. if (usedFilterWords.size === 0) return;
  2970. if (qA(querystring.split(/,(?![^()]*\))/g)[0]).length < 2) return;
  2971. const remainingResults = qA(selectors.split(/,(?![^()]*\))/g)[0]).length;
  2972. handleRemainingResults(remainingResults);
  2973. });
  2974. }
  2975.  
  2976. function processMatchedItem(item, content, filter) {
  2977. if (IS_DEBUG) addDebugNotice(item, filter);
  2978. usedFilterWords.add(filter);
  2979. item.classList.add(IS_DEBUG ? def.var.translucent : def.var.disappear);
  2980. DEBUG("Filter.match:", { filter, item, content });
  2981. qA("a", item).forEach(node => node.setAttribute("gd-antiredirect-status", "blocked"));
  2982. qA(item).forEach(subItem => safeRemove(subItem));
  2983. }
  2984.  
  2985. function addDebugNotice(item, filter) {
  2986. const noticeNode = qS("notice-label", item);
  2987. if (!noticeNode) {
  2988. const notice = cE("notice-label");
  2989. notice.classList.add("code");
  2990. notice.textContent = `<![CDATA[ "${filter}" ]]>`;
  2991. item.prepend(notice);
  2992. }
  2993. }
  2994.  
  2995. function adjustUI(siteName) {
  2996. const logicFunction = siteConfigMap[siteName]?.clear;
  2997. if (typeof logicFunction === "function") logicFunction();
  2998. }
  2999.  
  3000. function buildSelectors(querystring) {
  3001. return querystring
  3002. .split(/,(?![^()]*\))/g)
  3003. .map(item => `${item}:not(.${def.var.disappear},.${def.var.translucent},[gb-filter-notice])`)
  3004. .join(",");
  3005. }
  3006.  
  3007. function processNode(item, returnContent) {
  3008. if (item.nodeType !== Node.ELEMENT_NODE) return;
  3009. const href = qS("a:not([title^='Search']):not([aria-label^='Anonymous']):not([href*='.bing.com/ck/a?'])", item)?.href ?? "";
  3010. const url = [1, 5, 8].includes(listCurrentSite.siteTypeID) ? "" : getDecodeURI(href);
  3011. const content = item.innerText?.replace(/[\t\r\n\ue62b]/g, "").trim() + url;
  3012. content && returnContent.set(item, content);
  3013. }
  3014.  
  3015. function matchFilters(item, content) {
  3016. try {
  3017. for (let filter of resultFilters) {
  3018. const regex = new RegExp(filter, "i");
  3019. if (item?.nodeType !== Node.ELEMENT_NODE || !regex.test(content)) continue;
  3020. processMatchedItem(item, content, filter);
  3021. }
  3022. } catch (e) {
  3023. ERROR("Filter.match:", e.message);
  3024. }
  3025. }
  3026.  
  3027. function handleRemainingResults(remainingResults) {
  3028. if (remainingResults > 2) return;
  3029. if (remainingResults === 0) showEmptyNotice(currentSiteName);
  3030. adjustUI(currentSiteName);
  3031. }
  3032.  
  3033. function getDecodeURI(href) {
  3034. if (!href || typeof href !== "string") return "";
  3035. let url = href;
  3036. try {
  3037. if (listCurrentSite.siteTypeID === newSiteType.TOUTIAO) url = decodeURIComponent(new URLSearchParams(new URL(href).search).get("url"));
  3038. } catch (e) {
  3039. url = href.match(/\?url=([^&]+)/)?.[1];
  3040. url = url ? decodeURIComponent(url) : href;
  3041. }
  3042. return `\ue620${url}\ue620`;
  3043. }
  3044.  
  3045. function getGlobalGoogle(NCRHost, permission) {
  3046. if (!permission || CUR_HOST_NAME === NCRHost) return;
  3047. try {
  3048. top.location.href = `${CUR_PROTOCOL}//${NCRHost}/ncr?prev=${CUR_PATH_NAME}${encodeURIComponent(location.search)}`;
  3049. GMnotification({
  3050. title: "Google NCR",
  3051. text: createNoticeHTML(`<dd class="${def.notice.center}">${IS_CHN ? "即将跳转至 Google.com (NCR)" : "Jump to Google.com (NCR)"}</dd>`),
  3052. type: def.notice.info,
  3053. });
  3054. } catch (e) {
  3055. ERROR("getGlobalGoogle:", e.message);
  3056. }
  3057. }
  3058.  
  3059. function searchButtonAndStylesObserve() {
  3060. const processMainThreadTasks = () => {
  3061. if (currentSite.siteTypeID !== newSiteType.OTHERS && !def.var.securityPolicy) {
  3062. if (!qS(`#${def.const.rndclassName}`)) insertCSS();
  3063. if (!qS(`#${def.const.rndButtonID}`)) insertButtons();
  3064. }
  3065. if (listCurrentSite.siteTypeID !== newSiteType.OTHERS) {
  3066. if (!qS(`#${def.const.rndstyleName}`)) insertStyle();
  3067. antiAds && listCurrentSite.antiAdsFn?.();
  3068. antiResultsFilter && filterSearchResults(listCurrentSite.resultListProp);
  3069. antiLinkRedirect && !def.var.indexPage && listCurrentSite.antiRedirectFn?.();
  3070. }
  3071. };
  3072. const observer = new MutationObserver(processMainThreadTasks);
  3073. const config = { childList: true, subtree: true };
  3074. observer.observe(document, config);
  3075. }
  3076.  
  3077. /* SEARCH_ENGINE_ASSISTANT_MAIN_PROCESS */
  3078.  
  3079. void (function (updateFlag) {
  3080. if (CUR_WINDOW_TOP) {
  3081. const updateInfo = getUpdateInformation(updateFlag);
  3082. parseUpdateInformatio(updateInfo);
  3083. showSystemInfo();
  3084. insertMenus();
  3085. insertHotkey();
  3086. }
  3087. setupGlobalParameterListener();
  3088. searchButtonAndStylesObserve();
  3089. })(await cache.get("_autoupdate_"));
  3090. })(
  3091. updateFlag => {
  3092. if (CUR_WINDOW_TOP && isAutoUpdate && (!updateFlag || setDebuggerMode())) {
  3093. const updateDetectionResponses = updateDetectionAddress.map(addr => fetchUpdateResponse(addr));
  3094. return Promise.any(updateDetectionResponses).catch(e => ERROR("getUpdateInformation:", e.message));
  3095. }
  3096. },
  3097. updateResponse => {
  3098. updateResponse
  3099. ?.then(response => {
  3100. if (!response) return;
  3101. const { res, url } = response;
  3102. let version, notes;
  3103. let updateInfoList = "";
  3104. if (res) {
  3105. version = res.match(/\/\/\s+@version\s+(\S+)/)?.[1]?.trim();
  3106. notes = res.match(/\/\/\s+@note\s+(.+)/g);
  3107. notes?.forEach(item => {
  3108. const preNote = escapeHTML(item.replace(/\/\/\s+@note\s+/, "")).trim();
  3109. try {
  3110. const note = JSON.parse(preNote);
  3111. updateInfoList += `<li>${IS_CHN ? note.CN : note.EN}</li>`;
  3112. } catch (e) {
  3113. updateInfoList += `<li>${preNote}</li>`;
  3114. }
  3115. });
  3116. } else {
  3117. const props = ["font-weight:bold;color:crimson", "color:darkred"];
  3118. return __console("error", "%c[GB-UpdateError]%c\r\nRefused to connect to 'the UpdateList URLs', Please check your Network or local DNS!", ...props);
  3119. }
  3120. if (!version) return;
  3121. version = escapeHTML(version);
  3122. const updateText = notes ? updateInfoList : `<ol>当前更新源没有更新详情,请访问 <a target="_blank" href="${def.url.homepage}">Github</a> 查看。</ol><ol>&nbsp;</ol>`;
  3123. const newUpdateHTML = IS_CHN
  3124. ? `<dd><span>发现新版本</span><i>V${version}</i>,点击可自动更新。</dd><dd><ul>${updateText}</ul></dd><dd id="${def.notice.stopUpdate}"><input type="checkbox">一周内不再提醒</dd>`
  3125. : `<dd><span>New Version</span><i>V${version}</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>`;
  3126. if (versionCompare(def.var.curVersion, version)) {
  3127. const updateInterface = GMnotification({
  3128. title: IS_CHN ? "发现新更新" : "Found new update",
  3129. text: createNoticeHTML(newUpdateHTML),
  3130. type: def.notice.warning,
  3131. closeWith: ["click"],
  3132. timeout: 8e3,
  3133. callbacks: { onClick: [() => preInstall(url)] },
  3134. });
  3135. qS(`#${def.notice.stopUpdate}`)?.addEventListener("click", event => {
  3136. event.stopPropagation();
  3137. NoticeX.close(updateInterface);
  3138. cache.set("_autoupdate_", def.var.curVersion);
  3139. });
  3140. const props = ["font-weight:bold;color:crimson", "color:0", "color:crimson", "color:0"];
  3141. __console("shown_new_update", `%c[GB-Update]%c\r\nWe found a new version: %c${version}%c, which you can update now!`, ...props);
  3142. } else {
  3143. const successHTML = IS_CHN
  3144. ? `<dd style="margin: 10px 0"><span>恭喜您!</span>当前版本 <i>${def.var.curVersion}</i> 已为最新!</dd>`
  3145. : `<dd style="margin: 10px 0"><span>Congratulations!</span><br/>The current version <i>${def.var.curVersion}</i> is up-to-date!</dd>`;
  3146. GMnotification({
  3147. title: IS_CHN ? "更新成功" : "Update Success",
  3148. text: createNoticeHTML(successHTML),
  3149. timeout: 3e3,
  3150. closeWith: ["click"],
  3151. });
  3152. cache.set("_autoupdate_", version);
  3153. const props = ["font-weight:700;color:darkcyan", "color:0", "color:crimson", "color:0"];
  3154. __console("shown_update_info", `%c[GB-Update]%c\r\nCurretVersion: %c${def.var.curVersion}%c is up-to-date!`, ...props);
  3155. }
  3156. })
  3157. .catch(e => ERROR(`parseUpdateInformatio: ${e?.message}`));
  3158. }
  3159. );
  3160. })(function () {
  3161. const rnd = Date.now().toString(16);
  3162. const updateURLArray = [
  3163. `https://update.greasyfork.org/scripts/12909/Google_baidu_Switcher_(ALL_in_One).meta.js`,
  3164. `https://raw.githubusercontent.com/F9y4ng/GreasyFork-Scripts/master/Google%20%26%20Baidu%20Switcher.meta.js`,
  3165. `https://openuserjs.org/install/f9y4ng/Google_baidu_Switcher_(ALL_in_One).meta.js`,
  3166. ];
  3167. return updateURLArray.map(url => `${url}?${rnd}`);
  3168. });
  3169. })(
  3170. async () => {
  3171. let config_date, isAutoUpdate, keywordHighlight, isHotkey, selectedEngine, localWindow, googleJump, antiLinkRedirect, antiAds, customColor;
  3172. const configure = await GMgetValue("_configures_");
  3173. if (!configure) {
  3174. const keys = await GMlistValues();
  3175. keys.forEach(key => GMdeleteValue(key));
  3176. isAutoUpdate = true;
  3177. keywordHighlight = false;
  3178. isHotkey = true;
  3179. selectedEngine = [1, 2, 3];
  3180. localWindow = true;
  3181. googleJump = true;
  3182. antiLinkRedirect = true;
  3183. antiAds = false;
  3184. customColor = { foregroundColor: "#f73131cd", backgroundColor: "#ffff80ad" };
  3185. config_date = { isAutoUpdate, keywordHighlight, isHotkey, selectedEngine, localWindow, googleJump, antiLinkRedirect, antiAds, customColor };
  3186. GMsetValue("_configures_", encrypt(JSON.stringify(config_date)));
  3187. } else {
  3188. try {
  3189. config_date = JSON.parse(decrypt(configure));
  3190. isAutoUpdate = Boolean(config_date.isAutoUpdate);
  3191. keywordHighlight = Boolean(config_date.keywordHighlight);
  3192. isHotkey = Boolean(config_date.isHotkey);
  3193. selectedEngine = Array.isArray(config_date.selectedEngine) ? config_date.selectedEngine : [1, 2, 3];
  3194. localWindow = Boolean(config_date.localWindow);
  3195. googleJump = Boolean(config_date.googleJump);
  3196. antiLinkRedirect = Boolean(config_date.antiLinkRedirect);
  3197. antiAds = Boolean(config_date.antiAds);
  3198. customColor = config_date.customColor || { foregroundColor: "#f73131cd", backgroundColor: "#ffff80ad" };
  3199. } catch (e) {
  3200. ERROR("getConfigureData:", e.message);
  3201. return {
  3202. isAutoUpdate: true,
  3203. keywordHighlight: false,
  3204. isHotkey: true,
  3205. selectedEngine: [1, 2, 3],
  3206. localWindow: true,
  3207. googleJump: true,
  3208. antiLinkRedirect: true,
  3209. antiAds: false,
  3210. customColor: { foregroundColor: "#f73131cd", backgroundColor: "#ffff80ad" },
  3211. };
  3212. }
  3213. }
  3214. return { isAutoUpdate, keywordHighlight, isHotkey, selectedEngine, localWindow, googleJump, antiLinkRedirect, antiAds, customColor };
  3215. },
  3216. async () => {
  3217. const resultFilter = await GMgetValue("_resultFilter_");
  3218. if (!resultFilter) return { filter: [], trigger: false };
  3219. let { filter, trigger } = JSON.parse(decrypt(resultFilter));
  3220. if (!Array.isArray(filter)) filter = [];
  3221. return { filter, trigger };
  3222. },
  3223. imgUrl => {
  3224. if (!CUR_WINDOW_TOP) return;
  3225. return new Promise((resolve, reject) => {
  3226. GMxmlhttpRequest({
  3227. url: imgUrl,
  3228. headers: { Accept: "*/*", Referer: imgUrl },
  3229. method: "GET",
  3230. timeout: 5e3,
  3231. responseType: "blob",
  3232. onreadystatechange: response => {
  3233. if (response.readyState !== 4) return;
  3234. if (response.status === 200) {
  3235. let blob = response.response;
  3236. DEBUG("Response.Blob:", blob);
  3237. convertBlobToDataURL(blob, resolve, reject);
  3238. } else if (response.status !== 0) reject(new Error("NoAccessError"));
  3239. },
  3240. onerror: () => reject(new Error("NetworkError")),
  3241. ontimeout: () => reject(new Error("TimeoutError")),
  3242. });
  3243. }).catch(e => Promise.reject(ERROR("requestRemoteIcon:", e.message)));
  3244. },
  3245. options => {
  3246. try {
  3247. const { title, text, type, scroll, width, closeWith, newestOnTop, progressBar, timeout, callbacks, position } = options;
  3248. const parseOptions = {
  3249. title: title || "",
  3250. text: text || "",
  3251. type: type || def.notice.success,
  3252. width: width || 400,
  3253. newestOnTop: newestOnTop || false,
  3254. closeWith: closeWith || ["button"],
  3255. progressBar: progressBar ?? true,
  3256. timeout: timeout ?? 2e3,
  3257. scroll: scroll || { maxHeight: 400, showOnHover: true },
  3258. callbacks: callbacks ? { ...callbacks } : {},
  3259. position: position || "bottomRight",
  3260. };
  3261. const noticeX = new NoticeX(parseOptions).show();
  3262. return noticeX;
  3263. } catch (e) {
  3264. ERROR("GMnotification:", e.message);
  3265. }
  3266. }
  3267. );
  3268. })(createTrustedTypePolicy(), async () => ({ navigatorInfo: await getNavigatorInfo(), locationInfo: getLocationInfo() }));
  3269. },
  3270. (object => {
  3271. return {
  3272. defineMethod,
  3273. ArrayMethods: [
  3274. ["Some", someProxy],
  3275. ["Find", findProxy],
  3276. ],
  3277. __protos__: {
  3278. a: Array.prototype.slice,
  3279. s: Object.prototype.toString,
  3280. h: Object.prototype.hasOwnProperty,
  3281. },
  3282. };
  3283.  
  3284. function defineMethod(property, methodFunction) {
  3285. if (Reflect.getOwnPropertyDescriptor(object, property)) return;
  3286. Object.defineProperty(object, property, {
  3287. value: methodFunction,
  3288. writable: false,
  3289. configurable: false,
  3290. enumerable: false,
  3291. });
  3292. }
  3293.  
  3294. function someProxy(callback, thisArg = this) {
  3295. for (let i = 0; i < this.length; i++) {
  3296. if (callback.call(thisArg, this[i], i, this)) return true;
  3297. }
  3298. return false;
  3299. }
  3300.  
  3301. function findProxy(callback, thisArg) {
  3302. for (let i = 0; i < this.length; i++) {
  3303. if (callback.call(thisArg, this[i], i, this)) return this[i];
  3304. }
  3305. return void 0;
  3306. }
  3307. })(Array.prototype)
  3308. );