#pragma once #include "common/Aliases.hpp" #include "common/Atomic.hpp" #include "common/Channel.hpp" #include "common/Outcome.hpp" #include "common/UniqueAccess.hpp" #include "common/UsernameSet.hpp" #include "providers/ffz/FfzModBadge.hpp" #include "providers/twitch/TwitchEmotes.hpp" #include #include #include #include #include #include #include #include namespace chatterino { enum class HighlightState; struct Emote; using EmotePtr = std::shared_ptr; class EmoteMap; class TwitchBadges; class FfzEmotes; class BttvEmotes; class TwitchServer; class TwitchChannel : 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 RoomModes { bool submode = false; bool r9k = false; bool emoteOnly = false; // int folowerOnly = 0; int slowMode = 0; QString broadcasterLang; }; void initialize(); // Channel methods virtual bool isEmpty() const override; 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(); const QString &channelUrl(); const QString &popoutPlayerUrl(); virtual bool isLive() const override; QString roomId() const; AccessGuard accessRoomModes() const; AccessGuard accessStreamStatus() const; AccessGuard accessChatters() const; // Emotes const TwitchBadges &globalTwitchBadges() const; const BttvEmotes &globalBttv() const; const FfzEmotes &globalFfz() const; boost::optional bttvEmote(const EmoteName &name) const; boost::optional ffzEmote(const EmoteName &name) const; std::shared_ptr bttvEmotes() const; std::shared_ptr ffzEmotes() const; virtual void refreshChannelEmotes(); // Badges boost::optional ffzCustomModBadge() const; boost::optional twitchBadge(const QString &set, const QString &version) const; // Signals pajlada::Signals::NoArgSignal roomIdChanged; pajlada::Signals::NoArgSignal userStateChanged; pajlada::Signals::NoArgSignal liveStatusChanged; pajlada::Signals::NoArgSignal roomModesChanged; protected: void addRecentChatter(const MessagePtr &message) override; private: struct NameOptions { QString displayName; QString localizedName; }; protected: explicit TwitchChannel(const QString &channelName, TwitchBadges &globalTwitchBadges, BttvEmotes &globalBttv, FfzEmotes &globalFfz); private: // Methods void refreshLiveStatus(); Outcome parseLiveStatus(const rapidjson::Document &document); void refreshPubsub(); void refreshChatters(); void refreshBadges(); void refreshCheerEmotes(); void loadRecentMessages(); void addJoinedUser(const QString &user); 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_); // Data const QString subscriptionUrl_; const QString channelUrl_; const QString popoutPlayerUrl_; UniqueAccess streamStatus_; UniqueAccess roomModes_; UniqueAccess chatters_; // maps 2 char prefix to set of names // Emotes TwitchBadges &globalTwitchBadges_; protected: BttvEmotes &globalBttv_; FfzEmotes &globalFfz_; Atomic> bttvEmotes_; Atomic> ffzEmotes_; private: // Badges UniqueAccess>> badgeSets_; // "subscribers": { "0": ... "3": ... "6": ... UniqueAccess> cheerEmoteSets_; FfzModBadge ffzCustomModBadge_; bool mod_ = false; bool vip_ = false; bool staff_ = false; UniqueAccess roomID_; UniqueAccess joinedUsers_; bool joinedUsersMergeQueued_ = false; UniqueAccess partedUsers_; bool partedUsersMergeQueued_ = false; // -- QString lastSentMessage_; QObject lifetimeGuard_; QTimer liveStatusTimer_; QTimer chattersListTimer_; friend class TwitchServer; friend class TwitchMessageBuilder; friend class IrcMessageHandler; }; } // namespace chatterino