// ==UserScript==
// @name 聚合搜索
// @namespace http://tampermonkey.net/
// @version 10.0.28
// @description 在页面底部显示一个聚合搜索引擎切换导航
// @author 晚风知我意
// @match *://*/*keyword=*
// @match *://*/*query=*
// @match *://*/*word=*
// @match *://*/*text=*
// @match *://*/*key=*
// @match *://*/*web=*
// @match *://*/*wd=*
// @match *://*/*kw=*
// @match *://*/*q=*
// @match *://*/*p=*
// @grant unsafeWindow
// @run-at document-body
// @license MIT
// ==/UserScript==
const punkDeafultMark = "Google-Bing-Baidu-MetaSo-搜图-Bilibili-ApkPure-YandexSearch-Zhihu-Weibo-Toutiao-CSDN-YouCare-Efind-Cynay-Swisscows-夸克-360-DuckDuckGo-GitHub-Greasy Fork镜像";
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://www.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: "Bilibili",searchUrl: "https://m.bilibili.com/search?keyword=",searchkeyName: ["keyword"],matchUrl: /bilibili\.com.*?search\?keyword=/g,mark: "Bilibili" },
{name: "Swisscows", searchUrl: "https://swisscows.com/en/web?query=", searchkeyName: ["query"], matchUrl:/swisscows\.com.*?query=/g, mark:"Swisscows"},
{name: "CSDN", searchUrl: "https://so.csdn.net/wap?q=", searchkeyName: ["q"], matchUrl:/csdn\.net.*?q=?/g, mark:"CSDN"},
{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: "微博", searchUrl: "https://s.weibo.com/weibo?q=", searchkeyName: ["q"], matchUrl:/weibo\.com.*?q=?/g, mark:"Weibo"},
{ name: "ApkPure", searchUrl: "https://apkpure.com/search?q=",searchkeyName: ["q"],matchUrl: /apkpure\.com.*?q=?/g,mark: "ApkPure"},
{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=", 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: "Greasy Fork镜像", searchUrl: "https://gf.qytechs.cn/zh-CN/scripts?q=", searchkeyName: ["q"], matchUrl:/greasyfork\.org.*?q=?/g, mark:"Greasy Fork镜像"},
{name: "搜图",searchUrl: "https://cn.bing.com/images/search?q=",searchkeyName: ["q"],matchUrl: /bing\.com\/images\/search\?q=.*?/g,mark: "搜图"}
];
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) {
localStorage.setItem("last_successful_keywords", keywords);
sessionStorage.setItem("last_successful_keywords", keywords);
}
return keywords;
}
}
}
}
return sessionStorage.getItem("last_successful_keywords") || localStorage.getItem("last_successful_keywords") || "";
} catch (error) {
console.error("获取关键词时出错:", error.message, "当前URL:", window.location.href);
return "";
}
}
function monitorInputFields() {
const inputFields = document.querySelectorAll('input[type="text"], textarea');
if (inputFields.length > 0) {
inputFields.forEach(input => {
input.addEventListener('input', (event) => {
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) => {
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) => {
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.height = '32px';
punkJetBox.style.zIndex = '9999';
punkJetBox.style.display = 'flex';
punkJetBox.style.overflowX = 'auto';
punkJetBox.style.whiteSpace = 'nowrap';
punkJetBox.style.backgroundColor = '#ffffff';
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 = localStorage.getItem("punk_setup_search") || punkDeafultMark;
showList = showList.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.style.height = '32px';
liItem.innerHTML = `<button style="padding: 8px; margin: 0; height: 28px; border: none; border-radius: 7px; background-color: rgba(255, 255, 255, 0.8); color: #42A5F5; font-size: 14px; cursor: pointer; box-shadow: 1px 1px 1px rgba(0, 0, 0, 0.1), 0px 0px 0px rgba(255, 255, 255, 0.5), 6px 6px 10px rgba(0, 0, 0, 0.1) inset, -6px -6px 10px rgba(255, 255, 255, 0) inset; backdrop-filter: blur(5px); transition: background-color 0.3s, transform 0.2s; outline: none; display: flex; align-items: center; justify-content: center;" 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.addEventListener('mouseover', () => {
button.style.backgroundColor = 'rgba(241, 241, 241, 1)';
});
button.addEventListener('mouseout', () => {
button.style.backgroundColor = 'rgba(255, 255, 255, 0.8)';
});
button.addEventListener('click', (event) => {
event.preventDefault();
const url = button.getAttribute("url");
let keywords = currentInput.length > 0 ? currentInput : getKeywords();
if (url && keywords) {
window.open(url + encodeURIComponent(keywords), '_blank');
} else {
alert('未找到搜索关键词。');
}
});
});
} catch (error) {
console.error("添加搜索框时出错:", error.message);
}
}
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;
background-color: #ffffff;
border: none;
}
#punkjet-search-box ul {
margin: 0;
padding: 0;
list-style: none;
overflow-x: auto;
white-space: nowrap;
height: auto;
}
#punk-url-a {
padding: 8px;
border: none;
border-radius: 9px;
background-color: rgba(255, 255, 255, 0.8);
color: #42A5F5;
font-size: 14px;
cursor: pointer;
box-shadow: none;
backdrop-filter: blur(5px);
transition: background-color 0.3s, transform 0.2s;
outline: none;
display: inline-block;
}
#punk-url-a:hover {
background-color: rgba(241, 241, 241, 1);
}
`;
document.head.appendChild(cssNode);
} catch (error) {
console.error("注入样式时出错:", error.message);
}
}
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 {
const punkJetBox = document.getElementById("punkjet-search-box");
if (punkJetBox) {
punkJetBox.remove();
}
sessionStorage.clear();
localStorage.removeItem("last_successful_keywords");
localStorage.removeItem("punk_setup_search");
if (getKeywords() != null) {
if (!scriptLoaded) {
if (!localStorage.getItem("punk_setup_search")) {
localStorage.setItem("punk_setup_search", punkDeafultMark);
}
currentInput = sessionStorage.getItem("currentInput") || "";
monitorInputFields();
addSearchBox();
injectStyle();
scriptLoaded = true;
}
}
} catch (error) {
console.error("初始化时出错:", error.message);
}
}
document.addEventListener("visibilitychange", () => {
if (document.visibilityState === 'visible') {
reloadScript();
}
});
document.addEventListener("pageshow", (event) => {
if (event.persisted) {
reloadScript();
}
});
document.addEventListener("DOMContentLoaded", () => {
if (isValidScope()) {
reloadScript();
}
});
window.addEventListener('scroll', handleScroll);