// ==UserScript== // @name Metasearch // @namespace https://github.com/Jkker/metasearch-tampermonkey // @version 1.2.1 // @description Aggregated Searcher // @author Jkker // @license MIT // @match *://google.com/search* // @match *://*.google.com/search* // @match *://baidu.com/s* // @match *://*.baidu.com/s* // @match *://zhihu.com/search* // @match *://*.zhihu.com/search* // @match *://bilibili.com/all* // @match *://*.bilibili.com/all* // @match *://duckduckgo.com/* // @match *://*.duckduckgo.com/* // @match *://youtube.com/results* // @match *://*.youtube.com/results* // @match *://github.com/search* // @match *://*.github.com/search* // @match *://twitter.com/search* // @match *://*.twitter.com/search* // @match *://wolframalpha.com/input* // @match *://*.wolframalpha.com/input* // @match *://weibo.com/weibo* // @match *://*.weibo.com/weibo* // @match *://bing.com/dict/search* // @match *://*.bing.com/dict/search* // @match *://youdao.com/result* // @match *://*.youdao.com/result* // @match *://amazon.com/s* // @match *://*.amazon.com/s* // @match *://ebay.com/sch/i.html* // @match *://*.ebay.com/sch/i.html* // @match *://jd.com/bases/m/searchKeyword.htm* // @match *://*.jd.com/bases/m/searchKeyword.htm* // @match *://taobao.com/search* // @match *://*.taobao.com/search* // @match *://mozilla.org/en-US/search* // @match *://*.mozilla.org/en-US/search* // @icon https://raw.githubusercontent.com/Jkker/metasearch-tampermonkey/master/src/favicon.ico // @grant none // @supportURL https://github.com/Jkker/metasearch-tampermonkey/issues // @downloadURL none // ==/UserScript== (function() { var _a, _b; "use strict"; const allEngines = [ { name: "Google", key: "google", disabled: false, url: "https://www.google.com/search?igu=1&pws=0&gl=us&gws_rd=cr&source=hp&newwindow=1&q=%s&oq=%s&safe=off", matchSite: /^https?:\/\/www\.google(?:\.[A-z]{2,3}){1,2}\/[^?]+\?(?!tbm=)(?:&?q=|(?:[^#](?!&tbm=))+?&q=)(?:.(?!&tbm=))*$|(^https?:\/\/xn--flw351e\.ml\/search\?q=)/i, preload: false, embeddable: true, weight: 10, url_scheme: "", lightness: 0.607843137254902, color: "#4285F4", icon: '' }, { name: "\u767E\u5EA6", key: "baidu", disabled: false, url: "https://www.baidu.com/s?ie=utf-8&word=%s", matchSite: /^https?:\/\/www\.baidu\.com\/(?:s|baidu)/i, preload: false, embeddable: true, weight: 9, lightness: 0.5078431372549019, color: "#556dea", icon: '', q: ["wd", "word"] }, { name: "\u77E5\u4E4E", key: "zhihu", preload: false, disabled: false, url: "https://www.zhihu.com/search?type=content&q=%s", matchSite: /^https?:\/\/www\.zhihu\.com\/search\?/i, embeddable: false, weight: 8, url_scheme: "zhihu://search?q=%s", lightness: 0.5, color: "#0084FF", icon: '' }, { name: "bilibili", key: "bilibili", preload: false, disabled: false, url: "https://search.bilibili.com/all?keyword=%s", matchSite: /^https?:\/\/search\.bilibili\.com\/all/i, q: "keyword", embeddable: true, weight: 7, url_scheme: "bilibili://search?keyword=%s", lightness: 0.6431372549019607, color: "#DF698C", icon: '' }, { name: "DDG", key: "duckduckgo", url: "https://duckduckgo.com/?q=%s&kaj=m&k1=-1&kn=1&kp=-2", matchSite: /^https?:\/\/duckduckgo\.com\/*/i, preload: false, embeddable: true, weight: 6, disabled: false, lightness: 0.6039215686274509, color: "#E37151", icon: '' }, { name: "Reddit", key: "reddit", disabled: false, url: "https://www.google.com/search?q=%s+site%3Areddit.com", matchSite: (url2, query) => { var _a2, _b2, _c; return url2.includes("google.com") && ((_c = (_b2 = decodeURIComponent((_a2 = query.get("q")) != null ? _a2 : "")) == null ? void 0 : _b2.includes) == null ? void 0 : _c.call(_b2, "site:reddit.com")); }, q: (url2, query) => { var _a2, _b2, _c; return (_c = (_b2 = decodeURIComponent((_a2 = query.get("q")) != null ? _a2 : "")).replace) == null ? void 0 : _c.call(_b2, "site:reddit.com", ""); }, preload: false, embeddable: true, weight: 6, url_scheme: "", lightness: 0.5372549019607843, color: "#eb5527", icon: '' }, { name: "YouTube", key: "youtube", preload: false, disabled: false, url: "https://www.youtube.com/results?search_query=%s", matchSite: /^https?:\/\/www\.youtube\.com\/results/i, q: "search_query", embeddable: true, weight: 6, url_scheme: "youtube://YouTube.com/results?search_query=%s", lightness: 0.5254901960784314, color: "#ea3322", icon: '' }, { name: "Github", key: "github", preload: false, disabled: false, url: "https://github.com/search?q=%s", matchSite: /^https?:\/\/github\.com\/search/i, embeddable: true, weight: 5, lightness: 0.09215686274509804, color: "#181717", icon: '' }, { name: "Twitter", key: "twitter", preload: false, disabled: false, url: "https://twitter.com/search?q=%s", matchSite: /^https?:\/\/twitter\.com\/search/i, embeddable: true, weight: 2, lightness: 0.5254901960784314, color: "#1da1f2", icon: 'Twitter' }, { name: "Wolfram", key: "wolfram", preload: false, disabled: false, url: "https://www.wolframalpha.com/input?i=%s", matchSite: /^https?:\/\/www\.wolframalpha\.com\/input/i, embeddable: true, weight: 4, lightness: 0.5254901960784314, color: "#e87242", icon: '', q: "i" }, { name: "\u4ECA\u65E5\u5934\u6761", key: "toutiao", preload: false, disabled: true, url: "https://so.toutiao.com/search?keyword=%s", q: "keyword", embeddable: true, weight: 4, lightness: 0.5764705882352941, color: "#dd5049", icon: '' }, { name: "\u5FAE\u535A", key: "weibo", preload: false, disabled: false, url: "https://s.weibo.com/weibo?q=%s", matchSite: /^https?:\/\/(s|m)\.weibo\.c(om|n)\/(weibo|search)/i, q: (url2, query) => { if (url2.match(/^https?:\/\/s\.weibo\.com\/weibo/i)) { return query.get("q"); } return new URLSearchParams( decodeURIComponent(query.get("containerid")) ).get("q"); }, embeddable: true, weight: 3.5, url_scheme: "sinaweibo://searchall?q=%s", lightness: 0.5156862745098039, color: "#d33436", icon: '' }, { name: "Quora", key: "quora", url: "https://www.google.com/search?q=%s+site%3Aquora.com", matchSite: (url2, query) => { var _a2, _b2, _c; return url2.includes("google.com") && ((_c = (_b2 = decodeURIComponent((_a2 = query.get("q")) != null ? _a2 : "")) == null ? void 0 : _b2.includes) == null ? void 0 : _c.call(_b2, "site:quora.com")); }, q: (url2, query) => { var _a2, _b2, _c; return (_c = (_b2 = decodeURIComponent((_a2 = query.get("q")) != null ? _a2 : "")).replace) == null ? void 0 : _c.call(_b2, "site:quora.com", ""); }, url_scheme: "", preload: false, embeddable: true, weight: 3, disabled: false, lightness: 0.42549019607843136, color: "#aa382f", icon: '' }, { name: "Bing \u8BCD\u5178", key: "bingdict", url: "https://cn.bing.com/dict/search?q=%s", matchSite: "https://cn.bing.com/dict/search", embeddable: false, preload: false, weight: 3, disabled: false, url_scheme: "", lightness: 0.6, color: "#09ABA0", icon: ' ' }, { name: "\u6709\u9053", key: "youdao", preload: false, disabled: false, url: "https://dict.youdao.com/result?word=%s&lang=en", matchSite: /^https?:\/\/dict\.youdao\.com\/(m\/)?result/i, q: "word", embeddable: true, weight: 3, lightness: 0.484313725490196, color: "#E31436", icon: 'Created by potrace 1.16, written by Peter Selinger 2001-2019' }, { name: "Amazon", key: "amazon", preload: false, disabled: false, url: "https://www.amazon.com/s?k=%s", matchSite: "amazon.com/s", q: "k", embeddable: true, weight: 2, lightness: 0.5, color: "#FF9900", icon: '' }, { name: "eBay", key: "ebay", url: "https://www.ebay.com/sch/i.html?_nkw=%s", matchSite: "ebay.com/sch", q: "_nkw", preload: false, embeddable: true, weight: 2, disabled: false, lightness: 0.4862745098039215, color: "#4164ea", icon: '' }, { name: "\u4EAC\u4E1C", key: "jing-dong", preload: false, disabled: false, url: "https://sou.m.jd.com/bases/m/searchKeyword.htm?keyword=%s", matchSite: "sou.m.jd.com/bases/m/searchKeyword.htm", q: "keyword", embeddable: true, weight: 1, url_scheme: 'openapp.jdmobile://virtual?params={"des":"productList","keyWord":"%s","from":"search","category":"jump"}', lightness: 0.4941176470588235, color: "#E1251B", icon: '' }, { name: "\u6DD8\u5B9D", key: "taobao", preload: false, disabled: false, url: "https://s.taobao.com/search?q=%s", matchSite: "s.taobao.com/search", embeddable: true, weight: 1, url_scheme: "taobao://s.taobao.com?q=%s", lightness: 0.5196078431372548, color: "#E94F20", icon: '' }, { name: "MDN", key: "mdnwebdocs", preload: false, disabled: false, url: "https://developer.mozilla.org/en-US/search?q=%s", matchSite: "developer.mozilla.org/en-US/search", embeddable: true, weight: -1, lightness: 0, color: "#000000", icon: '' }, { name: "\u5FAE\u4FE1", key: "wechat", preload: false, disabled: true, url: "https://weixin.sogou.com/weixin?p=01030402&query=%s&type=2&ie=utf8", q: "query", embeddable: true, weight: -2, lightness: 0.39215686274509803, color: "#07C160", icon: '' } ]; const styles = ""; const engines = allEngines.filter((e) => !e.disabled).sort((a, b) => b.weight - a.weight); const hotkeys = engines.reduce((acc, engine, index) => { const key = engine.key[0].toLowerCase(); acc[key] = acc[key] ? [...acc[key], index] : [index]; return acc; }, {}); function Button({ icon, color, name, display, lightness, href, index }) { const a = document.createElement("a"); if (color) a.style.setProperty("--color", color); a.href = href; if (!display) { a.style.display = "none"; } a.setAttribute("target", "_blank"); a.setAttribute("rel", "noopener noreferrer"); a.setAttribute("title", name); a.setAttribute("aria-label", name); a.setAttribute("data-index", index + ""); a.title = name; a.classList.add("icon-button"); a.innerHTML = icon; const text = document.createElement("span"); text.innerText = name; if (lightness < 0.5) { a.classList.add("dark-invert"); } a.append(text); return a; } const getCurrentEngineIndex = (url2, searchParams) => { for (let i = engines.length - 1; i >= 0; i--) { const e = engines[i]; if (e.matchSite instanceof RegExp) { if (e.matchSite.test(url2)) { return i; } } else if (typeof e.matchSite === "function") { try { if (e.matchSite(url2, searchParams)) { return i; } } catch (e2) { console.error(e2); } } else if (typeof e.matchSite === "string") { if (url2.includes(e.matchSite)) { return i; } } } return -1; }; const getQuery = (engine, url2, searchParams) => { if (typeof engine.q === "string") { return searchParams.get(engine.q); } if (engine.q instanceof RegExp) { const match = engine.q.exec(window.location.href); if (match) return match[1]; } if (typeof engine.q === "function") { try { return engine.q(url2, searchParams); } catch (e) { console.error(e); } } if (Array.isArray(engine.q)) { for (let i = 0; i < engine.q.length; i++) { const q = searchParams.get(engine.q[i]); if (q) return q; } } return searchParams.get("q") || searchParams.get("query") || null; }; const url = window.location.href; const params = new URLSearchParams(window.location.search); const currEngineIndex = getCurrentEngineIndex(url, params); if (currEngineIndex !== -1) { const filtered = engines.filter((_, i) => i !== currEngineIndex); const matchedEngine = engines[currEngineIndex]; const q = encodeURIComponent((_b = (_a = getQuery(matchedEngine, url, params)) == null ? void 0 : _a.trim) == null ? void 0 : _b.call(_a)); const body = document.querySelector("body"); const root = document.createElement("div"); const linkContainer = document.createElement("div"); linkContainer.id = "metasearch-link-container"; root.id = "metasearch-root"; let prevScrollPosition = window.pageYOffset; window.addEventListener( "scroll", () => { const currentScrollPos = window.pageYOffset; if (prevScrollPosition > currentScrollPos) { root.style.bottom = "0"; } else { root.style.bottom = "-48px"; } prevScrollPosition = currentScrollPos; }, true ); const linkList = []; for (let i = 0; i < filtered.length; i++) { const engine = filtered[i]; const button = Button({ icon: engine.icon, color: engine.color, name: engine.name, display: true, lightness: engine.lightness, href: engine.url.replaceAll("%s", q), index: i }); linkList.push(button); linkContainer.appendChild(button); } root.appendChild(linkContainer); const close = document.createElement("button"); close.innerHTML = ``; close.classList.add("icon-button"); close.id = "metasearch-close"; close.addEventListener("click", () => { root.style.bottom = "-40px"; }); function styleInject(css,ref){if(ref===void 0){ref={}}var insertAt=ref.insertAt;if(!css||typeof document==="undefined"){return}var head=document.head||document.getElementsByTagName("head")[0];var style=document.createElement("style");style.type="text/css";if(insertAt==="top"){if(head.firstChild){head.insertBefore(style,head.firstChild)}else{head.appendChild(style)}}else{head.appendChild(style)}if(style.styleSheet){style.styleSheet.cssText=css}else{style.appendChild(document.createTextNode(css))}};styleInject(`#metasearch-root { box-sizing: border-box; width: 100vw; display: flex; position: fixed; bottom: 0; left: 0; transition: all 0.1s ease-in-out; height: 32px; background-color: rgba(255, 255, 255, 0.8); -webkit-backdrop-filter: blur(8px); backdrop-filter: blur(8px); z-index: 999999999; box-shadow: 0px 0px 9px rgba(0, 0, 0, 0.07); overflow-y: hidden; } #metasearch-root .icon-button { all: unset; box-sizing: border-box; text-decoration: none; color: var(--color); display: flex; align-items: center; justify-content: center; gap: 4px; background-color: transparent; border: 0; outline: transparent; cursor: pointer; transition: all 0.15s ease-in-out; white-space: nowrap; -webkit-tap-highlight-color: transparent; flex: 1 0 auto; padding: 2px 5px; min-width: 32px; height: 100%; } #metasearch-root .icon-button > svg { width: 20px; height: 20px; color: currentColor; fill: currentColor; stroke: currentColor; } @media screen and (max-width: 768px) { #metasearch-root .icon-button > svg { height: 24px; width: 24px; } } #metasearch-root .icon-button:hover { filter: brightness(0.85); background-color: rgba(0, 0, 0, 0.08); } @media screen and (prefers-color-scheme: dark) { #metasearch-root .icon-button:hover.dark-invert { filter: invert(1) hue-rotate(180deg) brightness(0.85); } } #metasearch-root .icon-button:active { -webkit-tap-highlight-color: transparent; filter: brightness(0.7); background-color: rgba(0, 0, 0, 0.12); } @media screen and (prefers-color-scheme: dark) { #metasearch-root .icon-button:active.dark-invert { filter: invert(1) hue-rotate(180deg) brightness(0.7); } } #metasearch-root .icon-button:focus { -webkit-tap-highlight-color: transparent; color: white; background-color: var(--color); } @media screen and (prefers-color-scheme: dark) { #metasearch-root .icon-button:focus.dark-invert { filter: invert(1) hue-rotate(180deg) brightness(0.7); } } @media screen and (max-width: 768px) { #metasearch-root .icon-button { padding: 0; min-width: 40px; } #metasearch-root .icon-button > span { display: none; } } @media screen and (max-width: 768px) { #metasearch-root { height: 40px; } } @media screen and (prefers-color-scheme: dark) { #metasearch-root { background-color: rgba(25, 25, 25, 0.7); color: rgba(255, 255, 255, 0.8); } #metasearch-root .dark-invert { filter: invert(1) hue-rotate(180deg); } } #metasearch-root #metasearch-close { box-shadow: -1px 2px 9px rgba(0, 0, 0, 0.1); } #metasearch-root #metasearch-link-container { scrollbar-width: none; overflow-x: auto; overflow-y: hidden; width: 100%; display: flex; box-sizing: border-box; } #metasearch-root #metasearch-link-container::-webkit-scrollbar { display: none; } body { position: relative !important; }`); root.appendChild(close); body.appendChild(root); const getNextTabIndex = (currIndex = -1, key) => { for (let i = currIndex + 1; i < filtered.length + currIndex; i++) { const index = i % filtered.length; if (filtered[index].key[0] === key.toLowerCase()) return index; } return currIndex; }; const keydownListener = (e) => { if (e.key === "Alt") { root.style.bottom = "0"; } const active = document.activeElement; if (e.key === "Escape" || e.key === "Esc") { if (root.contains(active)) { e.preventDefault(); active.blur(); return; } } const key = e.key.toLowerCase(); const focusIndex = linkContainer.contains(active) ? parseInt(active.getAttribute("data-index") || "-1", 10) : -1; if (e.altKey && hotkeys[key] !== void 0) { e.preventDefault(); const next = getNextTabIndex(focusIndex, key); linkList[next].focus(); return; } const num = parseInt(e.key, 10); if (e.altKey && !isNaN(num) && num < filtered.length) { e.preventDefault(); const index = num - 1; linkList[index].focus(); return; } if (e.altKey && e.key === "[") { const prevIndex = focusIndex - 1 < 0 ? filtered.length - 1 : focusIndex - 1; linkList[prevIndex].focus(); return; } if (e.altKey && e.key === "]") { const nextIndex = (focusIndex + 1) % filtered.length; linkList[nextIndex].focus(); return; } }; const keyUpListener = (e) => { const active = document.activeElement; if (e.key === "Alt" && linkContainer.contains(active)) { active.click(); active.blur(); } }; document.addEventListener("keydown", keydownListener); document.addEventListener("keyup", keyUpListener); } })();