1 //
2 // Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2021
3 //
4 // Distributed under the Boost Software License, Version 1.0. (See accompanying
5 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6 //
7 #include "td/telegram/ContactsManager.h"
8 
9 #include "td/telegram/AuthManager.h"
10 #include "td/telegram/ConfigManager.h"
11 #include "td/telegram/ConfigShared.h"
12 #include "td/telegram/Dependencies.h"
13 #include "td/telegram/DeviceTokenManager.h"
14 #include "td/telegram/DialogInviteLink.h"
15 #include "td/telegram/DialogLocation.h"
16 #include "td/telegram/FileReferenceManager.h"
17 #include "td/telegram/files/FileManager.h"
18 #include "td/telegram/files/FileType.h"
19 #include "td/telegram/FolderId.h"
20 #include "td/telegram/Global.h"
21 #include "td/telegram/GroupCallManager.h"
22 #include "td/telegram/InlineQueriesManager.h"
23 #include "td/telegram/InputGroupCallId.h"
24 #include "td/telegram/LinkManager.h"
25 #include "td/telegram/logevent/LogEvent.h"
26 #include "td/telegram/logevent/LogEventHelper.h"
27 #include "td/telegram/MessageSender.h"
28 #include "td/telegram/MessagesManager.h"
29 #include "td/telegram/MessageTtlSetting.h"
30 #include "td/telegram/misc.h"
31 #include "td/telegram/net/NetQuery.h"
32 #include "td/telegram/NotificationManager.h"
33 #include "td/telegram/PasswordManager.h"
34 #include "td/telegram/Photo.h"
35 #include "td/telegram/Photo.hpp"
36 #include "td/telegram/SecretChatLayer.h"
37 #include "td/telegram/SecretChatsManager.h"
38 #include "td/telegram/ServerMessageId.h"
39 #include "td/telegram/StickerSetId.hpp"
40 #include "td/telegram/StickersManager.h"
41 #include "td/telegram/Td.h"
42 #include "td/telegram/TdDb.h"
43 #include "td/telegram/TdParameters.h"
44 #include "td/telegram/telegram_api.hpp"
45 #include "td/telegram/UpdatesManager.h"
46 #include "td/telegram/Version.h"
47 
48 #include "td/db/binlog/BinlogEvent.h"
49 #include "td/db/binlog/BinlogHelper.h"
50 #include "td/db/SqliteKeyValue.h"
51 #include "td/db/SqliteKeyValueAsync.h"
52 
53 #include "td/actor/PromiseFuture.h"
54 #include "td/actor/SleepActor.h"
55 
56 #include "td/utils/algorithm.h"
57 #include "td/utils/buffer.h"
58 #include "td/utils/format.h"
59 #include "td/utils/logging.h"
60 #include "td/utils/misc.h"
61 #include "td/utils/Random.h"
62 #include "td/utils/Slice.h"
63 #include "td/utils/SliceBuilder.h"
64 #include "td/utils/StringBuilder.h"
65 #include "td/utils/Time.h"
66 #include "td/utils/tl_helpers.h"
67 #include "td/utils/utf8.h"
68 
69 #include <algorithm>
70 #include <limits>
71 #include <tuple>
72 #include <utility>
73 
74 namespace td {
75 
76 class DismissSuggestionQuery final : public Td::ResultHandler {
77   Promise<Unit> promise_;
78   DialogId dialog_id_;
79 
80  public:
DismissSuggestionQuery(Promise<Unit> && promise)81   explicit DismissSuggestionQuery(Promise<Unit> &&promise) : promise_(std::move(promise)) {
82   }
83 
send(SuggestedAction action)84   void send(SuggestedAction action) {
85     dialog_id_ = action.dialog_id_;
86     auto input_peer = td_->messages_manager_->get_input_peer(dialog_id_, AccessRights::Read);
87     CHECK(input_peer != nullptr);
88 
89     send_query(G()->net_query_creator().create(
90         telegram_api::help_dismissSuggestion(std::move(input_peer), action.get_suggested_action_str())));
91   }
92 
on_result(BufferSlice packet)93   void on_result(BufferSlice packet) final {
94     auto result_ptr = fetch_result<telegram_api::help_dismissSuggestion>(packet);
95     if (result_ptr.is_error()) {
96       return on_error(result_ptr.move_as_error());
97     }
98 
99     promise_.set_value(Unit());
100   }
101 
on_error(Status status)102   void on_error(Status status) final {
103     td_->messages_manager_->on_get_dialog_error(dialog_id_, status, "DismissSuggestionQuery");
104     promise_.set_error(std::move(status));
105   }
106 };
107 
108 class GetContactsQuery final : public Td::ResultHandler {
109  public:
send(int64 hash)110   void send(int64 hash) {
111     send_query(G()->net_query_creator().create(telegram_api::contacts_getContacts(hash)));
112   }
113 
on_result(BufferSlice packet)114   void on_result(BufferSlice packet) final {
115     auto result_ptr = fetch_result<telegram_api::contacts_getContacts>(packet);
116     if (result_ptr.is_error()) {
117       return on_error(result_ptr.move_as_error());
118     }
119 
120     auto ptr = result_ptr.move_as_ok();
121     LOG(INFO) << "Receive result for GetContactsQuery: " << to_string(ptr);
122     td_->contacts_manager_->on_get_contacts(std::move(ptr));
123   }
124 
on_error(Status status)125   void on_error(Status status) final {
126     td_->contacts_manager_->on_get_contacts_failed(std::move(status));
127     td_->updates_manager_->get_difference("GetContactsQuery");
128   }
129 };
130 
131 class GetContactsStatusesQuery final : public Td::ResultHandler {
132  public:
send()133   void send() {
134     send_query(G()->net_query_creator().create(telegram_api::contacts_getStatuses()));
135   }
136 
on_result(BufferSlice packet)137   void on_result(BufferSlice packet) final {
138     auto result_ptr = fetch_result<telegram_api::contacts_getStatuses>(packet);
139     if (result_ptr.is_error()) {
140       return on_error(result_ptr.move_as_error());
141     }
142 
143     td_->contacts_manager_->on_get_contacts_statuses(result_ptr.move_as_ok());
144   }
145 
on_error(Status status)146   void on_error(Status status) final {
147     if (!G()->is_expected_error(status)) {
148       LOG(ERROR) << "Receive error for GetContactsStatusesQuery: " << status;
149     }
150   }
151 };
152 
153 class AddContactQuery final : public Td::ResultHandler {
154   Promise<Unit> promise_;
155   UserId user_id_;
156 
157  public:
AddContactQuery(Promise<Unit> && promise)158   explicit AddContactQuery(Promise<Unit> &&promise) : promise_(std::move(promise)) {
159   }
160 
send(UserId user_id,tl_object_ptr<telegram_api::InputUser> && input_user,const Contact & contact,bool share_phone_number)161   void send(UserId user_id, tl_object_ptr<telegram_api::InputUser> &&input_user, const Contact &contact,
162             bool share_phone_number) {
163     user_id_ = user_id;
164     int32 flags = 0;
165     if (share_phone_number) {
166       flags |= telegram_api::contacts_addContact::ADD_PHONE_PRIVACY_EXCEPTION_MASK;
167     }
168     send_query(G()->net_query_creator().create(
169         telegram_api::contacts_addContact(flags, false /*ignored*/, std::move(input_user), contact.get_first_name(),
170                                           contact.get_last_name(), contact.get_phone_number())));
171   }
172 
on_result(BufferSlice packet)173   void on_result(BufferSlice packet) final {
174     auto result_ptr = fetch_result<telegram_api::contacts_addContact>(packet);
175     if (result_ptr.is_error()) {
176       return on_error(result_ptr.move_as_error());
177     }
178 
179     auto ptr = result_ptr.move_as_ok();
180     LOG(INFO) << "Receive result for AddContactQuery: " << to_string(ptr);
181     td_->updates_manager_->on_get_updates(std::move(ptr), std::move(promise_));
182   }
183 
on_error(Status status)184   void on_error(Status status) final {
185     promise_.set_error(std::move(status));
186     td_->contacts_manager_->reload_contacts(true);
187     td_->messages_manager_->reget_dialog_action_bar(DialogId(user_id_), "AddContactQuery");
188   }
189 };
190 
191 class AcceptContactQuery final : public Td::ResultHandler {
192   Promise<Unit> promise_;
193   UserId user_id_;
194 
195  public:
AcceptContactQuery(Promise<Unit> && promise)196   explicit AcceptContactQuery(Promise<Unit> &&promise) : promise_(std::move(promise)) {
197   }
198 
send(UserId user_id,tl_object_ptr<telegram_api::InputUser> && input_user)199   void send(UserId user_id, tl_object_ptr<telegram_api::InputUser> &&input_user) {
200     user_id_ = user_id;
201     send_query(G()->net_query_creator().create(telegram_api::contacts_acceptContact(std::move(input_user))));
202   }
203 
on_result(BufferSlice packet)204   void on_result(BufferSlice packet) final {
205     auto result_ptr = fetch_result<telegram_api::contacts_acceptContact>(packet);
206     if (result_ptr.is_error()) {
207       return on_error(result_ptr.move_as_error());
208     }
209 
210     auto ptr = result_ptr.move_as_ok();
211     LOG(INFO) << "Receive result for AcceptContactQuery: " << to_string(ptr);
212     td_->updates_manager_->on_get_updates(std::move(ptr), std::move(promise_));
213   }
214 
on_error(Status status)215   void on_error(Status status) final {
216     promise_.set_error(std::move(status));
217     td_->contacts_manager_->reload_contacts(true);
218     td_->messages_manager_->reget_dialog_action_bar(DialogId(user_id_), "AcceptContactQuery");
219   }
220 };
221 
222 class ImportContactsQuery final : public Td::ResultHandler {
223   int64 random_id_ = 0;
224   size_t sent_size_ = 0;
225 
226  public:
send(vector<tl_object_ptr<telegram_api::inputPhoneContact>> && input_phone_contacts,int64 random_id)227   void send(vector<tl_object_ptr<telegram_api::inputPhoneContact>> &&input_phone_contacts, int64 random_id) {
228     random_id_ = random_id;
229     sent_size_ = input_phone_contacts.size();
230     send_query(G()->net_query_creator().create(telegram_api::contacts_importContacts(std::move(input_phone_contacts))));
231   }
232 
on_result(BufferSlice packet)233   void on_result(BufferSlice packet) final {
234     auto result_ptr = fetch_result<telegram_api::contacts_importContacts>(packet);
235     if (result_ptr.is_error()) {
236       return on_error(result_ptr.move_as_error());
237     }
238 
239     auto ptr = result_ptr.move_as_ok();
240     LOG(INFO) << "Receive result for ImportContactsQuery: " << to_string(ptr);
241     if (sent_size_ == ptr->retry_contacts_.size()) {
242       return on_error(Status::Error(429, "Too Many Requests: retry after 3600"));
243     }
244     td_->contacts_manager_->on_imported_contacts(random_id_, std::move(ptr));
245   }
246 
on_error(Status status)247   void on_error(Status status) final {
248     td_->contacts_manager_->on_imported_contacts(random_id_, std::move(status));
249   }
250 };
251 
252 class DeleteContactsQuery final : public Td::ResultHandler {
253   Promise<Unit> promise_;
254 
255  public:
DeleteContactsQuery(Promise<Unit> && promise)256   explicit DeleteContactsQuery(Promise<Unit> &&promise) : promise_(std::move(promise)) {
257   }
258 
send(vector<tl_object_ptr<telegram_api::InputUser>> && input_users)259   void send(vector<tl_object_ptr<telegram_api::InputUser>> &&input_users) {
260     send_query(G()->net_query_creator().create(telegram_api::contacts_deleteContacts(std::move(input_users))));
261   }
262 
on_result(BufferSlice packet)263   void on_result(BufferSlice packet) final {
264     auto result_ptr = fetch_result<telegram_api::contacts_deleteContacts>(packet);
265     if (result_ptr.is_error()) {
266       return on_error(result_ptr.move_as_error());
267     }
268 
269     auto ptr = result_ptr.move_as_ok();
270     LOG(INFO) << "Receive result for DeleteContactsQuery: " << to_string(ptr);
271     td_->updates_manager_->on_get_updates(std::move(ptr), std::move(promise_));
272   }
273 
on_error(Status status)274   void on_error(Status status) final {
275     promise_.set_error(std::move(status));
276     td_->contacts_manager_->reload_contacts(true);
277   }
278 };
279 
280 class DeleteContactsByPhoneNumberQuery final : public Td::ResultHandler {
281   Promise<Unit> promise_;
282   vector<UserId> user_ids_;
283 
284  public:
DeleteContactsByPhoneNumberQuery(Promise<Unit> && promise)285   explicit DeleteContactsByPhoneNumberQuery(Promise<Unit> &&promise) : promise_(std::move(promise)) {
286   }
287 
send(vector<string> && user_phone_numbers,vector<UserId> && user_ids)288   void send(vector<string> &&user_phone_numbers, vector<UserId> &&user_ids) {
289     if (user_phone_numbers.empty()) {
290       return promise_.set_value(Unit());
291     }
292     user_ids_ = std::move(user_ids);
293     send_query(G()->net_query_creator().create(telegram_api::contacts_deleteByPhones(std::move(user_phone_numbers))));
294   }
295 
on_result(BufferSlice packet)296   void on_result(BufferSlice packet) final {
297     auto result_ptr = fetch_result<telegram_api::contacts_deleteByPhones>(packet);
298     if (result_ptr.is_error()) {
299       return on_error(result_ptr.move_as_error());
300     }
301 
302     bool result = result_ptr.ok();
303     if (!result) {
304       return on_error(Status::Error(500, "Some contacts can't be deleted"));
305     }
306 
307     td_->contacts_manager_->on_deleted_contacts(user_ids_);
308     promise_.set_value(Unit());
309   }
310 
on_error(Status status)311   void on_error(Status status) final {
312     promise_.set_error(std::move(status));
313     td_->contacts_manager_->reload_contacts(true);
314   }
315 };
316 
317 class ResetContactsQuery final : public Td::ResultHandler {
318   Promise<Unit> promise_;
319 
320  public:
ResetContactsQuery(Promise<Unit> && promise)321   explicit ResetContactsQuery(Promise<Unit> &&promise) : promise_(std::move(promise)) {
322   }
323 
send()324   void send() {
325     send_query(G()->net_query_creator().create(telegram_api::contacts_resetSaved()));
326   }
327 
on_result(BufferSlice packet)328   void on_result(BufferSlice packet) final {
329     auto result_ptr = fetch_result<telegram_api::contacts_resetSaved>(packet);
330     if (result_ptr.is_error()) {
331       return on_error(result_ptr.move_as_error());
332     }
333 
334     bool result = result_ptr.ok();
335     if (!result) {
336       LOG(ERROR) << "Failed to delete imported contacts";
337       td_->contacts_manager_->reload_contacts(true);
338     } else {
339       td_->contacts_manager_->on_update_contacts_reset();
340     }
341 
342     promise_.set_value(Unit());
343   }
344 
on_error(Status status)345   void on_error(Status status) final {
346     promise_.set_error(std::move(status));
347     td_->contacts_manager_->reload_contacts(true);
348   }
349 };
350 
351 class SearchDialogsNearbyQuery final : public Td::ResultHandler {
352   Promise<tl_object_ptr<telegram_api::Updates>> promise_;
353 
354  public:
SearchDialogsNearbyQuery(Promise<tl_object_ptr<telegram_api::Updates>> && promise)355   explicit SearchDialogsNearbyQuery(Promise<tl_object_ptr<telegram_api::Updates>> &&promise)
356       : promise_(std::move(promise)) {
357   }
358 
send(const Location & location,bool from_background,int32 expire_date)359   void send(const Location &location, bool from_background, int32 expire_date) {
360     int32 flags = 0;
361     if (from_background) {
362       flags |= telegram_api::contacts_getLocated::BACKGROUND_MASK;
363     }
364     if (expire_date != -1) {
365       flags |= telegram_api::contacts_getLocated::SELF_EXPIRES_MASK;
366     }
367     send_query(G()->net_query_creator().create(
368         telegram_api::contacts_getLocated(flags, false /*ignored*/, location.get_input_geo_point(), expire_date)));
369   }
370 
on_result(BufferSlice packet)371   void on_result(BufferSlice packet) final {
372     auto result_ptr = fetch_result<telegram_api::contacts_getLocated>(packet);
373     if (result_ptr.is_error()) {
374       return on_error(result_ptr.move_as_error());
375     }
376 
377     promise_.set_value(result_ptr.move_as_ok());
378   }
379 
on_error(Status status)380   void on_error(Status status) final {
381     promise_.set_error(std::move(status));
382   }
383 };
384 
385 class UploadProfilePhotoQuery final : public Td::ResultHandler {
386   Promise<Unit> promise_;
387   FileId file_id_;
388 
389  public:
UploadProfilePhotoQuery(Promise<Unit> && promise)390   explicit UploadProfilePhotoQuery(Promise<Unit> &&promise) : promise_(std::move(promise)) {
391   }
392 
send(FileId file_id,tl_object_ptr<telegram_api::InputFile> && input_file,bool is_animation,double main_frame_timestamp)393   void send(FileId file_id, tl_object_ptr<telegram_api::InputFile> &&input_file, bool is_animation,
394             double main_frame_timestamp) {
395     CHECK(input_file != nullptr);
396     CHECK(file_id.is_valid());
397 
398     file_id_ = file_id;
399 
400     int32 flags = 0;
401     tl_object_ptr<telegram_api::InputFile> photo_input_file;
402     tl_object_ptr<telegram_api::InputFile> video_input_file;
403     if (is_animation) {
404       flags |= telegram_api::photos_uploadProfilePhoto::VIDEO_MASK;
405       video_input_file = std::move(input_file);
406 
407       if (main_frame_timestamp != 0.0) {
408         flags |= telegram_api::photos_uploadProfilePhoto::VIDEO_START_TS_MASK;
409       }
410     } else {
411       flags |= telegram_api::photos_uploadProfilePhoto::FILE_MASK;
412       photo_input_file = std::move(input_file);
413     }
414     send_query(G()->net_query_creator().create(telegram_api::photos_uploadProfilePhoto(
415         flags, std::move(photo_input_file), std::move(video_input_file), main_frame_timestamp)));
416   }
417 
on_result(BufferSlice packet)418   void on_result(BufferSlice packet) final {
419     auto result_ptr = fetch_result<telegram_api::photos_uploadProfilePhoto>(packet);
420     if (result_ptr.is_error()) {
421       return on_error(result_ptr.move_as_error());
422     }
423 
424     td_->contacts_manager_->on_set_profile_photo(result_ptr.move_as_ok(), 0);
425 
426     td_->file_manager_->delete_partial_remote_location(file_id_);
427 
428     promise_.set_value(Unit());
429   }
430 
on_error(Status status)431   void on_error(Status status) final {
432     promise_.set_error(std::move(status));
433     td_->file_manager_->delete_partial_remote_location(file_id_);
434     td_->updates_manager_->get_difference("UploadProfilePhotoQuery");
435   }
436 };
437 
438 class UpdateProfilePhotoQuery final : public Td::ResultHandler {
439   Promise<Unit> promise_;
440   FileId file_id_;
441   int64 old_photo_id_;
442   string file_reference_;
443 
444  public:
UpdateProfilePhotoQuery(Promise<Unit> && promise)445   explicit UpdateProfilePhotoQuery(Promise<Unit> &&promise) : promise_(std::move(promise)) {
446   }
447 
send(FileId file_id,int64 old_photo_id,tl_object_ptr<telegram_api::InputPhoto> && input_photo)448   void send(FileId file_id, int64 old_photo_id, tl_object_ptr<telegram_api::InputPhoto> &&input_photo) {
449     CHECK(input_photo != nullptr);
450     file_id_ = file_id;
451     old_photo_id_ = old_photo_id;
452     file_reference_ = FileManager::extract_file_reference(input_photo);
453     send_query(G()->net_query_creator().create(telegram_api::photos_updateProfilePhoto(std::move(input_photo))));
454   }
455 
on_result(BufferSlice packet)456   void on_result(BufferSlice packet) final {
457     auto result_ptr = fetch_result<telegram_api::photos_updateProfilePhoto>(packet);
458     if (result_ptr.is_error()) {
459       return on_error(result_ptr.move_as_error());
460     }
461 
462     td_->contacts_manager_->on_set_profile_photo(result_ptr.move_as_ok(), old_photo_id_);
463 
464     promise_.set_value(Unit());
465   }
466 
on_error(Status status)467   void on_error(Status status) final {
468     if (!td_->auth_manager_->is_bot() && FileReferenceManager::is_file_reference_error(status)) {
469       if (file_id_.is_valid()) {
470         VLOG(file_references) << "Receive " << status << " for " << file_id_;
471         td_->file_manager_->delete_file_reference(file_id_, file_reference_);
472         td_->file_reference_manager_->repair_file_reference(
473             file_id_, PromiseCreator::lambda([file_id = file_id_, old_photo_id = old_photo_id_,
474                                               promise = std::move(promise_)](Result<Unit> result) mutable {
475               if (result.is_error()) {
476                 return promise.set_error(Status::Error(400, "Can't find the photo"));
477               }
478 
479               send_closure(G()->contacts_manager(), &ContactsManager::send_update_profile_photo_query, file_id,
480                            old_photo_id, std::move(promise));
481             }));
482         return;
483       } else {
484         LOG(ERROR) << "Receive file reference error, but file_id = " << file_id_;
485       }
486     }
487 
488     promise_.set_error(std::move(status));
489   }
490 };
491 
492 class DeleteProfilePhotoQuery final : public Td::ResultHandler {
493   Promise<Unit> promise_;
494   int64 profile_photo_id_;
495 
496  public:
DeleteProfilePhotoQuery(Promise<Unit> && promise)497   explicit DeleteProfilePhotoQuery(Promise<Unit> &&promise) : promise_(std::move(promise)) {
498   }
499 
send(int64 profile_photo_id)500   void send(int64 profile_photo_id) {
501     profile_photo_id_ = profile_photo_id;
502     vector<tl_object_ptr<telegram_api::InputPhoto>> input_photo_ids;
503     input_photo_ids.push_back(make_tl_object<telegram_api::inputPhoto>(profile_photo_id, 0, BufferSlice()));
504     send_query(G()->net_query_creator().create(telegram_api::photos_deletePhotos(std::move(input_photo_ids))));
505   }
506 
on_result(BufferSlice packet)507   void on_result(BufferSlice packet) final {
508     auto result_ptr = fetch_result<telegram_api::photos_deletePhotos>(packet);
509     if (result_ptr.is_error()) {
510       return on_error(result_ptr.move_as_error());
511     }
512 
513     auto result = result_ptr.move_as_ok();
514     LOG(INFO) << "Receive result for DeleteProfilePhotoQuery: " << format::as_array(result);
515     if (result.size() != 1u) {
516       LOG(WARNING) << "Photo can't be deleted";
517       return on_error(Status::Error(400, "Photo can't be deleted"));
518     }
519 
520     td_->contacts_manager_->on_delete_profile_photo(profile_photo_id_, std::move(promise_));
521   }
522 
on_error(Status status)523   void on_error(Status status) final {
524     promise_.set_error(std::move(status));
525   }
526 };
527 
528 class UpdateProfileQuery final : public Td::ResultHandler {
529   Promise<Unit> promise_;
530   int32 flags_;
531   string first_name_;
532   string last_name_;
533   string about_;
534 
535  public:
UpdateProfileQuery(Promise<Unit> && promise)536   explicit UpdateProfileQuery(Promise<Unit> &&promise) : promise_(std::move(promise)) {
537   }
538 
send(int32 flags,const string & first_name,const string & last_name,const string & about)539   void send(int32 flags, const string &first_name, const string &last_name, const string &about) {
540     flags_ = flags;
541     first_name_ = first_name;
542     last_name_ = last_name;
543     about_ = about;
544     send_query(
545         G()->net_query_creator().create(telegram_api::account_updateProfile(flags, first_name, last_name, about)));
546   }
547 
on_result(BufferSlice packet)548   void on_result(BufferSlice packet) final {
549     auto result_ptr = fetch_result<telegram_api::account_updateProfile>(packet);
550     if (result_ptr.is_error()) {
551       return on_error(result_ptr.move_as_error());
552     }
553 
554     LOG(DEBUG) << "Receive result for UpdateProfileQuery: " << to_string(result_ptr.ok());
555     td_->contacts_manager_->on_get_user(result_ptr.move_as_ok(), "UpdateProfileQuery");
556     td_->contacts_manager_->on_update_profile_success(flags_, first_name_, last_name_, about_);
557 
558     promise_.set_value(Unit());
559   }
560 
on_error(Status status)561   void on_error(Status status) final {
562     promise_.set_error(std::move(status));
563   }
564 };
565 
566 class CheckUsernameQuery final : public Td::ResultHandler {
567   Promise<bool> promise_;
568 
569  public:
CheckUsernameQuery(Promise<bool> && promise)570   explicit CheckUsernameQuery(Promise<bool> &&promise) : promise_(std::move(promise)) {
571   }
572 
send(const string & username)573   void send(const string &username) {
574     send_query(G()->net_query_creator().create(telegram_api::account_checkUsername(username)));
575   }
576 
on_result(BufferSlice packet)577   void on_result(BufferSlice packet) final {
578     auto result_ptr = fetch_result<telegram_api::account_checkUsername>(packet);
579     if (result_ptr.is_error()) {
580       return on_error(result_ptr.move_as_error());
581     }
582 
583     promise_.set_value(result_ptr.move_as_ok());
584   }
585 
on_error(Status status)586   void on_error(Status status) final {
587     promise_.set_error(std::move(status));
588   }
589 };
590 
591 class UpdateUsernameQuery final : public Td::ResultHandler {
592   Promise<Unit> promise_;
593 
594  public:
UpdateUsernameQuery(Promise<Unit> && promise)595   explicit UpdateUsernameQuery(Promise<Unit> &&promise) : promise_(std::move(promise)) {
596   }
597 
send(const string & username)598   void send(const string &username) {
599     send_query(G()->net_query_creator().create(telegram_api::account_updateUsername(username)));
600   }
601 
on_result(BufferSlice packet)602   void on_result(BufferSlice packet) final {
603     auto result_ptr = fetch_result<telegram_api::account_updateUsername>(packet);
604     if (result_ptr.is_error()) {
605       return on_error(result_ptr.move_as_error());
606     }
607 
608     LOG(DEBUG) << "Receive result for UpdateUsernameQuery: " << to_string(result_ptr.ok());
609     td_->contacts_manager_->on_get_user(result_ptr.move_as_ok(), "UpdateUsernameQuery");
610     promise_.set_value(Unit());
611   }
612 
on_error(Status status)613   void on_error(Status status) final {
614     if (status.message() == "USERNAME_NOT_MODIFIED" && !td_->auth_manager_->is_bot()) {
615       promise_.set_value(Unit());
616       return;
617     }
618     promise_.set_error(std::move(status));
619   }
620 };
621 
622 class CheckChannelUsernameQuery final : public Td::ResultHandler {
623   Promise<bool> promise_;
624   ChannelId channel_id_;
625   string username_;
626 
627  public:
CheckChannelUsernameQuery(Promise<bool> && promise)628   explicit CheckChannelUsernameQuery(Promise<bool> &&promise) : promise_(std::move(promise)) {
629   }
630 
send(ChannelId channel_id,const string & username)631   void send(ChannelId channel_id, const string &username) {
632     channel_id_ = channel_id;
633     tl_object_ptr<telegram_api::InputChannel> input_channel;
634     if (channel_id.is_valid()) {
635       input_channel = td_->contacts_manager_->get_input_channel(channel_id);
636     } else {
637       input_channel = make_tl_object<telegram_api::inputChannelEmpty>();
638     }
639     CHECK(input_channel != nullptr);
640     send_query(
641         G()->net_query_creator().create(telegram_api::channels_checkUsername(std::move(input_channel), username)));
642   }
643 
on_result(BufferSlice packet)644   void on_result(BufferSlice packet) final {
645     auto result_ptr = fetch_result<telegram_api::channels_checkUsername>(packet);
646     if (result_ptr.is_error()) {
647       return on_error(result_ptr.move_as_error());
648     }
649 
650     promise_.set_value(result_ptr.move_as_ok());
651   }
652 
on_error(Status status)653   void on_error(Status status) final {
654     if (channel_id_.is_valid()) {
655       td_->contacts_manager_->on_get_channel_error(channel_id_, status, "CheckChannelUsernameQuery");
656     }
657     promise_.set_error(std::move(status));
658   }
659 };
660 
661 class UpdateChannelUsernameQuery final : public Td::ResultHandler {
662   Promise<Unit> promise_;
663   ChannelId channel_id_;
664   string username_;
665 
666  public:
UpdateChannelUsernameQuery(Promise<Unit> && promise)667   explicit UpdateChannelUsernameQuery(Promise<Unit> &&promise) : promise_(std::move(promise)) {
668   }
669 
send(ChannelId channel_id,const string & username)670   void send(ChannelId channel_id, const string &username) {
671     channel_id_ = channel_id;
672     username_ = username;
673     auto input_channel = td_->contacts_manager_->get_input_channel(channel_id);
674     CHECK(input_channel != nullptr);
675     send_query(
676         G()->net_query_creator().create(telegram_api::channels_updateUsername(std::move(input_channel), username)));
677   }
678 
on_result(BufferSlice packet)679   void on_result(BufferSlice packet) final {
680     auto result_ptr = fetch_result<telegram_api::channels_updateUsername>(packet);
681     if (result_ptr.is_error()) {
682       return on_error(result_ptr.move_as_error());
683     }
684 
685     bool result = result_ptr.ok();
686     LOG(DEBUG) << "Receive result for UpdateChannelUsernameQuery: " << result;
687     if (!result) {
688       return on_error(Status::Error(500, "Supergroup username is not updated"));
689     }
690 
691     td_->contacts_manager_->on_update_channel_username(channel_id_, std::move(username_));
692     promise_.set_value(Unit());
693   }
694 
on_error(Status status)695   void on_error(Status status) final {
696     if (status.message() == "USERNAME_NOT_MODIFIED" || status.message() == "CHAT_NOT_MODIFIED") {
697       td_->contacts_manager_->on_update_channel_username(channel_id_, std::move(username_));
698       if (!td_->auth_manager_->is_bot()) {
699         promise_.set_value(Unit());
700         return;
701       }
702     } else {
703       td_->contacts_manager_->on_get_channel_error(channel_id_, status, "UpdateChannelUsernameQuery");
704     }
705     promise_.set_error(std::move(status));
706   }
707 };
708 
709 class SetChannelStickerSetQuery final : public Td::ResultHandler {
710   Promise<Unit> promise_;
711   ChannelId channel_id_;
712   StickerSetId sticker_set_id_;
713 
714  public:
SetChannelStickerSetQuery(Promise<Unit> && promise)715   explicit SetChannelStickerSetQuery(Promise<Unit> &&promise) : promise_(std::move(promise)) {
716   }
717 
send(ChannelId channel_id,StickerSetId sticker_set_id,telegram_api::object_ptr<telegram_api::InputStickerSet> && input_sticker_set)718   void send(ChannelId channel_id, StickerSetId sticker_set_id,
719             telegram_api::object_ptr<telegram_api::InputStickerSet> &&input_sticker_set) {
720     channel_id_ = channel_id;
721     sticker_set_id_ = sticker_set_id;
722     auto input_channel = td_->contacts_manager_->get_input_channel(channel_id);
723     CHECK(input_channel != nullptr);
724     send_query(G()->net_query_creator().create(
725         telegram_api::channels_setStickers(std::move(input_channel), std::move(input_sticker_set))));
726   }
727 
on_result(BufferSlice packet)728   void on_result(BufferSlice packet) final {
729     auto result_ptr = fetch_result<telegram_api::channels_setStickers>(packet);
730     if (result_ptr.is_error()) {
731       return on_error(result_ptr.move_as_error());
732     }
733 
734     bool result = result_ptr.ok();
735     LOG(DEBUG) << "Receive result for SetChannelStickerSetQuery: " << result;
736     if (!result) {
737       return on_error(Status::Error(500, "Supergroup sticker set not updated"));
738     }
739 
740     td_->contacts_manager_->on_update_channel_sticker_set(channel_id_, sticker_set_id_);
741     promise_.set_value(Unit());
742   }
743 
on_error(Status status)744   void on_error(Status status) final {
745     if (status.message() == "CHAT_NOT_MODIFIED") {
746       td_->contacts_manager_->on_update_channel_sticker_set(channel_id_, sticker_set_id_);
747       if (!td_->auth_manager_->is_bot()) {
748         promise_.set_value(Unit());
749         return;
750       }
751     } else {
752       td_->contacts_manager_->on_get_channel_error(channel_id_, status, "SetChannelStickerSetQuery");
753     }
754     promise_.set_error(std::move(status));
755   }
756 };
757 
758 class ToggleChannelSignaturesQuery final : public Td::ResultHandler {
759   Promise<Unit> promise_;
760   ChannelId channel_id_;
761 
762  public:
ToggleChannelSignaturesQuery(Promise<Unit> && promise)763   explicit ToggleChannelSignaturesQuery(Promise<Unit> &&promise) : promise_(std::move(promise)) {
764   }
765 
send(ChannelId channel_id,bool sign_messages)766   void send(ChannelId channel_id, bool sign_messages) {
767     channel_id_ = channel_id;
768     auto input_channel = td_->contacts_manager_->get_input_channel(channel_id);
769     CHECK(input_channel != nullptr);
770     send_query(G()->net_query_creator().create(
771         telegram_api::channels_toggleSignatures(std::move(input_channel), sign_messages)));
772   }
773 
on_result(BufferSlice packet)774   void on_result(BufferSlice packet) final {
775     auto result_ptr = fetch_result<telegram_api::channels_toggleSignatures>(packet);
776     if (result_ptr.is_error()) {
777       return on_error(result_ptr.move_as_error());
778     }
779 
780     auto ptr = result_ptr.move_as_ok();
781     LOG(INFO) << "Receive result for ToggleChannelSignaturesQuery: " << to_string(ptr);
782     td_->updates_manager_->on_get_updates(std::move(ptr), std::move(promise_));
783   }
784 
on_error(Status status)785   void on_error(Status status) final {
786     if (status.message() == "CHAT_NOT_MODIFIED") {
787       if (!td_->auth_manager_->is_bot()) {
788         promise_.set_value(Unit());
789         return;
790       }
791     } else {
792       td_->contacts_manager_->on_get_channel_error(channel_id_, status, "ToggleChannelSignaturesQuery");
793     }
794     promise_.set_error(std::move(status));
795   }
796 };
797 
798 class TogglePrehistoryHiddenQuery final : public Td::ResultHandler {
799   Promise<Unit> promise_;
800   ChannelId channel_id_;
801   bool is_all_history_available_;
802 
803  public:
TogglePrehistoryHiddenQuery(Promise<Unit> && promise)804   explicit TogglePrehistoryHiddenQuery(Promise<Unit> &&promise) : promise_(std::move(promise)) {
805   }
806 
send(ChannelId channel_id,bool is_all_history_available)807   void send(ChannelId channel_id, bool is_all_history_available) {
808     channel_id_ = channel_id;
809     is_all_history_available_ = is_all_history_available;
810 
811     auto input_channel = td_->contacts_manager_->get_input_channel(channel_id);
812     CHECK(input_channel != nullptr);
813     send_query(G()->net_query_creator().create(
814         telegram_api::channels_togglePreHistoryHidden(std::move(input_channel), !is_all_history_available)));
815   }
816 
on_result(BufferSlice packet)817   void on_result(BufferSlice packet) final {
818     auto result_ptr = fetch_result<telegram_api::channels_togglePreHistoryHidden>(packet);
819     if (result_ptr.is_error()) {
820       return on_error(result_ptr.move_as_error());
821     }
822 
823     auto ptr = result_ptr.move_as_ok();
824     LOG(INFO) << "Receive result for TogglePrehistoryHiddenQuery: " << to_string(ptr);
825 
826     td_->updates_manager_->on_get_updates(
827         std::move(ptr),
828         PromiseCreator::lambda([actor_id = G()->contacts_manager(), promise = std::move(promise_),
829                                 channel_id = channel_id_,
830                                 is_all_history_available = is_all_history_available_](Unit result) mutable {
831           send_closure(actor_id, &ContactsManager::on_update_channel_is_all_history_available, channel_id,
832                        is_all_history_available, std::move(promise));
833         }));
834   }
835 
on_error(Status status)836   void on_error(Status status) final {
837     if (status.message() == "CHAT_NOT_MODIFIED") {
838       if (!td_->auth_manager_->is_bot()) {
839         promise_.set_value(Unit());
840         return;
841       }
842     } else {
843       td_->contacts_manager_->on_get_channel_error(channel_id_, status, "TogglePrehistoryHiddenQuery");
844     }
845     promise_.set_error(std::move(status));
846   }
847 };
848 
849 class ConvertToGigagroupQuery final : public Td::ResultHandler {
850   Promise<Unit> promise_;
851   ChannelId channel_id_;
852 
853  public:
ConvertToGigagroupQuery(Promise<Unit> && promise)854   explicit ConvertToGigagroupQuery(Promise<Unit> &&promise) : promise_(std::move(promise)) {
855   }
856 
send(ChannelId channel_id)857   void send(ChannelId channel_id) {
858     channel_id_ = channel_id;
859 
860     auto input_channel = td_->contacts_manager_->get_input_channel(channel_id);
861     CHECK(input_channel != nullptr);
862     send_query(G()->net_query_creator().create(telegram_api::channels_convertToGigagroup(std::move(input_channel))));
863   }
864 
on_result(BufferSlice packet)865   void on_result(BufferSlice packet) final {
866     auto result_ptr = fetch_result<telegram_api::channels_convertToGigagroup>(packet);
867     if (result_ptr.is_error()) {
868       return on_error(result_ptr.move_as_error());
869     }
870 
871     auto ptr = result_ptr.move_as_ok();
872     LOG(INFO) << "Receive result for ConvertToGigagroupQuery: " << to_string(ptr);
873 
874     td_->updates_manager_->on_get_updates(std::move(ptr), std::move(promise_));
875   }
876 
on_error(Status status)877   void on_error(Status status) final {
878     if (status.message() == "CHAT_NOT_MODIFIED") {
879       promise_.set_value(Unit());
880       return;
881     } else {
882       td_->contacts_manager_->on_get_channel_error(channel_id_, status, "ConvertToGigagroupQuery");
883     }
884     promise_.set_error(std::move(status));
885   }
886 };
887 
888 class EditChatAboutQuery final : public Td::ResultHandler {
889   Promise<Unit> promise_;
890   DialogId dialog_id_;
891   string about_;
892 
on_success()893   void on_success() {
894     switch (dialog_id_.get_type()) {
895       case DialogType::Chat:
896         return td_->contacts_manager_->on_update_chat_description(dialog_id_.get_chat_id(), std::move(about_));
897       case DialogType::Channel:
898         return td_->contacts_manager_->on_update_channel_description(dialog_id_.get_channel_id(), std::move(about_));
899       case DialogType::User:
900       case DialogType::SecretChat:
901       case DialogType::None:
902         UNREACHABLE();
903     }
904   }
905 
906  public:
EditChatAboutQuery(Promise<Unit> && promise)907   explicit EditChatAboutQuery(Promise<Unit> &&promise) : promise_(std::move(promise)) {
908   }
909 
send(DialogId dialog_id,const string & about)910   void send(DialogId dialog_id, const string &about) {
911     dialog_id_ = dialog_id;
912     about_ = about;
913     auto input_peer = td_->messages_manager_->get_input_peer(dialog_id, AccessRights::Write);
914     if (input_peer == nullptr) {
915       return on_error(Status::Error(400, "Can't access the chat"));
916     }
917     send_query(G()->net_query_creator().create(telegram_api::messages_editChatAbout(std::move(input_peer), about)));
918   }
919 
on_result(BufferSlice packet)920   void on_result(BufferSlice packet) final {
921     auto result_ptr = fetch_result<telegram_api::messages_editChatAbout>(packet);
922     if (result_ptr.is_error()) {
923       return on_error(result_ptr.move_as_error());
924     }
925 
926     bool result = result_ptr.ok();
927     LOG(DEBUG) << "Receive result for EditChatAboutQuery: " << result;
928     if (!result) {
929       return on_error(Status::Error(500, "Chat description is not updated"));
930     }
931 
932     on_success();
933     promise_.set_value(Unit());
934   }
935 
on_error(Status status)936   void on_error(Status status) final {
937     if (status.message() == "CHAT_ABOUT_NOT_MODIFIED" || status.message() == "CHAT_NOT_MODIFIED") {
938       on_success();
939       if (!td_->auth_manager_->is_bot()) {
940         promise_.set_value(Unit());
941         return;
942       }
943     } else {
944       td_->messages_manager_->on_get_dialog_error(dialog_id_, status, "EditChatAboutQuery");
945     }
946     promise_.set_error(std::move(status));
947   }
948 };
949 
950 class SetDiscussionGroupQuery final : public Td::ResultHandler {
951   Promise<Unit> promise_;
952   ChannelId broadcast_channel_id_;
953   ChannelId group_channel_id_;
954 
955  public:
SetDiscussionGroupQuery(Promise<Unit> && promise)956   explicit SetDiscussionGroupQuery(Promise<Unit> &&promise) : promise_(std::move(promise)) {
957   }
958 
send(ChannelId broadcast_channel_id,telegram_api::object_ptr<telegram_api::InputChannel> broadcast_input_channel,ChannelId group_channel_id,telegram_api::object_ptr<telegram_api::InputChannel> group_input_channel)959   void send(ChannelId broadcast_channel_id,
960             telegram_api::object_ptr<telegram_api::InputChannel> broadcast_input_channel, ChannelId group_channel_id,
961             telegram_api::object_ptr<telegram_api::InputChannel> group_input_channel) {
962     broadcast_channel_id_ = broadcast_channel_id;
963     group_channel_id_ = group_channel_id;
964     send_query(G()->net_query_creator().create(
965         telegram_api::channels_setDiscussionGroup(std::move(broadcast_input_channel), std::move(group_input_channel))));
966   }
967 
on_result(BufferSlice packet)968   void on_result(BufferSlice packet) final {
969     auto result_ptr = fetch_result<telegram_api::channels_setDiscussionGroup>(packet);
970     if (result_ptr.is_error()) {
971       return on_error(result_ptr.move_as_error());
972     }
973 
974     bool result = result_ptr.move_as_ok();
975     LOG_IF(INFO, !result) << "Set discussion group has failed";
976 
977     td_->contacts_manager_->on_update_channel_linked_channel_id(broadcast_channel_id_, group_channel_id_);
978     promise_.set_value(Unit());
979   }
980 
on_error(Status status)981   void on_error(Status status) final {
982     if (status.message() == "LINK_NOT_MODIFIED") {
983       return promise_.set_value(Unit());
984     }
985     promise_.set_error(std::move(status));
986   }
987 };
988 
989 class EditLocationQuery final : public Td::ResultHandler {
990   Promise<Unit> promise_;
991   ChannelId channel_id_;
992   DialogLocation location_;
993 
994  public:
EditLocationQuery(Promise<Unit> && promise)995   explicit EditLocationQuery(Promise<Unit> &&promise) : promise_(std::move(promise)) {
996   }
997 
send(ChannelId channel_id,const DialogLocation & location)998   void send(ChannelId channel_id, const DialogLocation &location) {
999     channel_id_ = channel_id;
1000     location_ = location;
1001 
1002     auto input_channel = td_->contacts_manager_->get_input_channel(channel_id);
1003     CHECK(input_channel != nullptr);
1004 
1005     send_query(G()->net_query_creator().create(telegram_api::channels_editLocation(
1006         std::move(input_channel), location_.get_input_geo_point(), location_.get_address())));
1007   }
1008 
on_result(BufferSlice packet)1009   void on_result(BufferSlice packet) final {
1010     auto result_ptr = fetch_result<telegram_api::channels_editLocation>(packet);
1011     if (result_ptr.is_error()) {
1012       return on_error(result_ptr.move_as_error());
1013     }
1014 
1015     bool result = result_ptr.move_as_ok();
1016     LOG_IF(INFO, !result) << "Edit chat location has failed";
1017 
1018     td_->contacts_manager_->on_update_channel_location(channel_id_, location_);
1019     promise_.set_value(Unit());
1020   }
1021 
on_error(Status status)1022   void on_error(Status status) final {
1023     td_->contacts_manager_->on_get_channel_error(channel_id_, status, "EditLocationQuery");
1024     promise_.set_error(std::move(status));
1025   }
1026 };
1027 
1028 class ToggleSlowModeQuery final : public Td::ResultHandler {
1029   Promise<Unit> promise_;
1030   ChannelId channel_id_;
1031   int32 slow_mode_delay_ = 0;
1032 
1033  public:
ToggleSlowModeQuery(Promise<Unit> && promise)1034   explicit ToggleSlowModeQuery(Promise<Unit> &&promise) : promise_(std::move(promise)) {
1035   }
1036 
send(ChannelId channel_id,int32 slow_mode_delay)1037   void send(ChannelId channel_id, int32 slow_mode_delay) {
1038     channel_id_ = channel_id;
1039     slow_mode_delay_ = slow_mode_delay;
1040 
1041     auto input_channel = td_->contacts_manager_->get_input_channel(channel_id);
1042     CHECK(input_channel != nullptr);
1043 
1044     send_query(G()->net_query_creator().create(
1045         telegram_api::channels_toggleSlowMode(std::move(input_channel), slow_mode_delay)));
1046   }
1047 
on_result(BufferSlice packet)1048   void on_result(BufferSlice packet) final {
1049     auto result_ptr = fetch_result<telegram_api::channels_toggleSlowMode>(packet);
1050     if (result_ptr.is_error()) {
1051       return on_error(result_ptr.move_as_error());
1052     }
1053 
1054     auto ptr = result_ptr.move_as_ok();
1055     LOG(INFO) << "Receive result for ToggleSlowModeQuery: " << to_string(ptr);
1056 
1057     td_->updates_manager_->on_get_updates(
1058         std::move(ptr),
1059         PromiseCreator::lambda([actor_id = G()->contacts_manager(), promise = std::move(promise_),
1060                                 channel_id = channel_id_, slow_mode_delay = slow_mode_delay_](Unit result) mutable {
1061           send_closure(actor_id, &ContactsManager::on_update_channel_slow_mode_delay, channel_id, slow_mode_delay,
1062                        std::move(promise));
1063         }));
1064   }
1065 
on_error(Status status)1066   void on_error(Status status) final {
1067     if (status.message() == "CHAT_NOT_MODIFIED") {
1068       td_->contacts_manager_->on_update_channel_slow_mode_delay(channel_id_, slow_mode_delay_, Promise<Unit>());
1069       if (!td_->auth_manager_->is_bot()) {
1070         promise_.set_value(Unit());
1071         return;
1072       }
1073     } else {
1074       td_->contacts_manager_->on_get_channel_error(channel_id_, status, "ToggleSlowModeQuery");
1075     }
1076     promise_.set_error(std::move(status));
1077   }
1078 };
1079 
1080 class ReportChannelSpamQuery final : public Td::ResultHandler {
1081   Promise<Unit> promise_;
1082   ChannelId channel_id_;
1083 
1084  public:
ReportChannelSpamQuery(Promise<Unit> && promise)1085   explicit ReportChannelSpamQuery(Promise<Unit> &&promise) : promise_(std::move(promise)) {
1086   }
1087 
send(ChannelId channel_id,DialogId sender_dialog_id,const vector<MessageId> & message_ids)1088   void send(ChannelId channel_id, DialogId sender_dialog_id, const vector<MessageId> &message_ids) {
1089     channel_id_ = channel_id;
1090 
1091     auto input_channel = td_->contacts_manager_->get_input_channel(channel_id);
1092     CHECK(input_channel != nullptr);
1093 
1094     auto input_peer = td_->messages_manager_->get_input_peer(sender_dialog_id, AccessRights::Know);
1095     CHECK(input_peer != nullptr);
1096 
1097     send_query(G()->net_query_creator().create(telegram_api::channels_reportSpam(
1098         std::move(input_channel), std::move(input_peer), MessagesManager::get_server_message_ids(message_ids))));
1099   }
1100 
on_result(BufferSlice packet)1101   void on_result(BufferSlice packet) final {
1102     auto result_ptr = fetch_result<telegram_api::channels_reportSpam>(packet);
1103     if (result_ptr.is_error()) {
1104       return on_error(result_ptr.move_as_error());
1105     }
1106 
1107     bool result = result_ptr.move_as_ok();
1108     LOG_IF(INFO, !result) << "Report spam has failed in " << channel_id_;
1109 
1110     promise_.set_value(Unit());
1111   }
1112 
on_error(Status status)1113   void on_error(Status status) final {
1114     // td_->contacts_manager_->on_get_channel_error(channel_id_, status, "ReportChannelSpamQuery");
1115     promise_.set_error(std::move(status));
1116   }
1117 };
1118 
1119 class DeleteChatQuery final : public Td::ResultHandler {
1120   Promise<Unit> promise_;
1121 
1122  public:
DeleteChatQuery(Promise<Unit> && promise)1123   explicit DeleteChatQuery(Promise<Unit> &&promise) : promise_(std::move(promise)) {
1124   }
1125 
send(ChatId chat_id)1126   void send(ChatId chat_id) {
1127     send_query(G()->net_query_creator().create(telegram_api::messages_deleteChat(chat_id.get())));
1128   }
1129 
on_result(BufferSlice packet)1130   void on_result(BufferSlice packet) final {
1131     auto result_ptr = fetch_result<telegram_api::messages_deleteChat>(packet);
1132     if (result_ptr.is_error()) {
1133       return on_error(result_ptr.move_as_error());
1134     }
1135 
1136     LOG(INFO) << "Receive result for DeleteChatQuery: " << result_ptr.ok();
1137     td_->updates_manager_->get_difference("DeleteChatQuery");
1138     td_->updates_manager_->on_get_updates(make_tl_object<telegram_api::updates>(), std::move(promise_));
1139   }
1140 
on_error(Status status)1141   void on_error(Status status) final {
1142     promise_.set_error(std::move(status));
1143   }
1144 };
1145 
1146 class DeleteChannelQuery final : public Td::ResultHandler {
1147   Promise<Unit> promise_;
1148   ChannelId channel_id_;
1149 
1150  public:
DeleteChannelQuery(Promise<Unit> && promise)1151   explicit DeleteChannelQuery(Promise<Unit> &&promise) : promise_(std::move(promise)) {
1152   }
1153 
send(ChannelId channel_id)1154   void send(ChannelId channel_id) {
1155     channel_id_ = channel_id;
1156     auto input_channel = td_->contacts_manager_->get_input_channel(channel_id);
1157     CHECK(input_channel != nullptr);
1158     send_query(G()->net_query_creator().create(telegram_api::channels_deleteChannel(std::move(input_channel))));
1159   }
1160 
on_result(BufferSlice packet)1161   void on_result(BufferSlice packet) final {
1162     auto result_ptr = fetch_result<telegram_api::channels_deleteChannel>(packet);
1163     if (result_ptr.is_error()) {
1164       return on_error(result_ptr.move_as_error());
1165     }
1166 
1167     auto ptr = result_ptr.move_as_ok();
1168     LOG(INFO) << "Receive result for DeleteChannelQuery: " << to_string(ptr);
1169     td_->updates_manager_->on_get_updates(std::move(ptr), std::move(promise_));
1170   }
1171 
on_error(Status status)1172   void on_error(Status status) final {
1173     td_->contacts_manager_->on_get_channel_error(channel_id_, status, "DeleteChannelQuery");
1174     promise_.set_error(std::move(status));
1175   }
1176 };
1177 
1178 class AddChatUserQuery final : public Td::ResultHandler {
1179   Promise<Unit> promise_;
1180 
1181  public:
AddChatUserQuery(Promise<Unit> && promise)1182   explicit AddChatUserQuery(Promise<Unit> &&promise) : promise_(std::move(promise)) {
1183   }
1184 
send(ChatId chat_id,tl_object_ptr<telegram_api::InputUser> && input_user,int32 forward_limit)1185   void send(ChatId chat_id, tl_object_ptr<telegram_api::InputUser> &&input_user, int32 forward_limit) {
1186     send_query(G()->net_query_creator().create(
1187         telegram_api::messages_addChatUser(chat_id.get(), std::move(input_user), forward_limit)));
1188   }
1189 
on_result(BufferSlice packet)1190   void on_result(BufferSlice packet) final {
1191     auto result_ptr = fetch_result<telegram_api::messages_addChatUser>(packet);
1192     if (result_ptr.is_error()) {
1193       return on_error(result_ptr.move_as_error());
1194     }
1195 
1196     auto ptr = result_ptr.move_as_ok();
1197     LOG(INFO) << "Receive result for AddChatUserQuery: " << to_string(ptr);
1198     td_->updates_manager_->on_get_updates(std::move(ptr), std::move(promise_));
1199   }
1200 
on_error(Status status)1201   void on_error(Status status) final {
1202     promise_.set_error(std::move(status));
1203     td_->updates_manager_->get_difference("AddChatUserQuery");
1204   }
1205 };
1206 
1207 class EditChatAdminQuery final : public Td::ResultHandler {
1208   Promise<Unit> promise_;
1209   ChatId chat_id_;
1210 
1211  public:
EditChatAdminQuery(Promise<Unit> && promise)1212   explicit EditChatAdminQuery(Promise<Unit> &&promise) : promise_(std::move(promise)) {
1213   }
1214 
send(ChatId chat_id,tl_object_ptr<telegram_api::InputUser> && input_user,bool is_administrator)1215   void send(ChatId chat_id, tl_object_ptr<telegram_api::InputUser> &&input_user, bool is_administrator) {
1216     chat_id_ = chat_id;
1217     send_query(G()->net_query_creator().create(
1218         telegram_api::messages_editChatAdmin(chat_id.get(), std::move(input_user), is_administrator)));
1219   }
1220 
on_result(BufferSlice packet)1221   void on_result(BufferSlice packet) final {
1222     auto result_ptr = fetch_result<telegram_api::messages_editChatAdmin>(packet);
1223     if (result_ptr.is_error()) {
1224       return on_error(result_ptr.move_as_error());
1225     }
1226 
1227     bool result = result_ptr.move_as_ok();
1228     if (!result) {
1229       LOG(ERROR) << "Receive false as result of messages.editChatAdmin";
1230       return on_error(Status::Error(400, "Can't edit chat administrators"));
1231     }
1232 
1233     // result will come in the updates
1234     promise_.set_value(Unit());
1235   }
1236 
on_error(Status status)1237   void on_error(Status status) final {
1238     promise_.set_error(std::move(status));
1239     td_->updates_manager_->get_difference("EditChatAdminQuery");
1240   }
1241 };
1242 
1243 class ExportChatInviteQuery final : public Td::ResultHandler {
1244   Promise<td_api::object_ptr<td_api::chatInviteLink>> promise_;
1245   DialogId dialog_id_;
1246 
1247  public:
ExportChatInviteQuery(Promise<td_api::object_ptr<td_api::chatInviteLink>> && promise)1248   explicit ExportChatInviteQuery(Promise<td_api::object_ptr<td_api::chatInviteLink>> &&promise)
1249       : promise_(std::move(promise)) {
1250   }
1251 
send(DialogId dialog_id,const string & title,int32 expire_date,int32 usage_limit,bool creates_join_request,bool is_permanent)1252   void send(DialogId dialog_id, const string &title, int32 expire_date, int32 usage_limit, bool creates_join_request,
1253             bool is_permanent) {
1254     dialog_id_ = dialog_id;
1255     auto input_peer = td_->messages_manager_->get_input_peer(dialog_id, AccessRights::Write);
1256     if (input_peer == nullptr) {
1257       return on_error(Status::Error(400, "Can't access the chat"));
1258     }
1259 
1260     int32 flags = 0;
1261     if (expire_date > 0) {
1262       flags |= telegram_api::messages_exportChatInvite::EXPIRE_DATE_MASK;
1263     }
1264     if (usage_limit > 0) {
1265       flags |= telegram_api::messages_exportChatInvite::USAGE_LIMIT_MASK;
1266     }
1267     if (creates_join_request) {
1268       flags |= telegram_api::messages_exportChatInvite::REQUEST_NEEDED_MASK;
1269     }
1270     if (is_permanent) {
1271       flags |= telegram_api::messages_exportChatInvite::LEGACY_REVOKE_PERMANENT_MASK;
1272     }
1273     if (!title.empty()) {
1274       flags |= telegram_api::messages_exportChatInvite::TITLE_MASK;
1275     }
1276 
1277     send_query(G()->net_query_creator().create(telegram_api::messages_exportChatInvite(
1278         flags, false /*ignored*/, false /*ignored*/, std::move(input_peer), expire_date, usage_limit, title)));
1279   }
1280 
on_result(BufferSlice packet)1281   void on_result(BufferSlice packet) final {
1282     auto result_ptr = fetch_result<telegram_api::messages_exportChatInvite>(packet);
1283     if (result_ptr.is_error()) {
1284       return on_error(result_ptr.move_as_error());
1285     }
1286 
1287     auto ptr = result_ptr.move_as_ok();
1288     LOG(INFO) << "Receive result for ExportChatInviteQuery: " << to_string(ptr);
1289 
1290     DialogInviteLink invite_link(std::move(ptr));
1291     if (!invite_link.is_valid()) {
1292       return on_error(Status::Error(500, "Receive invalid invite link"));
1293     }
1294     if (invite_link.get_creator_user_id() != td_->contacts_manager_->get_my_id()) {
1295       return on_error(Status::Error(500, "Receive invalid invite link creator"));
1296     }
1297     if (invite_link.is_permanent()) {
1298       td_->contacts_manager_->on_get_permanent_dialog_invite_link(dialog_id_, invite_link);
1299     }
1300     promise_.set_value(invite_link.get_chat_invite_link_object(td_->contacts_manager_.get()));
1301   }
1302 
on_error(Status status)1303   void on_error(Status status) final {
1304     td_->messages_manager_->on_get_dialog_error(dialog_id_, status, "ExportChatInviteQuery");
1305     promise_.set_error(std::move(status));
1306   }
1307 };
1308 
1309 class EditChatInviteLinkQuery final : public Td::ResultHandler {
1310   Promise<td_api::object_ptr<td_api::chatInviteLink>> promise_;
1311   DialogId dialog_id_;
1312 
1313  public:
EditChatInviteLinkQuery(Promise<td_api::object_ptr<td_api::chatInviteLink>> && promise)1314   explicit EditChatInviteLinkQuery(Promise<td_api::object_ptr<td_api::chatInviteLink>> &&promise)
1315       : promise_(std::move(promise)) {
1316   }
1317 
send(DialogId dialog_id,const string & invite_link,const string & title,int32 expire_date,int32 usage_limit,bool creates_join_request)1318   void send(DialogId dialog_id, const string &invite_link, const string &title, int32 expire_date, int32 usage_limit,
1319             bool creates_join_request) {
1320     dialog_id_ = dialog_id;
1321     auto input_peer = td_->messages_manager_->get_input_peer(dialog_id, AccessRights::Write);
1322     if (input_peer == nullptr) {
1323       return on_error(Status::Error(400, "Can't access the chat"));
1324     }
1325 
1326     int32 flags = telegram_api::messages_editExportedChatInvite::EXPIRE_DATE_MASK |
1327                   telegram_api::messages_editExportedChatInvite::USAGE_LIMIT_MASK |
1328                   telegram_api::messages_editExportedChatInvite::REQUEST_NEEDED_MASK |
1329                   telegram_api::messages_editExportedChatInvite::TITLE_MASK;
1330     send_query(G()->net_query_creator().create(
1331         telegram_api::messages_editExportedChatInvite(flags, false /*ignored*/, std::move(input_peer), invite_link,
1332                                                       expire_date, usage_limit, creates_join_request, title)));
1333   }
1334 
on_result(BufferSlice packet)1335   void on_result(BufferSlice packet) final {
1336     auto result_ptr = fetch_result<telegram_api::messages_editExportedChatInvite>(packet);
1337     if (result_ptr.is_error()) {
1338       return on_error(result_ptr.move_as_error());
1339     }
1340 
1341     auto result = result_ptr.move_as_ok();
1342     LOG(INFO) << "Receive result for EditChatInviteLinkQuery: " << to_string(result);
1343 
1344     if (result->get_id() != telegram_api::messages_exportedChatInvite::ID) {
1345       return on_error(Status::Error(500, "Receive unexpected response from server"));
1346     }
1347 
1348     auto invite = move_tl_object_as<telegram_api::messages_exportedChatInvite>(result);
1349 
1350     td_->contacts_manager_->on_get_users(std::move(invite->users_), "EditChatInviteLinkQuery");
1351 
1352     DialogInviteLink invite_link(std::move(invite->invite_));
1353     if (!invite_link.is_valid()) {
1354       return on_error(Status::Error(500, "Receive invalid invite link"));
1355     }
1356     promise_.set_value(invite_link.get_chat_invite_link_object(td_->contacts_manager_.get()));
1357   }
1358 
on_error(Status status)1359   void on_error(Status status) final {
1360     td_->messages_manager_->on_get_dialog_error(dialog_id_, status, "EditChatInviteLinkQuery");
1361     promise_.set_error(std::move(status));
1362   }
1363 };
1364 
1365 class GetExportedChatInviteQuery final : public Td::ResultHandler {
1366   Promise<td_api::object_ptr<td_api::chatInviteLink>> promise_;
1367   DialogId dialog_id_;
1368 
1369  public:
GetExportedChatInviteQuery(Promise<td_api::object_ptr<td_api::chatInviteLink>> && promise)1370   explicit GetExportedChatInviteQuery(Promise<td_api::object_ptr<td_api::chatInviteLink>> &&promise)
1371       : promise_(std::move(promise)) {
1372   }
1373 
send(DialogId dialog_id,const string & invite_link)1374   void send(DialogId dialog_id, const string &invite_link) {
1375     dialog_id_ = dialog_id;
1376     auto input_peer = td_->messages_manager_->get_input_peer(dialog_id, AccessRights::Write);
1377     if (input_peer == nullptr) {
1378       return on_error(Status::Error(400, "Can't access the chat"));
1379     }
1380 
1381     send_query(G()->net_query_creator().create(
1382         telegram_api::messages_getExportedChatInvite(std::move(input_peer), invite_link)));
1383   }
1384 
on_result(BufferSlice packet)1385   void on_result(BufferSlice packet) final {
1386     auto result_ptr = fetch_result<telegram_api::messages_getExportedChatInvite>(packet);
1387     if (result_ptr.is_error()) {
1388       return on_error(result_ptr.move_as_error());
1389     }
1390 
1391     if (result_ptr.ok()->get_id() != telegram_api::messages_exportedChatInvite::ID) {
1392       LOG(ERROR) << "Receive wrong result for GetExportedChatInviteQuery: " << to_string(result_ptr.ok());
1393       return on_error(Status::Error(500, "Receive unexpected response"));
1394     }
1395 
1396     auto result = move_tl_object_as<telegram_api::messages_exportedChatInvite>(result_ptr.ok_ref());
1397     LOG(INFO) << "Receive result for GetExportedChatInviteQuery: " << to_string(result);
1398 
1399     td_->contacts_manager_->on_get_users(std::move(result->users_), "GetExportedChatInviteQuery");
1400 
1401     DialogInviteLink invite_link(std::move(result->invite_));
1402     if (!invite_link.is_valid()) {
1403       LOG(ERROR) << "Receive invalid invite link in " << dialog_id_;
1404       return on_error(Status::Error(500, "Receive invalid invite link"));
1405     }
1406     promise_.set_value(invite_link.get_chat_invite_link_object(td_->contacts_manager_.get()));
1407   }
1408 
on_error(Status status)1409   void on_error(Status status) final {
1410     td_->messages_manager_->on_get_dialog_error(dialog_id_, status, "GetExportedChatInviteQuery");
1411     promise_.set_error(std::move(status));
1412   }
1413 };
1414 
1415 class GetExportedChatInvitesQuery final : public Td::ResultHandler {
1416   Promise<td_api::object_ptr<td_api::chatInviteLinks>> promise_;
1417   DialogId dialog_id_;
1418 
1419  public:
GetExportedChatInvitesQuery(Promise<td_api::object_ptr<td_api::chatInviteLinks>> && promise)1420   explicit GetExportedChatInvitesQuery(Promise<td_api::object_ptr<td_api::chatInviteLinks>> &&promise)
1421       : promise_(std::move(promise)) {
1422   }
1423 
send(DialogId dialog_id,UserId creator_user_id,bool is_revoked,int32 offset_date,const string & offset_invite_link,int32 limit)1424   void send(DialogId dialog_id, UserId creator_user_id, bool is_revoked, int32 offset_date,
1425             const string &offset_invite_link, int32 limit) {
1426     dialog_id_ = dialog_id;
1427     auto input_peer = td_->messages_manager_->get_input_peer(dialog_id, AccessRights::Write);
1428     if (input_peer == nullptr) {
1429       return on_error(Status::Error(400, "Can't access the chat"));
1430     }
1431 
1432     auto input_user = td_->contacts_manager_->get_input_user(creator_user_id);
1433     CHECK(input_user != nullptr);
1434 
1435     int32 flags = 0;
1436     if (!offset_invite_link.empty() || offset_date != 0) {
1437       flags |= telegram_api::messages_getExportedChatInvites::OFFSET_DATE_MASK;
1438       flags |= telegram_api::messages_getExportedChatInvites::OFFSET_LINK_MASK;
1439     }
1440     if (is_revoked) {
1441       flags |= telegram_api::messages_getExportedChatInvites::REVOKED_MASK;
1442     }
1443     send_query(G()->net_query_creator().create(
1444         telegram_api::messages_getExportedChatInvites(flags, false /*ignored*/, std::move(input_peer),
1445                                                       std::move(input_user), offset_date, offset_invite_link, limit)));
1446   }
1447 
on_result(BufferSlice packet)1448   void on_result(BufferSlice packet) final {
1449     auto result_ptr = fetch_result<telegram_api::messages_getExportedChatInvites>(packet);
1450     if (result_ptr.is_error()) {
1451       return on_error(result_ptr.move_as_error());
1452     }
1453 
1454     auto result = result_ptr.move_as_ok();
1455     LOG(INFO) << "Receive result for GetExportedChatInvitesQuery: " << to_string(result);
1456 
1457     td_->contacts_manager_->on_get_users(std::move(result->users_), "GetExportedChatInvitesQuery");
1458 
1459     int32 total_count = result->count_;
1460     if (total_count < static_cast<int32>(result->invites_.size())) {
1461       LOG(ERROR) << "Receive wrong total count of invite links " << total_count << " in " << dialog_id_;
1462       total_count = static_cast<int32>(result->invites_.size());
1463     }
1464     vector<td_api::object_ptr<td_api::chatInviteLink>> invite_links;
1465     for (auto &invite : result->invites_) {
1466       DialogInviteLink invite_link(std::move(invite));
1467       if (!invite_link.is_valid()) {
1468         LOG(ERROR) << "Receive invalid invite link in " << dialog_id_;
1469         total_count--;
1470         continue;
1471       }
1472       invite_links.push_back(invite_link.get_chat_invite_link_object(td_->contacts_manager_.get()));
1473     }
1474     promise_.set_value(td_api::make_object<td_api::chatInviteLinks>(total_count, std::move(invite_links)));
1475   }
1476 
on_error(Status status)1477   void on_error(Status status) final {
1478     td_->messages_manager_->on_get_dialog_error(dialog_id_, status, "GetExportedChatInvitesQuery");
1479     promise_.set_error(std::move(status));
1480   }
1481 };
1482 
1483 class GetChatAdminWithInvitesQuery final : public Td::ResultHandler {
1484   Promise<td_api::object_ptr<td_api::chatInviteLinkCounts>> promise_;
1485   DialogId dialog_id_;
1486 
1487  public:
GetChatAdminWithInvitesQuery(Promise<td_api::object_ptr<td_api::chatInviteLinkCounts>> && promise)1488   explicit GetChatAdminWithInvitesQuery(Promise<td_api::object_ptr<td_api::chatInviteLinkCounts>> &&promise)
1489       : promise_(std::move(promise)) {
1490   }
1491 
send(DialogId dialog_id)1492   void send(DialogId dialog_id) {
1493     dialog_id_ = dialog_id;
1494     auto input_peer = td_->messages_manager_->get_input_peer(dialog_id, AccessRights::Write);
1495     if (input_peer == nullptr) {
1496       return on_error(Status::Error(400, "Can't access the chat"));
1497     }
1498 
1499     send_query(G()->net_query_creator().create(telegram_api::messages_getAdminsWithInvites(std::move(input_peer))));
1500   }
1501 
on_result(BufferSlice packet)1502   void on_result(BufferSlice packet) final {
1503     auto result_ptr = fetch_result<telegram_api::messages_getAdminsWithInvites>(packet);
1504     if (result_ptr.is_error()) {
1505       return on_error(result_ptr.move_as_error());
1506     }
1507 
1508     auto result = result_ptr.move_as_ok();
1509     LOG(INFO) << "Receive result for GetChatAdminWithInvitesQuery: " << to_string(result);
1510 
1511     td_->contacts_manager_->on_get_users(std::move(result->users_), "GetChatAdminWithInvitesQuery");
1512 
1513     vector<td_api::object_ptr<td_api::chatInviteLinkCount>> invite_link_counts;
1514     for (auto &admin : result->admins_) {
1515       UserId user_id(admin->admin_id_);
1516       if (!user_id.is_valid()) {
1517         LOG(ERROR) << "Receive invalid invite link creator " << user_id << " in " << dialog_id_;
1518         continue;
1519       }
1520       invite_link_counts.push_back(td_api::make_object<td_api::chatInviteLinkCount>(
1521           td_->contacts_manager_->get_user_id_object(user_id, "chatInviteLinkCount"), admin->invites_count_,
1522           admin->revoked_invites_count_));
1523     }
1524     promise_.set_value(td_api::make_object<td_api::chatInviteLinkCounts>(std::move(invite_link_counts)));
1525   }
1526 
on_error(Status status)1527   void on_error(Status status) final {
1528     td_->messages_manager_->on_get_dialog_error(dialog_id_, status, "GetChatAdminWithInvitesQuery");
1529     promise_.set_error(std::move(status));
1530   }
1531 };
1532 
1533 class GetChatInviteImportersQuery final : public Td::ResultHandler {
1534   Promise<td_api::object_ptr<td_api::chatInviteLinkMembers>> promise_;
1535   DialogId dialog_id_;
1536 
1537  public:
GetChatInviteImportersQuery(Promise<td_api::object_ptr<td_api::chatInviteLinkMembers>> && promise)1538   explicit GetChatInviteImportersQuery(Promise<td_api::object_ptr<td_api::chatInviteLinkMembers>> &&promise)
1539       : promise_(std::move(promise)) {
1540   }
1541 
send(DialogId dialog_id,const string & invite_link,int32 offset_date,UserId offset_user_id,int32 limit)1542   void send(DialogId dialog_id, const string &invite_link, int32 offset_date, UserId offset_user_id, int32 limit) {
1543     dialog_id_ = dialog_id;
1544     auto input_peer = td_->messages_manager_->get_input_peer(dialog_id, AccessRights::Write);
1545     if (input_peer == nullptr) {
1546       return on_error(Status::Error(400, "Can't access the chat"));
1547     }
1548 
1549     auto input_user = td_->contacts_manager_->get_input_user(offset_user_id);
1550     if (input_user == nullptr) {
1551       input_user = make_tl_object<telegram_api::inputUserEmpty>();
1552     }
1553 
1554     int32 flags = telegram_api::messages_getChatInviteImporters::LINK_MASK;
1555     send_query(G()->net_query_creator().create(
1556         telegram_api::messages_getChatInviteImporters(flags, false /*ignored*/, std::move(input_peer), invite_link,
1557                                                       string(), offset_date, std::move(input_user), limit)));
1558   }
1559 
on_result(BufferSlice packet)1560   void on_result(BufferSlice packet) final {
1561     auto result_ptr = fetch_result<telegram_api::messages_getChatInviteImporters>(packet);
1562     if (result_ptr.is_error()) {
1563       return on_error(result_ptr.move_as_error());
1564     }
1565 
1566     auto result = result_ptr.move_as_ok();
1567     LOG(INFO) << "Receive result for GetChatInviteImportersQuery: " << to_string(result);
1568 
1569     td_->contacts_manager_->on_get_users(std::move(result->users_), "GetChatInviteImportersQuery");
1570 
1571     int32 total_count = result->count_;
1572     if (total_count < static_cast<int32>(result->importers_.size())) {
1573       LOG(ERROR) << "Receive wrong total count of invite link users " << total_count << " in " << dialog_id_;
1574       total_count = static_cast<int32>(result->importers_.size());
1575     }
1576     vector<td_api::object_ptr<td_api::chatInviteLinkMember>> invite_link_members;
1577     for (auto &importer : result->importers_) {
1578       UserId user_id(importer->user_id_);
1579       UserId approver_user_id(importer->approved_by_);
1580       if (!user_id.is_valid() || (!approver_user_id.is_valid() && approver_user_id != UserId()) ||
1581           importer->requested_) {
1582         LOG(ERROR) << "Receive invalid invite link importer: " << to_string(importer);
1583         total_count--;
1584         continue;
1585       }
1586       invite_link_members.push_back(td_api::make_object<td_api::chatInviteLinkMember>(
1587           td_->contacts_manager_->get_user_id_object(user_id, "chatInviteLinkMember"), importer->date_,
1588           td_->contacts_manager_->get_user_id_object(approver_user_id, "chatInviteLinkMember")));
1589     }
1590     promise_.set_value(td_api::make_object<td_api::chatInviteLinkMembers>(total_count, std::move(invite_link_members)));
1591   }
1592 
on_error(Status status)1593   void on_error(Status status) final {
1594     td_->messages_manager_->on_get_dialog_error(dialog_id_, status, "GetChatInviteImportersQuery");
1595     promise_.set_error(std::move(status));
1596   }
1597 };
1598 
1599 class GetChatJoinRequestsQuery final : public Td::ResultHandler {
1600   Promise<td_api::object_ptr<td_api::chatJoinRequests>> promise_;
1601   DialogId dialog_id_;
1602   bool is_full_list_ = false;
1603 
1604  public:
GetChatJoinRequestsQuery(Promise<td_api::object_ptr<td_api::chatJoinRequests>> && promise)1605   explicit GetChatJoinRequestsQuery(Promise<td_api::object_ptr<td_api::chatJoinRequests>> &&promise)
1606       : promise_(std::move(promise)) {
1607   }
1608 
send(DialogId dialog_id,const string & invite_link,const string & query,int32 offset_date,UserId offset_user_id,int32 limit)1609   void send(DialogId dialog_id, const string &invite_link, const string &query, int32 offset_date,
1610             UserId offset_user_id, int32 limit) {
1611     dialog_id_ = dialog_id;
1612     is_full_list_ =
1613         invite_link.empty() && query.empty() && offset_date == 0 && !offset_user_id.is_valid() && limit >= 3;
1614 
1615     auto input_peer = td_->messages_manager_->get_input_peer(dialog_id, AccessRights::Write);
1616     if (input_peer == nullptr) {
1617       return on_error(Status::Error(400, "Can't access the chat"));
1618     }
1619 
1620     auto input_user = td_->contacts_manager_->get_input_user(offset_user_id);
1621     if (input_user == nullptr) {
1622       input_user = make_tl_object<telegram_api::inputUserEmpty>();
1623     }
1624 
1625     int32 flags = telegram_api::messages_getChatInviteImporters::REQUESTED_MASK;
1626     if (!invite_link.empty()) {
1627       flags |= telegram_api::messages_getChatInviteImporters::LINK_MASK;
1628     }
1629     if (!query.empty()) {
1630       flags |= telegram_api::messages_getChatInviteImporters::Q_MASK;
1631     }
1632     send_query(G()->net_query_creator().create(
1633         telegram_api::messages_getChatInviteImporters(flags, false /*ignored*/, std::move(input_peer), invite_link,
1634                                                       query, offset_date, std::move(input_user), limit)));
1635   }
1636 
on_result(BufferSlice packet)1637   void on_result(BufferSlice packet) final {
1638     auto result_ptr = fetch_result<telegram_api::messages_getChatInviteImporters>(packet);
1639     if (result_ptr.is_error()) {
1640       return on_error(result_ptr.move_as_error());
1641     }
1642 
1643     auto result = result_ptr.move_as_ok();
1644     LOG(INFO) << "Receive result for GetChatJoinRequestsQuery: " << to_string(result);
1645 
1646     td_->contacts_manager_->on_get_users(std::move(result->users_), "GetChatJoinRequestsQuery");
1647 
1648     int32 total_count = result->count_;
1649     if (total_count < static_cast<int32>(result->importers_.size())) {
1650       LOG(ERROR) << "Receive wrong total count of join requests " << total_count << " in " << dialog_id_;
1651       total_count = static_cast<int32>(result->importers_.size());
1652     }
1653     vector<td_api::object_ptr<td_api::chatJoinRequest>> join_requests;
1654     vector<int64> recent_requesters;
1655     for (auto &request : result->importers_) {
1656       UserId user_id(request->user_id_);
1657       UserId approver_user_id(request->approved_by_);
1658       if (!user_id.is_valid() || approver_user_id.is_valid() || !request->requested_) {
1659         LOG(ERROR) << "Receive invalid join request: " << to_string(request);
1660         total_count--;
1661         continue;
1662       }
1663       if (recent_requesters.size() < 3) {
1664         recent_requesters.push_back(user_id.get());
1665       }
1666       join_requests.push_back(td_api::make_object<td_api::chatJoinRequest>(
1667           td_->contacts_manager_->get_user_id_object(user_id, "chatJoinRequest"), request->date_, request->about_));
1668     }
1669     if (is_full_list_) {
1670       td_->messages_manager_->on_update_dialog_pending_join_requests(dialog_id_, total_count,
1671                                                                      std::move(recent_requesters));
1672     }
1673     promise_.set_value(td_api::make_object<td_api::chatJoinRequests>(total_count, std::move(join_requests)));
1674   }
1675 
on_error(Status status)1676   void on_error(Status status) final {
1677     td_->messages_manager_->on_get_dialog_error(dialog_id_, status, "GetChatJoinRequestsQuery");
1678     promise_.set_error(std::move(status));
1679   }
1680 };
1681 
1682 class HideChatJoinRequestQuery final : public Td::ResultHandler {
1683   Promise<Unit> promise_;
1684   DialogId dialog_id_;
1685 
1686  public:
HideChatJoinRequestQuery(Promise<Unit> && promise)1687   explicit HideChatJoinRequestQuery(Promise<Unit> &&promise) : promise_(std::move(promise)) {
1688   }
1689 
send(DialogId dialog_id,UserId user_id,bool approve)1690   void send(DialogId dialog_id, UserId user_id, bool approve) {
1691     dialog_id_ = dialog_id;
1692     auto input_peer = td_->messages_manager_->get_input_peer(dialog_id, AccessRights::Write);
1693     if (input_peer == nullptr) {
1694       return on_error(Status::Error(400, "Can't access the chat"));
1695     }
1696 
1697     auto input_user = td_->contacts_manager_->get_input_user(user_id);
1698     if (input_user == nullptr) {
1699       return on_error(Status::Error(400, "Can't find user"));
1700     }
1701 
1702     int32 flags = 0;
1703     if (approve) {
1704       flags |= telegram_api::messages_hideChatJoinRequest::APPROVED_MASK;
1705     }
1706     send_query(G()->net_query_creator().create(telegram_api::messages_hideChatJoinRequest(
1707         flags, false /*ignored*/, std::move(input_peer), std::move(input_user))));
1708   }
1709 
on_result(BufferSlice packet)1710   void on_result(BufferSlice packet) final {
1711     auto result_ptr = fetch_result<telegram_api::messages_hideChatJoinRequest>(packet);
1712     if (result_ptr.is_error()) {
1713       return on_error(result_ptr.move_as_error());
1714     }
1715 
1716     auto result = result_ptr.move_as_ok();
1717     LOG(INFO) << "Receive result for HideChatJoinRequestQuery: " << to_string(result);
1718     td_->updates_manager_->on_get_updates(std::move(result), std::move(promise_));
1719   }
1720 
on_error(Status status)1721   void on_error(Status status) final {
1722     td_->messages_manager_->on_get_dialog_error(dialog_id_, status, "HideChatJoinRequestQuery");
1723     promise_.set_error(std::move(status));
1724   }
1725 };
1726 
1727 class HideAllChatJoinRequestsQuery final : public Td::ResultHandler {
1728   Promise<Unit> promise_;
1729   DialogId dialog_id_;
1730 
1731  public:
HideAllChatJoinRequestsQuery(Promise<Unit> && promise)1732   explicit HideAllChatJoinRequestsQuery(Promise<Unit> &&promise) : promise_(std::move(promise)) {
1733   }
1734 
send(DialogId dialog_id,const string & invite_link,bool approve)1735   void send(DialogId dialog_id, const string &invite_link, bool approve) {
1736     dialog_id_ = dialog_id;
1737     auto input_peer = td_->messages_manager_->get_input_peer(dialog_id, AccessRights::Write);
1738     if (input_peer == nullptr) {
1739       return on_error(Status::Error(400, "Can't access the chat"));
1740     }
1741 
1742     int32 flags = 0;
1743     if (approve) {
1744       flags |= telegram_api::messages_hideAllChatJoinRequests::APPROVED_MASK;
1745     }
1746     if (!invite_link.empty()) {
1747       flags |= telegram_api::messages_hideAllChatJoinRequests::LINK_MASK;
1748     }
1749     send_query(G()->net_query_creator().create(
1750         telegram_api::messages_hideAllChatJoinRequests(flags, false /*ignored*/, std::move(input_peer), invite_link)));
1751   }
1752 
on_result(BufferSlice packet)1753   void on_result(BufferSlice packet) final {
1754     auto result_ptr = fetch_result<telegram_api::messages_hideAllChatJoinRequests>(packet);
1755     if (result_ptr.is_error()) {
1756       return on_error(result_ptr.move_as_error());
1757     }
1758 
1759     auto result = result_ptr.move_as_ok();
1760     LOG(INFO) << "Receive result for HideAllChatJoinRequestsQuery: " << to_string(result);
1761     td_->updates_manager_->on_get_updates(std::move(result), std::move(promise_));
1762   }
1763 
on_error(Status status)1764   void on_error(Status status) final {
1765     td_->messages_manager_->on_get_dialog_error(dialog_id_, status, "HideAllChatJoinRequestsQuery");
1766     promise_.set_error(std::move(status));
1767   }
1768 };
1769 
1770 class RevokeChatInviteLinkQuery final : public Td::ResultHandler {
1771   Promise<td_api::object_ptr<td_api::chatInviteLinks>> promise_;
1772   DialogId dialog_id_;
1773 
1774  public:
RevokeChatInviteLinkQuery(Promise<td_api::object_ptr<td_api::chatInviteLinks>> && promise)1775   explicit RevokeChatInviteLinkQuery(Promise<td_api::object_ptr<td_api::chatInviteLinks>> &&promise)
1776       : promise_(std::move(promise)) {
1777   }
1778 
send(DialogId dialog_id,const string & invite_link)1779   void send(DialogId dialog_id, const string &invite_link) {
1780     dialog_id_ = dialog_id;
1781     auto input_peer = td_->messages_manager_->get_input_peer(dialog_id, AccessRights::Write);
1782     if (input_peer == nullptr) {
1783       return on_error(Status::Error(400, "Can't access the chat"));
1784     }
1785 
1786     int32 flags = telegram_api::messages_editExportedChatInvite::REVOKED_MASK;
1787     send_query(G()->net_query_creator().create(telegram_api::messages_editExportedChatInvite(
1788         flags, false /*ignored*/, std::move(input_peer), invite_link, 0, 0, false, string())));
1789   }
1790 
on_result(BufferSlice packet)1791   void on_result(BufferSlice packet) final {
1792     auto result_ptr = fetch_result<telegram_api::messages_editExportedChatInvite>(packet);
1793     if (result_ptr.is_error()) {
1794       return on_error(result_ptr.move_as_error());
1795     }
1796 
1797     auto result = result_ptr.move_as_ok();
1798     LOG(INFO) << "Receive result for RevokeChatInviteLinkQuery: " << to_string(result);
1799 
1800     vector<td_api::object_ptr<td_api::chatInviteLink>> links;
1801     switch (result->get_id()) {
1802       case telegram_api::messages_exportedChatInvite::ID: {
1803         auto invite = move_tl_object_as<telegram_api::messages_exportedChatInvite>(result);
1804 
1805         td_->contacts_manager_->on_get_users(std::move(invite->users_), "RevokeChatInviteLinkQuery");
1806 
1807         DialogInviteLink invite_link(std::move(invite->invite_));
1808         if (!invite_link.is_valid()) {
1809           return on_error(Status::Error(500, "Receive invalid invite link"));
1810         }
1811         links.push_back(invite_link.get_chat_invite_link_object(td_->contacts_manager_.get()));
1812         break;
1813       }
1814       case telegram_api::messages_exportedChatInviteReplaced::ID: {
1815         auto invite = move_tl_object_as<telegram_api::messages_exportedChatInviteReplaced>(result);
1816 
1817         td_->contacts_manager_->on_get_users(std::move(invite->users_), "RevokeChatInviteLinkQuery");
1818 
1819         DialogInviteLink invite_link(std::move(invite->invite_));
1820         DialogInviteLink new_invite_link(std::move(invite->new_invite_));
1821         if (!invite_link.is_valid() || !new_invite_link.is_valid()) {
1822           return on_error(Status::Error(500, "Receive invalid invite link"));
1823         }
1824         if (new_invite_link.get_creator_user_id() == td_->contacts_manager_->get_my_id() &&
1825             new_invite_link.is_permanent()) {
1826           td_->contacts_manager_->on_get_permanent_dialog_invite_link(dialog_id_, new_invite_link);
1827         }
1828         links.push_back(invite_link.get_chat_invite_link_object(td_->contacts_manager_.get()));
1829         links.push_back(new_invite_link.get_chat_invite_link_object(td_->contacts_manager_.get()));
1830         break;
1831       }
1832       default:
1833         UNREACHABLE();
1834     }
1835     auto total_count = static_cast<int32>(links.size());
1836     promise_.set_value(td_api::make_object<td_api::chatInviteLinks>(total_count, std::move(links)));
1837   }
1838 
on_error(Status status)1839   void on_error(Status status) final {
1840     td_->messages_manager_->on_get_dialog_error(dialog_id_, status, "RevokeChatInviteLinkQuery");
1841     promise_.set_error(std::move(status));
1842   }
1843 };
1844 
1845 class DeleteExportedChatInviteQuery final : public Td::ResultHandler {
1846   Promise<Unit> promise_;
1847   DialogId dialog_id_;
1848 
1849  public:
DeleteExportedChatInviteQuery(Promise<Unit> && promise)1850   explicit DeleteExportedChatInviteQuery(Promise<Unit> &&promise) : promise_(std::move(promise)) {
1851   }
1852 
send(DialogId dialog_id,const string & invite_link)1853   void send(DialogId dialog_id, const string &invite_link) {
1854     dialog_id_ = dialog_id;
1855     auto input_peer = td_->messages_manager_->get_input_peer(dialog_id, AccessRights::Write);
1856     if (input_peer == nullptr) {
1857       return on_error(Status::Error(400, "Can't access the chat"));
1858     }
1859 
1860     send_query(G()->net_query_creator().create(
1861         telegram_api::messages_deleteExportedChatInvite(std::move(input_peer), invite_link)));
1862   }
1863 
on_result(BufferSlice packet)1864   void on_result(BufferSlice packet) final {
1865     auto result_ptr = fetch_result<telegram_api::messages_deleteExportedChatInvite>(packet);
1866     if (result_ptr.is_error()) {
1867       return on_error(result_ptr.move_as_error());
1868     }
1869 
1870     promise_.set_value(Unit());
1871   }
1872 
on_error(Status status)1873   void on_error(Status status) final {
1874     td_->messages_manager_->on_get_dialog_error(dialog_id_, status, "DeleteExportedChatInviteQuery");
1875     promise_.set_error(std::move(status));
1876   }
1877 };
1878 
1879 class DeleteRevokedExportedChatInvitesQuery final : public Td::ResultHandler {
1880   Promise<Unit> promise_;
1881   DialogId dialog_id_;
1882 
1883  public:
DeleteRevokedExportedChatInvitesQuery(Promise<Unit> && promise)1884   explicit DeleteRevokedExportedChatInvitesQuery(Promise<Unit> &&promise) : promise_(std::move(promise)) {
1885   }
1886 
send(DialogId dialog_id,UserId creator_user_id)1887   void send(DialogId dialog_id, UserId creator_user_id) {
1888     dialog_id_ = dialog_id;
1889     auto input_peer = td_->messages_manager_->get_input_peer(dialog_id, AccessRights::Write);
1890     if (input_peer == nullptr) {
1891       return on_error(Status::Error(400, "Can't access the chat"));
1892     }
1893 
1894     auto input_user = td_->contacts_manager_->get_input_user(creator_user_id);
1895     CHECK(input_user != nullptr);
1896 
1897     send_query(G()->net_query_creator().create(
1898         telegram_api::messages_deleteRevokedExportedChatInvites(std::move(input_peer), std::move(input_user))));
1899   }
1900 
on_result(BufferSlice packet)1901   void on_result(BufferSlice packet) final {
1902     auto result_ptr = fetch_result<telegram_api::messages_deleteRevokedExportedChatInvites>(packet);
1903     if (result_ptr.is_error()) {
1904       return on_error(result_ptr.move_as_error());
1905     }
1906 
1907     promise_.set_value(Unit());
1908   }
1909 
on_error(Status status)1910   void on_error(Status status) final {
1911     td_->messages_manager_->on_get_dialog_error(dialog_id_, status, "DeleteRevokedExportedChatInvitesQuery");
1912     promise_.set_error(std::move(status));
1913   }
1914 };
1915 
1916 class CheckChatInviteQuery final : public Td::ResultHandler {
1917   Promise<Unit> promise_;
1918   string invite_link_;
1919 
1920  public:
CheckChatInviteQuery(Promise<Unit> && promise)1921   explicit CheckChatInviteQuery(Promise<Unit> &&promise) : promise_(std::move(promise)) {
1922   }
1923 
send(const string & invite_link)1924   void send(const string &invite_link) {
1925     invite_link_ = invite_link;
1926     send_query(G()->net_query_creator().create(
1927         telegram_api::messages_checkChatInvite(LinkManager::get_dialog_invite_link_hash(invite_link_))));
1928   }
1929 
on_result(BufferSlice packet)1930   void on_result(BufferSlice packet) final {
1931     auto result_ptr = fetch_result<telegram_api::messages_checkChatInvite>(packet);
1932     if (result_ptr.is_error()) {
1933       return on_error(result_ptr.move_as_error());
1934     }
1935 
1936     auto ptr = result_ptr.move_as_ok();
1937     LOG(INFO) << "Receive result for CheckChatInviteQuery: " << to_string(ptr);
1938 
1939     td_->contacts_manager_->on_get_dialog_invite_link_info(invite_link_, std::move(ptr), std::move(promise_));
1940   }
1941 
on_error(Status status)1942   void on_error(Status status) final {
1943     promise_.set_error(std::move(status));
1944   }
1945 };
1946 
1947 class ImportChatInviteQuery final : public Td::ResultHandler {
1948   Promise<DialogId> promise_;
1949 
1950   string invite_link_;
1951 
1952  public:
ImportChatInviteQuery(Promise<DialogId> && promise)1953   explicit ImportChatInviteQuery(Promise<DialogId> &&promise) : promise_(std::move(promise)) {
1954   }
1955 
send(const string & invite_link)1956   void send(const string &invite_link) {
1957     invite_link_ = invite_link;
1958     send_query(G()->net_query_creator().create(
1959         telegram_api::messages_importChatInvite(LinkManager::get_dialog_invite_link_hash(invite_link_))));
1960   }
1961 
on_result(BufferSlice packet)1962   void on_result(BufferSlice packet) final {
1963     auto result_ptr = fetch_result<telegram_api::messages_importChatInvite>(packet);
1964     if (result_ptr.is_error()) {
1965       return on_error(result_ptr.move_as_error());
1966     }
1967 
1968     auto ptr = result_ptr.move_as_ok();
1969     LOG(INFO) << "Receive result for ImportChatInviteQuery: " << to_string(ptr);
1970 
1971     auto dialog_ids = UpdatesManager::get_chat_dialog_ids(ptr.get());
1972     if (dialog_ids.size() != 1u) {
1973       LOG(ERROR) << "Receive wrong result for ImportChatInviteQuery: " << to_string(ptr);
1974       return on_error(Status::Error(500, "Internal Server Error: failed to join chat by invite link"));
1975     }
1976     auto dialog_id = dialog_ids[0];
1977 
1978     td_->contacts_manager_->invalidate_invite_link_info(invite_link_);
1979     td_->updates_manager_->on_get_updates(
1980         std::move(ptr), PromiseCreator::lambda([promise = std::move(promise_), dialog_id](Unit) mutable {
1981           promise.set_value(std::move(dialog_id));
1982         }));
1983   }
1984 
on_error(Status status)1985   void on_error(Status status) final {
1986     td_->contacts_manager_->invalidate_invite_link_info(invite_link_);
1987     promise_.set_error(std::move(status));
1988   }
1989 };
1990 
1991 class DeleteChatUserQuery final : public Td::ResultHandler {
1992   Promise<Unit> promise_;
1993 
1994  public:
DeleteChatUserQuery(Promise<Unit> && promise)1995   explicit DeleteChatUserQuery(Promise<Unit> &&promise) : promise_(std::move(promise)) {
1996   }
1997 
send(ChatId chat_id,tl_object_ptr<telegram_api::InputUser> && input_user,bool revoke_messages)1998   void send(ChatId chat_id, tl_object_ptr<telegram_api::InputUser> &&input_user, bool revoke_messages) {
1999     int32 flags = 0;
2000     if (revoke_messages) {
2001       flags |= telegram_api::messages_deleteChatUser::REVOKE_HISTORY_MASK;
2002     }
2003     send_query(G()->net_query_creator().create(
2004         telegram_api::messages_deleteChatUser(flags, false /*ignored*/, chat_id.get(), std::move(input_user))));
2005   }
2006 
on_result(BufferSlice packet)2007   void on_result(BufferSlice packet) final {
2008     auto result_ptr = fetch_result<telegram_api::messages_deleteChatUser>(packet);
2009     if (result_ptr.is_error()) {
2010       return on_error(result_ptr.move_as_error());
2011     }
2012 
2013     auto ptr = result_ptr.move_as_ok();
2014     LOG(INFO) << "Receive result for DeleteChatUserQuery: " << to_string(ptr);
2015     td_->updates_manager_->on_get_updates(std::move(ptr), std::move(promise_));
2016   }
2017 
on_error(Status status)2018   void on_error(Status status) final {
2019     promise_.set_error(std::move(status));
2020     td_->updates_manager_->get_difference("DeleteChatUserQuery");
2021   }
2022 };
2023 
2024 class JoinChannelQuery final : public Td::ResultHandler {
2025   Promise<Unit> promise_;
2026   ChannelId channel_id_;
2027 
2028  public:
JoinChannelQuery(Promise<Unit> && promise)2029   explicit JoinChannelQuery(Promise<Unit> &&promise) : promise_(std::move(promise)) {
2030   }
2031 
send(ChannelId channel_id)2032   void send(ChannelId channel_id) {
2033     channel_id_ = channel_id;
2034     auto input_channel = td_->contacts_manager_->get_input_channel(channel_id);
2035     CHECK(input_channel != nullptr);
2036     send_query(G()->net_query_creator().create(telegram_api::channels_joinChannel(std::move(input_channel))));
2037   }
2038 
on_result(BufferSlice packet)2039   void on_result(BufferSlice packet) final {
2040     auto result_ptr = fetch_result<telegram_api::channels_joinChannel>(packet);
2041     if (result_ptr.is_error()) {
2042       return on_error(result_ptr.move_as_error());
2043     }
2044 
2045     auto ptr = result_ptr.move_as_ok();
2046     LOG(INFO) << "Receive result for JoinChannelQuery: " << to_string(ptr);
2047     td_->updates_manager_->on_get_updates(std::move(ptr), std::move(promise_));
2048   }
2049 
on_error(Status status)2050   void on_error(Status status) final {
2051     td_->contacts_manager_->on_get_channel_error(channel_id_, status, "JoinChannelQuery");
2052     promise_.set_error(std::move(status));
2053     td_->updates_manager_->get_difference("JoinChannelQuery");
2054   }
2055 };
2056 
2057 class InviteToChannelQuery final : public Td::ResultHandler {
2058   Promise<Unit> promise_;
2059   ChannelId channel_id_;
2060 
2061  public:
InviteToChannelQuery(Promise<Unit> && promise)2062   explicit InviteToChannelQuery(Promise<Unit> &&promise) : promise_(std::move(promise)) {
2063   }
2064 
send(ChannelId channel_id,vector<tl_object_ptr<telegram_api::InputUser>> && input_users)2065   void send(ChannelId channel_id, vector<tl_object_ptr<telegram_api::InputUser>> &&input_users) {
2066     channel_id_ = channel_id;
2067     auto input_channel = td_->contacts_manager_->get_input_channel(channel_id);
2068     CHECK(input_channel != nullptr);
2069     send_query(G()->net_query_creator().create(
2070         telegram_api::channels_inviteToChannel(std::move(input_channel), std::move(input_users))));
2071   }
2072 
on_result(BufferSlice packet)2073   void on_result(BufferSlice packet) final {
2074     auto result_ptr = fetch_result<telegram_api::channels_inviteToChannel>(packet);
2075     if (result_ptr.is_error()) {
2076       return on_error(result_ptr.move_as_error());
2077     }
2078 
2079     auto ptr = result_ptr.move_as_ok();
2080     LOG(INFO) << "Receive result for InviteToChannelQuery: " << to_string(ptr);
2081     td_->contacts_manager_->invalidate_channel_full(channel_id_, false);
2082     td_->updates_manager_->on_get_updates(std::move(ptr), std::move(promise_));
2083   }
2084 
on_error(Status status)2085   void on_error(Status status) final {
2086     td_->contacts_manager_->on_get_channel_error(channel_id_, status, "InviteToChannelQuery");
2087     promise_.set_error(std::move(status));
2088     td_->updates_manager_->get_difference("InviteToChannelQuery");
2089   }
2090 };
2091 
2092 class EditChannelAdminQuery final : public Td::ResultHandler {
2093   Promise<Unit> promise_;
2094   ChannelId channel_id_;
2095 
2096  public:
EditChannelAdminQuery(Promise<Unit> && promise)2097   explicit EditChannelAdminQuery(Promise<Unit> &&promise) : promise_(std::move(promise)) {
2098   }
2099 
send(ChannelId channel_id,tl_object_ptr<telegram_api::InputUser> && input_user,const DialogParticipantStatus & status)2100   void send(ChannelId channel_id, tl_object_ptr<telegram_api::InputUser> &&input_user,
2101             const DialogParticipantStatus &status) {
2102     channel_id_ = channel_id;
2103     auto input_channel = td_->contacts_manager_->get_input_channel(channel_id);
2104     CHECK(input_channel != nullptr);
2105     send_query(G()->net_query_creator().create(telegram_api::channels_editAdmin(
2106         std::move(input_channel), std::move(input_user), status.get_chat_admin_rights(), status.get_rank())));
2107   }
2108 
on_result(BufferSlice packet)2109   void on_result(BufferSlice packet) final {
2110     auto result_ptr = fetch_result<telegram_api::channels_editAdmin>(packet);
2111     if (result_ptr.is_error()) {
2112       return on_error(result_ptr.move_as_error());
2113     }
2114 
2115     auto ptr = result_ptr.move_as_ok();
2116     LOG(INFO) << "Receive result for EditChannelAdminQuery: " << to_string(ptr);
2117     td_->contacts_manager_->invalidate_channel_full(channel_id_, false);
2118     td_->updates_manager_->on_get_updates(std::move(ptr), std::move(promise_));
2119   }
2120 
on_error(Status status)2121   void on_error(Status status) final {
2122     td_->contacts_manager_->on_get_channel_error(channel_id_, status, "EditChannelAdminQuery");
2123     promise_.set_error(std::move(status));
2124     td_->updates_manager_->get_difference("EditChannelAdminQuery");
2125   }
2126 };
2127 
2128 class EditChannelBannedQuery final : public Td::ResultHandler {
2129   Promise<Unit> promise_;
2130   ChannelId channel_id_;
2131 
2132  public:
EditChannelBannedQuery(Promise<Unit> && promise)2133   explicit EditChannelBannedQuery(Promise<Unit> &&promise) : promise_(std::move(promise)) {
2134   }
2135 
send(ChannelId channel_id,tl_object_ptr<telegram_api::InputPeer> && input_peer,const DialogParticipantStatus & status)2136   void send(ChannelId channel_id, tl_object_ptr<telegram_api::InputPeer> &&input_peer,
2137             const DialogParticipantStatus &status) {
2138     channel_id_ = channel_id;
2139     auto input_channel = td_->contacts_manager_->get_input_channel(channel_id);
2140     CHECK(input_channel != nullptr);
2141     send_query(G()->net_query_creator().create(telegram_api::channels_editBanned(
2142         std::move(input_channel), std::move(input_peer), status.get_chat_banned_rights())));
2143   }
2144 
on_result(BufferSlice packet)2145   void on_result(BufferSlice packet) final {
2146     auto result_ptr = fetch_result<telegram_api::channels_editBanned>(packet);
2147     if (result_ptr.is_error()) {
2148       return on_error(result_ptr.move_as_error());
2149     }
2150 
2151     auto ptr = result_ptr.move_as_ok();
2152     LOG(INFO) << "Receive result for EditChannelBannedQuery: " << to_string(ptr);
2153     td_->contacts_manager_->invalidate_channel_full(channel_id_, false);
2154     td_->updates_manager_->on_get_updates(std::move(ptr), std::move(promise_));
2155   }
2156 
on_error(Status status)2157   void on_error(Status status) final {
2158     td_->contacts_manager_->on_get_channel_error(channel_id_, status, "EditChannelBannedQuery");
2159     promise_.set_error(std::move(status));
2160     td_->updates_manager_->get_difference("EditChannelBannedQuery");
2161   }
2162 };
2163 
2164 class LeaveChannelQuery final : public Td::ResultHandler {
2165   Promise<Unit> promise_;
2166   ChannelId channel_id_;
2167 
2168  public:
LeaveChannelQuery(Promise<Unit> && promise)2169   explicit LeaveChannelQuery(Promise<Unit> &&promise) : promise_(std::move(promise)) {
2170   }
2171 
send(ChannelId channel_id)2172   void send(ChannelId channel_id) {
2173     channel_id_ = channel_id;
2174     auto input_channel = td_->contacts_manager_->get_input_channel(channel_id);
2175     CHECK(input_channel != nullptr);
2176     send_query(G()->net_query_creator().create(telegram_api::channels_leaveChannel(std::move(input_channel))));
2177   }
2178 
on_result(BufferSlice packet)2179   void on_result(BufferSlice packet) final {
2180     auto result_ptr = fetch_result<telegram_api::channels_leaveChannel>(packet);
2181     if (result_ptr.is_error()) {
2182       return on_error(result_ptr.move_as_error());
2183     }
2184 
2185     auto ptr = result_ptr.move_as_ok();
2186     LOG(INFO) << "Receive result for LeaveChannelQuery: " << to_string(ptr);
2187     td_->updates_manager_->on_get_updates(std::move(ptr), std::move(promise_));
2188   }
2189 
on_error(Status status)2190   void on_error(Status status) final {
2191     td_->contacts_manager_->on_get_channel_error(channel_id_, status, "LeaveChannelQuery");
2192     promise_.set_error(std::move(status));
2193     td_->updates_manager_->get_difference("LeaveChannelQuery");
2194   }
2195 };
2196 
2197 class CanEditChannelCreatorQuery final : public Td::ResultHandler {
2198   Promise<Unit> promise_;
2199 
2200  public:
CanEditChannelCreatorQuery(Promise<Unit> && promise)2201   explicit CanEditChannelCreatorQuery(Promise<Unit> &&promise) : promise_(std::move(promise)) {
2202   }
2203 
send()2204   void send() {
2205     auto input_user = td_->contacts_manager_->get_input_user(td_->contacts_manager_->get_my_id());
2206     CHECK(input_user != nullptr);
2207     send_query(G()->net_query_creator().create(telegram_api::channels_editCreator(
2208         telegram_api::make_object<telegram_api::inputChannelEmpty>(), std::move(input_user),
2209         make_tl_object<telegram_api::inputCheckPasswordEmpty>())));
2210   }
2211 
on_result(BufferSlice packet)2212   void on_result(BufferSlice packet) final {
2213     auto result_ptr = fetch_result<telegram_api::channels_editCreator>(packet);
2214     if (result_ptr.is_error()) {
2215       return on_error(result_ptr.move_as_error());
2216     }
2217 
2218     auto ptr = result_ptr.move_as_ok();
2219     LOG(ERROR) << "Receive result for CanEditChannelCreatorQuery: " << to_string(ptr);
2220     promise_.set_error(Status::Error(500, "Server doesn't returned error"));
2221   }
2222 
on_error(Status status)2223   void on_error(Status status) final {
2224     promise_.set_error(std::move(status));
2225   }
2226 };
2227 
2228 class EditChannelCreatorQuery final : public Td::ResultHandler {
2229   Promise<Unit> promise_;
2230   ChannelId channel_id_;
2231 
2232  public:
EditChannelCreatorQuery(Promise<Unit> && promise)2233   explicit EditChannelCreatorQuery(Promise<Unit> &&promise) : promise_(std::move(promise)) {
2234   }
2235 
send(ChannelId channel_id,UserId user_id,tl_object_ptr<telegram_api::InputCheckPasswordSRP> input_check_password)2236   void send(ChannelId channel_id, UserId user_id,
2237             tl_object_ptr<telegram_api::InputCheckPasswordSRP> input_check_password) {
2238     channel_id_ = channel_id;
2239     auto input_channel = td_->contacts_manager_->get_input_channel(channel_id);
2240     if (input_channel == nullptr) {
2241       return promise_.set_error(Status::Error(400, "Have no access to the chat"));
2242     }
2243     auto input_user = td_->contacts_manager_->get_input_user(user_id);
2244     if (input_user == nullptr) {
2245       return promise_.set_error(Status::Error(400, "Have no access to the user"));
2246     }
2247     send_query(G()->net_query_creator().create(telegram_api::channels_editCreator(
2248         std::move(input_channel), std::move(input_user), std::move(input_check_password))));
2249   }
2250 
on_result(BufferSlice packet)2251   void on_result(BufferSlice packet) final {
2252     auto result_ptr = fetch_result<telegram_api::channels_editCreator>(packet);
2253     if (result_ptr.is_error()) {
2254       return on_error(result_ptr.move_as_error());
2255     }
2256 
2257     auto ptr = result_ptr.move_as_ok();
2258     LOG(INFO) << "Receive result for EditChannelCreatorQuery: " << to_string(ptr);
2259     td_->contacts_manager_->invalidate_channel_full(channel_id_, false);
2260     td_->updates_manager_->on_get_updates(std::move(ptr), std::move(promise_));
2261   }
2262 
on_error(Status status)2263   void on_error(Status status) final {
2264     td_->contacts_manager_->on_get_channel_error(channel_id_, status, "EditChannelCreatorQuery");
2265     promise_.set_error(std::move(status));
2266     td_->updates_manager_->get_difference("EditChannelCreatorQuery");
2267   }
2268 };
2269 
2270 class MigrateChatQuery final : public Td::ResultHandler {
2271   Promise<Unit> promise_;
2272 
2273  public:
MigrateChatQuery(Promise<Unit> && promise)2274   explicit MigrateChatQuery(Promise<Unit> &&promise) : promise_(std::move(promise)) {
2275   }
2276 
send(ChatId chat_id)2277   void send(ChatId chat_id) {
2278     send_query(G()->net_query_creator().create(telegram_api::messages_migrateChat(chat_id.get())));
2279   }
2280 
on_result(BufferSlice packet)2281   void on_result(BufferSlice packet) final {
2282     auto result_ptr = fetch_result<telegram_api::messages_migrateChat>(packet);
2283     if (result_ptr.is_error()) {
2284       return on_error(result_ptr.move_as_error());
2285     }
2286 
2287     auto ptr = result_ptr.move_as_ok();
2288     LOG(INFO) << "Receive result for MigrateChatQuery: " << to_string(ptr);
2289     td_->updates_manager_->on_get_updates(std::move(ptr), std::move(promise_));
2290   }
2291 
on_error(Status status)2292   void on_error(Status status) final {
2293     promise_.set_error(std::move(status));
2294     td_->updates_manager_->get_difference("MigrateChatQuery");
2295   }
2296 };
2297 
2298 class GetCreatedPublicChannelsQuery final : public Td::ResultHandler {
2299   Promise<Unit> promise_;
2300   PublicDialogType type_;
2301 
2302  public:
GetCreatedPublicChannelsQuery(Promise<Unit> && promise)2303   explicit GetCreatedPublicChannelsQuery(Promise<Unit> &&promise) : promise_(std::move(promise)) {
2304   }
2305 
send(PublicDialogType type,bool check_limit)2306   void send(PublicDialogType type, bool check_limit) {
2307     type_ = type;
2308     int32 flags = 0;
2309     if (type_ == PublicDialogType::IsLocationBased) {
2310       flags |= telegram_api::channels_getAdminedPublicChannels::BY_LOCATION_MASK;
2311     }
2312     if (check_limit) {
2313       flags |= telegram_api::channels_getAdminedPublicChannels::CHECK_LIMIT_MASK;
2314     }
2315     send_query(G()->net_query_creator().create(
2316         telegram_api::channels_getAdminedPublicChannels(flags, false /*ignored*/, false /*ignored*/)));
2317   }
2318 
on_result(BufferSlice packet)2319   void on_result(BufferSlice packet) final {
2320     auto result_ptr = fetch_result<telegram_api::channels_getAdminedPublicChannels>(packet);
2321     if (result_ptr.is_error()) {
2322       return on_error(result_ptr.move_as_error());
2323     }
2324 
2325     auto chats_ptr = result_ptr.move_as_ok();
2326     LOG(INFO) << "Receive result for GetCreatedPublicChannelsQuery: " << to_string(chats_ptr);
2327     int32 constructor_id = chats_ptr->get_id();
2328     switch (constructor_id) {
2329       case telegram_api::messages_chats::ID: {
2330         auto chats = move_tl_object_as<telegram_api::messages_chats>(chats_ptr);
2331         td_->contacts_manager_->on_get_created_public_channels(type_, std::move(chats->chats_));
2332         break;
2333       }
2334       case telegram_api::messages_chatsSlice::ID: {
2335         auto chats = move_tl_object_as<telegram_api::messages_chatsSlice>(chats_ptr);
2336         LOG(ERROR) << "Receive chatsSlice in result of GetCreatedPublicChannelsQuery";
2337         td_->contacts_manager_->on_get_created_public_channels(type_, std::move(chats->chats_));
2338         break;
2339       }
2340       default:
2341         UNREACHABLE();
2342     }
2343 
2344     promise_.set_value(Unit());
2345   }
2346 
on_error(Status status)2347   void on_error(Status status) final {
2348     promise_.set_error(std::move(status));
2349   }
2350 };
2351 
2352 class GetGroupsForDiscussionQuery final : public Td::ResultHandler {
2353   Promise<Unit> promise_;
2354 
2355  public:
GetGroupsForDiscussionQuery(Promise<Unit> && promise)2356   explicit GetGroupsForDiscussionQuery(Promise<Unit> &&promise) : promise_(std::move(promise)) {
2357   }
2358 
send()2359   void send() {
2360     send_query(G()->net_query_creator().create(telegram_api::channels_getGroupsForDiscussion()));
2361   }
2362 
on_result(BufferSlice packet)2363   void on_result(BufferSlice packet) final {
2364     auto result_ptr = fetch_result<telegram_api::channels_getGroupsForDiscussion>(packet);
2365     if (result_ptr.is_error()) {
2366       return on_error(result_ptr.move_as_error());
2367     }
2368 
2369     auto chats_ptr = result_ptr.move_as_ok();
2370     LOG(INFO) << "Receive result for GetGroupsForDiscussionQuery: " << to_string(chats_ptr);
2371     int32 constructor_id = chats_ptr->get_id();
2372     switch (constructor_id) {
2373       case telegram_api::messages_chats::ID: {
2374         auto chats = move_tl_object_as<telegram_api::messages_chats>(chats_ptr);
2375         td_->contacts_manager_->on_get_dialogs_for_discussion(std::move(chats->chats_));
2376         break;
2377       }
2378       case telegram_api::messages_chatsSlice::ID: {
2379         auto chats = move_tl_object_as<telegram_api::messages_chatsSlice>(chats_ptr);
2380         LOG(ERROR) << "Receive chatsSlice in result of GetGroupsForDiscussionQuery";
2381         td_->contacts_manager_->on_get_dialogs_for_discussion(std::move(chats->chats_));
2382         break;
2383       }
2384       default:
2385         UNREACHABLE();
2386     }
2387 
2388     promise_.set_value(Unit());
2389   }
2390 
on_error(Status status)2391   void on_error(Status status) final {
2392     promise_.set_error(std::move(status));
2393   }
2394 };
2395 
2396 class GetInactiveChannelsQuery final : public Td::ResultHandler {
2397   Promise<Unit> promise_;
2398 
2399  public:
GetInactiveChannelsQuery(Promise<Unit> && promise)2400   explicit GetInactiveChannelsQuery(Promise<Unit> &&promise) : promise_(std::move(promise)) {
2401   }
2402 
send()2403   void send() {
2404     send_query(G()->net_query_creator().create(telegram_api::channels_getInactiveChannels()));
2405   }
2406 
on_result(BufferSlice packet)2407   void on_result(BufferSlice packet) final {
2408     auto result_ptr = fetch_result<telegram_api::channels_getInactiveChannels>(packet);
2409     if (result_ptr.is_error()) {
2410       return on_error(result_ptr.move_as_error());
2411     }
2412 
2413     auto result = result_ptr.move_as_ok();
2414     LOG(INFO) << "Receive result for GetInactiveChannelsQuery: " << to_string(result);
2415     // TODO use result->dates_
2416     td_->contacts_manager_->on_get_users(std::move(result->users_), "GetInactiveChannelsQuery");
2417     td_->contacts_manager_->on_get_inactive_channels(std::move(result->chats_));
2418 
2419     promise_.set_value(Unit());
2420   }
2421 
on_error(Status status)2422   void on_error(Status status) final {
2423     promise_.set_error(std::move(status));
2424   }
2425 };
2426 
2427 class GetUsersQuery final : public Td::ResultHandler {
2428   Promise<Unit> promise_;
2429 
2430  public:
GetUsersQuery(Promise<Unit> && promise)2431   explicit GetUsersQuery(Promise<Unit> &&promise) : promise_(std::move(promise)) {
2432   }
2433 
send(vector<tl_object_ptr<telegram_api::InputUser>> && input_users)2434   void send(vector<tl_object_ptr<telegram_api::InputUser>> &&input_users) {
2435     send_query(G()->net_query_creator().create(telegram_api::users_getUsers(std::move(input_users))));
2436   }
2437 
on_result(BufferSlice packet)2438   void on_result(BufferSlice packet) final {
2439     auto result_ptr = fetch_result<telegram_api::users_getUsers>(packet);
2440     if (result_ptr.is_error()) {
2441       return on_error(result_ptr.move_as_error());
2442     }
2443 
2444     td_->contacts_manager_->on_get_users(result_ptr.move_as_ok(), "GetUsersQuery");
2445 
2446     promise_.set_value(Unit());
2447   }
2448 
on_error(Status status)2449   void on_error(Status status) final {
2450     promise_.set_error(std::move(status));
2451   }
2452 };
2453 
2454 class GetFullUserQuery final : public Td::ResultHandler {
2455   Promise<Unit> promise_;
2456 
2457  public:
GetFullUserQuery(Promise<Unit> && promise)2458   explicit GetFullUserQuery(Promise<Unit> &&promise) : promise_(std::move(promise)) {
2459   }
2460 
send(tl_object_ptr<telegram_api::InputUser> && input_user)2461   void send(tl_object_ptr<telegram_api::InputUser> &&input_user) {
2462     send_query(G()->net_query_creator().create(telegram_api::users_getFullUser(std::move(input_user))));
2463   }
2464 
on_result(BufferSlice packet)2465   void on_result(BufferSlice packet) final {
2466     auto result_ptr = fetch_result<telegram_api::users_getFullUser>(packet);
2467     if (result_ptr.is_error()) {
2468       return on_error(result_ptr.move_as_error());
2469     }
2470 
2471     auto ptr = result_ptr.move_as_ok();
2472     LOG(DEBUG) << "Receive result for GetFullUserQuery: " << to_string(ptr);
2473     td_->contacts_manager_->on_get_users(std::move(ptr->users_), "GetFullUserQuery");
2474     td_->contacts_manager_->on_get_chats(std::move(ptr->chats_), "GetFullUserQuery");
2475     td_->contacts_manager_->on_get_user_full(std::move(ptr->full_user_));
2476     promise_.set_value(Unit());
2477   }
2478 
on_error(Status status)2479   void on_error(Status status) final {
2480     promise_.set_error(std::move(status));
2481   }
2482 };
2483 
2484 class GetUserPhotosQuery final : public Td::ResultHandler {
2485   Promise<Unit> promise_;
2486   UserId user_id_;
2487   int32 offset_;
2488   int32 limit_;
2489 
2490  public:
GetUserPhotosQuery(Promise<Unit> && promise)2491   explicit GetUserPhotosQuery(Promise<Unit> &&promise) : promise_(std::move(promise)) {
2492   }
2493 
send(UserId user_id,tl_object_ptr<telegram_api::InputUser> && input_user,int32 offset,int32 limit,int64 photo_id)2494   void send(UserId user_id, tl_object_ptr<telegram_api::InputUser> &&input_user, int32 offset, int32 limit,
2495             int64 photo_id) {
2496     user_id_ = user_id;
2497     offset_ = offset;
2498     limit_ = limit;
2499     send_query(G()->net_query_creator().create(
2500         telegram_api::photos_getUserPhotos(std::move(input_user), offset, photo_id, limit)));
2501   }
2502 
on_result(BufferSlice packet)2503   void on_result(BufferSlice packet) final {
2504     auto result_ptr = fetch_result<telegram_api::photos_getUserPhotos>(packet);
2505     if (result_ptr.is_error()) {
2506       return on_error(result_ptr.move_as_error());
2507     }
2508 
2509     auto ptr = result_ptr.move_as_ok();
2510 
2511     LOG(INFO) << "Receive result for GetUserPhotosQuery: " << to_string(ptr);
2512     int32 constructor_id = ptr->get_id();
2513     if (constructor_id == telegram_api::photos_photos::ID) {
2514       auto photos = move_tl_object_as<telegram_api::photos_photos>(ptr);
2515 
2516       td_->contacts_manager_->on_get_users(std::move(photos->users_), "GetUserPhotosQuery");
2517       auto photos_size = narrow_cast<int32>(photos->photos_.size());
2518       td_->contacts_manager_->on_get_user_photos(user_id_, offset_, limit_, photos_size, std::move(photos->photos_));
2519     } else {
2520       CHECK(constructor_id == telegram_api::photos_photosSlice::ID);
2521       auto photos = move_tl_object_as<telegram_api::photos_photosSlice>(ptr);
2522 
2523       td_->contacts_manager_->on_get_users(std::move(photos->users_), "GetUserPhotosQuery");
2524       td_->contacts_manager_->on_get_user_photos(user_id_, offset_, limit_, photos->count_, std::move(photos->photos_));
2525     }
2526 
2527     promise_.set_value(Unit());
2528   }
2529 
on_error(Status status)2530   void on_error(Status status) final {
2531     promise_.set_error(std::move(status));
2532   }
2533 };
2534 
2535 class GetChatsQuery final : public Td::ResultHandler {
2536   Promise<Unit> promise_;
2537 
2538  public:
GetChatsQuery(Promise<Unit> && promise)2539   explicit GetChatsQuery(Promise<Unit> &&promise) : promise_(std::move(promise)) {
2540   }
2541 
send(vector<int64> && chat_ids)2542   void send(vector<int64> &&chat_ids) {
2543     send_query(G()->net_query_creator().create(telegram_api::messages_getChats(std::move(chat_ids))));
2544   }
2545 
on_result(BufferSlice packet)2546   void on_result(BufferSlice packet) final {
2547     auto result_ptr = fetch_result<telegram_api::messages_getChats>(packet);
2548     if (result_ptr.is_error()) {
2549       return on_error(result_ptr.move_as_error());
2550     }
2551 
2552     auto chats_ptr = result_ptr.move_as_ok();
2553     int32 constructor_id = chats_ptr->get_id();
2554     switch (constructor_id) {
2555       case telegram_api::messages_chats::ID: {
2556         auto chats = move_tl_object_as<telegram_api::messages_chats>(chats_ptr);
2557         td_->contacts_manager_->on_get_chats(std::move(chats->chats_), "GetChatsQuery");
2558         break;
2559       }
2560       case telegram_api::messages_chatsSlice::ID: {
2561         auto chats = move_tl_object_as<telegram_api::messages_chatsSlice>(chats_ptr);
2562         LOG(ERROR) << "Receive chatsSlice in result of GetChatsQuery";
2563         td_->contacts_manager_->on_get_chats(std::move(chats->chats_), "GetChatsQuery");
2564         break;
2565       }
2566       default:
2567         UNREACHABLE();
2568     }
2569 
2570     promise_.set_value(Unit());
2571   }
2572 
on_error(Status status)2573   void on_error(Status status) final {
2574     promise_.set_error(std::move(status));
2575   }
2576 };
2577 
2578 class GetFullChatQuery final : public Td::ResultHandler {
2579   Promise<Unit> promise_;
2580   ChatId chat_id_;
2581 
2582  public:
GetFullChatQuery(Promise<Unit> && promise)2583   explicit GetFullChatQuery(Promise<Unit> &&promise) : promise_(std::move(promise)) {
2584   }
2585 
send(ChatId chat_id)2586   void send(ChatId chat_id) {
2587     send_query(G()->net_query_creator().create(telegram_api::messages_getFullChat(chat_id.get())));
2588   }
2589 
on_result(BufferSlice packet)2590   void on_result(BufferSlice packet) final {
2591     auto result_ptr = fetch_result<telegram_api::messages_getFullChat>(packet);
2592     if (result_ptr.is_error()) {
2593       return on_error(result_ptr.move_as_error());
2594     }
2595 
2596     auto ptr = result_ptr.move_as_ok();
2597     td_->contacts_manager_->on_get_users(std::move(ptr->users_), "GetFullChatQuery");
2598     td_->contacts_manager_->on_get_chats(std::move(ptr->chats_), "GetFullChatQuery");
2599     td_->contacts_manager_->on_get_chat_full(std::move(ptr->full_chat_), std::move(promise_));
2600   }
2601 
on_error(Status status)2602   void on_error(Status status) final {
2603     td_->contacts_manager_->on_get_chat_full_failed(chat_id_);
2604     promise_.set_error(std::move(status));
2605   }
2606 };
2607 
2608 class GetChannelsQuery final : public Td::ResultHandler {
2609   Promise<Unit> promise_;
2610   ChannelId channel_id_;
2611 
2612  public:
GetChannelsQuery(Promise<Unit> && promise)2613   explicit GetChannelsQuery(Promise<Unit> &&promise) : promise_(std::move(promise)) {
2614   }
2615 
send(tl_object_ptr<telegram_api::InputChannel> && input_channel)2616   void send(tl_object_ptr<telegram_api::InputChannel> &&input_channel) {
2617     CHECK(input_channel != nullptr);
2618     if (input_channel->get_id() == telegram_api::inputChannel::ID) {
2619       channel_id_ = ChannelId(static_cast<const telegram_api::inputChannel *>(input_channel.get())->channel_id_);
2620     }
2621 
2622     vector<tl_object_ptr<telegram_api::InputChannel>> input_channels;
2623     input_channels.push_back(std::move(input_channel));
2624     send_query(G()->net_query_creator().create(telegram_api::channels_getChannels(std::move(input_channels))));
2625   }
2626 
on_result(BufferSlice packet)2627   void on_result(BufferSlice packet) final {
2628     auto result_ptr = fetch_result<telegram_api::channels_getChannels>(packet);
2629     if (result_ptr.is_error()) {
2630       return on_error(result_ptr.move_as_error());
2631     }
2632 
2633     //    LOG(INFO) << "Receive result for GetChannelsQuery: " << to_string(result_ptr.ok());
2634     auto chats_ptr = result_ptr.move_as_ok();
2635     int32 constructor_id = chats_ptr->get_id();
2636     switch (constructor_id) {
2637       case telegram_api::messages_chats::ID: {
2638         auto chats = move_tl_object_as<telegram_api::messages_chats>(chats_ptr);
2639         td_->contacts_manager_->on_get_chats(std::move(chats->chats_), "GetChannelsQuery");
2640         break;
2641       }
2642       case telegram_api::messages_chatsSlice::ID: {
2643         auto chats = move_tl_object_as<telegram_api::messages_chatsSlice>(chats_ptr);
2644         LOG(ERROR) << "Receive chatsSlice in result of GetChannelsQuery";
2645         td_->contacts_manager_->on_get_chats(std::move(chats->chats_), "GetChannelsQuery");
2646         break;
2647       }
2648       default:
2649         UNREACHABLE();
2650     }
2651 
2652     promise_.set_value(Unit());
2653   }
2654 
on_error(Status status)2655   void on_error(Status status) final {
2656     td_->contacts_manager_->on_get_channel_error(channel_id_, status, "GetChannelsQuery");
2657     promise_.set_error(std::move(status));
2658   }
2659 };
2660 
2661 class GetFullChannelQuery final : public Td::ResultHandler {
2662   Promise<Unit> promise_;
2663   ChannelId channel_id_;
2664 
2665  public:
GetFullChannelQuery(Promise<Unit> && promise)2666   explicit GetFullChannelQuery(Promise<Unit> &&promise) : promise_(std::move(promise)) {
2667   }
2668 
send(ChannelId channel_id,tl_object_ptr<telegram_api::InputChannel> && input_channel)2669   void send(ChannelId channel_id, tl_object_ptr<telegram_api::InputChannel> &&input_channel) {
2670     channel_id_ = channel_id;
2671     send_query(G()->net_query_creator().create(telegram_api::channels_getFullChannel(std::move(input_channel))));
2672   }
2673 
on_result(BufferSlice packet)2674   void on_result(BufferSlice packet) final {
2675     auto result_ptr = fetch_result<telegram_api::channels_getFullChannel>(packet);
2676     if (result_ptr.is_error()) {
2677       return on_error(result_ptr.move_as_error());
2678     }
2679 
2680     auto ptr = result_ptr.move_as_ok();
2681     td_->contacts_manager_->on_get_users(std::move(ptr->users_), "GetFullChannelQuery");
2682     td_->contacts_manager_->on_get_chats(std::move(ptr->chats_), "GetFullChannelQuery");
2683     td_->contacts_manager_->on_get_chat_full(std::move(ptr->full_chat_), std::move(promise_));
2684   }
2685 
on_error(Status status)2686   void on_error(Status status) final {
2687     td_->contacts_manager_->on_get_channel_error(channel_id_, status, "GetFullChannelQuery");
2688     td_->contacts_manager_->on_get_channel_full_failed(channel_id_);
2689     promise_.set_error(std::move(status));
2690   }
2691 };
2692 
2693 class GetChannelParticipantQuery final : public Td::ResultHandler {
2694   Promise<DialogParticipant> promise_;
2695   ChannelId channel_id_;
2696   DialogId participant_dialog_id_;
2697 
2698  public:
GetChannelParticipantQuery(Promise<DialogParticipant> && promise)2699   explicit GetChannelParticipantQuery(Promise<DialogParticipant> &&promise) : promise_(std::move(promise)) {
2700   }
2701 
send(ChannelId channel_id,DialogId participant_dialog_id,tl_object_ptr<telegram_api::InputPeer> && input_peer)2702   void send(ChannelId channel_id, DialogId participant_dialog_id, tl_object_ptr<telegram_api::InputPeer> &&input_peer) {
2703     auto input_channel = td_->contacts_manager_->get_input_channel(channel_id);
2704     if (input_channel == nullptr) {
2705       return promise_.set_error(Status::Error(400, "Supergroup not found"));
2706     }
2707 
2708     CHECK(input_peer != nullptr);
2709 
2710     channel_id_ = channel_id;
2711     participant_dialog_id_ = participant_dialog_id;
2712     send_query(G()->net_query_creator().create(
2713         telegram_api::channels_getParticipant(std::move(input_channel), std::move(input_peer))));
2714   }
2715 
on_result(BufferSlice packet)2716   void on_result(BufferSlice packet) final {
2717     auto result_ptr = fetch_result<telegram_api::channels_getParticipant>(packet);
2718     if (result_ptr.is_error()) {
2719       return on_error(result_ptr.move_as_error());
2720     }
2721 
2722     auto participant = result_ptr.move_as_ok();
2723     LOG(INFO) << "Receive result for GetChannelParticipantQuery: " << to_string(participant);
2724 
2725     td_->contacts_manager_->on_get_users(std::move(participant->users_), "GetChannelParticipantQuery");
2726     td_->contacts_manager_->on_get_chats(std::move(participant->chats_), "GetChannelParticipantQuery");
2727     DialogParticipant result(std::move(participant->participant_));
2728     if (!result.is_valid()) {
2729       LOG(ERROR) << "Receive invalid " << result;
2730       return promise_.set_error(Status::Error(500, "Receive invalid chat member"));
2731     }
2732     promise_.set_value(std::move(result));
2733   }
2734 
on_error(Status status)2735   void on_error(Status status) final {
2736     if (status.message() == "USER_NOT_PARTICIPANT") {
2737       promise_.set_value(DialogParticipant::left(participant_dialog_id_));
2738       return;
2739     }
2740 
2741     // td_->contacts_manager_->on_get_channel_error(channel_id_, status, "GetChannelParticipantQuery");
2742     promise_.set_error(std::move(status));
2743   }
2744 };
2745 
2746 class GetChannelParticipantsQuery final : public Td::ResultHandler {
2747   Promise<tl_object_ptr<telegram_api::channels_channelParticipants>> promise_;
2748   ChannelId channel_id_;
2749 
2750  public:
GetChannelParticipantsQuery(Promise<tl_object_ptr<telegram_api::channels_channelParticipants>> && promise)2751   explicit GetChannelParticipantsQuery(Promise<tl_object_ptr<telegram_api::channels_channelParticipants>> &&promise)
2752       : promise_(std::move(promise)) {
2753   }
2754 
send(ChannelId channel_id,const ChannelParticipantsFilter & filter,int32 offset,int32 limit)2755   void send(ChannelId channel_id, const ChannelParticipantsFilter &filter, int32 offset, int32 limit) {
2756     auto input_channel = td_->contacts_manager_->get_input_channel(channel_id);
2757     if (input_channel == nullptr) {
2758       return promise_.set_error(Status::Error(400, "Supergroup not found"));
2759     }
2760 
2761     channel_id_ = channel_id;
2762     send_query(G()->net_query_creator().create(telegram_api::channels_getParticipants(
2763         std::move(input_channel), filter.get_input_channel_participants_filter(), offset, limit, 0)));
2764   }
2765 
on_result(BufferSlice packet)2766   void on_result(BufferSlice packet) final {
2767     auto result_ptr = fetch_result<telegram_api::channels_getParticipants>(packet);
2768     if (result_ptr.is_error()) {
2769       return on_error(result_ptr.move_as_error());
2770     }
2771 
2772     auto participants_ptr = result_ptr.move_as_ok();
2773     LOG(INFO) << "Receive result for GetChannelParticipantsQuery: " << to_string(participants_ptr);
2774     switch (participants_ptr->get_id()) {
2775       case telegram_api::channels_channelParticipants::ID: {
2776         promise_.set_value(telegram_api::move_object_as<telegram_api::channels_channelParticipants>(participants_ptr));
2777         break;
2778       }
2779       case telegram_api::channels_channelParticipantsNotModified::ID:
2780         LOG(ERROR) << "Receive channelParticipantsNotModified";
2781         return on_error(Status::Error(500, "Receive channelParticipantsNotModified"));
2782       default:
2783         UNREACHABLE();
2784     }
2785   }
2786 
on_error(Status status)2787   void on_error(Status status) final {
2788     td_->contacts_manager_->on_get_channel_error(channel_id_, status, "GetChannelParticipantsQuery");
2789     promise_.set_error(std::move(status));
2790   }
2791 };
2792 
2793 class GetChannelAdministratorsQuery final : public Td::ResultHandler {
2794   Promise<Unit> promise_;
2795   ChannelId channel_id_;
2796 
2797  public:
GetChannelAdministratorsQuery(Promise<Unit> && promise)2798   explicit GetChannelAdministratorsQuery(Promise<Unit> &&promise) : promise_(std::move(promise)) {
2799   }
2800 
send(ChannelId channel_id,int64 hash)2801   void send(ChannelId channel_id, int64 hash) {
2802     auto input_channel = td_->contacts_manager_->get_input_channel(channel_id);
2803     if (input_channel == nullptr) {
2804       return promise_.set_error(Status::Error(400, "Supergroup not found"));
2805     }
2806 
2807     hash = 0;  // to load even only ranks or creator changed
2808 
2809     channel_id_ = channel_id;
2810     send_query(G()->net_query_creator().create(telegram_api::channels_getParticipants(
2811         std::move(input_channel), telegram_api::make_object<telegram_api::channelParticipantsAdmins>(), 0,
2812         std::numeric_limits<int32>::max(), hash)));
2813   }
2814 
on_result(BufferSlice packet)2815   void on_result(BufferSlice packet) final {
2816     auto result_ptr = fetch_result<telegram_api::channels_getParticipants>(packet);
2817     if (result_ptr.is_error()) {
2818       return on_error(result_ptr.move_as_error());
2819     }
2820 
2821     auto participants_ptr = result_ptr.move_as_ok();
2822     LOG(INFO) << "Receive result for GetChannelAdministratorsQuery: " << to_string(participants_ptr);
2823     switch (participants_ptr->get_id()) {
2824       case telegram_api::channels_channelParticipants::ID: {
2825         auto participants = telegram_api::move_object_as<telegram_api::channels_channelParticipants>(participants_ptr);
2826         td_->contacts_manager_->on_get_users(std::move(participants->users_), "GetChannelAdministratorsQuery");
2827         td_->contacts_manager_->on_get_chats(std::move(participants->chats_), "GetChannelAdministratorsQuery");
2828         vector<DialogAdministrator> administrators;
2829         administrators.reserve(participants->participants_.size());
2830         for (auto &participant : participants->participants_) {
2831           DialogParticipant dialog_participant(std::move(participant));
2832           if (!dialog_participant.is_valid() || !dialog_participant.status_.is_administrator() ||
2833               dialog_participant.dialog_id_.get_type() != DialogType::User) {
2834             LOG(ERROR) << "Receive " << dialog_participant << " as an administrator of " << channel_id_;
2835             continue;
2836           }
2837           administrators.emplace_back(dialog_participant.dialog_id_.get_user_id(),
2838                                       dialog_participant.status_.get_rank(), dialog_participant.status_.is_creator());
2839         }
2840 
2841         td_->contacts_manager_->on_update_channel_administrator_count(channel_id_,
2842                                                                       narrow_cast<int32>(administrators.size()));
2843         td_->contacts_manager_->on_update_dialog_administrators(DialogId(channel_id_), std::move(administrators), true,
2844                                                                 false);
2845 
2846         break;
2847       }
2848       case telegram_api::channels_channelParticipantsNotModified::ID:
2849         break;
2850       default:
2851         UNREACHABLE();
2852     }
2853 
2854     promise_.set_value(Unit());
2855   }
2856 
on_error(Status status)2857   void on_error(Status status) final {
2858     td_->contacts_manager_->on_get_channel_error(channel_id_, status, "GetChannelAdministratorsQuery");
2859     promise_.set_error(std::move(status));
2860   }
2861 };
2862 
2863 class GetSupportUserQuery final : public Td::ResultHandler {
2864   Promise<Unit> promise_;
2865 
2866  public:
GetSupportUserQuery(Promise<Unit> && promise)2867   explicit GetSupportUserQuery(Promise<Unit> &&promise) : promise_(std::move(promise)) {
2868   }
2869 
send()2870   void send() {
2871     send_query(G()->net_query_creator().create(telegram_api::help_getSupport()));
2872   }
2873 
on_result(BufferSlice packet)2874   void on_result(BufferSlice packet) final {
2875     auto result_ptr = fetch_result<telegram_api::help_getSupport>(packet);
2876     if (result_ptr.is_error()) {
2877       return on_error(result_ptr.move_as_error());
2878     }
2879 
2880     auto ptr = result_ptr.move_as_ok();
2881     LOG(INFO) << "Receive result for GetSupportUserQuery: " << to_string(ptr);
2882 
2883     td_->contacts_manager_->on_get_user(std::move(ptr->user_), "GetSupportUserQuery", false, true);
2884 
2885     promise_.set_value(Unit());
2886   }
2887 
on_error(Status status)2888   void on_error(Status status) final {
2889     promise_.set_error(std::move(status));
2890   }
2891 };
2892 
convert_date_range(const tl_object_ptr<telegram_api::statsDateRangeDays> & obj)2893 tl_object_ptr<td_api::dateRange> ContactsManager::convert_date_range(
2894     const tl_object_ptr<telegram_api::statsDateRangeDays> &obj) {
2895   return make_tl_object<td_api::dateRange>(obj->min_date_, obj->max_date_);
2896 }
2897 
convert_stats_graph(tl_object_ptr<telegram_api::StatsGraph> obj)2898 tl_object_ptr<td_api::StatisticalGraph> ContactsManager::convert_stats_graph(
2899     tl_object_ptr<telegram_api::StatsGraph> obj) {
2900   CHECK(obj != nullptr);
2901 
2902   switch (obj->get_id()) {
2903     case telegram_api::statsGraphAsync::ID: {
2904       auto graph = move_tl_object_as<telegram_api::statsGraphAsync>(obj);
2905       return make_tl_object<td_api::statisticalGraphAsync>(std::move(graph->token_));
2906     }
2907     case telegram_api::statsGraphError::ID: {
2908       auto graph = move_tl_object_as<telegram_api::statsGraphError>(obj);
2909       return make_tl_object<td_api::statisticalGraphError>(std::move(graph->error_));
2910     }
2911     case telegram_api::statsGraph::ID: {
2912       auto graph = move_tl_object_as<telegram_api::statsGraph>(obj);
2913       return make_tl_object<td_api::statisticalGraphData>(std::move(graph->json_->data_),
2914                                                           std::move(graph->zoom_token_));
2915     }
2916     default:
2917       UNREACHABLE();
2918       return nullptr;
2919   }
2920 }
2921 
get_percentage_value(double part,double total)2922 double ContactsManager::get_percentage_value(double part, double total) {
2923   if (total < 1e-6 && total > -1e-6) {
2924     if (part < 1e-6 && part > -1e-6) {
2925       return 0.0;
2926     }
2927     return 100.0;
2928   }
2929   if (part > 1e20) {
2930     return 100.0;
2931   }
2932   return part / total * 100;
2933 }
2934 
convert_stats_absolute_value(const tl_object_ptr<telegram_api::statsAbsValueAndPrev> & obj)2935 tl_object_ptr<td_api::statisticalValue> ContactsManager::convert_stats_absolute_value(
2936     const tl_object_ptr<telegram_api::statsAbsValueAndPrev> &obj) {
2937   return make_tl_object<td_api::statisticalValue>(obj->current_, obj->previous_,
2938                                                   get_percentage_value(obj->current_ - obj->previous_, obj->previous_));
2939 }
2940 
convert_megagroup_stats(tl_object_ptr<telegram_api::stats_megagroupStats> obj)2941 tl_object_ptr<td_api::chatStatisticsSupergroup> ContactsManager::convert_megagroup_stats(
2942     tl_object_ptr<telegram_api::stats_megagroupStats> obj) {
2943   CHECK(obj != nullptr);
2944 
2945   on_get_users(std::move(obj->users_), "convert_megagroup_stats");
2946 
2947   // just in case
2948   td::remove_if(obj->top_posters_, [](auto &obj) {
2949     return !UserId(obj->user_id_).is_valid() || obj->messages_ < 0 || obj->avg_chars_ < 0;
2950   });
2951   td::remove_if(obj->top_admins_, [](auto &obj) {
2952     return !UserId(obj->user_id_).is_valid() || obj->deleted_ < 0 || obj->kicked_ < 0 || obj->banned_ < 0;
2953   });
2954   td::remove_if(obj->top_inviters_,
2955                 [](auto &obj) { return !UserId(obj->user_id_).is_valid() || obj->invitations_ < 0; });
2956 
2957   auto top_senders =
2958       transform(std::move(obj->top_posters_), [this](tl_object_ptr<telegram_api::statsGroupTopPoster> &&top_poster) {
2959         return td_api::make_object<td_api::chatStatisticsMessageSenderInfo>(
2960             get_user_id_object(UserId(top_poster->user_id_), "get_top_senders"), top_poster->messages_,
2961             top_poster->avg_chars_);
2962       });
2963   auto top_administrators =
2964       transform(std::move(obj->top_admins_), [this](tl_object_ptr<telegram_api::statsGroupTopAdmin> &&top_admin) {
2965         return td_api::make_object<td_api::chatStatisticsAdministratorActionsInfo>(
2966             get_user_id_object(UserId(top_admin->user_id_), "get_top_administrators"), top_admin->deleted_,
2967             top_admin->kicked_, top_admin->banned_);
2968       });
2969   auto top_inviters =
2970       transform(std::move(obj->top_inviters_), [this](tl_object_ptr<telegram_api::statsGroupTopInviter> &&top_inviter) {
2971         return td_api::make_object<td_api::chatStatisticsInviterInfo>(
2972             get_user_id_object(UserId(top_inviter->user_id_), "get_top_inviters"), top_inviter->invitations_);
2973       });
2974 
2975   return make_tl_object<td_api::chatStatisticsSupergroup>(
2976       convert_date_range(obj->period_), convert_stats_absolute_value(obj->members_),
2977       convert_stats_absolute_value(obj->messages_), convert_stats_absolute_value(obj->viewers_),
2978       convert_stats_absolute_value(obj->posters_), convert_stats_graph(std::move(obj->growth_graph_)),
2979       convert_stats_graph(std::move(obj->members_graph_)),
2980       convert_stats_graph(std::move(obj->new_members_by_source_graph_)),
2981       convert_stats_graph(std::move(obj->languages_graph_)), convert_stats_graph(std::move(obj->messages_graph_)),
2982       convert_stats_graph(std::move(obj->actions_graph_)), convert_stats_graph(std::move(obj->top_hours_graph_)),
2983       convert_stats_graph(std::move(obj->weekdays_graph_)), std::move(top_senders), std::move(top_administrators),
2984       std::move(top_inviters));
2985 }
2986 
convert_broadcast_stats(tl_object_ptr<telegram_api::stats_broadcastStats> obj)2987 tl_object_ptr<td_api::chatStatisticsChannel> ContactsManager::convert_broadcast_stats(
2988     tl_object_ptr<telegram_api::stats_broadcastStats> obj) {
2989   CHECK(obj != nullptr);
2990 
2991   auto recent_message_interactions = transform(std::move(obj->recent_message_interactions_), [](auto &&interaction) {
2992     return make_tl_object<td_api::chatStatisticsMessageInteractionInfo>(
2993         MessageId(ServerMessageId(interaction->msg_id_)).get(), interaction->views_, interaction->forwards_);
2994   });
2995 
2996   return make_tl_object<td_api::chatStatisticsChannel>(
2997       convert_date_range(obj->period_), convert_stats_absolute_value(obj->followers_),
2998       convert_stats_absolute_value(obj->views_per_post_), convert_stats_absolute_value(obj->shares_per_post_),
2999       get_percentage_value(obj->enabled_notifications_->part_, obj->enabled_notifications_->total_),
3000       convert_stats_graph(std::move(obj->growth_graph_)), convert_stats_graph(std::move(obj->followers_graph_)),
3001       convert_stats_graph(std::move(obj->mute_graph_)), convert_stats_graph(std::move(obj->top_hours_graph_)),
3002       convert_stats_graph(std::move(obj->views_by_source_graph_)),
3003       convert_stats_graph(std::move(obj->new_followers_by_source_graph_)),
3004       convert_stats_graph(std::move(obj->languages_graph_)), convert_stats_graph(std::move(obj->interactions_graph_)),
3005       convert_stats_graph(std::move(obj->iv_interactions_graph_)), std::move(recent_message_interactions));
3006 }
3007 
3008 class GetMegagroupStatsQuery final : public Td::ResultHandler {
3009   Promise<td_api::object_ptr<td_api::ChatStatistics>> promise_;
3010   ChannelId channel_id_;
3011 
3012  public:
GetMegagroupStatsQuery(Promise<td_api::object_ptr<td_api::ChatStatistics>> && promise)3013   explicit GetMegagroupStatsQuery(Promise<td_api::object_ptr<td_api::ChatStatistics>> &&promise)
3014       : promise_(std::move(promise)) {
3015   }
3016 
send(ChannelId channel_id,bool is_dark,DcId dc_id)3017   void send(ChannelId channel_id, bool is_dark, DcId dc_id) {
3018     channel_id_ = channel_id;
3019 
3020     auto input_channel = td_->contacts_manager_->get_input_channel(channel_id);
3021     CHECK(input_channel != nullptr);
3022 
3023     int32 flags = 0;
3024     if (is_dark) {
3025       flags |= telegram_api::stats_getMegagroupStats::DARK_MASK;
3026     }
3027     send_query(G()->net_query_creator().create(
3028         telegram_api::stats_getMegagroupStats(flags, false /*ignored*/, std::move(input_channel)), dc_id));
3029   }
3030 
on_result(BufferSlice packet)3031   void on_result(BufferSlice packet) final {
3032     auto result_ptr = fetch_result<telegram_api::stats_getMegagroupStats>(packet);
3033     if (result_ptr.is_error()) {
3034       return on_error(result_ptr.move_as_error());
3035     }
3036 
3037     promise_.set_value(td_->contacts_manager_->convert_megagroup_stats(result_ptr.move_as_ok()));
3038   }
3039 
on_error(Status status)3040   void on_error(Status status) final {
3041     td_->contacts_manager_->on_get_channel_error(channel_id_, status, "GetMegagroupStatsQuery");
3042     promise_.set_error(std::move(status));
3043   }
3044 };
3045 
3046 class GetBroadcastStatsQuery final : public Td::ResultHandler {
3047   Promise<td_api::object_ptr<td_api::ChatStatistics>> promise_;
3048   ChannelId channel_id_;
3049 
3050  public:
GetBroadcastStatsQuery(Promise<td_api::object_ptr<td_api::ChatStatistics>> && promise)3051   explicit GetBroadcastStatsQuery(Promise<td_api::object_ptr<td_api::ChatStatistics>> &&promise)
3052       : promise_(std::move(promise)) {
3053   }
3054 
send(ChannelId channel_id,bool is_dark,DcId dc_id)3055   void send(ChannelId channel_id, bool is_dark, DcId dc_id) {
3056     channel_id_ = channel_id;
3057 
3058     auto input_channel = td_->contacts_manager_->get_input_channel(channel_id);
3059     CHECK(input_channel != nullptr);
3060 
3061     int32 flags = 0;
3062     if (is_dark) {
3063       flags |= telegram_api::stats_getBroadcastStats::DARK_MASK;
3064     }
3065     send_query(G()->net_query_creator().create(
3066         telegram_api::stats_getBroadcastStats(flags, false /*ignored*/, std::move(input_channel)), dc_id));
3067   }
3068 
on_result(BufferSlice packet)3069   void on_result(BufferSlice packet) final {
3070     auto result_ptr = fetch_result<telegram_api::stats_getBroadcastStats>(packet);
3071     if (result_ptr.is_error()) {
3072       return on_error(result_ptr.move_as_error());
3073     }
3074 
3075     auto result = ContactsManager::convert_broadcast_stats(result_ptr.move_as_ok());
3076     for (auto &info : result->recent_message_interactions_) {
3077       td_->messages_manager_->on_update_message_interaction_info({DialogId(channel_id_), MessageId(info->message_id_)},
3078                                                                  info->view_count_, info->forward_count_, false,
3079                                                                  nullptr);
3080     }
3081     promise_.set_value(std::move(result));
3082   }
3083 
on_error(Status status)3084   void on_error(Status status) final {
3085     td_->contacts_manager_->on_get_channel_error(channel_id_, status, "GetBroadcastStatsQuery");
3086     promise_.set_error(std::move(status));
3087   }
3088 };
3089 
convert_message_stats(tl_object_ptr<telegram_api::stats_messageStats> obj)3090 tl_object_ptr<td_api::messageStatistics> ContactsManager::convert_message_stats(
3091     tl_object_ptr<telegram_api::stats_messageStats> obj) {
3092   return make_tl_object<td_api::messageStatistics>(convert_stats_graph(std::move(obj->views_graph_)));
3093 }
3094 
3095 class GetMessageStatsQuery final : public Td::ResultHandler {
3096   Promise<td_api::object_ptr<td_api::messageStatistics>> promise_;
3097   ChannelId channel_id_;
3098 
3099  public:
GetMessageStatsQuery(Promise<td_api::object_ptr<td_api::messageStatistics>> && promise)3100   explicit GetMessageStatsQuery(Promise<td_api::object_ptr<td_api::messageStatistics>> &&promise)
3101       : promise_(std::move(promise)) {
3102   }
3103 
send(ChannelId channel_id,MessageId message_id,bool is_dark,DcId dc_id)3104   void send(ChannelId channel_id, MessageId message_id, bool is_dark, DcId dc_id) {
3105     channel_id_ = channel_id;
3106 
3107     auto input_channel = td_->contacts_manager_->get_input_channel(channel_id);
3108     CHECK(input_channel != nullptr);
3109 
3110     int32 flags = 0;
3111     if (is_dark) {
3112       flags |= telegram_api::stats_getMessageStats::DARK_MASK;
3113     }
3114     send_query(G()->net_query_creator().create(
3115         telegram_api::stats_getMessageStats(flags, false /*ignored*/, std::move(input_channel),
3116                                             message_id.get_server_message_id().get()),
3117         dc_id));
3118   }
3119 
on_result(BufferSlice packet)3120   void on_result(BufferSlice packet) final {
3121     auto result_ptr = fetch_result<telegram_api::stats_getMessageStats>(packet);
3122     if (result_ptr.is_error()) {
3123       return on_error(result_ptr.move_as_error());
3124     }
3125 
3126     promise_.set_value(td_->contacts_manager_->convert_message_stats(result_ptr.move_as_ok()));
3127   }
3128 
on_error(Status status)3129   void on_error(Status status) final {
3130     td_->contacts_manager_->on_get_channel_error(channel_id_, status, "GetMessageStatsQuery");
3131     promise_.set_error(std::move(status));
3132   }
3133 };
3134 
3135 class LoadAsyncGraphQuery final : public Td::ResultHandler {
3136   Promise<td_api::object_ptr<td_api::StatisticalGraph>> promise_;
3137 
3138  public:
LoadAsyncGraphQuery(Promise<td_api::object_ptr<td_api::StatisticalGraph>> && promise)3139   explicit LoadAsyncGraphQuery(Promise<td_api::object_ptr<td_api::StatisticalGraph>> &&promise)
3140       : promise_(std::move(promise)) {
3141   }
3142 
send(const string & token,int64 x,DcId dc_id)3143   void send(const string &token, int64 x, DcId dc_id) {
3144     int32 flags = 0;
3145     if (x != 0) {
3146       flags |= telegram_api::stats_loadAsyncGraph::X_MASK;
3147     }
3148     send_query(G()->net_query_creator().create(telegram_api::stats_loadAsyncGraph(flags, token, x), dc_id));
3149   }
3150 
on_result(BufferSlice packet)3151   void on_result(BufferSlice packet) final {
3152     auto result_ptr = fetch_result<telegram_api::stats_loadAsyncGraph>(packet);
3153     if (result_ptr.is_error()) {
3154       return on_error(result_ptr.move_as_error());
3155     }
3156 
3157     auto result = result_ptr.move_as_ok();
3158     promise_.set_value(ContactsManager::convert_stats_graph(std::move(result)));
3159   }
3160 
on_error(Status status)3161   void on_error(Status status) final {
3162     promise_.set_error(std::move(status));
3163   }
3164 };
3165 
3166 class ContactsManager::UploadProfilePhotoCallback final : public FileManager::UploadCallback {
3167  public:
on_upload_ok(FileId file_id,tl_object_ptr<telegram_api::InputFile> input_file)3168   void on_upload_ok(FileId file_id, tl_object_ptr<telegram_api::InputFile> input_file) final {
3169     send_closure_later(G()->contacts_manager(), &ContactsManager::on_upload_profile_photo, file_id,
3170                        std::move(input_file));
3171   }
on_upload_encrypted_ok(FileId file_id,tl_object_ptr<telegram_api::InputEncryptedFile> input_file)3172   void on_upload_encrypted_ok(FileId file_id, tl_object_ptr<telegram_api::InputEncryptedFile> input_file) final {
3173     UNREACHABLE();
3174   }
on_upload_secure_ok(FileId file_id,tl_object_ptr<telegram_api::InputSecureFile> input_file)3175   void on_upload_secure_ok(FileId file_id, tl_object_ptr<telegram_api::InputSecureFile> input_file) final {
3176     UNREACHABLE();
3177   }
on_upload_error(FileId file_id,Status error)3178   void on_upload_error(FileId file_id, Status error) final {
3179     send_closure_later(G()->contacts_manager(), &ContactsManager::on_upload_profile_photo_error, file_id,
3180                        std::move(error));
3181   }
3182 };
3183 
ContactsManager(Td * td,ActorShared<> parent)3184 ContactsManager::ContactsManager(Td *td, ActorShared<> parent) : td_(td), parent_(std::move(parent)) {
3185   upload_profile_photo_callback_ = std::make_shared<UploadProfilePhotoCallback>();
3186 
3187   my_id_ = load_my_id();
3188 
3189   G()->shared_config().set_option_integer("telegram_service_notifications_chat_id",
3190                                           DialogId(get_service_notifications_user_id()).get());
3191   G()->shared_config().set_option_integer("replies_bot_chat_id", DialogId(get_replies_bot_user_id()).get());
3192   G()->shared_config().set_option_integer("group_anonymous_bot_user_id", get_anonymous_bot_user_id().get());
3193 
3194   if (G()->parameters().use_chat_info_db) {
3195     auto next_contacts_sync_date_string = G()->td_db()->get_binlog_pmc()->get("next_contacts_sync_date");
3196     if (!next_contacts_sync_date_string.empty()) {
3197       next_contacts_sync_date_ = min(to_integer<int32>(next_contacts_sync_date_string), G()->unix_time() + 100000);
3198     }
3199 
3200     auto saved_contact_count_string = G()->td_db()->get_binlog_pmc()->get("saved_contact_count");
3201     if (!saved_contact_count_string.empty()) {
3202       saved_contact_count_ = to_integer<int32>(saved_contact_count_string);
3203     }
3204   } else {
3205     G()->td_db()->get_binlog_pmc()->erase("next_contacts_sync_date");
3206     G()->td_db()->get_binlog_pmc()->erase("saved_contact_count");
3207   }
3208   if (G()->parameters().use_file_db) {
3209     G()->td_db()->get_sqlite_pmc()->erase_by_prefix("us_bot_info", Auto());
3210   }
3211 
3212   was_online_local_ = to_integer<int32>(G()->td_db()->get_binlog_pmc()->get("my_was_online_local"));
3213   was_online_remote_ = to_integer<int32>(G()->td_db()->get_binlog_pmc()->get("my_was_online_remote"));
3214   if (was_online_local_ >= G()->unix_time_cached() && !td_->is_online()) {
3215     was_online_local_ = G()->unix_time_cached() - 1;
3216   }
3217 
3218   location_visibility_expire_date_ =
3219       to_integer<int32>(G()->td_db()->get_binlog_pmc()->get("location_visibility_expire_date"));
3220   if (location_visibility_expire_date_ != 0 && location_visibility_expire_date_ <= G()->unix_time()) {
3221     location_visibility_expire_date_ = 0;
3222     G()->td_db()->get_binlog_pmc()->erase("location_visibility_expire_date");
3223   }
3224   auto pending_location_visibility_expire_date_string =
3225       G()->td_db()->get_binlog_pmc()->get("pending_location_visibility_expire_date");
3226   if (!pending_location_visibility_expire_date_string.empty()) {
3227     pending_location_visibility_expire_date_ = to_integer<int32>(pending_location_visibility_expire_date_string);
3228     try_send_set_location_visibility_query();
3229   }
3230   update_is_location_visible();
3231   LOG(INFO) << "Loaded location_visibility_expire_date = " << location_visibility_expire_date_
3232             << " and pending_location_visibility_expire_date = " << pending_location_visibility_expire_date_;
3233 
3234   user_online_timeout_.set_callback(on_user_online_timeout_callback);
3235   user_online_timeout_.set_callback_data(static_cast<void *>(this));
3236 
3237   channel_unban_timeout_.set_callback(on_channel_unban_timeout_callback);
3238   channel_unban_timeout_.set_callback_data(static_cast<void *>(this));
3239 
3240   user_nearby_timeout_.set_callback(on_user_nearby_timeout_callback);
3241   user_nearby_timeout_.set_callback_data(static_cast<void *>(this));
3242 
3243   slow_mode_delay_timeout_.set_callback(on_slow_mode_delay_timeout_callback);
3244   slow_mode_delay_timeout_.set_callback_data(static_cast<void *>(this));
3245 
3246   invite_link_info_expire_timeout_.set_callback(on_invite_link_info_expire_timeout_callback);
3247   invite_link_info_expire_timeout_.set_callback_data(static_cast<void *>(this));
3248 
3249   channel_participant_cache_timeout_.set_callback(on_channel_participant_cache_timeout_callback);
3250   channel_participant_cache_timeout_.set_callback_data(static_cast<void *>(this));
3251 }
3252 
3253 ContactsManager::~ContactsManager() = default;
3254 
tear_down()3255 void ContactsManager::tear_down() {
3256   parent_.reset();
3257 }
3258 
load_my_id()3259 UserId ContactsManager::load_my_id() {
3260   auto id_string = G()->td_db()->get_binlog_pmc()->get("my_id");
3261   if (!id_string.empty()) {
3262     UserId my_id(to_integer<int64>(id_string));
3263     if (my_id.is_valid()) {
3264       return my_id;
3265     }
3266 
3267     my_id = UserId(to_integer<int64>(Slice(id_string).substr(5)));
3268     if (my_id.is_valid()) {
3269       G()->td_db()->get_binlog_pmc()->set("my_id", to_string(my_id.get()));
3270       return my_id;
3271     }
3272 
3273     LOG(ERROR) << "Wrong my ID = \"" << id_string << "\" stored in database";
3274   }
3275   return UserId();
3276 }
3277 
on_user_online_timeout_callback(void * contacts_manager_ptr,int64 user_id_long)3278 void ContactsManager::on_user_online_timeout_callback(void *contacts_manager_ptr, int64 user_id_long) {
3279   if (G()->close_flag()) {
3280     return;
3281   }
3282 
3283   auto contacts_manager = static_cast<ContactsManager *>(contacts_manager_ptr);
3284   send_closure_later(contacts_manager->actor_id(contacts_manager), &ContactsManager::on_user_online_timeout,
3285                      UserId(user_id_long));
3286 }
3287 
on_user_online_timeout(UserId user_id)3288 void ContactsManager::on_user_online_timeout(UserId user_id) {
3289   if (G()->close_flag()) {
3290     return;
3291   }
3292 
3293   auto u = get_user(user_id);
3294   CHECK(u != nullptr);
3295   CHECK(u->is_update_user_sent);
3296 
3297   LOG(INFO) << "Update " << user_id << " online status to offline";
3298   send_closure(G()->td(), &Td::send_update,
3299                td_api::make_object<td_api::updateUserStatus>(user_id.get(), get_user_status_object(user_id, u)));
3300 
3301   update_user_online_member_count(u);
3302 }
3303 
on_channel_unban_timeout_callback(void * contacts_manager_ptr,int64 channel_id_long)3304 void ContactsManager::on_channel_unban_timeout_callback(void *contacts_manager_ptr, int64 channel_id_long) {
3305   if (G()->close_flag()) {
3306     return;
3307   }
3308 
3309   auto contacts_manager = static_cast<ContactsManager *>(contacts_manager_ptr);
3310   send_closure_later(contacts_manager->actor_id(contacts_manager), &ContactsManager::on_channel_unban_timeout,
3311                      ChannelId(channel_id_long));
3312 }
3313 
on_channel_unban_timeout(ChannelId channel_id)3314 void ContactsManager::on_channel_unban_timeout(ChannelId channel_id) {
3315   if (G()->close_flag()) {
3316     return;
3317   }
3318 
3319   auto c = get_channel(channel_id);
3320   CHECK(c != nullptr);
3321 
3322   auto old_status = c->status;
3323   c->status.update_restrictions();
3324   if (c->status == old_status) {
3325     LOG_IF(ERROR, c->status.is_restricted() || c->status.is_banned())
3326         << "Status of " << channel_id << " wasn't updated: " << c->status;
3327   } else {
3328     c->is_changed = true;
3329   }
3330 
3331   LOG(INFO) << "Update " << channel_id << " status";
3332   c->is_status_changed = true;
3333   invalidate_channel_full(channel_id, !c->is_slow_mode_enabled);
3334   update_channel(c, channel_id);  // always call, because in case of failure we need to reactivate timeout
3335 }
3336 
on_user_nearby_timeout_callback(void * contacts_manager_ptr,int64 user_id_long)3337 void ContactsManager::on_user_nearby_timeout_callback(void *contacts_manager_ptr, int64 user_id_long) {
3338   if (G()->close_flag()) {
3339     return;
3340   }
3341 
3342   auto contacts_manager = static_cast<ContactsManager *>(contacts_manager_ptr);
3343   send_closure_later(contacts_manager->actor_id(contacts_manager), &ContactsManager::on_user_nearby_timeout,
3344                      UserId(user_id_long));
3345 }
3346 
on_user_nearby_timeout(UserId user_id)3347 void ContactsManager::on_user_nearby_timeout(UserId user_id) {
3348   if (G()->close_flag()) {
3349     return;
3350   }
3351 
3352   auto u = get_user(user_id);
3353   CHECK(u != nullptr);
3354 
3355   LOG(INFO) << "Remove " << user_id << " from nearby list";
3356   DialogId dialog_id(user_id);
3357   for (size_t i = 0; i < users_nearby_.size(); i++) {
3358     if (users_nearby_[i].dialog_id == dialog_id) {
3359       users_nearby_.erase(users_nearby_.begin() + i);
3360       send_update_users_nearby();
3361       return;
3362     }
3363   }
3364 }
3365 
on_slow_mode_delay_timeout_callback(void * contacts_manager_ptr,int64 channel_id_long)3366 void ContactsManager::on_slow_mode_delay_timeout_callback(void *contacts_manager_ptr, int64 channel_id_long) {
3367   if (G()->close_flag()) {
3368     return;
3369   }
3370 
3371   auto contacts_manager = static_cast<ContactsManager *>(contacts_manager_ptr);
3372   send_closure_later(contacts_manager->actor_id(contacts_manager), &ContactsManager::on_slow_mode_delay_timeout,
3373                      ChannelId(channel_id_long));
3374 }
3375 
on_slow_mode_delay_timeout(ChannelId channel_id)3376 void ContactsManager::on_slow_mode_delay_timeout(ChannelId channel_id) {
3377   if (G()->close_flag()) {
3378     return;
3379   }
3380 
3381   on_update_channel_slow_mode_next_send_date(channel_id, 0);
3382 }
3383 
on_invite_link_info_expire_timeout_callback(void * contacts_manager_ptr,int64 dialog_id_long)3384 void ContactsManager::on_invite_link_info_expire_timeout_callback(void *contacts_manager_ptr, int64 dialog_id_long) {
3385   if (G()->close_flag()) {
3386     return;
3387   }
3388 
3389   auto contacts_manager = static_cast<ContactsManager *>(contacts_manager_ptr);
3390   send_closure_later(contacts_manager->actor_id(contacts_manager), &ContactsManager::on_invite_link_info_expire_timeout,
3391                      DialogId(dialog_id_long));
3392 }
3393 
on_invite_link_info_expire_timeout(DialogId dialog_id)3394 void ContactsManager::on_invite_link_info_expire_timeout(DialogId dialog_id) {
3395   if (G()->close_flag()) {
3396     return;
3397   }
3398 
3399   auto access_it = dialog_access_by_invite_link_.find(dialog_id);
3400   if (access_it == dialog_access_by_invite_link_.end()) {
3401     return;
3402   }
3403   auto expires_in = access_it->second.accessible_before - G()->unix_time() - 1;
3404   if (expires_in >= 3) {
3405     invite_link_info_expire_timeout_.set_timeout_in(dialog_id.get(), expires_in);
3406     return;
3407   }
3408 
3409   remove_dialog_access_by_invite_link(dialog_id);
3410 }
3411 
on_channel_participant_cache_timeout_callback(void * contacts_manager_ptr,int64 channel_id_long)3412 void ContactsManager::on_channel_participant_cache_timeout_callback(void *contacts_manager_ptr, int64 channel_id_long) {
3413   if (G()->close_flag()) {
3414     return;
3415   }
3416 
3417   auto contacts_manager = static_cast<ContactsManager *>(contacts_manager_ptr);
3418   send_closure_later(contacts_manager->actor_id(contacts_manager),
3419                      &ContactsManager::on_channel_participant_cache_timeout, ChannelId(channel_id_long));
3420 }
3421 
on_channel_participant_cache_timeout(ChannelId channel_id)3422 void ContactsManager::on_channel_participant_cache_timeout(ChannelId channel_id) {
3423   if (G()->close_flag()) {
3424     return;
3425   }
3426 
3427   auto channel_participants_it = channel_participants_.find(channel_id);
3428   if (channel_participants_it == channel_participants_.end()) {
3429     return;
3430   }
3431 
3432   auto &participants = channel_participants_it->second.participants_;
3433   auto min_access_date = G()->unix_time() - CHANNEL_PARTICIPANT_CACHE_TIME;
3434   for (auto it = participants.begin(); it != participants.end();) {
3435     if (it->second.last_access_date_ < min_access_date) {
3436       it = participants.erase(it);
3437     } else {
3438       ++it;
3439     }
3440   }
3441 
3442   if (participants.empty()) {
3443     channel_participants_.erase(channel_participants_it);
3444   } else {
3445     channel_participant_cache_timeout_.set_timeout_in(channel_id.get(), CHANNEL_PARTICIPANT_CACHE_TIME);
3446   }
3447 }
3448 
3449 template <class StorerT>
store(StorerT & storer) const3450 void ContactsManager::User::store(StorerT &storer) const {
3451   using td::store;
3452   bool has_last_name = !last_name.empty();
3453   bool has_username = !username.empty();
3454   bool has_photo = photo.small_file_id.is_valid();
3455   bool has_language_code = !language_code.empty();
3456   bool have_access_hash = access_hash != -1;
3457   bool has_cache_version = cache_version != 0;
3458   bool has_is_contact = true;
3459   bool has_restriction_reasons = !restriction_reasons.empty();
3460   BEGIN_STORE_FLAGS();
3461   STORE_FLAG(is_received);
3462   STORE_FLAG(is_verified);
3463   STORE_FLAG(is_deleted);
3464   STORE_FLAG(is_bot);
3465   STORE_FLAG(can_join_groups);
3466   STORE_FLAG(can_read_all_group_messages);
3467   STORE_FLAG(is_inline_bot);
3468   STORE_FLAG(need_location_bot);
3469   STORE_FLAG(has_last_name);
3470   STORE_FLAG(has_username);
3471   STORE_FLAG(has_photo);
3472   STORE_FLAG(false);  // legacy is_restricted
3473   STORE_FLAG(has_language_code);
3474   STORE_FLAG(have_access_hash);
3475   STORE_FLAG(is_support);
3476   STORE_FLAG(is_min_access_hash);
3477   STORE_FLAG(is_scam);
3478   STORE_FLAG(has_cache_version);
3479   STORE_FLAG(has_is_contact);
3480   STORE_FLAG(is_contact);
3481   STORE_FLAG(is_mutual_contact);
3482   STORE_FLAG(has_restriction_reasons);
3483   STORE_FLAG(need_apply_min_photo);
3484   STORE_FLAG(is_fake);
3485   END_STORE_FLAGS();
3486   store(first_name, storer);
3487   if (has_last_name) {
3488     store(last_name, storer);
3489   }
3490   if (has_username) {
3491     store(username, storer);
3492   }
3493   store(phone_number, storer);
3494   if (have_access_hash) {
3495     store(access_hash, storer);
3496   }
3497   if (has_photo) {
3498     store(photo, storer);
3499   }
3500   store(was_online, storer);
3501   if (has_restriction_reasons) {
3502     store(restriction_reasons, storer);
3503   }
3504   if (is_inline_bot) {
3505     store(inline_query_placeholder, storer);
3506   }
3507   if (is_bot) {
3508     store(bot_info_version, storer);
3509   }
3510   if (has_language_code) {
3511     store(language_code, storer);
3512   }
3513   if (has_cache_version) {
3514     store(cache_version, storer);
3515   }
3516 }
3517 
3518 template <class ParserT>
parse(ParserT & parser)3519 void ContactsManager::User::parse(ParserT &parser) {
3520   using td::parse;
3521   bool has_last_name;
3522   bool has_username;
3523   bool has_photo;
3524   bool legacy_is_restricted;
3525   bool has_language_code;
3526   bool have_access_hash;
3527   bool has_cache_version;
3528   bool has_is_contact;
3529   bool has_restriction_reasons;
3530   BEGIN_PARSE_FLAGS();
3531   PARSE_FLAG(is_received);
3532   PARSE_FLAG(is_verified);
3533   PARSE_FLAG(is_deleted);
3534   PARSE_FLAG(is_bot);
3535   PARSE_FLAG(can_join_groups);
3536   PARSE_FLAG(can_read_all_group_messages);
3537   PARSE_FLAG(is_inline_bot);
3538   PARSE_FLAG(need_location_bot);
3539   PARSE_FLAG(has_last_name);
3540   PARSE_FLAG(has_username);
3541   PARSE_FLAG(has_photo);
3542   PARSE_FLAG(legacy_is_restricted);
3543   PARSE_FLAG(has_language_code);
3544   PARSE_FLAG(have_access_hash);
3545   PARSE_FLAG(is_support);
3546   PARSE_FLAG(is_min_access_hash);
3547   PARSE_FLAG(is_scam);
3548   PARSE_FLAG(has_cache_version);
3549   PARSE_FLAG(has_is_contact);
3550   PARSE_FLAG(is_contact);
3551   PARSE_FLAG(is_mutual_contact);
3552   PARSE_FLAG(has_restriction_reasons);
3553   PARSE_FLAG(need_apply_min_photo);
3554   PARSE_FLAG(is_fake);
3555   END_PARSE_FLAGS();
3556   parse(first_name, parser);
3557   if (has_last_name) {
3558     parse(last_name, parser);
3559   }
3560   if (has_username) {
3561     parse(username, parser);
3562   }
3563   parse(phone_number, parser);
3564   if (parser.version() < static_cast<int32>(Version::FixMinUsers)) {
3565     have_access_hash = is_received;
3566   }
3567   if (have_access_hash) {
3568     parse(access_hash, parser);
3569   } else {
3570     is_min_access_hash = true;
3571   }
3572   if (has_photo) {
3573     parse(photo, parser);
3574   }
3575   if (!has_is_contact) {
3576     // enum class LinkState : uint8 { Unknown, None, KnowsPhoneNumber, Contact };
3577 
3578     uint32 link_state_inbound;
3579     uint32 link_state_outbound;
3580     parse(link_state_inbound, parser);
3581     parse(link_state_outbound, parser);
3582 
3583     is_contact = link_state_outbound == 3;
3584     is_mutual_contact = is_contact && link_state_inbound == 3;
3585   }
3586   parse(was_online, parser);
3587   if (legacy_is_restricted) {
3588     string restriction_reason;
3589     parse(restriction_reason, parser);
3590     restriction_reasons = get_restriction_reasons(restriction_reason);
3591   } else if (has_restriction_reasons) {
3592     parse(restriction_reasons, parser);
3593   }
3594   if (is_inline_bot) {
3595     parse(inline_query_placeholder, parser);
3596   }
3597   if (is_bot) {
3598     parse(bot_info_version, parser);
3599   }
3600   if (has_language_code) {
3601     parse(language_code, parser);
3602   }
3603   if (has_cache_version) {
3604     parse(cache_version, parser);
3605   }
3606 
3607   if (!check_utf8(first_name)) {
3608     LOG(ERROR) << "Have invalid first name \"" << first_name << '"';
3609     first_name.clear();
3610     cache_version = 0;
3611   }
3612   if (!check_utf8(last_name)) {
3613     LOG(ERROR) << "Have invalid last name \"" << last_name << '"';
3614     last_name.clear();
3615     cache_version = 0;
3616   }
3617   if (!check_utf8(username)) {
3618     LOG(ERROR) << "Have invalid username \"" << username << '"';
3619     username.clear();
3620     cache_version = 0;
3621   }
3622 
3623   if (first_name.empty() && last_name.empty()) {
3624     first_name = phone_number;
3625   }
3626   if (!is_contact && is_mutual_contact) {
3627     LOG(ERROR) << "Have invalid flag is_mutual_contact";
3628     is_mutual_contact = false;
3629     cache_version = 0;
3630   }
3631 }
3632 
3633 template <class StorerT>
store(StorerT & storer) const3634 void ContactsManager::UserFull::store(StorerT &storer) const {
3635   using td::store;
3636   bool has_about = !about.empty();
3637   bool has_photo = !photo.is_empty();
3638   bool has_description = !description.empty();
3639   bool has_commands = !commands.empty();
3640   bool has_private_forward_name = !private_forward_name.empty();
3641   BEGIN_STORE_FLAGS();
3642   STORE_FLAG(has_about);
3643   STORE_FLAG(is_blocked);
3644   STORE_FLAG(can_be_called);
3645   STORE_FLAG(has_private_calls);
3646   STORE_FLAG(can_pin_messages);
3647   STORE_FLAG(need_phone_number_privacy_exception);
3648   STORE_FLAG(has_photo);
3649   STORE_FLAG(supports_video_calls);
3650   STORE_FLAG(has_description);
3651   STORE_FLAG(has_commands);
3652   STORE_FLAG(has_private_forward_name);
3653   END_STORE_FLAGS();
3654   if (has_about) {
3655     store(about, storer);
3656   }
3657   store(common_chat_count, storer);
3658   store_time(expires_at, storer);
3659   if (has_photo) {
3660     store(photo, storer);
3661   }
3662   if (has_description) {
3663     store(description, storer);
3664   }
3665   if (has_commands) {
3666     store(commands, storer);
3667   }
3668   if (has_private_forward_name) {
3669     store(private_forward_name, storer);
3670   }
3671 }
3672 
3673 template <class ParserT>
parse(ParserT & parser)3674 void ContactsManager::UserFull::parse(ParserT &parser) {
3675   using td::parse;
3676   bool has_about;
3677   bool has_photo;
3678   bool has_description;
3679   bool has_commands;
3680   bool has_private_forward_name;
3681   BEGIN_PARSE_FLAGS();
3682   PARSE_FLAG(has_about);
3683   PARSE_FLAG(is_blocked);
3684   PARSE_FLAG(can_be_called);
3685   PARSE_FLAG(has_private_calls);
3686   PARSE_FLAG(can_pin_messages);
3687   PARSE_FLAG(need_phone_number_privacy_exception);
3688   PARSE_FLAG(has_photo);
3689   PARSE_FLAG(supports_video_calls);
3690   PARSE_FLAG(has_description);
3691   PARSE_FLAG(has_commands);
3692   PARSE_FLAG(has_private_forward_name);
3693   END_PARSE_FLAGS();
3694   if (has_about) {
3695     parse(about, parser);
3696   }
3697   parse(common_chat_count, parser);
3698   parse_time(expires_at, parser);
3699   if (has_photo) {
3700     parse(photo, parser);
3701   }
3702   if (has_description) {
3703     parse(description, parser);
3704   }
3705   if (has_commands) {
3706     parse(commands, parser);
3707   }
3708   if (has_private_forward_name) {
3709     parse(private_forward_name, parser);
3710   }
3711 }
3712 
3713 template <class StorerT>
store(StorerT & storer) const3714 void ContactsManager::Chat::store(StorerT &storer) const {
3715   using td::store;
3716   bool has_photo = photo.small_file_id.is_valid();
3717   bool use_new_rights = true;
3718   bool has_default_permissions_version = default_permissions_version != -1;
3719   bool has_pinned_message_version = pinned_message_version != -1;
3720   bool has_cache_version = cache_version != 0;
3721   BEGIN_STORE_FLAGS();
3722   STORE_FLAG(false);
3723   STORE_FLAG(false);
3724   STORE_FLAG(false);
3725   STORE_FLAG(false);
3726   STORE_FLAG(false);
3727   STORE_FLAG(false);
3728   STORE_FLAG(is_active);
3729   STORE_FLAG(has_photo);
3730   STORE_FLAG(use_new_rights);
3731   STORE_FLAG(has_default_permissions_version);
3732   STORE_FLAG(has_pinned_message_version);
3733   STORE_FLAG(has_cache_version);
3734   STORE_FLAG(noforwards);
3735   END_STORE_FLAGS();
3736 
3737   store(title, storer);
3738   if (has_photo) {
3739     store(photo, storer);
3740   }
3741   store(participant_count, storer);
3742   store(date, storer);
3743   store(migrated_to_channel_id, storer);
3744   store(version, storer);
3745   store(status, storer);
3746   store(default_permissions, storer);
3747   if (has_default_permissions_version) {
3748     store(default_permissions_version, storer);
3749   }
3750   if (has_pinned_message_version) {
3751     store(pinned_message_version, storer);
3752   }
3753   if (has_cache_version) {
3754     store(cache_version, storer);
3755   }
3756 }
3757 
3758 template <class ParserT>
parse(ParserT & parser)3759 void ContactsManager::Chat::parse(ParserT &parser) {
3760   using td::parse;
3761   bool has_photo;
3762   bool left;
3763   bool kicked;
3764   bool is_creator;
3765   bool is_administrator;
3766   bool everyone_is_administrator;
3767   bool can_edit;
3768   bool use_new_rights;
3769   bool has_default_permissions_version;
3770   bool has_pinned_message_version;
3771   bool has_cache_version;
3772   BEGIN_PARSE_FLAGS();
3773   PARSE_FLAG(left);
3774   PARSE_FLAG(kicked);
3775   PARSE_FLAG(is_creator);
3776   PARSE_FLAG(is_administrator);
3777   PARSE_FLAG(everyone_is_administrator);
3778   PARSE_FLAG(can_edit);
3779   PARSE_FLAG(is_active);
3780   PARSE_FLAG(has_photo);
3781   PARSE_FLAG(use_new_rights);
3782   PARSE_FLAG(has_default_permissions_version);
3783   PARSE_FLAG(has_pinned_message_version);
3784   PARSE_FLAG(has_cache_version);
3785   PARSE_FLAG(noforwards);
3786   END_PARSE_FLAGS();
3787 
3788   parse(title, parser);
3789   if (has_photo) {
3790     parse(photo, parser);
3791   }
3792   parse(participant_count, parser);
3793   parse(date, parser);
3794   parse(migrated_to_channel_id, parser);
3795   parse(version, parser);
3796   if (use_new_rights) {
3797     parse(status, parser);
3798     parse(default_permissions, parser);
3799   } else {
3800     if (can_edit != (is_creator || is_administrator || everyone_is_administrator)) {
3801       LOG(ERROR) << "Have wrong can_edit flag";
3802     }
3803 
3804     if (kicked || !is_active) {
3805       status = DialogParticipantStatus::Banned(0);
3806     } else if (left) {
3807       status = DialogParticipantStatus::Left();
3808     } else if (is_creator) {
3809       status = DialogParticipantStatus::Creator(true, false, string());
3810     } else if (is_administrator && !everyone_is_administrator) {
3811       status = DialogParticipantStatus::GroupAdministrator(false);
3812     } else {
3813       status = DialogParticipantStatus::Member();
3814     }
3815     default_permissions = RestrictedRights(true, true, true, true, true, true, true, true, everyone_is_administrator,
3816                                            everyone_is_administrator, everyone_is_administrator);
3817   }
3818   if (has_default_permissions_version) {
3819     parse(default_permissions_version, parser);
3820   }
3821   if (has_pinned_message_version) {
3822     parse(pinned_message_version, parser);
3823   }
3824   if (has_cache_version) {
3825     parse(cache_version, parser);
3826   }
3827 
3828   if (!check_utf8(title)) {
3829     LOG(ERROR) << "Have invalid title \"" << title << '"';
3830     title.clear();
3831     cache_version = 0;
3832   }
3833 
3834   if (status.is_administrator() && !status.is_creator()) {
3835     status = DialogParticipantStatus::GroupAdministrator(false);
3836   }
3837 }
3838 
3839 template <class StorerT>
store(StorerT & storer) const3840 void ContactsManager::ChatFull::store(StorerT &storer) const {
3841   using td::store;
3842   bool has_description = !description.empty();
3843   bool has_legacy_invite_link = false;
3844   bool has_photo = !photo.is_empty();
3845   bool has_invite_link = invite_link.is_valid();
3846   bool has_bot_commands = !bot_commands.empty();
3847   BEGIN_STORE_FLAGS();
3848   STORE_FLAG(has_description);
3849   STORE_FLAG(has_legacy_invite_link);
3850   STORE_FLAG(can_set_username);
3851   STORE_FLAG(has_photo);
3852   STORE_FLAG(has_invite_link);
3853   STORE_FLAG(has_bot_commands);
3854   END_STORE_FLAGS();
3855   store(version, storer);
3856   store(creator_user_id, storer);
3857   store(participants, storer);
3858   if (has_description) {
3859     store(description, storer);
3860   }
3861   if (has_photo) {
3862     store(photo, storer);
3863   }
3864   if (has_invite_link) {
3865     store(invite_link, storer);
3866   }
3867   if (has_bot_commands) {
3868     store(bot_commands, storer);
3869   }
3870 }
3871 
3872 template <class ParserT>
parse(ParserT & parser)3873 void ContactsManager::ChatFull::parse(ParserT &parser) {
3874   using td::parse;
3875   bool has_description;
3876   bool legacy_has_invite_link;
3877   bool has_photo;
3878   bool has_invite_link;
3879   bool has_bot_commands;
3880   BEGIN_PARSE_FLAGS();
3881   PARSE_FLAG(has_description);
3882   PARSE_FLAG(legacy_has_invite_link);
3883   PARSE_FLAG(can_set_username);
3884   PARSE_FLAG(has_photo);
3885   PARSE_FLAG(has_invite_link);
3886   PARSE_FLAG(has_bot_commands);
3887   END_PARSE_FLAGS();
3888   parse(version, parser);
3889   parse(creator_user_id, parser);
3890   parse(participants, parser);
3891   if (has_description) {
3892     parse(description, parser);
3893   }
3894   if (legacy_has_invite_link) {
3895     string legacy_invite_link;
3896     parse(legacy_invite_link, parser);
3897   }
3898   if (has_photo) {
3899     parse(photo, parser);
3900   }
3901   if (has_invite_link) {
3902     parse(invite_link, parser);
3903   }
3904   if (has_bot_commands) {
3905     parse(bot_commands, parser);
3906   }
3907 }
3908 
3909 template <class StorerT>
store(StorerT & storer) const3910 void ContactsManager::Channel::store(StorerT &storer) const {
3911   using td::store;
3912   bool has_photo = photo.small_file_id.is_valid();
3913   bool has_username = !username.empty();
3914   bool use_new_rights = true;
3915   bool has_participant_count = participant_count != 0;
3916   bool have_default_permissions = true;
3917   bool has_cache_version = cache_version != 0;
3918   bool has_restriction_reasons = !restriction_reasons.empty();
3919   bool legacy_has_active_group_call = false;
3920   BEGIN_STORE_FLAGS();
3921   STORE_FLAG(false);
3922   STORE_FLAG(false);
3923   STORE_FLAG(false);
3924   STORE_FLAG(sign_messages);
3925   STORE_FLAG(false);
3926   STORE_FLAG(false);  // 5
3927   STORE_FLAG(false);
3928   STORE_FLAG(is_megagroup);
3929   STORE_FLAG(is_verified);
3930   STORE_FLAG(has_photo);
3931   STORE_FLAG(has_username);  // 10
3932   STORE_FLAG(false);
3933   STORE_FLAG(use_new_rights);
3934   STORE_FLAG(has_participant_count);
3935   STORE_FLAG(have_default_permissions);
3936   STORE_FLAG(is_scam);  // 15
3937   STORE_FLAG(has_cache_version);
3938   STORE_FLAG(has_linked_channel);
3939   STORE_FLAG(has_location);
3940   STORE_FLAG(is_slow_mode_enabled);
3941   STORE_FLAG(has_restriction_reasons);  // 20
3942   STORE_FLAG(legacy_has_active_group_call);
3943   STORE_FLAG(is_fake);
3944   STORE_FLAG(is_gigagroup);
3945   STORE_FLAG(noforwards);
3946   END_STORE_FLAGS();
3947 
3948   store(status, storer);
3949   store(access_hash, storer);
3950   store(title, storer);
3951   if (has_photo) {
3952     store(photo, storer);
3953   }
3954   if (has_username) {
3955     store(username, storer);
3956   }
3957   store(date, storer);
3958   if (has_restriction_reasons) {
3959     store(restriction_reasons, storer);
3960   }
3961   if (has_participant_count) {
3962     store(participant_count, storer);
3963   }
3964   if (is_megagroup) {
3965     store(default_permissions, storer);
3966   }
3967   if (has_cache_version) {
3968     store(cache_version, storer);
3969   }
3970 }
3971 
3972 template <class ParserT>
parse(ParserT & parser)3973 void ContactsManager::Channel::parse(ParserT &parser) {
3974   using td::parse;
3975   bool has_photo;
3976   bool has_username;
3977   bool legacy_is_restricted;
3978   bool left;
3979   bool kicked;
3980   bool is_creator;
3981   bool can_edit;
3982   bool can_moderate;
3983   bool anyone_can_invite;
3984   bool use_new_rights;
3985   bool has_participant_count;
3986   bool have_default_permissions;
3987   bool has_cache_version;
3988   bool has_restriction_reasons;
3989   bool legacy_has_active_group_call;
3990   BEGIN_PARSE_FLAGS();
3991   PARSE_FLAG(left);
3992   PARSE_FLAG(kicked);
3993   PARSE_FLAG(anyone_can_invite);
3994   PARSE_FLAG(sign_messages);
3995   PARSE_FLAG(is_creator);
3996   PARSE_FLAG(can_edit);
3997   PARSE_FLAG(can_moderate);
3998   PARSE_FLAG(is_megagroup);
3999   PARSE_FLAG(is_verified);
4000   PARSE_FLAG(has_photo);
4001   PARSE_FLAG(has_username);
4002   PARSE_FLAG(legacy_is_restricted);
4003   PARSE_FLAG(use_new_rights);
4004   PARSE_FLAG(has_participant_count);
4005   PARSE_FLAG(have_default_permissions);
4006   PARSE_FLAG(is_scam);
4007   PARSE_FLAG(has_cache_version);
4008   PARSE_FLAG(has_linked_channel);
4009   PARSE_FLAG(has_location);
4010   PARSE_FLAG(is_slow_mode_enabled);
4011   PARSE_FLAG(has_restriction_reasons);
4012   PARSE_FLAG(legacy_has_active_group_call);
4013   PARSE_FLAG(is_fake);
4014   PARSE_FLAG(is_gigagroup);
4015   PARSE_FLAG(noforwards);
4016   END_PARSE_FLAGS();
4017 
4018   if (use_new_rights) {
4019     parse(status, parser);
4020   } else {
4021     if (kicked) {
4022       status = DialogParticipantStatus::Banned(0);
4023     } else if (left) {
4024       status = DialogParticipantStatus::Left();
4025     } else if (is_creator) {
4026       status = DialogParticipantStatus::Creator(true, false, string());
4027     } else if (can_edit || can_moderate) {
4028       status = DialogParticipantStatus::ChannelAdministrator(false, is_megagroup);
4029     } else {
4030       status = DialogParticipantStatus::Member();
4031     }
4032   }
4033   parse(access_hash, parser);
4034   parse(title, parser);
4035   if (has_photo) {
4036     parse(photo, parser);
4037   }
4038   if (has_username) {
4039     parse(username, parser);
4040   }
4041   parse(date, parser);
4042   if (legacy_is_restricted) {
4043     string restriction_reason;
4044     parse(restriction_reason, parser);
4045     restriction_reasons = get_restriction_reasons(restriction_reason);
4046   } else if (has_restriction_reasons) {
4047     parse(restriction_reasons, parser);
4048   }
4049   if (has_participant_count) {
4050     parse(participant_count, parser);
4051   }
4052   if (is_megagroup) {
4053     if (have_default_permissions) {
4054       parse(default_permissions, parser);
4055     } else {
4056       default_permissions =
4057           RestrictedRights(true, true, true, true, true, true, true, true, false, anyone_can_invite, false);
4058     }
4059   }
4060   if (has_cache_version) {
4061     parse(cache_version, parser);
4062   }
4063 
4064   if (!check_utf8(title)) {
4065     LOG(ERROR) << "Have invalid title \"" << title << '"';
4066     title.clear();
4067     cache_version = 0;
4068   }
4069   if (!check_utf8(username)) {
4070     LOG(ERROR) << "Have invalid username \"" << username << '"';
4071     username.clear();
4072     cache_version = 0;
4073   }
4074   if (legacy_has_active_group_call) {
4075     cache_version = 0;
4076   }
4077 }
4078 
4079 template <class StorerT>
store(StorerT & storer) const4080 void ContactsManager::ChannelFull::store(StorerT &storer) const {
4081   using td::store;
4082   bool has_description = !description.empty();
4083   bool has_administrator_count = administrator_count != 0;
4084   bool has_restricted_count = restricted_count != 0;
4085   bool has_banned_count = banned_count != 0;
4086   bool legacy_has_invite_link = false;
4087   bool has_sticker_set = sticker_set_id.is_valid();
4088   bool has_linked_channel_id = linked_channel_id.is_valid();
4089   bool has_migrated_from_max_message_id = migrated_from_max_message_id.is_valid();
4090   bool has_migrated_from_chat_id = migrated_from_chat_id.is_valid();
4091   bool has_location = !location.empty();
4092   bool has_bot_user_ids = !bot_user_ids.empty();
4093   bool is_slow_mode_enabled = slow_mode_delay != 0;
4094   bool is_slow_mode_delay_active = slow_mode_next_send_date != 0;
4095   bool has_stats_dc_id = stats_dc_id.is_exact();
4096   bool has_photo = !photo.is_empty();
4097   bool legacy_has_active_group_call_id = false;
4098   bool has_invite_link = invite_link.is_valid();
4099   bool has_bot_commands = !bot_commands.empty();
4100   BEGIN_STORE_FLAGS();
4101   STORE_FLAG(has_description);
4102   STORE_FLAG(has_administrator_count);
4103   STORE_FLAG(has_restricted_count);
4104   STORE_FLAG(has_banned_count);
4105   STORE_FLAG(legacy_has_invite_link);
4106   STORE_FLAG(has_sticker_set);
4107   STORE_FLAG(has_linked_channel_id);
4108   STORE_FLAG(has_migrated_from_max_message_id);
4109   STORE_FLAG(has_migrated_from_chat_id);
4110   STORE_FLAG(can_get_participants);
4111   STORE_FLAG(can_set_username);
4112   STORE_FLAG(can_set_sticker_set);
4113   STORE_FLAG(false);  // legacy_can_view_statistics
4114   STORE_FLAG(is_all_history_available);
4115   STORE_FLAG(can_set_location);
4116   STORE_FLAG(has_location);
4117   STORE_FLAG(has_bot_user_ids);
4118   STORE_FLAG(is_slow_mode_enabled);
4119   STORE_FLAG(is_slow_mode_delay_active);
4120   STORE_FLAG(has_stats_dc_id);
4121   STORE_FLAG(has_photo);
4122   STORE_FLAG(is_can_view_statistics_inited);
4123   STORE_FLAG(can_view_statistics);
4124   STORE_FLAG(legacy_has_active_group_call_id);
4125   STORE_FLAG(has_invite_link);
4126   STORE_FLAG(has_bot_commands);
4127   END_STORE_FLAGS();
4128   if (has_description) {
4129     store(description, storer);
4130   }
4131   store(participant_count, storer);
4132   if (has_administrator_count) {
4133     store(administrator_count, storer);
4134   }
4135   if (has_restricted_count) {
4136     store(restricted_count, storer);
4137   }
4138   if (has_banned_count) {
4139     store(banned_count, storer);
4140   }
4141   if (has_sticker_set) {
4142     store(sticker_set_id, storer);
4143   }
4144   if (has_linked_channel_id) {
4145     store(linked_channel_id, storer);
4146   }
4147   if (has_location) {
4148     store(location, storer);
4149   }
4150   if (has_bot_user_ids) {
4151     store(bot_user_ids, storer);
4152   }
4153   if (has_migrated_from_max_message_id) {
4154     store(migrated_from_max_message_id, storer);
4155   }
4156   if (has_migrated_from_chat_id) {
4157     store(migrated_from_chat_id, storer);
4158   }
4159   if (is_slow_mode_enabled) {
4160     store(slow_mode_delay, storer);
4161   }
4162   if (is_slow_mode_delay_active) {
4163     store(slow_mode_next_send_date, storer);
4164   }
4165   store_time(expires_at, storer);
4166   if (has_stats_dc_id) {
4167     store(stats_dc_id.get_raw_id(), storer);
4168   }
4169   if (has_photo) {
4170     store(photo, storer);
4171   }
4172   if (has_invite_link) {
4173     store(invite_link, storer);
4174   }
4175   if (has_bot_commands) {
4176     store(bot_commands, storer);
4177   }
4178 }
4179 
4180 template <class ParserT>
parse(ParserT & parser)4181 void ContactsManager::ChannelFull::parse(ParserT &parser) {
4182   using td::parse;
4183   bool has_description;
4184   bool has_administrator_count;
4185   bool has_restricted_count;
4186   bool has_banned_count;
4187   bool legacy_has_invite_link;
4188   bool has_sticker_set;
4189   bool has_linked_channel_id;
4190   bool has_migrated_from_max_message_id;
4191   bool has_migrated_from_chat_id;
4192   bool legacy_can_view_statistics;
4193   bool has_location;
4194   bool has_bot_user_ids;
4195   bool is_slow_mode_enabled;
4196   bool is_slow_mode_delay_active;
4197   bool has_stats_dc_id;
4198   bool has_photo;
4199   bool legacy_has_active_group_call_id;
4200   bool has_invite_link;
4201   bool has_bot_commands;
4202   BEGIN_PARSE_FLAGS();
4203   PARSE_FLAG(has_description);
4204   PARSE_FLAG(has_administrator_count);
4205   PARSE_FLAG(has_restricted_count);
4206   PARSE_FLAG(has_banned_count);
4207   PARSE_FLAG(legacy_has_invite_link);
4208   PARSE_FLAG(has_sticker_set);
4209   PARSE_FLAG(has_linked_channel_id);
4210   PARSE_FLAG(has_migrated_from_max_message_id);
4211   PARSE_FLAG(has_migrated_from_chat_id);
4212   PARSE_FLAG(can_get_participants);
4213   PARSE_FLAG(can_set_username);
4214   PARSE_FLAG(can_set_sticker_set);
4215   PARSE_FLAG(legacy_can_view_statistics);
4216   PARSE_FLAG(is_all_history_available);
4217   PARSE_FLAG(can_set_location);
4218   PARSE_FLAG(has_location);
4219   PARSE_FLAG(has_bot_user_ids);
4220   PARSE_FLAG(is_slow_mode_enabled);
4221   PARSE_FLAG(is_slow_mode_delay_active);
4222   PARSE_FLAG(has_stats_dc_id);
4223   PARSE_FLAG(has_photo);
4224   PARSE_FLAG(is_can_view_statistics_inited);
4225   PARSE_FLAG(can_view_statistics);
4226   PARSE_FLAG(legacy_has_active_group_call_id);
4227   PARSE_FLAG(has_invite_link);
4228   PARSE_FLAG(has_bot_commands);
4229   END_PARSE_FLAGS();
4230   if (has_description) {
4231     parse(description, parser);
4232   }
4233   parse(participant_count, parser);
4234   if (has_administrator_count) {
4235     parse(administrator_count, parser);
4236   }
4237   if (has_restricted_count) {
4238     parse(restricted_count, parser);
4239   }
4240   if (has_banned_count) {
4241     parse(banned_count, parser);
4242   }
4243   if (legacy_has_invite_link) {
4244     string legacy_invite_link;
4245     parse(legacy_invite_link, parser);
4246   }
4247   if (has_sticker_set) {
4248     parse(sticker_set_id, parser);
4249   }
4250   if (has_linked_channel_id) {
4251     parse(linked_channel_id, parser);
4252   }
4253   if (has_location) {
4254     parse(location, parser);
4255   }
4256   if (has_bot_user_ids) {
4257     parse(bot_user_ids, parser);
4258   }
4259   if (has_migrated_from_max_message_id) {
4260     parse(migrated_from_max_message_id, parser);
4261   }
4262   if (has_migrated_from_chat_id) {
4263     parse(migrated_from_chat_id, parser);
4264   }
4265   if (is_slow_mode_enabled) {
4266     parse(slow_mode_delay, parser);
4267   }
4268   if (is_slow_mode_delay_active) {
4269     parse(slow_mode_next_send_date, parser);
4270   }
4271   parse_time(expires_at, parser);
4272   if (has_stats_dc_id) {
4273     stats_dc_id = DcId::create(parser.fetch_int());
4274   }
4275   if (has_photo) {
4276     parse(photo, parser);
4277   }
4278   if (legacy_has_active_group_call_id) {
4279     InputGroupCallId input_group_call_id;
4280     parse(input_group_call_id, parser);
4281   }
4282   if (has_invite_link) {
4283     parse(invite_link, parser);
4284   }
4285   if (has_bot_commands) {
4286     parse(bot_commands, parser);
4287   }
4288 
4289   if (legacy_can_view_statistics) {
4290     LOG(DEBUG) << "Ignore legacy can view statistics flag";
4291   }
4292   if (!is_can_view_statistics_inited) {
4293     can_view_statistics = stats_dc_id.is_exact();
4294   }
4295 }
4296 
4297 template <class StorerT>
store(StorerT & storer) const4298 void ContactsManager::SecretChat::store(StorerT &storer) const {
4299   using td::store;
4300   bool has_layer = layer > static_cast<int32>(SecretChatLayer::Default);
4301   bool has_initial_folder_id = initial_folder_id != FolderId();
4302   BEGIN_STORE_FLAGS();
4303   STORE_FLAG(is_outbound);
4304   STORE_FLAG(has_layer);
4305   STORE_FLAG(has_initial_folder_id);
4306   END_STORE_FLAGS();
4307 
4308   store(access_hash, storer);
4309   store(user_id, storer);
4310   store(state, storer);
4311   store(ttl, storer);
4312   store(date, storer);
4313   store(key_hash, storer);
4314   if (has_layer) {
4315     store(layer, storer);
4316   }
4317   if (has_initial_folder_id) {
4318     store(initial_folder_id, storer);
4319   }
4320 }
4321 
4322 template <class ParserT>
parse(ParserT & parser)4323 void ContactsManager::SecretChat::parse(ParserT &parser) {
4324   using td::parse;
4325   bool has_layer;
4326   bool has_initial_folder_id;
4327   BEGIN_PARSE_FLAGS();
4328   PARSE_FLAG(is_outbound);
4329   PARSE_FLAG(has_layer);
4330   PARSE_FLAG(has_initial_folder_id);
4331   END_PARSE_FLAGS();
4332 
4333   if (parser.version() >= static_cast<int32>(Version::AddAccessHashToSecretChat)) {
4334     parse(access_hash, parser);
4335   }
4336   parse(user_id, parser);
4337   parse(state, parser);
4338   parse(ttl, parser);
4339   parse(date, parser);
4340   if (parser.version() >= static_cast<int32>(Version::AddKeyHashToSecretChat)) {
4341     parse(key_hash, parser);
4342   }
4343   if (has_layer) {
4344     parse(layer, parser);
4345   } else {
4346     layer = static_cast<int32>(SecretChatLayer::Default);
4347   }
4348   if (has_initial_folder_id) {
4349     parse(initial_folder_id, parser);
4350   }
4351 }
4352 
get_input_user(UserId user_id) const4353 tl_object_ptr<telegram_api::InputUser> ContactsManager::get_input_user(UserId user_id) const {
4354   if (user_id == get_my_id()) {
4355     return make_tl_object<telegram_api::inputUserSelf>();
4356   }
4357 
4358   const User *u = get_user(user_id);
4359   if (u == nullptr || u->access_hash == -1 || u->is_min_access_hash) {
4360     if (td_->auth_manager_->is_bot() && user_id.is_valid()) {
4361       return make_tl_object<telegram_api::inputUser>(user_id.get(), 0);
4362     }
4363     return nullptr;
4364   }
4365 
4366   return make_tl_object<telegram_api::inputUser>(user_id.get(), u->access_hash);
4367 }
4368 
have_input_user(UserId user_id) const4369 bool ContactsManager::have_input_user(UserId user_id) const {
4370   if (user_id == get_my_id()) {
4371     return true;
4372   }
4373 
4374   const User *u = get_user(user_id);
4375   if (u == nullptr || u->access_hash == -1 || u->is_min_access_hash) {
4376     if (td_->auth_manager_->is_bot() && user_id.is_valid()) {
4377       return true;
4378     }
4379     return false;
4380   }
4381 
4382   return true;
4383 }
4384 
get_input_channel(ChannelId channel_id) const4385 tl_object_ptr<telegram_api::InputChannel> ContactsManager::get_input_channel(ChannelId channel_id) const {
4386   const Channel *c = get_channel(channel_id);
4387   if (c == nullptr) {
4388     if (td_->auth_manager_->is_bot() && channel_id.is_valid()) {
4389       return make_tl_object<telegram_api::inputChannel>(channel_id.get(), 0);
4390     }
4391     return nullptr;
4392   }
4393 
4394   return make_tl_object<telegram_api::inputChannel>(channel_id.get(), c->access_hash);
4395 }
4396 
have_input_peer_user(UserId user_id,AccessRights access_rights) const4397 bool ContactsManager::have_input_peer_user(UserId user_id, AccessRights access_rights) const {
4398   if (user_id == get_my_id()) {
4399     return true;
4400   }
4401   return have_input_peer_user(get_user(user_id), access_rights);
4402 }
4403 
have_input_peer_user(const User * u,AccessRights access_rights)4404 bool ContactsManager::have_input_peer_user(const User *u, AccessRights access_rights) {
4405   if (u == nullptr) {
4406     return false;
4407   }
4408   if (u->access_hash == -1 || u->is_min_access_hash) {
4409     return false;
4410   }
4411   if (access_rights == AccessRights::Know) {
4412     return true;
4413   }
4414   if (access_rights == AccessRights::Read) {
4415     return true;
4416   }
4417   if (u->is_deleted) {
4418     return false;
4419   }
4420   return true;
4421 }
4422 
get_input_peer_user(UserId user_id,AccessRights access_rights) const4423 tl_object_ptr<telegram_api::InputPeer> ContactsManager::get_input_peer_user(UserId user_id,
4424                                                                             AccessRights access_rights) const {
4425   if (user_id == get_my_id()) {
4426     return make_tl_object<telegram_api::inputPeerSelf>();
4427   }
4428   const User *u = get_user(user_id);
4429   if (!have_input_peer_user(u, access_rights)) {
4430     if ((u == nullptr || u->access_hash == -1 || u->is_min_access_hash) && td_->auth_manager_->is_bot() &&
4431         user_id.is_valid()) {
4432       return make_tl_object<telegram_api::inputPeerUser>(user_id.get(), 0);
4433     }
4434     return nullptr;
4435   }
4436 
4437   return make_tl_object<telegram_api::inputPeerUser>(user_id.get(), u->access_hash);
4438 }
4439 
have_input_peer_chat(ChatId chat_id,AccessRights access_rights) const4440 bool ContactsManager::have_input_peer_chat(ChatId chat_id, AccessRights access_rights) const {
4441   return have_input_peer_chat(get_chat(chat_id), access_rights);
4442 }
4443 
have_input_peer_chat(const Chat * c,AccessRights access_rights)4444 bool ContactsManager::have_input_peer_chat(const Chat *c, AccessRights access_rights) {
4445   if (c == nullptr) {
4446     return false;
4447   }
4448   if (access_rights == AccessRights::Know) {
4449     return true;
4450   }
4451   if (access_rights == AccessRights::Read) {
4452     return true;
4453   }
4454   if (c->status.is_left()) {
4455     return false;
4456   }
4457   if (access_rights == AccessRights::Write && !c->is_active) {
4458     return false;
4459   }
4460   return true;
4461 }
4462 
get_input_peer_chat(ChatId chat_id,AccessRights access_rights) const4463 tl_object_ptr<telegram_api::InputPeer> ContactsManager::get_input_peer_chat(ChatId chat_id,
4464                                                                             AccessRights access_rights) const {
4465   auto c = get_chat(chat_id);
4466   if (!have_input_peer_chat(c, access_rights)) {
4467     return nullptr;
4468   }
4469 
4470   return make_tl_object<telegram_api::inputPeerChat>(chat_id.get());
4471 }
4472 
have_input_peer_channel(ChannelId channel_id,AccessRights access_rights) const4473 bool ContactsManager::have_input_peer_channel(ChannelId channel_id, AccessRights access_rights) const {
4474   const Channel *c = get_channel(channel_id);
4475   return have_input_peer_channel(c, channel_id, access_rights);
4476 }
4477 
get_input_peer_channel(ChannelId channel_id,AccessRights access_rights) const4478 tl_object_ptr<telegram_api::InputPeer> ContactsManager::get_input_peer_channel(ChannelId channel_id,
4479                                                                                AccessRights access_rights) const {
4480   const Channel *c = get_channel(channel_id);
4481   if (!have_input_peer_channel(c, channel_id, access_rights)) {
4482     if (c == nullptr && td_->auth_manager_->is_bot() && channel_id.is_valid()) {
4483       return make_tl_object<telegram_api::inputPeerChannel>(channel_id.get(), 0);
4484     }
4485     return nullptr;
4486   }
4487 
4488   return make_tl_object<telegram_api::inputPeerChannel>(channel_id.get(), c->access_hash);
4489 }
4490 
have_input_peer_channel(const Channel * c,ChannelId channel_id,AccessRights access_rights,bool from_linked) const4491 bool ContactsManager::have_input_peer_channel(const Channel *c, ChannelId channel_id, AccessRights access_rights,
4492                                               bool from_linked) const {
4493   if (c == nullptr) {
4494     return false;
4495   }
4496   if (access_rights == AccessRights::Know) {
4497     return true;
4498   }
4499   if (c->status.is_administrator()) {
4500     return true;
4501   }
4502   if (c->status.is_banned()) {
4503     return false;
4504   }
4505   if (c->status.is_member()) {
4506     return true;
4507   }
4508 
4509   bool is_public = is_channel_public(c);
4510   if (access_rights == AccessRights::Read) {
4511     if (is_public) {
4512       return true;
4513     }
4514     if (!from_linked && c->has_linked_channel) {
4515       auto linked_channel_id = get_linked_channel_id(channel_id);
4516       if (linked_channel_id.is_valid() && have_channel(linked_channel_id)) {
4517         if (have_input_peer_channel(get_channel(linked_channel_id), linked_channel_id, access_rights, true)) {
4518           return true;
4519         }
4520       } else {
4521         return true;
4522       }
4523     }
4524     if (!from_linked && dialog_access_by_invite_link_.count(DialogId(channel_id))) {
4525       return true;
4526     }
4527   } else {
4528     if (!from_linked && c->is_megagroup && !td_->auth_manager_->is_bot() && c->has_linked_channel) {
4529       auto linked_channel_id = get_linked_channel_id(channel_id);
4530       if (linked_channel_id.is_valid() && (is_public || have_channel(linked_channel_id))) {
4531         return is_public ||
4532                have_input_peer_channel(get_channel(linked_channel_id), linked_channel_id, AccessRights::Read, true);
4533       } else {
4534         return true;
4535       }
4536     }
4537   }
4538   return false;
4539 }
4540 
have_input_encrypted_peer(SecretChatId secret_chat_id,AccessRights access_rights) const4541 bool ContactsManager::have_input_encrypted_peer(SecretChatId secret_chat_id, AccessRights access_rights) const {
4542   return have_input_encrypted_peer(get_secret_chat(secret_chat_id), access_rights);
4543 }
4544 
have_input_encrypted_peer(const SecretChat * secret_chat,AccessRights access_rights)4545 bool ContactsManager::have_input_encrypted_peer(const SecretChat *secret_chat, AccessRights access_rights) {
4546   if (secret_chat == nullptr) {
4547     return false;
4548   }
4549   if (access_rights == AccessRights::Know) {
4550     return true;
4551   }
4552   if (access_rights == AccessRights::Read) {
4553     return true;
4554   }
4555   return secret_chat->state == SecretChatState::Active;
4556 }
4557 
get_input_encrypted_chat(SecretChatId secret_chat_id,AccessRights access_rights) const4558 tl_object_ptr<telegram_api::inputEncryptedChat> ContactsManager::get_input_encrypted_chat(
4559     SecretChatId secret_chat_id, AccessRights access_rights) const {
4560   auto sc = get_secret_chat(secret_chat_id);
4561   if (!have_input_encrypted_peer(sc, access_rights)) {
4562     return nullptr;
4563   }
4564 
4565   return make_tl_object<telegram_api::inputEncryptedChat>(secret_chat_id.get(), sc->access_hash);
4566 }
4567 
get_user_dialog_photo(UserId user_id)4568 const DialogPhoto *ContactsManager::get_user_dialog_photo(UserId user_id) {
4569   auto u = get_user(user_id);
4570   if (u == nullptr) {
4571     return nullptr;
4572   }
4573 
4574   if (!u->is_photo_inited) {
4575     auto it = pending_user_photos_.find(user_id);
4576     if (it != pending_user_photos_.end()) {
4577       do_update_user_photo(u, user_id, std::move(it->second), "get_user_dialog_photo");
4578       pending_user_photos_.erase(it);
4579       update_user(u, user_id);
4580     }
4581   }
4582   return &u->photo;
4583 }
4584 
get_chat_dialog_photo(ChatId chat_id) const4585 const DialogPhoto *ContactsManager::get_chat_dialog_photo(ChatId chat_id) const {
4586   auto c = get_chat(chat_id);
4587   if (c == nullptr) {
4588     return nullptr;
4589   }
4590   return &c->photo;
4591 }
4592 
get_channel_dialog_photo(ChannelId channel_id) const4593 const DialogPhoto *ContactsManager::get_channel_dialog_photo(ChannelId channel_id) const {
4594   auto c = get_channel(channel_id);
4595   if (c == nullptr) {
4596     return nullptr;
4597   }
4598   return &c->photo;
4599 }
4600 
get_secret_chat_dialog_photo(SecretChatId secret_chat_id)4601 const DialogPhoto *ContactsManager::get_secret_chat_dialog_photo(SecretChatId secret_chat_id) {
4602   auto c = get_secret_chat(secret_chat_id);
4603   if (c == nullptr) {
4604     return nullptr;
4605   }
4606   return get_user_dialog_photo(c->user_id);
4607 }
4608 
get_user_title(UserId user_id) const4609 string ContactsManager::get_user_title(UserId user_id) const {
4610   auto u = get_user(user_id);
4611   if (u == nullptr) {
4612     return string();
4613   }
4614   if (u->last_name.empty()) {
4615     return u->first_name;
4616   }
4617   if (u->first_name.empty()) {
4618     return u->last_name;
4619   }
4620   return PSTRING() << u->first_name << ' ' << u->last_name;
4621 }
4622 
get_chat_title(ChatId chat_id) const4623 string ContactsManager::get_chat_title(ChatId chat_id) const {
4624   auto c = get_chat(chat_id);
4625   if (c == nullptr) {
4626     return string();
4627   }
4628   return c->title;
4629 }
4630 
get_channel_title(ChannelId channel_id) const4631 string ContactsManager::get_channel_title(ChannelId channel_id) const {
4632   auto c = get_channel(channel_id);
4633   if (c == nullptr) {
4634     return string();
4635   }
4636   return c->title;
4637 }
4638 
get_secret_chat_title(SecretChatId secret_chat_id) const4639 string ContactsManager::get_secret_chat_title(SecretChatId secret_chat_id) const {
4640   auto c = get_secret_chat(secret_chat_id);
4641   if (c == nullptr) {
4642     return string();
4643   }
4644   return get_user_title(c->user_id);
4645 }
4646 
get_user_default_permissions(UserId user_id) const4647 RestrictedRights ContactsManager::get_user_default_permissions(UserId user_id) const {
4648   auto u = get_user(user_id);
4649   if (u == nullptr || user_id == get_replies_bot_user_id()) {
4650     return RestrictedRights(false, false, false, false, false, false, false, false, false, false, u != nullptr);
4651   }
4652   return RestrictedRights(true, true, true, true, true, true, true, true, false, false, true);
4653 }
4654 
get_chat_default_permissions(ChatId chat_id) const4655 RestrictedRights ContactsManager::get_chat_default_permissions(ChatId chat_id) const {
4656   auto c = get_chat(chat_id);
4657   if (c == nullptr) {
4658     return RestrictedRights(false, false, false, false, false, false, false, false, false, false, false);
4659   }
4660   return c->default_permissions;
4661 }
4662 
get_channel_default_permissions(ChannelId channel_id) const4663 RestrictedRights ContactsManager::get_channel_default_permissions(ChannelId channel_id) const {
4664   auto c = get_channel(channel_id);
4665   if (c == nullptr) {
4666     return RestrictedRights(false, false, false, false, false, false, false, false, false, false, false);
4667   }
4668   return c->default_permissions;
4669 }
4670 
get_secret_chat_default_permissions(SecretChatId secret_chat_id) const4671 RestrictedRights ContactsManager::get_secret_chat_default_permissions(SecretChatId secret_chat_id) const {
4672   auto c = get_secret_chat(secret_chat_id);
4673   if (c == nullptr) {
4674     return RestrictedRights(false, false, false, false, false, false, false, false, false, false, false);
4675   }
4676   return RestrictedRights(true, true, true, true, true, true, true, true, false, false, false);
4677 }
4678 
get_chat_has_protected_content(ChatId chat_id) const4679 bool ContactsManager::get_chat_has_protected_content(ChatId chat_id) const {
4680   auto c = get_chat(chat_id);
4681   if (c == nullptr) {
4682     return false;
4683   }
4684   return c->noforwards;
4685 }
4686 
get_channel_has_protected_content(ChannelId channel_id) const4687 bool ContactsManager::get_channel_has_protected_content(ChannelId channel_id) const {
4688   auto c = get_channel(channel_id);
4689   if (c == nullptr) {
4690     return false;
4691   }
4692   return c->noforwards;
4693 }
4694 
get_user_private_forward_name(UserId user_id)4695 string ContactsManager::get_user_private_forward_name(UserId user_id) {
4696   auto user_full = get_user_full_force(user_id);
4697   if (user_full != nullptr) {
4698     return user_full->private_forward_name;
4699   }
4700   return string();
4701 }
4702 
get_dialog_about(DialogId dialog_id)4703 string ContactsManager::get_dialog_about(DialogId dialog_id) {
4704   switch (dialog_id.get_type()) {
4705     case DialogType::User: {
4706       auto user_full = get_user_full_force(dialog_id.get_user_id());
4707       if (user_full != nullptr) {
4708         return user_full->about;
4709       }
4710       break;
4711     }
4712     case DialogType::Chat: {
4713       auto chat_full = get_chat_full_force(dialog_id.get_chat_id(), "get_dialog_about");
4714       if (chat_full != nullptr) {
4715         return chat_full->description;
4716       }
4717       break;
4718     }
4719     case DialogType::Channel: {
4720       auto channel_full = get_channel_full_force(dialog_id.get_channel_id(), false, "get_dialog_about");
4721       if (channel_full != nullptr) {
4722         return channel_full->description;
4723       }
4724       break;
4725     }
4726     case DialogType::SecretChat: {
4727       auto user_full = get_user_full_force(get_secret_chat_user_id(dialog_id.get_secret_chat_id()));
4728       if (user_full != nullptr) {
4729         return user_full->about;
4730       }
4731       break;
4732     }
4733     case DialogType::None:
4734     default:
4735       UNREACHABLE();
4736   }
4737   return string();
4738 }
4739 
get_secret_chat_date(SecretChatId secret_chat_id) const4740 int32 ContactsManager::get_secret_chat_date(SecretChatId secret_chat_id) const {
4741   auto c = get_secret_chat(secret_chat_id);
4742   if (c == nullptr) {
4743     return 0;
4744   }
4745   return c->date;
4746 }
4747 
get_secret_chat_ttl(SecretChatId secret_chat_id) const4748 int32 ContactsManager::get_secret_chat_ttl(SecretChatId secret_chat_id) const {
4749   auto c = get_secret_chat(secret_chat_id);
4750   if (c == nullptr) {
4751     return 0;
4752   }
4753   return c->ttl;
4754 }
4755 
get_user_username(UserId user_id) const4756 string ContactsManager::get_user_username(UserId user_id) const {
4757   if (!user_id.is_valid()) {
4758     return string();
4759   }
4760 
4761   auto u = get_user(user_id);
4762   if (u == nullptr) {
4763     return string();
4764   }
4765   return u->username;
4766 }
4767 
get_secret_chat_username(SecretChatId secret_chat_id) const4768 string ContactsManager::get_secret_chat_username(SecretChatId secret_chat_id) const {
4769   auto c = get_secret_chat(secret_chat_id);
4770   if (c == nullptr) {
4771     return string();
4772   }
4773   return get_user_username(c->user_id);
4774 }
4775 
get_channel_username(ChannelId channel_id) const4776 string ContactsManager::get_channel_username(ChannelId channel_id) const {
4777   auto c = get_channel(channel_id);
4778   if (c == nullptr) {
4779     return string();
4780   }
4781   return c->username;
4782 }
4783 
get_secret_chat_user_id(SecretChatId secret_chat_id) const4784 UserId ContactsManager::get_secret_chat_user_id(SecretChatId secret_chat_id) const {
4785   auto c = get_secret_chat(secret_chat_id);
4786   if (c == nullptr) {
4787     return UserId();
4788   }
4789   return c->user_id;
4790 }
4791 
get_secret_chat_is_outbound(SecretChatId secret_chat_id) const4792 bool ContactsManager::get_secret_chat_is_outbound(SecretChatId secret_chat_id) const {
4793   auto c = get_secret_chat(secret_chat_id);
4794   if (c == nullptr) {
4795     return false;
4796   }
4797   return c->is_outbound;
4798 }
4799 
get_secret_chat_state(SecretChatId secret_chat_id) const4800 SecretChatState ContactsManager::get_secret_chat_state(SecretChatId secret_chat_id) const {
4801   auto c = get_secret_chat(secret_chat_id);
4802   if (c == nullptr) {
4803     return SecretChatState::Unknown;
4804   }
4805   return c->state;
4806 }
4807 
get_secret_chat_layer(SecretChatId secret_chat_id) const4808 int32 ContactsManager::get_secret_chat_layer(SecretChatId secret_chat_id) const {
4809   auto c = get_secret_chat(secret_chat_id);
4810   if (c == nullptr) {
4811     return 0;
4812   }
4813   return c->layer;
4814 }
4815 
get_secret_chat_initial_folder_id(SecretChatId secret_chat_id) const4816 FolderId ContactsManager::get_secret_chat_initial_folder_id(SecretChatId secret_chat_id) const {
4817   auto c = get_secret_chat(secret_chat_id);
4818   if (c == nullptr) {
4819     return FolderId::main();
4820   }
4821   return c->initial_folder_id;
4822 }
4823 
get_my_id() const4824 UserId ContactsManager::get_my_id() const {
4825   LOG_IF(ERROR, !my_id_.is_valid()) << "Wrong or unknown my ID returned";
4826   return my_id_;
4827 }
4828 
set_my_id(UserId my_id)4829 void ContactsManager::set_my_id(UserId my_id) {
4830   UserId my_old_id = my_id_;
4831   if (my_old_id.is_valid() && my_old_id != my_id) {
4832     LOG(ERROR) << "Already know that me is " << my_old_id << " but received userSelf with " << my_id;
4833   }
4834   if (!my_id.is_valid()) {
4835     LOG(ERROR) << "Receive invalid my ID " << my_id;
4836     return;
4837   }
4838   if (my_old_id != my_id) {
4839     my_id_ = my_id;
4840     G()->td_db()->get_binlog_pmc()->set("my_id", to_string(my_id.get()));
4841     G()->shared_config().set_option_integer("my_id", my_id_.get());
4842     G()->td_db()->get_binlog_pmc()->force_sync(Promise<Unit>());
4843   }
4844 }
4845 
set_my_online_status(bool is_online,bool send_update,bool is_local)4846 void ContactsManager::set_my_online_status(bool is_online, bool send_update, bool is_local) {
4847   if (td_->auth_manager_->is_bot()) {
4848     return;  // just in case
4849   }
4850 
4851   auto my_id = get_my_id();
4852   User *u = get_user_force(my_id);
4853   if (u != nullptr) {
4854     int32 new_online;
4855     int32 now = G()->unix_time();
4856     if (is_online) {
4857       new_online = now + 300;
4858     } else {
4859       new_online = now - 1;
4860     }
4861 
4862     if (is_local) {
4863       LOG(INFO) << "Update my local online from " << my_was_online_local_ << " to " << new_online;
4864       if (!is_online) {
4865         new_online = min(new_online, u->was_online);
4866       }
4867       if (new_online != my_was_online_local_) {
4868         my_was_online_local_ = new_online;
4869         u->is_status_changed = true;
4870         u->is_online_status_changed = true;
4871       }
4872     } else {
4873       if (my_was_online_local_ != 0 || new_online != u->was_online) {
4874         LOG(INFO) << "Update my online from " << u->was_online << " to " << new_online;
4875         my_was_online_local_ = 0;
4876         u->was_online = new_online;
4877         u->is_status_changed = true;
4878         u->is_online_status_changed = true;
4879       }
4880     }
4881 
4882     if (was_online_local_ != new_online) {
4883       was_online_local_ = new_online;
4884       VLOG(notifications) << "Set was_online_local to " << was_online_local_;
4885       G()->td_db()->get_binlog_pmc()->set("my_was_online_local", to_string(was_online_local_));
4886     }
4887 
4888     if (send_update) {
4889       update_user(u, my_id);
4890     }
4891   }
4892 }
4893 
get_my_online_status() const4894 ContactsManager::MyOnlineStatusInfo ContactsManager::get_my_online_status() const {
4895   MyOnlineStatusInfo status_info;
4896   status_info.is_online_local = td_->is_online();
4897   status_info.is_online_remote = was_online_remote_ > G()->unix_time_cached();
4898   status_info.was_online_local = was_online_local_;
4899   status_info.was_online_remote = was_online_remote_;
4900 
4901   return status_info;
4902 }
4903 
get_service_notifications_user_id()4904 UserId ContactsManager::get_service_notifications_user_id() {
4905   return UserId(static_cast<int64>(777000));
4906 }
4907 
add_service_notifications_user()4908 UserId ContactsManager::add_service_notifications_user() {
4909   auto user_id = get_service_notifications_user_id();
4910   if (!have_user_force(user_id)) {
4911     LOG(FATAL) << "Failed to load service notification user";
4912   }
4913   return user_id;
4914 }
4915 
get_replies_bot_user_id()4916 UserId ContactsManager::get_replies_bot_user_id() {
4917   return UserId(static_cast<int64>(G()->is_test_dc() ? 708513 : 1271266957));
4918 }
4919 
get_anonymous_bot_user_id()4920 UserId ContactsManager::get_anonymous_bot_user_id() {
4921   return UserId(static_cast<int64>(G()->is_test_dc() ? 552888 : 1087968824));
4922 }
4923 
add_anonymous_bot_user()4924 UserId ContactsManager::add_anonymous_bot_user() {
4925   auto user_id = get_anonymous_bot_user_id();
4926   if (!have_user_force(user_id)) {
4927     LOG(FATAL) << "Failed to load anonymous bot user";
4928   }
4929   return user_id;
4930 }
4931 
check_dialog_username(DialogId dialog_id,const string & username,Promise<CheckDialogUsernameResult> && promise)4932 void ContactsManager::check_dialog_username(DialogId dialog_id, const string &username,
4933                                             Promise<CheckDialogUsernameResult> &&promise) {
4934   if (dialog_id != DialogId() && !dialog_id.is_valid()) {
4935     return promise.set_error(Status::Error(400, "Chat not found"));
4936   }
4937 
4938   switch (dialog_id.get_type()) {
4939     case DialogType::User: {
4940       if (dialog_id.get_user_id() != get_my_id()) {
4941         return promise.set_error(Status::Error(400, "Can't check username for private chat with other user"));
4942       }
4943       break;
4944     }
4945     case DialogType::Channel: {
4946       auto c = get_channel(dialog_id.get_channel_id());
4947       if (c == nullptr) {
4948         return promise.set_error(Status::Error(400, "Chat not found"));
4949       }
4950       if (!get_channel_status(c).is_creator()) {
4951         return promise.set_error(Status::Error(400, "Not enough rights to change username"));
4952       }
4953 
4954       if (username == c->username) {
4955         return promise.set_value(CheckDialogUsernameResult::Ok);
4956       }
4957       break;
4958     }
4959     case DialogType::None:
4960       break;
4961     case DialogType::Chat:
4962     case DialogType::SecretChat:
4963       if (username.empty()) {
4964         return promise.set_value(CheckDialogUsernameResult::Ok);
4965       }
4966       return promise.set_error(Status::Error(400, "Chat can't have username"));
4967     default:
4968       UNREACHABLE();
4969       return;
4970   }
4971 
4972   if (username.empty()) {
4973     return promise.set_value(CheckDialogUsernameResult::Ok);
4974   }
4975   if (!is_valid_username(username)) {
4976     return promise.set_value(CheckDialogUsernameResult::Invalid);
4977   }
4978 
4979   auto request_promise = PromiseCreator::lambda([promise = std::move(promise)](Result<bool> result) mutable {
4980     if (result.is_error()) {
4981       auto error = result.move_as_error();
4982       if (error.message() == "CHANNEL_PUBLIC_GROUP_NA") {
4983         return promise.set_value(CheckDialogUsernameResult::PublicGroupsUnavailable);
4984       }
4985       if (error.message() == "CHANNELS_ADMIN_PUBLIC_TOO_MUCH") {
4986         return promise.set_value(CheckDialogUsernameResult::PublicDialogsTooMuch);
4987       }
4988       if (error.message() == "USERNAME_INVALID") {
4989         return promise.set_value(CheckDialogUsernameResult::Invalid);
4990       }
4991       return promise.set_error(std::move(error));
4992     }
4993 
4994     promise.set_value(result.ok() ? CheckDialogUsernameResult::Ok : CheckDialogUsernameResult::Occupied);
4995   });
4996 
4997   switch (dialog_id.get_type()) {
4998     case DialogType::User:
4999       return td_->create_handler<CheckUsernameQuery>(std::move(request_promise))->send(username);
5000     case DialogType::Channel:
5001       return td_->create_handler<CheckChannelUsernameQuery>(std::move(request_promise))
5002           ->send(dialog_id.get_channel_id(), username);
5003     case DialogType::None:
5004       return td_->create_handler<CheckChannelUsernameQuery>(std::move(request_promise))->send(ChannelId(), username);
5005     case DialogType::Chat:
5006     case DialogType::SecretChat:
5007     default:
5008       UNREACHABLE();
5009   }
5010 }
5011 
get_check_chat_username_result_object(CheckDialogUsernameResult result)5012 td_api::object_ptr<td_api::CheckChatUsernameResult> ContactsManager::get_check_chat_username_result_object(
5013     CheckDialogUsernameResult result) {
5014   switch (result) {
5015     case CheckDialogUsernameResult::Ok:
5016       return td_api::make_object<td_api::checkChatUsernameResultOk>();
5017     case CheckDialogUsernameResult::Invalid:
5018       return td_api::make_object<td_api::checkChatUsernameResultUsernameInvalid>();
5019     case CheckDialogUsernameResult::Occupied:
5020       return td_api::make_object<td_api::checkChatUsernameResultUsernameOccupied>();
5021     case CheckDialogUsernameResult::PublicDialogsTooMuch:
5022       return td_api::make_object<td_api::checkChatUsernameResultPublicChatsTooMuch>();
5023     case CheckDialogUsernameResult::PublicGroupsUnavailable:
5024       return td_api::make_object<td_api::checkChatUsernameResultPublicGroupsUnavailable>();
5025     default:
5026       UNREACHABLE();
5027       return nullptr;
5028   }
5029 }
5030 
is_valid_username(const string & username)5031 bool ContactsManager::is_valid_username(const string &username) {
5032   if (username.size() < 5 || username.size() > 32) {
5033     return false;
5034   }
5035   if (!is_alpha(username[0])) {
5036     return false;
5037   }
5038   for (auto c : username) {
5039     if (!is_alpha(c) && !is_digit(c) && c != '_') {
5040       return false;
5041     }
5042   }
5043   if (username.back() == '_') {
5044     return false;
5045   }
5046   for (size_t i = 1; i < username.size(); i++) {
5047     if (username[i - 1] == '_' && username[i] == '_') {
5048       return false;
5049     }
5050   }
5051   if (username.find("admin") == 0 || username.find("telegram") == 0 || username.find("support") == 0 ||
5052       username.find("security") == 0 || username.find("settings") == 0 || username.find("contacts") == 0 ||
5053       username.find("service") == 0 || username.find("telegraph") == 0) {
5054     return false;
5055   }
5056   return true;
5057 }
5058 
get_user_was_online(const User * u,UserId user_id) const5059 int32 ContactsManager::get_user_was_online(const User *u, UserId user_id) const {
5060   if (u == nullptr || u->is_deleted) {
5061     return 0;
5062   }
5063 
5064   int32 was_online = u->was_online;
5065   if (user_id == get_my_id()) {
5066     if (my_was_online_local_ != 0) {
5067       was_online = my_was_online_local_;
5068     }
5069   } else {
5070     if (u->local_was_online > 0 && u->local_was_online > was_online && u->local_was_online > G()->unix_time_cached()) {
5071       was_online = u->local_was_online;
5072     }
5073   }
5074   return was_online;
5075 }
5076 
load_contacts(Promise<Unit> && promise)5077 void ContactsManager::load_contacts(Promise<Unit> &&promise) {
5078   if (td_->auth_manager_->is_bot()) {
5079     are_contacts_loaded_ = true;
5080     saved_contact_count_ = 0;
5081   }
5082   if (are_contacts_loaded_ && saved_contact_count_ != -1) {
5083     LOG(INFO) << "Contacts are already loaded";
5084     promise.set_value(Unit());
5085     return;
5086   }
5087   load_contacts_queries_.push_back(std::move(promise));
5088   if (load_contacts_queries_.size() == 1u) {
5089     if (G()->parameters().use_chat_info_db && next_contacts_sync_date_ > 0 && saved_contact_count_ != -1) {
5090       LOG(INFO) << "Load contacts from database";
5091       G()->td_db()->get_sqlite_pmc()->get(
5092           "user_contacts", PromiseCreator::lambda([](string value) {
5093             send_closure(G()->contacts_manager(), &ContactsManager::on_load_contacts_from_database, std::move(value));
5094           }));
5095     } else {
5096       LOG(INFO) << "Load contacts from server";
5097       reload_contacts(true);
5098     }
5099   } else {
5100     LOG(INFO) << "Load contacts request has already been sent";
5101   }
5102 }
5103 
get_contacts_hash()5104 int64 ContactsManager::get_contacts_hash() {
5105   if (!are_contacts_loaded_) {
5106     return 0;
5107   }
5108 
5109   vector<int64> user_ids = contacts_hints_.search_empty(100000).second;
5110   CHECK(std::is_sorted(user_ids.begin(), user_ids.end()));
5111   auto my_id = get_my_id();
5112   const User *u = get_user_force(my_id);
5113   if (u != nullptr && u->is_contact) {
5114     user_ids.insert(std::upper_bound(user_ids.begin(), user_ids.end(), my_id.get()), my_id.get());
5115   }
5116 
5117   vector<uint64> numbers;
5118   numbers.reserve(user_ids.size() + 1);
5119   numbers.push_back(saved_contact_count_);
5120   for (auto user_id : user_ids) {
5121     numbers.push_back(user_id);
5122   }
5123   return get_vector_hash(numbers);
5124 }
5125 
reload_contacts(bool force)5126 void ContactsManager::reload_contacts(bool force) {
5127   if (!td_->auth_manager_->is_bot() && next_contacts_sync_date_ != std::numeric_limits<int32>::max() &&
5128       (next_contacts_sync_date_ < G()->unix_time() || force)) {
5129     next_contacts_sync_date_ = std::numeric_limits<int32>::max();
5130     td_->create_handler<GetContactsQuery>()->send(get_contacts_hash());
5131   }
5132 }
5133 
add_contact(Contact contact,bool share_phone_number,Promise<Unit> && promise)5134 void ContactsManager::add_contact(Contact contact, bool share_phone_number, Promise<Unit> &&promise) {
5135   TRY_STATUS_PROMISE(promise, G()->close_status());
5136 
5137   if (!are_contacts_loaded_) {
5138     load_contacts(PromiseCreator::lambda([actor_id = actor_id(this), contact = std::move(contact), share_phone_number,
5139                                           promise = std::move(promise)](Result<Unit> &&) mutable {
5140       send_closure(actor_id, &ContactsManager::add_contact, std::move(contact), share_phone_number, std::move(promise));
5141     }));
5142     return;
5143   }
5144 
5145   LOG(INFO) << "Add " << contact << " with share_phone_number = " << share_phone_number;
5146 
5147   auto user_id = contact.get_user_id();
5148   auto input_user = get_input_user(user_id);
5149   if (input_user == nullptr) {
5150     return promise.set_error(Status::Error(400, "User not found"));
5151   }
5152 
5153   td_->create_handler<AddContactQuery>(std::move(promise))
5154       ->send(user_id, std::move(input_user), contact, share_phone_number);
5155 }
5156 
import_contacts(const vector<Contact> & contacts,int64 & random_id,Promise<Unit> && promise)5157 std::pair<vector<UserId>, vector<int32>> ContactsManager::import_contacts(const vector<Contact> &contacts,
5158                                                                           int64 &random_id, Promise<Unit> &&promise) {
5159   if (!are_contacts_loaded_) {
5160     load_contacts(std::move(promise));
5161     return {};
5162   }
5163 
5164   LOG(INFO) << "Asked to import " << contacts.size() << " contacts with random_id = " << random_id;
5165   if (random_id != 0) {
5166     // request has already been sent before
5167     auto it = imported_contacts_.find(random_id);
5168     CHECK(it != imported_contacts_.end());
5169     auto result = std::move(it->second);
5170     imported_contacts_.erase(it);
5171 
5172     promise.set_value(Unit());
5173     return result;
5174   }
5175 
5176   do {
5177     random_id = Random::secure_int64();
5178   } while (random_id == 0 || imported_contacts_.find(random_id) != imported_contacts_.end());
5179   imported_contacts_[random_id];  // reserve place for result
5180 
5181   do_import_contacts(contacts, random_id, std::move(promise));
5182   return {};
5183 }
5184 
do_import_contacts(vector<Contact> contacts,int64 random_id,Promise<Unit> && promise)5185 void ContactsManager::do_import_contacts(vector<Contact> contacts, int64 random_id, Promise<Unit> &&promise) {
5186   size_t size = contacts.size();
5187   if (size == 0) {
5188     on_import_contacts_finished(random_id, {}, {});
5189     return promise.set_value(Unit());
5190   }
5191 
5192   vector<tl_object_ptr<telegram_api::inputPhoneContact>> input_phone_contacts;
5193   input_phone_contacts.reserve(size);
5194   for (size_t i = 0; i < size; i++) {
5195     input_phone_contacts.push_back(contacts[i].get_input_phone_contact(static_cast<int64>(i)));
5196   }
5197 
5198   auto task = make_unique<ImportContactsTask>();
5199   task->promise_ = std::move(promise);
5200   task->input_contacts_ = std::move(contacts);
5201   task->imported_user_ids_.resize(size);
5202   task->unimported_contact_invites_.resize(size);
5203 
5204   bool is_added = import_contact_tasks_.emplace(random_id, std::move(task)).second;
5205   CHECK(is_added);
5206 
5207   td_->create_handler<ImportContactsQuery>()->send(std::move(input_phone_contacts), random_id);
5208 }
5209 
on_imported_contacts(int64 random_id,Result<tl_object_ptr<telegram_api::contacts_importedContacts>> result)5210 void ContactsManager::on_imported_contacts(int64 random_id,
5211                                            Result<tl_object_ptr<telegram_api::contacts_importedContacts>> result) {
5212   auto it = import_contact_tasks_.find(random_id);
5213   CHECK(it != import_contact_tasks_.end());
5214   CHECK(it->second != nullptr);
5215 
5216   auto task = it->second.get();
5217   if (result.is_error()) {
5218     auto promise = std::move(task->promise_);
5219     import_contact_tasks_.erase(it);
5220     return promise.set_error(result.move_as_error());
5221   }
5222 
5223   auto imported_contacts = result.move_as_ok();
5224   on_get_users(std::move(imported_contacts->users_), "on_imported_contacts");
5225 
5226   for (auto &imported_contact : imported_contacts->imported_) {
5227     int64 client_id = imported_contact->client_id_;
5228     if (client_id < 0 || client_id >= static_cast<int64>(task->imported_user_ids_.size())) {
5229       LOG(ERROR) << "Wrong client_id " << client_id << " returned";
5230       continue;
5231     }
5232 
5233     task->imported_user_ids_[static_cast<size_t>(client_id)] = UserId(imported_contact->user_id_);
5234   }
5235   for (auto &popular_contact : imported_contacts->popular_invites_) {
5236     int64 client_id = popular_contact->client_id_;
5237     if (client_id < 0 || client_id >= static_cast<int64>(task->unimported_contact_invites_.size())) {
5238       LOG(ERROR) << "Wrong client_id " << client_id << " returned";
5239       continue;
5240     }
5241     if (popular_contact->importers_ < 0) {
5242       LOG(ERROR) << "Wrong number of importers " << popular_contact->importers_ << " returned";
5243       continue;
5244     }
5245 
5246     task->unimported_contact_invites_[static_cast<size_t>(client_id)] = popular_contact->importers_;
5247   }
5248 
5249   if (!imported_contacts->retry_contacts_.empty()) {
5250     auto total_size = static_cast<int64>(task->input_contacts_.size());
5251     vector<tl_object_ptr<telegram_api::inputPhoneContact>> input_phone_contacts;
5252     input_phone_contacts.reserve(imported_contacts->retry_contacts_.size());
5253     for (auto &client_id : imported_contacts->retry_contacts_) {
5254       if (client_id < 0 || client_id >= total_size) {
5255         LOG(ERROR) << "Wrong client_id " << client_id << " returned";
5256         continue;
5257       }
5258       auto i = static_cast<size_t>(client_id);
5259       input_phone_contacts.push_back(task->input_contacts_[i].get_input_phone_contact(client_id));
5260     }
5261     td_->create_handler<ImportContactsQuery>()->send(std::move(input_phone_contacts), random_id);
5262     return;
5263   }
5264 
5265   auto promise = std::move(task->promise_);
5266   on_import_contacts_finished(random_id, std::move(task->imported_user_ids_),
5267                               std::move(task->unimported_contact_invites_));
5268   import_contact_tasks_.erase(it);
5269   promise.set_value(Unit());
5270 }
5271 
remove_contacts(const vector<UserId> & user_ids,Promise<Unit> && promise)5272 void ContactsManager::remove_contacts(const vector<UserId> &user_ids, Promise<Unit> &&promise) {
5273   LOG(INFO) << "Delete contacts: " << format::as_array(user_ids);
5274   if (!are_contacts_loaded_) {
5275     load_contacts(std::move(promise));
5276     return;
5277   }
5278 
5279   vector<UserId> to_delete_user_ids;
5280   vector<tl_object_ptr<telegram_api::InputUser>> input_users;
5281   for (auto &user_id : user_ids) {
5282     const User *u = get_user(user_id);
5283     if (u != nullptr && u->is_contact) {
5284       auto input_user = get_input_user(user_id);
5285       if (input_user != nullptr) {
5286         to_delete_user_ids.push_back(user_id);
5287         input_users.push_back(std::move(input_user));
5288       }
5289     }
5290   }
5291 
5292   if (input_users.empty()) {
5293     return promise.set_value(Unit());
5294   }
5295 
5296   td_->create_handler<DeleteContactsQuery>(std::move(promise))->send(std::move(input_users));
5297 }
5298 
remove_contacts_by_phone_number(vector<string> user_phone_numbers,vector<UserId> user_ids,Promise<Unit> && promise)5299 void ContactsManager::remove_contacts_by_phone_number(vector<string> user_phone_numbers, vector<UserId> user_ids,
5300                                                       Promise<Unit> &&promise) {
5301   LOG(INFO) << "Delete contacts by phone number: " << format::as_array(user_phone_numbers);
5302   if (!are_contacts_loaded_) {
5303     load_contacts(std::move(promise));
5304     return;
5305   }
5306 
5307   td_->create_handler<DeleteContactsByPhoneNumberQuery>(std::move(promise))
5308       ->send(std::move(user_phone_numbers), std::move(user_ids));
5309 }
5310 
get_imported_contact_count(Promise<Unit> && promise)5311 int32 ContactsManager::get_imported_contact_count(Promise<Unit> &&promise) {
5312   LOG(INFO) << "Get imported contact count";
5313 
5314   if (!are_contacts_loaded_ || saved_contact_count_ == -1) {
5315     load_contacts(std::move(promise));
5316     return 0;
5317   }
5318   reload_contacts(false);
5319 
5320   promise.set_value(Unit());
5321   return saved_contact_count_;
5322 }
5323 
load_imported_contacts(Promise<Unit> && promise)5324 void ContactsManager::load_imported_contacts(Promise<Unit> &&promise) {
5325   if (td_->auth_manager_->is_bot()) {
5326     are_imported_contacts_loaded_ = true;
5327   }
5328   if (are_imported_contacts_loaded_) {
5329     LOG(INFO) << "Imported contacts are already loaded";
5330     promise.set_value(Unit());
5331     return;
5332   }
5333   load_imported_contacts_queries_.push_back(std::move(promise));
5334   if (load_imported_contacts_queries_.size() == 1u) {
5335     if (G()->parameters().use_chat_info_db) {
5336       LOG(INFO) << "Load imported contacts from database";
5337       G()->td_db()->get_sqlite_pmc()->get(
5338           "user_imported_contacts", PromiseCreator::lambda([](string value) {
5339             send_closure_later(G()->contacts_manager(), &ContactsManager::on_load_imported_contacts_from_database,
5340                                std::move(value));
5341           }));
5342     } else {
5343       LOG(INFO) << "Have no previously imported contacts";
5344       send_closure_later(G()->contacts_manager(), &ContactsManager::on_load_imported_contacts_from_database, string());
5345     }
5346   } else {
5347     LOG(INFO) << "Load imported contacts request has already been sent";
5348   }
5349 }
5350 
on_load_imported_contacts_from_database(string value)5351 void ContactsManager::on_load_imported_contacts_from_database(string value) {
5352   if (G()->close_flag()) {
5353     return;
5354   }
5355 
5356   CHECK(!are_imported_contacts_loaded_);
5357   if (need_clear_imported_contacts_) {
5358     need_clear_imported_contacts_ = false;
5359     value.clear();
5360   }
5361   if (value.empty()) {
5362     CHECK(all_imported_contacts_.empty());
5363   } else {
5364     log_event_parse(all_imported_contacts_, value).ensure();
5365     LOG(INFO) << "Successfully loaded " << all_imported_contacts_.size() << " imported contacts from database";
5366   }
5367 
5368   load_imported_contact_users_multipromise_.add_promise(
5369       PromiseCreator::lambda([actor_id = actor_id(this)](Result<Unit> result) {
5370         if (result.is_ok()) {
5371           send_closure_later(actor_id, &ContactsManager::on_load_imported_contacts_finished);
5372         }
5373       }));
5374 
5375   auto lock_promise = load_imported_contact_users_multipromise_.get_promise();
5376 
5377   for (const auto &contact : all_imported_contacts_) {
5378     auto user_id = contact.get_user_id();
5379     if (user_id.is_valid()) {
5380       get_user(user_id, 3, load_imported_contact_users_multipromise_.get_promise());
5381     }
5382   }
5383 
5384   lock_promise.set_value(Unit());
5385 }
5386 
on_load_imported_contacts_finished()5387 void ContactsManager::on_load_imported_contacts_finished() {
5388   LOG(INFO) << "Finished to load " << all_imported_contacts_.size() << " imported contacts";
5389 
5390   for (const auto &contact : all_imported_contacts_) {
5391     get_user_id_object(contact.get_user_id(), "on_load_imported_contacts_finished");  // to ensure updateUser
5392   }
5393 
5394   if (need_clear_imported_contacts_) {
5395     need_clear_imported_contacts_ = false;
5396     all_imported_contacts_.clear();
5397   }
5398   are_imported_contacts_loaded_ = true;
5399   auto promises = std::move(load_imported_contacts_queries_);
5400   load_imported_contacts_queries_.clear();
5401   for (auto &promise : promises) {
5402     promise.set_value(Unit());
5403   }
5404 }
5405 
change_imported_contacts(vector<Contact> & contacts,int64 & random_id,Promise<Unit> && promise)5406 std::pair<vector<UserId>, vector<int32>> ContactsManager::change_imported_contacts(vector<Contact> &contacts,
5407                                                                                    int64 &random_id,
5408                                                                                    Promise<Unit> &&promise) {
5409   if (!are_contacts_loaded_) {
5410     load_contacts(std::move(promise));
5411     return {};
5412   }
5413   if (!are_imported_contacts_loaded_) {
5414     load_imported_contacts(std::move(promise));
5415     return {};
5416   }
5417 
5418   LOG(INFO) << "Asked to change imported contacts to a list of " << contacts.size()
5419             << " contacts with random_id = " << random_id;
5420   if (random_id != 0) {
5421     // request has already been sent before
5422     if (need_clear_imported_contacts_) {
5423       need_clear_imported_contacts_ = false;
5424       all_imported_contacts_.clear();
5425       if (G()->parameters().use_chat_info_db) {
5426         G()->td_db()->get_sqlite_pmc()->erase("user_imported_contacts", Auto());
5427       }
5428       reload_contacts(true);
5429     }
5430 
5431     CHECK(are_imported_contacts_changing_);
5432     are_imported_contacts_changing_ = false;
5433 
5434     auto unimported_contact_invites = std::move(unimported_contact_invites_);
5435     unimported_contact_invites_.clear();
5436 
5437     auto imported_contact_user_ids = std::move(imported_contact_user_ids_);
5438     imported_contact_user_ids_.clear();
5439 
5440     promise.set_value(Unit());
5441     return {std::move(imported_contact_user_ids), std::move(unimported_contact_invites)};
5442   }
5443 
5444   if (are_imported_contacts_changing_) {
5445     promise.set_error(Status::Error(400, "ChangeImportedContacts can be called only once at the same time"));
5446     return {};
5447   }
5448 
5449   vector<size_t> new_contacts_unique_id(contacts.size());
5450   vector<Contact> unique_new_contacts;
5451   unique_new_contacts.reserve(contacts.size());
5452   std::unordered_map<Contact, size_t, ContactHash, ContactEqual> different_new_contacts;
5453   std::unordered_set<string> different_new_phone_numbers;
5454   size_t unique_size = 0;
5455   for (size_t i = 0; i < contacts.size(); i++) {
5456     auto it_success = different_new_contacts.emplace(std::move(contacts[i]), unique_size);
5457     new_contacts_unique_id[i] = it_success.first->second;
5458     if (it_success.second) {
5459       unique_new_contacts.push_back(it_success.first->first);
5460       different_new_phone_numbers.insert(unique_new_contacts.back().get_phone_number());
5461       unique_size++;
5462     }
5463   }
5464 
5465   vector<string> to_delete;
5466   vector<UserId> to_delete_user_ids;
5467   for (auto &old_contact : all_imported_contacts_) {
5468     auto user_id = old_contact.get_user_id();
5469     auto it = different_new_contacts.find(old_contact);
5470     if (it == different_new_contacts.end()) {
5471       auto phone_number = old_contact.get_phone_number();
5472       if (different_new_phone_numbers.count(phone_number) == 0) {
5473         to_delete.push_back(std::move(phone_number));
5474         if (user_id.is_valid()) {
5475           to_delete_user_ids.push_back(user_id);
5476         }
5477       }
5478     } else {
5479       unique_new_contacts[it->second].set_user_id(user_id);
5480       different_new_contacts.erase(it);
5481     }
5482   }
5483   std::pair<vector<size_t>, vector<Contact>> to_add;
5484   for (auto &new_contact : different_new_contacts) {
5485     to_add.first.push_back(new_contact.second);
5486     to_add.second.push_back(new_contact.first);
5487   }
5488 
5489   if (to_add.first.empty() && to_delete.empty()) {
5490     for (size_t i = 0; i < contacts.size(); i++) {
5491       auto unique_id = new_contacts_unique_id[i];
5492       contacts[i].set_user_id(unique_new_contacts[unique_id].get_user_id());
5493     }
5494 
5495     promise.set_value(Unit());
5496     return {transform(contacts, [&](const Contact &contact) { return contact.get_user_id(); }),
5497             vector<int32>(contacts.size())};
5498   }
5499 
5500   are_imported_contacts_changing_ = true;
5501   random_id = 1;
5502 
5503   remove_contacts_by_phone_number(
5504       std::move(to_delete), std::move(to_delete_user_ids),
5505       PromiseCreator::lambda([new_contacts = std::move(unique_new_contacts),
5506                               new_contacts_unique_id = std::move(new_contacts_unique_id), to_add = std::move(to_add),
5507                               promise = std::move(promise)](Result<> result) mutable {
5508         if (result.is_ok()) {
5509           send_closure_later(G()->contacts_manager(), &ContactsManager::on_clear_imported_contacts,
5510                              std::move(new_contacts), std::move(new_contacts_unique_id), std::move(to_add),
5511                              std::move(promise));
5512         } else {
5513           promise.set_error(result.move_as_error());
5514         }
5515       }));
5516   return {};
5517 }
5518 
on_clear_imported_contacts(vector<Contact> && contacts,vector<size_t> contacts_unique_id,std::pair<vector<size_t>,vector<Contact>> && to_add,Promise<Unit> && promise)5519 void ContactsManager::on_clear_imported_contacts(vector<Contact> &&contacts, vector<size_t> contacts_unique_id,
5520                                                  std::pair<vector<size_t>, vector<Contact>> &&to_add,
5521                                                  Promise<Unit> &&promise) {
5522   LOG(INFO) << "Add " << to_add.first.size() << " contacts";
5523   next_all_imported_contacts_ = std::move(contacts);
5524   imported_contacts_unique_id_ = std::move(contacts_unique_id);
5525   imported_contacts_pos_ = std::move(to_add.first);
5526 
5527   do_import_contacts(std::move(to_add.second), 0, std::move(promise));
5528 }
5529 
clear_imported_contacts(Promise<Unit> && promise)5530 void ContactsManager::clear_imported_contacts(Promise<Unit> &&promise) {
5531   LOG(INFO) << "Delete imported contacts";
5532 
5533   if (saved_contact_count_ == 0) {
5534     promise.set_value(Unit());
5535     return;
5536   }
5537 
5538   td_->create_handler<ResetContactsQuery>(std::move(promise))->send();
5539 }
5540 
on_update_contacts_reset()5541 void ContactsManager::on_update_contacts_reset() {
5542   /*
5543   UserId my_id = get_my_id();
5544   for (auto &p : users_) {
5545     UserId user_id = p.first;
5546     User u = &p.second;
5547     if (u->is_contact) {
5548       LOG(INFO) << "Drop contact with " << user_id;
5549       if (user_id != my_id) {
5550         CHECK(contacts_hints_.has_key(user_id.get()));
5551       }
5552       on_update_user_is_contact(u, user_id, false, false);
5553       CHECK(u->is_is_contact_changed);
5554       u->cache_version = 0;
5555       u->is_repaired = false;
5556       update_user(u, user_id);
5557       CHECK(!u->is_contact);
5558       if (user_id != my_id) {
5559         CHECK(!contacts_hints_.has_key(user_id.get()));
5560       }
5561     }
5562   }
5563   */
5564 
5565   saved_contact_count_ = 0;
5566   if (G()->parameters().use_chat_info_db) {
5567     G()->td_db()->get_binlog_pmc()->set("saved_contact_count", "0");
5568     G()->td_db()->get_sqlite_pmc()->erase("user_imported_contacts", Auto());
5569   }
5570   if (!are_imported_contacts_loaded_) {
5571     CHECK(all_imported_contacts_.empty());
5572     if (load_imported_contacts_queries_.empty()) {
5573       LOG(INFO) << "Imported contacts was never loaded, just clear them";
5574     } else {
5575       LOG(INFO) << "Imported contacts are being loaded, clear them also when they will be loaded";
5576       need_clear_imported_contacts_ = true;
5577     }
5578   } else {
5579     if (!are_imported_contacts_changing_) {
5580       LOG(INFO) << "Imported contacts was loaded, but aren't changing now, just clear them";
5581       all_imported_contacts_.clear();
5582     } else {
5583       LOG(INFO) << "Imported contacts are changing now, clear them also after they will be loaded";
5584       need_clear_imported_contacts_ = true;
5585     }
5586   }
5587   reload_contacts(true);
5588 }
5589 
search_contacts(const string & query,int32 limit,Promise<Unit> && promise)5590 std::pair<int32, vector<UserId>> ContactsManager::search_contacts(const string &query, int32 limit,
5591                                                                   Promise<Unit> &&promise) {
5592   LOG(INFO) << "Search contacts with query = \"" << query << "\" and limit = " << limit;
5593 
5594   if (limit < 0) {
5595     promise.set_error(Status::Error(400, "Limit must be non-negative"));
5596     return {};
5597   }
5598 
5599   if (!are_contacts_loaded_) {
5600     load_contacts(std::move(promise));
5601     return {};
5602   }
5603   reload_contacts(false);
5604 
5605   std::pair<size_t, vector<int64>> result;
5606   if (query.empty()) {
5607     result = contacts_hints_.search_empty(limit);
5608   } else {
5609     result = contacts_hints_.search(query, limit);
5610   }
5611 
5612   vector<UserId> user_ids;
5613   user_ids.reserve(result.second.size());
5614   for (auto key : result.second) {
5615     user_ids.emplace_back(key);
5616   }
5617 
5618   promise.set_value(Unit());
5619   return {narrow_cast<int32>(result.first), std::move(user_ids)};
5620 }
5621 
share_phone_number(UserId user_id,Promise<Unit> && promise)5622 void ContactsManager::share_phone_number(UserId user_id, Promise<Unit> &&promise) {
5623   TRY_STATUS_PROMISE(promise, G()->close_status());
5624 
5625   if (!are_contacts_loaded_) {
5626     load_contacts(PromiseCreator::lambda(
5627         [actor_id = actor_id(this), user_id, promise = std::move(promise)](Result<Unit> &&) mutable {
5628           send_closure(actor_id, &ContactsManager::share_phone_number, user_id, std::move(promise));
5629         }));
5630     return;
5631   }
5632 
5633   LOG(INFO) << "Share phone number with " << user_id;
5634   auto input_user = get_input_user(user_id);
5635   if (input_user == nullptr) {
5636     return promise.set_error(Status::Error(400, "User not found"));
5637   }
5638 
5639   td_->messages_manager_->hide_dialog_action_bar(DialogId(user_id));
5640 
5641   td_->create_handler<AcceptContactQuery>(std::move(promise))->send(user_id, std::move(input_user));
5642 }
5643 
search_dialogs_nearby(const Location & location,Promise<td_api::object_ptr<td_api::chatsNearby>> && promise)5644 void ContactsManager::search_dialogs_nearby(const Location &location,
5645                                             Promise<td_api::object_ptr<td_api::chatsNearby>> &&promise) {
5646   if (location.empty()) {
5647     return promise.set_error(Status::Error(400, "Invalid location specified"));
5648   }
5649   last_user_location_ = location;
5650   try_send_set_location_visibility_query();
5651 
5652   auto query_promise = PromiseCreator::lambda([actor_id = actor_id(this), promise = std::move(promise)](
5653                                                   Result<tl_object_ptr<telegram_api::Updates>> result) mutable {
5654     send_closure(actor_id, &ContactsManager::on_get_dialogs_nearby, std::move(result), std::move(promise));
5655   });
5656   td_->create_handler<SearchDialogsNearbyQuery>(std::move(query_promise))->send(location, false, -1);
5657 }
5658 
get_chats_nearby_object(const vector<DialogNearby> & dialogs_nearby)5659 vector<td_api::object_ptr<td_api::chatNearby>> ContactsManager::get_chats_nearby_object(
5660     const vector<DialogNearby> &dialogs_nearby) {
5661   return transform(dialogs_nearby, [](const DialogNearby &dialog_nearby) {
5662     return td_api::make_object<td_api::chatNearby>(dialog_nearby.dialog_id.get(), dialog_nearby.distance);
5663   });
5664 }
5665 
send_update_users_nearby() const5666 void ContactsManager::send_update_users_nearby() const {
5667   send_closure(G()->td(), &Td::send_update,
5668                td_api::make_object<td_api::updateUsersNearby>(get_chats_nearby_object(users_nearby_)));
5669 }
5670 
on_get_dialogs_nearby(Result<tl_object_ptr<telegram_api::Updates>> result,Promise<td_api::object_ptr<td_api::chatsNearby>> && promise)5671 void ContactsManager::on_get_dialogs_nearby(Result<tl_object_ptr<telegram_api::Updates>> result,
5672                                             Promise<td_api::object_ptr<td_api::chatsNearby>> &&promise) {
5673   if (result.is_error()) {
5674     return promise.set_error(result.move_as_error());
5675   }
5676 
5677   auto updates_ptr = result.move_as_ok();
5678   if (updates_ptr->get_id() != telegram_api::updates::ID) {
5679     LOG(ERROR) << "Receive " << oneline(to_string(*updates_ptr)) << " instead of updates";
5680     return promise.set_error(Status::Error(500, "Receive unsupported response from the server"));
5681   }
5682 
5683   auto update = telegram_api::move_object_as<telegram_api::updates>(updates_ptr);
5684   LOG(INFO) << "Receive chats nearby in " << to_string(update);
5685 
5686   on_get_users(std::move(update->users_), "on_get_dialogs_nearby");
5687   on_get_chats(std::move(update->chats_), "on_get_dialogs_nearby");
5688 
5689   for (auto &dialog_nearby : users_nearby_) {
5690     user_nearby_timeout_.cancel_timeout(dialog_nearby.dialog_id.get_user_id().get());
5691   }
5692   auto old_users_nearby = std::move(users_nearby_);
5693   users_nearby_.clear();
5694   channels_nearby_.clear();
5695   int32 location_visibility_expire_date = 0;
5696   for (auto &update_ptr : update->updates_) {
5697     if (update_ptr->get_id() != telegram_api::updatePeerLocated::ID) {
5698       LOG(ERROR) << "Receive unexpected " << to_string(update);
5699       continue;
5700     }
5701 
5702     auto expire_date = on_update_peer_located(
5703         std::move(static_cast<telegram_api::updatePeerLocated *>(update_ptr.get())->peers_), false);
5704     if (expire_date != -1) {
5705       location_visibility_expire_date = expire_date;
5706     }
5707   }
5708   if (location_visibility_expire_date != location_visibility_expire_date_) {
5709     set_location_visibility_expire_date(location_visibility_expire_date);
5710     update_is_location_visible();
5711   }
5712 
5713   std::sort(users_nearby_.begin(), users_nearby_.end());
5714   if (old_users_nearby != users_nearby_) {
5715     send_update_users_nearby();  // for other clients connected to the same TDLib instance
5716   }
5717   promise.set_value(td_api::make_object<td_api::chatsNearby>(get_chats_nearby_object(users_nearby_),
5718                                                              get_chats_nearby_object(channels_nearby_)));
5719 }
5720 
set_location(const Location & location,Promise<Unit> && promise)5721 void ContactsManager::set_location(const Location &location, Promise<Unit> &&promise) {
5722   if (location.empty()) {
5723     return promise.set_error(Status::Error(400, "Invalid location specified"));
5724   }
5725   last_user_location_ = location;
5726   try_send_set_location_visibility_query();
5727 
5728   auto query_promise = PromiseCreator::lambda(
5729       [promise = std::move(promise)](Result<tl_object_ptr<telegram_api::Updates>> result) mutable {
5730         promise.set_value(Unit());
5731       });
5732   td_->create_handler<SearchDialogsNearbyQuery>(std::move(query_promise))->send(location, true, -1);
5733 }
5734 
set_location_visibility()5735 void ContactsManager::set_location_visibility() {
5736   bool is_location_visible = G()->shared_config().get_option_boolean("is_location_visible");
5737   auto pending_location_visibility_expire_date = is_location_visible ? std::numeric_limits<int32>::max() : 0;
5738   if (pending_location_visibility_expire_date_ == -1 &&
5739       pending_location_visibility_expire_date == location_visibility_expire_date_) {
5740     return;
5741   }
5742   if (pending_location_visibility_expire_date_ != pending_location_visibility_expire_date) {
5743     pending_location_visibility_expire_date_ = pending_location_visibility_expire_date;
5744     G()->td_db()->get_binlog_pmc()->set("pending_location_visibility_expire_date",
5745                                         to_string(pending_location_visibility_expire_date));
5746     update_is_location_visible();
5747   }
5748   try_send_set_location_visibility_query();
5749 }
5750 
try_send_set_location_visibility_query()5751 void ContactsManager::try_send_set_location_visibility_query() {
5752   if (G()->close_flag()) {
5753     return;
5754   }
5755   if (pending_location_visibility_expire_date_ == -1) {
5756     return;
5757   }
5758 
5759   if (is_set_location_visibility_request_sent_) {
5760     return;
5761   }
5762   if (pending_location_visibility_expire_date_ != 0 && last_user_location_.empty()) {
5763     return;
5764   }
5765 
5766   is_set_location_visibility_request_sent_ = true;
5767   auto query_promise =
5768       PromiseCreator::lambda([actor_id = actor_id(this), set_expire_date = pending_location_visibility_expire_date_](
5769                                  Result<tl_object_ptr<telegram_api::Updates>> result) {
5770         send_closure(actor_id, &ContactsManager::on_set_location_visibility_expire_date, set_expire_date,
5771                      result.is_ok() ? 0 : result.error().code());
5772       });
5773   td_->create_handler<SearchDialogsNearbyQuery>(std::move(query_promise))
5774       ->send(last_user_location_, true, pending_location_visibility_expire_date_);
5775 }
5776 
on_set_location_visibility_expire_date(int32 set_expire_date,int32 error_code)5777 void ContactsManager::on_set_location_visibility_expire_date(int32 set_expire_date, int32 error_code) {
5778   bool success = error_code == 0;
5779   is_set_location_visibility_request_sent_ = false;
5780 
5781   if (set_expire_date != pending_location_visibility_expire_date_) {
5782     try_send_set_location_visibility_query();
5783     return;
5784   }
5785 
5786   if (success) {
5787     set_location_visibility_expire_date(pending_location_visibility_expire_date_);
5788   } else {
5789     if (G()->close_flag()) {
5790       // request will be re-sent after restart
5791       return;
5792     }
5793     if (error_code != 406) {
5794       LOG(ERROR) << "Failed to set location visibility expire date to " << pending_location_visibility_expire_date_;
5795     }
5796   }
5797   G()->td_db()->get_binlog_pmc()->erase("pending_location_visibility_expire_date");
5798   pending_location_visibility_expire_date_ = -1;
5799   update_is_location_visible();
5800 }
5801 
get_is_location_visible(Promise<Unit> && promise)5802 void ContactsManager::get_is_location_visible(Promise<Unit> &&promise) {
5803   auto query_promise = PromiseCreator::lambda([actor_id = actor_id(this), promise = std::move(promise)](
5804                                                   Result<tl_object_ptr<telegram_api::Updates>> result) mutable {
5805     send_closure(actor_id, &ContactsManager::on_get_is_location_visible, std::move(result), std::move(promise));
5806   });
5807   td_->create_handler<SearchDialogsNearbyQuery>(std::move(query_promise))->send(Location(), true, -1);
5808 }
5809 
on_get_is_location_visible(Result<tl_object_ptr<telegram_api::Updates>> && result,Promise<Unit> && promise)5810 void ContactsManager::on_get_is_location_visible(Result<tl_object_ptr<telegram_api::Updates>> &&result,
5811                                                  Promise<Unit> &&promise) {
5812   TRY_STATUS_PROMISE(promise, G()->close_status());
5813   if (result.is_error()) {
5814     if (result.error().message() == "GEO_POINT_INVALID" && pending_location_visibility_expire_date_ == -1 &&
5815         location_visibility_expire_date_ > 0) {
5816       set_location_visibility_expire_date(0);
5817       update_is_location_visible();
5818     }
5819     return promise.set_value(Unit());
5820   }
5821 
5822   auto updates_ptr = result.move_as_ok();
5823   if (updates_ptr->get_id() != telegram_api::updates::ID) {
5824     LOG(ERROR) << "Receive " << oneline(to_string(*updates_ptr)) << " instead of updates";
5825     return promise.set_value(Unit());
5826   }
5827 
5828   auto updates = std::move(telegram_api::move_object_as<telegram_api::updates>(updates_ptr)->updates_);
5829   if (updates.size() != 1 || updates[0]->get_id() != telegram_api::updatePeerLocated::ID) {
5830     LOG(ERROR) << "Receive unexpected " << to_string(updates);
5831     return promise.set_value(Unit());
5832   }
5833 
5834   auto peers = std::move(static_cast<telegram_api::updatePeerLocated *>(updates[0].get())->peers_);
5835   if (peers.size() != 1 || peers[0]->get_id() != telegram_api::peerSelfLocated::ID) {
5836     LOG(ERROR) << "Receive unexpected " << to_string(peers);
5837     return promise.set_value(Unit());
5838   }
5839 
5840   auto location_visibility_expire_date = static_cast<telegram_api::peerSelfLocated *>(peers[0].get())->expires_;
5841   if (location_visibility_expire_date != location_visibility_expire_date_) {
5842     set_location_visibility_expire_date(location_visibility_expire_date);
5843     update_is_location_visible();
5844   }
5845 
5846   promise.set_value(Unit());
5847 }
5848 
on_update_peer_located(vector<tl_object_ptr<telegram_api::PeerLocated>> && peers,bool from_update)5849 int32 ContactsManager::on_update_peer_located(vector<tl_object_ptr<telegram_api::PeerLocated>> &&peers,
5850                                               bool from_update) {
5851   auto now = G()->unix_time();
5852   bool need_update = false;
5853   int32 location_visibility_expire_date = -1;
5854   for (auto &peer_located_ptr : peers) {
5855     if (peer_located_ptr->get_id() == telegram_api::peerSelfLocated::ID) {
5856       auto peer_self_located = telegram_api::move_object_as<telegram_api::peerSelfLocated>(peer_located_ptr);
5857       if (peer_self_located->expires_ == 0 || peer_self_located->expires_ > G()->unix_time()) {
5858         location_visibility_expire_date = peer_self_located->expires_;
5859       }
5860       continue;
5861     }
5862 
5863     CHECK(peer_located_ptr->get_id() == telegram_api::peerLocated::ID);
5864     auto peer_located = telegram_api::move_object_as<telegram_api::peerLocated>(peer_located_ptr);
5865     DialogId dialog_id(peer_located->peer_);
5866     int32 expires_at = peer_located->expires_;
5867     int32 distance = peer_located->distance_;
5868     if (distance < 0 || distance > 50000000) {
5869       LOG(ERROR) << "Receive wrong distance to " << to_string(peer_located);
5870       continue;
5871     }
5872     if (expires_at <= now) {
5873       LOG(INFO) << "Skip expired result " << to_string(peer_located);
5874       continue;
5875     }
5876 
5877     auto dialog_type = dialog_id.get_type();
5878     if (dialog_type == DialogType::User) {
5879       auto user_id = dialog_id.get_user_id();
5880       if (!have_user(user_id)) {
5881         LOG(ERROR) << "Can't find " << user_id;
5882         continue;
5883       }
5884       if (expires_at < now + 86400) {
5885         user_nearby_timeout_.set_timeout_in(user_id.get(), expires_at - now + 1);
5886       }
5887     } else if (dialog_type == DialogType::Channel) {
5888       auto channel_id = dialog_id.get_channel_id();
5889       if (!have_channel(channel_id)) {
5890         LOG(ERROR) << "Can't find " << channel_id;
5891         continue;
5892       }
5893       if (expires_at != std::numeric_limits<int32>::max()) {
5894         LOG(ERROR) << "Receive expiring at " << expires_at << " group location in " << to_string(peer_located);
5895       }
5896       if (from_update) {
5897         LOG(ERROR) << "Receive nearby " << channel_id << " from update";
5898         continue;
5899       }
5900     } else {
5901       LOG(ERROR) << "Receive chat of wrong type in " << to_string(peer_located);
5902       continue;
5903     }
5904 
5905     td_->messages_manager_->force_create_dialog(dialog_id, "on_update_peer_located");
5906 
5907     if (from_update) {
5908       CHECK(dialog_type == DialogType::User);
5909       bool is_found = false;
5910       for (auto &dialog_nearby : users_nearby_) {
5911         if (dialog_nearby.dialog_id == dialog_id) {
5912           if (dialog_nearby.distance != distance) {
5913             dialog_nearby.distance = distance;
5914             need_update = true;
5915           }
5916           is_found = true;
5917           break;
5918         }
5919       }
5920       if (!is_found) {
5921         users_nearby_.emplace_back(dialog_id, distance);
5922         all_users_nearby_.insert(dialog_id.get_user_id());
5923         need_update = true;
5924       }
5925     } else {
5926       if (dialog_type == DialogType::User) {
5927         users_nearby_.emplace_back(dialog_id, distance);
5928         all_users_nearby_.insert(dialog_id.get_user_id());
5929       } else {
5930         channels_nearby_.emplace_back(dialog_id, distance);
5931       }
5932     }
5933   }
5934   if (need_update) {
5935     std::sort(users_nearby_.begin(), users_nearby_.end());
5936     send_update_users_nearby();
5937   }
5938   return location_visibility_expire_date;
5939 }
5940 
set_location_visibility_expire_date(int32 expire_date)5941 void ContactsManager::set_location_visibility_expire_date(int32 expire_date) {
5942   if (location_visibility_expire_date_ == expire_date) {
5943     return;
5944   }
5945 
5946   LOG(INFO) << "Set set_location_visibility_expire_date to " << expire_date;
5947   location_visibility_expire_date_ = expire_date;
5948   if (expire_date == 0) {
5949     G()->td_db()->get_binlog_pmc()->erase("location_visibility_expire_date");
5950   } else {
5951     G()->td_db()->get_binlog_pmc()->set("location_visibility_expire_date", to_string(expire_date));
5952   }
5953   // the caller must call update_is_location_visible() itself
5954 }
5955 
update_is_location_visible()5956 void ContactsManager::update_is_location_visible() {
5957   auto expire_date = pending_location_visibility_expire_date_ != -1 ? pending_location_visibility_expire_date_
5958                                                                     : location_visibility_expire_date_;
5959   G()->shared_config().set_option_boolean("is_location_visible", expire_date != 0);
5960 }
5961 
on_update_bot_commands(DialogId dialog_id,UserId bot_user_id,vector<tl_object_ptr<telegram_api::botCommand>> && bot_commands)5962 void ContactsManager::on_update_bot_commands(DialogId dialog_id, UserId bot_user_id,
5963                                              vector<tl_object_ptr<telegram_api::botCommand>> &&bot_commands) {
5964   if (!bot_user_id.is_valid()) {
5965     LOG(ERROR) << "Receive updateBotCOmmands about invalid " << bot_user_id;
5966     return;
5967   }
5968   if (!have_user(bot_user_id) || !is_user_bot(bot_user_id)) {
5969     return;
5970   }
5971   if (td_->auth_manager_->is_bot()) {
5972     return;
5973   }
5974 
5975   auto is_from_bot = [bot_user_id](const BotCommands &commands) {
5976     return commands.get_bot_user_id() == bot_user_id;
5977   };
5978 
5979   switch (dialog_id.get_type()) {
5980     case DialogType::User: {
5981       UserId user_id(dialog_id.get_user_id());
5982       auto user_full = get_user_full(user_id);
5983       if (user_full != nullptr) {
5984         on_update_user_full_commands(user_full, user_id, std::move(bot_commands));
5985         update_user_full(user_full, user_id, "on_update_bot_commands");
5986       }
5987       break;
5988     }
5989     case DialogType::Chat: {
5990       ChatId chat_id(dialog_id.get_chat_id());
5991       auto chat_full = get_chat_full(chat_id);
5992       if (chat_full != nullptr) {
5993         if (bot_commands.empty()) {
5994           if (td::remove_if(chat_full->bot_commands, is_from_bot)) {
5995             chat_full->is_changed = true;
5996           }
5997         } else {
5998           BotCommands commands(bot_user_id, std::move(bot_commands));
5999           auto it = std::find_if(chat_full->bot_commands.begin(), chat_full->bot_commands.end(), is_from_bot);
6000           if (it != chat_full->bot_commands.end()) {
6001             if (*it != commands) {
6002               *it = std::move(commands);
6003               chat_full->is_changed = true;
6004             }
6005           } else {
6006             chat_full->bot_commands.push_back(std::move(commands));
6007             chat_full->is_changed = true;
6008           }
6009         }
6010         update_chat_full(chat_full, chat_id, "on_update_bot_commands");
6011       }
6012       break;
6013     }
6014     case DialogType::Channel: {
6015       ChannelId channel_id(dialog_id.get_channel_id());
6016       auto channel_full = get_channel_full(channel_id, true, "on_update_bot_commands");
6017       if (channel_full != nullptr) {
6018         if (bot_commands.empty()) {
6019           if (td::remove_if(channel_full->bot_commands, is_from_bot)) {
6020             channel_full->is_changed = true;
6021           }
6022         } else {
6023           BotCommands commands(bot_user_id, std::move(bot_commands));
6024           auto it = std::find_if(channel_full->bot_commands.begin(), channel_full->bot_commands.end(), is_from_bot);
6025           if (it != channel_full->bot_commands.end()) {
6026             if (*it != commands) {
6027               *it = std::move(commands);
6028               channel_full->is_changed = true;
6029             }
6030           } else {
6031             channel_full->bot_commands.push_back(std::move(commands));
6032             channel_full->is_changed = true;
6033           }
6034         }
6035         update_channel_full(channel_full, channel_id, "on_update_bot_commands");
6036       }
6037       break;
6038     }
6039     case DialogType::SecretChat:
6040     default:
6041       LOG(ERROR) << "Receive updateBotCommands in " << dialog_id;
6042       break;
6043   }
6044 }
6045 
get_profile_photo_file_id(int64 photo_id) const6046 FileId ContactsManager::get_profile_photo_file_id(int64 photo_id) const {
6047   auto it = my_photo_file_id_.find(photo_id);
6048   if (it == my_photo_file_id_.end()) {
6049     return FileId();
6050   }
6051   return it->second;
6052 }
6053 
set_profile_photo(const td_api::object_ptr<td_api::InputChatPhoto> & input_photo,Promise<Unit> && promise)6054 void ContactsManager::set_profile_photo(const td_api::object_ptr<td_api::InputChatPhoto> &input_photo,
6055                                         Promise<Unit> &&promise) {
6056   if (input_photo == nullptr) {
6057     return promise.set_error(Status::Error(400, "New profile photo must be non-empty"));
6058   }
6059 
6060   const td_api::object_ptr<td_api::InputFile> *input_file = nullptr;
6061   double main_frame_timestamp = 0.0;
6062   bool is_animation = false;
6063   switch (input_photo->get_id()) {
6064     case td_api::inputChatPhotoPrevious::ID: {
6065       auto photo = static_cast<const td_api::inputChatPhotoPrevious *>(input_photo.get());
6066       auto photo_id = photo->chat_photo_id_;
6067       auto *u = get_user(get_my_id());
6068       if (u != nullptr && u->photo.id > 0 && photo_id == u->photo.id) {
6069         return promise.set_value(Unit());
6070       }
6071 
6072       auto file_id = get_profile_photo_file_id(photo_id);
6073       if (!file_id.is_valid()) {
6074         return promise.set_error(Status::Error(400, "Unknown profile photo ID specified"));
6075       }
6076       return send_update_profile_photo_query(td_->file_manager_->dup_file_id(file_id), photo_id, std::move(promise));
6077     }
6078     case td_api::inputChatPhotoStatic::ID: {
6079       auto photo = static_cast<const td_api::inputChatPhotoStatic *>(input_photo.get());
6080       input_file = &photo->photo_;
6081       break;
6082     }
6083     case td_api::inputChatPhotoAnimation::ID: {
6084       auto photo = static_cast<const td_api::inputChatPhotoAnimation *>(input_photo.get());
6085       input_file = &photo->animation_;
6086       main_frame_timestamp = photo->main_frame_timestamp_;
6087       is_animation = true;
6088       break;
6089     }
6090     default:
6091       UNREACHABLE();
6092       break;
6093   }
6094 
6095   const double MAX_ANIMATION_DURATION = 10.0;
6096   if (main_frame_timestamp < 0.0 || main_frame_timestamp > MAX_ANIMATION_DURATION) {
6097     return promise.set_error(Status::Error(400, "Wrong main frame timestamp specified"));
6098   }
6099 
6100   auto file_type = is_animation ? FileType::Animation : FileType::Photo;
6101   auto r_file_id = td_->file_manager_->get_input_file_id(file_type, *input_file, DialogId(get_my_id()), false, false);
6102   if (r_file_id.is_error()) {
6103     // TODO promise.set_error(std::move(status));
6104     return promise.set_error(Status::Error(400, r_file_id.error().message()));
6105   }
6106   FileId file_id = r_file_id.ok();
6107   CHECK(file_id.is_valid());
6108 
6109   upload_profile_photo(td_->file_manager_->dup_file_id(file_id), is_animation, main_frame_timestamp,
6110                        std::move(promise));
6111 }
6112 
send_update_profile_photo_query(FileId file_id,int64 old_photo_id,Promise<Unit> && promise)6113 void ContactsManager::send_update_profile_photo_query(FileId file_id, int64 old_photo_id, Promise<Unit> &&promise) {
6114   FileView file_view = td_->file_manager_->get_file_view(file_id);
6115   td_->create_handler<UpdateProfilePhotoQuery>(std::move(promise))
6116       ->send(file_id, old_photo_id, file_view.main_remote_location().as_input_photo());
6117 }
6118 
upload_profile_photo(FileId file_id,bool is_animation,double main_frame_timestamp,Promise<Unit> && promise,int reupload_count,vector<int> bad_parts)6119 void ContactsManager::upload_profile_photo(FileId file_id, bool is_animation, double main_frame_timestamp,
6120                                            Promise<Unit> &&promise, int reupload_count, vector<int> bad_parts) {
6121   CHECK(file_id.is_valid());
6122   CHECK(uploaded_profile_photos_.find(file_id) == uploaded_profile_photos_.end());
6123   uploaded_profile_photos_.emplace(
6124       file_id, UploadedProfilePhoto{main_frame_timestamp, is_animation, reupload_count, std::move(promise)});
6125   LOG(INFO) << "Ask to upload " << (is_animation ? "animated" : "static") << " profile photo " << file_id
6126             << " with bad parts " << bad_parts;
6127   // TODO use force_reupload if reupload_count >= 1, replace reupload_count with is_reupload
6128   td_->file_manager_->resume_upload(file_id, std::move(bad_parts), upload_profile_photo_callback_, 32, 0);
6129 }
6130 
delete_profile_photo(int64 profile_photo_id,Promise<Unit> && promise)6131 void ContactsManager::delete_profile_photo(int64 profile_photo_id, Promise<Unit> &&promise) {
6132   const User *u = get_user(get_my_id());
6133   if (u != nullptr && u->photo.id == profile_photo_id) {
6134     td_->create_handler<UpdateProfilePhotoQuery>(std::move(promise))
6135         ->send(FileId(), profile_photo_id, make_tl_object<telegram_api::inputPhotoEmpty>());
6136     return;
6137   }
6138 
6139   td_->create_handler<DeleteProfilePhotoQuery>(std::move(promise))->send(profile_photo_id);
6140 }
6141 
set_name(const string & first_name,const string & last_name,Promise<Unit> && promise)6142 void ContactsManager::set_name(const string &first_name, const string &last_name, Promise<Unit> &&promise) {
6143   auto new_first_name = clean_name(first_name, MAX_NAME_LENGTH);
6144   auto new_last_name = clean_name(last_name, MAX_NAME_LENGTH);
6145   if (new_first_name.empty()) {
6146     return promise.set_error(Status::Error(400, "First name must be non-empty"));
6147   }
6148 
6149   const User *u = get_user(get_my_id());
6150   int32 flags = 0;
6151   // TODO we can already send request for changing first_name and last_name and wanting to set initial values
6152   // TODO need to be rewritten using invoke after and cancelling previous request
6153   if (u == nullptr || u->first_name != new_first_name) {
6154     flags |= ACCOUNT_UPDATE_FIRST_NAME;
6155   }
6156   if (u == nullptr || u->last_name != new_last_name) {
6157     flags |= ACCOUNT_UPDATE_LAST_NAME;
6158   }
6159   if (flags == 0) {
6160     return promise.set_value(Unit());
6161   }
6162 
6163   td_->create_handler<UpdateProfileQuery>(std::move(promise))->send(flags, new_first_name, new_last_name, "");
6164 }
6165 
set_bio(const string & bio,Promise<Unit> && promise)6166 void ContactsManager::set_bio(const string &bio, Promise<Unit> &&promise) {
6167   auto new_bio = strip_empty_characters(bio, MAX_BIO_LENGTH);
6168   for (auto &c : new_bio) {
6169     if (c == '\n') {
6170       c = ' ';
6171     }
6172   }
6173 
6174   const UserFull *user_full = get_user_full(get_my_id());
6175   int32 flags = 0;
6176   // TODO we can already send request for changing bio and wanting to set initial values
6177   // TODO need to be rewritten using invoke after and cancelling previous request
6178   if (user_full == nullptr || user_full->about != new_bio) {
6179     flags |= ACCOUNT_UPDATE_ABOUT;
6180   }
6181   if (flags == 0) {
6182     return promise.set_value(Unit());
6183   }
6184 
6185   td_->create_handler<UpdateProfileQuery>(std::move(promise))->send(flags, "", "", new_bio);
6186 }
6187 
on_update_profile_success(int32 flags,const string & first_name,const string & last_name,const string & about)6188 void ContactsManager::on_update_profile_success(int32 flags, const string &first_name, const string &last_name,
6189                                                 const string &about) {
6190   CHECK(flags != 0);
6191 
6192   auto my_user_id = get_my_id();
6193   const User *u = get_user(my_user_id);
6194   if (u == nullptr) {
6195     LOG(ERROR) << "Doesn't receive info about me during update profile";
6196     return;
6197   }
6198   LOG_IF(ERROR, (flags & ACCOUNT_UPDATE_FIRST_NAME) != 0 && u->first_name != first_name)
6199       << "Wrong first name \"" << u->first_name << "\", expected \"" << first_name << '"';
6200   LOG_IF(ERROR, (flags & ACCOUNT_UPDATE_LAST_NAME) != 0 && u->last_name != last_name)
6201       << "Wrong last name \"" << u->last_name << "\", expected \"" << last_name << '"';
6202 
6203   if ((flags & ACCOUNT_UPDATE_ABOUT) != 0) {
6204     UserFull *user_full = get_user_full_force(my_user_id);
6205     if (user_full != nullptr) {
6206       user_full->about = about;
6207       user_full->is_changed = true;
6208       update_user_full(user_full, my_user_id, "on_update_profile_success");
6209       td_->group_call_manager_->on_update_dialog_about(DialogId(my_user_id), user_full->about, true);
6210     }
6211   }
6212 }
6213 
set_username(const string & username,Promise<Unit> && promise)6214 void ContactsManager::set_username(const string &username, Promise<Unit> &&promise) {
6215   if (!username.empty() && !is_valid_username(username)) {
6216     return promise.set_error(Status::Error(400, "Username is invalid"));
6217   }
6218   td_->create_handler<UpdateUsernameQuery>(std::move(promise))->send(username);
6219 }
6220 
set_chat_description(ChatId chat_id,const string & description,Promise<Unit> && promise)6221 void ContactsManager::set_chat_description(ChatId chat_id, const string &description, Promise<Unit> &&promise) {
6222   auto new_description = strip_empty_characters(description, MAX_DESCRIPTION_LENGTH);
6223   auto c = get_chat(chat_id);
6224   if (c == nullptr) {
6225     return promise.set_error(Status::Error(400, "Chat info not found"));
6226   }
6227   if (!get_chat_permissions(c).can_change_info_and_settings()) {
6228     return promise.set_error(Status::Error(400, "Not enough rights to set chat description"));
6229   }
6230 
6231   td_->create_handler<EditChatAboutQuery>(std::move(promise))->send(DialogId(chat_id), new_description);
6232 }
6233 
set_channel_username(ChannelId channel_id,const string & username,Promise<Unit> && promise)6234 void ContactsManager::set_channel_username(ChannelId channel_id, const string &username, Promise<Unit> &&promise) {
6235   auto c = get_channel(channel_id);
6236   if (c == nullptr) {
6237     return promise.set_error(Status::Error(400, "Supergroup not found"));
6238   }
6239   if (!get_channel_status(c).is_creator()) {
6240     return promise.set_error(Status::Error(400, "Not enough rights to change supergroup username"));
6241   }
6242 
6243   if (!username.empty() && !is_valid_username(username)) {
6244     return promise.set_error(Status::Error(400, "Username is invalid"));
6245   }
6246 
6247   if (!username.empty() && c->username.empty()) {
6248     auto channel_full = get_channel_full(channel_id, false, "set_channel_username");
6249     if (channel_full != nullptr && !channel_full->can_set_username) {
6250       return promise.set_error(Status::Error(400, "Can't set supergroup username"));
6251     }
6252   }
6253 
6254   td_->create_handler<UpdateChannelUsernameQuery>(std::move(promise))->send(channel_id, username);
6255 }
6256 
set_channel_sticker_set(ChannelId channel_id,StickerSetId sticker_set_id,Promise<Unit> && promise)6257 void ContactsManager::set_channel_sticker_set(ChannelId channel_id, StickerSetId sticker_set_id,
6258                                               Promise<Unit> &&promise) {
6259   auto c = get_channel(channel_id);
6260   if (c == nullptr) {
6261     return promise.set_error(Status::Error(400, "Supergroup not found"));
6262   }
6263   if (!c->is_megagroup) {
6264     return promise.set_error(Status::Error(400, "Chat sticker set can be set only for supergroups"));
6265   }
6266   if (!get_channel_permissions(c).can_change_info_and_settings()) {
6267     return promise.set_error(Status::Error(400, "Not enough rights to change supergroup sticker set"));
6268   }
6269 
6270   telegram_api::object_ptr<telegram_api::InputStickerSet> input_sticker_set;
6271   if (!sticker_set_id.is_valid()) {
6272     input_sticker_set = telegram_api::make_object<telegram_api::inputStickerSetEmpty>();
6273   } else {
6274     input_sticker_set = td_->stickers_manager_->get_input_sticker_set(sticker_set_id);
6275     if (input_sticker_set == nullptr) {
6276       return promise.set_error(Status::Error(400, "Sticker set not found"));
6277     }
6278   }
6279 
6280   auto channel_full = get_channel_full(channel_id, false, "set_channel_sticker_set");
6281   if (channel_full != nullptr && !channel_full->can_set_sticker_set) {
6282     return promise.set_error(Status::Error(400, "Can't set supergroup sticker set"));
6283   }
6284 
6285   td_->create_handler<SetChannelStickerSetQuery>(std::move(promise))
6286       ->send(channel_id, sticker_set_id, std::move(input_sticker_set));
6287 }
6288 
toggle_channel_sign_messages(ChannelId channel_id,bool sign_messages,Promise<Unit> && promise)6289 void ContactsManager::toggle_channel_sign_messages(ChannelId channel_id, bool sign_messages, Promise<Unit> &&promise) {
6290   auto c = get_channel(channel_id);
6291   if (c == nullptr) {
6292     return promise.set_error(Status::Error(400, "Supergroup not found"));
6293   }
6294   if (get_channel_type(c) == ChannelType::Megagroup) {
6295     return promise.set_error(Status::Error(400, "Message signatures can't be toggled in supergroups"));
6296   }
6297   if (!get_channel_permissions(c).can_change_info_and_settings()) {
6298     return promise.set_error(Status::Error(400, "Not enough rights to toggle channel sign messages"));
6299   }
6300 
6301   td_->create_handler<ToggleChannelSignaturesQuery>(std::move(promise))->send(channel_id, sign_messages);
6302 }
6303 
toggle_channel_is_all_history_available(ChannelId channel_id,bool is_all_history_available,Promise<Unit> && promise)6304 void ContactsManager::toggle_channel_is_all_history_available(ChannelId channel_id, bool is_all_history_available,
6305                                                               Promise<Unit> &&promise) {
6306   auto c = get_channel(channel_id);
6307   if (c == nullptr) {
6308     return promise.set_error(Status::Error(400, "Supergroup not found"));
6309   }
6310   if (!get_channel_permissions(c).can_change_info_and_settings()) {
6311     return promise.set_error(Status::Error(400, "Not enough rights to toggle all supergroup history availability"));
6312   }
6313   if (get_channel_type(c) != ChannelType::Megagroup) {
6314     return promise.set_error(Status::Error(400, "Message history can be hidden in supergroups only"));
6315   }
6316   if (c->has_linked_channel && !is_all_history_available) {
6317     return promise.set_error(Status::Error(400, "Message history can't be hidden in discussion supergroups"));
6318   }
6319   // it can be toggled in public chats, but will not affect them
6320 
6321   td_->create_handler<TogglePrehistoryHiddenQuery>(std::move(promise))->send(channel_id, is_all_history_available);
6322 }
6323 
convert_channel_to_gigagroup(ChannelId channel_id,Promise<Unit> && promise)6324 void ContactsManager::convert_channel_to_gigagroup(ChannelId channel_id, Promise<Unit> &&promise) {
6325   auto c = get_channel(channel_id);
6326   if (c == nullptr) {
6327     return promise.set_error(Status::Error(400, "Supergroup not found"));
6328   }
6329   if (!get_channel_permissions(c).is_creator()) {
6330     return promise.set_error(Status::Error(400, "Not enough rights to convert group to broadcast group"));
6331   }
6332   if (get_channel_type(c) != ChannelType::Megagroup) {
6333     return promise.set_error(Status::Error(400, "Chat must be a supergroup"));
6334   }
6335 
6336   remove_dialog_suggested_action(SuggestedAction{SuggestedAction::Type::ConvertToGigagroup, DialogId(channel_id)});
6337 
6338   td_->create_handler<ConvertToGigagroupQuery>(std::move(promise))->send(channel_id);
6339 }
6340 
set_channel_description(ChannelId channel_id,const string & description,Promise<Unit> && promise)6341 void ContactsManager::set_channel_description(ChannelId channel_id, const string &description,
6342                                               Promise<Unit> &&promise) {
6343   auto new_description = strip_empty_characters(description, MAX_DESCRIPTION_LENGTH);
6344   auto c = get_channel(channel_id);
6345   if (c == nullptr) {
6346     return promise.set_error(Status::Error(400, "Chat info not found"));
6347   }
6348   if (!get_channel_permissions(c).can_change_info_and_settings()) {
6349     return promise.set_error(Status::Error(400, "Not enough rights to set chat description"));
6350   }
6351 
6352   td_->create_handler<EditChatAboutQuery>(std::move(promise))->send(DialogId(channel_id), new_description);
6353 }
6354 
set_channel_discussion_group(DialogId dialog_id,DialogId discussion_dialog_id,Promise<Unit> && promise)6355 void ContactsManager::set_channel_discussion_group(DialogId dialog_id, DialogId discussion_dialog_id,
6356                                                    Promise<Unit> &&promise) {
6357   if (!dialog_id.is_valid() && !discussion_dialog_id.is_valid()) {
6358     return promise.set_error(Status::Error(400, "Invalid chat identifiers specified"));
6359   }
6360 
6361   ChannelId broadcast_channel_id;
6362   telegram_api::object_ptr<telegram_api::InputChannel> broadcast_input_channel;
6363   if (dialog_id.is_valid()) {
6364     if (!td_->messages_manager_->have_dialog_force(dialog_id, "set_channel_discussion_group 1")) {
6365       return promise.set_error(Status::Error(400, "Chat not found"));
6366     }
6367 
6368     if (dialog_id.get_type() != DialogType::Channel) {
6369       return promise.set_error(Status::Error(400, "Chat is not a channel"));
6370     }
6371 
6372     broadcast_channel_id = dialog_id.get_channel_id();
6373     const Channel *c = get_channel(broadcast_channel_id);
6374     if (c == nullptr) {
6375       return promise.set_error(Status::Error(400, "Chat info not found"));
6376     }
6377 
6378     if (c->is_megagroup) {
6379       return promise.set_error(Status::Error(400, "Chat is not a channel"));
6380     }
6381     if (!c->status.is_administrator() || !c->status.can_change_info_and_settings()) {
6382       return promise.set_error(Status::Error(400, "Not enough rights in the channel"));
6383     }
6384 
6385     broadcast_input_channel = get_input_channel(broadcast_channel_id);
6386     CHECK(broadcast_input_channel != nullptr);
6387   } else {
6388     broadcast_input_channel = telegram_api::make_object<telegram_api::inputChannelEmpty>();
6389   }
6390 
6391   ChannelId group_channel_id;
6392   telegram_api::object_ptr<telegram_api::InputChannel> group_input_channel;
6393   if (discussion_dialog_id.is_valid()) {
6394     if (!td_->messages_manager_->have_dialog_force(discussion_dialog_id, "set_channel_discussion_group 2")) {
6395       return promise.set_error(Status::Error(400, "Discussion chat not found"));
6396     }
6397     if (discussion_dialog_id.get_type() != DialogType::Channel) {
6398       return promise.set_error(Status::Error(400, "Discussion chat is not a supergroup"));
6399     }
6400 
6401     group_channel_id = discussion_dialog_id.get_channel_id();
6402     const Channel *c = get_channel(group_channel_id);
6403     if (c == nullptr) {
6404       return promise.set_error(Status::Error(400, "Discussion chat info not found"));
6405     }
6406 
6407     if (!c->is_megagroup) {
6408       return promise.set_error(Status::Error(400, "Discussion chat is not a supergroup"));
6409     }
6410     if (!c->status.is_administrator() || !c->status.can_pin_messages()) {
6411       return promise.set_error(Status::Error(400, "Not enough rights in the supergroup"));
6412     }
6413 
6414     group_input_channel = get_input_channel(group_channel_id);
6415     CHECK(group_input_channel != nullptr);
6416   } else {
6417     group_input_channel = telegram_api::make_object<telegram_api::inputChannelEmpty>();
6418   }
6419 
6420   td_->create_handler<SetDiscussionGroupQuery>(std::move(promise))
6421       ->send(broadcast_channel_id, std::move(broadcast_input_channel), group_channel_id,
6422              std::move(group_input_channel));
6423 }
6424 
set_channel_location(DialogId dialog_id,const DialogLocation & location,Promise<Unit> && promise)6425 void ContactsManager::set_channel_location(DialogId dialog_id, const DialogLocation &location,
6426                                            Promise<Unit> &&promise) {
6427   if (location.empty()) {
6428     return promise.set_error(Status::Error(400, "Invalid chat location specified"));
6429   }
6430 
6431   if (!dialog_id.is_valid()) {
6432     return promise.set_error(Status::Error(400, "Invalid chat identifier specified"));
6433   }
6434   if (!td_->messages_manager_->have_dialog_force(dialog_id, "set_channel_location")) {
6435     return promise.set_error(Status::Error(400, "Chat not found"));
6436   }
6437 
6438   if (dialog_id.get_type() != DialogType::Channel) {
6439     return promise.set_error(Status::Error(400, "Chat is not a supergroup"));
6440   }
6441 
6442   auto channel_id = dialog_id.get_channel_id();
6443   const Channel *c = get_channel(channel_id);
6444   if (c == nullptr) {
6445     return promise.set_error(Status::Error(400, "Chat info not found"));
6446   }
6447   if (!c->is_megagroup) {
6448     return promise.set_error(Status::Error(400, "Chat is not a supergroup"));
6449   }
6450   if (!c->status.is_creator()) {
6451     return promise.set_error(Status::Error(400, "Not enough rights in the supergroup"));
6452   }
6453 
6454   td_->create_handler<EditLocationQuery>(std::move(promise))->send(channel_id, location);
6455 }
6456 
set_channel_slow_mode_delay(DialogId dialog_id,int32 slow_mode_delay,Promise<Unit> && promise)6457 void ContactsManager::set_channel_slow_mode_delay(DialogId dialog_id, int32 slow_mode_delay, Promise<Unit> &&promise) {
6458   vector<int32> allowed_slow_mode_delays{0, 10, 30, 60, 300, 900, 3600};
6459   if (!td::contains(allowed_slow_mode_delays, slow_mode_delay)) {
6460     return promise.set_error(Status::Error(400, "Invalid new value for slow mode delay"));
6461   }
6462 
6463   if (!dialog_id.is_valid()) {
6464     return promise.set_error(Status::Error(400, "Invalid chat identifier specified"));
6465   }
6466   if (!td_->messages_manager_->have_dialog_force(dialog_id, "set_channel_slow_mode_delay")) {
6467     return promise.set_error(Status::Error(400, "Chat not found"));
6468   }
6469 
6470   if (dialog_id.get_type() != DialogType::Channel) {
6471     return promise.set_error(Status::Error(400, "Chat is not a supergroup"));
6472   }
6473 
6474   auto channel_id = dialog_id.get_channel_id();
6475   const Channel *c = get_channel(channel_id);
6476   if (c == nullptr) {
6477     return promise.set_error(Status::Error(400, "Chat info not found"));
6478   }
6479   if (!c->is_megagroup) {
6480     return promise.set_error(Status::Error(400, "Chat is not a supergroup"));
6481   }
6482   if (!get_channel_permissions(c).can_restrict_members()) {
6483     return promise.set_error(Status::Error(400, "Not enough rights in the supergroup"));
6484   }
6485 
6486   td_->create_handler<ToggleSlowModeQuery>(std::move(promise))->send(channel_id, slow_mode_delay);
6487 }
6488 
get_channel_statistics_dc_id(DialogId dialog_id,bool for_full_statistics,Promise<DcId> && promise)6489 void ContactsManager::get_channel_statistics_dc_id(DialogId dialog_id, bool for_full_statistics,
6490                                                    Promise<DcId> &&promise) {
6491   if (!dialog_id.is_valid()) {
6492     return promise.set_error(Status::Error(400, "Invalid chat identifier specified"));
6493   }
6494   if (!td_->messages_manager_->have_dialog_force(dialog_id, "get_channel_statistics_dc_id")) {
6495     return promise.set_error(Status::Error(400, "Chat not found"));
6496   }
6497 
6498   if (dialog_id.get_type() != DialogType::Channel) {
6499     return promise.set_error(Status::Error(400, "Chat is not a channel"));
6500   }
6501 
6502   auto channel_id = dialog_id.get_channel_id();
6503   const Channel *c = get_channel(channel_id);
6504   if (c == nullptr) {
6505     return promise.set_error(Status::Error(400, "Chat info not found"));
6506   }
6507 
6508   auto channel_full = get_channel_full_force(channel_id, false, "get_channel_statistics_dc_id");
6509   if (channel_full == nullptr || !channel_full->stats_dc_id.is_exact() ||
6510       (for_full_statistics && !channel_full->can_view_statistics)) {
6511     auto query_promise = PromiseCreator::lambda([actor_id = actor_id(this), channel_id, for_full_statistics,
6512                                                  promise = std::move(promise)](Result<Unit> result) mutable {
6513       send_closure(actor_id, &ContactsManager::get_channel_statistics_dc_id_impl, channel_id, for_full_statistics,
6514                    std::move(promise));
6515     });
6516     send_get_channel_full_query(channel_full, channel_id, std::move(query_promise), "get_channel_statistics_dc_id");
6517     return;
6518   }
6519 
6520   promise.set_value(DcId(channel_full->stats_dc_id));
6521 }
6522 
get_channel_statistics_dc_id_impl(ChannelId channel_id,bool for_full_statistics,Promise<DcId> && promise)6523 void ContactsManager::get_channel_statistics_dc_id_impl(ChannelId channel_id, bool for_full_statistics,
6524                                                         Promise<DcId> &&promise) {
6525   TRY_STATUS_PROMISE(promise, G()->close_status());
6526 
6527   auto channel_full = get_channel_full(channel_id, false, "get_channel_statistics_dc_id_impl");
6528   if (channel_full == nullptr) {
6529     return promise.set_error(Status::Error(400, "Chat full info not found"));
6530   }
6531 
6532   if (!channel_full->stats_dc_id.is_exact() || (for_full_statistics && !channel_full->can_view_statistics)) {
6533     return promise.set_error(Status::Error(400, "Chat statistics is not available"));
6534   }
6535 
6536   promise.set_value(DcId(channel_full->stats_dc_id));
6537 }
6538 
get_channel_statistics(DialogId dialog_id,bool is_dark,Promise<td_api::object_ptr<td_api::ChatStatistics>> && promise)6539 void ContactsManager::get_channel_statistics(DialogId dialog_id, bool is_dark,
6540                                              Promise<td_api::object_ptr<td_api::ChatStatistics>> &&promise) {
6541   auto dc_id_promise = PromiseCreator::lambda(
6542       [actor_id = actor_id(this), dialog_id, is_dark, promise = std::move(promise)](Result<DcId> r_dc_id) mutable {
6543         if (r_dc_id.is_error()) {
6544           return promise.set_error(r_dc_id.move_as_error());
6545         }
6546         send_closure(actor_id, &ContactsManager::send_get_channel_stats_query, r_dc_id.move_as_ok(),
6547                      dialog_id.get_channel_id(), is_dark, std::move(promise));
6548       });
6549   get_channel_statistics_dc_id(dialog_id, true, std::move(dc_id_promise));
6550 }
6551 
send_get_channel_stats_query(DcId dc_id,ChannelId channel_id,bool is_dark,Promise<td_api::object_ptr<td_api::ChatStatistics>> && promise)6552 void ContactsManager::send_get_channel_stats_query(DcId dc_id, ChannelId channel_id, bool is_dark,
6553                                                    Promise<td_api::object_ptr<td_api::ChatStatistics>> &&promise) {
6554   TRY_STATUS_PROMISE(promise, G()->close_status());
6555 
6556   const Channel *c = get_channel(channel_id);
6557   CHECK(c != nullptr);
6558   if (c->is_megagroup) {
6559     td_->create_handler<GetMegagroupStatsQuery>(std::move(promise))->send(channel_id, is_dark, dc_id);
6560   } else {
6561     td_->create_handler<GetBroadcastStatsQuery>(std::move(promise))->send(channel_id, is_dark, dc_id);
6562   }
6563 }
6564 
can_get_channel_message_statistics(DialogId dialog_id) const6565 bool ContactsManager::can_get_channel_message_statistics(DialogId dialog_id) const {
6566   if (dialog_id.get_type() != DialogType::Channel) {
6567     return false;
6568   }
6569 
6570   auto channel_id = dialog_id.get_channel_id();
6571   const Channel *c = get_channel(channel_id);
6572   if (c == nullptr || c->is_megagroup) {
6573     return false;
6574   }
6575 
6576   if (td_->auth_manager_->is_bot()) {
6577     return false;
6578   }
6579 
6580   auto channel_full = get_channel_full(channel_id);
6581   if (channel_full != nullptr) {
6582     return channel_full->stats_dc_id.is_exact();
6583   }
6584 
6585   return c->status.is_administrator();
6586 }
6587 
get_channel_message_statistics(FullMessageId full_message_id,bool is_dark,Promise<td_api::object_ptr<td_api::messageStatistics>> && promise)6588 void ContactsManager::get_channel_message_statistics(FullMessageId full_message_id, bool is_dark,
6589                                                      Promise<td_api::object_ptr<td_api::messageStatistics>> &&promise) {
6590   auto dc_id_promise = PromiseCreator::lambda([actor_id = actor_id(this), full_message_id, is_dark,
6591                                                promise = std::move(promise)](Result<DcId> r_dc_id) mutable {
6592     if (r_dc_id.is_error()) {
6593       return promise.set_error(r_dc_id.move_as_error());
6594     }
6595     send_closure(actor_id, &ContactsManager::send_get_channel_message_stats_query, r_dc_id.move_as_ok(),
6596                  full_message_id, is_dark, std::move(promise));
6597   });
6598   get_channel_statistics_dc_id(full_message_id.get_dialog_id(), false, std::move(dc_id_promise));
6599 }
6600 
send_get_channel_message_stats_query(DcId dc_id,FullMessageId full_message_id,bool is_dark,Promise<td_api::object_ptr<td_api::messageStatistics>> && promise)6601 void ContactsManager::send_get_channel_message_stats_query(
6602     DcId dc_id, FullMessageId full_message_id, bool is_dark,
6603     Promise<td_api::object_ptr<td_api::messageStatistics>> &&promise) {
6604   TRY_STATUS_PROMISE(promise, G()->close_status());
6605 
6606   auto dialog_id = full_message_id.get_dialog_id();
6607   if (!td_->messages_manager_->have_message_force(full_message_id, "send_get_channel_message_stats_query")) {
6608     return promise.set_error(Status::Error(400, "Message not found"));
6609   }
6610   if (!td_->messages_manager_->can_get_message_statistics(full_message_id)) {
6611     return promise.set_error(Status::Error(400, "Message statistics is inaccessible"));
6612   }
6613   CHECK(dialog_id.get_type() == DialogType::Channel);
6614   td_->create_handler<GetMessageStatsQuery>(std::move(promise))
6615       ->send(dialog_id.get_channel_id(), full_message_id.get_message_id(), is_dark, dc_id);
6616 }
6617 
load_statistics_graph(DialogId dialog_id,string token,int64 x,Promise<td_api::object_ptr<td_api::StatisticalGraph>> && promise)6618 void ContactsManager::load_statistics_graph(DialogId dialog_id, string token, int64 x,
6619                                             Promise<td_api::object_ptr<td_api::StatisticalGraph>> &&promise) {
6620   auto dc_id_promise = PromiseCreator::lambda([actor_id = actor_id(this), token = std::move(token), x,
6621                                                promise = std::move(promise)](Result<DcId> r_dc_id) mutable {
6622     if (r_dc_id.is_error()) {
6623       return promise.set_error(r_dc_id.move_as_error());
6624     }
6625     send_closure(actor_id, &ContactsManager::send_load_async_graph_query, r_dc_id.move_as_ok(), std::move(token), x,
6626                  std::move(promise));
6627   });
6628   get_channel_statistics_dc_id(dialog_id, false, std::move(dc_id_promise));
6629 }
6630 
send_load_async_graph_query(DcId dc_id,string token,int64 x,Promise<td_api::object_ptr<td_api::StatisticalGraph>> && promise)6631 void ContactsManager::send_load_async_graph_query(DcId dc_id, string token, int64 x,
6632                                                   Promise<td_api::object_ptr<td_api::StatisticalGraph>> &&promise) {
6633   TRY_STATUS_PROMISE(promise, G()->close_status());
6634 
6635   td_->create_handler<LoadAsyncGraphQuery>(std::move(promise))->send(token, x, dc_id);
6636 }
6637 
report_channel_spam(ChannelId channel_id,const vector<MessageId> & message_ids,Promise<Unit> && promise)6638 void ContactsManager::report_channel_spam(ChannelId channel_id, const vector<MessageId> &message_ids,
6639                                           Promise<Unit> &&promise) {
6640   auto c = get_channel(channel_id);
6641   if (c == nullptr) {
6642     return promise.set_error(Status::Error(400, "Supergroup not found"));
6643   }
6644   if (!c->is_megagroup) {
6645     return promise.set_error(Status::Error(400, "Spam can be reported only in supergroups"));
6646   }
6647 
6648   if (message_ids.empty()) {
6649     return promise.set_error(Status::Error(400, "Message list is empty"));
6650   }
6651 
6652   DialogId sender_dialog_id;
6653   vector<MessageId> server_message_ids;
6654   for (auto &message_id : message_ids) {
6655     if (message_id.is_valid_scheduled()) {
6656       return promise.set_error(Status::Error(400, "Can't report scheduled messages"));
6657     }
6658 
6659     if (!message_id.is_valid()) {
6660       return promise.set_error(Status::Error(400, "Message not found"));
6661     }
6662 
6663     if (!message_id.is_server()) {
6664       continue;
6665     }
6666 
6667     auto current_sender_dialog_id = td_->messages_manager_->get_message_sender({DialogId(channel_id), message_id});
6668     if (!current_sender_dialog_id.is_valid()) {
6669       continue;
6670     }
6671     if (sender_dialog_id.is_valid()) {
6672       if (current_sender_dialog_id != sender_dialog_id) {
6673         return promise.set_error(Status::Error(400, "All messages nust be from the same sender"));
6674       }
6675     } else {
6676       sender_dialog_id = current_sender_dialog_id;
6677     }
6678 
6679     server_message_ids.push_back(message_id);
6680   }
6681   if (server_message_ids.empty()) {
6682     return promise.set_value(Unit());
6683   }
6684   CHECK(sender_dialog_id.is_valid());
6685 
6686   if (!td_->messages_manager_->have_input_peer(sender_dialog_id, AccessRights::Know)) {
6687     return promise.set_error(Status::Error(400, "Have no access to the user"));
6688   }
6689   if (sender_dialog_id == DialogId(get_my_id())) {
6690     return promise.set_error(Status::Error(400, "Can't report self"));
6691   }
6692 
6693   td_->create_handler<ReportChannelSpamQuery>(std::move(promise))
6694       ->send(channel_id, sender_dialog_id, server_message_ids);
6695 }
6696 
delete_chat(ChatId chat_id,Promise<Unit> && promise)6697 void ContactsManager::delete_chat(ChatId chat_id, Promise<Unit> &&promise) {
6698   auto c = get_chat(chat_id);
6699   if (c == nullptr) {
6700     return promise.set_error(Status::Error(400, "Chat info not found"));
6701   }
6702   if (!get_chat_status(c).is_creator()) {
6703     return promise.set_error(Status::Error(400, "Not enough rights to delete the chat"));
6704   }
6705   if (!c->is_active) {
6706     return promise.set_error(Status::Error(400, "Chat is already deactivated"));
6707   }
6708 
6709   td_->create_handler<DeleteChatQuery>(std::move(promise))->send(chat_id);
6710 }
6711 
delete_channel(ChannelId channel_id,Promise<Unit> && promise)6712 void ContactsManager::delete_channel(ChannelId channel_id, Promise<Unit> &&promise) {
6713   auto c = get_channel(channel_id);
6714   if (c == nullptr) {
6715     return promise.set_error(Status::Error(400, "Chat info not found"));
6716   }
6717   if (!get_channel_status(c).is_creator()) {
6718     return promise.set_error(Status::Error(400, "Not enough rights to delete the chat"));
6719   }
6720 
6721   td_->create_handler<DeleteChannelQuery>(std::move(promise))->send(channel_id);
6722 }
6723 
delete_dialog(DialogId dialog_id,Promise<Unit> && promise)6724 void ContactsManager::delete_dialog(DialogId dialog_id, Promise<Unit> &&promise) {
6725   if (!td_->messages_manager_->have_dialog_force(dialog_id, "delete_dialog")) {
6726     return promise.set_error(Status::Error(400, "Chat not found"));
6727   }
6728 
6729   switch (dialog_id.get_type()) {
6730     case DialogType::User:
6731       return td_->messages_manager_->delete_dialog_history(dialog_id, true, true, std::move(promise));
6732     case DialogType::Chat:
6733       return delete_chat(dialog_id.get_chat_id(), std::move(promise));
6734     case DialogType::Channel:
6735       return delete_channel(dialog_id.get_channel_id(), std::move(promise));
6736     case DialogType::SecretChat:
6737       send_closure(td_->secret_chats_manager_, &SecretChatsManager::cancel_chat, dialog_id.get_secret_chat_id(), true,
6738                    std::move(promise));
6739       return;
6740     default:
6741       UNREACHABLE();
6742   }
6743 }
6744 
add_chat_participant(ChatId chat_id,UserId user_id,int32 forward_limit,Promise<Unit> && promise)6745 void ContactsManager::add_chat_participant(ChatId chat_id, UserId user_id, int32 forward_limit,
6746                                            Promise<Unit> &&promise) {
6747   const Chat *c = get_chat(chat_id);
6748   if (c == nullptr) {
6749     return promise.set_error(Status::Error(400, "Chat info not found"));
6750   }
6751   if (!c->is_active) {
6752     return promise.set_error(Status::Error(400, "Chat is deactivated"));
6753   }
6754   if (forward_limit < 0) {
6755     return promise.set_error(Status::Error(400, "Can't forward negative number of messages"));
6756   }
6757   if (user_id != get_my_id()) {
6758     if (!get_chat_permissions(c).can_invite_users()) {
6759       return promise.set_error(Status::Error(400, "Not enough rights to invite members to the group chat"));
6760     }
6761   } else if (c->status.is_banned()) {
6762     return promise.set_error(Status::Error(400, "User was kicked from the chat"));
6763   }
6764   // TODO upper bound on forward_limit
6765 
6766   auto input_user = get_input_user(user_id);
6767   if (input_user == nullptr) {
6768     return promise.set_error(Status::Error(400, "User not found"));
6769   }
6770 
6771   // TODO invoke after
6772   td_->create_handler<AddChatUserQuery>(std::move(promise))->send(chat_id, std::move(input_user), forward_limit);
6773 }
6774 
add_channel_participant(ChannelId channel_id,UserId user_id,const DialogParticipantStatus & old_status,Promise<Unit> && promise)6775 void ContactsManager::add_channel_participant(ChannelId channel_id, UserId user_id,
6776                                               const DialogParticipantStatus &old_status, Promise<Unit> &&promise) {
6777   if (td_->auth_manager_->is_bot()) {
6778     return promise.set_error(Status::Error(400, "Bots can't add new chat members"));
6779   }
6780 
6781   const Channel *c = get_channel(channel_id);
6782   if (c == nullptr) {
6783     return promise.set_error(Status::Error(400, "Chat info not found"));
6784   }
6785   auto input_user = get_input_user(user_id);
6786   if (input_user == nullptr) {
6787     return promise.set_error(Status::Error(400, "User not found"));
6788   }
6789 
6790   if (user_id == get_my_id()) {
6791     // join the channel
6792     if (get_channel_status(c).is_banned()) {
6793       return promise.set_error(Status::Error(400, "Can't return to kicked from chat"));
6794     }
6795 
6796     speculative_add_channel_user(channel_id, user_id, DialogParticipantStatus::Member(), c->status);
6797     td_->create_handler<JoinChannelQuery>(std::move(promise))->send(channel_id);
6798     return;
6799   }
6800 
6801   if (!get_channel_permissions(c).can_invite_users()) {
6802     return promise.set_error(Status::Error(400, "Not enough rights to invite members to the supergroup chat"));
6803   }
6804 
6805   speculative_add_channel_user(channel_id, user_id, DialogParticipantStatus::Member(), old_status);
6806   vector<tl_object_ptr<telegram_api::InputUser>> input_users;
6807   input_users.push_back(std::move(input_user));
6808   td_->create_handler<InviteToChannelQuery>(std::move(promise))->send(channel_id, std::move(input_users));
6809 }
6810 
add_channel_participants(ChannelId channel_id,const vector<UserId> & user_ids,Promise<Unit> && promise)6811 void ContactsManager::add_channel_participants(ChannelId channel_id, const vector<UserId> &user_ids,
6812                                                Promise<Unit> &&promise) {
6813   if (td_->auth_manager_->is_bot()) {
6814     return promise.set_error(Status::Error(400, "Bots can't add new chat members"));
6815   }
6816 
6817   const Channel *c = get_channel(channel_id);
6818   if (c == nullptr) {
6819     return promise.set_error(Status::Error(400, "Chat info not found"));
6820   }
6821 
6822   if (!get_channel_permissions(c).can_invite_users()) {
6823     return promise.set_error(Status::Error(400, "Not enough rights to invite members to the supergroup chat"));
6824   }
6825 
6826   vector<tl_object_ptr<telegram_api::InputUser>> input_users;
6827   for (auto user_id : user_ids) {
6828     auto input_user = get_input_user(user_id);
6829     if (input_user == nullptr) {
6830       return promise.set_error(Status::Error(400, "User not found"));
6831     }
6832 
6833     if (user_id == get_my_id()) {
6834       // can't invite self
6835       continue;
6836     }
6837     input_users.push_back(std::move(input_user));
6838   }
6839 
6840   if (input_users.empty()) {
6841     return promise.set_value(Unit());
6842   }
6843 
6844   td_->create_handler<InviteToChannelQuery>(std::move(promise))->send(channel_id, std::move(input_users));
6845 }
6846 
set_channel_participant_status(ChannelId channel_id,DialogId participant_dialog_id,DialogParticipantStatus status,Promise<Unit> && promise)6847 void ContactsManager::set_channel_participant_status(ChannelId channel_id, DialogId participant_dialog_id,
6848                                                      DialogParticipantStatus status, Promise<Unit> &&promise) {
6849   auto c = get_channel(channel_id);
6850   if (c == nullptr) {
6851     return promise.set_error(Status::Error(400, "Chat info not found"));
6852   }
6853 
6854   if (participant_dialog_id == DialogId(get_my_id())) {
6855     // fast path is needed, because get_channel_status may return Creator, while GetChannelParticipantQuery returning Left
6856     return set_channel_participant_status_impl(channel_id, participant_dialog_id, std::move(status),
6857                                                get_channel_status(c), std::move(promise));
6858   }
6859   if (participant_dialog_id.get_type() != DialogType::User) {
6860     if (status.is_administrator() || status.is_member() || status.is_restricted()) {
6861       return promise.set_error(Status::Error(400, "Other chats can be only banned or unbanned"));
6862     }
6863     // always pretend that old_status is different
6864     return restrict_channel_participant(
6865         channel_id, participant_dialog_id, std::move(status),
6866         status.is_banned() ? DialogParticipantStatus::Left() : DialogParticipantStatus::Banned(0), std::move(promise));
6867   }
6868 
6869   auto input_peer = td_->messages_manager_->get_input_peer(participant_dialog_id, AccessRights::Read);
6870   if (input_peer == nullptr) {
6871     return promise.set_error(Status::Error(400, "Member not found"));
6872   }
6873 
6874   auto on_result_promise =
6875       PromiseCreator::lambda([actor_id = actor_id(this), channel_id, participant_dialog_id, status,
6876                               promise = std::move(promise)](Result<DialogParticipant> r_dialog_participant) mutable {
6877         // ResultHandlers are cleared before managers, so it is safe to capture this
6878         if (r_dialog_participant.is_error()) {
6879           return promise.set_error(r_dialog_participant.move_as_error());
6880         }
6881 
6882         send_closure(actor_id, &ContactsManager::set_channel_participant_status_impl, channel_id, participant_dialog_id,
6883                      std::move(status), r_dialog_participant.ok().status_, std::move(promise));
6884       });
6885 
6886   td_->create_handler<GetChannelParticipantQuery>(std::move(on_result_promise))
6887       ->send(channel_id, participant_dialog_id, std::move(input_peer));
6888 }
6889 
set_channel_participant_status_impl(ChannelId channel_id,DialogId participant_dialog_id,DialogParticipantStatus status,DialogParticipantStatus old_status,Promise<Unit> && promise)6890 void ContactsManager::set_channel_participant_status_impl(ChannelId channel_id, DialogId participant_dialog_id,
6891                                                           DialogParticipantStatus status,
6892                                                           DialogParticipantStatus old_status, Promise<Unit> &&promise) {
6893   if (old_status == status && !old_status.is_creator()) {
6894     return promise.set_value(Unit());
6895   }
6896 
6897   LOG(INFO) << "Change status of " << participant_dialog_id << " in " << channel_id << " from " << old_status << " to "
6898             << status;
6899   bool need_add = false;
6900   bool need_promote = false;
6901   bool need_restrict = false;
6902   if (status.is_creator() || old_status.is_creator()) {
6903     if (!old_status.is_creator()) {
6904       return promise.set_error(Status::Error(400, "Can't add another owner to the chat"));
6905     }
6906     if (!status.is_creator()) {
6907       return promise.set_error(Status::Error(400, "Can't remove chat owner"));
6908     }
6909     if (participant_dialog_id != DialogId(get_my_id())) {
6910       return promise.set_error(Status::Error(400, "Not enough rights to edit chat owner rights"));
6911     }
6912     if (status.is_member() == old_status.is_member()) {
6913       // change rank and is_anonymous
6914       auto input_user = get_input_user(get_my_id());
6915       CHECK(input_user != nullptr);
6916       td_->create_handler<EditChannelAdminQuery>(std::move(promise))->send(channel_id, std::move(input_user), status);
6917       return;
6918     }
6919     if (status.is_member()) {
6920       // creator not member -> creator member
6921       need_add = true;
6922     } else {
6923       // creator member -> creator not member
6924       need_restrict = true;
6925     }
6926   } else if (status.is_administrator()) {
6927     need_promote = true;
6928   } else if (!status.is_member() || status.is_restricted()) {
6929     if (status.is_member() && !old_status.is_member()) {
6930       // TODO there is no way in server API to invite someone and change restrictions
6931       // we need to first add user and change restrictions again after that
6932       // but if restrictions aren't changed, then adding is enough
6933       auto copy_old_status = old_status;
6934       copy_old_status.set_is_member(true);
6935       if (copy_old_status == status) {
6936         need_add = true;
6937       } else {
6938         need_restrict = true;
6939       }
6940     } else {
6941       need_restrict = true;
6942     }
6943   } else {
6944     // regular member
6945     if (old_status.is_administrator()) {
6946       need_promote = true;
6947     } else if (old_status.is_restricted() || old_status.is_banned()) {
6948       need_restrict = true;
6949     } else {
6950       CHECK(!old_status.is_member());
6951       need_add = true;
6952     }
6953   }
6954 
6955   if (need_promote) {
6956     if (participant_dialog_id.get_type() != DialogType::User) {
6957       return promise.set_error(Status::Error(400, "Can't promote chats to chat administrators"));
6958     }
6959     return promote_channel_participant(channel_id, participant_dialog_id.get_user_id(), status, old_status,
6960                                        std::move(promise));
6961   } else if (need_restrict) {
6962     return restrict_channel_participant(channel_id, participant_dialog_id, std::move(status), std::move(old_status),
6963                                         std::move(promise));
6964   } else {
6965     CHECK(need_add);
6966     if (participant_dialog_id.get_type() != DialogType::User) {
6967       return promise.set_error(Status::Error(400, "Can't add chats as chat members"));
6968     }
6969     return add_channel_participant(channel_id, participant_dialog_id.get_user_id(), old_status, std::move(promise));
6970   }
6971 }
6972 
promote_channel_participant(ChannelId channel_id,UserId user_id,const DialogParticipantStatus & status,const DialogParticipantStatus & old_status,Promise<Unit> && promise)6973 void ContactsManager::promote_channel_participant(ChannelId channel_id, UserId user_id,
6974                                                   const DialogParticipantStatus &status,
6975                                                   const DialogParticipantStatus &old_status, Promise<Unit> &&promise) {
6976   LOG(INFO) << "Promote " << user_id << " in " << channel_id << " from " << old_status << " to " << status;
6977   const Channel *c = get_channel(channel_id);
6978   CHECK(c != nullptr);
6979 
6980   if (user_id == get_my_id()) {
6981     if (status.is_administrator()) {
6982       return promise.set_error(Status::Error(400, "Can't promote self"));
6983     }
6984     CHECK(status.is_member());
6985     // allow to demote self. TODO is it allowed server-side?
6986   } else {
6987     if (!get_channel_permissions(c).can_promote_members()) {
6988       return promise.set_error(Status::Error(400, "Not enough rights"));
6989     }
6990 
6991     CHECK(!old_status.is_creator());
6992     CHECK(!status.is_creator());
6993   }
6994 
6995   auto input_user = get_input_user(user_id);
6996   if (input_user == nullptr) {
6997     return promise.set_error(Status::Error(400, "User not found"));
6998   }
6999 
7000   speculative_add_channel_user(channel_id, user_id, status, old_status);
7001   td_->create_handler<EditChannelAdminQuery>(std::move(promise))->send(channel_id, std::move(input_user), status);
7002 }
7003 
set_chat_participant_status(ChatId chat_id,UserId user_id,DialogParticipantStatus status,Promise<Unit> && promise)7004 void ContactsManager::set_chat_participant_status(ChatId chat_id, UserId user_id, DialogParticipantStatus status,
7005                                                   Promise<Unit> &&promise) {
7006   if (!status.is_member()) {
7007     return delete_chat_participant(chat_id, user_id, false, std::move(promise));
7008   }
7009   if (status.is_creator()) {
7010     return promise.set_error(Status::Error(400, "Can't change owner in basic group chats"));
7011   }
7012   if (status.is_restricted()) {
7013     return promise.set_error(Status::Error(400, "Can't restrict users in basic group chats"));
7014   }
7015 
7016   auto c = get_chat(chat_id);
7017   if (c == nullptr) {
7018     return promise.set_error(Status::Error(400, "Chat info not found"));
7019   }
7020   if (!c->is_active) {
7021     return promise.set_error(Status::Error(400, "Chat is deactivated"));
7022   }
7023 
7024   auto chat_full = get_chat_full(chat_id);
7025   if (chat_full == nullptr) {
7026     auto load_chat_full_promise =
7027         PromiseCreator::lambda([actor_id = actor_id(this), chat_id, user_id, status = std::move(status),
7028                                 promise = std::move(promise)](Result<Unit> &&result) mutable {
7029           if (result.is_error()) {
7030             promise.set_error(result.move_as_error());
7031           } else {
7032             send_closure(actor_id, &ContactsManager::set_chat_participant_status, chat_id, user_id, status,
7033                          std::move(promise));
7034           }
7035         });
7036     return load_chat_full(chat_id, false, std::move(load_chat_full_promise), "set_chat_participant_status");
7037   }
7038 
7039   auto participant = get_chat_full_participant(chat_full, DialogId(user_id));
7040   if (participant == nullptr && !status.is_administrator()) {
7041     // the user isn't a member, but needs to be added
7042     return add_chat_participant(chat_id, user_id, 0, std::move(promise));
7043   }
7044 
7045   if (!get_chat_permissions(c).can_promote_members()) {
7046     return promise.set_error(Status::Error(400, "Need owner rights in the group chat"));
7047   }
7048 
7049   if (user_id == get_my_id()) {
7050     return promise.set_error(Status::Error(400, "Can't promote or demote self"));
7051   }
7052 
7053   if (participant == nullptr) {
7054     // the user must be added first
7055     CHECK(status.is_administrator());
7056     auto add_chat_participant_promise = PromiseCreator::lambda(
7057         [actor_id = actor_id(this), chat_id, user_id, promise = std::move(promise)](Result<Unit> &&result) mutable {
7058           if (result.is_error()) {
7059             promise.set_error(result.move_as_error());
7060           } else {
7061             send_closure(actor_id, &ContactsManager::send_edit_chat_admin_query, chat_id, user_id, true,
7062                          std::move(promise));
7063           }
7064         });
7065     return add_chat_participant(chat_id, user_id, 0, std::move(add_chat_participant_promise));
7066   }
7067 
7068   send_edit_chat_admin_query(chat_id, user_id, status.is_administrator(), std::move(promise));
7069 }
7070 
send_edit_chat_admin_query(ChatId chat_id,UserId user_id,bool is_administrator,Promise<Unit> && promise)7071 void ContactsManager::send_edit_chat_admin_query(ChatId chat_id, UserId user_id, bool is_administrator,
7072                                                  Promise<Unit> &&promise) {
7073   auto input_user = get_input_user(user_id);
7074   if (input_user == nullptr) {
7075     return promise.set_error(Status::Error(400, "User not found"));
7076   }
7077 
7078   td_->create_handler<EditChatAdminQuery>(std::move(promise))->send(chat_id, std::move(input_user), is_administrator);
7079 }
7080 
can_transfer_ownership(Promise<CanTransferOwnershipResult> && promise)7081 void ContactsManager::can_transfer_ownership(Promise<CanTransferOwnershipResult> &&promise) {
7082   auto request_promise = PromiseCreator::lambda([promise = std::move(promise)](Result<Unit> r_result) mutable {
7083     CHECK(r_result.is_error());
7084 
7085     auto error = r_result.move_as_error();
7086     CanTransferOwnershipResult result;
7087     if (error.message() == "PASSWORD_HASH_INVALID") {
7088       return promise.set_value(std::move(result));
7089     }
7090     if (error.message() == "PASSWORD_MISSING") {
7091       result.type = CanTransferOwnershipResult::Type::PasswordNeeded;
7092       return promise.set_value(std::move(result));
7093     }
7094     if (begins_with(error.message(), "PASSWORD_TOO_FRESH_")) {
7095       result.type = CanTransferOwnershipResult::Type::PasswordTooFresh;
7096       result.retry_after = to_integer<int32>(error.message().substr(Slice("PASSWORD_TOO_FRESH_").size()));
7097       if (result.retry_after < 0) {
7098         result.retry_after = 0;
7099       }
7100       return promise.set_value(std::move(result));
7101     }
7102     if (begins_with(error.message(), "SESSION_TOO_FRESH_")) {
7103       result.type = CanTransferOwnershipResult::Type::SessionTooFresh;
7104       result.retry_after = to_integer<int32>(error.message().substr(Slice("SESSION_TOO_FRESH_").size()));
7105       if (result.retry_after < 0) {
7106         result.retry_after = 0;
7107       }
7108       return promise.set_value(std::move(result));
7109     }
7110     promise.set_error(std::move(error));
7111   });
7112 
7113   td_->create_handler<CanEditChannelCreatorQuery>(std::move(request_promise))->send();
7114 }
7115 
get_can_transfer_ownership_result_object(CanTransferOwnershipResult result)7116 td_api::object_ptr<td_api::CanTransferOwnershipResult> ContactsManager::get_can_transfer_ownership_result_object(
7117     CanTransferOwnershipResult result) {
7118   switch (result.type) {
7119     case CanTransferOwnershipResult::Type::Ok:
7120       return td_api::make_object<td_api::canTransferOwnershipResultOk>();
7121     case CanTransferOwnershipResult::Type::PasswordNeeded:
7122       return td_api::make_object<td_api::canTransferOwnershipResultPasswordNeeded>();
7123     case CanTransferOwnershipResult::Type::PasswordTooFresh:
7124       return td_api::make_object<td_api::canTransferOwnershipResultPasswordTooFresh>(result.retry_after);
7125     case CanTransferOwnershipResult::Type::SessionTooFresh:
7126       return td_api::make_object<td_api::canTransferOwnershipResultSessionTooFresh>(result.retry_after);
7127     default:
7128       UNREACHABLE();
7129       return nullptr;
7130   }
7131 }
7132 
transfer_dialog_ownership(DialogId dialog_id,UserId user_id,const string & password,Promise<Unit> && promise)7133 void ContactsManager::transfer_dialog_ownership(DialogId dialog_id, UserId user_id, const string &password,
7134                                                 Promise<Unit> &&promise) {
7135   if (!td_->messages_manager_->have_dialog_force(dialog_id, "transfer_dialog_ownership")) {
7136     return promise.set_error(Status::Error(400, "Chat not found"));
7137   }
7138   if (!have_user_force(user_id)) {
7139     return promise.set_error(Status::Error(400, "User not found"));
7140   }
7141   if (is_user_bot(user_id)) {
7142     return promise.set_error(Status::Error(400, "User is a bot"));
7143   }
7144   if (is_user_deleted(user_id)) {
7145     return promise.set_error(Status::Error(400, "User is deleted"));
7146   }
7147   if (password.empty()) {
7148     return promise.set_error(Status::Error(400, "PASSWORD_HASH_INVALID"));
7149   }
7150 
7151   switch (dialog_id.get_type()) {
7152     case DialogType::User:
7153     case DialogType::Chat:
7154     case DialogType::SecretChat:
7155       return promise.set_error(Status::Error(400, "Can't transfer chat ownership"));
7156     case DialogType::Channel:
7157       send_closure(
7158           td_->password_manager_, &PasswordManager::get_input_check_password_srp, password,
7159           PromiseCreator::lambda([actor_id = actor_id(this), channel_id = dialog_id.get_channel_id(), user_id,
7160                                   promise = std::move(promise)](
7161                                      Result<tl_object_ptr<telegram_api::InputCheckPasswordSRP>> result) mutable {
7162             if (result.is_error()) {
7163               return promise.set_error(result.move_as_error());
7164             }
7165             send_closure(actor_id, &ContactsManager::transfer_channel_ownership, channel_id, user_id,
7166                          result.move_as_ok(), std::move(promise));
7167           }));
7168       break;
7169     case DialogType::None:
7170     default:
7171       UNREACHABLE();
7172   }
7173 }
7174 
transfer_channel_ownership(ChannelId channel_id,UserId user_id,tl_object_ptr<telegram_api::InputCheckPasswordSRP> input_check_password,Promise<Unit> && promise)7175 void ContactsManager::transfer_channel_ownership(
7176     ChannelId channel_id, UserId user_id, tl_object_ptr<telegram_api::InputCheckPasswordSRP> input_check_password,
7177     Promise<Unit> &&promise) {
7178   TRY_STATUS_PROMISE(promise, G()->close_status());
7179 
7180   td_->create_handler<EditChannelCreatorQuery>(std::move(promise))
7181       ->send(channel_id, user_id, std::move(input_check_password));
7182 }
7183 
can_manage_dialog_invite_links(DialogId dialog_id,bool creator_only)7184 Status ContactsManager::can_manage_dialog_invite_links(DialogId dialog_id, bool creator_only) {
7185   if (!td_->messages_manager_->have_dialog_force(dialog_id, "can_manage_dialog_invite_links")) {
7186     return Status::Error(400, "Chat not found");
7187   }
7188 
7189   switch (dialog_id.get_type()) {
7190     case DialogType::User:
7191       return Status::Error(400, "Can't invite members to a private chat");
7192     case DialogType::Chat: {
7193       const Chat *c = get_chat(dialog_id.get_chat_id());
7194       if (c == nullptr) {
7195         return Status::Error(400, "Chat info not found");
7196       }
7197       if (!c->is_active) {
7198         return Status::Error(400, "Chat is deactivated");
7199       }
7200       bool have_rights = creator_only ? c->status.is_creator() : c->status.can_manage_invite_links();
7201       if (!have_rights) {
7202         return Status::Error(400, "Not enough rights to manage chat invite link");
7203       }
7204       break;
7205     }
7206     case DialogType::Channel: {
7207       const Channel *c = get_channel(dialog_id.get_channel_id());
7208       if (c == nullptr) {
7209         return Status::Error(400, "Chat info not found");
7210       }
7211       bool have_rights = creator_only ? c->status.is_creator() : c->status.can_manage_invite_links();
7212       if (!have_rights) {
7213         return Status::Error(400, "Not enough rights to manage chat invite link");
7214       }
7215       break;
7216     }
7217     case DialogType::SecretChat:
7218       return Status::Error(400, "Can't invite members to a secret chat");
7219     case DialogType::None:
7220     default:
7221       UNREACHABLE();
7222   }
7223   return Status::OK();
7224 }
7225 
export_dialog_invite_link(DialogId dialog_id,string title,int32 expire_date,int32 usage_limit,bool creates_join_request,bool is_permanent,Promise<td_api::object_ptr<td_api::chatInviteLink>> && promise)7226 void ContactsManager::export_dialog_invite_link(DialogId dialog_id, string title, int32 expire_date, int32 usage_limit,
7227                                                 bool creates_join_request, bool is_permanent,
7228                                                 Promise<td_api::object_ptr<td_api::chatInviteLink>> &&promise) {
7229   get_me(PromiseCreator::lambda([actor_id = actor_id(this), dialog_id, title = std::move(title), expire_date,
7230                                  usage_limit, creates_join_request, is_permanent,
7231                                  promise = std::move(promise)](Result<Unit> &&result) mutable {
7232     if (result.is_error()) {
7233       promise.set_error(result.move_as_error());
7234     } else {
7235       send_closure(actor_id, &ContactsManager::export_dialog_invite_link_impl, dialog_id, std::move(title), expire_date,
7236                    usage_limit, creates_join_request, is_permanent, std::move(promise));
7237     }
7238   }));
7239 }
7240 
export_dialog_invite_link_impl(DialogId dialog_id,string title,int32 expire_date,int32 usage_limit,bool creates_join_request,bool is_permanent,Promise<td_api::object_ptr<td_api::chatInviteLink>> && promise)7241 void ContactsManager::export_dialog_invite_link_impl(DialogId dialog_id, string title, int32 expire_date,
7242                                                      int32 usage_limit, bool creates_join_request, bool is_permanent,
7243                                                      Promise<td_api::object_ptr<td_api::chatInviteLink>> &&promise) {
7244   TRY_STATUS_PROMISE(promise, G()->close_status());
7245   TRY_STATUS_PROMISE(promise, can_manage_dialog_invite_links(dialog_id));
7246   if (creates_join_request && usage_limit > 0) {
7247     return promise.set_error(
7248         Status::Error(400, "Member limit can't be specified for links requiring administrator approval"));
7249   }
7250 
7251   auto new_title = clean_name(std::move(title), MAX_INVITE_LINK_TITLE_LENGTH);
7252   td_->create_handler<ExportChatInviteQuery>(std::move(promise))
7253       ->send(dialog_id, new_title, expire_date, usage_limit, creates_join_request, is_permanent);
7254 }
7255 
edit_dialog_invite_link(DialogId dialog_id,const string & invite_link,string title,int32 expire_date,int32 usage_limit,bool creates_join_request,Promise<td_api::object_ptr<td_api::chatInviteLink>> && promise)7256 void ContactsManager::edit_dialog_invite_link(DialogId dialog_id, const string &invite_link, string title,
7257                                               int32 expire_date, int32 usage_limit, bool creates_join_request,
7258                                               Promise<td_api::object_ptr<td_api::chatInviteLink>> &&promise) {
7259   TRY_STATUS_PROMISE(promise, can_manage_dialog_invite_links(dialog_id));
7260   if (creates_join_request && usage_limit > 0) {
7261     return promise.set_error(
7262         Status::Error(400, "Member limit can't be specified for links requiring administrator approval"));
7263   }
7264 
7265   if (invite_link.empty()) {
7266     return promise.set_error(Status::Error(400, "Invite link must be non-empty"));
7267   }
7268 
7269   auto new_title = clean_name(std::move(title), MAX_INVITE_LINK_TITLE_LENGTH);
7270   td_->create_handler<EditChatInviteLinkQuery>(std::move(promise))
7271       ->send(dialog_id, invite_link, new_title, expire_date, usage_limit, creates_join_request);
7272 }
7273 
get_dialog_invite_link(DialogId dialog_id,const string & invite_link,Promise<td_api::object_ptr<td_api::chatInviteLink>> && promise)7274 void ContactsManager::get_dialog_invite_link(DialogId dialog_id, const string &invite_link,
7275                                              Promise<td_api::object_ptr<td_api::chatInviteLink>> &&promise) {
7276   TRY_STATUS_PROMISE(promise, can_manage_dialog_invite_links(dialog_id, false));
7277 
7278   if (invite_link.empty()) {
7279     return promise.set_error(Status::Error(400, "Invite link must be non-empty"));
7280   }
7281 
7282   td_->create_handler<GetExportedChatInviteQuery>(std::move(promise))->send(dialog_id, invite_link);
7283 }
7284 
get_dialog_invite_link_counts(DialogId dialog_id,Promise<td_api::object_ptr<td_api::chatInviteLinkCounts>> && promise)7285 void ContactsManager::get_dialog_invite_link_counts(
7286     DialogId dialog_id, Promise<td_api::object_ptr<td_api::chatInviteLinkCounts>> &&promise) {
7287   TRY_STATUS_PROMISE(promise, can_manage_dialog_invite_links(dialog_id, true));
7288 
7289   td_->create_handler<GetChatAdminWithInvitesQuery>(std::move(promise))->send(dialog_id);
7290 }
7291 
get_dialog_invite_links(DialogId dialog_id,UserId creator_user_id,bool is_revoked,int32 offset_date,const string & offset_invite_link,int32 limit,Promise<td_api::object_ptr<td_api::chatInviteLinks>> && promise)7292 void ContactsManager::get_dialog_invite_links(DialogId dialog_id, UserId creator_user_id, bool is_revoked,
7293                                               int32 offset_date, const string &offset_invite_link, int32 limit,
7294                                               Promise<td_api::object_ptr<td_api::chatInviteLinks>> &&promise) {
7295   TRY_STATUS_PROMISE(promise, can_manage_dialog_invite_links(dialog_id, creator_user_id != get_my_id()));
7296 
7297   if (!have_input_user(creator_user_id)) {
7298     return promise.set_error(Status::Error(400, "Administrator user not found"));
7299   }
7300 
7301   if (limit <= 0) {
7302     return promise.set_error(Status::Error(400, "Parameter limit must be positive"));
7303   }
7304 
7305   td_->create_handler<GetExportedChatInvitesQuery>(std::move(promise))
7306       ->send(dialog_id, creator_user_id, is_revoked, offset_date, offset_invite_link, limit);
7307 }
7308 
get_dialog_invite_link_users(DialogId dialog_id,const string & invite_link,td_api::object_ptr<td_api::chatInviteLinkMember> offset_member,int32 limit,Promise<td_api::object_ptr<td_api::chatInviteLinkMembers>> && promise)7309 void ContactsManager::get_dialog_invite_link_users(
7310     DialogId dialog_id, const string &invite_link, td_api::object_ptr<td_api::chatInviteLinkMember> offset_member,
7311     int32 limit, Promise<td_api::object_ptr<td_api::chatInviteLinkMembers>> &&promise) {
7312   TRY_STATUS_PROMISE(promise, can_manage_dialog_invite_links(dialog_id));
7313 
7314   if (limit <= 0) {
7315     return promise.set_error(Status::Error(400, "Parameter limit must be positive"));
7316   }
7317 
7318   if (invite_link.empty()) {
7319     return promise.set_error(Status::Error(400, "Invite link must be non-empty"));
7320   }
7321 
7322   UserId offset_user_id;
7323   int32 offset_date = 0;
7324   if (offset_member != nullptr) {
7325     offset_user_id = UserId(offset_member->user_id_);
7326     offset_date = offset_member->joined_chat_date_;
7327   }
7328 
7329   td_->create_handler<GetChatInviteImportersQuery>(std::move(promise))
7330       ->send(dialog_id, invite_link, offset_date, offset_user_id, limit);
7331 }
7332 
get_dialog_join_requests(DialogId dialog_id,const string & invite_link,const string & query,td_api::object_ptr<td_api::chatJoinRequest> offset_request,int32 limit,Promise<td_api::object_ptr<td_api::chatJoinRequests>> && promise)7333 void ContactsManager::get_dialog_join_requests(DialogId dialog_id, const string &invite_link, const string &query,
7334                                                td_api::object_ptr<td_api::chatJoinRequest> offset_request, int32 limit,
7335                                                Promise<td_api::object_ptr<td_api::chatJoinRequests>> &&promise) {
7336   TRY_STATUS_PROMISE(promise, can_manage_dialog_invite_links(dialog_id));
7337 
7338   if (limit <= 0) {
7339     return promise.set_error(Status::Error(400, "Parameter limit must be positive"));
7340   }
7341 
7342   UserId offset_user_id;
7343   int32 offset_date = 0;
7344   if (offset_request != nullptr) {
7345     offset_user_id = UserId(offset_request->user_id_);
7346     offset_date = offset_request->date_;
7347   }
7348 
7349   td_->create_handler<GetChatJoinRequestsQuery>(std::move(promise))
7350       ->send(dialog_id, invite_link, query, offset_date, offset_user_id, limit);
7351 }
7352 
process_dialog_join_request(DialogId dialog_id,UserId user_id,bool approve,Promise<Unit> && promise)7353 void ContactsManager::process_dialog_join_request(DialogId dialog_id, UserId user_id, bool approve,
7354                                                   Promise<Unit> &&promise) {
7355   TRY_STATUS_PROMISE(promise, can_manage_dialog_invite_links(dialog_id));
7356   td_->create_handler<HideChatJoinRequestQuery>(std::move(promise))->send(dialog_id, user_id, approve);
7357 }
7358 
process_dialog_join_requests(DialogId dialog_id,const string & invite_link,bool approve,Promise<Unit> && promise)7359 void ContactsManager::process_dialog_join_requests(DialogId dialog_id, const string &invite_link, bool approve,
7360                                                    Promise<Unit> &&promise) {
7361   TRY_STATUS_PROMISE(promise, can_manage_dialog_invite_links(dialog_id));
7362   td_->create_handler<HideAllChatJoinRequestsQuery>(std::move(promise))->send(dialog_id, invite_link, approve);
7363 }
7364 
revoke_dialog_invite_link(DialogId dialog_id,const string & invite_link,Promise<td_api::object_ptr<td_api::chatInviteLinks>> && promise)7365 void ContactsManager::revoke_dialog_invite_link(DialogId dialog_id, const string &invite_link,
7366                                                 Promise<td_api::object_ptr<td_api::chatInviteLinks>> &&promise) {
7367   TRY_STATUS_PROMISE(promise, can_manage_dialog_invite_links(dialog_id));
7368 
7369   if (invite_link.empty()) {
7370     return promise.set_error(Status::Error(400, "Invite link must be non-empty"));
7371   }
7372 
7373   td_->create_handler<RevokeChatInviteLinkQuery>(std::move(promise))->send(dialog_id, invite_link);
7374 }
7375 
delete_revoked_dialog_invite_link(DialogId dialog_id,const string & invite_link,Promise<Unit> && promise)7376 void ContactsManager::delete_revoked_dialog_invite_link(DialogId dialog_id, const string &invite_link,
7377                                                         Promise<Unit> &&promise) {
7378   TRY_STATUS_PROMISE(promise, can_manage_dialog_invite_links(dialog_id));
7379 
7380   if (invite_link.empty()) {
7381     return promise.set_error(Status::Error(400, "Invite link must be non-empty"));
7382   }
7383 
7384   td_->create_handler<DeleteExportedChatInviteQuery>(std::move(promise))->send(dialog_id, invite_link);
7385 }
7386 
delete_all_revoked_dialog_invite_links(DialogId dialog_id,UserId creator_user_id,Promise<Unit> && promise)7387 void ContactsManager::delete_all_revoked_dialog_invite_links(DialogId dialog_id, UserId creator_user_id,
7388                                                              Promise<Unit> &&promise) {
7389   TRY_STATUS_PROMISE(promise, can_manage_dialog_invite_links(dialog_id, creator_user_id != get_my_id()));
7390 
7391   if (!have_input_user(creator_user_id)) {
7392     return promise.set_error(Status::Error(400, "Administrator user not found"));
7393   }
7394 
7395   td_->create_handler<DeleteRevokedExportedChatInvitesQuery>(std::move(promise))->send(dialog_id, creator_user_id);
7396 }
7397 
check_dialog_invite_link(const string & invite_link,Promise<Unit> && promise) const7398 void ContactsManager::check_dialog_invite_link(const string &invite_link, Promise<Unit> &&promise) const {
7399   if (invite_link_infos_.count(invite_link) > 0) {
7400     return promise.set_value(Unit());
7401   }
7402 
7403   if (!DialogInviteLink::is_valid_invite_link(invite_link)) {
7404     return promise.set_error(Status::Error(400, "Wrong invite link"));
7405   }
7406 
7407   td_->create_handler<CheckChatInviteQuery>(std::move(promise))->send(invite_link);
7408 }
7409 
import_dialog_invite_link(const string & invite_link,Promise<DialogId> && promise)7410 void ContactsManager::import_dialog_invite_link(const string &invite_link, Promise<DialogId> &&promise) {
7411   if (!DialogInviteLink::is_valid_invite_link(invite_link)) {
7412     return promise.set_error(Status::Error(400, "Wrong invite link"));
7413   }
7414 
7415   td_->create_handler<ImportChatInviteQuery>(std::move(promise))->send(invite_link);
7416 }
7417 
delete_chat_participant(ChatId chat_id,UserId user_id,bool revoke_messages,Promise<Unit> && promise)7418 void ContactsManager::delete_chat_participant(ChatId chat_id, UserId user_id, bool revoke_messages,
7419                                               Promise<Unit> &&promise) {
7420   const Chat *c = get_chat(chat_id);
7421   if (c == nullptr) {
7422     return promise.set_error(Status::Error(400, "Chat info not found"));
7423   }
7424   if (!c->is_active) {
7425     return promise.set_error(Status::Error(400, "Chat is deactivated"));
7426   }
7427   auto my_id = get_my_id();
7428   if (c->status.is_left()) {
7429     if (user_id == my_id) {
7430       if (revoke_messages) {
7431         return td_->messages_manager_->delete_dialog_history(DialogId(chat_id), true, true, std::move(promise));
7432       }
7433       return promise.set_value(Unit());
7434     } else {
7435       return promise.set_error(Status::Error(400, "Not in the chat"));
7436     }
7437   }
7438   if (user_id != my_id) {
7439     auto my_status = get_chat_permissions(c);
7440     if (!my_status.is_creator()) {  // creator can delete anyone
7441       auto participant = get_chat_participant(chat_id, user_id);
7442       if (participant != nullptr) {  // if have no information about participant, just send request to the server
7443         /*
7444         TODO
7445         if (c->everyone_is_administrator) {
7446           // if all are administrators, only invited by me participants can be deleted
7447           if (participant->inviter_user_id_ != my_id) {
7448             return promise.set_error(Status::Error(400, "Need to be inviter of a user to kick it from a basic group"));
7449           }
7450         } else {
7451           // otherwise, only creator can kick administrators
7452           if (participant->status_.is_administrator()) {
7453             return promise.set_error(
7454                 Status::Error(400, "Only the creator of a basic group can kick group administrators"));
7455           }
7456           // regular users can be kicked by administrators and their inviters
7457           if (!my_status.is_administrator() && participant->inviter_user_id_ != my_id) {
7458             return promise.set_error(Status::Error(400, "Need to be inviter of a user to kick it from a basic group"));
7459           }
7460         }
7461         */
7462       }
7463     }
7464   }
7465   auto input_user = get_input_user(user_id);
7466   if (input_user == nullptr) {
7467     return promise.set_error(Status::Error(400, "User not found"));
7468   }
7469 
7470   // TODO invoke after
7471   td_->create_handler<DeleteChatUserQuery>(std::move(promise))->send(chat_id, std::move(input_user), revoke_messages);
7472 }
7473 
restrict_channel_participant(ChannelId channel_id,DialogId participant_dialog_id,DialogParticipantStatus && status,DialogParticipantStatus && old_status,Promise<Unit> && promise)7474 void ContactsManager::restrict_channel_participant(ChannelId channel_id, DialogId participant_dialog_id,
7475                                                    DialogParticipantStatus &&status,
7476                                                    DialogParticipantStatus &&old_status, Promise<Unit> &&promise) {
7477   TRY_STATUS_PROMISE(promise, G()->close_status());
7478 
7479   LOG(INFO) << "Restrict " << participant_dialog_id << " in " << channel_id << " from " << old_status << " to "
7480             << status;
7481   const Channel *c = get_channel(channel_id);
7482   if (c == nullptr) {
7483     return promise.set_error(Status::Error(400, "Chat info not found"));
7484   }
7485   if (!c->status.is_member() && !c->status.is_creator()) {
7486     if (participant_dialog_id == DialogId(get_my_id())) {
7487       if (status.is_member()) {
7488         return promise.set_error(Status::Error(400, "Can't unrestrict self"));
7489       }
7490       return promise.set_value(Unit());
7491     } else {
7492       return promise.set_error(Status::Error(400, "Not in the chat"));
7493     }
7494   }
7495   auto input_peer = td_->messages_manager_->get_input_peer(participant_dialog_id, AccessRights::Know);
7496   if (input_peer == nullptr) {
7497     return promise.set_error(Status::Error(400, "Member not found"));
7498   }
7499 
7500   if (participant_dialog_id == DialogId(get_my_id())) {
7501     if (status.is_restricted() || status.is_banned()) {
7502       return promise.set_error(Status::Error(400, "Can't restrict self"));
7503     }
7504     if (status.is_member()) {
7505       return promise.set_error(Status::Error(400, "Can't unrestrict self"));
7506     }
7507 
7508     // leave the channel
7509     speculative_add_channel_user(channel_id, participant_dialog_id.get_user_id(), status, c->status);
7510     td_->create_handler<LeaveChannelQuery>(std::move(promise))->send(channel_id);
7511     return;
7512   }
7513 
7514   switch (participant_dialog_id.get_type()) {
7515     case DialogType::User:
7516       // ok;
7517       break;
7518     case DialogType::Channel:
7519       if (status.is_administrator() || status.is_member() || status.is_restricted()) {
7520         return promise.set_error(Status::Error(400, "Other chats can be only banned or unbanned"));
7521       }
7522       break;
7523     default:
7524       return promise.set_error(Status::Error(400, "Can't restrict the chat"));
7525   }
7526 
7527   CHECK(!old_status.is_creator());
7528   CHECK(!status.is_creator());
7529 
7530   if (!get_channel_permissions(c).can_restrict_members()) {
7531     return promise.set_error(Status::Error(400, "Not enough rights to restrict/unrestrict chat member"));
7532   }
7533 
7534   if (old_status.is_member() && !status.is_member() && !status.is_banned()) {
7535     // we can't make participant Left without kicking it first
7536     auto on_result_promise = PromiseCreator::lambda([actor_id = actor_id(this), channel_id, participant_dialog_id,
7537                                                      status = std::move(status),
7538                                                      promise = std::move(promise)](Result<> result) mutable {
7539       if (result.is_error()) {
7540         return promise.set_error(result.move_as_error());
7541       }
7542 
7543       create_actor<SleepActor>(
7544           "RestrictChannelParticipantSleepActor", 1.0,
7545           PromiseCreator::lambda([actor_id, channel_id, participant_dialog_id, status = std::move(status),
7546                                   promise = std::move(promise)](Result<> result) mutable {
7547             if (result.is_error()) {
7548               return promise.set_error(result.move_as_error());
7549             }
7550 
7551             send_closure(actor_id, &ContactsManager::restrict_channel_participant, channel_id, participant_dialog_id,
7552                          std::move(status), DialogParticipantStatus::Banned(0), std::move(promise));
7553           }))
7554           .release();
7555     });
7556 
7557     promise = std::move(on_result_promise);
7558     status = DialogParticipantStatus::Banned(G()->unix_time() + 60);
7559   }
7560 
7561   if (participant_dialog_id.get_type() == DialogType::User) {
7562     speculative_add_channel_user(channel_id, participant_dialog_id.get_user_id(), status, old_status);
7563   }
7564   td_->create_handler<EditChannelBannedQuery>(std::move(promise))->send(channel_id, std::move(input_peer), status);
7565 }
7566 
migrate_chat_to_megagroup(ChatId chat_id,Promise<Unit> & promise)7567 ChannelId ContactsManager::migrate_chat_to_megagroup(ChatId chat_id, Promise<Unit> &promise) {
7568   auto c = get_chat(chat_id);
7569   if (c == nullptr) {
7570     promise.set_error(Status::Error(400, "Chat info not found"));
7571     return ChannelId();
7572   }
7573 
7574   if (!c->status.is_creator()) {
7575     promise.set_error(Status::Error(400, "Need creator rights in the chat"));
7576     return ChannelId();
7577   }
7578 
7579   if (c->migrated_to_channel_id.is_valid()) {
7580     return c->migrated_to_channel_id;
7581   }
7582 
7583   td_->create_handler<MigrateChatQuery>(std::move(promise))->send(chat_id);
7584   return ChannelId();
7585 }
7586 
get_channel_ids(vector<tl_object_ptr<telegram_api::Chat>> && chats,const char * source)7587 vector<ChannelId> ContactsManager::get_channel_ids(vector<tl_object_ptr<telegram_api::Chat>> &&chats,
7588                                                    const char *source) {
7589   vector<ChannelId> channel_ids;
7590   for (auto &chat : chats) {
7591     auto channel_id = get_channel_id(chat);
7592     if (!channel_id.is_valid()) {
7593       LOG(ERROR) << "Receive invalid " << channel_id << " from " << source << " in " << to_string(chat);
7594       continue;
7595     }
7596     on_get_chat(std::move(chat), source);
7597     if (have_channel(channel_id)) {
7598       channel_ids.push_back(channel_id);
7599     }
7600   }
7601   return channel_ids;
7602 }
7603 
get_dialog_ids(vector<tl_object_ptr<telegram_api::Chat>> && chats,const char * source)7604 vector<DialogId> ContactsManager::get_dialog_ids(vector<tl_object_ptr<telegram_api::Chat>> &&chats,
7605                                                  const char *source) {
7606   vector<DialogId> dialog_ids;
7607   for (auto &chat : chats) {
7608     auto channel_id = get_channel_id(chat);
7609     if (!channel_id.is_valid()) {
7610       auto chat_id = get_chat_id(chat);
7611       if (!chat_id.is_valid()) {
7612         LOG(ERROR) << "Receive invalid chat from " << source << " in " << to_string(chat);
7613       } else {
7614         dialog_ids.push_back(DialogId(chat_id));
7615       }
7616     } else {
7617       dialog_ids.push_back(DialogId(channel_id));
7618     }
7619     on_get_chat(std::move(chat), source);
7620   }
7621   return dialog_ids;
7622 }
7623 
return_created_public_dialogs(Promise<td_api::object_ptr<td_api::chats>> && promise,const vector<ChannelId> & channel_ids)7624 void ContactsManager::return_created_public_dialogs(Promise<td_api::object_ptr<td_api::chats>> &&promise,
7625                                                     const vector<ChannelId> &channel_ids) {
7626   if (!promise) {
7627     return;
7628   }
7629 
7630   auto total_count = narrow_cast<int32>(channel_ids.size());
7631   promise.set_value(td_api::make_object<td_api::chats>(
7632       total_count, transform(channel_ids, [](ChannelId channel_id) { return DialogId(channel_id).get(); })));
7633 }
7634 
get_created_public_dialogs(PublicDialogType type,Promise<td_api::object_ptr<td_api::chats>> && promise,bool from_binlog)7635 void ContactsManager::get_created_public_dialogs(PublicDialogType type,
7636                                                  Promise<td_api::object_ptr<td_api::chats>> &&promise,
7637                                                  bool from_binlog) {
7638   auto index = static_cast<int32>(type);
7639   if (created_public_channels_inited_[index]) {
7640     return return_created_public_dialogs(std::move(promise), created_public_channels_[index]);
7641   }
7642 
7643   if (get_created_public_channels_queries_[index].empty() && G()->parameters().use_chat_info_db) {
7644     auto pmc_key = PSTRING() << "public_channels" << index;
7645     auto str = G()->td_db()->get_binlog_pmc()->get(pmc_key);
7646     if (!str.empty()) {
7647       auto r_channel_ids = transform(full_split(Slice(str), ','), [](Slice str) -> Result<ChannelId> {
7648         TRY_RESULT(channel_id_int, to_integer_safe<int64>(str));
7649         ChannelId channel_id(channel_id_int);
7650         if (!channel_id.is_valid()) {
7651           return Status::Error("Have invalid channel ID");
7652         }
7653         return channel_id;
7654       });
7655       if (std::any_of(r_channel_ids.begin(), r_channel_ids.end(),
7656                       [](auto &r_channel_id) { return r_channel_id.is_error(); })) {
7657         LOG(ERROR) << "Can't parse " << str;
7658         G()->td_db()->get_binlog_pmc()->erase(pmc_key);
7659       } else {
7660         Dependencies dependencies;
7661         vector<ChannelId> channel_ids;
7662         for (auto &r_channel_id : r_channel_ids) {
7663           auto channel_id = r_channel_id.move_as_ok();
7664           add_dialog_and_dependencies(dependencies, DialogId(channel_id));
7665           channel_ids.push_back(channel_id);
7666         }
7667         if (!resolve_dependencies_force(td_, dependencies, "get_created_public_dialogs")) {
7668           G()->td_db()->get_binlog_pmc()->erase(pmc_key);
7669         } else {
7670           created_public_channels_[index] = std::move(channel_ids);
7671           created_public_channels_inited_[index] = true;
7672 
7673           if (type == PublicDialogType::HasUsername) {
7674             update_created_public_broadcasts();
7675           }
7676 
7677           if (from_binlog) {
7678             return return_created_public_dialogs(std::move(promise), created_public_channels_[index]);
7679           }
7680         }
7681       }
7682     }
7683   }
7684 
7685   reload_created_public_dialogs(type, std::move(promise));
7686 }
7687 
reload_created_public_dialogs(PublicDialogType type,Promise<td_api::object_ptr<td_api::chats>> && promise)7688 void ContactsManager::reload_created_public_dialogs(PublicDialogType type,
7689                                                     Promise<td_api::object_ptr<td_api::chats>> &&promise) {
7690   auto index = static_cast<int32>(type);
7691   get_created_public_channels_queries_[index].push_back(std::move(promise));
7692   if (get_created_public_channels_queries_[index].size() == 1) {
7693     auto query_promise = PromiseCreator::lambda([actor_id = actor_id(this), type](Result<Unit> &&result) {
7694       send_closure(actor_id, &ContactsManager::finish_get_created_public_dialogs, type, std::move(result));
7695     });
7696     td_->create_handler<GetCreatedPublicChannelsQuery>(std::move(query_promise))->send(type, false);
7697   }
7698 }
7699 
finish_get_created_public_dialogs(PublicDialogType type,Result<Unit> && result)7700 void ContactsManager::finish_get_created_public_dialogs(PublicDialogType type, Result<Unit> &&result) {
7701   auto index = static_cast<int32>(type);
7702   auto promises = std::move(get_created_public_channels_queries_[index]);
7703   reset_to_empty(get_created_public_channels_queries_[index]);
7704   if (G()->close_flag()) {
7705     result = G()->close_status();
7706   }
7707   if (result.is_error()) {
7708     for (auto &promise : promises) {
7709       promise.set_error(result.error().clone());
7710     }
7711     return;
7712   }
7713 
7714   CHECK(created_public_channels_inited_[index]);
7715   for (auto &promise : promises) {
7716     return_created_public_dialogs(std::move(promise), created_public_channels_[index]);
7717   }
7718 }
7719 
update_created_public_channels(Channel * c,ChannelId channel_id)7720 void ContactsManager::update_created_public_channels(Channel *c, ChannelId channel_id) {
7721   if (created_public_channels_inited_[0]) {
7722     bool was_changed = false;
7723     if (c->username.empty() || !c->status.is_creator()) {
7724       was_changed = td::remove(created_public_channels_[0], channel_id);
7725     } else {
7726       if (!td::contains(created_public_channels_[0], channel_id)) {
7727         created_public_channels_[0].push_back(channel_id);
7728         was_changed = true;
7729       }
7730     }
7731     if (was_changed) {
7732       if (!c->is_megagroup) {
7733         update_created_public_broadcasts();
7734       }
7735 
7736       save_created_public_channels(PublicDialogType::HasUsername);
7737 
7738       reload_created_public_dialogs(PublicDialogType::HasUsername, Promise<td_api::object_ptr<td_api::chats>>());
7739     }
7740   }
7741   if (created_public_channels_inited_[1]) {
7742     bool was_changed = false;
7743     if (!c->has_location || !c->status.is_creator()) {
7744       was_changed = td::remove(created_public_channels_[1], channel_id);
7745     } else {
7746       if (!td::contains(created_public_channels_[1], channel_id)) {
7747         created_public_channels_[1].push_back(channel_id);
7748         was_changed = true;
7749       }
7750     }
7751     if (was_changed) {
7752       save_created_public_channels(PublicDialogType::IsLocationBased);
7753 
7754       reload_created_public_dialogs(PublicDialogType::IsLocationBased, Promise<td_api::object_ptr<td_api::chats>>());
7755     }
7756   }
7757 }
7758 
on_get_created_public_channels(PublicDialogType type,vector<tl_object_ptr<telegram_api::Chat>> && chats)7759 void ContactsManager::on_get_created_public_channels(PublicDialogType type,
7760                                                      vector<tl_object_ptr<telegram_api::Chat>> &&chats) {
7761   auto index = static_cast<int32>(type);
7762   auto channel_ids = get_channel_ids(std::move(chats), "on_get_created_public_channels");
7763   if (created_public_channels_inited_[index] && created_public_channels_[index] == channel_ids) {
7764     return;
7765   }
7766   for (auto channel_id : channel_ids) {
7767     td_->messages_manager_->force_create_dialog(DialogId(channel_id), "on_get_created_public_channels");
7768   }
7769   created_public_channels_[index] = std::move(channel_ids);
7770   created_public_channels_inited_[index] = true;
7771 
7772   if (type == PublicDialogType::HasUsername) {
7773     update_created_public_broadcasts();
7774   }
7775 
7776   save_created_public_channels(type);
7777 }
7778 
save_created_public_channels(PublicDialogType type)7779 void ContactsManager::save_created_public_channels(PublicDialogType type) {
7780   auto index = static_cast<int32>(type);
7781   CHECK(created_public_channels_inited_[index]);
7782   if (G()->parameters().use_chat_info_db) {
7783     G()->td_db()->get_binlog_pmc()->set(
7784         PSTRING() << "public_channels" << index,
7785         implode(
7786             transform(created_public_channels_[index], [](auto channel_id) { return PSTRING() << channel_id.get(); }),
7787             ','));
7788   }
7789 }
7790 
update_created_public_broadcasts()7791 void ContactsManager::update_created_public_broadcasts() {
7792   CHECK(created_public_channels_inited_[0]);
7793   vector<ChannelId> channel_ids;
7794   for (auto &channel_id : created_public_channels_[0]) {
7795     auto c = get_channel(channel_id);
7796     if (!c->is_megagroup) {
7797       channel_ids.push_back(channel_id);
7798     }
7799   }
7800   send_closure_later(G()->messages_manager(), &MessagesManager::on_update_created_public_broadcasts,
7801                      std::move(channel_ids));
7802 }
7803 
check_created_public_dialogs_limit(PublicDialogType type,Promise<Unit> && promise)7804 void ContactsManager::check_created_public_dialogs_limit(PublicDialogType type, Promise<Unit> &&promise) {
7805   td_->create_handler<GetCreatedPublicChannelsQuery>(std::move(promise))->send(type, true);
7806 }
7807 
get_dialogs_for_discussion(Promise<Unit> && promise)7808 vector<DialogId> ContactsManager::get_dialogs_for_discussion(Promise<Unit> &&promise) {
7809   if (dialogs_for_discussion_inited_) {
7810     promise.set_value(Unit());
7811     return transform(dialogs_for_discussion_, [&](DialogId dialog_id) {
7812       td_->messages_manager_->force_create_dialog(dialog_id, "get_dialogs_for_discussion");
7813       return dialog_id;
7814     });
7815   }
7816 
7817   td_->create_handler<GetGroupsForDiscussionQuery>(std::move(promise))->send();
7818   return {};
7819 }
7820 
on_get_dialogs_for_discussion(vector<tl_object_ptr<telegram_api::Chat>> && chats)7821 void ContactsManager::on_get_dialogs_for_discussion(vector<tl_object_ptr<telegram_api::Chat>> &&chats) {
7822   dialogs_for_discussion_inited_ = true;
7823   dialogs_for_discussion_ = get_dialog_ids(std::move(chats), "on_get_dialogs_for_discussion");
7824 }
7825 
update_dialogs_for_discussion(DialogId dialog_id,bool is_suitable)7826 void ContactsManager::update_dialogs_for_discussion(DialogId dialog_id, bool is_suitable) {
7827   if (!dialogs_for_discussion_inited_) {
7828     return;
7829   }
7830 
7831   if (is_suitable) {
7832     if (!td::contains(dialogs_for_discussion_, dialog_id)) {
7833       LOG(DEBUG) << "Add " << dialog_id << " to list of suitable discussion chats";
7834       dialogs_for_discussion_.insert(dialogs_for_discussion_.begin(), dialog_id);
7835     }
7836   } else {
7837     if (td::remove(dialogs_for_discussion_, dialog_id)) {
7838       LOG(DEBUG) << "Remove " << dialog_id << " from list of suitable discussion chats";
7839     }
7840   }
7841 }
7842 
get_inactive_channels(Promise<Unit> && promise)7843 vector<DialogId> ContactsManager::get_inactive_channels(Promise<Unit> &&promise) {
7844   if (inactive_channels_inited_) {
7845     promise.set_value(Unit());
7846     return transform(inactive_channels_, [&](ChannelId channel_id) {
7847       DialogId dialog_id{channel_id};
7848       td_->messages_manager_->force_create_dialog(dialog_id, "get_inactive_channels");
7849       return dialog_id;
7850     });
7851   }
7852 
7853   td_->create_handler<GetInactiveChannelsQuery>(std::move(promise))->send();
7854   return {};
7855 }
7856 
on_get_inactive_channels(vector<tl_object_ptr<telegram_api::Chat>> && chats)7857 void ContactsManager::on_get_inactive_channels(vector<tl_object_ptr<telegram_api::Chat>> &&chats) {
7858   inactive_channels_inited_ = true;
7859   inactive_channels_ = get_channel_ids(std::move(chats), "on_get_inactive_channels");
7860 }
7861 
remove_inactive_channel(ChannelId channel_id)7862 void ContactsManager::remove_inactive_channel(ChannelId channel_id) {
7863   if (inactive_channels_inited_ && td::remove(inactive_channels_, channel_id)) {
7864     LOG(DEBUG) << "Remove " << channel_id << " from list of inactive channels";
7865   }
7866 }
7867 
remove_dialog_suggested_action(SuggestedAction action)7868 void ContactsManager::remove_dialog_suggested_action(SuggestedAction action) {
7869   auto it = dialog_suggested_actions_.find(action.dialog_id_);
7870   if (it == dialog_suggested_actions_.end()) {
7871     return;
7872   }
7873   remove_suggested_action(it->second, action);
7874   if (it->second.empty()) {
7875     dialog_suggested_actions_.erase(it);
7876   }
7877 }
7878 
dismiss_dialog_suggested_action(SuggestedAction action,Promise<Unit> && promise)7879 void ContactsManager::dismiss_dialog_suggested_action(SuggestedAction action, Promise<Unit> &&promise) {
7880   auto dialog_id = action.dialog_id_;
7881   if (!td_->messages_manager_->have_dialog(dialog_id)) {
7882     return promise.set_error(Status::Error(400, "Chat not found"));
7883   }
7884   if (!td_->messages_manager_->have_input_peer(dialog_id, AccessRights::Read)) {
7885     return promise.set_error(Status::Error(400, "Can't access the chat"));
7886   }
7887 
7888   auto it = dialog_suggested_actions_.find(dialog_id);
7889   if (it == dialog_suggested_actions_.end() || !td::contains(it->second, action)) {
7890     return promise.set_value(Unit());
7891   }
7892 
7893   auto action_str = action.get_suggested_action_str();
7894   if (action_str.empty()) {
7895     return promise.set_value(Unit());
7896   }
7897 
7898   auto &queries = dismiss_suggested_action_queries_[dialog_id];
7899   queries.push_back(std::move(promise));
7900   if (queries.size() == 1) {
7901     auto query_promise = PromiseCreator::lambda([actor_id = actor_id(this), action](Result<Unit> &&result) {
7902       send_closure(actor_id, &ContactsManager::on_dismiss_suggested_action, action, std::move(result));
7903     });
7904     td_->create_handler<DismissSuggestionQuery>(std::move(query_promise))->send(std::move(action));
7905   }
7906 }
7907 
on_dismiss_suggested_action(SuggestedAction action,Result<Unit> && result)7908 void ContactsManager::on_dismiss_suggested_action(SuggestedAction action, Result<Unit> &&result) {
7909   auto it = dismiss_suggested_action_queries_.find(action.dialog_id_);
7910   CHECK(it != dismiss_suggested_action_queries_.end());
7911   auto promises = std::move(it->second);
7912   dismiss_suggested_action_queries_.erase(it);
7913 
7914   if (result.is_error()) {
7915     for (auto &promise : promises) {
7916       promise.set_error(result.error().clone());
7917     }
7918     return;
7919   }
7920 
7921   remove_dialog_suggested_action(action);
7922 
7923   for (auto &promise : promises) {
7924     promise.set_value(Unit());
7925   }
7926 }
7927 
on_import_contacts_finished(int64 random_id,vector<UserId> imported_contact_user_ids,vector<int32> unimported_contact_invites)7928 void ContactsManager::on_import_contacts_finished(int64 random_id, vector<UserId> imported_contact_user_ids,
7929                                                   vector<int32> unimported_contact_invites) {
7930   LOG(INFO) << "Contacts import with random_id " << random_id
7931             << " has finished: " << format::as_array(imported_contact_user_ids);
7932   if (random_id == 0) {
7933     // import from change_imported_contacts
7934     all_imported_contacts_ = std::move(next_all_imported_contacts_);
7935     next_all_imported_contacts_.clear();
7936 
7937     auto result_size = imported_contacts_unique_id_.size();
7938     auto unique_size = all_imported_contacts_.size();
7939     auto add_size = imported_contacts_pos_.size();
7940 
7941     imported_contact_user_ids_.resize(result_size);
7942     unimported_contact_invites_.resize(result_size);
7943 
7944     CHECK(imported_contact_user_ids.size() == add_size);
7945     CHECK(unimported_contact_invites.size() == add_size);
7946     CHECK(imported_contacts_unique_id_.size() == result_size);
7947 
7948     std::unordered_map<size_t, int32> unique_id_to_unimported_contact_invites;
7949     for (size_t i = 0; i < add_size; i++) {
7950       auto unique_id = imported_contacts_pos_[i];
7951       get_user_id_object(imported_contact_user_ids[i], "on_import_contacts_finished");  // to ensure updateUser
7952       all_imported_contacts_[unique_id].set_user_id(imported_contact_user_ids[i]);
7953       unique_id_to_unimported_contact_invites[unique_id] = unimported_contact_invites[i];
7954     }
7955 
7956     if (G()->parameters().use_chat_info_db) {
7957       G()->td_db()->get_binlog()->force_sync(PromiseCreator::lambda(
7958           [log_event = log_event_store(all_imported_contacts_).as_slice().str()](Result<> result) mutable {
7959             if (result.is_ok()) {
7960               LOG(INFO) << "Save imported contacts to database";
7961               G()->td_db()->get_sqlite_pmc()->set("user_imported_contacts", std::move(log_event), Auto());
7962             }
7963           }));
7964     }
7965 
7966     for (size_t i = 0; i < result_size; i++) {
7967       auto unique_id = imported_contacts_unique_id_[i];
7968       CHECK(unique_id < unique_size);
7969       imported_contact_user_ids_[i] = all_imported_contacts_[unique_id].get_user_id();
7970       auto it = unique_id_to_unimported_contact_invites.find(unique_id);
7971       if (it == unique_id_to_unimported_contact_invites.end()) {
7972         unimported_contact_invites_[i] = 0;
7973       } else {
7974         unimported_contact_invites_[i] = it->second;
7975       }
7976     }
7977     return;
7978   }
7979 
7980   auto it = imported_contacts_.find(random_id);
7981   CHECK(it != imported_contacts_.end());
7982   CHECK(it->second.first.empty());
7983   CHECK(it->second.second.empty());
7984   imported_contacts_[random_id] = {std::move(imported_contact_user_ids), std::move(unimported_contact_invites)};
7985 }
7986 
on_deleted_contacts(const vector<UserId> & deleted_contact_user_ids)7987 void ContactsManager::on_deleted_contacts(const vector<UserId> &deleted_contact_user_ids) {
7988   LOG(INFO) << "Contacts deletion has finished for " << deleted_contact_user_ids;
7989 
7990   for (auto user_id : deleted_contact_user_ids) {
7991     auto u = get_user(user_id);
7992     CHECK(u != nullptr);
7993     if (!u->is_contact) {
7994       continue;
7995     }
7996 
7997     LOG(INFO) << "Drop contact with " << user_id;
7998     on_update_user_is_contact(u, user_id, false, false);
7999     CHECK(u->is_is_contact_changed);
8000     u->cache_version = 0;
8001     u->is_repaired = false;
8002     update_user(u, user_id);
8003     CHECK(!u->is_contact);
8004     CHECK(!contacts_hints_.has_key(user_id.get()));
8005   }
8006 }
8007 
save_next_contacts_sync_date()8008 void ContactsManager::save_next_contacts_sync_date() {
8009   if (G()->close_flag()) {
8010     return;
8011   }
8012   if (!G()->parameters().use_chat_info_db) {
8013     return;
8014   }
8015   G()->td_db()->get_binlog_pmc()->set("next_contacts_sync_date", to_string(next_contacts_sync_date_));
8016 }
8017 
on_get_contacts(tl_object_ptr<telegram_api::contacts_Contacts> && new_contacts)8018 void ContactsManager::on_get_contacts(tl_object_ptr<telegram_api::contacts_Contacts> &&new_contacts) {
8019   next_contacts_sync_date_ = G()->unix_time() + Random::fast(70000, 100000);
8020 
8021   CHECK(new_contacts != nullptr);
8022   if (new_contacts->get_id() == telegram_api::contacts_contactsNotModified::ID) {
8023     if (saved_contact_count_ == -1) {
8024       saved_contact_count_ = 0;
8025     }
8026     on_get_contacts_finished(contacts_hints_.size());
8027     td_->create_handler<GetContactsStatusesQuery>()->send();
8028     return;
8029   }
8030 
8031   auto contacts = move_tl_object_as<telegram_api::contacts_contacts>(new_contacts);
8032   std::unordered_set<UserId, UserIdHash> contact_user_ids;
8033   for (auto &user : contacts->users_) {
8034     auto user_id = get_user_id(user);
8035     if (!user_id.is_valid()) {
8036       LOG(ERROR) << "Receive invalid " << user_id;
8037       continue;
8038     }
8039     contact_user_ids.insert(user_id);
8040   }
8041   on_get_users(std::move(contacts->users_), "on_get_contacts");
8042 
8043   UserId my_id = get_my_id();
8044   for (auto &p : users_) {
8045     UserId user_id = p.first;
8046     User *u = p.second.get();
8047     bool should_be_contact = contact_user_ids.count(user_id) == 1;
8048     if (u->is_contact != should_be_contact) {
8049       if (u->is_contact) {
8050         LOG(INFO) << "Drop contact with " << user_id;
8051         if (user_id != my_id) {
8052           LOG_CHECK(contacts_hints_.has_key(user_id.get()))
8053               << my_id << " " << user_id << " " << to_string(get_user_object(user_id, u));
8054         }
8055         on_update_user_is_contact(u, user_id, false, false);
8056         CHECK(u->is_is_contact_changed);
8057         u->cache_version = 0;
8058         u->is_repaired = false;
8059         update_user(u, user_id);
8060         CHECK(!u->is_contact);
8061         if (user_id != my_id) {
8062           CHECK(!contacts_hints_.has_key(user_id.get()));
8063         }
8064       } else {
8065         LOG(ERROR) << "Receive non-contact " << user_id << " in the list of contacts";
8066       }
8067     }
8068   }
8069 
8070   saved_contact_count_ = contacts->saved_count_;
8071   on_get_contacts_finished(std::numeric_limits<size_t>::max());
8072 }
8073 
save_contacts_to_database()8074 void ContactsManager::save_contacts_to_database() {
8075   if (!G()->parameters().use_chat_info_db || !are_contacts_loaded_) {
8076     return;
8077   }
8078 
8079   LOG(INFO) << "Schedule save contacts to database";
8080   vector<UserId> user_ids =
8081       transform(contacts_hints_.search_empty(100000).second, [](int64 key) { return UserId(key); });
8082 
8083   G()->td_db()->get_binlog_pmc()->set("saved_contact_count", to_string(saved_contact_count_));
8084   G()->td_db()->get_binlog()->force_sync(PromiseCreator::lambda([user_ids = std::move(user_ids)](Result<> result) {
8085     if (result.is_ok()) {
8086       LOG(INFO) << "Save contacts to database";
8087       G()->td_db()->get_sqlite_pmc()->set(
8088           "user_contacts", log_event_store(user_ids).as_slice().str(), PromiseCreator::lambda([](Result<> result) {
8089             if (result.is_ok()) {
8090               send_closure(G()->contacts_manager(), &ContactsManager::save_next_contacts_sync_date);
8091             }
8092           }));
8093     }
8094   }));
8095 }
8096 
on_get_contacts_failed(Status error)8097 void ContactsManager::on_get_contacts_failed(Status error) {
8098   CHECK(error.is_error());
8099   next_contacts_sync_date_ = G()->unix_time() + Random::fast(5, 10);
8100   auto promises = std::move(load_contacts_queries_);
8101   load_contacts_queries_.clear();
8102   for (auto &promise : promises) {
8103     promise.set_error(error.clone());
8104   }
8105 }
8106 
on_load_contacts_from_database(string value)8107 void ContactsManager::on_load_contacts_from_database(string value) {
8108   if (G()->close_flag()) {
8109     return;
8110   }
8111   if (value.empty()) {
8112     reload_contacts(true);
8113     return;
8114   }
8115 
8116   vector<UserId> user_ids;
8117   log_event_parse(user_ids, value).ensure();
8118 
8119   LOG(INFO) << "Successfully loaded " << user_ids.size() << " contacts from database";
8120 
8121   load_contact_users_multipromise_.add_promise(PromiseCreator::lambda(
8122       [actor_id = actor_id(this), expected_contact_count = user_ids.size()](Result<Unit> result) {
8123         if (result.is_ok()) {
8124           send_closure(actor_id, &ContactsManager::on_get_contacts_finished, expected_contact_count);
8125         }
8126       }));
8127 
8128   auto lock_promise = load_contact_users_multipromise_.get_promise();
8129 
8130   for (auto user_id : user_ids) {
8131     get_user(user_id, 3, load_contact_users_multipromise_.get_promise());
8132   }
8133 
8134   lock_promise.set_value(Unit());
8135 }
8136 
on_get_contacts_finished(size_t expected_contact_count)8137 void ContactsManager::on_get_contacts_finished(size_t expected_contact_count) {
8138   LOG(INFO) << "Finished to get " << contacts_hints_.size() << " contacts out of expected " << expected_contact_count;
8139   are_contacts_loaded_ = true;
8140   auto promises = std::move(load_contacts_queries_);
8141   load_contacts_queries_.clear();
8142   for (auto &promise : promises) {
8143     promise.set_value(Unit());
8144   }
8145   if (expected_contact_count != contacts_hints_.size()) {
8146     save_contacts_to_database();
8147   }
8148 }
8149 
on_get_contacts_statuses(vector<tl_object_ptr<telegram_api::contactStatus>> && statuses)8150 void ContactsManager::on_get_contacts_statuses(vector<tl_object_ptr<telegram_api::contactStatus>> &&statuses) {
8151   auto my_user_id = get_my_id();
8152   for (auto &status : statuses) {
8153     UserId user_id(status->user_id_);
8154     if (user_id != my_user_id) {
8155       on_update_user_online(user_id, std::move(status->status_));
8156     }
8157   }
8158   save_next_contacts_sync_date();
8159 }
8160 
on_update_online_status_privacy()8161 void ContactsManager::on_update_online_status_privacy() {
8162   td_->create_handler<GetContactsStatusesQuery>()->send();
8163 }
8164 
on_update_phone_number_privacy()8165 void ContactsManager::on_update_phone_number_privacy() {
8166   // all UserFull.need_phone_number_privacy_exception can be outdated now,
8167   // so mark all of them as expired
8168   for (auto &it : users_full_) {
8169     it.second->expires_at = 0.0;
8170   }
8171 }
8172 
invalidate_user_full(UserId user_id)8173 void ContactsManager::invalidate_user_full(UserId user_id) {
8174   auto user_full = get_user_full_force(user_id);
8175   if (user_full != nullptr) {
8176     td_->messages_manager_->on_dialog_info_full_invalidated(DialogId(user_id));
8177 
8178     if (!user_full->is_expired()) {
8179       user_full->expires_at = 0.0;
8180       user_full->need_save_to_database = true;
8181 
8182       update_user_full(user_full, user_id, "invalidate_user_full");
8183     }
8184   }
8185 }
8186 
get_user_id(const tl_object_ptr<telegram_api::User> & user)8187 UserId ContactsManager::get_user_id(const tl_object_ptr<telegram_api::User> &user) {
8188   CHECK(user != nullptr);
8189   switch (user->get_id()) {
8190     case telegram_api::userEmpty::ID:
8191       return UserId(static_cast<const telegram_api::userEmpty *>(user.get())->id_);
8192     case telegram_api::user::ID:
8193       return UserId(static_cast<const telegram_api::user *>(user.get())->id_);
8194     default:
8195       UNREACHABLE();
8196       return UserId();
8197   }
8198 }
8199 
get_chat_id(const tl_object_ptr<telegram_api::Chat> & chat)8200 ChatId ContactsManager::get_chat_id(const tl_object_ptr<telegram_api::Chat> &chat) {
8201   CHECK(chat != nullptr);
8202   switch (chat->get_id()) {
8203     case telegram_api::chatEmpty::ID:
8204       return ChatId(static_cast<const telegram_api::chatEmpty *>(chat.get())->id_);
8205     case telegram_api::chat::ID:
8206       return ChatId(static_cast<const telegram_api::chat *>(chat.get())->id_);
8207     case telegram_api::chatForbidden::ID:
8208       return ChatId(static_cast<const telegram_api::chatForbidden *>(chat.get())->id_);
8209     default:
8210       return ChatId();
8211   }
8212 }
8213 
get_channel_id(const tl_object_ptr<telegram_api::Chat> & chat)8214 ChannelId ContactsManager::get_channel_id(const tl_object_ptr<telegram_api::Chat> &chat) {
8215   CHECK(chat != nullptr);
8216   switch (chat->get_id()) {
8217     case telegram_api::channel::ID:
8218       return ChannelId(static_cast<const telegram_api::channel *>(chat.get())->id_);
8219     case telegram_api::channelForbidden::ID:
8220       return ChannelId(static_cast<const telegram_api::channelForbidden *>(chat.get())->id_);
8221     default:
8222       return ChannelId();
8223   }
8224 }
8225 
on_get_user(tl_object_ptr<telegram_api::User> && user_ptr,const char * source,bool is_me,bool expect_support)8226 void ContactsManager::on_get_user(tl_object_ptr<telegram_api::User> &&user_ptr, const char *source, bool is_me,
8227                                   bool expect_support) {
8228   LOG(DEBUG) << "Receive from " << source << ' ' << to_string(user_ptr);
8229   int32 constructor_id = user_ptr->get_id();
8230   if (constructor_id == telegram_api::userEmpty::ID) {
8231     auto user = move_tl_object_as<telegram_api::userEmpty>(user_ptr);
8232     UserId user_id(user->id_);
8233     if (!user_id.is_valid()) {
8234       LOG(ERROR) << "Receive invalid " << user_id << " from " << source;
8235       return;
8236     }
8237     LOG(INFO) << "Receive empty " << user_id << " from " << source;
8238 
8239     User *u = get_user_force(user_id);
8240     if (u == nullptr && Slice(source) != Slice("GetUsersQuery")) {
8241       // userEmpty should be received only through getUsers for unexisting users
8242       LOG(ERROR) << "Have no information about " << user_id << ", but received userEmpty from " << source;
8243     }
8244     return;
8245   }
8246 
8247   CHECK(constructor_id == telegram_api::user::ID);
8248   auto user = move_tl_object_as<telegram_api::user>(user_ptr);
8249   UserId user_id(user->id_);
8250   if (!user_id.is_valid()) {
8251     LOG(ERROR) << "Receive invalid " << user_id;
8252     return;
8253   }
8254   int32 flags = user->flags_;
8255   LOG(INFO) << "Receive " << user_id << " with flags " << flags << " from " << source;
8256   if (is_me && (flags & USER_FLAG_IS_ME) == 0) {
8257     LOG(ERROR) << user_id << " doesn't have flag IS_ME, but must have it when received from " << source;
8258     flags |= USER_FLAG_IS_ME;
8259   }
8260 
8261   bool is_bot = (flags & USER_FLAG_IS_BOT) != 0;
8262   if (flags & USER_FLAG_IS_ME) {
8263     set_my_id(user_id);
8264     if (!is_bot) {
8265       G()->shared_config().set_option_string("my_phone_number", user->phone_);
8266     }
8267   }
8268 
8269   if (expect_support) {
8270     support_user_id_ = user_id;
8271   }
8272 
8273   bool have_access_hash = (flags & USER_FLAG_HAS_ACCESS_HASH) != 0;
8274   bool is_received = (flags & USER_FLAG_IS_INACCESSIBLE) == 0;
8275 
8276   if (!is_received && !have_user_force(user_id)) {
8277     // we must preload information about received inaccessible users from database in order to not save
8278     // the min-user to the database and to not override access_hash and another info
8279     LOG(INFO) << "Receive inaccessible " << user_id;
8280   }
8281 
8282   User *u = add_user(user_id, "on_get_user");
8283   if (have_access_hash) {  // access_hash must be updated before photo
8284     auto access_hash = user->access_hash_;
8285     bool is_min_access_hash = !is_received && !((flags & USER_FLAG_HAS_PHONE_NUMBER) != 0 && user->phone_.empty());
8286     if (u->access_hash != access_hash && (!is_min_access_hash || u->is_min_access_hash || u->access_hash == -1)) {
8287       LOG(DEBUG) << "Access hash has changed for " << user_id << " from " << u->access_hash << "/"
8288                  << u->is_min_access_hash << " to " << access_hash << "/" << is_min_access_hash;
8289       u->access_hash = access_hash;
8290       u->is_min_access_hash = is_min_access_hash;
8291       u->need_save_to_database = true;
8292     }
8293   }
8294   if (is_received || !user->phone_.empty()) {
8295     on_update_user_phone_number(u, user_id, std::move(user->phone_));
8296   }
8297   if (is_received || u->need_apply_min_photo || !u->is_received) {
8298     on_update_user_photo(u, user_id, std::move(user->photo_), source);
8299   }
8300   if (is_received) {
8301     on_update_user_online(u, user_id, std::move(user->status_));
8302 
8303     auto is_contact = (flags & USER_FLAG_IS_CONTACT) != 0;
8304     auto is_mutual_contact = (flags & USER_FLAG_IS_MUTUAL_CONTACT) != 0;
8305     on_update_user_is_contact(u, user_id, is_contact, is_mutual_contact);
8306   }
8307 
8308   if (is_received || !u->is_received) {
8309     on_update_user_name(u, user_id, std::move(user->first_name_), std::move(user->last_name_),
8310                         std::move(user->username_));
8311   }
8312 
8313   bool is_verified = (flags & USER_FLAG_IS_VERIFIED) != 0;
8314   bool is_support = (flags & USER_FLAG_IS_SUPPORT) != 0;
8315   bool is_deleted = (flags & USER_FLAG_IS_DELETED) != 0;
8316   bool can_join_groups = (flags & USER_FLAG_IS_PRIVATE_BOT) == 0;
8317   bool can_read_all_group_messages = (flags & USER_FLAG_IS_BOT_WITH_PRIVACY_DISABLED) != 0;
8318   auto restriction_reasons = get_restriction_reasons(std::move(user->restriction_reason_));
8319   bool is_scam = (flags & USER_FLAG_IS_SCAM) != 0;
8320   bool is_inline_bot = (flags & USER_FLAG_IS_INLINE_BOT) != 0;
8321   string inline_query_placeholder = user->bot_inline_placeholder_;
8322   bool need_location_bot = (flags & USER_FLAG_NEED_LOCATION_BOT) != 0;
8323   bool has_bot_info_version = (flags & USER_FLAG_HAS_BOT_INFO_VERSION) != 0;
8324   bool need_apply_min_photo = (flags & USER_FLAG_NEED_APPLY_MIN_PHOTO) != 0;
8325   bool is_fake = (flags & USER_FLAG_IS_FAKE) != 0;
8326 
8327   LOG_IF(ERROR, !is_support && expect_support) << "Receive non-support " << user_id << ", but expected a support user";
8328   LOG_IF(ERROR, !can_join_groups && !is_bot)
8329       << "Receive not bot " << user_id << " which can't join groups from " << source;
8330   LOG_IF(ERROR, can_read_all_group_messages && !is_bot)
8331       << "Receive not bot " << user_id << " which can read all group messages from " << source;
8332   LOG_IF(ERROR, is_inline_bot && !is_bot) << "Receive not bot " << user_id << " which is inline bot from " << source;
8333   LOG_IF(ERROR, need_location_bot && !is_inline_bot)
8334       << "Receive not inline bot " << user_id << " which needs user location from " << source;
8335 
8336   if (is_deleted) {
8337     // just in case
8338     is_verified = false;
8339     is_support = false;
8340     is_bot = false;
8341     can_join_groups = false;
8342     can_read_all_group_messages = false;
8343     is_inline_bot = false;
8344     inline_query_placeholder = string();
8345     need_location_bot = false;
8346     has_bot_info_version = false;
8347     need_apply_min_photo = false;
8348   }
8349 
8350   LOG_IF(ERROR, has_bot_info_version && !is_bot)
8351       << "Receive not bot " << user_id << " which has bot info version from " << source;
8352 
8353   int32 bot_info_version = has_bot_info_version ? user->bot_info_version_ : -1;
8354   if (is_verified != u->is_verified || is_support != u->is_support || is_bot != u->is_bot ||
8355       can_join_groups != u->can_join_groups || can_read_all_group_messages != u->can_read_all_group_messages ||
8356       restriction_reasons != u->restriction_reasons || is_scam != u->is_scam || is_fake != u->is_fake ||
8357       is_inline_bot != u->is_inline_bot || inline_query_placeholder != u->inline_query_placeholder ||
8358       need_location_bot != u->need_location_bot) {
8359     LOG_IF(ERROR, is_bot != u->is_bot && !is_deleted && !u->is_deleted && u->is_received)
8360         << "User.is_bot has changed for " << user_id << "/" << u->username << " from " << source << " from "
8361         << u->is_bot << " to " << is_bot;
8362     u->is_verified = is_verified;
8363     u->is_support = is_support;
8364     u->is_bot = is_bot;
8365     u->can_join_groups = can_join_groups;
8366     u->can_read_all_group_messages = can_read_all_group_messages;
8367     u->restriction_reasons = std::move(restriction_reasons);
8368     u->is_scam = is_scam;
8369     u->is_fake = is_fake;
8370     u->is_inline_bot = is_inline_bot;
8371     u->inline_query_placeholder = std::move(inline_query_placeholder);
8372     u->need_location_bot = need_location_bot;
8373 
8374     LOG(DEBUG) << "Info has changed for " << user_id;
8375     u->is_changed = true;
8376   }
8377 
8378   if (u->bot_info_version != bot_info_version) {
8379     u->bot_info_version = bot_info_version;
8380     LOG(DEBUG) << "Bot info version has changed for " << user_id;
8381     u->need_save_to_database = true;
8382   }
8383   if (is_received && u->need_apply_min_photo != need_apply_min_photo) {
8384     u->need_apply_min_photo = need_apply_min_photo;
8385     u->need_save_to_database = true;
8386   }
8387 
8388   if (is_received && !u->is_received) {
8389     u->is_received = true;
8390 
8391     LOG(DEBUG) << "Receive " << user_id;
8392     u->is_changed = true;
8393   }
8394 
8395   if (is_deleted != u->is_deleted) {
8396     u->is_deleted = is_deleted;
8397 
8398     LOG(DEBUG) << "User.is_deleted has changed for " << user_id << " to " << u->is_deleted;
8399     u->is_is_deleted_changed = true;
8400     u->is_changed = true;
8401   }
8402 
8403   bool has_language_code = (flags & USER_FLAG_HAS_LANGUAGE_CODE) != 0;
8404   LOG_IF(ERROR, has_language_code && !td_->auth_manager_->is_bot())
8405       << "Receive language code for " << user_id << " from " << source;
8406   if (u->language_code != user->lang_code_ && !user->lang_code_.empty()) {
8407     u->language_code = user->lang_code_;
8408 
8409     LOG(DEBUG) << "Language code has changed for " << user_id << " to " << u->language_code;
8410     u->is_changed = true;
8411   }
8412 
8413   if (u->cache_version != User::CACHE_VERSION && u->is_received) {
8414     u->cache_version = User::CACHE_VERSION;
8415     u->need_save_to_database = true;
8416   }
8417   u->is_received_from_server = true;
8418   update_user(u, user_id);
8419 }
8420 
8421 class ContactsManager::UserLogEvent {
8422  public:
8423   UserId user_id;
8424   User u;
8425 
8426   UserLogEvent() = default;
8427 
UserLogEvent(UserId user_id,const User & u)8428   UserLogEvent(UserId user_id, const User &u) : user_id(user_id), u(u) {
8429   }
8430 
8431   template <class StorerT>
store(StorerT & storer) const8432   void store(StorerT &storer) const {
8433     td::store(user_id, storer);
8434     td::store(u, storer);
8435   }
8436 
8437   template <class ParserT>
parse(ParserT & parser)8438   void parse(ParserT &parser) {
8439     td::parse(user_id, parser);
8440     td::parse(u, parser);
8441   }
8442 };
8443 
save_user(User * u,UserId user_id,bool from_binlog)8444 void ContactsManager::save_user(User *u, UserId user_id, bool from_binlog) {
8445   if (!G()->parameters().use_chat_info_db) {
8446     return;
8447   }
8448   CHECK(u != nullptr);
8449   if (!u->is_saved || !u->is_status_saved) {  // TODO more effective handling of !u->is_status_saved
8450     if (!from_binlog) {
8451       auto log_event = UserLogEvent(user_id, *u);
8452       auto storer = get_log_event_storer(log_event);
8453       if (u->log_event_id == 0) {
8454         u->log_event_id = binlog_add(G()->td_db()->get_binlog(), LogEvent::HandlerType::Users, storer);
8455       } else {
8456         binlog_rewrite(G()->td_db()->get_binlog(), u->log_event_id, LogEvent::HandlerType::Users, storer);
8457       }
8458     }
8459 
8460     save_user_to_database(u, user_id);
8461   }
8462 }
8463 
on_binlog_user_event(BinlogEvent && event)8464 void ContactsManager::on_binlog_user_event(BinlogEvent &&event) {
8465   if (!G()->parameters().use_chat_info_db) {
8466     binlog_erase(G()->td_db()->get_binlog(), event.id_);
8467     return;
8468   }
8469 
8470   UserLogEvent log_event;
8471   log_event_parse(log_event, event.data_).ensure();
8472 
8473   auto user_id = log_event.user_id;
8474   if (have_user(user_id)) {
8475     LOG(ERROR) << "Skip adding already added " << user_id;
8476     binlog_erase(G()->td_db()->get_binlog(), event.id_);
8477     return;
8478   }
8479 
8480   LOG(INFO) << "Add " << user_id << " from binlog";
8481   User *u = add_user(user_id, "on_binlog_user_event");
8482   *u = std::move(log_event.u);  // users come from binlog before all other events, so just add them
8483 
8484   u->log_event_id = event.id_;
8485 
8486   update_user(u, user_id, true, false);
8487 }
8488 
get_user_database_key(UserId user_id)8489 string ContactsManager::get_user_database_key(UserId user_id) {
8490   return PSTRING() << "us" << user_id.get();
8491 }
8492 
get_user_database_value(const User * u)8493 string ContactsManager::get_user_database_value(const User *u) {
8494   return log_event_store(*u).as_slice().str();
8495 }
8496 
save_user_to_database(User * u,UserId user_id)8497 void ContactsManager::save_user_to_database(User *u, UserId user_id) {
8498   CHECK(u != nullptr);
8499   if (u->is_being_saved) {
8500     return;
8501   }
8502   if (loaded_from_database_users_.count(user_id)) {
8503     save_user_to_database_impl(u, user_id, get_user_database_value(u));
8504     return;
8505   }
8506   if (load_user_from_database_queries_.count(user_id) != 0) {
8507     return;
8508   }
8509 
8510   load_user_from_database_impl(user_id, Auto());
8511 }
8512 
save_user_to_database_impl(User * u,UserId user_id,string value)8513 void ContactsManager::save_user_to_database_impl(User *u, UserId user_id, string value) {
8514   CHECK(u != nullptr);
8515   CHECK(load_user_from_database_queries_.count(user_id) == 0);
8516   CHECK(!u->is_being_saved);
8517   u->is_being_saved = true;
8518   u->is_saved = true;
8519   u->is_status_saved = true;
8520   LOG(INFO) << "Trying to save to database " << user_id;
8521   G()->td_db()->get_sqlite_pmc()->set(
8522       get_user_database_key(user_id), std::move(value), PromiseCreator::lambda([user_id](Result<> result) {
8523         send_closure(G()->contacts_manager(), &ContactsManager::on_save_user_to_database, user_id, result.is_ok());
8524       }));
8525 }
8526 
on_save_user_to_database(UserId user_id,bool success)8527 void ContactsManager::on_save_user_to_database(UserId user_id, bool success) {
8528   if (G()->close_flag()) {
8529     return;
8530   }
8531 
8532   User *u = get_user(user_id);
8533   CHECK(u != nullptr);
8534   LOG_CHECK(u->is_being_saved) << user_id << " " << u->is_saved << " " << u->is_status_saved << " "
8535                                << load_user_from_database_queries_.count(user_id) << " " << u->is_received << " "
8536                                << u->is_deleted << " " << u->is_bot << " " << u->need_save_to_database << " "
8537                                << u->is_changed << " " << u->is_status_changed << " " << u->is_name_changed << " "
8538                                << u->is_username_changed << " " << u->is_photo_changed << " "
8539                                << u->is_is_contact_changed << " " << u->is_is_deleted_changed;
8540   CHECK(load_user_from_database_queries_.count(user_id) == 0);
8541   u->is_being_saved = false;
8542 
8543   if (!success) {
8544     LOG(ERROR) << "Failed to save " << user_id << " to database";
8545     u->is_saved = false;
8546     u->is_status_saved = false;
8547   } else {
8548     LOG(INFO) << "Successfully saved " << user_id << " to database";
8549   }
8550   if (u->is_saved && u->is_status_saved) {
8551     if (u->log_event_id != 0) {
8552       binlog_erase(G()->td_db()->get_binlog(), u->log_event_id);
8553       u->log_event_id = 0;
8554     }
8555   } else {
8556     save_user(u, user_id, u->log_event_id != 0);
8557   }
8558 }
8559 
load_user_from_database(User * u,UserId user_id,Promise<Unit> promise)8560 void ContactsManager::load_user_from_database(User *u, UserId user_id, Promise<Unit> promise) {
8561   if (loaded_from_database_users_.count(user_id)) {
8562     promise.set_value(Unit());
8563     return;
8564   }
8565 
8566   CHECK(u == nullptr || !u->is_being_saved);
8567   load_user_from_database_impl(user_id, std::move(promise));
8568 }
8569 
load_user_from_database_impl(UserId user_id,Promise<Unit> promise)8570 void ContactsManager::load_user_from_database_impl(UserId user_id, Promise<Unit> promise) {
8571   LOG(INFO) << "Load " << user_id << " from database";
8572   auto &load_user_queries = load_user_from_database_queries_[user_id];
8573   load_user_queries.push_back(std::move(promise));
8574   if (load_user_queries.size() == 1u) {
8575     G()->td_db()->get_sqlite_pmc()->get(get_user_database_key(user_id), PromiseCreator::lambda([user_id](string value) {
8576                                           send_closure(G()->contacts_manager(),
8577                                                        &ContactsManager::on_load_user_from_database, user_id,
8578                                                        std::move(value), false);
8579                                         }));
8580   }
8581 }
8582 
on_load_user_from_database(UserId user_id,string value,bool force)8583 void ContactsManager::on_load_user_from_database(UserId user_id, string value, bool force) {
8584   if (G()->close_flag() && !force) {
8585     // the user is in Binlog and will be saved after restart
8586     return;
8587   }
8588 
8589   if (!loaded_from_database_users_.insert(user_id).second) {
8590     return;
8591   }
8592 
8593   auto it = load_user_from_database_queries_.find(user_id);
8594   vector<Promise<Unit>> promises;
8595   if (it != load_user_from_database_queries_.end()) {
8596     promises = std::move(it->second);
8597     CHECK(!promises.empty());
8598     load_user_from_database_queries_.erase(it);
8599   }
8600 
8601   LOG(INFO) << "Successfully loaded " << user_id << " of size " << value.size() << " from database";
8602   //  G()->td_db()->get_sqlite_pmc()->erase(get_user_database_key(user_id), Auto());
8603   //  return;
8604 
8605   User *u = get_user(user_id);
8606   if (u == nullptr) {
8607     if (!value.empty()) {
8608       u = add_user(user_id, "on_load_user_from_database");
8609 
8610       log_event_parse(*u, value).ensure();
8611 
8612       u->is_saved = true;
8613       u->is_status_saved = true;
8614       update_user(u, user_id, true, true);
8615     }
8616   } else {
8617     CHECK(!u->is_saved);  // user can't be saved before load completes
8618     CHECK(!u->is_being_saved);
8619     auto new_value = get_user_database_value(u);
8620     if (value != new_value) {
8621       save_user_to_database_impl(u, user_id, std::move(new_value));
8622     } else if (u->log_event_id != 0) {
8623       binlog_erase(G()->td_db()->get_binlog(), u->log_event_id);
8624       u->log_event_id = 0;
8625     }
8626   }
8627 
8628   for (auto &promise : promises) {
8629     promise.set_value(Unit());
8630   }
8631 }
8632 
have_user_force(UserId user_id)8633 bool ContactsManager::have_user_force(UserId user_id) {
8634   return get_user_force(user_id) != nullptr;
8635 }
8636 
get_user_force(UserId user_id)8637 ContactsManager::User *ContactsManager::get_user_force(UserId user_id) {
8638   auto u = get_user_force_impl(user_id);
8639   if ((u == nullptr || !u->is_received) &&
8640       (user_id == get_service_notifications_user_id() || user_id == get_replies_bot_user_id() ||
8641        user_id == get_anonymous_bot_user_id())) {
8642     int32 flags = USER_FLAG_HAS_ACCESS_HASH | USER_FLAG_HAS_FIRST_NAME | USER_FLAG_NEED_APPLY_MIN_PHOTO;
8643     int64 profile_photo_id = 0;
8644     int32 profile_photo_dc_id = 1;
8645     string first_name;
8646     string last_name;
8647     string username;
8648     string phone_number;
8649     int32 bot_info_version = 0;
8650 
8651     if (user_id == get_service_notifications_user_id()) {
8652       flags |= USER_FLAG_HAS_PHONE_NUMBER | USER_FLAG_IS_VERIFIED | USER_FLAG_IS_SUPPORT;
8653       first_name = "Telegram";
8654       if (G()->is_test_dc()) {
8655         flags |= USER_FLAG_HAS_LAST_NAME;
8656         last_name = "Notifications";
8657       }
8658       phone_number = "42777";
8659       profile_photo_id = 3337190045231023;
8660     } else if (user_id == get_replies_bot_user_id()) {
8661       flags |= USER_FLAG_HAS_USERNAME | USER_FLAG_IS_BOT;
8662       if (!G()->is_test_dc()) {
8663         flags |= USER_FLAG_IS_PRIVATE_BOT;
8664       }
8665       first_name = "Replies";
8666       username = "replies";
8667       bot_info_version = G()->is_test_dc() ? 1 : 3;
8668     } else if (user_id == get_anonymous_bot_user_id()) {
8669       flags |= USER_FLAG_HAS_USERNAME | USER_FLAG_IS_BOT;
8670       if (!G()->is_test_dc()) {
8671         flags |= USER_FLAG_IS_PRIVATE_BOT;
8672       }
8673       first_name = "Group";
8674       username = G()->is_test_dc() ? "izgroupbot" : "GroupAnonymousBot";
8675       bot_info_version = G()->is_test_dc() ? 1 : 3;
8676       profile_photo_id = 5159307831025969322;
8677     }
8678 
8679     telegram_api::object_ptr<telegram_api::userProfilePhoto> profile_photo;
8680     if (!G()->is_test_dc() && profile_photo_id != 0) {
8681       profile_photo = telegram_api::make_object<telegram_api::userProfilePhoto>(0, false /*ignored*/, profile_photo_id,
8682                                                                                 BufferSlice(), profile_photo_dc_id);
8683     }
8684 
8685     auto user = telegram_api::make_object<telegram_api::user>(
8686         flags, false /*ignored*/, false /*ignored*/, false /*ignored*/, false /*ignored*/, false /*ignored*/,
8687         false /*ignored*/, false /*ignored*/, false /*ignored*/, false /*ignored*/, false /*ignored*/,
8688         false /*ignored*/, false /*ignored*/, false /*ignored*/, false /*ignored*/, false /*ignored*/, user_id.get(), 1,
8689         first_name, string(), username, phone_number, std::move(profile_photo), nullptr, bot_info_version, Auto(),
8690         string(), string());
8691     on_get_user(std::move(user), "get_user_force");
8692     u = get_user(user_id);
8693     CHECK(u != nullptr && u->is_received);
8694   }
8695   return u;
8696 }
8697 
get_user_force_impl(UserId user_id)8698 ContactsManager::User *ContactsManager::get_user_force_impl(UserId user_id) {
8699   if (!user_id.is_valid()) {
8700     return nullptr;
8701   }
8702 
8703   User *u = get_user(user_id);
8704   if (u != nullptr) {
8705     return u;
8706   }
8707   if (!G()->parameters().use_chat_info_db) {
8708     return nullptr;
8709   }
8710   if (loaded_from_database_users_.count(user_id)) {
8711     return nullptr;
8712   }
8713 
8714   LOG(INFO) << "Trying to load " << user_id << " from database";
8715   on_load_user_from_database(user_id, G()->td_db()->get_sqlite_sync_pmc()->get(get_user_database_key(user_id)), true);
8716   return get_user(user_id);
8717 }
8718 
8719 class ContactsManager::ChatLogEvent {
8720  public:
8721   ChatId chat_id;
8722   Chat c;
8723 
8724   ChatLogEvent() = default;
8725 
ChatLogEvent(ChatId chat_id,const Chat & c)8726   ChatLogEvent(ChatId chat_id, const Chat &c) : chat_id(chat_id), c(c) {
8727   }
8728 
8729   template <class StorerT>
store(StorerT & storer) const8730   void store(StorerT &storer) const {
8731     td::store(chat_id, storer);
8732     td::store(c, storer);
8733   }
8734 
8735   template <class ParserT>
parse(ParserT & parser)8736   void parse(ParserT &parser) {
8737     td::parse(chat_id, parser);
8738     td::parse(c, parser);
8739   }
8740 };
8741 
save_chat(Chat * c,ChatId chat_id,bool from_binlog)8742 void ContactsManager::save_chat(Chat *c, ChatId chat_id, bool from_binlog) {
8743   if (!G()->parameters().use_chat_info_db) {
8744     return;
8745   }
8746   CHECK(c != nullptr);
8747   if (!c->is_saved) {
8748     if (!from_binlog) {
8749       auto log_event = ChatLogEvent(chat_id, *c);
8750       auto storer = get_log_event_storer(log_event);
8751       if (c->log_event_id == 0) {
8752         c->log_event_id = binlog_add(G()->td_db()->get_binlog(), LogEvent::HandlerType::Chats, storer);
8753       } else {
8754         binlog_rewrite(G()->td_db()->get_binlog(), c->log_event_id, LogEvent::HandlerType::Chats, storer);
8755       }
8756     }
8757 
8758     save_chat_to_database(c, chat_id);
8759     return;
8760   }
8761 }
8762 
on_binlog_chat_event(BinlogEvent && event)8763 void ContactsManager::on_binlog_chat_event(BinlogEvent &&event) {
8764   if (!G()->parameters().use_chat_info_db) {
8765     binlog_erase(G()->td_db()->get_binlog(), event.id_);
8766     return;
8767   }
8768 
8769   ChatLogEvent log_event;
8770   log_event_parse(log_event, event.data_).ensure();
8771 
8772   auto chat_id = log_event.chat_id;
8773   if (have_chat(chat_id)) {
8774     LOG(ERROR) << "Skip adding already added " << chat_id;
8775     binlog_erase(G()->td_db()->get_binlog(), event.id_);
8776     return;
8777   }
8778 
8779   LOG(INFO) << "Add " << chat_id << " from binlog";
8780   Chat *c = add_chat(chat_id);
8781   *c = std::move(log_event.c);  // chats come from binlog before all other events, so just add them
8782 
8783   c->log_event_id = event.id_;
8784 
8785   update_chat(c, chat_id, true, false);
8786 }
8787 
get_chat_database_key(ChatId chat_id)8788 string ContactsManager::get_chat_database_key(ChatId chat_id) {
8789   return PSTRING() << "gr" << chat_id.get();
8790 }
8791 
get_chat_database_value(const Chat * c)8792 string ContactsManager::get_chat_database_value(const Chat *c) {
8793   return log_event_store(*c).as_slice().str();
8794 }
8795 
save_chat_to_database(Chat * c,ChatId chat_id)8796 void ContactsManager::save_chat_to_database(Chat *c, ChatId chat_id) {
8797   CHECK(c != nullptr);
8798   if (c->is_being_saved) {
8799     return;
8800   }
8801   if (loaded_from_database_chats_.count(chat_id)) {
8802     save_chat_to_database_impl(c, chat_id, get_chat_database_value(c));
8803     return;
8804   }
8805   if (load_chat_from_database_queries_.count(chat_id) != 0) {
8806     return;
8807   }
8808 
8809   load_chat_from_database_impl(chat_id, Auto());
8810 }
8811 
save_chat_to_database_impl(Chat * c,ChatId chat_id,string value)8812 void ContactsManager::save_chat_to_database_impl(Chat *c, ChatId chat_id, string value) {
8813   CHECK(c != nullptr);
8814   CHECK(load_chat_from_database_queries_.count(chat_id) == 0);
8815   CHECK(!c->is_being_saved);
8816   c->is_being_saved = true;
8817   c->is_saved = true;
8818   LOG(INFO) << "Trying to save to database " << chat_id;
8819   G()->td_db()->get_sqlite_pmc()->set(
8820       get_chat_database_key(chat_id), std::move(value), PromiseCreator::lambda([chat_id](Result<> result) {
8821         send_closure(G()->contacts_manager(), &ContactsManager::on_save_chat_to_database, chat_id, result.is_ok());
8822       }));
8823 }
8824 
on_save_chat_to_database(ChatId chat_id,bool success)8825 void ContactsManager::on_save_chat_to_database(ChatId chat_id, bool success) {
8826   if (G()->close_flag()) {
8827     return;
8828   }
8829 
8830   Chat *c = get_chat(chat_id);
8831   CHECK(c != nullptr);
8832   CHECK(c->is_being_saved);
8833   CHECK(load_chat_from_database_queries_.count(chat_id) == 0);
8834   c->is_being_saved = false;
8835 
8836   if (!success) {
8837     LOG(ERROR) << "Failed to save " << chat_id << " to database";
8838     c->is_saved = false;
8839   } else {
8840     LOG(INFO) << "Successfully saved " << chat_id << " to database";
8841   }
8842   if (c->is_saved) {
8843     if (c->log_event_id != 0) {
8844       binlog_erase(G()->td_db()->get_binlog(), c->log_event_id);
8845       c->log_event_id = 0;
8846     }
8847   } else {
8848     save_chat(c, chat_id, c->log_event_id != 0);
8849   }
8850 }
8851 
load_chat_from_database(Chat * c,ChatId chat_id,Promise<Unit> promise)8852 void ContactsManager::load_chat_from_database(Chat *c, ChatId chat_id, Promise<Unit> promise) {
8853   if (loaded_from_database_chats_.count(chat_id)) {
8854     promise.set_value(Unit());
8855     return;
8856   }
8857 
8858   CHECK(c == nullptr || !c->is_being_saved);
8859   load_chat_from_database_impl(chat_id, std::move(promise));
8860 }
8861 
load_chat_from_database_impl(ChatId chat_id,Promise<Unit> promise)8862 void ContactsManager::load_chat_from_database_impl(ChatId chat_id, Promise<Unit> promise) {
8863   LOG(INFO) << "Load " << chat_id << " from database";
8864   auto &load_chat_queries = load_chat_from_database_queries_[chat_id];
8865   load_chat_queries.push_back(std::move(promise));
8866   if (load_chat_queries.size() == 1u) {
8867     G()->td_db()->get_sqlite_pmc()->get(get_chat_database_key(chat_id), PromiseCreator::lambda([chat_id](string value) {
8868                                           send_closure(G()->contacts_manager(),
8869                                                        &ContactsManager::on_load_chat_from_database, chat_id,
8870                                                        std::move(value), false);
8871                                         }));
8872   }
8873 }
8874 
on_load_chat_from_database(ChatId chat_id,string value,bool force)8875 void ContactsManager::on_load_chat_from_database(ChatId chat_id, string value, bool force) {
8876   if (G()->close_flag() && !force) {
8877     // the chat is in Binlog and will be saved after restart
8878     return;
8879   }
8880 
8881   if (!loaded_from_database_chats_.insert(chat_id).second) {
8882     return;
8883   }
8884 
8885   auto it = load_chat_from_database_queries_.find(chat_id);
8886   vector<Promise<Unit>> promises;
8887   if (it != load_chat_from_database_queries_.end()) {
8888     promises = std::move(it->second);
8889     CHECK(!promises.empty());
8890     load_chat_from_database_queries_.erase(it);
8891   }
8892 
8893   LOG(INFO) << "Successfully loaded " << chat_id << " of size " << value.size() << " from database";
8894   //  G()->td_db()->get_sqlite_pmc()->erase(get_chat_database_key(chat_id), Auto());
8895   //  return;
8896 
8897   Chat *c = get_chat(chat_id);
8898   if (c == nullptr) {
8899     if (!value.empty()) {
8900       c = add_chat(chat_id);
8901 
8902       log_event_parse(*c, value).ensure();
8903 
8904       c->is_saved = true;
8905       update_chat(c, chat_id, true, true);
8906     }
8907   } else {
8908     CHECK(!c->is_saved);  // chat can't be saved before load completes
8909     CHECK(!c->is_being_saved);
8910     auto new_value = get_chat_database_value(c);
8911     if (value != new_value) {
8912       save_chat_to_database_impl(c, chat_id, std::move(new_value));
8913     } else if (c->log_event_id != 0) {
8914       binlog_erase(G()->td_db()->get_binlog(), c->log_event_id);
8915       c->log_event_id = 0;
8916     }
8917   }
8918 
8919   if (c != nullptr && c->migrated_to_channel_id.is_valid() && !have_channel_force(c->migrated_to_channel_id)) {
8920     LOG(ERROR) << "Can't find " << c->migrated_to_channel_id << " from " << chat_id;
8921   }
8922 
8923   for (auto &promise : promises) {
8924     promise.set_value(Unit());
8925   }
8926 }
8927 
have_chat_force(ChatId chat_id)8928 bool ContactsManager::have_chat_force(ChatId chat_id) {
8929   return get_chat_force(chat_id) != nullptr;
8930 }
8931 
get_chat_force(ChatId chat_id)8932 ContactsManager::Chat *ContactsManager::get_chat_force(ChatId chat_id) {
8933   if (!chat_id.is_valid()) {
8934     return nullptr;
8935   }
8936 
8937   Chat *c = get_chat(chat_id);
8938   if (c != nullptr) {
8939     if (c->migrated_to_channel_id.is_valid() && !have_channel_force(c->migrated_to_channel_id)) {
8940       LOG(ERROR) << "Can't find " << c->migrated_to_channel_id << " from " << chat_id;
8941     }
8942 
8943     return c;
8944   }
8945   if (!G()->parameters().use_chat_info_db) {
8946     return nullptr;
8947   }
8948   if (loaded_from_database_chats_.count(chat_id)) {
8949     return nullptr;
8950   }
8951 
8952   LOG(INFO) << "Trying to load " << chat_id << " from database";
8953   on_load_chat_from_database(chat_id, G()->td_db()->get_sqlite_sync_pmc()->get(get_chat_database_key(chat_id)), true);
8954   return get_chat(chat_id);
8955 }
8956 
8957 class ContactsManager::ChannelLogEvent {
8958  public:
8959   ChannelId channel_id;
8960   Channel c;
8961 
8962   ChannelLogEvent() = default;
8963 
ChannelLogEvent(ChannelId channel_id,const Channel & c)8964   ChannelLogEvent(ChannelId channel_id, const Channel &c) : channel_id(channel_id), c(c) {
8965   }
8966 
8967   template <class StorerT>
store(StorerT & storer) const8968   void store(StorerT &storer) const {
8969     td::store(channel_id, storer);
8970     td::store(c, storer);
8971   }
8972 
8973   template <class ParserT>
parse(ParserT & parser)8974   void parse(ParserT &parser) {
8975     td::parse(channel_id, parser);
8976     td::parse(c, parser);
8977   }
8978 };
8979 
save_channel(Channel * c,ChannelId channel_id,bool from_binlog)8980 void ContactsManager::save_channel(Channel *c, ChannelId channel_id, bool from_binlog) {
8981   if (!G()->parameters().use_chat_info_db) {
8982     return;
8983   }
8984   CHECK(c != nullptr);
8985   if (!c->is_saved) {
8986     if (!from_binlog) {
8987       auto log_event = ChannelLogEvent(channel_id, *c);
8988       auto storer = get_log_event_storer(log_event);
8989       if (c->log_event_id == 0) {
8990         c->log_event_id = binlog_add(G()->td_db()->get_binlog(), LogEvent::HandlerType::Channels, storer);
8991       } else {
8992         binlog_rewrite(G()->td_db()->get_binlog(), c->log_event_id, LogEvent::HandlerType::Channels, storer);
8993       }
8994     }
8995 
8996     save_channel_to_database(c, channel_id);
8997     return;
8998   }
8999 }
9000 
on_binlog_channel_event(BinlogEvent && event)9001 void ContactsManager::on_binlog_channel_event(BinlogEvent &&event) {
9002   if (!G()->parameters().use_chat_info_db) {
9003     binlog_erase(G()->td_db()->get_binlog(), event.id_);
9004     return;
9005   }
9006 
9007   ChannelLogEvent log_event;
9008   log_event_parse(log_event, event.data_).ensure();
9009 
9010   auto channel_id = log_event.channel_id;
9011   if (have_channel(channel_id)) {
9012     LOG(ERROR) << "Skip adding already added " << channel_id;
9013     binlog_erase(G()->td_db()->get_binlog(), event.id_);
9014     return;
9015   }
9016 
9017   LOG(INFO) << "Add " << channel_id << " from binlog";
9018   Channel *c = add_channel(channel_id, "on_binlog_channel_event");
9019   *c = std::move(log_event.c);  // channels come from binlog before all other events, so just add them
9020 
9021   c->log_event_id = event.id_;
9022 
9023   update_channel(c, channel_id, true, false);
9024 }
9025 
get_channel_database_key(ChannelId channel_id)9026 string ContactsManager::get_channel_database_key(ChannelId channel_id) {
9027   return PSTRING() << "ch" << channel_id.get();
9028 }
9029 
get_channel_database_value(const Channel * c)9030 string ContactsManager::get_channel_database_value(const Channel *c) {
9031   return log_event_store(*c).as_slice().str();
9032 }
9033 
save_channel_to_database(Channel * c,ChannelId channel_id)9034 void ContactsManager::save_channel_to_database(Channel *c, ChannelId channel_id) {
9035   CHECK(c != nullptr);
9036   if (c->is_being_saved) {
9037     return;
9038   }
9039   if (loaded_from_database_channels_.count(channel_id)) {
9040     save_channel_to_database_impl(c, channel_id, get_channel_database_value(c));
9041     return;
9042   }
9043   if (load_channel_from_database_queries_.count(channel_id) != 0) {
9044     return;
9045   }
9046 
9047   load_channel_from_database_impl(channel_id, Auto());
9048 }
9049 
save_channel_to_database_impl(Channel * c,ChannelId channel_id,string value)9050 void ContactsManager::save_channel_to_database_impl(Channel *c, ChannelId channel_id, string value) {
9051   CHECK(c != nullptr);
9052   CHECK(load_channel_from_database_queries_.count(channel_id) == 0);
9053   CHECK(!c->is_being_saved);
9054   c->is_being_saved = true;
9055   c->is_saved = true;
9056   LOG(INFO) << "Trying to save to database " << channel_id;
9057   G()->td_db()->get_sqlite_pmc()->set(
9058       get_channel_database_key(channel_id), std::move(value), PromiseCreator::lambda([channel_id](Result<> result) {
9059         send_closure(G()->contacts_manager(), &ContactsManager::on_save_channel_to_database, channel_id,
9060                      result.is_ok());
9061       }));
9062 }
9063 
on_save_channel_to_database(ChannelId channel_id,bool success)9064 void ContactsManager::on_save_channel_to_database(ChannelId channel_id, bool success) {
9065   if (G()->close_flag()) {
9066     return;
9067   }
9068 
9069   Channel *c = get_channel(channel_id);
9070   CHECK(c != nullptr);
9071   CHECK(c->is_being_saved);
9072   CHECK(load_channel_from_database_queries_.count(channel_id) == 0);
9073   c->is_being_saved = false;
9074 
9075   if (!success) {
9076     LOG(ERROR) << "Failed to save " << channel_id << " to database";
9077     c->is_saved = false;
9078   } else {
9079     LOG(INFO) << "Successfully saved " << channel_id << " to database";
9080   }
9081   if (c->is_saved) {
9082     if (c->log_event_id != 0) {
9083       binlog_erase(G()->td_db()->get_binlog(), c->log_event_id);
9084       c->log_event_id = 0;
9085     }
9086   } else {
9087     save_channel(c, channel_id, c->log_event_id != 0);
9088   }
9089 }
9090 
load_channel_from_database(Channel * c,ChannelId channel_id,Promise<Unit> promise)9091 void ContactsManager::load_channel_from_database(Channel *c, ChannelId channel_id, Promise<Unit> promise) {
9092   if (loaded_from_database_channels_.count(channel_id)) {
9093     promise.set_value(Unit());
9094     return;
9095   }
9096 
9097   CHECK(c == nullptr || !c->is_being_saved);
9098   load_channel_from_database_impl(channel_id, std::move(promise));
9099 }
9100 
load_channel_from_database_impl(ChannelId channel_id,Promise<Unit> promise)9101 void ContactsManager::load_channel_from_database_impl(ChannelId channel_id, Promise<Unit> promise) {
9102   LOG(INFO) << "Load " << channel_id << " from database";
9103   auto &load_channel_queries = load_channel_from_database_queries_[channel_id];
9104   load_channel_queries.push_back(std::move(promise));
9105   if (load_channel_queries.size() == 1u) {
9106     G()->td_db()->get_sqlite_pmc()->get(
9107         get_channel_database_key(channel_id), PromiseCreator::lambda([channel_id](string value) {
9108           send_closure(G()->contacts_manager(), &ContactsManager::on_load_channel_from_database, channel_id,
9109                        std::move(value), false);
9110         }));
9111   }
9112 }
9113 
on_load_channel_from_database(ChannelId channel_id,string value,bool force)9114 void ContactsManager::on_load_channel_from_database(ChannelId channel_id, string value, bool force) {
9115   if (G()->close_flag() && !force) {
9116     // the channel is in Binlog and will be saved after restart
9117     return;
9118   }
9119 
9120   if (!loaded_from_database_channels_.insert(channel_id).second) {
9121     return;
9122   }
9123 
9124   auto it = load_channel_from_database_queries_.find(channel_id);
9125   vector<Promise<Unit>> promises;
9126   if (it != load_channel_from_database_queries_.end()) {
9127     promises = std::move(it->second);
9128     CHECK(!promises.empty());
9129     load_channel_from_database_queries_.erase(it);
9130   }
9131 
9132   LOG(INFO) << "Successfully loaded " << channel_id << " of size " << value.size() << " from database";
9133   //  G()->td_db()->get_sqlite_pmc()->erase(get_channel_database_key(channel_id), Auto());
9134   //  return;
9135 
9136   Channel *c = get_channel(channel_id);
9137   if (c == nullptr) {
9138     if (!value.empty()) {
9139       c = add_channel(channel_id, "on_load_channel_from_database");
9140 
9141       log_event_parse(*c, value).ensure();
9142 
9143       c->is_saved = true;
9144       update_channel(c, channel_id, true, true);
9145     }
9146   } else {
9147     CHECK(!c->is_saved);  // channel can't be saved before load completes
9148     CHECK(!c->is_being_saved);
9149     if (!value.empty()) {
9150       Channel temp_c;
9151       log_event_parse(temp_c, value).ensure();
9152       if (c->participant_count == 0 && temp_c.participant_count != 0) {
9153         c->participant_count = temp_c.participant_count;
9154         CHECK(c->is_update_supergroup_sent);
9155         send_closure(G()->td(), &Td::send_update,
9156                      make_tl_object<td_api::updateSupergroup>(get_supergroup_object(channel_id, c)));
9157       }
9158 
9159       c->status.update_restrictions();
9160       temp_c.status.update_restrictions();
9161       if (temp_c.status != c->status) {
9162         on_channel_status_changed(c, channel_id, temp_c.status, c->status);
9163         CHECK(!c->is_being_saved);
9164       }
9165 
9166       if (temp_c.username != c->username) {
9167         on_channel_username_changed(c, channel_id, temp_c.username, c->username);
9168         CHECK(!c->is_being_saved);
9169       }
9170     }
9171     auto new_value = get_channel_database_value(c);
9172     if (value != new_value) {
9173       save_channel_to_database_impl(c, channel_id, std::move(new_value));
9174     } else if (c->log_event_id != 0) {
9175       binlog_erase(G()->td_db()->get_binlog(), c->log_event_id);
9176       c->log_event_id = 0;
9177     }
9178   }
9179 
9180   for (auto &promise : promises) {
9181     promise.set_value(Unit());
9182   }
9183 }
9184 
have_channel_force(ChannelId channel_id)9185 bool ContactsManager::have_channel_force(ChannelId channel_id) {
9186   return get_channel_force(channel_id) != nullptr;
9187 }
9188 
get_channel_force(ChannelId channel_id)9189 ContactsManager::Channel *ContactsManager::get_channel_force(ChannelId channel_id) {
9190   if (!channel_id.is_valid()) {
9191     return nullptr;
9192   }
9193 
9194   Channel *c = get_channel(channel_id);
9195   if (c != nullptr) {
9196     return c;
9197   }
9198   if (!G()->parameters().use_chat_info_db) {
9199     return nullptr;
9200   }
9201   if (loaded_from_database_channels_.count(channel_id)) {
9202     return nullptr;
9203   }
9204 
9205   LOG(INFO) << "Trying to load " << channel_id << " from database";
9206   on_load_channel_from_database(channel_id,
9207                                 G()->td_db()->get_sqlite_sync_pmc()->get(get_channel_database_key(channel_id)), true);
9208   return get_channel(channel_id);
9209 }
9210 
9211 class ContactsManager::SecretChatLogEvent {
9212  public:
9213   SecretChatId secret_chat_id;
9214   SecretChat c;
9215 
9216   SecretChatLogEvent() = default;
9217 
SecretChatLogEvent(SecretChatId secret_chat_id,const SecretChat & c)9218   SecretChatLogEvent(SecretChatId secret_chat_id, const SecretChat &c) : secret_chat_id(secret_chat_id), c(c) {
9219   }
9220 
9221   template <class StorerT>
store(StorerT & storer) const9222   void store(StorerT &storer) const {
9223     td::store(secret_chat_id, storer);
9224     td::store(c, storer);
9225   }
9226 
9227   template <class ParserT>
parse(ParserT & parser)9228   void parse(ParserT &parser) {
9229     td::parse(secret_chat_id, parser);
9230     td::parse(c, parser);
9231   }
9232 };
9233 
save_secret_chat(SecretChat * c,SecretChatId secret_chat_id,bool from_binlog)9234 void ContactsManager::save_secret_chat(SecretChat *c, SecretChatId secret_chat_id, bool from_binlog) {
9235   if (!G()->parameters().use_chat_info_db) {
9236     return;
9237   }
9238   CHECK(c != nullptr);
9239   if (!c->is_saved) {
9240     if (!from_binlog) {
9241       auto log_event = SecretChatLogEvent(secret_chat_id, *c);
9242       auto storer = get_log_event_storer(log_event);
9243       if (c->log_event_id == 0) {
9244         c->log_event_id = binlog_add(G()->td_db()->get_binlog(), LogEvent::HandlerType::SecretChatInfos, storer);
9245       } else {
9246         binlog_rewrite(G()->td_db()->get_binlog(), c->log_event_id, LogEvent::HandlerType::SecretChatInfos, storer);
9247       }
9248     }
9249 
9250     save_secret_chat_to_database(c, secret_chat_id);
9251     return;
9252   }
9253 }
9254 
on_binlog_secret_chat_event(BinlogEvent && event)9255 void ContactsManager::on_binlog_secret_chat_event(BinlogEvent &&event) {
9256   if (!G()->parameters().use_chat_info_db) {
9257     binlog_erase(G()->td_db()->get_binlog(), event.id_);
9258     return;
9259   }
9260 
9261   SecretChatLogEvent log_event;
9262   log_event_parse(log_event, event.data_).ensure();
9263 
9264   auto secret_chat_id = log_event.secret_chat_id;
9265   if (have_secret_chat(secret_chat_id)) {
9266     LOG(ERROR) << "Skip adding already added " << secret_chat_id;
9267     binlog_erase(G()->td_db()->get_binlog(), event.id_);
9268     return;
9269   }
9270 
9271   LOG(INFO) << "Add " << secret_chat_id << " from binlog";
9272   SecretChat *c = add_secret_chat(secret_chat_id);
9273   *c = std::move(log_event.c);  // secret chats come from binlog before all other events, so just add them
9274 
9275   c->log_event_id = event.id_;
9276 
9277   update_secret_chat(c, secret_chat_id, true, false);
9278 }
9279 
get_secret_chat_database_key(SecretChatId secret_chat_id)9280 string ContactsManager::get_secret_chat_database_key(SecretChatId secret_chat_id) {
9281   return PSTRING() << "sc" << secret_chat_id.get();
9282 }
9283 
get_secret_chat_database_value(const SecretChat * c)9284 string ContactsManager::get_secret_chat_database_value(const SecretChat *c) {
9285   return log_event_store(*c).as_slice().str();
9286 }
9287 
save_secret_chat_to_database(SecretChat * c,SecretChatId secret_chat_id)9288 void ContactsManager::save_secret_chat_to_database(SecretChat *c, SecretChatId secret_chat_id) {
9289   CHECK(c != nullptr);
9290   if (c->is_being_saved) {
9291     return;
9292   }
9293   if (loaded_from_database_secret_chats_.count(secret_chat_id)) {
9294     save_secret_chat_to_database_impl(c, secret_chat_id, get_secret_chat_database_value(c));
9295     return;
9296   }
9297   if (load_secret_chat_from_database_queries_.count(secret_chat_id) != 0) {
9298     return;
9299   }
9300 
9301   load_secret_chat_from_database_impl(secret_chat_id, Auto());
9302 }
9303 
save_secret_chat_to_database_impl(SecretChat * c,SecretChatId secret_chat_id,string value)9304 void ContactsManager::save_secret_chat_to_database_impl(SecretChat *c, SecretChatId secret_chat_id, string value) {
9305   CHECK(c != nullptr);
9306   CHECK(load_secret_chat_from_database_queries_.count(secret_chat_id) == 0);
9307   CHECK(!c->is_being_saved);
9308   c->is_being_saved = true;
9309   c->is_saved = true;
9310   LOG(INFO) << "Trying to save to database " << secret_chat_id;
9311   G()->td_db()->get_sqlite_pmc()->set(get_secret_chat_database_key(secret_chat_id), std::move(value),
9312                                       PromiseCreator::lambda([secret_chat_id](Result<> result) {
9313                                         send_closure(G()->contacts_manager(),
9314                                                      &ContactsManager::on_save_secret_chat_to_database, secret_chat_id,
9315                                                      result.is_ok());
9316                                       }));
9317 }
9318 
on_save_secret_chat_to_database(SecretChatId secret_chat_id,bool success)9319 void ContactsManager::on_save_secret_chat_to_database(SecretChatId secret_chat_id, bool success) {
9320   if (G()->close_flag()) {
9321     return;
9322   }
9323 
9324   SecretChat *c = get_secret_chat(secret_chat_id);
9325   CHECK(c != nullptr);
9326   CHECK(c->is_being_saved);
9327   CHECK(load_secret_chat_from_database_queries_.count(secret_chat_id) == 0);
9328   c->is_being_saved = false;
9329 
9330   if (!success) {
9331     LOG(ERROR) << "Failed to save " << secret_chat_id << " to database";
9332     c->is_saved = false;
9333   } else {
9334     LOG(INFO) << "Successfully saved " << secret_chat_id << " to database";
9335   }
9336   if (c->is_saved) {
9337     if (c->log_event_id != 0) {
9338       binlog_erase(G()->td_db()->get_binlog(), c->log_event_id);
9339       c->log_event_id = 0;
9340     }
9341   } else {
9342     save_secret_chat(c, secret_chat_id, c->log_event_id != 0);
9343   }
9344 }
9345 
load_secret_chat_from_database(SecretChat * c,SecretChatId secret_chat_id,Promise<Unit> promise)9346 void ContactsManager::load_secret_chat_from_database(SecretChat *c, SecretChatId secret_chat_id,
9347                                                      Promise<Unit> promise) {
9348   if (loaded_from_database_secret_chats_.count(secret_chat_id)) {
9349     promise.set_value(Unit());
9350     return;
9351   }
9352 
9353   CHECK(c == nullptr || !c->is_being_saved);
9354   load_secret_chat_from_database_impl(secret_chat_id, std::move(promise));
9355 }
9356 
load_secret_chat_from_database_impl(SecretChatId secret_chat_id,Promise<Unit> promise)9357 void ContactsManager::load_secret_chat_from_database_impl(SecretChatId secret_chat_id, Promise<Unit> promise) {
9358   LOG(INFO) << "Load " << secret_chat_id << " from database";
9359   auto &load_secret_chat_queries = load_secret_chat_from_database_queries_[secret_chat_id];
9360   load_secret_chat_queries.push_back(std::move(promise));
9361   if (load_secret_chat_queries.size() == 1u) {
9362     G()->td_db()->get_sqlite_pmc()->get(
9363         get_secret_chat_database_key(secret_chat_id), PromiseCreator::lambda([secret_chat_id](string value) {
9364           send_closure(G()->contacts_manager(), &ContactsManager::on_load_secret_chat_from_database, secret_chat_id,
9365                        std::move(value), false);
9366         }));
9367   }
9368 }
9369 
on_load_secret_chat_from_database(SecretChatId secret_chat_id,string value,bool force)9370 void ContactsManager::on_load_secret_chat_from_database(SecretChatId secret_chat_id, string value, bool force) {
9371   if (G()->close_flag() && !force) {
9372     // the secret chat is in Binlog and will be saved after restart
9373     return;
9374   }
9375 
9376   if (!loaded_from_database_secret_chats_.insert(secret_chat_id).second) {
9377     return;
9378   }
9379 
9380   auto it = load_secret_chat_from_database_queries_.find(secret_chat_id);
9381   vector<Promise<Unit>> promises;
9382   if (it != load_secret_chat_from_database_queries_.end()) {
9383     promises = std::move(it->second);
9384     CHECK(!promises.empty());
9385     load_secret_chat_from_database_queries_.erase(it);
9386   }
9387 
9388   LOG(INFO) << "Successfully loaded " << secret_chat_id << " of size " << value.size() << " from database";
9389   //  G()->td_db()->get_sqlite_pmc()->erase(get_secret_chat_database_key(secret_chat_id), Auto());
9390   //  return;
9391 
9392   SecretChat *c = get_secret_chat(secret_chat_id);
9393   if (c == nullptr) {
9394     if (!value.empty()) {
9395       c = add_secret_chat(secret_chat_id);
9396 
9397       log_event_parse(*c, value).ensure();
9398 
9399       c->is_saved = true;
9400       update_secret_chat(c, secret_chat_id, true, true);
9401     }
9402   } else {
9403     CHECK(!c->is_saved);  // secret chat can't be saved before load completes
9404     CHECK(!c->is_being_saved);
9405     auto new_value = get_secret_chat_database_value(c);
9406     if (value != new_value) {
9407       save_secret_chat_to_database_impl(c, secret_chat_id, std::move(new_value));
9408     } else if (c->log_event_id != 0) {
9409       binlog_erase(G()->td_db()->get_binlog(), c->log_event_id);
9410       c->log_event_id = 0;
9411     }
9412   }
9413 
9414   // TODO load users asynchronously
9415   if (c != nullptr && !have_user_force(c->user_id)) {
9416     LOG(ERROR) << "Can't find " << c->user_id << " from " << secret_chat_id;
9417   }
9418 
9419   for (auto &promise : promises) {
9420     promise.set_value(Unit());
9421   }
9422 }
9423 
have_secret_chat_force(SecretChatId secret_chat_id)9424 bool ContactsManager::have_secret_chat_force(SecretChatId secret_chat_id) {
9425   return get_secret_chat_force(secret_chat_id) != nullptr;
9426 }
9427 
get_secret_chat_force(SecretChatId secret_chat_id)9428 ContactsManager::SecretChat *ContactsManager::get_secret_chat_force(SecretChatId secret_chat_id) {
9429   if (!secret_chat_id.is_valid()) {
9430     return nullptr;
9431   }
9432 
9433   SecretChat *c = get_secret_chat(secret_chat_id);
9434   if (c != nullptr) {
9435     if (!have_user_force(c->user_id)) {
9436       LOG(ERROR) << "Can't find " << c->user_id << " from " << secret_chat_id;
9437     }
9438     return c;
9439   }
9440   if (!G()->parameters().use_chat_info_db) {
9441     return nullptr;
9442   }
9443   if (loaded_from_database_secret_chats_.count(secret_chat_id)) {
9444     return nullptr;
9445   }
9446 
9447   LOG(INFO) << "Trying to load " << secret_chat_id << " from database";
9448   on_load_secret_chat_from_database(
9449       secret_chat_id, G()->td_db()->get_sqlite_sync_pmc()->get(get_secret_chat_database_key(secret_chat_id)), true);
9450   return get_secret_chat(secret_chat_id);
9451 }
9452 
save_user_full(const UserFull * user_full,UserId user_id)9453 void ContactsManager::save_user_full(const UserFull *user_full, UserId user_id) {
9454   if (!G()->parameters().use_chat_info_db) {
9455     return;
9456   }
9457 
9458   LOG(INFO) << "Trying to save to database full " << user_id;
9459   CHECK(user_full != nullptr);
9460   G()->td_db()->get_sqlite_pmc()->set(get_user_full_database_key(user_id), get_user_full_database_value(user_full),
9461                                       Auto());
9462 }
9463 
get_user_full_database_key(UserId user_id)9464 string ContactsManager::get_user_full_database_key(UserId user_id) {
9465   return PSTRING() << "usf" << user_id.get();
9466 }
9467 
get_user_full_database_value(const UserFull * user_full)9468 string ContactsManager::get_user_full_database_value(const UserFull *user_full) {
9469   return log_event_store(*user_full).as_slice().str();
9470 }
9471 
on_load_user_full_from_database(UserId user_id,string value)9472 void ContactsManager::on_load_user_full_from_database(UserId user_id, string value) {
9473   LOG(INFO) << "Successfully loaded full " << user_id << " of size " << value.size() << " from database";
9474   //  G()->td_db()->get_sqlite_pmc()->erase(get_user_full_database_key(user_id), Auto());
9475   //  return;
9476 
9477   if (get_user_full(user_id) != nullptr || value.empty()) {
9478     return;
9479   }
9480 
9481   UserFull *user_full = add_user_full(user_id);
9482   auto status = log_event_parse(*user_full, value);
9483   if (status.is_error()) {
9484     // can't happen unless database is broken
9485     LOG(ERROR) << "Repair broken full " << user_id << ' ' << format::as_hex_dump<4>(Slice(value));
9486 
9487     // just clean all known data about the user and pretend that there was nothing in the database
9488     users_full_.erase(user_id);
9489     G()->td_db()->get_sqlite_pmc()->erase(get_user_full_database_key(user_id), Auto());
9490     return;
9491   }
9492 
9493   Dependencies dependencies;
9494   dependencies.user_ids.insert(user_id);
9495   if (!resolve_dependencies_force(td_, dependencies, "on_load_user_full_from_database")) {
9496     users_full_.erase(user_id);
9497     G()->td_db()->get_sqlite_pmc()->erase(get_user_full_database_key(user_id), Auto());
9498     return;
9499   }
9500 
9501   if (user_full->need_phone_number_privacy_exception && is_user_contact(user_id)) {
9502     user_full->need_phone_number_privacy_exception = false;
9503   }
9504 
9505   User *u = get_user(user_id);
9506   CHECK(u != nullptr);
9507   if (u->photo.id != user_full->photo.id.get()) {
9508     user_full->photo = Photo();
9509     if (u->photo.id > 0) {
9510       user_full->expires_at = 0.0;
9511     }
9512   }
9513   if (!user_full->photo.is_empty()) {
9514     register_user_photo(u, user_id, user_full->photo);
9515   }
9516 
9517   td_->group_call_manager_->on_update_dialog_about(DialogId(user_id), user_full->about, false);
9518 
9519   user_full->is_update_user_full_sent = true;
9520   update_user_full(user_full, user_id, "on_load_user_full_from_database", true);
9521 
9522   if (is_user_deleted(user_id)) {
9523     drop_user_full(user_id);
9524   } else if (user_full->expires_at == 0.0) {
9525     load_user_full(user_id, true, Auto(), "on_load_user_full_from_database");
9526   }
9527 }
9528 
get_user_full_force(UserId user_id)9529 ContactsManager::UserFull *ContactsManager::get_user_full_force(UserId user_id) {
9530   if (!have_user_force(user_id)) {
9531     return nullptr;
9532   }
9533 
9534   UserFull *user_full = get_user_full(user_id);
9535   if (user_full != nullptr) {
9536     return user_full;
9537   }
9538   if (!G()->parameters().use_chat_info_db) {
9539     return nullptr;
9540   }
9541   if (!unavailable_user_fulls_.insert(user_id).second) {
9542     return nullptr;
9543   }
9544 
9545   LOG(INFO) << "Trying to load full " << user_id << " from database";
9546   on_load_user_full_from_database(user_id,
9547                                   G()->td_db()->get_sqlite_sync_pmc()->get(get_user_full_database_key(user_id)));
9548   return get_user_full(user_id);
9549 }
9550 
save_chat_full(const ChatFull * chat_full,ChatId chat_id)9551 void ContactsManager::save_chat_full(const ChatFull *chat_full, ChatId chat_id) {
9552   if (!G()->parameters().use_chat_info_db) {
9553     return;
9554   }
9555 
9556   LOG(INFO) << "Trying to save to database full " << chat_id;
9557   CHECK(chat_full != nullptr);
9558   G()->td_db()->get_sqlite_pmc()->set(get_chat_full_database_key(chat_id), get_chat_full_database_value(chat_full),
9559                                       Auto());
9560 }
9561 
get_chat_full_database_key(ChatId chat_id)9562 string ContactsManager::get_chat_full_database_key(ChatId chat_id) {
9563   return PSTRING() << "grf" << chat_id.get();
9564 }
9565 
get_chat_full_database_value(const ChatFull * chat_full)9566 string ContactsManager::get_chat_full_database_value(const ChatFull *chat_full) {
9567   return log_event_store(*chat_full).as_slice().str();
9568 }
9569 
on_load_chat_full_from_database(ChatId chat_id,string value)9570 void ContactsManager::on_load_chat_full_from_database(ChatId chat_id, string value) {
9571   LOG(INFO) << "Successfully loaded full " << chat_id << " of size " << value.size() << " from database";
9572   //  G()->td_db()->get_sqlite_pmc()->erase(get_chat_full_database_key(chat_id), Auto());
9573   //  return;
9574 
9575   if (get_chat_full(chat_id) != nullptr || value.empty()) {
9576     return;
9577   }
9578 
9579   ChatFull *chat_full = add_chat_full(chat_id);
9580   auto status = log_event_parse(*chat_full, value);
9581   if (status.is_error()) {
9582     // can't happen unless database is broken
9583     LOG(ERROR) << "Repair broken full " << chat_id << ' ' << format::as_hex_dump<4>(Slice(value));
9584 
9585     // just clean all known data about the chat and pretend that there was nothing in the database
9586     chats_full_.erase(chat_id);
9587     G()->td_db()->get_sqlite_pmc()->erase(get_chat_full_database_key(chat_id), Auto());
9588     return;
9589   }
9590 
9591   Dependencies dependencies;
9592   dependencies.chat_ids.insert(chat_id);
9593   dependencies.user_ids.insert(chat_full->creator_user_id);
9594   for (auto &participant : chat_full->participants) {
9595     add_message_sender_dependencies(dependencies, participant.dialog_id_);
9596     dependencies.user_ids.insert(participant.inviter_user_id_);
9597   }
9598   dependencies.user_ids.insert(chat_full->invite_link.get_creator_user_id());
9599   if (!resolve_dependencies_force(td_, dependencies, "on_load_chat_full_from_database")) {
9600     chats_full_.erase(chat_id);
9601     G()->td_db()->get_sqlite_pmc()->erase(get_chat_full_database_key(chat_id), Auto());
9602     return;
9603   }
9604 
9605   Chat *c = get_chat(chat_id);
9606   CHECK(c != nullptr);
9607 
9608   bool need_invite_link = c->is_active && c->status.can_manage_invite_links();
9609   bool have_invite_link = chat_full->invite_link.is_valid();
9610   if (need_invite_link != have_invite_link) {
9611     if (need_invite_link) {
9612       // ignore ChatFull without invite link
9613       chats_full_.erase(chat_id);
9614       return;
9615     } else {
9616       chat_full->invite_link = DialogInviteLink();
9617     }
9618   }
9619 
9620   if (td_->file_manager_->get_file_view(c->photo.small_file_id).get_unique_file_id() !=
9621       td_->file_manager_->get_file_view(as_fake_dialog_photo(chat_full->photo, DialogId(chat_id)).small_file_id)
9622           .get_unique_file_id()) {
9623     chat_full->photo = Photo();
9624     if (c->photo.small_file_id.is_valid()) {
9625       reload_chat_full(chat_id, Auto());
9626     }
9627   }
9628 
9629   td_->group_call_manager_->on_update_dialog_about(DialogId(chat_id), chat_full->description, false);
9630 
9631   on_update_chat_full_photo(chat_full, chat_id, std::move(chat_full->photo));
9632 
9633   chat_full->is_update_chat_full_sent = true;
9634   update_chat_full(chat_full, chat_id, "on_load_chat_full_from_database", true);
9635 }
9636 
get_chat_full_force(ChatId chat_id,const char * source)9637 ContactsManager::ChatFull *ContactsManager::get_chat_full_force(ChatId chat_id, const char *source) {
9638   if (!have_chat_force(chat_id)) {
9639     return nullptr;
9640   }
9641 
9642   ChatFull *chat_full = get_chat_full(chat_id);
9643   if (chat_full != nullptr) {
9644     return chat_full;
9645   }
9646   if (!G()->parameters().use_chat_info_db) {
9647     return nullptr;
9648   }
9649   if (!unavailable_chat_fulls_.insert(chat_id).second) {
9650     return nullptr;
9651   }
9652 
9653   LOG(INFO) << "Trying to load full " << chat_id << " from database from " << source;
9654   on_load_chat_full_from_database(chat_id,
9655                                   G()->td_db()->get_sqlite_sync_pmc()->get(get_chat_full_database_key(chat_id)));
9656   return get_chat_full(chat_id);
9657 }
9658 
save_channel_full(const ChannelFull * channel_full,ChannelId channel_id)9659 void ContactsManager::save_channel_full(const ChannelFull *channel_full, ChannelId channel_id) {
9660   if (!G()->parameters().use_chat_info_db) {
9661     return;
9662   }
9663 
9664   LOG(INFO) << "Trying to save to database full " << channel_id;
9665   CHECK(channel_full != nullptr);
9666   G()->td_db()->get_sqlite_pmc()->set(get_channel_full_database_key(channel_id),
9667                                       get_channel_full_database_value(channel_full), Auto());
9668 }
9669 
get_channel_full_database_key(ChannelId channel_id)9670 string ContactsManager::get_channel_full_database_key(ChannelId channel_id) {
9671   return PSTRING() << "chf" << channel_id.get();
9672 }
9673 
get_channel_full_database_value(const ChannelFull * channel_full)9674 string ContactsManager::get_channel_full_database_value(const ChannelFull *channel_full) {
9675   return log_event_store(*channel_full).as_slice().str();
9676 }
9677 
on_load_channel_full_from_database(ChannelId channel_id,string value,const char * source)9678 void ContactsManager::on_load_channel_full_from_database(ChannelId channel_id, string value, const char *source) {
9679   LOG(INFO) << "Successfully loaded full " << channel_id << " of size " << value.size() << " from database from "
9680             << source;
9681   //  G()->td_db()->get_sqlite_pmc()->erase(get_channel_full_database_key(channel_id), Auto());
9682   //  return;
9683 
9684   if (get_channel_full(channel_id, true, "on_load_channel_full_from_database") != nullptr || value.empty()) {
9685     return;
9686   }
9687 
9688   ChannelFull *channel_full = add_channel_full(channel_id);
9689   auto status = log_event_parse(*channel_full, value);
9690   if (status.is_error()) {
9691     // can't happen unless database is broken
9692     LOG(ERROR) << "Repair broken full " << channel_id << ' ' << format::as_hex_dump<4>(Slice(value));
9693 
9694     // just clean all known data about the channel and pretend that there was nothing in the database
9695     channels_full_.erase(channel_id);
9696     G()->td_db()->get_sqlite_pmc()->erase(get_channel_full_database_key(channel_id), Auto());
9697     return;
9698   }
9699 
9700   Dependencies dependencies;
9701   dependencies.channel_ids.insert(channel_id);
9702   // must not depend on the linked_dialog_id itself, because message database can be disabled
9703   // the Dialog will be forcely created in update_channel_full
9704   add_dialog_dependencies(dependencies, DialogId(channel_full->linked_channel_id));
9705   dependencies.chat_ids.insert(channel_full->migrated_from_chat_id);
9706   dependencies.user_ids.insert(channel_full->bot_user_ids.begin(), channel_full->bot_user_ids.end());
9707   dependencies.user_ids.insert(channel_full->invite_link.get_creator_user_id());
9708   if (!resolve_dependencies_force(td_, dependencies, source)) {
9709     channels_full_.erase(channel_id);
9710     G()->td_db()->get_sqlite_pmc()->erase(get_channel_full_database_key(channel_id), Auto());
9711     return;
9712   }
9713 
9714   Channel *c = get_channel(channel_id);
9715   CHECK(c != nullptr);
9716 
9717   bool need_invite_link = c->status.can_manage_invite_links();
9718   bool have_invite_link = channel_full->invite_link.is_valid();
9719   if (need_invite_link != have_invite_link) {
9720     if (need_invite_link) {
9721       // ignore ChannelFull without invite link
9722       channels_full_.erase(channel_id);
9723       return;
9724     } else {
9725       channel_full->invite_link = DialogInviteLink();
9726     }
9727   }
9728 
9729   if (td_->file_manager_->get_file_view(c->photo.small_file_id).get_unique_file_id() !=
9730       td_->file_manager_->get_file_view(as_fake_dialog_photo(channel_full->photo, DialogId(channel_id)).small_file_id)
9731           .get_unique_file_id()) {
9732     channel_full->photo = Photo();
9733     if (c->photo.small_file_id.is_valid()) {
9734       channel_full->expires_at = 0.0;
9735     }
9736   }
9737   auto photo = std::move(channel_full->photo);
9738   on_update_channel_full_photo(channel_full, channel_id, std::move(photo));
9739 
9740   if (channel_full->participant_count < channel_full->administrator_count) {
9741     channel_full->participant_count = channel_full->administrator_count;
9742   }
9743   if (c->participant_count != 0 && c->participant_count != channel_full->participant_count) {
9744     channel_full->participant_count = c->participant_count;
9745 
9746     if (channel_full->participant_count < channel_full->administrator_count) {
9747       channel_full->participant_count = channel_full->administrator_count;
9748       channel_full->expires_at = 0.0;
9749 
9750       c->participant_count = channel_full->participant_count;
9751       c->is_changed = true;
9752       update_channel(c, channel_id);
9753     }
9754   }
9755 
9756   if (invalidated_channels_full_.erase(channel_id) > 0 ||
9757       (!c->is_slow_mode_enabled && channel_full->slow_mode_delay != 0)) {
9758     do_invalidate_channel_full(channel_full, channel_id, !c->is_slow_mode_enabled);
9759   }
9760 
9761   td_->group_call_manager_->on_update_dialog_about(DialogId(channel_id), channel_full->description, false);
9762 
9763   send_closure_later(G()->messages_manager(), &MessagesManager::on_dialog_bots_updated, DialogId(channel_id),
9764                      channel_full->bot_user_ids, true);
9765 
9766   channel_full->is_update_channel_full_sent = true;
9767   update_channel_full(channel_full, channel_id, "on_load_channel_full_from_database", true);
9768 
9769   if (channel_full->expires_at == 0.0) {
9770     load_channel_full(channel_id, true, Auto(), "on_load_channel_full_from_database");
9771   }
9772 }
9773 
get_channel_full_force(ChannelId channel_id,bool only_local,const char * source)9774 ContactsManager::ChannelFull *ContactsManager::get_channel_full_force(ChannelId channel_id, bool only_local,
9775                                                                       const char *source) {
9776   if (!have_channel_force(channel_id)) {
9777     return nullptr;
9778   }
9779 
9780   ChannelFull *channel_full = get_channel_full(channel_id, only_local, source);
9781   if (channel_full != nullptr) {
9782     return channel_full;
9783   }
9784   if (!G()->parameters().use_chat_info_db) {
9785     return nullptr;
9786   }
9787   if (!unavailable_channel_fulls_.insert(channel_id).second) {
9788     return nullptr;
9789   }
9790 
9791   LOG(INFO) << "Trying to load full " << channel_id << " from database from " << source;
9792   on_load_channel_full_from_database(
9793       channel_id, G()->td_db()->get_sqlite_sync_pmc()->get(get_channel_full_database_key(channel_id)), source);
9794   return get_channel_full(channel_id, only_local, source);
9795 }
9796 
for_each_secret_chat_with_user(UserId user_id,const std::function<void (SecretChatId)> & f)9797 void ContactsManager::for_each_secret_chat_with_user(UserId user_id, const std::function<void(SecretChatId)> &f) {
9798   auto it = secret_chats_with_user_.find(user_id);
9799   if (it != secret_chats_with_user_.end()) {
9800     for (auto secret_chat_id : it->second) {
9801       f(secret_chat_id);
9802     }
9803   }
9804 }
9805 
update_user(User * u,UserId user_id,bool from_binlog,bool from_database)9806 void ContactsManager::update_user(User *u, UserId user_id, bool from_binlog, bool from_database) {
9807   CHECK(u != nullptr);
9808   if (u->is_name_changed || u->is_username_changed || u->is_is_contact_changed) {
9809     update_contacts_hints(u, user_id, from_database);
9810     u->is_username_changed = false;
9811   }
9812   if (u->is_is_contact_changed) {
9813     td_->messages_manager_->on_dialog_user_is_contact_updated(DialogId(user_id), u->is_contact);
9814     if (is_user_contact(u, user_id, false)) {
9815       auto user_full = get_user_full(user_id);
9816       if (user_full != nullptr && user_full->need_phone_number_privacy_exception) {
9817         on_update_user_full_need_phone_number_privacy_exception(user_full, user_id, false);
9818         update_user_full(user_full, user_id, "update_user");
9819       }
9820     }
9821     u->is_is_contact_changed = false;
9822   }
9823   if (u->is_is_deleted_changed) {
9824     td_->messages_manager_->on_dialog_user_is_deleted_updated(DialogId(user_id), u->is_deleted);
9825     if (u->is_deleted) {
9826       auto user_full = get_user_full(user_id);  // must not load user_full from database before sending updateUser
9827       if (user_full != nullptr) {
9828         drop_user_full(user_id);
9829       }
9830     }
9831     u->is_is_deleted_changed = false;
9832   }
9833   if (u->is_name_changed) {
9834     auto messages_manager = td_->messages_manager_.get();
9835     messages_manager->on_dialog_title_updated(DialogId(user_id));
9836     for_each_secret_chat_with_user(user_id, [messages_manager](SecretChatId secret_chat_id) {
9837       messages_manager->on_dialog_title_updated(DialogId(secret_chat_id));
9838     });
9839     u->is_name_changed = false;
9840   }
9841   if (u->is_photo_changed) {
9842     auto messages_manager = td_->messages_manager_.get();
9843     messages_manager->on_dialog_photo_updated(DialogId(user_id));
9844     for_each_secret_chat_with_user(user_id, [messages_manager](SecretChatId secret_chat_id) {
9845       messages_manager->on_dialog_photo_updated(DialogId(secret_chat_id));
9846     });
9847     u->is_photo_changed = false;
9848   }
9849   if (u->is_status_changed && user_id != get_my_id()) {
9850     auto left_time = get_user_was_online(u, user_id) - G()->server_time_cached();
9851     if (left_time >= 0 && left_time < 30 * 86400) {
9852       left_time += 2.0;  // to guarantee expiration
9853       LOG(DEBUG) << "Set online timeout for " << user_id << " in " << left_time;
9854       user_online_timeout_.set_timeout_in(user_id.get(), left_time);
9855     } else {
9856       LOG(DEBUG) << "Cancel online timeout for " << user_id;
9857       user_online_timeout_.cancel_timeout(user_id.get());
9858     }
9859   }
9860   if (!td_->auth_manager_->is_bot()) {
9861     if (u->restriction_reasons.empty()) {
9862       restricted_user_ids_.erase(user_id);
9863     } else {
9864       restricted_user_ids_.insert(user_id);
9865     }
9866   }
9867 
9868   if (u->is_deleted) {
9869     td_->inline_queries_manager_->remove_recent_inline_bot(user_id, Promise<>());
9870   }
9871 
9872   LOG(DEBUG) << "Update " << user_id << ": need_save_to_database = " << u->need_save_to_database
9873              << ", is_changed = " << u->is_changed << ", is_status_changed = " << u->is_status_changed;
9874   u->need_save_to_database |= u->is_changed;
9875   if (u->need_save_to_database) {
9876     if (!from_database) {
9877       u->is_saved = false;
9878     }
9879     u->need_save_to_database = false;
9880   }
9881   if (u->is_changed) {
9882     send_closure(G()->td(), &Td::send_update, make_tl_object<td_api::updateUser>(get_user_object(user_id, u)));
9883     u->is_changed = false;
9884     u->is_status_changed = false;
9885     u->is_update_user_sent = true;
9886   }
9887   if (u->is_status_changed) {
9888     if (!from_database) {
9889       u->is_status_saved = false;
9890     }
9891     CHECK(u->is_update_user_sent);
9892     send_closure(G()->td(), &Td::send_update,
9893                  make_tl_object<td_api::updateUserStatus>(user_id.get(), get_user_status_object(user_id, u)));
9894     u->is_status_changed = false;
9895   }
9896   if (u->is_online_status_changed) {
9897     update_user_online_member_count(u);
9898     u->is_online_status_changed = false;
9899   }
9900 
9901   if (!from_database) {
9902     save_user(u, user_id, from_binlog);
9903   }
9904 
9905   if (u->cache_version != User::CACHE_VERSION && !u->is_repaired && have_input_peer_user(u, AccessRights::Read) &&
9906       !G()->close_flag()) {
9907     u->is_repaired = true;
9908 
9909     LOG(INFO) << "Repairing cache of " << user_id;
9910     reload_user(user_id, Promise<Unit>());
9911   }
9912 }
9913 
update_chat(Chat * c,ChatId chat_id,bool from_binlog,bool from_database)9914 void ContactsManager::update_chat(Chat *c, ChatId chat_id, bool from_binlog, bool from_database) {
9915   CHECK(c != nullptr);
9916   if (c->is_photo_changed) {
9917     td_->messages_manager_->on_dialog_photo_updated(DialogId(chat_id));
9918     drop_chat_photos(chat_id, !c->photo.small_file_id.is_valid(), true, "update_chat");
9919     c->is_photo_changed = false;
9920   }
9921   if (c->is_title_changed) {
9922     td_->messages_manager_->on_dialog_title_updated(DialogId(chat_id));
9923     c->is_title_changed = false;
9924   }
9925   if (c->is_default_permissions_changed) {
9926     td_->messages_manager_->on_dialog_default_permissions_updated(DialogId(chat_id));
9927     c->is_default_permissions_changed = false;
9928   }
9929   if (c->is_is_active_changed) {
9930     update_dialogs_for_discussion(DialogId(chat_id), c->is_active && c->status.is_creator());
9931     c->is_is_active_changed = false;
9932   }
9933   if (c->is_status_changed) {
9934     if (!c->status.can_manage_invite_links()) {
9935       td_->messages_manager_->drop_dialog_pending_join_requests(DialogId(chat_id));
9936     }
9937     c->is_status_changed = false;
9938   }
9939   if (c->is_noforwards_changed) {
9940     td_->messages_manager_->on_dialog_has_protected_content_updated(DialogId(chat_id));
9941     c->is_noforwards_changed = false;
9942   }
9943 
9944   LOG(DEBUG) << "Update " << chat_id << ": need_save_to_database = " << c->need_save_to_database
9945              << ", is_changed = " << c->is_changed;
9946   c->need_save_to_database |= c->is_changed;
9947   if (c->need_save_to_database) {
9948     if (!from_database) {
9949       c->is_saved = false;
9950     }
9951     c->need_save_to_database = false;
9952   }
9953   if (c->is_changed) {
9954     send_closure(G()->td(), &Td::send_update,
9955                  make_tl_object<td_api::updateBasicGroup>(get_basic_group_object(chat_id, c)));
9956     c->is_changed = false;
9957     c->is_update_basic_group_sent = true;
9958   }
9959 
9960   if (!from_database) {
9961     save_chat(c, chat_id, from_binlog);
9962   }
9963 
9964   if (c->cache_version != Chat::CACHE_VERSION && !c->is_repaired && have_input_peer_chat(c, AccessRights::Read) &&
9965       !G()->close_flag()) {
9966     c->is_repaired = true;
9967 
9968     LOG(INFO) << "Repairing cache of " << chat_id;
9969     reload_chat(chat_id, Promise<Unit>());
9970   }
9971 }
9972 
update_channel(Channel * c,ChannelId channel_id,bool from_binlog,bool from_database)9973 void ContactsManager::update_channel(Channel *c, ChannelId channel_id, bool from_binlog, bool from_database) {
9974   CHECK(c != nullptr);
9975   if (c->is_photo_changed) {
9976     td_->messages_manager_->on_dialog_photo_updated(DialogId(channel_id));
9977     drop_channel_photos(channel_id, !c->photo.small_file_id.is_valid(), true, "update_channel");
9978     c->is_photo_changed = false;
9979   }
9980   if (c->is_title_changed) {
9981     td_->messages_manager_->on_dialog_title_updated(DialogId(channel_id));
9982     c->is_title_changed = false;
9983   }
9984   if (c->is_status_changed) {
9985     c->status.update_restrictions();
9986     auto until_date = c->status.get_until_date();
9987     int32 left_time = 0;
9988     if (until_date > 0) {
9989       left_time = until_date - G()->unix_time_cached() + 1;
9990       CHECK(left_time > 0);
9991     }
9992     if (left_time > 0 && left_time < 366 * 86400) {
9993       channel_unban_timeout_.set_timeout_in(channel_id.get(), left_time);
9994     } else {
9995       channel_unban_timeout_.cancel_timeout(channel_id.get());
9996     }
9997 
9998     if (c->is_megagroup) {
9999       update_dialogs_for_discussion(DialogId(channel_id), c->status.is_administrator() && c->status.can_pin_messages());
10000     }
10001     if (!c->status.is_member()) {
10002       remove_inactive_channel(channel_id);
10003     }
10004     if (!c->status.can_manage_invite_links()) {
10005       td_->messages_manager_->drop_dialog_pending_join_requests(DialogId(channel_id));
10006     }
10007     c->is_status_changed = false;
10008   }
10009   if (c->is_username_changed) {
10010     if (c->status.is_creator()) {
10011       update_created_public_channels(c, channel_id);
10012     }
10013     c->is_username_changed = false;
10014   }
10015   if (c->is_default_permissions_changed) {
10016     td_->messages_manager_->on_dialog_default_permissions_updated(DialogId(channel_id));
10017     if (c->default_permissions !=
10018         RestrictedRights(false, false, false, false, false, false, false, false, false, false, false)) {
10019       remove_dialog_suggested_action(SuggestedAction{SuggestedAction::Type::ConvertToGigagroup, DialogId(channel_id)});
10020     }
10021     c->is_default_permissions_changed = false;
10022   }
10023   if (c->is_has_location_changed) {
10024     if (c->status.is_creator()) {
10025       update_created_public_channels(c, channel_id);
10026     }
10027     c->is_has_location_changed = false;
10028   }
10029   if (c->is_creator_changed) {
10030     update_created_public_channels(c, channel_id);
10031     c->is_creator_changed = false;
10032   }
10033   if (c->is_noforwards_changed) {
10034     td_->messages_manager_->on_dialog_has_protected_content_updated(DialogId(channel_id));
10035     c->is_noforwards_changed = false;
10036   }
10037 
10038   if (!td_->auth_manager_->is_bot()) {
10039     if (c->restriction_reasons.empty()) {
10040       restricted_channel_ids_.erase(channel_id);
10041     } else {
10042       restricted_channel_ids_.insert(channel_id);
10043     }
10044   }
10045 
10046   LOG(DEBUG) << "Update " << channel_id << ": need_save_to_database = " << c->need_save_to_database
10047              << ", is_changed = " << c->is_changed;
10048   c->need_save_to_database |= c->is_changed;
10049   if (c->need_save_to_database) {
10050     if (!from_database) {
10051       c->is_saved = false;
10052     }
10053     c->need_save_to_database = false;
10054   }
10055   if (c->is_changed) {
10056     send_closure(G()->td(), &Td::send_update,
10057                  make_tl_object<td_api::updateSupergroup>(get_supergroup_object(channel_id, c)));
10058     c->is_changed = false;
10059     c->is_update_supergroup_sent = true;
10060   }
10061 
10062   if (!from_database) {
10063     save_channel(c, channel_id, from_binlog);
10064   }
10065 
10066   bool have_read_access = have_input_peer_channel(c, channel_id, AccessRights::Read);
10067   bool is_member = c->status.is_member();
10068   if (c->had_read_access && !have_read_access) {
10069     send_closure_later(G()->messages_manager(), &MessagesManager::on_dialog_deleted, DialogId(channel_id),
10070                        Promise<Unit>());
10071   } else if (!from_database && c->was_member != is_member) {
10072     DialogId dialog_id(channel_id);
10073     send_closure_later(G()->messages_manager(), &MessagesManager::force_create_dialog, dialog_id, "update channel",
10074                        true, true);
10075   }
10076   c->had_read_access = have_read_access;
10077   c->was_member = is_member;
10078 
10079   if (c->cache_version != Channel::CACHE_VERSION && !c->is_repaired &&
10080       have_input_peer_channel(c, channel_id, AccessRights::Read) && !G()->close_flag()) {
10081     c->is_repaired = true;
10082 
10083     LOG(INFO) << "Repairing cache of " << channel_id;
10084     reload_channel(channel_id, Promise<Unit>());
10085   }
10086 }
10087 
update_secret_chat(SecretChat * c,SecretChatId secret_chat_id,bool from_binlog,bool from_database)10088 void ContactsManager::update_secret_chat(SecretChat *c, SecretChatId secret_chat_id, bool from_binlog,
10089                                          bool from_database) {
10090   CHECK(c != nullptr);
10091   LOG(DEBUG) << "Update " << secret_chat_id << ": need_save_to_database = " << c->need_save_to_database
10092              << ", is_changed = " << c->is_changed;
10093   c->need_save_to_database |= c->is_changed;
10094   if (c->need_save_to_database) {
10095     if (!from_database) {
10096       c->is_saved = false;
10097     }
10098     c->need_save_to_database = false;
10099 
10100     DialogId dialog_id(secret_chat_id);
10101     send_closure_later(G()->messages_manager(), &MessagesManager::force_create_dialog, dialog_id, "update secret chat",
10102                        true, true);
10103     if (c->is_state_changed) {
10104       send_closure_later(G()->messages_manager(), &MessagesManager::on_update_secret_chat_state, secret_chat_id,
10105                          c->state);
10106       c->is_state_changed = false;
10107     }
10108     if (c->is_ttl_changed) {
10109       send_closure_later(G()->messages_manager(), &MessagesManager::on_update_dialog_message_ttl_setting,
10110                          DialogId(secret_chat_id), MessageTtlSetting(c->ttl));
10111       c->is_ttl_changed = false;
10112     }
10113   }
10114   if (c->is_changed) {
10115     send_closure(G()->td(), &Td::send_update,
10116                  make_tl_object<td_api::updateSecretChat>(get_secret_chat_object(secret_chat_id, c)));
10117     c->is_changed = false;
10118   }
10119 
10120   if (!from_database) {
10121     save_secret_chat(c, secret_chat_id, from_binlog);
10122   }
10123 }
10124 
update_user_full(UserFull * user_full,UserId user_id,const char * source,bool from_database)10125 void ContactsManager::update_user_full(UserFull *user_full, UserId user_id, const char *source, bool from_database) {
10126   CHECK(user_full != nullptr);
10127   unavailable_user_fulls_.erase(user_id);  // don't needed anymore
10128   if (user_full->is_common_chat_count_changed) {
10129     td_->messages_manager_->drop_common_dialogs_cache(user_id);
10130     user_full->is_common_chat_count_changed = false;
10131   }
10132 
10133   user_full->need_send_update |= user_full->is_changed;
10134   user_full->need_save_to_database |= user_full->is_changed;
10135   user_full->is_changed = false;
10136   if (user_full->need_send_update || user_full->need_save_to_database) {
10137     LOG(INFO) << "Update full " << user_id << " from " << source;
10138   }
10139   if (user_full->need_send_update) {
10140     {
10141       auto u = get_user(user_id);
10142       CHECK(u == nullptr || u->is_update_user_sent);
10143     }
10144     if (!user_full->is_update_user_full_sent) {
10145       LOG(ERROR) << "Send partial updateUserFullInfo for " << user_id << " from " << source;
10146       user_full->is_update_user_full_sent = true;
10147     }
10148     send_closure(G()->td(), &Td::send_update,
10149                  make_tl_object<td_api::updateUserFullInfo>(get_user_id_object(user_id, "updateUserFullInfo"),
10150                                                             get_user_full_info_object(user_id, user_full)));
10151     user_full->need_send_update = false;
10152   }
10153   if (user_full->need_save_to_database) {
10154     if (!from_database) {
10155       save_user_full(user_full, user_id);
10156     }
10157     user_full->need_save_to_database = false;
10158   }
10159 }
10160 
update_chat_full(ChatFull * chat_full,ChatId chat_id,const char * source,bool from_database)10161 void ContactsManager::update_chat_full(ChatFull *chat_full, ChatId chat_id, const char *source, bool from_database) {
10162   CHECK(chat_full != nullptr);
10163   unavailable_chat_fulls_.erase(chat_id);  // don't needed anymore
10164 
10165   chat_full->need_send_update |= chat_full->is_changed;
10166   chat_full->need_save_to_database |= chat_full->is_changed;
10167   chat_full->is_changed = false;
10168   if (chat_full->need_send_update || chat_full->need_save_to_database) {
10169     LOG(INFO) << "Update full " << chat_id << " from " << source;
10170   }
10171   if (chat_full->need_send_update) {
10172     vector<DialogAdministrator> administrators;
10173     vector<UserId> bot_user_ids;
10174     for (const auto &participant : chat_full->participants) {
10175       if (participant.status_.is_administrator() && participant.dialog_id_.get_type() == DialogType::User) {
10176         administrators.emplace_back(participant.dialog_id_.get_user_id(), participant.status_.get_rank(),
10177                                     participant.status_.is_creator());
10178       }
10179       if (participant.dialog_id_.get_type() == DialogType::User) {
10180         auto user_id = participant.dialog_id_.get_user_id();
10181         if (is_user_bot(user_id)) {
10182           bot_user_ids.push_back(user_id);
10183         }
10184       }
10185     }
10186     td::remove_if(chat_full->bot_commands, [&bot_user_ids](const BotCommands &commands) {
10187       return !td::contains(bot_user_ids, commands.get_bot_user_id());
10188     });
10189 
10190     on_update_dialog_administrators(DialogId(chat_id), std::move(administrators), chat_full->version != -1,
10191                                     from_database);
10192     send_closure_later(G()->messages_manager(), &MessagesManager::on_dialog_bots_updated, DialogId(chat_id),
10193                        std::move(bot_user_ids), from_database);
10194 
10195     {
10196       Chat *c = get_chat(chat_id);
10197       CHECK(c == nullptr || c->is_update_basic_group_sent);
10198     }
10199     if (!chat_full->is_update_chat_full_sent) {
10200       LOG(ERROR) << "Send partial updateBasicGroupFullInfo for " << chat_id << " from " << source;
10201       chat_full->is_update_chat_full_sent = true;
10202     }
10203     send_closure(
10204         G()->td(), &Td::send_update,
10205         make_tl_object<td_api::updateBasicGroupFullInfo>(get_basic_group_id_object(chat_id, "update_chat_full"),
10206                                                          get_basic_group_full_info_object(chat_full)));
10207     chat_full->need_send_update = false;
10208   }
10209   if (chat_full->need_save_to_database) {
10210     if (!from_database) {
10211       save_chat_full(chat_full, chat_id);
10212     }
10213     chat_full->need_save_to_database = false;
10214   }
10215 }
10216 
update_channel_full(ChannelFull * channel_full,ChannelId channel_id,const char * source,bool from_database)10217 void ContactsManager::update_channel_full(ChannelFull *channel_full, ChannelId channel_id, const char *source,
10218                                           bool from_database) {
10219   CHECK(channel_full != nullptr);
10220   unavailable_channel_fulls_.erase(channel_id);  // don't needed anymore
10221 
10222   CHECK(channel_full->participant_count >= channel_full->administrator_count);
10223 
10224   if (channel_full->is_slow_mode_next_send_date_changed) {
10225     auto now = G()->server_time();
10226     if (channel_full->slow_mode_next_send_date > now + 3601) {
10227       channel_full->slow_mode_next_send_date = static_cast<int32>(now) + 3601;
10228     }
10229     if (channel_full->slow_mode_next_send_date <= now) {
10230       channel_full->slow_mode_next_send_date = 0;
10231     }
10232     if (channel_full->slow_mode_next_send_date == 0) {
10233       slow_mode_delay_timeout_.cancel_timeout(channel_id.get());
10234     } else {
10235       slow_mode_delay_timeout_.set_timeout_in(channel_id.get(), channel_full->slow_mode_next_send_date - now + 0.002);
10236     }
10237     channel_full->is_slow_mode_next_send_date_changed = false;
10238   }
10239 
10240   if (channel_full->need_save_to_database) {
10241     channel_full->is_changed |= td::remove_if(
10242         channel_full->bot_commands, [bot_user_ids = &channel_full->bot_user_ids](const BotCommands &commands) {
10243           return !td::contains(*bot_user_ids, commands.get_bot_user_id());
10244         });
10245   }
10246 
10247   channel_full->need_send_update |= channel_full->is_changed;
10248   channel_full->need_save_to_database |= channel_full->is_changed;
10249   channel_full->is_changed = false;
10250   if (channel_full->need_send_update || channel_full->need_save_to_database) {
10251     LOG(INFO) << "Update full " << channel_id << " from " << source;
10252   }
10253   if (channel_full->need_send_update) {
10254     if (channel_full->linked_channel_id.is_valid()) {
10255       td_->messages_manager_->force_create_dialog(DialogId(channel_full->linked_channel_id), "update_channel_full",
10256                                                   true);
10257     }
10258 
10259     {
10260       Channel *c = get_channel(channel_id);
10261       CHECK(c == nullptr || c->is_update_supergroup_sent);
10262     }
10263     if (!channel_full->is_update_channel_full_sent) {
10264       LOG(ERROR) << "Send partial updateSupergroupFullInfo for " << channel_id << " from " << source;
10265       channel_full->is_update_channel_full_sent = true;
10266     }
10267     send_closure(
10268         G()->td(), &Td::send_update,
10269         make_tl_object<td_api::updateSupergroupFullInfo>(get_supergroup_id_object(channel_id, "update_channel_full"),
10270                                                          get_supergroup_full_info_object(channel_full, channel_id)));
10271     channel_full->need_send_update = false;
10272   }
10273   if (channel_full->need_save_to_database) {
10274     if (!from_database) {
10275       save_channel_full(channel_full, channel_id);
10276     }
10277     channel_full->need_save_to_database = false;
10278   }
10279 }
10280 
on_get_users(vector<tl_object_ptr<telegram_api::User>> && users,const char * source)10281 void ContactsManager::on_get_users(vector<tl_object_ptr<telegram_api::User>> &&users, const char *source) {
10282   for (auto &user : users) {
10283     on_get_user(std::move(user), source);
10284   }
10285 }
10286 
on_get_user_full(tl_object_ptr<telegram_api::userFull> && user)10287 void ContactsManager::on_get_user_full(tl_object_ptr<telegram_api::userFull> &&user) {
10288   UserId user_id(user->id_);
10289   User *u = get_user(user_id);
10290   if (u == nullptr) {
10291     LOG(ERROR) << "Failed to find " << user_id;
10292     return;
10293   }
10294 
10295   td_->messages_manager_->on_update_dialog_notify_settings(DialogId(user_id), std::move(user->notify_settings_),
10296                                                            "on_get_user_full");
10297 
10298   td_->messages_manager_->on_update_dialog_theme_name(DialogId(user_id), std::move(user->theme_emoticon_));
10299 
10300   {
10301     MessageId pinned_message_id;
10302     if ((user->flags_ & USER_FULL_FLAG_HAS_PINNED_MESSAGE) != 0) {
10303       pinned_message_id = MessageId(ServerMessageId(user->pinned_msg_id_));
10304     }
10305     td_->messages_manager_->on_update_dialog_last_pinned_message_id(DialogId(user_id), pinned_message_id);
10306   }
10307   {
10308     FolderId folder_id;
10309     if ((user->flags_ & USER_FULL_FLAG_HAS_FOLDER_ID) != 0) {
10310       folder_id = FolderId(user->folder_id_);
10311     }
10312     td_->messages_manager_->on_update_dialog_folder_id(DialogId(user_id), folder_id);
10313   }
10314   td_->messages_manager_->on_update_dialog_has_scheduled_server_messages(
10315       DialogId(user_id), (user->flags_ & USER_FULL_FLAG_HAS_SCHEDULED_MESSAGES) != 0);
10316   {
10317     MessageTtlSetting message_ttl_setting;
10318     if ((user->flags_ & USER_FULL_FLAG_HAS_MESSAGE_TTL) != 0) {
10319       message_ttl_setting = MessageTtlSetting(user->ttl_period_);
10320     }
10321     td_->messages_manager_->on_update_dialog_message_ttl_setting(DialogId(user_id), message_ttl_setting);
10322   }
10323 
10324   UserFull *user_full = add_user_full(user_id);
10325   user_full->expires_at = Time::now() + USER_FULL_EXPIRE_TIME;
10326 
10327   {
10328     bool is_blocked = (user->flags_ & USER_FULL_FLAG_IS_BLOCKED) != 0;
10329     on_update_user_full_is_blocked(user_full, user_id, is_blocked);
10330     td_->messages_manager_->on_update_dialog_is_blocked(DialogId(user_id), is_blocked);
10331   }
10332 
10333   on_update_user_full_common_chat_count(user_full, user_id, user->common_chats_count_);
10334   on_update_user_full_need_phone_number_privacy_exception(user_full, user_id,
10335                                                           user->settings_->need_contacts_exception_);
10336 
10337   bool can_pin_messages = user->can_pin_message_;
10338   if (user_full->can_pin_messages != can_pin_messages) {
10339     user_full->can_pin_messages = can_pin_messages;
10340     user_full->is_changed = true;
10341   }
10342 
10343   bool can_be_called = user->phone_calls_available_ && !user->phone_calls_private_;
10344   bool supports_video_calls = user->video_calls_available_ && !user->phone_calls_private_;
10345   bool has_private_calls = user->phone_calls_private_;
10346   if (user_full->can_be_called != can_be_called || user_full->supports_video_calls != supports_video_calls ||
10347       user_full->has_private_calls != has_private_calls ||
10348       user_full->private_forward_name != user->private_forward_name_) {
10349     user_full->can_be_called = can_be_called;
10350     user_full->supports_video_calls = supports_video_calls;
10351     user_full->has_private_calls = has_private_calls;
10352     user_full->private_forward_name = std::move(user->private_forward_name_);
10353 
10354     user_full->is_changed = true;
10355   }
10356   if (user_full->about != user->about_) {
10357     user_full->about = std::move(user->about_);
10358     user_full->is_changed = true;
10359     td_->group_call_manager_->on_update_dialog_about(DialogId(user_id), user_full->about, true);
10360   }
10361   string description;
10362   if (user->bot_info_ != nullptr && !td_->auth_manager_->is_bot()) {
10363     description = std::move(user->bot_info_->description_);
10364 
10365     on_update_user_full_commands(user_full, user_id, std::move(user->bot_info_->commands_));
10366   }
10367   if (user_full->description != description) {
10368     user_full->description = std::move(description);
10369     user_full->is_changed = true;
10370   }
10371 
10372   auto photo = get_photo(td_->file_manager_.get(), std::move(user->profile_photo_), DialogId(user_id));
10373   if (photo != user_full->photo) {
10374     user_full->photo = std::move(photo);
10375     user_full->is_changed = true;
10376   }
10377   if (user_full->photo.is_empty()) {
10378     drop_user_photos(user_id, true, false, "on_get_user_full");
10379   } else {
10380     register_user_photo(u, user_id, user_full->photo);
10381   }
10382 
10383   user_full->is_update_user_full_sent = true;
10384   update_user_full(user_full, user_id, "on_get_user_full");
10385 
10386   // update peer settings after UserFull is created and updated to not update twice need_phone_number_privacy_exception
10387   td_->messages_manager_->on_get_peer_settings(DialogId(user_id), std::move(user->settings_));
10388 }
10389 
on_get_user_photos(UserId user_id,int32 offset,int32 limit,int32 total_count,vector<tl_object_ptr<telegram_api::Photo>> photos)10390 void ContactsManager::on_get_user_photos(UserId user_id, int32 offset, int32 limit, int32 total_count,
10391                                          vector<tl_object_ptr<telegram_api::Photo>> photos) {
10392   auto photo_count = narrow_cast<int32>(photos.size());
10393   int32 min_total_count = (offset >= 0 && photo_count > 0 ? offset : 0) + photo_count;
10394   if (total_count < min_total_count) {
10395     LOG(ERROR) << "Wrong photos total_count " << total_count << ". Receive " << photo_count << " photos with offset "
10396                << offset;
10397     total_count = min_total_count;
10398   }
10399   LOG_IF(ERROR, limit < photo_count) << "Requested not more than " << limit << " photos, but " << photo_count
10400                                      << " received";
10401 
10402   User *u = get_user(user_id);
10403   if (u == nullptr) {
10404     LOG(ERROR) << "Can't find " << user_id;
10405     return;
10406   }
10407 
10408   if (offset == -1) {
10409     // from reload_user_profile_photo
10410     CHECK(limit == 1);
10411     for (auto &photo_ptr : photos) {
10412       if (photo_ptr->get_id() == telegram_api::photo::ID) {
10413         auto server_photo = telegram_api::move_object_as<telegram_api::photo>(photo_ptr);
10414         if (server_photo->id_ == u->photo.id) {
10415           auto profile_photo = convert_photo_to_profile_photo(server_photo);
10416           if (profile_photo) {
10417             LOG_IF(ERROR, u->access_hash == -1) << "Receive profile photo of " << user_id << " without access hash";
10418             get_profile_photo(td_->file_manager_.get(), user_id, u->access_hash, std::move(profile_photo));
10419           } else {
10420             LOG(ERROR) << "Failed to get profile photo from " << to_string(server_photo);
10421           }
10422         }
10423 
10424         auto photo = get_photo(td_->file_manager_.get(), std::move(server_photo), DialogId(user_id));
10425         register_user_photo(u, user_id, photo);
10426       }
10427     }
10428     return;
10429   }
10430 
10431   LOG(INFO) << "Receive " << photo_count << " photos of " << user_id << " out of " << total_count << " with offset "
10432             << offset << " and limit " << limit;
10433   UserPhotos *user_photos = &user_photos_[user_id];
10434   user_photos->count = total_count;
10435   CHECK(user_photos->getting_now);
10436   user_photos->getting_now = false;
10437 
10438   if (user_photos->offset == -1) {
10439     user_photos->offset = 0;
10440     CHECK(user_photos->photos.empty());
10441   }
10442 
10443   if (offset != narrow_cast<int32>(user_photos->photos.size()) + user_photos->offset) {
10444     LOG(INFO) << "Inappropriate offset to append " << user_id << " profile photos to cache: offset = " << offset
10445               << ", current_offset = " << user_photos->offset << ", photo_count = " << user_photos->photos.size();
10446     user_photos->photos.clear();
10447     user_photos->offset = offset;
10448   }
10449 
10450   for (auto &photo : photos) {
10451     auto user_photo = get_photo(td_->file_manager_.get(), std::move(photo), DialogId(user_id));
10452     if (user_photo.is_empty()) {
10453       LOG(ERROR) << "Receive empty profile photo in getUserPhotos request for " << user_id << " with offset " << offset
10454                  << " and limit " << limit << ". Receive " << photo_count << " photos out of " << total_count
10455                  << " photos";
10456       user_photos->count--;
10457       CHECK(user_photos->count >= 0);
10458       continue;
10459     }
10460 
10461     user_photos->photos.push_back(std::move(user_photo));
10462     register_user_photo(u, user_id, user_photos->photos.back());
10463   }
10464   if (user_photos->offset > user_photos->count) {
10465     user_photos->offset = user_photos->count;
10466     user_photos->photos.clear();
10467   }
10468 
10469   auto known_photo_count = narrow_cast<int32>(user_photos->photos.size());
10470   if (user_photos->offset + known_photo_count > user_photos->count) {
10471     user_photos->photos.resize(user_photos->count - user_photos->offset);
10472   }
10473 }
10474 
on_get_chat(tl_object_ptr<telegram_api::Chat> && chat,const char * source)10475 void ContactsManager::on_get_chat(tl_object_ptr<telegram_api::Chat> &&chat, const char *source) {
10476   LOG(DEBUG) << "Receive from " << source << ' ' << to_string(chat);
10477   downcast_call(*chat, [this, source](auto &c) { this->on_chat_update(c, source); });
10478 }
10479 
on_get_chats(vector<tl_object_ptr<telegram_api::Chat>> && chats,const char * source)10480 void ContactsManager::on_get_chats(vector<tl_object_ptr<telegram_api::Chat>> &&chats, const char *source) {
10481   for (auto &chat : chats) {
10482     auto constuctor_id = chat->get_id();
10483     if (constuctor_id == telegram_api::channel::ID || constuctor_id == telegram_api::channelForbidden::ID) {
10484       // apply info about megagroups before corresponding chats
10485       on_get_chat(std::move(chat), source);
10486       chat = nullptr;
10487     }
10488   }
10489   for (auto &chat : chats) {
10490     if (chat != nullptr) {
10491       on_get_chat(std::move(chat), source);
10492       chat = nullptr;
10493     }
10494   }
10495 }
10496 
get_bot_commands(vector<tl_object_ptr<telegram_api::botInfo>> && bot_infos,const vector<DialogParticipant> * participants)10497 vector<BotCommands> ContactsManager::get_bot_commands(vector<tl_object_ptr<telegram_api::botInfo>> &&bot_infos,
10498                                                       const vector<DialogParticipant> *participants) {
10499   vector<BotCommands> result;
10500   if (td_->auth_manager_->is_bot()) {
10501     return result;
10502   }
10503   for (auto &bot_info : bot_infos) {
10504     if (bot_info->commands_.empty()) {
10505       continue;
10506     }
10507 
10508     auto user_id = UserId(bot_info->user_id_);
10509     if (!have_user_force(user_id)) {
10510       LOG(ERROR) << "Receive unknown " << user_id;
10511       continue;
10512     }
10513     if (!is_user_bot(user_id)) {
10514       if (!is_user_deleted(user_id)) {
10515         LOG(ERROR) << "Receive non-bot " << user_id;
10516       }
10517       continue;
10518     }
10519     if (participants != nullptr) {
10520       bool is_participant = false;
10521       for (auto &participant : *participants) {
10522         if (participant.dialog_id_ == DialogId(user_id)) {
10523           is_participant = true;
10524           break;
10525         }
10526       }
10527       if (!is_participant) {
10528         LOG(ERROR) << "Skip commands of non-member bot " << user_id;
10529         continue;
10530       }
10531     }
10532     result.emplace_back(user_id, std::move(bot_info->commands_));
10533   }
10534   return result;
10535 }
10536 
on_get_chat_full(tl_object_ptr<telegram_api::ChatFull> && chat_full_ptr,Promise<Unit> && promise)10537 void ContactsManager::on_get_chat_full(tl_object_ptr<telegram_api::ChatFull> &&chat_full_ptr, Promise<Unit> &&promise) {
10538   LOG(INFO) << "Receive " << to_string(chat_full_ptr);
10539   if (chat_full_ptr->get_id() == telegram_api::chatFull::ID) {
10540     auto chat = move_tl_object_as<telegram_api::chatFull>(chat_full_ptr);
10541     ChatId chat_id(chat->id_);
10542     if (!chat_id.is_valid()) {
10543       LOG(ERROR) << "Receive invalid " << chat_id;
10544       return promise.set_value(Unit());
10545     }
10546 
10547     {
10548       MessageId pinned_message_id;
10549       if ((chat->flags_ & CHAT_FULL_FLAG_HAS_PINNED_MESSAGE) != 0) {
10550         pinned_message_id = MessageId(ServerMessageId(chat->pinned_msg_id_));
10551       }
10552       Chat *c = get_chat(chat_id);
10553       if (c == nullptr) {
10554         LOG(ERROR) << "Can't find " << chat_id;
10555         return promise.set_value(Unit());
10556       } else if (c->version >= c->pinned_message_version) {
10557         LOG(INFO) << "Receive pinned " << pinned_message_id << " in " << chat_id << " with version " << c->version
10558                   << ". Current version is " << c->pinned_message_version;
10559         td_->messages_manager_->on_update_dialog_last_pinned_message_id(DialogId(chat_id), pinned_message_id);
10560         if (c->version > c->pinned_message_version) {
10561           c->pinned_message_version = c->version;
10562           c->need_save_to_database = true;
10563           update_chat(c, chat_id);
10564         }
10565       }
10566     }
10567     {
10568       FolderId folder_id;
10569       if ((chat->flags_ & CHAT_FULL_FLAG_HAS_FOLDER_ID) != 0) {
10570         folder_id = FolderId(chat->folder_id_);
10571       }
10572       td_->messages_manager_->on_update_dialog_folder_id(DialogId(chat_id), folder_id);
10573     }
10574     td_->messages_manager_->on_update_dialog_has_scheduled_server_messages(
10575         DialogId(chat_id), (chat->flags_ & CHAT_FULL_FLAG_HAS_SCHEDULED_MESSAGES) != 0);
10576     {
10577       InputGroupCallId input_group_call_id;
10578       if (chat->call_ != nullptr) {
10579         input_group_call_id = InputGroupCallId(chat->call_);
10580       }
10581       td_->messages_manager_->on_update_dialog_group_call_id(DialogId(chat_id), input_group_call_id);
10582     }
10583     {
10584       DialogId default_join_group_call_as_dialog_id;
10585       if (chat->groupcall_default_join_as_ != nullptr) {
10586         default_join_group_call_as_dialog_id = DialogId(chat->groupcall_default_join_as_);
10587       }
10588       // use send closure later to not create synchronously default_join_group_call_as_dialog_id
10589       send_closure_later(G()->messages_manager(),
10590                          &MessagesManager::on_update_dialog_default_join_group_call_as_dialog_id, DialogId(chat_id),
10591                          default_join_group_call_as_dialog_id, false);
10592     }
10593     {
10594       MessageTtlSetting message_ttl_setting;
10595       if ((chat->flags_ & CHAT_FULL_FLAG_HAS_MESSAGE_TTL) != 0) {
10596         message_ttl_setting = MessageTtlSetting(chat->ttl_period_);
10597       }
10598       td_->messages_manager_->on_update_dialog_message_ttl_setting(DialogId(chat_id), message_ttl_setting);
10599     }
10600 
10601     ChatFull *chat_full = add_chat_full(chat_id);
10602     on_update_chat_full_invite_link(chat_full, std::move(chat->exported_invite_));
10603     on_update_chat_full_photo(chat_full, chat_id,
10604                               get_photo(td_->file_manager_.get(), std::move(chat->chat_photo_), DialogId(chat_id)));
10605     if (chat_full->description != chat->about_) {
10606       chat_full->description = std::move(chat->about_);
10607       chat_full->is_changed = true;
10608       td_->group_call_manager_->on_update_dialog_about(DialogId(chat_id), chat_full->description, true);
10609     }
10610     if (chat_full->can_set_username != chat->can_set_username_) {
10611       chat_full->can_set_username = chat->can_set_username_;
10612       chat_full->is_changed = true;
10613     }
10614 
10615     on_get_chat_participants(std::move(chat->participants_), false);
10616     td_->messages_manager_->on_update_dialog_notify_settings(DialogId(chat_id), std::move(chat->notify_settings_),
10617                                                              "on_get_chat_full");
10618 
10619     td_->messages_manager_->on_update_dialog_theme_name(DialogId(chat_id), std::move(chat->theme_emoticon_));
10620 
10621     td_->messages_manager_->on_update_dialog_pending_join_requests(DialogId(chat_id), chat->requests_pending_,
10622                                                                    std::move(chat->recent_requesters_));
10623 
10624     auto bot_commands = get_bot_commands(std::move(chat->bot_info_), &chat_full->participants);
10625     if (chat_full->bot_commands != bot_commands) {
10626       chat_full->bot_commands = std::move(bot_commands);
10627       chat_full->is_changed = true;
10628     }
10629 
10630     chat_full->is_update_chat_full_sent = true;
10631     update_chat_full(chat_full, chat_id, "on_get_chat_full");
10632   } else {
10633     CHECK(chat_full_ptr->get_id() == telegram_api::channelFull::ID);
10634     auto channel = move_tl_object_as<telegram_api::channelFull>(chat_full_ptr);
10635     ChannelId channel_id(channel->id_);
10636     if (!channel_id.is_valid()) {
10637       LOG(ERROR) << "Receive invalid " << channel_id;
10638       return promise.set_value(Unit());
10639     }
10640 
10641     invalidated_channels_full_.erase(channel_id);
10642 
10643     if (!G()->close_flag()) {
10644       auto channel_full = get_channel_full(channel_id, true, "on_get_channel_full");
10645       if (channel_full != nullptr) {
10646         if (channel_full->repair_request_version != 0 &&
10647             channel_full->repair_request_version < channel_full->speculative_version) {
10648           LOG(INFO) << "Receive ChannelFull with request version " << channel_full->repair_request_version
10649                     << ", but current speculative version is " << channel_full->speculative_version;
10650 
10651           channel_full->repair_request_version = channel_full->speculative_version;
10652 
10653           auto input_channel = get_input_channel(channel_id);
10654           CHECK(input_channel != nullptr);
10655           td_->create_handler<GetFullChannelQuery>(std::move(promise))->send(channel_id, std::move(input_channel));
10656           return;
10657         }
10658         channel_full->repair_request_version = 0;
10659       }
10660     }
10661 
10662     td_->messages_manager_->on_update_dialog_notify_settings(DialogId(channel_id), std::move(channel->notify_settings_),
10663                                                              "on_get_channel_full");
10664 
10665     td_->messages_manager_->on_update_dialog_theme_name(DialogId(channel_id), std::move(channel->theme_emoticon_));
10666 
10667     td_->messages_manager_->on_update_dialog_pending_join_requests(DialogId(channel_id), channel->requests_pending_,
10668                                                                    std::move(channel->recent_requesters_));
10669 
10670     {
10671       MessageTtlSetting message_ttl_setting;
10672       if ((channel->flags_ & CHANNEL_FULL_FLAG_HAS_MESSAGE_TTL) != 0) {
10673         message_ttl_setting = MessageTtlSetting(channel->ttl_period_);
10674       }
10675       td_->messages_manager_->on_update_dialog_message_ttl_setting(DialogId(channel_id), message_ttl_setting);
10676     }
10677 
10678     auto c = get_channel(channel_id);
10679     if (c == nullptr) {
10680       LOG(ERROR) << channel_id << " not found";
10681       return promise.set_value(Unit());
10682     }
10683 
10684     ChannelFull *channel_full = add_channel_full(channel_id);
10685 
10686     bool have_participant_count = (channel->flags_ & CHANNEL_FULL_FLAG_HAS_PARTICIPANT_COUNT) != 0;
10687     auto participant_count = have_participant_count ? channel->participants_count_ : channel_full->participant_count;
10688     auto administrator_count = 0;
10689     if ((channel->flags_ & CHANNEL_FULL_FLAG_HAS_ADMINISTRATOR_COUNT) != 0) {
10690       administrator_count = channel->admins_count_;
10691     } else if (c->is_megagroup || c->status.is_administrator()) {
10692       // in megagroups and administered channels don't drop known number of administrators
10693       administrator_count = channel_full->administrator_count;
10694     }
10695     if (participant_count < administrator_count) {
10696       participant_count = administrator_count;
10697     }
10698     auto restricted_count = (channel->flags_ & CHANNEL_FULL_FLAG_HAS_BANNED_COUNT) != 0 ? channel->banned_count_ : 0;
10699     auto banned_count = (channel->flags_ & CHANNEL_FULL_FLAG_HAS_BANNED_COUNT) != 0 ? channel->kicked_count_ : 0;
10700     auto can_get_participants = (channel->flags_ & CHANNEL_FULL_FLAG_CAN_GET_PARTICIPANTS) != 0;
10701     auto can_set_username = (channel->flags_ & CHANNEL_FULL_FLAG_CAN_SET_USERNAME) != 0;
10702     auto can_set_sticker_set = (channel->flags_ & CHANNEL_FULL_FLAG_CAN_SET_STICKER_SET) != 0;
10703     auto can_set_location = (channel->flags_ & CHANNEL_FULL_FLAG_CAN_SET_LOCATION) != 0;
10704     auto is_all_history_available = (channel->flags_ & CHANNEL_FULL_FLAG_IS_ALL_HISTORY_HIDDEN) == 0;
10705     auto can_view_statistics = (channel->flags_ & CHANNEL_FULL_FLAG_CAN_VIEW_STATISTICS) != 0;
10706     StickerSetId sticker_set_id;
10707     if (channel->stickerset_ != nullptr) {
10708       sticker_set_id =
10709           td_->stickers_manager_->on_get_sticker_set(std::move(channel->stickerset_), true, "on_get_channel_full");
10710     }
10711     DcId stats_dc_id;
10712     if ((channel->flags_ & CHANNEL_FULL_FLAG_HAS_STATISTICS_DC_ID) != 0) {
10713       stats_dc_id = DcId::create(channel->stats_dc_);
10714     }
10715     if (!stats_dc_id.is_exact() && can_view_statistics) {
10716       LOG(ERROR) << "Receive can_view_statistics == true, but invalid statistics DC ID in " << channel_id;
10717       can_view_statistics = false;
10718     }
10719 
10720     channel_full->repair_request_version = 0;
10721     channel_full->expires_at = Time::now() + CHANNEL_FULL_EXPIRE_TIME;
10722     if (channel_full->participant_count != participant_count ||
10723         channel_full->administrator_count != administrator_count ||
10724         channel_full->restricted_count != restricted_count || channel_full->banned_count != banned_count ||
10725         channel_full->can_get_participants != can_get_participants ||
10726         channel_full->can_set_username != can_set_username ||
10727         channel_full->can_set_sticker_set != can_set_sticker_set ||
10728         channel_full->can_set_location != can_set_location ||
10729         channel_full->can_view_statistics != can_view_statistics || channel_full->stats_dc_id != stats_dc_id ||
10730         channel_full->sticker_set_id != sticker_set_id ||
10731         channel_full->is_all_history_available != is_all_history_available) {
10732       channel_full->participant_count = participant_count;
10733       channel_full->administrator_count = administrator_count;
10734       channel_full->restricted_count = restricted_count;
10735       channel_full->banned_count = banned_count;
10736       channel_full->can_get_participants = can_get_participants;
10737       channel_full->can_set_username = can_set_username;
10738       channel_full->can_set_sticker_set = can_set_sticker_set;
10739       channel_full->can_set_location = can_set_location;
10740       channel_full->can_view_statistics = can_view_statistics;
10741       channel_full->stats_dc_id = stats_dc_id;
10742       channel_full->is_all_history_available = is_all_history_available;
10743       channel_full->sticker_set_id = sticker_set_id;
10744 
10745       channel_full->is_changed = true;
10746     }
10747     if (channel_full->description != channel->about_) {
10748       channel_full->description = std::move(channel->about_);
10749       channel_full->is_changed = true;
10750       td_->group_call_manager_->on_update_dialog_about(DialogId(channel_id), channel_full->description, true);
10751     }
10752 
10753     if (have_participant_count && c->participant_count != participant_count) {
10754       c->participant_count = participant_count;
10755       c->is_changed = true;
10756       update_channel(c, channel_id);
10757     }
10758     if (!channel_full->is_can_view_statistics_inited) {
10759       channel_full->is_can_view_statistics_inited = true;
10760       channel_full->need_save_to_database = true;
10761     }
10762 
10763     on_update_channel_full_photo(
10764         channel_full, channel_id,
10765         get_photo(td_->file_manager_.get(), std::move(channel->chat_photo_), DialogId(channel_id)));
10766 
10767     td_->messages_manager_->on_read_channel_outbox(channel_id,
10768                                                    MessageId(ServerMessageId(channel->read_outbox_max_id_)));
10769     if ((channel->flags_ & CHANNEL_FULL_FLAG_HAS_AVAILABLE_MIN_MESSAGE_ID) != 0) {
10770       td_->messages_manager_->on_update_channel_max_unavailable_message_id(
10771           channel_id, MessageId(ServerMessageId(channel->available_min_id_)));
10772     }
10773     td_->messages_manager_->on_read_channel_inbox(channel_id, MessageId(ServerMessageId(channel->read_inbox_max_id_)),
10774                                                   channel->unread_count_, channel->pts_, "ChannelFull");
10775 
10776     on_update_channel_full_invite_link(channel_full, std::move(channel->exported_invite_));
10777 
10778     {
10779       auto is_blocked = (channel->flags_ & CHANNEL_FULL_FLAG_IS_BLOCKED) != 0;
10780       td_->messages_manager_->on_update_dialog_is_blocked(DialogId(channel_id), is_blocked);
10781     }
10782     {
10783       MessageId pinned_message_id;
10784       if ((channel->flags_ & CHANNEL_FULL_FLAG_HAS_PINNED_MESSAGE) != 0) {
10785         pinned_message_id = MessageId(ServerMessageId(channel->pinned_msg_id_));
10786       }
10787       td_->messages_manager_->on_update_dialog_last_pinned_message_id(DialogId(channel_id), pinned_message_id);
10788     }
10789     {
10790       FolderId folder_id;
10791       if ((channel->flags_ & CHANNEL_FULL_FLAG_HAS_FOLDER_ID) != 0) {
10792         folder_id = FolderId(channel->folder_id_);
10793       }
10794       td_->messages_manager_->on_update_dialog_folder_id(DialogId(channel_id), folder_id);
10795     }
10796     td_->messages_manager_->on_update_dialog_has_scheduled_server_messages(
10797         DialogId(channel_id), (channel->flags_ & CHANNEL_FULL_FLAG_HAS_SCHEDULED_MESSAGES) != 0);
10798     {
10799       InputGroupCallId input_group_call_id;
10800       if (channel->call_ != nullptr) {
10801         input_group_call_id = InputGroupCallId(channel->call_);
10802       }
10803       td_->messages_manager_->on_update_dialog_group_call_id(DialogId(channel_id), input_group_call_id);
10804     }
10805     {
10806       DialogId default_join_group_call_as_dialog_id;
10807       if (channel->groupcall_default_join_as_ != nullptr) {
10808         default_join_group_call_as_dialog_id = DialogId(channel->groupcall_default_join_as_);
10809       }
10810       // use send closure later to not create synchronously default_join_group_call_as_dialog_id
10811       send_closure_later(G()->messages_manager(),
10812                          &MessagesManager::on_update_dialog_default_join_group_call_as_dialog_id, DialogId(channel_id),
10813                          default_join_group_call_as_dialog_id, false);
10814     }
10815     {
10816       DialogId default_send_message_as_dialog_id;
10817       if (channel->default_send_as_ != nullptr) {
10818         default_send_message_as_dialog_id = DialogId(channel->default_send_as_);
10819       }
10820       // use send closure later to not create synchronously default_send_message_as_dialog_id
10821       send_closure_later(G()->messages_manager(), &MessagesManager::on_update_dialog_default_send_message_as_dialog_id,
10822                          DialogId(channel_id), default_send_message_as_dialog_id, false);
10823     }
10824 
10825     if (participant_count >= 190) {
10826       int32 online_member_count = 0;
10827       if ((channel->flags_ & CHANNEL_FULL_FLAG_HAS_ONLINE_MEMBER_COUNT) != 0) {
10828         online_member_count = channel->online_count_;
10829       }
10830       td_->messages_manager_->on_update_dialog_online_member_count(DialogId(channel_id), online_member_count, true);
10831     }
10832 
10833     vector<UserId> bot_user_ids;
10834     for (const auto &bot_info : channel->bot_info_) {
10835       UserId user_id(bot_info->user_id_);
10836       if (!is_user_bot(user_id)) {
10837         continue;
10838       }
10839 
10840       bot_user_ids.push_back(user_id);
10841     }
10842     on_update_channel_full_bot_user_ids(channel_full, channel_id, std::move(bot_user_ids));
10843 
10844     auto bot_commands = get_bot_commands(std::move(channel->bot_info_), nullptr);
10845     if (channel_full->bot_commands != bot_commands) {
10846       channel_full->bot_commands = std::move(bot_commands);
10847       channel_full->is_changed = true;
10848     }
10849 
10850     ChannelId linked_channel_id;
10851     if ((channel->flags_ & CHANNEL_FULL_FLAG_HAS_LINKED_CHANNEL_ID) != 0) {
10852       linked_channel_id = ChannelId(channel->linked_chat_id_);
10853       auto linked_channel = get_channel_force(linked_channel_id);
10854       if (linked_channel == nullptr || c->is_megagroup == linked_channel->is_megagroup ||
10855           channel_id == linked_channel_id) {
10856         LOG(ERROR) << "Failed to add a link between " << channel_id << " and " << linked_channel_id;
10857         linked_channel_id = ChannelId();
10858       }
10859     }
10860     on_update_channel_full_linked_channel_id(channel_full, channel_id, linked_channel_id);
10861 
10862     on_update_channel_full_location(channel_full, channel_id, DialogLocation(std::move(channel->location_)));
10863 
10864     if (c->is_megagroup) {
10865       int32 slow_mode_delay = 0;
10866       int32 slow_mode_next_send_date = 0;
10867       if ((channel->flags_ & CHANNEL_FULL_FLAG_HAS_SLOW_MODE_DELAY) != 0) {
10868         slow_mode_delay = channel->slowmode_seconds_;
10869       }
10870       if ((channel->flags_ & CHANNEL_FULL_FLAG_HAS_SLOW_MODE_NEXT_SEND_DATE) != 0) {
10871         slow_mode_next_send_date = channel->slowmode_next_send_date_;
10872       }
10873       on_update_channel_full_slow_mode_delay(channel_full, channel_id, slow_mode_delay, slow_mode_next_send_date);
10874     }
10875 
10876     ChatId migrated_from_chat_id;
10877     MessageId migrated_from_max_message_id;
10878 
10879     if ((channel->flags_ & CHANNEL_FULL_FLAG_MIGRATED_FROM) != 0) {
10880       migrated_from_chat_id = ChatId(channel->migrated_from_chat_id_);
10881       migrated_from_max_message_id = MessageId(ServerMessageId(channel->migrated_from_max_id_));
10882     }
10883 
10884     if (channel_full->migrated_from_chat_id != migrated_from_chat_id ||
10885         channel_full->migrated_from_max_message_id != migrated_from_max_message_id) {
10886       channel_full->migrated_from_chat_id = migrated_from_chat_id;
10887       channel_full->migrated_from_max_message_id = migrated_from_max_message_id;
10888       channel_full->is_changed = true;
10889     }
10890 
10891     channel_full->is_update_channel_full_sent = true;
10892     update_channel_full(channel_full, channel_id, "on_get_channel_full");
10893 
10894     if (linked_channel_id.is_valid()) {
10895       auto linked_channel_full = get_channel_full_force(linked_channel_id, true, "on_get_chat_full");
10896       on_update_channel_full_linked_channel_id(linked_channel_full, linked_channel_id, channel_id);
10897       if (linked_channel_full != nullptr) {
10898         update_channel_full(linked_channel_full, linked_channel_id, "on_get_channel_full 2");
10899       }
10900     }
10901 
10902     if (dismiss_suggested_action_queries_.count(DialogId(channel_id)) == 0) {
10903       auto it = dialog_suggested_actions_.find(DialogId(channel_id));
10904       if (it != dialog_suggested_actions_.end() || !channel->pending_suggestions_.empty()) {
10905         vector<SuggestedAction> suggested_actions;
10906         for (auto &action_str : channel->pending_suggestions_) {
10907           SuggestedAction suggested_action(action_str, DialogId(channel_id));
10908           if (!suggested_action.is_empty()) {
10909             if (suggested_action == SuggestedAction{SuggestedAction::Type::ConvertToGigagroup, DialogId(channel_id)} &&
10910                 (c->is_gigagroup || c->default_permissions != RestrictedRights(false, false, false, false, false, false,
10911                                                                                false, false, false, false, false))) {
10912               LOG(INFO) << "Skip ConvertToGigagroup suggested action";
10913             } else {
10914               suggested_actions.push_back(suggested_action);
10915             }
10916           }
10917         }
10918         if (it == dialog_suggested_actions_.end()) {
10919           it = dialog_suggested_actions_.emplace(DialogId(channel_id), vector<SuggestedAction>()).first;
10920         }
10921         update_suggested_actions(it->second, std::move(suggested_actions));
10922         if (it->second.empty()) {
10923           dialog_suggested_actions_.erase(it);
10924         }
10925       }
10926     }
10927   }
10928   promise.set_value(Unit());
10929 }
10930 
on_get_chat_full_failed(ChatId chat_id)10931 void ContactsManager::on_get_chat_full_failed(ChatId chat_id) {
10932   if (G()->close_flag()) {
10933     return;
10934   }
10935 
10936   LOG(INFO) << "Failed to get full " << chat_id;
10937 }
10938 
on_get_channel_full_failed(ChannelId channel_id)10939 void ContactsManager::on_get_channel_full_failed(ChannelId channel_id) {
10940   if (G()->close_flag()) {
10941     return;
10942   }
10943 
10944   LOG(INFO) << "Failed to get full " << channel_id;
10945   auto channel_full = get_channel_full(channel_id, true, "on_get_channel_full");
10946   if (channel_full != nullptr) {
10947     channel_full->repair_request_version = 0;
10948   }
10949 }
10950 
is_update_about_username_change_received(UserId user_id) const10951 bool ContactsManager::is_update_about_username_change_received(UserId user_id) const {
10952   const User *u = get_user(user_id);
10953   if (u != nullptr) {
10954     return u->is_contact;
10955   } else {
10956     return false;
10957   }
10958 }
10959 
on_update_user_name(UserId user_id,string && first_name,string && last_name,string && username)10960 void ContactsManager::on_update_user_name(UserId user_id, string &&first_name, string &&last_name, string &&username) {
10961   if (!user_id.is_valid()) {
10962     LOG(ERROR) << "Receive invalid " << user_id;
10963     return;
10964   }
10965 
10966   User *u = get_user_force(user_id);
10967   if (u != nullptr) {
10968     on_update_user_name(u, user_id, std::move(first_name), std::move(last_name), std::move(username));
10969     update_user(u, user_id);
10970   } else {
10971     LOG(INFO) << "Ignore update user name about unknown " << user_id;
10972   }
10973 }
10974 
on_update_user_name(User * u,UserId user_id,string && first_name,string && last_name,string && username)10975 void ContactsManager::on_update_user_name(User *u, UserId user_id, string &&first_name, string &&last_name,
10976                                           string &&username) {
10977   if (first_name.empty() && last_name.empty()) {
10978     first_name = u->phone_number;
10979   }
10980   if (u->first_name != first_name || u->last_name != last_name) {
10981     u->first_name = std::move(first_name);
10982     u->last_name = std::move(last_name);
10983     u->is_name_changed = true;
10984     LOG(DEBUG) << "Name has changed for " << user_id;
10985     u->is_changed = true;
10986   }
10987   td_->messages_manager_->on_dialog_username_updated(DialogId(user_id), u->username, username);
10988   if (u->username != username) {
10989     u->username = std::move(username);
10990     u->is_username_changed = true;
10991     LOG(DEBUG) << "Username has changed for " << user_id;
10992     u->is_changed = true;
10993   }
10994 }
10995 
on_update_user_phone_number(UserId user_id,string && phone_number)10996 void ContactsManager::on_update_user_phone_number(UserId user_id, string &&phone_number) {
10997   if (!user_id.is_valid()) {
10998     LOG(ERROR) << "Receive invalid " << user_id;
10999     return;
11000   }
11001 
11002   User *u = get_user_force(user_id);
11003   if (u != nullptr) {
11004     on_update_user_phone_number(u, user_id, std::move(phone_number));
11005     update_user(u, user_id);
11006   } else {
11007     LOG(INFO) << "Ignore update user phone number about unknown " << user_id;
11008   }
11009 }
11010 
on_update_user_phone_number(User * u,UserId user_id,string && phone_number)11011 void ContactsManager::on_update_user_phone_number(User *u, UserId user_id, string &&phone_number) {
11012   if (u->phone_number != phone_number) {
11013     u->phone_number = std::move(phone_number);
11014     LOG(DEBUG) << "Phone number has changed for " << user_id;
11015     u->is_changed = true;
11016   }
11017 }
11018 
on_update_user_photo(UserId user_id,tl_object_ptr<telegram_api::UserProfilePhoto> && photo_ptr)11019 void ContactsManager::on_update_user_photo(UserId user_id, tl_object_ptr<telegram_api::UserProfilePhoto> &&photo_ptr) {
11020   if (!user_id.is_valid()) {
11021     LOG(ERROR) << "Receive invalid " << user_id;
11022     return;
11023   }
11024 
11025   User *u = get_user_force(user_id);
11026   if (u != nullptr) {
11027     on_update_user_photo(u, user_id, std::move(photo_ptr), "on_update_user_photo");
11028     update_user(u, user_id);
11029   } else {
11030     LOG(INFO) << "Ignore update user photo about unknown " << user_id;
11031   }
11032 }
11033 
on_update_user_photo(User * u,UserId user_id,tl_object_ptr<telegram_api::UserProfilePhoto> && photo,const char * source)11034 void ContactsManager::on_update_user_photo(User *u, UserId user_id,
11035                                            tl_object_ptr<telegram_api::UserProfilePhoto> &&photo, const char *source) {
11036   if (td_->auth_manager_->is_bot() && !G()->parameters().use_file_db && !u->is_photo_inited) {
11037     if (photo != nullptr && photo->get_id() == telegram_api::userProfilePhoto::ID) {
11038       auto *profile_photo = static_cast<telegram_api::userProfilePhoto *>(photo.get());
11039       if ((profile_photo->flags_ & telegram_api::userProfilePhoto::STRIPPED_THUMB_MASK) != 0) {
11040         profile_photo->flags_ -= telegram_api::userProfilePhoto::STRIPPED_THUMB_MASK;
11041         profile_photo->stripped_thumb_ = BufferSlice();
11042       }
11043     }
11044     auto &old_photo = pending_user_photos_[user_id];
11045     if (!LOG_IS_STRIPPED(ERROR) && to_string(old_photo) == to_string(photo)) {
11046       return;
11047     }
11048 
11049     bool is_empty = photo == nullptr || photo->get_id() == telegram_api::userProfilePhotoEmpty::ID;
11050     old_photo = std::move(photo);
11051 
11052     drop_user_photos(user_id, is_empty, true, "on_update_user_photo");
11053     return;
11054   }
11055 
11056   do_update_user_photo(u, user_id, std::move(photo), source);
11057 }
11058 
do_update_user_photo(User * u,UserId user_id,tl_object_ptr<telegram_api::UserProfilePhoto> && photo,const char * source)11059 void ContactsManager::do_update_user_photo(User *u, UserId user_id,
11060                                            tl_object_ptr<telegram_api::UserProfilePhoto> &&photo, const char *source) {
11061   ProfilePhoto new_photo = get_profile_photo(td_->file_manager_.get(), user_id, u->access_hash, std::move(photo));
11062   if (td_->auth_manager_->is_bot()) {
11063     new_photo.minithumbnail.clear();
11064   }
11065   do_update_user_photo(u, user_id, std::move(new_photo), true, source);
11066 }
11067 
do_update_user_photo(User * u,UserId user_id,ProfilePhoto && new_photo,bool invalidate_photo_cache,const char * source)11068 void ContactsManager::do_update_user_photo(User *u, UserId user_id, ProfilePhoto &&new_photo,
11069                                            bool invalidate_photo_cache, const char *source) {
11070   u->is_photo_inited = true;
11071   if (new_photo != u->photo) {
11072     LOG_IF(ERROR, u->access_hash == -1 && new_photo.small_file_id.is_valid())
11073         << "Update profile photo of " << user_id << " without access hash from " << source;
11074     u->photo = new_photo;
11075     u->is_photo_changed = true;
11076     LOG(DEBUG) << "Photo has changed for " << user_id;
11077     u->is_changed = true;
11078 
11079     if (invalidate_photo_cache) {
11080       drop_user_photos(user_id, u->photo.id <= 0, true, "do_update_user_photo");
11081     }
11082   }
11083 }
11084 
register_user_photo(User * u,UserId user_id,const Photo & photo)11085 void ContactsManager::register_user_photo(User *u, UserId user_id, const Photo &photo) {
11086   auto photo_file_ids = photo_get_file_ids(photo);
11087   if (photo.is_empty() || photo_file_ids.empty()) {
11088     return;
11089   }
11090   auto first_file_id = photo_file_ids[0];
11091   auto file_type = td_->file_manager_->get_file_view(first_file_id).get_type();
11092   if (file_type == FileType::ProfilePhoto) {
11093     return;
11094   }
11095   CHECK(file_type == FileType::Photo);
11096   CHECK(u != nullptr);
11097   auto photo_id = photo.id.get();
11098   if (u->photo_ids.emplace(photo_id).second) {
11099     VLOG(file_references) << "Register photo " << photo_id << " of " << user_id;
11100     if (user_id == get_my_id()) {
11101       my_photo_file_id_[photo_id] = first_file_id;
11102     }
11103     FileSourceId file_source_id;
11104     auto it = user_profile_photo_file_source_ids_.find(std::make_pair(user_id, photo_id));
11105     if (it != user_profile_photo_file_source_ids_.end()) {
11106       VLOG(file_references) << "Move " << it->second << " inside of " << user_id;
11107       file_source_id = it->second;
11108       user_profile_photo_file_source_ids_.erase(it);
11109     } else {
11110       VLOG(file_references) << "Need to create new file source for photo " << photo_id << " of " << user_id;
11111       file_source_id = td_->file_reference_manager_->create_user_photo_file_source(user_id, photo_id);
11112     }
11113     for (auto &file_id : photo_file_ids) {
11114       td_->file_manager_->add_file_source(file_id, file_source_id);
11115     }
11116   }
11117 }
11118 
on_update_user_is_contact(User * u,UserId user_id,bool is_contact,bool is_mutual_contact)11119 void ContactsManager::on_update_user_is_contact(User *u, UserId user_id, bool is_contact, bool is_mutual_contact) {
11120   UserId my_id = get_my_id();
11121   if (user_id == my_id) {
11122     is_mutual_contact = is_contact;
11123   }
11124   if (!is_contact && is_mutual_contact) {
11125     LOG(ERROR) << "Receive is_mutual_contact == true for non-contact " << user_id;
11126     is_mutual_contact = false;
11127   }
11128 
11129   if (u->is_contact != is_contact || u->is_mutual_contact != is_mutual_contact) {
11130     LOG(DEBUG) << "Update " << user_id << " is_contact from (" << u->is_contact << ", " << u->is_mutual_contact
11131                << ") to (" << is_contact << ", " << is_mutual_contact << ")";
11132     if (u->is_contact != is_contact) {
11133       u->is_is_contact_changed = true;
11134     }
11135     u->is_contact = is_contact;
11136     u->is_mutual_contact = is_mutual_contact;
11137     u->is_changed = true;
11138   }
11139 }
11140 
on_update_user_online(UserId user_id,tl_object_ptr<telegram_api::UserStatus> && status)11141 void ContactsManager::on_update_user_online(UserId user_id, tl_object_ptr<telegram_api::UserStatus> &&status) {
11142   if (!user_id.is_valid()) {
11143     LOG(ERROR) << "Receive invalid " << user_id;
11144     return;
11145   }
11146 
11147   User *u = get_user_force(user_id);
11148   if (u != nullptr) {
11149     if (u->is_bot) {
11150       LOG(ERROR) << "Receive updateUserStatus about bot " << user_id;
11151       return;
11152     }
11153     on_update_user_online(u, user_id, std::move(status));
11154     update_user(u, user_id);
11155 
11156     if (user_id == get_my_id() &&
11157         was_online_remote_ != u->was_online) {  // only update was_online_remote_ from updateUserStatus
11158       was_online_remote_ = u->was_online;
11159       VLOG(notifications) << "Set was_online_remote to " << was_online_remote_;
11160       G()->td_db()->get_binlog_pmc()->set("my_was_online_remote", to_string(was_online_remote_));
11161     }
11162   } else {
11163     LOG(INFO) << "Ignore update user online about unknown " << user_id;
11164   }
11165 }
11166 
on_update_user_online(User * u,UserId user_id,tl_object_ptr<telegram_api::UserStatus> && status)11167 void ContactsManager::on_update_user_online(User *u, UserId user_id, tl_object_ptr<telegram_api::UserStatus> &&status) {
11168   int32 id = status == nullptr ? telegram_api::userStatusEmpty::ID : status->get_id();
11169   int32 new_online;
11170   bool is_offline = false;
11171   if (id == telegram_api::userStatusOnline::ID) {
11172     int32 now = G()->unix_time();
11173 
11174     auto st = move_tl_object_as<telegram_api::userStatusOnline>(status);
11175     new_online = st->expires_;
11176     LOG_IF(ERROR, new_online < now - 86400)
11177         << "Receive userStatusOnline expired more than one day in past " << new_online;
11178   } else if (id == telegram_api::userStatusOffline::ID) {
11179     int32 now = G()->unix_time();
11180 
11181     auto st = move_tl_object_as<telegram_api::userStatusOffline>(status);
11182     new_online = st->was_online_;
11183     if (new_online >= now) {
11184       LOG_IF(ERROR, new_online > now + 10)
11185           << "Receive userStatusOffline but was online points to future time " << new_online << ", now is " << now;
11186       new_online = now - 1;
11187     }
11188     is_offline = true;
11189   } else if (id == telegram_api::userStatusRecently::ID) {
11190     new_online = -1;
11191   } else if (id == telegram_api::userStatusLastWeek::ID) {
11192     new_online = -2;
11193     is_offline = true;
11194   } else if (id == telegram_api::userStatusLastMonth::ID) {
11195     new_online = -3;
11196     is_offline = true;
11197   } else {
11198     CHECK(id == telegram_api::userStatusEmpty::ID);
11199     new_online = 0;
11200   }
11201 
11202   if (new_online != u->was_online) {
11203     LOG(DEBUG) << "Update " << user_id << " online from " << u->was_online << " to " << new_online;
11204     bool old_is_online = u->was_online > G()->unix_time_cached();
11205     bool new_is_online = new_online > G()->unix_time_cached();
11206     u->was_online = new_online;
11207     u->is_status_changed = true;
11208     if (u->was_online > 0) {
11209       u->local_was_online = 0;
11210     }
11211 
11212     if (user_id == get_my_id()) {
11213       if (my_was_online_local_ != 0 || old_is_online != new_is_online) {
11214         my_was_online_local_ = 0;
11215         u->is_online_status_changed = true;
11216       }
11217       if (is_offline) {
11218         td_->on_online_updated(false, false);
11219       }
11220     } else if (old_is_online != new_is_online) {
11221       u->is_online_status_changed = true;
11222     }
11223   }
11224 }
11225 
on_update_user_local_was_online(UserId user_id,int32 local_was_online)11226 void ContactsManager::on_update_user_local_was_online(UserId user_id, int32 local_was_online) {
11227   CHECK(user_id.is_valid());
11228 
11229   User *u = get_user_force(user_id);
11230   if (u == nullptr) {
11231     return;
11232   }
11233 
11234   on_update_user_local_was_online(u, user_id, local_was_online);
11235   update_user(u, user_id);
11236 }
11237 
on_update_user_local_was_online(User * u,UserId user_id,int32 local_was_online)11238 void ContactsManager::on_update_user_local_was_online(User *u, UserId user_id, int32 local_was_online) {
11239   CHECK(u != nullptr);
11240   if (u->is_deleted || u->is_bot || u->is_support || user_id == get_my_id()) {
11241     return;
11242   }
11243   if (u->was_online > G()->unix_time_cached()) {
11244     // if user is currently online, ignore local online
11245     return;
11246   }
11247 
11248   // bring users online for 30 seconds
11249   local_was_online += 30;
11250   if (local_was_online < G()->unix_time_cached() + 2 || local_was_online <= u->local_was_online ||
11251       local_was_online <= u->was_online) {
11252     return;
11253   }
11254 
11255   LOG(DEBUG) << "Update " << user_id << " local online from " << u->local_was_online << " to " << local_was_online;
11256   bool old_is_online = u->local_was_online > G()->unix_time_cached();
11257   u->local_was_online = local_was_online;
11258   u->is_status_changed = true;
11259 
11260   if (!old_is_online) {
11261     u->is_online_status_changed = true;
11262   }
11263 }
11264 
on_update_user_is_blocked(UserId user_id,bool is_blocked)11265 void ContactsManager::on_update_user_is_blocked(UserId user_id, bool is_blocked) {
11266   if (!user_id.is_valid()) {
11267     LOG(ERROR) << "Receive invalid " << user_id;
11268     return;
11269   }
11270 
11271   UserFull *user_full = get_user_full_force(user_id);
11272   if (user_full == nullptr || user_full->is_blocked == is_blocked) {
11273     return;
11274   }
11275   on_update_user_full_is_blocked(user_full, user_id, is_blocked);
11276   update_user_full(user_full, user_id, "on_update_user_is_blocked");
11277 }
11278 
on_update_user_full_is_blocked(UserFull * user_full,UserId user_id,bool is_blocked)11279 void ContactsManager::on_update_user_full_is_blocked(UserFull *user_full, UserId user_id, bool is_blocked) {
11280   CHECK(user_full != nullptr);
11281   if (user_full->is_blocked != is_blocked) {
11282     LOG(INFO) << "Receive update user full is blocked with " << user_id << " and is_blocked = " << is_blocked;
11283     user_full->is_blocked = is_blocked;
11284     user_full->is_changed = true;
11285   }
11286 }
11287 
on_update_user_common_chat_count(UserId user_id,int32 common_chat_count)11288 void ContactsManager::on_update_user_common_chat_count(UserId user_id, int32 common_chat_count) {
11289   LOG(INFO) << "Receive " << common_chat_count << " common chat count with " << user_id;
11290   if (!user_id.is_valid()) {
11291     LOG(ERROR) << "Receive invalid " << user_id;
11292     return;
11293   }
11294 
11295   UserFull *user_full = get_user_full_force(user_id);
11296   if (user_full == nullptr) {
11297     return;
11298   }
11299   on_update_user_full_common_chat_count(user_full, user_id, common_chat_count);
11300   update_user_full(user_full, user_id, "on_update_user_common_chat_count");
11301 }
11302 
on_update_user_full_common_chat_count(UserFull * user_full,UserId user_id,int32 common_chat_count)11303 void ContactsManager::on_update_user_full_common_chat_count(UserFull *user_full, UserId user_id,
11304                                                             int32 common_chat_count) {
11305   CHECK(user_full != nullptr);
11306   if (common_chat_count < 0) {
11307     LOG(ERROR) << "Receive " << common_chat_count << " as common group count with " << user_id;
11308     common_chat_count = 0;
11309   }
11310   if (user_full->common_chat_count != common_chat_count) {
11311     user_full->common_chat_count = common_chat_count;
11312     user_full->is_common_chat_count_changed = true;
11313     user_full->is_changed = true;
11314   }
11315 }
11316 
on_update_user_full_commands(UserFull * user_full,UserId user_id,vector<tl_object_ptr<telegram_api::botCommand>> && bot_commands)11317 void ContactsManager::on_update_user_full_commands(UserFull *user_full, UserId user_id,
11318                                                    vector<tl_object_ptr<telegram_api::botCommand>> &&bot_commands) {
11319   CHECK(user_full != nullptr);
11320   auto commands = transform(std::move(bot_commands), [](tl_object_ptr<telegram_api::botCommand> &&bot_command) {
11321     return BotCommand(std::move(bot_command));
11322   });
11323   if (user_full->commands != commands) {
11324     user_full->commands = std::move(commands);
11325     user_full->is_changed = true;
11326   }
11327 }
11328 
on_update_user_need_phone_number_privacy_exception(UserId user_id,bool need_phone_number_privacy_exception)11329 void ContactsManager::on_update_user_need_phone_number_privacy_exception(UserId user_id,
11330                                                                          bool need_phone_number_privacy_exception) {
11331   LOG(INFO) << "Receive " << need_phone_number_privacy_exception << " need phone number privacy exception with "
11332             << user_id;
11333   if (!user_id.is_valid()) {
11334     LOG(ERROR) << "Receive invalid " << user_id;
11335     return;
11336   }
11337 
11338   UserFull *user_full = get_user_full_force(user_id);
11339   if (user_full == nullptr) {
11340     return;
11341   }
11342   on_update_user_full_need_phone_number_privacy_exception(user_full, user_id, need_phone_number_privacy_exception);
11343   update_user_full(user_full, user_id, "on_update_user_need_phone_number_privacy_exception");
11344 }
11345 
on_update_user_full_need_phone_number_privacy_exception(UserFull * user_full,UserId user_id,bool need_phone_number_privacy_exception) const11346 void ContactsManager::on_update_user_full_need_phone_number_privacy_exception(
11347     UserFull *user_full, UserId user_id, bool need_phone_number_privacy_exception) const {
11348   CHECK(user_full != nullptr);
11349   if (need_phone_number_privacy_exception) {
11350     const User *u = get_user(user_id);
11351     if (u == nullptr || u->is_contact || user_id == get_my_id()) {
11352       need_phone_number_privacy_exception = false;
11353     }
11354   }
11355   if (user_full->need_phone_number_privacy_exception != need_phone_number_privacy_exception) {
11356     user_full->need_phone_number_privacy_exception = need_phone_number_privacy_exception;
11357     user_full->is_changed = true;
11358   }
11359 }
11360 
on_ignored_restriction_reasons_changed()11361 void ContactsManager::on_ignored_restriction_reasons_changed() {
11362   for (auto user_id : restricted_user_ids_) {
11363     send_closure(G()->td(), &Td::send_update,
11364                  td_api::make_object<td_api::updateUser>(get_user_object(user_id, get_user(user_id))));
11365   }
11366   for (auto channel_id : restricted_channel_ids_) {
11367     send_closure(
11368         G()->td(), &Td::send_update,
11369         td_api::make_object<td_api::updateSupergroup>(get_supergroup_object(channel_id, get_channel(channel_id))));
11370   }
11371 }
11372 
on_set_profile_photo(tl_object_ptr<telegram_api::photos_photo> && photo,int64 old_photo_id)11373 void ContactsManager::on_set_profile_photo(tl_object_ptr<telegram_api::photos_photo> &&photo, int64 old_photo_id) {
11374   LOG(INFO) << "Changed profile photo to " << to_string(photo);
11375 
11376   UserId my_user_id = get_my_id();
11377 
11378   if (old_photo_id != 0) {
11379     delete_profile_photo_from_cache(my_user_id, old_photo_id, false);
11380   }
11381 
11382   add_profile_photo_to_cache(my_user_id,
11383                              get_photo(td_->file_manager_.get(), std::move(photo->photo_), DialogId(my_user_id)));
11384 
11385   // if cache was correctly updated, this should produce no updates
11386   on_get_users(std::move(photo->users_), "on_set_profile_photo");
11387 }
11388 
on_delete_profile_photo(int64 profile_photo_id,Promise<Unit> promise)11389 void ContactsManager::on_delete_profile_photo(int64 profile_photo_id, Promise<Unit> promise) {
11390   UserId my_user_id = get_my_id();
11391 
11392   bool need_reget_user = delete_profile_photo_from_cache(my_user_id, profile_photo_id, true);
11393   if (need_reget_user && !G()->close_flag()) {
11394     return reload_user(my_user_id, std::move(promise));
11395   }
11396 
11397   promise.set_value(Unit());
11398 }
11399 
add_profile_photo_to_cache(UserId user_id,Photo && photo)11400 void ContactsManager::add_profile_photo_to_cache(UserId user_id, Photo &&photo) {
11401   if (photo.is_empty()) {
11402     return;
11403   }
11404 
11405   // we have subsequence of user photos in user_photos_
11406   // ProfilePhoto in User and Photo in UserFull
11407 
11408   User *u = get_user_force(user_id);
11409   if (u == nullptr) {
11410     return;
11411   }
11412 
11413   // update photo list
11414   auto it = user_photos_.find(user_id);
11415   if (it != user_photos_.end() && it->second.count != -1) {
11416     auto user_photos = &it->second;
11417     if (user_photos->offset == 0) {
11418       if (user_photos->photos.empty() || user_photos->photos[0].id.get() != photo.id.get()) {
11419         user_photos->photos.insert(user_photos->photos.begin(), photo);
11420         user_photos->count++;
11421         register_user_photo(u, user_id, user_photos->photos[0]);
11422       }
11423     } else {
11424       user_photos->count++;
11425       user_photos->offset++;
11426     }
11427   }
11428 
11429   // update Photo in UserFull
11430   auto user_full = get_user_full_force(user_id);
11431   if (user_full != nullptr) {
11432     if (user_full->photo != photo) {
11433       user_full->photo = photo;
11434       user_full->is_changed = true;
11435       register_user_photo(u, user_id, photo);
11436     }
11437     update_user_full(user_full, user_id, "add_profile_photo_to_cache");
11438   }
11439 
11440   // update ProfilePhoto in User
11441   do_update_user_photo(u, user_id, as_profile_photo(td_->file_manager_.get(), user_id, u->access_hash, photo), false,
11442                        "add_profile_photo_to_cache");
11443   update_user(u, user_id);
11444 }
11445 
delete_profile_photo_from_cache(UserId user_id,int64 profile_photo_id,bool send_updates)11446 bool ContactsManager::delete_profile_photo_from_cache(UserId user_id, int64 profile_photo_id, bool send_updates) {
11447   CHECK(profile_photo_id != 0);
11448 
11449   // we have subsequence of user photos in user_photos_
11450   // ProfilePhoto in User and Photo in UserFull
11451 
11452   User *u = get_user_force(user_id);
11453   bool is_main_photo_deleted = u != nullptr && u->photo.id == profile_photo_id;
11454 
11455   // update photo list
11456   auto it = user_photos_.find(user_id);
11457   if (it != user_photos_.end() && it->second.count > 0) {
11458     auto user_photos = &it->second;
11459     auto old_size = user_photos->photos.size();
11460     if (td::remove_if(user_photos->photos,
11461                       [profile_photo_id](const auto &photo) { return photo.id.get() == profile_photo_id; })) {
11462       auto removed_photos = old_size - user_photos->photos.size();
11463       CHECK(removed_photos > 0);
11464       LOG_IF(ERROR, removed_photos != 1) << "Had " << removed_photos << " photos with ID " << profile_photo_id;
11465       user_photos->count -= narrow_cast<int32>(removed_photos);
11466       // offset was not changed
11467       CHECK(user_photos->count >= 0);
11468     } else {
11469       // failed to find photo to remove from cache
11470       // don't know how to adjust user_photos->offset, so drop photos cache
11471       LOG(INFO) << "Drop photos of " << user_id;
11472       user_photos->photos.clear();
11473       user_photos->count = -1;
11474       user_photos->offset = -1;
11475     }
11476   }
11477 
11478   // update Photo in UserFull
11479   auto user_full = get_user_full_force(user_id);
11480   if (user_full != nullptr && !user_full->photo.is_empty() &&
11481       (is_main_photo_deleted || user_full->photo.id.get() == profile_photo_id)) {
11482     if (it != user_photos_.end() && it->second.count != -1 && it->second.offset == 0 && !it->second.photos.empty()) {
11483       // found exact new photo
11484       if (it->second.photos[0] != user_full->photo) {
11485         user_full->photo = it->second.photos[0];
11486         user_full->is_changed = true;
11487       }
11488     } else {
11489       // repair UserFull photo
11490       user_full->expires_at = 0.0;
11491       user_full->photo = Photo();
11492       user_full->is_changed = true;
11493 
11494       load_user_full(user_id, true, Auto(), "delete_profile_photo_from_cache");
11495     }
11496     if (send_updates) {
11497       update_user_full(user_full, user_id, "delete_profile_photo_from_cache");
11498     }
11499   }
11500 
11501   // update ProfilePhoto in User
11502   if (is_main_photo_deleted) {
11503     bool need_reget_user = false;
11504     if (it != user_photos_.end() && it->second.count != -1 && it->second.offset == 0 && !it->second.photos.empty()) {
11505       // found exact new photo
11506       do_update_user_photo(u, user_id,
11507                            as_profile_photo(td_->file_manager_.get(), user_id, u->access_hash, it->second.photos[0]),
11508                            false, "delete_profile_photo_from_cache");
11509     } else {
11510       do_update_user_photo(u, user_id, ProfilePhoto(), false, "delete_profile_photo_from_cache 2");
11511       need_reget_user = it == user_photos_.end() || it->second.count != 0;
11512     }
11513     if (send_updates) {
11514       update_user(u, user_id);
11515     }
11516     return need_reget_user;
11517   }
11518 
11519   return false;
11520 }
11521 
drop_user_photos(UserId user_id,bool is_empty,bool drop_user_full_photo,const char * source)11522 void ContactsManager::drop_user_photos(UserId user_id, bool is_empty, bool drop_user_full_photo, const char *source) {
11523   auto it = user_photos_.find(user_id);
11524   if (it != user_photos_.end()) {
11525     auto user_photos = &it->second;
11526     int32 new_count = is_empty ? 0 : -1;
11527     if (user_photos->count == new_count) {
11528       CHECK(user_photos->photos.empty());
11529       CHECK(user_photos->offset == user_photos->count);
11530       return;
11531     }
11532 
11533     LOG(INFO) << "Drop photos of " << user_id << " to " << (is_empty ? "empty" : "unknown") << " from " << source;
11534     user_photos->photos.clear();
11535     user_photos->count = new_count;
11536     user_photos->offset = user_photos->count;
11537   }
11538 
11539   if (drop_user_full_photo) {
11540     auto user_full = get_user_full(user_id);  // must not load UserFull
11541     if (user_full == nullptr) {
11542       return;
11543     }
11544 
11545     if (!user_full->photo.is_empty()) {
11546       user_full->photo = Photo();
11547       user_full->is_changed = true;
11548     }
11549     if (!is_empty) {
11550       if (user_full->expires_at > 0.0) {
11551         user_full->expires_at = 0.0;
11552         user_full->need_save_to_database = true;
11553       }
11554       load_user_full(user_id, true, Auto(), "drop_user_photos");
11555     }
11556     update_user_full(user_full, user_id, "drop_user_photos");
11557   }
11558 }
11559 
drop_user_full(UserId user_id)11560 void ContactsManager::drop_user_full(UserId user_id) {
11561   auto user_full = get_user_full_force(user_id);
11562 
11563   drop_user_photos(user_id, false, false, "drop_user_full");
11564 
11565   if (user_full == nullptr) {
11566     return;
11567   }
11568 
11569   user_full->expires_at = 0.0;
11570 
11571   user_full->photo = Photo();
11572   user_full->is_blocked = false;
11573   user_full->can_be_called = false;
11574   user_full->supports_video_calls = false;
11575   user_full->has_private_calls = false;
11576   user_full->need_phone_number_privacy_exception = false;
11577   user_full->about = string();
11578   user_full->description = string();
11579   user_full->commands.clear();
11580   user_full->common_chat_count = 0;
11581   user_full->private_forward_name.clear();
11582   user_full->is_changed = true;
11583 
11584   update_user_full(user_full, user_id, "drop_user_full");
11585   td_->group_call_manager_->on_update_dialog_about(DialogId(user_id), user_full->about, true);
11586 }
11587 
update_user_online_member_count(User * u)11588 void ContactsManager::update_user_online_member_count(User *u) {
11589   if (u->online_member_dialogs.empty()) {
11590     return;
11591   }
11592 
11593   auto now = G()->unix_time_cached();
11594   vector<DialogId> expired_dialog_ids;
11595   for (auto &it : u->online_member_dialogs) {
11596     auto dialog_id = it.first;
11597     auto time = it.second;
11598     if (time < now - MessagesManager::ONLINE_MEMBER_COUNT_CACHE_EXPIRE_TIME) {
11599       expired_dialog_ids.push_back(dialog_id);
11600       continue;
11601     }
11602 
11603     switch (dialog_id.get_type()) {
11604       case DialogType::Chat: {
11605         auto chat_id = dialog_id.get_chat_id();
11606         auto chat_full = get_chat_full(chat_id);
11607         CHECK(chat_full != nullptr);
11608         update_chat_online_member_count(chat_full, chat_id, false);
11609         break;
11610       }
11611       case DialogType::Channel: {
11612         auto channel_id = dialog_id.get_channel_id();
11613         update_channel_online_member_count(channel_id, false);
11614         break;
11615       }
11616       case DialogType::User:
11617       case DialogType::SecretChat:
11618       case DialogType::None:
11619         UNREACHABLE();
11620         break;
11621     }
11622   }
11623   for (auto &dialog_id : expired_dialog_ids) {
11624     u->online_member_dialogs.erase(dialog_id);
11625     if (dialog_id.get_type() == DialogType::Channel) {
11626       cached_channel_participants_.erase(dialog_id.get_channel_id());
11627     }
11628   }
11629 }
11630 
update_chat_online_member_count(const ChatFull * chat_full,ChatId chat_id,bool is_from_server)11631 void ContactsManager::update_chat_online_member_count(const ChatFull *chat_full, ChatId chat_id, bool is_from_server) {
11632   update_dialog_online_member_count(chat_full->participants, DialogId(chat_id), is_from_server);
11633 }
11634 
update_channel_online_member_count(ChannelId channel_id,bool is_from_server)11635 void ContactsManager::update_channel_online_member_count(ChannelId channel_id, bool is_from_server) {
11636   if (get_channel_type(channel_id) != ChannelType::Megagroup) {
11637     return;
11638   }
11639 
11640   auto it = cached_channel_participants_.find(channel_id);
11641   if (it == cached_channel_participants_.end()) {
11642     return;
11643   }
11644   update_dialog_online_member_count(it->second, DialogId(channel_id), is_from_server);
11645 }
11646 
update_dialog_online_member_count(const vector<DialogParticipant> & participants,DialogId dialog_id,bool is_from_server)11647 void ContactsManager::update_dialog_online_member_count(const vector<DialogParticipant> &participants,
11648                                                         DialogId dialog_id, bool is_from_server) {
11649   if (td_->auth_manager_->is_bot()) {
11650     return;
11651   }
11652 
11653   int32 online_member_count = 0;
11654   int32 time = G()->unix_time();
11655   for (const auto &participant : participants) {
11656     if (participant.dialog_id_.get_type() != DialogType::User) {
11657       continue;
11658     }
11659     auto user_id = participant.dialog_id_.get_user_id();
11660     auto u = get_user(user_id);
11661     if (u != nullptr && !u->is_deleted && !u->is_bot) {
11662       if (get_user_was_online(u, user_id) > time) {
11663         online_member_count++;
11664       }
11665       if (is_from_server) {
11666         u->online_member_dialogs[dialog_id] = time;
11667       }
11668     }
11669   }
11670   td_->messages_manager_->on_update_dialog_online_member_count(dialog_id, online_member_count, is_from_server);
11671 }
11672 
on_get_chat_participants(tl_object_ptr<telegram_api::ChatParticipants> && participants_ptr,bool from_update)11673 void ContactsManager::on_get_chat_participants(tl_object_ptr<telegram_api::ChatParticipants> &&participants_ptr,
11674                                                bool from_update) {
11675   switch (participants_ptr->get_id()) {
11676     case telegram_api::chatParticipantsForbidden::ID: {
11677       auto participants = move_tl_object_as<telegram_api::chatParticipantsForbidden>(participants_ptr);
11678       ChatId chat_id(participants->chat_id_);
11679       if (!chat_id.is_valid()) {
11680         LOG(ERROR) << "Receive invalid " << chat_id;
11681         return;
11682       }
11683 
11684       if (!have_chat_force(chat_id)) {
11685         LOG(ERROR) << chat_id << " not found";
11686         return;
11687       }
11688 
11689       if (from_update) {
11690         drop_chat_full(chat_id);
11691       }
11692       break;
11693     }
11694     case telegram_api::chatParticipants::ID: {
11695       auto participants = move_tl_object_as<telegram_api::chatParticipants>(participants_ptr);
11696       ChatId chat_id(participants->chat_id_);
11697       if (!chat_id.is_valid()) {
11698         LOG(ERROR) << "Receive invalid " << chat_id;
11699         return;
11700       }
11701 
11702       const Chat *c = get_chat_force(chat_id);
11703       if (c == nullptr) {
11704         LOG(ERROR) << chat_id << " not found";
11705         return;
11706       }
11707 
11708       ChatFull *chat_full = get_chat_full_force(chat_id, "telegram_api::chatParticipants");
11709       if (chat_full == nullptr) {
11710         LOG(INFO) << "Ignore update of members for unknown full " << chat_id;
11711         return;
11712       }
11713 
11714       UserId new_creator_user_id;
11715       vector<DialogParticipant> new_participants;
11716       new_participants.reserve(participants->participants_.size());
11717 
11718       for (auto &participant_ptr : participants->participants_) {
11719         DialogParticipant dialog_participant(std::move(participant_ptr), c->date, c->status.is_creator());
11720         if (!dialog_participant.is_valid()) {
11721           LOG(ERROR) << "Receive invalid " << dialog_participant;
11722           continue;
11723         }
11724 
11725         LOG_IF(ERROR, !td_->messages_manager_->have_dialog_info(dialog_participant.dialog_id_))
11726             << "Have no information about " << dialog_participant.dialog_id_ << " as a member of " << chat_id;
11727         LOG_IF(ERROR, !have_user(dialog_participant.inviter_user_id_))
11728             << "Have no information about " << dialog_participant.inviter_user_id_ << " as a member of " << chat_id;
11729         if (dialog_participant.joined_date_ < c->date) {
11730           LOG_IF(ERROR, dialog_participant.joined_date_ < c->date - 30 && c->date >= 1486000000)
11731               << "Wrong join date = " << dialog_participant.joined_date_ << " for " << dialog_participant.dialog_id_
11732               << ", " << chat_id << " was created at " << c->date;
11733           dialog_participant.joined_date_ = c->date;
11734         }
11735         if (dialog_participant.status_.is_creator() && dialog_participant.dialog_id_.get_type() == DialogType::User) {
11736           new_creator_user_id = dialog_participant.dialog_id_.get_user_id();
11737         }
11738         new_participants.push_back(std::move(dialog_participant));
11739       }
11740 
11741       if (chat_full->creator_user_id != new_creator_user_id) {
11742         if (new_creator_user_id.is_valid() && chat_full->creator_user_id.is_valid()) {
11743           LOG(ERROR) << "Group creator has changed from " << chat_full->creator_user_id << " to " << new_creator_user_id
11744                      << " in " << chat_id;
11745         }
11746         chat_full->creator_user_id = new_creator_user_id;
11747         chat_full->is_changed = true;
11748       }
11749 
11750       on_update_chat_full_participants(chat_full, chat_id, std::move(new_participants), participants->version_,
11751                                        from_update);
11752       if (from_update) {
11753         update_chat_full(chat_full, chat_id, "on_get_chat_participants");
11754       }
11755       break;
11756     }
11757     default:
11758       UNREACHABLE();
11759   }
11760 }
11761 
get_chat_participant(ChatId chat_id,UserId user_id) const11762 const DialogParticipant *ContactsManager::get_chat_participant(ChatId chat_id, UserId user_id) const {
11763   auto chat_full = get_chat_full(chat_id);
11764   if (chat_full == nullptr) {
11765     return nullptr;
11766   }
11767   return get_chat_full_participant(chat_full, DialogId(user_id));
11768 }
11769 
get_chat_full_participant(const ChatFull * chat_full,DialogId dialog_id)11770 const DialogParticipant *ContactsManager::get_chat_full_participant(const ChatFull *chat_full, DialogId dialog_id) {
11771   for (const auto &dialog_participant : chat_full->participants) {
11772     if (dialog_participant.dialog_id_ == dialog_id) {
11773       return &dialog_participant;
11774     }
11775   }
11776   return nullptr;
11777 }
11778 
get_chat_member_object(const DialogParticipant & dialog_participant) const11779 tl_object_ptr<td_api::chatMember> ContactsManager::get_chat_member_object(
11780     const DialogParticipant &dialog_participant) const {
11781   DialogId dialog_id = dialog_participant.dialog_id_;
11782   UserId participant_user_id;
11783   if (dialog_id.get_type() == DialogType::User) {
11784     participant_user_id = dialog_id.get_user_id();
11785   } else {
11786     td_->messages_manager_->force_create_dialog(dialog_id, "get_chat_member_object", true);
11787   }
11788   return td_api::make_object<td_api::chatMember>(
11789       get_message_sender_object_const(td_, dialog_id, "get_chat_member_object"),
11790       get_user_id_object(dialog_participant.inviter_user_id_, "chatMember.inviter_user_id"),
11791       dialog_participant.joined_date_, dialog_participant.status_.get_chat_member_status_object());
11792 }
11793 
on_get_channel_error(ChannelId channel_id,const Status & status,const string & source)11794 bool ContactsManager::on_get_channel_error(ChannelId channel_id, const Status &status, const string &source) {
11795   LOG(INFO) << "Receive " << status << " in " << channel_id << " from " << source;
11796   if (status.message() == CSlice("BOT_METHOD_INVALID")) {
11797     LOG(ERROR) << "Receive BOT_METHOD_INVALID from " << source;
11798     return true;
11799   }
11800   if (G()->is_expected_error(status)) {
11801     return true;
11802   }
11803   if (status.message() == "CHANNEL_PRIVATE" || status.message() == "CHANNEL_PUBLIC_GROUP_NA") {
11804     if (!channel_id.is_valid()) {
11805       LOG(ERROR) << "Receive " << status.message() << " in invalid " << channel_id << " from " << source;
11806       return false;
11807     }
11808 
11809     auto c = get_channel(channel_id);
11810     if (c == nullptr) {
11811       if (source == "GetChannelDifferenceQuery" || (td_->auth_manager_->is_bot() && source == "GetChannelsQuery")) {
11812         // get channel difference after restart
11813         // get channel from server by its identifier
11814         return true;
11815       }
11816       LOG(ERROR) << "Receive " << status.message() << " in not found " << channel_id << " from " << source;
11817       return false;
11818     }
11819 
11820     auto debug_channel_object = oneline(to_string(get_supergroup_object(channel_id, c)));
11821     if (c->status.is_member()) {
11822       LOG(INFO) << "Emulate leaving " << channel_id;
11823       // TODO we also may try to write to a public channel
11824       int32 flags = 0;
11825       if (c->is_megagroup) {
11826         flags |= CHANNEL_FLAG_IS_MEGAGROUP;
11827       } else {
11828         flags |= CHANNEL_FLAG_IS_BROADCAST;
11829       }
11830       telegram_api::channelForbidden update(flags, false /*ignored*/, false /*ignored*/, channel_id.get(),
11831                                             c->access_hash, c->title, 0);
11832       on_chat_update(update, "CHANNEL_PRIVATE");
11833     } else if (!c->status.is_banned()) {
11834       if (!c->username.empty()) {
11835         LOG(INFO) << "Drop username of " << channel_id;
11836         on_update_channel_username(c, channel_id, "");
11837       }
11838 
11839       on_update_channel_has_location(c, channel_id, false);
11840 
11841       on_update_channel_linked_channel_id(channel_id, ChannelId());
11842 
11843       update_channel(c, channel_id);
11844 
11845       remove_dialog_access_by_invite_link(DialogId(channel_id));
11846     }
11847     invalidate_channel_full(channel_id, !c->is_slow_mode_enabled);
11848     LOG_IF(ERROR, have_input_peer_channel(c, channel_id, AccessRights::Read))
11849         << "Have read access to channel after receiving CHANNEL_PRIVATE. Channel state: "
11850         << oneline(to_string(get_supergroup_object(channel_id, c)))
11851         << ". Previous channel state: " << debug_channel_object;
11852 
11853     return true;
11854   }
11855   return false;
11856 }
11857 
is_user_contact(UserId user_id,bool is_mutual) const11858 bool ContactsManager::is_user_contact(UserId user_id, bool is_mutual) const {
11859   return is_user_contact(get_user(user_id), user_id, is_mutual);
11860 }
11861 
is_user_contact(const User * u,UserId user_id,bool is_mutual) const11862 bool ContactsManager::is_user_contact(const User *u, UserId user_id, bool is_mutual) const {
11863   return u != nullptr && (is_mutual ? u->is_mutual_contact : u->is_contact) && user_id != get_my_id();
11864 }
11865 
on_get_channel_participants(ChannelId channel_id,ChannelParticipantsFilter filter,int32 offset,int32 limit,string additional_query,int32 additional_limit,tl_object_ptr<telegram_api::channels_channelParticipants> && channel_participants,Promise<DialogParticipants> && promise)11866 void ContactsManager::on_get_channel_participants(
11867     ChannelId channel_id, ChannelParticipantsFilter filter, int32 offset, int32 limit, string additional_query,
11868     int32 additional_limit, tl_object_ptr<telegram_api::channels_channelParticipants> &&channel_participants,
11869     Promise<DialogParticipants> &&promise) {
11870   TRY_STATUS_PROMISE(promise, G()->close_status());
11871 
11872   on_get_users(std::move(channel_participants->users_), "on_get_channel_participants");
11873   on_get_chats(std::move(channel_participants->chats_), "on_get_channel_participants");
11874   int32 total_count = channel_participants->count_;
11875   auto participants = std::move(channel_participants->participants_);
11876   LOG(INFO) << "Receive " << participants.size() << " " << filter << " members in " << channel_id;
11877 
11878   bool is_full = offset == 0 && static_cast<int32>(participants.size()) < limit && total_count < limit;
11879 
11880   vector<DialogParticipant> result;
11881   for (auto &participant_ptr : participants) {
11882     auto debug_participant = to_string(participant_ptr);
11883     result.emplace_back(std::move(participant_ptr));
11884     const auto &participant = result.back();
11885     UserId participant_user_id;
11886     if (participant.dialog_id_.get_type() == DialogType::User) {
11887       participant_user_id = participant.dialog_id_.get_user_id();
11888     }
11889     if (!participant.is_valid() || (filter.is_bots() && !is_user_bot(participant_user_id)) ||
11890         (filter.is_administrators() && !participant.status_.is_administrator()) ||
11891         ((filter.is_recent() || filter.is_contacts() || filter.is_search()) && !participant.status_.is_member()) ||
11892         (filter.is_contacts() && !is_user_contact(participant_user_id)) ||
11893         (filter.is_restricted() && !participant.status_.is_restricted()) ||
11894         (filter.is_banned() && !participant.status_.is_banned())) {
11895       bool skip_error = ((filter.is_administrators() || filter.is_bots()) && is_user_deleted(participant_user_id)) ||
11896                         (filter.is_contacts() && participant_user_id == get_my_id());
11897       if (!skip_error) {
11898         LOG(ERROR) << "Receive " << participant << ", while searching for " << filter << " in " << channel_id
11899                    << " with offset " << offset << " and limit " << limit << ": " << oneline(debug_participant);
11900       }
11901       result.pop_back();
11902       total_count--;
11903     }
11904   }
11905 
11906   if (total_count < narrow_cast<int32>(result.size())) {
11907     LOG(ERROR) << "Receive total_count = " << total_count << ", but have at least " << result.size() << " " << filter
11908                << " members in " << channel_id;
11909     total_count = static_cast<int32>(result.size());
11910   } else if (is_full && total_count > static_cast<int32>(result.size())) {
11911     LOG(ERROR) << "Fix total number of " << filter << " members from " << total_count << " to " << result.size()
11912                << " in " << channel_id;
11913     total_count = static_cast<int32>(result.size());
11914   }
11915 
11916   const auto max_participant_count = get_channel_type(channel_id) == ChannelType::Megagroup ? 975 : 195;
11917   auto participant_count =
11918       filter.is_recent() && total_count != 0 && total_count < max_participant_count ? total_count : -1;
11919   int32 administrator_count = filter.is_administrators() ? total_count : -1;
11920   if (is_full && (filter.is_administrators() || filter.is_bots() || filter.is_recent())) {
11921     vector<DialogAdministrator> administrators;
11922     vector<UserId> bot_user_ids;
11923     {
11924       if (filter.is_recent()) {
11925         for (const auto &participant : result) {
11926           if (participant.dialog_id_.get_type() == DialogType::User) {
11927             auto participant_user_id = participant.dialog_id_.get_user_id();
11928             if (participant.status_.is_administrator()) {
11929               administrators.emplace_back(participant_user_id, participant.status_.get_rank(),
11930                                           participant.status_.is_creator());
11931             }
11932             if (is_user_bot(participant_user_id)) {
11933               bot_user_ids.push_back(participant_user_id);
11934             }
11935           }
11936         }
11937         administrator_count = narrow_cast<int32>(administrators.size());
11938 
11939         if (get_channel_type(channel_id) == ChannelType::Megagroup && !td_->auth_manager_->is_bot()) {
11940           cached_channel_participants_[channel_id] = result;
11941           update_channel_online_member_count(channel_id, true);
11942         }
11943       } else if (filter.is_administrators()) {
11944         for (const auto &participant : result) {
11945           if (participant.dialog_id_.get_type() == DialogType::User) {
11946             administrators.emplace_back(participant.dialog_id_.get_user_id(), participant.status_.get_rank(),
11947                                         participant.status_.is_creator());
11948           }
11949         }
11950       } else if (filter.is_bots()) {
11951         bot_user_ids = transform(result, [](const DialogParticipant &participant) {
11952           CHECK(participant.dialog_id_.get_type() == DialogType::User);
11953           return participant.dialog_id_.get_user_id();
11954         });
11955       }
11956     }
11957     if (filter.is_administrators() || filter.is_recent()) {
11958       on_update_dialog_administrators(DialogId(channel_id), std::move(administrators), true, false);
11959     }
11960     if (filter.is_bots() || filter.is_recent()) {
11961       on_update_channel_bot_user_ids(channel_id, std::move(bot_user_ids));
11962     }
11963   }
11964   if (have_channel_participant_cache(channel_id)) {
11965     for (const auto &participant : result) {
11966       add_channel_participant_to_cache(channel_id, participant, false);
11967     }
11968   }
11969 
11970   if (participant_count != -1 || administrator_count != -1) {
11971     auto channel_full = get_channel_full_force(channel_id, true, "on_get_channel_participants_success");
11972     if (channel_full != nullptr) {
11973       if (administrator_count == -1) {
11974         administrator_count = channel_full->administrator_count;
11975       }
11976       if (participant_count == -1) {
11977         participant_count = channel_full->participant_count;
11978       }
11979       if (participant_count < administrator_count) {
11980         participant_count = administrator_count;
11981       }
11982       if (channel_full->participant_count != participant_count) {
11983         channel_full->participant_count = participant_count;
11984         channel_full->is_changed = true;
11985       }
11986       if (channel_full->administrator_count != administrator_count) {
11987         channel_full->administrator_count = administrator_count;
11988         channel_full->is_changed = true;
11989       }
11990       update_channel_full(channel_full, channel_id, "on_get_channel_participants");
11991     }
11992     if (participant_count != -1) {
11993       auto c = get_channel(channel_id);
11994       if (c != nullptr && c->participant_count != participant_count) {
11995         c->participant_count = participant_count;
11996         c->is_changed = true;
11997         update_channel(c, channel_id);
11998       }
11999     }
12000   }
12001 
12002   if (!additional_query.empty()) {
12003     auto dialog_ids = transform(result, [](const DialogParticipant &participant) { return participant.dialog_id_; });
12004     std::pair<int32, vector<DialogId>> result_dialog_ids =
12005         search_among_dialogs(dialog_ids, additional_query, additional_limit);
12006 
12007     total_count = result_dialog_ids.first;
12008     std::unordered_set<DialogId, DialogIdHash> result_dialog_ids_set(result_dialog_ids.second.begin(),
12009                                                                      result_dialog_ids.second.end());
12010     auto all_participants = std::move(result);
12011     result.clear();
12012     for (auto &participant : all_participants) {
12013       if (result_dialog_ids_set.count(participant.dialog_id_)) {
12014         result_dialog_ids_set.erase(participant.dialog_id_);
12015         result.push_back(std::move(participant));
12016       }
12017     }
12018   }
12019 
12020   promise.set_value(DialogParticipants{total_count, std::move(result)});
12021 }
12022 
have_channel_participant_cache(ChannelId channel_id) const12023 bool ContactsManager::have_channel_participant_cache(ChannelId channel_id) const {
12024   if (!td_->auth_manager_->is_bot()) {
12025     return false;
12026   }
12027   auto c = get_channel(channel_id);
12028   return c != nullptr && c->status.is_administrator();
12029 }
12030 
add_channel_participant_to_cache(ChannelId channel_id,const DialogParticipant & dialog_participant,bool allow_replace)12031 void ContactsManager::add_channel_participant_to_cache(ChannelId channel_id,
12032                                                        const DialogParticipant &dialog_participant,
12033                                                        bool allow_replace) {
12034   auto &participants = channel_participants_[channel_id];
12035   if (participants.participants_.empty()) {
12036     channel_participant_cache_timeout_.set_timeout_in(channel_id.get(), CHANNEL_PARTICIPANT_CACHE_TIME);
12037   }
12038   auto &participant_info = participants.participants_[dialog_participant.dialog_id_];
12039   if (participant_info.last_access_date_ > 0 && !allow_replace) {
12040     return;
12041   }
12042   participant_info.participant_ = dialog_participant;
12043   participant_info.last_access_date_ = G()->unix_time();
12044 }
12045 
get_channel_participant_from_cache(ChannelId channel_id,DialogId participant_dialog_id)12046 const DialogParticipant *ContactsManager::get_channel_participant_from_cache(ChannelId channel_id,
12047                                                                              DialogId participant_dialog_id) {
12048   auto channel_participants_it = channel_participants_.find(channel_id);
12049   if (channel_participants_it == channel_participants_.end()) {
12050     return nullptr;
12051   }
12052 
12053   auto &participants = channel_participants_it->second.participants_;
12054   CHECK(!participants.empty());
12055   auto it = participants.find(participant_dialog_id);
12056   if (it != participants.end()) {
12057     it->second.participant_.status_.update_restrictions();
12058     it->second.last_access_date_ = G()->unix_time();
12059     return &it->second.participant_;
12060   }
12061   return nullptr;
12062 }
12063 
speculative_add_count(int32 & count,int32 delta_count,int32 min_count)12064 bool ContactsManager::speculative_add_count(int32 &count, int32 delta_count, int32 min_count) {
12065   auto new_count = count + delta_count;
12066   if (new_count < min_count) {
12067     new_count = min_count;
12068   }
12069   if (new_count == count) {
12070     return false;
12071   }
12072 
12073   count = new_count;
12074   return true;
12075 }
12076 
speculative_add_channel_participants(ChannelId channel_id,const vector<UserId> & added_user_ids,UserId inviter_user_id,int32 date,bool by_me)12077 void ContactsManager::speculative_add_channel_participants(ChannelId channel_id, const vector<UserId> &added_user_ids,
12078                                                            UserId inviter_user_id, int32 date, bool by_me) {
12079   auto it = cached_channel_participants_.find(channel_id);
12080   auto channel_full = get_channel_full_force(channel_id, true, "speculative_add_channel_participants");
12081   bool is_participants_cache_changed = false;
12082 
12083   int32 delta_participant_count = 0;
12084   for (auto user_id : added_user_ids) {
12085     if (!user_id.is_valid()) {
12086       continue;
12087     }
12088 
12089     delta_participant_count++;
12090 
12091     if (it != cached_channel_participants_.end()) {
12092       auto &participants = it->second;
12093       bool is_found = false;
12094       for (auto &participant : participants) {
12095         if (participant.dialog_id_ == DialogId(user_id)) {
12096           is_found = true;
12097           break;
12098         }
12099       }
12100       if (!is_found) {
12101         is_participants_cache_changed = true;
12102         participants.emplace_back(DialogId(user_id), inviter_user_id, date, DialogParticipantStatus::Member());
12103       }
12104     }
12105 
12106     if (channel_full != nullptr && is_user_bot(user_id) && !td::contains(channel_full->bot_user_ids, user_id)) {
12107       channel_full->bot_user_ids.push_back(user_id);
12108       channel_full->need_save_to_database = true;
12109       reload_channel_full(channel_id, Promise<Unit>(), "speculative_add_channel_participants");
12110 
12111       send_closure_later(G()->messages_manager(), &MessagesManager::on_dialog_bots_updated, DialogId(channel_id),
12112                          channel_full->bot_user_ids, false);
12113     }
12114   }
12115   if (is_participants_cache_changed) {
12116     update_channel_online_member_count(channel_id, false);
12117   }
12118   if (channel_full != nullptr) {
12119     update_channel_full(channel_full, channel_id, "speculative_add_channel_participants");
12120   }
12121   if (delta_participant_count == 0) {
12122     return;
12123   }
12124 
12125   speculative_add_channel_participant_count(channel_id, delta_participant_count, by_me);
12126 }
12127 
speculative_delete_channel_participant(ChannelId channel_id,UserId deleted_user_id,bool by_me)12128 void ContactsManager::speculative_delete_channel_participant(ChannelId channel_id, UserId deleted_user_id, bool by_me) {
12129   if (!deleted_user_id.is_valid()) {
12130     return;
12131   }
12132 
12133   auto it = cached_channel_participants_.find(channel_id);
12134   if (it != cached_channel_participants_.end()) {
12135     auto &participants = it->second;
12136     for (size_t i = 0; i < participants.size(); i++) {
12137       if (participants[i].dialog_id_ == DialogId(deleted_user_id)) {
12138         participants.erase(participants.begin() + i);
12139         update_channel_online_member_count(channel_id, false);
12140         break;
12141       }
12142     }
12143   }
12144 
12145   if (is_user_bot(deleted_user_id)) {
12146     auto channel_full = get_channel_full_force(channel_id, true, "speculative_delete_channel_participant");
12147     if (channel_full != nullptr && td::remove(channel_full->bot_user_ids, deleted_user_id)) {
12148       channel_full->need_save_to_database = true;
12149       update_channel_full(channel_full, channel_id, "speculative_delete_channel_participant");
12150 
12151       send_closure_later(G()->messages_manager(), &MessagesManager::on_dialog_bots_updated, DialogId(channel_id),
12152                          channel_full->bot_user_ids, false);
12153     }
12154   }
12155 
12156   speculative_add_channel_participant_count(channel_id, -1, by_me);
12157 }
12158 
speculative_add_channel_participant_count(ChannelId channel_id,int32 delta_participant_count,bool by_me)12159 void ContactsManager::speculative_add_channel_participant_count(ChannelId channel_id, int32 delta_participant_count,
12160                                                                 bool by_me) {
12161   if (by_me) {
12162     // Currently ignore all changes made by the current user, because they may be already counted
12163     invalidate_channel_full(channel_id, false);  // just in case
12164     return;
12165   }
12166 
12167   auto channel_full = get_channel_full_force(channel_id, true, "speculative_add_channel_participant_count");
12168   auto min_count = channel_full == nullptr ? 0 : channel_full->administrator_count;
12169 
12170   auto c = get_channel_force(channel_id);
12171   if (c != nullptr && c->participant_count != 0 &&
12172       speculative_add_count(c->participant_count, delta_participant_count, min_count)) {
12173     c->is_changed = true;
12174     update_channel(c, channel_id);
12175   }
12176 
12177   if (channel_full == nullptr) {
12178     return;
12179   }
12180 
12181   channel_full->is_changed |=
12182       speculative_add_count(channel_full->participant_count, delta_participant_count, min_count);
12183 
12184   if (channel_full->is_changed) {
12185     channel_full->speculative_version++;
12186   }
12187 
12188   update_channel_full(channel_full, channel_id, "speculative_add_channel_participant_count");
12189 }
12190 
speculative_add_channel_user(ChannelId channel_id,UserId user_id,const DialogParticipantStatus & new_status,const DialogParticipantStatus & old_status)12191 void ContactsManager::speculative_add_channel_user(ChannelId channel_id, UserId user_id,
12192                                                    const DialogParticipantStatus &new_status,
12193                                                    const DialogParticipantStatus &old_status) {
12194   auto c = get_channel_force(channel_id);
12195   // channel full must be loaded before c->participant_count is updated, because on_load_channel_full_from_database
12196   // must copy the initial c->participant_count before it is speculatibely updated
12197   auto channel_full = get_channel_full_force(channel_id, true, "speculative_add_channel_user");
12198   int32 min_count = 0;
12199   if (channel_full != nullptr) {
12200     channel_full->is_changed |= speculative_add_count(channel_full->administrator_count,
12201                                                       new_status.is_administrator() - old_status.is_administrator());
12202     min_count = channel_full->administrator_count;
12203   }
12204 
12205   if (c != nullptr && c->participant_count != 0 &&
12206       speculative_add_count(c->participant_count, new_status.is_member() - old_status.is_member(), min_count)) {
12207     c->is_changed = true;
12208     update_channel(c, channel_id);
12209   }
12210 
12211   if (new_status.is_administrator() != old_status.is_administrator() ||
12212       new_status.get_rank() != old_status.get_rank()) {
12213     DialogId dialog_id(channel_id);
12214     auto administrators_it = dialog_administrators_.find(dialog_id);
12215     if (administrators_it != dialog_administrators_.end()) {
12216       auto administrators = administrators_it->second;
12217       if (new_status.is_administrator()) {
12218         bool is_found = false;
12219         for (auto &administrator : administrators) {
12220           if (administrator.get_user_id() == user_id) {
12221             is_found = true;
12222             if (administrator.get_rank() != new_status.get_rank() ||
12223                 administrator.is_creator() != new_status.is_creator()) {
12224               administrator = DialogAdministrator(user_id, new_status.get_rank(), new_status.is_creator());
12225               on_update_dialog_administrators(dialog_id, std::move(administrators), true, false);
12226             }
12227             break;
12228           }
12229         }
12230         if (!is_found) {
12231           administrators.emplace_back(user_id, new_status.get_rank(), new_status.is_creator());
12232           on_update_dialog_administrators(dialog_id, std::move(administrators), true, false);
12233         }
12234       } else {
12235         size_t i = 0;
12236         while (i != administrators.size() && administrators[i].get_user_id() != user_id) {
12237           i++;
12238         }
12239         if (i != administrators.size()) {
12240           administrators.erase(administrators.begin() + i);
12241           on_update_dialog_administrators(dialog_id, std::move(administrators), true, false);
12242         }
12243       }
12244     }
12245   }
12246 
12247   auto it = cached_channel_participants_.find(channel_id);
12248   if (it != cached_channel_participants_.end()) {
12249     auto &participants = it->second;
12250     bool is_found = false;
12251     for (size_t i = 0; i < participants.size(); i++) {
12252       if (participants[i].dialog_id_ == DialogId(user_id)) {
12253         if (!new_status.is_member()) {
12254           participants.erase(participants.begin() + i);
12255           update_channel_online_member_count(channel_id, false);
12256         } else {
12257           participants[i].status_ = new_status;
12258         }
12259         is_found = true;
12260         break;
12261       }
12262     }
12263     if (!is_found && new_status.is_member()) {
12264       participants.emplace_back(DialogId(user_id), get_my_id(), G()->unix_time(), new_status);
12265       update_channel_online_member_count(channel_id, false);
12266     }
12267   }
12268 
12269   if (channel_full == nullptr) {
12270     return;
12271   }
12272 
12273   channel_full->is_changed |= speculative_add_count(channel_full->participant_count,
12274                                                     new_status.is_member() - old_status.is_member(), min_count);
12275   channel_full->is_changed |=
12276       speculative_add_count(channel_full->restricted_count, new_status.is_restricted() - old_status.is_restricted());
12277   channel_full->is_changed |=
12278       speculative_add_count(channel_full->banned_count, new_status.is_banned() - old_status.is_banned());
12279 
12280   if (channel_full->is_changed) {
12281     channel_full->speculative_version++;
12282   }
12283 
12284   if (new_status.is_member() != old_status.is_member() && is_user_bot(user_id)) {
12285     if (new_status.is_member()) {
12286       if (!td::contains(channel_full->bot_user_ids, user_id)) {
12287         channel_full->bot_user_ids.push_back(user_id);
12288         channel_full->need_save_to_database = true;
12289         reload_channel_full(channel_id, Promise<Unit>(), "speculative_add_channel_user");
12290 
12291         send_closure_later(G()->messages_manager(), &MessagesManager::on_dialog_bots_updated, DialogId(channel_id),
12292                            channel_full->bot_user_ids, false);
12293       }
12294     } else {
12295       if (td::remove(channel_full->bot_user_ids, user_id)) {
12296         channel_full->need_save_to_database = true;
12297 
12298         send_closure_later(G()->messages_manager(), &MessagesManager::on_dialog_bots_updated, DialogId(channel_id),
12299                            channel_full->bot_user_ids, false);
12300       }
12301     }
12302   }
12303 
12304   update_channel_full(channel_full, channel_id, "speculative_add_channel_user");
12305 }
12306 
drop_channel_photos(ChannelId channel_id,bool is_empty,bool drop_channel_full_photo,const char * source)12307 void ContactsManager::drop_channel_photos(ChannelId channel_id, bool is_empty, bool drop_channel_full_photo,
12308                                           const char *source) {
12309   if (drop_channel_full_photo) {
12310     auto channel_full = get_channel_full(channel_id, true, "drop_channel_photos");  // must not load ChannelFull
12311     if (channel_full == nullptr) {
12312       return;
12313     }
12314 
12315     on_update_channel_full_photo(channel_full, channel_id, Photo());
12316     if (!is_empty) {
12317       if (channel_full->expires_at > 0.0) {
12318         channel_full->expires_at = 0.0;
12319         channel_full->need_save_to_database = true;
12320       }
12321       send_get_channel_full_query(channel_full, channel_id, Auto(), "drop_channel_photos");
12322     }
12323     update_channel_full(channel_full, channel_id, "drop_channel_photos");
12324   }
12325 }
12326 
invalidate_channel_full(ChannelId channel_id,bool need_drop_slow_mode_delay)12327 void ContactsManager::invalidate_channel_full(ChannelId channel_id, bool need_drop_slow_mode_delay) {
12328   LOG(INFO) << "Invalidate supergroup full for " << channel_id;
12329   auto channel_full = get_channel_full(channel_id, true, "invalidate_channel_full");  // must not load ChannelFull
12330   if (channel_full != nullptr) {
12331     do_invalidate_channel_full(channel_full, channel_id, need_drop_slow_mode_delay);
12332     update_channel_full(channel_full, channel_id, "invalidate_channel_full");
12333   } else {
12334     invalidated_channels_full_.insert(channel_id);
12335   }
12336 }
12337 
do_invalidate_channel_full(ChannelFull * channel_full,ChannelId channel_id,bool need_drop_slow_mode_delay)12338 void ContactsManager::do_invalidate_channel_full(ChannelFull *channel_full, ChannelId channel_id,
12339                                                  bool need_drop_slow_mode_delay) {
12340   CHECK(channel_full != nullptr);
12341   td_->messages_manager_->on_dialog_info_full_invalidated(DialogId(channel_id));
12342   if (channel_full->expires_at >= Time::now()) {
12343     channel_full->expires_at = 0.0;
12344     channel_full->need_save_to_database = true;
12345   }
12346   if (need_drop_slow_mode_delay && channel_full->slow_mode_delay != 0) {
12347     channel_full->slow_mode_delay = 0;
12348     channel_full->slow_mode_next_send_date = 0;
12349     channel_full->is_slow_mode_next_send_date_changed = true;
12350     channel_full->is_changed = true;
12351   }
12352 }
12353 
on_update_chat_full_photo(ChatFull * chat_full,ChatId chat_id,Photo photo)12354 void ContactsManager::on_update_chat_full_photo(ChatFull *chat_full, ChatId chat_id, Photo photo) {
12355   CHECK(chat_full != nullptr);
12356   if (photo != chat_full->photo) {
12357     chat_full->photo = std::move(photo);
12358     chat_full->is_changed = true;
12359   }
12360   if (chat_full->photo.is_empty()) {
12361     drop_chat_photos(chat_id, true, false, "on_update_chat_full_photo");
12362   }
12363 
12364   auto photo_file_ids = photo_get_file_ids(chat_full->photo);
12365   if (chat_full->registered_photo_file_ids == photo_file_ids) {
12366     return;
12367   }
12368 
12369   auto &file_source_id = chat_full->file_source_id;
12370   if (!file_source_id.is_valid()) {
12371     auto it = chat_full_file_source_ids_.find(chat_id);
12372     if (it != chat_full_file_source_ids_.end()) {
12373       VLOG(file_references) << "Move " << it->second << " inside of " << chat_id;
12374       file_source_id = it->second;
12375       chat_full_file_source_ids_.erase(it);
12376     } else {
12377       VLOG(file_references) << "Need to create new file source for full " << chat_id;
12378       file_source_id = td_->file_reference_manager_->create_chat_full_file_source(chat_id);
12379     }
12380   }
12381 
12382   for (auto &file_id : chat_full->registered_photo_file_ids) {
12383     td_->file_manager_->remove_file_source(file_id, file_source_id);
12384   }
12385   chat_full->registered_photo_file_ids = std::move(photo_file_ids);
12386   for (auto &file_id : chat_full->registered_photo_file_ids) {
12387     td_->file_manager_->add_file_source(file_id, file_source_id);
12388   }
12389 }
12390 
on_update_channel_full_photo(ChannelFull * channel_full,ChannelId channel_id,Photo photo)12391 void ContactsManager::on_update_channel_full_photo(ChannelFull *channel_full, ChannelId channel_id, Photo photo) {
12392   CHECK(channel_full != nullptr);
12393   if (photo != channel_full->photo) {
12394     channel_full->photo = std::move(photo);
12395     channel_full->is_changed = true;
12396   }
12397   if (channel_full->photo.is_empty()) {
12398     drop_channel_photos(channel_id, true, false, "on_update_channel_full_photo");
12399   }
12400 
12401   auto photo_file_ids = photo_get_file_ids(channel_full->photo);
12402   if (channel_full->registered_photo_file_ids == photo_file_ids) {
12403     return;
12404   }
12405 
12406   auto &file_source_id = channel_full->file_source_id;
12407   if (!file_source_id.is_valid()) {
12408     auto it = channel_full_file_source_ids_.find(channel_id);
12409     if (it != channel_full_file_source_ids_.end()) {
12410       VLOG(file_references) << "Move " << it->second << " inside of " << channel_id;
12411       file_source_id = it->second;
12412       channel_full_file_source_ids_.erase(it);
12413     } else {
12414       VLOG(file_references) << "Need to create new file source for full " << channel_id;
12415       file_source_id = td_->file_reference_manager_->create_channel_full_file_source(channel_id);
12416     }
12417   }
12418 
12419   for (auto &file_id : channel_full->registered_photo_file_ids) {
12420     td_->file_manager_->remove_file_source(file_id, file_source_id);
12421   }
12422   channel_full->registered_photo_file_ids = std::move(photo_file_ids);
12423   for (auto &file_id : channel_full->registered_photo_file_ids) {
12424     td_->file_manager_->add_file_source(file_id, file_source_id);
12425   }
12426 }
12427 
on_get_permanent_dialog_invite_link(DialogId dialog_id,const DialogInviteLink & invite_link)12428 void ContactsManager::on_get_permanent_dialog_invite_link(DialogId dialog_id, const DialogInviteLink &invite_link) {
12429   switch (dialog_id.get_type()) {
12430     case DialogType::Chat: {
12431       auto chat_id = dialog_id.get_chat_id();
12432       auto chat_full = get_chat_full_force(chat_id, "on_get_permanent_dialog_invite_link");
12433       if (chat_full != nullptr && update_permanent_invite_link(chat_full->invite_link, invite_link)) {
12434         chat_full->is_changed = true;
12435         update_chat_full(chat_full, chat_id, "on_get_permanent_dialog_invite_link");
12436       }
12437       break;
12438     }
12439     case DialogType::Channel: {
12440       auto channel_id = dialog_id.get_channel_id();
12441       auto channel_full = get_channel_full_force(channel_id, true, "on_get_permanent_dialog_invite_link");
12442       if (channel_full != nullptr && update_permanent_invite_link(channel_full->invite_link, invite_link)) {
12443         channel_full->is_changed = true;
12444         update_channel_full(channel_full, channel_id, "on_get_permanent_dialog_invite_link");
12445       }
12446       break;
12447     }
12448     case DialogType::User:
12449     case DialogType::SecretChat:
12450     case DialogType::None:
12451     default:
12452       UNREACHABLE();
12453   }
12454 }
12455 
on_update_chat_full_invite_link(ChatFull * chat_full,tl_object_ptr<telegram_api::chatInviteExported> && invite_link)12456 void ContactsManager::on_update_chat_full_invite_link(ChatFull *chat_full,
12457                                                       tl_object_ptr<telegram_api::chatInviteExported> &&invite_link) {
12458   CHECK(chat_full != nullptr);
12459   if (update_permanent_invite_link(chat_full->invite_link, DialogInviteLink(std::move(invite_link)))) {
12460     chat_full->is_changed = true;
12461   }
12462 }
12463 
on_update_channel_full_invite_link(ChannelFull * channel_full,tl_object_ptr<telegram_api::chatInviteExported> && invite_link)12464 void ContactsManager::on_update_channel_full_invite_link(
12465     ChannelFull *channel_full, tl_object_ptr<telegram_api::chatInviteExported> &&invite_link) {
12466   CHECK(channel_full != nullptr);
12467   if (update_permanent_invite_link(channel_full->invite_link, DialogInviteLink(std::move(invite_link)))) {
12468     channel_full->is_changed = true;
12469   }
12470 }
12471 
remove_linked_channel_id(ChannelId channel_id)12472 void ContactsManager::remove_linked_channel_id(ChannelId channel_id) {
12473   if (!channel_id.is_valid()) {
12474     return;
12475   }
12476 
12477   auto it = linked_channel_ids_.find(channel_id);
12478   if (it != linked_channel_ids_.end()) {
12479     auto linked_channel_id = it->second;
12480     linked_channel_ids_.erase(it);
12481     linked_channel_ids_.erase(linked_channel_id);
12482   }
12483 }
12484 
get_linked_channel_id(ChannelId channel_id) const12485 ChannelId ContactsManager::get_linked_channel_id(ChannelId channel_id) const {
12486   auto channel_full = get_channel_full(channel_id);
12487   if (channel_full != nullptr) {
12488     return channel_full->linked_channel_id;
12489   }
12490 
12491   auto it = linked_channel_ids_.find(channel_id);
12492   if (it != linked_channel_ids_.end()) {
12493     return it->second;
12494   }
12495 
12496   return ChannelId();
12497 }
12498 
on_update_channel_full_linked_channel_id(ChannelFull * channel_full,ChannelId channel_id,ChannelId linked_channel_id)12499 void ContactsManager::on_update_channel_full_linked_channel_id(ChannelFull *channel_full, ChannelId channel_id,
12500                                                                ChannelId linked_channel_id) {
12501   auto old_linked_channel_id = get_linked_channel_id(channel_id);
12502   LOG(INFO) << "Uplate linked channel in " << channel_id << " from " << old_linked_channel_id << " to "
12503             << linked_channel_id;
12504 
12505   if (channel_full != nullptr && channel_full->linked_channel_id != linked_channel_id &&
12506       channel_full->linked_channel_id.is_valid()) {
12507     get_channel_force(channel_full->linked_channel_id);
12508     get_channel_full_force(channel_full->linked_channel_id, true, "on_update_channel_full_linked_channel_id 0");
12509   }
12510   auto old_linked_linked_channel_id = get_linked_channel_id(linked_channel_id);
12511 
12512   remove_linked_channel_id(channel_id);
12513   remove_linked_channel_id(linked_channel_id);
12514   if (channel_id.is_valid() && linked_channel_id.is_valid()) {
12515     linked_channel_ids_[channel_id] = linked_channel_id;
12516     linked_channel_ids_[linked_channel_id] = channel_id;
12517   }
12518 
12519   if (channel_full != nullptr && channel_full->linked_channel_id != linked_channel_id) {
12520     if (channel_full->linked_channel_id.is_valid()) {
12521       // remove link from a previously linked channel_full
12522       auto linked_channel = get_channel_force(channel_full->linked_channel_id);
12523       if (linked_channel != nullptr && linked_channel->has_linked_channel) {
12524         linked_channel->has_linked_channel = false;
12525         linked_channel->is_changed = true;
12526         update_channel(linked_channel, channel_full->linked_channel_id);
12527         reload_channel(channel_full->linked_channel_id, Auto());
12528       }
12529       auto linked_channel_full =
12530           get_channel_full_force(channel_full->linked_channel_id, true, "on_update_channel_full_linked_channel_id 1");
12531       if (linked_channel_full != nullptr && linked_channel_full->linked_channel_id == channel_id) {
12532         linked_channel_full->linked_channel_id = ChannelId();
12533         linked_channel_full->is_changed = true;
12534         update_channel_full(linked_channel_full, channel_full->linked_channel_id,
12535                             "on_update_channel_full_linked_channel_id 3");
12536       }
12537     }
12538 
12539     channel_full->linked_channel_id = linked_channel_id;
12540     channel_full->is_changed = true;
12541 
12542     if (channel_full->linked_channel_id.is_valid()) {
12543       // add link from a newly linked channel_full
12544       auto linked_channel = get_channel_force(channel_full->linked_channel_id);
12545       if (linked_channel != nullptr && !linked_channel->has_linked_channel) {
12546         linked_channel->has_linked_channel = true;
12547         linked_channel->is_changed = true;
12548         update_channel(linked_channel, channel_full->linked_channel_id);
12549         reload_channel(channel_full->linked_channel_id, Auto());
12550       }
12551       auto linked_channel_full =
12552           get_channel_full_force(channel_full->linked_channel_id, true, "on_update_channel_full_linked_channel_id 2");
12553       if (linked_channel_full != nullptr && linked_channel_full->linked_channel_id != channel_id) {
12554         linked_channel_full->linked_channel_id = channel_id;
12555         linked_channel_full->is_changed = true;
12556         update_channel_full(linked_channel_full, channel_full->linked_channel_id,
12557                             "on_update_channel_full_linked_channel_id 4");
12558       }
12559     }
12560   }
12561 
12562   Channel *c = get_channel(channel_id);
12563   CHECK(c != nullptr);
12564   if (linked_channel_id.is_valid() != c->has_linked_channel) {
12565     c->has_linked_channel = linked_channel_id.is_valid();
12566     c->is_changed = true;
12567     update_channel(c, channel_id);
12568   }
12569 
12570   if (old_linked_channel_id != linked_channel_id) {
12571     // must be called after the linked channel is changed
12572     td_->messages_manager_->on_dialog_linked_channel_updated(DialogId(channel_id), old_linked_channel_id,
12573                                                              linked_channel_id);
12574   }
12575 
12576   if (linked_channel_id.is_valid()) {
12577     auto new_linked_linked_channel_id = get_linked_channel_id(linked_channel_id);
12578     LOG(INFO) << "Uplate linked channel in " << linked_channel_id << " from " << old_linked_linked_channel_id << " to "
12579               << new_linked_linked_channel_id;
12580     if (old_linked_linked_channel_id != new_linked_linked_channel_id) {
12581       // must be called after the linked channel is changed
12582       td_->messages_manager_->on_dialog_linked_channel_updated(
12583           DialogId(linked_channel_id), old_linked_linked_channel_id, new_linked_linked_channel_id);
12584     }
12585   }
12586 }
12587 
on_update_channel_full_location(ChannelFull * channel_full,ChannelId channel_id,const DialogLocation & location)12588 void ContactsManager::on_update_channel_full_location(ChannelFull *channel_full, ChannelId channel_id,
12589                                                       const DialogLocation &location) {
12590   if (channel_full->location != location) {
12591     channel_full->location = location;
12592     channel_full->is_changed = true;
12593   }
12594 
12595   Channel *c = get_channel(channel_id);
12596   CHECK(c != nullptr);
12597   on_update_channel_has_location(c, channel_id, !location.empty());
12598   update_channel(c, channel_id);
12599 }
12600 
on_update_channel_full_slow_mode_delay(ChannelFull * channel_full,ChannelId channel_id,int32 slow_mode_delay,int32 slow_mode_next_send_date)12601 void ContactsManager::on_update_channel_full_slow_mode_delay(ChannelFull *channel_full, ChannelId channel_id,
12602                                                              int32 slow_mode_delay, int32 slow_mode_next_send_date) {
12603   if (slow_mode_delay < 0) {
12604     LOG(ERROR) << "Receive slow mode delay " << slow_mode_delay << " in " << channel_id;
12605     slow_mode_delay = 0;
12606   }
12607 
12608   if (channel_full->slow_mode_delay != slow_mode_delay) {
12609     channel_full->slow_mode_delay = slow_mode_delay;
12610     channel_full->is_changed = true;
12611   }
12612   on_update_channel_full_slow_mode_next_send_date(channel_full, slow_mode_next_send_date);
12613 
12614   Channel *c = get_channel(channel_id);
12615   CHECK(c != nullptr);
12616   bool is_slow_mode_enabled = slow_mode_delay != 0;
12617   if (is_slow_mode_enabled != c->is_slow_mode_enabled) {
12618     c->is_slow_mode_enabled = is_slow_mode_enabled;
12619     c->is_changed = true;
12620     update_channel(c, channel_id);
12621   }
12622 }
12623 
on_update_channel_full_slow_mode_next_send_date(ChannelFull * channel_full,int32 slow_mode_next_send_date)12624 void ContactsManager::on_update_channel_full_slow_mode_next_send_date(ChannelFull *channel_full,
12625                                                                       int32 slow_mode_next_send_date) {
12626   if (slow_mode_next_send_date < 0) {
12627     LOG(ERROR) << "Receive slow mode next send date " << slow_mode_next_send_date;
12628     slow_mode_next_send_date = 0;
12629   }
12630   if (channel_full->slow_mode_delay == 0 && slow_mode_next_send_date > 0) {
12631     LOG(ERROR) << "Slow mode is disabled, but next send date is " << slow_mode_next_send_date;
12632     slow_mode_next_send_date = 0;
12633   }
12634 
12635   if (slow_mode_next_send_date != 0) {
12636     auto now = G()->unix_time();
12637     if (slow_mode_next_send_date <= now) {
12638       slow_mode_next_send_date = 0;
12639     }
12640     if (slow_mode_next_send_date > now + 3601) {
12641       slow_mode_next_send_date = now + 3601;
12642     }
12643   }
12644   if (channel_full->slow_mode_next_send_date != slow_mode_next_send_date) {
12645     channel_full->slow_mode_next_send_date = slow_mode_next_send_date;
12646     channel_full->is_slow_mode_next_send_date_changed = true;
12647     channel_full->is_changed = true;
12648   }
12649 }
12650 
on_get_dialog_invite_link_info(const string & invite_link,tl_object_ptr<telegram_api::ChatInvite> && chat_invite_ptr,Promise<Unit> && promise)12651 void ContactsManager::on_get_dialog_invite_link_info(const string &invite_link,
12652                                                      tl_object_ptr<telegram_api::ChatInvite> &&chat_invite_ptr,
12653                                                      Promise<Unit> &&promise) {
12654   CHECK(chat_invite_ptr != nullptr);
12655   switch (chat_invite_ptr->get_id()) {
12656     case telegram_api::chatInviteAlready::ID:
12657     case telegram_api::chatInvitePeek::ID: {
12658       telegram_api::object_ptr<telegram_api::Chat> chat = nullptr;
12659       int32 accessible_before = 0;
12660       if (chat_invite_ptr->get_id() == telegram_api::chatInviteAlready::ID) {
12661         auto chat_invite_already = move_tl_object_as<telegram_api::chatInviteAlready>(chat_invite_ptr);
12662         chat = std::move(chat_invite_already->chat_);
12663       } else {
12664         auto chat_invite_peek = move_tl_object_as<telegram_api::chatInvitePeek>(chat_invite_ptr);
12665         chat = std::move(chat_invite_peek->chat_);
12666         accessible_before = chat_invite_peek->expires_;
12667       }
12668       auto chat_id = get_chat_id(chat);
12669       if (chat_id != ChatId() && !chat_id.is_valid()) {
12670         LOG(ERROR) << "Receive invalid " << chat_id;
12671         chat_id = ChatId();
12672       }
12673       auto channel_id = get_channel_id(chat);
12674       if (channel_id != ChannelId() && !channel_id.is_valid()) {
12675         LOG(ERROR) << "Receive invalid " << channel_id;
12676         channel_id = ChannelId();
12677       }
12678       if (!channel_id.is_valid() || accessible_before < 0) {
12679         LOG(ERROR) << "Receive expires = " << accessible_before << " for invite link " << invite_link << " to "
12680                    << to_string(chat);
12681         accessible_before = 0;
12682       }
12683       on_get_chat(std::move(chat), "chatInviteAlready");
12684 
12685       CHECK(chat_id == ChatId() || channel_id == ChannelId());
12686 
12687       // the access is already expired, reget the info
12688       if (accessible_before != 0 && accessible_before <= G()->unix_time() + 1) {
12689         td_->create_handler<CheckChatInviteQuery>(std::move(promise))->send(invite_link);
12690         return;
12691       }
12692 
12693       DialogId dialog_id = chat_id.is_valid() ? DialogId(chat_id) : DialogId(channel_id);
12694       auto &invite_link_info = invite_link_infos_[invite_link];
12695       if (invite_link_info == nullptr) {
12696         invite_link_info = make_unique<InviteLinkInfo>();
12697       }
12698       invite_link_info->dialog_id = dialog_id;
12699       if (accessible_before != 0) {
12700         auto &access = dialog_access_by_invite_link_[dialog_id];
12701         access.invite_links.insert(invite_link);
12702         if (access.accessible_before < accessible_before) {
12703           access.accessible_before = accessible_before;
12704 
12705           auto expires_in = accessible_before - G()->unix_time() - 1;
12706           invite_link_info_expire_timeout_.set_timeout_in(dialog_id.get(), expires_in);
12707         }
12708       }
12709       break;
12710     }
12711     case telegram_api::chatInvite::ID: {
12712       auto chat_invite = move_tl_object_as<telegram_api::chatInvite>(chat_invite_ptr);
12713       vector<UserId> participant_user_ids;
12714       for (auto &user : chat_invite->participants_) {
12715         auto user_id = get_user_id(user);
12716         if (!user_id.is_valid()) {
12717           LOG(ERROR) << "Receive invalid " << user_id;
12718           continue;
12719         }
12720 
12721         on_get_user(std::move(user), "chatInvite");
12722         participant_user_ids.push_back(user_id);
12723       }
12724 
12725       auto &invite_link_info = invite_link_infos_[invite_link];
12726       if (invite_link_info == nullptr) {
12727         invite_link_info = make_unique<InviteLinkInfo>();
12728       }
12729       invite_link_info->dialog_id = DialogId();
12730       invite_link_info->title = chat_invite->title_;
12731       invite_link_info->photo = get_photo(td_->file_manager_.get(), std::move(chat_invite->photo_), DialogId());
12732       invite_link_info->description = std::move(chat_invite->about_);
12733       invite_link_info->participant_count = chat_invite->participants_count_;
12734       invite_link_info->participant_user_ids = std::move(participant_user_ids);
12735       invite_link_info->creates_join_request = std::move(chat_invite->request_needed_);
12736       invite_link_info->is_chat = (chat_invite->flags_ & CHAT_INVITE_FLAG_IS_CHANNEL) == 0;
12737       invite_link_info->is_channel = (chat_invite->flags_ & CHAT_INVITE_FLAG_IS_CHANNEL) != 0;
12738 
12739       bool is_broadcast = (chat_invite->flags_ & CHAT_INVITE_FLAG_IS_BROADCAST) != 0;
12740       bool is_public = (chat_invite->flags_ & CHAT_INVITE_FLAG_IS_PUBLIC) != 0;
12741       bool is_megagroup = (chat_invite->flags_ & CHAT_INVITE_FLAG_IS_MEGAGROUP) != 0;
12742 
12743       if (!invite_link_info->is_channel) {
12744         if (is_broadcast || is_public || is_megagroup) {
12745           LOG(ERROR) << "Receive wrong chat invite: " << to_string(chat_invite);
12746           is_public = is_megagroup = false;
12747         }
12748       } else {
12749         LOG_IF(ERROR, is_broadcast == is_megagroup) << "Receive wrong chat invite: " << to_string(chat_invite);
12750       }
12751 
12752       invite_link_info->is_public = is_public;
12753       invite_link_info->is_megagroup = is_megagroup;
12754       break;
12755     }
12756     default:
12757       UNREACHABLE();
12758   }
12759   promise.set_value(Unit());
12760 }
12761 
remove_dialog_access_by_invite_link(DialogId dialog_id)12762 void ContactsManager::remove_dialog_access_by_invite_link(DialogId dialog_id) {
12763   auto access_it = dialog_access_by_invite_link_.find(dialog_id);
12764   if (access_it == dialog_access_by_invite_link_.end()) {
12765     return;
12766   }
12767 
12768   for (auto &invite_link : access_it->second.invite_links) {
12769     invalidate_invite_link_info(invite_link);
12770   }
12771   dialog_access_by_invite_link_.erase(access_it);
12772 
12773   invite_link_info_expire_timeout_.cancel_timeout(dialog_id.get());
12774 }
12775 
update_permanent_invite_link(DialogInviteLink & invite_link,DialogInviteLink new_invite_link)12776 bool ContactsManager::update_permanent_invite_link(DialogInviteLink &invite_link, DialogInviteLink new_invite_link) {
12777   if (new_invite_link != invite_link) {
12778     if (invite_link.is_valid() && invite_link.get_invite_link() != new_invite_link.get_invite_link()) {
12779       // old link was invalidated
12780       invite_link_infos_.erase(invite_link.get_invite_link());
12781     }
12782 
12783     invite_link = std::move(new_invite_link);
12784     return true;
12785   }
12786   return false;
12787 }
12788 
invalidate_invite_link_info(const string & invite_link)12789 void ContactsManager::invalidate_invite_link_info(const string &invite_link) {
12790   LOG(INFO) << "Invalidate info about invite link " << invite_link;
12791   invite_link_infos_.erase(invite_link);
12792 }
12793 
repair_chat_participants(ChatId chat_id)12794 void ContactsManager::repair_chat_participants(ChatId chat_id) {
12795   send_get_chat_full_query(chat_id, Auto(), "repair_chat_participants");
12796 }
12797 
on_update_chat_add_user(ChatId chat_id,UserId inviter_user_id,UserId user_id,int32 date,int32 version)12798 void ContactsManager::on_update_chat_add_user(ChatId chat_id, UserId inviter_user_id, UserId user_id, int32 date,
12799                                               int32 version) {
12800   if (!chat_id.is_valid()) {
12801     LOG(ERROR) << "Receive invalid " << chat_id;
12802     return;
12803   }
12804   if (!have_user(user_id)) {
12805     LOG(ERROR) << "Can't find " << user_id;
12806     return;
12807   }
12808   if (!have_user(inviter_user_id)) {
12809     LOG(ERROR) << "Can't find " << inviter_user_id;
12810     return;
12811   }
12812   LOG(INFO) << "Receive updateChatParticipantAdd to " << chat_id << " with " << user_id << " invited by "
12813             << inviter_user_id << " at " << date << " with version " << version;
12814 
12815   ChatFull *chat_full = get_chat_full_force(chat_id, "on_update_chat_add_user");
12816   if (chat_full == nullptr) {
12817     LOG(INFO) << "Ignoring update about members of " << chat_id;
12818     return;
12819   }
12820   auto c = get_chat(chat_id);
12821   if (c == nullptr) {
12822     LOG(ERROR) << "Receive updateChatParticipantAdd for unknown " << chat_id << ". Couldn't apply it";
12823     repair_chat_participants(chat_id);
12824     return;
12825   }
12826   if (c->status.is_left()) {
12827     // possible if updates come out of order
12828     LOG(WARNING) << "Receive updateChatParticipantAdd for left " << chat_id << ". Couldn't apply it";
12829 
12830     repair_chat_participants(chat_id);  // just in case
12831     return;
12832   }
12833   if (on_update_chat_full_participants_short(chat_full, chat_id, version)) {
12834     for (auto &participant : chat_full->participants) {
12835       if (participant.dialog_id_ == DialogId(user_id)) {
12836         if (participant.inviter_user_id_ != inviter_user_id) {
12837           LOG(ERROR) << user_id << " was readded to " << chat_id << " by " << inviter_user_id
12838                      << ", previously invited by " << participant.inviter_user_id_;
12839           participant.inviter_user_id_ = inviter_user_id;
12840           participant.joined_date_ = date;
12841           repair_chat_participants(chat_id);
12842         } else {
12843           // Possible if update comes twice
12844           LOG(INFO) << user_id << " was readded to " << chat_id;
12845         }
12846         return;
12847       }
12848     }
12849     chat_full->participants.push_back(DialogParticipant{DialogId(user_id), inviter_user_id, date,
12850                                                         user_id == chat_full->creator_user_id
12851                                                             ? DialogParticipantStatus::Creator(true, false, string())
12852                                                             : DialogParticipantStatus::Member()});
12853     update_chat_online_member_count(chat_full, chat_id, false);
12854     chat_full->is_changed = true;
12855     update_chat_full(chat_full, chat_id, "on_update_chat_add_user");
12856 
12857     // Chat is already updated
12858     if (chat_full->version == c->version &&
12859         narrow_cast<int32>(chat_full->participants.size()) != c->participant_count) {
12860       LOG(ERROR) << "Number of members in " << chat_id << " with version " << c->version << " is "
12861                  << c->participant_count << " but there are " << chat_full->participants.size()
12862                  << " members in the ChatFull";
12863       repair_chat_participants(chat_id);
12864     }
12865   }
12866 }
12867 
on_update_chat_edit_administrator(ChatId chat_id,UserId user_id,bool is_administrator,int32 version)12868 void ContactsManager::on_update_chat_edit_administrator(ChatId chat_id, UserId user_id, bool is_administrator,
12869                                                         int32 version) {
12870   if (!chat_id.is_valid()) {
12871     LOG(ERROR) << "Receive invalid " << chat_id;
12872     return;
12873   }
12874   if (!have_user(user_id)) {
12875     LOG(ERROR) << "Can't find " << user_id;
12876     return;
12877   }
12878   LOG(INFO) << "Receive updateChatParticipantAdmin in " << chat_id << " with " << user_id << ", administrator rights "
12879             << (is_administrator ? "enabled" : "disabled") << " with version " << version;
12880 
12881   auto c = get_chat_force(chat_id);
12882   if (c == nullptr) {
12883     LOG(INFO) << "Ignoring update about members of unknown " << chat_id;
12884     return;
12885   }
12886 
12887   if (c->status.is_left()) {
12888     // possible if updates come out of order
12889     LOG(WARNING) << "Receive updateChatParticipantAdmin for left " << chat_id << ". Couldn't apply it";
12890 
12891     repair_chat_participants(chat_id);  // just in case
12892     return;
12893   }
12894   if (version <= -1) {
12895     LOG(ERROR) << "Receive wrong version " << version << " for " << chat_id;
12896     return;
12897   }
12898   CHECK(c->version >= 0);
12899 
12900   auto status = is_administrator ? DialogParticipantStatus::GroupAdministrator(c->status.is_creator())
12901                                  : DialogParticipantStatus::Member();
12902   if (version > c->version) {
12903     if (version != c->version + 1) {
12904       LOG(INFO) << "Administrators of " << chat_id << " with version " << c->version
12905                 << " has changed, but new version is " << version;
12906       repair_chat_participants(chat_id);
12907       return;
12908     }
12909 
12910     c->version = version;
12911     c->need_save_to_database = true;
12912     if (user_id == get_my_id() && !c->status.is_creator()) {
12913       // if chat with version was already received, then the update is already processed
12914       // so we need to call on_update_chat_status only if version > c->version
12915       on_update_chat_status(c, chat_id, status);
12916     }
12917     update_chat(c, chat_id);
12918   }
12919 
12920   ChatFull *chat_full = get_chat_full_force(chat_id, "on_update_chat_edit_administrator");
12921   if (chat_full != nullptr) {
12922     if (chat_full->version + 1 == version) {
12923       for (auto &participant : chat_full->participants) {
12924         if (participant.dialog_id_ == DialogId(user_id)) {
12925           participant.status_ = std::move(status);
12926           chat_full->is_changed = true;
12927           update_chat_full(chat_full, chat_id, "on_update_chat_edit_administrator");
12928           return;
12929         }
12930       }
12931     }
12932 
12933     // can't find chat member or version have increased too much
12934     repair_chat_participants(chat_id);
12935   }
12936 }
12937 
on_update_chat_delete_user(ChatId chat_id,UserId user_id,int32 version)12938 void ContactsManager::on_update_chat_delete_user(ChatId chat_id, UserId user_id, int32 version) {
12939   if (!chat_id.is_valid()) {
12940     LOG(ERROR) << "Receive invalid " << chat_id;
12941     return;
12942   }
12943   if (!have_user(user_id)) {
12944     LOG(ERROR) << "Can't find " << user_id;
12945     return;
12946   }
12947   LOG(INFO) << "Receive updateChatParticipantDelete from " << chat_id << " with " << user_id << " and version "
12948             << version;
12949 
12950   ChatFull *chat_full = get_chat_full_force(chat_id, "on_update_chat_delete_user");
12951   if (chat_full == nullptr) {
12952     LOG(INFO) << "Ignoring update about members of " << chat_id;
12953     return;
12954   }
12955   const Chat *c = get_chat_force(chat_id);
12956   if (c == nullptr) {
12957     LOG(ERROR) << "Receive updateChatParticipantDelete for unknown " << chat_id;
12958     repair_chat_participants(chat_id);
12959     return;
12960   }
12961   if (user_id == get_my_id()) {
12962     LOG_IF(WARNING, c->status.is_member()) << "User was removed from " << chat_id
12963                                            << " but it is not left the group. Possible if updates comes out of order";
12964     return;
12965   }
12966   if (c->status.is_left()) {
12967     // possible if updates come out of order
12968     LOG(INFO) << "Receive updateChatParticipantDelete for left " << chat_id;
12969 
12970     repair_chat_participants(chat_id);
12971     return;
12972   }
12973   if (on_update_chat_full_participants_short(chat_full, chat_id, version)) {
12974     for (size_t i = 0; i < chat_full->participants.size(); i++) {
12975       if (chat_full->participants[i].dialog_id_ == DialogId(user_id)) {
12976         chat_full->participants[i] = chat_full->participants.back();
12977         chat_full->participants.resize(chat_full->participants.size() - 1);
12978         chat_full->is_changed = true;
12979         update_chat_online_member_count(chat_full, chat_id, false);
12980         update_chat_full(chat_full, chat_id, "on_update_chat_delete_user");
12981 
12982         if (static_cast<int32>(chat_full->participants.size()) != c->participant_count) {
12983           repair_chat_participants(chat_id);
12984         }
12985         return;
12986       }
12987     }
12988     LOG(ERROR) << "Can't find basic group member " << user_id << " in " << chat_id << " to be removed";
12989     repair_chat_participants(chat_id);
12990   }
12991 }
12992 
on_update_chat_status(Chat * c,ChatId chat_id,DialogParticipantStatus status)12993 void ContactsManager::on_update_chat_status(Chat *c, ChatId chat_id, DialogParticipantStatus status) {
12994   if (c->status != status) {
12995     LOG(INFO) << "Update " << chat_id << " status from " << c->status << " to " << status;
12996     bool need_reload_group_call = c->status.can_manage_calls() != status.can_manage_calls();
12997     bool need_drop_invite_link = c->status.can_manage_invite_links() && !status.can_manage_invite_links();
12998 
12999     c->status = std::move(status);
13000     c->is_status_changed = true;
13001 
13002     if (c->status.is_left()) {
13003       c->participant_count = 0;
13004       c->version = -1;
13005       c->default_permissions_version = -1;
13006       c->pinned_message_version = -1;
13007 
13008       drop_chat_full(chat_id);
13009     } else if (need_drop_invite_link) {
13010       ChatFull *chat_full = get_chat_full_force(chat_id, "on_update_chat_status");
13011       if (chat_full != nullptr) {
13012         on_update_chat_full_invite_link(chat_full, nullptr);
13013         update_chat_full(chat_full, chat_id, "on_update_chat_status");
13014       }
13015     }
13016     if (need_reload_group_call) {
13017       send_closure_later(G()->messages_manager(), &MessagesManager::on_update_dialog_group_call_rights,
13018                          DialogId(chat_id));
13019     }
13020 
13021     c->is_changed = true;
13022   }
13023 }
13024 
on_update_chat_default_permissions(ChatId chat_id,RestrictedRights default_permissions,int32 version)13025 void ContactsManager::on_update_chat_default_permissions(ChatId chat_id, RestrictedRights default_permissions,
13026                                                          int32 version) {
13027   if (!chat_id.is_valid()) {
13028     LOG(ERROR) << "Receive invalid " << chat_id;
13029     return;
13030   }
13031   auto c = get_chat_force(chat_id);
13032   if (c == nullptr) {
13033     LOG(INFO) << "Ignoring update about unknown " << chat_id;
13034     return;
13035   }
13036 
13037   LOG(INFO) << "Receive updateChatDefaultBannedRights in " << chat_id << " with " << default_permissions
13038             << " and version " << version << ". Current version is " << c->version;
13039 
13040   if (c->status.is_left()) {
13041     // possible if updates come out of order
13042     LOG(WARNING) << "Receive updateChatDefaultBannedRights for left " << chat_id << ". Couldn't apply it";
13043 
13044     repair_chat_participants(chat_id);  // just in case
13045     return;
13046   }
13047   if (version <= -1) {
13048     LOG(ERROR) << "Receive wrong version " << version << " for " << chat_id;
13049     return;
13050   }
13051   CHECK(c->version >= 0);
13052 
13053   if (version > c->version) {
13054     // this should be unreachable, because version and default permissions must be already updated from
13055     // the chat object in on_chat_update
13056     if (version != c->version + 1) {
13057       LOG(INFO) << "Default permissions of " << chat_id << " with version " << c->version
13058                 << " has changed, but new version is " << version;
13059       repair_chat_participants(chat_id);
13060       return;
13061     }
13062 
13063     LOG_IF(ERROR, default_permissions == c->default_permissions)
13064         << "Receive updateChatDefaultBannedRights in " << chat_id << " with version " << version
13065         << " and default_permissions = " << default_permissions
13066         << ", but default_permissions are not changed. Current version is " << c->version;
13067     c->version = version;
13068     c->need_save_to_database = true;
13069     on_update_chat_default_permissions(c, chat_id, default_permissions, version);
13070     update_chat(c, chat_id);
13071   }
13072 }
13073 
on_update_chat_default_permissions(Chat * c,ChatId chat_id,RestrictedRights default_permissions,int32 version)13074 void ContactsManager::on_update_chat_default_permissions(Chat *c, ChatId chat_id, RestrictedRights default_permissions,
13075                                                          int32 version) {
13076   if (c->default_permissions != default_permissions && version >= c->default_permissions_version) {
13077     LOG(INFO) << "Update " << chat_id << " default permissions from " << c->default_permissions << " to "
13078               << default_permissions << " and version from " << c->default_permissions_version << " to " << version;
13079     c->default_permissions = default_permissions;
13080     c->default_permissions_version = version;
13081     c->is_default_permissions_changed = true;
13082     c->need_save_to_database = true;
13083   }
13084 }
13085 
on_update_chat_noforwards(Chat * c,ChatId chat_id,bool noforwards)13086 void ContactsManager::on_update_chat_noforwards(Chat *c, ChatId chat_id, bool noforwards) {
13087   if (c->noforwards != noforwards) {
13088     LOG(INFO) << "Update " << chat_id << " has_protected_content from " << c->noforwards << " to " << noforwards;
13089     c->noforwards = noforwards;
13090     c->is_noforwards_changed = true;
13091     c->need_save_to_database = true;
13092   }
13093 }
13094 
on_update_chat_pinned_message(ChatId chat_id,MessageId pinned_message_id,int32 version)13095 void ContactsManager::on_update_chat_pinned_message(ChatId chat_id, MessageId pinned_message_id, int32 version) {
13096   if (!chat_id.is_valid()) {
13097     LOG(ERROR) << "Receive invalid " << chat_id;
13098     return;
13099   }
13100   auto c = get_chat_force(chat_id);
13101   if (c == nullptr) {
13102     LOG(INFO) << "Ignoring update about unknown " << chat_id;
13103     return;
13104   }
13105 
13106   LOG(INFO) << "Receive updateChatPinnedMessage in " << chat_id << " with " << pinned_message_id << " and version "
13107             << version << ". Current version is " << c->version << "/" << c->pinned_message_version;
13108 
13109   if (c->status.is_left()) {
13110     // possible if updates come out of order
13111     repair_chat_participants(chat_id);  // just in case
13112     return;
13113   }
13114   if (version <= -1) {
13115     LOG(ERROR) << "Receive wrong version " << version << " for " << chat_id;
13116     return;
13117   }
13118   CHECK(c->version >= 0);
13119 
13120   if (version >= c->pinned_message_version) {
13121     if (version != c->version + 1 && version != c->version) {
13122       LOG(INFO) << "Pinned message of " << chat_id << " with version " << c->version
13123                 << " has changed, but new version is " << version;
13124       repair_chat_participants(chat_id);
13125     } else if (version == c->version + 1) {
13126       c->version = version;
13127       c->need_save_to_database = true;
13128     }
13129     td_->messages_manager_->on_update_dialog_last_pinned_message_id(DialogId(chat_id), pinned_message_id);
13130     if (version > c->pinned_message_version) {
13131       LOG(INFO) << "Change pinned message version of " << chat_id << " from " << c->pinned_message_version << " to "
13132                 << version;
13133       c->pinned_message_version = version;
13134       c->need_save_to_database = true;
13135     }
13136     update_chat(c, chat_id);
13137   }
13138 }
13139 
on_update_chat_participant_count(Chat * c,ChatId chat_id,int32 participant_count,int32 version,const string & debug_str)13140 void ContactsManager::on_update_chat_participant_count(Chat *c, ChatId chat_id, int32 participant_count, int32 version,
13141                                                        const string &debug_str) {
13142   if (version <= -1) {
13143     LOG(ERROR) << "Receive wrong version " << version << " in " << chat_id << debug_str;
13144     return;
13145   }
13146 
13147   if (version < c->version) {
13148     // some outdated data
13149     LOG(INFO) << "Receive number of members in " << chat_id << " with version " << version << debug_str
13150               << ", but current version is " << c->version;
13151     return;
13152   }
13153 
13154   if (c->participant_count != participant_count) {
13155     if (version == c->version && participant_count != 0) {
13156       // version is not changed when deleted user is removed from the chat
13157       LOG_IF(ERROR, c->participant_count != participant_count + 1)
13158           << "Number of members in " << chat_id << " has changed from " << c->participant_count << " to "
13159           << participant_count << ", but version " << c->version << " remains unchanged" << debug_str;
13160       repair_chat_participants(chat_id);
13161     }
13162 
13163     c->participant_count = participant_count;
13164     c->version = version;
13165     c->is_changed = true;
13166     return;
13167   }
13168 
13169   if (version > c->version) {
13170     c->version = version;
13171     c->need_save_to_database = true;
13172   }
13173 }
13174 
on_update_chat_photo(Chat * c,ChatId chat_id,tl_object_ptr<telegram_api::ChatPhoto> && chat_photo_ptr)13175 void ContactsManager::on_update_chat_photo(Chat *c, ChatId chat_id,
13176                                            tl_object_ptr<telegram_api::ChatPhoto> &&chat_photo_ptr) {
13177   DialogPhoto new_chat_photo =
13178       get_dialog_photo(td_->file_manager_.get(), DialogId(chat_id), 0, std::move(chat_photo_ptr));
13179   if (td_->auth_manager_->is_bot()) {
13180     new_chat_photo.minithumbnail.clear();
13181   }
13182 
13183   if (new_chat_photo != c->photo) {
13184     c->photo = new_chat_photo;
13185     c->is_photo_changed = true;
13186     c->need_save_to_database = true;
13187   }
13188 }
13189 
on_update_chat_title(Chat * c,ChatId chat_id,string && title)13190 void ContactsManager::on_update_chat_title(Chat *c, ChatId chat_id, string &&title) {
13191   if (c->title != title) {
13192     c->title = std::move(title);
13193     c->is_title_changed = true;
13194     c->need_save_to_database = true;
13195   }
13196 }
13197 
on_update_chat_active(Chat * c,ChatId chat_id,bool is_active)13198 void ContactsManager::on_update_chat_active(Chat *c, ChatId chat_id, bool is_active) {
13199   if (c->is_active != is_active) {
13200     c->is_active = is_active;
13201     c->is_is_active_changed = true;
13202     c->is_changed = true;
13203   }
13204 }
13205 
on_update_chat_migrated_to_channel_id(Chat * c,ChatId chat_id,ChannelId migrated_to_channel_id)13206 void ContactsManager::on_update_chat_migrated_to_channel_id(Chat *c, ChatId chat_id, ChannelId migrated_to_channel_id) {
13207   if (c->migrated_to_channel_id != migrated_to_channel_id && migrated_to_channel_id.is_valid()) {
13208     LOG_IF(ERROR, c->migrated_to_channel_id.is_valid())
13209         << "Upgraded supergroup ID for " << chat_id << " has changed from " << c->migrated_to_channel_id << " to "
13210         << migrated_to_channel_id;
13211     c->migrated_to_channel_id = migrated_to_channel_id;
13212     c->is_changed = true;
13213   }
13214 }
13215 
on_update_chat_description(ChatId chat_id,string && description)13216 void ContactsManager::on_update_chat_description(ChatId chat_id, string &&description) {
13217   if (!chat_id.is_valid()) {
13218     LOG(ERROR) << "Receive invalid " << chat_id;
13219     return;
13220   }
13221 
13222   auto chat_full = get_chat_full_force(chat_id, "on_update_chat_description");
13223   if (chat_full == nullptr) {
13224     return;
13225   }
13226   if (chat_full->description != description) {
13227     chat_full->description = std::move(description);
13228     chat_full->is_changed = true;
13229     update_chat_full(chat_full, chat_id, "on_update_chat_description");
13230     td_->group_call_manager_->on_update_dialog_about(DialogId(chat_id), chat_full->description, true);
13231   }
13232 }
13233 
on_update_chat_full_participants_short(ChatFull * chat_full,ChatId chat_id,int32 version)13234 bool ContactsManager::on_update_chat_full_participants_short(ChatFull *chat_full, ChatId chat_id, int32 version) {
13235   if (version <= -1) {
13236     LOG(ERROR) << "Receive wrong version " << version << " for " << chat_id;
13237     return false;
13238   }
13239   if (chat_full->version == -1) {
13240     // chat members are unknown, nothing to update
13241     return false;
13242   }
13243 
13244   if (chat_full->version + 1 == version) {
13245     chat_full->version = version;
13246     return true;
13247   }
13248 
13249   LOG(INFO) << "Number of members in " << chat_id << " with version " << chat_full->version
13250             << " has changed, but new version is " << version;
13251   repair_chat_participants(chat_id);
13252   return false;
13253 }
13254 
on_update_chat_full_participants(ChatFull * chat_full,ChatId chat_id,vector<DialogParticipant> participants,int32 version,bool from_update)13255 void ContactsManager::on_update_chat_full_participants(ChatFull *chat_full, ChatId chat_id,
13256                                                        vector<DialogParticipant> participants, int32 version,
13257                                                        bool from_update) {
13258   if (version <= -1) {
13259     LOG(ERROR) << "Receive members with wrong version " << version << " in " << chat_id;
13260     return;
13261   }
13262 
13263   if (version < chat_full->version) {
13264     // some outdated data
13265     LOG(WARNING) << "Receive members of " << chat_id << " with version " << version << " but current version is "
13266                  << chat_full->version;
13267     return;
13268   }
13269 
13270   if ((chat_full->participants.size() != participants.size() && version == chat_full->version) ||
13271       (from_update && version != chat_full->version + 1)) {
13272     LOG(INFO) << "Members of " << chat_id << " has changed";
13273     // this is possible in very rare situations
13274     repair_chat_participants(chat_id);
13275   }
13276 
13277   chat_full->participants = std::move(participants);
13278   chat_full->version = version;
13279   chat_full->is_changed = true;
13280   update_chat_online_member_count(chat_full, chat_id, true);
13281 }
13282 
drop_chat_photos(ChatId chat_id,bool is_empty,bool drop_chat_full_photo,const char * source)13283 void ContactsManager::drop_chat_photos(ChatId chat_id, bool is_empty, bool drop_chat_full_photo, const char *source) {
13284   if (drop_chat_full_photo) {
13285     auto chat_full = get_chat_full(chat_id);  // must not load ChatFull
13286     if (chat_full == nullptr) {
13287       return;
13288     }
13289 
13290     on_update_chat_full_photo(chat_full, chat_id, Photo());
13291     if (!is_empty) {
13292       reload_chat_full(chat_id, Auto());
13293     }
13294     update_chat_full(chat_full, chat_id, "drop_chat_photos");
13295   }
13296 }
13297 
drop_chat_full(ChatId chat_id)13298 void ContactsManager::drop_chat_full(ChatId chat_id) {
13299   ChatFull *chat_full = get_chat_full_force(chat_id, "drop_chat_full");
13300   if (chat_full == nullptr) {
13301     drop_chat_photos(chat_id, false, false, "drop_chat_full");
13302     return;
13303   }
13304 
13305   LOG(INFO) << "Drop basicGroupFullInfo of " << chat_id;
13306   on_update_chat_full_photo(chat_full, chat_id, Photo());
13307   // chat_full->creator_user_id = UserId();
13308   chat_full->participants.clear();
13309   chat_full->bot_commands.clear();
13310   chat_full->version = -1;
13311   on_update_chat_full_invite_link(chat_full, nullptr);
13312   update_chat_online_member_count(chat_full, chat_id, true);
13313   chat_full->is_changed = true;
13314   update_chat_full(chat_full, chat_id, "drop_chat_full");
13315 }
13316 
on_update_channel_photo(Channel * c,ChannelId channel_id,tl_object_ptr<telegram_api::ChatPhoto> && chat_photo_ptr)13317 void ContactsManager::on_update_channel_photo(Channel *c, ChannelId channel_id,
13318                                               tl_object_ptr<telegram_api::ChatPhoto> &&chat_photo_ptr) {
13319   DialogPhoto new_chat_photo =
13320       get_dialog_photo(td_->file_manager_.get(), DialogId(channel_id), c->access_hash, std::move(chat_photo_ptr));
13321   if (td_->auth_manager_->is_bot()) {
13322     new_chat_photo.minithumbnail.clear();
13323   }
13324 
13325   if (new_chat_photo != c->photo) {
13326     c->photo = new_chat_photo;
13327     c->is_photo_changed = true;
13328     c->need_save_to_database = true;
13329   }
13330 }
13331 
on_update_channel_title(Channel * c,ChannelId channel_id,string && title)13332 void ContactsManager::on_update_channel_title(Channel *c, ChannelId channel_id, string &&title) {
13333   if (c->title != title) {
13334     c->title = std::move(title);
13335     c->is_title_changed = true;
13336     c->need_save_to_database = true;
13337   }
13338 }
13339 
on_update_channel_status(Channel * c,ChannelId channel_id,DialogParticipantStatus && status)13340 void ContactsManager::on_update_channel_status(Channel *c, ChannelId channel_id, DialogParticipantStatus &&status) {
13341   if (c->status != status) {
13342     LOG(INFO) << "Update " << channel_id << " status from " << c->status << " to " << status;
13343     if (c->is_update_supergroup_sent) {
13344       on_channel_status_changed(c, channel_id, c->status, status);
13345     }
13346     c->status = status;
13347     c->is_status_changed = true;
13348     c->is_changed = true;
13349   }
13350 }
13351 
on_channel_status_changed(Channel * c,ChannelId channel_id,const DialogParticipantStatus & old_status,const DialogParticipantStatus & new_status)13352 void ContactsManager::on_channel_status_changed(Channel *c, ChannelId channel_id,
13353                                                 const DialogParticipantStatus &old_status,
13354                                                 const DialogParticipantStatus &new_status) {
13355   CHECK(c->is_update_supergroup_sent);
13356   bool have_channel_full = get_channel_full(channel_id) != nullptr;
13357 
13358   bool need_reload_group_call = old_status.can_manage_calls() != new_status.can_manage_calls();
13359   if (old_status.can_manage_invite_links() && !new_status.can_manage_invite_links()) {
13360     auto channel_full = get_channel_full(channel_id, true, "on_channel_status_changed");
13361     if (channel_full != nullptr) {  // otherwise invite_link will be dropped when the channel is loaded
13362       on_update_channel_full_invite_link(channel_full, nullptr);
13363       do_invalidate_channel_full(channel_full, channel_id, !c->is_slow_mode_enabled);
13364       update_channel_full(channel_full, channel_id, "on_channel_status_changed");
13365     }
13366   } else {
13367     invalidate_channel_full(channel_id, !c->is_slow_mode_enabled);
13368   }
13369 
13370   if (old_status.is_creator() != new_status.is_creator()) {
13371     c->is_creator_changed = true;
13372 
13373     send_get_channel_full_query(nullptr, channel_id, Auto(), "update channel owner");
13374     reload_dialog_administrators(DialogId(channel_id), 0, Auto());
13375     remove_dialog_suggested_action(SuggestedAction{SuggestedAction::Type::ConvertToGigagroup, DialogId(channel_id)});
13376   }
13377 
13378   if (old_status.is_member() != new_status.is_member() || new_status.is_banned()) {
13379     remove_dialog_access_by_invite_link(DialogId(channel_id));
13380 
13381     if (new_status.is_member()) {
13382       reload_channel_full(channel_id, Promise<Unit>(), "on_channel_status_changed");
13383     }
13384   }
13385   if (need_reload_group_call) {
13386     send_closure_later(G()->messages_manager(), &MessagesManager::on_update_dialog_group_call_rights,
13387                        DialogId(channel_id));
13388   }
13389   if (td_->auth_manager_->is_bot() && old_status.is_administrator() && !new_status.is_administrator()) {
13390     channel_participants_.erase(channel_id);
13391   }
13392   if (td_->auth_manager_->is_bot() && old_status.is_member() && !new_status.is_member() &&
13393       !G()->parameters().use_message_db) {
13394     send_closure_later(G()->messages_manager(), &MessagesManager::on_dialog_deleted, DialogId(channel_id),
13395                        Promise<Unit>());
13396   }
13397 
13398   // must not load ChannelFull, because must not change the Channel
13399   CHECK(have_channel_full == (get_channel_full(channel_id) != nullptr));
13400 }
13401 
on_update_channel_default_permissions(Channel * c,ChannelId channel_id,RestrictedRights default_permissions)13402 void ContactsManager::on_update_channel_default_permissions(Channel *c, ChannelId channel_id,
13403                                                             RestrictedRights default_permissions) {
13404   if (c->default_permissions != default_permissions) {
13405     LOG(INFO) << "Update " << channel_id << " default permissions from " << c->default_permissions << " to "
13406               << default_permissions;
13407     c->default_permissions = default_permissions;
13408     c->is_default_permissions_changed = true;
13409     c->need_save_to_database = true;
13410   }
13411 }
13412 
on_update_channel_has_location(Channel * c,ChannelId channel_id,bool has_location)13413 void ContactsManager::on_update_channel_has_location(Channel *c, ChannelId channel_id, bool has_location) {
13414   if (c->has_location != has_location) {
13415     LOG(INFO) << "Update " << channel_id << " has_location from " << c->has_location << " to " << has_location;
13416     c->has_location = has_location;
13417     c->is_has_location_changed = true;
13418     c->is_changed = true;
13419   }
13420 }
13421 
on_update_channel_noforwards(Channel * c,ChannelId channel_id,bool noforwards)13422 void ContactsManager::on_update_channel_noforwards(Channel *c, ChannelId channel_id, bool noforwards) {
13423   if (c->noforwards != noforwards) {
13424     LOG(INFO) << "Update " << channel_id << " has_protected_content from " << c->noforwards << " to " << noforwards;
13425     c->noforwards = noforwards;
13426     c->is_noforwards_changed = true;
13427     c->need_save_to_database = true;
13428   }
13429 }
13430 
on_update_channel_username(ChannelId channel_id,string && username)13431 void ContactsManager::on_update_channel_username(ChannelId channel_id, string &&username) {
13432   if (!channel_id.is_valid()) {
13433     LOG(ERROR) << "Receive invalid " << channel_id;
13434     return;
13435   }
13436 
13437   Channel *c = get_channel_force(channel_id);
13438   if (c != nullptr) {
13439     on_update_channel_username(c, channel_id, std::move(username));
13440     update_channel(c, channel_id);
13441   } else {
13442     LOG(INFO) << "Ignore update channel username about unknown " << channel_id;
13443   }
13444 }
13445 
on_update_channel_username(Channel * c,ChannelId channel_id,string && username)13446 void ContactsManager::on_update_channel_username(Channel *c, ChannelId channel_id, string &&username) {
13447   td_->messages_manager_->on_dialog_username_updated(DialogId(channel_id), c->username, username);
13448   if (c->username != username) {
13449     if (c->is_update_supergroup_sent) {
13450       on_channel_username_changed(c, channel_id, c->username, username);
13451     }
13452 
13453     c->username = std::move(username);
13454     c->is_username_changed = true;
13455     c->is_changed = true;
13456   }
13457 }
13458 
on_channel_username_changed(const Channel * c,ChannelId channel_id,const string & old_username,const string & new_username)13459 void ContactsManager::on_channel_username_changed(const Channel *c, ChannelId channel_id, const string &old_username,
13460                                                   const string &new_username) {
13461   bool have_channel_full = get_channel_full(channel_id) != nullptr;
13462   if (old_username.empty() || new_username.empty()) {
13463     // moving channel from private to public can change availability of chat members
13464     invalidate_channel_full(channel_id, !c->is_slow_mode_enabled);
13465   }
13466 
13467   // must not load ChannelFull, because must not change the Channel
13468   CHECK(have_channel_full == (get_channel_full(channel_id) != nullptr));
13469 }
13470 
on_update_channel_description(ChannelId channel_id,string && description)13471 void ContactsManager::on_update_channel_description(ChannelId channel_id, string &&description) {
13472   CHECK(channel_id.is_valid());
13473   auto channel_full = get_channel_full_force(channel_id, true, "on_update_channel_description");
13474   if (channel_full == nullptr) {
13475     return;
13476   }
13477   if (channel_full->description != description) {
13478     channel_full->description = std::move(description);
13479     channel_full->is_changed = true;
13480     update_channel_full(channel_full, channel_id, "on_update_channel_description");
13481     td_->group_call_manager_->on_update_dialog_about(DialogId(channel_id), channel_full->description, true);
13482   }
13483 }
13484 
on_update_channel_sticker_set(ChannelId channel_id,StickerSetId sticker_set_id)13485 void ContactsManager::on_update_channel_sticker_set(ChannelId channel_id, StickerSetId sticker_set_id) {
13486   CHECK(channel_id.is_valid());
13487   auto channel_full = get_channel_full_force(channel_id, true, "on_update_channel_sticker_set");
13488   if (channel_full == nullptr) {
13489     return;
13490   }
13491   if (channel_full->sticker_set_id != sticker_set_id) {
13492     channel_full->sticker_set_id = sticker_set_id;
13493     channel_full->is_changed = true;
13494     update_channel_full(channel_full, channel_id, "on_update_channel_sticker_set");
13495   }
13496 }
13497 
on_update_channel_linked_channel_id(ChannelId channel_id,ChannelId group_channel_id)13498 void ContactsManager::on_update_channel_linked_channel_id(ChannelId channel_id, ChannelId group_channel_id) {
13499   if (channel_id.is_valid()) {
13500     auto channel_full = get_channel_full_force(channel_id, true, "on_update_channel_linked_channel_id 1");
13501     on_update_channel_full_linked_channel_id(channel_full, channel_id, group_channel_id);
13502     if (channel_full != nullptr) {
13503       update_channel_full(channel_full, channel_id, "on_update_channel_linked_channel_id 3");
13504     }
13505   }
13506   if (group_channel_id.is_valid()) {
13507     auto channel_full = get_channel_full_force(group_channel_id, true, "on_update_channel_linked_channel_id 2");
13508     on_update_channel_full_linked_channel_id(channel_full, group_channel_id, channel_id);
13509     if (channel_full != nullptr) {
13510       update_channel_full(channel_full, group_channel_id, "on_update_channel_linked_channel_id 4");
13511     }
13512   }
13513 }
13514 
on_update_channel_location(ChannelId channel_id,const DialogLocation & location)13515 void ContactsManager::on_update_channel_location(ChannelId channel_id, const DialogLocation &location) {
13516   auto channel_full = get_channel_full_force(channel_id, true, "on_update_channel_location");
13517   if (channel_full != nullptr) {
13518     on_update_channel_full_location(channel_full, channel_id, location);
13519     update_channel_full(channel_full, channel_id, "on_update_channel_location");
13520   }
13521 }
13522 
on_update_channel_slow_mode_delay(ChannelId channel_id,int32 slow_mode_delay,Promise<Unit> && promise)13523 void ContactsManager::on_update_channel_slow_mode_delay(ChannelId channel_id, int32 slow_mode_delay,
13524                                                         Promise<Unit> &&promise) {
13525   TRY_STATUS_PROMISE(promise, G()->close_status());
13526 
13527   auto channel_full = get_channel_full_force(channel_id, true, "on_update_channel_slow_mode_delay");
13528   if (channel_full != nullptr) {
13529     on_update_channel_full_slow_mode_delay(channel_full, channel_id, slow_mode_delay, 0);
13530     update_channel_full(channel_full, channel_id, "on_update_channel_slow_mode_delay");
13531   }
13532   promise.set_value(Unit());
13533 }
13534 
on_update_channel_slow_mode_next_send_date(ChannelId channel_id,int32 slow_mode_next_send_date)13535 void ContactsManager::on_update_channel_slow_mode_next_send_date(ChannelId channel_id, int32 slow_mode_next_send_date) {
13536   auto channel_full = get_channel_full_force(channel_id, true, "on_update_channel_slow_mode_next_send_date");
13537   if (channel_full != nullptr) {
13538     on_update_channel_full_slow_mode_next_send_date(channel_full, slow_mode_next_send_date);
13539     update_channel_full(channel_full, channel_id, "on_update_channel_slow_mode_next_send_date");
13540   }
13541 }
13542 
on_update_channel_bot_user_ids(ChannelId channel_id,vector<UserId> && bot_user_ids)13543 void ContactsManager::on_update_channel_bot_user_ids(ChannelId channel_id, vector<UserId> &&bot_user_ids) {
13544   CHECK(channel_id.is_valid());
13545   if (!have_channel(channel_id)) {
13546     LOG(ERROR) << channel_id << " not found";
13547     return;
13548   }
13549 
13550   auto channel_full = get_channel_full_force(channel_id, true, "on_update_channel_bot_user_ids");
13551   if (channel_full == nullptr) {
13552     send_closure_later(G()->messages_manager(), &MessagesManager::on_dialog_bots_updated, DialogId(channel_id),
13553                        std::move(bot_user_ids), false);
13554     return;
13555   }
13556   on_update_channel_full_bot_user_ids(channel_full, channel_id, std::move(bot_user_ids));
13557   update_channel_full(channel_full, channel_id, "on_update_channel_bot_user_ids");
13558 }
13559 
on_update_channel_full_bot_user_ids(ChannelFull * channel_full,ChannelId channel_id,vector<UserId> && bot_user_ids)13560 void ContactsManager::on_update_channel_full_bot_user_ids(ChannelFull *channel_full, ChannelId channel_id,
13561                                                           vector<UserId> &&bot_user_ids) {
13562   CHECK(channel_full != nullptr);
13563   if (channel_full->bot_user_ids != bot_user_ids) {
13564     send_closure_later(G()->messages_manager(), &MessagesManager::on_dialog_bots_updated, DialogId(channel_id),
13565                        bot_user_ids, false);
13566     channel_full->bot_user_ids = std::move(bot_user_ids);
13567     channel_full->need_save_to_database = true;
13568   }
13569 }
13570 
on_update_channel_is_all_history_available(ChannelId channel_id,bool is_all_history_available,Promise<Unit> && promise)13571 void ContactsManager::on_update_channel_is_all_history_available(ChannelId channel_id, bool is_all_history_available,
13572                                                                  Promise<Unit> &&promise) {
13573   TRY_STATUS_PROMISE(promise, G()->close_status());
13574   CHECK(channel_id.is_valid());
13575   auto channel_full = get_channel_full_force(channel_id, true, "on_update_channel_is_all_history_available");
13576   if (channel_full != nullptr && channel_full->is_all_history_available != is_all_history_available) {
13577     channel_full->is_all_history_available = is_all_history_available;
13578     channel_full->is_changed = true;
13579     update_channel_full(channel_full, channel_id, "on_update_channel_is_all_history_available");
13580   }
13581   promise.set_value(Unit());
13582 }
13583 
on_update_channel_default_permissions(ChannelId channel_id,RestrictedRights default_permissions)13584 void ContactsManager::on_update_channel_default_permissions(ChannelId channel_id,
13585                                                             RestrictedRights default_permissions) {
13586   if (!channel_id.is_valid()) {
13587     LOG(ERROR) << "Receive invalid " << channel_id;
13588     return;
13589   }
13590 
13591   Channel *c = get_channel_force(channel_id);
13592   if (c != nullptr) {
13593     on_update_channel_default_permissions(c, channel_id, std::move(default_permissions));
13594     update_channel(c, channel_id);
13595   } else {
13596     LOG(INFO) << "Ignore update channel default permissions about unknown " << channel_id;
13597   }
13598 }
13599 
send_update_chat_member(DialogId dialog_id,UserId agent_user_id,int32 date,const DialogInviteLink & invite_link,const DialogParticipant & old_dialog_participant,const DialogParticipant & new_dialog_participant)13600 void ContactsManager::send_update_chat_member(DialogId dialog_id, UserId agent_user_id, int32 date,
13601                                               const DialogInviteLink &invite_link,
13602                                               const DialogParticipant &old_dialog_participant,
13603                                               const DialogParticipant &new_dialog_participant) {
13604   CHECK(td_->auth_manager_->is_bot());
13605   td_->messages_manager_->force_create_dialog(dialog_id, "send_update_chat_member", true);
13606   send_closure(G()->td(), &Td::send_update,
13607                td_api::make_object<td_api::updateChatMember>(
13608                    dialog_id.get(), get_user_id_object(agent_user_id, "send_update_chat_member"), date,
13609                    invite_link.get_chat_invite_link_object(this), get_chat_member_object(old_dialog_participant),
13610                    get_chat_member_object(new_dialog_participant)));
13611 }
13612 
on_update_bot_stopped(UserId user_id,int32 date,bool is_stopped)13613 void ContactsManager::on_update_bot_stopped(UserId user_id, int32 date, bool is_stopped) {
13614   if (!td_->auth_manager_->is_bot()) {
13615     LOG(ERROR) << "Receive updateBotStopped by non-bot";
13616     return;
13617   }
13618   if (date <= 0 || !have_user_force(user_id)) {
13619     LOG(ERROR) << "Receive invalid updateBotStopped by " << user_id << " at " << date;
13620     return;
13621   }
13622 
13623   DialogParticipant old_dialog_participant(DialogId(get_my_id()), user_id, date, DialogParticipantStatus::Banned(0));
13624   DialogParticipant new_dialog_participant(DialogId(get_my_id()), user_id, date, DialogParticipantStatus::Member());
13625   if (is_stopped) {
13626     std::swap(old_dialog_participant.status_, new_dialog_participant.status_);
13627   }
13628 
13629   send_update_chat_member(DialogId(user_id), user_id, date, DialogInviteLink(), old_dialog_participant,
13630                           new_dialog_participant);
13631 }
13632 
on_update_chat_participant(ChatId chat_id,UserId user_id,int32 date,DialogInviteLink invite_link,tl_object_ptr<telegram_api::ChatParticipant> old_participant,tl_object_ptr<telegram_api::ChatParticipant> new_participant)13633 void ContactsManager::on_update_chat_participant(ChatId chat_id, UserId user_id, int32 date,
13634                                                  DialogInviteLink invite_link,
13635                                                  tl_object_ptr<telegram_api::ChatParticipant> old_participant,
13636                                                  tl_object_ptr<telegram_api::ChatParticipant> new_participant) {
13637   if (!td_->auth_manager_->is_bot()) {
13638     LOG(ERROR) << "Receive updateChatParticipant by non-bot";
13639     return;
13640   }
13641   if (!chat_id.is_valid() || !user_id.is_valid() || date <= 0 ||
13642       (old_participant == nullptr && new_participant == nullptr)) {
13643     LOG(ERROR) << "Receive invalid updateChatParticipant in " << chat_id << " by " << user_id << " at " << date << ": "
13644                << to_string(old_participant) << " -> " << to_string(new_participant);
13645     return;
13646   }
13647 
13648   const Chat *c = get_chat(chat_id);
13649   if (c == nullptr) {
13650     LOG(ERROR) << "Receive updateChatParticipant in unknown " << chat_id;
13651     return;
13652   }
13653 
13654   DialogParticipant old_dialog_participant;
13655   DialogParticipant new_dialog_participant;
13656   if (old_participant != nullptr) {
13657     old_dialog_participant = DialogParticipant(std::move(old_participant), c->date, c->status.is_creator());
13658     if (new_participant == nullptr) {
13659       new_dialog_participant = DialogParticipant::left(old_dialog_participant.dialog_id_);
13660     } else {
13661       new_dialog_participant = DialogParticipant(std::move(new_participant), c->date, c->status.is_creator());
13662     }
13663   } else {
13664     new_dialog_participant = DialogParticipant(std::move(new_participant), c->date, c->status.is_creator());
13665     old_dialog_participant = DialogParticipant::left(new_dialog_participant.dialog_id_);
13666   }
13667   if (old_dialog_participant.dialog_id_ != new_dialog_participant.dialog_id_ || !old_dialog_participant.is_valid() ||
13668       !new_dialog_participant.is_valid()) {
13669     LOG(ERROR) << "Receive wrong updateChatParticipant: " << old_dialog_participant << " -> " << new_dialog_participant;
13670     return;
13671   }
13672   if (new_dialog_participant.dialog_id_ == DialogId(get_my_id()) &&
13673       new_dialog_participant.status_ != get_chat_status(chat_id) && false) {
13674     LOG(ERROR) << "Have status " << get_chat_status(chat_id) << " after receiving updateChatParticipant in " << chat_id
13675                << " by " << user_id << " at " << date << " from " << old_dialog_participant << " to "
13676                << new_dialog_participant;
13677   }
13678 
13679   send_update_chat_member(DialogId(chat_id), user_id, date, invite_link, old_dialog_participant,
13680                           new_dialog_participant);
13681 }
13682 
on_update_channel_participant(ChannelId channel_id,UserId user_id,int32 date,DialogInviteLink invite_link,tl_object_ptr<telegram_api::ChannelParticipant> old_participant,tl_object_ptr<telegram_api::ChannelParticipant> new_participant)13683 void ContactsManager::on_update_channel_participant(ChannelId channel_id, UserId user_id, int32 date,
13684                                                     DialogInviteLink invite_link,
13685                                                     tl_object_ptr<telegram_api::ChannelParticipant> old_participant,
13686                                                     tl_object_ptr<telegram_api::ChannelParticipant> new_participant) {
13687   if (!td_->auth_manager_->is_bot()) {
13688     LOG(ERROR) << "Receive updateChannelParticipant by non-bot";
13689     return;
13690   }
13691   if (!channel_id.is_valid() || !user_id.is_valid() || date <= 0 ||
13692       (old_participant == nullptr && new_participant == nullptr)) {
13693     LOG(ERROR) << "Receive invalid updateChannelParticipant in " << channel_id << " by " << user_id << " at " << date
13694                << ": " << to_string(old_participant) << " -> " << to_string(new_participant);
13695     return;
13696   }
13697 
13698   DialogParticipant old_dialog_participant;
13699   DialogParticipant new_dialog_participant;
13700   if (old_participant != nullptr) {
13701     old_dialog_participant = DialogParticipant(std::move(old_participant));
13702     if (new_participant == nullptr) {
13703       new_dialog_participant = DialogParticipant::left(old_dialog_participant.dialog_id_);
13704     } else {
13705       new_dialog_participant = DialogParticipant(std::move(new_participant));
13706     }
13707   } else {
13708     new_dialog_participant = DialogParticipant(std::move(new_participant));
13709     old_dialog_participant = DialogParticipant::left(new_dialog_participant.dialog_id_);
13710   }
13711   if (old_dialog_participant.dialog_id_ != new_dialog_participant.dialog_id_ || !old_dialog_participant.is_valid() ||
13712       !new_dialog_participant.is_valid()) {
13713     LOG(ERROR) << "Receive wrong updateChannelParticipant: " << old_dialog_participant << " -> "
13714                << new_dialog_participant;
13715     return;
13716   }
13717 
13718   if (old_dialog_participant.dialog_id_ == DialogId(get_my_id()) && old_dialog_participant.status_.is_administrator() &&
13719       !new_dialog_participant.status_.is_administrator()) {
13720     channel_participants_.erase(channel_id);
13721   } else if (have_channel_participant_cache(channel_id)) {
13722     add_channel_participant_to_cache(channel_id, new_dialog_participant, true);
13723   }
13724   if (new_dialog_participant.dialog_id_ == DialogId(get_my_id()) &&
13725       new_dialog_participant.status_ != get_channel_status(channel_id) && false) {
13726     LOG(ERROR) << "Have status " << get_channel_status(channel_id) << " after receiving updateChannelParticipant in "
13727                << channel_id << " by " << user_id << " at " << date << " from " << old_dialog_participant << " to "
13728                << new_dialog_participant;
13729   }
13730 
13731   send_update_chat_member(DialogId(channel_id), user_id, date, invite_link, old_dialog_participant,
13732                           new_dialog_participant);
13733 }
13734 
on_update_chat_invite_requester(DialogId dialog_id,UserId user_id,string about,int32 date,DialogInviteLink invite_link)13735 void ContactsManager::on_update_chat_invite_requester(DialogId dialog_id, UserId user_id, string about, int32 date,
13736                                                       DialogInviteLink invite_link) {
13737   if (!td_->auth_manager_->is_bot() || date <= 0 || !have_user_force(user_id) ||
13738       !td_->messages_manager_->have_dialog_info_force(dialog_id)) {
13739     LOG(ERROR) << "Receive invalid updateBotChatInviteRequester by " << user_id << " in " << dialog_id << " at "
13740                << date;
13741     return;
13742   }
13743   td_->messages_manager_->force_create_dialog(dialog_id, "on_update_chat_invite_requester", true);
13744 
13745   send_closure(G()->td(), &Td::send_update,
13746                td_api::make_object<td_api::updateNewChatJoinRequest>(
13747                    dialog_id.get(),
13748                    td_api::make_object<td_api::chatJoinRequest>(
13749                        get_user_id_object(user_id, "on_update_chat_invite_requester"), date, about),
13750                    invite_link.get_chat_invite_link_object(this)));
13751 }
13752 
update_contacts_hints(const User * u,UserId user_id,bool from_database)13753 void ContactsManager::update_contacts_hints(const User *u, UserId user_id, bool from_database) {
13754   bool is_contact = is_user_contact(u, user_id, false);
13755   if (td_->auth_manager_->is_bot()) {
13756     LOG_IF(ERROR, is_contact) << "Bot has " << user_id << " in the contacts list";
13757     return;
13758   }
13759 
13760   int64 key = user_id.get();
13761   string old_value = contacts_hints_.key_to_string(key);
13762   string new_value = is_contact ? u->first_name + " " + u->last_name + " " + u->username : "";
13763 
13764   if (new_value != old_value) {
13765     if (is_contact) {
13766       contacts_hints_.add(key, new_value);
13767     } else {
13768       contacts_hints_.remove(key);
13769     }
13770   }
13771 
13772   if (G()->parameters().use_chat_info_db) {
13773     // update contacts database
13774     if (!are_contacts_loaded_) {
13775       if (!from_database && load_contacts_queries_.empty()) {
13776         search_contacts("", std::numeric_limits<int32>::max(), Auto());
13777       }
13778     } else {
13779       if (old_value.empty() == is_contact) {
13780         save_contacts_to_database();
13781       }
13782     }
13783   }
13784 }
13785 
have_user(UserId user_id) const13786 bool ContactsManager::have_user(UserId user_id) const {
13787   auto u = get_user(user_id);
13788   return u != nullptr && u->is_received;
13789 }
13790 
have_min_user(UserId user_id) const13791 bool ContactsManager::have_min_user(UserId user_id) const {
13792   return users_.count(user_id) > 0;
13793 }
13794 
is_user_deleted(UserId user_id) const13795 bool ContactsManager::is_user_deleted(UserId user_id) const {
13796   auto u = get_user(user_id);
13797   return u == nullptr || u->is_deleted;
13798 }
13799 
is_user_support(UserId user_id) const13800 bool ContactsManager::is_user_support(UserId user_id) const {
13801   auto u = get_user(user_id);
13802   return u != nullptr && !u->is_deleted && u->is_support;
13803 }
13804 
is_user_bot(UserId user_id) const13805 bool ContactsManager::is_user_bot(UserId user_id) const {
13806   auto u = get_user(user_id);
13807   return u != nullptr && !u->is_deleted && u->is_bot;
13808 }
13809 
get_bot_data(UserId user_id) const13810 Result<ContactsManager::BotData> ContactsManager::get_bot_data(UserId user_id) const {
13811   auto p = users_.find(user_id);
13812   if (p == users_.end()) {
13813     return Status::Error(400, "Bot not found");
13814   }
13815 
13816   auto bot = p->second.get();
13817   if (!bot->is_bot) {
13818     return Status::Error(400, "User is not a bot");
13819   }
13820   if (bot->is_deleted) {
13821     return Status::Error(400, "Bot is deleted");
13822   }
13823   if (!bot->is_received) {
13824     return Status::Error(400, "Bot is inaccessible");
13825   }
13826 
13827   BotData bot_data;
13828   bot_data.username = bot->username;
13829   bot_data.can_join_groups = bot->can_join_groups;
13830   bot_data.can_read_all_group_messages = bot->can_read_all_group_messages;
13831   bot_data.is_inline = bot->is_inline_bot;
13832   bot_data.need_location = bot->need_location_bot;
13833   return bot_data;
13834 }
13835 
is_user_online(UserId user_id,int32 tolerance) const13836 bool ContactsManager::is_user_online(UserId user_id, int32 tolerance) const {
13837   int32 was_online = get_user_was_online(get_user(user_id), user_id);
13838   return was_online > G()->unix_time() - tolerance;
13839 }
13840 
is_user_status_exact(UserId user_id) const13841 bool ContactsManager::is_user_status_exact(UserId user_id) const {
13842   auto u = get_user(user_id);
13843   return u != nullptr && !u->is_deleted && !u->is_bot && u->was_online > 0;
13844 }
13845 
can_report_user(UserId user_id) const13846 bool ContactsManager::can_report_user(UserId user_id) const {
13847   auto u = get_user(user_id);
13848   return u != nullptr && !u->is_deleted && !u->is_support && (u->is_bot || all_users_nearby_.count(user_id) != 0);
13849 }
13850 
get_user(UserId user_id) const13851 const ContactsManager::User *ContactsManager::get_user(UserId user_id) const {
13852   auto p = users_.find(user_id);
13853   if (p == users_.end()) {
13854     return nullptr;
13855   } else {
13856     return p->second.get();
13857   }
13858 }
13859 
get_user(UserId user_id)13860 ContactsManager::User *ContactsManager::get_user(UserId user_id) {
13861   auto p = users_.find(user_id);
13862   if (p == users_.end()) {
13863     return nullptr;
13864   } else {
13865     return p->second.get();
13866   }
13867 }
13868 
is_dialog_info_received_from_server(DialogId dialog_id) const13869 bool ContactsManager::is_dialog_info_received_from_server(DialogId dialog_id) const {
13870   switch (dialog_id.get_type()) {
13871     case DialogType::User: {
13872       auto u = get_user(dialog_id.get_user_id());
13873       return u != nullptr && u->is_received_from_server;
13874     }
13875     case DialogType::Chat: {
13876       auto c = get_chat(dialog_id.get_chat_id());
13877       return c != nullptr && c->is_received_from_server;
13878     }
13879     case DialogType::Channel: {
13880       auto c = get_channel(dialog_id.get_channel_id());
13881       return c != nullptr && c->is_received_from_server;
13882     }
13883     default:
13884       return false;
13885   }
13886 }
13887 
reload_dialog_info(DialogId dialog_id,Promise<Unit> && promise)13888 void ContactsManager::reload_dialog_info(DialogId dialog_id, Promise<Unit> &&promise) {
13889   switch (dialog_id.get_type()) {
13890     case DialogType::User:
13891       return reload_user(dialog_id.get_user_id(), std::move(promise));
13892     case DialogType::Chat:
13893       return reload_chat(dialog_id.get_chat_id(), std::move(promise));
13894     case DialogType::Channel:
13895       return reload_channel(dialog_id.get_channel_id(), std::move(promise));
13896     default:
13897       return promise.set_error(Status::Error("Invalid dialog ID to reload"));
13898   }
13899 }
13900 
send_get_me_query(Td * td,Promise<Unit> && promise)13901 void ContactsManager::send_get_me_query(Td *td, Promise<Unit> &&promise) {
13902   vector<tl_object_ptr<telegram_api::InputUser>> users;
13903   users.push_back(make_tl_object<telegram_api::inputUserSelf>());
13904   td->create_handler<GetUsersQuery>(std::move(promise))->send(std::move(users));
13905 }
13906 
get_me(Promise<Unit> && promise)13907 UserId ContactsManager::get_me(Promise<Unit> &&promise) {
13908   auto my_id = get_my_id();
13909   if (!have_user_force(my_id)) {
13910     send_get_me_query(td_, std::move(promise));
13911     return UserId();
13912   }
13913 
13914   promise.set_value(Unit());
13915   return my_id;
13916 }
13917 
get_user(UserId user_id,int left_tries,Promise<Unit> && promise)13918 bool ContactsManager::get_user(UserId user_id, int left_tries, Promise<Unit> &&promise) {
13919   if (!user_id.is_valid()) {
13920     promise.set_error(Status::Error(400, "Invalid user identifier"));
13921     return false;
13922   }
13923 
13924   if (user_id == get_service_notifications_user_id() || user_id == get_replies_bot_user_id() ||
13925       user_id == get_anonymous_bot_user_id()) {
13926     get_user_force(user_id);
13927   }
13928 
13929   // TODO support loading user from database and merging it with min-user in memory
13930   if (!have_min_user(user_id)) {
13931     // TODO UserLoader
13932     if (left_tries > 2 && G()->parameters().use_chat_info_db) {
13933       send_closure_later(actor_id(this), &ContactsManager::load_user_from_database, nullptr, user_id,
13934                          std::move(promise));
13935       return false;
13936     }
13937     auto input_user = get_input_user(user_id);
13938     if (left_tries == 1 || input_user == nullptr) {
13939       promise.set_error(Status::Error(400, "User not found"));
13940       return false;
13941     }
13942 
13943     vector<tl_object_ptr<telegram_api::InputUser>> users;
13944     users.push_back(std::move(input_user));
13945     td_->create_handler<GetUsersQuery>(std::move(promise))->send(std::move(users));
13946     return false;
13947   }
13948 
13949   promise.set_value(Unit());
13950   return true;
13951 }
13952 
add_user(UserId user_id,const char * source)13953 ContactsManager::User *ContactsManager::add_user(UserId user_id, const char *source) {
13954   CHECK(user_id.is_valid());
13955   auto &user_ptr = users_[user_id];
13956   if (user_ptr == nullptr) {
13957     user_ptr = make_unique<User>();
13958   }
13959   return user_ptr.get();
13960 }
13961 
get_user_full(UserId user_id) const13962 const ContactsManager::UserFull *ContactsManager::get_user_full(UserId user_id) const {
13963   auto p = users_full_.find(user_id);
13964   if (p == users_full_.end()) {
13965     return nullptr;
13966   } else {
13967     return p->second.get();
13968   }
13969 }
13970 
get_user_full(UserId user_id)13971 ContactsManager::UserFull *ContactsManager::get_user_full(UserId user_id) {
13972   auto p = users_full_.find(user_id);
13973   if (p == users_full_.end()) {
13974     return nullptr;
13975   } else {
13976     return p->second.get();
13977   }
13978 }
13979 
add_user_full(UserId user_id)13980 ContactsManager::UserFull *ContactsManager::add_user_full(UserId user_id) {
13981   CHECK(user_id.is_valid());
13982   auto &user_full_ptr = users_full_[user_id];
13983   if (user_full_ptr == nullptr) {
13984     user_full_ptr = make_unique<UserFull>();
13985   }
13986   return user_full_ptr.get();
13987 }
13988 
reload_user(UserId user_id,Promise<Unit> && promise)13989 void ContactsManager::reload_user(UserId user_id, Promise<Unit> &&promise) {
13990   if (!user_id.is_valid()) {
13991     return promise.set_error(Status::Error(400, "Invalid user identifier"));
13992   }
13993 
13994   have_user_force(user_id);
13995   auto input_user = get_input_user(user_id);
13996   if (input_user == nullptr) {
13997     return promise.set_error(Status::Error(400, "User info not found"));
13998   }
13999 
14000   // there is no much reason to combine different requests into one request
14001   vector<tl_object_ptr<telegram_api::InputUser>> users;
14002   users.push_back(std::move(input_user));
14003   td_->create_handler<GetUsersQuery>(std::move(promise))->send(std::move(users));
14004 }
14005 
load_user_full(UserId user_id,bool force,Promise<Unit> && promise,const char * source)14006 void ContactsManager::load_user_full(UserId user_id, bool force, Promise<Unit> &&promise, const char *source) {
14007   auto u = get_user(user_id);
14008   if (u == nullptr) {
14009     return promise.set_error(Status::Error(400, "User not found"));
14010   }
14011 
14012   auto user_full = get_user_full_force(user_id);
14013   if (user_full == nullptr) {
14014     auto input_user = get_input_user(user_id);
14015     if (input_user == nullptr) {
14016       return promise.set_error(Status::Error(400, "Can't get info about inaccessible user"));
14017     }
14018 
14019     return send_get_user_full_query(user_id, std::move(input_user), std::move(promise), source);
14020   }
14021   if (user_full->is_expired()) {
14022     auto input_user = get_input_user(user_id);
14023     CHECK(input_user != nullptr);
14024     if (td_->auth_manager_->is_bot() && !force) {
14025       return send_get_user_full_query(user_id, std::move(input_user), std::move(promise), "load expired user_full");
14026     }
14027 
14028     send_get_user_full_query(user_id, std::move(input_user), Auto(), "load expired user_full");
14029   }
14030 
14031   promise.set_value(Unit());
14032 }
14033 
reload_user_full(UserId user_id)14034 void ContactsManager::reload_user_full(UserId user_id) {
14035   auto input_user = get_input_user(user_id);
14036   if (input_user != nullptr) {
14037     send_get_user_full_query(user_id, std::move(input_user), Auto(), "reload_user_full");
14038   }
14039 }
14040 
send_get_user_full_query(UserId user_id,tl_object_ptr<telegram_api::InputUser> && input_user,Promise<Unit> && promise,const char * source)14041 void ContactsManager::send_get_user_full_query(UserId user_id, tl_object_ptr<telegram_api::InputUser> &&input_user,
14042                                                Promise<Unit> &&promise, const char *source) {
14043   LOG(INFO) << "Get full " << user_id << " from " << source;
14044   auto send_query =
14045       PromiseCreator::lambda([td = td_, input_user = std::move(input_user)](Result<Promise<Unit>> &&promise) mutable {
14046         if (promise.is_ok() && !G()->close_flag()) {
14047           td->create_handler<GetFullUserQuery>(promise.move_as_ok())->send(std::move(input_user));
14048         }
14049       });
14050   get_user_full_queries_.add_query(user_id.get(), std::move(send_query), std::move(promise));
14051 }
14052 
get_user_profile_photos(UserId user_id,int32 offset,int32 limit,Promise<Unit> && promise)14053 std::pair<int32, vector<const Photo *>> ContactsManager::get_user_profile_photos(UserId user_id, int32 offset,
14054                                                                                  int32 limit, Promise<Unit> &&promise) {
14055   std::pair<int32, vector<const Photo *>> result;
14056   result.first = -1;
14057 
14058   if (offset < 0) {
14059     promise.set_error(Status::Error(400, "Parameter offset must be non-negative"));
14060     return result;
14061   }
14062   if (limit <= 0) {
14063     promise.set_error(Status::Error(400, "Parameter limit must be positive"));
14064     return result;
14065   }
14066   if (limit > MAX_GET_PROFILE_PHOTOS) {
14067     limit = MAX_GET_PROFILE_PHOTOS;
14068   }
14069 
14070   auto input_user = get_input_user(user_id);
14071   if (input_user == nullptr) {
14072     promise.set_error(Status::Error(400, "User not found"));
14073     return result;
14074   }
14075 
14076   get_user_dialog_photo(user_id);  // apply pending user photo
14077 
14078   auto user_photos = &user_photos_[user_id];
14079   if (user_photos->getting_now) {
14080     promise.set_error(Status::Error(400, "Request for new profile photos has already been sent"));
14081     return result;
14082   }
14083 
14084   if (user_photos->count != -1) {  // know photo count
14085     CHECK(user_photos->offset != -1);
14086     result.first = user_photos->count;
14087 
14088     if (offset >= user_photos->count) {
14089       // offset if too big
14090       promise.set_value(Unit());
14091       return result;
14092     }
14093 
14094     if (limit > user_photos->count - offset) {
14095       limit = user_photos->count - offset;
14096     }
14097 
14098     int32 cache_begin = user_photos->offset;
14099     int32 cache_end = cache_begin + narrow_cast<int32>(user_photos->photos.size());
14100     if (cache_begin <= offset && offset + limit <= cache_end) {
14101       // answer query from cache
14102       for (int i = 0; i < limit; i++) {
14103         result.second.push_back(&user_photos->photos[i + offset - cache_begin]);
14104       }
14105       promise.set_value(Unit());
14106       return result;
14107     }
14108 
14109     if (cache_begin <= offset && offset < cache_end) {
14110       // adjust offset to the end of cache
14111       limit = offset + limit - cache_end;
14112       offset = cache_end;
14113     }
14114   }
14115 
14116   user_photos->getting_now = true;
14117 
14118   if (limit < MAX_GET_PROFILE_PHOTOS / 5) {
14119     limit = MAX_GET_PROFILE_PHOTOS / 5;  // make limit reasonable
14120   }
14121 
14122   td_->create_handler<GetUserPhotosQuery>(std::move(promise))->send(user_id, std::move(input_user), offset, limit, 0);
14123   return result;
14124 }
14125 
reload_user_profile_photo(UserId user_id,int64 photo_id,Promise<Unit> && promise)14126 void ContactsManager::reload_user_profile_photo(UserId user_id, int64 photo_id, Promise<Unit> &&promise) {
14127   get_user_force(user_id);
14128   auto input_user = get_input_user(user_id);
14129   if (input_user == nullptr) {
14130     return promise.set_error(Status::Error(400, "User info not found"));
14131   }
14132 
14133   // this request will be needed only to download the photo,
14134   // so there is no reason to combine different requests for a photo into one request
14135   td_->create_handler<GetUserPhotosQuery>(std::move(promise))->send(user_id, std::move(input_user), -1, 1, photo_id);
14136 }
14137 
get_user_profile_photo_file_source_id(UserId user_id,int64 photo_id)14138 FileSourceId ContactsManager::get_user_profile_photo_file_source_id(UserId user_id, int64 photo_id) {
14139   auto u = get_user(user_id);
14140   if (u != nullptr && u->photo_ids.count(photo_id) != 0) {
14141     VLOG(file_references) << "Don't need to create file source for photo " << photo_id << " of " << user_id;
14142     // photo was already added, source ID was registered and shouldn't be needed
14143     return FileSourceId();
14144   }
14145 
14146   auto &source_id = user_profile_photo_file_source_ids_[std::make_pair(user_id, photo_id)];
14147   if (!source_id.is_valid()) {
14148     source_id = td_->file_reference_manager_->create_user_photo_file_source(user_id, photo_id);
14149   }
14150   VLOG(file_references) << "Return " << source_id << " for photo " << photo_id << " of " << user_id;
14151   return source_id;
14152 }
14153 
get_chat_full_file_source_id(ChatId chat_id)14154 FileSourceId ContactsManager::get_chat_full_file_source_id(ChatId chat_id) {
14155   if (get_chat_full(chat_id) != nullptr) {
14156     VLOG(file_references) << "Don't need to create file source for full " << chat_id;
14157     // chat full was already added, source ID was registered and shouldn't be needed
14158     return FileSourceId();
14159   }
14160 
14161   auto &source_id = chat_full_file_source_ids_[chat_id];
14162   if (!source_id.is_valid()) {
14163     source_id = td_->file_reference_manager_->create_chat_full_file_source(chat_id);
14164   }
14165   VLOG(file_references) << "Return " << source_id << " for full " << chat_id;
14166   return source_id;
14167 }
14168 
get_channel_full_file_source_id(ChannelId channel_id)14169 FileSourceId ContactsManager::get_channel_full_file_source_id(ChannelId channel_id) {
14170   if (get_channel_full(channel_id) != nullptr) {
14171     VLOG(file_references) << "Don't need to create file source for full " << channel_id;
14172     // channel full was already added, source ID was registered and shouldn't be needed
14173     return FileSourceId();
14174   }
14175 
14176   auto &source_id = channel_full_file_source_ids_[channel_id];
14177   if (!source_id.is_valid()) {
14178     source_id = td_->file_reference_manager_->create_channel_full_file_source(channel_id);
14179   }
14180   VLOG(file_references) << "Return " << source_id << " for full " << channel_id;
14181   return source_id;
14182 }
14183 
have_chat(ChatId chat_id) const14184 bool ContactsManager::have_chat(ChatId chat_id) const {
14185   return chats_.count(chat_id) > 0;
14186 }
14187 
get_chat(ChatId chat_id) const14188 const ContactsManager::Chat *ContactsManager::get_chat(ChatId chat_id) const {
14189   auto p = chats_.find(chat_id);
14190   if (p == chats_.end()) {
14191     return nullptr;
14192   } else {
14193     return p->second.get();
14194   }
14195 }
14196 
get_chat(ChatId chat_id)14197 ContactsManager::Chat *ContactsManager::get_chat(ChatId chat_id) {
14198   auto p = chats_.find(chat_id);
14199   if (p == chats_.end()) {
14200     return nullptr;
14201   } else {
14202     return p->second.get();
14203   }
14204 }
14205 
add_chat(ChatId chat_id)14206 ContactsManager::Chat *ContactsManager::add_chat(ChatId chat_id) {
14207   CHECK(chat_id.is_valid());
14208   auto &chat_ptr = chats_[chat_id];
14209   if (chat_ptr == nullptr) {
14210     chat_ptr = make_unique<Chat>();
14211   }
14212   return chat_ptr.get();
14213 }
14214 
get_chat(ChatId chat_id,int left_tries,Promise<Unit> && promise)14215 bool ContactsManager::get_chat(ChatId chat_id, int left_tries, Promise<Unit> &&promise) {
14216   if (!chat_id.is_valid()) {
14217     promise.set_error(Status::Error(400, "Invalid basic group identifier"));
14218     return false;
14219   }
14220 
14221   if (!have_chat(chat_id)) {
14222     if (left_tries > 2 && G()->parameters().use_chat_info_db) {
14223       send_closure_later(actor_id(this), &ContactsManager::load_chat_from_database, nullptr, chat_id,
14224                          std::move(promise));
14225       return false;
14226     }
14227 
14228     if (left_tries > 1) {
14229       td_->create_handler<GetChatsQuery>(std::move(promise))->send(vector<int64>{chat_id.get()});
14230       return false;
14231     }
14232 
14233     promise.set_error(Status::Error(400, "Group not found"));
14234     return false;
14235   }
14236 
14237   promise.set_value(Unit());
14238   return true;
14239 }
14240 
reload_chat(ChatId chat_id,Promise<Unit> && promise)14241 void ContactsManager::reload_chat(ChatId chat_id, Promise<Unit> &&promise) {
14242   if (!chat_id.is_valid()) {
14243     return promise.set_error(Status::Error(400, "Invalid basic group identifier"));
14244   }
14245 
14246   // there is no much reason to combine different requests into one request
14247   td_->create_handler<GetChatsQuery>(std::move(promise))->send(vector<int64>{chat_id.get()});
14248 }
14249 
get_chat_full(ChatId chat_id) const14250 const ContactsManager::ChatFull *ContactsManager::get_chat_full(ChatId chat_id) const {
14251   auto p = chats_full_.find(chat_id);
14252   if (p == chats_full_.end()) {
14253     return nullptr;
14254   } else {
14255     return p->second.get();
14256   }
14257 }
14258 
get_chat_full(ChatId chat_id)14259 ContactsManager::ChatFull *ContactsManager::get_chat_full(ChatId chat_id) {
14260   auto p = chats_full_.find(chat_id);
14261   if (p == chats_full_.end()) {
14262     return nullptr;
14263   } else {
14264     return p->second.get();
14265   }
14266 }
14267 
add_chat_full(ChatId chat_id)14268 ContactsManager::ChatFull *ContactsManager::add_chat_full(ChatId chat_id) {
14269   CHECK(chat_id.is_valid());
14270   auto &chat_full_ptr = chats_full_[chat_id];
14271   if (chat_full_ptr == nullptr) {
14272     chat_full_ptr = make_unique<ChatFull>();
14273   }
14274   return chat_full_ptr.get();
14275 }
14276 
is_chat_full_outdated(const ChatFull * chat_full,const Chat * c,ChatId chat_id)14277 bool ContactsManager::is_chat_full_outdated(const ChatFull *chat_full, const Chat *c, ChatId chat_id) {
14278   CHECK(c != nullptr);
14279   CHECK(chat_full != nullptr);
14280   if (!c->is_active && chat_full->version == -1) {
14281     return false;
14282   }
14283 
14284   if (chat_full->version != c->version) {
14285     LOG(INFO) << "Have outdated ChatFull " << chat_id << " with current version " << chat_full->version
14286               << " and chat version " << c->version;
14287     return true;
14288   }
14289 
14290   if (c->is_active && c->status.can_manage_invite_links() && !chat_full->invite_link.is_valid()) {
14291     LOG(INFO) << "Have outdated invite link in " << chat_id;
14292     return true;
14293   }
14294 
14295   LOG(DEBUG) << "Full " << chat_id << " is up-to-date with version " << chat_full->version;
14296   return false;
14297 }
14298 
load_chat_full(ChatId chat_id,bool force,Promise<Unit> && promise,const char * source)14299 void ContactsManager::load_chat_full(ChatId chat_id, bool force, Promise<Unit> &&promise, const char *source) {
14300   auto c = get_chat(chat_id);
14301   if (c == nullptr) {
14302     return promise.set_error(Status::Error(400, "Group not found"));
14303   }
14304 
14305   auto chat_full = get_chat_full_force(chat_id, source);
14306   if (chat_full == nullptr) {
14307     LOG(INFO) << "Full " << chat_id << " not found";
14308     return send_get_chat_full_query(chat_id, std::move(promise), source);
14309   }
14310 
14311   if (is_chat_full_outdated(chat_full, c, chat_id)) {
14312     LOG(INFO) << "Have outdated full " << chat_id;
14313     if (td_->auth_manager_->is_bot() && !force) {
14314       return send_get_chat_full_query(chat_id, std::move(promise), source);
14315     }
14316 
14317     send_get_chat_full_query(chat_id, Auto(), source);
14318   }
14319 
14320   promise.set_value(Unit());
14321 }
14322 
reload_chat_full(ChatId chat_id,Promise<Unit> && promise)14323 void ContactsManager::reload_chat_full(ChatId chat_id, Promise<Unit> &&promise) {
14324   send_get_chat_full_query(chat_id, std::move(promise), "reload_chat_full");
14325 }
14326 
send_get_chat_full_query(ChatId chat_id,Promise<Unit> && promise,const char * source)14327 void ContactsManager::send_get_chat_full_query(ChatId chat_id, Promise<Unit> &&promise, const char *source) {
14328   LOG(INFO) << "Get full " << chat_id << " from " << source;
14329   auto send_query = PromiseCreator::lambda([td = td_, chat_id](Result<Promise<Unit>> &&promise) {
14330     if (promise.is_ok() && !G()->close_flag()) {
14331       td->create_handler<GetFullChatQuery>(promise.move_as_ok())->send(chat_id);
14332     }
14333   });
14334 
14335   get_chat_full_queries_.add_query(DialogId(chat_id).get(), std::move(send_query), std::move(promise));
14336 }
14337 
get_chat_participant_count(ChatId chat_id) const14338 int32 ContactsManager::get_chat_participant_count(ChatId chat_id) const {
14339   auto c = get_chat(chat_id);
14340   if (c == nullptr) {
14341     return 0;
14342   }
14343   return c->participant_count;
14344 }
14345 
get_chat_is_active(ChatId chat_id) const14346 bool ContactsManager::get_chat_is_active(ChatId chat_id) const {
14347   auto c = get_chat(chat_id);
14348   if (c == nullptr) {
14349     return false;
14350   }
14351   return c->is_active;
14352 }
14353 
get_chat_migrated_to_channel_id(ChatId chat_id) const14354 ChannelId ContactsManager::get_chat_migrated_to_channel_id(ChatId chat_id) const {
14355   auto c = get_chat(chat_id);
14356   if (c == nullptr) {
14357     return ChannelId();
14358   }
14359   return c->migrated_to_channel_id;
14360 }
14361 
get_chat_status(ChatId chat_id) const14362 DialogParticipantStatus ContactsManager::get_chat_status(ChatId chat_id) const {
14363   auto c = get_chat(chat_id);
14364   if (c == nullptr) {
14365     return DialogParticipantStatus::Banned(0);
14366   }
14367   return get_chat_status(c);
14368 }
14369 
get_chat_status(const Chat * c)14370 DialogParticipantStatus ContactsManager::get_chat_status(const Chat *c) {
14371   if (!c->is_active) {
14372     return DialogParticipantStatus::Banned(0);
14373   }
14374   return c->status;
14375 }
14376 
get_chat_permissions(ChatId chat_id) const14377 DialogParticipantStatus ContactsManager::get_chat_permissions(ChatId chat_id) const {
14378   auto c = get_chat(chat_id);
14379   if (c == nullptr) {
14380     return DialogParticipantStatus::Banned(0);
14381   }
14382   return get_chat_permissions(c);
14383 }
14384 
get_chat_permissions(const Chat * c) const14385 DialogParticipantStatus ContactsManager::get_chat_permissions(const Chat *c) const {
14386   if (!c->is_active) {
14387     return DialogParticipantStatus::Banned(0);
14388   }
14389   return c->status.apply_restrictions(c->default_permissions, td_->auth_manager_->is_bot());
14390 }
14391 
is_appointed_chat_administrator(ChatId chat_id) const14392 bool ContactsManager::is_appointed_chat_administrator(ChatId chat_id) const {
14393   auto c = get_chat(chat_id);
14394   if (c == nullptr) {
14395     return false;
14396   }
14397   return c->status.is_administrator();
14398 }
14399 
is_channel_public(ChannelId channel_id) const14400 bool ContactsManager::is_channel_public(ChannelId channel_id) const {
14401   return is_channel_public(get_channel(channel_id));
14402 }
14403 
is_channel_public(const Channel * c)14404 bool ContactsManager::is_channel_public(const Channel *c) {
14405   return c != nullptr && (!c->username.empty() || c->has_location);
14406 }
14407 
get_channel_type(ChannelId channel_id) const14408 ContactsManager::ChannelType ContactsManager::get_channel_type(ChannelId channel_id) const {
14409   auto c = get_channel(channel_id);
14410   if (c == nullptr) {
14411     return ChannelType::Unknown;
14412   }
14413   return get_channel_type(c);
14414 }
14415 
get_channel_type(const Channel * c)14416 ContactsManager::ChannelType ContactsManager::get_channel_type(const Channel *c) {
14417   if (c->is_megagroup) {
14418     return ChannelType::Megagroup;
14419   }
14420   return ChannelType::Broadcast;
14421 }
14422 
get_channel_date(ChannelId channel_id) const14423 int32 ContactsManager::get_channel_date(ChannelId channel_id) const {
14424   auto c = get_channel(channel_id);
14425   if (c == nullptr) {
14426     return 0;
14427   }
14428   return c->date;
14429 }
14430 
get_channel_status(ChannelId channel_id) const14431 DialogParticipantStatus ContactsManager::get_channel_status(ChannelId channel_id) const {
14432   auto c = get_channel(channel_id);
14433   if (c == nullptr) {
14434     return DialogParticipantStatus::Banned(0);
14435   }
14436   return get_channel_status(c);
14437 }
14438 
get_channel_status(const Channel * c)14439 DialogParticipantStatus ContactsManager::get_channel_status(const Channel *c) {
14440   c->status.update_restrictions();
14441   return c->status;
14442 }
14443 
get_channel_permissions(ChannelId channel_id) const14444 DialogParticipantStatus ContactsManager::get_channel_permissions(ChannelId channel_id) const {
14445   auto c = get_channel(channel_id);
14446   if (c == nullptr) {
14447     return DialogParticipantStatus::Banned(0);
14448   }
14449   return get_channel_permissions(c);
14450 }
14451 
get_channel_permissions(const Channel * c) const14452 DialogParticipantStatus ContactsManager::get_channel_permissions(const Channel *c) const {
14453   c->status.update_restrictions();
14454   if (!c->is_megagroup) {
14455     // there is no restrictions in broadcast channels
14456     return c->status;
14457   }
14458   return c->status.apply_restrictions(c->default_permissions, td_->auth_manager_->is_bot());
14459 }
14460 
get_channel_participant_count(ChannelId channel_id) const14461 int32 ContactsManager::get_channel_participant_count(ChannelId channel_id) const {
14462   auto c = get_channel(channel_id);
14463   if (c == nullptr) {
14464     return 0;
14465   }
14466   return c->participant_count;
14467 }
14468 
get_channel_sign_messages(ChannelId channel_id) const14469 bool ContactsManager::get_channel_sign_messages(ChannelId channel_id) const {
14470   auto c = get_channel(channel_id);
14471   if (c == nullptr) {
14472     return false;
14473   }
14474   return get_channel_sign_messages(c);
14475 }
14476 
get_channel_sign_messages(const Channel * c)14477 bool ContactsManager::get_channel_sign_messages(const Channel *c) {
14478   return c->sign_messages;
14479 }
14480 
get_channel_has_linked_channel(ChannelId channel_id) const14481 bool ContactsManager::get_channel_has_linked_channel(ChannelId channel_id) const {
14482   auto c = get_channel(channel_id);
14483   if (c == nullptr) {
14484     return false;
14485   }
14486   return get_channel_has_linked_channel(c);
14487 }
14488 
get_channel_has_linked_channel(const Channel * c)14489 bool ContactsManager::get_channel_has_linked_channel(const Channel *c) {
14490   return c->has_linked_channel;
14491 }
14492 
get_channel_linked_channel_id(ChannelId channel_id)14493 ChannelId ContactsManager::get_channel_linked_channel_id(ChannelId channel_id) {
14494   auto channel_full = get_channel_full_const(channel_id);
14495   if (channel_full == nullptr) {
14496     channel_full = get_channel_full_force(channel_id, false, "get_channel_linked_channel_id");
14497     if (channel_full == nullptr) {
14498       return ChannelId();
14499     }
14500   }
14501   return channel_full->linked_channel_id;
14502 }
14503 
get_channel_slow_mode_delay(ChannelId channel_id)14504 int32 ContactsManager::get_channel_slow_mode_delay(ChannelId channel_id) {
14505   auto channel_full = get_channel_full_const(channel_id);
14506   if (channel_full == nullptr) {
14507     channel_full = get_channel_full_force(channel_id, false, "get_channel_slow_mode_delay");
14508     if (channel_full == nullptr) {
14509       return 0;
14510     }
14511   }
14512   return channel_full->slow_mode_delay;
14513 }
14514 
have_channel(ChannelId channel_id) const14515 bool ContactsManager::have_channel(ChannelId channel_id) const {
14516   return channels_.count(channel_id) > 0;
14517 }
14518 
have_min_channel(ChannelId channel_id) const14519 bool ContactsManager::have_min_channel(ChannelId channel_id) const {
14520   return min_channels_.count(channel_id) > 0;
14521 }
14522 
get_channel(ChannelId channel_id) const14523 const ContactsManager::Channel *ContactsManager::get_channel(ChannelId channel_id) const {
14524   auto p = channels_.find(channel_id);
14525   if (p == channels_.end()) {
14526     return nullptr;
14527   } else {
14528     return p->second.get();
14529   }
14530 }
14531 
get_channel(ChannelId channel_id)14532 ContactsManager::Channel *ContactsManager::get_channel(ChannelId channel_id) {
14533   auto p = channels_.find(channel_id);
14534   if (p == channels_.end()) {
14535     return nullptr;
14536   } else {
14537     return p->second.get();
14538   }
14539 }
14540 
add_channel(ChannelId channel_id,const char * source)14541 ContactsManager::Channel *ContactsManager::add_channel(ChannelId channel_id, const char *source) {
14542   CHECK(channel_id.is_valid());
14543   auto &channel_ptr = channels_[channel_id];
14544   if (channel_ptr == nullptr) {
14545     channel_ptr = make_unique<Channel>();
14546   }
14547   return channel_ptr.get();
14548 }
14549 
get_channel(ChannelId channel_id,int left_tries,Promise<Unit> && promise)14550 bool ContactsManager::get_channel(ChannelId channel_id, int left_tries, Promise<Unit> &&promise) {
14551   if (!channel_id.is_valid()) {
14552     promise.set_error(Status::Error(400, "Invalid supergroup identifier"));
14553     return false;
14554   }
14555 
14556   if (!have_channel(channel_id)) {
14557     if (left_tries > 2 && G()->parameters().use_chat_info_db) {
14558       send_closure_later(actor_id(this), &ContactsManager::load_channel_from_database, nullptr, channel_id,
14559                          std::move(promise));
14560       return false;
14561     }
14562 
14563     if (left_tries > 1 && td_->auth_manager_->is_bot()) {
14564       td_->create_handler<GetChannelsQuery>(std::move(promise))->send(get_input_channel(channel_id));
14565       return false;
14566     }
14567 
14568     promise.set_error(Status::Error(400, "Supergroup not found"));
14569     return false;
14570   }
14571 
14572   promise.set_value(Unit());
14573   return true;
14574 }
14575 
reload_channel(ChannelId channel_id,Promise<Unit> && promise)14576 void ContactsManager::reload_channel(ChannelId channel_id, Promise<Unit> &&promise) {
14577   if (!channel_id.is_valid()) {
14578     return promise.set_error(Status::Error(400, "Invalid supergroup identifier"));
14579   }
14580 
14581   have_channel_force(channel_id);
14582   auto input_channel = get_input_channel(channel_id);
14583   if (input_channel == nullptr) {
14584     input_channel = make_tl_object<telegram_api::inputChannel>(channel_id.get(), 0);
14585   }
14586 
14587   // there is no much reason to combine different requests into one request
14588   // requests with 0 access_hash must not be merged
14589   td_->create_handler<GetChannelsQuery>(std::move(promise))->send(std::move(input_channel));
14590 }
14591 
get_channel_full_const(ChannelId channel_id) const14592 const ContactsManager::ChannelFull *ContactsManager::get_channel_full_const(ChannelId channel_id) const {
14593   auto p = channels_full_.find(channel_id);
14594   if (p == channels_full_.end()) {
14595     return nullptr;
14596   } else {
14597     return p->second.get();
14598   }
14599 }
14600 
get_channel_full(ChannelId channel_id) const14601 const ContactsManager::ChannelFull *ContactsManager::get_channel_full(ChannelId channel_id) const {
14602   return get_channel_full_const(channel_id);
14603 }
14604 
get_channel_full(ChannelId channel_id,bool only_local,const char * source)14605 ContactsManager::ChannelFull *ContactsManager::get_channel_full(ChannelId channel_id, bool only_local,
14606                                                                 const char *source) {
14607   auto p = channels_full_.find(channel_id);
14608   if (p == channels_full_.end()) {
14609     return nullptr;
14610   }
14611 
14612   auto channel_full = p->second.get();
14613   if (!only_local && channel_full->is_expired() && !td_->auth_manager_->is_bot()) {
14614     send_get_channel_full_query(channel_full, channel_id, Auto(), source);
14615   }
14616 
14617   return channel_full;
14618 }
14619 
add_channel_full(ChannelId channel_id)14620 ContactsManager::ChannelFull *ContactsManager::add_channel_full(ChannelId channel_id) {
14621   CHECK(channel_id.is_valid());
14622   auto &channel_full_ptr = channels_full_[channel_id];
14623   if (channel_full_ptr == nullptr) {
14624     channel_full_ptr = make_unique<ChannelFull>();
14625   }
14626   return channel_full_ptr.get();
14627 }
14628 
load_channel_full(ChannelId channel_id,bool force,Promise<Unit> && promise,const char * source)14629 void ContactsManager::load_channel_full(ChannelId channel_id, bool force, Promise<Unit> &&promise, const char *source) {
14630   auto channel_full = get_channel_full_force(channel_id, true, source);
14631   if (channel_full == nullptr) {
14632     return send_get_channel_full_query(channel_full, channel_id, std::move(promise), source);
14633   }
14634   if (channel_full->is_expired()) {
14635     if (td_->auth_manager_->is_bot() && !force) {
14636       return send_get_channel_full_query(channel_full, channel_id, std::move(promise), "load expired channel_full");
14637     }
14638 
14639     send_get_channel_full_query(channel_full, channel_id, Auto(), "load expired channel_full");
14640   }
14641 
14642   promise.set_value(Unit());
14643 }
14644 
reload_channel_full(ChannelId channel_id,Promise<Unit> && promise,const char * source)14645 void ContactsManager::reload_channel_full(ChannelId channel_id, Promise<Unit> &&promise, const char *source) {
14646   send_get_channel_full_query(get_channel_full(channel_id, true, "reload_channel_full"), channel_id, std::move(promise),
14647                               source);
14648 }
14649 
send_get_channel_full_query(ChannelFull * channel_full,ChannelId channel_id,Promise<Unit> && promise,const char * source)14650 void ContactsManager::send_get_channel_full_query(ChannelFull *channel_full, ChannelId channel_id,
14651                                                   Promise<Unit> &&promise, const char *source) {
14652   auto input_channel = get_input_channel(channel_id);
14653   if (input_channel == nullptr) {
14654     return promise.set_error(Status::Error(400, "Supergroup not found"));
14655   }
14656 
14657   if (!have_input_peer_channel(channel_id, AccessRights::Read)) {
14658     return promise.set_error(Status::Error(400, "Can't access the chat"));
14659   }
14660 
14661   if (channel_full != nullptr) {
14662     if (!promise) {
14663       if (channel_full->repair_request_version != 0) {
14664         LOG(INFO) << "Skip get full " << channel_id << " request from " << source;
14665         return;
14666       }
14667       channel_full->repair_request_version = channel_full->speculative_version;
14668     } else {
14669       channel_full->repair_request_version = std::numeric_limits<uint32>::max();
14670     }
14671   }
14672 
14673   LOG(INFO) << "Get full " << channel_id << " from " << source;
14674   auto send_query = PromiseCreator::lambda(
14675       [td = td_, channel_id, input_channel = std::move(input_channel)](Result<Promise<Unit>> &&promise) mutable {
14676         if (promise.is_ok() && !G()->close_flag()) {
14677           td->create_handler<GetFullChannelQuery>(promise.move_as_ok())->send(channel_id, std::move(input_channel));
14678         }
14679       });
14680   get_chat_full_queries_.add_query(DialogId(channel_id).get(), std::move(send_query), std::move(promise));
14681 }
14682 
have_secret_chat(SecretChatId secret_chat_id) const14683 bool ContactsManager::have_secret_chat(SecretChatId secret_chat_id) const {
14684   return secret_chats_.count(secret_chat_id) > 0;
14685 }
14686 
add_secret_chat(SecretChatId secret_chat_id)14687 ContactsManager::SecretChat *ContactsManager::add_secret_chat(SecretChatId secret_chat_id) {
14688   CHECK(secret_chat_id.is_valid());
14689   auto &secret_chat_ptr = secret_chats_[secret_chat_id];
14690   if (secret_chat_ptr == nullptr) {
14691     secret_chat_ptr = make_unique<SecretChat>();
14692   }
14693   return secret_chat_ptr.get();
14694 }
14695 
get_secret_chat(SecretChatId secret_chat_id) const14696 const ContactsManager::SecretChat *ContactsManager::get_secret_chat(SecretChatId secret_chat_id) const {
14697   auto it = secret_chats_.find(secret_chat_id);
14698   if (it == secret_chats_.end()) {
14699     return nullptr;
14700   }
14701   return it->second.get();
14702 }
14703 
get_secret_chat(SecretChatId secret_chat_id)14704 ContactsManager::SecretChat *ContactsManager::get_secret_chat(SecretChatId secret_chat_id) {
14705   auto it = secret_chats_.find(secret_chat_id);
14706   if (it == secret_chats_.end()) {
14707     return nullptr;
14708   }
14709   return it->second.get();
14710 }
14711 
get_secret_chat(SecretChatId secret_chat_id,bool force,Promise<Unit> && promise)14712 bool ContactsManager::get_secret_chat(SecretChatId secret_chat_id, bool force, Promise<Unit> &&promise) {
14713   if (!secret_chat_id.is_valid()) {
14714     promise.set_error(Status::Error(400, "Invalid secret chat identifier"));
14715     return false;
14716   }
14717 
14718   if (!have_secret_chat(secret_chat_id)) {
14719     if (!force && G()->parameters().use_chat_info_db) {
14720       send_closure_later(actor_id(this), &ContactsManager::load_secret_chat_from_database, nullptr, secret_chat_id,
14721                          std::move(promise));
14722       return false;
14723     }
14724 
14725     promise.set_error(Status::Error(400, "Secret chat not found"));
14726     return false;
14727   }
14728 
14729   promise.set_value(Unit());
14730   return true;
14731 }
14732 
on_update_secret_chat(SecretChatId secret_chat_id,int64 access_hash,UserId user_id,SecretChatState state,bool is_outbound,int32 ttl,int32 date,string key_hash,int32 layer,FolderId initial_folder_id)14733 void ContactsManager::on_update_secret_chat(SecretChatId secret_chat_id, int64 access_hash, UserId user_id,
14734                                             SecretChatState state, bool is_outbound, int32 ttl, int32 date,
14735                                             string key_hash, int32 layer, FolderId initial_folder_id) {
14736   LOG(INFO) << "Update " << secret_chat_id << " with " << user_id << " and access_hash " << access_hash;
14737   auto *secret_chat = add_secret_chat(secret_chat_id);
14738   if (access_hash != secret_chat->access_hash) {
14739     secret_chat->access_hash = access_hash;
14740     secret_chat->need_save_to_database = true;
14741   }
14742   if (user_id.is_valid() && user_id != secret_chat->user_id) {
14743     if (secret_chat->user_id.is_valid()) {
14744       LOG(ERROR) << "Secret chat user has changed from " << secret_chat->user_id << " to " << user_id;
14745       auto &old_secret_chat_ids = secret_chats_with_user_[secret_chat->user_id];
14746       td::remove(old_secret_chat_ids, secret_chat_id);
14747     }
14748     secret_chat->user_id = user_id;
14749     secret_chats_with_user_[secret_chat->user_id].push_back(secret_chat_id);
14750     secret_chat->is_changed = true;
14751   }
14752   if (state != SecretChatState::Unknown && state != secret_chat->state) {
14753     secret_chat->state = state;
14754     secret_chat->is_changed = true;
14755     secret_chat->is_state_changed = true;
14756   }
14757   if (is_outbound != secret_chat->is_outbound) {
14758     secret_chat->is_outbound = is_outbound;
14759     secret_chat->is_changed = true;
14760   }
14761 
14762   if (ttl != -1 && ttl != secret_chat->ttl) {
14763     secret_chat->ttl = ttl;
14764     secret_chat->need_save_to_database = true;
14765     secret_chat->is_ttl_changed = true;
14766   }
14767   if (date != 0 && date != secret_chat->date) {
14768     secret_chat->date = date;
14769     secret_chat->need_save_to_database = true;
14770   }
14771   if (!key_hash.empty() && key_hash != secret_chat->key_hash) {
14772     secret_chat->key_hash = std::move(key_hash);
14773     secret_chat->is_changed = true;
14774   }
14775   if (layer != 0 && layer != secret_chat->layer) {
14776     secret_chat->layer = layer;
14777     secret_chat->is_changed = true;
14778   }
14779   if (initial_folder_id != FolderId() && initial_folder_id != secret_chat->initial_folder_id) {
14780     secret_chat->initial_folder_id = initial_folder_id;
14781     secret_chat->is_changed = true;
14782   }
14783 
14784   update_secret_chat(secret_chat, secret_chat_id);
14785 }
14786 
search_among_dialogs(const vector<DialogId> & dialog_ids,const string & query,int32 limit) const14787 std::pair<int32, vector<DialogId>> ContactsManager::search_among_dialogs(const vector<DialogId> &dialog_ids,
14788                                                                          const string &query, int32 limit) const {
14789   Hints hints;  // TODO cache Hints
14790 
14791   for (auto dialog_id : dialog_ids) {
14792     int64 rating = 0;
14793     if (dialog_id.get_type() == DialogType::User) {
14794       auto user_id = dialog_id.get_user_id();
14795       auto u = get_user(user_id);
14796       if (u == nullptr) {
14797         continue;
14798       }
14799       if (query.empty()) {
14800         hints.add(dialog_id.get(), Slice(" "));
14801       } else {
14802         hints.add(dialog_id.get(), PSLICE() << u->first_name << ' ' << u->last_name << ' ' << u->username);
14803       }
14804       rating = -get_user_was_online(u, user_id);
14805     } else {
14806       if (!td_->messages_manager_->have_dialog_info(dialog_id)) {
14807         continue;
14808       }
14809       if (query.empty()) {
14810         hints.add(dialog_id.get(), Slice(" "));
14811       } else {
14812         hints.add(dialog_id.get(), td_->messages_manager_->get_dialog_title(dialog_id));
14813       }
14814     }
14815     hints.set_rating(dialog_id.get(), rating);
14816   }
14817 
14818   auto result = hints.search(query, limit, true);
14819   return {narrow_cast<int32>(result.first), transform(result.second, [](int64 key) { return DialogId(key); })};
14820 }
14821 
add_dialog_participant(DialogId dialog_id,UserId user_id,int32 forward_limit,Promise<Unit> && promise)14822 void ContactsManager::add_dialog_participant(DialogId dialog_id, UserId user_id, int32 forward_limit,
14823                                              Promise<Unit> &&promise) {
14824   if (!td_->messages_manager_->have_dialog_force(dialog_id, "add_dialog_participant")) {
14825     return promise.set_error(Status::Error(400, "Chat not found"));
14826   }
14827 
14828   switch (dialog_id.get_type()) {
14829     case DialogType::User:
14830       return promise.set_error(Status::Error(400, "Can't add members to a private chat"));
14831     case DialogType::Chat:
14832       return add_chat_participant(dialog_id.get_chat_id(), user_id, forward_limit, std::move(promise));
14833     case DialogType::Channel:
14834       return add_channel_participant(dialog_id.get_channel_id(), user_id, DialogParticipantStatus::Left(),
14835                                      std::move(promise));
14836     case DialogType::SecretChat:
14837       return promise.set_error(Status::Error(400, "Can't add members to a secret chat"));
14838     case DialogType::None:
14839     default:
14840       UNREACHABLE();
14841   }
14842 }
14843 
add_dialog_participants(DialogId dialog_id,const vector<UserId> & user_ids,Promise<Unit> && promise)14844 void ContactsManager::add_dialog_participants(DialogId dialog_id, const vector<UserId> &user_ids,
14845                                               Promise<Unit> &&promise) {
14846   if (!td_->messages_manager_->have_dialog_force(dialog_id, "add_dialog_participants")) {
14847     return promise.set_error(Status::Error(400, "Chat not found"));
14848   }
14849 
14850   switch (dialog_id.get_type()) {
14851     case DialogType::User:
14852       return promise.set_error(Status::Error(400, "Can't add members to a private chat"));
14853     case DialogType::Chat:
14854       return promise.set_error(Status::Error(400, "Can't add many members at once to a basic group chat"));
14855     case DialogType::Channel:
14856       return add_channel_participants(dialog_id.get_channel_id(), user_ids, std::move(promise));
14857     case DialogType::SecretChat:
14858       return promise.set_error(Status::Error(400, "Can't add members to a secret chat"));
14859     case DialogType::None:
14860     default:
14861       UNREACHABLE();
14862   }
14863 }
14864 
set_dialog_participant_status(DialogId dialog_id,DialogId participant_dialog_id,DialogParticipantStatus && status,Promise<Unit> && promise)14865 void ContactsManager::set_dialog_participant_status(DialogId dialog_id, DialogId participant_dialog_id,
14866                                                     DialogParticipantStatus &&status, Promise<Unit> &&promise) {
14867   if (!td_->messages_manager_->have_dialog_force(dialog_id, "set_dialog_participant_status")) {
14868     return promise.set_error(Status::Error(400, "Chat not found"));
14869   }
14870 
14871   switch (dialog_id.get_type()) {
14872     case DialogType::User:
14873       return promise.set_error(Status::Error(400, "Chat member status can't be changed in private chats"));
14874     case DialogType::Chat:
14875       if (participant_dialog_id.get_type() != DialogType::User) {
14876         if (status == DialogParticipantStatus::Left()) {
14877           return promise.set_value(Unit());
14878         } else {
14879           return promise.set_error(Status::Error(400, "Chats can't be members of basic groups"));
14880         }
14881       }
14882       return set_chat_participant_status(dialog_id.get_chat_id(), participant_dialog_id.get_user_id(), status,
14883                                          std::move(promise));
14884     case DialogType::Channel:
14885       return set_channel_participant_status(dialog_id.get_channel_id(), participant_dialog_id, status,
14886                                             std::move(promise));
14887     case DialogType::SecretChat:
14888       return promise.set_error(Status::Error(400, "Chat member status can't be changed in secret chats"));
14889     case DialogType::None:
14890     default:
14891       UNREACHABLE();
14892   }
14893 }
14894 
ban_dialog_participant(DialogId dialog_id,DialogId participant_dialog_id,int32 banned_until_date,bool revoke_messages,Promise<Unit> && promise)14895 void ContactsManager::ban_dialog_participant(DialogId dialog_id, DialogId participant_dialog_id,
14896                                              int32 banned_until_date, bool revoke_messages, Promise<Unit> &&promise) {
14897   if (!td_->messages_manager_->have_dialog_force(dialog_id, "ban_dialog_participant")) {
14898     return promise.set_error(Status::Error(400, "Chat not found"));
14899   }
14900 
14901   switch (dialog_id.get_type()) {
14902     case DialogType::User:
14903       return promise.set_error(Status::Error(400, "Can't ban members in private chats"));
14904     case DialogType::Chat:
14905       if (participant_dialog_id.get_type() != DialogType::User) {
14906         return promise.set_error(Status::Error(400, "Can't ban chats in basic groups"));
14907       }
14908       return delete_chat_participant(dialog_id.get_chat_id(), participant_dialog_id.get_user_id(), revoke_messages,
14909                                      std::move(promise));
14910     case DialogType::Channel:
14911       return set_channel_participant_status(dialog_id.get_channel_id(), participant_dialog_id,
14912                                             DialogParticipantStatus::Banned(banned_until_date), std::move(promise));
14913     case DialogType::SecretChat:
14914       return promise.set_error(Status::Error(400, "Can't ban members in secret chats"));
14915     case DialogType::None:
14916     default:
14917       UNREACHABLE();
14918   }
14919 }
14920 
get_dialog_participant(DialogId dialog_id,DialogId participant_dialog_id,Promise<td_api::object_ptr<td_api::chatMember>> && promise)14921 void ContactsManager::get_dialog_participant(DialogId dialog_id, DialogId participant_dialog_id,
14922                                              Promise<td_api::object_ptr<td_api::chatMember>> &&promise) {
14923   auto new_promise = PromiseCreator::lambda(
14924       [actor_id = actor_id(this), promise = std::move(promise)](Result<DialogParticipant> &&result) mutable {
14925         TRY_RESULT_PROMISE(promise, dialog_participant, std::move(result));
14926         send_closure(actor_id, &ContactsManager::finish_get_dialog_participant, std::move(dialog_participant),
14927                      std::move(promise));
14928       });
14929   do_get_dialog_participant(dialog_id, participant_dialog_id, std::move(new_promise));
14930 }
14931 
finish_get_dialog_participant(DialogParticipant && dialog_participant,Promise<td_api::object_ptr<td_api::chatMember>> && promise)14932 void ContactsManager::finish_get_dialog_participant(DialogParticipant &&dialog_participant,
14933                                                     Promise<td_api::object_ptr<td_api::chatMember>> &&promise) {
14934   TRY_STATUS_PROMISE(promise, G()->close_status());
14935 
14936   auto participant_dialog_id = dialog_participant.dialog_id_;
14937   bool is_user = participant_dialog_id.get_type() == DialogType::User;
14938   if ((is_user && !have_user(participant_dialog_id.get_user_id())) ||
14939       (!is_user && !td_->messages_manager_->have_dialog(participant_dialog_id))) {
14940     return promise.set_error(Status::Error(400, "Member not found"));
14941   }
14942 
14943   promise.set_value(get_chat_member_object(dialog_participant));
14944 }
14945 
do_get_dialog_participant(DialogId dialog_id,DialogId participant_dialog_id,Promise<DialogParticipant> && promise)14946 void ContactsManager::do_get_dialog_participant(DialogId dialog_id, DialogId participant_dialog_id,
14947                                                 Promise<DialogParticipant> &&promise) {
14948   LOG(INFO) << "Receive GetChatMember request to get " << participant_dialog_id << " in " << dialog_id;
14949   if (!td_->messages_manager_->have_dialog_force(dialog_id, "do_get_dialog_participant")) {
14950     return promise.set_error(Status::Error(400, "Chat not found"));
14951   }
14952 
14953   switch (dialog_id.get_type()) {
14954     case DialogType::User: {
14955       auto my_user_id = get_my_id();
14956       auto peer_user_id = dialog_id.get_user_id();
14957       if (participant_dialog_id == DialogId(my_user_id)) {
14958         return promise.set_value(DialogParticipant::private_member(my_user_id, peer_user_id));
14959       }
14960       if (participant_dialog_id == dialog_id) {
14961         return promise.set_value(DialogParticipant::private_member(peer_user_id, my_user_id));
14962       }
14963 
14964       return promise.set_error(Status::Error(400, "Member not found"));
14965     }
14966     case DialogType::Chat:
14967       if (participant_dialog_id.get_type() != DialogType::User) {
14968         return promise.set_value(DialogParticipant::left(participant_dialog_id));
14969       }
14970       return get_chat_participant(dialog_id.get_chat_id(), participant_dialog_id.get_user_id(), std::move(promise));
14971     case DialogType::Channel:
14972       return get_channel_participant(dialog_id.get_channel_id(), participant_dialog_id, std::move(promise));
14973     case DialogType::SecretChat: {
14974       auto my_user_id = get_my_id();
14975       auto peer_user_id = get_secret_chat_user_id(dialog_id.get_secret_chat_id());
14976       if (participant_dialog_id == DialogId(my_user_id)) {
14977         return promise.set_value(DialogParticipant::private_member(my_user_id, peer_user_id));
14978       }
14979       if (peer_user_id.is_valid() && participant_dialog_id == DialogId(peer_user_id)) {
14980         return promise.set_value(DialogParticipant::private_member(peer_user_id, my_user_id));
14981       }
14982 
14983       return promise.set_error(Status::Error(400, "Member not found"));
14984     }
14985     case DialogType::None:
14986     default:
14987       UNREACHABLE();
14988       return promise.set_error(Status::Error(500, "Wrong chat type"));
14989   }
14990 }
14991 
search_private_chat_participants(UserId my_user_id,UserId peer_user_id,const string & query,int32 limit,DialogParticipantsFilter filter) const14992 DialogParticipants ContactsManager::search_private_chat_participants(UserId my_user_id, UserId peer_user_id,
14993                                                                      const string &query, int32 limit,
14994                                                                      DialogParticipantsFilter filter) const {
14995   vector<DialogId> dialog_ids;
14996   if (filter.is_dialog_participant_suitable(td_, DialogParticipant::private_member(my_user_id, peer_user_id))) {
14997     dialog_ids.push_back(DialogId(my_user_id));
14998   }
14999   if (peer_user_id.is_valid() && peer_user_id != my_user_id &&
15000       filter.is_dialog_participant_suitable(td_, DialogParticipant::private_member(peer_user_id, my_user_id))) {
15001     dialog_ids.push_back(DialogId(peer_user_id));
15002   }
15003 
15004   auto result = search_among_dialogs(dialog_ids, query, limit);
15005   return {result.first, transform(result.second, [&](DialogId dialog_id) {
15006             auto user_id = dialog_id.get_user_id();
15007             return DialogParticipant::private_member(user_id, user_id == my_user_id ? peer_user_id : my_user_id);
15008           })};
15009 }
15010 
search_dialog_participants(DialogId dialog_id,const string & query,int32 limit,DialogParticipantsFilter filter,Promise<DialogParticipants> && promise)15011 void ContactsManager::search_dialog_participants(DialogId dialog_id, const string &query, int32 limit,
15012                                                  DialogParticipantsFilter filter,
15013                                                  Promise<DialogParticipants> &&promise) {
15014   LOG(INFO) << "Receive searchChatMembers request to search for \"" << query << "\" in " << dialog_id << " with filter "
15015             << filter;
15016   if (!td_->messages_manager_->have_dialog_force(dialog_id, "search_dialog_participants")) {
15017     return promise.set_error(Status::Error(400, "Chat not found"));
15018   }
15019   if (limit < 0) {
15020     return promise.set_error(Status::Error(400, "Parameter limit must be non-negative"));
15021   }
15022 
15023   switch (dialog_id.get_type()) {
15024     case DialogType::User:
15025       promise.set_value(search_private_chat_participants(get_my_id(), dialog_id.get_user_id(), query, limit, filter));
15026       return;
15027     case DialogType::Chat:
15028       return search_chat_participants(dialog_id.get_chat_id(), query, limit, filter, std::move(promise));
15029     case DialogType::Channel: {
15030       auto channel_id = dialog_id.get_channel_id();
15031       if (filter.has_query()) {
15032         return get_channel_participants(channel_id, filter.get_supergroup_members_filter_object(query), string(), 0,
15033                                         limit, 0, std::move(promise));
15034       } else {
15035         return get_channel_participants(channel_id, filter.get_supergroup_members_filter_object(string()), query, 0,
15036                                         100, limit, std::move(promise));
15037       }
15038     }
15039     case DialogType::SecretChat: {
15040       auto peer_user_id = get_secret_chat_user_id(dialog_id.get_secret_chat_id());
15041       promise.set_value(search_private_chat_participants(get_my_id(), peer_user_id, query, limit, filter));
15042       return;
15043     }
15044     case DialogType::None:
15045     default:
15046       UNREACHABLE();
15047       promise.set_error(Status::Error(500, "Wrong chat type"));
15048   }
15049 }
15050 
get_chat_participant(ChatId chat_id,UserId user_id,Promise<DialogParticipant> && promise)15051 void ContactsManager::get_chat_participant(ChatId chat_id, UserId user_id, Promise<DialogParticipant> &&promise) {
15052   LOG(INFO) << "Trying to get " << user_id << " as member of " << chat_id;
15053 
15054   auto c = get_chat(chat_id);
15055   if (c == nullptr) {
15056     return promise.set_error(Status::Error(400, "Group not found"));
15057   }
15058 
15059   auto chat_full = get_chat_full_force(chat_id, "get_chat_participant");
15060   if (chat_full == nullptr || (td_->auth_manager_->is_bot() && is_chat_full_outdated(chat_full, c, chat_id))) {
15061     auto query_promise = PromiseCreator::lambda(
15062         [actor_id = actor_id(this), chat_id, user_id, promise = std::move(promise)](Result<Unit> &&result) mutable {
15063           TRY_STATUS_PROMISE(promise, std::move(result));
15064           send_closure(actor_id, &ContactsManager::finish_get_chat_participant, chat_id, user_id, std::move(promise));
15065         });
15066     send_get_chat_full_query(chat_id, std::move(query_promise), "get_chat_participant");
15067     return;
15068   }
15069 
15070   if (is_chat_full_outdated(chat_full, c, chat_id)) {
15071     send_get_chat_full_query(chat_id, Auto(), "get_chat_participant lazy");
15072   }
15073 
15074   finish_get_chat_participant(chat_id, user_id, std::move(promise));
15075 }
15076 
finish_get_chat_participant(ChatId chat_id,UserId user_id,Promise<DialogParticipant> && promise)15077 void ContactsManager::finish_get_chat_participant(ChatId chat_id, UserId user_id,
15078                                                   Promise<DialogParticipant> &&promise) {
15079   TRY_STATUS_PROMISE(promise, G()->close_status());
15080 
15081   const auto *participant = get_chat_participant(chat_id, user_id);
15082   if (participant == nullptr) {
15083     return promise.set_value(DialogParticipant::left(DialogId(user_id)));
15084   }
15085 
15086   promise.set_value(DialogParticipant(*participant));
15087 }
15088 
search_chat_participants(ChatId chat_id,const string & query,int32 limit,DialogParticipantsFilter filter,Promise<DialogParticipants> && promise)15089 void ContactsManager::search_chat_participants(ChatId chat_id, const string &query, int32 limit,
15090                                                DialogParticipantsFilter filter, Promise<DialogParticipants> &&promise) {
15091   if (limit < 0) {
15092     return promise.set_error(Status::Error(400, "Parameter limit must be non-negative"));
15093   }
15094 
15095   auto load_chat_full_promise = PromiseCreator::lambda([actor_id = actor_id(this), chat_id, query, limit, filter,
15096                                                         promise = std::move(promise)](Result<Unit> &&result) mutable {
15097     if (result.is_error()) {
15098       promise.set_error(result.move_as_error());
15099     } else {
15100       send_closure(actor_id, &ContactsManager::do_search_chat_participants, chat_id, query, limit, filter,
15101                    std::move(promise));
15102     }
15103   });
15104   load_chat_full(chat_id, false, std::move(load_chat_full_promise), "search_chat_participants");
15105 }
15106 
do_search_chat_participants(ChatId chat_id,const string & query,int32 limit,DialogParticipantsFilter filter,Promise<DialogParticipants> && promise)15107 void ContactsManager::do_search_chat_participants(ChatId chat_id, const string &query, int32 limit,
15108                                                   DialogParticipantsFilter filter,
15109                                                   Promise<DialogParticipants> &&promise) {
15110   TRY_STATUS_PROMISE(promise, G()->close_status());
15111 
15112   auto chat_full = get_chat_full(chat_id);
15113   if (chat_full == nullptr) {
15114     return promise.set_error(Status::Error(500, "Can't find basic group full info"));
15115   }
15116 
15117   vector<DialogId> dialog_ids;
15118   for (const auto &participant : chat_full->participants) {
15119     if (filter.is_dialog_participant_suitable(td_, participant)) {
15120       dialog_ids.push_back(participant.dialog_id_);
15121     }
15122   }
15123 
15124   int32 total_count;
15125   std::tie(total_count, dialog_ids) = search_among_dialogs(dialog_ids, query, limit);
15126   promise.set_value(DialogParticipants{total_count, transform(dialog_ids, [chat_full](DialogId dialog_id) {
15127                                          return *ContactsManager::get_chat_full_participant(chat_full, dialog_id);
15128                                        })});
15129 }
15130 
get_channel_participant(ChannelId channel_id,DialogId participant_dialog_id,Promise<DialogParticipant> && promise)15131 void ContactsManager::get_channel_participant(ChannelId channel_id, DialogId participant_dialog_id,
15132                                               Promise<DialogParticipant> &&promise) {
15133   LOG(INFO) << "Trying to get " << participant_dialog_id << " as member of " << channel_id;
15134 
15135   auto input_peer = td_->messages_manager_->get_input_peer(participant_dialog_id, AccessRights::Read);
15136   if (input_peer == nullptr) {
15137     return promise.set_error(Status::Error(400, "User not found"));
15138   }
15139 
15140   if (have_channel_participant_cache(channel_id)) {
15141     auto *participant = get_channel_participant_from_cache(channel_id, participant_dialog_id);
15142     if (participant != nullptr) {
15143       return promise.set_value(DialogParticipant{*participant});
15144     }
15145   }
15146 
15147   auto on_result_promise = PromiseCreator::lambda([actor_id = actor_id(this), channel_id, promise = std::move(promise)](
15148                                                       Result<DialogParticipant> r_dialog_participant) mutable {
15149     TRY_RESULT_PROMISE(promise, dialog_participant, std::move(r_dialog_participant));
15150     send_closure(actor_id, &ContactsManager::finish_get_channel_participant, channel_id, std::move(dialog_participant),
15151                  std::move(promise));
15152   });
15153 
15154   td_->create_handler<GetChannelParticipantQuery>(std::move(on_result_promise))
15155       ->send(channel_id, participant_dialog_id, std::move(input_peer));
15156 }
15157 
finish_get_channel_participant(ChannelId channel_id,DialogParticipant && dialog_participant,Promise<DialogParticipant> && promise)15158 void ContactsManager::finish_get_channel_participant(ChannelId channel_id, DialogParticipant &&dialog_participant,
15159                                                      Promise<DialogParticipant> &&promise) {
15160   TRY_STATUS_PROMISE(promise, G()->close_status());
15161 
15162   LOG(INFO) << "Receive a member " << dialog_participant.dialog_id_ << " of a channel " << channel_id;
15163 
15164   dialog_participant.status_.update_restrictions();
15165   if (have_channel_participant_cache(channel_id)) {
15166     add_channel_participant_to_cache(channel_id, dialog_participant, false);
15167   }
15168   promise.set_value(std::move(dialog_participant));
15169 }
15170 
get_channel_participants(ChannelId channel_id,tl_object_ptr<td_api::SupergroupMembersFilter> && filter,string additional_query,int32 offset,int32 limit,int32 additional_limit,Promise<DialogParticipants> && promise)15171 void ContactsManager::get_channel_participants(ChannelId channel_id,
15172                                                tl_object_ptr<td_api::SupergroupMembersFilter> &&filter,
15173                                                string additional_query, int32 offset, int32 limit,
15174                                                int32 additional_limit, Promise<DialogParticipants> &&promise) {
15175   if (limit <= 0) {
15176     return promise.set_error(Status::Error(400, "Parameter limit must be positive"));
15177   }
15178   if (limit > MAX_GET_CHANNEL_PARTICIPANTS) {
15179     limit = MAX_GET_CHANNEL_PARTICIPANTS;
15180   }
15181 
15182   if (offset < 0) {
15183     return promise.set_error(Status::Error(400, "Parameter offset must be non-negative"));
15184   }
15185 
15186   auto channel_full = get_channel_full_force(channel_id, false, "get_channel_participants");
15187   if (channel_full != nullptr && !channel_full->is_expired() && !channel_full->can_get_participants) {
15188     return promise.set_error(Status::Error(400, "Member list is inaccessible"));
15189   }
15190 
15191   ChannelParticipantsFilter participants_filter(filter);
15192   auto get_channel_participants_promise = PromiseCreator::lambda(
15193       [actor_id = actor_id(this), channel_id, filter = participants_filter,
15194        additional_query = std::move(additional_query), offset, limit, additional_limit, promise = std::move(promise)](
15195           Result<tl_object_ptr<telegram_api::channels_channelParticipants>> &&result) mutable {
15196         if (result.is_error()) {
15197           promise.set_error(result.move_as_error());
15198         } else {
15199           send_closure(actor_id, &ContactsManager::on_get_channel_participants, channel_id, std::move(filter), offset,
15200                        limit, std::move(additional_query), additional_limit, result.move_as_ok(), std::move(promise));
15201         }
15202       });
15203   td_->create_handler<GetChannelParticipantsQuery>(std::move(get_channel_participants_promise))
15204       ->send(channel_id, participants_filter, offset, limit);
15205 }
15206 
get_dialog_administrators(DialogId dialog_id,int left_tries,Promise<Unit> && promise)15207 vector<DialogAdministrator> ContactsManager::get_dialog_administrators(DialogId dialog_id, int left_tries,
15208                                                                        Promise<Unit> &&promise) {
15209   LOG(INFO) << "Receive GetChatAdministrators request in " << dialog_id << " with " << left_tries << " left tries";
15210   if (!td_->messages_manager_->have_dialog_force(dialog_id, "get_dialog_administrators")) {
15211     promise.set_error(Status::Error(400, "Chat not found"));
15212     return {};
15213   }
15214 
15215   switch (dialog_id.get_type()) {
15216     case DialogType::User:
15217     case DialogType::SecretChat:
15218       promise.set_value(Unit());
15219       return {};
15220     case DialogType::Chat:
15221     case DialogType::Channel:
15222       break;
15223     case DialogType::None:
15224     default:
15225       UNREACHABLE();
15226       return {};
15227   }
15228 
15229   auto it = dialog_administrators_.find(dialog_id);
15230   if (it != dialog_administrators_.end()) {
15231     promise.set_value(Unit());
15232     if (left_tries >= 2) {
15233       auto hash = get_vector_hash(transform(it->second, [](const DialogAdministrator &administrator) {
15234         return static_cast<uint64>(administrator.get_user_id().get());
15235       }));
15236       reload_dialog_administrators(dialog_id, hash, Auto());  // update administrators cache
15237     }
15238     return it->second;
15239   }
15240 
15241   if (left_tries >= 3) {
15242     load_dialog_administrators(dialog_id, std::move(promise));
15243     return {};
15244   }
15245 
15246   if (left_tries >= 2) {
15247     reload_dialog_administrators(dialog_id, 0, std::move(promise));
15248     return {};
15249   }
15250 
15251   LOG(ERROR) << "Have no known administrators in " << dialog_id;
15252   promise.set_value(Unit());
15253   return {};
15254 }
15255 
get_dialog_administrators_database_key(DialogId dialog_id)15256 string ContactsManager::get_dialog_administrators_database_key(DialogId dialog_id) {
15257   return PSTRING() << "adm" << (-dialog_id.get());
15258 }
15259 
load_dialog_administrators(DialogId dialog_id,Promise<Unit> && promise)15260 void ContactsManager::load_dialog_administrators(DialogId dialog_id, Promise<Unit> &&promise) {
15261   if (G()->parameters().use_chat_info_db) {
15262     LOG(INFO) << "Load administrators of " << dialog_id << " from database";
15263     G()->td_db()->get_sqlite_pmc()->get(get_dialog_administrators_database_key(dialog_id),
15264                                         PromiseCreator::lambda([actor_id = actor_id(this), dialog_id,
15265                                                                 promise = std::move(promise)](string value) mutable {
15266                                           send_closure(actor_id,
15267                                                        &ContactsManager::on_load_dialog_administrators_from_database,
15268                                                        dialog_id, std::move(value), std::move(promise));
15269                                         }));
15270   } else {
15271     promise.set_value(Unit());
15272   }
15273 }
15274 
on_load_dialog_administrators_from_database(DialogId dialog_id,string value,Promise<Unit> && promise)15275 void ContactsManager::on_load_dialog_administrators_from_database(DialogId dialog_id, string value,
15276                                                                   Promise<Unit> &&promise) {
15277   if (value.empty() || G()->close_flag()) {
15278     promise.set_value(Unit());
15279     return;
15280   }
15281 
15282   vector<DialogAdministrator> administrators;
15283   log_event_parse(administrators, value).ensure();
15284 
15285   LOG(INFO) << "Successfully loaded " << administrators.size() << " administrators in " << dialog_id
15286             << " from database";
15287 
15288   MultiPromiseActorSafe load_users_multipromise{"LoadUsersMultiPromiseActor"};
15289   load_users_multipromise.add_promise(
15290       PromiseCreator::lambda([actor_id = actor_id(this), dialog_id, administrators,
15291                               promise = std::move(promise)](Result<Unit> result) mutable {
15292         send_closure(actor_id, &ContactsManager::on_load_administrator_users_finished, dialog_id,
15293                      std::move(administrators), std::move(result), std::move(promise));
15294       }));
15295 
15296   auto lock_promise = load_users_multipromise.get_promise();
15297 
15298   for (auto &administrator : administrators) {
15299     get_user(administrator.get_user_id(), 3, load_users_multipromise.get_promise());
15300   }
15301 
15302   lock_promise.set_value(Unit());
15303 }
15304 
on_load_administrator_users_finished(DialogId dialog_id,vector<DialogAdministrator> administrators,Result<> result,Promise<Unit> promise)15305 void ContactsManager::on_load_administrator_users_finished(DialogId dialog_id,
15306                                                            vector<DialogAdministrator> administrators, Result<> result,
15307                                                            Promise<Unit> promise) {
15308   if (!G()->close_flag() && result.is_ok()) {
15309     dialog_administrators_.emplace(dialog_id, std::move(administrators));
15310   }
15311   promise.set_value(Unit());
15312 }
15313 
on_update_channel_administrator_count(ChannelId channel_id,int32 administrator_count)15314 void ContactsManager::on_update_channel_administrator_count(ChannelId channel_id, int32 administrator_count) {
15315   auto channel_full = get_channel_full_force(channel_id, true, "on_update_channel_administrator_count");
15316   if (channel_full != nullptr && channel_full->administrator_count != administrator_count) {
15317     channel_full->administrator_count = administrator_count;
15318     channel_full->is_changed = true;
15319 
15320     if (channel_full->participant_count < channel_full->administrator_count) {
15321       channel_full->participant_count = channel_full->administrator_count;
15322 
15323       auto c = get_channel(channel_id);
15324       if (c != nullptr && c->participant_count != channel_full->participant_count) {
15325         c->participant_count = channel_full->participant_count;
15326         c->is_changed = true;
15327         update_channel(c, channel_id);
15328       }
15329     }
15330 
15331     update_channel_full(channel_full, channel_id, "on_update_channel_administrator_count");
15332   }
15333 }
15334 
on_update_dialog_administrators(DialogId dialog_id,vector<DialogAdministrator> && administrators,bool have_access,bool from_database)15335 void ContactsManager::on_update_dialog_administrators(DialogId dialog_id, vector<DialogAdministrator> &&administrators,
15336                                                       bool have_access, bool from_database) {
15337   LOG(INFO) << "Update administrators in " << dialog_id << " to " << format::as_array(administrators);
15338   if (have_access) {
15339     std::sort(administrators.begin(), administrators.end(),
15340               [](const DialogAdministrator &lhs, const DialogAdministrator &rhs) {
15341                 return lhs.get_user_id().get() < rhs.get_user_id().get();
15342               });
15343 
15344     auto it = dialog_administrators_.find(dialog_id);
15345     if (it != dialog_administrators_.end()) {
15346       if (it->second == administrators) {
15347         return;
15348       }
15349       it->second = std::move(administrators);
15350     } else {
15351       it = dialog_administrators_.emplace(dialog_id, std::move(administrators)).first;
15352     }
15353 
15354     if (G()->parameters().use_chat_info_db && !from_database) {
15355       LOG(INFO) << "Save administrators of " << dialog_id << " to database";
15356       G()->td_db()->get_sqlite_pmc()->set(get_dialog_administrators_database_key(dialog_id),
15357                                           log_event_store(it->second).as_slice().str(), Auto());
15358     }
15359   } else {
15360     dialog_administrators_.erase(dialog_id);
15361     if (G()->parameters().use_chat_info_db) {
15362       G()->td_db()->get_sqlite_pmc()->erase(get_dialog_administrators_database_key(dialog_id), Auto());
15363     }
15364   }
15365 }
15366 
reload_dialog_administrators(DialogId dialog_id,int64 hash,Promise<Unit> && promise)15367 void ContactsManager::reload_dialog_administrators(DialogId dialog_id, int64 hash, Promise<Unit> &&promise) {
15368   switch (dialog_id.get_type()) {
15369     case DialogType::Chat:
15370       load_chat_full(dialog_id.get_chat_id(), false, std::move(promise), "reload_dialog_administrators");
15371       break;
15372     case DialogType::Channel:
15373       td_->create_handler<GetChannelAdministratorsQuery>(std::move(promise))->send(dialog_id.get_channel_id(), hash);
15374       break;
15375     default:
15376       UNREACHABLE();
15377   }
15378 }
15379 
on_chat_update(telegram_api::chatEmpty & chat,const char * source)15380 void ContactsManager::on_chat_update(telegram_api::chatEmpty &chat, const char *source) {
15381   ChatId chat_id(chat.id_);
15382   if (!chat_id.is_valid()) {
15383     LOG(ERROR) << "Receive invalid " << chat_id << " from " << source;
15384     return;
15385   }
15386 
15387   if (!have_chat(chat_id)) {
15388     LOG(ERROR) << "Have no information about " << chat_id << " but received chatEmpty from " << source;
15389   }
15390 }
15391 
on_chat_update(telegram_api::chat & chat,const char * source)15392 void ContactsManager::on_chat_update(telegram_api::chat &chat, const char *source) {
15393   auto debug_str = PSTRING() << " from " << source << " in " << oneline(to_string(chat));
15394   ChatId chat_id(chat.id_);
15395   if (!chat_id.is_valid()) {
15396     LOG(ERROR) << "Receive invalid " << chat_id << debug_str;
15397     return;
15398   }
15399 
15400   DialogParticipantStatus status = [&] {
15401     bool is_creator = 0 != (chat.flags_ & CHAT_FLAG_USER_IS_CREATOR);
15402     bool has_left = 0 != (chat.flags_ & CHAT_FLAG_USER_HAS_LEFT);
15403     bool was_kicked = 0 != (chat.flags_ & CHAT_FLAG_USER_WAS_KICKED);
15404     if (was_kicked) {
15405       LOG_IF(ERROR, has_left) << "Kicked and left" << debug_str;  // only one of the flags can be set
15406       has_left = true;
15407     }
15408 
15409     if (is_creator) {
15410       return DialogParticipantStatus::Creator(!has_left, false, string());
15411     } else if (chat.admin_rights_ != nullptr) {
15412       return get_dialog_participant_status(false, std::move(chat.admin_rights_), string());
15413     } else if (was_kicked) {
15414       return DialogParticipantStatus::Banned(0);
15415     } else if (has_left) {
15416       return DialogParticipantStatus::Left();
15417     } else {
15418       return DialogParticipantStatus::Member();
15419     }
15420   }();
15421 
15422   bool is_active = 0 == (chat.flags_ & CHAT_FLAG_IS_DEACTIVATED);
15423 
15424   ChannelId migrated_to_channel_id;
15425   if (chat.flags_ & CHAT_FLAG_WAS_MIGRATED) {
15426     switch (chat.migrated_to_->get_id()) {
15427       case telegram_api::inputChannelEmpty::ID: {
15428         LOG(ERROR) << "Receive empty upgraded to supergroup for " << chat_id << debug_str;
15429         break;
15430       }
15431       case telegram_api::inputChannel::ID: {
15432         auto input_channel = move_tl_object_as<telegram_api::inputChannel>(chat.migrated_to_);
15433         migrated_to_channel_id = ChannelId(input_channel->channel_id_);
15434         if (!have_channel_force(migrated_to_channel_id)) {
15435           if (!migrated_to_channel_id.is_valid()) {
15436             LOG(ERROR) << "Receive invalid " << migrated_to_channel_id << debug_str;
15437           } else {
15438             // temporarily create the channel
15439             Channel *c = add_channel(migrated_to_channel_id, "on_chat_update");
15440             c->access_hash = input_channel->access_hash_;
15441             c->title = chat.title_;
15442             c->status = DialogParticipantStatus::Left();
15443             c->is_megagroup = true;
15444 
15445             // we definitely need to call update_channel, because client should know about every added channel
15446             update_channel(c, migrated_to_channel_id);
15447 
15448             // get info about the channel
15449             td_->create_handler<GetChannelsQuery>(Promise<>())->send(std::move(input_channel));
15450           }
15451         }
15452         break;
15453       }
15454       default:
15455         UNREACHABLE();
15456     }
15457   }
15458 
15459   Chat *c = get_chat_force(chat_id);  // to load versions
15460   if (c == nullptr) {
15461     c = add_chat(chat_id);
15462   }
15463   on_update_chat_title(c, chat_id, std::move(chat.title_));
15464   if (!status.is_left()) {
15465     on_update_chat_participant_count(c, chat_id, chat.participants_count_, chat.version_, debug_str);
15466   }
15467   if (c->date != chat.date_) {
15468     LOG_IF(ERROR, c->date != 0) << "Chat creation date has changed from " << c->date << " to " << chat.date_
15469                                 << debug_str;
15470     c->date = chat.date_;
15471     c->need_save_to_database = true;
15472   }
15473   on_update_chat_status(c, chat_id, std::move(status));
15474   on_update_chat_default_permissions(c, chat_id, get_restricted_rights(std::move(chat.default_banned_rights_)),
15475                                      chat.version_);
15476   on_update_chat_photo(c, chat_id, std::move(chat.photo_));
15477   on_update_chat_active(c, chat_id, is_active);
15478   on_update_chat_noforwards(c, chat_id, chat.noforwards_);
15479   on_update_chat_migrated_to_channel_id(c, chat_id, migrated_to_channel_id);
15480   LOG_IF(INFO, !is_active && !migrated_to_channel_id.is_valid()) << chat_id << " is deactivated" << debug_str;
15481   if (c->cache_version != Chat::CACHE_VERSION) {
15482     c->cache_version = Chat::CACHE_VERSION;
15483     c->need_save_to_database = true;
15484   }
15485   c->is_received_from_server = true;
15486   update_chat(c, chat_id);
15487 
15488   bool has_active_group_call = (chat.flags_ & CHAT_FLAG_HAS_ACTIVE_GROUP_CALL) != 0;
15489   bool is_group_call_empty = (chat.flags_ & CHAT_FLAG_IS_GROUP_CALL_NON_EMPTY) == 0;
15490   td_->messages_manager_->on_update_dialog_group_call(DialogId(chat_id), has_active_group_call, is_group_call_empty,
15491                                                       "receive chat");
15492 }
15493 
on_chat_update(telegram_api::chatForbidden & chat,const char * source)15494 void ContactsManager::on_chat_update(telegram_api::chatForbidden &chat, const char *source) {
15495   ChatId chat_id(chat.id_);
15496   if (!chat_id.is_valid()) {
15497     LOG(ERROR) << "Receive invalid " << chat_id << " from " << source;
15498     return;
15499   }
15500 
15501   bool is_uninited = get_chat_force(chat_id) == nullptr;
15502   Chat *c = add_chat(chat_id);
15503   on_update_chat_title(c, chat_id, std::move(chat.title_));
15504   // chat participant count will be updated in on_update_chat_status
15505   on_update_chat_photo(c, chat_id, nullptr);
15506   if (c->date != 0) {
15507     c->date = 0;  // removed in 38-th layer
15508     c->need_save_to_database = true;
15509   }
15510   on_update_chat_status(c, chat_id, DialogParticipantStatus::Banned(0));
15511   if (is_uninited) {
15512     on_update_chat_active(c, chat_id, true);
15513     on_update_chat_migrated_to_channel_id(c, chat_id, ChannelId());
15514   } else {
15515     // leave active and migrated to as is
15516   }
15517   if (c->cache_version != Chat::CACHE_VERSION) {
15518     c->cache_version = Chat::CACHE_VERSION;
15519     c->need_save_to_database = true;
15520   }
15521   c->is_received_from_server = true;
15522   update_chat(c, chat_id);
15523 }
15524 
on_chat_update(telegram_api::channel & channel,const char * source)15525 void ContactsManager::on_chat_update(telegram_api::channel &channel, const char *source) {
15526   ChannelId channel_id(channel.id_);
15527   if (!channel_id.is_valid()) {
15528     LOG(ERROR) << "Receive invalid " << channel_id << " from " << source << ": " << to_string(channel);
15529     return;
15530   }
15531 
15532   if (channel.flags_ == 0 && channel.access_hash_ == 0 && channel.title_.empty()) {
15533     Channel *c = get_channel_force(channel_id);
15534     LOG(ERROR) << "Receive empty " << to_string(channel) << " from " << source << ", have "
15535                << to_string(get_supergroup_object(channel_id, c));
15536     if (c == nullptr) {
15537       min_channels_.insert(channel_id);
15538     }
15539     return;
15540   }
15541 
15542   bool is_min = (channel.flags_ & CHANNEL_FLAG_IS_MIN) != 0;
15543   bool has_access_hash = (channel.flags_ & CHANNEL_FLAG_HAS_ACCESS_HASH) != 0;
15544   auto access_hash = has_access_hash ? channel.access_hash_ : 0;
15545 
15546   bool has_linked_channel = (channel.flags_ & CHANNEL_FLAG_HAS_LINKED_CHAT) != 0;
15547   bool sign_messages = (channel.flags_ & CHANNEL_FLAG_SIGN_MESSAGES) != 0;
15548   bool is_slow_mode_enabled = (channel.flags_ & CHANNEL_FLAG_IS_SLOW_MODE_ENABLED) != 0;
15549   bool is_megagroup = (channel.flags_ & CHANNEL_FLAG_IS_MEGAGROUP) != 0;
15550   bool is_verified = (channel.flags_ & CHANNEL_FLAG_IS_VERIFIED) != 0;
15551   auto restriction_reasons = get_restriction_reasons(std::move(channel.restriction_reason_));
15552   bool is_scam = (channel.flags_ & CHANNEL_FLAG_IS_SCAM) != 0;
15553   bool is_fake = (channel.flags_ & CHANNEL_FLAG_IS_FAKE) != 0;
15554   bool is_gigagroup = (channel.flags_ & CHANNEL_FLAG_IS_GIGAGROUP) != 0;
15555   bool have_participant_count = (channel.flags_ & CHANNEL_FLAG_HAS_PARTICIPANT_COUNT) != 0;
15556   int32 participant_count = have_participant_count ? channel.participants_count_ : 0;
15557 
15558   if (have_participant_count) {
15559     auto channel_full = get_channel_full_const(channel_id);
15560     if (channel_full != nullptr && channel_full->administrator_count > participant_count) {
15561       participant_count = channel_full->administrator_count;
15562     }
15563   }
15564 
15565   {
15566     bool is_broadcast = (channel.flags_ & CHANNEL_FLAG_IS_BROADCAST) != 0;
15567     LOG_IF(ERROR, is_broadcast == is_megagroup)
15568         << "Receive wrong channel flag is_broadcast == is_megagroup == " << is_megagroup << " from " << source << ": "
15569         << oneline(to_string(channel));
15570   }
15571 
15572   if (is_megagroup) {
15573     LOG_IF(ERROR, sign_messages) << "Need to sign messages in the supergroup " << channel_id << " from " << source;
15574     sign_messages = true;
15575   } else {
15576     LOG_IF(ERROR, is_slow_mode_enabled) << "Slow mode enabled in the " << channel_id << " from " << source;
15577     LOG_IF(ERROR, is_gigagroup) << "Receive broadcast group as channel " << channel_id << " from " << source;
15578     is_slow_mode_enabled = false;
15579     is_gigagroup = false;
15580   }
15581   if (is_gigagroup) {
15582     remove_dialog_suggested_action(SuggestedAction{SuggestedAction::Type::ConvertToGigagroup, DialogId(channel_id)});
15583   }
15584 
15585   DialogParticipantStatus status = [&] {
15586     bool has_left = (channel.flags_ & CHANNEL_FLAG_USER_HAS_LEFT) != 0;
15587     bool is_creator = (channel.flags_ & CHANNEL_FLAG_USER_IS_CREATOR) != 0;
15588 
15589     if (is_creator) {
15590       bool is_anonymous = channel.admin_rights_ != nullptr &&
15591                           (channel.admin_rights_->flags_ & telegram_api::chatAdminRights::ANONYMOUS_MASK) != 0;
15592       return DialogParticipantStatus::Creator(!has_left, is_anonymous, string());
15593     } else if (channel.admin_rights_ != nullptr) {
15594       return get_dialog_participant_status(false, std::move(channel.admin_rights_), string());
15595     } else if (channel.banned_rights_ != nullptr) {
15596       return get_dialog_participant_status(!has_left, std::move(channel.banned_rights_));
15597     } else if (has_left) {
15598       return DialogParticipantStatus::Left();
15599     } else {
15600       return DialogParticipantStatus::Member();
15601     }
15602   }();
15603 
15604   if (is_min) {
15605     // TODO there can be better support for min channels
15606     Channel *c = get_channel_force(channel_id);
15607     if (c != nullptr) {
15608       LOG(DEBUG) << "Receive known min " << channel_id;
15609       on_update_channel_title(c, channel_id, std::move(channel.title_));
15610       on_update_channel_username(c, channel_id, std::move(channel.username_));
15611       on_update_channel_photo(c, channel_id, std::move(channel.photo_));
15612       on_update_channel_default_permissions(c, channel_id,
15613                                             get_restricted_rights(std::move(channel.default_banned_rights_)));
15614       on_update_channel_has_location(c, channel_id, channel.has_geo_);
15615       on_update_channel_noforwards(c, channel_id, channel.noforwards_);
15616 
15617       if (c->has_linked_channel != has_linked_channel || c->is_slow_mode_enabled != is_slow_mode_enabled ||
15618           c->is_megagroup != is_megagroup || c->restriction_reasons != restriction_reasons || c->is_scam != is_scam ||
15619           c->is_fake != is_fake || c->is_gigagroup != is_gigagroup) {
15620         c->has_linked_channel = has_linked_channel;
15621         c->is_slow_mode_enabled = is_slow_mode_enabled;
15622         c->is_megagroup = is_megagroup;
15623         c->restriction_reasons = std::move(restriction_reasons);
15624         c->is_scam = is_scam;
15625         c->is_fake = is_fake;
15626         c->is_gigagroup = is_gigagroup;
15627 
15628         c->is_changed = true;
15629         invalidate_channel_full(channel_id, !c->is_slow_mode_enabled);
15630       }
15631       if (c->is_verified != is_verified || c->sign_messages != sign_messages) {
15632         c->is_verified = is_verified;
15633         c->sign_messages = sign_messages;
15634 
15635         c->is_changed = true;
15636       }
15637 
15638       update_channel(c, channel_id);
15639     } else {
15640       min_channels_.insert(channel_id);
15641     }
15642     return;
15643   }
15644   if (!has_access_hash) {
15645     LOG(ERROR) << "Receive non-min " << channel_id << " without access_hash from " << source;
15646     return;
15647   }
15648 
15649   if (status.is_creator()) {
15650     // to correctly calculate is_ownership_transferred in on_update_channel_status
15651     get_channel_force(channel_id);
15652   }
15653 
15654   Channel *c = add_channel(channel_id, "on_channel");
15655   if (c->status.is_banned()) {  // possibly uninited channel
15656     min_channels_.erase(channel_id);
15657   }
15658   if (c->access_hash != access_hash) {
15659     c->access_hash = access_hash;
15660     c->need_save_to_database = true;
15661   }
15662   on_update_channel_title(c, channel_id, std::move(channel.title_));
15663   if (c->date != channel.date_) {
15664     c->date = channel.date_;
15665     c->is_changed = true;
15666   }
15667   on_update_channel_photo(c, channel_id, std::move(channel.photo_));
15668   on_update_channel_status(c, channel_id, std::move(status));
15669   on_update_channel_username(c, channel_id, std::move(channel.username_));  // uses status, must be called after
15670   on_update_channel_default_permissions(c, channel_id,
15671                                         get_restricted_rights(std::move(channel.default_banned_rights_)));
15672   on_update_channel_has_location(c, channel_id, channel.has_geo_);
15673   on_update_channel_noforwards(c, channel_id, channel.noforwards_);
15674 
15675   bool need_update_participant_count = have_participant_count && participant_count != c->participant_count;
15676   if (need_update_participant_count) {
15677     c->participant_count = participant_count;
15678     c->is_changed = true;
15679   }
15680 
15681   bool need_invalidate_channel_full = false;
15682   if (c->has_linked_channel != has_linked_channel || c->is_slow_mode_enabled != is_slow_mode_enabled ||
15683       c->is_megagroup != is_megagroup || c->restriction_reasons != restriction_reasons || c->is_scam != is_scam ||
15684       c->is_fake != is_fake || c->is_gigagroup != is_gigagroup) {
15685     c->has_linked_channel = has_linked_channel;
15686     c->is_slow_mode_enabled = is_slow_mode_enabled;
15687     c->is_megagroup = is_megagroup;
15688     c->restriction_reasons = std::move(restriction_reasons);
15689     c->is_scam = is_scam;
15690     c->is_fake = is_fake;
15691     c->is_gigagroup = is_gigagroup;
15692 
15693     c->is_changed = true;
15694     need_invalidate_channel_full = true;
15695   }
15696   if (c->is_verified != is_verified || c->sign_messages != sign_messages) {
15697     c->is_verified = is_verified;
15698     c->sign_messages = sign_messages;
15699 
15700     c->is_changed = true;
15701   }
15702 
15703   if (c->cache_version != Channel::CACHE_VERSION) {
15704     c->cache_version = Channel::CACHE_VERSION;
15705     c->need_save_to_database = true;
15706   }
15707   c->is_received_from_server = true;
15708   update_channel(c, channel_id);
15709 
15710   if (need_update_participant_count) {
15711     auto channel_full = get_channel_full(channel_id, true, "on_chat_update");
15712     if (channel_full != nullptr && channel_full->participant_count != participant_count) {
15713       channel_full->participant_count = participant_count;
15714       channel_full->is_changed = true;
15715       update_channel_full(channel_full, channel_id, "on_chat_update");
15716     }
15717   }
15718 
15719   if (need_invalidate_channel_full) {
15720     invalidate_channel_full(channel_id, !c->is_slow_mode_enabled);
15721   }
15722 
15723   bool has_active_group_call = (channel.flags_ & CHANNEL_FLAG_HAS_ACTIVE_GROUP_CALL) != 0;
15724   bool is_group_call_empty = (channel.flags_ & CHANNEL_FLAG_IS_GROUP_CALL_NON_EMPTY) == 0;
15725   td_->messages_manager_->on_update_dialog_group_call(DialogId(channel_id), has_active_group_call, is_group_call_empty,
15726                                                       "receive channel");
15727 }
15728 
on_chat_update(telegram_api::channelForbidden & channel,const char * source)15729 void ContactsManager::on_chat_update(telegram_api::channelForbidden &channel, const char *source) {
15730   ChannelId channel_id(channel.id_);
15731   if (!channel_id.is_valid()) {
15732     LOG(ERROR) << "Receive invalid " << channel_id << " from " << source << ": " << to_string(channel);
15733     return;
15734   }
15735 
15736   if (channel.flags_ == 0 && channel.access_hash_ == 0 && channel.title_.empty()) {
15737     Channel *c = get_channel_force(channel_id);
15738     LOG(ERROR) << "Receive empty " << to_string(channel) << " from " << source << ", have "
15739                << to_string(get_supergroup_object(channel_id, c));
15740     if (c == nullptr) {
15741       min_channels_.insert(channel_id);
15742     }
15743     return;
15744   }
15745 
15746   Channel *c = add_channel(channel_id, "on_channel_forbidden");
15747   if (c->status.is_banned()) {  // possibly uninited channel
15748     min_channels_.erase(channel_id);
15749   }
15750   if (c->access_hash != channel.access_hash_) {
15751     c->access_hash = channel.access_hash_;
15752     c->need_save_to_database = true;
15753   }
15754   on_update_channel_title(c, channel_id, std::move(channel.title_));
15755   on_update_channel_photo(c, channel_id, nullptr);
15756   if (c->date != 0) {
15757     c->date = 0;
15758     c->is_changed = true;
15759   }
15760   int32 unban_date = (channel.flags_ & CHANNEL_FLAG_HAS_UNBAN_DATE) != 0 ? channel.until_date_ : 0;
15761   on_update_channel_status(c, channel_id, DialogParticipantStatus::Banned(unban_date));
15762   // on_update_channel_username(c, channel_id, "");  // don't know if channel username is empty, so don't update it
15763   tl_object_ptr<telegram_api::chatBannedRights> banned_rights;  // == nullptr
15764   on_update_channel_default_permissions(c, channel_id, get_restricted_rights(std::move(banned_rights)));
15765   // on_update_channel_has_location(c, channel_id, false);
15766   on_update_channel_noforwards(c, channel_id, false);
15767   td_->messages_manager_->on_update_dialog_group_call(DialogId(channel_id), false, false, "receive channelForbidden");
15768 
15769   bool sign_messages = false;
15770   bool is_slow_mode_enabled = false;
15771   bool is_megagroup = (channel.flags_ & CHANNEL_FLAG_IS_MEGAGROUP) != 0;
15772   bool is_verified = false;
15773   bool is_scam = false;
15774   bool is_fake = false;
15775 
15776   {
15777     bool is_broadcast = (channel.flags_ & CHANNEL_FLAG_IS_BROADCAST) != 0;
15778     LOG_IF(ERROR, is_broadcast == is_megagroup)
15779         << "Receive wrong channel flag is_broadcast == is_megagroup == " << is_megagroup << " from " << source << ": "
15780         << oneline(to_string(channel));
15781   }
15782 
15783   if (is_megagroup) {
15784     sign_messages = true;
15785   }
15786 
15787   bool need_invalidate_channel_full = false;
15788   if (c->is_slow_mode_enabled != is_slow_mode_enabled || c->is_megagroup != is_megagroup ||
15789       !c->restriction_reasons.empty() || c->is_scam != is_scam || c->is_fake != is_fake) {
15790     // c->has_linked_channel = has_linked_channel;
15791     c->is_slow_mode_enabled = is_slow_mode_enabled;
15792     c->is_megagroup = is_megagroup;
15793     c->restriction_reasons.clear();
15794     c->is_scam = is_scam;
15795     c->is_fake = is_fake;
15796 
15797     c->is_changed = true;
15798     need_invalidate_channel_full = true;
15799   }
15800   if (c->sign_messages != sign_messages || c->is_verified != is_verified) {
15801     c->sign_messages = sign_messages;
15802     c->is_verified = is_verified;
15803 
15804     c->is_changed = true;
15805   }
15806 
15807   bool need_drop_participant_count = c->participant_count != 0;
15808   if (need_drop_participant_count) {
15809     c->participant_count = 0;
15810     c->is_changed = true;
15811   }
15812 
15813   if (c->cache_version != Channel::CACHE_VERSION) {
15814     c->cache_version = Channel::CACHE_VERSION;
15815     c->need_save_to_database = true;
15816   }
15817   c->is_received_from_server = true;
15818   update_channel(c, channel_id);
15819 
15820   if (need_drop_participant_count) {
15821     auto channel_full = get_channel_full(channel_id, true, "on_chat_update");
15822     if (channel_full != nullptr && channel_full->participant_count != 0) {
15823       channel_full->participant_count = 0;
15824       channel_full->administrator_count = 0;
15825       channel_full->is_changed = true;
15826       update_channel_full(channel_full, channel_id, "on_chat_update 2");
15827     }
15828   }
15829   if (need_invalidate_channel_full) {
15830     invalidate_channel_full(channel_id, !c->is_slow_mode_enabled);
15831   }
15832 }
15833 
on_upload_profile_photo(FileId file_id,tl_object_ptr<telegram_api::InputFile> input_file)15834 void ContactsManager::on_upload_profile_photo(FileId file_id, tl_object_ptr<telegram_api::InputFile> input_file) {
15835   auto it = uploaded_profile_photos_.find(file_id);
15836   CHECK(it != uploaded_profile_photos_.end());
15837 
15838   double main_frame_timestamp = it->second.main_frame_timestamp;
15839   bool is_animation = it->second.is_animation;
15840   int32 reupload_count = it->second.reupload_count;
15841   auto promise = std::move(it->second.promise);
15842 
15843   uploaded_profile_photos_.erase(it);
15844 
15845   LOG(INFO) << "Uploaded " << (is_animation ? "animated" : "static") << " profile photo " << file_id
15846             << " with reupload_count = " << reupload_count;
15847   FileView file_view = td_->file_manager_->get_file_view(file_id);
15848   if (file_view.has_remote_location() && input_file == nullptr) {
15849     if (file_view.main_remote_location().is_web()) {
15850       return promise.set_error(Status::Error(400, "Can't use web photo as profile photo"));
15851     }
15852     if (reupload_count == 3) {  // upload, ForceReupload repair file reference, reupload
15853       return promise.set_error(Status::Error(400, "Failed to reupload the file"));
15854     }
15855 
15856     // delete file reference and forcely reupload the file
15857     if (is_animation) {
15858       CHECK(file_view.get_type() == FileType::Animation);
15859       LOG_CHECK(file_view.main_remote_location().is_common()) << file_view.main_remote_location();
15860     } else {
15861       CHECK(file_view.get_type() == FileType::Photo);
15862       LOG_CHECK(file_view.main_remote_location().is_photo()) << file_view.main_remote_location();
15863     }
15864     auto file_reference =
15865         is_animation ? FileManager::extract_file_reference(file_view.main_remote_location().as_input_document())
15866                      : FileManager::extract_file_reference(file_view.main_remote_location().as_input_photo());
15867     td_->file_manager_->delete_file_reference(file_id, file_reference);
15868     upload_profile_photo(file_id, is_animation, main_frame_timestamp, std::move(promise), reupload_count + 1, {-1});
15869     return;
15870   }
15871   CHECK(input_file != nullptr);
15872 
15873   td_->create_handler<UploadProfilePhotoQuery>(std::move(promise))
15874       ->send(file_id, std::move(input_file), is_animation, main_frame_timestamp);
15875 }
15876 
on_upload_profile_photo_error(FileId file_id,Status status)15877 void ContactsManager::on_upload_profile_photo_error(FileId file_id, Status status) {
15878   LOG(INFO) << "File " << file_id << " has upload error " << status;
15879   CHECK(status.is_error());
15880 
15881   auto it = uploaded_profile_photos_.find(file_id);
15882   CHECK(it != uploaded_profile_photos_.end());
15883 
15884   auto promise = std::move(it->second.promise);
15885 
15886   uploaded_profile_photos_.erase(it);
15887 
15888   promise.set_error(std::move(status));  // TODO check that status has valid error code
15889 }
15890 
get_user_status_object(UserId user_id,const User * u) const15891 td_api::object_ptr<td_api::UserStatus> ContactsManager::get_user_status_object(UserId user_id, const User *u) const {
15892   if (u->is_bot) {
15893     return make_tl_object<td_api::userStatusOnline>(std::numeric_limits<int32>::max());
15894   }
15895 
15896   int32 was_online = get_user_was_online(u, user_id);
15897   switch (was_online) {
15898     case -3:
15899       return make_tl_object<td_api::userStatusLastMonth>();
15900     case -2:
15901       return make_tl_object<td_api::userStatusLastWeek>();
15902     case -1:
15903       return make_tl_object<td_api::userStatusRecently>();
15904     case 0:
15905       return make_tl_object<td_api::userStatusEmpty>();
15906     default: {
15907       int32 time = G()->unix_time();
15908       if (was_online > time) {
15909         return make_tl_object<td_api::userStatusOnline>(was_online);
15910       } else {
15911         return make_tl_object<td_api::userStatusOffline>(was_online);
15912       }
15913     }
15914   }
15915 }
15916 
get_update_unknown_user_object(UserId user_id)15917 td_api::object_ptr<td_api::updateUser> ContactsManager::get_update_unknown_user_object(UserId user_id) {
15918   return td_api::make_object<td_api::updateUser>(td_api::make_object<td_api::user>(
15919       user_id.get(), "", "", "", "", td_api::make_object<td_api::userStatusEmpty>(), nullptr, false, false, false,
15920       false, "", false, false, false, td_api::make_object<td_api::userTypeUnknown>(), ""));
15921 }
15922 
get_user_id_object(UserId user_id,const char * source) const15923 int64 ContactsManager::get_user_id_object(UserId user_id, const char *source) const {
15924   if (user_id.is_valid() && get_user(user_id) == nullptr && unknown_users_.count(user_id) == 0) {
15925     LOG(ERROR) << "Have no info about " << user_id << " from " << source;
15926     unknown_users_.insert(user_id);
15927     send_closure(G()->td(), &Td::send_update, get_update_unknown_user_object(user_id));
15928   }
15929   return user_id.get();
15930 }
15931 
get_user_object(UserId user_id) const15932 tl_object_ptr<td_api::user> ContactsManager::get_user_object(UserId user_id) const {
15933   return get_user_object(user_id, get_user(user_id));
15934 }
15935 
get_user_object(UserId user_id,const User * u) const15936 tl_object_ptr<td_api::user> ContactsManager::get_user_object(UserId user_id, const User *u) const {
15937   if (u == nullptr) {
15938     return nullptr;
15939   }
15940   tl_object_ptr<td_api::UserType> type;
15941   if (u->is_deleted) {
15942     type = make_tl_object<td_api::userTypeDeleted>();
15943   } else if (u->is_bot) {
15944     type = make_tl_object<td_api::userTypeBot>(u->can_join_groups, u->can_read_all_group_messages, u->is_inline_bot,
15945                                                u->inline_query_placeholder, u->need_location_bot);
15946   } else {
15947     type = make_tl_object<td_api::userTypeRegular>();
15948   }
15949 
15950   return make_tl_object<td_api::user>(
15951       user_id.get(), u->first_name, u->last_name, u->username, u->phone_number, get_user_status_object(user_id, u),
15952       get_profile_photo_object(td_->file_manager_.get(), u->photo), u->is_contact, u->is_mutual_contact, u->is_verified,
15953       u->is_support, get_restriction_reason_description(u->restriction_reasons), u->is_scam, u->is_fake, u->is_received,
15954       std::move(type), u->language_code);
15955 }
15956 
get_user_ids_object(const vector<UserId> & user_ids,const char * source) const15957 vector<int64> ContactsManager::get_user_ids_object(const vector<UserId> &user_ids, const char *source) const {
15958   return transform(user_ids, [this, source](UserId user_id) { return get_user_id_object(user_id, source); });
15959 }
15960 
get_users_object(int32 total_count,const vector<UserId> & user_ids) const15961 tl_object_ptr<td_api::users> ContactsManager::get_users_object(int32 total_count,
15962                                                                const vector<UserId> &user_ids) const {
15963   if (total_count == -1) {
15964     total_count = narrow_cast<int32>(user_ids.size());
15965   }
15966   return td_api::make_object<td_api::users>(total_count, get_user_ids_object(user_ids, "get_users_object"));
15967 }
15968 
get_user_full_info_object(UserId user_id) const15969 tl_object_ptr<td_api::userFullInfo> ContactsManager::get_user_full_info_object(UserId user_id) const {
15970   return get_user_full_info_object(user_id, get_user_full(user_id));
15971 }
15972 
get_user_full_info_object(UserId user_id,const UserFull * user_full) const15973 tl_object_ptr<td_api::userFullInfo> ContactsManager::get_user_full_info_object(UserId user_id,
15974                                                                                const UserFull *user_full) const {
15975   CHECK(user_full != nullptr);
15976   bool is_bot = is_user_bot(user_id);
15977   auto commands = transform(user_full->commands, [](const auto &command) { return command.get_bot_command_object(); });
15978   return make_tl_object<td_api::userFullInfo>(
15979       get_chat_photo_object(td_->file_manager_.get(), user_full->photo), user_full->is_blocked,
15980       user_full->can_be_called, user_full->supports_video_calls, user_full->has_private_calls,
15981       !user_full->private_forward_name.empty(), user_full->need_phone_number_privacy_exception,
15982       is_bot ? string() : user_full->about, is_bot ? user_full->about : string(),
15983       is_bot ? user_full->description : string(), user_full->common_chat_count, std::move(commands));
15984 }
15985 
get_update_unknown_basic_group_object(ChatId chat_id)15986 td_api::object_ptr<td_api::updateBasicGroup> ContactsManager::get_update_unknown_basic_group_object(ChatId chat_id) {
15987   return td_api::make_object<td_api::updateBasicGroup>(td_api::make_object<td_api::basicGroup>(
15988       chat_id.get(), 0, DialogParticipantStatus::Banned(0).get_chat_member_status_object(), true, 0));
15989 }
15990 
get_basic_group_id_object(ChatId chat_id,const char * source) const15991 int64 ContactsManager::get_basic_group_id_object(ChatId chat_id, const char *source) const {
15992   if (chat_id.is_valid() && get_chat(chat_id) == nullptr && unknown_chats_.count(chat_id) == 0) {
15993     LOG(ERROR) << "Have no info about " << chat_id << " from " << source;
15994     unknown_chats_.insert(chat_id);
15995     send_closure(G()->td(), &Td::send_update, get_update_unknown_basic_group_object(chat_id));
15996   }
15997   return chat_id.get();
15998 }
15999 
get_basic_group_object(ChatId chat_id)16000 tl_object_ptr<td_api::basicGroup> ContactsManager::get_basic_group_object(ChatId chat_id) {
16001   return get_basic_group_object(chat_id, get_chat(chat_id));
16002 }
16003 
get_basic_group_object(ChatId chat_id,const Chat * c)16004 tl_object_ptr<td_api::basicGroup> ContactsManager::get_basic_group_object(ChatId chat_id, const Chat *c) {
16005   if (c == nullptr) {
16006     return nullptr;
16007   }
16008   if (c->migrated_to_channel_id.is_valid()) {
16009     get_channel_force(c->migrated_to_channel_id);
16010   }
16011   return get_basic_group_object_const(chat_id, c);
16012 }
16013 
get_basic_group_object_const(ChatId chat_id,const Chat * c) const16014 tl_object_ptr<td_api::basicGroup> ContactsManager::get_basic_group_object_const(ChatId chat_id, const Chat *c) const {
16015   return make_tl_object<td_api::basicGroup>(
16016       chat_id.get(), c->participant_count, get_chat_status(c).get_chat_member_status_object(), c->is_active,
16017       get_supergroup_id_object(c->migrated_to_channel_id, "get_basic_group_object"));
16018 }
16019 
get_basic_group_full_info_object(ChatId chat_id) const16020 tl_object_ptr<td_api::basicGroupFullInfo> ContactsManager::get_basic_group_full_info_object(ChatId chat_id) const {
16021   return get_basic_group_full_info_object(get_chat_full(chat_id));
16022 }
16023 
get_basic_group_full_info_object(const ChatFull * chat_full) const16024 tl_object_ptr<td_api::basicGroupFullInfo> ContactsManager::get_basic_group_full_info_object(
16025     const ChatFull *chat_full) const {
16026   CHECK(chat_full != nullptr);
16027   auto bot_commands = transform(chat_full->bot_commands, [td = td_](const BotCommands &commands) {
16028     return commands.get_bot_commands_object(td);
16029   });
16030   return make_tl_object<td_api::basicGroupFullInfo>(
16031       get_chat_photo_object(td_->file_manager_.get(), chat_full->photo), chat_full->description,
16032       get_user_id_object(chat_full->creator_user_id, "basicGroupFullInfo"),
16033       transform(chat_full->participants,
16034                 [this](const DialogParticipant &chat_participant) { return get_chat_member_object(chat_participant); }),
16035       chat_full->invite_link.get_chat_invite_link_object(this), std::move(bot_commands));
16036 }
16037 
get_update_unknown_supergroup_object(ChannelId channel_id)16038 td_api::object_ptr<td_api::updateSupergroup> ContactsManager::get_update_unknown_supergroup_object(
16039     ChannelId channel_id) {
16040   return td_api::make_object<td_api::updateSupergroup>(td_api::make_object<td_api::supergroup>(
16041       channel_id.get(), string(), 0, DialogParticipantStatus::Banned(0).get_chat_member_status_object(), 0, false,
16042       false, false, false, true, false, false, string(), false, false));
16043 }
16044 
get_supergroup_id_object(ChannelId channel_id,const char * source) const16045 int64 ContactsManager::get_supergroup_id_object(ChannelId channel_id, const char *source) const {
16046   if (channel_id.is_valid() && get_channel(channel_id) == nullptr && unknown_channels_.count(channel_id) == 0) {
16047     LOG(ERROR) << "Have no info about " << channel_id << " received from " << source;
16048     unknown_channels_.insert(channel_id);
16049     send_closure(G()->td(), &Td::send_update, get_update_unknown_supergroup_object(channel_id));
16050   }
16051   return channel_id.get();
16052 }
16053 
get_supergroup_object(ChannelId channel_id) const16054 tl_object_ptr<td_api::supergroup> ContactsManager::get_supergroup_object(ChannelId channel_id) const {
16055   return get_supergroup_object(channel_id, get_channel(channel_id));
16056 }
16057 
get_supergroup_object(ChannelId channel_id,const Channel * c)16058 tl_object_ptr<td_api::supergroup> ContactsManager::get_supergroup_object(ChannelId channel_id, const Channel *c) {
16059   if (c == nullptr) {
16060     return nullptr;
16061   }
16062   return td_api::make_object<td_api::supergroup>(
16063       channel_id.get(), c->username, c->date, get_channel_status(c).get_chat_member_status_object(),
16064       c->participant_count, c->has_linked_channel, c->has_location, c->sign_messages, c->is_slow_mode_enabled,
16065       !c->is_megagroup, c->is_gigagroup, c->is_verified, get_restriction_reason_description(c->restriction_reasons),
16066       c->is_scam, c->is_fake);
16067 }
16068 
get_supergroup_full_info_object(ChannelId channel_id) const16069 tl_object_ptr<td_api::supergroupFullInfo> ContactsManager::get_supergroup_full_info_object(ChannelId channel_id) const {
16070   return get_supergroup_full_info_object(get_channel_full(channel_id), channel_id);
16071 }
16072 
get_supergroup_full_info_object(const ChannelFull * channel_full,ChannelId channel_id) const16073 tl_object_ptr<td_api::supergroupFullInfo> ContactsManager::get_supergroup_full_info_object(
16074     const ChannelFull *channel_full, ChannelId channel_id) const {
16075   CHECK(channel_full != nullptr);
16076   double slow_mode_delay_expires_in = 0;
16077   if (channel_full->slow_mode_next_send_date != 0) {
16078     slow_mode_delay_expires_in = max(channel_full->slow_mode_next_send_date - G()->server_time(), 1e-3);
16079   }
16080   auto bot_commands = transform(channel_full->bot_commands, [td = td_](const BotCommands &commands) {
16081     return commands.get_bot_commands_object(td);
16082   });
16083   return td_api::make_object<td_api::supergroupFullInfo>(
16084       get_chat_photo_object(td_->file_manager_.get(), channel_full->photo), channel_full->description,
16085       channel_full->participant_count, channel_full->administrator_count, channel_full->restricted_count,
16086       channel_full->banned_count, DialogId(channel_full->linked_channel_id).get(), channel_full->slow_mode_delay,
16087       slow_mode_delay_expires_in, channel_full->can_get_participants, channel_full->can_set_username,
16088       channel_full->can_set_sticker_set, channel_full->can_set_location, channel_full->can_view_statistics,
16089       channel_full->is_all_history_available, channel_full->sticker_set_id.get(),
16090       channel_full->location.get_chat_location_object(), channel_full->invite_link.get_chat_invite_link_object(this),
16091       std::move(bot_commands),
16092       get_basic_group_id_object(channel_full->migrated_from_chat_id, "get_supergroup_full_info_object"),
16093       channel_full->migrated_from_max_message_id.get());
16094 }
16095 
get_secret_chat_state_object(SecretChatState state)16096 tl_object_ptr<td_api::SecretChatState> ContactsManager::get_secret_chat_state_object(SecretChatState state) {
16097   switch (state) {
16098     case SecretChatState::Waiting:
16099       return make_tl_object<td_api::secretChatStatePending>();
16100     case SecretChatState::Active:
16101       return make_tl_object<td_api::secretChatStateReady>();
16102     case SecretChatState::Closed:
16103     case SecretChatState::Unknown:
16104       return make_tl_object<td_api::secretChatStateClosed>();
16105     default:
16106       UNREACHABLE();
16107       return nullptr;
16108   }
16109 }
16110 
get_update_unknown_secret_chat_object(SecretChatId secret_chat_id)16111 td_api::object_ptr<td_api::updateSecretChat> ContactsManager::get_update_unknown_secret_chat_object(
16112     SecretChatId secret_chat_id) {
16113   return td_api::make_object<td_api::updateSecretChat>(td_api::make_object<td_api::secretChat>(
16114       secret_chat_id.get(), 0, get_secret_chat_state_object(SecretChatState::Unknown), false, string(), 0));
16115 }
16116 
get_secret_chat_id_object(SecretChatId secret_chat_id,const char * source) const16117 int32 ContactsManager::get_secret_chat_id_object(SecretChatId secret_chat_id, const char *source) const {
16118   if (secret_chat_id.is_valid() && get_secret_chat(secret_chat_id) == nullptr &&
16119       unknown_secret_chats_.count(secret_chat_id) == 0) {
16120     LOG(ERROR) << "Have no info about " << secret_chat_id << " from " << source;
16121     unknown_secret_chats_.insert(secret_chat_id);
16122     send_closure(G()->td(), &Td::send_update, get_update_unknown_secret_chat_object(secret_chat_id));
16123   }
16124   return secret_chat_id.get();
16125 }
16126 
get_secret_chat_object(SecretChatId secret_chat_id)16127 tl_object_ptr<td_api::secretChat> ContactsManager::get_secret_chat_object(SecretChatId secret_chat_id) {
16128   return get_secret_chat_object(secret_chat_id, get_secret_chat(secret_chat_id));
16129 }
16130 
get_secret_chat_object(SecretChatId secret_chat_id,const SecretChat * secret_chat)16131 tl_object_ptr<td_api::secretChat> ContactsManager::get_secret_chat_object(SecretChatId secret_chat_id,
16132                                                                           const SecretChat *secret_chat) {
16133   if (secret_chat == nullptr) {
16134     return nullptr;
16135   }
16136   get_user_force(secret_chat->user_id);
16137   return get_secret_chat_object_const(secret_chat_id, secret_chat);
16138 }
16139 
get_secret_chat_object_const(SecretChatId secret_chat_id,const SecretChat * secret_chat) const16140 tl_object_ptr<td_api::secretChat> ContactsManager::get_secret_chat_object_const(SecretChatId secret_chat_id,
16141                                                                                 const SecretChat *secret_chat) const {
16142   return td_api::make_object<td_api::secretChat>(secret_chat_id.get(),
16143                                                  get_user_id_object(secret_chat->user_id, "secretChat"),
16144                                                  get_secret_chat_state_object(secret_chat->state),
16145                                                  secret_chat->is_outbound, secret_chat->key_hash, secret_chat->layer);
16146 }
16147 
get_chat_invite_link_info_object(const string & invite_link)16148 tl_object_ptr<td_api::chatInviteLinkInfo> ContactsManager::get_chat_invite_link_info_object(const string &invite_link) {
16149   auto it = invite_link_infos_.find(invite_link);
16150   if (it == invite_link_infos_.end()) {
16151     return nullptr;
16152   }
16153 
16154   auto invite_link_info = it->second.get();
16155   CHECK(invite_link_info != nullptr);
16156 
16157   DialogId dialog_id = invite_link_info->dialog_id;
16158   string title;
16159   const DialogPhoto *photo = nullptr;
16160   DialogPhoto invite_link_photo;
16161   string description;
16162   int32 participant_count = 0;
16163   vector<int64> member_user_ids;
16164   bool creates_join_request = false;
16165   bool is_public = false;
16166   bool is_member = false;
16167   td_api::object_ptr<td_api::ChatType> chat_type;
16168 
16169   if (dialog_id.is_valid()) {
16170     switch (dialog_id.get_type()) {
16171       case DialogType::Chat: {
16172         auto chat_id = dialog_id.get_chat_id();
16173         const Chat *c = get_chat(chat_id);
16174 
16175         if (c != nullptr) {
16176           title = c->title;
16177           photo = &c->photo;
16178           participant_count = c->participant_count;
16179           is_member = c->status.is_member();
16180         } else {
16181           LOG(ERROR) << "Have no information about " << chat_id;
16182         }
16183         chat_type = td_api::make_object<td_api::chatTypeBasicGroup>(
16184             get_basic_group_id_object(chat_id, "get_chat_invite_link_info_object"));
16185         break;
16186       }
16187       case DialogType::Channel: {
16188         auto channel_id = dialog_id.get_channel_id();
16189         const Channel *c = get_channel(channel_id);
16190 
16191         bool is_megagroup = false;
16192         if (c != nullptr) {
16193           title = c->title;
16194           photo = &c->photo;
16195           is_public = is_channel_public(c);
16196           is_megagroup = c->is_megagroup;
16197           participant_count = c->participant_count;
16198           is_member = c->status.is_member();
16199         } else {
16200           LOG(ERROR) << "Have no information about " << channel_id;
16201         }
16202         chat_type = td_api::make_object<td_api::chatTypeSupergroup>(
16203             get_supergroup_id_object(channel_id, "get_chat_invite_link_info_object"), !is_megagroup);
16204         break;
16205       }
16206       default:
16207         UNREACHABLE();
16208     }
16209     description = get_dialog_about(dialog_id);
16210   } else {
16211     title = invite_link_info->title;
16212     invite_link_photo = as_fake_dialog_photo(invite_link_info->photo, dialog_id);
16213     photo = &invite_link_photo;
16214     description = invite_link_info->description;
16215     participant_count = invite_link_info->participant_count;
16216     member_user_ids = get_user_ids_object(invite_link_info->participant_user_ids, "get_chat_invite_link_info_object");
16217     creates_join_request = invite_link_info->creates_join_request;
16218     is_public = invite_link_info->is_public;
16219 
16220     if (invite_link_info->is_chat) {
16221       chat_type = td_api::make_object<td_api::chatTypeBasicGroup>(0);
16222     } else {
16223       chat_type = td_api::make_object<td_api::chatTypeSupergroup>(0, !invite_link_info->is_megagroup);
16224     }
16225   }
16226 
16227   if (dialog_id.is_valid()) {
16228     td_->messages_manager_->force_create_dialog(dialog_id, "get_chat_invite_link_info_object");
16229   }
16230   int32 accessible_for = 0;
16231   if (dialog_id.is_valid() && !is_member) {
16232     auto access_it = dialog_access_by_invite_link_.find(dialog_id);
16233     if (access_it != dialog_access_by_invite_link_.end()) {
16234       accessible_for = td::max(1, access_it->second.accessible_before - G()->unix_time() - 1);
16235     }
16236   }
16237 
16238   return make_tl_object<td_api::chatInviteLinkInfo>(dialog_id.get(), accessible_for, std::move(chat_type), title,
16239                                                     get_chat_photo_info_object(td_->file_manager_.get(), photo),
16240                                                     description, participant_count, std::move(member_user_ids),
16241                                                     creates_join_request, is_public);
16242 }
16243 
get_support_user(Promise<Unit> && promise)16244 UserId ContactsManager::get_support_user(Promise<Unit> &&promise) {
16245   if (support_user_id_.is_valid()) {
16246     promise.set_value(Unit());
16247     return support_user_id_;
16248   }
16249 
16250   td_->create_handler<GetSupportUserQuery>(std::move(promise))->send();
16251   return UserId();
16252 }
16253 
after_get_difference()16254 void ContactsManager::after_get_difference() {
16255   if (td_->auth_manager_->is_bot()) {
16256     return;
16257   }
16258   get_user(get_my_id(), 3, Promise<Unit>());
16259 
16260   if (td_->is_online()) {
16261     reload_created_public_dialogs(PublicDialogType::HasUsername, Promise<td_api::object_ptr<td_api::chats>>());
16262     reload_created_public_dialogs(PublicDialogType::IsLocationBased, Promise<td_api::object_ptr<td_api::chats>>());
16263   }
16264 }
16265 
get_current_state(vector<td_api::object_ptr<td_api::Update>> & updates) const16266 void ContactsManager::get_current_state(vector<td_api::object_ptr<td_api::Update>> &updates) const {
16267   for (auto user_id : unknown_users_) {
16268     if (!have_min_user(user_id)) {
16269       updates.push_back(get_update_unknown_user_object(user_id));
16270     }
16271   }
16272   for (auto chat_id : unknown_chats_) {
16273     if (!have_chat(chat_id)) {
16274       updates.push_back(get_update_unknown_basic_group_object(chat_id));
16275     }
16276   }
16277   for (auto channel_id : unknown_channels_) {
16278     if (!have_channel(channel_id)) {
16279       updates.push_back(get_update_unknown_supergroup_object(channel_id));
16280     }
16281   }
16282   for (auto secret_chat_id : unknown_secret_chats_) {
16283     if (!have_secret_chat(secret_chat_id)) {
16284       updates.push_back(get_update_unknown_secret_chat_object(secret_chat_id));
16285     }
16286   }
16287 
16288   for (auto &it : users_) {
16289     updates.push_back(td_api::make_object<td_api::updateUser>(get_user_object(it.first, it.second.get())));
16290   }
16291   for (auto &it : channels_) {
16292     updates.push_back(td_api::make_object<td_api::updateSupergroup>(get_supergroup_object(it.first, it.second.get())));
16293   }
16294   for (auto &it : chats_) {  // chat object can contain channel_id, so it must be sent after channels
16295     updates.push_back(
16296         td_api::make_object<td_api::updateBasicGroup>(get_basic_group_object_const(it.first, it.second.get())));
16297   }
16298   for (auto &it : secret_chats_) {  // secret chat object contains user_id, so it must be sent after users
16299     updates.push_back(
16300         td_api::make_object<td_api::updateSecretChat>(get_secret_chat_object_const(it.first, it.second.get())));
16301   }
16302 
16303   for (auto &it : users_full_) {
16304     updates.push_back(td_api::make_object<td_api::updateUserFullInfo>(
16305         it.first.get(), get_user_full_info_object(it.first, it.second.get())));
16306   }
16307   for (auto &it : channels_full_) {
16308     updates.push_back(td_api::make_object<td_api::updateSupergroupFullInfo>(
16309         it.first.get(), get_supergroup_full_info_object(it.second.get(), it.first)));
16310   }
16311   for (auto &it : chats_full_) {
16312     updates.push_back(td_api::make_object<td_api::updateBasicGroupFullInfo>(
16313         it.first.get(), get_basic_group_full_info_object(it.second.get())));
16314   }
16315 }
16316 
16317 }  // namespace td
16318