Merge branch 'release-3.0.0-beta'
This commit is contained in:
commit
9c1cb78df6
47 changed files with 1459 additions and 1777 deletions
9
.gitignore
vendored
9
.gitignore
vendored
|
@ -1,16 +1,9 @@
|
||||||
youtube-dl
|
|
||||||
dist/
|
|
||||||
node_modules/
|
|
||||||
config.php
|
|
||||||
vendor/
|
vendor/
|
||||||
templates_c/
|
templates_c/
|
||||||
ffmpeg.tar.xz
|
|
||||||
ffmpeg-*/
|
|
||||||
alltube-*.zip
|
alltube-*.zip
|
||||||
coverage/
|
coverage/
|
||||||
bower_components/
|
|
||||||
config/config.yml
|
config/config.yml
|
||||||
docs/
|
|
||||||
clover.xml
|
clover.xml
|
||||||
i18n/*/LC_MESSAGES/*.mo
|
i18n/*/LC_MESSAGES/*.mo
|
||||||
.phpunit.result.cache
|
.phpunit.result.cache
|
||||||
|
.git/
|
||||||
|
|
|
@ -7,5 +7,6 @@ addons:
|
||||||
- language-pack-fr
|
- language-pack-fr
|
||||||
install: composer install --no-progress
|
install: composer install --no-progress
|
||||||
script:
|
script:
|
||||||
|
- composer check-platform-reqs
|
||||||
- composer lint
|
- composer lint
|
||||||
- composer test
|
- composer test
|
||||||
|
|
|
@ -1,14 +1,13 @@
|
||||||
FROM php:7.3-apache
|
FROM php:7.3-apache
|
||||||
RUN apt-get update
|
RUN apt-get update
|
||||||
RUN apt-get install -y libicu-dev xz-utils git zlib1g-dev python libgmp-dev gettext libzip-dev
|
RUN apt-get install -y libicu-dev xz-utils git python libgmp-dev unzip ffmpeg
|
||||||
RUN docker-php-ext-install mbstring
|
RUN docker-php-ext-install mbstring
|
||||||
RUN docker-php-ext-install intl
|
RUN docker-php-ext-install intl
|
||||||
RUN docker-php-ext-install zip
|
|
||||||
RUN docker-php-ext-install gmp
|
RUN docker-php-ext-install gmp
|
||||||
RUN docker-php-ext-install gettext
|
|
||||||
RUN a2enmod rewrite
|
RUN a2enmod rewrite
|
||||||
RUN curl -sS https://getcomposer.org/installer | php
|
RUN curl -sS https://getcomposer.org/installer | php -- --quiet
|
||||||
COPY resources/php.ini /usr/local/etc/php/
|
COPY resources/php.ini /usr/local/etc/php/
|
||||||
COPY . /var/www/html/
|
COPY . /var/www/html/
|
||||||
RUN php composer.phar install --prefer-dist --no-progress
|
RUN php composer.phar check-platform-reqs --no-dev
|
||||||
|
RUN php composer.phar install --prefer-dist --no-progress --no-dev --optimize-autoloader
|
||||||
ENV CONVERT=1
|
ENV CONVERT=1
|
||||||
|
|
52
README.md
52
README.md
|
@ -25,10 +25,6 @@ composer install
|
||||||
|
|
||||||
This will download all the required dependencies.
|
This will download all the required dependencies.
|
||||||
|
|
||||||
(Note that it will download the ffmpeg binary for 64-bits Linux.
|
|
||||||
If you are on another platform,
|
|
||||||
you might want to specify the path to avconv/ffmpeg in your config file.)
|
|
||||||
|
|
||||||
You should also ensure that the *templates_c* folder has the right permissions:
|
You should also ensure that the *templates_c* folder has the right permissions:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
|
@ -66,19 +62,22 @@ cp config/config.example.yml config/config.yml
|
||||||
|
|
||||||
You will need PHP 7.2 (or higher) and the following PHP modules:
|
You will need PHP 7.2 (or higher) and the following PHP modules:
|
||||||
|
|
||||||
* fileinfo
|
|
||||||
* intl
|
* intl
|
||||||
* mbstring
|
* mbstring
|
||||||
* curl
|
* gmp
|
||||||
|
|
||||||
## Web server configuration
|
## Web server configuration
|
||||||
|
|
||||||
### Apache
|
### Apache
|
||||||
|
|
||||||
You will need the following modules:
|
The following modules are recommended:
|
||||||
|
|
||||||
* mod_mime
|
* mod_mime
|
||||||
* mod_rewrite
|
* mod_rewrite
|
||||||
|
* mod_expires
|
||||||
|
* mod_filter
|
||||||
|
* mod_deflate
|
||||||
|
* mod_headers
|
||||||
|
|
||||||
### Nginx
|
### Nginx
|
||||||
|
|
||||||
|
@ -133,47 +132,22 @@ server {
|
||||||
|
|
||||||
## Other dependencies
|
## Other dependencies
|
||||||
|
|
||||||
You need [avconv](https://libav.org/avconv.html)
|
You need [ffmpeg](https://ffmpeg.org/)
|
||||||
in order to enable conversions.
|
in order to enable conversions.
|
||||||
If you don't want to enable conversions, you can disable it in `config.yml`.
|
(Conversions are disabled by default.)
|
||||||
|
|
||||||
On Debian-based systems:
|
On Debian-based systems:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
sudo apt-get install libav-tools
|
sudo apt-get install ffmpeg
|
||||||
```
|
```
|
||||||
|
|
||||||
You also probably need to edit the `avconv` variable in `config.yml`
|
If your ffmpeg binary is not installed at `/usr/bin/ffmpeg`, you also need to edit the `ffmpeg` variable in `config.yml`.
|
||||||
so that it points to your ffmpeg/avconv binary (`/usr/bin/avconv` on Debian/Ubuntu).
|
|
||||||
|
|
||||||
## Use as library
|
## Use as a library
|
||||||
|
|
||||||
AllTube can also be used as a library to extract a video URL from a webpage.
|
The `Video` class is now available as [a separate package](https://packagist.org/packages/rudloff/alltube-library)
|
||||||
|
so that you can reuse it in your projects.
|
||||||
You can install it with:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
composer require rudloff/alltube
|
|
||||||
```
|
|
||||||
|
|
||||||
You can then use it in your PHP code:
|
|
||||||
|
|
||||||
```php
|
|
||||||
use Alltube\Config;
|
|
||||||
use Alltube\Video;
|
|
||||||
|
|
||||||
require_once __DIR__.'/vendor/autoload.php';
|
|
||||||
|
|
||||||
Config::setOptions(
|
|
||||||
[
|
|
||||||
'youtubedl' => '/usr/local/bin/youtube-dl',
|
|
||||||
]
|
|
||||||
);
|
|
||||||
$video = new Video('https://www.youtube.com/watch?v=dQw4w9WgXcQ');
|
|
||||||
$video->getUrl();
|
|
||||||
```
|
|
||||||
|
|
||||||
You can also have a look at this [example project](https://github.com/Rudloff/alltube-example-project).
|
|
||||||
|
|
||||||
## JSON API
|
## JSON API
|
||||||
|
|
||||||
|
|
61
RoboFile.php
61
RoboFile.php
|
@ -1,7 +1,6 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
use Robo\Tasks;
|
use Robo\Tasks;
|
||||||
use Symfony\Component\Finder\Finder;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Manage robo tasks.
|
* Manage robo tasks.
|
||||||
|
@ -15,51 +14,33 @@ class RoboFile extends Tasks
|
||||||
*/
|
*/
|
||||||
public function release()
|
public function release()
|
||||||
{
|
{
|
||||||
|
$this->stopOnFail();
|
||||||
|
|
||||||
$result = $this->taskExec('git')
|
$result = $this->taskExec('git')
|
||||||
->args('describe')
|
->arg('describe')
|
||||||
->printOutput(false)
|
|
||||||
->run();
|
->run();
|
||||||
$result->provideOutputdata();
|
$result->provideOutputdata();
|
||||||
$tag = $result->getOutputData();
|
|
||||||
|
|
||||||
// We don't want the whole vendor directory.
|
$tmpDir = $this->_tmpDir();
|
||||||
$finder = new Finder();
|
|
||||||
$finder->files()
|
|
||||||
->in(__DIR__ . '/vendor/')
|
|
||||||
->exclude(
|
|
||||||
[
|
|
||||||
'ffmpeg/',
|
|
||||||
'bin/',
|
|
||||||
'anam/phantomjs-linux-x86-binary/',
|
|
||||||
'phpunit/',
|
|
||||||
'squizlabs/',
|
|
||||||
'rinvex/countries/resources/geodata/',
|
|
||||||
'rinvex/countries/resources/flags/'
|
|
||||||
]
|
|
||||||
);
|
|
||||||
|
|
||||||
$zipTask = $this->taskPack('alltube-' . $tag . '.zip')
|
$filename = 'alltube-' . trim($result->getOutputData()) . '.zip';
|
||||||
->add('index.php')
|
|
||||||
->add('config/config.example.yml')
|
|
||||||
->add('.htaccess')
|
|
||||||
->add('img')
|
|
||||||
->add('LICENSE')
|
|
||||||
->add('README.md')
|
|
||||||
->add('robots.txt')
|
|
||||||
->add('resources')
|
|
||||||
->add('templates')
|
|
||||||
->add('templates_c/')
|
|
||||||
->add('classes')
|
|
||||||
->add('controllers')
|
|
||||||
->add('css')
|
|
||||||
->add('i18n');
|
|
||||||
|
|
||||||
foreach ($finder as $file) {
|
$this->taskFilesystemStack()
|
||||||
if ($path = $file->getRelativePathname()) {
|
->remove($filename)
|
||||||
$zipTask->add('vendor/' . $path);
|
->run();
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$zipTask->run();
|
$this->taskGitStack()
|
||||||
|
->cloneRepo(__DIR__, $tmpDir)
|
||||||
|
->run();
|
||||||
|
|
||||||
|
$this->taskComposerInstall()
|
||||||
|
->dir($tmpDir)
|
||||||
|
->optimizeAutoloader()
|
||||||
|
->noDev()
|
||||||
|
->run();
|
||||||
|
|
||||||
|
$this->taskPack($filename)
|
||||||
|
->addDir('alltube', $tmpDir)
|
||||||
|
->run();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
4
app.json
4
app.json
|
@ -19,10 +19,6 @@
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"env": {
|
"env": {
|
||||||
"CONVERT": {
|
|
||||||
"description": "Enable audio conversion",
|
|
||||||
"value": "true"
|
|
||||||
},
|
|
||||||
"PYTHON": {
|
"PYTHON": {
|
||||||
"description": "Path to python binary",
|
"description": "Path to python binary",
|
||||||
"value": "/app/.heroku/python/bin/python"
|
"value": "/app/.heroku/python/bin/python"
|
||||||
|
|
|
@ -6,8 +6,12 @@
|
||||||
|
|
||||||
namespace Alltube;
|
namespace Alltube;
|
||||||
|
|
||||||
use Exception;
|
use Alltube\Exception\ConfigException;
|
||||||
|
use Alltube\Library\Downloader;
|
||||||
use Jawira\CaseConverter\CaseConverterException;
|
use Jawira\CaseConverter\CaseConverterException;
|
||||||
|
use Jean85\PrettyVersions;
|
||||||
|
use PackageVersions\Versions;
|
||||||
|
use Symfony\Component\ErrorHandler\Debug;
|
||||||
use Symfony\Component\Yaml\Yaml;
|
use Symfony\Component\Yaml\Yaml;
|
||||||
use Jawira\CaseConverter\Convert;
|
use Jawira\CaseConverter\Convert;
|
||||||
|
|
||||||
|
@ -66,18 +70,18 @@ class Config
|
||||||
public $convertAdvancedFormats = ['mp3', 'avi', 'flv', 'wav'];
|
public $convertAdvancedFormats = ['mp3', 'avi', 'flv', 'wav'];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* avconv or ffmpeg binary path.
|
* ffmpeg binary path.
|
||||||
*
|
*
|
||||||
* @var string
|
* @var string
|
||||||
*/
|
*/
|
||||||
public $avconv = 'vendor/bin/ffmpeg';
|
public $ffmpeg = '/usr/bin/ffmpeg';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Path to the directory that contains the phantomjs binary.
|
* Path to the directory that contains the phantomjs binary.
|
||||||
*
|
*
|
||||||
* @var string
|
* @var string
|
||||||
*/
|
*/
|
||||||
public $phantomjsDir = 'vendor/bin/';
|
public $phantomjsDir = '/usr/bin/';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Disable URL rewriting.
|
* Disable URL rewriting.
|
||||||
|
@ -108,12 +112,12 @@ class Config
|
||||||
public $audioBitrate = 128;
|
public $audioBitrate = 128;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* avconv/ffmpeg logging level.
|
* ffmpeg logging level.
|
||||||
* Must be one of these: quiet, panic, fatal, error, warning, info, verbose, debug.
|
* Must be one of these: quiet, panic, fatal, error, warning, info, verbose, debug.
|
||||||
*
|
*
|
||||||
* @var string
|
* @var string
|
||||||
*/
|
*/
|
||||||
public $avconvVerbosity = 'error';
|
public $ffmpegVerbosity = 'error';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* App name.
|
* App name.
|
||||||
|
@ -140,7 +144,7 @@ class Config
|
||||||
* Config constructor.
|
* Config constructor.
|
||||||
*
|
*
|
||||||
* @param mixed[] $options Options
|
* @param mixed[] $options Options
|
||||||
* @throws CaseConverterException
|
* @throws ConfigException
|
||||||
*/
|
*/
|
||||||
private function __construct(array $options = [])
|
private function __construct(array $options = [])
|
||||||
{
|
{
|
||||||
|
@ -151,9 +155,9 @@ class Config
|
||||||
if (empty($this->genericFormats)) {
|
if (empty($this->genericFormats)) {
|
||||||
// We don't put this in the class definition so it can be detected by xgettext.
|
// We don't put this in the class definition so it can be detected by xgettext.
|
||||||
$this->genericFormats = [
|
$this->genericFormats = [
|
||||||
'best' => $localeManager->t('Best'),
|
'best/bestvideo' => $localeManager->t('Best'),
|
||||||
'bestvideo+bestaudio' => $localeManager->t('Remux best video with best audio'),
|
'bestvideo+bestaudio' => $localeManager->t('Remux best video with best audio'),
|
||||||
'worst' => $localeManager->t('Worst'),
|
'worst/worstvideo' => $localeManager->t('Worst'),
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -165,46 +169,51 @@ class Config
|
||||||
}
|
}
|
||||||
} elseif (!$this->stream) {
|
} elseif (!$this->stream) {
|
||||||
// Force HTTP if stream is not enabled.
|
// Force HTTP if stream is not enabled.
|
||||||
$this->replaceGenericFormat($format, $format . '[protocol=https]/' . $format . '[protocol=http]');
|
$keys = array_keys($this->genericFormats);
|
||||||
|
$keys[array_search($format, $keys)] = $this->addHttpToFormat($format);
|
||||||
|
if ($genericFormats = array_combine($keys, $this->genericFormats)) {
|
||||||
|
$this->genericFormats = $genericFormats;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Replace a format key.
|
* Add HTTP condition to a format.
|
||||||
*
|
*
|
||||||
* @param string $oldFormat Old format
|
* @param string $format Format
|
||||||
* @param string $newFormat New format
|
|
||||||
*
|
*
|
||||||
* @return void
|
* @return string
|
||||||
*/
|
*/
|
||||||
private function replaceGenericFormat($oldFormat, $newFormat)
|
public static function addHttpToFormat($format)
|
||||||
{
|
{
|
||||||
$keys = array_keys($this->genericFormats);
|
$newFormat = [];
|
||||||
$keys[array_search($oldFormat, $keys)] = $newFormat;
|
foreach (explode('/', $format) as $subformat) {
|
||||||
if ($genericFormats = array_combine($keys, $this->genericFormats)) {
|
$newFormat[] = $subformat . '[protocol=https]';
|
||||||
$this->genericFormats = $genericFormats;
|
$newFormat[] = $subformat . '[protocol=http]';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return implode('/', $newFormat);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Throw an exception if some of the options are invalid.
|
* Throw an exception if some of the options are invalid.
|
||||||
*
|
*
|
||||||
* @return void
|
* @return void
|
||||||
* @throws Exception If Python is missing
|
* @throws ConfigException If Python is missing
|
||||||
*
|
* @throws ConfigException If youtube-dl is missing
|
||||||
* @throws Exception If youtube-dl is missing
|
|
||||||
*/
|
*/
|
||||||
private function validateOptions()
|
private function validateOptions()
|
||||||
{
|
{
|
||||||
/*
|
|
||||||
We don't translate these exceptions because they usually occur before Slim can catch them
|
|
||||||
so they will go to the logs.
|
|
||||||
*/
|
|
||||||
if (!is_file($this->youtubedl)) {
|
if (!is_file($this->youtubedl)) {
|
||||||
throw new Exception("Can't find youtube-dl at " . $this->youtubedl);
|
throw new ConfigException("Can't find youtube-dl at " . $this->youtubedl);
|
||||||
} elseif (!Video::checkCommand([$this->python, '--version'])) {
|
} elseif (!Downloader::checkCommand([$this->python, '--version'])) {
|
||||||
throw new Exception("Can't find Python at " . $this->python);
|
throw new ConfigException("Can't find Python at " . $this->python);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!class_exists(Debug::class)) {
|
||||||
|
// Dev dependencies are probably not installed.
|
||||||
|
$this->debug = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -225,18 +234,23 @@ class Config
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Override options from environement variables.
|
* Override options from environment variables.
|
||||||
* Environment variables should use screaming snake case: CONVERT, PYTHON, AUDIO_BITRATE, etc.
|
* Environment variables should use screaming snake case: CONVERT, PYTHON, AUDIO_BITRATE, etc.
|
||||||
* If the value is an array, you should use the YAML format: "CONVERT_ADVANCED_FORMATS='[foo, bar]'"
|
* If the value is an array, you should use the YAML format: "CONVERT_ADVANCED_FORMATS='[foo, bar]'"
|
||||||
*
|
*
|
||||||
* @return void
|
* @return void
|
||||||
* @throws CaseConverterException
|
* @throws ConfigException
|
||||||
*/
|
*/
|
||||||
private function getEnv()
|
private function getEnv()
|
||||||
{
|
{
|
||||||
foreach (get_object_vars($this) as $prop => $value) {
|
foreach (get_object_vars($this) as $prop => $value) {
|
||||||
$convert = new Convert($prop);
|
try {
|
||||||
$env = getenv($convert->toMacro());
|
$convert = new Convert($prop);
|
||||||
|
$env = getenv($convert->toMacro());
|
||||||
|
} catch (CaseConverterException $e) {
|
||||||
|
// This should not happen.
|
||||||
|
throw new ConfigException('Could not parse option name: ' . $prop, $e->getCode(), $e);
|
||||||
|
}
|
||||||
if ($env) {
|
if ($env) {
|
||||||
$this->$prop = Yaml::parse($env);
|
$this->$prop = Yaml::parse($env);
|
||||||
}
|
}
|
||||||
|
@ -262,7 +276,7 @@ class Config
|
||||||
*
|
*
|
||||||
* @param string $file Path to the YAML file
|
* @param string $file Path to the YAML file
|
||||||
* @return void
|
* @return void
|
||||||
* @throws Exception
|
* @throws ConfigException
|
||||||
*/
|
*/
|
||||||
public static function setFile($file)
|
public static function setFile($file)
|
||||||
{
|
{
|
||||||
|
@ -271,7 +285,7 @@ class Config
|
||||||
self::$instance = new self($options);
|
self::$instance = new self($options);
|
||||||
self::$instance->validateOptions();
|
self::$instance->validateOptions();
|
||||||
} else {
|
} else {
|
||||||
throw new Exception("Can't find config file at " . $file);
|
throw new ConfigException("Can't find config file at " . $file);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -281,7 +295,7 @@ class Config
|
||||||
* @param mixed[] $options Options (see `config/config.example.yml` for available options)
|
* @param mixed[] $options Options (see `config/config.example.yml` for available options)
|
||||||
* @param bool $update True to update an existing instance
|
* @param bool $update True to update an existing instance
|
||||||
* @return void
|
* @return void
|
||||||
* @throws Exception
|
* @throws ConfigException
|
||||||
*/
|
*/
|
||||||
public static function setOptions(array $options, $update = true)
|
public static function setOptions(array $options, $update = true)
|
||||||
{
|
{
|
||||||
|
@ -303,4 +317,31 @@ class Config
|
||||||
{
|
{
|
||||||
self::$instance = null;
|
self::$instance = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return a downloader object with the current config.
|
||||||
|
*
|
||||||
|
* @return Downloader
|
||||||
|
*/
|
||||||
|
public function getDownloader()
|
||||||
|
{
|
||||||
|
return new Downloader(
|
||||||
|
$this->youtubedl,
|
||||||
|
$this->params,
|
||||||
|
$this->python,
|
||||||
|
$this->ffmpeg,
|
||||||
|
$this->phantomjsDir,
|
||||||
|
$this->ffmpegVerbosity
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getAppVersion()
|
||||||
|
{
|
||||||
|
$version = PrettyVersions::getVersion(Versions::ROOT_PACKAGE_NAME);
|
||||||
|
|
||||||
|
return $version->getPrettyVersion();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
namespace Alltube;
|
namespace Alltube;
|
||||||
|
|
||||||
use Aura\Session\Segment;
|
use Aura\Session\Segment;
|
||||||
|
use Symfony\Component\Finder\Finder;
|
||||||
use Symfony\Component\Translation\Translator;
|
use Symfony\Component\Translation\Translator;
|
||||||
use Symfony\Component\Translation\Loader\PoFileLoader;
|
use Symfony\Component\Translation\Loader\PoFileLoader;
|
||||||
|
|
||||||
|
@ -15,12 +16,11 @@ use Symfony\Component\Translation\Loader\PoFileLoader;
|
||||||
*/
|
*/
|
||||||
class LocaleManager
|
class LocaleManager
|
||||||
{
|
{
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Supported locales.
|
* Path to locales.
|
||||||
*
|
|
||||||
* @var string[]
|
|
||||||
*/
|
*/
|
||||||
private $supportedLocales = ['en_US', 'fr_FR', 'zh_CN', 'es_ES', 'pt_BR', 'de_DE', 'ar', 'pl_PL', 'tr_TR'];
|
private const PATH = __DIR__ . '/../i18n/';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Current locale.
|
* Current locale.
|
||||||
|
@ -75,7 +75,7 @@ class LocaleManager
|
||||||
foreach ($this->getSupportedLocales() as $locale) {
|
foreach ($this->getSupportedLocales() as $locale) {
|
||||||
$this->translator->addResource(
|
$this->translator->addResource(
|
||||||
'gettext',
|
'gettext',
|
||||||
__DIR__ . '/../i18n/' . $locale->getIso15897() . '/LC_MESSAGES/Alltube.po',
|
self::PATH . $locale->getIso15897() . '/LC_MESSAGES/Alltube.po',
|
||||||
$locale->getIso15897()
|
$locale->getIso15897()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -88,10 +88,17 @@ class LocaleManager
|
||||||
*/
|
*/
|
||||||
public function getSupportedLocales()
|
public function getSupportedLocales()
|
||||||
{
|
{
|
||||||
$return = [];
|
$return = [
|
||||||
|
new Locale('en_US')
|
||||||
|
];
|
||||||
|
|
||||||
foreach ($this->supportedLocales as $supportedLocale) {
|
$finder = new Finder();
|
||||||
$return[] = new Locale($supportedLocale);
|
$finder->depth(0)
|
||||||
|
->directories()
|
||||||
|
->in(self::PATH);
|
||||||
|
|
||||||
|
foreach ($finder as $file) {
|
||||||
|
$return[] = new Locale($file->getFilename());
|
||||||
}
|
}
|
||||||
|
|
||||||
return $return;
|
return $return;
|
||||||
|
|
|
@ -48,7 +48,6 @@ class UglyRouter extends Router
|
||||||
*
|
*
|
||||||
* @return string
|
* @return string
|
||||||
* @throws InvalidArgumentException If required data not provided
|
* @throws InvalidArgumentException If required data not provided
|
||||||
*
|
|
||||||
* @throws RuntimeException If named route does not exist
|
* @throws RuntimeException If named route does not exist
|
||||||
*/
|
*/
|
||||||
public function pathFor($name, array $data = [], array $queryParams = [])
|
public function pathFor($name, array $data = [], array $queryParams = [])
|
||||||
|
|
|
@ -1,647 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
/**
|
|
||||||
* VideoDownload class.
|
|
||||||
*/
|
|
||||||
|
|
||||||
namespace Alltube;
|
|
||||||
|
|
||||||
use Alltube\Exception\EmptyUrlException;
|
|
||||||
use Alltube\Exception\PasswordException;
|
|
||||||
use Exception;
|
|
||||||
use GuzzleHttp\Client;
|
|
||||||
use Psr\Http\Message\ResponseInterface;
|
|
||||||
use stdClass;
|
|
||||||
use Symfony\Component\Process\Process;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Extract info about videos.
|
|
||||||
*
|
|
||||||
* Due to the way youtube-dl behaves, this class can also contain information about a playlist.
|
|
||||||
*
|
|
||||||
* @property-read string $title Title
|
|
||||||
* @property-read string $protocol Network protocol (HTTP, RTMP, etc.)
|
|
||||||
* @property-read string $url File URL
|
|
||||||
* @property-read string $ext File extension
|
|
||||||
* @property-read string $extractor_key youtube-dl extractor class used
|
|
||||||
* @property-read array $entries List of videos (if the object contains information about a playlist)
|
|
||||||
* @property-read array $rtmp_conn
|
|
||||||
* @property-read string|null $_type Object type (usually "playlist" or null)
|
|
||||||
* @property-read stdClass $downloader_options
|
|
||||||
* @property-read stdClass $http_headers
|
|
||||||
*/
|
|
||||||
class Video
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Config instance.
|
|
||||||
*
|
|
||||||
* @var Config
|
|
||||||
*/
|
|
||||||
private $config;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* URL of the page containing the video.
|
|
||||||
*
|
|
||||||
* @var string
|
|
||||||
*/
|
|
||||||
private $webpageUrl;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Requested video format.
|
|
||||||
*
|
|
||||||
* @var string
|
|
||||||
*/
|
|
||||||
private $requestedFormat;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Password.
|
|
||||||
*
|
|
||||||
* @var string|null
|
|
||||||
*/
|
|
||||||
private $password;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* JSON object returned by youtube-dl.
|
|
||||||
*
|
|
||||||
* @var stdClass
|
|
||||||
*/
|
|
||||||
private $json;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* URLs of the video files.
|
|
||||||
*
|
|
||||||
* @var string[]
|
|
||||||
*/
|
|
||||||
private $urls;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* LocaleManager instance.
|
|
||||||
*
|
|
||||||
* @var LocaleManager
|
|
||||||
*/
|
|
||||||
protected $localeManager;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* VideoDownload constructor.
|
|
||||||
*
|
|
||||||
* @param string $webpageUrl URL of the page containing the video
|
|
||||||
* @param string $requestedFormat Requested video format
|
|
||||||
* (can be any format string accepted by youtube-dl,
|
|
||||||
* including selectors like "[height<=720]")
|
|
||||||
* @param string $password Password
|
|
||||||
*/
|
|
||||||
public function __construct($webpageUrl, $requestedFormat = 'best', $password = null)
|
|
||||||
{
|
|
||||||
$this->webpageUrl = $webpageUrl;
|
|
||||||
$this->requestedFormat = $requestedFormat;
|
|
||||||
$this->password = $password;
|
|
||||||
$this->config = Config::getInstance();
|
|
||||||
|
|
||||||
$this->localeManager = LocaleManager::getInstance();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return a youtube-dl process with the specified arguments.
|
|
||||||
*
|
|
||||||
* @param string[] $arguments Arguments
|
|
||||||
*
|
|
||||||
* @return Process<string>
|
|
||||||
*/
|
|
||||||
private static function getProcess(array $arguments)
|
|
||||||
{
|
|
||||||
$config = Config::getInstance();
|
|
||||||
|
|
||||||
return new Process(
|
|
||||||
array_merge(
|
|
||||||
[$config->python, $config->youtubedl],
|
|
||||||
$config->params,
|
|
||||||
$arguments
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* List all extractors.
|
|
||||||
*
|
|
||||||
* @return string[] Extractors
|
|
||||||
*
|
|
||||||
* @throws PasswordException
|
|
||||||
*/
|
|
||||||
public static function getExtractors()
|
|
||||||
{
|
|
||||||
$video = new self('');
|
|
||||||
|
|
||||||
return explode("\n", trim($video->callYoutubedl(['--list-extractors'])));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Call youtube-dl.
|
|
||||||
*
|
|
||||||
* @param string[] $arguments Arguments
|
|
||||||
*
|
|
||||||
* @return string Result
|
|
||||||
* @throws Exception If the password is wrong
|
|
||||||
* @throws Exception If youtube-dl returns an error
|
|
||||||
*
|
|
||||||
* @throws PasswordException If the video is protected by a password and no password was specified
|
|
||||||
*/
|
|
||||||
private function callYoutubedl(array $arguments)
|
|
||||||
{
|
|
||||||
$config = Config::getInstance();
|
|
||||||
|
|
||||||
$process = self::getProcess($arguments);
|
|
||||||
//This is needed by the openload extractor because it runs PhantomJS
|
|
||||||
$process->setEnv(['PATH' => $config->phantomjsDir]);
|
|
||||||
$process->run();
|
|
||||||
if (!$process->isSuccessful()) {
|
|
||||||
$errorOutput = trim($process->getErrorOutput());
|
|
||||||
$exitCode = intval($process->getExitCode());
|
|
||||||
if ($errorOutput == 'ERROR: This video is protected by a password, use the --video-password option') {
|
|
||||||
throw new PasswordException($errorOutput, $exitCode);
|
|
||||||
} elseif (substr($errorOutput, 0, 21) == 'ERROR: Wrong password') {
|
|
||||||
throw new Exception($this->localeManager->t('Wrong password'), $exitCode);
|
|
||||||
} else {
|
|
||||||
throw new Exception($errorOutput, $exitCode);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return trim($process->getOutput());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get a property from youtube-dl.
|
|
||||||
*
|
|
||||||
* @param string $prop Property
|
|
||||||
*
|
|
||||||
* @return string
|
|
||||||
* @throws PasswordException
|
|
||||||
*/
|
|
||||||
private function getProp($prop = 'dump-json')
|
|
||||||
{
|
|
||||||
$arguments = ['--' . $prop];
|
|
||||||
|
|
||||||
if (isset($this->webpageUrl)) {
|
|
||||||
$arguments[] = $this->webpageUrl;
|
|
||||||
}
|
|
||||||
if (isset($this->requestedFormat)) {
|
|
||||||
$arguments[] = '-f';
|
|
||||||
$arguments[] = $this->requestedFormat;
|
|
||||||
}
|
|
||||||
if (isset($this->password)) {
|
|
||||||
$arguments[] = '--video-password';
|
|
||||||
$arguments[] = $this->password;
|
|
||||||
}
|
|
||||||
|
|
||||||
return $this->callYoutubedl($arguments);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get all information about a video.
|
|
||||||
*
|
|
||||||
* @return stdClass Decoded JSON
|
|
||||||
*
|
|
||||||
* @throws PasswordException
|
|
||||||
*/
|
|
||||||
public function getJson()
|
|
||||||
{
|
|
||||||
if (!isset($this->json)) {
|
|
||||||
$this->json = json_decode($this->getProp('dump-single-json'));
|
|
||||||
}
|
|
||||||
|
|
||||||
return $this->json;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Magic method to get a property from the JSON object returned by youtube-dl.
|
|
||||||
*
|
|
||||||
* @param string $name Property
|
|
||||||
*
|
|
||||||
* @return mixed
|
|
||||||
* @throws PasswordException
|
|
||||||
*/
|
|
||||||
public function __get($name)
|
|
||||||
{
|
|
||||||
if (isset($this->$name)) {
|
|
||||||
return $this->getJson()->$name;
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Magic method to check if the JSON object returned by youtube-dl has a property.
|
|
||||||
*
|
|
||||||
* @param string $name Property
|
|
||||||
*
|
|
||||||
* @return bool
|
|
||||||
* @throws PasswordException
|
|
||||||
*/
|
|
||||||
public function __isset($name)
|
|
||||||
{
|
|
||||||
return isset($this->getJson()->$name);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get URL of video from URL of page.
|
|
||||||
*
|
|
||||||
* It generally returns only one URL.
|
|
||||||
* But it can return two URLs when multiple formats are specified
|
|
||||||
* (eg. bestvideo+bestaudio).
|
|
||||||
*
|
|
||||||
* @return string[] URLs of video
|
|
||||||
* @throws EmptyUrlException
|
|
||||||
* @throws PasswordException
|
|
||||||
*/
|
|
||||||
public function getUrl()
|
|
||||||
{
|
|
||||||
// Cache the URLs.
|
|
||||||
if (!isset($this->urls)) {
|
|
||||||
$this->urls = explode("\n", $this->getProp('get-url'));
|
|
||||||
|
|
||||||
if (empty($this->urls[0])) {
|
|
||||||
throw new EmptyUrlException($this->localeManager->t('youtube-dl returned an empty URL.'));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return $this->urls;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get filename of video file from URL of page.
|
|
||||||
*
|
|
||||||
* @return string Filename of extracted video
|
|
||||||
*
|
|
||||||
* @throws PasswordException
|
|
||||||
*/
|
|
||||||
public function getFilename()
|
|
||||||
{
|
|
||||||
return trim($this->getProp('get-filename'));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get filename of video with the specified extension.
|
|
||||||
*
|
|
||||||
* @param string $extension New file extension
|
|
||||||
*
|
|
||||||
* @return string Filename of extracted video with specified extension
|
|
||||||
* @throws PasswordException
|
|
||||||
*/
|
|
||||||
public function getFileNameWithExtension($extension)
|
|
||||||
{
|
|
||||||
return str_replace('.' . $this->ext, '.' . $extension, $this->getFilename());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return arguments used to run rtmp for a specific video.
|
|
||||||
*
|
|
||||||
* @return string[] Arguments
|
|
||||||
*/
|
|
||||||
private function getRtmpArguments()
|
|
||||||
{
|
|
||||||
$arguments = [];
|
|
||||||
|
|
||||||
if ($this->protocol == 'rtmp') {
|
|
||||||
foreach (
|
|
||||||
[
|
|
||||||
'url' => '-rtmp_tcurl',
|
|
||||||
'webpage_url' => '-rtmp_pageurl',
|
|
||||||
'player_url' => '-rtmp_swfverify',
|
|
||||||
'flash_version' => '-rtmp_flashver',
|
|
||||||
'play_path' => '-rtmp_playpath',
|
|
||||||
'app' => '-rtmp_app',
|
|
||||||
] as $property => $option
|
|
||||||
) {
|
|
||||||
if (isset($this->{$property})) {
|
|
||||||
$arguments[] = $option;
|
|
||||||
$arguments[] = $this->{$property};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isset($this->rtmp_conn)) {
|
|
||||||
foreach ($this->rtmp_conn as $conn) {
|
|
||||||
$arguments[] = '-rtmp_conn';
|
|
||||||
$arguments[] = $conn;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return $arguments;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Check if a command runs successfully.
|
|
||||||
*
|
|
||||||
* @param string[] $command Command and arguments
|
|
||||||
*
|
|
||||||
* @return bool False if the command returns an error, true otherwise
|
|
||||||
*/
|
|
||||||
public static function checkCommand(array $command)
|
|
||||||
{
|
|
||||||
$process = new Process($command);
|
|
||||||
$process->run();
|
|
||||||
|
|
||||||
return $process->isSuccessful();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get a process that runs avconv in order to convert a video.
|
|
||||||
*
|
|
||||||
* @param int $audioBitrate Audio bitrate of the converted file
|
|
||||||
* @param string $filetype Filetype of the converted file
|
|
||||||
* @param bool $audioOnly True to return an audio-only file
|
|
||||||
* @param string $from Start the conversion at this time
|
|
||||||
* @param string $to End the conversion at this time
|
|
||||||
*
|
|
||||||
* @return Process<string> Process
|
|
||||||
* @throws Exception If avconv/ffmpeg is missing
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
private function getAvconvProcess(
|
|
||||||
$audioBitrate,
|
|
||||||
$filetype = 'mp3',
|
|
||||||
$audioOnly = true,
|
|
||||||
$from = null,
|
|
||||||
$to = null
|
|
||||||
) {
|
|
||||||
if (!$this->checkCommand([$this->config->avconv, '-version'])) {
|
|
||||||
throw new Exception(
|
|
||||||
$this->localeManager->t(
|
|
||||||
"Can't find avconv or ffmpeg at @path.",
|
|
||||||
['@path' => $this->config->avconv]
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
$durationRegex = '/(\d+:)?(\d+:)?(\d+)/';
|
|
||||||
|
|
||||||
$afterArguments = [];
|
|
||||||
|
|
||||||
if ($audioOnly) {
|
|
||||||
$afterArguments[] = '-vn';
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!empty($from)) {
|
|
||||||
if (!preg_match($durationRegex, $from)) {
|
|
||||||
throw new Exception($this->localeManager->t('Invalid start time: @from.', ['@from' => $from]));
|
|
||||||
}
|
|
||||||
$afterArguments[] = '-ss';
|
|
||||||
$afterArguments[] = $from;
|
|
||||||
}
|
|
||||||
if (!empty($to)) {
|
|
||||||
if (!preg_match($durationRegex, $to)) {
|
|
||||||
throw new Exception($this->localeManager->t('Invalid end time: @to.', ['@to' => $to]));
|
|
||||||
}
|
|
||||||
$afterArguments[] = '-to';
|
|
||||||
$afterArguments[] = $to;
|
|
||||||
}
|
|
||||||
|
|
||||||
$urls = $this->getUrl();
|
|
||||||
|
|
||||||
$arguments = array_merge(
|
|
||||||
[
|
|
||||||
$this->config->avconv,
|
|
||||||
'-v', $this->config->avconvVerbosity,
|
|
||||||
],
|
|
||||||
$this->getRtmpArguments(),
|
|
||||||
[
|
|
||||||
'-i', $urls[0],
|
|
||||||
'-f', $filetype,
|
|
||||||
'-b:a', $audioBitrate . 'k',
|
|
||||||
],
|
|
||||||
$afterArguments,
|
|
||||||
[
|
|
||||||
'pipe:1',
|
|
||||||
]
|
|
||||||
);
|
|
||||||
|
|
||||||
//Vimeo needs a correct user-agent
|
|
||||||
$arguments[] = '-user_agent';
|
|
||||||
$arguments[] = $this->getProp('dump-user-agent');
|
|
||||||
|
|
||||||
return new Process($arguments);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get audio stream of converted video.
|
|
||||||
*
|
|
||||||
* @param string $from Start the conversion at this time
|
|
||||||
* @param string $to End the conversion at this time
|
|
||||||
*
|
|
||||||
* @return resource popen stream
|
|
||||||
* @throws Exception If the popen stream was not created correctly
|
|
||||||
*
|
|
||||||
* @throws Exception If your try to convert an M3U8 video
|
|
||||||
*/
|
|
||||||
public function getAudioStream($from = null, $to = null)
|
|
||||||
{
|
|
||||||
if (isset($this->_type) && $this->_type == 'playlist') {
|
|
||||||
throw new Exception($this->localeManager->t('Conversion of playlists is not supported.'));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isset($this->protocol)) {
|
|
||||||
if (in_array($this->protocol, ['m3u8', 'm3u8_native'])) {
|
|
||||||
throw new Exception($this->localeManager->t('Conversion of M3U8 files is not supported.'));
|
|
||||||
} elseif ($this->protocol == 'http_dash_segments') {
|
|
||||||
throw new Exception($this->localeManager->t('Conversion of DASH segments is not supported.'));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$avconvProc = $this->getAvconvProcess($this->config->audioBitrate, 'mp3', true, $from, $to);
|
|
||||||
|
|
||||||
$stream = popen($avconvProc->getCommandLine(), 'r');
|
|
||||||
|
|
||||||
if (!is_resource($stream)) {
|
|
||||||
throw new Exception($this->localeManager->t('Could not open popen stream.'));
|
|
||||||
}
|
|
||||||
|
|
||||||
return $stream;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get video stream from an M3U playlist.
|
|
||||||
*
|
|
||||||
* @return resource popen stream
|
|
||||||
* @throws Exception If the popen stream was not created correctly
|
|
||||||
*
|
|
||||||
* @throws Exception If avconv/ffmpeg is missing
|
|
||||||
*/
|
|
||||||
public function getM3uStream()
|
|
||||||
{
|
|
||||||
if (!$this->checkCommand([$this->config->avconv, '-version'])) {
|
|
||||||
throw new Exception(
|
|
||||||
$this->localeManager->t(
|
|
||||||
"Can't find avconv or ffmpeg at @path.",
|
|
||||||
['@path' => $this->config->avconv]
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
$urls = $this->getUrl();
|
|
||||||
|
|
||||||
$process = new Process(
|
|
||||||
[
|
|
||||||
$this->config->avconv,
|
|
||||||
'-v', $this->config->avconvVerbosity,
|
|
||||||
'-i', $urls[0],
|
|
||||||
'-f', $this->ext,
|
|
||||||
'-c', 'copy',
|
|
||||||
'-bsf:a', 'aac_adtstoasc',
|
|
||||||
'-movflags', 'frag_keyframe+empty_moov',
|
|
||||||
'pipe:1',
|
|
||||||
]
|
|
||||||
);
|
|
||||||
|
|
||||||
$stream = popen($process->getCommandLine(), 'r');
|
|
||||||
if (!is_resource($stream)) {
|
|
||||||
throw new Exception($this->localeManager->t('Could not open popen stream.'));
|
|
||||||
}
|
|
||||||
|
|
||||||
return $stream;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get an avconv stream to remux audio and video.
|
|
||||||
*
|
|
||||||
* @return resource popen stream
|
|
||||||
* @throws Exception If the popen stream was not created correctly
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public function getRemuxStream()
|
|
||||||
{
|
|
||||||
$urls = $this->getUrl();
|
|
||||||
|
|
||||||
if (!isset($urls[0]) || !isset($urls[1])) {
|
|
||||||
throw new Exception($this->localeManager->t('This video does not have two URLs.'));
|
|
||||||
}
|
|
||||||
|
|
||||||
$process = new Process(
|
|
||||||
[
|
|
||||||
$this->config->avconv,
|
|
||||||
'-v', $this->config->avconvVerbosity,
|
|
||||||
'-i', $urls[0],
|
|
||||||
'-i', $urls[1],
|
|
||||||
'-c', 'copy',
|
|
||||||
'-map', '0:v:0',
|
|
||||||
'-map', '1:a:0',
|
|
||||||
'-f', 'matroska',
|
|
||||||
'pipe:1',
|
|
||||||
]
|
|
||||||
);
|
|
||||||
|
|
||||||
$stream = popen($process->getCommandLine(), 'r');
|
|
||||||
if (!is_resource($stream)) {
|
|
||||||
throw new Exception($this->localeManager->t('Could not open popen stream.'));
|
|
||||||
}
|
|
||||||
|
|
||||||
return $stream;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get video stream from an RTMP video.
|
|
||||||
*
|
|
||||||
* @return resource popen stream
|
|
||||||
* @throws Exception If the popen stream was not created correctly
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public function getRtmpStream()
|
|
||||||
{
|
|
||||||
$urls = $this->getUrl();
|
|
||||||
|
|
||||||
$process = new Process(
|
|
||||||
array_merge(
|
|
||||||
[
|
|
||||||
$this->config->avconv,
|
|
||||||
'-v', $this->config->avconvVerbosity,
|
|
||||||
],
|
|
||||||
$this->getRtmpArguments(),
|
|
||||||
[
|
|
||||||
'-i', $urls[0],
|
|
||||||
'-f', $this->ext,
|
|
||||||
'pipe:1',
|
|
||||||
]
|
|
||||||
)
|
|
||||||
);
|
|
||||||
$stream = popen($process->getCommandLine(), 'r');
|
|
||||||
if (!is_resource($stream)) {
|
|
||||||
throw new Exception($this->localeManager->t('Could not open popen stream.'));
|
|
||||||
}
|
|
||||||
|
|
||||||
return $stream;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the stream of a converted video.
|
|
||||||
*
|
|
||||||
* @param int $audioBitrate Audio bitrate of the converted file
|
|
||||||
* @param string $filetype Filetype of the converted file
|
|
||||||
*
|
|
||||||
* @return resource popen stream
|
|
||||||
* @throws Exception If the popen stream was not created correctly
|
|
||||||
*
|
|
||||||
* @throws Exception If your try to convert and M3U8 video
|
|
||||||
*/
|
|
||||||
public function getConvertedStream($audioBitrate, $filetype)
|
|
||||||
{
|
|
||||||
if (in_array($this->protocol, ['m3u8', 'm3u8_native'])) {
|
|
||||||
throw new Exception($this->localeManager->t('Conversion of M3U8 files is not supported.'));
|
|
||||||
}
|
|
||||||
|
|
||||||
$avconvProc = $this->getAvconvProcess($audioBitrate, $filetype, false);
|
|
||||||
|
|
||||||
$stream = popen($avconvProc->getCommandLine(), 'r');
|
|
||||||
|
|
||||||
if (!is_resource($stream)) {
|
|
||||||
throw new Exception($this->localeManager->t('Could not open popen stream.'));
|
|
||||||
}
|
|
||||||
|
|
||||||
return $stream;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the same video but with another format.
|
|
||||||
*
|
|
||||||
* @param string $format New format
|
|
||||||
*
|
|
||||||
* @return Video
|
|
||||||
*/
|
|
||||||
public function withFormat($format)
|
|
||||||
{
|
|
||||||
return new self($this->webpageUrl, $format, $this->password);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get a HTTP response containing the video.
|
|
||||||
*
|
|
||||||
* @param mixed[] $headers HTTP headers of the request
|
|
||||||
*
|
|
||||||
* @return ResponseInterface
|
|
||||||
* @throws EmptyUrlException
|
|
||||||
* @throws PasswordException
|
|
||||||
* @link https://github.com/guzzle/guzzle/issues/2640
|
|
||||||
*/
|
|
||||||
public function getHttpResponse(array $headers = [])
|
|
||||||
{
|
|
||||||
// IDN conversion breaks with Google hosts like https://r3---sn-25glene6.googlevideo.com/.
|
|
||||||
$client = new Client(['idn_conversion' => false]);
|
|
||||||
$urls = $this->getUrl();
|
|
||||||
$stream_context_options = [];
|
|
||||||
|
|
||||||
if (array_key_exists('Referer', (array)$this->http_headers)) {
|
|
||||||
$stream_context_options = [
|
|
||||||
'http' => [
|
|
||||||
'header' => 'Referer: ' . $this->http_headers->Referer
|
|
||||||
]
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
return $client->request(
|
|
||||||
'GET',
|
|
||||||
$urls[0],
|
|
||||||
[
|
|
||||||
'stream' => true,
|
|
||||||
'stream_context' => $stream_context_options,
|
|
||||||
'headers' => array_merge((array)$this->http_headers, $headers)
|
|
||||||
]
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
10
classes/exceptions/ConfigException.php
Normal file
10
classes/exceptions/ConfigException.php
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Alltube\Exception;
|
||||||
|
|
||||||
|
use Exception;
|
||||||
|
|
||||||
|
class ConfigException extends Exception
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
|
@ -1,16 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
/**
|
|
||||||
* EmptyUrlException class.
|
|
||||||
*/
|
|
||||||
|
|
||||||
namespace Alltube\Exception;
|
|
||||||
|
|
||||||
use Exception;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Exception thrown when youtube-dl returns an empty URL.
|
|
||||||
*/
|
|
||||||
class EmptyUrlException extends Exception
|
|
||||||
{
|
|
||||||
}
|
|
|
@ -1,16 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
/**
|
|
||||||
* PasswordException class.
|
|
||||||
*/
|
|
||||||
|
|
||||||
namespace Alltube\Exception;
|
|
||||||
|
|
||||||
use Exception;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Exception thrown when a video requires a password.
|
|
||||||
*/
|
|
||||||
class PasswordException extends Exception
|
|
||||||
{
|
|
||||||
}
|
|
|
@ -6,8 +6,8 @@
|
||||||
|
|
||||||
namespace Alltube\Stream;
|
namespace Alltube\Stream;
|
||||||
|
|
||||||
use Alltube\Video;
|
use Alltube\Library\Exception\AlltubeLibraryException;
|
||||||
use Exception;
|
use Alltube\Library\Video;
|
||||||
use Slim\Http\Stream;
|
use Slim\Http\Stream;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -21,11 +21,11 @@ class ConvertedPlaylistArchiveStream extends PlaylistArchiveStream
|
||||||
* @param Video $video Video to stream
|
* @param Video $video Video to stream
|
||||||
*
|
*
|
||||||
* @return void
|
* @return void
|
||||||
* @throws Exception
|
* @throws AlltubeLibraryException
|
||||||
*/
|
*/
|
||||||
protected function startVideoStream(Video $video)
|
protected function startVideoStream(Video $video)
|
||||||
{
|
{
|
||||||
$this->curVideoStream = new Stream($video->getAudioStream());
|
$this->curVideoStream = new Stream($this->downloader->getAudioStream($video));
|
||||||
|
|
||||||
$this->init_file_stream_transfer(
|
$this->init_file_stream_transfer(
|
||||||
$video->getFileNameWithExtension('mp3'),
|
$video->getFileNameWithExtension('mp3'),
|
||||||
|
|
|
@ -6,9 +6,9 @@
|
||||||
|
|
||||||
namespace Alltube\Stream;
|
namespace Alltube\Stream;
|
||||||
|
|
||||||
use Alltube\Exception\EmptyUrlException;
|
use Alltube\Library\Downloader;
|
||||||
use Alltube\Exception\PasswordException;
|
use Alltube\Library\Exception\AlltubeLibraryException;
|
||||||
use Alltube\Video;
|
use Alltube\Library\Video;
|
||||||
use Barracuda\ArchiveStream\ZipArchive;
|
use Barracuda\ArchiveStream\ZipArchive;
|
||||||
use Psr\Http\Message\StreamInterface;
|
use Psr\Http\Message\StreamInterface;
|
||||||
|
|
||||||
|
@ -47,22 +47,32 @@ class PlaylistArchiveStream extends ZipArchive implements StreamInterface
|
||||||
*/
|
*/
|
||||||
private $isComplete = false;
|
private $isComplete = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Downloader object.
|
||||||
|
*
|
||||||
|
* @var Downloader
|
||||||
|
*/
|
||||||
|
protected $downloader;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* PlaylistArchiveStream constructor.
|
* PlaylistArchiveStream constructor.
|
||||||
*
|
*
|
||||||
* We don't call the parent constructor because it messes up the output buffering.
|
* We don't call the parent constructor because it messes up the output buffering.
|
||||||
*
|
*
|
||||||
|
* @param Downloader $downloader Downloader object
|
||||||
* @param Video $video Video/playlist to download
|
* @param Video $video Video/playlist to download
|
||||||
* @noinspection PhpMissingParentConstructorInspection
|
* @noinspection PhpMissingParentConstructorInspection
|
||||||
*/
|
*/
|
||||||
public function __construct(Video $video)
|
public function __construct(Downloader $downloader, Video $video)
|
||||||
{
|
{
|
||||||
|
$this->downloader = $downloader;
|
||||||
|
|
||||||
$buffer = fopen('php://temp', 'r+');
|
$buffer = fopen('php://temp', 'r+');
|
||||||
if ($buffer !== false) {
|
if ($buffer !== false) {
|
||||||
$this->buffer = $buffer;
|
$this->buffer = $buffer;
|
||||||
}
|
}
|
||||||
foreach ($video->entries as $entry) {
|
foreach ($video->entries as $entry) {
|
||||||
$this->videos[] = new Video($entry->url);
|
$this->videos[] = $downloader->getVideo($entry->url);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -244,12 +254,11 @@ class PlaylistArchiveStream extends ZipArchive implements StreamInterface
|
||||||
* @param Video $video Video to stream
|
* @param Video $video Video to stream
|
||||||
*
|
*
|
||||||
* @return void
|
* @return void
|
||||||
* @throws PasswordException
|
* @throws AlltubeLibraryException
|
||||||
* @throws EmptyUrlException
|
|
||||||
*/
|
*/
|
||||||
protected function startVideoStream(Video $video)
|
protected function startVideoStream(Video $video)
|
||||||
{
|
{
|
||||||
$response = $video->getHttpResponse();
|
$response = $this->downloader->getHttpResponse($video);
|
||||||
|
|
||||||
$this->curVideoStream = $response->getBody();
|
$this->curVideoStream = $response->getBody();
|
||||||
$contentLengthHeaders = $response->getHeader('Content-Length');
|
$contentLengthHeaders = $response->getHeader('Content-Length');
|
||||||
|
@ -266,8 +275,7 @@ class PlaylistArchiveStream extends ZipArchive implements StreamInterface
|
||||||
* @param int $count Number of bytes to read
|
* @param int $count Number of bytes to read
|
||||||
*
|
*
|
||||||
* @return string|false
|
* @return string|false
|
||||||
* @throws EmptyUrlException
|
* @throws AlltubeLibraryException
|
||||||
* @throws PasswordException
|
|
||||||
*/
|
*/
|
||||||
public function read($count)
|
public function read($count)
|
||||||
{
|
{
|
||||||
|
|
|
@ -6,9 +6,9 @@
|
||||||
|
|
||||||
namespace Alltube\Stream;
|
namespace Alltube\Stream;
|
||||||
|
|
||||||
use Alltube\Exception\EmptyUrlException;
|
use Alltube\Library\Downloader;
|
||||||
use Alltube\Exception\PasswordException;
|
use Alltube\Library\Exception\AlltubeLibraryException;
|
||||||
use Alltube\Video;
|
use Alltube\Library\Video;
|
||||||
use GuzzleHttp\Psr7\AppendStream;
|
use GuzzleHttp\Psr7\AppendStream;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -20,15 +20,15 @@ class YoutubeStream extends AppendStream
|
||||||
/**
|
/**
|
||||||
* YoutubeStream constructor.
|
* YoutubeStream constructor.
|
||||||
*
|
*
|
||||||
|
* @param Downloader $downloader Downloader object
|
||||||
* @param Video $video Video to stream
|
* @param Video $video Video to stream
|
||||||
* @throws EmptyUrlException
|
* @throws AlltubeLibraryException
|
||||||
* @throws PasswordException
|
|
||||||
*/
|
*/
|
||||||
public function __construct(Video $video)
|
public function __construct(Downloader $downloader, Video $video)
|
||||||
{
|
{
|
||||||
parent::__construct();
|
parent::__construct();
|
||||||
|
|
||||||
$stream = $video->getHttpResponse();
|
$stream = $downloader->getHttpResponse($video);
|
||||||
$contentLenghtHeader = $stream->getHeader('Content-Length');
|
$contentLenghtHeader = $stream->getHeader('Content-Length');
|
||||||
$rangeStart = 0;
|
$rangeStart = 0;
|
||||||
|
|
||||||
|
@ -37,7 +37,7 @@ class YoutubeStream extends AppendStream
|
||||||
if ($rangeEnd >= $contentLenghtHeader[0]) {
|
if ($rangeEnd >= $contentLenghtHeader[0]) {
|
||||||
$rangeEnd = intval($contentLenghtHeader[0]) - 1;
|
$rangeEnd = intval($contentLenghtHeader[0]) - 1;
|
||||||
}
|
}
|
||||||
$response = $video->getHttpResponse(['Range' => 'bytes=' . $rangeStart . '-' . $rangeEnd]);
|
$response = $downloader->getHttpResponse($video, ['Range' => 'bytes=' . $rangeStart . '-' . $rangeEnd]);
|
||||||
$this->addStream(new YoutubeChunkStream($response));
|
$this->addStream(new YoutubeChunkStream($response));
|
||||||
$rangeStart = $rangeEnd + 1;
|
$rangeStart = $rangeEnd + 1;
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,21 +9,20 @@
|
||||||
"ext-json": "*",
|
"ext-json": "*",
|
||||||
"aura/session": "^2.1",
|
"aura/session": "^2.1",
|
||||||
"barracudanetworks/archivestream-php": "^1.0",
|
"barracudanetworks/archivestream-php": "^1.0",
|
||||||
"guzzlehttp/guzzle": "^6.5",
|
|
||||||
"jawira/case-converter": "^3.4",
|
"jawira/case-converter": "^3.4",
|
||||||
|
"jean85/pretty-package-versions": "^1.3",
|
||||||
"mathmarques/smarty-view": "^1.1",
|
"mathmarques/smarty-view": "^1.1",
|
||||||
"npm-asset/open-sans-fontface": "^1.4",
|
"npm-asset/open-sans-fontface": "^1.4",
|
||||||
"rinvex/countries": "^6.1",
|
"rinvex/countries": "^6.1",
|
||||||
"symfony/process": "^4.0",
|
"rudloff/alltube-library": "^0.1.0",
|
||||||
|
"symfony/finder": "^5.0",
|
||||||
"symfony/translation": "^4.0",
|
"symfony/translation": "^4.0",
|
||||||
"symfony/yaml": "^4.0",
|
"symfony/yaml": "^4.0",
|
||||||
|
"ytdl-org/youtube-dl": "^2020.06",
|
||||||
"zonuexe/http-accept-language": "^0.4.1"
|
"zonuexe/http-accept-language": "^0.4.1"
|
||||||
},
|
},
|
||||||
"require-dev": {
|
"require-dev": {
|
||||||
"anam/phantomjs-linux-x86-binary": "^2.1",
|
"consolidation/robo": "^2.1",
|
||||||
"consolidation/robo": "^2.0",
|
|
||||||
"ffmpeg/ffmpeg": "^4.1",
|
|
||||||
"heroku/heroku-buildpack-php": "^162.0",
|
|
||||||
"php-mock/php-mock-mockery": "^1.3",
|
"php-mock/php-mock-mockery": "^1.3",
|
||||||
"phpro/grumphp": "^0.18.0",
|
"phpro/grumphp": "^0.18.0",
|
||||||
"phpstan/phpstan": "^0.12.25",
|
"phpstan/phpstan": "^0.12.25",
|
||||||
|
@ -32,15 +31,7 @@
|
||||||
"smarty-gettext/smarty-gettext": "^1.6",
|
"smarty-gettext/smarty-gettext": "^1.6",
|
||||||
"squizlabs/php_codesniffer": "^3.5",
|
"squizlabs/php_codesniffer": "^3.5",
|
||||||
"symfony/error-handler": "^5.0",
|
"symfony/error-handler": "^5.0",
|
||||||
"symfony/var-dumper": "^5.0",
|
"symfony/var-dumper": "^5.0"
|
||||||
"ytdl-org/youtube-dl": "^2020.05"
|
|
||||||
},
|
|
||||||
"extra": {
|
|
||||||
"paas": {
|
|
||||||
"nginx-includes": [
|
|
||||||
"resources/nginx.conf"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
"repositories": [
|
"repositories": [
|
||||||
{
|
{
|
||||||
|
@ -51,26 +42,12 @@
|
||||||
"type": "package",
|
"type": "package",
|
||||||
"package": {
|
"package": {
|
||||||
"name": "ytdl-org/youtube-dl",
|
"name": "ytdl-org/youtube-dl",
|
||||||
"version": "2020.05.08",
|
"version": "2020.06.16.1",
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://github.com/ytdl-org/youtube-dl/archive/2020.05.08.zip"
|
"url": "https://github.com/ytdl-org/youtube-dl/archive/2020.06.16.1.zip"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "package",
|
|
||||||
"package": {
|
|
||||||
"name": "ffmpeg/ffmpeg",
|
|
||||||
"version": "4.1.4",
|
|
||||||
"dist": {
|
|
||||||
"url": "https://www.johnvansickle.com/ffmpeg/old-releases/ffmpeg-4.1.4-amd64-static.tar.xz",
|
|
||||||
"type": "xz"
|
|
||||||
},
|
|
||||||
"bin": [
|
|
||||||
"ffmpeg"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"authors": [
|
"authors": [
|
||||||
|
@ -97,10 +74,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"compile": "composer install --ignore-platform-reqs",
|
|
||||||
"lint": "grumphp run --ansi",
|
"lint": "grumphp run --ansi",
|
||||||
"test": "phpunit",
|
"test": "phpunit",
|
||||||
"release": "robo release",
|
"release": "robo release --ansi",
|
||||||
"update-locales": [
|
"update-locales": [
|
||||||
"tsmarty2c.php templates > i18n/template.pot",
|
"tsmarty2c.php templates > i18n/template.pot",
|
||||||
"xgettext --omit-header -kt -j -o i18n/template.pot classes/*.php classes/*/*.php controllers/*"
|
"xgettext --omit-header -kt -j -o i18n/template.pot classes/*.php classes/*/*.php controllers/*"
|
||||||
|
|
890
composer.lock
generated
890
composer.lock
generated
File diff suppressed because it is too large
Load diff
|
@ -22,14 +22,14 @@ convertAdvanced: false
|
||||||
# List of formats available in advanced conversion mode
|
# List of formats available in advanced conversion mode
|
||||||
convertAdvancedFormats: [mp3, avi, flv, wav]
|
convertAdvancedFormats: [mp3, avi, flv, wav]
|
||||||
|
|
||||||
# Path to your avconv or ffmpeg binary
|
# Path to your ffmpeg binary
|
||||||
avconv: vendor/bin/ffmpeg
|
ffmpeg: /usr/bin/ffmpeg
|
||||||
|
|
||||||
# avconv/ffmpeg logging level.
|
# ffmpeg logging level.
|
||||||
avconvVerbosity: error
|
ffmpegVerbosity: error
|
||||||
|
|
||||||
# Path to the directory that contains the phantomjs binary.
|
# Path to the directory that contains the phantomjs binary.
|
||||||
phantomjsDir: vendor/bin/
|
phantomjsDir: /usr/bin/
|
||||||
|
|
||||||
# True to disable URL rewriting
|
# True to disable URL rewriting
|
||||||
uglyUrls: false
|
uglyUrls: false
|
||||||
|
@ -49,9 +49,9 @@ appName: AllTube Download
|
||||||
|
|
||||||
# Generic formats supported by youtube-dl
|
# Generic formats supported by youtube-dl
|
||||||
genericFormats:
|
genericFormats:
|
||||||
best: Best
|
best/bestvideo: Best
|
||||||
bestvideo+bestaudio: Remux best video with best audio
|
bestvideo+bestaudio: Remux best video with best audio
|
||||||
worst: Worst
|
worst/worstvideo: Worst
|
||||||
|
|
||||||
# Enable debug mode.
|
# Enable debug mode.
|
||||||
debug: false
|
debug: false
|
||||||
|
|
|
@ -1,3 +1,3 @@
|
||||||
---
|
---
|
||||||
convert: false
|
convert: false
|
||||||
avconvVerbosity: fatal
|
ffmpegVerbosity: fatal
|
||||||
|
|
|
@ -1,13 +0,0 @@
|
||||||
---
|
|
||||||
convert: false
|
|
||||||
python: C:\Python36\python.exe
|
|
||||||
avconv: C:\ProgramData\chocolatey\bin\ffmpeg.exe
|
|
||||||
avconvVerbosity: fatal
|
|
||||||
phantomjsDir: C:\ProgramData\chocolatey\bin\
|
|
||||||
youtubedl: C:\Python36\Lib\site-packages\youtube_dl\__main__.py
|
|
||||||
params:
|
|
||||||
- --no-warnings
|
|
||||||
- --ignore-errors
|
|
||||||
- --flat-playlist
|
|
||||||
- --restrict-filenames
|
|
||||||
- --no-check-certificate
|
|
|
@ -7,12 +7,14 @@
|
||||||
namespace Alltube\Controller;
|
namespace Alltube\Controller;
|
||||||
|
|
||||||
use Alltube\Config;
|
use Alltube\Config;
|
||||||
|
use Alltube\Library\Downloader;
|
||||||
|
use Alltube\Library\Video;
|
||||||
use Alltube\LocaleManager;
|
use Alltube\LocaleManager;
|
||||||
use Alltube\SessionManager;
|
use Alltube\SessionManager;
|
||||||
use Alltube\Video;
|
|
||||||
use Aura\Session\Segment;
|
use Aura\Session\Segment;
|
||||||
use Psr\Container\ContainerInterface;
|
use Psr\Container\ContainerInterface;
|
||||||
use Slim\Http\Request;
|
use Slim\Http\Request;
|
||||||
|
use Slim\Http\Response;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Abstract class used by every controller.
|
* Abstract class used by every controller.
|
||||||
|
@ -31,7 +33,7 @@ abstract class BaseController
|
||||||
*
|
*
|
||||||
* @var string
|
* @var string
|
||||||
*/
|
*/
|
||||||
protected $defaultFormat = 'best[protocol=https]/best[protocol=http]';
|
protected $defaultFormat = 'best/bestvideo';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Slim dependency container.
|
* Slim dependency container.
|
||||||
|
@ -61,6 +63,13 @@ abstract class BaseController
|
||||||
*/
|
*/
|
||||||
protected $localeManager;
|
protected $localeManager;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Downloader instance.
|
||||||
|
*
|
||||||
|
* @var Downloader
|
||||||
|
*/
|
||||||
|
protected $downloader;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* BaseController constructor.
|
* BaseController constructor.
|
||||||
*
|
*
|
||||||
|
@ -73,9 +82,11 @@ abstract class BaseController
|
||||||
$session = SessionManager::getSession();
|
$session = SessionManager::getSession();
|
||||||
$this->sessionSegment = $session->getSegment(self::class);
|
$this->sessionSegment = $session->getSegment(self::class);
|
||||||
$this->localeManager = $this->container->get('locale');
|
$this->localeManager = $this->container->get('locale');
|
||||||
|
$this->downloader = $this->config->getDownloader();
|
||||||
|
|
||||||
if ($this->config->stream) {
|
if (!$this->config->stream) {
|
||||||
$this->defaultFormat = 'best';
|
// Force HTTP if stream is not enabled.
|
||||||
|
$this->defaultFormat = Config::addHttpToFormat($this->defaultFormat);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -116,4 +127,20 @@ abstract class BaseController
|
||||||
|
|
||||||
return $password;
|
return $password;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Display an user-friendly error.
|
||||||
|
*
|
||||||
|
* @param Request $request PSR-7 request
|
||||||
|
* @param Response $response PSR-7 response
|
||||||
|
* @param string $message Error message
|
||||||
|
*
|
||||||
|
* @return Response HTTP response
|
||||||
|
*/
|
||||||
|
protected function displayError(Request $request, Response $response, $message)
|
||||||
|
{
|
||||||
|
$controller = new FrontController($this->container);
|
||||||
|
|
||||||
|
return $controller->displayError($request, $response, $message);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,13 +6,19 @@
|
||||||
|
|
||||||
namespace Alltube\Controller;
|
namespace Alltube\Controller;
|
||||||
|
|
||||||
use Alltube\Exception\EmptyUrlException;
|
use Alltube\Config;
|
||||||
use Alltube\Exception\PasswordException;
|
use Alltube\Library\Exception\EmptyUrlException;
|
||||||
|
use Alltube\Library\Exception\InvalidProtocolConversionException;
|
||||||
|
use Alltube\Library\Exception\PasswordException;
|
||||||
|
use Alltube\Library\Exception\AlltubeLibraryException;
|
||||||
|
use Alltube\Library\Exception\PlaylistConversionException;
|
||||||
|
use Alltube\Library\Exception\PopenStreamException;
|
||||||
|
use Alltube\Library\Exception\RemuxException;
|
||||||
|
use Alltube\Library\Exception\WrongPasswordException;
|
||||||
|
use Alltube\Library\Exception\YoutubedlException;
|
||||||
use Alltube\Stream\ConvertedPlaylistArchiveStream;
|
use Alltube\Stream\ConvertedPlaylistArchiveStream;
|
||||||
use Alltube\Stream\PlaylistArchiveStream;
|
use Alltube\Stream\PlaylistArchiveStream;
|
||||||
use Alltube\Stream\YoutubeStream;
|
use Alltube\Stream\YoutubeStream;
|
||||||
use Alltube\Video;
|
|
||||||
use Exception;
|
|
||||||
use Slim\Http\Request;
|
use Slim\Http\Request;
|
||||||
use Slim\Http\Response;
|
use Slim\Http\Response;
|
||||||
use Slim\Http\Stream;
|
use Slim\Http\Stream;
|
||||||
|
@ -25,17 +31,18 @@ class DownloadController extends BaseController
|
||||||
/**
|
/**
|
||||||
* Redirect to video file.
|
* Redirect to video file.
|
||||||
*
|
*
|
||||||
* @param Request $request PSR-7 request
|
* @param Request $request PSR-7 request
|
||||||
* @param Response $response PSR-7 response
|
* @param Response $response PSR-7 response
|
||||||
*
|
*
|
||||||
* @return Response HTTP response
|
* @return Response HTTP response
|
||||||
|
* @throws AlltubeLibraryException
|
||||||
*/
|
*/
|
||||||
public function download(Request $request, Response $response)
|
public function download(Request $request, Response $response)
|
||||||
{
|
{
|
||||||
$url = $request->getQueryParam('url');
|
$url = $request->getQueryParam('url');
|
||||||
|
|
||||||
if (isset($url)) {
|
if (isset($url)) {
|
||||||
$this->video = new Video($url, $this->getFormat($request), $this->getPassword($request));
|
$this->video = $this->downloader->getVideo($url, $this->getFormat($request), $this->getPassword($request));
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if ($this->config->convert && $request->getQueryParam('audio')) {
|
if ($this->config->convert && $request->getQueryParam('audio')) {
|
||||||
|
@ -49,14 +56,33 @@ class DownloadController extends BaseController
|
||||||
// Regular download.
|
// Regular download.
|
||||||
return $this->getDownloadResponse($request, $response);
|
return $this->getDownloadResponse($request, $response);
|
||||||
} catch (PasswordException $e) {
|
} catch (PasswordException $e) {
|
||||||
return $response->withRedirect(
|
$frontController = new FrontController($this->container);
|
||||||
$this->container->get('router')->pathFor('info') .
|
|
||||||
'?' . http_build_query($request->getQueryParams())
|
|
||||||
);
|
|
||||||
} catch (Exception $e) {
|
|
||||||
$response->getBody()->write($e->getMessage());
|
|
||||||
|
|
||||||
return $response->withHeader('Content-Type', 'text/plain')->withStatus(500);
|
return $frontController->password($request, $response);
|
||||||
|
} catch (WrongPasswordException $e) {
|
||||||
|
return $this->displayError($request, $response, $this->localeManager->t('Wrong password'));
|
||||||
|
} catch (PlaylistConversionException $e) {
|
||||||
|
return $this->displayError(
|
||||||
|
$request,
|
||||||
|
$response,
|
||||||
|
$this->localeManager->t('Conversion of playlists is not supported.')
|
||||||
|
);
|
||||||
|
} catch (InvalidProtocolConversionException $e) {
|
||||||
|
if (in_array($this->video->protocol, ['m3u8', 'm3u8_native'])) {
|
||||||
|
return $this->displayError(
|
||||||
|
$request,
|
||||||
|
$response,
|
||||||
|
$this->localeManager->t('Conversion of M3U8 files is not supported.')
|
||||||
|
);
|
||||||
|
} elseif ($this->video->protocol == 'http_dash_segments') {
|
||||||
|
return $this->displayError(
|
||||||
|
$request,
|
||||||
|
$response,
|
||||||
|
$this->localeManager->t('Conversion of DASH segments is not supported.')
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
throw $e;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return $response->withRedirect($this->container->get('router')->pathFor('index'));
|
return $response->withRedirect($this->container->get('router')->pathFor('index'));
|
||||||
|
@ -70,8 +96,7 @@ class DownloadController extends BaseController
|
||||||
* @param Response $response PSR-7 response
|
* @param Response $response PSR-7 response
|
||||||
*
|
*
|
||||||
* @return Response HTTP response
|
* @return Response HTTP response
|
||||||
* @throws PasswordException
|
* @throws AlltubeLibraryException
|
||||||
* @throws Exception
|
|
||||||
*/
|
*/
|
||||||
private function getConvertedAudioResponse(Request $request, Response $response)
|
private function getConvertedAudioResponse(Request $request, Response $response)
|
||||||
{
|
{
|
||||||
|
@ -86,13 +111,7 @@ class DownloadController extends BaseController
|
||||||
$response = $response->withHeader('Content-Type', 'audio/mpeg');
|
$response = $response->withHeader('Content-Type', 'audio/mpeg');
|
||||||
|
|
||||||
if ($request->isGet() || $request->isPost()) {
|
if ($request->isGet() || $request->isPost()) {
|
||||||
try {
|
$process = $this->downloader->getAudioStream($this->video, $this->config->audioBitrate, $from, $to);
|
||||||
$process = $this->video->getAudioStream($from, $to);
|
|
||||||
} catch (Exception $e) {
|
|
||||||
// Fallback to default format.
|
|
||||||
$this->video = $this->video->withFormat($this->defaultFormat);
|
|
||||||
$process = $this->video->getAudioStream($from, $to);
|
|
||||||
}
|
|
||||||
$response = $response->withBody(new Stream($process));
|
$response = $response->withBody(new Stream($process));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -106,36 +125,38 @@ class DownloadController extends BaseController
|
||||||
* @param Response $response PSR-7 response
|
* @param Response $response PSR-7 response
|
||||||
*
|
*
|
||||||
* @return Response HTTP response
|
* @return Response HTTP response
|
||||||
|
* @throws AlltubeLibraryException
|
||||||
|
* @throws EmptyUrlException
|
||||||
* @throws PasswordException
|
* @throws PasswordException
|
||||||
|
* @throws WrongPasswordException
|
||||||
*/
|
*/
|
||||||
private function getAudioResponse(Request $request, Response $response)
|
private function getAudioResponse(Request $request, Response $response)
|
||||||
{
|
{
|
||||||
try {
|
if (!empty($request->getQueryParam('from')) || !empty($request->getQueryParam('to'))) {
|
||||||
// First, we try to get a MP3 file directly.
|
// Force convert when we need to seek.
|
||||||
if (!empty($request->getQueryParam('from')) || !empty($request->getQueryParam('to'))) {
|
$this->video = $this->video->withFormat('bestaudio/' . $this->defaultFormat);
|
||||||
throw new Exception('Force convert when we need to seek.');
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($this->config->stream) {
|
|
||||||
$this->video = $this->video->withFormat('mp3');
|
|
||||||
|
|
||||||
return $this->getStream($request, $response);
|
|
||||||
} else {
|
|
||||||
$this->video = $this->video->withFormat('mp3[protocol=https]/mp3[protocol=http]');
|
|
||||||
|
|
||||||
$urls = $this->video->getUrl();
|
|
||||||
|
|
||||||
return $response->withRedirect($urls[0]);
|
|
||||||
}
|
|
||||||
} catch (PasswordException $e) {
|
|
||||||
$frontController = new FrontController($this->container);
|
|
||||||
|
|
||||||
return $frontController->password($request, $response);
|
|
||||||
} catch (Exception $e) {
|
|
||||||
// If MP3 is not available, we convert it.
|
|
||||||
$this->video = $this->video->withFormat('bestaudio/best');
|
|
||||||
|
|
||||||
return $this->getConvertedAudioResponse($request, $response);
|
return $this->getConvertedAudioResponse($request, $response);
|
||||||
|
} else {
|
||||||
|
try {
|
||||||
|
// First, we try to get a MP3 file directly.
|
||||||
|
if ($this->config->stream) {
|
||||||
|
$this->video = $this->video->withFormat('mp3');
|
||||||
|
|
||||||
|
return $this->getStream($request, $response);
|
||||||
|
} else {
|
||||||
|
$this->video = $this->video->withFormat(Config::addHttpToFormat('mp3'));
|
||||||
|
|
||||||
|
$urls = $this->video->getUrl();
|
||||||
|
|
||||||
|
return $response->withRedirect($urls[0]);
|
||||||
|
}
|
||||||
|
} catch (YoutubedlException $e) {
|
||||||
|
// If MP3 is not available, we convert it.
|
||||||
|
$this->video = $this->video->withFormat('bestaudio/' . $this->defaultFormat);
|
||||||
|
|
||||||
|
return $this->getConvertedAudioResponse($request, $response);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -146,17 +167,15 @@ class DownloadController extends BaseController
|
||||||
*
|
*
|
||||||
* @param Response $response PSR-7 response
|
* @param Response $response PSR-7 response
|
||||||
* @return Response HTTP response
|
* @return Response HTTP response
|
||||||
* @throws EmptyUrlException
|
* @throws AlltubeLibraryException
|
||||||
* @throws PasswordException
|
|
||||||
* @throws Exception
|
|
||||||
*/
|
*/
|
||||||
private function getStream(Request $request, Response $response)
|
private function getStream(Request $request, Response $response)
|
||||||
{
|
{
|
||||||
if (isset($this->video->entries)) {
|
if (isset($this->video->entries)) {
|
||||||
if ($this->config->convert && $request->getQueryParam('audio')) {
|
if ($this->config->convert && $request->getQueryParam('audio')) {
|
||||||
$stream = new ConvertedPlaylistArchiveStream($this->video);
|
$stream = new ConvertedPlaylistArchiveStream($this->downloader, $this->video);
|
||||||
} else {
|
} else {
|
||||||
$stream = new PlaylistArchiveStream($this->video);
|
$stream = new PlaylistArchiveStream($this->downloader, $this->video);
|
||||||
}
|
}
|
||||||
$response = $response->withHeader('Content-Type', 'application/zip');
|
$response = $response->withHeader('Content-Type', 'application/zip');
|
||||||
$response = $response->withHeader(
|
$response = $response->withHeader(
|
||||||
|
@ -167,10 +186,10 @@ class DownloadController extends BaseController
|
||||||
return $response->withBody($stream);
|
return $response->withBody($stream);
|
||||||
} elseif ($this->video->protocol == 'rtmp') {
|
} elseif ($this->video->protocol == 'rtmp') {
|
||||||
$response = $response->withHeader('Content-Type', 'video/' . $this->video->ext);
|
$response = $response->withHeader('Content-Type', 'video/' . $this->video->ext);
|
||||||
$body = new Stream($this->video->getRtmpStream());
|
$body = new Stream($this->downloader->getRtmpStream($this->video));
|
||||||
} elseif ($this->video->protocol == 'm3u8' || $this->video->protocol == 'm3u8_native') {
|
} elseif ($this->video->protocol == 'm3u8' || $this->video->protocol == 'm3u8_native') {
|
||||||
$response = $response->withHeader('Content-Type', 'video/' . $this->video->ext);
|
$response = $response->withHeader('Content-Type', 'video/' . $this->video->ext);
|
||||||
$body = new Stream($this->video->getM3uStream());
|
$body = new Stream($this->downloader->getM3uStream($this->video));
|
||||||
} else {
|
} else {
|
||||||
$headers = [];
|
$headers = [];
|
||||||
$range = $request->getHeader('Range');
|
$range = $request->getHeader('Range');
|
||||||
|
@ -178,7 +197,7 @@ class DownloadController extends BaseController
|
||||||
if (!empty($range)) {
|
if (!empty($range)) {
|
||||||
$headers['Range'] = $range;
|
$headers['Range'] = $range;
|
||||||
}
|
}
|
||||||
$stream = $this->video->getHttpResponse($headers);
|
$stream = $this->downloader->getHttpResponse($this->video, $headers);
|
||||||
|
|
||||||
$response = $response->withHeader('Content-Type', $stream->getHeader('Content-Type'));
|
$response = $response->withHeader('Content-Type', $stream->getHeader('Content-Type'));
|
||||||
$response = $response->withHeader('Content-Length', $stream->getHeader('Content-Length'));
|
$response = $response->withHeader('Content-Length', $stream->getHeader('Content-Length'));
|
||||||
|
@ -190,7 +209,7 @@ class DownloadController extends BaseController
|
||||||
|
|
||||||
if (isset($this->video->downloader_options->http_chunk_size)) {
|
if (isset($this->video->downloader_options->http_chunk_size)) {
|
||||||
// Workaround for Youtube throttling the download speed.
|
// Workaround for Youtube throttling the download speed.
|
||||||
$body = new YoutubeStream($this->video);
|
$body = new YoutubeStream($this->downloader, $this->video);
|
||||||
} else {
|
} else {
|
||||||
$body = $stream->getBody();
|
$body = $stream->getBody();
|
||||||
}
|
}
|
||||||
|
@ -201,7 +220,7 @@ class DownloadController extends BaseController
|
||||||
$response = $response->withHeader(
|
$response = $response->withHeader(
|
||||||
'Content-Disposition',
|
'Content-Disposition',
|
||||||
'attachment; filename="' .
|
'attachment; filename="' .
|
||||||
$this->video->getFilename() . '"'
|
$this->video->getFilename() . '"'
|
||||||
);
|
);
|
||||||
|
|
||||||
return $response;
|
return $response;
|
||||||
|
@ -210,19 +229,18 @@ class DownloadController extends BaseController
|
||||||
/**
|
/**
|
||||||
* Get a remuxed stream piped through the server.
|
* Get a remuxed stream piped through the server.
|
||||||
*
|
*
|
||||||
* @param Response $response PSR-7 response
|
|
||||||
* @param Request $request PSR-7 request
|
* @param Request $request PSR-7 request
|
||||||
*
|
*
|
||||||
|
* @param Response $response PSR-7 response
|
||||||
* @return Response HTTP response
|
* @return Response HTTP response
|
||||||
* @throws PasswordException
|
* @throws AlltubeLibraryException
|
||||||
* @throws Exception
|
|
||||||
*/
|
*/
|
||||||
private function getRemuxStream(Request $request, Response $response)
|
private function getRemuxStream(Request $request, Response $response)
|
||||||
{
|
{
|
||||||
if (!$this->config->remux) {
|
if (!$this->config->remux) {
|
||||||
throw new Exception($this->localeManager->t('You need to enable remux mode to merge two formats.'));
|
throw new RemuxException('You need to enable remux mode to merge two formats.');
|
||||||
}
|
}
|
||||||
$stream = $this->video->getRemuxStream();
|
$stream = $this->downloader->getRemuxStream($this->video);
|
||||||
$response = $response->withHeader('Content-Type', 'video/x-matroska');
|
$response = $response->withHeader('Content-Type', 'video/x-matroska');
|
||||||
if ($request->isGet()) {
|
if ($request->isGet()) {
|
||||||
$response = $response->withBody(new Stream($stream));
|
$response = $response->withBody(new Stream($stream));
|
||||||
|
@ -242,9 +260,7 @@ class DownloadController extends BaseController
|
||||||
*
|
*
|
||||||
* @param Response $response PSR-7 response
|
* @param Response $response PSR-7 response
|
||||||
* @return Response HTTP response
|
* @return Response HTTP response
|
||||||
* @throws EmptyUrlException
|
* @throws AlltubeLibraryException
|
||||||
* @throws PasswordException
|
|
||||||
* @throws Exception
|
|
||||||
*/
|
*/
|
||||||
private function getDownloadResponse(Request $request, Response $response)
|
private function getDownloadResponse(Request $request, Response $response)
|
||||||
{
|
{
|
||||||
|
@ -263,7 +279,7 @@ class DownloadController extends BaseController
|
||||||
return $this->getStream($request, $response);
|
return $this->getStream($request, $response);
|
||||||
} else {
|
} else {
|
||||||
if (empty($videoUrls[0])) {
|
if (empty($videoUrls[0])) {
|
||||||
throw new Exception($this->localeManager->t("Can't find URL of video."));
|
throw new EmptyUrlException("Can't find URL of video.");
|
||||||
}
|
}
|
||||||
|
|
||||||
return $response->withRedirect($videoUrls[0]);
|
return $response->withRedirect($videoUrls[0]);
|
||||||
|
@ -277,8 +293,13 @@ class DownloadController extends BaseController
|
||||||
* @param Response $response PSR-7 response
|
* @param Response $response PSR-7 response
|
||||||
*
|
*
|
||||||
* @return Response HTTP response
|
* @return Response HTTP response
|
||||||
|
* @throws AlltubeLibraryException
|
||||||
|
* @throws InvalidProtocolConversionException
|
||||||
* @throws PasswordException
|
* @throws PasswordException
|
||||||
* @throws Exception
|
* @throws PlaylistConversionException
|
||||||
|
* @throws WrongPasswordException
|
||||||
|
* @throws YoutubedlException
|
||||||
|
* @throws PopenStreamException
|
||||||
*/
|
*/
|
||||||
private function getConvertedResponse(Request $request, Response $response)
|
private function getConvertedResponse(Request $request, Response $response)
|
||||||
{
|
{
|
||||||
|
@ -290,7 +311,8 @@ class DownloadController extends BaseController
|
||||||
$response = $response->withHeader('Content-Type', 'video/' . $request->getQueryParam('customFormat'));
|
$response = $response->withHeader('Content-Type', 'video/' . $request->getQueryParam('customFormat'));
|
||||||
|
|
||||||
if ($request->isGet() || $request->isPost()) {
|
if ($request->isGet() || $request->isPost()) {
|
||||||
$process = $this->video->getConvertedStream(
|
$process = $this->downloader->getConvertedStream(
|
||||||
|
$this->video,
|
||||||
$request->getQueryParam('customBitrate'),
|
$request->getQueryParam('customBitrate'),
|
||||||
$request->getQueryParam('customFormat')
|
$request->getQueryParam('customFormat')
|
||||||
);
|
);
|
||||||
|
|
|
@ -6,14 +6,13 @@
|
||||||
|
|
||||||
namespace Alltube\Controller;
|
namespace Alltube\Controller;
|
||||||
|
|
||||||
use Alltube\Exception\PasswordException;
|
use Alltube\Library\Exception\PasswordException;
|
||||||
|
use Alltube\Library\Exception\AlltubeLibraryException;
|
||||||
|
use Alltube\Library\Exception\WrongPasswordException;
|
||||||
use Alltube\Locale;
|
use Alltube\Locale;
|
||||||
use Alltube\Video;
|
|
||||||
use Symfony\Component\ErrorHandler\ErrorHandler;
|
|
||||||
use Symfony\Component\ErrorHandler\ErrorRenderer\HtmlErrorRenderer;
|
|
||||||
use Symfony\Component\ErrorHandler\Exception\FlattenException;
|
|
||||||
use Throwable;
|
|
||||||
use Exception;
|
use Exception;
|
||||||
|
use Symfony\Component\ErrorHandler\ErrorRenderer\HtmlErrorRenderer;
|
||||||
|
use Throwable;
|
||||||
use Psr\Container\ContainerInterface;
|
use Psr\Container\ContainerInterface;
|
||||||
use Slim\Http\Request;
|
use Slim\Http\Request;
|
||||||
use Slim\Http\Response;
|
use Slim\Http\Response;
|
||||||
|
@ -96,7 +95,7 @@ class FrontController extends BaseController
|
||||||
* @param Response $response PSR-7 response
|
* @param Response $response PSR-7 response
|
||||||
*
|
*
|
||||||
* @return Response HTTP response
|
* @return Response HTTP response
|
||||||
* @throws PasswordException
|
* @throws AlltubeLibraryException
|
||||||
*/
|
*/
|
||||||
public function extractors(Request $request, Response $response)
|
public function extractors(Request $request, Response $response)
|
||||||
{
|
{
|
||||||
|
@ -105,7 +104,7 @@ class FrontController extends BaseController
|
||||||
'extractors.tpl',
|
'extractors.tpl',
|
||||||
[
|
[
|
||||||
'config' => $this->config,
|
'config' => $this->config,
|
||||||
'extractors' => Video::getExtractors(),
|
'extractors' => $this->downloader->getExtractors(),
|
||||||
'class' => 'extractors',
|
'class' => 'extractors',
|
||||||
'title' => $this->localeManager->t('Supported websites'),
|
'title' => $this->localeManager->t('Supported websites'),
|
||||||
'description' => $this->localeManager->t('List of all supported websites from which Alltube Download ' .
|
'description' => $this->localeManager->t('List of all supported websites from which Alltube Download ' .
|
||||||
|
@ -143,7 +142,7 @@ class FrontController extends BaseController
|
||||||
]
|
]
|
||||||
);
|
);
|
||||||
|
|
||||||
return $response;
|
return $response->withStatus(403);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -153,6 +152,7 @@ class FrontController extends BaseController
|
||||||
* @param Response $response PSR-7 response
|
* @param Response $response PSR-7 response
|
||||||
*
|
*
|
||||||
* @return Response HTTP response
|
* @return Response HTTP response
|
||||||
|
* @throws AlltubeLibraryException
|
||||||
*/
|
*/
|
||||||
private function getInfoResponse(Request $request, Response $response)
|
private function getInfoResponse(Request $request, Response $response)
|
||||||
{
|
{
|
||||||
|
@ -160,6 +160,8 @@ class FrontController extends BaseController
|
||||||
$this->video->getJson();
|
$this->video->getJson();
|
||||||
} catch (PasswordException $e) {
|
} catch (PasswordException $e) {
|
||||||
return $this->password($request, $response);
|
return $this->password($request, $response);
|
||||||
|
} catch (WrongPasswordException $e) {
|
||||||
|
return $this->displayError($request, $response, $this->localeManager->t('Wrong password'));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isset($this->video->entries)) {
|
if (isset($this->video->entries)) {
|
||||||
|
@ -207,13 +209,14 @@ class FrontController extends BaseController
|
||||||
* @param Response $response PSR-7 response
|
* @param Response $response PSR-7 response
|
||||||
*
|
*
|
||||||
* @return Response HTTP response
|
* @return Response HTTP response
|
||||||
|
* @throws AlltubeLibraryException
|
||||||
*/
|
*/
|
||||||
public function info(Request $request, Response $response)
|
public function info(Request $request, Response $response)
|
||||||
{
|
{
|
||||||
$url = $request->getQueryParam('url') ?: $request->getQueryParam('v');
|
$url = $request->getQueryParam('url') ?: $request->getQueryParam('v');
|
||||||
|
|
||||||
if (isset($url) && !empty($url)) {
|
if (isset($url) && !empty($url)) {
|
||||||
$this->video = new Video($url, $this->getFormat($request), $this->getPassword($request));
|
$this->video = $this->downloader->getVideo($url, $this->getFormat($request), $this->getPassword($request));
|
||||||
|
|
||||||
if ($this->config->convert && $request->getQueryParam('audio')) {
|
if ($this->config->convert && $request->getQueryParam('audio')) {
|
||||||
// We skip the info page and get directly to the download.
|
// We skip the info page and get directly to the download.
|
||||||
|
@ -229,6 +232,33 @@ class FrontController extends BaseController
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Display an user-friendly error.
|
||||||
|
*
|
||||||
|
* @param Request $request PSR-7 request
|
||||||
|
* @param Response $response PSR-7 response
|
||||||
|
* @param string $message Error message
|
||||||
|
*
|
||||||
|
* @return Response HTTP response
|
||||||
|
*/
|
||||||
|
protected function displayError(Request $request, Response $response, $message)
|
||||||
|
{
|
||||||
|
$this->view->render(
|
||||||
|
$response,
|
||||||
|
'error.tpl',
|
||||||
|
[
|
||||||
|
'config' => $this->config,
|
||||||
|
'error' => $message,
|
||||||
|
'class' => 'video',
|
||||||
|
'title' => $this->localeManager->t('Error'),
|
||||||
|
'canonical' => $this->getCanonicalUrl($request),
|
||||||
|
'locale' => $this->localeManager->getLocale(),
|
||||||
|
]
|
||||||
|
);
|
||||||
|
|
||||||
|
return $response->withStatus(500);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Display an error page.
|
* Display an error page.
|
||||||
*
|
*
|
||||||
|
@ -243,7 +273,11 @@ class FrontController extends BaseController
|
||||||
if ($this->config->debug) {
|
if ($this->config->debug) {
|
||||||
$renderer = new HtmlErrorRenderer(true);
|
$renderer = new HtmlErrorRenderer(true);
|
||||||
$exception = $renderer->render($error);
|
$exception = $renderer->render($error);
|
||||||
|
|
||||||
$response->getBody()->write($exception->getAsString());
|
$response->getBody()->write($exception->getAsString());
|
||||||
|
foreach ($exception->getHeaders() as $header => $value) {
|
||||||
|
$response = $response->withHeader($header, $value);
|
||||||
|
}
|
||||||
|
|
||||||
return $response->withStatus($exception->getStatusCode());
|
return $response->withStatus($exception->getStatusCode());
|
||||||
} else {
|
} else {
|
||||||
|
@ -253,20 +287,7 @@ class FrontController extends BaseController
|
||||||
$message = '';
|
$message = '';
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->view->render(
|
return $this->displayError($request, $response, $message);
|
||||||
$response,
|
|
||||||
'error.tpl',
|
|
||||||
[
|
|
||||||
'config' => $this->config,
|
|
||||||
'error' => $message,
|
|
||||||
'class' => 'video',
|
|
||||||
'title' => $this->localeManager->t('Error'),
|
|
||||||
'canonical' => $this->getCanonicalUrl($request),
|
|
||||||
'locale' => $this->localeManager->getLocale(),
|
|
||||||
]
|
|
||||||
);
|
|
||||||
|
|
||||||
return $response->withStatus(500);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -6,8 +6,7 @@
|
||||||
|
|
||||||
namespace Alltube\Controller;
|
namespace Alltube\Controller;
|
||||||
|
|
||||||
use Alltube\Video;
|
use Alltube\Library\Exception\AlltubeLibraryException;
|
||||||
use Exception;
|
|
||||||
use Slim\Http\Request;
|
use Slim\Http\Request;
|
||||||
use Slim\Http\Response;
|
use Slim\Http\Response;
|
||||||
|
|
||||||
|
@ -19,24 +18,24 @@ class JsonController extends BaseController
|
||||||
/**
|
/**
|
||||||
* Return the JSON object generated by youtube-dl.
|
* Return the JSON object generated by youtube-dl.
|
||||||
*
|
*
|
||||||
* @param Request $request PSR-7 request
|
* @param Request $request PSR-7 request
|
||||||
* @param Response $response PSR-7 response
|
* @param Response $response PSR-7 response
|
||||||
*
|
*
|
||||||
* @return Response HTTP response
|
* @return Response HTTP response
|
||||||
|
* @throws AlltubeLibraryException
|
||||||
*/
|
*/
|
||||||
public function json(Request $request, Response $response)
|
public function json(Request $request, Response $response)
|
||||||
{
|
{
|
||||||
$url = $request->getQueryParam('url');
|
$url = $request->getQueryParam('url');
|
||||||
|
|
||||||
if (isset($url)) {
|
if (isset($url)) {
|
||||||
try {
|
$this->video = $this->downloader->getVideo(
|
||||||
$this->video = new Video($url, $this->getFormat($request), $this->getPassword($request));
|
$url,
|
||||||
|
$this->getFormat($request),
|
||||||
|
$this->getPassword($request)
|
||||||
|
);
|
||||||
|
|
||||||
return $response->withJson($this->video->getJson());
|
return $response->withJson($this->video->getJson());
|
||||||
} catch (Exception $e) {
|
|
||||||
return $response->withJson(['error' => $e->getMessage()])
|
|
||||||
->withStatus(500);
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
return $response->withJson(['error' => 'You need to provide the url parameter'])
|
return $response->withJson(['error' => 'You need to provide the url parameter'])
|
||||||
->withStatus(400);
|
->withStatus(400);
|
||||||
|
|
|
@ -1,3 +0,0 @@
|
||||||
<ifmodule mod_headers.c>
|
|
||||||
Header set Content-Security-Policy "default-src 'self'; object-src 'none'; script-src http: 'unsafe-inline'; img-src http:; style-src 'self' 'unsafe-inline' https:; font-src http:"
|
|
||||||
</ifmodule>
|
|
248
i18n/it_IT/LC_MESSAGES/Alltube.po
Normal file
248
i18n/it_IT/LC_MESSAGES/Alltube.po
Normal file
|
@ -0,0 +1,248 @@
|
||||||
|
msgid ""
|
||||||
|
msgstr "Content-Type: text/plain; charset=UTF-8\n"
|
||||||
|
|
||||||
|
#: templates/playlist.tpl:13
|
||||||
|
msgid "Videos extracted from @title:"
|
||||||
|
msgstr "Video estratti da @title:"
|
||||||
|
|
||||||
|
#: templates/playlist.tpl:38 templates/password.tpl:11 templates/index.tpl:19
|
||||||
|
#: templates/info.tpl:98
|
||||||
|
msgid "Download"
|
||||||
|
msgstr "Download"
|
||||||
|
|
||||||
|
#: templates/playlist.tpl:39
|
||||||
|
msgid "More options"
|
||||||
|
msgstr "Più opzioni"
|
||||||
|
|
||||||
|
#: templates/inc/header.tpl:4
|
||||||
|
msgid "Switch language"
|
||||||
|
msgstr "Cambia lingua"
|
||||||
|
|
||||||
|
#: templates/inc/header.tpl:8
|
||||||
|
msgid "Set language"
|
||||||
|
msgstr "Imposta lingua"
|
||||||
|
|
||||||
|
#: templates/inc/footer.tpl:8
|
||||||
|
msgid "Code by @dev"
|
||||||
|
msgstr "Codice di @dev"
|
||||||
|
|
||||||
|
#: templates/inc/footer.tpl:16
|
||||||
|
msgid "Design by @designer"
|
||||||
|
msgstr "Design di @designer"
|
||||||
|
|
||||||
|
#: templates/inc/footer.tpl:21
|
||||||
|
msgid "Get the code"
|
||||||
|
msgstr "Ottieni il codice"
|
||||||
|
|
||||||
|
#: templates/inc/footer.tpl:29
|
||||||
|
msgid "Based on @youtubedl"
|
||||||
|
msgstr "Basato su @youtubedl"
|
||||||
|
|
||||||
|
#: templates/inc/footer.tpl:33
|
||||||
|
msgid "Donate using Liberapay"
|
||||||
|
msgstr "Fai una donazione con Liberapay"
|
||||||
|
|
||||||
|
#: templates/inc/footer.tpl:35
|
||||||
|
msgid "Donate"
|
||||||
|
msgstr "Dona"
|
||||||
|
|
||||||
|
#: templates/password.tpl:5
|
||||||
|
msgid "This video is protected"
|
||||||
|
msgstr "Questo video è protetto"
|
||||||
|
|
||||||
|
#: templates/password.tpl:6
|
||||||
|
msgid "You need a password in order to download this video."
|
||||||
|
msgstr "Ti serve una password per scaricare questo video."
|
||||||
|
|
||||||
|
#: templates/password.tpl:8
|
||||||
|
msgid "Video password"
|
||||||
|
msgstr "Password del video"
|
||||||
|
|
||||||
|
#: templates/index.tpl:8
|
||||||
|
msgid "Copy here the URL of your video (Youtube, Dailymotion, etc.)"
|
||||||
|
msgstr "Copia qui l'URL del video (Youtube, Dailymotion, ecc.)"
|
||||||
|
|
||||||
|
#: templates/index.tpl:25
|
||||||
|
msgid "Audio only (MP3)"
|
||||||
|
msgstr "Solo audio (MP3)"
|
||||||
|
|
||||||
|
#: templates/index.tpl:28
|
||||||
|
msgid "From"
|
||||||
|
msgstr "Da"
|
||||||
|
|
||||||
|
#: templates/index.tpl:29
|
||||||
|
msgid "to"
|
||||||
|
msgstr "a"
|
||||||
|
|
||||||
|
#: templates/index.tpl:36
|
||||||
|
msgid "See all supported websites"
|
||||||
|
msgstr "Guarda tutti i siti supportati"
|
||||||
|
|
||||||
|
#: templates/index.tpl:38
|
||||||
|
msgid "Drag this to your bookmarks bar:"
|
||||||
|
msgstr "Trascina questo nella tua barra dei segnalibri:"
|
||||||
|
|
||||||
|
#: templates/index.tpl:39
|
||||||
|
msgid "Bookmarklet"
|
||||||
|
msgstr "Bookmarklet"
|
||||||
|
|
||||||
|
#: templates/info.tpl:13
|
||||||
|
msgid "You are going to download @title."
|
||||||
|
msgstr "Stai per scaricare @title."
|
||||||
|
|
||||||
|
#: templates/info.tpl:31
|
||||||
|
msgid "Available formats:"
|
||||||
|
msgstr "Formati disponibili:"
|
||||||
|
|
||||||
|
#: templates/info.tpl:33
|
||||||
|
msgid "Generic formats"
|
||||||
|
msgstr "Formati generici"
|
||||||
|
|
||||||
|
#: templates/info.tpl:38
|
||||||
|
msgid "Detailed formats"
|
||||||
|
msgstr "Formati dettagliati"
|
||||||
|
|
||||||
|
#: templates/info.tpl:80
|
||||||
|
msgid "Stream the video through the server"
|
||||||
|
msgstr "Riproduci il video attraverso il server"
|
||||||
|
|
||||||
|
#: templates/info.tpl:85
|
||||||
|
msgid "Convert into a custom format:"
|
||||||
|
msgstr "Converti in un formato personalizzato:"
|
||||||
|
|
||||||
|
#: templates/info.tpl:86
|
||||||
|
msgid "Custom format"
|
||||||
|
msgstr "Formato personalizzato"
|
||||||
|
|
||||||
|
#: templates/info.tpl:86
|
||||||
|
msgid "Format to convert to"
|
||||||
|
msgstr "Formato verso cui convertire"
|
||||||
|
|
||||||
|
#: templates/info.tpl:91
|
||||||
|
msgid "with"
|
||||||
|
msgstr "con"
|
||||||
|
|
||||||
|
#: templates/info.tpl:92
|
||||||
|
msgid "Bit rate"
|
||||||
|
msgstr "Bit rate"
|
||||||
|
|
||||||
|
#: templates/info.tpl:93
|
||||||
|
msgid "Custom bitrate"
|
||||||
|
msgstr "bitrate personalizzato"
|
||||||
|
|
||||||
|
#: templates/info.tpl:95
|
||||||
|
msgid "kbit/s audio"
|
||||||
|
msgstr "kbit/s audio"
|
||||||
|
|
||||||
|
#: templates/error.tpl:5
|
||||||
|
msgid "An error occurred"
|
||||||
|
msgstr "Si è verificato un errore"
|
||||||
|
|
||||||
|
#: templates/error.tpl:6
|
||||||
|
msgid "Please check the URL of your video."
|
||||||
|
msgstr "Per favore controlla l'URL del video."
|
||||||
|
|
||||||
|
#: templates/extractors.tpl:4 controllers/FrontController.php:109
|
||||||
|
msgid "Supported websites"
|
||||||
|
msgstr "Siti supportati"
|
||||||
|
|
||||||
|
#: classes/Config.php:158
|
||||||
|
msgid "Best"
|
||||||
|
msgstr "Migliore"
|
||||||
|
|
||||||
|
#: classes/Config.php:159
|
||||||
|
msgid "Remux best video with best audio"
|
||||||
|
msgstr "Fai il remux del video migliore con l'audio migliore"
|
||||||
|
|
||||||
|
#: classes/Config.php:160
|
||||||
|
msgid "Worst"
|
||||||
|
msgstr "Peggiore"
|
||||||
|
|
||||||
|
#: classes/Video.php:159
|
||||||
|
msgid "Wrong password"
|
||||||
|
msgstr "Password errata"
|
||||||
|
|
||||||
|
#: classes/Video.php:250
|
||||||
|
msgid "youtube-dl returned an empty URL."
|
||||||
|
msgstr "youtube-dl ha restituito un URL vuoto."
|
||||||
|
|
||||||
|
#: classes/Video.php:361 classes/Video.php:465
|
||||||
|
msgid "Can't find avconv or ffmpeg at @path."
|
||||||
|
msgstr "Impossibile trovare avconv o ffmpeg in @path."
|
||||||
|
|
||||||
|
#: classes/Video.php:377
|
||||||
|
msgid "Invalid start time: @from."
|
||||||
|
msgstr "Punto di inizio non valido: @from."
|
||||||
|
|
||||||
|
#: classes/Video.php:384
|
||||||
|
msgid "Invalid end time: @to."
|
||||||
|
msgstr "Punto di fine non valido: @to."
|
||||||
|
|
||||||
|
#: classes/Video.php:430
|
||||||
|
msgid "Conversion of playlists is not supported."
|
||||||
|
msgstr "La conversione delle playlist non è supportata."
|
||||||
|
|
||||||
|
#: classes/Video.php:435 classes/Video.php:578
|
||||||
|
msgid "Conversion of M3U8 files is not supported."
|
||||||
|
msgstr "La conversione di file M3U8 non è supportata."
|
||||||
|
|
||||||
|
#: classes/Video.php:437
|
||||||
|
msgid "Conversion of DASH segments is not supported."
|
||||||
|
msgstr "La conversione di segmenti DASH non è supportata."
|
||||||
|
|
||||||
|
#: classes/Video.php:446 classes/Video.php:488 classes/Video.php:525
|
||||||
|
#: classes/Video.php:558 classes/Video.php:586
|
||||||
|
msgid "Could not open popen stream."
|
||||||
|
msgstr "Non è stato possibile aprire il popen stream."
|
||||||
|
|
||||||
|
#: classes/Video.php:506
|
||||||
|
msgid "This video does not have two URLs."
|
||||||
|
msgstr "Questo video non ha due URL."
|
||||||
|
|
||||||
|
#: controllers/DownloadController.php:215
|
||||||
|
msgid "You need to enable remux mode to merge two formats."
|
||||||
|
msgstr "Devi abilitare la modalità remux per unire due formati."
|
||||||
|
|
||||||
|
#: controllers/DownloadController.php:255
|
||||||
|
msgid "Can't find URL of video."
|
||||||
|
msgstr "Impossibile trovare l'URL del video."
|
||||||
|
|
||||||
|
#: controllers/FrontController.php:64
|
||||||
|
msgid ""
|
||||||
|
"Easily download videos from Youtube, Dailymotion, Vimeo and other websites."
|
||||||
|
msgstr ""
|
||||||
|
"Scarica facilmente video da Youtube, Dailymotion, Vimeo e altri siti."
|
||||||
|
|
||||||
|
#: controllers/FrontController.php:110
|
||||||
|
msgid ""
|
||||||
|
"List of all supported websites from which Alltube Download can extract video "
|
||||||
|
"or audio files"
|
||||||
|
msgstr ""
|
||||||
|
"Lista di tutti i siti supportati da cui Alltube Download può estrarre file "
|
||||||
|
"video o audio"
|
||||||
|
|
||||||
|
#: controllers/FrontController.php:136
|
||||||
|
msgid "Password prompt"
|
||||||
|
msgstr "Richiesta password"
|
||||||
|
|
||||||
|
#: controllers/FrontController.php:138
|
||||||
|
msgid ""
|
||||||
|
"You need a password in order to download this video with Alltube Download"
|
||||||
|
msgstr ""
|
||||||
|
"Ti serve una password per scaricare questo video con Alltube Download"
|
||||||
|
|
||||||
|
#: controllers/FrontController.php:169
|
||||||
|
msgid "Video download"
|
||||||
|
msgstr "Download video"
|
||||||
|
|
||||||
|
#: controllers/FrontController.php:171
|
||||||
|
msgid "Download video from @extractor"
|
||||||
|
msgstr "Scarica video da @extractor"
|
||||||
|
|
||||||
|
#: controllers/FrontController.php:177
|
||||||
|
msgid "Download @title from @extractor"
|
||||||
|
msgstr "Scarica @title da @extractor"
|
||||||
|
|
||||||
|
#: controllers/FrontController.php:253 controllers/FrontController.php:284
|
||||||
|
msgid "Error"
|
||||||
|
msgstr "Errore"
|
|
@ -1,27 +1,6 @@
|
||||||
msgid ""
|
msgid ""
|
||||||
msgstr "Content-Type: text/plain; charset=UTF-8\n"
|
msgstr "Content-Type: text/plain; charset=UTF-8\n"
|
||||||
|
|
||||||
#: templates/playlist.tpl:13
|
|
||||||
msgid "Videos extracted from @title:"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: templates/playlist.tpl:38 templates/password.tpl:11 templates/index.tpl:19
|
|
||||||
#: templates/info.tpl:98
|
|
||||||
msgid "Download"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: templates/playlist.tpl:39
|
|
||||||
msgid "More options"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: templates/inc/header.tpl:4
|
|
||||||
msgid "Switch language"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: templates/inc/header.tpl:8
|
|
||||||
msgid "Set language"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: templates/inc/footer.tpl:8
|
#: templates/inc/footer.tpl:8
|
||||||
msgid "Code by @dev"
|
msgid "Code by @dev"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
@ -46,6 +25,87 @@ msgstr ""
|
||||||
msgid "Donate"
|
msgid "Donate"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#: templates/inc/header.tpl:4
|
||||||
|
msgid "Switch language"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: templates/inc/header.tpl:8
|
||||||
|
msgid "Set language"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: templates/info.tpl:11
|
||||||
|
msgid "You are going to download @title."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: templates/info.tpl:29
|
||||||
|
msgid "Available formats:"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: templates/info.tpl:31
|
||||||
|
msgid "Generic formats"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: templates/info.tpl:36
|
||||||
|
msgid "Detailed formats"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: templates/info.tpl:80
|
||||||
|
msgid "Stream the video through the server"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: templates/info.tpl:86
|
||||||
|
msgid "Convert into a custom format:"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: templates/info.tpl:87
|
||||||
|
msgid "Custom format"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: templates/info.tpl:87
|
||||||
|
msgid "Format to convert to"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: templates/info.tpl:92
|
||||||
|
msgid "with"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: templates/info.tpl:93
|
||||||
|
msgid "Bit rate"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: templates/info.tpl:94
|
||||||
|
msgid "Custom bitrate"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: templates/info.tpl:97
|
||||||
|
msgid "kbit/s audio"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: templates/info.tpl:101 templates/playlist.tpl:38 templates/password.tpl:11
|
||||||
|
#: templates/index.tpl:19
|
||||||
|
msgid "Download"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: templates/playlist.tpl:12
|
||||||
|
msgid "Videos extracted from @title:"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: templates/playlist.tpl:39
|
||||||
|
msgid "More options"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: templates/extractors.tpl:4 controllers/FrontController.php:109
|
||||||
|
msgid "Supported websites"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: templates/error.tpl:5
|
||||||
|
msgid "An error occurred"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: templates/error.tpl:6
|
||||||
|
msgid "Please check the URL of your video."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: templates/password.tpl:5
|
#: templates/password.tpl:5
|
||||||
msgid "This video is protected"
|
msgid "This video is protected"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
@ -70,144 +130,51 @@ msgstr ""
|
||||||
msgid "From"
|
msgid "From"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: templates/index.tpl:29
|
#: templates/index.tpl:31
|
||||||
msgid "to"
|
msgid "to"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: templates/index.tpl:36
|
#: templates/index.tpl:39
|
||||||
msgid "See all supported websites"
|
msgid "See all supported websites"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: templates/index.tpl:38
|
#: templates/index.tpl:41
|
||||||
msgid "Drag this to your bookmarks bar:"
|
msgid "Drag this to your bookmarks bar:"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: templates/index.tpl:39
|
#: templates/index.tpl:43
|
||||||
msgid "Bookmarklet"
|
msgid "Bookmarklet"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: templates/info.tpl:13
|
#: classes/Config.php:156
|
||||||
msgid "You are going to download @title."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: templates/info.tpl:31
|
|
||||||
msgid "Available formats:"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: templates/info.tpl:33
|
|
||||||
msgid "Generic formats"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: templates/info.tpl:38
|
|
||||||
msgid "Detailed formats"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: templates/info.tpl:80
|
|
||||||
msgid "Stream the video through the server"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: templates/info.tpl:85
|
|
||||||
msgid "Convert into a custom format:"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: templates/info.tpl:86
|
|
||||||
msgid "Custom format"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: templates/info.tpl:86
|
|
||||||
msgid "Format to convert to"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: templates/info.tpl:91
|
|
||||||
msgid "with"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: templates/info.tpl:92
|
|
||||||
msgid "Bit rate"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: templates/info.tpl:93
|
|
||||||
msgid "Custom bitrate"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: templates/info.tpl:95
|
|
||||||
msgid "kbit/s audio"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: templates/error.tpl:5
|
|
||||||
msgid "An error occurred"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: templates/error.tpl:6
|
|
||||||
msgid "Please check the URL of your video."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: templates/extractors.tpl:4 controllers/FrontController.php:109
|
|
||||||
msgid "Supported websites"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: classes/Config.php:158
|
|
||||||
msgid "Best"
|
msgid "Best"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: classes/Config.php:159
|
#: classes/Config.php:157
|
||||||
msgid "Remux best video with best audio"
|
msgid "Remux best video with best audio"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: classes/Config.php:160
|
#: classes/Config.php:158
|
||||||
msgid "Worst"
|
msgid "Worst"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: classes/Video.php:159
|
#: controllers/DownloadController.php:63 controllers/FrontController.php:164
|
||||||
msgid "Wrong password"
|
msgid "Wrong password"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: classes/Video.php:250
|
#: controllers/DownloadController.php:68
|
||||||
msgid "youtube-dl returned an empty URL."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: classes/Video.php:361 classes/Video.php:465
|
|
||||||
msgid "Can't find avconv or ffmpeg at @path."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: classes/Video.php:377
|
|
||||||
msgid "Invalid start time: @from."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: classes/Video.php:384
|
|
||||||
msgid "Invalid end time: @to."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: classes/Video.php:430
|
|
||||||
msgid "Conversion of playlists is not supported."
|
msgid "Conversion of playlists is not supported."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: classes/Video.php:435 classes/Video.php:578
|
#: controllers/DownloadController.php:75
|
||||||
msgid "Conversion of M3U8 files is not supported."
|
msgid "Conversion of M3U8 files is not supported."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: classes/Video.php:437
|
#: controllers/DownloadController.php:81
|
||||||
msgid "Conversion of DASH segments is not supported."
|
msgid "Conversion of DASH segments is not supported."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: classes/Video.php:446 classes/Video.php:488 classes/Video.php:525
|
#: controllers/FrontController.php:63
|
||||||
#: classes/Video.php:558 classes/Video.php:586
|
|
||||||
msgid "Could not open popen stream."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: classes/Video.php:506
|
|
||||||
msgid "This video does not have two URLs."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: controllers/DownloadController.php:215
|
|
||||||
msgid "You need to enable remux mode to merge two formats."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: controllers/DownloadController.php:255
|
|
||||||
msgid "Can't find URL of video."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: controllers/FrontController.php:64
|
|
||||||
msgid ""
|
msgid ""
|
||||||
"Easily download videos from Youtube, Dailymotion, Vimeo and other websites."
|
"Easily download videos from Youtube, Dailymotion, Vimeo and other websites."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
@ -227,18 +194,18 @@ msgid ""
|
||||||
"You need a password in order to download this video with Alltube Download"
|
"You need a password in order to download this video with Alltube Download"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: controllers/FrontController.php:169
|
#: controllers/FrontController.php:172
|
||||||
msgid "Video download"
|
msgid "Video download"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: controllers/FrontController.php:171
|
#: controllers/FrontController.php:174
|
||||||
msgid "Download video from @extractor"
|
msgid "Download video from @extractor"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: controllers/FrontController.php:177
|
#: controllers/FrontController.php:180
|
||||||
msgid "Download @title from @extractor"
|
msgid "Download @title from @extractor"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: controllers/FrontController.php:253 controllers/FrontController.php:284
|
#: controllers/FrontController.php:253
|
||||||
msgid "Error"
|
msgid "Error"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
|
@ -85,8 +85,6 @@ $app->any(
|
||||||
'/info',
|
'/info',
|
||||||
[$frontController, 'info']
|
[$frontController, 'info']
|
||||||
)->setName('info');
|
)->setName('info');
|
||||||
// Legacy route.
|
|
||||||
$app->any('/video', [$frontController, 'info']);
|
|
||||||
|
|
||||||
$app->any(
|
$app->any(
|
||||||
'/watch',
|
'/watch',
|
||||||
|
@ -97,8 +95,6 @@ $app->any(
|
||||||
'/download',
|
'/download',
|
||||||
[$downloadController, 'download']
|
[$downloadController, 'download']
|
||||||
)->setName('download');
|
)->setName('download');
|
||||||
// Legacy route.
|
|
||||||
$app->get('/redirect', [$downloadController, 'download']);
|
|
||||||
|
|
||||||
$app->get(
|
$app->get(
|
||||||
'/locale/{locale}',
|
'/locale/{locale}',
|
||||||
|
@ -116,5 +112,5 @@ try {
|
||||||
die('Smarty could not compile the template file: ' . $e->getMessage());
|
die('Smarty could not compile the template file: ' . $e->getMessage());
|
||||||
} catch (Throwable $e) {
|
} catch (Throwable $e) {
|
||||||
// Last resort if the error has not been caught by the error handler for some reason.
|
// Last resort if the error has not been caught by the error handler for some reason.
|
||||||
die('Error when starting the app: ' . $e->getMessage());
|
die('Error when starting the app: ' . htmlentities($e->getMessage()));
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,13 +33,13 @@ In order to enable audio conversion, you need to add this to your `config.yml` f
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
convert: true
|
convert: true
|
||||||
avconv: path/to/avconv
|
ffmpeg: path/to/ffmpeg
|
||||||
```
|
```
|
||||||
|
|
||||||
You will also need to install `avconv` on your server:
|
You will also need to install `ffmpeg` on your server:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
sudo apt-get install libav-tools
|
sudo apt-get install ffmpeg
|
||||||
```
|
```
|
||||||
|
|
||||||
## Deploy AllTube on Heroku
|
## Deploy AllTube on Heroku
|
||||||
|
@ -47,7 +47,6 @@ sudo apt-get install libav-tools
|
||||||
Create a dyno with the following buildpacks:
|
Create a dyno with the following buildpacks:
|
||||||
|
|
||||||
* `heroku/php`
|
* `heroku/php`
|
||||||
* `heroku/nodejs`
|
|
||||||
* `heroku/python`
|
* `heroku/python`
|
||||||
|
|
||||||
You might also need to add the following config variables:
|
You might also need to add the following config variables:
|
||||||
|
@ -113,30 +112,6 @@ you can download it if you enable streaming (see above).
|
||||||
docker run -p 8080:80 rudloff/alltube
|
docker run -p 8080:80 rudloff/alltube
|
||||||
```
|
```
|
||||||
|
|
||||||
## Run Heroku locally
|
|
||||||
|
|
||||||
You should be able to use `heroku local` like this:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
sudo APACHE_LOCK_DIR=. APACHE_PID_FILE=./pid APACHE_RUN_USER=www-data \
|
|
||||||
APACHE_RUN_GROUP=www-data APACHE_LOG_DIR=. \
|
|
||||||
heroku local
|
|
||||||
```
|
|
||||||
|
|
||||||
You might need to create some symlinks before that:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
ln -s /usr/sbin/apache2 /usr/sbin/httpd
|
|
||||||
ln -s /usr/sbin/php-fpm7.0 /usr/sbin/php-fpm
|
|
||||||
```
|
|
||||||
|
|
||||||
And you probably need to run this in another terminal
|
|
||||||
after `heroku local` has finished launching `php-fpm`:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
chmod 0667 /tmp/heroku.fcgi.5000.sock
|
|
||||||
```
|
|
||||||
|
|
||||||
## Download 1080p videos from Youtube
|
## Download 1080p videos from Youtube
|
||||||
|
|
||||||
Youtube distributes HD content in two separate video and audio files.
|
Youtube distributes HD content in two separate video and audio files.
|
||||||
|
|
|
@ -1,23 +0,0 @@
|
||||||
<?xml version="1.0"?>
|
|
||||||
<!DOCTYPE html>
|
|
||||||
<html xmlns="http://www.w3.org/1999/xhtml" lang="en">
|
|
||||||
<head>
|
|
||||||
<meta charset="UTF-8"/>
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1"/>
|
|
||||||
<title>AllTube Download - Maintenance</title>
|
|
||||||
<link rel="stylesheet" href="../dist/main.css"/>
|
|
||||||
<link rel="icon" href="../img/favicon.png"/>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<div class="wrapper">
|
|
||||||
<div class="main">
|
|
||||||
<h1>
|
|
||||||
<img class="logo" src="../img/logo.png" alt="AllTube Download" width="328" height="284"/>
|
|
||||||
</h1>
|
|
||||||
<div>An error occurred in the application and your page could not be served. Please try again in a few
|
|
||||||
moments.
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
|
@ -1,21 +0,0 @@
|
||||||
<?xml version="1.0"?>
|
|
||||||
<!DOCTYPE html>
|
|
||||||
<html xmlns="http://www.w3.org/1999/xhtml" lang="en">
|
|
||||||
<head>
|
|
||||||
<meta charset="UTF-8"/>
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1"/>
|
|
||||||
<title>AllTube Download - Maintenance</title>
|
|
||||||
<link rel="stylesheet" href="../dist/main.css"/>
|
|
||||||
<link rel="icon" href="../img/favicon.png"/>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<div class="wrapper">
|
|
||||||
<div class="main">
|
|
||||||
<h1>
|
|
||||||
<img class="logo" src="../img/logo.png" alt="AllTube Download" width="328" height="284"/>
|
|
||||||
</h1>
|
|
||||||
<div>This application is undergoing maintenance right now. Please check back later.</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
|
@ -4,6 +4,6 @@
|
||||||
{include file="inc/logo.tpl"}
|
{include file="inc/logo.tpl"}
|
||||||
<h2>{t}An error occurred{/t}</h2>
|
<h2>{t}An error occurred{/t}</h2>
|
||||||
{t}Please check the URL of your video.{/t}
|
{t}Please check the URL of your video.{/t}
|
||||||
<p><i>{$error|escape}</i></p>
|
<p><i>{$error|escape|nl2br}</i></p>
|
||||||
</main>
|
</main>
|
||||||
{include file='inc/footer.tpl'}
|
{include file='inc/footer.tpl'}
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
<html {if isset($locale)}lang="{$locale->getBcp47()}"{/if}>
|
<html {if isset($locale)}lang="{$locale->getBcp47()}"{/if}>
|
||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8"/>
|
<meta charset="UTF-8"/>
|
||||||
<meta name=viewport content="width=device-width, initial-scale=1">
|
<meta name=viewport content="width=device-width, initial-scale=1"/>
|
||||||
{if isset($description)}
|
{if isset($description)}
|
||||||
<meta name="description" content="{$description|escape}"/>
|
<meta name="description" content="{$description|escape}"/>
|
||||||
<meta name="twitter:description" content="{$description|escape}"/>
|
<meta name="twitter:description" content="{$description|escape}"/>
|
||||||
|
@ -19,7 +19,8 @@
|
||||||
<meta name="twitter:title" content="{$config->appName}{if isset($title)} - {$title|escape}{/if}"/>
|
<meta name="twitter:title" content="{$config->appName}{if isset($title)} - {$title|escape}{/if}"/>
|
||||||
<meta name="twitter:image" content="{base_url}/img/logo.png"/>
|
<meta name="twitter:image" content="{base_url}/img/logo.png"/>
|
||||||
<meta name="twitter:creator" content="@Tael67"/>
|
<meta name="twitter:creator" content="@Tael67"/>
|
||||||
<meta name="theme-color" content="#4F4F4F">
|
<meta name="theme-color" content="#4F4F4F"/>
|
||||||
<link rel="manifest" href="{base_url}/resources/manifest.json"/>
|
<link rel="manifest" href="{base_url}/resources/manifest.json"/>
|
||||||
|
<meta name="generator" content="AllTube Download ({$config->getAppVersion()})"/>
|
||||||
</head>
|
</head>
|
||||||
<body class="{$class}">
|
<body class="{$class}">
|
||||||
|
|
|
@ -76,7 +76,7 @@
|
||||||
<br/>
|
<br/>
|
||||||
{/if}
|
{/if}
|
||||||
{if $config->stream}
|
{if $config->stream}
|
||||||
<input type="checkbox" {if $config->stream != 'ask'}checked{/if} name="stream" id="stream"/>
|
<input type="checkbox" {if $config->stream !== 'ask'}checked{/if} name="stream" id="stream"/>
|
||||||
<label for="stream">{t}Stream the video through the server{/t}</label>
|
<label for="stream">{t}Stream the video through the server{/t}</label>
|
||||||
<br/>
|
<br/>
|
||||||
<br/>
|
<br/>
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
namespace Alltube\Test;
|
namespace Alltube\Test;
|
||||||
|
|
||||||
use Alltube\Config;
|
use Alltube\Config;
|
||||||
use Exception;
|
use Alltube\Exception\ConfigException;
|
||||||
use PHPUnit\Framework\TestCase;
|
use PHPUnit\Framework\TestCase;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -22,18 +22,12 @@ abstract class BaseTest extends TestCase
|
||||||
*/
|
*/
|
||||||
protected function getConfigFile()
|
protected function getConfigFile()
|
||||||
{
|
{
|
||||||
if (PHP_OS == 'WINNT') {
|
return __DIR__ . '/../config/config_test.yml';
|
||||||
$configFile = 'config_test_windows.yml';
|
|
||||||
} else {
|
|
||||||
$configFile = 'config_test.yml';
|
|
||||||
}
|
|
||||||
|
|
||||||
return __DIR__ . '/../config/' . $configFile;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Prepare tests.
|
* Prepare tests.
|
||||||
* @throws Exception
|
* @throws ConfigException
|
||||||
*/
|
*/
|
||||||
protected function setUp(): void
|
protected function setUp(): void
|
||||||
{
|
{
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
namespace Alltube\Test;
|
namespace Alltube\Test;
|
||||||
|
|
||||||
use Alltube\Config;
|
use Alltube\Config;
|
||||||
use Exception;
|
use Alltube\Exception\ConfigException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Unit tests for the Config class.
|
* Unit tests for the Config class.
|
||||||
|
@ -23,7 +23,7 @@ class ConfigTest extends BaseTest
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Prepare tests.
|
* Prepare tests.
|
||||||
* @throws Exception
|
* @throws ConfigException
|
||||||
*/
|
*/
|
||||||
protected function setUp(): void
|
protected function setUp(): void
|
||||||
{
|
{
|
||||||
|
@ -70,7 +70,7 @@ class ConfigTest extends BaseTest
|
||||||
$this->assertIsArray($config->params);
|
$this->assertIsArray($config->params);
|
||||||
$this->assertIsString($config->youtubedl);
|
$this->assertIsString($config->youtubedl);
|
||||||
$this->assertIsString($config->python);
|
$this->assertIsString($config->python);
|
||||||
$this->assertIsString($config->avconv);
|
$this->assertIsString($config->ffmpeg);
|
||||||
$this->assertIsBool($config->convert);
|
$this->assertIsBool($config->convert);
|
||||||
$this->assertIsBool($config->uglyUrls);
|
$this->assertIsBool($config->uglyUrls);
|
||||||
$this->assertIsBool($config->stream);
|
$this->assertIsBool($config->stream);
|
||||||
|
@ -82,7 +82,7 @@ class ConfigTest extends BaseTest
|
||||||
* Test the setFile function.
|
* Test the setFile function.
|
||||||
*
|
*
|
||||||
* @return void
|
* @return void
|
||||||
* @throws Exception
|
* @throws ConfigException
|
||||||
*/
|
*/
|
||||||
public function testSetFile()
|
public function testSetFile()
|
||||||
{
|
{
|
||||||
|
@ -97,7 +97,7 @@ class ConfigTest extends BaseTest
|
||||||
*/
|
*/
|
||||||
public function testSetFileWithMissingFile()
|
public function testSetFileWithMissingFile()
|
||||||
{
|
{
|
||||||
$this->expectException(Exception::class);
|
$this->expectException(ConfigException::class);
|
||||||
Config::setFile('foo');
|
Config::setFile('foo');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -105,7 +105,7 @@ class ConfigTest extends BaseTest
|
||||||
* Test the setOptions function.
|
* Test the setOptions function.
|
||||||
*
|
*
|
||||||
* @return void
|
* @return void
|
||||||
* @throws Exception
|
* @throws ConfigException
|
||||||
*/
|
*/
|
||||||
public function testSetOptions()
|
public function testSetOptions()
|
||||||
{
|
{
|
||||||
|
@ -118,7 +118,7 @@ class ConfigTest extends BaseTest
|
||||||
* Test the setOptions function.
|
* Test the setOptions function.
|
||||||
*
|
*
|
||||||
* @return void
|
* @return void
|
||||||
* @throws Exception
|
* @throws ConfigException
|
||||||
*/
|
*/
|
||||||
public function testSetOptionsWithoutUpdate()
|
public function testSetOptionsWithoutUpdate()
|
||||||
{
|
{
|
||||||
|
@ -134,7 +134,7 @@ class ConfigTest extends BaseTest
|
||||||
*/
|
*/
|
||||||
public function testSetOptionsWithBadYoutubedl()
|
public function testSetOptionsWithBadYoutubedl()
|
||||||
{
|
{
|
||||||
$this->expectException(Exception::class);
|
$this->expectException(ConfigException::class);
|
||||||
Config::setOptions(['youtubedl' => 'foo']);
|
Config::setOptions(['youtubedl' => 'foo']);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -145,7 +145,7 @@ class ConfigTest extends BaseTest
|
||||||
*/
|
*/
|
||||||
public function testSetOptionsWithBadPython()
|
public function testSetOptionsWithBadPython()
|
||||||
{
|
{
|
||||||
$this->expectException(Exception::class);
|
$this->expectException(ConfigException::class);
|
||||||
Config::setOptions(['python' => 'foo']);
|
Config::setOptions(['python' => 'foo']);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -153,7 +153,7 @@ class ConfigTest extends BaseTest
|
||||||
* Test the getInstance function with the CONVERT and PYTHON environment variables.
|
* Test the getInstance function with the CONVERT and PYTHON environment variables.
|
||||||
*
|
*
|
||||||
* @return void
|
* @return void
|
||||||
* @throws Exception
|
* @throws ConfigException
|
||||||
*/
|
*/
|
||||||
public function testGetInstanceWithEnv()
|
public function testGetInstanceWithEnv()
|
||||||
{
|
{
|
||||||
|
|
|
@ -9,13 +9,14 @@ namespace Alltube\Test;
|
||||||
use Alltube\Controller\BaseController;
|
use Alltube\Controller\BaseController;
|
||||||
use Alltube\Controller\DownloadController;
|
use Alltube\Controller\DownloadController;
|
||||||
use Alltube\Controller\FrontController;
|
use Alltube\Controller\FrontController;
|
||||||
|
use Alltube\Exception\ConfigException;
|
||||||
use Alltube\LocaleManager;
|
use Alltube\LocaleManager;
|
||||||
use Alltube\ViewFactory;
|
use Alltube\ViewFactory;
|
||||||
use Exception;
|
|
||||||
use Slim\Container;
|
use Slim\Container;
|
||||||
use Slim\Http\Environment;
|
use Slim\Http\Environment;
|
||||||
use Slim\Http\Request;
|
use Slim\Http\Request;
|
||||||
use Slim\Http\Response;
|
use Slim\Http\Response;
|
||||||
|
use SmartyException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Abstract class used by the controller tests.
|
* Abstract class used by the controller tests.
|
||||||
|
@ -51,7 +52,7 @@ abstract class ControllerTest extends BaseTest
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Prepare tests.
|
* Prepare tests.
|
||||||
* @throws Exception
|
* @throws ConfigException|SmartyException
|
||||||
*/
|
*/
|
||||||
protected function setUp(): void
|
protected function setUp(): void
|
||||||
{
|
{
|
||||||
|
|
|
@ -6,9 +6,9 @@
|
||||||
|
|
||||||
namespace Alltube\Test;
|
namespace Alltube\Test;
|
||||||
|
|
||||||
|
use Alltube\Config;
|
||||||
|
use Alltube\Exception\ConfigException;
|
||||||
use Alltube\Stream\ConvertedPlaylistArchiveStream;
|
use Alltube\Stream\ConvertedPlaylistArchiveStream;
|
||||||
use Alltube\Video;
|
|
||||||
use Exception;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Unit tests for the ConvertedPlaylistArchiveStream class.
|
* Unit tests for the ConvertedPlaylistArchiveStream class.
|
||||||
|
@ -18,14 +18,16 @@ class ConvertedPlaylistArchiveStreamTest extends StreamTest
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* Prepare tests.
|
* Prepare tests.
|
||||||
* @throws Exception
|
* @throws ConfigException
|
||||||
*/
|
*/
|
||||||
protected function setUp(): void
|
protected function setUp(): void
|
||||||
{
|
{
|
||||||
parent::setUp();
|
parent::setUp();
|
||||||
|
|
||||||
$video = new Video('https://www.youtube.com/playlist?list=PL1j4Ff8cAqPu5iowaeUAY8lRgkfT4RybJ');
|
$config = Config::getInstance();
|
||||||
|
$downloader = $config->getDownloader();
|
||||||
|
$video = $downloader->getVideo('https://www.youtube.com/playlist?list=PL1j4Ff8cAqPu5iowaeUAY8lRgkfT4RybJ');
|
||||||
|
|
||||||
$this->stream = new ConvertedPlaylistArchiveStream($video);
|
$this->stream = new ConvertedPlaylistArchiveStream($downloader, $video);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,7 +8,11 @@ namespace Alltube\Test;
|
||||||
|
|
||||||
use Alltube\Config;
|
use Alltube\Config;
|
||||||
use Alltube\Controller\DownloadController;
|
use Alltube\Controller\DownloadController;
|
||||||
use Exception;
|
use Alltube\Exception\ConfigException;
|
||||||
|
use Alltube\Library\Exception\EmptyUrlException;
|
||||||
|
use Alltube\Library\Exception\RemuxException;
|
||||||
|
use Alltube\Library\Exception\YoutubedlException;
|
||||||
|
use SmartyException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Unit tests for the FrontController class.
|
* Unit tests for the FrontController class.
|
||||||
|
@ -18,7 +22,7 @@ class DownloadControllerTest extends ControllerTest
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* Prepare tests.
|
* Prepare tests.
|
||||||
* @throws Exception
|
* @throws ConfigException|SmartyException
|
||||||
*/
|
*/
|
||||||
protected function setUp(): void
|
protected function setUp(): void
|
||||||
{
|
{
|
||||||
|
@ -64,7 +68,7 @@ class DownloadControllerTest extends ControllerTest
|
||||||
* Test the download() function with streams enabled.
|
* Test the download() function with streams enabled.
|
||||||
*
|
*
|
||||||
* @return void
|
* @return void
|
||||||
* @throws Exception
|
* @throws ConfigException
|
||||||
*/
|
*/
|
||||||
public function testDownloadWithStream()
|
public function testDownloadWithStream()
|
||||||
{
|
{
|
||||||
|
@ -80,7 +84,7 @@ class DownloadControllerTest extends ControllerTest
|
||||||
* Test the download() function with an M3U stream.
|
* Test the download() function with an M3U stream.
|
||||||
*
|
*
|
||||||
* @return void
|
* @return void
|
||||||
* @throws Exception
|
* @throws ConfigException
|
||||||
*/
|
*/
|
||||||
public function testDownloadWithM3uStream()
|
public function testDownloadWithM3uStream()
|
||||||
{
|
{
|
||||||
|
@ -100,7 +104,7 @@ class DownloadControllerTest extends ControllerTest
|
||||||
* Test the download() function with an RTMP stream.
|
* Test the download() function with an RTMP stream.
|
||||||
*
|
*
|
||||||
* @return void
|
* @return void
|
||||||
* @throws Exception
|
* @throws ConfigException
|
||||||
*/
|
*/
|
||||||
public function testDownloadWithRtmpStream()
|
public function testDownloadWithRtmpStream()
|
||||||
{
|
{
|
||||||
|
@ -118,7 +122,7 @@ class DownloadControllerTest extends ControllerTest
|
||||||
* Test the download() function with a remuxed video.
|
* Test the download() function with a remuxed video.
|
||||||
*
|
*
|
||||||
* @return void
|
* @return void
|
||||||
* @throws Exception
|
* @throws ConfigException
|
||||||
*/
|
*/
|
||||||
public function testDownloadWithRemux()
|
public function testDownloadWithRemux()
|
||||||
{
|
{
|
||||||
|
@ -140,7 +144,8 @@ class DownloadControllerTest extends ControllerTest
|
||||||
*/
|
*/
|
||||||
public function testDownloadWithRemuxDisabled()
|
public function testDownloadWithRemuxDisabled()
|
||||||
{
|
{
|
||||||
$this->assertRequestIsServerError(
|
$this->expectException(RemuxException::class);
|
||||||
|
$this->getRequestResult(
|
||||||
'download',
|
'download',
|
||||||
[
|
[
|
||||||
'url' => 'https://www.youtube.com/watch?v=M7IpKCZ47pU',
|
'url' => 'https://www.youtube.com/watch?v=M7IpKCZ47pU',
|
||||||
|
@ -166,7 +171,8 @@ class DownloadControllerTest extends ControllerTest
|
||||||
*/
|
*/
|
||||||
public function testDownloadWithError()
|
public function testDownloadWithError()
|
||||||
{
|
{
|
||||||
$this->assertRequestIsServerError('download', ['url' => 'http://example.com/foo']);
|
$this->expectException(YoutubedlException::class);
|
||||||
|
$this->getRequestResult('download', ['url' => 'http://example.com/foo']);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -177,7 +183,8 @@ class DownloadControllerTest extends ControllerTest
|
||||||
*/
|
*/
|
||||||
public function testDownloadWithEmptyUrl()
|
public function testDownloadWithEmptyUrl()
|
||||||
{
|
{
|
||||||
$this->assertRequestIsServerError(
|
$this->expectException(EmptyUrlException::class);
|
||||||
|
$this->getRequestResult(
|
||||||
'download',
|
'download',
|
||||||
['url' => 'https://www.youtube.com/playlist?list=PLgdySZU6KUXL_8Jq5aUkyNV7wCa-4wZsC']
|
['url' => 'https://www.youtube.com/playlist?list=PLgdySZU6KUXL_8Jq5aUkyNV7wCa-4wZsC']
|
||||||
);
|
);
|
||||||
|
@ -188,7 +195,7 @@ class DownloadControllerTest extends ControllerTest
|
||||||
*
|
*
|
||||||
* @return void
|
* @return void
|
||||||
* @requires OS Linux
|
* @requires OS Linux
|
||||||
* @throws Exception
|
* @throws ConfigException
|
||||||
*/
|
*/
|
||||||
public function testDownloadWithPlaylist()
|
public function testDownloadWithPlaylist()
|
||||||
{
|
{
|
||||||
|
@ -204,7 +211,7 @@ class DownloadControllerTest extends ControllerTest
|
||||||
* Test the download() function with an advanced conversion.
|
* Test the download() function with an advanced conversion.
|
||||||
*
|
*
|
||||||
* @return void
|
* @return void
|
||||||
* @throws Exception
|
* @throws ConfigException
|
||||||
*/
|
*/
|
||||||
public function testDownloadWithAdvancedConversion()
|
public function testDownloadWithAdvancedConversion()
|
||||||
{
|
{
|
||||||
|
|
|
@ -8,9 +8,12 @@ namespace Alltube\Test;
|
||||||
|
|
||||||
use Alltube\Config;
|
use Alltube\Config;
|
||||||
use Alltube\Controller\FrontController;
|
use Alltube\Controller\FrontController;
|
||||||
|
use Alltube\Exception\ConfigException;
|
||||||
|
use Alltube\Library\Exception\AlltubeLibraryException;
|
||||||
use Exception;
|
use Exception;
|
||||||
use Slim\Http\Environment;
|
use Slim\Http\Environment;
|
||||||
use Slim\Http\Request;
|
use Slim\Http\Request;
|
||||||
|
use SmartyException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Unit tests for the FrontController class.
|
* Unit tests for the FrontController class.
|
||||||
|
@ -25,7 +28,7 @@ class FrontControllerTest extends ControllerTest
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Prepare tests.
|
* Prepare tests.
|
||||||
* @throws Exception
|
* @throws ConfigException|SmartyException
|
||||||
*/
|
*/
|
||||||
protected function setUp(): void
|
protected function setUp(): void
|
||||||
{
|
{
|
||||||
|
@ -48,7 +51,7 @@ class FrontControllerTest extends ControllerTest
|
||||||
* Test the constructor with streams enabled.
|
* Test the constructor with streams enabled.
|
||||||
*
|
*
|
||||||
* @return void
|
* @return void
|
||||||
* @throws Exception
|
* @throws ConfigException
|
||||||
*/
|
*/
|
||||||
public function testConstructorWithStream()
|
public function testConstructorWithStream()
|
||||||
{
|
{
|
||||||
|
@ -99,7 +102,7 @@ class FrontControllerTest extends ControllerTest
|
||||||
*/
|
*/
|
||||||
public function testPassword()
|
public function testPassword()
|
||||||
{
|
{
|
||||||
$this->assertRequestIsOk('password');
|
$this->assertRequestIsClientError('password');
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -128,7 +131,7 @@ class FrontControllerTest extends ControllerTest
|
||||||
*
|
*
|
||||||
* @return void
|
* @return void
|
||||||
* @requires download
|
* @requires download
|
||||||
* @throws Exception
|
* @throws ConfigException
|
||||||
*/
|
*/
|
||||||
public function testInfoWithAudio()
|
public function testInfoWithAudio()
|
||||||
{
|
{
|
||||||
|
@ -145,7 +148,7 @@ class FrontControllerTest extends ControllerTest
|
||||||
*
|
*
|
||||||
* @return void
|
* @return void
|
||||||
* @requires download
|
* @requires download
|
||||||
* @throws Exception
|
* @throws ConfigException
|
||||||
*/
|
*/
|
||||||
public function testInfoWithVimeoAudio()
|
public function testInfoWithVimeoAudio()
|
||||||
{
|
{
|
||||||
|
@ -160,7 +163,7 @@ class FrontControllerTest extends ControllerTest
|
||||||
*
|
*
|
||||||
* @return void
|
* @return void
|
||||||
* @requires download
|
* @requires download
|
||||||
* @throws Exception
|
* @throws ConfigException
|
||||||
*/
|
*/
|
||||||
public function testInfoWithUnconvertedAudio()
|
public function testInfoWithUnconvertedAudio()
|
||||||
{
|
{
|
||||||
|
@ -180,6 +183,7 @@ class FrontControllerTest extends ControllerTest
|
||||||
*
|
*
|
||||||
* @return void
|
* @return void
|
||||||
* @requires download
|
* @requires download
|
||||||
|
* @throws AlltubeLibraryException
|
||||||
*/
|
*/
|
||||||
public function testInfoWithPassword()
|
public function testInfoWithPassword()
|
||||||
{
|
{
|
||||||
|
@ -199,8 +203,8 @@ class FrontControllerTest extends ControllerTest
|
||||||
*/
|
*/
|
||||||
public function testInfoWithMissingPassword()
|
public function testInfoWithMissingPassword()
|
||||||
{
|
{
|
||||||
$this->assertRequestIsOk('info', ['url' => 'http://vimeo.com/68375962']);
|
$this->assertRequestIsClientError('info', ['url' => 'http://vimeo.com/68375962']);
|
||||||
$this->assertRequestIsOk('info', ['url' => 'http://vimeo.com/68375962', 'audio' => true]);
|
$this->assertRequestIsClientError('info', ['url' => 'http://vimeo.com/68375962', 'audio' => true]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -208,7 +212,7 @@ class FrontControllerTest extends ControllerTest
|
||||||
*
|
*
|
||||||
* @return void
|
* @return void
|
||||||
* @requires download
|
* @requires download
|
||||||
* @throws Exception
|
* @throws ConfigException
|
||||||
*/
|
*/
|
||||||
public function testInfoWithStream()
|
public function testInfoWithStream()
|
||||||
{
|
{
|
||||||
|
|
|
@ -7,7 +7,9 @@
|
||||||
namespace Alltube\Test;
|
namespace Alltube\Test;
|
||||||
|
|
||||||
use Alltube\Controller\JsonController;
|
use Alltube\Controller\JsonController;
|
||||||
use Exception;
|
use Alltube\Exception\ConfigException;
|
||||||
|
use Alltube\Library\Exception\YoutubedlException;
|
||||||
|
use SmartyException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Unit tests for the FrontController class.
|
* Unit tests for the FrontController class.
|
||||||
|
@ -16,7 +18,7 @@ class JsonControllerTest extends ControllerTest
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* Prepare tests.
|
* Prepare tests.
|
||||||
* @throws Exception
|
* @throws ConfigException|SmartyException
|
||||||
*/
|
*/
|
||||||
protected function setUp(): void
|
protected function setUp(): void
|
||||||
{
|
{
|
||||||
|
@ -44,7 +46,8 @@ class JsonControllerTest extends ControllerTest
|
||||||
*/
|
*/
|
||||||
public function testJsonWithError()
|
public function testJsonWithError()
|
||||||
{
|
{
|
||||||
$this->assertRequestIsServerError('json', ['url' => 'http://example.com/foo']);
|
$this->expectException(YoutubedlException::class);
|
||||||
|
$this->getRequestResult('json', ['url' => 'http://example.com/foo']);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -6,9 +6,9 @@
|
||||||
|
|
||||||
namespace Alltube\Test;
|
namespace Alltube\Test;
|
||||||
|
|
||||||
|
use Alltube\Config;
|
||||||
|
use Alltube\Exception\ConfigException;
|
||||||
use Alltube\Stream\PlaylistArchiveStream;
|
use Alltube\Stream\PlaylistArchiveStream;
|
||||||
use Alltube\Video;
|
|
||||||
use Exception;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Unit tests for the PlaylistArchiveStream class.
|
* Unit tests for the PlaylistArchiveStream class.
|
||||||
|
@ -18,14 +18,16 @@ class PlaylistArchiveStreamTest extends StreamTest
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* Prepare tests.
|
* Prepare tests.
|
||||||
* @throws Exception
|
* @throws ConfigException
|
||||||
*/
|
*/
|
||||||
protected function setUp(): void
|
protected function setUp(): void
|
||||||
{
|
{
|
||||||
parent::setUp();
|
parent::setUp();
|
||||||
|
|
||||||
$video = new Video('https://www.youtube.com/playlist?list=PL1j4Ff8cAqPu5iowaeUAY8lRgkfT4RybJ');
|
$config = Config::getInstance();
|
||||||
|
$downloader = $config->getDownloader();
|
||||||
|
$video = $downloader->getVideo('https://www.youtube.com/playlist?list=PL1j4Ff8cAqPu5iowaeUAY8lRgkfT4RybJ');
|
||||||
|
|
||||||
$this->stream = new PlaylistArchiveStream($video);
|
$this->stream = new PlaylistArchiveStream($downloader, $video);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,36 +6,51 @@
|
||||||
|
|
||||||
namespace Alltube\Test;
|
namespace Alltube\Test;
|
||||||
|
|
||||||
use Alltube\Video;
|
use Alltube\Config;
|
||||||
|
use Alltube\Exception\ConfigException;
|
||||||
|
use Alltube\Library\Downloader;
|
||||||
|
use Alltube\Library\Exception\AlltubeLibraryException;
|
||||||
|
use Alltube\Library\Exception\PopenStreamException;
|
||||||
|
use Alltube\Library\Video;
|
||||||
use Mockery;
|
use Mockery;
|
||||||
use phpmock\mockery\PHPMockery;
|
use phpmock\mockery\PHPMockery;
|
||||||
use Exception;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Unit tests for the Video class.
|
* Unit tests for the Video class.
|
||||||
* They are in a separate file so they can safely replace PHP functions with stubs.
|
* They are in a separate file so they can safely replace PHP functions with stubs.
|
||||||
|
*
|
||||||
|
* @requires download
|
||||||
*/
|
*/
|
||||||
class VideoStubsTest extends BaseTest
|
class VideoStubsTest extends BaseTest
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* Video URL used in many tests.
|
* Video used in many tests.
|
||||||
*
|
*
|
||||||
* @var Video
|
* @var Video
|
||||||
*/
|
*/
|
||||||
private $video;
|
private $video;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Downloader instance used in tests.
|
||||||
|
*
|
||||||
|
* @var Downloader
|
||||||
|
*/
|
||||||
|
private $downloader;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initialize properties used by test.
|
* Initialize properties used by test.
|
||||||
* @throws Exception
|
* @throws ConfigException
|
||||||
*/
|
*/
|
||||||
protected function setUp(): void
|
protected function setUp(): void
|
||||||
{
|
{
|
||||||
parent::setUp();
|
parent::setUp();
|
||||||
|
|
||||||
PHPMockery::mock('Alltube', 'popen');
|
PHPMockery::mock('Alltube\Library', 'popen');
|
||||||
PHPMockery::mock('Alltube', 'fopen');
|
PHPMockery::mock('Alltube\Library', 'fopen');
|
||||||
|
|
||||||
$this->video = new Video('https://www.youtube.com/watch?v=XJC9_JkzugE');
|
$config = Config::getInstance();
|
||||||
|
$this->downloader = $config->getDownloader();
|
||||||
|
$this->video = $this->downloader->getVideo('https://www.youtube.com/watch?v=XJC9_JkzugE');
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -52,55 +67,60 @@ class VideoStubsTest extends BaseTest
|
||||||
* Test getAudioStream function with a buggy popen.
|
* Test getAudioStream function with a buggy popen.
|
||||||
*
|
*
|
||||||
* @return void
|
* @return void
|
||||||
|
* @throws AlltubeLibraryException
|
||||||
*/
|
*/
|
||||||
public function testGetAudioStreamWithPopenError()
|
public function testGetAudioStreamWithPopenError()
|
||||||
{
|
{
|
||||||
$this->expectException(Exception::class);
|
$this->expectException(PopenStreamException::class);
|
||||||
$this->video->getAudioStream();
|
$this->downloader->getAudioStream($this->video);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test getM3uStream function with a buggy popen.
|
* Test getM3uStream function with a buggy popen.
|
||||||
*
|
*
|
||||||
* @return void
|
* @return void
|
||||||
|
* @throws AlltubeLibraryException
|
||||||
*/
|
*/
|
||||||
public function testGetM3uStreamWithPopenError()
|
public function testGetM3uStreamWithPopenError()
|
||||||
{
|
{
|
||||||
$this->expectException(Exception::class);
|
$this->expectException(PopenStreamException::class);
|
||||||
$this->video->getM3uStream();
|
$this->downloader->getM3uStream($this->video);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test getRtmpStream function with a buggy popen.
|
* Test getRtmpStream function with a buggy popen.
|
||||||
*
|
*
|
||||||
* @return void
|
* @return void
|
||||||
|
* @throws AlltubeLibraryException
|
||||||
*/
|
*/
|
||||||
public function testGetRtmpStreamWithPopenError()
|
public function testGetRtmpStreamWithPopenError()
|
||||||
{
|
{
|
||||||
$this->expectException(Exception::class);
|
$this->expectException(PopenStreamException::class);
|
||||||
$this->video->getRtmpStream();
|
$this->downloader->getRtmpStream($this->video);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test getRemuxStream function with a buggy popen.
|
* Test getRemuxStream function with a buggy popen.
|
||||||
*
|
*
|
||||||
* @return void
|
* @return void
|
||||||
|
* @throws AlltubeLibraryException
|
||||||
*/
|
*/
|
||||||
public function testGetRemuxStreamWithPopenError()
|
public function testGetRemuxStreamWithPopenError()
|
||||||
{
|
{
|
||||||
$this->expectException(Exception::class);
|
$this->expectException(PopenStreamException::class);
|
||||||
$video = $this->video->withFormat('bestvideo+bestaudio');
|
$video = $this->video->withFormat('bestvideo+bestaudio');
|
||||||
$video->getRemuxStream();
|
$this->downloader->getRemuxStream($video);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test getConvertedStream function with a buggy popen.
|
* Test getConvertedStream function with a buggy popen.
|
||||||
*
|
*
|
||||||
* @return void
|
* @return void
|
||||||
|
* @throws AlltubeLibraryException
|
||||||
*/
|
*/
|
||||||
public function testGetConvertedStreamWithPopenError()
|
public function testGetConvertedStreamWithPopenError()
|
||||||
{
|
{
|
||||||
$this->expectException(Exception::class);
|
$this->expectException(PopenStreamException::class);
|
||||||
$this->video->getConvertedStream(32, 'flv');
|
$this->downloader->getConvertedStream($this->video, 32, 'flv');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,26 +7,61 @@
|
||||||
namespace Alltube\Test;
|
namespace Alltube\Test;
|
||||||
|
|
||||||
use Alltube\Config;
|
use Alltube\Config;
|
||||||
use Alltube\Exception\EmptyUrlException;
|
use Alltube\Exception\ConfigException;
|
||||||
use Alltube\Exception\PasswordException;
|
use Alltube\Library\Downloader;
|
||||||
use Alltube\Video;
|
use Alltube\Library\Exception\AlltubeLibraryException;
|
||||||
use Exception;
|
use Alltube\Library\Exception\AvconvException;
|
||||||
|
use Alltube\Library\Exception\InvalidProtocolConversionException;
|
||||||
|
use Alltube\Library\Exception\PasswordException;
|
||||||
|
use Alltube\Library\Exception\PlaylistConversionException;
|
||||||
|
use Alltube\Library\Exception\RemuxException;
|
||||||
|
use Alltube\Library\Exception\WrongPasswordException;
|
||||||
|
use Alltube\Library\Exception\YoutubedlException;
|
||||||
|
use Alltube\Library\Video;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Unit tests for the Video class.
|
* Unit tests for the Video class.
|
||||||
* @requires download
|
* @requires download
|
||||||
|
* @todo Split Downloader and Video tests.
|
||||||
*/
|
*/
|
||||||
class VideoTest extends BaseTest
|
class VideoTest extends BaseTest
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* Downloader instance used in tests.
|
||||||
|
*
|
||||||
|
* @var Downloader
|
||||||
|
*/
|
||||||
|
private $downloader;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Video format used in tests.
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
private $format;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Prepare tests.
|
||||||
|
* @throws ConfigException
|
||||||
|
*/
|
||||||
|
protected function setUp(): void
|
||||||
|
{
|
||||||
|
parent::setUp();
|
||||||
|
|
||||||
|
$config = Config::getInstance();
|
||||||
|
$this->downloader = $config->getDownloader();
|
||||||
|
$this->format = 'best';
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test getExtractors function.
|
* Test getExtractors function.
|
||||||
*
|
*
|
||||||
* @return void
|
* @return void
|
||||||
* @throws PasswordException
|
* @throws AlltubeLibraryException
|
||||||
*/
|
*/
|
||||||
public function testGetExtractors()
|
public function testGetExtractors()
|
||||||
{
|
{
|
||||||
$this->assertContains('youtube', Video::getExtractors());
|
$this->assertContains('youtube', $this->downloader->getExtractors());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -39,8 +74,7 @@ class VideoTest extends BaseTest
|
||||||
* @param string $domain Domain
|
* @param string $domain Domain
|
||||||
*
|
*
|
||||||
* @return void
|
* @return void
|
||||||
* @throws PasswordException
|
* @throws AlltubeLibraryException
|
||||||
* @throws EmptyUrlException
|
|
||||||
* @dataProvider urlProvider
|
* @dataProvider urlProvider
|
||||||
* @dataProvider m3uUrlProvider
|
* @dataProvider m3uUrlProvider
|
||||||
* @dataProvider remuxUrlProvider
|
* @dataProvider remuxUrlProvider
|
||||||
|
@ -52,7 +86,7 @@ class VideoTest extends BaseTest
|
||||||
/* @scrutinizer ignore-unused */ $extension,
|
/* @scrutinizer ignore-unused */ $extension,
|
||||||
$domain
|
$domain
|
||||||
) {
|
) {
|
||||||
$video = new Video($url, $format);
|
$video = new Video($this->downloader, $url, $format);
|
||||||
foreach ($video->getUrl() as $videoURL) {
|
foreach ($video->getUrl() as $videoURL) {
|
||||||
$this->assertStringContainsString($domain, $videoURL);
|
$this->assertStringContainsString($domain, $videoURL);
|
||||||
}
|
}
|
||||||
|
@ -62,12 +96,11 @@ class VideoTest extends BaseTest
|
||||||
* Test getUrl function with a protected video.
|
* Test getUrl function with a protected video.
|
||||||
*
|
*
|
||||||
* @return void
|
* @return void
|
||||||
* @throws EmptyUrlException
|
* @throws AlltubeLibraryException
|
||||||
* @throws PasswordException
|
|
||||||
*/
|
*/
|
||||||
public function testgetUrlWithPassword()
|
public function testgetUrlWithPassword()
|
||||||
{
|
{
|
||||||
$video = new Video('http://vimeo.com/68375962', 'best', 'youtube-dl');
|
$video = new Video($this->downloader, 'http://vimeo.com/68375962', 'best', 'youtube-dl');
|
||||||
foreach ($video->getUrl() as $videoURL) {
|
foreach ($video->getUrl() as $videoURL) {
|
||||||
$this->assertStringContainsString('vimeocdn.com', $videoURL);
|
$this->assertStringContainsString('vimeocdn.com', $videoURL);
|
||||||
}
|
}
|
||||||
|
@ -77,13 +110,12 @@ class VideoTest extends BaseTest
|
||||||
* Test getUrl function with a protected video and no password.
|
* Test getUrl function with a protected video and no password.
|
||||||
*
|
*
|
||||||
* @return void
|
* @return void
|
||||||
* @throws EmptyUrlException
|
* @throws AlltubeLibraryException
|
||||||
* @throws PasswordException
|
|
||||||
*/
|
*/
|
||||||
public function testgetUrlWithMissingPassword()
|
public function testgetUrlWithMissingPassword()
|
||||||
{
|
{
|
||||||
$this->expectException(Exception::class);
|
$this->expectException(PasswordException::class);
|
||||||
$video = new Video('http://vimeo.com/68375962');
|
$video = new Video($this->downloader, 'http://vimeo.com/68375962', $this->format);
|
||||||
$video->getUrl();
|
$video->getUrl();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -91,13 +123,12 @@ class VideoTest extends BaseTest
|
||||||
* Test getUrl function with a protected video and a wrong password.
|
* Test getUrl function with a protected video and a wrong password.
|
||||||
*
|
*
|
||||||
* @return void
|
* @return void
|
||||||
* @throws EmptyUrlException
|
* @throws AlltubeLibraryException
|
||||||
* @throws PasswordException
|
|
||||||
*/
|
*/
|
||||||
public function testgetUrlWithWrongPassword()
|
public function testgetUrlWithWrongPassword()
|
||||||
{
|
{
|
||||||
$this->expectException(Exception::class);
|
$this->expectException(WrongPasswordException::class);
|
||||||
$video = new Video('http://vimeo.com/68375962', 'best', 'foo');
|
$video = new Video($this->downloader, 'http://vimeo.com/68375962', 'best', 'foo');
|
||||||
$video->getUrl();
|
$video->getUrl();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -107,14 +138,13 @@ class VideoTest extends BaseTest
|
||||||
* @param string $url URL
|
* @param string $url URL
|
||||||
*
|
*
|
||||||
* @return void
|
* @return void
|
||||||
* @throws EmptyUrlException
|
* @throws AlltubeLibraryException
|
||||||
* @throws PasswordException
|
* @dataProvider ErrorUrlProvider
|
||||||
* @dataProvider ErrorUrlProvider
|
|
||||||
*/
|
*/
|
||||||
public function testgetUrlError($url)
|
public function testgetUrlError($url)
|
||||||
{
|
{
|
||||||
$this->expectException(Exception::class);
|
$this->expectException(YoutubedlException::class);
|
||||||
$video = new Video($url);
|
$video = new Video($this->downloader, $url, $this->format);
|
||||||
$video->getUrl();
|
$video->getUrl();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -224,13 +254,13 @@ class VideoTest extends BaseTest
|
||||||
* @param string $format Format
|
* @param string $format Format
|
||||||
*
|
*
|
||||||
* @return void
|
* @return void
|
||||||
|
* @throws AlltubeLibraryException
|
||||||
* @dataProvider urlProvider
|
* @dataProvider urlProvider
|
||||||
* @dataProvider m3uUrlProvider
|
* @dataProvider m3uUrlProvider
|
||||||
* @throws PasswordException
|
|
||||||
*/
|
*/
|
||||||
public function testGetJson($url, $format)
|
public function testGetJson($url, $format)
|
||||||
{
|
{
|
||||||
$video = new Video($url, $format);
|
$video = new Video($this->downloader, $url, $format);
|
||||||
$info = $video->getJson();
|
$info = $video->getJson();
|
||||||
$this->assertObjectHasAttribute('webpage_url', $info);
|
$this->assertObjectHasAttribute('webpage_url', $info);
|
||||||
$this->assertObjectHasAttribute('url', $info);
|
$this->assertObjectHasAttribute('url', $info);
|
||||||
|
@ -246,13 +276,13 @@ class VideoTest extends BaseTest
|
||||||
* @param string $url URL
|
* @param string $url URL
|
||||||
*
|
*
|
||||||
* @return void
|
* @return void
|
||||||
* @dataProvider ErrorURLProvider
|
* @throws AlltubeLibraryException
|
||||||
* @throws PasswordException
|
* @dataProvider ErrorURLProvider
|
||||||
*/
|
*/
|
||||||
public function testGetJsonError($url)
|
public function testGetJsonError($url)
|
||||||
{
|
{
|
||||||
$this->expectException(Exception::class);
|
$this->expectException(YoutubedlException::class);
|
||||||
$video = new Video($url);
|
$video = new Video($this->downloader, $url, $this->format);
|
||||||
$video->getJson();
|
$video->getJson();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -265,14 +295,14 @@ class VideoTest extends BaseTest
|
||||||
* @param string $extension File extension
|
* @param string $extension File extension
|
||||||
*
|
*
|
||||||
* @return void
|
* @return void
|
||||||
|
* @throws AlltubeLibraryException
|
||||||
* @dataProvider urlProvider
|
* @dataProvider urlProvider
|
||||||
* @dataProvider m3uUrlProvider
|
* @dataProvider m3uUrlProvider
|
||||||
* @dataProvider remuxUrlProvider
|
* @dataProvider remuxUrlProvider
|
||||||
* @throws PasswordException
|
|
||||||
*/
|
*/
|
||||||
public function testGetFilename($url, $format, $filename, $extension)
|
public function testGetFilename($url, $format, $filename, $extension)
|
||||||
{
|
{
|
||||||
$video = new Video($url, $format);
|
$video = new Video($this->downloader, $url, $format);
|
||||||
$this->assertEquals($video->getFilename(), $filename . '.' . $extension);
|
$this->assertEquals($video->getFilename(), $filename . '.' . $extension);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -282,13 +312,13 @@ class VideoTest extends BaseTest
|
||||||
* @param string $url URL
|
* @param string $url URL
|
||||||
*
|
*
|
||||||
* @return void
|
* @return void
|
||||||
* @dataProvider ErrorUrlProvider
|
* @throws AlltubeLibraryException
|
||||||
* @throws PasswordException
|
* @dataProvider ErrorUrlProvider
|
||||||
*/
|
*/
|
||||||
public function testGetFilenameError($url)
|
public function testGetFilenameError($url)
|
||||||
{
|
{
|
||||||
$this->expectException(Exception::class);
|
$this->expectException(YoutubedlException::class);
|
||||||
$video = new Video($url);
|
$video = new Video($this->downloader, $url, $this->format);
|
||||||
$video->getFilename();
|
$video->getFilename();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -300,73 +330,80 @@ class VideoTest extends BaseTest
|
||||||
*
|
*
|
||||||
* @return void
|
* @return void
|
||||||
* @dataProvider urlProvider
|
* @dataProvider urlProvider
|
||||||
* @throws Exception
|
* @throws AlltubeLibraryException
|
||||||
*/
|
*/
|
||||||
public function testGetAudioStream($url, $format)
|
public function testGetAudioStream($url, $format)
|
||||||
{
|
{
|
||||||
$video = new Video($url, $format);
|
$video = new Video($this->downloader, $url, $format);
|
||||||
$this->assertStream($video->getAudioStream());
|
$this->assertStream($this->downloader->getAudioStream($video));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test getAudioStream function without avconv.
|
* Test getAudioStream function without ffmpeg.
|
||||||
*
|
*
|
||||||
* @param string $url URL
|
* @param string $url URL
|
||||||
* @param string $format Format
|
* @param string $format Format
|
||||||
*
|
*
|
||||||
* @return void
|
* @return void
|
||||||
* @dataProvider urlProvider
|
* @throws AlltubeLibraryException|ConfigException
|
||||||
|
* @dataProvider urlProvider
|
||||||
*/
|
*/
|
||||||
public function testGetAudioStreamAvconvError($url, $format)
|
public function testGetAudioStreamFfmpegError($url, $format)
|
||||||
{
|
{
|
||||||
$this->expectException(Exception::class);
|
$this->expectException(AvconvException::class);
|
||||||
Config::setOptions(['avconv' => 'foobar']);
|
Config::setOptions(['ffmpeg' => 'foobar']);
|
||||||
|
$config = Config::getInstance();
|
||||||
|
$downloader = $config->getDownloader();
|
||||||
|
|
||||||
$video = new Video($url, $format);
|
$video = new Video($this->downloader, $url, $format, $this->format);
|
||||||
$video->getAudioStream();
|
$downloader->getAudioStream($video);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test getAudioStream function with a M3U8 file.
|
* Test getAudioStream function with a M3U8 file.
|
||||||
*
|
*
|
||||||
* @param string $url URL
|
* @param string $url URL
|
||||||
* @param string $format Format
|
* @param string $format Format
|
||||||
*
|
*
|
||||||
* @return void
|
* @return void
|
||||||
|
* @throws AlltubeLibraryException
|
||||||
* @dataProvider m3uUrlProvider
|
* @dataProvider m3uUrlProvider
|
||||||
*/
|
*/
|
||||||
public function testGetAudioStreamM3uError($url, $format)
|
public function testGetAudioStreamM3uError($url, $format)
|
||||||
{
|
{
|
||||||
$this->expectException(Exception::class);
|
$this->expectException(InvalidProtocolConversionException::class);
|
||||||
$video = new Video($url, $format);
|
$video = new Video($this->downloader, $url, $format);
|
||||||
$video->getAudioStream();
|
$this->downloader->getAudioStream($video);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test getAudioStream function with a DASH URL.
|
* Test getAudioStream function with a DASH URL.
|
||||||
*
|
*
|
||||||
* @return void
|
* @return void
|
||||||
|
* @throws AlltubeLibraryException
|
||||||
*/
|
*/
|
||||||
public function testGetAudioStreamDashError()
|
public function testGetAudioStreamDashError()
|
||||||
{
|
{
|
||||||
$this->expectException(Exception::class);
|
$this->expectException(InvalidProtocolConversionException::class);
|
||||||
$video = new Video('https://vimeo.com/251997032', 'bestaudio/best');
|
$video = new Video($this->downloader, 'https://vimeo.com/251997032', 'bestaudio/best');
|
||||||
$video->getAudioStream();
|
$this->downloader->getAudioStream($video);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test getAudioStream function with a playlist.
|
* Test getAudioStream function with a playlist.
|
||||||
*
|
*
|
||||||
* @return void
|
* @return void
|
||||||
|
* @throws AlltubeLibraryException
|
||||||
*/
|
*/
|
||||||
public function testGetAudioStreamPlaylistError()
|
public function testGetAudioStreamPlaylistError()
|
||||||
{
|
{
|
||||||
$this->expectException(Exception::class);
|
$this->expectException(PlaylistConversionException::class);
|
||||||
$video = new Video(
|
$video = new Video(
|
||||||
|
$this->downloader,
|
||||||
'https://www.youtube.com/playlist?list=PLgdySZU6KUXL_8Jq5aUkyNV7wCa-4wZsC',
|
'https://www.youtube.com/playlist?list=PLgdySZU6KUXL_8Jq5aUkyNV7wCa-4wZsC',
|
||||||
'best'
|
'best'
|
||||||
);
|
);
|
||||||
$video->getAudioStream();
|
$this->downloader->getAudioStream($video);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -390,12 +427,12 @@ class VideoTest extends BaseTest
|
||||||
*
|
*
|
||||||
* @return void
|
* @return void
|
||||||
* @dataProvider m3uUrlProvider
|
* @dataProvider m3uUrlProvider
|
||||||
* @throws Exception
|
* @throws AlltubeLibraryException
|
||||||
*/
|
*/
|
||||||
public function testGetM3uStream($url, $format)
|
public function testGetM3uStream($url, $format)
|
||||||
{
|
{
|
||||||
$video = new Video($url, $format);
|
$video = new Video($this->downloader, $url, $format);
|
||||||
$this->assertStream($video->getM3uStream());
|
$this->assertStream($this->downloader->getM3uStream($video));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -406,28 +443,29 @@ class VideoTest extends BaseTest
|
||||||
*
|
*
|
||||||
* @return void
|
* @return void
|
||||||
* @dataProvider remuxUrlProvider
|
* @dataProvider remuxUrlProvider
|
||||||
* @throws Exception
|
* @throws AlltubeLibraryException
|
||||||
*/
|
*/
|
||||||
public function testGetRemuxStream($url, $format)
|
public function testGetRemuxStream($url, $format)
|
||||||
{
|
{
|
||||||
$video = new Video($url, $format);
|
$video = new Video($this->downloader, $url, $format);
|
||||||
$this->assertStream($video->getRemuxStream());
|
$this->assertStream($this->downloader->getRemuxStream($video));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test getRemuxStream function with a video with only one URL.
|
* Test getRemuxStream function with a video with only one URL.
|
||||||
*
|
*
|
||||||
* @param string $url URL
|
* @param string $url URL
|
||||||
* @param string $format Format
|
* @param string $format Format
|
||||||
*
|
*
|
||||||
* @return void
|
* @return void
|
||||||
|
* @throws AlltubeLibraryException
|
||||||
* @dataProvider urlProvider
|
* @dataProvider urlProvider
|
||||||
*/
|
*/
|
||||||
public function testGetRemuxStreamWithWrongVideo($url, $format)
|
public function testGetRemuxStreamWithWrongVideo($url, $format)
|
||||||
{
|
{
|
||||||
$this->expectException(Exception::class);
|
$this->expectException(RemuxException::class);
|
||||||
$video = new Video($url, $format);
|
$video = new Video($this->downloader, $url, $format);
|
||||||
$video->getRemuxStream();
|
$this->downloader->getRemuxStream($video);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -437,65 +475,69 @@ class VideoTest extends BaseTest
|
||||||
* @param string $format Format
|
* @param string $format Format
|
||||||
*
|
*
|
||||||
* @return void
|
* @return void
|
||||||
|
* @throws AlltubeLibraryException
|
||||||
* @dataProvider rtmpUrlProvider
|
* @dataProvider rtmpUrlProvider
|
||||||
* @throws Exception
|
|
||||||
*/
|
*/
|
||||||
public function testGetRtmpStream($url, $format)
|
public function testGetRtmpStream($url, $format)
|
||||||
{
|
{
|
||||||
$this->markTestIncomplete('We need to find another RTMP video.');
|
$this->markTestIncomplete('We need to find another RTMP video.');
|
||||||
|
|
||||||
$video = new Video($url, $format);
|
$video = new Video($this->downloader, $url, $format);
|
||||||
|
|
||||||
$this->assertStream($video->getRtmpStream());
|
$this->assertStream($this->downloader->getRtmpStream($video));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test getM3uStream function without avconv.
|
* Test getM3uStream function without ffmpeg.
|
||||||
*
|
*
|
||||||
* @param string $url URL
|
* @param string $url URL
|
||||||
* @param string $format Format
|
* @param string $format Format
|
||||||
*
|
*
|
||||||
* @return void
|
* @return void
|
||||||
|
* @throws AlltubeLibraryException|ConfigException
|
||||||
* @dataProvider m3uUrlProvider
|
* @dataProvider m3uUrlProvider
|
||||||
*/
|
*/
|
||||||
public function testGetM3uStreamAvconvError($url, $format)
|
public function testGetM3uStreamFfmpegError($url, $format)
|
||||||
{
|
{
|
||||||
$this->expectException(Exception::class);
|
$this->expectException(AvconvException::class);
|
||||||
Config::setOptions(['avconv' => 'foobar']);
|
Config::setOptions(['ffmpeg' => 'foobar']);
|
||||||
|
$config = Config::getInstance();
|
||||||
|
$downloader = $config->getDownloader();
|
||||||
|
|
||||||
$video = new Video($url, $format);
|
$video = new Video($downloader, $url, $format);
|
||||||
$video->getM3uStream();
|
$downloader->getM3uStream($video);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test getConvertedStream function without avconv.
|
* Test getConvertedStream function without ffmpeg.
|
||||||
*
|
*
|
||||||
* @param string $url URL
|
* @param string $url URL
|
||||||
* @param string $format Format
|
* @param string $format Format
|
||||||
*
|
*
|
||||||
* @return void
|
* @return void
|
||||||
* @dataProvider urlProvider
|
* @dataProvider urlProvider
|
||||||
* @throws Exception
|
* @throws AlltubeLibraryException
|
||||||
*/
|
*/
|
||||||
public function testGetConvertedStream($url, $format)
|
public function testGetConvertedStream($url, $format)
|
||||||
{
|
{
|
||||||
$video = new Video($url, $format);
|
$video = new Video($this->downloader, $url, $format);
|
||||||
$this->assertStream($video->getConvertedStream(32, 'flv'));
|
$this->assertStream($this->downloader->getConvertedStream($video, 32, 'flv'));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test getConvertedStream function with a M3U8 file.
|
* Test getConvertedStream function with a M3U8 file.
|
||||||
*
|
*
|
||||||
* @param string $url URL
|
* @param string $url URL
|
||||||
* @param string $format Format
|
* @param string $format Format
|
||||||
*
|
*
|
||||||
* @return void
|
* @return void
|
||||||
|
* @throws AlltubeLibraryException
|
||||||
* @dataProvider m3uUrlProvider
|
* @dataProvider m3uUrlProvider
|
||||||
*/
|
*/
|
||||||
public function testGetConvertedStreamM3uError($url, $format)
|
public function testGetConvertedStreamM3uError($url, $format)
|
||||||
{
|
{
|
||||||
$this->expectException(Exception::class);
|
$this->expectException(InvalidProtocolConversionException::class);
|
||||||
$video = new Video($url, $format);
|
$video = new Video($this->downloader, $url, $format);
|
||||||
$video->getConvertedStream(32, 'flv');
|
$this->downloader->getConvertedStream($video, 32, 'flv');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,9 +6,10 @@
|
||||||
|
|
||||||
namespace Alltube\Test;
|
namespace Alltube\Test;
|
||||||
|
|
||||||
|
use Alltube\Config;
|
||||||
|
use Alltube\Exception\ConfigException;
|
||||||
|
use Alltube\Library\Exception\AlltubeLibraryException;
|
||||||
use Alltube\Stream\YoutubeChunkStream;
|
use Alltube\Stream\YoutubeChunkStream;
|
||||||
use Alltube\Video;
|
|
||||||
use Exception;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Unit tests for the YoutubeChunkStream class.
|
* Unit tests for the YoutubeChunkStream class.
|
||||||
|
@ -18,14 +19,17 @@ class YoutubeChunkStreamTest extends StreamTest
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* Prepare tests.
|
* Prepare tests.
|
||||||
* @throws Exception
|
* @throws ConfigException
|
||||||
|
* @throws AlltubeLibraryException
|
||||||
*/
|
*/
|
||||||
protected function setUp(): void
|
protected function setUp(): void
|
||||||
{
|
{
|
||||||
parent::setUp();
|
parent::setUp();
|
||||||
|
|
||||||
$video = new Video('https://www.youtube.com/watch?v=dQw4w9WgXcQ');
|
$config = Config::getInstance();
|
||||||
|
$downloader = $config->getDownloader();
|
||||||
|
$video = $downloader->getVideo('https://www.youtube.com/watch?v=dQw4w9WgXcQ');
|
||||||
|
|
||||||
$this->stream = new YoutubeChunkStream($video->getHttpResponse());
|
$this->stream = new YoutubeChunkStream($downloader->getHttpResponse($video));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,9 +6,10 @@
|
||||||
|
|
||||||
namespace Alltube\Test;
|
namespace Alltube\Test;
|
||||||
|
|
||||||
|
use Alltube\Config;
|
||||||
|
use Alltube\Exception\ConfigException;
|
||||||
|
use Alltube\Library\Exception\AlltubeLibraryException;
|
||||||
use Alltube\Stream\YoutubeStream;
|
use Alltube\Stream\YoutubeStream;
|
||||||
use Alltube\Video;
|
|
||||||
use Exception;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Unit tests for the YoutubeStream class.
|
* Unit tests for the YoutubeStream class.
|
||||||
|
@ -18,15 +19,17 @@ class YoutubeStreamTest extends StreamTest
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* Prepare tests.
|
* Prepare tests.
|
||||||
* @throws Exception
|
* @throws ConfigException|AlltubeLibraryException
|
||||||
*/
|
*/
|
||||||
protected function setUp(): void
|
protected function setUp(): void
|
||||||
{
|
{
|
||||||
parent::setUp();
|
parent::setUp();
|
||||||
|
|
||||||
$video = new Video('https://www.youtube.com/watch?v=dQw4w9WgXcQ', '135');
|
$config = Config::getInstance();
|
||||||
|
$downloader = $config->getDownloader();
|
||||||
|
$video = $downloader->getVideo('https://www.youtube.com/watch?v=dQw4w9WgXcQ', '135');
|
||||||
|
|
||||||
$this->stream = new YoutubeStream($video);
|
$this->stream = new YoutubeStream($downloader, $video);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue