Discord.py tempmute命令如何支持s/m/h/d时间单位后缀
实现tempmute命令识别s/m/h/d时间后缀的改造方案
改造核心逻辑
不需要复杂的自定义discord.py转换器,只需要新增时间字符串解析逻辑,替换原有直接读取整数秒的参数逻辑即可。改造完成后命令调用格式和预期完全一致,示例:tempmute @张三 30m 恶意刷屏,会自动识别30m为30分钟,后面的内容自动拼接为违规原因,同时兼容原有的纯数字(默认按秒计算)的输入习惯。
支持的输入规则
- 带后缀格式:
30s(30秒)、30m(30分钟)、2h(2小时)、1d(1天),后缀大小写不敏感(比如30M和30m效果一致) - 兼容原有格式:纯数字输入默认按秒计算,比如
60等同于60s - 非法输入(比如
30x、abc、负数时长)会自动触发报错提示,不会导致机器人崩溃
改造后完整代码
import asyncio import discord from discord.ext import commands # 时间单位和秒数的映射规则,可自行扩展支持的单位 TIME_UNITS = { "s": 1, "m": 60, "h": 3600, "d": 86400 } def parse_time(time_input: str): """解析时间字符串,返回(总秒数, 人类可读时间描述),非法输入返回(None, None)""" time_input = time_input.strip().lower() # 处理纯数字的情况,默认单位为秒 if time_input.isdigit(): total_seconds = int(time_input) * TIME_UNITS["s"] return total_seconds, f"{time_input}秒" # 提取最后一位作为单位校验 unit = time_input[-1] if unit not in TIME_UNITS: return None, None # 提取数值部分校验 num_part = time_input[:-1] if not num_part.isdigit(): return None, None num = int(num_part) total_seconds = num * TIME_UNITS[unit] unit_cn = {"s": "秒", "m": "分钟", "h": "小时", "d": "天"}[unit] return total_seconds, f"{num}{unit_cn}" # 以下为原有客户端初始化逻辑,按实际配置替换 client = commands.Bot(command_prefix="!") @client.command() @commands.has_permissions(manage_messages=True) async def tempmute(ctx, member: discord.Member, time_str: str, reason=None): # 处理未提供原因的默认情况 if reason == None: reason = "未提供违规原因" # 自静音校验,补充原代码缺失的return逻辑,否则校验后仍会继续执行静音流程 if member.id == ctx.author.id: await ctx.send(f"{ctx.author.mention}, 你不能给自己使用临时静音命令") return # 解析并校验时间参数合法性 total_seconds, time_desc = parse_time(time_str) if total_seconds is None or total_seconds <= 0: await ctx.send("时间格式有误!请输入类似 `30s`/`30m`/`2h`/`1d` 的格式,纯数字默认按秒计算,且时长必须大于0") return role = discord.utils.get(ctx.guild.roles, name="Muted") guild = ctx.guild # 不存在Muted角色时自动创建并配置全频道权限 if not role: role = await guild.create_role(name="Muted") for channel in guild.channels: await channel.set_permissions(role, speak=False, send_messages=False, read_message_history=True, read_messages=False) embed = discord.Embed(title="临时静音生效", description=f"{member.mention} 已被临时静音", colour=discord.Colour.light_gray()) embed.add_field(name="违规原因", value=reason, inline=False) embed.add_field(name="静音时长", value=time_desc, inline=False) await member.add_roles(role) await ctx.send(embed=embed) # 等待对应时长后自动移除静音角色 await asyncio.sleep(total_seconds) await member.remove_roles(role) # 以下为原有机器人运行逻辑,按实际配置替换 # client.run("你的机器人Token")
额外注意点
- 目前的解析逻辑仅支持单单位后缀,不支持组合格式(比如
1h30m),如果需要支持组合格式可以自行扩展解析函数的拆分逻辑 - 原有逻辑的临时静音状态存储在内存中,如果机器人重启,所有未到期的临时静音会直接失效,不会自动恢复,属于原有代码的设计限制,本次改造未调整这部分逻辑
- 请确保机器人的角色层级在「Muted」角色上方,且拥有管理频道权限、管理角色的权限,否则会出现创建角色、设置频道权限失败的问题
内容的提问来源于stack exchange,提问作者Codestuff
相关产品推荐
相关产品推荐

