Merge branch 'release-3.0.0'

This commit is contained in:
Pierre Rudloff 2021-04-20 23:16:45 +02:00
commit eeda434b2f
35 changed files with 846 additions and 1066 deletions

View File

@ -1,7 +1,5 @@
# AllTube Download
[![Donate using Liberapay](https://liberapay.com/assets/widgets/donate.svg)](https://liberapay.com/Rudloff/donate)
HTML GUI for youtube-dl ([alltubedownload.net](http://alltubedownload.net/))
![Screenshot](img/screenshot.png "AllTube GUI screenshot")

View File

@ -8,6 +8,7 @@ use Alltube\Controller\JsonController;
use Alltube\Exception\ConfigException;
use Alltube\Exception\DependencyException;
use Alltube\Factory\ConfigFactory;
use Alltube\Factory\DebugBarFactory;
use Alltube\Factory\LocaleManagerFactory;
use Alltube\Factory\LoggerFactory;
use Alltube\Factory\SessionFactory;
@ -16,6 +17,7 @@ use Alltube\Middleware\CspMiddleware;
use Alltube\Middleware\LinkHeaderMiddleware;
use Alltube\Middleware\LocaleMiddleware;
use Alltube\Middleware\RouterPathMiddleware;
use DebugBar\DebugBarException;
use Slim\Container;
use SmartyException;
@ -26,6 +28,7 @@ class App extends \Slim\App
* @throws ConfigException
* @throws DependencyException
* @throws SmartyException
* @throws DebugBarException
*/
public function __construct()
{
@ -34,6 +37,8 @@ class App extends \Slim\App
/** @var Container $container */
$container = $this->getContainer();
$container['root_path'] = $this->getRootPath();
// Config.
$container['config'] = ConfigFactory::create($container);
@ -43,12 +48,17 @@ class App extends \Slim\App
// Locales.
$container['locale'] = LocaleManagerFactory::create($container);
// Smarty.
$container['view'] = ViewFactory::create($container);
// Logger.
$container['logger'] = LoggerFactory::create($container);
if ($container->get('config')->debug) {
// Debug bar.
$container['debugbar'] = DebugBarFactory::create($container);
}
// Smarty.
$container['view'] = ViewFactory::create($container);
// Middlewares.
$this->add(new LocaleMiddleware($container));
$this->add(new CspMiddleware($container));
@ -102,4 +112,17 @@ class App extends \Slim\App
[$jsonController, 'json']
)->setName('json');
}
/**
* @return string|null
*/
private function getRootPath(): ?string
{
// realpath() can return false but we prefer using null.
if ($rootPath = realpath(__DIR__ . '/../')) {
return $rootPath;
}
return null;
}
}

View File

@ -187,7 +187,7 @@ class Config
*
* @return string
*/
public static function addHttpToFormat(string $format)
public static function addHttpToFormat(string $format): string
{
$newFormat = [];
foreach (explode('/', $format) as $subformat) {
@ -266,7 +266,7 @@ class Config
* @return Config
* @throws ConfigException
*/
public static function fromFile(string $file)
public static function fromFile(string $file): Config
{
if (is_file($file)) {
return new self(Yaml::parse(strval(file_get_contents($file))));
@ -293,7 +293,7 @@ class Config
*
* @return Downloader
*/
public function getDownloader()
public function getDownloader(): Downloader
{
return new Downloader(
$this->youtubedl,
@ -308,7 +308,7 @@ class Config
/**
* @return string
*/
public function getAppVersion()
public function getAppVersion(): string
{
$version = PrettyVersions::getRootPackageVersion();

View File

@ -11,8 +11,8 @@ use Alltube\Library\Downloader;
use Alltube\Library\Video;
use Alltube\LocaleManager;
use Aura\Session\Segment;
use Consolidation\Log\Logger;
use Psr\Container\ContainerInterface;
use Psr\Log\LoggerInterface;
use Slim\Http\Request;
use Slim\Http\Response;
use Slim\Router;
@ -72,7 +72,7 @@ abstract class BaseController
protected $downloader;
/**
* @var Logger
* @var LoggerInterface
*/
protected $logger;
@ -111,7 +111,7 @@ abstract class BaseController
*
* @return string format
*/
protected function getFormat(Request $request)
protected function getFormat(Request $request): string
{
$format = $request->getQueryParam('format');
if (!isset($format)) {
@ -126,9 +126,9 @@ abstract class BaseController
*
* @param Request $request PSR-7 request
*
* @return string Password
* @return string|null Password
*/
protected function getPassword(Request $request)
protected function getPassword(Request $request): ?string
{
$url = $request->getQueryParam('url');
@ -151,7 +151,7 @@ abstract class BaseController
*
* @return Response HTTP response
*/
protected function displayError(Request $request, Response $response, string $message)
protected function displayError(Request $request, Response $response, string $message): Response
{
$controller = new FrontController($this->container);

View File

@ -38,7 +38,7 @@ class DownloadController extends BaseController
* @return Response HTTP response
* @throws AlltubeLibraryException
*/
public function download(Request $request, Response $response)
public function download(Request $request, Response $response): Response
{
$url = $request->getQueryParam('url');
@ -99,7 +99,7 @@ class DownloadController extends BaseController
* @return Response HTTP response
* @throws AlltubeLibraryException
*/
private function getConvertedAudioResponse(Request $request, Response $response)
private function getConvertedAudioResponse(Request $request, Response $response): Response
{
$from = null;
$to = null;
@ -135,7 +135,7 @@ class DownloadController extends BaseController
* @throws PasswordException
* @throws WrongPasswordException
*/
private function getAudioResponse(Request $request, Response $response)
private function getAudioResponse(Request $request, Response $response): Response
{
if (!empty($request->getQueryParam('from')) || !empty($request->getQueryParam('to'))) {
// Force convert when we need to seek.
@ -174,7 +174,7 @@ class DownloadController extends BaseController
* @return Response HTTP response
* @throws AlltubeLibraryException
*/
private function getStream(Request $request, Response $response)
private function getStream(Request $request, Response $response): Response
{
if (isset($this->video->entries)) {
if ($this->config->convert && $request->getQueryParam('audio')) {
@ -240,7 +240,7 @@ class DownloadController extends BaseController
* @return Response HTTP response
* @throws AlltubeLibraryException
*/
private function getRemuxStream(Request $request, Response $response)
private function getRemuxStream(Request $request, Response $response): Response
{
if (!$this->config->remux) {
throw new RemuxException('You need to enable remux mode to merge two formats.');
@ -267,7 +267,7 @@ class DownloadController extends BaseController
* @return Response HTTP response
* @throws AlltubeLibraryException
*/
private function getDownloadResponse(Request $request, Response $response)
private function getDownloadResponse(Request $request, Response $response): Response
{
try {
$videoUrls = $this->video->getUrl();
@ -306,7 +306,7 @@ class DownloadController extends BaseController
* @throws YoutubedlException
* @throws PopenStreamException
*/
private function getConvertedResponse(Request $request, Response $response)
private function getConvertedResponse(Request $request, Response $response): Response
{
$response = $response->withHeader(
'Content-Disposition',

View File

@ -52,7 +52,7 @@ class FrontController extends BaseController
*
* @return Response HTTP response
*/
public function index(Request $request, Response $response)
public function index(Request $request, Response $response): Response
{
$this->view->render(
$response,
@ -78,7 +78,7 @@ class FrontController extends BaseController
*
* @return Response
*/
public function locale(Request $request, Response $response, array $data)
public function locale(Request $request, Response $response, array $data): Response
{
$this->localeManager->setLocale(new Locale($data['locale']));
@ -94,7 +94,7 @@ class FrontController extends BaseController
* @return Response HTTP response
* @throws AlltubeLibraryException
*/
public function extractors(Request $request, Response $response)
public function extractors(Request $request, Response $response): Response
{
$this->view->render(
$response,
@ -119,7 +119,7 @@ class FrontController extends BaseController
*
* @return Response HTTP response
*/
public function password(Request $request, Response $response)
public function password(Request $request, Response $response): Response
{
$this->view->render(
$response,
@ -199,7 +199,7 @@ class FrontController extends BaseController
* @return Response HTTP response
* @throws AlltubeLibraryException
*/
public function info(Request $request, Response $response)
public function info(Request $request, Response $response): Response
{
$url = $request->getQueryParam('url') ?: $request->getQueryParam('v');
@ -228,7 +228,7 @@ class FrontController extends BaseController
*
* @return Response HTTP response
*/
protected function displayError(Request $request, Response $response, string $message)
protected function displayError(Request $request, Response $response, string $message): Response
{
$this->view->render(
$response,
@ -248,7 +248,7 @@ class FrontController extends BaseController
* @param Response $response
* @return Response
*/
public function notFound(Request $request, Response $response)
public function notFound(Request $request, Response $response): Response
{
return $this->displayError($request, $response, $this->localeManager->t('Page not found'))
->withStatus(StatusCode::HTTP_NOT_FOUND);
@ -259,7 +259,7 @@ class FrontController extends BaseController
* @param Response $response
* @return Response
*/
public function notAllowed(Request $request, Response $response)
public function notAllowed(Request $request, Response $response): Response
{
return $this->displayError($request, $response, $this->localeManager->t('Method not allowed'))
->withStatus(StatusCode::HTTP_METHOD_NOT_ALLOWED);
@ -274,7 +274,7 @@ class FrontController extends BaseController
*
* @return Response HTTP response
*/
public function error(Request $request, Response $response, Throwable $error)
public function error(Request $request, Response $response, Throwable $error): Response
{
$this->logger->error($error);
@ -285,7 +285,7 @@ class FrontController extends BaseController
$response = $cspMiddleware->applyHeader($response);
if ($this->config->debug) {
$renderer = new HtmlErrorRenderer(true);
$renderer = new HtmlErrorRenderer(true, null, null, $this->container->get('root_path'));
$exception = $renderer->render($error);
$response->getBody()->write($exception->getAsString());

View File

@ -25,7 +25,7 @@ class JsonController extends BaseController
* @return Response HTTP response
* @throws AlltubeLibraryException
*/
public function json(Request $request, Response $response)
public function json(Request $request, Response $response): Response
{
$url = $request->getQueryParam('url');

View File

@ -23,7 +23,7 @@ class ErrorHandler
if (class_exists(HtmlErrorRenderer::class)) {
// If dev dependencies are loaded, we can use symfony/error-handler.
$renderer = new HtmlErrorRenderer(true);
$renderer = new HtmlErrorRenderer(true, null, null, dirname(__DIR__));
$exception = $renderer->render($e);
http_response_code($exception->getStatusCode());

View File

@ -20,9 +20,9 @@ class ConfigFactory
* @return Config
* @throws ConfigException
*/
public static function create(Container $container)
public static function create(Container $container): Config
{
$configPath = __DIR__ . '/../../config/config.yml';
$configPath = $container->get('root_path') . '/config/config.yml';
if (is_file($configPath)) {
$config = Config::fromFile($configPath);
} else {

View File

@ -0,0 +1,48 @@
<?php
namespace Alltube\Factory;
use DebugBar\DataCollector\ConfigCollector;
use DebugBar\DataCollector\MemoryCollector;
use DebugBar\DataCollector\MessagesCollector;
use DebugBar\DataCollector\PhpInfoCollector;
use DebugBar\DataCollector\RequestDataCollector;
use DebugBar\DebugBar;
use DebugBar\DebugBarException;
use Kitchenu\Debugbar\DataCollector\SlimRouteCollector;
use Slim\Container;
/**
* Class DebugBarFactory
* @package Alltube\Factory
*/
class DebugBarFactory
{
/**
* @param Container $container
* @return DebugBar
* @throws DebugBarException
*/
public static function create(Container $container): DebugBar
{
$debugBar = new DebugBar();
$requestCollector = new RequestDataCollector();
$configCollector = new ConfigCollector(get_object_vars($container->get('config')));
$debugBar->addCollector(new PhpInfoCollector())
->addCollector(new MessagesCollector())
->addCollector($requestCollector)
->addCollector(new MemoryCollector())
->addCollector($configCollector)
->addCollector(new SlimRouteCollector($container->get('router'), $container->get('request')));
$container->get('logger')->add('debugbar', $debugBar->getCollector('messages'));
$requestCollector->useHtmlVarDumper();
$configCollector->useHtmlVarDumper();
return $debugBar;
}
}

View File

@ -15,10 +15,10 @@ class LocaleManagerFactory
/**
* @param Container $container
* @return LocaleManager|null
* @return LocaleManager
* @throws DependencyException
*/
public static function create(Container $container)
public static function create(Container $container): LocaleManager
{
if (!class_exists('Locale')) {
throw new DependencyException('You need to install the intl extension for PHP.');

View File

@ -3,6 +3,7 @@
namespace Alltube\Factory;
use Consolidation\Log\Logger;
use Consolidation\Log\LoggerManager;
use Consolidation\Log\LogOutputStyler;
use Slim\Container;
use Symfony\Component\Console\Output\ConsoleOutput;
@ -16,9 +17,9 @@ class LoggerFactory
/**
* @param Container $container
* @return Logger
* @return LoggerManager
*/
public static function create(Container $container)
public static function create(Container $container): LoggerManager
{
$config = $container->get('config');
if ($config->debug) {
@ -27,9 +28,13 @@ class LoggerFactory
$verbosity = ConsoleOutput::VERBOSITY_NORMAL;
}
$loggerManager = new LoggerManager();
$logger = new Logger(new ConsoleOutput($verbosity));
$logger->setLogOutputStyler(new LogOutputStyler());
return $logger;
$loggerManager->add('default', $logger);
return $loggerManager;
}
}

View File

@ -21,7 +21,7 @@ class SessionFactory
* @param Container $container
* @return Session
*/
public static function create(Container $container)
public static function create(Container $container): Session
{
$session_factory = new \Aura\Session\SessionFactory();
$session = $session_factory->newInstance($_COOKIE);

View File

@ -7,6 +7,7 @@
namespace Alltube\Factory;
use Alltube\LocaleManager;
use Junker\DebugBar\Bridge\SmartyCollector;
use Psr\Container\ContainerInterface;
use Slim\Http\Request;
use Slim\Http\Uri;
@ -26,7 +27,7 @@ class ViewFactory
*
* @return string URL
*/
private static function getCanonicalUrl(Request $request)
private static function getCanonicalUrl(Request $request): string
{
/** @var Uri $uri */
$uri = $request->getUri();
@ -45,13 +46,13 @@ class ViewFactory
* @return Smarty
* @throws SmartyException
*/
public static function create(ContainerInterface $container, Request $request = null)
public static function create(ContainerInterface $container, Request $request = null): Smarty
{
if (!isset($request)) {
$request = $container->get('request');
}
$view = new Smarty(__DIR__ . '/../../templates/');
$view = new Smarty($container->get('root_path') . '/templates/');
/** @var Uri $uri */
$uri = $request->getUri();
@ -85,6 +86,19 @@ class ViewFactory
$view->offsetSet('config', $container->get('config'));
$view->offsetSet('domain', $uri->withBasePath('')->getBaseUrl());
if ($container->has('debugbar')) {
$debugBar = $container->get('debugbar');
$debugBar->addCollector(new SmartyCollector($view->getSmarty()));
$view->offsetSet(
'debug_render',
$debugBar->getJavascriptRenderer(
$uri->getBaseUrl() . '/vendor/maximebf/debugbar/src/DebugBar/Resources/'
)
);
}
return $view;
}
}

View File

@ -48,7 +48,7 @@ class Locale
*
* @return string ISO 15897 code
*/
public function __toString()
public function __toString(): string
{
return $this->getIso15897();
}
@ -58,7 +58,7 @@ class Locale
*
* @return string
*/
public function getFullName()
public function getFullName(): string
{
return PHPLocale::getDisplayName($this->getIso15897(), $this->getIso15897());
}
@ -68,7 +68,7 @@ class Locale
*
* @return string
*/
public function getIso15897()
public function getIso15897(): string
{
if (isset($this->region)) {
return $this->language . '_' . $this->region;
@ -82,7 +82,7 @@ class Locale
*
* @return string
*/
public function getBcp47()
public function getBcp47(): string
{
if (isset($this->region)) {
return $this->language . '-' . $this->region;
@ -96,7 +96,7 @@ class Locale
*
* @return string
*/
public function getIso3166()
public function getIso3166(): string
{
return strtolower($this->region);
}

View File

@ -80,7 +80,7 @@ class LocaleManager
*
* @return Locale[]
*/
public function getSupportedLocales()
public function getSupportedLocales(): array
{
$return = [
new Locale('en_US')
@ -103,7 +103,7 @@ class LocaleManager
*
* @return Locale|null
*/
public function getLocale()
public function getLocale(): ?Locale
{
return $this->curLocale;
}
@ -140,7 +140,7 @@ class LocaleManager
*
* @return string Translated string
*/
public function smartyTranslate(array $params, string $text = null)
public function smartyTranslate(array $params, string $text = null): string
{
if (isset($params['params'])) {
return $this->t($text, $params['params']);
@ -157,7 +157,7 @@ class LocaleManager
* @param mixed[] $params
* @return string Translated string
*/
public function t(string $string = null, array $params = [])
public function t(string $string = null, array $params = []): string
{
if (isset($string)) {
return $this->translator->trans($string, $params);

View File

@ -34,10 +34,11 @@ class CspMiddleware
* @param Response $response
* @return MessageInterface
*/
public function applyHeader(Response $response)
public function applyHeader(Response $response): MessageInterface
{
$csp = new CSPBuilder();
$csp->addDirective('default-src', [])
$csp->disableOldBrowserSupport()
->addDirective('default-src', [])
->addDirective('font-src', ['self' => true])
->addDirective('style-src', ['self' => true])
->addDirective('manifest-src', ['self' => true])
@ -47,9 +48,10 @@ class CspMiddleware
->addSource('img-src', '*');
if ($this->config->debug) {
// So symfony/debug and symfony/error-handler can work.
$csp->setDirective('script-src', ['unsafe-inline' => true])
->setDirective('style-src', ['self' => true, 'unsafe-inline' => true]);
// So maximebf/debugbar, symfony/debug and symfony/error-handler can work.
$csp->setDirective('script-src', ['self' => true, 'unsafe-inline' => true])
->setDirective('style-src', ['self' => true, 'unsafe-inline' => true])
->addSource('img-src', 'data:');
}
return $csp->injectCSPHeader($response);

View File

@ -42,7 +42,7 @@ class LocaleMiddleware
*
* @return Locale|null Locale if chosen, nothing otherwise
*/
public function testLocale(array $proposedLocale)
public function testLocale(array $proposedLocale): ?Locale
{
foreach ($this->localeManager->getSupportedLocales() as $locale) {
$parsedLocale = AcceptLanguage::parse($locale);
@ -67,7 +67,7 @@ class LocaleMiddleware
*
* @return Response
*/
public function __invoke(Request $request, Response $response, callable $next)
public function __invoke(Request $request, Response $response, callable $next): Response
{
$headers = $request->getHeader('Accept-Language');
$curLocale = $this->localeManager->getLocale();

View File

@ -113,7 +113,7 @@ class PlaylistArchiveStream extends ZipArchive implements StreamInterface
*
* @return int|null
*/
public function getSize()
public function getSize(): ?int
{
return null;
}
@ -123,7 +123,7 @@ class PlaylistArchiveStream extends ZipArchive implements StreamInterface
*
* @return bool
*/
public function isSeekable()
public function isSeekable(): bool
{
return true;
}
@ -143,7 +143,7 @@ class PlaylistArchiveStream extends ZipArchive implements StreamInterface
*
* @return bool
*/
public function isWritable()
public function isWritable(): bool
{
return true;
}
@ -153,7 +153,7 @@ class PlaylistArchiveStream extends ZipArchive implements StreamInterface
*
* @return bool
*/
public function isReadable()
public function isReadable(): bool
{
return true;
}
@ -173,7 +173,7 @@ class PlaylistArchiveStream extends ZipArchive implements StreamInterface
*
* @param string|null $key string $key Specific metadata to retrieve.
*
* @return array|mixed|null
* @return mixed|null
*/
public function getMetadata($key = null)
{
@ -208,7 +208,7 @@ class PlaylistArchiveStream extends ZipArchive implements StreamInterface
*
* @return string
*/
public function __toString()
public function __toString(): string
{
$this->rewind();
@ -243,7 +243,7 @@ class PlaylistArchiveStream extends ZipArchive implements StreamInterface
*
* @return bool
*/
public function eof()
public function eof(): bool
{
return $this->isComplete && feof($this->buffer);
}
@ -272,12 +272,12 @@ class PlaylistArchiveStream extends ZipArchive implements StreamInterface
/**
* Read data from the stream.
*
* @param mixed $count Number of bytes to read
* @param mixed $length Number of bytes to read
*
* @return string|false
* @throws AlltubeLibraryException
*/
public function read($count)
public function read($length)
{
// If the archive is complete, we only read the remaining buffer.
if (!$this->isComplete) {
@ -297,15 +297,22 @@ class PlaylistArchiveStream extends ZipArchive implements StreamInterface
}
} else {
// Continue streaming the current video.
$this->stream_file_part($this->curVideoStream->read($count));
$this->stream_file_part($this->curVideoStream->read($length));
}
} else {
// Start streaming the first video.
$this->startVideoStream(current($this->videos));
$video = current($this->videos);
if ($video) {
$this->startVideoStream($video);
} else {
$this->push_error('Playlist was empty');
$this->finish();
$this->isComplete = true;
}
}
}
return fread($this->buffer, $count);
return fread($this->buffer, $length);
}
/**

View File

@ -39,7 +39,7 @@ class YoutubeChunkStream implements StreamInterface
*
* @return string
*/
public function read($length)
public function read($length): string
{
$size = intval($this->response->getHeader('Content-Length')[0]);
if ($size - $this->tell() < $length) {
@ -53,7 +53,7 @@ class YoutubeChunkStream implements StreamInterface
/**
* Reads all data from the stream into a string, from the beginning to end.
*/
public function __toString()
public function __toString(): string
{
return (string)$this->response->getBody();
}
@ -83,7 +83,7 @@ class YoutubeChunkStream implements StreamInterface
*
* @return int|null
*/
public function getSize()
public function getSize(): ?int
{
return $this->response->getBody()->getSize();
}
@ -93,7 +93,7 @@ class YoutubeChunkStream implements StreamInterface
*
* @return int
*/
public function tell()
public function tell(): int
{
return $this->response->getBody()->tell();
}
@ -103,7 +103,7 @@ class YoutubeChunkStream implements StreamInterface
*
* @return bool
*/
public function eof()
public function eof(): bool
{
return $this->response->getBody()->eof();
}
@ -113,7 +113,7 @@ class YoutubeChunkStream implements StreamInterface
*
* @return bool
*/
public function isSeekable()
public function isSeekable(): bool
{
return $this->response->getBody()->isSeekable();
}
@ -146,7 +146,7 @@ class YoutubeChunkStream implements StreamInterface
*
* @return bool
*/
public function isWritable()
public function isWritable(): bool
{
return $this->response->getBody()->isWritable();
}
@ -168,7 +168,7 @@ class YoutubeChunkStream implements StreamInterface
*
* @return bool
*/
public function isReadable()
public function isReadable(): bool
{
return $this->response->getBody()->isReadable();
}
@ -178,7 +178,7 @@ class YoutubeChunkStream implements StreamInterface
*
* @return string
*/
public function getContents()
public function getContents(): string
{
return $this->response->getBody()->getContents();
}
@ -188,7 +188,7 @@ class YoutubeChunkStream implements StreamInterface
*
* @param string|null $key Specific metadata to retrieve.
*
* @return array|mixed|null
* @return mixed|null
*/
public function getMetadata($key = null)
{

View File

@ -26,7 +26,7 @@ class UglyRouter extends Router
*
* @link https://github.com/nikic/FastRoute/blob/master/src/Dispatcher.php
*/
public function dispatch(ServerRequestInterface $request)
public function dispatch(ServerRequestInterface $request): array
{
$params = $request->getQueryParams();
$uri = new Uri('', '');
@ -53,7 +53,7 @@ class UglyRouter extends Router
* @throws InvalidArgumentException If required data not provided
* @throws RuntimeException If named route does not exist
*/
public function pathFor($name, array $data = [], array $queryParams = [])
public function pathFor($name, array $data = [], array $queryParams = []): string
{
$queryParams['page'] = $name;
$url = Uri::createFromString($this->relativePathFor($name, $data, $queryParams))->withPath('');

View File

@ -36,18 +36,21 @@
"symfony/translation": "^4.0",
"symfony/yaml": "^4.0",
"webfontkit/open-sans": "^1.0",
"ytdl-org/youtube-dl": "^2020.11",
"ytdl-org/youtube-dl": "^2021.04",
"zonuexe/http-accept-language": "^0.4.1"
},
"require-dev": {
"consolidation/robo": "^2.1",
"enlightn/security-checker": "^1.4",
"ergebnis/composer-normalize": "^2.6",
"insite/composer-dangling-locked-deps": "^0.2.1",
"junker/debugbar-smarty": "^0.1.0",
"kitchenu/slim-debugbar": "^1.1",
"maximebf/debugbar": "^1.16",
"php-mock/php-mock-mockery": "^1.3",
"phpro/grumphp": "^1.1",
"phpstan/phpstan": "^0.12.25",
"phpro/grumphp": "^1.3",
"phpstan/phpstan": "^0.12.72",
"phpunit/phpunit": "^8.4",
"sensiolabs/security-checker": "^6.0",
"smarty-gettext/smarty-gettext": "^1.6",
"squizlabs/php_codesniffer": "^3.5",
"symfony/error-handler": "^5.0",
@ -87,10 +90,10 @@
"type": "package",
"package": {
"name": "ytdl-org/youtube-dl",
"version": "2020.11.12",
"version": "2021.04.01",
"dist": {
"type": "zip",
"url": "https://github.com/ytdl-org/youtube-dl/archive/2020.11.12.zip"
"url": "https://github.com/ytdl-org/youtube-dl/archive/2021.04.01.zip"
}
}
}

1342
composer.lock generated

File diff suppressed because it is too large Load Diff

View File

@ -10,7 +10,7 @@ grumphp:
xmllint: ~
yamllint: ~
composer: ~
securitychecker: ~
securitychecker_enlightn: ~
composer_normalize: ~
composer_dangling_locked_deps: ~
phpcs:

View File

@ -0,0 +1,218 @@
msgid ""
msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Generator: POEditor.com\n"
"Project-Id-Version: Alltube Download\n"
"Language: ja-JP\n"
#: templates/inc/footer.tpl:8
msgid "Code by @dev"
msgstr "作成: @dev"
#: templates/inc/footer.tpl:16
msgid "Design by @designer"
msgstr "デザイン: @designer"
#: templates/inc/footer.tpl:21
msgid "Get the code"
msgstr "プログラムをダウンロード"
#: templates/inc/footer.tpl:29
msgid "Based on @youtubedl"
msgstr "本ソフトは@youtubedlを基に構成されています。"
#: templates/inc/footer.tpl:33
msgid "Donate using Liberapay"
msgstr "Liberapayで寄付"
#: templates/inc/footer.tpl:35
msgid "Donate"
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 "ダウンロード対象: @title"
#: templates/info.tpl:29
msgid "Available formats:"
msgstr "ダウンロード可能な形式"
#: templates/info.tpl:31
msgid "Generic formats"
msgstr "よく使われる形式"
#: templates/info.tpl:35
msgid "Best"
msgstr "最高品質"
#: templates/info.tpl:36
msgid "Remux best video with best audio"
msgstr "最高品質に再エンコード"
#: templates/info.tpl:37
msgid "Worst"
msgstr "最低品質"
#: templates/info.tpl:42
msgid "Detailed formats"
msgstr "その他の形式"
#: templates/info.tpl:86
msgid "Stream the video through the server"
msgstr "ビデオをサーバーに設置してダウンロード"
#: templates/info.tpl:92
msgid "Convert into a custom format:"
msgstr "指定した形式への変換"
#: templates/info.tpl:93
msgid "Custom format"
msgstr "カスタム形式"
#: templates/info.tpl:93
msgid "Format to convert to"
msgstr "ファイル形式の変換"
#: templates/info.tpl:98
msgid "with"
msgstr "と"
#: templates/info.tpl:99
msgid "Bit rate"
msgstr "ビットレート"
#: templates/info.tpl:100
msgid "Custom bitrate"
msgstr "カスタム・ビットレート"
#: templates/info.tpl:103
msgid "kbit/s audio"
msgstr "kbps 音声"
#: templates/info.tpl:107 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 "デコードの対象: @title"
#: templates/playlist.tpl:39
msgid "More options"
msgstr "詳細設定"
#: templates/extractors.tpl:4 classes/Controller/FrontController.php:111
msgid "Supported websites"
msgstr "ダウンロードに対応しているサイト"
#: templates/error.tpl:5
msgid "An error occurred"
msgstr "予期せぬエラーが発生しました。"
#: templates/password.tpl:5
msgid "This video is protected"
msgstr "このビデオにはプロテクトがかかっています。"
#: templates/password.tpl:6
msgid "You need a password in order to download this video."
msgstr "このビデオをダウンロードするには閲覧用のパスワードが必要です。"
#: templates/password.tpl:8
msgid "Video password"
msgstr "閲覧用パスワード"
#: templates/index.tpl:8
msgid "Copy here the URL of your video (YouTube, Dailymotion, etc.)"
msgstr "動画のリンク(URL)を入力欄に入力してください。(例:Youtube,Dailymotion等。)"
#: templates/index.tpl:25
msgid "Audio only (MP3)"
msgstr "音声のみのダウンロード(mp3形式)"
#: templates/index.tpl:29
msgid "From"
msgstr "から"
#: templates/index.tpl:32
msgid "to"
msgstr "へ"
#: templates/index.tpl:41
msgid "See all supported websites"
msgstr "ダウンロード可能なサイトを見る"
#: templates/index.tpl:43
msgid "Drag this to your bookmarks bar:"
msgstr "ブックマークバーにドラッグして登録"
#: templates/index.tpl:45
msgid "Bookmarklet"
msgstr "ブックマークボタン"
#: classes/Controller/DownloadController.php:64
#: classes/Controller/FrontController.php:166
msgid "Wrong password"
msgstr "パスワードが間違っています。"
#: classes/Controller/DownloadController.php:69
msgid "Conversion of playlists is not supported."
msgstr "プレイリストからの読み出しには対応しておりません。"
#: classes/Controller/DownloadController.php:76
msgid "Conversion of M3U8 files is not supported."
msgstr "HLS(m3u8)プレイリストファイルからの読み出しには対応しておりません。"
#: classes/Controller/DownloadController.php:82
msgid "Conversion of DASH segments is not supported."
msgstr "MPEG DASHストリーミングからの読み出しには対応しておりません。"
#: classes/Controller/FrontController.php:65
msgid "Easily download videos from YouTube, Dailymotion, Vimeo and other websites."
msgstr "Youtubeから動画を簡単にダウンロード!、DailymotionやVimeo等にも対応しております"
#: classes/Controller/FrontController.php:112
msgid "List of all supported websites from which AllTube Download can extract video or audio files"
msgstr "AllTube上でのダウンロードおよびファイルの変換に対応している音声または動画ファイルのサイト"
#: classes/Controller/FrontController.php:138
msgid "Password prompt"
msgstr "パスワード画面"
#: classes/Controller/FrontController.php:140
msgid "You need a password in order to download this video with AllTube Download"
msgstr "このビデオをAllTubeでダウンロードするにはパスワードが必要です。"
#: classes/Controller/FrontController.php:174
msgid "Video download"
msgstr "動画をダウンロード"
#: classes/Controller/FrontController.php:176
msgid "Download video from @extractor"
msgstr "@extractor からダウンロードします。"
#: classes/Controller/FrontController.php:182
msgid "Download @title from @extractor"
msgstr "@extractor から @title をダウンロードします"
#: classes/Controller/FrontController.php:255
msgid "Error"
msgstr "エラーが発生しました。"
#: classes/Controller/FrontController.php:271
msgid "Page not found"
msgstr "存在しないページです。"
#: classes/Controller/FrontController.php:282
msgid "Method not allowed"
msgstr "無効なリクエストです。"

View File

@ -10,8 +10,4 @@
<directory>tests/</directory>
</testsuite>
</testsuites>
<logging>
<log type="coverage-html" target="coverage/"/>
<log type="coverage-clover" target="clover.xml"/>
</logging>
</phpunit>

View File

@ -13,7 +13,6 @@ so it has low RAM and CPU.
AllTube probably won't switch to a more expensive hosting
because this project does not earn any financial resources
(although [donations are welcome](https://liberapay.com/Rudloff/))
and you are encouraged to host it yourself.
## alltubedownload.net often says "An error occurred in the application…"

View File

@ -27,15 +27,11 @@
youtube-dl
</a>"}
{t params=['@youtubedl'=>$youtubedl]}Based on @youtubedl{/t}
&middot;
<a rel="noopener" target="_blank" title="{t}Donate using Liberapay{/t}"
href="https://liberapay.com/Rudloff/donate">
{t}Donate{/t}
</a>
</div>
</footer>
</div>
{if isset($debug_render)}
{$debug_render->render()}
{/if}
</body>
</html>

View File

@ -22,6 +22,10 @@
<meta name="theme-color" content="#4F4F4F"/>
<link rel="manifest" href="{base_url}/resources/manifest.json"/>
<meta name="generator" content="AllTube Download ({$config->getAppVersion()})"/>
{if isset($debug_render)}
{$debug_render->renderHead()}
{/if}
</head>
<body>
<div class="page {$class}">

View File

@ -18,7 +18,7 @@ abstract class BaseTest extends TestCase
*
* @return string Path to file
*/
protected function getConfigFile()
protected function getConfigFile(): string
{
return __DIR__ . '/../config/config_test.yml';
}

View File

@ -40,6 +40,7 @@ abstract class ContainerTest extends BaseTest
$this->checkRequirements();
$this->container = new Container(['environment' => Environment::mock()]);
$this->container['root_path'] = dirname(__DIR__);
$this->container['config'] = Config::fromFile($this->getConfigFile());
$this->container['session'] = SessionFactory::create($this->container);
$this->container['locale'] = LocaleManagerFactory::create($this->container);

View File

@ -13,6 +13,7 @@ use Alltube\Controller\FrontController;
use Alltube\Exception\ConfigException;
use Alltube\Exception\DependencyException;
use Slim\Http\Response;
use Slim\Views\Smarty;
use SmartyException;
/**
@ -52,6 +53,12 @@ abstract class ControllerTest extends ContainerTest
->setName('locale');
$router->map(['GET'], '/redirect', [$downloadController, 'download'])
->setName('download');
/** @var Smarty $view */
$view = $this->container->get('view');
// Make sure we start the tests without compiled templates.
$view->getSmarty()->clearCompiledTemplate();
}
/**
@ -62,7 +69,7 @@ abstract class ControllerTest extends ContainerTest
*
* @return Response HTTP response
*/
protected function getRequestResult(string $request, array $params)
protected function getRequestResult(string $request, array $params): Response
{
return $this->controller->$request(
$this->container->get('request')->withQueryParams($params),

View File

@ -85,26 +85,32 @@ class LocaleMiddlewareTest extends ContainerTest
* Check that the request contains an Accept-Language header.
*
* @param Request $request PSR-7 request
* @param Response $response
*
* @return void
* @return Response
*/
public function assertHeader(Request $request)
public function assertHeader(Request $request, Response $response): Response
{
$header = $request->getHeader('Accept-Language');
$this->assertEquals('foo-BAR', $header[0]);
return $response;
}
/**
* Check that the request contains no Accept-Language header.
*
* @param Request $request PSR-7 request
* @param Response $response
*
* @return void
* @return Response
*/
public function assertNoHeader(Request $request)
public function assertNoHeader(Request $request, Response $response): Response
{
$header = $request->getHeader('Accept-Language');
$this->assertEmpty($header);
return $response;
}
/**

View File

@ -37,7 +37,16 @@ class UglyRouterTest extends ContainerTest
parent::setUp();
$this->router = new UglyRouter();
$this->router->map(['GET'], '/foo', 'print')->setName('foo');
$this->router->map(['GET'], '/foo', [$this, 'fakeHandler'])->setName('foo');
}
/**
* Empty function that only exists so that our route can have a handler.
*
* @return void
*/
private function fakeHandler()
{
}
/**
@ -54,7 +63,7 @@ class UglyRouterTest extends ContainerTest
Environment::mock(
[
'REQUEST_METHOD' => 'GET',
'QUERY_STRING' => 'page=foo',
'QUERY_STRING' => 'page=foo',
]
)
)

View File

@ -157,7 +157,7 @@ class VideoTest extends ContainerTest
*
* @return array[]
*/
public function urlProvider()
public function urlProvider(): array
{
return [
[
@ -193,7 +193,7 @@ class VideoTest extends ContainerTest
*
* @return array[]
*/
public function remuxUrlProvider()
public function remuxUrlProvider(): array
{
return [
[
@ -210,7 +210,7 @@ class VideoTest extends ContainerTest
*
* @return array[]
*/
public function m3uUrlProvider()
public function m3uUrlProvider(): array
{
return [
[
@ -227,7 +227,7 @@ class VideoTest extends ContainerTest
*
* @return array[]
*/
public function rtmpUrlProvider()
public function rtmpUrlProvider(): array
{
return [
[
@ -244,7 +244,7 @@ class VideoTest extends ContainerTest
*
* @return array[]
*/
public function errorUrlProvider()
public function errorUrlProvider(): array
{
return [
['http://example.com/video'],