[精讚] [會員登入]
891

【Discord bot】[botton]按鈕的使用、響應和關閉

Discord的botton通常都要和View配合使用。

分享此文連結 //n.sfs.tw/16017

分享連結 【Discord bot】[botton]按鈕的使用、響應和關閉@小編過路君子
(文章歡迎轉載,務必尊重版權註明連結來源)
2022-12-13 12:51:31 最後編修
2022-12-12 03:38:52 By 過路君子
 

哈囉大家好,這裡是正在回味舊新聞的小編過路君子

目前正在看「蕭明禮惡意阻擋救護車」和「賴俊吉惡意阻擋救護車」這兩事件當時的新聞。

 

 

上一篇文章我們提到了如何將 Discord 機器人從 1.7.3 更新成 2.0.1,沒看過的可以往這裡走:【Discord bot 2.0.1】如何將舊機器人升級至目前最新版本

在那篇文章裡面我們有提到如果在 on_ready() 函數裡面少了一些設置,可能會造成 Discord 機器人在響應按鈕上失敗:

(所有圖片點擊都可以放大、變高清)

 

而當時小編對於 discord.ui.View 和 discord.ui.button 的介紹僅僅只有如此。

所以,今天小編來詳細的說一下該如何使用 Discord button 這個新的功能。

 

那麼在開始之前,小編先簡單的提一下按鈕的響應。

Discord botton 使用的響應方式是用 callback(event),那至於要如何響應,有兩種實作的方式,分別是:

  1. event 搭配 function 來完成響應。
  2. 使用 class 搭配 event 來完成響應。

小編認為對於程式管理來說第二種方式比較好,使用第一種方式的話程式碼會散落在檔案各處,所以接下來都會以介紹第二種方式為主。

 

Discord.ui.button 宣告

Step1. 宣告class

那我們接下來所有使用到的 class 都在 discord 裡面,所以只要開頭有寫: import discord即可正常執行。

首先我們先來寫個簡單的 class,那這個我們自己寫的 class 必須要繼承 discord.ui.View 呦。

class aButton(discord.ui.View):
    def __init__(self):
        super().__init__()

 

Step2. 註冊按鈕

接下來,我們會直接在這個 class 內註冊一個按鈕:

class aButton(discord.ui.View):
    def __init__(self):
        super().__init__()

    @discord.ui.button(label="confirm", emoji='\u2705', style=discord.ButtonStyle.success)

 

其中 button 後面括號可以設定三種屬性,分別是:

  1. label: 按鈕上所顯示的文字。
  2. emoji: 按鈕上所顯示的表情符號。
  3. style: 按鈕的樣式,總共有五種可選:primary, secondary, success, danger, & link(註1);實際效果可參考下圖。

圖片來源:https://guide.pycord.dev/interactions/ui-components/buttons

 

Step3. 加上callback

講白話一點就是當我們的按鈕被使用者點擊的時候,我們的程式需要做些什麼事情。

那使用方式也非常簡單,直接寫在下方即可。

class aButton(discord.ui.View):
    def __init__(self):
        super().__init__()

    @discord.ui.button(label="confirm", emoji='\u2705', style=discord.ButtonStyle.success)
    async def buttonEvent(self, interaction, button):
        # code here...
        pass

 

其中,按鈕的函數會被傳入兩個參數,而小編在這邊就不細講了,但會將它們的型態和相關的 reference 放在下方,有興趣的人可以自行查閱。

 

Discord.ui.button 基本使用

發送幾顆按鈕出去

class aButton(discord.ui.View):
    def __init__(self):
        super().__init__()

    @discord.ui.button(label="confirm", emoji='\u2705', style=discord.ButtonStyle.success)
    async def buttonEvent(self, interaction, button):
        # code here... 
        pass

class file(default):
    @commands.command()
    @commands.check(Permission.developer)
    async def sendButton(self, ctx):
        view = aButton()
        await ctx.send(content="nothing~", view=view)

async def setup(bot):
    await bot.add_cog(file(bot))

當使用者使用機器人指令「sendButton」的時候,我們的機器人會回應一串文字和一個按鈕給該使用者。

如果要送兩顆或以上的按鈕,就只需要多打幾行 @discord.ui.button 即可,每個按鈕皆可以獨自設定,不一定要每一顆都一樣。

當然,這顆按鈕是沒有任何的功能,畢竟我們按鈕的函數還是只有放 pass 嘛!而接下來我們就會針對此區塊來修改。

 

修改發送的訊息內容

class aButton(discord.ui.View):
    def __init__(self):
        super().__init__()

    @discord.ui.button(label="confirm", emoji='\u2705', style=discord.ButtonStyle.success)
    async def buttonEvent(self, interaction, button):
        await interaction.response.edit_message(content="Hello world")

 

停用按鈕

class aButton(discord.ui.View):
    def __init__(self):
        super().__init__()

    @discord.ui.button(label="confirm", emoji='\u2705', style=discord.ButtonStyle.success)
    async def buttonEvent(self, interaction, button):
        button.disabled = True
        await interaction.response.edit_message(content="Hello world", view=button.view)

這邊比較要注意的一點就是:如果有對按鈕(視圖View)做任何的變更都要傳回客戶端(上方程式最後一行),客戶端才會更新。

所以很多人遇上了明明已經將 disabled 設為 True,但是發現不管怎麼按按鈕,程式碼都沒有生效,其實不是程式碼沒有生效,而是生效了你沒有告知客戶端。

 

移除按鈕

有時候我們需要使用者按下按鈕,但我們只需要顯示對應的純文字訊息,此後按鈕便再無用處。

此時,雖然我們可以直接停用按鈕,但是如果我們每按下一個按鈕便會回傳兩個按鈕,例如:請使用者選擇一個是非題,然後產生兩個按鈕給使用者答題。如果僅僅只是將按鈕停用,很快便會造成版面的紊亂。

所以,這時候我們就必須將舊的按鈕移除,以免造成版面上掛滿數十個被停用的按鈕。

class aButton(discord.ui.View):
    def __init__(self):
        super().__init__()

    @discord.ui.button(label="confirm", emoji='\u2705', style=discord.ButtonStyle.success)
    async def buttonEvent(self, interaction, button):
        button.disabled = True
        button.view.remove_item(button)
        await interaction.response.edit_message(content="Hello world", view=button.view)

 

不響應的按鈕

當我們想要一個啞彈,也就是按下但客戶端不會發生任何事情的按鈕,例如:向其他伺服器發送一段訊息,但我不想讓客戶端發現我偷偷送了訊息出去。

我們的直覺就是直接在函數內寫入 pass 嘛!但是當我們真正按下按鈕的時候卻顯示這樣:

正確的方式是使用 defer() 來告訴客戶端此按鈕並不會回傳任何值會對其做響應。

class aButton(discord.ui.View):
    def __init__(self):
        super().__init__()

    @discord.ui.button(label="confirm", emoji='\u2705', style=discord.ButtonStyle.success)
    async def buttonEvent(self, interaction, button):
        await interaction.response.defer()

 

停止監聽

只要一顆按鈕被創建出來,那我們的 Discord機器人便會持續監聽此按鈕,直至 timeout(預設為 3 分鐘)。

在一般情況之下,我們不主動停止監聽按鈕問題不大(畢竟等到它 timeout 就好了嘛),但是如果我們有手動將 timeout 取消,就會造成伺服器資源被永久占用。

除非將機器人重新啟動,否則被使用完的按鈕仍舊會繼續占用伺服器資源,無法釋出給下一個人使用。

class aButton(discord.ui.View):
    def __init__(self):
        super().__init__()

    @discord.ui.button(label="confirm", emoji='\u2705', style=discord.ButtonStyle.success)
    async def buttonEvent(self, interaction, button):
        button.view.stop()
        await interaction.response.edit_message(content="Hello world", view=view)

使用這種方式要非常注意,如果同時有兩個及以上的按鈕,會一同被停止監聽

 

 

 

後記

上文小編有提到按鈕的樣式總共有五個,但是明明就有人寫了那五個 style 以外的呀!

那其實只是該名稱的別名,其效果是一樣的,小編在此當成附錄羅列出給各位。

樣式名稱 別名
primary blurple
secondary grey, gray
success green
danger red
link url

至於誰是樣式名稱、誰是別名,不是小編自己覺得,而是根據官方的Reference所整理出來的。

END

你可能感興趣的文章

【Wicket】[Cookie]如何讀取和設定客戶端的Cookie 對於某些參數需要給予使用者,我們可以使用 Cookie 來讓客戶端記著,之後再跟伺服器裡的比對來達到驗證的目的

【JAVA】[java.lang.Class]如何不透過new來實體化class 在某些極端狀態下,我們沒有辦法直接將實體化後的 Object 傳入函數內,只能採用傳入 Class 在實體化成物件這種極端的方式來進行

【JDA/discord bot】如何獲得訊息中的圖片和影片並儲存或轉傳 如何將訊息中的圖片或影片之類的多媒體提取出來之後,再進行相關的處理

【Firefox \ Maven】[Headless](Linux) 如何使用Maven打包並驅動Firefox 有時候我們需要取得渲染後的網頁,當然是直接呼叫瀏覽器出來用啦

【Discord bot】(ERROR)await self.bot.wait_for() 大坑 今天真的是採到大坑,只找到解決方法,具體原因不明

【Java】[debug]多維泛型的大坑 incompatible types error

我有話要說

>>

限制:留言最高字數1000字。 限制:未登入訪客,每則留言間隔需超過10分鐘,每日最多5則留言。

訪客留言

[無留言]

隨機好文

[活動] 2017年4/1雲空幻想愚人節活動彩蛋&攻略 (紀念性質) 雲空幻想2017年的愚人節活動介紹同時也是本小編的第一篇網路文章(*^ω^)♪

高捷少女:地下城的探險少女② 「等我一下喔,我好像有帶去漬的清潔噴霧。」婕兒翻翻飛揚,拿出噴霧劑給小穹,小穹趕緊對著汙漬噴了噴,紅茶漬果然乾淨了許多。「婕兒,謝謝妳。來,還妳。」小穹感謝地把噴霧還給她,卻發現婕兒盯著打開的飛揚,一

高捷少女:購票大作戰(終) 完了。 這下真的完了! 艾米腦內所有的思考中樞,同時發出了淒厲的吶喊。完蛋啦!這下真的被揭穿了啦!! 「那……那是因為……」艾米結結巴巴的說:「因為……

高捷少女:美麗島的守護者④ 光之穹頂的某處垃圾桶底,一個四方形的機器持續發出聲音,機器的儀表板上顯示著「1:25:10」的字樣,外表被一層鞭炮所掩蓋。儀表板的數字每秒不斷減少,細微的嗶嗶聲也隨著數字的改變發出,但在熙來攘往的美麗

高捷少女:美麗島的守護者⑥ 一陣貓叫傳到小雅耳中,原本要朝小雅撲過去的北風轉了個圈,從半空中落地,牠的表情宛如五雷轟頂。這聲音……難道是……