From 80434fcc27df30252e6be58a64dc621c4beb851d Mon Sep 17 00:00:00 2001 From: Pierre Rudloff Date: Thu, 14 May 2020 12:48:06 +0200 Subject: [PATCH 01/34] Don't include phpstan in the release package --- RoboFile.php | 1 + 1 file changed, 1 insertion(+) diff --git a/RoboFile.php b/RoboFile.php index a3a53af..f4980cf 100644 --- a/RoboFile.php +++ b/RoboFile.php @@ -29,6 +29,7 @@ class RoboFile extends Tasks ->exclude( [ 'ffmpeg/', + 'phpstan/', 'bin/', 'anam/phantomjs-linux-x86-binary/', 'phpunit/', From c30b0a40496a0750ec856a4d93f0adfdb4110dcf Mon Sep 17 00:00:00 2001 From: Pierre Rudloff Date: Thu, 14 May 2020 14:11:22 +0200 Subject: [PATCH 02/34] Remove unused classes --- controllers/FrontController.php | 2 -- 1 file changed, 2 deletions(-) diff --git a/controllers/FrontController.php b/controllers/FrontController.php index 01030aa..b0c4a65 100644 --- a/controllers/FrontController.php +++ b/controllers/FrontController.php @@ -9,9 +9,7 @@ namespace Alltube\Controller; use Alltube\Exception\PasswordException; 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 Psr\Container\ContainerInterface; From 689264cb3515452af9508b48109703e6fa7af315 Mon Sep 17 00:00:00 2001 From: Pierre Rudloff Date: Fri, 15 May 2020 21:18:01 +0200 Subject: [PATCH 03/34] Fix typo --- classes/Config.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/classes/Config.php b/classes/Config.php index c68d5b3..d8ca08f 100644 --- a/classes/Config.php +++ b/classes/Config.php @@ -225,7 +225,7 @@ class Config } /** - * Override options from environement variables. + * Override options from environment variables. * 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]'" * From 1d95ba7b5719330527c1f2ae623c83457ec4b9a9 Mon Sep 17 00:00:00 2001 From: Pierre Rudloff Date: Sat, 23 May 2020 16:21:46 +0200 Subject: [PATCH 04/34] =?UTF-8?q?Fix=20`stream:=20ask`=20detection=20(see?= =?UTF-8?q?=C2=A0#283)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- templates/info.tpl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/templates/info.tpl b/templates/info.tpl index 07ae547..fce119a 100644 --- a/templates/info.tpl +++ b/templates/info.tpl @@ -76,7 +76,7 @@
{/if} {if $config->stream} - stream != 'ask'}checked{/if} name="stream" id="stream"/> + stream !== 'ask'}checked{/if} name="stream" id="stream"/>

