// ==UserScript== // @name 飞鸽AI客服2.0 // @namespace http://tampermonkey.net/ // @version 2.0 // @description 精准理解上下文,只回复客户最后一句话,避免答非所问 + 检测.FDBMBK87T0SHSZ_4swP6内5秒并点击 // @author lzylzy6314 // @match https://im.jinritemai.com/* // @grant GM_xmlhttpRequest // @connect api.deepseek.com // @downloadURL https://update.greasyfork.icu/scripts/571092/%E9%A3%9E%E9%B8%BDAI%E5%AE%A2%E6%9C%8D20.user.js // @updateURL https://update.greasyfork.icu/scripts/571092/%E9%A3%9E%E9%B8%BDAI%E5%AE%A2%E6%9C%8D20.meta.js // ==/UserScript== (function() { 'use strict'; // ==================== 核心配置 ==================== const API_KEY = ''; // 替换为你的有效API Key let AUTO_TRIGGER = false; // 默认关闭 const API_URL = 'https://api.deepseek.com/chat/completions'; // 记录会话状态 let lastSessionId = null; let lastCustomerMsg = ''; // 保存最近3条对话历史,用于上下文理解 const chatHistory = []; // 新增:防重复点击5秒的标记 let hasClicked5Seconds = false; // ==================== 核心工具函数 ==================== function findRealInputBox() { let inputBox = document.querySelector('[contenteditable="true"].chat-input'); if (inputBox) return inputBox; inputBox = document.querySelector('#im-input, #im-input-box textarea, .input-area textarea'); if (inputBox) return inputBox; const candidates = document.querySelectorAll('textarea, [contenteditable="true"]'); for (const el of candidates) { if (el.offsetHeight > 0 && el.offsetWidth > 0 && el.getAttribute('placeholder')?.includes('发送')) { return el; } } return null; } function forceFillInput(text) { const inputBox = findRealInputBox(); if (!inputBox) return { success: false, msg: '未找到输入框' }; try { if (inputBox.isContentEditable) { inputBox.innerHTML = ''; const textNode = document.createTextNode(text); inputBox.appendChild(textNode); inputBox.dispatchEvent(new Event('input', { bubbles: true })); inputBox.dispatchEvent(new Event('DOMNodeInserted', { bubbles: true })); const range = document.createRange(); const sel = window.getSelection(); range.selectNodeContents(inputBox); range.collapse(false); sel.removeAllRanges(); sel.addRange(range); } else { inputBox.value = text; inputBox.setAttribute('value', text); inputBox.dispatchEvent(new Event('input', { bubbles: true })); inputBox.dispatchEvent(new Event('change', { bubbles: true })); inputBox.dispatchEvent(new Event('compositionend', { bubbles: true })); } const countEl = document.querySelector('.char-count, [class*="count"]'); if (countEl) countEl.textContent = `${text.length}/800`; return { success: true, msg: '填充成功', inputBox }; } catch (e) { return { success: false, msg: `填充失败:${e.message}` }; } } function forceSendMessage(inputBox) { try { let sendBtn = document.querySelector('#im-send-btn, .send-btn, [class*="send"] button, #im-input-box button'); if (!sendBtn) { sendBtn = Array.from(document.querySelectorAll('button')).find(btn => btn.textContent.includes('发送') && btn.style.background.includes('blue') ); } if (sendBtn) { sendBtn.removeAttribute('disabled'); sendBtn.classList.remove('disabled', 'btn-disabled'); sendBtn.click(); sendBtn.dispatchEvent(new MouseEvent('mousedown', { bubbles: true })); sendBtn.dispatchEvent(new MouseEvent('mouseup', { bubbles: true })); return { success: true, msg: '发送成功' }; } else { inputBox.dispatchEvent(new KeyboardEvent('keydown', { bubbles: true, key: 'Enter', code: 'Enter', keyCode: 13 })); return { success: true, msg: 'Enter键发送成功' }; } } catch (e) { return { success: false, msg: `发送失败:${e.message}` }; } } // ==================== 新增核心:检测.FDBMBK87T0SHSZ_4swP6内的5秒并点击 ==================== function checkAndClick5Seconds() { if (!AUTO_TRIGGER || hasClicked5Seconds) return; // 精准定位指定选择器 const secondElement = document.querySelector('.FDBMBK87T0SHSZ_4swP6'); if (!secondElement) return; // 获取元素内的文本(如:37秒、5秒) const secondText = secondElement.textContent.trim(); // 提取数字部分 const secondNum = parseInt(secondText.replace('秒', ''), 10); // 当数值等于5秒时触发点击 if (secondNum === 5) { try { console.log(`[AI客服] 检测到${secondText},开始点击该元素`); // 点击该元素 secondElement.click(); // 模拟鼠标事件确保触发 secondElement.dispatchEvent(new MouseEvent('mousedown', { bubbles: true })); secondElement.dispatchEvent(new MouseEvent('mouseup', { bubbles: true })); hasClicked5Seconds = true; // 标记已点击,防止重复 // 3秒后重置标记(下次5秒仍能点击) setTimeout(() => { hasClicked5Seconds = false; }, 3000); // 点击后延迟1秒,确保会话加载完成再触发回复 setTimeout(() => { processLatestMsg(); }, 1000); } catch (e) { console.error('[AI客服] 点击5秒元素失败:', e); hasClicked5Seconds = false; } } } // ==================== 精准获取【客户最后一句话】 ==================== function getLatestCustomerMsg() { const selectors = [ '.message-item:not(.self) .message-content', '.chat-item:not(.mine) .chat-content', '.msg-content:not(.self) .msg-text', '.leaveMessage.messageNotMe span' ]; let latestMsg = ''; for (const selector of selectors) { const msgEls = document.querySelectorAll(selector); if (msgEls.length === 0) continue; const lastMsgEl = msgEls[msgEls.length - 1]; const text = lastMsgEl.textContent.trim(); if (text) { latestMsg = text; break; } } return latestMsg; } // ==================== 更新对话历史 ==================== function updateChatHistory(role, content) { chatHistory.push({ role, content }); // 只保留最近3条对话,避免上下文过长 if (chatHistory.length > 3) { chatHistory.shift(); } } // ==================== 核心:处理客户最后一句话(带上下文) ==================== async function processLatestMsg() { if (!AUTO_TRIGGER) return; const currentSessionId = new URLSearchParams(window.location.search).get('selfId'); if (!currentSessionId) return; // 切换会话时重置 if (currentSessionId !== lastSessionId) { lastSessionId = currentSessionId; lastCustomerMsg = ''; chatHistory.length = 0; console.log('[AI客服] 切换到新会话,重置上下文'); return; } const latestMsg = getLatestCustomerMsg(); if (!latestMsg) return; if (latestMsg === lastCustomerMsg) { return; } lastCustomerMsg = latestMsg; updateChatHistory('user', latestMsg); console.log('[AI客服] 处理客户最后一句话:', latestMsg); console.log('[AI客服] 当前对话历史:', chatHistory); try { // 构造带上下文的请求 const messages = [ { role: 'system', content: `你是专业的抖店客服,语气亲切友好(用亲/哦),回复简洁(50字内)。 请严格结合上下文理解客户最后一句话,只针对客户当前问题回复,不要回答之前的问题。 如果客户说【没有了谢谢/不用了/再见】等结束对话的话,请回复【好的亲,祝您生活愉快😊】。` }, ...chatHistory, { role: 'user', content: `请结合上下文,只回复我最后这句话:${latestMsg}` } ]; const aiReply = await new Promise((resolve, reject) => { GM_xmlhttpRequest({ method: 'POST', url: API_URL, headers: { 'Authorization': `Bearer ${API_KEY}`, 'Content-Type': 'application/json' }, data: JSON.stringify({ model: 'deepseek-chat', messages: messages, stream: false, temperature: 0.3, // 降低随机性,让回复更稳定 max_tokens: 100 }), timeout: 20000, onload: (res) => { try { const data = JSON.parse(res.responseText); if (data.error) reject(`DeepSeek错误:${data.error.message}`); const reply = data.choices?.[0]?.message?.content?.trim(); if (!reply) reject('AI回复为空'); resolve(reply); } catch (e) { reject(`解析失败:${e.message}`); } }, onerror: (err) => reject(`网络错误:${err.status}`), ontimeout: () => reject('请求超时') }); }); updateChatHistory('assistant', aiReply); const fillResult = forceFillInput(aiReply); if (!fillResult.success) throw new Error(fillResult.msg); await new Promise(resolve => setTimeout(resolve, 500)); const sendResult = forceSendMessage(fillResult.inputBox); if (!sendResult.success) throw new Error(sendResult.msg); console.log(`[AI客服] 回复成功:${aiReply}`); } catch (e) { console.error(`[AI客服] 回复失败:`, e); lastCustomerMsg = ''; } } // ==================== 实时监听(整合5秒检测+消息回复) ==================== function watchMessages() { setInterval(() => { if (AUTO_TRIGGER) { checkAndClick5Seconds(); // 优先检测5秒并点击 processLatestMsg(); // 然后处理消息回复 } }, 500); // 缩短检测间隔到500ms,秒级响应 } // ==================== 浮窗开关面板 ==================== function createFloatPanel() { const panel = document.createElement('div'); panel.id = 'ai-float-panel'; panel.style = ` position: fixed; bottom: 20px; right: 20px; z-index: 9999999; background: #1677ff; border-radius: 12px; padding: 12px 16px; box-shadow: 0 4px 12px rgba(0,0,0,0.15); color: #fff; font-size: 14px; cursor: move; user-select: none; display: flex; align-items: center; gap: 10px; `; const statusText = document.createElement('span'); statusText.id = 'ai-status'; statusText.textContent = '🤖 AI客服:已关闭'; panel.appendChild(statusText); const toggleBtn = document.createElement('button'); toggleBtn.id = 'ai-toggle'; toggleBtn.style = ` padding: 6px 12px; border: none; border-radius: 6px; background: #ff4d4f; color: #fff; cursor: pointer; font-size: 12px; `; toggleBtn.textContent = '开启AI'; toggleBtn.addEventListener('click', () => { AUTO_TRIGGER = !AUTO_TRIGGER; if (AUTO_TRIGGER) { statusText.textContent = '🤖 AI客服:运行中(监听5秒)'; toggleBtn.textContent = '关闭AI'; toggleBtn.style.background = '#52c41a'; console.log('[AI客服] 已开启,精准理解上下文 + 监听5秒点击'); watchMessages(); } else { statusText.textContent = '🤖 AI客服:已关闭'; toggleBtn.textContent = '开启AI'; toggleBtn.style.background = '#ff4d4f'; console.log('[AI客服] 已关闭'); } }); panel.appendChild(toggleBtn); let isDragging = false, offsetX, offsetY; panel.addEventListener('mousedown', (e) => { if (e.target === toggleBtn) return; isDragging = true; offsetX = e.clientX - panel.offsetLeft; offsetY = e.clientY - panel.offsetTop; e.preventDefault(); }); document.addEventListener('mousemove', (e) => { if (!isDragging) return; panel.style.left = `${e.clientX - offsetX}px`; panel.style.top = `${e.clientY - offsetY}px`; }); document.addEventListener('mouseup', () => isDragging = false); document.body.appendChild(panel); } // ==================== 初始化 ==================== window.addEventListener('load', () => { createFloatPanel(); console.log('[AI客服] 浮窗已加载,默认关闭'); }); })();