commit 52759b7ce967824a678a7978f4fddeb871b27b50 Author: genio Date: Thu Nov 18 15:09:56 2021 +0100 first commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..3ffcba0 --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +.parcel-cache +dist +package-lock.json +node_modules \ No newline at end of file diff --git a/downloader.js b/downloader.js new file mode 100644 index 0000000..372d448 --- /dev/null +++ b/downloader.js @@ -0,0 +1,39 @@ +const { spawn } = require('child_process'); +const logger = require('./lib/logger'); +const settings = require('./settings.json'); + +const download = (socket, url) => { + const ytldp = spawn('./lib/yt-dlp.exe', + ['-o', `${settings.download_path}%(title)s.%(ext)s`, url] + ) + + ytldp.stdout.on('data', data => { + socket.emit('progress', data.toString()) + console.log(data.toString()) + }) + ytldp.on('exit', () => { + socket.emit('progress', 'Done!') + }) +} + +const abortDownload = (socket) => { + const res = process.platform === 'win32' ? + spawn('taskkill', ['/IM', 'yt-dlp.exe', '/F', '/T']) : + spawn('killall', ['yt-dlp']) + res.stdout.on('data', data => { + socket.emit('progress', 'Aborted!') + console.log(data.toString()) + }) + 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 +} \ No newline at end of file diff --git a/frontend/index.css b/frontend/index.css new file mode 100644 index 0000000..c19d095 --- /dev/null +++ b/frontend/index.css @@ -0,0 +1,5 @@ +body{ + height: 100vh; + background-color: #202124; + color: #f1f1f1; +} \ No newline at end of file diff --git a/frontend/index.html b/frontend/index.html new file mode 100644 index 0000000..4913569 --- /dev/null +++ b/frontend/index.html @@ -0,0 +1,19 @@ + + + + + + + + + + Frontend + + + +
+ + + + \ No newline at end of file diff --git a/frontend/index.js b/frontend/index.js new file mode 100644 index 0000000..e54c1ad --- /dev/null +++ b/frontend/index.js @@ -0,0 +1,5 @@ +import ReactDOM from 'react-dom' +import { App } from './src/App' + +const root = document.getElementById('root') +ReactDOM.render(, root) diff --git a/frontend/src/App.css b/frontend/src/App.css new file mode 100644 index 0000000..e69de29 diff --git a/frontend/src/App.jsx b/frontend/src/App.jsx new file mode 100644 index 0000000..8d2e9b8 --- /dev/null +++ b/frontend/src/App.jsx @@ -0,0 +1,69 @@ +import { io } from "socket.io-client"; +import React, { useState, useEffect } from "react"; +import { Container, ProgressBar, InputGroup, FormControl, Button } from "react-bootstrap"; +import './App.css' + +const socket = io('http://localhost:3000') + +export function App() { + useEffect(() => { + socket.on('progress', data => { + setMessage(data.trim()) + if (data.trim() === 'Done!') { + setHalt(false) + setProgress(0) + } + try { + setProgress(Math.ceil(data.split(" ")[2].replace('%', ''))) + } catch (error) { + console.log('finished or empty url') + } + }) + }, []) + + const sendUrl = () => { + setHalt(true) + console.log(url) + socket.emit('send-url', url) + } + + const handleUrlChange = (e) => { + setUrl(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

+ + + + + +
+
Status
+
{message}
+
+ + + + {' '} + + +
+
+ Once you close the page the download will continue in the background. It won't be possible retriving the progress though. +
+ + ) +} \ No newline at end of file diff --git a/lib/event.js b/lib/event.js new file mode 100644 index 0000000..02fdb72 --- /dev/null +++ b/lib/event.js @@ -0,0 +1,19 @@ +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/logger.js b/lib/logger.js new file mode 100644 index 0000000..6d37787 --- /dev/null +++ b/lib/logger.js @@ -0,0 +1,5 @@ +const logger = (proto, args) => { + console.log(`[${proto}] ${args}`) +} + +module.exports = logger \ No newline at end of file diff --git a/lib/yt-dlp.exe b/lib/yt-dlp.exe new file mode 100644 index 0000000..c1fb0a0 Binary files /dev/null and b/lib/yt-dlp.exe differ diff --git a/lib/yt-dlpCaller.js b/lib/yt-dlpCaller.js new file mode 100644 index 0000000..3c45198 --- /dev/null +++ b/lib/yt-dlpCaller.js @@ -0,0 +1,24 @@ +const Readable = require('stream').Readable; + +class Subscription extends Readable{ + constructor(options) { + super(); + if (!(this instanceof Subscription)) + return new Subscription(options); + + options = options || {}; + Readable.call(this, options); + + this.value = 0; + } + _read() { + while(this.value <= 100){ + this.push(String(this.value++)); + } + } +} + + +exports.subscribe = function(event, options){ + return new Subscription(options); +} \ No newline at end of file diff --git a/package.json b/package.json new file mode 100644 index 0000000..74e6eb8 --- /dev/null +++ b/package.json @@ -0,0 +1,26 @@ +{ + "name": "youtube-dlp-web", + "version": "1.0.0", + "description": "", + "scripts": { + "start": "node --harmony app.js", + "dev": "nodemon app.js", + "build": "parcel build ./frontend/index.html", + "fe": "parcel ./frontend/index.html --open" + }, + "author": "", + "license": "ISC", + "dependencies": { + "@koa/cors": "^3.1.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", + "react-dom": "^17.0.2", + "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 new file mode 100644 index 0000000..115b0a6 --- /dev/null +++ b/server.js @@ -0,0 +1,42 @@ +const Koa = require('koa'); +const serve = require('koa-static'); +const { Server } = require('socket.io'); +const path = require('path'); +const { createServer } = require('http'); +const cors = require('@koa/cors'); +const logger = require('./lib/logger'); +const { download, abortDownload } = require('./downloader'); + +const app = new Koa() +const server = createServer(app.callback()) +const io = new Server(server, { + cors: { + origin: "*", + methods: ["GET", "POST"] + } +}) + +io.on('connection', socket => { + logger('ws', 'connesso') + + socket.on('send-url', args => { + logger('ws', args) + download(socket, args) + }) + + socket.on('abort', () => { + abortDownload(socket) + }) +}); + +io.on('disconnect', () => { + logger('ws', 'disconnesso') +}); + +app + .use(cors()) + .use(serve(path.join(__dirname, 'dist'))) + +console.log('[koa] Server started port', 3000) + +server.listen(3000) \ No newline at end of file diff --git a/settings.json b/settings.json new file mode 100644 index 0000000..d79c421 --- /dev/null +++ b/settings.json @@ -0,0 +1,3 @@ +{ + "download_path": "C:\\Users\\marco\\Downloads\\" +} \ No newline at end of file