diff --git a/README.md b/README.md new file mode 100644 index 0000000..8f285fc --- /dev/null +++ b/README.md @@ -0,0 +1,6 @@ +# youtube-downloader + +Simple to use youtube downloader, simply run the index javascript file with node and then go to localhost on your browser, by default the video will download to this folder but can be changed in src/index.js + +# Contrubutors +- Ben (plane000)#8618 diff --git a/legacy/README.md b/legacy/README.md deleted file mode 100644 index 2593dbe..0000000 --- a/legacy/README.md +++ /dev/null @@ -1,6 +0,0 @@ -# youtube-downloader - -Simple to use youtube downloader, simply fill up the text files with videos you wish to download, sepperated by lines. run `npm i` and `node index.js` to download all of the videos in the file! - -# Contrubutors -- Ben (plane000)#8618 diff --git a/package-lock.json b/package-lock.json index 6a377c9..48a2583 100644 --- a/package-lock.json +++ b/package-lock.json @@ -389,6 +389,11 @@ "resolved": "https://registry.npmjs.org/miniget/-/miniget-1.5.1.tgz", "integrity": "sha512-KJ3AyIVZ76QuWAq43BWjkK+jLdhxhy3s4tsdg9Je91+cIFkeOSW2VEj2lSeKw50CPu1eCCkSbiQEBKL36mpA5w==" }, + "moment": { + "version": "2.23.0", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.23.0.tgz", + "integrity": "sha512-3IE39bHVqFbWWaPOMHZF98Q9c3LDKGTmypMiTM2QygGXXElkFWIH7GxfmlwmY2vwa+wmNsoYZmG2iusf1ZjJoA==" + }, "ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", diff --git a/package.json b/package.json index f594f00..f449945 100644 --- a/package.json +++ b/package.json @@ -12,6 +12,7 @@ "devDependencies": {}, "dependencies": { "express": "^4.16.4", + "moment": "^2.23.0", "socket.io": "^2.2.0", "ytdl-core": "^0.28.3" } diff --git a/public/favicon.ico b/public/favicon.ico new file mode 100644 index 0000000..e69de29 diff --git a/public/index.html b/public/index.html index 0a481b9..a9b9f7d 100644 --- a/public/index.html +++ b/public/index.html @@ -6,10 +6,11 @@ Page Title +
-

Currently saving videos to: ~/Desktop

+

Currently saving videos to: ./

