分类: Discord 机器人开发

Discord 机器人开发#5实现按钮(Button)交互!

本文译自韩语原文。

目录8 项

大家好!我是 Mojangcam 😎

在上一篇 #4中,我们用 Slash Command 发送了 Embed 对吧?这次更进一步,给消息加上可以点击的按钮(Button)!一起来做一个点击按钮就会响应的、真正的"交互式机器人"吧。

完成之后,就可以实现下面这些功能:

  • 用 ✅ 确认 / ❌ 取消按钮让用户做选择
  • 🎫 创建工单、发放身份组之类的一键功能
  • 发送只有点击按钮的人才能看到的回复

📌 准备工作

  • Python 3.8 及以上
  • discord.py 2.x(按钮功能从 2.0 开始支持!)
  • 机器人 Token + 已把机器人邀请进服务器(参考第 1 篇!)
终端
pip install -U discord.py

如果版本较低,请务必更新。可以用 pip show discord.py 查看版本。

📌 第 1 步 - 按钮的核心:理解 View

在 discord.py 中,按钮不能单独使用,而是要装进一个叫 View 的容器里,和消息一起发送。

  • discord.ui.View → 装按钮、下拉菜单等组件的盒子 📦
  • discord.ui.button 装饰器 → 在 View 里创建按钮,并绑定点击时要执行的函数

先来看看结构!

Python
import discord

class MyView(discord.ui.View):
    @discord.ui.button(label="点我试试!", style=discord.ButtonStyle.primary)
    async def my_button(self, interaction: discord.Interaction, button: discord.ui.Button):
        await interaction.response.send_message("按钮被点击了!")

⚠️ 回调函数的参数顺序是 (self, interaction, button)。它和其他库(如 pycord)示例中的顺序正好相反,很容易搞混,请注意!

📌 第 2 步 - 了解按钮样式

style= 可以设置的按钮颜色共有 5 种。

样式 颜色 用途示例
ButtonStyle.primary 蓝色 主要操作
ButtonStyle.secondary 灰色 次要操作
ButtonStyle.success 绿色 确认/接受
ButtonStyle.danger 红色 删除/拒绝
ButtonStyle.link 链接型 跳转 URL(需要 url=,没有回调)

📌 第 3 步 - 制作确认/取消按钮

来做一个实战中最常用的确认/取消模式。

Python
class ConfirmView(discord.ui.View):
    def __init__(self):
        super().__init__(timeout=60)  # 60 秒后按钮失效

    @discord.ui.button(label="确认", style=discord.ButtonStyle.success)
    async def confirm(self, interaction: discord.Interaction, button: discord.ui.Button):
        await interaction.response.edit_message(content="✅ 已确认!", view=None)

    @discord.ui.button(label="取消", style=discord.ButtonStyle.danger)
    async def cancel(self, interaction: discord.Interaction, button: discord.ui.Button):
        await interaction.response.edit_message(content="❌ 已取消。", view=None)

要点整理 💡

  • timeout=60:60 秒后按钮就不再生效(默认值是 180 秒)
  • edit_message(..., view=None):点击按钮时修改原消息,同时移除按钮
  • interaction.response 必须在 3 秒内响应,而且只能响应 1 次。如果还要再发消息,请使用 interaction.followup.send()!

📌 第 4 步 - 完整代码(可直接复制)

这是和 Slash Command 结合后的完整版本。

Python
import discord
from discord.ext import commands

intents = discord.Intents.default()
bot = commands.Bot(command_prefix="/", intents=intents)

class ConfirmView(discord.ui.View):
    def __init__(self):
        super().__init__(timeout=60)

    @discord.ui.button(label="确认", style=discord.ButtonStyle.success)
    async def confirm(self, interaction: discord.Interaction, button: discord.ui.Button):
        await interaction.response.edit_message(content="✅ 已确认!", view=None)

    @discord.ui.button(label="取消", style=discord.ButtonStyle.danger)
    async def cancel(self, interaction: discord.Interaction, button: discord.ui.Button):
        await interaction.response.edit_message(content="❌ 已取消。", view=None)

@bot.event
async def on_ready():
    await bot.tree.sync()
    print(f"{bot.user} 机器人已准备就绪!")

@bot.tree.command(name="확인", description="发送确认/取消按钮")
async def confirm_command(interaction: discord.Interaction):
    await interaction.response.send_message("要继续吗?", view=ConfirmView())

bot.run("Token")

📌 查看结果

运行机器人,在 Discord 频道里输入 /확인(即"确认"),就会出现"要继续吗?"消息,以及绿色的确认按钮和红色的取消按钮!点击按钮后,消息会变成"✅ 已确认!",按钮也会消失。

📌 常见错误

1. 点击按钮后提示"交互失败"

回调没有在 3 秒内响应时就会出现这个错误。如果处理需要一些时间,请先调用 await interaction.response.defer()。

2. TypeError: ... missing 1 required positional argument

