1
0
mirror of https://github.com/InsanusMokrassar/TelegramBotAPI.git synced 2026-03-03 09:22:22 +00:00

some additions(need to check all this commit)

This commit is contained in:
2026-02-10 16:02:28 +06:00
parent cc5056b685
commit e40424b26a
21 changed files with 559 additions and 14 deletions

View File

@@ -37,6 +37,8 @@ data class ForwardMessage(
val disableNotification: Boolean = false,
@SerialName(protectContentField)
override val protectContent: Boolean = false,
@SerialName(messageEffectIdField)
val effectId: EffectId? = null,
@SerialName(suggestedPostParametersField)
override val suggestedPostParameters: SuggestedPostParameters? = null
): SimpleRequest<PossiblyForwardedMessage>,

View File

@@ -9,7 +9,10 @@ import dev.inmo.tgbotapi.types.excludeUnsavedField
import dev.inmo.tgbotapi.types.excludeSavedField
import dev.inmo.tgbotapi.types.excludeUnlimitedField
import dev.inmo.tgbotapi.types.excludeLimitedField
import dev.inmo.tgbotapi.types.excludeLimitedUpgradableField
import dev.inmo.tgbotapi.types.excludeLimitedNonUpgradableField
import dev.inmo.tgbotapi.types.excludeUniqueField
import dev.inmo.tgbotapi.types.excludeFromBlockchainField
import dev.inmo.tgbotapi.types.sortByPriceField
import dev.inmo.tgbotapi.types.offsetField
import dev.inmo.tgbotapi.types.limitField
@@ -29,10 +32,17 @@ data class GetBusinessAccountGifts(
val excludeSaved: Boolean = false,
@SerialName(excludeUnlimitedField)
val excludeUnlimited: Boolean = false,
@Deprecated("Use excludeLimitedUpgradable and excludeLimitedNonUpgradable instead")
@SerialName(excludeLimitedField)
val excludeLimited: Boolean = false,
@SerialName(excludeLimitedUpgradableField)
val excludeLimitedUpgradable: Boolean = false,
@SerialName(excludeLimitedNonUpgradableField)
val excludeLimitedNonUpgradable: Boolean = false,
@SerialName(excludeUniqueField)
val excludeUnique: Boolean = false,
@SerialName(excludeFromBlockchainField)
val excludeFromBlockchain: Boolean = false,
@SerialName(sortByPriceField)
val sortByPrice: Boolean = false,
@SerialName(offsetField)

View File

@@ -0,0 +1,38 @@
package dev.inmo.tgbotapi.requests.gifts
import dev.inmo.micro_utils.common.Warning
import dev.inmo.tgbotapi.abstracts.types.ChatRequest
import dev.inmo.tgbotapi.requests.abstracts.SimpleRequest
import dev.inmo.tgbotapi.types.ChatIdentifier
import dev.inmo.tgbotapi.types.OwnedGifts
import dev.inmo.tgbotapi.types.chatIdField
import dev.inmo.tgbotapi.types.gifts.GiftSentOrReceived
import dev.inmo.tgbotapi.types.limitField
import dev.inmo.tgbotapi.types.offsetField
import kotlinx.serialization.DeserializationStrategy
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
import kotlinx.serialization.SerializationStrategy
// TODO::Fix
@Serializable
data class GetChatGifts(
@SerialName(chatIdField)
override val chatId: ChatIdentifier,
@SerialName(offsetField)
val offset: String? = null,
@SerialName(limitField)
val limit: Int? = null,
) : SimpleRequest<OwnedGifts<GiftSentOrReceived>>, ChatRequest {
override fun method(): String = "getChatGifts"
override val resultDeserializer: DeserializationStrategy<OwnedGifts<GiftSentOrReceived>>
get() = Companion.resultSerializer
override val requestSerializer: SerializationStrategy<*>
get() = serializer()
companion object {
@Warning("This API can be changed without any warranties of backward compatibility")
val resultSerializer = OwnedGifts.serializer(GiftSentOrReceived.serializer())
}
}

View File

@@ -0,0 +1,38 @@
package dev.inmo.tgbotapi.requests.gifts
import dev.inmo.micro_utils.common.Warning
import dev.inmo.tgbotapi.requests.abstracts.SimpleRequest
import dev.inmo.tgbotapi.types.OwnedGifts
import dev.inmo.tgbotapi.types.UserId
import dev.inmo.tgbotapi.types.gifts.GiftSentOrReceived
import dev.inmo.tgbotapi.types.limitField
import dev.inmo.tgbotapi.types.offsetField
import dev.inmo.tgbotapi.types.userIdField
import kotlinx.serialization.DeserializationStrategy
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
import kotlinx.serialization.SerializationStrategy
// TODO::Fix
@Serializable
data class GetUserGifts(
@Suppress("SERIALIZER_TYPE_INCOMPATIBLE")
@SerialName(userIdField)
val userId: UserId,
@SerialName(offsetField)
val offset: String? = null,
@SerialName(limitField)
val limit: Int? = null,
) : SimpleRequest<OwnedGifts<GiftSentOrReceived>> {
override fun method(): String = "getUserGifts"
override val resultDeserializer: DeserializationStrategy<OwnedGifts<GiftSentOrReceived>>
get() = Companion.resultSerializer
override val requestSerializer: SerializationStrategy<*>
get() = serializer()
companion object {
@Warning("This API can be changed without any warranties of backward compatibility")
val resultSerializer = OwnedGifts.serializer(GiftSentOrReceived.serializer())
}
}

View File

@@ -95,6 +95,7 @@ fun CopyMessage(
disableNotification: Boolean = false,
protectContent: Boolean = false,
allowPaidBroadcast: Boolean = false,
effectId: EffectId? = null,
suggestedPostParameters: SuggestedPostParameters? = null,
replyParameters: ReplyParameters? = null,
replyMarkup: KeyboardMarkup? = null
@@ -112,6 +113,7 @@ fun CopyMessage(
disableNotification = disableNotification,
protectContent = protectContent,
allowPaidBroadcast = allowPaidBroadcast,
effectId = effectId,
suggestedPostParameters = suggestedPostParameters,
replyParameters = replyParameters,
replyMarkup = replyMarkup
@@ -129,6 +131,7 @@ fun CopyMessage(
disableNotification: Boolean = false,
protectContent: Boolean = false,
allowPaidBroadcast: Boolean = false,
effectId: EffectId? = null,
suggestedPostParameters: SuggestedPostParameters? = null,
replyParameters: ReplyParameters? = null,
replyMarkup: KeyboardMarkup? = null
@@ -146,6 +149,7 @@ fun CopyMessage(
disableNotification = disableNotification,
protectContent = protectContent,
allowPaidBroadcast = allowPaidBroadcast,
effectId = effectId,
suggestedPostParameters = suggestedPostParameters,
replyParameters = replyParameters,
replyMarkup = replyMarkup
@@ -184,6 +188,8 @@ data class CopyMessage internal constructor(
override val protectContent: Boolean = false,
@SerialName(allowPaidBroadcastField)
override val allowPaidBroadcast: Boolean = false,
@SerialName(messageEffectIdField)
val effectId: EffectId? = null,
@SerialName(suggestedPostParametersField)
override val suggestedPostParameters: SuggestedPostParameters? = null,
@SerialName(replyParametersField)

View File

@@ -0,0 +1,146 @@
package dev.inmo.tgbotapi.requests.send
import dev.inmo.tgbotapi.abstracts.types.LinkPreviewOptionsContainer
import dev.inmo.tgbotapi.requests.send.abstracts.*
import dev.inmo.tgbotapi.types.*
import dev.inmo.tgbotapi.types.business_connection.BusinessConnectionId
import dev.inmo.tgbotapi.types.message.textsources.TextSourcesList
import dev.inmo.tgbotapi.types.message.ParseMode
import dev.inmo.tgbotapi.types.message.parseModeField
import dev.inmo.tgbotapi.types.buttons.KeyboardMarkup
import dev.inmo.tgbotapi.types.message.*
import dev.inmo.tgbotapi.types.message.RawMessageEntity
import dev.inmo.tgbotapi.types.message.abstracts.ContentMessage
import dev.inmo.tgbotapi.types.message.abstracts.TelegramBotAPIMessageDeserializationStrategyClass
import dev.inmo.tgbotapi.types.message.content.TextContent
import dev.inmo.tgbotapi.types.message.toRawMessageEntities
import dev.inmo.tgbotapi.utils.extensions.makeString
import dev.inmo.tgbotapi.utils.throwRangeError
import kotlinx.serialization.*
internal val TextContentMessageDraftResultDeserializer: DeserializationStrategy<ContentMessage<TextContent>>
= TelegramBotAPIMessageDeserializationStrategyClass()
fun SendMessageDraft(
chatId: ChatIdentifier,
text: String,
parseMode: ParseMode? = null,
linkPreviewOptions: LinkPreviewOptions? = null,
threadId: MessageThreadId? = chatId.threadId,
directMessageThreadId: DirectMessageThreadId? = chatId.directMessageThreadId,
businessConnectionId: BusinessConnectionId? = chatId.businessConnectionId,
disableNotification: Boolean = false,
protectContent: Boolean = false,
allowPaidBroadcast: Boolean = false,
effectId: EffectId? = null,
suggestedPostParameters: SuggestedPostParameters? = null,
replyParameters: ReplyParameters? = null,
replyMarkup: KeyboardMarkup? = null
) = SendMessageDraft(
chatId = chatId,
text = text,
parseMode = parseMode,
rawEntities = null,
threadId = threadId,
directMessageThreadId = directMessageThreadId,
businessConnectionId = businessConnectionId,
linkPreviewOptions = linkPreviewOptions,
disableNotification = disableNotification,
protectContent = protectContent,
allowPaidBroadcast = allowPaidBroadcast,
effectId = effectId,
suggestedPostParameters = suggestedPostParameters,
replyParameters = replyParameters,
replyMarkup = replyMarkup
)
fun SendMessageDraft(
chatId: ChatIdentifier,
entities: TextSourcesList,
linkPreviewOptions: LinkPreviewOptions? = null,
threadId: MessageThreadId? = chatId.threadId,
directMessageThreadId: DirectMessageThreadId? = chatId.directMessageThreadId,
businessConnectionId: BusinessConnectionId? = chatId.businessConnectionId,
disableNotification: Boolean = false,
protectContent: Boolean = false,
allowPaidBroadcast: Boolean = false,
effectId: EffectId? = null,
suggestedPostParameters: SuggestedPostParameters? = null,
replyParameters: ReplyParameters? = null,
replyMarkup: KeyboardMarkup? = null
) = SendMessageDraft(
chatId = chatId,
text = entities.makeString(),
parseMode = null,
rawEntities = entities.toRawMessageEntities(),
threadId = threadId,
directMessageThreadId = directMessageThreadId,
businessConnectionId = businessConnectionId,
linkPreviewOptions = linkPreviewOptions,
disableNotification = disableNotification,
protectContent = protectContent,
allowPaidBroadcast = allowPaidBroadcast,
effectId = effectId,
suggestedPostParameters = suggestedPostParameters,
replyParameters = replyParameters,
replyMarkup = replyMarkup
)
@ConsistentCopyVisibility
@Serializable
data class SendMessageDraft internal constructor(
@SerialName(chatIdField)
override val chatId: ChatIdentifier,
@SerialName(textField)
override val text: String,
@SerialName(parseModeField)
override val parseMode: ParseMode? = null,
@SerialName(entitiesField)
private val rawEntities: List<RawMessageEntity>? = null,
@OptIn(ExperimentalSerializationApi::class)
@SerialName(messageThreadIdField)
@EncodeDefault
override val threadId: MessageThreadId? = chatId.threadId,
@OptIn(ExperimentalSerializationApi::class)
@EncodeDefault
@SerialName(directMessagesTopicIdField)
override val directMessageThreadId: DirectMessageThreadId? = chatId.directMessageThreadId,
@SerialName(businessConnectionIdField)
override val businessConnectionId: BusinessConnectionId? = chatId.businessConnectionId,
@SerialName(linkPreviewOptionsField)
override val linkPreviewOptions: LinkPreviewOptions? = null,
@SerialName(disableNotificationField)
override val disableNotification: Boolean = false,
@SerialName(protectContentField)
override val protectContent: Boolean = false,
@SerialName(allowPaidBroadcastField)
override val allowPaidBroadcast: Boolean = false,
@SerialName(messageEffectIdField)
override val effectId: EffectId? = null,
@SerialName(suggestedPostParametersField)
override val suggestedPostParameters: SuggestedPostParameters? = null,
@SerialName(replyParametersField)
override val replyParameters: ReplyParameters? = null,
@SerialName(replyMarkupField)
override val replyMarkup: KeyboardMarkup? = null
) : SendContentMessageRequest<ContentMessage<TextContent>>,
ReplyingMarkupSendMessageRequest<ContentMessage<TextContent>>,
TextableSendMessageRequest<ContentMessage<TextContent>>,
LinkPreviewOptionsContainer
{
override val textSources: TextSourcesList? by lazy {
rawEntities ?.asTextSources(text)
}
init {
if (text.length !in textLength) {
throwRangeError("Text length", textLength, text.length)
}
}
override fun method(): String = "sendMessageDraft"
override val resultDeserializer: DeserializationStrategy<ContentMessage<TextContent>>
get() = TextContentMessageDraftResultDeserializer
override val requestSerializer: SerializationStrategy<*>
get() = serializer()
}

View File

@@ -0,0 +1,31 @@
package dev.inmo.tgbotapi.requests.stories
import dev.inmo.tgbotapi.abstracts.types.WithBusinessConnectionId
import dev.inmo.tgbotapi.requests.abstracts.SimpleRequest
import dev.inmo.tgbotapi.types.StoryId
import dev.inmo.tgbotapi.types.businessConnectionIdField
import dev.inmo.tgbotapi.types.business_connection.BusinessConnectionId
import dev.inmo.tgbotapi.types.fromBusinessConnectionIdField
import dev.inmo.tgbotapi.types.storyIdField
import dev.inmo.tgbotapi.types.stories.Story
import kotlinx.serialization.DeserializationStrategy
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
import kotlinx.serialization.SerializationStrategy
@Serializable
data class RepostStory(
@SerialName(businessConnectionIdField)
override val businessConnectionId: BusinessConnectionId,
@SerialName(fromBusinessConnectionIdField)
val fromBusinessConnectionId: BusinessConnectionId,
@SerialName(storyIdField)
val storyId: StoryId,
) : SimpleRequest<Story>, WithBusinessConnectionId {
override fun method(): String = "repostStory"
override val requestSerializer: SerializationStrategy<*>
get() = serializer()
override val resultDeserializer: DeserializationStrategy<Story>
get() = Story.serializer()
}

View File

@@ -190,6 +190,7 @@ const val unrestrictBoostsCountField = "unrestrict_boost_count"
const val customEmojiStickerSetNameField = "custom_emoji_sticker_set_name"
const val iconCustomEmojiIdField = "icon_custom_emoji_id"
const val hasMainWebAppField = "has_main_web_app"
const val hasTopicsEnabledField = "has_topics_enabled"
const val canJoinGroupsField = "can_join_groups"
const val canReadAllGroupMessagesField = "can_read_all_group_messages"
const val canReplyField = "can_reply"
@@ -313,8 +314,10 @@ const val createsJoinRequestField = "creates_join_request"
const val pendingJoinRequestCountField = "pending_join_request_count"
const val memberLimitField = "member_limit"
const val iconColorField = "icon_color"
const val isNameImplicitField = "is_name_implicit"
const val emojiListField = "emoji_list"
const val completedByUserField = "completed_by_user"
const val completedByChatField = "completed_by_chat"
const val completionDateField = "completion_date"
const val titleEntitiesField = "title_entities"
const val tasksField = "tasks"
@@ -533,6 +536,7 @@ const val topicIdField = "topic_id"
const val isPublicField = "is_public"
const val giftField = "gift"
const val giftUpgradeSentField = "gift_upgrade_sent"
const val giftsField = "gifts"
const val rarityPerMilleField = "rarity_per_mille"
const val acceptedGiftTypesField = "accepted_gift_types"
@@ -545,6 +549,8 @@ const val isDirectMessagesField = "is_direct_messages"
const val nextTransferDateField = "next_transfer_date"
const val transferStarCountField = "transfer_star_count"
const val lastResaleStarCountField = "last_resale_star_count"
const val lastResaleCurrencyField = "last_resale_currency"
const val lastResaleAmountField = "last_resale_amount"
const val newOwnerChatIdField = "new_owner_chat_id"
const val pointField = "point"
@@ -649,6 +655,8 @@ const val mediaField = "media"
const val mainFrameTimestampField = "main_frame_timestamp"
const val paidMessageStarCountField = "paid_message_star_count"
const val ratingField = "rating"
const val uniqueGiftColorsField = "unique_gift_colors"
const val paidStarCountField = "paid_star_count"
const val isPaidPostField = "is_paid_post"
@@ -730,31 +738,48 @@ const val upgradeStarCountField = "upgrade_star_count"
const val payToUpgradeField = "pay_for_upgrade"
const val paidMediaField = "paid_media"
const val publisherChatField = "publisher_chat"
const val personalTotalCountField = "personal_total_count"
const val personalRemainingCountField = "personal_remaining_count"
const val isPremiumField2 = "is_premium"
const val hasColorsField = "has_colors"
const val uniqueGiftVariantCountField = "unique_gift_variant_count"
const val uniqueGiftNumberField = "unique_gift_number"
const val isUpgradeSeparateField = "is_upgrade_separate"
const val isFromBlockchainField = "is_from_blockchain"
const val centerColorField = "center_color"
const val edgeColorField = "edge_color"
const val symbolColorField = "symbol_color"
const val textColorField = "text_color"
const val nameColorField = "name_color"
const val baseColorField = "base_color"
const val linkColorField = "link_color"
const val baseNameField = "base_name"
const val numberField = "number"
const val modelField = "model"
const val symbolField = "symbol"
const val backdropField = "backdrop"
const val backgroundField = "background"
const val unlimitedGiftsField = "unlimited_gifts"
const val limitedGiftsField = "limited_gifts"
const val uniqueGiftsField = "unique_gifts"
const val premiumSubscriptionField = "premium_subscription"
const val giftsFromChannelsField = "gifts_from_channels"
const val excludeUnsavedField = "exclude_unsaved"
const val excludeSavedField = "exclude_saved"
const val excludeUnlimitedField = "exclude_unlimited"
const val excludeLimitedField = "exclude_limited"
const val excludeLimitedUpgradableField = "exclude_limited_upgradable"
const val excludeLimitedNonUpgradableField = "exclude_limited_non_upgradable"
const val excludeUniqueField = "exclude_unique"
const val excludeFromBlockchainField = "exclude_from_blockchain"
const val sortByPriceField = "sort_by_price"
const val businessConnectionIdField = "business_connection_id"
const val fromBusinessConnectionIdField = "from_business_connection_id"
const val businessIntroField = "business_intro"
const val businessLocationField = "business_location"
const val businessOpeningHoursField = "business_opening_hours"

View File

@@ -13,7 +13,9 @@ data class ForumTopic(
@SerialName(iconColorField)
val color: RGBColor,
@SerialName(iconCustomEmojiIdField)
val iconEmojiId: CustomEmojiId? = null
val iconEmojiId: CustomEmojiId? = null,
@SerialName(isNameImplicitField)
val isNameImplicit: Boolean = false
) {
companion object {
val CYAN = RGBColor(0x6FB9F0)

View File

@@ -6,6 +6,7 @@ import dev.inmo.tgbotapi.types.business_connection.BusinessLocation
import dev.inmo.tgbotapi.types.business_connection.BusinessOpeningHours
import dev.inmo.tgbotapi.types.colors.ColorId
import dev.inmo.tgbotapi.types.gifts.AcceptedGiftTypes
import dev.inmo.tgbotapi.types.gifts.unique.UniqueGiftColors
import dev.inmo.tgbotapi.types.message.abstracts.Message
import dev.inmo.tgbotapi.types.message.abstracts.TelegramBotAPIMessageDeserializeOnlySerializer
import dev.inmo.tgbotapi.types.reactions.Reaction
@@ -65,7 +66,13 @@ data class ExtendedChannelChatImpl(
@SerialName(hasVisibleHistoryField)
override val newMembersSeeHistory: Boolean = false,
@SerialName(maxReactionCountField)
override val maxReactionsCount: Int = 3
override val maxReactionsCount: Int = 3,
@SerialName(ratingField)
override val rating: UserRating? = null,
@SerialName(paidMessageStarCountField)
override val paidMessageStarCount: Int? = null,
@SerialName(uniqueGiftColorsField)
override val uniqueGiftColors: UniqueGiftColors? = null
) : ExtendedChannelChat
@Serializable
@@ -109,6 +116,12 @@ data class ExtendedGroupChatImpl(
override val maxReactionsCount: Int = 3,
@SerialName(acceptedGiftTypesField)
override val acceptedGiftTypes: AcceptedGiftTypes = AcceptedGiftTypes(),
@SerialName(ratingField)
override val rating: UserRating? = null,
@SerialName(paidMessageStarCountField)
override val paidMessageStarCount: Int? = null,
@SerialName(uniqueGiftColorsField)
override val uniqueGiftColors: UniqueGiftColors? = null
) : ExtendedGroupChat
@Serializable
@@ -289,6 +302,12 @@ data class ExtendedSupergroupChatImpl(
override val maxReactionsCount: Int = 3,
@SerialName(acceptedGiftTypesField)
override val acceptedGiftTypes: AcceptedGiftTypes = AcceptedGiftTypes(),
@SerialName(ratingField)
override val rating: UserRating? = null,
@SerialName(paidMessageStarCountField)
override val paidMessageStarCount: Int? = null,
@SerialName(uniqueGiftColorsField)
override val uniqueGiftColors: UniqueGiftColors? = null
) : ExtendedSupergroupChat
@Serializable
@@ -359,6 +378,12 @@ data class ExtendedForumChatImpl(
override val maxReactionsCount: Int = 3,
@SerialName(acceptedGiftTypesField)
override val acceptedGiftTypes: AcceptedGiftTypes = AcceptedGiftTypes(),
@SerialName(ratingField)
override val rating: UserRating? = null,
@SerialName(paidMessageStarCountField)
override val paidMessageStarCount: Int? = null,
@SerialName(uniqueGiftColorsField)
override val uniqueGiftColors: UniqueGiftColors? = null
) : ExtendedForumChat
@Serializable
@@ -432,6 +457,12 @@ data class ExtendedChannelDirectMessagesChatImpl(
override val maxReactionsCount: Int = 3,
@SerialName(acceptedGiftTypesField)
override val acceptedGiftTypes: AcceptedGiftTypes = AcceptedGiftTypes(),
@SerialName(ratingField)
override val rating: UserRating? = null,
@SerialName(paidMessageStarCountField)
override val paidMessageStarCount: Int? = null,
@SerialName(uniqueGiftColorsField)
override val uniqueGiftColors: UniqueGiftColors? = null
) : ExtendedChannelDirectMessagesChat {
@OptIn(ExperimentalSerializationApi::class)
@SerialName(isDirectMessagesField)
@@ -473,6 +504,8 @@ data class ExtendedBot(
override val maxReactionsCount: Int = 3,
@SerialName(hasMainWebAppField)
val hasMainWebApp: Boolean = false,
@SerialName(hasTopicsEnabledField)
val hasTopicsEnabled: Boolean = false,
@SerialName(acceptedGiftTypesField)
override val acceptedGiftTypes: AcceptedGiftTypes = AcceptedGiftTypes(),
) : Bot(), ExtendedChat {

View File

@@ -6,6 +6,7 @@ import dev.inmo.tgbotapi.types.business_connection.BusinessLocation
import dev.inmo.tgbotapi.types.business_connection.BusinessOpeningHours
import dev.inmo.tgbotapi.types.colors.ColorId
import dev.inmo.tgbotapi.types.gifts.AcceptedGiftTypes
import dev.inmo.tgbotapi.types.gifts.unique.UniqueGiftColors
import dev.inmo.tgbotapi.types.message.abstracts.Message
import dev.inmo.tgbotapi.types.message.abstracts.TelegramBotAPIMessageDeserializeOnlySerializer
import dev.inmo.tgbotapi.types.reactions.Reaction
@@ -85,6 +86,9 @@ sealed interface ExtendedPublicChat : ExtendedChat, PublicChat, ExtendedNonBotCh
val membersHidden: Boolean
val availableReactions: List<Reaction>?
val newMembersSeeHistory: Boolean
val rating: UserRating?
val paidMessageStarCount: Int?
val uniqueGiftColors: UniqueGiftColors?
}
@Suppress("SERIALIZER_TYPE_INCOMPATIBLE")

View File

@@ -143,6 +143,8 @@ data class CommonBot(
@Suppress("SERIALIZER_TYPE_INCOMPATIBLE")
@SerialName(usernameField)
override val username: Username? = null,
@SerialName(hasTopicsEnabledField)
val hasTopicsEnabled: Boolean = false,
) : PreviewBot() {
@SerialName(isBotField)
private val isBot = true

View File

@@ -0,0 +1,14 @@
package dev.inmo.tgbotapi.types.chat
import dev.inmo.tgbotapi.types.countField
import dev.inmo.tgbotapi.types.ratingField
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
@Serializable
data class UserRating(
@SerialName(countField)
val count: Int,
@SerialName(ratingField)
val rating: Double
)

View File

@@ -3,8 +3,10 @@ package dev.inmo.tgbotapi.types.checklists
import dev.inmo.micro_utils.common.Warning
import dev.inmo.tgbotapi.abstracts.TextedInput
import dev.inmo.tgbotapi.types.TelegramDate
import dev.inmo.tgbotapi.types.chat.PreviewChat
import dev.inmo.tgbotapi.types.chat.PreviewUser
import dev.inmo.tgbotapi.types.completedByUserField
import dev.inmo.tgbotapi.types.completedByChatField
import dev.inmo.tgbotapi.types.completionDateField
import dev.inmo.tgbotapi.types.idField
import dev.inmo.tgbotapi.types.message.ParseMode
@@ -130,6 +132,8 @@ sealed interface ChecklistTask : TextedInput {
override val id: ChecklistTaskId,
@SerialName(completedByUserField)
override val completedByUser: PreviewUser,
@SerialName(completedByChatField)
val completedByChat: PreviewChat? = null,
@SerialName(completionDateField)
override val completionDate: TelegramDate,
@SerialName(textEntitiesField)
@@ -145,10 +149,12 @@ sealed interface ChecklistTask : TextedInput {
id: ChecklistTaskId,
text: String,
completedByUser: PreviewUser,
completedByChat: PreviewChat? = null,
completionDate: TelegramDate,
): this(
id,
completedByUser,
completedByChat,
completionDate,
listOf(
RegularTextSource(text)
@@ -176,6 +182,8 @@ sealed interface ChecklistTask : TextedInput {
@Suppress("SERIALIZER_TYPE_INCOMPATIBLE")
@SerialName(completedByUserField)
val completedByUser: PreviewUser? = null,
@SerialName(completedByChatField)
val completedByChat: PreviewChat? = null,
@SerialName(completionDateField)
val completionDate: TelegramDate = TelegramDate(0), // TelegramDate(0) is the default according to https://core.telegram.org/bots/api#checklisttask
)
@@ -190,6 +198,7 @@ sealed interface ChecklistTask : TextedInput {
raw.completedByUser != null -> Done(
id = raw.id,
completedByUser = raw.completedByUser,
completedByChat = raw.completedByChat,
completionDate = raw.completionDate,
textSources = raw.textSources.asTextSources(raw.text),
)
@@ -207,6 +216,7 @@ sealed interface ChecklistTask : TextedInput {
id = value.id,
text = value.text,
completedByUser = value.completedByUser,
completedByChat = (value as? Done)?.completedByChat,
completionDate = value.completionDate ?: TelegramDate(0),
textSources = value.textSources.toRawMessageEntities()
)

View File

@@ -1,5 +1,6 @@
package dev.inmo.tgbotapi.types.gifts
import dev.inmo.tgbotapi.types.giftsFromChannelsField
import dev.inmo.tgbotapi.types.limitedGiftsField
import dev.inmo.tgbotapi.types.premiumSubscriptionField
import dev.inmo.tgbotapi.types.uniqueGiftsField
@@ -17,5 +18,7 @@ data class AcceptedGiftTypes(
@SerialName(uniqueGiftsField)
val uniqueGifts: Boolean = false,
@SerialName(premiumSubscriptionField)
val premiumSubscription: Boolean = false
val premiumSubscription: Boolean = false,
@SerialName(giftsFromChannelsField)
val giftsFromChannels: Boolean = false
)

View File

@@ -4,6 +4,7 @@ import dev.inmo.tgbotapi.types.*
import dev.inmo.tgbotapi.types.chat.PreviewChat
import dev.inmo.tgbotapi.types.files.Sticker
import dev.inmo.tgbotapi.types.gifts.unique.UniqueGiftBackdrop
import dev.inmo.tgbotapi.types.gifts.unique.UniqueGiftColors
import dev.inmo.tgbotapi.types.gifts.unique.UniqueGiftModel
import dev.inmo.tgbotapi.types.gifts.unique.UniqueGiftSymbol
import kotlinx.serialization.KSerializer
@@ -24,6 +25,12 @@ sealed interface Gift {
val totalCount: Int?
val upgradeStarCount: Int?
val remainingCount: Int?
val personalTotalCount: Int?
val personalRemainingCount: Int?
val isPremium: Boolean
val hasColors: Boolean
val background: dev.inmo.tgbotapi.types.gifts.GiftBackground?
val uniqueGiftVariantCount: Int?
@Serializable
data class Unlimited(
@@ -37,6 +44,18 @@ sealed interface Gift {
override val upgradeStarCount: Int? = null,
@SerialName(publisherChatField)
override val publisherChat: PreviewChat? = null,
@SerialName(personalTotalCountField)
override val personalTotalCount: Int? = null,
@SerialName(personalRemainingCountField)
override val personalRemainingCount: Int? = null,
@SerialName(isPremiumField2)
override val isPremium: Boolean = false,
@SerialName(hasColorsField)
override val hasColors: Boolean = false,
@SerialName(backgroundField)
override val background: dev.inmo.tgbotapi.types.gifts.GiftBackground? = null,
@SerialName(uniqueGiftVariantCountField)
override val uniqueGiftVariantCount: Int? = null,
) : Regular {
override val totalCount: Int?
get() = null
@@ -60,6 +79,18 @@ sealed interface Gift {
override val upgradeStarCount: Int? = null,
@SerialName(publisherChatField)
override val publisherChat: PreviewChat? = null,
@SerialName(personalTotalCountField)
override val personalTotalCount: Int? = null,
@SerialName(personalRemainingCountField)
override val personalRemainingCount: Int? = null,
@SerialName(isPremiumField2)
override val isPremium: Boolean = false,
@SerialName(hasColorsField)
override val hasColors: Boolean = false,
@SerialName(backgroundField)
override val background: dev.inmo.tgbotapi.types.gifts.GiftBackground? = null,
@SerialName(uniqueGiftVariantCountField)
override val uniqueGiftVariantCount: Int? = null,
) : Regular
companion object : KSerializer<Regular> {
@@ -73,6 +104,12 @@ sealed interface Gift {
val remaining_count: Int? = null,
val upgrade_star_count: Int? = null,
val publisher_chat: PreviewChat? = null,
val personal_total_count: Int? = null,
val personal_remaining_count: Int? = null,
val is_premium: Boolean = false,
val has_colors: Boolean = false,
val background: dev.inmo.tgbotapi.types.gifts.GiftBackground? = null,
val unique_gift_variant_count: Int? = null,
)
override val descriptor: SerialDescriptor
@@ -89,7 +126,13 @@ sealed interface Gift {
totalCount = surrogate.total_count,
remainingCount = surrogate.remaining_count,
upgradeStarCount = surrogate.upgrade_star_count,
publisherChat = surrogate.publisher_chat
publisherChat = surrogate.publisher_chat,
personalTotalCount = surrogate.personal_total_count,
personalRemainingCount = surrogate.personal_remaining_count,
isPremium = surrogate.is_premium,
hasColors = surrogate.has_colors,
background = surrogate.background,
uniqueGiftVariantCount = surrogate.unique_gift_variant_count
)
} else {
Unlimited(
@@ -98,6 +141,12 @@ sealed interface Gift {
starCount = surrogate.star_count,
upgradeStarCount = surrogate.upgrade_star_count,
publisherChat = surrogate.publisher_chat,
personalTotalCount = surrogate.personal_total_count,
personalRemainingCount = surrogate.personal_remaining_count,
isPremium = surrogate.is_premium,
hasColors = surrogate.has_colors,
background = surrogate.background,
uniqueGiftVariantCount = surrogate.unique_gift_variant_count
)
}
}
@@ -110,7 +159,13 @@ sealed interface Gift {
total_count = value.totalCount,
remaining_count = value.remainingCount,
upgrade_star_count = value.upgradeStarCount,
publisher_chat = value.publisherChat
publisher_chat = value.publisherChat,
personal_total_count = value.personalTotalCount,
personal_remaining_count = value.personalRemainingCount,
is_premium = value.isPremium,
has_colors = value.hasColors,
background = value.background,
unique_gift_variant_count = value.uniqueGiftVariantCount
)
RegularGiftSurrogate.serializer().serialize(encoder, surrogate)
}
@@ -119,6 +174,8 @@ sealed interface Gift {
@Serializable
data class Unique(
@SerialName(giftIdField)
val id: GiftId? = null,
@SerialName(baseNameField)
val baseName: String,
@SerialName(nameField)
@@ -132,7 +189,13 @@ sealed interface Gift {
@SerialName(backdropField)
val backdrop: UniqueGiftBackdrop,
@SerialName(publisherChatField)
override val publisherChat: PreviewChat? = null
override val publisherChat: PreviewChat? = null,
@SerialName(isFromBlockchainField)
val isFromBlockchain: Boolean = false,
@SerialName(isPremiumField2)
val isPremium: Boolean = false,
@SerialName(colorsField)
val colors: UniqueGiftColors = null
) : Gift
companion object : KSerializer<Gift> {
@@ -146,6 +209,12 @@ sealed interface Gift {
val total_count: Int? = null,
val remaining_count: Int? = null,
val upgrade_star_count: Int? = null,
val personal_total_count: Int? = null,
val personal_remaining_count: Int? = null,
val is_premium: Boolean = false,
val has_colors: Boolean = false,
val background: dev.inmo.tgbotapi.types.gifts.GiftBackground? = null,
val unique_gift_variant_count: Int? = null,
// unique gift fields
val base_name: String? = null,
val name: String? = null,
@@ -153,6 +222,8 @@ sealed interface Gift {
val model: UniqueGiftModel? = null,
val symbol: UniqueGiftSymbol? = null,
val backdrop: UniqueGiftBackdrop? = null,
val is_from_blockchain: Boolean = false,
val colors: dev.inmo.tgbotapi.types.gifts.unique.UniqueGiftColors? = null,
val publisher_chat: PreviewChat? = null,
)
@@ -164,13 +235,17 @@ sealed interface Gift {
return if (surrogate.base_name != null && surrogate.name != null && surrogate.number != null && surrogate.model != null && surrogate.symbol != null && surrogate.backdrop != null) {
Unique(
id = surrogate.id,
baseName = surrogate.base_name,
name = surrogate.name,
number = surrogate.number,
model = surrogate.model,
symbol = surrogate.symbol,
backdrop = surrogate.backdrop,
publisherChat = surrogate.publisher_chat
publisherChat = surrogate.publisher_chat,
isFromBlockchain = surrogate.is_from_blockchain,
isPremium = surrogate.is_premium,
colors = surrogate.colors
)
} else {
decoder.decodeSerializableValue(Regular.serializer())
@@ -188,12 +263,21 @@ sealed interface Gift {
total_count = (value as? Regular.Limited)?.totalCount,
remaining_count = (value as? Regular.Limited)?.remainingCount,
upgrade_star_count = (value as? Regular)?.upgradeStarCount,
personal_total_count = (value as? Regular)?.personalTotalCount,
personal_remaining_count = (value as? Regular)?.personalRemainingCount,
is_premium = (value as? Regular)?.isPremium ?: (value as? Unique)?.isPremium ?: false,
has_colors = (value as? Regular)?.hasColors ?: false,
background = (value as? Regular)?.background,
unique_gift_variant_count = (value as? Regular)?.uniqueGiftVariantCount,
base_name = (value as? Unique)?.baseName,
name = (value as? Unique)?.name,
number = (value as? Unique)?.number,
model = (value as? Unique)?.model,
symbol = (value as? Unique)?.symbol,
backdrop = (value as? Unique)?.backdrop,
gift_id = (value as? Unique)?.id,
is_from_blockchain = (value as? Unique)?.isFromBlockchain ?: false,
colors = (value as? Unique)?.colors,
publisher_chat = value.publisherChat,
)
GiftSurrogate.serializer().serialize(encoder, surrogate)

View File

@@ -0,0 +1,13 @@
package dev.inmo.tgbotapi.types.gifts
import dev.inmo.tgbotapi.types.backgroundField
import dev.inmo.tgbotapi.types.files.PathedFile
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
@Serializable
data class GiftBackground(
@SerialName(backgroundField)
val background: PathedFile
)

View File

@@ -9,6 +9,7 @@ import dev.inmo.tgbotapi.types.message.asTextSources
import dev.inmo.tgbotapi.types.message.textsources.TextSource
import dev.inmo.tgbotapi.types.message.textsources.TextSourcesList
import dev.inmo.tgbotapi.types.message.toRawMessageEntities
import dev.inmo.tgbotapi.types.payments.abstracts.Currency
import dev.inmo.tgbotapi.utils.internal.ClassCastsIncluded
import kotlinx.serialization.EncodeDefault
import kotlinx.serialization.KSerializer
@@ -51,6 +52,8 @@ sealed interface GiftSentOrReceived : CommonEvent {
val prepaidUpgradeStarCount: Int?
val canBeUpgraded: Boolean
val isPrivate: Boolean
val isUpgradeSeparate: Boolean
val uniqueGiftNumber: Int?
@Serializable
data class Common(
@@ -68,6 +71,10 @@ sealed interface GiftSentOrReceived : CommonEvent {
private val entities: RawMessageEntities? = null,
@SerialName(isPrivateField)
override val isPrivate: Boolean = false,
@SerialName(isUpgradeSeparateField)
override val isUpgradeSeparate: Boolean = false,
@SerialName(uniqueGiftNumberField)
override val uniqueGiftNumber: Int? = null,
@SerialName(nextTransferDateField)
override val nextTransferDate: TelegramDate? = null
) : Regular {
@@ -96,6 +103,10 @@ sealed interface GiftSentOrReceived : CommonEvent {
private val entities: RawMessageEntities? = null,
@SerialName(isPrivateField)
override val isPrivate: Boolean = false,
@SerialName(isUpgradeSeparateField)
override val isUpgradeSeparate: Boolean = false,
@SerialName(uniqueGiftNumberField)
override val uniqueGiftNumber: Int? = null,
@SerialName(nextTransferDateField)
override val nextTransferDate: TelegramDate? = null
) : Regular, GiftSentOrReceived.ReceivedInBusinessAccount {
@@ -123,6 +134,10 @@ sealed interface GiftSentOrReceived : CommonEvent {
val entities: RawMessageEntities? = null,
@SerialName(isPrivateField)
val isPrivate: Boolean = false,
@SerialName(isUpgradeSeparateField)
val isUpgradeSeparate: Boolean = false,
@SerialName(uniqueGiftNumberField)
val uniqueGiftNumber: Int? = null,
@SerialName(nextTransferDateField)
val nextTransferDate: TelegramDate? = null
)
@@ -150,6 +165,8 @@ sealed interface GiftSentOrReceived : CommonEvent {
text = surrogate.text,
entities = surrogate.entities,
isPrivate = surrogate.isPrivate,
isUpgradeSeparate = surrogate.isUpgradeSeparate,
uniqueGiftNumber = surrogate.uniqueGiftNumber,
nextTransferDate = surrogate.nextTransferDate
)
}
@@ -163,6 +180,8 @@ sealed interface GiftSentOrReceived : CommonEvent {
text = surrogate.text,
entities = surrogate.entities,
isPrivate = surrogate.isPrivate,
isUpgradeSeparate = surrogate.isUpgradeSeparate,
uniqueGiftNumber = surrogate.uniqueGiftNumber,
nextTransferDate = surrogate.nextTransferDate
)
}
@@ -178,7 +197,9 @@ sealed interface GiftSentOrReceived : CommonEvent {
text: String? = null,
textSources: TextSourcesList = emptyList(),
position: Int,
isPrivate: Boolean = false
isPrivate: Boolean = false,
isUpgradeSeparate: Boolean = false,
uniqueGiftNumber: Int? = null
) = ownedGiftId ?.let {
ReceivedInBusinessAccount(
gift,
@@ -188,7 +209,9 @@ sealed interface GiftSentOrReceived : CommonEvent {
canBeUpgraded,
text,
textSources.toRawMessageEntities(position),
isPrivate
isPrivate,
isUpgradeSeparate,
uniqueGiftNumber
)
} ?: Common(
gift,
@@ -197,7 +220,9 @@ sealed interface GiftSentOrReceived : CommonEvent {
canBeUpgraded,
text,
textSources.toRawMessageEntities(position),
isPrivate
isPrivate,
isUpgradeSeparate,
uniqueGiftNumber
)
}
}
@@ -207,7 +232,10 @@ sealed interface GiftSentOrReceived : CommonEvent {
override val gift: Gift.Unique
val origin: String?
val originTyped: Origin?
@Deprecated("Use lastResaleCurrency and lastResaleAmount instead")
val lastResaleStarCount: Int?
val lastResaleCurrency: String?
val lastResaleAmount: Long?
val transferStarCount: Int?
@Suppress("SERIALIZER_TYPE_INCOMPATIBLE")
@@ -215,11 +243,15 @@ sealed interface GiftSentOrReceived : CommonEvent {
sealed interface Origin {
val string: String
@Serializable(Origin.Companion::class)
object Upgrade : Origin { override val string: String = "upgrade" }
data object Upgrade : Origin { override val string: String = "upgrade" }
@Serializable(Origin.Companion::class)
object Transfer : Origin { override val string: String = "transfer" }
data object Transfer : Origin { override val string: String = "transfer" }
@Serializable(Origin.Companion::class)
object Resale : Origin { override val string: String = "resale" }
data object Resale : Origin { override val string: String = "resale" }
@Serializable(Origin.Companion::class)
data object GiftedUpgrade : Origin { override val string: String = "gifted_upgrade" }
@Serializable(Origin.Companion::class)
data object Offer : Origin { override val string: String = "offer" }
@Serializable(Origin.Companion::class)
@JvmInline
value class Unknown(override val string: String) : Origin
@@ -231,6 +263,8 @@ sealed interface GiftSentOrReceived : CommonEvent {
Upgrade.string -> Upgrade
Transfer.string -> Transfer
Resale.string -> Resale
GiftedUpgrade.string -> GiftedUpgrade
Offer.string -> Offer
else -> Unknown(value)
}
@@ -254,8 +288,13 @@ sealed interface GiftSentOrReceived : CommonEvent {
override val gift: Gift.Unique,
@SerialName(originField)
override val originTyped: Origin? = null,
@Deprecated("Use lastResaleCurrency and lastResaleAmount instead")
@SerialName(lastResaleStarCountField)
override val lastResaleStarCount: Int? = null,
@SerialName(lastResaleCurrencyField)
override val lastResaleCurrency: Currency? = null,
@SerialName(lastResaleAmountField)
override val lastResaleAmount: Long? = null,
@SerialName(transferStarCountField)
override val transferStarCount: Int? = null,
@SerialName(nextTransferDateField)
@@ -271,12 +310,16 @@ sealed interface GiftSentOrReceived : CommonEvent {
gift: Gift.Unique,
origin: String?,
lastResaleStarCount: Int? = null,
lastResaleCurrency: Currency? = null,
lastResaleAmount: Long? = null,
transferStarCount: Int? = null,
nextTransferDate: TelegramDate? = null
) : this(
gift,
origin ?.let { Origin.fromString(it) },
lastResaleStarCount,
lastResaleCurrency,
lastResaleAmount,
transferStarCount,
nextTransferDate
)
@@ -290,8 +333,13 @@ sealed interface GiftSentOrReceived : CommonEvent {
override val ownedGiftId: GiftId,
@SerialName(originField)
override val originTyped: Origin? = null,
@Deprecated("Use lastResaleCurrency and lastResaleAmount instead")
@SerialName(lastResaleStarCountField)
override val lastResaleStarCount: Int? = null,
@SerialName(lastResaleCurrencyField)
override val lastResaleCurrency: Currency? = null,
@SerialName(lastResaleAmountField)
override val lastResaleAmount: Long? = null,
@SerialName(transferStarCountField)
override val transferStarCount: Int? = null,
@SerialName(nextTransferDateField)
@@ -305,6 +353,8 @@ sealed interface GiftSentOrReceived : CommonEvent {
ownedGiftId: GiftId,
origin: String? = null,
lastResaleStarCount: Int? = null,
lastResaleCurrency: Currency? = null,
lastResaleAmount: Long? = null,
transferStarCount: Int? = null,
nextTransferDate: TelegramDate? = null
) : this(
@@ -312,6 +362,8 @@ sealed interface GiftSentOrReceived : CommonEvent {
ownedGiftId = ownedGiftId,
originTyped = origin ?.let { Origin.fromString(it) },
lastResaleStarCount = lastResaleStarCount,
lastResaleCurrency = lastResaleCurrency,
lastResaleAmount = lastResaleAmount,
transferStarCount = transferStarCount,
nextTransferDate = nextTransferDate
)
@@ -328,6 +380,10 @@ sealed interface GiftSentOrReceived : CommonEvent {
val origin: Origin? = null,
@SerialName(lastResaleStarCountField)
val lastResaleStarCount: Int? = null,
@SerialName(lastResaleCurrencyField)
val lastResaleCurrency: Currency? = null,
@SerialName(lastResaleAmountField)
val lastResaleAmount: Long? = null,
@SerialName(transferStarCountField)
val transferStarCount: Int? = null,
@SerialName(nextTransferDateField)
@@ -353,6 +409,8 @@ sealed interface GiftSentOrReceived : CommonEvent {
gift = surrogate.gift,
originTyped = surrogate.origin,
lastResaleStarCount = surrogate.lastResaleStarCount,
lastResaleCurrency = surrogate.lastResaleCurrency,
lastResaleAmount = surrogate.lastResaleAmount,
transferStarCount = surrogate.transferStarCount,
nextTransferDate = surrogate.nextTransferDate
)
@@ -363,6 +421,8 @@ sealed interface GiftSentOrReceived : CommonEvent {
ownedGiftId = surrogate.ownedGiftId,
originTyped = surrogate.origin,
lastResaleStarCount = surrogate.lastResaleStarCount,
lastResaleCurrency = surrogate.lastResaleCurrency,
lastResaleAmount = surrogate.lastResaleAmount,
transferStarCount = surrogate.transferStarCount,
nextTransferDate = surrogate.nextTransferDate
)

View File

@@ -0,0 +1,19 @@
package dev.inmo.tgbotapi.types.gifts.unique
import dev.inmo.tgbotapi.types.baseColorField
import dev.inmo.tgbotapi.types.linkColorField
import dev.inmo.tgbotapi.types.nameColorField
import dev.inmo.tgbotapi.utils.RGBColor
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
@Serializable
data class UniqueGiftColors(
@SerialName(nameColorField)
val nameColor: RGBColor,
@SerialName(baseColorField)
val baseColor: RGBColor,
@SerialName(linkColorField)
val linkColor: RGBColor
)

View File

@@ -3,6 +3,7 @@ package dev.inmo.tgbotapi.types.message.ChatEvents.forum
import dev.inmo.tgbotapi.types.CustomEmojiId
import dev.inmo.tgbotapi.types.iconColorField
import dev.inmo.tgbotapi.types.iconCustomEmojiIdField
import dev.inmo.tgbotapi.types.isNameImplicitField
import dev.inmo.tgbotapi.types.message.ChatEvents.abstracts.ForumEvent
import dev.inmo.tgbotapi.types.nameField
import dev.inmo.tgbotapi.utils.RGBColor
@@ -16,5 +17,7 @@ data class ForumTopicCreated(
@SerialName(iconColorField)
val iconColor: RGBColor,
@SerialName(iconCustomEmojiIdField)
val iconEmojiId: CustomEmojiId? = null
val iconEmojiId: CustomEmojiId? = null,
@SerialName(isNameImplicitField)
val isNameImplicit: Boolean = false
) : ForumEvent

View File

@@ -201,6 +201,7 @@ internal data class RawMessage(
// Gifts
private val gift: GiftSentOrReceived.Regular? = null,
private val unique_gift: GiftSentOrReceived.Unique? = null,
private val gift_upgrade_sent: GiftSentOrReceived? = null,
) {
@Suppress("SERIALIZER_TYPE_INCOMPATIBLE")
private val checkedFrom = from ?.takeIf { !it.isFakeTelegramUser() }
@@ -328,6 +329,7 @@ internal data class RawMessage(
paid_message_price_changed != null -> paid_message_price_changed
gift != null -> gift
unique_gift != null -> unique_gift
gift_upgrade_sent != null -> gift_upgrade_sent
checklist_tasks_done != null -> checklist_tasks_done
checklist_tasks_added != null -> checklist_tasks_added
direct_message_price_changed != null -> direct_message_price_changed