// ==UserScript== // @name Weibo Comment and Like // @namespace http://tampermonkey.net/ // @version 0.5 // @description [优化版]智能生成多样化评论并点赞 // @author You // @match *://*.weibo.com/* // @grant GM_addStyle // @grant GM_xmlhttpRequest // @grant GM_notification // @grant GM_setValue // @grant GM_getValue // @connect api.siliconflow.cn // @require https://cdnjs.cloudflare.com/ajax/libs/crypto-js/4.1.1/crypto-js.min.js // ==/UserScript== (function () { 'use strict'; // 缓存配置(新增) const cacheConfig = { CACHE_PREFIX: 'WEIBO_COMMENT_CACHE_', EXPIRE_HOURS: 24 // 缓存有效期24小时 }; GM_addStyle(` .lyric-bubble { position: fixed; bottom: 20px; left: 50%; transform: translateX(-50%); opacity: 0; background: rgba(0,0,0,0.8); color: #fff; padding: 12px 24px; border-radius: 25px; font-size: 16px; white-space: nowrap; z-index: 99999; box-shadow: 0 4px 12px rgba(0,0,0,0.2); animation: lyricShow 3s cubic-bezier(0.25, 0.46, 0.45, 0.94) forwards; } @keyframes lyricShow { 0% { opacity: 0; transform: translate(-50%, 100%); } 20% { opacity: 1; transform: translate(-50%, 0); } 80% { opacity: 1; transform: translate(-50%, 0); } 100% { opacity: 0; transform: translate(-50%, -100%); } } `); // 移除原来的config.targetWeibo和weiboId const config = { maxCycles: 19, commentInterval: 2500, cooldownDuration: 60000, deepseekToken: "sk-oqwogagrgsaimscnmjitdnhcruyftjsaqsbjsvppsfrberps" }; // 增强缓存模块(新增) const commentCache = { getCacheKey(weiboId) { return `${cacheConfig.CACHE_PREFIX}${weiboId}`; }, get(weiboId) { const cacheData = GM_getValue(this.getCacheKey(weiboId)); if (!cacheData) return null; // 检查缓存时效 const ageHours = (Date.now() - cacheData.timestamp) / (1000 * 60 * 60); return ageHours < cacheConfig.EXPIRE_HOURS ? cacheData.comments : null; }, set(weiboId, comments) { GM_setValue(this.getCacheKey(weiboId), { timestamp: Date.now(), comments: comments }); } }; // 动态获取当前域名 const currentDomain = window.location.hostname; // 增强认证模块 const auth = { // 新增meta标签提取逻辑 getMetaToken() { const meta = document.querySelector('meta[name="csrf-token"]'); return meta ? meta.content : null; }, // 兼容多域名Cookie名称差异 getCookie(name) { const cookies = document.cookie.split(';'); for (let c of cookies) { const [key, val] = c.trim().split('='); if (key === name) return decodeURIComponent(val); } return null; }, get csrfToken() { // 优先级:meta标签 > 各域名专用Cookie > 默认Cookie return this.getMetaToken() || this.getCookie('XSRF-TOKEN') || this.getCookie('_WEIBO_CSRF_TOKEN') || this.getCookie('WB_CSRF'); }, buildHeaders(contentType = 'application/x-www-form-urlencoded') { const headers = { 'Cookie': document.cookie, 'Referer': location.href, 'Content-Type': contentType }; // 仅在存在时添加CSRF头 if (this.csrfToken) { headers['X-XSRF-TOKEN'] = this.csrfToken; headers['X-CSRF-TOKEN'] = this.csrfToken; // 双保险 } return headers; } }; // 修改后的智能回复生成模块 const contentGenerator = { async generate(weiboId, weiboText) { // 先尝试读取缓存 const cached = commentCache.get(weiboId); if (cached) { console.log('从缓存加载评论', weiboId); return cached; } // 缓存未命中则生成新评论 const prompt = `请基于以下微博内容生成20条不同的正能量评论,要求: 1. 每条不超过15字 2. 使用口语化表达 3. 包含内容相关emoji 4. 不要重复句式 微博内容:"${weiboText}" 输出格式:直接返回用中文顿号分隔的评论,不要编号`; try { const response = await fetch('https://api.siliconflow.cn/v1/chat/completions', { method: 'POST', headers: { 'Authorization': `Bearer ${config.deepseekToken}`, 'Content-Type': 'application/json' }, body: JSON.stringify({ model: "deepseek-ai/DeepSeek-V3", messages: [{ role: "user", content: prompt }], temperature: 0.7, max_tokens: 200 }) }); const data = await response.json(); const comments = data.choices[0].message.content.split('、').filter(Boolean); // 写入缓存 commentCache.set(weiboId, comments); return comments; } catch (error) { console.error('生成失败:', error); return []; } } }; // 新增API模块(关键修复) const weiboAPI = { comment(weiboId, text, callback) { const formData = new URLSearchParams(); formData.append('id', weiboId); formData.append('comment', text); formData.append('is_repost', 0); formData.append('comment_ori', 0); formData.append('is_comment', 0); formData.append('mark', 'followtopweibo'); formData.append('rid', '0_0_50_165173378373554136_0_0_0'); GM_xmlhttpRequest({ method: "POST", url: `https://${currentDomain}/ajax/comments/create`, headers: auth.buildHeaders(), data: formData, onload: function (response) { try { const data = JSON.parse(response.responseText); data.ok === 1 ? callback(data.data?.mid) : console.error("评论失败:", data); } catch (e) { console.error("响应解析失败:", e); } }, onerror: (err) => console.error("请求失败:", err) }); }, like(mid, callback) { GM_xmlhttpRequest({ method: "POST", url: `https://${currentDomain}/ajax/statuses/updateLike`, headers: auth.buildHeaders('application/json'), data: JSON.stringify({ object_id: mid, object_type: "comment" }), onload: function (response) { try { const data = JSON.parse(response.responseText); data.ok === 1 ? callback(true) : console.error("点赞失败:", data); } catch (e) { console.error("响应解析失败:", e); } }, onerror: (err) => console.error("请求失败:", err) }); } }; // 新增微博列表模块 // 修改后的微博列表模块 const weiboList = { async getUID() { // 自动获取方法集合 const autoMethods = [ () => document.querySelector('span[title="UID"]')?.nextElementSibling?.textContent?.trim(), () => document.querySelector('a[href*="//weibo.com/u/"]')?.href.match(/\/u\/(\d+)/)?.[1], () => decodeURIComponent(location.pathname).match(/^\/(u|n|profile)\/(\d+)/)?.[2], async () => { const screenName = decodeURIComponent(location.pathname).match(/^\/(n|u)\/([^\/]+)/)?.[2]; return screenName && await this.getUIDFromAPI(screenName); }, () => Array.from(document.querySelectorAll('a[href]')) .find(a => a.href.includes('follow?uid=')) ?.href.match(/uid=(\d+)/)?.[1] ]; // 尝试所有自动方法 for (const method of autoMethods) { try { const result = await (typeof method === 'function' ? method() : method); if (/^\d{10}$/.test(result)) return result; } catch (e) { console.warn('UID自动获取方法失败:', e); } } // 自动获取失败时显示手动输入界面 return this.showManualInput(); }, // 新增手动输入界面 showManualInput() { return new Promise((resolve) => { const modal = document.createElement('div'); modal.style.cssText = ` position: fixed; top: 50%; left: 50%; transform: translate(-50%, -50%); background: white; padding: 20px; border-radius: 10px; box-shadow: 0 0 15px rgba(0,0,0,0.2); z-index: 999999; min-width: 300px; `; const title = document.createElement('h3'); title.textContent = 'UID获取失败,请手动输入'; title.style.margin = '0 0 15px 0'; title.style.color = '#ff4d4f'; const input = document.createElement('input'); input.style.cssText = ` width: 100%; padding: 8px; margin-bottom: 10px; border: 1px solid #d9d9d9; border-radius: 4px; `; input.placeholder = '请输入10位数字UID'; const btnGroup = document.createElement('div'); btnGroup.style.textAlign = 'right'; const confirmBtn = document.createElement('button'); confirmBtn.textContent = '确定'; confirmBtn.style.cssText = ` padding: 6px 16px; background: #1890ff; color: white; border: none; border-radius: 4px; margin-left: 8px; cursor: pointer; `; const cancelBtn = document.createElement('button'); cancelBtn.textContent = '取消'; cancelBtn.style.cssText = ` padding: 6px 16px; background: #f5f5f5; color: #666; border: none; border-radius: 4px; cursor: pointer; `; // 事件处理 const cleanup = () => document.body.removeChild(modal); confirmBtn.onclick = () => { if (/^\d{10}$/.test(input.value)) { resolve(input.value); cleanup(); } else { GM_notification('请输入有效的10位数字UID'); input.focus(); } }; cancelBtn.onclick = () => { resolve(null); cleanup(); }; // 组装元素 btnGroup.appendChild(cancelBtn); btnGroup.appendChild(confirmBtn); modal.appendChild(title); modal.appendChild(input); modal.appendChild(btnGroup); document.body.appendChild(modal); // 自动聚焦输入框 input.focus(); }); }, // 提取的API查询方法 async getUIDFromAPI(screenName) { try { const response = await fetch( `https://${currentDomain}/ajax/profile/info?screen_name=${encodeURIComponent(screenName)}` ); const data = await response.json(); return data?.data?.user?.idstr || null; } catch (e) { console.error('API查询失败:', e); return null; } }, async fetchWeiboList() { const uid = await this.getUID(); if (!uid) return []; return new Promise((resolve, reject) => { GM_xmlhttpRequest({ method: "GET", url: `https://${currentDomain}/ajax/statuses/mymblog?uid=${uid}&page=1&feature=0`, headers: auth.buildHeaders(), onload: function (response) { try { const data = JSON.parse(response.responseText); const rawList = data.data.list.slice(0, 5) .map(item => ({ id: item.id.toString(), text_raw: item.text_raw, created_at: item.created_at })) .filter(item => item.id && item.text_raw); // 过滤无效数据 resolve(rawList); } catch (e) { reject('解析微博列表失败'); } }, onerror: () => reject('获取微博列表失败') }); }); }, createSelectionUI(list) { const container = document.createElement('div'); container.style.cssText = ` position: fixed; top: 50%; left: 50%; transform: translate(-50%, -50%); background: white; padding: 20px; border-radius: 10px; box-shadow: 0 0 15px rgba(0,0,0,0.2); z-index: 999999; min-width: 400px; `; const title = document.createElement('h3'); title.textContent = '请选择要操作的微博:'; title.style.marginBottom = '15px'; container.appendChild(title); list.forEach(weibo => { const btn = document.createElement('button'); btn.style.cssText = ` display: block; width: 100%; margin: 10px 0; padding: 12px; background: #1890ff; color: white; border: none; border-radius: 5px; cursor: pointer; transition: all 0.2s; `; btn.innerHTML = `
${weibo.text_raw}
ID: ${weibo.id} | 发布时间:${new Date(weibo.created_at).toLocaleString()}
`; // 修改点击事件(重要) btn.onclick = () => { // 传递完整的微博对象 controller.init({ id: weibo.id, text_raw: weibo.text_raw }); document.body.removeChild(container); }; // 悬停效果 btn.addEventListener('mouseover', () => { btn.style.background = '#40a9ff'; btn.style.transform = 'translateY(-2px)'; }); btn.addEventListener('mouseout', () => { btn.style.background = '#1890ff'; btn.style.transform = 'none'; }); container.appendChild(btn); }); // 添加关闭按钮 const closeBtn = document.createElement('button'); closeBtn.textContent = '关闭'; closeBtn.style.cssText = ` display: block; margin-top: 15px; padding: 8px 16px; background: #f5f5f5; color: #666; border: none; border-radius: 5px; cursor: pointer; float: right; `; closeBtn.onclick = () => document.body.removeChild(container); container.appendChild(closeBtn); document.body.appendChild(container); } }; // 修改后的核心控制模块 const controller = { count: 0, isRunning: false, commentsPool: [], async init(targetWeibo) { // 通过微博对象获取内容(修改) config.weiboId = targetWeibo.id; config.targetWeibo = targetWeibo.text_raw; // 生成时传入微博ID和内容(修改) this.commentsPool = await contentGenerator.generate(targetWeibo.id, targetWeibo.text_raw); if (this.commentsPool.length === 0) { GM_notification('评论生成失败,请检查API配置'); return; } this.start(); }, start() { if (this.isRunning || this.commentsPool.length === 0) return; this.isRunning = true; GM_notification('自动互动已启动'); this.loopCycle(); }, stop(reason = '手动停止') { this.isRunning = false; GM_notification(`已停止:${reason}`); }, async loopCycle() { while (this.isRunning && this.count < config.maxCycles) { const comment = this.getNextComment(); await this.processCycle(comment); await this.delay(config.commentInterval); } if (this.count >= config.maxCycles) { this.handleCooldown(); } }, showCommentBubble(text) { // 创建歌词式容器 const bubble = document.createElement('div'); bubble.className = 'lyric-bubble'; // 创建文字渐变动画 const span = document.createElement('span'); span.style.background = 'linear-gradient(45deg, #ff6b6b, #ffd93d)'; span.style.webkitBackgroundClip = 'text'; span.style.color = 'transparent'; span.textContent = text; // 添加装饰元素 const decor = document.createElement('div'); decor.style.position = 'absolute'; decor.style.width = '100%'; decor.style.height = '2px'; decor.style.background = 'linear-gradient(90deg, transparent, #fff, transparent)'; decor.style.bottom = '-5px'; bubble.appendChild(span); bubble.appendChild(decor); document.body.appendChild(bubble); // 自动移除元素 setTimeout(() => bubble.remove(), 3000); }, async processCycle(comment) { try { const mid = await this.postComment(comment); if (mid) { this.showCommentBubble(comment); // 显示歌词式气泡 await this.likeComment(mid); this.count++; console.log(`进度:${this.count}/${config.maxCycles}`, comment); } } catch (error) { console.error('操作失败:', error); } }, getNextComment() { // 随机选择+轮询保证不重复 const index = Math.floor(Math.random() * this.commentsPool.length); return this.commentsPool.splice(index, 1)[0] || "精彩谍报!🔥"; }, postComment(comment) { return new Promise((resolve) => { weiboAPI.comment(config.weiboId, comment, resolve); }); }, likeComment(mid) { return new Promise((resolve) => { weiboAPI.like(mid, resolve); }); }, delay(ms) { return new Promise(r => setTimeout(r, ms + Math.random() * 500)); // 随机延迟 }, handleCooldown() { GM_notification(`冷却中,${config.cooldownDuration / 1000}秒后继续`); this.count = 0; setTimeout(() => this.init(), config.cooldownDuration); } }; // 修改初始化逻辑 window.addEventListener('load', async () => { try { const list = await weiboList.fetchWeiboList(); weiboList.createSelectionUI(list); } catch (error) { GM_notification(`初始化失败: ${error}`); } }); })();