B4J Question [JDA] Retrieve Archived Public Thread Channels?

Magma

Expert
Licensed User
Longtime User
Today found time, to play with JDA Discord API Library wrapper created by @DonManfred

I have to say with simple words, that is perfect!


I ve managed to show all channels, threads i have at my discord server... with this code:
B4X:
Sub ListAllChannelsAndThreads(chan As MessageChannel)
    Dim guilds As List = jda.Guilds

    For Each gw As Guild In guilds
        SendMessage(chan,$"Guild: ${gw.Name} (ID: ${gw.Id})"$)
        
'        ' All guild channels
        Dim chans As List = gw.GuildChannels
        For Each ch As GuildChannel In chans
            SendMessage(chan,$"  Channel: ${ch.name} [${ch.ID}] Type: ${ch.Type}"$)
        Next
        
        ' All active threads at guild
        Dim threads As List = gw.ThreadChannels  ' List of ThreadChannelwrapper
        For Each th As ThreadChannel In threads
            SendMessage(chan,$"  Thread: ${th.Name} [${th.ID}] Parent: ${th.ParentChannel}"$)
        Next
    Next
End Sub

But as I am saying at forum thread title can;t Retrieve Archived Public Thread Channels..

Anyone can do that ?

My wish... is take all my messages (or from specific user, or from all) and save them in sqlite database. I have answers that i wanted to use in a huge FAQ. Also this can help me create an AI Chat bot for my webpages.
 
Solution
BTW: You need to call
B4X:
retrieveArchivedPublicThreadChannels()
on the Textchannel followed by
B4X:
complete()
on the result. You then get the List of archived Threadchannels in the use Textchannel.

I now added retrieveArchivedPrivateJoinedThreadChannels, retrieveArchivedPrivateThreadChannels and retrieveArchivedPublicThreadChannels in the Textchannelobject for the next Libversion.
But i still have to do some additions because of deprecated methods in V6....

In the meantime you can try it with javaobject

DonManfred

Expert
Licensed User
Longtime User
I can´t remember seeing any such method.

You can check the JDA-Docs if you find such a method. If it is there i can help adding it to the wrapper.

The only i know is that you can use jda_onThreadHidden event to get informed when a thread is archived and just remember that.
 
Upvote 0

Magma

Expert
Licensed User
Longtime User
I can´t remember seeing any such method.

You can check the JDA-Docs if you find such a method. If it is there i can help adding it to the wrapper.

The only i know is that you can use jda_onThreadHidden event to get informed when a thread is archived and just remember that.
Hi there ...


Searching JDA docs found:
retrieveArchivedPublicThreadChannels
retrieveArchivedPrivateThreadChannels
retrieveArchivedPrivateJoinedThreadChannels
retrievePast for messages
*history* for messages

As I understand those are commands that may be require some extra events...

Can I somehow use them with javaobject on your lib wrapper ?

Thanks in advance
 
Upvote 0

DonManfred

Expert
Licensed User
Longtime User
Hi there ...
I can´t see how or where i do get a Threadcontainer from.

I can´t see any missing events for them too. What missing events you are talking about?

if you use V6 of the jars you probably can use javaobject, yes.
But note that for the V6-Jars some methods are deprecated and the lib as it stands actually are probably not compatible with these jars.
The V6 of JDA was released TWO days ago.
 
Upvote 0

Magma

Expert
Licensed User
Longtime User
I can´t see how or where i do get a Threadcontainer from.

I can´t see any missing events for them too. What missing events you are talking about?

if you use V6 of the jars you probably can use javaobject, yes.
But note that for the V6-Jars some methods are deprecated and the lib as it stands actually are probably not compatible with these jars.
The V6 of JDA was released TWO days ago.
The method retrieveArchivedPublicThreadChannels was added to JDA starting with version 5.0.0-xxx. This method (and friends for private thread channels) is part of the JDA 5.x API for TextChannel and ForumChannel entities and is not available in JDA 4.x or earlier.
At least this found when searched at Google.

At real don't know if need any extra events...

