[精讚] [會員登入]
262

【JDA/discord bot】刪除事件或slash(斜槓)指令的reply訊息

如何正確的等待 Async 的結束,在進行接下來的刪除訊息動作

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

分享連結 【JDA/discord bot】刪除事件或slash(斜槓)指令的reply訊息@小編過路君子
(文章歡迎轉載,務必尊重版權註明連結來源)
2024-02-15 16:33:03 最後編修
2024-02-15 15:03:48 By 過路君子
 

哈囉大家好,這裡是在回顧自己舊文章的小編過路君子

小編正在回顧自己以前寫的 Wicket 系列文章,恩,沒錯,仍是 Java 這個程式語言

 

 

 

小編所使用的 JDA 版本是:5.0.0-beta.20

小編之前一直都是使用 discord.py 的 command_prefix 來實現命令的,而小編也比較喜歡這個方式,但似乎 JDA 並未提供相關的設置可以使用,小編目前也在慎重的考慮是否手動實現相關的功能,目前有考慮使用 Map 來達成快速索引以重現相關的功能。

但有一點是可以肯定的,就是那個 reply 是真的很醜,還不如直接 sendMessage() 來的好看。

 

所以小編就想在 reply 之後刪除剛剛 reply 的訊息並重新傳送一段新的訊息到聊天室內。

但這個時候就又遇到新的問題了,就是如果直接去呼叫 getIterableHistory() 的話,有可能會取得使用者的命令訊息而非機器人的 reply 訊息。

為了解決這個問題,我們勢必得等到整個 reply 或 sendMessage 的 Async 完成之後,再去取得頻道的訊息才行。

 

那在這邊小編提供兩種情況下的使用。

分別是使用 sendMessage() 和事件的響應,例如 onSlashCommandInteraction 等等事件,順手再各提供一種 onSuccess() 的變體寫法。

刪除sendMessage的訊息

使用 queue()

import java.util.List;
import net.dv8tion.jda.api.JDA;
import java.util.stream.Collectors;
import net.dv8tion.jda.api.entities.Message;
import net.dv8tion.jda.api.entities.channel.concrete.TextChannel;

public void deleteSentMessage(JDA bot)
{
    // Get the channel
    long channelID = 9000000000L;
    TextChannel channel = bot.getTextChannelById(channelID);

    // Callback values class type is:
    // net.dv8tion.jda.internal.interactions.InteractionHookImpl
    channel.sendMessage("will delete").queue(interactionHookImpl ->
    {
        try
        {
            // Try to get the last message on that channel.
            List<Message> message = channel.getIterableHistory().takeAsync(1).thenApply(list -> list.stream().collect(Collectors.toList())).get();
         
            // If successful, get the corresponding message.
            if(message.isEmpty()) return;
            Message last = message.get(0);
         
            // Delete it.
            last.delete().queue();
        }
        catch(Exception error) {System.out.println(error);}
    });
}

使用 onSuccess()

import java.util.List;
import net.dv8tion.jda.api.JDA;
import java.util.stream.Collectors;
import net.dv8tion.jda.api.entities.Message;
import net.dv8tion.jda.api.entities.channel.concrete.TextChannel;

public void deleteSentMessage(JDA bot)
{
    // Get the channel
    long channelID = 9000000000L;
    TextChannel channel = bot.getTextChannelById(channelID);

    // Callback values class type is:
    // net.dv8tion.jda.internal.interactions.InteractionHookImpl
    channel.sendMessage("will delete").onSuccess(interactionHookImpl ->
    {
        try
        {
            // Try to get the last message on that channel.
            List<Message> message = channel.getIterableHistory().takeAsync(1).thenApply(list -> list.stream().collect(Collectors.toList())).get();
         
            // If successful, get the corresponding message.
            if(message.isEmpty()) return;
            Message last = message.get(0);
         
            // Delete it.
            last.delete().queue();
        }
        catch(Exception error) {System.out.println(error);}
    }).queue();
}

大同小異,就是呼叫函數的時機不同而已,整體結構都一樣,依照個人喜好使用即可。

 

刪除由事件回應(event reply)的訊息

小編在此同樣提供兩種寫法,以供各位自行取用。

由於 JDA 內的事件眾多,而每個事件之間又有些微的差異,這邊小編僅以 onSlashCommandInteraction 這個事件作為範例。

更詳細的訊息可以參考 javadoc 的 ListenerAdapter 說明頁面

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

使用 queue()

