Compare commits

...

39 commits

Author SHA1 Message Date
2e1585f497 version bump 2020-11-26 17:24:54 +01:00
e9d68a43a6 hide anything that contain "porn" in the url 2020-11-26 17:24:30 +01:00
9dff68bc7f R.I.P brave referal 2020-11-26 17:24:02 +01:00
3e1fa2f988 Move to gitea 2020-10-25 04:31:29 +01:00
e53e3f4487 Merge remote-tracking branch 'origin/master' into master 2020-10-07 00:49:24 +02:00
24803cc606 version bump 2020-10-07 00:49:14 +02:00
a87d194c2e make thumbnail for audio so browser stop complaining 2020-10-07 00:49:09 +02:00
679b53a993 added thing for first of april & snow 2020-10-07 00:48:31 +02:00
20969f948f Don't use categories for sponsorBlock ( forgot to revert that ) 2020-09-02 23:26:48 +00:00
98c815ee71 bump version 2020-09-03 01:10:54 +02:00
10f4fba062 Made some part be less crap and more error handling 2020-09-03 01:10:34 +02:00
56ff410487 Added link to gitlab 2020-09-03 01:04:03 +02:00
db7f200e23 Added link to gitlab 2020-09-03 00:59:21 +02:00
65b657ca0a make choosing announcement less trash 2020-09-03 00:36:09 +02:00
261c6f64d0 need that folder too 2020-09-02 23:02:18 +02:00
1f133552a3 version bump 2020-09-02 22:47:30 +02:00
b8c70ca4d8 disable sponsorBlock with alt download 2020-09-02 22:47:25 +02:00
5c7044dd19 Handled more error and changed waveform to an image 2020-09-02 22:47:10 +02:00
db0aa8a886 Keep that folder 2020-09-02 22:41:04 +02:00
a244678894 Version bump 2020-08-31 03:13:39 +02:00
a3e24dd68a Added SponsorBlock! 2020-08-31 03:13:33 +02:00
68dbd4ffb0 Bump version 2020-08-30 20:29:38 +00:00
af93b014f7 Don't delete .keep 2020-08-30 22:20:11 +02:00
7eb866cfe4 Need this folder 2020-08-30 22:20:03 +02:00
8277e7ece9 updated a package 2020-08-30 22:17:18 +02:00
909d40fde4 added thumbnail rather than full video and made displaying error work again 2020-08-30 22:17:08 +02:00
826ad44907 added ffmpeg 2020-08-30 19:41:21 +02:00
5fb88fedef Fixed background 2020-08-30 19:41:17 +02:00
585117c47f Update Dockerfile 2020-08-28 03:24:51 +00:00
97792466ca Update .env.example 2020-08-28 03:19:37 +00:00
d48a1e2cec New background 2020-08-27 20:32:37 +02:00
13256850d9 Docker??!!?!??!??!?!!??!?!?!?!?!?!?!?!?!?!?! 2020-08-27 20:22:21 +02:00
95ef53fae0 Forgot to remove a console.log 2020-08-27 20:06:26 +02:00
6d573ff96c bump version 2020-08-27 19:57:36 +02:00
ffc6fe1dd8 Added proxy options 2020-08-27 19:57:27 +02:00
b722935561 example of proxy.json 2020-08-27 19:56:20 +02:00
0cc72a7aa6 announcement about preview version 2020-08-27 19:56:08 +02:00
cb82f9d48f Added proxy file 2020-08-27 19:55:46 +02:00
8b3a140c42 Update .env.example 2020-08-27 16:32:50 +00:00
25 changed files with 622 additions and 207 deletions

View file

@ -1,9 +1,9 @@
HOST=localhost
HOST=0.0.0.0
PORT=3333
NODE_ENV=development
APP_URL=http://${HOST}:${PORT}
CACHE_VIEWS=false
APP_KEY=Please do 'adonis key:generate'
APP_KEY=
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306

7
.gitignore vendored
View file

