Add photo to *FullInfo.

GitOrigin-RevId: 21346a0880239abe428799fa58b9132abded6f13
This commit is contained in:
levlam 2020-07-06 15:26:29 +03:00
parent 4a5a6e708f
commit a7bd0c3932
13 changed files with 346 additions and 90 deletions

View File

@ -351,6 +351,10 @@ userProfilePhoto id:int64 added_date:int32 sizes:vector<photoSize> = UserProfile
userProfilePhotos total_count:int32 photos:vector<userProfilePhoto> = UserProfilePhotos;
//@description Contains full information about a chat photo @added_date Point in time (Unix timestamp) when the photo has been added @sizes Available variants of the chat photo, in different size
chatPhotoFullInfo added_date:int32 sizes:vector<photoSize> = ChatPhotoFullInfo;
//@description Represents a user @id User identifier @first_name First name of the user @last_name Last name of the user @username Username of the user
//@phone_number Phone number of the user @status Current online status of the user @profile_photo Profile photo of the user; may be null
//@is_contact The user is a contact of the current user
@ -490,8 +494,13 @@ supergroupMembersFilterBots = SupergroupMembersFilter;
//@upgraded_to_supergroup_id Identifier of the supergroup to which this group was upgraded; 0 if none
basicGroup id:int32 member_count:int32 status:ChatMemberStatus is_active:Bool upgraded_to_supergroup_id:int32 = BasicGroup;
//@description Contains full information about a basic group @param_description Group description @creator_user_id User identifier of the creator of the group; 0 if unknown @members Group members @invite_link Invite link for this group; available only after it has been generated at least once and only for the group creator
basicGroupFullInfo description:string creator_user_id:int32 members:vector<chatMember> invite_link:string = BasicGroupFullInfo;
//@description Contains full information about a basic group
//@photo Chat photo; may be null
//@param_description Group description
//@creator_user_id User identifier of the creator of the group; 0 if unknown
//@members Group members
//@invite_link Invite link for this group; available only after it has been generated at least once and only for the group creator
basicGroupFullInfo photo:chatPhotoFullInfo description:string creator_user_id:int32 members:vector<chatMember> invite_link:string = BasicGroupFullInfo;
//@description Represents a supergroup or channel with zero or more members (subscribers in the case of channels). From the point of view of the system, a channel is a special kind of a supergroup: only administrators can post and see the list of members, and posts from all administrators use the name and photo of the channel instead of individual names and profile photos. Unlike supergroups, channels can have an unlimited number of subscribers
@ -511,6 +520,7 @@ basicGroupFullInfo description:string creator_user_id:int32 members:vector<chatM
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;
//@description Contains full information about a supergroup or channel
//@photo Chat photo; may be null
//@param_description Supergroup or channel description
//@member_count Number of members in the supergroup or channel; 0 if unknown
//@administrator_count Number of privileged users in the supergroup or channel; 0 if unknown
@ -530,7 +540,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 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_view_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:chatPhotoFullInfo 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_view_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

Binary file not shown.

View File

