All Downloads are FREE. Search and download functionalities are using the official Maven repository.

commonMain.entity.Emoji.kt Maven / Gradle / Ivy

There is a newer version: 0.15.0
Show newest version
package dev.kord.core.entity

import dev.kord.common.entity.Snowflake
import dev.kord.common.entity.optional.orEmpty
import dev.kord.common.exception.RequestException
import dev.kord.core.Kord
import dev.kord.core.behavior.MemberBehavior
import dev.kord.core.behavior.RoleBehavior
import dev.kord.core.behavior.UserBehavior
import dev.kord.core.cache.data.EmojiData
import dev.kord.core.supplier.EntitySupplier
import dev.kord.core.supplier.EntitySupplyStrategy
import dev.kord.rest.builder.guild.EmojiModifyBuilder
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.emptyFlow
import kotlinx.coroutines.flow.filter
import dev.kord.core.hash
import kotlin.contracts.InvocationKind
import kotlin.contracts.contract

/** Either a [StandardEmoji] or a [GuildEmoji]. */
public sealed interface Emoji {
    /**
     * Either the unicode representation of the emoji if it's a [StandardEmoji] or the emoji name if it's a
     * [GuildEmoji].
     */
    public val name: String?

    /**
     * Either the unicode representation of the emoji if it's a [StandardEmoji] or the
     * [mention string](https://discord.com/developers/docs/reference#message-formatting) if it's a [GuildEmoji].
     */
    public val mention: String
}

/**
 * An instance of a
 * [standard emoji](https://discord.com/developers/docs/resources/emoji#emoji-object-standard-emoji-example).
 *
 * @property name The unicode representation of this emoji.
 */
public class StandardEmoji(override val name: String) : Emoji {
    /** The unicode representation of this emoji. */
    override val mention: String get() = name
    override fun equals(other: Any?): Boolean = other is StandardEmoji && this.name == other.name
    override fun hashCode(): Int = name.hashCode()
    override fun toString(): String = "StandardEmoji(name=$name)"
}

/**
 * An instance of an [emoji](https://discord.com/developers/docs/resources/emoji#emoji-object) belonging to a specific
 * [Guild].
 */
public class GuildEmoji(
    public val data: EmojiData,
    override val kord: Kord,
    override val supplier: EntitySupplier = kord.defaultSupplier
) : Emoji, KordEntity, Strategizable {

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

    public val guildId: Snowflake
        get() = data.guildId

    override val mention: String
        get() = if (isAnimated) "" else "<:$name:$id>"

    /**
     * Whether this emoji can be used, may be false due to loss of Server Boosts.
     */
    public val isAvailable: Boolean get() = data.available.discordBoolean

    /**
     * Whether is emoji is animated.
     */
    public val isAnimated: Boolean get() = data.animated.discordBoolean

    /**
     * Whether is emote is managed by Discord instead of the guild members.
     */
    public val isManaged: Boolean get() = data.managed.discordBoolean

    /**
     * The name of this emoji.
     *
     * This property can be null when trying to get the name of an emoji that was deleted.
     */
    override val name: String? get() = data.name

    /**
     * Whether this emoji needs to be wrapped in colons.
     */
    public val requiresColons: Boolean get() = data.requireColons.discordBoolean

    /**
     * The ids of the [roles][Role] for which this emoji was whitelisted.
     */
    public val roleIds: Set get() = data.roles.orEmpty().toSet()

    /**
     * The behaviors of the [roles][Role] for which this emoji was whitelisted.
     */
    public val roleBehaviors: Set
        get() = data.roles.orEmpty().map { roleId -> RoleBehavior(guildId = guildId, id = roleId, kord = kord) }.toSet()

    /**
     * The [roles][Role] for which this emoji was whitelisted.
     *
     * This request uses state [data] to resolve the entities belonging to the flow,
     * as such it can't guarantee an up to date representation if the [data] is outdated.
     *
     * 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.
     */
    public val roles: Flow
        get() = if (roleIds.isEmpty()) emptyFlow()
        else supplier.getGuildRoles(guildId).filter { it.id in roleIds }

    /**
     * The behavior of the [Member] who created the emote, if present.
     */
    public val member: MemberBehavior? get() = userId?.let { MemberBehavior(guildId, it, kord) }

    /**
     * The id of the [User] who created the emote, if present.
     */
    public val userId: Snowflake? get() = data.userId.value

    /**
     * The [User] who created the emote, if present.
     */
    public val user: UserBehavior? get() = userId?.let { UserBehavior(it, kord) }

    /**
     * The image as [Icon] object for the emoji
     */
    @Suppress("DEPRECATION_ERROR")
    @Deprecated("Binary compatibility", level = DeprecationLevel.HIDDEN)
    public fun getImage(): Icon = Icon.EmojiIcon(data.animated.discordBoolean, data.id, kord)

    /** The image of this emoji as an [Asset]. */
    public val image: Asset get() = Asset.emoji(id, isAnimated, kord)

    /**
     * Requests to delete this emoji, with the given [reason].
     *
     * @param reason the reason showing up in the audit log
     * @throws RequestException if anything went wrong during the request.
     */
    public suspend fun delete(reason: String? = null) {
        kord.rest.emoji.deleteEmoji(guildId = guildId, emojiId = id, reason = reason)
    }

    /**
     *  Requests to edit the emoji.
     *
     *  @throws [RequestException] if anything went wrong during the request.
     */
    public suspend inline fun edit(builder: EmojiModifyBuilder.() -> Unit) {
        contract {
            callsInPlace(builder, InvocationKind.EXACTLY_ONCE)
        }
        kord.rest.emoji.modifyEmoji(guildId = guildId, emojiId = id, builder = builder)
    }

    /**
     * Requests to get the creator of the emoji as a [Member],
     * returns null if the [Member] isn't present or [userId] is null.
     *
     * @throws [RequestException] if anything went wrong during the request.
     */
    public suspend fun getMember(): Member? = userId?.let { supplier.getMemberOrNull(guildId = guildId, userId = it) }

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

    /**
     * Returns a new [GuildEmoji] with the given [strategy].
     */
    override fun withStrategy(strategy: EntitySupplyStrategy<*>): GuildEmoji = GuildEmoji(data, kord, strategy.supply(kord))

    override fun hashCode(): Int = hash(id, guildId)

    override fun equals(other: Any?): Boolean = when (other) {
        is GuildEmoji -> other.id == id && other.guildId == guildId
        else -> super.equals(other)
    }

    override fun toString(): String {
        return "GuildEmoji(data=$data, kord=$kord, supplier=$supplier)"
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy