0

I want that my Discord jda bot reads the last message of an textchannel after starting.

So I call :

textChannel.getHistory().getMessageById(config.getLatestMessageId());

The MessageHistory class doesn't have an getLatestMessage method somehow. And for some reason textChannel.getHistory() is always empty and therefore always return null.

is there an other way to read messages (written before the bot was started).

Some aditional information: The textchannel is the correct textchannel. it is not empty, and I also tried writing new messages while the bot is active. But the messagehistory is always empty.

Also something I find weird: textchannel.gethistory().isempty() is true and textchannel.hasLastMessage is true as well.

Dude2345
  • 57
  • 8

1 Answers1

1

EDIT:

Do the following:

channel.getHistory().retrievePast(1).queue(messages -> {
    // messages (list) contains all received messages
    // Access them in here
    // Use for example messages.get(0) to get the received message
    // (messages is of type List)
});
// DON'T access the received messages outside here
// If you use queue the received messages WON'T be available directly after the call

PREVIOUS:

If I do the following on my bot it works:

channel.getHistory().retrievePast(1).queue(messages -> {
    if (messages.size() > 0) System.out.println(messages.get(0).getContentDisplay());
});

After the call succeeded and the lambda is executed, calling

channel.getHistory().getRetrievedHistory()

should return the received chat history


You can also execute the action directly and block the current thread until the message history was received by doing the following:

MessageHistory h = channel.getHistory();
h.retrievePast(1).complete();
List<Message> ml = h.getRetrievedHistory();
if (ml.size() > 0) System.out.println(ml.get(0).getContentDisplay());

but I don't recommand doing this, since it will block the current thread. Use the code in the first part of my answer instead, which won't block execution, and will fill the message history with data and once its ready it will call the lambda.

Notice that I'm passing in 1 as an argument for the call to 'retrievePast'. This will only receive the last message send inside the text channel. I guess you can't receive the entire text channel, since it would be to expensive to store all the sent data in the RAM or it would just take to long.

IntoVoid
  • 914
  • 4
  • 7
  • I copy pasted your code in an messagReceive listener and somehow still received an empty Message List. – Dude2345 Apr 09 '21 at 15:49
  • Which one did you copy? If it is the first one then you have to execute your other code inside of the lamda – IntoVoid Apr 09 '21 at 15:51
  • ah okay it was the 1st one – Dude2345 Apr 09 '21 at 15:51
  • 1
    @Dude2345 you should use the first one, but the message history will only be available once the history was received, meaning you will only be able to access the history inside the lambda body (where i did the system out) – IntoVoid Apr 09 '21 at 15:56
  • and it still outputs:" messages[]" – Dude2345 Apr 09 '21 at 15:57
  • what have i done wrong? tbh i dont know what lambda expression does – Dude2345 Apr 09 '21 at 15:59
  • 1
    When you use queue to send a request to the discord api, it will handle that request on ANOTHER thread. Meaning that System.out.println("messages" + messagesTest); will be called before the other thread receives a result. It will add all the received messages to your list as expected, but after your method already finished executing – IntoVoid Apr 09 '21 at 16:00
  • 1
    @Override public void onGuildMessageReceived(@NotNull GuildMessageReceivedEvent event) { super.onGuildMessageReceived(event); TextChannel textChannel = event.getChannel(); textChannel.getHistory().retrievePast(1).queue(messages -> { List messagesTest = new ArrayList<>(); messagesTest.addAll(textChannel.getHistory().getRetrievedHistory()); System.out.println("messages" + messagesTest); }); } – IntoVoid Apr 09 '21 at 16:02
  • ah okay. How do I retreive the messages after it received an result? – Dude2345 Apr 09 '21 at 16:03
  • If you use queue than just execute all of your code inside of the lamda – IntoVoid Apr 09 '21 at 16:03
  • @Dude2345 I edited my answer. Please do all of your message handling inside the lambda (the curly brackets) – IntoVoid Apr 09 '21 at 16:09
  • Yes i saw it . Sorry i wrote that before acutalising my page. It worked, thanks a lot ! – Dude2345 Apr 09 '21 at 16:11
  • Great. Please learn about how threading works ;) – IntoVoid Apr 09 '21 at 16:12
  • True, I didn't even now it would thread there. – Dude2345 Apr 09 '21 at 16:13
  • 1
    it does, in order to process your request without blocking the current thread. Because that would mean that the bot could only handle a single request at a time. If you use 'complete' instead of 'queue' it will block the current thread, but the result will be available directly after the call (it will block until the result is ready, but it will STILL do all the handling on another thread, since the entire connection to the discord server is running on another thread). – IntoVoid Apr 09 '21 at 16:16
  • 1
    That is also the reason, why you should call shutdown on the JDA instance when you close your bot, bacuse that will stop the running thread. In order to keep the connection to the discord servers open (because you don't want to reopen the connection for every single litte request), while also not blocking execution on the curren thread, the entire server / client connection needs to run on another thread. If you request something using queue it will list that request somewhere and once the other thread is ready to process another task it will process your task – IntoVoid Apr 09 '21 at 16:20
  • 1
    once it is done executing your task it will call the function you passed in when calling queue. So the code inside of the lamdas body will be called once the other thread receives a result from the discord server. Problem is, your method, from which you called queue will already be finished, since queue doesn't block execution. – IntoVoid Apr 09 '21 at 16:22
  • 1
    Or simplified: You call queue and pass in a function (lamda). The request will be stored inside a list or something. Once the thread, which is handling the server connection is ready, it will look for new requests inside that list. if there is one, it will execute that request (in your case receiving messages). The other thread will block until it receives a result. Once it has a result, it will call your provided lamda (function you passes in when calling queue). The advantage: The current thread won't block until a result is ready. – IntoVoid Apr 09 '21 at 16:29
  • nice. ok. glad to hear that – IntoVoid Apr 09 '21 at 16:32