实现Discord机器人向指定角色成员发私信并统计回复状态
Discord 私信机器人实现方案(Discord.js v14)
以下是基于最新Discord.js v14的完整实现代码,包含私信发送、回复统计和报告生成功能:
1. 核心代码实现
首先确保你已经安装了discord.js和@discordjs/builders:
npm install discord.js @discordjs/builders
完整机器人代码:
const { Client, GatewayIntentBits, EmbedBuilder } = require('discord.js'); const client = new Client({ intents: [ GatewayIntentBits.Guilds, GatewayIntentBits.GuildMembers, GatewayIntentBits.DirectMessages, GatewayIntentBits.MessageContent ] }); // 存储统计数据:key为用户ID,value为状态(delivered/failed/responded) const statusTracker = new Map(); // 存储当前任务的目标角色和消息内容 let currentTask = null; client.on('ready', () => { console.log(`Logged in as ${client.user.tag}!`); }); // 处理!send前缀命令 client.on('messageCreate', async (message) => { if (!message.content.startsWith('!send') || message.author.bot) return; // 解析命令参数:@角色 消息内容 const args = message.content.slice(6).trim().split(/\s+/); const roleMention = args.shift(); if (!roleMention) { return message.reply('格式错误:!send @角色 "消息内容"'); } const roleId = roleMention.match(/\d+/)[0]; const role = message.guild.roles.cache.get(roleId); if (!role) { return message.reply('找不到指定角色'); } const messageContent = args.join(' ').replace(/^['"]|['"]$/g, ''); if (!messageContent) { return message.reply('请输入要发送的消息内容'); } // 初始化统计数据 statusTracker.clear(); currentTask = { roleId, messageContent }; // 获取角色成员(排除机器人) const members = role.members.filter(m => !m.user.bot); const total = members.size; message.reply(`开始给${role.name}的${total}名成员发送私信...`); // 批量发送,避免触发速率限制 for (const [userId, member] of members) { try { const dmChannel = await member.user.createDM(); await dmChannel.send(messageContent); statusTracker.set(userId, 'delivered'); } catch (err) { statusTracker.set(userId, 'failed'); } // 每发送一条暂停1秒 await new Promise(resolve => setTimeout(resolve, 1000)); } message.reply('私信发送完成,可使用!report查看统计'); }); // 监听用户DM回复 client.on('messageCreate', async (message) => { if (!message.guild && !message.author.bot && currentTask) { const userId = message.author.id; if (statusTracker.has(userId) && statusTracker.get(userId) === 'delivered') { statusTracker.set(userId, 'responded'); } } }); // 生成统计报告命令 client.on('messageCreate', async (message) => { if (message.content !== '!report' || message.author.bot || !currentTask) return; const role = message.guild.roles.cache.get(currentTask.roleId); if (!role) return message.reply('当前任务的角色已不存在'); const delivered = []; const responded = []; const notResponded = []; const failed = []; for (const [userId, status] of statusTracker) { const user = await client.users.fetch(userId).catch(() => null); const username = user ? `${user.tag}` : `未知用户(${userId})`; switch (status) { case 'delivered': delivered.push(username); notResponded.push(username); break; case 'responded': responded.push(username); break; case 'failed': failed.push(username); break; } } // 移除未回复列表中的已回复用户 notResponded.forEach((user, index) => { if (responded.includes(user)) notResponded.splice(index, 1); }); // 构建报告内容 const report = [ `${role.name}的${delivered.length + failed.length}名成员已收到私信;`, `${responded.length}名用户已回复(${responded.join(', ')});`, `${notResponded.length}名用户未回复(${notResponded.join(', ')});`, `${failed.length}条消息无法送达(${failed.join(', ')})。` ].join('\n'); // 用Embed发送避免内容截断 const embed = new EmbedBuilder() .setTitle('私信回复统计报告') .setDescription(report) .setColor('#0099ff'); message.channel.send({ embeds: [embed] }); }); // 替换为你的机器人Token client.login('YOUR_BOT_TOKEN');
2. 关键功能说明
- 命令解析:支持
!send @角色 "消息内容"格式,自动提取目标角色和消息文本 - 速率控制:每发送一条私信暂停1秒,规避Discord的API请求限制
- 状态追踪:用
Map实时记录每个用户的私信状态(已送达/发送失败/已回复) - 报告生成:通过
!report命令生成符合要求的统计报告,使用Embed格式避免内容过长被截断
3. 其他实现方式
- Slash命令替代前缀命令:Discord官方推荐使用
/send这类Slash命令,无需处理前缀解析,更符合平台规范 - 持久化存储:用SQLite、MongoDB替代内存
Map,可保留历史任务数据,重启机器人后不丢失 - 批量发送优化:使用
Promise.allSettled结合分批处理,提升发送效率的同时严格控制请求速率 - 按钮式回复确认:在私信中添加Discord按钮组件,用户点击按钮即视为回复,无需发送消息,统计更精准
内容的提问来源于stack exchange,提问作者eNFThusiast.eth
相关产品推荐
相关产品推荐

