From f75d084ab56204a04c00b5182c1cc42d67f2cfbd Mon Sep 17 00:00:00 2001 From: marcobaobao Date: Mon, 29 Nov 2021 22:13:15 +0100 Subject: [PATCH] core rework --- frontend/src/{App.jsx => App.tsx} | 24 ++++++------- frontend/src/interfaces.tsx | 11 ++++++ frontend/src/{utils.js => utils.ts} | 4 +-- lib/downloader.js | 53 ++++++++++++++++++++++------- server.js | 1 - 5 files changed, 65 insertions(+), 28 deletions(-) rename frontend/src/{App.jsx => App.tsx} (90%) create mode 100644 frontend/src/interfaces.tsx rename frontend/src/{utils.js => utils.ts} (70%) diff --git a/frontend/src/App.jsx b/frontend/src/App.tsx similarity index 90% rename from frontend/src/App.jsx rename to frontend/src/App.tsx index 11d5a52..203a46a 100644 --- a/frontend/src/App.jsx +++ b/frontend/src/App.tsx @@ -13,6 +13,7 @@ import { } from "react-bootstrap"; import { validateDomain, validateIP } from "./utils"; import './App.css'; +import { IMessage } from "./interfaces"; const socket = io(`http://${localStorage.getItem('server-addr') || 'localhost'}:3022`) @@ -34,20 +35,17 @@ export function App() { }, []) useEffect(() => { - socket.on('progress', data => { - setMessage(data.trim()) - if (data.trim() === 'Done!') { + socket.on('progress', (data: IMessage) => { + setMessage(`${data.status || 'starting'} | progress: ${data.progress || '?'} | size: ${data.size || '?'} | speed: ${data.dlSpeed || '?'}`) + if (data.status === 'Done!') { setHalt(false) + setMessage('Done!') setProgress(0) + return } - try { - const _progress = Math.ceil(data.split(" ")[2].replace('%', '')) - if (!isNaN(_progress)) { - setProgress(_progress) - } - } catch (error) { - console.warn('finished or empty url or aborted') - } + setProgress( + Math.ceil(Number(data.progress.replace('%', ''))) + ) }) }, []) @@ -63,11 +61,11 @@ export function App() { socket.emit('send-url', url) } - const handleUrlChange = (e) => { + const handleUrlChange = (e: React.ChangeEvent) => { setUrl(e.target.value) } - const handleAddrChange = (e) => { + const handleAddrChange = (e: React.ChangeEvent) => { const input = e.target.value; if (validateIP(input)) { setInvalidIP(false) diff --git a/frontend/src/interfaces.tsx b/frontend/src/interfaces.tsx new file mode 100644 index 0000000..acad891 --- /dev/null +++ b/frontend/src/interfaces.tsx @@ -0,0 +1,11 @@ +export interface IMessage { + status: string, + progress?: string, + size?: string, + dlSpeed?: string +} + +export interface IDLSpeed { + effective: number, + unit: string, +} \ No newline at end of file diff --git a/frontend/src/utils.js b/frontend/src/utils.ts similarity index 70% rename from frontend/src/utils.js rename to frontend/src/utils.ts index 77ac5ce..7b99e3c 100644 --- a/frontend/src/utils.js +++ b/frontend/src/utils.ts @@ -1,9 +1,9 @@ -export function validateIP(ipAddr) { +export function validateIP(ipAddr: string): boolean { let ipRegex = /^(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)){3}$/gm return ipRegex.test(ipAddr) } -export function validateDomain(domainName) { +export function validateDomain(domainName: string): boolean { let domainRegex = /[^@ \t\r\n]+.[^@ \t\r\n]+\.[^@ \t\r\n]+/ return domainRegex.test(domainName) || domainName === 'localhost' } \ No newline at end of file diff --git a/lib/downloader.js b/lib/downloader.js index 9b00233..287c91a 100644 --- a/lib/downloader.js +++ b/lib/downloader.js @@ -17,19 +17,24 @@ const download = (socket, url) => { const ytldp = spawn(`./lib/yt-dlp${isWindows ? '.exe' : ''}`, ['-o', `${settings.download_path || 'downloads/'}%(title)s.%(ext)s`, url] ) - ytldp.stdout.on('data', data => { - // reactive programming magic - from(Promise.resolve(data)) // stout as promise => Observable - .pipe(throttle(() => interval(500))) // discard events closer than 500ms - .subscribe({ - next: () => { - socket.emit('progress', data.toString()) // finally, emit - logger('download', `Fetching ${data.toString()}`) - } - }) - }) + + from(ytldp.stdout) // stout as observable + .pipe(throttle(() => interval(500))) // discard events closer than 500ms + .subscribe({ + next: (stdout) => { + let _stdout = String(stdout) + socket.emit('progress', formatter(_stdout)) // finally, emit + //logger('download', `Fetching ${stdout}`) + console.log(formatter(_stdout)) + }, + complete: () => { + socket.emit('progress', { status: 'Done!' }) + logger('download', 'Done!') + } + }) + ytldp.on('exit', () => { - socket.emit('progress', 'Done!') + socket.emit('progress', { status: 'Done!' }) logger('download', 'Done!') }) } @@ -45,6 +50,30 @@ const abortDownload = (socket) => { logger('download', 'Aborted') } +const formatter = (stdout) => { + const cleanStdout = stdout + .replace(/\s\s+/g, ' ') + .split(' ') + const status = cleanStdout[0].replace(/\[|\]|\r/g, '') + switch (status) { + case 'download': + return { + status: cleanStdout[0].replace(/\[|\]|\r/g, ''), + progress: cleanStdout[1], + size: cleanStdout[3], + dlSpeed: cleanStdout[5], + } + case 'merger': + return { + status: 'merging', + progress: '100', + } + default: + return { progress: '0' } + } + +} + module.exports = { download: download, abortDownload: abortDownload diff --git a/server.js b/server.js index 2134ac2..4bfa675 100644 --- a/server.js +++ b/server.js @@ -27,7 +27,6 @@ io.on('connection', socket => { socket.on('abort', () => { abortDownload(socket) }) - socket.on('update-bin', () => { ytdlpUpdater(socket) })