244 lines
		
	
	
		
			12 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			244 lines
		
	
	
		
			12 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
| "use strict";
 | |
| var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
 | |
|     function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
 | |
|     return new (P || (P = Promise))(function (resolve, reject) {
 | |
|         function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
 | |
|         function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
 | |
|         function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
 | |
|         step((generator = generator.apply(thisArg, _arguments || [])).next());
 | |
|     });
 | |
| };
 | |
| var __importDefault = (this && this.__importDefault) || function (mod) {
 | |
|     return (mod && mod.__esModule) ? mod : { "default": mod };
 | |
| };
 | |
| Object.defineProperty(exports, "__esModule", { value: true });
 | |
| exports.restoreQueueFromDisk = exports.clearCompletedDownloads = exports.cancelAllDownloads = exports.cancelDownload = exports.startQueue = exports.addToQueue = exports.currentJob = exports.queue = exports.queueOrder = exports.saveSettings = exports.getSettings = exports.listener = exports.plugins = exports.getArlFromAccessToken = exports.getAccessToken = exports.sessionDZ = exports.settings = exports.configFolder = exports.defaultSettings = void 0;
 | |
| const fs_1 = __importDefault(require("fs"));
 | |
| const path_1 = require("path");
 | |
| const uuid_1 = require("uuid");
 | |
| // @ts-expect-error
 | |
| const deemix_1 = __importDefault(require("deemix"));
 | |
| const ws_1 = __importDefault(require("ws"));
 | |
| const app_1 = require("./app");
 | |
| const errors_1 = require("./helpers/errors");
 | |
| const Downloader = deemix_1.default.downloader.Downloader;
 | |
| const { Single, Collection, Convertable } = deemix_1.default.types.downloadObjects;
 | |
| exports.defaultSettings = deemix_1.default.settings.DEFAULTS;
 | |
| exports.configFolder = deemix_1.default.utils.localpaths.getConfigFolder();
 | |
| exports.settings = deemix_1.default.settings.load(exports.configFolder);
 | |
| exports.sessionDZ = {};
 | |
| exports.getAccessToken = deemix_1.default.utils.deezer.getAccessToken;
 | |
| exports.getArlFromAccessToken = deemix_1.default.utils.deezer.getArlFromAccessToken;
 | |
| exports.plugins = {
 | |
|     spotify: new deemix_1.default.plugins.spotify()
 | |
| };
 | |
| exports.plugins.spotify.setup();
 | |
| exports.listener = {
 | |
|     send(key, data) {
 | |
|         console.log(key, data);
 | |
|         app_1.wss.clients.forEach(client => {
 | |
|             if (client.readyState === ws_1.default.OPEN) {
 | |
|                 client.send(JSON.stringify({ key, data }));
 | |
|             }
 | |
|         });
 | |
|     }
 | |
| };
 | |
| function getSettings() {
 | |
|     return { settings: exports.settings, defaultSettings: exports.defaultSettings, spotifySettings: exports.plugins.spotify.getCredentials() };
 | |
| }
 | |
| exports.getSettings = getSettings;
 | |
| function saveSettings(newSettings, newSpotifySettings) {
 | |
|     deemix_1.default.settings.save(newSettings, exports.configFolder);
 | |
|     exports.settings = newSettings;
 | |
|     exports.plugins.spotify.setCredentials(newSpotifySettings);
 | |
| }
 | |
| exports.saveSettings = saveSettings;
 | |
| exports.queueOrder = [];
 | |
| exports.queue = {};
 | |
| exports.currentJob = null;
 | |
| restoreQueueFromDisk();
 | |