Videos to record (seperate different videos by new lines):
@@ -18,7 +19,10 @@ - + + +
+ diff --git a/public/index.js b/public/index.js index 600e6a1..b311a23 100644 --- a/public/index.js +++ b/public/index.js @@ -1,10 +1,65 @@ +let socket = io(); + (() => { console.log('Starting up'); })(); -let VideosToDownload = []; +socket.on('path', async (data) => { + document.getElementById('saveloc').innerText = data; +}); + +let isDownloading = false; +let VideosToDownload = {}; document.getElementById('VideosToRecord').addEventListener('keyup', (e) => { + if (isDownloading) return; let current = document.getElementById('VideosToRecord').value; VideosToDownload = current.split('\n'); - console.log(VideosToDownload); + + let payload = { + ExpectPreview: true, + VideosToDownload: VideosToDownload + }; + + socket.emit('video-list', payload); }); + +let VideoPreview = []; + +function renderPreview() { + if (isDownloading) return; + document.getElementById('VideoPreview').innerText = ''; + for (const [key, value] of Object.entries(VideoPreview)) { + if (document.getElementById(key) == null) { + if (!value.found) { + document.getElementById('VideoPreview').innerHTML += `
${key}: Video not found
`; + } else { + document.getElementById('VideoPreview').innerHTML += `
${key}: ${value.title}
`; + } + } + } +} + +function clearPreview() { + document.getElementById('VideoPreview').innerText = ''; +} + +socket.on('video-preview', async (data) => { + if (isDownloading) return; + if (!data || !data.data || data.contents == false) { + clearPreview(); + return; + } + VideoPreview = data.data; + renderPreview(); +}); + +document.getElementById('Download').addEventListener('click', async (event) => { + if (isDownloading) return; + socket.emit('download', document.getElementById('VideosToRecord').value.split('\n')); + document.getElementById('VideoPreview').innerText = '\nDownloading...'; + document.getElementById('VideosToRecord').value = null; + isDownloading = true; + console.log('Asked server for download...'); +}); + + diff --git a/public/style.css b/public/style.css index 771235f..ad6d181 100644 --- a/public/style.css +++ b/public/style.css @@ -29,3 +29,11 @@ textarea { width: 400px; height: 100px; } + +#VideoPreview { + font-weight: lighter; +} + +h { + font-weight: 400; +} diff --git a/src/index.js b/src/index.js index ac17ff7..60ed9f1 100644 --- a/src/index.js +++ b/src/index.js @@ -1,5 +1,12 @@ const server = require('./server'); +let config = { + serverPort: 80, + downloadLocation: './' +}; + +module.exports.config = config; + module.exports.main = async () => { await server.init(); await server.listen(); diff --git a/src/logger.js b/src/logger.js new file mode 100644 index 0000000..98ce516 --- /dev/null +++ b/src/logger.js @@ -0,0 +1,7 @@ +const moment = require('moment'); +const dateFormat = 'DD-MM-YY HH:mm:ss' + +module.exports.log = function(log) { + let d = moment().format(dateFormat); + console.log('[' + d.toLocaleString() + '] ' + log); +} diff --git a/src/server.js b/src/server.js index a530a20..a9f476f 100644 --- a/src/server.js +++ b/src/server.js @@ -1,3 +1,7 @@ +const logger = require('./logger') +const main = require('./index'); +const youtube = require('./youtubehelper'); + const express = require('express'); let app; @@ -9,14 +13,34 @@ module.exports.init = async () => { http = require('http').Server(app); io = require('socket.io')(http); - http.listen(8080, () => { - console.log('HTTP server listening on port 8080'); - console.log('WebSocket server listening'); + http.listen(main.config.serverPort, () => { + logger.log(`HTTP server listening on port ${main.config.serverPort}`); + logger.log(`WebSocket server listening on ${main.config.serverPort}`); }); } module.exports.listen = async () => { app.use(express.static('public')); + + io.on('connection', async (socket) => { + logger.log(`New socket connection from id: ${socket.id}`); + + socket.emit('path', main.config.downloadLocation); + + socket.on('video-list', async (data) => { + if (data.ExpectPreview) { + logger.log(`Socket id '${socket.id}' is requesting a video preview`); + let response = await youtube.resolveVideos(data.VideosToDownload); + socket.emit('video-preview', response); + logger.log(`Finished preview for socket id '${socket.id}'`); + } + }); + + socket.on('download', async (data) => { + logger.log(`Socket id ${socket.id}' is requesting a download`); + youtube.downloadVideos(data, socket, {path: main.config.downloadLocation}); + }); + }); } module.exports.app = app; diff --git a/src/youtubehelper.js b/src/youtubehelper.js new file mode 100644 index 0000000..a8559aa --- /dev/null +++ b/src/youtubehelper.js @@ -0,0 +1,34 @@ +const ytdl = require('ytdl-core'); + +module.exports.resolveVideos = async (arr) => { + let output = {contents: false, data: {}}; + + for (let video of arr) { + if (video == '' || video == ' ') continue; + if (await ytdl.validateURL(video)) { + const info = await ytdl.getBasicInfo(video); + if (!info) { + output.data[video] = {found: false}; + return; + } + output.data[video] = { + found: true, + title: info.title, + thumbnail: info.thumbnail_url.replace('default', 'maxresdefault'), + runtime: info.length_seconds + } + output.contents = true; + } else { + output.data[video] = {found: false}; + output.contents = true; + } + } + + return output; +} + +module.exports.downloadVideos = async (arr, socket, options) => { + let path = options.path ? options.path : './' + + +}