// ==UserScript==
// @name 聚合搜索
// @namespace http://tampermonkey.net/
// @version 10.0.6
// @description 在页面底部显示一个聚合搜索引擎切换导航
// @author 晚风知我意
// @include *://*.google.com/*
// @include *://*.bing.com/*
// @include *://*.baidu.com/*
// @include *://*.yandex.com/*
// @include *://*.swisscows.com/*
// @include *://*.metaso.cn/*
// @include *://*.zhihu.com/*
// @include *://*.so.com/*
// @include *://*.sm.cn/*
// @include *://*.toutiao.com/*
// @include *://*.duckduckgo.com/*
// @include *://*.github.com/*
// @include *://*.pinterest.jp/*
// @include *://*.youcare.world/*
// @include *://*.efind.com/*
// @include *://*.cynay.com/*
// @grant unsafeWindow
// @grant GM_getValue
// @grant GM_setValue
// @run-at document-body
// @license MIT
// ==/UserScript==
const punkDeafultMark = "Google-Bing-Baidu-MetaSo-夸克-YandexSearch-YouCare-Efind-Cynay-Swisscows-Zhihu-360-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://m.baidu.com/s?from=1030335w&word=", 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:"夸克"},
{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: "YouCare", searchUrl: "https://youcare.world/all?q=&l=", searchkeyName: ["q"], matchUrl:/youcare\.world\/all/g, mark:"YouCare"},
{name: "Efind", searchUrl: "https://efind.com/search?q=", searchkeyName: ["q"], matchUrl:/efind\.com\/search/g, mark:"Efind"},
{name: "Cynay", searchUrl: "https://cynay.com/search?q=", searchkeyName: ["q"], matchUrl:/cynay\.com\/search/g, mark:"Cynay"},
{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 = "";
let scriptLoaded = false;
function isValidScope() {
return searchUrlMap.some(item => window.location.href.match(item.matchUrl) != null);
}
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);
sessionStorage.setItem("last_successful_keywords", keywords);
}
return keywords;
}
}
}
}
return sessionStorage.getItem("last_successful_keywords") || GM_getValue("last_successful_keywords", "");
} catch (error) {
console.error("获取关键词时出错:", error, "当前URL:", window.location.href);
return "";
}
}
function monitorInputFields() {
const inputFields = document.querySelectorAll('input[type="text"], textarea');
inputFields.forEach(input => {
input.addEventListener('input', (event) => {
console.log("输入框内容变化:", event.target.value);
currentInput = event.target.value;
sessionStorage.setItem("currentInput", currentInput);
});
});
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) => {
console.log("输入框内容变化:", event.target.value);
currentInput = event.target.value;
sessionStorage.setItem("currentInput", currentInput);
});
}
});
});
observer.observe(document.body, {
childList: true,
subtree: true
});
const baiduSearchInput = document.querySelector('#kw');
if (baiduSearchInput) {
baiduSearchInput.addEventListener('input', (event) => {
console.log("百度搜索框内容变化:", event.target.value);
currentInput = event.target.value;
sessionStorage.setItem("currentInput", currentInput);
});
}
}
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('-');
console.log("显示的搜索引擎:", showList);
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: 9px; 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', handleScroll);
} catch (error) {
console.error("添加搜索框时出错:", error);
}
}
function handleScroll() {
const scrollTop = window.scrollY || document.documentElement.scrollTop;
if (scrollTop < lastScrollTop) {
document.getElementById("punkjet-search-box").style.display = 'flex';
punkJetBoxVisible = true;
} else if (scrollTop > lastScrollTop) {
document.getElementById("punkjet-search-box").style.display = 'none';
punkJetBoxVisible = false;
}
lastScrollTop = scrollTop <= 0 ? 0 : scrollTop;
}
function injectStyle() {
try {
const cssNode = document.createElement("style");
cssNode.textContent = `
#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;
}
`;
document.head.appendChild(cssNode);
} catch (error) {
console.error("注入样式时出错:", error);
}
}
function reloadScript() {
const punkJetBox = document.getElementById("punkjet-search-box");
if (punkJetBox) {
punkJetBox.remove();
}
scriptLoaded = false;
init();
}
setInterval(() => {
if (isValidScope() && !scriptLoaded) {
init();
} else if (!isValidScope() && scriptLoaded) {
reloadScript();
}
}, 1000);
function init() {
try {
if (getKeywords() != null) {
if (!GM_getValue("punk_setup_search")) {
GM_setValue("punk_setup_search", punkDeafultMark);
}
currentInput = sessionStorage.getItem("currentInput") || "";
monitorInputFields();
addSearchBox();
injectStyle();
scriptLoaded = true;
} else {
const punkJetBox = document.getElementById("punkjet-search-box");
if (punkJetBox) {
punkJetBox.remove();
}
}
} catch (error) {
console.error("初始化时出错:", error);
}
}
document.addEventListener("visibilitychange", () => {
if (document.visibilityState === 'visible') {
reloadScript();
}
});
document.addEventListener("pageshow", (event) => {
if (event.persisted) {
reloadScript();
}
});
document.addEventListener("DOMContentLoaded", () => {
console.log("DOM内容加载完成,当前URL:", window.location.href);
if (isValidScope()) {
reloadScript();
}
});