1 #pragma once 2 3 #include "common/Aliases.hpp" 4 #include "common/Atomic.hpp" 5 #include "common/Channel.hpp" 6 #include "common/ChannelChatters.hpp" 7 #include "common/ChatterSet.hpp" 8 #include "common/Outcome.hpp" 9 #include "common/UniqueAccess.hpp" 10 #include "providers/twitch/ChannelPointReward.hpp" 11 #include "providers/twitch/TwitchEmotes.hpp" 12 #include "providers/twitch/api/Helix.hpp" 13 #include "util/QStringHash.hpp" 14 15 #include <QColor> 16 #include <QElapsedTimer> 17 #include <QRegularExpression> 18 #include <boost/optional.hpp> 19 #include <pajlada/signals/signalholder.hpp> 20 21 #include <mutex> 22 #include <unordered_map> 23 24 namespace chatterino { 25 26 enum class HighlightState; 27 28 struct Emote; 29 using EmotePtr = std::shared_ptr<const Emote>; 30 class EmoteMap; 31 32 class TwitchBadges; 33 class FfzEmotes; 34 class BttvEmotes; 35 36 class TwitchIrcServer; 37 38 class TwitchChannel : public Channel, 39 public ChannelChatters, 40 pajlada::Signals::SignalHolder 41 { 42 public: 43 struct StreamStatus { 44 bool live = false; 45 bool rerun = false; 46 unsigned viewerCount = 0; 47 QString title; 48 QString game; 49 QString gameId; 50 QString uptime; 51 QString streamType; 52 }; 53 54 struct RoomModes { 55 bool submode = false; 56 bool r9k = false; 57 bool emoteOnly = false; 58 int followerOnly = -1; 59 int slowMode = 0; 60 }; 61 62 void initialize(); 63 64 // Channel methods 65 virtual bool isEmpty() const override; 66 virtual bool canSendMessage() const override; 67 virtual void sendMessage(const QString &message) override; 68 virtual bool isMod() const override; 69 bool isVip() const; 70 bool isStaff() const; 71 virtual bool isBroadcaster() const override; 72 virtual bool hasHighRateLimit() const override; 73 virtual bool canReconnect() const override; 74 virtual void reconnect() override; 75 void refreshTitle(); 76 void createClip(); 77 78 // Data 79 const QString &subscriptionUrl(); 80 const QString &channelUrl(); 81 const QString &popoutPlayerUrl(); 82 int chatterCount(); 83 virtual bool isLive() const override; 84 QString roomId() const; 85 SharedAccessGuard<const RoomModes> accessRoomModes() const; 86 SharedAccessGuard<const StreamStatus> accessStreamStatus() const; 87 88 // Emotes 89 boost::optional<EmotePtr> bttvEmote(const EmoteName &name) const; 90 boost::optional<EmotePtr> ffzEmote(const EmoteName &name) const; 91 std::shared_ptr<const EmoteMap> bttvEmotes() const; 92 std::shared_ptr<const EmoteMap> ffzEmotes() const; 93 94 virtual void refreshBTTVChannelEmotes(bool manualRefresh); 95 virtual void refreshFFZChannelEmotes(bool manualRefresh); 96 97 // Badges 98 boost::optional<EmotePtr> ffzCustomModBadge() const; 99 boost::optional<EmotePtr> ffzCustomVipBadge() const; 100 boost::optional<EmotePtr> twitchBadge(const QString &set, 101 const QString &version) const; 102 103 // Cheers 104 boost::optional<CheerEmote> cheerEmote(const QString &string); 105 106 // Signals 107 pajlada::Signals::NoArgSignal roomIdChanged; 108 pajlada::Signals::NoArgSignal userStateChanged; 109 pajlada::Signals::NoArgSignal liveStatusChanged; 110 pajlada::Signals::NoArgSignal roomModesChanged; 111 112 // Channel point rewards 113 pajlada::Signals::SelfDisconnectingSignal<ChannelPointReward> 114 channelPointRewardAdded; 115 void addChannelPointReward(const ChannelPointReward &reward); 116 bool isChannelPointRewardKnown(const QString &rewardId); 117 boost::optional<ChannelPointReward> channelPointReward( 118 const QString &rewardId) const; 119 120 private: 121 struct NameOptions { 122 QString displayName; 123 QString localizedName; 124 } nameOptions; 125 126 protected: 127 explicit TwitchChannel(const QString &channelName); 128 129 private: 130 // Methods 131 void refreshLiveStatus(); 132 void parseLiveStatus(bool live, const HelixStream &stream); 133 void refreshPubsub(); 134 void refreshChatters(); 135 void refreshBadges(); 136 void refreshCheerEmotes(); 137 void loadRecentMessages(); 138 void fetchDisplayName(); 139 140 void setLive(bool newLiveStatus); 141 void setMod(bool value); 142 void setVIP(bool value); 143 void setStaff(bool value); 144 void setRoomId(const QString &id); 145 void setRoomModes(const RoomModes &roomModes_); 146 void setDisplayName(const QString &name); 147 void setLocalizedName(const QString &name); 148 149 const QString &getDisplayName() const override; 150 const QString &getLocalizedName() const override; 151 152 // Data 153 const QString subscriptionUrl_; 154 const QString channelUrl_; 155 const QString popoutPlayerUrl_; 156 int chatterCount_; 157 UniqueAccess<StreamStatus> streamStatus_; 158 UniqueAccess<RoomModes> roomModes_; 159 160 protected: 161 Atomic<std::shared_ptr<const EmoteMap>> bttvEmotes_; 162 Atomic<std::shared_ptr<const EmoteMap>> ffzEmotes_; 163 Atomic<boost::optional<EmotePtr>> ffzCustomModBadge_; 164 Atomic<boost::optional<EmotePtr>> ffzCustomVipBadge_; 165 166 private: 167 // Badges 168 UniqueAccess<std::map<QString, std::map<QString, EmotePtr>>> 169 badgeSets_; // "subscribers": { "0": ... "3": ... "6": ... 170 UniqueAccess<std::vector<CheerEmoteSet>> cheerEmoteSets_; 171 UniqueAccess<std::map<QString, ChannelPointReward>> channelPointRewards_; 172 173 bool mod_ = false; 174 bool vip_ = false; 175 bool staff_ = false; 176 UniqueAccess<QString> roomID_; 177 178 // -- 179 QString lastSentMessage_; 180 QObject lifetimeGuard_; 181 QTimer liveStatusTimer_; 182 QTimer chattersListTimer_; 183 QElapsedTimer titleRefreshedTimer_; 184 QElapsedTimer clipCreationTimer_; 185 bool isClipCreationInProgress{false}; 186 187 friend class TwitchIrcServer; 188 friend class TwitchMessageBuilder; 189 friend class IrcMessageHandler; 190 }; 191 192 } // namespace chatterino 193