I am still using V5 beta you ve suggested in one old thread and works perfect with some I ve tried:
jda_onMessageReceived(event As MessageReceivedEvent) ' here I can read now/live messages...
B4X:
 ' here... welcome new members here...
Sub JDA_onGuildMemberJoin(ev As Object)
    Dim event As GuildMemberJoinEvent=ev
    Log($"JDA_onGuildMemberJoin(${event})"$)
    Log($"GuildMemberJoin.Member ${event.Member}"$)
    Log($"GuildMemberJoin.User ${event.User}"$)

Created also this - not know if it is 100% right - but i works:
B4X:
Sub SendMessage(channelJO As MessageChannel, content As String)
    Try

        channelJO.sendMessageFormat(content,Null)

    Catch
        Log("Error sending message: " & LastException.Message)
    End Try
End Sub


sharing how listing all current active channels:
B4X:
Sub ListAllChannelsAndThreads(chan As MessageChannel)
    Dim guilds As List = jda.Guilds

    For Each gw As Guild In guilds
        SendMessage(chan,$"Guild: ${gw.Name} (ID: ${gw.Id})"$)
       
'        ' Όλα τα κανάλια στο guild
        Dim chans As List = gw.GuildChannels
        For Each ch As GuildChannel In chans
            SendMessage(chan,$"  Channel: ${ch.name} [${ch.ID}] Type: ${ch.Type}"$)
        Next
       
        ' Όλα τα active threads στο guild
        Dim threads As List = gw.ThreadChannels  ' List of ThreadChannelwrapper
        For Each th As ThreadChannel In threads
            SendMessage(chan,$"  Thread: ${th.Name} [${th.ID}] Parent: ${th.ParentChannel}"$)
        Next
    Next
End Sub
'

At the last part of code... i want also include old/archieved channels... and then loop at all messages to add them in a database... So no need again to search archieved...
I hope that those messages will have a link (id or something will help me at future)..
When i will save them all in a db...

I will have an extra command for my bot lets say: !askbot "question" ---> that will query my db and return link/tag/id to have the feature the member, to see an old discuss....
 
Upvote 0

DonManfred

Expert
Licensed User
Longtime User
and friends for private thread channels
don´t expect to get private threadchannels methods as they are only available for the creator and members added by the creator. Not for all

But i´ll have a look at
for TextChannel and ForumChannel
i´ll recheck these if i can "reach" the missing methods from here.
 
Upvote 0

Magma

Expert
Licensed User
Longtime User
don´t expect to get private threadchannels methods as they are only available for the creator and members added by the creator. Not for all

But i´ll have a look at

i´ll recheck these if i can "reach" the missing methods from here.
B4X:
Sub ListAllChannelsAndThreads(chan As MessageChannel)
    ' Παίρνουμε μόνο το guild από το οποίο ήρθε η εντολή
    Dim currentGuild As Guild
   
       Dim joChannel As JavaObject = chan
    Try
        currentGuild = joChannel.RunMethod("getGuild", Null)
    Catch
        SendMessage(chan, "This command can only be used in a server channel.")
        Return
    End Try
   
    SendMessage(chan,$"Guild: ${currentGuild.Name} (ID: ${currentGuild.Id})"$)
   
       Dim chans As List = currentGuild.GuildChannels
    For Each ch As GuildChannel In chans
        SendMessage(chan,$"  Channel: ${ch.name} [${ch.ID}] Type: ${ch.Type}"$)
       
        ' Convert to JavaObject to check type properly
        Dim joChannelCheck As JavaObject = ch
        Dim channelType As JavaObject = joChannelCheck.RunMethod("getType", Null)
        Dim typeName As String = channelType.RunMethod("name", Null)
       
        ' Check if it's a TextChannel for archived threads
        If typeName = "GUILD_TEXT" Then
            RetrieveArchivedThreadsForTextChannel(chan, ch)
        End If
       
        ' Check if it's a ForumChannel for archived forum threads
        If typeName = "GUILD_FORUM" Then
            RetrieveArchivedThreadsForForumChannel(chan, ch)
        End If
    Next
   
    'active threads
    Dim threads As List = currentGuild.ThreadChannels
    For Each th As ThreadChannel In threads
        SendMessage(chan,$"  Active Thread: ${th.Name} [${th.ID}] Parent: ${th.ParentChannel}"$)
    Next
