diff --git a/td/generate/scheme/td_api.tl b/td/generate/scheme/td_api.tl index 9bf3120f0..48270c432 100644 --- a/td/generate/scheme/td_api.tl +++ b/td/generate/scheme/td_api.tl @@ -566,13 +566,14 @@ basicGroupFullInfo photo:chatPhoto description:string creator_user_id:int32 memb //@member_count Number of members in the supergroup or channel; 0 if unknown. Currently it is guaranteed to be known only if the supergroup or channel was received through searchPublicChats, searchChatsNearby, getInactiveSupergroupChats, getSuitableDiscussionChats, getGroupsInCommon, or getUserPrivacySettingRules //@has_linked_chat True, if the channel has a discussion group, or the supergroup is the designated discussion group for a channel //@has_location True, if the supergroup is connected to a location, i.e. the supergroup is a location-based supergroup +//@has_active_call True, if the supergroup has active group call //@sign_messages True, if messages sent to the channel should contain information about the sender. This field is only applicable to channels //@is_slow_mode_enabled True, if the slow mode is enabled in the supergroup //@is_channel True, if the supergroup is a channel //@is_verified True, if the supergroup or channel is verified //@restriction_reason If non-empty, contains a human-readable description of the reason why access to this supergroup or channel must be restricted //@is_scam True, if many users reported this supergroup as a scam -supergroup id:int32 username:string date:int32 status:ChatMemberStatus member_count:int32 has_linked_chat:Bool has_location:Bool sign_messages:Bool is_slow_mode_enabled:Bool is_channel:Bool is_verified:Bool restriction_reason:string is_scam:Bool = Supergroup; +supergroup id:int32 username:string date:int32 status:ChatMemberStatus member_count:int32 has_linked_chat:Bool has_location:Bool has_active_call:Bool sign_messages:Bool is_slow_mode_enabled:Bool is_channel:Bool is_verified:Bool restriction_reason:string is_scam:Bool = Supergroup; //@description Contains full information about a supergroup or channel //@photo Chat photo; may be null @@ -1627,8 +1628,8 @@ messageInvoice title:string description:string photo:photo currency:string total //@description A message with information about an ended call @is_video True, if the call was a video call @discard_reason Reason why the call was discarded @duration Call duration, in seconds messageCall is_video:Bool discard_reason:CallDiscardReason duration:int32 = MessageContent; -//@description A message with information about a group call @group_call_id Group call identifier -messageGroupCall group_call_id:string = MessageContent; +//@description A message with information about a group call @group_call_id Group call identifier @duration Call duration; for finished calls only +messageGroupCall group_call_id:string duration:int32 = MessageContent; //@description A message with information about an invite to a group call @group_call_id Group call identifier @user_id Invited user identifier messageInviteToGroupCall group_call_id:string user_id:int32 = MessageContent; @@ -2057,6 +2058,10 @@ callStateDiscarded reason:CallDiscardReason need_rating:Bool need_debug_informat callStateError error:error = CallState; +//@description Describes a group call @id Group call identifier @is_active True, if the call is active @member_count Number of members in the group call @duration Call duration; for ended calls only +groupCall id:string is_active:Bool member_count:int32 duration:int32 = GroupCall; + + //@class CallProblem @description Describes the exact type of a problem with a call //@description The user heard their own voice @@ -3334,6 +3339,9 @@ updateFileGenerationStop generation_id:int64 = Update; //@description New call was created or information about a call was updated @call New data about a call updateCall call:call = Update; +//@description Information about a group call was updated @group_call New data about the call +updateGroupCall group_call:groupCall = Update; + //@description New call signaling data arrived @call_id The call identifier @data The data updateNewCallSignalingData call_id:int32 data:bytes = Update; diff --git a/td/generate/scheme/td_api.tlo b/td/generate/scheme/td_api.tlo index 6c3fc23bb..d2a084221 100644 Binary files a/td/generate/scheme/td_api.tlo and b/td/generate/scheme/td_api.tlo differ diff --git a/td/telegram/ContactsManager.cpp b/td/telegram/ContactsManager.cpp index e0693423d..ced796ecd 100644 --- a/td/telegram/ContactsManager.cpp +++ b/td/telegram/ContactsManager.cpp @@ -3559,6 +3559,7 @@ void ContactsManager::Channel::store(StorerT &storer) const { STORE_FLAG(has_location); STORE_FLAG(is_slow_mode_enabled); STORE_FLAG(has_restriction_reasons); + STORE_FLAG(has_active_group_call); END_STORE_FLAGS(); store(status, storer); @@ -3624,6 +3625,7 @@ void ContactsManager::Channel::parse(ParserT &parser) { PARSE_FLAG(has_location); PARSE_FLAG(is_slow_mode_enabled); PARSE_FLAG(has_restriction_reasons); + PARSE_FLAG(has_active_group_call); END_PARSE_FLAGS(); if (use_new_rights) { @@ -3691,6 +3693,7 @@ void ContactsManager::ChannelFull::store(StorerT &storer) const { bool is_slow_mode_delay_active = slow_mode_next_send_date != 0; bool has_stats_dc_id = stats_dc_id.is_exact(); bool has_photo = !photo.is_empty(); + bool has_active_group_call_id = active_group_call_id.is_valid(); BEGIN_STORE_FLAGS(); STORE_FLAG(has_description); STORE_FLAG(has_administrator_count); @@ -3715,6 +3718,7 @@ void ContactsManager::ChannelFull::store(StorerT &storer) const { STORE_FLAG(has_photo); STORE_FLAG(is_can_view_statistics_inited); STORE_FLAG(can_view_statistics); + STORE_FLAG(has_active_group_call_id); END_STORE_FLAGS(); if (has_description) { store(description, storer); @@ -3763,6 +3767,9 @@ void ContactsManager::ChannelFull::store(StorerT &storer) const { if (has_photo) { store(photo, storer); } + if (has_active_group_call_id) { + store(active_group_call_id, storer); + } } template @@ -3784,6 +3791,7 @@ void ContactsManager::ChannelFull::parse(ParserT &parser) { bool is_slow_mode_delay_active; bool has_stats_dc_id; bool has_photo; + bool has_active_group_call_id; BEGIN_PARSE_FLAGS(); PARSE_FLAG(has_description); PARSE_FLAG(has_administrator_count); @@ -3808,6 +3816,7 @@ void ContactsManager::ChannelFull::parse(ParserT &parser) { PARSE_FLAG(has_photo); PARSE_FLAG(is_can_view_statistics_inited); PARSE_FLAG(can_view_statistics); + PARSE_FLAG(has_active_group_call_id); END_PARSE_FLAGS(); if (has_description) { parse(description, parser); @@ -3856,6 +3865,9 @@ void ContactsManager::ChannelFull::parse(ParserT &parser) { if (has_photo) { parse(photo, parser); } + if (has_active_group_call_id) { + parse(active_group_call_id, parser); + } if (legacy_can_view_statistics) { LOG(DEBUG) << "Ignore legacy can view statistics flag"; @@ -9532,6 +9544,10 @@ void ContactsManager::on_get_chat_full(tl_object_ptr &&c LOG(ERROR) << "Receive can_view_statistics == true, but invalid statistics DC ID in " << channel_id; can_view_statistics = false; } + InputGroupCallId group_call_id; + if (channel_full->call_ != nullptr) { + group_call_id = InputGroupCallId(channel_full->call_); + } channel->repair_request_version = 0; channel->expires_at = Time::now() + CHANNEL_FULL_EXPIRE_TIME; @@ -9568,6 +9584,17 @@ void ContactsManager::on_get_chat_full(tl_object_ptr &&c channel->need_save_to_database = true; } + if (channel->active_group_call_id != group_call_id) { + channel->active_group_call_id = group_call_id; + bool has_active_group_call = group_call_id.is_valid(); + if (c->has_active_group_call != has_active_group_call) { + LOG(ERROR) << "Receive invalid has_active_group_call flag " << c->has_active_group_call; + c->has_active_group_call = has_active_group_call; + c->is_changed = true; + update_channel(c, channel_id); + } + } + on_update_channel_full_photo( channel, channel_id, get_photo(td_->file_manager_.get(), std::move(channel_full->chat_photo_), DialogId(channel_id))); @@ -13822,6 +13849,7 @@ void ContactsManager::on_chat_update(telegram_api::channel &channel, const char bool has_linked_channel = (channel.flags_ & CHANNEL_FLAG_HAS_LINKED_CHAT) != 0; bool has_location = (channel.flags_ & CHANNEL_FLAG_HAS_LOCATION) != 0; + bool has_active_group_call = (channel.flags_ & CHANNEL_FLAG_HAS_ACTIVE_GROUP_CALL) != 0; bool sign_messages = (channel.flags_ & CHANNEL_FLAG_SIGN_MESSAGES) != 0; bool is_slow_mode_enabled = (channel.flags_ & CHANNEL_FLAG_IS_SLOW_MODE_ENABLED) != 0; bool is_megagroup = (channel.flags_ & CHANNEL_FLAG_IS_MEGAGROUP) != 0; @@ -13926,10 +13954,12 @@ void ContactsManager::on_chat_update(telegram_api::channel &channel, const char bool need_invalidate_channel_full = false; if (c->has_linked_channel != has_linked_channel || c->has_location != has_location || - c->sign_messages != sign_messages || c->is_megagroup != is_megagroup || c->is_verified != is_verified || + c->has_active_group_call != has_active_group_call || c->sign_messages != sign_messages || + c->is_megagroup != is_megagroup || c->is_verified != is_verified || c->restriction_reasons != restriction_reasons || c->is_scam != is_scam) { c->has_linked_channel = has_linked_channel; c->has_location = has_location; + c->has_active_group_call = has_active_group_call; c->sign_messages = sign_messages; c->is_slow_mode_enabled = is_slow_mode_enabled; c->is_megagroup = is_megagroup; @@ -13990,6 +14020,7 @@ void ContactsManager::on_chat_update(telegram_api::channelForbidden &channel, co tl_object_ptr banned_rights; // == nullptr on_update_channel_default_permissions(c, channel_id, get_restricted_rights(banned_rights)); + bool has_active_group_call = false; bool sign_messages = false; bool is_slow_mode_enabled = false; bool is_megagroup = (channel.flags_ & CHANNEL_FLAG_IS_MEGAGROUP) != 0; @@ -14013,11 +14044,12 @@ void ContactsManager::on_chat_update(telegram_api::channelForbidden &channel, co } bool need_invalidate_channel_full = false; - if (c->sign_messages != sign_messages || c->is_slow_mode_enabled != is_slow_mode_enabled || - c->is_megagroup != is_megagroup || c->is_verified != is_verified || !c->restriction_reasons.empty() || - c->is_scam != is_scam) { + if (c->has_active_group_call != has_active_group_call || c->sign_messages != sign_messages || + c->is_slow_mode_enabled != is_slow_mode_enabled || c->is_megagroup != is_megagroup || + c->is_verified != is_verified || !c->restriction_reasons.empty() || c->is_scam != is_scam) { // c->has_linked_channel = has_linked_channel; // c->has_location = has_location; + c->has_active_group_call = has_active_group_call; c->sign_messages = sign_messages; c->is_slow_mode_enabled = is_slow_mode_enabled; c->is_megagroup = is_megagroup; @@ -14243,7 +14275,7 @@ td_api::object_ptr ContactsManager::get_update_unknown ChannelId channel_id) { return td_api::make_object(td_api::make_object( channel_id.get(), string(), 0, DialogParticipantStatus::Banned(0).get_chat_member_status_object(), 0, false, - false, false, false, true, false, "", false)); + false, false, false, false, true, false, "", false)); } int32 ContactsManager::get_supergroup_id_object(ChannelId channel_id, const char *source) const { @@ -14265,8 +14297,9 @@ tl_object_ptr ContactsManager::get_supergroup_object(Channel } return td_api::make_object( channel_id.get(), c->username, c->date, get_channel_status(c).get_chat_member_status_object(), - c->participant_count, c->has_linked_channel, c->has_location, c->sign_messages, c->is_slow_mode_enabled, - !c->is_megagroup, c->is_verified, get_restriction_reason_description(c->restriction_reasons), c->is_scam); + c->participant_count, c->has_linked_channel, c->has_location, c->has_active_group_call, c->sign_messages, + c->is_slow_mode_enabled, !c->is_megagroup, c->is_verified, + get_restriction_reason_description(c->restriction_reasons), c->is_scam); } tl_object_ptr ContactsManager::get_supergroup_full_info_object(ChannelId channel_id) const { diff --git a/td/telegram/ContactsManager.h b/td/telegram/ContactsManager.h index e73ba3e3c..2dab53930 100644 --- a/td/telegram/ContactsManager.h +++ b/td/telegram/ContactsManager.h @@ -21,6 +21,7 @@ #include "td/telegram/files/FileSourceId.h" #include "td/telegram/FolderId.h" #include "td/telegram/FullMessageId.h" +#include "td/telegram/InputGroupCallId.h" #include "td/telegram/Location.h" #include "td/telegram/MessageId.h" #include "td/telegram/net/DcId.h" @@ -789,6 +790,7 @@ class ContactsManager : public Actor { bool has_linked_channel = false; bool has_location = false; + bool has_active_group_call = false; bool sign_messages = false; bool is_slow_mode_enabled = false; @@ -847,6 +849,8 @@ class ContactsManager : public Actor { DcId stats_dc_id; + InputGroupCallId active_group_call_id; + int32 slow_mode_delay = 0; int32 slow_mode_next_send_date = 0; @@ -1017,6 +1021,7 @@ class ContactsManager : public Actor { static constexpr int32 CHANNEL_FLAG_HAS_LINKED_CHAT = 1 << 20; static constexpr int32 CHANNEL_FLAG_HAS_LOCATION = 1 << 21; static constexpr int32 CHANNEL_FLAG_IS_SLOW_MODE_ENABLED = 1 << 22; + static constexpr int32 CHANNEL_FLAG_HAS_ACTIVE_GROUP_CALL = 1 << 23; static constexpr int32 CHANNEL_FULL_FLAG_HAS_PARTICIPANT_COUNT = 1 << 0; static constexpr int32 CHANNEL_FULL_FLAG_HAS_ADMINISTRATOR_COUNT = 1 << 1; @@ -1039,6 +1044,7 @@ class ContactsManager : public Actor { static constexpr int32 CHANNEL_FULL_FLAG_HAS_SLOW_MODE_NEXT_SEND_DATE = 1 << 18; static constexpr int32 CHANNEL_FULL_FLAG_HAS_SCHEDULED_MESSAGES = 1 << 19; static constexpr int32 CHANNEL_FULL_FLAG_CAN_VIEW_STATISTICS = 1 << 20; + static constexpr int32 CHANNEL_FULL_FLAG_HAS_ACTIVE_GROUP_CALL = 1 << 21; static constexpr int32 CHANNEL_FULL_FLAG_IS_BLOCKED = 1 << 22; static constexpr int32 CHAT_INVITE_FLAG_IS_CHANNEL = 1 << 0; diff --git a/td/telegram/Global.h b/td/telegram/Global.h index 85d2a2e04..5c5f211bc 100644 --- a/td/telegram/Global.h +++ b/td/telegram/Global.h @@ -38,6 +38,7 @@ class ConnectionCreator; class ContactsManager; class FileManager; class FileReferenceManager; +class GroupCallManager; class LanguagePackManager; class MessagesManager; class MtprotoHeader; @@ -215,6 +216,13 @@ class Global : public ActorContext { file_reference_manager_ = std::move(file_reference_manager); } + ActorId group_call_manager() const { + return group_call_manager_; + } + void set_group_call_manager(ActorId group_call_manager) { + group_call_manager_ = group_call_manager; + } + ActorId language_pack_manager() const { return language_pack_manager_; } @@ -385,6 +393,7 @@ class Global : public ActorContext { ActorId contacts_manager_; ActorId file_manager_; ActorId file_reference_manager_; + ActorId group_call_manager_; ActorId language_pack_manager_; ActorId messages_manager_; ActorId notification_manager_; diff --git a/td/telegram/InputGroupCallId.cpp b/td/telegram/InputGroupCallId.cpp index 69f05a66d..296dc3d89 100644 --- a/td/telegram/InputGroupCallId.cpp +++ b/td/telegram/InputGroupCallId.cpp @@ -27,10 +27,7 @@ Result InputGroupCallId::from_group_call_id(const string &grou return Status::Error("Invalid group call identifier specified"); } - InputGroupCallId result; - result.group_call_id = r_group_call_id.ok(); - result.access_hash = r_access_hash.ok(); - return result; + return InputGroupCallId{r_group_call_id.ok(), r_access_hash.ok()}; } string InputGroupCallId::get_group_call_id() const { @@ -45,7 +42,7 @@ tl_object_ptr InputGroupCallId::get_input_group_ca } StringBuilder &operator<<(StringBuilder &string_builder, InputGroupCallId input_group_call_id) { - return string_builder << "input group call " << input_group_call_id.group_call_id; + return string_builder << "group call " << input_group_call_id.group_call_id; } } // namespace td diff --git a/td/telegram/InputGroupCallId.h b/td/telegram/InputGroupCallId.h index 7107f764d..b8583e1e6 100644 --- a/td/telegram/InputGroupCallId.h +++ b/td/telegram/InputGroupCallId.h @@ -12,6 +12,8 @@ #include "td/utils/Status.h" #include "td/utils/StringBuilder.h" +#include + namespace td { class InputGroupCallId { @@ -23,22 +25,33 @@ class InputGroupCallId { explicit InputGroupCallId(const tl_object_ptr &input_group_call); + InputGroupCallId(int64 group_call_id, int64 access_hash) : group_call_id(group_call_id), access_hash(access_hash) { + } + static Result from_group_call_id(const string &group_call_id); string get_group_call_id() const; bool operator==(const InputGroupCallId &other) const { - return group_call_id == other.group_call_id && access_hash == other.access_hash; + return group_call_id == other.group_call_id; } bool operator!=(const InputGroupCallId &other) const { return !(*this == other); } + bool is_identical(const InputGroupCallId &other) const { + return group_call_id == other.group_call_id && access_hash == other.access_hash; + } + bool is_valid() const { return group_call_id != 0; } + std::size_t get_hash() const { + return std::hash()(group_call_id); + } + tl_object_ptr get_input_group_call() const; template @@ -56,4 +69,10 @@ class InputGroupCallId { friend StringBuilder &operator<<(StringBuilder &string_builder, InputGroupCallId input_group_call_id); }; +struct InputGroupCallIdHash { + std::size_t operator()(InputGroupCallId input_group_call_id) const { + return input_group_call_id.get_hash(); + } +}; + } // namespace td diff --git a/td/telegram/MessageContent.cpp b/td/telegram/MessageContent.cpp index 62f4a48cc..95ef9d25f 100644 --- a/td/telegram/MessageContent.cpp +++ b/td/telegram/MessageContent.cpp @@ -3303,6 +3303,9 @@ void merge_message_contents(Td *td, const MessageContent *old_content, MessageCo if (old_->group_call_id != new_->group_call_id || old_->duration != new_->duration) { need_update = true; } + if (!old_->group_call_id.is_identical(new_->group_call_id)) { + is_content_changed = true; + } break; } case MessageContentType::InviteToGroupCall: { @@ -3311,6 +3314,9 @@ void merge_message_contents(Td *td, const MessageContent *old_content, MessageCo if (old_->group_call_id != new_->group_call_id || old_->user_id != new_->user_id) { need_update = true; } + if (!old_->group_call_id.is_identical(new_->group_call_id)) { + is_content_changed = true; + } break; } case MessageContentType::Unsupported: { @@ -4770,7 +4776,8 @@ tl_object_ptr get_message_content_object(const MessageCo } case MessageContentType::GroupCall: { auto *m = static_cast(content); - return make_tl_object(m->group_call_id.get_group_call_id()); + return make_tl_object(m->group_call_id.get_group_call_id(), + m->duration >= 0 ? max(m->duration, 1) : 0); } case MessageContentType::InviteToGroupCall: { auto *m = static_cast(content); diff --git a/td/telegram/Td.cpp b/td/telegram/Td.cpp index 7320118ae..502fa9dfc 100644 --- a/td/telegram/Td.cpp +++ b/td/telegram/Td.cpp @@ -4517,6 +4517,7 @@ void Td::init_managers() { country_info_manager_actor_ = register_actor("CountryInfoManager", country_info_manager_.get()); group_call_manager_ = make_unique(this, create_reference()); group_call_manager_actor_ = register_actor("GroupCallManager", group_call_manager_.get()); + G()->set_group_call_manager(group_call_manager_actor_.get()); inline_queries_manager_ = make_unique(this, create_reference()); inline_queries_manager_actor_ = register_actor("InlineQueriesManager", inline_queries_manager_.get()); messages_manager_ = make_unique(this, create_reference()); diff --git a/td/telegram/UpdatesManager.cpp b/td/telegram/UpdatesManager.cpp index 7191d924e..8e54ba631 100644 --- a/td/telegram/UpdatesManager.cpp +++ b/td/telegram/UpdatesManager.cpp @@ -21,6 +21,7 @@ #include "td/telegram/DialogId.h" #include "td/telegram/FolderId.h" #include "td/telegram/Global.h" +#include "td/telegram/GroupCallManager.h" #include "td/telegram/InlineQueriesManager.h" #include "td/telegram/LanguagePackManager.h" #include "td/telegram/Location.h" @@ -2122,6 +2123,10 @@ void UpdatesManager::on_update(tl_object_ptrdata_.as_slice().str()); } +void UpdatesManager::on_update(tl_object_ptr update, bool /*force_apply*/) { + send_closure(G()->group_call_manager(), &GroupCallManager::on_update_group_call, std::move(update->call_)); +} + void UpdatesManager::on_update(tl_object_ptr update, bool /*force_apply*/) { td_->contacts_manager_->on_update_contacts_reset(); } @@ -2184,7 +2189,4 @@ void UpdatesManager::on_update(tl_object_ptr update, void UpdatesManager::on_update(tl_object_ptr update, bool /*force_apply*/) { } -void UpdatesManager::on_update(tl_object_ptr update, bool /*force_apply*/) { -} - } // namespace td diff --git a/td/telegram/UpdatesManager.h b/td/telegram/UpdatesManager.h index efe3f3dbf..9cc8ec416 100644 --- a/td/telegram/UpdatesManager.h +++ b/td/telegram/UpdatesManager.h @@ -298,6 +298,8 @@ class UpdatesManager : public Actor { void on_update(tl_object_ptr update, bool /*force_apply*/); void on_update(tl_object_ptr update, bool /*force_apply*/); + void on_update(tl_object_ptr update, bool /*force_apply*/); + void on_update(tl_object_ptr update, bool /*force_apply*/); void on_update(tl_object_ptr update, bool /*force_apply*/); @@ -320,8 +322,6 @@ class UpdatesManager : public Actor { void on_update(tl_object_ptr update, bool /*force_apply*/); void on_update(tl_object_ptr update, bool /*force_apply*/); - - void on_update(tl_object_ptr update, bool /*force_apply*/); }; } // namespace td