1
0
mirror of https://github.com/InsanusMokrassar/TelegramBotAPI.git synced 2026-03-05 18:32:27 +00:00

add support of profile audios

This commit is contained in:
2026-02-18 21:22:16 +06:00
parent e02849ae5e
commit a0bb05ce4a
29 changed files with 599 additions and 183 deletions

View File

@@ -2,6 +2,7 @@ package dev.inmo.tgbotapi.requests
import dev.inmo.tgbotapi.abstracts.WithCustomStartMediaData
import dev.inmo.tgbotapi.abstracts.types.MessageAction
import dev.inmo.tgbotapi.abstracts.types.OptionallyWithEffectId
import dev.inmo.tgbotapi.abstracts.types.ProtectContent
import dev.inmo.tgbotapi.requests.abstracts.SimpleRequest
import dev.inmo.tgbotapi.requests.send.abstracts.OptionallyDirectMessageThreadRequest
@@ -38,7 +39,7 @@ data class ForwardMessage(
@SerialName(protectContentField)
override val protectContent: Boolean = false,
@SerialName(messageEffectIdField)
val effectId: EffectId? = null,
override val effectId: EffectId? = null,
@SerialName(suggestedPostParametersField)
override val suggestedPostParameters: SuggestedPostParameters? = null
): SimpleRequest<PossiblyForwardedMessage>,
@@ -47,7 +48,8 @@ data class ForwardMessage(
OptionallyMessageThreadRequest,
OptionallyDirectMessageThreadRequest,
OptionallySuggestedPostRequest,
WithCustomStartMediaData {
WithCustomStartMediaData,
OptionallyWithEffectId {
override val chatId: ChatIdentifier
get() = fromChatId

View File

@@ -0,0 +1,32 @@
package dev.inmo.tgbotapi.requests.get
import dev.inmo.tgbotapi.requests.abstracts.SimpleRequest
import dev.inmo.tgbotapi.types.*
import dev.inmo.tgbotapi.types.UserProfileAudios
import kotlinx.serialization.*
@Serializable
data class GetUserProfileAudios(
@Suppress("SERIALIZER_TYPE_INCOMPATIBLE")
@SerialName(userIdField)
val userId: UserId,
@SerialName(offsetField)
val offset: Int? = null,
@SerialName(limitField)
val limit: Int? = null
): SimpleRequest<UserProfileAudios> {
init {
if (offset != null && offset < 0) {
throw IllegalArgumentException("Offset for getting user profile audios must be positive")
}
if (limit != null && limit !in userProfileAudiosRequestLimit) {
throw IllegalArgumentException("Limit for getting user profile audios must be in 0 .. 100 range")
}
}
override fun method(): String = "getUserProfileAudios"
override val resultDeserializer: DeserializationStrategy<UserProfileAudios>
get() = UserProfileAudios.serializer()
override val requestSerializer: SerializationStrategy<*>
get() = serializer()
}

View File

@@ -5,6 +5,7 @@ package dev.inmo.tgbotapi.requests.send
import dev.inmo.tgbotapi.abstracts.TextedOutput
import dev.inmo.tgbotapi.abstracts.WithCustomStartMediaData
import dev.inmo.tgbotapi.abstracts.types.MessageAction
import dev.inmo.tgbotapi.abstracts.types.OptionallyWithEffectId
import dev.inmo.tgbotapi.abstracts.types.ProtectContent
import dev.inmo.tgbotapi.requests.abstracts.SimpleRequest
import dev.inmo.tgbotapi.requests.send.abstracts.OptionallyMessageThreadRequest
@@ -189,7 +190,7 @@ data class CopyMessage internal constructor(
@SerialName(allowPaidBroadcastField)
override val allowPaidBroadcast: Boolean = false,
@SerialName(messageEffectIdField)
val effectId: EffectId? = null,
override val effectId: EffectId? = null,
@SerialName(suggestedPostParametersField)
override val suggestedPostParameters: SuggestedPostParameters? = null,
@SerialName(replyParametersField)
@@ -203,7 +204,8 @@ data class CopyMessage internal constructor(
TextedOutput,
ProtectContent,
OptionallyMessageThreadRequest,
WithCustomStartMediaData {
WithCustomStartMediaData,
OptionallyWithEffectId {
override val chatId: ChatIdentifier
get() = fromChatId
override val textSources: List<TextSource>? by lazy {

View File

@@ -58,7 +58,8 @@ val callbackQueryAnswerLength = 0 until 200
val captionLength = 0 .. 1024
val storyCaptionLength = 0 .. 2048
val textLength = 1 .. 4096
val userProfilePhotosRequestLimit = 0 .. 100
val userProfilePhotosRequestLimit = 1 .. 100
val userProfileAudiosRequestLimit = 1 .. 100
val chatTitleLength = 1 until 255
val threadNameLength = 1 until 128
val chatDescriptionLength = 0 until 256
@@ -364,6 +365,7 @@ const val fileIdField = "file_id"
const val fileSizeField = "file_size"
const val fileDateField = "file_date"
const val filePathField = "file_path"
const val qualitiesField = "qualities"
const val requestWriteAccessField = "request_write_access"
@@ -608,6 +610,7 @@ const val shippingOptionsField = "shipping_options"
const val countryCodeField = "country_code"
const val countryCodesField = "country_codes"
const val totalCountField = "total_count"
const val audiosField = "audios"
const val remainingCountField = "remaining_count"
const val stateField = "state"
const val cityField = "city"
@@ -659,6 +662,7 @@ const val mediaField = "media"
const val mainFrameTimestampField = "main_frame_timestamp"
const val firstProfileAudioField = "first_profile_audio"
const val paidMessageStarCountField = "paid_message_star_count"
const val countField = "count"
const val ratingField = "rating"
@@ -842,3 +846,5 @@ const val isFlippedField = "is_flipped"
const val temperatureField = "temperature"
const val backgroundColorField = "background_color"
const val keepOriginalDetailsField = "keep_original_details"
const val codecField = "codec"

View File

@@ -0,0 +1,13 @@
package dev.inmo.tgbotapi.types
import dev.inmo.tgbotapi.types.files.AudioFile
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
@Serializable
data class UserProfileAudios(
@SerialName(totalCountField)
val totalCount: Int,
@SerialName(audiosField)
val audios: List<AudioFile>
)

View File

@@ -5,6 +5,7 @@ import dev.inmo.tgbotapi.types.business_connection.BusinessIntro
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.files.AudioFile
import dev.inmo.tgbotapi.types.gifts.AcceptedGiftTypes
import dev.inmo.tgbotapi.types.gifts.unique.UniqueGiftColors
import dev.inmo.tgbotapi.types.message.abstracts.Message
@@ -176,6 +177,8 @@ data class ExtendedPrivateChatImpl(
override val acceptedGiftTypes: AcceptedGiftTypes = AcceptedGiftTypes(),
@SerialName(paidMessageStarCountField)
override val paidMessageStarCount: Int? = null,
@SerialName(firstProfileAudioField)
override val firstProfileAudio: AudioFile? = null,
) : ExtendedPrivateChat
@Serializable
@@ -232,6 +235,8 @@ data class ExtendedPrivateForumChatImpl(
override val acceptedGiftTypes: AcceptedGiftTypes = AcceptedGiftTypes(),
@SerialName(paidMessageStarCountField)
override val paidMessageStarCount: Int? = null,
@SerialName(firstProfileAudioField)
override val firstProfileAudio: AudioFile? = null,
) : ExtendedPrivateForumChat
typealias ExtendedUser = ExtendedPrivateChat

View File

@@ -6,6 +6,7 @@ import dev.inmo.tgbotapi.types.business_connection.BusinessIntro
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.files.AudioFile
import dev.inmo.tgbotapi.types.gifts.AcceptedGiftTypes
import dev.inmo.tgbotapi.types.gifts.unique.UniqueGiftColors
import dev.inmo.tgbotapi.types.message.abstracts.Message
@@ -72,6 +73,7 @@ sealed interface ExtendedPrivateChat : PrivateUserChat,
val birthdate: Birthdate?
val personalChat: PreviewChannelChat?
val firstProfileAudio: AudioFile?
val allowCreateUserIdLink: Boolean
get() = hasPrivateForwards

View File

@@ -22,6 +22,6 @@ data class AnimationFile(
@SerialName(mimeTypeField)
override val mimeType: MimeType? = null,
@SerialName(fileSizeField)
override val fileSize: Long? = null
override val fileSize: FileSize? = null
) : TelegramMediaFile, MimedMediaFile, ThumbedMediaFile, PlayableMediaFile, CustomNamedMediaFile, SizedMediaFile,
MediaContentVariant

View File

@@ -25,10 +25,16 @@ data class AudioFile(
@SerialName(mimeTypeField)
override val mimeType: MimeType? = null,
@SerialName(fileSizeField)
override val fileSize: Long? = null,
override val fileSize: FileSize? = null,
@SerialName(thumbnailField)
override val thumbnail: PhotoSize? = null
) : TelegramMediaFile, CustomNamedMediaFile, MimedMediaFile, ThumbedMediaFile, PlayableMediaFile, TitledMediaFile,
Performerable, MediaContentVariant
fun AudioFile.asVoiceFile() = VoiceFile(fileId, fileUniqueId, duration, mimeType, fileSize)
fun AudioFile.asVoiceFile() = VoiceFile(
fileId = fileId,
fileUniqueId = fileUniqueId,
duration = duration,
mimeType = mimeType,
fileSize = fileSize
)

View File

@@ -14,7 +14,7 @@ data class DocumentFile(
@SerialName(fileUniqueIdField)
override val fileUniqueId: TgFileUniqueId,
@SerialName(fileSizeField)
override val fileSize: Long? = null,
override val fileSize: FileSize? = null,
override val thumbnail: PhotoSize? = null,
@SerialName(mimeTypeField)
override val mimeType: MimeType? = null,
@@ -27,11 +27,11 @@ inline fun TelegramMediaFile.asDocumentFile() = if (this is DocumentFile) {
this
} else {
DocumentFile(
fileId,
fileUniqueId,
fileSize,
(this as? ThumbedMediaFile) ?.thumbnail,
(this as? MimedMediaFile) ?.mimeType,
(this as? CustomNamedMediaFile) ?.fileName
fileId = fileId,
fileUniqueId = fileUniqueId,
fileSize = fileSize,
thumbnail = (this as? ThumbedMediaFile) ?.thumbnail,
mimeType = (this as? MimedMediaFile) ?.mimeType,
fileName = (this as? CustomNamedMediaFile) ?.fileName
)
}

View File

@@ -13,5 +13,5 @@ data class File(
@SerialName(fileUniqueIdField)
override val fileUniqueId: TgFileUniqueId,
@SerialName(fileSizeField)
override val fileSize: Long? = null
override val fileSize: FileSize? = null
): TelegramMediaFile

View File

@@ -0,0 +1,12 @@
package dev.inmo.tgbotapi.types.files
import kotlinx.serialization.Serializable
import kotlin.jvm.JvmInline
@Serializable
@JvmInline
value class FileSize(
val bytes: ULong
) : Comparable<FileSize> {
override fun compareTo(other: FileSize): Int = bytes.compareTo(other.bytes)
}

View File

@@ -19,5 +19,5 @@ data class PassportFile(
@SerialName(fileDateField)
val uploadingDate: TelegramDate,
@SerialName(fileSizeField)
override val fileSize: Long? = null
override val fileSize: FileSize? = null
) : TelegramMediaFile

View File

@@ -15,7 +15,7 @@ data class PathedFile(
@SerialName(filePathField)
val filePath: String,
@SerialName(fileSizeField)
override val fileSize: Long? = null
override val fileSize: FileSize? = null
): TelegramMediaFile {
@Suppress("TRANSIENT_IS_REDUNDANT")
@Transient

View File

@@ -17,7 +17,7 @@ value class PhotoFile(
get() = biggest.fileId
override val fileUniqueId: TgFileUniqueId
get() = biggest.fileUniqueId
override val fileSize: Long?
override val fileSize: FileSize?
get() = biggest.fileSize
init {
@@ -44,7 +44,7 @@ data class PhotoSize(
@SerialName(fileUniqueIdField)
override val fileUniqueId: TgFileUniqueId,
@SerialName(fileSizeField)
override val fileSize: Long? = null,
override val fileSize: FileSize? = null,
override val width: Int,
override val height: Int
) : SizedMediaFile {

View File

@@ -31,7 +31,7 @@ data class StickerSurrogate(
val premium_animation: File? = null,
val mask_position: MaskPosition? = null,
val custom_emoji_id: CustomEmojiId? = null,
val file_size: Long? = null,
val file_size: FileSize? = null,
val needs_repainting: Boolean = false,
)
@@ -267,7 +267,7 @@ data class RegularSimpleSticker(
@SerialName(premiumAnimationField)
override val premiumAnimationFile: File? = null,
@SerialName(fileSizeField)
override val fileSize: Long? = null,
override val fileSize: FileSize? = null,
) : RegularSticker {
@SerialName(stickerFormatField)
@EncodeDefault
@@ -299,7 +299,7 @@ data class RegularAnimatedSticker(
@SerialName(premiumAnimationField)
override val premiumAnimationFile: File? = null,
@SerialName(fileSizeField)
override val fileSize: Long? = null,
override val fileSize: FileSize? = null,
) : RegularSticker, AnimatedSticker {
@SerialName(stickerTypeField)
@Serializable(StickerType.Serializer::class)
@@ -327,7 +327,7 @@ data class RegularVideoSticker(
@SerialName(premiumAnimationField)
override val premiumAnimationFile: File? = null,
@SerialName(fileSizeField)
override val fileSize: Long? = null,
override val fileSize: FileSize? = null,
) : RegularSticker, VideoSticker {
@SerialName(stickerTypeField)
@Serializable(StickerType.Serializer::class)
@@ -371,7 +371,7 @@ data class MaskSimpleSticker(
@SerialName(stickerSetNameField)
override val stickerSetName: StickerSetName? = null,
@SerialName(fileSizeField)
override val fileSize: Long? = null,
override val fileSize: FileSize? = null,
) : MaskSticker {
@SerialName(stickerFormatField)
@EncodeDefault
@@ -403,7 +403,7 @@ data class MaskAnimatedSticker(
@SerialName(stickerSetNameField)
override val stickerSetName: StickerSetName? = null,
@SerialName(fileSizeField)
override val fileSize: Long? = null,
override val fileSize: FileSize? = null,
) : MaskSticker, AnimatedSticker {
@SerialName(stickerTypeField)
@Serializable(StickerType.Serializer::class)
@@ -431,7 +431,7 @@ data class MaskVideoSticker(
@SerialName(stickerSetNameField)
override val stickerSetName: StickerSetName? = null,
@SerialName(fileSizeField)
override val fileSize: Long? = null,
override val fileSize: FileSize? = null,
) : MaskSticker, VideoSticker {
@SerialName(stickerTypeField)
@Serializable(StickerType.Serializer::class)
@@ -476,7 +476,7 @@ data class CustomEmojiSimpleSticker(
@SerialName(stickerSetNameField)
override val stickerSetName: StickerSetName? = null,
@SerialName(fileSizeField)
override val fileSize: Long? = null,
override val fileSize: FileSize? = null,
@SerialName(needsRepaintingField)
override val needsRepainting: Boolean = false
) : CustomEmojiSticker {
@@ -510,7 +510,7 @@ data class CustomEmojiAnimatedSticker(
@SerialName(stickerSetNameField)
override val stickerSetName: StickerSetName? = null,
@SerialName(fileSizeField)
override val fileSize: Long? = null,
override val fileSize: FileSize? = null,
@SerialName(needsRepaintingField)
override val needsRepainting: Boolean = false,
) : CustomEmojiSticker, AnimatedSticker {
@@ -540,7 +540,7 @@ data class CustomEmojiVideoSticker(
@SerialName(stickerSetNameField)
override val stickerSetName: StickerSetName? = null,
@SerialName(fileSizeField)
override val fileSize: Long? = null,
override val fileSize: FileSize? = null,
@SerialName(needsRepaintingField)
override val needsRepainting: Boolean = false,
) : CustomEmojiSticker, VideoSticker {
@@ -569,7 +569,7 @@ data class UnknownSticker(
@SerialName(stickerSetNameField)
override val stickerSetName: StickerSetName? = null,
@SerialName(fileSizeField)
override val fileSize: Long? = null,
override val fileSize: FileSize? = null,
@SerialName(stickerFormatField)
override val stickerFormat: StickerFormat = StickerFormat.Static,
@SerialName(stickerTypeField)

View File

@@ -11,5 +11,5 @@ import dev.inmo.tgbotapi.types.TgFileUniqueId
sealed interface TelegramMediaFile {
val fileId: FileId
val fileUniqueId: TgFileUniqueId
val fileSize: Long?
val fileSize: FileSize?
}

View File

@@ -0,0 +1,53 @@
package dev.inmo.tgbotapi.types.files
import kotlinx.serialization.KSerializer
import kotlinx.serialization.Serializable
import kotlinx.serialization.builtins.serializer
import kotlinx.serialization.descriptors.SerialDescriptor
import kotlinx.serialization.encoding.Decoder
import kotlinx.serialization.encoding.Encoder
@Serializable(VideoCodec.Serializer::class)
sealed interface VideoCodec {
val name: String
@Suppress("SERIALIZER_TYPE_INCOMPATIBLE")
@Serializable(VideoCodec.Serializer::class)
data object H264 : VideoCodec { override val name = "h264" }
@Suppress("SERIALIZER_TYPE_INCOMPATIBLE")
@Serializable(VideoCodec.Serializer::class)
data object H265 : VideoCodec { override val name = "h265" }
@Suppress("SERIALIZER_TYPE_INCOMPATIBLE")
@Serializable(VideoCodec.Serializer::class)
data object AV1 : VideoCodec { override val name = "av01" }
@Suppress("SERIALIZER_TYPE_INCOMPATIBLE")
@Serializable(VideoCodec.Serializer::class)
data class Custom(
override val name: String
) : VideoCodec
object Serializer : KSerializer<VideoCodec> {
override val descriptor: SerialDescriptor
get() = String.serializer().descriptor
override fun serialize(
encoder: Encoder,
value: VideoCodec
) {
encoder.encodeString(value.name)
}
override fun deserialize(decoder: Decoder): VideoCodec {
return when (val name = decoder.decodeString()) {
H264.name -> H264
H265.name -> H265
AV1.name -> AV1
else -> Custom(name)
}
}
}
}

View File

@@ -29,14 +29,24 @@ data class VideoFile(
override val cover: Photo? = null,
@SerialName(startTimestampField)
override val startTimestamp: Seconds? = null,
@SerialName(qualitiesField)
val qualities: List<VideoQuality>? = null,
@SerialName(fileNameField)
override val fileName: String? = null,
@SerialName(mimeTypeField)
override val mimeType: MimeType? = null,
@SerialName(fileSizeField)
override val fileSize: Long? = null
) : TelegramMediaFile, CustomNamedMediaFile, MimedMediaFile, CoveredMediaFile, CustomStartMediaFile, ThumbedMediaFile, PlayableMediaFile, SizedMediaFile,
MediaContentVariant, UsefulAsPaidMediaFile
override val fileSize: FileSize? = null
) : TelegramMediaFile,
CustomNamedMediaFile,
MimedMediaFile,
CoveredMediaFile,
CustomStartMediaFile,
ThumbedMediaFile,
PlayableMediaFile,
SizedMediaFile,
MediaContentVariant,
UsefulAsPaidMediaFile
@Suppress("NOTHING_TO_INLINE")
inline fun VideoFile.toTelegramMediaVideo(

View File

@@ -17,7 +17,7 @@ data class VideoNoteFile(
override val duration: Long? = null,
override val thumbnail: PhotoSize? = null,
@SerialName(fileSizeField)
override val fileSize: Long? = null
override val fileSize: FileSize? = null
) : TelegramMediaFile, ThumbedMediaFile, PlayableMediaFile, SizedMediaFile, MediaContentVariant {
override val height: Int
get() = width

View File

@@ -0,0 +1,24 @@
package dev.inmo.tgbotapi.types.files
import dev.inmo.tgbotapi.requests.abstracts.FileId
import dev.inmo.tgbotapi.types.*
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
@Serializable
data class VideoQuality(
@Suppress("SERIALIZER_TYPE_INCOMPATIBLE")
@SerialName(fileIdField)
override val fileId: FileId,
@SerialName(fileUniqueIdField)
override val fileUniqueId: TgFileUniqueId,
@SerialName(widthField)
override val width: Int,
@SerialName(heightField)
override val height: Int,
@SerialName(codecField)
val codec: VideoCodec,
@SerialName(fileSizeField)
override val fileSize: FileSize? = null
) : TelegramMediaFile, SizedMediaFile {
}

View File

@@ -18,7 +18,7 @@ data class VoiceFile(
@SerialName(mimeTypeField)
override val mimeType: MimeType? = null,
@SerialName(fileSizeField)
override val fileSize: Long? = null
override val fileSize: FileSize? = null
) : TelegramMediaFile, MimedMediaFile, PlayableMediaFile, MediaContentVariant
fun VoiceFile.asAudioFile(

View File

@@ -2,6 +2,7 @@ package dev.inmo.tgbotapi
import dev.inmo.tgbotapi.requests.abstracts.toInputFile
import dev.inmo.tgbotapi.types.TgFileUniqueId
import dev.inmo.tgbotapi.types.files.FileSize
import dev.inmo.tgbotapi.types.files.PhotoFile
import dev.inmo.tgbotapi.types.media.MediaGroupMemberTelegramMediaSerializer
import dev.inmo.tgbotapi.types.files.PhotoSize
@@ -24,7 +25,7 @@ class SimpleInputFilesTest {
val photoContent = PhotoContent(
PhotoFile(
listOf(
PhotoSize("example_file_id".toInputFile(), TgFileUniqueId("example_unique_file_id"), 100, 100, 100)
PhotoSize("example_file_id".toInputFile(), TgFileUniqueId("example_unique_file_id"), FileSize(100u), 100, 100)
)
)
)