Networkmanager (#134)

* rename ImageLoader* to Network*

* static NetworkManager

* NetworkManager queue arbitrary requests

* modify urlfetch to use NetworkManager

* urlfetchjson in terms of NetworkManager

* fetchurljson fetchurltimeout fetchurljsontimeout

special fetch url functions with various connects and functions to be
called

* operate on fetched data in the correct thread

* operate on fetched resources in correct thread

* networkmanager urlfetch functions

* expose urlfetch functions of networkmanager through util and
util::twitch

* add caller to util functions

* cleanup

* formatting

* urlPut function for NetworkManager and util::twitch

* cleanup worker (no more leak)

* use urlfetch for LazyLoadedImage::loadImage

* Rename NetworkManager methods (#1)

* Rename NetworkManager methods

Remove unused NetworkManager methods
Remove unused NetworkManager includes

Reorder includes in lazyloadedimage.cpp and urlfetch.hpp

* try to simplify code, might break everything

* fixed some more stuff?
This commit is contained in:
hemirt
2017-10-27 20:09:02 +02:00
committed by pajlada
parent a4c0bdb926
commit f51372102e
17 changed files with 521 additions and 427 deletions
+121 -193
View File
@@ -1,7 +1,8 @@
#pragma once
#include "credentials.hpp"
#include "accountmanager.hpp"
#include "credentials.hpp"
#include "util/networkmanager.hpp"
#include <QEventLoop>
#include <QJsonArray>
@@ -14,68 +15,128 @@
#include <QString>
#include <QTimer>
#include <QDebug>
#include <functional>
namespace chatterino {
namespace util {
namespace twitch {
static void get(QString url, std::function<void(QJsonObject &)> successCallback)
static QJsonObject parseJSONFromReply(QNetworkReply *reply)
{
auto manager = new QNetworkAccessManager();
if (reply->error() != QNetworkReply::NetworkError::NoError) {
return QJsonObject();
}
QUrl requestUrl(url);
QNetworkRequest request(requestUrl);
QByteArray data = reply->readAll();
QJsonDocument jsonDoc(QJsonDocument::fromJson(data));
request.setRawHeader("Client-ID", getDefaultClientID());
request.setRawHeader("Accept", "application/vnd.twitchtv.v5+json");
if (jsonDoc.isNull()) {
return QJsonObject();
}
QNetworkReply *reply = manager->get(request);
return jsonDoc.object();
}
QObject::connect(reply, &QNetworkReply::finished, [=] {
if (reply->error() == QNetworkReply::NetworkError::NoError) {
QByteArray data = reply->readAll();
QJsonDocument jsonDoc(QJsonDocument::fromJson(data));
if (!jsonDoc.isNull()) {
QJsonObject rootNode = jsonDoc.object();
successCallback(rootNode);
}
}
reply->deleteLater();
manager->deleteLater();
static void urlFetchJSON(const QString &url, const QObject *caller,
std::function<void(QJsonObject &)> successCallback)
{
util::NetworkRequest req(url);
req.setCaller(caller);
req.get([=](QNetworkReply *reply) {
auto node = parseJSONFromReply(reply);
successCallback(node);
});
}
static void getUserID(QString username, std::function<void(QString)> successCallback)
static void urlFetchTimeout(const QString &url, const QObject *caller,
std::function<void(QNetworkReply *)> successCallback, int timeoutMs)
{
get("https://api.twitch.tv/kraken/users?login=" + username, [=](const QJsonObject &root) {
if (!root.value("users").isArray()) {
qDebug() << "API Error while getting user id, users is not an array";
return;
QTimer *timer = new QTimer;
timer->setSingleShot(true);
QEventLoop *loop = new QEventLoop;
util::NetworkRequest req(url);
req.setCaller(loop);
req.setOnReplyCreated([loop, timer](QNetworkReply *reply) {
QObject::connect(timer, &QTimer::timeout, loop, [=]() {
QObject::disconnect(reply, &QNetworkReply::finished, loop, &QEventLoop::quit);
reply->abort();
reply->deleteLater();
});
});
req.get([=](QNetworkReply *reply) {
if (reply->error() == QNetworkReply::NetworkError::NoError) {
successCallback(reply);
}
auto users = root.value("users").toArray();
if (users.size() != 1) {
qDebug() << "API Error while getting user id, users array size is not 1";
return;
}
if (!users[0].isObject()) {
qDebug() << "API Error while getting user id, first user is not an object";
return;
}
auto firstUser = users[0].toObject();
auto id = firstUser.value("_id");
if (!id.isString()) {
qDebug()
<< "API Error: while getting user id, first user object `_id` key is not a string";
return;
}
successCallback(id.toString());
reply->deleteLater();
loop->quit();
});
QObject::connect(timer, SIGNAL(timeout()), loop, SLOT(quit()));
timer->start(timeoutMs);
loop->exec();
delete timer;
delete loop;
}
static void urlFetchJSONTimeout(const QString &url, const QObject *caller,
std::function<void(QJsonObject &)> successCallback, int timeoutMs)
{
urlFetchTimeout(url, caller,
[=](QNetworkReply *reply) {
auto node = parseJSONFromReply(reply);
successCallback(node);
},
timeoutMs);
}
namespace twitch {
static void get(QString url, const QObject *caller,
std::function<void(QJsonObject &)> successCallback)
{
util::NetworkRequest req(url);
req.setCaller(caller);
req.setRawHeader("Client-ID", getDefaultClientID());
req.setRawHeader("Accept", "application/vnd.twitchtv.v5+json");
req.get([=](QNetworkReply *reply) {
auto node = parseJSONFromReply(reply);
successCallback(node);
});
}
static void getUserID(QString username, const QObject *caller,
std::function<void(QString)> successCallback)
{
get("https://api.twitch.tv/kraken/users?login=" + username, caller,
[=](const QJsonObject &root) {
if (!root.value("users").isArray()) {
qDebug() << "API Error while getting user id, users is not an array";
return;
}
auto users = root.value("users").toArray();
if (users.size() != 1) {
qDebug() << "API Error while getting user id, users array size is not 1";
return;
}
if (!users[0].isObject()) {
qDebug() << "API Error while getting user id, first user is not an object";
return;
}
auto firstUser = users[0].toObject();
auto id = firstUser.value("_id");
if (!id.isString()) {
qDebug() << "API Error: while getting user id, first user object `_id` key is not "
"a string";
return;
}
successCallback(id.toString());
});
}
static void put(QUrl url, std::function<void(QJsonObject)> successCallback)
{
@@ -84,157 +145,24 @@ static void put(QUrl url, std::function<void(QJsonObject)> successCallback)
request.setRawHeader("Client-ID", getDefaultClientID());
request.setRawHeader("Accept", "application/vnd.twitchtv.v5+json");
request.setRawHeader("Authorization", "OAuth " +
AccountManager::getInstance().getTwitchUser().getOAuthToken().toUtf8());
QNetworkReply *reply = manager->put(request,"");
QObject::connect(reply, &QNetworkReply::finished, [=](){
if(reply->error() == QNetworkReply::NetworkError::NoError)
{
QByteArray data = reply->readAll();
QJsonDocument jsonDoc(QJsonDocument::fromJson(data));
if(!jsonDoc.isNull())
{
QJsonObject rootNode = jsonDoc.object();
request.setRawHeader(
"Authorization",
"OAuth " + AccountManager::getInstance().getTwitchUser().getOAuthToken().toUtf8());
successCallback(rootNode);
}
}
reply->deleteLater();
manager->deleteLater();
NetworkManager::urlPut(std::move(request), [=](QNetworkReply *reply) {
if (reply->error() == QNetworkReply::NetworkError::NoError) {
QByteArray data = reply->readAll();
QJsonDocument jsonDoc(QJsonDocument::fromJson(data));
if (!jsonDoc.isNull()) {
QJsonObject rootNode = jsonDoc.object();
successCallback(rootNode);
}
}
reply->deleteLater();
});
}
} // namespace twitch
static void urlFetch(const QString &url, std::function<void(QNetworkReply &)> successCallback,
QNetworkAccessManager *manager = nullptr)
{
bool customManager = true;
if (manager == nullptr) {
manager = new QNetworkAccessManager();
customManager = false;
}
QUrl requestUrl(url);
QNetworkRequest request(requestUrl);
QNetworkReply *reply = manager->get(request);
QObject::connect(reply, &QNetworkReply::finished, [=] {
/* uncomment to follow redirects
QVariant replyStatus = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute);
if (replyStatus >= 300 && replyStatus <= 304) {
QString newUrl =
reply->attribute(QNetworkRequest::RedirectionTargetAttribute).toString();
urlFetch(newUrl, successCallback);
return;
}
*/
if (reply->error() == QNetworkReply::NetworkError::NoError) {
successCallback(*reply);
}
reply->deleteLater();
if (!customManager) {
manager->deleteLater();
}
});
}
static void urlFetchJSON(const QString &url, std::function<void(QJsonObject &)> successCallback,
QNetworkAccessManager *manager = nullptr)
{
urlFetch(url,
[=](QNetworkReply &reply) {
QByteArray data = reply.readAll();
QJsonDocument jsonDoc(QJsonDocument::fromJson(data));
if (jsonDoc.isNull()) {
return;
}
QJsonObject rootNode = jsonDoc.object();
successCallback(rootNode);
},
manager);
}
static void urlFetchTimeout(const QString &url,
std::function<void(QNetworkReply &)> successCallback, int timeoutMs,
QNetworkAccessManager *manager = nullptr)
{
bool customManager = true;
if (manager == nullptr) {
manager = new QNetworkAccessManager();
customManager = false;
}
QUrl requestUrl(url);
QNetworkRequest request(requestUrl);
QNetworkReply *reply = manager->get(request);
QTimer timer;
timer.setSingleShot(true);
QEventLoop loop;
QObject::connect(&timer, SIGNAL(timeout()), &loop, SLOT(quit()));
QObject::connect(reply, SIGNAL(finished()), &loop, SLOT(quit()));
QObject::connect(reply, &QNetworkReply::finished, [=] {
/* uncomment to follow redirects
QVariant replyStatus = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute);
if (replyStatus >= 300 && replyStatus <= 304) {
QString newUrl =
reply->attribute(QNetworkRequest::RedirectionTargetAttribute).toString();
urlFetch(newUrl, successCallback);
return;
}
*/
if (reply->error() == QNetworkReply::NetworkError::NoError) {
successCallback(*reply);
}
reply->deleteLater();
if (!customManager) {
manager->deleteLater();
}
});
timer.start(timeoutMs);
loop.exec();
if (!timer.isActive()) {
qDebug() << "TIMED OUT";
QObject::disconnect(reply, SIGNAL(finished()), &loop, SLOT(quit()));
reply->abort();
} else {
// qDebug() << "XDDD HEHEHE";
}
}
static void urlFetchJSONTimeout(const QString &url,
std::function<void(QJsonObject &)> successCallback, int timeoutMs,
QNetworkAccessManager *manager = nullptr)
{
urlFetchTimeout(url,
[=](QNetworkReply &reply) {
QByteArray data = reply.readAll();
QJsonDocument jsonDoc(QJsonDocument::fromJson(data));
if (jsonDoc.isNull()) {
return;
}
QJsonObject rootNode = jsonDoc.object();
successCallback(rootNode);
},
timeoutMs, manager);
}
} // namespace util
} // namespace chatterino