Allow moderators to see who deleted a message (#2874)

Co-authored-by: pajlada <rasmus.karlsson@pajlada.com>
This commit is contained in:
Mm2PL 2021-06-19 13:56:00 +02:00 committed by GitHub
parent f9ddd53037
commit 9640837957
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 136 additions and 2 deletions

View file

@ -12,7 +12,7 @@
- Minor: Limit the number of recent chatters to improve memory usage and reduce freezes. (#2796, #2814) - Minor: Limit the number of recent chatters to improve memory usage and reduce freezes. (#2796, #2814)
- Minor: Added `/popout` command. Usage: `/popout [channel]`. It opens browser chat for the provided channel. Can also be used without arguments to open current channels browser chat. (#2556, #2812) - Minor: Added `/popout` command. Usage: `/popout [channel]`. It opens browser chat for the provided channel. Can also be used without arguments to open current channels browser chat. (#2556, #2812)
- Minor: Improved matching of game names when using `/setgame` command (#2636) - Minor: Improved matching of game names when using `/setgame` command (#2636)
- Minor: Now shows deletions of messages like timeouts (#1155, #2841) - Minor: Now shows deletions of messages like timeouts (#1155, #2841, #2867, #2874)
- Minor: Added a link to accounts page in settings to "You need to be logged in to send messages" message. (#2862) - Minor: Added a link to accounts page in settings to "You need to be logged in to send messages" message. (#2862)
- Minor: Switch to Twitch v2 emote API for animated emote support. (#2863) - Minor: Switch to Twitch v2 emote API for animated emote support. (#2863)
- Bugfix: Fixed FFZ emote links for global emotes (#2807, #2808) - Bugfix: Fixed FFZ emote links for global emotes (#2807, #2808)

View file

@ -18,6 +18,7 @@
#include "providers/irc/Irc2.hpp" #include "providers/irc/Irc2.hpp"
#include "providers/twitch/PubsubClient.hpp" #include "providers/twitch/PubsubClient.hpp"
#include "providers/twitch/TwitchIrcServer.hpp" #include "providers/twitch/TwitchIrcServer.hpp"
#include "providers/twitch/TwitchMessageBuilder.hpp"
#include "singletons/Emotes.hpp" #include "singletons/Emotes.hpp"
#include "singletons/Fonts.hpp" #include "singletons/Fonts.hpp"
#include "singletons/Logging.hpp" #include "singletons/Logging.hpp"
@ -287,6 +288,46 @@ void Application::initPubsub()
chan->addOrReplaceTimeout(msg); chan->addOrReplaceTimeout(msg);
}); });
}); });
this->twitch.pubsub->signals_.moderation.messageDeleted.connect(
[&](const auto &action) {
auto chan =
this->twitch.server->getChannelOrEmptyByID(action.roomID);
if (chan->isEmpty())
{
return;
}
MessageBuilder msg;
TwitchMessageBuilder::deletionMessage(action, &msg);
msg->flags.set(MessageFlag::PubSub);
postToThread([chan, msg = msg.release()] {
auto replaced = false;
LimitedQueueSnapshot<MessagePtr> snapshot =
chan->getMessageSnapshot();
int snapshotLength = snapshot.size();
// without parens it doesn't build on windows
int end = (std::max)(0, snapshotLength - 200);
for (int i = snapshotLength - 1; i >= end; --i)
{
auto &s = snapshot[i];
if (!s->flags.has(MessageFlag::PubSub) &&
s->timeoutUser == msg->timeoutUser)
{
chan->replaceMessage(s, msg);
replaced = true;
break;
}
}
if (!replaced)
{
chan->addMessage(msg);
}
});
});
this->twitch.pubsub->signals_.moderation.userUnbanned.connect( this->twitch.pubsub->signals_.moderation.userUnbanned.connect(
[&](const auto &action) { [&](const auto &action) {

View file

@ -75,6 +75,15 @@ struct BanAction : PubSubAction {
} }
}; };
struct DeleteAction : PubSubAction {
using PubSubAction::PubSubAction;
ActionUser target;
QString messageId;
QString messageText;
};
struct UnbanAction : PubSubAction { struct UnbanAction : PubSubAction {
using PubSubAction::PubSubAction; using PubSubAction::PubSubAction;

View file

@ -428,6 +428,46 @@ PubSub::PubSub()
} }
}; };
this->moderationActionHandlers["delete"] = [this](const auto &data,
const auto &roomID) {
DeleteAction action(data, roomID);
getCreatedByUser(data, action.source);
getTargetUser(data, action.target);
try
{
const auto &args = getArgs(data);
if (args.Size() < 3)
{
return;
}
if (!rj::getSafe(args[0], action.target.name))
{
return;
}
if (!rj::getSafe(args[1], action.messageText))
{
return;
}
if (!rj::getSafe(args[2], action.messageId))
{
return;
}
this->signals_.moderation.messageDeleted.invoke(action);
}
catch (const std::runtime_error &ex)
{
qCDebug(chatterinoPubsub)
<< "Error parsing moderation action:" << ex.what();
}
};
this->moderationActionHandlers["ban"] = [this](const auto &data, this->moderationActionHandlers["ban"] = [this](const auto &data,
const auto &roomID) { const auto &roomID) {
BanAction action(data, roomID); BanAction action(data, roomID);

View file

@ -124,6 +124,7 @@ public:
struct { struct {
struct { struct {
Signal<ClearChatAction> chatCleared; Signal<ClearChatAction> chatCleared;
Signal<DeleteAction> messageDeleted;
Signal<ModeChangedAction> modeChanged; Signal<ModeChangedAction> modeChanged;
Signal<ModerationStateAction> moderationStateChanged; Signal<ModerationStateAction> moderationStateChanged;

View file

@ -1352,6 +1352,8 @@ void TwitchMessageBuilder::hostingSystemMessage(const QString &channelName,
MessageColor::System, FontStyle::ChatMediumBold) MessageColor::System, FontStyle::ChatMediumBold)
->setLink({Link::UserInfo, channelName}); ->setLink({Link::UserInfo, channelName});
} }
// irc variant
void TwitchMessageBuilder::deletionMessage(const MessagePtr originalMessage, void TwitchMessageBuilder::deletionMessage(const MessagePtr originalMessage,
MessageBuilder *builder) MessageBuilder *builder)
{ {
@ -1373,7 +1375,7 @@ void TwitchMessageBuilder::deletionMessage(const MessagePtr originalMessage,
if (originalMessage->messageText.length() > 50) if (originalMessage->messageText.length() > 50)
{ {
builder->emplace<TextElement>( builder->emplace<TextElement>(
originalMessage->messageText.left(50) + "...", originalMessage->messageText.left(50) + "",
MessageElementFlag::Text, MessageColor::Text); MessageElementFlag::Text, MessageColor::Text);
} }
else else
@ -1382,6 +1384,44 @@ void TwitchMessageBuilder::deletionMessage(const MessagePtr originalMessage,
MessageElementFlag::Text, MessageElementFlag::Text,
MessageColor::Text); MessageColor::Text);
} }
builder->message().timeoutUser = "msg:" + originalMessage->id;
}
// pubsub variant
void TwitchMessageBuilder::deletionMessage(const DeleteAction &action,
MessageBuilder *builder)
{
builder->emplace<TimestampElement>();
builder->message().flags.set(MessageFlag::System);
builder->message().flags.set(MessageFlag::DoNotTriggerNotification);
builder->message().flags.set(MessageFlag::Timeout);
builder
->emplace<TextElement>(action.source.name, MessageElementFlag::Username,
MessageColor::System, FontStyle::ChatMediumBold)
->setLink({Link::UserInfo, action.source.name});
// TODO(mm2pl): If or when jumping to a single message gets implemented a link,
// add a link to the originalMessage
builder->emplace<TextElement>(
"deleted message from", MessageElementFlag::Text, MessageColor::System);
builder
->emplace<TextElement>(action.target.name, MessageElementFlag::Username,
MessageColor::System, FontStyle::ChatMediumBold)
->setLink({Link::UserInfo, action.target.name});
builder->emplace<TextElement>("saying:", MessageElementFlag::Text,
MessageColor::System);
if (action.messageText.length() > 50)
{
builder->emplace<TextElement>(action.messageText.left(50) + "",
MessageElementFlag::Text,
MessageColor::Text);
}
else
{
builder->emplace<TextElement>(
action.messageText, MessageElementFlag::Text, MessageColor::Text);
}
builder->message().timeoutUser = "msg:" + action.messageId;
} }
} // namespace chatterino } // namespace chatterino

View file

@ -4,6 +4,7 @@
#include "common/Outcome.hpp" #include "common/Outcome.hpp"
#include "messages/SharedMessageBuilder.hpp" #include "messages/SharedMessageBuilder.hpp"
#include "providers/twitch/ChannelPointReward.hpp" #include "providers/twitch/ChannelPointReward.hpp"
#include "providers/twitch/PubsubActions.hpp"
#include "providers/twitch/TwitchBadge.hpp" #include "providers/twitch/TwitchBadge.hpp"
#include <IrcMessage> #include <IrcMessage>
@ -60,6 +61,8 @@ public:
MessageBuilder *builder); MessageBuilder *builder);
static void deletionMessage(const MessagePtr originalMessage, static void deletionMessage(const MessagePtr originalMessage,
MessageBuilder *builder); MessageBuilder *builder);
static void deletionMessage(const DeleteAction &action,
MessageBuilder *builder);
private: private:
void parseUsernameColor() override; void parseUsernameColor() override;