From eed706f9176e3aca44b10946f3b114aa4a4b32ce Mon Sep 17 00:00:00 2001 From: 23rd <23rd@vivaldi.net> Date: Thu, 1 Dec 2022 02:22:39 +0300 Subject: [PATCH] Added ability to filter and report of anti-spam in admin log. --- Telegram/Resources/langs/lang.strings | 4 + .../admin_log/history_admin_log_inner.cpp | 12 +- .../admin_log/history_admin_log_inner.h | 2 + .../menu/menu_antispam_validator.cpp | 103 ++++++++++++++++++ .../menu/menu_antispam_validator.h | 6 + 5 files changed, 125 insertions(+), 2 deletions(-) diff --git a/Telegram/Resources/langs/lang.strings b/Telegram/Resources/langs/lang.strings index b57393769..3e1996f57 100644 --- a/Telegram/Resources/langs/lang.strings +++ b/Telegram/Resources/langs/lang.strings @@ -3183,6 +3183,10 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL "lng_admin_log_admin_manage_calls_channel" = "Manage live streams"; "lng_admin_log_admin_add_admins" = "Add new admins"; +"lng_admin_log_antispam_menu_report" = "Report False Positive"; +"lng_admin_log_antispam_menu_report_toast" = "You can manage anti-spam settings in {link}."; +"lng_admin_log_antispam_menu_report_toast_link" = "Group Info > Administrators"; + "lng_terms_signup" = "By signing up,\nyou agree to the {link}."; "lng_terms_signup_link" = "Terms of Service"; "lng_terms_header" = "Terms of Service"; diff --git a/Telegram/SourceFiles/history/admin_log/history_admin_log_inner.cpp b/Telegram/SourceFiles/history/admin_log/history_admin_log_inner.cpp index b93b849e3..20b195e8d 100644 --- a/Telegram/SourceFiles/history/admin_log/history_admin_log_inner.cpp +++ b/Telegram/SourceFiles/history/admin_log/history_admin_log_inner.cpp @@ -250,7 +250,8 @@ InnerWidget::InnerWidget( , _emptyText( st::historyAdminLogEmptyWidth - st::historyAdminLogEmptyPadding.left() - - st::historyAdminLogEmptyPadding.left()) { + - st::historyAdminLogEmptyPadding.left()) +, _antiSpamValidator(_controller, _channel) { Window::ChatThemeValueFromPeer( controller, channel @@ -326,7 +327,9 @@ InnerWidget::InnerWidget( updateEmptyText(); - requestAdmins(); + _antiSpamValidator.resolveUser(crl::guard( + this, + [=] { requestAdmins(); })); } Main::Session &InnerWidget::session() const { @@ -470,6 +473,9 @@ void InnerWidget::requestAdmins() { data); _admins.clear(); _adminsCanEdit.clear(); + if (const auto user = _antiSpamValidator.maybeAppendUser()) { + _admins.emplace_back(user); + } for (const auto &parsed : list) { if (parsed.isUser()) { const auto user = _channel->owner().userLoaded( @@ -1274,6 +1280,8 @@ void InnerWidget::showContextMenu(QContextMenuEvent *e, bool showFromTouch) { const auto item = view ? view->data().get() : nullptr; const auto itemId = item ? item->fullId() : FullMsgId(); + _antiSpamValidator.addAction(_menu, itemId); + auto msg = dynamic_cast(item); if (isUponSelected > 0) { _menu->addAction( diff --git a/Telegram/SourceFiles/history/admin_log/history_admin_log_inner.h b/Telegram/SourceFiles/history/admin_log/history_admin_log_inner.h index 7f1ce801b..a62fc47a8 100644 --- a/Telegram/SourceFiles/history/admin_log/history_admin_log_inner.h +++ b/Telegram/SourceFiles/history/admin_log/history_admin_log_inner.h @@ -10,6 +10,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "history/view/history_view_element.h" #include "history/admin_log/history_admin_log_item.h" #include "history/admin_log/history_admin_log_section.h" +#include "menu/menu_antispam_validator.h" #include "ui/rp_widget.h" #include "ui/effects/animations.h" #include "ui/widgets/tooltip.h" @@ -325,6 +326,7 @@ private: Qt::CursorShape _cursor = style::cur_default; base::unique_qptr _menu; + const AntiSpamMenu::AntiSpamValidator _antiSpamValidator; QPoint _trippleClickPoint; base::Timer _trippleClickTimer; diff --git a/Telegram/SourceFiles/menu/menu_antispam_validator.cpp b/Telegram/SourceFiles/menu/menu_antispam_validator.cpp index 1879b327c..4588d1484 100644 --- a/Telegram/SourceFiles/menu/menu_antispam_validator.cpp +++ b/Telegram/SourceFiles/menu/menu_antispam_validator.cpp @@ -8,9 +8,12 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "menu/menu_antispam_validator.h" #include "apiwrap.h" +#include "boxes/peers/edit_participants_box.h" #include "boxes/peers/edit_peer_info_box.h" #include "data/data_changes.h" #include "data/data_channel.h" +#include "data/data_session.h" +#include "history/history_item.h" #include "lang/lang_keys.h" #include "main/main_account.h" #include "main/main_app_config.h" @@ -19,10 +22,12 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "ui/text/text_utilities.h" #include "ui/toasts/common_toasts.h" #include "ui/widgets/buttons.h" +#include "ui/widgets/popup_menu.h" #include "ui/wrap/slide_wrap.h" #include "ui/wrap/vertical_layout.h" #include "window/window_session_controller.h" #include "styles/style_info.h" +#include "styles/style_menu_icons.h" #include "styles/style_settings.h" namespace AntiSpamMenu { @@ -34,6 +39,13 @@ namespace { 100); } +[[nodiscard]] UserId AntiSpamUserId(not_null channel) { + const auto id = channel->session().account().appConfig().get( + u"telegram_antispam_user_id"_q, + QString()); + return UserId(id.toULongLong()); +} + } // namespace AntiSpamValidator::AntiSpamValidator( @@ -108,4 +120,95 @@ object_ptr AntiSpamValidator::createButton() const { return container; } +void AntiSpamValidator::resolveUser(Fn finish) const { + if (_channel->antiSpamMode()) { + const auto mtpUserId = peerToBareMTPInt(AntiSpamUserId(_channel)); + _channel->session().api().request(MTPusers_GetUsers( + MTP_vector(1, MTP_inputUser(mtpUserId, MTPlong())) + )).done([=, channel = _channel](const MTPVector &result) { + channel->owner().processUsers(result); + finish(); + }).fail([=] { + finish(); + }).send(); + } else { + finish(); + } +} + +UserData *AntiSpamValidator::maybeAppendUser() const { + if (_channel->antiSpamMode()) { + const auto userId = AntiSpamUserId(_channel); + if (const auto user = _channel->owner().user(userId)) { + return user; + } + } + return nullptr; +} + +void AntiSpamValidator::addAction( + not_null menu, + FullMsgId fullId) const { + if (!fullId) { + return; + } + const auto antiSpamUserId = AntiSpamUserId(_channel); + const auto suggestReport = [&] { + const auto text = tr::lng_admin_log_antispam_menu_report_toast( + tr::now, + lt_link, + Ui::Text::Link( + tr::lng_admin_log_antispam_menu_report_toast_link( + tr::now), + "internal:show"), + Ui::Text::RichLangValue); + const auto showToast = [=, + window = _controller, + channel = _channel] { + Ui::ShowMultilineToast({ + .parentOverride = Window::Show(window).toastParent(), + .text = text, + .duration = ApiWrap::kJoinErrorDuration, + .filter = [=]( + const ClickHandlerPtr&, + Qt::MouseButton) { + ParticipantsBoxController::Start( + window, + channel, + ParticipantsRole::Admins); + return true; + }, + }); + }; + menu->addAction( + tr::lng_admin_log_antispam_menu_report(tr::now), + [=, channel = _channel] { + _channel->session().api().request( + MTPchannels_ReportAntiSpamFalsePositive( + channel->inputChannel, + MTP_int(fullId.msg) + )).done(showToast).send(); + }, + &st::menuIconAdmin); + }; + const auto &data = _channel->owner(); + const auto findItem = [&](FullMsgId id, int offset) { + id.msg.bare -= offset; + if (const auto item = data.message(id)) { + if (peerToUser(item->from()->id) == antiSpamUserId) { + suggestReport(); + return true; + } + } + return false; + }; + // Context menu on service message. + if (!findItem(fullId, 0)) { + // Take a previous. + if (findItem(fullId, 1)) { + menu->addSeparator(); + } + } +} + } // namespace AntiSpamMenu diff --git a/Telegram/SourceFiles/menu/menu_antispam_validator.h b/Telegram/SourceFiles/menu/menu_antispam_validator.h index 7930b4de9..12f0aeb27 100644 --- a/Telegram/SourceFiles/menu/menu_antispam_validator.h +++ b/Telegram/SourceFiles/menu/menu_antispam_validator.h @@ -11,8 +11,10 @@ template class object_ptr; class ChannelData; +class UserData; namespace Ui { +class PopupMenu; class RpWidget; } // namespace Ui @@ -30,6 +32,10 @@ public: [[nodiscard]] object_ptr createButton() const; + void resolveUser(Fn finish) const; + [[nodiscard]] UserData *maybeAppendUser() const; + void addAction(not_null menu, FullMsgId fullId) const; + private: const not_null _channel; const not_null _controller;