diff --git a/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/chat/member/ChatMember.kt b/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/chat/member/ChatMember.kt index b2598b7d67..e2c67a3eba 100644 --- a/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/chat/member/ChatMember.kt +++ b/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/chat/member/ChatMember.kt @@ -2,6 +2,7 @@ package dev.inmo.tgbotapi.types.chat.member import dev.inmo.tgbotapi.abstracts.WithUser import dev.inmo.tgbotapi.types.statusField +import dev.inmo.tgbotapi.types.untilDateField import dev.inmo.tgbotapi.utils.RiskFeature import dev.inmo.tgbotapi.utils.nonstrictJsonFormat import kotlinx.serialization.DeserializationStrategy @@ -11,6 +12,7 @@ import kotlinx.serialization.builtins.serializer import kotlinx.serialization.descriptors.SerialDescriptor import kotlinx.serialization.encoding.Decoder import kotlinx.serialization.encoding.Encoder +import kotlinx.serialization.json.JsonElement import kotlinx.serialization.json.JsonObject import kotlinx.serialization.json.jsonPrimitive @@ -19,11 +21,13 @@ sealed interface ChatMember : WithUser { @Serializable(StatusSerializer::class) enum class Status( val status: String, - val deserializationStrategy: DeserializationStrategy + val deserializationStrategy: DeserializationStrategy, + val checker: (String, JsonObject) -> Boolean = { outerStatus, _ -> outerStatus == status }, ) { Creator("creator", OwnerChatMember.serializer()), Administrator("administrator", AdministratorChatMemberImpl.serializer()), - Member("member", MemberChatMemberImpl.serializer()), + Member("member", MemberChatMemberImpl.serializer(), { status, json -> status == "member" && json[untilDateField] ?.jsonPrimitive == null }), + SubscriptionMember("member", SubscriptionMemberChatMemberImpl.serializer(), { status, json -> status == "member" && json[untilDateField] ?.jsonPrimitive != null }), Restricted("restricted", RestrictedChatMember.serializer()), Left("left", LeftChatMemberImpl.serializer()), Kicked("kicked", KickedChatMember.serializer()) @@ -56,7 +60,7 @@ object ChatMemberSerializer : KSerializer { val json = JsonObject.serializer().deserialize(decoder) val status = json[statusField] ?.jsonPrimitive ?.content ?: error("Status field of chat member must be specified, but incoming json contains next: $json") return ChatMember.Status.values().firstNotNullOfOrNull { - if (it.status == status) { + if (it.checker(status, json)) { nonstrictJsonFormat.decodeFromJsonElement(it.deserializationStrategy, json) } else { null @@ -68,6 +72,7 @@ object ChatMemberSerializer : KSerializer { when (value) { is OwnerChatMember -> OwnerChatMember.serializer().serialize(encoder, value) is AdministratorChatMemberImpl -> AdministratorChatMemberImpl.serializer().serialize(encoder, value) + is SubscriptionMemberChatMemberImpl -> SubscriptionMemberChatMemberImpl.serializer().serialize(encoder, value) is MemberChatMemberImpl -> MemberChatMemberImpl.serializer().serialize(encoder, value) is RestrictedChatMember -> RestrictedChatMember.serializer().serialize(encoder, value) is LeftChatMemberImpl -> LeftChatMemberImpl.serializer().serialize(encoder, value) diff --git a/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/chat/member/MemberChatMember.kt b/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/chat/member/MemberChatMember.kt index e852e21dcd..e11554acb7 100644 --- a/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/chat/member/MemberChatMember.kt +++ b/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/chat/member/MemberChatMember.kt @@ -1,11 +1,6 @@ package dev.inmo.tgbotapi.types.chat.member -import dev.inmo.tgbotapi.abstracts.types.UntilDate -import korlibs.time.DateTime import kotlinx.serialization.Serializable @Serializable(ChatMemberSerializer::class) -sealed interface MemberChatMember : ChatMember, UntilDate { - val until: DateTime? - get() = untilDate ?.asDate -} +sealed interface MemberChatMember : ChatMember diff --git a/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/chat/member/MemberChatMemberImpl.kt b/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/chat/member/MemberChatMemberImpl.kt index 3e2d10dd26..19030de711 100644 --- a/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/chat/member/MemberChatMemberImpl.kt +++ b/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/chat/member/MemberChatMemberImpl.kt @@ -8,10 +8,7 @@ import kotlinx.serialization.* @Serializable data class MemberChatMemberImpl( @SerialName(userField) - override val user: User, - @SerialName(untilDateField) - @Serializable(TelegramDateSerializer::class) - override val untilDate: TelegramDate? = null + override val user: User ) : MemberChatMember { @SerialName(statusField) @Required diff --git a/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/chat/member/SubscriptionMemberChatMember.kt b/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/chat/member/SubscriptionMemberChatMember.kt new file mode 100644 index 0000000000..d70d51a502 --- /dev/null +++ b/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/chat/member/SubscriptionMemberChatMember.kt @@ -0,0 +1,13 @@ +package dev.inmo.tgbotapi.types.chat.member + +import dev.inmo.tgbotapi.abstracts.types.UntilDate +import dev.inmo.tgbotapi.types.TelegramDate +import korlibs.time.DateTime +import kotlinx.serialization.Serializable + +@Serializable(ChatMemberSerializer::class) +sealed interface SubscriptionMemberChatMember : MemberChatMember, UntilDate { + override val untilDate: TelegramDate + val until: DateTime + get() = untilDate.asDate +} diff --git a/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/chat/member/SubscriptionMemberChatMemberImpl.kt b/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/chat/member/SubscriptionMemberChatMemberImpl.kt new file mode 100644 index 0000000000..e36f884394 --- /dev/null +++ b/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/chat/member/SubscriptionMemberChatMemberImpl.kt @@ -0,0 +1,20 @@ +package dev.inmo.tgbotapi.types.chat.member + +import dev.inmo.tgbotapi.types.* +import dev.inmo.tgbotapi.types.chat.User +import korlibs.time.DateTime +import kotlinx.serialization.* + +@Serializable +data class SubscriptionMemberChatMemberImpl( + @SerialName(userField) + override val user: User, + @SerialName(untilDateField) + @Serializable(TelegramDateSerializer::class) + override val untilDate: TelegramDate +) : SubscriptionMemberChatMember { + @SerialName(statusField) + @Required + @EncodeDefault + override val status: ChatMember.Status = ChatMember.Status.SubscriptionMember +} diff --git a/tgbotapi.utils/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/utils/ClassCastsNew.kt b/tgbotapi.utils/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/utils/ClassCastsNew.kt index 3386b01d4a..3525e7e1a1 100644 --- a/tgbotapi.utils/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/utils/ClassCastsNew.kt +++ b/tgbotapi.utils/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/utils/ClassCastsNew.kt @@ -170,6 +170,7 @@ import dev.inmo.tgbotapi.types.chat.member.MemberChatMember import dev.inmo.tgbotapi.types.chat.member.OwnerChatMember import dev.inmo.tgbotapi.types.chat.member.RestrictedChatMember import dev.inmo.tgbotapi.types.chat.member.SpecialRightsChatMember +import dev.inmo.tgbotapi.types.chat.member.SubscriptionMemberChatMember import dev.inmo.tgbotapi.types.dice.BasketballDiceAnimationType import dev.inmo.tgbotapi.types.dice.BowlingDiceAnimationType import dev.inmo.tgbotapi.types.dice.CubeDiceAnimationType @@ -772,6 +773,18 @@ public inline fun OptionallyWithUser.ifSpecialRightsChatMember(block: (SpecialRightsChatMember) -> T): T? = specialRightsChatMemberOrNull() ?.let(block) +public inline fun OptionallyWithUser.subscriptionMemberChatMemberOrNull(): + SubscriptionMemberChatMember? = this as? + dev.inmo.tgbotapi.types.chat.member.SubscriptionMemberChatMember + +public inline fun OptionallyWithUser.subscriptionMemberChatMemberOrThrow(): + SubscriptionMemberChatMember = this as + dev.inmo.tgbotapi.types.chat.member.SubscriptionMemberChatMember + +public inline fun + OptionallyWithUser.ifSubscriptionMemberChatMember(block: (SubscriptionMemberChatMember) -> T): + T? = subscriptionMemberChatMemberOrNull() ?.let(block) + public inline fun OptionallyWithUser.leftChatMemberEventOrNull(): LeftChatMemberEvent? = this as? dev.inmo.tgbotapi.types.message.ChatEvents.LeftChatMemberEvent