diff --git a/CMake/TdSetUpCompiler.cmake b/CMake/TdSetUpCompiler.cmake
index 728615e27..d9d67da33 100644
--- a/CMake/TdSetUpCompiler.cmake
+++ b/CMake/TdSetUpCompiler.cmake
@@ -85,9 +85,8 @@ function(td_set_up_compiler)
add_definitions(-D_DEFAULT_SOURCE=1 -DFD_SETSIZE=4096)
endif()
- if (NOT ANDROID) # _FILE_OFFSET_BITS is broken in NDK r15, r15b and r17 and doesn't work prior to Android 7.0
- add_definitions(-D_FILE_OFFSET_BITS=64)
- endif()
+ # _FILE_OFFSET_BITS is broken in Android NDK r15, r15b and r17 and doesn't work prior to Android 7.0
+ add_definitions(-D_FILE_OFFSET_BITS=64)
if (CMAKE_SYSTEM_NAME STREQUAL "SunOS")
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -lsocket -lnsl")
diff --git a/CMakeLists.txt b/CMakeLists.txt
index f377a018b..92b8c2fc5 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -6,7 +6,7 @@ if (POLICY CMP0065)
cmake_policy(SET CMP0065 NEW)
endif()
-project(TDLib VERSION 1.8.3 LANGUAGES CXX C)
+project(TDLib VERSION 1.8.4 LANGUAGES CXX C)
if (NOT DEFINED CMAKE_MODULE_PATH)
set(CMAKE_MODULE_PATH "")
@@ -287,6 +287,7 @@ set(TDLIB_SOURCE
td/telegram/AudiosManager.cpp
td/telegram/AuthManager.cpp
td/telegram/AutoDownloadSettings.cpp
+ td/telegram/AvailableReaction.cpp
td/telegram/BackgroundManager.cpp
td/telegram/BackgroundType.cpp
td/telegram/BotCommand.cpp
@@ -410,6 +411,7 @@ set(TDLIB_SOURCE
td/telegram/PhotoSize.cpp
td/telegram/PhotoSizeSource.cpp
td/telegram/PollManager.cpp
+ td/telegram/Premium.cpp
td/telegram/QueryCombiner.cpp
td/telegram/RecentDialogList.cpp
td/telegram/ReplyMarkup.cpp
@@ -484,6 +486,7 @@ set(TDLIB_SOURCE
td/telegram/AudiosManager.h
td/telegram/AuthManager.h
td/telegram/AutoDownloadSettings.h
+ td/telegram/AvailableReaction.h
td/telegram/BackgroundId.h
td/telegram/BackgroundManager.h
td/telegram/BackgroundType.h
@@ -644,6 +647,7 @@ set(TDLIB_SOURCE
td/telegram/PhotoSizeSource.h
td/telegram/PollId.h
td/telegram/PollManager.h
+ td/telegram/Premium.h
td/telegram/PrivacyManager.h
td/telegram/PtsManager.h
td/telegram/PublicDialogType.h
diff --git a/README.md b/README.md
index e57e23316..60a925e5a 100644
--- a/README.md
+++ b/README.md
@@ -130,7 +130,7 @@ target_link_libraries(YourTarget PRIVATE Td::TdStatic)
Or you could install `TDLib` and then reference it in your CMakeLists.txt like this:
```
-find_package(Td 1.8.3 REQUIRED)
+find_package(Td 1.8.4 REQUIRED)
target_link_libraries(YourTarget PRIVATE Td::TdStatic)
```
See [example/cpp/CMakeLists.txt](https://github.com/tdlight-team/tdlight/tree/master/example/cpp/CMakeLists.txt).
diff --git a/build.html b/build.html
index e16968de2..614b93356 100644
--- a/build.html
+++ b/build.html
@@ -928,6 +928,7 @@ function onOptionsChanged() {
if (use_vcpkg) {
commands.push('git clone https://github.com/Microsoft/vcpkg.git');
commands.push('cd vcpkg');
+ commands.push('git checkout 1b1ae50e1a69f7c659bd7d731e80b358d21c86ad');
commands.push(local + 'bootstrap-vcpkg.bat');
if (target === 'C++/CX') {
commands.push(local + 'vcpkg.exe install gperf:x86-windows openssl:arm-uwp openssl:arm64-uwp openssl:x64-uwp openssl:x86-uwp zlib:arm-uwp zlib:arm64-uwp zlib:x64-uwp zlib:x86-uwp');
diff --git a/example/README.md b/example/README.md
index 4d0b6c741..302e0104c 100644
--- a/example/README.md
+++ b/example/README.md
@@ -166,8 +166,7 @@ TDLib can be used from the Dart programming language through the [JSON](https://
See [dart_tdlib](https://github.com/periodicaidan/dart_tdlib) or [Dart wrapper for TDLib](https://github.com/tdlight-team/tdlight/pull/708/commits/237060abd4c205768153180e9f814298d1aa9d49) for an example of a TDLib Dart bindings through FFI.
-See [project.scarlet](https://github.com/aaugmentum/project.scarlet), [tdlib](https://github.com/i-Naji/tdlib), [tdlib](https://github.com/pqhaz/tdlib),
-[tdlib-dart](https://github.com/drewpayment/tdlib-dart), [tdlib-dart](https://github.com/triedcatched/tdlib-dart), or [telegram-service](https://github.com/igorder-dev/telegram-service) for examples of using TDLib from Dart.
+See [project.scarlet](https://github.com/aaugmentum/project.scarlet), [tdlib](https://github.com/i-Naji/tdlib), [tdlib-dart](https://github.com/drewpayment/tdlib-dart), [tdlib-dart](https://github.com/triedcatched/tdlib-dart), or [telegram-service](https://github.com/igorder-dev/telegram-service) for examples of using TDLib from Dart.
## Using TDLib in Rust projects
diff --git a/example/cpp/CMakeLists.txt b/example/cpp/CMakeLists.txt
index a766bc3c7..e2801ef75 100644
--- a/example/cpp/CMakeLists.txt
+++ b/example/cpp/CMakeLists.txt
@@ -2,7 +2,7 @@ cmake_minimum_required(VERSION 3.4 FATAL_ERROR)
project(TdExample VERSION 1.0 LANGUAGES CXX)
-find_package(Td 1.8.3 REQUIRED)
+find_package(Td 1.8.4 REQUIRED)
add_executable(tdjson_example tdjson_example.cpp)
target_link_libraries(tdjson_example PRIVATE Td::TdJson)
diff --git a/example/java/CMakeLists.txt b/example/java/CMakeLists.txt
index 602a5fa99..2c685a774 100644
--- a/example/java/CMakeLists.txt
+++ b/example/java/CMakeLists.txt
@@ -65,7 +65,7 @@ add_custom_target(build_java
)
add_custom_target(generate_javadoc
- COMMAND ${Java_JAVADOC_EXECUTABLE} -encoding UTF-8 -d ${JAVA_OUTPUT_DIRECTORY}/../docs org.drinkless.tdlib
+ COMMAND ${Java_JAVADOC_EXECUTABLE} -encoding UTF-8 -charset UTF-8 -d ${JAVA_OUTPUT_DIRECTORY}/../docs org.drinkless.tdlib
WORKING_DIRECTORY ${TD_API_JAVA_PATH}
COMMENT "Generating Javadoc documentation"
DEPENDS td_generate_java_api
diff --git a/example/uwp/extension.vsixmanifest b/example/uwp/extension.vsixmanifest
index 5b33a6ab4..0a3ba73bb 100644
--- a/example/uwp/extension.vsixmanifest
+++ b/example/uwp/extension.vsixmanifest
@@ -1,6 +1,6 @@
-
+
TDLib for Universal Windows Platform
TDLib is a library for building Telegram clients
https://core.telegram.org/tdlib
diff --git a/td/generate/scheme/secret_api.tl b/td/generate/scheme/secret_api.tl
index c47756a2e..4dd5e8345 100644
--- a/td/generate/scheme/secret_api.tl
+++ b/td/generate/scheme/secret_api.tl
@@ -78,7 +78,7 @@ documentAttributeAudio45#ded218e0 duration:int title:string performer:string = D
decryptedMessage46#36b091de flags:# random_id:long ttl:int message:string media:flags.9?DecryptedMessageMedia entities:flags.7?Vector via_bot_name:flags.11?string reply_to_random_id:flags.3?long = DecryptedMessage;
decryptedMessageMediaPhoto#f1fa8d78 thumb:bytes thumb_w:int thumb_h:int w:int h:int size:int key:bytes iv:bytes caption:string = DecryptedMessageMedia;
decryptedMessageMediaVideo#970c8c0e thumb:bytes thumb_w:int thumb_h:int duration:int mime_type:string w:int h:int size:int key:bytes iv:bytes caption:string = DecryptedMessageMedia;
-decryptedMessageMediaDocument#7afe8ae2 thumb:bytes thumb_w:int thumb_h:int mime_type:string size:int key:bytes iv:bytes attributes:Vector caption:string = DecryptedMessageMedia;
+decryptedMessageMediaDocument46#7afe8ae2 thumb:bytes thumb_w:int thumb_h:int mime_type:string size:int key:bytes iv:bytes attributes:Vector caption:string = DecryptedMessageMedia;
documentAttributeSticker#3a556302 alt:string stickerset:InputStickerSet = DocumentAttribute;
documentAttributeAudio#9852f9c6 flags:# voice:flags.10?true duration:int title:flags.0?string performer:flags.1?string waveform:flags.2?bytes = DocumentAttribute;
messageEntityUnknown#bb92ba95 offset:int length:int = MessageEntity;
@@ -117,6 +117,10 @@ messageEntityUnderline#9c4e7e8b offset:int length:int = MessageEntity;
messageEntityStrike#bf0693d4 offset:int length:int = MessageEntity;
messageEntityBlockquote#20df5d0 offset:int length:int = MessageEntity;
+// layer 143
+
+decryptedMessageMediaDocument#6abd9782 thumb:bytes thumb_w:int thumb_h:int mime_type:string size:long key:bytes iv:bytes attributes:Vector caption:string = DecryptedMessageMedia;
+
---functions---
test.dummyFunction = Bool;
diff --git a/td/generate/scheme/td_api.tl b/td/generate/scheme/td_api.tl
index 370fc4bdd..e34aa3775 100644
--- a/td/generate/scheme/td_api.tl
+++ b/td/generate/scheme/td_api.tl
@@ -142,7 +142,7 @@ temporaryPasswordState has_password:Bool valid_for:int32 = TemporaryPasswordStat
//@download_offset Download will be started from this offset. downloaded_prefix_size is calculated from this offset
//@downloaded_prefix_size If is_downloading_completed is false, then only some prefix of the file starting from download_offset is ready to be read. downloaded_prefix_size is the size of that prefix in bytes
//@downloaded_size Total downloaded file size, in bytes. Can be used only for calculating download progress. The actual file size may be bigger, and some parts of it may contain garbage
-localFile path:string can_be_downloaded:Bool can_be_deleted:Bool is_downloading_active:Bool is_downloading_completed:Bool download_offset:int32 downloaded_prefix_size:int32 downloaded_size:int32 = LocalFile;
+localFile path:string can_be_downloaded:Bool can_be_deleted:Bool is_downloading_active:Bool is_downloading_completed:Bool download_offset:int53 downloaded_prefix_size:int53 downloaded_size:int53 = LocalFile;
//@description Represents a remote file
//@id Remote file identifier; may be empty. Can be used by the current user across application restarts or even from other devices. Uniquely identifies a file, but a file can have a lot of different valid identifiers.
@@ -152,7 +152,7 @@ localFile path:string can_be_downloaded:Bool can_be_deleted:Bool is_downloading_
//@is_uploading_active True, if the file is currently being uploaded (or a remote copy is being generated by some other means)
//@is_uploading_completed True, if a remote copy is fully available
//@uploaded_size Size of the remote available part of the file, in bytes; 0 if unknown
-remoteFile id:string unique_id:string is_uploading_active:Bool is_uploading_completed:Bool uploaded_size:int32 = RemoteFile;
+remoteFile id:string unique_id:string is_uploading_active:Bool is_uploading_completed:Bool uploaded_size:int53 = RemoteFile;
//@description Represents a file
//@id Unique file identifier
@@ -160,7 +160,7 @@ remoteFile id:string unique_id:string is_uploading_active:Bool is_uploading_comp
//@expected_size Approximate file size in bytes in case the exact file size is unknown. Can be used to show download/upload progress
//@local Information about the local copy of the file
//@remote Information about the remote copy of the file
-file id:int32 size:int32 expected_size:int32 local:localFile remote:remoteFile = File;
+file id:int32 size:int53 expected_size:int53 local:localFile remote:remoteFile = File;
//@class InputFile @description Points to a file
@@ -179,7 +179,7 @@ inputFileLocal path:string = InputFile;
//@description A file generated by the application @original_path Local path to a file from which the file is generated; may be empty if there is no such file
//@conversion String specifying the conversion applied to the original file; must be persistent across application restarts. Conversions beginning with '#' are reserved for internal TDLib usage
//@expected_size Expected size of the generated file, in bytes; 0 if unknown
-inputFileGenerated original_path:string conversion:string expected_size:int32 = InputFile;
+inputFileGenerated original_path:string conversion:string expected_size:int53 = InputFile;
//@description Describes an image in JPEG format @type Image type (see https://core.telegram.org/constructor/photoSize)
@@ -296,8 +296,8 @@ photo has_stickers:Bool minithumbnail:minithumbnail sizes:vector = Ph
//@description Describes a sticker @set_id The identifier of the sticker set to which the sticker belongs; 0 if none @width Sticker width; as defined by the sender @height Sticker height; as defined by the sender
//@emoji Emoji corresponding to the sticker @type Sticker type @outline Sticker's outline represented as a list of closed vector paths; may be empty. The coordinate system origin is in the upper-left corner
-//@thumbnail Sticker thumbnail in WEBP or JPEG format; may be null @sticker File containing the sticker
-sticker set_id:int64 width:int32 height:int32 emoji:string type:StickerType outline:vector thumbnail:thumbnail sticker:file = Sticker;
+//@thumbnail Sticker thumbnail in WEBP or JPEG format; may be null @premium_animation Premium animation of the sticker; may be null. If present, only Premium users can send the sticker @sticker File containing the sticker
+sticker set_id:int64 width:int32 height:int32 emoji:string type:StickerType outline:vector thumbnail:thumbnail premium_animation:file sticker:file = Sticker;
//@description Describes a video file @duration Duration of the video, in seconds; as defined by the sender @width Video width; as defined by the sender @height Video height; as defined by the sender
//@file_name Original name of the file; as defined by the sender @mime_type MIME type of the file; as defined by the sender
@@ -311,9 +311,11 @@ video duration:int32 width:int32 height:int32 file_name:string mime_type:string
//@thumbnail Video thumbnail in JPEG format; as defined by the sender; may be null @video File containing the video
videoNote duration:int32 length:int32 minithumbnail:minithumbnail thumbnail:thumbnail video:file = VideoNote;
-//@description Describes a voice note. The voice note must be encoded with the Opus codec, and stored inside an OGG container. Voice notes can have only a single audio channel @duration Duration of the voice note, in seconds; as defined by the sender
-//@waveform A waveform representation of the voice note in 5-bit format @mime_type MIME type of the file; as defined by the sender @voice File containing the voice note
-voiceNote duration:int32 waveform:bytes mime_type:string voice:file = VoiceNote;
+//@description Describes a voice note. The voice note must be encoded with the Opus codec, and stored inside an OGG container. Voice notes can have only a single audio channel
+//@duration Duration of the voice note, in seconds; as defined by the sender @waveform A waveform representation of the voice note in 5-bit format
+//@mime_type MIME type of the file; as defined by the sender @is_recognized True, if speech recognition is completed; Premium users only
+//@recognized_text Recognized text of the voice note; Premium users only. Call recognizeSpeech to get recognized text of the voice note @voice File containing the voice note
+voiceNote duration:int32 waveform:bytes mime_type:string is_recognized:Bool recognized_text:string voice:file = VoiceNote;
//@description Describes an animated representation of an emoji
//@sticker Animated sticker for the emoji
@@ -419,8 +421,9 @@ animatedChatPhoto length:int32 file:file main_frame_timestamp:double = AnimatedC
//@added_date Point in time (Unix timestamp) when the photo has been added
//@minithumbnail Photo minithumbnail; may be null
//@sizes Available variants of the photo in JPEG format, in different size
-//@animation Animated variant of the photo in MPEG4 format; may be null
-chatPhoto id:int64 added_date:int32 minithumbnail:minithumbnail sizes:vector animation:animatedChatPhoto = ChatPhoto;
+//@animation A big (640x640) animated variant of the photo in MPEG4 format; may be null
+//@small_animation A small (160x160) animated variant of the photo in MPEG4 format; may be null even the big animation is available
+chatPhoto id:int64 added_date:int32 minithumbnail:minithumbnail sizes:vector animation:animatedChatPhoto small_animation:animatedChatPhoto = ChatPhoto;
//@description Contains a list of chat or user profile photos @total_count Total number of photos @photos List of photos
chatPhotos total_count:int32 photos:vector = ChatPhotos;
@@ -477,6 +480,7 @@ chatAdministratorRights can_manage_chat:Bool can_change_info:Bool can_post_messa
//@is_contact The user is a contact of the current user
//@is_mutual_contact The user is a contact of the current user and the current user is a contact of the user
//@is_verified True, if the user is verified
+//@is_premium True, if the user is a Telegram Premium user
//@is_support True, if the user is Telegram support account
//@restriction_reason If non-empty, it contains a human-readable description of the reason why access to this user must be restricted
//@is_scam True, if many users reported this user as a scam
@@ -484,16 +488,20 @@ chatAdministratorRights can_manage_chat:Bool can_change_info:Bool can_post_messa
//@have_access If false, the user is inaccessible, and the only information known about the user is inside this class. Identifier of the user can't be passed to any method except GetUser
//@type Type of the user
//@language_code IETF language tag of the user's language; only available to bots
-user id:int53 first_name:string last_name:string username:string phone_number:string status:UserStatus profile_photo:profilePhoto is_contact:Bool is_mutual_contact:Bool is_verified:Bool is_support:Bool restriction_reason:string is_scam:Bool is_fake:Bool have_access:Bool type:UserType language_code:string = User;
+//@added_to_attachment_menu True, if the user added the current bot to attachment menu; only available to bots
+user id:int53 first_name:string last_name:string username:string phone_number:string status:UserStatus profile_photo:profilePhoto is_contact:Bool is_mutual_contact:Bool is_verified:Bool is_premium:Bool is_support:Bool restriction_reason:string is_scam:Bool is_fake:Bool have_access:Bool type:UserType language_code:string added_to_attachment_menu:Bool = User;
//@description Contains information about a bot
//@share_text The text that is shown on the bot's profile page and is sent together with the link when users share the bot
//@param_description The text shown in the chat with the bot if the chat is empty
+//@photo Photo shown in the chat with the bot if the chat is empty; may be null
+//@animation Animation shown in the chat with the bot if the chat is empty; may be null
//@menu_button Information about a button to show instead of the bot commands menu button; may be null if ordinary bot commands menu must be shown
//@commands List of the bot commands
//@default_group_administrator_rights Default administrator rights for adding the bot to basic group and supergroup chats; may be null
//@default_channel_administrator_rights Default administrator rights for adding the bot to channels; may be null
-botInfo share_text:string description:string menu_button:botMenuButton commands:vector default_group_administrator_rights:chatAdministratorRights default_channel_administrator_rights:chatAdministratorRights = BotInfo;
+botInfo share_text:string description:string photo:photo animation:animation menu_button:botMenuButton commands:vector default_group_administrator_rights:chatAdministratorRights default_channel_administrator_rights:chatAdministratorRights = BotInfo;
+
//@description Contains full information about a user
//@photo User profile photo; may be null
@@ -503,10 +511,10 @@ botInfo share_text:string description:string menu_button:botMenuButton commands:
//@has_private_calls True, if the user can't be called due to their privacy settings
//@has_private_forwards True, if the user can't be linked in forwarded messages due to their privacy settings
//@need_phone_number_privacy_exception True, if the current user needs to explicitly allow to share their phone number with the user when the method addContact is used
-//@bio A short user bio
+//@bio A short user bio; may be null for bots
//@group_in_common_count Number of group chats where both the other user and the current user are a member; 0 for the current user
//@bot_info For bots, information about the bot; may be null
-userFullInfo photo:chatPhoto is_blocked:Bool can_be_called:Bool supports_video_calls:Bool has_private_calls:Bool has_private_forwards:Bool need_phone_number_privacy_exception:Bool bio:string group_in_common_count:int32 bot_info:botInfo = UserFullInfo;
+userFullInfo photo:chatPhoto is_blocked:Bool can_be_called:Bool supports_video_calls:Bool has_private_calls:Bool has_private_forwards:Bool need_phone_number_privacy_exception:Bool bio:formattedText group_in_common_count:int32 bot_info:botInfo = UserFullInfo;
//@description Represents a list of users @total_count Approximate total number of users found @user_ids A list of user identifiers
users total_count:int32 user_ids:vector = Users;
@@ -695,6 +703,8 @@ basicGroupFullInfo photo:chatPhoto description:string creator_user_id:int53 memb
//@has_linked_chat True, if the channel has a discussion group, or the supergroup is the designated discussion group for a channel
//@has_location True, if the supergroup is connected to a location, i.e. the supergroup is a location-based supergroup
//@sign_messages True, if messages sent to the channel need to contain information about the sender. This field is only applicable to channels
+//@join_to_send_messages True, if users need to join the supergroup before they can send messages. Always true for channels and non-discussion supergroups
+//@join_by_request True, if all users directly joining the supergroup need to be approved by supergroup administrators. Always false for channels and supergroups without username, location, or a linked chat
//@is_slow_mode_enabled True, if the slow mode is enabled in the supergroup
//@is_channel True, if the supergroup is a channel
//@is_broadcast_group True, if the supergroup is a broadcast group, i.e. only administrators can send messages and there is no limit on the number of members
@@ -702,7 +712,7 @@ basicGroupFullInfo photo:chatPhoto description:string creator_user_id:int53 memb
//@restriction_reason If non-empty, contains a human-readable description of the reason why access to this supergroup or channel must be restricted
//@is_scam True, if many users reported this supergroup or channel as a scam
//@is_fake True, if many users reported this supergroup or channel as a fake account
-supergroup id:int53 username:string date:int32 status:ChatMemberStatus member_count:int32 has_linked_chat:Bool has_location:Bool sign_messages:Bool is_slow_mode_enabled:Bool is_channel:Bool is_broadcast_group:Bool is_verified:Bool restriction_reason:string is_scam:Bool is_fake:Bool = Supergroup;
+supergroup id:int53 username:string date:int32 status:ChatMemberStatus member_count:int32 has_linked_chat:Bool has_location:Bool sign_messages:Bool join_to_send_messages:Bool join_by_request:Bool is_slow_mode_enabled:Bool is_channel:Bool is_broadcast_group:Bool is_verified:Bool restriction_reason:string is_scam:Bool is_fake:Bool = Supergroup;
//@description Contains full information about a supergroup or channel
//@photo Chat photo; may be null
@@ -748,7 +758,7 @@ secretChatStateClosed = SecretChatState;
//@is_outbound True, if the chat was created by the current user; otherwise false
//@key_hash Hash of the currently used key for comparison with the hash of the chat partner's key. This is a string of 36 little-endian bytes, which must be split into groups of 2 bits, each denoting a pixel of one of 4 colors FFFFFF, D5E6F3, 2D5775, and 2F99C9.
//-The pixels must be used to make a 12x12 square image filled from left to right, top to bottom. Alternatively, the first 32 bytes of the hash can be converted to the hexadecimal format and printed as 32 2-digit hex numbers
-//@layer Secret chat layer; determines features supported by the chat partner's application. Nested text entities and underline and strikethrough entities are supported if the layer >= 101
+//@layer Secret chat layer; determines features supported by the chat partner's application. Nested text entities and underline and strikethrough entities are supported if the layer >= 101, files bigger than 2000MB are supported if the layer >= 143
secretChat id:int32 user_id:int53 state:SecretChatState is_outbound:Bool key_hash:bytes layer:int32 = SecretChat;
@@ -897,11 +907,12 @@ messageCalendar total_count:int32 days:vector = MessageCalen
//@description Describes a sponsored message
//@message_id Message identifier; unique for the chat to which the sponsored message belongs among both ordinary and sponsored messages
+//@is_recommended True, if the message needs to be labeled as "recommended" instead of "sponsored"
//@sponsor_chat_id Sponsor chat identifier; 0 if the sponsor chat is accessible through an invite link
//@sponsor_chat_info Information about the sponsor chat; may be null unless sponsor_chat_id == 0
//@link An internal link to be opened when the sponsored message is clicked; may be null if the sponsor chat needs to be opened instead
//@content Content of the message. Currently, can be only of the type messageText
-sponsoredMessage message_id:int53 sponsor_chat_id:int53 sponsor_chat_info:chatInviteLinkInfo link:InternalLinkType content:MessageContent = SponsoredMessage;
+sponsoredMessage message_id:int53 is_recommended:Bool sponsor_chat_id:int53 sponsor_chat_info:chatInviteLinkInfo link:InternalLinkType content:MessageContent = SponsoredMessage;
//@description Describes a file added to file download list
@@ -980,9 +991,9 @@ chatTypeSecret secret_chat_id:int32 user_id:int53 = ChatType;
//@title The title of the filter; 1-12 characters without line feeds
//@icon_name The chosen icon name for short filter representation. If non-empty, must be one of "All", "Unread", "Unmuted", "Bots", "Channels", "Groups", "Private", "Custom", "Setup", "Cat", "Crown", "Favorite", "Flower", "Game", "Home", "Love", "Mask", "Party", "Sport", "Study", "Trade", "Travel", "Work".
//-If empty, use getChatFilterDefaultIconName to get default icon name for the filter
-//@pinned_chat_ids The chat identifiers of pinned chats in the filtered chat list
-//@included_chat_ids The chat identifiers of always included chats in the filtered chat list
-//@excluded_chat_ids The chat identifiers of always excluded chats in the filtered chat list
+//@pinned_chat_ids The chat identifiers of pinned chats in the filtered chat list. There can be up to GetOption("chat_filter_chosen_chat_count_max") pinned and always included non-secret chats and the same number of secret chats, but the limit can be increased with Telegram Premium
+//@included_chat_ids The chat identifiers of always included chats in the filtered chat list. There can be up to GetOption("chat_filter_chosen_chat_count_max") pinned and always included non-secret chats and the same number of secret chats, but the limit can be increased with Telegram Premium
+//@excluded_chat_ids The chat identifiers of always excluded chats in the filtered chat list. There can be up to GetOption("chat_filter_chosen_chat_count_max") always excluded non-secret chats and the same number of secret chats, but the limit can be increased with Telegram Premium
//@exclude_muted True, if muted chats need to be excluded
//@exclude_read True, if read chats need to be excluded
//@exclude_archived True, if archived chats need to be excluded
@@ -1143,7 +1154,7 @@ keyboardButtonTypeRequestLocation = KeyboardButtonType;
//@description A button that allows the user to create and send a poll when pressed; available only in private chats @force_regular If true, only regular polls must be allowed to create @force_quiz If true, only polls in quiz mode must be allowed to create
keyboardButtonTypeRequestPoll force_regular:Bool force_quiz:Bool = KeyboardButtonType;
-//@description A button that opens a web app by calling getWebAppUrl @url An HTTP URL to pass to getWebAppUrl
+//@description A button that opens a Web App by calling getWebAppUrl @url An HTTP URL to pass to getWebAppUrl
keyboardButtonTypeWebApp url:string = KeyboardButtonType;
@@ -1159,7 +1170,7 @@ inlineKeyboardButtonTypeUrl url:string = InlineKeyboardButtonType;
//@description A button that opens a specified URL and automatically authorize the current user by calling getLoginUrlInfo @url An HTTP URL to pass to getLoginUrlInfo @id Unique button identifier @forward_text If non-empty, new text of the button in forwarded messages
inlineKeyboardButtonTypeLoginUrl url:string id:int53 forward_text:string = InlineKeyboardButtonType;
-//@description A button that opens a web app by calling openWebApp @url An HTTP URL to pass to openWebApp
+//@description A button that opens a Web App by calling openWebApp @url An HTTP URL to pass to openWebApp
inlineKeyboardButtonTypeWebApp url:string = InlineKeyboardButtonType;
//@description A button that sends a callback query to a bot @data Data to be sent to the bot via a callback query
@@ -1219,7 +1230,7 @@ loginUrlInfoOpen url:string skip_confirm:Bool = LoginUrlInfo;
loginUrlInfoRequestConfirmation url:string domain:string bot_user_id:int53 request_write_access:Bool = LoginUrlInfo;
-//@description Contains information about a web app @launch_id Unique identifier for the web app launch @url A web app URL to open in a web view
+//@description Contains information about a Web App @launch_id Unique identifier for the Web App launch @url A Web App URL to open in a web view
webAppInfo launch_id:int64 url:string = WebAppInfo;
@@ -1481,19 +1492,21 @@ bankCardInfo title:string actions:vector = BankCardInfo;
address country_code:string state:string city:string street_line1:string street_line2:string postal_code:string = Address;
-//@description Contains parameters of the app theme @background_color A color of the background in the RGB24 format @text_color A color of text in the RGB24 format
-//@hint_color A color of hints in the RGB24 format @link_color A color of links in the RGB24 format @button_color A color of the buttons in the RGB24 format
+//@description Contains parameters of the application theme @background_color A color of the background in the RGB24 format @secondary_background_color A secondary color for the background in the RGB24 format
+//@text_color A color of text in the RGB24 format @hint_color A color of hints in the RGB24 format @link_color A color of links in the RGB24 format @button_color A color of the buttons in the RGB24 format
//@button_text_color A color of text on the buttons in the RGB24 format
-themeParameters background_color:int32 text_color:int32 hint_color:int32 link_color:int32 button_color:int32 button_text_color:int32 = ThemeParameters;
+themeParameters background_color:int32 secondary_background_color:int32 text_color:int32 hint_color:int32 link_color:int32 button_color:int32 button_text_color:int32 = ThemeParameters;
//@description Portion of the price of a product (e.g., "delivery cost", "tax amount") @label Label for this portion of the product price @amount Currency amount in the smallest units of the currency
labeledPricePart label:string amount:int53 = LabeledPricePart;
-//@description Product invoice @currency ISO 4217 currency code
+//@description Product invoice
+//@currency ISO 4217 currency code
//@price_parts A list of objects used to calculate the total price of the product
//@max_tip_amount The maximum allowed amount of tip in the smallest units of the currency
//@suggested_tip_amounts Suggested amounts of tip in the smallest units of the currency
+//@recurring_payment_terms_of_service_url An HTTP URL with terms of service for recurring payments. If non-empty, the invoice payment will result in recurring payments and the user must accept the terms of service before allowed to pay
//@is_test True, if the payment is a test payment
//@need_name True, if the user's name is needed for payment
//@need_phone_number True, if the user's phone number is needed for payment
@@ -1502,7 +1515,7 @@ labeledPricePart label:string amount:int53 = LabeledPricePart;
//@send_phone_number_to_provider True, if the user's phone number will be sent to the provider
//@send_email_address_to_provider True, if the user's email address will be sent to the provider
//@is_flexible True, if the total price depends on the shipping method
-invoice currency:string price_parts:vector max_tip_amount:int53 suggested_tip_amounts:vector is_test:Bool need_name:Bool need_phone_number:Bool need_email_address:Bool need_shipping_address:Bool send_phone_number_to_provider:Bool send_email_address_to_provider:Bool is_flexible:Bool = Invoice;
+invoice currency:string price_parts:vector max_tip_amount:int53 suggested_tip_amounts:vector recurring_payment_terms_of_service_url:string is_test:Bool need_name:Bool need_phone_number:Bool need_email_address:Bool need_shipping_address:Bool send_phone_number_to_provider:Bool send_email_address_to_provider:Bool is_flexible:Bool = Invoice;
//@description Order information @name Name of the user @phone_number Phone number of the user @email_address Email address of the user @shipping_address Shipping address for this order; may be null
orderInfo name:string phone_number:string email_address:string shipping_address:address = OrderInfo;
@@ -1513,6 +1526,7 @@ shippingOption id:string title:string price_parts:vector = Shi
//@description Contains information about saved card credentials @id Unique identifier of the saved credentials @title Title of the saved credentials
savedCredentials id:string title:string = SavedCredentials;
+
//@class InputCredentials @description Contains information about the payment method chosen by the user
//@description Applies if a user chooses some previously saved payment credentials. To use their previously saved credentials, the user must have a valid temporary password @saved_credentials_id Identifier of the saved credentials
@@ -1527,21 +1541,33 @@ inputCredentialsApplePay data:string = InputCredentials;
//@description Applies if a user enters new credentials using Google Pay @data JSON-encoded data with the credential identifier
inputCredentialsGooglePay data:string = InputCredentials;
+
+//@class PaymentProvider @description Contains information about a payment provider
+
+//@description Smart Glocal payment provider @public_token Public payment token
+paymentProviderSmartGlocal public_token:string = PaymentProvider;
+
//@description Stripe payment provider @publishable_key Stripe API publishable key @need_country True, if the user country must be provided @need_postal_code True, if the user ZIP/postal code must be provided @need_cardholder_name True, if the cardholder name must be provided
-paymentsProviderStripe publishable_key:string need_country:Bool need_postal_code:Bool need_cardholder_name:Bool = PaymentsProviderStripe;
+paymentProviderStripe publishable_key:string need_country:Bool need_postal_code:Bool need_cardholder_name:Bool = PaymentProvider;
+
+//@description Some other payment provider, for which a web payment form must be shown @url Payment form URL
+paymentProviderOther url:string = PaymentProvider;
+
//@description Contains information about an invoice payment form
//@id The payment form identifier
-//@invoice Full information of the invoice
-//@url Payment form URL
+//@invoice Full information about the invoice
//@seller_bot_user_id User identifier of the seller bot
-//@payments_provider_user_id User identifier of the payment provider bot
-//@payments_provider Information about the payment provider, if available, to support it natively without the need for opening the URL; may be null
+//@payment_provider_user_id User identifier of the payment provider bot
+//@payment_provider Information about the payment provider
//@saved_order_info Saved server-side order information; may be null
//@saved_credentials Information about saved card credentials; may be null
//@can_save_credentials True, if the user can choose to save credentials
//@need_password True, if the user will be able to save credentials protected by a password they set up
-paymentForm id:int64 invoice:invoice url:string seller_bot_user_id:int53 payments_provider_user_id:int53 payments_provider:paymentsProviderStripe saved_order_info:orderInfo saved_credentials:savedCredentials can_save_credentials:Bool need_password:Bool = PaymentForm;
+//@product_title Product title
+//@product_description Product description
+//@product_photo Product photo; may be null
+paymentForm id:int64 invoice:invoice seller_bot_user_id:int53 payment_provider_user_id:int53 payment_provider:PaymentProvider saved_order_info:orderInfo saved_credentials:savedCredentials can_save_credentials:Bool need_password:Bool product_title:string product_description:formattedText product_photo:photo = PaymentForm;
//@description Contains a temporary identifier of validated order information, which is stored for one hour. Also contains the available shipping options @order_info_id Temporary identifier of the order information @shipping_options Available shipping options
validatedOrderInfo order_info_id:string shipping_options:vector = ValidatedOrderInfo;
@@ -1555,13 +1581,22 @@ paymentResult success:Bool verification_url:string = PaymentResult;
//@photo Product photo; may be null
//@date Point in time (Unix timestamp) when the payment was made
//@seller_bot_user_id User identifier of the seller bot
-//@payments_provider_user_id User identifier of the payment provider bot
+//@payment_provider_user_id User identifier of the payment provider bot
//@invoice Information about the invoice
//@order_info Order information; may be null
//@shipping_option Chosen shipping option; may be null
//@credentials_title Title of the saved credentials chosen by the buyer
//@tip_amount The amount of tip chosen by the buyer in the smallest units of the currency
-paymentReceipt title:string description:string photo:photo date:int32 seller_bot_user_id:int53 payments_provider_user_id:int53 invoice:invoice order_info:orderInfo shipping_option:shippingOption credentials_title:string tip_amount:int53 = PaymentReceipt;
+paymentReceipt title:string description:formattedText photo:photo date:int32 seller_bot_user_id:int53 payment_provider_user_id:int53 invoice:invoice order_info:orderInfo shipping_option:shippingOption credentials_title:string tip_amount:int53 = PaymentReceipt;
+
+
+//@class InputInvoice @description Describe an invoice to process
+
+//@description An invoice from a message of the type messageInvoice @chat_id Chat identifier of the message @message_id Message identifier
+inputInvoiceMessage chat_id:int53 message_id:int53 = InputInvoice;
+
+//@description An invoice from a link of the type internalLinkTypeInvoice @name Name of the invoice
+inputInvoiceName name:string = InputInvoice;
//@description File with the date it was uploaded @file The file @date Point in time (Unix timestamp) when the file was uploaded
@@ -1834,8 +1869,8 @@ messagePhoto photo:photo caption:formattedText is_secret:Bool = MessageContent;
//@description An expired photo message (self-destructed after TTL has elapsed)
messageExpiredPhoto = MessageContent;
-//@description A sticker message @sticker The sticker description
-messageSticker sticker:sticker = MessageContent;
+//@description A sticker message @sticker The sticker description @is_premium True, if premium animation of the sticker must be played
+messageSticker sticker:sticker is_premium:Bool = MessageContent;
//@description A video message @video The video description @caption Video caption @is_secret True, if the video thumbnail must be blurred and the video must be shown only while tapped
messageVideo video:video caption:formattedText is_secret:Bool = MessageContent;
@@ -1881,7 +1916,7 @@ messagePoll poll:poll = MessageContent;
//@description A message with an invoice from a bot @title Product title @param_description Product description @photo Product photo; may be null @currency Currency for the product price @total_amount Product total price in the smallest units of the currency
//@start_parameter Unique invoice bot start_parameter. To share an invoice use the URL https://t.me/{bot_username}?start={start_parameter} @is_test True, if the invoice is a test invoice
//@need_shipping_address True, if the shipping address must be specified @receipt_message_id The identifier of the message with the receipt, after the product has been purchased
-messageInvoice title:string description:string photo:photo currency:string total_amount:int53 start_parameter:string is_test:Bool need_shipping_address:Bool receipt_message_id:int53 = MessageContent;
+messageInvoice title:string description:formattedText photo:photo currency:string total_amount:int53 start_parameter:string is_test:Bool need_shipping_address:Bool receipt_message_id:int53 = MessageContent;
//@description A message with information about an ended call @is_video True, if the call was a video call @discard_reason Reason why the call was discarded @duration Call duration, in seconds
messageCall is_video:Bool discard_reason:CallDiscardReason duration:int32 = MessageContent;
@@ -1949,13 +1984,16 @@ messageCustomServiceAction text:string = MessageContent;
//@description A new high score was achieved in a game @game_message_id Identifier of the message with the game, can be an identifier of a deleted message @game_id Identifier of the game; may be different from the games presented in the message with the game @score New score
messageGameScore game_message_id:int53 game_id:int64 score:int32 = MessageContent;
-//@description A payment has been completed @invoice_chat_id Identifier of the chat, containing the corresponding invoice message; 0 if unknown @invoice_message_id Identifier of the message with the corresponding invoice; can be an identifier of a deleted message @currency Currency for the price of the product @total_amount Total price for the product, in the smallest units of the currency
-messagePaymentSuccessful invoice_chat_id:int53 invoice_message_id:int53 currency:string total_amount:int53 = MessageContent;
+//@description A payment has been completed @invoice_chat_id Identifier of the chat, containing the corresponding invoice message; 0 if unknown @invoice_message_id Identifier of the message with the corresponding invoice; can be 0 or an identifier of a deleted message
+//@currency Currency for the price of the product @total_amount Total price for the product, in the smallest units of the currency
+//@is_recurring True, if this is a recurring payment @is_first_recurring True, if this is the first recurring payment @invoice_name Name of the invoice; may be empty if unknown
+messagePaymentSuccessful invoice_chat_id:int53 invoice_message_id:int53 currency:string total_amount:int53 is_recurring:Bool is_first_recurring:Bool invoice_name:string = MessageContent;
-//@description A payment has been completed; for bots only @currency Currency for price of the product
-//@total_amount Total price for the product, in the smallest units of the currency @invoice_payload Invoice payload @shipping_option_id Identifier of the shipping option chosen by the user; may be empty if not applicable @order_info Information about the order; may be null
+//@description A payment has been completed; for bots only @currency Currency for price of the product @total_amount Total price for the product, in the smallest units of the currency
+//@is_recurring True, if this is a recurring payment @is_first_recurring True, if this is the first recurring payment
+//@invoice_payload Invoice payload @shipping_option_id Identifier of the shipping option chosen by the user; may be empty if not applicable @order_info Information about the order; may be null
//@telegram_payment_charge_id Telegram payment identifier @provider_payment_charge_id Provider payment identifier
-messagePaymentSuccessfulBot currency:string total_amount:int53 invoice_payload:bytes shipping_option_id:string order_info:orderInfo telegram_payment_charge_id:string provider_payment_charge_id:string = MessageContent;
+messagePaymentSuccessfulBot currency:string total_amount:int53 is_recurring:Bool is_first_recurring:Bool invoice_payload:bytes shipping_option_id:string order_info:orderInfo telegram_payment_charge_id:string provider_payment_charge_id:string = MessageContent;
//@description A contact has registered with Telegram
messageContactRegistered = MessageContent;
@@ -1963,10 +2001,10 @@ messageContactRegistered = MessageContent;
//@description The current user has connected a website by logging in using Telegram Login Widget on it @domain_name Domain name of the connected website
messageWebsiteConnected domain_name:string = MessageContent;
-//@description Data from a web app has been sent to a bot @button_text Text of the keyboardButtonTypeWebApp button, which opened the web app
+//@description Data from a Web App has been sent to a bot @button_text Text of the keyboardButtonTypeWebApp button, which opened the Web App
messageWebAppDataSent button_text:string = MessageContent;
-//@description Data from a web app has been received; for bots only @button_text Text of the keyboardButtonTypeWebApp button, which opened the web app @data Received data
+//@description Data from a Web App has been received; for bots only @button_text Text of the keyboardButtonTypeWebApp button, which opened the Web App @data Received data
messageWebAppDataReceived button_text:string data:string = MessageContent;
//@description Telegram Passport data has been sent to a bot @types List of Telegram Passport element types sent
@@ -2089,7 +2127,7 @@ inputMessageAudio audio:InputFile album_cover_thumbnail:inputThumbnail duration:
//@description A document message (general file) @document Document to be sent @thumbnail Document thumbnail; pass null to skip thumbnail uploading @disable_content_type_detection If true, automatic file type detection will be disabled and the document will be always sent as file. Always true for files sent to secret chats @caption Document caption; pass null to use an empty caption; 0-GetOption("message_caption_length_max") characters
inputMessageDocument document:InputFile thumbnail:inputThumbnail disable_content_type_detection:Bool caption:formattedText = InputMessageContent;
-//@description A photo message @photo Photo to send @thumbnail Photo thumbnail to be sent; pass null to skip thumbnail uploading. The thumbnail is sent to the other party only in secret chats @added_sticker_file_ids File identifiers of the stickers added to the photo, if applicable @width Photo width @height Photo height @caption Photo caption; pass null to use an empty caption; 0-GetOption("message_caption_length_max") characters
+//@description A photo message @photo Photo to send. The photo must be at most 10 MB in size. The photo's width and height must not exceed 10000 in total. Width and height ratio must be at most 20 @thumbnail Photo thumbnail to be sent; pass null to skip thumbnail uploading. The thumbnail is sent to the other party only in secret chats @added_sticker_file_ids File identifiers of the stickers added to the photo, if applicable @width Photo width @height Photo height @caption Photo caption; pass null to use an empty caption; 0-GetOption("message_caption_length_max") characters
//@ttl Photo TTL (Time To Live), in seconds (0-60). A non-zero TTL can be specified only in private chats
inputMessagePhoto photo:InputFile thumbnail:inputThumbnail added_sticker_file_ids:vector width:int32 height:int32 caption:formattedText ttl:int32 = InputMessageContent;
@@ -2291,6 +2329,9 @@ stickerSetInfo id:int64 title:string name:string thumbnail:thumbnail thumbnail_o
//@description Represents a list of sticker sets @total_count Approximate total number of sticker sets found @sets List of sticker sets
stickerSets total_count:int32 sets:vector = StickerSets;
+//@description Represents a list of trending sticker sets @total_count Approximate total number of trending sticker sets @sets List of trending sticker sets @is_premium True, if the list contains sticker sets with premium stickers
+trendingStickerSets total_count:int32 sets:vector is_premium:Bool = TrendingStickerSets;
+
//@class CallDiscardReason @description Describes the reason why a call was discarded
@@ -2321,8 +2362,8 @@ callProtocol udp_p2p:Bool udp_reflector:Bool min_layer:int32 max_layer:int32 lib
//@class CallServerType @description Describes the type of a call server
-//@description A Telegram call reflector @peer_tag A peer tag to be used with the reflector
-callServerTypeTelegramReflector peer_tag:bytes = CallServerType;
+//@description A Telegram call reflector @peer_tag A peer tag to be used with the reflector @is_tcp True, if the server uses TCP instead of UDP
+callServerTypeTelegramReflector peer_tag:bytes is_tcp:Bool = CallServerType;
//@description A WebRTC server @username Username to be used for authentication @password Authentication password @supports_turn True, if the server supports TURN @supports_stun True, if the server supports STUN
callServerTypeWebrtc username:string password:string supports_turn:Bool supports_stun:Bool = CallServerType;
@@ -2490,14 +2531,18 @@ addedReaction reaction:string sender_id:MessageSender = AddedReaction;
//@description Represents a list of reactions added to a message @total_count The total number of found reactions @reactions The list of added reactions @next_offset The offset for the next request. If empty, there are no more results
addedReactions total_count:int32 reactions:vector next_offset:string = AddedReactions;
+//@description Represents an available reaction @reaction Text representation of the reaction @needs_premium True, if Telegram Premium is needed to send the reaction
+availableReaction reaction:string needs_premium:Bool = AvailableReaction;
+
//@description Represents a list of available reactions @reactions List of reactions
-availableReactions reactions:vector = AvailableReactions;
+availableReactions reactions:vector = AvailableReactions;
//@description Contains stickers which must be used for reaction animation rendering
//@reaction Text representation of the reaction
//@title Reaction title
//@is_active True, if the reaction can be added to new messages and enabled in chats
+//@is_premium True, if the reaction is available only for Premium users
//@static_icon Static icon for the reaction
//@appear_animation Appear animation for the reaction
//@select_animation Select animation for the reaction
@@ -2505,7 +2550,7 @@ availableReactions reactions:vector = AvailableReactions;
//@effect_animation Effect animation for the reaction
//@around_animation Around animation for the reaction; may be null
//@center_animation Center animation for the reaction; may be null
-reaction reaction:string title:string is_active:Bool static_icon:sticker appear_animation:sticker select_animation:sticker activate_animation:sticker effect_animation:sticker around_animation:sticker center_animation:sticker = Reaction;
+reaction reaction:string title:string is_active:Bool is_premium:Bool static_icon:sticker appear_animation:sticker select_animation:sticker activate_animation:sticker effect_animation:sticker around_animation:sticker center_animation:sticker = Reaction;
//@description Represents a list of animations @animations List of animations
@@ -2536,6 +2581,12 @@ attachmentMenuBotColor light_color:int32 dark_color:int32 = AttachmentMenuBotCol
//@description Represents a bot added to attachment menu
//@bot_user_id User identifier of the bot added to attachment menu
+//@supports_self_chat True, if the bot supports opening from attachment menu in the chat with the bot
+//@supports_user_chats True, if the bot supports opening from attachment menu in private chats with ordinary users
+//@supports_bot_chats True, if the bot supports opening from attachment menu in private chats with other bots
+//@supports_group_chats True, if the bot supports opening from attachment menu in basic group and supergroup chats
+//@supports_channel_chats True, if the bot supports opening from attachment menu in channel chats
+//@supports_settings True, if the bot supports "settings_button_pressed" event
//@name Name for the bot in attachment menu
//@name_color Color to highlight selected name of the bot if appropriate; may be null
//@default_icon Default attachment menu icon for the bot in SVG format; may be null
@@ -2544,7 +2595,8 @@ attachmentMenuBotColor light_color:int32 dark_color:int32 = AttachmentMenuBotCol
//@android_icon Attachment menu icon for the bot in TGS format for the official Android app; may be null
//@macos_icon Attachment menu icon for the bot in TGS format for the official native macOS app; may be null
//@icon_color Color to highlight selected icon of the bot if appropriate; may be null
-attachmentMenuBot bot_user_id:int53 name:string name_color:attachmentMenuBotColor default_icon:file ios_static_icon:file ios_animated_icon:file android_icon:file macos_icon:file icon_color:attachmentMenuBotColor = AttachmentMenuBot;
+//@web_app_placeholder Default placeholder for opened Web Apps in SVG format; may be null
+attachmentMenuBot bot_user_id:int53 supports_self_chat:Bool supports_user_chats:Bool supports_bot_chats:Bool supports_group_chats:Bool supports_channel_chats:Bool supports_settings:Bool name:string name_color:attachmentMenuBotColor default_icon:file ios_static_icon:file ios_animated_icon:file android_icon:file macos_icon:file icon_color:attachmentMenuBotColor web_app_placeholder:file = AttachmentMenuBot;
//@description Information about the message sent by answerWebAppQuery @inline_message_id Identifier of the sent inline message, if known
sentWebAppMessage inline_message_id:string = SentWebAppMessage;
@@ -2864,6 +2916,109 @@ languagePackInfo id:string base_language_pack_id:string name:string native_name:
localizationTargetInfo language_packs:vector = LocalizationTargetInfo;
+//@class PremiumLimitType @description Describes type of a limit, increased for Premium users
+
+//@description The maximum number of joined supergroups and channels
+premiumLimitTypeSupergroupCount = PremiumLimitType;
+
+//@description The maximum number of pinned chats in the main chat list
+premiumLimitTypePinnedChatCount = PremiumLimitType;
+
+//@description The maximum number of created public chats
+premiumLimitTypeCreatedPublicChatCount = PremiumLimitType;
+
+//@description The maximum number of saved animations
+premiumLimitTypeSavedAnimationCount = PremiumLimitType;
+
+//@description The maximum number of favorite stickers
+premiumLimitTypeFavoriteStickerCount = PremiumLimitType;
+
+//@description The maximum number of chat filters
+premiumLimitTypeChatFilterCount = PremiumLimitType;
+
+//@description The maximum number of pinned and always included, or always excluded chats in a chat filter
+premiumLimitTypeChatFilterChosenChatCount = PremiumLimitType;
+
+//@description The maximum number of pinned chats in the archive chat list
+premiumLimitTypePinnedArchivedChatCount = PremiumLimitType;
+
+//@description The maximum length of sent media caption
+premiumLimitTypeCaptionLength = PremiumLimitType;
+
+//@description The maximum length of the user's bio
+premiumLimitTypeBioLength = PremiumLimitType;
+
+
+//@class PremiumFeature @description Describes a feature available to Premium users
+
+//@description Increased limits
+premiumFeatureIncreasedLimits = PremiumFeature;
+
+//@description Increased maximum upload file size
+premiumFeatureIncreasedUploadFileSize = PremiumFeature;
+
+//@description Improved download speed
+premiumFeatureImprovedDownloadSpeed = PremiumFeature;
+
+//@description The ability to convert voice notes to text
+premiumFeatureVoiceRecognition = PremiumFeature;
+
+//@description Disabled ads
+premiumFeatureDisabledAds = PremiumFeature;
+
+//@description Allowed to use more reactions
+premiumFeatureUniqueReactions = PremiumFeature;
+
+//@description Allowed to use premium stickers with unique effects
+premiumFeatureUniqueStickers = PremiumFeature;
+
+//@description Ability to change position of the main chat list, archive and mute all new chats from non-contacts, and completely disable notifications about the user's contacts joined Telegram
+premiumFeatureAdvancedChatManagement = PremiumFeature;
+
+//@description A badge in the user's profile
+premiumFeatureProfileBadge = PremiumFeature;
+
+//@description Profile photo animation on message and chat screens
+premiumFeatureAnimatedProfilePhoto = PremiumFeature;
+
+//@description Allowed to set a premium appllication icons
+premiumFeatureAppIcons = PremiumFeature;
+
+
+//@description Contains information about a limit, increased for Premium users @type The type of the limit @default_value Default value of the limit @premium_value Value of the limit for Premium users
+premiumLimit type:PremiumLimitType default_value:int32 premium_value:int32 = PremiumLimit;
+
+//@description Contains information about features, available to Premium users @features The list of available features @limits The list of limits, increased for Premium users
+//@payment_link An internal link to be opened to pay for Telegram Premium if store payment isn't possible; may be null if direct payment isn't available. If the link has type internalLinkTypeBotStart, then sendBotStartMessage must be called automatically
+premiumFeatures features:vector limits:vector payment_link:InternalLinkType = PremiumFeatures;
+
+
+//@class PremiumSource @description Describes a source from which the Premium features screen is opened
+
+//@description A limit was exceeded @limit_type Type of the exceeded limit
+premiumSourceLimitExceeded limit_type:PremiumLimitType = PremiumSource;
+
+//@description A user tried to use a Premium feature @feature The used feature
+premiumSourceFeature feature:PremiumFeature = PremiumSource;
+
+//@description A user opened an internal link of the type internalLinkTypePremiumFeatures @referrer The referrer from the link
+premiumSourceLink referrer:string = PremiumSource;
+
+//@description A user opened the Premium features screen from settings
+premiumSourceSettings = PremiumSource;
+
+
+//@description Describes a promotion animation for a Premium feature @feature Premium feature @animation Promotion animation for the feature
+premiumFeaturePromotionAnimation feature:PremiumFeature animation:animation = PremiumFeaturePromotionAnimation;
+
+//@description Contains state of Telegram Premium subscription and promotion videos for Premium features
+//@state Text description of the state of the current Premium subscription; may be empty if the current user has no Telegram Premium subscription
+//@currency ISO 4217 currency code for Telegram Premium subscription payment
+//@monthly_amount Monthly subscription payment for Telegram Premium subscription, in the smallest units of the currency
+//@animations The list of available promotion animations for Premium features
+premiumState state:formattedText currency:string monthly_amount:int53 animations:vector = PremiumState;
+
+
//@class DeviceToken @description Represents a data needed to subscribe for push notifications through registerDevice method. To use specific push notification service, the correct application platform must be specified and a valid server authentication data must be uploaded at https://my.telegram.org
//@description A token for Firebase Cloud Messaging @token Device registration token; may be empty to deregister a device @encrypt True, if push notifications must be additionally encrypted
@@ -3130,6 +3285,9 @@ pushMessageContentChatJoinByLink = PushMessageContent;
//@description A new member was accepted to the chat by an administrator
pushMessageContentChatJoinByRequest = PushMessageContent;
+//@description A new recurrent payment was made by the current user @amount The paid amount
+pushMessageContentRecurringPayment amount:string = PushMessageContent;
+
//@description A forwarded messages @total_count Number of forwarded messages
pushMessageContentMessageForwards total_count:int32 = PushMessageContent;
@@ -3140,8 +3298,8 @@ pushMessageContentMediaAlbum total_count:int32 has_photos:Bool has_videos:Bool h
//@class NotificationType @description Contains detailed information about a notification
-//@description New message was received @message The message
-notificationTypeNewMessage message:message = NotificationType;
+//@description New message was received @message The message @show_preview True, if message content must be displayed in notifications
+notificationTypeNewMessage message:message show_preview:Bool = NotificationType;
//@description New secret chat was created
notificationTypeNewSecretChat = NotificationType;
@@ -3416,17 +3574,33 @@ chatReportReasonPersonalDetails = ChatReportReason;
chatReportReasonCustom = ChatReportReason;
-//@class InternalLinkType @description Describes an internal https://t.me or tg: link, which must be processed by the app in a special way
+//@class TargetChat @description Describes the target chat to be opened
-//@description The link is a link to the active sessions section of the app. Use getActiveSessions to handle the link
+//@description The currently opened chat needs to be kept
+targetChatCurrent = TargetChat;
+
+//@description The chat needs to be chosen by the user among chats of the specified types
+//@allow_user_chats True, if private chats with ordinary users are allowed
+//@allow_bot_chats True, if private chats with other bots are allowed
+//@allow_group_chats True, if basic group and supergroup chats are allowed
+//@allow_channel_chats True, if channel chats are allowed
+targetChatChosen allow_user_chats:Bool allow_bot_chats:Bool allow_group_chats:Bool allow_channel_chats:Bool = TargetChat;
+
+//@description The chat needs to be open with the provided internal link @link An internal link pointing to the chat
+targetChatInternalLink link:InternalLinkType = TargetChat;
+
+
+//@class InternalLinkType @description Describes an internal https://t.me or tg: link, which must be processed by the application in a special way
+
+//@description The link is a link to the active sessions section of the application. Use getActiveSessions to handle the link
internalLinkTypeActiveSessions = InternalLinkType;
-//@description The link is a link to an attachment menu bot to be opened in the specified chat. Process given chat_link to open corresponding chat.
+//@description The link is a link to an attachment menu bot to be opened in the specified or a chosen chat. Process given target_chat to open the chat.
//-Then call searchPublicChat with the given bot username, check that the user is a bot and can be added to attachment menu. Then use getAttachmentMenuBot to receive information about the bot.
//-If the bot isn't added to attachment menu, then user needs to confirm adding the bot to attachment menu. If user confirms adding, then use toggleBotIsAddedToAttachmentMenu to add it.
-//-If attachment menu bots can't be used in the current chat, show an error to the user. If the bot is added to attachment menu, then use openWebApp with the given URL
-//@chat_link An internal link pointing to a chat; may be null if the current chat needs to be kept @bot_username Username of the bot @url URL to be passed to openWebApp
-internalLinkTypeAttachmentMenuBot chat_link:InternalLinkType bot_username:string url:string = InternalLinkType;
+//-If the attachment menu bot can't be used in the opened chat, show an error to the user. If the bot is added to attachment menu and can be used in the chat, then use openWebApp with the given URL
+//@target_chat Target chat to be opened @bot_username Username of the bot @url URL to be passed to openWebApp
+internalLinkTypeAttachmentMenuBot target_chat:TargetChat bot_username:string url:string = InternalLinkType;
//@description The link contains an authentication code. Call checkAuthenticationCode with the code if the current authorization state is authorizationStateWaitCode @code The authentication code
internalLinkTypeAuthenticationCode code:string = InternalLinkType;
@@ -3467,6 +3641,9 @@ internalLinkTypeFilterSettings = InternalLinkType;
//@bot_username Username of the bot that owns the game @game_short_name Short name of the game
internalLinkTypeGame bot_username:string game_short_name:string = InternalLinkType;
+//@description The link is a link to an invoice. Call getPaymentForm with the given invoice name to process the link @invoice_name Name of the invoice
+internalLinkTypeInvoice invoice_name:string = InternalLinkType;
+
//@description The link is a link to a language pack. Call getLanguagePackInfo with the given language pack identifier to process the link @language_pack_id Language pack identifier
internalLinkTypeLanguagePack language_pack_id:string = InternalLinkType;
@@ -3480,7 +3657,7 @@ internalLinkTypeMessage url:string = InternalLinkType;
//@text Message draft text @contains_link True, if the first line of the text contains a link. If true, the input field needs to be focused and the text after the link must be selected
internalLinkTypeMessageDraft text:formattedText contains_link:Bool = InternalLinkType;
-//@description The link contains a request of Telegram passport data. Call getPassportAuthorizationForm with the given parameters to process the link if the link was received from outside of the app, otherwise ignore it
+//@description The link contains a request of Telegram passport data. Call getPassportAuthorizationForm with the given parameters to process the link if the link was received from outside of the application, otherwise ignore it
//@bot_user_id User identifier of the service's bot @scope Telegram Passport element types requested by the service @public_key Service's public key @nonce Unique request identifier provided by the service
//@callback_url An HTTP URL to open once the request is finished or canceled with the parameter tg_passport=success or tg_passport=cancel respectively. If empty, then the link tgbot{bot_user_id}://passport/success or tgbot{bot_user_id}://passport/cancel needs to be opened instead
internalLinkTypePassportDataRequest bot_user_id:int53 scope:string public_key:string nonce:string callback_url:string = InternalLinkType;
@@ -3489,6 +3666,9 @@ internalLinkTypePassportDataRequest bot_user_id:int53 scope:string public_key:st
//@hash Hash value from the link @phone_number Phone number value from the link
internalLinkTypePhoneNumberConfirmation hash:string phone_number:string = InternalLinkType;
+//@description The link is a link to the Premium features screen of the applcation from which the user can subscribe to Telegram Premium. Call getPremiumFeatures with the given referrer to process the link @referrer Referrer specified in the link
+internalLinkTypePremiumFeatures referrer:string = InternalLinkType;
+
//@description The link is a link to the privacy and security settings section of the app
internalLinkTypePrivacyAndSecuritySettings = InternalLinkType;
@@ -3503,7 +3683,7 @@ internalLinkTypePublicChat chat_username:string = InternalLinkType;
//-"This code can be used to allow someone to log in to your Telegram account. To confirm Telegram login, please go to Settings > Devices > Scan QR and scan the code" needs to be shown
internalLinkTypeQrCodeAuthentication = InternalLinkType;
-//@description The link is a link to app settings
+//@description The link is a link to application settings
internalLinkTypeSettings = InternalLinkType;
//@description The link is a link to a sticker set. Call searchStickerSet with the given sticker set name to process the link and show the sticker set @sticker_set_name Name of the sticker set
@@ -3669,7 +3849,7 @@ networkStatistics since_date:int32 entries:vector = Netw
//@preload_large_videos True, if the beginning of video files needs to be preloaded for instant playback
//@preload_next_audio True, if the next audio track needs to be preloaded while the user is listening to an audio file
//@use_less_data_for_calls True, if "use less data for calls" option needs to be enabled
-autoDownloadSettings is_auto_download_enabled:Bool max_photo_file_size:int32 max_video_file_size:int32 max_other_file_size:int32 video_upload_bitrate:int32 preload_large_videos:Bool preload_next_audio:Bool use_less_data_for_calls:Bool = AutoDownloadSettings;
+autoDownloadSettings is_auto_download_enabled:Bool max_photo_file_size:int32 max_video_file_size:int53 max_other_file_size:int53 video_upload_bitrate:int32 preload_large_videos:Bool preload_next_audio:Bool use_less_data_for_calls:Bool = AutoDownloadSettings;
//@description Contains auto-download settings presets for the current user
//@low Preset with lowest settings; supposed to be used by default when roaming
@@ -3771,6 +3951,9 @@ text text:string = Text;
//@description Contains a value representing a number of seconds @seconds Number of seconds
seconds seconds:double = Seconds;
+//@description Contains size of downloaded prefix of a file @size The prefix size, in bytes
+fileDownloadedPrefixSize size:int53 = FileDownloadedPrefixSize;
+
//@description Contains information about a tg: deep link @text Text to be shown to the user @need_update_application True, if the user must be asked to update the application
deepLinkInfo text:formattedText need_update_application:Bool = DeepLinkInfo;
@@ -4058,8 +4241,8 @@ updateChatIsBlocked chat_id:int53 is_blocked:Bool = Update;
//@description A chat was marked as unread or was read @chat_id Chat identifier @is_marked_as_unread New value of is_marked_as_unread
updateChatIsMarkedAsUnread chat_id:int53 is_marked_as_unread:Bool = Update;
-//@description The list of chat filters or a chat filter has changed @chat_filters The new list of chat filters
-updateChatFilters chat_filters:vector = Update;
+//@description The list of chat filters or a chat filter has changed @chat_filters The new list of chat filters @main_chat_list_position Position of the main chat list among chat filters, 0-based
+updateChatFilters chat_filters:vector main_chat_list_position:int32 = Update;
//@description The number of online group members has changed. This update with non-zero number of online group members is sent only for currently opened chats. There is no guarantee that it will be sent just after the number of online users has changed @chat_id Identifier of the chat @online_member_count New number of online members in the chat, or 0 if unknown
updateChatOnlineMemberCount chat_id:int53 online_member_count:int32 = Update;
@@ -4196,7 +4379,7 @@ updateStickerSet sticker_set:stickerSet = Update;
updateInstalledStickerSets is_masks:Bool sticker_set_ids:vector = Update;
//@description The list of trending sticker sets was updated or some of them were viewed @sticker_sets The prefix of the list of trending sticker sets with the newest trending sticker sets
-updateTrendingStickerSets sticker_sets:stickerSets = Update;
+updateTrendingStickerSets sticker_sets:trendingStickerSets = Update;
//@description The list of recently used stickers was updated @is_attached True, if the list of stickers attached to photo or video files was updated, otherwise the list of sent stickers is updated @sticker_ids The new list of file identifiers of recently used stickers
updateRecentStickers is_attached:Bool sticker_ids:vector = Update;
@@ -4228,10 +4411,10 @@ updateTermsOfService terms_of_service_id:string terms_of_service:termsOfService
//@description The list of users nearby has changed. The update is guaranteed to be sent only 60 seconds after a successful searchChatsNearby request @users_nearby The new list of users nearby
updateUsersNearby users_nearby:vector = Update;
-//@description The list of bots added to attachment menu has changed @bots The new list of bots added to attachment menu. The bots must be shown in attachment menu only in private chats. The bots must not be shown on scheduled messages screen
+//@description The list of bots added to attachment menu has changed @bots The new list of bots added to attachment menu. The bots must not be shown on scheduled messages screen
updateAttachmentMenuBots bots:vector = Update;
-//@description A message was sent by an opened web app, so the web app needs to be closed @web_app_launch_id Identifier of web app launch
+//@description A message was sent by an opened Web App, so the Web App needs to be closed @web_app_launch_id Identifier of Web App launch
updateWebAppMessageSent web_app_launch_id:int64 = Update;
//@description The list of supported reactions has changed @reactions The new list of supported reactions
@@ -4558,13 +4741,13 @@ checkChatUsername chat_id:int53 username:string = CheckChatUsernameResult;
//@description Returns a list of public chats of the specified type, owned by the user @type Type of the public chats to return
getCreatedPublicChats type:PublicChatType = Chats;
-//@description Checks whether the maximum number of owned public chats has been reached. Returns corresponding error if the limit was reached @type Type of the public chats, for which to check the limit
+//@description Checks whether the maximum number of owned public chats has been reached. Returns corresponding error if the limit was reached. The limit can be increased with Telegram Premium @type Type of the public chats, for which to check the limit
checkCreatedPublicChatsLimit type:PublicChatType = Ok;
//@description Returns a list of basic group and supergroup chats, which can be used as a discussion group for a channel. Returned basic group chats must be first upgraded to supergroups before they can be set as a discussion group. To set a returned supergroup as a discussion group, access to its old messages must be enabled using toggleSupergroupIsAllHistoryAvailable first
getSuitableDiscussionChats = Chats;
-//@description Returns a list of recently inactive supergroups and channels. Can be used when user reaches limit on the number of joined supergroups and channels and receives CHANNELS_TOO_MUCH error
+//@description Returns a list of recently inactive supergroups and channels. Can be used when user reaches limit on the number of joined supergroups and channels and receives CHANNELS_TOO_MUCH error. Also, the limit can be increased with Telegram Premium
getInactiveSupergroupChats = Chats;
@@ -4715,6 +4898,14 @@ getMessageLinkInfo url:string = MessageLinkInfo;
//@to_language_code A two-letter ISO 639-1 language code of the language to which the message is translated
translateText text:string from_language_code:string to_language_code:string = Text;
+//@description Recognizes speech in a voice note message. The message must be successfully sent and must not be scheduled. May return an error with a message "MSG_VOICE_TOO_LONG" if the voice note is too long to be recognized
+//@chat_id Identifier of the chat to which the message belongs
+//@message_id Identifier of the message
+recognizeSpeech chat_id:int53 message_id:int53 = Ok;
+
+//@description Rates recognized speech in a voice note message @chat_id Identifier of the chat to which the message belongs @message_id Identifier of the message @is_good Pass true if the speech recognition is good
+rateSpeechRecognition chat_id:int53 message_id:int53 is_good:Bool = Ok;
+
//@description Returns list of message sender identifiers, which can be used to send messages in a chat @chat_id Chat identifier
getChatAvailableMessageSenders chat_id:int53 = MessageSenders;
@@ -4866,7 +5057,7 @@ editInlineMessageReplyMarkup inline_message_id:string reply_markup:ReplyMarkup =
editMessageSchedulingState chat_id:int53 message_id:int53 scheduling_state:MessageSchedulingState = Ok;
-//@description Returns reactions, which can be added to a message. The list can change after updateReactions, updateChatAvailableReactions for the chat, or updateMessageInteractionInfo for the message
+//@description Returns reactions, which can be added to a message. The list can change after updateReactions, updateChatAvailableReactions for the chat, or updateMessageInteractionInfo for the message. The method will return Premium reactions, even the current user has no Premium subscription
//@chat_id Identifier of the chat to which the message belongs
//@message_id Identifier of the message
getMessageAvailableReactions chat_id:int53 message_id:int53 = AvailableReactions;
@@ -4978,30 +5169,30 @@ getInlineQueryResults bot_user_id:int53 chat_id:int53 user_location:location que
answerInlineQuery inline_query_id:int64 is_personal:Bool results:vector cache_time:int32 next_offset:string switch_pm_text:string switch_pm_parameter:string = Ok;
-//@description Returns an HTTPS URL of a web app to open after keyboardButtonTypeWebApp button is pressed
+//@description Returns an HTTPS URL of a Web App to open after keyboardButtonTypeWebApp button is pressed
//@bot_user_id Identifier of the target bot
//@url The URL from the keyboardButtonTypeWebApp button
-//@theme Preferred web app theme; pass null to use the default theme
+//@theme Preferred Web App theme; pass null to use the default theme
getWebAppUrl bot_user_id:int53 url:string theme:themeParameters = HttpUrl;
-//@description Sends data received from a keyboardButtonTypeWebApp web app to a bot
-//@bot_user_id Identifier of the target bot @button_text Text of the keyboardButtonTypeWebApp button, which opened the web app @data Received data
+//@description Sends data received from a keyboardButtonTypeWebApp Web App to a bot
+//@bot_user_id Identifier of the target bot @button_text Text of the keyboardButtonTypeWebApp button, which opened the Web App @data Received data
sendWebAppData bot_user_id:int53 button_text:string data:string = Ok;
-//@description Informs TDLib that a web app is being opened from attachment menu, a botMenuButton button, an internalLinkTypeAttachmentMenuBot link, or an inlineKeyboardButtonTypeWebApp button.
+//@description Informs TDLib that a Web App is being opened from attachment menu, a botMenuButton button, an internalLinkTypeAttachmentMenuBot link, or an inlineKeyboardButtonTypeWebApp button.
//-For each bot, a confirmation alert about data sent to the bot must be shown once
-//@chat_id Identifier of the chat in which the web app is opened. Web apps can be opened only in private chats for now
-//@bot_user_id Identifier of the bot, providing the web app
+//@chat_id Identifier of the chat in which the Web App is opened
+//@bot_user_id Identifier of the bot, providing the Web App
//@url The URL from an inlineKeyboardButtonTypeWebApp button, a botMenuButton button, or an internalLinkTypeAttachmentMenuBot link, or an empty string otherwise
-//@theme Preferred web app theme; pass null to use the default theme
-//@reply_to_message_id Identifier of the replied message for the message sent by the web app; 0 if none
+//@theme Preferred Web App theme; pass null to use the default theme
+//@reply_to_message_id Identifier of the replied message for the message sent by the Web App; 0 if none
openWebApp chat_id:int53 bot_user_id:int53 url:string theme:themeParameters reply_to_message_id:int53 = WebAppInfo;
-//@description Informs TDLib that a previously opened web app was closed @web_app_launch_id Identifier of web app launch, received from openWebApp
+//@description Informs TDLib that a previously opened Web App was closed @web_app_launch_id Identifier of Web App launch, received from openWebApp
closeWebApp web_app_launch_id:int64 = Ok;
-//@description Sets the result of interaction with a web app and sends corresponding message on behalf of the user to the chat from which the query originated; for bots only
-//@web_app_query_id Identifier of the web app query
+//@description Sets the result of interaction with a Web App and sends corresponding message on behalf of the user to the chat from which the query originated; for bots only
+//@web_app_query_id Identifier of the Web App query
//@result The result of the query
answerWebAppQuery web_app_query_id:string result:InputInlineQueryResult = SentWebAppMessage;
@@ -5123,7 +5314,7 @@ addChatToList chat_id:int53 chat_list:ChatList = Ok;
//@description Returns information about a chat filter by its identifier @chat_filter_id Chat filter identifier
getChatFilter chat_filter_id:int32 = ChatFilter;
-//@description Creates new chat filter. Returns information about the created chat filter @filter Chat filter
+//@description Creates new chat filter. Returns information about the created chat filter. There can be up to GetOption("chat_filter_count_max") chat filters, but the limit can be increased with Telegram Premium @filter Chat filter
createChatFilter filter:chatFilter = ChatFilterInfo;
//@description Edits existing chat filter. Returns information about the edited chat filter @chat_filter_id Chat filter identifier @filter The edited chat filter
@@ -5132,8 +5323,8 @@ editChatFilter chat_filter_id:int32 filter:chatFilter = ChatFilterInfo;
//@description Deletes existing chat filter @chat_filter_id Chat filter identifier
deleteChatFilter chat_filter_id:int32 = Ok;
-//@description Changes the order of chat filters @chat_filter_ids Identifiers of chat filters in the new correct order
-reorderChatFilters chat_filter_ids:vector = Ok;
+//@description Changes the order of chat filters @chat_filter_ids Identifiers of chat filters in the new correct order @main_chat_list_position Position of the main chat list among chat filters, 0-based. Can be non-zero only for Premium users
+reorderChatFilters chat_filter_ids:vector main_chat_list_position:int32 = Ok;
//@description Returns recommended chat filters for the current user
getRecommendedChatFilters = RecommendedChatFilters;
@@ -5212,7 +5403,7 @@ unpinChatMessage chat_id:int53 message_id:int53 = Ok;
unpinAllChatMessages chat_id:int53 = Ok;
-//@description Adds the current user as a new member to a chat. Private and secret chats can't be joined using this method @chat_id Chat identifier
+//@description Adds the current user as a new member to a chat. Private and secret chats can't be joined using this method. May return an error with a message "INVITE_REQUEST_SENT" if only a join request was created @chat_id Chat identifier
joinChat chat_id:int53 = Ok;
//@description Removes the current user from chat members. Private and secret chats can't be left using this method @chat_id Chat identifier
@@ -5290,7 +5481,7 @@ setScopeNotificationSettings scope:NotificationSettingsScope notification_settin
resetAllNotificationSettings = Ok;
-//@description Changes the pinned state of a chat. There can be up to GetOption("pinned_chat_count_max")/GetOption("pinned_archived_chat_count_max") pinned non-secret chats and the same number of secret chats in the main/archive chat list
+//@description Changes the pinned state of a chat. There can be up to GetOption("pinned_chat_count_max")/GetOption("pinned_archived_chat_count_max") pinned non-secret chats and the same number of secret chats in the main/archive chat list. The limit can be increased with Telegram Premium
//@chat_list Chat list in which to change the pinned state of the chat @chat_id Chat identifier @is_pinned Pass true to pin the chat; pass false to unpin it
toggleChatIsPinned chat_list:ChatList chat_id:int53 is_pinned:Bool = Ok;
@@ -5311,10 +5502,10 @@ toggleBotIsAddedToAttachmentMenu bot_user_id:int53 is_added:Bool = Ok;
//@offset The starting position from which the file needs to be downloaded
//@limit Number of bytes which need to be downloaded starting from the "offset" position before the download will automatically be canceled; use 0 to download without a limit
//@synchronous Pass true to return response only after the file download has succeeded, has failed, has been canceled, or a new downloadFile request with different offset/limit parameters was sent; pass false to return file state immediately, just after the download has been started
-downloadFile file_id:int32 priority:int32 offset:int32 limit:int32 synchronous:Bool = File;
+downloadFile file_id:int32 priority:int32 offset:int53 limit:int53 synchronous:Bool = File;
//@description Returns file downloaded prefix size from a given offset, in bytes @file_id Identifier of the file @offset Offset from which downloaded prefix size needs to be calculated
-getFileDownloadedPrefixSize file_id:int32 offset:int32 = Count;
+getFileDownloadedPrefixSize file_id:int32 offset:int53 = FileDownloadedPrefixSize;
//@description Stops the downloading of a file. If a file has already been downloaded, does nothing @file_id Identifier of a file to stop downloading @only_if_pending Pass true to stop downloading only if it hasn't been started, i.e. request hasn't been sent to server
cancelDownloadFile file_id:int32 only_if_pending:Bool = Ok;
@@ -5333,13 +5524,13 @@ cancelUploadFile file_id:int32 = Ok;
//@description Writes a part of a generated file. This method is intended to be used only if the application has no direct access to TDLib's file system, because it is usually slower than a direct write to the destination file
//@generation_id The identifier of the generation process @offset The offset from which to write the data to the file @data The data to write
-writeGeneratedFilePart generation_id:int64 offset:int32 data:bytes = Ok;
+writeGeneratedFilePart generation_id:int64 offset:int53 data:bytes = Ok;
//@description Informs TDLib on a file generation progress
//@generation_id The identifier of the generation process
//@expected_size Expected size of the generated file, in bytes; 0 if unknown
//@local_prefix_size The number of bytes already generated
-setFileGenerationProgress generation_id:int64 expected_size:int32 local_prefix_size:int32 = Ok;
+setFileGenerationProgress generation_id:int64 expected_size:int53 local_prefix_size:int53 = Ok;
//@description Finishes the file generation
//@generation_id The identifier of the generation process
@@ -5350,7 +5541,7 @@ finishFileGeneration generation_id:int64 error:error = Ok;
//@file_id Identifier of the file. The file must be located in the TDLib file cache
//@offset The offset from which to read the file
//@count Number of bytes to read. An error will be returned if there are not enough bytes available in the file from the specified position. Pass 0 to read all available data from the specified position
-readFilePart file_id:int32 offset:int32 count:int32 = FilePart;
+readFilePart file_id:int32 offset:int53 count:int53 = FilePart;
//@description Deletes a file from the TDLib file cache @file_id Identifier of the file to delete
deleteFile file_id:int32 = Ok;
@@ -5389,7 +5580,7 @@ removeAllFilesFromDownloads only_active:Bool only_completed:Bool delete_from_cac
searchFileDownloads query:string only_active:Bool only_completed:Bool offset:string limit:int32 = FoundFileDownloads;
-//@description Returns information about a file with messages exported from another app @message_file_head Beginning of the message file; up to 100 first lines
+//@description Returns information about a file with messages exported from another application @message_file_head Beginning of the message file; up to 100 first lines
getMessageFileType message_file_head:string = MessageFileType;
//@description Returns a confirmation text to be shown to the user before starting message import
@@ -5461,7 +5652,7 @@ deleteAllRevokedChatInviteLinks chat_id:int53 creator_user_id:int53 = Ok;
//@description Checks the validity of an invite link for a chat and returns information about the corresponding chat @invite_link Invite link to be checked
checkChatInviteLink invite_link:string = ChatInviteLinkInfo;
-//@description Uses an invite link to add the current user to the chat if possible @invite_link Invite link to use
+//@description Uses an invite link to add the current user to the chat if possible. May return an error with a message "INVITE_REQUEST_SENT" if only a join request was created @invite_link Invite link to use
joinChatByInviteLink invite_link:string = Chat;
//@description Returns pending join requests in a chat
@@ -5694,7 +5885,7 @@ getArchivedStickerSets is_masks:Bool offset_sticker_set_id:int64 limit:int32 = S
//@description Returns a list of trending sticker sets. For optimal performance, the number of returned sticker sets is chosen by TDLib
//@offset The offset from which to return the sticker sets; must be non-negative
//@limit The maximum number of sticker sets to be returned; up to 100. For optimal performance, the number of returned sticker sets is chosen by TDLib and can be smaller than the specified limit, even if the end of the list has not been reached
-getTrendingStickerSets offset:int32 limit:int32 = StickerSets;
+getTrendingStickerSets offset:int32 limit:int32 = TrendingStickerSets;
//@description Returns a list of sticker sets attached to a file. Currently, only photos and videos can have attached sticker sets @file_id File identifier
getAttachedStickerSets file_id:int32 = StickerSets;
@@ -5752,6 +5943,9 @@ searchEmojis text:string exact_match:Bool input_language_codes:vector =
//@description Returns an animated emoji corresponding to a given emoji. Returns a 404 error if the emoji has no animated emoji @emoji The emoji
getAnimatedEmoji emoji:string = AnimatedEmoji;
+//@description Returns all emojis, which has a corresponding animated emoji
+getAllAnimatedEmojis = Emojis;
+
//@description Returns an HTTP URL which can be used to automatically log in to the translation platform and suggest new emoji replacements. The URL will be valid for 30 seconds after generation @language_code Language code for which the emoji replacements will be suggested
getEmojiSuggestionsUrl language_code:string = HttpUrl;
@@ -5794,7 +5988,7 @@ deleteProfilePhoto profile_photo_id:int64 = Ok;
//@description Changes the first and last name of the current user @first_name The new value of the first name for the current user; 1-64 characters @last_name The new value of the optional last name for the current user; 0-64 characters
setName first_name:string last_name:string = Ok;
-//@description Changes the bio of the current user @bio The new value of the user bio; 0-70 characters without line feeds
+//@description Changes the bio of the current user @bio The new value of the user bio; 0-GetOption("bio_length_max") characters without line feeds
setBio bio:string = Ok;
//@description Changes the username of the current user @username The new value of the username. Use an empty string to remove the username
@@ -5883,6 +6077,12 @@ setSupergroupStickerSet supergroup_id:int53 sticker_set_id:int64 = Ok;
//@description Toggles whether sender signature is added to sent messages in a channel; requires can_change_info administrator right @supergroup_id Identifier of the channel @sign_messages New value of sign_messages
toggleSupergroupSignMessages supergroup_id:int53 sign_messages:Bool = Ok;
+//@description Toggles whether joining is mandatory to send messages to a discussion supergroup; requires can_restrict_members administrator right @supergroup_id Identifier of the supergroup @join_to_send_messages New value of join_to_send_messages
+toggleSupergroupJoinToSendMessages supergroup_id:int53 join_to_send_messages:Bool = Ok;
+
+//@description Toggles whether all users directly joining the supergroup need to be approved by supergroup administrators; requires can_restrict_members administrator right @supergroup_id Identifier of the channel @join_by_request New value of join_by_request
+toggleSupergroupJoinByRequest supergroup_id:int53 join_by_request:Bool = Ok;
+
//@description Toggles whether the message history of a supergroup is available to new members; requires can_change_info administrator right @supergroup_id The identifier of the supergroup @is_all_history_available The new value of is_all_history_available
toggleSupergroupIsAllHistoryAvailable supergroup_id:int53 is_all_history_available:Bool = Ok;
@@ -5908,22 +6108,20 @@ getChatEventLog chat_id:int53 query:string from_event_id:int64 limit:int32 filte
//@description Returns an invoice payment form. This method must be called when the user presses inlineKeyboardButtonBuy
-//@chat_id Chat identifier of the Invoice message
-//@message_id Message identifier
+//@input_invoice The invoice
//@theme Preferred payment form theme; pass null to use the default theme
-getPaymentForm chat_id:int53 message_id:int53 theme:themeParameters = PaymentForm;
+getPaymentForm input_invoice:InputInvoice theme:themeParameters = PaymentForm;
//@description Validates the order information provided by a user and returns the available shipping options for a flexible invoice
-//@chat_id Chat identifier of the Invoice message
-//@message_id Message identifier
+//@input_invoice The invoice
//@order_info The order information, provided by the user; pass null if empty
//@allow_save Pass true to save the order information
-validateOrderInfo chat_id:int53 message_id:int53 order_info:orderInfo allow_save:Bool = ValidatedOrderInfo;
+validateOrderInfo input_invoice:InputInvoice order_info:orderInfo allow_save:Bool = ValidatedOrderInfo;
-//@description Sends a filled-out payment form to the bot for final verification @chat_id Chat identifier of the Invoice message @message_id Message identifier
+//@description Sends a filled-out payment form to the bot for final verification @input_invoice The invoice
//@payment_form_id Payment form identifier returned by getPaymentForm @order_info_id Identifier returned by validateOrderInfo, or an empty string @shipping_option_id Identifier of a chosen shipping option, if applicable
//@credentials The credentials chosen by user for payment @tip_amount Chosen by the user amount of tip in the smallest units of the currency
-sendPaymentForm chat_id:int53 message_id:int53 payment_form_id:int64 order_info_id:string shipping_option_id:string credentials:InputCredentials tip_amount:int53 = PaymentResult;
+sendPaymentForm input_invoice:InputInvoice payment_form_id:int64 order_info_id:string shipping_option_id:string credentials:InputCredentials tip_amount:int53 = PaymentResult;
//@description Returns information about a successful payment @chat_id Chat identifier of the PaymentSuccessful message @message_id Message identifier
getPaymentReceipt chat_id:int53 message_id:int53 = PaymentReceipt;
@@ -5938,6 +6136,10 @@ deleteSavedOrderInfo = Ok;
deleteSavedCredentials = Ok;
+//@description Creates a link for the given invoice; for bots only @invoice Information about the invoice of the type inputMessageInvoice
+createInvoiceLink invoice:InputMessageContent = HttpUrl;
+
+
//@description Returns a user that can be contacted to get support
getSupportUser = User;
@@ -6197,7 +6399,7 @@ addStickerToSet user_id:int53 name:string sticker:inputSticker = StickerSet;
setStickerSetThumbnail user_id:int53 name:string thumbnail:InputFile = StickerSet;
//@description Changes the position of a sticker in the set to which it belongs; for bots only. The sticker set must have been created by the bot
-//@sticker Sticker @position New position of the sticker in the set, zero-based
+//@sticker Sticker @position New position of the sticker in the set, 0-based
setStickerPositionInSet sticker:InputFile position:int32 = Ok;
//@description Removes a sticker from the set to which it belongs; for bots only. The sticker set must have been created by the bot @sticker Sticker
@@ -6208,6 +6410,25 @@ removeStickerFromSet sticker:InputFile = Ok;
getMapThumbnailFile location:location zoom:int32 width:int32 height:int32 scale:int32 chat_id:int53 = File;
+//@description Returns information about a limit, increased for Premium users. Returns a 404 error if the limit is unknown @limit_type Type of the limit
+getPremiumLimit limit_type:PremiumLimitType = PremiumLimit;
+
+//@description Returns information about features, available to Premium users @source Source of the request; pass null if the method is called from some non-standard source
+getPremiumFeatures source:PremiumSource = PremiumFeatures;
+
+//@description Returns examples of premium stickers for demonstration purposes
+getPremiumStickers = Stickers;
+
+//@description Informs TDLib that the user viewed detailed information about a Premium feature on the Premium features screen @feature The viewed premium feature
+viewPremiumFeature feature:PremiumFeature = Ok;
+
+//@description Informs TDLib that the user clicked Premium subscription button on the Premium features screen
+clickPremiumSubscriptionButton = Ok;
+
+//@description Returns state of Telegram Premium subscription and promotion videos for Premium features
+getPremiumState = PremiumState;
+
+
//@description Accepts Telegram terms of services @terms_of_service_id Terms of service identifier
acceptTermsOfService terms_of_service_id:string = Ok;
diff --git a/td/generate/scheme/telegram_api.tl b/td/generate/scheme/telegram_api.tl
index 5d6f3d2b1..61e68c5f9 100644
--- a/td/generate/scheme/telegram_api.tl
+++ b/td/generate/scheme/telegram_api.tl
@@ -100,7 +100,7 @@ storage.fileMp4#b3cea0e4 = storage.FileType;
storage.fileWebp#1081464c = storage.FileType;
userEmpty#d3bc4b7a id:long = User;
-user#3ff6ecb0 flags:# self:flags.10?true contact:flags.11?true mutual_contact:flags.12?true deleted:flags.13?true bot:flags.14?true bot_chat_history:flags.15?true bot_nochats:flags.16?true verified:flags.17?true restricted:flags.18?true min:flags.20?true bot_inline_geo:flags.21?true support:flags.23?true scam:flags.24?true apply_min_photo:flags.25?true fake:flags.26?true bot_attach_menu:flags.27?true id:long access_hash:flags.0?long first_name:flags.1?string last_name:flags.2?string username:flags.3?string phone:flags.4?string photo:flags.5?UserProfilePhoto status:flags.6?UserStatus bot_info_version:flags.14?int restriction_reason:flags.18?Vector bot_inline_placeholder:flags.19?string lang_code:flags.22?string = User;
+user#3ff6ecb0 flags:# self:flags.10?true contact:flags.11?true mutual_contact:flags.12?true deleted:flags.13?true bot:flags.14?true bot_chat_history:flags.15?true bot_nochats:flags.16?true verified:flags.17?true restricted:flags.18?true min:flags.20?true bot_inline_geo:flags.21?true support:flags.23?true scam:flags.24?true apply_min_photo:flags.25?true fake:flags.26?true bot_attach_menu:flags.27?true premium:flags.28?true attach_menu_enabled:flags.29?true id:long access_hash:flags.0?long first_name:flags.1?string last_name:flags.2?string username:flags.3?string phone:flags.4?string photo:flags.5?UserProfilePhoto status:flags.6?UserStatus bot_info_version:flags.14?int restriction_reason:flags.18?Vector bot_inline_placeholder:flags.19?string lang_code:flags.22?string = User;
userProfilePhotoEmpty#4f11bae1 = UserProfilePhoto;
userProfilePhoto#82d1f706 flags:# has_video:flags.0?true photo_id:long stripped_thumb:flags.1?bytes dc_id:int = UserProfilePhoto;
@@ -115,7 +115,7 @@ userStatusLastMonth#77ebc742 = UserStatus;
chatEmpty#29562865 id:long = Chat;
chat#41cbf256 flags:# creator:flags.0?true left:flags.2?true deactivated:flags.5?true call_active:flags.23?true call_not_empty:flags.24?true noforwards:flags.25?true id:long title:string photo:ChatPhoto participants_count:int date:int version:int migrated_to:flags.6?InputChannel admin_rights:flags.14?ChatAdminRights default_banned_rights:flags.18?ChatBannedRights = Chat;
chatForbidden#6592a1a7 id:long title:string = Chat;
-channel#8261ac61 flags:# creator:flags.0?true left:flags.2?true broadcast:flags.5?true verified:flags.7?true megagroup:flags.8?true restricted:flags.9?true signatures:flags.11?true min:flags.12?true scam:flags.19?true has_link:flags.20?true has_geo:flags.21?true slowmode_enabled:flags.22?true call_active:flags.23?true call_not_empty:flags.24?true fake:flags.25?true gigagroup:flags.26?true noforwards:flags.27?true id:long access_hash:flags.13?long title:string username:flags.6?string photo:ChatPhoto date:int restriction_reason:flags.9?Vector admin_rights:flags.14?ChatAdminRights banned_rights:flags.15?ChatBannedRights default_banned_rights:flags.18?ChatBannedRights participants_count:flags.17?int = Chat;
+channel#8261ac61 flags:# creator:flags.0?true left:flags.2?true broadcast:flags.5?true verified:flags.7?true megagroup:flags.8?true restricted:flags.9?true signatures:flags.11?true min:flags.12?true scam:flags.19?true has_link:flags.20?true has_geo:flags.21?true slowmode_enabled:flags.22?true call_active:flags.23?true call_not_empty:flags.24?true fake:flags.25?true gigagroup:flags.26?true noforwards:flags.27?true join_to_send:flags.28?true join_request:flags.29?true id:long access_hash:flags.13?long title:string username:flags.6?string photo:ChatPhoto date:int restriction_reason:flags.9?Vector admin_rights:flags.14?ChatAdminRights banned_rights:flags.15?ChatBannedRights default_banned_rights:flags.18?ChatBannedRights participants_count:flags.17?int = Chat;
channelForbidden#17d493d5 flags:# broadcast:flags.5?true megagroup:flags.8?true id:long access_hash:long title:string until_date:flags.16?int = Chat;
chatFull#d18ee226 flags:# can_set_username:flags.7?true has_scheduled:flags.8?true id:long about:string participants:ChatParticipants chat_photo:flags.2?Photo notify_settings:PeerNotifySettings exported_invite:flags.13?ExportedChatInvite bot_info:flags.3?Vector pinned_msg_id:flags.6?int folder_id:flags.11?int call:flags.12?InputGroupCall ttl_period:flags.14?int groupcall_default_join_as:flags.15?Peer theme_emoticon:flags.16?string requests_pending:flags.17?int recent_requesters:flags.17?Vector available_reactions:flags.18?Vector = ChatFull;
@@ -140,7 +140,7 @@ messageMediaPhoto#695150d7 flags:# photo:flags.0?Photo ttl_seconds:flags.2?int =
messageMediaGeo#56e0d474 geo:GeoPoint = MessageMedia;
messageMediaContact#70322949 phone_number:string first_name:string last_name:string vcard:string user_id:long = MessageMedia;
messageMediaUnsupported#9f84f49e = MessageMedia;
-messageMediaDocument#9cb070d7 flags:# document:flags.0?Document ttl_seconds:flags.2?int = MessageMedia;
+messageMediaDocument#9cb070d7 flags:# nopremium:flags.3?true document:flags.0?Document ttl_seconds:flags.2?int = MessageMedia;
messageMediaWebPage#a32dd600 webpage:WebPage = MessageMedia;
messageMediaVenue#2ec0533f geo:GeoPoint title:string address:string provider:string venue_id:string venue_type:string = MessageMedia;
messageMediaGame#fdb19008 game:Game = MessageMedia;
@@ -163,8 +163,8 @@ messageActionChannelMigrateFrom#ea3948e9 title:string chat_id:long = MessageActi
messageActionPinMessage#94bd38ed = MessageAction;
messageActionHistoryClear#9fbab604 = MessageAction;
messageActionGameScore#92a72876 game_id:long score:int = MessageAction;
-messageActionPaymentSentMe#8f31b327 flags:# currency:string total_amount:long payload:bytes info:flags.0?PaymentRequestedInfo shipping_option_id:flags.1?string charge:PaymentCharge = MessageAction;
-messageActionPaymentSent#40699cd0 currency:string total_amount:long = MessageAction;
+messageActionPaymentSentMe#8f31b327 flags:# recurring_init:flags.2?true recurring_used:flags.3?true currency:string total_amount:long payload:bytes info:flags.0?PaymentRequestedInfo shipping_option_id:flags.1?string charge:PaymentCharge = MessageAction;
+messageActionPaymentSent#96163f56 flags:# recurring_init:flags.2?true recurring_used:flags.3?true currency:string total_amount:long invoice_slug:flags.0?string = MessageAction;
messageActionPhoneCall#80e11a7f flags:# video:flags.2?true call_id:long reason:flags.0?PhoneCallDiscardReason duration:flags.1?int = MessageAction;
messageActionScreenshotTaken#4792929b = MessageAction;
messageActionCustomAction#fae69f56 message:string = MessageAction;
@@ -380,6 +380,7 @@ updateAttachMenuBots#17b7a20b = Update;
updateWebViewResultSent#1592b79d query_id:long = Update;
updateBotMenuButton#14b85813 bot_id:long button:BotMenuButton = Update;
updateSavedRingtones#74d8be99 = Update;
+updateTranscribedAudio#84cd5a flags:# pending:flags.0?true peer:Peer msg_id:int transcription_id:long text:string = Update;
updates.state#a56c2a3e pts:int qts:int date:int seq:int unread_count:int = updates.State;
@@ -404,9 +405,9 @@ photos.photo#20212ca8 photo:Photo users:Vector = photos.Photo;
upload.file#96a18d5 type:storage.FileType mtime:int bytes:bytes = upload.File;
upload.fileCdnRedirect#f18cda44 dc_id:int file_token:bytes encryption_key:bytes encryption_iv:bytes file_hashes:Vector = upload.File;
-dcOption#18b7a10d flags:# ipv6:flags.0?true media_only:flags.1?true tcpo_only:flags.2?true cdn:flags.3?true static:flags.4?true id:int ip_address:string port:int secret:flags.10?bytes = DcOption;
+dcOption#18b7a10d flags:# ipv6:flags.0?true media_only:flags.1?true tcpo_only:flags.2?true cdn:flags.3?true static:flags.4?true this_port_only:flags.5?true id:int ip_address:string port:int secret:flags.10?bytes = DcOption;
-config#330b4067 flags:# phonecalls_enabled:flags.1?true default_p2p_contacts:flags.3?true preload_featured_stickers:flags.4?true ignore_phone_entities:flags.5?true revoke_pm_inbox:flags.6?true blocked_mode:flags.8?true pfs_enabled:flags.13?true date:int expires:int test_mode:Bool this_dc:int dc_options:Vector dc_txt_domain_name:string chat_size_max:int megagroup_size_max:int forwarded_count_max:int online_update_period_ms:int offline_blur_timeout_ms:int offline_idle_timeout_ms:int online_cloud_timeout_ms:int notify_cloud_delay_ms:int notify_default_delay_ms:int push_chat_period_ms:int push_chat_limit:int saved_gifs_limit:int edit_time_limit:int revoke_time_limit:int revoke_pm_time_limit:int rating_e_decay:int stickers_recent_limit:int stickers_faved_limit:int channels_read_media_period:int tmp_sessions:flags.0?int pinned_dialogs_count_max:int pinned_infolder_count_max:int call_receive_timeout_ms:int call_ring_timeout_ms:int call_connect_timeout_ms:int call_packet_timeout_ms:int me_url_prefix:string autoupdate_url_prefix:flags.7?string gif_search_username:flags.9?string venue_search_username:flags.10?string img_search_username:flags.11?string static_maps_provider:flags.12?string caption_length_max:int message_length_max:int webfile_dc_id:int suggested_lang_code:flags.2?string lang_pack_version:flags.2?int base_lang_pack_version:flags.2?int = Config;
+config#330b4067 flags:# phonecalls_enabled:flags.1?true default_p2p_contacts:flags.3?true preload_featured_stickers:flags.4?true ignore_phone_entities:flags.5?true revoke_pm_inbox:flags.6?true blocked_mode:flags.8?true pfs_enabled:flags.13?true force_try_ipv6:flags.14?true date:int expires:int test_mode:Bool this_dc:int dc_options:Vector dc_txt_domain_name:string chat_size_max:int megagroup_size_max:int forwarded_count_max:int online_update_period_ms:int offline_blur_timeout_ms:int offline_idle_timeout_ms:int online_cloud_timeout_ms:int notify_cloud_delay_ms:int notify_default_delay_ms:int push_chat_period_ms:int push_chat_limit:int saved_gifs_limit:int edit_time_limit:int revoke_time_limit:int revoke_pm_time_limit:int rating_e_decay:int stickers_recent_limit:int stickers_faved_limit:int channels_read_media_period:int tmp_sessions:flags.0?int pinned_dialogs_count_max:int pinned_infolder_count_max:int call_receive_timeout_ms:int call_ring_timeout_ms:int call_connect_timeout_ms:int call_packet_timeout_ms:int me_url_prefix:string autoupdate_url_prefix:flags.7?string gif_search_username:flags.9?string venue_search_username:flags.10?string img_search_username:flags.11?string static_maps_provider:flags.12?string caption_length_max:int message_length_max:int webfile_dc_id:int suggested_lang_code:flags.2?string lang_pack_version:flags.2?int base_lang_pack_version:flags.2?int = Config;
nearestDc#8e1a1775 country:string this_dc:int nearest_dc:int = NearestDc;
@@ -424,7 +425,7 @@ encryptedChatDiscarded#1e1c7c45 flags:# history_deleted:flags.0?true id:int = En
inputEncryptedChat#f141b5e1 chat_id:int access_hash:long = InputEncryptedChat;
encryptedFileEmpty#c21f497e = EncryptedFile;
-encryptedFile#4a70994c id:long access_hash:long size:int dc_id:int key_fingerprint:int = EncryptedFile;
+encryptedFile#a8008cd8 id:long access_hash:long size:long dc_id:int key_fingerprint:int = EncryptedFile;
inputEncryptedFileEmpty#1837c364 = InputEncryptedFile;
inputEncryptedFileUploaded#64bd0306 id:long parts:int md5_checksum:string key_fingerprint:int = InputEncryptedFile;
@@ -444,7 +445,7 @@ inputDocumentEmpty#72f0eaae = InputDocument;
inputDocument#1abfb575 id:long access_hash:long file_reference:bytes = InputDocument;
documentEmpty#36f8c871 id:long = Document;
-document#1e87342b flags:# id:long access_hash:long file_reference:bytes date:int mime_type:string size:int thumbs:flags.0?Vector video_thumbs:flags.1?Vector dc_id:int attributes:Vector = Document;
+document#8fd4c4d8 flags:# id:long access_hash:long file_reference:bytes date:int mime_type:string size:long thumbs:flags.0?Vector video_thumbs:flags.1?Vector dc_id:int attributes:Vector = Document;
help.support#17c6b5f6 phone_number:string user:User = help.Support;
@@ -552,6 +553,7 @@ auth.passwordRecovery#137948a5 email_pattern:string = auth.PasswordRecovery;
receivedNotifyMessage#a384b779 id:int flags:int = ReceivedNotifyMessage;
chatInviteExported#ab4a819 flags:# revoked:flags.0?true permanent:flags.5?true request_needed:flags.6?true link:string admin_id:long date:int start_date:flags.4?int expire_date:flags.1?int usage_limit:flags.2?int usage:flags.3?int requested:flags.7?int title:flags.8?string = ExportedChatInvite;
+chatInvitePublicJoinRequests#ed107ab7 = ExportedChatInvite;
chatInviteAlready#5a686d7c chat:Chat = ChatInvite;
chatInvite#300c44c1 flags:# channel:flags.0?true broadcast:flags.1?true public:flags.2?true megagroup:flags.3?true request_needed:flags.6?true title:string about:flags.5?string photo:Photo participants_count:int participants:flags.4?Vector = ChatInvite;
@@ -571,7 +573,7 @@ messages.stickerSetNotModified#d3f924eb = messages.StickerSet;
botCommand#c27ac8c7 command:string description:string = BotCommand;
-botInfo#e4169b5d user_id:long description:string commands:Vector menu_button:BotMenuButton = BotInfo;
+botInfo#8f300b57 flags:# user_id:flags.0?long description:flags.1?string description_photo:flags.4?Photo description_document:flags.5?Document commands:flags.2?Vector menu_button:flags.3?BotMenuButton = BotInfo;
keyboardButton#a2fa4880 text:string = KeyboardButton;
keyboardButtonUrl#258aff05 text:string url:string = KeyboardButton;
@@ -730,7 +732,7 @@ draftMessageEmpty#1b0c841a flags:# date:flags.0?int = DraftMessage;
draftMessage#fd8e711f flags:# no_webpage:flags.1?true reply_to_msg_id:flags.0?int message:string entities:flags.3?Vector date:int = DraftMessage;
messages.featuredStickersNotModified#c6dc0c66 count:int = messages.FeaturedStickers;
-messages.featuredStickers#84c02310 hash:long count:int sets:Vector unread:Vector = messages.FeaturedStickers;
+messages.featuredStickers#be382906 flags:# premium:flags.0?true hash:long count:int sets:Vector unread:Vector = messages.FeaturedStickers;
messages.recentStickersNotModified#b17f890 = messages.RecentStickers;
messages.recentStickers#88d37c56 hash:long packs:Vector stickers:Vector dates:Vector = messages.RecentStickers;
@@ -813,7 +815,7 @@ dataJSON#7d748d04 data:string = DataJSON;
labeledPrice#cb296bf8 label:string amount:long = LabeledPrice;
-invoice#cd886e0 flags:# test:flags.0?true name_requested:flags.1?true phone_requested:flags.2?true email_requested:flags.3?true shipping_address_requested:flags.4?true flexible:flags.5?true phone_to_provider:flags.6?true email_to_provider:flags.7?true currency:string prices:Vector max_tip_amount:flags.8?long suggested_tip_amounts:flags.8?Vector = Invoice;
+invoice#3e85a91b flags:# test:flags.0?true name_requested:flags.1?true phone_requested:flags.2?true email_requested:flags.3?true shipping_address_requested:flags.4?true flexible:flags.5?true phone_to_provider:flags.6?true email_to_provider:flags.7?true recurring:flags.9?true currency:string prices:Vector max_tip_amount:flags.8?long suggested_tip_amounts:flags.8?Vector recurring_terms_url:flags.9?string = Invoice;
paymentCharge#ea02c27e id:string provider_charge_id:string = PaymentCharge;
@@ -833,7 +835,7 @@ inputWebFileGeoPointLocation#9f2221c9 geo_point:InputGeoPoint access_hash:long w
upload.webFile#21e753bc size:int mime_type:string file_type:storage.FileType mtime:int bytes:bytes = upload.WebFile;
-payments.paymentForm#1694761b flags:# can_save_credentials:flags.2?true password_missing:flags.3?true form_id:long bot_id:long invoice:Invoice provider_id:long url:string native_provider:flags.4?string native_params:flags.4?DataJSON saved_info:flags.0?PaymentRequestedInfo saved_credentials:flags.1?PaymentSavedCredentials users:Vector = payments.PaymentForm;
+payments.paymentForm#b0133b37 flags:# can_save_credentials:flags.2?true password_missing:flags.3?true form_id:long bot_id:long title:string description:string photo:flags.5?WebDocument invoice:Invoice provider_id:long url:string native_provider:flags.4?string native_params:flags.4?DataJSON saved_info:flags.0?PaymentRequestedInfo saved_credentials:flags.1?PaymentSavedCredentials users:Vector = payments.PaymentForm;
payments.validatedRequestedInfo#d1451883 flags:# id:flags.0?string shipping_options:flags.1?Vector = payments.ValidatedRequestedInfo;
@@ -864,7 +866,7 @@ phoneCallAccepted#3660c311 flags:# video:flags.6?true id:long access_hash:long d
phoneCall#967f7c67 flags:# p2p_allowed:flags.5?true video:flags.6?true id:long access_hash:long date:int admin_id:long participant_id:long g_a_or_b:bytes key_fingerprint:long protocol:PhoneCallProtocol connections:Vector start_date:int = PhoneCall;
phoneCallDiscarded#50ca4de1 flags:# need_rating:flags.2?true need_debug:flags.3?true video:flags.6?true id:long reason:flags.0?PhoneCallDiscardReason duration:flags.1?int = PhoneCall;
-phoneConnection#9d4c17c0 id:long ip:string ipv6:string port:int peer_tag:bytes = PhoneConnection;
+phoneConnection#9cc123c7 flags:# tcp:flags.0?true id:long ip:string ipv6:string port:int peer_tag:bytes = PhoneConnection;
phoneConnectionWebrtc#635fe375 flags:# turn:flags.0?true stun:flags.1?true id:long ip:string ipv6:string port:int username:string password:string = PhoneConnection;
phoneCallProtocol#fc878fc8 flags:# udp_p2p:flags.0?true udp_reflector:flags.1?true min_layer:int max_layer:int library_versions:Vector = PhoneCallProtocol;
@@ -962,7 +964,7 @@ dialogPeerFolder#514519e2 folder_id:int = DialogPeer;
messages.foundStickerSetsNotModified#d54b65d = messages.FoundStickerSets;
messages.foundStickerSets#8af09dd2 hash:long sets:Vector = messages.FoundStickerSets;
-fileHash#6242c773 offset:int limit:int hash:bytes = FileHash;
+fileHash#f39b035c offset:long limit:int hash:bytes = FileHash;
inputClientProxy#75588b3f address:string port:int = InputClientProxy;
@@ -973,7 +975,7 @@ inputSecureFileUploaded#3334b0f0 id:long parts:int md5_checksum:string file_hash
inputSecureFile#5367e5be id:long access_hash:long = InputSecureFile;
secureFileEmpty#64199744 = SecureFile;
-secureFile#e0277a62 id:long access_hash:long size:int dc_id:int date:int file_hash:bytes secret:bytes = SecureFile;
+secureFile#7d09c27e id:long access_hash:long size:long dc_id:int date:int file_hash:bytes secret:bytes = SecureFile;
secureData#8aeabec3 data:bytes data_hash:bytes secret:bytes = SecureData;
@@ -1100,7 +1102,7 @@ codeSettings#8a6469c2 flags:# allow_flashcall:flags.0?true current_number:flags.
wallPaperSettings#1dc1bca4 flags:# blur:flags.1?true motion:flags.2?true background_color:flags.0?int second_background_color:flags.4?int third_background_color:flags.5?int fourth_background_color:flags.6?int intensity:flags.3?int rotation:flags.4?int = WallPaperSettings;
-autoDownloadSettings#e04232f3 flags:# disabled:flags.0?true video_preload_large:flags.1?true audio_preload_next:flags.2?true phonecalls_less_data:flags.3?true photo_size_max:int video_size_max:int file_size_max:int video_upload_maxbitrate:int = AutoDownloadSettings;
+autoDownloadSettings#8efab953 flags:# disabled:flags.0?true video_preload_large:flags.1?true audio_preload_next:flags.2?true phonecalls_less_data:flags.3?true photo_size_max:int video_size_max:long file_size_max:long video_upload_maxbitrate:int = AutoDownloadSettings;
account.autoDownloadSettings#63cacf26 low:AutoDownloadSettings medium:AutoDownloadSettings high:AutoDownloadSettings = account.AutoDownloadSettings;
@@ -1172,6 +1174,7 @@ bankCardOpenUrl#f568028a url:string name:string = BankCardOpenUrl;
payments.bankCardData#3e24e573 title:string open_urls:Vector = payments.BankCardData;
dialogFilter#7438f7e8 flags:# contacts:flags.0?true non_contacts:flags.1?true groups:flags.2?true broadcasts:flags.3?true bots:flags.4?true exclude_muted:flags.11?true exclude_read:flags.12?true exclude_archived:flags.13?true id:int title:string emoticon:flags.25?string pinned_peers:Vector include_peers:Vector exclude_peers:Vector = DialogFilter;
+dialogFilterDefault#363293ae = DialogFilter;
dialogFilterSuggested#77744d4a filter:DialogFilter description:string = DialogFilterSuggested;
@@ -1217,7 +1220,7 @@ messages.messageViews#b6c4f543 views:Vector chats:Vector use
messages.discussionMessage#a6341782 flags:# messages:Vector max_id:flags.0?int read_inbox_max_id:flags.1?int read_outbox_max_id:flags.2?int unread_count:int chats:Vector users:Vector = messages.DiscussionMessage;
-messageReplyHeader#a6d57763 flags:# reply_to_msg_id:int reply_to_peer_id:flags.0?Peer reply_to_top_id:flags.1?int = MessageReplyHeader;
+messageReplyHeader#a6d57763 flags:# reply_to_scheduled:flags.2?true reply_to_msg_id:int reply_to_peer_id:flags.0?Peer reply_to_top_id:flags.1?int = MessageReplyHeader;
messageReplies#83d60fc2 flags:# comments:flags.0?true replies:int replies_pts:int recent_repliers:flags.1?Vector channel_id:flags.0?long max_id:flags.2?int read_max_id:flags.3?int = MessageReplies;
@@ -1285,7 +1288,7 @@ account.resetPasswordFailedWait#e3779861 retry_date:int = account.ResetPasswordR
account.resetPasswordRequestedWait#e9effc7d until_date:int = account.ResetPasswordResult;
account.resetPasswordOk#e926d63e = account.ResetPasswordResult;
-sponsoredMessage#3a836df8 flags:# random_id:bytes from_id:flags.3?Peer chat_invite:flags.4?ChatInvite chat_invite_hash:flags.4?string channel_post:flags.2?int start_param:flags.0?string message:string entities:flags.1?Vector = SponsoredMessage;
+sponsoredMessage#3a836df8 flags:# recommended:flags.5?true random_id:bytes from_id:flags.3?Peer chat_invite:flags.4?ChatInvite chat_invite_hash:flags.4?string channel_post:flags.2?int start_param:flags.0?string message:string entities:flags.1?Vector = SponsoredMessage;
messages.sponsoredMessages#65a4c7d5 messages:Vector chats:Vector users:Vector = messages.SponsoredMessages;
@@ -1311,7 +1314,7 @@ messageReactions#4f2b9479 flags:# min:flags.0?true can_see_list:flags.2?true res
messages.messageReactionsList#31bd492d flags:# count:int reactions:Vector chats:Vector users:Vector next_offset:flags.0?string = messages.MessageReactionsList;
-availableReaction#c077ec01 flags:# inactive:flags.0?true reaction:string title:string static_icon:Document appear_animation:Document select_animation:Document activate_animation:Document effect_animation:Document around_animation:flags.1?Document center_icon:flags.1?Document = AvailableReaction;
+availableReaction#c077ec01 flags:# inactive:flags.0?true premium:flags.2?true reaction:string title:string static_icon:Document appear_animation:Document select_animation:Document activate_animation:Document effect_animation:Document around_animation:flags.1?Document center_icon:flags.1?Document = AvailableReaction;
messages.availableReactionsNotModified#9f071957 = messages.AvailableReactions;
messages.availableReactions#768e3aad hash:int reactions:Vector = messages.AvailableReactions;
@@ -1331,7 +1334,7 @@ attachMenuBotIconColor#4576f3f0 name:string color:int = AttachMenuBotIconColor;
attachMenuBotIcon#b2a7386b flags:# name:string icon:Document colors:flags.0?Vector = AttachMenuBotIcon;
-attachMenuBot#e93cb772 flags:# inactive:flags.0?true bot_id:long short_name:string icons:Vector = AttachMenuBot;
+attachMenuBot#c8aa2cd2 flags:# inactive:flags.0?true has_settings:flags.1?true bot_id:long short_name:string peer_types:Vector icons:Vector = AttachMenuBot;
attachMenuBotsNotModified#f1d88a5c = AttachMenuBots;
attachMenuBots#3c4301c0 hash:long bots:Vector users:Vector = AttachMenuBots;
@@ -1359,6 +1362,21 @@ notificationSoundRingtone#ff6c8049 id:long = NotificationSound;
account.savedRingtone#b7263f6d = account.SavedRingtone;
account.savedRingtoneConverted#1f307eb7 document:Document = account.SavedRingtone;
+attachMenuPeerTypeSameBotPM#7d6be90e = AttachMenuPeerType;
+attachMenuPeerTypeBotPM#c32bfa1a = AttachMenuPeerType;
+attachMenuPeerTypePM#f146d31f = AttachMenuPeerType;
+attachMenuPeerTypeChat#509113f = AttachMenuPeerType;
+attachMenuPeerTypeBroadcast#7bfbdefc = AttachMenuPeerType;
+
+inputInvoiceMessage#c5b56859 peer:InputPeer msg_id:int = InputInvoice;
+inputInvoiceSlug#c326caef slug:string = InputInvoice;
+
+payments.exportedInvoice#aed0cbd9 url:string = payments.ExportedInvoice;
+
+messages.transcribedAudio#93752c52 flags:# pending:flags.0?true transcription_id:long text:string = messages.TranscribedAudio;
+
+help.premiumPromo#8a4f3c29 status_text:string status_entities:Vector video_sections:Vector videos:Vector currency:string monthly_amount:long users:Vector = help.PremiumPromo;
+
---functions---
invokeAfterMsg#cb9f372d {X:Type} msg_id:long query:!X = X;
@@ -1429,7 +1447,7 @@ account.sendVerifyPhoneCode#a5a356f9 phone_number:string settings:CodeSettings =
account.verifyPhone#4dd3a7f6 phone_number:string phone_code_hash:string phone_code:string = Bool;
account.sendVerifyEmailCode#7011509f email:string = account.SentEmailCode;
account.verifyEmail#ecba39db email:string code:string = Bool;
-account.initTakeoutSession#f05b4804 flags:# contacts:flags.0?true message_users:flags.1?true message_chats:flags.2?true message_megagroups:flags.3?true message_channels:flags.4?true files:flags.5?true file_max_size:flags.5?int = account.Takeout;
+account.initTakeoutSession#8ef3eab0 flags:# contacts:flags.0?true message_users:flags.1?true message_chats:flags.2?true message_megagroups:flags.3?true message_channels:flags.4?true files:flags.5?true file_max_size:flags.5?long = account.Takeout;
account.finishTakeoutSession#1d2652ee flags:# success:flags.0?true = Bool;
account.confirmPasswordEmail#8fdf1920 code:string = Bool;
account.resendPasswordEmail#7a7f2a15 = Bool;
@@ -1541,7 +1559,7 @@ messages.editChatAdmin#a85bd1c2 chat_id:long user_id:InputUser is_admin:Bool = B
messages.migrateChat#a2875319 chat_id:long = Updates;
messages.searchGlobal#4bc6589a flags:# folder_id:flags.0?int q:string filter:MessagesFilter min_date:int max_date:int offset_rate:int offset_peer:InputPeer offset_id:int limit:int = messages.Messages;
messages.reorderStickerSets#78337739 flags:# masks:flags.0?true order:Vector = Bool;
-messages.getDocumentByHash#338e2464 sha256:bytes size:int mime_type:string = Document;
+messages.getDocumentByHash#b1f2061f sha256:bytes size:long mime_type:string = Document;
messages.getSavedGifs#5cf09635 hash:long = messages.SavedGifs;
messages.saveGif#327a30cb id:InputDocument unsave:Bool = Bool;
messages.getInlineBotResults#514e999d flags:# bot:InputUser peer:InputPeer geo_point:flags.0?InputGeoPoint query:string offset:string = messages.BotResults;
@@ -1654,11 +1672,13 @@ messages.searchSentMedia#107e31a0 q:string filter:MessagesFilter limit:int = mes
messages.getAttachMenuBots#16fcc2cb hash:long = AttachMenuBots;
messages.getAttachMenuBot#77216192 bot:InputUser = AttachMenuBotsBot;
messages.toggleBotInAttachMenu#1aee33af bot:InputUser enabled:Bool = Bool;
-messages.requestWebView#fa04dff flags:# from_bot_menu:flags.4?true silent:flags.5?true peer:InputPeer bot:InputUser url:flags.1?string start_param:flags.3?string theme_params:flags.2?DataJSON reply_to_msg_id:flags.0?int = WebViewResult;
-messages.prolongWebView#d22ad148 flags:# silent:flags.5?true peer:InputPeer bot:InputUser query_id:long reply_to_msg_id:flags.0?int = Bool;
+messages.requestWebView#91b15831 flags:# from_bot_menu:flags.4?true silent:flags.5?true peer:InputPeer bot:InputUser url:flags.1?string start_param:flags.3?string theme_params:flags.2?DataJSON reply_to_msg_id:flags.0?int send_as:flags.13?InputPeer = WebViewResult;
+messages.prolongWebView#ea5fbcce flags:# silent:flags.5?true peer:InputPeer bot:InputUser query_id:long reply_to_msg_id:flags.0?int send_as:flags.13?InputPeer = Bool;
messages.requestSimpleWebView#6abb2f73 flags:# bot:InputUser url:string theme_params:flags.0?DataJSON = SimpleWebViewResult;
messages.sendWebViewResultMessage#a4314f5 bot_query_id:string result:InputBotInlineResult = WebViewMessageSent;
messages.sendWebViewData#dc0242c8 bot:InputUser random_id:long button_text:string data:string = Updates;
+messages.transcribeAudio#269e9a49 peer:InputPeer msg_id:int = messages.TranscribedAudio;
+messages.rateTranscribedAudio#7f1d072f peer:InputPeer msg_id:int transcription_id:long good:Bool = Bool;
updates.getState#edd4882a = updates.State;
updates.getDifference#25939651 flags:# pts:int pts_total_limit:flags.0?int date:int qts:int = updates.Difference;
@@ -1670,13 +1690,13 @@ photos.deletePhotos#87cf7f2f id:Vector = Vector;
photos.getUserPhotos#91cd32a8 user_id:InputUser offset:int max_id:long limit:int = photos.Photos;
upload.saveFilePart#b304a621 file_id:long file_part:int bytes:bytes = Bool;
-upload.getFile#b15a9afc flags:# precise:flags.0?true cdn_supported:flags.1?true location:InputFileLocation offset:int limit:int = upload.File;
+upload.getFile#be5335be flags:# precise:flags.0?true cdn_supported:flags.1?true location:InputFileLocation offset:long limit:int = upload.File;
upload.saveBigFilePart#de7b673d file_id:long file_part:int file_total_parts:int bytes:bytes = Bool;
upload.getWebFile#24e6818d location:InputWebFileLocation offset:int limit:int = upload.WebFile;
-upload.getCdnFile#2000bcc3 file_token:bytes offset:int limit:int = upload.CdnFile;
+upload.getCdnFile#395f69da file_token:bytes offset:long limit:int = upload.CdnFile;
upload.reuploadCdnFile#9b2754a8 file_token:bytes request_token:bytes = Vector;
-upload.getCdnFileHashes#4da54231 file_token:bytes offset:int = Vector;
-upload.getFileHashes#c7025931 location:InputFileLocation offset:int = Vector;
+upload.getCdnFileHashes#91dc3f31 file_token:bytes offset:long = Vector;
+upload.getFileHashes#9156982a location:InputFileLocation offset:long = Vector;
help.getConfig#c4f9186b = Config;
help.getNearestDc#1fb33026 = NearestDc;
@@ -1700,6 +1720,7 @@ help.getPromoData#c0977421 = help.PromoData;
help.hidePromoData#1e251c95 peer:InputPeer = Bool;
help.dismissSuggestion#f50dbaa1 peer:InputPeer suggestion:string = Bool;
help.getCountriesList#735787a8 lang_code:string hash:int = help.CountriesList;
+help.getPremiumPromo#b81b93d4 = help.PremiumPromo;
channels.readHistory#cc104937 channel:InputChannel max_id:int = Bool;
channels.deleteMessages#84c1fd4e channel:InputChannel id:Vector = messages.AffectedMessages;
@@ -1740,6 +1761,8 @@ channels.viewSponsoredMessage#beaedb94 channel:InputChannel random_id:bytes = Bo
channels.getSponsoredMessages#ec210fbf channel:InputChannel = messages.SponsoredMessages;
channels.getSendAs#dc770ee peer:InputPeer = channels.SendAsPeers;
channels.deleteParticipantHistory#367544db channel:InputChannel participant:InputPeer = messages.AffectedHistory;
+channels.toggleJoinToSend#e4cb9580 channel:InputChannel enabled:Bool = Updates;
+channels.toggleJoinRequest#4c2985b6 channel:InputChannel enabled:Bool = Updates;
bots.sendCustomRequest#aa2769ed custom_method:string params:DataJSON = DataJSON;
bots.answerWebhookJSONQuery#e6213f4d query_id:long data:DataJSON = Bool;
@@ -1751,13 +1774,18 @@ bots.getBotMenuButton#9c60eb28 user_id:InputUser = BotMenuButton;
bots.setBotBroadcastDefaultAdminRights#788464e1 admin_rights:ChatAdminRights = Bool;
bots.setBotGroupDefaultAdminRights#925ec9ea admin_rights:ChatAdminRights = Bool;
-payments.getPaymentForm#8a333c8d flags:# peer:InputPeer msg_id:int theme_params:flags.0?DataJSON = payments.PaymentForm;
+payments.getPaymentForm#37148dbb flags:# invoice:InputInvoice theme_params:flags.0?DataJSON = payments.PaymentForm;
payments.getPaymentReceipt#2478d1cc peer:InputPeer msg_id:int = payments.PaymentReceipt;
-payments.validateRequestedInfo#db103170 flags:# save:flags.0?true peer:InputPeer msg_id:int info:PaymentRequestedInfo = payments.ValidatedRequestedInfo;
-payments.sendPaymentForm#30c3bc9d flags:# form_id:long peer:InputPeer msg_id:int requested_info_id:flags.0?string shipping_option_id:flags.1?string credentials:InputPaymentCredentials tip_amount:flags.2?long = payments.PaymentResult;
+payments.validateRequestedInfo#b6c8f12b flags:# save:flags.0?true invoice:InputInvoice info:PaymentRequestedInfo = payments.ValidatedRequestedInfo;
+payments.sendPaymentForm#2d03522f flags:# form_id:long invoice:InputInvoice requested_info_id:flags.0?string shipping_option_id:flags.1?string credentials:InputPaymentCredentials tip_amount:flags.2?long = payments.PaymentResult;
payments.getSavedInfo#227d824b = payments.SavedInfo;
payments.clearSavedInfo#d83d70c1 flags:# credentials:flags.0?true info:flags.1?true = Bool;
payments.getBankCardData#2e79d779 number:string = payments.BankCardData;
+payments.exportInvoice#f91b065 invoice_media:InputMedia = payments.ExportedInvoice;
+payments.assignAppStoreTransaction#d5ccfd0 flags:# restore:flags.0?true receipt:bytes = Updates;
+payments.assignPlayMarketTransaction#4faa4aed purchase_token:string = Updates;
+payments.canPurchasePremium#aa6a90c8 = Bool;
+payments.requestRecurringPayment#146e958d user_id:InputUser recurring_init_charge:string invoice_media:InputMedia = Updates;
stickers.createStickerSet#9021ab67 flags:# masks:flags.0?true animated:flags.1?true videos:flags.4?true user_id:InputUser title:string short_name:string thumb:flags.2?InputDocument stickers:Vector software:flags.3?string = messages.StickerSet;
stickers.removeStickerFromSet#f7760f51 sticker:InputDocument = messages.StickerSet;
diff --git a/td/telegram/AnimationsManager.cpp b/td/telegram/AnimationsManager.cpp
index dc52706da..b14ba5e76 100644
--- a/td/telegram/AnimationsManager.cpp
+++ b/td/telegram/AnimationsManager.cpp
@@ -389,7 +389,8 @@ tl_object_ptr AnimationsManager::get_input_media(
SecretInputMedia AnimationsManager::get_secret_input_media(FileId animation_file_id,
tl_object_ptr input_file,
- const string &caption, BufferSlice thumbnail) const {
+ const string &caption, BufferSlice thumbnail,
+ int32 layer) const {
auto *animation = get_animation(animation_file_id);
CHECK(animation != nullptr);
auto file_view = td_->file_manager_->get_file_view(animation_file_id);
@@ -425,7 +426,8 @@ SecretInputMedia AnimationsManager::get_secret_input_media(FileId animation_file
animation->mime_type,
file_view,
std::move(attributes),
- caption};
+ caption,
+ layer};
}
void AnimationsManager::on_update_animation_search_emojis(string animation_search_emojis) {
diff --git a/td/telegram/AnimationsManager.h b/td/telegram/AnimationsManager.h
index f0d4b3832..54383b94e 100644
--- a/td/telegram/AnimationsManager.h
+++ b/td/telegram/AnimationsManager.h
@@ -46,7 +46,7 @@ class AnimationsManager final : public Actor {
SecretInputMedia get_secret_input_media(FileId animation_file_id,
tl_object_ptr input_file,
- const string &caption, BufferSlice thumbnail) const;
+ const string &caption, BufferSlice thumbnail, int32 layer) const;
FileId get_animation_thumbnail_file_id(FileId file_id) const;
diff --git a/td/telegram/Application.cpp b/td/telegram/Application.cpp
index 7c33fa646..8f4e559d4 100644
--- a/td/telegram/Application.cpp
+++ b/td/telegram/Application.cpp
@@ -11,6 +11,7 @@
#include "td/utils/buffer.h"
#include "td/utils/logging.h"
+#include "td/utils/Status.h"
namespace td {
diff --git a/td/telegram/AttachMenuManager.cpp b/td/telegram/AttachMenuManager.cpp
index 84cc6bfc4..f4d8cf2ea 100644
--- a/td/telegram/AttachMenuManager.cpp
+++ b/td/telegram/AttachMenuManager.cpp
@@ -39,6 +39,7 @@ class RequestWebViewQuery final : public Td::ResultHandler {
DialogId dialog_id_;
UserId bot_user_id_;
MessageId reply_to_message_id_;
+ DialogId as_dialog_id_;
bool from_attach_menu_ = false;
public:
@@ -47,10 +48,12 @@ class RequestWebViewQuery final : public Td::ResultHandler {
}
void send(DialogId dialog_id, UserId bot_user_id, tl_object_ptr &&input_user, string &&url,
- td_api::object_ptr &&theme, MessageId reply_to_message_id, bool silent) {
+ td_api::object_ptr &&theme, MessageId reply_to_message_id, bool silent,
+ DialogId as_dialog_id) {
dialog_id_ = dialog_id;
bot_user_id_ = bot_user_id;
reply_to_message_id_ = reply_to_message_id;
+ as_dialog_id_ = as_dialog_id;
int32 flags = 0;
@@ -90,9 +93,17 @@ class RequestWebViewQuery final : public Td::ResultHandler {
flags |= telegram_api::messages_requestWebView::SILENT_MASK;
}
+ tl_object_ptr as_input_peer;
+ if (as_dialog_id.is_valid()) {
+ as_input_peer = td_->messages_manager_->get_input_peer(as_dialog_id, AccessRights::Write);
+ if (as_input_peer != nullptr) {
+ flags |= telegram_api::messages_requestWebView::SEND_AS_MASK;
+ }
+ }
+
send_query(G()->net_query_creator().create(telegram_api::messages_requestWebView(
flags, false /*ignored*/, false /*ignored*/, std::move(input_peer), std::move(input_user), url, start_parameter,
- std::move(theme_parameters), reply_to_message_id.get_server_message_id().get())));
+ std::move(theme_parameters), reply_to_message_id.get_server_message_id().get(), std::move(as_input_peer))));
}
void on_result(BufferSlice packet) final {
@@ -102,7 +113,8 @@ class RequestWebViewQuery final : public Td::ResultHandler {
}
auto ptr = result_ptr.move_as_ok();
- td_->attach_menu_manager_->open_web_view(ptr->query_id_, dialog_id_, bot_user_id_, reply_to_message_id_);
+ td_->attach_menu_manager_->open_web_view(ptr->query_id_, dialog_id_, bot_user_id_, reply_to_message_id_,
+ as_dialog_id_);
promise_.set_value(td_api::make_object(ptr->query_id_, ptr->url_));
}
@@ -120,7 +132,8 @@ class ProlongWebViewQuery final : public Td::ResultHandler {
DialogId dialog_id_;
public:
- void send(DialogId dialog_id, UserId bot_user_id, int64 query_id, MessageId reply_to_message_id, bool silent) {
+ void send(DialogId dialog_id, UserId bot_user_id, int64 query_id, MessageId reply_to_message_id, bool silent,
+ DialogId as_dialog_id) {
dialog_id_ = dialog_id;
auto input_peer = td_->messages_manager_->get_input_peer(dialog_id, AccessRights::Write);
@@ -133,13 +146,22 @@ class ProlongWebViewQuery final : public Td::ResultHandler {
if (reply_to_message_id.is_valid()) {
flags |= telegram_api::messages_prolongWebView::REPLY_TO_MSG_ID_MASK;
}
+
if (silent) {
flags |= telegram_api::messages_prolongWebView::SILENT_MASK;
}
+ tl_object_ptr as_input_peer;
+ if (as_dialog_id.is_valid()) {
+ as_input_peer = td_->messages_manager_->get_input_peer(as_dialog_id, AccessRights::Write);
+ if (as_input_peer != nullptr) {
+ flags |= telegram_api::messages_prolongWebView::SEND_AS_MASK;
+ }
+ }
+
send_query(G()->net_query_creator().create(telegram_api::messages_prolongWebView(
flags, false /*ignored*/, std::move(input_peer), r_input_user.move_as_ok(), query_id,
- reply_to_message_id.get_server_message_id().get())));
+ reply_to_message_id.get_server_message_id().get(), std::move(as_input_peer))));
}
void on_result(BufferSlice packet) final {
@@ -268,12 +290,18 @@ void AttachMenuManager::AttachMenuBotColor::parse(ParserT &parser) {
}
bool operator==(const AttachMenuManager::AttachMenuBot &lhs, const AttachMenuManager::AttachMenuBot &rhs) {
- return lhs.user_id_ == rhs.user_id_ && lhs.name_ == rhs.name_ &&
+ return lhs.user_id_ == rhs.user_id_ && lhs.supports_self_dialog_ == rhs.supports_self_dialog_ &&
+ lhs.supports_user_dialogs_ == rhs.supports_user_dialogs_ &&
+ lhs.supports_bot_dialogs_ == rhs.supports_bot_dialogs_ &&
+ lhs.supports_group_dialogs_ == rhs.supports_group_dialogs_ &&
+ lhs.supports_broadcast_dialogs_ == rhs.supports_broadcast_dialogs_ &&
+ lhs.supports_settings_ == rhs.supports_settings_ && lhs.name_ == rhs.name_ &&
lhs.default_icon_file_id_ == rhs.default_icon_file_id_ &&
lhs.ios_static_icon_file_id_ == rhs.ios_static_icon_file_id_ &&
lhs.ios_animated_icon_file_id_ == rhs.ios_animated_icon_file_id_ &&
lhs.android_icon_file_id_ == rhs.android_icon_file_id_ && lhs.macos_icon_file_id_ == rhs.macos_icon_file_id_ &&
- lhs.is_added_ == rhs.is_added_ && lhs.name_color_ == rhs.name_color_ && lhs.icon_color_ == rhs.icon_color_;
+ lhs.is_added_ == rhs.is_added_ && lhs.name_color_ == rhs.name_color_ && lhs.icon_color_ == rhs.icon_color_ &&
+ lhs.placeholder_file_id_ == rhs.placeholder_file_id_;
}
bool operator!=(const AttachMenuManager::AttachMenuBot &lhs, const AttachMenuManager::AttachMenuBot &rhs) {
@@ -288,6 +316,9 @@ void AttachMenuManager::AttachMenuBot::store(StorerT &storer) const {
bool has_macos_icon_file_id = macos_icon_file_id_.is_valid();
bool has_name_color = name_color_ != AttachMenuBotColor();
bool has_icon_color = icon_color_ != AttachMenuBotColor();
+ bool has_support_flags = true;
+ bool has_placeholder_file_id = placeholder_file_id_.is_valid();
+ bool has_cache_version = cache_version_ != 0;
BEGIN_STORE_FLAGS();
STORE_FLAG(has_ios_static_icon_file_id);
STORE_FLAG(has_ios_animated_icon_file_id);
@@ -296,6 +327,15 @@ void AttachMenuManager::AttachMenuBot::store(StorerT &storer) const {
STORE_FLAG(is_added_);
STORE_FLAG(has_name_color);
STORE_FLAG(has_icon_color);
+ STORE_FLAG(has_support_flags);
+ STORE_FLAG(supports_self_dialog_);
+ STORE_FLAG(supports_user_dialogs_);
+ STORE_FLAG(supports_bot_dialogs_);
+ STORE_FLAG(supports_group_dialogs_);
+ STORE_FLAG(supports_broadcast_dialogs_);
+ STORE_FLAG(supports_settings_);
+ STORE_FLAG(has_placeholder_file_id);
+ STORE_FLAG(has_cache_version);
END_STORE_FLAGS();
td::store(user_id_, storer);
td::store(name_, storer);
@@ -318,6 +358,12 @@ void AttachMenuManager::AttachMenuBot::store(StorerT &storer) const {
if (has_icon_color) {
td::store(icon_color_, storer);
}
+ if (has_placeholder_file_id) {
+ td::store(placeholder_file_id_, storer);
+ }
+ if (has_cache_version) {
+ td::store(cache_version_, storer);
+ }
}
template
@@ -328,6 +374,9 @@ void AttachMenuManager::AttachMenuBot::parse(ParserT &parser) {
bool has_macos_icon_file_id;
bool has_name_color;
bool has_icon_color;
+ bool has_support_flags;
+ bool has_placeholder_file_id;
+ bool has_cache_version;
BEGIN_PARSE_FLAGS();
PARSE_FLAG(has_ios_static_icon_file_id);
PARSE_FLAG(has_ios_animated_icon_file_id);
@@ -336,6 +385,15 @@ void AttachMenuManager::AttachMenuBot::parse(ParserT &parser) {
PARSE_FLAG(is_added_);
PARSE_FLAG(has_name_color);
PARSE_FLAG(has_icon_color);
+ PARSE_FLAG(has_support_flags);
+ PARSE_FLAG(supports_self_dialog_);
+ PARSE_FLAG(supports_user_dialogs_);
+ PARSE_FLAG(supports_bot_dialogs_);
+ PARSE_FLAG(supports_group_dialogs_);
+ PARSE_FLAG(supports_broadcast_dialogs_);
+ PARSE_FLAG(supports_settings_);
+ PARSE_FLAG(has_placeholder_file_id);
+ PARSE_FLAG(has_cache_version);
END_PARSE_FLAGS();
td::parse(user_id_, parser);
td::parse(name_, parser);
@@ -358,6 +416,18 @@ void AttachMenuManager::AttachMenuBot::parse(ParserT &parser) {
if (has_icon_color) {
td::parse(icon_color_, parser);
}
+ if (has_placeholder_file_id) {
+ td::parse(placeholder_file_id_, parser);
+ }
+ if (has_cache_version) {
+ td::parse(cache_version_, parser);
+ }
+
+ if (!has_support_flags) {
+ supports_self_dialog_ = true;
+ supports_user_dialogs_ = true;
+ supports_bot_dialogs_ = true;
+ }
}
class AttachMenuManager::AttachMenuBotsLogEvent {
@@ -425,7 +495,13 @@ void AttachMenuManager::init() {
dependencies.add(attach_menu_bot.user_id_);
}
if (is_valid && dependencies.resolve_force(td_, "AttachMenuBotsLogEvent")) {
- hash_ = attach_menu_bots_log_event.hash_;
+ bool is_cache_outdated = false;
+ for (auto &bot : attach_menu_bots_log_event.attach_menu_bots_) {
+ if (bot.cache_version_ != AttachMenuBot::CACHE_VERSION) {
+ is_cache_outdated = true;
+ }
+ }
+ hash_ = is_cache_outdated ? 0 : attach_menu_bots_log_event.hash_;
attach_menu_bots_ = std::move(attach_menu_bots_log_event.attach_menu_bots_);
} else {
LOG(ERROR) << "Ignore invalid attachment menu bots log event";
@@ -493,7 +569,8 @@ void AttachMenuManager::ping_web_view() {
const auto &opened_web_view = it.second;
bool silent = td_->messages_manager_->get_dialog_silent_send_message(opened_web_view.dialog_id_);
td_->create_handler()->send(opened_web_view.dialog_id_, opened_web_view.bot_user_id_, it.first,
- opened_web_view.reply_to_message_id_, silent);
+ opened_web_view.reply_to_message_id_, silent,
+ opened_web_view.as_dialog_id_);
}
schedule_ping_web_view();
@@ -517,12 +594,12 @@ void AttachMenuManager::request_web_view(DialogId dialog_id, UserId bot_user_id,
switch (dialog_id.get_type()) {
case DialogType::User:
- // ok
- break;
case DialogType::Chat:
case DialogType::Channel:
+ // ok
+ break;
case DialogType::SecretChat:
- return promise.set_error(Status::Error(400, "Web apps can be opened only in private chats"));
+ return promise.set_error(Status::Error(400, "Web Apps can't be opened in secret chats"));
case DialogType::None:
default:
UNREACHABLE();
@@ -538,16 +615,17 @@ void AttachMenuManager::request_web_view(DialogId dialog_id, UserId bot_user_id,
}
bool silent = td_->messages_manager_->get_dialog_silent_send_message(dialog_id);
+ DialogId as_dialog_id = td_->messages_manager_->get_dialog_default_send_message_as_dialog_id(dialog_id);
td_->create_handler(std::move(promise))
->send(dialog_id, bot_user_id, std::move(input_user), std::move(url), std::move(theme), reply_to_message_id,
- silent);
+ silent, as_dialog_id);
}
void AttachMenuManager::open_web_view(int64 query_id, DialogId dialog_id, UserId bot_user_id,
- MessageId reply_to_message_id) {
+ MessageId reply_to_message_id, DialogId as_dialog_id) {
if (query_id == 0) {
- LOG(ERROR) << "Receive web app query identifier == 0";
+ LOG(ERROR) << "Receive Web App query identifier == 0";
return;
}
@@ -558,6 +636,7 @@ void AttachMenuManager::open_web_view(int64 query_id, DialogId dialog_id, UserId
opened_web_view.dialog_id_ = dialog_id;
opened_web_view.bot_user_id_ = bot_user_id;
opened_web_view.reply_to_message_id_ = reply_to_message_id;
+ opened_web_view.as_dialog_id_ = as_dialog_id;
opened_web_views_.emplace(query_id, std::move(opened_web_view));
}
@@ -589,7 +668,7 @@ Result AttachMenuManager::get_attach_menu_bot(
CHECK(document_id == telegram_api::document::ID);
if (name != "default_static" && name != "ios_static" && name != "ios_animated" && name != "android_animated" &&
- name != "macos_animated") {
+ name != "macos_animated" && name != "placeholder_static") {
LOG(ERROR) << "Have icon for " << user_id << " with name " << name;
continue;
}
@@ -598,9 +677,7 @@ Result AttachMenuManager::get_attach_menu_bot(
auto parsed_document =
td_->documents_manager_->on_get_document(move_tl_object_as(icon->icon_), DialogId());
if (parsed_document.type != expected_document_type) {
- if (user_id != UserId(static_cast(5000860301)) || !G()->is_test_dc() || name != "macos_animated") {
- LOG(ERROR) << "Receive wrong attachment menu bot icon \"" << name << "\" for " << user_id;
- }
+ LOG(ERROR) << "Receive wrong attachment menu bot icon \"" << name << "\" for " << user_id;
continue;
}
bool expect_colors = false;
@@ -621,6 +698,9 @@ Result AttachMenuManager::get_attach_menu_bot(
case '_':
attach_menu_bot.macos_icon_file_id_ = parsed_document.file_id;
break;
+ case 'h':
+ attach_menu_bot.placeholder_file_id_ = parsed_document.file_id;
+ break;
default:
UNREACHABLE();
}
@@ -671,10 +751,33 @@ Result AttachMenuManager::get_attach_menu_bot(
}
}
}
-
+ for (auto &peer_type : bot->peer_types_) {
+ switch (peer_type->get_id()) {
+ case telegram_api::attachMenuPeerTypeSameBotPM::ID:
+ attach_menu_bot.supports_self_dialog_ = true;
+ break;
+ case telegram_api::attachMenuPeerTypeBotPM::ID:
+ attach_menu_bot.supports_bot_dialogs_ = true;
+ break;
+ case telegram_api::attachMenuPeerTypePM::ID:
+ attach_menu_bot.supports_user_dialogs_ = true;
+ break;
+ case telegram_api::attachMenuPeerTypeChat::ID:
+ attach_menu_bot.supports_group_dialogs_ = true;
+ break;
+ case telegram_api::attachMenuPeerTypeBroadcast::ID:
+ attach_menu_bot.supports_broadcast_dialogs_ = true;
+ break;
+ default:
+ UNREACHABLE();
+ break;
+ }
+ }
+ attach_menu_bot.supports_settings_ = bot->has_settings_;
if (!attach_menu_bot.default_icon_file_id_.is_valid()) {
return Status::Error(PSLICE() << "Have no default icon for " << user_id);
}
+ attach_menu_bot.cache_version_ = AttachMenuBot::CACHE_VERSION;
return std::move(attach_menu_bot);
}
@@ -872,11 +975,13 @@ td_api::object_ptr AttachMenuManager::get_attachment_
};
return td_api::make_object(
- td_->contacts_manager_->get_user_id_object(bot.user_id_, "get_attachment_menu_bot_object"), bot.name_,
+ td_->contacts_manager_->get_user_id_object(bot.user_id_, "get_attachment_menu_bot_object"),
+ bot.supports_self_dialog_, bot.supports_user_dialogs_, bot.supports_bot_dialogs_, bot.supports_group_dialogs_,
+ bot.supports_broadcast_dialogs_, bot.supports_settings_, bot.name_,
get_attach_menu_bot_color_object(bot.name_color_), get_file(bot.default_icon_file_id_),
get_file(bot.ios_static_icon_file_id_), get_file(bot.ios_animated_icon_file_id_),
get_file(bot.android_icon_file_id_), get_file(bot.macos_icon_file_id_),
- get_attach_menu_bot_color_object(bot.icon_color_));
+ get_attach_menu_bot_color_object(bot.icon_color_), get_file(bot.placeholder_file_id_));
}
td_api::object_ptr AttachMenuManager::get_update_attachment_menu_bots_object() const {
diff --git a/td/telegram/AttachMenuManager.h b/td/telegram/AttachMenuManager.h
index 80b39085b..8bc10e2fd 100644
--- a/td/telegram/AttachMenuManager.h
+++ b/td/telegram/AttachMenuManager.h
@@ -35,7 +35,8 @@ class AttachMenuManager final : public Actor {
td_api::object_ptr &&theme,
Promise> &&promise);
- void open_web_view(int64 query_id, DialogId dialog_id, UserId bot_user_id, MessageId reply_to_message_id);
+ void open_web_view(int64 query_id, DialogId dialog_id, UserId bot_user_id, MessageId reply_to_message_id,
+ DialogId as_dialog_id);
void close_web_view(int64 query_id, Promise &&promise);
@@ -74,6 +75,12 @@ class AttachMenuManager final : public Actor {
struct AttachMenuBot {
bool is_added_ = false;
UserId user_id_;
+ bool supports_self_dialog_ = false;
+ bool supports_user_dialogs_ = false;
+ bool supports_bot_dialogs_ = false;
+ bool supports_group_dialogs_ = false;
+ bool supports_broadcast_dialogs_ = false;
+ bool supports_settings_ = false;
string name_;
AttachMenuBotColor name_color_;
FileId default_icon_file_id_;
@@ -82,6 +89,10 @@ class AttachMenuManager final : public Actor {
FileId android_icon_file_id_;
FileId macos_icon_file_id_;
AttachMenuBotColor icon_color_;
+ FileId placeholder_file_id_;
+
+ static constexpr uint32 CACHE_VERSION = 1;
+ uint32 cache_version_ = 0;
template
void store(StorerT &storer) const;
@@ -138,6 +149,7 @@ class AttachMenuManager final : public Actor {
DialogId dialog_id_;
UserId bot_user_id_;
MessageId reply_to_message_id_;
+ DialogId as_dialog_id_;
};
FlatHashMap opened_web_views_;
Timeout ping_web_view_timeout_;
diff --git a/td/telegram/AudiosManager.cpp b/td/telegram/AudiosManager.cpp
index bae9e6b99..73b6d8a56 100644
--- a/td/telegram/AudiosManager.cpp
+++ b/td/telegram/AudiosManager.cpp
@@ -8,6 +8,7 @@
#include "td/telegram/AuthManager.h"
#include "td/telegram/files/FileManager.h"
+#include "td/telegram/files/FileType.h"
#include "td/telegram/PhotoFormat.h"
#include "td/telegram/secret_api.h"
#include "td/telegram/Td.h"
@@ -206,7 +207,8 @@ void AudiosManager::create_audio(FileId file_id, string minithumbnail, PhotoSize
SecretInputMedia AudiosManager::get_secret_input_media(FileId audio_file_id,
tl_object_ptr input_file,
- const string &caption, BufferSlice thumbnail) const {
+ const string &caption, BufferSlice thumbnail,
+ int32 layer) const {
auto *audio = get_audio(audio_file_id);
CHECK(audio != nullptr);
auto file_view = td_->file_manager_->get_file_view(audio_file_id);
@@ -236,7 +238,8 @@ SecretInputMedia AudiosManager::get_secret_input_media(FileId audio_file_id,
audio->mime_type,
file_view,
std::move(attributes),
- caption};
+ caption,
+ layer};
}
tl_object_ptr AudiosManager::get_input_media(
diff --git a/td/telegram/AudiosManager.h b/td/telegram/AudiosManager.h
index 305c88ad2..b0232f68d 100644
--- a/td/telegram/AudiosManager.h
+++ b/td/telegram/AudiosManager.h
@@ -41,7 +41,7 @@ class AudiosManager {
SecretInputMedia get_secret_input_media(FileId audio_file_id,
tl_object_ptr input_file,
- const string &caption, BufferSlice thumbnail) const;
+ const string &caption, BufferSlice thumbnail, int32 layer) const;
FileId get_audio_thumbnail_file_id(FileId file_id) const;
diff --git a/td/telegram/AuthManager.cpp b/td/telegram/AuthManager.cpp
index 24702f2f6..fb34fb4dd 100644
--- a/td/telegram/AuthManager.cpp
+++ b/td/telegram/AuthManager.cpp
@@ -685,7 +685,7 @@ void AuthManager::on_log_out_result(NetQueryPtr &result) {
} else {
status = std::move(result->error());
}
- LOG_IF(ERROR, status.is_error()) << "Receive error for auth.logOut: " << status;
+ LOG_IF(ERROR, status.is_error() && status.error().code() != 401) << "Receive error for auth.logOut: " << status;
// state_ will stay LoggingOut, so no queries will work.
destroy_auth_keys();
if (query_id_ != 0) {
@@ -693,6 +693,10 @@ void AuthManager::on_log_out_result(NetQueryPtr &result) {
}
}
void AuthManager::on_authorization_lost(string source) {
+ if (state_ == State::LoggingOut && net_query_type_ == NetQueryType::LogOut) {
+ LOG(INFO) << "Ignore authorization loss because of " << source << ", while logging out";
+ return;
+ }
LOG(WARNING) << "Lost authorization because of " << source;
destroy_auth_keys();
}
@@ -803,7 +807,7 @@ void AuthManager::on_get_authorization(tl_object_ptrset_is_bot_online(true);
}
- send_closure(G()->config_manager(), &ConfigManager::request_config);
+ send_closure(G()->config_manager(), &ConfigManager::request_config, false);
if (query_id_ != 0) {
on_query_ok();
}
diff --git a/td/telegram/AutoDownloadSettings.cpp b/td/telegram/AutoDownloadSettings.cpp
index 70ceffa07..d2ff4c5ad 100644
--- a/td/telegram/AutoDownloadSettings.cpp
+++ b/td/telegram/AutoDownloadSettings.cpp
@@ -13,6 +13,7 @@
#include "td/utils/buffer.h"
#include "td/utils/logging.h"
+#include "td/utils/misc.h"
#include "td/utils/Status.h"
namespace td {
@@ -25,9 +26,13 @@ static td_api::object_ptr convert_auto_download_se
auto video_preload_large = (flags & telegram_api::autoDownloadSettings::VIDEO_PRELOAD_LARGE_MASK) != 0;
auto audio_preload_next = (flags & telegram_api::autoDownloadSettings::AUDIO_PRELOAD_NEXT_MASK) != 0;
auto phonecalls_less_data = (flags & telegram_api::autoDownloadSettings::PHONECALLS_LESS_DATA_MASK) != 0;
+ constexpr int32 MAX_PHOTO_SIZE = 10 * (1 << 20) /* 10 MB */;
+ constexpr int64 MAX_DOCUMENT_SIZE = (static_cast(1) << 52);
return td_api::make_object(
- !disabled, settings->photo_size_max_, settings->video_size_max_, settings->file_size_max_,
- settings->video_upload_maxbitrate_, video_preload_large, audio_preload_next, phonecalls_less_data);
+ !disabled, clamp(settings->photo_size_max_, static_cast(0), MAX_PHOTO_SIZE),
+ clamp(settings->video_size_max_, static_cast(0), MAX_DOCUMENT_SIZE),
+ clamp(settings->file_size_max_, static_cast(0), MAX_DOCUMENT_SIZE), settings->video_upload_maxbitrate_,
+ video_preload_large, audio_preload_next, phonecalls_less_data);
}
class GetAutoDownloadSettingsQuery final : public Td::ResultHandler {
diff --git a/td/telegram/AutoDownloadSettings.h b/td/telegram/AutoDownloadSettings.h
index 5cc92c6b5..9efce1ffe 100644
--- a/td/telegram/AutoDownloadSettings.h
+++ b/td/telegram/AutoDownloadSettings.h
@@ -20,8 +20,8 @@ class Td;
class AutoDownloadSettings {
public:
int32 max_photo_file_size = 0;
- int32 max_video_file_size = 0;
- int32 max_other_file_size = 0;
+ int64 max_video_file_size = 0;
+ int64 max_other_file_size = 0;
int32 video_upload_bitrate = 0;
bool is_enabled = false;
bool preload_large_videos = false;
diff --git a/td/telegram/AvailableReaction.cpp b/td/telegram/AvailableReaction.cpp
new file mode 100644
index 000000000..dfd794437
--- /dev/null
+++ b/td/telegram/AvailableReaction.cpp
@@ -0,0 +1,61 @@
+//
+// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2022
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+#include "td/telegram/AvailableReaction.h"
+
+#include "td/utils/algorithm.h"
+
+namespace td {
+
+AvailableReactionType get_reaction_type(const vector &available_reactions, const string &reaction) {
+ for (auto &available_reaction : available_reactions) {
+ if (available_reaction.reaction_ == reaction) {
+ if (available_reaction.is_premium_) {
+ return AvailableReactionType::NeedsPremium;
+ }
+ return AvailableReactionType::Available;
+ }
+ }
+ return AvailableReactionType::Unavailable;
+}
+
+vector get_active_reactions(const vector &available_reactions,
+ const vector &active_reactions) {
+ if (available_reactions.empty()) {
+ // fast path
+ return available_reactions;
+ }
+ if (available_reactions.size() == active_reactions.size()) {
+ size_t i;
+ for (i = 0; i < available_reactions.size(); i++) {
+ if (available_reactions[i] != active_reactions[i].reaction_) {
+ break;
+ }
+ }
+ if (i == available_reactions.size()) {
+ // fast path
+ return available_reactions;
+ }
+ }
+
+ vector result;
+ for (const auto &active_reaction : active_reactions) {
+ if (td::contains(available_reactions, active_reaction.reaction_)) {
+ result.push_back(active_reaction.reaction_);
+ }
+ }
+ return result;
+}
+
+td_api::object_ptr AvailableReaction::get_available_reaction_object() const {
+ return td_api::make_object(reaction_, is_premium_);
+}
+
+bool operator==(const AvailableReaction &lhs, const AvailableReaction &rhs) {
+ return lhs.reaction_ == rhs.reaction_ && lhs.is_premium_ == rhs.is_premium_;
+}
+
+} // namespace td
diff --git a/td/telegram/AvailableReaction.h b/td/telegram/AvailableReaction.h
new file mode 100644
index 000000000..e3196382d
--- /dev/null
+++ b/td/telegram/AvailableReaction.h
@@ -0,0 +1,38 @@
+//
+// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2022
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+#pragma once
+
+#include "td/telegram/td_api.h"
+
+#include "td/utils/common.h"
+
+namespace td {
+
+struct AvailableReaction {
+ string reaction_;
+ bool is_premium_;
+
+ AvailableReaction(const string &reaction, bool is_premium) : reaction_(reaction), is_premium_(is_premium) {
+ }
+
+ td_api::object_ptr get_available_reaction_object() const;
+};
+
+bool operator==(const AvailableReaction &lhs, const AvailableReaction &rhs);
+
+inline bool operator!=(const AvailableReaction &lhs, const AvailableReaction &rhs) {
+ return !(lhs == rhs);
+}
+
+enum class AvailableReactionType : int32 { Unavailable, Available, NeedsPremium };
+
+AvailableReactionType get_reaction_type(const vector &reactions, const string &reaction);
+
+vector get_active_reactions(const vector &available_reactions,
+ const vector &active_reactions);
+
+} // namespace td
diff --git a/td/telegram/BackgroundManager.cpp b/td/telegram/BackgroundManager.cpp
index 8244ae5bf..cd881176f 100644
--- a/td/telegram/BackgroundManager.cpp
+++ b/td/telegram/BackgroundManager.cpp
@@ -35,6 +35,8 @@
#include "td/utils/SliceBuilder.h"
#include "td/utils/tl_helpers.h"
+#include
+
namespace td {
class GetBackgroundQuery final : public Td::ResultHandler {
diff --git a/td/telegram/BotMenuButton.cpp b/td/telegram/BotMenuButton.cpp
index 4676f856d..32c18c418 100644
--- a/td/telegram/BotMenuButton.cpp
+++ b/td/telegram/BotMenuButton.cpp
@@ -84,7 +84,9 @@ class GetBotMenuButtonQuery final : public Td::ResultHandler {
};
unique_ptr get_bot_menu_button(telegram_api::object_ptr &&bot_menu_button) {
- CHECK(bot_menu_button != nullptr);
+ if (bot_menu_button == nullptr) {
+ return nullptr;
+ }
switch (bot_menu_button->get_id()) {
case telegram_api::botMenuButtonCommands::ID:
return nullptr;
diff --git a/td/telegram/CallActor.cpp b/td/telegram/CallActor.cpp
index 7e23512dc..45c7ade10 100644
--- a/td/telegram/CallActor.cpp
+++ b/td/telegram/CallActor.cpp
@@ -11,6 +11,7 @@
#include "td/telegram/DhCache.h"
#include "td/telegram/DialogId.h"
#include "td/telegram/files/FileManager.h"
+#include "td/telegram/files/FileType.h"
#include "td/telegram/Global.h"
#include "td/telegram/misc.h"
#include "td/telegram/net/NetQueryCreator.h"
@@ -74,6 +75,7 @@ CallConnection::CallConnection(const telegram_api::PhoneConnection &connection)
ipv6 = conn.ipv6_;
port = conn.port_;
peer_tag = conn.peer_tag_.as_slice().str();
+ is_tcp = conn.tcp_;
break;
}
case telegram_api::phoneConnectionWebrtc::ID: {
@@ -103,7 +105,7 @@ tl_object_ptr CallConnection::get_call_server_object() const
auto server_type = [&]() -> tl_object_ptr {
switch (type) {
case Type::Telegram:
- return make_tl_object(peer_tag);
+ return make_tl_object(peer_tag, is_tcp);
case Type::Webrtc:
return make_tl_object(username, password, supports_turn, supports_stun);
default:
diff --git a/td/telegram/CallActor.h b/td/telegram/CallActor.h
index 0c936099b..97186f35f 100644
--- a/td/telegram/CallActor.h
+++ b/td/telegram/CallActor.h
@@ -20,6 +20,7 @@
#include "td/actor/actor.h"
#include "td/actor/PromiseFuture.h"
+#include "td/utils/common.h"
#include "td/utils/Container.h"
#include "td/utils/Status.h"
@@ -55,6 +56,7 @@ struct CallConnection {
// Telegram
string peer_tag;
+ bool is_tcp = false;
// WebRTC
string username;
diff --git a/td/telegram/CallManager.h b/td/telegram/CallManager.h
index 2430fdc65..54a16f32b 100644
--- a/td/telegram/CallManager.h
+++ b/td/telegram/CallManager.h
@@ -13,6 +13,8 @@
#include "td/actor/actor.h"
#include "td/actor/PromiseFuture.h"
+
+#include "td/utils/common.h"
#include "td/utils/FlatHashMap.h"
#include "td/utils/Status.h"
diff --git a/td/telegram/Client.cpp b/td/telegram/Client.cpp
index a102efbfd..b6d9fea60 100644
--- a/td/telegram/Client.cpp
+++ b/td/telegram/Client.cpp
@@ -24,6 +24,7 @@
#include "td/utils/port/RwMutex.h"
#include "td/utils/port/thread.h"
#include "td/utils/Slice.h"
+#include "td/utils/SliceBuilder.h"
#include "td/utils/StringBuilder.h"
#include "td/utils/utf8.h"
diff --git a/td/telegram/ConfigManager.cpp b/td/telegram/ConfigManager.cpp
index a8ba77049..57c8faf16 100644
--- a/td/telegram/ConfigManager.cpp
+++ b/td/telegram/ConfigManager.cpp
@@ -22,6 +22,7 @@
#include "td/telegram/net/NetType.h"
#include "td/telegram/net/PublicRsaKeyShared.h"
#include "td/telegram/net/Session.h"
+#include "td/telegram/Premium.h"
#include "td/telegram/StateManager.h"
#include "td/telegram/Td.h"
#include "td/telegram/TdDb.h"
@@ -908,7 +909,7 @@ void ConfigManager::start_up() {
auto expire_time = load_config_expire_time();
if (expire_time.is_in_past() || true) {
- request_config();
+ request_config(false);
} else {
expire_time_ = expire_time;
set_timeout_in(expire_time_.in());
@@ -934,7 +935,7 @@ void ConfigManager::hangup() {
void ConfigManager::loop() {
if (expire_time_ && expire_time_.is_in_past()) {
- request_config();
+ request_config(reopen_sessions_after_get_config_);
expire_time_ = {};
}
}
@@ -945,17 +946,17 @@ void ConfigManager::try_stop() {
}
}
-void ConfigManager::request_config() {
+void ConfigManager::request_config(bool reopen_sessions) {
if (G()->close_flag()) {
return;
}
- if (config_sent_cnt_ != 0) {
+ if (config_sent_cnt_ != 0 && !reopen_sessions) {
return;
}
lazy_request_flood_control_.add_event(static_cast(Timestamp::now().at()));
- request_config_from_dc_impl(DcId::main());
+ request_config_from_dc_impl(DcId::main(), reopen_sessions);
}
void ConfigManager::lazy_request_config() {
@@ -1085,11 +1086,13 @@ void ConfigManager::on_dc_options_update(DcOptions dc_options) {
send_closure(config_recoverer_, &ConfigRecoverer::on_dc_options_update, std::move(dc_options));
}
-void ConfigManager::request_config_from_dc_impl(DcId dc_id) {
+void ConfigManager::request_config_from_dc_impl(DcId dc_id, bool reopen_sessions) {
config_sent_cnt_++;
+ reopen_sessions_after_get_config_ |= reopen_sessions;
auto query = G()->net_query_creator().create_unauth(telegram_api::help_getConfig(), dc_id);
query->total_timeout_limit_ = 60 * 60 * 24;
- G()->net_query_dispatcher().dispatch_with_callback(std::move(query), actor_shared(this, 8));
+ G()->net_query_dispatcher().dispatch_with_callback(std::move(query),
+ actor_shared(this, 8 + static_cast(reopen_sessions)));
}
void ConfigManager::do_set_ignore_sensitive_content_restrictions(bool ignore_sensitive_content_restrictions) {
@@ -1256,7 +1259,7 @@ void ConfigManager::on_result(NetQueryPtr res) {
return;
}
- CHECK(token == 8);
+ CHECK(token == 8 || token == 9);
CHECK(config_sent_cnt_ > 0);
config_sent_cnt_--;
auto r_config = fetch_result(std::move(res));
@@ -1269,6 +1272,9 @@ void ConfigManager::on_result(NetQueryPtr res) {
} else {
on_dc_options_update(DcOptions());
process_config(r_config.move_as_ok());
+ if (token == 9) {
+ G()->net_query_dispatcher().update_mtproto_header();
+ }
}
}
@@ -1472,12 +1478,20 @@ void ConfigManager::process_app_config(tl_object_ptr &c
double animated_emoji_zoom = 0.0;
string default_reaction;
int64 reactions_uniq_max = 0;
+ vector premium_features;
+ auto &premium_limit_keys = get_premium_limit_keys();
+ string premium_bot_username;
+ string premium_invoice_slug;
+ bool is_premium_available = false;
+ int32 stickers_premium_by_emoji_num = 0;
+ int32 stickers_normal_by_emoji_per_premium_num = 2;
if (config->get_id() == telegram_api::jsonObject::ID) {
for (auto &key_value : static_cast(config.get())->value_) {
Slice key = key_value->key_;
telegram_api::JSONValue *value = key_value->value_.get();
- if (key == "test" || key == "wallet_enabled" || key == "wallet_blockchain_name" || key == "wallet_config" ||
- key == "stickers_emoji_cache_time") {
+ if (key == "message_animated_emoji_max" || key == "stickers_emoji_cache_time" || key == "test" ||
+ key == "upload_max_fileparts_default" || key == "upload_max_fileparts_premium" ||
+ key == "wallet_blockchain_name" || key == "wallet_config" || key == "wallet_enabled") {
continue;
}
if (key == "ignore_restriction_reasons") {
@@ -1733,6 +1747,59 @@ void ConfigManager::process_app_config(tl_object_ptr &c
G()->shared_config().set_option_integer("notification_sound_count_max", setting_value);
continue;
}
+ if (key == "premium_promo_order") {
+ if (value->get_id() == telegram_api::jsonArray::ID) {
+ auto features = std::move(static_cast(value)->value_);
+ for (auto &feature : features) {
+ auto premium_feature = get_json_value_string(std::move(feature), key);
+ if (!td::contains(premium_feature, ',')) {
+ premium_features.push_back(std::move(premium_feature));
+ }
+ }
+ } else {
+ LOG(ERROR) << "Receive unexpected premium_promo_order " << to_string(*value);
+ }
+ continue;
+ }
+ bool is_premium_limit_key = false;
+ for (auto premium_limit_key : premium_limit_keys) {
+ if (begins_with(key, premium_limit_key)) {
+ auto suffix = key.substr(premium_limit_key.size());
+ if (suffix == "_limit_default" || suffix == "_limit_premium") {
+ auto setting_value = get_json_value_int(std::move(key_value->value_), key);
+ if (setting_value > 0) {
+ G()->shared_config().set_option_integer(key, setting_value);
+ } else {
+ LOG(ERROR) << "Receive invalid value " << setting_value << " for " << key;
+ }
+ is_premium_limit_key = true;
+ break;
+ }
+ }
+ }
+ if (is_premium_limit_key) {
+ continue;
+ }
+ if (key == "premium_bot_username") {
+ premium_bot_username = get_json_value_string(std::move(key_value->value_), key);
+ continue;
+ }
+ if (key == "premium_invoice_slug") {
+ premium_invoice_slug = get_json_value_string(std::move(key_value->value_), key);
+ continue;
+ }
+ if (key == "premium_purchase_blocked") {
+ is_premium_available = !get_json_value_bool(std::move(key_value->value_), key);
+ continue;
+ }
+ if (key == "stickers_premium_by_emoji_num") {
+ stickers_premium_by_emoji_num = get_json_value_int(std::move(key_value->value_), key);
+ continue;
+ }
+ if (key == "stickers_normal_by_emoji_per_premium_num") {
+ stickers_normal_by_emoji_per_premium_num = get_json_value_int(std::move(key_value->value_), key);
+ continue;
+ }
new_values.push_back(std::move(key_value));
}
@@ -1816,6 +1883,46 @@ void ConfigManager::process_app_config(tl_object_ptr &c
shared_config.set_option_integer("reactions_uniq_max", reactions_uniq_max);
}
+ bool is_premium = shared_config.get_option_boolean("is_premium");
+
+ auto chat_filter_count_max = shared_config.get_option_integer(
+ is_premium ? Slice("dialog_filters_limit_premium") : Slice("dialog_filters_limit_default"), is_premium ? 20 : 10);
+ shared_config.set_option_integer("chat_filter_count_max", static_cast(chat_filter_count_max));
+
+ auto chat_filter_chosen_chat_count_max = shared_config.get_option_integer(
+ is_premium ? Slice("dialog_filters_chats_limit_premium") : Slice("dialog_filters_chats_limit_default"),
+ is_premium ? 200 : 100);
+ shared_config.set_option_integer("chat_filter_chosen_chat_count_max",
+ static_cast(chat_filter_chosen_chat_count_max));
+
+ auto bio_length_max = shared_config.get_option_integer(
+ is_premium ? Slice("about_length_limit_premium") : Slice("about_length_limit_default"), is_premium ? 140 : 70);
+ shared_config.set_option_integer("bio_length_max", bio_length_max);
+
+ if (!is_premium_available) {
+ premium_bot_username.clear(); // just in case
+ premium_invoice_slug.clear(); // just in case
+ premium_features.clear(); // just in case
+ shared_config.set_option_empty("is_premium_available");
+ } else {
+ shared_config.set_option_boolean("is_premium_available", is_premium_available);
+ }
+ shared_config.set_option_string("premium_features", implode(premium_features, ','));
+ if (premium_bot_username.empty()) {
+ shared_config.set_option_empty("premium_bot_username");
+ } else {
+ shared_config.set_option_string("premium_bot_username", premium_bot_username);
+ }
+ if (premium_invoice_slug.empty()) {
+ shared_config.set_option_empty("premium_invoice_slug");
+ } else {
+ shared_config.set_option_string("premium_invoice_slug", premium_invoice_slug);
+ }
+
+ shared_config.set_option_integer("stickers_premium_by_emoji_num", stickers_premium_by_emoji_num);
+ shared_config.set_option_integer("stickers_normal_by_emoji_per_premium_num",
+ stickers_normal_by_emoji_per_premium_num);
+
shared_config.set_option_empty("default_ton_blockchain_config");
shared_config.set_option_empty("default_ton_blockchain_name");
diff --git a/td/telegram/ConfigManager.h b/td/telegram/ConfigManager.h
index 472982cea..b04be2133 100644
--- a/td/telegram/ConfigManager.h
+++ b/td/telegram/ConfigManager.h
@@ -81,7 +81,7 @@ class ConfigManager final : public NetQueryCallback {
public:
explicit ConfigManager(ActorShared<> parent);
- void request_config();
+ void request_config(bool reopen_sessions);
void lazy_request_config();
@@ -108,6 +108,7 @@ class ConfigManager final : public NetQueryCallback {
private:
ActorShared<> parent_;
int32 config_sent_cnt_{0};
+ bool reopen_sessions_after_get_config_{false};
ActorOwn config_recoverer_;
int ref_cnt_{1};
Timestamp expire_time_;
@@ -141,7 +142,7 @@ class ConfigManager final : public NetQueryCallback {
void on_result(NetQueryPtr res) final;
- void request_config_from_dc_impl(DcId dc_id);
+ void request_config_from_dc_impl(DcId dc_id, bool reopen_sessions);
void process_config(tl_object_ptr config);
void try_request_app_config();
diff --git a/td/telegram/ContactsManager.cpp b/td/telegram/ContactsManager.cpp
index 29b374f39..2a00b9ac5 100644
--- a/td/telegram/ContactsManager.cpp
+++ b/td/telegram/ContactsManager.cpp
@@ -6,13 +6,17 @@
//
#include "td/telegram/ContactsManager.h"
+#include "td/telegram/AnimationsManager.h"
#include "td/telegram/AuthManager.h"
#include "td/telegram/BotMenuButton.h"
#include "td/telegram/ChannelParticipantFilter.h"
+#include "td/telegram/ConfigManager.h"
#include "td/telegram/ConfigShared.h"
#include "td/telegram/Dependencies.h"
#include "td/telegram/DialogInviteLink.h"
#include "td/telegram/DialogLocation.h"
+#include "td/telegram/Document.h"
+#include "td/telegram/DocumentsManager.h"
#include "td/telegram/FileReferenceManager.h"
#include "td/telegram/files/FileManager.h"
#include "td/telegram/files/FileType.h"
@@ -843,6 +847,86 @@ class ToggleChannelSignaturesQuery final : public Td::ResultHandler {
}
};
+class ToggleChannelJoinToSendQuery final : public Td::ResultHandler {
+ Promise promise_;
+ ChannelId channel_id_;
+
+ public:
+ explicit ToggleChannelJoinToSendQuery(Promise &&promise) : promise_(std::move(promise)) {
+ }
+
+ void send(ChannelId channel_id, bool join_to_send) {
+ channel_id_ = channel_id;
+ auto input_channel = td_->contacts_manager_->get_input_channel(channel_id);
+ CHECK(input_channel != nullptr);
+ send_query(G()->net_query_creator().create(
+ telegram_api::channels_toggleJoinToSend(std::move(input_channel), join_to_send)));
+ }
+
+ void on_result(BufferSlice packet) final {
+ auto result_ptr = fetch_result(packet);
+ if (result_ptr.is_error()) {
+ return on_error(result_ptr.move_as_error());
+ }
+
+ auto ptr = result_ptr.move_as_ok();
+ LOG(INFO) << "Receive result for ToggleChannelJoinToSendQuery: " << to_string(ptr);
+ td_->updates_manager_->on_get_updates(std::move(ptr), std::move(promise_));
+ }
+
+ void on_error(Status status) final {
+ if (status.message() == "CHAT_NOT_MODIFIED") {
+ if (!td_->auth_manager_->is_bot()) {
+ promise_.set_value(Unit());
+ return;
+ }
+ } else {
+ td_->contacts_manager_->on_get_channel_error(channel_id_, status, "ToggleChannelJoinToSendQuery");
+ }
+ promise_.set_error(std::move(status));
+ }
+};
+
+class ToggleChannelJoinRequestQuery final : public Td::ResultHandler {
+ Promise promise_;
+ ChannelId channel_id_;
+
+ public:
+ explicit ToggleChannelJoinRequestQuery(Promise &&promise) : promise_(std::move(promise)) {
+ }
+
+ void send(ChannelId channel_id, bool join_request) {
+ channel_id_ = channel_id;
+ auto input_channel = td_->contacts_manager_->get_input_channel(channel_id);
+ CHECK(input_channel != nullptr);
+ send_query(G()->net_query_creator().create(
+ telegram_api::channels_toggleJoinRequest(std::move(input_channel), join_request)));
+ }
+
+ void on_result(BufferSlice packet) final {
+ auto result_ptr = fetch_result(packet);
+ if (result_ptr.is_error()) {
+ return on_error(result_ptr.move_as_error());
+ }
+
+ auto ptr = result_ptr.move_as_ok();
+ LOG(INFO) << "Receive result for ToggleChannelJoinRequestQuery: " << to_string(ptr);
+ td_->updates_manager_->on_get_updates(std::move(ptr), std::move(promise_));
+ }
+
+ void on_error(Status status) final {
+ if (status.message() == "CHAT_NOT_MODIFIED") {
+ if (!td_->auth_manager_->is_bot()) {
+ promise_.set_value(Unit());
+ return;
+ }
+ } else {
+ td_->contacts_manager_->on_get_channel_error(channel_id_, status, "ToggleChannelJoinRequestQuery");
+ }
+ promise_.set_error(std::move(status));
+ }
+};
+
class TogglePrehistoryHiddenQuery final : public Td::ResultHandler {
Promise promise_;
ChannelId channel_id_;
@@ -1339,7 +1423,7 @@ class ExportChatInviteQuery final : public Td::ResultHandler {
auto ptr = result_ptr.move_as_ok();
LOG(INFO) << "Receive result for ExportChatInviteQuery: " << to_string(ptr);
- DialogInviteLink invite_link(std::move(ptr));
+ DialogInviteLink invite_link(std::move(ptr), "ExportChatInviteQuery");
if (!invite_link.is_valid()) {
return on_error(Status::Error(500, "Receive invalid invite link"));
}
@@ -1401,7 +1485,7 @@ class EditChatInviteLinkQuery final : public Td::ResultHandler {
td_->contacts_manager_->on_get_users(std::move(invite->users_), "EditChatInviteLinkQuery");
- DialogInviteLink invite_link(std::move(invite->invite_));
+ DialogInviteLink invite_link(std::move(invite->invite_), "EditChatInviteLinkQuery");
if (!invite_link.is_valid()) {
return on_error(Status::Error(500, "Receive invalid invite link"));
}
@@ -1450,7 +1534,7 @@ class GetExportedChatInviteQuery final : public Td::ResultHandler {
td_->contacts_manager_->on_get_users(std::move(result->users_), "GetExportedChatInviteQuery");
- DialogInviteLink invite_link(std::move(result->invite_));
+ DialogInviteLink invite_link(std::move(result->invite_), "GetExportedChatInviteQuery");
if (!invite_link.is_valid()) {
LOG(ERROR) << "Receive invalid invite link in " << dialog_id_;
return on_error(Status::Error(500, "Receive invalid invite link"));
@@ -1512,7 +1596,7 @@ class GetExportedChatInvitesQuery final : public Td::ResultHandler {
}
vector> invite_links;
for (auto &invite : result->invites_) {
- DialogInviteLink invite_link(std::move(invite));
+ DialogInviteLink invite_link(std::move(invite), "GetExportedChatInvitesQuery");
if (!invite_link.is_valid()) {
LOG(ERROR) << "Receive invalid invite link in " << dialog_id_;
total_count--;
@@ -1853,7 +1937,7 @@ class RevokeChatInviteLinkQuery final : public Td::ResultHandler {
td_->contacts_manager_->on_get_users(std::move(invite->users_), "RevokeChatInviteLinkQuery");
- DialogInviteLink invite_link(std::move(invite->invite_));
+ DialogInviteLink invite_link(std::move(invite->invite_), "RevokeChatInviteLinkQuery");
if (!invite_link.is_valid()) {
return on_error(Status::Error(500, "Receive invalid invite link"));
}
@@ -1865,8 +1949,8 @@ class RevokeChatInviteLinkQuery final : public Td::ResultHandler {
td_->contacts_manager_->on_get_users(std::move(invite->users_), "RevokeChatInviteLinkQuery replaced");
- DialogInviteLink invite_link(std::move(invite->invite_));
- DialogInviteLink new_invite_link(std::move(invite->new_invite_));
+ DialogInviteLink invite_link(std::move(invite->invite_), "RevokeChatInviteLinkQuery replaced");
+ DialogInviteLink new_invite_link(std::move(invite->new_invite_), "RevokeChatInviteLinkQuery new replaced");
if (!invite_link.is_valid() || !new_invite_link.is_valid()) {
return on_error(Status::Error(500, "Receive invalid invite link"));
}
@@ -3528,26 +3612,28 @@ void ContactsManager::User::store(StorerT &storer) const {
STORE_FLAG(is_deleted);
STORE_FLAG(is_bot);
STORE_FLAG(can_join_groups);
- STORE_FLAG(can_read_all_group_messages);
+ STORE_FLAG(can_read_all_group_messages); // 5
STORE_FLAG(is_inline_bot);
STORE_FLAG(need_location_bot);
STORE_FLAG(has_last_name);
STORE_FLAG(has_username);
- STORE_FLAG(has_photo);
- STORE_FLAG(false); // legacy is_restricted
+ STORE_FLAG(has_photo); // 10
+ STORE_FLAG(false); // legacy is_restricted
STORE_FLAG(has_language_code);
STORE_FLAG(have_access_hash);
STORE_FLAG(is_support);
- STORE_FLAG(is_min_access_hash);
+ STORE_FLAG(is_min_access_hash); // 15
STORE_FLAG(is_scam);
STORE_FLAG(has_cache_version);
STORE_FLAG(has_is_contact);
STORE_FLAG(is_contact);
- STORE_FLAG(is_mutual_contact);
+ STORE_FLAG(is_mutual_contact); // 20
STORE_FLAG(has_restriction_reasons);
STORE_FLAG(need_apply_min_photo);
STORE_FLAG(is_fake);
STORE_FLAG(can_be_added_to_attach_menu);
+ STORE_FLAG(is_premium); // 25
+ STORE_FLAG(attach_menu_enabled);
END_STORE_FLAGS();
store(first_name, storer);
if (has_last_name) {
@@ -3619,6 +3705,8 @@ void ContactsManager::User::parse(ParserT &parser) {
PARSE_FLAG(need_apply_min_photo);
PARSE_FLAG(is_fake);
PARSE_FLAG(can_be_added_to_attach_menu);
+ PARSE_FLAG(is_premium);
+ PARSE_FLAG(attach_menu_enabled);
END_PARSE_FLAGS();
parse(first_name, parser);
if (has_last_name) {
@@ -3709,6 +3797,8 @@ void ContactsManager::UserFull::store(StorerT &storer) const {
bool has_group_administrator_rights = group_administrator_rights != AdministratorRights();
bool has_broadcast_administrator_rights = broadcast_administrator_rights != AdministratorRights();
bool has_menu_button = menu_button != nullptr;
+ bool has_description_photo = !description_photo.is_empty();
+ bool has_description_animation = description_animation_file_id.is_valid();
BEGIN_STORE_FLAGS();
STORE_FLAG(has_about);
STORE_FLAG(is_blocked);
@@ -3724,6 +3814,8 @@ void ContactsManager::UserFull::store(StorerT &storer) const {
STORE_FLAG(has_group_administrator_rights);
STORE_FLAG(has_broadcast_administrator_rights);
STORE_FLAG(has_menu_button);
+ STORE_FLAG(has_description_photo);
+ STORE_FLAG(has_description_animation);
END_STORE_FLAGS();
if (has_about) {
store(about, storer);
@@ -3751,6 +3843,13 @@ void ContactsManager::UserFull::store(StorerT &storer) const {
if (has_menu_button) {
store(menu_button, storer);
}
+ if (has_description_photo) {
+ store(description_photo, storer);
+ }
+ if (has_description_animation) {
+ storer.context()->td().get_actor_unsafe()->animations_manager_->store_animation(description_animation_file_id,
+ storer);
+ }
}
template
@@ -3764,6 +3863,8 @@ void ContactsManager::UserFull::parse(ParserT &parser) {
bool has_group_administrator_rights;
bool has_broadcast_administrator_rights;
bool has_menu_button;
+ bool has_description_photo;
+ bool has_description_animation;
BEGIN_PARSE_FLAGS();
PARSE_FLAG(has_about);
PARSE_FLAG(is_blocked);
@@ -3779,6 +3880,8 @@ void ContactsManager::UserFull::parse(ParserT &parser) {
PARSE_FLAG(has_group_administrator_rights);
PARSE_FLAG(has_broadcast_administrator_rights);
PARSE_FLAG(has_menu_button);
+ PARSE_FLAG(has_description_photo);
+ PARSE_FLAG(has_description_animation);
END_PARSE_FLAGS();
if (has_about) {
parse(about, parser);
@@ -3806,6 +3909,13 @@ void ContactsManager::UserFull::parse(ParserT &parser) {
if (has_menu_button) {
parse(menu_button, parser);
}
+ if (has_description_photo) {
+ parse(description_photo, parser);
+ }
+ if (has_description_animation) {
+ description_animation_file_id =
+ parser.context()->td().get_actor_unsafe()->animations_manager_->parse_animation(parser);
+ }
}
template
@@ -4042,6 +4152,8 @@ void ContactsManager::Channel::store(StorerT &storer) const {
STORE_FLAG(is_gigagroup);
STORE_FLAG(noforwards);
STORE_FLAG(can_be_deleted); // 25
+ STORE_FLAG(join_to_send);
+ STORE_FLAG(join_request);
END_STORE_FLAGS();
store(status, storer);
@@ -4113,6 +4225,8 @@ void ContactsManager::Channel::parse(ParserT &parser) {
PARSE_FLAG(is_gigagroup);
PARSE_FLAG(noforwards);
PARSE_FLAG(can_be_deleted);
+ PARSE_FLAG(join_to_send);
+ PARSE_FLAG(join_request);
END_PARSE_FLAGS();
if (use_new_rights) {
@@ -6345,7 +6459,8 @@ void ContactsManager::set_name(const string &first_name, const string &last_name
}
void ContactsManager::set_bio(const string &bio, Promise &&promise) {
- auto new_bio = strip_empty_characters(bio, MAX_BIO_LENGTH);
+ auto max_bio_length = static_cast(G()->shared_config().get_option_integer("bio_length_max"));
+ auto new_bio = strip_empty_characters(bio, max_bio_length);
for (auto &c : new_bio) {
if (c == '\n') {
c = ' ';
@@ -6482,6 +6597,36 @@ void ContactsManager::toggle_channel_sign_messages(ChannelId channel_id, bool si
td_->create_handler(std::move(promise))->send(channel_id, sign_messages);
}
+void ContactsManager::toggle_channel_join_to_send(ChannelId channel_id, bool join_to_send, Promise &&promise) {
+ auto c = get_channel(channel_id);
+ if (c == nullptr) {
+ return promise.set_error(Status::Error(400, "Supergroup not found"));
+ }
+ if (get_channel_type(c) == ChannelType::Broadcast || c->is_gigagroup) {
+ return promise.set_error(Status::Error(400, "The method can be called only for ordinary supergroups"));
+ }
+ if (!get_channel_permissions(c).can_restrict_members()) {
+ return promise.set_error(Status::Error(400, "Not enough rights"));
+ }
+
+ td_->create_handler(std::move(promise))->send(channel_id, join_to_send);
+}
+
+void ContactsManager::toggle_channel_join_request(ChannelId channel_id, bool join_request, Promise &&promise) {
+ auto c = get_channel(channel_id);
+ if (c == nullptr) {
+ return promise.set_error(Status::Error(400, "Supergroup not found"));
+ }
+ if (get_channel_type(c) == ChannelType::Broadcast || c->is_gigagroup) {
+ return promise.set_error(Status::Error(400, "The method can be called only for ordinary supergroups"));
+ }
+ if (!get_channel_permissions(c).can_restrict_members()) {
+ return promise.set_error(Status::Error(400, "Not enough rights"));
+ }
+
+ td_->create_handler(std::move(promise))->send(channel_id, join_request);
+}
+
void ContactsManager::toggle_channel_is_all_history_available(ChannelId channel_id, bool is_all_history_available,
Promise &&promise) {
auto c = get_channel(channel_id);
@@ -8493,11 +8638,13 @@ void ContactsManager::on_get_user(tl_object_ptr &&user_ptr,
}
bool is_verified = (flags & USER_FLAG_IS_VERIFIED) != 0;
+ bool is_premium = (flags & USER_FLAG_IS_PREMIUM) != 0;
bool is_support = (flags & USER_FLAG_IS_SUPPORT) != 0;
bool is_deleted = (flags & USER_FLAG_IS_DELETED) != 0;
bool can_join_groups = (flags & USER_FLAG_IS_PRIVATE_BOT) == 0;
bool can_read_all_group_messages = (flags & USER_FLAG_IS_BOT_WITH_PRIVACY_DISABLED) != 0;
bool can_be_added_to_attach_menu = (flags & USER_FLAG_IS_ATTACH_MENU_BOT) != 0;
+ bool attach_menu_enabled = (flags & USER_FLAG_ATTACH_MENU_ENABLED) != 0;
auto restriction_reasons = get_restriction_reasons(std::move(user->restriction_reason_));
bool is_scam = (flags & USER_FLAG_IS_SCAM) != 0;
bool is_inline_bot = (flags & USER_FLAG_IS_INLINE_BOT) != 0;
@@ -8520,6 +8667,7 @@ void ContactsManager::on_get_user(tl_object_ptr &&user_ptr,
if (is_deleted) {
// just in case
is_verified = false;
+ is_premium = false;
is_support = false;
is_bot = false;
can_join_groups = false;
@@ -8536,15 +8684,17 @@ void ContactsManager::on_get_user(tl_object_ptr &&user_ptr,
<< "Receive not bot " << user_id << " which has bot info version from " << source;
int32 bot_info_version = has_bot_info_version ? user->bot_info_version_ : -1;
- if (is_verified != u->is_verified || is_support != u->is_support || is_bot != u->is_bot ||
- can_join_groups != u->can_join_groups || can_read_all_group_messages != u->can_read_all_group_messages ||
- restriction_reasons != u->restriction_reasons || is_scam != u->is_scam || is_fake != u->is_fake ||
- is_inline_bot != u->is_inline_bot || inline_query_placeholder != u->inline_query_placeholder ||
- need_location_bot != u->need_location_bot || can_be_added_to_attach_menu != u->can_be_added_to_attach_menu) {
+ if (is_verified != u->is_verified || is_premium != u->is_premium || is_support != u->is_support ||
+ is_bot != u->is_bot || can_join_groups != u->can_join_groups ||
+ can_read_all_group_messages != u->can_read_all_group_messages || restriction_reasons != u->restriction_reasons ||
+ is_scam != u->is_scam || is_fake != u->is_fake || is_inline_bot != u->is_inline_bot ||
+ inline_query_placeholder != u->inline_query_placeholder || need_location_bot != u->need_location_bot ||
+ can_be_added_to_attach_menu != u->can_be_added_to_attach_menu || attach_menu_enabled != u->attach_menu_enabled) {
LOG_IF(ERROR, is_bot != u->is_bot && !is_deleted && !u->is_deleted && u->is_received)
<< "User.is_bot has changed for " << user_id << "/" << u->username << " from " << source << " from "
<< u->is_bot << " to " << is_bot;
u->is_verified = is_verified;
+ u->is_premium = is_premium;
u->is_support = is_support;
u->is_bot = is_bot;
u->can_join_groups = can_join_groups;
@@ -8556,6 +8706,7 @@ void ContactsManager::on_get_user(tl_object_ptr &&user_ptr,
u->inline_query_placeholder = std::move(inline_query_placeholder);
u->need_location_bot = need_location_bot;
u->can_be_added_to_attach_menu = can_be_added_to_attach_menu;
+ u->attach_menu_enabled = attach_menu_enabled;
LOG(DEBUG) << "Info has changed for " << user_id;
u->is_changed = true;
@@ -8888,8 +9039,8 @@ ContactsManager::User *ContactsManager::get_user_force(UserId user_id) {
flags, false /*ignored*/, false /*ignored*/, false /*ignored*/, false /*ignored*/, false /*ignored*/,
false /*ignored*/, false /*ignored*/, false /*ignored*/, false /*ignored*/, false /*ignored*/,
false /*ignored*/, false /*ignored*/, false /*ignored*/, false /*ignored*/, false /*ignored*/,
- false /*ignored*/, user_id.get(), 1, first_name, string(), username, phone_number, std::move(profile_photo),
- nullptr, bot_info_version, Auto(), string(), string());
+ false /*ignored*/, false /*ignored*/, false /*ignored*/, user_id.get(), 1, first_name, string(), username,
+ phone_number, std::move(profile_photo), nullptr, bot_info_version, Auto(), string(), string());
on_get_user(std::move(user), "get_user_force");
u = get_user(user_id);
CHECK(u != nullptr && u->is_received);
@@ -10018,6 +10169,12 @@ void ContactsManager::for_each_secret_chat_with_user(UserId user_id, const std::
void ContactsManager::update_user(User *u, UserId user_id, bool from_binlog, bool from_database) {
CHECK(u != nullptr);
+ if (user_id == get_my_id()) {
+ if (G()->shared_config().get_option_boolean("is_premium") != u->is_premium) {
+ G()->shared_config().set_option_boolean("is_premium", u->is_premium);
+ send_closure(td_->config_manager_, &ConfigManager::request_config, true);
+ }
+ }
if (u->is_name_changed || u->is_username_changed || u->is_is_contact_changed) {
update_contacts_hints(u, user_id, from_database);
u->is_username_changed = false;
@@ -10625,14 +10782,34 @@ void ContactsManager::on_get_user_full(tl_object_ptr &&u
td_->group_call_manager_->on_update_dialog_about(DialogId(user_id), user_full->about, true);
}
string description;
+ Photo description_photo;
+ FileId description_animation_file_id;
if (user->bot_info_ != nullptr && !td_->auth_manager_->is_bot()) {
description = std::move(user->bot_info_->description_);
+ description_photo =
+ get_photo(td_->file_manager_.get(), std::move(user->bot_info_->description_photo_), DialogId(user_id));
+ auto document = std::move(user->bot_info_->description_document_);
+ if (document != nullptr) {
+ int32 document_id = document->get_id();
+ if (document_id == telegram_api::document::ID) {
+ auto parsed_document = td_->documents_manager_->on_get_document(
+ move_tl_object_as(document), DialogId(user_id));
+ if (parsed_document.type == Document::Type::Animation) {
+ description_animation_file_id = parsed_document.file_id;
+ } else {
+ LOG(ERROR) << "Receive non-animation document in bot description";
+ }
+ }
+ }
on_update_user_full_commands(user_full, user_id, std::move(user->bot_info_->commands_));
on_update_user_full_menu_button(user_full, user_id, std::move(user->bot_info_->menu_button_));
}
- if (user_full->description != description) {
+ if (user_full->description != description || user_full->description_photo != description_photo ||
+ user_full->description_animation_file_id != description_animation_file_id) {
user_full->description = std::move(description);
+ user_full->description_photo = std::move(description_photo);
+ user_full->description_animation_file_id = description_animation_file_id;
user_full->is_changed = true;
}
@@ -11642,7 +11819,6 @@ void ContactsManager::on_update_user_full_commands(UserFull *user_full, UserId u
void ContactsManager::on_update_user_full_menu_button(UserFull *user_full, UserId user_id,
tl_object_ptr &&bot_menu_button) {
CHECK(user_full != nullptr);
- CHECK(bot_menu_button != nullptr);
auto new_button = get_bot_menu_button(std::move(bot_menu_button));
bool is_changed;
if (user_full->menu_button == nullptr) {
@@ -11906,6 +12082,8 @@ void ContactsManager::drop_user_full(UserId user_id) {
user_full->need_phone_number_privacy_exception = false;
user_full->about = string();
user_full->description = string();
+ user_full->description_photo = Photo();
+ user_full->description_animation_file_id = FileId();
user_full->menu_button = nullptr;
user_full->commands.clear();
user_full->common_chat_count = 0;
@@ -12788,17 +12966,18 @@ void ContactsManager::on_get_permanent_dialog_invite_link(DialogId dialog_id, co
}
void ContactsManager::on_update_chat_full_invite_link(ChatFull *chat_full,
- tl_object_ptr &&invite_link) {
+ tl_object_ptr &&invite_link) {
CHECK(chat_full != nullptr);
- if (update_permanent_invite_link(chat_full->invite_link, DialogInviteLink(std::move(invite_link)))) {
+ if (update_permanent_invite_link(chat_full->invite_link, DialogInviteLink(std::move(invite_link), "ChatFull"))) {
chat_full->is_changed = true;
}
}
void ContactsManager::on_update_channel_full_invite_link(
- ChannelFull *channel_full, tl_object_ptr &&invite_link) {
+ ChannelFull *channel_full, tl_object_ptr &&invite_link) {
CHECK(channel_full != nullptr);
- if (update_permanent_invite_link(channel_full->invite_link, DialogInviteLink(std::move(invite_link)))) {
+ if (update_permanent_invite_link(channel_full->invite_link,
+ DialogInviteLink(std::move(invite_link), "ChannelFull"))) {
channel_full->is_changed = true;
}
}
@@ -14154,6 +14333,11 @@ bool ContactsManager::have_min_user(UserId user_id) const {
return users_.count(user_id) > 0;
}
+bool ContactsManager::is_user_premium(UserId user_id) const {
+ auto u = get_user(user_id);
+ return u != nullptr && u->is_premium;
+}
+
bool ContactsManager::is_user_deleted(UserId user_id) const {
auto u = get_user(user_id);
return u == nullptr || u->is_deleted;
@@ -14657,7 +14841,8 @@ ContactsManager::ChatFull *ContactsManager::add_chat_full(ChatId chat_id) {
return chat_full_ptr.get();
}
-bool ContactsManager::is_chat_full_outdated(const ChatFull *chat_full, const Chat *c, ChatId chat_id) {
+bool ContactsManager::is_chat_full_outdated(const ChatFull *chat_full, const Chat *c, ChatId chat_id,
+ bool only_participants) const {
CHECK(c != nullptr);
CHECK(chat_full != nullptr);
if (!c->is_active && chat_full->version == -1) {
@@ -14670,11 +14855,17 @@ bool ContactsManager::is_chat_full_outdated(const ChatFull *chat_full, const Cha
return true;
}
- if (c->is_active && c->status.can_manage_invite_links() && !chat_full->invite_link.is_valid()) {
+ if (!only_participants && c->is_active && c->status.can_manage_invite_links() && !chat_full->invite_link.is_valid()) {
LOG(INFO) << "Have outdated invite link in " << chat_id;
return true;
}
+ if (!only_participants &&
+ !is_same_dialog_photo(td_->file_manager_.get(), DialogId(chat_id), chat_full->photo, c->photo)) {
+ LOG(INFO) << "Have outdated chat photo in " << chat_id;
+ return true;
+ }
+
LOG(DEBUG) << "Full " << chat_id << " is up-to-date with version " << chat_full->version;
return false;
}
@@ -14691,7 +14882,7 @@ void ContactsManager::load_chat_full(ChatId chat_id, bool force, Promise &
return send_get_chat_full_query(chat_id, std::move(promise), source);
}
- if (is_chat_full_outdated(chat_full, c, chat_id)) {
+ if (is_chat_full_outdated(chat_full, c, chat_id, false)) {
LOG(INFO) << "Have outdated full " << chat_id;
if (td_->auth_manager_->is_bot() && !force) {
return send_get_chat_full_query(chat_id, std::move(promise), source);
@@ -14908,6 +15099,14 @@ bool ContactsManager::get_channel_can_be_deleted(const Channel *c) {
return c->can_be_deleted;
}
+bool ContactsManager::get_channel_join_to_send(const Channel *c) {
+ return c->join_to_send || !c->is_megagroup || !c->has_linked_channel;
+}
+
+bool ContactsManager::get_channel_join_request(const Channel *c) {
+ return c->join_request && c->is_megagroup && (is_channel_public(c) || c->has_linked_channel);
+}
+
ChannelId ContactsManager::get_channel_linked_channel_id(ChannelId channel_id) {
auto channel_full = get_channel_full_const(channel_id);
if (channel_full == nullptr) {
@@ -15505,7 +15704,7 @@ void ContactsManager::get_chat_participant(ChatId chat_id, UserId user_id, Promi
}
auto chat_full = get_chat_full_force(chat_id, "get_chat_participant");
- if (chat_full == nullptr || (td_->auth_manager_->is_bot() && is_chat_full_outdated(chat_full, c, chat_id))) {
+ if (chat_full == nullptr || (td_->auth_manager_->is_bot() && is_chat_full_outdated(chat_full, c, chat_id, true))) {
auto query_promise = PromiseCreator::lambda(
[actor_id = actor_id(this), chat_id, user_id, promise = std::move(promise)](Result &&result) mutable {
TRY_STATUS_PROMISE(promise, std::move(result));
@@ -15515,7 +15714,7 @@ void ContactsManager::get_chat_participant(ChatId chat_id, UserId user_id, Promi
return;
}
- if (is_chat_full_outdated(chat_full, c, chat_id)) {
+ if (is_chat_full_outdated(chat_full, c, chat_id, true)) {
send_get_chat_full_query(chat_id, Auto(), "get_chat_participant lazy");
}
@@ -16011,6 +16210,8 @@ void ContactsManager::on_chat_update(telegram_api::channel &channel, const char
bool has_linked_channel = (channel.flags_ & CHANNEL_FLAG_HAS_LINKED_CHAT) != 0;
bool sign_messages = (channel.flags_ & CHANNEL_FLAG_SIGN_MESSAGES) != 0;
+ bool join_to_send = (channel.flags_ & CHANNEL_FLAG_JOIN_TO_SEND) != 0;
+ bool join_request = (channel.flags_ & CHANNEL_FLAG_JOIN_REQUEST) != 0;
bool is_slow_mode_enabled = (channel.flags_ & CHANNEL_FLAG_IS_SLOW_MODE_ENABLED) != 0;
bool is_megagroup = (channel.flags_ & CHANNEL_FLAG_IS_MEGAGROUP) != 0;
bool is_verified = (channel.flags_ & CHANNEL_FLAG_IS_VERIFIED) != 0;
@@ -16072,6 +16273,9 @@ void ContactsManager::on_chat_update(telegram_api::channel &channel, const char
Channel *c = get_channel_force(channel_id);
if (c != nullptr) {
LOG(DEBUG) << "Receive known min " << channel_id;
+
+ auto old_join_to_send = get_channel_join_to_send(c);
+ auto old_join_request = get_channel_join_request(c);
on_update_channel_title(c, channel_id, std::move(channel.title_));
on_update_channel_username(c, channel_id, std::move(channel.username_));
on_update_channel_photo(c, channel_id, std::move(channel.photo_));
@@ -16093,12 +16297,21 @@ void ContactsManager::on_chat_update(telegram_api::channel &channel, const char
c->is_changed = true;
invalidate_channel_full(channel_id, !c->is_slow_mode_enabled);
}
+ if (c->join_to_send != join_to_send || c->join_request != join_request) {
+ c->join_to_send = join_to_send;
+ c->join_request = join_request;
+
+ c->need_save_to_database = true;
+ }
// sign_messages isn't known for min-channels
if (c->is_verified != is_verified) {
c->is_verified = is_verified;
c->is_changed = true;
}
+ if (old_join_to_send != get_channel_join_to_send(c) || old_join_request != get_channel_join_request(c)) {
+ c->is_changed = true;
+ }
update_channel(c, channel_id);
} else {
@@ -16129,6 +16342,8 @@ void ContactsManager::on_chat_update(telegram_api::channel &channel, const char
if (c->status.is_banned()) { // possibly uninited channel
min_channels_.erase(channel_id);
}
+ auto old_join_to_send = get_channel_join_to_send(c);
+ auto old_join_request = get_channel_join_request(c);
if (c->access_hash != access_hash) {
c->access_hash = access_hash;
c->need_save_to_database = true;
@@ -16162,16 +16377,27 @@ void ContactsManager::on_chat_update(telegram_api::channel &channel, const char
c->is_scam = is_scam;
c->is_fake = is_fake;
c->is_gigagroup = is_gigagroup;
+ c->join_to_send = join_to_send;
+ c->join_request = join_request;
c->is_changed = true;
need_invalidate_channel_full = true;
}
+ if (c->join_to_send != join_to_send || c->join_request != join_request) {
+ c->join_to_send = join_to_send;
+ c->join_request = join_request;
+
+ c->need_save_to_database = true;
+ }
if (c->is_verified != is_verified || c->sign_messages != sign_messages) {
c->is_verified = is_verified;
c->sign_messages = sign_messages;
c->is_changed = true;
}
+ if (old_join_to_send != get_channel_join_to_send(c) || old_join_request != get_channel_join_request(c)) {
+ c->is_changed = true;
+ }
if (c->cache_version != Channel::CACHE_VERSION) {
c->cache_version = Channel::CACHE_VERSION;
@@ -16220,6 +16446,8 @@ void ContactsManager::on_chat_update(telegram_api::channelForbidden &channel, co
if (c->status.is_banned()) { // possibly uninited channel
min_channels_.erase(channel_id);
}
+ auto old_join_to_send = get_channel_join_to_send(c);
+ auto old_join_request = get_channel_join_request(c);
if (c->access_hash != channel.access_hash_) {
c->access_hash = channel.access_hash_;
c->need_save_to_database = true;
@@ -16240,6 +16468,8 @@ void ContactsManager::on_chat_update(telegram_api::channelForbidden &channel, co
td_->messages_manager_->on_update_dialog_group_call(DialogId(channel_id), false, false, "receive channelForbidden");
bool sign_messages = false;
+ bool join_to_send = false;
+ bool join_request = false;
bool is_slow_mode_enabled = false;
bool is_megagroup = (channel.flags_ & CHANNEL_FLAG_IS_MEGAGROUP) != 0;
bool is_verified = false;
@@ -16259,23 +16489,35 @@ void ContactsManager::on_chat_update(telegram_api::channelForbidden &channel, co
bool need_invalidate_channel_full = false;
if (c->is_slow_mode_enabled != is_slow_mode_enabled || c->is_megagroup != is_megagroup ||
- !c->restriction_reasons.empty() || c->is_scam != is_scam || c->is_fake != is_fake) {
+ !c->restriction_reasons.empty() || c->is_scam != is_scam || c->is_fake != is_fake ||
+ c->join_to_send != join_to_send || c->join_request != join_request) {
// c->has_linked_channel = has_linked_channel;
c->is_slow_mode_enabled = is_slow_mode_enabled;
c->is_megagroup = is_megagroup;
c->restriction_reasons.clear();
c->is_scam = is_scam;
c->is_fake = is_fake;
+ c->join_to_send = join_to_send;
+ c->join_request = join_request;
c->is_changed = true;
need_invalidate_channel_full = true;
}
+ if (c->join_to_send != join_to_send || c->join_request != join_request) {
+ c->join_to_send = join_to_send;
+ c->join_request = join_request;
+
+ c->need_save_to_database = true;
+ }
if (c->sign_messages != sign_messages || c->is_verified != is_verified) {
c->sign_messages = sign_messages;
c->is_verified = is_verified;
c->is_changed = true;
}
+ if (old_join_to_send != get_channel_join_to_send(c) || old_join_request != get_channel_join_request(c)) {
+ c->is_changed = true;
+ }
bool need_drop_participant_count = c->participant_count != 0;
if (need_drop_participant_count) {
@@ -16390,7 +16632,7 @@ td_api::object_ptr ContactsManager::get_user_status_object(U
td_api::object_ptr ContactsManager::get_update_unknown_user_object(UserId user_id) {
return td_api::make_object(td_api::make_object(
user_id.get(), "", "", "", "", td_api::make_object(), nullptr, false, false, false,
- false, "", false, false, false, td_api::make_object(), ""));
+ false, false, "", false, false, false, td_api::make_object(), "", false));
}
int64 ContactsManager::get_user_id_object(UserId user_id, const char *source) const {
@@ -16450,8 +16692,8 @@ tl_object_ptr ContactsManager::get_user_object(UserId user_id, con
return make_tl_object(
user_id.get(), u->first_name, u->last_name, u->username, u->phone_number, get_user_status_object(user_id, u),
get_profile_photo_object(td_->file_manager_.get(), u->photo), u->is_contact, u->is_mutual_contact, u->is_verified,
- u->is_support, get_restriction_reason_description(u->restriction_reasons), u->is_scam, u->is_fake, u->is_received,
- std::move(type), u->language_code);
+ u->is_premium, u->is_support, get_restriction_reason_description(u->restriction_reasons), u->is_scam, u->is_fake,
+ u->is_received, std::move(type), u->language_code, u->attach_menu_enabled);
}
vector ContactsManager::get_user_ids_object(const vector &user_ids, const char *source) const {
@@ -16475,24 +16717,33 @@ tl_object_ptr ContactsManager::get_user_full_info_object(U
CHECK(user_full != nullptr);
td_api::object_ptr bot_info;
bool is_bot = is_user_bot(user_id);
+ td_api::object_ptr bio_object;
if (is_bot) {
auto menu_button = get_bot_menu_button_object(td_, user_full->menu_button.get());
auto commands =
transform(user_full->commands, [](const auto &command) { return command.get_bot_command_object(); });
bot_info = td_api::make_object(
- user_full->about, user_full->description, std::move(menu_button), std::move(commands),
+ user_full->about, user_full->description,
+ get_photo_object(td_->file_manager_.get(), user_full->description_photo),
+ td_->animations_manager_->get_animation_object(user_full->description_animation_file_id),
+ std::move(menu_button), std::move(commands),
user_full->group_administrator_rights == AdministratorRights()
? nullptr
: user_full->group_administrator_rights.get_chat_administrator_rights_object(),
user_full->broadcast_administrator_rights == AdministratorRights()
? nullptr
: user_full->broadcast_administrator_rights.get_chat_administrator_rights_object());
+ } else {
+ FormattedText bio;
+ bio.text = user_full->about;
+ bio.entities = find_entities(bio.text, true, true, !is_user_premium(user_id));
+ bio_object = get_formatted_text_object(bio, true, 0);
}
return make_tl_object(
get_chat_photo_object(td_->file_manager_.get(), user_full->photo), user_full->is_blocked,
user_full->can_be_called, user_full->supports_video_calls, user_full->has_private_calls,
- !user_full->private_forward_name.empty(), user_full->need_phone_number_privacy_exception,
- is_bot ? string() : user_full->about, user_full->common_chat_count, std::move(bot_info));
+ !user_full->private_forward_name.empty(), user_full->need_phone_number_privacy_exception, std::move(bio_object),
+ user_full->common_chat_count, std::move(bot_info));
}
td_api::object_ptr ContactsManager::get_update_unknown_basic_group_object(ChatId chat_id) {
@@ -16550,10 +16801,10 @@ tl_object_ptr ContactsManager::get_basic_group_full_
td_api::object_ptr ContactsManager::get_update_unknown_supergroup_object(
ChannelId channel_id) const {
auto min_channel = get_min_channel(channel_id);
+ bool is_megagroup = min_channel == nullptr ? false : min_channel->is_megagroup_;
return td_api::make_object(td_api::make_object(
channel_id.get(), string(), 0, DialogParticipantStatus::Banned(0).get_chat_member_status_object(), 0, false,
- false, false, false, min_channel == nullptr ? true : !min_channel->is_megagroup_, false, false, string(), false,
- false));
+ false, false, !is_megagroup, false, false, !is_megagroup, false, false, string(), false, false));
}
int64 ContactsManager::get_supergroup_id_object(ChannelId channel_id, const char *source) const {
@@ -16579,9 +16830,9 @@ tl_object_ptr ContactsManager::get_supergroup_object(Channel
}
return td_api::make_object(
channel_id.get(), c->username, c->date, get_channel_status(c).get_chat_member_status_object(),
- c->participant_count, c->has_linked_channel, c->has_location, c->sign_messages, c->is_slow_mode_enabled,
- !c->is_megagroup, c->is_gigagroup, c->is_verified, get_restriction_reason_description(c->restriction_reasons),
- c->is_scam, c->is_fake);
+ c->participant_count, c->has_linked_channel, c->has_location, c->sign_messages, get_channel_join_to_send(c),
+ get_channel_join_request(c), c->is_slow_mode_enabled, !c->is_megagroup, c->is_gigagroup, c->is_verified,
+ get_restriction_reason_description(c->restriction_reasons), c->is_scam, c->is_fake);
}
tl_object_ptr ContactsManager::get_supergroup_full_info_object(ChannelId channel_id) const {
diff --git a/td/telegram/ContactsManager.h b/td/telegram/ContactsManager.h
index 4c5b19507..2730d2369 100644
--- a/td/telegram/ContactsManager.h
+++ b/td/telegram/ContactsManager.h
@@ -349,6 +349,10 @@ class ContactsManager final : public Actor {
void toggle_channel_sign_messages(ChannelId channel_id, bool sign_messages, Promise &&promise);
+ void toggle_channel_join_to_send(ChannelId channel_id, bool joint_to_send, Promise &&promise);
+
+ void toggle_channel_join_request(ChannelId channel_id, bool join_request, Promise &&promise);
+
void toggle_channel_is_all_history_available(ChannelId channel_id, bool is_all_history_available,
Promise &&promise);
@@ -450,6 +454,8 @@ class ContactsManager final : public Actor {
bool is_user_contact(UserId user_id, bool is_mutual = false) const;
+ bool is_user_premium(UserId user_id) const;
+
bool is_user_deleted(UserId user_id) const;
bool is_user_support(UserId user_id) const;
@@ -654,6 +660,7 @@ class ContactsManager final : public Actor {
bool is_min_access_hash = true;
bool is_received = false;
bool is_verified = false;
+ bool is_premium = false;
bool is_support = false;
bool is_deleted = true;
bool is_bot = true;
@@ -667,6 +674,7 @@ class ContactsManager final : public Actor {
bool is_mutual_contact = false;
bool need_apply_min_photo = false;
bool can_be_added_to_attach_menu = false;
+ bool attach_menu_enabled = false;
bool is_photo_inited = false;
@@ -704,8 +712,10 @@ class ContactsManager final : public Actor {
Photo photo;
string about;
- string description;
string private_forward_name;
+ string description;
+ Photo description_photo;
+ FileId description_animation_file_id;
unique_ptr menu_button;
vector commands;
@@ -826,7 +836,7 @@ class ContactsManager final : public Actor {
int32 date = 0;
int32 participant_count = 0;
- static constexpr uint32 CACHE_VERSION = 8;
+ static constexpr uint32 CACHE_VERSION = 9;
uint32 cache_version = 0;
bool has_linked_channel = false;
@@ -835,6 +845,8 @@ class ContactsManager final : public Actor {
bool is_slow_mode_enabled = false;
bool noforwards = false;
bool can_be_deleted = false;
+ bool join_to_send = false;
+ bool join_request = false;
bool is_megagroup = false;
bool is_gigagroup = false;
@@ -1016,7 +1028,6 @@ class ContactsManager final : public Actor {
static constexpr int32 MAX_GET_PROFILE_PHOTOS = 100; // server side limit
static constexpr size_t MAX_NAME_LENGTH = 64; // server side limit for first/last name
static constexpr size_t MAX_DESCRIPTION_LENGTH = 255; // server side limit for chat/channel description
- static constexpr size_t MAX_BIO_LENGTH = 70; // server side limit
static constexpr size_t MAX_INVITE_LINK_TITLE_LENGTH = 32; // server side limit
static constexpr int32 MAX_GET_CHANNEL_PARTICIPANTS = 200; // server side limit
@@ -1048,6 +1059,8 @@ class ContactsManager final : public Actor {
static constexpr int32 USER_FLAG_NEED_APPLY_MIN_PHOTO = 1 << 25;
static constexpr int32 USER_FLAG_IS_FAKE = 1 << 26;
static constexpr int32 USER_FLAG_IS_ATTACH_MENU_BOT = 1 << 27;
+ static constexpr int32 USER_FLAG_IS_PREMIUM = 1 << 28;
+ static constexpr int32 USER_FLAG_ATTACH_MENU_ENABLED = 1 << 29;
static constexpr int32 USER_FULL_FLAG_IS_BLOCKED = 1 << 0;
static constexpr int32 USER_FULL_FLAG_HAS_ABOUT = 1 << 1;
@@ -1104,6 +1117,8 @@ class ContactsManager final : public Actor {
static constexpr int32 CHANNEL_FLAG_IS_FAKE = 1 << 25;
static constexpr int32 CHANNEL_FLAG_IS_GIGAGROUP = 1 << 26;
static constexpr int32 CHANNEL_FLAG_NOFORWARDS = 1 << 27;
+ static constexpr int32 CHANNEL_FLAG_JOIN_TO_SEND = 1 << 28;
+ static constexpr int32 CHANNEL_FLAG_JOIN_REQUEST = 1 << 29;
static constexpr int32 CHANNEL_FULL_FLAG_HAS_PARTICIPANT_COUNT = 1 << 0;
static constexpr int32 CHANNEL_FULL_FLAG_HAS_ADMINISTRATOR_COUNT = 1 << 1;
@@ -1214,6 +1229,8 @@ class ContactsManager final : public Actor {
static bool get_channel_sign_messages(const Channel *c);
static bool get_channel_has_linked_channel(const Channel *c);
static bool get_channel_can_be_deleted(const Channel *c);
+ static bool get_channel_join_to_send(const Channel *c);
+ static bool get_channel_join_request(const Channel *c);
void set_my_id(UserId my_id);
@@ -1272,7 +1289,7 @@ class ContactsManager final : public Actor {
void on_update_chat_full_participants(ChatFull *chat_full, ChatId chat_id, vector participants,
int32 version, bool from_update);
void on_update_chat_full_invite_link(ChatFull *chat_full,
- tl_object_ptr &&invite_link);
+ tl_object_ptr