2020-10-04 11:06:30 +00:00
|
|
|
package dev.inmo.tgbotapi.types
|
2018-12-26 08:07:24 +00:00
|
|
|
|
2021-02-09 11:15:28 +00:00
|
|
|
import dev.inmo.micro_utils.common.Warning
|
2022-04-21 18:16:41 +00:00
|
|
|
import dev.inmo.tgbotapi.types.chat.User
|
2021-05-29 09:34:14 +00:00
|
|
|
import dev.inmo.tgbotapi.utils.RiskFeature
|
2022-11-10 10:24:20 +00:00
|
|
|
import dev.inmo.tgbotapi.utils.internal.ClassCastsIncluded
|
2021-06-28 05:12:51 +00:00
|
|
|
import kotlinx.serialization.KSerializer
|
|
|
|
import kotlinx.serialization.Serializable
|
2021-05-29 09:34:14 +00:00
|
|
|
import kotlinx.serialization.descriptors.SerialDescriptor
|
2020-08-18 06:50:11 +00:00
|
|
|
import kotlinx.serialization.encoding.Decoder
|
|
|
|
import kotlinx.serialization.encoding.Encoder
|
2020-11-05 18:12:14 +00:00
|
|
|
import kotlinx.serialization.json.JsonPrimitive
|
|
|
|
import kotlinx.serialization.json.longOrNull
|
2022-11-10 09:56:38 +00:00
|
|
|
import kotlin.jvm.JvmInline
|
2018-12-26 08:07:24 +00:00
|
|
|
|
2022-07-09 16:43:19 +00:00
|
|
|
const val internalLinkBeginning = "https://t.me"
|
|
|
|
|
2018-12-26 08:07:24 +00:00
|
|
|
@Serializable(ChatIdentifierSerializer::class)
|
2022-11-10 10:24:20 +00:00
|
|
|
@ClassCastsIncluded
|
2022-11-10 09:56:38 +00:00
|
|
|
sealed interface ChatIdentifier
|
2018-12-26 08:07:24 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Also used as User Identifier
|
|
|
|
*/
|
|
|
|
@Serializable(ChatIdentifierSerializer::class)
|
2022-11-10 09:56:38 +00:00
|
|
|
sealed interface IdChatIdentifier : ChatIdentifier {
|
|
|
|
abstract val chatId: Identifier
|
|
|
|
val threadId: MessageThreadId?
|
|
|
|
get() = null
|
|
|
|
|
|
|
|
companion object {
|
|
|
|
operator fun invoke(chatId: Identifier) = ChatId(chatId)
|
2022-11-11 06:59:42 +00:00
|
|
|
operator fun invoke(chatId: Identifier, threadId: MessageThreadId?) = threadId ?.let {
|
|
|
|
ChatIdWithThreadId(chatId, threadId)
|
|
|
|
} ?: ChatId(chatId)
|
2022-11-10 09:56:38 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
@Serializable(ChatIdentifierSerializer::class)
|
|
|
|
@JvmInline
|
|
|
|
value class ChatId(override val chatId: Identifier) : IdChatIdentifier
|
|
|
|
|
|
|
|
@Serializable(ChatIdentifierSerializer::class)
|
|
|
|
@JvmInline
|
|
|
|
value class ChatIdWithThreadId(val chatIdWithThreadId: Pair<Identifier, MessageThreadId>) : IdChatIdentifier {
|
|
|
|
override val chatId: Identifier
|
|
|
|
get() = chatIdWithThreadId.first
|
|
|
|
override val threadId: MessageThreadId
|
|
|
|
get() = chatIdWithThreadId.second
|
|
|
|
|
|
|
|
constructor(chatId: Identifier, threadId: MessageThreadId): this(chatId to threadId)
|
|
|
|
}
|
|
|
|
|
|
|
|
val ChatIdentifier.threadId: MessageThreadId?
|
|
|
|
get() = (this as? IdChatIdentifier) ?.threadId
|
2018-12-26 08:07:24 +00:00
|
|
|
|
2021-02-09 11:15:28 +00:00
|
|
|
/**
|
|
|
|
* https://core.telegram.org/bots/api#formatting-options
|
|
|
|
*/
|
|
|
|
@Warning("This API have restrictions in Telegram System")
|
2022-07-09 16:43:19 +00:00
|
|
|
val Identifier.userLink: String
|
2021-02-09 11:15:28 +00:00
|
|
|
get() = "tg://user?id=$this"
|
|
|
|
/**
|
|
|
|
* https://core.telegram.org/bots/api#formatting-options
|
|
|
|
*/
|
|
|
|
@Warning("This API have restrictions in Telegram System")
|
2022-07-09 16:43:19 +00:00
|
|
|
val UserId.userLink: String
|
|
|
|
get() = chatId.userLink
|
2021-02-09 11:15:28 +00:00
|
|
|
val User.link: String
|
2022-07-09 16:43:19 +00:00
|
|
|
get() = id.userLink
|
|
|
|
|
2022-11-10 09:56:38 +00:00
|
|
|
typealias UserId = IdChatIdentifier
|
2018-12-26 08:07:24 +00:00
|
|
|
|
2022-11-10 09:56:38 +00:00
|
|
|
fun Identifier.toChatId(): IdChatIdentifier = ChatId(this)
|
|
|
|
fun Int.toChatId(): IdChatIdentifier = toLong().toChatId()
|
|
|
|
fun Byte.toChatId(): IdChatIdentifier = toLong().toChatId()
|
2018-12-26 08:07:24 +00:00
|
|
|
|
|
|
|
@Serializable(ChatIdentifierSerializer::class)
|
2019-01-21 00:23:27 +00:00
|
|
|
data class Username(
|
2019-02-18 06:35:58 +00:00
|
|
|
val username: String
|
2022-11-10 09:56:38 +00:00
|
|
|
) : ChatIdentifier {
|
2022-02-07 12:08:06 +00:00
|
|
|
val usernameWithoutAt
|
|
|
|
get() = username.dropWhile { it == '@' }
|
|
|
|
|
2019-02-18 06:35:58 +00:00
|
|
|
init {
|
|
|
|
if (!username.startsWith("@")) {
|
|
|
|
throw IllegalArgumentException("Username must starts with `@`")
|
2019-02-18 04:53:01 +00:00
|
|
|
}
|
2018-12-26 08:07:24 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-06-02 14:57:52 +00:00
|
|
|
fun String.toUsername(): Username = Username(this)
|
2018-12-26 08:07:24 +00:00
|
|
|
|
2021-05-29 09:34:14 +00:00
|
|
|
@RiskFeature
|
|
|
|
object ChatIdentifierSerializer : KSerializer<ChatIdentifier> {
|
|
|
|
private val internalSerializer = JsonPrimitive.serializer()
|
|
|
|
override val descriptor: SerialDescriptor = internalSerializer.descriptor
|
2019-02-21 06:21:33 +00:00
|
|
|
override fun deserialize(decoder: Decoder): ChatIdentifier {
|
2021-05-29 09:34:14 +00:00
|
|
|
val id = internalSerializer.deserialize(decoder)
|
2022-11-11 15:44:37 +00:00
|
|
|
|
2020-03-22 09:53:37 +00:00
|
|
|
return id.longOrNull ?.let {
|
2018-12-26 08:07:24 +00:00
|
|
|
ChatId(it)
|
2020-03-22 09:53:37 +00:00
|
|
|
} ?: id.content.let {
|
|
|
|
if (!it.startsWith("@")) {
|
|
|
|
Username("@$it")
|
|
|
|
} else {
|
|
|
|
Username(it)
|
|
|
|
}
|
2019-02-18 06:35:58 +00:00
|
|
|
}
|
2018-12-26 08:07:24 +00:00
|
|
|
}
|
|
|
|
|
2020-03-22 07:37:01 +00:00
|
|
|
override fun serialize(encoder: Encoder, value: ChatIdentifier) {
|
|
|
|
when (value) {
|
2022-11-10 09:56:38 +00:00
|
|
|
is IdChatIdentifier -> encoder.encodeLong(value.chatId)
|
2020-03-22 07:37:01 +00:00
|
|
|
is Username -> encoder.encodeString(value.username)
|
2018-12-26 08:07:24 +00:00
|
|
|
}
|
|
|
|
}
|
2021-05-29 09:34:14 +00:00
|
|
|
}
|
2022-11-11 15:44:37 +00:00
|
|
|
|
|
|
|
@RiskFeature
|
|
|
|
object FullChatIdentifierSerializer : KSerializer<ChatIdentifier> {
|
|
|
|
private val internalSerializer = JsonPrimitive.serializer()
|
|
|
|
override val descriptor: SerialDescriptor = internalSerializer.descriptor
|
|
|
|
override fun deserialize(decoder: Decoder): ChatIdentifier {
|
|
|
|
val id = internalSerializer.deserialize(decoder)
|
|
|
|
|
|
|
|
return id.longOrNull ?.let {
|
|
|
|
ChatId(it)
|
|
|
|
} ?:let {
|
|
|
|
val splitted = id.content.split("/")
|
|
|
|
if (splitted.size == 2) {
|
|
|
|
val (chatId, threadId) = splitted
|
|
|
|
ChatIdWithThreadId(
|
|
|
|
chatId.toLongOrNull() ?: return@let null,
|
|
|
|
threadId.toLongOrNull() ?: return@let null
|
|
|
|
)
|
|
|
|
} else {
|
|
|
|
null
|
|
|
|
}
|
|
|
|
} ?: id.content.let {
|
|
|
|
if (!it.startsWith("@")) {
|
|
|
|
Username("@$it")
|
|
|
|
} else {
|
|
|
|
Username(it)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
override fun serialize(encoder: Encoder, value: ChatIdentifier) {
|
|
|
|
when (value) {
|
|
|
|
is ChatId -> encoder.encodeLong(value.chatId)
|
|
|
|
is ChatIdWithThreadId -> encoder.encodeString("${value.chatId}/${value.threadId}")
|
|
|
|
is Username -> encoder.encodeString(value.username)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|