监控Discord特定用户的消息内容并发送到自定义Webhook
// ==UserScript==
// @name Discord消息Follow邀请码监控
// @namespace http://tampermonkey.net/
// @version 2024-09-19
// @description 监控Discord特定用户的消息内容并发送到自定义Webhook
// @author recar
// @match https://discord.com/channels/1243823539426033696/1265932718084984963
// @icon https://www.google.com/s2/favicons?sz=64&domain=discord.com
// @grant GM_xmlhttpRequest
// @grant GM_addStyle
// @license MIT
// ==/UserScript==
(function() {
'use strict';
// 添加样式
GM_addStyle(`
#config-panel {
position: fixed;
top: 20px;
right: -300px;
width: 280px;
background: #36393f;
border-radius: 8px;
box-shadow: 0 2px 10px 0 rgba(0,0,0,.2);
padding: 16px;
z-index: 9999;
transition: right 0.3s ease-in-out;
color: #dcddde;
font-family: 'Whitney', 'Helvetica Neue', Helvetica, Arial, sans-serif;
}
#config-panel.open {
right: 20px;
}
#config-panel h3 {
margin-top: 0;
color: #fff;
font-size: 16px;
margin-bottom: 16px;
}
#config-panel input, #config-panel button {
width: 100%;
padding: 8px;
margin: 8px 0;
border-radius: 4px;
border: none;
background: #40444b;
color: #dcddde;
font-size: 14px;
}
#config-panel input::placeholder {
color: #72767d;
}
#config-panel button {
background: #5865f2;
color: #fff;
cursor: pointer;
transition: background 0.2s;
}
#config-panel button:hover {
background: #4752c4;
}
#toggle-config {
position: fixed;
top: 20px;
right: 20px;
background: #5865f2;
color: #fff;
border: none;
border-radius: 50%;
width: 40px;
height: 40px;
font-size: 20px;
cursor: pointer;
z-index: 10000;
transition: transform 0.3s;
}
#toggle-config:hover {
transform: rotate(180deg);
}
.example {
font-size: 12px;
color: #72767d;
margin-top: 4px;
}
#status-message {
position: fixed;
bottom: 20px;
right: 20px;
padding: 10px 20px;
background: #5865f2;
color: #fff;
border-radius: 4px;
opacity: 0;
transition: opacity 0.3s;
}
#status-message.show {
opacity: 1;
}
`);
// 配置面板HTML
const configPanelHTML = `
<button id="toggle-config">⚙️</button>
<div id="config-panel">
<h3>配置面板</h3>
<input id="usernames" type="text" placeholder="用户名(逗号分隔)">
<div class="example">例如: Joshua,Alice,Bob</div>
<input id="webhook-url" type="text" placeholder="Webhook URL">
<div class="example">例如: https://api2.pushdeer.com/message/push?pushkey=YOUR_KEY</div>
<input id="interval" type="number" placeholder="检查间隔(毫秒)">
<div class="example">例如: 5000 (5秒)</div>
<button id="save-config">保存配置</button>
<button id="test-config">测试配置</button>
</div>
<div id="status-message"></div>
`;
// 添加配置面板到页面
document.body.insertAdjacentHTML('beforeend', configPanelHTML);
// 获取配置
function getConfig() {
return {
usernames: localStorage.getItem('discord-monitor-usernames') || '',
webhookUrl: localStorage.getItem('discord-monitor-webhook-url') || '',
interval: parseInt(localStorage.getItem('discord-monitor-interval')) || 5000
};
}
// 保存配置
function saveConfig() {
const usernames = document.getElementById('usernames').value;
const webhookUrl = document.getElementById('webhook-url').value;
const interval = document.getElementById('interval').value;
localStorage.setItem('discord-monitor-usernames', usernames);
localStorage.setItem('discord-monitor-webhook-url', webhookUrl);
localStorage.setItem('discord-monitor-interval', interval);
showStatus('配置已保存');
setTimeout(() => location.reload(), 1000);
}
// 测试配置
function testConfig() {
const config = getConfig();
sendWebhook('这是一条测试消息', config.webhookUrl);
}
// 发送webhook
function sendWebhook(message, webhookUrl) {
const url = `${webhookUrl}&text=${encodeURIComponent(message)}`;
GM_xmlhttpRequest({
method: "GET",
url: url,
onload: function(response) {
console.log("Webhook发送成功:", response.responseText);
showStatus("Webhook发送成功");
},
onerror: function(error) {
console.error("Webhook发送失败:", error);
showStatus("Webhook发送失败", true);
}
});
}
// 显示状态消息
function showStatus(message, isError = false) {
const statusElement = document.getElementById('status-message');
statusElement.textContent = message;
statusElement.style.background = isError ? '#ed4245' : '#5865f2';
statusElement.classList.add('show');
setTimeout(() => statusElement.classList.remove('show'), 3000);
}
// 用于存储已处理的消息ID
const processedMessages = new Set();
// 监控新消息
function checkForNewMessages() {
const config = getConfig();
const usernames = config.usernames.split(',').map(u => u.trim());
const messages = document.evaluate(
'//div[contains(@class, "contents_f9f2ca")]',
document,
null,
XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE,
null
);
for (let i = 0; i < messages.snapshotLength; i++) {
const messageElement = messages.snapshotItem(i);
const usernameElement = messageElement.querySelector('.username_f9f2ca');
if (usernameElement && usernames.includes(usernameElement.textContent.trim())) {
const contentElements = messageElement.querySelectorAll('div[id^="message-content-"] span');
contentElements.forEach(contentElement => {
const messageId = contentElement.parentElement.id;
if (!processedMessages.has(messageId)) {
processedMessages.add(messageId);
const content = contentElement.textContent.trim();
console.log(`${usernameElement.textContent.trim()}的新消息 (${messageId}): ${content}`);
sendWebhook(`${usernameElement.textContent.trim()}的新消息: ${content}`, config.webhookUrl);
}
});
}
}
}
// 初始化
function init() {
const config = getConfig();
document.getElementById('usernames').value = config.usernames;
document.getElementById('webhook-url').value = config.webhookUrl;
document.getElementById('interval').value = config.interval;
document.getElementById('save-config').addEventListener('click', saveConfig);
document.getElementById('test-config').addEventListener('click', testConfig);
document.getElementById('toggle-config').addEventListener('click', () => {
document.getElementById('config-panel').classList.toggle('open');
});
setInterval(checkForNewMessages, config.interval);
checkForNewMessages(); // 初始检查
}
// 运行初始化
init();
})();
QingJ © 2025
镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址