Skip to content

Commit

Permalink
feat: more hype chat
Browse files Browse the repository at this point in the history
  • Loading branch information
Nerixyz committed Jul 2, 2023
1 parent 7652707 commit 75fc3fc
Show file tree
Hide file tree
Showing 2 changed files with 102 additions and 7 deletions.
103 changes: 96 additions & 7 deletions src/providers/twitch/IrcMessageHandler.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#include "IrcMessageHandler.hpp"

#include "Application.hpp"
#include "common/Literals.hpp"
#include "common/QLogging.hpp"
#include "controllers/accounts/AccountController.hpp"
#include "messages/LimitedQueue.hpp"
Expand All @@ -26,12 +27,17 @@
#include "util/StreamerMode.hpp"

#include <IrcMessage>
#include <QLocale>
#include <QStringBuilder>

#include <chrono>
#include <memory>
#include <unordered_set>

namespace {
using namespace chatterino;
using namespace chatterino::literals;
using namespace std::chrono_literals;

// Message types below are the ones that might contain special user's message on USERNOTICE
static const QSet<QString> specialMessageTypes{
Expand All @@ -43,6 +49,19 @@ static const QSet<QString> specialMessageTypes{
"announcement", // new mod announcement thing
};

struct PinnedChatPaidLevel {
std::chrono::duration<uint32_t> duration;
uint8_t numeric;
};

const QHash<QString, PinnedChatPaidLevel> PINNED_CHAT_PAID_LEVEL = {
{u"ONE"_s, {30s, 1}}, {u"TWO"_s, {2min + 30s, 2}},
{u"THREE"_s, {5min, 3}}, {u"FOUR"_s, {10min, 4}},
{u"FIVE"_s, {30min, 5}}, {u"SIX"_s, {1h, 6}},
{u"SEVEN"_s, {2h, 7}}, {u"EIGHT"_s, {3h, 8}},
{u"NINE"_s, {4h, 9}}, {u"TEN"_s, {5h, 10}},
};

MessagePtr generateBannedMessage(bool confirmedBan)
{
const auto linkColor = MessageColor(MessageColor::Link);
Expand Down Expand Up @@ -156,9 +175,60 @@ void updateReplyParticipatedStatus(const QVariantMap &tags,
}
}

ChannelPtr channelOrEmptyByTarget(const QString &target,
TwitchIrcServer &server)
{
QString channelName;
if (!trimChannelName(target, channelName))
{
return Channel::getEmpty();
}

return server.getChannelOrEmpty(channelName);
}

MessagePtr parsePinnedChat(Communi::IrcPrivateMessage *message)
{
auto level = message->tag(u"pinned-chat-paid-level"_s).toString();
auto currency = message->tag(u"pinned-chat-paid-currency"_s).toString();
bool okAmount = false;
auto amount = message->tag(u"pinned-chat-paid-amount"_s).toInt(&okAmount);
bool okExponent = false;
auto exponent =
message->tag(u"pinned-chat-paid-exponent"_s).toInt(&okExponent);
if (!okAmount || !okExponent || currency.isEmpty())
{
return {};
}
// additionally, there's `pinned-chat-paid-is-system-message` which isn't used by Chatterino.

QString subtitle;
auto levelIt = PINNED_CHAT_PAID_LEVEL.find(level);
if (levelIt != PINNED_CHAT_PAID_LEVEL.end())
{
subtitle = u"Level %1 Hype Chat ("_s.arg(levelIt->numeric) %
formatTime(int(levelIt->duration.count())) % (") ");
}
else
{
subtitle = u"Hype Chat "_s;
}

// actualAmount = amount * 10^(-exponent)
double actualAmount = std::pow(10.0, double(-exponent)) * double(amount);
subtitle += QLocale::system().toCurrencyString(actualAmount, currency);

MessageBuilder builder(systemMessage, parseTagString(subtitle),
calculateMessageTime(message).time());
builder->flags.set(MessageFlag::ElevatedMessage);
return builder.release();
}

} // namespace
namespace chatterino {

using namespace literals;

static float relativeSimilarity(const QString &str1, const QString &str2)
{
// Longest Common Substring Problem
Expand Down Expand Up @@ -314,6 +384,16 @@ std::vector<MessagePtr> IrcMessageHandler::parsePrivMessage(
builtMessages.emplace_back(builder.build());
builder.triggerHighlights();
}

if (message->tags().contains(u"pinned-chat-paid-amount"_s))
{
auto ptr = parsePinnedChat(message);
if (ptr)
{
builtMessages.emplace_back(std::move(ptr));
}
}

return builtMessages;
}

Expand All @@ -330,6 +410,21 @@ void IrcMessageHandler::handlePrivMessage(Communi::IrcPrivateMessage *message,
message, message->target(),
message->content().replace(COMBINED_FIXER, ZERO_WIDTH_JOINER), server,
false, message->isAction());

auto chan = channelOrEmptyByTarget(message->target(), server);
if (chan->isEmpty())
{
return;
}

if (message->tags().contains(u"pinned-chat-paid-amount"_s))
{
auto ptr = parsePinnedChat(message);
if (ptr)
{
chan->addMessage(ptr);
}
}
}

std::vector<MessagePtr> IrcMessageHandler::parseMessageWithReply(
Expand Down Expand Up @@ -442,13 +537,7 @@ void IrcMessageHandler::addMessage(Communi::IrcMessage *_message,
TwitchIrcServer &server, bool isSub,
bool isAction)
{
QString channelName;
if (!trimChannelName(target, channelName))
{
return;
}

auto chan = server.getChannelOrEmpty(channelName);
auto chan = channelOrEmptyByTarget(target, server);

if (chan->isEmpty())
{
Expand Down
6 changes: 6 additions & 0 deletions src/util/SampleData.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,13 @@ const QStringList &getSampleMiscMessages()
R"(@badge-info=subscriber/47;badges=broadcaster/1,subscriber/3012,twitchconAmsterdam2020/1;color=#FF0000;display-name=Supinic;emotes=;flags=;id=8c26e1ab-b50c-4d9d-bc11-3fd57a941d90;login=supinic;mod=0;msg-id=announcement;msg-param-color=PRIMARY;room-id=31400525;subscriber=1;system-msg=;tmi-sent-ts=1648762219962;user-id=31400525;user-type= :tmi.twitch.tv USERNOTICE #supinic :mm test lol)",

// Elevated Message (Paid option for keeping a message in chat longer)
// no level
R"(@badge-info=subscriber/3;badges=subscriber/0,bits-charity/1;color=#0000FF;display-name=SnoopyTheBot;emotes=;first-msg=0;flags=;id=8779a9e5-cf1b-47b3-b9fe-67a5b1b605f6;mod=0;pinned-chat-paid-amount=500;pinned-chat-paid-canonical-amount=5;pinned-chat-paid-currency=USD;pinned-chat-paid-exponent=2;returning-chatter=0;room-id=36340781;subscriber=1;tmi-sent-ts=1664505974154;turbo=0;user-id=136881249;user-type= :[email protected] PRIVMSG #pajlada :-$5)",
// level 1
R"(@pinned-chat-paid-level=ONE;mod=0;flags=;pinned-chat-paid-amount=1400;pinned-chat-paid-exponent=2;tmi-sent-ts=1687970631828;subscriber=1;user-type=;color=#9DA364;emotes=;badges=predictions/blue-1,subscriber/60,twitchconAmsterdam2020/1;pinned-chat-paid-canonical-amount=1400;turbo=0;user-id=26753388;id=e6681ba0-cdc6-4482-93a3-515b74361e8b;room-id=36340781;first-msg=0;returning-chatter=0;pinned-chat-paid-currency=NOK;pinned-chat-paid-is-system-message=0;badge-info=predictions/Day\s53/53\sforsenSmug,subscriber/67;display-name=matrHS :[email protected] PRIVMSG #pajlada :Title: Beating the record. but who is recordingLOL)",
R"(@flags=;pinned-chat-paid-amount=8761;turbo=0;user-id=35669184;pinned-chat-paid-level=ONE;user-type=;pinned-chat-paid-canonical-amount=8761;badge-info=subscriber/2;badges=subscriber/2,sub-gifter/1;emotes=;pinned-chat-paid-exponent=2;subscriber=1;mod=0;room-id=36340781;returning-chatter=0;id=289b614d-1837-4cff-ac22-ce33a9735323;first-msg=0;tmi-sent-ts=1687631719188;color=#00FF7F;pinned-chat-paid-currency=RUB;display-name=Danis;pinned-chat-paid-is-system-message=0 :[email protected] PRIVMSG #pajlada :-1 lulw)",
// level 2
R"(@room-id=36340781;tmi-sent-ts=1687970634371;flags=;id=39a80a3d-c16e-420f-9bbb-faba4976a3bb;badges=subscriber/6,premium/1;emotes=;display-name=rickharrisoncoc;pinned-chat-paid-level=TWO;turbo=0;pinned-chat-paid-amount=500;pinned-chat-paid-is-system-message=0;color=#FF69B4;subscriber=1;user-type=;first-msg=0;pinned-chat-paid-currency=USD;pinned-chat-paid-canonical-amount=500;user-id=518404689;badge-info=subscriber/10;pinned-chat-paid-exponent=2;returning-chatter=0;mod=0 :[email protected] PRIVMSG #pajlada :forsen please read my super chat. Please.)",
};
return list;
}
Expand Down

0 comments on commit 75fc3fc

Please sign in to comment.