Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -106,13 +106,14 @@ suspend fun Guild.retrieveVanityInviteOrNull(): VanityInvite? {
}

/**
* Retrieves a thread by ID.
* Retrieves a thread belonging to this guild, by ID.
*
* The cached threads are checked first, and then a request is made.
*
* The [RestAction] may throw [InvalidChannelTypeException] if a channel with the ID was found, but isn't a thread.
* It may also throw [ParentGuildMismatchException] if the channel isn't from the same guild.
*
* @see retrieveThreadChannelByIdOrNull
* @see Guild.retrieveThreadChannelByIdOrNull
*/
fun Guild.retrieveThreadChannelById(id: Long): CacheRestAction<ThreadChannel> {
return jda.deferredRestAction(
Expand All @@ -124,58 +125,67 @@ fun Guild.retrieveThreadChannelById(id: Long): CacheRestAction<ThreadChannel> {
if (!channelType.isThread)
throw InvalidChannelTypeException("Invalid channel type, expected a thread, got $channelType")

if (dataObject.getUnsignedLong("guild_id", 0) != this.idLong) {
throw ParentGuildMismatchException("Thread is not from the same guild")
}

(jda as JDAImpl).entityBuilder.createThreadChannel(this as GuildImpl, dataObject, this.idLong, false)
}
}
)
}

/**
* Retrieves a thread by ID.
* Retrieves a thread belonging to this guild, by ID.
*
* The cached threads are checked first, and then a request is made.
*
* The [RestAction] may throw [InvalidChannelTypeException] if a channel with the ID was found, but isn't a thread.
* It may also throw [ParentGuildMismatchException] if the channel isn't from the same guild.
*
* @see retrieveThreadChannelByIdOrNull
* @see Guild.retrieveThreadChannelByIdOrNull
*/
fun Guild.retrieveThreadChannelById(id: String): CacheRestAction<ThreadChannel> {
return retrieveThreadChannelById(MiscUtil.parseSnowflake(id))
}

/**
* Retrieves a thread by ID.
* Retrieves a thread belonging to this guild, by ID.
*
* The cached threads are checked first, and then a request is made.
*
* The returned thread may be null if:
* The returned thread may be `null` if:
* - It doesn't exist
* - The bot doesn't have access to it
* - The channel isn't a thread
* - The channel isn't from the correct guild
*
* @see retrieveThreadChannelById
* @see Guild.retrieveThreadChannelById
*/
suspend fun Guild.retrieveThreadChannelByIdOrNull(id: Long): ThreadChannel? {
return runIgnoringResponseOrNull(ErrorResponse.UNKNOWN_CHANNEL, ErrorResponse.MISSING_ACCESS) {
try {
retrieveThreadChannelById(id).await()
} catch (_: InvalidChannelTypeException) {
return null
} catch (_: ParentGuildMismatchException) {
return null
}
}
}

