如何在discord.py中用Discord原生系统设置带单位的Timeout
在discord.py中使用原生系统设置用户Timeout(支持带单位时长)
前提依赖
确保你使用的是discord.py v2.0及以上版本,原生Timeout功能是在这个版本之后正式加入的。安装/更新命令:
pip install discord.py>=2.0
1. 解析带单位的时长字符串
先实现一个函数,将1m、2h、3d这类格式的字符串转换为datetime.timedelta对象,同时遵守Discord对Timeout的最长限制(28天):
import re from datetime import timedelta def parse_duration(duration_str: str) -> timedelta: # 匹配数字+单位的模式,支持s(秒)、m(分)、h(时)、d(天) pattern = re.compile(r'(\d+)([smhd])') matches = pattern.findall(duration_str.lower()) if not matches: raise ValueError("无效的时长格式,请使用如1m、2h、3d的格式") total_seconds = 0 for value, unit in matches: value = int(value) if unit == 's': total_seconds += value elif unit == 'm': total_seconds += value * 60 elif unit == 'h': total_seconds += value * 3600 elif unit == 'd': total_seconds += value * 86400 # Discord限制Timeout最长为28天,超出则自动截断 max_duration = timedelta(days=28) parsed_duration = timedelta(seconds=total_seconds) return parsed_duration if parsed_duration <= max_duration else max_duration
2. 从数据库获取目标用户ID
根据你的数据库结构,实现查询逻辑(以下为示例,需根据实际数据库类型调整):
def get_user_id_by_username(target_username: str) -> int | None: # 替换为你实际的数据库操作代码,比如SQLite/MySQL查询 cursor.execute("SELECT user_id FROM users WHERE username = ?", (target_username,)) result = cursor.fetchone() return result[0] if result else None
3. 实现原生Timeout命令
使用discord.py提供的Member.timeout()原生方法(无需角色循环),结合上述函数完成完整命令:
import discord from discord.ext import commands # 初始化Bot,启用message_content意图(前缀命令需要) intents = discord.Intents.default() intents.message_content = True bot = commands.Bot(command_prefix='!', intents=intents) @bot.command(name='timeout') @commands.has_permissions(moderate_members=True) # 限制仅有权限的用户执行 async def timeout_user(ctx: commands.Context, target_username: str, duration_str: str): # 1. 从数据库获取目标用户ID user_id = get_user_id_by_username(target_username) if not user_id: await ctx.send(f"未找到用户 {target_username}") return # 2. 获取服务器内的成员对象(Timeout仅针对服务器成员) target_member = ctx.guild.get_member(user_id) if not target_member: await ctx.send(f"用户 {target_username} 不在当前服务器中") return # 3. 解析输入的时长 try: duration = parse_duration(duration_str) except ValueError as e: await ctx.send(str(e)) return # 4. 执行原生Timeout操作 try: await target_member.timeout(duration, reason="管理员执行Timeout") await ctx.send(f"已将 {target_username} 禁言 {duration_str}") except discord.Forbidden: await ctx.send("我没有权限执行该操作") except discord.HTTPException as e: await ctx.send(f"执行Timeout时出错:{e}") # 启动Bot bot.run('你的Bot令牌')
额外说明
- 权限要求:Bot需要服务器的「Moderate Members」权限,命令执行者也需拥有该权限。
- 时长限制:Discord原生Timeout最长支持28天,超出的时长会自动截断为28天。
- Slash命令适配:如果需要使用Slash命令,只需将命令改为
@bot.tree.command()格式,参数处理逻辑基本一致。
内容的提问来源于stack exchange,提问作者romi5792
相关产品推荐
相关产品推荐

