微博热点回复
// ==UserScript==
// @name 微博热点回复
// @namespace http://tampermonkey.net/
// @version 1.3
// @description 微博热点回复
// @match https://*.weibo.com/*
// @grant GM_xmlhttpRequest
// @grant GM_addStyle
// @grant GM_getValue
// @grant GM_setValue
// @grant GM_getResourceText
// @connect weibo.com
// @connect ark.cn-beijing.volces.com
// @require https://cdnjs.cloudflare.com/ajax/libs/crypto-js/4.1.1/crypto-js.min.js
// @resource ENC_KEY ZWNkOTg2OGItMzBjYy00NmExLTg1MWUtODNkZWMzMjBlNmU0
// ==/UserScript==
(function () {
"use strict";
// 动态获取当前域名
const currentDomain = window.location.hostname;
const CONFIG = {
commentTemplate: "支持正能量!👍",
checkInterval: 300000, // 5分钟检查一次
cooldownPeriod: 900000, // 15分钟冷却时间
maxCommentsPerCycle: 25, // 每个周期最大评论数
}
// 将密钥转换为字节数组
function keyToBytes(key) {
const bytes = [];
for (let i = 0; i < key.length; i += 2) {
bytes.push(parseInt(key.substr(i, 2), 16));
}
return bytes;
}
// XOR 加密/解密函数
function xorCrypto(input, keyBytes) {
let output = '';
for (let i = 0; i < input.length; i++) {
const charCode = input.charCodeAt(i) ^ keyBytes[i % keyBytes.length];
output += String.fromCharCode(charCode);
}
return output;
}
// 加密函数
function encrypt(plaintext,SECRET_KEY) {
const keyBytes = keyToBytes(SECRET_KEY);
return btoa(xorCrypto(plaintext, keyBytes)); // 使用 Base64 编码
}
// 解密函数
function decryptToken(ciphertext,SECRET_KEY) {
const keyBytes = keyToBytes(SECRET_KEY);
const decoded = atob(ciphertext); // 使用 Base64 解码
return xorCrypto(decoded, keyBytes);
}
// 使用示例 ---------------------------------------------------
// 生成密钥(推荐使用安全随机数生成)
const secretKey =
"666f2fdde94d9f0d1120404a85b1d800494556a7815bef3c526389ea523c45f4"; // CryptoJS.lib.WordArray.random(256/8).toString();
const encryptedToken="A1wd698rqTw8QyUvt5zsYnEge57iOd0RYga60mBfJ5JUWRbq"
//"e3266f61-cee2-4b8e-9cb2-0e382cbf2697"
// 解密验证
const decryptedToken = decryptToken(encryptedToken, secretKey);
// 全局状态
let timer = null;
let cooldownTimer = null;
let toggleButton = null;
let countElement = null;
// 初始化入口
function init() {
initPanel();
initEventListeners();
updateCounter();
}
// 新增冷却状态提示
function showCoolDownTip() {
if (!document.getElementById("coolDownTip")) {
const tip = document.createElement("div");
tip.id = "coolDownTip";
tip.style = `position: fixed; top: 130px; right: 20px; background: #ff9800;
color: white; padding: 8px; border-radius: 4px;`;
tip.textContent = "冷却中(15分钟)";
document.body.appendChild(tip);
}
}
// 获取CSRF Token
function getXsrfToken() {
const match = document.cookie.match(/XSRF-TOKEN=([^;]+)/);
return match ? decodeURIComponent(match[1]) : "";
}
// 初始化控制面板
function initPanel() {
GM_addStyle(`
#weibo-comment-panel {
position: fixed;
top: 100px;
right: 20px;
background: #fff;
padding: 15px;
border-radius: 8px;
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
z-index: 99999;
}
#toggleBtn {
margin-top: 10px;
padding: 5px 15px;
cursor: pointer;
}
`);
const panelHTML = `
<h3 style="margin:0 0 10px 0; font-size:16px;">自动评论状态</h3>
<p>今日已评论:<span id="commentCount">0</span>/${CONFIG.maxCommentsPerCycle}</p >
<button id="toggleBtn">启动</button>
`;
const panel = document.createElement("div");
panel.id = "weibo-comment-panel";
panel.innerHTML = panelHTML;
document.body.appendChild(panel);
// 获取元素引用
toggleButton = document.getElementById("toggleBtn");
countElement = document.getElementById("commentCount");
}
// 初始化事件监听
function initEventListeners() {
if (toggleButton) {
toggleButton.addEventListener("click", handleToggle);
} else {
console.error("无法找到切换按钮");
}
}
// 主流程控制
async function mainProcess() {
try {
// const todayCount = GM_getValue('dailyCount', 0);
// if (todayCount >= CONFIG.maxCommentsPerDay) {
// stopTimer();
// return;
// }
await processWeibo();
updateCounter();
} catch (e) {
console.error("处理失败:", e);
}
}
// 获取微博列表
function fetchWeiboList() {
return new Promise((resolve, reject) => {
GM_xmlhttpRequest({
method: "GET",
//url: `https://${currentDomain}/ajax/feed/unreadfriendstimeline?list_id=100015273983120&refresh=4&since_id=${CONFIG.since_id}&count=15`,
url: `https://${currentDomain}/ajax/feed/hottimeline?since_id=0&refresh=0&group_id=102803&containerid=102803&extparam=discover%7Cnew_feed&max_id=0&count=10`,
// url:`https://${currentDomain}/ajax/feed/unreadfriendstimeline?list_id=100016096514678&refresh=4&since_id=0&count=15`,
headers: {
"X-Requested-With": "XMLHttpRequest",
Cookie: document.cookie,
"X-XSRF-TOKEN": getXsrfToken(),
},
onload: (res) => {
try {
const data = JSON.parse(res.responseText);
if (data.ok === 1) {
GM_setValue("since_id", data.max_id_str);
resolve(data.statuses);
}
} catch (e) {
reject(e);
}
},
onerror: reject,
});
});
}
// 发送评论
function postComment(weiboId, content) {
return new Promise((resolve, reject) => {
console.log("回复的内容:" + content);
GM_xmlhttpRequest({
method: "POST",
url: `https://${currentDomain}/ajax/comments/create`,
headers: {
"Content-Type": "application/x-www-form-urlencoded",
"X-XSRF-TOKEN": getXsrfToken(),
Cookie: document.cookie,
},
data: `id=${weiboId}&comment=${encodeURIComponent(
content
)}&pic_id=&is_repost=0&comment_ori=0&is_comment=0`,
onload: resolve,
onerror: reject,
});
});
}
// 修改后的处理微博流程
async function processWeibo() {
try {
const currentCount = GM_getValue("commentCount", 0);
// 达到限制时进入冷却
if (currentCount >= CONFIG.maxCommentsPerCycle) {
stopTimer();
GM_setValue("commentCount", 0);
showCoolDownTip();
cooldownTimer = setTimeout(() => {
document.getElementById("coolDownTip").remove();
startTimer();
}, CONFIG.cooldownPeriod);
return;
}
const weiboList = await fetchWeiboList();
// const targetWeibos = weiboList.filter(weibo =>
// CONFIG.keywords.some(keyword =>
// weibo.text_raw.includes(keyword)
// )
// );
for (const weibo of weiboList) {
if (GM_getValue("commentCount", 0) >= CONFIG.maxCommentsPerCycle) break;
await new Promise((r) => setTimeout(r, 2000));
const content = await generateContent(weibo.text_raw);
await postComment(weibo.id, content);
GM_setValue("commentCount", GM_getValue("commentCount", 0) + 1);
updateCounter();
// 实时检查评论限制
if (GM_getValue("commentCount", 0) >= CONFIG.maxCommentsPerCycle) {
stopTimer();
showCoolDownTip();
cooldownTimer = setTimeout(() => {
document.getElementById("coolDownTip").remove();
GM_setValue("commentCount", 0);
startTimer();
}, CONFIG.cooldownPeriod);
break;
}
}
} catch (e) {
console.error("处理失败:", e);
}
}
// 修改后的定时器控制
function startTimer() {
if (!timer) {
timer = setInterval(() => {
processWeibo().catch(console.error);
}, CONFIG.checkInterval);
// 立即执行一次检查
processWeibo().catch(console.error);
updateButtonState();
}
}
function stopTimer() {
if (timer) {
clearInterval(timer);
timer = null;
updateButtonState();
}
if (cooldownTimer) {
clearTimeout(cooldownTimer);
cooldownTimer = null;
}
}
// 更新状态显示
function updateCounter() {
if (countElement) {
countElement.textContent = GM_getValue("commentCount", 0);
countElement.style.color =
GM_getValue("commentCount", 0) >= CONFIG.maxCommentsPerCycle
? "red"
: "inherit";
}
}
// 按钮点击处理(修复版)
function handleToggle() {
if (timer) {
stopTimer();
} else {
startTimer();
// 立即执行一次
mainProcess().catch(console.error);
}
updateButtonState();
}
// 更新按钮状态
function updateButtonState() {
if (toggleButton) {
toggleButton.textContent = timer ? "暂停" : "启动";
toggleButton.style.backgroundColor = timer ? "#ff4444" : "#4CAF50";
}
}
// 更新计数器
// function updateCounter() {
// if (countElement) {
// countElement.textContent = GM_getValue('dailyCount', 0);
// }
// }
// 修改后的generateContent函数
function generateContent(content) {
console.log("需要回复的内容:" + content);
const prompt = `根据以下微博内容生成一句积极温暖的回复(口语化、带表情符号、不超过40字):${content}`;
return new Promise((resolve, reject) => {
GM_xmlhttpRequest({
method: "POST",
url: "https://ark.cn-beijing.volces.com/api/v3/chat/completions",
headers: {
Authorization: `Bearer ${decryptedToken}`,
"Content-Type": "application/json",
},
data: JSON.stringify({
model: "deepseek-v3-241226",
messages: [
{
role: "system",
content: "你是一个社交媒体回复助手。",
},
{
role: "user",
content: prompt,
},
],
max_tokens: 150,
}),
onload: function (response) {
try {
const result = JSON.parse(response.responseText);
if (result.choices && result.choices[0].message.content) {
resolve(
result.choices[0].message.content
.replace(/【\d+†.*】/g, "") // 清理特殊标记
.trim()
);
} else {
throw new Error("API返回格式异常");
}
} catch (e) {
console.error("解析失败:", e);
reject(e);
}
},
onerror: function (err) {
console.error("请求失败:", err);
reject(err);
},
});
});
}
// 页面加载初始化
if (document.readyState === "complete") {
init();
} else {
window.addEventListener("load", init);
}
})();