您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
自动填充URL中的q参数到豆包聊天框并发送
// ==UserScript== // @name 豆包自动发送助手,添加q=?查询参数 // @namespace Violentmonkey Scripts // @match https://www.doubao.com/chat/* // @grant none // @license MIT // @version 1.10 // @author Doubao Assistant // @description 自动填充URL中的q参数到豆包聊天框并发送 // ==/UserScript== /* * 功能说明: * 1. 自动提取URL中的q参数 * 2. 智能填充到豆包聊天输入框 * 3. 模拟真实用户输入行为 * 4. 自动发送消息 */ async function addDoubaoQueryParam() { // 获取URL中的q参数 const query = new URLSearchParams(window.location.search).get('q'); if (!query) { console.log('URL中未检测到q参数,脚本终止'); return; } console.log(`检测到查询参数:${query}`); // 元素等待函数 const waitForElement = async (selectors, timeout = 10000) => { const selectorList = Array.isArray(selectors) ? selectors : [selectors]; while (timeout > 0) { for (const selector of selectorList) { const element = document.querySelector(selector); if (element) { console.log(`通过选择器 "${selector}" 定位到元素`); return element; } } await delay(300); timeout -= 300; } throw new Error(`所有选择器均未定位到元素:${selectorList.join(' / ')}`); }; // 延时函数 function delay(ms) { return new Promise(resolve => setTimeout(resolve, ms)); } // 注入式输入内容 async function injectText(element, text) { console.log(`开始注入内容,长度:${text.length} 字符`); // 分块注入 const chunks = splitTextIntoChunks(text); for (let i = 0; i < chunks.length; i++) { const chunk = chunks[i]; // 使用不同的方法注入内容 if (chunk.type === 'normal') { setNativeValue(element, chunk.content); } else if (chunk.type === 'html') { if (element.insertAdjacentHTML) { element.insertAdjacentHTML('beforeend', chunk.content); } else { setNativeValue(element, chunk.content); } } else if (chunk.type === 'paste') { simulatePaste(element, chunk.content); } // 触发必要的事件 triggerInputEvents(element); // 等待页面响应 await delay(150 + Math.random() * 100); // 检查内容是否被清空 if (element.value.length < chunk.content.length) { console.warn('警告:内容被部分清空,尝试恢复'); if (Math.random() > 0.5) { setNativeValue(element, element.value + chunk.content); } else { simulatePaste(element, chunk.content); } triggerInputEvents(element); await delay(200); } // 模拟思考时间 if (i < chunks.length - 1) { await delay(300 + Math.random() * 400); } } // 触发最终事件 element.dispatchEvent(new Event('change', { bubbles: true })); element.dispatchEvent(new Event('blur', { bubbles: true })); console.log(`内容注入完成:${text}`); } // 将文本分成不同类型的块 function splitTextIntoChunks(text) { const chunks = []; const maxChunkSize = 15 + Math.floor(Math.random() * 10); let currentType = 'normal'; let currentChunk = ''; for (let i = 0; i < text.length; i++) { currentChunk += text[i]; if (currentChunk.length >= maxChunkSize || /[,.?!;:]/.test(text[i])) { chunks.push({ content: currentChunk, type: currentType }); const types = ['normal', 'html', 'paste']; currentType = types[Math.floor(Math.random() * types.length)]; currentChunk = ''; } } if (currentChunk) { chunks.push({ content: currentChunk, type: currentType }); } return chunks; } // 使用原生方法设置值 function setNativeValue(element, value) { const valueSetter = Object.getOwnPropertyDescriptor(element, 'value').set; const prototype = Object.getPrototypeOf(element); const prototypeValueSetter = Object.getOwnPropertyDescriptor(prototype, 'value').set; if (valueSetter && valueSetter !== prototypeValueSetter) { prototypeValueSetter.call(element, value); } else { valueSetter.call(element, value); } } // 模拟粘贴操作 function simulatePaste(element, text) { const clipboardData = new DataTransfer(); clipboardData.setData('text/plain', text); const pasteEvent = new ClipboardEvent('paste', { bubbles: true, cancelable: true, clipboardData: clipboardData, composed: true }); element.dispatchEvent(pasteEvent); } // 触发完整的输入事件序列 function triggerInputEvents(element) { const events = [ 'focus', 'input', 'change', 'keydown', 'keypress', 'keyup' ]; events.forEach(eventName => { const event = new Event(eventName, { bubbles: true, cancelable: true, composed: true }); element.dispatchEvent(event); }); if (document.activeElement === element) { document.dispatchEvent(new Event('selectionchange')); } } // 模拟真实鼠标点击按钮 async function realisticClick(element) { // 获取元素位置 const rect = element.getBoundingClientRect(); // 计算点击位置 const clickX = rect.left + rect.width / 2 + (Math.random() * 10 - 5); const clickY = rect.top + rect.height / 2 + (Math.random() * 10 - 5); // 模拟鼠标移动轨迹 const moveToButton = (x, y) => { const moveEvent = new MouseEvent('mousemove', { bubbles: true, cancelable: true, clientX: x, clientY: y, view: window, buttons: 0 }); document.dispatchEvent(moveEvent); }; // 贝塞尔曲线移动 const startX = clickX + (Math.random() * 100 - 50); const startY = clickY + (Math.random() * 100 - 50); const controlX = (startX + clickX) / 2 + (Math.random() * 40 - 20); const controlY = (startY + clickY) / 2 + (Math.random() * 40 - 20); const points = []; for (let t = 0; t <= 1; t += 0.1) { const x = Math.pow(1 - t, 2) * startX + 2 * (1 - t) * t * controlX + Math.pow(t, 2) * clickX; const y = Math.pow(1 - t, 2) * startY + 2 * (1 - t) * t * controlY + Math.pow(t, 2) * clickY; points.push({ x, y }); } // 移动鼠标 for (const point of points) { moveToButton(point.x, point.y); await delay(10 + Math.random() * 15); } // 鼠标交互序列 element.dispatchEvent(new MouseEvent('mouseenter', { bubbles: true, cancelable: true, clientX: clickX, clientY: clickY, view: window, buttons: 0 })); await delay(120 + Math.random() * 80); element.dispatchEvent(new MouseEvent('mousedown', { bubbles: true, cancelable: true, clientX: clickX, clientY: clickY, view: window, buttons: 1, button: 0 })); await delay(70 + Math.random() * 30); element.dispatchEvent(new MouseEvent('mouseup', { bubbles: true, cancelable: true, clientX: clickX, clientY: clickY, view: window, buttons: 0, button: 0 })); element.dispatchEvent(new MouseEvent('click', { bubbles: true, cancelable: true, clientX: clickX, clientY: clickY, view: window, buttons: 0, button: 0 })); element.dispatchEvent(new MouseEvent('mouseleave', { bubbles: true, cancelable: true, clientX: clickX + 10, clientY: clickY + 10, view: window, buttons: 0 })); await delay(150 + Math.random() * 100); } try { // 定位输入框 const textarea = await waitForElement([ '[data-testid="chat_input_input"]', '.semi-input-textarea.semi-input-textarea-autosize', 'textarea[placeholder="发消息、输入 @ 选择技能或 / 选择文件"]' ]); // 准备输入框 textarea.focus(); await delay(600 + Math.random() * 200); // 清除可能存在的内容 textarea.value = ''; triggerInputEvents(textarea); await delay(200 + Math.random() * 100); // 注入内容 await injectText(textarea, query); // 调整输入框高度 textarea.style.height = 'auto'; textarea.style.height = `${textarea.scrollHeight}px`; await delay(200 + Math.random() * 100); // 验证内容 if (textarea.value.trim() !== query.trim()) { console.warn(`内容验证不匹配(期望: ${query}, 实际: ${textarea.value}),尝试修复`); setNativeValue(textarea, query); triggerInputEvents(textarea); await delay(300 + Math.random() * 150); if (textarea.value.trim() !== query.trim()) { throw new Error(`内容验证失败:期望 "${query}",实际 "${textarea.value}"`); } } console.log(`内容已成功设置:${query}`); await delay(500 + Math.random() * 200); // 定位发送按钮 const sendButton = await waitForElement([ '[data-testid="chat_input_send_button"]', '.send-btn-DDB6yN:not([disabled])', '.semi-button-primary:not([disabled])' ]); // 发送消息 console.log('准备发送消息...'); // 确保输入框有焦点 textarea.focus(); await delay(200 + Math.random() * 100); // 点击发送按钮 await realisticClick(sendButton); // 等待发送结果 await delay(1000 + Math.random() * 500); // 验证是否发送成功 if (textarea.value.trim() !== '') { console.warn('警告:发送后输入框未清空,可能发送失败'); // 尝试使用Enter键发送 const enterEvent = new KeyboardEvent('keydown', { bubbles: true, cancelable: true, key: 'Enter', code: 'Enter', keyCode: 13, which: 13, location: 0, repeat: false, isComposing: false, view: window }); textarea.dispatchEvent(enterEvent); await delay(150); const keyupEvent = new KeyboardEvent('keyup', { bubbles: true, cancelable: true, key: 'Enter', code: 'Enter', keyCode: 13, which: 13, location: 0, repeat: false, isComposing: false, view: window }); textarea.dispatchEvent(keyupEvent); await delay(1000 + Math.random() * 500); if (textarea.value.trim() !== '') { throw new Error('消息发送失败:输入框内容未清空'); } } console.log('消息已成功发送!'); } catch (error) { console.error('脚本执行失败:', error.message); console.trace('错误堆栈跟踪'); } } // 执行条件:仅在豆包聊天页面执行 if (window.location.host === 'www.doubao.com' && window.location.pathname.startsWith('/chat')) { try { addDoubaoQueryParam(); } catch (e) { console.error('脚本主流程异常:', e); } }