| function addToQueue(dz, url, bitrate) {
 | |
|     return __awaiter(this, void 0, void 0, function* () {
 | |
|         if (!dz.logged_in)
 | |
|             throw new errors_1.NotLoggedIn();
 | |
|         let downloadObjs = [];
 | |
|         let link = "";
 | |
|         const requestUUID = uuid_1.v4();
 | |
|         if (url.length > 1) {
 | |
|             exports.listener.send("startGeneratingItems", { uuid: requestUUID, total: url.length });
 | |
|         }
 | |
|         for (let i = 0; i < url.length; i++) {
 | |
|             link = url[i];
 | |
|             console.log(`Adding ${link} to queue`);
 | |
|             let downloadObj = yield deemix_1.default.generateDownloadObject(dz, link, bitrate, exports.plugins, exports.listener);
 | |
|             if (Array.isArray(downloadObj)) {
 | |
|                 downloadObjs.concat(downloadObj);
 | |
|             }
 | |
|             else {
 | |
|                 downloadObjs.push(downloadObj);
 | |
|             }
 | |
|         }
 | |
|         if (url.length > 1) {
 | |
|             exports.listener.send("finishGeneratingItems", { uuid: requestUUID, total: downloadObjs.length });
 | |
|         }
 | |
|         const isSingleObject = downloadObjs.length == 1;
 | |
|         const slimmedObjects = [];
 | |
|         downloadObjs.forEach((downloadObj) => {
 | |
|             // Check if element is already in queue
 | |
|             if (Object.keys(exports.queue).includes(downloadObj.uuid))
 | |
|                 throw new errors_1.AlreadyInQueue(downloadObj.getEssentialDict(), !isSingleObject);
 | |
|             // Save queue status when adding something to the queue
 | |
|             if (!fs_1.default.existsSync(exports.configFolder + 'queue'))
 | |
|                 fs_1.default.mkdirSync(exports.configFolder + 'queue');
 | |
|             exports.queueOrder.push(downloadObj.uuid);
 | |
|             fs_1.default.writeFileSync(exports.configFolder + `queue${path_1.sep}order.json`, JSON.stringify(exports.queueOrder));
 | |
|             exports.queue[downloadObj.uuid] = downloadObj.getEssentialDict();
 | |
|             exports.queue[downloadObj.uuid].status = 'inQueue';
 | |
|             const savedObject = downloadObj.toDict();
 | |
|             savedObject.status = 'inQueue';
 | |
|             fs_1.default.writeFileSync(exports.configFolder + `queue${path_1.sep}${downloadObj.uuid}.json`, JSON.stringify(savedObject));
 | |
|             slimmedObjects.push(downloadObj.getSlimmedDict());
 | |
|         });
 | |
|         if (isSingleObject)
 | |
|             exports.listener.send('addedToQueue', downloadObjs[0].getSlimmedDict());
 | |
|         else
 | |
|             exports.listener.send('addedToQueue', slimmedObjects);
 | |
|         startQueue(dz);
 | |
|         return slimmedObjects;
 | |
|     });
 | |
| }
 | |
| exports.addToQueue = addToQueue;
 | |
| function startQueue(dz) {
 | |
|     return __awaiter(this, void 0, void 0, function* () {
 | |
|         do {
 | |
|             if (exports.currentJob !== null || exports.queueOrder.length === 0) {
 | |
|                 // Should not start another download
 | |
|                 return null;
 | |
|             }
 | |
|             exports.currentJob = true; // lock currentJob
 | |
|             const currentUUID = exports.queueOrder.shift() || '';
 | |
|             console.log(currentUUID);
 | |
|             exports.queue[currentUUID].status = 'downloading';
 | |
|             const currentItem = JSON.parse(fs_1.default.readFileSync(exports.configFolder + `queue${path_1.sep}${currentUUID}.json`).toString());
 | |
|             let downloadObject;
 | |
|             switch (currentItem.__type__) {
 | |
|                 case 'Single':
 | |
|                     downloadObject = new Single(currentItem);
 | |
|                     break;
 | |
|                 case 'Collection':
 | |
|                     downloadObject = new Collection(currentItem);
 | |
|                     break;
 | |
|                 case 'Convertable':
 | |
|                     downloadObject = new Convertable(currentItem);
 | |
|                     downloadObject = yield exports.plugins[downloadObject.plugin].convert(dz, downloadObject, exports.settings, exports.listener);
 | |
|                     fs_1.default.writeFileSync(exports.configFolder + `queue${path_1.sep}${downloadObject.uuid}.json`, JSON.stringify(Object.assign(Object.assign({}, downloadObject.toDict()), { status: 'inQueue' })));
 | |
|                     break;
 | |
|             }
 | |
|             exports.currentJob = new Downloader(dz, downloadObject, exports.settings, exports.listener);
 | |
|             exports.listener.send('startDownload', currentUUID);
 | |
|             yield exports.currentJob.start();
 | |
|             if (!downloadObject.isCanceled) {
 | |
|                 // Set status
 | |
|                 if (downloadObject.failed == downloadObject.size) {
 | |
|                     exports.queue[currentUUID].status = 'failed';
 | |
|                 }
 | |
|                 else if (downloadObject.failed > 0) {
 | |
|                     exports.queue[currentUUID].status = 'withErrors';
 | |
|                 }
 | |
|                 else {
 | |
|                     exports.queue[currentUUID].status = 'completed';
 | |
|                 }
 | |
|                 const savedObject = downloadObject.getSlimmedDict();
 | |
|                 savedObject.status = exports.queue[currentUUID].status;
 | |
|                 // Save queue status
 | |
|                 exports.queue[currentUUID] = savedObject;
 | |
|                 fs_1.default.writeFileSync(exports.configFolder + `queue${path_1.sep}${currentUUID}.json`, JSON.stringify(savedObject));
 | |
|             }
 | |
|             console.log(exports.queueOrder);
 | |
|             fs_1.default.writeFileSync(exports.configFolder + `queue${path_1.sep}order.json`, JSON.stringify(exports.queueOrder));
 | |
|             exports.currentJob = null;
 | |
|         } while (exports.queueOrder.length);
 | |
|     });
 | |
| }
 | |
| exports.startQueue = startQueue;
 | |
| function cancelDownload(uuid) {
 | |
|     if (Object.keys(exports.queue).includes(uuid)) {
 | |
|         switch (exports.queue[uuid].status) {
 | |
|             case 'downloading':
 | |
|                 exports.currentJob.downloadObject.isCanceled = true;
 | |
|                 exports.listener.send('cancellingCurrentItem', uuid);
 | |
|                 break;
 | |
|             case 'inQueue':
 | |
|                 exports.queueOrder.splice(exports.queueOrder.indexOf(uuid), 1);
 | |
|                 fs_1.default.writeFileSync(exports.configFolder + `queue${path_1.sep}order.json`, JSON.stringify(exports.queueOrder));
 | |
|             // break
 | |
|             default:
 | |
|                 // This gets called even in the 'inQueue' case. Is this the expected behaviour? If no, de-comment the break
 | |
|                 exports.listener.send('removedFromQueue', uuid);
 | |
|                 break;
 | |
|         }
 | |
|         fs_1.default.unlinkSync(exports.configFolder + `queue${path_1.sep}${uuid}.json`);
 | |
|         delete exports.queue[uuid];
 | |
|     }
 | |
| }
 | |
| exports.cancelDownload = cancelDownload;
 | |
| function cancelAllDownloads() {
 | |
|     exports.queueOrder = [];
 | |
|     let currentItem = null;
 | |
|     Object.values(exports.queue).forEach((downloadObject) => {
 | |
|         if (downloadObject.status == 'downloading') {
 | |
|             exports.currentJob.downloadObject.isCanceled = true;
 | |
|             exports.listener.send('cancellingCurrentItem', downloadObject.uuid);
 | |
|             currentItem = downloadObject.uuid;
 | |
|         }
 | |
|         fs_1.default.unlinkSync(exports.configFolder + `queue${path_1.sep}${downloadObject.uuid}.json`);
 | |
|         delete exports.queue[downloadObject.uuid];
 | |
|     });
 | |
|     fs_1.default.writeFileSync(exports.configFolder + `queue${path_1.sep}order.json`, JSON.stringify(exports.queueOrder));
 | |
|     exports.listener.send('removedAllDownloads', currentItem);
 | |
| }
 | |
| exports.cancelAllDownloads = cancelAllDownloads;
 | |
| function clearCompletedDownloads() {
 | |
|     Object.values(exports.queue).forEach((downloadObject) => {
 | |
|         if (downloadObject.status === 'completed') {
 | |
|             fs_1.default.unlinkSync(exports.configFolder + `queue${path_1.sep}${downloadObject.uuid}.json`);
 | |
|             delete exports.queue[downloadObject.uuid];
 | |
|         }
 | |
|     });
 | |
|     exports.listener.send('removedFinishedDownloads');
 | |
| }
 | |
| exports.clearCompletedDownloads = clearCompletedDownloads;
 | |
| function restoreQueueFromDisk() {
 | |
|     if (!fs_1.default.existsSync(exports.configFolder + 'queue'))
 | |
|         fs_1.default.mkdirSync(exports.configFolder + 'queue');
 | |
|     const allItems = fs_1.default.readdirSync(exports.configFolder + 'queue');
 | |
|     allItems.forEach((filename) => {
 | |
|         if (filename == 'order.json') {
 | |
|             exports.queueOrder = JSON.parse(fs_1.default.readFileSync(exports.configFolder + `queue${path_1.sep}order.json`).toString());
 | |
|         }
 | |
|         else {
 | |
|             const currentItem = JSON.parse(fs_1.default.readFileSync(exports.configFolder + `queue${path_1.sep}${filename}`).toString());
 | |
|             if (currentItem.status === 'inQueue') {
 | |
|                 let downloadObject;
 | |
|                 switch (currentItem.__type__) {
 | |
|                     case 'Single':
 | |
|                         downloadObject = new Single(currentItem);
 | |
|                         break;
 | |
|                     case 'Collection':
 | |
|                         downloadObject = new Collection(currentItem);
 | |
|                         break;
 | |
|                     case 'Convertable':
 | |
|                         downloadObject = new Convertable(currentItem);
 | |
|                         break;
 | |
|                 }
 | |
|                 exports.queue[downloadObject.uuid] = downloadObject.getEssentialDict();
 | |
|                 exports.queue[downloadObject.uuid].status = 'inQueue';
 | |
|             }
 | |
|             else {
 | |
|                 exports.queue[currentItem.uuid] = currentItem;
 | |
|             }
 | |
|         }
 | |
|     });
 | |
| }
 | |
| exports.restoreQueueFromDisk = restoreQueueFromDisk;
 |