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

Discord.py中discord.Member.timeout()函数无法正常运行问题求助

问题排查与修复方案

核心问题分析

你的代码存在几个关键问题,直接导致timeout()函数失效且交互报错:

1. 未处理Discord交互响应

当用户选择"Timeouten"且有足够超时券时,代码执行到await member1.timeout(timeout)后没有对交互做任何回应。Discord要求所有交互必须在3秒内得到响应,超时就会返回"This interaction wasn't successful"。

2. 全局变量的不安全使用

用全局变量member1传递目标成员,多用户同时使用命令时会导致变量被覆盖,引发逻辑混乱。正确做法是把目标成员存储在View实例内部。

3. 缺少错误处理与权限校验

没有捕获timeout()可能抛出的异常(比如机器人权限不足、目标成员权限高于机器人、目标是服务器所有者等),无法定位具体失败原因。

4. 全局变量初始化错误

初始member1 = discord.Member是把类赋值给变量,虽然后续命令会覆盖,但这种写法容易引发混淆和潜在问题。


修复后的完整代码

import discord
from discord.ext import commands
import json
import datetime
from discord import app_commands

class SelectMenu3(discord.ui.View):
    def __init__(self, target_member: discord.Member):
        super().__init__(timeout=180)  # 设置View超时时间,避免长期占用资源
        self.target_member = target_member  # 将目标成员存入View实例,替代全局变量

    options1 = [
        discord.SelectOption(label="Timeouten", value="1", description="Timeout someone"),
        discord.SelectOption(label="Enttimeouten", value="2", description="Opposite")
    ]

    @discord.ui.select(placeholder="Options", options=options1)
    async def menu_callback3(self, interaction: discord.Interaction, select):
        select.disabled = True
        await interaction.response.edit_message(view=self)  # 先禁用选择器,防止重复操作

        with open("cogs/eco.json", "r") as f:
            user_eco = json.load(f)
        
        member = interaction.user
        eco_embed = discord.Embed(title="Timeouts", description="", colour=discord.Color.blue())
        eco_embed.add_field(name="Amount Timeout:", value=f"{user_eco[str(member.id)]['Timeout']}")

        if select.values[0] == "1":
            if user_eco[str(member.id)]['Timeout'] >= 1:
                timeout_duration = datetime.timedelta(minutes=1)
                try:
                    # 执行禁言,附带原因便于服务器审计
                    await self.target_member.timeout(timeout_duration, reason=f"Timeout by {member.display_name} using timeout ticket")
                    # 扣除超时券并保存到文件
                    user_eco[str(member.id)]['Timeout'] -= 1
                    with open("cogs/eco.json", "w") as f:
                        json.dump(user_eco, f, indent=4)
                    # 发送成功反馈
                    await interaction.followup.send(content=f"✅ 成功将{self.target_member.mention}禁言1分钟!", ephemeral=True)
                except discord.Forbidden:
                    await interaction.followup.send(content="❌ 我没有权限对该成员执行禁言操作!", ephemeral=True)
                except discord.HTTPException as e:
                    await interaction.followup.send(content=f"❌ 禁言失败:{str(e)}", ephemeral=True)
            else:
                await interaction.followup.send(content="Du hast nicht genug Timeout-Tickets für diese Aktion", ephemeral=True)
        elif select.values[0] == "2":
            if user_eco[str(member.id)]['Timeout'] >= 1:
                try:
                    # 解除禁言逻辑
                    await self.target_member.timeout(None, reason=f"Removed timeout by {member.display_name} using timeout ticket")
                    # 扣除超时券并保存
                    user_eco[str(member.id)]['Timeout'] -= 1
                    with open("cogs/eco.json", "w") as f:
                        json.dump(user_eco, f, indent=4)
                    await interaction.followup.send(content=f"✅ 成功解除{self.target_member.mention}的禁言!", ephemeral=True)
                except discord.Forbidden:
                    await interaction.followup.send(content="❌ 我没有权限解除该成员的禁言!", ephemeral=True)
                except discord.HTTPException as e:
                    await interaction.followup.send(content=f"❌ 解除禁言失败:{str(e)}", ephemeral=True)
            else:
                await interaction.followup.send(content="Du hast nicht genug Timeout-Tickets für diese Aktion", ephemeral=True)

@app_commands.command(name="timeout", description="使用超时券对成员进行禁言或解除禁言")
async def timeout(self, interaction: discord.Interaction, member: discord.Member):
    # 提前校验无效目标
    if member == interaction.client.user:
        await interaction.response.send_message(content="❌ 我不能对自己执行操作!", ephemeral=True)
        return
    if member == interaction.guild.owner:
        await interaction.response.send_message(content="❌ 我不能对服务器所有者执行操作!", ephemeral=True)
        return
    # 创建View并传入目标成员
    view = SelectMenu3(target_member=member)
    await interaction.response.send_message(content="Choose", view=view, ephemeral=True)

关键修复点说明

  • 替换全局变量:通过View构造函数传递目标成员,彻底避免多用户并发时的变量冲突。
  • 强制交互响应:在回调开头先更新View禁用选择器,再用followup.send()返回操作结果,确保Discord交互不会超时。
  • 添加错误处理:捕获Forbidden(权限不足)和HTTPException(API/网络错误)异常,给出明确的失败提示。
  • 完善权限校验:提前过滤机器人自身和服务器所有者,避免无效操作。
  • 补全超时券逻辑:执行操作后自动扣除超时券并保存到JSON文件(原代码遗漏了这一核心逻辑)。
  • 优化代码可读性:用datetime.timedelta(minutes=1)替代冗长的全参数写法,提升代码简洁度。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.01 23:10:43