You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Discord.py 定时禁言(mute)命令无报错也不生效问题求助

问题排查与修复

你代码里的问题如下,按影响优先级排序:

  • time参数类型错误:你将time参数注解为int类型,但实际需要传入带单位的字符串(如10m),discord.py的参数转换器会直接拒绝这类输入,就算你传纯数字,后续time[:-1]的切片操作也会因为int类型不支持切片直接报错。把参数注解改成time:str=None即可解决。
  • reason默认值逻辑位置错误:if reason == None的判断写在了if time == None的return分支内部,只要传入了有效time,该判断永远不会触发,reason会一直为None,把这段逻辑移到time判断的外面。
  • Muted角色无权限限制:这是禁言不生效的核心原因。你只是创建了名为Muted的空角色,没有给这个角色配置所有频道的「禁止发送消息」「禁止连接语音」「禁止发送语音消息」等限制权限,用户带上这个角色没有任何实际限制,看起来就像功能没生效。创建角色后需要遍历服务器所有频道,给Muted角色设置对应禁止权限。
  • Bot角色权限不足:Bot的最高角色的排序必须高于Muted角色,也必须高于你要禁言的目标用户的最高角色,否则Bot没有权限给目标用户添加Muted角色。
  • 定时逻辑有缺陷:用asyncio.sleep做定时,只要Bot重启,所有待执行的解除禁言任务都会丢失,用户会被永久禁言,建议改用定时任务配合数据库存储禁言到期时间的方案。

修复后参考代码

import asyncio
import discord
from discord.ext import commands

@commands.command()
@commands.guild_only()
@commands.has_permissions(kick_members=True)
async def mute(self, ctx, member: discord.Member=None, time:str=None, reason=None):
    # 找Muted角色,不存在就创建并配置权限
    muted_role = discord.utils.get(ctx.guild.roles, name="Muted")
    if not muted_role:
        muted_role = await ctx.guild.create_role(name="Muted")
        # 给所有频道配置Muted角色的禁止权限
        for channel in ctx.guild.channels:
            await channel.set_permissions(muted_role, 
                                          send_messages=False,
                                          speak=False,
                                          send_messages_in_threads=False,
                                          add_reactions=False)
    # 参数校验
    if not member or member == ctx.author:
         await ctx.send("You cannot mute yourself :angry:")
         return
    if not time:
        return await ctx.send("You have to write the time for which you want to mute the mentioned user!")
    # 处理默认reason
    if not reason:
        reason = "For being a jerk."
    # 角色权限校验,直接用role.position属性,不用取index
    if ctx.author.top_role.position <= member.top_role.position:
        return await ctx.send("You don't have enough permission to mute this user!")
    # Bot自身权限校验
    if ctx.guild.me.top_role.position <= member.top_role.position or ctx.guild.me.top_role.position <= muted_role.position:
        return await ctx.send("I don't have enough permission to mute this user!")
    
    # 时间转换
    time_convert = {"s":1, "m":60, "h":3600,"d":86400}
    unit = time[-1].lower()
    if unit not in time_convert:
        return await ctx.send("Invalid time unit! Use s/m/h/d, e.g. 10m")
    try:
        num = int(time[:-1])
    except ValueError:
        return await ctx.send("Invalid time format! e.g. 10m")
    tempmute = num * time_convert[unit]
    
    # 执行禁言
    await member.add_roles(muted_role, reason=reason)
    await ctx.send(f'{member.mention} has been muted for {time}. Reason: {reason}.')
    
    # 定时解除禁言,优化方案可以用tasks loop代替sleep
    await asyncio.sleep(tempmute)
    # 解除前先校验用户还在服务器,还持有Muted角色
    if member in ctx.guild.members and muted_role in member.roles:
        await member.remove_roles(muted_role, reason="Mute expired")

内容的提问来源于stack exchange,提问作者Captain Underpants

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.04 08:00:00