@ -8,6 +8,9 @@ tmp
# Environment variables, never commit this file
.env
# List of proxy
proxy/proxy.json
# The development sqlite file
database/development.sqlite
@ -29,5 +32,5 @@ public/uploads/hidden/*.mp3
public/uploads/hidden/*.flac
# Thumbnail
public/Thumbnail/*.*
# Thumbnail
public/Thumbnail/*.*

20
Dockerfile Normal file
View file

@ -0,0 +1,20 @@
# 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"]

View file

@ -5,6 +5,9 @@ Jeff downloader is a website to download from [hundreds](https://ytdl-org.github
You can find a hosted version on https://namejeff.xyz/
# 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/)
Major Tom#6196 for AR translation
@ -13,4 +16,4 @@ Major Tom#6196 for AR translation
Mastah Gengu#1596 for DE translation
МeiYali#2457 for CS translation
МeiYali#2457 for CS translation

View file

@ -1,16 +1,20 @@
'use strict'
const youtubedl = require('youtube-dl')
const fs = require('fs')
const ffmpeg = require('fluent-ffmpeg')
const youtubedl = require('youtube-dl');
const fs = require('fs');
const path = require('path');
const ffmpeg = require('fluent-ffmpeg');
const { version } = require('../../../package.json');
const Antl = use('Antl')
const Antl = use('Antl');
const proxy = require('../../../proxy/proxy.json');
const fetch = require('node-fetch');
let viewCounter = 0;
let files = [];
let day;
let month;
let announcementArray;
let announcement
let announcementArray = [];
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
@ -29,53 +33,64 @@ class DownloadController {
async index ({ view, request, locale }) {
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')];
defaultViewOption.viewCounter = viewCounter;
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
announcement = announcementArray[Math.floor(Math.random() * announcementArray.length)];
defaultViewOption.announcement = announcementArray[Math.floor(Math.random() * announcementArray.length)];
// Get date for some event
let today = new Date();
day = today.getDay();
month = today.getMonth();
defaultViewOption.day = today.getDay();
defaultViewOption.month = today.getMonth();
// If legacy link return
if (request.url() == '/legacy') return view.render('legacy', { version: version, viewCounter: viewCounter, day: day, month: month, announcement: announcement});
if (request.url() == '/legacy') return view.render('legacy', defaultViewOption);
files = [];
let file = [];
for (let f of fs.readdirSync('./public/uploads')) {
file.push(f)
if (f.endsWith('.mp4') || f.endsWith('.webm') || f.endsWith('.mp3') || f.endsWith('.flac'))
file.push(f)
}
// get the 5 most recent files
file = file.sort((a, b) => {
if ((a || b).endsWith('.mp4') || (a || b).endsWith('.webm') || (a || b).endsWith('.mp3') || (a || b).endsWith('.flac')) {
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;
}
return 0;
}).slice(0, 5)
// 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')) {
if (!file.includes(f) && (f != 'hidden' && f != '.keep')) {
fs.unlinkSync(`./public/uploads/${f}`);
if (fs.existsSync(`./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) {
if (f.endsWith('.mp4') || f.endsWith('.webm')) {
// Send file name, file size in MB relative path for the file
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: '' });
} 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` });
for (let f of file) {
let fileInfo = formatBytes(fs.statSync(`./public/uploads/${f}`).size).split(' ');
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')}` };
if (f.endsWith('.mp3') || f.endsWith('.flac')) {
defaultFiles.thumbnail = `./thumbnail/${f.replace(path.extname(f), '.png')}`
}
files.push(defaultFiles);
}
return view.render('index', { version: version, viewCounter: viewCounter, file: files, day: day, month: month, announcement: announcement});
defaultViewOption.file = files;
return view.render('index', defaultViewOption);
}
async download({ view, request, response }) {
@ -91,18 +106,33 @@ class DownloadController {
quality: request.input('quality'),
format: request.input('format'),
alt: request.input('alt'),
feed: request.input('feed')
feed: request.input('feed'),
proxy: request.input('proxy'),
sponsorBlock : request.input('sponsorBlock')
}
if (!data.url) {
return view.render(page, {
version: version,
viewCounter: viewCounter,
file: files,
day: day, month: month, announcement: announcement ,
error: true,
errormsg: 'bruh moment, you didin\'t input a link.'
});
let viewOption = {...defaultViewOption};
viewOption.error = true;
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);
}
}
// Youtube-dl quality settings
@ -125,72 +155,153 @@ class DownloadController {
if (err);
});
}
return youtubedl.exec(data.url, ['--format=mp4', '-o', altFolder], {}, function(err, output) {
let options = ['--format=mp4', '-o', altFolder];
if (data.proxy !== "none") {
options.push('--proxy');
options.push(data.proxy);
}
return youtubedl.exec(data.url, options, {}, function(err, output) {
if (err) {
console.error(err);
return response.send(view.render(page, {
version: version,
viewCounter: viewCounter,
file: files,
day: day, month: month, announcement: announcement ,
error: true,
errormsg: err
}));
let viewOption = {...defaultViewOption};
viewOption.error = true;
viewOption.errormsg = err;
return response.send(view.render(page, viewOption))
}
return response.attachment(altFolder);
});
} else {
// Download as mp4 if possible
let video = youtubedl(data.url, ['--format=mp4', '-f', option]);
let options = ['--format=mp4', '-f', option];
if (data.proxy !== "none") {
options.push('--proxy');
options.push(data.proxy);
}
let video = youtubedl(data.url, options);
video.on('error', function(err) {
console.error(err);
return response.send(view.render(page, {
version: version,
viewCounter: viewCounter,
file: files,
day: day, month: month, announcement: announcement ,
error: true,
errormsg: err
}));
})
let viewOption = {...defaultViewOption};
viewOption.error = true;
viewOption.errormsg = err;
return response.send(view.render(page, viewOption))
});
let ext;
video.on('info', function(info) {
// Set file name
ext = info.ext;
let title = info.title.slice(0,50);
DLFile = `${title.replace(/\s/g, '_')}.${ext}`;
DLFile = DLFile.replace(/[()]|[/]|[\\]/g, '_');
DLFile = `${title.replace(/\s/g, '')}.${ext}`;
DLFile = DLFile.replace(/[()]|[/]|[\\]|[!]|[?]/g, '');
DLFile = DLFile.replace(',', '');
// If no title use the ID
if (title == '_') title = `_${info.id}`;
// If user want to hide from the feed
if (data.feed == 'on')
// If user want to hide from the feed
if (data.feed == 'on')
DLFile = `hidden/${title}.${ext}`;
video.pipe(fs.createWriteStream(`./public/uploads/${DLFile}`));
if (data.sponsorBlock) video.pipe(fs.createWriteStream(`./public/uploads/hidden/${DLFile}`));
else video.pipe(fs.createWriteStream(`./public/uploads/${DLFile}`));
});
video.on('end', function() {
if (data.format == 'mp4' || data.format == 'webm') {
// If user requested mp4 directly attach the file
return response.attachment(`./public/uploads/${DLFile}`)
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
ffmpeg(`./public/uploads/${DLFile}`)
.noVideo()
.audioChannels('2')
.audioFrequency('44100')
.audioBitrate('320k')
.format(data.format)
.save(`./public/uploads/${DLFile.replace(`.${ext}`, `.${data.format}`)}`)
.on('end', () => {
fs.unlinkSync(`./public/uploads/${DLFile}`);
return response.attachment(`./public/uploads/${DLFile.replace(`.${ext}`, `.${data.format}`)}`);
})
.noVideo()
.audioChannels('2')
.audioFrequency('44100')
.audioBitrate('320k')
.format(data.format)
.save(`./public/uploads/${DLFile.replace(`.${ext}`, `.${data.format}`)}`)
.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', () => {
fs.unlinkSync(`./public/uploads/${DLFile}`);
generateWaveform(DLFile.replace(`.${ext}`, `.${data.format}`));
return response.attachment(`./public/uploads/${DLFile.replace(`.${ext}`, `.${data.format}`)}`);
});
}
});
}
@ -198,3 +309,61 @@ class 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}`);
});
});
}

View file

@ -1,6 +1,6 @@
{
"name": "jeff-downloader",
"version": "0.13.0",
"version": "0.16.4",
"adonis-version": "4.1.0",
"description": "A video downloader based on youtube-dl",
"main": "server.js",
@ -26,7 +26,7 @@
"@adonisjs/fold": "^4.0.9",
"@adonisjs/framework": "^5.0.9",
"@adonisjs/ignitor": "^2.0.8",
"@adonisjs/lucid": "^6.1.3",
"@adonisjs/lucid": "^6.2.0",
"@adonisjs/session": "^1.0.27",
"@adonisjs/shield": "^1.0.8",
"@adonisjs/validator": "^5.0.6",

11
proxy/proxy.json.example Normal file
View file

@ -0,0 +1,11 @@
[
{
"ip": "IP:PORT",
"country": "Country",
"hideip": true (Optional)
},
{
"ip": "IP:PORT",
"country": "Country"
},
]

149
public/css/background.css Normal file
View file

@ -0,0 +1,149 @@
/* https://codepen.io/mohaiman/pen/MQqMyo */
*{
margin: 0px;
padding: 0px;
}
body{
font-family: 'Exo', sans-serif;
}
.context {
width: 100%;
position: absolute;
top:50vh;
}
.context h1{
text-align: center;
color: #fff;
font-size: 50px;
}
.area{
background: rgb(59,44,207);
background: -webkit-linear-gradient(90deg, rgba(59,44,207,1) 0%, rgba(140,41,151,1) 100%);
width: 100%;
height:100vh;
}
.circles{
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
overflow: hidden;
}
.circles li{
position: absolute;
display: block;
list-style: none;
width: 20px;
height: 20px;
background: rgba(255, 255, 255, 0.2);
animation: animate 25s linear infinite;
bottom: -150px;
}
.circles li:nth-child(1){
left: 25%;
width: 80px;
height: 80px;
animation-delay: 0s;
}
.circles li:nth-child(2){
left: 10%;
width: 20px;
height: 20px;
animation-delay: 2s;
animation-duration: 12s;
}
.circles li:nth-child(3){
left: 70%;
width: 20px;
height: 20px;
animation-delay: 4s;
}
.circles li:nth-child(4){
left: 40%;
width: 60px;
height: 60px;
animation-delay: 0s;
animation-duration: 18s;
}
.circles li:nth-child(5){
left: 65%;
width: 20px;
height: 20px;
animation-delay: 0s;
}
.circles li:nth-child(6){
left: 75%;
width: 110px;
height: 110px;
animation-delay: 3s;
}
.circles li:nth-child(7){
left: 35%;
width: 150px;
height: 150px;
animation-delay: 7s;
}
.circles li:nth-child(8){
left: 50%;
width: 25px;
height: 25px;
animation-delay: 15s;
animation-duration: 45s;
}
.circles li:nth-child(9){
left: 20%;
width: 15px;
height: 15px;
animation-delay: 2s;
animation-duration: 35s;
}
.circles li:nth-child(10){
left: 85%;
width: 150px;
height: 150px;
animation-delay: 0s;
animation-duration: 11s;
}
@keyframes animate {
0%{
transform: translateY(0) rotate(0deg);
opacity: 1;
border-radius: 0;
}
100%{
transform: translateY(-1000px) rotate(720deg);
opacity: 0;
border-radius: 50%;
}
}

