From 13475332fb22fc1e8001f212dbf7e512007698a0 Mon Sep 17 00:00:00 2001 From: Rasmus Karlsson Date: Sat, 13 Apr 2019 15:26:47 +0200 Subject: [PATCH] Adds VIP rate limit support Closes #875 --- src/common/Channel.cpp | 5 ++ src/common/Channel.hpp | 1 + src/providers/twitch/IrcMessageHandler.cpp | 59 ++++++++++++++++------ src/providers/twitch/TwitchChannel.cpp | 37 +++++++++++++- src/providers/twitch/TwitchChannel.hpp | 7 +++ src/providers/twitch/TwitchServer.cpp | 9 ++-- 6 files changed, 98 insertions(+), 20 deletions(-) diff --git a/src/common/Channel.cpp b/src/common/Channel.cpp index 8d247cf2f..570ea64f1 100644 --- a/src/common/Channel.cpp +++ b/src/common/Channel.cpp @@ -239,6 +239,11 @@ bool Channel::hasModRights() const return this->isMod() || this->isBroadcaster(); } +bool Channel::hasHighRateLimit() const +{ + return this->isMod() || this->isBroadcaster(); +} + bool Channel::isLive() const { return false; diff --git a/src/common/Channel.hpp b/src/common/Channel.hpp index 9e111aa46..097957569 100644 --- a/src/common/Channel.hpp +++ b/src/common/Channel.hpp @@ -70,6 +70,7 @@ public: virtual bool isMod() const; virtual bool isBroadcaster() const; virtual bool hasModRights() const; + virtual bool hasHighRateLimit() const; virtual bool isLive() const; virtual bool shouldIgnoreHighlights() const; diff --git a/src/providers/twitch/IrcMessageHandler.cpp b/src/providers/twitch/IrcMessageHandler.cpp index 27df7cb8c..c5526d44a 100644 --- a/src/providers/twitch/IrcMessageHandler.cpp +++ b/src/providers/twitch/IrcMessageHandler.cpp @@ -20,6 +20,24 @@ namespace chatterino { +static QMap parseBadges(QString badgesString) +{ + QMap badges; + + for (auto badgeData : badgesString.split(',')) + { + auto parts = badgeData.split('/'); + if (parts.length() != 2) + { + continue; + } + + badges.insert(parts[0], parts[1]); + } + + return badges; +} + IrcMessageHandler &IrcMessageHandler::getInstance() { static IrcMessageHandler instance; @@ -207,24 +225,35 @@ void IrcMessageHandler::handleClearChatMessage(Communi::IrcMessage *message) void IrcMessageHandler::handleUserStateMessage(Communi::IrcMessage *message) { - QVariant _mod = message->tag("mod"); + auto app = getApp(); + QString channelName; + if (!trimChannelName(message->parameter(0), channelName)) + { + return; + } + + auto c = app->twitch.server->getChannelOrEmpty(channelName); + if (c->isEmpty()) + { + return; + } + + QVariant _badges = message->tag("badges"); + if (_badges.isValid()) + { + TwitchChannel *tc = dynamic_cast(c.get()); + if (tc != nullptr) + { + auto parsedBadges = parseBadges(_badges.toString()); + tc->setVIP(parsedBadges.contains("vip")); + tc->setStaff(parsedBadges.contains("staff")); + } + } + + QVariant _mod = message->tag("mod"); if (_mod.isValid()) { - auto app = getApp(); - - QString channelName; - if (!trimChannelName(message->parameter(0), channelName)) - { - return; - } - - auto c = app->twitch.server->getChannelOrEmpty(channelName); - if (c->isEmpty()) - { - return; - } - TwitchChannel *tc = dynamic_cast(c.get()); if (tc != nullptr) { diff --git a/src/providers/twitch/TwitchChannel.cpp b/src/providers/twitch/TwitchChannel.cpp index e1afffd20..9551a476c 100644 --- a/src/providers/twitch/TwitchChannel.cpp +++ b/src/providers/twitch/TwitchChannel.cpp @@ -200,7 +200,7 @@ void TwitchChannel::sendMessage(const QString &message) return; } - if (!this->hasModRights()) + if (!this->hasHighRateLimit()) { if (getSettings()->allowDuplicateMessages) { @@ -226,6 +226,16 @@ bool TwitchChannel::isMod() const return this->mod_; } +bool TwitchChannel::isVIP() const +{ + return this->vip_; +} + +bool TwitchChannel::isStaff() const +{ + return this->staff_; +} + void TwitchChannel::setMod(bool value) { if (this->mod_ != value) @@ -236,6 +246,26 @@ void TwitchChannel::setMod(bool value) } } +void TwitchChannel::setVIP(bool value) +{ + if (this->vip_ != value) + { + this->vip_ = value; + + this->userStateChanged.invoke(); + } +} + +void TwitchChannel::setStaff(bool value) +{ + if (this->staff_ != value) + { + this->staff_ = value; + + this->userStateChanged.invoke(); + } +} + bool TwitchChannel::isBroadcaster() const { auto app = getApp(); @@ -243,6 +273,11 @@ bool TwitchChannel::isBroadcaster() const return this->getName() == app->accounts->twitch.getCurrent()->getUserName(); } +bool TwitchChannel::hasHighRateLimit() const +{ + return this->isMod() || this->isBroadcaster() || this->isVIP(); +} + void TwitchChannel::addRecentChatter(const MessagePtr &message) { this->chatters_.access()->insert(message->displayName); diff --git a/src/providers/twitch/TwitchChannel.hpp b/src/providers/twitch/TwitchChannel.hpp index 0383cd43d..00a6c9513 100644 --- a/src/providers/twitch/TwitchChannel.hpp +++ b/src/providers/twitch/TwitchChannel.hpp @@ -61,7 +61,10 @@ public: virtual bool canSendMessage() const override; virtual void sendMessage(const QString &message) override; virtual bool isMod() const override; + bool isVIP() const; + bool isStaff() const; virtual bool isBroadcaster() const override; + virtual bool hasHighRateLimit() const override; // Data const QString &subscriptionUrl(); @@ -123,6 +126,8 @@ private: void addPartedUser(const QString &user); void setLive(bool newLiveStatus); void setMod(bool value); + void setVIP(bool value); + void setStaff(bool value); void setRoomId(const QString &id); void setRoomModes(const RoomModes &roomModes_); @@ -151,6 +156,8 @@ private: FfzModBadge ffzCustomModBadge_; bool mod_ = false; + bool vip_ = false; + bool staff_ = false; UniqueAccess roomID_; UniqueAccess joinedUsers_; diff --git a/src/providers/twitch/TwitchServer.cpp b/src/providers/twitch/TwitchServer.cpp index b12a46190..349e40357 100644 --- a/src/providers/twitch/TwitchServer.cpp +++ b/src/providers/twitch/TwitchServer.cpp @@ -293,10 +293,11 @@ void TwitchServer::onMessageSendRequested(TwitchChannel *channel, std::lock_guard guard(this->lastMessageMutex_); // std::queue - auto &lastMessage = channel->hasModRights() ? this->lastMessageMod_ - : this->lastMessagePleb_; - size_t maxMessageCount = channel->hasModRights() ? 99 : 19; - auto minMessageOffset = (channel->hasModRights() ? 100ms : 1100ms); + auto &lastMessage = channel->hasHighRateLimit() + ? this->lastMessageMod_ + : this->lastMessagePleb_; + size_t maxMessageCount = channel->hasHighRateLimit() ? 99 : 19; + auto minMessageOffset = (channel->hasHighRateLimit() ? 100ms : 1100ms); auto now = std::chrono::steady_clock::now();