Add cached emotes fallback for failed provider fetches (#6125)
This commit is contained in:
@@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
## Unversioned
|
## Unversioned
|
||||||
|
|
||||||
|
- Minor: Added cached emotes fallback when fetching from a provider fails. (#6125)
|
||||||
- Minor: Add an option for the reduced opacity of message history. (#6121)
|
- Minor: Add an option for the reduced opacity of message history. (#6121)
|
||||||
- Minor: Make paused chat indicator more visible, and fix its zoom behavior. (#6123)
|
- Minor: Make paused chat indicator more visible, and fix its zoom behavior. (#6123)
|
||||||
- Minor: Added WebSocket API for plugins. (#6076)
|
- Minor: Added WebSocket API for plugins. (#6076)
|
||||||
|
|||||||
@@ -11,8 +11,11 @@
|
|||||||
#include "providers/bttv/liveupdates/BttvLiveUpdateMessages.hpp"
|
#include "providers/bttv/liveupdates/BttvLiveUpdateMessages.hpp"
|
||||||
#include "providers/twitch/TwitchChannel.hpp"
|
#include "providers/twitch/TwitchChannel.hpp"
|
||||||
#include "singletons/Settings.hpp"
|
#include "singletons/Settings.hpp"
|
||||||
|
#include "util/Helpers.hpp"
|
||||||
|
|
||||||
#include <QJsonArray>
|
#include <QJsonArray>
|
||||||
|
#include <QLoggingCategory>
|
||||||
|
#include <QStringLiteral>
|
||||||
#include <QThread>
|
#include <QThread>
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
@@ -218,9 +221,19 @@ void BttvEmotes::loadEmotes()
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
readProviderEmotesCache("global", "betterttv", [this](const auto &jsonDoc) {
|
||||||
|
auto emotes = this->global_.get();
|
||||||
|
auto pair = parseGlobalEmotes(jsonDoc.array(), *emotes);
|
||||||
|
if (pair.first)
|
||||||
|
{
|
||||||
|
this->setEmotes(std::make_shared<EmoteMap>(std::move(pair.second)));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
NetworkRequest(QString(globalEmoteApiUrl))
|
NetworkRequest(QString(globalEmoteApiUrl))
|
||||||
.timeout(30000)
|
.timeout(30000)
|
||||||
.onSuccess([this](auto result) {
|
.onSuccess([this](auto result) {
|
||||||
|
writeProviderEmotesCache("global", "betterttv", result.getData());
|
||||||
auto emotes = this->global_.get();
|
auto emotes = this->global_.get();
|
||||||
auto pair = parseGlobalEmotes(result.parseJsonArray(), *emotes);
|
auto pair = parseGlobalEmotes(result.parseJsonArray(), *emotes);
|
||||||
if (pair.first)
|
if (pair.first)
|
||||||
@@ -229,6 +242,10 @@ void BttvEmotes::loadEmotes()
|
|||||||
std::make_shared<EmoteMap>(std::move(pair.second)));
|
std::make_shared<EmoteMap>(std::move(pair.second)));
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
.onError([](auto result) {
|
||||||
|
qCWarning(chatterinoBttv) << "Failed to fetch global BTTV emotes. "
|
||||||
|
<< result.formatError();
|
||||||
|
})
|
||||||
.execute();
|
.execute();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -241,15 +258,16 @@ void BttvEmotes::loadChannel(std::weak_ptr<Channel> channel,
|
|||||||
const QString &channelId,
|
const QString &channelId,
|
||||||
const QString &channelDisplayName,
|
const QString &channelDisplayName,
|
||||||
std::function<void(EmoteMap &&)> callback,
|
std::function<void(EmoteMap &&)> callback,
|
||||||
bool manualRefresh)
|
bool manualRefresh, bool cacheHit)
|
||||||
{
|
{
|
||||||
NetworkRequest(QString(bttvChannelEmoteApiUrl) + channelId)
|
NetworkRequest(QString(bttvChannelEmoteApiUrl) + channelId)
|
||||||
.timeout(20000)
|
.timeout(20000)
|
||||||
.onSuccess([callback = std::move(callback), channel, channelDisplayName,
|
.onSuccess([callback = std::move(callback), channel, channelId,
|
||||||
manualRefresh](auto result) {
|
channelDisplayName, manualRefresh](auto result) {
|
||||||
auto emotes =
|
auto emotes =
|
||||||
parseChannelEmotes(result.parseJson(), channelDisplayName);
|
parseChannelEmotes(result.parseJson(), channelDisplayName);
|
||||||
bool hasEmotes = !emotes.empty();
|
bool hasEmotes = !emotes.empty();
|
||||||
|
writeProviderEmotesCache(channelId, "betterttv", result.getData());
|
||||||
callback(std::move(emotes));
|
callback(std::move(emotes));
|
||||||
|
|
||||||
if (auto shared = channel.lock(); manualRefresh)
|
if (auto shared = channel.lock(); manualRefresh)
|
||||||
@@ -265,7 +283,7 @@ void BttvEmotes::loadChannel(std::weak_ptr<Channel> channel,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.onError([channelId, channel, manualRefresh](auto result) {
|
.onError([channelId, channel, manualRefresh, cacheHit](auto result) {
|
||||||
auto shared = channel.lock();
|
auto shared = channel.lock();
|
||||||
if (!shared)
|
if (!shared)
|
||||||
{
|
{
|
||||||
@@ -291,6 +309,11 @@ void BttvEmotes::loadChannel(std::weak_ptr<Channel> channel,
|
|||||||
QStringLiteral("Failed to fetch BetterTTV channel "
|
QStringLiteral("Failed to fetch BetterTTV channel "
|
||||||
"emotes. (Error: %1)")
|
"emotes. (Error: %1)")
|
||||||
.arg(errorString));
|
.arg(errorString));
|
||||||
|
if (cacheHit)
|
||||||
|
{
|
||||||
|
shared->addSystemMessage(
|
||||||
|
"Using cached BetterTTV emotes as fallback.");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.execute();
|
.execute();
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ public:
|
|||||||
const QString &channelId,
|
const QString &channelId,
|
||||||
const QString &channelDisplayName,
|
const QString &channelDisplayName,
|
||||||
std::function<void(EmoteMap &&)> callback,
|
std::function<void(EmoteMap &&)> callback,
|
||||||
bool manualRefresh);
|
bool manualRefresh, bool cacheHit);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds an emote to the `channelEmoteMap`.
|
* Adds an emote to the `channelEmoteMap`.
|
||||||
|
|||||||
@@ -9,6 +9,7 @@
|
|||||||
#include "providers/ffz/FfzUtil.hpp"
|
#include "providers/ffz/FfzUtil.hpp"
|
||||||
#include "providers/twitch/TwitchChannel.hpp"
|
#include "providers/twitch/TwitchChannel.hpp"
|
||||||
#include "singletons/Settings.hpp"
|
#include "singletons/Settings.hpp"
|
||||||
|
#include "util/Helpers.hpp"
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
@@ -237,15 +238,26 @@ void FfzEmotes::loadEmotes()
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
readProviderEmotesCache("global", "frankerfacez", [this](auto jsonDoc) {
|
||||||
|
auto parsedSet = parseGlobalEmotes(jsonDoc.object());
|
||||||
|
this->setEmotes(std::make_shared<EmoteMap>(std::move(parsedSet)));
|
||||||
|
});
|
||||||
|
|
||||||
QString url("https://api.frankerfacez.com/v1/set/global");
|
QString url("https://api.frankerfacez.com/v1/set/global");
|
||||||
|
|
||||||
NetworkRequest(url)
|
NetworkRequest(url)
|
||||||
|
|
||||||
.timeout(30000)
|
.timeout(30000)
|
||||||
.onSuccess([this](auto result) {
|
.onSuccess([this](auto result) {
|
||||||
|
writeProviderEmotesCache("global", "frankerfacez",
|
||||||
|
result.getData());
|
||||||
auto parsedSet = parseGlobalEmotes(result.parseJson());
|
auto parsedSet = parseGlobalEmotes(result.parseJson());
|
||||||
this->setEmotes(std::make_shared<EmoteMap>(std::move(parsedSet)));
|
this->setEmotes(std::make_shared<EmoteMap>(std::move(parsedSet)));
|
||||||
})
|
})
|
||||||
|
.onError([](auto result) {
|
||||||
|
qCWarning(chatterinoFfzemotes)
|
||||||
|
<< "Failed to fetch global FFZ emotes. "
|
||||||
|
<< result.formatError();
|
||||||
|
})
|
||||||
.execute();
|
.execute();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -260,7 +272,7 @@ void FfzEmotes::loadChannel(
|
|||||||
std::function<void(std::optional<EmotePtr>)> modBadgeCallback,
|
std::function<void(std::optional<EmotePtr>)> modBadgeCallback,
|
||||||
std::function<void(std::optional<EmotePtr>)> vipBadgeCallback,
|
std::function<void(std::optional<EmotePtr>)> vipBadgeCallback,
|
||||||
std::function<void(FfzChannelBadgeMap &&)> channelBadgesCallback,
|
std::function<void(FfzChannelBadgeMap &&)> channelBadgesCallback,
|
||||||
bool manualRefresh)
|
bool manualRefresh, bool cacheHit)
|
||||||
{
|
{
|
||||||
qCDebug(LOG) << "Reload FFZ Channel Emotes for channel" << channelID;
|
qCDebug(LOG) << "Reload FFZ Channel Emotes for channel" << channelID;
|
||||||
|
|
||||||
@@ -271,7 +283,9 @@ void FfzEmotes::loadChannel(
|
|||||||
modBadgeCallback = std::move(modBadgeCallback),
|
modBadgeCallback = std::move(modBadgeCallback),
|
||||||
vipBadgeCallback = std::move(vipBadgeCallback),
|
vipBadgeCallback = std::move(vipBadgeCallback),
|
||||||
channelBadgesCallback = std::move(channelBadgesCallback),
|
channelBadgesCallback = std::move(channelBadgesCallback),
|
||||||
channel, manualRefresh](const auto &result) {
|
channel, channelID, manualRefresh](const auto &result) {
|
||||||
|
writeProviderEmotesCache(channelID, "frankerfacez",
|
||||||
|
result.getData());
|
||||||
const auto json = result.parseJson();
|
const auto json = result.parseJson();
|
||||||
|
|
||||||
auto emoteMap = parseChannelEmotes(json);
|
auto emoteMap = parseChannelEmotes(json);
|
||||||
@@ -301,33 +315,39 @@ void FfzEmotes::loadChannel(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.onError([channelID, channel, manualRefresh](const auto &result) {
|
.onError(
|
||||||
auto shared = channel.lock();
|
[channelID, channel, manualRefresh, cacheHit](const auto &result) {
|
||||||
if (!shared)
|
auto shared = channel.lock();
|
||||||
{
|
if (!shared)
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (result.status() == 404)
|
|
||||||
{
|
|
||||||
// User does not have any FFZ emotes
|
|
||||||
if (manualRefresh)
|
|
||||||
{
|
{
|
||||||
shared->addSystemMessage(CHANNEL_HAS_NO_EMOTES);
|
return;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
else
|
if (result.status() == 404)
|
||||||
{
|
{
|
||||||
// TODO: Auto retry in case of a timeout, with a delay
|
// User does not have any FFZ emotes
|
||||||
auto errorString = result.formatError();
|
if (manualRefresh)
|
||||||
qCWarning(LOG) << "Error fetching FFZ emotes for channel"
|
{
|
||||||
<< channelID << ", error" << errorString;
|
shared->addSystemMessage(CHANNEL_HAS_NO_EMOTES);
|
||||||
shared->addSystemMessage(
|
}
|
||||||
QStringLiteral("Failed to fetch FrankerFaceZ channel "
|
}
|
||||||
"emotes. (Error: %1)")
|
else
|
||||||
.arg(errorString));
|
{
|
||||||
}
|
// TODO: Auto retry in case of a timeout, with a delay
|
||||||
})
|
auto errorString = result.formatError();
|
||||||
|
qCWarning(LOG) << "Error fetching FFZ emotes for channel"
|
||||||
|
<< channelID << ", error" << errorString;
|
||||||
|
shared->addSystemMessage(
|
||||||
|
QStringLiteral("Failed to fetch FrankerFaceZ channel "
|
||||||
|
"emotes. (Error: %1)")
|
||||||
|
.arg(errorString));
|
||||||
|
if (cacheHit)
|
||||||
|
{
|
||||||
|
shared->addSystemMessage(
|
||||||
|
"Using cached FrankerFaceZ emotes as fallback.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
.execute();
|
.execute();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -51,7 +51,7 @@ public:
|
|||||||
std::function<void(std::optional<EmotePtr>)> modBadgeCallback,
|
std::function<void(std::optional<EmotePtr>)> modBadgeCallback,
|
||||||
std::function<void(std::optional<EmotePtr>)> vipBadgeCallback,
|
std::function<void(std::optional<EmotePtr>)> vipBadgeCallback,
|
||||||
std::function<void(FfzChannelBadgeMap &&)> channelBadgesCallback,
|
std::function<void(FfzChannelBadgeMap &&)> channelBadgesCallback,
|
||||||
bool manualRefresh);
|
bool manualRefresh, bool cacheHit);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Atomic<std::shared_ptr<const EmoteMap>> global_;
|
Atomic<std::shared_ptr<const EmoteMap>> global_;
|
||||||
|
|||||||
@@ -16,6 +16,8 @@
|
|||||||
|
|
||||||
#include <QJsonArray>
|
#include <QJsonArray>
|
||||||
#include <QJsonDocument>
|
#include <QJsonDocument>
|
||||||
|
#include <QJsonObject>
|
||||||
|
#include <QStringView>
|
||||||
#include <QThread>
|
#include <QThread>
|
||||||
|
|
||||||
#include <array>
|
#include <array>
|
||||||
@@ -230,11 +232,18 @@ void SeventvEmotes::loadGlobalEmotes()
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
readProviderEmotesCache("global", "seventv", [this](auto jsonDoc) {
|
||||||
|
auto emoteMap = parseEmotes(jsonDoc.object()["emotes"].toArray(), true);
|
||||||
|
this->setGlobalEmotes(std::make_shared<EmoteMap>(std::move(emoteMap)));
|
||||||
|
});
|
||||||
|
|
||||||
qCDebug(chatterinoSeventv) << "Loading 7TV Global Emotes";
|
qCDebug(chatterinoSeventv) << "Loading 7TV Global Emotes";
|
||||||
|
|
||||||
getApp()->getSeventvAPI()->getEmoteSet(
|
getApp()->getSeventvAPI()->getEmoteSet(
|
||||||
u"global"_s,
|
u"global"_s,
|
||||||
[this](const auto &json) {
|
[this](const auto &json) {
|
||||||
|
writeProviderEmotesCache("global", "seventv",
|
||||||
|
QJsonDocument(json).toJson());
|
||||||
QJsonArray parsedEmotes = json["emotes"].toArray();
|
QJsonArray parsedEmotes = json["emotes"].toArray();
|
||||||
|
|
||||||
auto emoteMap = parseEmotes(parsedEmotes, true);
|
auto emoteMap = parseEmotes(parsedEmotes, true);
|
||||||
@@ -256,7 +265,8 @@ void SeventvEmotes::setGlobalEmotes(std::shared_ptr<const EmoteMap> emotes)
|
|||||||
|
|
||||||
void SeventvEmotes::loadChannelEmotes(
|
void SeventvEmotes::loadChannelEmotes(
|
||||||
const std::weak_ptr<Channel> &channel, const QString &channelId,
|
const std::weak_ptr<Channel> &channel, const QString &channelId,
|
||||||
std::function<void(EmoteMap &&, ChannelInfo)> callback, bool manualRefresh)
|
std::function<void(EmoteMap &&, ChannelInfo)> callback, bool manualRefresh,
|
||||||
|
bool cacheHit)
|
||||||
{
|
{
|
||||||
qCDebug(chatterinoSeventv)
|
qCDebug(chatterinoSeventv)
|
||||||
<< "Reloading 7TV Channel Emotes" << channelId << manualRefresh;
|
<< "Reloading 7TV Channel Emotes" << channelId << manualRefresh;
|
||||||
@@ -265,6 +275,8 @@ void SeventvEmotes::loadChannelEmotes(
|
|||||||
channelId,
|
channelId,
|
||||||
[callback = std::move(callback), channel, channelId,
|
[callback = std::move(callback), channel, channelId,
|
||||||
manualRefresh](const auto &json) {
|
manualRefresh](const auto &json) {
|
||||||
|
writeProviderEmotesCache(channelId, "seventv",
|
||||||
|
QJsonDocument(json).toJson());
|
||||||
const auto emoteSet = json["emote_set"].toObject();
|
const auto emoteSet = json["emote_set"].toObject();
|
||||||
const auto parsedEmotes = emoteSet["emotes"].toArray();
|
const auto parsedEmotes = emoteSet["emotes"].toArray();
|
||||||
|
|
||||||
@@ -312,7 +324,7 @@ void SeventvEmotes::loadChannelEmotes(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
[channelId, channel, manualRefresh](const auto &result) {
|
[channelId, channel, manualRefresh, cacheHit](const auto &result) {
|
||||||
auto shared = channel.lock();
|
auto shared = channel.lock();
|
||||||
if (!shared)
|
if (!shared)
|
||||||
{
|
{
|
||||||
@@ -339,6 +351,11 @@ void SeventvEmotes::loadChannelEmotes(
|
|||||||
QStringLiteral("Failed to fetch 7TV channel "
|
QStringLiteral("Failed to fetch 7TV channel "
|
||||||
"emotes. (Error: %1)")
|
"emotes. (Error: %1)")
|
||||||
.arg(errorString));
|
.arg(errorString));
|
||||||
|
if (cacheHit)
|
||||||
|
{
|
||||||
|
shared->addSystemMessage(
|
||||||
|
"Using cached 7TV emotes as fallback.");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -108,7 +108,7 @@ public:
|
|||||||
static void loadChannelEmotes(
|
static void loadChannelEmotes(
|
||||||
const std::weak_ptr<Channel> &channel, const QString &channelId,
|
const std::weak_ptr<Channel> &channel, const QString &channelId,
|
||||||
std::function<void(EmoteMap &&, ChannelInfo)> callback,
|
std::function<void(EmoteMap &&, ChannelInfo)> callback,
|
||||||
bool manualRefresh);
|
bool manualRefresh, bool cacheHit);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds an emote to the `map` if it's valid.
|
* Adds an emote to the `map` if it's valid.
|
||||||
|
|||||||
@@ -327,6 +327,17 @@ void TwitchChannel::refreshBTTVChannelEmotes(bool manualRefresh)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool cacheHit = readProviderEmotesCache(
|
||||||
|
this->roomId(), "betterttv",
|
||||||
|
[this, weak = weakOf<Channel>(this)](auto jsonDoc) {
|
||||||
|
if (auto shared = weak.lock())
|
||||||
|
{
|
||||||
|
auto emoteMap = bttv::detail::parseChannelEmotes(
|
||||||
|
jsonDoc.object(), this->getLocalizedName());
|
||||||
|
this->setBttvEmotes(std::make_shared<const EmoteMap>(emoteMap));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
BttvEmotes::loadChannel(
|
BttvEmotes::loadChannel(
|
||||||
weakOf<Channel>(this), this->roomId(), this->getLocalizedName(),
|
weakOf<Channel>(this), this->roomId(), this->getLocalizedName(),
|
||||||
[this, weak = weakOf<Channel>(this)](auto &&emoteMap) {
|
[this, weak = weakOf<Channel>(this)](auto &&emoteMap) {
|
||||||
@@ -335,7 +346,7 @@ void TwitchChannel::refreshBTTVChannelEmotes(bool manualRefresh)
|
|||||||
this->setBttvEmotes(std::make_shared<const EmoteMap>(emoteMap));
|
this->setBttvEmotes(std::make_shared<const EmoteMap>(emoteMap));
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
manualRefresh);
|
manualRefresh, cacheHit);
|
||||||
}
|
}
|
||||||
|
|
||||||
void TwitchChannel::refreshFFZChannelEmotes(bool manualRefresh)
|
void TwitchChannel::refreshFFZChannelEmotes(bool manualRefresh)
|
||||||
@@ -346,6 +357,12 @@ void TwitchChannel::refreshFFZChannelEmotes(bool manualRefresh)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool cacheHit = readProviderEmotesCache(
|
||||||
|
this->roomId(), "frankerfacez", [this](const auto &jsonDoc) {
|
||||||
|
auto emoteMap = ffz::detail::parseChannelEmotes(jsonDoc.object());
|
||||||
|
this->setFfzEmotes(std::make_shared<const EmoteMap>(emoteMap));
|
||||||
|
});
|
||||||
|
|
||||||
FfzEmotes::loadChannel(
|
FfzEmotes::loadChannel(
|
||||||
weakOf<Channel>(this), this->roomId(),
|
weakOf<Channel>(this), this->roomId(),
|
||||||
[this, weak = weakOf<Channel>(this)](auto &&emoteMap) {
|
[this, weak = weakOf<Channel>(this)](auto &&emoteMap) {
|
||||||
@@ -376,7 +393,7 @@ void TwitchChannel::refreshFFZChannelEmotes(bool manualRefresh)
|
|||||||
std::forward<decltype(channelBadges)>(channelBadges);
|
std::forward<decltype(channelBadges)>(channelBadges);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
manualRefresh);
|
manualRefresh, cacheHit);
|
||||||
}
|
}
|
||||||
|
|
||||||
void TwitchChannel::refreshSevenTVChannelEmotes(bool manualRefresh)
|
void TwitchChannel::refreshSevenTVChannelEmotes(bool manualRefresh)
|
||||||
@@ -387,6 +404,15 @@ void TwitchChannel::refreshSevenTVChannelEmotes(bool manualRefresh)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool cacheHit = readProviderEmotesCache(
|
||||||
|
this->roomId(), "seventv", [this](auto jsonDoc) {
|
||||||
|
const auto json = jsonDoc.object();
|
||||||
|
const auto emoteSet = json["emote_set"].toObject();
|
||||||
|
const auto parsedEmotes = emoteSet["emotes"].toArray();
|
||||||
|
auto emoteMap = seventv::detail::parseEmotes(parsedEmotes, false);
|
||||||
|
this->setSeventvEmotes(std::make_shared<const EmoteMap>(emoteMap));
|
||||||
|
});
|
||||||
|
|
||||||
SeventvEmotes::loadChannelEmotes(
|
SeventvEmotes::loadChannelEmotes(
|
||||||
weakOf<Channel>(this), this->roomId(),
|
weakOf<Channel>(this), this->roomId(),
|
||||||
[this, weak = weakOf<Channel>(this)](auto &&emoteMap,
|
[this, weak = weakOf<Channel>(this)](auto &&emoteMap,
|
||||||
@@ -401,7 +427,7 @@ void TwitchChannel::refreshSevenTVChannelEmotes(bool manualRefresh)
|
|||||||
channelInfo.twitchConnectionIndex;
|
channelInfo.twitchConnectionIndex;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
manualRefresh);
|
manualRefresh, cacheHit);
|
||||||
}
|
}
|
||||||
|
|
||||||
void TwitchChannel::setBttvEmotes(std::shared_ptr<const EmoteMap> &&map)
|
void TwitchChannel::setBttvEmotes(std::shared_ptr<const EmoteMap> &&map)
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ QString Paths::cacheDirectory() const
|
|||||||
static const auto pathSetting = [] {
|
static const auto pathSetting = [] {
|
||||||
QStringSetting cachePathSetting("/cache/path");
|
QStringSetting cachePathSetting("/cache/path");
|
||||||
|
|
||||||
cachePathSetting.connect([](const auto &newPath, auto) {
|
cachePathSetting.connect([](const auto &newPath) {
|
||||||
if (!newPath.isEmpty())
|
if (!newPath.isEmpty())
|
||||||
{
|
{
|
||||||
QDir().mkpath(newPath);
|
QDir().mkpath(newPath);
|
||||||
@@ -59,6 +59,11 @@ QString Paths::cacheDirectory() const
|
|||||||
return path;
|
return path;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QString Paths::cacheFilePath(const QString &fileName) const
|
||||||
|
{
|
||||||
|
return combinePath(this->cacheDirectory(), fileName);
|
||||||
|
}
|
||||||
|
|
||||||
void Paths::initAppFilePathHash()
|
void Paths::initAppFilePathHash()
|
||||||
{
|
{
|
||||||
this->applicationFilePathHash =
|
this->applicationFilePathHash =
|
||||||
|
|||||||
@@ -50,6 +50,11 @@ public:
|
|||||||
|
|
||||||
QString cacheDirectory() const;
|
QString cacheDirectory() const;
|
||||||
|
|
||||||
|
/// Returns the full file path for a file in the cache directory
|
||||||
|
///
|
||||||
|
/// e.g. cacheFilePath("foo") will return <cacheDirectory>/foo
|
||||||
|
QString cacheFilePath(const QString &fileName) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void initAppFilePathHash();
|
void initAppFilePathHash();
|
||||||
void initCheckPortable();
|
void initCheckPortable();
|
||||||
|
|||||||
@@ -1,12 +1,19 @@
|
|||||||
#include "util/Helpers.hpp"
|
#include "util/Helpers.hpp"
|
||||||
|
|
||||||
#include "Application.hpp"
|
#include "Application.hpp"
|
||||||
|
#include "common/QLogging.hpp"
|
||||||
#include "providers/twitch/TwitchCommon.hpp"
|
#include "providers/twitch/TwitchCommon.hpp"
|
||||||
|
#include "singletons/Paths.hpp"
|
||||||
|
|
||||||
#include <QDateTime>
|
#include <QDateTime>
|
||||||
#include <QDirIterator>
|
#include <QDirIterator>
|
||||||
|
#include <QJsonObject>
|
||||||
#include <QLocale>
|
#include <QLocale>
|
||||||
|
#include <QLoggingCategory>
|
||||||
#include <QRegularExpression>
|
#include <QRegularExpression>
|
||||||
|
#include <QStringBuilder>
|
||||||
|
#include <QStringView>
|
||||||
|
#include <QThreadPool>
|
||||||
#include <QTimeZone>
|
#include <QTimeZone>
|
||||||
#include <QUuid>
|
#include <QUuid>
|
||||||
|
|
||||||
@@ -386,4 +393,49 @@ void removeLastQS(QString &str)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void writeProviderEmotesCache(const QString &id, const QString &provider,
|
||||||
|
const QByteArray &bytes)
|
||||||
|
{
|
||||||
|
QThreadPool::globalInstance()->start([bytes, id, provider]() {
|
||||||
|
auto cacheKey = id % "." % provider;
|
||||||
|
QFile responseCache(getApp()->getPaths().cacheFilePath(cacheKey));
|
||||||
|
|
||||||
|
if (responseCache.open(QIODevice::WriteOnly))
|
||||||
|
{
|
||||||
|
qCDebug(chatterinoCache)
|
||||||
|
<< "Saved json response " << id << "." << provider;
|
||||||
|
responseCache.write(qCompress(bytes));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
bool readProviderEmotesCache(const QString &id, const QString &provider,
|
||||||
|
const std::function<void(QJsonDocument)> &callback)
|
||||||
|
{
|
||||||
|
auto cacheKey = id % "." % provider;
|
||||||
|
QFile responseCache(getApp()->getPaths().cacheFilePath(cacheKey));
|
||||||
|
|
||||||
|
if (responseCache.open(QIODevice::ReadOnly))
|
||||||
|
{
|
||||||
|
QJsonParseError parseError;
|
||||||
|
auto doc = QJsonDocument::fromJson(qUncompress(responseCache.readAll()),
|
||||||
|
&parseError);
|
||||||
|
|
||||||
|
if (parseError.error != QJsonParseError::NoError)
|
||||||
|
{
|
||||||
|
qCWarning(chatterinoCache)
|
||||||
|
<< "Emote cache " << id << "." << provider
|
||||||
|
<< " parsing failed: " << parseError.errorString();
|
||||||
|
}
|
||||||
|
|
||||||
|
qCDebug(chatterinoCache)
|
||||||
|
<< "Loaded emote cache: " << id << "." << provider;
|
||||||
|
callback(doc);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the API call fails, we need to know if loading cached emotes was successful
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace chatterino
|
} // namespace chatterino
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <QColor>
|
#include <QColor>
|
||||||
|
#include <QJsonDocument>
|
||||||
#include <QLocale>
|
#include <QLocale>
|
||||||
#include <QString>
|
#include <QString>
|
||||||
|
|
||||||
@@ -218,4 +219,11 @@ void removeFirstQS(QString &str);
|
|||||||
/// @param str The Qt string we want to remove 1 character from
|
/// @param str The Qt string we want to remove 1 character from
|
||||||
void removeLastQS(QString &str);
|
void removeLastQS(QString &str);
|
||||||
|
|
||||||
|
void writeProviderEmotesCache(const QString &id, const QString &provider,
|
||||||
|
const QByteArray &bytes);
|
||||||
|
|
||||||
|
bool readProviderEmotesCache(
|
||||||
|
const QString &id, const QString &provider,
|
||||||
|
const std::function<void(QJsonDocument)> &callback);
|
||||||
|
|
||||||
} // namespace chatterino
|
} // namespace chatterino
|
||||||
|
|||||||
Reference in New Issue
Block a user