Fixed reporting to anti-spam incorrect message id from admin log.

This commit is contained in:
23rd 2022-12-03 14:19:14 +03:00
parent beb062dd64
commit badebb261b
7 changed files with 87 additions and 49 deletions

View file

@ -829,20 +829,32 @@ void InnerWidget::addEvents(Direction direction, const QVector<MTPChannelAdminLo
? _items ? _items
: newItemsForDownDirection; : newItemsForDownDirection;
addToItems.reserve(oldItemsCount + events.size() * 2); addToItems.reserve(oldItemsCount + events.size() * 2);
const auto antiSpamUserId = _antiSpamValidator.userId();
for (const auto &event : events) { for (const auto &event : events) {
const auto &data = event.data(); const auto &data = event.data();
const auto id = data.vid().v; const auto id = data.vid().v;
if (_eventIds.find(id) != _eventIds.end()) { if (_eventIds.find(id) != _eventIds.end()) {
return; return;
} }
const auto rememberRealMsgId = (antiSpamUserId
== peerToUser(peerFromUser(data.vuser_id())));
auto count = 0; auto count = 0;
const auto addOne = [&](OwnedItem item, TimeId sentDate) { const auto addOne = [&](
OwnedItem item,
TimeId sentDate,
MsgId realId) {
if (sentDate) { if (sentDate) {
_itemDates.emplace(item->data(), sentDate); _itemDates.emplace(item->data(), sentDate);
} }
_eventIds.emplace(id); _eventIds.emplace(id);
_itemsByData.emplace(item->data(), item.get()); _itemsByData.emplace(item->data(), item.get());
if (rememberRealMsgId && realId) {
_antiSpamValidator.addEventMsgId(
item->data()->fullId(),
realId);
}
addToItems.push_back(std::move(item)); addToItems.push_back(std::move(item));
++count; ++count;
}; };

View file

@ -326,7 +326,7 @@ private:
Qt::CursorShape _cursor = style::cur_default; Qt::CursorShape _cursor = style::cur_default;
base::unique_qptr<Ui::PopupMenu> _menu; base::unique_qptr<Ui::PopupMenu> _menu;
const AntiSpamMenu::AntiSpamValidator _antiSpamValidator; AntiSpamMenu::AntiSpamValidator _antiSpamValidator;
QPoint _trippleClickPoint; QPoint _trippleClickPoint;
base::Timer _trippleClickTimer; base::Timer _trippleClickTimer;

View file

@ -60,16 +60,26 @@ TextWithEntities PrepareText(
return result; return result;
} }
TimeId ExtractSentDate(const MTPMessage &message) { [[nodiscard]] TimeId ExtractSentDate(const MTPMessage &message) {
return message.match([&](const MTPDmessageEmpty &) { return message.match([](const MTPDmessageEmpty &) {
return 0; return 0;
}, [&](const MTPDmessageService &data) { }, [](const MTPDmessageService &data) {
return data.vdate().v; return data.vdate().v;
}, [&](const MTPDmessage &data) { }, [](const MTPDmessage &data) {
return data.vdate().v; return data.vdate().v;
}); });
} }
[[nodiscard]] MsgId ExtractRealMsgId(const MTPMessage &message) {
return MsgId(message.match([](const MTPDmessageEmpty &) {
return 0;
}, [](const MTPDmessageService &data) {
return data.vid().v;
}, [](const MTPDmessage &data) {
return data.vid().v;
}));
}
MTPMessage PrepareLogMessage(const MTPMessage &message, TimeId newDate) { MTPMessage PrepareLogMessage(const MTPMessage &message, TimeId newDate) {
return message.match([&](const MTPDmessageEmpty &data) { return message.match([&](const MTPDmessageEmpty &data) {
return MTP_messageEmpty( return MTP_messageEmpty(
@ -680,7 +690,7 @@ void GenerateItems(
not_null<HistoryView::ElementDelegate*> delegate, not_null<HistoryView::ElementDelegate*> delegate,
not_null<History*> history, not_null<History*> history,
const MTPDchannelAdminLogEvent &event, const MTPDchannelAdminLogEvent &event,
Fn<void(OwnedItem item, TimeId sentDate)> callback) { Fn<void(OwnedItem item, TimeId sentDate, MsgId)> callback) {
Expects(history->peer->isChannel()); Expects(history->peer->isChannel());
using LogTitle = MTPDchannelAdminLogEventActionChangeTitle; using LogTitle = MTPDchannelAdminLogEventActionChangeTitle;
@ -741,8 +751,9 @@ void GenerateItems(
const auto date = event.vdate().v; const auto date = event.vdate().v;
const auto addPart = [&]( const auto addPart = [&](
not_null<HistoryItem*> item, not_null<HistoryItem*> item,
TimeId sentDate = 0) { TimeId sentDate = 0,
return callback(OwnedItem(delegate, item), sentDate); MsgId realId = MsgId()) {
return callback(OwnedItem(delegate, item), sentDate, realId);
}; };
const auto fromName = from->name(); const auto fromName = from->name();
@ -751,16 +762,20 @@ void GenerateItems(
const auto addSimpleServiceMessage = [&]( const auto addSimpleServiceMessage = [&](
const TextWithEntities &text, const TextWithEntities &text,
MsgId realId = MsgId(),
PhotoData *photo = nullptr) { PhotoData *photo = nullptr) {
auto message = HistoryService::PreparedText{ text }; auto message = HistoryService::PreparedText{ text };
message.links.push_back(fromLink); message.links.push_back(fromLink);
addPart(history->makeServiceMessage( addPart(
history->nextNonHistoryEntryId(), history->makeServiceMessage(
MessageFlag::AdminLogEntry, history->nextNonHistoryEntryId(),
date, MessageFlag::AdminLogEntry,
std::move(message), date,
peerToUser(from->id), std::move(message),
photo)); peerToUser(from->id),
photo),
0,
realId);
}; };
const auto createChangeTitle = [&](const LogTitle &action) { const auto createChangeTitle = [&](const LogTitle &action) {
@ -865,7 +880,7 @@ void GenerateItems(
lt_from, lt_from,
fromLinkText, fromLinkText,
Ui::Text::WithEntities); Ui::Text::WithEntities);
addSimpleServiceMessage(text, photo); addSimpleServiceMessage(text, MsgId(), photo);
}, [&](const MTPDphotoEmpty &data) { }, [&](const MTPDphotoEmpty &data) {
const auto text = (channel->isMegagroup() const auto text = (channel->isMegagroup()
? tr::lng_admin_log_removed_photo_group ? tr::lng_admin_log_removed_photo_group
@ -905,6 +920,7 @@ void GenerateItems(
const auto createUpdatePinned = [&](const LogPin &action) { const auto createUpdatePinned = [&](const LogPin &action) {
action.vmessage().match([&](const MTPDmessage &data) { action.vmessage().match([&](const MTPDmessage &data) {
const auto pinned = data.is_pinned(); const auto pinned = data.is_pinned();
const auto realId = ExtractRealMsgId(action.vmessage());
const auto text = (pinned const auto text = (pinned
? tr::lng_admin_log_pinned_message ? tr::lng_admin_log_pinned_message
: tr::lng_admin_log_unpinned_message)( : tr::lng_admin_log_unpinned_message)(
@ -912,7 +928,7 @@ void GenerateItems(
lt_from, lt_from,
fromLinkText, fromLinkText,
Ui::Text::WithEntities); Ui::Text::WithEntities);
addSimpleServiceMessage(text); addSimpleServiceMessage(text, realId);
const auto detachExistingItem = false; const auto detachExistingItem = false;
addPart( addPart(
@ -921,7 +937,8 @@ void GenerateItems(
PrepareLogMessage(action.vmessage(), date), PrepareLogMessage(action.vmessage(), date),
MessageFlag::AdminLogEntry, MessageFlag::AdminLogEntry,
detachExistingItem), detachExistingItem),
ExtractSentDate(action.vmessage())); ExtractSentDate(action.vmessage()),
realId);
}, [&](const auto &) { }, [&](const auto &) {
const auto text = tr::lng_admin_log_unpinned_message( const auto text = tr::lng_admin_log_unpinned_message(
tr::now, tr::now,
@ -933,6 +950,8 @@ void GenerateItems(
}; };
const auto createEditMessage = [&](const LogEdit &action) { const auto createEditMessage = [&](const LogEdit &action) {
const auto realId = ExtractRealMsgId(action.vnew_message());
const auto sentDate = ExtractSentDate(action.vnew_message());
const auto newValue = ExtractEditedText( const auto newValue = ExtractEditedText(
session, session,
action.vnew_message()); action.vnew_message());
@ -964,7 +983,7 @@ void GenerateItems(
lt_from, lt_from,
fromLinkText, fromLinkText,
Ui::Text::WithEntities); Ui::Text::WithEntities);
addSimpleServiceMessage(text); addSimpleServiceMessage(text, realId);
const auto detachExistingItem = false; const auto detachExistingItem = false;
const auto body = history->createItem( const auto body = history->createItem(
@ -984,16 +1003,17 @@ void GenerateItems(
? tr::lng_admin_log_previous_caption ? tr::lng_admin_log_previous_caption
: tr::lng_admin_log_previous_message)(tr::now), : tr::lng_admin_log_previous_message)(tr::now),
oldValue); oldValue);
addPart(body); addPart(body, sentDate, realId);
}; };
const auto createDeleteMessage = [&](const LogDelete &action) { const auto createDeleteMessage = [&](const LogDelete &action) {
const auto realId = ExtractRealMsgId(action.vmessage());
const auto text = tr::lng_admin_log_deleted_message( const auto text = tr::lng_admin_log_deleted_message(
tr::now, tr::now,
lt_from, lt_from,
fromLinkText, fromLinkText,
Ui::Text::WithEntities); Ui::Text::WithEntities);
addSimpleServiceMessage(text); addSimpleServiceMessage(text, realId);
const auto detachExistingItem = false; const auto detachExistingItem = false;
addPart( addPart(
@ -1002,7 +1022,8 @@ void GenerateItems(
PrepareLogMessage(action.vmessage(), date), PrepareLogMessage(action.vmessage(), date),
MessageFlag::AdminLogEntry, MessageFlag::AdminLogEntry,
detachExistingItem), detachExistingItem),
ExtractSentDate(action.vmessage())); ExtractSentDate(action.vmessage()),
realId);
}; };
const auto createParticipantJoin = [&](const LogJoin&) { const auto createParticipantJoin = [&](const LogJoin&) {
@ -1122,12 +1143,13 @@ void GenerateItems(
}; };
const auto createStopPoll = [&](const LogPoll &action) { const auto createStopPoll = [&](const LogPoll &action) {
const auto realId = ExtractRealMsgId(action.vmessage());
const auto text = tr::lng_admin_log_stopped_poll( const auto text = tr::lng_admin_log_stopped_poll(
tr::now, tr::now,
lt_from, lt_from,
fromLinkText, fromLinkText,
Ui::Text::WithEntities); Ui::Text::WithEntities);
addSimpleServiceMessage(text); addSimpleServiceMessage(text, realId);
const auto detachExistingItem = false; const auto detachExistingItem = false;
addPart( addPart(
@ -1136,7 +1158,8 @@ void GenerateItems(
PrepareLogMessage(action.vmessage(), date), PrepareLogMessage(action.vmessage(), date),
MessageFlag::AdminLogEntry, MessageFlag::AdminLogEntry,
detachExistingItem), detachExistingItem),
ExtractSentDate(action.vmessage())); ExtractSentDate(action.vmessage()),
realId);
}; };
const auto createChangeLinkedChat = [&](const LogDiscussion &action) { const auto createChangeLinkedChat = [&](const LogDiscussion &action) {
@ -1493,12 +1516,13 @@ void GenerateItems(
}; };
const auto createSendMessage = [&](const LogSendMessage &data) { const auto createSendMessage = [&](const LogSendMessage &data) {
const auto realId = ExtractRealMsgId(data.vmessage());
const auto text = tr::lng_admin_log_sent_message( const auto text = tr::lng_admin_log_sent_message(
tr::now, tr::now,
lt_from, lt_from,
fromLinkText, fromLinkText,
Ui::Text::WithEntities); Ui::Text::WithEntities);
addSimpleServiceMessage(text); addSimpleServiceMessage(text, realId);
const auto detachExistingItem = false; const auto detachExistingItem = false;
addPart( addPart(
@ -1507,7 +1531,8 @@ void GenerateItems(
PrepareLogMessage(data.vmessage(), date), PrepareLogMessage(data.vmessage(), date),
MessageFlag::AdminLogEntry, MessageFlag::AdminLogEntry,
detachExistingItem), detachExistingItem),
ExtractSentDate(data.vmessage())); ExtractSentDate(data.vmessage()),
realId);
}; };
const auto createChangeAvailableReactions = [&]( const auto createChangeAvailableReactions = [&](

View file

@ -22,7 +22,7 @@ void GenerateItems(
not_null<HistoryView::ElementDelegate*> delegate, not_null<HistoryView::ElementDelegate*> delegate,
not_null<History*> history, not_null<History*> history,
const MTPDchannelAdminLogEvent &event, const MTPDchannelAdminLogEvent &event,
Fn<void(OwnedItem item, TimeId sentDate)> callback); Fn<void(OwnedItem item, TimeId sentDate, MsgId)> callback);
// Smart pointer wrapper for HistoryItem* that destroys the owned item. // Smart pointer wrapper for HistoryItem* that destroys the owned item.
class OwnedItem { class OwnedItem {

View file

@ -147,14 +147,18 @@ UserData *AntiSpamValidator::maybeAppendUser() const {
return nullptr; return nullptr;
} }
UserId AntiSpamValidator::userId() const {
return AntiSpamUserId(_channel);
}
void AntiSpamValidator::addAction( void AntiSpamValidator::addAction(
not_null<Ui::PopupMenu*> menu, not_null<Ui::PopupMenu*> menu,
FullMsgId fullId) const { FullMsgId fakeId) const {
if (!fullId) { if (!fakeId) {
return; return;
} }
const auto antiSpamUserId = AntiSpamUserId(_channel); const auto antiSpamUserId = AntiSpamUserId(_channel);
const auto suggestReport = [&] { const auto suggestReport = [&](MsgId eventId) {
const auto text = tr::lng_admin_log_antispam_menu_report_toast( const auto text = tr::lng_admin_log_antispam_menu_report_toast(
tr::now, tr::now,
lt_link, lt_link,
@ -187,29 +191,22 @@ void AntiSpamValidator::addAction(
_channel->session().api().request( _channel->session().api().request(
MTPchannels_ReportAntiSpamFalsePositive( MTPchannels_ReportAntiSpamFalsePositive(
channel->inputChannel, channel->inputChannel,
MTP_int(fullId.msg) MTP_int(eventId)
)).done(showToast).send(); )).done(showToast).send();
}, },
&st::menuIconAdmin); &st::menuIconAdmin);
}; };
const auto &data = _channel->owner(); {
const auto findItem = [&](FullMsgId id, int offset) { const auto it = _itemEventMsgIds.find(fakeId);
id.msg.bare -= offset; if (it != end(_itemEventMsgIds)) {
if (const auto item = data.message(id)) { suggestReport(it->second);
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(); menu->addSeparator();
} }
} }
} }
void AntiSpamValidator::addEventMsgId(FullMsgId fakeId, MsgId realId) {
_itemEventMsgIds.emplace(fakeId, realId);
}
} // namespace AntiSpamMenu } // namespace AntiSpamMenu

View file

@ -34,12 +34,16 @@ public:
void resolveUser(Fn<void()> finish) const; void resolveUser(Fn<void()> finish) const;
[[nodiscard]] UserData *maybeAppendUser() const; [[nodiscard]] UserData *maybeAppendUser() const;
void addAction(not_null<Ui::PopupMenu*> menu, FullMsgId fullId) const; [[nodiscard]] UserId userId() const;
void addAction(not_null<Ui::PopupMenu*> menu, FullMsgId fakeId) const;
void addEventMsgId(FullMsgId fakeId, MsgId realId);
private: private:
const not_null<ChannelData*> _channel; const not_null<ChannelData*> _channel;
const not_null<Window::SessionController*> _controller; const not_null<Window::SessionController*> _controller;
base::flat_map<FullMsgId, MsgId> _itemEventMsgIds;
}; };
} // namespace AntiSpamMenu } // namespace AntiSpamMenu

@ -1 +1 @@
Subproject commit 6c345d2076e0b1997ef64b13f617bf5afbaf396b Subproject commit ff821bc3d79761a2b801bd067d38d2a4d7f766e3