diff --git a/td/generate/scheme/td_api.tl b/td/generate/scheme/td_api.tl index d0f40c8ea..65b05afd5 100644 --- a/td/generate/scheme/td_api.tl +++ b/td/generate/scheme/td_api.tl @@ -4005,6 +4005,9 @@ setChatNotificationSettings chat_id:int53 notification_settings:chatNotification //@description Changes the marked as unread state of a chat @chat_id Chat identifier @is_marked_as_unread New value of is_marked_as_unread toggleChatIsMarkedAsUnread chat_id:int53 is_marked_as_unread:Bool = Ok; +//@description Changes the block state of a chat @chat_id Chat identifier @is_blocked New value of is_blocked +toggleChatIsBlocked chat_id:int53 is_blocked:Bool = Ok; + //@description Changes the value of the default disable_notification parameter, used when a message is sent to a chat @chat_id Chat identifier @default_disable_notification New value of default_disable_notification toggleChatDefaultDisableNotification chat_id:int53 default_disable_notification:Bool = Ok; @@ -4169,12 +4172,6 @@ sendCallDebugInformation call_id:int32 debug_information:string = Ok; -//@description Blocks a user @user_id User identifier -blockUser user_id:int32 = Ok; - -//@description Unblocks a user @user_id User identifier -unblockUser user_id:int32 = Ok; - //@description Returns users that were blocked by the current user @offset Number of users to skip in the result; must be non-negative @limit The maximum number of users to return; up to 100 getBlockedUsers offset:int32 limit:int32 = Users; diff --git a/td/generate/scheme/td_api.tlo b/td/generate/scheme/td_api.tlo index 6098f140e..74b862aab 100644 Binary files a/td/generate/scheme/td_api.tlo and b/td/generate/scheme/td_api.tlo differ diff --git a/td/telegram/ContactsManager.cpp b/td/telegram/ContactsManager.cpp index 8408b47f4..2ab2a767f 100644 --- a/td/telegram/ContactsManager.cpp +++ b/td/telegram/ContactsManager.cpp @@ -349,43 +349,6 @@ class ResetWebAuthorizationsQuery : public Td::ResultHandler { } }; -class SetUserIsBlockedQuery : public Td::ResultHandler { - Promise promise_; - UserId user_id_; - - public: - explicit SetUserIsBlockedQuery(Promise &&promise) : promise_(std::move(promise)) { - } - - void send(UserId user_id, tl_object_ptr &&input_user, bool is_blocked) { - user_id_ = user_id; - auto input_peer = td->contacts_manager_->get_input_peer_user(user_id, AccessRights::Read); - if (is_blocked) { - send_query(G()->net_query_creator().create(telegram_api::contacts_block(std::move(input_peer)))); - } else { - send_query(G()->net_query_creator().create(telegram_api::contacts_unblock(std::move(input_peer)))); - } - } - - void on_result(uint64 id, BufferSlice packet) override { - static_assert( - std::is_same::value, ""); - auto result_ptr = fetch_result(packet); - if (result_ptr.is_error()) { - return on_error(id, result_ptr.move_as_error()); - } - - bool result = result_ptr.ok(); - LOG_IF(WARNING, !result) << "Block/Unblock " << user_id_ << " has failed"; - - promise_.set_value(Unit()); - } - - void on_error(uint64 id, Status status) override { - promise_.set_error(std::move(status)); - } -}; - class GetBlockedUsersQuery : public Td::ResultHandler { Promise promise_; int32 offset_; @@ -4643,36 +4606,6 @@ void ContactsManager::disconnect_all_websites(Promise &&promise) const { td_->create_handler(std::move(promise))->send(); } -Status ContactsManager::set_user_is_blocked(UserId user_id, bool is_blocked) { - if (user_id == get_my_id()) { - return Status::Error(5, is_blocked ? Slice("Can't block self") : Slice("Can't unblock self")); - } - - auto input_user = get_input_user(user_id); - if (input_user == nullptr) { - return Status::Error(5, "User not found"); - } - - auto query_promise = PromiseCreator::lambda([actor_id = actor_id(this), user_id, is_blocked](Result result) { - if (!G()->close_flag() && result.is_error()) { - send_closure(actor_id, &ContactsManager::on_set_user_is_blocked_failed, user_id, is_blocked, - result.move_as_error()); - } - }); - td_->create_handler(std::move(query_promise)) - ->send(user_id, std::move(input_user), is_blocked); - - td_->messages_manager_->on_update_dialog_is_blocked(DialogId(user_id), is_blocked); - return Status::OK(); -} - -void ContactsManager::on_set_user_is_blocked_failed(UserId user_id, bool is_blocked, Status error) { - LOG(WARNING) << "Receive error for SetUserIsBlockedQuery: " << error; - td_->messages_manager_->on_update_dialog_is_blocked(DialogId(user_id), !is_blocked); - reload_user_full(user_id); - td_->messages_manager_->reget_dialog_action_bar(DialogId(user_id), "on_set_user_is_blocked_failed"); -} - bool ContactsManager::is_valid_username(const string &username) { if (username.size() < 5 || username.size() > 32) { return false; diff --git a/td/telegram/ContactsManager.h b/td/telegram/ContactsManager.h index 43e1b75ea..49c3a12b4 100644 --- a/td/telegram/ContactsManager.h +++ b/td/telegram/ContactsManager.h @@ -290,8 +290,6 @@ class ContactsManager : public Actor { void disconnect_website(int64 authorizations_id, Promise &&promise) const; void disconnect_all_websites(Promise &&promise) const; - Status set_user_is_blocked(UserId user_id, bool is_blocked); - int64 get_blocked_users(int32 offset, int32 limit, Promise &&promise); void on_get_blocked_users_result(int32 offset, int32 limit, int64 random_id, int32 total_count, @@ -1161,8 +1159,6 @@ class ContactsManager : public Actor { void drop_user_photos(UserId user_id, bool is_empty, bool drop_user_full_photo, const char *source); void drop_user_full(UserId user_id); - void on_set_user_is_blocked_failed(UserId user_id, bool is_blocked, Status error); - void on_update_chat_status(Chat *c, ChatId chat_id, DialogParticipantStatus status); void on_update_chat_default_permissions(Chat *c, ChatId chat_id, RestrictedRights default_permissions, int32 version); void on_update_chat_participant_count(Chat *c, ChatId chat_id, int32 participant_count, int32 version, diff --git a/td/telegram/MessagesManager.cpp b/td/telegram/MessagesManager.cpp index e28cffd13..14c50dc0c 100644 --- a/td/telegram/MessagesManager.cpp +++ b/td/telegram/MessagesManager.cpp @@ -1341,7 +1341,58 @@ class ToggleDialogUnreadMarkQuery : public Td::ResultHandler { if (!td->messages_manager_->on_get_dialog_error(dialog_id_, status, "ToggleDialogUnreadMarkQuery")) { LOG(ERROR) << "Receive error for ToggleDialogUnreadMarkQuery: " << status; } - td->messages_manager_->on_update_dialog_is_marked_as_unread(dialog_id_, !is_marked_as_unread_); + if (!G()->close_flag()) { + td->messages_manager_->on_update_dialog_is_marked_as_unread(dialog_id_, !is_marked_as_unread_); + } + promise_.set_error(std::move(status)); + } +}; + +class ToggleDialogIsBlockedQuery : public Td::ResultHandler { + Promise promise_; + DialogId dialog_id_; + bool is_blocked_; + + public: + explicit ToggleDialogIsBlockedQuery(Promise &&promise) : promise_(std::move(promise)) { + } + + void send(DialogId dialog_id, bool is_blocked) { + dialog_id_ = dialog_id; + is_blocked_ = is_blocked; + + auto input_peer = MessagesManager::get_input_peer_force(dialog_id); + CHECK(input_peer != nullptr && input_peer->get_id() != telegram_api::inputPeerEmpty::ID); + if (is_blocked) { + send_query(G()->net_query_creator().create(telegram_api::contacts_block(std::move(input_peer)))); + } else { + send_query(G()->net_query_creator().create(telegram_api::contacts_unblock(std::move(input_peer)))); + } + } + + void on_result(uint64 id, BufferSlice packet) override { + static_assert( + std::is_same::value, ""); + auto result_ptr = fetch_result(packet); + if (result_ptr.is_error()) { + return on_error(id, result_ptr.move_as_error()); + } + + bool result = result_ptr.ok(); + LOG_IF(WARNING, !result) << "Block/Unblock " << dialog_id_ << " has failed"; + + promise_.set_value(Unit()); + } + + void on_error(uint64 id, Status status) override { + if (!td->messages_manager_->on_get_dialog_error(dialog_id_, status, "ToggleDialogIsBlockedQuery")) { + LOG(ERROR) << "Receive error for ToggleDialogIsBlockedQuery: " << status; + } + if (!G()->close_flag()) { + td->messages_manager_->on_update_dialog_is_blocked(dialog_id_, !is_blocked_); + td->messages_manager_->get_dialog_info_full(dialog_id_, Auto()); + td->messages_manager_->reget_dialog_action_bar(dialog_id_, "ToggleDialogIsBlockedQuery"); + } promise_.set_error(std::move(status)); } }; @@ -17550,6 +17601,75 @@ void MessagesManager::toggle_dialog_is_marked_as_unread_on_server(DialogId dialo ->send(dialog_id, is_marked_as_unread); } +Status MessagesManager::toggle_dialog_is_blocked(DialogId dialog_id, bool is_blocked) { + Dialog *d = get_dialog_force(dialog_id); + if (d == nullptr) { + return Status::Error(6, "Chat not found"); + } + if (dialog_id.get_type() == DialogType::SecretChat) { + auto user_id = td_->contacts_manager_->get_secret_chat_user_id(dialog_id.get_secret_chat_id()); + dialog_id = DialogId(user_id); + d = get_dialog_force(dialog_id); + if (d == nullptr) { + return Status::Error(6, "Chat info not found"); + } + } + if (dialog_id == get_my_dialog_id()) { + return Status::Error(5, is_blocked ? Slice("Can't block self") : Slice("Can't unblock self")); + } + + if (is_blocked == d->is_blocked) { + return Status::OK(); + } + set_dialog_is_blocked(d, is_blocked); + + toggle_dialog_is_blocked_on_server(dialog_id, is_blocked, 0); + return Status::OK(); +} + +class MessagesManager::ToggleDialogIsBlockedOnServerLogEvent { + public: + DialogId dialog_id_; + bool is_blocked_; + + template + void store(StorerT &storer) const { + BEGIN_STORE_FLAGS(); + STORE_FLAG(is_blocked_); + END_STORE_FLAGS(); + + td::store(dialog_id_, storer); + } + + template + void parse(ParserT &parser) { + BEGIN_PARSE_FLAGS(); + PARSE_FLAG(is_blocked_); + END_PARSE_FLAGS(); + + td::parse(dialog_id_, parser); + } +}; + +uint64 MessagesManager::save_toggle_dialog_is_blocked_on_server_logevent(DialogId dialog_id, bool is_blocked) { + ToggleDialogIsBlockedOnServerLogEvent logevent{dialog_id, is_blocked}; + auto storer = LogEventStorerImpl(logevent); + return binlog_add(G()->td_db()->get_binlog(), LogEvent::HandlerType::ToggleDialogIsBlockedOnServer, storer); +} + +void MessagesManager::toggle_dialog_is_blocked_on_server(DialogId dialog_id, bool is_blocked, uint64 logevent_id) { + if (logevent_id == 0 && dialog_id.get_type() == DialogType::SecretChat) { + // don't even create new binlog events + return; + } + + if (logevent_id == 0 && G()->parameters().use_message_db) { + logevent_id = save_toggle_dialog_is_blocked_on_server_logevent(dialog_id, is_blocked); + } + + td_->create_handler(get_erase_logevent_promise(logevent_id))->send(dialog_id, is_blocked); +} + Status MessagesManager::toggle_dialog_silent_send_message(DialogId dialog_id, bool silent_send_message) { CHECK(!td_->auth_manager_->is_bot()); @@ -34126,6 +34246,25 @@ void MessagesManager::on_binlog_events(vector &&events) { toggle_dialog_is_marked_as_unread_on_server(dialog_id, log_event.is_marked_as_unread_, event.id_); break; } + case LogEvent::HandlerType::ToggleDialogIsBlockedOnServer: { + if (!G()->parameters().use_message_db) { + binlog_erase(G()->td_db()->get_binlog(), event.id_); + break; + } + + ToggleDialogIsBlockedOnServerLogEvent log_event; + log_event_parse(log_event, event.data_).ensure(); + + auto dialog_id = log_event.dialog_id_; + Dialog *d = get_dialog_force(dialog_id); + if (d == nullptr || !have_input_peer(dialog_id, AccessRights::Read)) { + binlog_erase(G()->td_db()->get_binlog(), event.id_); + break; + } + + toggle_dialog_is_blocked_on_server(dialog_id, log_event.is_blocked_, event.id_); + break; + } case LogEvent::HandlerType::SaveDialogDraftMessageOnServer: { if (!G()->parameters().use_message_db) { binlog_erase(G()->td_db()->get_binlog(), event.id_); diff --git a/td/telegram/MessagesManager.h b/td/telegram/MessagesManager.h index 1d0418558..801d1631b 100644 --- a/td/telegram/MessagesManager.h +++ b/td/telegram/MessagesManager.h @@ -622,6 +622,8 @@ class MessagesManager : public Actor { Status toggle_dialog_is_marked_as_unread(DialogId dialog_id, bool is_marked_as_unread) TD_WARN_UNUSED_RESULT; + Status toggle_dialog_is_blocked(DialogId dialog_id, bool is_blocked) TD_WARN_UNUSED_RESULT; + Status toggle_dialog_silent_send_message(DialogId dialog_id, bool silent_send_message) TD_WARN_UNUSED_RESULT; Status set_pinned_dialogs(DialogListId dialog_list_id, vector dialog_ids) TD_WARN_UNUSED_RESULT; @@ -1599,6 +1601,7 @@ class MessagesManager : public Actor { class SetDialogFolderIdOnServerLogEvent; class ToggleDialogIsPinnedOnServerLogEvent; class ToggleDialogIsMarkedAsUnreadOnServerLogEvent; + class ToggleDialogIsBlockedOnServerLogEvent; class UpdateDialogNotificationSettingsOnServerLogEvent; class UpdateScopeNotificationSettingsOnServerLogEvent; @@ -2252,6 +2255,8 @@ class MessagesManager : public Actor { void toggle_dialog_is_marked_as_unread_on_server(DialogId dialog_id, bool is_marked_as_unread, uint64 logevent_id); + void toggle_dialog_is_blocked_on_server(DialogId dialog_id, bool is_blocked, uint64 logevent_id); + void reorder_pinned_dialogs_on_server(FolderId folder_id, const vector &dialog_ids, uint64 logevent_id); void set_dialog_reply_markup(Dialog *d, MessageId message_id); @@ -2822,6 +2827,8 @@ class MessagesManager : public Actor { uint64 save_toggle_dialog_is_marked_as_unread_on_server_logevent(DialogId dialog_id, bool is_marked_as_unread); + uint64 save_toggle_dialog_is_blocked_on_server_logevent(DialogId dialog_id, bool is_blocked); + uint64 save_read_message_contents_on_server_logevent(DialogId dialog_id, const vector &message_ids); uint64 save_update_scope_notification_settings_on_server_logevent(NotificationSettingsScope scope); diff --git a/td/telegram/Td.cpp b/td/telegram/Td.cpp index f2a2e3529..74c1f8d11 100644 --- a/td/telegram/Td.cpp +++ b/td/telegram/Td.cpp @@ -6050,6 +6050,11 @@ void Td::on_request(uint64 id, const td_api::toggleChatIsMarkedAsUnread &request request.is_marked_as_unread_)); } +void Td::on_request(uint64 id, const td_api::toggleChatIsBlocked &request) { + CHECK_IS_USER(); + answer_ok_query(id, messages_manager_->toggle_dialog_is_blocked(DialogId(request.chat_id_), request.is_blocked_)); +} + void Td::on_request(uint64 id, const td_api::toggleChatDefaultDisableNotification &request) { CHECK_IS_USER(); answer_ok_query(id, messages_manager_->toggle_dialog_silent_send_message(DialogId(request.chat_id_), @@ -6373,16 +6378,6 @@ void Td::on_request(uint64 id, const td_api::deleteFile &request) { "td_api::deleteFile"); } -void Td::on_request(uint64 id, const td_api::blockUser &request) { - CHECK_IS_USER(); - answer_ok_query(id, contacts_manager_->set_user_is_blocked(UserId(request.user_id_), true)); -} - -void Td::on_request(uint64 id, const td_api::unblockUser &request) { - CHECK_IS_USER(); - answer_ok_query(id, contacts_manager_->set_user_is_blocked(UserId(request.user_id_), false)); -} - void Td::on_request(uint64 id, const td_api::getBlockedUsers &request) { CHECK_IS_USER(); CREATE_REQUEST(GetBlockedUsersRequest, request.offset_, request.limit_); diff --git a/td/telegram/Td.h b/td/telegram/Td.h index b6a9504df..68f033ba1 100644 --- a/td/telegram/Td.h +++ b/td/telegram/Td.h @@ -714,6 +714,8 @@ class Td final : public NetQueryCallback { void on_request(uint64 id, const td_api::toggleChatIsMarkedAsUnread &request); + void on_request(uint64 id, const td_api::toggleChatIsBlocked &request); + void on_request(uint64 id, const td_api::toggleChatDefaultDisableNotification &request); void on_request(uint64 id, const td_api::setPinnedChats &request); @@ -782,10 +784,6 @@ class Td final : public NetQueryCallback { void on_request(uint64 id, const td_api::deleteFile &request); - void on_request(uint64 id, const td_api::blockUser &request); - - void on_request(uint64 id, const td_api::unblockUser &request); - void on_request(uint64 id, const td_api::getBlockedUsers &request); void on_request(uint64 id, td_api::addContact &request); diff --git a/td/telegram/TdDb.cpp b/td/telegram/TdDb.cpp index ded847c0e..2f1cf18d2 100644 --- a/td/telegram/TdDb.cpp +++ b/td/telegram/TdDb.cpp @@ -112,6 +112,7 @@ Status init_binlog(Binlog &binlog, string path, BinlogKeyValue &binlog_p case LogEvent::HandlerType::ToggleDialogIsMarkedAsUnreadOnServer: case LogEvent::HandlerType::SetDialogFolderIdOnServer: case LogEvent::HandlerType::DeleteScheduledMessagesFromServer: + case LogEvent::HandlerType::ToggleDialogIsBlockedOnServer: events.to_messages_manager.push_back(event.clone()); break; case LogEvent::HandlerType::AddMessagePushNotification: diff --git a/td/telegram/cli.cpp b/td/telegram/cli.cpp index 6027c6b2d..603e40547 100644 --- a/td/telegram/cli.cpp +++ b/td/telegram/cli.cpp @@ -2293,10 +2293,6 @@ class CliClient final : public Actor { send_request(td_api::make_object(args)); } else if (op == "tme") { send_request(td_api::make_object(args)); - } else if (op == "bu") { - send_request(td_api::make_object(as_user_id(args))); - } else if (op == "ubu") { - send_request(td_api::make_object(as_user_id(args))); } else if (op == "gbu") { string offset; string limit; @@ -2915,12 +2911,17 @@ class CliClient final : public Actor { std::tie(chat_id, is_pinned) = split(args); send_request( td_api::make_object(as_chat_list(op), as_chat_id(chat_id), as_bool(is_pinned))); - } else if (op == "tcimar") { + } else if (op == "tcimau") { string chat_id; string is_marked_as_read; std::tie(chat_id, is_marked_as_read) = split(args); send_request( td_api::make_object(as_chat_id(chat_id), as_bool(is_marked_as_read))); + } else if (op == "tcib") { + string chat_id; + string is_blocked; + std::tie(chat_id, is_blocked) = split(args); + send_request(td_api::make_object(as_chat_id(chat_id), as_bool(is_blocked))); } else if (op == "tcddn") { string chat_id; string default_disable_notification; diff --git a/td/telegram/logevent/LogEvent.h b/td/telegram/logevent/LogEvent.h index dd0fa076b..6b843b1d1 100644 --- a/td/telegram/logevent/LogEvent.h +++ b/td/telegram/logevent/LogEvent.h @@ -96,6 +96,7 @@ class LogEvent { ToggleDialogIsMarkedAsUnreadOnServer = 0x115, SetDialogFolderIdOnServer = 0x116, DeleteScheduledMessagesFromServer = 0x117, + ToggleDialogIsBlockedOnServer = 0x118, GetChannelDifference = 0x140, AddMessagePushNotification = 0x200, EditMessagePushNotification = 0x201,