Compare commits
2 commits
Author | SHA1 | Date | |
---|---|---|---|
468112c1f6 | |||
dc0db93490 |
31 changed files with 487 additions and 455 deletions
|
@ -1,9 +1,9 @@
|
||||||
HOST=0.0.0.0
|
HOST=localhost
|
||||||
PORT=3333
|
PORT=3333
|
||||||
NODE_ENV=development
|
NODE_ENV=development
|
||||||
APP_URL=http://${HOST}:${PORT}
|
APP_URL=http://${HOST}:${PORT}
|
||||||
CACHE_VIEWS=false
|
CACHE_VIEWS=false
|
||||||
APP_KEY=
|
APP_KEY=Please do 'adonis key:generate'
|
||||||
DB_CONNECTION=mysql
|
DB_CONNECTION=mysql
|
||||||
DB_HOST=127.0.0.1
|
DB_HOST=127.0.0.1
|
||||||
DB_PORT=3306
|
DB_PORT=3306
|
||||||
|
|
3
.gitignore
vendored
3
.gitignore
vendored
|
@ -8,9 +8,6 @@ tmp
|
||||||
# Environment variables, never commit this file
|
# Environment variables, never commit this file
|
||||||
.env
|
.env
|
||||||
|
|
||||||
# List of proxy
|
|
||||||
proxy/proxy.json
|
|
||||||
|
|
||||||
# The development sqlite file
|
# The development sqlite file
|
||||||
database/development.sqlite
|
database/development.sqlite
|
||||||
|
|
||||||
|
|
20
Dockerfile
20
Dockerfile
|
@ -1,20 +0,0 @@
|
||||||
# My first docker hope it isn't too bad :)
|
|
||||||
FROM node:12
|
|
||||||
|
|
||||||
WORKDIR /var/www/jeffdownloader/
|
|
||||||
|
|
||||||
RUN git clone https://git.namejeff.xyz/Supositware/jeff-downloader.git .
|
|
||||||
|
|
||||||
RUN npm install
|
|
||||||
|
|
||||||
RUN npm i -g pm2
|
|
||||||
|
|
||||||
RUN cp .env.example .env
|
|
||||||
|
|
||||||
RUN echo "[]" > proxy/proxy.json
|
|
||||||
|
|
||||||
RUN apt-get update && apt-get install -y ffmpeg
|
|
||||||
|
|
||||||
EXPOSE 3333
|
|
||||||
|
|
||||||
CMD ["pm2-runtime", "server.js"]
|
|
|
@ -5,9 +5,6 @@ Jeff downloader is a website to download from [hundreds](https://ytdl-org.github
|
||||||
You can find a hosted version on https://namejeff.xyz/
|
You can find a hosted version on https://namejeff.xyz/
|
||||||
|
|
||||||
# Credit
|
# Credit
|
||||||
|
|
||||||
SponsorBlock data is used under [CC BY-NC-SA 4.0](https://creativecommons.org/licenses/by-nc-sa/4.0/). More details: https://sponsor.ajay.app/
|
|
||||||
|
|
||||||
[Youtube-dl](https://github.com/ytdl-org/youtube-dl/)
|
[Youtube-dl](https://github.com/ytdl-org/youtube-dl/)
|
||||||
|
|
||||||
Major Tom#6196 for AR translation
|
Major Tom#6196 for AR translation
|
||||||
|
|
|
@ -1,21 +1,17 @@
|
||||||
'use strict'
|
'use strict'
|
||||||
const youtubedl = require('youtube-dl');
|
const youtubedl = require('youtube-dl')
|
||||||
const fs = require('fs');
|
const fs = require('fs')
|
||||||
const path = require('path');
|
const ffmpeg = require('fluent-ffmpeg')
|
||||||
const ffmpeg = require('fluent-ffmpeg');
|
|
||||||
const { version } = require('../../../package.json');
|
const { version } = require('../../../package.json');
|
||||||
|
const Ws = use('Ws');
|
||||||
const Antl = use('Antl');
|
const Antl = use('Antl');
|
||||||
const proxy = require('../../../proxy/proxy.json');
|
|
||||||
const fetch = require('node-fetch');
|
|
||||||
|
|
||||||
let viewCounter = 0;
|
let viewCounter = 0;
|
||||||
let files = [];
|
let files = [];
|
||||||
let day;
|
let day;
|
||||||
let month;
|
let month;
|
||||||
let announcementArray = [];
|
let announcementArray;
|
||||||
let announcement;
|
let announcement;
|
||||||
let defaultViewOption = { version: version, viewCounter: viewCounter, file: files, day: day, month: month, announcement: announcement, proxy: proxy }
|
|
||||||
|
|
||||||
|
|
||||||
function formatBytes(bytes, decimals = 2) { // https://stackoverflow.com/a/18650828
|
function formatBytes(bytes, decimals = 2) { // https://stackoverflow.com/a/18650828
|
||||||
if (bytes === 0) return '0 Bytes';
|
if (bytes === 0) return '0 Bytes';
|
||||||
|
@ -33,31 +29,25 @@ class DownloadController {
|
||||||
|
|
||||||
async index ({ view, request, locale }) {
|
async index ({ view, request, locale }) {
|
||||||
viewCounter++;
|
viewCounter++;
|
||||||
defaultViewOption.viewCounter = viewCounter;
|
// Coudln't find a cleaner way to make it change with the browser locale
|
||||||
|
announcementArray = [Antl.forLocale(locale).formatMessage('announcement.1'), Antl.forLocale(locale).formatMessage('announcement.2'), Antl.forLocale(locale).formatMessage('announcement.3'), Antl.forLocale(locale).formatMessage('announcement.4'), Antl.forLocale(locale).formatMessage('announcement.5'), Antl.forLocale(locale).formatMessage('announcement.6'), 'Playlist download is experimental'];
|
||||||
for (let i = 0; Antl.forLocale(locale)._messages.fr.announcement.length > i; i++) {
|
|
||||||
announcementArray.push(Antl.forLocale(locale).formatMessage(`announcement.${i + 1}`));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get random announcement
|
// Get random announcement
|
||||||
defaultViewOption.announcement = announcementArray[Math.floor(Math.random() * announcementArray.length)];
|
announcement = announcementArray[Math.floor(Math.random() * announcementArray.length)];
|
||||||
|
|
||||||
// Get date for some event
|
// Get date for some event
|
||||||
let today = new Date();
|
let today = new Date();
|
||||||
defaultViewOption.day = today.getDay();
|
day = today.getDay();
|
||||||
defaultViewOption.month = today.getMonth();
|
month = today.getMonth();
|
||||||
// If legacy link return
|
// If legacy link return
|
||||||
if (request.url() == '/legacy') return view.render('legacy', defaultViewOption);
|
if (request.url() == '/legacy') return view.render('legacy', { version: version, viewCounter: viewCounter, day: day, month: month, announcement: announcement});
|
||||||
|
|
||||||
files = [];
|
files = [];
|
||||||
let file = [];
|
let file = [];
|
||||||
for (let f of fs.readdirSync('./public/uploads')) {
|
for (let f of fs.readdirSync('./public/uploads')) {
|
||||||
if (f.endsWith('.mp4') || f.endsWith('.webm') || f.endsWith('.mp3') || f.endsWith('.flac'))
|
file.push(f)
|
||||||
file.push(f)
|
|
||||||
}
|
}
|
||||||
// get the 5 most recent files
|
// get the 5 most recent files
|
||||||
file = file.sort((a, b) => {
|
file = file.sort((a, b) => {
|
||||||
if ((a || b).endsWith('.mp4') || (a || b).endsWith('.webm') || (a || b).endsWith('.mp3') || (a || b).endsWith('.flac')) {
|
if ((a || b).endsWith('.mp4') || (a || b).endsWith('.webm') || (a || b).endsWith('.mp3') || (a || b).endsWith('.flac') || (a || b).endsWith('.zip')) {
|
||||||
let time1 = fs.statSync(`./public/uploads/${b}`).ctime;
|
let time1 = fs.statSync(`./public/uploads/${b}`).ctime;
|
||||||
let time2 = fs.statSync(`./public/uploads/${a}`).ctime;
|
let time2 = fs.statSync(`./public/uploads/${a}`).ctime;
|
||||||
if (time1 < time2) return -1;
|
if (time1 < time2) return -1;
|
||||||
|
@ -68,34 +58,28 @@ class DownloadController {
|
||||||
|
|
||||||
// Save space by deleting file that doesn't appear in the recent feed
|
// Save space by deleting file that doesn't appear in the recent feed
|
||||||
for (let f of fs.readdirSync('./public/uploads')) {
|
for (let f of fs.readdirSync('./public/uploads')) {
|
||||||
if (!file.includes(f) && (f != 'hidden' && f != '.keep')) {
|
if (!file.includes(f) && (f != 'hidden' && f != '.keep' && f != 'playlist')) {
|
||||||
if (fs.existsSync(`./public/uploads/${f}`))
|
fs.unlinkSync(`./public/uploads/${f}`);
|
||||||
fs.unlinkSync(`./public/uploads/${f}`);
|
|
||||||
|
|
||||||
if (fs.existsSync(`./public/thumbnail/${f}`))
|
|
||||||
fs.unlinkSync(`./public/thumbnail/${f}`);
|
|
||||||
|
|
||||||
if (fs.existsSync(`./public/thumbnail/${f}.png`))
|
|
||||||
fs.unlinkSync(`./public/thumbnail/${f}.png`);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (let f of file) {
|
for (let f of file) {
|
||||||
let fileInfo = formatBytes(fs.statSync(`./public/uploads/${f}`).size).split(' ');
|
if (f.endsWith('.mp4') || f.endsWith('.webm')) {
|
||||||
let defaultFiles = { name: f.replace(path.extname(f), ''), size: fileInfo[0], unit: fileInfo[1], date: fs.statSync(`./public/uploads/${f}`).ctime, location: `uploads/${f}`, ext: path.extname(f), thumbnail: `/thumbnail/${f}`, img: `/thumbnail/${f.replace(path.extname(f), '.png')}` };
|
// Send file name, file size in MB relative path for the file
|
||||||
|
let fileInfo = formatBytes(fs.statSync(`./public/uploads/${f}`).size).split(' ');
|
||||||
if (f.endsWith('.mp3') || f.endsWith('.flac')) {
|
files.push({ name: f.split('.').slice(0, -1).join('.'), size: fileInfo[0], unit: fileInfo[1], date: fs.statSync(`./public/uploads/${f}`).ctime, location: `uploads/${f}`, ext: f.split('.').pop(), img: '' });
|
||||||
defaultFiles.thumbnail = `./thumbnail/${f.replace(path.extname(f), '.png')}`
|
} else if (f.endsWith('.mp3') || f.endsWith('.flac')) {
|
||||||
|
// Send file name, file size in MB relative path for the file and relative path of music.png
|
||||||
|
let fileInfo = formatBytes(fs.statSync(`./public/uploads/${f}`).size).split(' ');
|
||||||
|
files.push({ name: f.split('.').slice(0, -1).join('.'), size: fileInfo[0], unit: fileInfo[1], date: fs.statSync(`./public/uploads/${f}`).ctime, location: `uploads/${f}`, ext: f.split('.').pop(), img: `/asset/music.png` });
|
||||||
}
|
}
|
||||||
files.push(defaultFiles);
|
|
||||||
}
|
}
|
||||||
defaultViewOption.file = files;
|
|
||||||
return view.render('index', defaultViewOption);
|
return view.render('index', { version: version, viewCounter: viewCounter, file: files, day: day, month: month, announcement: announcement});
|
||||||
}
|
}
|
||||||
|
|
||||||
async download({ view, request, response }) {
|
async download({ view, request, response }) {
|
||||||
let page = 'index';
|
const ws = Ws.getChannel('progress').topic('progress');
|
||||||
if (response.request.url == '/legacy') page = 'legacy';
|
|
||||||
// To be honest i forgot what it does, but i think i need it
|
// To be honest i forgot what it does, but i think i need it
|
||||||
response.implicitEnd = false
|
response.implicitEnd = false
|
||||||
|
|
||||||
|
@ -106,41 +90,16 @@ class DownloadController {
|
||||||
quality: request.input('quality'),
|
quality: request.input('quality'),
|
||||||
format: request.input('format'),
|
format: request.input('format'),
|
||||||
alt: request.input('alt'),
|
alt: request.input('alt'),
|
||||||
feed: request.input('feed'),
|
feed: request.input('feed')
|
||||||
proxy: request.input('proxy'),
|
|
||||||
sponsorBlock : request.input('sponsorBlock')
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!data.url) {
|
if (!data.url) {
|
||||||
let viewOption = {...defaultViewOption};
|
if (ws) {
|
||||||
viewOption.error = true;
|
ws.socket.emit('error', 'bruh moment, you didin\'t input a link.');
|
||||||
viewOption.errormsg = 'bruh moment, you didin\'t input a link.';
|
|
||||||
return view.render(page, viewOption);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (data.url.toLowerCase().includes("porn")) {
|
|
||||||
data.feed = "on";
|
|
||||||
}
|
|
||||||
|
|
||||||
let videoID;
|
|
||||||
if (data.sponsorBlock) {
|
|
||||||
let regExp = /^.*((youtu.be\/)|(v\/)|(\/u\/\w\/)|(embed\/)|(watch\?))\??v?=?([^#&?]*).*/;
|
|
||||||
let match = data.url.match(regExp);
|
|
||||||
videoID = (match&&match[7].length==11)? match[7] : false;
|
|
||||||
if (!videoID) {
|
|
||||||
let viewOption = {...defaultViewOption};
|
|
||||||
viewOption.error = true;
|
|
||||||
viewOption.errormsg = 'To use sponsorBlock you need a valid youtube link!';
|
|
||||||
return view.render(page, viewOption);
|
|
||||||
}
|
}
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Youtube-dl quality settings
|
|
||||||
if (data.quality == 'small')
|
|
||||||
option = 'worst'
|
|
||||||
else
|
|
||||||
option = 'best'
|
|
||||||
|
|
||||||
// If alt download ( Quality settings and file format option doesn't work here )
|
// If alt download ( Quality settings and file format option doesn't work here )
|
||||||
if (data.alt) {
|
if (data.alt) {
|
||||||
let altFolder;
|
let altFolder;
|
||||||
|
@ -156,214 +115,173 @@ class DownloadController {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
let options = ['--format=mp4', '-o', altFolder];
|
return youtubedl.exec(data.url, ['--format=mp4', '-o', altFolder], {}, function(err, output) {
|
||||||
if (data.proxy !== "none") {
|
|
||||||
options.push('--proxy');
|
|
||||||
options.push(data.proxy);
|
|
||||||
}
|
|
||||||
|
|
||||||
return youtubedl.exec(data.url, options, {}, function(err, output) {
|
|
||||||
if (err) {
|
if (err) {
|
||||||
let viewOption = {...defaultViewOption};
|
console.error(err);
|
||||||
viewOption.error = true;
|
if (ws) {
|
||||||
viewOption.errormsg = err;
|
ws.socket.emit('error', err.toString());
|
||||||
return response.send(view.render(page, viewOption))
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
console.log(altFolder.slice(17))
|
||||||
|
if (ws) {
|
||||||
|
ws.socket.emit('end', altFolder.slice(17));
|
||||||
}
|
}
|
||||||
|
|
||||||
return response.attachment(altFolder);
|
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
// Download as mp4 if possible
|
if (data.url.match( /^.*(youtu.be\/|list=)([^#\&\?]*).*/)) {
|
||||||
let options = ['--format=mp4', '-f', option];
|
playlistDownload(data);
|
||||||
if (data.proxy !== "none") {
|
} else {
|
||||||
options.push('--proxy');
|
videoDownload(data);
|
||||||
options.push(data.proxy);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let video = youtubedl(data.url, options);
|
}
|
||||||
|
|
||||||
|
function videoDownload(data) {
|
||||||
|
// Download as mp4 if possible
|
||||||
|
let video = youtubedl(data.url, ['-f', data.quality]);
|
||||||
|
|
||||||
video.on('error', function(err) {
|
video.on('error', function(err) {
|
||||||
console.error(err);
|
console.error(err);
|
||||||
let viewOption = {...defaultViewOption};
|
if (ws) {
|
||||||
viewOption.error = true;
|
ws.socket.emit('error', err.toString());
|
||||||
viewOption.errormsg = err;
|
}
|
||||||
|
})
|
||||||
return response.send(view.render(page, viewOption))
|
|
||||||
});
|
|
||||||
|
|
||||||
let ext;
|
let ext;
|
||||||
|
let size = 0
|
||||||
video.on('info', function(info) {
|
video.on('info', function(info) {
|
||||||
|
size = info.size
|
||||||
// Set file name
|
// Set file name
|
||||||
ext = info.ext;
|
ext = info.ext;
|
||||||
let title = info.title.slice(0,50);
|
let title = info.title.slice(0,50);
|
||||||
DLFile = `${title.replace(/\s/g, '')}.${ext}`;
|
DLFile = `${title.replace(/\s/g, '_')}.${ext}`;
|
||||||
DLFile = DLFile.replace(/[()]|[/]|[\\]|[!]|[?]/g, '');
|
DLFile = DLFile.replace(/[()]|[/]|[\\]|[?]|[!]|[#]/g, '_');
|
||||||
DLFile = DLFile.replace(',', '');
|
|
||||||
|
|
||||||
// If no title use the ID
|
// If no title use the ID
|
||||||
if (title == '_') title = `_${info.id}`;
|
if (title == '_') title = `_${info.id}`;
|
||||||
// If user want to hide from the feed
|
// If user want to hide from the feed
|
||||||
if (data.feed == 'on')
|
if (data.feed == 'on')
|
||||||
DLFile = `hidden/${title}.${ext}`;
|
DLFile = `hidden/${DLFile}`;
|
||||||
|
|
||||||
if (data.sponsorBlock) video.pipe(fs.createWriteStream(`./public/uploads/hidden/${DLFile}`));
|
video.pipe(fs.createWriteStream(`./public/uploads/${DLFile}`));
|
||||||
else video.pipe(fs.createWriteStream(`./public/uploads/${DLFile}`));
|
});
|
||||||
|
|
||||||
|
let pos = 0
|
||||||
|
video.on('data', function data(chunk) {
|
||||||
|
pos += chunk.length
|
||||||
|
// `size` should not be 0 here.
|
||||||
|
if (size) {
|
||||||
|
let percent = (pos / size * 100).toFixed(2)
|
||||||
|
if (ws) {
|
||||||
|
ws.socket.emit('progress', percent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
video.on('end', function() {
|
||||||
|
if (data.format == 'mp3' || data.format == 'flac') {
|
||||||
|
// If user requested an audio format, convert it
|
||||||
|
ffmpeg(`./public/uploads/${DLFile}`)
|
||||||
|
.noVideo()
|
||||||
|
.audioChannels('2')
|
||||||
|
.audioFrequency('44100')
|
||||||
|
.audioBitrate('320k')
|
||||||
|
.format(data.format)
|
||||||
|
.save(`./public/uploads/${DLFile.replace(`.${ext}`, `.${data.format}`)}`)
|
||||||
|
.on('progress', (progress) => {
|
||||||
|
ws.socket.emit(progress.percent)
|
||||||
|
})
|
||||||
|
.on('end', () => {
|
||||||
|
fs.unlinkSync(`./public/uploads/${DLFile}`);
|
||||||
|
if (ws) {
|
||||||
|
ws.socket.emit('end', `./public/uploads/${DLFile.replace(`.${ext}`, `.${data.format}`)}`);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
if (ws) {
|
||||||
|
ws.socket.emit('end', `./public/uploads/${DLFile}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function playlistDownload(data) {
|
||||||
|
const video = youtubedl(data.url)
|
||||||
|
|
||||||
|
video.on('error', function error(err) {
|
||||||
|
console.error(err);
|
||||||
|
if (ws) {
|
||||||
|
ws.socket.emit('error', err.toString());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
let ext;
|
||||||
|
let size = 0
|
||||||
|
video.on('info', function(info) {
|
||||||
|
console.log(info);
|
||||||
|
size = info.size
|
||||||
|
// Set file name
|
||||||
|
ext = info.ext;
|
||||||
|
let title = info.title.slice(0,50);
|
||||||
|
DLFile = `${title.replace(/\s/g, '_')}.${ext}`;
|
||||||
|
DLFile = DLFile.replace(/[()]|[/]|[\\]|[?]|[!]|[#]/g, '_');
|
||||||
|
|
||||||
|
// If no title use the ID
|
||||||
|
if (title == '_') title = `_${info.id}`;
|
||||||
|
// If user want to hide from the feed
|
||||||
|
if (data.feed == 'on')
|
||||||
|
DLFile = `hidden/playlist/${DLFile}`;
|
||||||
|
|
||||||
|
|
||||||
|
video.pipe(fs.createWriteStream(`./public/uploads/playlist/${DLFile}`));
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
let pos = 0
|
||||||
|
video.on('data', function data(chunk) {
|
||||||
|
pos += chunk.length
|
||||||
|
// `size` should not be 0 here.
|
||||||
|
if (size) {
|
||||||
|
let percent = (pos / size * 100).toFixed(2)
|
||||||
|
process.stdout.cursorTo(0)
|
||||||
|
process.stdout.clearLine(1)
|
||||||
|
if (ws) {
|
||||||
|
ws.socket.emit('progress', percent);
|
||||||
|
}
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
video.on('end', function() {
|
video.on('end', function() {
|
||||||
if (data.format == 'mp4' || data.format == 'webm') {
|
if (data.format == 'mp3' || data.format == 'flac') {
|
||||||
if (data.sponsorBlock) { // WARNING: THIS PART SUCK
|
|
||||||
let filter = '';
|
|
||||||
let abc = ['a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z'];
|
|
||||||
fetch(`https://sponsor.ajay.app/api/skipSegments?videoID=${videoID}`)
|
|
||||||
.then(res => {
|
|
||||||
if (res.status === 404) {
|
|
||||||
let viewOption = {...defaultViewOption};
|
|
||||||
viewOption.error = true;
|
|
||||||
viewOption.errormsg = 'Couldn\'t find any SponsorBlock data for this video.';
|
|
||||||
|
|
||||||
return response.send(view.render(page, viewOption));
|
|
||||||
}
|
|
||||||
return res.json()
|
|
||||||
})
|
|
||||||
.then(json => {
|
|
||||||
if (json === undefined) return;
|
|
||||||
let i = 0;
|
|
||||||
let previousEnd;
|
|
||||||
let usedLetter = [];
|
|
||||||
json.forEach(sponsor => {
|
|
||||||
usedLetter.push(abc[i]);
|
|
||||||
if (i === 0) {
|
|
||||||
filter += `[0:v]trim=start=0:end=${sponsor.segment[0]},setpts=PTS-STARTPTS[${abc[i]}v];`;
|
|
||||||
filter += `[0:a]atrim=start=0:end=${sponsor.segment[0]},asetpts=PTS-STARTPTS[${abc[i]}a];`;
|
|
||||||
} else {
|
|
||||||
filter += `[0:v]trim=start=${previousEnd}:end=${sponsor.segment[0]},setpts=PTS-STARTPTS[${abc[i]}v];`;
|
|
||||||
filter += `[0:a]atrim=start=${previousEnd}:end=${sponsor.segment[0]},asetpts=PTS-STARTPTS[${abc[i]}a];`;
|
|
||||||
}
|
|
||||||
previousEnd = sponsor.segment[1];
|
|
||||||
i++;
|
|
||||||
});
|
|
||||||
usedLetter.push(abc[i]);
|
|
||||||
filter += `[0:v]trim=start=${previousEnd},setpts=PTS-STARTPTS[${abc[i]}v];`;
|
|
||||||
filter += `[0:a]atrim=start=${previousEnd},asetpts=PTS-STARTPTS[${abc[i]}a];`;
|
|
||||||
let video = '';
|
|
||||||
let audio = '';
|
|
||||||
usedLetter.forEach(letter => {
|
|
||||||
video += `[${letter}v]`
|
|
||||||
audio += `[${letter}a]`
|
|
||||||
});
|
|
||||||
filter += `${video}concat=n=${i + 1}[outv];`;
|
|
||||||
filter += `${audio}concat=n=${i + 1}:v=0:a=1[outa]`;
|
|
||||||
|
|
||||||
ffmpeg(`./public/uploads/hidden/${DLFile}`)
|
|
||||||
.inputFormat('mp4')
|
|
||||||
.complexFilter(filter)
|
|
||||||
.outputOptions('-map [outv]')
|
|
||||||
.outputOptions('-map [outa]')
|
|
||||||
.save(`./public/uploads/${DLFile}`)
|
|
||||||
.on('error', function(err, stdout, stderr) {
|
|
||||||
console.log('Cannot process video: ' + err.message);
|
|
||||||
let viewOption = {...defaultViewOption};
|
|
||||||
viewOption.error = true;
|
|
||||||
viewOption.errormsg = err.message;
|
|
||||||
|
|
||||||
return response.send(view.render(page, viewOption))
|
|
||||||
})
|
|
||||||
.on('end', () => {
|
|
||||||
console.log('end');
|
|
||||||
response.attachment(`./public/uploads/${DLFile}`)
|
|
||||||
generateThumbnail(DLFile);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
// If user requested mp4 directly attach the file
|
|
||||||
response.attachment(`./public/uploads/${DLFile}`)
|
|
||||||
generateThumbnail(DLFile);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// If user requested an audio format, convert it
|
// If user requested an audio format, convert it
|
||||||
ffmpeg(`./public/uploads/${DLFile}`)
|
ffmpeg(`./public/uploads/playlist/${DLFile}`)
|
||||||
.noVideo()
|
.noVideo()
|
||||||
.audioChannels('2')
|
.audioChannels('2')
|
||||||
.audioFrequency('44100')
|
.audioFrequency('44100')
|
||||||
.audioBitrate('320k')
|
.audioBitrate('320k')
|
||||||
.format(data.format)
|
.format(data.format)
|
||||||
.save(`./public/uploads/${DLFile.replace(`.${ext}`, `.${data.format}`)}`)
|
.save(`./public/uploads/playlist/${DLFile.replace(`.${ext}`, `.${data.format}`)}`)
|
||||||
.on('error', function(err, stdout, stderr) {
|
.on('progress', (progress) => {
|
||||||
console.log('Cannot process video: ' + err.message);
|
ws.socket.emit(progress.percent)
|
||||||
let viewOption = {...defaultViewOption};
|
})
|
||||||
viewOption.error = true;
|
.on('end', () => {
|
||||||
viewOption.errormsg = err.message;
|
fs.unlinkSync(`./public/uploads/playlist/${DLFile}`);
|
||||||
|
if (ws) {
|
||||||
return response.send(view.render(page, viewOption))
|
ws.socket.emit('end', `./public/uploads/playlist/${DLFile.replace(`.${ext}`, `.${data.format}`)}`);
|
||||||
})
|
}
|
||||||
.on('end', () => {
|
});
|
||||||
fs.unlinkSync(`./public/uploads/${DLFile}`);
|
} else {
|
||||||
generateWaveform(DLFile.replace(`.${ext}`, `.${data.format}`));
|
if (ws) {
|
||||||
return response.attachment(`./public/uploads/${DLFile.replace(`.${ext}`, `.${data.format}`)}`);
|
ws.socket.emit('end', `./public/uploads/playlist/${DLFile}`);
|
||||||
});
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
video.on('next', playlistDownload);
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = DownloadController
|
module.exports = DownloadController
|
||||||
|
|
||||||
async function generateWaveform(f) {
|
|
||||||
ffmpeg(`./public/uploads/${f}`)
|
|
||||||
.complexFilter('[0:a]aformat=channel_layouts=mono,compand=gain=-6,showwavespic=s=600x120:colors=#9cf42f[fg];color=s=600x120:color=#44582c,drawgrid=width=iw/10:height=ih/5:color=#9cf42f@0.1[bg];[bg][fg]overlay=format=rgb,drawbox=x=(iw-w)/2:y=(ih-h)/2:w=iw:h=1:color=#9cf42f')
|
|
||||||
.frames(1)
|
|
||||||
.noVideo()
|
|
||||||
.noAudio()
|
|
||||||
.duration(0.1)
|
|
||||||
.on('error', function(err, stdout, stderr) {
|
|
||||||
return console.log('Cannot process video: ' + err.message);
|
|
||||||
})
|
|
||||||
.on('end', () => {
|
|
||||||
generateThumbnail(`../thumbnail/${f.replace(path.extname(f), '.mp4')}`);
|
|
||||||
})
|
|
||||||
.save(`./public/thumbnail/${f.replace(path.extname(f), '.mp4')}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
async function generateThumbnail(f) {
|
|
||||||
ffmpeg(`./public/uploads/${f}`)
|
|
||||||
.screenshots({
|
|
||||||
timestamps: ['20%'],
|
|
||||||
size: '720x480',
|
|
||||||
folder: './public/thumbnail/',
|
|
||||||
filename: f.replace(path.extname(f), '.png')
|
|
||||||
})
|
|
||||||
.on('error', function(err, stdout, stderr) {
|
|
||||||
return console.log('Cannot process video: ' + err.message);
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!fs.existsSync(`./public/thumbnail/tmp/${f}`) && !f.startsWith('../thumbnail'))
|
|
||||||
fs.mkdirSync(`./public/thumbnail/tmp/${f}`)
|
|
||||||
|
|
||||||
ffmpeg(`./public/uploads/${f}`)
|
|
||||||
.complexFilter('select=gt(scene\\,0.8)')
|
|
||||||
.frames(10)
|
|
||||||
.complexFilter('fps=fps=1/10')
|
|
||||||
.save(`./public/thumbnail/tmp/${f}/%03d.png`)
|
|
||||||
.on('error', function(err, stdout, stderr) {
|
|
||||||
return console.log('Cannot process video: ' + err.message);
|
|
||||||
})
|
|
||||||
.on('end', () => {
|
|
||||||
ffmpeg(`./public/thumbnail/tmp/${f}/%03d.png`)
|
|
||||||
.complexFilter('zoompan=d=(.5+.5)/.5:s=640x480:fps=1/.5,framerate=25:interp_start=0:interp_end=255:scene=100')
|
|
||||||
.format('mp4')
|
|
||||||
.save(`./public/thumbnail/${f}`)
|
|
||||||
.on('error', function(err, stdout, stderr) {
|
|
||||||
return console.log('Cannot process video: ' + err.message);
|
|
||||||
})
|
|
||||||
.on('end', () => {
|
|
||||||
// Save space by deleting tmp directory
|
|
||||||
for (let files of fs.readdirSync(`./public/thumbnail/tmp/${f}`)) {
|
|
||||||
if (files == '.keep') return;
|
|
||||||
fs.unlinkSync(`./public/thumbnail/tmp/${f}/${files}`);
|
|
||||||
}
|
|
||||||
fs.rmdirSync(`./public/thumbnail/tmp/${f}`);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
10
app/Controllers/Ws/ProgressController.js
Normal file
10
app/Controllers/Ws/ProgressController.js
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
'use strict'
|
||||||
|
|
||||||
|
class ProgressController {
|
||||||
|
constructor ({ socket, request }) {
|
||||||
|
this.socket = socket
|
||||||
|
this.request = request
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = ProgressController
|
66
config/socket.js
Normal file
66
config/socket.js
Normal file
|
@ -0,0 +1,66 @@
|
||||||
|
'use strict'
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Websocket Config
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| Used by AdonisJs websocket server
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
module.exports = {
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Path
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| The base path on which the websocket server will accept connections.
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
path: '/adonis-ws',
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Server Interval
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| This interval is used to create a timer for identifying dead client
|
||||||
|
| connections.
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
serverInterval: 30000,
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Server Attempts
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| Server attempts are used with serverInterval to identify dead client
|
||||||
|
| connections. A total of `serverAttempts` attmepts after `serverInterval`
|
||||||
|
| will be made before terminating the client connection.
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
serverAttempts: 3,
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Client Interval
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| This interval is used by client to send ping frames to the server.
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
clientInterval: 25000,
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Client Attempts
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| Clients attempts are number of times the client will attempt to send the
|
||||||
|
| ping, without receiving a pong from the server. After attempts have
|
||||||
|
| been elapsed, the client will consider server as dead.
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
clientAttempts: 3
|
||||||
|
}
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "jeff-downloader",
|
"name": "jeff-downloader",
|
||||||
"version": "0.16.4",
|
"version": "0.14.0",
|
||||||
"adonis-version": "4.1.0",
|
"adonis-version": "4.1.0",
|
||||||
"description": "A video downloader based on youtube-dl",
|
"description": "A video downloader based on youtube-dl",
|
||||||
"main": "server.js",
|
"main": "server.js",
|
||||||
|
@ -26,12 +26,15 @@
|
||||||
"@adonisjs/fold": "^4.0.9",
|
"@adonisjs/fold": "^4.0.9",
|
||||||
"@adonisjs/framework": "^5.0.9",
|
"@adonisjs/framework": "^5.0.9",
|
||||||
"@adonisjs/ignitor": "^2.0.8",
|
"@adonisjs/ignitor": "^2.0.8",
|
||||||
"@adonisjs/lucid": "^6.2.0",
|
"@adonisjs/lucid": "^6.1.3",
|
||||||
"@adonisjs/session": "^1.0.27",
|
"@adonisjs/session": "^1.0.27",
|
||||||
"@adonisjs/shield": "^1.0.8",
|
"@adonisjs/shield": "^1.0.8",
|
||||||
"@adonisjs/validator": "^5.0.6",
|
"@adonisjs/validator": "^5.0.6",
|
||||||
|
"@adonisjs/websocket": "^1.0.12",
|
||||||
|
"@adonisjs/websocket-client": "^1.0.9",
|
||||||
|
"archiver": "^3.1.1",
|
||||||
"fluent-ffmpeg": "^2.1.2",
|
"fluent-ffmpeg": "^2.1.2",
|
||||||
"mysql": "^2.17.1",
|
"mysql": "^2.18.1",
|
||||||
"node-fetch": "^2.6.0",
|
"node-fetch": "^2.6.0",
|
||||||
"youtube-dl": "^1.13.1"
|
"youtube-dl": "^1.13.1"
|
||||||
},
|
},
|
||||||
|
|
|
@ -1,11 +0,0 @@
|
||||||
[
|
|
||||||
{
|
|
||||||
"ip": "IP:PORT",
|
|
||||||
"country": "Country",
|
|
||||||
"hideip": true (Optional)
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ip": "IP:PORT",
|
|
||||||
"country": "Country"
|
|
||||||
},
|
|
||||||
]
|
|
1
public/JS/tis.min.js
vendored
Normal file
1
public/JS/tis.min.js
vendored
Normal file
|
@ -0,0 +1 @@
|
||||||
|
!function(){var e,t=document,i="addEventListener",o="charCodeAt",n="keyCode",r="keydown",f=0;t[i](r,function(c){f=c[n]=="&&((%'%'BA"[o](f)?f+1:0,!e&&f>9&&(e=3,function(){function f(e){if(k=j[e])k.currentTime=0;else{k=new Uint8Array(9e3),O=50;for(m in k)N=m>1e3?e>>4&63:e>>10,k[m]=127+(O*=1-(15&e)/1e4)*(N/2>m/10%N?-1:1);k=j[y]=c(k)}k.play()}function c(e){return k=e.length,new Audio(URL.createObjectURL(new Blob(["RIFF",new Uint32Array([k+36,1163280727,544501094,16,65537,22050,22050,524289,1635017060,k]),e],{type:"audio/wav"})))}function p(e,t,i,n){return A&&!(-4&e)&&!(-4&t)&&z[o](8*(n||A)-8+2*i+(t>>1))&1<<4*(1&t)+e}function a(){for(B=g;A&&s(h,g+1,w,1););for(L=0;F+4>L;L++)for(T=0;D>T;T++)y=L*D+T,L>=F&&(K[y]=p(T,L-F,0,V[0])?V[0]:0),R[y]=p(T-h,L-B,w)?A:p(T-h,L-g,w)?A+8:K[y]||0,(N=q["tis-"+y])&&(N=N.style,N.background="#"+(1==e&&2>b%4&&x[L]?"fff":Z[R[y]%8]),N.opacity=R[y]>7?.2:1);g=B,B=it+'0;text-align:right;font-size:150%">',q["tis-status"].innerHTML="Score"+B+W+ot+"Lines"+B+X+ot+"Level"+B+_+ot}function s(e,t,i,o){for(m=0;T=3&m,L=m>>2,16>m;m++)if(p(T,L,i)&&((T+=e)<0||T>=D||(L+=t)<0||L>=F||K[L*D+T]))return;return h=e,g=t,w=i,et=0,o||a(),1}function d(t){if(e){if(C=(t-S)/1e3||0,C>.1&&(C=.1),S=t,2==e){if(b-->4&&!(b%4)){for(T=0;D>T;)K[b*D/4+T++]=1+~~(7*I.random());a()}}else if(1==e){if(--b<0){for(L in x)for(y=L*D+D-1;y>=0;y--)K[y]=K[y-D];e=3}a()}else{for(Y in tt){if((37==Y||39==Y)&&tt[Y]>=0&&(tt[Y]-=tt[Y]?.05:.2,s(h+1-2*(37==Y),g,w)),32==Y&&!tt[Y]){for(;s(h,g+1,w););et=9}if((38==Y||18==Y||17==Y)&&(O=1-2*(17==Y),!tt[Y]))for(y=0;5>y;)if(B=(1==A?Q:P)[o]((w+4+(O-1)/2)%4*5+y++)-32,s(h+O*((7&B)-2),g+O*(2-(B>>3)),(w+4+O)%4)){f(8303);break}tt[Y]+=C}if(v+=I.max(tt[40]?.2:0,C*I.pow(1.23,_)),v>1&&(v=0,s(h,g+1,w)),et>1){A&&f(31445);for(y in K)K[y]=R[y];Y=0,x=[];e:for(L=0;F>L;L++){for(T=0;D>T;)if(!K[L*D+T++])continue e;x[L]=e=1,Y++,b=6}if(Y&&f([,8392,8260,8242,8225][Y]),W+=100*[0,1,3,5,8][Y]*_,X+=Y,_=1+~~(X/10),V.length<2)for(B=1;255!=B;){for(m=0;B&1<<m;m=1+~~(7*I.random()));B|=1<<m,V.push(m)}A=V.shift(),v=0,s(3,0,0)||(A=0,e=2,b=4*F,f(31360))}et+=C}requestAnimationFrame(d)}}function u(i){B=i[n],77==B&&J[J.paused?"play":"pause"](),27==B&&(t.body.removeChild(nt),t[M](r,u),t[M](G,l),J.pause(),e=0),tt[B]=tt[B]||0,[17,18,27,37,38,39,40,77].indexOf(B)>=0&&i.preventDefault()}function l(e){delete tt[e[n]]}var A,h,g,w,b,x,C,v,S,y,m,T,L,B,Y,N,O,k,q=window,E="createElement",M="removeEventListener",G="keyup",I=Math,U="LSOSLSOSKSNSKSNS",J=["`+,^,+Y),`.,C,^`\\Yq^.1e31H,01.,C,^`\\Yq","T$$T,+)$),Y))<$TTYTl.).1^..D,\\.,<$TTTTT`","GNKNGNKN"+U+"LSNSL@BCESOSESOSCOCOCOCOBNBN?J?J@CGL@@@@"],$=["xtvstqpsxtvs\\`}|x","tqspqqpptqspY`xx",U+U+U+U],j=[],K=[],R=[],D=10,F=22,H=D*F+20,Z="08080890dd936f9e809dd090e09c0c9f22".split(9),z=atob("8ABERAAPIiJxACYCcAQiA3QAIgZwASMCZgBmAGYAZgA2AGIEYAMxAnIAYgJwAjICYwBkAjAGMgE"),Q="203(C214A,241<!230#8",P='219"!23+BC23;"#21)BA',V=[],W=0,X=0,_=1,et=2,tt=[],it='<div style="margin:',ot="</div>",nt=it+'-14pc -10pc;position:fixed;width:20pc;left:50%;top:50%;font:12px Arial;background:rgba(0,0,0,.8);box-shadow:0 0 2pc #000;border-radius:1pc">'+it+'1pc 2pc;color:#888"><b><a href="http://github.com/ttencate/tis" style="color:inherit">Tis</a></b>: Tetris clone in just 4 kB of JavaScript<br><br>Left/right: move | Up/Ctrl/Alt: rotate | Esc: quit<br>Down/space: soft/hard drop | M: music'+ot+it+'0 1pc;float:right;color:#eee;font-size:1pc"><div id="tis-status">'+ot+"Next"+it+'8px 0;width:4pc">';for(Y=it+'0;width:1pc;height:1pc;float:left;box-shadow:-2px -2px 8px rgba(0,0,0,.4) inset,0 0 2px #000 inset" id="tis-',y=220;H>y;y++)4>y%D&&(nt+=Y+y+'">'+ot);for(nt+=ot+ot+it+'0 2pc 2pc;background:#000;width:10pc;height:20pc">',y=0;H>y;y++)K.push(0),y>19&&220>y&&(nt+=Y+y+'">'+ot);nt+=ot+ot,B=t[E]("div"),B.innerHTML=nt,t.body.appendChild(nt=B),B=new Uint8Array(881856);for(C in J)for(J[C]+=J[C]+$[C],y=0,m=0;m<J[C].length;)for(N=J[C][o](m++)-(2==C?64:32),T=.00499*I.pow(2,(N%24+(2==C?0:27))/12),Y=[15,9,9][C],L=0;L<4593*[1,3,2,4][~~(N/24)];)B[y++]=(B[y]||127)+(L++*T%2<1?Y:-Y),Y*=.9999;J=c(B),J.play(),J.loop=1,d(0),t[i](r,u),t[i](G,l)}())})}();
|
|
@ -4,6 +4,5 @@
|
||||||
"3": "If you want to support me you can donate through my paypal at the bottom of the page",
|
"3": "If you want to support me you can donate through my paypal at the bottom of the page",
|
||||||
"4": "Did you know this website is open source?",
|
"4": "Did you know this website is open source?",
|
||||||
"5": "Did you know this website can download from other website than youtube?",
|
"5": "Did you know this website can download from other website than youtube?",
|
||||||
"6": "You can mouse hover a video to see a preview of it!",
|
"6": "You can mouse hover a video to see a preview of it!"
|
||||||
"7": "You can test experimental version of the website on https://preview.namejeff.xyz"
|
|
||||||
}
|
}
|
|
@ -20,7 +20,7 @@
|
||||||
"footer2p2": "أعمالي الأخرى",
|
"footer2p2": "أعمالي الأخرى",
|
||||||
"footer2p3": "عدد زيارات هذا الموقع حتى الأن",
|
"footer2p3": "عدد زيارات هذا الموقع حتى الأن",
|
||||||
"footer2p4": "إذا واجهتك اي مشاكل خلال محاولتك لتنزيل المقاطع يمكنك التواصل مع:",
|
"footer2p4": "إذا واجهتك اي مشاكل خلال محاولتك لتنزيل المقاطع يمكنك التواصل مع:",
|
||||||
"footer2p5": "على Discord",
|
"footer2p5": "على Discord",
|
||||||
"footer3p1": "يمكنك اظهار دعمك من خلال",
|
"footer3p1": "يمكنك اظهار دعمك من خلال",
|
||||||
"footer3p2": "او بإرسال",
|
"footer3p2": "او بإرسال",
|
||||||
"footer3p3": "إلى هذا الموقع او من خلال استخدام رابط الإحالة الخاص بي",
|
"footer3p3": "إلى هذا الموقع او من خلال استخدام رابط الإحالة الخاص بي",
|
||||||
|
|
|
@ -5,5 +5,5 @@
|
||||||
"4": "Víte, že tento web je open source?",
|
"4": "Víte, že tento web je open source?",
|
||||||
"5": "Víte, že touto stránkou můžete stáhnout videa z dalším stránkám než Youtubu?",
|
"5": "Víte, že touto stránkou můžete stáhnout videa z dalším stránkám než Youtubu?",
|
||||||
"6": "Můžete najet myší na video abyste viděli náhled!",
|
"6": "Můžete najet myší na video abyste viděli náhled!",
|
||||||
"7": "You can test experimental version of the website on https://preview.namejeff.xyz"
|
"7": "Pokud chcete stáhnout výsledky vyhledávání, můžete použít \"ytsearch:něco\""
|
||||||
}
|
}
|
|
@ -23,7 +23,7 @@
|
||||||
"footer2p5": "na Discordu pokud máte problémy",
|
"footer2p5": "na Discordu pokud máte problémy",
|
||||||
"footer3p1": "Můžete mě taky podporovat na",
|
"footer3p1": "Můžete mě taky podporovat na",
|
||||||
"footer3p2": "nebo dát spropitné",
|
"footer3p2": "nebo dát spropitné",
|
||||||
"footer3p3": "na tomto webu!",
|
"footer3p3": "na tomto webu! Nebo odkaz pro",
|
||||||
"footer4": "Starší verze",
|
"footer4": "Starší verze",
|
||||||
"eggXmas": "Pour féliciter!"
|
"eggXmas": "Pour féliciter!"
|
||||||
}
|
}
|
|
@ -5,5 +5,5 @@
|
||||||
"4": "Did you know this website is open source?",
|
"4": "Did you know this website is open source?",
|
||||||
"5": "Did you know this website can download from other website than youtube?",
|
"5": "Did you know this website can download from other website than youtube?",
|
||||||
"6": "You can mouse hover a video to see a preview of it!",
|
"6": "You can mouse hover a video to see a preview of it!",
|
||||||
"7": "You can test experimental version of the website on https://preview.namejeff.xyz"
|
"7": "Wenn sie das Ergebnis von den Download finden wollen, sie können es mit \"ytsearch:machen\""
|
||||||
}
|
}
|
|
@ -23,7 +23,7 @@
|
||||||
"footer2p5": "auf Discord wenn sie Probleme haben",
|
"footer2p5": "auf Discord wenn sie Probleme haben",
|
||||||
"footer3p1": "Sie können mich hier unterstüzten",
|
"footer3p1": "Sie können mich hier unterstüzten",
|
||||||
"footer3p2": "Oder mit Trinkgeld",
|
"footer3p2": "Oder mit Trinkgeld",
|
||||||
"footer3p3": "auf dieser Website",
|
"footer3p3": "auf dieser Website oder mit meinen link",
|
||||||
"footer4": "Legacy Version",
|
"footer4": "Legacy Version",
|
||||||
"eggXmas": "Frohe Weihnachten"
|
"eggXmas": "Frohe Weihnachten"
|
||||||
}
|
}
|
|
@ -5,5 +5,5 @@
|
||||||
"4": "Did you know this website is open source?",
|
"4": "Did you know this website is open source?",
|
||||||
"5": "Did you know this website can download from websites other than Youtube?",
|
"5": "Did you know this website can download from websites other than Youtube?",
|
||||||
"6": "You can hover your mouse cursor over a video to see a preview of it!",
|
"6": "You can hover your mouse cursor over a video to see a preview of it!",
|
||||||
"7": "You can test experimental version of the website on https://preview.namejeff.xyz"
|
"7": "If you want to download the result of a youtube search you can do so with ytsearch:something"
|
||||||
}
|
}
|
|
@ -23,7 +23,7 @@
|
||||||
"footer2p5": "on Discord if you have any issues",
|
"footer2p5": "on Discord if you have any issues",
|
||||||
"footer3p1": "You can also support me either on",
|
"footer3p1": "You can also support me either on",
|
||||||
"footer3p2": "or by tipping",
|
"footer3p2": "or by tipping",
|
||||||
"footer3p3": "on this website!",
|
"footer3p3": "on this website! or using my referal link for",
|
||||||
"footer4": "Legacy version",
|
"footer4": "Legacy version",
|
||||||
"eggXmas": "Merry Christmas!"
|
"eggXmas": "Merry Christmas!"
|
||||||
}
|
}
|
|
@ -5,5 +5,5 @@
|
||||||
"4": "Did you know this website is open source?",
|
"4": "Did you know this website is open source?",
|
||||||
"5": "Did you know this website can download from websites other than Youtube?",
|
"5": "Did you know this website can download from websites other than Youtube?",
|
||||||
"6": "You can hover your mouse cursor over a video to see a preview of it!",
|
"6": "You can hover your mouse cursor over a video to see a preview of it!",
|
||||||
"7": "You can test experimental version of the website on https://preview.namejeff.xyz"
|
"7": "If you want to download the result of a youtube search you can do so with ytsearch:something"
|
||||||
}
|
}
|
|
@ -23,7 +23,7 @@
|
||||||
"footer2p5": "on Discord if you have any issues",
|
"footer2p5": "on Discord if you have any issues",
|
||||||
"footer3p1": "You can also support me either on",
|
"footer3p1": "You can also support me either on",
|
||||||
"footer3p2": "or by tipping",
|
"footer3p2": "or by tipping",
|
||||||
"footer3p3": "on this website!",
|
"footer3p3": "on this website! or using my referal link for",
|
||||||
"footer4": "Legacy version",
|
"footer4": "Legacy version",
|
||||||
"eggXmas": "Merry Christmas!"
|
"eggXmas": "Merry Christmas!"
|
||||||
}
|
}
|
|
@ -5,5 +5,5 @@
|
||||||
"4": "Le saviez-vous? Le site est open source!",
|
"4": "Le saviez-vous? Le site est open source!",
|
||||||
"5": "Le saviez-vous? Vous pouvez télécharger des vidéos sur d'autre site que youtube.",
|
"5": "Le saviez-vous? Vous pouvez télécharger des vidéos sur d'autre site que youtube.",
|
||||||
"6": "Vous pouvez passer la souris sur une vidéo pour en voir un aperçu!",
|
"6": "Vous pouvez passer la souris sur une vidéo pour en voir un aperçu!",
|
||||||
"7": "Vous pouvez tester la version experimental du site sur https://preview.namejeff.xyz"
|
"7": "Si vous voulez télécharger le résulta d'une recherche youtube vous pouvez le faire avec \"ytsearch:quelque-chose\""
|
||||||
}
|
}
|
|
@ -23,7 +23,7 @@
|
||||||
"footer2p5": "sur Discord si vous avez des problèmes",
|
"footer2p5": "sur Discord si vous avez des problèmes",
|
||||||
"footer3p1": "Vous pouvez me supporter sur",
|
"footer3p1": "Vous pouvez me supporter sur",
|
||||||
"footer3p2": "ou en faisant une donation avec",
|
"footer3p2": "ou en faisant une donation avec",
|
||||||
"footer3p3": "sur ce site!",
|
"footer3p3": "sur ce site! Ou en utilisent mon lien de parrainage pour",
|
||||||
"footer4": "Legacy version",
|
"footer4": "Legacy version",
|
||||||
"eggXmas": "Joyeu noël!"
|
"eggXmas": "Joyeu noël!"
|
||||||
}
|
}
|
|
@ -5,5 +5,5 @@
|
||||||
"4": "Vai tu zināji, ka šī mājaslapa ir balstīta uz atvērto kodu?",
|
"4": "Vai tu zināji, ka šī mājaslapa ir balstīta uz atvērto kodu?",
|
||||||
"5": "Vai tu zināji, ka šī mājaslapa spēj lejupielādēt arī no citiem video servisiem, ne tikai youtube?",
|
"5": "Vai tu zināji, ka šī mājaslapa spēj lejupielādēt arī no citiem video servisiem, ne tikai youtube?",
|
||||||
"6": "Novieto kursoru uz video lai redzētu īsu priekšskatījumu!",
|
"6": "Novieto kursoru uz video lai redzētu īsu priekšskatījumu!",
|
||||||
"7": "You can test experimental version of the website on https://preview.namejeff.xyz"
|
"7": "Ja tu vēlies lejupielādēt kādu klipu caur youtube meklētāju vari to darīt rakstot \"ytsearch:atslēgvārds\""
|
||||||
}
|
}
|
|
@ -23,7 +23,7 @@
|
||||||
"footer2p5": "caur Discord ja atradi kādu nepilnību",
|
"footer2p5": "caur Discord ja atradi kādu nepilnību",
|
||||||
"footer3p1": "Tu vari atbalstīt mani vai nu caur",
|
"footer3p1": "Tu vari atbalstīt mani vai nu caur",
|
||||||
"footer3p2": ", vai ziedojot",
|
"footer3p2": ", vai ziedojot",
|
||||||
"footer3p3": "šinī mājaslapā!",
|
"footer3p3": "šinī mājaslapā! Vēl vari izmantot uzaicinājuma linku",
|
||||||
"footer4": "Agrīnā versija",
|
"footer4": "Agrīnā versija",
|
||||||
"eggXmas": "Priecīgus Ziemassvētkus!"
|
"eggXmas": "Priecīgus Ziemassvētkus!"
|
||||||
}
|
}
|
|
@ -1,8 +1,3 @@
|
||||||
<!--
|
|
||||||
What are you doing here 😳😳😳😳
|
|
||||||
I guess have fun looking at the html, no easter egg to find here.
|
|
||||||
Come take a look here https://git.namejeff.xyz/Supositware/jeff-downloader for all my bad coding
|
|
||||||
-->
|
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html class="has-background-grey-dark" lang="en">
|
<html class="has-background-grey-dark" lang="en">
|
||||||
<head>
|
<head>
|
||||||
|
@ -23,7 +18,7 @@ Come take a look here https://git.namejeff.xyz/Supositware/jeff-downloader for a
|
||||||
<script defer src="https://use.fontawesome.com/releases/v5.3.1/js/all.js"></script>
|
<script defer src="https://use.fontawesome.com/releases/v5.3.1/js/all.js"></script>
|
||||||
<title>{{ antl.formatMessage('messages.title') }} v{{ version }}</title>
|
<title>{{ antl.formatMessage('messages.title') }} v{{ version }}</title>
|
||||||
</head>
|
</head>
|
||||||
<body class="gradientBG has-text-light">
|
<body class="gradientBG area has-text-light">
|
||||||
<ul class="circles">
|
<ul class="circles">
|
||||||
<li></li>
|
<li></li>
|
||||||
<li></li>
|
<li></li>
|
||||||
|
@ -36,6 +31,7 @@ Come take a look here https://git.namejeff.xyz/Supositware/jeff-downloader for a
|
||||||
<li></li>
|
<li></li>
|
||||||
<li></li>
|
<li></li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
<header>
|
<header>
|
||||||
<section class="section" id="announcement">
|
<section class="section" id="announcement">
|
||||||
<div class="container">
|
<div class="container">
|
||||||
|
@ -60,23 +56,21 @@ Come take a look here https://git.namejeff.xyz/Supositware/jeff-downloader for a
|
||||||
<section class="section has-text-centered">
|
<section class="section has-text-centered">
|
||||||
<div class="container ">
|
<div class="container ">
|
||||||
<div class="downloader form">
|
<div class="downloader form">
|
||||||
<h1 class="title has-text-light">{{ antl.formatMessage('messages.title') }} v{{ version }}</h1>
|
<h1 class="title has-text-light"><a style="color: white" href="/">{{ antl.formatMessage('messages.title') }} v{{ version }}</a></h1>
|
||||||
<form name="download-form" method="POST" action="/">
|
<form name="download-form" method="POST" action="/">
|
||||||
{{ csrfField() }}
|
{{ csrfField() }}
|
||||||
@if(month == '11')
|
|
||||||
<script src="JS/snow.js"></script>
|
<div class="field ">
|
||||||
@endif
|
<div class="field-body is-horizontal">
|
||||||
<div class="field is-horizontal">
|
|
||||||
<div class="field-body">
|
|
||||||
<div class="field is-horizontal">
|
<div class="field is-horizontal">
|
||||||
<div class="control">
|
<div class="control">
|
||||||
<label class="radio" for="small">
|
<label class="radio" for="small">
|
||||||
<input class="radio" type="radio" name="quality" id="small" value="small">
|
<input class="radio" type="radio" name="quality" id="small" value="worst">
|
||||||
{{ antl.formatMessage('messages.LQ') }}
|
{{ antl.formatMessage('messages.LQ') }}
|
||||||
</label>
|
</label>
|
||||||
|
|
||||||
<label class="radio" for="high">
|
<label class="radio" for="high">
|
||||||
<input class="radio" type="radio" name="quality" id="high" value="high" checked>
|
<input class="radio" type="radio" name="quality" id="high" value="best" checked>
|
||||||
{{ antl.formatMessage('messages.HQ') }}
|
{{ antl.formatMessage('messages.HQ') }}
|
||||||
</label>
|
</label>
|
||||||
|
|
||||||
|
@ -89,12 +83,6 @@ Come take a look here https://git.namejeff.xyz/Supositware/jeff-downloader for a
|
||||||
<input class="checkbox" type="checkbox" name="feed" id="feed" title="Use this if you don't want the video you are downloading to be public">
|
<input class="checkbox" type="checkbox" name="feed" id="feed" title="Use this if you don't want the video you are downloading to be public">
|
||||||
{{ antl.formatMessage('messages.feed') }}
|
{{ antl.formatMessage('messages.feed') }}
|
||||||
</label>
|
</label>
|
||||||
|
|
||||||
<label class="checkbox" for="sponsorBlock">
|
|
||||||
<input class="checkbox" type="checkbox" name="sponsorBlock" id="sponsorBlock" title="(Using sponsor.ajay.app)">
|
|
||||||
(W.I.P) Remove sponsors of video using <a href="https://sponsor.ajay.app/">SponsorBlock</a>
|
|
||||||
</label>
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -121,9 +109,13 @@ Come take a look here https://git.namejeff.xyz/Supositware/jeff-downloader for a
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="field is-horizontal level">
|
<div id="progression"></div>
|
||||||
|
<br>
|
||||||
|
|
||||||
<div class="control level-left">
|
<div class="field is-horizontal">
|
||||||
|
<div class="field-body">
|
||||||
|
<div class="field is-horizontal">
|
||||||
|
<div class="control">
|
||||||
<label class="radio" for="mp4">
|
<label class="radio" for="mp4">
|
||||||
<input class="radio" type="radio" name="format" value="mp4" id="mp4" checked>
|
<input class="radio" type="radio" name="format" value="mp4" id="mp4" checked>
|
||||||
Video?
|
Video?
|
||||||
|
@ -134,34 +126,19 @@ Come take a look here https://git.namejeff.xyz/Supositware/jeff-downloader for a
|
||||||
MP3?
|
MP3?
|
||||||
</label>
|
</label>
|
||||||
|
|
||||||
<label class="radio" for="flac" title="This is pure placebo">
|
<label class="radio" for="flac">
|
||||||
<input class="radio" type="radio" name="format" value="flac" id="flac" title="This is pure placebo">
|
<input class="radio" type="radio" name="format" value="flac" id="flac">
|
||||||
FLAC?
|
FLAC?
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="field-body level-right">
|
|
||||||
<div class="field is-horizontal">
|
|
||||||
<div class="control">
|
|
||||||
<span>Proxy options:</span>
|
|
||||||
<label class="radio" for="none">
|
|
||||||
<input class="radio" type="radio" name="proxy" value="none" id="none" checked>
|
|
||||||
None
|
|
||||||
</label>
|
|
||||||
@each(proxy in proxy)
|
|
||||||
<label class="radio" for="{{ proxy.ip }}">
|
|
||||||
<input class="radio" type="radio" name="proxy" value="{{ proxy.ip }}" id="{{ proxy.ip }}">
|
|
||||||
{{ proxy.ip.substring(0, proxy.ip.length - 5) }} - {{ proxy.country }}
|
|
||||||
</label>
|
|
||||||
@endeach
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<div id="msg"></div>
|
<div id="msg"></div>
|
||||||
|
|
||||||
@if(error)
|
@if(error)
|
||||||
<div class="notification is-danger fadein" id="error">
|
<div class="notification is-danger fadein" id="error">
|
||||||
<button class="delete" onclick="fadeout('error')"></button>
|
<button class="delete" onclick="fadeout('error')"></button>
|
||||||
|
@ -179,15 +156,13 @@ Come take a look here https://git.namejeff.xyz/Supositware/jeff-downloader for a
|
||||||
<div class="columns is-vcentered is-multiline fadein">
|
<div class="columns is-vcentered is-multiline fadein">
|
||||||
@each(file in file)
|
@each(file in file)
|
||||||
<div class="column hvr-grow">
|
<div class="column hvr-grow">
|
||||||
<div class="column box notification is-dark level">
|
<div class="column box notification is-dark">
|
||||||
<p class="subtitle">{{ file.name }}</p>
|
<p class="subtitle">{{ file.name }}</p>
|
||||||
<div>
|
<div>
|
||||||
<figure class="is-4by3">
|
<video muted loop onmouseover="this.play()" onmouseout="this.pause();" oncanplay="this.muted=true" poster="{{ file.img }}" preload="metadata">
|
||||||
<video muted loop onmouseover="this.play();" onmouseout="this.pause();this.currentTime = 0;" oncanplay="this.muted=true;" poster="{{ file.img }}" preload="metadata">
|
<source src="{{ file.location }}#t=0.5" >
|
||||||
<source src="/thumbnail/{{ file.name }}.mp4#t=0.5" >
|
|
||||||
<img src="{{ file.img }}" title="Your browser does not support the <video> tag">
|
<img src="{{ file.img }}" title="Your browser does not support the <video> tag">
|
||||||
</video>
|
</video>
|
||||||
</figure>
|
|
||||||
</div>
|
</div>
|
||||||
<br>
|
<br>
|
||||||
<div class="content">
|
<div class="content">
|
||||||
|
@ -227,34 +202,80 @@ Come take a look here https://git.namejeff.xyz/Supositware/jeff-downloader for a
|
||||||
</section>
|
</section>
|
||||||
@endif
|
@endif
|
||||||
<footer class="footer has-background-grey-dark has-text-light has-text-centered">
|
<footer class="footer has-background-grey-dark has-text-light has-text-centered">
|
||||||
<p>Uses SponsorBlock API from <a href="https://sponsor.ajay.app/">https://sponsor.ajay.app/</a></p>
|
|
||||||
<p>{{ antl.formatMessage('messages.footer') }}</p>
|
<p>{{ antl.formatMessage('messages.footer') }}</p>
|
||||||
@if(antl._locale == 'ar')
|
@if(antl._locale == 'ar')
|
||||||
<bdi><p>{{ antl.formatMessage('messages.footer2p1') }} <a href="https://github.com/rg3/youtube-dl/">youtube-dl</a> - {{ antl.formatMessage('messages.footer2p2') }} <a href="https://discordapp.com/oauth2/authorize?client_id=377563711927484418&scope=bot&permissions=0">Haha yes</a> & <a href="https://twitter.com/ExplosmR">ExplosmRCG twitter bot</a> - {{ antl.formatMessage('messages.footer2p3') }}: {{ viewCounter }} - {{ antl.formatMessage('messages.footer2p4') }} <a href="https://discord.gg/cNRh5JQ">Supositware#1616</a> {{ antl.formatMessage('messages.footer2p5') }} </bdi></p>
|
<bdi><p>{{ antl.formatMessage('messages.footer2p1') }} <a href="https://github.com/rg3/youtube-dl/">youtube-dl</a> - {{ antl.formatMessage('messages.footer2p2') }} <a href="https://discordapp.com/oauth2/authorize?client_id=377563711927484418&scope=bot&permissions=0">Haha yes</a> & <a href="https://twitter.com/ExplosmR">ExplosmRCG twitter bot</a> - {{ antl.formatMessage('messages.footer2p3') }}: {{ viewCounter }} - {{ antl.formatMessage('messages.footer2p4') }} <a href="https://discord.gg/cNRh5JQ">Supositware#1616</a> {{ antl.formatMessage('messages.footer2p5') }} </bdi></p>
|
||||||
<bdi><p>{{ antl.formatMessage('messages.footer3p1') }} <a href="https://www.paypal.me/supositware">Paypal</a> {{ antl.formatMessage('messages.footer3p2') }} <a href="https://basicattentiontoken.org/">BAT</a> {{ antl.formatMessage('messages.footer3p3') }} <a href="https://brave.com/nam120">Brave Browser </a> </bdi>
|
<bdi><p>{{ antl.formatMessage('messages.footer3p1') }} <a href="https://www.paypal.me/supositware">Paypal</a> {{ antl.formatMessage('messages.footer3p2') }} <a href="https://basicattentiontoken.org/">BAT</a> {{ antl.formatMessage('messages.footer3p3') }} <a href="https://brave.com/nam120">Brave Browser </a> </bdi>
|
||||||
@else
|
@else
|
||||||
<p>{{ antl.formatMessage('messages.footer2p1') }} <a href="https://github.com/rg3/youtube-dl/">youtube-dl</a> - {{ antl.formatMessage('messages.footer2p2') }} <a href="https://discordapp.com/oauth2/authorize?client_id=377563711927484418&scope=bot&permissions=0">Haha yes</a> & <a href="https://twitter.com/ExplosmR">ExplosmRCG twitter bot</a> - {{ antl.formatMessage('messages.footer2p3') }}: {{ viewCounter }} - {{ antl.formatMessage('messages.footer2p4') }} <a href="https://discord.gg/cNRh5JQ">Supositware#1616</a> {{ antl.formatMessage('messages.footer2p5') }}</p>
|
<p>{{ antl.formatMessage('messages.footer2p1') }} <a href="https://github.com/rg3/youtube-dl/">youtube-dl</a> - {{ antl.formatMessage('messages.footer2p2') }} <a href="https://discordapp.com/oauth2/authorize?client_id=377563711927484418&scope=bot&permissions=0">Haha yes</a> & <a href="https://twitter.com/ExplosmR">ExplosmRCG twitter bot</a> - {{ antl.formatMessage('messages.footer2p3') }}: {{ viewCounter }} - {{ antl.formatMessage('messages.footer2p4') }} <a href="https://discord.gg/cNRh5JQ">Supositware#1616</a> {{ antl.formatMessage('messages.footer2p5') }}</p>
|
||||||
<p>{{ antl.formatMessage('messages.footer3p1') }} <a href="https://www.paypal.me/supositware">Paypal</a> {{ antl.formatMessage('messages.footer3p2') }} <a href="https://basicattentiontoken.org/">BAT</a> {{ antl.formatMessage('messages.footer3p3') }} </a>
|
<p>{{ antl.formatMessage('messages.footer3p1') }} <a href="https://www.paypal.me/supositware">Paypal</a> {{ antl.formatMessage('messages.footer3p2') }} <a href="https://basicattentiontoken.org/">BAT</a> {{ antl.formatMessage('messages.footer3p3') }} <a href="https://brave.com/nam120">Brave Browser </a>
|
||||||
@endif
|
@endif
|
||||||
<p><a href="legacy">{{ antl.formatMessage('messages.footer4') }}</a> - <a href="https://git.namejeff.xyz/Supositware/jeff-downloader">Source code</a></p>
|
<p><a href="legacy">{{ antl.formatMessage('messages.footer4') }}</a></p>
|
||||||
</footer>
|
</footer>
|
||||||
@if(month == '11')
|
@if(month == '11')
|
||||||
<script src="JS/snow.js"></script>
|
<script src="JS/snow.js"></script>
|
||||||
@endif
|
@endif
|
||||||
|
<script src="JS/tis.min.js"></script>
|
||||||
</body>
|
</body>
|
||||||
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/babel-polyfill/7.4.4/polyfill.min.js"></script>
|
||||||
|
<script src="https://unpkg.com/@adonisjs/websocket-client"></script>
|
||||||
<script>
|
<script>
|
||||||
function submitDownload() {
|
const ws = adonis.Ws();
|
||||||
|
ws.connect();
|
||||||
|
let channel = ws.subscribe('progress');
|
||||||
|
|
||||||
|
ws.on('open', () => {
|
||||||
|
console.log('is open');
|
||||||
|
});
|
||||||
|
|
||||||
|
ws.on('close', () => {
|
||||||
|
console.log('is closed');
|
||||||
|
});
|
||||||
|
|
||||||
|
channel.on('progress', (message) => {
|
||||||
|
document.getElementById('progress').innerHTML = message + '%';
|
||||||
|
document.getElementById('progress').value = message;
|
||||||
|
});
|
||||||
|
|
||||||
|
channel.on('error', (message) => {
|
||||||
|
console.log(message);
|
||||||
|
document.getElementById('msg').innerHTML = '<div class="notification is-danger fadein" id="error">' + message + '</div>';
|
||||||
|
setTimeout(() => {
|
||||||
|
fadeout('error')
|
||||||
|
}, 5000);
|
||||||
|
});
|
||||||
|
|
||||||
|
channel.on('end', (message) => {
|
||||||
let frm = document.getElementsByName('download-form')[0];
|
let frm = document.getElementsByName('download-form')[0];
|
||||||
frm.submit();
|
frm.reset();
|
||||||
|
|
||||||
|
link = document.createElement("a");
|
||||||
|
link.setAttribute("href", message.substring(9));
|
||||||
|
if (message.includes('/hidden/')) {
|
||||||
|
link.setAttribute("download", message.substring(24));
|
||||||
|
} else {
|
||||||
|
link.setAttribute("download", message.substring(17));
|
||||||
|
}
|
||||||
|
link.click(); //virtually click <a> element to initiate download
|
||||||
|
document.getElementById('progression').innerHTML = '';
|
||||||
|
});
|
||||||
|
|
||||||
|
async function submitDownload() {
|
||||||
document.getElementById('msg').innerHTML = '<div class="notification is-success fadein" id="notif"></button>{{ antl.formatMessage('messages.dlStart') }}</div>';
|
document.getElementById('msg').innerHTML = '<div class="notification is-success fadein" id="notif"></button>{{ antl.formatMessage('messages.dlStart') }}</div>';
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
fadeout('notif')
|
fadeout('notif')
|
||||||
}, 2000);
|
}, 2000);
|
||||||
frm.reset();
|
|
||||||
return false;
|
FD = new FormData(document.getElementsByName('download-form')[0]);
|
||||||
|
fetch('/', {
|
||||||
|
method: 'POST',
|
||||||
|
body: FD
|
||||||
|
});
|
||||||
|
|
||||||
|
document.getElementById('progression').innerHTML = '<progress class="progress is-primary" max="100" id="progress">0%</progress>'
|
||||||
}
|
}
|
||||||
|
|
||||||
function fadeout(id) {
|
async function fadeout(id) {
|
||||||
document.getElementById(id).classList.add('fadeout');
|
document.getElementById(id).classList.add('fadeout');
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
let element = document.getElementById(id);
|
let element = document.getElementById(id);
|
||||||
|
@ -262,22 +283,23 @@ Come take a look here https://git.namejeff.xyz/Supositware/jeff-downloader for a
|
||||||
}, 2000);
|
}, 2000);
|
||||||
}
|
}
|
||||||
|
|
||||||
function toClipboard(text) {
|
async function toClipboard(text) {
|
||||||
navigator.clipboard.writeText(text)
|
navigator.clipboard.writeText(text)
|
||||||
.catch(err => {
|
.catch(err => {
|
||||||
console.error(err);
|
console.error(err);
|
||||||
document.getElementById('msg').innerHTML = '<div class="notification is-error fadein" id="notif">{{ antl.formatMessage('messages.errorCopy') }}</div>';
|
document.getElementById('msg').innerHTML = '<div class="notification is-error fadein" id="notif">{{ antl.formatMessage('messages.errorCopy') }}</div>';
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
fadeout('notif')
|
fadeout('notif')
|
||||||
}, 2000);
|
}, 5000);
|
||||||
});
|
});
|
||||||
document.getElementById('msg').innerHTML = '<div class="notification is-success fadein" id="notif">{{ antl.formatMessage('messages.successCopy') }}</div>';
|
document.getElementById('msg').innerHTML = '<div class="notification is-success fadein" id="notif">{{ antl.formatMessage('messages.successCopy') }}</div>';
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
fadeout('notif')
|
fadeout('notif')
|
||||||
}, 2000);
|
}, 5000);
|
||||||
}
|
}
|
||||||
|
|
||||||
// If alt download block other settings since they don't work anyway
|
// If alt download block other settings since they don't work anyway
|
||||||
document.getElementById('alt').onclick = function() {
|
document.getElementById('alt').onclick = async function() {
|
||||||
if(document.getElementById('alt').checked) {
|
if(document.getElementById('alt').checked) {
|
||||||
document.getElementById('small').disabled = true;
|
document.getElementById('small').disabled = true;
|
||||||
document.getElementById('small').checked = false;
|
document.getElementById('small').checked = false;
|
||||||
|
@ -286,11 +308,8 @@ Come take a look here https://git.namejeff.xyz/Supositware/jeff-downloader for a
|
||||||
document.getElementById('mp3').checked = false;
|
document.getElementById('mp3').checked = false;
|
||||||
document.getElementById('flac').disabled = true;
|
document.getElementById('flac').disabled = true;
|
||||||
document.getElementById('flac').checked = false;
|
document.getElementById('flac').checked = false;
|
||||||
document.getElementById('sponsorBlock').disable = true;
|
|
||||||
document.getElementById('sponsorBlock').disable = false;
|
|
||||||
document.getElementById('mp4').checked = true;
|
document.getElementById('mp4').checked = true;
|
||||||
document.getElementById('high').checked = true;
|
document.getElementById('high').checked = true;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
document.getElementById('small').disabled = false;
|
document.getElementById('small').disabled = false;
|
||||||
document.getElementById('mp3').disabled = false;
|
document.getElementById('mp3').disabled = false;
|
||||||
|
@ -300,17 +319,11 @@ Come take a look here https://git.namejeff.xyz/Supositware/jeff-downloader for a
|
||||||
|
|
||||||
// If user press enter do same thing as if pressing the button
|
// If user press enter do same thing as if pressing the button
|
||||||
let input = document.getElementById("URL");
|
let input = document.getElementById("URL");
|
||||||
input.addEventListener("keyup", function(event) {
|
input.addEventListener("keyup", async function(event) {
|
||||||
if (event.keyCode === 13) {
|
if (event.keyCode === 13) {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
document.getElementById("button").click();
|
document.getElementById("button").click();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
console.log('%cWhat are you doing here 😳😳😳😳', 'font-size: 40px;');
|
|
||||||
|
|
||||||
@if(day == '1' && month == '3')
|
|
||||||
eval(atob('bGV0IGN1ckJsdXI9LjM7ZG9jdW1lbnQuZG9jdW1lbnRFbGVtZW50LnN0eWxlLmZpbHRlcj1gYmx1cigke2N1ckJsdXJ9cHgpYCxzZXRJbnRlcnZhbCgoKT0+e2N1ckJsdXIrPS4xLGRvY3VtZW50LmRvY3VtZW50RWxlbWVudC5zdHlsZS5maWx0ZXI9YGJsdXIoJHtjdXJCbHVyfXB4KWB9LDFlNCk7'));
|
|
||||||
@endif
|
|
||||||
</script>
|
</script>
|
||||||
</html>
|
</html>
|
||||||
|
|
|
@ -20,5 +20,6 @@
|
||||||
const { Ignitor } = require('@adonisjs/ignitor')
|
const { Ignitor } = require('@adonisjs/ignitor')
|
||||||
new Ignitor(require('@adonisjs/fold'))
|
new Ignitor(require('@adonisjs/fold'))
|
||||||
.appRoot(__dirname)
|
.appRoot(__dirname)
|
||||||
|
.wsServer()
|
||||||
.fireHttpServer()
|
.fireHttpServer()
|
||||||
.catch(console.error)
|
.catch(console.error)
|
||||||
|
|
|
@ -21,6 +21,7 @@ const providers = [
|
||||||
'@adonisjs/auth/providers/AuthProvider',
|
'@adonisjs/auth/providers/AuthProvider',
|
||||||
'@adonisjs/validator/providers/ValidatorProvider',
|
'@adonisjs/validator/providers/ValidatorProvider',
|
||||||
'@adonisjs/antl/providers/AntlProvider',
|
'@adonisjs/antl/providers/AntlProvider',
|
||||||
|
'@adonisjs/websocket/providers/WsProvider',
|
||||||
]
|
]
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
18
start/socket.js
Normal file
18
start/socket.js
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
'use strict'
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Websocket
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| This file is used to register websocket channels and start the Ws server.
|
||||||
|
| Learn more about same in the official documentation.
|
||||||
|
| https://adonisjs.com/docs/websocket
|
||||||
|
|
|
||||||
|
| For middleware, do check `wsKernel.js` file.
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
const Ws = use('Ws')
|
||||||
|
|
||||||
|
Ws.channel('progress', 'ProgressController');
|
39
start/wsKernel.js
Normal file
39
start/wsKernel.js
Normal file
|
@ -0,0 +1,39 @@
|
||||||
|
'use strict'
|
||||||
|
|
||||||
|
const Ws = use('Ws')
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Global middleware
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| Global middleware are executed on each Websocket channel subscription.
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
const globalMiddleware = [
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Named middleware
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| Named middleware are defined as key/value pairs. Later you can use the
|
||||||
|
| keys to run selected middleware on a given channel.
|
||||||
|
|
|
||||||
|
| // define
|
||||||
|
| {
|
||||||
|
| auth: 'Adonis/Middleware/Auth'
|
||||||
|
| }
|
||||||
|
|
|
||||||
|
| // use
|
||||||
|
| Ws.channel('chat', 'ChatController').middleware(['auth'])
|
||||||
|
*/
|
||||||
|
const namedMiddleware = {
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Ws
|
||||||
|
.registerGlobal(globalMiddleware)
|
||||||
|
.registerNamed(namedMiddleware)
|
Loading…
Reference in a new issue