]> git.sur5r.net Git - minitube/blob - src/ytjs/ytjs.cpp
086374189df6b83947bae1551167af451e8a9309
[minitube] / src / ytjs / ytjs.cpp
1 #include "ytjs.h"
2
3 #include "ytjsnamfactory.h"
4
5 #include "cachedhttp.h"
6 #include "http.h"
7 #include "httputils.h"
8
9 namespace {
10
11 QString wsBase = "https://flavio.tordini.org/minitube-ws/ytjs/";
12 QString ytJs = wsBase + "yt.js";
13
14 } // namespace
15
16 YTJS &YTJS::instance() {
17     static YTJS i;
18     return i;
19 }
20
21 Http &YTJS::http() {
22     static Http *h = [] {
23         Http *http = new Http;
24         http->addRequestHeader("User-Agent", HttpUtils::userAgent());
25         return http;
26     }();
27     return *h;
28 }
29
30 Http &YTJS::cachedHttp() {
31     static Http *h = [] {
32         CachedHttp *cachedHttp = new CachedHttp(http(), "ytjs");
33         cachedHttp->setMaxSeconds(3600 * 6);
34         cachedHttp->setIgnoreHostname(true);
35
36         cachedHttp->getValidators().insert("application/javascript", [](const auto &reply) -> bool {
37             return !reply.body().isEmpty();
38         });
39
40         return cachedHttp;
41     }();
42     return *h;
43 }
44
45 YTJS::YTJS(QObject *parent) : QObject(parent), engine(nullptr) {
46     initialize();
47 }
48
49 bool YTJS::checkError(const QJSValue &value) {
50     if (value.isError()) {
51         qWarning() << "Error" << value.toString();
52         qDebug() << value.property("stack").toString().splitRef('\n');
53         return true;
54     }
55     return false;
56 }
57
58 bool YTJS::isInitialized() {
59     if (ready) return true;
60     initialize();
61     return false;
62 }
63
64 void YTJS::initialize() {
65     if (initializing) return;
66     initializing = true;
67
68     if (engine) engine->deleteLater();
69     engine = new QQmlEngine(this);
70     engine->setNetworkAccessManagerFactory(new YTJSNAMFactory);
71
72     engine->globalObject().setProperty("global", engine->globalObject());
73
74     QJSValue timer = engine->newQObject(new JsTimer(engine));
75     engine->globalObject().setProperty("clearTimeout", timer.property("clearTimeout"));
76     engine->globalObject().setProperty("setTimeout", timer.property("setTimeout"));
77
78     connect(cachedHttp().get(ytJs), &HttpReply::finished, this, [this](auto &reply) {
79         if (!reply.isSuccessful()) {
80             emit initFailed("Cannot load " + ytJs);
81             return;
82         }
83         evaluate(reply.body());
84         ready = true;
85         initializing = false;
86         emit initialized();
87     });
88 }
89
90 QJSValue YTJS::evaluate(const QString &js) {
91     auto value = engine->evaluate(js);
92     checkError(value);
93     return value;
94 }