这是回调参数顺序的问题!discord.py 2.x 的顺序是 (self, interaction, button)。如果写成 (self, button, interaction) 就会报这个错。

3. 重启机器人后,之前消息里的按钮点不动了

View 默认只存在于内存中。要让它在重启后也能继续工作,需要创建指定了 timeout=None + custom_id 的 persistent view,并用 bot.add_view() 注册。(这部分会在以后的进阶篇里讲!)

📌 总结

今天我们用 discord.py 的 View 和按钮实现了点击交互。

  • 按钮要装进 View 里发送
  • 5 种样式(primary/secondary/success/danger/link)
  • 3 秒内响应,而且只能响应 1 次!

下一篇打算做下拉菜单(Select Menu),敬请期待 🙌

📚 Discord 机器人开发系列

  1. Slash Command 完全攻略
  2. 为 Slash Command 添加选项(Arguments)
  3. 在 Slash Command 中添加子命令
  4. 用 Slash Command 发送 Embed
  5. 实现按钮(Button)交互 ← 就是这篇!

连载 · 共 32 篇中的第 5 篇

Discord 机器人开发

  1. #1Discord 机器人开发 - Slash Command 完全攻略!
  2. #2为 Slash Command 添加选项(Arguments)!
  3. #3在 Slash Command 中添加子命令(Subcommand)!
  4. #4用 Slash Command 发送 Embed 嵌入消息!
  5. #5实现按钮(Button)交互!当前文章
  6. #6实现下拉菜单(Select Menu)!
  7. #7用模态框(Modal)接收用户输入(Python 示例)
  8. #8用嵌入消息(Embed)的图片和字段美化消息(Python 示例)
  9. #9接入 AI(Claude·ChatGPT API)!(Python 示例)
  10. #10支持多语言(i18n)!(Python 示例)
  11. #11用 Flask 制作网页仪表盘!(Python 示例)
  12. #12管理命令冷却时间(Cooldown)与权限(Permission)!(Python 示例)
  13. #13用身份组·频道自动化管理服务器!(Python 示例)
  14. #14保存数据!JSON vs SQLite(Python 示例)
  15. #15슬래시 명령어 그룹(Group)으로 명령어 정리하기! (파이썬 예제) (韩语)
  16. #16리마인더·알림 기능 만들기! 봇이 먼저 말 걸게 하기 (파이썬 예제) (韩语)
  17. #17RAG로 문서 기반 답변봇 만들기! 우리 서버 전용 FAQ 봇 (파이썬 예제) (韩语)
  18. #18투표(Poll) 기능 만들기! 다수결로 정하는 서버 규칙 (파이썬 예제) (韩语)
  19. #19Cog로 코드 쪼개기! 1000줄 봇도 안 더러워지는 구조 (파이썬 예제) (韩语)
  20. #20자동 환영 메시지·온보딩 만들기! 규칙 동의 버튼으로 자동 역할 부여 (파이썬 예제) (韩语)
  21. #21키워드 자동응답·금지어 필터 만들기! 경고 누적으로 자동 제재까지 (파이썬 예제) (韩语)
  22. #22슬래시 명령어 자동완성(Autocomplete) 만들기! 금지어를 골라서 추가·삭제 (파이썬 예제) (韩语)
  23. #23aiosqlite로 비동기 DB 제대로 설계하기! JSON 탈출 (파이썬 예제) (韩语)
  24. #24채널 난독화(Channel Obfuscation) 대응하기! 11/16부터 안 보이는 채널이 생겨요 (파이썬 예제) (韩语)
  25. #25봇이 죽지 않게! 에러 핸들링·로깅 체계 잡기 (파이썬 예제) (韩语)
  26. #26티켓(Ticket) 문의 시스템 만들기! 버튼 하나로 1:1 상담 채널 자동 생성 (파이썬 예제) (韩语)
  27. #27티켓 담당자 배정·우선순위 만들기! 스태프가 여러 명이어도 안 꼬이게 (파이썬 예제) (韩语)
  28. #28레벨·경험치(XP) 시스템 만들기! 채팅할수록 레벨업, 랭킹판까지 (파이썬 예제) (韩语)
  29. #29화폐·상점(Economy) 시스템 만들기! 코인 벌어서 아이템 사기 (파이썬 예제) (韩语)
  30. #30打造投票·问卷(Poll)机器人!原生投票 + 按钮实时统计(Python 示例)🗳️
  31. #32打造服务器日志·审核日志(Audit Log)频道!自动记录消息删除、编辑、成员进出和踢出(Python 示例)🕵️
  32. #33임시 음성방 확장, 파티방 만들기! 방장 위임·강퇴·초대 전용(비공개) 방 + 전용 채팅방 자동 생성 (파이썬 예제) 🎉 (韩语)
显示全部 32 篇收起

作者

Mojangcam

亲手写代码、跑服务器、解决卡住的报错,把一路学到的东西记录下来的开发与 IT 实战博客