This commit is contained in:
Andrea Cavalli 2020-12-25 20:24:09 +01:00
commit f610ff028c
32 changed files with 1267 additions and 672 deletions

View File

@ -92,7 +92,7 @@ PenaltyBreakString: 1000
PenaltyBreakTemplateDeclaration: 10
PenaltyExcessCharacter: 1000000
PenaltyReturnTypeOnItsOwnLine: 200
PointerAlignment: Left
PointerAlignment: Right
ReflowComments: false # true
SortIncludes: false # disabled, because we need case insensitive sort
SortUsingDeclarations: false # true

View File

@ -127,6 +127,7 @@ class DoxygenTlDocumentationGenerator extends TlDocumentationGenerator
return empty($tline) || $tline[0] === '}' || $tline === 'public:' || strpos($line, '#pragma ') === 0 ||
strpos($line, '#include <') === 0 || strpos($tline, 'return ') === 0 || strpos($tline, 'namespace') === 0 ||
preg_match('/class [A-Za-z0-9_]*;/', $line) || $tline === 'if (value == nullptr) {' ||
strpos($tline, 'result += ') === 0 || strpos($tline, 'result = ') || strpos($tline, ' : values') ||
strpos($line, 'JNIEnv') || strpos($line, 'jfieldID') || $tline === 'virtual ~Object() {' ||
$tline === 'virtual void store(TlStorerToString &s, const char *field_name) const = 0;';
}
@ -294,7 +295,7 @@ EOT
$this->addDocumentation('std::string to_string(const BaseObject &value);', <<<EOT
/**
* Returns a string representation of the TDLib API object.
* Returns a string representation of a TDLib API object.
* \\param[in] value The object.
* \\return Object string representation.
*/
@ -303,12 +304,22 @@ EOT
$this->addDocumentation('std::string to_string(const object_ptr<T> &value) {', <<<EOT
/**
* Returns a string representation of the TDLib API object.
* Returns a string representation of a TDLib API object.
* \\tparam T Object type, auto-deduced.
* \\param[in] value The object.
* \\return Object string representation.
*/
EOT
);
$this->addDocumentation('std::string to_string(const std::vector<object_ptr<T>> &values) {', <<<EOT
/**
* Returns a string representation of a list of TDLib API objects.
* \\tparam T Object type, auto-deduced.
* \\param[in] values The objects.
* \\return Objects string representation.
*/
EOT
);
$this->addDocumentation(' void store(TlStorerToString &s, const char *field_name) const final;', <<<EOT

View File

@ -719,7 +719,7 @@ messageSendingStateFailed error_code:int32 error_message:string can_retry:Bool r
//@ttl_expires_in Time left before the message expires, in seconds
//@via_bot_user_id If non-zero, the user identifier of the bot through which this message was sent
//@author_signature For channel posts and anonymous group messages, optional author signature
//@media_album_id Unique identifier of an album this message belongs to. Only photos and videos can be grouped together in albums
//@media_album_id Unique identifier of an album this message belongs to. Only audios, documents, photos and videos can be grouped together in albums
//@restriction_reason If non-empty, contains a human-readable description of the reason why access to this message must be restricted
//@content Content of the message
//@reply_markup Reply markup for the message; may be null
@ -953,7 +953,7 @@ keyboardButton text:string type:KeyboardButtonType = KeyboardButton;
//@description A button that opens a specified URL @url HTTP or tg:// URL to open
inlineKeyboardButtonTypeUrl url:string = InlineKeyboardButtonType;
//@description A button that opens a specified URL and automatically logs in in current user if they allowed to do that @url An HTTP URL to open @id Unique button identifier @forward_text If non-empty, new text of the button in forwarded messages
//@description A button that opens a specified URL and automatically authorize the current user if allowed to do so @url An HTTP URL to open @id Unique button identifier @forward_text If non-empty, new text of the button in forwarded messages
inlineKeyboardButtonTypeLoginUrl url:string id:int32 forward_text: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
@ -1816,8 +1816,8 @@ inputMessageDocument document:InputFile thumbnail:inputThumbnail disable_content
//@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<int32> width:int32 height:int32 caption:formattedText ttl:int32 = InputMessageContent;
//@description A sticker message @sticker Sticker to be sent @thumbnail Sticker thumbnail, if available @width Sticker width @height Sticker height
inputMessageSticker sticker:InputFile thumbnail:inputThumbnail width:int32 height:int32 = InputMessageContent;
//@description A sticker message @sticker Sticker to be sent @thumbnail Sticker thumbnail, if available @width Sticker width @height Sticker height @emoji Emoji used to choose the sticker
inputMessageSticker sticker:InputFile thumbnail:inputThumbnail width:int32 height:int32 emoji:string = InputMessageContent;
//@description A video message @video Video to be sent @thumbnail Video thumbnail, if available @added_sticker_file_ids File identifiers of the stickers added to the video, if applicable
//@duration Duration of the video, in seconds @width Video width @height Video height @supports_streaming True, if the video should be tried to be streamed
@ -1989,7 +1989,7 @@ stickerSet id:int64 title:string name:string thumbnail:thumbnail thumbnail_outli
//@description Represents short information about a sticker set
//@id Identifier of the sticker set @title Title of the sticker set @name Name of the sticker set @thumbnail Sticker set thumbnail in WEBP or TGS format with width and height 100; may be null
//@thumbnail_outline Sticker set thumbnail's outline represented as a list of closed vector paths; may be empty. The coordinate system origin is in the upper-left corner
//@is_installed True, if the sticker set has been installed by current user @is_archived True, if the sticker set has been archived. A sticker set can't be installed and archived simultaneously
//@is_installed True, if the sticker set has been installed by the current user @is_archived True, if the sticker set has been archived. A sticker set can't be installed and archived simultaneously
//@is_official True, if the sticker set is official @is_animated True, is the stickers in the set are animated @is_masks True, if the stickers in the set are masks @is_viewed True for already viewed trending sticker sets
//@size Total number of stickers in the set @covers Contains up to the first 5 stickers from the set, depending on the context. If the application needs more stickers the full set should be requested
stickerSetInfo id:int64 title:string name:string thumbnail:thumbnail thumbnail_outline:vector<closedVectorPath> is_installed:Bool is_archived:Bool is_official:Bool is_animated:Bool is_masks:Bool is_viewed:Bool size:int32 covers:vector<sticker> = StickerSetInfo;
@ -2070,14 +2070,16 @@ callStateError error:error = CallState;
//@id Group call identifier
//@is_active True, if the call is active
//@is_joined True, if the call is joined
//@can_unmute_self True, if the user can unmute themself
//@need_rejoin True, if user was kicked from the call because of network loss and the call needs to be rejoined
//@can_unmute_self True, if the current user can unmute themself
//@can_be_managed True, if the current user can manage the group call
//@participant_count Number of participants in the group call
//@loaded_all_participants True, if all group call participants are loaded
//@recent_speaker_user_ids Identifiers of recently speaking users in the group call
//@mute_new_participants True, if only group call administrators can unmute new participants
//@allowed_change_mute_new_participants True, if group call administrators can enable or disable mute_new_participants setting
//@duration Call duration; for ended calls only
groupCall id:int32 is_active:Bool is_joined:Bool can_unmute_self:Bool participant_count:int32 loaded_all_participants:Bool recent_speaker_user_ids:vector<int32> mute_new_participants:Bool allowed_change_mute_new_participants:Bool duration:int32 = GroupCall;
groupCall id:int32 is_active:Bool is_joined:Bool need_rejoin:Bool can_unmute_self:Bool can_be_managed:Bool participant_count:int32 loaded_all_participants:Bool recent_speaker_user_ids:vector<int32> mute_new_participants:Bool allowed_change_mute_new_participants:Bool duration:int32 = GroupCall;
//@description Describes a payload fingerprint for interaction with tgcalls @hash Value of the field hash @setup Value of the field setup @fingerprint Value of the field fingerprint
groupCallPayloadFingerprint hash:string setup:string fingerprint:string = GroupCallPayloadFingerprint;
@ -2093,10 +2095,16 @@ groupCallJoinResponseCandidate port:string protocol:string network:string genera
//@description Describes a join response for interaction with tgcalls @payload Join response payload to pass to tgcalls @candidates Join response candidates to pass to tgcalls
groupCallJoinResponse payload:groupCallPayload candidates:vector<groupCallJoinResponseCandidate> = GroupCallJoinResponse;
//@description Represents a group call participant @user_id Identifier of the user @source User's synchronization source
//@is_speaking True, if the user is speaking as set by setGroupCallParticipantIsSpeaking @is_muted True, if the user is muted @can_unmute_self True, if the user can unmute themself
//@description Represents a group call participant
//@user_id Identifier of the user
//@source User's synchronization source
//@is_speaking True, if the participant is speaking as set by setGroupCallParticipantIsSpeaking
//@can_be_muted True, if the current user can mute the participant
//@can_be_unmuted True, if the current user can allow the participant to unmute themself or unmute the participant (only for self)
//@is_muted True, if the participant is muted
//@can_unmute_self True, if the participant can unmute themself
//@order User's order in the group call participant list. The bigger is order, the higher is user in the list. If order is 0, the user must be removed from the participant list
groupCallParticipant user_id:int32 source:int32 is_speaking:Bool is_muted:Bool can_unmute_self:Bool order:int64 = GroupCallParticipant;
groupCallParticipant user_id:int32 source:int32 is_speaking:Bool can_be_muted:Bool can_be_unmuted:Bool is_muted:Bool can_unmute_self:Bool order:int64 = GroupCallParticipant;
//@class CallProblem @description Describes the exact type of a problem with a call
@ -3413,8 +3421,7 @@ updateCall call:call = Update;
updateGroupCall group_call:groupCall = Update;
//@description Information about a group call participant was changed. The updates are sent only after the group call is received through getGroupCall and only if the call is joined or being joined
//@group_call_id Identifier of group call
//@participant New data about a participant. If this is a current user with different source, then the current user joined the call from another device and the call must not be rejoined automatically
//@group_call_id Identifier of group call @participant New data about a participant
updateGroupCallParticipant group_call_id:int32 participant:groupCallParticipant = Update;
//@description New call signaling data arrived @call_id The call identifier @data The data
@ -4227,10 +4234,10 @@ unpinChatMessage chat_id:int53 message_id:int53 = Ok;
unpinAllChatMessages chat_id:int53 = Ok;
//@description Adds 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 @chat_id Chat identifier
joinChat chat_id:int53 = Ok;
//@description Removes current user from chat members. Private and secret chats can't be left using this method @chat_id Chat identifier
//@description Removes the current user from chat members. Private and secret chats can't be left using this method @chat_id Chat identifier
leaveChat chat_id:int53 = Ok;
//@description Adds a new member to a chat. Members can't be added to private or secret chats. Members will not be added until the chat state has been synchronized with the server
@ -4382,10 +4389,10 @@ toggleGroupCallMuteNewParticipants group_call_id:int32 mute_new_participants:Boo
inviteGroupCallParticipants group_call_id:int32 user_ids:vector<int32> = Ok;
//@description Informs TDLib that a group call participant speaking state has changed @group_call_id Group call identifier
//@source Group call participant's synchronization source identifier @is_speaking True, if the user is speaking
//@source Group call participant's synchronization source identifier, or 0 for the current user @is_speaking True, if the user is speaking
setGroupCallParticipantIsSpeaking group_call_id:int32 source:int32 is_speaking:Bool = Ok;
//@description Toggles whether a group call participant is muted. Requires can_manage_voice_chats rights to mute other group call participants
//@description Toggles whether a group call participant is muted, unmuted, or allowed to unmute themself
//@group_call_id Group call identifier @user_id User identifier @is_muted Pass true if the user must be muted and false otherwise
toggleGroupCallParticipantIsMuted group_call_id:int32 user_id:int32 is_muted:Bool = Ok;
@ -4437,7 +4444,7 @@ removeContacts user_ids:vector<int32> = Ok;
//@description Returns the total number of imported contacts
getImportedContactCount = Count;
//@description Changes imported contacts using the list of current user contacts saved on the device. Imports newly added contacts and, if at least the file database is enabled, deletes recently deleted contacts.
//@description Changes imported contacts using the list of contacts saved on the device. Imports newly added contacts and, if at least the file database is enabled, deletes recently deleted contacts.
//-Query result depends on the result of the previous query, so only one query is possible at the same time @contacts The new list of contacts, contact's vCard are ignored and are not imported
changeImportedContacts contacts:vector<contact> = ImportedContacts;
@ -4951,7 +4958,7 @@ setAlarm seconds:double = Ok;
//@description Returns information about existing countries. Can be called before authorization
getCountries = Countries;
//@description Uses current user IP address to find their country. Returns two-letter ISO 3166-1 alpha-2 country code. Can be called before authorization
//@description Uses the current IP address to find the current country. Returns two-letter ISO 3166-1 alpha-2 country code. Can be called before authorization
getCountryCode = Text;
//@description Returns information about a phone number by its prefix. Can be called before authorization @phone_number_prefix The phone number prefix

View File

@ -50,7 +50,7 @@ inputMediaPhoto#b3ba0635 flags:# id:InputPhoto ttl_seconds:flags.0?int = InputMe
inputMediaGeoPoint#f9c44144 geo_point:InputGeoPoint = InputMedia;
inputMediaContact#f8ab7dfb phone_number:string first_name:string last_name:string vcard:string = InputMedia;
inputMediaUploadedDocument#5b38c6c1 flags:# nosound_video:flags.3?true force_file:flags.4?true file:InputFile thumb:flags.2?InputFile mime_type:string attributes:Vector<DocumentAttribute> stickers:flags.0?Vector<InputDocument> ttl_seconds:flags.1?int = InputMedia;
inputMediaDocument#23ab23d2 flags:# id:InputDocument ttl_seconds:flags.0?int = InputMedia;
inputMediaDocument#33473058 flags:# id:InputDocument ttl_seconds:flags.0?int query:flags.1?string = InputMedia;
inputMediaVenue#c13d1c11 geo_point:InputGeoPoint title:string address:string provider:string venue_id:string venue_type:string = InputMedia;
inputMediaPhotoExternal#e5bbfe1a flags:# url:string ttl_seconds:flags.0?int = InputMedia;
inputMediaDocumentExternal#fb52dc99 flags:# url:string ttl_seconds:flags.0?int = InputMedia;
@ -1182,7 +1182,7 @@ groupCall#55903081 flags:# join_muted:flags.1?true can_change_join_muted:flags.2
inputGroupCall#d8aa840f id:long access_hash:long = InputGroupCall;
groupCallParticipant#56b087c9 flags:# muted:flags.0?true left:flags.1?true can_self_unmute:flags.2?true just_joined:flags.4?true user_id:int date:int active_date:flags.3?int source:int = GroupCallParticipant;
groupCallParticipant#56b087c9 flags:# muted:flags.0?true left:flags.1?true can_self_unmute:flags.2?true just_joined:flags.4?true versioned:flags.5?true user_id:int date:int active_date:flags.3?int source:int = GroupCallParticipant;
phone.groupCall#66ab0bfc call:GroupCall participants:Vector<GroupCallParticipant> participants_next_offset:string users:Vector<User> = phone.GroupCall;

View File

@ -94,6 +94,20 @@ std::string TD_TL_writer_h::gen_output_begin() const {
" }\n"
"\n"
" return to_string(*value);\n"
"}\n\n"
"template <class T>\n"
"std::string to_string(const std::vector<object_ptr<T>> &values) {\n"
" std::string result = \"{\\n\";\n"
" for (const auto &value : values) {\n"
" if (value == nullptr) {\n"
" result += \"null\\n\";\n"
" } else {\n"
" result += to_string(*value);\n"
" }\n"
" }\n"
" result += \"}\\n\";\n"
" return result;\n"
"}\n\n";
}

View File

@ -359,7 +359,8 @@ tl_object_ptr<telegram_api::InputMedia> AnimationsManager::get_input_media(
return nullptr;
}
if (file_view.has_remote_location() && !file_view.main_remote_location().is_web() && input_file == nullptr) {
return make_tl_object<telegram_api::inputMediaDocument>(0, file_view.main_remote_location().as_input_document(), 0);
return make_tl_object<telegram_api::inputMediaDocument>(0, file_view.main_remote_location().as_input_document(), 0,
string());
}
if (file_view.has_url()) {
return make_tl_object<telegram_api::inputMediaDocumentExternal>(0, file_view.url(), 0);

View File

@ -239,7 +239,8 @@ tl_object_ptr<telegram_api::InputMedia> AudiosManager::get_input_media(
return nullptr;
}
if (file_view.has_remote_location() && !file_view.main_remote_location().is_web() && input_file == nullptr) {
return make_tl_object<telegram_api::inputMediaDocument>(0, file_view.main_remote_location().as_input_document(), 0);
return make_tl_object<telegram_api::inputMediaDocument>(0, file_view.main_remote_location().as_input_document(), 0,
string());
}
if (file_view.has_url()) {
return make_tl_object<telegram_api::inputMediaDocumentExternal>(0, file_view.url(), 0);

View File

@ -310,7 +310,7 @@ void CallActor::on_set_rating_query_result(NetQueryPtr net_query) {
return on_error(res.move_as_error());
}
call_state_.need_rating = false;
send_closure(G()->updates_manager(), &UpdatesManager::on_get_updates, res.move_as_ok());
send_closure(G()->updates_manager(), &UpdatesManager::on_get_updates, res.move_as_ok(), Promise<Unit>());
}
void CallActor::send_call_debug_information(string data, Promise<> promise) {
@ -730,7 +730,7 @@ void CallActor::on_discard_query_result(NetQueryPtr net_query) {
if (res.is_error()) {
return on_error(res.move_as_error());
}
send_closure(G()->updates_manager(), &UpdatesManager::on_get_updates, res.move_as_ok());
send_closure(G()->updates_manager(), &UpdatesManager::on_get_updates, res.move_as_ok(), Promise<Unit>());
}
void CallActor::flush_call_state() {

View File

@ -424,9 +424,7 @@ class AddContactQuery : public Td::ResultHandler {
auto ptr = result_ptr.move_as_ok();
LOG(INFO) << "Receive result for AddContactQuery: " << to_string(ptr);
td->updates_manager_->on_get_updates(std::move(ptr));
promise_.set_value(Unit());
td->updates_manager_->on_get_updates(std::move(ptr), std::move(promise_));
}
void on_error(uint64 id, Status status) override {
@ -457,9 +455,7 @@ class AcceptContactQuery : public Td::ResultHandler {
auto ptr = result_ptr.move_as_ok();
LOG(INFO) << "Receive result for AcceptContactQuery: " << to_string(ptr);
td->updates_manager_->on_get_updates(std::move(ptr));
promise_.set_value(Unit());
td->updates_manager_->on_get_updates(std::move(ptr), std::move(promise_));
}
void on_error(uint64 id, Status status) override {
@ -591,9 +587,7 @@ class DeleteContactsQuery : public Td::ResultHandler {
auto ptr = result_ptr.move_as_ok();
LOG(INFO) << "Receive result for DeleteContactsQuery: " << to_string(ptr);
td->updates_manager_->on_get_updates(std::move(ptr));
promise_.set_value(Unit());
td->updates_manager_->on_get_updates(std::move(ptr), std::move(promise_));
}
void on_error(uint64 id, Status status) override {
@ -1140,9 +1134,7 @@ class ToggleChannelSignaturesQuery : public Td::ResultHandler {
auto ptr = result_ptr.move_as_ok();
LOG(INFO) << "Receive result for ToggleChannelSignaturesQuery: " << to_string(ptr);
td->updates_manager_->on_get_updates(std::move(ptr));
promise_.set_value(Unit());
td->updates_manager_->on_get_updates(std::move(ptr), std::move(promise_));
}
void on_error(uint64 id, Status status) override {
@ -1185,10 +1177,17 @@ class ToggleChannelIsAllHistoryAvailableQuery : public Td::ResultHandler {
auto ptr = result_ptr.move_as_ok();
LOG(INFO) << "Receive result for TogglePreHistoryHiddenQuery: " << to_string(ptr);
td->updates_manager_->on_get_updates(std::move(ptr));
td->contacts_manager_->on_update_channel_is_all_history_available(channel_id_, is_all_history_available_);
promise_.set_value(Unit());
td->updates_manager_->on_get_updates(
std::move(ptr),
PromiseCreator::lambda([promise = std::move(promise_), channel_id = channel_id_,
is_all_history_available = is_all_history_available_](Unit result) mutable {
if (G()->close_flag()) {
return promise.set_error(Status::Error(500, "Request aborted"));
}
send_closure(G()->contacts_manager(), &ContactsManager::on_update_channel_is_all_history_available,
channel_id, is_all_history_available, std::move(promise));
}));
}
void on_error(uint64 id, Status status) override {
@ -1372,15 +1371,21 @@ class ToggleSlowModeQuery : public Td::ResultHandler {
auto ptr = result_ptr.move_as_ok();
LOG(INFO) << "Receive result for ToggleSlowModeQuery: " << to_string(ptr);
td->updates_manager_->on_get_updates(std::move(ptr));
td->contacts_manager_->on_update_channel_slow_mode_delay(channel_id_, slow_mode_delay_);
promise_.set_value(Unit());
td->updates_manager_->on_get_updates(
std::move(ptr), PromiseCreator::lambda([promise = std::move(promise_), channel_id = channel_id_,
slow_mode_delay = slow_mode_delay_](Unit result) mutable {
if (G()->close_flag()) {
return promise.set_error(Status::Error(500, "Request aborted"));
}
send_closure(G()->contacts_manager(), &ContactsManager::on_update_channel_slow_mode_delay, channel_id,
slow_mode_delay, std::move(promise));
}));
}
void on_error(uint64 id, Status status) override {
if (status.message() == "CHAT_NOT_MODIFIED") {
td->contacts_manager_->on_update_channel_slow_mode_delay(channel_id_, slow_mode_delay_);
td->contacts_manager_->on_update_channel_slow_mode_delay(channel_id_, slow_mode_delay_, Promise<Unit>());
if (!td->auth_manager_->is_bot()) {
promise_.set_value(Unit());
return;
@ -1456,9 +1461,7 @@ class DeleteChannelQuery : public Td::ResultHandler {
auto ptr = result_ptr.move_as_ok();
LOG(INFO) << "Receive result for DeleteChannelQuery: " << to_string(ptr);
td->updates_manager_->on_get_updates(std::move(ptr));
promise_.set_value(Unit());
td->updates_manager_->on_get_updates(std::move(ptr), std::move(promise_));
}
void on_error(uint64 id, Status status) override {
@ -1487,9 +1490,7 @@ class AddChatUserQuery : public Td::ResultHandler {
auto ptr = result_ptr.move_as_ok();
LOG(INFO) << "Receive result for AddChatUserQuery: " << to_string(ptr);
td->updates_manager_->on_get_updates(std::move(ptr));
promise_.set_value(Unit());
td->updates_manager_->on_get_updates(std::move(ptr), std::move(promise_));
}
void on_error(uint64 id, Status status) override {
@ -1667,10 +1668,13 @@ class ImportDialogInviteLinkQuery : public Td::ResultHandler {
LOG(ERROR) << "Receive wrong result for ImportDialogInviteLinkQuery: " << to_string(ptr);
return on_error(id, Status::Error(500, "Internal Server Error"));
}
auto dialog_id = dialog_ids[0];
td->updates_manager_->on_get_updates(std::move(ptr));
td->contacts_manager_->invalidate_invite_link_info(invite_link_);
promise_.set_value(std::move(dialog_ids[0]));
td->updates_manager_->on_get_updates(
std::move(ptr), PromiseCreator::lambda([promise = std::move(promise_), dialog_id](Unit) mutable {
promise.set_value(std::move(dialog_id));
}));
}
void on_error(uint64 id, Status status) override {
@ -1699,9 +1703,7 @@ class DeleteChatUserQuery : public Td::ResultHandler {
auto ptr = result_ptr.move_as_ok();
LOG(INFO) << "Receive result for DeleteChatUserQuery: " << to_string(ptr);
td->updates_manager_->on_get_updates(std::move(ptr));
promise_.set_value(Unit());
td->updates_manager_->on_get_updates(std::move(ptr), std::move(promise_));
}
void on_error(uint64 id, Status status) override {
@ -1733,9 +1735,7 @@ class JoinChannelQuery : public Td::ResultHandler {
auto ptr = result_ptr.move_as_ok();
LOG(INFO) << "Receive result for JoinChannelQuery: " << to_string(ptr);
td->updates_manager_->on_get_updates(std::move(ptr));
promise_.set_value(Unit());
td->updates_manager_->on_get_updates(std::move(ptr), std::move(promise_));
}
void on_error(uint64 id, Status status) override {
@ -1769,10 +1769,8 @@ class InviteToChannelQuery : public Td::ResultHandler {
auto ptr = result_ptr.move_as_ok();
LOG(INFO) << "Receive result for InviteToChannelQuery: " << to_string(ptr);
td->updates_manager_->on_get_updates(std::move(ptr));
td->contacts_manager_->invalidate_channel_full(channel_id_, false, false);
promise_.set_value(Unit());
td->updates_manager_->on_get_updates(std::move(ptr), std::move(promise_));
}
void on_error(uint64 id, Status status) override {
@ -1806,10 +1804,8 @@ class EditChannelAdminQuery : public Td::ResultHandler {
auto ptr = result_ptr.move_as_ok();
LOG(INFO) << "Receive result for EditChannelAdminQuery: " << to_string(ptr);
td->updates_manager_->on_get_updates(std::move(ptr));
td->contacts_manager_->invalidate_channel_full(channel_id_, false, false);
promise_.set_value(Unit());
td->updates_manager_->on_get_updates(std::move(ptr), std::move(promise_));
}
void on_error(uint64 id, Status status) override {
@ -1843,10 +1839,8 @@ class EditChannelBannedQuery : public Td::ResultHandler {
auto ptr = result_ptr.move_as_ok();
LOG(INFO) << "Receive result for EditChannelBannedQuery: " << to_string(ptr);
td->updates_manager_->on_get_updates(std::move(ptr));
td->contacts_manager_->invalidate_channel_full(channel_id_, false, false);
promise_.set_value(Unit());
td->updates_manager_->on_get_updates(std::move(ptr), std::move(promise_));
}
void on_error(uint64 id, Status status) override {
@ -1879,9 +1873,7 @@ class LeaveChannelQuery : public Td::ResultHandler {
auto ptr = result_ptr.move_as_ok();
LOG(INFO) << "Receive result for LeaveChannelQuery: " << to_string(ptr);
td->updates_manager_->on_get_updates(std::move(ptr));
promise_.set_value(Unit());
td->updates_manager_->on_get_updates(std::move(ptr), std::move(promise_));
}
void on_error(uint64 id, Status status) override {
@ -1953,10 +1945,8 @@ class EditChannelCreatorQuery : public Td::ResultHandler {
auto ptr = result_ptr.move_as_ok();
LOG(INFO) << "Receive result for EditChannelCreatorQuery: " << to_string(ptr);
td->updates_manager_->on_get_updates(std::move(ptr));
td->contacts_manager_->invalidate_channel_full(channel_id_, false, false);
promise_.set_value(Unit());
td->updates_manager_->on_get_updates(std::move(ptr), std::move(promise_));
}
void on_error(uint64 id, Status status) override {
@ -1985,9 +1975,7 @@ class MigrateChatQuery : public Td::ResultHandler {
auto ptr = result_ptr.move_as_ok();
LOG(INFO) << "Receive result for MigrateChatQuery: " << to_string(ptr);
td->updates_manager_->on_get_updates(std::move(ptr));
promise_.set_value(Unit());
td->updates_manager_->on_get_updates(std::move(ptr), std::move(promise_));
}
void on_error(uint64 id, Status status) override {
@ -11726,7 +11714,8 @@ void ContactsManager::on_update_chat_status(Chat *c, ChatId chat_id, DialogParti
}
}
if (need_reload_group_call) {
td_->messages_manager_->reload_dialog_group_call(DialogId(chat_id));
send_closure_later(G()->messages_manager(), &MessagesManager::on_update_dialog_group_call_rights,
DialogId(chat_id));
}
c->is_changed = true;
@ -12068,7 +12057,8 @@ void ContactsManager::on_channel_status_changed(Channel *c, ChannelId channel_id
reload_dialog_administrators(DialogId(channel_id), 0, Auto());
}
if (need_reload_group_call) {
td_->messages_manager_->reload_dialog_group_call(DialogId(channel_id));
send_closure_later(G()->messages_manager(), &MessagesManager::on_update_dialog_group_call_rights,
DialogId(channel_id));
}
}
@ -12170,12 +12160,17 @@ void ContactsManager::on_update_channel_location(ChannelId channel_id, const Dia
}
}
void ContactsManager::on_update_channel_slow_mode_delay(ChannelId channel_id, int32 slow_mode_delay) {
void ContactsManager::on_update_channel_slow_mode_delay(ChannelId channel_id, int32 slow_mode_delay,
Promise<Unit> &&promise) {
if (G()->close_flag()) {
return promise.set_error(Status::Error(500, "Request aborted"));
}
auto channel_full = get_channel_full_force(channel_id, "on_update_channel_slow_mode_delay");
if (channel_full != nullptr) {
on_update_channel_full_slow_mode_delay(channel_full, channel_id, slow_mode_delay, 0);
update_channel_full(channel_full, channel_id);
}
promise.set_value(Unit());
}
void ContactsManager::on_update_channel_slow_mode_next_send_date(ChannelId channel_id, int32 slow_mode_next_send_date) {
@ -12212,17 +12207,19 @@ void ContactsManager::on_update_channel_full_bot_user_ids(ChannelFull *channel_f
}
}
void ContactsManager::on_update_channel_is_all_history_available(ChannelId channel_id, bool is_all_history_available) {
void ContactsManager::on_update_channel_is_all_history_available(ChannelId channel_id, bool is_all_history_available,
Promise<Unit> &&promise) {
if (G()->close_flag()) {
return promise.set_error(Status::Error(500, "Request aborted"));
}
CHECK(channel_id.is_valid());
auto channel_full = get_channel_full_force(channel_id, "on_update_channel_is_all_history_available");
if (channel_full == nullptr) {
return;
}
if (channel_full->is_all_history_available != is_all_history_available) {
if (channel_full != nullptr && channel_full->is_all_history_available != is_all_history_available) {
channel_full->is_all_history_available = is_all_history_available;
channel_full->is_changed = true;
update_channel_full(channel_full, channel_id);
}
promise.set_value(Unit());
}
void ContactsManager::on_update_channel_default_permissions(ChannelId channel_id,
@ -13515,7 +13512,8 @@ DialogParticipant ContactsManager::get_channel_participant(ChannelId channel_id,
std::pair<int32, vector<DialogParticipant>> ContactsManager::get_channel_participants(
ChannelId channel_id, const tl_object_ptr<td_api::SupergroupMembersFilter> &filter, const string &additional_query,
int32 offset, int32 limit, int32 additional_limit, int64 &random_id, bool force, Promise<Unit> &&promise) {
int32 offset, int32 limit, int32 additional_limit, int64 &random_id, bool without_bot_info, bool force,
Promise<Unit> &&promise) {
if (random_id != 0) {
// request has already been sent before
auto it = received_channel_participants_.find(random_id);
@ -13560,7 +13558,10 @@ std::pair<int32, vector<DialogParticipant>> ContactsManager::get_channel_partici
}
auto channel_full = get_channel_full_force(channel_id, "get_channel_participants");
if (channel_full == nullptr || (!force && channel_full->is_expired())) {
if (td_->auth_manager_->is_bot()) {
without_bot_info = true;
}
if (!without_bot_info && (channel_full == nullptr || (!force && channel_full->is_expired()))) {
if (force) {
LOG(ERROR) << "Can't find cached ChannelFull";
} else {

View File

@ -200,9 +200,10 @@ class ContactsManager : public Actor {
void on_update_channel_sticker_set(ChannelId channel_id, StickerSetId sticker_set_id);
void on_update_channel_linked_channel_id(ChannelId channel_id, ChannelId group_channel_id);
void on_update_channel_location(ChannelId channel_id, const DialogLocation &location);
void on_update_channel_slow_mode_delay(ChannelId channel_id, int32 slow_mode_delay);
void on_update_channel_slow_mode_delay(ChannelId channel_id, int32 slow_mode_delay, Promise<Unit> &&promise);
void on_update_channel_slow_mode_next_send_date(ChannelId channel_id, int32 slow_mode_next_send_date);
void on_update_channel_is_all_history_available(ChannelId channel_id, bool is_all_history_available);
void on_update_channel_is_all_history_available(ChannelId channel_id, bool is_all_history_available,
Promise<Unit> &&promise);
void on_update_channel_default_permissions(ChannelId channel_id, RestrictedRights default_permissions);
void on_update_channel_administrator_count(ChannelId channel_id, int32 administrator_count);
void on_update_channel_participant(ChannelId channel_id, UserId user_id, int32 date,
@ -513,8 +514,8 @@ class ContactsManager : public Actor {
std::pair<int32, vector<DialogParticipant>> get_channel_participants(
ChannelId channel_id, const tl_object_ptr<td_api::SupergroupMembersFilter> &filter,
const string &additional_query, int32 offset, int32 limit, int32 additional_limit, int64 &random_id, bool force,
Promise<Unit> &&promise);
const string &additional_query, int32 offset, int32 limit, int32 additional_limit, int64 &random_id,
bool without_bot_info, bool force, Promise<Unit> &&promise);
void send_get_channel_participants_query(ChannelId channel_id, ChannelParticipantsFilter filter, int32 offset,
int32 limit, int64 random_id, Promise<Unit> &&promise);

View File

@ -590,7 +590,8 @@ tl_object_ptr<telegram_api::InputMedia> DocumentsManager::get_input_media(
return nullptr;
}
if (file_view.has_remote_location() && !file_view.main_remote_location().is_web() && input_file == nullptr) {
return make_tl_object<telegram_api::inputMediaDocument>(0, file_view.main_remote_location().as_input_document(), 0);
return make_tl_object<telegram_api::inputMediaDocument>(0, file_view.main_remote_location().as_input_document(), 0,
string());
}
if (file_view.has_url()) {
return make_tl_object<telegram_api::inputMediaDocumentExternal>(0, file_view.url(), 0);

View File

@ -8,6 +8,7 @@
#include "td/telegram/AuthManager.h"
#include "td/telegram/ContactsManager.h"
#include "td/telegram/DialogParticipant.h"
#include "td/telegram/Global.h"
#include "td/telegram/MessagesManager.h"
#include "td/telegram/misc.h"
@ -15,9 +16,12 @@
#include "td/telegram/Td.h"
#include "td/telegram/UpdatesManager.h"
#include "td/actor/MultiPromise.h"
#include "td/utils/JsonBuilder.h"
#include "td/utils/Random.h"
#include <unordered_set>
#include <utility>
namespace td {
@ -54,11 +58,12 @@ class CreateGroupCallQuery : public Td::ResultHandler {
LOG(ERROR) << "Receive wrong CreateGroupCallQuery response " << to_string(ptr);
return on_error(id, Status::Error(500, "Receive wrong response"));
}
auto group_call_id = group_call_ids[0];
td->updates_manager_->on_get_updates(std::move(ptr));
// TODO set promise after updates are processed
promise_.set_value(std::move(group_call_ids[0]));
td->updates_manager_->on_get_updates(
std::move(ptr), PromiseCreator::lambda([promise = std::move(promise_), group_call_id](Unit) mutable {
promise.set_value(std::move(group_call_id));
}));
}
void on_error(uint64 id, Status status) override {
@ -222,10 +227,7 @@ class ToggleGroupCallSettingsQuery : public Td::ResultHandler {
auto ptr = result_ptr.move_as_ok();
LOG(INFO) << "Receive result for ToggleGroupCallSettingsQuery: " << to_string(ptr);
td->updates_manager_->on_get_updates(std::move(ptr));
// TODO set promise after updates are processed
promise_.set_value(Unit());
td->updates_manager_->on_get_updates(std::move(ptr), std::move(promise_));
}
void on_error(uint64 id, Status status) override {
@ -253,10 +255,7 @@ class InviteToGroupCallQuery : public Td::ResultHandler {
auto ptr = result_ptr.move_as_ok();
LOG(INFO) << "Receive result for InviteToGroupCallQuery: " << to_string(ptr);
td->updates_manager_->on_get_updates(std::move(ptr));
// TODO set promise after updates are processed
promise_.set_value(Unit());
td->updates_manager_->on_get_updates(std::move(ptr), std::move(promise_));
}
void on_error(uint64 id, Status status) override {
@ -292,10 +291,7 @@ class EditGroupCallMemberQuery : public Td::ResultHandler {
auto ptr = result_ptr.move_as_ok();
LOG(INFO) << "Receive result for EditGroupCallMemberQuery: " << to_string(ptr);
td->updates_manager_->on_get_updates(std::move(ptr));
// TODO set promise after updates are processed
promise_.set_value(Unit());
td->updates_manager_->on_get_updates(std::move(ptr), std::move(promise_));
}
void on_error(uint64 id, Status status) override {
@ -356,10 +352,7 @@ class LeaveGroupCallQuery : public Td::ResultHandler {
auto ptr = result_ptr.move_as_ok();
LOG(INFO) << "Receive result for LeaveGroupCallQuery: " << to_string(ptr);
td->updates_manager_->on_get_updates(std::move(ptr));
// TODO set promise after updates are processed
promise_.set_value(Unit());
td->updates_manager_->on_get_updates(std::move(ptr), std::move(promise_));
}
void on_error(uint64 id, Status status) override {
@ -387,10 +380,7 @@ class DiscardGroupCallQuery : public Td::ResultHandler {
auto ptr = result_ptr.move_as_ok();
LOG(INFO) << "Receive result for DiscardGroupCallQuery: " << to_string(ptr);
td->updates_manager_->on_get_updates(std::move(ptr));
// TODO set promise after updates are processed
promise_.set_value(Unit());
td->updates_manager_->on_get_updates(std::move(ptr), std::move(promise_));
}
void on_error(uint64 id, Status status) override {
@ -404,8 +394,11 @@ struct GroupCallManager::GroupCall {
bool is_inited = false;
bool is_active = false;
bool is_joined = false;
bool need_rejoin = false;
bool is_being_left = false;
bool is_speaking = false;
bool can_self_unmute = false;
bool can_be_managed = false;
bool syncing_participants = false;
bool loaded_all_participants = false;
bool mute_new_participants = false;
@ -414,6 +407,7 @@ struct GroupCallManager::GroupCall {
int32 version = -1;
int32 duration = 0;
int32 source = 0;
int32 joined_date = 0;
};
struct GroupCallManager::GroupCallParticipants {
@ -421,7 +415,11 @@ struct GroupCallManager::GroupCallParticipants {
string next_offset;
int64 min_order = std::numeric_limits<int64>::max();
std::map<int32, vector<tl_object_ptr<telegram_api::groupCallParticipant>>> pending_updates_;
bool are_administrators_loaded = false;
vector<UserId> administrator_user_ids;
std::map<int32, vector<tl_object_ptr<telegram_api::groupCallParticipant>>> pending_version_updates_;
std::map<int32, vector<tl_object_ptr<telegram_api::groupCallParticipant>>> pending_mute_updates_;
};
struct GroupCallManager::GroupCallRecentSpeakers {
@ -592,7 +590,7 @@ GroupCallManager::GroupCall *GroupCallManager::get_group_call(InputGroupCallId i
}
}
Status GroupCallManager::can_manage_group_calls(DialogId dialog_id) {
Status GroupCallManager::can_manage_group_calls(DialogId dialog_id) const {
switch (dialog_id.get_type()) {
case DialogType::Chat: {
auto chat_id = dialog_id.get_chat_id();
@ -632,6 +630,14 @@ Status GroupCallManager::can_manage_group_calls(DialogId dialog_id) {
return Status::OK();
}
bool GroupCallManager::can_manage_group_call(InputGroupCallId input_group_call_id) const {
auto group_call = get_group_call(input_group_call_id);
if (group_call == nullptr) {
return false;
}
return can_manage_group_calls(group_call->dialog_id).is_ok();
}
void GroupCallManager::create_voice_chat(DialogId dialog_id, Promise<GroupCallId> &&promise) {
if (!dialog_id.is_valid()) {
return promise.set_error(Status::Error(400, "Invalid chat identifier specified"));
@ -684,6 +690,33 @@ void GroupCallManager::get_group_call(GroupCallId group_call_id,
reload_group_call(input_group_call_id, std::move(promise));
}
void GroupCallManager::on_update_group_call_rights(InputGroupCallId input_group_call_id) {
auto group_call = get_group_call(input_group_call_id);
if (need_group_call_participants(input_group_call_id)) {
CHECK(group_call != nullptr && group_call->is_inited);
try_load_group_call_administrators(input_group_call_id, group_call->dialog_id);
auto participants_it = group_call_participants_.find(input_group_call_id);
if (participants_it != group_call_participants_.end()) {
CHECK(participants_it->second != nullptr);
if (participants_it->second->are_administrators_loaded) {
update_group_call_participants_can_be_muted(
input_group_call_id, can_manage_group_calls(group_call->dialog_id).is_ok(), participants_it->second.get());
}
}
}
if (group_call != nullptr && group_call->is_inited) {
bool can_be_managed = group_call->is_active && can_manage_group_calls(group_call->dialog_id).is_ok();
if (can_be_managed != group_call->can_be_managed) {
group_call->can_be_managed = can_be_managed;
send_update_group_call(group_call, "on_update_group_call_rights");
}
}
reload_group_call(input_group_call_id, Auto());
}
void GroupCallManager::reload_group_call(InputGroupCallId input_group_call_id,
Promise<td_api::object_ptr<td_api::groupCall>> &&promise) {
auto &queries = load_group_call_queries_[input_group_call_id];
@ -734,6 +767,7 @@ void GroupCallManager::finish_get_group_call(InputGroupCallId input_group_call_i
}
auto group_call = get_group_call(input_group_call_id);
CHECK(group_call != nullptr && group_call->is_inited);
for (auto &promise : promises) {
if (promise) {
promise.set_value(get_group_call_object(group_call, get_recent_speaker_user_ids(group_call, false)));
@ -770,6 +804,7 @@ void GroupCallManager::on_get_group_call_participants(
bool is_sync = is_load && offset.empty();
if (is_sync) {
auto group_call = get_group_call(input_group_call_id);
CHECK(group_call != nullptr && group_call->is_inited);
is_sync = group_call->syncing_participants;
if (is_sync) {
group_call->syncing_participants = false;
@ -837,6 +872,9 @@ void GroupCallManager::on_get_group_call_participants(
group_call->loaded_all_participants = false;
need_update = true;
}
if (process_pending_group_call_participant_updates(input_group_call_id)) {
need_update = false;
}
if (need_update) {
send_update_group_call(group_call, "on_get_group_call_participants");
}
@ -844,6 +882,17 @@ void GroupCallManager::on_get_group_call_participants(
}
}
GroupCallManager::GroupCallParticipants *GroupCallManager::add_group_call_participants(
InputGroupCallId input_group_call_id) {
CHECK(need_group_call_participants(input_group_call_id));
auto &participants = group_call_participants_[input_group_call_id];
if (participants == nullptr) {
participants = make_unique<GroupCallParticipants>();
}
return participants.get();
}
void GroupCallManager::on_update_group_call_participants(
InputGroupCallId input_group_call_id, vector<tl_object_ptr<telegram_api::groupCallParticipant>> &&participants,
int32 version) {
@ -856,7 +905,7 @@ void GroupCallManager::on_update_group_call_participants(
if (participant.user_id == td_->contacts_manager_->get_my_id() && group_call != nullptr &&
group_call->is_inited && group_call->is_joined &&
(participant.joined_date == 0) == (participant.source == group_call->source)) {
on_group_call_left_impl(group_call);
on_group_call_left_impl(group_call, participant.joined_date == 0);
need_update = true;
}
if (participant.joined_date == 0) {
@ -875,7 +924,7 @@ void GroupCallManager::on_update_group_call_participants(
group_call->participant_count += diff;
if (group_call->participant_count < 0) {
LOG(ERROR) << "Participant count became negative in " << input_group_call_id << " from "
<< group_call->dialog_id;
<< group_call->dialog_id << " after applying " << to_string(participants);
group_call->participant_count = 0;
}
update_group_call_dialog(group_call, "on_update_group_call_participants");
@ -886,7 +935,7 @@ void GroupCallManager::on_update_group_call_participants(
send_update_group_call(group_call, "on_update_group_call_participants");
}
LOG(INFO) << "Ignore updateGroupCallParticipants in " << input_group_call_id << " from " << group_call->dialog_id;
LOG(INFO) << "Ignore updateGroupCallParticipants in " << input_group_call_id;
return;
}
if (version <= 0) {
@ -899,18 +948,25 @@ void GroupCallManager::on_update_group_call_participants(
return;
}
auto &group_call_participants = group_call_participants_[input_group_call_id];
if (group_call_participants == nullptr) {
group_call_participants = make_unique<GroupCallParticipants>();
auto *group_call_participants = add_group_call_participants(input_group_call_id);
auto &pending_mute_updates = group_call_participants->pending_mute_updates_[version];
vector<tl_object_ptr<telegram_api::groupCallParticipant>> version_updates;
for (auto &participant : participants) {
if (GroupCallParticipant::is_versioned_update(participant)) {
version_updates.push_back(std::move(participant));
} else {
pending_mute_updates.push_back(std::move(participant));
}
}
auto &pending_updates = group_call_participants->pending_updates_[version];
if (!pending_updates.empty()) {
LOG(INFO) << "Receive duplicate updateGroupCallParticipants with version " << version << " in "
<< input_group_call_id;
sync_group_call_participants(input_group_call_id);
return;
if (!version_updates.empty()) {
auto &pending_version_updates = group_call_participants->pending_version_updates_[version];
if (version_updates.size() <= pending_version_updates.size()) {
LOG(INFO) << "Receive duplicate updateGroupCallParticipants with version " << version << " in "
<< input_group_call_id;
return;
}
pending_version_updates = std::move(version_updates);
}
pending_updates = std::move(participants);
process_pending_group_call_participant_updates(input_group_call_id);
}
@ -924,7 +980,6 @@ bool GroupCallManager::process_pending_group_call_participant_updates(InputGroup
if (participants_it == group_call_participants_.end()) {
return false;
}
auto &pending_updates = participants_it->second->pending_updates_;
auto group_call = get_group_call(input_group_call_id);
CHECK(group_call != nullptr && group_call->is_inited);
if (group_call->version == -1 || !group_call->is_active) {
@ -933,41 +988,41 @@ bool GroupCallManager::process_pending_group_call_participant_updates(InputGroup
int32 diff = 0;
bool is_left = false;
while (!pending_updates.empty()) {
auto it = pending_updates.begin();
bool need_rejoin = true;
auto &pending_version_updates = participants_it->second->pending_version_updates_;
while (!pending_version_updates.empty()) {
auto it = pending_version_updates.begin();
auto version = it->first;
auto &participants = it->second;
if (version <= group_call->version) {
for (auto &group_call_participant : participants) {
GroupCallParticipant participant(group_call_participant);
if (participant.user_id == td_->contacts_manager_->get_my_id()) {
on_participant_speaking_in_group_call(input_group_call_id, participant);
if (participant.user_id == td_->contacts_manager_->get_my_id() && version == group_call->version &&
participant.is_just_joined) {
process_group_call_participant(input_group_call_id, std::move(participant));
}
on_participant_speaking_in_group_call(input_group_call_id, participant);
}
LOG(INFO) << "Ignore already applied updateGroupCallParticipants with version " << version << " in "
<< input_group_call_id << " from " << group_call->dialog_id;
pending_updates.erase(it);
pending_version_updates.erase(it);
continue;
}
if (version < group_call->version + static_cast<int32>(participants.size())) {
LOG(INFO) << "Receive " << participants.size() << " group call participant updates with version " << version
<< ", but current version is " << group_call->version;
sync_group_call_participants(input_group_call_id);
break;
}
if (version == group_call->version + static_cast<int32>(participants.size())) {
if (version == group_call->version + 1) {
group_call->version = version;
for (auto &participant : participants) {
GroupCallParticipant group_call_participant(participant);
if (group_call_participant.user_id == td_->contacts_manager_->get_my_id() && group_call->is_joined &&
(group_call_participant.joined_date == 0) == (group_call_participant.source == group_call->source)) {
is_left = true;
if (group_call_participant.joined_date != 0) {
need_rejoin = false;
}
}
diff += process_group_call_participant(input_group_call_id, std::move(group_call_participant));
}
pending_updates.erase(it);
pending_version_updates.erase(it);
} else if (!group_call->syncing_participants) {
// found a gap
LOG(INFO) << "Receive " << participants.size() << " group call participant updates with version " << version
@ -976,7 +1031,27 @@ bool GroupCallManager::process_pending_group_call_participant_updates(InputGroup
break;
}
}
if (pending_updates.empty()) {
auto &pending_mute_updates = participants_it->second->pending_mute_updates_;
while (!pending_mute_updates.empty()) {
auto it = pending_mute_updates.begin();
auto version = it->first;
if (version <= group_call->version) {
auto &participants = it->second;
for (auto &group_call_participant : participants) {
GroupCallParticipant participant(group_call_participant);
on_participant_speaking_in_group_call(input_group_call_id, participant);
int mute_diff = process_group_call_participant(input_group_call_id, std::move(participant));
CHECK(mute_diff == 0);
}
pending_mute_updates.erase(it);
continue;
}
on_receive_group_call_version(input_group_call_id, version);
break;
}
if (pending_version_updates.empty() && pending_mute_updates.empty()) {
sync_participants_timeout_.cancel_timeout(group_call->group_call_id.get());
}
@ -991,7 +1066,7 @@ bool GroupCallManager::process_pending_group_call_participant_updates(InputGroup
update_group_call_dialog(group_call, "process_pending_group_call_participant_updates");
}
if (is_left && group_call->is_joined) {
on_group_call_left_impl(group_call);
on_group_call_left_impl(group_call, need_rejoin);
need_update = true;
}
if (need_update) {
@ -1133,6 +1208,26 @@ void GroupCallManager::process_group_call_participants(
}
}
bool GroupCallManager::update_group_call_participant_can_be_muted(bool can_manage,
const GroupCallParticipants *participants,
GroupCallParticipant &participant) {
bool is_self = participant.user_id == td_->contacts_manager_->get_my_id();
bool is_admin = td::contains(participants->administrator_user_ids, participant.user_id);
return participant.update_can_be_muted(can_manage, is_self, is_admin);
}
void GroupCallManager::update_group_call_participants_can_be_muted(InputGroupCallId input_group_call_id,
bool can_manage,
GroupCallParticipants *participants) {
CHECK(participants != nullptr);
LOG(INFO) << "Update group call participants can_be_muted in " << input_group_call_id;
for (auto &participant : participants->participants) {
if (update_group_call_participant_can_be_muted(can_manage, participants, participant) && participant.order != 0) {
send_update_group_call_participant(input_group_call_id, participant);
}
}
}
int GroupCallManager::process_group_call_participant(InputGroupCallId input_group_call_id,
GroupCallParticipant &&participant) {
if (!participant.is_valid()) {
@ -1148,17 +1243,15 @@ int GroupCallManager::process_group_call_participant(InputGroupCallId input_grou
if (participant.user_id == td_->contacts_manager_->get_my_id()) {
auto *group_call = get_group_call(input_group_call_id);
CHECK(group_call != nullptr && group_call->is_inited);
if (group_call->is_joined && group_call->is_active && group_call->can_self_unmute != participant.can_self_unmute) {
if (group_call->is_joined && group_call->is_active && participant.source == group_call->source &&
participant.is_muted && group_call->can_self_unmute != participant.can_self_unmute) {
group_call->can_self_unmute = participant.can_self_unmute;
send_update_group_call(group_call, "process_group_call_participant");
}
}
auto &participants = group_call_participants_[input_group_call_id];
if (participants == nullptr) {
participants = make_unique<GroupCallParticipants>();
}
bool can_manage = can_manage_group_call(input_group_call_id);
auto *participants = add_group_call_participants(input_group_call_id);
for (size_t i = 0; i < participants->participants.size(); i++) {
auto &old_participant = participants->participants[i];
if (old_participant.user_id == participant.user_id) {
@ -1172,7 +1265,6 @@ int GroupCallManager::process_group_call_participant(InputGroupCallId input_grou
return -1;
}
LOG(INFO) << "Edit " << old_participant;
if (participant.joined_date < old_participant.joined_date) {
LOG(ERROR) << "Join date of " << participant.user_id << " in " << input_group_call_id << " decreased from "
<< old_participant.joined_date << " to " << participant.joined_date;
@ -1188,15 +1280,14 @@ int GroupCallManager::process_group_call_participant(InputGroupCallId input_grou
participant.order = real_order;
}
participant.is_just_joined = false;
update_group_call_participant_can_be_muted(can_manage, participants, participant);
if (old_participant != participant) {
bool need_update = old_participant.order != 0 || participant.order != 0;
old_participant = std::move(participant);
if (need_update) {
send_update_group_call_participant(input_group_call_id, old_participant);
}
on_participant_speaking_in_group_call(input_group_call_id, participant);
LOG(INFO) << "Edit " << old_participant << " to " << participant;
if (old_participant != participant && (old_participant.order != 0 || participant.order != 0)) {
send_update_group_call_participant(input_group_call_id, participant);
}
on_participant_speaking_in_group_call(input_group_call_id, participant);
old_participant = std::move(participant);
return 0;
}
}
@ -1218,6 +1309,7 @@ int GroupCallManager::process_group_call_participant(InputGroupCallId input_grou
participant.order = real_order;
}
participant.is_just_joined = false;
update_group_call_participant_can_be_muted(can_manage, participants, participant);
participants->participants.push_back(std::move(participant));
if (participants->participants.back().order != 0) {
send_update_group_call_participant(input_group_call_id, participants->participants.back());
@ -1241,6 +1333,11 @@ void GroupCallManager::join_group_call(GroupCallId group_call_id,
if (group_call->is_inited && !group_call->is_active) {
return promise.set_error(Status::Error(400, "Group call is finished"));
}
if (group_call->need_rejoin) {
group_call->need_rejoin = false;
send_update_group_call(group_call, "join_group_call");
}
group_call->is_being_left = false;
if (pending_join_requests_.count(input_group_call_id)) {
auto it = pending_join_requests_.find(input_group_call_id);
@ -1306,6 +1403,82 @@ void GroupCallManager::join_group_call(GroupCallId group_call_id,
});
request->query_ref = td_->create_handler<JoinGroupCallQuery>(std::move(query_promise))
->send(input_group_call_id, json_payload, is_muted, generation);
try_load_group_call_administrators(input_group_call_id, group_call->dialog_id);
}
void GroupCallManager::try_load_group_call_administrators(InputGroupCallId input_group_call_id, DialogId dialog_id) {
if (!dialog_id.is_valid() || !need_group_call_participants(input_group_call_id) ||
can_manage_group_calls(dialog_id).is_error()) {
LOG(INFO) << "Don't need to load administrators in " << input_group_call_id << " from " << dialog_id;
return;
}
unique_ptr<int64> random_id_ptr = td::make_unique<int64>();
auto random_id_raw = random_id_ptr.get();
auto promise = PromiseCreator::lambda(
[actor_id = actor_id(this), input_group_call_id, random_id = std::move(random_id_ptr)](Result<Unit> &&result) {
send_closure(actor_id, &GroupCallManager::finish_load_group_call_administrators, input_group_call_id,
*random_id, std::move(result));
});
td_->messages_manager_->search_dialog_participants(
dialog_id, string(), 100, DialogParticipantsFilter(DialogParticipantsFilter::Type::Administrators),
*random_id_raw, true, true, std::move(promise));
}
void GroupCallManager::finish_load_group_call_administrators(InputGroupCallId input_group_call_id, int64 random_id,
Result<Unit> &&result) {
if (G()->close_flag()) {
return;
}
auto *group_call = get_group_call(input_group_call_id);
CHECK(group_call != nullptr);
if (!group_call->dialog_id.is_valid() || !can_manage_group_calls(group_call->dialog_id).is_ok()) {
return;
}
vector<UserId> administrator_user_ids;
if (result.is_ok()) {
result = Status::Error(500, "Failed to receive result");
unique_ptr<bool> ignore_result = make_unique<bool>();
auto ignore_result_ptr = ignore_result.get();
auto promise = PromiseCreator::lambda([&result, ignore_result = std::move(ignore_result)](Result<Unit> new_result) {
if (!*ignore_result) {
result = std::move(new_result);
}
});
auto participants = td_->messages_manager_->search_dialog_participants(
group_call->dialog_id, string(), 100, DialogParticipantsFilter(DialogParticipantsFilter::Type::Administrators),
random_id, true, true, std::move(promise));
for (auto &administrator : participants.second) {
if (administrator.status.can_manage_calls() && administrator.user_id != td_->contacts_manager_->get_my_id()) {
administrator_user_ids.push_back(administrator.user_id);
}
}
*ignore_result_ptr = true;
}
if (result.is_error()) {
LOG(WARNING) << "Failed to get administrators of " << input_group_call_id << ": " << result.error();
return;
}
if (!need_group_call_participants(input_group_call_id)) {
return;
}
auto *group_call_participants = add_group_call_participants(input_group_call_id);
if (group_call_participants->administrator_user_ids == administrator_user_ids) {
return;
}
LOG(INFO) << "Set administrators of " << input_group_call_id << " to " << administrator_user_ids;
group_call_participants->are_administrators_loaded = true;
group_call_participants->administrator_user_ids = std::move(administrator_user_ids);
update_group_call_participants_can_be_muted(input_group_call_id, true, group_call_participants);
}
void GroupCallManager::process_join_group_call_response(InputGroupCallId input_group_call_id, uint64 generation,
@ -1318,9 +1491,10 @@ void GroupCallManager::process_join_group_call_response(InputGroupCallId input_g
}
LOG(INFO) << "Receive result for JoinGroupCallQuery: " << to_string(updates);
td_->updates_manager_->on_get_updates(std::move(updates));
promise.set_error(Status::Error(500, "Wrong join response received"));
td_->updates_manager_->on_get_updates(std::move(updates),
PromiseCreator::lambda([promise = std::move(promise)](Unit) mutable {
promise.set_error(Status::Error(500, "Wrong join response received"));
}));
}
Result<td_api::object_ptr<td_api::groupCallJoinResponse>> GroupCallManager::get_group_call_join_response_object(
@ -1403,6 +1577,9 @@ bool GroupCallManager::on_join_group_call_response(InputGroupCallId input_group_
auto group_call = get_group_call(input_group_call_id);
CHECK(group_call != nullptr);
group_call->is_joined = true;
group_call->need_rejoin = false;
group_call->is_being_left = false;
group_call->joined_date = G()->unix_time();
group_call->source = it->second->source;
it->second->promise.set_value(result.move_as_ok());
need_update = true;
@ -1470,6 +1647,9 @@ void GroupCallManager::set_group_call_participant_is_speaking(GroupCallId group_
if (group_call == nullptr || !group_call->is_inited || !group_call->is_active || !group_call->is_joined) {
return promise.set_value(Unit());
}
if (source == 0) {
source = group_call->source;
}
bool recursive = false;
if (date == 0) {
@ -1506,7 +1686,7 @@ void GroupCallManager::set_group_call_participant_is_speaking(GroupCallId group_
on_user_speaking_in_group_call(group_call_id, user_id, date, recursive);
}
if (group_call->source == source && !group_call->dialog_id.is_valid() && group_call->is_speaking != is_speaking) {
if (group_call->source == source && group_call->dialog_id.is_valid() && group_call->is_speaking != is_speaking) {
group_call->is_speaking = is_speaking;
if (is_speaking) {
pending_send_speaking_action_timeout_.add_timeout_in(group_call_id.get(), 0.0);
@ -1548,7 +1728,7 @@ void GroupCallManager::check_group_call_is_joined(GroupCallId group_call_id, Pro
if (group_call == nullptr || !group_call->is_inited) {
return promise.set_error(Status::Error(400, "GROUP_CALL_JOIN_MISSING"));
}
if (!group_call->is_active || !group_call->is_joined) {
if (!group_call->is_active || !group_call->is_joined || group_call->joined_date > G()->unix_time() - 8) {
return promise.set_value(Unit());
}
auto source = group_call->source;
@ -1556,7 +1736,7 @@ void GroupCallManager::check_group_call_is_joined(GroupCallId group_call_id, Pro
auto query_promise = PromiseCreator::lambda([actor_id = actor_id(this), input_group_call_id, source,
promise = std::move(promise)](Result<Unit> &&result) mutable {
if (result.is_error() && result.error().message() == "GROUP_CALL_JOIN_MISSING") {
send_closure(actor_id, &GroupCallManager::on_group_call_left, input_group_call_id, source);
send_closure(actor_id, &GroupCallManager::on_group_call_left, input_group_call_id, source, true);
result = Unit();
}
promise.set_result(std::move(result));
@ -1598,32 +1778,37 @@ void GroupCallManager::leave_group_call(GroupCallId group_call_id, Promise<Unit>
return promise.set_error(Status::Error(400, "GROUP_CALL_JOIN_MISSING"));
}
auto source = group_call->source;
group_call->is_being_left = true;
auto query_promise = PromiseCreator::lambda([actor_id = actor_id(this), input_group_call_id, source,
promise = std::move(promise)](Result<Unit> &&result) mutable {
if (result.is_ok()) {
// just in case
send_closure(actor_id, &GroupCallManager::on_group_call_left, input_group_call_id, source);
send_closure(actor_id, &GroupCallManager::on_group_call_left, input_group_call_id, source, false);
}
promise.set_result(std::move(result));
});
td_->create_handler<LeaveGroupCallQuery>(std::move(query_promise))->send(input_group_call_id, source);
}
void GroupCallManager::on_group_call_left(InputGroupCallId input_group_call_id, int32 source) {
void GroupCallManager::on_group_call_left(InputGroupCallId input_group_call_id, int32 source, bool need_rejoin) {
auto *group_call = get_group_call(input_group_call_id);
CHECK(group_call != nullptr && group_call->is_inited);
if (group_call->is_joined && group_call->source == source) {
on_group_call_left_impl(group_call);
on_group_call_left_impl(group_call, need_rejoin);
send_update_group_call(group_call, "on_group_call_left");
}
}
void GroupCallManager::on_group_call_left_impl(GroupCall *group_call) {
void GroupCallManager::on_group_call_left_impl(GroupCall *group_call, bool need_rejoin) {
CHECK(group_call != nullptr && group_call->is_inited && group_call->is_joined);
group_call->is_joined = false;
group_call->need_rejoin = need_rejoin && !group_call->is_being_left;
group_call->is_being_left = false;
group_call->is_speaking = false;
group_call->can_self_unmute = false;
group_call->can_be_managed = false;
group_call->joined_date = 0;
group_call->source = 0;
group_call->loaded_all_participants = false;
group_call->version = -1;
@ -1640,7 +1825,7 @@ void GroupCallManager::on_update_group_call(tl_object_ptr<telegram_api::GroupCal
LOG(ERROR) << "Receive " << to_string(group_call_ptr);
return;
}
if (!dialog_id.is_valid()) {
if (dialog_id != DialogId() && !dialog_id.is_valid()) {
LOG(ERROR) << "Receive " << to_string(group_call_ptr) << " in invalid " << dialog_id;
dialog_id = DialogId();
}
@ -1724,21 +1909,31 @@ InputGroupCallId GroupCallManager::update_group_call(const tl_object_ptr<telegra
auto *group_call = add_group_call(input_group_call_id, dialog_id);
call.group_call_id = group_call->group_call_id;
call.dialog_id = dialog_id.is_valid() ? dialog_id : group_call->dialog_id;
call.can_self_unmute =
call.is_active && (!call.mute_new_participants || can_manage_group_calls(call.dialog_id).is_ok());
call.can_be_managed = call.is_active && can_manage_group_calls(call.dialog_id).is_ok();
call.can_self_unmute = (call.is_active && !call.mute_new_participants) || call.can_be_managed;
if (!group_call->dialog_id.is_valid()) {
group_call->dialog_id = dialog_id;
}
LOG(INFO) << "Update " << call.group_call_id << " with " << group_call->participant_count
<< " participants and version " << group_call->version;
if (!group_call->is_inited) {
call.is_joined = group_call->is_joined;
call.need_rejoin = group_call->need_rejoin;
call.is_being_left = group_call->is_being_left;
call.is_speaking = group_call->is_speaking;
call.can_self_unmute = group_call->can_self_unmute;
call.syncing_participants = group_call->syncing_participants;
call.loaded_all_participants = group_call->loaded_all_participants;
call.source = group_call->source;
*group_call = std::move(call);
if (need_group_call_participants(input_group_call_id)) {
// init version
group_call->version = call.version;
if (process_pending_group_call_participant_updates(input_group_call_id)) {
need_update = false;
}
try_load_group_call_administrators(input_group_call_id, group_call->dialog_id);
} else {
group_call->version = -1;
}
@ -1759,6 +1954,10 @@ InputGroupCallId GroupCallManager::update_group_call(const tl_object_ptr<telegra
group_call->allowed_change_mute_new_participants = call.allowed_change_mute_new_participants;
need_update = true;
}
if (call.can_be_managed != group_call->can_be_managed) {
group_call->can_be_managed = call.can_be_managed;
need_update = true;
}
if (call.version > group_call->version) {
if (group_call->version != -1) {
// if we know group call version, then update participants only by corresponding updates
@ -1816,11 +2015,9 @@ void GroupCallManager::on_receive_group_call_version(InputGroupCallId input_grou
}
// found a gap
auto &group_call_participants = group_call_participants_[input_group_call_id];
if (group_call_participants == nullptr) {
group_call_participants = make_unique<GroupCallParticipants>();
}
group_call_participants->pending_updates_[version]; // reserve place for updates
LOG(INFO) << "Receive version " << version << " for group call " << input_group_call_id;
auto *group_call_participants = add_group_call_participants(input_group_call_id);
group_call_participants->pending_version_updates_[version]; // reserve place for updates
sync_participants_timeout_.add_timeout_in(group_call->group_call_id.get(), 1.0);
}
@ -1856,8 +2053,7 @@ void GroupCallManager::on_user_speaking_in_group_call(GroupCallId group_call_id,
if (!td_->contacts_manager_->have_user_force(user_id)) {
if (recursive) {
LOG(ERROR) << "Failed to find speaking " << user_id << " from " << input_group_call_id << " in "
<< group_call->dialog_id;
LOG(ERROR) << "Failed to find speaking " << user_id << " from " << input_group_call_id;
} else {
auto query_promise = PromiseCreator::lambda([actor_id = actor_id(this), group_call_id, user_id,
date](Result<Unit> &&result) {
@ -1871,8 +2067,7 @@ void GroupCallManager::on_user_speaking_in_group_call(GroupCallId group_call_id,
return;
}
LOG(INFO) << "Add " << user_id << " as recent speaker at " << date << " in " << input_group_call_id << " from "
<< group_call->dialog_id;
LOG(INFO) << "Add " << user_id << " as recent speaker at " << date << " in " << input_group_call_id;
auto &recent_speakers = group_call_recent_speakers_[group_call_id];
if (recent_speakers == nullptr) {
recent_speakers = make_unique<GroupCallRecentSpeakers>();
@ -1916,7 +2111,7 @@ void GroupCallManager::on_user_speaking_in_group_call(GroupCallId group_call_id,
void GroupCallManager::remove_recent_group_call_speaker(InputGroupCallId input_group_call_id, UserId user_id) {
auto *group_call = get_group_call(input_group_call_id);
if (group_call != nullptr && group_call->is_inited && !group_call->is_active) {
if (group_call == nullptr) {
return;
}
@ -2039,9 +2234,10 @@ tl_object_ptr<td_api::groupCall> GroupCallManager::get_group_call_object(const G
CHECK(group_call->is_inited);
return td_api::make_object<td_api::groupCall>(
group_call->group_call_id.get(), group_call->is_active, group_call->is_joined, group_call->can_self_unmute,
group_call->participant_count, group_call->loaded_all_participants, std::move(recent_speaker_user_ids),
group_call->mute_new_participants, group_call->allowed_change_mute_new_participants, group_call->duration);
group_call->group_call_id.get(), group_call->is_active, group_call->is_joined, group_call->need_rejoin,
group_call->can_self_unmute, group_call->can_be_managed, group_call->participant_count,
group_call->loaded_all_participants, std::move(recent_speaker_user_ids), group_call->mute_new_participants,
group_call->allowed_change_mute_new_participants, group_call->duration);
}
tl_object_ptr<td_api::updateGroupCall> GroupCallManager::get_update_group_call_object(

View File

@ -41,6 +41,8 @@ class GroupCallManager : public Actor {
void get_group_call(GroupCallId group_call_id, Promise<td_api::object_ptr<td_api::groupCall>> &&promise);
void on_update_group_call_rights(InputGroupCallId input_group_call_id);
void reload_group_call(InputGroupCallId input_group_call_id,
Promise<td_api::object_ptr<td_api::groupCall>> &&promise);
@ -112,7 +114,9 @@ class GroupCallManager : public Actor {
const GroupCall *get_group_call(InputGroupCallId input_group_call_id) const;
GroupCall *get_group_call(InputGroupCallId input_group_call_id);
Status can_manage_group_calls(DialogId dialog_id);
Status can_manage_group_calls(DialogId dialog_id) const;
bool can_manage_group_call(InputGroupCallId input_group_call_id) const;
void on_voice_chat_created(DialogId dialog_id, InputGroupCallId input_group_call_id, Promise<GroupCallId> &&promise);
@ -131,15 +135,28 @@ class GroupCallManager : public Actor {
vector<tl_object_ptr<telegram_api::groupCallParticipant>> &&participants,
bool is_load, bool is_sync);
bool update_group_call_participant_can_be_muted(bool can_manage, const GroupCallParticipants *participants,
GroupCallParticipant &participant);
void update_group_call_participants_can_be_muted(InputGroupCallId input_group_call_id, bool can_manage,
GroupCallParticipants *participants);
int process_group_call_participant(InputGroupCallId group_call_id, GroupCallParticipant &&participant);
void try_load_group_call_administrators(InputGroupCallId input_group_call_id, DialogId dialog_id);
void finish_load_group_call_administrators(InputGroupCallId input_group_call_id, int64 random_id,
Result<Unit> &&result);
bool on_join_group_call_response(InputGroupCallId input_group_call_id, string json_response);
void finish_join_group_call(InputGroupCallId input_group_call_id, uint64 generation, Status error);
void on_group_call_left(InputGroupCallId input_group_call_id, int32 source);
GroupCallParticipants *add_group_call_participants(InputGroupCallId input_group_call_id);
void on_group_call_left_impl(GroupCall *group_call);
void on_group_call_left(InputGroupCallId input_group_call_id, int32 source, bool need_rejoin);
void on_group_call_left_impl(GroupCall *group_call, bool need_rejoin);
InputGroupCallId update_group_call(const tl_object_ptr<telegram_api::GroupCall> &group_call_ptr, DialogId dialog_id);

View File

@ -30,6 +30,36 @@ GroupCallParticipant::GroupCallParticipant(const tl_object_ptr<telegram_api::gro
is_just_joined = participant->just_joined_;
}
bool GroupCallParticipant::is_versioned_update(const tl_object_ptr<telegram_api::groupCallParticipant> &participant) {
return participant->just_joined_ || participant->left_ || participant->versioned_;
}
bool GroupCallParticipant::update_can_be_muted(bool can_manage, bool is_self, bool is_admin) {
bool new_can_be_muted = false;
bool new_can_be_unmuted = false;
if (is_self) {
// current user can be muted if !is_muted; after that is_muted && can_self_unmute
// current user can be unmuted if is_muted && can_self_unmute; after that !is_muted
new_can_be_muted = !is_muted;
new_can_be_unmuted = is_muted && can_self_unmute;
} else if (is_admin) {
// admin user can be muted if can_manage && !is_muted; after that is_muted && can_self_unmute
// admin user can't be unmuted
new_can_be_muted = can_manage && !is_muted;
} else {
// other user can be muted if can_manage; after that is_muted && !can_self_unmute
// other user can be unmuted if can_manage && is_muted && !can_self_unmute; after that is_muted && can_self_unmute
new_can_be_muted = can_manage && (!is_muted || can_self_unmute);
new_can_be_unmuted = can_manage && is_muted && !can_self_unmute;
}
if (new_can_be_muted != can_be_muted || new_can_be_unmuted != can_be_unmuted) {
can_be_muted = new_can_be_muted;
can_be_unmuted = new_can_be_unmuted;
return true;
}
return false;
}
td_api::object_ptr<td_api::groupCallParticipant> GroupCallParticipant::get_group_call_participant_object(
ContactsManager *contacts_manager) const {
if (!is_valid()) {
@ -37,16 +67,14 @@ td_api::object_ptr<td_api::groupCallParticipant> GroupCallParticipant::get_group
}
return td_api::make_object<td_api::groupCallParticipant>(
contacts_manager->get_user_id_object(user_id, "get_group_call_participant_object"), source, is_speaking, is_muted,
can_self_unmute, order);
contacts_manager->get_user_id_object(user_id, "get_group_call_participant_object"), source, is_speaking,
can_be_muted, can_be_unmuted, is_muted, can_self_unmute, order);
}
bool operator==(const GroupCallParticipant &lhs, const GroupCallParticipant &rhs) {
return lhs.user_id == rhs.user_id && lhs.source == rhs.source && lhs.is_muted == rhs.is_muted &&
lhs.can_self_unmute == rhs.can_self_unmute &&
max(lhs.active_date, lhs.local_active_date) == max(rhs.active_date, rhs.local_active_date) &&
lhs.joined_date == rhs.joined_date && lhs.is_speaking == rhs.is_speaking ||
lhs.order != rhs.order;
return lhs.user_id == rhs.user_id && lhs.source == rhs.source && lhs.can_be_muted == rhs.can_be_muted &&
lhs.can_be_unmuted == rhs.can_be_unmuted && lhs.is_muted == rhs.is_muted &&
lhs.can_self_unmute == rhs.can_self_unmute && lhs.is_speaking == rhs.is_speaking && lhs.order == rhs.order;
}
bool operator!=(const GroupCallParticipant &lhs, const GroupCallParticipant &rhs) {

View File

@ -20,16 +20,27 @@ class ContactsManager;
struct GroupCallParticipant {
UserId user_id;
int32 source = 0;
bool is_muted = false;
bool can_self_unmute = false;
int32 joined_date = 0;
int32 active_date = 0;
bool is_muted = false;
bool can_self_unmute = false;
bool can_be_muted = false;
bool can_be_unmuted = false;
bool is_just_joined = false;
bool is_speaking = false;
int32 local_active_date = 0;
int64 order = 0;
GroupCallParticipant() = default;
explicit GroupCallParticipant(const tl_object_ptr<telegram_api::groupCallParticipant> &participant);
static bool is_versioned_update(const tl_object_ptr<telegram_api::groupCallParticipant> &participant);
bool update_can_be_muted(bool can_manage, bool is_self, bool is_admin);
int64 get_real_order() const {
return (static_cast<int64>(max(active_date, local_active_date)) << 32) + joined_date;
}
@ -38,10 +49,6 @@ struct GroupCallParticipant {
return user_id.is_valid();
}
GroupCallParticipant() = default;
explicit GroupCallParticipant(const tl_object_ptr<telegram_api::groupCallParticipant> &participant);
td_api::object_ptr<td_api::groupCallParticipant> get_group_call_participant_object(
ContactsManager *contacts_manager) const;
};

View File

@ -1594,6 +1594,7 @@ static Result<InputMessageContent> create_input_message_content(
unique_ptr<MessageContent> content;
UserId via_bot_user_id;
int32 ttl = 0;
string emoji;
bool is_bot = td->auth_manager_->is_bot();
switch (input_message_content->get_id()) {
case td_api::inputMessageText::ID: {
@ -1709,6 +1710,9 @@ static Result<InputMessageContent> create_input_message_content(
}
case td_api::inputMessageSticker::ID: {
auto input_sticker = static_cast<td_api::inputMessageSticker *>(input_message_content.get());
emoji = std::move(input_sticker->emoji_);
td->stickers_manager_->create_sticker(file_id, string(), thumbnail,
get_dimensions(input_sticker->width_, input_sticker->height_), nullptr,
false, nullptr);
@ -1967,7 +1971,8 @@ static Result<InputMessageContent> create_input_message_content(
default:
UNREACHABLE();
}
return InputMessageContent{std::move(content), disable_web_page_preview, clear_draft, ttl, via_bot_user_id};
return InputMessageContent{std::move(content), disable_web_page_preview, clear_draft, ttl,
via_bot_user_id, std::move(emoji)};
}
Result<InputMessageContent> get_input_message_content(
@ -2323,7 +2328,7 @@ static tl_object_ptr<telegram_api::inputMediaInvoice> get_input_media_invoice(co
static tl_object_ptr<telegram_api::InputMedia> get_input_media_impl(
const MessageContent *content, Td *td, tl_object_ptr<telegram_api::InputFile> input_file,
tl_object_ptr<telegram_api::InputFile> input_thumbnail, int32 ttl) {
tl_object_ptr<telegram_api::InputFile> input_thumbnail, int32 ttl, const string &emoji) {
if (!can_have_input_media(td, content)) {
return nullptr;
}
@ -2381,7 +2386,8 @@ static tl_object_ptr<telegram_api::InputMedia> get_input_media_impl(
}
case MessageContentType::Sticker: {
auto m = static_cast<const MessageSticker *>(content);
return td->stickers_manager_->get_input_media(m->file_id, std::move(input_file), std::move(input_thumbnail));
return td->stickers_manager_->get_input_media(m->file_id, std::move(input_file), std::move(input_thumbnail),
emoji);
}
case MessageContentType::Venue: {
auto m = static_cast<const MessageVenue *>(content);
@ -2442,7 +2448,8 @@ tl_object_ptr<telegram_api::InputMedia> get_input_media(const MessageContent *co
bool force) {
bool had_input_file = input_file != nullptr;
bool had_input_thumbnail = input_thumbnail != nullptr;
auto input_media = get_input_media_impl(content, td, std::move(input_file), std::move(input_thumbnail), ttl);
auto input_media =
get_input_media_impl(content, td, std::move(input_file), std::move(input_thumbnail), ttl, string());
auto was_uploaded = FileManager::extract_was_uploaded(input_media);
if (had_input_file) {
if (!was_uploaded) {
@ -2471,8 +2478,9 @@ tl_object_ptr<telegram_api::InputMedia> get_input_media(const MessageContent *co
return input_media;
}
tl_object_ptr<telegram_api::InputMedia> get_input_media(const MessageContent *content, Td *td, int32 ttl, bool force) {
auto input_media = get_input_media_impl(content, td, nullptr, nullptr, ttl);
tl_object_ptr<telegram_api::InputMedia> get_input_media(const MessageContent *content, Td *td, int32 ttl,
const string &emoji, bool force) {
auto input_media = get_input_media_impl(content, td, nullptr, nullptr, ttl, emoji);
auto file_reference = FileManager::extract_file_reference(input_media);
if (file_reference == FileReferenceView::invalid_file_reference()) {
auto file_id = get_message_content_any_file_id(content);

View File

@ -61,14 +61,16 @@ struct InputMessageContent {
bool clear_draft = false;
int32 ttl = 0;
UserId via_bot_user_id;
string emoji;
InputMessageContent(unique_ptr<MessageContent> &&content, bool disable_web_page_preview, bool clear_draft, int32 ttl,
UserId via_bot_user_id)
UserId via_bot_user_id, string emoji)
: content(std::move(content))
, disable_web_page_preview(disable_web_page_preview)
, clear_draft(clear_draft)
, ttl(ttl)
, via_bot_user_id(via_bot_user_id) {
, via_bot_user_id(via_bot_user_id)
, emoji(std::move(emoji)) {
}
};
@ -112,7 +114,8 @@ tl_object_ptr<telegram_api::InputMedia> get_input_media(const MessageContent *co
FileId file_id, FileId thumbnail_file_id, int32 ttl,
bool force);
tl_object_ptr<telegram_api::InputMedia> get_input_media(const MessageContent *content, Td *td, int32 ttl, bool force);
tl_object_ptr<telegram_api::InputMedia> get_input_media(const MessageContent *content, Td *td, int32 ttl,
const string &emoji, bool force);
void delete_message_content_thumbnail(MessageContent *content, Td *td);

View File

@ -2797,7 +2797,7 @@ static Result<vector<MessageEntity>> do_parse_html(CSlice text, string &result)
while (!is_space(text[i]) && text[i] != '>') {
i++;
}
Slice end_tag_name = text.substr(begin_pos + 2, i - begin_pos - 2);
string end_tag_name = to_lower(text.substr(begin_pos + 2, i - begin_pos - 2));
while (is_space(text[i]) && text[i] != 0) {
i++;
}

View File

@ -243,7 +243,7 @@ class GetAllDraftsQuery : public Td::ResultHandler {
auto ptr = result_ptr.move_as_ok();
LOG(INFO) << "Receive result for GetAllDraftsQuery: " << to_string(ptr);
td->updates_manager_->on_get_updates(std::move(ptr));
td->updates_manager_->on_get_updates(std::move(ptr), Promise<Unit>());
}
void on_error(uint64 id, Status status) override {
@ -612,9 +612,7 @@ class UpdateDialogPinnedMessageQuery : public Td::ResultHandler {
auto ptr = result_ptr.move_as_ok();
LOG(INFO) << "Receive result for UpdateDialogPinnedMessageQuery: " << to_string(ptr);
td->updates_manager_->on_get_updates(std::move(ptr));
promise_.set_value(Unit());
td->updates_manager_->on_get_updates(std::move(ptr), std::move(promise_));
}
void on_error(uint64 id, Status status) override {
@ -1068,13 +1066,12 @@ class EditDialogPhotoQuery : public Td::ResultHandler {
auto ptr = result_ptr.move_as_ok();
LOG(INFO) << "Receive result for EditDialogPhotoQuery: " << to_string(ptr);
td->updates_manager_->on_get_updates(std::move(ptr));
if (file_id_.is_valid() && was_uploaded_) {
td->file_manager_->delete_partial_remote_location(file_id_);
}
promise_.set_value(Unit());
td->updates_manager_->on_get_updates(std::move(ptr), std::move(promise_));
}
void on_error(uint64 id, Status status) override {
@ -1144,9 +1141,7 @@ class EditDialogTitleQuery : public Td::ResultHandler {
auto ptr = result_ptr.move_as_ok();
LOG(INFO) << "Receive result for EditDialogTitleQuery: " << to_string(ptr);
td->updates_manager_->on_get_updates(std::move(ptr));
promise_.set_value(Unit());
td->updates_manager_->on_get_updates(std::move(ptr), std::move(promise_));
}
void on_error(uint64 id, Status status) override {
@ -1188,9 +1183,7 @@ class EditDialogDefaultBannedRightsQuery : public Td::ResultHandler {
auto ptr = result_ptr.move_as_ok();
LOG(INFO) << "Receive result for EditDialogPermissionsQuery: " << to_string(ptr);
td->updates_manager_->on_get_updates(std::move(ptr));
promise_.set_value(Unit());
td->updates_manager_->on_get_updates(std::move(ptr), std::move(promise_));
}
void on_error(uint64 id, Status status) override {
@ -2348,9 +2341,7 @@ class BlockFromRepliesQuery : public Td::ResultHandler {
auto ptr = result_ptr.move_as_ok();
LOG(INFO) << "Receive result for BlockFromRepliesQuery: " << to_string(ptr);
td->updates_manager_->on_get_updates(std::move(ptr));
promise_.set_value(Unit());
td->updates_manager_->on_get_updates(std::move(ptr), std::move(promise_));
}
void on_error(uint64 id, Status status) override {
@ -2580,7 +2571,7 @@ class SendMessageActor : public NetActorOnce {
auto constructor_id = ptr->get_id();
if (constructor_id != telegram_api::updateShortSentMessage::ID) {
td->messages_manager_->check_send_message_result(random_id_, dialog_id_, ptr.get(), "SendMessage");
return td->updates_manager_->on_get_updates(std::move(ptr));
return td->updates_manager_->on_get_updates(std::move(ptr), Promise<Unit>());
}
auto sent_message = move_tl_object_as<telegram_api::updateShortSentMessage>(ptr);
td->messages_manager_->on_update_sent_text_message(random_id_, std::move(sent_message->media_),
@ -2646,7 +2637,7 @@ class StartBotQuery : public Td::ResultHandler {
LOG(INFO) << "Receive result for StartBotQuery for " << random_id_ << ": " << to_string(ptr);
// Result may contain messageActionChatAddUser
// td->messages_manager_->check_send_message_result(random_id_, dialog_id_, ptr.get(), "StartBot");
td->updates_manager_->on_get_updates(std::move(ptr));
td->updates_manager_->on_get_updates(std::move(ptr), Promise<Unit>());
}
void on_error(uint64 id, Status status) override {
@ -2690,7 +2681,7 @@ class SendInlineBotResultQuery : public Td::ResultHandler {
auto ptr = result_ptr.move_as_ok();
LOG(INFO) << "Receive result for SendInlineBotResultQuery for " << random_id_ << ": " << to_string(ptr);
td->messages_manager_->check_send_message_result(random_id_, dialog_id_, ptr.get(), "SendInlineBotResult");
td->updates_manager_->on_get_updates(std::move(ptr));
td->updates_manager_->on_get_updates(std::move(ptr), Promise<Unit>());
}
void on_error(uint64 id, Status status) override {
@ -2783,7 +2774,7 @@ class SendMultiMediaActor : public NetActorOnce {
td->updates_manager_->schedule_get_difference("Wrong sendMultiMedia result");
}
td->updates_manager_->on_get_updates(std::move(ptr));
td->updates_manager_->on_get_updates(std::move(ptr), Promise<Unit>());
}
void on_error(uint64 id, Status status) override {
@ -2877,7 +2868,7 @@ class SendMediaActor : public NetActorOnce {
auto ptr = result_ptr.move_as_ok();
LOG(INFO) << "Receive result for SendMediaQuery for " << random_id_ << ": " << to_string(ptr);
td->messages_manager_->check_send_message_result(random_id_, dialog_id_, ptr.get(), "SendMedia");
td->updates_manager_->on_get_updates(std::move(ptr));
td->updates_manager_->on_get_updates(std::move(ptr), Promise<Unit>());
}
void on_error(uint64 id, Status status) override {
@ -3036,9 +3027,7 @@ class SendScheduledMessageActor : public NetActorOnce {
auto ptr = result_ptr.move_as_ok();
LOG(INFO) << "Receive result for SendScheduledMessageActor: " << to_string(ptr);
td->updates_manager_->on_get_updates(std::move(ptr));
promise_.set_value(Unit());
td->updates_manager_->on_get_updates(std::move(ptr), std::move(promise_));
}
void on_error(uint64 id, Status status) override {
@ -3112,9 +3101,7 @@ class EditMessageActor : public NetActorOnce {
auto ptr = result_ptr.move_as_ok();
LOG(INFO) << "Receive result for EditMessageActor: " << to_string(ptr);
td->updates_manager_->on_get_updates(std::move(ptr));
promise_.set_value(Unit());
td->updates_manager_->on_get_updates(std::move(ptr), std::move(promise_));
}
void on_error(uint64 id, Status status) override {
@ -3230,9 +3217,7 @@ class SetGameScoreActor : public NetActorOnce {
auto ptr = result_ptr.move_as_ok();
LOG(INFO) << "Receive result for SetGameScoreActor: " << to_string(ptr);
td->updates_manager_->on_get_updates(std::move(ptr));
promise_.set_value(Unit());
td->updates_manager_->on_get_updates(std::move(ptr), std::move(promise_));
}
void on_error(uint64 id, Status status) override {
@ -3457,8 +3442,7 @@ class ForwardMessagesActor : public NetActorOnce {
td->updates_manager_->schedule_get_difference("Wrong forwardMessages result");
}
td->updates_manager_->on_get_updates(std::move(ptr));
promise_.set_value(Unit());
td->updates_manager_->on_get_updates(std::move(ptr), std::move(promise_));
}
void on_error(uint64 id, Status status) override {
@ -3508,8 +3492,7 @@ class SendScreenshotNotificationQuery : public Td::ResultHandler {
LOG(INFO) << "Receive result for SendScreenshotNotificationQuery for " << random_id_ << ": " << to_string(ptr);
td->messages_manager_->check_send_message_result(random_id_, dialog_id_, ptr.get(),
"SendScreenshotNotificationQuery");
td->updates_manager_->on_get_updates(std::move(ptr));
promise_.set_value(Unit());
td->updates_manager_->on_get_updates(std::move(ptr), std::move(promise_));
}
void on_error(uint64 id, Status status) override {
@ -3722,9 +3705,7 @@ class DeleteScheduledMessagesQuery : public Td::ResultHandler {
auto ptr = result_ptr.move_as_ok();
LOG(INFO) << "Receive result for DeleteScheduledMessagesQuery: " << to_string(ptr);
td->updates_manager_->on_get_updates(std::move(ptr));
promise_.set_value(Unit());
td->updates_manager_->on_get_updates(std::move(ptr), std::move(promise_));
}
void on_error(uint64 id, Status status) override {
@ -3817,9 +3798,7 @@ class GetNotifySettingsExceptionsQuery : public Td::ResultHandler {
for (auto &dialog_id : dialog_ids) {
td->messages_manager_->force_create_dialog(dialog_id, "GetNotifySettingsExceptionsQuery");
}
td->updates_manager_->on_get_updates(std::move(updates_ptr));
promise_.set_value(Unit());
td->updates_manager_->on_get_updates(std::move(updates_ptr), std::move(promise_));
}
void on_error(uint64 id, Status status) override {
@ -4201,8 +4180,7 @@ class EditPeerFoldersQuery : public Td::ResultHandler {
auto ptr = result_ptr.move_as_ok();
LOG(INFO) << "Receive result for EditPeerFoldersQuery: " << to_string(ptr);
td->updates_manager_->on_get_updates(std::move(ptr));
promise_.set_value(Unit());
td->updates_manager_->on_get_updates(std::move(ptr), std::move(promise_));
}
void on_error(uint64 id, Status status) override {
@ -4584,6 +4562,7 @@ void MessagesManager::Message::store(StorerT &storer) const {
bool has_local_thread_message_ids = !local_thread_message_ids.empty();
bool has_linked_top_thread_message_id = linked_top_thread_message_id.is_valid();
bool has_interaction_info_update_date = interaction_info_update_date != 0;
bool has_send_emoji = !send_emoji.empty();
BEGIN_STORE_FLAGS();
STORE_FLAG(is_channel_post);
STORE_FLAG(is_outgoing);
@ -4642,6 +4621,7 @@ void MessagesManager::Message::store(StorerT &storer) const {
STORE_FLAG(has_linked_top_thread_message_id);
STORE_FLAG(is_pinned);
STORE_FLAG(has_interaction_info_update_date);
STORE_FLAG(has_send_emoji);
END_STORE_FLAGS();
}
@ -4747,6 +4727,9 @@ void MessagesManager::Message::store(StorerT &storer) const {
if (has_interaction_info_update_date) {
store(interaction_info_update_date, storer);
}
if (has_send_emoji) {
store(send_emoji, storer);
}
store_message_content(content.get(), storer);
if (has_reply_markup) {
store(reply_markup, storer);
@ -4789,6 +4772,7 @@ void MessagesManager::Message::parse(ParserT &parser) {
bool has_local_thread_message_ids = false;
bool has_linked_top_thread_message_id = false;
bool has_interaction_info_update_date = false;
bool has_send_emoji = false;
BEGIN_PARSE_FLAGS();
PARSE_FLAG(is_channel_post);
PARSE_FLAG(is_outgoing);
@ -4847,6 +4831,7 @@ void MessagesManager::Message::parse(ParserT &parser) {
PARSE_FLAG(has_linked_top_thread_message_id);
PARSE_FLAG(is_pinned);
PARSE_FLAG(has_interaction_info_update_date);
PARSE_FLAG(has_send_emoji);
END_PARSE_FLAGS();
}
@ -4958,6 +4943,9 @@ void MessagesManager::Message::parse(ParserT &parser) {
if (has_interaction_info_update_date) {
parse(interaction_info_update_date, parser);
}
if (has_send_emoji) {
parse(send_emoji, parser);
}
parse_message_content(content, parser);
if (has_reply_markup) {
parse(reply_markup, parser);
@ -10830,7 +10818,7 @@ void MessagesManager::delete_dialog(DialogId dialog_id) {
close_dialog(d);
}
void MessagesManager::reload_dialog_group_call(DialogId dialog_id) {
void MessagesManager::on_update_dialog_group_call_rights(DialogId dialog_id) {
if (td_->auth_manager_->is_bot()) {
return;
}
@ -10842,7 +10830,7 @@ void MessagesManager::reload_dialog_group_call(DialogId dialog_id) {
}
if (d->active_group_call_id.is_valid()) {
td_->group_call_manager_->reload_group_call(d->active_group_call_id, Auto());
td_->group_call_manager_->on_update_group_call_rights(d->active_group_call_id);
}
}
@ -19381,6 +19369,10 @@ void MessagesManager::open_dialog(Dialog *d) {
get_dialog_pinned_message(dialog_id, Auto());
if (d->active_group_call_id.is_valid()) {
td_->group_call_manager_->reload_group_call(d->active_group_call_id, Auto());
}
switch (dialog_id.get_type()) {
case DialogType::User:
break;
@ -20158,8 +20150,8 @@ tl_object_ptr<td_api::messages> MessagesManager::get_dialog_history(DialogId dia
}
LOG(INFO) << "Return " << messages.size() << " messages in result to getChatHistory";
promise.set_value(Unit()); // can return some messages
return get_messages_object(-1, std::move(messages)); // TODO return real total_count of messages in the dialog
promise.set_value(Unit()); // can return some messages
return get_messages_object(-1, std::move(messages), false); // TODO return real total_count of messages in the dialog
}
class MessagesManager::ReadHistoryOnServerLogEvent {
@ -22538,26 +22530,36 @@ tl_object_ptr<td_api::message> MessagesManager::get_message_object(DialogId dial
}
tl_object_ptr<td_api::messages> MessagesManager::get_messages_object(int32 total_count, DialogId dialog_id,
const vector<MessageId> &message_ids) {
const vector<MessageId> &message_ids,
bool skip_not_found) {
Dialog *d = get_dialog(dialog_id);
CHECK(d != nullptr);
return get_messages_object(total_count, transform(message_ids, [this, dialog_id, d](MessageId message_id) {
return get_message_object(dialog_id,
get_message_force(d, message_id, "get_messages_object"));
}));
auto message_objects = transform(message_ids, [this, dialog_id, d](MessageId message_id) {
return get_message_object(dialog_id, get_message_force(d, message_id, "get_messages_object"));
});
return get_messages_object(total_count, std::move(message_objects), skip_not_found);
}
tl_object_ptr<td_api::messages> MessagesManager::get_messages_object(int32 total_count,
const vector<FullMessageId> &full_message_ids) {
return get_messages_object(total_count, transform(full_message_ids, [this](FullMessageId full_message_id) {
return get_message_object(full_message_id);
}));
const vector<FullMessageId> &full_message_ids,
bool skip_not_found) {
auto message_objects = transform(
full_message_ids, [this](FullMessageId full_message_id) { return get_message_object(full_message_id); });
return get_messages_object(total_count, std::move(message_objects), skip_not_found);
}
tl_object_ptr<td_api::messages> MessagesManager::get_messages_object(
int32 total_count, vector<tl_object_ptr<td_api::message>> &&messages) {
if (total_count == -1) {
total_count = narrow_cast<int32>(messages.size());
tl_object_ptr<td_api::messages> MessagesManager::get_messages_object(int32 total_count,
vector<tl_object_ptr<td_api::message>> &&messages,
bool skip_not_found) {
auto message_count = narrow_cast<int32>(messages.size());
if (total_count < message_count) {
if (total_count != -1) {
LOG(ERROR) << "Have wrong total_count = " << total_count << ", while having " << message_count << " messages";
}
total_count = message_count;
}
if (skip_not_found && td::remove(messages, nullptr)) {
total_count -= message_count - static_cast<int32>(messages.size());
}
return td_api::make_object<td_api::messages>(total_count, std::move(messages));
}
@ -23219,6 +23221,7 @@ Result<MessageId> MessagesManager::send_message(DialogId dialog_id, MessageId to
m->ttl = message_content.ttl;
m->is_content_secret = is_secret_message_content(m->ttl, m->content->get_type());
}
m->send_emoji = std::move(message_content.emoji);
if (message_content.clear_draft) {
if (top_thread_message_id.is_valid()) {
@ -23281,7 +23284,7 @@ Result<InputMessageContent> MessagesManager::process_input_message_content(
}
return InputMessageContent(std::move(content), get_message_disable_web_page_preview(copied_message), false, 0,
UserId());
UserId(), copied_message->send_emoji);
}
TRY_RESULT(content, get_input_message_content(dialog_id, std::move(input_message_content), td_));
@ -23539,7 +23542,8 @@ void MessagesManager::do_send_message(DialogId dialog_id, const Message *m, vect
on_secret_message_media_uploaded(dialog_id, m, std::move(secret_input_media), file_id, thumbnail_file_id);
}
} else {
auto input_media = get_input_media(content, td_, m->ttl, td_->auth_manager_->is_bot() && bad_parts.empty());
auto input_media =
get_input_media(content, td_, m->ttl, m->send_emoji, td_->auth_manager_->is_bot() && bad_parts.empty());
if (input_media == nullptr) {
if (content_type == MessageContentType::Game || content_type == MessageContentType::Poll) {
return;
@ -23722,7 +23726,7 @@ void MessagesManager::on_upload_message_media_success(DialogId dialog_id, Messag
update_message_content(dialog_id, m, std::move(content), true, true, true);
auto input_media = get_input_media(m->content.get(), td_, m->ttl, true);
auto input_media = get_input_media(m->content.get(), td_, m->ttl, m->send_emoji, true);
Status result;
if (input_media == nullptr) {
result = Status::Error(400, "Failed to upload file");
@ -23900,7 +23904,7 @@ void MessagesManager::do_send_message_group(int64 media_album_id) {
}
const FormattedText *caption = get_message_content_caption(m->content.get());
auto input_media = get_input_media(m->content.get(), td_, m->ttl, true);
auto input_media = get_input_media(m->content.get(), td_, m->ttl, m->send_emoji, true);
if (input_media == nullptr) {
// TODO return CHECK
auto file_id = get_message_content_any_file_id(m->content.get());
@ -25111,7 +25115,7 @@ void MessagesManager::edit_inline_message_media(const string &inline_message_id,
return promise.set_error(Status::Error(400, "Invalid inline message identifier specified"));
}
auto input_media = get_input_media(content.content.get(), td_, 0, true);
auto input_media = get_input_media(content.content.get(), td_, 0, string(), true);
if (input_media == nullptr) {
return promise.set_error(Status::Error(400, "Invalid message content specified"));
}
@ -26184,6 +26188,7 @@ Result<vector<MessageId>> MessagesManager::resend_messages(DialogId dialog_id, v
m->ttl = message->ttl;
m->is_content_secret = message->is_content_secret;
m->media_album_id = new_media_album_ids[message->media_album_id].first;
m->send_emoji = message->send_emoji;
save_send_message_log_event(dialog_id, m);
do_send_message(dialog_id, m);
@ -26434,6 +26439,7 @@ Result<MessageId> MessagesManager::add_local_message(
m->ttl = message_content.ttl;
}
m->is_content_secret = is_secret_message_content(m->ttl, m->content->get_type());
m->send_emoji = std::move(message_content.emoji);
m->have_previous = true;
m->have_next = true;
@ -29442,7 +29448,7 @@ void MessagesManager::on_create_new_dialog_success(int64 random_id, tl_object_pt
return on_create_new_dialog_fail(random_id, Status::Error(500, "Chat was created earlier"), std::move(promise));
}
td_->updates_manager_->on_get_updates(std::move(updates));
td_->updates_manager_->on_get_updates(std::move(updates), Promise<Unit>());
}
void MessagesManager::on_create_new_dialog_fail(int64 random_id, Status error, Promise<Unit> &&promise) {
@ -30822,8 +30828,8 @@ std::pair<int32, vector<DialogParticipant>> MessagesManager::search_private_chat
}
std::pair<int32, vector<DialogParticipant>> MessagesManager::search_dialog_participants(
DialogId dialog_id, const string &query, int32 limit, DialogParticipantsFilter filter, int64 &random_id, bool force,
Promise<Unit> &&promise) {
DialogId dialog_id, const string &query, int32 limit, DialogParticipantsFilter filter, int64 &random_id,
bool without_bot_info, bool force, Promise<Unit> &&promise) {
LOG(INFO) << "Receive searchChatMembers request to search for " << query << " in " << dialog_id;
if (!have_dialog_force(dialog_id)) {
promise.set_error(Status::Error(3, "Chat not found"));
@ -30892,7 +30898,7 @@ std::pair<int32, vector<DialogParticipant>> MessagesManager::search_dialog_parti
return td_->contacts_manager_->get_channel_participants(dialog_id.get_channel_id(), request_filter,
additional_query, 0, limit, additional_limit, random_id,
force, std::move(promise));
without_bot_info, force, std::move(promise));
}
case DialogType::SecretChat: {
promise.set_value(Unit());

View File

@ -401,7 +401,7 @@ class MessagesManager : public Actor {
void delete_dialog(DialogId dialog_id);
void reload_dialog_group_call(DialogId dialog_id);
void on_update_dialog_group_call_rights(DialogId dialog_id);
void read_all_dialog_mentions(DialogId dialog_id, Promise<Unit> &&promise);
@ -538,8 +538,8 @@ class MessagesManager : public Actor {
std::pair<int32, vector<DialogParticipant>> search_dialog_participants(DialogId dialog_id, const string &query,
int32 limit, DialogParticipantsFilter filter,
int64 &random_id, bool force,
Promise<Unit> &&promise);
int64 &random_id, bool without_bot_info,
bool force, Promise<Unit> &&promise);
vector<DialogAdministrator> get_dialog_administrators(DialogId dialog_id, int left_tries, Promise<Unit> &&promise);
@ -791,9 +791,10 @@ class MessagesManager : public Actor {
tl_object_ptr<td_api::message> get_message_object(FullMessageId full_message_id);
tl_object_ptr<td_api::messages> get_messages_object(int32 total_count, DialogId dialog_id,
const vector<MessageId> &message_ids);
const vector<MessageId> &message_ids, bool skip_not_found);
tl_object_ptr<td_api::messages> get_messages_object(int32 total_count, const vector<FullMessageId> &full_message_ids);
tl_object_ptr<td_api::messages> get_messages_object(int32 total_count, const vector<FullMessageId> &full_message_ids,
bool skip_not_found);
void add_pending_update(tl_object_ptr<telegram_api::Update> &&update, int32 new_pts, int32 pts_count,
bool force_apply, const char *source);
@ -1111,6 +1112,8 @@ class MessagesManager : public Actor {
DialogId real_forward_from_dialog_id; // for resend_message
MessageId real_forward_from_message_id; // for resend_message
string send_emoji; // for send_message
NotificationId notification_id;
NotificationId removed_notification_id;
@ -1679,7 +1682,7 @@ class MessagesManager : public Actor {
static constexpr int32 MAX_GET_DIALOGS = 100; // server side limit
static constexpr int32 MAX_GET_HISTORY = 100; // server side limit
static constexpr int32 MAX_SEARCH_MESSAGES = 100; // server side limit
static constexpr int32 MIN_SEARCH_PUBLIC_DIALOG_PREFIX_LEN = 5; // server side limit
static constexpr int32 MIN_SEARCH_PUBLIC_DIALOG_PREFIX_LEN = 4; // server side limit
static constexpr int32 MIN_CHANNEL_DIFFERENCE = 10;
static constexpr int32 MAX_CHANNEL_DIFFERENCE = 100;
static constexpr int32 MAX_BOT_CHANNEL_DIFFERENCE = 100000; // server side limit
@ -2284,7 +2287,8 @@ class MessagesManager : public Actor {
bool for_event_log = false) const;
static tl_object_ptr<td_api::messages> get_messages_object(int32 total_count,
vector<tl_object_ptr<td_api::message>> &&messages);
vector<tl_object_ptr<td_api::message>> &&messages,
bool skip_not_found);
vector<DialogId> sort_dialogs_by_order(const vector<DialogId> &dialog_ids, int32 limit) const;

View File

@ -361,8 +361,10 @@ class SendPaymentFormQuery : public Td::ResultHandler {
switch (payment_result->get_id()) {
case telegram_api::payments_paymentResult::ID: {
auto result = move_tl_object_as<telegram_api::payments_paymentResult>(payment_result);
G()->td().get_actor_unsafe()->updates_manager_->on_get_updates(std::move(result->updates_));
promise_.set_value(make_tl_object<td_api::paymentResult>(true, string()));
td->updates_manager_->on_get_updates(std::move(result->updates_),
PromiseCreator::lambda([promise = std::move(promise_)](Unit) mutable {
promise.set_value(make_tl_object<td_api::paymentResult>(true, string()));
}));
return;
}
case telegram_api::payments_paymentVerificationNeeded::ID: {
@ -410,9 +412,7 @@ class GetPaymentReceiptQuery : public Td::ResultHandler {
}
promise_.set_value(make_tl_object<td_api::paymentReceipt>(
payment_receipt->date_,
G()->td().get_actor_unsafe()->contacts_manager_->get_user_id_object(payments_provider_user_id,
"paymentReceipt"),
payment_receipt->date_, td->contacts_manager_->get_user_id_object(payments_provider_user_id, "paymentReceipt"),
convert_invoice(std::move(payment_receipt->invoice_)), convert_order_info(std::move(payment_receipt->info_)),
convert_shipping_option(std::move(payment_receipt->shipping_)),
std::move(payment_receipt->credentials_title_)));

View File

@ -224,9 +224,7 @@ class StopPollActor : public NetActorOnce {
auto result = result_ptr.move_as_ok();
LOG(INFO) << "Receive result for StopPollQuery: " << to_string(result);
td->updates_manager_->on_get_updates(std::move(result));
promise_.set_value(Unit());
td->updates_manager_->on_get_updates(std::move(result), std::move(promise_));
}
void on_error(uint64 id, Status status) override {
@ -846,7 +844,7 @@ void PollManager::on_set_poll_answer(PollId poll_id, uint64 generation,
poll->was_saved = false;
}
if (result.is_ok()) {
td_->updates_manager_->on_get_updates(result.move_as_ok());
td_->updates_manager_->on_get_updates(result.move_as_ok(), Promise<Unit>());
for (auto &promise : promises) {
promise.set_value(Unit());
@ -1220,7 +1218,7 @@ void PollManager::on_get_poll_results(PollId poll_id, uint64 generation,
return;
}
td_->updates_manager_->on_get_updates(result.move_as_ok());
td_->updates_manager_->on_get_updates(result.move_as_ok(), Promise<Unit>());
}
void PollManager::on_online() {

View File

@ -2374,13 +2374,18 @@ SecretInputMedia StickersManager::get_secret_input_media(FileId sticker_file_id,
tl_object_ptr<telegram_api::InputMedia> StickersManager::get_input_media(
FileId file_id, tl_object_ptr<telegram_api::InputFile> input_file,
tl_object_ptr<telegram_api::InputFile> input_thumbnail) const {
tl_object_ptr<telegram_api::InputFile> input_thumbnail, const string &emoji) const {
auto file_view = td_->file_manager_->get_file_view(file_id);
if (file_view.is_encrypted()) {
return nullptr;
}
if (file_view.has_remote_location() && !file_view.main_remote_location().is_web() && input_file == nullptr) {
return make_tl_object<telegram_api::inputMediaDocument>(0, file_view.main_remote_location().as_input_document(), 0);
int32 flags = 0;
if (!emoji.empty()) {
flags |= telegram_api::inputMediaDocument::QUERY_MASK;
}
return make_tl_object<telegram_api::inputMediaDocument>(flags, file_view.main_remote_location().as_input_document(),
0, emoji);
}
if (file_view.has_url()) {
return make_tl_object<telegram_api::inputMediaDocumentExternal>(0, file_view.url(), 0);
@ -4789,7 +4794,7 @@ void StickersManager::create_new_sticker_set(UserId user_id, string &title, stri
void StickersManager::upload_sticker_file(UserId user_id, FileId file_id, Promise<Unit> &&promise) {
FileId upload_file_id;
if (td_->file_manager_->get_file_view(file_id).get_type() == FileType::Sticker) {
CHECK(get_input_media(file_id, nullptr, nullptr) == nullptr);
CHECK(get_input_media(file_id, nullptr, nullptr, string()) == nullptr);
upload_file_id = dup_sticker(td_->file_manager_->dup_file_id(file_id), file_id);
} else {
CHECK(td_->documents_manager_->get_input_media(file_id, nullptr, nullptr) == nullptr);
@ -4850,7 +4855,7 @@ void StickersManager::do_upload_sticker_file(UserId user_id, FileId file_id,
bool is_animated = file_view.get_type() == FileType::Sticker;
bool had_input_file = input_file != nullptr;
auto input_media = is_animated ? get_input_media(file_id, std::move(input_file), nullptr)
auto input_media = is_animated ? get_input_media(file_id, std::move(input_file), nullptr, string())
: td_->documents_manager_->get_input_media(file_id, std::move(input_file), nullptr);
CHECK(input_media != nullptr);
if (had_input_file && !FileManager::extract_was_uploaded(input_media)) {

View File

@ -81,7 +81,8 @@ class StickersManager : public Actor {
tl_object_ptr<telegram_api::InputMedia> get_input_media(FileId file_id,
tl_object_ptr<telegram_api::InputFile> input_file,
tl_object_ptr<telegram_api::InputFile> input_thumbnail) const;
tl_object_ptr<telegram_api::InputFile> input_thumbnail,
const string &emoji) const;
SecretInputMedia get_secret_input_media(FileId sticker_file_id,
tl_object_ptr<telegram_api::InputEncryptedFile> input_file,

View File

@ -1136,7 +1136,7 @@ class GetMessagesRequest : public RequestOnceActor {
}
void do_send_result() override {
send_result(td->messages_manager_->get_messages_object(-1, dialog_id_, message_ids_));
send_result(td->messages_manager_->get_messages_object(-1, dialog_id_, message_ids_, false));
}
public:
@ -1447,7 +1447,7 @@ class GetMessageThreadHistoryRequest : public RequestActor<> {
}
void do_send_result() override {
send_result(td->messages_manager_->get_messages_object(-1, messages_.first, messages_.second));
send_result(td->messages_manager_->get_messages_object(-1, messages_.first, messages_.second, true));
}
public:
@ -1484,7 +1484,7 @@ class SearchChatMessagesRequest : public RequestActor<> {
}
void do_send_result() override {
send_result(td->messages_manager_->get_messages_object(messages_.first, dialog_id_, messages_.second));
send_result(td->messages_manager_->get_messages_object(messages_.first, dialog_id_, messages_.second, true));
}
void do_send_error(Status &&status) override {
@ -1568,7 +1568,7 @@ class SearchMessagesRequest : public RequestActor<> {
}
void do_send_result() override {
send_result(td->messages_manager_->get_messages_object(messages_.first, messages_.second));
send_result(td->messages_manager_->get_messages_object(messages_.first, messages_.second, true));
}
void do_send_error(Status &&status) override {
@ -1613,7 +1613,7 @@ class SearchCallMessagesRequest : public RequestActor<> {
}
void do_send_result() override {
send_result(td->messages_manager_->get_messages_object(messages_.first, messages_.second));
send_result(td->messages_manager_->get_messages_object(messages_.first, messages_.second, true));
}
public:
@ -1640,7 +1640,7 @@ class SearchChatRecentLocationMessagesRequest : public RequestActor<> {
}
void do_send_result() override {
send_result(td->messages_manager_->get_messages_object(messages_.first, dialog_id_, messages_.second));
send_result(td->messages_manager_->get_messages_object(messages_.first, dialog_id_, messages_.second, true));
}
public:
@ -1657,7 +1657,7 @@ class GetActiveLiveLocationMessagesRequest : public RequestActor<> {
}
void do_send_result() override {
send_result(td->messages_manager_->get_messages_object(-1, full_message_ids_));
send_result(td->messages_manager_->get_messages_object(-1, full_message_ids_, true));
}
public:
@ -1725,7 +1725,7 @@ class GetChatScheduledMessagesRequest : public RequestActor<> {
}
void do_send_result() override {
send_result(td->messages_manager_->get_messages_object(-1, dialog_id_, message_ids_));
send_result(td->messages_manager_->get_messages_object(-1, dialog_id_, message_ids_, true));
}
public:
@ -1971,7 +1971,7 @@ class SearchChatMembersRequest : public RequestActor<> {
void do_run(Promise<Unit> &&promise) override {
participants_ = td->messages_manager_->search_dialog_participants(dialog_id_, query_, limit_, filter_, random_id_,
get_tries() < 3, std::move(promise));
false, get_tries() < 3, std::move(promise));
}
void do_send_result() override {
@ -2287,8 +2287,8 @@ class GetSupergroupMembersRequest : public RequestActor<> {
std::pair<int32, vector<DialogParticipant>> participants_;
void do_run(Promise<Unit> &&promise) override {
participants_ = td->contacts_manager_->get_channel_participants(channel_id_, filter_, string(), offset_, limit_, -1,
random_id_, get_tries() < 3, std::move(promise));
participants_ = td->contacts_manager_->get_channel_participants(
channel_id_, filter_, string(), offset_, limit_, -1, random_id_, false, get_tries() < 3, std::move(promise));
}
void do_send_result() override {
@ -3623,7 +3623,7 @@ void Td::on_result(NetQueryPtr query) {
LOG(ERROR) << "Failed to fetch update: " << parser.get_error() << format::as_hex_dump<4>(ok.as_slice());
updates_manager_->schedule_get_difference("failed to fetch update");
} else {
updates_manager_->on_get_updates(std::move(ptr));
updates_manager_->on_get_updates(std::move(ptr), Promise<Unit>());
if (auth_manager_->is_bot() && auth_manager_->is_authorized()) {
alarm_timeout_.set_timeout_in(PING_SERVER_ALARM_ID,
PING_SERVER_TIMEOUT + Random::fast(0, PING_SERVER_TIMEOUT / 5));
@ -5730,7 +5730,7 @@ void Td::on_request(uint64 id, td_api::sendMessageAlbum &request) {
}
send_closure(actor_id(this), &Td::send_result, id,
messages_manager_->get_messages_object(-1, dialog_id, r_message_ids.ok()));
messages_manager_->get_messages_object(-1, dialog_id, r_message_ids.ok(), false));
}
void Td::on_request(uint64 id, td_api::sendBotStartMessage &request) {
@ -5927,7 +5927,7 @@ void Td::on_request(uint64 id, td_api::forwardMessages &request) {
}
send_closure(actor_id(this), &Td::send_result, id,
messages_manager_->get_messages_object(-1, dialog_id, r_message_ids.ok()));
messages_manager_->get_messages_object(-1, dialog_id, r_message_ids.ok(), false));
}
void Td::on_request(uint64 id, const td_api::resendMessages &request) {
@ -5939,7 +5939,7 @@ void Td::on_request(uint64 id, const td_api::resendMessages &request) {
}
send_closure(actor_id(this), &Td::send_result, id,
messages_manager_->get_messages_object(-1, dialog_id, r_message_ids.ok()));
messages_manager_->get_messages_object(-1, dialog_id, r_message_ids.ok(), false));
}
void Td::on_request(uint64 id, td_api::getWebPagePreview &request) {

File diff suppressed because it is too large Load Diff

View File

@ -34,7 +34,7 @@ class UpdatesManager : public Actor {
public:
UpdatesManager(Td *td, ActorShared<> parent);
void on_get_updates(tl_object_ptr<telegram_api::Updates> &&updates_ptr);
void on_get_updates(tl_object_ptr<telegram_api::Updates> &&updates_ptr, Promise<Unit> &&promise);
void on_get_updates_state(tl_object_ptr<telegram_api::updates_state> &&state, const char *source);
@ -92,12 +92,20 @@ class UpdatesManager : public Actor {
int32 seq_end;
int32 date;
vector<tl_object_ptr<telegram_api::Update>> updates;
Promise<Unit> promise;
PendingUpdates(int32 seq_begin, int32 seq_end, int32 date, vector<tl_object_ptr<telegram_api::Update>> &&updates)
: seq_begin(seq_begin), seq_end(seq_end), date(date), updates(std::move(updates)) {
PendingUpdates(int32 seq_begin, int32 seq_end, int32 date, vector<tl_object_ptr<telegram_api::Update>> &&updates,
Promise<Unit> &&promise)
: seq_begin(seq_begin), seq_end(seq_end), date(date), updates(std::move(updates)), promise(std::move(promise)) {
}
};
class PendingQtsUpdate {
public:
tl_object_ptr<telegram_api::Update> update;
Promise<Unit> promise;
};
Td *td_;
ActorShared<> parent_;
@ -112,7 +120,7 @@ class UpdatesManager : public Actor {
std::multimap<int32, PendingUpdates> postponed_updates_; // updates received during getDifference
std::multimap<int32, PendingUpdates> pending_seq_updates_; // updates with too big seq
std::map<int32, tl_object_ptr<telegram_api::Update>> pending_qts_updates_; // updates with too big qts
std::map<int32, PendingQtsUpdate> pending_qts_updates_; // updates with too big qts
Timeout seq_gap_timeout_;
@ -142,18 +150,21 @@ class UpdatesManager : public Actor {
vector<tl_object_ptr<telegram_api::EncryptedMessage>> &&new_encrypted_messages,
vector<tl_object_ptr<telegram_api::Update>> &&other_updates);
void on_pending_update(tl_object_ptr<telegram_api::Update> update, int32 seq, const char *source);
void on_pending_update(tl_object_ptr<telegram_api::Update> update, int32 seq, Promise<Unit> &&promise,
const char *source);
void add_pending_qts_update(tl_object_ptr<telegram_api::Update> &&update, int32 qts);
void add_pending_qts_update(tl_object_ptr<telegram_api::Update> &&update, int32 qts, Promise<Unit> &&promise);
void on_pending_updates(vector<tl_object_ptr<telegram_api::Update>> &&updates, int32 seq_begin, int32 seq_end,
int32 date, const char *source);
int32 date, Promise<Unit> &&promise, const char *source);
void process_updates(vector<tl_object_ptr<telegram_api::Update>> &&updates, bool force_apply);
void process_updates(vector<tl_object_ptr<telegram_api::Update>> &&updates, bool force_apply,
Promise<Unit> &&promise);
void process_seq_updates(int32 seq_end, int32 date, vector<tl_object_ptr<telegram_api::Update>> &&updates);
void process_seq_updates(int32 seq_end, int32 date, vector<tl_object_ptr<telegram_api::Update>> &&updates,
Promise<Unit> &&promise);
void process_qts_update(tl_object_ptr<telegram_api::Update> &&update_ptr, int32 qts);
void process_qts_update(tl_object_ptr<telegram_api::Update> &&update_ptr, int32 qts, Promise<Unit> &&promise);
void process_pending_seq_updates();
@ -199,133 +210,185 @@ class UpdatesManager : public Actor {
bool is_acceptable_update(const telegram_api::Update *update) const;
void on_update(tl_object_ptr<telegram_api::updateNewMessage> update, bool force_apply);
void on_update(tl_object_ptr<telegram_api::updateMessageID> update, bool force_apply);
void on_update(tl_object_ptr<telegram_api::updateReadMessagesContents> update, bool force_apply);
void on_update(tl_object_ptr<telegram_api::updateEditMessage> update, bool force_apply);
void on_update(tl_object_ptr<telegram_api::updateDeleteMessages> update, bool force_apply);
void on_update(tl_object_ptr<telegram_api::updateReadHistoryInbox> update, bool force_apply);
void on_update(tl_object_ptr<telegram_api::updateReadHistoryOutbox> update, bool force_apply);
void on_update(tl_object_ptr<telegram_api::updateNotifySettings> update, bool /*force_apply*/);
void on_update(tl_object_ptr<telegram_api::updatePeerSettings> update, bool /*force_apply*/);
void on_update(tl_object_ptr<telegram_api::updatePeerLocated> update, bool /*force_apply*/);
void on_update(tl_object_ptr<telegram_api::updateNewMessage> update, bool force_apply, Promise<Unit> &&promise);
void on_update(tl_object_ptr<telegram_api::updateMessageID> update, bool force_apply, Promise<Unit> &&promise);
void on_update(tl_object_ptr<telegram_api::updateReadMessagesContents> update, bool force_apply,
Promise<Unit> &&promise);
void on_update(tl_object_ptr<telegram_api::updateEditMessage> update, bool force_apply, Promise<Unit> &&promise);
void on_update(tl_object_ptr<telegram_api::updateDeleteMessages> update, bool force_apply, Promise<Unit> &&promise);
void on_update(tl_object_ptr<telegram_api::updateReadHistoryInbox> update, bool force_apply, Promise<Unit> &&promise);
void on_update(tl_object_ptr<telegram_api::updateReadHistoryOutbox> update, bool force_apply,
Promise<Unit> &&promise);
void on_update(tl_object_ptr<telegram_api::updateNotifySettings> update, bool /*force_apply*/,
Promise<Unit> &&promise);
void on_update(tl_object_ptr<telegram_api::updatePeerSettings> update, bool /*force_apply*/, Promise<Unit> &&promise);
void on_update(tl_object_ptr<telegram_api::updatePeerLocated> update, bool /*force_apply*/, Promise<Unit> &&promise);
void on_update(tl_object_ptr<telegram_api::updateWebPage> update, bool force_apply);
void on_update(tl_object_ptr<telegram_api::updateChannelWebPage> update, bool force_apply);
void on_update(tl_object_ptr<telegram_api::updateWebPage> update, bool force_apply, Promise<Unit> &&promise);
void on_update(tl_object_ptr<telegram_api::updateChannelWebPage> update, bool force_apply, Promise<Unit> &&promise);
void on_update(tl_object_ptr<telegram_api::updateFolderPeers> update, bool /*force_apply*/);
void on_update(tl_object_ptr<telegram_api::updateFolderPeers> update, bool /*force_apply*/, Promise<Unit> &&promise);
void on_update(tl_object_ptr<telegram_api::updateUserTyping> update, bool /*force_apply*/);
void on_update(tl_object_ptr<telegram_api::updateChatUserTyping> update, bool /*force_apply*/);
void on_update(tl_object_ptr<telegram_api::updateChannelUserTyping> update, bool /*force_apply*/);
void on_update(tl_object_ptr<telegram_api::updateEncryptedChatTyping> update, bool /*force_apply*/);
void on_update(tl_object_ptr<telegram_api::updateUserTyping> update, bool /*force_apply*/, Promise<Unit> &&promise);
void on_update(tl_object_ptr<telegram_api::updateChatUserTyping> update, bool /*force_apply*/,
Promise<Unit> &&promise);
void on_update(tl_object_ptr<telegram_api::updateChannelUserTyping> update, bool /*force_apply*/,
Promise<Unit> &&promise);
void on_update(tl_object_ptr<telegram_api::updateEncryptedChatTyping> update, bool /*force_apply*/,
Promise<Unit> &&promise);
void on_update(tl_object_ptr<telegram_api::updateUserStatus> update, bool /*force_apply*/);
void on_update(tl_object_ptr<telegram_api::updateUserName> update, bool /*force_apply*/);
void on_update(tl_object_ptr<telegram_api::updateUserPhone> update, bool /*force_apply*/);
void on_update(tl_object_ptr<telegram_api::updateUserPhoto> update, bool /*force_apply*/);
void on_update(tl_object_ptr<telegram_api::updateUserStatus> update, bool /*force_apply*/, Promise<Unit> &&promise);
void on_update(tl_object_ptr<telegram_api::updateUserName> update, bool /*force_apply*/, Promise<Unit> &&promise);
void on_update(tl_object_ptr<telegram_api::updateUserPhone> update, bool /*force_apply*/, Promise<Unit> &&promise);
void on_update(tl_object_ptr<telegram_api::updateUserPhoto> update, bool /*force_apply*/, Promise<Unit> &&promise);
void on_update(tl_object_ptr<telegram_api::updatePeerBlocked> update, bool /*force_apply*/);
void on_update(tl_object_ptr<telegram_api::updatePeerBlocked> update, bool /*force_apply*/, Promise<Unit> &&promise);
void on_update(tl_object_ptr<telegram_api::updateChatParticipants> update, bool /*force_apply*/);
void on_update(tl_object_ptr<telegram_api::updateChatParticipantAdd> update, bool /*force_apply*/);
void on_update(tl_object_ptr<telegram_api::updateChatParticipantAdmin> update, bool /*force_apply*/);
void on_update(tl_object_ptr<telegram_api::updateChatParticipantDelete> update, bool /*force_apply*/);
void on_update(tl_object_ptr<telegram_api::updateChatParticipants> update, bool /*force_apply*/,
Promise<Unit> &&promise);
void on_update(tl_object_ptr<telegram_api::updateChatParticipantAdd> update, bool /*force_apply*/,
Promise<Unit> &&promise);
void on_update(tl_object_ptr<telegram_api::updateChatParticipantAdmin> update, bool /*force_apply*/,
Promise<Unit> &&promise);
void on_update(tl_object_ptr<telegram_api::updateChatParticipantDelete> update, bool /*force_apply*/,
Promise<Unit> &&promise);
void on_update(tl_object_ptr<telegram_api::updateChatDefaultBannedRights> update, bool /*force_apply*/);
void on_update(tl_object_ptr<telegram_api::updateChatDefaultBannedRights> update, bool /*force_apply*/,
Promise<Unit> &&promise);
void on_update(tl_object_ptr<telegram_api::updateServiceNotification> update, bool force_apply);
void on_update(tl_object_ptr<telegram_api::updateServiceNotification> update, bool force_apply,
Promise<Unit> &&promise);
void on_update(tl_object_ptr<telegram_api::updateDcOptions> update, bool /*force_apply*/);
void on_update(tl_object_ptr<telegram_api::updateDcOptions> update, bool /*force_apply*/, Promise<Unit> &&promise);
void on_update(tl_object_ptr<telegram_api::updateChat> update, bool /*force_apply*/);
void on_update(tl_object_ptr<telegram_api::updateChat> update, bool /*force_apply*/, Promise<Unit> &&promise);
void on_update(tl_object_ptr<telegram_api::updateNewChannelMessage> update, bool /*force_apply*/);
void on_update(tl_object_ptr<telegram_api::updateReadChannelInbox> update, bool /*force_apply*/);
void on_update(tl_object_ptr<telegram_api::updateReadChannelOutbox> update, bool /*force_apply*/);
void on_update(tl_object_ptr<telegram_api::updateChannelReadMessagesContents> update, bool /*force_apply*/);
void on_update(tl_object_ptr<telegram_api::updateChannelTooLong> update, bool force_apply);
void on_update(tl_object_ptr<telegram_api::updateChannel> update, bool force_apply);
void on_update(tl_object_ptr<telegram_api::updateEditChannelMessage> update, bool /*force_apply*/);
void on_update(tl_object_ptr<telegram_api::updateDeleteChannelMessages> update, bool /*force_apply*/);
void on_update(tl_object_ptr<telegram_api::updateChannelMessageViews> update, bool /*force_apply*/);
void on_update(tl_object_ptr<telegram_api::updateChannelMessageForwards> update, bool /*force_apply*/);
void on_update(tl_object_ptr<telegram_api::updateChannelAvailableMessages> update, bool /*force_apply*/);
void on_update(tl_object_ptr<telegram_api::updateNewChannelMessage> update, bool /*force_apply*/,
Promise<Unit> &&promise);
void on_update(tl_object_ptr<telegram_api::updateReadChannelInbox> update, bool /*force_apply*/,
Promise<Unit> &&promise);
void on_update(tl_object_ptr<telegram_api::updateReadChannelOutbox> update, bool /*force_apply*/,
Promise<Unit> &&promise);
void on_update(tl_object_ptr<telegram_api::updateChannelReadMessagesContents> update, bool /*force_apply*/,
Promise<Unit> &&promise);
void on_update(tl_object_ptr<telegram_api::updateChannelTooLong> update, bool force_apply, Promise<Unit> &&promise);
void on_update(tl_object_ptr<telegram_api::updateChannel> update, bool force_apply, Promise<Unit> &&promise);
void on_update(tl_object_ptr<telegram_api::updateEditChannelMessage> update, bool /*force_apply*/,
Promise<Unit> &&promise);
void on_update(tl_object_ptr<telegram_api::updateDeleteChannelMessages> update, bool /*force_apply*/,
Promise<Unit> &&promise);
void on_update(tl_object_ptr<telegram_api::updateChannelMessageViews> update, bool /*force_apply*/,
Promise<Unit> &&promise);
void on_update(tl_object_ptr<telegram_api::updateChannelMessageForwards> update, bool /*force_apply*/,
Promise<Unit> &&promise);
void on_update(tl_object_ptr<telegram_api::updateChannelAvailableMessages> update, bool /*force_apply*/,
Promise<Unit> &&promise);
void on_update(tl_object_ptr<telegram_api::updateReadChannelDiscussionInbox> update, bool /*force_apply*/);
void on_update(tl_object_ptr<telegram_api::updateReadChannelDiscussionOutbox> update, bool /*force_apply*/);
void on_update(tl_object_ptr<telegram_api::updateReadChannelDiscussionInbox> update, bool /*force_apply*/,
Promise<Unit> &&promise);
void on_update(tl_object_ptr<telegram_api::updateReadChannelDiscussionOutbox> update, bool /*force_apply*/,
Promise<Unit> &&promise);
void on_update(tl_object_ptr<telegram_api::updatePinnedMessages> update, bool force_apply);
void on_update(tl_object_ptr<telegram_api::updatePinnedChannelMessages> update, bool /*force_apply*/);
void on_update(tl_object_ptr<telegram_api::updatePinnedMessages> update, bool force_apply, Promise<Unit> &&promise);
void on_update(tl_object_ptr<telegram_api::updatePinnedChannelMessages> update, bool /*force_apply*/,
Promise<Unit> &&promise);
void on_update(tl_object_ptr<telegram_api::updateDraftMessage> update, bool /*force_apply*/);
void on_update(tl_object_ptr<telegram_api::updateDraftMessage> update, bool /*force_apply*/, Promise<Unit> &&promise);
void on_update(tl_object_ptr<telegram_api::updateDialogPinned> update, bool /*force_apply*/);
void on_update(tl_object_ptr<telegram_api::updatePinnedDialogs> update, bool /*force_apply*/);
void on_update(tl_object_ptr<telegram_api::updateDialogUnreadMark> update, bool /*force_apply*/);
void on_update(tl_object_ptr<telegram_api::updateDialogPinned> update, bool /*force_apply*/, Promise<Unit> &&promise);
void on_update(tl_object_ptr<telegram_api::updatePinnedDialogs> update, bool /*force_apply*/,
Promise<Unit> &&promise);
void on_update(tl_object_ptr<telegram_api::updateDialogUnreadMark> update, bool /*force_apply*/,
Promise<Unit> &&promise);
void on_update(tl_object_ptr<telegram_api::updateDialogFilter> update, bool /*force_apply*/);
void on_update(tl_object_ptr<telegram_api::updateDialogFilters> update, bool /*force_apply*/);
void on_update(tl_object_ptr<telegram_api::updateDialogFilterOrder> update, bool /*force_apply*/);
void on_update(tl_object_ptr<telegram_api::updateDialogFilter> update, bool /*force_apply*/, Promise<Unit> &&promise);
void on_update(tl_object_ptr<telegram_api::updateDialogFilters> update, bool /*force_apply*/,
Promise<Unit> &&promise);
void on_update(tl_object_ptr<telegram_api::updateDialogFilterOrder> update, bool /*force_apply*/,
Promise<Unit> &&promise);
void on_update(tl_object_ptr<telegram_api::updateBotInlineQuery> update, bool /*force_apply*/);
void on_update(tl_object_ptr<telegram_api::updateBotInlineSend> update, bool /*force_apply*/);
void on_update(tl_object_ptr<telegram_api::updateBotInlineQuery> update, bool /*force_apply*/,
Promise<Unit> &&promise);
void on_update(tl_object_ptr<telegram_api::updateBotInlineSend> update, bool /*force_apply*/,
Promise<Unit> &&promise);
void on_update(tl_object_ptr<telegram_api::updateBotCallbackQuery> update, bool /*force_apply*/);
void on_update(tl_object_ptr<telegram_api::updateInlineBotCallbackQuery> update, bool /*force_apply*/);
void on_update(tl_object_ptr<telegram_api::updateBotCallbackQuery> update, bool /*force_apply*/,
Promise<Unit> &&promise);
void on_update(tl_object_ptr<telegram_api::updateInlineBotCallbackQuery> update, bool /*force_apply*/,
Promise<Unit> &&promise);
void on_update(tl_object_ptr<telegram_api::updateFavedStickers> update, bool /*force_apply*/);
void on_update(tl_object_ptr<telegram_api::updateFavedStickers> update, bool /*force_apply*/,
Promise<Unit> &&promise);
void on_update(tl_object_ptr<telegram_api::updateSavedGifs> update, bool /*force_apply*/);
void on_update(tl_object_ptr<telegram_api::updateSavedGifs> update, bool /*force_apply*/, Promise<Unit> &&promise);
void on_update(tl_object_ptr<telegram_api::updateConfig> update, bool /*force_apply*/);
void on_update(tl_object_ptr<telegram_api::updateConfig> update, bool /*force_apply*/, Promise<Unit> &&promise);
void on_update(tl_object_ptr<telegram_api::updatePtsChanged> update, bool /*force_apply*/);
void on_update(tl_object_ptr<telegram_api::updatePtsChanged> update, bool /*force_apply*/, Promise<Unit> &&promise);
void on_update(tl_object_ptr<telegram_api::updatePrivacy> update, bool /*force_apply*/);
void on_update(tl_object_ptr<telegram_api::updatePrivacy> update, bool /*force_apply*/, Promise<Unit> &&promise);
void on_update(tl_object_ptr<telegram_api::updateEncryption> update, bool /*force_apply*/);
void on_update(tl_object_ptr<telegram_api::updateNewEncryptedMessage> update, bool force_apply);
void on_update(tl_object_ptr<telegram_api::updateEncryptedMessagesRead> update, bool /*force_apply*/);
void on_update(tl_object_ptr<telegram_api::updateEncryption> update, bool /*force_apply*/, Promise<Unit> &&promise);
void on_update(tl_object_ptr<telegram_api::updateNewEncryptedMessage> update, bool force_apply,
Promise<Unit> &&promise);
void on_update(tl_object_ptr<telegram_api::updateEncryptedMessagesRead> update, bool /*force_apply*/,
Promise<Unit> &&promise);
void on_update(tl_object_ptr<telegram_api::updateNewStickerSet> update, bool /*force_apply*/);
void on_update(tl_object_ptr<telegram_api::updateStickerSets> update, bool /*force_apply*/);
void on_update(tl_object_ptr<telegram_api::updateStickerSetsOrder> update, bool /*force_apply*/);
void on_update(tl_object_ptr<telegram_api::updateReadFeaturedStickers> update, bool /*force_apply*/);
void on_update(tl_object_ptr<telegram_api::updateRecentStickers> update, bool /*force_apply*/);
void on_update(tl_object_ptr<telegram_api::updateNewStickerSet> update, bool /*force_apply*/,
Promise<Unit> &&promise);
void on_update(tl_object_ptr<telegram_api::updateStickerSets> update, bool /*force_apply*/, Promise<Unit> &&promise);
void on_update(tl_object_ptr<telegram_api::updateStickerSetsOrder> update, bool /*force_apply*/,
Promise<Unit> &&promise);
void on_update(tl_object_ptr<telegram_api::updateReadFeaturedStickers> update, bool /*force_apply*/,
Promise<Unit> &&promise);
void on_update(tl_object_ptr<telegram_api::updateRecentStickers> update, bool /*force_apply*/,
Promise<Unit> &&promise);
void on_update(tl_object_ptr<telegram_api::updateBotShippingQuery> update, bool /*force_apply*/);
void on_update(tl_object_ptr<telegram_api::updateBotPrecheckoutQuery> update, bool /*force_apply*/);
void on_update(tl_object_ptr<telegram_api::updateBotShippingQuery> update, bool /*force_apply*/,
Promise<Unit> &&promise);
void on_update(tl_object_ptr<telegram_api::updateBotPrecheckoutQuery> update, bool /*force_apply*/,
Promise<Unit> &&promise);
void on_update(tl_object_ptr<telegram_api::updateBotWebhookJSON> update, bool /*force_apply*/);
void on_update(tl_object_ptr<telegram_api::updateBotWebhookJSONQuery> update, bool /*force_apply*/);
void on_update(tl_object_ptr<telegram_api::updateBotWebhookJSON> update, bool /*force_apply*/,
Promise<Unit> &&promise);
void on_update(tl_object_ptr<telegram_api::updateBotWebhookJSONQuery> update, bool /*force_apply*/,
Promise<Unit> &&promise);
void on_update(tl_object_ptr<telegram_api::updatePhoneCall> update, bool /*force_apply*/);
void on_update(tl_object_ptr<telegram_api::updatePhoneCallSignalingData> update, bool /*force_apply*/);
void on_update(tl_object_ptr<telegram_api::updatePhoneCall> update, bool /*force_apply*/, Promise<Unit> &&promise);
void on_update(tl_object_ptr<telegram_api::updatePhoneCallSignalingData> update, bool /*force_apply*/,
Promise<Unit> &&promise);
void on_update(tl_object_ptr<telegram_api::updateGroupCall> update, bool /*force_apply*/);
void on_update(tl_object_ptr<telegram_api::updateGroupCallParticipants> update, bool /*force_apply*/);
void on_update(tl_object_ptr<telegram_api::updateGroupCall> update, bool /*force_apply*/, Promise<Unit> &&promise);
void on_update(tl_object_ptr<telegram_api::updateGroupCallParticipants> update, bool /*force_apply*/,
Promise<Unit> &&promise);
void on_update(tl_object_ptr<telegram_api::updateContactsReset> update, bool /*force_apply*/);
void on_update(tl_object_ptr<telegram_api::updateContactsReset> update, bool /*force_apply*/,
Promise<Unit> &&promise);
void on_update(tl_object_ptr<telegram_api::updateLangPackTooLong> update, bool /*force_apply*/);
void on_update(tl_object_ptr<telegram_api::updateLangPack> update, bool /*force_apply*/);
void on_update(tl_object_ptr<telegram_api::updateLangPackTooLong> update, bool /*force_apply*/,
Promise<Unit> &&promise);
void on_update(tl_object_ptr<telegram_api::updateLangPack> update, bool /*force_apply*/, Promise<Unit> &&promise);
void on_update(tl_object_ptr<telegram_api::updateGeoLiveViewed> update, bool /*force_apply*/);
void on_update(tl_object_ptr<telegram_api::updateGeoLiveViewed> update, bool /*force_apply*/,
Promise<Unit> &&promise);
void on_update(tl_object_ptr<telegram_api::updateMessagePoll> update, bool /*force_apply*/);
void on_update(tl_object_ptr<telegram_api::updateMessagePollVote> update, bool /*force_apply*/);
void on_update(tl_object_ptr<telegram_api::updateMessagePoll> update, bool /*force_apply*/, Promise<Unit> &&promise);
void on_update(tl_object_ptr<telegram_api::updateMessagePollVote> update, bool /*force_apply*/,
Promise<Unit> &&promise);
void on_update(tl_object_ptr<telegram_api::updateNewScheduledMessage> update, bool /*force_apply*/);
void on_update(tl_object_ptr<telegram_api::updateDeleteScheduledMessages> update, bool /*force_apply*/);
void on_update(tl_object_ptr<telegram_api::updateNewScheduledMessage> update, bool /*force_apply*/,
Promise<Unit> &&promise);
void on_update(tl_object_ptr<telegram_api::updateDeleteScheduledMessages> update, bool /*force_apply*/,
Promise<Unit> &&promise);
void on_update(tl_object_ptr<telegram_api::updateLoginToken> update, bool /*force_apply*/);
void on_update(tl_object_ptr<telegram_api::updateLoginToken> update, bool /*force_apply*/, Promise<Unit> &&promise);
void on_update(tl_object_ptr<telegram_api::updateChannelParticipant> update, bool /*force_apply*/);
void on_update(tl_object_ptr<telegram_api::updateChannelParticipant> update, bool /*force_apply*/,
Promise<Unit> &&promise);
// unsupported updates
void on_update(tl_object_ptr<telegram_api::updateTheme> update, bool /*force_apply*/);
void on_update(tl_object_ptr<telegram_api::updateTheme> update, bool /*force_apply*/, Promise<Unit> &&promise);
};
} // namespace td

View File

@ -215,7 +215,8 @@ tl_object_ptr<telegram_api::InputMedia> VideoNotesManager::get_input_media(
return nullptr;
}
if (file_view.has_remote_location() && !file_view.main_remote_location().is_web() && input_file == nullptr) {
return make_tl_object<telegram_api::inputMediaDocument>(0, file_view.main_remote_location().as_input_document(), 0);
return make_tl_object<telegram_api::inputMediaDocument>(0, file_view.main_remote_location().as_input_document(), 0,
string());
}
if (file_view.has_url()) {
return make_tl_object<telegram_api::inputMediaDocumentExternal>(0, file_view.url(), 0);

View File

@ -268,7 +268,7 @@ tl_object_ptr<telegram_api::InputMedia> VideosManager::get_input_media(
flags |= telegram_api::inputMediaDocument::TTL_SECONDS_MASK;
}
return make_tl_object<telegram_api::inputMediaDocument>(flags, file_view.main_remote_location().as_input_document(),
ttl);
ttl, string());
}
if (file_view.has_url()) {
int32 flags = 0;

View File

@ -174,7 +174,8 @@ tl_object_ptr<telegram_api::InputMedia> VoiceNotesManager::get_input_media(
return nullptr;
}
if (file_view.has_remote_location() && !file_view.main_remote_location().is_web() && input_file == nullptr) {
return make_tl_object<telegram_api::inputMediaDocument>(0, file_view.main_remote_location().as_input_document(), 0);
return make_tl_object<telegram_api::inputMediaDocument>(0, file_view.main_remote_location().as_input_document(), 0,
string());
}
if (file_view.has_url()) {
return make_tl_object<telegram_api::inputMediaDocumentExternal>(0, file_view.url(), 0);

View File

@ -2848,12 +2848,13 @@ class CliClient final : public Actor {
fingerprints.push_back(td_api::make_object<td_api::groupCallPayloadFingerprint>("h2", "s2", "fingerprint2"));
send_request(td_api::make_object<td_api::joinGroupCall>(
as_group_call_id(args),
td_api::make_object<td_api::groupCallPayload>("ufrag", "pwd", std::move(fingerprints)), 123, true));
td_api::make_object<td_api::groupCallPayload>("ufrag", "pwd", std::move(fingerprints)), group_call_source_,
true));
} else if (op == "jgcc") {
send_request(td_api::make_object<td_api::joinGroupCall>(as_group_call_id(args), nullptr, 123, true));
send_request(td_api::make_object<td_api::joinGroupCall>(as_group_call_id(args), nullptr, 0, true));
} else if (op == "tgcmnp" || op == "tgcmnpe") {
send_request(
td_api::make_object<td_api::toggleGroupCallMuteNewParticipants>(as_group_call_id(args), op == "tgcmnme"));
td_api::make_object<td_api::toggleGroupCallMuteNewParticipants>(as_group_call_id(args), op == "tgcmnpe"));
} else if (op == "sgcpis") {
string group_call_id;
string source;
@ -3595,8 +3596,8 @@ class CliClient final : public Actor {
string sticker_path;
std::tie(chat_id, sticker_path) = split(args);
send_message(chat_id,
td_api::make_object<td_api::inputMessageSticker>(as_input_file(sticker_path), nullptr, 0, 0));
send_message(chat_id, td_api::make_object<td_api::inputMessageSticker>(as_input_file(sticker_path), nullptr, 0, 0,
string()));
} else if (op == "sstt") {
string chat_id;
string sticker_path;
@ -3604,14 +3605,17 @@ class CliClient final : public Actor {
std::tie(chat_id, args) = split(args);
std::tie(sticker_path, thumbnail_path) = split(args);
send_message(chat_id, td_api::make_object<td_api::inputMessageSticker>(as_input_file(sticker_path),
as_input_thumbnail(thumbnail_path), 0, 0));
send_message(chat_id, td_api::make_object<td_api::inputMessageSticker>(
as_input_file(sticker_path), as_input_thumbnail(thumbnail_path), 0, 0, string()));
} else if (op == "ssid") {
string chat_id;
string file_id;
std::tie(chat_id, file_id) = split(args);
string emoji;
std::tie(chat_id, args) = split(args);
std::tie(file_id, emoji) = split(args);
send_message(chat_id, td_api::make_object<td_api::inputMessageSticker>(as_input_file_id(file_id), nullptr, 0, 0));
send_message(chat_id,
td_api::make_object<td_api::inputMessageSticker>(as_input_file_id(file_id), nullptr, 0, 0, emoji));
} else if (op == "sv" || op == "svttl") {
string chat_id;
string video_path;
@ -3898,6 +3902,9 @@ class CliClient final : public Actor {
} else if (status_str == "addadmin") {
status = td_api::make_object<td_api::chatMemberStatusAdministrator>("anon", false, false, false, false, false,
false, false, false, true, false, false);
} else if (status_str == "calladmin") {
status = td_api::make_object<td_api::chatMemberStatusAdministrator>("anon", false, false, false, false, false,
false, false, false, false, true, false);
} else if (status_str == "admin") {
status = td_api::make_object<td_api::chatMemberStatusAdministrator>("", true, true, true, true, true, true,
true, true, true, false, false);
@ -4551,6 +4558,8 @@ class CliClient final : public Actor {
int api_id_ = 0;
std::string api_hash_;
int32 group_call_source_ = Random::fast(1, 1000000000);
static std::atomic<uint64> cpu_counter_;
};
CliClient *CliClient::instance_ = nullptr;

View File

@ -8,6 +8,7 @@
#include "td/tl/TlObject.h"
#include "td/utils/logging.h"
#include "td/utils/UInt.h"
#include <cstdint>
@ -21,8 +22,10 @@ class TlFetchBoxed {
public:
template <class ParserT>
static auto parse(ParserT &parser) -> decltype(Func::parse(parser)) {
if (parser.fetch_int() != constructor_id) {
parser.set_error("Wrong constructor found");
auto parsed_constructor_id = parser.fetch_int();
if (parsed_constructor_id != constructor_id) {
parser.set_error(PSTRING() << "Wrong constructor " << parsed_constructor_id << " found instead of "
<< constructor_id);
return decltype(Func::parse(parser))();
}
return Func::parse(parser);