Corrected the way we parse comma-separated "list tags" in PRIVMSGs (#3771)

tl;dr: we now split by slash only its first occurrence instead of every occurrence.
This commit is contained in:
Kasia
2022-05-28 11:55:48 +02:00
committed by GitHub
parent 6ef3ecc952
commit 7d0023cf73
10 changed files with 228 additions and 102 deletions
+2 -1
View File
@@ -2,6 +2,7 @@
#include "common/FlagsEnum.hpp"
#include "providers/twitch/TwitchBadge.hpp"
#include "util/QStringHash.hpp"
#include "widgets/helper/ScrollbarHighlight.hpp"
#include <QTime>
@@ -65,7 +66,7 @@ struct Message : boost::noncopyable {
QColor usernameColor;
QDateTime serverReceivedTime;
std::vector<Badge> badges;
std::map<QString, QString> badgeInfos;
std::unordered_map<QString, QString> badgeInfos;
std::shared_ptr<QColor> highlightColor;
uint32_t count = 1;
std::vector<std::unique_ptr<MessageElement>> elements;
+41 -29
View File
@@ -4,7 +4,6 @@
#include "common/QLogging.hpp"
#include "controllers/ignores/IgnoreController.hpp"
#include "controllers/ignores/IgnorePhrase.hpp"
#include "messages/Message.hpp"
#include "messages/MessageElement.hpp"
#include "singletons/Settings.hpp"
#include "singletons/WindowManager.hpp"
@@ -36,33 +35,6 @@ namespace {
}
}
QStringList parseTagList(const QVariantMap &tags, const QString &key)
{
auto iterator = tags.find(key);
if (iterator == tags.end())
return QStringList{};
return iterator.value().toString().split(',', Qt::SkipEmptyParts);
}
std::vector<Badge> parseBadges(const QVariantMap &tags)
{
std::vector<Badge> badges;
for (QString badge : parseTagList(tags, "badges"))
{
QStringList parts = badge.split('/');
if (parts.size() != 2)
{
continue;
}
badges.emplace_back(parts[0], parts[1]);
}
return badges;
}
} // namespace
SharedMessageBuilder::SharedMessageBuilder(
@@ -103,6 +75,46 @@ void SharedMessageBuilder::parse()
this->message().flags.set(MessageFlag::Collapsed);
}
// "foo/bar/baz,tri/hard" can be a valid badge-info tag
// In that case, valid map content should be 'split by slash' only once:
// {"foo": "bar/baz", "tri": "hard"}
std::pair<QString, QString> SharedMessageBuilder::slashKeyValue(
const QString &kvStr)
{
return {
// part before first slash (index 0 of section)
kvStr.section('/', 0, 0),
// part after first slash (index 1 of section)
kvStr.section('/', 1, -1),
};
}
std::vector<Badge> SharedMessageBuilder::parseBadgeTag(const QVariantMap &tags)
{
std::vector<Badge> b;
auto badgesIt = tags.constFind("badges");
if (badgesIt == tags.end())
{
return b;
}
auto badges = badgesIt.value().toString().split(',', Qt::SkipEmptyParts);
for (const QString &badge : badges)
{
if (!badge.contains('/'))
{
continue;
}
auto pair = SharedMessageBuilder::slashKeyValue(badge);
b.emplace_back(Badge{pair.first, pair.second});
}
return b;
}
bool SharedMessageBuilder::isIgnored() const
{
return isIgnoredMessage({
@@ -332,7 +344,7 @@ void SharedMessageBuilder::parseHighlights()
}
// Highlight because of badge
auto badges = parseBadges(this->tags);
auto badges = this->parseBadgeTag(this->tags);
auto badgeHighlights = getCSettings().highlightedBadges.readOnly();
bool badgeHighlightSet = false;
for (const HighlightBadge &highlight : *badgeHighlights)
+6
View File
@@ -3,6 +3,7 @@
#include "common/Aliases.hpp"
#include "common/Outcome.hpp"
#include "messages/MessageColor.hpp"
#include "providers/twitch/TwitchBadge.hpp"
#include <IrcMessage>
#include <QColor>
@@ -32,6 +33,11 @@ public:
virtual void triggerHighlights();
virtual MessagePtr build() = 0;
static std::pair<QString, QString> slashKeyValue(const QString &kvStr);
// Parses "badges" tag which contains a comma separated list of key-value elements
static std::vector<Badge> parseBadgeTag(const QVariantMap &tags);
protected:
virtual void parse();