[精讚] [會員登入]
832

【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

你可能感興趣的文章

【Raspberry Pi/樹梅派】(gcc 10) 如何安裝 gcc & g++ 需要的時間非常久,不愧是gcc的編譯

【Wildfly/jBoss】[Linux](Connection Datasource)如何與MySQL資料庫建立連線 網頁瀏覽器和資料庫的關係密不可分,而通常會將兩者分開架設在不同的伺服器上面來提供服務,這時要如何進行連線呢?

【C++】如何解決TLE,換句話說便是加速cin, cout的執行速度 [ZERO JUDGE](UVa) a159: 11743 - Credit Check 題目練習和副程式練習

【C++】使用struct array和一維int array模擬二維int array 主要是因為用sort去排序int array的二維陣列小編懶得研究,於是就研究了一種維持一維陣列但是有二維陣列效果的程式,小編就廢~~

【Wicket】[nonce]如何導入css以及javascript 如果只是用一般的 HTML link 或是 script 標籤來寫,會被 CSP 擋住,禁止加載資源,那我們除了關閉 CSP 以外還有沒有辦法來解決呢?

【Linux】[CentOS 8] How to update sudo instruction The last time I wanted to update the sudo command should be 2017, right? It's 2021 in a blink of an

我有話要說

>>

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

訪客留言

[無留言]

隨機好文

【手遊介紹】小品手遊─寶箱是我的!(SUMMONER'S GREED) 輕鬆無腦的塔防遊戲,殺時間本小編推薦的遊戲之一

【分享、整合串】什麼?!高捷少女竟然有二創小說!! 由時零宇宙大大在巴哈上面連載的二創高捷少女小說,就讓我們來看看,究竟在時零大大的巧手下,高捷少女們會擦出什麼樣的火花吧!

高捷少女:布拉格體驗㊤ 「可……可以去歐洲玩?而且還有人出錢?太棒囉!」婕兒忍不住歡呼起來,把扳手拋呀拋的,旁邊的客人紛紛轉過來看。「好了啦!」耐耐忍不住害羞起來,輕輕敲了一下婕兒的頭

高捷少女:小穹與果仁巧克力㊤ 阿敏突然輕笑一聲,從櫃臺拿來一個塑膠餐盒,打開給大家看。「這是小穹烤的餅乾,妳們吃吃看就知道她為什麼不想講了。」小穹變得緊張起來。「阿敏,妳怎麼還留著呀?」艾米莉亞、婕兒與耐耐各自拿了一塊,把夾著奶油

高捷少女:耐耐的新年驚喜(終) 他的話說到一半,便被一陣響亮的哭聲打住了,是從產房中的傳來的。聽起來就像嬰兒的哭聲。 婕兒、小穹跟艾米也被哭聲吵醒,婕兒揉揉眼睛,看向呆若木雞的耐耐父女。「剛剛的聲音,該不會是……」