Skip to content

Commit

Permalink
Add core support for Invites
Browse files Browse the repository at this point in the history
  • Loading branch information
HopeBaron committed Jun 22, 2020
1 parent 5bfbe6e commit 72e2742
Show file tree
Hide file tree
Showing 16 changed files with 214 additions and 82 deletions.
7 changes: 5 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,14 +1,17 @@
# 0.5.1

## Additions

* Added `PartialGuild` in `Invite`
* Added `GuildBehavior.createEmoji`
* Added `GuildEmoji.delete` and `GuildEmoji.edit`
* Added `getInviteOrNull` method to `RestEntitySupplier`

## Fixes

* `DiscordInvite#targetUser` is now correctly nullable.

* `PermissionOverwriteEntity#getGuildOrNull` uses the correct supplier method.
## Changes
* `Invite` now uses a `Channel` instead of `GuildChannel`.
# 0.5.0

## Additions
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import com.gitlab.kordlib.core.exception.EntityNotFoundException
import com.gitlab.kordlib.core.sorted
import com.gitlab.kordlib.core.supplier.EntitySupplier
import com.gitlab.kordlib.core.supplier.EntitySupplyStrategy
import com.gitlab.kordlib.core.supplier.EntitySupplyStrategy.Companion.rest
import com.gitlab.kordlib.rest.builder.ban.BanCreateBuilder
import com.gitlab.kordlib.rest.builder.channel.*
import com.gitlab.kordlib.rest.builder.guild.EmojiCreateBuilder
Expand Down Expand Up @@ -197,6 +198,30 @@ interface GuildBehavior : Entity, Strategizable {
*/
suspend fun getRoleOrNull(roleId: Snowflake): Role? = supplier.getRoleOrNull(guildId = id, roleId = roleId)

/**
* Requests to get the [Invite] represented by the [code].
*
*
* This property is not resolvable through cache and will always use the [RestClient] instead.
*
* @throws [RequestException] if anything went wrong during the request.
* @throws [EntityNotFoundException] if the [Invite] wasn't present.
*/
suspend fun getInvite(code: String, withCounts: Boolean = true): Invite =
kord.with(rest).getInvite(code, withCounts)

/**
* Requests to get the [Invite] represented by the [code],
* returns null if the [Invite] isn't present.
*
* This property is not resolvable through cache and will always use the [RestClient] instead.
*
* @throws [RequestException] if anything went wrong during the request.
*/
suspend fun getInviteOrNull(code: String, withCounts: Boolean = true): Invite? =
kord.with(rest).getInviteOrNull(code, withCounts)


/**
* Requests to change the nickname of the bot in this guild, passing `null` will remove it.
*
Expand Down Expand Up @@ -251,7 +276,7 @@ interface GuildBehavior : Entity, Strategizable {
* @throws RequestException if the guild does not exist or is not public.
* @throws [EntityNotFoundException] if the preview was not found.
*/
suspend fun getPreview(): GuildPreview = kord.with(EntitySupplyStrategy.rest).getGuildPreview(id)
suspend fun getPreview(): GuildPreview = kord.with(rest).getGuildPreview(id)

/**
* Returns the preview of this guild. The bot does not need to present in this guild
Expand All @@ -261,7 +286,7 @@ interface GuildBehavior : Entity, Strategizable {
*
* @throws RequestException if the guild does not exist or is not public.
*/
suspend fun getPreviewOrNull(): GuildPreview? = kord.with(EntitySupplyStrategy.rest).getGuildPreviewOrNull(id)
suspend fun getPreviewOrNull(): GuildPreview? = kord.with(rest).getGuildPreviewOrNull(id)

/**
* Requests to get the amount of users that would be pruned in this guild.
Expand Down Expand Up @@ -311,6 +336,7 @@ interface GuildBehavior : Entity, Strategizable {

override fun equals(other: Any?): Boolean = when (other) {
is GuildBehavior -> other.id == id
is PartialGuild -> other.id == id
else -> false
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,16 +65,9 @@ interface MessageBehavior : Entity, Strategizable {
* The returned flow is lazily executed, any [RequestException] will be thrown on
* [terminal operators](https://kotlinlang.org/docs/reference/coroutines/flow.html#terminal-flow-operators) instead.
*/

fun getReactors(emoji: ReactionEmoji): Flow<User> =
paginateForwards(batchSize = 100, idSelector = { it.id }) { position ->
kord.rest.channel.getReactions(
channelId = channelId.value,
messageId = id.value,
emoji = emoji.urlFormat,
limit = 100,
position = position
)
}.map { UserData.from(it) }.map { User(it, kord) }
kord.with(EntitySupplyStrategy.rest).getReactors(channelId, id, emoji)

/**
* Requests to add an [emoji] to this message.
Expand Down Expand Up @@ -153,7 +146,7 @@ interface MessageBehavior : Entity, Strategizable {
*/
override fun withStrategy(
strategy: EntitySupplyStrategy<*>
) : MessageBehavior = MessageBehavior(channelId, id, kord, strategy)
): MessageBehavior = MessageBehavior(channelId, id, kord, strategy)

