mirror of
https://github.com/Chatterino/chatterino2.git
synced 2024-11-13 19:49:51 +01:00
Added custom FrankerFaceZ VIP badges (#2628)
Co-authored-by: pajlada <rasmus.karlsson@pajlada.com>
This commit is contained in:
parent
2f906c5504
commit
ed7d1a88d0
|
@ -2,6 +2,7 @@
|
|||
|
||||
## Unversioned
|
||||
|
||||
- Major: Added custom FrankerFaceZ VIP Badges. (#2628)
|
||||
- Minor: Added `in:<channels>` search filter to find messages sent in specific channels. (#2299, #2634)
|
||||
- Minor: Allow for built-in Chatterino commands to be used in custom commands. (#2632)
|
||||
- Bugfix: Fix crash that could occur when the user changed the "Custom stream player URI Scheme" setting if the user had closed down and splits in the application runtime. (#2592)
|
||||
|
|
|
@ -253,6 +253,22 @@ MessageLayoutElement *ModBadgeElement::makeImageLayoutElement(
|
|||
return element;
|
||||
}
|
||||
|
||||
// VIP BADGE
|
||||
VipBadgeElement::VipBadgeElement(const EmotePtr &data,
|
||||
MessageElementFlags flags_)
|
||||
: BadgeElement(data, flags_)
|
||||
{
|
||||
}
|
||||
|
||||
MessageLayoutElement *VipBadgeElement::makeImageLayoutElement(
|
||||
const ImagePtr &image, const QSize &size)
|
||||
{
|
||||
auto element =
|
||||
(new ImageLayoutElement(*this, image, size))->setLink(this->getLink());
|
||||
|
||||
return element;
|
||||
}
|
||||
|
||||
// FFZ Badge
|
||||
FfzBadgeElement::FfzBadgeElement(const EmotePtr &data,
|
||||
MessageElementFlags flags_, QColor &color)
|
||||
|
|
|
@ -60,6 +60,7 @@ enum class MessageElementFlag : int64_t {
|
|||
BadgeGlobalAuthority = (1LL << 14),
|
||||
|
||||
// Slot 2: Twitch
|
||||
// - VIP badge
|
||||
// - Moderator badge
|
||||
// - Broadcaster badge
|
||||
BadgeChannelAuthority = (1LL << 15),
|
||||
|
@ -275,6 +276,16 @@ protected:
|
|||
const QSize &size) override;
|
||||
};
|
||||
|
||||
class VipBadgeElement : public BadgeElement
|
||||
{
|
||||
public:
|
||||
VipBadgeElement(const EmotePtr &data, MessageElementFlags flags_);
|
||||
|
||||
protected:
|
||||
MessageLayoutElement *makeImageLayoutElement(const ImagePtr &image,
|
||||
const QSize &size) override;
|
||||
};
|
||||
|
||||
class FfzBadgeElement : public BadgeElement
|
||||
{
|
||||
public:
|
||||
|
|
|
@ -86,34 +86,36 @@ namespace {
|
|||
return {Success, std::move(emotes)};
|
||||
}
|
||||
|
||||
boost::optional<EmotePtr> parseModBadge(const QJsonObject &jsonRoot)
|
||||
boost::optional<EmotePtr> parseAuthorityBadge(const QJsonObject &badgeUrls,
|
||||
const QString tooltip)
|
||||
{
|
||||
boost::optional<EmotePtr> modBadge;
|
||||
boost::optional<EmotePtr> authorityBadge;
|
||||
|
||||
auto room = jsonRoot.value("room").toObject();
|
||||
auto modUrls = room.value("mod_urls").toObject();
|
||||
if (!modUrls.isEmpty())
|
||||
qDebug() << badgeUrls;
|
||||
if (!badgeUrls.isEmpty())
|
||||
{
|
||||
auto modBadge1x = getEmoteLink(modUrls, "1");
|
||||
auto modBadge2x = getEmoteLink(modUrls, "2");
|
||||
auto modBadge3x = getEmoteLink(modUrls, "4");
|
||||
auto authorityBadge1x = getEmoteLink(badgeUrls, "1");
|
||||
auto authorityBadge2x = getEmoteLink(badgeUrls, "2");
|
||||
auto authorityBadge3x = getEmoteLink(badgeUrls, "4");
|
||||
|
||||
auto modBadgeImageSet = ImageSet{
|
||||
Image::fromUrl(modBadge1x, 1),
|
||||
modBadge2x.string.isEmpty() ? Image::getEmpty()
|
||||
: Image::fromUrl(modBadge2x, 0.5),
|
||||
modBadge3x.string.isEmpty() ? Image::getEmpty()
|
||||
: Image::fromUrl(modBadge3x, 0.25),
|
||||
auto authorityBadgeImageSet = ImageSet{
|
||||
Image::fromUrl(authorityBadge1x, 1),
|
||||
authorityBadge2x.string.isEmpty()
|
||||
? Image::getEmpty()
|
||||
: Image::fromUrl(authorityBadge2x, 0.5),
|
||||
authorityBadge3x.string.isEmpty()
|
||||
? Image::getEmpty()
|
||||
: Image::fromUrl(authorityBadge3x, 0.25),
|
||||
};
|
||||
|
||||
modBadge = std::make_shared<Emote>(Emote{
|
||||
authorityBadge = std::make_shared<Emote>(Emote{
|
||||
{""},
|
||||
modBadgeImageSet,
|
||||
Tooltip{"Moderator"},
|
||||
modBadge1x,
|
||||
authorityBadgeImageSet,
|
||||
Tooltip{tooltip},
|
||||
authorityBadge1x,
|
||||
});
|
||||
}
|
||||
return modBadge;
|
||||
return authorityBadge;
|
||||
}
|
||||
|
||||
EmoteMap parseChannelEmotes(const QJsonObject &jsonRoot)
|
||||
|
@ -199,6 +201,7 @@ void FfzEmotes::loadChannel(
|
|||
std::weak_ptr<Channel> channel, const QString &channelId,
|
||||
std::function<void(EmoteMap &&)> emoteCallback,
|
||||
std::function<void(boost::optional<EmotePtr>)> modBadgeCallback,
|
||||
std::function<void(boost::optional<EmotePtr>)> vipBadgeCallback,
|
||||
bool manualRefresh)
|
||||
{
|
||||
qCDebug(chatterinoFfzemotes)
|
||||
|
@ -208,16 +211,23 @@ void FfzEmotes::loadChannel(
|
|||
|
||||
.timeout(20000)
|
||||
.onSuccess([emoteCallback = std::move(emoteCallback),
|
||||
modBadgeCallback = std::move(modBadgeCallback), channel,
|
||||
modBadgeCallback = std::move(modBadgeCallback),
|
||||
vipBadgeCallback = std::move(vipBadgeCallback), channel,
|
||||
manualRefresh](auto result) -> Outcome {
|
||||
auto json = result.parseJson();
|
||||
auto emoteMap = parseChannelEmotes(json);
|
||||
auto modBadge = parseModBadge(json);
|
||||
auto modBadge = parseAuthorityBadge(
|
||||
json.value("room").toObject().value("mod_urls").toObject(),
|
||||
"Moderator");
|
||||
auto vipBadge = parseAuthorityBadge(
|
||||
json.value("room").toObject().value("vip_badge").toObject(),
|
||||
"VIP");
|
||||
|
||||
bool hasEmotes = !emoteMap.empty();
|
||||
|
||||
emoteCallback(std::move(emoteMap));
|
||||
modBadgeCallback(std::move(modBadge));
|
||||
vipBadgeCallback(std::move(vipBadge));
|
||||
if (auto shared = channel.lock(); manualRefresh)
|
||||
{
|
||||
if (hasEmotes)
|
||||
|
|
|
@ -27,6 +27,7 @@ public:
|
|||
std::weak_ptr<Channel> channel, const QString &channelId,
|
||||
std::function<void(EmoteMap &&)> emoteCallback,
|
||||
std::function<void(boost::optional<EmotePtr>)> modBadgeCallback,
|
||||
std::function<void(boost::optional<EmotePtr>)> vipBadgeCallback,
|
||||
bool manualRefresh);
|
||||
|
||||
private:
|
||||
|
|
|
@ -269,6 +269,12 @@ void TwitchChannel::refreshFFZChannelEmotes(bool manualRefresh)
|
|||
this->ffzCustomModBadge_.set(std::move(modBadge));
|
||||
}
|
||||
},
|
||||
[this, weak = weakOf<Channel>(this)](auto &&vipBadge) {
|
||||
if (auto shared = weak.lock())
|
||||
{
|
||||
this->ffzCustomVipBadge_.set(std::move(vipBadge));
|
||||
}
|
||||
},
|
||||
manualRefresh);
|
||||
}
|
||||
|
||||
|
@ -1067,6 +1073,11 @@ boost::optional<EmotePtr> TwitchChannel::ffzCustomModBadge() const
|
|||
return this->ffzCustomModBadge_.get();
|
||||
}
|
||||
|
||||
boost::optional<EmotePtr> TwitchChannel::ffzCustomVipBadge() const
|
||||
{
|
||||
return this->ffzCustomVipBadge_.get();
|
||||
}
|
||||
|
||||
boost::optional<CheerEmote> TwitchChannel::cheerEmote(const QString &string)
|
||||
{
|
||||
auto sets = this->cheerEmoteSets_.access();
|
||||
|
|
|
@ -100,6 +100,7 @@ public:
|
|||
|
||||
// Badges
|
||||
boost::optional<EmotePtr> ffzCustomModBadge() const;
|
||||
boost::optional<EmotePtr> ffzCustomVipBadge() const;
|
||||
boost::optional<EmotePtr> twitchBadge(const QString &set,
|
||||
const QString &version) const;
|
||||
|
||||
|
@ -171,6 +172,7 @@ protected:
|
|||
Atomic<std::shared_ptr<const EmoteMap>> bttvEmotes_;
|
||||
Atomic<std::shared_ptr<const EmoteMap>> ffzEmotes_;
|
||||
Atomic<boost::optional<EmotePtr>> ffzCustomModBadge_;
|
||||
Atomic<boost::optional<EmotePtr>> ffzCustomVipBadge_;
|
||||
|
||||
private:
|
||||
// Badges
|
||||
|
|
|
@ -1128,6 +1128,18 @@ void TwitchMessageBuilder::appendTwitchBadges()
|
|||
continue;
|
||||
}
|
||||
}
|
||||
else if (badge.key_ == "vip")
|
||||
{
|
||||
if (auto customVipBadge = this->twitchChannel->ffzCustomVipBadge())
|
||||
{
|
||||
this->emplace<VipBadgeElement>(
|
||||
customVipBadge.get(),
|
||||
MessageElementFlag::BadgeChannelAuthority)
|
||||
->setTooltip((*customVipBadge)->tooltip.string);
|
||||
// early out, since we have to add a custom badge element here
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else if (badge.flag_ == MessageElementFlag::BadgeSubscription)
|
||||
{
|
||||
auto badgeInfoIt = badgeInfos.find(badge.key_);
|
||||
|
|
Loading…
Reference in a new issue