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

discord.py报错:'Button'对象无'response'属性及房间选择需求

Discord房间预订机器人问题修复与功能实现

问题描述

我正在开发一款连接Discord与Google Sheets的房间预订机器人,执行!reserver指令会弹出一个按钮,但点击按钮时触发交互错误,报错信息为:AttributeError: 'Button' object has no attribute 'response'。同时希望实现点击按钮后显示房间选择菜单的功能。

源代码

import discord
from discord.ext import commands
from discord.ui import Button, View, Select
import gspread
from oauth2client.service_account import ServiceAccountCredentials
import logging


logging.basicConfig(level=logging.ERROR)

intents = discord.Intents.default()
intents.message_content = True
intents.members = True
bot = commands.Bot(command_prefix='!', intents=intents)


def get_gspread_client():
  scope = [
      "https://spreadsheets.google.com/feeds",
      "https://www.googleapis.com/auth/spreadsheets",
      "https://www.googleapis.com/auth/drive.file",
      "https://www.googleapis.com/auth/drive"
  ]
  creds = ServiceAccountCredentials.from_json_keyfile_name(
      "reservation-salles-brique-901c122a60ee.json", scope)
  return gspread.authorize(creds)


def get_room_names():
  client = get_gspread_client()
  spreadsheet = client.open('Réservation des salles')
  worksheet = spreadsheet.worksheet('Nom des salles')
  room_names = [
      item['Nom de la salle'] for item in worksheet.get_all_records()
  ]
  return room_names


class RoomSelect(Select):

  def __init__(self):
    room_names = get_room_names()
    options = [discord.SelectOption(label=room) for room in room_names]
    super().__init__(placeholder='Sélectionnez une salle...', options=options)

  async def callback(self, interaction: discord.Interaction):
    self.view.room = self.values[0]
    self.view.stop()


class TimeInputView(View):

  def __init__(self):
    super().__init__()
    self.room = None

  @discord.ui.button(label="Réserver", style=discord.ButtonStyle.green)
  async def reserve_button(self, button: discord.ui.Button,
                           interaction: discord.Interaction):
    try:
      if self.room:
        # ...
        await interaction.response.send(
            f'Réservation confirmée pour {self.room} dans la feuille "Réservation".'
        )
      else:
        await interaction.response.send('Veuillez sélectionner une salle.')
    except gspread.exceptions.APIError as e:
      logging.error(f"Erreur lors de l'interaction avec Google Sheets : {e}")
    except discord.errors.DiscordException as e:
      logging.error(f"Erreur lors de l'interaction avec Discord : {e}")


@bot.command()
async def reserver(ctx):
  view = TimeInputView()
  await ctx.send(
      "Veuillez sélectionner la salle que vous souhaitez réserver :",
      view=view)


@bot.event
async def on_ready():
  print(f'Bot connecté comme {bot.user}')


bot.run('TOKEN')

错误日志

ERROR    discord.ui.view Ignoring exception in view <TimeInputView timeout=180.0 children=1> for item <Button style=<ButtonStyle.success: 3> url=None disabled=False label='Réserver' emoji=None row=None>
Traceback (most recent call last):
  File "/home/runner/Bot-reservation-discord/.pythonlibs/lib/python3.10/site-packages/discord/ui/view.py", line 427, in _scheduled_task
    await item.callback(interaction)
  File "/home/runner/Bot-reservation-discord/main.py", line 67, in reserve_button
    await interaction.response.send('Veuillez sélectionner une salle.')
AttributeError: 'Button' object has no attribute 'response'
ERROR:discord.ui.view:Ignoring exception in view <TimeInputView timeout=180.0 children=1> for item <Button style=<ButtonStyle.success: 3> url=None disabled=False label='Réserver' emoji=None row=None>
Traceback (most recent call last):
  File "/home/runner/Bot-reservation-discord/.pythonlibs/lib/python3.10/site-packages/discord/ui/view.py", line 427, in _scheduled_task
    await item.callback(interaction)
  File "/home/runner/Bot-reservation-discord/main.py", line 67, in reserve_button
    await interaction.response.send('Veuillez sélectionner une salle.')
AttributeError: 'Button' object has no attribute 'response'

修复与功能实现方案

核心问题解析

  1. 交互响应方法错误:Discord.py中interaction.response没有send方法,正确的发送交互响应方法是send_message,这是导致AttributeError的直接原因。
  2. 流程逻辑缺失:原代码中用户没有途径选择房间,点击按钮时self.room始终为None,不符合“点击按钮显示房间选择菜单”的需求。

修改后的完整代码

import discord
from discord.ext import commands
from discord.ui import Button, View, Select
import gspread
from oauth2client.service_account import ServiceAccountCredentials
import logging


logging.basicConfig(level=logging.ERROR)

intents = discord.Intents.default()
intents.message_content = True
intents.members = True
bot = commands.Bot(command_prefix='!', intents=intents)


def get_gspread_client():
  scope = [
      "https://spreadsheets.google.com/feeds",
      "https://www.googleapis.com/auth/spreadsheets",
      "https://www.googleapis.com/auth/drive.file",
      "https://www.googleapis.com/auth/drive"
  ]
  creds = ServiceAccountCredentials.from_json_keyfile_name(
      "reservation-salles-brique-901c122a60ee.json", scope)
  return gspread.authorize(creds)


def get_room_names():
  client = get_gspread_client()
  spreadsheet = client.open('Réservation des salles')
  worksheet = spreadsheet.worksheet('Nom des salles')
  room_names = [
      item['Nom de la salle'] for item in worksheet.get_all_records()
  ]
  return room_names


class RoomSelect(Select):

  def __init__(self):
    room_names = get_room_names()
    options = [discord.SelectOption(label=room) for room in room_names]
    super().__init__(placeholder='Sélectionnez une salle...', options=options)

  async def callback(self, interaction: discord.Interaction):
    selected_room = self.values[0]
    # 此处可添加写入Google Sheets的逻辑
    await interaction.response.send_message(
        f'Réservation confirmée pour la salle : {selected_room}.'
    )
    self.view.stop()


class ReservationView(View):

  def __init__(self):
    super().__init__()

  @discord.ui.button(label="Réserver", style=discord.ButtonStyle.green)
  async def reserve_button(self, button: discord.ui.Button,
                           interaction: discord.Interaction):
    try:
      # 创建包含房间选择菜单的View
      select_view = View()
      select_view.add_item(RoomSelect())
      # 发送带选择菜单的交互响应
      await interaction.response.send_message(
          "Veuillez sélectionner la salle que vous souhaitez réserver :",
          view=select_view
      )
    except gspread.exceptions.APIError as e:
      logging.error(f"Erreur lors de l'interaction avec Google Sheets : {e}")
    except discord.errors.DiscordException as e:
      logging.error(f"Erreur lors de l'interaction avec Discord : {e}")


@bot.command()
async def reserver(ctx):
  view = ReservationView()
  await ctx.send(
      "Cliquez sur le bouton pour commencer la réservation :",
      view=view)


@bot.event
async def on_ready():
  print(f'Bot connecté comme {bot.user}')


bot.run('TOKEN')

关键改动说明

  1. 修正交互响应方法:将interaction.response.send()替换为interaction.response.send_message(),符合Discord.py的API规范。
  2. 重构View逻辑:点击“Réserver”按钮时,动态生成包含房间选择菜单的View并发送,实现“点击按钮显示房间选择菜单”的需求。
  3. 优化选择回调:在RoomSelect的回调中直接处理房间选择结果,可在此处扩展写入Google Sheets的业务逻辑。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.08 21:25:08