1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
|
#pragma once
#include <QJsonArray>
#include <QJsonDocument>
#include <QJsonObject>
#include <QNetworkAccessManager>
#include <QNetworkCookieJar>
#include <QNetworkReply>
#include <QTimer>
#include <functional>
class GitHubException : public std::exception
{
public:
GitHubException(const QJsonObject& errorObj) : std::exception()
{
initMessage(errorObj);
}
virtual ~GitHubException() throw() override {}
virtual const char* what() const throw() { return m_Message.constData(); }
private:
void initMessage(const QJsonObject& obj)
{
if (obj.contains("http_status")) {
m_Message = QString("HTTP Status %1: %2")
.arg(obj.value("http_status").toInt())
.arg(obj.value("reason").toString())
.toUtf8();
} else if (obj.contains("parse_error")) {
m_Message = QString("Parsing failed: %1")
.arg(obj.value("parse_error").toString())
.toUtf8();
} else if (obj.contains("network_error")) {
m_Message = QString("Network failed: %1")
.arg(obj.value("network_error").toString())
.toUtf8();
} else {
m_Message = "Unknown error";
}
}
QByteArray m_Message;
};
class GitHub : public QObject
{
Q_OBJECT
public:
enum class Method
{
GET,
POST
};
struct Repository
{
Repository(const QString& owner, const QString& project)
: owner(owner), project(project)
{}
QString owner;
QString project;
};
public:
GitHub(const char* clientId = nullptr);
~GitHub();
QJsonArray releases(const Repository& repo);
void releases(const Repository& repo,
const std::function<void(const QJsonArray&)>& callback);
private:
QJsonDocument request(Method method, const QString& path, const QByteArray& data,
bool relative);
void request(Method method, const QString& path, const QByteArray& data,
const std::function<void(const QJsonDocument&)>& callback,
bool relative);
QJsonDocument handleReply(QNetworkReply* reply);
QNetworkReply* genReply(Method method, const QString& path, const QByteArray& data,
bool relative);
private:
struct Request
{
Method method = Method::GET;
QByteArray data;
std::function<void(const QJsonDocument&)> callback;
QTimer* timer = nullptr;
QNetworkReply* reply = nullptr;
};
QNetworkAccessManager* m_AccessManager;
// remember the replies that are in flight and delete them in the destructor
std::vector<QNetworkReply*> m_replies;
void onFinished(const Request& req);
void onError(const Request& req, QNetworkReply::NetworkError error);
void onTimeout(const Request& req);
void deleteReply(QNetworkReply* reply);
};
|