Added Dockerfile and sources
This commit is contained in:
3
.dockerignore
Normal file
3
.dockerignore
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
/Dockerfile
|
||||||
|
/LICENSE
|
||||||
|
/README.md
|
9
Dockerfile
Normal file
9
Dockerfile
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
FROM php:7.0-apache
|
||||||
|
|
||||||
|
RUN apt update \
|
||||||
|
&& apt install youtube-dl -y \
|
||||||
|
&& rm /var/lib/apt/lists/* /var/log/* -Rf
|
||||||
|
|
||||||
|
ADD . /var/www/html
|
||||||
|
|
||||||
|
VOLUME ["/var/www/html/files"]
|
132
index.php
Executable file
132
index.php
Executable file
@ -0,0 +1,132 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
$options = [
|
||||||
|
"audio_mp3" => [
|
||||||
|
'name' => 'Audio Only (MP3)',
|
||||||
|
'group' => 'Audio Only',
|
||||||
|
'option' => '-k -x --audio-format mp3 --audio-quality 0',
|
||||||
|
'cache' => '*-%youtubeid%.mp3'
|
||||||
|
],
|
||||||
|
"audio_flac" => [
|
||||||
|
'name' => 'Audio Only (FLAC)',
|
||||||
|
'group' => 'Audio Only',
|
||||||
|
'option' => '-k -x --audio-format flac --audio-quality 0',
|
||||||
|
'cache' => '*-%youtubeid%.flac'
|
||||||
|
],
|
||||||
|
"best_video_audio" => [
|
||||||
|
'name' => 'Combine best Video+Audio',
|
||||||
|
'group' => NULL,
|
||||||
|
'option' => '-k',
|
||||||
|
'cache' => NULL
|
||||||
|
]
|
||||||
|
];
|
||||||
|
|
||||||
|
if(!chdir('files')) {
|
||||||
|
die('could not enter files folder');
|
||||||
|
}
|
||||||
|
|
||||||
|
if($_SERVER['REQUEST_METHOD'] == 'POST') {
|
||||||
|
if(!isset($_POST['option'], $_POST['url'])) {
|
||||||
|
http_response_code(400);
|
||||||
|
die('not all required values set!');
|
||||||
|
}
|
||||||
|
|
||||||
|
if(empty($option = trim($_POST['option'])) ||
|
||||||
|
empty($url = trim($_POST['url']))) {
|
||||||
|
http_response_code(400);
|
||||||
|
die('url empty!');
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!filter_var($url, FILTER_VALIDATE_URL)) {
|
||||||
|
http_response_code(400);
|
||||||
|
die('invalid url!');
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!isset($options[$option])) {
|
||||||
|
http_response_code(400);
|
||||||
|
die('invalid option!');
|
||||||
|
}
|
||||||
|
|
||||||
|
$option = $options[$option];
|
||||||
|
|
||||||
|
preg_match("#(?<=v=)[a-zA-Z0-9-]+(?=&)|(?<=v\/)[^&\n]+(?=\?)|(?<=v=)[^&\n]+|(?<=youtu.be/)[^&\n]+#", $url, $matches);
|
||||||
|
if(count($matches) != 1) {
|
||||||
|
http_response_code(400);
|
||||||
|
die('invalid youtube url!' . count($matches));
|
||||||
|
}
|
||||||
|
|
||||||
|
$cached = false;
|
||||||
|
|
||||||
|
if(!is_null($option['cache'])) {
|
||||||
|
foreach(glob(str_replace("%youtubeid%", $matches[0], $option['cache'])) as $file) {
|
||||||
|
echo '[cache] Destination: ' . $file . "\n";
|
||||||
|
$cached = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if($cached) {
|
||||||
|
die('exit code: 0');
|
||||||
|
}
|
||||||
|
|
||||||
|
ini_set('output_buffering', 'off');
|
||||||
|
ini_set('zlib.output_compression', false);
|
||||||
|
ini_set('implicit_flush', true);
|
||||||
|
ob_implicit_flush(true);
|
||||||
|
while (ob_get_level() > 0) {
|
||||||
|
$level = ob_get_level();
|
||||||
|
ob_end_clean();
|
||||||
|
if (ob_get_level() == $level) break;
|
||||||
|
}
|
||||||
|
if (function_exists('apache_setenv')) {
|
||||||
|
apache_setenv('no-gzip', '1');
|
||||||
|
apache_setenv('dont-vary', '1');
|
||||||
|
}
|
||||||
|
set_time_limit(0);
|
||||||
|
|
||||||
|
system('youtube-dl ' . $option['option']. ' ' . $url . ' 2>&1', $exitCode);
|
||||||
|
die('exit code: ' . $exitCode);
|
||||||
|
}
|
||||||
|
|
||||||
|
?>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<meta http-equiv="x-ua-compatible" content="ie=edge">
|
||||||
|
|
||||||
|
<title>Daniel's YouTube Downloader</title>
|
||||||
|
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
||||||
|
|
||||||
|
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossorigin="anonymous" />
|
||||||
|
<style>
|
||||||
|
pre {
|
||||||
|
max-height: 100px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div class="container">
|
||||||
|
<form method="POST" class="form-inline">
|
||||||
|
<select name="option" class="form-control">
|
||||||
|
<?php $lastGroup = NULL; ?>
|
||||||
|
<?php foreach($options as $index => $option) { ?>
|
||||||
|
<?php if($option['group'] != $lastGroup) { ?>
|
||||||
|
<?php if(!is_null($lastGroup)) { ?></optgroup><?php } ?>
|
||||||
|
<?php if(!is_null($option['group'])) { ?><optgroup label="<?php echo htmlentities($option['group']); ?>"><?php } ?>
|
||||||
|
<?php $lastGroup = $option['group']; ?>
|
||||||
|
<?php } ?>
|
||||||
|
<option value="<?php echo $index; ?>"><?php echo htmlentities($option['name']); ?></option>
|
||||||
|
<?php } ?>
|
||||||
|
</select>
|
||||||
|
<input type="url" name="url" <?php if(isset($url)) { echo 'value="' . htmlentities($url) . '"'; } ?> required="required" class="form-control" />
|
||||||
|
<button type="submit" class="btn btn-primary">Los</button>
|
||||||
|
<a href="info.php">Service Status</a>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="row" id="results"></div>
|
||||||
|
|
||||||
|
<script src="https://code.jquery.com/jquery-3.3.1.min.js"></script>
|
||||||
|
<script src="script.js"></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
61
info.php
Executable file
61
info.php
Executable file
@ -0,0 +1,61 @@
|
|||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>Daniel's YouTube Downloader</title>
|
||||||
|
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossorigin="anonymous" />
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div class="container">
|
||||||
|
<a href="index.php">Back</a>
|
||||||
|
|
||||||
|
<table class="table table-striped">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<?php
|
||||||
|
$output = shell_exec('ps aux');
|
||||||
|
$lines = explode("\n", $output);
|
||||||
|
|
||||||
|
$regExpr = "^";
|
||||||
|
foreach($lines as $i=>$line) {
|
||||||
|
if($i == 0) {
|
||||||
|
$columns = preg_split('/ +/', $line);
|
||||||
|
foreach($columns as $column) {
|
||||||
|
echo ' <th>' . htmlentities($column) . "</th>\n";
|
||||||
|
}
|
||||||
|
echo " </tr>\n";
|
||||||
|
echo " </thead>\n";
|
||||||
|
echo " <tbody>\n";
|
||||||
|
|
||||||
|
for($i = 1; $i < count($columns); $i++) {
|
||||||
|
$regExpr .= '([^ ]+) +';
|
||||||
|
}
|
||||||
|
$regExpr .= '(.*)$';
|
||||||
|
} else {
|
||||||
|
//if(strpos($line, "youtube-dl") === FALSE) {
|
||||||
|
// continue;
|
||||||
|
//}
|
||||||
|
|
||||||
|
if(!preg_match('/' . $regExpr . '/', $line, $matches)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
array_shift($matches);
|
||||||
|
|
||||||
|
if($matches[0] != 'www-data') {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
echo " <tr>\n";
|
||||||
|
|
||||||
|
foreach($matches as $match) {
|
||||||
|
echo ' <td>' . htmlentities($match) . "</td>\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
echo " </tr>\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
?>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
122
script.js
Normal file
122
script.js
Normal file
@ -0,0 +1,122 @@
|
|||||||
|
jQuery(document).ready(function($){
|
||||||
|
$('form').submit(function(e) {
|
||||||
|
e.preventDefault();
|
||||||
|
|
||||||
|
var resultWrapper, result, resultHeader, resultBody, resultContent;
|
||||||
|
$('#results').append(resultWrapper = $('<div>')
|
||||||
|
.addClass('col-xl-3 col-md-4 col-sm-6 col-12')
|
||||||
|
.append(result = $('<div>')
|
||||||
|
.addClass('card text-white bg-secondary')
|
||||||
|
.append(resultHeader = $('<div>')
|
||||||
|
.addClass('card-header')
|
||||||
|
.text($("input[name=url]").val() + ' ')
|
||||||
|
.append($('<small>')
|
||||||
|
.text($('select[name=option] option:selected').text())
|
||||||
|
)
|
||||||
|
)
|
||||||
|
.append(resultBody = $('<div>')
|
||||||
|
.addClass('card-body')
|
||||||
|
.append(resultContent = $('<pre>')
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
function formatText(text) {
|
||||||
|
var result = "";
|
||||||
|
for(var line of text.split("\n")) {
|
||||||
|
var parts = line.split("\r");
|
||||||
|
result += parts[parts.length - 1] + "\n";
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
$.ajax({
|
||||||
|
'url': $('form').attr('action'),
|
||||||
|
'method': $('form').attr('method'),
|
||||||
|
'data': (function() {
|
||||||
|
var data = {};
|
||||||
|
$('form input, form select').each(function(){
|
||||||
|
data[$(this).attr('name')] = $(this).val();
|
||||||
|
});
|
||||||
|
return data;
|
||||||
|
})(),
|
||||||
|
'processData': true,
|
||||||
|
'contentType': 'application/x-www-form-urlencoded; charset=UTF-8',
|
||||||
|
'xhr': function() {
|
||||||
|
var xhr = new XMLHttpRequest();
|
||||||
|
|
||||||
|
xhr.addEventListener('progress', function(e) {
|
||||||
|
resultContent.text(formatText(e.target.response));
|
||||||
|
}, false);
|
||||||
|
|
||||||
|
return xhr;
|
||||||
|
},
|
||||||
|
'success': function(data) {
|
||||||
|
resultContent.text(formatText(data));
|
||||||
|
|
||||||
|
result
|
||||||
|
.removeClass('bg-warning')
|
||||||
|
|
||||||
|
if(data.indexOf('exit code: 0') == -1) {
|
||||||
|
result
|
||||||
|
.addClass('bg-danger')
|
||||||
|
.append($('<p>').text('There was an error while processing your request!'));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var anyLink = false;
|
||||||
|
|
||||||
|
for(regex of [
|
||||||
|
/Destination: ([^\n\r$]*)/g,
|
||||||
|
/ ([^ ]+) has already been downloaded and merged/g
|
||||||
|
]) {
|
||||||
|
var match;
|
||||||
|
while (match = regex.exec(data)) {
|
||||||
|
if(anyLink) {
|
||||||
|
resultBody.append($('<br/>'));
|
||||||
|
}
|
||||||
|
|
||||||
|
resultBody.append($('<a>')
|
||||||
|
.addClass('btn btn-sm btn-primary')
|
||||||
|
.attr('href', 'files/' + match[1])
|
||||||
|
.text(match[1])
|
||||||
|
);
|
||||||
|
|
||||||
|
anyLink = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(anyLink) {
|
||||||
|
result
|
||||||
|
.addClass('bg-success');
|
||||||
|
} else {
|
||||||
|
result
|
||||||
|
.addClass('bg-danger')
|
||||||
|
.append($('<p>').text('Did not find any downloadable file!'));
|
||||||
|
}
|
||||||
|
|
||||||
|
},
|
||||||
|
'error': function(jqXHR, textStatus, errorThrown) {
|
||||||
|
resultContent.text(formatText(jqXHR.responseText));
|
||||||
|
|
||||||
|
result
|
||||||
|
.removeClass('alert-warning')
|
||||||
|
.addClass('alert-danger')
|
||||||
|
.append($('<p>').text('Request failed!'));
|
||||||
|
},
|
||||||
|
'complete': function() {
|
||||||
|
resultHeader.prepend($('<a>')
|
||||||
|
.html('×')
|
||||||
|
.addClass('float-right btn btn-sm btn-danger')
|
||||||
|
.attr('href', '#')
|
||||||
|
.click(function(e) {
|
||||||
|
e.preventDefault();
|
||||||
|
|
||||||
|
resultWrapper.remove();
|
||||||
|
})
|
||||||
|
)
|
||||||
|
}
|
||||||
|
});
|
||||||
|
})
|
||||||
|
});
|
Reference in New Issue
Block a user