feat(plugins): allow message introspection (#6353)

This allows users to introspect messages (i.e. look at the elements they're made up of).

Reviewed-by: Mm2PL <mm2pl+gh@kotmisia.pl>
This commit is contained in:
nerix
2025-12-07 15:52:59 +01:00
committed by GitHub
parent 0aff6fbe83
commit 74b4674c6b
12 changed files with 1836 additions and 210 deletions
+115 -8
View File
@@ -184,6 +184,12 @@ public:
virtual QJsonObject toJson() const;
/// The type name for this message element. Used for Lua plugins.
///
/// This must be unique per element. It should return the static `TYPE`
/// member.
virtual std::string_view type() const = 0;
protected:
MessageElement(MessageElementFlags flags);
bool trailingSpace = true;
@@ -198,12 +204,15 @@ private:
class ImageElement : public MessageElement
{
public:
static constexpr std::string_view TYPE = "image";
ImageElement(ImagePtr image, MessageElementFlags flags);
void addToContainer(MessageLayoutContainer &container,
const MessageLayoutContext &ctx) override;
QJsonObject toJson() const override;
std::string_view type() const override;
private:
ImagePtr image_;
@@ -213,6 +222,8 @@ private:
class CircularImageElement : public MessageElement
{
public:
static constexpr std::string_view TYPE = "circular-image";
CircularImageElement(ImagePtr image, int padding, QColor background,
MessageElementFlags flags);
@@ -220,6 +231,16 @@ public:
const MessageLayoutContext &ctx) override;
QJsonObject toJson() const override;
std::string_view type() const override;
int padding() const
{
return this->padding_;
}
QColor background() const
{
return this->background_;
}
private:
ImagePtr image_;
@@ -231,6 +252,8 @@ private:
class TextElement : public MessageElement
{
public:
static constexpr std::string_view TYPE = "text";
TextElement(const QString &text, MessageElementFlags flags,
const MessageColor &color = MessageColor::Text,
FontStyle style = FontStyle::ChatMedium);
@@ -240,6 +263,7 @@ public:
const MessageLayoutContext &ctx) override;
QJsonObject toJson() const override;
std::string_view type() const override;
const MessageColor &color() const noexcept;
FontStyle fontStyle() const noexcept;
@@ -247,6 +271,11 @@ public:
void appendText(QStringView text);
void appendText(const QString &text);
QStringList words() const
{
return this->words_;
}
protected:
QStringList words_;
@@ -258,6 +287,8 @@ protected:
class SingleLineTextElement : public MessageElement
{
public:
static constexpr std::string_view TYPE = "single-line-text";
SingleLineTextElement(const QString &text, MessageElementFlags flags,
const MessageColor &color = MessageColor::Text,
FontStyle style = FontStyle::ChatMedium);
@@ -267,21 +298,33 @@ public:
const MessageLayoutContext &ctx) override;
QJsonObject toJson() const override;
std::string_view type() const override;
const MessageColor &color() const
{
return this->color_;
}
FontStyle fontStyle() const
{
return this->style_;
}
QStringList words() const
{
return this->words_;
}
private:
MessageColor color_;
FontStyle style_;
struct Word {
QString text;
int width = -1;
};
std::vector<Word> words_;
QStringList words_;
};
class LinkElement : public TextElement
{
public:
static constexpr std::string_view TYPE = "link";
struct Parsed {
QString lowercase;
QString original;
@@ -309,7 +352,17 @@ public:
return &this->linkInfo_;
}
QStringList lowercase() const
{
return this->lowercase_;
}
QStringList original() const
{
return this->original_;
}
QJsonObject toJson() const override;
std::string_view type() const override;
private:
LinkInfo linkInfo_;
@@ -331,6 +384,8 @@ private:
class MentionElement : public TextElement
{
public:
static constexpr std::string_view TYPE = "mention";
explicit MentionElement(const QString &displayName, QString loginName_,
MessageColor fallbackColor_,
MessageColor userColor_);
@@ -352,20 +407,34 @@ public:
MessageElement *setLink(const Link &link) override;
Link getLink() const override;
const MessageColor &fallbackColor() const
{
return this->fallbackColor_;
}
const MessageColor &userColor() const
{
return this->userColor_;
}
QString userLoginName() const
{
return this->userLoginName_;
}
QJsonObject toJson() const override;
std::string_view type() const override;
private:
/**
* The color of the element in case the "Colorize @usernames" is disabled
**/
MessageColor fallbackColor;
MessageColor fallbackColor_;
/**
* The color of the element in case the "Colorize @usernames" is enabled
**/
MessageColor userColor;
MessageColor userColor_;
QString userLoginName;
QString userLoginName_;
};
// contains emote data and will pick the emote based on :
@@ -374,6 +443,8 @@ private:
class EmoteElement : public MessageElement
{
public:
static constexpr std::string_view TYPE = "emote";
EmoteElement(const EmotePtr &data, MessageElementFlags flags_,
const MessageColor &textElementColor = MessageColor::Text);
@@ -382,6 +453,7 @@ public:
EmotePtr getEmote() const;
QJsonObject toJson() const override;
std::string_view type() const override;
protected:
virtual MessageLayoutElement *makeImageLayoutElement(const ImagePtr &image,
@@ -403,6 +475,8 @@ private:
class LayeredEmoteElement : public MessageElement
{
public:
static constexpr std::string_view TYPE = "layered-emote";
struct Emote {
EmotePtr ptr;
MessageElementFlags flags;
@@ -424,6 +498,7 @@ public:
const std::vector<QString> &getEmoteTooltips() const;
QJsonObject toJson() const override;
std::string_view type() const override;
private:
MessageLayoutElement *makeImageLayoutElement(
@@ -444,6 +519,8 @@ private:
class BadgeElement : public MessageElement
{
public:
static constexpr std::string_view TYPE = "badge";
BadgeElement(const EmotePtr &data, MessageElementFlags flags_);
void addToContainer(MessageLayoutContainer &container,
@@ -452,6 +529,7 @@ public:
EmotePtr getEmote() const;
QJsonObject toJson() const override;
std::string_view type() const override;
protected:
virtual MessageLayoutElement *makeImageLayoutElement(const ImagePtr &image,
@@ -464,9 +542,12 @@ private:
class ModBadgeElement : public BadgeElement
{
public:
static constexpr std::string_view TYPE = "mod-badge";
ModBadgeElement(const EmotePtr &data, MessageElementFlags flags_);
QJsonObject toJson() const override;
std::string_view type() const override;
protected:
MessageLayoutElement *makeImageLayoutElement(const ImagePtr &image,
@@ -476,9 +557,12 @@ protected:
class VipBadgeElement : public BadgeElement
{
public:
static constexpr std::string_view TYPE = "vip-badge";
VipBadgeElement(const EmotePtr &data, MessageElementFlags flags_);
QJsonObject toJson() const override;
std::string_view type() const override;
protected:
MessageLayoutElement *makeImageLayoutElement(const ImagePtr &image,
@@ -488,10 +572,13 @@ protected:
class FfzBadgeElement : public BadgeElement
{
public:
static constexpr std::string_view TYPE = "ffz-badge";
FfzBadgeElement(const EmotePtr &data, MessageElementFlags flags_,
QColor color_);
QJsonObject toJson() const override;
std::string_view type() const override;
protected:
MessageLayoutElement *makeImageLayoutElement(const ImagePtr &image,
@@ -503,6 +590,8 @@ protected:
class TimestampElement : public MessageElement
{
public:
static constexpr std::string_view TYPE = "timestamp";
TimestampElement();
TimestampElement(QTime time_);
~TimestampElement() override = default;
@@ -513,7 +602,13 @@ public:
TextElement *formatTime(const QTime &time);
MessageElement *setLink(const Link &link) override;
QTime time() const
{
return this->time_;
}
QJsonObject toJson() const override;
std::string_view type() const override;
private:
QTime time_;
@@ -526,36 +621,45 @@ private:
class TwitchModerationElement : public MessageElement
{
public:
static constexpr std::string_view TYPE = "twitch-moderation";
TwitchModerationElement();
void addToContainer(MessageLayoutContainer &container,
const MessageLayoutContext &ctx) override;
QJsonObject toJson() const override;
std::string_view type() const override;
};
// Forces a linebreak
class LinebreakElement : public MessageElement
{
public:
static constexpr std::string_view TYPE = "linebreak";
LinebreakElement(MessageElementFlags flags);
void addToContainer(MessageLayoutContainer &container,
const MessageLayoutContext &ctx) override;
QJsonObject toJson() const override;
std::string_view type() const override;
};
// Image element which will pick the quality of the image based on ui scale
class ScalingImageElement : public MessageElement
{
public:
static constexpr std::string_view TYPE = "scaling-image";
ScalingImageElement(ImageSet images, MessageElementFlags flags);
void addToContainer(MessageLayoutContainer &container,
const MessageLayoutContext &ctx) override;
QJsonObject toJson() const override;
std::string_view type() const override;
private:
ImageSet images_;
@@ -564,12 +668,15 @@ private:
class ReplyCurveElement : public MessageElement
{
public:
static constexpr std::string_view TYPE = "reply-curve";
ReplyCurveElement();
void addToContainer(MessageLayoutContainer &container,
const MessageLayoutContext &ctx) override;
QJsonObject toJson() const override;
std::string_view type() const override;
};
} // namespace chatterino