diff --git a/td/generate/scheme/td_api.tl b/td/generate/scheme/td_api.tl index 2d383bc7..b011cdfb 100644 --- a/td/generate/scheme/td_api.tl +++ b/td/generate/scheme/td_api.tl @@ -523,7 +523,7 @@ messageSendingStateFailed error_code:int32 error_message:string can_retry:Bool r //@chat_id Chat identifier //@sending_state Information about the sending state of the message; may be null //@is_outgoing True, if the message is outgoing -//@can_be_edited True, if the message can be edited. For live location and poll messages this fields shows, whether editMessageLiveLocation or stopPoll can be used with this message by the client +//@can_be_edited True, if the message can be edited. For live location and poll messages this fields shows whether editMessageLiveLocation or stopPoll can be used with this message by the client //@can_be_forwarded True, if the message can be forwarded //@can_be_deleted_only_for_self True, if the message can be deleted only for the current user while other users will continue to see it //@can_be_deleted_for_all_users True, if the message can be deleted for all users @@ -667,7 +667,7 @@ chatActionBarReportAddBlock = ChatActionBar; //@description The chat is a private or a secret chat and the other user can be added to the contact list using the method addContact chatActionBarAddContact = ChatActionBar; -//@description The chat is a private or a secret chat and the phone number can be shared with the other user using the method sharePhoneNumber +//@description The chat is a private or a secret chat with a mutual contact and the user's phone number can be shared with the other user using the method sharePhoneNumber chatActionBarSharePhoneNumber = ChatActionBar; @@ -2730,7 +2730,7 @@ updateNotificationGroup notification_group_id:int32 type:NotificationGroupType c //@description Contains active notifications that was shown on previous application launches. This update is sent only if a message database is used. In that case it comes once before any updateNotification and updateNotificationGroup update @groups Lists of active notification groups updateActiveNotifications groups:vector = Update; -//@description Describes, whether there are some pending notification updates. Can be used to prevent application from killing, while there are some pending notifications +//@description Describes whether there are some pending notification updates. Can be used to prevent application from killing, while there are some pending notifications //@have_delayed_notifications True, if there are some delayed notification updates, which will be sent soon //@have_unreceived_notifications True, if there can be some yet unreceived notifications, which are being fetched from the server updateHavePendingNotifications have_delayed_notifications:Bool have_unreceived_notifications:Bool = Update; @@ -2837,7 +2837,7 @@ updateNewInlineQuery id:int64 sender_user_id:int32 user_location:location query: //@description The user has chosen a result of an inline query; for bots only @sender_user_id Identifier of the user who sent the query @user_location User location, provided by the client; may be null @query Text of the query @result_id Identifier of the chosen result @inline_message_id Identifier of the sent inline message, if known updateNewChosenInlineResult sender_user_id:int32 user_location:location query:string result_id:string inline_message_id:string = Update; -//@description A new incoming callback query; for bots only @id Unique query identifier @sender_user_id Identifier of the user who sent the query @chat_id Identifier of the chat, in which the query was sent +//@description A new incoming callback query; for bots only @id Unique query identifier @sender_user_id Identifier of the user who sent the query @chat_id Identifier of the chat where the query was sent //@message_id Identifier of the message, from which the query originated @chat_instance Identifier that uniquely corresponds to the chat to which the message was sent @payload Query payload updateNewCallbackQuery id:int64 sender_user_id:int32 chat_id:int53 message_id:int53 chat_instance:int64 payload:CallbackQueryPayload = Update; @@ -3302,7 +3302,7 @@ getLoginUrl chat_id:int53 message_id:int53 button_id:int32 allow_write_access:Bo //@description Sends an inline query to a bot and returns its results. Returns an error with code 502 if the bot fails to answer the query before the query timeout expires @bot_user_id The identifier of the target bot -//@chat_id Identifier of the chat, where the query was sent @user_location Location of the user, only if needed @query Text of the query @offset Offset of the first entry to return +//@chat_id Identifier of the chat where the query was sent @user_location Location of the user, only if needed @query Text of the query @offset Offset of the first entry to return getInlineQueryResults bot_user_id:int32 chat_id:int53 user_location:location query:string offset:string = InlineQueryResults; //@description Sets the result of an inline query; for bots only @inline_query_id Identifier of the inline query @is_personal True, if the result of the query can be cached for the specified user @@ -3599,6 +3599,10 @@ changeImportedContacts contacts:vector = ImportedContacts; clearImportedContacts = Ok; +//@description Shares a phone number of the current user with a mutual contact. Supposed to be called when the user clicks on chatActionBarSharePhoneNumber @user_id Identifier of the user with whom to share the phone number. The user must be a mutual contact +sharePhoneNumber user_id:int32 = Ok; + + //@description Returns the profile photos of a user. The result of this query may be outdated: some photos might have been deleted already @user_id User identifier @offset The number of photos to skip; must be non-negative @limit Maximum number of photos to be returned; up to 100 getUserProfilePhotos user_id:int32 offset:int32 limit:int32 = UserProfilePhotos; diff --git a/td/generate/scheme/td_api.tlo b/td/generate/scheme/td_api.tlo index f522c64e..e9c255dc 100644 Binary files a/td/generate/scheme/td_api.tlo and b/td/generate/scheme/td_api.tlo differ diff --git a/td/generate/scheme/telegram_api.tl b/td/generate/scheme/telegram_api.tl index f194ced8..3dc1c681 100644 --- a/td/generate/scheme/telegram_api.tl +++ b/td/generate/scheme/telegram_api.tl @@ -1153,6 +1153,7 @@ contacts.resetSaved#879537f1 = Bool; contacts.getSaved#82f1e39f = Vector; contacts.toggleTopPeers#8514bdda enabled:Bool = Bool; contacts.addContact#e8f463d0 flags:# add_phone_privacy_exception:flags.0?true id:InputUser first_name:string last_name:string phone:string = Updates; +contacts.acceptContact#f831a20f id:InputUser = Updates; contacts.getLocated#a356056 geo_point:InputGeoPoint = Updates; messages.getMessages#63c66506 id:Vector = messages.Messages; diff --git a/td/generate/scheme/telegram_api.tlo b/td/generate/scheme/telegram_api.tlo index 672e48dd..bf7a8eae 100644 Binary files a/td/generate/scheme/telegram_api.tlo and b/td/generate/scheme/telegram_api.tlo differ diff --git a/td/telegram/ContactsManager.cpp b/td/telegram/ContactsManager.cpp index 2af354a9..872f43b8 100644 --- a/td/telegram/ContactsManager.cpp +++ b/td/telegram/ContactsManager.cpp @@ -490,13 +490,15 @@ class GetContactsStatusesQuery : public Td::ResultHandler { class AddContactQuery : public Td::ResultHandler { Promise promise_; + UserId user_id_; public: explicit AddContactQuery(Promise &&promise) : promise_(std::move(promise)) { } - void send(tl_object_ptr &&input_user, const string &first_name, const string &last_name, - const string &phone_number, bool share_phone_number) { + void send(UserId user_id, tl_object_ptr &&input_user, const string &first_name, + const string &last_name, const string &phone_number, bool share_phone_number) { + user_id_ = user_id; int32 flags = 0; if (share_phone_number) { flags |= telegram_api::contacts_addContact::ADD_PHONE_PRIVACY_EXCEPTION_MASK; @@ -521,6 +523,41 @@ class AddContactQuery : public Td::ResultHandler { void on_error(uint64 id, Status status) override { promise_.set_error(std::move(status)); td->contacts_manager_->reload_contacts(true); + td->messages_manager_->repair_dialog_action_bar(DialogId(user_id_)); + } +}; + +class AcceptContactQuery : public Td::ResultHandler { + Promise promise_; + UserId user_id_; + + public: + explicit AcceptContactQuery(Promise &&promise) : promise_(std::move(promise)) { + } + + void send(UserId user_id, tl_object_ptr &&input_user) { + user_id_ = user_id; + send_query( + G()->net_query_creator().create(create_storer(telegram_api::contacts_acceptContact(std::move(input_user))))); + } + + void on_result(uint64 id, BufferSlice packet) override { + auto result_ptr = fetch_result(packet); + if (result_ptr.is_error()) { + return on_error(id, result_ptr.move_as_error()); + } + + auto ptr = result_ptr.move_as_ok(); + LOG(INFO) << "Receive result for AcceptContactQuery: " << to_string(ptr); + td->updates_manager_->on_get_updates(std::move(ptr)); + + promise_.set_value(Unit()); + } + + void on_error(uint64 id, Status status) override { + promise_.set_error(std::move(status)); + td->contacts_manager_->reload_contacts(true); + td->messages_manager_->repair_dialog_action_bar(DialogId(user_id_)); } }; @@ -3988,7 +4025,7 @@ void ContactsManager::add_contact(td_api::object_ptr &&contact, } td_->create_handler(std::move(promise)) - ->send(std::move(input_user), contact->first_name_, contact->last_name_, contact->phone_number_, + ->send(user_id, std::move(input_user), contact->first_name_, contact->last_name_, contact->phone_number_, share_phone_number); } @@ -4384,6 +4421,30 @@ std::pair> ContactsManager::search_contacts(const string & return {narrow_cast(result.first), std::move(user_ids)}; } +void ContactsManager::share_phone_number(UserId user_id, Promise &&promise) { + if (G()->close_flag()) { + return promise.set_error(Status::Error(500, "Request aborted")); + } + + if (!are_contacts_loaded_) { + load_contacts(PromiseCreator::lambda( + [actor_id = actor_id(this), user_id, promise = std::move(promise)](Result &&) mutable { + send_closure(actor_id, &ContactsManager::share_phone_number, user_id, std::move(promise)); + })); + return; + } + + LOG(INFO) << "Share phone number with " << user_id; + auto input_user = get_input_user(user_id); + if (input_user == nullptr) { + return promise.set_error(Status::Error(3, "User not found")); + } + + td_->messages_manager_->hide_dialog_action_bar(DialogId(user_id)); + + td_->create_handler(std::move(promise))->send(user_id, std::move(input_user)); +} + void ContactsManager::set_profile_photo(const tl_object_ptr &input_photo, Promise &&promise) { auto r_file_id = td_->file_manager_->get_input_file_id(FileType::Photo, input_photo, DialogId(get_my_id()), false, false); diff --git a/td/telegram/ContactsManager.h b/td/telegram/ContactsManager.h index 62c58820..00b67436 100644 --- a/td/telegram/ContactsManager.h +++ b/td/telegram/ContactsManager.h @@ -280,6 +280,8 @@ class ContactsManager : public Actor { void on_update_contacts_reset(); + void share_phone_number(UserId user_id, Promise &&promise); + void set_profile_photo(const tl_object_ptr &input_photo, Promise &&promise); void delete_profile_photo(int64 profile_photo_id, Promise &&promise); diff --git a/td/telegram/MessagesManager.cpp b/td/telegram/MessagesManager.cpp index 5749a729..c8b11f99 100644 --- a/td/telegram/MessagesManager.cpp +++ b/td/telegram/MessagesManager.cpp @@ -3249,6 +3249,7 @@ class UpdatePeerSettingsQuery : public Td::ResultHandler { void on_error(uint64 id, Status status) override { LOG(INFO) << "Receive error for update peer settings: " << status; td->messages_manager_->on_get_dialog_error(dialog_id_, status, "UpdatePeerSettingsQuery"); + td->messages_manager_->repair_dialog_action_bar(dialog_id_); promise_.set_error(std::move(status)); } }; @@ -3289,6 +3290,8 @@ class ReportEncryptedSpamQuery : public Td::ResultHandler { void on_error(uint64 id, Status status) override { LOG(INFO) << "Receive error for report encrypted spam: " << status; td->messages_manager_->on_get_dialog_error(dialog_id_, status, "ReportEncryptedSpamQuery"); + td->messages_manager_->repair_dialog_action_bar( + DialogId(td->contacts_manager_->get_secret_chat_user_id(dialog_id_.get_secret_chat_id()))); promise_.set_error(std::move(status)); } }; @@ -3337,6 +3340,7 @@ class ReportPeerQuery : public Td::ResultHandler { void on_error(uint64 id, Status status) override { LOG(INFO) << "Receive error for report peer: " << status; td->messages_manager_->on_get_dialog_error(dialog_id_, status, "ReportPeerQuery"); + td->messages_manager_->repair_dialog_action_bar(dialog_id_); promise_.set_error(std::move(status)); } }; @@ -6454,8 +6458,19 @@ void MessagesManager::repair_dialog_action_bar(DialogId dialog_id) { } } +void MessagesManager::hide_dialog_action_bar(DialogId dialog_id) { + Dialog *d = get_dialog_force(dialog_id); + if (d == nullptr) { + return; + } + hide_dialog_action_bar(d); +} + void MessagesManager::hide_dialog_action_bar(Dialog *d) { CHECK(d->dialog_id.get_type() != DialogType::SecretChat); + if (!d->know_can_report_spam) { + return; + } if (!d->can_report_spam && !d->can_add_contact && !d->can_block_user && !d->can_share_phone_number && !d->can_report_location) { return; diff --git a/td/telegram/MessagesManager.h b/td/telegram/MessagesManager.h index c07a7583..21204759 100644 --- a/td/telegram/MessagesManager.h +++ b/td/telegram/MessagesManager.h @@ -663,8 +663,12 @@ class MessagesManager : public Actor { void on_update_scope_notify_settings(NotificationSettingsScope scope, tl_object_ptr &&peer_notify_settings); + void hide_dialog_action_bar(DialogId dialog_id); + void remove_dialog_action_bar(DialogId dialog_id, Promise &&promise); + void repair_dialog_action_bar(DialogId dialog_id); + void report_dialog(DialogId dialog_id, const tl_object_ptr &reason, const vector &message_ids, Promise &&promise); @@ -1630,8 +1634,6 @@ class MessagesManager : public Actor { void load_messages(DialogId dialog_id, MessageId from_message_id, int32 offset, int32 limit, int left_tries, bool only_local, Promise &&promise); - void repair_dialog_action_bar(DialogId dialog_id); - static int32 get_random_y(MessageId message_id); bool is_allowed_useless_update(const tl_object_ptr &update) const; diff --git a/td/telegram/Td.cpp b/td/telegram/Td.cpp index 16991ffc..1d877740 100644 --- a/td/telegram/Td.cpp +++ b/td/telegram/Td.cpp @@ -6377,6 +6377,12 @@ void Td::on_request(uint64 id, const td_api::clearImportedContacts &request) { contacts_manager_->clear_imported_contacts(std::move(promise)); } +void Td::on_request(uint64 id, const td_api::sharePhoneNumber &request) { + CHECK_IS_USER(); + CREATE_OK_REQUEST_PROMISE(); + contacts_manager_->share_phone_number(UserId(request.user_id_), std::move(promise)); +} + void Td::on_request(uint64 id, const td_api::getRecentInlineBots &request) { CHECK_IS_USER(); CREATE_NO_ARGS_REQUEST(GetRecentInlineBotsRequest); diff --git a/td/telegram/Td.h b/td/telegram/Td.h index 36acc5bf..eb7d666e 100644 --- a/td/telegram/Td.h +++ b/td/telegram/Td.h @@ -742,6 +742,8 @@ class Td final : public NetQueryCallback { void on_request(uint64 id, const td_api::clearImportedContacts &request); + void on_request(uint64 id, const td_api::sharePhoneNumber &request); + void on_request(uint64 id, const td_api::getRecentInlineBots &request); void on_request(uint64 id, td_api::setName &request); diff --git a/td/telegram/cli.cpp b/td/telegram/cli.cpp index b0dc6439..6f15d52c 100644 --- a/td/telegram/cli.cpp +++ b/td/telegram/cli.cpp @@ -1606,6 +1606,10 @@ class CliClient final : public Actor { send_request(td_api::make_object( td_api::make_object(string(), first_name, last_name, string(), as_user_id(user_id)), false)); + } else if (op == "spn") { + string user_id = args; + + send_request(td_api::make_object(as_user_id(user_id))); } else if (op == "ImportContacts" || op == "cic") { vector contacts_str = full_split(args, ';'); vector> contacts;