From f0802af05506d3f6d02119ba1e608d4be8ac83d0 Mon Sep 17 00:00:00 2001 From: pajlada Date: Thu, 8 Aug 2024 15:08:31 +0200 Subject: [PATCH] refactor: move seventv/bttv event apis to application (#5532) --- CHANGELOG.md | 1 + mocks/include/mocks/BaseApplication.hpp | 11 +++ mocks/include/mocks/EmptyApplication.hpp | 14 ++++ mocks/include/mocks/TwitchIrcServer.hpp | 15 ---- src/Application.cpp | 94 ++++++++++++++++++------ src/Application.hpp | 8 ++ src/RunGui.cpp | 1 + src/providers/twitch/TwitchChannel.cpp | 23 +++--- src/providers/twitch/TwitchIrcServer.cpp | 33 +-------- src/providers/twitch/TwitchIrcServer.hpp | 11 --- src/singletons/StreamerMode.cpp | 11 +++ tests/src/Commands.cpp | 8 +- 12 files changed, 133 insertions(+), 97 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f458677cc..b4c03b1af 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -58,6 +58,7 @@ - Dev: The running Qt version is now shown in the about page if it differs from the compiled version. (#5501) - Dev: `FlagsEnum` is now `constexpr`. (#5510) - Dev: Documented and added tests to RTL handling. (#5473) +- Dev: Refactored 7TV/BTTV definitions out of `TwitchIrcServer` into `Application`. (#5532) - Dev: Refactored a few `#define`s into `const(expr)` and cleaned includes. (#5527) - Dev: Prepared for Qt 6.8 by addressing some deprecations. (#5529) diff --git a/mocks/include/mocks/BaseApplication.hpp b/mocks/include/mocks/BaseApplication.hpp index 720d1f684..b858a87a1 100644 --- a/mocks/include/mocks/BaseApplication.hpp +++ b/mocks/include/mocks/BaseApplication.hpp @@ -2,6 +2,7 @@ #include "mocks/DisabledStreamerMode.hpp" #include "mocks/EmptyApplication.hpp" +#include "providers/bttv/BttvLiveUpdates.hpp" #include "singletons/Settings.hpp" #include @@ -30,6 +31,16 @@ public: return &this->streamerMode; } + BttvLiveUpdates *getBttvLiveUpdates() override + { + return nullptr; + } + + SeventvEventAPI *getSeventvEventAPI() override + { + return nullptr; + } + Settings settings; DisabledStreamerMode streamerMode; }; diff --git a/mocks/include/mocks/EmptyApplication.hpp b/mocks/include/mocks/EmptyApplication.hpp index e293a56e4..c88902871 100644 --- a/mocks/include/mocks/EmptyApplication.hpp +++ b/mocks/include/mocks/EmptyApplication.hpp @@ -231,6 +231,13 @@ public: return nullptr; } + BttvLiveUpdates *getBttvLiveUpdates() override + { + assert(false && "EmptyApplication::getBttvLiveUpdates was called " + "without being initialized"); + return nullptr; + } + FfzEmotes *getFfzEmotes() override { assert(false && "EmptyApplication::getFfzEmotes was called without " @@ -245,6 +252,13 @@ public: return nullptr; } + SeventvEventAPI *getSeventvEventAPI() override + { + assert(false && "EmptyApplication::getSeventvEventAPI was called " + "without being initialized"); + return nullptr; + } + ILinkResolver *getLinkResolver() override { assert(false && "EmptyApplication::getLinkResolver was called without " diff --git a/mocks/include/mocks/TwitchIrcServer.hpp b/mocks/include/mocks/TwitchIrcServer.hpp index 42abc30ec..9428a1d1d 100644 --- a/mocks/include/mocks/TwitchIrcServer.hpp +++ b/mocks/include/mocks/TwitchIrcServer.hpp @@ -2,13 +2,11 @@ #include "mocks/Channel.hpp" #include "providers/bttv/BttvEmotes.hpp" -#include "providers/bttv/BttvLiveUpdates.hpp" #include "providers/ffz/FfzEmotes.hpp" #include "providers/seventv/eventapi/Client.hpp" #include "providers/seventv/eventapi/Dispatch.hpp" #include "providers/seventv/eventapi/Message.hpp" #include "providers/seventv/SeventvEmotes.hpp" -#include "providers/seventv/SeventvEventAPI.hpp" #include "providers/twitch/TwitchIrcServer.hpp" namespace chatterino::mock { @@ -46,16 +44,6 @@ public: // } - std::unique_ptr &getBTTVLiveUpdates() override - { - return this->bttvLiveUpdates; - } - - std::unique_ptr &getSeventvEventAPI() override - { - return this->seventvEventAPI; - } - const IndirectChannel &getWatchingChannel() const override { return this->watchingChannel; @@ -103,9 +91,6 @@ public: ChannelPtr liveChannel; ChannelPtr automodChannel; QString lastUserThatWhisperedMe{"forsen"}; - - std::unique_ptr bttvLiveUpdates; - std::unique_ptr seventvEventAPI; }; } // namespace chatterino::mock diff --git a/src/Application.cpp b/src/Application.cpp index 6020fb865..5495d3af0 100644 --- a/src/Application.cpp +++ b/src/Application.cpp @@ -72,6 +72,9 @@ namespace { using namespace chatterino; +const QString BTTV_LIVE_UPDATES_URL = "wss://sockets.betterttv.net/ws"; +const QString SEVENTV_EVENTAPI_URL = "wss://events.7tv.io/v3"; + ISoundController *makeSoundController(Settings &settings) { SoundBackend soundBackend = settings.soundBackend; @@ -94,6 +97,31 @@ ISoundController *makeSoundController(Settings &settings) } } +BttvLiveUpdates *makeBttvLiveUpdates(Settings &settings) +{ + bool enabled = + settings.enableBTTVLiveUpdates && settings.enableBTTVChannelEmotes; + + if (enabled) + { + return new BttvLiveUpdates(BTTV_LIVE_UPDATES_URL); + } + + return nullptr; +} + +SeventvEventAPI *makeSeventvEventAPI(Settings &settings) +{ + bool enabled = settings.enableSevenTVEventAPI; + + if (enabled) + { + return new SeventvEventAPI(SEVENTV_EVENTAPI_URL); + } + + return nullptr; +} + const QString TWITCH_PUBSUB_URL = "wss://pubsub-edge.twitch.tv"; } // namespace @@ -142,8 +170,10 @@ Application::Application(Settings &_settings, const Paths &paths, , twitchBadges(new TwitchBadges) , chatterinoBadges(new ChatterinoBadges) , bttvEmotes(new BttvEmotes) + , bttvLiveUpdates(makeBttvLiveUpdates(_settings)) , ffzEmotes(new FfzEmotes) , seventvEmotes(new SeventvEmotes) + , seventvEventAPI(makeSeventvEventAPI(_settings)) , logging(new Logging(_settings)) , linkResolver(new LinkResolver) , streamerMode(new StreamerMode) @@ -161,7 +191,10 @@ Application::Application(Settings &_settings, const Paths &paths, }); } -Application::~Application() = default; +Application::~Application() +{ + Application::instance = nullptr; +} void Application::fakeDtor() { @@ -172,8 +205,10 @@ void Application::fakeDtor() this->twitchBadges.reset(); this->twitchLiveController.reset(); this->chatterinoBadges.reset(); + // this->bttvLiveUpdates.reset(); this->bttvEmotes.reset(); this->ffzEmotes.reset(); + // this->seventvEventAPI.reset(); this->seventvEmotes.reset(); this->notifications.reset(); this->commands.reset(); @@ -194,6 +229,7 @@ void Application::fakeDtor() this->accounts.reset(); this->emotes.reset(); this->themes.reset(); + this->streamerMode.reset(); } void Application::initialize(Settings &settings, const Paths &paths) @@ -574,6 +610,14 @@ BttvEmotes *Application::getBttvEmotes() return this->bttvEmotes.get(); } +BttvLiveUpdates *Application::getBttvLiveUpdates() +{ + assertInGuiThread(); + // bttvLiveUpdates may be nullptr if it's not enabled + + return this->bttvLiveUpdates.get(); +} + FfzEmotes *Application::getFfzEmotes() { assertInGuiThread(); @@ -590,6 +634,14 @@ SeventvEmotes *Application::getSeventvEmotes() return this->seventvEmotes.get(); } +SeventvEventAPI *Application::getSeventvEventAPI() +{ + assertInGuiThread(); + // seventvEventAPI may be nullptr if it's not enabled + + return this->seventvEventAPI.get(); +} + void Application::save() { this->commands->save(); @@ -1066,9 +1118,7 @@ void Application::initPubSub() void Application::initBttvLiveUpdates() { - auto &bttvLiveUpdates = this->twitch->getBTTVLiveUpdates(); - - if (!bttvLiveUpdates) + if (!this->bttvLiveUpdates) { qCDebug(chatterinoBttv) << "Skipping initialization of Live Updates as it's disabled"; @@ -1077,8 +1127,8 @@ void Application::initBttvLiveUpdates() // We can safely ignore these signal connections since the twitch object will always // be destroyed before the Application - std::ignore = - bttvLiveUpdates->signals_.emoteAdded.connect([&](const auto &data) { + std::ignore = this->bttvLiveUpdates->signals_.emoteAdded.connect( + [&](const auto &data) { auto chan = this->twitch->getChannelOrEmptyByID(data.channelID); postToThread([chan, data] { @@ -1088,8 +1138,8 @@ void Application::initBttvLiveUpdates() } }); }); - std::ignore = - bttvLiveUpdates->signals_.emoteUpdated.connect([&](const auto &data) { + std::ignore = this->bttvLiveUpdates->signals_.emoteUpdated.connect( + [&](const auto &data) { auto chan = this->twitch->getChannelOrEmptyByID(data.channelID); postToThread([chan, data] { @@ -1099,8 +1149,8 @@ void Application::initBttvLiveUpdates() } }); }); - std::ignore = - bttvLiveUpdates->signals_.emoteRemoved.connect([&](const auto &data) { + std::ignore = this->bttvLiveUpdates->signals_.emoteRemoved.connect( + [&](const auto &data) { auto chan = this->twitch->getChannelOrEmptyByID(data.channelID); postToThread([chan, data] { @@ -1110,14 +1160,12 @@ void Application::initBttvLiveUpdates() } }); }); - bttvLiveUpdates->start(); + this->bttvLiveUpdates->start(); } void Application::initSeventvEventAPI() { - auto &seventvEventAPI = this->twitch->getSeventvEventAPI(); - - if (!seventvEventAPI) + if (!this->seventvEventAPI) { qCDebug(chatterinoSeventvEventAPI) << "Skipping initialization as the EventAPI is disabled"; @@ -1126,8 +1174,8 @@ void Application::initSeventvEventAPI() // We can safely ignore these signal connections since the twitch object will always // be destroyed before the Application - std::ignore = - seventvEventAPI->signals_.emoteAdded.connect([&](const auto &data) { + std::ignore = this->seventvEventAPI->signals_.emoteAdded.connect( + [&](const auto &data) { postToThread([this, data] { this->twitch->forEachSeventvEmoteSet( data.emoteSetID, [data](TwitchChannel &chan) { @@ -1135,8 +1183,8 @@ void Application::initSeventvEventAPI() }); }); }); - std::ignore = - seventvEventAPI->signals_.emoteUpdated.connect([&](const auto &data) { + std::ignore = this->seventvEventAPI->signals_.emoteUpdated.connect( + [&](const auto &data) { postToThread([this, data] { this->twitch->forEachSeventvEmoteSet( data.emoteSetID, [data](TwitchChannel &chan) { @@ -1144,8 +1192,8 @@ void Application::initSeventvEventAPI() }); }); }); - std::ignore = - seventvEventAPI->signals_.emoteRemoved.connect([&](const auto &data) { + std::ignore = this->seventvEventAPI->signals_.emoteRemoved.connect( + [&](const auto &data) { postToThread([this, data] { this->twitch->forEachSeventvEmoteSet( data.emoteSetID, [data](TwitchChannel &chan) { @@ -1153,15 +1201,15 @@ void Application::initSeventvEventAPI() }); }); }); - std::ignore = - seventvEventAPI->signals_.userUpdated.connect([&](const auto &data) { + std::ignore = this->seventvEventAPI->signals_.userUpdated.connect( + [&](const auto &data) { this->twitch->forEachSeventvUser(data.userID, [data](TwitchChannel &chan) { chan.updateSeventvUser(data); }); }); - seventvEventAPI->start(); + this->seventvEventAPI->start(); } IApplication *getApp() diff --git a/src/Application.hpp b/src/Application.hpp index 59ca9b1a3..ff9863851 100644 --- a/src/Application.hpp +++ b/src/Application.hpp @@ -50,8 +50,10 @@ class ImageUploader; class SeventvAPI; class CrashHandler; class BttvEmotes; +class BttvLiveUpdates; class FfzEmotes; class SeventvEmotes; +class SeventvEventAPI; class ILinkResolver; class IStreamerMode; class IAbstractIrcServer; @@ -97,8 +99,10 @@ public: #endif virtual Updates &getUpdates() = 0; virtual BttvEmotes *getBttvEmotes() = 0; + virtual BttvLiveUpdates *getBttvLiveUpdates() = 0; virtual FfzEmotes *getFfzEmotes() = 0; virtual SeventvEmotes *getSeventvEmotes() = 0; + virtual SeventvEventAPI *getSeventvEventAPI() = 0; virtual ILinkResolver *getLinkResolver() = 0; virtual IStreamerMode *getStreamerMode() = 0; }; @@ -165,8 +169,10 @@ private: std::unique_ptr twitchBadges; std::unique_ptr chatterinoBadges; std::unique_ptr bttvEmotes; + std::unique_ptr bttvLiveUpdates; std::unique_ptr ffzEmotes; std::unique_ptr seventvEmotes; + std::unique_ptr seventvEventAPI; const std::unique_ptr logging; std::unique_ptr linkResolver; std::unique_ptr streamerMode; @@ -218,8 +224,10 @@ public: } BttvEmotes *getBttvEmotes() override; + BttvLiveUpdates *getBttvLiveUpdates() override; FfzEmotes *getFfzEmotes() override; SeventvEmotes *getSeventvEmotes() override; + SeventvEventAPI *getSeventvEventAPI() override; ILinkResolver *getLinkResolver() override; IStreamerMode *getStreamerMode() override; diff --git a/src/RunGui.cpp b/src/RunGui.cpp index 06e9a7b94..52094a21c 100644 --- a/src/RunGui.cpp +++ b/src/RunGui.cpp @@ -297,4 +297,5 @@ void runGui(QApplication &a, const Paths &paths, Settings &settings, _exit(0); } + } // namespace chatterino diff --git a/src/providers/twitch/TwitchChannel.cpp b/src/providers/twitch/TwitchChannel.cpp index cfb046a4d..13ee42335 100644 --- a/src/providers/twitch/TwitchChannel.cpp +++ b/src/providers/twitch/TwitchChannel.cpp @@ -146,15 +146,14 @@ TwitchChannel::~TwitchChannel() getApp()->getTwitch()->dropSeventvChannel(this->seventvUserID_, this->seventvEmoteSetID_); - if (getApp()->getTwitch()->getBTTVLiveUpdates()) + if (getApp()->getBttvLiveUpdates()) { - getApp()->getTwitch()->getBTTVLiveUpdates()->partChannel( - this->roomId()); + getApp()->getBttvLiveUpdates()->partChannel(this->roomId()); } - if (getApp()->getTwitch()->getSeventvEventAPI()) + if (getApp()->getSeventvEventAPI()) { - getApp()->getTwitch()->getSeventvEventAPI()->unsubscribeTwitchChannel( + getApp()->getSeventvEventAPI()->unsubscribeTwitchChannel( this->roomId()); } } @@ -854,7 +853,7 @@ const QString &TwitchChannel::seventvEmoteSetID() const void TwitchChannel::joinBttvChannel() const { - if (getApp()->getTwitch()->getBTTVLiveUpdates()) + if (getApp()->getBttvLiveUpdates()) { const auto currentAccount = getApp()->getAccounts()->twitch.getCurrent(); @@ -863,8 +862,7 @@ void TwitchChannel::joinBttvChannel() const { userName = currentAccount->getUserName(); } - getApp()->getTwitch()->getBTTVLiveUpdates()->joinChannel(this->roomId(), - userName); + getApp()->getBttvLiveUpdates()->joinChannel(this->roomId(), userName); } } @@ -1012,9 +1010,9 @@ void TwitchChannel::updateSeventvData(const QString &newUserID, this->seventvUserID_ = newUserID; this->seventvEmoteSetID_ = newEmoteSetID; runInGuiThread([this, oldUserID, oldEmoteSetID]() { - if (getApp()->getTwitch()->getSeventvEventAPI()) + if (getApp()->getSeventvEventAPI()) { - getApp()->getTwitch()->getSeventvEventAPI()->subscribeUser( + getApp()->getSeventvEventAPI()->subscribeUser( this->seventvUserID_, this->seventvEmoteSetID_); if (oldUserID || oldEmoteSetID) @@ -1811,10 +1809,9 @@ void TwitchChannel::updateSevenTVActivity() void TwitchChannel::listenSevenTVCosmetics() const { - if (getApp()->getTwitch()->getSeventvEventAPI()) + if (getApp()->getSeventvEventAPI()) { - getApp()->getTwitch()->getSeventvEventAPI()->subscribeTwitchChannel( - this->roomId()); + getApp()->getSeventvEventAPI()->subscribeTwitchChannel(this->roomId()); } } diff --git a/src/providers/twitch/TwitchIrcServer.cpp b/src/providers/twitch/TwitchIrcServer.cpp index dc12d562b..0fdc5bf1a 100644 --- a/src/providers/twitch/TwitchIrcServer.cpp +++ b/src/providers/twitch/TwitchIrcServer.cpp @@ -33,9 +33,6 @@ namespace { using namespace chatterino; -const QString BTTV_LIVE_UPDATES_URL = "wss://sockets.betterttv.net/ws"; -const QString SEVENTV_EVENTAPI_URL = "wss://events.7tv.io/v3"; - void sendHelixMessage(const std::shared_ptr &channel, const QString &message, const QString &replyParentId = {}) { @@ -145,20 +142,6 @@ TwitchIrcServer::TwitchIrcServer() { this->initializeIrc(); - if (getSettings()->enableBTTVLiveUpdates && - getSettings()->enableBTTVChannelEmotes) - { - this->bttvLiveUpdates = - std::make_unique(BTTV_LIVE_UPDATES_URL); - } - - if (getSettings()->enableSevenTVEventAPI && - getSettings()->enableSevenTVChannelEmotes) - { - this->seventvEventAPI = - std::make_unique(SEVENTV_EVENTAPI_URL); - } - // getSettings()->twitchSeperateWriteConnection.connect([this](auto, auto) { // this->connect(); }, // this->signalHolder_, @@ -638,16 +621,6 @@ void TwitchIrcServer::onReplySendRequested( sent = true; } -std::unique_ptr &TwitchIrcServer::getBTTVLiveUpdates() -{ - return this->bttvLiveUpdates; -} - -std::unique_ptr &TwitchIrcServer::getSeventvEventAPI() -{ - return this->seventvEventAPI; -} - const IndirectChannel &TwitchIrcServer::getWatchingChannel() const { return this->watchingChannel; @@ -759,7 +732,7 @@ void TwitchIrcServer::forEachSeventvUser( void TwitchIrcServer::dropSeventvChannel(const QString &userID, const QString &emoteSetID) { - if (!this->seventvEventAPI) + if (!getApp()->getSeventvEventAPI()) { return; } @@ -798,11 +771,11 @@ void TwitchIrcServer::dropSeventvChannel(const QString &userID, if (!foundUser) { - this->seventvEventAPI->unsubscribeUser(userID); + getApp()->getSeventvEventAPI()->unsubscribeUser(userID); } if (!foundSet) { - this->seventvEventAPI->unsubscribeEmoteSet(emoteSetID); + getApp()->getSeventvEventAPI()->unsubscribeEmoteSet(emoteSetID); } } diff --git a/src/providers/twitch/TwitchIrcServer.hpp b/src/providers/twitch/TwitchIrcServer.hpp index 1f3dbe730..85c0a5677 100644 --- a/src/providers/twitch/TwitchIrcServer.hpp +++ b/src/providers/twitch/TwitchIrcServer.hpp @@ -15,8 +15,6 @@ namespace chatterino { class Settings; class Paths; class TwitchChannel; -class BttvLiveUpdates; -class SeventvEventAPI; class BttvEmotes; class FfzEmotes; class SeventvEmotes; @@ -35,9 +33,6 @@ public: virtual void dropSeventvChannel(const QString &userID, const QString &emoteSetID) = 0; - virtual std::unique_ptr &getBTTVLiveUpdates() = 0; - virtual std::unique_ptr &getSeventvEventAPI() = 0; - virtual const IndirectChannel &getWatchingChannel() const = 0; virtual void setWatchingChannel(ChannelPtr newWatchingChannel) = 0; virtual ChannelPtr getWhispersChannel() const = 0; @@ -102,13 +97,7 @@ private: const ChannelPtr automodChannel; IndirectChannel watchingChannel; - std::unique_ptr bttvLiveUpdates; - std::unique_ptr seventvEventAPI; - public: - std::unique_ptr &getBTTVLiveUpdates() override; - std::unique_ptr &getSeventvEventAPI() override; - const IndirectChannel &getWatchingChannel() const override; void setWatchingChannel(ChannelPtr newWatchingChannel) override; ChannelPtr getWhispersChannel() const override; diff --git a/src/singletons/StreamerMode.cpp b/src/singletons/StreamerMode.cpp index 659bfd9ea..eb79be9a1 100644 --- a/src/singletons/StreamerMode.cpp +++ b/src/singletons/StreamerMode.cpp @@ -152,6 +152,11 @@ class StreamerModePrivate { public: StreamerModePrivate(StreamerMode *parent_); + ~StreamerModePrivate(); + StreamerModePrivate(const StreamerModePrivate &) = delete; + StreamerModePrivate(StreamerModePrivate &&) = delete; + StreamerModePrivate &operator=(const StreamerModePrivate &) = delete; + StreamerModePrivate &operator=(StreamerModePrivate &&) = delete; [[nodiscard]] bool isEnabled() const; @@ -219,6 +224,12 @@ StreamerModePrivate::StreamerModePrivate(StreamerMode *parent) this->thread_.start(); } +StreamerModePrivate::~StreamerModePrivate() +{ + this->thread_.quit(); + this->thread_.wait(50); +} + bool StreamerModePrivate::isEnabled() const { this->timeouts_.store(SKIPPED_TIMEOUTS, std::memory_order::relaxed); diff --git a/tests/src/Commands.cpp b/tests/src/Commands.cpp index 2a4d259aa..420f71fdf 100644 --- a/tests/src/Commands.cpp +++ b/tests/src/Commands.cpp @@ -3,7 +3,7 @@ #include "controllers/commands/CommandContext.hpp" #include "controllers/commands/CommandController.hpp" #include "controllers/commands/common/ChannelAction.hpp" -#include "mocks/EmptyApplication.hpp" +#include "mocks/BaseApplication.hpp" #include "mocks/Helix.hpp" #include "mocks/Logging.hpp" #include "mocks/TwitchIrcServer.hpp" @@ -22,12 +22,11 @@ using ::testing::StrictMock; namespace { -class MockApplication : mock::EmptyApplication +class MockApplication : public mock::BaseApplication { public: MockApplication() - : settings(this->settingsDir.filePath("settings.json")) - , commands(this->paths_) + : commands(this->paths_) { } @@ -56,7 +55,6 @@ public: return &this->chatLogger; } - Settings settings; AccountController accounts; CommandController commands; mock::MockTwitchIrcServer twitch;