diff --git a/src/providers/twitch/ircmessagehandler.cpp b/src/providers/twitch/ircmessagehandler.cpp index 6fbb95b4c..e6c1802ca 100644 --- a/src/providers/twitch/ircmessagehandler.cpp +++ b/src/providers/twitch/ircmessagehandler.cpp @@ -246,6 +246,26 @@ void IrcMessageHandler::handleWriteConnectionNoticeMessage(Communi::IrcNoticeMes this->handleNoticeMessage(message); } +void IrcMessageHandler::handleJoinMessage(Communi::IrcMessage *message) +{ + auto app = getApp(); + auto channel = app->twitch.server->getChannelOrEmpty(message->parameter(0).remove(0, 1)); + + if (TwitchChannel *twitchChannel = dynamic_cast(channel.get())) { + twitchChannel->addJoinedUser(message->nick()); + } +} + +void IrcMessageHandler::handlePartMessage(Communi::IrcMessage *message) +{ + auto app = getApp(); + auto channel = app->twitch.server->getChannelOrEmpty(message->parameter(0).remove(0, 1)); + + if (TwitchChannel *twitchChannel = dynamic_cast(channel.get())) { + twitchChannel->addPartedUser(message->nick()); + } +} + } // namespace twitch } // namespace providers } // namespace chatterino diff --git a/src/providers/twitch/ircmessagehandler.hpp b/src/providers/twitch/ircmessagehandler.hpp index d79296a9d..d0c242860 100644 --- a/src/providers/twitch/ircmessagehandler.hpp +++ b/src/providers/twitch/ircmessagehandler.hpp @@ -21,6 +21,9 @@ public: void handleModeMessage(Communi::IrcMessage *message); void handleNoticeMessage(Communi::IrcNoticeMessage *message); void handleWriteConnectionNoticeMessage(Communi::IrcNoticeMessage *message); + + void handleJoinMessage(Communi::IrcMessage *message); + void handlePartMessage(Communi::IrcMessage *message); }; } // namespace twitch diff --git a/src/providers/twitch/twitchchannel.cpp b/src/providers/twitch/twitchchannel.cpp index 0243bae4a..c66508a87 100644 --- a/src/providers/twitch/twitchchannel.cpp +++ b/src/providers/twitch/twitchchannel.cpp @@ -213,6 +213,58 @@ void TwitchChannel::addRecentChatter(const std::shared_ptr &m this->completionModel.addUser(message->displayName); } +void TwitchChannel::addJoinedUser(const QString &user) +{ + auto *app = getApp(); + if (user == app->accounts->Twitch.getCurrent()->getUserName() || + !app->settings->showJoins.getValue()) { + return; + } + + std::lock_guard guard(this->joinedUserMutex); + + joinedUsers << user; + + if (!this->joinedUsersMergeQueued) { + this->joinedUsersMergeQueued = true; + + QTimer::singleShot(500, &this->object, [this] { + std::lock_guard guard(this->joinedUserMutex); + + this->addMessage(messages::Message::createSystemMessage("Users joined: " + + this->joinedUsers.join(", "))); + this->joinedUsersMergeQueued = false; + }); + } +} + +void TwitchChannel::addPartedUser(const QString &user) +{ + auto *app = getApp(); + + if (user == app->accounts->Twitch.getCurrent()->getUserName() || + !app->settings->showJoins.getValue()) { + return; + } + + std::lock_guard guard(this->partedUserMutex); + + partedUsers << user; + + if (!this->partedUsersMergeQueued) { + this->partedUsersMergeQueued = true; + + QTimer::singleShot(500, &this->object, [this] { + std::lock_guard guard(this->partedUserMutex); + + this->addMessage(messages::Message::createSystemMessage("Users parted: " + + this->partedUsers.join(", "))); + + this->partedUsersMergeQueued = false; + }); + } +} + TwitchChannel::RoomModes TwitchChannel::getRoomModes() { std::lock_guard lock(this->roomModeMutex); diff --git a/src/providers/twitch/twitchchannel.hpp b/src/providers/twitch/twitchchannel.hpp index 52a3e1729..60fe88336 100644 --- a/src/providers/twitch/twitchchannel.hpp +++ b/src/providers/twitch/twitchchannel.hpp @@ -63,6 +63,8 @@ public: bool hasModRights(); void addRecentChatter(const std::shared_ptr &message) final; + void addJoinedUser(const QString &user); + void addPartedUser(const QString &user); const std::shared_ptr bttvChannelEmotes; const std::shared_ptr ffzChannelEmotes; @@ -113,6 +115,14 @@ private: RoomModes roomModes; std::mutex roomModeMutex; + QObject object; + std::mutex joinedUserMutex; + QStringList joinedUsers; + bool joinedUsersMergeQueued = false; + std::mutex partedUserMutex; + QStringList partedUsers; + bool partedUsersMergeQueued = false; + Communi::IrcConnection *readConnection; friend class TwitchServer; diff --git a/src/providers/twitch/twitchserver.cpp b/src/providers/twitch/twitchserver.cpp index 9b10df7b7..a3db8f148 100644 --- a/src/providers/twitch/twitchserver.cpp +++ b/src/providers/twitch/twitchserver.cpp @@ -114,21 +114,26 @@ void TwitchServer::messageReceived(IrcMessage *message) const QString &command = message->command(); + auto &handler = IrcMessageHandler::getInstance(); + if (command == "ROOMSTATE") { - IrcMessageHandler::getInstance().handleRoomStateMessage(message); + handler.handleRoomStateMessage(message); } else if (command == "CLEARCHAT") { - IrcMessageHandler::getInstance().handleClearChatMessage(message); + handler.handleClearChatMessage(message); } else if (command == "USERSTATE") { - IrcMessageHandler::getInstance().handleUserStateMessage(message); + handler.handleUserStateMessage(message); } else if (command == "WHISPER") { - IrcMessageHandler::getInstance().handleWhisperMessage(message); + handler.handleWhisperMessage(message); } else if (command == "USERNOTICE") { - IrcMessageHandler::getInstance().handleUserNoticeMessage(message); + handler.handleUserNoticeMessage(message); } else if (command == "MODE") { - IrcMessageHandler::getInstance().handleModeMessage(message); + handler.handleModeMessage(message); } else if (command == "NOTICE") { - IrcMessageHandler::getInstance().handleNoticeMessage( - static_cast(message)); + handler.handleNoticeMessage(static_cast(message)); + } else if (command == "JOIN") { + handler.handleJoinMessage(message); + } else if (command == "PART") { + handler.handlePartMessage(message); } } diff --git a/src/singletons/settingsmanager.hpp b/src/singletons/settingsmanager.hpp index dcaad8529..ec3231534 100644 --- a/src/singletons/settingsmanager.hpp +++ b/src/singletons/settingsmanager.hpp @@ -55,6 +55,8 @@ public: /// Behaviour BoolSetting allowDuplicateMessages = {"/behaviour/allowDuplicateMessages", true}; BoolSetting mentionUsersWithAt = {"/behaviour/mentionUsersWithAt", false}; + BoolSetting showJoins = {"/behaviour/showJoins", false}; + BoolSetting showParts = {"/behaviour/showParts", false}; FloatSetting mouseScrollMultiplier = {"/behaviour/mouseScrollMultiplier", 1.0}; // Auto-completion diff --git a/src/widgets/settingspages/behaviourpage.cpp b/src/widgets/settingspages/behaviourpage.cpp index 68ea46ef4..94d0bc371 100644 --- a/src/widgets/settingspages/behaviourpage.cpp +++ b/src/widgets/settingspages/behaviourpage.cpp @@ -34,6 +34,10 @@ BehaviourPage::BehaviourPage() { form->addRow("Window:", this->createCheckBox(WINDOW_TOPMOST, app->settings->windowTopMost)); form->addRow("Messages:", this->createCheckBox(INPUT_EMPTY, app->settings->hideEmptyInput)); + form->addRow("", this->createCheckBox("Show which users joined the channel", + app->settings->showJoins)); + form->addRow("", this->createCheckBox("Show which users parted the channel", + app->settings->showParts)); form->addRow("Pause chat:", this->createCheckBox(PAUSE_HOVERING, app->settings->pauseChatHover));