incyclist-services 1.3.32 → 1.3.33
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/routes/base/types/index.d.ts +1 -0
- package/lib/routes/base/utils/route.js +5 -3
- package/lib/routes/download/service.d.ts +5 -0
- package/lib/routes/download/service.js +23 -0
- package/lib/routes/list/cards/RouteCard.d.ts +2 -0
- package/lib/routes/list/cards/RouteCard.js +30 -10
- package/lib/routes/list/loaders/api.d.ts +1 -1
- package/lib/routes/list/loaders/api.js +3 -3
- package/lib/routes/list/loaders/db.js +25 -20
- package/package.json +1 -1
|
@@ -129,7 +129,7 @@ const addGenericDetails = (details, route) => {
|
|
|
129
129
|
route.description.routeHash = details.routeHash;
|
|
130
130
|
};
|
|
131
131
|
const addVideoDetails = (route, details) => {
|
|
132
|
-
var _a, _b;
|
|
132
|
+
var _a, _b, _c;
|
|
133
133
|
if (!(0, valid_1.valid)(route.description.requiresDownload))
|
|
134
134
|
route.description.requiresDownload = (_a = details.requiresDownload) !== null && _a !== void 0 ? _a : (0, valid_1.valid)(details.downloadUrl);
|
|
135
135
|
if (!(0, valid_1.valid)(route.description.downloadUrl))
|
|
@@ -138,7 +138,9 @@ const addVideoDetails = (route, details) => {
|
|
|
138
138
|
route.description.videoUrl = details.video.url;
|
|
139
139
|
}
|
|
140
140
|
if (!(0, valid_1.valid)(route.description.videoUrl)) {
|
|
141
|
-
|
|
141
|
+
if ((0, valid_1.valid)((_b = details.video) === null || _b === void 0 ? void 0 : _b.file)) {
|
|
142
|
+
route.description.videoUrl = details.video.file.startsWith('http') ? details.video.file : 'video:///' + details.video.file;
|
|
143
|
+
}
|
|
142
144
|
}
|
|
143
145
|
if (!(0, valid_1.valid)(route.description.videoFormat)) {
|
|
144
146
|
route.description.videoFormat = details.video.format;
|
|
@@ -147,7 +149,7 @@ const addVideoDetails = (route, details) => {
|
|
|
147
149
|
route.description.previewUrl = details.previewUrl;
|
|
148
150
|
}
|
|
149
151
|
route.description.hasGpx = details.points.find(p => p.lat && p.lng) !== undefined;
|
|
150
|
-
route.description.next = (
|
|
152
|
+
route.description.next = (_c = details.video) === null || _c === void 0 ? void 0 : _c.next;
|
|
151
153
|
};
|
|
152
154
|
const validateRoute = (route) => {
|
|
153
155
|
var _a;
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { IncyclistService } from "../../base/service";
|
|
2
2
|
import { Route } from "../base/model/route";
|
|
3
|
+
import { RoutesApiLoader } from "../list/loaders/api";
|
|
4
|
+
import { RoutesDbLoader } from "../list/loaders/db";
|
|
3
5
|
import { DownloadObserver } from "./types";
|
|
4
6
|
export declare class RouteDownloadService extends IncyclistService {
|
|
5
7
|
protected downloads: Array<{
|
|
@@ -8,11 +10,14 @@ export declare class RouteDownloadService extends IncyclistService {
|
|
|
8
10
|
}>;
|
|
9
11
|
protected progressLogTs: Record<string, number>;
|
|
10
12
|
constructor();
|
|
13
|
+
getRepo(): RoutesDbLoader;
|
|
14
|
+
getRoutesApi(): RoutesApiLoader;
|
|
11
15
|
download(route: Route): DownloadObserver;
|
|
12
16
|
stopDownload(route: Route): void;
|
|
13
17
|
protected getObserver(route: Route): DownloadObserver;
|
|
14
18
|
protected _download(route: Route): Promise<void>;
|
|
15
19
|
protected waitForVideoDir(observer: DownloadObserver): any;
|
|
16
20
|
protected downloadRoute(route: Route, targetDir: string, observer: DownloadObserver): Promise<void>;
|
|
21
|
+
protected restoreFromRepo(route: Route): Promise<string>;
|
|
17
22
|
protected onDownloadProgress(id: string, observer: DownloadObserver, pct: any, speed: any, downloaded: any): void;
|
|
18
23
|
}
|
|
@@ -14,6 +14,8 @@ const api_1 = require("../../api");
|
|
|
14
14
|
const service_1 = require("../../base/service");
|
|
15
15
|
const settings_1 = require("../../settings");
|
|
16
16
|
const utils_1 = require("../../utils");
|
|
17
|
+
const api_2 = require("../list/loaders/api");
|
|
18
|
+
const db_1 = require("../list/loaders/db");
|
|
17
19
|
const types_1 = require("./types");
|
|
18
20
|
class RouteDownloadService extends service_1.IncyclistService {
|
|
19
21
|
constructor() {
|
|
@@ -21,6 +23,12 @@ class RouteDownloadService extends service_1.IncyclistService {
|
|
|
21
23
|
this.progressLogTs = {};
|
|
22
24
|
this.downloads = [];
|
|
23
25
|
}
|
|
26
|
+
getRepo() {
|
|
27
|
+
return new db_1.RoutesDbLoader();
|
|
28
|
+
}
|
|
29
|
+
getRoutesApi() {
|
|
30
|
+
return new api_2.RoutesApiLoader();
|
|
31
|
+
}
|
|
24
32
|
download(route) {
|
|
25
33
|
const running = this.getObserver(route);
|
|
26
34
|
if (running) {
|
|
@@ -78,6 +86,13 @@ class RouteDownloadService extends service_1.IncyclistService {
|
|
|
78
86
|
let url;
|
|
79
87
|
try {
|
|
80
88
|
url = ((_a = route === null || route === void 0 ? void 0 : route.description) === null || _a === void 0 ? void 0 : _a.downloadUrl) || ((_b = route === null || route === void 0 ? void 0 : route.description) === null || _b === void 0 ? void 0 : _b.videoUrl);
|
|
89
|
+
if (!url) {
|
|
90
|
+
url = this.restoreFromRepo(route);
|
|
91
|
+
}
|
|
92
|
+
if (!url) {
|
|
93
|
+
observer.emit('error', new Error('download not supported'));
|
|
94
|
+
return;
|
|
95
|
+
}
|
|
81
96
|
const { id, title } = route.description;
|
|
82
97
|
const { path, downloadManager } = (0, api_1.getBindings)();
|
|
83
98
|
if (!path || !downloadManager) {
|
|
@@ -117,6 +132,14 @@ class RouteDownloadService extends service_1.IncyclistService {
|
|
|
117
132
|
}
|
|
118
133
|
});
|
|
119
134
|
}
|
|
135
|
+
restoreFromRepo(route) {
|
|
136
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
137
|
+
yield this.getRoutesApi().loadDetails([{ route, added: false }], true);
|
|
138
|
+
yield (0, utils_1.waitNextTick)();
|
|
139
|
+
const descr = this.getRepo().getDescription(route.description.id);
|
|
140
|
+
return (descr === null || descr === void 0 ? void 0 : descr.downloadUrl) || (descr === null || descr === void 0 ? void 0 : descr.videoUrl);
|
|
141
|
+
});
|
|
142
|
+
}
|
|
120
143
|
onDownloadProgress(id, observer, pct, speed, downloaded) {
|
|
121
144
|
const prev = this.progressLogTs[id] || 0;
|
|
122
145
|
const ts = Date.now();
|
|
@@ -94,6 +94,8 @@ export declare class RouteCard extends BaseCard implements Card<Route> {
|
|
|
94
94
|
download(): Observer;
|
|
95
95
|
stopDownload(): void;
|
|
96
96
|
protected onDownloadCompleted(url: string): Promise<void>;
|
|
97
|
+
private saveOriginalVideoUrl;
|
|
98
|
+
private restoreVideoUrl;
|
|
97
99
|
protected onDownloadError(err: Error): Promise<void>;
|
|
98
100
|
getCurrentConversion(): Observer;
|
|
99
101
|
convert(): Observer;
|
|
@@ -360,10 +360,18 @@ class RouteCard extends base_1.BaseCard {
|
|
|
360
360
|
}
|
|
361
361
|
}
|
|
362
362
|
download() {
|
|
363
|
-
var _a
|
|
363
|
+
var _a;
|
|
364
364
|
try {
|
|
365
365
|
if (!this.downloadObserver) {
|
|
366
|
-
|
|
366
|
+
const routeDescr = (_a = this.route) === null || _a === void 0 ? void 0 : _a.description;
|
|
367
|
+
const lv = (v) => {
|
|
368
|
+
if (v === null)
|
|
369
|
+
return 'null';
|
|
370
|
+
if (v === undefined)
|
|
371
|
+
return undefined;
|
|
372
|
+
return v;
|
|
373
|
+
};
|
|
374
|
+
(0, service_1.getRouteList)().logEvent({ message: 'download started', route: routeDescr === null || routeDescr === void 0 ? void 0 : routeDescr.title, videoUrl: lv(routeDescr === null || routeDescr === void 0 ? void 0 : routeDescr.videoUrl), downloadUrl: lv(routeDescr === null || routeDescr === void 0 ? void 0 : routeDescr.downloadUrl) });
|
|
367
375
|
const dl = new service_2.RouteDownloadService();
|
|
368
376
|
this.downloadObserver = dl.download(this.route);
|
|
369
377
|
this.downloadObserver
|
|
@@ -392,12 +400,11 @@ class RouteCard extends base_1.BaseCard {
|
|
|
392
400
|
var _a, _b;
|
|
393
401
|
try {
|
|
394
402
|
(0, service_1.getRouteList)().logEvent({ message: 'download completed', route: (_b = (_a = this.route) === null || _a === void 0 ? void 0 : _a.description) === null || _b === void 0 ? void 0 : _b.title });
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
this.route.description.tsImported = Date.now();
|
|
403
|
+
this.saveOriginalVideoUrl();
|
|
404
|
+
const descr = this.getRouteDescription();
|
|
405
|
+
descr.videoUrl = url;
|
|
406
|
+
descr.isDownloaded = true;
|
|
407
|
+
descr.tsImported = Date.now();
|
|
401
408
|
this.route.details.video.file = undefined;
|
|
402
409
|
this.route.details.video.url = url;
|
|
403
410
|
this.updateRoute(this.route);
|
|
@@ -416,6 +423,19 @@ class RouteCard extends base_1.BaseCard {
|
|
|
416
423
|
}
|
|
417
424
|
});
|
|
418
425
|
}
|
|
426
|
+
saveOriginalVideoUrl() {
|
|
427
|
+
const descr = this.getRouteDescription();
|
|
428
|
+
descr.originalVideoUrl = descr.videoUrl;
|
|
429
|
+
if (!descr.downloadUrl && descr.videoUrl.startsWith('http')) {
|
|
430
|
+
descr.downloadUrl = descr.videoUrl;
|
|
431
|
+
}
|
|
432
|
+
this.save();
|
|
433
|
+
}
|
|
434
|
+
restoreVideoUrl() {
|
|
435
|
+
var _a;
|
|
436
|
+
const descr = this.getRouteDescription();
|
|
437
|
+
descr.videoUrl = (_a = descr.originalVideoUrl) !== null && _a !== void 0 ? _a : descr.downloadUrl;
|
|
438
|
+
}
|
|
419
439
|
onDownloadError(err) {
|
|
420
440
|
return __awaiter(this, void 0, void 0, function* () {
|
|
421
441
|
var _a, _b;
|
|
@@ -556,10 +576,10 @@ class RouteCard extends base_1.BaseCard {
|
|
|
556
576
|
return __awaiter(this, void 0, void 0, function* () {
|
|
557
577
|
const descr = this.getRouteDescription();
|
|
558
578
|
descr.isDownloaded = false;
|
|
559
|
-
|
|
579
|
+
this.restoreVideoUrl();
|
|
560
580
|
descr.tsImported = null;
|
|
561
581
|
this.route.details.video.file = undefined;
|
|
562
|
-
this.route.details.video.url = descr.
|
|
582
|
+
this.route.details.video.url = descr.videoUrl;
|
|
563
583
|
if (this.downloadObserver) {
|
|
564
584
|
this.downloadObserver.stop();
|
|
565
585
|
process.nextTick(() => { delete this.downloadObserver; });
|
|
@@ -22,7 +22,7 @@ export declare class RoutesApiLoader extends Loader<RouteApiDescription> {
|
|
|
22
22
|
protected isCompleted(route: Route): boolean;
|
|
23
23
|
protected isPreviewMissing(route: Route): boolean;
|
|
24
24
|
protected loadDetailsFromRepo(items: LoadDetailsTargets): Promise<LoadDetailsTargets>;
|
|
25
|
-
loadDetails(items: LoadDetailsTargets): Promise<void>;
|
|
25
|
+
loadDetails(items: LoadDetailsTargets, enforced?: boolean): Promise<void>;
|
|
26
26
|
private processLoadDetailsResult;
|
|
27
27
|
protected getDetails(route: Route): Promise<void>;
|
|
28
28
|
protected buildRouteInfo(descr: RouteApiDescription, isLocal?: boolean): RouteInfo;
|
|
@@ -169,9 +169,9 @@ class RoutesApiLoader extends types_1.Loader {
|
|
|
169
169
|
return failed;
|
|
170
170
|
});
|
|
171
171
|
}
|
|
172
|
-
loadDetails(
|
|
173
|
-
return __awaiter(this,
|
|
174
|
-
const failed = yield this.loadDetailsFromRepo(items);
|
|
172
|
+
loadDetails(items_1) {
|
|
173
|
+
return __awaiter(this, arguments, void 0, function* (items, enforced = false) {
|
|
174
|
+
const failed = enforced ? items : yield this.loadDetailsFromRepo(items);
|
|
175
175
|
const promises = failed.map(i => this.getDetails(i.route));
|
|
176
176
|
const res = yield Promise.allSettled(promises);
|
|
177
177
|
yield this.processLoadDetailsResult(res, items, true);
|
|
@@ -122,7 +122,7 @@ let RoutesDbLoader = (() => {
|
|
|
122
122
|
}
|
|
123
123
|
getDetails(id) {
|
|
124
124
|
return __awaiter(this, void 0, void 0, function* () {
|
|
125
|
-
const descr = this.
|
|
125
|
+
const descr = this.getDescription(id);
|
|
126
126
|
if (!descr)
|
|
127
127
|
return;
|
|
128
128
|
const details = yield this.loadDetailRecord(descr);
|
|
@@ -217,29 +217,34 @@ let RoutesDbLoader = (() => {
|
|
|
217
217
|
}
|
|
218
218
|
loadDetailRecord(target) {
|
|
219
219
|
return __awaiter(this, void 0, void 0, function* () {
|
|
220
|
-
var _a;
|
|
221
220
|
const description = (target.description || target);
|
|
222
221
|
const repo = (description === null || description === void 0 ? void 0 : description.hasVideo) ? this.getVideosRepo() : this.getRoutesRepo();
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
catch (err) {
|
|
233
|
-
this.logger.logEvent({ message: 'could not load route details', id: (description === null || description === void 0 ? void 0 : description.legacyId) || (description === null || description === void 0 ? void 0 : description.id), title: description === null || description === void 0 ? void 0 : description.title, reason: err.message, stack: err.stack });
|
|
234
|
-
if (description.id && description.legacyId !== description.id) {
|
|
235
|
-
try {
|
|
236
|
-
details = (yield repo.read(description.id));
|
|
237
|
-
description.originalName = details.title;
|
|
238
|
-
}
|
|
239
|
-
catch (err) {
|
|
240
|
-
this.logger.logEvent({ message: 'could not load route details', id: (description === null || description === void 0 ? void 0 : description.legacyId) || (description === null || description === void 0 ? void 0 : description.id), title: description === null || description === void 0 ? void 0 : description.title, reason: err.message, stack: err.stack });
|
|
222
|
+
const loadFromRepo = (id_1, ...args_1) => __awaiter(this, [id_1, ...args_1], void 0, function* (id, logErrors = true) {
|
|
223
|
+
var _a;
|
|
224
|
+
try {
|
|
225
|
+
const res = yield repo.read(id);
|
|
226
|
+
if (res) {
|
|
227
|
+
description.originalName = res.title;
|
|
228
|
+
if (description.hasVideo && !description.segments) {
|
|
229
|
+
description.segments = ((_a = res.video) === null || _a === void 0 ? void 0 : _a.selectableSegments) || res.selectableSegments;
|
|
230
|
+
}
|
|
241
231
|
}
|
|
232
|
+
else if (logErrors)
|
|
233
|
+
this.logger.logEvent({ message: 'could not load route details', id, title: description === null || description === void 0 ? void 0 : description.title, reason: 'no data received' });
|
|
234
|
+
return res;
|
|
242
235
|
}
|
|
236
|
+
catch (err) {
|
|
237
|
+
if (logErrors)
|
|
238
|
+
this.logger.logEvent({ message: 'could not load route details', id, title: description === null || description === void 0 ? void 0 : description.title, reason: err.message, stack: err.stack });
|
|
239
|
+
return null;
|
|
240
|
+
}
|
|
241
|
+
});
|
|
242
|
+
let details;
|
|
243
|
+
if (description.legacyId) {
|
|
244
|
+
details = yield loadFromRepo(description.legacyId, false);
|
|
245
|
+
}
|
|
246
|
+
if (!details) {
|
|
247
|
+
details = yield loadFromRepo(description.id);
|
|
243
248
|
}
|
|
244
249
|
if (!details) {
|
|
245
250
|
return;
|