From 33d567aaeda17ff0a6db1b12df2de2df44cfab3a Mon Sep 17 00:00:00 2001 From: marcobaobao Date: Sun, 30 Jan 2022 12:18:36 +0100 Subject: [PATCH] Refactoring and small optimizations --- frontend/src/App.tsx | 31 +++++++++++++++++++++++-------- package.json | 4 ++-- server/src/core/Process.ts | 9 ++++++++- server/src/core/downloader.ts | 6 ++++-- server/src/db/db.ts | 27 +++++++++++++++------------ server/src/interfaces/IPayload.ts | 4 ++++ server/src/interfaces/IRecord.ts | 14 ++++++++++++++ server/src/main.ts | 4 ++++ server/src/utils/BetterLogger.ts | 14 +++++++------- server/src/utils/procUtils.ts | 12 ++++++++++-- 10 files changed, 91 insertions(+), 34 deletions(-) diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx index c13b0fb..9515fb1 100644 --- a/frontend/src/App.tsx +++ b/frontend/src/App.tsx @@ -9,7 +9,7 @@ import { Button, ButtonGroup, } from "react-bootstrap"; -import { X } from "react-bootstrap-icons"; +import { X, HddFill } from "react-bootstrap-icons"; import { buildMessage, updateInStateMap, validateDomain, validateIP } from "./utils"; import { IDLInfo, IDLInfoBase, IMessage } from "./interfaces"; import { MessageToast } from "./components/MessageToast"; @@ -31,6 +31,7 @@ export function App() { const [invalidIP, setInvalidIP] = useState(false); const [updatedBin, setUpdatedBin] = useState(false); const [showSettings, setShowSettings] = useState(false); + const [freeDiskSpace, setFreeDiskSpace] = useState(''); const [darkMode, setDarkMode] = useState(localStorage.getItem('theme') === 'dark'); const xaInput = useRef(null); @@ -53,6 +54,7 @@ export function App() { socket.on('connect', () => { setShowToast(true) socket.emit('fetch-jobs') + socket.emit('disk-space') }) return () => { socket.disconnect() @@ -80,6 +82,7 @@ export function App() { setHalt(false); updateInStateMap(data.pid, 'Done!', messageMap, setMessageMap); updateInStateMap(data.pid, 0, progressMap, setProgressMap); + socket.emit('disk-space') return; } updateInStateMap(data.pid, buildMessage(data), messageMap, setMessageMap); @@ -104,6 +107,13 @@ export function App() { document.body.classList.remove('dark'); }, [darkMode]) + /* Get disk free space */ + useEffect(() => { + socket.on('free-space', (res: string) => { + setFreeDiskSpace(res) + }) + }, []) + /* -------------------- component functions -------------------- */ /** @@ -282,6 +292,10 @@ export function App() { + + {' '} + {freeDiskSpace ? freeDiskSpace : '-'} + @@ -304,21 +318,22 @@ export function App() { /> :3022 - {' '} -
-    +
+
+ {' '} + : null } diff --git a/package.json b/package.json index ee2d031..d585019 100644 --- a/package.json +++ b/package.json @@ -3,8 +3,8 @@ "version": "1.1.0", "description": "A terrible webUI for yt-dlp, all-in-one solution.", "scripts": { - "start": "node server.js", - "dev": "nodemon app.js", + "start": "node dist/main.js", + "dev": "tsc --build -w", "build": "parcel build ./frontend/index.html --dist-dir ./dist/frontend", "build-server": "tsc --build", "build-all": "tsc --build && npm run build && npm run fetch", diff --git a/server/src/core/Process.ts b/server/src/core/Process.ts index 27b1130..59ce29d 100644 --- a/server/src/core/Process.ts +++ b/server/src/core/Process.ts @@ -52,7 +52,14 @@ class Process { log.info('proc', `Spawned a new process, pid: ${this.pid}`) - await insertDownload(this.url, this.info?.title, this.info?.thumbnail, null, this.pid); + await insertDownload( + this.url, + this.info?.title, + this.info?.thumbnail, + null, + this.params.reduce((prev, next) => `${prev} ${next}`), + this.pid + ); return this; } diff --git a/server/src/core/downloader.ts b/server/src/core/downloader.ts index 13c6268..1515cdc 100644 --- a/server/src/core/downloader.ts +++ b/server/src/core/downloader.ts @@ -95,7 +95,9 @@ export async function retriveDownload(socket: Socket) { if (coldRestart) { coldRestart = false; let downloads = await pruneDownloads(); - downloads = [... new Set(downloads)]; + console.log(downloads) + // sanitize + downloads = [... new Set(downloads.filter(el => el !== undefined))]; log.info('dl', `Cold restart, retrieving ${downloads.length} jobs`) for (const entry of downloads) { if (entry) { @@ -180,7 +182,7 @@ const formatter = (stdout: string, pid: number) => { switch (status) { case 'download': return { - status: cleanStdout[0].replace(/\[|\]|\r/g, ''), + status: 'download', progress: cleanStdout[1], size: cleanStdout[3], dlSpeed: cleanStdout[5], diff --git a/server/src/db/db.ts b/server/src/db/db.ts index 9c33f2d..9d0be96 100644 --- a/server/src/db/db.ts +++ b/server/src/db/db.ts @@ -1,5 +1,6 @@ import { v1 } from 'uuid'; import { existsInProc } from '../utils/procUtils'; +import { IRecord } from '../interfaces/IRecord'; import Logger from '../utils/BetterLogger'; const db = require('better-sqlite3')('downloads.db'); @@ -17,7 +18,8 @@ export async function init() { thumbnail text, created date, size text, - process_pid int NOT NULL, + params text, + pid int NOT NULL, PRIMARY KEY (uid) )`) } catch (e) { @@ -39,21 +41,22 @@ export async function get_db(): Promise { * @param {string} title the title fetched by the info process * @param {string} thumbnail the thumbnail url fetched by the info process * @param {string} size optional - the download size + * @param {string} params optional - the download parameters, cli arguments * @param {number} PID the pid of the downloader * @returns {Promise} the download UUID */ -export async function insertDownload(url: string, title: string, thumbnail: string, size: string, PID: number): Promise { +export async function insertDownload(url: string, title: string, thumbnail: string, size: string, params: string, PID: number): Promise { const uid = v1() try { db .prepare(` INSERT INTO downloads - (uid, url, title, thumbnail, size, process_pid) - VALUES (?, ?, ?, ?, ?, ?)` + (uid, url, title, thumbnail, size, params, pid) + VALUES (?, ?, ?, ?, ?, ?, ?)` ) - .run(uid, url, title, thumbnail, size, PID) + .run(uid, url, title, thumbnail, size, params, PID) } catch (error) { - log.err('db', 'some error occourred') + log.err('db', error) } return uid @@ -63,7 +66,7 @@ export async function insertDownload(url: string, title: string, thumbnail: stri * Retrieve all downloads from the database * @returns {ArrayLike} a collection of results */ -export async function retrieveAll(): Promise { +export async function retrieveAll(): Promise> { return db .prepare('SELECT * FROM downloads') .all() @@ -81,20 +84,20 @@ export async function deleteDownloadById(uid: string) { * Delete a download by its pid * @param {string} pid the to-be-deleted download pid */ -export async function deleteDownloadByPID(PID) { - db.prepare(`DELETE FROM downloads WHERE process_pid=${PID}`).run() +export async function deleteDownloadByPID(pid: number) { + db.prepare(`DELETE FROM downloads WHERE pid=${pid}`).run() } /** * Deletes the downloads that aren't active anymore * @returns {Promise} */ -export async function pruneDownloads(): Promise { +export async function pruneDownloads(): Promise> { const all = await retrieveAll() return all.map(job => { - if (existsInProc(job.process_pid)) { + if (existsInProc(job.pid)) { return job } - deleteDownloadByPID(job.process_pid) + deleteDownloadByPID(job.pid) }) } \ No newline at end of file diff --git a/server/src/interfaces/IPayload.ts b/server/src/interfaces/IPayload.ts index 25f1e04..f3cf324 100644 --- a/server/src/interfaces/IPayload.ts +++ b/server/src/interfaces/IPayload.ts @@ -1,3 +1,7 @@ +/** + * Represent a download payload sent by the frontend + */ + export interface IPayload { url: string params: Array | string, diff --git a/server/src/interfaces/IRecord.ts b/server/src/interfaces/IRecord.ts index e69de29..e4e6109 100644 --- a/server/src/interfaces/IRecord.ts +++ b/server/src/interfaces/IRecord.ts @@ -0,0 +1,14 @@ +/** + * Represent a download db record + */ + +export interface IRecord { + uid: string, + url: string, + title: string, + thumbnail: string, + created: Date, + size: string, + pid: number, + params: string, +} \ No newline at end of file diff --git a/server/src/main.ts b/server/src/main.ts index 511f8c2..79f54e9 100644 --- a/server/src/main.ts +++ b/server/src/main.ts @@ -9,6 +9,7 @@ import { ytdlpUpdater } from './utils/updater'; import { download, abortDownload, retriveDownload, abortAllDownloads } from './core/downloader'; import Logger from './utils/BetterLogger'; import { retrieveAll, init } from './db/db'; +import { getFreeDiskSpace } from './utils/procUtils'; const app = new Koa() const log = new Logger() @@ -45,6 +46,9 @@ io.on('connection', socket => { socket.on('retrieve-jobs', () => { retriveDownload(socket) }) + socket.on('disk-space', () => { + getFreeDiskSpace(socket) + }) }) io.on('disconnect', (socket) => { diff --git a/server/src/utils/BetterLogger.ts b/server/src/utils/BetterLogger.ts index 02902d9..678fabb 100644 --- a/server/src/utils/BetterLogger.ts +++ b/server/src/utils/BetterLogger.ts @@ -12,9 +12,9 @@ class Logger { * @param {string} proto the context/protocol/section outputting the message * @param {string} args the acutal message */ - info(proto: string, args: string) { + public info(proto: string, args: string) { process.stdout.write( - this.#__formatter(proto, args) + this.formatter(proto, args) ) } /** @@ -22,9 +22,9 @@ class Logger { * @param {string} proto the context/protocol/section outputting the message * @param {string} args the acutal message */ - warn(proto: string, args: string) { + public warn(proto: string, args: string) { process.stdout.write( - `${ansi.yellow}${this.#__formatter(proto, args)}${ansi.reset}` + `${ansi.yellow}${this.formatter(proto, args)}${ansi.reset}` ) } /** @@ -32,13 +32,13 @@ class Logger { * @param {string} proto the context/protocol/section outputting the message * @param {string} args the acutal message */ - err(proto: string, args: string) { + public err(proto: string, args: string) { process.stdout.write( - `${ansi.red}${this.#__formatter(proto, args)}${ansi.reset}` + `${ansi.red}${this.formatter(proto, args)}${ansi.reset}` ) } - #__formatter(proto: any, args: any) { + private formatter(proto: any, args: any) { return `[${proto}]\t${args}\n` } } diff --git a/server/src/utils/procUtils.ts b/server/src/utils/procUtils.ts index 4a77582..a085ad0 100644 --- a/server/src/utils/procUtils.ts +++ b/server/src/utils/procUtils.ts @@ -1,6 +1,6 @@ -import { spawn } from 'child_process'; +import { exec, spawn } from 'child_process'; import fs = require('fs'); -import net = require('net'); +// import net = require('net'); import { logger } from './logger'; /** @@ -39,3 +39,11 @@ export async function killProcess(pid: number) { logger('proc', `Successfully killed yt-dlp process, pid: ${pid}`) }) } + +export function getFreeDiskSpace(socket: any) { + let buffer: string = ''; + let message: string = 'free-space'; + exec("df -h / | tail -1 | awk '{print $4}'", (_, stdout) => { + socket.emit(message, stdout) + }) +} \ No newline at end of file