]> git.sur5r.net Git - minitube/blob - src/yt/ytjs/ytjstrending.cpp
New upstream version 3.9.1
[minitube] / src / yt / ytjs / ytjstrending.cpp
1 #include "ytjstrending.h"
2
3 #include "js.h"
4 #include "video.h"
5
6 namespace {
7
8 QDateTime parsePublishedText(const QString &s) {
9     int num = 0;
10     const auto parts = s.splitRef(' ');
11     for (const auto &part : parts) {
12         num = part.toInt();
13         if (num > 0) break;
14     }
15     if (num == 0) return QDateTime();
16
17     auto now = QDateTime::currentDateTimeUtc();
18     if (s.contains("hour")) {
19         return now.addSecs(-num * 3600);
20     } else if (s.contains("day")) {
21         return now.addDays(-num);
22     } else if (s.contains("week")) {
23         return now.addDays(-num * 7);
24     } else if (s.contains("month")) {
25         return now.addMonths(-num);
26     } else if (s.contains("year")) {
27         return now.addDays(-num * 365);
28     }
29     return QDateTime();
30 }
31
32 } // namespace
33
34 YTJSTrending::YTJSTrending(QString name, QVariantMap params, QObject *parent)
35     : VideoSource(parent), name(name), params(params) {}
36
37 void YTJSTrending::loadVideos(int max, int startIndex) {
38     aborted = false;
39
40     auto &js = JS::instance();
41
42     QJSValue options = js.getEngine().toScriptValue(params);
43
44     js.callFunction(new JSResult(this), "trending", {options})
45             .onJson([this](auto &doc) {
46                 const auto items = doc.array();
47
48                 QVector<Video *> videos;
49                 videos.reserve(items.size());
50
51                 for (const auto &i : items) {
52                     QString type = i["type"].toString();
53                     if (type != "video") continue;
54
55                     Video *video = new Video();
56
57                     QString id = i["videoId"].toString();
58                     video->setId(id);
59
60                     QString title = i["title"].toString();
61                     video->setTitle(title);
62
63                     QString desc = i["description"].toString();
64                     if (desc.isEmpty()) desc = i["desc"].toString();
65                     video->setDescription(desc);
66
67                     const auto thumbs = i["videoThumbnails"].toArray();
68                     for (const auto &t : thumbs) {
69                         video->addThumb(t["width"].toInt(), t["height"].toInt(),
70                                         t["url"].toString());
71                     }
72
73                     int views = i["viewCount"].toInt();
74                     video->setViewCount(views);
75
76                     int duration = i["lengthSeconds"].toInt();
77                     video->setDuration(duration);
78
79                     auto published = parsePublishedText(i["publishedText"].toString());
80                     if (published.isValid()) video->setPublished(published);
81
82                     QString channelName = i["author"].toString();
83                     video->setChannelTitle(channelName);
84                     QString channelId = i["authorId"].toString();
85                     video->setChannelId(channelId);
86
87                     videos << video;
88                 }
89
90                 emit gotVideos(videos);
91                 emit finished(videos.size());
92             })
93             .onError([this, max, startIndex](auto &msg) {
94                 static int retries = 0;
95                 if (retries < 3) {
96                     qDebug() << "Retrying...";
97                     QTimer::singleShot(0, this,
98                                        [this, max, startIndex] { loadVideos(max, startIndex); });
99                     retries++;
100                 } else {
101                     emit error(msg);
102                 }
103             });
104 }