Stremlined dependencies | built ad'Hoc http server

This commit is contained in:
2022-02-05 13:35:27 +01:00
parent fede4df965
commit 044004fd05
7 changed files with 123 additions and 277 deletions

View File

@@ -0,0 +1,86 @@
import http from 'http';
import url from 'url';
import fs, { open, close } from 'fs';
import { parse, join } from 'path';
namespace server {
export const mimes = {
'.html': 'text/html',
'.ico': 'image/x-icon',
'.js': 'text/javascript',
'.json': 'application/json',
'.css': 'text/css',
'.png': 'image/png',
'.jpg': 'image/jpeg',
'.webp': 'image/webp',
};
}
class Jean {
private workingDir: string;
/**
* Jean static file server its only purpose is serving SPA and images
* with the lowest impact possible.
* @param workingDir sets the root directory automatically trying index.html
* If specified the file in addition to the directory it will serve the
* file directly.
* *e.g* new Jean(path.join(__dirname, 'dist')) will try
* index.html from the dist directory;
* @author me :D
*/
constructor(workingDir: string) {
this.workingDir = workingDir;
}
/**
* Create a static file server
* @returns an instance of a standard NodeJS http.Server
*/
public createServer(): http.Server {
return http.createServer((req, res) => {
// parse the current given url
const parsedUrl = url.parse(req.url, false)
// extract the pathname and guard it with the working dir
let pathname = join(this.workingDir, `.${parsedUrl.pathname}`);
// extract the file extension
const ext = parse(pathname).ext;
// open the file or directory and fetch its descriptor
open(pathname, 'r', (err, fd) => {
// whoops, not found, send a 404
if (err) {
res.statusCode = 404;
res.end(`File ${pathname} not found!`);
return;
}
// something's gone wrong it's not a file or a directory
fs.fstat(fd, (err, stat) => {
if (err) {
res.statusCode = 500;
res.end(err);
}
// try file index.html
if (stat.isDirectory()) {
pathname = join(pathname, 'index.html')
}
// read the file
fs.readFile(pathname, (err, data) => {
if (err) {
res.statusCode = 500;
res.end(`Error reading the file: ${err}`);
} else {
// infer it's extension otherwise it's the index.html
res.setHeader('Content-type', server.mimes[ext] || 'text/html');
res.end(data);
close(fd);
}
});
})
});
})
}
}
export default Jean;

View File

@@ -2,6 +2,7 @@ import { spawn } from 'child_process';
import { join } from 'path';
import { Readable } from 'stream';
import { deleteDownloadByPID, insertDownload } from '../db/db';
import { ISettings } from '../interfaces/ISettings';
import Logger from '../utils/BetterLogger';
const log = new Logger();
@@ -9,15 +10,15 @@ const log = new Logger();
/**
* Represents a download process that spawns yt-dlp.
* @constructor
* @param {string} url - The downlaod url.
* @param {Array<String>} params - The cli arguments passed by the frontend.
* @param {*} settings - The download settings passed by the frontend.
* @param url - The downlaod url.
* @param params - The cli arguments passed by the frontend.
* @param settings - The download settings passed by the frontend.
*/
class Process {
private url: string;
private params: Array<string>;
private settings: any;
private settings: ISettings;
private stdout: Readable;
private pid: number;
private info: any;
@@ -35,11 +36,11 @@ class Process {
/**
* function that launch the download process, sets the stdout property and the pid
* @param {Function} callback not yet implemented
* @returns {Promise<this>} the process instance
* @param callback not yet implemented
* @returns the process instance
*/
async start(callback?: Function): Promise<this> {
await this.#__internalGetInfo();
await this.internalGetInfo();
const ytldp = spawn(this.exePath,
['-o', `${this.settings?.download_path || 'downloads/'}%(title)s.%(ext)s`]
@@ -69,8 +70,8 @@ class Process {
* function used internally by the download process to fetch information, usually thumbnail and title
* @returns Promise to the lock
*/
async #__internalGetInfo() {
let lock = true;
private async internalGetInfo() {
this.lock = true;
let stdoutChunks = [];
const ytdlpInfo = spawn(this.exePath, ['-s', '-j', this.url]);
@@ -93,7 +94,7 @@ class Process {
}
});
if (!lock) {
if (!this.lock) {
return true;
}
}

View File

@@ -3,14 +3,15 @@ import { from, interval } from 'rxjs';
import { throttle } from 'rxjs/operators';
import { pruneDownloads } from '../db/db';
import { killProcess } from '../utils/procUtils';
import { Socket } from 'socket.io';
import { IPayload } from '../interfaces/IPayload';
import { ISettings } from '../interfaces/ISettings';
import Logger from '../utils/BetterLogger';
import Process from './Process';
import ProcessPool from './ProcessPool';
import { Socket } from 'socket.io';
import { IPayload } from '../interfaces/IPayload';
// settings read from settings.json
let settings;
let settings: ISettings;
let coldRestart = true;
const log = new Logger();
@@ -20,7 +21,7 @@ try {
settings = require('../settings.json');
}
catch (e) {
console.warn("settings.json not found");
log.warn('dl', 'settings.json not found');
}
/**
@@ -95,7 +96,6 @@ export async function retriveDownload(socket: Socket) {
if (coldRestart) {
coldRestart = false;
let downloads = await pruneDownloads();
console.log(downloads)
// sanitize
downloads = [... new Set(downloads.filter(el => el !== undefined))];
log.info('dl', `Cold restart, retrieving ${downloads.length} jobs`)