diff --git a/server/src/main.ts b/server/src/main.ts index f0b5b26..99901fa 100644 --- a/server/src/main.ts +++ b/server/src/main.ts @@ -32,9 +32,11 @@ export function saveSettings(newSettings: any) { settings = newSettings } -export const queueOrder: string[] = [] -export const queue: any = {} -let currentJob: any = null +export let queueOrder: string[] = [] +export let queue: any = {} +export let currentJob: any = null + +restoreQueueFromDisk() export async function addToQueue(dz: any, url: string, bitrate: number) { if (!dz.logged_in) throw new NotLoggedIn() @@ -58,7 +60,12 @@ export async function addToQueue(dz: any, url: string, bitrate: number) { queueOrder.push(downloadObj.uuid) fs.writeFileSync(configFolder + `queue${sep}order.json`, JSON.stringify(queueOrder)) queue[downloadObj.uuid] = downloadObj.getEssentialDict() - fs.writeFileSync(configFolder + `queue${sep}${downloadObj.uuid}.json`, JSON.stringify(downloadObj.toDict())) + queue[downloadObj.uuid].status = "inQueue" + + let savedObject = downloadObj.toDict() + savedObject.status = "inQueue" + fs.writeFileSync(configFolder + `queue${sep}${downloadObj.uuid}.json`, JSON.stringify(savedObject)) + slimmedObjects.push(downloadObj.getSlimmedDict()) }) if (isSingleObject) listener.send('addedToQueue', downloadObjs[0].getSlimmedDict()) @@ -76,7 +83,7 @@ async function startQueue(dz: any): Promise { } currentJob = true // lock currentJob - const currentUUID: string | undefined = queueOrder.shift() + const currentUUID: string = queueOrder.shift() || "" const currentItem: any = JSON.parse(fs.readFileSync(configFolder + `queue${sep}${currentUUID}.json`).toString()) let downloadObject: any switch (currentItem.__type__) { @@ -93,7 +100,65 @@ async function startQueue(dz: any): Promise { } currentJob = new Downloader(dz, downloadObject, settings, listener) listener.send('startDownload', currentUUID) + queue[currentUUID].status = "downloading" await currentJob.start() + + // Set status + if (downloadObject.failed == downloadObject.size){ + queue[currentUUID].status = "failed" + } else if(downloadObject.failed > 0){ + queue[currentUUID].status = "withErrors" + } else { + queue[currentUUID].status = "completed" + } + + let savedObject = downloadObject.getSlimmedDict() + savedObject.status = queue[currentUUID].status + + // Save queue status + fs.writeFileSync(configFolder + `queue${sep}${currentUUID}.json`, JSON.stringify(savedObject)) + fs.writeFileSync(configFolder + `queue${sep}order.json`, JSON.stringify(queueOrder)) + currentJob = null } while (queueOrder.length) } + +export function clearCompletedDownloads(){ + Object.values(queue).forEach((downloadObject: any) => { + if (downloadObject.status === "completed"){ + fs.unlinkSync(configFolder + `queue${sep}${downloadObject.uuid}.json`) + delete queue[downloadObject.uuid] + } + }) + listener.send("removedFinishedDownloads") +} + +export function restoreQueueFromDisk(){ + if (!fs.existsSync(configFolder + 'queue')) fs.mkdirSync(configFolder + 'queue') + const allItems: string[] = fs.readdirSync(configFolder + 'queue') + allItems.forEach((filename: string) => { + if (filename == 'order.json'){ + queueOrder = JSON.parse(fs.readFileSync(configFolder + `queue${sep}order.json`).toString()) + } else { + const currentItem: any = JSON.parse(fs.readFileSync(configFolder + `queue${sep}${filename}`).toString()) + if (currentItem.status === 'inQueue'){ + let downloadObject: any + switch (currentItem.__type__) { + case 'Single': + downloadObject = new Single(currentItem) + break + case 'Collection': + downloadObject = new Collection(currentItem) + break + case 'Convertable': + downloadObject = new Convertable(currentItem) + break + } + queue[downloadObject.uuid] = downloadObject.getEssentialDict() + queue[downloadObject.uuid].status = "inQueue" + } else { + queue[currentItem.uuid] = currentItem + } + } + }) +} diff --git a/server/src/routes/api/get/getQueue.ts b/server/src/routes/api/get/getQueue.ts new file mode 100644 index 0000000..fca3a7a --- /dev/null +++ b/server/src/routes/api/get/getQueue.ts @@ -0,0 +1,23 @@ +// @ts-expect-error +import { Deezer } from 'deezer-js' +import { ApiHandler } from '../../../types' +import { queueOrder, queue, currentJob } from '../../../main' + +const path: ApiHandler['path'] = '/getQueue' + +let homeCache: any + +const handler: ApiHandler['handler'] = async (req, res) => { + let result = { + queue, + order: queueOrder, + currentItem: "", + } + if (currentJob) result.currentItem = currentJob.downloadObject.uuid + + res.send(result) +} + +const apiHandler: ApiHandler = { path, handler } + +export default apiHandler diff --git a/server/src/routes/api/get/index.ts b/server/src/routes/api/get/index.ts index 2c0ca91..6f9892f 100644 --- a/server/src/routes/api/get/index.ts +++ b/server/src/routes/api/get/index.ts @@ -11,6 +11,7 @@ import getUserAlbums from './getUserAlbums' import getUserArtists from './getUserArtists' import getUserPlaylists from './getUserPlaylists' import getUserFavorites from './getUserFavorites' +import getQueue from './getQueue' export default [ albumSearch, @@ -25,5 +26,6 @@ export default [ getUserAlbums, getUserArtists, getUserPlaylists, - getUserFavorites + getUserFavorites, + getQueue ] diff --git a/server/src/websocket/modules/index.ts b/server/src/websocket/modules/index.ts index d9dd639..e68634b 100644 --- a/server/src/websocket/modules/index.ts +++ b/server/src/websocket/modules/index.ts @@ -1,3 +1,7 @@ import saveSettings from './saveSettings' +import removeFinishedDownloads from './removeFinishedDownloads' -export default [saveSettings] +export default [ + saveSettings, + removeFinishedDownloads +] diff --git a/server/src/websocket/modules/removeFinishedDownloads.ts b/server/src/websocket/modules/removeFinishedDownloads.ts index e69de29..49c79ff 100644 --- a/server/src/websocket/modules/removeFinishedDownloads.ts +++ b/server/src/websocket/modules/removeFinishedDownloads.ts @@ -0,0 +1,12 @@ +import { Server as WsServer } from 'ws' +import { consoleInfo } from '../../helpers/errors' +import { clearCompletedDownloads } from '../../main' + +const eventName = 'removeFinishedDownloads' + +const cb = (_: any, __: any, ___: WsServer) => { + clearCompletedDownloads() + consoleInfo('Completed downloads cleared') +} + +export default { eventName, cb }