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

Discord.py 临时禁言指令适配无空格时间输入的实现方法

tempmute指令参数兼容优化实现

问题根源

原代码的参数定义为time: int, d,框架做参数解析时,碰到用户输入的10m会直接把整段字符串塞给time参数尝试转换为整数,转换失败就直接抛出BadArgument报错,根本走不到后续的参数解析流程,自然无法识别紧凑的无空格时间输入格式。

优化思路

不再强制把时间数值和时间单位拆成两个独立入参——直接收集成员参数之后、原因参数之前的所有输入内容,在指令内部统一做拆分解析,这样不管用户是把数字和单位连起来输(10m),还是按老习惯用空格分开输(10 m),都能正常解析,也不用强迫老用户改变原有使用习惯。

具体改动点

  • 把原来拆分的time: int, d两个入参换成可变位置参数*time_parts,把所有时间相关的输入片段统一收集
  • 新增正则格式校验逻辑,将收集到的片段拼接后,直接匹配「数字+单字符时间单位」的规则
  • 用字典存储时间单位和对应秒数的映射,删掉原来重复编写的多分支if判断
  • 移除原代码里多余的循环查找Muted角色的逻辑——之前已经通过工具方法获取/创建好该角色,没必要再遍历全服务器的角色列表重复检索

优化后的完整代码

import asyncio
import re
import discord
from discord.ext import commands

# 预定义时间单位对应的秒数映射
UNIT_SECONDS_MAP = {
    "s": 1,
    "m": 60,
    "h": 60 * 60,
    "d": 60 * 60 * 24
}

@bot.command()
async def tempmute(ctx, member: discord.Member, *time_parts: str, reason: str = None):
    guild = ctx.guild
    mutedRole = discord.utils.get(guild.roles, name="Muted")
    
    # 不存在Muted角色时自动创建
    if not mutedRole:
        mutedRole = await guild.create_role(name="Muted")
        # 为所有频道配置禁言角色的权限限制
        for channel in guild.channels:
            await channel.set_permissions(mutedRole, speak=False, send_messages=False)

    # 解析时间参数:同时兼容 "10m" 和 "10 m" 两种输入格式
    raw_time_str = "".join(time_parts).lower().strip()
    time_match = re.match(r"^(\d+)([smhd])$", raw_time_str)
    
    # 格式不合法时直接给用户友好提示
    if not time_match:
        await ctx.send("时间格式不合法,请输入类似 `10s`/`5m`/`2h`/`3d` 的格式,示例:`!tempmute @用户 10m 违规发言`")
        return

    time_value = int(time_match.group(1))
    time_unit = time_match.group(2)
    total_sleep_seconds = time_value * UNIT_SECONDS_MAP[time_unit]
    display_time = f"{time_value}{time_unit}"

    # 执行禁言操作
    await member.add_roles(mutedRole)
    embed = discord.Embed(
        title="TempMuted!",
        description=f"{member.mention} 已被临时禁言",
        colour=discord.Colour.red()
    )
    embed.add_field(name="禁言原因", value=reason if reason else "未指定原因", inline=False)
    embed.add_field(name="禁言时长", value=display_time, inline=False)
    await ctx.send(embed=embed)

    # 等待禁言时长结束后自动解除
    await asyncio.sleep(total_sleep_seconds)
    await member.remove_roles(mutedRole)

    unmute_embed = discord.Embed(
        title="临时禁言到期",
        description=f"{member.mention} 已自动解除禁言",
        colour=discord.Colour.light_gray()
    )
    await ctx.send(embed=unmute_embed)

实际兼容效果

改完后两种输入方式都可以正常使用:

  • 新支持的紧凑写法:!tempmute @违规用户 10m 恶意刷屏
  • 完全兼容的旧拆分写法:!tempmute @违规用户 10 m 恶意刷屏
    如果用户输入了非法的时间格式(比如10x、abc这类无意义内容),指令会直接返回明确的格式提示,不会把框架的原始报错暴露给用户。

内容的提问来源于stack exchange,提问作者Jack Thorn

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.28 00:24:08