Compare commits
No commits in common. "master" and "master" have entirely different histories.
2
AUTHORS
2
AUTHORS
@ -1,4 +1,4 @@
|
||||
@sergiotarxz:sergiotarxz.hopto.org (Matrix address.)
|
||||
@ale@ale.manalejandro.com/@ale@mastodon.madrid (Fediverse accounts.)
|
||||
@destinyuwu:sergiotarxz.hopto.org (Matrix address.)
|
||||
@abnazhor (Telegram.)
|
||||
|
||||
|
@ -1,7 +0,0 @@
|
||||
{
|
||||
"version" : "0.0.1",
|
||||
"name" : "Peertube-DL",
|
||||
"author" : "sergiotarxz",
|
||||
"abstract" : "A module for downloading videos from various webpages",
|
||||
"license" : "AGPLv3"
|
||||
}
|
@ -43,9 +43,6 @@ if ( defined $download_data->{options}{list} && $download_data->{options}{list}
|
||||
say "The urls are:\n" . join "\n", @$urls;
|
||||
}
|
||||
} elsif ( defined $download_data->{options}{list_formats} && $download_data->{options}{list_formats} ) {
|
||||
say 'Listing formats available.';
|
||||
delete $download_data->{options};
|
||||
say "The available formats are: @{[Data::Dumper::Dumper $download_data]}";
|
||||
exit 0;
|
||||
} else {
|
||||
downloadVideo( $ua, $download_data );
|
||||
|
@ -1,24 +0,0 @@
|
||||
#!/sbin/openrc-run
|
||||
|
||||
# Requires OpenRC >= 0.35
|
||||
directory=/var/lib/peertubedl
|
||||
|
||||
PATH="/var/lib/peertubedl/perl5/bin${PATH:+:${PATH}}"; export PATH;
|
||||
PERL5LIB="/var/lib/peertubedl/perl5/lib/perl5${PERL5LIB:+:${PERL5LIB}}"; export PERL5LIB;
|
||||
PERL_LOCAL_LIB_ROOT="/var/lib/peertubedl/perl5${PERL_LOCAL_LIB_ROOT:+:${PERL_LOCAL_LIB_ROOT}}"; export PERL_LOCAL_LIB_ROOT;
|
||||
PERL_MB_OPT="--install_base \"/var/lib/peertubedl/perl5\""; export PERL_MB_OPT;
|
||||
PERL_MM_OPT="INSTALL_BASE=/var/lib/peertubedl/perl5"; export PERL_MM_OPT;
|
||||
|
||||
command=/var/lib/peertubedl/perl5/bin/peertube-dl-hypnotoad
|
||||
|
||||
command_args=""
|
||||
|
||||
command_user=peertubedl:peertubedl
|
||||
|
||||
pidfile="/var/lib/peertubedl/peertube-dl-web.pid"
|
||||
|
||||
export PIDFILE=$pidfile
|
||||
|
||||
depend() {
|
||||
need postgresql
|
||||
}
|
@ -298,10 +298,7 @@ sub animeid {
|
||||
filename => $filename,
|
||||
};
|
||||
} else {
|
||||
return {
|
||||
url => $download_redirect_url,
|
||||
filename => $filename,
|
||||
}
|
||||
die 'Getting redirect failed because: ' . $video_response->status_line;
|
||||
}
|
||||
}
|
||||
1;
|
||||
|
@ -67,6 +67,9 @@ sub getDownloadDataFromURL {
|
||||
die "No description." unless defined $download_data->{description};
|
||||
die "No formats available." unless defined $download_data->{formats};
|
||||
die "Formats is not a hash." unless ref $download_data->{formats} eq 'HASH';
|
||||
say "The video title is $download_data->{title}.";
|
||||
say "The video description is $download_data->{description}.";
|
||||
say "The available formats are: @{[Data::Dumper::Dumper $download_data->{formats}]}.";
|
||||
return $download_data;
|
||||
}
|
||||
}
|
||||
|
@ -5,6 +5,5 @@
|
||||
clients => 3,
|
||||
proxy => 1,
|
||||
pid_file => $ENV{PIDFILE} || '/var/run/peertube-dl-web.pid',
|
||||
},
|
||||
theme => 'new_look_default',
|
||||
}
|
||||
};
|
||||
|
@ -1,321 +0,0 @@
|
||||
#!/usr/bin/env perl
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use Test::Most tests => 5;
|
||||
use Digest::SHA qw/sha512_hex/;
|
||||
use Data::Dumper;
|
||||
|
||||
BEGIN {
|
||||
use_ok 'Peertube::DL::URLHandler';
|
||||
}
|
||||
|
||||
## Tests WITH signatures.
|
||||
{
|
||||
my $download_data = Peertube::DL::URLHandler::getDownloadDataFromURL(
|
||||
'https://www.youtube.com/watch?v=nqc4t4029as');
|
||||
my $download_data_expected = {
|
||||
'formats' => {
|
||||
'audio_formats' => [
|
||||
{
|
||||
'mimeType' => 'audio/webm; codecs="opus"',
|
||||
'quality' => 'tiny',
|
||||
'audioSampleRate' => 48000,
|
||||
'bitrate' => 133750,
|
||||
'id' => 251
|
||||
},
|
||||
{
|
||||
'bitrate' => 67550,
|
||||
'id' => 250,
|
||||
'mimeType' => 'audio/webm; codecs="opus"',
|
||||
'quality' => 'tiny',
|
||||
'audioSampleRate' => 48000
|
||||
},
|
||||
{
|
||||
'bitrate' => 51104,
|
||||
'id' => 249,
|
||||
'mimeType' => 'audio/webm; codecs="opus"',
|
||||
'audioSampleRate' => 48000,
|
||||
'quality' => 'tiny'
|
||||
}
|
||||
],
|
||||
'video_formats' => [
|
||||
{
|
||||
'qualityLabel' => 1080,
|
||||
'mimeType' => 'video/mp4; codecs="avc1.640028"',
|
||||
'quality' => 'hd1080',
|
||||
'id' => 137,
|
||||
'bitrate' => 1610654
|
||||
},
|
||||
{
|
||||
'quality' => 'hd1080',
|
||||
'mimeType' => 'video/webm; codecs="vp9"',
|
||||
'qualityLabel' => 1080,
|
||||
'bitrate' => 1552727,
|
||||
'id' => 248
|
||||
},
|
||||
{
|
||||
'bitrate' => 1074995,
|
||||
'id' => 399,
|
||||
'mimeType' => 'video/mp4; codecs="av01.0.08M.08"',
|
||||
'qualityLabel' => 1080,
|
||||
'quality' => 'hd1080'
|
||||
},
|
||||
{
|
||||
'id' => 247,
|
||||
'bitrate' => 687059,
|
||||
'quality' => 'hd720',
|
||||
'mimeType' => 'video/webm; codecs="vp9"',
|
||||
'qualityLabel' => 720
|
||||
},
|
||||
{
|
||||
'quality' => 'hd720',
|
||||
'qualityLabel' => 720,
|
||||
'mimeType' => 'video/mp4; codecs="av01.0.05M.08"',
|
||||
'id' => 398,
|
||||
'bitrate' => 659074
|
||||
},
|
||||
{
|
||||
'mimeType' => 'video/mp4; codecs="avc1.4d401f"',
|
||||
'qualityLabel' => 720,
|
||||
'quality' => 'hd720',
|
||||
'id' => 136,
|
||||
'bitrate' => 579992
|
||||
},
|
||||
{
|
||||
'id' => 244,
|
||||
'bitrate' => 421009,
|
||||
'qualityLabel' => 480,
|
||||
'mimeType' => 'video/webm; codecs="vp9"',
|
||||
'quality' => 'large'
|
||||
},
|
||||
{
|
||||
'quality' => 'large',
|
||||
'mimeType' => 'video/mp4; codecs="av01.0.04M.08"',
|
||||
'qualityLabel' => 480,
|
||||
'id' => 397,
|
||||
'bitrate' => 385094
|
||||
},
|
||||
{
|
||||
'mimeType' => 'video/mp4; codecs="avc1.4d401e"',
|
||||
'qualityLabel' => 480,
|
||||
'quality' => 'large',
|
||||
'id' => 135,
|
||||
'bitrate' => 353336
|
||||
},
|
||||
{
|
||||
'bitrate' => 645178,
|
||||
'id' => 18,
|
||||
'mimeType' => 'video/mp4; codecs="avc1.42001E, mp4a.40.2"',
|
||||
'quality' => 'medium',
|
||||
'qualityLabel' => 360,
|
||||
'audioSampleRate' => '44100'
|
||||
},
|
||||
{
|
||||
'quality' => 'medium',
|
||||
'qualityLabel' => 360,
|
||||
'mimeType' => 'video/webm; codecs="vp9"',
|
||||
'bitrate' => 281570,
|
||||
'id' => 243
|
||||
},
|
||||
{
|
||||
'id' => 134,
|
||||
'bitrate' => 241943,
|
||||
'quality' => 'medium',
|
||||
'qualityLabel' => 360,
|
||||
'mimeType' => 'video/mp4; codecs="avc1.4d401e"'
|
||||
},
|
||||
{
|
||||
'bitrate' => 234609,
|
||||
'id' => 396,
|
||||
'quality' => 'medium',
|
||||
'qualityLabel' => 360,
|
||||
'mimeType' => 'video/mp4; codecs="av01.0.01M.08"'
|
||||
},
|
||||
{
|
||||
'mimeType' => 'video/webm; codecs="vp9"',
|
||||
'qualityLabel' => 240,
|
||||
'quality' => 'small',
|
||||
'id' => 242,
|
||||
'bitrate' => 160233
|
||||
},
|
||||
{
|
||||
'qualityLabel' => 240,
|
||||
'mimeType' => 'video/mp4; codecs="avc1.4d4015"',
|
||||
'quality' => 'small',
|
||||
'bitrate' => 130312,
|
||||
'id' => 133
|
||||
},
|
||||
{
|
||||
'id' => 395,
|
||||
'bitrate' => 121695,
|
||||
'mimeType' => 'video/mp4; codecs="av01.0.00M.08"',
|
||||
'qualityLabel' => 240,
|
||||
'quality' => 'small'
|
||||
},
|
||||
{
|
||||
'id' => 278,
|
||||
'bitrate' => 86048,
|
||||
'quality' => 'tiny',
|
||||
'qualityLabel' => 144,
|
||||
'mimeType' => 'video/webm; codecs="vp9"'
|
||||
},
|
||||
{
|
||||
'bitrate' => 77340,
|
||||
'id' => 160,
|
||||
'qualityLabel' => 144,
|
||||
'mimeType' => 'video/mp4; codecs="avc1.4d400c"',
|
||||
'quality' => 'tiny'
|
||||
},
|
||||
{
|
||||
'mimeType' => 'video/mp4; codecs="av01.0.00M.08"',
|
||||
'qualityLabel' => 144,
|
||||
'quality' => 'tiny',
|
||||
'bitrate' => 63369,
|
||||
'id' => 394
|
||||
}
|
||||
]
|
||||
},
|
||||
'options' => { 'list_formats' => 1 },
|
||||
'description' =>
|
||||
"Tras el \x{e9}xito de Zeus, Hades, Poseid\x{f3}n y Dem\x{e9}ter, hoy os traemos la canci\x{f3}n de otra de sus hermanas, \x{a1}Hestia! \x{bf}A qu\x{e9} esperas para descubrir la historia de esta diosa de la mitolog\x{ed}a griega en un nuevo Destripando la Historia?
|
||||
|
||||
\x{a1}Suscr\x{ed}bete a nuestro canal!
|
||||
http://bit.ly/pascuyrodri
|
||||
|
||||
\x{a1}Escucha esta y otras canciones en SPOTIFY!
|
||||
https://spoti.fi/2SY6zni
|
||||
|
||||
\x{a1}Consigue nuestras camisetas, chapas y l\x{e1}minas!
|
||||
https://www.destripandolahistoria.es
|
||||
*Solo con env\x{ed}o a Espa\x{f1}a peninsular.
|
||||
|
||||
\x{a1}Tambi\x{e9}n ten\x{e9}is parte de nuestro merchandising en Teespring!
|
||||
(Con env\x{ed}os internacionales)
|
||||
https://www.teespring.com/stores/destripandolahistoria
|
||||
|
||||
|
||||
\x{a1}Puedes seguir a Destripando la Historia en Facebook, Instagram y Twitter! Publicamos contenido extra como dibujos, v\x{ed}deos cantando en directo o tonter\x{ed}as absurdas, ya nos conoc\x{e9}is...
|
||||
|
||||
http://www.instagram.com/destripandolahistoria
|
||||
http://www.facebook.com/destripandolahistoria
|
||||
https://twitter.com/pascuyrodri
|
||||
|
||||
\x{a1}Hola a todos!
|
||||
\x{a1}La cuarentena no ha podido con nosotros y aqu\x{ed} ten\x{e9}is un nuevo v\x{ed}deo! Esperamos que est\x{e9}is todos bien y que lo disfrut\x{e9}is. Si hab\x{e9}is le\x{ed}do hasta aqu\x{ed}, como venganza porque Pascu ha metido una foto m\x{ed}a al principio del v\x{ed}deo, os pido que pong\x{e1}is en los comentarios: \x{201c}Pascu, baja la tapa del v\x{e1}ter\x{201d}.
|
||||
|
||||
Rodri
|
||||
|
||||
\x{a1}Recordad que pod\x{e9}is seguirnos tambi\x{e9}n en nuestras redes sociales personales!
|
||||
|
||||
http://www.instagram.com/rodrigoseptienmusic
|
||||
https://www.instagram.com/alv_pascu/
|
||||
https://twitter.com/var_Stark
|
||||
https://twitter.com/RodrigoSeptien",
|
||||
'title' => 'Hestia | Destripando la Historia'
|
||||
};
|
||||
is_deeply $download_data, $download_data_expected,
|
||||
'Testing listing formats with obfuscated signatures.';
|
||||
}
|
||||
|
||||
{
|
||||
my $download_data = Peertube::DL::URLHandler::getDownloadDataFromURL(
|
||||
'https://www.youtube.com/watch?v=nqc4t4029as', { format => 18 } );
|
||||
my $ua = Peertube::DL::URLHandler::generateUA();
|
||||
my $downloaded_video_checksum =
|
||||
sha512_hex( $ua->get( $download_data->{url} )->decoded_content );
|
||||
my $expected_checksum =
|
||||
'a59f5f1e582bd558ef4e928d7edfd942452aff5084218a3470da946d73c94f28e102773d5b19f47c6224492a82e6c7072a47aae87333bcfeda457a33626c92e7';
|
||||
is $downloaded_video_checksum, $expected_checksum,
|
||||
'Testing downloading with obfuscated signatures.';
|
||||
}
|
||||
|
||||
## WITHOUT signature.
|
||||
{
|
||||
my $expected_download_data = {
|
||||
'description' =>
|
||||
'Richard Stallman en Ecuador, cantando el temita, del free software, grabado por Julian Coccia.',
|
||||
'formats' => {
|
||||
'audio_formats' => [
|
||||
{
|
||||
'bitrate' => 139941,
|
||||
'id' => 251,
|
||||
'quality' => 'tiny',
|
||||
'audioSampleRate' => 48000,
|
||||
'mimeType' => 'audio/webm; codecs="opus"'
|
||||
},
|
||||
{
|
||||
'bitrate' => 72446,
|
||||
'id' => 250,
|
||||
'audioSampleRate' => 48000,
|
||||
'quality' => 'tiny',
|
||||
'mimeType' => 'audio/webm; codecs="opus"'
|
||||
},
|
||||
{
|
||||
'bitrate' => 55976,
|
||||
'id' => 249,
|
||||
'quality' => 'tiny',
|
||||
'audioSampleRate' => 48000,
|
||||
'mimeType' => 'audio/webm; codecs="opus"'
|
||||
}
|
||||
],
|
||||
'video_formats' => [
|
||||
{
|
||||
'id' => 18,
|
||||
'bitrate' => 367576,
|
||||
'audioSampleRate' => '44100',
|
||||
'quality' => 'small',
|
||||
'mimeType' => 'video/mp4; codecs="avc1.42001E, mp4a.40.2"',
|
||||
'qualityLabel' => 240
|
||||
},
|
||||
{
|
||||
'bitrate' => 244690,
|
||||
'id' => 133,
|
||||
'quality' => 'small',
|
||||
'qualityLabel' => 240,
|
||||
'mimeType' => 'video/mp4; codecs="avc1.4d400d"'
|
||||
},
|
||||
{
|
||||
'mimeType' => 'video/webm; codecs="vp9"',
|
||||
'quality' => 'small',
|
||||
'qualityLabel' => 240,
|
||||
'id' => 242,
|
||||
'bitrate' => 161442
|
||||
},
|
||||
{
|
||||
'bitrate' => 112818,
|
||||
'id' => 160,
|
||||
'qualityLabel' => 144,
|
||||
'quality' => 'tiny',
|
||||
'mimeType' => 'video/mp4; codecs="avc1.4d400c"'
|
||||
},
|
||||
{
|
||||
'mimeType' => 'video/webm; codecs="vp9"',
|
||||
'quality' => 'tiny',
|
||||
'qualityLabel' => 144,
|
||||
'id' => 278,
|
||||
'bitrate' => 70172
|
||||
}
|
||||
]
|
||||
},
|
||||
'title' => 'Richard Stallman Free software Song'
|
||||
};
|
||||
my $download_data = Peertube::DL::URLHandler::getDownloadDataFromURL(
|
||||
'https://www.youtube.com/watch?v=9sJUDx7iEJw');
|
||||
delete $download_data->{options};
|
||||
is_deeply( $download_data, $expected_download_data,
|
||||
'Testing listing signatures without obfuscated signatures.' );
|
||||
}
|
||||
|
||||
{
|
||||
my $download_data = Peertube::DL::URLHandler::getDownloadDataFromURL(
|
||||
'https://www.youtube.com/watch?v=9sJUDx7iEJw', { format => 18 } );
|
||||
my $ua = Peertube::DL::URLHandler::generateUA();
|
||||
my $downloaded_video_checksum =
|
||||
sha512_hex( $ua->get( $download_data->{url} )->decoded_content );
|
||||
my $expected_checksum =
|
||||
'16343940a5473a2ac3f485d11b1e920c974a4f506859368f669ad8af4a30b885b41c8ba301364997fc2ae50bb41d9d167768bcd9bfb4a51d76767ec165b744da';
|
||||
is $downloaded_video_checksum, $expected_checksum,
|
||||
'Testing downloading without obfuscated signatures.';
|
||||
}
|
387
themes/default/public/dist/css/index.css
vendored
387
themes/default/public/dist/css/index.css
vendored
@ -1,276 +1,189 @@
|
||||
body {
|
||||
height: 99.9%;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
height: 98vh;
|
||||
|
||||
a {
|
||||
color: blue;
|
||||
}
|
||||
display: flex;
|
||||
flex-flow: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
||||
a:hover,a:focus {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
#video {
|
||||
width: 100%;
|
||||
margin: 3px;
|
||||
}
|
||||
|
||||
#modal-video-container {
|
||||
display: none;
|
||||
background: white;
|
||||
position: fixed;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
transform: translate(-50%, -50%);
|
||||
border: black 1px solid;
|
||||
}
|
||||
|
||||
#modal-video-container.active {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.video-container-bar {
|
||||
display: flex;
|
||||
justify-content: right;
|
||||
}
|
||||
|
||||
#close-and-reset-video-container {
|
||||
margin-top: 0.25rem;
|
||||
margin-right: 0.25rem;
|
||||
border: 1px solid black;
|
||||
}
|
||||
|
||||
#close-and-reset-video-container:hover:#close-and-reset-video-container:focus {
|
||||
background: black;
|
||||
color: white;
|
||||
}
|
||||
|
||||
#download-video-container {
|
||||
margin: 10px;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
#download-video-container a {
|
||||
display: none;
|
||||
padding-left: 5px;
|
||||
padding-right: 5px;
|
||||
padding-top: 5px;
|
||||
padding-bottom: 5px;
|
||||
width: 100%;
|
||||
background: #0a0;
|
||||
border-radius: 5px;
|
||||
font-size: 30px;
|
||||
color: white;
|
||||
height: 30px;
|
||||
}
|
||||
|
||||
#download-video-container a.active {
|
||||
display: block;
|
||||
}
|
||||
|
||||
#download-video-container a embed {
|
||||
height: 30px;
|
||||
}
|
||||
|
||||
#video-container {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
flex-direction: column;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.block {
|
||||
display: block;
|
||||
background-color: #111827;
|
||||
}
|
||||
|
||||
.application-container {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
flex-direction: column;
|
||||
text-align: center;
|
||||
height: 100%;
|
||||
background: #000;
|
||||
color: white;
|
||||
display: flex;
|
||||
flex-flow: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
||||
border-radius: 0.3rem;
|
||||
|
||||
background-color: #1f2937;
|
||||
|
||||
padding: 1.5rem 3rem 1.5rem 3rem;
|
||||
}
|
||||
|
||||
#download-form {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
flex-direction: column;
|
||||
.application-container form {
|
||||
display: flex;
|
||||
flex-flow: column;
|
||||
justify-content: center;
|
||||
|
||||
width: 100%;
|
||||
padding: 1rem;
|
||||
}
|
||||
|
||||
#download-form-button {
|
||||
margin-top: 5px;
|
||||
height: 50px;
|
||||
font-size: 1.5rem;
|
||||
background: #fff;
|
||||
color: black;
|
||||
border: none;
|
||||
.application-container h2 {
|
||||
color: #ffffff;
|
||||
font-weight: 400;
|
||||
font-size: 1.6rem;
|
||||
}
|
||||
|
||||
h2 {
|
||||
font-size: 2rem;
|
||||
.application-container input {
|
||||
padding: 1rem;
|
||||
|
||||
color: #ffffff;
|
||||
background-color: #374151;
|
||||
|
||||
border-radius: 0.2rem;
|
||||
border: 1px solid transparent;
|
||||
}
|
||||
|
||||
#modal-loading {
|
||||
display: none;
|
||||
position: fixed;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
transform: translate(-50%, -50%);
|
||||
border: black 1px solid;
|
||||
justify-content: right;
|
||||
align-items: center;
|
||||
.application-container button {
|
||||
margin-top: 1rem;
|
||||
|
||||
color: #ffffff;
|
||||
font-weight: bold;
|
||||
|
||||
background-color: #059669;
|
||||
|
||||
border-radius: 0.2rem;
|
||||
border: 1px solid transparent;
|
||||
|
||||
padding: 0.5rem 1rem 0.5rem 1rem;
|
||||
}
|
||||
|
||||
#modal-loading.active {
|
||||
display: flex;
|
||||
.application-container button,
|
||||
.application-container input {
|
||||
font-size: 0.9rem;
|
||||
}
|
||||
|
||||
#modal-loading embed {
|
||||
width: 10%;
|
||||
.application-container.active {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
#poping-notice {
|
||||
display: none;
|
||||
position: fixed;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
border: black 1px solid;
|
||||
width: 91%;
|
||||
background: white;
|
||||
padding: 10px;
|
||||
border-radius: 15px;
|
||||
max-height: 95%;
|
||||
overflow-y: scroll;
|
||||
}
|
||||
position: absolute;
|
||||
display: none;
|
||||
width: 40%;
|
||||
padding: 3rem;
|
||||
border-radius: 0.3rem;
|
||||
background-color: #374151;
|
||||
color: white;
|
||||
}
|
||||
|
||||
#poping-notice.active {
|
||||
display: block;
|
||||
#poping-notice-content a {
|
||||
text-decoration: none;
|
||||
color: #10b981;
|
||||
}
|
||||
|
||||
#poping-notice-container-bar {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
font-size: 5rem;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
#close-poping-notice {
|
||||
width: 150px;
|
||||
height: 150px;
|
||||
align-items: center;
|
||||
display: flex;
|
||||
text-align: center;
|
||||
justify-content: center;
|
||||
border-radius: 50%;
|
||||
background: #0f0;
|
||||
color: black;
|
||||
text-decoration: none;
|
||||
background-color: #059669;
|
||||
padding: 0.5rem 5rem 0.5rem 5rem;
|
||||
border-radius: 0.3rem;
|
||||
text-decoration: none;
|
||||
font-weight: bolder;
|
||||
color: white;
|
||||
}
|
||||
|
||||
#close-poping-notice:hover,#close-poping-notice:focus {
|
||||
background: black;
|
||||
color: white;
|
||||
#modal-video-container {
|
||||
position: absolute;
|
||||
display: none;
|
||||
|
||||
height: 100vh;
|
||||
width: 100%;
|
||||
|
||||
flex-flow: column;
|
||||
align-items: center;
|
||||
|
||||
background-color: #111827;
|
||||
}
|
||||
|
||||
.video-container-bar {
|
||||
width: 95%;
|
||||
height: 2rem;
|
||||
padding: 1rem;
|
||||
display: flex;
|
||||
justify-content: end;
|
||||
}
|
||||
|
||||
.video-container-bar a {
|
||||
padding: 1rem;
|
||||
border-radius: 0.3rem;
|
||||
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
||||
background-color: #dc2626;
|
||||
}
|
||||
|
||||
#modal-video-container > #block {
|
||||
display: flex;
|
||||
flex-flow: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
#download-video-container {
|
||||
padding: 2rem;
|
||||
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
#download-video-prepare,
|
||||
#download-video {
|
||||
display: none;
|
||||
border-radius: 0.3rem;
|
||||
background-color: #059669;
|
||||
text-decoration: none;
|
||||
color: white;
|
||||
user-select: none;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
#download-video-loading.active {
|
||||
height: 2rem;
|
||||
}
|
||||
|
||||
#download-video-container a.active,
|
||||
#download-video-loading.active {
|
||||
display: block;
|
||||
padding: 0.5rem 2rem 0.5rem 2rem;
|
||||
}
|
||||
|
||||
#modal-loading,
|
||||
#modal-format-selector {
|
||||
display: none;
|
||||
background: white;
|
||||
position: fixed;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
transform: translate(-50%, -50%);
|
||||
border: black 1px solid;
|
||||
flex-direction: column;
|
||||
overflow-y: scroll;
|
||||
display: none;
|
||||
}
|
||||
|
||||
#modal-format-selector.active {
|
||||
display: flex;
|
||||
#poping-notice.active,
|
||||
#modal-video-container.active {
|
||||
--tw-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1),
|
||||
0 4px 6px -2px rgba(0, 0, 0, 0.05);
|
||||
box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000),
|
||||
var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow);
|
||||
}
|
||||
|
||||
#modal-format-selector > h2 {
|
||||
text-align: center;
|
||||
width: 100%;
|
||||
#poping-notice.active {
|
||||
display: block;
|
||||
}
|
||||
|
||||
#modal-format-selector > p {
|
||||
margin-left: 2rem;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
#modal-format-selector .format-list {
|
||||
box-sizing: border-box;
|
||||
background: #fff;
|
||||
margin: 2rem;
|
||||
}
|
||||
|
||||
#close-modal-format-selector {
|
||||
margin-top: 0.50rem;
|
||||
margin-right: 0.50rem;
|
||||
border: 1px solid black;
|
||||
background: grey;
|
||||
color: white;
|
||||
width: 25px;
|
||||
height: 25px;
|
||||
text-align: center;
|
||||
font-size: 20px;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
#close-modal-format-selector:hover,#close-modal-format-selector:focus {
|
||||
background: black;
|
||||
}
|
||||
|
||||
.format-list > div {
|
||||
width: 100%;
|
||||
display: grid;
|
||||
grid-auto-columns: 50%;
|
||||
grid-template-areas: "a a";
|
||||
}
|
||||
|
||||
.format-list > div > a {
|
||||
border: 1px solid black;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: 1.5rem;
|
||||
padding-right: 5%;
|
||||
padding-left: 5%;
|
||||
text-decoration: none;
|
||||
color: black;
|
||||
background: #eee;
|
||||
overflow-wrap: anywhere;
|
||||
}
|
||||
|
||||
.format-list > div > a:hover {
|
||||
background: black;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.format-list > div > a:after {
|
||||
padding-bottom: 100%;
|
||||
display: block;
|
||||
content: "";
|
||||
}
|
||||
|
||||
div.video-formats a {
|
||||
background: #f00;
|
||||
}
|
||||
|
||||
@media (min-width: 668px) {
|
||||
#poping-notice {
|
||||
width: 629px;
|
||||
}
|
||||
}
|
||||
#modal-video-container.active {
|
||||
display: flex;
|
||||
}
|
@ -1,327 +0,0 @@
|
||||
body {
|
||||
height: 98vh;
|
||||
|
||||
display: flex;
|
||||
flex-flow: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
||||
background-color: #FF69B4;
|
||||
}
|
||||
|
||||
.application-container {
|
||||
display: flex;
|
||||
flex-flow: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
||||
border-radius: 0.3rem;
|
||||
|
||||
background-color: #C71585;
|
||||
|
||||
padding: 1.5rem 3rem 1.5rem 3rem;
|
||||
}
|
||||
|
||||
.application-container form {
|
||||
display: flex;
|
||||
flex-flow: column;
|
||||
justify-content: center;
|
||||
|
||||
width: 100%;
|
||||
padding: 1rem;
|
||||
}
|
||||
|
||||
.application-container h2 {
|
||||
color: #ffffff;
|
||||
font-weight: 400;
|
||||
font-size: 1.6rem;
|
||||
}
|
||||
|
||||
.application-container input {
|
||||
padding: 1rem;
|
||||
|
||||
color: #C71585;
|
||||
background-color: #FFB6C1;
|
||||
|
||||
border-radius: 0.2rem;
|
||||
border: 1px solid transparent;
|
||||
}
|
||||
|
||||
.application-container button {
|
||||
margin-top: 1rem;
|
||||
|
||||
color: #ffffff;
|
||||
font-weight: bold;
|
||||
|
||||
background-color: #059669;
|
||||
|
||||
border-radius: 0.2rem;
|
||||
border: 1px solid transparent;
|
||||
|
||||
padding: 0.5rem 1rem 0.5rem 1rem;
|
||||
}
|
||||
|
||||
.application-container button:hover,.application-container button:focus {
|
||||
background-color: #059;
|
||||
}
|
||||
|
||||
.application-container button,
|
||||
.application-container input {
|
||||
font-size: 0.9rem;
|
||||
}
|
||||
|
||||
.application-container.active {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
#poping-notice-content a {
|
||||
text-decoration: none;
|
||||
color: lime;
|
||||
}
|
||||
|
||||
#poping-notice-content a:hover,#poping-notice-content a:focus {
|
||||
color: aqua;
|
||||
}
|
||||
|
||||
#poping-notice-container-bar {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
#close-poping-notice {
|
||||
background-color: #059669;
|
||||
padding: 0.5rem 5rem 0.5rem 5rem;
|
||||
border-radius: 0.3rem;
|
||||
text-decoration: none;
|
||||
font-weight: bolder;
|
||||
color: white;
|
||||
}
|
||||
|
||||
#close-poping-notice:hover,#close-poping-notice:focus {
|
||||
background-color: #059;
|
||||
}
|
||||
|
||||
.modal {
|
||||
position: fixed;
|
||||
display: none;
|
||||
color: white;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
}
|
||||
|
||||
#poping-notice {
|
||||
padding: 3rem;
|
||||
border-radius: 0.3rem;
|
||||
background-color: #C71585;
|
||||
color: white;
|
||||
overflow-y: scroll;
|
||||
width: 94%;
|
||||
max-height: 70%;
|
||||
flex-direction: column;
|
||||
scrollbar-width: none;
|
||||
}
|
||||
|
||||
#modal-video-container,#modal-format-selector {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
flex-flow: column;
|
||||
align-items: center;
|
||||
background-color: #FF69B4;
|
||||
}
|
||||
|
||||
#modal-format-selector h2 {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
#modal-format-selector p {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.video-container-bar {
|
||||
width: 99%;
|
||||
height: 2rem;
|
||||
padding-top: 1rem;
|
||||
padding-bottom: 1rem;
|
||||
display: flex;
|
||||
justify-content: end;
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
.video-container-bar a {
|
||||
padding: 1rem;
|
||||
margin-right: 1rem;
|
||||
border-radius: 0.3rem;
|
||||
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
||||
background-color: #dc2626;
|
||||
}
|
||||
|
||||
.video-container-bar a:hover,.video-container-bar a:focus {
|
||||
color: white;
|
||||
background-color: grey;
|
||||
}
|
||||
|
||||
|
||||
#modal-video-container > #block {
|
||||
display: flex;
|
||||
flex-flow: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
#download-video-container {
|
||||
padding: 2rem;
|
||||
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.button-download {
|
||||
display: none;
|
||||
border-radius: 0.3rem;
|
||||
background-color: #059669;
|
||||
text-decoration: none;
|
||||
color: white;
|
||||
user-select: none;
|
||||
cursor: pointer;
|
||||
height: 30px;
|
||||
padding: 0 2rem;
|
||||
}
|
||||
|
||||
.button-download:hover,.button-download:focus {
|
||||
background-color: #059;
|
||||
}
|
||||
|
||||
.button-download embed {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
#download-video-loading.active {
|
||||
height: 2rem;
|
||||
}
|
||||
|
||||
#download-video-container .button-download.active {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
#modal-loading {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.modal {
|
||||
--tw-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1),
|
||||
0 4px 6px -2px rgba(0, 0, 0, 0.05);
|
||||
box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000),
|
||||
var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow);
|
||||
overflow-y: scroll;
|
||||
}
|
||||
|
||||
#poping-notice.active {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.modal.active {
|
||||
display: flex;
|
||||
scrollbar-width: none;
|
||||
}
|
||||
|
||||
.modal.active.active::-webkit-scrollbar {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#modal-loading {
|
||||
display: none;
|
||||
position: fixed;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
transform: translate(-50%, -50%);
|
||||
border: black 1px solid;
|
||||
justify-content: right;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
#modal-loading.active {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
#modal-loading embed {
|
||||
width: 10%;
|
||||
}
|
||||
|
||||
#video {
|
||||
width: 100%;
|
||||
max-width: 636px;
|
||||
}
|
||||
|
||||
#video-container {
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.format-list > div {
|
||||
display: grid;
|
||||
grid-column-gap: 10px;
|
||||
grid-row-gap: 10px;
|
||||
grid-template-areas: "a";
|
||||
grid-auto-columns: 99%;
|
||||
margin: 1rem;
|
||||
}
|
||||
|
||||
.format-list > div > a {
|
||||
border: 1px solid black;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: 1.5rem;
|
||||
padding-right: 5%;
|
||||
padding-left: 5%;
|
||||
text-decoration: none;
|
||||
border-radius: 0.5rem;
|
||||
background-color: #059669;
|
||||
overflow-wrap: anywhere;
|
||||
}
|
||||
|
||||
.format-list > div > a:focus,.format-list > div > a:hover {
|
||||
background-color: #059;
|
||||
}
|
||||
|
||||
.format-list > div > a:after {
|
||||
padding-bottom: 100%;
|
||||
display: block;
|
||||
content: "";
|
||||
}
|
||||
|
||||
.scale {
|
||||
height: 1em;
|
||||
width; 1em;
|
||||
}
|
||||
|
||||
@media (min-width: 600px) {
|
||||
.format-list > div {
|
||||
grid-template-areas: "a a";
|
||||
grid-auto-columns: 49.75%;
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 805px) {
|
||||
.format-list > div {
|
||||
grid-template-areas: "a a a";
|
||||
grid-auto-columns: 33%;
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 812px) {
|
||||
#poping-notice {
|
||||
width: 40%;
|
||||
}
|
||||
}
|
Binary file not shown.
Before Width: | Height: | Size: 66 KiB |
Binary file not shown.
Before Width: | Height: | Size: 3.6 KiB |
@ -1,76 +0,0 @@
|
||||
<html>
|
||||
<head>
|
||||
<script src="js/peertube-dl-web.js?v=1"></script>
|
||||
<link rel="stylesheet" href="css/index.css?v=4"></script>
|
||||
<link rel="icon" type="image/png" href="img/peertube-dl-logo.png"/>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Peertube-dl Web</title>
|
||||
<meta name="description" content="Webpage intended to download videos from various webpages for fair use."/>
|
||||
<meta property="og:type" content="website" />
|
||||
<meta property="og:title" content="Peertube-dl Web"/>
|
||||
<meta property="og:site_name" content="Peertube-dl"/>
|
||||
<meta property="og:description" content="Webpage intended to download videos from various webpages for fair use."/>
|
||||
<meta property="og:image" content="./img/peertube-dl-logo-fullsize.png"/>
|
||||
</head>
|
||||
<body>
|
||||
<div class="application-container">
|
||||
<h2>Peertube-dl Web Application</h2>
|
||||
<form id="download-form">
|
||||
<input class="block" type="text" id="download-form-url" placeholder="Introduce the url you want to download."/>
|
||||
<button class="block" id="download-form-button" >Fetch from api</button>
|
||||
</form>
|
||||
</div>
|
||||
<div id="modal-format-selector" class="modal">
|
||||
<div class="video-container-bar">
|
||||
<a id="close-modal-format-selector">x</a>
|
||||
</div>
|
||||
<h2>Example video</h2>
|
||||
<p>Example description</p>
|
||||
<div class="format-list">
|
||||
<h3>Video Formats.</h3>
|
||||
<div class="video-formats">
|
||||
</div>
|
||||
<h3>Audio Formats.</h3>
|
||||
<div class="audio-formats">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="modal-loading">
|
||||
<embed src="img/spinner.svg"/>
|
||||
</div>
|
||||
<div id="modal-video-container" class="modal">
|
||||
<div class="video-container-bar">
|
||||
<a id="close-and-reset-video-container">x</a>
|
||||
</div>
|
||||
<div id="video-container">
|
||||
<div class="block">
|
||||
<video id="video" controls="controls"></video>
|
||||
</div>
|
||||
<div id="download-video-container" class="block">
|
||||
<a id="download-video-prepare" class="button-download active">Prepare download</a>
|
||||
<a id="download-video-loading" class="button-download"><embed src="img/spinner.svg"/></a>
|
||||
<a id="download-video" class="button-download">Download</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="poping-notice" class="modal">
|
||||
<div id="poping-notice-content">
|
||||
<p>This webpage is free as in freedom software, it is offered to you with the hope it will be useful, but without any warranty,
|
||||
you can find the source code at <a href="https://gitea.sergiotarxz.freemyip.com/sergiotarxz/Peertube-dl">my gitea</a> with docs to setup your own
|
||||
webpage like this, this software is licensed under the AGPLv3 license which means you MUST convey the source code in a human readable form
|
||||
if you distribute this software or use it as an service to users of service or distributees.<p>
|
||||
|
||||
<p>I hope that if you find a non supported url which should be supported, a bug, or a feature you would like this webpage to have you file an issue in
|
||||
<a href="https://gitea.sergiotarxz.freemyip.com/sergiotarxz/Peertube-dl/issues">https://gitea.sergiotarxz.freemyip.com/sergiotarxz/Peertube-dl/issues</a>
|
||||
to help this software improve since I find tracking users a pretty bad way to discover bugs and potential good features.</p>
|
||||
|
||||
<p>This webpage may load third party resources depending on the url you give to it which may put cookies in your browser, you are
|
||||
encouraged to frecuently delete your browser cookies to avoid those third parties tracking you on internet, Firefox offers you an
|
||||
option to delete cookies as soon as you close the browser which may be a good idea to enable in the orwellian internet of today.</p>
|
||||
</div>
|
||||
<div id="poping-notice-container-bar">
|
||||
<a id="close-poping-notice" href="#">X</a>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
@ -1,13 +0,0 @@
|
||||
{
|
||||
"name": "default-theme",
|
||||
"version": "1.0.0",
|
||||
"private": true,
|
||||
"license": "MIT",
|
||||
"scripts": {
|
||||
"build": "webpack"
|
||||
},
|
||||
"dependencies": {
|
||||
"webpack": "^5.15.0",
|
||||
"webpack-cli": "^4.3.1"
|
||||
}
|
||||
}
|
@ -1,106 +0,0 @@
|
||||
"use strict";
|
||||
|
||||
import { PopingNotice } from './view/poping_notice.js';
|
||||
import { DownloadForm } from './view/download_form.js';
|
||||
import { LoadingModal } from './view/loading_modal.js';
|
||||
import { VideoContainer } from './view/video_container.js';
|
||||
import { FormatSelector } from './view/format_selector.js';
|
||||
|
||||
class Application {
|
||||
constructor() {
|
||||
this.poping_notice = new PopingNotice();
|
||||
this.download_form = new DownloadForm(this.onDownloadFormGot.bind(this));
|
||||
this.loading_modal = new LoadingModal();
|
||||
this.video_container = new VideoContainer();
|
||||
this.format_selector = new FormatSelector();
|
||||
}
|
||||
|
||||
init() {
|
||||
this.popingNotice.setVisible(true);
|
||||
}
|
||||
|
||||
onDownloadFormGot(url) {
|
||||
this.dispatchURL(url);
|
||||
}
|
||||
|
||||
dispatchURL(url, format) {
|
||||
this.loadingModal.setVisible(true);
|
||||
let error_str;
|
||||
let success = this.queryAPI(url, format).then( (response) => {
|
||||
if ( response.options !== undefined && response.options.list_formats !== undefined && response.options.list_formats ) {
|
||||
if ( response.formats === undefined
|
||||
|| response.formats.audio_formats === undefined
|
||||
|| response.formats.video_formats === undefined ) {
|
||||
throw 'Format object is not valid.';
|
||||
}
|
||||
this.formatSelector.prepareFormatSelector(
|
||||
response.title, response.description,
|
||||
response.formats.audio_formats, response.formats.video_formats,
|
||||
( id ) => {
|
||||
this.loadingModal.setVisible(true);
|
||||
this.dispatchURL(url, id);
|
||||
});
|
||||
this.formatSelector.setVisible(true);
|
||||
this.loadingModal.setVisible(false);
|
||||
} else {
|
||||
this.videoContainer.onCanPlay(this.onCanPlayVideoContainer.bind(this));
|
||||
this.videoContainer.setURLVideo(response.url);
|
||||
this.videoContainer.setFilename(response.filename);
|
||||
}
|
||||
}).catch( (error) => {
|
||||
error_str = error.toString();
|
||||
this.loadingModal.setVisible(false);
|
||||
let input_url = document.createElement('a');
|
||||
input_url.href = url;
|
||||
input_url.innerText = url;
|
||||
let issues_url = document.createElement('a');
|
||||
issues_url.href = 'https://gitea.sergiotarxz.freemyip.com/sergiotarxz/Peertube-dl/issues';
|
||||
issues_url.innerText = 'here';
|
||||
this.popingNotice.setMessage( [ 'The url ', input_url, ' is not supported, the error was: ', error_str , ' if you think this is an error, report it ', issues_url, '.' ]);
|
||||
this.popingNotice.setVisible(true);
|
||||
});
|
||||
}
|
||||
|
||||
onCanPlayVideoContainer() {
|
||||
this.videoContainer.setVisible(true);
|
||||
this.loadingModal.setVisible(false);
|
||||
}
|
||||
|
||||
async queryAPI(url, format) {
|
||||
let request = { url: url };
|
||||
if (format !== undefined)
|
||||
request.format = format;
|
||||
const response = await fetch('/api', {
|
||||
method: 'POST',
|
||||
mode: 'cors',
|
||||
cache: 'no-cache',
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
body: JSON.stringify(request),
|
||||
});
|
||||
return response.json();
|
||||
}
|
||||
|
||||
get formatSelector() {
|
||||
return this.format_selector;
|
||||
}
|
||||
|
||||
get videoContainer() {
|
||||
return this.video_container;
|
||||
}
|
||||
|
||||
get downloadForm() {
|
||||
return this.download_form;
|
||||
}
|
||||
|
||||
get popingNotice() {
|
||||
return this.poping_notice;
|
||||
}
|
||||
|
||||
get loadingModal() {
|
||||
return this.loading_modal;
|
||||
}
|
||||
}
|
||||
|
||||
export { Application };
|
@ -1,10 +0,0 @@
|
||||
"use strict";
|
||||
|
||||
import { Application } from './application.js';
|
||||
|
||||
window.addEventListener('load', (event) => {
|
||||
let application = new Application();
|
||||
application.init();
|
||||
});
|
||||
|
||||
|
@ -1,35 +0,0 @@
|
||||
"use strict";
|
||||
|
||||
class DownloadForm {
|
||||
constructor(callback) {
|
||||
this.query_selector = '#download-form';
|
||||
this.callback = (event) => {
|
||||
event.preventDefault();
|
||||
callback(this.downloadFormUrl.value);
|
||||
};
|
||||
this.addEventListeners();
|
||||
}
|
||||
|
||||
addEventListeners() {
|
||||
this.downloadFormButton.addEventListener('click', this.callback);
|
||||
this.element.addEventListener('submit', this.callback);
|
||||
}
|
||||
|
||||
get downloadFormButton() {
|
||||
return this.element.querySelector('#download-form-button');
|
||||
}
|
||||
|
||||
get downloadFormUrl() {
|
||||
return this.element.querySelector('#download-form-url');
|
||||
}
|
||||
|
||||
get querySelector() {
|
||||
return this.query_selector;
|
||||
}
|
||||
|
||||
get element() {
|
||||
return document.querySelector(this.querySelector);
|
||||
}
|
||||
}
|
||||
|
||||
export { DownloadForm };
|
@ -1,120 +0,0 @@
|
||||
"use strict";
|
||||
|
||||
class FormatSelector {
|
||||
constructor() {
|
||||
this.query_selector = '#modal-format-selector';
|
||||
this.addEventListeners();
|
||||
}
|
||||
|
||||
appendFormat(container, object, is_video, callback) {
|
||||
let a = document.createElement('a');
|
||||
let br = function() { return document.createElement('br') };
|
||||
let inner_text = [];
|
||||
let muted_video = false;
|
||||
if ( is_video ) {
|
||||
if ( object.audioSampleRate === undefined ) {
|
||||
muted_video = true;
|
||||
}
|
||||
inner_text.push('Id: ' + object.id);
|
||||
inner_text.push(br());
|
||||
inner_text.push('Format: ' + object.mimeType);
|
||||
inner_text.push(br());
|
||||
inner_text.push('QualityLabel: ' + object.qualityLabel + "p");
|
||||
inner_text.push(br());
|
||||
inner_text.push('Bitrate: ' + object.bitrate);
|
||||
inner_text.push(br());
|
||||
inner_text.push( ( muted_video) ?
|
||||
"No audio. " :
|
||||
'AudioSampleRate: ' + object.audioSampleRate
|
||||
);
|
||||
} else {
|
||||
inner_text.push('Id: ' + object.id + "\n");
|
||||
inner_text.push(br());
|
||||
inner_text.push('Format: ' + object.mimeType);
|
||||
inner_text.push(br());
|
||||
inner_text.push('AudioSampleRate: ' + object.audioSampleRate);
|
||||
inner_text.push(br());
|
||||
inner_text.push('Bitrate: ' + object.bitrate);
|
||||
}
|
||||
|
||||
a.addEventListener( 'click', (event) => {
|
||||
callback(object.id);
|
||||
});
|
||||
if (muted_video) {
|
||||
let img_muted_video = document.createElement('img');
|
||||
img_muted_video.classList.add('mute_img');
|
||||
img_muted_video.classList.add('scale');
|
||||
img_muted_video.src = 'img/audio_muted.svg';
|
||||
inner_text.push(img_muted_video);
|
||||
}
|
||||
|
||||
for (let text of inner_text) {
|
||||
if (typeof text === "string"
|
||||
|| text instanceof String) {
|
||||
text = document.createTextNode(text);
|
||||
a.appendChild(text);
|
||||
} else if ( text instanceof Node) {
|
||||
a.appendChild(text);
|
||||
} else {
|
||||
throw ('Text is not a instance of Node nor a String');
|
||||
}
|
||||
}
|
||||
|
||||
container.appendChild(a);
|
||||
}
|
||||
|
||||
prepareFormatSelector(title, description, audio_formats, video_formats, callback) {
|
||||
this.titleFormatSelector.innerText = title;
|
||||
this.descriptionFormatSelector.innerText = description;
|
||||
this.videoFormats.innerHTML = '';
|
||||
this.audioFormats.innerHTML = '';
|
||||
for ( let x of audio_formats) {
|
||||
this.appendFormat(this.audioFormats, x, false, callback);
|
||||
}
|
||||
for ( let x of video_formats ) {
|
||||
this.appendFormat(this.videoFormats, x, true, callback);
|
||||
}
|
||||
}
|
||||
|
||||
setVisible(option) {
|
||||
if (option) {
|
||||
this.element.classList.add('active');
|
||||
} else {
|
||||
this.element.classList.remove('active');
|
||||
}
|
||||
}
|
||||
|
||||
addEventListeners() {
|
||||
this.closeFormatSelector.addEventListener('click', (event) => { this.setVisible(false); });
|
||||
}
|
||||
|
||||
get videoFormats() {
|
||||
return this.element.querySelector('.video-formats');
|
||||
}
|
||||
|
||||
get audioFormats() {
|
||||
return this.element.querySelector('.audio-formats');
|
||||
}
|
||||
|
||||
get titleFormatSelector() {
|
||||
return this.element.querySelector('h2');
|
||||
}
|
||||
|
||||
get descriptionFormatSelector() {
|
||||
return this.element.querySelector('p');
|
||||
}
|
||||
|
||||
get closeFormatSelector() {
|
||||
return this.element.querySelector('#close-modal-format-selector');
|
||||
}
|
||||
|
||||
get element() {
|
||||
return document.querySelector(this.querySelector);
|
||||
}
|
||||
|
||||
get querySelector() {
|
||||
return this.query_selector;
|
||||
}
|
||||
}
|
||||
|
||||
export { FormatSelector };
|
@ -1,25 +0,0 @@
|
||||
"use strict";
|
||||
|
||||
class LoadingModal {
|
||||
constructor() {
|
||||
this.query_selector = '#modal-loading';
|
||||
}
|
||||
|
||||
setVisible(option) {
|
||||
if (option) {
|
||||
this.element.classList.add('active');
|
||||
} else {
|
||||
this.element.classList.remove('active');
|
||||
}
|
||||
}
|
||||
|
||||
get element() {
|
||||
return document.querySelector(this.querySelector);
|
||||
}
|
||||
|
||||
get querySelector() {
|
||||
return this.query_selector;
|
||||
}
|
||||
}
|
||||
|
||||
export { LoadingModal };
|
@ -1,56 +0,0 @@
|
||||
"use strict";
|
||||
|
||||
class PopingNotice {
|
||||
constructor() {
|
||||
this.query_selector = '#poping-notice';
|
||||
this.closePopingNotice.addEventListener('click', (event) => {
|
||||
this.setVisible(false);
|
||||
});
|
||||
}
|
||||
|
||||
setVisible(option) {
|
||||
if (option) {
|
||||
this.element.classList.add('active');
|
||||
} else {
|
||||
this.element.classList.remove('active');
|
||||
}
|
||||
}
|
||||
|
||||
setMessage(message) {
|
||||
if (!message instanceof Array)
|
||||
throw 'Message is not instance of Array.';
|
||||
let p = document.createElement('p');
|
||||
for (let node of message) {
|
||||
if (typeof node === "string"
|
||||
|| node instanceof String) {
|
||||
node = document.createTextNode(node);
|
||||
p.appendChild(node);
|
||||
} else if ( node instanceof Node) {
|
||||
p.appendChild(node);
|
||||
} else {
|
||||
throw ('Node is not a instance of Node nor a String');
|
||||
}
|
||||
}
|
||||
this.popingNoticeContent.innerHTML = '';
|
||||
this.popingNoticeContent.appendChild(p);
|
||||
|
||||
}
|
||||
|
||||
get querySelector() {
|
||||
return this.query_selector;
|
||||
}
|
||||
|
||||
get element() {
|
||||
return document.querySelector(this.querySelector);
|
||||
}
|
||||
|
||||
get popingNoticeContent() {
|
||||
return this.element.querySelector('#poping-notice-content');
|
||||
}
|
||||
|
||||
get closePopingNotice() {
|
||||
return this.element.querySelector('#close-poping-notice');
|
||||
}
|
||||
}
|
||||
|
||||
export { PopingNotice };
|
@ -1,113 +0,0 @@
|
||||
"use strict";
|
||||
|
||||
class VideoContainer {
|
||||
constructor() {
|
||||
this.query_selector = '#modal-video-container';
|
||||
this.addEventListeners();
|
||||
}
|
||||
|
||||
setVisible(option) {
|
||||
if (option) {
|
||||
this.element.classList.add('active');
|
||||
} else {
|
||||
this.video.pause();
|
||||
this.element.classList.remove('active');
|
||||
this.downloadVideoPrepare.classList.add('active');
|
||||
this.downloadVideoLoading.classList.remove('active');
|
||||
this.downloadVideo.classList.remove('active');
|
||||
}
|
||||
}
|
||||
|
||||
addEventListeners() {
|
||||
this.downloadVideoPrepare.addEventListener('click', this.downloadPrepareHandler.bind(this));
|
||||
this.closeAndResetVideoContainer.addEventListener('click', (event) => {
|
||||
this.setVisible(false);
|
||||
});
|
||||
}
|
||||
|
||||
downloadPrepareHandler(event) {
|
||||
this.downloadVideoPrepare.classList.remove('active');
|
||||
this.downloadVideoLoading.classList.add('active');
|
||||
this.generateBlobVideo(this.URLVideo).then( blob => {
|
||||
this.downloadVideo.href = URL.createObjectURL(blob);
|
||||
this.downloadVideo.download = this.filename;
|
||||
this.downloadVideoLoading.classList.remove('active');
|
||||
this.downloadVideo.classList.add('active');
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
async generateBlobVideo(url) {
|
||||
const blob = await fetch(url, { mode: 'cors', })
|
||||
.then(res => res.blob())
|
||||
.catch( err => this.generateBlobVideoByProxy(url) );
|
||||
return blob;
|
||||
}
|
||||
|
||||
async generateBlobVideoByProxy(url) {
|
||||
const blob = await fetch( '/proxy_to_get', {
|
||||
method: 'POST',
|
||||
mode: 'cors',
|
||||
cache: 'no-cache',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: JSON.stringify({url: url}),
|
||||
}
|
||||
).then(res => res.blob());
|
||||
return blob;
|
||||
}
|
||||
|
||||
onCanPlay(callback) {
|
||||
video.addEventListener('canplay', (event) => {
|
||||
callback();
|
||||
});
|
||||
}
|
||||
|
||||
setURLVideo(url) {
|
||||
this.url_video = url;
|
||||
video.src = url;
|
||||
}
|
||||
|
||||
setFilename(filename) {
|
||||
this.filename = filename;
|
||||
}
|
||||
|
||||
get closeAndResetVideoContainer() {
|
||||
return this.element.querySelector('#close-and-reset-video-container');
|
||||
}
|
||||
|
||||
get downloadVideo() {
|
||||
return this.element.querySelector('#download-video');
|
||||
}
|
||||
|
||||
get URLVideo() {
|
||||
return this.url_video;
|
||||
}
|
||||
|
||||
get closeAndResetVideoContainer() {
|
||||
return this.element.querySelector('#close-and-reset-video-container');
|
||||
}
|
||||
|
||||
get downloadVideoLoading() {
|
||||
return this.element.querySelector('#download-video-loading');
|
||||
}
|
||||
|
||||
get downloadVideoPrepare() {
|
||||
return this.element.querySelector('#download-video-prepare');
|
||||
}
|
||||
|
||||
get video() {
|
||||
return this.element.querySelector('#video');
|
||||
}
|
||||
|
||||
get element() {
|
||||
return document.querySelector(this.querySelector);
|
||||
}
|
||||
|
||||
get querySelector() {
|
||||
return this.query_selector;
|
||||
}
|
||||
}
|
||||
|
||||
export { VideoContainer };
|
@ -1,10 +0,0 @@
|
||||
const path = require('path');
|
||||
|
||||
module.exports = {
|
||||
entry: './src/index.js',
|
||||
devtool: 'source-map',
|
||||
output: {
|
||||
filename: 'peertube-dl-web.js',
|
||||
path: path.resolve(__dirname, 'dist/js'),
|
||||
},
|
||||
};
|
327
themes/new_look_default/public/dist/css/index.css
vendored
327
themes/new_look_default/public/dist/css/index.css
vendored
@ -1,327 +0,0 @@
|
||||
body {
|
||||
height: 98vh;
|
||||
|
||||
display: flex;
|
||||
flex-flow: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
||||
background-color: #111827;
|
||||
}
|
||||
|
||||
.application-container {
|
||||
display: flex;
|
||||
flex-flow: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
||||
border-radius: 0.3rem;
|
||||
|
||||
background-color: #1f2937;
|
||||
|
||||
padding: 1.5rem 3rem 1.5rem 3rem;
|
||||
}
|
||||
|
||||
.application-container form {
|
||||
display: flex;
|
||||
flex-flow: column;
|
||||
justify-content: center;
|
||||
|
||||
width: 100%;
|
||||
padding: 1rem;
|
||||
}
|
||||
|
||||
.application-container h2 {
|
||||
color: #ffffff;
|
||||
font-weight: 400;
|
||||
font-size: 1.6rem;
|
||||
}
|
||||
|
||||
.application-container input {
|
||||
padding: 1rem;
|
||||
|
||||
color: #ffffff;
|
||||
background-color: #374151;
|
||||
|
||||
border-radius: 0.2rem;
|
||||
border: 1px solid transparent;
|
||||
}
|
||||
|
||||
.application-container button {
|
||||
margin-top: 1rem;
|
||||
|
||||
color: #ffffff;
|
||||
font-weight: bold;
|
||||
|
||||
background-color: #059669;
|
||||
|
||||
border-radius: 0.2rem;
|
||||
border: 1px solid transparent;
|
||||
|
||||
padding: 0.5rem 1rem 0.5rem 1rem;
|
||||
}
|
||||
|
||||
.application-container button:hover,.application-container button:focus {
|
||||
background-color: #059;
|
||||
}
|
||||
|
||||
.application-container button,
|
||||
.application-container input {
|
||||
font-size: 0.9rem;
|
||||
}
|
||||
|
||||
.application-container.active {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
#poping-notice-content a {
|
||||
text-decoration: none;
|
||||
color: #10b981;
|
||||
}
|
||||
|
||||
#poping-notice-content a:hover,#poping-notice-content a:focus {
|
||||
color: #0ae;
|
||||
}
|
||||
|
||||
#poping-notice-container-bar {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
#close-poping-notice {
|
||||
background-color: #059669;
|
||||
padding: 0.5rem 5rem 0.5rem 5rem;
|
||||
border-radius: 0.3rem;
|
||||
text-decoration: none;
|
||||
font-weight: bolder;
|
||||
color: white;
|
||||
}
|
||||
|
||||
#close-poping-notice:hover,#close-poping-notice:focus {
|
||||
background-color: #059;
|
||||
}
|
||||
|
||||
.modal {
|
||||
position: fixed;
|
||||
display: none;
|
||||
color: white;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
}
|
||||
|
||||
#poping-notice {
|
||||
padding: 3rem;
|
||||
border-radius: 0.3rem;
|
||||
background-color: #374151;
|
||||
color: white;
|
||||
overflow-y: scroll;
|
||||
width: 94%;
|
||||
max-height: 70%;
|
||||
flex-direction: column;
|
||||
scrollbar-width: none;
|
||||
}
|
||||
|
||||
#modal-video-container,#modal-format-selector {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
flex-flow: column;
|
||||
align-items: center;
|
||||
background-color: #111827;
|
||||
}
|
||||
|
||||
#modal-format-selector h2 {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
#modal-format-selector p {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.video-container-bar {
|
||||
width: 99%;
|
||||
height: 2rem;
|
||||
padding-top: 1rem;
|
||||
padding-bottom: 1rem;
|
||||
display: flex;
|
||||
justify-content: end;
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
.video-container-bar a {
|
||||
padding: 1rem;
|
||||
margin-right: 1rem;
|
||||
border-radius: 0.3rem;
|
||||
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
||||
background-color: #dc2626;
|
||||
}
|
||||
|
||||
.video-container-bar a:hover,.video-container-bar a:focus {
|
||||
color: white;
|
||||
background-color: grey;
|
||||
}
|
||||
|
||||
|
||||
#modal-video-container > #block {
|
||||
display: flex;
|
||||
flex-flow: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
#download-video-container {
|
||||
padding: 2rem;
|
||||
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.button-download {
|
||||
display: none;
|
||||
border-radius: 0.3rem;
|
||||
background-color: #059669;
|
||||
text-decoration: none;
|
||||
color: white;
|
||||
user-select: none;
|
||||
cursor: pointer;
|
||||
height: 30px;
|
||||
padding: 0 2rem;
|
||||
}
|
||||
|
||||
.button-download:hover,.button-download:focus {
|
||||
background-color: #059;
|
||||
}
|
||||
|
||||
.button-download embed {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
#download-video-loading.active {
|
||||
height: 2rem;
|
||||
}
|
||||
|
||||
#download-video-container .button-download.active {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
#modal-loading {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.modal {
|
||||
--tw-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1),
|
||||
0 4px 6px -2px rgba(0, 0, 0, 0.05);
|
||||
box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000),
|
||||
var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow);
|
||||
overflow-y: scroll;
|
||||
}
|
||||
|
||||
#poping-notice.active {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.modal.active {
|
||||
display: flex;
|
||||
scrollbar-width: none;
|
||||
}
|
||||
|
||||
.modal.active.active::-webkit-scrollbar {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#modal-loading {
|
||||
display: none;
|
||||
position: fixed;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
transform: translate(-50%, -50%);
|
||||
border: black 1px solid;
|
||||
justify-content: right;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
#modal-loading.active {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
#modal-loading embed {
|
||||
width: 10%;
|
||||
}
|
||||
|
||||
#video {
|
||||
width: 100%;
|
||||
max-width: 636px;
|
||||
}
|
||||
|
||||
#video-container {
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.format-list > div {
|
||||
display: grid;
|
||||
grid-column-gap: 10px;
|
||||
grid-row-gap: 10px;
|
||||
grid-template-areas: "a";
|
||||
grid-auto-columns: 99%;
|
||||
margin: 1rem;
|
||||
}
|
||||
|
||||
.format-list > div > a {
|
||||
border: 1px solid black;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: 1.5rem;
|
||||
padding-right: 5%;
|
||||
padding-left: 5%;
|
||||
text-decoration: none;
|
||||
border-radius: 0.5rem;
|
||||
background-color: #059669;
|
||||
overflow-wrap: anywhere;
|
||||
}
|
||||
|
||||
.format-list > div > a:focus,.format-list > div > a:hover {
|
||||
background-color: #059;
|
||||
}
|
||||
|
||||
.format-list > div > a:after {
|
||||
padding-bottom: 100%;
|
||||
display: block;
|
||||
content: "";
|
||||
}
|
||||
|
||||
.scale {
|
||||
height: 1em;
|
||||
width; 1em;
|
||||
}
|
||||
|
||||
@media (min-width: 600px) {
|
||||
.format-list > div {
|
||||
grid-template-areas: "a a";
|
||||
grid-auto-columns: 49.75%;
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 805px) {
|
||||
.format-list > div {
|
||||
grid-template-areas: "a a a";
|
||||
grid-auto-columns: 33%;
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 812px) {
|
||||
#poping-notice {
|
||||
width: 40%;
|
||||
}
|
||||
}
|
@ -1,18 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 22 22">
|
||||
<g transform="matrix(.13811 0 0 .13811 4.964 5.832)" fill-opacity=".8">
|
||||
<g transform="matrix(6.5167 0 0 6.5167-28.01-34.23)">
|
||||
<g transform="matrix(1.17633 0 0 1.17633 1 1.589)" stroke-opacity=".85" fill="#000" stroke="none" fill-opacity="0" stroke-width=".73">
|
||||
<path d="m11.243 12.993c-.192 0-.384-.073-.53-.22-.293-.293-.293-.768 0-1.061 2.047-2.047 2.047-5.378 0-7.425-.293-.293-.293-.768 0-1.061.293-.293.768-.293 1.061 0 1.275 1.275 1.977 2.97 1.977 4.773 0 1.803-.702 3.498-1.977 4.773-.146.146-.338.22-.53.22z"/>
|
||||
<path d="m8.578 11.578c-.192 0-.384-.073-.53-.22-.293-.293-.293-.768 0-1.061 1.267-1.267 1.267-3.329 0-4.596-.293-.293-.293-.768 0-1.061.293-.293.768-.293 1.061 0 1.852 1.852 1.852 4.865 0 6.718-.146.146-.338.22-.53.22z"/>
|
||||
</g>
|
||||
<g transform="translate(16 4)">
|
||||
<g fill="#f2f2f2" fill-opacity="0">
|
||||
<path d="m-1.773 12.874c-.226 0-.452-.086-.623-.259-.345-.345-.345-.903 0-1.248 2.408-2.408 2.408-6.326 0-8.734-.345-.345-.345-.903 0-1.248.345-.345.903-.345 1.248 0 1.5 1.5 2.326 3.494 2.326 5.615 0 2.121-.826 4.115-2.326 5.615-.172.172-.398.259-.623.259z"/>
|
||||
<path d="m-4.908 11.209c-.226 0-.452-.086-.623-.259-.345-.345-.345-.903 0-1.248 1.49-1.49 1.49-3.916 0-5.406-.345-.345-.345-.903 0-1.248.345-.345.903-.345 1.248 0 2.179 2.179 2.179 5.723 0 7.903-.172.172-.398.259-.623.259z"/>
|
||||
</g>
|
||||
<path d="m-7.353 15.235c-.153 0-.303-.06-.416-.172l-4.534-4.534h-2.109c-.325 0-.588-.263-.588-.588v-5.882c0-.325.263-.588.588-.588h2.109l4.534-4.534c.168-.168.421-.219.641-.127.22.092.363.306.363.543v15.292c0 .238-.144.453-.363.543-.073.031-.149.045-.225.045" fill="#4d4d4d" fill-opacity="1"/>
|
||||
</g>
|
||||
</g>
|
||||
<path d="m14.75 9.674v1.326h-1.326l-1.674-1.674-1.674 1.674h-1.326v-1.326l1.674-1.674-1.674-1.674v-1.326h1.326l1.674 1.674 1.674-1.674h1.326v1.326l-1.674 1.674 1.674 1.674" fill="#4d4d4d" fill-opacity="1" transform="matrix(8.22579 0 0 8.22579-32.543-28.351)"/>
|
||||
</g>
|
||||
</svg>
|
Before Width: | Height: | Size: 2.1 KiB |
Binary file not shown.
Before Width: | Height: | Size: 66 KiB |
Binary file not shown.
Before Width: | Height: | Size: 3.6 KiB |
76
themes/new_look_default/public/dist/index.html
vendored
76
themes/new_look_default/public/dist/index.html
vendored
@ -1,76 +0,0 @@
|
||||
<html>
|
||||
<head>
|
||||
<script src="js/peertube-dl-web.js?v=1"></script>
|
||||
<link rel="stylesheet" href="css/index.css?v=4"></script>
|
||||
<link rel="icon" type="image/png" href="img/peertube-dl-logo.png"/>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Peertube-dl Web</title>
|
||||
<meta name="description" content="Webpage intended to download videos from various webpages for fair use."/>
|
||||
<meta property="og:type" content="website" />
|
||||
<meta property="og:title" content="Peertube-dl Web"/>
|
||||
<meta property="og:site_name" content="Peertube-dl"/>
|
||||
<meta property="og:description" content="Webpage intended to download videos from various webpages for fair use."/>
|
||||
<meta property="og:image" content="./img/peertube-dl-logo-fullsize.png"/>
|
||||
</head>
|
||||
<body>
|
||||
<div class="application-container">
|
||||
<h2>Peertube-dl Web Application</h2>
|
||||
<form id="download-form">
|
||||
<input class="block" type="text" id="download-form-url" placeholder="Introduce the url you want to download."/>
|
||||
<button class="block" id="download-form-button" >Fetch from api</button>
|
||||
</form>
|
||||
</div>
|
||||
<div id="modal-format-selector" class="modal">
|
||||
<div class="video-container-bar">
|
||||
<a id="close-modal-format-selector">x</a>
|
||||
</div>
|
||||
<h2>Example video</h2>
|
||||
<p>Example description</p>
|
||||
<div class="format-list">
|
||||
<h3>Video Formats.</h3>
|
||||
<div class="video-formats">
|
||||
</div>
|
||||
<h3>Audio Formats.</h3>
|
||||
<div class="audio-formats">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="modal-loading">
|
||||
<embed src="img/spinner.svg"/>
|
||||
</div>
|
||||
<div id="modal-video-container" class="modal">
|
||||
<div class="video-container-bar">
|
||||
<a id="close-and-reset-video-container">x</a>
|
||||
</div>
|
||||
<div id="video-container">
|
||||
<div class="block">
|
||||
<video id="video" controls="controls"></video>
|
||||
</div>
|
||||
<div id="download-video-container" class="block">
|
||||
<a id="download-video-prepare" class="button-download active">Prepare download</a>
|
||||
<a id="download-video-loading" class="button-download"><embed src="img/spinner.svg"/></a>
|
||||
<a id="download-video" class="button-download">Download</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="poping-notice" class="modal">
|
||||
<div id="poping-notice-content">
|
||||
<p>This webpage is free as in freedom software, it is offered to you with the hope it will be useful, but without any warranty,
|
||||
you can find the source code at <a href="https://gitea.sergiotarxz.freemyip.com/sergiotarxz/Peertube-dl">my gitea</a> with docs to setup your own
|
||||
webpage like this, this software is licensed under the AGPLv3 license which means you MUST convey the source code in a human readable form
|
||||
if you distribute this software or use it as an service to users of service or distributees.<p>
|
||||
|
||||
<p>I hope that if you find a non supported url which should be supported, a bug, or a feature you would like this webpage to have you file an issue in
|
||||
<a href="https://gitea.sergiotarxz.freemyip.com/sergiotarxz/Peertube-dl/issues">https://gitea.sergiotarxz.freemyip.com/sergiotarxz/Peertube-dl/issues</a>
|
||||
to help this software improve since I find tracking users a pretty bad way to discover bugs and potential good features.</p>
|
||||
|
||||
<p>This webpage may load third party resources depending on the url you give to it which may put cookies in your browser, you are
|
||||
encouraged to frecuently delete your browser cookies to avoid those third parties tracking you on internet, Firefox offers you an
|
||||
option to delete cookies as soon as you close the browser which may be a good idea to enable in the orwellian internet of today.</p>
|
||||
</div>
|
||||
<div id="poping-notice-container-bar">
|
||||
<a id="close-poping-notice" href="#">X</a>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
@ -1,13 +0,0 @@
|
||||
{
|
||||
"name": "default-theme",
|
||||
"version": "1.0.0",
|
||||
"private": true,
|
||||
"license": "MIT",
|
||||
"scripts": {
|
||||
"build": "webpack"
|
||||
},
|
||||
"dependencies": {
|
||||
"webpack": "^5.15.0",
|
||||
"webpack-cli": "^4.3.1"
|
||||
}
|
||||
}
|
@ -1,106 +0,0 @@
|
||||
"use strict";
|
||||
|
||||
import { PopingNotice } from './view/poping_notice.js';
|
||||
import { DownloadForm } from './view/download_form.js';
|
||||
import { LoadingModal } from './view/loading_modal.js';
|
||||
import { VideoContainer } from './view/video_container.js';
|
||||
import { FormatSelector } from './view/format_selector.js';
|
||||
|
||||
class Application {
|
||||
constructor() {
|
||||
this.poping_notice = new PopingNotice();
|
||||
this.download_form = new DownloadForm(this.onDownloadFormGot.bind(this));
|
||||
this.loading_modal = new LoadingModal();
|
||||
this.video_container = new VideoContainer();
|
||||
this.format_selector = new FormatSelector();
|
||||
}
|
||||
|
||||
init() {
|
||||
this.popingNotice.setVisible(true);
|
||||
}
|
||||
|
||||
onDownloadFormGot(url) {
|
||||
this.dispatchURL(url);
|
||||
}
|
||||
|
||||
dispatchURL(url, format) {
|
||||
this.loadingModal.setVisible(true);
|
||||
let error_str;
|
||||
let success = this.queryAPI(url, format).then( (response) => {
|
||||
if ( response.options !== undefined && response.options.list_formats !== undefined && response.options.list_formats ) {
|
||||
if ( response.formats === undefined
|
||||
|| response.formats.audio_formats === undefined
|
||||
|| response.formats.video_formats === undefined ) {
|
||||
throw 'Format object is not valid.';
|
||||
}
|
||||
this.formatSelector.prepareFormatSelector(
|
||||
response.title, response.description,
|
||||
response.formats.audio_formats, response.formats.video_formats,
|
||||
( id ) => {
|
||||
this.loadingModal.setVisible(true);
|
||||
this.dispatchURL(url, id);
|
||||
});
|
||||
this.formatSelector.setVisible(true);
|
||||
this.loadingModal.setVisible(false);
|
||||
} else {
|
||||
this.videoContainer.onCanPlay(this.onCanPlayVideoContainer.bind(this));
|
||||
this.videoContainer.setURLVideo(response.url);
|
||||
this.videoContainer.setFilename(response.filename);
|
||||
}
|
||||
}).catch( (error) => {
|
||||
error_str = error.toString();
|
||||
this.loadingModal.setVisible(false);
|
||||
let input_url = document.createElement('a');
|
||||
input_url.href = url;
|
||||
input_url.innerText = url;
|
||||
let issues_url = document.createElement('a');
|
||||
issues_url.href = 'https://gitea.sergiotarxz.freemyip.com/sergiotarxz/Peertube-dl/issues';
|
||||
issues_url.innerText = 'here';
|
||||
this.popingNotice.setMessage( [ 'The url ', input_url, ' is not supported, the error was: ', error_str , ' if you think this is an error, report it ', issues_url, '.' ]);
|
||||
this.popingNotice.setVisible(true);
|
||||
});
|
||||
}
|
||||
|
||||
onCanPlayVideoContainer() {
|
||||
this.videoContainer.setVisible(true);
|
||||
this.loadingModal.setVisible(false);
|
||||
}
|
||||
|
||||
async queryAPI(url, format) {
|
||||
let request = { url: url };
|
||||
if (format !== undefined)
|
||||
request.format = format;
|
||||
const response = await fetch('/api', {
|
||||
method: 'POST',
|
||||
mode: 'cors',
|
||||
cache: 'no-cache',
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
body: JSON.stringify(request),
|
||||
});
|
||||
return response.json();
|
||||
}
|
||||
|
||||
get formatSelector() {
|
||||
return this.format_selector;
|
||||
}
|
||||
|
||||
get videoContainer() {
|
||||
return this.video_container;
|
||||
}
|
||||
|
||||
get downloadForm() {
|
||||
return this.download_form;
|
||||
}
|
||||
|
||||
get popingNotice() {
|
||||
return this.poping_notice;
|
||||
}
|
||||
|
||||
get loadingModal() {
|
||||
return this.loading_modal;
|
||||
}
|
||||
}
|
||||
|
||||
export { Application };
|
@ -1,10 +0,0 @@
|
||||
"use strict";
|
||||
|
||||
import { Application } from './application.js';
|
||||
|
||||
window.addEventListener('load', (event) => {
|
||||
let application = new Application();
|
||||
application.init();
|
||||
});
|
||||
|
||||
|
@ -1,35 +0,0 @@
|
||||
"use strict";
|
||||
|
||||
class DownloadForm {
|
||||
constructor(callback) {
|
||||
this.query_selector = '#download-form';
|
||||
this.callback = (event) => {
|
||||
event.preventDefault();
|
||||
callback(this.downloadFormUrl.value);
|
||||
};
|
||||
this.addEventListeners();
|
||||
}
|
||||
|
||||
addEventListeners() {
|
||||
this.downloadFormButton.addEventListener('click', this.callback);
|
||||
this.element.addEventListener('submit', this.callback);
|
||||
}
|
||||
|
||||
get downloadFormButton() {
|
||||
return this.element.querySelector('#download-form-button');
|
||||
}
|
||||
|
||||
get downloadFormUrl() {
|
||||
return this.element.querySelector('#download-form-url');
|
||||
}
|
||||
|
||||
get querySelector() {
|
||||
return this.query_selector;
|
||||
}
|
||||
|
||||
get element() {
|
||||
return document.querySelector(this.querySelector);
|
||||
}
|
||||
}
|
||||
|
||||
export { DownloadForm };
|
@ -1,120 +0,0 @@
|
||||
"use strict";
|
||||
|
||||
class FormatSelector {
|
||||
constructor() {
|
||||
this.query_selector = '#modal-format-selector';
|
||||
this.addEventListeners();
|
||||
}
|
||||
|
||||
appendFormat(container, object, is_video, callback) {
|
||||
let a = document.createElement('a');
|
||||
let br = function() { return document.createElement('br') };
|
||||
let inner_text = [];
|
||||
let muted_video = false;
|
||||
if ( is_video ) {
|
||||
if ( object.audioSampleRate === undefined ) {
|
||||
muted_video = true;
|
||||
}
|
||||
inner_text.push('Id: ' + object.id);
|
||||
inner_text.push(br());
|
||||
inner_text.push('Format: ' + object.mimeType);
|
||||
inner_text.push(br());
|
||||
inner_text.push('QualityLabel: ' + object.qualityLabel + "p");
|
||||
inner_text.push(br());
|
||||
inner_text.push('Bitrate: ' + object.bitrate);
|
||||
inner_text.push(br());
|
||||
inner_text.push( ( muted_video) ?
|
||||
"No audio. " :
|
||||
'AudioSampleRate: ' + object.audioSampleRate
|
||||
);
|
||||
} else {
|
||||
inner_text.push('Id: ' + object.id + "\n");
|
||||
inner_text.push(br());
|
||||
inner_text.push('Format: ' + object.mimeType);
|
||||
inner_text.push(br());
|
||||
inner_text.push('AudioSampleRate: ' + object.audioSampleRate);
|
||||
inner_text.push(br());
|
||||
inner_text.push('Bitrate: ' + object.bitrate);
|
||||
}
|
||||
|
||||
a.addEventListener( 'click', (event) => {
|
||||
callback(object.id);
|
||||
});
|
||||
if (muted_video) {
|
||||
let img_muted_video = document.createElement('img');
|
||||
img_muted_video.classList.add('mute_img');
|
||||
img_muted_video.classList.add('scale');
|
||||
img_muted_video.src = 'img/audio_muted.svg';
|
||||
inner_text.push(img_muted_video);
|
||||
}
|
||||
|
||||
for (let text of inner_text) {
|
||||
if (typeof text === "string"
|
||||
|| text instanceof String) {
|
||||
text = document.createTextNode(text);
|
||||
a.appendChild(text);
|
||||
} else if ( text instanceof Node) {
|
||||
a.appendChild(text);
|
||||
} else {
|
||||
throw ('Text is not a instance of Node nor a String');
|
||||
}
|
||||
}
|
||||
|
||||
container.appendChild(a);
|
||||
}
|
||||
|
||||
prepareFormatSelector(title, description, audio_formats, video_formats, callback) {
|
||||
this.titleFormatSelector.innerText = title;
|
||||
this.descriptionFormatSelector.innerText = description;
|
||||
this.videoFormats.innerHTML = '';
|
||||
this.audioFormats.innerHTML = '';
|
||||
for ( let x of audio_formats) {
|
||||
this.appendFormat(this.audioFormats, x, false, callback);
|
||||
}
|
||||
for ( let x of video_formats ) {
|
||||
this.appendFormat(this.videoFormats, x, true, callback);
|
||||
}
|
||||
}
|
||||
|
||||
setVisible(option) {
|
||||
if (option) {
|
||||
this.element.classList.add('active');
|
||||
} else {
|
||||
this.element.classList.remove('active');
|
||||
}
|
||||
}
|
||||
|
||||
addEventListeners() {
|
||||
this.closeFormatSelector.addEventListener('click', (event) => { this.setVisible(false); });
|
||||
}
|
||||
|
||||
get videoFormats() {
|
||||
return this.element.querySelector('.video-formats');
|
||||
}
|
||||
|
||||
get audioFormats() {
|
||||
return this.element.querySelector('.audio-formats');
|
||||
}
|
||||
|
||||
get titleFormatSelector() {
|
||||
return this.element.querySelector('h2');
|
||||
}
|
||||
|
||||
get descriptionFormatSelector() {
|
||||
return this.element.querySelector('p');
|
||||
}
|
||||
|
||||
get closeFormatSelector() {
|
||||
return this.element.querySelector('#close-modal-format-selector');
|
||||
}
|
||||
|
||||
get element() {
|
||||
return document.querySelector(this.querySelector);
|
||||
}
|
||||
|
||||
get querySelector() {
|
||||
return this.query_selector;
|
||||
}
|
||||
}
|
||||
|
||||
export { FormatSelector };
|
@ -1,25 +0,0 @@
|
||||
"use strict";
|
||||
|
||||
class LoadingModal {
|
||||
constructor() {
|
||||
this.query_selector = '#modal-loading';
|
||||
}
|
||||
|
||||
setVisible(option) {
|
||||
if (option) {
|
||||
this.element.classList.add('active');
|
||||
} else {
|
||||
this.element.classList.remove('active');
|
||||
}
|
||||
}
|
||||
|
||||
get element() {
|
||||
return document.querySelector(this.querySelector);
|
||||
}
|
||||
|
||||
get querySelector() {
|
||||
return this.query_selector;
|
||||
}
|
||||
}
|
||||
|
||||
export { LoadingModal };
|
@ -1,56 +0,0 @@
|
||||
"use strict";
|
||||
|
||||
class PopingNotice {
|
||||
constructor() {
|
||||
this.query_selector = '#poping-notice';
|
||||
this.closePopingNotice.addEventListener('click', (event) => {
|
||||
this.setVisible(false);
|
||||
});
|
||||
}
|
||||
|
||||
setVisible(option) {
|
||||
if (option) {
|
||||
this.element.classList.add('active');
|
||||
} else {
|
||||
this.element.classList.remove('active');
|
||||
}
|
||||
}
|
||||
|
||||
setMessage(message) {
|
||||
if (!message instanceof Array)
|
||||
throw 'Message is not instance of Array.';
|
||||
let p = document.createElement('p');
|
||||
for (let node of message) {
|
||||
if (typeof node === "string"
|
||||
|| node instanceof String) {
|
||||
node = document.createTextNode(node);
|
||||
p.appendChild(node);
|
||||
} else if ( node instanceof Node) {
|
||||
p.appendChild(node);
|
||||
} else {
|
||||
throw ('Node is not a instance of Node nor a String');
|
||||
}
|
||||
}
|
||||
this.popingNoticeContent.innerHTML = '';
|
||||
this.popingNoticeContent.appendChild(p);
|
||||
|
||||
}
|
||||
|
||||
get querySelector() {
|
||||
return this.query_selector;
|
||||
}
|
||||
|
||||
get element() {
|
||||
return document.querySelector(this.querySelector);
|
||||
}
|
||||
|
||||
get popingNoticeContent() {
|
||||
return this.element.querySelector('#poping-notice-content');
|
||||
}
|
||||
|
||||
get closePopingNotice() {
|
||||
return this.element.querySelector('#close-poping-notice');
|
||||
}
|
||||
}
|
||||
|
||||
export { PopingNotice };
|
@ -1,113 +0,0 @@
|
||||
"use strict";
|
||||
|
||||
class VideoContainer {
|
||||
constructor() {
|
||||
this.query_selector = '#modal-video-container';
|
||||
this.addEventListeners();
|
||||
}
|
||||
|
||||
setVisible(option) {
|
||||
if (option) {
|
||||
this.element.classList.add('active');
|
||||
} else {
|
||||
this.video.pause();
|
||||
this.element.classList.remove('active');
|
||||
this.downloadVideoPrepare.classList.add('active');
|
||||
this.downloadVideoLoading.classList.remove('active');
|
||||
this.downloadVideo.classList.remove('active');
|
||||
}
|
||||
}
|
||||
|
||||
addEventListeners() {
|
||||
this.downloadVideoPrepare.addEventListener('click', this.downloadPrepareHandler.bind(this));
|
||||
this.closeAndResetVideoContainer.addEventListener('click', (event) => {
|
||||
this.setVisible(false);
|
||||
});
|
||||
}
|
||||
|
||||
downloadPrepareHandler(event) {
|
||||
this.downloadVideoPrepare.classList.remove('active');
|
||||
this.downloadVideoLoading.classList.add('active');
|
||||
this.generateBlobVideo(this.URLVideo).then( blob => {
|
||||
this.downloadVideo.href = URL.createObjectURL(blob);
|
||||
this.downloadVideo.download = this.filename;
|
||||
this.downloadVideoLoading.classList.remove('active');
|
||||
this.downloadVideo.classList.add('active');
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
async generateBlobVideo(url) {
|
||||
const blob = await fetch(url, { mode: 'cors', })
|
||||
.then(res => res.blob())
|
||||
.catch( err => this.generateBlobVideoByProxy(url) );
|
||||
return blob;
|
||||
}
|
||||
|
||||
async generateBlobVideoByProxy(url) {
|
||||
const blob = await fetch( '/proxy_to_get', {
|
||||
method: 'POST',
|
||||
mode: 'cors',
|
||||
cache: 'no-cache',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: JSON.stringify({url: url}),
|
||||
}
|
||||
).then(res => res.blob());
|
||||
return blob;
|
||||
}
|
||||
|
||||
onCanPlay(callback) {
|
||||
video.addEventListener('canplay', (event) => {
|
||||
callback();
|
||||
});
|
||||
}
|
||||
|
||||
setURLVideo(url) {
|
||||
this.url_video = url;
|
||||
video.src = url;
|
||||
}
|
||||
|
||||
setFilename(filename) {
|
||||
this.filename = filename;
|
||||
}
|
||||
|
||||
get closeAndResetVideoContainer() {
|
||||
return this.element.querySelector('#close-and-reset-video-container');
|
||||
}
|
||||
|
||||
get downloadVideo() {
|
||||
return this.element.querySelector('#download-video');
|
||||
}
|
||||
|
||||
get URLVideo() {
|
||||
return this.url_video;
|
||||
}
|
||||
|
||||
get closeAndResetVideoContainer() {
|
||||
return this.element.querySelector('#close-and-reset-video-container');
|
||||
}
|
||||
|
||||
get downloadVideoLoading() {
|
||||
return this.element.querySelector('#download-video-loading');
|
||||
}
|
||||
|
||||
get downloadVideoPrepare() {
|
||||
return this.element.querySelector('#download-video-prepare');
|
||||
}
|
||||
|
||||
get video() {
|
||||
return this.element.querySelector('#video');
|
||||
}
|
||||
|
||||
get element() {
|
||||
return document.querySelector(this.querySelector);
|
||||
}
|
||||
|
||||
get querySelector() {
|
||||
return this.query_selector;
|
||||
}
|
||||
}
|
||||
|
||||
export { VideoContainer };
|
@ -1,10 +0,0 @@
|
||||
const path = require('path');
|
||||
|
||||
module.exports = {
|
||||
entry: './src/index.js',
|
||||
devtool: 'source-map',
|
||||
output: {
|
||||
filename: 'peertube-dl-web.js',
|
||||
path: path.resolve(__dirname, 'dist/js'),
|
||||
},
|
||||
};
|
Loading…
Reference in New Issue
Block a user