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

Discord.py机器人启动4分钟后按钮失效的解决办法咨询

Discord机器人按钮4分钟后失效的修复方案

问题描述

使用Python的discord.py开发Discord机器人,机器人启动4分钟后按钮会停止工作,原本打算每3分钟重启机器人,寻求其他修复方案。

当前代码情况

导入的库

import discord
from random import randint
import json
from discord.ext import commands
# 注意:此处导入错误,正确应为 from discord.ui import Button, View
from discord.User interface import button, view

按钮示例代码

class ButtonSandStone8(discord.ui.Button):
    def __init__(self, label):
        super().__init__(label=label, style=discord.ButtonStyle.grey, custom_id='SandStone_btn8')

    async def callback(self, interaction):
        global queue8
        if f"<@{interaction.user.id}>\n\n\n" in queue8:
            global lobby_voice8, ct8, t8, voice_ct8, voice_t8
            voice_state = interaction.user.voice

            if voice_state is None:
                embed = discord.Embed(description='你必须进入语音频道才能参与!', color=discord.Color.dark_grey())
                return await interaction.response.send_message(embed=embed, ephemeral=True)

            elif interaction.user.voice.channel.id == lobby_voice8:
                global voices8
                if len(queue8)-10 < 10:
                    embed = discord.Embed(description='队列未满!', color=discord.Color.dark_grey())
                    await interaction.response.send_message(embed=embed, ephemeral=True)

                elif len(queue8)-10 == 10 and interaction.user not in voices8 and f"<@{interaction.user.id}>\n\n\n" in queue8:
                    voices8.append(interaction.user)
                    global SandStone8, Rust8, Zone98, Province8, Breeze8
                    SandStone8 += 1
                    if len(voices8) < 10:
                        embed = discord.Embed(description='+1 票给SandStone地图', color=discord.Color.dark_grey())
                        await interaction.response.send_message(embed=embed, ephemeral=True)

                    if len(voices8) == 10:
                        global msg8
                        await msg8.delete()
                        if SandStone8 > Rust8 and SandStone8 > Zone98 and SandStone8 > Breeze8 and SandStone8 > Province8:
                            await distribution_sandstone8(interaction)

                        elif Rust8 > SandStone8 and Rust8 > Zone98 and Rust8 > Breeze8 and Rust8 > Province8:
                            await distribution_rust8(interaction)

                        elif Zone98 > SandStone8 and Zone98 > Rust8 and Zone98 > Province8 and Zone98 > Breeze8:
                            await distribution_zone98(interaction)

                        elif Province8 > SandStone8 and Province8 > Rust8 and Province8 > Zone98 and Province8 > Breeze8:
                            await distribution_province8(interaction)

                        elif Breeze8 > SandStone8 and Breeze8 > Rust8 and Breeze8 > Zone98 and Breeze8 > Province8:
                            await distribution_breeze8(interaction)

                        else:
                            voices8.clear()
                            SandStone8 = 0
                            Rust8 = 0
                            Zone98 = 0
                            Province8 = 0
                            Breeze8 = 0
                            embed = discord.Embed(description='平局!重新投票', color=discord.Color.dark_grey())
                            await interaction.response.send_message(embed=embed, delete_after=180)

            else:
                embed = discord.Embed(description='你连接的不是正确的语音频道!', color=discord.Color.dark_grey())
                await interaction.response.send_message(embed=embed, ephemeral=True)

        else:
            embed = discord.Embed(description='你不在投票队列中!', color=discord.Color.red())
            await interaction.response.send_message(embed=embed, ephemeral=True)

按钮调用示例代码

SandStone_btn8 = ButtonSandStone8("1.SandStone")
# 修改此处:设置timeout=None避免超时失效
w = discord.ui.View(timeout=None)
w.add_item(SandStone_btn8)

修复方案

1. 解决View超时问题

discord.py的View默认超时时间为180秒(3分钟),超时后按钮会自动失效。直接将View的timeout参数设为None,即可让按钮永久有效:

w = discord.ui.View(timeout=None)

2. 修复导入错误

原代码中的导入语句有误,正确的导入方式应为:

from discord.ui import Button, View

错误的导入可能导致视图系统无法正常工作,进而引发按钮失效问题。

3. 使用持久化视图(可选)

如果希望机器人重启后按钮依然能响应,需要注册持久化视图。在机器人启动时添加以下代码:

# 在机器人启动完成后注册持久化视图
@bot.event
async def on_ready():
    bot.add_view(ButtonSandStone8(label="1.SandStone"))
    print(f"Logged in as {bot.user}")

注意:持久化视图要求按钮必须设置唯一的custom_id(你的代码中已经设置了custom_id='SandStone_btn8',符合要求)。

4. 替换全局变量,用类封装状态

代码中大量使用全局变量,容易导致状态混乱和内存泄漏,建议用类来封装每个游戏大厅的状态:

class GameLobby:
    def __init__(self, lobby_voice_channel):
        self.lobby_voice = lobby_voice_channel
        self.queue = []
        self.voices = []
        # 投票计数
        self.votes = {
            "SandStone": 0,
            "Rust": 0,
            "Zone9": 0,
            "Province": 0,
            "Breeze": 0
        }
        self.msg = None

# 使用示例
lobby8 = GameLobby(lobby_voice_channel)

然后在按钮的callback方法中引用这个类的实例,替代全局变量,避免全局状态污染。

5. 检查交互响应的完整性

确保所有分支都有对应的交互响应,避免因未响应导致Discord标记交互失败,进而影响后续按钮功能。你的代码中大部分分支都有send_message,但要确保没有遗漏的情况。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.11 04:20:24