View file

View file

View file

@ -4,5 +4,6 @@
"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?",
"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"
}

View file

@ -20,10 +20,10 @@
"footer2p2": "أعمالي الأخرى",
"footer2p3": "عدد زيارات هذا الموقع حتى الأن",
"footer2p4": "إذا واجهتك اي مشاكل خلال محاولتك لتنزيل المقاطع يمكنك التواصل مع:",
"footer2p5": "على Discord",
"footer2p5": "على Discord",
"footer3p1": "يمكنك اظهار دعمك من خلال",
"footer3p2": "او بإرسال",
"footer3p3": "إلى هذا الموقع او من خلال استخدام رابط الإحالة الخاص بي",
"footer4": "النسخة القديمة من هذا الموقع",
"eggXmas": "كريسماس سعيد"
}
}

View file

@ -4,5 +4,6 @@
"3": "Pokud mě chcete podporovat můžete mi dát peníze na Paypalu na dně stránky",
"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?",
"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"
}

View file

@ -23,7 +23,7 @@
"footer2p5": "na Discordu pokud máte problémy",
"footer3p1": "Můžete mě taky podporovat na",
"footer3p2": "nebo dát spropitné",
"footer3p3": "na tomto webu! Nebo odkaz pro",
"footer3p3": "na tomto webu!",
"footer4": "Starší verze",
"eggXmas": "Pour féliciter!"
}
}

View file

@ -4,5 +4,6 @@
"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?",
"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"
}

View file

@ -1,29 +1,29 @@
{
"title": "Le epic downloader",
"announcement": "Ansage",
"LQ": "Niedrige Qualität",
"HQ": "Hohe Qualität",
"altDL": "Alternativer Download",
"feed": "Von Feed verstecken",
"download": "Laden sie das scheiß Video herunter",
"dlStart": "Das Download hat angefangen!",
"errorCopy": "Ein Fehler ist aufgetreten bei dem Kopieren.",
"successCopy": "Erfolgreichlich Kopiert!",
"recentFeed": "Video die vor kurzen gedownloaded wurden",
"recentDownload": "Download",
"recentCopy": "Kopieren zu clipboard",
"recentFormat": "Datei Format",
"recentSize": "Dateigröße",
"recentDate": "Downloaddatum",
"footer": "Ich Ablehene alle Verantwortlichkeiten die website is für downloaden.",
"footer2p1": "Gutschrift an",
"footer2p2": "Meine andere Projekten",
"footer2p3": "Anzahl der Besuche",
"footer2p4": "Kontaktieren",
"footer2p5": "auf Discord wenn sie Probleme haben",
"footer3p1": "Sie können mich hier unterstüzten",
"footer3p2": "Oder mit Trinkgeld",
"footer3p3": "auf dieser Website oder mit meinen link",
"footer4": "Legacy Version",
"eggXmas": "Frohe Weihnachten"
}
{
"title": "Le epic downloader",
"announcement": "Ansage",
"LQ": "Niedrige Qualität",
"HQ": "Hohe Qualität",
"altDL": "Alternativer Download",
"feed": "Von Feed verstecken",
"download": "Laden sie das scheiß Video herunter",
"dlStart": "Das Download hat angefangen!",
"errorCopy": "Ein Fehler ist aufgetreten bei dem Kopieren.",
"successCopy": "Erfolgreichlich Kopiert!",
"recentFeed": "Video die vor kurzen gedownloaded wurden",
"recentDownload": "Download",
"recentCopy": "Kopieren zu clipboard",
"recentFormat": "Datei Format",
"recentSize": "Dateigröße",
"recentDate": "Downloaddatum",
"footer": "Ich Ablehene alle Verantwortlichkeiten die website is für downloaden.",
"footer2p1": "Gutschrift an",
"footer2p2": "Meine andere Projekten",
"footer2p3": "Anzahl der Besuche",
"footer2p4": "Kontaktieren",
"footer2p5": "auf Discord wenn sie Probleme haben",
"footer3p1": "Sie können mich hier unterstüzten",
"footer3p2": "Oder mit Trinkgeld",
"footer3p3": "auf dieser Website",
"footer4": "Legacy Version",
"eggXmas": "Frohe Weihnachten"
}

