import fs from 'fs'; import nodePath from 'node:path'; import { finished } from 'stream/promises'; import type { SongMeta, ServerCreds } from './services/jellyfin.ts'; import { getSongFileBuffer } from './services/jellyfin.ts'; const QUEUE: (() => Promise)[] = []; let downloadCount = 0; const DOWNLOAD_LIMIT = 10; export const downloadSongs = async ( creds: ServerCreds, songs: SongMeta[], path: string, ) => { const promises = songs.map(s => getSongDownloader(creds, s, path)); QUEUE.push(...promises); processQueue(); await Promise.all(promises); }; const getSongDownloader = (creds: ServerCreds, song: SongMeta, path: string) => async () => { const extension = song.Path.split('.').pop(); const filePath = nodePath.join(path, `${song.Id}.${extension}`); try { const write = fs.createWriteStream(filePath, { flags: 'wx', }); console.log('Downloading: ', filePath); const download = await getSongFileBuffer(creds, song.Id); await finished(download.pipe(write)); } catch (err: any) { if (err?.code !== 'EEXIST') { throw err; } console.log('File already exists, skipping: ', filePath); } }; const processQueue = () => { if (downloadCount < DOWNLOAD_LIMIT && QUEUE.length) { downloadCount++; const next = QUEUE.shift(); next && next().then(() => { downloadCount--; processQueue(); }); processQueue(); } };