#pragma once #include #include "common/Channel.hpp" #include "common/Common.hpp" #include "common/MutexValue.hpp" #include "common/UniqueAccess.hpp" #include "messages/Emote.hpp" #include "singletons/Emotes.hpp" #include "util/ConcurrentMap.hpp" #include #include #include namespace chatterino { class TwitchServer; class TwitchChannel final : public Channel, pajlada::Signals::SignalHolder { public: struct StreamStatus { bool live = false; bool rerun = false; unsigned viewerCount = 0; QString title; QString game; QString uptime; QString streamType; }; struct UserState { bool mod; bool broadcaster; }; struct RoomModes { bool submode = false; bool r9k = false; bool emoteOnly = false; // int folowerOnly = 0; int slowMode = 0; QString broadcasterLang; }; void refreshChannelEmotes(); // Channel methods virtual bool isEmpty() const override; virtual bool canSendMessage() const override; virtual void sendMessage(const QString &message) override; // Auto completion void addRecentChatter(const MessagePtr &message) final; void addJoinedUser(const QString &user); void addPartedUser(const QString &user); // Twitch data bool isLive() const; virtual bool isMod() const override; void setMod(bool value); virtual bool isBroadcaster() const override; QString getRoomId() const; void setRoomId(const QString &id); AccessGuard accessRoomModes() const; void setRoomModes(const RoomModes &roomModes_); AccessGuard accessStreamStatus() const; boost::optional getBttvEmote(const EmoteName &name) const; boost::optional getFfzEmote(const EmoteName &name) const; AccessGuard accessBttvEmotes() const; AccessGuard accessFfzEmotes() const; const QString &getSubscriptionUrl(); const QString &getChannelUrl(); const QString &getPopoutPlayerUrl(); boost::optional getTwitchBadge(const QString &set, const QString &version) const; // Signals pajlada::Signals::NoArgSignal roomIdChanged; pajlada::Signals::NoArgSignal liveStatusChanged; pajlada::Signals::NoArgSignal userStateChanged; pajlada::Signals::NoArgSignal roomModesChanged; private: struct NameOptions { QString displayName; QString localizedName; }; struct CheerEmote { // a Cheermote indicates one tier QColor color; int minBits; EmotePtr animatedEmote; EmotePtr staticEmote; }; struct CheerEmoteSet { QRegularExpression regex; std::vector cheerEmotes; }; explicit TwitchChannel(const QString &channelName); // Methods void refreshLiveStatus(); Outcome parseLiveStatus(const rapidjson::Document &document); void refreshPubsub(); void refreshViewerList(); Outcome parseViewerList(const QJsonObject &jsonRoot); void loadRecentMessages(); void setLive(bool newLiveStatus); void loadBadges(); void loadCheerEmotes(); // Twitch data UniqueAccess streamStatus_; UniqueAccess userState_; UniqueAccess roomModes_; UniqueAccess bttvEmotes_; UniqueAccess ffzEmotes_; const QString subscriptionUrl_; const QString channelUrl_; const QString popoutPlayerUrl_; bool mod_ = false; MutexValue roomID_; UniqueAccess joinedUsers_; bool joinedUsersMergeQueued_ = false; UniqueAccess partedUsers_; bool partedUsersMergeQueued_ = false; // "subscribers": { "0": ... "3": ... "6": ... UniqueAccess>> badgeSets_; UniqueAccess> cheerEmoteSets_; // -- QByteArray messageSuffix_; QString lastSentMessage_; QObject lifetimeGuard_; QTimer liveStatusTimer_; QTimer chattersListTimer_; friend class TwitchServer; }; } // namespace chatterino