View file

@ -4,5 +4,6 @@
"3": "If you want to support me you can donate to my Paypal at the bottom of this page",
"4": "Did you know this website is open source?",
"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"
}

View file

@ -23,7 +23,7 @@
"footer2p5": "on Discord if you have any issues",
"footer3p1": "You can also support me either on",
"footer3p2": "or by tipping",
"footer3p3": "on this website! or using my referal link for",
"footer3p3": "on this website!",
"footer4": "Legacy version",
"eggXmas": "Merry Christmas!"
}
}

View file

@ -4,5 +4,6 @@
"3": "If you want to support me you can donate to my Paypal at the bottom of this page",
"4": "Did you know this website is open source?",
"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"
}

View file

@ -23,7 +23,7 @@
"footer2p5": "on Discord if you have any issues",
"footer3p1": "You can also support me either on",
"footer3p2": "or by tipping",
"footer3p3": "on this website! or using my referal link for",
"footer3p3": "on this website!",
"footer4": "Legacy version",
"eggXmas": "Merry Christmas!"
}
}

View file

@ -4,5 +4,6 @@
"3": "Si vous voulez me supporter vous pouvez me faire une donation avec paypal en bas de la page.",
"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.",
"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"
}

View file

@ -23,7 +23,7 @@
"footer2p5": "sur Discord si vous avez des problèmes",
"footer3p1": "Vous pouvez me supporter sur",
"footer3p2": "ou en faisant une donation avec",
"footer3p3": "sur ce site! Ou en utilisent mon lien de parrainage pour",
"footer3p3": "sur ce site!",
"footer4": "Legacy version",
"eggXmas": "Joyeu noël!"
}
}