End Sub
Sub RetrieveArchivedThreadsForTextChannel(chan As MessageChannel, textCh As GuildChannel)
    Try
        Dim joChannel As JavaObject = textCh
       
        ' Public archived threads
        Try
            Dim publicAction As JavaObject = joChannel.RunMethod("retrieveArchivedPublicThreadChannels", Null)
            Dim publicResult As JavaObject = publicAction.RunMethod("complete", Null)
           
            ' Εναλλακτικά, δοκίμασε με forEach
            Dim joConsumer As JavaObject
            joConsumer.InitializeNewInstance("java.util.function.Consumer", Array(Me, "ProcessArchivedThread"))
            publicResult.RunMethod("forEach", Array(joConsumer))
           
        Catch
            Log("No permission for public archived threads: " & LastException.Message)
        End Try
       
        ' Private archived threads (needs special permission)
        Try
            Dim privateAction As JavaObject = joChannel.RunMethod("retrieveArchivedPrivateThreadChannels", Null)
            Dim privateResult As JavaObject = privateAction.RunMethod("complete", Null)
           
            Dim iterator As JavaObject = privateResult.RunMethod("iterator", Null)
            Do While iterator.RunMethod("hasNext", Null)
                Dim archThread As JavaObject = iterator.RunMethod("next", Null)
                Dim threadName As String = archThread.RunMethod("getName", Null)
                Dim threadId As String = archThread.RunMethod("getId", Null)
                SendMessage(chan, $"    Archived Private Thread: ${threadName} [${threadId}]"$)
            Loop
           
        Catch
            Log("No permission for private archived threads or none exist")
        End Try
       
    Catch
        Log("Error retrieving archived threads: " & LastException.Message)
    End Try
End Sub


Sub RetrieveArchivedThreadsForForumChannel(chan As MessageChannel, forumCh As GuildChannel)
    Try
        ' Convert to JavaObject to access raw JDA methods
        Dim joChannel As JavaObject = forumCh
       
        ' Retrieve archived public threads for forum
        Dim archivedAction As JavaObject = joChannel.RunMethod("retrieveArchivedPublicThreadChannels", Null)
        Dim archivedResult As JavaObject = archivedAction.RunMethod("complete", Null)
       
        ' Get the list from PagedIterable using iterator
        Dim archivedList As List
        archivedList.Initialize
       
        Dim iterator As JavaObject = archivedResult.RunMethod("iterator", Null)
        Do While iterator.RunMethod("hasNext", Null)
            Dim archThread As JavaObject = iterator.RunMethod("next", Null)
            archivedList.Add(archThread)
        Loop
       
        For Each archThread As JavaObject In archivedList
            Dim threadName As String = archThread.RunMethod("getName", Null)
            Dim threadId As String = archThread.RunMethod("getId", Null)
            SendMessage(chan, $"    Archived Forum Thread: ${threadName} [${threadId}]"$)
        Next
       
    Catch
        Log("Error retrieving archived threads for ForumChannel: " & LastException.Message)
    End Try
End Sub


