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")
我自己初步梳理的几个怀疑方向,但还没实锤问题:
- View的超时机制:Discord.py的
View默认是不是有超时时间?我印象里默认是180秒,但我遇到的是5分钟左右,不过会不会是超时后旧的View实例就失效了?但为什么重新发命令生成的新View又能正常工作? - VPS的网络稳定性:树莓派VPS会不会有网络波动,导致Bot和Discord的网关连接断断续续?如果网关重连了,之前生成的View交互令牌应该就失效了吧?
- 代码里的View生命周期问题:我在命令里动态创建View和Button,会不会有变量回收或者作用域的问题?
- Discord的交互令牌过期:点击按钮时用的是旧消息里的交互令牌,超过Discord的有效时间后就触发失败了?
有没有大佬能帮我分析下根因,或者给点具体的排查步骤?比如怎么查看Bot的网关连接日志,或者怎么修改代码来规避这个问题?
备注:内容来源于stack exchange,提问作者user28899013