View file

@ -1,8 +1,9 @@
{
"1": "tu šodien labi izskaties ;)))",
"2": "Es neatbildu par saturu, ko tu lejupielādē.",
"3": "Ja tu vēlies atbalstīt manu projektu, ir iespēja ziedot caur paypal mājaslapas apakšā.",
"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?",
"6": "Novieto kursoru uz video lai redzētu īsu priekšskatījumu!"
}
{
"1": "tu šodien labi izskaties ;)))",
"2": "Es neatbildu par saturu, ko tu lejupielādē.",
"3": "Ja tu vēlies atbalstīt manu projektu, ir iespēja ziedot caur paypal mājaslapas apakšā.",
"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?",
"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"
}

View file

@ -1,29 +1,29 @@
{
"title": "le episkais lejupielādētājs",
"announcement": "Paziņojums",
"LQ": "Zema kvalitāte",
"HQ": "Augsta kvalitāte",
"altDL": "Alternatīva lejupielāde",
"feed": "Paslēpt ziņojumus",
"download": "Lejupielādēt to sasodīto video",
"dlStart": "Lejupielāde sākusies!",
"errorCopy": "Radās kļūda kamēr mēģinājām nokopēt linku tavā vietā.",
"successCopy": "Links tika nokopēts tavā vietā.",
"recentFeed": "Nesen lejupielādētie video",
"recentDownload": "Lejupielādēt",
"recentCopy": "Kopēt saiti",
"recentFormat": "Faila formāts",
"recentSize": "Faila izmērs",
"recentDate": "Lejupielādes datums",
"footer": "Es neuzņemos atbildību par jebkādu saturu, kas tiek lejupielādēts izmantojot šo mājaslapu.",
"footer2p1": "Pateicība",
"footer2p2": "Citi mani projekti",
"footer2p3": "Apmeklējumu skaits",
"footer2p4": "Kontaktējies ar",
"footer2p5": "caur Discord ja atradi kādu nepilnību",
"footer3p1": "Tu vari atbalstīt mani vai nu caur",
"footer3p2": ", vai ziedojot",
"footer3p3": "šinī mājaslapā! Vēl vari izmantot uzaicinājuma linku",
"footer4": "Agrīnā versija",
"eggXmas": "Priecīgus Ziemassvētkus!"
}
{
"title": "le episkais lejupielādētājs",
"announcement": "Paziņojums",
"LQ": "Zema kvalitāte",
"HQ": "Augsta kvalitāte",
"altDL": "Alternatīva lejupielāde",
"feed": "Paslēpt ziņojumus",
"download": "Lejupielādēt to sasodīto video",
"dlStart": "Lejupielāde sākusies!",
"errorCopy": "Radās kļūda kamēr mēģinājām nokopēt linku tavā vietā.",
"successCopy": "Links tika nokopēts tavā vietā.",
"recentFeed": "Nesen lejupielādētie video",
"recentDownload": "Lejupielādēt",
"recentCopy": "Kopēt saiti",
"recentFormat": "Faila formāts",
"recentSize": "Faila izmērs",
"recentDate": "Lejupielādes datums",
"footer": "Es neuzņemos atbildību par jebkādu saturu, kas tiek lejupielādēts izmantojot šo mājaslapu.",
"footer2p1": "Pateicība",
"footer2p2": "Citi mani projekti",
"footer2p3": "Apmeklējumu skaits",
"footer2p4": "Kontaktējies ar",
"footer2p5": "caur Discord ja atradi kādu nepilnību",
"footer3p1": "Tu vari atbalstīt mani vai nu caur",
"footer3p2": ", vai ziedojot",
"footer3p3": "šinī mājaslapā!",
"footer4": "Agrīnā versija",
"eggXmas": "Priecīgus Ziemassvētkus!"
}

