You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

Python Discord Bot在树莓派VPS运行5分钟后交互失败问题排查求助

Python Discord Bot在树莓派VPS运行5分钟后交互失败问题排查求助

我现在遇到了一个头疼的问题:我把自己写的Discord Bot部署在朋友的树莓派VPS上,启动一切正常,发送!comando_iscrizioni命令后绿色的"Iscriviti"按钮也能正常显示。前5分钟完全没问题,但过一阵子就会随机出现交互失败的情况——点击绿色按钮时Discord会提示"Interaction Failed"。不过这时候再重新发送!comando_iscrizioni命令,会弹出新的消息,按钮又能正常工作了(而且用户ID还存在iscrizioni这个签到字典里),但再过5分钟又会重复这个问题。看起来Bot并没有真正停止运行,但交互部分就是出问题了,想问问这到底是代码的问题还是VPS的问题?

我的Bot代码

import discord
from discord.ui import Button, View, Modal, TextInput
from discord.ext import commands
from discord import Interaction
import re

intents = discord.Intents.default()
intents.message_content = True
intents.members = True

bot = commands.Bot(command_prefix="!", intents=intents)


iscrizioni = {} # Sign in Dict


report_channel_id = 1234567891011
rules_channel_id = 1234567891011


@bot.command()
async def comando_iscrizioni(ctx):

    button = Button(label="Iscriviti", style=discord.ButtonStyle.green)

    async def button_callback(interaction: discord.Interaction):
        user_id = interaction.user.id

        if user_id in iscrizioni:
            await interaction.response.send_message("Sei già registrato", ephemeral=True)
            return
        
       
        modal = IscrizioneModal()
        await interaction.response.send_modal(modal) 

    button.callback = button_callback
    view = View()
    view.add_item(button)


    await ctx.send(f""" test message <#{rules_channel_id}>""", view=view)

# Sign Up Modal
class IscrizioneModal(Modal):
    def __init__(self):
        super().__init__(title="Modulo di Iscrizione")

       
        self.nickname = TextInput(label='Nickname', placeholder='Inserisci il tuo nickname')
        self.platform = TextInput(label='Piattaforma di gioco', placeholder='PC, PS, Xbox')
        self.assists = TextInput(label='Aiuti Utilizzati', placeholder='ABS, Traiettoria')


        
        self.add_item(self.nickname)
        self.add_item(self.platform)
        self.add_item(self.assists)


    async def on_submit(self, interaction: Interaction):
        nickname = self.nickname.value
        platform = self.platform.value
        assists = self.assists.value

        
        iscrizioni[interaction.user.id] = {
            "nickname": nickname,
            "platform": platform,
            "assists": assists
        }
        
        
        button = Button(label="Next", style=discord.ButtonStyle.primary)

        async def button_callback(button_interaction: Interaction):
            modale_tempi = SecondModal()
            await button_interaction.response.send_modal(modale_tempi)

        button.callback = button_callback
        view = View()
        view.add_item(button)
        await interaction.response.send_message("Dati salvati! Premi il pulsante NEXT per continuare", view=view, ephemeral=True)
        

# Second modal
class SecondModal(Modal):
    def __init__(self):
        super().__init__(title="Inserimento Tempi")

        
        self.bahrain = TextInput(label='Bahrain', placeholder='Inserisci il tempo in modalità Time Trial')
        self.spa = TextInput(label='Belgio', placeholder='Inserisci il tempo in modalità Time Trial')
        self.silverstone = TextInput(label='Silverstone', placeholder='Inserisci il tempo in modalità Time Trial')

        
        self.add_item(self.bahrain)
        self.add_item(self.spa)
        self.add_item(self.silverstone)

    # Format Check Function
    def is_valid_time_format(self, time_str):
        # Regex per il formato minuti.secondi,millesimi
        pattern = r'^\d+\.\d{2},\d{3}$'
        return re.match(pattern, time_str) is not None

    
    async def on_submit(self, interaction: Interaction):
        Bahrain = self.bahrain.value
        Belgio = self.spa.value
        Silverstone = self.silverstone.value

        # Correct Format Check
        if not all(self.is_valid_time_format(time) for time in [Bahrain, Belgio, Silverstone]):
            await interaction.response.send_message("Errore: I tempi devono essere inseriti nel formato 'minuti.secondi,millesimi (Es: 1.26,388)", ephemeral=True)
            return

       
        iscrizioni[interaction.user.id].update({
            "Bahrain": Bahrain,
            "Belgio": Belgio,
            "Silverstone": Silverstone
        })

        await interaction.response.send_message("Iscrizione completata con successo!", ephemeral=True)

        # Send report
        report_channel = bot.get_channel(report_channel_id)
        await report_channel.send(f"""Nuova iscrizione:
        Nickname: {iscrizioni[interaction.user.id]['nickname']}
        Piattaforma: {iscrizioni[interaction.user.id]['platform']}
        Aiuti: {iscrizioni[interaction.user.id]['assists']}
        Bahrain: {iscrizioni[interaction.user.id]['Bahrain']}
        Belgio: {iscrizioni[interaction.user.id]['Belgio']}
        Silverstone: {iscrizioni[interaction.user.id]['Silverstone']}""")


# Avvia il bot
bot.run("ABCDEFGHIKLMNOPQRSTUVXYZ1234567890")

我自己初步梳理的几个怀疑方向,但还没实锤问题:

  1. View的超时机制:Discord.py的View默认是不是有超时时间?我印象里默认是180秒,但我遇到的是5分钟左右,不过会不会是超时后旧的View实例就失效了?但为什么重新发命令生成的新View又能正常工作?
  2. VPS的网络稳定性:树莓派VPS会不会有网络波动,导致Bot和Discord的网关连接断断续续?如果网关重连了,之前生成的View交互令牌应该就失效了吧?
  3. 代码里的View生命周期问题:我在命令里动态创建View和Button,会不会有变量回收或者作用域的问题?
  4. Discord的交互令牌过期:点击按钮时用的是旧消息里的交互令牌,超过Discord的有效时间后就触发失败了?

有没有大佬能帮我分析下根因,或者给点具体的排查步骤?比如怎么查看Bot的网关连接日志,或者怎么修改代码来规避这个问题?

备注:内容来源于stack exchange,提问作者user28899013

火山引擎 最新活动