This commit is contained in:
Andrea Cavalli 2020-12-25 19:09:41 +01:00
commit c032df3b76
13 changed files with 311 additions and 37 deletions

View File

@ -323,6 +323,7 @@ set(TDLIB_SOURCE
td/telegram/files/ResourceManager.cpp
td/telegram/Game.cpp
td/telegram/Global.cpp
td/telegram/GroupCallManager.cpp
td/telegram/HashtagHints.cpp
td/telegram/InlineQueriesManager.cpp
td/telegram/InputDialogId.cpp
@ -497,6 +498,7 @@ set(TDLIB_SOURCE
td/telegram/FullMessageId.h
td/telegram/Game.h
td/telegram/Global.h
td/telegram/GroupCallManager.h
td/telegram/HashtagHints.h
td/telegram/InlineQueriesManager.h
td/telegram/InputDialogId.h

View File

@ -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
@ -582,6 +583,7 @@ supergroup id:int32 username:string date:int32 status:ChatMemberStatus member_co
//@restricted_count Number of restricted users in the supergroup; 0 if unknown
//@banned_count Number of users banned from chat; 0 if unknown
//@linked_chat_id Chat identifier of a discussion group for the channel, or a channel, for which the supergroup is the designated discussion group; 0 if none or unknown
//@group_call_id Identifier of an active group call; empty if none or unknown
//@slow_mode_delay Delay between consecutive sent messages for non-administrator supergroup members, in seconds
//@slow_mode_delay_expires_in Time left before next message can be sent in the supergroup, in seconds. An updateSupergroupFullInfo update is not triggered when value of this field changes, but both new and old values are non-zero
//@can_get_members True, if members of the chat can be retrieved
@ -595,7 +597,7 @@ supergroup id:int32 username:string date:int32 status:ChatMemberStatus member_co
//@invite_link Invite link for this chat
//@upgraded_from_basic_group_id Identifier of the basic group from which supergroup was upgraded; 0 if none
//@upgraded_from_max_message_id Identifier of the last message in the basic group from which supergroup was upgraded; 0 if none
supergroupFullInfo photo:chatPhoto description:string member_count:int32 administrator_count:int32 restricted_count:int32 banned_count:int32 linked_chat_id:int53 slow_mode_delay:int32 slow_mode_delay_expires_in:double can_get_members:Bool can_set_username:Bool can_set_sticker_set:Bool can_set_location:Bool can_get_statistics:Bool is_all_history_available:Bool sticker_set_id:int64 location:chatLocation invite_link:string upgraded_from_basic_group_id:int32 upgraded_from_max_message_id:int53 = SupergroupFullInfo;
supergroupFullInfo photo:chatPhoto description:string member_count:int32 administrator_count:int32 restricted_count:int32 banned_count:int32 linked_chat_id:int53 group_call_id:string slow_mode_delay:int32 slow_mode_delay_expires_in:double can_get_members:Bool can_set_username:Bool can_set_sticker_set:Bool can_set_location:Bool can_get_statistics:Bool is_all_history_available:Bool sticker_set_id:int64 location:chatLocation invite_link:string upgraded_from_basic_group_id:int32 upgraded_from_max_message_id:int53 = SupergroupFullInfo;
//@class SecretChatState @description Describes the current secret chat state
@ -1627,11 +1629,11 @@ 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
messageGroupCall = 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
messageInviteToGroupCall = 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;
//@description A newly created basic group @title Title of the basic group @member_user_ids User identifiers of members in the basic group
messageBasicGroupChatCreate title:string member_user_ids:vector<int32> = MessageContent;
@ -2032,6 +2034,9 @@ callServer id:int64 ip_address:string ipv6_address:string port:int32 type:CallSe
//@description Contains the call identifier @id Call identifier
callId id:int32 = CallId;
//@description Contains the group call identifier @id Group call identifier
groupCallId id:string = GroupCallId;
//@class CallState @description Describes the current call state
@ -2054,6 +2059,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
@ -3335,6 +3344,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;
@ -4282,6 +4294,10 @@ sendCallRating call_id:int32 rating:int32 comment:string problems:vector<CallPro
sendCallDebugInformation call_id:int32 debug_information:string = Ok;
//@description Creates a group call in a chat. Available only for supergroups; requires can_manage_calls rights @chat_id Chat identifier
createChatGroupCall chat_id:int53 = GroupCallId;
//@description Changes the block state of a message sender. Currently, only users and supergroup chats can be blocked @sender Message Sender @is_blocked New value of is_blocked
toggleMessageSenderIsBlocked sender:MessageSender is_blocked:Bool = Ok;

View File

@ -19,6 +19,7 @@
#include "td/telegram/files/FileType.h"
#include "td/telegram/FolderId.h"
#include "td/telegram/Global.h"
#include "td/telegram/GroupCallManager.h"
#include "td/telegram/InlineQueriesManager.h"
#include "td/telegram/logevent/LogEvent.h"
#include "td/telegram/logevent/LogEventHelper.h"
@ -3559,6 +3560,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 +3626,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 +3694,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 +3719,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 +3768,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 <class ParserT>
@ -3784,6 +3792,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 +3817,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 +3866,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";
@ -5901,6 +5914,70 @@ void ContactsManager::set_channel_slow_mode_delay(DialogId dialog_id, int32 slow
td_->create_handler<ToggleSlowModeQuery>(std::move(promise))->send(channel_id, slow_mode_delay);
}
void ContactsManager::create_channel_group_call(DialogId dialog_id, Promise<InputGroupCallId> &&promise) {
if (!dialog_id.is_valid()) {
return promise.set_error(Status::Error(400, "Invalid chat identifier specified"));
}
if (!td_->messages_manager_->have_dialog_force(dialog_id)) {
return promise.set_error(Status::Error(400, "Chat not found"));
}
if (dialog_id.get_type() != DialogType::Channel) {
return promise.set_error(Status::Error(400, "Chat is not a supergroup"));
}
auto channel_id = dialog_id.get_channel_id();
const Channel *c = get_channel(channel_id);
if (c == nullptr) {
return promise.set_error(Status::Error(400, "Chat info not found"));
}
if (!c->is_megagroup) {
return promise.set_error(Status::Error(400, "Chat is not a supergroup"));
}
if (!get_channel_permissions(c).can_manage_calls()) {
return promise.set_error(Status::Error(400, "Not enough rights in the supergroup"));
}
auto new_promise = PromiseCreator::lambda(
[actor_id = actor_id(this), channel_id, promise = std::move(promise)](Result<InputGroupCallId> result) mutable {
if (result.is_error()) {
promise.set_error(result.move_as_error());
} else {
send_closure(actor_id, &ContactsManager::on_create_channel_group_call, channel_id, result.move_as_ok(),
std::move(promise));
}
});
send_closure(G()->group_call_manager(), &GroupCallManager::create_group_call, channel_id, std::move(new_promise));
}
void ContactsManager::on_create_channel_group_call(ChannelId channel_id, InputGroupCallId group_call_id,
Promise<InputGroupCallId> &&promise) {
if (G()->close_flag()) {
return promise.set_error(Status::Error(500, "Request aborted"));
}
if (!group_call_id.is_valid()) {
return promise.set_error(Status::Error(500, "Receive invalid group call identifier"));
}
Channel *c = get_channel(channel_id);
if (c == nullptr) {
return promise.set_error(Status::Error(500, "Channel not found"));
}
if (!c->has_active_group_call) {
c->has_active_group_call = true;
c->is_changed = true;
update_channel(c, channel_id);
}
auto channel_full = get_channel_full_force(channel_id, "on_create_channel_group_call");
if (channel_full != nullptr && channel_full->active_group_call_id != group_call_id) {
channel_full->active_group_call_id = group_call_id;
channel_full->is_changed = true;
update_channel_full(channel_full, channel_id);
}
promise.set_value(std::move(group_call_id));
}
void ContactsManager::get_channel_statistics_dc_id(DialogId dialog_id, bool for_full_statistics,
Promise<DcId> &&promise) {
if (!dialog_id.is_valid()) {
@ -8695,7 +8772,13 @@ void ContactsManager::on_load_channel_full_from_database(ChannelId channel_id, s
channel_full->expires_at = 0.0;
}
}
on_update_channel_full_photo(channel_full, channel_id, std::move(channel_full->photo));
auto photo = std::move(channel_full->photo);
on_update_channel_full_photo(channel_full, channel_id, std::move(photo));
if (!c->has_active_group_call && channel_full->active_group_call_id.is_valid()) {
channel_full->active_group_call_id = InputGroupCallId();
channel_full->expires_at = 0.0;
}
update_channel_full(channel_full, channel_id, true);
@ -9532,6 +9615,14 @@ void ContactsManager::on_get_chat_full(tl_object_ptr<telegram_api::ChatFull> &&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_);
if (group_call_id.is_valid() && !c->is_megagroup) {
LOG(ERROR) << "Receive " << group_call_id << " in " << channel_id;
group_call_id = InputGroupCallId();
}
}
channel->repair_request_version = 0;
channel->expires_at = Time::now() + CHANNEL_FULL_EXPIRE_TIME;
@ -9568,6 +9659,19 @@ void ContactsManager::on_get_chat_full(tl_object_ptr<telegram_api::ChatFull> &&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 << ", but have "
<< group_call_id << " in " << channel_id;
c->has_active_group_call = has_active_group_call;
c->is_changed = true;
update_channel(c, channel_id);
}
channel->is_changed = true;
}
on_update_channel_full_photo(
channel, channel_id,
get_photo(td_->file_manager_.get(), std::move(channel_full->chat_photo_), DialogId(channel_id)));
@ -10943,7 +11047,8 @@ void ContactsManager::drop_channel_photos(ChannelId channel_id, bool is_empty, b
}
}
void ContactsManager::invalidate_channel_full(ChannelId channel_id, bool drop_invite_link, bool drop_slow_mode_delay) {
void ContactsManager::invalidate_channel_full(ChannelId channel_id, bool drop_invite_link, bool drop_slow_mode_delay,
bool drop_active_group_call_id) {
LOG(INFO) << "Invalidate supergroup full for " << channel_id;
// drop channel full cache
auto channel_full = get_channel_full_force(channel_id, "invalidate_channel_full");
@ -10958,6 +11063,10 @@ void ContactsManager::invalidate_channel_full(ChannelId channel_id, bool drop_in
channel_full->is_slow_mode_next_send_date_changed = true;
channel_full->is_changed = true;
}
if (drop_active_group_call_id && channel_full->active_group_call_id.is_valid()) {
channel_full->active_group_call_id = InputGroupCallId();
channel_full->is_changed = true;
}
update_channel_full(channel_full, channel_id);
}
if (drop_invite_link) {
@ -13845,6 +13954,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;
@ -13948,11 +14058,14 @@ void ContactsManager::on_chat_update(telegram_api::channel &channel, const char
}
bool need_invalidate_channel_full = false;
bool need_drop_active_group_call_id = c->has_active_group_call != has_active_group_call;
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;
@ -13972,7 +14085,7 @@ void ContactsManager::on_chat_update(telegram_api::channel &channel, const char
update_channel(c, channel_id);
if (need_invalidate_channel_full) {
invalidate_channel_full(channel_id, false, !c->is_slow_mode_enabled);
invalidate_channel_full(channel_id, false, !c->is_slow_mode_enabled, need_drop_active_group_call_id);
}
}
@ -14013,6 +14126,7 @@ void ContactsManager::on_chat_update(telegram_api::channelForbidden &channel, co
tl_object_ptr<telegram_api::chatBannedRights> 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;
@ -14036,11 +14150,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;
@ -14266,7 +14381,7 @@ td_api::object_ptr<td_api::updateSupergroup> ContactsManager::get_update_unknown
ChannelId channel_id) {
return td_api::make_object<td_api::updateSupergroup>(td_api::make_object<td_api::supergroup>(
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 {
@ -14288,8 +14403,9 @@ tl_object_ptr<td_api::supergroup> ContactsManager::get_supergroup_object(Channel
}
return td_api::make_object<td_api::supergroup>(
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<td_api::supergroupFullInfo> ContactsManager::get_supergroup_full_info_object(ChannelId channel_id) const {
@ -14308,11 +14424,11 @@ tl_object_ptr<td_api::supergroupFullInfo> ContactsManager::get_supergroup_full_i
return td_api::make_object<td_api::supergroupFullInfo>(
get_chat_photo_object(td_->file_manager_.get(), channel_full->photo), channel_full->description,
channel_full->participant_count, channel_full->administrator_count, channel_full->restricted_count,
channel_full->banned_count, DialogId(channel_full->linked_channel_id).get(), channel_full->slow_mode_delay,
slow_mode_delay_expires_in, channel_full->can_get_participants, channel_full->can_set_username,
channel_full->can_set_sticker_set, channel_full->can_set_location, channel_full->can_view_statistics,
channel_full->is_all_history_available, channel_full->sticker_set_id.get(),
channel_full->location.get_chat_location_object(), channel_full->invite_link,
channel_full->banned_count, DialogId(channel_full->linked_channel_id).get(),
channel_full->active_group_call_id.get_group_call_id(), channel_full->slow_mode_delay, slow_mode_delay_expires_in,
channel_full->can_get_participants, channel_full->can_set_username, channel_full->can_set_sticker_set,
channel_full->can_set_location, channel_full->can_view_statistics, channel_full->is_all_history_available,
channel_full->sticker_set_id.get(), channel_full->location.get_chat_location_object(), channel_full->invite_link,
get_basic_group_id_object(channel_full->migrated_from_chat_id, "get_supergroup_full_info_object"),
channel_full->migrated_from_max_message_id.get());
}

View File

@ -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"
@ -219,7 +220,8 @@ class ContactsManager : public Actor {
void speculative_delete_channel_participant(ChannelId channel_id, UserId deleted_user_id, bool by_me);
void invalidate_channel_full(ChannelId channel_id, bool drop_invite_link, bool drop_slow_mode_delay);
void invalidate_channel_full(ChannelId channel_id, bool drop_invite_link, bool drop_slow_mode_delay,
bool drop_active_group_call_id = false);
bool on_get_channel_error(ChannelId channel_id, const Status &status, const string &source);
@ -367,6 +369,8 @@ class ContactsManager : public Actor {
void set_channel_slow_mode_delay(DialogId dialog_id, int32 slow_mode_delay, Promise<Unit> &&promise);
void create_channel_group_call(DialogId dialog_id, Promise<InputGroupCallId> &&promise);
void report_channel_spam(ChannelId channel_id, UserId user_id, const vector<MessageId> &message_ids,
Promise<Unit> &&promise);
@ -793,6 +797,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;
@ -851,6 +856,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;
@ -1021,6 +1028,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;
@ -1043,6 +1051,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;
@ -1312,6 +1321,9 @@ class ContactsManager : public Actor {
void update_bot_info(BotInfo *bot_info, UserId user_id, bool send_update, bool from_database);
void on_create_channel_group_call(ChannelId channel_id, InputGroupCallId group_call_id,
Promise<InputGroupCallId> &&promise);
bool is_chat_full_outdated(const ChatFull *chat_full, const Chat *c, ChatId chat_id);
bool is_user_contact(const User *u, UserId user_id) const;

View File

@ -38,6 +38,7 @@ class ConnectionCreator;
class ContactsManager;
class FileManager;
class FileReferenceManager;
class GroupCallManager;
class LanguagePackManager;
class MessagesManager;
class MtprotoHeader;
@ -216,6 +217,13 @@ class Global : public ActorContext {
file_reference_manager_ = std::move(file_reference_manager);
}
ActorId<GroupCallManager> group_call_manager() const {
return group_call_manager_;
}
void set_group_call_manager(ActorId<GroupCallManager> group_call_manager) {
group_call_manager_ = group_call_manager;
}
ActorId<LanguagePackManager> language_pack_manager() const {
return language_pack_manager_;
}
@ -393,6 +401,7 @@ class Global : public ActorContext {
ActorId<ContactsManager> contacts_manager_;
ActorId<FileManager> file_manager_;
ActorId<FileReferenceManager> file_reference_manager_;
ActorId<GroupCallManager> group_call_manager_;
ActorId<LanguagePackManager> language_pack_manager_;
ActorId<MessagesManager> messages_manager_;
ActorId<NotificationManager> notification_manager_;

View File

@ -7,6 +7,7 @@
#include "td/telegram/InputGroupCallId.h"
#include "td/utils/logging.h"
#include "td/utils/misc.h"
namespace td {
@ -14,12 +15,34 @@ InputGroupCallId::InputGroupCallId(const tl_object_ptr<telegram_api::inputGroupC
: group_call_id(input_group_call->id_), access_hash(input_group_call->access_hash_) {
}
Result<InputGroupCallId> InputGroupCallId::from_group_call_id(const string &group_call_id) {
if (group_call_id.empty()) {
return InputGroupCallId();
}
auto splitted = split(group_call_id, '_');
auto r_group_call_id = to_integer_safe<int64>(splitted.first);
auto r_access_hash = to_integer_safe<int64>(splitted.second);
if (r_group_call_id.is_error() || r_access_hash.is_error()) {
return Status::Error("Invalid group call identifier specified");
}
return InputGroupCallId{r_group_call_id.ok(), r_access_hash.ok()};
}
string InputGroupCallId::get_group_call_id() const {
if (is_valid()) {
return PSTRING() << group_call_id << '_' << access_hash;
}
return string();
}
tl_object_ptr<telegram_api::inputGroupCall> InputGroupCallId::get_input_group_call() const {
return make_tl_object<telegram_api::inputGroupCall>(group_call_id, access_hash);
}
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

View File

@ -9,8 +9,11 @@
#include "td/telegram/telegram_api.h"
#include "td/utils/common.h"
#include "td/utils/Status.h"
#include "td/utils/StringBuilder.h"
#include <functional>
namespace td {
class InputGroupCallId {
@ -22,18 +25,33 @@ class InputGroupCallId {
explicit InputGroupCallId(const tl_object_ptr<telegram_api::inputGroupCall> &input_group_call);
InputGroupCallId(int64 group_call_id, int64 access_hash) : group_call_id(group_call_id), access_hash(access_hash) {
}
static Result<InputGroupCallId> 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<int64>()(group_call_id);
}
tl_object_ptr<telegram_api::inputGroupCall> get_input_group_call() const;
template <class StorerT>
@ -51,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

View File

@ -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: {
@ -4024,7 +4030,7 @@ unique_ptr<MessageContent> get_message_content(Td *td, FormattedText message,
auto message_contact = move_tl_object_as<telegram_api::messageMediaContact>(media);
if (message_contact->user_id_ != 0) {
td->contacts_manager_->get_user_id_object(UserId(message_contact->user_id_),
"messageMediaContact"); // to ensure updateUser
"MessageMediaContact"); // to ensure updateUser
}
return make_unique<MessageContact>(Contact(
std::move(message_contact->phone_number_), std::move(message_contact->first_name_),
@ -4677,12 +4683,12 @@ tl_object_ptr<td_api::MessageContent> get_message_content_object(const MessageCo
case MessageContentType::ChatDeleteUser: {
const MessageChatDeleteUser *m = static_cast<const MessageChatDeleteUser *>(content);
return make_tl_object<td_api::messageChatDeleteMember>(
td->contacts_manager_->get_user_id_object(m->user_id, "messageChatDeleteMember"));
td->contacts_manager_->get_user_id_object(m->user_id, "MessageChatDeleteMember"));
}
case MessageContentType::ChatMigrateTo: {
const MessageChatMigrateTo *m = static_cast<const MessageChatMigrateTo *>(content);
return make_tl_object<td_api::messageChatUpgradeTo>(
td->contacts_manager_->get_supergroup_id_object(m->migrated_to_channel_id, "messageChatUpgradeTo"));
td->contacts_manager_->get_supergroup_id_object(m->migrated_to_channel_id, "MessageChatUpgradeTo"));
}
case MessageContentType::ChannelCreate: {
const MessageChannelCreate *m = static_cast<const MessageChannelCreate *>(content);
@ -4692,7 +4698,7 @@ tl_object_ptr<td_api::MessageContent> get_message_content_object(const MessageCo
const MessageChannelMigrateFrom *m = static_cast<const MessageChannelMigrateFrom *>(content);
return make_tl_object<td_api::messageChatUpgradeFrom>(
m->title,
td->contacts_manager_->get_basic_group_id_object(m->migrated_from_chat_id, "messageChatUpgradeFrom"));
td->contacts_manager_->get_basic_group_id_object(m->migrated_from_chat_id, "MessageChatUpgradeFrom"));
}
case MessageContentType::PinMessage: {
const MessagePinMessage *m = static_cast<const MessagePinMessage *>(content);
@ -4768,10 +4774,17 @@ tl_object_ptr<td_api::MessageContent> get_message_content_object(const MessageCo
td->messages_manager_->get_message_sender_object(m->traveler_dialog_id),
td->messages_manager_->get_message_sender_object(m->watcher_dialog_id), m->distance);
}
case MessageContentType::GroupCall:
return make_tl_object<td_api::messageGroupCall>();
case MessageContentType::InviteToGroupCall:
return make_tl_object<td_api::messageInviteToGroupCall>();
case MessageContentType::GroupCall: {
auto *m = static_cast<const MessageGroupCall *>(content);
return make_tl_object<td_api::messageGroupCall>(m->group_call_id.get_group_call_id(),
m->duration >= 0 ? max(m->duration, 1) : 0);
}
case MessageContentType::InviteToGroupCall: {
auto *m = static_cast<const MessageInviteToGroupCall *>(content);
return make_tl_object<td_api::messageInviteToGroupCall>(
m->group_call_id.get_group_call_id(),
td->contacts_manager_->get_user_id_object(m->user_id, "MessageInviteToGroupCall"));
}
default:
UNREACHABLE();
return nullptr;

View File

@ -43,6 +43,7 @@
#include "td/telegram/FolderId.h"
#include "td/telegram/FullMessageId.h"
#include "td/telegram/Global.h"
#include "td/telegram/GroupCallManager.h"
#include "td/telegram/HashtagHints.h"
#include "td/telegram/InlineQueriesManager.h"
#include "td/telegram/JsonValue.h"
@ -3896,6 +3897,8 @@ void Td::dec_actor_refcnt() {
LOG(DEBUG) << "FileManager was cleared" << timer;
file_reference_manager_.reset();
LOG(DEBUG) << "FileReferenceManager was cleared" << timer;
group_call_manager_.reset();
LOG(DEBUG) << "GroupCallManager was cleared" << timer;
inline_queries_manager_.reset();
LOG(DEBUG) << "InlineQueriesManager was cleared" << timer;
messages_manager_.reset();
@ -4082,6 +4085,8 @@ void Td::clear() {
LOG(DEBUG) << "FileManager actor was cleared" << timer;
file_reference_manager_actor_.reset();
LOG(DEBUG) << "FileReferenceManager actor was cleared" << timer;
group_call_manager_actor_.reset();
LOG(DEBUG) << "GroupCallManager actor was cleared" << timer;
inline_queries_manager_actor_.reset();
LOG(DEBUG) << "InlineQueriesManager actor was cleared" << timer;
messages_manager_actor_.reset(); // TODO: Stop silent
@ -4521,6 +4526,9 @@ void Td::init_managers() {
G()->set_contacts_manager(contacts_manager_actor_.get());
country_info_manager_ = make_unique<CountryInfoManager>(this, create_reference());
country_info_manager_actor_ = register_actor("CountryInfoManager", country_info_manager_.get());
group_call_manager_ = make_unique<GroupCallManager>(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<InlineQueriesManager>(this, create_reference());
inline_queries_manager_actor_ = register_actor("InlineQueriesManager", inline_queries_manager_.get());
messages_manager_ = make_unique<MessagesManager>(this, create_reference());
@ -4941,6 +4949,7 @@ void Td::on_request(uint64 id, const td_api::getCurrentState &request) {
// TODO updateFileGenerationStart generation_id:int64 original_path:string destination_path:string conversion:string = Update;
// TODO updateCall call:call = Update;
// TODO updateGroupCall call:groupCall = Update;
}
auto update_terms_of_service = get_update_terms_of_service_object();
@ -6058,6 +6067,20 @@ void Td::on_request(uint64 id, td_api::sendCallDebugInformation &request) {
std::move(request.debug_information_), std::move(promise));
}
void Td::on_request(uint64 id, const td_api::createChatGroupCall &request) {
CHECK_IS_USER();
CREATE_REQUEST_PROMISE();
auto query_promise = PromiseCreator::lambda([promise = std::move(promise)](Result<InputGroupCallId> result) mutable {
if (result.is_error()) {
promise.set_error(result.move_as_error());
} else {
promise.set_value(td_api::make_object<td_api::groupCallId>(result.ok().get_group_call_id()));
}
});
contacts_manager_->create_channel_group_call(DialogId(request.chat_id_), std::move(query_promise));
}
void Td::on_request(uint64 id, const td_api::upgradeBasicGroupChatToSupergroupChat &request) {
CHECK_IS_USER();
CREATE_REQUEST(UpgradeGroupChatToSupergroupChatRequest, request.chat_id_);

View File

@ -57,6 +57,7 @@ class DeviceTokenManager;
class DocumentsManager;
class FileManager;
class FileReferenceManager;
class GroupCallManager;
class InlineQueriesManager;
class HashtagHints;
class LanguagePackManager;
@ -164,6 +165,8 @@ class Td final : public NetQueryCallback {
ActorOwn<FileManager> file_manager_actor_;
unique_ptr<FileReferenceManager> file_reference_manager_;
ActorOwn<FileReferenceManager> file_reference_manager_actor_;
unique_ptr<GroupCallManager> group_call_manager_;
ActorOwn<GroupCallManager> group_call_manager_actor_;
unique_ptr<InlineQueriesManager> inline_queries_manager_;
ActorOwn<InlineQueriesManager> inline_queries_manager_actor_;
unique_ptr<MessagesManager> messages_manager_;
@ -702,6 +705,8 @@ class Td final : public NetQueryCallback {
void on_request(uint64 id, td_api::sendCallDebugInformation &request);
void on_request(uint64 id, const td_api::createChatGroupCall &request);
void on_request(uint64 id, const td_api::upgradeBasicGroupChatToSupergroupChat &request);
void on_request(uint64 id, const td_api::getChatListsToAddChat &request);

View File

@ -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"
@ -900,6 +901,30 @@ vector<const tl_object_ptr<telegram_api::Message> *> UpdatesManager::get_new_mes
return messages;
}
vector<InputGroupCallId> UpdatesManager::get_update_new_group_call_ids(const telegram_api::Updates *updates_ptr) {
vector<InputGroupCallId> group_call_ids;
auto updates = get_updates(updates_ptr);
if (updates != nullptr) {
for (auto &update : *updates) {
InputGroupCallId group_call_id;
if (update->get_id() == telegram_api::updateGroupCall::ID) {
auto group_call_ptr = static_cast<const telegram_api::updateGroupCall *>(update.get())->call_.get();
if (group_call_ptr->get_id() == telegram_api::groupCall::ID) {
auto group_call = static_cast<const telegram_api::groupCall *>(group_call_ptr);
group_call_id = InputGroupCallId(group_call->id_, group_call->access_hash_);
}
}
if (group_call_id.is_valid()) {
group_call_ids.push_back(group_call_id);
} else {
LOG(ERROR) << "Receive unexpected " << to_string(update);
}
}
}
return group_call_ids;
}
vector<DialogId> UpdatesManager::get_update_notify_settings_dialog_ids(const telegram_api::Updates *updates_ptr) {
vector<DialogId> dialog_ids;
auto updates = get_updates(updates_ptr);
@ -2122,6 +2147,10 @@ void UpdatesManager::on_update(tl_object_ptr<telegram_api::updatePhoneCallSignal
update->data_.as_slice().str());
}
void UpdatesManager::on_update(tl_object_ptr<telegram_api::updateGroupCall> 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<telegram_api::updateContactsReset> update, bool /*force_apply*/) {
td_->contacts_manager_->on_update_contacts_reset();
}
@ -2184,7 +2213,4 @@ void UpdatesManager::on_update(tl_object_ptr<telegram_api::updateTheme> update,
void UpdatesManager::on_update(tl_object_ptr<telegram_api::updateGroupCallParticipants> update, bool /*force_apply*/) {
}
void UpdatesManager::on_update(tl_object_ptr<telegram_api::updateGroupCall> update, bool /*force_apply*/) {
}
} // namespace td

View File

@ -9,6 +9,7 @@
#include "td/telegram/ChannelId.h"
#include "td/telegram/ChatId.h"
#include "td/telegram/DialogId.h"
#include "td/telegram/InputGroupCallId.h"
#include "td/telegram/PtsManager.h"
#include "td/telegram/telegram_api.h"
#include "td/telegram/UserId.h"
@ -44,6 +45,8 @@ class UpdatesManager : public Actor {
static vector<const tl_object_ptr<telegram_api::Message> *> get_new_messages(
const telegram_api::Updates *updates_ptr);
static vector<InputGroupCallId> get_update_new_group_call_ids(const telegram_api::Updates *updates_ptr);
static vector<DialogId> get_update_notify_settings_dialog_ids(const telegram_api::Updates *updates_ptr);
static vector<DialogId> get_chat_dialog_ids(const telegram_api::Updates *updates_ptr);
@ -298,6 +301,8 @@ class UpdatesManager : public Actor {
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::updateGroupCall> update, bool /*force_apply*/);
void on_update(tl_object_ptr<telegram_api::updateContactsReset> update, bool /*force_apply*/);
void on_update(tl_object_ptr<telegram_api::updateLangPackTooLong> update, bool /*force_apply*/);
@ -320,8 +325,6 @@ class UpdatesManager : public Actor {
void on_update(tl_object_ptr<telegram_api::updateTheme> 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*/);
};
} // namespace td

View File

@ -2837,6 +2837,8 @@ class CliClient final : public Actor {
as_call_id(call_id), to_integer<int32>(rating), "Wow, such good call! (TDLib test)", std::move(problems)));
} else if (op == "scdi" || op == "SendCallDebugInformation") {
send_request(td_api::make_object<td_api::sendCallDebugInformation>(as_call_id(args), "{}"));
} else if (op == "ccgc") {
send_request(td_api::make_object<td_api::createChatGroupCall>(as_chat_id(args)));
} else if (op == "gcil") {
send_request(td_api::make_object<td_api::generateChatInviteLink>(as_chat_id(args)));
} else if (op == "ccil") {