diff --git a/Telegram/SourceFiles/calls/group/calls_group_common.cpp b/Telegram/SourceFiles/calls/group/calls_group_common.cpp index eabcca6a35..82ca38f25a 100644 --- a/Telegram/SourceFiles/calls/group/calls_group_common.cpp +++ b/Telegram/SourceFiles/calls/group/calls_group_common.cpp @@ -281,7 +281,8 @@ void ShowConferenceCallLinkBox( MTPphone_ToggleGroupCallSettings( MTP_flags(Flag::f_reset_invite_hash), call->input(), - MTPbool()) // join_muted + MTPBool(), // join_muted + MTPBool()) // messages_enabled ).done([=](const MTPUpdates &result) { call->session().api().applyUpdates(result); ShowConferenceCallLinkBox(show, call, args); diff --git a/Telegram/SourceFiles/calls/group/calls_group_message_encryption.cpp b/Telegram/SourceFiles/calls/group/calls_group_message_encryption.cpp index 96b81bec37..04fd654e93 100644 --- a/Telegram/SourceFiles/calls/group/calls_group_message_encryption.cpp +++ b/Telegram/SourceFiles/calls/group/calls_group_message_encryption.cpp @@ -309,20 +309,23 @@ template } // namespace -QByteArray SerializeMessage(const MTPTextWithEntities &text) { +QByteArray SerializeMessage(const PreparedMessage &data) { return Serialize(Object("groupCallMessage", { + Value( + "random_id", + String(QByteArray::number(int64(data.randomId)))), Value( "message", Object("textWithEntities", { - Value("text", String(text.data().vtext().v)), + Value("text", String(data.message.data().vtext().v)), Value( "entities", - Array(Entities(text.data().ventities().v))), + Array(Entities(data.message.data().ventities().v))), })), })); } -std::optional DeserializeMessage( +std::optional DeserializeMessage( const QByteArray &data) { auto error = QJsonParseError(); auto document = QJsonDocument::fromJson(data, &error); @@ -335,6 +338,10 @@ std::optional DeserializeMessage( if (Unsupported(groupCallMessage, "groupCallMessage")) { return {}; } + const auto randomId = GetLong(groupCallMessage, "random_id").value_or(0); + if (!randomId) { + return {}; + } const auto message = groupCallMessage["message"].toObject(); if (Unsupported(message, "textWithEntities")) { return {}; @@ -349,9 +356,12 @@ std::optional DeserializeMessage( return {}; } const auto entities = GetEntities(text, maybeEntities->toArray()); - return MTP_textWithEntities( - MTP_string(text), - MTP_vector(entities)); + return PreparedMessage{ + .randomId = randomId, + .message = MTP_textWithEntities( + MTP_string(text), + MTP_vector(entities)), + }; } } // namespace Calls::Group diff --git a/Telegram/SourceFiles/calls/group/calls_group_message_encryption.h b/Telegram/SourceFiles/calls/group/calls_group_message_encryption.h index ec0af2b193..a71dd2894c 100644 --- a/Telegram/SourceFiles/calls/group/calls_group_message_encryption.h +++ b/Telegram/SourceFiles/calls/group/calls_group_message_encryption.h @@ -9,8 +9,13 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL namespace Calls::Group { -[[nodiscard]] QByteArray SerializeMessage(const MTPTextWithEntities &text); -[[nodiscard]] std::optional DeserializeMessage( +struct PreparedMessage { + uint64 randomId = 0; + MTPTextWithEntities message; +}; + +[[nodiscard]] QByteArray SerializeMessage(const PreparedMessage &data); +[[nodiscard]] std::optional DeserializeMessage( const QByteArray &data); } // namespace Calls::Group diff --git a/Telegram/SourceFiles/calls/group/calls_group_messages.cpp b/Telegram/SourceFiles/calls/group/calls_group_messages.cpp index 8281f672ec..a73643ebfd 100644 --- a/Telegram/SourceFiles/calls/group/calls_group_messages.cpp +++ b/Telegram/SourceFiles/calls/group/calls_group_messages.cpp @@ -9,6 +9,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "apiwrap.h" #include "api/api_text_entities.h" +#include "base/random.h" #include "base/unixtime.h" #include "calls/group/calls_group_call.h" #include "calls/group/calls_group_message_encryption.h" @@ -63,10 +64,10 @@ void Messages::send(TextWithTags text) { prepared.entities, Api::ConvertOption::SkipLocal))); - const auto id = ++_autoincrementId; + const auto randomId = base::RandomValue(); const auto from = _call->peer()->session().user(); _messages.push_back({ - .id = id, + .randomId = randomId, .peer = from, .text = std::move(prepared), }); @@ -74,14 +75,15 @@ void Messages::send(TextWithTags text) { if (!_call->conference()) { _api->request(MTPphone_SendGroupCallMessage( _call->inputCall(), + MTP_long(randomId), serialized )).done([=](const MTPBool &, const MTP::Response &response) { - sent(id, response); + sent(randomId, response); }).fail([=](const MTP::Error &, const MTP::Response &response) { - failed(id, response); + failed(randomId, response); }).send(); } else { - const auto bytes = SerializeMessage(serialized); + const auto bytes = SerializeMessage({ randomId, serialized }); auto v = std::vector(bytes.size()); bytes::copy(bytes::make_span(v), bytes::make_span(bytes)); @@ -93,9 +95,9 @@ void Messages::send(TextWithTags text) { _call->inputCall(), MTP_bytes(bytes::make_span(encrypted)) )).done([=](const MTPBool &, const MTP::Response &response) { - sent(id, response); + sent(randomId, response); }).fail([=](const MTP::Error &, const MTP::Response &response) { - failed(id, response); + failed(randomId, response); }).send(); } checkDestroying(true); @@ -105,7 +107,7 @@ void Messages::received(const MTPDupdateGroupCallMessage &data) { if (!ready()) { return; } - received(data.vfrom_id(), data.vmessage()); + received(data.vrandom_id().v, data.vfrom_id(), data.vmessage()); pushChanges(); } @@ -129,17 +131,22 @@ void Messages::received(const MTPDupdateGroupCallEncryptedMessage &data) { LOG(("API Error: Can't parse decrypted message")); return; } - received(fromId, *deserialized, true); + received(deserialized->randomId, fromId, deserialized->message, true); pushChanges(); } void Messages::received( + uint64 randomId, const MTPPeer &from, const MTPTextWithEntities &message, bool checkCustomEmoji) { const auto peer = _call->peer(); - if (peerFromMTP(from) == peer->session().userPeerId()) { - // Our own we add only locally. + const auto i = ranges::find(_messages, randomId, &Message::randomId); + if (i != end(_messages)) { + if (peerFromMTP(from) == peer->session().userPeerId() && !i->date) { + i->date = base::unixtime::now(); + checkDestroying(true); + } return; } auto allowedEntityTypes = std::vector{ @@ -155,9 +162,8 @@ void Messages::received( if (checkCustomEmoji && !peer->isSelf() && !peer->isPremium()) { allowedEntityTypes.pop_back(); } - const auto id = ++_autoincrementId; _messages.push_back({ - .id = id, + .randomId = randomId, .date = base::unixtime::now(), .peer = peer->owner().peer(peerFromMTP(from)), .text = Ui::Text::Filtered( @@ -215,17 +221,17 @@ void Messages::pushChanges() { _changes.fire_copy(_messages); } -void Messages::sent(int id, const MTP::Response &response) { - const auto i = ranges::find(_messages, id, &Message::id); - if (i != end(_messages)) { +void Messages::sent(uint64 randomId, const MTP::Response &response) { + const auto i = ranges::find(_messages, randomId, &Message::randomId); + if (i != end(_messages) && !i->date) { i->date = Api::UnixtimeFromMsgId(response.outerMsgId); checkDestroying(true); } } -void Messages::failed(int id, const MTP::Response &response) { - const auto i = ranges::find(_messages, id, &Message::id); - if (i != end(_messages)) { +void Messages::failed(uint64 randomId, const MTP::Response &response) { + const auto i = ranges::find(_messages, randomId, &Message::randomId); + if (i != end(_messages) && !i->date) { i->date = Api::UnixtimeFromMsgId(response.outerMsgId); i->failed = true; checkDestroying(true); diff --git a/Telegram/SourceFiles/calls/group/calls_group_messages.h b/Telegram/SourceFiles/calls/group/calls_group_messages.h index 909d688145..c3ac582b18 100644 --- a/Telegram/SourceFiles/calls/group/calls_group_messages.h +++ b/Telegram/SourceFiles/calls/group/calls_group_messages.h @@ -25,7 +25,7 @@ struct Response; namespace Calls::Group { struct Message { - int id = 0; + uint64 randomId = 0; TimeId date = 0; not_null peer; TextWithEntities text; @@ -50,11 +50,12 @@ private: void checkDestroying(bool afterChanges = false); void received( + uint64 randomId, const MTPPeer &from, const MTPTextWithEntities &message, bool checkCustomEmoji = false); - void sent(int id, const MTP::Response &response); - void failed(int id, const MTP::Response &response); + void sent(uint64 randomId, const MTP::Response &response); + void failed(uint64 randomId, const MTP::Response &response); const not_null _call; const not_null _api; @@ -67,7 +68,6 @@ private: std::vector _messages; rpl::event_stream> _changes; - int _autoincrementId = 0; TimeId _ttl = 0; rpl::lifetime _lifetime; diff --git a/Telegram/SourceFiles/calls/group/calls_group_messages_ui.cpp b/Telegram/SourceFiles/calls/group/calls_group_messages_ui.cpp index d55fd60152..a034dd5cba 100644 --- a/Telegram/SourceFiles/calls/group/calls_group_messages_ui.cpp +++ b/Telegram/SourceFiles/calls/group/calls_group_messages_ui.cpp @@ -101,7 +101,7 @@ void ReceiveOnlyWheelEvents(not_null scroll) { } // namespace struct MessagesUi::MessageView { - int id = 0; + uint64 id = 0; PeerData *from = nullptr; Ui::Animations::Simple toggleAnimation; Ui::Animations::Simple sentAnimation; @@ -150,7 +150,11 @@ void MessagesUi::setupList(rpl::producer> messages) { for (auto &entry : _views) { if (!entry.removed) { const auto id = entry.id; - const auto i = ranges::find(from, till, id, &Message::id); + const auto i = ranges::find( + from, + till, + id, + &Message::randomId); if (i == till) { toggleMessage(entry, false); continue; @@ -168,7 +172,7 @@ void MessagesUi::setupList(rpl::producer> messages) { } auto addedSendingToBottom = false; for (auto i = from; i != till; ++i) { - if (!ranges::contains(_views, i->id, &MessageView::id)) { + if (!ranges::contains(_views, i->randomId, &MessageView::id)) { if (i + 1 == till && !i->date) { addedSendingToBottom = true; } @@ -277,7 +281,7 @@ void MessagesUi::toggleMessage(MessageView &entry, bool shown) { repaintMessage(id); } -void MessagesUi::repaintMessage(int id) { +void MessagesUi::repaintMessage(uint64 id) { auto i = ranges::find(_views, id, &MessageView::id); if (i == end(_views)) { return; @@ -327,7 +331,7 @@ void MessagesUi::appendMessage(const Message &data) { } auto &entry = _views.emplace_back(); - const auto id = entry.id = data.id; + const auto id = entry.id = data.randomId; const auto repaint = [=] { repaintMessage(id); }; diff --git a/Telegram/SourceFiles/calls/group/calls_group_messages_ui.h b/Telegram/SourceFiles/calls/group/calls_group_messages_ui.h index a4d9d88a61..c6d74ed17d 100644 --- a/Telegram/SourceFiles/calls/group/calls_group_messages_ui.h +++ b/Telegram/SourceFiles/calls/group/calls_group_messages_ui.h @@ -56,7 +56,7 @@ private: void updateMessageSize(MessageView &entry); bool updateMessageHeight(MessageView &entry); void animateMessageSent(MessageView &entry); - void repaintMessage(int id); + void repaintMessage(uint64 id); void recountHeights(std::vector::iterator i, int top); void appendMessage(const Message &data); void checkReactionContent( diff --git a/Telegram/SourceFiles/calls/group/calls_group_settings.cpp b/Telegram/SourceFiles/calls/group/calls_group_settings.cpp index cb70c06e6d..007908d117 100644 --- a/Telegram/SourceFiles/calls/group/calls_group_settings.cpp +++ b/Telegram/SourceFiles/calls/group/calls_group_settings.cpp @@ -84,7 +84,8 @@ void SaveCallJoinMuted( peer->session().api().request(MTPphone_ToggleGroupCallSettings( MTP_flags(MTPphone_ToggleGroupCallSettings::Flag::f_join_muted), call->input(), - MTP_bool(joinMuted) + MTP_bool(joinMuted), + MTPBool() // messages_enabled )).send(); } diff --git a/Telegram/SourceFiles/mtproto/scheme/api.tl b/Telegram/SourceFiles/mtproto/scheme/api.tl index dba3bef7f9..19a425a4ba 100644 --- a/Telegram/SourceFiles/mtproto/scheme/api.tl +++ b/Telegram/SourceFiles/mtproto/scheme/api.tl @@ -442,7 +442,7 @@ updateGroupCallChainBlocks#a477288f call:InputGroupCall sub_chain_id:int blocks: updateReadMonoForumInbox#77b0e372 channel_id:long saved_peer_id:Peer read_max_id:int = Update; updateReadMonoForumOutbox#a4a79376 channel_id:long saved_peer_id:Peer read_max_id:int = Update; updateMonoForumNoPaidException#9f812b08 flags:# exception:flags.0?true channel_id:long saved_peer_id:Peer = Update; -updateGroupCallMessage#96fb0840 call:InputGroupCall from_id:Peer message:TextWithEntities = Update; +updateGroupCallMessage#78c314e0 call:InputGroupCall from_id:Peer random_id:long message:TextWithEntities = Update; updateGroupCallEncryptedMessage#c957a766 call:InputGroupCall from_id:Peer encrypted_message:bytes = Update; updatePinnedForumTopic#683b2c52 flags:# pinned:flags.0?true peer:Peer topic_id:int = Update; updatePinnedForumTopics#def143d0 flags:# peer:Peer order:flags.0?Vector = Update; @@ -1359,7 +1359,7 @@ peerBlocked#e8fd8014 peer_id:Peer date:int = PeerBlocked; stats.messageStats#7fe91c14 views_graph:StatsGraph reactions_by_emotion_graph:StatsGraph = stats.MessageStats; groupCallDiscarded#7780bcb4 id:long access_hash:long duration:int = GroupCall; -groupCall#553b0ba1 flags:# join_muted:flags.1?true can_change_join_muted:flags.2?true join_date_asc:flags.6?true schedule_start_subscribed:flags.8?true can_start_video:flags.9?true record_video_active:flags.11?true rtmp_stream:flags.12?true listeners_hidden:flags.13?true conference:flags.14?true creator:flags.15?true id:long access_hash:long participants_count:int title:flags.3?string stream_dc_id:flags.4?int record_start_date:flags.5?int schedule_date:flags.7?int unmuted_video_count:flags.10?int unmuted_video_limit:int version:int invite_link:flags.16?string = GroupCall; +groupCall#553b0ba1 flags:# join_muted:flags.1?true can_change_join_muted:flags.2?true join_date_asc:flags.6?true schedule_start_subscribed:flags.8?true can_start_video:flags.9?true record_video_active:flags.11?true rtmp_stream:flags.12?true listeners_hidden:flags.13?true conference:flags.14?true creator:flags.15?true messages_enabled:flags.17?true can_change_messages_enabled:flags.18?true min:flags.19?true id:long access_hash:long participants_count:int title:flags.3?string stream_dc_id:flags.4?int record_start_date:flags.5?int schedule_date:flags.7?int unmuted_video_count:flags.10?int unmuted_video_limit:int version:int invite_link:flags.16?string = GroupCall; inputGroupCall#d8aa840f id:long access_hash:long = InputGroupCall; inputGroupCallSlug#fe06823f slug:string = InputGroupCall; @@ -1578,7 +1578,7 @@ stickerKeyword#fcfeb29c document_id:long keyword:Vector = StickerKeyword username#b4073647 flags:# editable:flags.0?true active:flags.1?true username:string = Username; forumTopicDeleted#23f109b id:int = ForumTopic; -forumTopic#71701da9 flags:# my:flags.1?true closed:flags.2?true pinned:flags.3?true short:flags.5?true hidden:flags.6?true title_missing:flags.7?true id:int date:int title:string icon_color:int icon_emoji_id:flags.0?long top_message:int read_inbox_max_id:int read_outbox_max_id:int unread_count:int unread_mentions_count:int unread_reactions_count:int from_id:Peer notify_settings:PeerNotifySettings draft:flags.4?DraftMessage = ForumTopic; +forumTopic#cdff0eca flags:# my:flags.1?true closed:flags.2?true pinned:flags.3?true short:flags.5?true hidden:flags.6?true title_missing:flags.7?true id:int date:int peer:Peer title:string icon_color:int icon_emoji_id:flags.0?long top_message:int read_inbox_max_id:int read_outbox_max_id:int unread_count:int unread_mentions_count:int unread_reactions_count:int from_id:Peer notify_settings:PeerNotifySettings draft:flags.4?DraftMessage = ForumTopic; messages.forumTopics#367617d3 flags:# order_by_create_date:flags.0?true count:int topics:Vector messages:Vector chats:Vector users:Vector pts:int = messages.ForumTopics; @@ -2699,7 +2699,7 @@ phone.joinGroupCall#8fb53057 flags:# muted:flags.0?true video_stopped:flags.2?tr phone.leaveGroupCall#500377f9 call:InputGroupCall source:int = Updates; phone.inviteToGroupCall#7b393160 call:InputGroupCall users:Vector = Updates; phone.discardGroupCall#7a777135 call:InputGroupCall = Updates; -phone.toggleGroupCallSettings#74bbb43d flags:# reset_invite_hash:flags.1?true call:InputGroupCall join_muted:flags.0?Bool = Updates; +phone.toggleGroupCallSettings#e9723804 flags:# reset_invite_hash:flags.1?true call:InputGroupCall join_muted:flags.0?Bool messages_enabled:flags.2?Bool = Updates; phone.getGroupCall#41845db call:InputGroupCall limit:int = phone.GroupCall; phone.getGroupParticipants#c558d8ab call:InputGroupCall ids:Vector sources:Vector offset:string limit:int = phone.GroupParticipants; phone.checkGroupCall#b59cf977 call:InputGroupCall sources:Vector = Vector; @@ -2722,7 +2722,7 @@ phone.sendConferenceCallBroadcast#c6701900 call:InputGroupCall block:bytes = Upd phone.inviteConferenceCallParticipant#bcf22685 flags:# video:flags.0?true call:InputGroupCall user_id:InputUser = Updates; phone.declineConferenceCallInvite#3c479971 msg_id:int = Updates; phone.getGroupCallChainBlocks#ee9f88a6 call:InputGroupCall sub_chain_id:int offset:int limit:int = Updates; -phone.sendGroupCallMessage#db608048 call:InputGroupCall message:TextWithEntities = Bool; +phone.sendGroupCallMessage#87893014 call:InputGroupCall random_id:long message:TextWithEntities = Bool; phone.sendGroupCallEncryptedMessage#e5afa56d call:InputGroupCall encrypted_message:bytes = Bool; langpack.getLangPack#f2f2330a lang_pack:string lang_code:string = LangPackDifference;