From cb20f4e51dff102047f707462a1766450eb2cc3e Mon Sep 17 00:00:00 2001 From: Pierre Rudloff Date: Thu, 28 May 2020 00:22:30 +0200 Subject: [PATCH 05/34] Detect locales automatically --- classes/LocaleManager.php | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/classes/LocaleManager.php b/classes/LocaleManager.php index 813ea79..ee2c4cf 100644 --- a/classes/LocaleManager.php +++ b/classes/LocaleManager.php @@ -7,6 +7,7 @@ namespace Alltube; use Aura\Session\Segment; +use Symfony\Component\Finder\Finder; use Symfony\Component\Translation\Translator; use Symfony\Component\Translation\Loader\PoFileLoader; @@ -15,12 +16,7 @@ use Symfony\Component\Translation\Loader\PoFileLoader; */ class LocaleManager { - /** - * Supported 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. @@ -75,7 +71,7 @@ class LocaleManager foreach ($this->getSupportedLocales() as $locale) { $this->translator->addResource( 'gettext', - __DIR__ . '/../i18n/' . $locale->getIso15897() . '/LC_MESSAGES/Alltube.po', + self::PATH . $locale->getIso15897() . '/LC_MESSAGES/Alltube.po', $locale->getIso15897() ); } @@ -90,8 +86,13 @@ class LocaleManager { $return = []; - foreach ($this->supportedLocales as $supportedLocale) { - $return[] = new Locale($supportedLocale); + $finder = new Finder(); + $finder->depth(0) + ->directories() + ->in(self::PATH); + + foreach ($finder as $file) { + $return[] = new Locale($file->getFilename()); } return $return; From 2c28cf95c8634e18db119cc265d45fa18d9c124c Mon Sep 17 00:00:00 2001 From: holoitsme <35468654+holoitsme@users.noreply.github.com> Date: Thu, 28 May 2020 00:27:18 +0200 Subject: [PATCH 06/34] Added Italian translation (#285) --- i18n/it_IT/LC_MESSAGES/Alltube.po | 248 ++++++++++++++++++++++++++++++ 1 file changed, 248 insertions(+) create mode 100644 i18n/it_IT/LC_MESSAGES/Alltube.po diff --git a/i18n/it_IT/LC_MESSAGES/Alltube.po b/i18n/it_IT/LC_MESSAGES/Alltube.po new file mode 100644 index 0000000..cd7ab21 --- /dev/null +++ b/i18n/it_IT/LC_MESSAGES/Alltube.po @@ -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" From ad77d029d303c0f62ac22ff9c29227201827e377 Mon Sep 17 00:00:00 2001 From: Pierre Rudloff Date: Thu, 28 May 2020 00:33:07 +0200 Subject: [PATCH 07/34] fixup! Detect locales automatically --- classes/LocaleManager.php | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/classes/LocaleManager.php b/classes/LocaleManager.php index ee2c4cf..df7661c 100644 --- a/classes/LocaleManager.php +++ b/classes/LocaleManager.php @@ -16,6 +16,10 @@ use Symfony\Component\Translation\Loader\PoFileLoader; */ class LocaleManager { + + /** + * Path to locales. + */ private const PATH = __DIR__ . '/../i18n/'; /** @@ -84,7 +88,9 @@ class LocaleManager */ public function getSupportedLocales() { - $return = []; + $return = [ + new Locale('en_US') + ]; $finder = new Finder(); $finder->depth(0) From e777f514900671db9d40599ae2e81704af9e0b74 Mon Sep 17 00:00:00 2001 From: Pierre Rudloff Date: Thu, 28 May 2020 00:55:49 +0200 Subject: [PATCH 08/34] Dependencies update symfony/finder should be a production dependency --- composer.json | 3 +- composer.lock | 571 +++++++++++++++++++++++++++----------------------- 2 files changed, 310 insertions(+), 264 deletions(-) diff --git a/composer.json b/composer.json index 0bd4fc6..b223fec 100644 --- a/composer.json +++ b/composer.json @@ -14,6 +14,7 @@ "mathmarques/smarty-view": "^1.1", "npm-asset/open-sans-fontface": "^1.4", "rinvex/countries": "^6.1", + "symfony/finder": "^5.0", "symfony/process": "^4.0", "symfony/translation": "^4.0", "symfony/yaml": "^4.0", @@ -21,7 +22,7 @@ }, "require-dev": { "anam/phantomjs-linux-x86-binary": "^2.1", - "consolidation/robo": "^2.0", + "consolidation/robo": "^2.1", "ffmpeg/ffmpeg": "^4.1", "heroku/heroku-buildpack-php": "^162.0", "php-mock/php-mock-mockery": "^1.3", diff --git a/composer.lock b/composer.lock index 15ca205..4acd9ea 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "5fdb499464d2fcf04d97dca8c099a075", + "content-hash": "e02a081a0f220bf779ab5ba047c1ca68", "packages": [ { "name": "aura/session", @@ -456,7 +456,7 @@ "version": "1.4.2", "source": { "type": "git", - "url": "git@github.com:FontFaceKit/open-sans.git", + "url": "https://github.com/FontFaceKit/open-sans.git", "reference": "2285c0300e6a4c8b102b98fb030fb38c26aa081c" }, "dist": { @@ -863,17 +863,66 @@ "time": "2018-09-12T20:54:16+00:00" }, { - "name": "symfony/polyfill-ctype", - "version": "v1.13.1", + "name": "symfony/finder", + "version": "v5.0.8", "source": { "type": "git", - "url": "https://github.com/symfony/polyfill-ctype.git", - "reference": "f8f0b461be3385e56d6de3dbb5a0df24c0c275e3" + "url": "https://github.com/symfony/finder.git", + "reference": "600a52c29afc0d1caa74acbec8d3095ca7e9910d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/f8f0b461be3385e56d6de3dbb5a0df24c0c275e3", - "reference": "f8f0b461be3385e56d6de3dbb5a0df24c0c275e3", + "url": "https://api.github.com/repos/symfony/finder/zipball/600a52c29afc0d1caa74acbec8d3095ca7e9910d", + "reference": "600a52c29afc0d1caa74acbec8d3095ca7e9910d", + "shasum": "" + }, + "require": { + "php": "^7.2.5" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "5.0-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\Finder\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony Finder Component", + "homepage": "https://symfony.com", + "time": "2020-03-27T16:56:45+00:00" + }, + { + "name": "symfony/polyfill-ctype", + "version": "v1.17.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-ctype.git", + "reference": "e94c8b1bbe2bc77507a1056cdb06451c75b427f9" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/e94c8b1bbe2bc77507a1056cdb06451c75b427f9", + "reference": "e94c8b1bbe2bc77507a1056cdb06451c75b427f9", "shasum": "" }, "require": { @@ -885,7 +934,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "1.13-dev" + "dev-master": "1.17-dev" } }, "autoload": { @@ -918,7 +967,7 @@ "polyfill", "portable" ], - "time": "2019-11-27T13:56:44+00:00" + "time": "2020-05-12T16:14:59+00:00" }, { "name": "symfony/polyfill-intl-idn", @@ -984,16 +1033,16 @@ }, { "name": "symfony/polyfill-mbstring", - "version": "v1.13.0", + "version": "v1.17.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-mbstring.git", - "reference": "7b4aab9743c30be783b73de055d24a39cf4b954f" + "reference": "fa79b11539418b02fc5e1897267673ba2c19419c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/7b4aab9743c30be783b73de055d24a39cf4b954f", - "reference": "7b4aab9743c30be783b73de055d24a39cf4b954f", + "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/fa79b11539418b02fc5e1897267673ba2c19419c", + "reference": "fa79b11539418b02fc5e1897267673ba2c19419c", "shasum": "" }, "require": { @@ -1005,7 +1054,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "1.13-dev" + "dev-master": "1.17-dev" } }, "autoload": { @@ -1039,7 +1088,7 @@ "portable", "shim" ], - "time": "2019-11-27T14:18:11+00:00" + "time": "2020-05-12T16:47:27+00:00" }, { "name": "symfony/polyfill-php72", @@ -1098,16 +1147,16 @@ }, { "name": "symfony/process", - "version": "v4.4.0", + "version": "v4.4.8", "source": { "type": "git", "url": "https://github.com/symfony/process.git", - "reference": "75ad33d9b6f25325ebc396d68ad86fd74bcfbb06" + "reference": "4b6a9a4013baa65d409153cbb5a895bf093dc7f4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/process/zipball/75ad33d9b6f25325ebc396d68ad86fd74bcfbb06", - "reference": "75ad33d9b6f25325ebc396d68ad86fd74bcfbb06", + "url": "https://api.github.com/repos/symfony/process/zipball/4b6a9a4013baa65d409153cbb5a895bf093dc7f4", + "reference": "4b6a9a4013baa65d409153cbb5a895bf093dc7f4", "shasum": "" }, "require": { @@ -1143,7 +1192,7 @@ ], "description": "Symfony Process Component", "homepage": "https://symfony.com", - "time": "2019-10-28T20:30:34+00:00" + "time": "2020-04-15T15:56:18+00:00" }, { "name": "symfony/translation", @@ -1424,34 +1473,46 @@ }, { "name": "consolidation/annotated-command", - "version": "4.0.0", + "version": "4.1.1", "source": { "type": "git", "url": "https://github.com/consolidation/annotated-command.git", - "reference": "be011ba6314d76cabf78afbeb275694795c88360" + "reference": "efc58dc0f34a45539787c5190b41b5d2a50a08da" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/consolidation/annotated-command/zipball/be011ba6314d76cabf78afbeb275694795c88360", - "reference": "be011ba6314d76cabf78afbeb275694795c88360", + "url": "https://api.github.com/repos/consolidation/annotated-command/zipball/efc58dc0f34a45539787c5190b41b5d2a50a08da", + "reference": "efc58dc0f34a45539787c5190b41b5d2a50a08da", "shasum": "" }, "require": { - "consolidation/output-formatters": "^4", + "consolidation/output-formatters": "^4.1.1", "php": ">=7.1.3", - "psr/log": "^1", - "symfony/console": "^4", - "symfony/event-dispatcher": "^4", - "symfony/finder": "^4" + "psr/log": "^1|^2", + "symfony/console": "^4.4.8|^5", + "symfony/event-dispatcher": "^4.4.8|^5", + "symfony/finder": "^4.4.8|^5" }, "require-dev": { "g1a/composer-test-scenarios": "^3", - "php-coveralls/php-coveralls": "^1", + "php-coveralls/php-coveralls": "^2.2", "phpunit/phpunit": "^6", - "squizlabs/php_codesniffer": "^2.7" + "squizlabs/php_codesniffer": "^3" }, "type": "library", "extra": { + "scenarios": { + "symfony4": { + "require": { + "symfony/console": "^4.0" + }, + "config": { + "platform": { + "php": "7.1.3" + } + } + } + }, "branch-alias": { "dev-master": "4.x-dev" } @@ -1472,34 +1533,35 @@ } ], "description": "Initialize Symfony Console commands from annotated command class methods.", - "time": "2019-10-29T13:44:48+00:00" + "time": "2020-05-27T21:11:36+00:00" }, { "name": "consolidation/config", - "version": "1.2.1", + "version": "2.0.0", "source": { "type": "git", "url": "https://github.com/consolidation/config.git", - "reference": "cac1279bae7efb5c7fb2ca4c3ba4b8eb741a96c1" + "reference": "9842670aad3406dbc8df3069fd680a9f8cd6edd7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/consolidation/config/zipball/cac1279bae7efb5c7fb2ca4c3ba4b8eb741a96c1", - "reference": "cac1279bae7efb5c7fb2ca4c3ba4b8eb741a96c1", + "url": "https://api.github.com/repos/consolidation/config/zipball/9842670aad3406dbc8df3069fd680a9f8cd6edd7", + "reference": "9842670aad3406dbc8df3069fd680a9f8cd6edd7", "shasum": "" }, "require": { "dflydev/dot-access-data": "^1.1.0", "grasmash/expander": "^1", - "php": ">=5.4.0" + "php": ">=7.1.3" }, "require-dev": { "g1a/composer-test-scenarios": "^3", - "php-coveralls/php-coveralls": "^1", - "phpunit/phpunit": "^5", - "squizlabs/php_codesniffer": "2.*", - "symfony/console": "^2.5|^3|^4", - "symfony/yaml": "^2.8.11|^3|^4" + "php-coveralls/php-coveralls": "^2.2", + "phpunit/phpunit": "^6", + "squizlabs/php_codesniffer": "^3", + "symfony/console": "^4|^5", + "symfony/event-dispatcher": "^4|^5", + "symfony/yaml": "^4|^5" }, "suggest": { "symfony/yaml": "Required to use Consolidation\\Config\\Loader\\YamlConfigLoader" @@ -1509,32 +1571,17 @@ "scenarios": { "symfony4": { "require-dev": { - "symfony/console": "^4.0" + "symfony/console": "^4" }, "config": { "platform": { "php": "7.1.3" } } - }, - "symfony2": { - "require-dev": { - "symfony/console": "^2.8", - "symfony/event-dispatcher": "^2.8", - "phpunit/phpunit": "^4.8.36" - }, - "remove": [ - "php-coveralls/php-coveralls" - ], - "config": { - "platform": { - "php": "5.4.8" - } - } } }, "branch-alias": { - "dev-master": "1.x-dev" + "dev-master": "2.x-dev" } }, "autoload": { @@ -1553,78 +1600,49 @@ } ], "description": "Provide configuration services for a commandline tool.", - "time": "2019-03-03T19:37:04+00:00" + "time": "2020-05-27T17:11:23+00:00" }, { "name": "consolidation/log", - "version": "1.1.1", + "version": "2.0.1", "source": { "type": "git", "url": "https://github.com/consolidation/log.git", - "reference": "b2e887325ee90abc96b0a8b7b474cd9e7c896e3a" + "reference": "ba0bf6af1fbd09ed4dc18fc2f27b12ceff487cbf" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/consolidation/log/zipball/b2e887325ee90abc96b0a8b7b474cd9e7c896e3a", - "reference": "b2e887325ee90abc96b0a8b7b474cd9e7c896e3a", + "url": "https://api.github.com/repos/consolidation/log/zipball/ba0bf6af1fbd09ed4dc18fc2f27b12ceff487cbf", + "reference": "ba0bf6af1fbd09ed4dc18fc2f27b12ceff487cbf", "shasum": "" }, "require": { - "php": ">=5.4.5", + "php": ">=7.1.3", "psr/log": "^1.0", - "symfony/console": "^2.8|^3|^4" + "symfony/console": "^4|^5" }, "require-dev": { "g1a/composer-test-scenarios": "^3", - "php-coveralls/php-coveralls": "^1", + "php-coveralls/php-coveralls": "^2.2", "phpunit/phpunit": "^6", - "squizlabs/php_codesniffer": "^2" + "squizlabs/php_codesniffer": "^3" }, "type": "library", "extra": { "scenarios": { "symfony4": { - "require": { - "symfony/console": "^4.0" + "require-dev": { + "symfony/console": "^4" }, "config": { "platform": { "php": "7.1.3" } } - }, - "symfony2": { - "require": { - "symfony/console": "^2.8" - }, - "require-dev": { - "phpunit/phpunit": "^4.8.36" - }, - "remove": [ - "php-coveralls/php-coveralls" - ], - "config": { - "platform": { - "php": "5.4.8" - } - } - }, - "phpunit4": { - "require-dev": { - "phpunit/phpunit": "^4.8.36" - }, - "remove": [ - "php-coveralls/php-coveralls" - ], - "config": { - "platform": { - "php": "5.4.8" - } - } } }, "branch-alias": { - "dev-master": "1.x-dev" + "dev-master": "2.x-dev" } }, "autoload": { @@ -1643,41 +1661,53 @@ } ], "description": "Improved Psr-3 / Psr\\Log logger based on Symfony Console components.", - "time": "2019-01-01T17:30:51+00:00" + "time": "2020-05-27T17:06:13+00:00" }, { "name": "consolidation/output-formatters", - "version": "4.0.0", + "version": "4.1.1", "source": { "type": "git", "url": "https://github.com/consolidation/output-formatters.git", - "reference": "8e747762963ab48912fb75fc24dbe39175f47057" + "reference": "9deeddd6a916d0a756b216a8b40ce1016e17c0b9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/consolidation/output-formatters/zipball/8e747762963ab48912fb75fc24dbe39175f47057", - "reference": "8e747762963ab48912fb75fc24dbe39175f47057", + "url": "https://api.github.com/repos/consolidation/output-formatters/zipball/9deeddd6a916d0a756b216a8b40ce1016e17c0b9", + "reference": "9deeddd6a916d0a756b216a8b40ce1016e17c0b9", "shasum": "" }, "require": { "dflydev/dot-access-data": "^1.1.0", - "php": ">=5.4.0", - "symfony/console": "^4", - "symfony/finder": "^4" + "php": ">=7.1.3", + "symfony/console": "^4|^5", + "symfony/finder": "^4|^5" }, "require-dev": { "g1a/composer-test-scenarios": "^3", - "php-coveralls/php-coveralls": "^1", - "phpunit/phpunit": "^5.7.27", - "squizlabs/php_codesniffer": "^2.7", + "php-coveralls/php-coveralls": "^2.2", + "phpunit/phpunit": "^6", + "squizlabs/php_codesniffer": "^3", "symfony/var-dumper": "^4", - "victorjonsson/markdowndocs": "^1.3" + "symfony/yaml": "^4" }, "suggest": { "symfony/var-dumper": "For using the var_dump formatter" }, "type": "library", "extra": { + "scenarios": { + "symfony4": { + "require": { + "symfony/console": "^4.0" + }, + "config": { + "platform": { + "php": "7.1.3" + } + } + } + }, "branch-alias": { "dev-master": "4.x-dev" } @@ -1698,54 +1728,49 @@ } ], "description": "Format text by applying transformations provided by plug-in formatters.", - "time": "2019-10-29T13:39:04+00:00" + "time": "2020-05-27T20:51:17+00:00" }, { "name": "consolidation/robo", - "version": "2.0.0", + "version": "2.1.0", "source": { "type": "git", "url": "https://github.com/consolidation/Robo.git", - "reference": "f21c960ebec8c94a85ead5dc22c1a7d581a24055" + "reference": "a0415a2663f6d9426d3cb9013446d3f00225d76d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/consolidation/Robo/zipball/f21c960ebec8c94a85ead5dc22c1a7d581a24055", - "reference": "f21c960ebec8c94a85ead5dc22c1a7d581a24055", + "url": "https://api.github.com/repos/consolidation/Robo/zipball/a0415a2663f6d9426d3cb9013446d3f00225d76d", + "reference": "a0415a2663f6d9426d3cb9013446d3f00225d76d", "shasum": "" }, "require": { - "consolidation/annotated-command": "^4", - "consolidation/config": "^1.2.1", - "consolidation/log": "^1.1.1", - "consolidation/output-formatters": "^4", - "consolidation/self-update": "^1", + "consolidation/annotated-command": "^4.1.1", + "consolidation/config": "^1.2.1|^2", + "consolidation/log": "^1.1.1|^2.0.1", + "consolidation/output-formatters": "^4.1.1", + "consolidation/self-update": "^1.2", "grasmash/yaml-expander": "^1.4", - "league/container": "^2.2", + "league/container": "^2.4.1", "php": ">=7.1.3", - "symfony/console": "^4.3.5", - "symfony/event-dispatcher": "^4", - "symfony/filesystem": "^4", - "symfony/finder": "^4", - "symfony/process": "^4" + "symfony/console": "^4.4.8|^5", + "symfony/event-dispatcher": "^4.4.8|^5", + "symfony/filesystem": "^4.4.8|^5", + "symfony/finder": "^4.4.8|^5", + "symfony/process": "^4.4.8|^5" }, "conflict": { "codegyre/robo": "*" }, "require-dev": { - "codeception/aspect-mock": "^3.0.2", - "codeception/base": "^3.1.2", - "codeception/phpunit-wrapper": "^7.7.1", - "codeception/stub": "^3", - "doctrine/annotations": "^1.8.0", "g1a/composer-test-scenarios": "^3", "natxet/cssmin": "3.0.4", - "nikic/php-parser": "^3.1.5", "patchwork/jsqueeze": "^2", "pear/archive_tar": "^1.4.4", - "php-coveralls/php-coveralls": "^1", + "php-coveralls/php-coveralls": "^2.2", "phpdocumentor/reflection-docblock": "^4.3.2", - "squizlabs/php_codesniffer": "^2.8" + "phpunit/phpunit": "^6.5.14", + "squizlabs/php_codesniffer": "^3" }, "suggest": { "henrikbjorn/lurker": "For monitoring filesystem changes in taskWatch", @@ -1758,6 +1783,27 @@ ], "type": "library", "extra": { + "scenarios": { + "symfony4": { + "require": { + "symfony/console": "^4.4.8", + "symfony/event-dispatcher": "^4.4.8", + "symfony/filesystem": "^4.4.8", + "symfony/finder": "^4.4.8", + "symfony/process": "^4.4.8", + "phpunit/phpunit": "^6", + "nikic/php-parser": "^2" + }, + "remove": [ + "codeception/phpunit-wrapper" + ], + "config": { + "platform": { + "php": "7.1.3" + } + } + } + }, "branch-alias": { "dev-master": "2.x-dev" } @@ -1778,26 +1824,26 @@ } ], "description": "Modern task runner", - "time": "2019-10-29T14:11:02+00:00" + "time": "2020-05-27T22:03:57+00:00" }, { "name": "consolidation/self-update", - "version": "1.1.5", + "version": "1.2.0", "source": { "type": "git", "url": "https://github.com/consolidation/self-update.git", - "reference": "a1c273b14ce334789825a09d06d4c87c0a02ad54" + "reference": "dba6b2c0708f20fa3ba8008a2353b637578849b4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/consolidation/self-update/zipball/a1c273b14ce334789825a09d06d4c87c0a02ad54", - "reference": "a1c273b14ce334789825a09d06d4c87c0a02ad54", + "url": "https://api.github.com/repos/consolidation/self-update/zipball/dba6b2c0708f20fa3ba8008a2353b637578849b4", + "reference": "dba6b2c0708f20fa3ba8008a2353b637578849b4", "shasum": "" }, "require": { "php": ">=5.5.0", - "symfony/console": "^2.8|^3|^4", - "symfony/filesystem": "^2.5|^3|^4" + "symfony/console": "^2.8|^3|^4|^5", + "symfony/filesystem": "^2.5|^3|^4|^5" }, "bin": [ "scripts/release" @@ -1818,17 +1864,17 @@ "MIT" ], "authors": [ - { - "name": "Greg Anderson", - "email": "greg.1.anderson@greenknowe.org" - }, { "name": "Alexander Menk", "email": "menk@mestrona.net" + }, + { + "name": "Greg Anderson", + "email": "greg.1.anderson@greenknowe.org" } ], "description": "Provides a self:update command for Symfony Console applications.", - "time": "2018-10-28T01:52:03+00:00" + "time": "2020-04-13T02:49:20+00:00" }, { "name": "container-interop/container-interop", @@ -4099,6 +4145,52 @@ ], "time": "2019-11-06T09:42:23+00:00" }, + { + "name": "psr/event-dispatcher", + "version": "1.0.0", + "source": { + "type": "git", + "url": "https://github.com/php-fig/event-dispatcher.git", + "reference": "dbefd12671e8a14ec7f180cab83036ed26714bb0" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/event-dispatcher/zipball/dbefd12671e8a14ec7f180cab83036ed26714bb0", + "reference": "dbefd12671e8a14ec7f180cab83036ed26714bb0", + "shasum": "" + }, + "require": { + "php": ">=7.2.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\EventDispatcher\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" + } + ], + "description": "Standard interfaces for event handling.", + "keywords": [ + "events", + "psr", + "psr-14" + ], + "time": "2019-01-08T18:20:26+00:00" + }, { "name": "psr/log", "version": "1.1.3", @@ -4152,12 +4244,12 @@ "source": { "type": "git", "url": "https://github.com/Roave/SecurityAdvisories.git", - "reference": "5a342e2dc0408d026b97ee3176b5b406e54e3766" + "reference": "e38de1df609b39d97144514d28b0804ad4daaddb" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Roave/SecurityAdvisories/zipball/5a342e2dc0408d026b97ee3176b5b406e54e3766", - "reference": "5a342e2dc0408d026b97ee3176b5b406e54e3766", + "url": "https://api.github.com/repos/Roave/SecurityAdvisories/zipball/e38de1df609b39d97144514d28b0804ad4daaddb", + "reference": "e38de1df609b39d97144514d28b0804ad4daaddb", "shasum": "" }, "conflict": { @@ -4170,7 +4262,8 @@ "asymmetricrypt/asymmetricrypt": ">=0,<9.9.99", "aws/aws-sdk-php": ">=3,<3.2.1", "bagisto/bagisto": "<0.1.5", - "barrelstrength/sprout-base-email": "<3.9", + "barrelstrength/sprout-base-email": "<1.2.7", + "barrelstrength/sprout-forms": "<3.9", "bolt/bolt": "<3.6.10", "brightlocal/phpwhois": "<=4.2.5", "buddypress/buddypress": "<5.1.2", @@ -4197,10 +4290,10 @@ "doctrine/mongodb-odm": ">=1,<1.0.2", "doctrine/mongodb-odm-bundle": ">=2,<3.0.1", "doctrine/orm": ">=2,<2.4.8|>=2.5,<2.5.1", - "dolibarr/dolibarr": "<=10.0.6", + "dolibarr/dolibarr": "<11.0.4", "dompdf/dompdf": ">=0.6,<0.6.2", - "drupal/core": ">=7,<7.69|>=8,<8.7.12|>=8.8,<8.8.4", - "drupal/drupal": ">=7,<7.69|>=8,<8.7.12|>=8.8,<8.8.4", + "drupal/core": ">=7,<7.70|>=8,<8.7.14|>=8.8,<8.8.6", + "drupal/drupal": ">=7,<7.70|>=8,<8.7.14|>=8.8,<8.8.6", "endroid/qr-code-bundle": "<3.4.2", "enshrined/svg-sanitize": "<0.13.1", "erusev/parsedown": "<1.7.2", @@ -4341,6 +4434,7 @@ "symfony/var-exporter": ">=4.2,<4.2.12|>=4.3,<4.3.8", "symfony/web-profiler-bundle": ">=2,<2.3.19|>=2.4,<2.4.9|>=2.5,<2.5.4", "symfony/yaml": ">=2,<2.0.22|>=2.1,<2.1.7", + "t3g/svg-sanitizer": "<1.0.3", "tecnickcom/tcpdf": "<6.2.22", "thelia/backoffice-default-template": ">=2.1,<2.1.2", "thelia/thelia": ">=2.1-beta.1,<2.1.3", @@ -4412,7 +4506,7 @@ } ], "description": "Prevents installation of composer packages with known security vulnerabilities: no API, simply require it", - "time": "2020-05-12T11:18:47+00:00" + "time": "2020-05-22T06:49:22+00:00" }, { "name": "sebastian/code-unit-reverse-lookup", @@ -5250,41 +5344,41 @@ }, { "name": "symfony/console", - "version": "v4.4.0", + "version": "v5.0.8", "source": { "type": "git", "url": "https://github.com/symfony/console.git", - "reference": "35d9077f495c6d184d9930f7a7ecbd1ad13c7ab8" + "reference": "5fa1caadc8cdaa17bcfb25219f3b53fe294a9935" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/35d9077f495c6d184d9930f7a7ecbd1ad13c7ab8", - "reference": "35d9077f495c6d184d9930f7a7ecbd1ad13c7ab8", + "url": "https://api.github.com/repos/symfony/console/zipball/5fa1caadc8cdaa17bcfb25219f3b53fe294a9935", + "reference": "5fa1caadc8cdaa17bcfb25219f3b53fe294a9935", "shasum": "" }, "require": { - "php": "^7.1.3", + "php": "^7.2.5", "symfony/polyfill-mbstring": "~1.0", "symfony/polyfill-php73": "^1.8", "symfony/service-contracts": "^1.1|^2" }, "conflict": { - "symfony/dependency-injection": "<3.4", - "symfony/event-dispatcher": "<4.3|>=5", + "symfony/dependency-injection": "<4.4", + "symfony/event-dispatcher": "<4.4", "symfony/lock": "<4.4", - "symfony/process": "<3.3" + "symfony/process": "<4.4" }, "provide": { "psr/log-implementation": "1.0" }, "require-dev": { "psr/log": "~1.0", - "symfony/config": "^3.4|^4.0|^5.0", - "symfony/dependency-injection": "^3.4|^4.0|^5.0", - "symfony/event-dispatcher": "^4.3", + "symfony/config": "^4.4|^5.0", + "symfony/dependency-injection": "^4.4|^5.0", + "symfony/event-dispatcher": "^4.4|^5.0", "symfony/lock": "^4.4|^5.0", - "symfony/process": "^3.4|^4.0|^5.0", - "symfony/var-dumper": "^4.3|^5.0" + "symfony/process": "^4.4|^5.0", + "symfony/var-dumper": "^4.4|^5.0" }, "suggest": { "psr/log": "For using the console logger", @@ -5295,7 +5389,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "4.4-dev" + "dev-master": "5.0-dev" } }, "autoload": { @@ -5322,7 +5416,7 @@ ], "description": "Symfony Console Component", "homepage": "https://symfony.com", - "time": "2019-11-13T07:39:40+00:00" + "time": "2020-03-30T11:42:42+00:00" }, { "name": "symfony/dependency-injection", @@ -5454,37 +5548,37 @@ }, { "name": "symfony/event-dispatcher", - "version": "v4.4.0", + "version": "v5.0.8", "source": { "type": "git", "url": "https://github.com/symfony/event-dispatcher.git", - "reference": "ab1c43e17fff802bef0a898f3bc088ac33b8e0e1" + "reference": "24f40d95385774ed5c71dbf014edd047e2f2f3dc" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/ab1c43e17fff802bef0a898f3bc088ac33b8e0e1", - "reference": "ab1c43e17fff802bef0a898f3bc088ac33b8e0e1", + "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/24f40d95385774ed5c71dbf014edd047e2f2f3dc", + "reference": "24f40d95385774ed5c71dbf014edd047e2f2f3dc", "shasum": "" }, "require": { - "php": "^7.1.3", - "symfony/event-dispatcher-contracts": "^1.1" + "php": "^7.2.5", + "symfony/event-dispatcher-contracts": "^2" }, "conflict": { - "symfony/dependency-injection": "<3.4" + "symfony/dependency-injection": "<4.4" }, "provide": { "psr/event-dispatcher-implementation": "1.0", - "symfony/event-dispatcher-implementation": "1.1" + "symfony/event-dispatcher-implementation": "2.0" }, "require-dev": { "psr/log": "~1.0", - "symfony/config": "^3.4|^4.0|^5.0", - "symfony/dependency-injection": "^3.4|^4.0|^5.0", - "symfony/expression-language": "^3.4|^4.0|^5.0", - "symfony/http-foundation": "^3.4|^4.0|^5.0", + "symfony/config": "^4.4|^5.0", + "symfony/dependency-injection": "^4.4|^5.0", + "symfony/expression-language": "^4.4|^5.0", + "symfony/http-foundation": "^4.4|^5.0", "symfony/service-contracts": "^1.1|^2", - "symfony/stopwatch": "^3.4|^4.0|^5.0" + "symfony/stopwatch": "^4.4|^5.0" }, "suggest": { "symfony/dependency-injection": "", @@ -5493,7 +5587,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "4.4-dev" + "dev-master": "5.0-dev" } }, "autoload": { @@ -5520,33 +5614,33 @@ ], "description": "Symfony EventDispatcher Component", "homepage": "https://symfony.com", - "time": "2019-11-08T22:40:51+00:00" + "time": "2020-03-27T16:56:45+00:00" }, { "name": "symfony/event-dispatcher-contracts", - "version": "v1.1.7", + "version": "v2.0.1", "source": { "type": "git", "url": "https://github.com/symfony/event-dispatcher-contracts.git", - "reference": "c43ab685673fb6c8d84220c77897b1d6cdbe1d18" + "reference": "af23c2584d4577d54661c434446fb8fbed6025dd" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/event-dispatcher-contracts/zipball/c43ab685673fb6c8d84220c77897b1d6cdbe1d18", - "reference": "c43ab685673fb6c8d84220c77897b1d6cdbe1d18", + "url": "https://api.github.com/repos/symfony/event-dispatcher-contracts/zipball/af23c2584d4577d54661c434446fb8fbed6025dd", + "reference": "af23c2584d4577d54661c434446fb8fbed6025dd", "shasum": "" }, "require": { - "php": "^7.1.3" + "php": "^7.2.5", + "psr/event-dispatcher": "^1" }, "suggest": { - "psr/event-dispatcher": "", "symfony/event-dispatcher-implementation": "" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.1-dev" + "dev-master": "2.0-dev" } }, "autoload": { @@ -5578,30 +5672,30 @@ "interoperability", "standards" ], - "time": "2019-09-17T09:54:03+00:00" + "time": "2019-11-18T17:27:11+00:00" }, { "name": "symfony/filesystem", - "version": "v4.4.0", + "version": "v5.0.8", "source": { "type": "git", "url": "https://github.com/symfony/filesystem.git", - "reference": "d12b01cba60be77b583c9af660007211e3909854" + "reference": "7cd0dafc4353a0f62e307df90b48466379c8cc91" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/filesystem/zipball/d12b01cba60be77b583c9af660007211e3909854", - "reference": "d12b01cba60be77b583c9af660007211e3909854", + "url": "https://api.github.com/repos/symfony/filesystem/zipball/7cd0dafc4353a0f62e307df90b48466379c8cc91", + "reference": "7cd0dafc4353a0f62e307df90b48466379c8cc91", "shasum": "" }, "require": { - "php": "^7.1.3", + "php": "^7.2.5", "symfony/polyfill-ctype": "~1.8" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "4.4-dev" + "dev-master": "5.0-dev" } }, "autoload": { @@ -5628,56 +5722,7 @@ ], "description": "Symfony Filesystem Component", "homepage": "https://symfony.com", - "time": "2019-11-12T14:51:11+00:00" - }, - { - "name": "symfony/finder", - "version": "v4.4.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/finder.git", - "reference": "ce8743441da64c41e2a667b8eb66070444ed911e" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/finder/zipball/ce8743441da64c41e2a667b8eb66070444ed911e", - "reference": "ce8743441da64c41e2a667b8eb66070444ed911e", - "shasum": "" - }, - "require": { - "php": "^7.1.3" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "4.4-dev" - } - }, - "autoload": { - "psr-4": { - "Symfony\\Component\\Finder\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony Finder Component", - "homepage": "https://symfony.com", - "time": "2019-11-17T21:56:56+00:00" + "time": "2020-04-12T14:40:17+00:00" }, { "name": "symfony/options-resolver", @@ -5735,16 +5780,16 @@ }, { "name": "symfony/polyfill-php73", - "version": "v1.13.0", + "version": "v1.17.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-php73.git", - "reference": "4b0e2222c55a25b4541305a053013d5647d3a25f" + "reference": "a760d8964ff79ab9bf057613a5808284ec852ccc" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php73/zipball/4b0e2222c55a25b4541305a053013d5647d3a25f", - "reference": "4b0e2222c55a25b4541305a053013d5647d3a25f", + "url": "https://api.github.com/repos/symfony/polyfill-php73/zipball/a760d8964ff79ab9bf057613a5808284ec852ccc", + "reference": "a760d8964ff79ab9bf057613a5808284ec852ccc", "shasum": "" }, "require": { @@ -5753,7 +5798,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "1.13-dev" + "dev-master": "1.17-dev" } }, "autoload": { @@ -5789,24 +5834,24 @@ "portable", "shim" ], - "time": "2019-11-27T16:25:15+00:00" + "time": "2020-05-12T16:47:27+00:00" }, { "name": "symfony/service-contracts", - "version": "v2.0.0", + "version": "v2.0.1", "source": { "type": "git", "url": "https://github.com/symfony/service-contracts.git", - "reference": "9d99e1556417bf227a62e14856d630672bf10eaf" + "reference": "144c5e51266b281231e947b51223ba14acf1a749" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/service-contracts/zipball/9d99e1556417bf227a62e14856d630672bf10eaf", - "reference": "9d99e1556417bf227a62e14856d630672bf10eaf", + "url": "https://api.github.com/repos/symfony/service-contracts/zipball/144c5e51266b281231e947b51223ba14acf1a749", + "reference": "144c5e51266b281231e947b51223ba14acf1a749", "shasum": "" }, "require": { - "php": "^7.2.9", + "php": "^7.2.5", "psr/container": "^1.0" }, "suggest": { @@ -5847,7 +5892,7 @@ "interoperability", "standards" ], - "time": "2019-11-09T09:18:34+00:00" + "time": "2019-11-18T17:27:11+00:00" }, { "name": "symfony/var-dumper", From 190238ab960ce9c176e59eae2c814394bd34aed4 Mon Sep 17 00:00:00 2001 From: Pierre Rudloff Date: Mon, 8 Jun 2020 23:42:37 +0200 Subject: [PATCH 09/34] No reason to hide "git describe" output --- RoboFile.php | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/RoboFile.php b/RoboFile.php index f4980cf..6481aa6 100644 --- a/RoboFile.php +++ b/RoboFile.php @@ -17,10 +17,9 @@ class RoboFile extends Tasks { $result = $this->taskExec('git') ->args('describe') - ->printOutput(false) ->run(); $result->provideOutputdata(); - $tag = $result->getOutputData(); + $tag = trim($result->getOutputData()); // We don't want the whole vendor directory. $finder = new Finder(); From 4ef7a93dce5f527eb4d786cc5b214c8cbeed97fa Mon Sep 17 00:00:00 2001 From: Pierre Rudloff Date: Mon, 8 Jun 2020 23:49:59 +0200 Subject: [PATCH 10/34] Escape error message Because of the "Maybe you have characters before an opening getMessage()); } catch (Throwable $e) { // 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())); } From 29756cf290006fbd610a46f74040ce6cf29f0077 Mon Sep 17 00:00:00 2001 From: Pierre Rudloff Date: Sat, 20 Jun 2020 13:33:16 +0200 Subject: [PATCH 11/34] Add fallback to bestvideo and worstvideo (fixes #288) --- classes/Config.php | 29 +++++++++++++++++------------ config/config.example.yml | 4 ++-- controllers/BaseController.php | 7 ++++--- 3 files changed, 23 insertions(+), 17 deletions(-) diff --git a/classes/Config.php b/classes/Config.php index d8ca08f..62a1698 100644 --- a/classes/Config.php +++ b/classes/Config.php @@ -151,9 +151,9 @@ class Config if (empty($this->genericFormats)) { // We don't put this in the class definition so it can be detected by xgettext. $this->genericFormats = [ - 'best' => $localeManager->t('Best'), + 'best/bestvideo' => $localeManager->t('Best'), 'bestvideo+bestaudio' => $localeManager->t('Remux best video with best audio'), - 'worst' => $localeManager->t('Worst'), + 'worst/worstvideo' => $localeManager->t('Worst'), ]; } @@ -165,26 +165,31 @@ class Config } } elseif (!$this->stream) { // 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 $newFormat New format + * @param string $format Format * - * @return void + * @return string */ - private function replaceGenericFormat($oldFormat, $newFormat) + public static function addHttpToFormat($format) { - $keys = array_keys($this->genericFormats); - $keys[array_search($oldFormat, $keys)] = $newFormat; - if ($genericFormats = array_combine($keys, $this->genericFormats)) { - $this->genericFormats = $genericFormats; + $newFormat = []; + foreach (explode('/', $format) as $subformat) { + $newFormat[] = $subformat . '[protocol=https]'; + $newFormat[] = $subformat . '[protocol=http]'; } + + return implode('/', $newFormat); } /** diff --git a/config/config.example.yml b/config/config.example.yml index 7bf520c..29d6c5d 100644 --- a/config/config.example.yml +++ b/config/config.example.yml @@ -49,9 +49,9 @@ appName: AllTube Download # Generic formats supported by youtube-dl genericFormats: - best: Best + best/bestvideo: Best bestvideo+bestaudio: Remux best video with best audio - worst: Worst + worst/worstvideo: Worst # Enable debug mode. debug: false diff --git a/controllers/BaseController.php b/controllers/BaseController.php index 59e9862..bf48a24 100644 --- a/controllers/BaseController.php +++ b/controllers/BaseController.php @@ -31,7 +31,7 @@ abstract class BaseController * * @var string */ - protected $defaultFormat = 'best[protocol=https]/best[protocol=http]'; + protected $defaultFormat = 'best/bestvideo'; /** * Slim dependency container. @@ -74,8 +74,9 @@ abstract class BaseController $this->sessionSegment = $session->getSegment(self::class); $this->localeManager = $this->container->get('locale'); - if ($this->config->stream) { - $this->defaultFormat = 'best'; + if (!$this->config->stream) { + // Force HTTP if stream is not enabled. + $this->defaultFormat = Config::addHttpToFormat($this->defaultFormat); } } From a79c89aea7b4261a01f377f1e41d1dbebf298c8b Mon Sep 17 00:00:00 2001 From: Pierre Rudloff Date: Sat, 20 Jun 2020 13:39:35 +0200 Subject: [PATCH 12/34] fixup! Add fallback to bestvideo and worstvideo (fixes #288) --- classes/Video.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/classes/Video.php b/classes/Video.php index f88a088..38c9287 100644 --- a/classes/Video.php +++ b/classes/Video.php @@ -90,7 +90,7 @@ class Video * including selectors like "[height<=720]") * @param string $password Password */ - public function __construct($webpageUrl, $requestedFormat = 'best', $password = null) + public function __construct($webpageUrl, $requestedFormat = 'best/bestvideo', $password = null) { $this->webpageUrl = $webpageUrl; $this->requestedFormat = $requestedFormat; From f028db6b1ead623c77baa56584629b74abe49e81 Mon Sep 17 00:00:00 2001 From: Pierre Rudloff Date: Sat, 20 Jun 2020 13:44:40 +0200 Subject: [PATCH 13/34] "composer check-platform-reqs" on CI --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index c3316a3..02d0a2b 100644 --- a/.travis.yml +++ b/.travis.yml @@ -7,5 +7,6 @@ addons: - language-pack-fr install: composer install --no-progress script: + - composer check-platform-reqs - composer lint - composer test From 359615d0edb7daede7c37620272847578d459f12 Mon Sep 17 00:00:00 2001 From: Pierre Rudloff Date: Sat, 20 Jun 2020 13:49:01 +0200 Subject: [PATCH 14/34] grumphp update To provide Composer 2 compatibility --- composer.lock | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/composer.lock b/composer.lock index 4acd9ea..36a3581 100644 --- a/composer.lock +++ b/composer.lock @@ -3557,20 +3557,20 @@ }, { "name": "phpro/grumphp", - "version": "v0.18.0", + "version": "v0.18.1", "source": { "type": "git", "url": "https://github.com/phpro/grumphp.git", - "reference": "b3d80bbcbac8068f21ea5f5da18a4af01d2d471d" + "reference": "d07e59ebfdd48cf41d12b2af3670abcd1a2b01ef" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpro/grumphp/zipball/b3d80bbcbac8068f21ea5f5da18a4af01d2d471d", - "reference": "b3d80bbcbac8068f21ea5f5da18a4af01d2d471d", + "url": "https://api.github.com/repos/phpro/grumphp/zipball/d07e59ebfdd48cf41d12b2af3670abcd1a2b01ef", + "reference": "d07e59ebfdd48cf41d12b2af3670abcd1a2b01ef", "shasum": "" }, "require": { - "composer-plugin-api": "~1.0", + "composer-plugin-api": "~1.0 || ~2.0", "doctrine/collections": "~1.2", "ext-json": "*", "gitonomy/gitlib": "^1.0.3", @@ -3588,10 +3588,9 @@ "symfony/yaml": "~3.4 || ~4.0 || ~5.0" }, "require-dev": { - "brianium/paratest": "~3.1", - "composer/composer": "~1.9", + "brianium/paratest": "~3.1 || dev-master", + "composer/composer": "~1.9 || ^2.0@dev", "ergebnis/composer-normalize": "~2.1", - "friendsofphp/php-cs-fixer": "~2.16", "jakub-onderka/php-parallel-lint": "~1.0", "nikic/php-parser": "~3.1", "phpspec/phpspec": "~6.1", @@ -3658,7 +3657,7 @@ } ], "description": "A composer plugin that enables source code quality checks.", - "time": "2020-02-25T17:51:17+00:00" + "time": "2020-05-27T04:48:38+00:00" }, { "name": "phpspec/prophecy", From 672a1a9754bfae5e1d5be928213766ea9e4d0ac0 Mon Sep 17 00:00:00 2001 From: Pierre Rudloff Date: Sat, 20 Jun 2020 14:14:38 +0200 Subject: [PATCH 15/34] Disable debug mode if dev dependencies are not installed --- classes/Config.php | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/classes/Config.php b/classes/Config.php index 62a1698..e308218 100644 --- a/classes/Config.php +++ b/classes/Config.php @@ -8,6 +8,7 @@ namespace Alltube; use Exception; use Jawira\CaseConverter\CaseConverterException; +use Symfony\Component\ErrorHandler\Debug; use Symfony\Component\Yaml\Yaml; use Jawira\CaseConverter\Convert; @@ -211,6 +212,11 @@ class Config } elseif (!Video::checkCommand([$this->python, '--version'])) { throw new Exception("Can't find Python at " . $this->python); } + + if (!class_exists(Debug::class)) { + // Dev dependencies are probably not installed. + $this->debug = false; + } } /** From 62dac1e5bb66ff4a2698cca7aca06ce4bc92551b Mon Sep 17 00:00:00 2001 From: Pierre Rudloff Date: Sat, 20 Jun 2020 14:20:31 +0200 Subject: [PATCH 16/34] =?UTF-8?q?Move=20youtube-dl,=20ffmpeg=20and=20phant?= =?UTF-8?q?omsjs=20to=20dev=20dependencies=20(fixes=C2=A0#280)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- composer.json | 9 ++- composer.lock | 151 ++++++++++++++++++++++++++------------------------ 2 files changed, 82 insertions(+), 78 deletions(-) diff --git a/composer.json b/composer.json index b223fec..736e380 100644 --- a/composer.json +++ b/composer.json @@ -7,8 +7,10 @@ "require": { "ext-intl": "*", "ext-json": "*", + "anam/phantomjs-linux-x86-binary": "^2.1", "aura/session": "^2.1", "barracudanetworks/archivestream-php": "^1.0", + "ffmpeg/ffmpeg": "^4.1", "guzzlehttp/guzzle": "^6.5", "jawira/case-converter": "^3.4", "mathmarques/smarty-view": "^1.1", @@ -18,12 +20,11 @@ "symfony/process": "^4.0", "symfony/translation": "^4.0", "symfony/yaml": "^4.0", + "ytdl-org/youtube-dl": "^2020.05", "zonuexe/http-accept-language": "^0.4.1" }, "require-dev": { - "anam/phantomjs-linux-x86-binary": "^2.1", "consolidation/robo": "^2.1", - "ffmpeg/ffmpeg": "^4.1", "heroku/heroku-buildpack-php": "^162.0", "php-mock/php-mock-mockery": "^1.3", "phpro/grumphp": "^0.18.0", @@ -33,8 +34,7 @@ "smarty-gettext/smarty-gettext": "^1.6", "squizlabs/php_codesniffer": "^3.5", "symfony/error-handler": "^5.0", - "symfony/var-dumper": "^5.0", - "ytdl-org/youtube-dl": "^2020.05" + "symfony/var-dumper": "^5.0" }, "extra": { "paas": { @@ -98,7 +98,6 @@ } }, "scripts": { - "compile": "composer install --ignore-platform-reqs", "lint": "grumphp run --ansi", "test": "phpunit", "release": "robo release", diff --git a/composer.lock b/composer.lock index 36a3581..26d0ff0 100644 --- a/composer.lock +++ b/composer.lock @@ -4,8 +4,50 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "e02a081a0f220bf779ab5ba047c1ca68", + "content-hash": "a61a7bc33d1de355e511fe3aa1b6a193", "packages": [ + { + "name": "anam/phantomjs-linux-x86-binary", + "version": "v2.1.1", + "source": { + "type": "git", + "url": "https://github.com/anam-hossain/phantomjs-linux-x86-binary.git", + "reference": "cb90cd0e7bd4ad34f52e6834783b1c5adae15014" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/anam-hossain/phantomjs-linux-x86-binary/zipball/cb90cd0e7bd4ad34f52e6834783b1c5adae15014", + "reference": "cb90cd0e7bd4ad34f52e6834783b1c5adae15014", + "shasum": "" + }, + "bin": [ + "bin/phantomjs" + ], + "type": "library", + "autoload": { + "psr-4": { + "Anam\\PhantomLinux\\": "/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-2-Clause" + ], + "authors": [ + { + "name": "Anam hossain", + "email": "enam33@gmail.com" + } + ], + "description": "PhantomJS static linked binary for 64 bit linux systems. Most of Linux distributions are supported including Ubuntu, Debian, Fedora and CentOS.", + "homepage": "http://phantomjs.org/download.html", + "keywords": [ + "binary", + "phantomjs", + "phantomjs binary" + ], + "time": "2016-04-05T05:24:48+00:00" + }, { "name": "aura/session", "version": "2.1.0", @@ -108,6 +150,18 @@ ], "time": "2018-08-10T13:58:33+00:00" }, + { + "name": "ffmpeg/ffmpeg", + "version": "4.1.4", + "dist": { + "type": "xz", + "url": "https://www.johnvansickle.com/ffmpeg/old-releases/ffmpeg-4.1.4-amd64-static.tar.xz" + }, + "bin": [ + "ffmpeg" + ], + "type": "library" + }, { "name": "guzzlehttp/guzzle", "version": "6.5.3", @@ -1386,6 +1440,15 @@ "homepage": "https://symfony.com", "time": "2019-11-12T14:51:11+00:00" }, + { + "name": "ytdl-org/youtube-dl", + "version": "2020.05.08", + "dist": { + "type": "zip", + "url": "https://github.com/ytdl-org/youtube-dl/archive/2020.05.08.zip" + }, + "type": "library" + }, { "name": "zonuexe/http-accept-language", "version": "0.4.1", @@ -1429,48 +1492,6 @@ } ], "packages-dev": [ - { - "name": "anam/phantomjs-linux-x86-binary", - "version": "v2.1.1", - "source": { - "type": "git", - "url": "https://github.com/anam-hossain/phantomjs-linux-x86-binary.git", - "reference": "cb90cd0e7bd4ad34f52e6834783b1c5adae15014" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/anam-hossain/phantomjs-linux-x86-binary/zipball/cb90cd0e7bd4ad34f52e6834783b1c5adae15014", - "reference": "cb90cd0e7bd4ad34f52e6834783b1c5adae15014", - "shasum": "" - }, - "bin": [ - "bin/phantomjs" - ], - "type": "library", - "autoload": { - "psr-4": { - "Anam\\PhantomLinux\\": "/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-2-Clause" - ], - "authors": [ - { - "name": "Anam hossain", - "email": "enam33@gmail.com" - } - ], - "description": "PhantomJS static linked binary for 64 bit linux systems. Most of Linux distributions are supported including Ubuntu, Debian, Fedora and CentOS.", - "homepage": "http://phantomjs.org/download.html", - "keywords": [ - "binary", - "phantomjs", - "phantomjs binary" - ], - "time": "2016-04-05T05:24:48+00:00" - }, { "name": "consolidation/annotated-command", "version": "4.1.1", @@ -2093,18 +2114,6 @@ ], "time": "2019-10-21T16:45:58+00:00" }, - { - "name": "ffmpeg/ffmpeg", - "version": "4.1.4", - "dist": { - "type": "xz", - "url": "https://www.johnvansickle.com/ffmpeg/old-releases/ffmpeg-4.1.4-amd64-static.tar.xz" - }, - "bin": [ - "ffmpeg" - ], - "type": "library" - }, { "name": "gitonomy/gitlib", "version": "v1.1.0", @@ -4243,12 +4252,12 @@ "source": { "type": "git", "url": "https://github.com/Roave/SecurityAdvisories.git", - "reference": "e38de1df609b39d97144514d28b0804ad4daaddb" + "reference": "6d2e5ab854782830911ddd33b7d4649b9f18c10f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Roave/SecurityAdvisories/zipball/e38de1df609b39d97144514d28b0804ad4daaddb", - "reference": "e38de1df609b39d97144514d28b0804ad4daaddb", + "url": "https://api.github.com/repos/Roave/SecurityAdvisories/zipball/6d2e5ab854782830911ddd33b7d4649b9f18c10f", + "reference": "6d2e5ab854782830911ddd33b7d4649b9f18c10f", "shasum": "" }, "conflict": { @@ -4257,13 +4266,14 @@ "alterphp/easyadmin-extension-bundle": ">=1.2,<1.2.11|>=1.3,<1.3.1", "amphp/artax": "<1.0.6|>=2,<2.0.6", "amphp/http": "<1.0.1", + "amphp/http-client": ">=4,<4.4", "api-platform/core": ">=2.2,<2.2.10|>=2.3,<2.3.6", "asymmetricrypt/asymmetricrypt": ">=0,<9.9.99", "aws/aws-sdk-php": ">=3,<3.2.1", "bagisto/bagisto": "<0.1.5", "barrelstrength/sprout-base-email": "<1.2.7", "barrelstrength/sprout-forms": "<3.9", - "bolt/bolt": "<3.6.10", + "bolt/bolt": "<3.7.1", "brightlocal/phpwhois": "<=4.2.5", "buddypress/buddypress": "<5.1.2", "bugsnag/bugsnag-laravel": ">=2,<2.0.2", @@ -4291,8 +4301,8 @@ "doctrine/orm": ">=2,<2.4.8|>=2.5,<2.5.1", "dolibarr/dolibarr": "<11.0.4", "dompdf/dompdf": ">=0.6,<0.6.2", - "drupal/core": ">=7,<7.70|>=8,<8.7.14|>=8.8,<8.8.6", - "drupal/drupal": ">=7,<7.70|>=8,<8.7.14|>=8.8,<8.8.6", + "drupal/core": ">=7,<7.72|>=8,<8.8.8|>=8.9,<8.9.1|>=9,<9.0.1", + "drupal/drupal": ">=7,<7.72|>=8,<8.8.8|>=8.9,<8.9.1|>=9,<9.0.1", "endroid/qr-code-bundle": "<3.4.2", "enshrined/svg-sanitize": "<0.13.1", "erusev/parsedown": "<1.7.2", @@ -4302,8 +4312,9 @@ "ezsystems/ezplatform": ">=1.7,<1.7.9.1|>=1.13,<1.13.5.1|>=2.5,<2.5.4", "ezsystems/ezplatform-admin-ui": ">=1.3,<1.3.5|>=1.4,<1.4.6", "ezsystems/ezplatform-admin-ui-assets": ">=4,<4.2", + "ezsystems/ezplatform-kernel": ">=1,<1.0.2.1", "ezsystems/ezplatform-user": ">=1,<1.0.1", - "ezsystems/ezpublish-kernel": ">=5.3,<5.3.12.1|>=5.4,<5.4.14.1|>=6,<6.7.9.1|>=6.8,<6.13.6.2|>=7,<7.2.4.1|>=7.3,<7.3.2.1|>=7.5,<7.5.6.2", + "ezsystems/ezpublish-kernel": ">=5.3,<5.3.12.1|>=5.4,<5.4.14.2|>=6,<6.7.9.1|>=6.8,<6.13.6.3|>=7,<7.2.4.1|>=7.3,<7.3.2.1|>=7.5,<7.5.7.1", "ezsystems/ezpublish-legacy": ">=5.3,<5.3.12.6|>=5.4,<5.4.14.1|>=2011,<2017.12.7.2|>=2018.6,<2018.6.1.4|>=2018.9,<2018.9.1.3|>=2019.3,<2019.3.4.2", "ezsystems/repository-forms": ">=2.3,<2.3.2.1", "ezyang/htmlpurifier": "<4.1.1", @@ -4341,6 +4352,7 @@ "monolog/monolog": ">=1.8,<1.12", "namshi/jose": "<2.2", "nzo/url-encryptor-bundle": ">=4,<4.3.2|>=5,<5.0.1", + "october/october": ">=1.0.319,<1.0.466", "onelogin/php-saml": "<2.10.4", "oneup/uploader-bundle": "<1.9.3|>=2,<2.1.5", "openid/php-openid": "<2.3", @@ -4352,7 +4364,8 @@ "paypal/merchant-sdk-php": "<3.12", "pear/archive_tar": "<1.4.4", "phpfastcache/phpfastcache": ">=5,<5.0.13", - "phpmailer/phpmailer": ">=5,<5.2.27|>=6,<6.0.6", + "phpmailer/phpmailer": "<6.1.6", + "phpmussel/phpmussel": ">=1,<1.6", "phpmyadmin/phpmyadmin": "<4.9.2", "phpoffice/phpexcel": "<1.8.2", "phpoffice/phpspreadsheet": "<1.8", @@ -4367,6 +4380,7 @@ "propel/propel": ">=2-alpha.1,<=2-alpha.7", "propel/propel1": ">=1,<=1.7.1", "pusher/pusher-php-server": "<2.2.1", + "rainlab/debugbar-plugin": "<3.1", "robrichards/xmlseclibs": "<3.0.4", "sabre/dav": ">=1.6,<1.6.99|>=1.7,<1.7.11|>=1.8,<1.8.9", "scheb/two-factor-bundle": ">=0,<3.26|>=4,<4.11", @@ -4505,7 +4519,7 @@ } ], "description": "Prevents installation of composer packages with known security vulnerabilities: no API, simply require it", - "time": "2020-05-22T06:49:22+00:00" + "time": "2020-06-19T13:23:43+00:00" }, { "name": "sebastian/code-unit-reverse-lookup", @@ -6055,15 +6069,6 @@ "validate" ], "time": "2019-11-24T13:36:37+00:00" - }, - { - "name": "ytdl-org/youtube-dl", - "version": "2020.05.08", - "dist": { - "type": "zip", - "url": "https://github.com/ytdl-org/youtube-dl/archive/2020.05.08.zip" - }, - "type": "library" } ], "aliases": [], From 7d94271a491885cbf2997364038d0c7bb67a7244 Mon Sep 17 00:00:00 2001 From: Pierre Rudloff Date: Sat, 20 Jun 2020 14:24:47 +0200 Subject: [PATCH 17/34] Remove support for launching Heroku locally This is untested and probably broken --- composer.json | 1 - composer.lock | 46 +--------------------------------------------- resources/FAQ.md | 24 ------------------------ 3 files changed, 1 insertion(+), 70 deletions(-) diff --git a/composer.json b/composer.json index 736e380..36c437b 100644 --- a/composer.json +++ b/composer.json @@ -25,7 +25,6 @@ }, "require-dev": { "consolidation/robo": "^2.1", - "heroku/heroku-buildpack-php": "^162.0", "php-mock/php-mock-mockery": "^1.3", "phpro/grumphp": "^0.18.0", "phpstan/phpstan": "^0.12.25", diff --git a/composer.lock b/composer.lock index 26d0ff0..c1459b1 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "a61a7bc33d1de355e511fe3aa1b6a193", + "content-hash": "5b43d7dd93a519a8edb85623fcffc639", "packages": [ { "name": "anam/phantomjs-linux-x86-binary", @@ -2313,50 +2313,6 @@ ], "time": "2016-01-20T08:20:44+00:00" }, - { - "name": "heroku/heroku-buildpack-php", - "version": "v162", - "source": { - "type": "git", - "url": "https://github.com/heroku/heroku-buildpack-php.git", - "reference": "343fa959d4c195beb7febe1996340624baf713b9" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/heroku/heroku-buildpack-php/zipball/343fa959d4c195beb7febe1996340624baf713b9", - "reference": "343fa959d4c195beb7febe1996340624baf713b9", - "shasum": "" - }, - "bin": [ - "bin/heroku-hhvm-apache2", - "bin/heroku-hhvm-nginx", - "bin/heroku-php-apache2", - "bin/heroku-php-nginx" - ], - "type": "library", - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "David Zuelke", - "email": "dz@heroku.com" - } - ], - "description": "Toolkit for starting a PHP application locally, with or without foreman, using the same config for PHP/HHVM and Apache2/Nginx as on Heroku", - "homepage": "https://github.com/heroku/heroku-buildpack-php", - "keywords": [ - "apache", - "apache2", - "foreman", - "heroku", - "hhvm", - "nginx", - "php" - ], - "time": "2019-09-27T22:17:17+00:00" - }, { "name": "league/container", "version": "2.4.1", diff --git a/resources/FAQ.md b/resources/FAQ.md index d6304e8..c2d3b65 100644 --- a/resources/FAQ.md +++ b/resources/FAQ.md @@ -113,30 +113,6 @@ you can download it if you enable streaming (see above). 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 Youtube distributes HD content in two separate video and audio files. From 5c2823e3f1bc8605830b41a51f0d3f6ca5054844 Mon Sep 17 00:00:00 2001 From: Pierre Rudloff Date: Sun, 21 Jun 2020 01:44:20 +0200 Subject: [PATCH 18/34] Move Video class to a separate library + improve error handling + youtube-dl update --- README.md | 28 +- classes/Config.php | 54 +- classes/UglyRouter.php | 1 - classes/Video.php | 647 ------------------ classes/exceptions/ConfigException.php | 10 + classes/exceptions/EmptyUrlException.php | 16 - classes/exceptions/PasswordException.php | 16 - .../ConvertedPlaylistArchiveStream.php | 8 +- classes/streams/PlaylistArchiveStream.php | 28 +- classes/streams/YoutubeStream.php | 16 +- composer.json | 9 +- composer.lock | 81 ++- controllers/BaseController.php | 28 +- controllers/DownloadController.php | 156 +++-- controllers/FrontController.php | 65 +- controllers/JsonController.php | 19 +- i18n/template.pot | 227 +++--- templates/error.tpl | 2 +- tests/BaseTest.php | 4 +- tests/ConfigTest.php | 18 +- tests/ControllerTest.php | 5 +- tests/ConvertedPlaylistArchiveStreamTest.php | 12 +- tests/DownloadControllerTest.php | 29 +- tests/FrontControllerTest.php | 22 +- tests/JsonControllerTest.php | 9 +- tests/PlaylistArchiveStreamTest.php | 12 +- tests/VideoStubsTest.php | 54 +- tests/VideoTest.php | 198 +++--- tests/YoutubeChunkStreamTest.php | 14 +- tests/YoutubeStreamTest.php | 13 +- 30 files changed, 649 insertions(+), 1152 deletions(-) delete mode 100644 classes/Video.php create mode 100644 classes/exceptions/ConfigException.php delete mode 100644 classes/exceptions/EmptyUrlException.php delete mode 100644 classes/exceptions/PasswordException.php diff --git a/README.md b/README.md index a310a85..9b60df9 100644 --- a/README.md +++ b/README.md @@ -148,32 +148,8 @@ so that it points to your ffmpeg/avconv binary (`/usr/bin/avconv` on Debian/Ubun ## Use as library -AllTube can also be used as a library to extract a video URL from a webpage. - -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). +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. ## JSON API diff --git a/classes/Config.php b/classes/Config.php index e308218..337192a 100644 --- a/classes/Config.php +++ b/classes/Config.php @@ -6,7 +6,8 @@ namespace Alltube; -use Exception; +use Alltube\Exception\ConfigException; +use Alltube\Library\Downloader; use Jawira\CaseConverter\CaseConverterException; use Symfony\Component\ErrorHandler\Debug; use Symfony\Component\Yaml\Yaml; @@ -141,7 +142,7 @@ class Config * Config constructor. * * @param mixed[] $options Options - * @throws CaseConverterException + * @throws ConfigException */ private function __construct(array $options = []) { @@ -197,20 +198,15 @@ class Config * Throw an exception if some of the options are invalid. * * @return void - * @throws Exception If Python is missing - * - * @throws Exception If youtube-dl is missing + * @throws ConfigException If Python is missing + * @throws ConfigException If youtube-dl is missing */ 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)) { - throw new Exception("Can't find youtube-dl at " . $this->youtubedl); - } elseif (!Video::checkCommand([$this->python, '--version'])) { - throw new Exception("Can't find Python at " . $this->python); + throw new ConfigException("Can't find youtube-dl at " . $this->youtubedl); + } elseif (!Downloader::checkCommand([$this->python, '--version'])) { + throw new ConfigException("Can't find Python at " . $this->python); } if (!class_exists(Debug::class)) { @@ -241,13 +237,18 @@ class Config * If the value is an array, you should use the YAML format: "CONVERT_ADVANCED_FORMATS='[foo, bar]'" * * @return void - * @throws CaseConverterException + * @throws ConfigException */ private function getEnv() { foreach (get_object_vars($this) as $prop => $value) { - $convert = new Convert($prop); - $env = getenv($convert->toMacro()); + try { + $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) { $this->$prop = Yaml::parse($env); } @@ -273,7 +274,7 @@ class Config * * @param string $file Path to the YAML file * @return void - * @throws Exception + * @throws ConfigException */ public static function setFile($file) { @@ -282,7 +283,7 @@ class Config self::$instance = new self($options); self::$instance->validateOptions(); } else { - throw new Exception("Can't find config file at " . $file); + throw new ConfigException("Can't find config file at " . $file); } } @@ -292,7 +293,7 @@ class Config * @param mixed[] $options Options (see `config/config.example.yml` for available options) * @param bool $update True to update an existing instance * @return void - * @throws Exception + * @throws ConfigException */ public static function setOptions(array $options, $update = true) { @@ -314,4 +315,21 @@ class Config { 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->avconv, + $this->phantomjsDir, + $this->avconvVerbosity + ); + } } diff --git a/classes/UglyRouter.php b/classes/UglyRouter.php index f03efe7..a5b1020 100644 --- a/classes/UglyRouter.php +++ b/classes/UglyRouter.php @@ -48,7 +48,6 @@ class UglyRouter extends Router * * @return string * @throws InvalidArgumentException If required data not provided - * * @throws RuntimeException If named route does not exist */ public function pathFor($name, array $data = [], array $queryParams = []) diff --git a/classes/Video.php b/classes/Video.php deleted file mode 100644 index 38c9287..0000000 --- a/classes/Video.php +++ /dev/null @@ -1,647 +0,0 @@ -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 - */ - 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 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) - ] - ); - } -} diff --git a/classes/exceptions/ConfigException.php b/classes/exceptions/ConfigException.php new file mode 100644 index 0000000..f533b35 --- /dev/null +++ b/classes/exceptions/ConfigException.php @@ -0,0 +1,10 @@ +curVideoStream = new Stream($video->getAudioStream()); + $this->curVideoStream = new Stream($this->downloader->getAudioStream($video)); $this->init_file_stream_transfer( $video->getFileNameWithExtension('mp3'), diff --git a/classes/streams/PlaylistArchiveStream.php b/classes/streams/PlaylistArchiveStream.php index 2e682fb..d55e554 100644 --- a/classes/streams/PlaylistArchiveStream.php +++ b/classes/streams/PlaylistArchiveStream.php @@ -6,9 +6,9 @@ namespace Alltube\Stream; -use Alltube\Exception\EmptyUrlException; -use Alltube\Exception\PasswordException; -use Alltube\Video; +use Alltube\Library\Downloader; +use Alltube\Library\Exception\AlltubeLibraryException; +use Alltube\Library\Video; use Barracuda\ArchiveStream\ZipArchive; use Psr\Http\Message\StreamInterface; @@ -47,22 +47,32 @@ class PlaylistArchiveStream extends ZipArchive implements StreamInterface */ private $isComplete = false; + /** + * Downloader object. + * + * @var Downloader + */ + protected $downloader; + /** * PlaylistArchiveStream constructor. * * 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 * @noinspection PhpMissingParentConstructorInspection */ - public function __construct(Video $video) + public function __construct(Downloader $downloader, Video $video) { + $this->downloader = $downloader; + $buffer = fopen('php://temp', 'r+'); if ($buffer !== false) { $this->buffer = $buffer; } 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 * * @return void - * @throws PasswordException - * @throws EmptyUrlException + * @throws AlltubeLibraryException */ protected function startVideoStream(Video $video) { - $response = $video->getHttpResponse(); + $response = $this->downloader->getHttpResponse($video); $this->curVideoStream = $response->getBody(); $contentLengthHeaders = $response->getHeader('Content-Length'); @@ -266,8 +275,7 @@ class PlaylistArchiveStream extends ZipArchive implements StreamInterface * @param int $count Number of bytes to read * * @return string|false - * @throws EmptyUrlException - * @throws PasswordException + * @throws AlltubeLibraryException */ public function read($count) { diff --git a/classes/streams/YoutubeStream.php b/classes/streams/YoutubeStream.php index 3995d11..fdd19dd 100644 --- a/classes/streams/YoutubeStream.php +++ b/classes/streams/YoutubeStream.php @@ -6,9 +6,9 @@ namespace Alltube\Stream; -use Alltube\Exception\EmptyUrlException; -use Alltube\Exception\PasswordException; -use Alltube\Video; +use Alltube\Library\Downloader; +use Alltube\Library\Exception\AlltubeLibraryException; +use Alltube\Library\Video; use GuzzleHttp\Psr7\AppendStream; /** @@ -20,15 +20,15 @@ class YoutubeStream extends AppendStream /** * YoutubeStream constructor. * + * @param Downloader $downloader Downloader object * @param Video $video Video to stream - * @throws EmptyUrlException - * @throws PasswordException + * @throws AlltubeLibraryException */ - public function __construct(Video $video) + public function __construct(Downloader $downloader, Video $video) { parent::__construct(); - $stream = $video->getHttpResponse(); + $stream = $downloader->getHttpResponse($video); $contentLenghtHeader = $stream->getHeader('Content-Length'); $rangeStart = 0; @@ -37,7 +37,7 @@ class YoutubeStream extends AppendStream if ($rangeEnd >= $contentLenghtHeader[0]) { $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)); $rangeStart = $rangeEnd + 1; } diff --git a/composer.json b/composer.json index 36c437b..83f059b 100644 --- a/composer.json +++ b/composer.json @@ -11,16 +11,15 @@ "aura/session": "^2.1", "barracudanetworks/archivestream-php": "^1.0", "ffmpeg/ffmpeg": "^4.1", - "guzzlehttp/guzzle": "^6.5", "jawira/case-converter": "^3.4", "mathmarques/smarty-view": "^1.1", "npm-asset/open-sans-fontface": "^1.4", "rinvex/countries": "^6.1", + "rudloff/alltube-library": "^0.1.0", "symfony/finder": "^5.0", - "symfony/process": "^4.0", "symfony/translation": "^4.0", "symfony/yaml": "^4.0", - "ytdl-org/youtube-dl": "^2020.05", + "ytdl-org/youtube-dl": "^2020.06", "zonuexe/http-accept-language": "^0.4.1" }, "require-dev": { @@ -51,10 +50,10 @@ "type": "package", "package": { "name": "ytdl-org/youtube-dl", - "version": "2020.05.08", + "version": "2020.06.16.1", "dist": { "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" } } }, diff --git a/composer.lock b/composer.lock index c1459b1..d164fd2 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "5b43d7dd93a519a8edb85623fcffc639", + "content-hash": "dba22d2bff872c8e1310567d4336db16", "packages": [ { "name": "anam/phantomjs-linux-x86-binary", @@ -164,16 +164,16 @@ }, { "name": "guzzlehttp/guzzle", - "version": "6.5.3", + "version": "6.5.5", "source": { "type": "git", "url": "https://github.com/guzzle/guzzle.git", - "reference": "aab4ebd862aa7d04f01a4b51849d657db56d882e" + "reference": "9d4290de1cfd701f38099ef7e183b64b4b7b0c5e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/guzzle/guzzle/zipball/aab4ebd862aa7d04f01a4b51849d657db56d882e", - "reference": "aab4ebd862aa7d04f01a4b51849d657db56d882e", + "url": "https://api.github.com/repos/guzzle/guzzle/zipball/9d4290de1cfd701f38099ef7e183b64b4b7b0c5e", + "reference": "9d4290de1cfd701f38099ef7e183b64b4b7b0c5e", "shasum": "" }, "require": { @@ -181,7 +181,7 @@ "guzzlehttp/promises": "^1.0", "guzzlehttp/psr7": "^1.6.1", "php": ">=5.5", - "symfony/polyfill-intl-idn": "^1.11" + "symfony/polyfill-intl-idn": "^1.17.0" }, "require-dev": { "ext-curl": "*", @@ -227,7 +227,7 @@ "rest", "web service" ], - "time": "2020-04-18T10:38:46+00:00" + "time": "2020-06-16T21:01:06+00:00" }, { "name": "guzzlehttp/promises", @@ -790,6 +790,47 @@ ], "time": "2020-03-13T18:04:45+00:00" }, + { + "name": "rudloff/alltube-library", + "version": "0.1.0", + "source": { + "type": "git", + "url": "https://github.com/Rudloff/alltube-library.git", + "reference": "09b47e0cf3157a79724177d6cadac8cee8cae588" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Rudloff/alltube-library/zipball/09b47e0cf3157a79724177d6cadac8cee8cae588", + "reference": "09b47e0cf3157a79724177d6cadac8cee8cae588", + "shasum": "" + }, + "require": { + "ext-json": "*", + "guzzlehttp/guzzle": "^6.5", + "symfony/process": "^4.0|^5.0" + }, + "require-dev": { + "phpro/grumphp": "^0.18.0", + "phpstan/phpstan": "^0.12.29", + "roave/security-advisories": "dev-master", + "squizlabs/php_codesniffer": "^3.5", + "symfony/var-dumper": "^5.1" + }, + "type": "library", + "autoload": { + "psr-4": { + "Alltube\\Library\\": "classes/", + "Alltube\\Library\\Exception\\": "classes/exceptions/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "GPL-3.0-only" + ], + "description": "PHP wrapper for youtube-dl", + "homepage": "http://alltubedownload.net/", + "time": "2020-06-21T12:25:10+00:00" + }, { "name": "slim/slim", "version": "3.12.3", @@ -1146,16 +1187,16 @@ }, { "name": "symfony/polyfill-php72", - "version": "v1.13.1", + "version": "v1.17.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-php72.git", - "reference": "66fea50f6cb37a35eea048d75a7d99a45b586038" + "reference": "f048e612a3905f34931127360bdd2def19a5e582" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php72/zipball/66fea50f6cb37a35eea048d75a7d99a45b586038", - "reference": "66fea50f6cb37a35eea048d75a7d99a45b586038", + "url": "https://api.github.com/repos/symfony/polyfill-php72/zipball/f048e612a3905f34931127360bdd2def19a5e582", + "reference": "f048e612a3905f34931127360bdd2def19a5e582", "shasum": "" }, "require": { @@ -1164,7 +1205,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "1.13-dev" + "dev-master": "1.17-dev" } }, "autoload": { @@ -1197,20 +1238,20 @@ "portable", "shim" ], - "time": "2019-11-27T13:56:44+00:00" + "time": "2020-05-12T16:47:27+00:00" }, { "name": "symfony/process", - "version": "v4.4.8", + "version": "v4.4.10", "source": { "type": "git", "url": "https://github.com/symfony/process.git", - "reference": "4b6a9a4013baa65d409153cbb5a895bf093dc7f4" + "reference": "c714958428a85c86ab97e3a0c96db4c4f381b7f5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/process/zipball/4b6a9a4013baa65d409153cbb5a895bf093dc7f4", - "reference": "4b6a9a4013baa65d409153cbb5a895bf093dc7f4", + "url": "https://api.github.com/repos/symfony/process/zipball/c714958428a85c86ab97e3a0c96db4c4f381b7f5", + "reference": "c714958428a85c86ab97e3a0c96db4c4f381b7f5", "shasum": "" }, "require": { @@ -1246,7 +1287,7 @@ ], "description": "Symfony Process Component", "homepage": "https://symfony.com", - "time": "2020-04-15T15:56:18+00:00" + "time": "2020-05-30T20:06:45+00:00" }, { "name": "symfony/translation", @@ -1442,10 +1483,10 @@ }, { "name": "ytdl-org/youtube-dl", - "version": "2020.05.08", + "version": "2020.06.16.1", "dist": { "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": "library" }, diff --git a/controllers/BaseController.php b/controllers/BaseController.php index bf48a24..05d3eb2 100644 --- a/controllers/BaseController.php +++ b/controllers/BaseController.php @@ -7,12 +7,14 @@ namespace Alltube\Controller; use Alltube\Config; +use Alltube\Library\Downloader; +use Alltube\Library\Video; use Alltube\LocaleManager; use Alltube\SessionManager; -use Alltube\Video; use Aura\Session\Segment; use Psr\Container\ContainerInterface; use Slim\Http\Request; +use Slim\Http\Response; /** * Abstract class used by every controller. @@ -61,6 +63,13 @@ abstract class BaseController */ protected $localeManager; + /** + * Downloader instance. + * + * @var Downloader + */ + protected $downloader; + /** * BaseController constructor. * @@ -73,6 +82,7 @@ abstract class BaseController $session = SessionManager::getSession(); $this->sessionSegment = $session->getSegment(self::class); $this->localeManager = $this->container->get('locale'); + $this->downloader = $this->config->getDownloader(); if (!$this->config->stream) { // Force HTTP if stream is not enabled. @@ -117,4 +127,20 @@ abstract class BaseController 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); + } } diff --git a/controllers/DownloadController.php b/controllers/DownloadController.php index 30f1e27..dd3e46f 100644 --- a/controllers/DownloadController.php +++ b/controllers/DownloadController.php @@ -6,13 +6,19 @@ namespace Alltube\Controller; -use Alltube\Exception\EmptyUrlException; -use Alltube\Exception\PasswordException; +use Alltube\Config; +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\PlaylistArchiveStream; use Alltube\Stream\YoutubeStream; -use Alltube\Video; -use Exception; use Slim\Http\Request; use Slim\Http\Response; use Slim\Http\Stream; @@ -25,17 +31,18 @@ class DownloadController extends BaseController /** * Redirect to video file. * - * @param Request $request PSR-7 request + * @param Request $request PSR-7 request * @param Response $response PSR-7 response * * @return Response HTTP response + * @throws AlltubeLibraryException */ public function download(Request $request, Response $response) { $url = $request->getQueryParam('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 { if ($this->config->convert && $request->getQueryParam('audio')) { @@ -49,14 +56,33 @@ class DownloadController extends BaseController // Regular download. return $this->getDownloadResponse($request, $response); } catch (PasswordException $e) { - return $response->withRedirect( - $this->container->get('router')->pathFor('info') . - '?' . http_build_query($request->getQueryParams()) - ); - } catch (Exception $e) { - $response->getBody()->write($e->getMessage()); + $frontController = new FrontController($this->container); - 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 { return $response->withRedirect($this->container->get('router')->pathFor('index')); @@ -70,8 +96,7 @@ class DownloadController extends BaseController * @param Response $response PSR-7 response * * @return Response HTTP response - * @throws PasswordException - * @throws Exception + * @throws AlltubeLibraryException */ private function getConvertedAudioResponse(Request $request, Response $response) { @@ -86,13 +111,7 @@ class DownloadController extends BaseController $response = $response->withHeader('Content-Type', 'audio/mpeg'); if ($request->isGet() || $request->isPost()) { - try { - $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); - } + $process = $this->downloader->getAudioStream($this->video, $this->config->audioBitrate, $from, $to); $response = $response->withBody(new Stream($process)); } @@ -106,36 +125,38 @@ class DownloadController extends BaseController * @param Response $response PSR-7 response * * @return Response HTTP response + * @throws AlltubeLibraryException + * @throws EmptyUrlException * @throws PasswordException + * @throws WrongPasswordException */ private function getAudioResponse(Request $request, Response $response) { - try { - // First, we try to get a MP3 file directly. - if (!empty($request->getQueryParam('from')) || !empty($request->getQueryParam('to'))) { - 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'); + if (!empty($request->getQueryParam('from')) || !empty($request->getQueryParam('to'))) { + // Force convert when we need to seek. + $this->video = $this->video->withFormat('bestaudio/' . $this->defaultFormat); 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 * @return Response HTTP response - * @throws EmptyUrlException - * @throws PasswordException - * @throws Exception + * @throws AlltubeLibraryException */ private function getStream(Request $request, Response $response) { if (isset($this->video->entries)) { if ($this->config->convert && $request->getQueryParam('audio')) { - $stream = new ConvertedPlaylistArchiveStream($this->video); + $stream = new ConvertedPlaylistArchiveStream($this->downloader, $this->video); } else { - $stream = new PlaylistArchiveStream($this->video); + $stream = new PlaylistArchiveStream($this->downloader, $this->video); } $response = $response->withHeader('Content-Type', 'application/zip'); $response = $response->withHeader( @@ -167,10 +186,10 @@ class DownloadController extends BaseController return $response->withBody($stream); } elseif ($this->video->protocol == 'rtmp') { $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') { $response = $response->withHeader('Content-Type', 'video/' . $this->video->ext); - $body = new Stream($this->video->getM3uStream()); + $body = new Stream($this->downloader->getM3uStream($this->video)); } else { $headers = []; $range = $request->getHeader('Range'); @@ -178,7 +197,7 @@ class DownloadController extends BaseController if (!empty($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-Length', $stream->getHeader('Content-Length')); @@ -190,7 +209,7 @@ class DownloadController extends BaseController if (isset($this->video->downloader_options->http_chunk_size)) { // Workaround for Youtube throttling the download speed. - $body = new YoutubeStream($this->video); + $body = new YoutubeStream($this->downloader, $this->video); } else { $body = $stream->getBody(); } @@ -201,7 +220,7 @@ class DownloadController extends BaseController $response = $response->withHeader( 'Content-Disposition', 'attachment; filename="' . - $this->video->getFilename() . '"' + $this->video->getFilename() . '"' ); return $response; @@ -210,19 +229,18 @@ class DownloadController extends BaseController /** * Get a remuxed stream piped through the server. * - * @param Response $response PSR-7 response * @param Request $request PSR-7 request * + * @param Response $response PSR-7 response * @return Response HTTP response - * @throws PasswordException - * @throws Exception + * @throws AlltubeLibraryException */ private function getRemuxStream(Request $request, Response $response) { 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'); if ($request->isGet()) { $response = $response->withBody(new Stream($stream)); @@ -242,9 +260,7 @@ class DownloadController extends BaseController * * @param Response $response PSR-7 response * @return Response HTTP response - * @throws EmptyUrlException - * @throws PasswordException - * @throws Exception + * @throws AlltubeLibraryException */ private function getDownloadResponse(Request $request, Response $response) { @@ -263,7 +279,7 @@ class DownloadController extends BaseController return $this->getStream($request, $response); } else { 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]); @@ -277,8 +293,13 @@ class DownloadController extends BaseController * @param Response $response PSR-7 response * * @return Response HTTP response + * @throws AlltubeLibraryException + * @throws InvalidProtocolConversionException * @throws PasswordException - * @throws Exception + * @throws PlaylistConversionException + * @throws WrongPasswordException + * @throws YoutubedlException + * @throws PopenStreamException */ private function getConvertedResponse(Request $request, Response $response) { @@ -290,7 +311,8 @@ class DownloadController extends BaseController $response = $response->withHeader('Content-Type', 'video/' . $request->getQueryParam('customFormat')); if ($request->isGet() || $request->isPost()) { - $process = $this->video->getConvertedStream( + $process = $this->downloader->getConvertedStream( + $this->video, $request->getQueryParam('customBitrate'), $request->getQueryParam('customFormat') ); diff --git a/controllers/FrontController.php b/controllers/FrontController.php index b0c4a65..2b6109a 100644 --- a/controllers/FrontController.php +++ b/controllers/FrontController.php @@ -6,12 +6,13 @@ 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\Video; +use Exception; use Symfony\Component\ErrorHandler\ErrorRenderer\HtmlErrorRenderer; use Throwable; -use Exception; use Psr\Container\ContainerInterface; use Slim\Http\Request; use Slim\Http\Response; @@ -94,7 +95,7 @@ class FrontController extends BaseController * @param Response $response PSR-7 response * * @return Response HTTP response - * @throws PasswordException + * @throws AlltubeLibraryException */ public function extractors(Request $request, Response $response) { @@ -103,7 +104,7 @@ class FrontController extends BaseController 'extractors.tpl', [ 'config' => $this->config, - 'extractors' => Video::getExtractors(), + 'extractors' => $this->downloader->getExtractors(), 'class' => 'extractors', 'title' => $this->localeManager->t('Supported websites'), 'description' => $this->localeManager->t('List of all supported websites from which Alltube Download ' . @@ -141,7 +142,7 @@ class FrontController extends BaseController ] ); - return $response; + return $response->withStatus(403); } /** @@ -151,6 +152,7 @@ class FrontController extends BaseController * @param Response $response PSR-7 response * * @return Response HTTP response + * @throws AlltubeLibraryException */ private function getInfoResponse(Request $request, Response $response) { @@ -158,6 +160,8 @@ class FrontController extends BaseController $this->video->getJson(); } catch (PasswordException $e) { return $this->password($request, $response); + } catch (WrongPasswordException $e) { + return $this->displayError($request, $response, $this->localeManager->t('Wrong password')); } if (isset($this->video->entries)) { @@ -205,13 +209,14 @@ class FrontController extends BaseController * @param Response $response PSR-7 response * * @return Response HTTP response + * @throws AlltubeLibraryException */ public function info(Request $request, Response $response) { $url = $request->getQueryParam('url') ?: $request->getQueryParam('v'); 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')) { // We skip the info page and get directly to the download. @@ -227,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. * @@ -241,7 +273,11 @@ class FrontController extends BaseController if ($this->config->debug) { $renderer = new HtmlErrorRenderer(true); $exception = $renderer->render($error); + $response->getBody()->write($exception->getAsString()); + foreach ($exception->getHeaders() as $header => $value) { + $response = $response->withHeader($header, $value); + } return $response->withStatus($exception->getStatusCode()); } else { @@ -251,20 +287,7 @@ class FrontController extends BaseController $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); + return $this->displayError($request, $response, $message); } } diff --git a/controllers/JsonController.php b/controllers/JsonController.php index bfc9d75..9e37cc2 100644 --- a/controllers/JsonController.php +++ b/controllers/JsonController.php @@ -6,8 +6,7 @@ namespace Alltube\Controller; -use Alltube\Video; -use Exception; +use Alltube\Library\Exception\AlltubeLibraryException; use Slim\Http\Request; use Slim\Http\Response; @@ -19,24 +18,24 @@ class JsonController extends BaseController /** * 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 * * @return Response HTTP response + * @throws AlltubeLibraryException */ public function json(Request $request, Response $response) { $url = $request->getQueryParam('url'); if (isset($url)) { - try { - $this->video = new Video($url, $this->getFormat($request), $this->getPassword($request)); + $this->video = $this->downloader->getVideo( + $url, + $this->getFormat($request), + $this->getPassword($request) + ); - return $response->withJson($this->video->getJson()); - } catch (Exception $e) { - return $response->withJson(['error' => $e->getMessage()]) - ->withStatus(500); - } + return $response->withJson($this->video->getJson()); } else { return $response->withJson(['error' => 'You need to provide the url parameter']) ->withStatus(400); diff --git a/i18n/template.pot b/i18n/template.pot index a7d5402..ce9d383 100644 --- a/i18n/template.pot +++ b/i18n/template.pot @@ -1,27 +1,6 @@ msgid "" 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 msgid "Code by @dev" msgstr "" @@ -46,6 +25,87 @@ msgstr "" 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 "" + +#: 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 msgid "This video is protected" msgstr "" @@ -70,144 +130,51 @@ msgstr "" msgid "From" msgstr "" -#: templates/index.tpl:29 +#: templates/index.tpl:31 msgid "to" msgstr "" -#: templates/index.tpl:36 +#: templates/index.tpl:39 msgid "See all supported websites" msgstr "" -#: templates/index.tpl:38 +#: templates/index.tpl:41 msgid "Drag this to your bookmarks bar:" msgstr "" -#: templates/index.tpl:39 +#: templates/index.tpl:43 msgid "Bookmarklet" msgstr "" -#: templates/info.tpl:13 -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 +#: classes/Config.php:156 msgid "Best" msgstr "" -#: classes/Config.php:159 +#: classes/Config.php:157 msgid "Remux best video with best audio" msgstr "" -#: classes/Config.php:160 +#: classes/Config.php:158 msgid "Worst" msgstr "" -#: classes/Video.php:159 +#: controllers/DownloadController.php:63 controllers/FrontController.php:164 msgid "Wrong password" msgstr "" -#: classes/Video.php:250 -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 +#: controllers/DownloadController.php:68 msgid "Conversion of playlists is not supported." msgstr "" -#: classes/Video.php:435 classes/Video.php:578 +#: controllers/DownloadController.php:75 msgid "Conversion of M3U8 files is not supported." msgstr "" -#: classes/Video.php:437 +#: controllers/DownloadController.php:81 msgid "Conversion of DASH segments is not supported." msgstr "" -#: 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 "" - -#: 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 +#: controllers/FrontController.php:63 msgid "" "Easily download videos from Youtube, Dailymotion, Vimeo and other websites." msgstr "" @@ -227,18 +194,18 @@ msgid "" "You need a password in order to download this video with Alltube Download" msgstr "" -#: controllers/FrontController.php:169 +#: controllers/FrontController.php:172 msgid "Video download" msgstr "" -#: controllers/FrontController.php:171 +#: controllers/FrontController.php:174 msgid "Download video from @extractor" msgstr "" -#: controllers/FrontController.php:177 +#: controllers/FrontController.php:180 msgid "Download @title from @extractor" msgstr "" -#: controllers/FrontController.php:253 controllers/FrontController.php:284 +#: controllers/FrontController.php:253 msgid "Error" msgstr "" diff --git a/templates/error.tpl b/templates/error.tpl index 49663ec..98605b8 100644 --- a/templates/error.tpl +++ b/templates/error.tpl @@ -4,6 +4,6 @@ {include file="inc/logo.tpl"}

{t}An error occurred{/t}

{t}Please check the URL of your video.{/t} -

{$error|escape}

+

{$error|escape|nl2br}

{include file='inc/footer.tpl'} diff --git a/tests/BaseTest.php b/tests/BaseTest.php index d717b79..aac832b 100644 --- a/tests/BaseTest.php +++ b/tests/BaseTest.php @@ -7,7 +7,7 @@ namespace Alltube\Test; use Alltube\Config; -use Exception; +use Alltube\Exception\ConfigException; use PHPUnit\Framework\TestCase; /** @@ -33,7 +33,7 @@ abstract class BaseTest extends TestCase /** * Prepare tests. - * @throws Exception + * @throws ConfigException */ protected function setUp(): void { diff --git a/tests/ConfigTest.php b/tests/ConfigTest.php index 09374cf..cbaf21d 100644 --- a/tests/ConfigTest.php +++ b/tests/ConfigTest.php @@ -7,7 +7,7 @@ namespace Alltube\Test; use Alltube\Config; -use Exception; +use Alltube\Exception\ConfigException; /** * Unit tests for the Config class. @@ -23,7 +23,7 @@ class ConfigTest extends BaseTest /** * Prepare tests. - * @throws Exception + * @throws ConfigException */ protected function setUp(): void { @@ -82,7 +82,7 @@ class ConfigTest extends BaseTest * Test the setFile function. * * @return void - * @throws Exception + * @throws ConfigException */ public function testSetFile() { @@ -97,7 +97,7 @@ class ConfigTest extends BaseTest */ public function testSetFileWithMissingFile() { - $this->expectException(Exception::class); + $this->expectException(ConfigException::class); Config::setFile('foo'); } @@ -105,7 +105,7 @@ class ConfigTest extends BaseTest * Test the setOptions function. * * @return void - * @throws Exception + * @throws ConfigException */ public function testSetOptions() { @@ -118,7 +118,7 @@ class ConfigTest extends BaseTest * Test the setOptions function. * * @return void - * @throws Exception + * @throws ConfigException */ public function testSetOptionsWithoutUpdate() { @@ -134,7 +134,7 @@ class ConfigTest extends BaseTest */ public function testSetOptionsWithBadYoutubedl() { - $this->expectException(Exception::class); + $this->expectException(ConfigException::class); Config::setOptions(['youtubedl' => 'foo']); } @@ -145,7 +145,7 @@ class ConfigTest extends BaseTest */ public function testSetOptionsWithBadPython() { - $this->expectException(Exception::class); + $this->expectException(ConfigException::class); Config::setOptions(['python' => 'foo']); } @@ -153,7 +153,7 @@ class ConfigTest extends BaseTest * Test the getInstance function with the CONVERT and PYTHON environment variables. * * @return void - * @throws Exception + * @throws ConfigException */ public function testGetInstanceWithEnv() { diff --git a/tests/ControllerTest.php b/tests/ControllerTest.php index bd9f737..abb3756 100644 --- a/tests/ControllerTest.php +++ b/tests/ControllerTest.php @@ -9,13 +9,14 @@ namespace Alltube\Test; use Alltube\Controller\BaseController; use Alltube\Controller\DownloadController; use Alltube\Controller\FrontController; +use Alltube\Exception\ConfigException; use Alltube\LocaleManager; use Alltube\ViewFactory; -use Exception; use Slim\Container; use Slim\Http\Environment; use Slim\Http\Request; use Slim\Http\Response; +use SmartyException; /** * Abstract class used by the controller tests. @@ -51,7 +52,7 @@ abstract class ControllerTest extends BaseTest /** * Prepare tests. - * @throws Exception + * @throws ConfigException|SmartyException */ protected function setUp(): void { diff --git a/tests/ConvertedPlaylistArchiveStreamTest.php b/tests/ConvertedPlaylistArchiveStreamTest.php index e8cb002..0ed373f 100644 --- a/tests/ConvertedPlaylistArchiveStreamTest.php +++ b/tests/ConvertedPlaylistArchiveStreamTest.php @@ -6,9 +6,9 @@ namespace Alltube\Test; +use Alltube\Config; +use Alltube\Exception\ConfigException; use Alltube\Stream\ConvertedPlaylistArchiveStream; -use Alltube\Video; -use Exception; /** * Unit tests for the ConvertedPlaylistArchiveStream class. @@ -18,14 +18,16 @@ class ConvertedPlaylistArchiveStreamTest extends StreamTest { /** * Prepare tests. - * @throws Exception + * @throws ConfigException */ protected function setUp(): void { 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); } } diff --git a/tests/DownloadControllerTest.php b/tests/DownloadControllerTest.php index 761ba21..019122b 100644 --- a/tests/DownloadControllerTest.php +++ b/tests/DownloadControllerTest.php @@ -8,7 +8,11 @@ namespace Alltube\Test; use Alltube\Config; 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. @@ -18,7 +22,7 @@ class DownloadControllerTest extends ControllerTest { /** * Prepare tests. - * @throws Exception + * @throws ConfigException|SmartyException */ protected function setUp(): void { @@ -64,7 +68,7 @@ class DownloadControllerTest extends ControllerTest * Test the download() function with streams enabled. * * @return void - * @throws Exception + * @throws ConfigException */ public function testDownloadWithStream() { @@ -80,7 +84,7 @@ class DownloadControllerTest extends ControllerTest * Test the download() function with an M3U stream. * * @return void - * @throws Exception + * @throws ConfigException */ public function testDownloadWithM3uStream() { @@ -100,7 +104,7 @@ class DownloadControllerTest extends ControllerTest * Test the download() function with an RTMP stream. * * @return void - * @throws Exception + * @throws ConfigException */ public function testDownloadWithRtmpStream() { @@ -118,7 +122,7 @@ class DownloadControllerTest extends ControllerTest * Test the download() function with a remuxed video. * * @return void - * @throws Exception + * @throws ConfigException */ public function testDownloadWithRemux() { @@ -140,7 +144,8 @@ class DownloadControllerTest extends ControllerTest */ public function testDownloadWithRemuxDisabled() { - $this->assertRequestIsServerError( + $this->expectException(RemuxException::class); + $this->getRequestResult( 'download', [ 'url' => 'https://www.youtube.com/watch?v=M7IpKCZ47pU', @@ -166,7 +171,8 @@ class DownloadControllerTest extends ControllerTest */ 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() { - $this->assertRequestIsServerError( + $this->expectException(EmptyUrlException::class); + $this->getRequestResult( 'download', ['url' => 'https://www.youtube.com/playlist?list=PLgdySZU6KUXL_8Jq5aUkyNV7wCa-4wZsC'] ); @@ -188,7 +195,7 @@ class DownloadControllerTest extends ControllerTest * * @return void * @requires OS Linux - * @throws Exception + * @throws ConfigException */ public function testDownloadWithPlaylist() { @@ -204,7 +211,7 @@ class DownloadControllerTest extends ControllerTest * Test the download() function with an advanced conversion. * * @return void - * @throws Exception + * @throws ConfigException */ public function testDownloadWithAdvancedConversion() { diff --git a/tests/FrontControllerTest.php b/tests/FrontControllerTest.php index 92e4824..0e2ffe0 100644 --- a/tests/FrontControllerTest.php +++ b/tests/FrontControllerTest.php @@ -8,9 +8,12 @@ namespace Alltube\Test; use Alltube\Config; use Alltube\Controller\FrontController; +use Alltube\Exception\ConfigException; +use Alltube\Library\Exception\AlltubeLibraryException; use Exception; use Slim\Http\Environment; use Slim\Http\Request; +use SmartyException; /** * Unit tests for the FrontController class. @@ -25,7 +28,7 @@ class FrontControllerTest extends ControllerTest /** * Prepare tests. - * @throws Exception + * @throws ConfigException|SmartyException */ protected function setUp(): void { @@ -48,7 +51,7 @@ class FrontControllerTest extends ControllerTest * Test the constructor with streams enabled. * * @return void - * @throws Exception + * @throws ConfigException */ public function testConstructorWithStream() { @@ -99,7 +102,7 @@ class FrontControllerTest extends ControllerTest */ public function testPassword() { - $this->assertRequestIsOk('password'); + $this->assertRequestIsClientError('password'); } /** @@ -128,7 +131,7 @@ class FrontControllerTest extends ControllerTest * * @return void * @requires download - * @throws Exception + * @throws ConfigException */ public function testInfoWithAudio() { @@ -145,7 +148,7 @@ class FrontControllerTest extends ControllerTest * * @return void * @requires download - * @throws Exception + * @throws ConfigException */ public function testInfoWithVimeoAudio() { @@ -160,7 +163,7 @@ class FrontControllerTest extends ControllerTest * * @return void * @requires download - * @throws Exception + * @throws ConfigException */ public function testInfoWithUnconvertedAudio() { @@ -180,6 +183,7 @@ class FrontControllerTest extends ControllerTest * * @return void * @requires download + * @throws AlltubeLibraryException */ public function testInfoWithPassword() { @@ -199,8 +203,8 @@ class FrontControllerTest extends ControllerTest */ public function testInfoWithMissingPassword() { - $this->assertRequestIsOk('info', ['url' => 'http://vimeo.com/68375962']); - $this->assertRequestIsOk('info', ['url' => 'http://vimeo.com/68375962', 'audio' => true]); + $this->assertRequestIsClientError('info', ['url' => 'http://vimeo.com/68375962']); + $this->assertRequestIsClientError('info', ['url' => 'http://vimeo.com/68375962', 'audio' => true]); } /** @@ -208,7 +212,7 @@ class FrontControllerTest extends ControllerTest * * @return void * @requires download - * @throws Exception + * @throws ConfigException */ public function testInfoWithStream() { diff --git a/tests/JsonControllerTest.php b/tests/JsonControllerTest.php index d2d6c3e..438b482 100644 --- a/tests/JsonControllerTest.php +++ b/tests/JsonControllerTest.php @@ -7,7 +7,9 @@ namespace Alltube\Test; use Alltube\Controller\JsonController; -use Exception; +use Alltube\Exception\ConfigException; +use Alltube\Library\Exception\YoutubedlException; +use SmartyException; /** * Unit tests for the FrontController class. @@ -16,7 +18,7 @@ class JsonControllerTest extends ControllerTest { /** * Prepare tests. - * @throws Exception + * @throws ConfigException|SmartyException */ protected function setUp(): void { @@ -44,7 +46,8 @@ class JsonControllerTest extends ControllerTest */ public function testJsonWithError() { - $this->assertRequestIsServerError('json', ['url' => 'http://example.com/foo']); + $this->expectException(YoutubedlException::class); + $this->getRequestResult('json', ['url' => 'http://example.com/foo']); } /** diff --git a/tests/PlaylistArchiveStreamTest.php b/tests/PlaylistArchiveStreamTest.php index f02a6ea..29b103f 100644 --- a/tests/PlaylistArchiveStreamTest.php +++ b/tests/PlaylistArchiveStreamTest.php @@ -6,9 +6,9 @@ namespace Alltube\Test; +use Alltube\Config; +use Alltube\Exception\ConfigException; use Alltube\Stream\PlaylistArchiveStream; -use Alltube\Video; -use Exception; /** * Unit tests for the PlaylistArchiveStream class. @@ -18,14 +18,16 @@ class PlaylistArchiveStreamTest extends StreamTest { /** * Prepare tests. - * @throws Exception + * @throws ConfigException */ protected function setUp(): void { 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); } } diff --git a/tests/VideoStubsTest.php b/tests/VideoStubsTest.php index 51f758d..789e839 100644 --- a/tests/VideoStubsTest.php +++ b/tests/VideoStubsTest.php @@ -6,36 +6,51 @@ 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 phpmock\mockery\PHPMockery; -use Exception; /** * Unit tests for the Video class. * They are in a separate file so they can safely replace PHP functions with stubs. + * + * @requires download */ class VideoStubsTest extends BaseTest { /** - * Video URL used in many tests. + * Video used in many tests. * * @var Video */ private $video; + /** + * Downloader instance used in tests. + * + * @var Downloader + */ + private $downloader; + /** * Initialize properties used by test. - * @throws Exception + * @throws ConfigException */ protected function setUp(): void { parent::setUp(); - PHPMockery::mock('Alltube', 'popen'); - PHPMockery::mock('Alltube', 'fopen'); + PHPMockery::mock('Alltube\Library', 'popen'); + 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. * * @return void + * @throws AlltubeLibraryException */ public function testGetAudioStreamWithPopenError() { - $this->expectException(Exception::class); - $this->video->getAudioStream(); + $this->expectException(PopenStreamException::class); + $this->downloader->getAudioStream($this->video); } /** * Test getM3uStream function with a buggy popen. * * @return void + * @throws AlltubeLibraryException */ public function testGetM3uStreamWithPopenError() { - $this->expectException(Exception::class); - $this->video->getM3uStream(); + $this->expectException(PopenStreamException::class); + $this->downloader->getM3uStream($this->video); } /** * Test getRtmpStream function with a buggy popen. * * @return void + * @throws AlltubeLibraryException */ public function testGetRtmpStreamWithPopenError() { - $this->expectException(Exception::class); - $this->video->getRtmpStream(); + $this->expectException(PopenStreamException::class); + $this->downloader->getRtmpStream($this->video); } /** * Test getRemuxStream function with a buggy popen. * * @return void + * @throws AlltubeLibraryException */ public function testGetRemuxStreamWithPopenError() { - $this->expectException(Exception::class); + $this->expectException(PopenStreamException::class); $video = $this->video->withFormat('bestvideo+bestaudio'); - $video->getRemuxStream(); + $this->downloader->getRemuxStream($video); } /** * Test getConvertedStream function with a buggy popen. * * @return void + * @throws AlltubeLibraryException */ public function testGetConvertedStreamWithPopenError() { - $this->expectException(Exception::class); - $this->video->getConvertedStream(32, 'flv'); + $this->expectException(PopenStreamException::class); + $this->downloader->getConvertedStream($this->video, 32, 'flv'); } } diff --git a/tests/VideoTest.php b/tests/VideoTest.php index e6d4552..1b85038 100644 --- a/tests/VideoTest.php +++ b/tests/VideoTest.php @@ -7,26 +7,61 @@ namespace Alltube\Test; use Alltube\Config; -use Alltube\Exception\EmptyUrlException; -use Alltube\Exception\PasswordException; -use Alltube\Video; -use Exception; +use Alltube\Exception\ConfigException; +use Alltube\Library\Downloader; +use Alltube\Library\Exception\AlltubeLibraryException; +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. * @requires download + * @todo Split Downloader and Video tests. */ 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. * * @return void - * @throws PasswordException + * @throws AlltubeLibraryException */ 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 * * @return void - * @throws PasswordException - * @throws EmptyUrlException + * @throws AlltubeLibraryException * @dataProvider urlProvider * @dataProvider m3uUrlProvider * @dataProvider remuxUrlProvider @@ -52,7 +86,7 @@ class VideoTest extends BaseTest /* @scrutinizer ignore-unused */ $extension, $domain ) { - $video = new Video($url, $format); + $video = new Video($this->downloader, $url, $format); foreach ($video->getUrl() as $videoURL) { $this->assertStringContainsString($domain, $videoURL); } @@ -62,12 +96,11 @@ class VideoTest extends BaseTest * Test getUrl function with a protected video. * * @return void - * @throws EmptyUrlException - * @throws PasswordException + * @throws AlltubeLibraryException */ 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) { $this->assertStringContainsString('vimeocdn.com', $videoURL); } @@ -77,13 +110,12 @@ class VideoTest extends BaseTest * Test getUrl function with a protected video and no password. * * @return void - * @throws EmptyUrlException - * @throws PasswordException + * @throws AlltubeLibraryException */ public function testgetUrlWithMissingPassword() { - $this->expectException(Exception::class); - $video = new Video('http://vimeo.com/68375962'); + $this->expectException(PasswordException::class); + $video = new Video($this->downloader, 'http://vimeo.com/68375962', $this->format); $video->getUrl(); } @@ -91,13 +123,12 @@ class VideoTest extends BaseTest * Test getUrl function with a protected video and a wrong password. * * @return void - * @throws EmptyUrlException - * @throws PasswordException + * @throws AlltubeLibraryException */ public function testgetUrlWithWrongPassword() { - $this->expectException(Exception::class); - $video = new Video('http://vimeo.com/68375962', 'best', 'foo'); + $this->expectException(WrongPasswordException::class); + $video = new Video($this->downloader, 'http://vimeo.com/68375962', 'best', 'foo'); $video->getUrl(); } @@ -107,14 +138,13 @@ class VideoTest extends BaseTest * @param string $url URL * * @return void - * @throws EmptyUrlException - * @throws PasswordException - * @dataProvider ErrorUrlProvider + * @throws AlltubeLibraryException + * @dataProvider ErrorUrlProvider */ public function testgetUrlError($url) { - $this->expectException(Exception::class); - $video = new Video($url); + $this->expectException(YoutubedlException::class); + $video = new Video($this->downloader, $url, $this->format); $video->getUrl(); } @@ -224,13 +254,13 @@ class VideoTest extends BaseTest * @param string $format Format * * @return void + * @throws AlltubeLibraryException * @dataProvider urlProvider * @dataProvider m3uUrlProvider - * @throws PasswordException */ public function testGetJson($url, $format) { - $video = new Video($url, $format); + $video = new Video($this->downloader, $url, $format); $info = $video->getJson(); $this->assertObjectHasAttribute('webpage_url', $info); $this->assertObjectHasAttribute('url', $info); @@ -246,13 +276,13 @@ class VideoTest extends BaseTest * @param string $url URL * * @return void - * @dataProvider ErrorURLProvider - * @throws PasswordException + * @throws AlltubeLibraryException + * @dataProvider ErrorURLProvider */ public function testGetJsonError($url) { - $this->expectException(Exception::class); - $video = new Video($url); + $this->expectException(YoutubedlException::class); + $video = new Video($this->downloader, $url, $this->format); $video->getJson(); } @@ -265,14 +295,14 @@ class VideoTest extends BaseTest * @param string $extension File extension * * @return void + * @throws AlltubeLibraryException * @dataProvider urlProvider * @dataProvider m3uUrlProvider * @dataProvider remuxUrlProvider - * @throws PasswordException */ 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); } @@ -282,13 +312,13 @@ class VideoTest extends BaseTest * @param string $url URL * * @return void - * @dataProvider ErrorUrlProvider - * @throws PasswordException + * @throws AlltubeLibraryException + * @dataProvider ErrorUrlProvider */ public function testGetFilenameError($url) { - $this->expectException(Exception::class); - $video = new Video($url); + $this->expectException(YoutubedlException::class); + $video = new Video($this->downloader, $url, $this->format); $video->getFilename(); } @@ -300,73 +330,80 @@ class VideoTest extends BaseTest * * @return void * @dataProvider urlProvider - * @throws Exception + * @throws AlltubeLibraryException */ public function testGetAudioStream($url, $format) { - $video = new Video($url, $format); - $this->assertStream($video->getAudioStream()); + $video = new Video($this->downloader, $url, $format); + $this->assertStream($this->downloader->getAudioStream($video)); } /** * Test getAudioStream function without avconv. * - * @param string $url URL + * @param string $url URL * @param string $format Format * * @return void - * @dataProvider urlProvider + * @throws AlltubeLibraryException|ConfigException + * @dataProvider urlProvider */ public function testGetAudioStreamAvconvError($url, $format) { - $this->expectException(Exception::class); + $this->expectException(AvconvException::class); Config::setOptions(['avconv' => 'foobar']); + $config = Config::getInstance(); + $downloader = $config->getDownloader(); - $video = new Video($url, $format); - $video->getAudioStream(); + $video = new Video($this->downloader, $url, $format, $this->format); + $downloader->getAudioStream($video); } /** * Test getAudioStream function with a M3U8 file. * - * @param string $url URL + * @param string $url URL * @param string $format Format * * @return void + * @throws AlltubeLibraryException * @dataProvider m3uUrlProvider */ public function testGetAudioStreamM3uError($url, $format) { - $this->expectException(Exception::class); - $video = new Video($url, $format); - $video->getAudioStream(); + $this->expectException(InvalidProtocolConversionException::class); + $video = new Video($this->downloader, $url, $format); + $this->downloader->getAudioStream($video); } /** * Test getAudioStream function with a DASH URL. * * @return void + * @throws AlltubeLibraryException */ public function testGetAudioStreamDashError() { - $this->expectException(Exception::class); - $video = new Video('https://vimeo.com/251997032', 'bestaudio/best'); - $video->getAudioStream(); + $this->expectException(InvalidProtocolConversionException::class); + $video = new Video($this->downloader, 'https://vimeo.com/251997032', 'bestaudio/best'); + $this->downloader->getAudioStream($video); } /** * Test getAudioStream function with a playlist. * * @return void + * @throws AlltubeLibraryException */ public function testGetAudioStreamPlaylistError() { - $this->expectException(Exception::class); + $this->expectException(PlaylistConversionException::class); $video = new Video( + $this->downloader, 'https://www.youtube.com/playlist?list=PLgdySZU6KUXL_8Jq5aUkyNV7wCa-4wZsC', 'best' ); - $video->getAudioStream(); + $this->downloader->getAudioStream($video); } /** @@ -390,12 +427,12 @@ class VideoTest extends BaseTest * * @return void * @dataProvider m3uUrlProvider - * @throws Exception + * @throws AlltubeLibraryException */ public function testGetM3uStream($url, $format) { - $video = new Video($url, $format); - $this->assertStream($video->getM3uStream()); + $video = new Video($this->downloader, $url, $format); + $this->assertStream($this->downloader->getM3uStream($video)); } /** @@ -406,28 +443,29 @@ class VideoTest extends BaseTest * * @return void * @dataProvider remuxUrlProvider - * @throws Exception + * @throws AlltubeLibraryException */ public function testGetRemuxStream($url, $format) { - $video = new Video($url, $format); - $this->assertStream($video->getRemuxStream()); + $video = new Video($this->downloader, $url, $format); + $this->assertStream($this->downloader->getRemuxStream($video)); } /** * Test getRemuxStream function with a video with only one URL. * - * @param string $url URL + * @param string $url URL * @param string $format Format * * @return void + * @throws AlltubeLibraryException * @dataProvider urlProvider */ public function testGetRemuxStreamWithWrongVideo($url, $format) { - $this->expectException(Exception::class); - $video = new Video($url, $format); - $video->getRemuxStream(); + $this->expectException(RemuxException::class); + $video = new Video($this->downloader, $url, $format); + $this->downloader->getRemuxStream($video); } /** @@ -437,34 +475,37 @@ class VideoTest extends BaseTest * @param string $format Format * * @return void + * @throws AlltubeLibraryException * @dataProvider rtmpUrlProvider - * @throws Exception */ public function testGetRtmpStream($url, $format) { $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. * - * @param string $url URL + * @param string $url URL * @param string $format Format * * @return void + * @throws AlltubeLibraryException|ConfigException * @dataProvider m3uUrlProvider */ public function testGetM3uStreamAvconvError($url, $format) { - $this->expectException(Exception::class); + $this->expectException(AvconvException::class); Config::setOptions(['avconv' => 'foobar']); + $config = Config::getInstance(); + $downloader = $config->getDownloader(); - $video = new Video($url, $format); - $video->getM3uStream(); + $video = new Video($downloader, $url, $format); + $downloader->getM3uStream($video); } /** @@ -475,27 +516,28 @@ class VideoTest extends BaseTest * * @return void * @dataProvider urlProvider - * @throws Exception + * @throws AlltubeLibraryException */ public function testGetConvertedStream($url, $format) { - $video = new Video($url, $format); - $this->assertStream($video->getConvertedStream(32, 'flv')); + $video = new Video($this->downloader, $url, $format); + $this->assertStream($this->downloader->getConvertedStream($video, 32, 'flv')); } /** * Test getConvertedStream function with a M3U8 file. * - * @param string $url URL + * @param string $url URL * @param string $format Format * * @return void + * @throws AlltubeLibraryException * @dataProvider m3uUrlProvider */ public function testGetConvertedStreamM3uError($url, $format) { - $this->expectException(Exception::class); - $video = new Video($url, $format); - $video->getConvertedStream(32, 'flv'); + $this->expectException(InvalidProtocolConversionException::class); + $video = new Video($this->downloader, $url, $format); + $this->downloader->getConvertedStream($video, 32, 'flv'); } } diff --git a/tests/YoutubeChunkStreamTest.php b/tests/YoutubeChunkStreamTest.php index 41a2f38..aec785d 100644 --- a/tests/YoutubeChunkStreamTest.php +++ b/tests/YoutubeChunkStreamTest.php @@ -6,9 +6,10 @@ namespace Alltube\Test; +use Alltube\Config; +use Alltube\Exception\ConfigException; +use Alltube\Library\Exception\AlltubeLibraryException; use Alltube\Stream\YoutubeChunkStream; -use Alltube\Video; -use Exception; /** * Unit tests for the YoutubeChunkStream class. @@ -18,14 +19,17 @@ class YoutubeChunkStreamTest extends StreamTest { /** * Prepare tests. - * @throws Exception + * @throws ConfigException + * @throws AlltubeLibraryException */ protected function setUp(): void { 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)); } } diff --git a/tests/YoutubeStreamTest.php b/tests/YoutubeStreamTest.php index b8b4d13..d551e0c 100644 --- a/tests/YoutubeStreamTest.php +++ b/tests/YoutubeStreamTest.php @@ -6,9 +6,10 @@ namespace Alltube\Test; +use Alltube\Config; +use Alltube\Exception\ConfigException; +use Alltube\Library\Exception\AlltubeLibraryException; use Alltube\Stream\YoutubeStream; -use Alltube\Video; -use Exception; /** * Unit tests for the YoutubeStream class. @@ -18,15 +19,17 @@ class YoutubeStreamTest extends StreamTest { /** * Prepare tests. - * @throws Exception + * @throws ConfigException|AlltubeLibraryException */ protected function setUp(): void { 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); } /** From d4b3a82ebbf33f556e1b2bf51fee431145bcbccd Mon Sep 17 00:00:00 2001 From: Pierre Rudloff Date: Sun, 21 Jun 2020 15:04:01 +0200 Subject: [PATCH 19/34] Remove obsolete Composer config --- composer.json | 7 ------- composer.lock | 2 +- 2 files changed, 1 insertion(+), 8 deletions(-) diff --git a/composer.json b/composer.json index 83f059b..a5122bb 100644 --- a/composer.json +++ b/composer.json @@ -34,13 +34,6 @@ "symfony/error-handler": "^5.0", "symfony/var-dumper": "^5.0" }, - "extra": { - "paas": { - "nginx-includes": [ - "resources/nginx.conf" - ] - } - }, "repositories": [ { "type": "composer", diff --git a/composer.lock b/composer.lock index d164fd2..b612219 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "dba22d2bff872c8e1310567d4336db16", + "content-hash": "03b37b613f8ae3881395adf1cbc72b67", "packages": [ { "name": "anam/phantomjs-linux-x86-binary", From 251fbe48cac3bfd757699e5727af7a7de141da01 Mon Sep 17 00:00:00 2001 From: Pierre Rudloff Date: Sun, 21 Jun 2020 15:30:39 +0200 Subject: [PATCH 20/34] Add generator meta with the current version --- classes/Config.php | 12 +++++ composer.json | 1 + composer.lock | 108 ++++++++++++++++++++++++++++++++++++++++- templates/inc/head.tpl | 5 +- 4 files changed, 123 insertions(+), 3 deletions(-) diff --git a/classes/Config.php b/classes/Config.php index 337192a..d95e212 100644 --- a/classes/Config.php +++ b/classes/Config.php @@ -9,6 +9,8 @@ namespace Alltube; use Alltube\Exception\ConfigException; use Alltube\Library\Downloader; use Jawira\CaseConverter\CaseConverterException; +use Jean85\PrettyVersions; +use PackageVersions\Versions; use Symfony\Component\ErrorHandler\Debug; use Symfony\Component\Yaml\Yaml; use Jawira\CaseConverter\Convert; @@ -332,4 +334,14 @@ class Config $this->avconvVerbosity ); } + + /** + * @return string + */ + public function getAppVersion() + { + $version = PrettyVersions::getVersion(Versions::ROOT_PACKAGE_NAME); + + return $version->getPrettyVersion(); + } } diff --git a/composer.json b/composer.json index a5122bb..530604a 100644 --- a/composer.json +++ b/composer.json @@ -12,6 +12,7 @@ "barracudanetworks/archivestream-php": "^1.0", "ffmpeg/ffmpeg": "^4.1", "jawira/case-converter": "^3.4", + "jean85/pretty-package-versions": "^1.3", "mathmarques/smarty-view": "^1.1", "npm-asset/open-sans-fontface": "^1.4", "rinvex/countries": "^6.1", diff --git a/composer.lock b/composer.lock index b612219..90c8d5a 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "03b37b613f8ae3881395adf1cbc72b67", + "content-hash": "4468e4da3c9a9626c997b0da8be455ae", "packages": [ { "name": "anam/phantomjs-linux-x86-binary", @@ -150,6 +150,61 @@ ], "time": "2018-08-10T13:58:33+00:00" }, + { + "name": "composer/package-versions-deprecated", + "version": "1.8.1", + "source": { + "type": "git", + "url": "https://github.com/composer/package-versions-deprecated.git", + "reference": "b9805885293f3957ee0dd42616ac6915c4ac9a4b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/composer/package-versions-deprecated/zipball/b9805885293f3957ee0dd42616ac6915c4ac9a4b", + "reference": "b9805885293f3957ee0dd42616ac6915c4ac9a4b", + "shasum": "" + }, + "require": { + "composer-plugin-api": "^1.1.0 || ^2.0", + "php": "^7" + }, + "replace": { + "ocramius/package-versions": "1.8.99" + }, + "require-dev": { + "composer/composer": "^1.9.3 || ^2.0@dev", + "ext-zip": "^1.13", + "phpunit/phpunit": "^6.5 || ^7" + }, + "type": "composer-plugin", + "extra": { + "class": "PackageVersions\\Installer", + "branch-alias": { + "dev-master": "1.x-dev" + } + }, + "autoload": { + "psr-4": { + "PackageVersions\\": "src/PackageVersions" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Marco Pivetta", + "email": "ocramius@gmail.com" + }, + { + "name": "Jordi Boggiano", + "email": "j.boggiano@seld.be" + } + ], + "description": "Composer plugin that provides efficient querying for installed package versions (no runtime IO)", + "time": "2020-06-19T07:59:31+00:00" + }, { "name": "ffmpeg/ffmpeg", "version": "4.1.4", @@ -409,6 +464,57 @@ ], "time": "2019-12-15T14:31:43+00:00" }, + { + "name": "jean85/pretty-package-versions", + "version": "1.3.0", + "source": { + "type": "git", + "url": "https://github.com/Jean85/pretty-package-versions.git", + "reference": "e3517fb11b67e798239354fe8213927d012ad8f9" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Jean85/pretty-package-versions/zipball/e3517fb11b67e798239354fe8213927d012ad8f9", + "reference": "e3517fb11b67e798239354fe8213927d012ad8f9", + "shasum": "" + }, + "require": { + "composer/package-versions-deprecated": "^1.8.0", + "php": "^7.0" + }, + "require-dev": { + "phpunit/phpunit": "^6.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.x-dev" + } + }, + "autoload": { + "psr-4": { + "Jean85\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Alessandro Lai", + "email": "alessandro.lai85@gmail.com" + } + ], + "description": "A wrapper for ocramius/package-versions to get pretty versions strings", + "keywords": [ + "composer", + "package", + "release", + "versions" + ], + "time": "2020-04-24T14:19:45+00:00" + }, { "name": "mathmarques/smarty-view", "version": "1.1.2", diff --git a/templates/inc/head.tpl b/templates/inc/head.tpl index 00a98c8..7b2f3d4 100644 --- a/templates/inc/head.tpl +++ b/templates/inc/head.tpl @@ -2,7 +2,7 @@ - + {if isset($description)} @@ -19,7 +19,8 @@ - + + From 72e5e682743245f6491986e014393cd0372f2647 Mon Sep 17 00:00:00 2001 From: Pierre Rudloff Date: Mon, 22 Jun 2020 22:25:32 +0200 Subject: [PATCH 21/34] Remove obsolete routes --- index.php | 4 ---- 1 file changed, 4 deletions(-) diff --git a/index.php b/index.php index b2e9ec3..4760670 100644 --- a/index.php +++ b/index.php @@ -85,8 +85,6 @@ $app->any( '/info', [$frontController, 'info'] )->setName('info'); -// Legacy route. -$app->any('/video', [$frontController, 'info']); $app->any( '/watch', @@ -97,8 +95,6 @@ $app->any( '/download', [$downloadController, 'download'] )->setName('download'); -// Legacy route. -$app->get('/redirect', [$downloadController, 'download']); $app->get( '/locale/{locale}', From a518e3b7b35902dd184a78994c816b28cfb6442b Mon Sep 17 00:00:00 2001 From: Pierre Rudloff Date: Mon, 22 Jun 2020 23:15:31 +0200 Subject: [PATCH 22/34] Create release package cleanly from a temporary folder (#279) --- RoboFile.php | 61 ++++++++++++++++++--------------------------------- composer.json | 2 +- 2 files changed, 22 insertions(+), 41 deletions(-) diff --git a/RoboFile.php b/RoboFile.php index 6481aa6..53f97fd 100644 --- a/RoboFile.php +++ b/RoboFile.php @@ -1,7 +1,6 @@ stopOnFail(); + $result = $this->taskExec('git') - ->args('describe') + ->arg('describe') ->run(); $result->provideOutputdata(); - $tag = trim($result->getOutputData()); - // We don't want the whole vendor directory. - $finder = new Finder(); - $finder->files() - ->in(__DIR__ . '/vendor/') - ->exclude( - [ - 'ffmpeg/', - 'phpstan/', - 'bin/', - 'anam/phantomjs-linux-x86-binary/', - 'phpunit/', - 'squizlabs/', - 'rinvex/countries/resources/geodata/', - 'rinvex/countries/resources/flags/' - ] - ); + $tmpDir = $this->_tmpDir(); - $zipTask = $this->taskPack('alltube-' . $tag . '.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'); + $filename = 'alltube-' . trim($result->getOutputData()) . '.zip'; - foreach ($finder as $file) { - if ($path = $file->getRelativePathname()) { - $zipTask->add('vendor/' . $path); - } - } + $this->taskFilesystemStack() + ->remove($filename) + ->run(); - $zipTask->run(); + $this->taskGitStack() + ->cloneRepo(__DIR__, $tmpDir) + ->run(); + + $this->taskComposerInstall() + ->dir($tmpDir) + ->optimizeAutoloader() + ->noDev() + ->run(); + + $this->taskPack($filename) + ->addDir('alltube', $tmpDir) + ->run(); } } diff --git a/composer.json b/composer.json index 530604a..9510c22 100644 --- a/composer.json +++ b/composer.json @@ -92,7 +92,7 @@ "scripts": { "lint": "grumphp run --ansi", "test": "phpunit", - "release": "robo release", + "release": "robo release --ansi", "update-locales": [ "tsmarty2c.php templates > i18n/template.pot", "xgettext --omit-header -kt -j -o i18n/template.pot classes/*.php classes/*/*.php controllers/*" From f90a08e89c96cf6593a403296d9ec458c1e265e8 Mon Sep 17 00:00:00 2001 From: Pierre Rudloff Date: Mon, 22 Jun 2020 23:16:42 +0200 Subject: [PATCH 23/34] Stop installing ffmpeg and phantomjs with Composer It is convenient but this a the job of the OS package manager --- classes/Config.php | 4 +-- composer.json | 16 ----------- composer.lock | 56 +-------------------------------------- config/config.example.yml | 4 +-- 4 files changed, 5 insertions(+), 75 deletions(-) diff --git a/classes/Config.php b/classes/Config.php index d95e212..8b90f8a 100644 --- a/classes/Config.php +++ b/classes/Config.php @@ -74,14 +74,14 @@ class Config * * @var string */ - public $avconv = 'vendor/bin/ffmpeg'; + public $avconv = '/usr/bin/ffmpeg'; /** * Path to the directory that contains the phantomjs binary. * * @var string */ - public $phantomjsDir = 'vendor/bin/'; + public $phantomjsDir = '/usr/bin/'; /** * Disable URL rewriting. diff --git a/composer.json b/composer.json index 9510c22..df69396 100644 --- a/composer.json +++ b/composer.json @@ -7,10 +7,8 @@ "require": { "ext-intl": "*", "ext-json": "*", - "anam/phantomjs-linux-x86-binary": "^2.1", "aura/session": "^2.1", "barracudanetworks/archivestream-php": "^1.0", - "ffmpeg/ffmpeg": "^4.1", "jawira/case-converter": "^3.4", "jean85/pretty-package-versions": "^1.3", "mathmarques/smarty-view": "^1.1", @@ -50,20 +48,6 @@ "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": [ diff --git a/composer.lock b/composer.lock index 90c8d5a..44749d8 100644 --- a/composer.lock +++ b/composer.lock @@ -4,50 +4,8 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "4468e4da3c9a9626c997b0da8be455ae", + "content-hash": "3c17df3876a2c769f866f845e4491763", "packages": [ - { - "name": "anam/phantomjs-linux-x86-binary", - "version": "v2.1.1", - "source": { - "type": "git", - "url": "https://github.com/anam-hossain/phantomjs-linux-x86-binary.git", - "reference": "cb90cd0e7bd4ad34f52e6834783b1c5adae15014" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/anam-hossain/phantomjs-linux-x86-binary/zipball/cb90cd0e7bd4ad34f52e6834783b1c5adae15014", - "reference": "cb90cd0e7bd4ad34f52e6834783b1c5adae15014", - "shasum": "" - }, - "bin": [ - "bin/phantomjs" - ], - "type": "library", - "autoload": { - "psr-4": { - "Anam\\PhantomLinux\\": "/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-2-Clause" - ], - "authors": [ - { - "name": "Anam hossain", - "email": "enam33@gmail.com" - } - ], - "description": "PhantomJS static linked binary for 64 bit linux systems. Most of Linux distributions are supported including Ubuntu, Debian, Fedora and CentOS.", - "homepage": "http://phantomjs.org/download.html", - "keywords": [ - "binary", - "phantomjs", - "phantomjs binary" - ], - "time": "2016-04-05T05:24:48+00:00" - }, { "name": "aura/session", "version": "2.1.0", @@ -205,18 +163,6 @@ "description": "Composer plugin that provides efficient querying for installed package versions (no runtime IO)", "time": "2020-06-19T07:59:31+00:00" }, - { - "name": "ffmpeg/ffmpeg", - "version": "4.1.4", - "dist": { - "type": "xz", - "url": "https://www.johnvansickle.com/ffmpeg/old-releases/ffmpeg-4.1.4-amd64-static.tar.xz" - }, - "bin": [ - "ffmpeg" - ], - "type": "library" - }, { "name": "guzzlehttp/guzzle", "version": "6.5.5", diff --git a/config/config.example.yml b/config/config.example.yml index 29d6c5d..c6b1f0b 100644 --- a/config/config.example.yml +++ b/config/config.example.yml @@ -23,13 +23,13 @@ convertAdvanced: false convertAdvancedFormats: [mp3, avi, flv, wav] # Path to your avconv or ffmpeg binary -avconv: vendor/bin/ffmpeg +avconv: /usr/bin/ffmpeg # avconv/ffmpeg logging level. avconvVerbosity: error # Path to the directory that contains the phantomjs binary. -phantomjsDir: vendor/bin/ +phantomjsDir: /usr/bin/ # True to disable URL rewriting uglyUrls: false From 7a2c7b42fb770dd1f8d161266800d70317fa72b3 Mon Sep 17 00:00:00 2001 From: Pierre Rudloff Date: Mon, 22 Jun 2020 23:22:42 +0200 Subject: [PATCH 24/34] Remove Windows test config file We don't have a Windows CI anymore --- config/config_test_windows.yml | 13 ------------- tests/BaseTest.php | 8 +------- 2 files changed, 1 insertion(+), 20 deletions(-) delete mode 100644 config/config_test_windows.yml diff --git a/config/config_test_windows.yml b/config/config_test_windows.yml deleted file mode 100644 index 34d8f13..0000000 --- a/config/config_test_windows.yml +++ /dev/null @@ -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 diff --git a/tests/BaseTest.php b/tests/BaseTest.php index aac832b..a377617 100644 --- a/tests/BaseTest.php +++ b/tests/BaseTest.php @@ -22,13 +22,7 @@ abstract class BaseTest extends TestCase */ protected function getConfigFile() { - if (PHP_OS == 'WINNT') { - $configFile = 'config_test_windows.yml'; - } else { - $configFile = 'config_test.yml'; - } - - return __DIR__ . '/../config/' . $configFile; + return __DIR__ . '/../config/config_test.yml'; } /** From 683a19b0fb0c4013db9ff5416e73aca27a967bd0 Mon Sep 17 00:00:00 2001 From: Pierre Rudloff Date: Mon, 22 Jun 2020 23:26:47 +0200 Subject: [PATCH 25/34] Remove references to avconv Most distributions now use ffmpeg instead --- README.md | 10 +++++----- classes/Config.php | 12 ++++++------ config/config.example.yml | 8 ++++---- config/config_test.yml | 2 +- resources/FAQ.md | 6 +++--- tests/ConfigTest.php | 2 +- tests/VideoTest.php | 14 +++++++------- 7 files changed, 27 insertions(+), 27 deletions(-) diff --git a/README.md b/README.md index 9b60df9..3ac824c 100644 --- a/README.md +++ b/README.md @@ -27,7 +27,7 @@ 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 might want to specify the path to ffmpeg in your config file.) You should also ensure that the *templates_c* folder has the right permissions: @@ -133,18 +133,18 @@ server { ## Other dependencies -You need [avconv](https://libav.org/avconv.html) +You need [ffmpeg](https://ffmpeg.org/) in order to enable conversions. If you don't want to enable conversions, you can disable it in `config.yml`. On Debian-based systems: ```bash -sudo apt-get install libav-tools +sudo apt-get install ffmpeg ``` -You also probably need to edit the `avconv` variable in `config.yml` -so that it points to your ffmpeg/avconv binary (`/usr/bin/avconv` on Debian/Ubuntu). +You also probably need to edit the `ffmpeg` variable in `config.yml` +so that it points to your ffmpeg binary (`/usr/bin/ffmpeg` on Debian/Ubuntu). ## Use as library diff --git a/classes/Config.php b/classes/Config.php index 8b90f8a..0460765 100644 --- a/classes/Config.php +++ b/classes/Config.php @@ -70,11 +70,11 @@ class Config public $convertAdvancedFormats = ['mp3', 'avi', 'flv', 'wav']; /** - * avconv or ffmpeg binary path. + * ffmpeg binary path. * * @var string */ - public $avconv = '/usr/bin/ffmpeg'; + public $ffmpeg = '/usr/bin/ffmpeg'; /** * Path to the directory that contains the phantomjs binary. @@ -112,12 +112,12 @@ class Config public $audioBitrate = 128; /** - * avconv/ffmpeg logging level. + * ffmpeg logging level. * Must be one of these: quiet, panic, fatal, error, warning, info, verbose, debug. * * @var string */ - public $avconvVerbosity = 'error'; + public $ffmpegVerbosity = 'error'; /** * App name. @@ -329,9 +329,9 @@ class Config $this->youtubedl, $this->params, $this->python, - $this->avconv, + $this->ffmpeg, $this->phantomjsDir, - $this->avconvVerbosity + $this->ffmpegVerbosity ); } diff --git a/config/config.example.yml b/config/config.example.yml index c6b1f0b..8aeb99a 100644 --- a/config/config.example.yml +++ b/config/config.example.yml @@ -22,11 +22,11 @@ convertAdvanced: false # List of formats available in advanced conversion mode convertAdvancedFormats: [mp3, avi, flv, wav] -# Path to your avconv or ffmpeg binary -avconv: /usr/bin/ffmpeg +# Path to your ffmpeg binary +ffmpeg: /usr/bin/ffmpeg -# avconv/ffmpeg logging level. -avconvVerbosity: error +# ffmpeg logging level. +ffmpegVerbosity: error # Path to the directory that contains the phantomjs binary. phantomjsDir: /usr/bin/ diff --git a/config/config_test.yml b/config/config_test.yml index 99b704b..893344a 100644 --- a/config/config_test.yml +++ b/config/config_test.yml @@ -1,3 +1,3 @@ --- convert: false -avconvVerbosity: fatal +ffmpegVerbosity: fatal diff --git a/resources/FAQ.md b/resources/FAQ.md index c2d3b65..4b80889 100644 --- a/resources/FAQ.md +++ b/resources/FAQ.md @@ -33,13 +33,13 @@ In order to enable audio conversion, you need to add this to your `config.yml` f ```yaml 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 -sudo apt-get install libav-tools +sudo apt-get install ffmpeg ``` ## Deploy AllTube on Heroku diff --git a/tests/ConfigTest.php b/tests/ConfigTest.php index cbaf21d..e0fe7d8 100644 --- a/tests/ConfigTest.php +++ b/tests/ConfigTest.php @@ -70,7 +70,7 @@ class ConfigTest extends BaseTest $this->assertIsArray($config->params); $this->assertIsString($config->youtubedl); $this->assertIsString($config->python); - $this->assertIsString($config->avconv); + $this->assertIsString($config->ffmpeg); $this->assertIsBool($config->convert); $this->assertIsBool($config->uglyUrls); $this->assertIsBool($config->stream); diff --git a/tests/VideoTest.php b/tests/VideoTest.php index 1b85038..7f58516 100644 --- a/tests/VideoTest.php +++ b/tests/VideoTest.php @@ -339,7 +339,7 @@ class VideoTest extends BaseTest } /** - * Test getAudioStream function without avconv. + * Test getAudioStream function without ffmpeg. * * @param string $url URL * @param string $format Format @@ -348,10 +348,10 @@ class VideoTest extends BaseTest * @throws AlltubeLibraryException|ConfigException * @dataProvider urlProvider */ - public function testGetAudioStreamAvconvError($url, $format) + public function testGetAudioStreamFfmpegError($url, $format) { $this->expectException(AvconvException::class); - Config::setOptions(['avconv' => 'foobar']); + Config::setOptions(['ffmpeg' => 'foobar']); $config = Config::getInstance(); $downloader = $config->getDownloader(); @@ -488,7 +488,7 @@ class VideoTest extends BaseTest } /** - * Test getM3uStream function without avconv. + * Test getM3uStream function without ffmpeg. * * @param string $url URL * @param string $format Format @@ -497,10 +497,10 @@ class VideoTest extends BaseTest * @throws AlltubeLibraryException|ConfigException * @dataProvider m3uUrlProvider */ - public function testGetM3uStreamAvconvError($url, $format) + public function testGetM3uStreamFfmpegError($url, $format) { $this->expectException(AvconvException::class); - Config::setOptions(['avconv' => 'foobar']); + Config::setOptions(['ffmpeg' => 'foobar']); $config = Config::getInstance(); $downloader = $config->getDownloader(); @@ -509,7 +509,7 @@ class VideoTest extends BaseTest } /** - * Test getConvertedStream function without avconv. + * Test getConvertedStream function without ffmpeg. * * @param string $url URL * @param string $format Format From 0d5e97d37c3d39e51bebd7c1e75576140a385d9f Mon Sep 17 00:00:00 2001 From: Pierre Rudloff Date: Mon, 22 Jun 2020 23:32:23 +0200 Subject: [PATCH 26/34] Remove obsolete entries from gitignore (fixes #291) --- .gitignore | 8 -------- 1 file changed, 8 deletions(-) diff --git a/.gitignore b/.gitignore index 0875093..05855c8 100644 --- a/.gitignore +++ b/.gitignore @@ -1,16 +1,8 @@ -youtube-dl -dist/ -node_modules/ -config.php vendor/ templates_c/ -ffmpeg.tar.xz -ffmpeg-*/ alltube-*.zip coverage/ -bower_components/ config/config.yml -docs/ clover.xml i18n/*/LC_MESSAGES/*.mo .phpunit.result.cache From eb9d64d7469dc380f90e3f2e0c7ccf8e8e5c7be5 Mon Sep 17 00:00:00 2001 From: Pierre Rudloff Date: Mon, 22 Jun 2020 23:33:39 +0200 Subject: [PATCH 27/34] Remove CONVERT option on Heroku as ffmpeg will not be available --- app.json | 4 ---- 1 file changed, 4 deletions(-) diff --git a/app.json b/app.json index 60c06c2..32b2202 100644 --- a/app.json +++ b/app.json @@ -19,10 +19,6 @@ } ], "env": { - "CONVERT": { - "description": "Enable audio conversion", - "value": "true" - }, "PYTHON": { "description": "Path to python binary", "value": "/app/.heroku/python/bin/python" From b70a3d067906bdd6029164679600544091e6d7da Mon Sep 17 00:00:00 2001 From: Pierre Rudloff Date: Mon, 22 Jun 2020 23:36:43 +0200 Subject: [PATCH 28/34] Remove obsolete resources --- resources/error.xhtml | 23 ----------------------- resources/maintenance.xhtml | 21 --------------------- 2 files changed, 44 deletions(-) delete mode 100644 resources/error.xhtml delete mode 100644 resources/maintenance.xhtml diff --git a/resources/error.xhtml b/resources/error.xhtml deleted file mode 100644 index c0f95bf..0000000 --- a/resources/error.xhtml +++ /dev/null @@ -1,23 +0,0 @@ - - - - - - - AllTube Download - Maintenance - - - - -
-
-

- -

-
An error occurred in the application and your page could not be served. Please try again in a few - moments. -
-
-
- - diff --git a/resources/maintenance.xhtml b/resources/maintenance.xhtml deleted file mode 100644 index c1c9eba..0000000 --- a/resources/maintenance.xhtml +++ /dev/null @@ -1,21 +0,0 @@ - - - - - - - AllTube Download - Maintenance - - - - -
-
-

- -

-
This application is undergoing maintenance right now. Please check back later.
-
-
- - From 606810e99bb0405de1034b79c719f000de2057d4 Mon Sep 17 00:00:00 2001 From: Pierre Rudloff Date: Mon, 22 Jun 2020 23:38:29 +0200 Subject: [PATCH 29/34] Remove gettext extension from Docker image (fixes #290) And only install production dependencies --- Dockerfile | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/Dockerfile b/Dockerfile index 949dd54..5cef839 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,14 +1,13 @@ FROM php:7.3-apache 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 zlib1g-dev python libgmp-dev libzip-dev RUN docker-php-ext-install mbstring RUN docker-php-ext-install intl RUN docker-php-ext-install zip RUN docker-php-ext-install gmp -RUN docker-php-ext-install gettext RUN a2enmod rewrite RUN curl -sS https://getcomposer.org/installer | php COPY resources/php.ini /usr/local/etc/php/ COPY . /var/www/html/ -RUN php composer.phar install --prefer-dist --no-progress +RUN php composer.phar install --prefer-dist --no-progress --no-dev --optimize-autoloader ENV CONVERT=1 From 75d1c08702279ff4d9c8912487b2af001a06b50c Mon Sep 17 00:00:00 2001 From: Pierre Rudloff Date: Mon, 22 Jun 2020 23:51:53 +0200 Subject: [PATCH 30/34] Update dependencies for Docker image --- Dockerfile | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/Dockerfile b/Dockerfile index 5cef839..8a9d7f5 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,12 +1,11 @@ FROM php:7.3-apache RUN apt-get update -RUN apt-get install -y libicu-dev xz-utils git zlib1g-dev python libgmp-dev 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 intl -RUN docker-php-ext-install zip RUN docker-php-ext-install gmp 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 . /var/www/html/ RUN php composer.phar install --prefer-dist --no-progress --no-dev --optimize-autoloader From 7d565bfa89e944fe5c6a7c1b3692de4c7564a9d4 Mon Sep 17 00:00:00 2001 From: Pierre Rudloff Date: Mon, 22 Jun 2020 23:56:18 +0200 Subject: [PATCH 31/34] Don't include .git folder in Docker image (fixes #281) --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 05855c8..950d07a 100644 --- a/.gitignore +++ b/.gitignore @@ -6,3 +6,4 @@ config/config.yml clover.xml i18n/*/LC_MESSAGES/*.mo .phpunit.result.cache +.git/ From 9f6b2d41a947e533125a6467475cc2e9249a0a6a Mon Sep 17 00:00:00 2001 From: Pierre Rudloff Date: Tue, 23 Jun 2020 00:01:55 +0200 Subject: [PATCH 32/34] Call check-platform-reqs when building the Docker image This way we can catch dependency issues earlier --- Dockerfile | 1 + 1 file changed, 1 insertion(+) diff --git a/Dockerfile b/Dockerfile index 8a9d7f5..e5ac935 100644 --- a/Dockerfile +++ b/Dockerfile @@ -8,5 +8,6 @@ RUN a2enmod rewrite RUN curl -sS https://getcomposer.org/installer | php -- --quiet COPY resources/php.ini /usr/local/etc/php/ COPY . /var/www/html/ +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 From 0d7cbfe590ef7bfda3980ac62a14b3c212164df0 Mon Sep 17 00:00:00 2001 From: Pierre Rudloff Date: Tue, 23 Jun 2020 00:15:48 +0200 Subject: [PATCH 33/34] Remove obsolete docs folder --- docs/.htaccess | 3 --- 1 file changed, 3 deletions(-) delete mode 100644 docs/.htaccess diff --git a/docs/.htaccess b/docs/.htaccess deleted file mode 100644 index 4ee1d3d..0000000 --- a/docs/.htaccess +++ /dev/null @@ -1,3 +0,0 @@ - - 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:" - From a8b9b1894927cbf3851606ac3030cff1270fd2e7 Mon Sep 17 00:00:00 2001 From: Pierre Rudloff Date: Tue, 23 Jun 2020 01:05:44 +0200 Subject: [PATCH 34/34] Remove obsolete documentation --- README.md | 20 +++++++++----------- resources/FAQ.md | 1 - 2 files changed, 9 insertions(+), 12 deletions(-) diff --git a/README.md b/README.md index 3ac824c..35ca060 100644 --- a/README.md +++ b/README.md @@ -25,10 +25,6 @@ composer install 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 ffmpeg in your config file.) - You should also ensure that the *templates_c* folder has the right permissions: ```bash @@ -66,19 +62,22 @@ cp config/config.example.yml config/config.yml You will need PHP 7.1 (or higher) and the following PHP modules: -* fileinfo * intl * mbstring -* curl +* gmp ## Web server configuration ### Apache -You will need the following modules: +The following modules are recommended: * mod_mime * mod_rewrite +* mod_expires +* mod_filter +* mod_deflate +* mod_headers ### Nginx @@ -135,7 +134,7 @@ server { You need [ffmpeg](https://ffmpeg.org/) 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: @@ -143,10 +142,9 @@ On Debian-based systems: sudo apt-get install ffmpeg ``` -You also probably need to edit the `ffmpeg` variable in `config.yml` -so that it points to your ffmpeg binary (`/usr/bin/ffmpeg` on Debian/Ubuntu). +If your ffmpeg binary is not installed at `/usr/bin/ffmpeg`, you also need to edit the `ffmpeg` variable in `config.yml`. -## Use as library +## Use as a library 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. diff --git a/resources/FAQ.md b/resources/FAQ.md index 4b80889..2c49197 100644 --- a/resources/FAQ.md +++ b/resources/FAQ.md @@ -47,7 +47,6 @@ sudo apt-get install ffmpeg Create a dyno with the following buildpacks: * `heroku/php` -* `heroku/nodejs` * `heroku/python` You might also need to add the following config variables: