#pragma once #include "common/Aliases.hpp" #include "common/Outcome.hpp" #include "messages/MessageThread.hpp" #include "messages/SharedMessageBuilder.hpp" #include "providers/twitch/ChannelPointReward.hpp" #include "providers/twitch/PubSubActions.hpp" #include "providers/twitch/TwitchBadge.hpp" #include "providers/twitch/api/Helix.hpp" #include #include #include namespace chatterino { struct Emote; using EmotePtr = std::shared_ptr; class Channel; class TwitchChannel; struct TwitchEmoteOccurrence { int start; int end; EmotePtr ptr; EmoteName name; bool operator==(const TwitchEmoteOccurrence &other) const { return std::tie(this->start, this->end, this->ptr, this->name) == std::tie(other.start, other.end, other.ptr, other.name); } }; class TwitchMessageBuilder : public SharedMessageBuilder { public: TwitchMessageBuilder() = delete; explicit TwitchMessageBuilder(Channel *_channel, const Communi::IrcPrivateMessage *_ircMessage, const MessageParseArgs &_args); explicit TwitchMessageBuilder(Channel *_channel, const Communi::IrcMessage *_ircMessage, const MessageParseArgs &_args, QString content, bool isAction); TwitchChannel *twitchChannel; [[nodiscard]] bool isIgnored() const override; void triggerHighlights() override; MessagePtr build() override; void setThread(std::shared_ptr thread); void setMessageOffset(int offset); static void appendChannelPointRewardMessage( const ChannelPointReward &reward, MessageBuilder *builder, bool isMod, bool isBroadcaster); // Message in the /live chat for channel going live static void liveMessage(const QString &channelName, MessageBuilder *builder); // Messages in normal chat for channel stuff static void liveSystemMessage(const QString &channelName, MessageBuilder *builder); static void offlineSystemMessage(const QString &channelName, MessageBuilder *builder); static void hostingSystemMessage(const QString &channelName, MessageBuilder *builder, bool hostOn); static void deletionMessage(const MessagePtr originalMessage, MessageBuilder *builder); static void deletionMessage(const DeleteAction &action, MessageBuilder *builder); static void listOfUsersSystemMessage(QString prefix, QStringList users, Channel *channel, MessageBuilder *builder); static void listOfUsersSystemMessage( QString prefix, const std::vector &users, Channel *channel, MessageBuilder *builder); // Shares some common logic from SharedMessageBuilder::parseBadgeTag static std::unordered_map parseBadgeInfoTag( const QVariantMap &tags); static std::vector parseTwitchEmotes( const QVariantMap &tags, const QString &originalMessage, int messageOffset); private: void parseUsernameColor() override; void parseUsername() override; void parseMessageID(); void parseRoomID(); void appendUsername(); void runIgnoreReplaces(std::vector &twitchEmotes); boost::optional getTwitchBadge(const Badge &badge); Outcome tryAppendEmote(const EmoteName &name) override; void addWords(const QStringList &words, const std::vector &twitchEmotes); void addTextOrEmoji(EmotePtr emote) override; void addTextOrEmoji(const QString &value) override; void appendTwitchBadges(); void appendChatterinoBadges(); void appendFfzBadges(); void appendSeventvBadges(); Outcome tryParseCheermote(const QString &string); bool shouldAddModerationElements() const; QString roomID_; bool hasBits_ = false; QString bits; int bitsLeft; bool bitsStacked = false; bool historicalMessage_ = false; std::shared_ptr thread_; /** * Starting offset to be used on index-based operations on `originalMessage_`. * * For example: * originalMessage_ = "there" * messageOffset_ = 4 * (the irc message is "hey there") * * then the index 6 would resolve to 6 - 4 = 2 => 'e' */ int messageOffset_ = 0; QString userId_; bool senderIsBroadcaster{}; }; } // namespace chatterino