diff --git a/lib/libcommuni b/lib/libcommuni index ac0e713e5..9dc0de7c9 160000 --- a/lib/libcommuni +++ b/lib/libcommuni @@ -1 +1 @@ -Subproject commit ac0e713e5a904b6f3231c70e076f6fd67a78455e +Subproject commit 9dc0de7c91d362abc431f680dd94e81eadf41622 diff --git a/src/messages/MessageBuilder.cpp b/src/messages/MessageBuilder.cpp index 0fa8c00c2..121f365fa 100644 --- a/src/messages/MessageBuilder.cpp +++ b/src/messages/MessageBuilder.cpp @@ -523,15 +523,15 @@ EmotePtr parseEmote(TwitchChannel *twitchChannel, const EmoteName &name) return {}; } -std::pair parseMessageType(const QVariantMap &tags) +std::pair 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(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(), - }) + 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 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 MessageBuilder::makeIrcMessage( auto *twitchChannel = dynamic_cast(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 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 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 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 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 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( - 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 &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( "@" + 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; diff --git a/src/messages/MessageBuilder.hpp b/src/messages/MessageBuilder.hpp index 84e112c90..d1a276d39 100644 --- a/src/messages/MessageBuilder.hpp +++ b/src/messages/MessageBuilder.hpp @@ -10,6 +10,7 @@ #include "messages/MessageFlag.hpp" #include +#include #include #include #include @@ -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 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 &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 &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); diff --git a/src/providers/recentmessages/Impl.cpp b/src/providers/recentmessages/Impl.cpp index 8b50b697f..6e8966df5 100644 --- a/src/providers/recentmessages/Impl.cpp +++ b/src/providers/recentmessages/Impl.cpp @@ -56,11 +56,10 @@ std::vector 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 diff --git a/src/providers/twitch/IrcMessageHandler.cpp b/src/providers/twitch/IrcMessageHandler.cpp index 9b9f85359..6e31d5d34 100644 --- a/src/providers/twitch/IrcMessageHandler.cpp +++ b/src/providers/twitch/IrcMessageHandler.cpp @@ -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 &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(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(), - }) - .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 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) diff --git a/src/providers/twitch/TwitchIrc.cpp b/src/providers/twitch/TwitchIrc.cpp index e0ce9ec1c..f5807fba0 100644 --- a/src/providers/twitch/TwitchIrc.cpp +++ b/src/providers/twitch/TwitchIrc.cpp @@ -90,17 +90,17 @@ void appendTwitchEmoteOccurrences(const QString &emote, namespace chatterino { -std::unordered_map parseBadgeInfoTag(const QVariantMap &tags) +std::unordered_map parseBadgeInfoTag(Communi::TagsRef tags) { std::unordered_map 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 parseBadgeInfoTag(const QVariantMap &tags) return infoMap; } -std::vector parseBadgeTag(const QVariantMap &tags, +std::vector parseBadgeTag(Communi::TagsRef tags, const QString &tagName) { std::vector 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 parseBadgeTag(const QVariantMap &tags, return b; } -std::vector parseTwitchEmotes(const QVariantMap &tags, +std::vector parseTwitchEmotes(Communi::TagsRef tags, const QString &content, int messageOffset) { // Twitch emotes std::vector 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 correctPositions; for (int i = 0; i < content.size(); ++i) { diff --git a/src/providers/twitch/TwitchIrc.hpp b/src/providers/twitch/TwitchIrc.hpp index 5f5ea2cfa..9669b6c9c 100644 --- a/src/providers/twitch/TwitchIrc.hpp +++ b/src/providers/twitch/TwitchIrc.hpp @@ -7,6 +7,7 @@ #include "messages/Emote.hpp" #include "providers/twitch/TwitchBadge.hpp" +#include #include #include @@ -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 parseBadgeInfoTag(const QVariantMap &tags); +std::unordered_map parseBadgeInfoTag(Communi::TagsRef tags); /// @brief Parses the badges from the specified tag of an IRC message /// @@ -51,7 +52,7 @@ std::unordered_map 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 parseBadgeTag(const QVariantMap &tags, +std::vector parseBadgeTag(Communi::TagsRef tags, const QString &tagName = "badges"); /// @brief Parses Twitch emotes in an IRC message @@ -66,7 +67,7 @@ std::vector parseBadgeTag(const QVariantMap &tags, /// original message (`@a foo` (original message) -> `foo` /// (content)). /// @returns A list of emotes and their positions -std::vector parseTwitchEmotes(const QVariantMap &tags, +std::vector parseTwitchEmotes(Communi::TagsRef tags, const QString &content, int messageOffset); diff --git a/src/util/IrcHelpers.cpp b/src/util/IrcHelpers.cpp index e27ee360a..02e8f65ee 100644 --- a/src/util/IrcHelpers.cpp +++ b/src/util/IrcHelpers.cpp @@ -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(); }