refactor: some Application & style things (#5561)

This commit is contained in:
pajlada
2024-08-25 15:33:07 +02:00
committed by GitHub
parent ac88730563
commit 627c735524
41 changed files with 733 additions and 678 deletions
+439
View File
@@ -16,9 +16,13 @@
#include "providers/seventv/SeventvEventAPI.hpp"
#include "providers/twitch/api/Helix.hpp"
#include "providers/twitch/IrcMessageHandler.hpp"
#include "providers/twitch/PubSubActions.hpp"
#include "providers/twitch/PubSubManager.hpp"
#include "providers/twitch/pubsubmessages/AutoMod.hpp"
#include "providers/twitch/TwitchAccount.hpp"
#include "providers/twitch/TwitchChannel.hpp"
#include "singletons/Settings.hpp"
#include "singletons/StreamerMode.hpp"
#include "util/PostToThread.hpp"
#include "util/RatelimitBucket.hpp"
@@ -230,6 +234,441 @@ void TwitchIrcServer::initialize()
this->connect();
});
});
this->connections_.managedConnect(
getApp()->getTwitchPubSub()->moderation.chatCleared,
[this](const auto &action) {
auto chan = this->getChannelOrEmptyByID(action.roomID);
if (chan->isEmpty())
{
return;
}
QString text =
QString("%1 cleared the chat.").arg(action.source.login);
postToThread([chan, text] {
chan->addSystemMessage(text);
});
});
this->connections_.managedConnect(
getApp()->getTwitchPubSub()->moderation.modeChanged,
[this](const auto &action) {
auto chan = this->getChannelOrEmptyByID(action.roomID);
if (chan->isEmpty())
{
return;
}
QString text =
QString("%1 turned %2 %3 mode.")
.arg(action.source.login)
.arg(action.state == ModeChangedAction::State::On ? "on"
: "off")
.arg(action.getModeName());
if (action.duration > 0)
{
text += QString(" (%1 seconds)").arg(action.duration);
}
postToThread([chan, text] {
chan->addSystemMessage(text);
});
});
this->connections_.managedConnect(
getApp()->getTwitchPubSub()->moderation.moderationStateChanged,
[this](const auto &action) {
auto chan = this->getChannelOrEmptyByID(action.roomID);
if (chan->isEmpty())
{
return;
}
QString text;
text = QString("%1 %2 %3.")
.arg(action.source.login,
(action.modded ? "modded" : "unmodded"),
action.target.login);
postToThread([chan, text] {
chan->addSystemMessage(text);
});
});
this->connections_.managedConnect(
getApp()->getTwitchPubSub()->moderation.userBanned,
[this](const auto &action) {
auto chan = this->getChannelOrEmptyByID(action.roomID);
if (chan->isEmpty())
{
return;
}
postToThread([chan, action] {
MessageBuilder msg(action);
msg->flags.set(MessageFlag::PubSub);
chan->addOrReplaceTimeout(msg.release());
});
});
this->connections_.managedConnect(
getApp()->getTwitchPubSub()->moderation.userWarned,
[this](const auto &action) {
auto chan = this->getChannelOrEmptyByID(action.roomID);
if (chan->isEmpty())
{
return;
}
// TODO: Resolve the moderator's user ID into a full user here, so message can look better
postToThread([chan, action] {
MessageBuilder msg(action);
msg->flags.set(MessageFlag::PubSub);
chan->addMessage(msg.release(), MessageContext::Original);
});
});
this->connections_.managedConnect(
getApp()->getTwitchPubSub()->moderation.messageDeleted,
[this](const auto &action) {
auto chan = this->getChannelOrEmptyByID(action.roomID);
if (chan->isEmpty() || getSettings()->hideDeletionActions)
{
return;
}
auto msg = MessageBuilder::makeDeletionMessageFromPubSub(action);
postToThread([chan, msg] {
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)
{
const 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, MessageContext::Original);
}
});
});
this->connections_.managedConnect(
getApp()->getTwitchPubSub()->moderation.userUnbanned,
[this](const auto &action) {
auto chan = this->getChannelOrEmptyByID(action.roomID);
if (chan->isEmpty())
{
return;
}
auto msg = MessageBuilder(action).release();
postToThread([chan, msg] {
chan->addMessage(msg, MessageContext::Original);
});
});
this->connections_.managedConnect(
getApp()->getTwitchPubSub()->moderation.suspiciousMessageReceived,
[this](const auto &action) {
if (action.treatment ==
PubSubLowTrustUsersMessage::Treatment::INVALID)
{
qCWarning(chatterinoTwitch)
<< "Received suspicious message with unknown "
"treatment:"
<< action.treatmentString;
return;
}
// monitored chats are received over irc; in the future, we will use pubsub instead
if (action.treatment !=
PubSubLowTrustUsersMessage::Treatment::Restricted)
{
return;
}
if (getSettings()->streamerModeHideModActions &&
getApp()->getStreamerMode()->isEnabled())
{
return;
}
auto chan = this->getChannelOrEmptyByID(action.channelID);
if (chan->isEmpty())
{
return;
}
auto twitchChannel = std::dynamic_pointer_cast<TwitchChannel>(chan);
if (!twitchChannel)
{
return;
}
postToThread([twitchChannel, action] {
const auto p = MessageBuilder::makeLowTrustUserMessage(
action, twitchChannel->getName(), twitchChannel.get());
twitchChannel->addMessage(p.first, MessageContext::Original);
twitchChannel->addMessage(p.second, MessageContext::Original);
});
});
this->connections_.managedConnect(
getApp()->getTwitchPubSub()->moderation.suspiciousTreatmentUpdated,
[this](const auto &action) {
if (action.treatment ==
PubSubLowTrustUsersMessage::Treatment::INVALID)
{
qCWarning(chatterinoTwitch)
<< "Received suspicious user update with unknown "
"treatment:"
<< action.treatmentString;
return;
}
if (action.updatedByUserLogin.isEmpty())
{
return;
}
if (getSettings()->streamerModeHideModActions &&
getApp()->getStreamerMode()->isEnabled())
{
return;
}
auto chan = this->getChannelOrEmptyByID(action.channelID);
if (chan->isEmpty())
{
return;
}
postToThread([chan, action] {
auto msg = MessageBuilder::makeLowTrustUpdateMessage(action);
chan->addMessage(msg, MessageContext::Original);
});
});
this->connections_.managedConnect(
getApp()->getTwitchPubSub()->moderation.autoModMessageCaught,
[this](const auto &msg, const QString &channelID) {
auto chan = this->getChannelOrEmptyByID(channelID);
if (chan->isEmpty())
{
return;
}
switch (msg.type)
{
case PubSubAutoModQueueMessage::Type::AutoModCaughtMessage: {
if (msg.status == "PENDING")
{
AutomodAction action(msg.data, channelID);
action.reason = QString("%1 level %2")
.arg(msg.contentCategory)
.arg(msg.contentLevel);
action.msgID = msg.messageID;
action.message = msg.messageText;
// this message also contains per-word automod data, which could be implemented
// extract sender data manually because Twitch loves not being consistent
QString senderDisplayName =
msg.senderUserDisplayName; // Might be transformed later
bool hasLocalizedName = false;
if (!msg.senderUserDisplayName.isEmpty())
{
// check for non-ascii display names
if (QString::compare(msg.senderUserDisplayName,
msg.senderUserLogin,
Qt::CaseInsensitive) != 0)
{
hasLocalizedName = true;
}
}
QColor senderColor = msg.senderUserChatColor;
QString senderColor_;
if (!senderColor.isValid() &&
getSettings()->colorizeNicknames)
{
// color may be not present if user is a grey-name
senderColor = getRandomColor(msg.senderUserID);
}
// handle username style based on prefered setting
switch (getSettings()->usernameDisplayMode.getValue())
{
case UsernameDisplayMode::Username: {
if (hasLocalizedName)
{
senderDisplayName = msg.senderUserLogin;
}
break;
}
case UsernameDisplayMode::LocalizedName: {
break;
}
case UsernameDisplayMode::
UsernameAndLocalizedName: {
if (hasLocalizedName)
{
senderDisplayName = QString("%1(%2)").arg(
msg.senderUserLogin,
msg.senderUserDisplayName);
}
break;
}
}
action.target =
ActionUser{msg.senderUserID, msg.senderUserLogin,
senderDisplayName, senderColor};
postToThread([chan, action] {
const auto p = MessageBuilder::makeAutomodMessage(
action, chan->getName());
chan->addMessage(p.first, MessageContext::Original);
chan->addMessage(p.second,
MessageContext::Original);
getApp()
->getTwitch()
->getAutomodChannel()
->addMessage(p.first, MessageContext::Original);
getApp()
->getTwitch()
->getAutomodChannel()
->addMessage(p.second,
MessageContext::Original);
if (getSettings()->showAutomodInMentions)
{
getApp()
->getTwitch()
->getMentionsChannel()
->addMessage(p.first,
MessageContext::Original);
getApp()
->getTwitch()
->getMentionsChannel()
->addMessage(p.second,
MessageContext::Original);
}
});
}
// "ALLOWED" and "DENIED" statuses remain unimplemented
// They are versions of automod_message_(denied|approved) but for mods.
}
break;
case PubSubAutoModQueueMessage::Type::INVALID:
default: {
}
break;
}
});
this->connections_.managedConnect(
getApp()->getTwitchPubSub()->moderation.autoModMessageBlocked,
[this](const auto &action) {
auto chan = this->getChannelOrEmptyByID(action.roomID);
if (chan->isEmpty())
{
return;
}
postToThread([chan, action] {
const auto p =
MessageBuilder::makeAutomodMessage(action, chan->getName());
chan->addMessage(p.first, MessageContext::Original);
chan->addMessage(p.second, MessageContext::Original);
});
});
this->connections_.managedConnect(
getApp()->getTwitchPubSub()->moderation.automodUserMessage,
[this](const auto &action) {
if (getSettings()->streamerModeHideModActions &&
getApp()->getStreamerMode()->isEnabled())
{
return;
}
auto chan = this->getChannelOrEmptyByID(action.roomID);
if (chan->isEmpty())
{
return;
}
auto msg = MessageBuilder(action).release();
postToThread([chan, msg] {
chan->addMessage(msg, MessageContext::Original);
});
chan->deleteMessage(msg->id);
});
this->connections_.managedConnect(
getApp()->getTwitchPubSub()->moderation.automodInfoMessage,
[this](const auto &action) {
auto chan = this->getChannelOrEmptyByID(action.roomID);
if (chan->isEmpty())
{
return;
}
postToThread([chan, action] {
const auto p = MessageBuilder::makeAutomodInfoMessage(action);
chan->addMessage(p, MessageContext::Original);
});
});
this->connections_.managedConnect(
getApp()->getTwitchPubSub()->pointReward.redeemed, [this](auto &data) {
QString channelId = data.value("channel_id").toString();
if (channelId.isEmpty())
{
qCDebug(chatterinoApp)
<< "Couldn't find channel id of point reward";
return;
}
auto chan = this->getChannelOrEmptyByID(channelId);
auto reward = ChannelPointReward(data);
postToThread([chan, reward] {
if (auto *channel = dynamic_cast<TwitchChannel *>(chan.get()))
{
channel->addChannelPointReward(reward);
}
});
});
}
void TwitchIrcServer::initializeConnection(IrcConnection *connection,