diff --git a/plugins/twitch/chat-connection.cpp b/plugins/twitch/chat-connection.cpp index ac0fb2a4..2416b25a 100644 --- a/plugins/twitch/chat-connection.cpp +++ b/plugins/twitch/chat-connection.cpp @@ -5,6 +5,8 @@ #include #include +#undef DispatchMessage + namespace advss { using websocketpp::lib::placeholders::_1; @@ -354,43 +356,11 @@ TwitchChatConnection::TwitchChatConnection(const TwitchToken &token, asio::ssl::context::sslv23_client); }); _url = defaultURL.data(); - RegisterInstance(); } TwitchChatConnection::~TwitchChatConnection() { Disconnect(); - UnregisterInstance(); -} - -static bool setupChatMessageClear() -{ - AddIntervalResetStep(&TwitchChatConnection::ClearAllMessages); - return true; -} - -bool TwitchChatConnection::_setupDone = setupChatMessageClear(); - -void TwitchChatConnection::ClearMessages() -{ - std::lock_guard lock(_messageMtx); - _messages.clear(); -} - -std::mutex TwitchChatConnection::_instancesMtx; -std::vector TwitchChatConnection::_instances; - -void TwitchChatConnection::RegisterInstance() -{ - std::lock_guard lock(_instancesMtx); - _instances.emplace_back(this); -} - -void TwitchChatConnection::UnregisterInstance() -{ - std::lock_guard lock(_instancesMtx); - auto it = std::remove(_instances.begin(), _instances.end(), this); - _instances.erase(it, _instances.end()); } std::shared_ptr @@ -414,17 +384,10 @@ TwitchChatConnection::GetChatConnection(const TwitchToken &token_, auto connection = std::shared_ptr( new TwitchChatConnection(token_, channel)); _chatMap[key] = connection; + connection->ConnectToChat(); return connection; } -void TwitchChatConnection::ClearAllMessages() -{ - std::lock_guard lock(_instancesMtx); - for (const auto &TwitchChatConnection : _instances) { - TwitchChatConnection->ClearMessages(); - } -} - void TwitchChatConnection::ConnectThread() { while (!_disconnect) { @@ -503,55 +466,29 @@ static std::string toLowerCase(const std::string &str) return result; } -std::vector TwitchChatConnection::Messages() +void TwitchChatConnection::ConnectToChat() { if (!_connected) { Connect(); - return {}; + return; } - - if (_joinedChannelName != - "#" + toLowerCase(std::string(_channel.GetName()))) { - // TODO: disconnect previous channel? - JoinChannel(_channel.GetName()); - return {}; - } - - std::lock_guard lock(_messageMtx); - return _messages; } -std::vector TwitchChatConnection::Whispers() +ChatMessageBuffer TwitchChatConnection::RegisterForMessages() { - if (!_connected) { - Connect(); - return {}; - } + ConnectToChat(); + return _messageDispatcher.RegisterClient(); +} - if (_joinedChannelName != - "#" + toLowerCase(std::string(_channel.GetName()))) { - // TODO: disconnect previous channel? - JoinChannel(_channel.GetName()); - return {}; - } - - std::lock_guard lock(_messageMtx); - return _whispers; +ChatMessageBuffer TwitchChatConnection::RegisterForWhispers() +{ + ConnectToChat(); + return _whisperDispatcher.RegisterClient(); } void TwitchChatConnection::SendChatMessage(const std::string &message) { - if (!_connected) { - Connect(); - return; - } - - if (_joinedChannelName != - "#" + toLowerCase(std::string(_channel.GetName()))) { - // TODO: disconnect previous channel? - JoinChannel(_channel.GetName()); - return; - } + ConnectToChat(); Send("PRIVMSG " + _joinedChannelName + " :" + message); } @@ -582,23 +519,20 @@ void TwitchChatConnection::JoinChannel(const std::string &channelName) void TwitchChatConnection::HandleJoin(const IRCMessage &message) { - std::lock_guard lock(_messageMtx); _joinedChannelName = std::get(message.command.parameters); vblog(LOG_INFO, "Twitch chat join was successful!"); } void TwitchChatConnection::HandleNewMessage(const IRCMessage &message) { - std::lock_guard lock(_messageMtx); - _messages.emplace_back(message); + _messageDispatcher.DispatchMessage(message); vblog(LOG_INFO, "Received new chat message %s", message.message.c_str()); } void TwitchChatConnection::HandleWhisper(const IRCMessage &message) { - std::lock_guard lock(_messageMtx); - _whispers.emplace_back(message); + _whisperDispatcher.DispatchMessage(message); vblog(LOG_INFO, "Received new chat whisper message %s", message.message.c_str()); } @@ -662,6 +596,7 @@ void TwitchChatConnection::OnMessage( vblog(LOG_INFO, "Twitch chat connection authenticated!"); _authenticated = true; + JoinChannel(_channel.GetName()); } else if (message.command.command == pingCommand) { Send("PONG " + std::get(message.command.parameters)); diff --git a/plugins/twitch/chat-connection.hpp b/plugins/twitch/chat-connection.hpp index e3e6de30..ed1757e3 100644 --- a/plugins/twitch/chat-connection.hpp +++ b/plugins/twitch/chat-connection.hpp @@ -2,13 +2,13 @@ #include "channel-selection.hpp" #include "token.hpp" -#include -#include -#include #include - -#include +#include +#include +#include +#include #include +#include namespace advss { @@ -38,6 +38,9 @@ struct IRCMessage { std::string message; }; +using ChatMessageBuffer = std::shared_ptr>; +using ChatMessageDispatcher = MessageDispatcher; + class TwitchChatConnection : public QObject { public: ~TwitchChatConnection(); @@ -45,12 +48,10 @@ public: static std::shared_ptr GetChatConnection(const TwitchToken &token, const TwitchChannel &channel); - std::vector Messages(); - std::vector Whispers(); + [[nodiscard]] ChatMessageBuffer RegisterForMessages(); + [[nodiscard]] ChatMessageBuffer RegisterForWhispers(); void SendChatMessage(const std::string &message); - - static void ClearAllMessages(); - void ClearMessages(); + void ConnectToChat(); private: TwitchChatConnection(const TwitchToken &token, @@ -77,9 +78,6 @@ private: void HandleNotice(const IRCMessage &) const; void HandleReconnect(); - void RegisterInstance(); - void UnregisterInstance(); - struct ChatMapKey { std::string channelName; std::string token; @@ -103,12 +101,8 @@ private: std::atomic_bool _disconnect{false}; std::string _url; - std::mutex _messageMtx; - std::vector _messages; - std::vector _whispers; - static std::mutex _instancesMtx; - static std::vector _instances; - static bool _setupDone; + ChatMessageDispatcher _messageDispatcher; + ChatMessageDispatcher _whisperDispatcher; }; } // namespace advss diff --git a/plugins/twitch/macro-condition-twitch.cpp b/plugins/twitch/macro-condition-twitch.cpp index 7ced7276..dc914231 100644 --- a/plugins/twitch/macro-condition-twitch.cpp +++ b/plugins/twitch/macro-condition-twitch.cpp @@ -363,14 +363,18 @@ bool MacroConditionTwitch::CheckChatMessages(TwitchToken &token) if (!_chatConnection) { _chatConnection = TwitchChatConnection::GetChatConnection( token, _channel); + _chatBuffer = _chatConnection->RegisterForMessages(); return false; } - auto messages = _chatConnection->Messages(); - for (const auto &message : messages) { - if (stringMatches(_regexChat, message.message, _chatMessage)) { - SetTempVarValue("chatter", message.source.nick); - SetTempVarValue("chat_message", message.message); + while (!_chatBuffer->Empty()) { + auto message = _chatBuffer->ConsumeMessage(); + if (!message) { + continue; + } + if (stringMatches(_regexChat, message->message, _chatMessage)) { + SetTempVarValue("chatter", message->source.nick); + SetTempVarValue("chat_message", message->message); return true; } } diff --git a/plugins/twitch/macro-condition-twitch.hpp b/plugins/twitch/macro-condition-twitch.hpp index e51cc097..b51a846b 100644 --- a/plugins/twitch/macro-condition-twitch.hpp +++ b/plugins/twitch/macro-condition-twitch.hpp @@ -131,6 +131,7 @@ private: std::future _subscriptionIDFuture; std::string _subscriptionID; + ChatMessageBuffer _chatBuffer; std::shared_ptr _chatConnection; static bool _registered;