如何在Discord.py中通过表情反应关闭消息删除监听等moderation事件
功能实现指导
核心实现思路
你不需要复杂调用wait_for或dispatch即可实现需求,核心逻辑是给每个服务器单独存储删除消息日志的开关状态,通过点击❗表情切换开关即可:
- 初始化时为Cog添加字典存储每个服务器的开关状态,默认开启删消息日志
- 完善
on_reaction_add中❗表情的触发逻辑,切换对应服务器的开关并给出提示 - 修复原代码中
on_message_delete里未定义的x变量,替换为开关状态判断
完整修改后代码
import discord from discord.ext import commands import datetime import asyncio class log(commands.Cog): def __init__(self,bot): self.bot = bot # 存储每个服务器的删除消息日志开关,key为guild id,value为bool值,默认开启 self.delete_log_enabled = {} @commands.Cog.listener() async def on_reaction_add(self, reaction, user): channel = reaction.message.channel guild = channel.guild message = reaction.message if user != self.bot.user: # 初始化当前服务器的开关状态(如果不存在) if guild.id not in self.delete_log_enabled: self.delete_log_enabled[guild.id] = True if reaction.emoji == '1️⃣': check = discord.utils.get(guild.categories, name="Chilly Logs") if not check: cat = await guild.create_category_channel('Chilly Logs') await guild.create_text_channel("Message Logs", category=cat) await guild.create_text_channel("Other Logs", category=cat) await channel.send('**日志频道创建成功!**') await message.remove_reaction('1️⃣', user) return else: await channel.send('**日志频道已存在**') await message.remove_reaction('1️⃣', user) if reaction.emoji == '2️⃣': channel1 = discord.utils.get(guild.channels, name="other-logs") channel2 = discord.utils.get(guild.channels, name="message-logs") category = discord.utils.get(guild.categories, name="Chilly Logs") if category is not None: await channel1.delete() await channel2.delete() await category.delete() await channel.send('**日志频道已移除**') await message.remove_reaction('2️⃣', user) else: await channel.send('**频道不存在或已被重命名**') await message.remove_reaction('2️⃣', user) if reaction.emoji == '❗': # 切换删除日志开关状态 self.delete_log_enabled[guild.id] = not self.delete_log_enabled[guild.id] status = "已开启" if self.delete_log_enabled[guild.id] else "已关闭" await channel.send(f'**删除消息日志{status}**') await message.remove_reaction('❗', user) return @commands.command() async def test(self, ctx): embed = discord.Embed(title = "Chilly 日志功能", description = "Chilly会记录所有编辑、删除的消息,更多功能正在开发中", colour = discord.Color.blurple()) embed.add_field(name="日志操作指令", value="1️⃣ - 开启服务器日志", inline=True) embed.add_field(name=" ", value= "2️⃣ - 关闭日志并删除日志频道", inline=False) embed.add_field(name=" ", value= "❗ - 开启/关闭删除消息日志记录", inline=False) msg = await ctx.send(embed=embed) emoji = ['1️⃣', '2️⃣', '❗'] for e in emoji: await msg.add_reaction(e) @commands.Cog.listener() async def on_message_delete(self, message): # 先判断当前服务器开关状态,默认开启 guild_id = message.guild.id if guild_id not in self.delete_log_enabled: self.delete_log_enabled[guild_id] = True if not self.delete_log_enabled[guild_id]: return if not message.author.bot: channel = message.channel.name logchannel = discord.utils.get(message.guild.channels, name='message-logs') if not logchannel: return embed = discord.Embed(title="消息日志", description="", color= discord.Color.red()) embed.add_field(name=f"{message.author.display_name} 发送的消息在 `{channel}` 频道被删除", value=message.content, inline=True) embed.set_footer(text=f'用户ID: {message.author.id} | 消息ID: {message.id}') await logchannel.send(embed=embed) @commands.Cog.listener() async def on_message_edit(self, before, after): if not after.author.bot: if before.content != after.content: channel = after.channel.name logchannel = discord.utils.get(after.guild.channels, name='message-logs') if not logchannel: return embed = discord.Embed(title="消息日志", description=f"消息在 `{channel}` 频道被 {after.author.display_name} 编辑", color= discord.Color.red()) embed.add_field(name="编辑前", value=before.content, inline=True) embed.add_field(name="编辑后", value=after.content, inline=False) embed.set_footer(text=f'用户ID: {after.author.id} | 消息ID: {before.id}') await logchannel.send(embed=embed) def setup(bot): bot.add_cog(log(bot))
相关函数用法说明
你提到的两个函数用法如下:
wait_for:用于等待指定事件触发,适合单次等待用户操作场景,比如发送消息后等待指定用户添加反应,示例用法:# 等待60秒内用户对消息添加反应 def check(reaction, user): return user == ctx.author and str(reaction.emoji) == '❗' try: reaction, user = await self.bot.wait_for('reaction_add', timeout=60.0, check=check) except asyncio.TimeoutError: await ctx.send('操作超时') else: await ctx.send('你点击了❗反应')dispatch:用于手动触发指定事件,一般用于自定义事件或测试场景,比如手动触发一次消息删除事件:# 手动触发on_message_delete事件,传入要模拟删除的消息对象 self.bot.dispatch("message_delete", message_obj)
内容的提问来源于stack exchange,提问作者Zyb3rWolfi
相关产品推荐
相关产品推荐

