jellyfin-to-m3u/lib/fileDownloader.ts

54 lines
1.4 KiB
TypeScript
Raw Permalink Normal View History

2024-08-20 06:19:59 +00:00
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<void>)[] = [];
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();
}
};