companion object {
internal operator fun invoke(
Expand All @@ -169,7 +162,7 @@ interface MessageBehavior : Entity, Strategizable {

override fun hashCode(): Int = Objects.hash(id)

override fun equals(other: Any?): Boolean = when(other) {
override fun equals(other: Any?): Boolean = when (other) {
is MessageBehavior -> other.id == id && other.channelId == channelId
else -> false
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,4 +41,4 @@ internal suspend fun DataCache.removeKordData() {
* Creates a [DataCacheView] for this view, only removing elements that were added
* directly to this instance.
*/
suspend fun DataCache.createView() : DataCacheView = DataCacheView(this)
suspend fun DataCache.createView(): DataCacheView = DataCacheView(this)
Original file line number Diff line number Diff line change
@@ -1,26 +1,29 @@
package com.gitlab.kordlib.core.cache.data

import com.gitlab.kordlib.cache.api.data.description
import com.gitlab.kordlib.common.entity.TargetUserType
import com.gitlab.kordlib.rest.json.response.InviteResponse
import kotlinx.serialization.Serializable

@Serializable
data class InviteData(
val code: String,
val guildId: Long?,
val guild: PartialGuildData?,
val channelId: Long,
val targetUserId: Long?,
val inviterId: Long?,
val approximatePresenceCount: Int?,
val approximateMemberCount: Int?,
val targetUserType: TargetUserType?
) {

companion object {

fun from(entity: InviteResponse) = with(entity) {
InviteData(
code!!,
guild!!.id.toLong(),
channel!!.id.toLong(),
code,
guild?.let { PartialGuildData.from(it) },
channel.id.toLong(),
targetUser?.id?.toLong(),
inviter?.id?.toLong(),
approximatePresenceCount,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package com.gitlab.kordlib.core.cache.data

import com.gitlab.kordlib.cache.api.data.description
import com.gitlab.kordlib.common.entity.DiscordPartialGuild
import com.gitlab.kordlib.common.entity.Permissions
import kotlinx.serialization.Serializable

@Serializable
class PartialGuildData(
val id: Long,
val name: String,
val icon: String? = null,
val owner: Boolean? = null,
val permissions: Permissions? = null
) {
companion object {

fun from(partialGuild: DiscordPartialGuild) = with(partialGuild) {
PartialGuildData(id.toLong(), name, icon, owner, permissions)
}
}


}

val InviteData.guildId get() = guild?.id
42 changes: 11 additions & 31 deletions core/src/main/kotlin/com/gitlab/kordlib/core/entity/Invite.kt
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,10 @@ import com.gitlab.kordlib.common.entity.TargetUserType
import com.gitlab.kordlib.common.exception.RequestException
import com.gitlab.kordlib.core.Kord
import com.gitlab.kordlib.core.KordObject
import com.gitlab.kordlib.core.behavior.GuildBehavior
import com.gitlab.kordlib.core.behavior.UserBehavior
import com.gitlab.kordlib.core.behavior.channel.GuildChannelBehavior
import com.gitlab.kordlib.core.behavior.channel.ChannelBehavior
import com.gitlab.kordlib.core.cache.data.InviteData
import com.gitlab.kordlib.core.entity.channel.GuildChannel
import com.gitlab.kordlib.core.entity.channel.Channel
import com.gitlab.kordlib.core.exception.EntityNotFoundException
import com.gitlab.kordlib.core.supplier.EntitySupplier
import com.gitlab.kordlib.core.supplier.EntitySupplyStrategy
Expand Down Expand Up @@ -37,9 +36,9 @@ data class Invite(
val channelId: Snowflake get() = Snowflake(data.channelId)

/**
* The id of the guild this invite is associated to.
* Returns [PartialGuild] if the invite was made in a guild, or null if not.
*/
val guildId: Snowflake get() = Snowflake(data.guildId!!)
val partialGuild: PartialGuild? get() = data.guild?.let { PartialGuild(it, kord) }

/**
* The id of the user who created this invite, if present.
Expand All @@ -54,12 +53,8 @@ data class Invite(
/**
* The behavior of the channel this invite is associated to.
*/
val channel: GuildChannelBehavior get() = GuildChannelBehavior(guildId, channelId, kord)
val channel: ChannelBehavior get() = ChannelBehavior(channelId, kord)

/**
* The behavior of the guild this invite is associated to.
*/
val guild: GuildBehavior get() = GuildBehavior(guildId, kord)

/**
* The user behavior of the user who created this invite, if present.
Expand Down Expand Up @@ -90,40 +85,25 @@ data class Invite(
* Requests to get the channel this invite is for.
*
* @throws [RequestException] if anything went wrong during the request.
* @throws [EntityNotFoundException] if the [GuildChannel] wasn't present.
* @throws [EntityNotFoundException] if the [Channel] wasn't present.
*/
suspend fun getChannel(): GuildChannel = supplier.getChannelOf(channelId)
suspend fun getChannel(): Channel = supplier.getChannelOf(channelId)

/**
* Requests to get the channel this invite is for,
* returns null if the [GuildChannel] isn't present.
*
* @throws [RequestException] if anything went wrong during the request.
*/
suspend fun getChannelOrNull(): GuildChannel? = supplier.getChannelOfOrNull(channelId)

/**
* Requests to get the [Guild] for this invite.
* returns null if the [Channel] isn't present.
*
* @throws [RequestException] if anything went wrong during the request.
* @throws [EntityNotFoundException] if the [Guild] wasn't present.
*/
suspend fun getGuild(): Guild = supplier.getGuild(guildId)

/**
* Requests to get the [Guild] for this invite,
* returns null if the [Guild] isn't present.
*
* @throws [RequestException] if anything went wrong during the request.
*/
suspend fun getGuildOrNull(): Guild? = supplier.getGuildOrNull(guildId)
suspend fun getChannelOrNull(): Channel? = supplier.getChannelOfOrNull(channelId)

/**
* Requests to get the creator of the invite for,
* returns null if the [User] isn't present or [inviterId] is null.
*
* @throws [RequestException] if anything went wrong during the request.
*/ suspend fun getInviter(): User? = inviterId?.let { supplier.getUserOrNull(it) }
*/
suspend fun getInviter(): User? = inviterId?.let { supplier.getUserOrNull(it) }

/**
* Requests to get the user this invite was created for,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
package com.gitlab.kordlib.core.entity

import com.gitlab.kordlib.common.entity.Permissions
import com.gitlab.kordlib.common.entity.Snowflake
import com.gitlab.kordlib.common.exception.RequestException
import com.gitlab.kordlib.core.Kord
import com.gitlab.kordlib.core.behavior.GuildBehavior
import com.gitlab.kordlib.core.cache.data.PartialGuildData
import com.gitlab.kordlib.core.entity.channel.Channel
import com.gitlab.kordlib.core.exception.EntityNotFoundException
import com.gitlab.kordlib.core.supplier.EntitySupplier
import com.gitlab.kordlib.core.supplier.EntitySupplyStrategy
import com.gitlab.kordlib.core.supplier.getChannelOf
import com.gitlab.kordlib.core.supplier.getChannelOfOrNull
import com.gitlab.kordlib.rest.Image
import java.util.*

class PartialGuild(
val data: PartialGuildData,
override val kord: Kord,
override val supplier: EntitySupplier = kord.defaultSupplier
) : Entity, Strategizable {

/**
* The name of this guild.
*/
val name: String get() = data.name


override val id: Snowflake get() = Snowflake(data.id)

/**
* The icon hash, if present.
*/
val iconHash: String? get() = data.icon

/**
* wither who created the invite is the owner or not.
*/

val owner: Boolean? get() = data.owner

/**
* permissions that the invite creator has, if present.
*/

val permissions: Permissions? get() = data.permissions

/**
* Gets the icon url, if present.
*/
fun getIconUrl(format: Image.Format): String? = data.icon?.let { "https://cdn.discordapp.com/icons/${id.value}/$it.${format.extension}" }

/**
* Requests to get the icon image in the specified [format], if present.
*/
suspend fun getIcon(format: Image.Format): Image? {
val url = getIconUrl(format) ?: return null

return Image.fromUrl(kord.resources.httpClient, url)
}

/**
* Requests to get the full [Guild] entity for this [PartialGuild].
*
* @throws [RequestException] if anything went wrong during the request.
* @throws [EntityNotFoundException] if the [Guild] wasn't present, or the bot is not a part of this [Guild].
*/
suspend fun getGuild(): Guild = supplier.getGuild(id)

/**
* Requests to get the [Guild] for this invite,
* returns null if the [Guild] isn't present.
*
* @throws [RequestException] if anything went wrong during the request.
*/
suspend fun getGuildOrNull(): Guild? = supplier.getGuildOrNull(id)


override fun hashCode(): Int = Objects.hash(id)

override fun equals(other: Any?): Boolean = when (other) {
is GuildBehavior -> other.id == id
is PartialGuild -> other.id == id
else -> false
}


override fun withStrategy(strategy: EntitySupplyStrategy<*>): PartialGuild =
PartialGuild(data, kord, strategy.supply(kord))

}
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ class PermissionOverwriteEntity(
*
* @throws [RequestException] if anything went wrong during the request.
*/
suspend fun getGuildOrNull(): Guild? = supplier.getGuild(guildId)
suspend fun getGuildOrNull(): Guild? = supplier.getGuildOrNull(guildId)

/**
* Requests to delete this overwrite.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,9 @@ class EntityNotFoundException : Exception {
fun webhookNotFound(webhookId: Snowflake): Nothing =
entityNotFound("Webhook", webhookId)

fun inviteNotFound(code: String): Nothing =
throw EntityNotFoundException("Invite with code $code was not found.")

}

}
Loading

0 comments on commit 72e2742

Please sign in to comment.