diff --git a/MANIFEST b/MANIFEST index ae192bb..2162982 100644 --- a/MANIFEST +++ b/MANIFEST @@ -1,6 +1,7 @@ .proverc AUTHORS bin/peertube-dl +bin/peertube-dl-web.pl cpanfile lib/Peertube/DL/Downloaders.pm lib/Peertube/DL/URLHandler.pm @@ -9,6 +10,9 @@ lib/Peertube/DL/Utils.pm LICENSE Makefile.PL MANIFEST This list of files +public/css/index.css +public/index.html +public/js/peertube-dl-web.js README.md t/00-use_ok.t t/downloaders/animeflv_example_response.html diff --git a/bin/peertube-dl-web.pl b/bin/peertube-dl-web.pl new file mode 100644 index 0000000..12a9913 --- /dev/null +++ b/bin/peertube-dl-web.pl @@ -0,0 +1,36 @@ +use Mojolicious::Lite -signatures; +use Peertube::DL::URLHandler; + +get '/' => sub { + my $c = shift; + return $c->redirect_to('index.html'); +}; + +post '/api' => sub { + my $c = shift; + my $url = $c->req->json->{url} + // ( return $c->render( text => 'Malformed request due missing url json parameter.', status => 400 ) ); + my $render_returned; + eval { $render_returned = $c->render( json => Peertube::DL::URLHandler::getDownloadDataFromURL($url) ); }; + if ($@) { + return $c->render( text => $@, status => 500 ); + } + return $render_returned; +}; + +post '/proxy_to_get' => sub { + my $c = shift; + my $url = $c->req->json->{url} + // ( return $c->render( text => 'Malformed request due missing url json parameter.', status => 400 ) ); + die "Not supported url" unless $url =~ s/^https:\/\///r =~ /^storage\.googleapis\.com/; + my $ua = Peertube::DL::URLHandler::generateUA(); + return $c->render( + data => $ua->get($url)->decoded_content, + format => 'bin' + ); +}; + +push @{ app->renderer->paths }, ('./templates'); +push @{ app->static->paths }, ('./public'); +app->start; + diff --git a/public/css/index.css b/public/css/index.css new file mode 100644 index 0000000..9091cb3 --- /dev/null +++ b/public/css/index.css @@ -0,0 +1,39 @@ +body { + height: 90%; +} + +a { + color: blue; +} + +a:hover { + text-decoration: underline; +} + +#video-container { + display: none; + background: white; + position: fixed; + top: 50%; + left: 50%; + height: 100%; + width: 100%; + transform: translate(-50%, -50%); + border: black 1px solid; +} + +.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 { + background: black; + color: white; +} diff --git a/public/index.html b/public/index.html new file mode 100644 index 0000000..2db6b60 --- /dev/null +++ b/public/index.html @@ -0,0 +1,19 @@ + + + + + + +
+ + +
+
+
+ X +
+ + Download +
+ + diff --git a/public/js/peertube-dl-web.js b/public/js/peertube-dl-web.js new file mode 100644 index 0000000..69390ae --- /dev/null +++ b/public/js/peertube-dl-web.js @@ -0,0 +1,81 @@ +"use strict"; + +let downloadFormButton; +let videoContainer; +let closeAndResetVideoContainer; +let downloadFormUrl; +let downloadVideo; +let downloadForm; +let video; + +function downloadFormButtonHandler(event) { + event.preventDefault(); + getRealURL(downloadFormUrl.value).then( (response) => { + video.src = response.url; + videoContainer.style.display = 'block'; + generateBlobVideo(response.url).then( blob => { + downloadVideo.href = URL.createObjectURL(blob); + downloadVideo.download = response.filename; + }); + }); +} + +function downloadFormHandler(event) { + downloadFormButtonHandler(event); +} + +async function generateBlobVideo(url) { + const blob = await fetch(url, { + mode: 'cors', + }) + .then(res => res.blob()) + .catch( err => generateBlobVideoByProxy(url) ); + return blob; +} + +async function 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; + } + +async function getRealURL(url) { + const response = await fetch('/api', { + method: 'POST', + mode: 'cors', + cache: 'no-cache', + headers: { + 'Content-Type': 'application/json' + }, + body: JSON.stringify({url: url}), + }); + return response.json(); +} + +function closeAndResetVideoContainerHandler(event) { + event.preventDefault(); + videoContainer.style.display = 'none'; +} + +window.addEventListener('load', (event) => { + downloadFormButton = document.querySelector('#download-form-button'); + downloadForm = document.querySelector('#download-form'); + videoContainer = document.querySelector('#video-container'); + video = document.querySelector('#video'); + downloadFormUrl = document.querySelector('#download-form-url'); + downloadVideo = document.querySelector('#download-video'); + closeAndResetVideoContainer = document.querySelector('#close-and-reset-video-container'); + downloadFormButton.addEventListener('click', downloadFormButtonHandler); + downloadForm.addEventListener('submit', downloadFormHandler); + closeAndResetVideoContainer.addEventListener('click', closeAndResetVideoContainerHandler); +}); + + diff --git a/t/downloaders/gocdn.t b/t/downloaders/gocdn.t index 1d02317..04fb151 100644 --- a/t/downloaders/gocdn.t +++ b/t/downloaders/gocdn.t @@ -32,6 +32,7 @@ use JSON; get => sub { my $self = shift; my $url = shift; + say STDERR $url; $gocdn_url = $url; return $gocdn_response; }