]> git.sur5r.net Git - minitube/blob - src/invidious/invidious.cpp
New upstream version 3.5
[minitube] / src / invidious / invidious.cpp
1 #include "invidious.h"
2
3 #include "cachedhttp.h"
4 #include "http.h"
5 #include "httputils.h"
6 #include "throttledhttp.h"
7
8 Invidious &Invidious::instance() {
9     static Invidious i;
10     return i;
11 }
12
13 Http &Invidious::http() {
14     static Http *h = [] {
15         Http *http = new Http;
16         http->addRequestHeader("User-Agent", HttpUtils::stealthUserAgent());
17         http->setMaxRetries(0);
18         return http;
19     }();
20     return *h;
21 }
22
23 Http &Invidious::cachedHttp() {
24     static Http *h = [] {
25         ThrottledHttp *throttledHttp = new ThrottledHttp(http());
26         throttledHttp->setMilliseconds(300);
27
28         CachedHttp *cachedHttp = new CachedHttp(*throttledHttp, "iv");
29         cachedHttp->setMaxSeconds(86400);
30         cachedHttp->setIgnoreHostname(true);
31         return cachedHttp;
32     }();
33     return *h;
34 }
35
36 Invidious::Invidious(QObject *parent) : QObject(parent) {}
37
38 void Invidious::initServers() {
39     servers.clear();
40     QUrl url("https://instances.invidio.us/instances.json?sort_by=type,health,users");
41     auto reply = HttpUtils::yt().get(url);
42     connect(reply, &HttpReply::finished, this, [this](auto &reply) {
43         if (reply.isSuccessful()) {
44             QSettings settings;
45             QStringList keywords = settings.value("recentKeywords").toStringList();
46             QString testKeyword = keywords.isEmpty() ? "test" : keywords.first();
47
48             bool haveEnoughServers = false;
49             QJsonDocument doc = QJsonDocument::fromJson(reply.body());
50             for (const auto &v : doc.array()) {
51                 auto serverArray = v.toArray();
52                 QString host = serverArray.first().toString();
53                 QJsonObject serverObj = serverArray.at(1).toObject();
54                 if (serverObj["type"] == "https") {
55                     QString url = "https://" + host;
56
57                     if (haveEnoughServers) break;
58                     QUrl testUrl(url + "/api/v1/search?q=" + testKeyword);
59                     auto reply = http().get(testUrl);
60                     connect(reply, &HttpReply::finished, this,
61                             [this, url, &haveEnoughServers](auto &reply) {
62                                 if (!haveEnoughServers && reply.isSuccessful()) {
63                                     QJsonDocument doc = QJsonDocument::fromJson(reply.body());
64                                     if (!doc.array().isEmpty()) {
65                                         servers << url;
66                                         if (servers.size() > 4) {
67                                             haveEnoughServers = true;
68                                             std::shuffle(servers.begin(), servers.end(),
69                                                          *QRandomGenerator::global());
70                                             qDebug() << servers;
71                                             emit serversInitialized();
72                                         }
73                                     }
74                                 }
75                             });
76                 }
77             }
78         }
79     });
80 }
81
82 QString Invidious::baseUrl() {
83     QString host;
84     if (servers.isEmpty())
85         host = "https://invidious.snopyta.org";
86     else
87         host = servers.first();
88     QString url = host + QLatin1String("/api/v1/");
89     return url;
90 }
91
92 QUrl Invidious::method(const QString &name) {
93     QUrl url(baseUrl() + name);
94     return url;
95 }