deps: Update libcommuni and use Communi::TagsRef (#7134)

This updates `libcommuni` to include
https://github.com/Chatterino/libcommuni/pull/13 which refactors the tag
handling (see PR for the reasons).

The only change here is the replacement of the map and the lookup
functions.

Reviewed-by: pajlada <rasmus.karlsson@pajlada.com>
This commit is contained in:
Nerixyz
2026-07-26 17:23:17 +00:00
committed by GitHub
parent 1e5dd7363b
commit 772c291196
8 changed files with 187 additions and 208 deletions
+80 -95
View File
@@ -523,15 +523,15 @@ EmotePtr parseEmote(TwitchChannel *twitchChannel, const EmoteName &name)
return {};
}
std::pair<QString, bool> parseMessageType(const QVariantMap &tags)
std::pair<QString, bool> parseMessageType(Communi::TagsRef tags)
{
auto msgId = tags.value("msg-id").toString();
auto msgId = tags.getOrEmpty("msg-id");
bool mirrored = msgId == "sharedchatnotice";
if (mirrored)
{
msgId = tags.value("source-msg-id").toString();
msgId = tags.getOrEmpty("source-msg-id");
}
// TODO: room-id & source-room-id comparison?
@@ -618,33 +618,30 @@ MessagePtrMut MessageBuilder::makeSystemMessageWithUser(
return builder.release();
}
MessagePtrMut MessageBuilder::makeSubgiftMessage(const QVariantMap &tags,
MessagePtrMut MessageBuilder::makeSubgiftMessage(Communi::TagsRef tags,
const QTime &time,
TwitchChannel *channel)
{
auto text = parseTagString(tags.value("system-msg").toString());
auto text = parseTagString(tags.getOrEmpty("system-msg"));
if (auto monthsIt = tags.find("msg-param-gift-months");
monthsIt != tags.end())
if (auto monthsStr = tags.get("msg-param-gift-months"))
{
int months = monthsIt.value().toInt();
int months = monthsStr->toInt();
if (months > 1)
{
auto plan = tags.value("msg-param-sub-plan").toString();
QString name =
ANONYMOUS_GIFTER_ID == tags.value("user-id").toString()
? "An anonymous user"
: tags.value("display-name").toString();
text = QString("%1 gifted %2 months of a Tier %3 sub to %4!")
.arg(name, QString::number(months),
plan.isEmpty() ? '1' : plan.at(0),
tags.value("msg-param-recipient-display-name")
.toString());
auto plan = tags.getOrEmpty("msg-param-sub-plan");
QString name = ANONYMOUS_GIFTER_ID == tags.getOrEmpty("user-id")
? "An anonymous user"
: tags.getOrEmpty("display-name");
text =
QString("%1 gifted %2 months of a Tier %3 sub to %4!")
.arg(name, QString::number(months),
plan.isEmpty() ? '1' : plan.at(0),
tags.getOrEmpty("msg-param-recipient-display-name"));
if (auto countIt = tags.find("msg-param-sender-count");
countIt != tags.end())
if (auto countStr = tags.get("msg-param-sender-count"))
{
int count = countIt.value().toInt();
int count = countStr->toInt();
if (count > months)
{
text += QString(" They've gifted %1 months in the channel.")
@@ -660,31 +657,31 @@ MessagePtrMut MessageBuilder::makeSubgiftMessage(const QVariantMap &tags,
MessageBuilder builder;
builder.emplace<TimestampElement>(time);
auto gifterLogin = tags.value("login").toString();
auto gifterDisplayName = tags.value("display-name").toString();
auto gifterLogin = tags.getOrEmpty("login");
auto gifterDisplayName = tags.getOrEmpty("display-name");
if (gifterDisplayName.isEmpty())
{
gifterDisplayName = gifterLogin;
}
auto gifterColor =
twitch::getUserColor({
.userLogin = gifterLogin,
.userID = tags.value("user-id").toString(),
.userDataController = userDataController,
.channelChatters = channel,
.color = tags.value("color").value<QColor>(),
})
twitch::getUserColor(
{
.userLogin = gifterLogin,
.userID = tags.getOrEmpty("user-id"),
.userDataController = userDataController,
.channelChatters = channel,
.color = QColor::fromString(tags.getOrEmpty("color")),
})
.value_or(MessageColor::System);
auto recipientLogin =
tags.value("msg-param-recipient-user-name").toString();
auto recipientLogin = tags.getOrEmpty("msg-param-recipient-user-name");
if (recipientLogin.isEmpty())
{
recipientLogin = tags.value("msg-param-recipient-name").toString();
recipientLogin = tags.getOrEmpty("msg-param-recipient-name");
}
auto recipientDisplayName =
tags.value("msg-param-recipient-display-name").toString();
tags.getOrEmpty("msg-param-recipient-display-name");
if (recipientDisplayName.isEmpty())
{
recipientDisplayName = recipientLogin;
@@ -694,7 +691,7 @@ MessagePtrMut MessageBuilder::makeSubgiftMessage(const QVariantMap &tags,
twitch::getUserColor(
{
.userLogin = recipientLogin,
.userID = tags.value("msg-param-recipient-id").toString(),
.userID = tags.getOrEmpty("msg-param-recipient-id"),
.userDataController = userDataController,
.channelChatters = channel,
@@ -1673,7 +1670,7 @@ std::pair<MessagePtrMut, HighlightAlert> MessageBuilder::makeIrcMessage(
if (args.allowIgnore)
{
bool ignored = MessageBuilder::isIgnored(
content, tags.value("user-id").toString(), channel);
content, tags.getOrEmpty("user-id"), channel);
if (ignored)
{
return {};
@@ -1682,7 +1679,7 @@ std::pair<MessagePtrMut, HighlightAlert> MessageBuilder::makeIrcMessage(
auto *twitchChannel = dynamic_cast<TwitchChannel *>(channel);
auto userID = tags.value("user-id").toString();
auto userID = tags.getOrEmpty("user-id");
MessageBuilder builder;
builder.parseUsernameColor(tags, userID);
@@ -1725,22 +1722,22 @@ std::pair<MessagePtrMut, HighlightAlert> MessageBuilder::makeIrcMessage(
builder.appendChannelName(channel);
if (tags.contains("rm-deleted"))
if (tags.has("rm-deleted"))
{
builder->flags.set(MessageFlag::Disabled);
}
builder.parseMessageTags(tags);
if (tags.contains("first-msg") && tags["first-msg"].toString() == "1")
if (tags.getOrEmpty("first-msg") == "1")
{
builder->flags.set(MessageFlag::FirstMessage);
}
if (tags.contains("bits"))
if (auto bits = tags.get("bits"))
{
builder->flags.set(MessageFlag::CheerMessage);
builder->bits = tags["bits"].toInt();
builder->bits = bits->toInt();
}
// reply threads
@@ -1757,8 +1754,7 @@ std::pair<MessagePtrMut, HighlightAlert> MessageBuilder::makeIrcMessage(
return false;
}
if (tags.value("user-type").toString() == "mod" &&
!userIsStaffOrBroadcaster)
if (tags.getOrEmpty("user-type") == "mod" && !userIsStaffOrBroadcaster)
{
// You cannot timeout moderators UNLESS you are Twitch Staff or the broadcaster of the channel
// TODO: This is actually incorrect now - Twitch Staff do not have universal permission to timeout moderators anymore
@@ -1782,14 +1778,11 @@ std::pair<MessagePtrMut, HighlightAlert> MessageBuilder::makeIrcMessage(
builder.appendUsername(tags, args);
TextState textState{.twitchChannel = twitchChannel};
QString bits;
auto iterator = tags.find("bits");
if (iterator != tags.end())
if (auto optBits = tags.get("bits"))
{
textState.hasBits = true;
textState.bitsLeft = iterator.value().toInt();
bits = iterator.value().toString();
textState.bitsLeft = optBits->toInt();
}
// Twitch emotes
@@ -1824,7 +1817,7 @@ std::pair<MessagePtrMut, HighlightAlert> MessageBuilder::makeIrcMessage(
// highlights
HighlightAlert highlight = builder.parseHighlights(tags, content, args);
if (tags.contains("historical"))
if (tags.has("historical"))
{
highlight.playSound = false;
highlight.windowAlert = false;
@@ -1838,7 +1831,7 @@ std::pair<MessagePtrMut, HighlightAlert> MessageBuilder::makeIrcMessage(
ColorProvider::instance().color(ColorType::Whisper);
}
if (!args.isReceivedWhisper && tags.value("msg-id") != "announcement")
if (!args.isReceivedWhisper && tags.getOrEmpty("msg-id") != "announcement")
{
if (thread)
{
@@ -1994,7 +1987,7 @@ TextElement *MessageBuilder::emplaceSystemTextAndUpdate(const QString &text,
MessageColor::System);
}
void MessageBuilder::parseUsernameColor(const QVariantMap &tags,
void MessageBuilder::parseUsernameColor(Communi::TagsRef tags,
const QString &userID)
{
const auto *userData = getApp()->getUserData();
@@ -2010,21 +2003,20 @@ void MessageBuilder::parseUsernameColor(const QVariantMap &tags,
}
}
const auto iterator = tags.find("color");
if (iterator != tags.end())
if (const auto color = tags.getOrEmpty("color"); !color.isEmpty())
{
if (const auto color = iterator.value().toString(); !color.isEmpty())
{
this->usernameColor_ = QColor(color);
this->message().usernameColor = this->usernameColor_;
return;
}
this->usernameColor_ = QColor(color);
this->message().usernameColor = this->usernameColor_;
return;
}
if (getSettings()->colorizeNicknames && tags.contains("user-id"))
if (getSettings()->colorizeNicknames)
{
this->usernameColor_ = getRandomColor(tags.value("user-id").toString());
this->message().usernameColor = this->usernameColor_;
if (auto userID = tags.get("user-id"))
{
this->usernameColor_ = getRandomColor(*userID);
this->message().usernameColor = this->usernameColor_;
}
}
}
@@ -2054,17 +2046,15 @@ void MessageBuilder::parseUsername(const Communi::IrcMessage *ircMessage,
}
}
void MessageBuilder::parseMessageID(const QVariantMap &tags)
void MessageBuilder::parseMessageID(Communi::TagsRef tags)
{
auto iterator = tags.find("id");
if (iterator != tags.end())
if (auto id = tags.get("id"))
{
this->message().id = iterator.value().toString();
this->message().id = *id;
}
}
void MessageBuilder::parseMessageTags(const QVariantMap &tags)
void MessageBuilder::parseMessageTags(Communi::TagsRef tags)
{
const auto [messageType, mirrored] = parseMessageType(tags);
@@ -2082,11 +2072,11 @@ void MessageBuilder::parseMessageTags(const QVariantMap &tags)
{
this->message().flags.set(MessageFlag::Announcement);
if (auto cit = tags.constFind("msg-param-color"); cit != tags.end())
if (auto color = tags.get("msg-param-color"))
{
this->message().announcementColor =
qmagicenum::enumCast<HelixAnnouncementColor>(
cit->toString(), qmagicenum::CASE_INSENSITIVE)
*color, qmagicenum::CASE_INSENSITIVE)
.value_or(HelixAnnouncementColor::Primary);
}
}
@@ -2107,7 +2097,7 @@ void MessageBuilder::parseMessageTags(const QVariantMap &tags)
}
}
QString MessageBuilder::parseRoomID(const QVariantMap &tags,
QString MessageBuilder::parseRoomID(Communi::TagsRef tags,
TwitchChannel *twitchChannel)
{
if (twitchChannel == nullptr)
@@ -2115,11 +2105,9 @@ QString MessageBuilder::parseRoomID(const QVariantMap &tags,
return {};
}
auto iterator = tags.find("room-id");
if (iterator != std::end(tags))
if (auto optRoomID = tags.get("room-id"))
{
auto roomID = iterator->toString();
const auto &roomID = *optRoomID;
if (twitchChannel->roomId() != roomID)
{
if (twitchChannel->roomId().isEmpty())
@@ -2140,7 +2128,7 @@ QString MessageBuilder::parseRoomID(const QVariantMap &tags,
return {};
}
TwitchChannel *MessageBuilder::parseSharedChatInfo(const QVariantMap &tags,
TwitchChannel *MessageBuilder::parseSharedChatInfo(Communi::TagsRef tags,
TwitchChannel *twitchChannel)
{
if (!twitchChannel)
@@ -2148,9 +2136,9 @@ TwitchChannel *MessageBuilder::parseSharedChatInfo(const QVariantMap &tags,
return twitchChannel;
}
if (auto it = tags.find("source-room-id"); it != tags.end())
if (auto optSourceRoom = tags.get("source-room-id"))
{
auto sourceRoom = it.value().toString();
const auto &sourceRoom = *optSourceRoom;
if (twitchChannel->roomId() != sourceRoom)
{
this->message().flags.set(MessageFlag::SharedMessage);
@@ -2175,8 +2163,7 @@ TwitchChannel *MessageBuilder::parseSharedChatInfo(const QVariantMap &tags,
}
void MessageBuilder::parseThread(const QString &messageContent,
const QVariantMap &tags,
const Channel *channel,
Communi::TagsRef tags, const Channel *channel,
const std::shared_ptr<MessageThread> &thread,
const MessagePtr &parent)
{
@@ -2235,15 +2222,15 @@ void MessageBuilder::parseThread(const QString &messageContent,
color, FontStyle::ChatMediumSmall)
->setLink({Link::ViewThread, thread->rootId()});
}
else if (tags.find("reply-parent-msg-id") != tags.end())
else if (tags.has("reply-parent-msg-id"))
{
// Message is a reply but we couldn't find the original message.
// Render the message using the additional reply tags
auto replyDisplayName = tags.find("reply-parent-display-name");
auto replyBody = tags.find("reply-parent-msg-body");
auto replyDisplayName = tags.get("reply-parent-display-name");
auto replyBody = tags.get("reply-parent-msg-body");
if (replyDisplayName != tags.end() && replyBody != tags.end())
if (replyDisplayName && replyBody)
{
QString body;
@@ -2253,7 +2240,7 @@ void MessageBuilder::parseThread(const QString &messageContent,
MessageColor::System, FontStyle::ChatMediumSmall);
bool ignored = MessageBuilder::isIgnored(
messageContent, tags.value("reply-parent-user-id").toString(),
messageContent, tags.getOrEmpty("reply-parent-user-id"),
channel);
if (ignored)
{
@@ -2261,8 +2248,8 @@ void MessageBuilder::parseThread(const QString &messageContent,
}
else
{
auto name = replyDisplayName->toString();
body = parseTagString(replyBody->toString());
const auto &name = *replyDisplayName;
body = parseTagString(*replyBody);
this->emplace<TextElement>(
"@" + name + ":", MessageElementFlag::RepliedMessage,
@@ -2279,7 +2266,7 @@ void MessageBuilder::parseThread(const QString &messageContent,
}
}
HighlightAlert MessageBuilder::parseHighlights(const QVariantMap &tags,
HighlightAlert MessageBuilder::parseHighlights(Communi::TagsRef tags,
const QString &originalMessage,
const MessageParseArgs &args)
{
@@ -2334,7 +2321,7 @@ void MessageBuilder::appendChannelName(const Channel *channel)
->setLink(link);
}
void MessageBuilder::appendUsername(const QVariantMap &tags,
void MessageBuilder::appendUsername(Communi::TagsRef tags,
const MessageParseArgs &args)
{
auto *app = getApp();
@@ -2342,11 +2329,9 @@ void MessageBuilder::appendUsername(const QVariantMap &tags,
QString username = this->message_->loginName;
QString localizedName;
auto iterator = tags.find("display-name");
if (iterator != tags.end())
if (auto optDisplayName = tags.get("display-name"))
{
QString displayName =
parseTagString(iterator.value().toString()).trimmed();
QString displayName = parseTagString(*optDisplayName).trimmed();
if (QString::compare(displayName, username, Qt::CaseInsensitive) == 0)
{
@@ -2551,7 +2536,7 @@ void MessageBuilder::addWords(
}
}
void MessageBuilder::appendTwitchBadges(const QVariantMap &tags,
void MessageBuilder::appendTwitchBadges(Communi::TagsRef tags,
TwitchChannel *twitchChannel)
{
if (twitchChannel == nullptr)
@@ -2565,7 +2550,7 @@ void MessageBuilder::appendTwitchBadges(const QVariantMap &tags,
(getSettings()->sharedChatAlwaysShowBadge &&
!twitchChannel->getSharedChatSessionParticipants().empty()))
{
const QString sourceId = tags["source-room-id"].toString();
const QString sourceId = tags.getOrEmpty("source-room-id");
QString sourceName;
QString sourceProfilePicture;
QString sourceLogin;
+11 -10
View File
@@ -10,6 +10,7 @@
#include "messages/MessageFlag.hpp"
#include <IrcMessage>
#include <IrcTagsRef>
#include <QRegularExpression>
#include <QString>
#include <QTime>
@@ -241,7 +242,7 @@ public:
const QString &displayName, const MessageColor &userColor,
const QTime &time, const Communi::IrcMessage &ircMessage);
static MessagePtrMut makeSubgiftMessage(const QVariantMap &tags,
static MessagePtrMut makeSubgiftMessage(Communi::TagsRef tags,
const QTime &time,
TwitchChannel *channel);
@@ -277,18 +278,18 @@ private:
std::unique_ptr<MessageElement> releaseBack();
void parse();
void parseUsernameColor(const QVariantMap &tags, const QString &userID);
void parseUsernameColor(Communi::TagsRef tags, const QString &userID);
void parseUsername(const Communi::IrcMessage *ircMessage,
TwitchChannel *twitchChannel,
bool trimSubscriberUsername);
void parseMessageID(const QVariantMap &tags);
void parseMessageID(Communi::TagsRef tags);
/// Parses most of them message flags based on the given tags
void parseMessageTags(const QVariantMap &tags);
void parseMessageTags(Communi::TagsRef tags);
/// Parses the room-ID this message was received in
///
/// @returns The room-ID
static QString parseRoomID(const QVariantMap &tags,
static QString parseRoomID(Communi::TagsRef tags,
TwitchChannel *twitchChannel);
/// Parses the shared-chat information from this message.
@@ -298,28 +299,28 @@ private:
/// @returns The source channel - the channel this message originated from.
/// If there's no channel currently open, @a twitchChannel is
/// returned.
TwitchChannel *parseSharedChatInfo(const QVariantMap &tags,
TwitchChannel *parseSharedChatInfo(Communi::TagsRef tags,
TwitchChannel *twitchChannel);
// Parse & build thread information into the message
// Will read information from thread_ or from IRC tags
void parseThread(const QString &messageContent, const QVariantMap &tags,
void parseThread(const QString &messageContent, Communi::TagsRef tags,
const Channel *channel,
const std::shared_ptr<MessageThread> &thread,
const MessagePtr &parent);
// parseHighlights only updates the visual state of the message, but leaves the playing of alerts and sounds to the triggerHighlights function
HighlightAlert parseHighlights(const QVariantMap &tags,
HighlightAlert parseHighlights(Communi::TagsRef tags,
const QString &originalMessage,
const MessageParseArgs &args);
void appendChannelName(const Channel *channel);
void appendUsername(const QVariantMap &tags, const MessageParseArgs &args);
void appendUsername(Communi::TagsRef tags, const MessageParseArgs &args);
void addWords(const QStringList &words,
const std::vector<TwitchEmoteOccurrence> &twitchEmotes,
TextState &state);
void appendTwitchBadges(const QVariantMap &tags,
void appendTwitchBadges(Communi::TagsRef tags,
TwitchChannel *twitchChannel);
void appendChatterinoBadges(const QString &userID);
void appendFfzBadges(TwitchChannel *twitchChannel, const QString &userID);
+2 -3
View File
@@ -56,11 +56,10 @@ std::vector<MessagePtr> buildRecentMessages(
for (auto *message : messages)
{
if (message->tags().contains("rm-received-ts"))
if (auto optReceivedTs = message->tags().get("rm-received-ts"))
{
const auto msgDate =
QDateTime::fromMSecsSinceEpoch(
message->tags().value("rm-received-ts").toLongLong())
QDateTime::fromMSecsSinceEpoch(optReceivedTs->toLongLong())
.date();
// Check if we need to insert a message stating that a new day began
+69 -74
View File
@@ -97,7 +97,7 @@ MessagePtr generateBannedMessage(bool confirmedBan)
return builder.release();
}
int stripLeadingReplyMention(const QVariantMap &tags, QString &content)
int stripLeadingReplyMention(Communi::TagsRef tags, QString &content)
{
if (!getSettings()->stripReplyMention)
{
@@ -109,10 +109,9 @@ int stripLeadingReplyMention(const QVariantMap &tags, QString &content)
return 0;
}
if (const auto it = tags.find("reply-parent-display-name");
it != tags.end())
if (auto optDisplayName = tags.get("reply-parent-display-name"))
{
auto displayName = parseTagString(it.value().toString());
auto displayName = parseTagString(*optDisplayName);
if (content.length() <= 1 + displayName.length())
{
@@ -133,8 +132,7 @@ int stripLeadingReplyMention(const QVariantMap &tags, QString &content)
return 0;
}
void checkThreadSubscription(const QVariantMap &tags,
const QString &senderLogin,
void checkThreadSubscription(Communi::TagsRef tags, const QString &senderLogin,
std::shared_ptr<MessageThread> &thread)
{
if (thread->subscribed() || thread->unsubscribed())
@@ -151,11 +149,9 @@ void checkThreadSubscription(const QVariantMap &tags,
{
thread->markSubscribed();
}
else if (const auto it = tags.find("reply-parent-user-login");
it != tags.end())
else if (auto optName = tags.get("reply-parent-user-login"))
{
auto name = it.value().toString();
if (name == currentLogin)
if (*optName == currentLogin)
{
thread->markSubscribed();
}
@@ -275,7 +271,7 @@ MessagePtr parseNoticeMessage(Communi::IrcNoticeMessage *message)
return {generateBannedMessage(true)};
}
if (message->tags().value("msg-id") == "msg_timedout")
if (message->tags().getOrEmpty("msg-id") == "msg_timedout")
{
QString remainingTime =
formatTime(message->content().split(" ").value(5));
@@ -360,7 +356,7 @@ void IrcMessageHandler::parseMessageInto(Communi::IrcMessage *message,
auto tags = message->tags();
QString targetID = tags.value("target-msg-id").toString();
QString targetID = tags.getOrEmpty("target-msg-id");
auto msg = sink.findMessageByID(targetID);
if (msg == nullptr)
@@ -458,35 +454,34 @@ void IrcMessageHandler::handleRoomStateMessage(Communi::IrcMessage *message)
// room-id
if (auto it = tags.find("room-id"); it != tags.end())
if (auto optRoomId = tags.get("room-id"))
{
auto roomId = it.value().toString();
twitchChannel->setRoomId(roomId);
twitchChannel->setRoomId(*std::move(optRoomId));
}
// Room modes
{
auto roomModes = *twitchChannel->accessRoomModes();
if (auto it = tags.find("emote-only"); it != tags.end())
if (auto value = tags.get("emote-only"))
{
roomModes.emoteOnly = it.value() == "1";
roomModes.emoteOnly = *value == "1";
}
if (auto it = tags.find("subs-only"); it != tags.end())
if (auto value = tags.get("subs-only"))
{
roomModes.submode = it.value() == "1";
roomModes.submode = *value == "1";
}
if (auto it = tags.find("slow"); it != tags.end())
if (auto value = tags.get("slow"))
{
roomModes.slowMode = it.value().toInt();
roomModes.slowMode = value->toInt();
}
if (auto it = tags.find("r9k"); it != tags.end())
if (auto value = tags.get("r9k"))
{
roomModes.r9k = it.value() == "1";
roomModes.r9k = *value == "1";
}
if (auto it = tags.find("followers-only"); it != tags.end())
if (auto value = tags.get("followers-only"))
{
roomModes.followerOnly = it.value().toInt();
roomModes.followerOnly = value->toInt();
}
twitchChannel->setRoomModes(roomModes);
}
@@ -536,7 +531,7 @@ void IrcMessageHandler::handleClearChatMessage(Communi::IrcMessage *message)
{
bool ok = false;
int remainingTime =
message->tags().value("ban-duration").toInt(&ok);
message->tags().getOrEmpty("ban-duration").toInt(&ok);
if (ok)
{
auto *tc = dynamic_cast<TwitchChannel *>(chan.get());
@@ -587,7 +582,7 @@ void IrcMessageHandler::handleClearMessageMessage(Communi::IrcMessage *message)
auto tags = message->tags();
QString targetID = tags.value("target-msg-id").toString();
QString targetID = tags.getOrEmpty("target-msg-id");
auto msg = chan->findMessageByID(targetID);
if (msg == nullptr)
@@ -603,7 +598,7 @@ void IrcMessageHandler::handleClearMessageMessage(Communi::IrcMessage *message)
MessageContext::Original);
}
if (getSettings()->hideModerated && !tags.contains("historical"))
if (getSettings()->hideModerated && !tags.has("historical"))
{
// XXX: This is expensive. We could use a layout request if the layout
// would store the previous message flags.
@@ -735,19 +730,19 @@ void IrcMessageHandler::parseUserNoticeMessageInto(Communi::IrcMessage *message,
auto tags = message->tags();
auto parameters = message->parameters();
QString msgType = tags.value("msg-id").toString();
QString msgType = tags.getOrEmpty("msg-id");
bool mirrored = msgType == "sharedchatnotice";
if (mirrored)
{
msgType = tags.value("source-msg-id").toString();
msgType = tags.getOrEmpty("source-msg-id");
}
else
{
auto rIt = tags.find("room-id");
auto sIt = tags.find("source-room-id");
if (rIt != tags.end() && sIt != tags.end())
auto rID = tags.get("room-id");
auto sID = tags.get("source-room-id");
if (rID && sID)
{
mirrored = rIt.value().toString() != sIt.value().toString();
mirrored = *rID != *sID;
}
}
@@ -765,7 +760,7 @@ void IrcMessageHandler::parseUserNoticeMessageInto(Communi::IrcMessage *message,
if (isIgnoredMessage({
.message = content,
.twitchUserID = tags.value("user-id").toString(),
.twitchUserID = tags.getOrEmpty("user-id"),
.isMod = channel->isMod(),
.isBroadcaster = channel->isBroadcaster(),
}))
@@ -787,21 +782,19 @@ void IrcMessageHandler::parseUserNoticeMessageInto(Communi::IrcMessage *message,
}
}
auto it = tags.find("system-msg");
if (it != tags.end())
if (auto optSystemMsg = tags.get("system-msg"))
{
// By default, we return value of system-msg tag
QString messageText = it.value().toString();
QString messageText = *std::move(optSystemMsg);
auto displayName = [&] {
if (msgType == u"raid")
{
return tags.value("msg-param-displayName").toString();
return tags.getOrEmpty("msg-param-displayName");
}
return tags.value("display-name").toString();
return tags.getOrEmpty("display-name");
}();
auto login = tags.value("login").toString();
auto login = tags.getOrEmpty("login");
if (displayName.isEmpty())
{
displayName = login;
@@ -811,9 +804,9 @@ void IrcMessageHandler::parseUserNoticeMessageInto(Communi::IrcMessage *message,
{
messageText =
QString("%1 just earned a new %2 Bits badge!")
.arg(tags.value("display-name").toString(),
.arg(tags.getOrEmpty("display-name"),
kFormatNumbers(
tags.value("msg-param-threshold").toInt()));
tags.getOrEmpty("msg-param-threshold").toInt()));
}
else if (msgType == "announcement")
{
@@ -830,24 +823,26 @@ void IrcMessageHandler::parseUserNoticeMessageInto(Communi::IrcMessage *message,
}
else if (msgType == "sub" || msgType == "resub")
{
if (auto tenure = tags.find("msg-param-multimonth-tenure");
tenure != tags.end() && tenure.value().toInt() == 0)
if (auto tenure = tags.get("msg-param-multimonth-tenure");
tenure && tenure->toInt() == 0)
{
int months =
tags.value("msg-param-multimonth-duration").toInt();
tags.getOrEmpty("msg-param-multimonth-duration").toInt();
if (months > 1)
{
int tier = tags.value("msg-param-sub-plan").toInt() / 1000;
int tier =
tags.getOrEmpty("msg-param-sub-plan").toInt() / 1000;
messageText =
QString(
"%1 subscribed at Tier %2 for %3 months in advance")
.arg(tags.value("display-name").toString(),
.arg(tags.getOrEmpty("display-name"),
QString::number(tier),
QString::number(months));
if (msgType == "resub")
{
int cumulative =
tags.value("msg-param-cumulative-months").toInt();
tags.getOrEmpty("msg-param-cumulative-months")
.toInt();
messageText +=
QString(", reaching %1 months cumulatively so far!")
.arg(QString::number(cumulative));
@@ -861,9 +856,10 @@ void IrcMessageHandler::parseUserNoticeMessageInto(Communi::IrcMessage *message,
}
else if (msgType == "socialsharingbadge")
{
int level = tags.value("msg-param-current-badge-level").toInt();
int level =
tags.getOrEmpty("msg-param-current-badge-level").toInt();
messageText = QString("%1 earned a Level %2 Social Media Badge!")
.arg(tags.value("display-name").toString(),
.arg(tags.getOrEmpty("display-name"),
QString::number(level));
}
else if (msgType == "modiversary")
@@ -877,16 +873,17 @@ void IrcMessageHandler::parseUserNoticeMessageInto(Communi::IrcMessage *message,
}
}
auto userID = tags.value("user-id").toString();
auto userColor = twitch::getUserColor(
{
.userLogin = login,
.userID = userID,
.userDataController = userDataController,
.channelChatters = channel,
.color = tags.value("color").value<QColor>(),
})
.value_or(MessageColor::System);
auto userID = tags.getOrEmpty("user-id");
auto userColor =
twitch::getUserColor(
{
.userLogin = login,
.userID = userID,
.userDataController = userDataController,
.channelChatters = channel,
.color = QColor::fromString(tags.getOrEmpty("color")),
})
.value_or(MessageColor::System);
auto msg = MessageBuilder::makeSystemMessageWithUser(
parseTagString(messageText), login, displayName, userColor,
@@ -929,7 +926,7 @@ void IrcMessageHandler::handleNoticeMessage(Communi::IrcNoticeMessage *message)
return;
}
QString tags = message->tags().value("msg-id").toString();
QString tags = message->tags().getOrEmpty("msg-id");
if (tags == "usage_delete")
{
channel->addSystemMessage(
@@ -1096,16 +1093,16 @@ void IrcMessageHandler::addMessage(Communi::IrcMessage *message,
args.isAction = isAction;
const auto &tags = message->tags();
auto tags = message->tags();
QString rewardId;
if (const auto it = tags.find("custom-reward-id"); it != tags.end())
if (auto optRewardId = tags.get("custom-reward-id"))
{
rewardId = it.value().toString();
rewardId = *std::move(optRewardId);
}
else if (const auto typeIt = tags.find("msg-id"); typeIt != tags.end())
else if (auto optMsgId = tags.get("msg-id"))
{
// slight hack to treat bits power-ups as channel point redemptions
const auto msgId = typeIt.value().toString();
const auto msgId = *std::move(optMsgId);
if (msgId == "animated-message" || msgId == "gigantified-emote-message")
{
rewardId = msgId;
@@ -1129,10 +1126,9 @@ void IrcMessageHandler::addMessage(Communi::IrcMessage *message,
ReplyContext replyCtx;
if (const auto it = tags.find("reply-thread-parent-msg-id");
it != tags.end())
if (auto optReplyID = tags.get("reply-thread-parent-msg-id"))
{
const QString replyID = it.value().toString();
const QString replyID = *std::move(optReplyID);
auto threadIt = chan->threads().find(replyID);
std::shared_ptr<MessageThread> rootThread;
if (threadIt != chan->threads().end() && !threadIt->second.expired())
@@ -1160,10 +1156,9 @@ void IrcMessageHandler::addMessage(Communi::IrcMessage *message,
}
}
if (const auto parentIt = tags.find("reply-parent-msg-id");
parentIt != tags.end())
if (auto optParentID = tags.get("reply-parent-msg-id"))
{
const QString parentID = parentIt.value().toString();
const QString parentID = *std::move(optParentID);
if (replyID == parentID)
{
if (rootThread)
+12 -12
View File
@@ -90,17 +90,17 @@ void appendTwitchEmoteOccurrences(const QString &emote,
namespace chatterino {
std::unordered_map<QString, QString> parseBadgeInfoTag(const QVariantMap &tags)
std::unordered_map<QString, QString> parseBadgeInfoTag(Communi::TagsRef tags)
{
std::unordered_map<QString, QString> infoMap;
auto infoIt = tags.constFind("badge-info");
if (infoIt == tags.end())
auto infoIt = tags.get("badge-info");
if (!infoIt)
{
return infoMap;
}
auto info = infoIt.value().toString().split(',', Qt::SkipEmptyParts);
auto info = infoIt->split(',', Qt::SkipEmptyParts);
for (const QString &badge : info)
{
@@ -110,18 +110,18 @@ std::unordered_map<QString, QString> parseBadgeInfoTag(const QVariantMap &tags)
return infoMap;
}
std::vector<TwitchBadge> parseBadgeTag(const QVariantMap &tags,
std::vector<TwitchBadge> parseBadgeTag(Communi::TagsRef tags,
const QString &tagName)
{
std::vector<TwitchBadge> b;
auto badgesIt = tags.constFind(tagName);
if (badgesIt == tags.end())
auto badgesIt = tags.get(tagName);
if (!badgesIt)
{
return b;
}
auto badges = badgesIt.value().toString().split(',', Qt::SkipEmptyParts);
auto badges = badgesIt->split(',', Qt::SkipEmptyParts);
for (const QString &badge : badges)
{
@@ -137,21 +137,21 @@ std::vector<TwitchBadge> parseBadgeTag(const QVariantMap &tags,
return b;
}
std::vector<TwitchEmoteOccurrence> parseTwitchEmotes(const QVariantMap &tags,
std::vector<TwitchEmoteOccurrence> parseTwitchEmotes(Communi::TagsRef tags,
const QString &content,
int messageOffset)
{
// Twitch emotes
std::vector<TwitchEmoteOccurrence> twitchEmotes;
auto emotesTag = tags.find("emotes");
auto emotesTag = tags.get("emotes");
if (emotesTag == tags.end())
if (!emotesTag)
{
return twitchEmotes;
}
QStringList emoteString = emotesTag.value().toString().split('/');
QStringList emoteString = emotesTag->split('/');
std::vector<int> correctPositions;
for (int i = 0; i < content.size(); ++i)
{
+4 -3
View File
@@ -7,6 +7,7 @@
#include "messages/Emote.hpp"
#include "providers/twitch/TwitchBadge.hpp"
#include <IrcTagsRef>
#include <QString>
#include <QVariantMap>
@@ -37,7 +38,7 @@ struct TwitchEmoteOccurrence {
///
/// @param tags The tags of the IRC message
/// @returns A map of badge-names to their values
std::unordered_map<QString, QString> parseBadgeInfoTag(const QVariantMap &tags);
std::unordered_map<QString, QString> parseBadgeInfoTag(Communi::TagsRef tags);
/// @brief Parses the badges from the specified tag of an IRC message
///
@@ -51,7 +52,7 @@ std::unordered_map<QString, QString> parseBadgeInfoTag(const QVariantMap &tags);
/// @param tags The tags of the IRC message
/// @param tagName The name of the tag to read badges from
/// @returns A list of badges (name and version)
std::vector<TwitchBadge> parseBadgeTag(const QVariantMap &tags,
std::vector<TwitchBadge> parseBadgeTag(Communi::TagsRef tags,
const QString &tagName = "badges");
/// @brief Parses Twitch emotes in an IRC message
@@ -66,7 +67,7 @@ std::vector<TwitchBadge> parseBadgeTag(const QVariantMap &tags,
/// original message (`@a foo` (original message) -> `foo`
/// (content)).
/// @returns A list of emotes and their positions
std::vector<TwitchEmoteOccurrence> parseTwitchEmotes(const QVariantMap &tags,
std::vector<TwitchEmoteOccurrence> parseTwitchEmotes(Communi::TagsRef tags,
const QString &content,
int messageOffset);
+8 -10
View File
@@ -13,33 +13,31 @@ using namespace chatterino;
QDateTime calculateMessageTimeBase(const Communi::IrcMessage *message)
{
// Check if message is from recent-messages API
if (message->tags().contains("historical"))
auto tags = message->tags();
if (tags.has("historical"))
{
bool customReceived = false;
auto ts =
message->tags().value("rm-received-ts").toLongLong(&customReceived);
auto ts = tags.getOrEmpty("rm-received-ts").toLongLong(&customReceived);
if (!customReceived)
{
ts = message->tags().value("tmi-sent-ts").toLongLong();
ts = tags.getOrEmpty("tmi-sent-ts").toLongLong();
}
return QDateTime::fromMSecsSinceEpoch(ts);
}
// If present, handle tmi-sent-ts tag and use it as timestamp
if (message->tags().contains("tmi-sent-ts"))
if (auto tmiSentTs = tags.get("tmi-sent-ts"))
{
auto ts = message->tags().value("tmi-sent-ts").toLongLong();
auto ts = tmiSentTs->toLongLong();
return QDateTime::fromMSecsSinceEpoch(ts);
}
// Some IRC Servers might have server-time tag containing UTC date in ISO format, use it as timestamp
// See: https://ircv3.net/irc/#server-time
if (message->tags().contains("time"))
if (auto optTime = message->tags().get("time"))
{
QString timedate = message->tags().value("time").toString();
auto date = QDateTime::fromString(timedate, Qt::ISODate);
auto date = QDateTime::fromString(*optTime, Qt::ISODate);
date.setTimeZone(QTimeZone::utc());
return date.toLocalTime();
}