1
0
mirror of https://github.com/InsanusMokrassar/TelegramBotAPI.git synced 2024-12-23 09:07:12 +00:00

some progress on business chats

This commit is contained in:
InsanusMokrassar 2024-04-16 19:25:18 +06:00
parent 8de584b292
commit c1f40c1030
8 changed files with 91 additions and 14 deletions

View File

@ -2,6 +2,7 @@ package dev.inmo.tgbotapi.requests.chat.get
import dev.inmo.tgbotapi.abstracts.types.ChatRequest import dev.inmo.tgbotapi.abstracts.types.ChatRequest
import dev.inmo.tgbotapi.requests.abstracts.SimpleRequest import dev.inmo.tgbotapi.requests.abstracts.SimpleRequest
import dev.inmo.tgbotapi.types.BusinessChatId
import dev.inmo.tgbotapi.types.ChatIdWithThreadId import dev.inmo.tgbotapi.types.ChatIdWithThreadId
import dev.inmo.tgbotapi.types.ChatIdentifier import dev.inmo.tgbotapi.types.ChatIdentifier
import dev.inmo.tgbotapi.types.chat.ExtendedChatSerializer import dev.inmo.tgbotapi.types.chat.ExtendedChatSerializer
@ -16,10 +17,10 @@ data class GetChat(
): ChatRequest, SimpleRequest<ExtendedChat> { ): ChatRequest, SimpleRequest<ExtendedChat> {
override fun method(): String = "getChat" override fun method(): String = "getChat"
@Transient @Transient
override val resultDeserializer: DeserializationStrategy<ExtendedChat> = if (chatId is ChatIdWithThreadId) { override val resultDeserializer: DeserializationStrategy<ExtendedChat> = when {
ExtendedChatSerializer.BasedOnForumThread(chatId.threadId) chatId is ChatIdWithThreadId -> ExtendedChatSerializer.BasedOnForumThread(chatId.threadId)
} else { chatId is BusinessChatId -> ExtendedChatSerializer.BasedOnBusinessConnection(chatId.businessId)
ExtendedChatSerializer.Companion else -> ExtendedChatSerializer.Companion
} }
override val requestSerializer: SerializationStrategy<*> override val requestSerializer: SerializationStrategy<*>
get() = serializer() get() = serializer()

View File

@ -1,6 +1,7 @@
package dev.inmo.tgbotapi.types package dev.inmo.tgbotapi.types
import dev.inmo.micro_utils.common.Warning import dev.inmo.micro_utils.common.Warning
import dev.inmo.tgbotapi.types.business_connection.BusinessConnectionId
import dev.inmo.tgbotapi.types.chat.User import dev.inmo.tgbotapi.types.chat.User
import dev.inmo.tgbotapi.utils.RiskFeature import dev.inmo.tgbotapi.utils.RiskFeature
import dev.inmo.tgbotapi.utils.internal.ClassCastsIncluded import dev.inmo.tgbotapi.utils.internal.ClassCastsIncluded
@ -29,12 +30,17 @@ sealed interface IdChatIdentifier : ChatIdentifier {
abstract val chatId: RawChatId abstract val chatId: RawChatId
val threadId: MessageThreadId? val threadId: MessageThreadId?
get() = null get() = null
val businessId: BusinessConnectionId?
get() = null
companion object { companion object {
operator fun invoke(chatId: RawChatId) = ChatId(chatId) operator fun invoke(chatId: RawChatId) = ChatId(chatId)
operator fun invoke(chatId: RawChatId, threadId: MessageThreadId?) = threadId ?.let { operator fun invoke(chatId: RawChatId, threadId: MessageThreadId?) = threadId ?.let {
ChatIdWithThreadId(chatId, threadId) ChatIdWithThreadId(chatId, threadId)
} ?: ChatId(chatId) } ?: ChatId(chatId)
operator fun invoke(chatId: RawChatId, businessConnectionId: BusinessConnectionId?) = businessConnectionId ?.let {
BusinessChatId(chatId, businessConnectionId)
} ?: ChatId(chatId)
} }
} }
@ -52,6 +58,16 @@ value class ChatIdWithThreadId(val chatIdWithThreadId: Pair<RawChatId, MessageTh
constructor(chatId: RawChatId, threadId: MessageThreadId): this(chatId to threadId) constructor(chatId: RawChatId, threadId: MessageThreadId): this(chatId to threadId)
} }
@Serializable(ChatIdentifierSerializer::class)
@JvmInline
value class BusinessChatId(val chatIdWithBusinessConnectionId: Pair<RawChatId, BusinessConnectionId>) : IdChatIdentifier {
override val chatId: RawChatId
get() = chatIdWithBusinessConnectionId.first
override val businessId: BusinessConnectionId
get() = chatIdWithBusinessConnectionId.second
constructor(chatId: RawChatId, businessConnectionId: BusinessConnectionId): this(chatId to businessConnectionId)
}
val ChatIdentifier.threadId: MessageThreadId? val ChatIdentifier.threadId: MessageThreadId?
get() = (this as? IdChatIdentifier) ?.threadId get() = (this as? IdChatIdentifier) ?.threadId
@ -59,9 +75,11 @@ val ChatIdentifier.threadId: MessageThreadId?
fun IdChatIdentifier.toChatId() = when (this) { fun IdChatIdentifier.toChatId() = when (this) {
is ChatId -> this is ChatId -> this
is ChatIdWithThreadId -> ChatId(chatId) is ChatIdWithThreadId -> ChatId(chatId)
is BusinessChatId -> ChatId(chatId)
} }
fun IdChatIdentifier.toChatWithThreadId(threadId: MessageThreadId) = IdChatIdentifier(chatId, threadId) fun IdChatIdentifier.toChatWithThreadId(threadId: MessageThreadId) = IdChatIdentifier(chatId, threadId)
fun IdChatIdentifier.toBusinessChatId(businessConnectionId: BusinessConnectionId) = IdChatIdentifier(chatId, businessConnectionId)
/** /**
* https://core.telegram.org/bots/api#formatting-options * https://core.telegram.org/bots/api#formatting-options
@ -145,14 +163,22 @@ object FullChatIdentifierSerializer : KSerializer<ChatIdentifier> {
ChatId(RawChatId(it)) ChatId(RawChatId(it))
} ?:let { } ?:let {
val splitted = id.content.split("/") val splitted = id.content.split("/")
if (splitted.size == 2) { when (splitted.size) {
val (chatId, threadId) = splitted 2 -> {
ChatIdWithThreadId( val (chatId, threadId) = splitted
chatId.toLongOrNull() ?.let(::RawChatId) ?: return@let null, ChatIdWithThreadId(
threadId.toLongOrNull() ?.let(::MessageThreadId) ?: return@let null chatId.toLongOrNull() ?.let(::RawChatId) ?: return@let null,
) threadId.toLongOrNull() ?.let(::MessageThreadId) ?: return@let null
} else { )
null }
3 -> {
val (chatId, _, businessConnectionId) = splitted
BusinessChatId(
chatId.toLongOrNull() ?.let(::RawChatId) ?: return@let null,
businessConnectionId.let(::BusinessConnectionId) ?: return@let null
)
}
else -> null
} }
} ?: id.content.let { } ?: id.content.let {
if (!it.startsWith("@")) { if (!it.startsWith("@")) {
@ -167,6 +193,7 @@ object FullChatIdentifierSerializer : KSerializer<ChatIdentifier> {
when (value) { when (value) {
is ChatId -> encoder.encodeLong(value.chatId.long) is ChatId -> encoder.encodeLong(value.chatId.long)
is ChatIdWithThreadId -> encoder.encodeString("${value.chatId}/${value.threadId}") is ChatIdWithThreadId -> encoder.encodeString("${value.chatId}/${value.threadId}")
is BusinessChatId -> encoder.encodeString("${value.chatId}//${value.businessId}")
is Username -> encoder.encodeString(value.full) is Username -> encoder.encodeString(value.full)
} }
} }

View File

@ -7,4 +7,8 @@ import kotlin.jvm.JvmInline
@JvmInline @JvmInline
value class BusinessConnectionId( value class BusinessConnectionId(
val string: String val string: String
) ) {
override fun toString(): String {
return string
}
}

View File

@ -16,6 +16,12 @@ sealed interface PrivateChat : Chat, UsernameChat {
val lastName: String val lastName: String
} }
@Serializable(ChatSerializer::class)
sealed interface BusinessChat : Chat {
override val id: BusinessChatId
val original: PrivateChat
}
@Serializable(ChatSerializer::class) @Serializable(ChatSerializer::class)
sealed interface PublicChat : Chat { sealed interface PublicChat : Chat {
val title: String val title: String

View File

@ -1,6 +1,7 @@
package dev.inmo.tgbotapi.types.chat package dev.inmo.tgbotapi.types.chat
import dev.inmo.tgbotapi.types.* import dev.inmo.tgbotapi.types.*
import dev.inmo.tgbotapi.types.business_connection.BusinessConnectionId
import dev.inmo.tgbotapi.utils.RiskFeature import dev.inmo.tgbotapi.utils.RiskFeature
import dev.inmo.tgbotapi.utils.nonstrictJsonFormat import dev.inmo.tgbotapi.utils.nonstrictJsonFormat
import kotlinx.serialization.* import kotlinx.serialization.*
@ -103,10 +104,17 @@ object PreviewChatSerializer : KSerializer<PreviewChat> {
val type = decodedJson[typeField] ?.jsonPrimitive ?.content ?.asChatType ?: error("Field $typeField must be presented, but absent in $decodedJson") val type = decodedJson[typeField] ?.jsonPrimitive ?.content ?.asChatType ?: error("Field $typeField must be presented, but absent in $decodedJson")
val isForum = decodedJson[isForumField] ?.jsonPrimitive ?.booleanOrNull == true val isForum = decodedJson[isForumField] ?.jsonPrimitive ?.booleanOrNull == true
val isBusiness = decodedJson[chatIdField] ?.jsonPrimitive ?.contentOrNull ?.contains("//") == true
return when (type) { return when (type) {
ChatType.Sender -> formatter.decodeFromJsonElement(PrivateChatImpl.serializer(), decodedJson) ChatType.Sender -> formatter.decodeFromJsonElement(PrivateChatImpl.serializer(), decodedJson)
ChatType.Private -> formatter.decodeFromJsonElement(PrivateChatImpl.serializer(), decodedJson) ChatType.Private -> {
if (isBusiness) {
formatter.decodeFromJsonElement(BusinessChatImpl.serializer(), decodedJson)
} else {
formatter.decodeFromJsonElement(PrivateChatImpl.serializer(), decodedJson)
}
}
ChatType.Group -> formatter.decodeFromJsonElement(GroupChatImpl.serializer(), decodedJson) ChatType.Group -> formatter.decodeFromJsonElement(GroupChatImpl.serializer(), decodedJson)
ChatType.Supergroup -> if (isForum) { ChatType.Supergroup -> if (isForum) {
formatter.decodeFromJsonElement(ForumChatImpl.serializer(), decodedJson) formatter.decodeFromJsonElement(ForumChatImpl.serializer(), decodedJson)
@ -125,6 +133,7 @@ object PreviewChatSerializer : KSerializer<PreviewChat> {
override fun serialize(encoder: Encoder, value: PreviewChat) { override fun serialize(encoder: Encoder, value: PreviewChat) {
when (value) { when (value) {
is PrivateChatImpl -> PrivateChatImpl.serializer().serialize(encoder, value) is PrivateChatImpl -> PrivateChatImpl.serializer().serialize(encoder, value)
is BusinessChatImpl -> BusinessChatImpl.serializer().serialize(encoder, value)
is GroupChatImpl -> GroupChatImpl.serializer().serialize(encoder, value) is GroupChatImpl -> GroupChatImpl.serializer().serialize(encoder, value)
is SupergroupChatImpl -> SupergroupChatImpl.serializer().serialize(encoder, value) is SupergroupChatImpl -> SupergroupChatImpl.serializer().serialize(encoder, value)
is ForumChatImpl -> ForumChatImpl.serializer().serialize(encoder, value) is ForumChatImpl -> ForumChatImpl.serializer().serialize(encoder, value)
@ -190,6 +199,19 @@ sealed class ExtendedChatSerializer : KSerializer<ExtendedChat> {
} }
} }
} }
class BasedOnBusinessConnection(private val businessConnectionId: BusinessConnectionId) : ExtendedChatSerializer() {
override fun deserialize(decoder: Decoder): ExtendedChat {
return super.deserialize(decoder).let {
if (it is ExtendedPrivateChatImpl) {
it.copy(
id = (it.id as? BusinessChatId) ?: BusinessChatId(it.id.chatId, businessConnectionId)
)
} else {
it
}
}
}
}
companion object : ExtendedChatSerializer() companion object : ExtendedChatSerializer()
} }

View File

@ -93,3 +93,8 @@ sealed interface ExtendedForumChat : ExtendedSupergroupChat, ForumChat
sealed interface ExtendedChatWithUsername : UsernameChat, ExtendedChat { sealed interface ExtendedChatWithUsername : UsernameChat, ExtendedChat {
val activeUsernames: List<Username> val activeUsernames: List<Username>
} }
@Serializable(ExtendedChatSerializer.Companion::class)
sealed interface ExtendedBusinessChat : BusinessChat, ExtendedChat {
override val original: ExtendedPrivateChat
}

View File

@ -30,6 +30,15 @@ data class PrivateChatImpl(
override val lastName: String = "" override val lastName: String = ""
) : PreviewPrivateChat ) : PreviewPrivateChat
@Serializable
@RiskFeature("This class is a subject of changes. It is better to use PrivateChat due")
data class BusinessChatImpl(
@SerialName(idField)
override val id: BusinessChatId,
@SerialName(firstNameField)
override val original: PreviewPrivateChat
) : PreviewBusinessChat
@Serializable @Serializable
@RiskFeature("This class is a subject of changes. It is better to use SupergroupChat due") @RiskFeature("This class is a subject of changes. It is better to use SupergroupChat due")
data class SupergroupChatImpl( data class SupergroupChatImpl(

View File

@ -11,6 +11,9 @@ sealed interface PreviewUsernameChat : PreviewChat, UsernameChat
@Serializable(PreviewChatSerializer::class) @Serializable(PreviewChatSerializer::class)
sealed interface PreviewPrivateChat : PreviewUsernameChat, PrivateChat sealed interface PreviewPrivateChat : PreviewUsernameChat, PrivateChat
@Serializable(PreviewChatSerializer::class)
sealed interface PreviewBusinessChat : BusinessChat, PreviewChat
@Serializable(PreviewChatSerializer::class) @Serializable(PreviewChatSerializer::class)
sealed interface PreviewPublicChat : PreviewChat, PublicChat sealed interface PreviewPublicChat : PreviewChat, PublicChat