I ve done this with perplexity AI (hope helps you) .. not getting error... but still get ActiveThreads and not archieved :-( ...ofcourse as you said no the private (not a problem)
but public archieved not got it...
 
Upvote 0

DonManfred

Expert
Licensed User
Longtime User
. i want also include old/archieved channels... and then loop at all messages to add them in a database..
Please note that you do not get any messages from archived threads. At least i guess so.
As the thread is archived you´ll have to reopen it. You need to get the messages while the thread is open.

You can get every new message when it is posted in messagereceived event (just in time). No need to wait for the thread being archived...
 
Upvote 0

Magma

Expert
Licensed User
Longtime User
Please note that you do not get any messages from archived threads. At least i guess so.
As the thread is archived you´ll have to reopen it. You need to get the messages while the thread is open.

You can get every new message when it is posted in messagereceived event (just in time). No need to wait for the thread being archived...
Yes I ve got that... the problem is not the "now" and the "future" coming messages... are the old... :-( too many... and need them
 
Upvote 0

DonManfred

Expert
Licensed User
Longtime User
BTW: You need to call
B4X:
retrieveArchivedPublicThreadChannels()
on the Textchannel followed by
B4X:
complete()
on the result. You then get the List of archived Threadchannels in the use Textchannel.

I now added retrieveArchivedPrivateJoinedThreadChannels, retrieveArchivedPrivateThreadChannels and retrieveArchivedPublicThreadChannels in the Textchannelobject for the next Libversion.
But i still have to do some additions because of deprecated methods in V6....

In the meantime you can try it with javaobject
 
Upvote 0
Solution

Magma

Expert
Licensed User
Longtime User
BTW: You need to call
B4X:
retrieveArchivedPublicThreadChannels()
on the Textchannel followed by
B4X:
complete()
on the result. You then get the List of archived Threadchannels in the use Textchannel.

I now added retrieveArchivedPrivateJoinedThreadChannels, retrieveArchivedPrivateThreadChannels and retrieveArchivedPublicThreadChannels in the Textchannelobject for the next Libversion.
But i still have to do some additions because of deprecated methods in V6....

In the meantime you can try it with javaobject
ok is it possible to give me the part of code / including the "complete" ?
 
Upvote 0

DonManfred

Expert
Licensed User
Longtime User
ok is it possible to give me the part of code / including the "complete" ?
I can only give the java-part but yes, here

B4X:
    public List<ThreadChannel> retrieveArchivedPrivateJoinedThreadChannels() {
        return getObject().retrieveArchivedPrivateJoinedThreadChannels().complete();
    }
    public List<ThreadChannel> retrieveArchivedPrivateThreadChannels() {
        return getObject().retrieveArchivedPrivateThreadChannels().complete();
    }
    public List<ThreadChannel> retrieveArchivedPublicThreadChannels() {
        return getObject().retrieveArchivedPublicThreadChannels().complete();
    }
 
Upvote 0

Magma

Expert
Licensed User
Longtime User
ΟΚ ...

here where am I - now! - this code works (but stops at first 100 from a channel have more):

I can read all archieved threads ! - I can read old hundred archieved messages too from channels...
B4X:
Sub ListAllChannelsAndThreadsAsString(guild1 As Object) As ResumableSub
    Dim output As String = ""
    Dim joJDA As JavaObject = jda
    File.OpenOutput(File.DirApp,"allmsg.txt",False)

    ' 1. Πάρε το Guild αντικείμενο
    Dim guildObj As Guild = guild1'joJDA.RunMethod("getGuildById", Array(guildId))
    'If guildObj = Null Then Return $"Guild with ID ${guildId} not found."$
    
    Log("X1")

    ' 2. Λίστα όλων των καναλιών του guild
    Dim channelsList As List = guildObj.GuildChannels
    
    Log("X2")
    
    For Each gc As Object In channelsList
        Dim joGC As JavaObject = gc
        Dim chanType As JavaObject= joGC.RunMethod("getType", Null)
        Dim chantype2 As String = chanType.RunMethod("name", Null)
        Dim chanName As String = joGC.RunMethod("getName", Null)
        Dim chanId   As String = joGC.RunMethod("getId",   Null)
        output = output & $"Channel: ${chanName} [${chanId}] Type: ${chantype2}"$ & CRLF


        'trigger them all!
        Log("X4")
        ' 4. Archived public threads (εφόσον υποστηρίζεται)
        Try
            Dim pubThreadss As JavaObject= joGC.RunMethod("retrieveArchivedPublicThreadChannels", Null)
            Dim pubThreads As List=pubThreadss.RunMethod("complete", Null)
            For Each t As Object In pubThreads
                Dim joT As JavaObject = t
                Dim tName As String = joT.RunMethod("getName", Null)
                Dim tId   As String = joT.RunMethod("getId",   Null)
                output = output & $"  Archived Public Thread: ${tName} [${tId}]"$ & CRLF
            Next
        Catch
            ' skip if unsupported or no permission
        End Try

        ' 5. Archived private threads
        Log("X5")
        Try
            Dim privThreadss As JavaObject = joGC.RunMethod("retrieveArchivedPrivateThreadChannels", Null)
            Dim privThreads As List = privThreadss.RunMethod("complete", Null)
            For Each t As Object In privThreads
                Dim joT As JavaObject = t
                Dim tName As String = joT.RunMethod("getName", Null)
                Dim tId   As String = joT.RunMethod("getId",   Null)
                output = output & $"  Archived Private Thread: ${tName} [${tId}]"$ & CRLF
            Next
        Catch
        End Try

        ' 6. Archived private-joined threads
        Log("X6")
        Try
            Dim joinedThreadss As JavaObject = joGC.RunMethod("retrieveArchivedPrivateJoinedThreadChannels", Null)
            Dim joinedThreads As List = joinedThreadss.RunMethod("complete", Null)
            For Each t As Object In joinedThreads
                Dim joT As JavaObject = t
                Dim tName As String = joT.RunMethod("getName", Null)
                Dim tId   As String = joT.RunMethod("getId",   Null)
                output = output & $"  Archived Private-Joined Thread: ${tName} [${tId}]"$ & CRLF
            Next
        Catch
        End Try





        Log("X3")
        ' 3. Active threads
        Dim activeThreads As List = guildObj.ThreadChannels 'guildObj.RunMethod("getThreadChannels", Null)
        For Each at As Object In activeThreads
            Dim joAT As JavaObject = at
            Dim parentId As JavaObject= joAT.RunMethod("getParentChannel", Null)
            Dim parentId2 As String = parentId.RunMethod("getId", Null)
            Dim aName As String = joAT.RunMethod("getName", Null)
            Dim aId   As String = joAT.RunMethod("getId",   Null)
            output = output & $"  Active Thread (in ${parentId2}): ${aName} [${aId}]"$ & CRLF
            


            Dim joThread As JavaObject = guildObj.getThreadChannelById(aId)
            ' Write header once
            AppendLineToFile("allmsg.txt", $"-- Messages in Thread [${aId}] --"$)

            ' Get history object
            Dim historyJo As JavaObject = joThread.RunMethod("getHistory", Null)

            Dim batch As List
            Dim retrievedJos As JavaObject

            ' First batch (newest 100)
            retrievedJos = historyJo.RunMethod("retrievePast", Array(100))
            Dim retrievedjo As JavaObject=retrievedJos.RunMethod("complete", Null)
            batch = retrievedjo ' complete() returns List<Message>

            Do While batch.IsInitialized And batch.Size > 0
                For Each m As Object In batch
                    Dim joM    As JavaObject = m
                    Dim authorJo As JavaObject = joM.RunMethod("getAuthor", Null)
                    Dim author   As String     = authorJo.RunMethod("getName", Null)
                    Dim timeJo   As JavaObject = joM.RunMethod("getTimeCreated", Null)
                    Dim timeStr  As String     = timeJo.RunMethod("toString", Null)
                    Dim content  As String     = joM.RunMethod("getContentDisplay", Null)
                    Dim line     As String     = $"  Message [${timeStr}] ${author}: ${content}"$
                    AppendLineToFile("allmsg.txt", line)
                Next

                If batch.Size < 100 Then Exit

                ' Page older using the last message object
                Dim oldestJo As JavaObject = batch.Get(batch.Size - 1)
                retrievedJos = historyJo.RunMethod("retrievePast", Array(100, oldestJo))
                retrievedjo= retrievedJos.RunMethod("complete", Null)
                batch = retrievedjo
            Loop


        Next



    Next

    Return output
End Sub

The problem is that javaobject not having runmethod2 to continue from last msgid to see next 100 msgs and then the other 100... and go on...


wish working the following somehow:
B4X:
......

Dim joThread As JavaObject = guildObj.getThreadChannelById(aId)
AppendLineToFile("allmsg.txt", $"-- Messages in Thread [${aId}] --"$)

' Obtain the MessageHistory object
Dim historyJo As JavaObject = joThread.RunMethod("getHistory", Null)

Dim batch As List
Dim retrievedJo As JavaObject

' First batch: retrievePast(int amount)
retrievedJo = historyJo.RunMethod2("retrievePast", Array(100), Array("int"))
retrievedJo = retrievedJo.RunMethod("complete", Null)
batch = retrievedJo ' It is a List<Message>

Do While batch.IsInitialized And batch.Size > 0
    For Each m As Object In batch
        Dim joM As JavaObject = m
        Dim authorJo As JavaObject = joM.RunMethod("getAuthor", Null)
        Dim author   As String     = authorJo.RunMethod("getName", Null)
        Dim timeJo   As JavaObject = joM.RunMethod("getTimeCreated", Null)
        Dim timeStr  As String     = timeJo.RunMethod("toString", Null)
        Dim content  As String     = joM.RunMethod("getContentDisplay", Null)
        AppendLineToFile("allmsg.txt", $"  Message [{timeStr}] ${author}: ${content}"$)
    Next

    If batch.Size < 100 Then Exit

    ' Page older using retrievePast(int, Message)
    Dim oldestJo As JavaObject = batch.Get(batch.Size - 1)
    retrievedJo = historyJo.RunMethod2("retrievePast", Array(100, oldestJo), _
        Array("int","net.dv8tion.jda.api.entities.Message"))
    retrievedJo = retrievedJo.RunMethod("complete", Null)
    batch = retrievedJo
Loop

' Helper to append lines to file
Sub AppendLineToFile(fileName As String, line As String)
    Dim out As OutputStream = File.OpenOutput(File.DirApp, fileName, True)
    Dim writer As TextWriter
    writer.Initialize(out)
    writer.WriteLine(line)
    writer.Close
    out.Close
End Sub

is there a way have a RunMethod2 for javaobject somehow ?
 
Upvote 0

DonManfred

Expert
Licensed User
Longtime User
is there a way have a RunMethod2 for javaobject somehow ?
JavaObject is part of B4X-Code. This is 100% the wrong subject to ask this.

Away from that your question is NOT related to the question in #1
You should always create a new thread for any new question. You are member since 2013 and should know that already.
 
Upvote 0

Magma

Expert
Licensed User
Longtime User
Every day brings something new to learn, both in life and in B4X development. I’m not afraid to acknowledge that I’m still a work in progress + growing, improving, hoping for better days ahead for myself and for the tools I use. But as with every coin, there are always two sides: progress comes with its trials. With patience and an open mind, both sides help shape us into better creators and better people.
 
Upvote 0

Magma

Expert
Licensed User
Longtime User
BTW: You need to call
B4X:
retrieveArchivedPublicThreadChannels()
on the Textchannel followed by
B4X:
complete()
on the result. You then get the List of archived Threadchannels in the use Textchannel.

I now added retrieveArchivedPrivateJoinedThreadChannels, retrieveArchivedPrivateThreadChannels and retrieveArchivedPublicThreadChannels in the Textchannelobject for the next Libversion.
But i still have to do some additions because of deprecated methods in V6....

In the meantime you can try it with javaobject
Thanks for your time!

ps: I will share some snippets or a tutoral when I will understand JDA. Great wrapper - waiting for next versions !
 
Upvote 0

Magma

Expert
Licensed User
Longtime User
look for a Method like GetIterableHistory4Backup in Threadchannel
I don´t know if it works in archived threads though.
Found Solution... it was simple... now testing a big guild/server (grabbing everything)...
I will inform you here and create a thread at snippets..

Thanks again for helping and openning my mind :)
 
Upvote 0

Magma

Expert
Licensed User
Longtime User
 
Upvote 0
Top