View file

@ -1,3 +1,8 @@
<!--
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>
<html class="has-background-grey-dark" lang="en">
<head>
@ -13,11 +18,24 @@
<link rel="icon" href="/asset/favicon.ico" type="image/x-icon"/>
<link rel="shortcut icon" href="asset/favicon.ico" type="image/x-icon"/>
<link rel="stylesheet" type="text/css" href="css/index.css">
<link rel="stylesheet" type="text/css" href="css/background.css">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bulma@0.8.0/css/bulma.min.css">
<script defer src="https://use.fontawesome.com/releases/v5.3.1/js/all.js"></script>
<title>{{ antl.formatMessage('messages.title') }} v{{ version }}</title>
</head>
<body class="gradientBG has-text-light">
<ul class="circles">
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
</ul>
<header>
<section class="section" id="announcement">
<div class="container">
@ -33,7 +51,7 @@
@endif
<p class="subtitle">{{ announcement }}</p>
</div>
</div>
</div>
@endif
</div>
</section>
@ -45,35 +63,43 @@
<h1 class="title has-text-light">{{ antl.formatMessage('messages.title') }} v{{ version }}</h1>
<form name="download-form" method="POST" action="/">
{{ csrfField() }}
@if(month == '11')
<script src="JS/snow.js"></script>
@endif
<div class="field is-horizontal">
<div class="field-body">
<div class="field is-horizontal">
<div class="control">
<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="small">
{{ antl.formatMessage('messages.LQ') }}
</label>
<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="high" checked>
{{ antl.formatMessage('messages.HQ') }}
</label>
<label class="checkbox" for="alt">
<input class="checkbox" type="checkbox" name="alt" id="alt" title="Use this if download dosen't work">
{{ antl.formatMessage('messages.altDL') }}
</label>
<label class="checkbox" for="feed">
<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') }}
</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 class="field-body">
<div class="field is-expanded">
<div class="field has-addons">
@ -86,41 +112,56 @@
</div>
</div>
</div>
<div class="field has-addon">
<div class="control">
</div>
<div class="control">
</div>
</div>
<div class="field is-horizontal">
<div class="field-body">
<div class="field is-horizontal">
<div class="control">
<div class="field is-horizontal level">
<div class="control level-left">
<label class="radio" for="mp4">
<input class="radio" type="radio" name="format" value="mp4" id="mp4" checked>
Video?
</label>
<label class="radio" for="mp3">
<input class="radio" type="radio" name="format" value="mp3" id="mp3">
MP3?
</label>
<label class="radio" for="flac">
<input class="radio" type="radio" name="format" value="flac" id="flac">
<label class="radio" for="flac" title="This is pure placebo">
<input class="radio" type="radio" name="format" value="flac" id="flac" title="This is pure placebo">
FLAC?
</label>
</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>
</form>
<div class="contaianer">
<div id="msg"></div>
<div class="container">
<div id="msg"></div>
@if(error)
<div class="notification is-danger fadein" id="error">
<button class="delete" onclick="fadeout('error')"></button>
@ -133,18 +174,20 @@
</section>
@if(file != "")
<p class="title has-text-light has-text-centered">{{ antl.formatMessage('messages.recentFeed') }}</p>
<p class="title has-text-light has-text-centered">{{ antl.formatMessage('messages.recentFeed') }}</p>
<section class="section">
<div class="columns is-vcentered is-multiline fadein">
@each(file in file)
<div class="column hvr-grow">
<div class="column box notification is-dark">
<div class="column box notification is-dark level">
<p class="subtitle">{{ file.name }}</p>
<div>
<video muted loop onmouseover="this.play()" onmouseout="this.pause();" oncanplay="this.muted=true" poster="{{ file.img }}" preload="metadata">
<source src="{{ file.location }}#t=0.5" >
<figure class="is-4by3">
<video muted loop onmouseover="this.play();" onmouseout="this.pause();this.currentTime = 0;" oncanplay="this.muted=true;" poster="{{ file.img }}" preload="metadata">
<source src="/thumbnail/{{ file.name }}.mp4#t=0.5" >
<img src="{{ file.img }}" title="Your browser does not support the <video> tag">
</video>
</figure>
</div>
<br>
<div class="content">
@ -152,7 +195,7 @@
<p class="control">
<a class="button is-link is-rounded" href="{{ file.location }}" download>{{ antl.formatMessage('messages.recentDownload') }}<i class="fas fa-fw fa-file-download" aria-hidden="true"></i></a>
</p>
<p class="control">
<p class="control">
<button class="button is-link is-rounded" onclick="toClipboard('https:\/\/namejeff.xyz\/{{ file.location }}')">{{ antl.formatMessage('messages.recentCopy') }}<i class="fas fa-fw fa-clipboard" aria-hidden="true"></i></button>
</p>
</div>
@ -184,15 +227,16 @@
</section>
@endif
<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>
@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.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
<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 href="https://brave.com/nam120">Brave Browser </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>
@endif
<p><a href="legacy">{{ antl.formatMessage('messages.footer4') }}</a></p>
<p><a href="legacy">{{ antl.formatMessage('messages.footer4') }}</a> - <a href="https://git.namejeff.xyz/Supositware/jeff-downloader">Source code</a></p>
</footer>
@if(month == '11')
<script src="JS/snow.js"></script>
@ -224,7 +268,7 @@
console.error(err);
document.getElementById('msg').innerHTML = '<div class="notification is-error fadein" id="notif">{{ antl.formatMessage('messages.errorCopy') }}</div>';
setTimeout(() => {
fadeout('notif')
fadeout('notif')
}, 2000);
});
document.getElementById('msg').innerHTML = '<div class="notification is-success fadein" id="notif">{{ antl.formatMessage('messages.successCopy') }}</div>';
@ -242,8 +286,11 @@
document.getElementById('mp3').checked = false;
document.getElementById('flac').disabled = true;
document.getElementById('flac').checked = false;
document.getElementById('sponsorBlock').disable = true;
document.getElementById('sponsorBlock').disable = false;
document.getElementById('mp4').checked = true;
document.getElementById('high').checked = true;
} else {
document.getElementById('small').disabled = false;
document.getElementById('mp3').disabled = false;
@ -251,7 +298,7 @@
}
}
// If user press enter do samething as if pressing the button
// If user press enter do same thing as if pressing the button
let input = document.getElementById("URL");
input.addEventListener("keyup", function(event) {
if (event.keyCode === 13) {
@ -259,5 +306,11 @@
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>
</html>
</html>