// ==UserScript==
// @name 聚合搜索
// @namespace http://tampermonkey.net/
// @version 10.0.0
// @description 在页面底部显示一个聚合搜索引擎切换导航
// @author 晚风知我意
// @include *keyword=*
// @include *query=*
// @include *word=*
// @include *text=*
// @include *key=*
// @include *web=*
// @include *wd=*
// @include *kw=*
// @include *q=*
// @include *p=*
// @grant unsafeWindow
// @grant GM_getValue
// @grant GM_setValue
// @run-at document-body
// @license MIT
// ==/UserScript==
const punkDeafultMark = "Google-Bing-Baidu-YandexSearch-MetaSo-Swisscows-Zhihu-360-Quark-Sougou-Toutiao-DuckDuckGo-GitHub-Pinterest";
const searchUrlMap = [
{name: "谷歌", searchUrl: "https://www.google.com/search?q=", searchkeyName: ["q"], matchUrl:/google\.com.*?search.*?q=/g, mark:"Google"},
{name: "必应", searchUrl: "https://www.bing.com/search?q=", searchkeyName: ["q"], matchUrl:/bing\.com.*?search\?q=?/g, mark:"Bing"},
{name: "百度", searchUrl: "https://baidu.com/s?wd=", searchkeyName: ["wd", "word"], matchUrl:/baidu\.com.*?w(or)?d=?/g, mark:"Baidu"},
{name: "Yandex", searchUrl: "https://yandex.com/search/?text=", searchkeyName: ["text"], matchUrl:/yandex\.com.*?text=/g, mark:"YandexSearch"},
{name: "Swisscows", searchUrl: "https://swisscows.com/en/web?query=", searchkeyName: ["query"], matchUrl:/swisscows\.com.*?query=/g, mark:"Swisscows"},
{name: "秘塔", searchUrl: "https://metaso.cn/?s=itab1&q=", searchkeyName: ["q"], matchUrl:/metaso\.cn.*?q=/g, mark:"MetaSo"},
{name: "知乎", searchUrl: "https://www.zhihu.com/search?q=", searchkeyName: ["q"], matchUrl:/zhihu\.com\/search.*?q=/g, mark:"Zhihu"},
{name: "360", searchUrl: "https://www.so.com/s?q=", searchkeyName: ["q"], matchUrl:/\.so\.com.*?q=/g, mark:"360"},
{name: "夸克", searchUrl: "https://quark.sm.cn/s?q=", searchkeyName: ["q"], matchUrl:/sm\.cn.*?q=/g, mark:"Quark"},
{name: "搜狗", searchUrl: "https://m.sogou.com/web/searchList.jsp?keyword=", searchkeyName: ["keyword"], matchUrl:/sogou\.com.*?keyword=/g, mark:"Sougou"},
{name: "头条", searchUrl: "https://so.toutiao.com/search/?keyword=", searchkeyName: ["keyword"], matchUrl:/toutiao\.com.*?keyword=/g, mark:"Toutiao"},
{name: "DuckDuckGo", searchUrl: "https://duckduckgo.com/?q=", searchkeyName: ["q"], matchUrl:/duckduckgo\.com.*?q=/g, mark:"DuckDuckGo"},
{name: "GitHub", searchUrl: "https://github.com/search?q=", searchkeyName: ["q"], matchUrl:/github\.com\/search.*?q=/g, mark:"GitHub"},
{name: "图片搜", searchUrl: "https://www.pinterest.jp/search/pins/?q=", searchkeyName: ["q"], matchUrl:/pinterest\.jp.*?q=/g, mark:"Pinterest"}
];
let lastScrollTop = 0;
let punkJetBoxVisible = true;
let currentInput = "";
function getKeywords() {
try {
let keywords = "";
for (let urlItem of searchUrlMap) {
if (window.location.href.match(urlItem.matchUrl) != null) {
for (let keyItem of urlItem.searchkeyName) {
if (window.location.href.indexOf(keyItem) >= 0) {
let url = new URL(window.location.href);
keywords = url.searchParams.get(keyItem);
if (keywords) {
GM_setValue("last_successful_keywords", keywords);
}
return keywords;
}
}
}
}
return GM_getValue("last_successful_keywords", "");
} catch (error) {
console.error("获取关键词时出错:", error);
return "";
}
}
function monitorInputFields() {
const inputFields = document.querySelectorAll('input[type="text"], textarea');
inputFields.forEach(input => {
input.addEventListener('input', (event) => {
currentInput = event.target.value;
});
});
const observer = new MutationObserver(() => {
const newInputFields = document.querySelectorAll('input[type="text"], textarea');
newInputFields.forEach(input => {
if (!input.dataset.monitored) {
input.dataset.monitored = true;
input.addEventListener('input', (event) => {
currentInput = event.target.value;
});
}
});
});
observer.observe(document.body, {
childList: true,
subtree: true
});
const baiduSearchInput = document.querySelector('#kw');
if (baiduSearchInput) {
baiduSearchInput.addEventListener('input', (event) => {
currentInput = event.target.value;
});
}
}
function addSearchBox() {
try {
const punkJetBox = document.createElement("div");
punkJetBox.id = "punkjet-search-box";
punkJetBox.style.position = 'fixed';
punkJetBox.style.bottom = '0';
punkJetBox.style.left = '0';
punkJetBox.style.right = '0';
punkJetBox.style.padding = '5px 0';
punkJetBox.style.zIndex = '9999';
punkJetBox.style.display = 'flex';
punkJetBox.style.overflowX = 'auto';
punkJetBox.style.whiteSpace = 'nowrap';
punkJetBox.style.backgroundColor = 'rgba(255, 255, 255, 0)';
punkJetBox.style.border = '1px solid transparent';
const ulList = document.createElement('ul');
ulList.style.margin = '0';
ulList.style.padding = '0';
ulList.style.listStyle = 'none';
ulList.style.overflowX = 'auto';
ulList.style.whiteSpace = 'nowrap';
ulList.style.height = 'auto';
let fragment = document.createDocumentFragment();
let showList = GM_getValue("punk_setup_search", punkDeafultMark).split('-');
for (let showListIndex = 0; showListIndex < showList.length; showListIndex++) {
for (let index = 0; index < searchUrlMap.length; index++) {
let item = searchUrlMap[index];
if (item.mark == showList[showListIndex]) {
let liItem = document.createElement('li');
liItem.style.display = 'inline-block';
liItem.style.marginLeft = '2px';
liItem.innerHTML = `<button style="padding: 9px 15px; border: none; border-radius: 8px; background-color: rgba(255, 255, 255, 0.8); color: #42A5F5; font-size: 14px; cursor: pointer; box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.2); backdrop-filter: blur(5px); transition: background-color 0.3s, transform 0.2s; outline: none;" id="punk-url-a" url='${item.searchUrl}'>${item.name}</button>`;
fragment.appendChild(liItem);
break;
}
}
}
ulList.appendChild(fragment);
punkJetBox.appendChild(ulList);
document.body.appendChild(punkJetBox);
const buttons = document.querySelectorAll("#punk-url-a");
buttons.forEach(button => {
button.onmouseover = () => button.style.backgroundColor = 'rgba(241, 241, 241, 0.8)';
button.onmouseout = () => button.style.backgroundColor = 'rgba(255, 255, 255, 0.8)';
button.onclick = (event) => {
event.preventDefault();
let keywords = currentInput.length > 0 ? currentInput : getKeywords();
if (keywords) {
window.open(button.getAttribute("url") + encodeURIComponent(keywords), '_blank');
} else {
alert('未找到搜索关键词。');
}
};
});
window.addEventListener('scroll', () => {
const scrollTop = window.scrollY || document.documentElement.scrollTop;
if (scrollTop < lastScrollTop) {
punkJetBox.style.display = 'flex';
punkJetBoxVisible = true;
} else if (scrollTop > lastScrollTop) {
punkJetBox.style.display = 'none';
punkJetBoxVisible = false;
}
lastScrollTop = scrollTop <= 0 ? 0 : scrollTop;
});
} catch (error) {
console.error("添加搜索框时出错:", error);
}
}
function injectStyle() {
try {
const css = `
#punkjet-search-box {
display: flex;
flex-direction: column;
}
#punk-search-navi-box {
display: flex;
width: 100%;
height: auto;
}
#punk-search-app-box {
flex: 1;
width: 0;
}
`;
const cssNode = document.createElement("style");
cssNode.setAttribute("type", "text/css");
cssNode.appendChild(document.createTextNode(css));
document.head.appendChild(cssNode);
} catch (error) {
console.error("注入样式时出错:", error);
}
}
function init() {
try {
if (getKeywords() != null) {
if (!GM_getValue("punk_setup_search")) {
GM_setValue("punk_setup_search", punkDeafultMark);
}
monitorInputFields();
addSearchBox();
injectStyle();
} else {
setTimeout(init, 1000);
}
} catch (error) {
console.error("初始化时出错:", error);
}
}
document.addEventListener("DOMContentLoaded", init);