// ==UserScript==
// @name 百度/谷歌/ddg搜索跳转ChatGPT
// @namespace https://www.tampermonkey.net/
// @version 1.9.1
// @description 在 Google、百度、DuckDuckGo 搜索页面添加按钮,一键跳转到 ChatGPT 并自动使用联网搜索
// @author schweigen
// @match https://www.google.com/search*
// @match https://google.com/search*
// @match https://www.baidu.com/*
// @match https://duckduckgo.com/*
// @match https://chatgpt.com/*
// @icon https://www.google.com/s2/favicons?sz=64&domain=google.com
// @grant none
// @license MIT
// @noframes
// ==/UserScript==
/**
* 用户设置 - 可以修改以下变量来自定义脚本行为
*/
const USER_SETTINGS = {
// 备注:部分账号暂时无法使用 o4-mini-high 模型
// 是否启用临时聊天模式
ENABLE_TEMPORARY_CHAT: false,
// 默认使用的模型(作为备用)
DEFAULT_MODEL: "o4-mini-high",
// 搜索页面展示的模型按钮
MODEL_BUTTONS: [
{ label: 'o4mh', model: 'o4-mini-high', color: '#d97706', hoverColor: '#b45309' },
{ label: 'o3', model: 'o3', color: '#2563eb', hoverColor: '#1d4ed8' },
{ label: '5T', model: 'gpt-5-thinking', color: '#059669', hoverColor: '#047857' }
],
// 按钮的垂直位置(距离顶部的像素值)
BUTTON_TOP_POSITION: 80,
// 按钮距离右侧的像素值(Google、DuckDuckGo 使用)
BUTTON_RIGHT_POSITION: 20,
// 百度页面按钮距离左侧的像素值
BUTTON_LEFT_POSITION: 20,
// 要添加到搜索前的前缀文字
SEARCH_PREFIX: "websearch: ",
// 等待发送按钮出现的最长时间(毫秒)
SEND_BUTTON_WAIT_TIMEOUT: 5000
};
(function() {
'use strict';
const hostname = window.location.hostname;
const isGooglePage = hostname.includes('google');
const isBaiduPage = hostname.includes('baidu.com');
const isDuckDuckGoPage = hostname.includes('duckduckgo.com');
const isChatGPTPage = hostname.includes('chatgpt.com');
if (isGooglePage || isBaiduPage || isDuckDuckGoPage) {
if (!document.getElementById('gpt-buttons-style')) {
const style = document.createElement('style');
style.id = 'gpt-buttons-style';
style.textContent = `
.gpt-buttons-container {
position: fixed;
top: ${USER_SETTINGS.BUTTON_TOP_POSITION}px;
display: flex;
flex-direction: column;
gap: 8px;
z-index: 1000;
}
.gpt-buttons-container.gpt-buttons-right {
right: ${USER_SETTINGS.BUTTON_RIGHT_POSITION}px;
}
.gpt-buttons-container.gpt-buttons-left {
left: ${USER_SETTINGS.BUTTON_LEFT_POSITION}px;
}
.gpt-button {
background-color: var(--bg-color, #10a37f);
color: white;
border: none;
border-radius: 4px;
padding: 8px 12px;
margin: 0;
font-size: 14px;
cursor: pointer;
display: flex;
align-items: center;
transition: background-color 0.3s;
}
.gpt-button:hover {
background-color: var(--hover-color, #0d8c6d);
}
.gpt-icon {
margin-right: 6px;
width: 16px;
height: 16px;
}
`;
document.head.appendChild(style);
}
const SEARCH_PARAM_MAP = {
google: 'q',
baidu: 'wd',
duckduckgo: 'q'
};
function getSearchInput() {
if (isGooglePage) {
return document.querySelector('input[name="q"]');
}
if (isBaiduPage) {
return document.querySelector('input[name="wd"], input#kw');
}
if (isDuckDuckGoPage) {
return document.querySelector('input[name="q"], input#searchbox_input, input#search_form_input, input#search_form_input_homepage');
}
return null;
}
function getSearchParamKey() {
if (isBaiduPage) {
return SEARCH_PARAM_MAP.baidu;
}
if (isDuckDuckGoPage) {
return SEARCH_PARAM_MAP.duckduckgo;
}
return SEARCH_PARAM_MAP.google;
}
function createGptButton(buttonLabel, targetModel, colors) {
const button = document.createElement('button');
button.className = 'gpt-button';
if (colors) {
const { color, hoverColor } = colors;
if (color) {
button.style.setProperty('--bg-color', color);
}
if (hoverColor) {
button.style.setProperty('--hover-color', hoverColor);
}
}
const iconSvg = `<svg class="gpt-icon" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path fill="white" d="M22.2819 9.8211a5.9847 5.9847 0 0 0-.5157-4.9108 6.0462 6.0462 0 0 0-6.5098-2.9A6.0651 6.0651 0 0 0 4.9807 4.1818a5.9847 5.9847 0 0 0-3.9977 2.9 6.0462 6.0462 0 0 0 .7427 7.0966 5.98 5.98 0 0 0 .511 4.9107 6.051 6.051 0 0 0 6.5146 2.9001A5.9847 5.9847 0 0 0 13.2599 24a6.0557 6.0557 0 0 0 5.7718-4.2058 5.9894 5.9894 0 0 0 3.9977-2.9001 6.0557 6.0557 0 0 0-.7475-7.0729zm-9.022 12.6081a4.4755 4.4755 0 0 1-2.8764-1.0408l.1419-.0804 4.7783-2.7582a.7948.7948 0 0 0 .3927-.6813v-6.7369l2.02 1.1686a.071.071 0 0 1 .038.052v5.5826a4.504 4.504 0 0 1-4.4945 4.4944zm-9.6607-4.1254a4.4708 4.4708 0 0 1-.5346-3.0137l.142.0852 4.783 2.7582a.7712.7712 0 0 0 .7806 0l5.8428-3.3685v2.3324a.0804.0804 0 0 1-.0332.0615L9.74 19.9502a4.4992 4.4992 0 0 1-6.1408-1.6464zM2.3408 7.8956a4.485 4.485 0 0 1 2.3655-1.9728V11.6a.7664.7664 0 0 0 .3879.6765l5.8144 3.3543-2.0201 1.1685a.0757.0757 0 0 1-.071 0l-4.8303-2.7865A4.504 4.504 0 0 1 2.3408 7.872zm16.5963 3.8558L13.1038 8.364 15.1192 7.2a.0757.0757 0 0 1 .071 0l4.8303 2.7913a4.4944 4.4944 0 0 1-.6765 8.1042v-5.6772a.79.79 0 0 0-.407-.667zm2.0107-3.0231l-.142-.0852-4.7735-2.7818a.7759.7759 0 0 0-.7854 0L9.409 9.2297V6.8974a.0662.0662 0 0 1 .0284-.0615l4.8303-2.7866a4.4992 4.4992 0 0 1 6.6802 4.66zM8.3065 12.863l-2.02-1.1638a.0804.0804 0 0 1-.038-.0567V6.0742a4.4992 4.4992 0 0 1 7.3757-3.4537l-.142.0805L8.704 5.459a.7948.7948 0 0 0-.3927.6813zm1.0976-2.3654l2.602-1.4998 2.6069 1.4998v2.9994l-2.5974 1.5093-2.6067-1.4997z"></path></svg>`;
button.innerHTML = iconSvg + buttonLabel;
button.title = `使用 ${targetModel} 模型在 ChatGPT 中查询`;
button.addEventListener('click', function() {
const searchInput = getSearchInput();
let searchText = searchInput ? searchInput.value.trim() : '';
if (!searchText) {
const params = new URLSearchParams(window.location.search);
const fallbackParam = getSearchParamKey();
searchText = (params.get(fallbackParam) || '').trim();
}
if (searchText) {
redirectToChatGPT(searchText, targetModel);
}
});
return button;
}
function redirectToChatGPT(searchText, model) {
const selectedModel = model || USER_SETTINGS.DEFAULT_MODEL;
let urlParams = `model=${selectedModel}&prompt=${encodeURIComponent(USER_SETTINGS.SEARCH_PREFIX + searchText)}`;
if (USER_SETTINGS.ENABLE_TEMPORARY_CHAT) {
urlParams += '&temporary-chat=true';
}
const chatGptUrl = `https://chatgpt.com/?${urlParams}`;
window.open(chatGptUrl, '_blank');
}
function addButtonsToPage() {
if (document.querySelector('.gpt-buttons-container')) {
return;
}
const container = document.createElement('div');
container.className = 'gpt-buttons-container';
if (isBaiduPage) {
container.classList.add('gpt-buttons-left');
} else {
container.classList.add('gpt-buttons-right');
}
USER_SETTINGS.MODEL_BUTTONS.forEach(({ label, model: modelName, color, hoverColor }) => {
const button = createGptButton(label, modelName, { color, hoverColor });
container.appendChild(button);
});
document.body.appendChild(container);
}
window.addEventListener('load', function() {
addButtonsToPage();
});
function setupMutationObserver() {
const targetNode = document.body;
if (!targetNode) {
document.addEventListener('DOMContentLoaded', setupMutationObserver, { once: true });
return;
}
const observer = new MutationObserver(function() {
if (!document.querySelector('.gpt-buttons-container')) {
addButtonsToPage();
}
});
observer.observe(targetNode, { childList: true, subtree: true });
}
setupMutationObserver();
setTimeout(addButtonsToPage, 1000);
}
else if (isChatGPTPage) {
// ChatGPT页面的脚本处理
// 从URL参数中检查是否是从Google搜索跳转过来的
const urlParams = new URLSearchParams(window.location.search);
const promptParam = urlParams.get('prompt');
if (promptParam) {
// 标记是否已经点击过发送按钮
let hasClickedSendButton = false;
// 使用MutationObserver监听DOM变化,等待发送按钮出现
const observer = new MutationObserver(function(mutations) {
if (hasClickedSendButton) return; // 如果已经点击过,不再尝试
// 尝试精确匹配发送按钮
const sendButton = document.querySelector('button#composer-submit-button[data-testid="send-button"]');
if (sendButton && !sendButton.disabled) {
console.log("找到发送按钮,准备点击");
hasClickedSendButton = true; // 标记为已点击
// 创建一个鼠标点击事件
const clickEvent = new MouseEvent('click', {
bubbles: true,
cancelable: true,
view: window
});
// 分发事件到发送按钮
sendButton.dispatchEvent(clickEvent);
console.log("已点击发送按钮,停止监听");
// 停止观察
observer.disconnect();
}
});
// 开始观察文档
observer.observe(document, { childList: true, subtree: true });
// 设置超时,最多等待指定时间
setTimeout(function() {
if (!hasClickedSendButton) {
console.log("达到最大等待时间,停止监听");
observer.disconnect();
}
}, USER_SETTINGS.SEND_BUTTON_WAIT_TIMEOUT);
}
}
})();