fix: correctly override user color in sub gifts (#6322)

This commit is contained in:
pajlada
2025-07-06 15:05:28 +02:00
committed by GitHub
parent f2d7e4d073
commit 7f2168a9d4
14 changed files with 410 additions and 12 deletions
+1
View File
@@ -57,6 +57,7 @@ set(test_SOURCES
${CMAKE_CURRENT_LIST_DIR}/src/NativeMessaging.cpp
${CMAKE_CURRENT_LIST_DIR}/src/ImageUploader.cpp
${CMAKE_CURRENT_LIST_DIR}/src/TwitchChannel.cpp
${CMAKE_CURRENT_LIST_DIR}/src/TwitchUserColor.cpp
${CMAKE_CURRENT_LIST_DIR}/src/lib/Snapshot.cpp
${CMAKE_CURRENT_LIST_DIR}/src/lib/Snapshot.hpp
@@ -0,0 +1,131 @@
{
"input": "@tmi-sent-ts=1751793597378;subscriber=1;id=ac51c358-0525-468f-9e0f-e9f2b7953c29;room-id=11148817;user-id=11148817;login=pajlada;display-name=pajlada;badges=broadcaster/1,subscriber/3072,partner/1;badge-info=subscriber/114;color=#CC44FF;flags=;user-type=;emotes=;msg-param-sub-plan-name=look\\sat\\sthose\\sshitty\\semotes,\\srip\\s$5\\sLUL;msg-param-gift-months=1;system-msg=pajlada\\sgifted\\sa\\sTier\\s1\\ssub\\sto\\srustafur!;msg-param-months=6;msg-param-origin-id=4645652708379472175;msg-param-recipient-id=27787997;msg-param-sub-plan=1000;msg-id=subgift;msg-param-recipient-display-name=rustafur;msg-param-recipient-user-name=rustafur;msg-param-community-gift-id=4645652708379472175;msg-param-sender-count=0 :tmi.twitch.tv USERNOTICE #pajlada",
"output": [
{
"badgeInfos": {
},
"badges": [
],
"channelName": "",
"count": 1,
"displayName": "",
"elements": [
{
"element": {
"color": "System",
"flags": "Timestamp",
"link": {
"type": "None",
"value": ""
},
"style": "TimestampMedium",
"tooltip": "",
"trailingSpace": true,
"type": "TextElement",
"words": [
"9:19"
]
},
"flags": "Timestamp",
"format": "",
"link": {
"type": "None",
"value": ""
},
"time": "09:19:57",
"tooltip": "",
"trailingSpace": true,
"type": "TimestampElement"
},
{
"color": "Text",
"fallbackColor": "System",
"flags": "Text|Mention",
"link": {
"type": "None",
"value": ""
},
"style": "ChatMedium",
"tooltip": "",
"trailingSpace": true,
"type": "MentionElement",
"userColor": "#ffcc44ff",
"userLoginName": "pajlada",
"words": [
"pajlada"
]
},
{
"color": "System",
"flags": "Text",
"link": {
"type": "None",
"value": ""
},
"style": "ChatMedium",
"tooltip": "",
"trailingSpace": true,
"type": "TextElement",
"words": [
"gifted",
"a",
"Tier",
"1",
"sub",
"to"
]
},
{
"color": "Text",
"fallbackColor": "System",
"flags": "Text|Mention",
"link": {
"type": "None",
"value": ""
},
"style": "ChatMedium",
"tooltip": "",
"trailingSpace": false,
"type": "MentionElement",
"userColor": "#ffff00ff",
"userLoginName": "rustafur",
"words": [
"rustafur"
]
},
{
"color": "System",
"flags": "Text",
"link": {
"type": "None",
"value": ""
},
"style": "ChatMedium",
"tooltip": "",
"trailingSpace": true,
"type": "TextElement",
"words": [
"!"
]
}
],
"flags": "System|DoNotTriggerNotification|Subscription",
"id": "",
"localizedName": "",
"loginName": "",
"messageText": "pajlada gifted a Tier 1 sub to rustafur!",
"searchText": "pajlada gifted a Tier 1 sub to rustafur!",
"serverReceivedTime": "",
"timeoutUser": "",
"userID": "",
"usernameColor": "#ff000000"
}
],
"params": {
"userData": {
"27787997": {
"color": "#FF00FF"
}
}
}
}
+11
View File
@@ -576,6 +576,17 @@ TEST_P(TestIrcMessageHandlerP, Run)
VectorMessageSink sink;
const auto &userData = snapshot->param("userData").toObject();
for (auto it = userData.begin(); it != userData.end(); ++it)
{
const auto &userID = it.key();
const auto &data = it.value().toObject();
if (auto color = data.value("color").toString(); !color.isEmpty())
{
this->mockApplication->getUserData()->setUserColor(userID, color);
}
}
for (auto prevInput : snapshot->param("prevMessages").toArray())
{
auto *ircMessage = Communi::IrcMessage::fromData(
+141
View File
@@ -0,0 +1,141 @@
#include "common/ChannelChatters.hpp"
#include "mocks/BaseApplication.hpp"
#include "mocks/Channel.hpp"
#include "mocks/Logging.hpp"
#include "mocks/UserData.hpp"
#include "providers/twitch/UserColor.hpp"
#include "Test.hpp"
#include <QString>
namespace chatterino::twitch {
namespace {
class MockApplication : public mock::BaseApplication
{
public:
MockApplication() = default;
ILogging *getChatLogger() override
{
return &this->logging;
}
mock::EmptyLogging logging;
};
} // namespace
class TwitchUserColor : public ::testing::Test
{
protected:
void SetUp() override
{
this->app = std::make_unique<MockApplication>();
this->userDataController = std::make_unique<mock::UserDataController>();
this->channel = std::make_unique<mock::MockChannel>("test");
this->chatters = std::make_unique<ChannelChatters>(*this->channel);
}
void TearDown() override
{
this->chatters.reset();
this->channel.reset();
this->userDataController.reset();
this->app.reset();
}
std::unique_ptr<MockApplication> app;
std::unique_ptr<mock::UserDataController> userDataController;
std::unique_ptr<mock::MockChannel> channel;
std::unique_ptr<ChannelChatters> chatters;
};
TEST_F(TwitchUserColor, NoDataForUser)
{
ASSERT_EQ(getUserColor({
.userLogin = "pajlada",
.userID = "11148817",
.userDataController = userDataController.get(),
.channelChatters = chatters.get(),
.color = {},
}),
std::nullopt);
}
TEST_F(TwitchUserColor, ChannelChattersData)
{
// User exists in channel chatters.
// Their color should be fetched from there.
chatters->setUserColor("pajlada", QColor("#FF0000"));
ASSERT_EQ(getUserColor({
.userLogin = "pajlada",
.userID = "11148817",
.userDataController = userDataController.get(),
.channelChatters = chatters.get(),
.color = {},
}),
QColor("#FF0000"));
}
TEST_F(TwitchUserColor, ChannelChattersDataButBaseColor)
{
// User exists in channel chatters
// The base color is valid and should be used.
chatters->setUserColor("pajlada", QColor("#FF0000"));
ASSERT_EQ(getUserColor({
.userLogin = "pajlada",
.userID = "11148817",
.userDataController = userDataController.get(),
.channelChatters = chatters.get(),
.color = QColor("#00FF00"),
}),
QColor("#00FF00"));
}
TEST_F(TwitchUserColor, ChannelChattersDataButBaseColorInvalid)
{
// User exists in channel chatters
// A base color has been defined but it's invalid
// The channel chatter color should be used
ASSERT_EQ(0, chatters->colorsSize());
chatters->setUserColor("pajlada", QColor("#FF0000"));
ASSERT_EQ(getUserColor({
.userLogin = "pajlada",
.userID = "11148817",
.userDataController = userDataController.get(),
.channelChatters = chatters.get(),
.color = QColor("this is an invalid color"),
}),
QColor("#FF0000"));
}
TEST_F(TwitchUserColor, UCD)
{
// User exists in channel chatters
// A base color has been defined
// User exists in user data controller
// The user data controller color should be used
chatters->setUserColor("pajlada", QColor("#FF0000"));
userDataController->setUserColor("11148817", "#0000FF");
ASSERT_EQ(getUserColor({
.userLogin = "pajlada",
.userID = "11148817",
.userDataController = userDataController.get(),
.channelChatters = chatters.get(),
.color = QColor("#00FF00"),
}),
QColor("#0000FF"));
}
} // namespace chatterino::twitch