]> git.sur5r.net Git - minitube/blob - src/ytjs/ytjs.cpp
New upstream version 3.6.1
[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         // Avoid expiring the cached js
35         cachedHttp->setMaxSize(0);
36         cachedHttp->setIgnoreHostname(true);
37
38         cachedHttp->getValidators().insert("application/javascript", [](const auto &reply) -> bool {
39             return !reply.body().isEmpty();
40         });
41
42         return cachedHttp;
43     }();
44     return *h;
45 }
46
47 YTJS::YTJS(QObject *parent) : QObject(parent), engine(nullptr) {
48     initialize();
49 }
50
51 bool YTJS::checkError(const QJSValue &value) {
52     if (value.isError()) {
53         qWarning() << "Error" << value.toString();
54         qDebug() << value.property("stack").toString().splitRef('\n');
55         return true;
56     }
57     return false;
58 }
59
60 bool YTJS::isInitialized() {
61     if (ready) return true;
62     initialize();
63     return false;
64 }
65
66 void YTJS::initialize() {
67     if (initializing) return;
68     initializing = true;
69
70     if (engine) engine->deleteLater();
71     engine = new QQmlEngine(this);
72     engine->setNetworkAccessManagerFactory(new YTJSNAMFactory);
73
74     engine->globalObject().setProperty("global", engine->globalObject());
75
76     QJSValue timer = engine->newQObject(new JsTimer(engine));
77     engine->globalObject().setProperty("clearTimeout", timer.property("clearTimeout"));
78     engine->globalObject().setProperty("setTimeout", timer.property("setTimeout"));
79
80     connect(cachedHttp().get(ytJs), &HttpReply::finished, this, [this](auto &reply) {
81         if (!reply.isSuccessful()) {
82             emit initFailed("Cannot load JS");
83             qDebug() << "Cannot load JS";
84             return;
85         }
86         evaluate(reply.body());
87         ready = true;
88         initializing = false;
89         qDebug() << "Initialized";
90         emit initialized();
91     });
92 }
93
94 QJSValue YTJS::evaluate(const QString &js) {
95     auto value = engine->evaluate(js);
96     checkError(value);
97     return value;
98 }