/**
* Retrieves a thread by ID.
* Retrieves a thread belonging to this guild, by ID.
*
* The cached threads are checked first, and then a request is made.
*
* The returned thread may be null if:
* The returned thread may be `null` if:
* - It doesn't exist
* - The bot doesn't have access to it
* - The channel isn't a thread
* - The channel isn't from the correct guild
*
* @see retrieveThreadChannelById
* @see Guild.retrieveThreadChannelById
*/
suspend fun Guild.retrieveThreadChannelByIdOrNull(id: String): ThreadChannel? {
return retrieveThreadChannelByIdOrNull(MiscUtil.parseSnowflake(id))
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package dev.freya02.botcommands.jda.ktx.retrieve

/**
* Exception thrown when a guild was expected but not found, typically in sharded applications.
*/
class GuildNotFoundException internal constructor(message: String) : IllegalStateException(message)
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,5 @@ package dev.freya02.botcommands.jda.ktx.retrieve

/**
* Exception thrown when retrieving a channel by ID, but the type is incorrect.
*
* @see retrieveThreadChannelById
*/
class InvalidChannelTypeException(message: String) : IllegalArgumentException(message)
class InvalidChannelTypeException internal constructor(message: String) : IllegalArgumentException(message)
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,24 @@ package dev.freya02.botcommands.jda.ktx.retrieve

import dev.freya02.botcommands.jda.ktx.IgnoreForMatch
import dev.freya02.botcommands.jda.ktx.coroutines.await
import dev.freya02.botcommands.jda.ktx.deferredRestAction
import dev.freya02.botcommands.jda.ktx.requests.runIgnoringResponseOrNull
import net.dv8tion.jda.api.JDA
import net.dv8tion.jda.api.entities.Entitlement
import net.dv8tion.jda.api.entities.User
import net.dv8tion.jda.api.entities.Webhook
import net.dv8tion.jda.api.entities.channel.ChannelType
import net.dv8tion.jda.api.entities.channel.concrete.ThreadChannel
import net.dv8tion.jda.api.entities.sticker.StickerSnowflake
import net.dv8tion.jda.api.entities.sticker.StickerUnion
import net.dv8tion.jda.api.requests.ErrorResponse
import net.dv8tion.jda.api.requests.RestAction
import net.dv8tion.jda.api.requests.Route
import net.dv8tion.jda.api.requests.restaction.CacheRestAction
import net.dv8tion.jda.api.utils.MiscUtil
import net.dv8tion.jda.internal.JDAImpl
import net.dv8tion.jda.internal.entities.GuildImpl
import net.dv8tion.jda.internal.requests.RestActionImpl

/**
* Retrieves a [User] with the provided ID.
Expand Down Expand Up @@ -107,3 +117,94 @@ suspend fun JDA.retrieveWebhookByIdOrNull(webhookId: Long): Webhook? {
retrieveWebhookById(webhookId).await()
}
}

/**
* Retrieves a thread from any guild, by ID.
*
* The cached threads are checked first, and then a request is made.
*
* The [RestAction] may throw [InvalidChannelTypeException] if a channel with the ID was found, but isn't a thread.
* If the thread is not owned by the current shard, [GuildNotFoundException] is thrown.
*
* @see JDA.retrieveThreadChannelByIdOrNull
*/
fun JDA.retrieveThreadChannelById(id: Long): CacheRestAction<ThreadChannel> {
return deferredRestAction(
valueSupplier = { getThreadChannelById(id) },
actionSupplier = {
RestActionImpl(this, Route.Channels.GET_CHANNEL.compile(id.toString())) { res, _ ->
val json = res.`object`
val channelType = json.getInt("type").let(ChannelType::fromId)
if (!channelType.isThread)
throw InvalidChannelTypeException("Invalid channel type, expected a thread, got $channelType")

val guildId = json.getUnsignedLong("guild_id")
val guild = getGuildById(guildId) ?: run {
val expectedShard = (guildId shr 22) % shardInfo.shardTotal
val actualShard = shardInfo.shardId
if (expectedShard.toInt() == actualShard) {
throw GuildNotFoundException("Thread was found but its guild was not found")
} else {
throw GuildNotFoundException("Thread was found but its guild was not found as it is from a different shard")
}
}

(this as JDAImpl).entityBuilder.createThreadChannel(guild as GuildImpl, json, guildId, false)
}
}
)
}

/**
* Retrieves a thread from any guild, by ID.
*
* The cached threads are checked first, and then a request is made.
*
* The [RestAction] may throw [InvalidChannelTypeException] if a channel with the ID was found, but isn't a thread.
* If the thread is not owned by the current shard, [GuildNotFoundException] is thrown.
*
* @see JDA.retrieveThreadChannelByIdOrNull
*/
fun JDA.retrieveThreadChannelById(id: String): CacheRestAction<ThreadChannel> {
return retrieveThreadChannelById(MiscUtil.parseSnowflake(id))
}

/**
* Retrieves a thread from any guild, by ID.
*
* The cached threads are checked first, and then a request is made.
*
* The returned thread may be `null` if:
* - It doesn't exist
* - The bot doesn't have access to it
* - The channel isn't a thread
* - The thread isn't owned by a guild of this shard
*
* @see JDA.retrieveThreadChannelById
*/
suspend fun JDA.retrieveThreadChannelByIdOrNull(id: Long): ThreadChannel? {
return runIgnoringResponseOrNull(ErrorResponse.UNKNOWN_CHANNEL, ErrorResponse.MISSING_ACCESS) {
try {
retrieveThreadChannelById(id).await()
} catch (_: InvalidChannelTypeException) {
return null
}
}
}

/**
* Retrieves a thread from any guild, by ID.
*
* The cached threads are checked first, and then a request is made.
*
* The returned thread may be `null` if:
* - It doesn't exist
* - The bot doesn't have access to it
* - The channel isn't a thread
* - The thread isn't owned by a guild of this shard
*
* @see JDA.retrieveThreadChannelById
*/
suspend fun JDA.retrieveThreadChannelByIdOrNull(id: String): ThreadChannel? {
return retrieveThreadChannelByIdOrNull(MiscUtil.parseSnowflake(id))
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package dev.freya02.botcommands.jda.ktx.retrieve

/**
* Exception thrown when retrieving a channel by ID from a guild, but their expected guild is incorrect.
*/
class ParentGuildMismatchException internal constructor(message: String) : IllegalArgumentException(message)