diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..da14b2b --- /dev/null +++ b/.dockerignore @@ -0,0 +1,4 @@ +node_modules +dist +package-lock.json +.parcel-cache \ No newline at end of file diff --git a/.gitignore b/.gitignore index 3ffcba0..cc1abb6 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,6 @@ .parcel-cache dist package-lock.json -node_modules \ No newline at end of file +node_modules +lib/*.exe +.env \ No newline at end of file diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..403ef25 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,9 @@ +FROM node:14 +VOLUME /downloads +WORKDIR /usr/src/yt-dlp-webui +COPY package*.json ./ +RUN npm install +RUN npm run build +COPY . . +EXPOSE 3022 +CMD [ "node" , "./server.js" ] \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..474a2fa --- /dev/null +++ b/README.md @@ -0,0 +1,35 @@ +## yt-dlp Web UI + +A terrible web ui for yt-dlp. +Created for the only purpose of *cough cough* k-pop videos from my server/nas. + +yt + +### Docker install +``` +// download the yt-dl build and put it in the lib folder + +mkdir downloads + +docker build -t yt-dlp-webui . +docker run -d -p 3022:3022 yt-dlp-webui +``` + +### Manual install +``` +// download the yt-dl build and put it in the lib folder + +npm i +npm run build + +// edit the settings.json specifying the download path or +// it will use the following folder + +mkdir downloads + +node server.js +``` + +### Todo list +- retrieve background task +- better ui/ux \ No newline at end of file diff --git a/frontend/index.css b/frontend/index.css index c19d095..b15b3d7 100644 --- a/frontend/index.css +++ b/frontend/index.css @@ -1,5 +1,5 @@ body{ - height: 100vh; + height: 80vh; background-color: #202124; color: #f1f1f1; } \ No newline at end of file diff --git a/frontend/index.html b/frontend/index.html index 4913569..9bf13cb 100644 --- a/frontend/index.html +++ b/frontend/index.html @@ -8,7 +8,7 @@ - Frontend + yt-dlp Web UI diff --git a/frontend/src/App.css b/frontend/src/App.css index e69de29..4786733 100644 --- a/frontend/src/App.css +++ b/frontend/src/App.css @@ -0,0 +1,5 @@ +.status-box{ + background-color: #2b2c31; + padding: 8px; + border-radius: 5px; +} \ No newline at end of file diff --git a/frontend/src/App.jsx b/frontend/src/App.jsx index 8d2e9b8..b779588 100644 --- a/frontend/src/App.jsx +++ b/frontend/src/App.jsx @@ -1,11 +1,34 @@ import { io } from "socket.io-client"; import React, { useState, useEffect } from "react"; -import { Container, ProgressBar, InputGroup, FormControl, Button } from "react-bootstrap"; +import { + Container, + Row, + Col, + ProgressBar, + InputGroup, + FormControl, + Button, + Toast +} from "react-bootstrap"; import './App.css' -const socket = io('http://localhost:3000') +const socket = io(`http://${localStorage.getItem('server-addr') || 'localhost'}:3022`) export function App() { + + const [progress, setProgress] = useState(0) + const [message, setMessage] = useState('') + const [halt, setHalt] = useState(false) + const [url, setUrl] = useState('') + const [showToast, setShowToast] = useState(false) + const [showSettings, setShowSettings] = useState(false) + + useEffect(() => { + socket.on('connect', () => { + setShowToast(true) + }) + }, []) + useEffect(() => { socket.on('progress', data => { setMessage(data.trim()) @@ -14,9 +37,12 @@ export function App() { setProgress(0) } try { - setProgress(Math.ceil(data.split(" ")[2].replace('%', ''))) + const _progress = Math.ceil(data.split(" ")[2].replace('%', '')) + if (!isNaN(_progress)) { + setProgress(_progress) + } } catch (error) { - console.log('finished or empty url') + console.log('finished or empty url or aborted') } }) }, []) @@ -31,39 +57,81 @@ export function App() { setUrl(e.target.value) } + const handleAddrChange = (e) => { + localStorage.setItem('server-addr', e.target.value) + } + const abort = () => { socket.emit('abort') setHalt(false) } - const [progress, setProgress] = useState(0) - const [message, setMessage] = useState('') - const [halt, setHalt] = useState(false) - const [url, setUrl] = useState('') - return ( -
-

yt-dlp web ui

+ + +
+

yt-dlp Web UI 🤠

- - - + + + -
-
Status
-
{message}
-
+
+
Status
+
{message}
+
- + {progress ? : null} - {' '} - + {' '} + {' '} + -
-
- Once you close the page the download will continue in the background. It won't be possible retriving the progress though. -
+ {showSettings ? + <> +
Server address
+ + ws:// + + :3022 + + : + null + } + +
+
Once you close the page the download will continue in the background.
+
It won't be possible retriving the progress though.
+
+ Made with ❤️ by Marcobaobao + + + setShowToast(false)} + bg={'success'} + delay={1000} + autohide + className="mt-5" + > + + Server + Now + + {`Connected to ${localStorage.getItem('server-addr')}`} + + + ) } \ No newline at end of file diff --git a/lib/downloader.js b/lib/downloader.js index bfa4ad5..fad53b8 100644 --- a/lib/downloader.js +++ b/lib/downloader.js @@ -1,10 +1,17 @@ const { spawn } = require('child_process'); const logger = require('./logger'); -const settings = require('../settings.json'); +let settings; + +try { + settings = require('../settings.json'); +} +catch (e) { + console.warn("settings.json not found") +} const download = (socket, url) => { const ytldp = spawn('./lib/yt-dlp.exe', - ['-o', `${settings.download_path}%(title)s.%(ext)s`, url] + ['-o', `${settings.download_path || './downloads/'}%(title)s.%(ext)s`, url] ) ytldp.stdout.on('data', data => { @@ -27,12 +34,6 @@ const abortDownload = (socket) => { logger('download', 'Aborted') } -const kill = async () => { - return process.platform === 'win32' ? - spawn('taskkill', ['/IM', 'yt-dlp.exe', '/F', '/T']) : - spawn('killall', ['yt-dlp']) -} - module.exports = { download: download, abortDownload: abortDownload diff --git a/lib/event.js b/lib/event.js deleted file mode 100644 index 02fdb72..0000000 --- a/lib/event.js +++ /dev/null @@ -1,19 +0,0 @@ -var Transform = require('stream').Transform; - -class SSE extends Transform{ - constructor(options) { - super(); - - if (!(this instanceof SSE)) - return new SSE(options); - - options = options || {}; - Transform.call(this, options); - } - _transform(data, enc, cb) { - this.push('data: ' + data.toString('utf8') + '\n\n'); - cb(); - } -} - -module.exports = SSE; diff --git a/lib/fetch-yt-dlp.js b/lib/fetch-yt-dlp.js new file mode 100644 index 0000000..e893f4b --- /dev/null +++ b/lib/fetch-yt-dlp.js @@ -0,0 +1,16 @@ +const https = require('https'); +const path = require('path'); +const fs = require('fs'); + +const isWindows = process.platform === 'win32'; + +const file = fs.createWriteStream(path.join( + __dirname, `yt-dlp${isWindows ? '.exe' : ''}` +)); + +https.get( + isWindows ? + 'https://github.com/yt-dlp/yt-dlp/releases/download/2021.11.10.1/yt-dlp.exe' : + 'https://github.com/yt-dlp/yt-dlp/releases/download/2021.11.10.1/yt-dlp', + res => res.pipe(file) +); \ No newline at end of file diff --git a/package.json b/package.json index 74e6eb8..993298a 100644 --- a/package.json +++ b/package.json @@ -12,10 +12,9 @@ "license": "ISC", "dependencies": { "@koa/cors": "^3.1.0", + "dotenv": "^10.0.0", "koa": "^2.13.4", - "koa-router": "^10.1.1", "koa-static": "^5.0.0", - "koa-views": "^7.0.2", "parcel": "^2.0.1", "react": "^17.0.2", "react-bootstrap": "^2.0.2", @@ -23,4 +22,4 @@ "socket.io": "^4.3.2", "socket.io-client": "^4.3.2" } -} \ No newline at end of file +} diff --git a/server.js b/server.js index 1b108ff..68deb8a 100644 --- a/server.js +++ b/server.js @@ -1,7 +1,7 @@ const Koa = require('koa'); const serve = require('koa-static'); -const { Server } = require('socket.io'); const path = require('path'); +const { Server } = require('socket.io'); const { createServer } = require('http'); const cors = require('@koa/cors'); const logger = require('./lib/logger'); @@ -37,6 +37,6 @@ app .use(cors()) .use(serve(path.join(__dirname, 'dist'))) -console.log('[koa] Server started port', 3000) +console.log('[koa] Server started port', process.env.PORT || 3022) -server.listen(3000) \ No newline at end of file +server.listen(process.env.PORT || 3022) \ No newline at end of file diff --git a/settings.json b/settings.json index d79c421..4512535 100644 --- a/settings.json +++ b/settings.json @@ -1,3 +1,3 @@ { - "download_path": "C:\\Users\\marco\\Downloads\\" + "download_path": "" } \ No newline at end of file