package dev.inmo.tgbotapi.types import korlibs.time.DateTime import dev.inmo.tgbotapi.abstracts.WithUser import dev.inmo.tgbotapi.types.chat.User import dev.inmo.tgbotapi.utils.RiskFeature import kotlinx.serialization.* import kotlinx.serialization.descriptors.SerialDescriptor import kotlinx.serialization.encoding.Decoder import kotlinx.serialization.encoding.Encoder @Serializable private data class RawChatInviteLink( @SerialName(inviteLinkField) val inviteLink: String, @SerialName(creatorField) val creator: User, @SerialName(isPrimaryField) val isPrimary: Boolean, @SerialName(isRevokedField) val isRevoked: Boolean, @SerialName(nameField) val name: String? = null, @SerialName(expireDateField) val expirationDateTime: TelegramDate? = null, @SerialName(memberLimitField) val membersLimit: MembersLimit ?= null, @SerialName(createsJoinRequestField) val createsJoinRequest: Boolean? = null, @SerialName(pendingJoinRequestCountField) val pendingJoinRequestCount: MembersLimit ?= null ) private fun ChatInviteLink.toRawChatInviteLink() = RawChatInviteLink( inviteLink, creator, isPrimary, isRevoked, (this as? SecondaryChatInviteLink) ?.name, expirationDateTime ?.toTelegramDate(), (this as? ChatInviteLinkWithLimitedMembers) ?.membersLimit, this is ChatInviteLinkWithJoinRequest, (this as? ChatInviteLinkWithJoinRequest) ?.leftToReview ) /** * Base interface for all chat invite links. See inheritors for more info or official [docs](https://core.telegram.org/bots/api#chatinvitelink) */ @Serializable(ChatInviteLinkSerializer::class) sealed interface ChatInviteLink : WithUser { val inviteLink: String val creator: User val isPrimary: Boolean get() = this is PrimaryInviteLink val isRevoked: Boolean val expirationDateTime: DateTime? val name: String? override val user: User get() = creator } /** * Base interface for all [ChatInviteLink]s which are NOT [PrimaryInviteLink] */ @Serializable(ChatInviteLinkSerializer::class) sealed interface SecondaryChatInviteLink : ChatInviteLink { override val isPrimary: Boolean get() = false } /** * Primary invite link in the chat for this bot */ @Serializable data class PrimaryInviteLink( @SerialName(inviteLinkField) override val inviteLink: String, @SerialName(creatorField) override val creator: User, @SerialName(isRevokedField) override val isRevoked: Boolean = false, @SerialName(expireDateField) private val expireDate: TelegramDate? = null, ) : ChatInviteLink { override val expirationDateTime: DateTime? get() = expireDate ?.asDate override val name: String? get() = null } /** * Represent [SecondaryChatInviteLink] which will require an aprovement from one of the administrators * * @see ChatJoinRequest * @see dev.inmo.tgbotapi.types.update.ChatJoinRequestUpdate */ @Serializable data class ChatInviteLinkWithJoinRequest( @SerialName(inviteLinkField) override val inviteLink: String, @SerialName(creatorField) override val creator: User, @SerialName(nameField) override val name: String? = null, @SerialName(pendingJoinRequestCountField) val leftToReview: Int = 0, @SerialName(isRevokedField) override val isRevoked: Boolean = false, @SerialName(expireDateField) private val expireDate: TelegramDate? = null ) : SecondaryChatInviteLink { override val expirationDateTime: DateTime? get() = expireDate ?.asDate } /** * Represent [SecondaryChatInviteLink] which will have limitation for the amount of chat members to join */ @Serializable data class ChatInviteLinkWithLimitedMembers( @SerialName(inviteLinkField) override val inviteLink: String, @SerialName(creatorField) override val creator: User, @SerialName(nameField) override val name: String? = null, @SerialName(memberLimitField) val membersLimit: MembersLimit, @SerialName(isRevokedField) override val isRevoked: Boolean = false, @SerialName(expireDateField) private val expireDate: TelegramDate? = null, ) : SecondaryChatInviteLink { override val expirationDateTime: DateTime? get() = expireDate ?.asDate } /** * Represent [SecondaryChatInviteLink] which have no any restrictions like [ChatInviteLinkWithJoinRequest] or * [ChatInviteLinkWithLimitedMembers] */ @Serializable data class ChatInviteLinkUnlimited( @SerialName(inviteLinkField) override val inviteLink: String, @SerialName(creatorField) override val creator: User, @SerialName(nameField) override val name: String? = null, @SerialName(isRevokedField) override val isRevoked: Boolean = false, @SerialName(expireDateField) private val expireDate: TelegramDate? = null, ) : SecondaryChatInviteLink { override val expirationDateTime: DateTime? get() = expireDate ?.asDate } @RiskFeature object ChatInviteLinkSerializer : KSerializer { override val descriptor: SerialDescriptor get() = RawChatInviteLink.serializer().descriptor override fun deserialize(decoder: Decoder): ChatInviteLink { val deserializedRaw = RawChatInviteLink.serializer().deserialize(decoder) return deserializedRaw.run { when { isPrimary -> PrimaryInviteLink( inviteLink, creator, isRevoked, expirationDateTime ) createsJoinRequest == true -> { ChatInviteLinkWithJoinRequest( inviteLink, creator, name, pendingJoinRequestCount ?: 0, isRevoked, expirationDateTime ) } membersLimit != null -> { ChatInviteLinkWithLimitedMembers( inviteLink, creator, name, membersLimit, isRevoked, expirationDateTime ) } else -> ChatInviteLinkUnlimited( inviteLink, creator, name, isRevoked, expirationDateTime ) } } } override fun serialize(encoder: Encoder, value: ChatInviteLink) { RawChatInviteLink.serializer().serialize(encoder, value.toRawChatInviteLink()) } }