mirror of
https://github.com/Chatterino/chatterino2.git
synced 2024-11-13 19:49:51 +01:00
dev: Add RecentMessages benchmark (#5071)
Co-authored-by: Rasmus Karlsson <rasmus.karlsson@pajlada.com>
This commit is contained in:
parent
78a7ebb9f9
commit
f42ae07408
|
@ -65,5 +65,11 @@ CheckOptions:
|
||||||
- key: readability-identifier-naming.LocalPointerIgnoredRegexp
|
- key: readability-identifier-naming.LocalPointerIgnoredRegexp
|
||||||
value: ^L$
|
value: ^L$
|
||||||
|
|
||||||
|
# Benchmarks
|
||||||
|
- key: readability-identifier-naming.FunctionIgnoredRegexp
|
||||||
|
value: ^BM_[^_]+$
|
||||||
|
- key: readability-identifier-naming.ClassIgnoredRegexp
|
||||||
|
value: ^BM_[^_]+$
|
||||||
|
|
||||||
- key: misc-const-correctness.AnalyzeValues
|
- key: misc-const-correctness.AnalyzeValues
|
||||||
value: false
|
value: false
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
# JSON resources should not be prettified...
|
# JSON resources should not be prettified...
|
||||||
resources/*.json
|
resources/*.json
|
||||||
|
benchmarks/resources/*.json
|
||||||
|
tests/resources/*.json
|
||||||
# ...themes should be prettified for readability.
|
# ...themes should be prettified for readability.
|
||||||
!resources/themes/*.json
|
!resources/themes/*.json
|
||||||
|
|
||||||
|
@ -7,6 +9,7 @@ resources/*.json
|
||||||
lib/*/
|
lib/*/
|
||||||
conan-pkgs/*/
|
conan-pkgs/*/
|
||||||
cmake/sanitizers-cmake/
|
cmake/sanitizers-cmake/
|
||||||
|
tools/crash-handler
|
||||||
|
|
||||||
# Build folders
|
# Build folders
|
||||||
*build-*/
|
*build-*/
|
||||||
|
|
|
@ -112,6 +112,7 @@
|
||||||
- Dev: Autogenerate docs/plugin-meta.lua. (#5055)
|
- Dev: Autogenerate docs/plugin-meta.lua. (#5055)
|
||||||
- Dev: Removed duplicate scale in settings dialog. (#5069)
|
- Dev: Removed duplicate scale in settings dialog. (#5069)
|
||||||
- Dev: Fix `NotebookTab` emitting updates for every message. (#5068)
|
- Dev: Fix `NotebookTab` emitting updates for every message. (#5068)
|
||||||
|
- Dev: Added benchmark for parsing and building recent messages. (#5071)
|
||||||
|
|
||||||
## 2.4.6
|
## 2.4.6
|
||||||
|
|
||||||
|
|
|
@ -1,13 +1,16 @@
|
||||||
project(chatterino-benchmark)
|
project(chatterino-benchmark)
|
||||||
|
|
||||||
set(benchmark_SOURCES
|
set(benchmark_SOURCES
|
||||||
${CMAKE_CURRENT_LIST_DIR}/src/main.cpp
|
src/main.cpp
|
||||||
${CMAKE_CURRENT_LIST_DIR}/src/Emojis.cpp
|
resources/bench.qrc
|
||||||
${CMAKE_CURRENT_LIST_DIR}/src/Highlights.cpp
|
|
||||||
${CMAKE_CURRENT_LIST_DIR}/src/FormatTime.cpp
|
src/Emojis.cpp
|
||||||
${CMAKE_CURRENT_LIST_DIR}/src/Helpers.cpp
|
src/Highlights.cpp
|
||||||
${CMAKE_CURRENT_LIST_DIR}/src/LimitedQueue.cpp
|
src/FormatTime.cpp
|
||||||
${CMAKE_CURRENT_LIST_DIR}/src/LinkParser.cpp
|
src/Helpers.cpp
|
||||||
|
src/LimitedQueue.cpp
|
||||||
|
src/LinkParser.cpp
|
||||||
|
src/RecentMessages.cpp
|
||||||
# Add your new file above this line!
|
# Add your new file above this line!
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -27,4 +30,5 @@ set_target_properties(${PROJECT_NAME}
|
||||||
RUNTIME_OUTPUT_DIRECTORY_RELEASE "${CMAKE_BINARY_DIR}/bin"
|
RUNTIME_OUTPUT_DIRECTORY_RELEASE "${CMAKE_BINARY_DIR}/bin"
|
||||||
RUNTIME_OUTPUT_DIRECTORY_DEBUG "${CMAKE_BINARY_DIR}/bin"
|
RUNTIME_OUTPUT_DIRECTORY_DEBUG "${CMAKE_BINARY_DIR}/bin"
|
||||||
RUNTIME_OUTPUT_DIRECTORY_RELWITHDEBINFO "${CMAKE_BINARY_DIR}/bin"
|
RUNTIME_OUTPUT_DIRECTORY_RELWITHDEBINFO "${CMAKE_BINARY_DIR}/bin"
|
||||||
|
AUTORCC ON
|
||||||
)
|
)
|
||||||
|
|
6
benchmarks/resources/bench.qrc
Normal file
6
benchmarks/resources/bench.qrc
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
<RCC>
|
||||||
|
<qresource prefix="/bench">
|
||||||
|
<file>recentmessages-nymn.json</file>
|
||||||
|
<file>seventvemotes-nymn.json</file>
|
||||||
|
</qresource>
|
||||||
|
</RCC>
|
1
benchmarks/resources/recentmessages-nymn.json
Normal file
1
benchmarks/resources/recentmessages-nymn.json
Normal file
File diff suppressed because one or more lines are too long
1
benchmarks/resources/seventvemotes-nymn.json
Normal file
1
benchmarks/resources/seventvemotes-nymn.json
Normal file
File diff suppressed because one or more lines are too long
|
@ -145,16 +145,13 @@ static void BM_EmojiParsing(benchmark::State &state)
|
||||||
|
|
||||||
BENCHMARK(BM_EmojiParsing);
|
BENCHMARK(BM_EmojiParsing);
|
||||||
|
|
||||||
template <class... Args>
|
static void BM_EmojiParsing2(benchmark::State &state, const QString &input,
|
||||||
static void BM_EmojiParsing2(benchmark::State &state, Args &&...args)
|
int expectedNumEmojis)
|
||||||
{
|
{
|
||||||
Emojis emojis;
|
Emojis emojis;
|
||||||
|
|
||||||
emojis.load();
|
emojis.load();
|
||||||
|
|
||||||
auto argsTuple = std::make_tuple(std::move(args)...);
|
|
||||||
auto input = std::get<0>(argsTuple);
|
|
||||||
auto expectedNumEmojis = std::get<1>(argsTuple);
|
|
||||||
for (auto _ : state)
|
for (auto _ : state)
|
||||||
{
|
{
|
||||||
auto output = emojis.parse(input);
|
auto output = emojis.parse(input);
|
||||||
|
|
|
@ -4,35 +4,41 @@
|
||||||
|
|
||||||
using namespace chatterino;
|
using namespace chatterino;
|
||||||
|
|
||||||
template <class... Args>
|
void BM_TimeFormattingQString(benchmark::State &state, const QString &v)
|
||||||
void BM_TimeFormatting(benchmark::State &state, Args &&...args)
|
|
||||||
{
|
{
|
||||||
auto args_tuple = std::make_tuple(std::move(args)...);
|
|
||||||
for (auto _ : state)
|
for (auto _ : state)
|
||||||
{
|
{
|
||||||
formatTime(std::get<0>(args_tuple));
|
formatTime(v);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
BENCHMARK_CAPTURE(BM_TimeFormatting, 0, 0);
|
void BM_TimeFormattingInt(benchmark::State &state, int v)
|
||||||
BENCHMARK_CAPTURE(BM_TimeFormatting, qs0, "0");
|
{
|
||||||
BENCHMARK_CAPTURE(BM_TimeFormatting, 1337, 1337);
|
for (auto _ : state)
|
||||||
BENCHMARK_CAPTURE(BM_TimeFormatting, qs1337, "1337");
|
{
|
||||||
BENCHMARK_CAPTURE(BM_TimeFormatting, 623452, 623452);
|
formatTime(v);
|
||||||
BENCHMARK_CAPTURE(BM_TimeFormatting, qs623452, "623452");
|
}
|
||||||
BENCHMARK_CAPTURE(BM_TimeFormatting, 8345, 8345);
|
}
|
||||||
BENCHMARK_CAPTURE(BM_TimeFormatting, qs8345, "8345");
|
|
||||||
BENCHMARK_CAPTURE(BM_TimeFormatting, 314034, 314034);
|
BENCHMARK_CAPTURE(BM_TimeFormattingInt, 0, 0);
|
||||||
BENCHMARK_CAPTURE(BM_TimeFormatting, qs314034, "314034");
|
BENCHMARK_CAPTURE(BM_TimeFormattingInt, 1045345, 1045345);
|
||||||
BENCHMARK_CAPTURE(BM_TimeFormatting, 27, 27);
|
BENCHMARK_CAPTURE(BM_TimeFormattingInt, 1337, 1337);
|
||||||
BENCHMARK_CAPTURE(BM_TimeFormatting, qs27, "27");
|
BENCHMARK_CAPTURE(BM_TimeFormattingInt, 27, 27);
|
||||||
BENCHMARK_CAPTURE(BM_TimeFormatting, 34589, 34589);
|
BENCHMARK_CAPTURE(BM_TimeFormattingInt, 314034, 314034);
|
||||||
BENCHMARK_CAPTURE(BM_TimeFormatting, qs34589, "34589");
|
BENCHMARK_CAPTURE(BM_TimeFormattingInt, 34589, 34589);
|
||||||
BENCHMARK_CAPTURE(BM_TimeFormatting, 3659, 3659);
|
BENCHMARK_CAPTURE(BM_TimeFormattingInt, 3659, 3659);
|
||||||
BENCHMARK_CAPTURE(BM_TimeFormatting, qs3659, "3659");
|
BENCHMARK_CAPTURE(BM_TimeFormattingInt, 623452, 623452);
|
||||||
BENCHMARK_CAPTURE(BM_TimeFormatting, 1045345, 1045345);
|
BENCHMARK_CAPTURE(BM_TimeFormattingInt, 8345, 8345);
|
||||||
BENCHMARK_CAPTURE(BM_TimeFormatting, qs1045345, "1045345");
|
BENCHMARK_CAPTURE(BM_TimeFormattingInt, 86432, 86432);
|
||||||
BENCHMARK_CAPTURE(BM_TimeFormatting, 86432, 86432);
|
BENCHMARK_CAPTURE(BM_TimeFormattingQString, qs0, "0");
|
||||||
BENCHMARK_CAPTURE(BM_TimeFormatting, qs86432, "86432");
|
BENCHMARK_CAPTURE(BM_TimeFormattingQString, qs1045345, "1045345");
|
||||||
BENCHMARK_CAPTURE(BM_TimeFormatting, qsempty, "");
|
BENCHMARK_CAPTURE(BM_TimeFormattingQString, qs1337, "1337");
|
||||||
BENCHMARK_CAPTURE(BM_TimeFormatting, qsinvalid, "asd");
|
BENCHMARK_CAPTURE(BM_TimeFormattingQString, qs27, "27");
|
||||||
|
BENCHMARK_CAPTURE(BM_TimeFormattingQString, qs314034, "314034");
|
||||||
|
BENCHMARK_CAPTURE(BM_TimeFormattingQString, qs34589, "34589");
|
||||||
|
BENCHMARK_CAPTURE(BM_TimeFormattingQString, qs3659, "3659");
|
||||||
|
BENCHMARK_CAPTURE(BM_TimeFormattingQString, qs623452, "623452");
|
||||||
|
BENCHMARK_CAPTURE(BM_TimeFormattingQString, qs8345, "8345");
|
||||||
|
BENCHMARK_CAPTURE(BM_TimeFormattingQString, qs86432, "86432");
|
||||||
|
BENCHMARK_CAPTURE(BM_TimeFormattingQString, qsempty, "");
|
||||||
|
BENCHMARK_CAPTURE(BM_TimeFormattingQString, qsinvalid, "asd");
|
||||||
|
|
223
benchmarks/src/RecentMessages.cpp
Normal file
223
benchmarks/src/RecentMessages.cpp
Normal file
|
@ -0,0 +1,223 @@
|
||||||
|
#include "common/Literals.hpp"
|
||||||
|
#include "controllers/accounts/AccountController.hpp"
|
||||||
|
#include "controllers/highlights/HighlightController.hpp"
|
||||||
|
#include "messages/Emote.hpp"
|
||||||
|
#include "mocks/EmptyApplication.hpp"
|
||||||
|
#include "mocks/TwitchIrcServer.hpp"
|
||||||
|
#include "mocks/UserData.hpp"
|
||||||
|
#include "providers/bttv/BttvEmotes.hpp"
|
||||||
|
#include "providers/chatterino/ChatterinoBadges.hpp"
|
||||||
|
#include "providers/ffz/FfzBadges.hpp"
|
||||||
|
#include "providers/ffz/FfzEmotes.hpp"
|
||||||
|
#include "providers/recentmessages/Impl.hpp"
|
||||||
|
#include "providers/seventv/SeventvBadges.hpp"
|
||||||
|
#include "providers/seventv/SeventvEmotes.hpp"
|
||||||
|
#include "providers/twitch/TwitchChannel.hpp"
|
||||||
|
#include "singletons/Emotes.hpp"
|
||||||
|
#include "singletons/Resources.hpp"
|
||||||
|
|
||||||
|
#include <benchmark/benchmark.h>
|
||||||
|
#include <QFile>
|
||||||
|
#include <QJsonArray>
|
||||||
|
#include <QJsonDocument>
|
||||||
|
#include <QString>
|
||||||
|
|
||||||
|
#include <optional>
|
||||||
|
|
||||||
|
using namespace chatterino;
|
||||||
|
using namespace literals;
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
class MockApplication : mock::EmptyApplication
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
IEmotes *getEmotes() override
|
||||||
|
{
|
||||||
|
return &this->emotes;
|
||||||
|
}
|
||||||
|
|
||||||
|
IUserDataController *getUserData() override
|
||||||
|
{
|
||||||
|
return &this->userData;
|
||||||
|
}
|
||||||
|
|
||||||
|
AccountController *getAccounts() override
|
||||||
|
{
|
||||||
|
return &this->accounts;
|
||||||
|
}
|
||||||
|
|
||||||
|
ITwitchIrcServer *getTwitch() override
|
||||||
|
{
|
||||||
|
return &this->twitch;
|
||||||
|
}
|
||||||
|
|
||||||
|
ChatterinoBadges *getChatterinoBadges() override
|
||||||
|
{
|
||||||
|
return &this->chatterinoBadges;
|
||||||
|
}
|
||||||
|
|
||||||
|
FfzBadges *getFfzBadges() override
|
||||||
|
{
|
||||||
|
return &this->ffzBadges;
|
||||||
|
}
|
||||||
|
|
||||||
|
SeventvBadges *getSeventvBadges() override
|
||||||
|
{
|
||||||
|
return &this->seventvBadges;
|
||||||
|
}
|
||||||
|
|
||||||
|
HighlightController *getHighlights() override
|
||||||
|
{
|
||||||
|
return &this->highlights;
|
||||||
|
}
|
||||||
|
|
||||||
|
AccountController accounts;
|
||||||
|
Emotes emotes;
|
||||||
|
mock::UserDataController userData;
|
||||||
|
mock::MockTwitchIrcServer twitch;
|
||||||
|
ChatterinoBadges chatterinoBadges;
|
||||||
|
FfzBadges ffzBadges;
|
||||||
|
SeventvBadges seventvBadges;
|
||||||
|
HighlightController highlights;
|
||||||
|
};
|
||||||
|
|
||||||
|
std::optional<QJsonDocument> tryReadJsonFile(const QString &path)
|
||||||
|
{
|
||||||
|
QFile file(path);
|
||||||
|
if (!file.open(QFile::ReadOnly))
|
||||||
|
{
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
|
||||||
|
QJsonParseError e;
|
||||||
|
auto doc = QJsonDocument::fromJson(file.readAll(), &e);
|
||||||
|
if (e.error != QJsonParseError::NoError)
|
||||||
|
{
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
|
||||||
|
return doc;
|
||||||
|
}
|
||||||
|
|
||||||
|
QJsonDocument readJsonFile(const QString &path)
|
||||||
|
{
|
||||||
|
auto opt = tryReadJsonFile(path);
|
||||||
|
if (!opt)
|
||||||
|
{
|
||||||
|
_exit(1);
|
||||||
|
}
|
||||||
|
return *opt;
|
||||||
|
}
|
||||||
|
|
||||||
|
class RecentMessages
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
explicit RecentMessages(const QString &name_)
|
||||||
|
: name(name_)
|
||||||
|
, chan(this->name)
|
||||||
|
{
|
||||||
|
const auto seventvEmotes =
|
||||||
|
tryReadJsonFile(u":/bench/seventvemotes-%1.json"_s.arg(this->name));
|
||||||
|
const auto bttvEmotes =
|
||||||
|
tryReadJsonFile(u":/bench/bttvemotes-%1.json"_s.arg(this->name));
|
||||||
|
const auto ffzEmotes =
|
||||||
|
tryReadJsonFile(u":/bench/ffzemotes-%1.json"_s.arg(this->name));
|
||||||
|
|
||||||
|
if (seventvEmotes)
|
||||||
|
{
|
||||||
|
this->chan.setSeventvEmotes(
|
||||||
|
std::make_shared<const EmoteMap>(seventv::detail::parseEmotes(
|
||||||
|
seventvEmotes->object()["emote_set"_L1]
|
||||||
|
.toObject()["emotes"_L1]
|
||||||
|
.toArray(),
|
||||||
|
false)));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bttvEmotes)
|
||||||
|
{
|
||||||
|
this->chan.setBttvEmotes(std::make_shared<const EmoteMap>(
|
||||||
|
bttv::detail::parseChannelEmotes(bttvEmotes->object(),
|
||||||
|
this->name)));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ffzEmotes)
|
||||||
|
{
|
||||||
|
this->chan.setFfzEmotes(std::make_shared<const EmoteMap>(
|
||||||
|
ffz::detail::parseChannelEmotes(ffzEmotes->object())));
|
||||||
|
}
|
||||||
|
|
||||||
|
this->messages =
|
||||||
|
readJsonFile(u":/bench/recentmessages-%1.json"_s.arg(this->name));
|
||||||
|
}
|
||||||
|
|
||||||
|
~RecentMessages()
|
||||||
|
{
|
||||||
|
QCoreApplication::sendPostedEvents(nullptr, QEvent::DeferredDelete);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void run(benchmark::State &state) = 0;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
QString name;
|
||||||
|
MockApplication app;
|
||||||
|
TwitchChannel chan;
|
||||||
|
QJsonDocument messages;
|
||||||
|
};
|
||||||
|
|
||||||
|
class ParseRecentMessages : public RecentMessages
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
explicit ParseRecentMessages(const QString &name_)
|
||||||
|
: RecentMessages(name_)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void run(benchmark::State &state)
|
||||||
|
{
|
||||||
|
for (auto _ : state)
|
||||||
|
{
|
||||||
|
auto parsed = recentmessages::detail::parseRecentMessages(
|
||||||
|
this->messages.object());
|
||||||
|
benchmark::DoNotOptimize(parsed);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class BuildRecentMessages : public RecentMessages
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
explicit BuildRecentMessages(const QString &name_)
|
||||||
|
: RecentMessages(name_)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void run(benchmark::State &state)
|
||||||
|
{
|
||||||
|
auto parsed = recentmessages::detail::parseRecentMessages(
|
||||||
|
this->messages.object());
|
||||||
|
for (auto _ : state)
|
||||||
|
{
|
||||||
|
auto built = recentmessages::detail::buildRecentMessages(
|
||||||
|
parsed, &this->chan);
|
||||||
|
benchmark::DoNotOptimize(built);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
void BM_ParseRecentMessages(benchmark::State &state, const QString &name)
|
||||||
|
{
|
||||||
|
ParseRecentMessages bench(name);
|
||||||
|
bench.run(state);
|
||||||
|
}
|
||||||
|
|
||||||
|
void BM_BuildRecentMessages(benchmark::State &state, const QString &name)
|
||||||
|
{
|
||||||
|
BuildRecentMessages bench(name);
|
||||||
|
bench.run(state);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
BENCHMARK_CAPTURE(BM_ParseRecentMessages, nymn, u"nymn"_s);
|
||||||
|
BENCHMARK_CAPTURE(BM_BuildRecentMessages, nymn, u"nymn"_s);
|
|
@ -1,3 +1,4 @@
|
||||||
|
#include "singletons/Resources.hpp"
|
||||||
#include "singletons/Settings.hpp"
|
#include "singletons/Settings.hpp"
|
||||||
|
|
||||||
#include <benchmark/benchmark.h>
|
#include <benchmark/benchmark.h>
|
||||||
|
@ -11,6 +12,8 @@ int main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
QApplication app(argc, argv);
|
QApplication app(argc, argv);
|
||||||
|
|
||||||
|
initResources();
|
||||||
|
|
||||||
::benchmark::Initialize(&argc, argv);
|
::benchmark::Initialize(&argc, argv);
|
||||||
|
|
||||||
// Ensure settings are initialized before any benchmarks are run
|
// Ensure settings are initialized before any benchmarks are run
|
||||||
|
|
|
@ -32,9 +32,11 @@ bool isIgnoredMessage(IgnoredMessageParameters &¶ms)
|
||||||
{
|
{
|
||||||
auto sourceUserID = params.twitchUserID;
|
auto sourceUserID = params.twitchUserID;
|
||||||
|
|
||||||
bool isBlocked =
|
bool isBlocked = getIApp()
|
||||||
getApp()->accounts->twitch.getCurrent()->blockedUserIds().contains(
|
->getAccounts()
|
||||||
sourceUserID);
|
->twitch.getCurrent()
|
||||||
|
->blockedUserIds()
|
||||||
|
.contains(sourceUserID);
|
||||||
if (isBlocked)
|
if (isBlocked)
|
||||||
{
|
{
|
||||||
switch (static_cast<ShowIgnoredUsersMessages>(
|
switch (static_cast<ShowIgnoredUsersMessages>(
|
||||||
|
|
|
@ -142,31 +142,33 @@ namespace {
|
||||||
return anyModifications;
|
return anyModifications;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::pair<Outcome, EmoteMap> parseChannelEmotes(
|
|
||||||
const QJsonObject &jsonRoot, const QString &channelDisplayName)
|
|
||||||
{
|
|
||||||
auto emotes = EmoteMap();
|
|
||||||
|
|
||||||
auto innerParse = [&jsonRoot, &emotes,
|
|
||||||
&channelDisplayName](const char *key) {
|
|
||||||
auto jsonEmotes = jsonRoot.value(key).toArray();
|
|
||||||
for (auto jsonEmote_ : jsonEmotes)
|
|
||||||
{
|
|
||||||
auto emote = createChannelEmote(channelDisplayName,
|
|
||||||
jsonEmote_.toObject());
|
|
||||||
|
|
||||||
emotes[emote.name] =
|
|
||||||
cachedOrMake(std::move(emote.emote), emote.id);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
innerParse("channelEmotes");
|
|
||||||
innerParse("sharedEmotes");
|
|
||||||
|
|
||||||
return {Success, std::move(emotes)};
|
|
||||||
}
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
|
using namespace bttv::detail;
|
||||||
|
|
||||||
|
EmoteMap bttv::detail::parseChannelEmotes(const QJsonObject &jsonRoot,
|
||||||
|
const QString &channelDisplayName)
|
||||||
|
{
|
||||||
|
auto emotes = EmoteMap();
|
||||||
|
|
||||||
|
auto innerParse = [&jsonRoot, &emotes,
|
||||||
|
&channelDisplayName](const char *key) {
|
||||||
|
auto jsonEmotes = jsonRoot.value(key).toArray();
|
||||||
|
for (auto jsonEmote_ : jsonEmotes)
|
||||||
|
{
|
||||||
|
auto emote =
|
||||||
|
createChannelEmote(channelDisplayName, jsonEmote_.toObject());
|
||||||
|
|
||||||
|
emotes[emote.name] = cachedOrMake(std::move(emote.emote), emote.id);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
innerParse("channelEmotes");
|
||||||
|
innerParse("sharedEmotes");
|
||||||
|
|
||||||
|
return emotes;
|
||||||
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// BttvEmotes
|
// BttvEmotes
|
||||||
//
|
//
|
||||||
|
@ -230,14 +232,11 @@ void BttvEmotes::loadChannel(std::weak_ptr<Channel> channel,
|
||||||
.timeout(20000)
|
.timeout(20000)
|
||||||
.onSuccess([callback = std::move(callback), channel, channelDisplayName,
|
.onSuccess([callback = std::move(callback), channel, channelDisplayName,
|
||||||
manualRefresh](auto result) {
|
manualRefresh](auto result) {
|
||||||
auto pair =
|
auto emotes =
|
||||||
parseChannelEmotes(result.parseJson(), channelDisplayName);
|
parseChannelEmotes(result.parseJson(), channelDisplayName);
|
||||||
bool hasEmotes = false;
|
bool hasEmotes = !emotes.empty();
|
||||||
if (pair.first)
|
callback(std::move(emotes));
|
||||||
{
|
|
||||||
hasEmotes = !pair.second.empty();
|
|
||||||
callback(std::move(pair.second));
|
|
||||||
}
|
|
||||||
if (auto shared = channel.lock(); manualRefresh)
|
if (auto shared = channel.lock(); manualRefresh)
|
||||||
{
|
{
|
||||||
if (hasEmotes)
|
if (hasEmotes)
|
||||||
|
|
|
@ -3,6 +3,8 @@
|
||||||
#include "common/Aliases.hpp"
|
#include "common/Aliases.hpp"
|
||||||
#include "common/Atomic.hpp"
|
#include "common/Atomic.hpp"
|
||||||
|
|
||||||
|
#include <QJsonObject>
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <optional>
|
#include <optional>
|
||||||
|
|
||||||
|
@ -15,6 +17,13 @@ class Channel;
|
||||||
struct BttvLiveUpdateEmoteUpdateAddMessage;
|
struct BttvLiveUpdateEmoteUpdateAddMessage;
|
||||||
struct BttvLiveUpdateEmoteRemoveMessage;
|
struct BttvLiveUpdateEmoteRemoveMessage;
|
||||||
|
|
||||||
|
namespace bttv::detail {
|
||||||
|
|
||||||
|
EmoteMap parseChannelEmotes(const QJsonObject &jsonRoot,
|
||||||
|
const QString &channelDisplayName);
|
||||||
|
|
||||||
|
} // namespace bttv::detail
|
||||||
|
|
||||||
class BttvEmotes final
|
class BttvEmotes final
|
||||||
{
|
{
|
||||||
static constexpr const char *globalEmoteApiUrl =
|
static constexpr const char *globalEmoteApiUrl =
|
||||||
|
|
|
@ -149,19 +149,22 @@ namespace {
|
||||||
return authorityBadge;
|
return authorityBadge;
|
||||||
}
|
}
|
||||||
|
|
||||||
EmoteMap parseChannelEmotes(const QJsonObject &jsonRoot)
|
|
||||||
{
|
|
||||||
auto emotes = EmoteMap();
|
|
||||||
|
|
||||||
for (const auto emoteSetRef : jsonRoot["sets"].toObject())
|
|
||||||
{
|
|
||||||
parseEmoteSetInto(emoteSetRef.toObject(), "Channel", emotes);
|
|
||||||
}
|
|
||||||
|
|
||||||
return emotes;
|
|
||||||
}
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
|
using namespace ffz::detail;
|
||||||
|
|
||||||
|
EmoteMap ffz::detail::parseChannelEmotes(const QJsonObject &jsonRoot)
|
||||||
|
{
|
||||||
|
auto emotes = EmoteMap();
|
||||||
|
|
||||||
|
for (const auto emoteSetRef : jsonRoot["sets"].toObject())
|
||||||
|
{
|
||||||
|
parseEmoteSetInto(emoteSetRef.toObject(), "Channel", emotes);
|
||||||
|
}
|
||||||
|
|
||||||
|
return emotes;
|
||||||
|
}
|
||||||
|
|
||||||
FfzEmotes::FfzEmotes()
|
FfzEmotes::FfzEmotes()
|
||||||
: global_(std::make_shared<EmoteMap>())
|
: global_(std::make_shared<EmoteMap>())
|
||||||
{
|
{
|
||||||
|
|
|
@ -3,6 +3,8 @@
|
||||||
#include "common/Aliases.hpp"
|
#include "common/Aliases.hpp"
|
||||||
#include "common/Atomic.hpp"
|
#include "common/Atomic.hpp"
|
||||||
|
|
||||||
|
#include <QJsonObject>
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <optional>
|
#include <optional>
|
||||||
|
|
||||||
|
@ -13,6 +15,12 @@ using EmotePtr = std::shared_ptr<const Emote>;
|
||||||
class EmoteMap;
|
class EmoteMap;
|
||||||
class Channel;
|
class Channel;
|
||||||
|
|
||||||
|
namespace ffz::detail {
|
||||||
|
|
||||||
|
EmoteMap parseChannelEmotes(const QJsonObject &jsonRoot);
|
||||||
|
|
||||||
|
} // namespace ffz::detail
|
||||||
|
|
||||||
class FfzEmotes final
|
class FfzEmotes final
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
|
@ -128,7 +128,34 @@ bool checkEmoteVisibility(const QJsonObject &emoteData)
|
||||||
return !flags.has(SeventvEmoteFlag::ContentTwitchDisallowed);
|
return !flags.has(SeventvEmoteFlag::ContentTwitchDisallowed);
|
||||||
}
|
}
|
||||||
|
|
||||||
EmoteMap parseEmotes(const QJsonArray &emoteSetEmotes, bool isGlobal)
|
EmotePtr createUpdatedEmote(const EmotePtr &oldEmote,
|
||||||
|
const EmoteUpdateDispatch &dispatch)
|
||||||
|
{
|
||||||
|
bool toNonAliased = oldEmote->baseName.has_value() &&
|
||||||
|
dispatch.emoteName == oldEmote->baseName->string;
|
||||||
|
|
||||||
|
auto baseName = oldEmote->baseName.value_or(oldEmote->name);
|
||||||
|
auto emote = std::make_shared<const Emote>(Emote(
|
||||||
|
{EmoteName{dispatch.emoteName}, oldEmote->images,
|
||||||
|
toNonAliased
|
||||||
|
? createTooltip(dispatch.emoteName, oldEmote->author.string, false)
|
||||||
|
: createAliasedTooltip(dispatch.emoteName, baseName.string,
|
||||||
|
oldEmote->author.string, false),
|
||||||
|
oldEmote->homePage, oldEmote->zeroWidth, oldEmote->id,
|
||||||
|
oldEmote->author, makeConditionedOptional(!toNonAliased, baseName)}));
|
||||||
|
return emote;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
namespace chatterino {
|
||||||
|
|
||||||
|
using namespace seventv::eventapi;
|
||||||
|
using namespace seventv::detail;
|
||||||
|
using namespace literals;
|
||||||
|
|
||||||
|
EmoteMap seventv::detail::parseEmotes(const QJsonArray &emoteSetEmotes,
|
||||||
|
bool isGlobal)
|
||||||
{
|
{
|
||||||
auto emotes = EmoteMap();
|
auto emotes = EmoteMap();
|
||||||
|
|
||||||
|
@ -158,31 +185,6 @@ EmoteMap parseEmotes(const QJsonArray &emoteSetEmotes, bool isGlobal)
|
||||||
return emotes;
|
return emotes;
|
||||||
}
|
}
|
||||||
|
|
||||||
EmotePtr createUpdatedEmote(const EmotePtr &oldEmote,
|
|
||||||
const EmoteUpdateDispatch &dispatch)
|
|
||||||
{
|
|
||||||
bool toNonAliased = oldEmote->baseName.has_value() &&
|
|
||||||
dispatch.emoteName == oldEmote->baseName->string;
|
|
||||||
|
|
||||||
auto baseName = oldEmote->baseName.value_or(oldEmote->name);
|
|
||||||
auto emote = std::make_shared<const Emote>(Emote(
|
|
||||||
{EmoteName{dispatch.emoteName}, oldEmote->images,
|
|
||||||
toNonAliased
|
|
||||||
? createTooltip(dispatch.emoteName, oldEmote->author.string, false)
|
|
||||||
: createAliasedTooltip(dispatch.emoteName, baseName.string,
|
|
||||||
oldEmote->author.string, false),
|
|
||||||
oldEmote->homePage, oldEmote->zeroWidth, oldEmote->id,
|
|
||||||
oldEmote->author, makeConditionedOptional(!toNonAliased, baseName)}));
|
|
||||||
return emote;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace
|
|
||||||
|
|
||||||
namespace chatterino {
|
|
||||||
|
|
||||||
using namespace seventv::eventapi;
|
|
||||||
using namespace literals;
|
|
||||||
|
|
||||||
SeventvEmotes::SeventvEmotes()
|
SeventvEmotes::SeventvEmotes()
|
||||||
: global_(std::make_shared<EmoteMap>())
|
: global_(std::make_shared<EmoteMap>())
|
||||||
{
|
{
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
#include "common/Atomic.hpp"
|
#include "common/Atomic.hpp"
|
||||||
#include "common/FlagsEnum.hpp"
|
#include "common/FlagsEnum.hpp"
|
||||||
|
|
||||||
|
#include <QJsonArray>
|
||||||
#include <QJsonObject>
|
#include <QJsonObject>
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
@ -77,6 +78,12 @@ enum class SeventvEmoteSetFlag : uint32_t {
|
||||||
};
|
};
|
||||||
using SeventvEmoteSetFlags = FlagsEnum<SeventvEmoteSetFlag>;
|
using SeventvEmoteSetFlags = FlagsEnum<SeventvEmoteSetFlag>;
|
||||||
|
|
||||||
|
namespace seventv::detail {
|
||||||
|
|
||||||
|
EmoteMap parseEmotes(const QJsonArray &emoteSetEmotes, bool isGlobal);
|
||||||
|
|
||||||
|
} // namespace seventv::detail
|
||||||
|
|
||||||
class SeventvEmotes final
|
class SeventvEmotes final
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
|
@ -128,7 +128,7 @@ void updateReplyParticipatedStatus(const QVariantMap &tags,
|
||||||
bool isNew)
|
bool isNew)
|
||||||
{
|
{
|
||||||
const auto ¤tLogin =
|
const auto ¤tLogin =
|
||||||
getApp()->accounts->twitch.getCurrent()->getUserName();
|
getIApp()->getAccounts()->twitch.getCurrent()->getUserName();
|
||||||
|
|
||||||
if (thread->subscribed())
|
if (thread->subscribed())
|
||||||
{
|
{
|
||||||
|
|
|
@ -29,6 +29,12 @@ void TwitchBadges::loadTwitchBadges()
|
||||||
{
|
{
|
||||||
assert(this->loaded_ == false);
|
assert(this->loaded_ == false);
|
||||||
|
|
||||||
|
if (!getHelix())
|
||||||
|
{
|
||||||
|
// This is intended for tests and benchmarks.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
getHelix()->getGlobalBadges(
|
getHelix()->getGlobalBadges(
|
||||||
[this](auto globalBadges) {
|
[this](auto globalBadges) {
|
||||||
auto badgeSets = this->badgeSets_.access();
|
auto badgeSets = this->badgeSets_.access();
|
||||||
|
|
|
@ -87,6 +87,13 @@ TwitchChannel::TwitchChannel(const QString &name)
|
||||||
{
|
{
|
||||||
qCDebug(chatterinoTwitch) << "[TwitchChannel" << name << "] Opened";
|
qCDebug(chatterinoTwitch) << "[TwitchChannel" << name << "] Opened";
|
||||||
|
|
||||||
|
if (!getApp())
|
||||||
|
{
|
||||||
|
// This is intended for tests and benchmarks.
|
||||||
|
// Irc, Pubsub, live-updates, and live-notifications aren't mocked there.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
this->bSignals_.emplace_back(
|
this->bSignals_.emplace_back(
|
||||||
getApp()->accounts->twitch.currentUserChanged.connect([this] {
|
getApp()->accounts->twitch.currentUserChanged.connect([this] {
|
||||||
this->setMod(false);
|
this->setMod(false);
|
||||||
|
@ -219,6 +226,13 @@ TwitchChannel::TwitchChannel(const QString &name)
|
||||||
|
|
||||||
TwitchChannel::~TwitchChannel()
|
TwitchChannel::~TwitchChannel()
|
||||||
{
|
{
|
||||||
|
if (!getApp())
|
||||||
|
{
|
||||||
|
// This is for tests and benchmarks, where live-updates aren't mocked
|
||||||
|
// see comment in constructor.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
getApp()->twitch->dropSeventvChannel(this->seventvUserID_,
|
getApp()->twitch->dropSeventvChannel(this->seventvUserID_,
|
||||||
this->seventvEmoteSetID_);
|
this->seventvEmoteSetID_);
|
||||||
|
|
||||||
|
@ -282,8 +296,9 @@ void TwitchChannel::refreshBTTVChannelEmotes(bool manualRefresh)
|
||||||
weakOf<Channel>(this), this->roomId(), this->getLocalizedName(),
|
weakOf<Channel>(this), this->roomId(), this->getLocalizedName(),
|
||||||
[this, weak = weakOf<Channel>(this)](auto &&emoteMap) {
|
[this, weak = weakOf<Channel>(this)](auto &&emoteMap) {
|
||||||
if (auto shared = weak.lock())
|
if (auto shared = weak.lock())
|
||||||
this->bttvEmotes_.set(
|
{
|
||||||
std::make_shared<EmoteMap>(std::move(emoteMap)));
|
this->setBttvEmotes(std::make_shared<const EmoteMap>(emoteMap));
|
||||||
|
}
|
||||||
},
|
},
|
||||||
manualRefresh);
|
manualRefresh);
|
||||||
}
|
}
|
||||||
|
@ -300,8 +315,9 @@ void TwitchChannel::refreshFFZChannelEmotes(bool manualRefresh)
|
||||||
weakOf<Channel>(this), this->roomId(),
|
weakOf<Channel>(this), this->roomId(),
|
||||||
[this, weak = weakOf<Channel>(this)](auto &&emoteMap) {
|
[this, weak = weakOf<Channel>(this)](auto &&emoteMap) {
|
||||||
if (auto shared = weak.lock())
|
if (auto shared = weak.lock())
|
||||||
this->ffzEmotes_.set(
|
{
|
||||||
std::make_shared<EmoteMap>(std::move(emoteMap)));
|
this->setFfzEmotes(std::make_shared<const EmoteMap>(emoteMap));
|
||||||
|
}
|
||||||
},
|
},
|
||||||
[this, weak = weakOf<Channel>(this)](auto &&modBadge) {
|
[this, weak = weakOf<Channel>(this)](auto &&modBadge) {
|
||||||
if (auto shared = weak.lock())
|
if (auto shared = weak.lock())
|
||||||
|
@ -332,8 +348,8 @@ void TwitchChannel::refreshSevenTVChannelEmotes(bool manualRefresh)
|
||||||
auto channelInfo) {
|
auto channelInfo) {
|
||||||
if (auto shared = weak.lock())
|
if (auto shared = weak.lock())
|
||||||
{
|
{
|
||||||
this->seventvEmotes_.set(std::make_shared<EmoteMap>(
|
this->setSeventvEmotes(
|
||||||
std::forward<decltype(emoteMap)>(emoteMap)));
|
std::make_shared<const EmoteMap>(emoteMap));
|
||||||
this->updateSeventvData(channelInfo.userID,
|
this->updateSeventvData(channelInfo.userID,
|
||||||
channelInfo.emoteSetID);
|
channelInfo.emoteSetID);
|
||||||
this->seventvUserTwitchConnectionIndex_ =
|
this->seventvUserTwitchConnectionIndex_ =
|
||||||
|
@ -343,6 +359,21 @@ void TwitchChannel::refreshSevenTVChannelEmotes(bool manualRefresh)
|
||||||
manualRefresh);
|
manualRefresh);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void TwitchChannel::setBttvEmotes(std::shared_ptr<const EmoteMap> &&map)
|
||||||
|
{
|
||||||
|
this->bttvEmotes_.set(std::move(map));
|
||||||
|
}
|
||||||
|
|
||||||
|
void TwitchChannel::setFfzEmotes(std::shared_ptr<const EmoteMap> &&map)
|
||||||
|
{
|
||||||
|
this->ffzEmotes_.set(std::move(map));
|
||||||
|
}
|
||||||
|
|
||||||
|
void TwitchChannel::setSeventvEmotes(std::shared_ptr<const EmoteMap> &&map)
|
||||||
|
{
|
||||||
|
this->seventvEmotes_.set(std::move(map));
|
||||||
|
}
|
||||||
|
|
||||||
void TwitchChannel::addQueuedRedemption(const QString &rewardId,
|
void TwitchChannel::addQueuedRedemption(const QString &rewardId,
|
||||||
const QString &originalContent,
|
const QString &originalContent,
|
||||||
Communi::IrcMessage *message)
|
Communi::IrcMessage *message)
|
||||||
|
@ -700,9 +731,10 @@ void TwitchChannel::setStaff(bool value)
|
||||||
|
|
||||||
bool TwitchChannel::isBroadcaster() const
|
bool TwitchChannel::isBroadcaster() const
|
||||||
{
|
{
|
||||||
auto app = getApp();
|
auto *app = getIApp();
|
||||||
|
|
||||||
return this->getName() == app->accounts->twitch.getCurrent()->getUserName();
|
return this->getName() ==
|
||||||
|
app->getAccounts()->twitch.getCurrent()->getUserName();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TwitchChannel::hasHighRateLimit() const
|
bool TwitchChannel::hasHighRateLimit() const
|
||||||
|
@ -730,8 +762,12 @@ void TwitchChannel::setRoomId(const QString &id)
|
||||||
if (*this->roomID_.accessConst() != id)
|
if (*this->roomID_.accessConst() != id)
|
||||||
{
|
{
|
||||||
*this->roomID_.access() = id;
|
*this->roomID_.access() = id;
|
||||||
this->roomIdChanged();
|
// This is intended for tests and benchmarks. See comment in constructor.
|
||||||
this->loadRecentMessages();
|
if (getApp())
|
||||||
|
{
|
||||||
|
this->roomIdChanged();
|
||||||
|
this->loadRecentMessages();
|
||||||
|
}
|
||||||
this->disconnected_ = false;
|
this->disconnected_ = false;
|
||||||
this->lastConnectedAt_ = std::chrono::system_clock::now();
|
this->lastConnectedAt_ = std::chrono::system_clock::now();
|
||||||
}
|
}
|
||||||
|
|
|
@ -158,6 +158,10 @@ public:
|
||||||
void refreshFFZChannelEmotes(bool manualRefresh);
|
void refreshFFZChannelEmotes(bool manualRefresh);
|
||||||
void refreshSevenTVChannelEmotes(bool manualRefresh);
|
void refreshSevenTVChannelEmotes(bool manualRefresh);
|
||||||
|
|
||||||
|
void setBttvEmotes(std::shared_ptr<const EmoteMap> &&map);
|
||||||
|
void setFfzEmotes(std::shared_ptr<const EmoteMap> &&map);
|
||||||
|
void setSeventvEmotes(std::shared_ptr<const EmoteMap> &&map);
|
||||||
|
|
||||||
const QString &seventvUserID() const;
|
const QString &seventvUserID() const;
|
||||||
const QString &seventvEmoteSetID() const;
|
const QString &seventvEmoteSetID() const;
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue