Implemented simple queue structure
This commit is contained in:
parent
7b16ddc91a
commit
dbc1e2bcfb
@ -15,7 +15,7 @@
|
||||
"dependencies": {
|
||||
"cookie-parser": "1.4.5",
|
||||
"debug": "2.6.9",
|
||||
"deemix": "0.0.2",
|
||||
"deemix": "0.0.3",
|
||||
"deezer-js": "0.0.10",
|
||||
"dotenv": "8.2.0",
|
||||
"express": "4.17.1",
|
||||
|
@ -1,12 +1,110 @@
|
||||
// @ts-expect-error
|
||||
import deemix from 'deemix'
|
||||
import fs from 'fs'
|
||||
import {sep} from 'path'
|
||||
import { wss } from './app'
|
||||
import WebSocket from 'ws'
|
||||
|
||||
export const loadSettings = deemix.settings.load
|
||||
const Downloader = deemix.downloader.Downloader
|
||||
const { Single, Collection, Convertable } = deemix.types.downloadObjects
|
||||
export const defaultSettings: any = deemix.settings.DEFAULTS
|
||||
export let settings: any = loadSettings()
|
||||
export const configFolder: string = deemix.utils.localpaths.getConfigFolder()
|
||||
export let settings: any = deemix.settings.load(configFolder)
|
||||
export let sessionDZ: any = {}
|
||||
|
||||
let deemixPlugins = {}
|
||||
|
||||
export const listener = {
|
||||
send: function(key:string, data:any){
|
||||
console.log(key, data)
|
||||
wss.clients.forEach(client => {
|
||||
if (client.readyState === WebSocket.OPEN) {
|
||||
client.send(JSON.stringify({key, data}))
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
export function saveSettings(newSettings: any) {
|
||||
deemix.settings.save(newSettings)
|
||||
deemix.settings.save(newSettings, configFolder)
|
||||
settings = newSettings
|
||||
}
|
||||
|
||||
export let queueOrder: string[] = []
|
||||
export let queue: any = {}
|
||||
export let currentJob: any = null
|
||||
|
||||
export async function addToQueue(dz: any, url: string, bitrate: number){
|
||||
if (!dz.logged_in) throw new NotLoggedIn
|
||||
console.log(`Adding ${url} to queue`)
|
||||
let downloadObj = await deemix.generateDownloadObject(dz, url, bitrate, deemixPlugins, listener)
|
||||
|
||||
// Check if element is already in queue
|
||||
if (queueOrder.includes(downloadObj.uuid))
|
||||
throw new AlreadyInQueue(downloadObj.getEssentialDict())
|
||||
|
||||
// Save queue status when adding something to the queue
|
||||
if (!fs.existsSync(configFolder+'queue')) fs.mkdirSync(configFolder+'queue')
|
||||
|
||||
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()))
|
||||
listener.send('addedToQueue', downloadObj.getSlimmedDict())
|
||||
|
||||
startQueue(dz)
|
||||
return queue[downloadObj.uuid]
|
||||
}
|
||||
|
||||
async function startQueue(dz: any): Promise<any>{
|
||||
do {
|
||||
if (currentJob !== null || queueOrder.length === 0){
|
||||
// Should not start another download
|
||||
return null
|
||||
}
|
||||
currentJob = true // lock currentJob
|
||||
|
||||
let currentUUID: string | undefined = queueOrder.shift()
|
||||
let currentItem: any = JSON.parse(fs.readFileSync(configFolder+`queue${sep}${currentUUID}.json`).toString())
|
||||
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)
|
||||
// Convert object here
|
||||
break;
|
||||
}
|
||||
currentJob = new Downloader(dz, downloadObject, settings, listener)
|
||||
listener.send('startDownload', currentUUID)
|
||||
await currentJob.start()
|
||||
currentJob = null
|
||||
} while (queueOrder.length)
|
||||
}
|
||||
|
||||
class QueueError extends Error {
|
||||
constructor(message: string) {
|
||||
super(message)
|
||||
this.name = "QueueError"
|
||||
}
|
||||
}
|
||||
|
||||
class AlreadyInQueue extends QueueError {
|
||||
item: any
|
||||
constructor(dwObj: any) {
|
||||
super(`${dwObj.artist} - ${dwObj.title} is already in queue.`)
|
||||
this.name = "AlreadyInQueue"
|
||||
this.item = dwObj
|
||||
}
|
||||
}
|
||||
|
||||
class NotLoggedIn extends QueueError {
|
||||
constructor() {
|
||||
super(`You must be logged in to start a download.`)
|
||||
this.name = "NotLoggedIn"
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,38 @@
|
||||
// @ts-expect-error
|
||||
import { Deezer } from 'deezer-js'
|
||||
import { ApiHandler } from '../../../types'
|
||||
import { sessionDZ, addToQueue, settings } from '../../../main'
|
||||
|
||||
const path: ApiHandler['path'] = '/addToQueue'
|
||||
|
||||
const handler: ApiHandler['handler'] = async (req, res) => {
|
||||
if (!sessionDZ[req.session.id]) sessionDZ[req.session.id] = new Deezer()
|
||||
const dz = sessionDZ[req.session.id]
|
||||
|
||||
const url = req.query.url
|
||||
let bitrate = req.query.bitrate
|
||||
if (bitrate === 'null') bitrate = settings.maxBitrate
|
||||
let obj: any;
|
||||
|
||||
try {
|
||||
obj = await addToQueue(dz, url, bitrate)
|
||||
} catch (e){
|
||||
switch (e.name) {
|
||||
case 'AlreadyInQueue':
|
||||
res.send({result: false, errid: e.name, data: {url, bitrate, obj: e.data}})
|
||||
break
|
||||
default:
|
||||
console.error(e)
|
||||
case 'NotLoggedIn':
|
||||
res.send({result: false, errid: e.name, data: {url, bitrate}})
|
||||
break
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
res.send({result: true, data: {url, bitrate, obj}})
|
||||
}
|
||||
|
||||
const apiHandler: ApiHandler = { path, handler }
|
||||
|
||||
export default apiHandler
|
@ -1,3 +1,4 @@
|
||||
import loginArl from './login-arl'
|
||||
import addToQueue from './addToQueue'
|
||||
|
||||
export default [loginArl]
|
||||
export default [loginArl, addToQueue]
|
||||
|
@ -6,14 +6,6 @@ import wsModules from './modules'
|
||||
// ? Is this needed?
|
||||
// ? https://github.com/websockets/ws#how-to-detect-and-close-broken-connections
|
||||
|
||||
export const broadcast = function(wss:WsServer, key:string, data:any) {
|
||||
wss.clients.forEach(client => {
|
||||
if (client.readyState === WebSocket.OPEN) {
|
||||
client.send(JSON.stringify({key, data}))
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
export const registerWebsocket = (wss: WsServer) => {
|
||||
wss.on('connection', ws => {
|
||||
ws.on('message', (message)=>{
|
||||
|
@ -1,7 +1,6 @@
|
||||
import { Server as WsServer } from 'ws'
|
||||
import { consoleInfo } from '../../helpers/errors'
|
||||
import { saveSettings } from '../../main'
|
||||
import { broadcast } from '../index'
|
||||
import { saveSettings, listener } from '../../main'
|
||||
|
||||
const eventName = 'saveSettings'
|
||||
|
||||
@ -9,7 +8,7 @@ const cb = (data: any, ws: any, wss: WsServer) => {
|
||||
const {settings, spotifySettings} = data
|
||||
saveSettings(settings)
|
||||
consoleInfo('Settings saved')
|
||||
broadcast(wss, 'updateSettings', {settings, spotifySettings})
|
||||
listener.send('updateSettings', {settings, spotifySettings})
|
||||
}
|
||||
|
||||
export default { eventName, cb }
|
||||
|
@ -1878,10 +1878,10 @@ decompress-response@^6.0.0:
|
||||
dependencies:
|
||||
mimic-response "^3.1.0"
|
||||
|
||||
deemix@0.0.2:
|
||||
version "0.0.2"
|
||||
resolved "https://registry.yarnpkg.com/deemix/-/deemix-0.0.2.tgz#3b375834327d4d6bd1d1db072db976ced86746ee"
|
||||
integrity sha512-NhTAM2LcoNxit6GiQYlUUO0YaGUMWtN8brGt9HO5mkvbn2cKojF1k9BulmUt/38NoiVvfkqTEtSQD8RtD4qPIA==
|
||||
deemix@0.0.3:
|
||||
version "0.0.3"
|
||||
resolved "https://registry.yarnpkg.com/deemix/-/deemix-0.0.3.tgz#a32b1b3c8e99fe26ea7a326658e49b4892c96dd5"
|
||||
integrity sha512-cUsfliHRXWLOYB7K+UCN0Lmx3d4ueWfaQ/Xinhg8/cHetifJC4/CxD8YDdBArI7Fl3StkJVGt45BajU/z00k6Q==
|
||||
dependencies:
|
||||
async "^3.2.0"
|
||||
browser-id3-writer "^4.4.0"
|
||||
|
Loading…
Reference in New Issue
Block a user