mirror of
https://github.com/Chatterino/chatterino2.git
synced 2024-11-13 19:49:51 +01:00
Improve network error messages (#4704)
This commit is contained in:
parent
d2f1516818
commit
22b290cb2d
|
@ -16,6 +16,7 @@
|
||||||
- Bugfix: Fix visual glitches with smooth scrolling. (#4501)
|
- Bugfix: Fix visual glitches with smooth scrolling. (#4501)
|
||||||
- Bugfix: Fixed pings firing for the "Your username" highlight when not signed in. (#4698)
|
- Bugfix: Fixed pings firing for the "Your username" highlight when not signed in. (#4698)
|
||||||
- Bugfix: Fixed partially broken filters on Qt 6 builds. (#4702)
|
- Bugfix: Fixed partially broken filters on Qt 6 builds. (#4702)
|
||||||
|
- Bugfix: Fixed some network errors having `0` as their HTTP status. (#4704)
|
||||||
- Bugfix: Fixed crash that could occurr when closing the usercard too quickly after blocking or unblocking a user. (#4711)
|
- Bugfix: Fixed crash that could occurr when closing the usercard too quickly after blocking or unblocking a user. (#4711)
|
||||||
- Dev: Added command to set Qt's logging filter/rules at runtime (`/c2-set-logging-rules`). (#4637)
|
- Dev: Added command to set Qt's logging filter/rules at runtime (`/c2-set-logging-rules`). (#4637)
|
||||||
- Dev: Added the ability to see & load custom themes from the Themes directory. No stable promises are made of this feature, changes might be made that breaks custom themes without notice. (#4570)
|
- Dev: Added the ability to see & load custom themes from the Themes directory. No stable promises are made of this feature, changes might be made that breaks custom themes without notice. (#4570)
|
||||||
|
|
|
@ -155,7 +155,8 @@ void loadUncached(std::shared_ptr<NetworkData> &&data)
|
||||||
{
|
{
|
||||||
postToThread([data] {
|
postToThread([data] {
|
||||||
data->onError_(NetworkResult(
|
data->onError_(NetworkResult(
|
||||||
{}, NetworkResult::timedoutStatus));
|
NetworkResult::NetworkError::TimeoutError, {},
|
||||||
|
{}));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -218,8 +219,9 @@ void loadUncached(std::shared_ptr<NetworkData> &&data)
|
||||||
QString(data->payload_));
|
QString(data->payload_));
|
||||||
}
|
}
|
||||||
// TODO: Should this always be run on the GUI thread?
|
// TODO: Should this always be run on the GUI thread?
|
||||||
postToThread([data, code = status.toInt(), reply] {
|
postToThread([data, status, reply] {
|
||||||
data->onError_(NetworkResult(reply->readAll(), code));
|
data->onError_(NetworkResult(reply->error(), status,
|
||||||
|
reply->readAll()));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -238,7 +240,7 @@ void loadUncached(std::shared_ptr<NetworkData> &&data)
|
||||||
auto status =
|
auto status =
|
||||||
reply->attribute(QNetworkRequest::HttpStatusCodeAttribute);
|
reply->attribute(QNetworkRequest::HttpStatusCodeAttribute);
|
||||||
|
|
||||||
NetworkResult result(bytes, status.toInt());
|
NetworkResult result(reply->error(), status, bytes);
|
||||||
|
|
||||||
DebugCount::increase("http request success");
|
DebugCount::increase("http request success");
|
||||||
// log("starting {}", data->request_.url().toString());
|
// log("starting {}", data->request_.url().toString());
|
||||||
|
@ -337,7 +339,8 @@ void loadCached(std::shared_ptr<NetworkData> &&data)
|
||||||
|
|
||||||
// XXX: check if bytes is empty?
|
// XXX: check if bytes is empty?
|
||||||
QByteArray bytes = cachedFile.readAll();
|
QByteArray bytes = cachedFile.readAll();
|
||||||
NetworkResult result(bytes, 200);
|
NetworkResult result(NetworkResult::NetworkError::NoError, QVariant(200),
|
||||||
|
bytes);
|
||||||
|
|
||||||
qCDebug(chatterinoHTTP)
|
qCDebug(chatterinoHTTP)
|
||||||
<< QString("%1 [CACHED] 200 %2")
|
<< QString("%1 [CACHED] 200 %2")
|
||||||
|
|
|
@ -3,15 +3,21 @@
|
||||||
#include "common/QLogging.hpp"
|
#include "common/QLogging.hpp"
|
||||||
|
|
||||||
#include <QJsonDocument>
|
#include <QJsonDocument>
|
||||||
|
#include <QMetaEnum>
|
||||||
#include <rapidjson/document.h>
|
#include <rapidjson/document.h>
|
||||||
#include <rapidjson/error/en.h>
|
#include <rapidjson/error/en.h>
|
||||||
|
|
||||||
namespace chatterino {
|
namespace chatterino {
|
||||||
|
|
||||||
NetworkResult::NetworkResult(const QByteArray &data, int status)
|
NetworkResult::NetworkResult(NetworkError error, const QVariant &httpStatusCode,
|
||||||
: data_(data)
|
QByteArray data)
|
||||||
, status_(status)
|
: data_(std::move(data))
|
||||||
|
, error_(error)
|
||||||
{
|
{
|
||||||
|
if (httpStatusCode.isValid())
|
||||||
|
{
|
||||||
|
this->status_ = httpStatusCode.toInt();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
QJsonObject NetworkResult::parseJson() const
|
QJsonObject NetworkResult::parseJson() const
|
||||||
|
@ -59,9 +65,21 @@ const QByteArray &NetworkResult::getData() const
|
||||||
return this->data_;
|
return this->data_;
|
||||||
}
|
}
|
||||||
|
|
||||||
int NetworkResult::status() const
|
QString NetworkResult::formatError() const
|
||||||
{
|
{
|
||||||
return this->status_;
|
if (this->status_)
|
||||||
|
{
|
||||||
|
return QString::number(*this->status_);
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto *name =
|
||||||
|
QMetaEnum::fromType<QNetworkReply::NetworkError>().valueToKey(
|
||||||
|
this->error_);
|
||||||
|
if (name == nullptr)
|
||||||
|
{
|
||||||
|
return QStringLiteral("unknown error (%1)").arg(this->error_);
|
||||||
|
}
|
||||||
|
return name;
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace chatterino
|
} // namespace chatterino
|
||||||
|
|
|
@ -2,14 +2,20 @@
|
||||||
|
|
||||||
#include <QJsonArray>
|
#include <QJsonArray>
|
||||||
#include <QJsonObject>
|
#include <QJsonObject>
|
||||||
|
#include <QNetworkReply>
|
||||||
#include <rapidjson/document.h>
|
#include <rapidjson/document.h>
|
||||||
|
|
||||||
|
#include <optional>
|
||||||
|
|
||||||
namespace chatterino {
|
namespace chatterino {
|
||||||
|
|
||||||
class NetworkResult
|
class NetworkResult
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
NetworkResult(const QByteArray &data, int status);
|
using NetworkError = QNetworkReply::NetworkError;
|
||||||
|
|
||||||
|
NetworkResult(NetworkError error, const QVariant &httpStatusCode,
|
||||||
|
QByteArray data);
|
||||||
|
|
||||||
/// Parses the result as json and returns the root as an object.
|
/// Parses the result as json and returns the root as an object.
|
||||||
/// Returns empty object if parsing failed.
|
/// Returns empty object if parsing failed.
|
||||||
|
@ -20,13 +26,29 @@ public:
|
||||||
/// Parses the result as json and returns the document.
|
/// Parses the result as json and returns the document.
|
||||||
rapidjson::Document parseRapidJson() const;
|
rapidjson::Document parseRapidJson() const;
|
||||||
const QByteArray &getData() const;
|
const QByteArray &getData() const;
|
||||||
int status() const;
|
|
||||||
|
|
||||||
static constexpr int timedoutStatus = -2;
|
/// The error code of the reply.
|
||||||
|
/// In case of a successful reply, this will be NoError (0)
|
||||||
|
NetworkError error() const
|
||||||
|
{
|
||||||
|
return this->error_;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The HTTP status code if a response was received.
|
||||||
|
std::optional<int> status() const
|
||||||
|
{
|
||||||
|
return this->status_;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Formats the error.
|
||||||
|
/// If a reply is received, returns the HTTP status otherwise, the network error.
|
||||||
|
QString formatError() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QByteArray data_;
|
QByteArray data_;
|
||||||
int status_;
|
|
||||||
|
NetworkError error_;
|
||||||
|
std::optional<int> status_;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace chatterino
|
} // namespace chatterino
|
||||||
|
|
|
@ -27,7 +27,7 @@ void IvrApi::getSubage(QString userName, QString channelName,
|
||||||
})
|
})
|
||||||
.onError([failureCallback](auto result) {
|
.onError([failureCallback](auto result) {
|
||||||
qCWarning(chatterinoIvr)
|
qCWarning(chatterinoIvr)
|
||||||
<< "Failed IVR API Call!" << result.status()
|
<< "Failed IVR API Call!" << result.formatError()
|
||||||
<< QString(result.getData());
|
<< QString(result.getData());
|
||||||
failureCallback();
|
failureCallback();
|
||||||
})
|
})
|
||||||
|
@ -51,7 +51,7 @@ void IvrApi::getBulkEmoteSets(QString emoteSetList,
|
||||||
})
|
})
|
||||||
.onError([failureCallback](auto result) {
|
.onError([failureCallback](auto result) {
|
||||||
qCWarning(chatterinoIvr)
|
qCWarning(chatterinoIvr)
|
||||||
<< "Failed IVR API Call!" << result.status()
|
<< "Failed IVR API Call!" << result.formatError()
|
||||||
<< QString(result.getData());
|
<< QString(result.getData());
|
||||||
failureCallback();
|
failureCallback();
|
||||||
})
|
})
|
||||||
|
|
|
@ -217,17 +217,20 @@ void RecentMessagesApi::loadRecentMessages(const QString &channelName,
|
||||||
|
|
||||||
return Success;
|
return Success;
|
||||||
})
|
})
|
||||||
.onError([channelPtr, onError](NetworkResult result) {
|
.onError([channelPtr, onError](const NetworkResult &result) {
|
||||||
auto shared = channelPtr.lock();
|
auto shared = channelPtr.lock();
|
||||||
if (!shared)
|
if (!shared)
|
||||||
|
{
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
qCDebug(chatterinoRecentMessages)
|
qCDebug(chatterinoRecentMessages)
|
||||||
<< "Failed to load recent messages for" << shared->getName();
|
<< "Failed to load recent messages for" << shared->getName();
|
||||||
|
|
||||||
shared->addMessage(makeSystemMessage(
|
shared->addMessage(makeSystemMessage(
|
||||||
QString("Message history service unavailable (Error %1)")
|
QStringLiteral(
|
||||||
.arg(result.status())));
|
"Message history service unavailable (Error: %1)")
|
||||||
|
.arg(result.formatError())));
|
||||||
|
|
||||||
onError();
|
onError();
|
||||||
})
|
})
|
||||||
|
|
|
@ -259,23 +259,17 @@ void BttvEmotes::loadChannel(std::weak_ptr<Channel> channel,
|
||||||
shared->addMessage(
|
shared->addMessage(
|
||||||
makeSystemMessage(CHANNEL_HAS_NO_EMOTES));
|
makeSystemMessage(CHANNEL_HAS_NO_EMOTES));
|
||||||
}
|
}
|
||||||
else if (result.status() == NetworkResult::timedoutStatus)
|
|
||||||
{
|
|
||||||
// TODO: Auto retry in case of a timeout, with a delay
|
|
||||||
qCWarning(chatterinoBttv)
|
|
||||||
<< "Fetching BTTV emotes for channel" << channelId
|
|
||||||
<< "failed due to timeout";
|
|
||||||
shared->addMessage(makeSystemMessage(
|
|
||||||
"Failed to fetch BetterTTV channel emotes. (timed out)"));
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
// TODO: Auto retry in case of a timeout, with a delay
|
||||||
|
auto errorString = result.formatError();
|
||||||
qCWarning(chatterinoBttv)
|
qCWarning(chatterinoBttv)
|
||||||
<< "Error fetching BTTV emotes for channel" << channelId
|
<< "Error fetching BTTV emotes for channel" << channelId
|
||||||
<< ", error" << result.status();
|
<< ", error" << errorString;
|
||||||
shared->addMessage(
|
shared->addMessage(makeSystemMessage(
|
||||||
makeSystemMessage("Failed to fetch BetterTTV channel "
|
QStringLiteral("Failed to fetch BetterTTV channel "
|
||||||
"emotes. (unknown error)"));
|
"emotes. (Error: %1)")
|
||||||
|
.arg(errorString)));
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.execute();
|
.execute();
|
||||||
|
|
|
@ -273,24 +273,17 @@ void FfzEmotes::loadChannel(
|
||||||
makeSystemMessage(CHANNEL_HAS_NO_EMOTES));
|
makeSystemMessage(CHANNEL_HAS_NO_EMOTES));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (result.status() == NetworkResult::timedoutStatus)
|
|
||||||
{
|
|
||||||
// TODO: Auto retry in case of a timeout, with a delay
|
|
||||||
qCWarning(chatterinoFfzemotes)
|
|
||||||
<< "Fetching FFZ emotes for channel" << channelID
|
|
||||||
<< "failed due to timeout";
|
|
||||||
shared->addMessage(
|
|
||||||
makeSystemMessage("Failed to fetch FrankerFaceZ channel "
|
|
||||||
"emotes. (timed out)"));
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
// TODO: Auto retry in case of a timeout, with a delay
|
||||||
|
auto errorString = result.formatError();
|
||||||
qCWarning(chatterinoFfzemotes)
|
qCWarning(chatterinoFfzemotes)
|
||||||
<< "Error fetching FFZ emotes for channel" << channelID
|
<< "Error fetching FFZ emotes for channel" << channelID
|
||||||
<< ", error" << result.status();
|
<< ", error" << errorString;
|
||||||
shared->addMessage(
|
shared->addMessage(makeSystemMessage(
|
||||||
makeSystemMessage("Failed to fetch FrankerFaceZ channel "
|
QStringLiteral("Failed to fetch FrankerFaceZ channel "
|
||||||
"emotes. (unknown error)"));
|
"emotes. (Error: %1)")
|
||||||
|
.arg(errorString)));
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.execute();
|
.execute();
|
||||||
|
|
|
@ -386,23 +386,17 @@ void SeventvEmotes::loadChannelEmotes(
|
||||||
makeSystemMessage(CHANNEL_HAS_NO_EMOTES));
|
makeSystemMessage(CHANNEL_HAS_NO_EMOTES));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (result.status() == NetworkResult::timedoutStatus)
|
|
||||||
{
|
|
||||||
// TODO: Auto retry in case of a timeout, with a delay
|
|
||||||
qCWarning(chatterinoSeventv)
|
|
||||||
<< "Fetching 7TV emotes for channel" << channelId
|
|
||||||
<< "failed due to timeout";
|
|
||||||
shared->addMessage(makeSystemMessage(
|
|
||||||
"Failed to fetch 7TV channel emotes. (timed out)"));
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
// TODO: Auto retry in case of a timeout, with a delay
|
||||||
|
auto errorString = result.formatError();
|
||||||
qCWarning(chatterinoSeventv)
|
qCWarning(chatterinoSeventv)
|
||||||
<< "Error fetching 7TV emotes for channel" << channelId
|
<< "Error fetching 7TV emotes for channel" << channelId
|
||||||
<< ", error" << result.status();
|
<< ", error" << errorString;
|
||||||
shared->addMessage(
|
shared->addMessage(makeSystemMessage(
|
||||||
makeSystemMessage("Failed to fetch 7TV channel "
|
QStringLiteral("Failed to fetch 7TV channel "
|
||||||
"emotes. (unknown error)"));
|
"emotes. (Error: %1)")
|
||||||
|
.arg(errorString)));
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.execute();
|
.execute();
|
||||||
|
@ -502,14 +496,7 @@ void SeventvEmotes::getEmoteSet(
|
||||||
})
|
})
|
||||||
.onError([emoteSetId, callback = std::move(errorCallback)](
|
.onError([emoteSetId, callback = std::move(errorCallback)](
|
||||||
const NetworkResult &result) {
|
const NetworkResult &result) {
|
||||||
if (result.status() == NetworkResult::timedoutStatus)
|
callback(result.formatError());
|
||||||
{
|
|
||||||
callback("timed out");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
callback(QString("status: %1").arg(result.status()));
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
.execute();
|
.execute();
|
||||||
}
|
}
|
||||||
|
|
|
@ -390,7 +390,7 @@ void Helix::createClip(QString channelId,
|
||||||
return Success;
|
return Success;
|
||||||
})
|
})
|
||||||
.onError([failureCallback](auto result) {
|
.onError([failureCallback](auto result) {
|
||||||
switch (result.status())
|
switch (result.status().value_or(0))
|
||||||
{
|
{
|
||||||
case 503: {
|
case 503: {
|
||||||
// Channel has disabled clip-creation, or channel has made cliops only creatable by followers and the user is not a follower (or subscriber)
|
// Channel has disabled clip-creation, or channel has made cliops only creatable by followers and the user is not a follower (or subscriber)
|
||||||
|
@ -406,7 +406,7 @@ void Helix::createClip(QString channelId,
|
||||||
|
|
||||||
default: {
|
default: {
|
||||||
qCDebug(chatterinoTwitch)
|
qCDebug(chatterinoTwitch)
|
||||||
<< "Failed to create a clip: " << result.status()
|
<< "Failed to create a clip: " << result.formatError()
|
||||||
<< result.getData();
|
<< result.getData();
|
||||||
failureCallback(HelixClipError::Unknown);
|
failureCallback(HelixClipError::Unknown);
|
||||||
}
|
}
|
||||||
|
@ -477,7 +477,7 @@ void Helix::createStreamMarker(
|
||||||
return Success;
|
return Success;
|
||||||
})
|
})
|
||||||
.onError([failureCallback](NetworkResult result) {
|
.onError([failureCallback](NetworkResult result) {
|
||||||
switch (result.status())
|
switch (result.status().value_or(0))
|
||||||
{
|
{
|
||||||
case 403: {
|
case 403: {
|
||||||
// User isn't a Channel Editor, so he can't create markers
|
// User isn't a Channel Editor, so he can't create markers
|
||||||
|
@ -495,7 +495,7 @@ void Helix::createStreamMarker(
|
||||||
default: {
|
default: {
|
||||||
qCDebug(chatterinoTwitch)
|
qCDebug(chatterinoTwitch)
|
||||||
<< "Failed to create a stream marker: "
|
<< "Failed to create a stream marker: "
|
||||||
<< result.status() << result.getData();
|
<< result.formatError() << result.getData();
|
||||||
failureCallback(HelixStreamMarkerError::Unknown);
|
failureCallback(HelixStreamMarkerError::Unknown);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -638,7 +638,7 @@ void Helix::manageAutoModMessages(
|
||||||
return Success;
|
return Success;
|
||||||
})
|
})
|
||||||
.onError([failureCallback, msgID, action](NetworkResult result) {
|
.onError([failureCallback, msgID, action](NetworkResult result) {
|
||||||
switch (result.status())
|
switch (result.status().value_or(0))
|
||||||
{
|
{
|
||||||
case 400: {
|
case 400: {
|
||||||
// Message was already processed
|
// Message was already processed
|
||||||
|
@ -670,7 +670,7 @@ void Helix::manageAutoModMessages(
|
||||||
default: {
|
default: {
|
||||||
qCDebug(chatterinoTwitch)
|
qCDebug(chatterinoTwitch)
|
||||||
<< "Failed to manage automod message: " << action
|
<< "Failed to manage automod message: " << action
|
||||||
<< msgID << result.status() << result.getData();
|
<< msgID << result.formatError() << result.getData();
|
||||||
failureCallback(HelixAutoModMessageError::Unknown);
|
failureCallback(HelixAutoModMessageError::Unknown);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -712,7 +712,7 @@ void Helix::getCheermotes(
|
||||||
.onError([broadcasterId, failureCallback](NetworkResult result) {
|
.onError([broadcasterId, failureCallback](NetworkResult result) {
|
||||||
qCDebug(chatterinoTwitch)
|
qCDebug(chatterinoTwitch)
|
||||||
<< "Failed to get cheermotes(broadcaster_id=" << broadcasterId
|
<< "Failed to get cheermotes(broadcaster_id=" << broadcasterId
|
||||||
<< "): " << result.status() << result.getData();
|
<< "): " << result.formatError() << result.getData();
|
||||||
failureCallback();
|
failureCallback();
|
||||||
})
|
})
|
||||||
.execute();
|
.execute();
|
||||||
|
@ -806,17 +806,24 @@ void Helix::updateUserChatColor(
|
||||||
{
|
{
|
||||||
qCWarning(chatterinoTwitch)
|
qCWarning(chatterinoTwitch)
|
||||||
<< "Success result for updating chat color was"
|
<< "Success result for updating chat color was"
|
||||||
<< result.status() << "but we only expected it to be 204";
|
<< result.formatError()
|
||||||
|
<< "but we only expected it to be 204";
|
||||||
}
|
}
|
||||||
|
|
||||||
successCallback();
|
successCallback();
|
||||||
return Success;
|
return Success;
|
||||||
})
|
})
|
||||||
.onError([failureCallback](auto result) {
|
.onError([failureCallback](const auto &result) -> void {
|
||||||
|
if (!result.status())
|
||||||
|
{
|
||||||
|
failureCallback(Error::Unknown, result.formatError());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
auto obj = result.parseJson();
|
auto obj = result.parseJson();
|
||||||
auto message = obj.value("message").toString();
|
auto message = obj.value("message").toString();
|
||||||
|
|
||||||
switch (result.status())
|
switch (*result.status())
|
||||||
{
|
{
|
||||||
case 400: {
|
case 400: {
|
||||||
if (message.startsWith("invalid color",
|
if (message.startsWith("invalid color",
|
||||||
|
@ -849,7 +856,7 @@ void Helix::updateUserChatColor(
|
||||||
default: {
|
default: {
|
||||||
qCDebug(chatterinoTwitch)
|
qCDebug(chatterinoTwitch)
|
||||||
<< "Unhandled error changing user color:"
|
<< "Unhandled error changing user color:"
|
||||||
<< result.status() << result.getData() << obj;
|
<< result.formatError() << result.getData() << obj;
|
||||||
failureCallback(Error::Unknown, message);
|
failureCallback(Error::Unknown, message);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -882,17 +889,24 @@ void Helix::deleteChatMessages(
|
||||||
{
|
{
|
||||||
qCWarning(chatterinoTwitch)
|
qCWarning(chatterinoTwitch)
|
||||||
<< "Success result for deleting chat messages was"
|
<< "Success result for deleting chat messages was"
|
||||||
<< result.status() << "but we only expected it to be 204";
|
<< result.formatError()
|
||||||
|
<< "but we only expected it to be 204";
|
||||||
}
|
}
|
||||||
|
|
||||||
successCallback();
|
successCallback();
|
||||||
return Success;
|
return Success;
|
||||||
})
|
})
|
||||||
.onError([failureCallback](auto result) {
|
.onError([failureCallback](const auto &result) -> void {
|
||||||
|
if (!result.status())
|
||||||
|
{
|
||||||
|
failureCallback(Error::Unknown, result.formatError());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
auto obj = result.parseJson();
|
auto obj = result.parseJson();
|
||||||
auto message = obj.value("message").toString();
|
auto message = obj.value("message").toString();
|
||||||
|
|
||||||
switch (result.status())
|
switch (*result.status())
|
||||||
{
|
{
|
||||||
case 404: {
|
case 404: {
|
||||||
// A 404 on this endpoint means message id is invalid or unable to be deleted.
|
// A 404 on this endpoint means message id is invalid or unable to be deleted.
|
||||||
|
@ -934,7 +948,7 @@ void Helix::deleteChatMessages(
|
||||||
default: {
|
default: {
|
||||||
qCDebug(chatterinoTwitch)
|
qCDebug(chatterinoTwitch)
|
||||||
<< "Unhandled error deleting chat messages:"
|
<< "Unhandled error deleting chat messages:"
|
||||||
<< result.status() << result.getData() << obj;
|
<< result.formatError() << result.getData() << obj;
|
||||||
failureCallback(Error::Unknown, message);
|
failureCallback(Error::Unknown, message);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -960,17 +974,24 @@ void Helix::addChannelModerator(
|
||||||
{
|
{
|
||||||
qCWarning(chatterinoTwitch)
|
qCWarning(chatterinoTwitch)
|
||||||
<< "Success result for adding a moderator was"
|
<< "Success result for adding a moderator was"
|
||||||
<< result.status() << "but we only expected it to be 204";
|
<< result.formatError()
|
||||||
|
<< "but we only expected it to be 204";
|
||||||
}
|
}
|
||||||
|
|
||||||
successCallback();
|
successCallback();
|
||||||
return Success;
|
return Success;
|
||||||
})
|
})
|
||||||
.onError([failureCallback](auto result) {
|
.onError([failureCallback](const auto &result) -> void {
|
||||||
|
if (!result.status())
|
||||||
|
{
|
||||||
|
failureCallback(Error::Unknown, result.formatError());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
auto obj = result.parseJson();
|
auto obj = result.parseJson();
|
||||||
auto message = obj.value("message").toString();
|
auto message = obj.value("message").toString();
|
||||||
|
|
||||||
switch (result.status())
|
switch (*result.status())
|
||||||
{
|
{
|
||||||
case 401: {
|
case 401: {
|
||||||
if (message.startsWith("Missing scope",
|
if (message.startsWith("Missing scope",
|
||||||
|
@ -1022,7 +1043,7 @@ void Helix::addChannelModerator(
|
||||||
default: {
|
default: {
|
||||||
qCDebug(chatterinoTwitch)
|
qCDebug(chatterinoTwitch)
|
||||||
<< "Unhandled error adding channel moderator:"
|
<< "Unhandled error adding channel moderator:"
|
||||||
<< result.status() << result.getData() << obj;
|
<< result.formatError() << result.getData() << obj;
|
||||||
failureCallback(Error::Unknown, message);
|
failureCallback(Error::Unknown, message);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -1048,17 +1069,24 @@ void Helix::removeChannelModerator(
|
||||||
{
|
{
|
||||||
qCWarning(chatterinoTwitch)
|
qCWarning(chatterinoTwitch)
|
||||||
<< "Success result for unmodding user was"
|
<< "Success result for unmodding user was"
|
||||||
<< result.status() << "but we only expected it to be 204";
|
<< result.formatError()
|
||||||
|
<< "but we only expected it to be 204";
|
||||||
}
|
}
|
||||||
|
|
||||||
successCallback();
|
successCallback();
|
||||||
return Success;
|
return Success;
|
||||||
})
|
})
|
||||||
.onError([failureCallback](auto result) {
|
.onError([failureCallback](const auto &result) -> void {
|
||||||
|
if (!result.status())
|
||||||
|
{
|
||||||
|
failureCallback(Error::Unknown, result.formatError());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
auto obj = result.parseJson();
|
auto obj = result.parseJson();
|
||||||
auto message = obj.value("message").toString();
|
auto message = obj.value("message").toString();
|
||||||
|
|
||||||
switch (result.status())
|
switch (*result.status())
|
||||||
{
|
{
|
||||||
case 400: {
|
case 400: {
|
||||||
if (message.compare("user is not a mod",
|
if (message.compare("user is not a mod",
|
||||||
|
@ -1100,8 +1128,8 @@ void Helix::removeChannelModerator(
|
||||||
|
|
||||||
default: {
|
default: {
|
||||||
qCDebug(chatterinoTwitch)
|
qCDebug(chatterinoTwitch)
|
||||||
<< "Unhandled error unmodding user:" << result.status()
|
<< "Unhandled error unmodding user:"
|
||||||
<< result.getData() << obj;
|
<< result.formatError() << result.getData() << obj;
|
||||||
failureCallback(Error::Unknown, message);
|
failureCallback(Error::Unknown, message);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -1135,17 +1163,24 @@ void Helix::sendChatAnnouncement(
|
||||||
{
|
{
|
||||||
qCWarning(chatterinoTwitch)
|
qCWarning(chatterinoTwitch)
|
||||||
<< "Success result for sending an announcement was"
|
<< "Success result for sending an announcement was"
|
||||||
<< result.status() << "but we only expected it to be 204";
|
<< result.formatError()
|
||||||
|
<< "but we only expected it to be 204";
|
||||||
}
|
}
|
||||||
|
|
||||||
successCallback();
|
successCallback();
|
||||||
return Success;
|
return Success;
|
||||||
})
|
})
|
||||||
.onError([failureCallback](auto result) {
|
.onError([failureCallback](const auto &result) -> void {
|
||||||
|
if (!result.status())
|
||||||
|
{
|
||||||
|
failureCallback(Error::Unknown, result.formatError());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
auto obj = result.parseJson();
|
auto obj = result.parseJson();
|
||||||
auto message = obj.value("message").toString();
|
auto message = obj.value("message").toString();
|
||||||
|
|
||||||
switch (result.status())
|
switch (*result.status())
|
||||||
{
|
{
|
||||||
case 400: {
|
case 400: {
|
||||||
// These errors are generally well formatted, so we just forward them.
|
// These errors are generally well formatted, so we just forward them.
|
||||||
|
@ -1178,7 +1213,7 @@ void Helix::sendChatAnnouncement(
|
||||||
default: {
|
default: {
|
||||||
qCDebug(chatterinoTwitch)
|
qCDebug(chatterinoTwitch)
|
||||||
<< "Unhandled error sending an announcement:"
|
<< "Unhandled error sending an announcement:"
|
||||||
<< result.status() << result.getData() << obj;
|
<< result.formatError() << result.getData() << obj;
|
||||||
failureCallback(Error::Unknown, message);
|
failureCallback(Error::Unknown, message);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -1204,17 +1239,24 @@ void Helix::addChannelVIP(
|
||||||
{
|
{
|
||||||
qCWarning(chatterinoTwitch)
|
qCWarning(chatterinoTwitch)
|
||||||
<< "Success result for adding channel VIP was"
|
<< "Success result for adding channel VIP was"
|
||||||
<< result.status() << "but we only expected it to be 204";
|
<< result.formatError()
|
||||||
|
<< "but we only expected it to be 204";
|
||||||
}
|
}
|
||||||
|
|
||||||
successCallback();
|
successCallback();
|
||||||
return Success;
|
return Success;
|
||||||
})
|
})
|
||||||
.onError([failureCallback](auto result) {
|
.onError([failureCallback](const auto &result) -> void {
|
||||||
|
if (!result.status())
|
||||||
|
{
|
||||||
|
failureCallback(Error::Unknown, result.formatError());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
auto obj = result.parseJson();
|
auto obj = result.parseJson();
|
||||||
auto message = obj.value("message").toString();
|
auto message = obj.value("message").toString();
|
||||||
|
|
||||||
switch (result.status())
|
switch (*result.status())
|
||||||
{
|
{
|
||||||
case 400:
|
case 400:
|
||||||
case 409:
|
case 409:
|
||||||
|
@ -1256,7 +1298,7 @@ void Helix::addChannelVIP(
|
||||||
default: {
|
default: {
|
||||||
qCDebug(chatterinoTwitch)
|
qCDebug(chatterinoTwitch)
|
||||||
<< "Unhandled error adding channel VIP:"
|
<< "Unhandled error adding channel VIP:"
|
||||||
<< result.status() << result.getData() << obj;
|
<< result.formatError() << result.getData() << obj;
|
||||||
failureCallback(Error::Unknown, message);
|
failureCallback(Error::Unknown, message);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -1282,17 +1324,24 @@ void Helix::removeChannelVIP(
|
||||||
{
|
{
|
||||||
qCWarning(chatterinoTwitch)
|
qCWarning(chatterinoTwitch)
|
||||||
<< "Success result for removing channel VIP was"
|
<< "Success result for removing channel VIP was"
|
||||||
<< result.status() << "but we only expected it to be 204";
|
<< result.formatError()
|
||||||
|
<< "but we only expected it to be 204";
|
||||||
}
|
}
|
||||||
|
|
||||||
successCallback();
|
successCallback();
|
||||||
return Success;
|
return Success;
|
||||||
})
|
})
|
||||||
.onError([failureCallback](auto result) {
|
.onError([failureCallback](const auto &result) -> void {
|
||||||
|
if (!result.status())
|
||||||
|
{
|
||||||
|
failureCallback(Error::Unknown, result.formatError());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
auto obj = result.parseJson();
|
auto obj = result.parseJson();
|
||||||
auto message = obj.value("message").toString();
|
auto message = obj.value("message").toString();
|
||||||
|
|
||||||
switch (result.status())
|
switch (*result.status())
|
||||||
{
|
{
|
||||||
case 400:
|
case 400:
|
||||||
case 409:
|
case 409:
|
||||||
|
@ -1333,7 +1382,7 @@ void Helix::removeChannelVIP(
|
||||||
default: {
|
default: {
|
||||||
qCDebug(chatterinoTwitch)
|
qCDebug(chatterinoTwitch)
|
||||||
<< "Unhandled error removing channel VIP:"
|
<< "Unhandled error removing channel VIP:"
|
||||||
<< result.status() << result.getData() << obj;
|
<< result.formatError() << result.getData() << obj;
|
||||||
failureCallback(Error::Unknown, message);
|
failureCallback(Error::Unknown, message);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -1371,17 +1420,24 @@ void Helix::unbanUser(
|
||||||
{
|
{
|
||||||
qCWarning(chatterinoTwitch)
|
qCWarning(chatterinoTwitch)
|
||||||
<< "Success result for unbanning user was"
|
<< "Success result for unbanning user was"
|
||||||
<< result.status() << "but we only expected it to be 204";
|
<< result.formatError()
|
||||||
|
<< "but we only expected it to be 204";
|
||||||
}
|
}
|
||||||
|
|
||||||
successCallback();
|
successCallback();
|
||||||
return Success;
|
return Success;
|
||||||
})
|
})
|
||||||
.onError([failureCallback](auto result) {
|
.onError([failureCallback](const auto &result) -> void {
|
||||||
|
if (!result.status())
|
||||||
|
{
|
||||||
|
failureCallback(Error::Unknown, result.formatError());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
auto obj = result.parseJson();
|
auto obj = result.parseJson();
|
||||||
auto message = obj.value("message").toString();
|
auto message = obj.value("message").toString();
|
||||||
|
|
||||||
switch (result.status())
|
switch (*result.status())
|
||||||
{
|
{
|
||||||
case 400: {
|
case 400: {
|
||||||
if (message.startsWith("The user in the user_id query "
|
if (message.startsWith("The user in the user_id query "
|
||||||
|
@ -1437,8 +1493,8 @@ void Helix::unbanUser(
|
||||||
|
|
||||||
default: {
|
default: {
|
||||||
qCDebug(chatterinoTwitch)
|
qCDebug(chatterinoTwitch)
|
||||||
<< "Unhandled error unbanning user:" << result.status()
|
<< "Unhandled error unbanning user:"
|
||||||
<< result.getData() << obj;
|
<< result.formatError() << result.getData() << obj;
|
||||||
failureCallback(Error::Unknown, message);
|
failureCallback(Error::Unknown, message);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -1476,11 +1532,17 @@ void Helix::startRaid(
|
||||||
successCallback();
|
successCallback();
|
||||||
return Success;
|
return Success;
|
||||||
})
|
})
|
||||||
.onError([failureCallback](auto result) {
|
.onError([failureCallback](const auto &result) -> void {
|
||||||
|
if (!result.status())
|
||||||
|
{
|
||||||
|
failureCallback(Error::Unknown, result.formatError());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
auto obj = result.parseJson();
|
auto obj = result.parseJson();
|
||||||
auto message = obj.value("message").toString();
|
auto message = obj.value("message").toString();
|
||||||
|
|
||||||
switch (result.status())
|
switch (*result.status())
|
||||||
{
|
{
|
||||||
case 400: {
|
case 400: {
|
||||||
if (message.compare("The IDs in from_broadcaster_id and "
|
if (message.compare("The IDs in from_broadcaster_id and "
|
||||||
|
@ -1531,7 +1593,7 @@ void Helix::startRaid(
|
||||||
default: {
|
default: {
|
||||||
qCDebug(chatterinoTwitch)
|
qCDebug(chatterinoTwitch)
|
||||||
<< "Unhandled error while starting a raid:"
|
<< "Unhandled error while starting a raid:"
|
||||||
<< result.status() << result.getData() << obj;
|
<< result.formatError() << result.getData() << obj;
|
||||||
failureCallback(Error::Unknown, message);
|
failureCallback(Error::Unknown, message);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -1556,17 +1618,24 @@ void Helix::cancelRaid(
|
||||||
{
|
{
|
||||||
qCWarning(chatterinoTwitch)
|
qCWarning(chatterinoTwitch)
|
||||||
<< "Success result for canceling the raid was"
|
<< "Success result for canceling the raid was"
|
||||||
<< result.status() << "but we only expected it to be 204";
|
<< result.formatError()
|
||||||
|
<< "but we only expected it to be 204";
|
||||||
}
|
}
|
||||||
|
|
||||||
successCallback();
|
successCallback();
|
||||||
return Success;
|
return Success;
|
||||||
})
|
})
|
||||||
.onError([failureCallback](auto result) {
|
.onError([failureCallback](const auto &result) -> void {
|
||||||
|
if (!result.status())
|
||||||
|
{
|
||||||
|
failureCallback(Error::Unknown, result.formatError());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
auto obj = result.parseJson();
|
auto obj = result.parseJson();
|
||||||
auto message = obj.value("message").toString();
|
auto message = obj.value("message").toString();
|
||||||
|
|
||||||
switch (result.status())
|
switch (*result.status())
|
||||||
{
|
{
|
||||||
case 401: {
|
case 401: {
|
||||||
if (message.startsWith("Missing scope",
|
if (message.startsWith("Missing scope",
|
||||||
|
@ -1603,7 +1672,7 @@ void Helix::cancelRaid(
|
||||||
default: {
|
default: {
|
||||||
qCDebug(chatterinoTwitch)
|
qCDebug(chatterinoTwitch)
|
||||||
<< "Unhandled error while canceling the raid:"
|
<< "Unhandled error while canceling the raid:"
|
||||||
<< result.status() << result.getData() << obj;
|
<< result.formatError() << result.getData() << obj;
|
||||||
failureCallback(Error::Unknown, message);
|
failureCallback(Error::Unknown, message);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -1717,18 +1786,24 @@ void Helix::updateChatSettings(
|
||||||
{
|
{
|
||||||
qCWarning(chatterinoTwitch)
|
qCWarning(chatterinoTwitch)
|
||||||
<< "Success result for updating chat settings was"
|
<< "Success result for updating chat settings was"
|
||||||
<< result.status() << "but we expected it to be 200";
|
<< result.formatError() << "but we expected it to be 200";
|
||||||
}
|
}
|
||||||
auto response = result.parseJson();
|
auto response = result.parseJson();
|
||||||
successCallback(HelixChatSettings(
|
successCallback(HelixChatSettings(
|
||||||
response.value("data").toArray().first().toObject()));
|
response.value("data").toArray().first().toObject()));
|
||||||
return Success;
|
return Success;
|
||||||
})
|
})
|
||||||
.onError([failureCallback](auto result) {
|
.onError([failureCallback](const auto &result) -> void {
|
||||||
|
if (!result.status())
|
||||||
|
{
|
||||||
|
failureCallback(Error::Unknown, result.formatError());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
auto obj = result.parseJson();
|
auto obj = result.parseJson();
|
||||||
auto message = obj.value("message").toString();
|
auto message = obj.value("message").toString();
|
||||||
|
|
||||||
switch (result.status())
|
switch (*result.status())
|
||||||
{
|
{
|
||||||
case 400: {
|
case 400: {
|
||||||
if (message.contains("must be in the range"))
|
if (message.contains("must be in the range"))
|
||||||
|
@ -1775,7 +1850,7 @@ void Helix::updateChatSettings(
|
||||||
default: {
|
default: {
|
||||||
qCDebug(chatterinoTwitch)
|
qCDebug(chatterinoTwitch)
|
||||||
<< "Unhandled error updating chat settings:"
|
<< "Unhandled error updating chat settings:"
|
||||||
<< result.status() << result.getData() << obj;
|
<< result.formatError() << result.getData() << obj;
|
||||||
failureCallback(Error::Unknown, message);
|
failureCallback(Error::Unknown, message);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -1840,18 +1915,24 @@ void Helix::fetchChatters(
|
||||||
{
|
{
|
||||||
qCWarning(chatterinoTwitch)
|
qCWarning(chatterinoTwitch)
|
||||||
<< "Success result for getting chatters was "
|
<< "Success result for getting chatters was "
|
||||||
<< result.status() << "but we expected it to be 200";
|
<< result.formatError() << "but we expected it to be 200";
|
||||||
}
|
}
|
||||||
|
|
||||||
auto response = result.parseJson();
|
auto response = result.parseJson();
|
||||||
successCallback(HelixChatters(response));
|
successCallback(HelixChatters(response));
|
||||||
return Success;
|
return Success;
|
||||||
})
|
})
|
||||||
.onError([failureCallback](auto result) {
|
.onError([failureCallback](const auto &result) -> void {
|
||||||
|
if (!result.status())
|
||||||
|
{
|
||||||
|
failureCallback(Error::Unknown, result.formatError());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
auto obj = result.parseJson();
|
auto obj = result.parseJson();
|
||||||
auto message = obj.value("message").toString();
|
auto message = obj.value("message").toString();
|
||||||
|
|
||||||
switch (result.status())
|
switch (*result.status())
|
||||||
{
|
{
|
||||||
case 400: {
|
case 400: {
|
||||||
failureCallback(Error::Forwarded, message);
|
failureCallback(Error::Forwarded, message);
|
||||||
|
@ -1882,7 +1963,7 @@ void Helix::fetchChatters(
|
||||||
|
|
||||||
default: {
|
default: {
|
||||||
qCDebug(chatterinoTwitch)
|
qCDebug(chatterinoTwitch)
|
||||||
<< "Unhandled error data:" << result.status()
|
<< "Unhandled error data:" << result.formatError()
|
||||||
<< result.getData() << obj;
|
<< result.getData() << obj;
|
||||||
failureCallback(Error::Unknown, message);
|
failureCallback(Error::Unknown, message);
|
||||||
}
|
}
|
||||||
|
@ -1949,18 +2030,24 @@ void Helix::fetchModerators(
|
||||||
{
|
{
|
||||||
qCWarning(chatterinoTwitch)
|
qCWarning(chatterinoTwitch)
|
||||||
<< "Success result for getting moderators was "
|
<< "Success result for getting moderators was "
|
||||||
<< result.status() << "but we expected it to be 200";
|
<< result.formatError() << "but we expected it to be 200";
|
||||||
}
|
}
|
||||||
|
|
||||||
auto response = result.parseJson();
|
auto response = result.parseJson();
|
||||||
successCallback(HelixModerators(response));
|
successCallback(HelixModerators(response));
|
||||||
return Success;
|
return Success;
|
||||||
})
|
})
|
||||||
.onError([failureCallback](auto result) {
|
.onError([failureCallback](const auto &result) -> void {
|
||||||
|
if (!result.status())
|
||||||
|
{
|
||||||
|
failureCallback(Error::Unknown, result.formatError());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
auto obj = result.parseJson();
|
auto obj = result.parseJson();
|
||||||
auto message = obj.value("message").toString();
|
auto message = obj.value("message").toString();
|
||||||
|
|
||||||
switch (result.status())
|
switch (*result.status())
|
||||||
{
|
{
|
||||||
case 400: {
|
case 400: {
|
||||||
failureCallback(Error::Forwarded, message);
|
failureCallback(Error::Forwarded, message);
|
||||||
|
@ -1991,7 +2078,7 @@ void Helix::fetchModerators(
|
||||||
|
|
||||||
default: {
|
default: {
|
||||||
qCDebug(chatterinoTwitch)
|
qCDebug(chatterinoTwitch)
|
||||||
<< "Unhandled error data:" << result.status()
|
<< "Unhandled error data:" << result.formatError()
|
||||||
<< result.getData() << obj;
|
<< result.getData() << obj;
|
||||||
failureCallback(Error::Unknown, message);
|
failureCallback(Error::Unknown, message);
|
||||||
}
|
}
|
||||||
|
@ -2035,17 +2122,23 @@ void Helix::banUser(QString broadcasterID, QString moderatorID, QString userID,
|
||||||
{
|
{
|
||||||
qCWarning(chatterinoTwitch)
|
qCWarning(chatterinoTwitch)
|
||||||
<< "Success result for banning a user was"
|
<< "Success result for banning a user was"
|
||||||
<< result.status() << "but we expected it to be 200";
|
<< result.formatError() << "but we expected it to be 200";
|
||||||
}
|
}
|
||||||
// we don't care about the response
|
// we don't care about the response
|
||||||
successCallback();
|
successCallback();
|
||||||
return Success;
|
return Success;
|
||||||
})
|
})
|
||||||
.onError([failureCallback](auto result) {
|
.onError([failureCallback](const auto &result) -> void {
|
||||||
|
if (!result.status())
|
||||||
|
{
|
||||||
|
failureCallback(Error::Unknown, result.formatError());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
auto obj = result.parseJson();
|
auto obj = result.parseJson();
|
||||||
auto message = obj.value("message").toString();
|
auto message = obj.value("message").toString();
|
||||||
|
|
||||||
switch (result.status())
|
switch (*result.status())
|
||||||
{
|
{
|
||||||
case 400: {
|
case 400: {
|
||||||
if (message.startsWith("The user specified in the user_id "
|
if (message.startsWith("The user specified in the user_id "
|
||||||
|
@ -2099,8 +2192,8 @@ void Helix::banUser(QString broadcasterID, QString moderatorID, QString userID,
|
||||||
|
|
||||||
default: {
|
default: {
|
||||||
qCDebug(chatterinoTwitch)
|
qCDebug(chatterinoTwitch)
|
||||||
<< "Unhandled error banning user:" << result.status()
|
<< "Unhandled error banning user:"
|
||||||
<< result.getData() << obj;
|
<< result.formatError() << result.getData() << obj;
|
||||||
failureCallback(Error::Unknown, message);
|
failureCallback(Error::Unknown, message);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -2132,17 +2225,23 @@ void Helix::sendWhisper(
|
||||||
{
|
{
|
||||||
qCWarning(chatterinoTwitch)
|
qCWarning(chatterinoTwitch)
|
||||||
<< "Success result for sending a whisper was"
|
<< "Success result for sending a whisper was"
|
||||||
<< result.status() << "but we expected it to be 204";
|
<< result.formatError() << "but we expected it to be 204";
|
||||||
}
|
}
|
||||||
// we don't care about the response
|
// we don't care about the response
|
||||||
successCallback();
|
successCallback();
|
||||||
return Success;
|
return Success;
|
||||||
})
|
})
|
||||||
.onError([failureCallback](auto result) {
|
.onError([failureCallback](const auto &result) -> void {
|
||||||
|
if (!result.status())
|
||||||
|
{
|
||||||
|
failureCallback(Error::Unknown, result.formatError());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
auto obj = result.parseJson();
|
auto obj = result.parseJson();
|
||||||
auto message = obj.value("message").toString();
|
auto message = obj.value("message").toString();
|
||||||
|
|
||||||
switch (result.status())
|
switch (*result.status())
|
||||||
{
|
{
|
||||||
case 400: {
|
case 400: {
|
||||||
if (message.startsWith("A user cannot whisper themself",
|
if (message.startsWith("A user cannot whisper themself",
|
||||||
|
@ -2203,8 +2302,8 @@ void Helix::sendWhisper(
|
||||||
|
|
||||||
default: {
|
default: {
|
||||||
qCDebug(chatterinoTwitch)
|
qCDebug(chatterinoTwitch)
|
||||||
<< "Unhandled error banning user:" << result.status()
|
<< "Unhandled error banning user:"
|
||||||
<< result.getData() << obj;
|
<< result.formatError() << result.getData() << obj;
|
||||||
failureCallback(Error::Unknown, message);
|
failureCallback(Error::Unknown, message);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -2274,8 +2373,8 @@ void Helix::getChannelVIPs(
|
||||||
if (result.status() != 200)
|
if (result.status() != 200)
|
||||||
{
|
{
|
||||||
qCWarning(chatterinoTwitch)
|
qCWarning(chatterinoTwitch)
|
||||||
<< "Success result for getting VIPs was" << result.status()
|
<< "Success result for getting VIPs was"
|
||||||
<< "but we expected it to be 200";
|
<< result.formatError() << "but we expected it to be 200";
|
||||||
}
|
}
|
||||||
|
|
||||||
auto response = result.parseJson();
|
auto response = result.parseJson();
|
||||||
|
@ -2289,11 +2388,17 @@ void Helix::getChannelVIPs(
|
||||||
successCallback(channelVips);
|
successCallback(channelVips);
|
||||||
return Success;
|
return Success;
|
||||||
})
|
})
|
||||||
.onError([failureCallback](auto result) {
|
.onError([failureCallback](const auto &result) -> void {
|
||||||
|
if (!result.status())
|
||||||
|
{
|
||||||
|
failureCallback(Error::Unknown, result.formatError());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
auto obj = result.parseJson();
|
auto obj = result.parseJson();
|
||||||
auto message = obj.value("message").toString();
|
auto message = obj.value("message").toString();
|
||||||
|
|
||||||
switch (result.status())
|
switch (*result.status())
|
||||||
{
|
{
|
||||||
case 400: {
|
case 400: {
|
||||||
failureCallback(Error::Forwarded, message);
|
failureCallback(Error::Forwarded, message);
|
||||||
|
@ -2333,8 +2438,8 @@ void Helix::getChannelVIPs(
|
||||||
|
|
||||||
default: {
|
default: {
|
||||||
qCDebug(chatterinoTwitch)
|
qCDebug(chatterinoTwitch)
|
||||||
<< "Unhandled error listing VIPs:" << result.status()
|
<< "Unhandled error listing VIPs:"
|
||||||
<< result.getData() << obj;
|
<< result.formatError() << result.getData() << obj;
|
||||||
failureCallback(Error::Unknown, message);
|
failureCallback(Error::Unknown, message);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -2370,11 +2475,17 @@ void Helix::startCommercial(
|
||||||
successCallback(HelixStartCommercialResponse(obj));
|
successCallback(HelixStartCommercialResponse(obj));
|
||||||
return Success;
|
return Success;
|
||||||
})
|
})
|
||||||
.onError([failureCallback](auto result) {
|
.onError([failureCallback](const auto &result) -> void {
|
||||||
|
if (!result.status())
|
||||||
|
{
|
||||||
|
failureCallback(Error::Unknown, result.formatError());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
auto obj = result.parseJson();
|
auto obj = result.parseJson();
|
||||||
auto message = obj.value("message").toString();
|
auto message = obj.value("message").toString();
|
||||||
|
|
||||||
switch (result.status())
|
switch (*result.status())
|
||||||
{
|
{
|
||||||
case 400: {
|
case 400: {
|
||||||
if (message.startsWith("Missing scope",
|
if (message.startsWith("Missing scope",
|
||||||
|
@ -2429,7 +2540,7 @@ void Helix::startCommercial(
|
||||||
default: {
|
default: {
|
||||||
qCDebug(chatterinoTwitch)
|
qCDebug(chatterinoTwitch)
|
||||||
<< "Unhandled error starting commercial:"
|
<< "Unhandled error starting commercial:"
|
||||||
<< result.status() << result.getData() << obj;
|
<< result.formatError() << result.getData() << obj;
|
||||||
failureCallback(Error::Unknown, message);
|
failureCallback(Error::Unknown, message);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -2452,18 +2563,24 @@ void Helix::getGlobalBadges(
|
||||||
{
|
{
|
||||||
qCWarning(chatterinoTwitch)
|
qCWarning(chatterinoTwitch)
|
||||||
<< "Success result for getting global badges was "
|
<< "Success result for getting global badges was "
|
||||||
<< result.status() << "but we expected it to be 200";
|
<< result.formatError() << "but we expected it to be 200";
|
||||||
}
|
}
|
||||||
|
|
||||||
auto response = result.parseJson();
|
auto response = result.parseJson();
|
||||||
successCallback(HelixGlobalBadges(response));
|
successCallback(HelixGlobalBadges(response));
|
||||||
return Success;
|
return Success;
|
||||||
})
|
})
|
||||||
.onError([failureCallback](auto result) {
|
.onError([failureCallback](const auto &result) -> void {
|
||||||
|
if (!result.status())
|
||||||
|
{
|
||||||
|
failureCallback(Error::Unknown, result.formatError());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
auto obj = result.parseJson();
|
auto obj = result.parseJson();
|
||||||
auto message = obj.value("message").toString();
|
auto message = obj.value("message").toString();
|
||||||
|
|
||||||
switch (result.status())
|
switch (*result.status())
|
||||||
{
|
{
|
||||||
case 401: {
|
case 401: {
|
||||||
failureCallback(Error::Forwarded, message);
|
failureCallback(Error::Forwarded, message);
|
||||||
|
@ -2473,7 +2590,7 @@ void Helix::getGlobalBadges(
|
||||||
default: {
|
default: {
|
||||||
qCWarning(chatterinoTwitch)
|
qCWarning(chatterinoTwitch)
|
||||||
<< "Helix global badges, unhandled error data:"
|
<< "Helix global badges, unhandled error data:"
|
||||||
<< result.status() << result.getData() << obj;
|
<< result.formatError() << result.getData() << obj;
|
||||||
failureCallback(Error::Unknown, message);
|
failureCallback(Error::Unknown, message);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -2499,18 +2616,24 @@ void Helix::getChannelBadges(
|
||||||
{
|
{
|
||||||
qCWarning(chatterinoTwitch)
|
qCWarning(chatterinoTwitch)
|
||||||
<< "Success result for getting badges was "
|
<< "Success result for getting badges was "
|
||||||
<< result.status() << "but we expected it to be 200";
|
<< result.formatError() << "but we expected it to be 200";
|
||||||
}
|
}
|
||||||
|
|
||||||
auto response = result.parseJson();
|
auto response = result.parseJson();
|
||||||
successCallback(HelixChannelBadges(response));
|
successCallback(HelixChannelBadges(response));
|
||||||
return Success;
|
return Success;
|
||||||
})
|
})
|
||||||
.onError([failureCallback](auto result) {
|
.onError([failureCallback](const auto &result) -> void {
|
||||||
|
if (!result.status())
|
||||||
|
{
|
||||||
|
failureCallback(Error::Unknown, result.formatError());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
auto obj = result.parseJson();
|
auto obj = result.parseJson();
|
||||||
auto message = obj.value("message").toString();
|
auto message = obj.value("message").toString();
|
||||||
|
|
||||||
switch (result.status())
|
switch (*result.status())
|
||||||
{
|
{
|
||||||
case 400:
|
case 400:
|
||||||
case 401: {
|
case 401: {
|
||||||
|
@ -2521,7 +2644,7 @@ void Helix::getChannelBadges(
|
||||||
default: {
|
default: {
|
||||||
qCWarning(chatterinoTwitch)
|
qCWarning(chatterinoTwitch)
|
||||||
<< "Helix channel badges, unhandled error data:"
|
<< "Helix channel badges, unhandled error data:"
|
||||||
<< result.status() << result.getData() << obj;
|
<< result.formatError() << result.getData() << obj;
|
||||||
failureCallback(Error::Unknown, message);
|
failureCallback(Error::Unknown, message);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -2552,7 +2675,7 @@ void Helix::updateShieldMode(
|
||||||
{
|
{
|
||||||
qCWarning(chatterinoTwitch)
|
qCWarning(chatterinoTwitch)
|
||||||
<< "Success result for updating shield mode was "
|
<< "Success result for updating shield mode was "
|
||||||
<< result.status() << "but we expected it to be 200";
|
<< result.formatError() << "but we expected it to be 200";
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto response = result.parseJson();
|
const auto response = result.parseJson();
|
||||||
|
@ -2560,11 +2683,17 @@ void Helix::updateShieldMode(
|
||||||
HelixShieldModeStatus(response["data"][0].toObject()));
|
HelixShieldModeStatus(response["data"][0].toObject()));
|
||||||
return Success;
|
return Success;
|
||||||
})
|
})
|
||||||
.onError([failureCallback](auto result) {
|
.onError([failureCallback](const auto &result) -> void {
|
||||||
|
if (!result.status())
|
||||||
|
{
|
||||||
|
failureCallback(Error::Unknown, result.formatError());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const auto obj = result.parseJson();
|
const auto obj = result.parseJson();
|
||||||
auto message = obj["message"].toString();
|
auto message = obj["message"].toString();
|
||||||
|
|
||||||
switch (result.status())
|
switch (*result.status())
|
||||||
{
|
{
|
||||||
case 400: {
|
case 400: {
|
||||||
if (message.startsWith("Missing scope",
|
if (message.startsWith("Missing scope",
|
||||||
|
@ -2590,7 +2719,7 @@ void Helix::updateShieldMode(
|
||||||
default: {
|
default: {
|
||||||
qCWarning(chatterinoTwitch)
|
qCWarning(chatterinoTwitch)
|
||||||
<< "Helix shield mode, unhandled error data:"
|
<< "Helix shield mode, unhandled error data:"
|
||||||
<< result.status() << result.getData() << obj;
|
<< result.formatError() << result.getData() << obj;
|
||||||
failureCallback(Error::Unknown, message);
|
failureCallback(Error::Unknown, message);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -2619,17 +2748,23 @@ void Helix::sendShoutout(
|
||||||
{
|
{
|
||||||
qCWarning(chatterinoTwitch)
|
qCWarning(chatterinoTwitch)
|
||||||
<< "Success result for sending shoutout was "
|
<< "Success result for sending shoutout was "
|
||||||
<< result.status() << "but we expected it to be 204";
|
<< result.formatError() << "but we expected it to be 204";
|
||||||
}
|
}
|
||||||
|
|
||||||
successCallback();
|
successCallback();
|
||||||
return Success;
|
return Success;
|
||||||
})
|
})
|
||||||
.onError([failureCallback](NetworkResult result) -> void {
|
.onError([failureCallback](const NetworkResult &result) -> void {
|
||||||
|
if (!result.status())
|
||||||
|
{
|
||||||
|
failureCallback(Error::Unknown, result.formatError());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const auto obj = result.parseJson();
|
const auto obj = result.parseJson();
|
||||||
auto message = obj["message"].toString();
|
auto message = obj["message"].toString();
|
||||||
|
|
||||||
switch (result.status())
|
switch (*result.status())
|
||||||
{
|
{
|
||||||
case 400: {
|
case 400: {
|
||||||
if (message.startsWith("The broadcaster may not give "
|
if (message.startsWith("The broadcaster may not give "
|
||||||
|
@ -2692,7 +2827,7 @@ void Helix::sendShoutout(
|
||||||
default: {
|
default: {
|
||||||
qCWarning(chatterinoTwitch)
|
qCWarning(chatterinoTwitch)
|
||||||
<< "Helix send shoutout, unhandled error data:"
|
<< "Helix send shoutout, unhandled error data:"
|
||||||
<< result.status() << result.getData() << obj;
|
<< result.formatError() << result.getData() << obj;
|
||||||
failureCallback(Error::Unknown, message);
|
failureCallback(Error::Unknown, message);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -128,8 +128,8 @@ void Updates::installUpdates()
|
||||||
auto *box = new QMessageBox(
|
auto *box = new QMessageBox(
|
||||||
QMessageBox::Information, "Chatterino Update",
|
QMessageBox::Information, "Chatterino Update",
|
||||||
QStringLiteral("The update couldn't be downloaded "
|
QStringLiteral("The update couldn't be downloaded "
|
||||||
"(HTTP status %1).")
|
"(Error: %1).")
|
||||||
.arg(result.status()));
|
.arg(result.formatError()));
|
||||||
box->setAttribute(Qt::WA_DeleteOnClose);
|
box->setAttribute(Qt::WA_DeleteOnClose);
|
||||||
box->exec();
|
box->exec();
|
||||||
return Failure;
|
return Failure;
|
||||||
|
@ -189,8 +189,8 @@ void Updates::installUpdates()
|
||||||
auto *box = new QMessageBox(
|
auto *box = new QMessageBox(
|
||||||
QMessageBox::Information, "Chatterino Update",
|
QMessageBox::Information, "Chatterino Update",
|
||||||
QStringLiteral("The update couldn't be downloaded "
|
QStringLiteral("The update couldn't be downloaded "
|
||||||
"(HTTP status %1).")
|
"(Error: %1).")
|
||||||
.arg(result.status()));
|
.arg(result.formatError()));
|
||||||
box->setAttribute(Qt::WA_DeleteOnClose);
|
box->setAttribute(Qt::WA_DeleteOnClose);
|
||||||
box->exec();
|
box->exec();
|
||||||
return Failure;
|
return Failure;
|
||||||
|
|
|
@ -208,7 +208,7 @@ void uploadImageToNuuls(RawImageData imageData, ChannelPtr channel,
|
||||||
.onError([channel](NetworkResult result) -> bool {
|
.onError([channel](NetworkResult result) -> bool {
|
||||||
auto errorMessage =
|
auto errorMessage =
|
||||||
QString("An error happened while uploading your image: %1")
|
QString("An error happened while uploading your image: %1")
|
||||||
.arg(result.status());
|
.arg(result.formatError());
|
||||||
|
|
||||||
// Try to read more information from the result body
|
// Try to read more information from the result body
|
||||||
auto obj = result.parseJson();
|
auto obj = result.parseJson();
|
||||||
|
|
|
@ -8,6 +8,7 @@ set(test_SOURCES
|
||||||
${CMAKE_CURRENT_LIST_DIR}/src/AccessGuard.cpp
|
${CMAKE_CURRENT_LIST_DIR}/src/AccessGuard.cpp
|
||||||
${CMAKE_CURRENT_LIST_DIR}/src/NetworkCommon.cpp
|
${CMAKE_CURRENT_LIST_DIR}/src/NetworkCommon.cpp
|
||||||
${CMAKE_CURRENT_LIST_DIR}/src/NetworkRequest.cpp
|
${CMAKE_CURRENT_LIST_DIR}/src/NetworkRequest.cpp
|
||||||
|
${CMAKE_CURRENT_LIST_DIR}/src/NetworkResult.cpp
|
||||||
${CMAKE_CURRENT_LIST_DIR}/src/ChatterSet.cpp
|
${CMAKE_CURRENT_LIST_DIR}/src/ChatterSet.cpp
|
||||||
${CMAKE_CURRENT_LIST_DIR}/src/HighlightPhrase.cpp
|
${CMAKE_CURRENT_LIST_DIR}/src/HighlightPhrase.cpp
|
||||||
${CMAKE_CURRENT_LIST_DIR}/src/Emojis.cpp
|
${CMAKE_CURRENT_LIST_DIR}/src/Emojis.cpp
|
||||||
|
|
|
@ -210,7 +210,9 @@ TEST(NetworkRequest, TimeoutTimingOut)
|
||||||
.onError([&waiter, url](const NetworkResult &result) {
|
.onError([&waiter, url](const NetworkResult &result) {
|
||||||
qDebug() << QTime::currentTime().toString()
|
qDebug() << QTime::currentTime().toString()
|
||||||
<< "timeout request finish error";
|
<< "timeout request finish error";
|
||||||
EXPECT_EQ(result.status(), NetworkResult::timedoutStatus);
|
EXPECT_EQ(result.error(),
|
||||||
|
NetworkResult::NetworkError::TimeoutError);
|
||||||
|
EXPECT_EQ(result.status(), std::nullopt);
|
||||||
|
|
||||||
waiter.requestDone();
|
waiter.requestDone();
|
||||||
})
|
})
|
||||||
|
@ -267,7 +269,9 @@ TEST(NetworkRequest, FinallyCallbackOnTimeout)
|
||||||
})
|
})
|
||||||
.onError([&](const NetworkResult &result) {
|
.onError([&](const NetworkResult &result) {
|
||||||
onErrorCalled = true;
|
onErrorCalled = true;
|
||||||
EXPECT_EQ(result.status(), NetworkResult::timedoutStatus);
|
EXPECT_EQ(result.error(),
|
||||||
|
NetworkResult::NetworkError::TimeoutError);
|
||||||
|
EXPECT_EQ(result.status(), std::nullopt);
|
||||||
})
|
})
|
||||||
.finally([&] {
|
.finally([&] {
|
||||||
finallyCalled = true;
|
finallyCalled = true;
|
||||||
|
|
48
tests/src/NetworkResult.cpp
Normal file
48
tests/src/NetworkResult.cpp
Normal file
|
@ -0,0 +1,48 @@
|
||||||
|
#include "common/NetworkResult.hpp"
|
||||||
|
|
||||||
|
#include <gtest/gtest.h>
|
||||||
|
|
||||||
|
using namespace chatterino;
|
||||||
|
|
||||||
|
using Error = NetworkResult::NetworkError;
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
void checkResult(const NetworkResult &res, Error error,
|
||||||
|
std::optional<int> status, const QString &formatted)
|
||||||
|
{
|
||||||
|
ASSERT_EQ(res.error(), error);
|
||||||
|
ASSERT_EQ(res.status(), status);
|
||||||
|
ASSERT_EQ(res.formatError(), formatted);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
TEST(NetworkResult, NoError)
|
||||||
|
{
|
||||||
|
checkResult({Error::NoError, 200, {}}, Error::NoError, 200, "200");
|
||||||
|
checkResult({Error::NoError, 202, {}}, Error::NoError, 202, "202");
|
||||||
|
|
||||||
|
// no status code
|
||||||
|
checkResult({Error::NoError, {}, {}}, Error::NoError, std::nullopt,
|
||||||
|
"NoError");
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(NetworkResult, Errors)
|
||||||
|
{
|
||||||
|
checkResult({Error::TimeoutError, {}, {}}, Error::TimeoutError,
|
||||||
|
std::nullopt, "TimeoutError");
|
||||||
|
checkResult({Error::RemoteHostClosedError, {}, {}},
|
||||||
|
Error::RemoteHostClosedError, std::nullopt,
|
||||||
|
"RemoteHostClosedError");
|
||||||
|
|
||||||
|
// status code takes precedence
|
||||||
|
checkResult({Error::TimeoutError, 400, {}}, Error::TimeoutError, 400,
|
||||||
|
"400");
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(NetworkResult, InvalidError)
|
||||||
|
{
|
||||||
|
checkResult({static_cast<Error>(-1), {}, {}}, static_cast<Error>(-1),
|
||||||
|
std::nullopt, "unknown error (-1)");
|
||||||
|
}
|
Loading…
Reference in a new issue