Discord.py中on_message无法识别ctx、member参数,如何实现违禁词自动禁言功能
Discord.py 违禁词自动禁言功能正确实现
你原有代码的核心错误点如下:
on_message事件仅接收message参数,你用到的ctx、member均属于未定义变量,所需的服务器、发信用户对象都可以从message的内置属性获取- 直接使用
asyncio.sleep(3600)逻辑不可靠,若机器人中途重启,将永远不会触发解除禁言的操作 - 未过滤机器人自身发送的消息,可能出现机器人自己触发规则的问题
- 仅检测消息开头是否匹配违禁词,会漏掉消息中后部包含违禁词的情况
推荐实现(使用Discord原生超时功能,无需自定义Muted角色,Discord.py v2.0+支持)
这是最稳定的实现方案,超时逻辑由Discord服务端维护,即使机器人重启也不会影响到期自动解除:
import discord from discord.ext import commands # 初始化时需要开启成员意图 intents = discord.Intents.default() intents.message_content = True intents.members = True client = commands.Bot(command_prefix='!', intents=intents) # 违禁词列表,可自行扩充 BANNED_WORDS = ["坏词1", "坏词2", "坏词3"] @client.event async def on_message(message): # 跳过机器人自己发的消息 if message.author.bot: return # 检测消息内容是否包含违禁词 if any(bad_word in message.content.lower() for bad_word in BANNED_WORDS): # 从message对象获取服务器和发信成员 guild = message.guild member = message.author # 先发送提示 await message.channel.send(f"{member.mention}, 你发送了违禁内容,已被自动禁言1小时。") # 删除违禁消息 await message.delete() # 执行超时禁言,时间单位为秒,3600秒即1小时 await member.timeout(discord.utils.utcnow() + discord.timedelta(seconds=3600), reason="发送违禁内容") # 如果你同时写了指令功能,需要加这行保证指令正常触发 await client.process_commands(message)
兼容旧版本实现(使用自定义Muted角色)
如果你使用的Discord.py版本低于2.0,不支持原生超时功能,可以用自定义角色的方式实现,注意该方案下机器人重启会导致未执行的解除禁言失效:
import discord import asyncio from discord.ext import commands intents = discord.Intents.default() intents.message_content = True intents.members = True client = commands.Bot(command_prefix='!', intents=intents) BANNED_WORDS = ["坏词1", "坏词2", "坏词3"] @client.event async def on_message(message): if message.author.bot: return if any(bad_word in message.content.lower() for bad_word in BANNED_WORDS): guild = message.guild member = message.author await message.channel.send(f"{member.mention}, 你发送了违禁内容,已被自动禁言1小时。") await message.delete() # 获取Muted角色 muted_role = discord.utils.get(guild.roles, name="Muted") if not muted_role: # 可以加自动创建Muted角色的逻辑,也可以手动提前创建 await message.channel.send("未找到Muted角色,请先手动创建禁言角色") return await member.add_roles(muted_role, reason="发送违禁内容") # 等待1小时后解除 await asyncio.sleep(3600) # 解除前先判断用户是否还在服务器、是否还有禁言角色 if muted_role in member.roles: await member.remove_roles(muted_role, reason="禁言到期自动解除") await client.process_commands(message)
注意事项
- 需要提前在Discord开发者门户的机器人设置页面开启
Server Members Intent和Message Content Intent两个权限开关,否则无法读取消息内容和获取成员信息 - 机器人的角色排序需要高于普通用户角色,且拥有「管理成员」权限,才能正常执行禁言操作
- 可以自行扩充
BANNED_WORDS列表里的违禁词,支持任意数量的关键词匹配
内容的提问来源于stack exchange,提问作者Tigran
相关产品推荐
相关产品推荐