import java.util.stream.Collectors;
import net.dv8tion.jda.api.entities.Message;
import net.dv8tion.jda.api.hooks.ListenerAdapter;
import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent;

public class DiscordEvents extends ListenerAdapter
{
    @Override
    public void onSlashCommandInteraction(SlashCommandInteractionEvent event)
    {
        // callback values class type is:
        // net.dv8tion.jda.internal.interactions.InteractionHookImpl
        event.reply("Test!").queue(interactionHookImpl ->
        {
            try
            {
                // Try to get the message that just replied
                Message message = event.getChannel().getIterableHistory().takeAsync(1).thenApply(list -> list.stream().collect(Collectors.toList())).get().get(0);

                // If the user is not the bot itself,
                // the delete command is not executed.
                if(last.getAuthor().getIdLong() != event.getJDA().getSelfUser().getIdLong()) return;

                // Delete it.
                last.delete().queue();
            }
            catch(Exception error) {System.out.println(error);}
        });
    }
}

使用 onSuccess()

import java.util.stream.Collectors;
import net.dv8tion.jda.api.entities.Message;
import net.dv8tion.jda.api.hooks.ListenerAdapter;
import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent;

public class DiscordEvents extends ListenerAdapter
{
    @Override
    public void onSlashCommandInteraction(SlashCommandInteractionEvent event)
    {
        // callback values class type is:
        // net.dv8tion.jda.internal.interactions.InteractionHookImpl
        event.reply("Test!").onSuccess(interactionHookImpl ->
        {
            try
            {
                // Try to get the message that just replied
                Message message = event.getChannel().getIterableHistory().takeAsync(1).thenApply(list -> list.stream().collect(Collectors.toList())).get().get(0);

                // If the user is not the bot itself,
                // the delete command is not executed.
                if(last.getAuthor().getIdLong() != event.getJDA().getSelfUser().getIdLong()) return;

                // Delete it.
                last.delete().queue();
            }
            catch(Exception error) {System.out.println(error);}
        }).queue();
    }
}

 

 

 

後記

細心的人應該已經發現了,小編提供的程式碼之中都有些微的差異,而非完全相同,是小編故意的。

不同的寫法因應不同的場景,依照個人需求斟酌使用吧。

END

你可能感興趣的文章

【NodeMCU / ESP8266】[Arduino]測量溫溼度並上傳至ThinkSpeak 使用簡單的溫度計來測量溫濕度並上傳至第三方網站,這樣他人只要有瀏覽器就能看到我們的數據了

【Maven】如何創建一個簡單可部屬的WAR檔 滿重要的一個大功能,在使用JAVA網頁伺服器的時候一定會需要這個WAR檔來進行部屬

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

【無料版模】﹝CSS&HTML﹞製作epub電子書版模免費下載&附使用教學 一個專門用來製作epub的簡單CSS檔案,基本上已經可以做出一本還不錯的電子書,讓妳的電子書不在只有預設的字體、樣式

【ThinkSpeak】一個IoT數據分析(IoT analytics)及呈現的網站 世界上有著各式各樣的需求,因而誕生出了各式各樣的網站,絕對不是沒有人提供,而是你不知道哪裡有這東西

【C++】使用SFML創建新視窗和新增圖標(ICON)並隱藏DOS 筆記,怕自己以後忘記怎麼創建並開啓一個新視窗

我有話要說

>>

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

訪客留言

[無留言]

隨機好文

【開箱】高捷少女collection總集篇1 由希萌創意寄來的大包裹!裡面究竟有什麼呢?小編就帶大家來看看!

高捷少女:小穹與果仁巧克力㊦ 「如果妳跟一個女生同班三年,看過她午休流口水跟狼吞虎嚥地吃午餐,就算變成高捷代言人,也很難把她當女神的啦!」她說,小穹氣得搶走她義大利麵裡的蝦子,其他人笑得花枝招展。

高捷少女:地下城的探險少女① 婕兒心中一奇,便走上前看著仔細。那塊凹進去的地方中心大約三公分厚,越往邊緣就越淺,圓型直徑十五公分。婕兒拿出銅盤對比一下,發現兩者大小竟然一致,銅盤似乎能夠完整的嵌進去。     婕兒看著凹槽,心中

高捷少女:地下城的探險少女③ 過了十分鐘後,前方的天花板滴下一滴水珠,發出「噠」一聲響亮地落在石地上,讓大家嚇一跳。     「什麼嘛,只是水珠而已。」艾米撫著胸口噓了一聲。     忽然間,耐耐的臉色發白起來。「各位,你們看

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