优雅的搜索引擎跳转助手

优雅的搜索引擎跳转助手,更美观、更便捷。新版本增加去重定向功能、自定义搜索引擎选取功能,提供可视化搜索参数设置,及自动更新检测等高级功能。

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

  1. // ==UserScript==
  2. // @name Google & baidu Switcher (ALL in One)
  3. // @name:zh-CN 优雅的搜索引擎跳转助手
  4. // @name:zh-TW 优雅的搜索引擎跳轉助手
  5. // @name:ja 検索エンジンジャンプアシスタント
  6. // @version 2022.08.27.1
  7. // @author F9y4ng
  8. // @description Graceful search engine Switch assistant, more beautiful and more convenient. The new version adds anti-redirect function, custom search engine selection function, visual search parameter setting, and automatic update detection and other advanced functions.
  9. // @description:zh-CN 优雅的搜索引擎跳转助手,更美观、更便捷。新版本增加去重定向功能、自定义搜索引擎选取功能,提供可视化搜索参数设置,及自动更新检测等高级功能。
  10. // @description:zh-TW 優雅的搜尋引擎跳轉助手,更美觀、更便捷。新版本增加去重定向功能、自定義搜尋引擎選取功能,提供可視化搜索參數設置,及自動更新檢測等高級功能。
  11. // @description:ja エレガントな検索エンジンジャンプアシスタントは、より美しく、より便利です。 新しいバージョンは、リダイレクト機能、カスタム検索エンジン選択機能、ビジュアル検索パラメータ設定、自動更新検出などの高度な機能を追加します。
  12. // @namespace https://openuserjs.org/scripts/f9y4ng/Google_baidu_Switcher_(ALL_in_One)
  13. // @icon https://img.icons8.com/stickers/48/search-in-cloud.png
  14. // @homepage https://f9y4ng.github.io/GreasyFork-Scripts/
  15. // @homepageURL https://f9y4ng.github.io/GreasyFork-Scripts/
  16. // @supportURL https://github.com/F9y4ng/GreasyFork-Scripts/issues
  17. // @match *://www.baidu.com/*
  18. // @match *://ipv6.baidu.com/*
  19. // @match *://image.baidu.com/*
  20. // @match *://*.bing.com/*
  21. // @match *://duckduckgo.com/*
  22. // @match *://*.sogou.com/*
  23. // @match *://fsoufsou.com/search*
  24. // @match *://www.so.com/s*
  25. // @match *://image.so.com/*
  26. // @match *://so.toutiao.com/search*
  27. // @match *://yandex.com/*search*
  28. // @include *://*.google.*/search*
  29. // @exclude *://www.google.com/sorry*
  30. // @exclude *://www.baidu.com/link*
  31. // @exclude *://www.sogou.com/link*
  32. // @exclude *://www.so.com/link*
  33. // @exclude *://so.toutiao.com/search/jump*
  34. // @connect baidu.com
  35. // @connect bing.com
  36. // @connect sogou.com
  37. // @connect so.com
  38. // @connect greasyfork.org
  39. // @connect openuserjs.org
  40. // @connect githubusercontent.com
  41. // @compatible edge 兼容TamperMonkey, ViolentMonkey
  42. // @compatible Chrome 兼容TamperMonkey, ViolentMonkey
  43. // @compatible Firefox 兼容Greasemonkey4.0+, TamperMonkey, ViolentMonkey
  44. // @compatible Opera 兼容TamperMonkey, ViolentMonkey
  45. // @compatible Safari 兼容Tampermonkey • Safari
  46. // @note 修正Bing搜索结果去广告的bug。\n修正Google搜图搜索框样式问题。\n修正一些已知的问题,优化代码。
  47. // @grant GM_getValue
  48. // @grant GM.getValue
  49. // @grant GM_setValue
  50. // @grant GM.setValue
  51. // @grant GM_listValues
  52. // @grant GM.listValues
  53. // @grant GM_deleteValue
  54. // @grant GM.deleteValue
  55. // @grant GM_openInTab
  56. // @grant GM.openInTab
  57. // @grant GM_registerMenuCommand
  58. // @grant GM.registerMenuCommand
  59. // @grant GM_xmlhttpRequest
  60. // @grant GM.xmlHttpRequest
  61. // @grant GM_unregisterMenuCommand
  62. // @license GPL-3.0-only
  63. // @create 2015-10-07
  64. // @copyright 2015-2022, F9y4ng
  65. // @run-at document-start
  66. // ==/UserScript==
  67.  
  68. /* jshint esversion: 9 */
  69.  
  70. ~(function (trustedTypesPolicy) {
  71. "use strict";
  72.  
  73. /* customize */
  74.  
  75. const IS_OPEN_DEBUG = false; // set "true" to debug scripts, May cause script response slower.
  76.  
  77. /* Perfectly Compatible For Greasemonkey4.0+, TamperMonkey, ViolentMonkey * F9y4ng * 20210609 */
  78.  
  79. const GMinfo = GM_info;
  80. const GMscriptHandler = GMinfo.scriptHandler;
  81. const isGM = GMscriptHandler.toLowerCase() === "greasemonkey";
  82. const debug = IS_OPEN_DEBUG ? console.log.bind(console) : () => {};
  83. const error = IS_OPEN_DEBUG ? console.error.bind(console) : () => {};
  84. const warn = IS_OPEN_DEBUG ? console.warn.bind(console) : () => {};
  85. const count = IS_OPEN_DEBUG ? console.count.bind(console) : () => {};
  86.  
  87. /* GM selector */
  88.  
  89. const GMsetValue = isGM ? GM.setValue : GM_setValue;
  90. const GMgetValue = isGM ? GM.getValue : GM_getValue;
  91. const GMdeleteValue = isGM ? GM.deleteValue : GM_deleteValue;
  92. const GMlistValues = isGM ? GM.listValues : GM_listValues;
  93. const GMopenInTab = isGM ? GM.openInTab : GM_openInTab;
  94. const GMxmlhttpRequest = isGM ? GM.xmlHttpRequest : GM_xmlhttpRequest;
  95. const GMregisterMenuCommand = isGM ? GM.registerMenuCommand : GM_registerMenuCommand;
  96. const GMunregisterMenuCommand = isGM ? () => {} : GM_unregisterMenuCommand;
  97.  
  98. /* default CONST Values */
  99.  
  100. const defCon = {
  101. clickTimer: 0,
  102. scriptName: getScriptNameViaLanguage(),
  103. curVersion: GMinfo.script.version || GMinfo.scriptMetaStr.match(/@version\s+(\S+)/)[1],
  104. options: isGM ? false : { active: true, insert: true, setParent: true },
  105. elCompat: document.compatMode === "CSS1Compat" ? document.documentElement : document.body,
  106. encrypt: n => {
  107. try {
  108. return window.btoa(encodeURIComponent(String(n)));
  109. } catch (e) {
  110. error("Encrypt.error:", e.message);
  111. }
  112. },
  113. decrypt: n => {
  114. try {
  115. if (typeof n === "string") {
  116. return decodeURIComponent(window.atob(n.replace(/[^A-Za-z0-9+/=]/g, "")));
  117. } else {
  118. throw new Error("Non-string type");
  119. }
  120. } catch (e) {
  121. error("Decrypt.error:", e.message);
  122. }
  123. },
  124. randString: (n, v) => {
  125. const a = "0123456789";
  126. const b = "abcdefghijklmnopqrstuvwxyz";
  127. const c = b.toUpperCase();
  128. let r, m;
  129. let s = "";
  130. let z = true;
  131. switch (v) {
  132. case "mix":
  133. m = Number(n - 1) || 8;
  134. r = b + a + c;
  135. z = false;
  136. break;
  137. case "char":
  138. m = Number(n) || 8;
  139. r = b + c;
  140. break;
  141. case "digit":
  142. m = Number(n) || 8;
  143. r = a;
  144. break;
  145. default:
  146. m = Number(n) || 8;
  147. r = c;
  148. break;
  149. }
  150. for (; m > 0; --m) {
  151. s += r[Math.floor(Math.random() * r.length)];
  152. }
  153. return z ? s : c[Math.floor(Math.random() * c.length)].concat(s);
  154. },
  155. isWinTop: () => {
  156. try {
  157. return window.self === window.top;
  158. } catch (e) {
  159. return !parent.frames.length;
  160. }
  161. },
  162. };
  163.  
  164. const CUR_WINDOW_TOP = defCon.isWinTop();
  165.  
  166. /* Define random aliases */
  167.  
  168. const Notice = {
  169. rName: defCon.randString(8, "char"),
  170. random: defCon.randString(5, "char"),
  171. noticejs: defCon.randString(7, "char"),
  172. item: defCon.randString(6, "mix"),
  173. close: defCon.randString(6, "mix"),
  174. center: defCon.randString(6, "mix"),
  175. success: defCon.randString(7, "char"),
  176. warning: defCon.randString(7, "char"),
  177. info: defCon.randString(7, "char"),
  178. error: defCon.randString(7, "char"),
  179. checkbox: defCon.randString(6, "char"),
  180. configuration: defCon.randString(7, "char"),
  181. animated: defCon.randString(7, "char"),
  182. stopUpdate: defCon.randString(6, "mix"),
  183. searchButton: defCon.randString(6, "mix"),
  184. favicon: defCon.randString(6, "mix"),
  185. favicons: defCon.randString(6, "mix"),
  186. searchList: defCon.randString(7, "mix"),
  187. fieldset: defCon.randString(6, "char"),
  188. legend: defCon.randString(6, "char"),
  189. settingList: defCon.randString(7, "mix"),
  190. hk: defCon.randString(5, "mix"),
  191. gj: defCon.randString(5, "mix"),
  192. lw: defCon.randString(5, "mix"),
  193. kh: defCon.randString(5, "mix"),
  194. ar: defCon.randString(5, "mix"),
  195. aa: defCon.randString(5, "mix"),
  196. au: defCon.randString(5, "mix"),
  197. grid: defCon.randString(7, "char"),
  198. card: defCon.randString(7, "char"),
  199. me: defCon.decrypt("Zjl5NG5n"),
  200. noticeHTML: str => {
  201. return String(`<div class="${Notice.rName}"><dl>${str}</dl></div>`);
  202. },
  203. };
  204.  
  205. /* New RAF for setTimeout & setInterval */
  206.  
  207. window.requestAnimationFrame ||
  208. (function () {
  209. "use strict";
  210. window.requestAnimationFrame =
  211. window.msRequestAnimationFrame ||
  212. window.mozRequestAnimationFrame ||
  213. window.webkitRequestAnimationFrame ||
  214. (function () {
  215. const fps = 60;
  216. const delay = 1000 / fps;
  217. const animationStartTime = Date.now();
  218. let previousCallTime = animationStartTime;
  219. return function requestAnimationFrame(callback) {
  220. const requestTime = Date.now();
  221. const timeout = Math.max(0, delay - (requestTime - previousCallTime));
  222. const timeToCall = requestTime + timeout;
  223. previousCallTime = timeToCall;
  224. return window.setTimeout(function onAnimationFrame() {
  225. callback(timeToCall - animationStartTime);
  226. }, timeout);
  227. };
  228. })();
  229. window.cancelAnimationFrame =
  230. window.mozCancelAnimationFrame ||
  231. window.webkitCancelAnimationFrame ||
  232. window.cancelRequestAnimationFrame ||
  233. window.msCancelRequestAnimationFrame ||
  234. window.mozCancelRequestAnimationFrame ||
  235. window.webkitCancelRequestAnimationFrame ||
  236. function cancelAnimationFrame(id) {
  237. window.clearTimeout(id);
  238. };
  239. })();
  240.  
  241. class RAF {
  242. constructor() {
  243. this._timerMap = {
  244. timeout: {},
  245. interval: {},
  246. };
  247. }
  248. _ticking(_fn, type = "interval", interval = 100, lastTime = Date.now()) {
  249. const timerSymbol = Symbol(type);
  250. const step = () => {
  251. this._setTimerMap(timerSymbol, type, step);
  252. if (Date.now() - lastTime >= interval || interval < 17) {
  253. _fn.call();
  254. lastTime = type === "interval" ? Date.now() : lastTime;
  255. type === "timeout" && this.clearTimeout(timerSymbol);
  256. }
  257. };
  258. this._setTimerMap(timerSymbol, type, step);
  259. return timerSymbol;
  260. }
  261. _setTimerMap(timerSymbol, type, step) {
  262. const stack = window.requestAnimationFrame(step);
  263. this._timerMap[type][timerSymbol] = stack;
  264. }
  265. setTimeout(fn, interval) {
  266. return this._ticking(fn, "timeout", interval);
  267. }
  268. clearTimeout(timer) {
  269. window.cancelAnimationFrame(this._timerMap.timeout[timer]);
  270. delete this._timerMap.timeout[timer];
  271. }
  272. setInterval(fn, interval) {
  273. return this._ticking(fn, "interval", interval);
  274. }
  275. clearInterval(timer) {
  276. window.cancelAnimationFrame(this._timerMap.interval[timer]);
  277. delete this._timerMap.interval[timer];
  278. }
  279. }
  280.  
  281. /* Sleep Promise Function */
  282.  
  283. const raf = new RAF();
  284. const cachedSetTimeout = setTimeout;
  285. const createSleepPromise = (timeout, { useCachedSetTimeout }) => {
  286. return new Promise(resolve => {
  287. useCachedSetTimeout ? cachedSetTimeout(resolve, timeout) : raf.setTimeout(resolve, timeout);
  288. }).catch(e => {
  289. error("CreateSleepPromise:", e.message);
  290. });
  291. };
  292. const sleep = function (timeout, { useCachedSetTimeout } = {}) {
  293. const sleepPromise = createSleepPromise(timeout, { useCachedSetTimeout });
  294. const promiseFunction = value => {
  295. return sleepPromise.then(() => {
  296. return value;
  297. });
  298. };
  299. promiseFunction.then = (...args) => {
  300. return sleepPromise.then(...args);
  301. };
  302. promiseFunction.catch = Promise.resolve().catch;
  303. return promiseFunction;
  304. };
  305.  
  306. /* Abbreviated functions */
  307.  
  308. const oH = Object.prototype.hasOwnProperty;
  309. const qA = (str, node = document) => {
  310. return Array.prototype.slice.call(node.querySelectorAll(str), 0);
  311. };
  312. const qS = (str, node = document) => {
  313. return node.querySelector(str);
  314. };
  315. const cE = str => {
  316. return document.createElement(str);
  317. };
  318.  
  319. /* Content-Security-Policy: trustedTypes */
  320.  
  321. if (window.trustedTypes && window.trustedTypes.createPolicy) {
  322. trustedTypesPolicy = window.trustedTypes.createPolicy("default", {
  323. createHTML: string => {
  324. return string;
  325. },
  326. });
  327. } else {
  328. trustedTypesPolicy = {
  329. createHTML: string => {
  330. return string;
  331. },
  332. };
  333. }
  334.  
  335. /* Get browser core & system parameters */
  336.  
  337. const getNavigator = {
  338. uaData: (navigator => {
  339. try {
  340. // eslint-disable-next-line no-undef
  341. return Boolean(navigator.userAgentData && navigator.userAgentData instanceof NavigatorUAData);
  342. } catch (e) {
  343. error("getNavigator.uaData:", e.message);
  344. return false;
  345. }
  346. })(unsafeWindow.navigator),
  347. init: function (v = this.uaData) {
  348. return v ? navigator.userAgentData : navigator.userAgent.toLowerCase();
  349. },
  350. core: function (u = JSON.stringify(this.init())) {
  351. return {
  352. Trident: u.includes("trident") || u.includes("compatible"),
  353. Presto: u.includes("presto"),
  354. WebKit: u.includes("applewebkit") || u.includes("Chromium"),
  355. Gecko: u.includes("gecko") && !u.includes("khtml") && !u.includes("trident") && !u.includes("compatible"),
  356. Blink: (u.includes("applewebkit") && (u.includes("chromium") || u.includes("chrome"))) || u.includes("Chromium"),
  357. };
  358. },
  359. system: function (u = this.init(), system = "Unknown") {
  360. if (this.uaData) {
  361. system = u.platform ? u.platform.toString() : system;
  362. } else {
  363. if (/windows|win32|win64|wow32|wow64/g.test(u)) {
  364. system = "Windows";
  365. } else if (/macintosh|macintel|mac os x/g.test(u)) {
  366. system = "macOS";
  367. } else if (/linux|x11/g.test(u)) {
  368. system = "Linux";
  369. } else if (/android|adr/g.test(u)) {
  370. system = "Android";
  371. } else if (/ios|iphone|ipad|ipod|iwatch/g.test(u)) {
  372. system = "iOS";
  373. }
  374. }
  375. return system;
  376. },
  377. isCheatUA: function () {
  378. return (
  379. (!this.uaData && !!navigator.userAgentData) ||
  380. (!this.core().Gecko && !isNaN(parseFloat(unsafeWindow.mozInnerScreenX))) ||
  381. (this.core().Gecko && isNaN(parseFloat(unsafeWindow.mozInnerScreenX)))
  382. );
  383. },
  384. };
  385.  
  386. const IS_REAL_GECKO = (getNavigator.core().Gecko && !getNavigator.isCheatUA()) || !isNaN(parseFloat(unsafeWindow.mozInnerScreenX));
  387.  
  388. /* expire for fontlist cache */
  389.  
  390. const cache = {
  391. value: (data, eT = 6048e5) => {
  392. return {
  393. data: data,
  394. expired: Date.now() + eT,
  395. };
  396. },
  397. set: (key, ...options) => {
  398. const obj = defCon.encrypt(JSON.stringify(cache.value(...options)));
  399. GMsetValue(key, obj);
  400. },
  401. get: async key => {
  402. const obj = await GMgetValue(key);
  403. if (!obj) {
  404. return null;
  405. } else {
  406. try {
  407. const value = JSON.parse(defCon.decrypt(obj));
  408. const data = value.data;
  409. const expiredTime = value.expired;
  410. const curTime = Date.now();
  411. if (expiredTime > curTime && typeof data !== "undefined") {
  412. return data;
  413. } else {
  414. cache.remove(key);
  415. return null;
  416. }
  417. } catch (e) {
  418. error("Cache.get:", e.message);
  419. cache.remove(key);
  420. return null;
  421. }
  422. }
  423. },
  424. remove: key => {
  425. GMdeleteValue(key);
  426. },
  427. };
  428.  
  429. /* Initialized important functions */
  430.  
  431. function getScriptNameViaLanguage() {
  432. const language = navigator.language || "zh-CN";
  433. const name_i18n = new RegExp(`(@name:${language}\\s+)(\\S+)`);
  434. const languageString = GMinfo.scriptMetaStr.match(name_i18n);
  435. const scriptName = languageString ? languageString[2] : GMinfo.script.name;
  436. return String(scriptName || "Search Engine Assistant");
  437. }
  438.  
  439. function getCookie(sKey) {
  440. const cookies = decodeURIComponent(
  441. document.cookie.replace(new RegExp("(?:(?:^|.*;)\\s*" + encodeURIComponent(sKey).replace(/[-.+*]/g, "\\$&") + "\\s*\\=\\s*([^;]*).*$)|^.*$"), "$1")
  442. );
  443. return cookies ? cookies.replace(/[a-z=]+/gi, "") : 0;
  444. }
  445.  
  446. function setRAFInterval(callback, interval, { runNow }) {
  447. if (runNow === true) {
  448. const shouldFinish = callback();
  449. if (shouldFinish) {
  450. return;
  451. }
  452. }
  453. const tickId = raf.setInterval(shouldFinish => {
  454. shouldFinish = callback() || false;
  455. if (shouldFinish) {
  456. raf.clearInterval(tickId);
  457. return;
  458. }
  459. }, interval);
  460. }
  461.  
  462. function deBounce(fn, delay, timer, immediate) {
  463. return function () {
  464. const _this = this;
  465. const args = arguments;
  466. if (!defCon[timer] && immediate) {
  467. fn.apply(_this, args);
  468. }
  469. if (defCon[timer]) {
  470. raf.clearTimeout(defCon[timer]);
  471. }
  472. defCon[timer] = raf.setTimeout(function () {
  473. fn.apply(_this, args);
  474. delete defCon[timer];
  475. }, delay);
  476. };
  477. }
  478.  
  479. function getUrlParam(paraName) {
  480. try {
  481. switch (paraName) {
  482. case null:
  483. case undefined:
  484. case "":
  485. return "";
  486. case "/":
  487. return document.location.pathname.split("/")[1] || "";
  488. default:
  489. return new URLSearchParams(document.location.search).get(paraName) || "";
  490. }
  491. } catch (e) {
  492. error("getUrlParam:", e.message);
  493. return "";
  494. }
  495. }
  496.  
  497. /* GMnotification Functions */
  498.  
  499. const Defaults = {
  500. title: "",
  501. text: "",
  502. type: `${Notice.success}`,
  503. position: "bottomRight",
  504. newestOnTop: false,
  505. timeout: 30,
  506. progressBar: true,
  507. closeWith: ["button"],
  508. animation: {
  509. open: `${Notice.animated} fadeIn`,
  510. close: `${Notice.animated} fadeOut`,
  511. },
  512. modal: false,
  513. width: 400,
  514. scroll: { maxHeight: 400, showOnHover: false },
  515. rtl: false,
  516. callbacks: { beforeShow: [], onShow: [], afterShow: [], onClose: [], afterClose: [], onClick: [], onHover: [], onTemplate: [] },
  517. };
  518. const options = Defaults;
  519. const getCallback = (ref, eventName) => {
  520. if (oH.call(ref.callbacks, eventName)) {
  521. ref.callbacks[eventName].forEach(cb => {
  522. if (typeof cb === "function") {
  523. cb.apply(ref);
  524. }
  525. });
  526. }
  527. };
  528.  
  529. const addModal = () => {
  530. if (document.getElementsByClassName(`${Notice.noticejs}-modal`).length <= 0) {
  531. const element = cE("div");
  532. element.classList.add(`${Notice.noticejs}-modal`);
  533. element.classList.add(`${Notice.noticejs}-modal-open`);
  534. document.body.appendChild(element);
  535. raf.setTimeout(() => {
  536. element.className = `${Notice.noticejs}-modal`;
  537. }, 200);
  538. }
  539. };
  540.  
  541. const closeItem = item => {
  542. getCallback(options, "onClose");
  543. if (options.animation !== null && options.animation.close !== null) {
  544. item.className += " " + options.animation.close;
  545. }
  546. raf.setTimeout(() => {
  547. item.remove();
  548. }, 200);
  549. if (options.modal === true && qA(`[${Notice.noticejs}-modal='true']`).length >= 1) {
  550. qS(`.${Notice.noticejs}-modal`).className += ` ${Notice.noticejs}-modal-close`;
  551. raf.setTimeout(() => {
  552. qS(`.${Notice.noticejs}-modal`).remove();
  553. }, 500);
  554. }
  555. const closetNode = item.closest(`.${Notice.noticejs}`);
  556. const closetNodeCName = closetNode ? closetNode.className.replace(`${Notice.noticejs}`, "").trim() : `${Notice.noticejs}-bottomRight`;
  557. const position = "." + closetNodeCName;
  558. raf.setTimeout(() => {
  559. if (qA(position + ` .${Notice.item}`).length <= 0) {
  560. qS(position) && qS(position).remove();
  561. }
  562. }, 500);
  563. };
  564.  
  565. const addListener = item => {
  566. if (options.closeWith.includes("button")) {
  567. if (item.querySelector(`.${Notice.close}`)) {
  568. item.querySelector(`.${Notice.close}`).addEventListener("click", () => {
  569. closeItem(item);
  570. });
  571. }
  572. }
  573. if (options.closeWith.includes("click")) {
  574. item.style.cursor = "pointer";
  575. item.addEventListener("click", e => {
  576. if (e.target.className !== `${Notice.close}`) {
  577. getCallback(options, "onClick");
  578. closeItem(item);
  579. }
  580. });
  581. } else {
  582. item.addEventListener("click", e => {
  583. if (e.target.className !== `${Notice.close}`) {
  584. getCallback(options, "onClick");
  585. }
  586. });
  587. }
  588. item.addEventListener("mouseover", () => {
  589. getCallback(options, "onHover");
  590. });
  591. };
  592.  
  593. const appendNoticeJs = (noticeJsHeader, noticeJsBody, noticeJsProgressBar) => {
  594. const target_class = `.${Notice.noticejs}-` + options.position;
  595. const noticeJsItem = cE("div");
  596. noticeJsItem.classList.add(`${Notice.item}`);
  597. noticeJsItem.classList.add(options.type);
  598. if (options.rtl === true) {
  599. noticeJsItem.classList.add(`${Notice.noticejs}-rtl`);
  600. }
  601. if (options.width !== "" && Number.isInteger(options.width)) {
  602. noticeJsItem.style.width = options.width + "px";
  603. }
  604. if (noticeJsHeader && noticeJsHeader !== "" && noticeJsHeader.nodeType) {
  605. noticeJsItem.appendChild(noticeJsHeader);
  606. }
  607. if (noticeJsBody.nodeType) {
  608. noticeJsItem.appendChild(noticeJsBody);
  609. }
  610. if (noticeJsProgressBar && noticeJsProgressBar !== "" && noticeJsProgressBar.nodeType) {
  611. noticeJsItem.appendChild(noticeJsProgressBar);
  612. }
  613. if (["top", "bottom"].includes(options.position)) {
  614. qS(target_class).textContent = "";
  615. }
  616. if (options.animation !== null && options.animation.open !== null) {
  617. noticeJsItem.className += " " + options.animation.open;
  618. }
  619. if (options.modal === true) {
  620. noticeJsItem.setAttribute(`${Notice.noticejs}-modal`, "true");
  621. addModal();
  622. }
  623. addListener(noticeJsItem);
  624. getCallback(options, "beforeShow");
  625. getCallback(options, "onShow");
  626. if (options.newestOnTop === true) {
  627. qS(target_class) && qS(target_class).insertAdjacentElement("afterbegin", noticeJsItem);
  628. } else {
  629. qS(target_class) && qS(target_class).appendChild(noticeJsItem);
  630. }
  631. getCallback(options, "afterShow");
  632. return noticeJsItem;
  633. };
  634.  
  635. class Components {
  636. createContainer() {
  637. const element_class = `${Notice.noticejs}-` + options.position;
  638. const element = cE("gb-notice");
  639. element.classList.add(`${Notice.noticejs}`);
  640. element.classList.add(element_class);
  641. element.id = element_class;
  642. return element;
  643. }
  644. createHeader() {
  645. let element;
  646. if (options.title && options.title !== "") {
  647. element = cE("div");
  648. element.setAttribute("class", `${Notice.noticejs}-heading`);
  649. element.textContent = options.title;
  650. }
  651. if (options.closeWith.includes("button")) {
  652. const close = cE("div");
  653. close.setAttribute("class", `${Notice.close}`);
  654. close.innerHTML = trustedTypesPolicy.createHTML("&times;");
  655. if (element) {
  656. element.appendChild(close);
  657. } else {
  658. element = close;
  659. }
  660. }
  661. return element;
  662. }
  663. createBody() {
  664. const element = cE("div");
  665. element.setAttribute("class", `${Notice.noticejs}-body`);
  666. const content = cE("div");
  667. content.setAttribute("class", `${Notice.noticejs}-content`);
  668. content.innerHTML = trustedTypesPolicy.createHTML(options.text);
  669. element.appendChild(content);
  670. if (options.scroll !== null && options.scroll.maxHeight !== "") {
  671. element.style.overflowY = "auto";
  672. element.style.maxHeight = options.scroll.maxHeight + "px";
  673. if (options.scroll.showOnHover === true) {
  674. element.style.visibility = "hidden";
  675. }
  676. }
  677. return element;
  678. }
  679. createProgressBar() {
  680. const element = cE("div");
  681. element.setAttribute("class", `${Notice.noticejs}-progressbar`);
  682. const bar = cE("div");
  683. bar.setAttribute("class", `${Notice.noticejs}-bar`);
  684. element.appendChild(bar);
  685. if (options.progressBar === true && typeof options.timeout !== "boolean" && options.timeout !== false) {
  686. let width = 100;
  687. const progress = raf.setInterval(() => {
  688. if (width <= 0) {
  689. raf.clearInterval(progress);
  690. let item = element.closest(`div.${Notice.item}`);
  691. if (options.animation !== null && options.animation.close !== null) {
  692. item.className = item.className.replace(new RegExp("(?:^|\\s)" + options.animation.open + "(?:\\s|$)"), " ");
  693. item.className += " " + options.animation.close;
  694. const close_time = parseInt(options.timeout) + 500;
  695. raf.setTimeout(() => {
  696. closeItem(item);
  697. }, close_time);
  698. } else {
  699. closeItem(item);
  700. }
  701. } else {
  702. width = width - 1;
  703. bar.style.width = width + "%";
  704. }
  705. }, options.timeout);
  706. }
  707. return element;
  708. }
  709. }
  710.  
  711. class NoticeJs {
  712. constructor(options = {}) {
  713. this.options = Object.assign(Defaults, options);
  714. this.component = new Components();
  715. this.on("beforeShow", this.options.callbacks.beforeShow);
  716. this.on("onShow", this.options.callbacks.onShow);
  717. this.on("afterShow", this.options.callbacks.afterShow);
  718. this.on("onClose", this.options.callbacks.onClose);
  719. this.on("afterClose", this.options.callbacks.afterClose);
  720. this.on("onClick", this.options.callbacks.onClick);
  721. this.on("onHover", this.options.callbacks.onHover);
  722. }
  723. show() {
  724. let container = this.component.createContainer();
  725. if (document.body && qS(`.${Notice.noticejs}-` + this.options.position) === null) {
  726. document.body.appendChild(container);
  727. }
  728. let noticeJsHeader, noticeJsBody, noticeJsProgressBar;
  729. noticeJsHeader = this.component.createHeader(this.options.title, this.options.closeWith);
  730. noticeJsBody = this.component.createBody(this.options.text);
  731. if (this.options.progressBar === true) {
  732. noticeJsProgressBar = this.component.createProgressBar();
  733. }
  734. const noticeJs = appendNoticeJs(noticeJsHeader, noticeJsBody, noticeJsProgressBar);
  735. return noticeJs;
  736. }
  737. on(eventName, cb = () => {}) {
  738. if (typeof cb === "function" && oH.call(this.options.callbacks, eventName)) {
  739. this.options.callbacks[eventName].push(cb);
  740. }
  741. return this;
  742. }
  743. static overrideDefaults(options) {
  744. this.options = Object.assign(Defaults, options);
  745. return this;
  746. }
  747. }
  748.  
  749. const fixedZoomNodeStyle = position => {
  750. if (document.body) {
  751. const zoom = Number(window.getComputedStyle(document.body, null).getPropertyValue("zoom"));
  752. const transform = window.getComputedStyle(document.body, null).getPropertyValue("transform");
  753. const thatNotice = qS(`#${Notice.noticejs}-${position}`);
  754. const rePosition = (item, top, distTop) => {
  755. let sT = -defCon.elCompat.getBoundingClientRect().top;
  756. item.style.top = `${top + sT}px`;
  757. window.scrollTo(0, sT - 1e-5);
  758. if (item.childNodes.length === 1) {
  759. defCon[distTop] = () => {
  760. sT = -defCon.elCompat.getBoundingClientRect().top;
  761. item.style.top = `${top + sT}px`;
  762. };
  763. document.addEventListener("scroll", defCon[distTop]);
  764. }
  765. };
  766. if (zoom && zoom !== 1) {
  767. thatNotice.style.cssText += `zoom:${1 / zoom}!important`;
  768. } else if (IS_REAL_GECKO && transform && transform !== "none") {
  769. const ratio = Number(transform.split(",")[3]) || 1;
  770. if (ratio && ratio !== 1) {
  771. if (thatNotice) {
  772. thatNotice.style.cssText += `width:${defCon.elCompat.clientWidth / ratio}px;height:${defCon.elCompat.clientHeight / ratio}px;top:0;left:0`;
  773. thatNotice.childNodes.forEach((item, index, array) => {
  774. let curItem = 0;
  775. switch (position) {
  776. case "topRight":
  777. item.style.cssText += String(
  778. `transform-origin:right top 0;
  779. transform:scale(${1 / ratio});
  780. position:absolute;
  781. right:${10 / ratio}px;
  782. top:${10 / ratio}px`
  783. );
  784. break;
  785. default:
  786. curItem = !index ? 10 / ratio : (array[index - 1].clientHeight + 10) / ratio + Number(array[index - 1].style.bottom.replace("px", ""));
  787. item.style.cssText += String(
  788. `transform-origin:right bottom 0;
  789. transform:scale(${1 / ratio});
  790. position:absolute;
  791. right:${10 / ratio}px;
  792. bottom:${curItem}px`
  793. );
  794. break;
  795. }
  796. });
  797. rePosition(thatNotice, 0, position);
  798. }
  799. }
  800. }
  801. }
  802. };
  803.  
  804. const GMnotification = ({ title, text, type, scroll, width, closeWith, newestOnTop, progressBar, timeout, callbacks, position }) => {
  805. try {
  806. new NoticeJs({
  807. title: title || "",
  808. text: text,
  809. type: type || `${Notice.success}`,
  810. width: width || 400,
  811. newestOnTop: newestOnTop || false,
  812. closeWith: closeWith || ["button"],
  813. progressBar: typeof progressBar === "undefined" ? true : progressBar,
  814. timeout: typeof timeout === "undefined" ? 30 : timeout,
  815. scroll: scroll || { maxHeight: 400, showOnHover: true },
  816. callbacks: { ...callbacks },
  817. position: position || "bottomRight",
  818. }).show();
  819. fixedZoomNodeStyle(position || "bottomRight");
  820. } catch (e) {
  821. error("GMnotification:", e.message);
  822. }
  823. };
  824.  
  825. /* initialize configure_data function */
  826.  
  827. let config_date, isAutoUpdate, keywordHighlight, isHotkey, selectedEngine, localWindow, googleJump, antiLinkRedirect, antiAds;
  828. async function init_Config_Data() {
  829. const configure = await GMgetValue("_configures_");
  830. if (!configure) {
  831. // delete Invalid config data for NG.
  832. const keys = await GMlistValues();
  833. for (let key of keys) {
  834. GMdeleteValue(key);
  835. }
  836. // rebuild if not exist.
  837. isAutoUpdate = true;
  838. keywordHighlight = false;
  839. isHotkey = true;
  840. selectedEngine = [1, 2, 3];
  841. localWindow = true;
  842. googleJump = true;
  843. antiLinkRedirect = true;
  844. antiAds = false;
  845. config_date = { isAutoUpdate, keywordHighlight, isHotkey, selectedEngine, localWindow, googleJump, antiLinkRedirect, antiAds };
  846. GMsetValue("_configures_", defCon.encrypt(JSON.stringify(config_date)));
  847. } else {
  848. config_date = JSON.parse(defCon.decrypt(configure));
  849. isAutoUpdate = Boolean(config_date.isAutoUpdate);
  850. keywordHighlight = Boolean(config_date.keywordHighlight);
  851. isHotkey = Boolean(config_date.isHotkey);
  852. selectedEngine = Array.isArray(config_date.selectedEngine) ? config_date.selectedEngine : [1, 2, 3];
  853. localWindow = Boolean(config_date.localWindow);
  854. googleJump = Boolean(config_date.googleJump);
  855. antiLinkRedirect = Boolean(config_date.antiLinkRedirect);
  856. antiAds = Boolean(config_date.antiAds);
  857. }
  858. }
  859.  
  860. /* auto check update */
  861.  
  862. !(async function AutoUpdate() {
  863. "use strict";
  864. await init_Config_Data();
  865. const cache_autoupdate = await cache.get("_autoupdate_");
  866. if (CUR_WINDOW_TOP && isAutoUpdate && (!cache_autoupdate || getUrlParam("whoami").endsWith(Notice.me))) {
  867. const isNeedUpdate = (current, compare) => {
  868. let updateFlag = false;
  869. const compare_array = compare.split(".");
  870. const current_array = current.split(".");
  871. if (compare_array.length === current_array.length) {
  872. for (let i = 0; i < compare_array.length; i++) {
  873. if (parseInt(compare_array[i]) < parseInt(current_array[i])) {
  874. break;
  875. } else {
  876. if (parseInt(compare_array[i]) === parseInt(current_array[i])) {
  877. continue;
  878. } else {
  879. updateFlag = true;
  880. break;
  881. }
  882. }
  883. }
  884. } else {
  885. updateFlag = true;
  886. }
  887. return updateFlag;
  888. };
  889. const rnd = Date.now().toString().slice(-8);
  890. const update = url => {
  891. return new Promise((resolve, reject) => {
  892. GMxmlhttpRequest({
  893. url: url,
  894. nocache: true,
  895. headers: { Accept: "*/*", Referer: url.replace(new URL(url).pathname, "") },
  896. method: "GET",
  897. timeout: 9e3,
  898. onreadystatechange: response => {
  899. if (response.status === 200 && response.readyState === 4) {
  900. const res = response.responseText || response.response || "";
  901. res && resolve({ res: res, source: url });
  902. }
  903. },
  904. ontimeout: () => {
  905. reject(new Error("Update.TimeoutError"));
  906. },
  907. });
  908. }).catch(e => {
  909. error("AutoUpdate.XHR:", e.message);
  910. return { res: undefined, source: undefined };
  911. });
  912. };
  913. Promise.race([
  914. update(`https://greasyfork.org/scripts/12909/code/Google%20%20baidu%20Switcher%20(ALL%20in%20One).meta.js?${rnd}`),
  915. update(`https://raw.githubusercontent.com/F9y4ng/GreasyFork-Scripts/master/Google%20%26%20Baidu%20Switcher.meta.js?${rnd}`),
  916. update(`https://openuserjs.org/install/f9y4ng/Google_baidu_Switcher_(ALL_in_One).meta.js?${rnd}`),
  917. ])
  918. .then(value => {
  919. let version, note;
  920. let updateInfoList = "";
  921. value.res
  922. ? value.res.split(/[\r\n]+/).forEach(item => {
  923. const versions = item.match(/^(\/\/\s+@version\s+)(\S+)$/);
  924. version = versions ? versions[2] : version;
  925. const notes = item.match(/^(\/\/\s+@note\s+)(.+)$/);
  926. note = notes ? notes[2] : note;
  927. })
  928. : console.warn(
  929. String(`%c[GB-UpdateError]%c\nRefused to connect to 'the UpdateList URLs', Please check your Network or local DNS!`),
  930. "font-weight:bold;color:crimson",
  931. "color:darkred"
  932. );
  933. note &&
  934. note.split(/\\n/g).forEach(item => {
  935. updateInfoList += `<li>${item}</li>`;
  936. });
  937. const updateInfo = `<dd><ul>${note ? updateInfoList : "暂时无法获取更新详情。"}</ul></dd>`;
  938. const updateHost = value.source ? new URL(value.source).hostname : null;
  939. updateHost && debug("\ud83d\udd33 [UpdateURI]: %c%s", "color:crimson", updateHost.replace(/raw\.|usercontent/g, ""));
  940. if (version) {
  941. if (isNeedUpdate(defCon.curVersion, version)) {
  942. const preInstall = () => {
  943. sleep(5e2)(value.source.replace(".meta.", ".user."))
  944. .then(url => {
  945. if (IS_REAL_GECKO) {
  946. GMopenInTab(isGM ? url.replace(/\?\d+/g, "") : url, false);
  947. } else {
  948. location.href = url;
  949. }
  950. return true;
  951. })
  952. .then(e => {
  953. const refresh = () => {
  954. location.reload(e);
  955. };
  956. GMnotification({
  957. title: `升级提示!`,
  958. text: Notice.noticeHTML(
  959. `<dd id="${Notice.random}_loading">${IS_REAL_GECKO ? "已经在新窗口打开脚本升级页面!" : "正在申请脚本更新安装页面,请稍后……"}</dd>
  960. <dd>请点击<strong>这里</strong>刷新页面,以使新版本脚本生效!</dd>`
  961. ),
  962. type: `${Notice.info}`,
  963. closeWith: ["click"],
  964. timeout: false,
  965. position: "topRight",
  966. callbacks: { onClose: [refresh] },
  967. });
  968. return qS(`#${Notice.random}_loading`);
  969. })
  970. .then(r => {
  971. sleep(2e3, { useCachedSetTimeout: true })(r).then(s => {
  972. s && s.remove();
  973. });
  974. })
  975. .catch(e => {
  976. error("preInstall:", e.message);
  977. });
  978. };
  979. sleep(5e2, { useCachedSetTimeout: true })
  980. .then(() => {
  981. GMnotification({
  982. title: `更新检测`,
  983. text: Notice.noticeHTML(
  984. `<dd><span>发现新版本</span><i>V${version}</i>,点击可自动更新。</dd>${updateInfo}<dd id="${Notice.stopUpdate}"><input type="checkbox">一周内不再提醒</dd>`
  985. ),
  986. type: `${Notice.warning}`,
  987. closeWith: ["click"],
  988. timeout: 60,
  989. callbacks: { onClick: [preInstall] },
  990. });
  991. return qS(`#${Notice.stopUpdate}`);
  992. })
  993. .then(r => {
  994. r &&
  995. r.addEventListener("click", event => {
  996. event.stopPropagation();
  997. closeItem(qS(`gb-notice.${Notice.noticejs} .${Notice.warning}`));
  998. cache.set("_autoupdate_", version);
  999. });
  1000. })
  1001. .then(() => {
  1002. console.log(
  1003. String(`%c[GB-Update]%c\nWe found a new version: %c${version}%c.You can update now!`),
  1004. "font-weight:bold;color:crimson",
  1005. "color:0",
  1006. "color:crimson",
  1007. "color:0"
  1008. );
  1009. });
  1010. } else {
  1011. sleep(5e2, { useCachedSetTimeout: true })
  1012. .then(() => {
  1013. GMnotification({
  1014. title: `更新检测`,
  1015. text: Notice.noticeHTML(`<dd style="margin: 10px 0"><span>恭喜您!</span>当前版本 <i>${defCon.curVersion}</i> 已为最新!</dd>`),
  1016. type: `${Notice.success}`,
  1017. closeWith: ["click"],
  1018. timeout: 5,
  1019. });
  1020. })
  1021. .then(cache.set("_autoupdate_", version))
  1022. .then(() => {
  1023. console.log(`%c[GB-Update]%c\nCurretVersion: %c${defCon.curVersion}%c is up-to-date!`, "font-weight:bold;color:darkcyan", "color:0", "color:crimson", "color:0");
  1024. });
  1025. }
  1026. }
  1027. })
  1028. .catch(e => {
  1029. error("CheckUpdate:", e);
  1030. });
  1031. }
  1032. })();
  1033.  
  1034. /* init CONST values */
  1035.  
  1036. const IS_MACOS = getNavigator.system().startsWith("macOS");
  1037. const API_ICO_YANDEX = defCon.decrypt("aHR0cHMlM0ElMkYlMkZmYXZpY29uLnlhbmRleC5uZXQlMkZmYXZpY29uJTJGdjI=");
  1038. const API_ICO_BACKUP = defCon.decrypt("aHR0cHMlM0ElMkYlMkZzMS5heDF4LmNvbSUyRjIwMjIlMkYwOCUyRjExJTJGdkdXVUc4LnBuZw==");
  1039. const API_ICO_DDUCKGO = defCon.decrypt("aHR0cHMlM0ElMkYlMkZpY29ucy5kdWNrZHVja2dvLmNvbSUyRmlwMg==");
  1040. const HOST_URI = defCon.decrypt("aHR0cHMlM0ElMkYlMkZncmVhc3lmb3JrLm9yZyUyRnNjcmlwdHMlMkYxMjkwOQ==");
  1041. const FEEDBACK_URI = GMinfo.scriptMetaStr.match(/(\u0040\u0073\u0075\u0070\u0070\u006f\u0072\u0074\u0055\u0052\u004c\s+)(\S+)/)[2];
  1042. const CONST = {
  1043. allSiteURIs: "",
  1044. isSecurityPolicy: false,
  1045. rndID: defCon.randString(9, "char"),
  1046. rndclassName: defCon.randString(9, "char"),
  1047. rndstyleName: defCon.randString(9, "char"),
  1048. leftButton: defCon.randString(6, "mix"),
  1049. rightButton: defCon.randString(6, "mix"),
  1050. scrollspan: defCon.randString(8, "char"),
  1051. scrollspan2: defCon.randString(8, "char"),
  1052. scrollbars: defCon.randString(8, "char"),
  1053. scrollbars2: defCon.randString(8, "char"),
  1054. };
  1055.  
  1056. CONST.noticeCss = String(
  1057. String(
  1058. `.${Notice.noticejs} *,.${Notice.noticejs} *::after,.${Notice.noticejs} *::before {scrollbar-width:thin;box-sizing:content-box;line-height:normal}.${Notice.animated}{animation-duration:1s;animation-fill-mode:both}.${Notice.animated}.infinite{animation-iteration-count:infinite}.${Notice.animated}.hinge{animation-duration:2s}.${Notice.animated}.bounceIn,.${Notice.animated}.bounceOut,.${Notice.animated}.flipOutX,.${Notice.animated}.flipOutY{animation-duration:1.25s}@keyframes fadeIn{from{opacity:0}to{opacity:1}}.fadeIn{animation-name:fadeIn}@keyframes fadeOut{from{opacity:1}to{opacity:0}}.fadeOut{animation-name:fadeOut}#${CONST.rndID} *{font-family:'Helvetica',system-ui,-apple-system,BlinkMacSystemFont,sans-serif!important;-webkit-text-stroke:initial!important;text-shadow:initial!important}.${Notice.noticejs},.${Notice.noticejs} *{font-family:'Microsoft YaHei',system-ui,-apple-system,BlinkMacSystemFont,sans-serif!important;-webkit-text-stroke:initial!important;text-shadow:initial!important}.${Notice.noticejs}-top{top:0;width:100%}.${Notice.noticejs}-top .${Notice.item}{border-radius:0!important;margin:0!important}.${Notice.noticejs}-topRight{top:10px;right:10px;z-index:10059!important}.${Notice.noticejs}-topLeft{top:10px;left:10px}.${Notice.noticejs}-topCenter{top:10px;left:50%;transform:translate(-50%)}.${Notice.noticejs}-middleLeft,.${Notice.noticejs}-middleRight{right:10px;top:50%;transform:translateY(-50%)}.${Notice.noticejs}-middleLeft{left:10px}.${Notice.noticejs}-middleCenter{top:50%;left:50%;transform:translate(-50%,-50%)}.${Notice.noticejs}-bottom{bottom:0;width:100%}.${Notice.noticejs}-bottom .${Notice.item}{border-radius:0!important;margin:0!important}.${Notice.noticejs}-bottomRight{bottom:10px;right:10px;z-index:10055!important}.${Notice.noticejs}-bottomLeft{bottom:10px;left:10px}.${Notice.noticejs}-bottomCenter{bottom:10px;left:50%;transform:translate(-50%)}.${Notice.noticejs} .${Notice.item}{margin:0 0 10px;border-radius:6px;overflow:hidden}` +
  1059. `.${Notice.noticejs} .${Notice.item} .${Notice.close}{float:right;font-size:18px!important;font-weight:700;line-height:1;color:#fff;text-shadow:0 1px 0 #fff;opacity:1;margin-right:7px}.${Notice.noticejs} .${Notice.item} .${Notice.close}:hover{opacity:.5;color:#000;cursor:pointer}.${Notice.noticejs} .${Notice.item} a{color:#fff;border-bottom:1px dashed #fff}.${Notice.noticejs} .${Notice.item} a,.${Notice.noticejs} .${Notice.item} a:hover{text-decoration:none}.${Notice.noticejs} .${Notice.success}{background-color:#64ce83}.${Notice.noticejs} .${Notice.success} .${Notice.noticejs}-heading{font-size:14px!important;background-color:#3da95c;color:#fff;padding:10px;font-weight:700}.${Notice.noticejs} .${Notice.success} .${Notice.noticejs}-body{color:#fff;padding:10px!important}.${Notice.noticejs} .${Notice.success} .${Notice.noticejs}-body:hover{visibility:visible!important}.${Notice.noticejs} .${Notice.success} .${Notice.noticejs}-content{visibility:visible}.${Notice.noticejs} .${Notice.info}{background-color:#3ea2ff}.${Notice.noticejs} .${Notice.info} .${Notice.noticejs}-heading{font-size:14px!important;background-color:#067cea;color:#fff;padding:10px;font-weight:700}.${Notice.noticejs} .${Notice.info} .${Notice.noticejs}-body{color:#fff;padding:10px!important}.${Notice.noticejs} .${Notice.info} .${Notice.noticejs}-body:hover{visibility:visible!important}.${Notice.noticejs} .${Notice.info} .${Notice.noticejs}-content{visibility:visible}.${Notice.noticejs} .${Notice.warning}{background-color:#ff7f48;}.${Notice.noticejs} .${Notice.warning} .${Notice.noticejs}-heading{font-size:14px!important;background-color:#f97038;color:#fff;padding:10px!important;font-weight:700}.${Notice.noticejs} .${Notice.warning} .${Notice.noticejs}-body{color:#fff;padding:10px}.${Notice.noticejs} .${Notice.warning} .${Notice.noticejs}-body:hover{visibility:visible!important}.${Notice.noticejs} .${Notice.warning} .${Notice.noticejs}-content{visibility:visible}.${Notice.noticejs} .${Notice.error}{background-color:#e74c3c}.${Notice.noticejs} .${Notice.error} .${Notice.noticejs}-heading{font-size:14px!important;background-color:#e93724;color:#fff;padding:10px!important;font-weight:700}.${Notice.noticejs} .${Notice.error} .${Notice.noticejs}-body{color:#fff;padding:10px}.${Notice.noticejs} .${Notice.error} .${Notice.noticejs}-body:hover{visibility:visible!important}` +
  1060. `.${Notice.noticejs} .${Notice.error} .${Notice.noticejs}-content{visibility:visible}.${Notice.configuration} input[disabled],.${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}.${Notice.noticejs} .${Notice.configuration}{background-color:linear-gradient(to right,#fcfcfc,#f2f2f7);background:-webkit-gradient(linear,0 0,0 100%,from(#fcfcfc),to(#f2f2f7));box-shadow:0 0 5px #888}.${Notice.noticejs} .${Notice.configuration} .${Notice.close}{float:right;font-size:18px!important;font-weight:700;line-height:1;color:#000;text-shadow:0 1px 0 #aaa;opacity:1;margin-right:7px}.${Notice.noticejs} .${Notice.configuration} .${Notice.close}:hover{opacity:.5;color:#555;cursor:pointer}.${Notice.noticejs} .${Notice.configuration} .${Notice.noticejs}-heading{font-size:14px!important;background-color:#e7e7e7;color:#333;padding:10px!important;font-weight:700}.${Notice.noticejs} .${Notice.configuration} .${Notice.noticejs}-body{color:#333;padding:10px}.${Notice.noticejs} .${Notice.configuration} .${Notice.noticejs}-body:hover{visibility:visible!important}.${Notice.noticejs} .${Notice.configuration} .${Notice.noticejs}-content{visibility:visible}.${Notice.noticejs} .${Notice.success} .${Notice.noticejs}-progressbar{width:100%;background-color:#64ce83;margin-top:-1px}.${Notice.noticejs} .${Notice.success} .${Notice.noticejs}-progressbar .${Notice.noticejs}-bar{width:100%;height:5px;background:#3da95c;}.${Notice.noticejs} .${Notice.info} .${Notice.noticejs}-progressbar{width:100%;background-color:#3ea2ff;margin-top:-1px}.${Notice.noticejs} .${Notice.info} .${Notice.noticejs}-progressbar .${Notice.noticejs}-bar{width:100%;height:5px;background:#067cea;}.${Notice.noticejs} .${Notice.warning} .${Notice.noticejs}-progressbar{width:100%;background-color:#ff7f48;margin-top:-1px}.${Notice.noticejs} .${Notice.warning} .${Notice.noticejs}-progressbar .${Notice.noticejs}-bar{width:100%;height:5px;background:#f44e06;}.${Notice.noticejs} .${Notice.error} .${Notice.noticejs}-progressbar{width:100%;background-color:#fd5f4e;margin-top:-1px}.${Notice.noticejs} .${Notice.error} .${Notice.noticejs}-progressbar .${Notice.noticejs}-bar{width:100%;height:5px;background:#ba2c1d;}` +
  1061. `.${Notice.noticejs} .${Notice.configuration} .${Notice.noticejs}-progressbar{width:100%;background-color:#efefef;margin-top:-1px}.${Notice.noticejs} .${Notice.configuration} .${Notice.noticejs}-progressbar .${Notice.noticejs}-bar{background:#ccc;width:100%;height:5px}@keyframes ${Notice.noticejs}-fadeOut{0%{opacity:1}to{opacity:0}}.${Notice.noticejs}-fadeOut{animation-name:${Notice.noticejs}-fadeOut}@keyframes ${Notice.noticejs}-modal-in{to{opacity:.3}}@keyframes ${Notice.noticejs}-modal-out{to{opacity:0}}.${Notice.noticejs}{position:fixed;z-index:10050}.${Notice.noticejs} ::-webkit-scrollbar{width:8px}.${Notice.noticejs} ::-webkit-scrollbar-button{width:8px;height:5px}.${Notice.noticejs} ::-webkit-scrollbar-track{border-radius:3px}.${Notice.noticejs} ::-webkit-scrollbar-thumb{background:#e1e1e1;border-radius:3px}.${Notice.noticejs} ::-webkit-scrollbar-thumb:hover{background:#cccccc;}.${Notice.noticejs}-modal{position:fixed;width:100%;height:100%;background-color:#000;z-index:999999;opacity:.3;left:0;top:0}.${Notice.noticejs}-modal-open{opacity:0;animation:${Notice.noticejs}-modal-in .3s ease-out}.${Notice.noticejs}-modal-close{animation:${Notice.noticejs}-modal-out .3s ease-out;animation-fill-mode:forwards}.${Notice.rName}{padding:2px!important}.${Notice.noticejs} .${Notice.rName} dl{margin:0!important;padding:1px!important}.${Notice.noticejs} .${Notice.rName} dl dt{margin:2px 0 6px 0!important;font-size:16px!important;font-weight:900!important}.${Notice.noticejs} .${Notice.rName} dl dd{margin:2px 2px 0 0!important;font-size:14px!important;line-height:180%!important;margin-inline-start:10px!important}.${Notice.noticejs} .${Notice.rName} .${Notice.center}{width:100%;text-align:center!important}.${Notice.noticejs} .${Notice.rName} dl dd em{color:#fff;font-family:Candara,sans-serif!important;font-size:24px!important;padding:0 5px;font-style:italic}.${Notice.noticejs} .${Notice.rName} dl dd span{font-weight:700;font-size:15px!important;margin-right:8px}.${Notice.noticejs} .${Notice.rName} dl dd i{font-family:Candara,sans-serif!important;font-size:20px!important}.${Notice.noticejs} .${Notice.rName} dl dd .im{color:gold;font-size:16px!important;font-weight:900;padding:0 3px}` +
  1062. `.${Notice.noticejs} .${Notice.warning} .${Notice.rName} ul{width:90%;display:inline-block;text-align:left;vertical-align:top;color:rgba(255, 255, 255, 0.8);padding:4px 4px 8px 4px;margin:0 0 0 8px;counter-reset:xxx 0}.${Notice.noticejs} .${Notice.warning} .${Notice.rName} li{list-style:none;font-style:italic!important;line-height:150%;position:relative;padding:0 0 2px 2px;margin:0 0 0 2px;-webkit-transition:.12s;transition:.12s}.${Notice.noticejs} .${Notice.warning} .${Notice.rName} li::before{content:counter(xxx,decimal) "、";counter-increment:xxx 1;font-family:Candara,sans-serif;font-size:1em;display:inline-block;width:1.5em;margin-left:-1.5em;-webkit-transition:.5s;transition:.5s}.${Notice.noticejs} .${Notice.warning} .${Notice.rName} #${Notice.stopUpdate}{float:right;margin:0px 5px!important;font-size:12px!important;cursor:help}#${Notice.stopUpdate} input[type='checkbox']{box-sizing:content-box;vertical-align:top;margin:2px 4px 0 0;width:14px;height:14px;cursor:help;-webkit-appearance:none;border-radius:50%;border:2px solid #fff;background:#ffa077;}#${Notice.stopUpdate}:hover input,#${Notice.stopUpdate} input:hover{background:#ba2c1d;}.${Notice.noticejs} .${Notice.configuration} .${Notice.checkbox}{display:none!important}.${Notice.noticejs} .${Notice.configuration} .${Notice.checkbox}+label{cursor:pointer;padding:11px 9px;margin:0 0 0 25px;border-radius:7px;display:inline-block;position:relative;background:#f7836d;width:58px;height:10px;box-shadow:inset 0 0 20px rgba(0,0,0,.1),0 0 10px rgba(245,146,146,.4);-webkit-box-sizing:content-box;box-sizing:content-box;word-wrap:normal!important}.${Notice.noticejs} .${Notice.configuration} .${Notice.checkbox}+label::before{position:absolute;top:0;left:0;z-index:99;-webkit-border-radius:7px;border-radius:7px;width:24px;height:32px;color:#fff;background:#fff;box-shadow:0 0 1px rgba(0,0,0,.6);content:" "}.${Notice.noticejs} .${Notice.configuration} .${Notice.checkbox}+label::after{position:absolute;top:0;left:28px;-webkit-box-sizing:content-box;box-sizing:content-box;-webkit-border-radius:100px;border-radius:100px;padding:5px;font-size:1em;font-weight:700;color:#fff;content:"OFF"}.${Notice.noticejs} .${Notice.configuration} .${Notice.checkbox}:checked+label{cursor:pointer;margin:0 0 0 25px;-webkit-box-sizing:content-box;box-sizing:content-box;background:#67a5df!important;box-shadow:inset 0 0 20px rgba(0,0,0,.1),0 0 10px rgba(146,196,245,.4)}` +
  1063. `.${Notice.noticejs} .${Notice.configuration} .${Notice.checkbox}:checked+label::after{content:"ON";left:10px}.${Notice.noticejs} .${Notice.configuration} .${Notice.checkbox}:checked+label::before{content:" ";position:absolute;z-index:99;left:52px}.${Notice.noticejs} .${Notice.configuration} button.${Notice.searchButton}{display:flex;align-content:center;justify-content:center;align-items:center;width:146px;height:25px;margin:0 0 10px 0;padding:6px 0;border-radius:6px;border:2px solid #eee;background:#fff;box-shadow:1px 1px 0px 1px #aaa;font-size:14px!important;cursor:pointer}.${Notice.noticejs} .${Notice.configuration} button.${Notice.searchButton}:hover{color:red;box-shadow:1px 1px 3px 0px #888;}.${Notice.noticejs} .${Notice.configuration} span.${Notice.favicon}{width:24px;height:24px;margin:0 6px 0 0}.${Notice.noticejs} .${Notice.configuration} ul.${Notice.searchList}{list-style:none;margin:5px;padding:2px;}.${Notice.noticejs} .${Notice.configuration} ul.${Notice.searchList} li{list-style:none;font-style:normal;margin:0}.${Notice.noticejs} .${Notice.configuration} .${Notice.fieldset}{border:2px dashed #dfdfdf;border-radius:10px;padding:4px 6px;margin:2px;background:transparent!important;width:auto;height:auto;display:block}.${Notice.noticejs} .${Notice.configuration} .${Notice.legend}{width:auto;margin:0;color:#8b0000!important;font-size:14px!important;font-weight:900!important;-webkit-user-select:all;user-select:all;display:block;padding:0 8px}.${Notice.noticejs} .${Notice.configuration} .${Notice.settingList}{padding:0;margin:0;background:transparent!important}.${Notice.noticejs} .${Notice.configuration} .${Notice.settingList} li{display:flex;list-style:none;margin:3px 0;border:none;float:none;background:transparent!important;cursor:default;-webkit-user-select:none;user-select:none;padding:2px 8px 2px 12px;height:36px;align-content:center;justify-content:space-between}.${Notice.noticejs} .${Notice.configuration} .${Notice.settingList} li>div{font:normal 700 14px/150% 'Microsoft YaHei','Helvetica Neue',sans-serif!important}.${Notice.noticejs} .${Notice.configuration} .${Notice.settingList} button{background:#fafafa;border:1px solid #ccc;border-radius:8px;min-width:65px;height:36px;padding:4px 8px;margin:0 0 0 8px;box-sizing:border-box;font-size:14px!important;font-weight:700;color:#5e5e5e;box-shadow:1px 1px 1px 0 #ccc}` +
  1064. `.${Notice.noticejs} .${Notice.configuration} .${Notice.settingList} button:hover{background:#fff;cursor:pointer}.${Notice.noticejs} .${Notice.configuration} .${Notice.settingList} .${Notice.random}__content{margin:0;height:268px;display:block}.${Notice.noticejs} .${Notice.configuration} .${Notice.settingList} .${Notice.grid}{overflow-y:auto;overflow-x:hidden;box-sizing:border-box;max-height:237px;width:266px;padding:8px;margin:4px 0 3px 0;overscroll-behavior:contain;}.${Notice.card} h2{margin:0;padding:0;border:0;font-size:100%;font:inherit;vertical-align:baseline}.${Notice.card}{--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;padding:0;margin:0}.${Notice.card}__input{position:absolute;display:block;outline:none;border:none;background:none;padding:0;margin:0;-webkit-appearance:none;}.${Notice.card}__input:checked ~ .${Notice.card}__body{--shadow:0 0 0 3px var(--card-shadow);}.${Notice.card}__input:checked ~ .${Notice.card}__body .${Notice.card}__body-cover-chackbox{--chack-bg:var(--background-chackbox);--chack-border:#fff;--chack-scale:1;--chack-opacity:1;}.${Notice.card}__input:checked ~ .${Notice.card}__body .${Notice.card}__body-cover-chackbox--svg{--stroke-color:#fff;--stroke-dashoffset:0;}.${Notice.card}__input:checked ~ .${Notice.card}__body .${Notice.card}__body-cover:after{--opacity-bg:0;}` +
  1065. `.${Notice.card}__input:disabled ~ .${Notice.card}__body{cursor:not-allowed;opacity:0.5;}.${Notice.card}__input:disabled ~ .${Notice.card}__body:active{--scale:1;}.${Notice.card}__body{display:grid;grid-auto-rows:calc(var(--card-height) - var(--header-height)) auto;background:var(--background);height:var(--card-height);width:var(--card-witght);border-radius:var(--card-radius);overflow:hidden;position:relative;cursor:pointer;box-shadow:var(--shadow, 1px 1px 3px 1px #cccccc);-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);}.${Notice.card}__body:active{--scale:0.96;}.${Notice.card}__body-cover-image{position:absolute;left:10px;top:8px;z-index:100;width:32px;height:32px;}.${Notice.card}__body-cover-image span.${Notice.favicons}{display:block;width:32px;height:32px}.${Notice.card}__body-cover-chackbox{background:var(--chack-bg, var(--background-chackbox));border:2px solid var(--chack-border, #fff);position:absolute;right:10px;top:10px;z-index:1;width:28px;height:28px;border-radius:50%;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));}.${Notice.card}__body-cover-chackbox--svg{visibility:visible!important;width:13px;height:11px;display:inline-block;vertical-align:top;fill:none;margin:8px 0 0 7px;stroke:var(--stroke-color, #fff);stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:16px;stroke-dashoffset:var(--stroke-dashoffset, 16px);-webkit-transition:stroke-dashoffset 0.4s ease var(--transition);transition:stroke-dashoffset 0.4s ease var(--transition);}` +
  1066. `.${Notice.card}__body-header{height:var(--header-height);background:var(--background);padding:4px 10px 6px 50px;}.${Notice.card}__body-header-title{color:var(--text-headline);font-weight:700!important;margin-bottom:0!important;font-size:15px!important;}.${Notice.card}__body-header-subtitle{color:var(--text-color);font-weight:500;font-size:13px!important;}.${Notice.noticejs} .${Notice.configuration} .${Notice.settingList} .${Notice.grid}{display:grid;grid-template-columns:repeat(1, 1fr);grid-gap:10px;}#${Notice.random}_help{position:relative;right:16%;background:#f07f6a!important;color:#ffffff!important;padding:4px 15px!important;border:1px solid transparent;box-shadow:0 0 6px 0 #f5846f;cursor:help}#${Notice.random}_clear{margin:0 0 0 12px;cursor:pointer;color:#666;font-weight:500}#${Notice.random}_clear:hover{color:red}#${Notice.random}_clear u{padding:0 2px;text-decoration:none}`
  1067. )
  1068. );
  1069.  
  1070. /* AntiRedirect Functions */
  1071.  
  1072. function clearHrefEvents(node) {
  1073. node.removeAttribute("data-hveid");
  1074. node.removeAttribute("data-cthref");
  1075. node.removeAttribute("data-jsarwt");
  1076. node.removeAttribute("data-usg");
  1077. node.removeAttribute("data-ved");
  1078. node.removeAttribute("ping");
  1079. node.removeAttribute("onmouseover");
  1080. node.setAttribute("target", "_blank");
  1081. return !node.getAttribute("ping");
  1082. }
  1083.  
  1084. function addTargetEvent(str, siteName) {
  1085. const requestNodes = qA(str);
  1086. requestNodes.length && count(`\ud83d\udd33 [${siteName}-Anti-Redirect]`);
  1087. requestNodes.forEach(node => {
  1088. node.setAttribute("target", "_blank");
  1089. node.removeAttribute("h");
  1090. });
  1091. }
  1092.  
  1093. function antiRedirect_Baidu(str) {
  1094. const requestNodes = qA(str);
  1095. requestNodes.length && count(`\ud83d\udd33 [Baidu-Anti-Redirect]`);
  1096. requestNodes.forEach(node => {
  1097. node.setAttribute("gd-antiredirect-status", "pending");
  1098. const url = node.href.replace(/http:/, "https:");
  1099. return new Promise((resolve, reject) => {
  1100. GMxmlhttpRequest({
  1101. url: url,
  1102. headers: { Accept: "*/*", Referer: location.href.replace(/^http:/, "https:") },
  1103. method: "GET",
  1104. timeout: 5e3,
  1105. onreadystatechange: response => {
  1106. if (response.status === 200 && response.readyState === 4) {
  1107. resolve(response.finalUrl);
  1108. }
  1109. },
  1110. onerror: e => {
  1111. if (e.error && e.error.includes("Request was redirected to a not whitelisted URL")) {
  1112. const rUrl = e.error.toString().match(/Refused to connect to "([^"]*)"/)[1];
  1113. if (typeof rUrl === "undefined" || rUrl === null || rUrl === "" || rUrl.includes("www.baidu.com/search/error")) {
  1114. reject(new Error(`URLNotExistError`));
  1115. }
  1116. resolve(rUrl);
  1117. } else if (e.responseHeaders && e.responseHeaders.match(/Location:\s*([\S]+)/)) {
  1118. resolve(e.responseHeaders.match(/Location:\s*([\S]+)/)[1]);
  1119. } else {
  1120. reject(new Error(`URLBrokenError`));
  1121. }
  1122. },
  1123. ontimeout: () => {
  1124. warn("\ud83d\udd33 Timeout-Retry: %o", { Node: node, Text: node.textContent, URL: node.href });
  1125. node.style.backgroundColor = "lemonchiffon";
  1126. GMxmlhttpRequest({
  1127. url: url,
  1128. headers: { Accept: "*/*", Referer: location.href.replace(/^http:/, "https:") },
  1129. method: "GET",
  1130. timeout: 12e3,
  1131. onload: response => {
  1132. resolve(response.finalUrl);
  1133. },
  1134. onerror: e => {
  1135. if (e.error && e.error.includes("Request was redirected to a not whitelisted URL")) {
  1136. const rUrl = e.error.toString().match(/Refused to connect to "([^"]*)"/)[1];
  1137. if (typeof rUrl === "undefined" || rUrl === null || rUrl === "" || rUrl.includes("www.baidu.com/search/error")) {
  1138. reject(new Error(`URLNotExistError`));
  1139. }
  1140. resolve(rUrl);
  1141. } else if (e.responseHeaders && e.responseHeaders.match(/Location:\s*([\S]+)/)) {
  1142. resolve(e.responseHeaders.match(/Location:\s*([\S]+)/)[1]);
  1143. } else {
  1144. reject(new Error(`URLBrokenError`));
  1145. }
  1146. },
  1147. ontimeout: () => {
  1148. reject(new Error(`TimeoutError`));
  1149. },
  1150. });
  1151. },
  1152. });
  1153. })
  1154. .then(res => {
  1155. debug("\ud83d\udd33", res);
  1156. node.href = res;
  1157. node.style.backgroundColor = null;
  1158. node.setAttribute("gd-antiredirect-status", "success");
  1159. })
  1160. .catch(e => {
  1161. node.style = "color:gray!important;text-decoration:line-through wavy red!important";
  1162. node.setAttribute("gd-antiredirect-status", "failure");
  1163. error("antiRedirect_Baidu: %s %O", e.message, { Node: node, Text: node.textContent, URL: node.href });
  1164. });
  1165. });
  1166. }
  1167.  
  1168. function antiRedirect_Sogou(str) {
  1169. const requestNodes = qA(str);
  1170. requestNodes.length && count(`\ud83d\udd33 [Sogou-Anti-Redirect]`);
  1171. requestNodes.forEach(node => {
  1172. node.setAttribute("gd-antiredirect-status", "pending");
  1173. const url = node.href;
  1174. return new Promise((resolve, reject) => {
  1175. GMxmlhttpRequest({
  1176. url: url,
  1177. headers: { Accept: "*/*", Referer: location.href },
  1178. method: "GET",
  1179. timeout: 8e3,
  1180. onreadystatechange: response => {
  1181. if (response.status === 200 && response.readyState === 4) {
  1182. const resText = response.responseText || response.response || "";
  1183. let res = resText.match(/(URL\s*=\s*')([^']+)(')/);
  1184. res = res ? res[2] : response.finalUrl || null;
  1185. resolve(res);
  1186. }
  1187. },
  1188. onerror: () => {
  1189. reject(new Error(`URLBrokenError`));
  1190. },
  1191. ontimeout: () => {
  1192. reject(new Error(`TimeoutError`));
  1193. },
  1194. });
  1195. })
  1196. .then(res => {
  1197. debug("\ud83d\udd33", res);
  1198. node.href = res || node.href;
  1199. node.setAttribute("gd-antiredirect-status", "success");
  1200. })
  1201. .catch(e => {
  1202. node.style = "color:gray!important;text-decoration:line-through wavy red!important";
  1203. node.setAttribute("gd-antiredirect-status", "failure");
  1204. error("antiRedirect_Sogou: %s %O", e.message, { Node: node, Text: node.textContent, URL: node.href });
  1205. });
  1206. });
  1207. }
  1208.  
  1209. function antiRedirect_Bing(str) {
  1210. const requestNodes = qA(str);
  1211. requestNodes.length && count("\ud83d\udd33 [Bing-Anti-Redirect]");
  1212. requestNodes.forEach(node => {
  1213. node.setAttribute("gd-antiredirect-status", "pending");
  1214. const url = node.href;
  1215. return new Promise((resolve, reject) => {
  1216. GMxmlhttpRequest({
  1217. url: url,
  1218. headers: { Accept: "*/*", Referer: location.href },
  1219. method: "GET",
  1220. timeout: 8e3,
  1221. onreadystatechange: response => {
  1222. if (response.status === 200 && response.readyState === 4) {
  1223. const resText = response.responseText || response.response || "";
  1224. let res = resText.match(/(var\s+u\s*=\s*")([^"]+)("\s*;\s*\r\n)/i);
  1225. res = res ? res[2] : response.finalUrl || null;
  1226. resolve(res);
  1227. }
  1228. },
  1229. onerror: () => {
  1230. reject(new Error(`URLBrokenError`));
  1231. },
  1232. ontimeout: () => {
  1233. reject(new Error(`TimeoutError`));
  1234. },
  1235. });
  1236. })
  1237. .then(res => {
  1238. debug("\ud83d\udd33", res);
  1239. node.href = res || node.href;
  1240. node.removeAttribute("h");
  1241. node.setAttribute("gd-antiredirect-status", "success");
  1242. })
  1243. .catch(e => {
  1244. node.style = "color:gray!important;text-decoration:line-through wavy red!important";
  1245. node.setAttribute("gd-antiredirect-status", "failure");
  1246. error("antiRedirect_Bing: %s %O", e.message, { Node: node, Text: node.textContent, URL: node.href });
  1247. });
  1248. });
  1249. addTargetEvent(".b_algo a[h]:not([gd-antiredirect-status])", "Bing.exp");
  1250. }
  1251.  
  1252. function antiRedirect_Goolge(str) {
  1253. const requestNodes = qA(str);
  1254. requestNodes.length && count("\ud83d\udd33 [Google-Anti-Redirect]");
  1255. requestNodes.forEach(node => {
  1256. node.getAttribute("href") &&
  1257. (node.getAttribute("data-hveid") ||
  1258. node.getAttribute("data-usg") ||
  1259. node.getAttribute("data-cthref") ||
  1260. node.getAttribute("data-ved") ||
  1261. node.getAttribute("ping") ||
  1262. node.getAttribute("data-jsarwt") ||
  1263. node.getAttribute("onmouseover")) &&
  1264. clearHrefEvents(node) &&
  1265. node.setAttribute("gd-antiredirect-status", "success");
  1266. });
  1267. }
  1268.  
  1269. function antiRedirect_So360(str) {
  1270. const requestNodes = qA(str);
  1271. requestNodes.length && count("\ud83d\udd33 [So360-Anti-Redirect]");
  1272. requestNodes.forEach(node => {
  1273. if (node.getAttribute("data-mdurl")) {
  1274. node.href = node.dataset.mdurl;
  1275. node.setAttribute("gd-antiredirect-status", "success");
  1276. } else {
  1277. node.setAttribute("gd-antiredirect-status", "pending");
  1278. const url = node.href;
  1279. return new Promise((resolve, reject) => {
  1280. GMxmlhttpRequest({
  1281. url: url,
  1282. headers: { Accept: "*/*", Referer: location.href },
  1283. method: "GET",
  1284. timeout: 8e3,
  1285. onreadystatechange: response => {
  1286. if (response.status === 200 && response.readyState === 4) {
  1287. const resText = response.responseText || response.response || "";
  1288. let res = resText.match(/(URL\s*=\s*')([^']+)(')/);
  1289. res = res ? res[2] : response.finalUrl || null;
  1290. resolve(res);
  1291. }
  1292. },
  1293. onerror: () => {
  1294. reject(new Error(`URLBrokenError`));
  1295. },
  1296. ontimeout: () => {
  1297. reject(new Error(`TimeoutError`));
  1298. },
  1299. });
  1300. })
  1301. .then(res => {
  1302. debug("\ud83d\udd33", res);
  1303. node.href = res || node.href;
  1304. node.setAttribute("gd-antiredirect-status", "success");
  1305. })
  1306. .catch(e => {
  1307. node.style = "color:gray!important;text-decoration:line-through wavy red!important";
  1308. node.setAttribute("gd-antiredirect-status", "failure");
  1309. error("antiRedirect_So360: %s %O", e.message, { Node: node, Text: node.textContent, URL: node.href });
  1310. });
  1311. }
  1312. node.removeAttribute("data-res");
  1313. node.removeAttribute("data-mdurl");
  1314. node.removeAttribute("data-replaceurl");
  1315. node.removeAttribute("data-initurl");
  1316. });
  1317. }
  1318.  
  1319. function antiRedirect_Toutiao(str) {
  1320. const requestNodes = qA(str);
  1321. requestNodes.length && count("\ud83d\udd33 [Toutiao-Anti-Redirect]");
  1322. requestNodes.forEach(node => {
  1323. const localUrl = node.href || "#";
  1324. const realUrl = localUrl.match(/(\/search\/jump\?url=)([^&]+)(&)/);
  1325. node.href = realUrl ? decodeURI(decodeURIComponent(realUrl[2])) : localUrl;
  1326. node.setAttribute("gd-antiredirect-status", "success");
  1327. });
  1328. }
  1329.  
  1330. /* AntiAds Functions */
  1331.  
  1332. function antiAds_RemoveNodes(str, siteName) {
  1333. const requestNodes = qA(str);
  1334. requestNodes.length && count(`\ud83d\udd33 [${siteName}-Anti-Ads]`);
  1335. requestNodes.forEach(node => {
  1336. node && node.remove();
  1337. });
  1338. // Ads Deep Cleanup
  1339. switch (siteName) {
  1340. case "Bing":
  1341. if (qA("li.b_algo:not([style*='display:none']) .b_caption>div.b_attribution:not([u])+p[class]").length > 0) {
  1342. count(`\ud83d\udd33 [${siteName}-Anti-Ads-Deep]`);
  1343. qA("li.b_algo").forEach(node => {
  1344. if (qS(".b_caption>div.b_attribution:not([u])+p[class]", node)) {
  1345. node.style.display = "none";
  1346. sleep(5e2)(node).then(r => {
  1347. r && r.remove();
  1348. });
  1349. }
  1350. });
  1351. }
  1352. break;
  1353. case "So360":
  1354. if (qA("ul.section>li span[class='txt']>s").length > 0) {
  1355. count(`\ud83d\udd33 [${siteName}-Anti-Ads-Deep]`);
  1356. qA("ul.section>li").forEach(node => {
  1357. const ads = qS("span[class='txt']>s", node);
  1358. if (ads && ads.textContent.includes("\u5e7f\u544a")) {
  1359. node && node.remove();
  1360. }
  1361. });
  1362. }
  1363. break;
  1364. }
  1365. }
  1366.  
  1367. /* Menus & Button insert */
  1368.  
  1369. !(async function () {
  1370. "use strict";
  1371. await init_Config_Data();
  1372. const selectedSite = [];
  1373.  
  1374. /* init search engine sites */
  1375.  
  1376. const listSite = {
  1377. baidu: {
  1378. SiteTypeID: 1,
  1379. SiteName: "百度一下",
  1380. SiteNick: "百度 搜索",
  1381. SiteURI: "www.baidu.com",
  1382. WebURL: "https://www.baidu.com/s?ie=utf-8&rqlang=cn&wd=",
  1383. ImgURL: "https://image.baidu.com/search/index?tn=baiduimage&ps=1&ie=utf-8&word=",
  1384. IMGType: ["baiduimage", "baiduimagedetail"],
  1385. SplitName: "tn",
  1386. MainType: ".s_btn_wr,#sugOut",
  1387. StyleCode: `a,a em{text-decoration:none!important}a:hover{text-decoration:underline!important}#form{white-space:nowrap}#u{z-index:1!important}#${CONST.rndID}{z-index:1999999995;position:relative;margin-left:4px;height:40px;display:inline-block}#${CONST.rndID} #${CONST.leftButton}{display:inline-block;margin-left:2px;height:40px}#${CONST.rndID} #${CONST.rightButton}{display:inline-block;margin-left:-1px;height:40px}#${CONST.leftButton} input{margin:0;padding:1px 12px 1px 18px!important;background:#4e6ef2;border-top-left-radius:10px;border-bottom-left-radius:10px;cursor:pointer;height:40px;color:#fff;min-width:80px;border:1px solid #3476d2;font-size:16px!important;vertical-align:top;font-weight:600}#${CONST.rightButton} input{margin:0;padding:1px 18px 1px 12px!important;background:#4e6ef2;border-top-right-radius:10px;border-bottom-right-radius:10px;cursor:pointer;height:40px;color:#fff;min-width:80px;border:1px solid #3476d2;font-size:16px!important;vertical-align:top;font-weight:600}#${CONST.leftButton} input:hover,#${CONST.rightButton} input:hover{background: #4662D9;border:1px solid #3476d2}`,
  1388. KeyStyle: "#wrapper_wrapper em",
  1389. AntiRedirect: () => {
  1390. deBounce(antiRedirect_Baidu, 200, "baidu", true)(".c-container a[href*='//www.baidu.com/link?url=']:not([gd-antiredirect-status])");
  1391. },
  1392. AntiAds: () => {
  1393. const ads_Filter = `#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`;
  1394. deBounce(antiAds_RemoveNodes, 20, "ad_baidu", true)(ads_Filter, "Baidu");
  1395. },
  1396. },
  1397. google: {
  1398. SiteTypeID: 2,
  1399. SiteName: "Google",
  1400. SiteNick: "Google 搜索",
  1401. SiteURI: "www.google.com",
  1402. WebURL: "https://www.google.com/search?hl=zh-CN&source=hp&safe=off&newwindow=1&q=",
  1403. ImgURL: "https://www.google.com/search?hl=zh-CN&source=lnms&tbm=isch&sa=X&safe=off&q=",
  1404. IMGType: ["isch"],
  1405. SplitName: "tbm",
  1406. MainType: "form button[type='submit']",
  1407. StyleCode: `#${CONST.rndID}{z-index:100;position:relative;margin:0 4px 0 -5px;display:flex;justify-content:center;align-items:center}#${CONST.rndID} #${CONST.leftButton}{padding:0 2px 0 8px}.${CONST.scrollspan}{min-height:26px}.${CONST.scrollspan2}{min-height:26px;margin-top:0!important}.${CONST.scrollbars}{display:inline-block;margin:0;height:26px!important;font-weight:400!important;font-size:13px!important}.${CONST.scrollbars2}{display:inline-block;margin:0;height:26px!important;font-weight:400!important;font-size:13px!important}#${CONST.leftButton} input{margin:0;cursor:pointer;padding:1px 12px 1px 18px!important;border:1px solid transparent;background:#1a73e8;box-shadow:none;border-top-left-radius:24px;border-bottom-left-radius:24px;min-width:90px;height:38px;font-size:16px;font-weight:600;color:#fff;vertical-align:top;}#${CONST.rightButton} input{margin:0;cursor:pointer;padding:1px 18px 1px 12px!important;border:1px solid transparent;background:#1a73e8;box-shadow:none;border-top-right-radius:24px;border-bottom-right-radius:24px;min-width:90px;height:38px;font-size:16px;font-weight:600;color:#fff;vertical-align:top;}#${CONST.leftButton} input:hover,#${CONST.rightButton} input:hover{background:#2b7de9;}`,
  1408. KeyStyle: ".aCOpRe em,.aCOpRe a em,.yXK7lf em,.yXK7lf a em,.st em,.st a em,.c2xzTb b,em.qkunPe",
  1409. AntiRedirect: () => {
  1410. deBounce(antiRedirect_Goolge, 500, "google", true)("#rcnt a:not([gd-antiredirect-ok])");
  1411. },
  1412. AntiAds: () => {
  1413. deBounce(antiAds_RemoveNodes, 20, "ad_google", true)("div[aria-label='\u5e7f\u544a'],div[aria-label='Ads'],#bottomads", "Google");
  1414. },
  1415. },
  1416. bing: {
  1417. SiteTypeID: 3,
  1418. SiteName: "Bing ®",
  1419. SiteNick: "Bing 搜索",
  1420. SiteURI: "www.bing.com",
  1421. WebURL: "https://cn.bing.com/search?q=",
  1422. ImgURL: "https://cn.bing.com/images/search?first=1&tsc=ImageBasicHover&q=",
  1423. IMGType: ["images"],
  1424. SplitName: "/",
  1425. MainType: "#sb_search",
  1426. StyleCode: `#${CONST.rndID}{z-index:1500;position:relative;display:inline-flex;top:0;left:0;height:39px;min-width:160px;width:max-content;align-content:center;justify-content: center;margin:1px 0 0 8px;padding:0}#${CONST.leftButton}{padding:0 5px 0 0;}#${CONST.rndID} input{box-sizing:border-box;cursor:pointer;min-width:80px;height:39px;background-color:#f7faff;border:1px solid #0095B7;color:#0095B7;font-weight:600;font-size:16px}#${CONST.leftButton} input{border-top-left-radius:24px;border-bottom-left-radius:24px;margin:0;padding:0 12px 0 18px;}#${CONST.rightButton} input{border-top-right-radius:24px;border-bottom-right-radius:24px;margin:0 0 0 -3px;padding:0 18px 0 12px;}.${CONST.scrollspan2}{max-height:30px;padding:0 3px 0 8px!important;margin:0!important;top:3px!important}.${CONST.scrollspan}{/*max-height:30px;top:-1px!important*/}.${CONST.scrollbars2}{border-radius:4px!important;max-height:30px;padding:0 12px!important;margin-right:0!important;vertical-align:bottom}.${CONST.scrollbars}{/*max-height:30px*/}#${CONST.leftButton} input:hover,#${CONST.rightButton} input:hover{background-color:#fff;transition:border linear .1s,box-shadow linear .3s;box-shadow:1px 1px 8px #08748D;border:2px solid #0095B7;text-shadow:0 0 1px #0095B7!important;color:#0095B7}.${Notice.random}_input{width:300px!important}`,
  1427. KeyStyle: String(
  1428. Number(getUrlParam("ensearch")) || Number(getCookie("ENSEARCH"))
  1429. ? ".b_caption p strong, .b_caption .b_factrow strong, .b_secondaryText strong,th, h2 strong, h3 strong"
  1430. : "#sp_requery strong, #sp_recourse strong, #tile_link_cn strong, .b_ad .ad_esltitle~div strong, h2 strong, .b_caption p strong, .b_snippetBigText strong, .recommendationsTableTitle+.b_slideexp strong, .recommendationsTableTitle+table strong, .recommendationsTableTitle+ul strong, .pageRecoContainer .b_module_expansion_control strong, .b_rs strong, .b_rrsr strong, #dict_ans strong, .b_listnav>.b_ans_stamp>strong, .adltwrnmsg strong"
  1431. ),
  1432. AntiRedirect: () => {
  1433. deBounce(antiRedirect_Bing, 300, "bing", true)("#b_results a[href*='.bing.com/ck/a?']:not([gd-antiredirect-status])");
  1434. },
  1435. AntiAds: () => {
  1436. deBounce(antiAds_RemoveNodes, 20, "ad_bing", true)("li.b_ad", "Bing");
  1437. },
  1438. },
  1439. duckduckgo: {
  1440. SiteTypeID: 4,
  1441. SiteName: "Duckduckgo",
  1442. SiteNick: "鸭鸭 搜索",
  1443. SiteURI: "duckduckgo.com",
  1444. WebURL: "https://duckduckgo.com/?k1=-1&kl=wt-wt&kd=-1&ko=1&kn=1&kp=-2&t=h_&ia=web&q=",
  1445. ImgURL: "https://duckduckgo.com/?k1=-1&kl=wt-wt&kd=-1&ko=s&kn=1&kp=-2&t=h_&iax=images&ia=images&q=",
  1446. IMGType: ["images"],
  1447. SplitName: "ia",
  1448. MainType: "#search_form",
  1449. StyleCode: `#${CONST.rndID}{z-index:1999999995;position:absolute;top:0;right:-188px;height:44px;display:block;}#${CONST.leftButton}{display:inline-block;height:44px}#${CONST.rightButton}{margin:0 0 0 -2px;display:inline-block;height:44px}#${CONST.leftButton} input{margin:0;cursor:pointer;padding:1px 10px 1px 15px!important;border:1px solid #00000026;box-shadow:0 2px 3px rgb(0 0 0 / 6%);background:#fff;border-top-left-radius:8px;border-bottom-left-radius:8px;min-width:90px;height:44px;font-size:16px;font-weight:400;color:#888;vertical-align:top;}#${CONST.rightButton} input{margin:0;cursor:pointer;padding:1px 15px 1px 10px!important;border:1px solid #00000026;box-shadow:0 2px 3px rgb(0 0 0 / 6%);background:#fff;border-top-right-radius:8px;border-bottom-right-radius:8px;min-width:90px;height:44px;font-size:16px;font-weight:400;color:#888;vertical-align:top;}#${CONST.rndID}:hover #${CONST.leftButton} input,#${CONST.rndID}:hover #${CONST.rightButton} input{background:#3969ef;color:#fff;}#${CONST.leftButton} input:hover,#${CONST.rightButton} input:hover{background-color:#2950bf!important;border:1px solid #00000026;color:#fff;}`,
  1450. KeyStyle: "strong, b",
  1451. AntiRedirect: () => {},
  1452. AntiAds: () => {},
  1453. },
  1454. sogou: {
  1455. SiteTypeID: 5,
  1456. SiteName: "搜狗搜索",
  1457. SiteNick: "搜狗 搜索",
  1458. SiteURI: "www.sogou.com",
  1459. WebURL: "https://www.sogou.com/web?query=",
  1460. ImgURL: "https://pic.sogou.com/pics?query=",
  1461. IMGType: ["pics", "d"],
  1462. SplitName: "/",
  1463. MainType: "input[type='submit'].sbtn1,input[type='button'][uigs='search_account'],input[type='submit'].search-btn",
  1464. StyleCode: `#${CONST.rndID}{z-index:1999999995;position:absolute;right:0;top:0;width:auto;height:34px;margin:-1px 0 0 0;padding:0;cursor:pointer;-webkit-appearance:none}#${CONST.leftButton}{display:inline;height:34px}#${CONST.rightButton}{display:inline;height:34px}#${CONST.leftButton} input{padding:0 18px!important;background:#fafafa;border-radius:3px;cursor:pointer;height:34px;color:#000;min-width:80px;border:1px solid #ababab;font-size:14px!important;font-weight:400;vertical-align:top;margin:0}#${CONST.rightButton} input{padding:0 18px!important;background:#fafafa;border-radius:3px;cursor:pointer;height:34px;color:#000;min-width:80px;border:1px solid #ababab;font-size:14px!important;font-weight:400;vertical-align:top;margin:0}#${CONST.leftButton} input:hover,#${CONST.rightButton} input:hover{background: #f2f2f2;border:1px solid #7a7a7a;}.${Notice.random}_weixin{background:#fff!important;border:1px solid #00a06a!important;color:#00a06a!important;border-radius:2px!important;font-size:15px!important}.${Notice.random}_weixin:hover{background:#f7fffd!important}`,
  1465. KeyStyle: "#wrapper em",
  1466. AntiRedirect: () => {
  1467. deBounce(antiRedirect_Sogou, 200, "sogou", true)(".vrwrap a[href^='/link?url=']:not([gd-antiredirect-status])");
  1468. },
  1469. AntiAds: () => {
  1470. const ads_Filter = "#biz_tip_box_tuiguang_float,.pz_pc_new_container,.share-wrap,.sponsored,.tgad-box";
  1471. deBounce(antiAds_RemoveNodes, 20, "ad_sogou", true)(ads_Filter, "Sogou");
  1472. },
  1473. },
  1474. fsou: {
  1475. SiteTypeID: 6,
  1476. SiteName: "F搜 ®",
  1477. SiteNick: "FSou 搜索",
  1478. SiteURI: "fsoufsou.com",
  1479. WebURL: "https://fsoufsou.com/search?tbn=all&q=",
  1480. ImgURL: "https://fsoufsou.com/search?tbn=images&q=",
  1481. IMGType: ["images"],
  1482. SplitName: "tbn",
  1483. MainType: ".input-group-container .search-icon",
  1484. StyleCode: `#${CONST.rndID}{z-index:1999999995;position:relative;height:36px;margin:0 -17px 0 15px;z-index:100;display:inline-flex;justify-content:center;align-items:center}#${CONST.rightButton}{padding:0 0 0 2px}#${CONST.leftButton} input{cursor:pointer;padding:1px 12px 1px 18px!important;border:1px solid transparent;background:#1a73e8;box-shadow:none;border-top-left-radius:22px;border-bottom-left-radius:22px;min-width:90px;height:36px;font-size:15px;font-weight:600;color:#fff;vertical-align:top;}#${CONST.rightButton} input{cursor:pointer;padding:1px 18px 1px 12px!important;border:1px solid transparent;background:#1a73e8;box-shadow:none;border-top-right-radius:22px;border-bottom-right-radius:22px;min-width:90px;height:36px;font-size:15px;font-weight:600;color:#fff;vertical-align:top;}`,
  1485. KeyStyle: ".highlight-style",
  1486. AntiRedirect: () => {},
  1487. AntiAds: () => {},
  1488. },
  1489. yandex: {
  1490. SiteTypeID: 7,
  1491. SiteName: "Yandex",
  1492. SiteNick: "Yandex 搜索",
  1493. SiteURI: "yandex.com",
  1494. WebURL: "https://yandex.com/search/?text=",
  1495. ImgURL: "https://yandex.com/images/search?from=tabbar&text=",
  1496. IMGType: ["images"],
  1497. SplitName: "/",
  1498. MainType: "form>div.search2__input",
  1499. StyleCode: `#${CONST.rndID}{z-index:1999999995;position:absolute;right:0;top:0;width:auto;height:40px;margin:0;padding:0;cursor:pointer;-webkit-appearance:none}#${CONST.leftButton}{display:inline-block;height:40px}#${CONST.rightButton}{margin:0 0 0 -2px;display:inline-block;height:40px}#${CONST.leftButton} input{cursor:pointer;padding:0 12px 0 18px!important;border:1px solid transparent;background:#fc0;box-shadow:none;border-top-left-radius:10px;border-bottom-left-radius:10px;min-width:90px;height:40px;font-size:15px;font-weight:400;color:#000;vertical-align:top;}#${CONST.rightButton} input{cursor:pointer;padding:0 18px 0 12px!important;border:1px solid transparent;background:#fc0;box-shadow:none;border-top-right-radius:10px;border-bottom-right-radius:10px;min-width:90px;height:40px;font-size:15px;font-weight:400;color:#000;vertical-align:top;}`,
  1500. KeyStyle: ".OrganicTitleContentSpan b,.OrganicTextContentSpan b",
  1501. AntiRedirect: () => {},
  1502. AntiAds: () => {},
  1503. },
  1504. so360: {
  1505. SiteTypeID: 8,
  1506. SiteName: "360搜索",
  1507. SiteNick: "360 搜索",
  1508. SiteURI: "www.so.com",
  1509. WebURL: "https://www.so.com/s?ie=utf-8&q=",
  1510. ImgURL: "https://image.so.com/i?q=",
  1511. IMGType: ["i", "view"],
  1512. SplitName: "/",
  1513. MainType: "input[type='submit'][value='搜索'],button[type='submit'][class~='so-search__button']",
  1514. StyleCode: `#hd-rtools{z-index:1!important}#${CONST.rndID}{z-index:199999995;position:relative;left:0;top:0;width:auto;height:40px;margin:0 0 0 5px;padding:0;cursor:pointer;-webkit-appearance:none}#${CONST.leftButton}{padding:0 1px 0 0;height:40px;display:inline-block;vertical-align:top}#${CONST.rightButton}{height:40px;display:inline-block;vertical-align:top}#${CONST.leftButton} input{padding:0 18px!important;background:#0fb264;border:1px solid #0fb264;border-top-left-radius:8px;border-bottom-left-radius:8px;cursor:pointer;height:40px;color:#fff;min-width:80px;font-size:16px!important;font-weight:400;vertical-align:top;margin:0 -2px 0 0}#${CONST.rightButton} input{padding:0 18px!important;background:#0fb264;border:1px solid #0fb264;border-top-right-radius:8px;border-bottom-right-radius:8px;cursor:pointer;height:40px;color:#fff;min-width:80px;font-size:16px!important;font-weight:400;vertical-align:top;margin:0}#${CONST.leftButton} input:hover,#${CONST.rightButton} input:hover{background: #109e5a;border:1px solid #109e5a;}`,
  1515. KeyStyle: "em,#mohe-newdict_dict .mh-exsentence b",
  1516. AntiRedirect: () => {
  1517. deBounce(antiRedirect_So360, 300, "so360", true)(".res-list a[href*='//www.so.com/link?m=']:not([gd-antiredirect-status])");
  1518. },
  1519. AntiAds: () => {
  1520. const ads_Filter = `#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`;
  1521. deBounce(antiAds_RemoveNodes, 20, "ad_so360", true)(ads_Filter, "So360");
  1522. },
  1523. },
  1524. toutiao: {
  1525. SiteTypeID: 9,
  1526. SiteName: "搜头条",
  1527. SiteNick: "头条 搜索",
  1528. SiteURI: "so.toutiao.com",
  1529. WebURL: "https://so.toutiao.com/search?dvpf=pc&keyword=",
  1530. ImgURL: "https://so.toutiao.com/search?dvpf=pc&pd=atlas&from=gallery&keyword=",
  1531. IMGType: ["atlas"],
  1532. SplitName: "pd",
  1533. MainType: "div[class^='search'][data-log-click]",
  1534. StyleCode: `#${CONST.rndID}{z-index:1999999995;position:absolute;right:-160px;top:0;width:auto;height:44px;margin:-1px;padding:0;cursor:pointer;-webkit-appearance:none}#${CONST.leftButton}{display:inline-block;height:44px}#${CONST.rightButton}{margin:0 0 0 -2px;display:inline-block;height:44px}#${CONST.leftButton} input{margin:0;cursor:pointer;padding:1px 10px 1px 15px!important;background:#f04142ff;border:1px solid transparent;border-top-left-radius:8px;border-bottom-left-radius:8px;min-width:90px;height:44px;font-size:18px;font-weight:500;color:#fff;vertical-align:top;}#${CONST.rightButton} input{margin:0;cursor:pointer;padding:1px 15px 1px 10px!important;background:#f04142ff;border:1px solid transparent;border-top-right-radius:8px;border-bottom-right-radius:8px;min-width:90px;height:44px;font-size:18px;font-weight:500;color:#fff;vertical-align:top;}#${CONST.leftButton} input:hover,#${CONST.rightButton} input:hover{background-color:#f04142b3;color:#fff;}`,
  1535. KeyStyle: "em",
  1536. AntiRedirect: () => {
  1537. const keyString = `.main a[href*='/search/jump?url=']:not([gd-antiredirect-status]),.main a.cs-view-block[href*='/search/jump?url=']:not([gd-antiredirect-status])`;
  1538. deBounce(antiRedirect_Toutiao, 200, "toutiao", true)(keyString);
  1539. },
  1540. AntiAds: () => {},
  1541. },
  1542. other: { SiteTypeID: 0 },
  1543. };
  1544.  
  1545. const newSiteType = {
  1546. BAIDU: listSite.baidu.SiteTypeID,
  1547. GOOGLE: listSite.google.SiteTypeID,
  1548. BING: listSite.bing.SiteTypeID,
  1549. DUCKDUCKGO: listSite.duckduckgo.SiteTypeID,
  1550. SOGOU: listSite.sogou.SiteTypeID,
  1551. FSOU: listSite.fsou.SiteTypeID,
  1552. YANDEX: listSite.yandex.SiteTypeID,
  1553. SO360: listSite.so360.SiteTypeID,
  1554. TOUTIAO: listSite.toutiao.SiteTypeID,
  1555. OTHERS: listSite.other.SiteTypeID,
  1556. };
  1557.  
  1558. let listCurrentSite, currentSite;
  1559. if (location.host.endsWith(".baidu.com")) {
  1560. currentSite = selectedEngine.includes(newSiteType.BAIDU) ? listSite.baidu : listSite.other;
  1561. listCurrentSite = listSite.baidu;
  1562. } else if (location.host.endsWith(".bing.com")) {
  1563. currentSite = selectedEngine.includes(newSiteType.BING) ? listSite.bing : listSite.other;
  1564. listCurrentSite = listSite.bing;
  1565. } else if (/^(\w+\.)?google\.[a-z.]{2,6}$/.test(location.hostname)) {
  1566. currentSite = selectedEngine.includes(newSiteType.GOOGLE) ? listSite.google : listSite.other;
  1567. listCurrentSite = listSite.google;
  1568. } else if (location.host.endsWith("duckduckgo.com")) {
  1569. currentSite = selectedEngine.includes(newSiteType.DUCKDUCKGO) ? listSite.duckduckgo : listSite.other;
  1570. listCurrentSite = listSite.duckduckgo;
  1571. } else if (location.host.endsWith(".sogou.com")) {
  1572. currentSite = selectedEngine.includes(newSiteType.SOGOU) ? listSite.sogou : listSite.other;
  1573. listCurrentSite = listSite.sogou;
  1574. } else if (location.host.endsWith("fsoufsou.com")) {
  1575. currentSite = selectedEngine.includes(newSiteType.FSOU) ? listSite.fsou : listSite.other;
  1576. listCurrentSite = listSite.fsou;
  1577. } else if (location.host.endsWith("yandex.com")) {
  1578. currentSite = selectedEngine.includes(newSiteType.YANDEX) ? listSite.yandex : listSite.other;
  1579. listCurrentSite = listSite.yandex;
  1580. } else if (location.host.endsWith(".so.com")) {
  1581. currentSite = selectedEngine.includes(newSiteType.SO360) ? listSite.so360 : listSite.other;
  1582. listCurrentSite = listSite.so360;
  1583. } else if (location.host.endsWith("so.toutiao.com")) {
  1584. currentSite = selectedEngine.includes(newSiteType.TOUTIAO) ? listSite.toutiao : listSite.other;
  1585. listCurrentSite = listSite.toutiao;
  1586. } else {
  1587. currentSite = listSite.other;
  1588. listCurrentSite = listSite.other;
  1589. }
  1590.  
  1591. for (let site in listSite) {
  1592. if (oH.call(listSite, site)) {
  1593. if (listSite[site].SiteTypeID !== newSiteType.OTHERS) {
  1594. CONST.allSiteURIs += listSite[site].SiteURI.concat(";");
  1595. }
  1596. if (listSite[site].SiteTypeID === listCurrentSite.SiteTypeID) {
  1597. defCon.curSiteName = site;
  1598. }
  1599. if (listSite[site].SiteTypeID !== currentSite.SiteTypeID && selectedEngine.includes(Number(listSite[site].SiteTypeID))) {
  1600. selectedSite.length < 2 && selectedSite.push(listSite[site]);
  1601. }
  1602. }
  1603. }
  1604.  
  1605. CONST.vim = getUrlParam(currentSite.SplitName).trim();
  1606. CONST.googleSplitLine = currentSite.SiteTypeID === newSiteType.GOOGLE ? `<span jsname="s1VaRe" class="ACRAdd M2vV3"></span>` : ``;
  1607. CONST.fsouSplitLine = currentSite.SiteTypeID === newSiteType.FSOU ? `<div class="divider"></div>` : ``;
  1608. CONST.buttonCode = String(
  1609. CONST.googleSplitLine +
  1610. CONST.fsouSplitLine +
  1611. `<span id="${CONST.leftButton}" sn="${selectedSite[0].SiteTypeID}">
  1612. <input type="button" title="${selectedSite[0].SiteNick}一下" value="${selectedSite[0].SiteName}"/>
  1613. </span>
  1614. <span id="${CONST.rightButton}" sn="${selectedSite[1].SiteTypeID}">
  1615. <input type="button" title="${selectedSite[1].SiteNick}一下" value="${selectedSite[1].SiteName}"/>
  1616. </span>`
  1617. );
  1618. CONST.highlightCss = String(`${listCurrentSite.KeyStyle} {background-color:#ffff80ad!important;color:#f73131cd!important;font-weight:700!important}`);
  1619. CONST.iconCss = String(
  1620. `.${Notice.noticejs} .${Notice.configuration} span.${Notice.favicon},
  1621. .${Notice.card}__body-cover-image span.${Notice.favicons} {
  1622. background-color:#fff;
  1623. background-image:url('${API_ICO_YANDEX}/${CONST.allSiteURIs}?size=32&stub=1'),url('${API_ICO_BACKUP}');
  1624. background-repeat:no-repeat;
  1625. }`
  1626. );
  1627. CONST.indexPage = () => {
  1628. return currentSite.SiteTypeID === newSiteType.DUCKDUCKGO ? !location.search.includes("q=") : location.pathname === "/";
  1629. };
  1630.  
  1631. if (
  1632. (listCurrentSite.SiteTypeID === newSiteType.GOOGLE && /^(lcl|flm|fin)$/.test(CONST.vim)) ||
  1633. (listCurrentSite.SiteTypeID === newSiteType.BING && /^(maps)$/.test(CONST.vim)) ||
  1634. (listCurrentSite.SiteTypeID === newSiteType.BAIDU && /^(news|vsearch)$/.test(CONST.vim)) ||
  1635. (listCurrentSite.SiteTypeID === newSiteType.SOGOU && (/^(kexue)$/.test(CONST.vim) || /^(fanyi|hanyu|gouwu|as|map)/.test(location.hostname))) ||
  1636. (listCurrentSite.SiteTypeID === newSiteType.DUCKDUCKGO && /^(maps)$/.test(getUrlParam("iaxm"))) ||
  1637. (listCurrentSite.SiteTypeID === newSiteType.YANDEX && location.pathname.includes("/direct"))
  1638. ) {
  1639. CONST.isSecurityPolicy = true;
  1640. }
  1641.  
  1642. /* SYSTEM INFO */
  1643.  
  1644. if (CUR_WINDOW_TOP && listCurrentSite.SiteTypeID !== newSiteType.OTHERS) {
  1645. const isFavEngine = currentSite.SiteTypeID !== newSiteType.OTHERS;
  1646. console.log(
  1647. `%c${defCon.scriptName}\n%cINTRO.URL:\u0020https://f9y4ng.likes.fans/SearchEngine\n%cVersion:\u0020%cV%s\n%cCurrentEngine:\u0020%c%s\n%cYourFavEngine:\u0020%c%s\n%cAntiRedirect:\u0020%c%s\n%cAntiAdvertising:\u0020%c%s\n%cSecurityPolicy:\u0020%c%s`,
  1648. "font:normal 700 16px/150% system-ui,-apple-system,BlinkMacSystemFont,sans-serif;color:crimson",
  1649. "line-height:180%;font-size:10px;color:#777;font-style:italic",
  1650. "font-size:12px;font-weight:700;color:steelblue",
  1651. "color:slategrey;text-transform:capitalize;font:italic 16px/130% Candara,'Times New Roman'",
  1652. defCon.curVersion,
  1653. "font-size:12px;font-weight:700;color:steelblue",
  1654. "color:crimson;text-transform:capitalize;font:italic 16px/130% Candara,'Times New Roman'",
  1655. defCon.curSiteName,
  1656. "font-size:12px;font-weight:700;color:steelblue",
  1657. `color:${isFavEngine ? "green" : "blue"};text-transform:capitalize;font:italic 16px/130% Candara,'Times New Roman'`,
  1658. isFavEngine,
  1659. "font-size:12px;font-weight:700;color:steelblue",
  1660. `color:${antiLinkRedirect ? "green" : "blue"};text-transform:capitalize;font:italic 16px/130% Candara,'Times New Roman'`,
  1661. antiLinkRedirect,
  1662. "font-size:12px;font-weight:700;color:steelblue",
  1663. `color:${antiAds ? "green" : "blue"};text-transform:capitalize;font:italic 16px/130% Candara,'Times New Roman'`,
  1664. antiAds,
  1665. "font-size:12px;font-weight:700;color:steelblue",
  1666. `color:${CONST.isSecurityPolicy ? "green" : "blue"};text-transform:capitalize;font:italic 16px/130% Candara,'Times New Roman'`,
  1667. CONST.isSecurityPolicy
  1668. );
  1669. }
  1670.  
  1671. /* Menus insert */
  1672.  
  1673. const addAction = {
  1674. closeConfig: (configPage = qS(`gb-notice.${Notice.noticejs} .${Notice.configuration}`)) => {
  1675. configPage && closeItem(configPage);
  1676. return !0;
  1677. },
  1678. listSearchEngine: currentSite => {
  1679. let returnHtml = "";
  1680. for (let site in listSite) {
  1681. if (oH.call(listSite, site) && listSite[site].SiteTypeID !== 0 && listSite[site].SiteTypeID !== currentSite.SiteTypeID) {
  1682. const iconStyle = String(
  1683. currentSite.SiteTypeID === newSiteType.DUCKDUCKGO
  1684. ? `background-image:url('${API_ICO_DDUCKGO}/${listSite[site].SiteURI}.ico')!important;`
  1685. : `background-position:0 ${(1 - listSite[site].SiteTypeID) * 24}px;`
  1686. ).concat(`background-attachment:local;background-size:cover;`);
  1687. returnHtml += String(
  1688. `<li>
  1689. <button class="${Notice.searchButton}" id="${listSite[site].SiteTypeID}" ${selectedEngine.includes(listSite[site].SiteTypeID) ? `title="您常用的搜索引擎"` : ``}>
  1690. <span class="${Notice.favicon} ${Notice.random}_icon" style="${iconStyle}"></span>
  1691. <span>${listSite[site].SiteNick}<sup>${selectedEngine.includes(listSite[site].SiteTypeID) ? "\u0020\u2726" : "\u0020\u0020"}</sup></span>
  1692. </button>
  1693. </li>`
  1694. );
  1695. }
  1696. }
  1697. return String(`<ul class="${Notice.searchList}">${returnHtml}</ul>`);
  1698. },
  1699. listSelectSearchEngine: () => {
  1700. let returnHtml = "";
  1701. for (let site in listSite) {
  1702. if (oH.call(listSite, site) && listSite[site].SiteTypeID !== 0) {
  1703. const iconStyle = String(
  1704. listCurrentSite.SiteTypeID === newSiteType.DUCKDUCKGO
  1705. ? `background-image:url('${API_ICO_DDUCKGO}/${listSite[site].SiteURI}.ico')!important;`
  1706. : `background-position:0 ${(1 - listSite[site].SiteTypeID) * 32}px;`
  1707. ).concat(`background-attachment:local;background-size:32px auto;`);
  1708. returnHtml += String(
  1709. `<label class="${Notice.card}">
  1710. <input class="${Notice.card}__input" type="checkbox" name="${Notice.card}_lists" data-sn="${listSite[site].SiteTypeID}"\
  1711. ${selectedEngine.includes(listSite[site].SiteTypeID) ? "checked" : "disabled"}>
  1712. <div class="${Notice.card}__body">
  1713. <header class="${Notice.card}__body-header">
  1714. <span class="${Notice.card}__body-cover-chackbox">
  1715. <svg class="${Notice.card}__body-cover-chackbox--svg" viewBox="0 0 12 10">
  1716. <polyline points="1.5 6 4.5 9 10.5 1"></polyline>
  1717. </svg>
  1718. </span>
  1719. <span class="${Notice.card}__body-cover-image">
  1720. <span class="${Notice.favicons} ${Notice.random}_icon" style="${iconStyle}"></span>
  1721. </span>
  1722. <h2 class="${Notice.card}__body-header-title" fr-fix-stroke="true">${listSite[site].SiteNick}</h2>
  1723. <p class="${Notice.card}__body-header-subtitle" style="margin:0;padding:0">${listSite[site].SiteURI}</p>
  1724. </header>
  1725. </div>
  1726. </label>`
  1727. );
  1728. }
  1729. }
  1730. return returnHtml;
  1731. },
  1732. setConfigure: () => {
  1733. sleep(500)(addAction.closeConfig()).then(r => {
  1734. if (!qS(`.${Notice.noticejs} .${Notice.configuration}`) && r) {
  1735. GMnotification({
  1736. title: `${defCon.scriptName} v${defCon.curVersion}`,
  1737. text: String(
  1738. `<fieldset class="${Notice.fieldset}">
  1739. <legend class="${Notice.legend}" title="Version ${defCon.curVersion}">
  1740. 高级功能参数设置
  1741. </legend>
  1742. <ur class="${Notice.settingList}">
  1743. <li class="${Notice.random}__content">
  1744. <div>请选择三个您最常用的搜索引擎:<span id="${Notice.random}_clear">[<u>清除</u>]</span></div>
  1745. <div class="${Notice.grid}">
  1746. ${addAction.listSelectSearchEngine()}
  1747. </div>
  1748. </li>
  1749. <li>
  1750. <div>键盘快捷键功能开关</div>
  1751. <div style="margin:-2px 2px 0 10px">
  1752. <input type="checkbox" id="${Notice.hk}" class="${Notice.checkbox}" ${isHotkey ? "checked" : ""} />
  1753. <label for="${Notice.hk}"></label>
  1754. </div>
  1755. </li>
  1756. <li>
  1757. <div>Google 国际站跳转</div>
  1758. <div style="margin:-2px 2px 0 10px">
  1759. <input type="checkbox" id="${Notice.gj}" class="${Notice.checkbox}" ${googleJump ? "checked" : ""} />
  1760. <label for="${Notice.gj}"></label>
  1761. </div>
  1762. </li>
  1763. <li>
  1764. <div>在当前浏览器窗口跳转</div>
  1765. <div style="margin:-2px 2px 0 10px">
  1766. <input type="checkbox" id="${Notice.lw}" class="${Notice.checkbox}" ${localWindow ? "checked" : ""} />
  1767. <label for="${Notice.lw}"></label>
  1768. </div>
  1769. </li>
  1770. <li>
  1771. <div>搜索关键词高亮增强</div>
  1772. <div style="margin:-2px 2px 0 10px">
  1773. <input type="checkbox" id="${Notice.kh}" class="${Notice.checkbox}" ${keywordHighlight ? "checked" : ""} />
  1774. <label for="${Notice.kh}"></label>
  1775. </div>
  1776. </li>
  1777. <li>
  1778. <div>去除链接重定向跳转</div>
  1779. <div style="margin:-2px 2px 0 10px">
  1780. <input type="checkbox" id="${Notice.ar}" class="${Notice.checkbox}" ${antiLinkRedirect ? "checked" : ""} />
  1781. <label for="${Notice.ar}"></label>
  1782. </div>
  1783. </li>
  1784. <li>
  1785. <div title="实验性功能">去除搜索结果广告<sup style="padding:0 0 0 2px;font-style:italic;color:crimson">Beta!</sup></div>
  1786. <div style="margin:-2px 2px 0 10px">
  1787. <input type="checkbox" id="${Notice.aa}" class="${Notice.checkbox}" ${antiAds ? "checked" : ""} />
  1788. <label for="${Notice.aa}"></label>
  1789. </div>
  1790. </li>
  1791. <li>
  1792. <div>更新检测(默认:开)</div>
  1793. <div style="margin:-2px 2px 0 10px">
  1794. <input type="checkbox" id="${Notice.au}" class="${Notice.checkbox}" ${isAutoUpdate ? "checked" : ""} />
  1795. <label for="${Notice.au}"></label>
  1796. </div>
  1797. </li>
  1798. <li style="float:right">
  1799. <button id="${Notice.random}_help">使用帮助</button>
  1800. <button id="${Notice.random}_cancel">取消</button>
  1801. <button id="${Notice.random}_submit">保存</button>
  1802. </li>
  1803. </ul>
  1804. </fieldset>`
  1805. ),
  1806. type: `${Notice.configuration}`,
  1807. width: 330,
  1808. closeWith: ["button"],
  1809. scroll: { maxHeight: 680, showOnHover: true },
  1810. progressBar: false,
  1811. timeout: false,
  1812. callbacks: {},
  1813. position: "topRight",
  1814. });
  1815. qA(`input[name='${Notice.card}_lists']`).forEach(node => {
  1816. node.addEventListener("click", () => {
  1817. const input_checked = qA(`input[name='${Notice.card}_lists']:checked:enabled`).length;
  1818. if (input_checked < 3) {
  1819. qA(`input[name='${Notice.card}_lists']:disabled`).forEach(item => {
  1820. item.disabled = false;
  1821. });
  1822. qS(`#${Notice.random}_clear`).style.display = input_checked === 0 ? "none" : "inline";
  1823. } else {
  1824. qA(`input[name='${Notice.card}_lists']:not(:checked)`).forEach(item => {
  1825. item.disabled = true;
  1826. });
  1827. }
  1828. });
  1829. });
  1830. qS(`#${Notice.random}_clear`).addEventListener("click", () => {
  1831. qA(`input[name='${Notice.card}_lists']:checked:enabled`).forEach(node => {
  1832. node.click();
  1833. });
  1834. });
  1835. // help
  1836. qS(`#${Notice.random}_help`).addEventListener("click", () => {
  1837. GMopenInTab(`${HOST_URI}#guide`, defCon.options);
  1838. });
  1839. // cancel
  1840. qS(`#${Notice.random}_cancel`).addEventListener("click", () => {
  1841. closeItem(qS(`gb-notice.${Notice.noticejs} .${Notice.configuration}`));
  1842. });
  1843. // submit
  1844. qS(`#${Notice.random}_submit`).addEventListener("click", () => {
  1845. let selectEngineList = [];
  1846. qA(`input[name='${Notice.card}_lists']:checked`).forEach(item => {
  1847. selectEngineList.push(Number(item.dataset.sn));
  1848. });
  1849. if (selectEngineList.length < 3) {
  1850. GMnotification({
  1851. text: Notice.noticeHTML(
  1852. `<dd><e style="font-size:24px;vertical-align:bottom">\ud83d\ude31</e>\u0020您需要选择「三个」搜索引擎,还少<em>${3 - selectEngineList.length}</em>个呢!</dd>`
  1853. ),
  1854. type: `${Notice.error}`,
  1855. closeWith: ["click"],
  1856. timeout: 18,
  1857. callbacks: {},
  1858. });
  1859. return;
  1860. }
  1861. const refresh = () => {
  1862. location.reload(true);
  1863. };
  1864. selectedEngine = selectEngineList;
  1865. isHotkey = qS(`#${Notice.hk}`).checked;
  1866. googleJump = qS(`#${Notice.gj}`).checked;
  1867. localWindow = qS(`#${Notice.lw}`).checked;
  1868. keywordHighlight = qS(`#${Notice.kh}`).checked;
  1869. antiLinkRedirect = qS(`#${Notice.ar}`).checked;
  1870. antiAds = qS(`#${Notice.aa}`).checked;
  1871. isAutoUpdate = qS(`#${Notice.au}`).checked;
  1872. config_date = { isAutoUpdate, keywordHighlight, isHotkey, selectedEngine, localWindow, googleJump, antiLinkRedirect, antiAds };
  1873. GMsetValue("_configures_", defCon.encrypt(JSON.stringify(config_date)));
  1874. GMnotification({
  1875. title: "保存成功!",
  1876. text: Notice.noticeHTML(`<dd>设置参数已成功保存,页面稍后自动刷新!</dd>`),
  1877. type: `${Notice.success}`,
  1878. closeWith: ["click"],
  1879. timeout: 10,
  1880. callbacks: { onClose: [refresh] },
  1881. });
  1882. });
  1883. }
  1884. });
  1885. },
  1886. listEngine: () => {
  1887. sleep(500)(addAction.closeConfig()).then(r => {
  1888. if (!qS(`.${Notice.noticejs} .${Notice.configuration}`) && r) {
  1889. GMnotification({
  1890. title: "\ud83d\udc4b 你想去哪里吖?",
  1891. text: addAction.listSearchEngine(listCurrentSite),
  1892. type: `${Notice.configuration}`,
  1893. width: 184,
  1894. closeWith: ["button"],
  1895. scroll: { maxHeight: 500, showOnHover: false },
  1896. timeout: 120,
  1897. callbacks: {},
  1898. position: "topRight",
  1899. });
  1900. qA(`.${Notice.noticejs} .${Notice.configuration} .${Notice.searchButton}`).forEach(item => {
  1901. item.addEventListener(
  1902. "click",
  1903. function (listCurrentSite, localWindow) {
  1904. let url;
  1905. for (let type in newSiteType) {
  1906. if (oH.call(newSiteType, type) && newSiteType[type] === Number(item.id)) {
  1907. if (listCurrentSite.IMGType.includes(getUrlParam(listCurrentSite.SplitName).trim())) {
  1908. url = listSite[type.toLowerCase()].ImgURL;
  1909. } else {
  1910. url = listSite[type.toLowerCase()].WebURL;
  1911. }
  1912. break;
  1913. }
  1914. }
  1915. if (localWindow) {
  1916. top.location.href = decodeURI(url + getQueryString());
  1917. } else {
  1918. GMopenInTab(decodeURI(url + getQueryString()), defCon.options);
  1919. }
  1920. }.bind(this, listCurrentSite, localWindow)
  1921. );
  1922. });
  1923. }
  1924. });
  1925. },
  1926. };
  1927.  
  1928. if (CUR_WINDOW_TOP) {
  1929. let parameter_Set, engine_List, feed_Back;
  1930. parameter_Set ? GMunregisterMenuCommand(parameter_Set) : debug("\ud83d\udd33 %cInstalling Font_Set_Menu", "color:gray");
  1931. parameter_Set = GMregisterMenuCommand(`\ufff0\u2699\ufe0f 搜索引擎助手参数设置${isHotkey ? "(" + String.fromCharCode(IS_MACOS ? 89 : 69) + ")" : ""}`, () => {
  1932. addAction.setConfigure();
  1933. });
  1934. engine_List ? GMunregisterMenuCommand(engine_List) : debug("\ud83d\udd33 %cInstalling Exclude_site_Menu", "color:gray");
  1935. engine_List = GMregisterMenuCommand(`\ufff2\ud83d\udc4b 嗨,你想去哪里吖?${isHotkey ? "(" + String.fromCharCode(IS_MACOS ? 75 : 86) + ")" : ""}`, () => {
  1936. addAction.listEngine();
  1937. });
  1938. feed_Back ? GMunregisterMenuCommand(feed_Back) : debug("\ud83d\udd33 %cInstalling Feed_Back_Menu", "color:gray");
  1939. feed_Back = GMregisterMenuCommand(`\ufff9\u2712\ufe0f 向作者提点儿建议${isHotkey ? "(" + String.fromCharCode(66) + ")" : ""}`, () => {
  1940. GMopenInTab(FEEDBACK_URI, defCon.options);
  1941. });
  1942. }
  1943.  
  1944. /* hotkey setting */
  1945.  
  1946. if (isHotkey && CUR_WINDOW_TOP) {
  1947. document.addEventListener("keydown", e => {
  1948. const ekey = (IS_MACOS ? e.metaKey : e.altKey) && !e.ctrlKey && !e.shiftKey;
  1949. if (e.keyCode === (IS_MACOS ? 89 : 69) && ekey) {
  1950. e.preventDefault();
  1951. if (Date.now() - defCon.clickTimer > 1e3) {
  1952. defCon.clickTimer = Date.now();
  1953. addAction.setConfigure();
  1954. }
  1955. }
  1956. if (e.keyCode === (IS_MACOS ? 75 : 86) && ekey) {
  1957. e.preventDefault();
  1958. if (Date.now() - defCon.clickTimer > 1e3) {
  1959. defCon.clickTimer = Date.now();
  1960. addAction.listEngine();
  1961. }
  1962. }
  1963. if (e.keyCode === 66 && ekey) {
  1964. e.preventDefault();
  1965. if (Date.now() - defCon.clickTimer > 5e3) {
  1966. defCon.clickTimer = Date.now();
  1967. GMopenInTab(FEEDBACK_URI, defCon.options);
  1968. }
  1969. }
  1970. });
  1971. }
  1972.  
  1973. /* Insert CSS & buttons */
  1974.  
  1975. CUR_WINDOW_TOP && preInsertContentsToDocument();
  1976. new MutationObserver(() => {
  1977. if (CONST.isSecurityPolicy ? !qS(`.${CONST.rndstyleName}`) : !qS(`.${CONST.rndclassName}`) || !qS(`#${CONST.rndID}`) || !qS(`.${CONST.rndstyleName}`)) {
  1978. preInsertContentsToDocument();
  1979. }
  1980. antiLinkRedirect && listCurrentSite.SiteTypeID !== newSiteType.OTHERS && !CONST.indexPage() && listCurrentSite.AntiRedirect();
  1981. antiAds && listCurrentSite.SiteTypeID !== newSiteType.OTHERS && listCurrentSite.AntiAds();
  1982. }).observe(document, { childList: true, subtree: true });
  1983.  
  1984. /* important Functions */
  1985.  
  1986. function preInsertContentsToDocument() {
  1987. try {
  1988. setRAFInterval(
  1989. () => {
  1990. !qS(`.${CONST.rndstyleName}`) && insertStyle();
  1991. if (currentSite.SiteTypeID !== newSiteType.OTHERS && !CONST.isSecurityPolicy) {
  1992. !qS(`.${CONST.rndclassName}`) && insertCSS();
  1993. !qS(`#${CONST.rndID}`) && insertButtons();
  1994. }
  1995. return Boolean(CONST.isSecurityPolicy ? qS(`.${CONST.rndstyleName}`) : qS(`.${CONST.rndclassName}`) && qS(`#${CONST.rndID}`) && qS(`.${CONST.rndstyleName}`));
  1996. },
  1997. 50,
  1998. { runNow: true }
  1999. );
  2000. } catch (e) {
  2001. error("InsertHTML:", e.message);
  2002. }
  2003. }
  2004.  
  2005. function insertCSS() {
  2006. try {
  2007. const buttonCss = `@charset "UTF-8";` + currentSite.StyleCode;
  2008. addStyle(buttonCss, `${CONST.rndclassName}`, document.head, "SC");
  2009. } catch (e) {
  2010. error("insertCSS:", e.message);
  2011. }
  2012. }
  2013.  
  2014. function insertStyle() {
  2015. try {
  2016. const noticeStyle = `@charset "UTF-8";` + CONST.noticeCss + CONST.iconCss + String(keywordHighlight ? CONST.highlightCss : "");
  2017. addStyle(noticeStyle, `${CONST.rndstyleName}`, document.head, "SS");
  2018. } catch (e) {
  2019. error("insertStyle:", e.message);
  2020. }
  2021. }
  2022.  
  2023. function insertButtons() {
  2024. try {
  2025. const getTarget = currentSite.MainType;
  2026. const userSpan = cE("span");
  2027. const indexPage = CONST.indexPage();
  2028. userSpan.id = `${CONST.rndID}`;
  2029. userSpan.innerHTML = CONST.buttonCode;
  2030. const SpanID = `#${userSpan.id}`;
  2031. let Target = qS(getTarget);
  2032. if (!indexPage && Target && getQueryString() && !qS(SpanID)) {
  2033. return new Promise(resolve => {
  2034. switch (currentSite.SiteTypeID) {
  2035. case newSiteType.BAIDU:
  2036. insterAfter(userSpan, Target);
  2037. if (qS(SpanID)) {
  2038. switch (CONST.vim) {
  2039. case currentSite.IMGType[0]:
  2040. qS(SpanID).style.marginLeft = "16px";
  2041. qS(`#${CONST.rightButton} input`).style.marginLeft = "3px";
  2042. break;
  2043. case currentSite.IMGType[1]:
  2044. qS(SpanID).style.height = "34px";
  2045. qA(`${SpanID} input`).forEach(node => {
  2046. node.style.cssText = "min-width:90px;height:34px;padding:0 5px!important;color:#fff;background:#38f;border-radius:0;border:1px solid #2d78f4";
  2047. });
  2048. break;
  2049. }
  2050. }
  2051. break;
  2052. case newSiteType.GOOGLE:
  2053. getGlobalGoogle("www.google.com", googleJump);
  2054. insterAfter(userSpan, Target);
  2055. if (qS(SpanID)) {
  2056. qS(SpanID).parentNode.style.width = "100%";
  2057. qS(SpanID).parentNode.style.minWidth = "100%";
  2058. qS(SpanID).parentNode.parentNode.style.width = "100%";
  2059. qS(SpanID).parentNode.parentNode.parentNode.style.width = "95%";
  2060. if (currentSite.IMGType.includes(CONST.vim)) {
  2061. qS(SpanID).parentNode.firstElementChild.style.width = "400px";
  2062. }
  2063. }
  2064. break;
  2065. case newSiteType.BING:
  2066. Target.appendChild(userSpan);
  2067. if (Target.parentNode.firstElementChild.tagName === "INPUT") {
  2068. Target.parentNode.firstElementChild.style.width = "400px";
  2069. }
  2070. if (qS(".b_searchboxForm") && location.search.includes("view=detailV2")) {
  2071. qS(".b_searchboxForm").style.cssText += "width:max-content!important;padding-right:5px!important";
  2072. qA(`#${CONST.rndID} input`).forEach(node => {
  2073. node.style.cssText += "height:36px!important;border-radius:6px!important;padding:0 12px!important;margin:0 -2px 0 0!important;";
  2074. });
  2075. }
  2076. break;
  2077. case newSiteType.SOGOU:
  2078. if (currentSite.IMGType.includes(CONST.vim)) {
  2079. sleep(500, { useCachedSetTimeout: true }).then(() => {
  2080. if (!qS(SpanID) && Target) {
  2081. insterAfter(userSpan, Target);
  2082. qS(SpanID).style.right = `-${qS(SpanID).getBoundingClientRect().width + 10}px`;
  2083. addSearchButtonEvent(qA(`${SpanID} span[sn]:not([event-insert])`));
  2084. scrollDetect(getTarget, indexPage);
  2085. }
  2086. });
  2087. } else if (CONST.vim.endsWith("weixin")) {
  2088. insterAfter(userSpan, Target);
  2089. qS(SpanID).style = "position:relative";
  2090. qA(`${SpanID} input`).forEach(node => {
  2091. node.classList.add(`${Notice.random}_weixin`);
  2092. });
  2093. } else {
  2094. insterAfter(userSpan, Target);
  2095. qS(`#searchBtn2[value="\u5168\u7f51\u641c\u7d22"]`) && qS(`#searchBtn2[value="\u5168\u7f51\u641c\u7d22"]`).remove();
  2096. sleep(200, { useCachedSetTimeout: true }).then(() => {
  2097. qS(SpanID).style.right = `-${qS(SpanID).getBoundingClientRect().width + 10}px`;
  2098. qS(`#searchBtn2`) && (qS(`#searchBtn2`).style.right = `-${qS(SpanID).getBoundingClientRect().width + 120}px`);
  2099. });
  2100. }
  2101. break;
  2102. case newSiteType.SO360:
  2103. insterAfter(userSpan, Target);
  2104. if (currentSite.IMGType.includes(CONST.vim)) {
  2105. qA(`${SpanID} input`).forEach(node => {
  2106. node.style = "margin:0 0 0 1px;";
  2107. });
  2108. }
  2109. break;
  2110. case newSiteType.FSOU:
  2111. insterAfter(userSpan, Target);
  2112. break;
  2113. case newSiteType.DUCKDUCKGO:
  2114. Target.parentNode.appendChild(userSpan);
  2115. Target.parentNode.appendChild(Target.cloneNode(true));
  2116. Target.remove();
  2117. sleep(100).then(() => {
  2118. qS(SpanID).style.right = `-${qS(SpanID).getBoundingClientRect().width + 8}px`;
  2119. });
  2120. break;
  2121. case newSiteType.TOUTIAO:
  2122. insterAfter(userSpan, Target);
  2123. sleep(100).then(() => {
  2124. qS(SpanID).style.right = `-${qS(SpanID).getBoundingClientRect().width + 10}px`;
  2125. });
  2126. break;
  2127. case newSiteType.YANDEX:
  2128. insterAfter(userSpan, Target);
  2129. sleep(500, { useCachedSetTimeout: true })(qS(SpanID).getBoundingClientRect().width).then(width => {
  2130. qS(SpanID).style.right = `-${width + 60}px`;
  2131. if (currentSite.IMGType !== CONST.vim) {
  2132. qS(`.input__settings`) && (qS(`.input__settings`).style.right = `-${width + 273}px`);
  2133. qS(`span.serp-header__voice-search-container`) && (qS(`span.serp-header__voice-search-container`).style.right = `-${width + 273}px`);
  2134. } else {
  2135. qS(`button.button2[data-bem]`) && (qS(`button.button2[data-bem]`).style.right = `-${width + 268}px`);
  2136. }
  2137. });
  2138. break;
  2139. }
  2140. resolve({ SpanID, getTarget, indexPage });
  2141. })
  2142. .then(r => {
  2143. addSearchButtonEvent(qA(`${r.SpanID} span[sn]:not([event-insert])`));
  2144. scrollDetect(r.getTarget, r.indexPage);
  2145. })
  2146. .catch(e => {
  2147. error("insertHTML:", e);
  2148. });
  2149. }
  2150. } catch (e) {
  2151. error("insertButtons:", e.message);
  2152. }
  2153. }
  2154.  
  2155. function scrollDetect(getTarget, indexPage) {
  2156. let scrollbars, scrollspan, height, e;
  2157. if (!indexPage && qS(getTarget)) {
  2158. switch (currentSite.SiteTypeID) {
  2159. case newSiteType.GOOGLE:
  2160. e = /^isch$/.test(CONST.vim);
  2161. scrollspan = e ? CONST.scrollspan2 : CONST.scrollspan;
  2162. scrollbars = e ? CONST.scrollbars2 : CONST.scrollbars;
  2163. height = e ? 0 : 35;
  2164. setScrollButton(`#${CONST.rndID}`, scrollspan, height);
  2165. setScrollButton(`#${CONST.rndID} #${CONST.leftButton} input`, scrollbars, height);
  2166. setScrollButton(`#${CONST.rndID} #${CONST.rightButton} input`, scrollbars, height);
  2167. break;
  2168. case newSiteType.BING:
  2169. e = /^(images|videos)$/.test(CONST.vim);
  2170. scrollspan = e ? CONST.scrollspan2 : CONST.scrollspan;
  2171. scrollbars = e ? CONST.scrollbars2 : CONST.scrollbars;
  2172. !e && setScrollButton(`#sb_form_q`, `${Notice.random}_input`, 200); // fixed bing searchbar scroll style (new A/B Testing). 2022.08.16
  2173. setScrollButton(`#${CONST.rndID}`, scrollspan, 50);
  2174. setScrollButton(`#${CONST.rndID} #${CONST.leftButton} input`, scrollbars, 50);
  2175. setScrollButton(`#${CONST.rndID} #${CONST.rightButton} input`, scrollbars, 50);
  2176. break;
  2177. }
  2178. }
  2179. }
  2180.  
  2181. function insterAfter(newElement, targetElement) {
  2182. if (targetElement !== null) {
  2183. const parent = targetElement.parentNode;
  2184. if (parent.lastChild === targetElement) {
  2185. parent.appendChild(newElement);
  2186. } else {
  2187. parent.insertBefore(newElement, targetElement.nextSibling);
  2188. }
  2189. }
  2190. }
  2191.  
  2192. function addSearchButtonEvent(nodes) {
  2193. let gotoUrl = "about:blank";
  2194. nodes.forEach(node => {
  2195. node.setAttribute("event-insert", true);
  2196. qS("input", node).addEventListener("click", () => {
  2197. CONST.vim = getUrlParam(currentSite.SplitName).trim();
  2198. switch (Number(node.getAttribute("sn"))) {
  2199. case selectedSite[0].SiteTypeID:
  2200. if (currentSite.IMGType.includes(CONST.vim)) {
  2201. gotoUrl = selectedSite[0].ImgURL;
  2202. } else {
  2203. gotoUrl = selectedSite[0].WebURL;
  2204. }
  2205. break;
  2206. case selectedSite[1].SiteTypeID:
  2207. if (currentSite.IMGType.includes(CONST.vim)) {
  2208. gotoUrl = selectedSite[1].ImgURL;
  2209. } else {
  2210. gotoUrl = selectedSite[1].WebURL;
  2211. }
  2212. break;
  2213. }
  2214. if (localWindow) {
  2215. top.location.href = decodeURI(gotoUrl + getQueryString());
  2216. } else {
  2217. GMopenInTab(decodeURI(gotoUrl + getQueryString()), defCon.options);
  2218. }
  2219. });
  2220. });
  2221. }
  2222.  
  2223. function addStyle(css, className, addToTarget, T = "T", isReload = false, initType = "text/css") {
  2224. setRAFInterval(
  2225. () => {
  2226. try {
  2227. if (addToTarget && typeof addToTarget === "object") {
  2228. if (className && typeof className === "string") {
  2229. if (isReload === true && addToTarget.querySelector(`.${className}`)) {
  2230. safeRemove(`.${className}`, addToTarget);
  2231. } else if (isReload === false && addToTarget.querySelector(`.${className}`)) {
  2232. return true;
  2233. }
  2234. } else {
  2235. className = defCon.randString(10, "char");
  2236. }
  2237. let cssNode = cE("style");
  2238. cssNode.className = className;
  2239. cssNode.id = T + defCon.randString(null, "digit");
  2240. cssNode.media = "screen";
  2241. cssNode.type = initType;
  2242. cssNode.textContent = css;
  2243. addToTarget.appendChild(cssNode);
  2244. cssNode = null;
  2245. return Boolean(addToTarget.querySelector(`.${className}`));
  2246. } else {
  2247. return true;
  2248. }
  2249. } catch (e) {
  2250. error("AddStyle:", e.message);
  2251. return true;
  2252. }
  2253. },
  2254. 20,
  2255. true
  2256. );
  2257. }
  2258.  
  2259. function safeRemove(Css) {
  2260. try {
  2261. const removeNodes = qA(Css);
  2262. for (let i = 0; i < removeNodes.length; i++) {
  2263. removeNodes[i].remove();
  2264. }
  2265. } catch (e) {
  2266. error("safeRemove:", e.name);
  2267. }
  2268. }
  2269.  
  2270. function setScrollButton(paraName, classNameIn, scrollSize) {
  2271. const oDiv = qS(paraName);
  2272. let H = 0;
  2273. let Y = oDiv;
  2274. if (Y !== null) {
  2275. debug(`\ud83d\udd33 %s %O`, Y.nodeName, { Y });
  2276. while (Y) {
  2277. H += Y.offsetTop;
  2278. Y = Y.offsetParent;
  2279. }
  2280. document.addEventListener("scroll", () => {
  2281. if (defCon.elCompat.scrollTop > H + scrollSize) {
  2282. oDiv.classList.add(classNameIn);
  2283. } else {
  2284. oDiv.classList.remove(classNameIn);
  2285. }
  2286. });
  2287. }
  2288. }
  2289.  
  2290. function getQueryString() {
  2291. let val = "";
  2292. qA(
  2293. `input[id="kw"][name^="w"],input[name="q"]:not([type="hidden"]),input[name="text"][type="text"],input[name="query"][class$="query"],input[name="keyword"],input[id="search-input"],input[type="search"][class^="input"]`
  2294. ).forEach((item, index, arr) => {
  2295. val = item.value;
  2296. val && debug(`\ud83d\udd33 QueryString[INPUT]: %O`, { current_keyword: val, input_index: index, previous_keyword: arr[index].value });
  2297. });
  2298. if (val === null || val === "" || typeof val === "undefined") {
  2299. const keys = ["wd", "word", "query", "q", "text", "keyword"];
  2300. for (let i = 0; i < keys.length; i++) {
  2301. const queryString = getUrlParam(keys[i]);
  2302. if (queryString) {
  2303. val = queryString;
  2304. debug(`\ud83d\udd33 QueryString[URL]: %s`, val);
  2305. break;
  2306. }
  2307. }
  2308. val = val ? val.replace(/\+/g, " ") : "";
  2309. }
  2310. return encodeURIComponent(val);
  2311. }
  2312.  
  2313. function getGlobalGoogle(google, checkGoogleJump) {
  2314. if (checkGoogleJump) {
  2315. const getRealHostName = hostname => {
  2316. const index = hostname || top.location.hostname;
  2317. return index.substring(index.indexOf("google"));
  2318. };
  2319. if (getRealHostName() !== getRealHostName(google) && !sessionStorage.getItem("_global_google_")) {
  2320. sessionStorage.setItem("_global_google_", 1);
  2321. const redirectNCR = () => {
  2322. defCon.s && defCon.s.close();
  2323. delete defCon.s;
  2324. sessionStorage.removeItem("_global_google_");
  2325. top.location.href = top.location.href.replace(top.location.hostname, google);
  2326. };
  2327. try {
  2328. sleep(500).then(() => {
  2329. defCon.s = GMopenInTab(`https://${google}/ncr`, true);
  2330. GMnotification({
  2331. title: `智能跳转`,
  2332. text: Notice.noticeHTML(`<dd class="${Notice.center}">当前页面即将跳转至 Google国际站(NCR)<br/><span>${google.toUpperCase()}</span></dd>`),
  2333. type: `${Notice.info}`,
  2334. closeWith: ["click"],
  2335. timeout: 20,
  2336. callbacks: { onClose: [redirectNCR] },
  2337. });
  2338. });
  2339. } catch (e) {
  2340. error("getGlobalGoogle:", e.message);
  2341. }
  2342. }
  2343. }
  2344. }
  2345. })();
  2346. })();