Harden emote parsing (#3885)

This commit is contained in:
pajlada
2022-11-05 11:04:35 +01:00
committed by GitHub
parent f00f766eeb
commit aac9ea53d0
14 changed files with 1163 additions and 104 deletions
+110 -78
View File
@@ -107,6 +107,77 @@ namespace {
return usernameText;
}
void appendTwitchEmoteOccurrences(const QString &emote,
std::vector<TwitchEmoteOccurrence> &vec,
const std::vector<int> &correctPositions,
const QString &originalMessage,
int messageOffset)
{
auto *app = getIApp();
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
TwitchMessageBuilder::TwitchMessageBuilder(
@@ -304,25 +375,8 @@ MessagePtr TwitchMessageBuilder::build()
}
// Twitch emotes
std::vector<TwitchEmoteOccurence> twitchEmotes;
iterator = this->tags.find("emotes");
if (iterator != this->tags.end())
{
QStringList emoteString = iterator.value().toString().split('/');
std::vector<int> correctPositions;
for (int i = 0; i < this->originalMessage_.size(); ++i)
{
if (!this->originalMessage_.at(i).isLowSurrogate())
{
correctPositions.push_back(i);
}
}
for (QString emote : emoteString)
{
this->appendTwitchEmote(emote, twitchEmotes, correctPositions);
}
}
auto twitchEmotes = TwitchMessageBuilder::parseTwitchEmotes(
this->tags, this->originalMessage_, this->messageOffset_);
// This runs through all ignored phrases and runs its replacements on this->originalMessage_
this->runIgnoreReplaces(twitchEmotes);
@@ -379,8 +433,8 @@ MessagePtr TwitchMessageBuilder::build()
bool doesWordContainATwitchEmote(
int cursor, const QString &word,
const std::vector<TwitchEmoteOccurence> &twitchEmotes,
std::vector<TwitchEmoteOccurence>::const_iterator &currentTwitchEmoteIt)
const std::vector<TwitchEmoteOccurrence> &twitchEmotes,
std::vector<TwitchEmoteOccurrence>::const_iterator &currentTwitchEmoteIt)
{
if (currentTwitchEmoteIt == twitchEmotes.end())
{
@@ -404,7 +458,7 @@ bool doesWordContainATwitchEmote(
void TwitchMessageBuilder::addWords(
const QStringList &words,
const std::vector<TwitchEmoteOccurence> &twitchEmotes)
const std::vector<TwitchEmoteOccurrence> &twitchEmotes)
{
// cursor currently indicates what character index we're currently operating in the full list of words
int cursor = 0;
@@ -762,7 +816,7 @@ void TwitchMessageBuilder::appendUsername()
}
void TwitchMessageBuilder::runIgnoreReplaces(
std::vector<TwitchEmoteOccurence> &twitchEmotes)
std::vector<TwitchEmoteOccurrence> &twitchEmotes)
{
auto phrases = getCSettings().ignoredMessages.readOnly();
auto removeEmotesInRange = [](int pos, int len,
@@ -780,7 +834,7 @@ void TwitchMessageBuilder::runIgnoreReplaces(
<< "remem nullptr" << (*copy).name.string;
}
}
std::vector<TwitchEmoteOccurence> v(it, twitchEmotes.end());
std::vector<TwitchEmoteOccurrence> v(it, twitchEmotes.end());
twitchEmotes.erase(it, twitchEmotes.end());
return v;
};
@@ -818,7 +872,7 @@ void TwitchMessageBuilder::runIgnoreReplaces(
qCDebug(chatterinoTwitch)
<< "emote null" << emote.first.string;
}
twitchEmotes.push_back(TwitchEmoteOccurence{
twitchEmotes.push_back(TwitchEmoteOccurrence{
startIndex + pos,
startIndex + pos + emote.first.string.length(),
emote.second,
@@ -980,59 +1034,6 @@ void TwitchMessageBuilder::runIgnoreReplaces(
}
}
void TwitchMessageBuilder::appendTwitchEmote(
const QString &emote, std::vector<TwitchEmoteOccurence> &vec,
std::vector<int> &correctPositions)
{
auto app = getApp();
if (!emote.contains(':'))
{
return;
}
auto parameters = emote.split(':');
if (parameters.length() < 2)
{
return;
}
auto id = EmoteId{parameters.at(0)};
auto occurences = parameters.at(1).split(',');
for (QString occurence : occurences)
{
auto coords = occurence.split('-');
if (coords.length() < 2)
{
return;
}
auto start =
correctPositions[coords.at(0).toUInt() - this->messageOffset_];
auto end =
correctPositions[coords.at(1).toUInt() - this->messageOffset_];
if (start >= end || start < 0 || end > this->originalMessage_.length())
{
return;
}
auto name =
EmoteName{this->originalMessage_.mid(start, end - start + 1)};
TwitchEmoteOccurence emoteOccurence{
start, end, app->emotes->twitch.getOrCreateEmote(id, name), name};
if (emoteOccurence.ptr == nullptr)
{
qCDebug(chatterinoTwitch)
<< "nullptr" << emoteOccurence.name.string;
}
vec.push_back(std::move(emoteOccurence));
}
}
Outcome TwitchMessageBuilder::tryAppendEmote(const EmoteName &name)
{
auto *app = getApp();
@@ -1137,6 +1138,37 @@ std::unordered_map<QString, QString> TwitchMessageBuilder::parseBadgeInfoTag(
return infoMap;
}
std::vector<TwitchEmoteOccurrence> TwitchMessageBuilder::parseTwitchEmotes(
const QVariantMap &tags, const QString &originalMessage, 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 < originalMessage.size(); ++i)
{
if (!originalMessage.at(i).isLowSurrogate())
{
correctPositions.push_back(i);
}
}
for (const QString &emote : emoteString)
{
appendTwitchEmoteOccurrences(emote, twitchEmotes, correctPositions,
originalMessage, messageOffset);
}
return twitchEmotes;
}
void TwitchMessageBuilder::appendTwitchBadges()
{
if (this->twitchChannel == nullptr)