@ -3407,10 +3407,12 @@ void ContactsManager::ChatFull::store(StorerT &storer) const {
using td::store;
bool has_description = !description.empty();
bool has_invite_link = !invite_link.empty();
bool has_photo = !photo.is_empty();
BEGIN_STORE_FLAGS();
STORE_FLAG(has_description);
STORE_FLAG(has_invite_link);
STORE_FLAG(can_set_username);
STORE_FLAG(has_photo);
END_STORE_FLAGS();
store(version, storer);
store(creator_user_id, storer);
@ -3421,6 +3423,9 @@ void ContactsManager::ChatFull::store(StorerT &storer) const {
if (has_invite_link) {
store(invite_link, storer);
}
if (has_photo) {
store(photo, storer);
}
}
template <class ParserT>
@ -3428,10 +3433,12 @@ void ContactsManager::ChatFull::parse(ParserT &parser) {
using td::parse;
bool has_description;
bool has_invite_link;
bool has_photo;
BEGIN_PARSE_FLAGS();
PARSE_FLAG(has_description);
PARSE_FLAG(has_invite_link);
PARSE_FLAG(can_set_username);
PARSE_FLAG(has_photo);
END_PARSE_FLAGS();
parse(version, parser);
parse(creator_user_id, parser);
@ -3442,6 +3449,9 @@ void ContactsManager::ChatFull::parse(ParserT &parser) {
if (has_invite_link) {
parse(invite_link, parser);
}
if (has_photo) {
parse(photo, parser);
}
}
template <class StorerT>
@ -3607,6 +3617,7 @@ void ContactsManager::ChannelFull::store(StorerT &storer) const {
bool is_slow_mode_enabled = slow_mode_delay != 0;
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();
BEGIN_STORE_FLAGS();
STORE_FLAG(has_description);
STORE_FLAG(has_administrator_count);
@ -3628,6 +3639,7 @@ void ContactsManager::ChannelFull::store(StorerT &storer) const {
STORE_FLAG(is_slow_mode_enabled);
STORE_FLAG(is_slow_mode_delay_active);
STORE_FLAG(has_stats_dc_id);
STORE_FLAG(has_photo);
END_STORE_FLAGS();
if (has_description) {
store(description, storer);
@ -3673,6 +3685,9 @@ void ContactsManager::ChannelFull::store(StorerT &storer) const {
if (has_stats_dc_id) {
store(stats_dc_id.get_raw_id(), storer);
}
if (has_photo) {
store(photo, storer);
}
}
template <class ParserT>
@ -3693,6 +3708,7 @@ void ContactsManager::ChannelFull::parse(ParserT &parser) {
bool is_slow_mode_enabled;
bool is_slow_mode_delay_active;
bool has_stats_dc_id;
bool has_photo;
BEGIN_PARSE_FLAGS();
PARSE_FLAG(has_description);
PARSE_FLAG(has_administrator_count);
@ -3714,6 +3730,7 @@ void ContactsManager::ChannelFull::parse(ParserT &parser) {
PARSE_FLAG(is_slow_mode_enabled);
PARSE_FLAG(is_slow_mode_delay_active);
PARSE_FLAG(has_stats_dc_id);
PARSE_FLAG(has_photo);
END_PARSE_FLAGS();
if (has_description) {
parse(description, parser);
@ -3759,6 +3776,10 @@ void ContactsManager::ChannelFull::parse(ParserT &parser) {
if (has_stats_dc_id) {
stats_dc_id = DcId::create(parser.fetch_int());
}
if (has_photo) {
parse(photo, parser);
}
if (legacy_can_view_statistics) {
LOG(DEBUG) << "Ignore legacy can view statistics flag";
}
@ -5791,15 +5812,11 @@ void ContactsManager::get_channel_statistics_dc_id(DialogId dialog_id, Promise<D
auto channel_full = get_channel_full_force(channel_id, "get_channel_statistics_dc_id");
if (channel_full == nullptr || !channel_full->stats_dc_id.is_exact()) {
auto input_channel = get_input_channel(channel_id);
CHECK(input_channel != nullptr);
auto query_promise = PromiseCreator::lambda(
[actor_id = actor_id(this), channel_id, promise = std::move(promise)](Result<Unit> result) mutable {
send_closure(actor_id, &ContactsManager::get_channel_statistics_dc_id_impl, channel_id, std::move(promise));
});
send_get_channel_full_query(channel_full, channel_id, std::move(input_channel), std::move(query_promise),
"get_channel_statistics_dc_id");
send_get_channel_full_query(channel_full, channel_id, std::move(query_promise), "get_channel_statistics_dc_id");
return;
}
@ -8149,9 +8166,15 @@ void ContactsManager::on_load_user_full_from_database(UserId user_id, string val
}
get_bot_info_force(user_id, false);
User *u = get_user(user_id);
CHECK(u != nullptr);
if (u->photo.id != user_full->photo.id.get()) {
user_full->photo = Photo();
if (u->photo.id > 0) {
user_full->expires_at = 0.0;
}
}
if (!user_full->photo.is_empty()) {
User *u = get_user(user_id);
CHECK(u != nullptr);
register_user_photo(u, user_id, user_full->photo);
}
@ -8159,6 +8182,8 @@ void ContactsManager::on_load_user_full_from_database(UserId user_id, string val
if (is_user_deleted(user_id)) {
drop_user_full(user_id);
} else if (user_full->expires_at == 0.0) {
get_user_full(user_id, true, Auto());
}
}
@ -8324,6 +8349,8 @@ void ContactsManager::on_load_chat_full_from_database(ChatId chat_id, string val
get_bot_info_force(participant.user_id);
}
on_update_chat_full_photo(chat_full, chat_id, std::move(chat_full->photo));
update_chat_full(chat_full, chat_id, true);
}
@ -8400,7 +8427,13 @@ void ContactsManager::on_load_channel_full_from_database(ChannelId channel_id, s
get_bot_info_force(user_id);
}
on_update_channel_full_photo(channel_full, channel_id, std::move(channel_full->photo));
update_channel_full(channel_full, channel_id, true);
if (channel_full->expires_at == 0.0) {
get_channel_full(channel_id, true, Auto());
}
}
ContactsManager::ChannelFull *ContactsManager::get_channel_full_force(ChannelId channel_id, const char *source) {
@ -8550,6 +8583,7 @@ void ContactsManager::update_chat(Chat *c, ChatId chat_id, bool from_binlog, boo
CHECK(c != nullptr);
if (c->is_photo_changed) {
td_->messages_manager_->on_dialog_photo_updated(DialogId(chat_id));
drop_chat_photos(chat_id, !c->photo.small_file_id.is_valid(), true, "update_chat");
}
if (c->is_title_changed) {
td_->messages_manager_->on_dialog_title_updated(DialogId(chat_id));
@ -8597,6 +8631,7 @@ void ContactsManager::update_channel(Channel *c, ChannelId channel_id, bool from
CHECK(c != nullptr);
if (c->is_photo_changed) {
td_->messages_manager_->on_dialog_photo_updated(DialogId(channel_id));
drop_channel_photos(channel_id, !c->photo.small_file_id.is_valid(), true, "update_channel");
}
if (c->is_title_changed) {
td_->messages_manager_->on_dialog_title_updated(DialogId(channel_id));
@ -9118,9 +9153,8 @@ void ContactsManager::on_get_chat_full(tl_object_ptr<telegram_api::ChatFull> &&c
ChatFull *chat = add_chat_full(chat_id);
on_update_chat_full_invite_link(chat, std::move(chat_full->exported_invite_));
// Ignoring chat_full->photo
// If not ignored, file reference needs to be repaired with getChatFull
on_update_chat_full_photo(
chat, chat_id, get_photo(td_->file_manager_.get(), std::move(chat_full->chat_photo_), DialogId(chat_id)));
for (auto &bot_info : chat_full->bot_info_) {
if (on_update_bot_info(std::move(bot_info))) {
@ -9172,9 +9206,6 @@ void ContactsManager::on_get_chat_full(tl_object_ptr<telegram_api::ChatFull> &&c
td_->messages_manager_->on_update_dialog_notify_settings(
DialogId(channel_id), std::move(channel_full->notify_settings_), "on_get_channel_full");
// Ignoring channel_full->photo
// If not ignored, file reference needs to be repaired with getChannelFull
auto c = get_channel(channel_id);
if (c == nullptr) {
LOG(ERROR) << channel_id << " not found";
@ -9235,6 +9266,10 @@ void ContactsManager::on_get_chat_full(tl_object_ptr<telegram_api::ChatFull> &&c
}
}
on_update_channel_full_photo(
channel, channel_id,
get_photo(td_->file_manager_.get(), std::move(channel_full->chat_photo_), DialogId(channel_id)));
td_->messages_manager_->on_read_channel_outbox(channel_id,
MessageId(ServerMessageId(channel_full->read_outbox_max_id_)));
if ((channel_full->flags_ & CHANNEL_FULL_FLAG_HAS_AVAILABLE_MIN_MESSAGE_ID) != 0) {
@ -9448,7 +9483,7 @@ void ContactsManager::do_update_user_photo(User *u, UserId user_id,
void ContactsManager::register_user_photo(User *u, UserId user_id, const Photo &photo) {
auto photo_file_ids = photo_get_file_ids(photo);
if (photo.id <= 0 || photo_file_ids.empty()) {
if (photo.is_empty() || photo_file_ids.empty()) {
return;
}
auto first_file_id = photo_file_ids[0];
@ -9457,19 +9492,20 @@ void ContactsManager::register_user_photo(User *u, UserId user_id, const Photo &
return;
}
CHECK(file_type == FileType::Photo);
if (u->photo_ids.emplace(photo.id).second) {
auto photo_id = photo.id.get();
if (u->photo_ids.emplace(photo_id).second) {
if (user_id == get_my_id()) {
my_photo_file_id_[photo.id] = first_file_id;
my_photo_file_id_[photo_id] = first_file_id;
}
FileSourceId file_source_id;
auto it = user_profile_photo_file_source_ids_.find(std::make_pair(user_id, photo.id));
auto it = user_profile_photo_file_source_ids_.find(std::make_pair(user_id, photo_id));
if (it != user_profile_photo_file_source_ids_.end()) {
VLOG(file_references) << "Move " << it->second << " inside of " << user_id;
file_source_id = it->second;
user_profile_photo_file_source_ids_.erase(it);
} else {
VLOG(file_references) << "Need to create new file source for photo " << photo.id << " of " << user_id;
file_source_id = td_->file_reference_manager_->create_user_photo_file_source(user_id, photo.id);
VLOG(file_references) << "Need to create new file source for photo " << photo_id << " of " << user_id;
file_source_id = td_->file_reference_manager_->create_user_photo_file_source(user_id, photo_id);
}
for (auto &file_id : photo_file_ids) {
td_->file_manager_->add_file_source(file_id, file_source_id);
@ -9751,29 +9787,29 @@ void ContactsManager::drop_user_photos(UserId user_id, bool is_empty, bool drop_
}
if (drop_user_full_photo) {
auto user_full = get_user_full_force(user_id);
auto user_full = get_user_full(user_id); // must not load UserFull
if (user_full == nullptr) {
return;
}
if (is_empty) {
if (!user_full->photo.is_empty()) {
user_full->photo = Photo();
user_full->is_changed = true;
}
} else {
if (!user_full->photo.is_empty()) {
user_full->photo = Photo();
user_full->is_changed = true;
}
if (!is_empty) {
if (user_full->expires_at > 0.0) {
user_full->expires_at = 0.0;
user_full->need_save_to_database = true;
get_user_full(user_id, true, Auto());
}
get_user_full(user_id, true, Auto());
}
update_user_full(user_full, user_id);
}
}
void ContactsManager::drop_user_full(UserId user_id) {
auto user_full = get_user_full_force(user_id);
drop_user_photos(user_id, false, false, "drop_user_full");
bot_infos_.erase(user_id);
@ -9781,7 +9817,6 @@ void ContactsManager::drop_user_full(UserId user_id) {
G()->td_db()->get_sqlite_pmc()->erase(get_bot_info_database_key(user_id), Auto());
}
auto user_full = get_user_full_force(user_id);
if (user_full == nullptr) {
return;
}
@ -10431,6 +10466,26 @@ void ContactsManager::speculative_add_channel_user(ChannelId channel_id, UserId
update_channel_full(channel_full, channel_id);
}
void ContactsManager::drop_channel_photos(ChannelId channel_id, bool is_empty, bool drop_channel_full_photo,
const char *source) {
if (drop_channel_full_photo) {
auto channel_full = get_channel_full(channel_id, "drop_channel_photos"); // must not load ChannelFull
if (channel_full == nullptr) {
return;
}
on_update_channel_full_photo(channel_full, channel_id, Photo());
if (!is_empty) {
if (channel_full->expires_at > 0.0) {
channel_full->expires_at = 0.0;
channel_full->need_save_to_database = true;
}
send_get_channel_full_query(channel_full, channel_id, Auto(), "drop_channel_photos");
}
update_channel_full(channel_full, channel_id);
}
}
void ContactsManager::invalidate_channel_full(ChannelId channel_id, bool drop_invite_link, bool drop_slow_mode_delay) {
LOG(INFO) << "Invalidate supergroup full for " << channel_id;
// drop channel full cache
@ -10458,6 +10513,80 @@ void ContactsManager::invalidate_channel_full(ChannelId channel_id, bool drop_in
}
}
void ContactsManager::on_update_chat_full_photo(ChatFull *chat_full, ChatId chat_id, Photo photo) {
CHECK(chat_full != nullptr);
if (photo != chat_full->photo) {
chat_full->photo = std::move(photo);
chat_full->is_changed = true;
}
if (chat_full->photo.is_empty()) {
drop_chat_photos(chat_id, true, false, "on_update_chat_full_photo");
}
auto photo_file_ids = photo_get_file_ids(photo);
if (chat_full->registered_photo_file_ids == photo_file_ids) {
return;
}
auto &file_source_id = chat_full->file_source_id;
if (!file_source_id.is_valid()) {
auto it = chat_full_file_source_ids_.find(chat_id);
if (it != chat_full_file_source_ids_.end()) {
VLOG(file_references) << "Move " << it->second << " inside of " << chat_id;
file_source_id = it->second;
chat_full_file_source_ids_.erase(it);
} else {
VLOG(file_references) << "Need to create new file source for full " << chat_id;
file_source_id = td_->file_reference_manager_->create_chat_full_file_source(chat_id);
}
}
for (auto &file_id : chat_full->registered_photo_file_ids) {
td_->file_manager_->remove_file_source(file_id, file_source_id);
}
chat_full->registered_photo_file_ids = std::move(photo_file_ids);
for (auto &file_id : chat_full->registered_photo_file_ids) {
td_->file_manager_->add_file_source(file_id, file_source_id);
}
}
void ContactsManager::on_update_channel_full_photo(ChannelFull *channel_full, ChannelId channel_id, Photo photo) {
CHECK(channel_full != nullptr);
if (photo != channel_full->photo) {
channel_full->photo = std::move(photo);
channel_full->is_changed = true;
}
if (channel_full->photo.is_empty()) {
drop_channel_photos(channel_id, true, false, "on_update_channel_full_photo");
}
auto photo_file_ids = photo_get_file_ids(photo);
if (channel_full->registered_photo_file_ids == photo_file_ids) {
return;
}
auto &file_source_id = channel_full->file_source_id;
if (!file_source_id.is_valid()) {
auto it = channel_full_file_source_ids_.find(channel_id);
if (it != channel_full_file_source_ids_.end()) {
VLOG(file_references) << "Move " << it->second << " inside of " << channel_id;
file_source_id = it->second;
channel_full_file_source_ids_.erase(it);
} else {
VLOG(file_references) << "Need to create new file source for full " << channel_id;
file_source_id = td_->file_reference_manager_->create_channel_full_file_source(channel_id);
}
}
for (auto &file_id : channel_full->registered_photo_file_ids) {
td_->file_manager_->remove_file_source(file_id, file_source_id);
}
channel_full->registered_photo_file_ids = std::move(photo_file_ids);
for (auto &file_id : channel_full->registered_photo_file_ids) {
td_->file_manager_->add_file_source(file_id, file_source_id);
}
}
void ContactsManager::on_get_chat_invite_link(ChatId chat_id,
tl_object_ptr<telegram_api::ExportedChatInvite> &&invite_link_ptr) {
CHECK(chat_id.is_valid());
@ -11322,9 +11451,26 @@ void ContactsManager::on_update_chat_full_participants(ChatFull *chat_full, Chat
update_chat_online_member_count(chat_full, chat_id, true);
}
void ContactsManager::drop_chat_photos(ChatId chat_id, bool is_empty, bool drop_chat_full_photo, const char *source) {
if (drop_chat_full_photo) {
auto chat_full = get_chat_full(chat_id); // must not load ChatFull
if (chat_full == nullptr) {
return;
}
on_update_chat_full_photo(chat_full, chat_id, Photo());
if (!is_empty) {
reload_chat_full(chat_id, Auto());
}
update_chat_full(chat_full, chat_id);
}
}
void ContactsManager::drop_chat_full(ChatId chat_id) {
ChatFull *chat_full = get_chat_full_force(chat_id);
if (chat_full == nullptr) {
drop_chat_photos(chat_id, false, false, "drop_chat_full");
auto it = dialog_invite_links_.find(DialogId(chat_id));
if (it != dialog_invite_links_.end()) {
invalidate_invite_link_info(it->second);
@ -11333,7 +11479,8 @@ void ContactsManager::drop_chat_full(ChatId chat_id) {
}
LOG(INFO) << "Drop basicGroupFullInfo of " << chat_id;
//chat_full->creator_user_id = UserId();
on_update_chat_full_photo(chat_full, chat_id, Photo());
// chat_full->creator_user_id = UserId();
chat_full->participants.clear();
chat_full->version = -1;
update_invite_link(chat_full->invite_link, nullptr);
@ -11378,11 +11525,7 @@ void ContactsManager::on_update_channel_status(Channel *c, ChannelId channel_id,
created_public_channels_[i].clear();
}
auto input_channel = get_input_channel(channel_id);
if (input_channel != nullptr) {
send_get_channel_full_query(nullptr, channel_id, std::move(input_channel), Auto(), "update channel owner");
}
send_get_channel_full_query(nullptr, channel_id, Auto(), "update channel owner");
reload_dialog_administrators(DialogId(channel_id), 0, Auto());
}
}
@ -11696,7 +11839,7 @@ void ContactsManager::reload_dialog_info(DialogId dialog_id, Promise<Unit> &&pro
case DialogType::Channel:
return reload_channel(dialog_id.get_channel_id(), std::move(promise));
default:
promise.set_error(Status::Error("Invalid dialog id to reload"));
promise.set_error(Status::Error("Invalid dialog ID to reload"));
}
}
@ -11985,6 +12128,36 @@ FileSourceId ContactsManager::get_user_profile_photo_file_source_id(UserId user_
return source_id;
}
FileSourceId ContactsManager::get_chat_full_file_source_id(ChatId chat_id) {
if (get_chat_full(chat_id) != nullptr) {
VLOG(file_references) << "Don't need to create file source for full " << chat_id;
// chat full was already added, source ID was registered and shouldn't be needed
return FileSourceId();
}
auto &source_id = chat_full_file_source_ids_[chat_id];
if (!source_id.is_valid()) {
source_id = td_->file_reference_manager_->create_chat_full_file_source(chat_id);
}
VLOG(file_references) << "Return " << source_id << " for full " << chat_id;
return source_id;
}
FileSourceId ContactsManager::get_channel_full_file_source_id(ChannelId channel_id) {
if (get_channel_full(channel_id) != nullptr) {
VLOG(file_references) << "Don't need to create file source for full " << channel_id;
// channel full was already added, source ID was registered and shouldn't be needed
return FileSourceId();
}
auto &source_id = channel_full_file_source_ids_[channel_id];
if (!source_id.is_valid()) {
source_id = td_->file_reference_manager_->create_channel_full_file_source(channel_id);
}
VLOG(file_references) << "Return " << source_id << " for full " << channel_id;
return source_id;
}
bool ContactsManager::have_chat(ChatId chat_id) const {
return chats_.count(chat_id) > 0;
}
@ -12131,6 +12304,10 @@ bool ContactsManager::get_chat_full(ChatId chat_id, bool force, Promise<Unit> &&
return true;
}
void ContactsManager::reload_chat_full(ChatId chat_id, Promise<Unit> &&promise) {
send_get_chat_full_query(chat_id, std::move(promise), "reload_chat_full");
}
void ContactsManager::send_get_chat_full_query(ChatId chat_id, Promise<Unit> &&promise, const char *source) {
LOG(INFO) << "Get full " << chat_id << " from " << source;
auto send_query = PromiseCreator::lambda([td = td_, chat_id](Result<Promise<Unit>> &&promise) {
@ -12371,9 +12548,7 @@ ContactsManager::ChannelFull *ContactsManager::get_channel_full(ChannelId channe
auto channel_full = p->second.get();
if (channel_full->is_expired() && !td_->auth_manager_->is_bot()) {
auto input_channel = get_input_channel(channel_id);
CHECK(input_channel != nullptr);
send_get_channel_full_query(channel_full, channel_id, std::move(input_channel), Auto(), source);
send_get_channel_full_query(channel_full, channel_id, Auto(), source);
}
return channel_full;
@ -12391,25 +12566,16 @@ ContactsManager::ChannelFull *ContactsManager::add_channel_full(ChannelId channe
bool ContactsManager::get_channel_full(ChannelId channel_id, bool force, Promise<Unit> &&promise) {
auto channel_full = get_channel_full_force(channel_id, "get_channel_full");
if (channel_full == nullptr) {
auto input_channel = get_input_channel(channel_id);
if (input_channel == nullptr) {
promise.set_error(Status::Error(6, "Supergroup not found"));
return false;
}
send_get_channel_full_query(nullptr, channel_id, std::move(input_channel), std::move(promise), "get channel_full");
send_get_channel_full_query(channel_full, channel_id, std::move(promise), "get_channel_full");
return false;
}
if (channel_full->is_expired()) {
if (td_->auth_manager_->is_bot() && !force) {
auto input_channel = get_input_channel(channel_id);
CHECK(input_channel != nullptr);
send_get_channel_full_query(channel_full, channel_id, std::move(input_channel), std::move(promise),
"get expired channel_full");
send_get_channel_full_query(channel_full, channel_id, std::move(promise), "get expired channel_full");
return false;
} else {
// request has already been sent in get_channel_full_force
// send_get_channel_full_query(channel_full, channel_id, std::move(input_channel), Auto(), "get expired channel_full");
// send_get_channel_full_query(channel_full, channel_id, Auto(), "get expired channel_full");
}
}
@ -12417,9 +12583,18 @@ bool ContactsManager::get_channel_full(ChannelId channel_id, bool force, Promise
return true;
}
void ContactsManager::reload_channel_full(ChannelId channel_id, Promise<Unit> &&promise, const char *source) {
send_get_channel_full_query(get_channel_full(channel_id, "reload_channel_full"), channel_id, std::move(promise),
source);
}
void ContactsManager::send_get_channel_full_query(ChannelFull *channel_full, ChannelId channel_id,
tl_object_ptr<telegram_api::InputChannel> &&input_channel,
Promise<Unit> &&promise, const char *source) {
auto input_channel = get_input_channel(channel_id);
if (input_channel == nullptr) {
return promise.set_error(Status::Error(6, "Supergroup not found"));
}
if (channel_full != nullptr) {
if (!promise) {
if (channel_full->repair_request_version != 0) {
@ -12743,13 +12918,7 @@ std::pair<int32, vector<DialogParticipant>> ContactsManager::get_channel_partici
if (force) {
LOG(ERROR) << "Can't find cached ChannelFull";
} else {
auto input_channel = get_input_channel(channel_id);
if (input_channel == nullptr) {
promise.set_error(Status::Error(6, "Supergroup not found"));
} else {
send_get_channel_full_query(channel_full, channel_id, std::move(input_channel), std::move(promise),
"get_channel_participants");
}
send_get_channel_full_query(channel_full, channel_id, std::move(promise), "get_channel_participants");
return result;
}
}
@ -13457,7 +13626,8 @@ tl_object_ptr<td_api::basicGroupFullInfo> ContactsManager::get_basic_group_full_
const ChatFull *chat_full) const {
CHECK(chat_full != nullptr);
return make_tl_object<td_api::basicGroupFullInfo>(
chat_full->description, get_user_id_object(chat_full->creator_user_id, "basicGroupFullInfo"),
get_chat_photo_full_info_object(td_->file_manager_.get(), &chat_full->photo), chat_full->description,
get_user_id_object(chat_full->creator_user_id, "basicGroupFullInfo"),
transform(chat_full->participants,
[this](const DialogParticipant &chat_participant) { return get_chat_member_object(chat_participant); }),
chat_full->invite_link);
@ -13501,11 +13671,12 @@ tl_object_ptr<td_api::supergroupFullInfo> ContactsManager::get_supergroup_full_i
slow_mode_delay_expires_in = max(channel_full->slow_mode_next_send_date - G()->server_time(), 1e-3);
}
return td_api::make_object<td_api::supergroupFullInfo>(
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->stats_dc_id.is_exact(), channel_full->is_all_history_available, channel_full->sticker_set_id.get(),
get_chat_photo_full_info_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->stats_dc_id.is_exact(),
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

@ -446,6 +446,8 @@ class ContactsManager : public Actor {
bool get_chat(ChatId chat_id, int left_tries, Promise<Unit> &&promise);
void reload_chat(ChatId chat_id, Promise<Unit> &&promise);
bool get_chat_full(ChatId chat_id, bool force, Promise<Unit> &&promise);
FileSourceId get_chat_full_file_source_id(ChatId chat_id);
void reload_chat_full(ChatId chat_id, Promise<Unit> &&promise);
bool get_chat_is_active(ChatId chat_id) const;
DialogParticipantStatus get_chat_status(ChatId chat_id) const;
@ -458,6 +460,8 @@ class ContactsManager : public Actor {
bool get_channel(ChannelId channel_id, int left_tries, Promise<Unit> &&promise);
void reload_channel(ChannelId chnanel_id, Promise<Unit> &&promise);
bool get_channel_full(ChannelId channel_id, bool force, Promise<Unit> &&promise);
FileSourceId get_channel_full_file_source_id(ChannelId channel_id);
void reload_channel_full(ChannelId channel_id, Promise<Unit> &&promise, const char *source);
bool is_channel_public(ChannelId channel_id) const;
@ -714,11 +718,16 @@ class ContactsManager : public Actor {
void parse(ParserT &parser);
};
// do not forget to update drop_chat_full and on_get_chat_full
struct ChatFull {
int32 version = -1;
UserId creator_user_id;
vector<DialogParticipant> participants;
Photo photo;
vector<FileId> registered_photo_file_ids;
FileSourceId file_source_id;
string description;
string invite_link;
@ -785,7 +794,12 @@ class ContactsManager : public Actor {
void parse(ParserT &parser);
};
// do not forget to update invalidate_channel_full and on_get_chat_full
struct ChannelFull {
Photo photo;
vector<FileId> registered_photo_file_ids;
FileSourceId file_source_id;
string description;
int32 participant_count = 0;
int32 administrator_count = 0;
@ -1061,8 +1075,7 @@ class ContactsManager : public Actor {
ChannelFull *add_channel_full(ChannelId channel_id);
void send_get_channel_full_query(ChannelFull *channel_full, ChannelId channel_id,
tl_object_ptr<telegram_api::InputChannel> &&input_channel, Promise<Unit> &&promise,
void send_get_channel_full_query(ChannelFull *channel_full, ChannelId channel_id, Promise<Unit> &&promise,
const char *source);
const SecretChat *get_secret_chat(SecretChatId secret_chat_id) const;
@ -1117,6 +1130,7 @@ class ContactsManager : public Actor {
void on_update_chat_active(Chat *c, ChatId chat_id, bool is_active);
void on_update_chat_migrated_to_channel_id(Chat *c, ChatId chat_id, ChannelId migrated_to_channel_id);
void on_update_chat_full_photo(ChatFull *chat_full, ChatId chat_id, Photo photo);
bool on_update_chat_full_participants_short(ChatFull *chat_full, ChatId chat_id, int32 version);
void on_update_chat_full_participants(ChatFull *chat_full, ChatId chat_id, vector<DialogParticipant> participants,
int32 version, bool from_update);
@ -1132,6 +1146,7 @@ class ContactsManager : public Actor {
void on_update_channel_bot_user_ids(ChannelId channel_id, vector<UserId> &&bot_user_ids);
void on_update_channel_full_photo(ChannelFull *channel_full, ChannelId channel_id, Photo photo);
void on_update_channel_full_invite_link(ChannelFull *channel_full,
tl_object_ptr<telegram_api::ExportedChatInvite> &&invite_link_ptr);
void on_update_channel_full_linked_channel_id(ChannelFull *channel_full, ChannelId channel_id,
@ -1153,8 +1168,11 @@ class ContactsManager : public Actor {
void speculative_add_channel_user(ChannelId channel_id, UserId user_id, DialogParticipantStatus new_status,
DialogParticipantStatus old_status);
void drop_chat_photos(ChatId chat_id, bool is_empty, bool drop_chat_full_photo, const char *source);
void drop_chat_full(ChatId chat_id);
void drop_channel_photos(ChannelId channel_id, bool is_empty, bool drop_channel_full_photo, const char *source);
void update_user_online_member_count(User *u);
void update_chat_online_member_count(const ChatFull *chat_full, ChatId chat_id, bool is_from_server);
void update_channel_online_member_count(ChannelId channel_id, bool is_from_server);
@ -1406,11 +1424,13 @@ class ContactsManager : public Actor {
std::unordered_map<ChatId, unique_ptr<Chat>, ChatIdHash> chats_;
std::unordered_map<ChatId, unique_ptr<ChatFull>, ChatIdHash> chats_full_;
mutable std::unordered_set<ChatId, ChatIdHash> unknown_chats_;
std::unordered_map<ChatId, FileSourceId, ChatIdHash> chat_full_file_source_ids_;
std::unordered_set<ChannelId, ChannelIdHash> min_channels_;
std::unordered_map<ChannelId, unique_ptr<Channel>, ChannelIdHash> channels_;
std::unordered_map<ChannelId, unique_ptr<ChannelFull>, ChannelIdHash> channels_full_;
mutable std::unordered_set<ChannelId, ChannelIdHash> unknown_channels_;
std::unordered_map<ChannelId, FileSourceId, ChannelIdHash> channel_full_file_source_ids_;
std::unordered_map<SecretChatId, unique_ptr<SecretChat>, SecretChatIdHash> secret_chats_;
mutable std::unordered_set<SecretChatId, SecretChatIdHash> unknown_secret_chats_;

View File

@ -45,7 +45,7 @@ size_t FileReferenceManager::get_file_reference_error_pos(const Status &error) {
/*
fileSourceMessage chat_id:int53 message_id:int53 = FileSource; // repaired with get_message_from_server
fileSourceUserProfilePhoto user_id:int32 photo_id:int64 = FileSource; // repaired with photos.getUserPhotos
fileSourceBasicGroupPhoto basic_group_id:int32 = FileSource; // repaired with messages.getChats
fileSourceBasicGroupPhoto basic_group_id:int32 = FileSource; // no need to repair
fileSourceSupergroupPhoto supergroup_id:int32 = FileSource; // no need to repair
fileSourceWebPage url:string = FileSource; // repaired with messages.getWebPage
fileSourceWallpapers = FileSource; // can't be repaired
@ -53,6 +53,8 @@ fileSourceSavedAnimations = FileSource; // repa
fileSourceRecentStickers is_attached:Bool = FileSource; // repaired with messages.getRecentStickers, not reliable
fileSourceFavoriteStickers = FileSource; // repaired with messages.getFavedStickers, not reliable
fileSourceBackground background_id:int64 access_hash:int64 = FileSource; // repaired with account.getWallPaper
fileSourceBasicGroupFull basic_group_id:int32 = FileSource; // repaired with messages.getFullChat
fileSourceSupergroupFull supergroup_id:int32 = FileSource; // repaired with messages.getFullChannel
*/
FileSourceId FileReferenceManager::get_current_file_source_id() const {
@ -102,6 +104,16 @@ FileSourceId FileReferenceManager::create_background_file_source(BackgroundId ba
return add_file_source_id(source, PSLICE() << background_id);
}
FileSourceId FileReferenceManager::create_chat_full_file_source(ChatId chat_id) {
FileSourceChatFull source{chat_id};
return add_file_source_id(source, PSLICE() << "full " << chat_id);
}
FileSourceId FileReferenceManager::create_channel_full_file_source(ChannelId channel_id) {
FileSourceChannelFull source{channel_id};
return add_file_source_id(source, PSLICE() << "full " << channel_id);
}
bool FileReferenceManager::add_file_source(NodeId node_id, FileSourceId file_source_id) {
bool is_added = nodes_[node_id].file_source_ids.add(file_source_id);
VLOG(file_references) << "Add " << (is_added ? "new" : "old") << ' ' << file_source_id << " for file " << node_id;
@ -272,6 +284,14 @@ void FileReferenceManager::send_query(Destination dest, FileSourceId file_source
[&](const FileSourceBackground &source) {
send_closure_later(G()->background_manager(), &BackgroundManager::reload_background, source.background_id,
source.access_hash, std::move(promise));
},
[&](const FileSourceChatFull &source) {
send_closure_later(G()->contacts_manager(), &ContactsManager::reload_chat_full, source.chat_id,
std::move(promise));
},
[&](const FileSourceChannelFull &source) {
send_closure_later(G()->contacts_manager(), &ContactsManager::reload_channel_full, source.channel_id,
std::move(promise), "repair file reference");
}));
}

View File

@ -49,6 +49,8 @@ class FileReferenceManager : public Actor {
FileSourceId create_recent_stickers_file_source(bool is_attached);
FileSourceId create_favorite_stickers_file_source();
FileSourceId create_background_file_source(BackgroundId background_id, int64 access_hash);
FileSourceId create_chat_full_file_source(ChatId chat_id);
FileSourceId create_channel_full_file_source(ChannelId channel_id);
using NodeId = FileId;
void repair_file_reference(NodeId node_id, Promise<> promise);
@ -123,11 +125,18 @@ class FileReferenceManager : public Actor {
BackgroundId background_id;
int64 access_hash;
};
struct FileSourceChatFull {
ChatId chat_id;
};
struct FileSourceChannelFull {
ChannelId channel_id;
};
// append only
using FileSource = Variant<FileSourceMessage, FileSourceUserPhoto, FileSourceChatPhoto, FileSourceChannelPhoto,
FileSourceWallpapers, FileSourceWebPage, FileSourceSavedAnimations,
FileSourceRecentStickers, FileSourceFavoriteStickers, FileSourceBackground>;
using FileSource =
Variant<FileSourceMessage, FileSourceUserPhoto, FileSourceChatPhoto, FileSourceChannelPhoto, FileSourceWallpapers,
FileSourceWebPage, FileSourceSavedAnimations, FileSourceRecentStickers, FileSourceFavoriteStickers,
FileSourceBackground, FileSourceChatFull, FileSourceChannelFull>;
vector<FileSource> file_sources_;
int64 query_generation_{0};

View File

@ -47,7 +47,9 @@ void FileReferenceManager::store_file_source(FileSourceId file_source_id, Storer
[&](const FileSourceBackground &source) {
td::store(source.background_id, storer);
td::store(source.access_hash, storer);
}));
},
[&](const FileSourceChatFull &source) { td::store(source.chat_id, storer); },
[&](const FileSourceChannelFull &source) { td::store(source.channel_id, storer); }));
}
template <class ParserT>
@ -99,6 +101,16 @@ FileSourceId FileReferenceManager::parse_file_source(Td *td, ParserT &parser) {
td::parse(access_hash, parser);
return td->background_manager_->get_background_file_source_id(background_id, access_hash);
}
case 10: {
ChatId chat_id;
td::parse(chat_id, parser);
return td->contacts_manager_->get_chat_full_file_source_id(chat_id);
}
case 11: {
ChannelId channel_id;
td::parse(channel_id, parser);
return td->contacts_manager_->get_channel_full_file_source_id(channel_id);
}
default:
parser.set_error("Invalid type in FileSource");
return FileSourceId();

View File

@ -2831,7 +2831,7 @@ void merge_message_contents(Td *td, const MessageContent *old_content, MessageCo
if (old_photo->date != new_photo->date) {
is_content_changed = true;
}
if (old_photo->id != new_photo->id || old_->caption != new_->caption) {
if (old_photo->id.get() != new_photo->id.get() || old_->caption != new_->caption) {
need_update = true;
}
if (old_photo->minithumbnail != new_photo->minithumbnail) {

View File

@ -610,7 +610,7 @@ Photo get_photo(FileManager *file_manager, tl_object_ptr<telegram_api::photo> &&
res.has_stickers = (photo->flags_ & telegram_api::photo::HAS_STICKERS_MASK) != 0;
if (res.is_empty()) {
LOG(ERROR) << "Receive photo with id " << res.id;
LOG(ERROR) << "Receive photo with id " << res.id.get();
res.id = -3;
}
@ -658,10 +658,20 @@ tl_object_ptr<td_api::userProfilePhoto> get_user_profile_photo_object(FileManage
return nullptr;
}
return td_api::make_object<td_api::userProfilePhoto>(photo->id, photo->date,
return td_api::make_object<td_api::userProfilePhoto>(photo->id.get(), photo->date,
get_photo_sizes_object(file_manager, photo->photos));
}
tl_object_ptr<td_api::chatPhotoFullInfo> get_chat_photo_full_info_object(FileManager *file_manager,
const Photo *photo) {
if (photo == nullptr || photo->is_empty()) {
return nullptr;
}
return td_api::make_object<td_api::chatPhotoFullInfo>(photo->date,
get_photo_sizes_object(file_manager, photo->photos));
}
void photo_delete_thumbnail(Photo &photo) {
for (size_t i = 0; i < photo.photos.size(); i++) {
if (photo.photos[i].type == 't') {
@ -801,7 +811,7 @@ vector<FileId> photo_get_file_ids(const Photo &photo) {
}
bool operator==(const Photo &lhs, const Photo &rhs) {
return lhs.id == rhs.id && lhs.photos == rhs.photos;
return lhs.id.get() == rhs.id.get() && lhs.photos == rhs.photos;
}
bool operator!=(const Photo &lhs, const Photo &rhs) {
@ -809,7 +819,7 @@ bool operator!=(const Photo &lhs, const Photo &rhs) {
}
StringBuilder &operator<<(StringBuilder &string_builder, const Photo &photo) {
return string_builder << "[id = " << photo.id << ", photos = " << format::as_array(photo.photos) << "]";
return string_builder << "[id = " << photo.id.get() << ", photos = " << format::as_array(photo.photos) << "]";
}
static tl_object_ptr<telegram_api::fileLocationToBeDeprecated> copy_location(

View File

@ -20,6 +20,7 @@
#include "td/utils/buffer.h"
#include "td/utils/common.h"
#include "td/utils/MovableValue.h"
#include "td/utils/StringBuilder.h"
#include "td/utils/Variant.h"
@ -49,7 +50,7 @@ struct PhotoSize {
};
struct Photo {
int64 id = -2;
MovableValue<int64, -2> id;
int32 date = 0;
string minithumbnail;
vector<PhotoSize> photos;
@ -58,7 +59,7 @@ struct Photo {
vector<FileId> sticker_file_ids;
bool is_empty() const {
return id == -2;
return id.get() == -2;
}
};
@ -125,6 +126,7 @@ Photo get_web_document_photo(FileManager *file_manager, tl_object_ptr<telegram_a
DialogId owner_dialog_id);
tl_object_ptr<td_api::photo> get_photo_object(FileManager *file_manager, const Photo *photo);
tl_object_ptr<td_api::userProfilePhoto> get_user_profile_photo_object(FileManager *file_manager, const Photo *photo);
tl_object_ptr<td_api::chatPhotoFullInfo> get_chat_photo_full_info_object(FileManager *file_manager, const Photo *photo);
void photo_delete_thumbnail(Photo &photo);

View File

@ -77,7 +77,7 @@ void store(const Photo &photo, StorerT &storer) {
STORE_FLAG(photo.has_stickers);
STORE_FLAG(has_minithumbnail);
END_STORE_FLAGS();
store(photo.id, storer);
store(photo.id.get(), storer);
store(photo.date, storer);
store(photo.photos, storer);
if (photo.has_stickers) {
@ -95,7 +95,9 @@ void parse(Photo &photo, ParserT &parser) {
PARSE_FLAG(photo.has_stickers);
PARSE_FLAG(has_minithumbnail);
END_PARSE_FLAGS();
parse(photo.id, parser);
int64 id;
parse(id, parser);
photo.id = id;
parse(photo.date, parser);
parse(photo.photos, parser);
if (photo.has_stickers) {

View File

@ -1391,15 +1391,15 @@ void WebPagesManager::on_get_web_page_instant_view(WebPage *web_page, tl_object_
std::unordered_map<int64, Photo> photos;
for (auto &photo_ptr : page->photos_) {
Photo photo = get_photo(td_->file_manager_.get(), std::move(photo_ptr), owner_dialog_id);
if (photo.is_empty() || photo.id == 0) {
if (photo.is_empty() || photo.id.get() == 0) {
LOG(ERROR) << "Receive empty photo in web page instant view for " << web_page->url;
} else {
auto photo_id = photo.id;
auto photo_id = photo.id.get();
photos.emplace(photo_id, std::move(photo));
}
}
if (!web_page->photo.is_empty() && web_page->photo.id != 0) {
photos.emplace(web_page->photo.id, web_page->photo);
if (!web_page->photo.is_empty() && web_page->photo.id.get() != 0) {
photos.emplace(web_page->photo.id.get(), web_page->photo);
}
std::unordered_map<int64, FileId> animations;

View File

@ -24,8 +24,8 @@ class MovableValue {
}
return *this;
}
MovableValue(const MovableValue &) = delete;
MovableValue &operator=(const MovableValue &) = delete;
MovableValue(const MovableValue &) = default;
MovableValue &operator=(const MovableValue &) = default;
~MovableValue() = default;
void clear() {