diff --git a/CMakeLists.txt b/CMakeLists.txt index 8ff8afb9c..3faec5b54 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -372,6 +372,7 @@ set(TDLIB_SOURCE td/telegram/PollManager.cpp td/telegram/QueryCombiner.cpp td/telegram/ReplyMarkup.cpp + td/telegram/ReportReason.cpp td/telegram/RestrictionReason.cpp td/telegram/SecretChatActor.cpp td/telegram/SecretChatDb.cpp @@ -566,6 +567,7 @@ set(TDLIB_SOURCE td/telegram/PublicDialogType.h td/telegram/QueryCombiner.h td/telegram/ReplyMarkup.h + td/telegram/ReportReason.h td/telegram/RequestActor.h td/telegram/RestrictionReason.h td/telegram/ScheduledServerMessageId.h diff --git a/td/telegram/MessagesManager.cpp b/td/telegram/MessagesManager.cpp index e7974da4a..45ec84eaa 100644 --- a/td/telegram/MessagesManager.cpp +++ b/td/telegram/MessagesManager.cpp @@ -4388,20 +4388,19 @@ class ReportPeerQuery : public Td::ResultHandler { explicit ReportPeerQuery(Promise &&promise) : promise_(std::move(promise)) { } - void send(DialogId dialog_id, const vector &message_ids, - tl_object_ptr &&report_reason, const string &message) { + void send(DialogId dialog_id, const vector &message_ids, ReportReason &&report_reason) { dialog_id_ = dialog_id; auto input_peer = td->messages_manager_->get_input_peer(dialog_id, AccessRights::Read); CHECK(input_peer != nullptr); if (message_ids.empty()) { - send_query(G()->net_query_creator().create( - telegram_api::account_reportPeer(std::move(input_peer), std::move(report_reason), message))); + send_query(G()->net_query_creator().create(telegram_api::account_reportPeer( + std::move(input_peer), report_reason.get_input_report_reason(), report_reason.get_message()))); } else { send_query(G()->net_query_creator().create( telegram_api::messages_report(std::move(input_peer), MessagesManager::get_server_message_ids(message_ids), - std::move(report_reason), message))); + report_reason.get_input_report_reason(), report_reason.get_message()))); } } @@ -4438,15 +4437,15 @@ class ReportProfilePhotoQuery : public Td::ResultHandler { explicit ReportProfilePhotoQuery(Promise &&promise) : promise_(std::move(promise)) { } - void send(DialogId dialog_id, tl_object_ptr &&input_photo, - tl_object_ptr &&report_reason, const string &message) { + void send(DialogId dialog_id, tl_object_ptr &&input_photo, ReportReason &&report_reason) { dialog_id_ = dialog_id; auto input_peer = td->messages_manager_->get_input_peer(dialog_id, AccessRights::Read); CHECK(input_peer != nullptr); send_query(G()->net_query_creator().create(telegram_api::account_reportProfilePhoto( - std::move(input_peer), std::move(input_photo), std::move(report_reason), message))); + std::move(input_peer), std::move(input_photo), report_reason.get_input_report_reason(), + report_reason.get_message()))); } void on_result(uint64 id, BufferSlice packet) override { @@ -8209,8 +8208,7 @@ bool MessagesManager::can_report_dialog(DialogId dialog_id) const { } } -void MessagesManager::report_dialog(DialogId dialog_id, const vector &message_ids, - const tl_object_ptr &reason, const string &message, +void MessagesManager::report_dialog(DialogId dialog_id, const vector &message_ids, ReportReason &&reason, Promise &&promise) { Dialog *d = get_dialog_force(dialog_id); if (d == nullptr) { @@ -8221,14 +8219,10 @@ void MessagesManager::report_dialog(DialogId dialog_id, const vector return promise.set_error(Status::Error(3, "Can't access the chat")); } - if (reason == nullptr) { - return promise.set_error(Status::Error(3, "Reason must be non-empty")); - } - Dialog *user_d = d; bool is_dialog_spam_report = false; bool can_report_spam = d->can_report_spam; - if (reason->get_id() == td_api::chatReportReasonSpam::ID && message_ids.empty()) { + if (reason.is_spam() && message_ids.empty()) { // report from action bar if (dialog_id.get_type() == DialogType::SecretChat) { auto user_dialog_id = DialogId(td_->contacts_manager_->get_secret_chat_user_id(dialog_id.get_secret_chat_id())); @@ -8267,46 +8261,14 @@ void MessagesManager::report_dialog(DialogId dialog_id, const vector } } - tl_object_ptr report_reason; - switch (reason->get_id()) { - case td_api::chatReportReasonSpam::ID: - report_reason = make_tl_object(); - break; - case td_api::chatReportReasonViolence::ID: - report_reason = make_tl_object(); - break; - case td_api::chatReportReasonPornography::ID: - report_reason = make_tl_object(); - break; - case td_api::chatReportReasonChildAbuse::ID: - report_reason = make_tl_object(); - break; - case td_api::chatReportReasonCopyright::ID: - report_reason = make_tl_object(); - break; - case td_api::chatReportReasonFake::ID: - report_reason = make_tl_object(); - break; - case td_api::chatReportReasonUnrelatedLocation::ID: - report_reason = make_tl_object(); - if (dialog_id.get_type() == DialogType::Channel) { - hide_dialog_action_bar(d); - } - break; - case td_api::chatReportReasonCustom::ID: - report_reason = make_tl_object(); - break; - default: - UNREACHABLE(); + if (dialog_id.get_type() == DialogType::Channel && reason.is_unrelated_location()) { + hide_dialog_action_bar(d); } - CHECK(report_reason != nullptr); - td_->create_handler(std::move(promise)) - ->send(dialog_id, server_message_ids, std::move(report_reason), message); + td_->create_handler(std::move(promise))->send(dialog_id, server_message_ids, std::move(reason)); } -void MessagesManager::report_dialog_photo(DialogId dialog_id, FileId file_id, - const tl_object_ptr &reason, const string &message, +void MessagesManager::report_dialog_photo(DialogId dialog_id, FileId file_id, ReportReason &&reason, Promise &&promise) { Dialog *d = get_dialog_force(dialog_id); if (d == nullptr) { @@ -8317,10 +8279,6 @@ void MessagesManager::report_dialog_photo(DialogId dialog_id, FileId file_id, return promise.set_error(Status::Error(3, "Can't access the chat")); } - if (reason == nullptr) { - return promise.set_error(Status::Error(3, "Reason must be non-empty")); - } - if (!can_report_dialog(dialog_id)) { return promise.set_error(Status::Error(3, "Chat photo can't be reported")); } @@ -8334,42 +8292,8 @@ void MessagesManager::report_dialog_photo(DialogId dialog_id, FileId file_id, return promise.set_error(Status::Error(400, "Only full chat photos can be reported")); } - tl_object_ptr report_reason; - switch (reason->get_id()) { - case td_api::chatReportReasonSpam::ID: - report_reason = make_tl_object(); - break; - case td_api::chatReportReasonViolence::ID: - report_reason = make_tl_object(); - break; - case td_api::chatReportReasonPornography::ID: - report_reason = make_tl_object(); - break; - case td_api::chatReportReasonChildAbuse::ID: - report_reason = make_tl_object(); - break; - case td_api::chatReportReasonCopyright::ID: - report_reason = make_tl_object(); - break; - case td_api::chatReportReasonFake::ID: - report_reason = make_tl_object(); - break; - case td_api::chatReportReasonUnrelatedLocation::ID: - report_reason = make_tl_object(); - if (dialog_id.get_type() == DialogType::Channel) { - hide_dialog_action_bar(d); - } - break; - case td_api::chatReportReasonCustom::ID: - report_reason = make_tl_object(); - break; - default: - UNREACHABLE(); - } - CHECK(report_reason != nullptr); - td_->create_handler(std::move(promise)) - ->send(dialog_id, file_view.remote_location().as_input_photo(), std::move(report_reason), message); + ->send(dialog_id, file_view.remote_location().as_input_photo(), std::move(reason)); } void MessagesManager::on_get_peer_settings(DialogId dialog_id, diff --git a/td/telegram/MessagesManager.h b/td/telegram/MessagesManager.h index 5078f5795..50f6f077e 100644 --- a/td/telegram/MessagesManager.h +++ b/td/telegram/MessagesManager.h @@ -41,6 +41,7 @@ #include "td/telegram/NotificationId.h" #include "td/telegram/NotificationSettings.h" #include "td/telegram/ReplyMarkup.h" +#include "td/telegram/ReportReason.h" #include "td/telegram/RestrictionReason.h" #include "td/telegram/ScheduledServerMessageId.h" #include "td/telegram/SecretChatId.h" @@ -775,12 +776,10 @@ class MessagesManager : public Actor { void reget_dialog_action_bar(DialogId dialog_id, const char *source); - void report_dialog(DialogId dialog_id, const vector &message_ids, - const tl_object_ptr &reason, const string &message, + void report_dialog(DialogId dialog_id, const vector &message_ids, ReportReason &&reason, Promise &&promise); - void report_dialog_photo(DialogId dialog_id, FileId file_id, const tl_object_ptr &reason, - const string &message, Promise &&promise); + void report_dialog_photo(DialogId dialog_id, FileId file_id, ReportReason &&reason, Promise &&promise); void on_get_peer_settings(DialogId dialog_id, tl_object_ptr &&peer_settings, bool ignore_privacy_exception = false); diff --git a/td/telegram/ReportReason.cpp b/td/telegram/ReportReason.cpp new file mode 100644 index 000000000..5d983f67c --- /dev/null +++ b/td/telegram/ReportReason.cpp @@ -0,0 +1,97 @@ +// +// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2021 +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +#include "td/telegram/ReportReason.h" + +#include "td/telegram/misc.h" + +namespace td { + +Result ReportReason::get_report_reason(td_api::object_ptr reason, + string &&message) { + if (!clean_input_string(message)) { + return Status::Error(400, "Report text must be encoded in UTF-8"); + } + if (reason == nullptr) { + return Status::Error(400, "Reason must be non-empty"); + } + + auto type = [&] { + switch (reason->get_id()) { + case td_api::chatReportReasonSpam::ID: + return ReportReason::Type::Spam; + case td_api::chatReportReasonViolence::ID: + return ReportReason::Type::Violence; + case td_api::chatReportReasonPornography::ID: + return ReportReason::Type::Pornography; + case td_api::chatReportReasonChildAbuse::ID: + return ReportReason::Type::ChildAbuse; + case td_api::chatReportReasonCopyright::ID: + return ReportReason::Type::Copyright; + case td_api::chatReportReasonUnrelatedLocation::ID: + return ReportReason::Type::UnrelatedLocation; + case td_api::chatReportReasonFake::ID: + return ReportReason::Type::Fake; + case td_api::chatReportReasonCustom::ID: + return ReportReason::Type::Custom; + default: + UNREACHABLE(); + return ReportReason::Type::Custom; + } + }(); + return ReportReason(type, std::move(message)); +} + +tl_object_ptr ReportReason::get_input_report_reason() const { + switch (type_) { + case ReportReason::Type::Spam: + return make_tl_object(); + case ReportReason::Type::Violence: + return make_tl_object(); + case ReportReason::Type::Pornography: + return make_tl_object(); + case ReportReason::Type::ChildAbuse: + return make_tl_object(); + case ReportReason::Type::Copyright: + return make_tl_object(); + case ReportReason::Type::UnrelatedLocation: + return make_tl_object(); + case ReportReason::Type::Fake: + return make_tl_object(); + case ReportReason::Type::Custom: + return make_tl_object(); + default: + UNREACHABLE(); + return nullptr; + } +} + +StringBuilder &operator<<(StringBuilder &string_builder, const ReportReason &report_reason) { + string_builder << "ReportReason"; + switch (report_reason.type_) { + case ReportReason::Type::Spam: + return string_builder << "Spam"; + case ReportReason::Type::Violence: + return string_builder << "Violence"; + case ReportReason::Type::Pornography: + return string_builder << "Pornography"; + case ReportReason::Type::ChildAbuse: + return string_builder << "ChildAbuse"; + case ReportReason::Type::Copyright: + return string_builder << "Copyright"; + case ReportReason::Type::UnrelatedLocation: + return string_builder << "UnrelatedLocation"; + case ReportReason::Type::Fake: + return string_builder << "Fake"; + case ReportReason::Type::Custom: + return string_builder << "Custom"; + default: + UNREACHABLE(); + } + return string_builder; +} + +} // namespace td diff --git a/td/telegram/ReportReason.h b/td/telegram/ReportReason.h new file mode 100644 index 000000000..edccf287e --- /dev/null +++ b/td/telegram/ReportReason.h @@ -0,0 +1,48 @@ +// +// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2021 +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +#pragma once + +#include "td/telegram/td_api.h" +#include "td/telegram/telegram_api.h" + +#include "td/utils/common.h" +#include "td/utils/Status.h" +#include "td/utils/StringBuilder.h" + +namespace td { + +class ReportReason { + enum class Type : int32 { Spam, Violence, Pornography, ChildAbuse, Copyright, UnrelatedLocation, Fake, Custom }; + Type type_ = Type::Spam; + string message_; + + friend StringBuilder &operator<<(StringBuilder &string_builder, const ReportReason &report_reason); + + ReportReason(Type type, string &&message) : type_(type), message_(std::move(message)) { + } + + public: + static Result get_report_reason(td_api::object_ptr reason, string &&message); + + tl_object_ptr get_input_report_reason() const; + + const string &get_message() const { + return message_; + } + + bool is_spam() const { + return type_ == Type::Spam; + } + + bool is_unrelated_location() const { + return type_ == Type::UnrelatedLocation; + } +}; + +StringBuilder &operator<<(StringBuilder &string_builder, const ReportReason &report_reason); + +} // namespace td diff --git a/td/telegram/Td.cpp b/td/telegram/Td.cpp index 0928d5020..c2c5f24a3 100644 --- a/td/telegram/Td.cpp +++ b/td/telegram/Td.cpp @@ -80,6 +80,7 @@ #include "td/telegram/PollManager.h" #include "td/telegram/PrivacyManager.h" #include "td/telegram/PublicDialogType.h" +#include "td/telegram/ReportReason.h" #include "td/telegram/RequestActor.h" #include "td/telegram/SecretChatId.h" #include "td/telegram/SecretChatsManager.h" @@ -6971,18 +6972,24 @@ void Td::on_request(uint64 id, const td_api::removeChatActionBar &request) { void Td::on_request(uint64 id, td_api::reportChat &request) { CHECK_IS_USER(); - CLEAN_INPUT_STRING(request.text_); + auto r_report_reason = ReportReason::get_report_reason(std::move(request.reason_), std::move(request.text_)); + if (r_report_reason.is_error()) { + return send_error_raw(id, r_report_reason.error().code(), r_report_reason.error().message()); + } CREATE_OK_REQUEST_PROMISE(); messages_manager_->report_dialog(DialogId(request.chat_id_), MessagesManager::get_message_ids(request.message_ids_), - request.reason_, request.text_, std::move(promise)); + r_report_reason.move_as_ok(), std::move(promise)); } void Td::on_request(uint64 id, td_api::reportChatPhoto &request) { CHECK_IS_USER(); - CLEAN_INPUT_STRING(request.text_); + auto r_report_reason = ReportReason::get_report_reason(std::move(request.reason_), std::move(request.text_)); + if (r_report_reason.is_error()) { + return send_error_raw(id, r_report_reason.error().code(), r_report_reason.error().message()); + } CREATE_OK_REQUEST_PROMISE(); - messages_manager_->report_dialog_photo(DialogId(request.chat_id_), FileId(request.file_id_, 0), request.reason_, - request.text_, std::move(promise)); + messages_manager_->report_dialog_photo(DialogId(request.chat_id_), FileId(request.file_id_, 0), + r_report_reason.move_as_ok(), std::move(promise)); } void Td::on_request(uint64 id, td_api::getChatStatisticsUrl &request) { diff --git a/td/telegram/cli.cpp b/td/telegram/cli.cpp index 40813c946..38d233285 100644 --- a/td/telegram/cli.cpp +++ b/td/telegram/cli.cpp @@ -1317,6 +1317,9 @@ class CliClient final : public Actor { static td_api::object_ptr get_chat_report_reason(MutableSlice reason) { reason = trim(reason); + if (reason == "null") { + return nullptr; + } if (reason == "spam") { return td_api::make_object(); } @@ -2544,7 +2547,8 @@ class CliClient final : public Actor { int32 max_file_id = as_file_id(file_id); int32 min_file_id = (op == "dff" ? 1 : max_file_id); for (int32 i = min_file_id; i <= max_file_id; i++) { - send_request(td_api::make_object(i, priority, offset, to_integer(limit), op == "dfs")); + send_request( + td_api::make_object(i, priority, offset, to_integer(limit), op == "dfs")); } } else if (op == "cdf") { send_request(td_api::make_object(as_file_id(args), false));