refactor(message-builder): move static helper methods to functions (#5652)

This commit is contained in:
nerix
2024-10-18 13:03:36 +02:00
committed by GitHub
parent 6d139af553
commit 800f6df2cf
12 changed files with 1090 additions and 928 deletions
+166
View File
@@ -0,0 +1,166 @@
#include "providers/twitch/TwitchIrc.hpp"
#include "Application.hpp"
#include "common/Aliases.hpp"
#include "common/QLogging.hpp"
#include "singletons/Emotes.hpp"
#include "util/IrcHelpers.hpp"
namespace {
using namespace chatterino;
void appendTwitchEmoteOccurrences(const QString &emote,
std::vector<TwitchEmoteOccurrence> &vec,
const std::vector<int> &correctPositions,
const QString &originalMessage,
int messageOffset)
{
auto *app = getApp();
if (!emote.contains(':'))
{
return;
}
auto parameters = emote.split(':');
if (parameters.length() < 2)
{
return;
}
auto id = EmoteId{parameters.at(0)};
auto occurrences = parameters.at(1).split(',');
for (const QString &occurrence : occurrences)
{
auto coords = occurrence.split('-');
if (coords.length() < 2)
{
return;
}
auto from = coords.at(0).toUInt() - messageOffset;
auto to = coords.at(1).toUInt() - messageOffset;
auto maxPositions = correctPositions.size();
if (from > to || to >= maxPositions)
{
// Emote coords are out of range
qCDebug(chatterinoTwitch)
<< "Emote coords" << from << "-" << to << "are out of range ("
<< maxPositions << ")";
return;
}
auto start = correctPositions[from];
auto end = correctPositions[to];
if (start > end || start < 0 || end > originalMessage.length())
{
// Emote coords are out of range from the modified character positions
qCDebug(chatterinoTwitch) << "Emote coords" << from << "-" << to
<< "are out of range after offsets ("
<< originalMessage.length() << ")";
return;
}
auto name = EmoteName{originalMessage.mid(start, end - start + 1)};
TwitchEmoteOccurrence emoteOccurrence{
start,
end,
app->getEmotes()->getTwitchEmotes()->getOrCreateEmote(id, name),
name,
};
if (emoteOccurrence.ptr == nullptr)
{
qCDebug(chatterinoTwitch)
<< "nullptr" << emoteOccurrence.name.string;
}
vec.push_back(std::move(emoteOccurrence));
}
}
} // namespace
namespace chatterino {
std::unordered_map<QString, QString> parseBadgeInfoTag(const QVariantMap &tags)
{
std::unordered_map<QString, QString> infoMap;
auto infoIt = tags.constFind("badge-info");
if (infoIt == tags.end())
{
return infoMap;
}
auto info = infoIt.value().toString().split(',', Qt::SkipEmptyParts);
for (const QString &badge : info)
{
infoMap.emplace(slashKeyValue(badge));
}
return infoMap;
}
std::vector<Badge> 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 = slashKeyValue(badge);
b.emplace_back(Badge{pair.first, pair.second});
}
return b;
}
std::vector<TwitchEmoteOccurrence> parseTwitchEmotes(const QVariantMap &tags,
const QString &content,
int messageOffset)
{
// Twitch emotes
std::vector<TwitchEmoteOccurrence> twitchEmotes;
auto emotesTag = tags.find("emotes");
if (emotesTag == tags.end())
{
return twitchEmotes;
}
QStringList emoteString = emotesTag.value().toString().split('/');
std::vector<int> correctPositions;
for (int i = 0; i < content.size(); ++i)
{
if (!content.at(i).isLowSurrogate())
{
correctPositions.push_back(i);
}
}
for (const QString &emote : emoteString)
{
appendTwitchEmoteOccurrences(emote, twitchEmotes, correctPositions,
content, messageOffset);
}
return twitchEmotes;
}
} // namespace chatterino
+67
View File
@@ -0,0 +1,67 @@
#pragma once
#include "messages/Emote.hpp"
#include "providers/twitch/TwitchBadge.hpp"
#include <QString>
#include <QVariantMap>
#include <unordered_map>
namespace chatterino {
struct TwitchEmoteOccurrence {
int start;
int end;
EmotePtr ptr;
EmoteName name;
bool operator==(const TwitchEmoteOccurrence &other) const
{
return std::tie(this->start, this->end, this->ptr, this->name) ==
std::tie(other.start, other.end, other.ptr, other.name);
}
};
/// @brief Parses the `badge-info` tag of an IRC message
///
/// The `badge-info` tag maps badge-names to a value. Subscriber badges, for
/// example, are mapped to the number of months the chatter is subscribed for.
///
/// **Example**:
/// `badge-info=subscriber/22` would be parsed as `{ subscriber => 22 }`
///
/// @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);
/// @brief Parses the `badges` tag of an IRC message
///
/// The `badges` tag contains a comma separated list of key-value elements which
/// make up the name and version of each badge.
///
/// **Example**:
/// `badges=broadcaster/1,subscriber/18` would be parsed as
/// `[(broadcaster, 1), (subscriber, 18)]`
///
/// @param tags The tags of the IRC message
/// @returns A list of badges (name and version)
std::vector<Badge> parseBadgeTag(const QVariantMap &tags);
/// @brief Parses Twitch emotes in an IRC message
///
/// @param tags The tags of the IRC message
/// @param content The message text. This might be shortened due to skipping
/// content at the start. `messageOffset` describes this offset.
/// @param messageOffset The offset of `content` compared to the original
/// message text. Used for calculating indices into the
/// message. An offset of 3, for example, indicates that
/// `content` excludes the first three characters of the
/// original message (`@a foo` (original message) -> `foo`
/// (content)).
/// @returns A list of emotes and their positions
std::vector<TwitchEmoteOccurrence> parseTwitchEmotes(const QVariantMap &tags,
const QString &content,
int messageOffset);
} // namespace chatterino