Merge branch 'develop' into feature/stream

Conflicts:
	composer.json
	composer.lock
	controllers/FrontController.php
This commit is contained in:
Pierre Rudloff 2016-09-11 18:58:58 +02:00
commit dd67495ccb
18 changed files with 481 additions and 372 deletions

1
.gitignore vendored
View file

@ -11,3 +11,4 @@ coverage/
bower_components/ bower_components/
config.yml config.yml
docs/ docs/
clover.xml

View file

@ -3,3 +3,5 @@ install:
- composer install --no-dev - composer install --no-dev
before_install: before_install:
- composer selfupdate - composer selfupdate
after_success:
- bash <(curl -s https://codecov.io/bash)

6
CONTRIBUTING.md Normal file
View file

@ -0,0 +1,6 @@
## Report a bug
Before opening a new issue, make sure that:
* It has not already been [reported](https://github.com/Rudloff/alltube/issues).
* You read the [README](README.md) and the [FAQ](FAQ.md).
* You can provide **logs**.

View file

@ -77,6 +77,19 @@ module.exports = function (grunt) {
directory: 'classes/,controllers/,tests/' directory: 'classes/,controllers/,tests/'
} }
} }
},
jsonlint: {
manifests: {
src: ['*.json', '*.webapp'],
options: {
format: true
}
}
},
fixpack: {
package: {
src: 'package.json'
}
} }
} }
); );
@ -90,9 +103,11 @@ module.exports = function (grunt) {
grunt.loadNpmTasks('grunt-contrib-compress'); grunt.loadNpmTasks('grunt-contrib-compress');
grunt.loadNpmTasks('grunt-jslint'); grunt.loadNpmTasks('grunt-jslint');
grunt.loadNpmTasks('grunt-phpdocumentor'); grunt.loadNpmTasks('grunt-phpdocumentor');
grunt.loadNpmTasks('grunt-jsonlint');
grunt.loadNpmTasks('grunt-fixpack');
grunt.registerTask('default', ['uglify', 'cssmin']); grunt.registerTask('default', ['uglify', 'cssmin']);
grunt.registerTask('lint', ['phpcs', 'jslint']); grunt.registerTask('lint', ['jslint', 'fixpack', 'jsonlint', 'phpcs']);
grunt.registerTask('test', ['phpunit']); grunt.registerTask('test', ['phpunit']);
grunt.registerTask('doc', ['phpdocumentor']); grunt.registerTask('doc', ['phpdocumentor']);
grunt.registerTask('release', ['default', 'githash', 'compress']); grunt.registerTask('release', ['default', 'githash', 'compress']);

View file

@ -1,76 +1,94 @@
<?php <?php
/** /**
* Config class * Config class.
*/ */
namespace Alltube; namespace Alltube;
use Symfony\Component\Yaml\Yaml; use Symfony\Component\Yaml\Yaml;
/** /**
* Manage config parameters * Manage config parameters.
*/ */
class Config class Config
{ {
/** /**
* Singleton instance * Singleton instance.
*
* @var Config * @var Config
*/ */
private static $instance; private static $instance;
/** /**
* youtube-dl binary path * youtube-dl binary path.
*
* @var string * @var string
*/ */
public $youtubedl = 'vendor/rg3/youtube-dl/youtube_dl/__main__.py'; public $youtubedl = 'vendor/rg3/youtube-dl/youtube_dl/__main__.py';
/** /**
* python binary path * python binary path.
*
* @var string * @var string
*/ */
public $python = '/usr/bin/python'; public $python = '/usr/bin/python';
/** /**
* youtube-dl parameters * youtube-dl parameters.
*
* @var array * @var array
*/ */
public $params = array('--no-playlist', '--no-warnings', '-f best[protocol^=http]', '--playlist-end', 1); public $params = ['--no-playlist', '--no-warnings', '-f best[protocol^=http]', '--playlist-end', 1];
/** /**
* Enable audio conversion * Enable audio conversion.
*
* @var bool * @var bool
*/ */
public $convert = false; public $convert = false;
/** /**
* avconv or ffmpeg binary path * avconv or ffmpeg binary path.
*
* @var string * @var string
*/ */
public $avconv = 'vendor/bin/ffmpeg'; public $avconv = 'vendor/bin/ffmpeg';
/** /**
* rtmpdump binary path * rtmpdump binary path.
*
* @var string * @var string
*/ */
public $rtmpdump = 'vendor/bin/rtmpdump'; public $rtmpdump = 'vendor/bin/rtmpdump';
/** /**
* curl binary path * curl binary path.
*
* @var string * @var string
*/ */
public $curl = '/usr/bin/curl'; public $curl = '/usr/bin/curl';
/** /**
* curl parameters * curl parameters.
*
* @var array * @var array
*/ */
public $curl_params = array(); public $curl_params = [];
/** /**
* Config constructor * YAML config file path.
*
* @var string
*/ */
private function __construct() private $file;
/**
* Config constructor.
*
* @param string $yamlfile YAML config file path
*/
private function __construct($yamlfile)
{ {
$yamlfile = __DIR__.'/../config.yml'; $this->file = $yamlfile;
if (is_file($yamlfile)) { if (is_file($yamlfile)) {
$yaml = Yaml::parse(file_get_contents($yamlfile)); $yaml = Yaml::parse(file_get_contents($yamlfile));
if (isset($yaml) && is_array($yaml)) { if (isset($yaml) && is_array($yaml)) {
@ -87,20 +105,25 @@ class Config
} }
/** /**
* Get singleton instance * Get singleton instance.
*
* @param string $yamlfile YAML config file name
* *
* @return Config * @return Config
*/ */
public static function getInstance() public static function getInstance($yamlfile = 'config.yml')
{ {
if (is_null(self::$instance)) { $yamlfile = __DIR__.'/../'.$yamlfile;
self::$instance = new Config(); if (is_null(self::$instance) || self::$instance->file != $yamlfile) {
self::$instance = new self($yamlfile);
} }
return self::$instance; return self::$instance;
} }
/** /**
* Destroy singleton instance * Destroy singleton instance.
*
* @return void * @return void
*/ */
public static function destroyInstance() public static function destroyInstance()

View file

@ -1,21 +1,19 @@
<?php <?php
/** /**
* VideoDownload class * VideoDownload class.
*/ */
namespace Alltube; namespace Alltube;
use Symfony\Component\Process\Process;
use Symfony\Component\Process\ProcessBuilder;
use Chain\Chain; use Chain\Chain;
use Symfony\Component\Process\ProcessBuilder;
/** /**
* Extract info about videos * Extract info about videos.
*/ */
class VideoDownload class VideoDownload
{ {
/** /**
* VideoDownload constructor * VideoDownload constructor.
*/ */
public function __construct() public function __construct()
{ {
@ -23,31 +21,32 @@ class VideoDownload
$this->procBuilder = new ProcessBuilder(); $this->procBuilder = new ProcessBuilder();
$this->procBuilder->setPrefix( $this->procBuilder->setPrefix(
array_merge( array_merge(
array($this->config->python, $this->config->youtubedl), [$this->config->python, $this->config->youtubedl],
$this->config->params $this->config->params
) )
); );
} }
/** /**
* List all extractors * List all extractors.
* *
* @return string[] Extractors * @return string[] Extractors
* */ * */
public function listExtractors() public function listExtractors()
{ {
$this->procBuilder->setArguments( $this->procBuilder->setArguments(
array( [
'--list-extractors' '--list-extractors',
) ]
); );
$process = $this->procBuilder->getProcess(); $process = $this->procBuilder->getProcess();
$process->run(); $process->run();
return explode(PHP_EOL, trim($process->getOutput())); return explode(PHP_EOL, trim($process->getOutput()));
} }
/** /**
* Get all information about a video * Get all information about a video.
* *
* @param string $url URL of page * @param string $url URL of page
* @param string $format Format to use for the video * @param string $format Format to use for the video
@ -57,10 +56,10 @@ class VideoDownload
public function getJSON($url, $format = null) public function getJSON($url, $format = null)
{ {
$this->procBuilder->setArguments( $this->procBuilder->setArguments(
array( [
'--dump-json', '--dump-json',
$url $url,
) ]
); );
if (isset($format)) { if (isset($format)) {
$this->procBuilder->add('-f '.$format); $this->procBuilder->add('-f '.$format);
@ -75,7 +74,7 @@ class VideoDownload
} }
/** /**
* Get URL of video from URL of page * Get URL of video from URL of page.
* *
* @param string $url URL of page * @param string $url URL of page
* @param string $format Format to use for the video * @param string $format Format to use for the video
@ -85,10 +84,10 @@ class VideoDownload
public function getURL($url, $format = null) public function getURL($url, $format = null)
{ {
$this->procBuilder->setArguments( $this->procBuilder->setArguments(
array( [
'--get-url', '--get-url',
$url $url,
) ]
); );
if (isset($format)) { if (isset($format)) {
$this->procBuilder->add('-f '.$format); $this->procBuilder->add('-f '.$format);
@ -103,7 +102,7 @@ class VideoDownload
} }
/** /**
* Get filename of video file from URL of page * Get filename of video file from URL of page.
* *
* @param string $url URL of page * @param string $url URL of page
* @param string $format Format to use for the video * @param string $format Format to use for the video
@ -113,10 +112,10 @@ class VideoDownload
public function getFilename($url, $format = null) public function getFilename($url, $format = null)
{ {
$this->procBuilder->setArguments( $this->procBuilder->setArguments(
array( [
'--get-filename', '--get-filename',
$url $url,
) ]
); );
if (isset($format)) { if (isset($format)) {
$this->procBuilder->add('-f '.$format); $this->procBuilder->add('-f '.$format);
@ -131,7 +130,7 @@ class VideoDownload
} }
/** /**
* Get filename of audio from URL of page * Get filename of audio from URL of page.
* *
* @param string $url URL of page * @param string $url URL of page
* @param string $format Format to use for the video * @param string $format Format to use for the video
@ -151,7 +150,7 @@ class VideoDownload
} }
/** /**
* Get audio stream of converted video * Get audio stream of converted video.
* *
* @param string $url URL of page * @param string $url URL of page
* @param string $format Format to use for the video * @param string $format Format to use for the video
@ -172,14 +171,14 @@ class VideoDownload
$video->http_headers->{'User-Agent'} $video->http_headers->{'User-Agent'}
); );
$avconvProc = ProcessBuilder::create( $avconvProc = ProcessBuilder::create(
array( [
$this->config->avconv, $this->config->avconv,
'-v', 'quiet', '-v', 'quiet',
'-i', '-', '-i', '-',
'-f', 'mp3', '-f', 'mp3',
'-vn', '-vn',
'pipe:1' 'pipe:1',
) ]
); );
if (parse_url($video->url, PHP_URL_SCHEME) == 'rtmp') { if (parse_url($video->url, PHP_URL_SCHEME) == 'rtmp') {
@ -187,13 +186,13 @@ class VideoDownload
throw(new \Exception('Can\'t find rtmpdump')); throw(new \Exception('Can\'t find rtmpdump'));
} }
$builder = new ProcessBuilder( $builder = new ProcessBuilder(
array( [
$this->config->rtmpdump, $this->config->rtmpdump,
'-q', '-q',
'-r', '-r',
$video->url, $video->url,
'--pageUrl', $video->webpage_url '--pageUrl', $video->webpage_url,
) ]
); );
if (isset($video->player_url)) { if (isset($video->player_url)) {
$builder->add('--swfVfy'); $builder->add('--swfVfy');
@ -226,19 +225,20 @@ class VideoDownload
$chain = new Chain( $chain = new Chain(
ProcessBuilder::create( ProcessBuilder::create(
array_merge( array_merge(
array( [
$this->config->curl, $this->config->curl,
'--silent', '--silent',
'--location', '--location',
'--user-agent', $video->http_headers->{'User-Agent'}, '--user-agent', $video->http_headers->{'User-Agent'},
$video->url $video->url,
), ],
$this->config->curl_params $this->config->curl_params
) )
) )
); );
$chain->add('|', $avconvProc); $chain->add('|', $avconvProc);
} }
return popen($chain->getProcess()->getCommandLine(), 'r'); return popen($chain->getProcess()->getCommandLine(), 'r');
} }
} }

View file

@ -6,7 +6,7 @@
"type": "project", "type": "project",
"require": { "require": {
"smarty/smarty": "~3.1.29", "smarty/smarty": "~3.1.29",
"rg3/youtube-dl": "~2016.08.12", "rg3/youtube-dl": "~2016.09.08",
"slim/slim": "~3.5.0", "slim/slim": "~3.5.0",
"mathmarques/smarty-view": "~1.1.0", "mathmarques/smarty-view": "~1.1.0",
"symfony/yaml": "~3.1.0", "symfony/yaml": "~3.1.0",
@ -20,7 +20,7 @@
"require-dev": { "require-dev": {
"symfony/var-dumper": "~3.1.0", "symfony/var-dumper": "~3.1.0",
"squizlabs/php_codesniffer": "~2.6.2", "squizlabs/php_codesniffer": "~2.6.2",
"phpunit/phpunit": "~5.4.8" "phpunit/phpunit": "~5.5.2"
}, },
"extra": { "extra": {
"paas": { "paas": {
@ -29,18 +29,20 @@
] ]
} }
}, },
"repositories": [{ "repositories": [
{
"type": "package", "type": "package",
"package": { "package": {
"name": "rg3/youtube-dl", "name": "rg3/youtube-dl",
"version": "2016.08.12", "version": "2016.09.08",
"source": { "source": {
"url": "https://github.com/rg3/youtube-dl.git", "url": "https://github.com/rg3/youtube-dl.git",
"type": "git", "type": "git",
"reference": "2016.08.12" "reference": "2016.09.08"
} }
} }
}, { },
{
"type": "package", "type": "package",
"package": { "package": {
"name": "ffmpeg/ffmpeg", "name": "ffmpeg/ffmpeg",
@ -53,18 +55,22 @@
"ffmpeg" "ffmpeg"
] ]
} }
}], }
"authors": [{ ],
"authors": [
{
"name": "Pierre Rudloff", "name": "Pierre Rudloff",
"email": "contact@rudloff.pro", "email": "contact@rudloff.pro",
"homepage": "https://rudloff.pro/", "homepage": "https://rudloff.pro/",
"role": "Developer" "role": "Developer"
}, { },
{
"name": "Olivier Haquette", "name": "Olivier Haquette",
"email": "contact@olivierhaquette.fr", "email": "contact@olivierhaquette.fr",
"homepage": "http://olivierhaquette.fr/", "homepage": "http://olivierhaquette.fr/",
"role": "Designer" "role": "Designer"
}], }
],
"autoload": { "autoload": {
"psr-4": { "psr-4": {
"Alltube\\": "classes/", "Alltube\\": "classes/",

80
composer.lock generated
View file

@ -4,8 +4,8 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file",
"This file is @generated automatically" "This file is @generated automatically"
], ],
"hash": "45458ad3758a4bfcdcff81c70a53e796", "hash": "086ca596eeeb4c2a0e5d27976b21e4d2",
"content-hash": "2ee8e0ffa53778d2a2eaa5de447573e8", "content-hash": "ec541955f4eb561e1b37b3bbb081af09",
"packages": [ "packages": [
{ {
"name": "container-interop/container-interop", "name": "container-interop/container-interop",
@ -347,16 +347,16 @@
}, },
{ {
"name": "mathmarques/smarty-view", "name": "mathmarques/smarty-view",
"version": "1.1.0", "version": "1.1.1",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/mathmarques/Smarty-View.git", "url": "https://github.com/mathmarques/Smarty-View.git",
"reference": "66f4d28c564c0363eda18d3f5b85a4241b1c4ad1" "reference": "c8f8501a0be4c290e1165fcb9e5064952ef6969d"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/mathmarques/Smarty-View/zipball/66f4d28c564c0363eda18d3f5b85a4241b1c4ad1", "url": "https://api.github.com/repos/mathmarques/Smarty-View/zipball/c8f8501a0be4c290e1165fcb9e5064952ef6969d",
"reference": "66f4d28c564c0363eda18d3f5b85a4241b1c4ad1", "reference": "c8f8501a0be4c290e1165fcb9e5064952ef6969d",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -393,7 +393,7 @@
"template", "template",
"view" "view"
], ],
"time": "2016-03-31 00:41:59" "time": "2016-08-25 19:04:49"
}, },
{ {
"name": "nikic/fast-route", "name": "nikic/fast-route",
@ -572,11 +572,11 @@
}, },
{ {
"name": "rg3/youtube-dl", "name": "rg3/youtube-dl",
"version": "2016.08.12", "version": "2016.09.08",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/rg3/youtube-dl.git", "url": "https://github.com/rg3/youtube-dl.git",
"reference": "2016.08.12" "reference": "2016.09.08"
}, },
"type": "library" "type": "library"
}, },
@ -776,16 +776,16 @@
}, },
{ {
"name": "symfony/process", "name": "symfony/process",
"version": "v3.1.3", "version": "v3.1.4",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/symfony/process.git", "url": "https://github.com/symfony/process.git",
"reference": "04c2dfaae4ec56a5c677b0c69fac34637d815758" "reference": "e64e93041c80e77197ace5ab9385dedb5a143697"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/symfony/process/zipball/04c2dfaae4ec56a5c677b0c69fac34637d815758", "url": "https://api.github.com/repos/symfony/process/zipball/e64e93041c80e77197ace5ab9385dedb5a143697",
"reference": "04c2dfaae4ec56a5c677b0c69fac34637d815758", "reference": "e64e93041c80e77197ace5ab9385dedb5a143697",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -821,20 +821,20 @@
], ],
"description": "Symfony Process Component", "description": "Symfony Process Component",
"homepage": "https://symfony.com", "homepage": "https://symfony.com",
"time": "2016-07-28 11:13:48" "time": "2016-08-16 14:58:24"
}, },
{ {
"name": "symfony/yaml", "name": "symfony/yaml",
"version": "v3.1.3", "version": "v3.1.4",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/symfony/yaml.git", "url": "https://github.com/symfony/yaml.git",
"reference": "1819adf2066880c7967df7180f4f662b6f0567ac" "reference": "f291ed25eb1435bddbe8a96caaef16469c2a092d"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/symfony/yaml/zipball/1819adf2066880c7967df7180f4f662b6f0567ac", "url": "https://api.github.com/repos/symfony/yaml/zipball/f291ed25eb1435bddbe8a96caaef16469c2a092d",
"reference": "1819adf2066880c7967df7180f4f662b6f0567ac", "reference": "f291ed25eb1435bddbe8a96caaef16469c2a092d",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -870,7 +870,7 @@
], ],
"description": "Symfony Yaml Component", "description": "Symfony Yaml Component",
"homepage": "https://symfony.com", "homepage": "https://symfony.com",
"time": "2016-07-17 14:02:08" "time": "2016-09-02 02:12:52"
} }
], ],
"packages-dev": [ "packages-dev": [
@ -930,16 +930,16 @@
}, },
{ {
"name": "myclabs/deep-copy", "name": "myclabs/deep-copy",
"version": "1.5.1", "version": "1.5.2",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/myclabs/DeepCopy.git", "url": "https://github.com/myclabs/DeepCopy.git",
"reference": "a8773992b362b58498eed24bf85005f363c34771" "reference": "da8529775f14f4fdae33f916eb0cf65f6afbddbc"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/a8773992b362b58498eed24bf85005f363c34771", "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/da8529775f14f4fdae33f916eb0cf65f6afbddbc",
"reference": "a8773992b362b58498eed24bf85005f363c34771", "reference": "da8529775f14f4fdae33f916eb0cf65f6afbddbc",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -968,7 +968,7 @@
"object", "object",
"object graph" "object graph"
], ],
"time": "2015-11-20 12:04:31" "time": "2016-09-06 16:07:05"
}, },
{ {
"name": "phpdocumentor/reflection-common", "name": "phpdocumentor/reflection-common",
@ -1424,16 +1424,16 @@
}, },
{ {
"name": "phpunit/phpunit", "name": "phpunit/phpunit",
"version": "5.4.8", "version": "5.5.4",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/sebastianbergmann/phpunit.git", "url": "https://github.com/sebastianbergmann/phpunit.git",
"reference": "3132365e1430c091f208e120b8845d39c25f20e6" "reference": "3e6e88e56c912133de6e99b87728cca7ed70c5f5"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/3132365e1430c091f208e120b8845d39c25f20e6", "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/3e6e88e56c912133de6e99b87728cca7ed70c5f5",
"reference": "3132365e1430c091f208e120b8845d39c25f20e6", "reference": "3e6e88e56c912133de6e99b87728cca7ed70c5f5",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -1472,7 +1472,7 @@
"type": "library", "type": "library",
"extra": { "extra": {
"branch-alias": { "branch-alias": {
"dev-master": "5.4.x-dev" "dev-master": "5.5.x-dev"
} }
}, },
"autoload": { "autoload": {
@ -1498,20 +1498,20 @@
"testing", "testing",
"xunit" "xunit"
], ],
"time": "2016-07-26 14:48:00" "time": "2016-08-26 07:11:44"
}, },
{ {
"name": "phpunit/phpunit-mock-objects", "name": "phpunit/phpunit-mock-objects",
"version": "3.2.4", "version": "3.2.7",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/sebastianbergmann/phpunit-mock-objects.git", "url": "https://github.com/sebastianbergmann/phpunit-mock-objects.git",
"reference": "4e83390f64e7ce04fcaec2ce95cd72823b431d19" "reference": "546898a2c0c356ef2891b39dd7d07f5d82c8ed0a"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/phpunit-mock-objects/zipball/4e83390f64e7ce04fcaec2ce95cd72823b431d19", "url": "https://api.github.com/repos/sebastianbergmann/phpunit-mock-objects/zipball/546898a2c0c356ef2891b39dd7d07f5d82c8ed0a",
"reference": "4e83390f64e7ce04fcaec2ce95cd72823b431d19", "reference": "546898a2c0c356ef2891b39dd7d07f5d82c8ed0a",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -1557,7 +1557,7 @@
"mock", "mock",
"xunit" "xunit"
], ],
"time": "2016-08-17 09:33:51" "time": "2016-09-06 16:07:45"
}, },
{ {
"name": "sebastian/code-unit-reverse-lookup", "name": "sebastian/code-unit-reverse-lookup",
@ -2211,16 +2211,16 @@
}, },
{ {
"name": "symfony/var-dumper", "name": "symfony/var-dumper",
"version": "v3.1.3", "version": "v3.1.4",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/symfony/var-dumper.git", "url": "https://github.com/symfony/var-dumper.git",
"reference": "076235b750137518408f1bc17a8e69b43211836a" "reference": "62ee73706c421654a4c840028954510277f7dfc8"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/symfony/var-dumper/zipball/076235b750137518408f1bc17a8e69b43211836a", "url": "https://api.github.com/repos/symfony/var-dumper/zipball/62ee73706c421654a4c840028954510277f7dfc8",
"reference": "076235b750137518408f1bc17a8e69b43211836a", "reference": "62ee73706c421654a4c840028954510277f7dfc8",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -2270,7 +2270,7 @@
"debug", "debug",
"dump" "dump"
], ],
"time": "2016-07-26 08:04:17" "time": "2016-08-31 09:05:42"
}, },
{ {
"name": "webmozart/assert", "name": "webmozart/assert",

1
config_test.yml Normal file
View file

@ -0,0 +1 @@
convert: false

View file

@ -1,41 +1,45 @@
<?php <?php
/** /**
* FrontController class * FrontController class.
*/ */
namespace Alltube\Controller; namespace Alltube\Controller;
use Alltube\VideoDownload;
use Alltube\Config; use Alltube\Config;
use Slim\Http\Stream; use Alltube\VideoDownload;
use Slim\Container;
use Slim\Http\Request; use Slim\Http\Request;
use Slim\Http\Response; use Slim\Http\Response;
use Slim\Container; use Slim\Http\Stream;
/** /**
* Main controller * Main controller.
*/ */
class FrontController class FrontController
{ {
/** /**
* Config instance * Config instance.
*
* @var Config * @var Config
*/ */
private $config; private $config;
/** /**
* VideoDownload instance * VideoDownload instance.
*
* @var VideoDownload * @var VideoDownload
*/ */
private $download; private $download;
/** /**
* Slim dependency container * Slim dependency container.
*
* @var Container * @var Container
*/ */
private $container; private $container;
/** /**
* FrontController constructor * FrontController constructor.
*
* @param Container $container Slim dependency container * @param Container $container Slim dependency container
*/ */
public function __construct(Container $container) public function __construct(Container $container)
@ -46,7 +50,7 @@ class FrontController
} }
/** /**
* Display index page * Display index page.
* *
* @param Request $request PSR-7 request * @param Request $request PSR-7 request
* @param Response $response PSR-7 response * @param Response $response PSR-7 response
@ -58,16 +62,16 @@ class FrontController
$this->container->view->render( $this->container->view->render(
$response, $response,
'index.tpl', 'index.tpl',
array( [
'convert'=>$this->config->convert, 'convert' => $this->config->convert,
'class'=>'index', 'class' => 'index',
'description'=>'Easily download videos from Youtube, Dailymotion, Vimeo and other websites.' 'description' => 'Easily download videos from Youtube, Dailymotion, Vimeo and other websites.',
) ]
); );
} }
/** /**
* Display a list of extractors * Display a list of extractors.
* *
* @param Request $request PSR-7 request * @param Request $request PSR-7 request
* @param Response $response PSR-7 response * @param Response $response PSR-7 response
@ -79,18 +83,17 @@ class FrontController
$this->container->view->render( $this->container->view->render(
$response, $response,
'extractors.tpl', 'extractors.tpl',
array( [
'extractors'=>$this->download->listExtractors(), 'extractors' => $this->download->listExtractors(),
'class'=>'extractors', 'class' => 'extractors',
'title'=>'Supported websites', 'title' => 'Supported websites',
'description' 'description' => 'List of all supported websites from which Alltube Download can extract video or audio files',
=>'List of all supported websites from which Alltube Download can extract video or audio files' ]
)
); );
} }
/** /**
* Dislay information about the video * Dislay information about the video.
* *
* @param Request $request PSR-7 request * @param Request $request PSR-7 request
* @param Response $response PSR-7 response * @param Response $response PSR-7 response
@ -101,7 +104,7 @@ class FrontController
{ {
$params = $request->getQueryParams(); $params = $request->getQueryParams();
$this->config = Config::getInstance(); $this->config = Config::getInstance();
if (isset($params["url"])) { if (isset($params['url'])) {
if (isset($params['audio'])) { if (isset($params['audio'])) {
try { try {
return $this->getStream($params["url"], 'mp3[protocol^=http]', $response, $request); return $this->getStream($params["url"], 'mp3[protocol^=http]', $response, $request);
@ -109,27 +112,28 @@ class FrontController
$response = $response->withHeader( $response = $response->withHeader(
'Content-Disposition', 'Content-Disposition',
'attachment; filename="'. 'attachment; filename="'.
$this->download->getAudioFilename($params["url"], 'bestaudio/best').'"' $this->download->getAudioFilename($params['url'], 'bestaudio/best').'"'
); );
$response = $response->withHeader('Content-Type', 'audio/mpeg'); $response = $response->withHeader('Content-Type', 'audio/mpeg');
if ($request->isGet()) { if ($request->isGet()) {
$process = $this->download->getAudioStream($params["url"], 'bestaudio/best'); $process = $this->download->getAudioStream($params['url'], 'bestaudio/best');
$response = $response->withBody(new Stream($process)); $response = $response->withBody(new Stream($process));
} }
return $response; return $response;
} }
} else { } else {
$video = $this->download->getJSON($params["url"]); $video = $this->download->getJSON($params['url']);
$this->container->view->render( $this->container->view->render(
$response, $response,
'video.tpl', 'video.tpl',
array( [
'video'=>$video, 'video' => $video,
'class'=>'video', 'class' => 'video',
'title'=>$video->title, 'title' => $video->title,
'description'=>'Download "'.$video->title.'" from '.$video->extractor_key 'description' => 'Download "'.$video->title.'" from '.$video->extractor_key,
) ]
); );
} }
} else { } else {
@ -138,10 +142,12 @@ class FrontController
} }
/** /**
* Display an error page * Display an error page.
*
* @param Request $request PSR-7 request * @param Request $request PSR-7 request
* @param Response $response PSR-7 response * @param Response $response PSR-7 response
* @param \Exception $exception Error to display * @param \Exception $exception Error to display
*
* @return Response HTTP response * @return Response HTTP response
*/ */
public function error(Request $request, Response $response, \Exception $exception) public function error(Request $request, Response $response, \Exception $exception)
@ -149,12 +155,13 @@ class FrontController
$this->container->view->render( $this->container->view->render(
$response, $response,
'error.tpl', 'error.tpl',
array( [
'errors'=>$exception->getMessage(), 'errors' => $exception->getMessage(),
'class'=>'video', 'class' => 'video',
'title'=>'Error' 'title' => 'Error',
) ]
); );
return $response->withStatus(500); return $response->withStatus(500);
} }
@ -176,7 +183,7 @@ class FrontController
} }
/** /**
* Redirect to video file * Redirect to video file.
* *
* @param Request $request PSR-7 request * @param Request $request PSR-7 request
* @param Response $response PSR-7 response * @param Response $response PSR-7 response
@ -186,18 +193,19 @@ class FrontController
public function redirect(Request $request, Response $response) public function redirect(Request $request, Response $response)
{ {
$params = $request->getQueryParams(); $params = $request->getQueryParams();
if (isset($params["url"])) { if (isset($params['url'])) {
try { try {
return $this->getStream($params["url"], $params["format"], $response, $request); return $this->getStream($params["url"], $params["format"], $response, $request);
} catch (\Exception $e) { } catch (\Exception $e) {
$response->getBody()->write($e->getMessage()); $response->getBody()->write($e->getMessage());
return $response->withHeader('Content-Type', 'text/plain'); return $response->withHeader('Content-Type', 'text/plain');
} }
} }
} }
/** /**
* Output JSON info about the video * Output JSON info about the video.
* *
* @param Request $request PSR-7 request * @param Request $request PSR-7 request
* @param Response $response PSR-7 response * @param Response $response PSR-7 response
@ -207,13 +215,14 @@ class FrontController
public function json(Request $request, Response $response) public function json(Request $request, Response $response)
{ {
$params = $request->getQueryParams(); $params = $request->getQueryParams();
if (isset($params["url"])) { if (isset($params['url'])) {
try { try {
$video = $this->download->getJSON($params["url"]); $video = $this->download->getJSON($params['url']);
return $response->withJson($video); return $response->withJson($video);
} catch (\Exception $e) { } catch (\Exception $e) {
return $response->withJson( return $response->withJson(
array('success'=>false, 'error'=>$e->getMessage()) ['success' => false, 'error' => $e->getMessage()]
); );
} }
} }

View file

@ -1,6 +1,6 @@
<?php <?php
require_once __DIR__.'/vendor/autoload.php'; require_once __DIR__.'/vendor/autoload.php';
use Alltube\VideoDownload;
use Alltube\Controller\FrontController; use Alltube\Controller\FrontController;
if (strpos($_SERVER['REQUEST_URI'], '/index.php') !== false) { if (strpos($_SERVER['REQUEST_URI'], '/index.php') !== false) {
@ -22,26 +22,26 @@ $container['view'] = function ($c) {
$controller = new FrontController($container); $controller = new FrontController($container);
$container['errorHandler'] = array($controller, 'error'); $container['errorHandler'] = [$controller, 'error'];
$app->get( $app->get(
'/', '/',
array($controller, 'index') [$controller, 'index']
)->setName('index'); )->setName('index');
$app->get( $app->get(
'/extractors', '/extractors',
array($controller, 'extractors') [$controller, 'extractors']
)->setName('extractors'); )->setName('extractors');
$app->get( $app->get(
'/video', '/video',
array($controller, 'video') [$controller, 'video']
)->setName('video'); )->setName('video');
$app->get( $app->get(
'/redirect', '/redirect',
array($controller, 'redirect') [$controller, 'redirect']
)->setName('redirect'); )->setName('redirect');
$app->get( $app->get(
'/json', '/json',
array($controller, 'json') [$controller, 'json']
); );
$app->run(); $app->run();

View file

@ -3,27 +3,33 @@
"name": "AllTube Download", "name": "AllTube Download",
"description": "Easily download videos from Youtube, Dailymotion, Vimeo and other websites", "description": "Easily download videos from Youtube, Dailymotion, Vimeo and other websites",
"display": "standalone", "display": "standalone",
"icons": [{ "icons": [
{
"src": "img/favicon.png", "src": "img/favicon.png",
"sizes": "32x32", "sizes": "32x32",
"type": "image/png" "type": "image/png"
}, { },
{
"src": "img/logo_60.png", "src": "img/logo_60.png",
"sizes": "60x60", "sizes": "60x60",
"type": "image/png" "type": "image/png"
}, { },
{
"src": "img/logo_90.png", "src": "img/logo_90.png",
"sizes": "90x60", "sizes": "90x60",
"type": "image/png" "type": "image/png"
}, { },
{
"src": "img/logo_app.png", "src": "img/logo_app.png",
"sizes": "243x243", "sizes": "243x243",
"type": "image/png" "type": "image/png"
}, { },
{
"src": "img/logo_250.png", "src": "img/logo_250.png",
"sizes": "250x250", "sizes": "250x250",
"type": "image/png" "type": "image/png"
}], }
],
"lang": "en", "lang": "en",
"start_url": "./", "start_url": "./",
"theme_color": "#4F4F4F", "theme_color": "#4F4F4F",

View file

@ -1,23 +1,36 @@
{ {
"name": "alltube", "name": "alltube",
"description": "HTML GUI for youtube-dl",
"version": "0.5.0", "version": "0.5.0",
"license": "GPL-3.0", "author": "Pierre Rudloff",
"bugs": "https://github.com/Rudloff/alltube/issues",
"dependencies": { "dependencies": {
"bower": "~1.7.1",
"grunt": "~1.0.1", "grunt": "~1.0.1",
"grunt-cli": "~1.2.0", "grunt-cli": "~1.2.0",
"grunt-contrib-cssmin": "~1.0.0", "grunt-contrib-cssmin": "~1.0.0",
"grunt-contrib-uglify": "~2.0.0", "grunt-contrib-uglify": "~2.0.0"
"bower": "~1.7.1"
}, },
"devDependencies": { "devDependencies": {
"grunt-contrib-watch": "~1.0.0",
"grunt-phpcs": "~0.4.0",
"grunt-phpunit": "~0.3.6",
"grunt-contrib-compress": "~1.3.0", "grunt-contrib-compress": "~1.3.0",
"grunt-contrib-watch": "~1.0.0",
"grunt-fixpack": "~0.1.0",
"grunt-githash": "~0.1.3", "grunt-githash": "~0.1.3",
"grunt-jslint": "~1.1.14", "grunt-jslint": "~1.1.14",
"grunt-phpdocumentor": "~0.4.1" "grunt-jsonlint": "~1.1.0",
"grunt-phpcs": "~0.4.0",
"grunt-phpdocumentor": "~0.4.1",
"grunt-phpunit": "~0.3.6"
}, },
"homepage": "https://www.alltubedownload.net/",
"keywords": [
"alltube",
"dowload",
"video",
"youtube"
],
"license": "GPL-3.0",
"main": "index.php",
"repository": { "repository": {
"type": "git", "type": "git",
"url": "https://github.com/Rudloff/alltube.git" "url": "https://github.com/Rudloff/alltube.git"

View file

@ -11,5 +11,6 @@
</testsuites> </testsuites>
<logging> <logging>
<log type="coverage-html" target="coverage/" /> <log type="coverage-html" target="coverage/" />
<log type="coverage-clover" target="clover.xml" />
</logging> </logging>
</phpunit> </phpunit>

View file

@ -1,32 +1,57 @@
<?php <?php
/** /**
* ConfigTest class * ConfigTest class.
*/ */
namespace Alltube\Test; namespace Alltube\Test;
use Alltube\Config; use Alltube\Config;
/** /**
* Unit tests for the Config class * Unit tests for the Config class.
*/ */
class ConfigTest extends \PHPUnit_Framework_TestCase class ConfigTest extends \PHPUnit_Framework_TestCase
{ {
/**
* Config class instance.
*
* @var Config
*/
private $config;
/** /**
* Test the getInstance function * Prepare tests.
*/
protected function setUp()
{
$this->config = Config::getInstance('config_test.yml');
}
/**
* Test the getInstance function.
* *
* @return void * @return void
*/ */
public function testGetInstance() public function testGetInstance()
{
$this->assertEquals($this->config->convert, false);
$this->assertInternalType('array', $this->config->curl_params);
$this->assertInternalType('array', $this->config->params);
$this->assertInternalType('string', $this->config->youtubedl);
$this->assertInternalType('string', $this->config->python);
$this->assertInternalType('string', $this->config->avconv);
$this->assertInternalType('string', $this->config->rtmpdump);
}
/**
* Test the getInstance function with the CONVERT environment variable.
*
* @return void
*/
public function testGetInstanceWithEnv()
{ {
putenv('CONVERT=1'); putenv('CONVERT=1');
$config = Config::getInstance(); Config::destroyInstance();
$config = Config::getInstance('config_test.yml');
$this->assertEquals($config->convert, true); $this->assertEquals($config->convert, true);
$this->assertInternalType('array', $config->curl_params);
$this->assertInternalType('array', $config->params);
$this->assertInternalType('string', $config->youtubedl);
$this->assertInternalType('string', $config->python);
$this->assertInternalType('string', $config->avconv);
$this->assertInternalType('string', $config->rtmpdump);
} }
} }

View file

@ -1,24 +1,25 @@
<?php <?php
/** /**
* VideoDownloadTest class * VideoDownloadTest class.
*/ */
namespace Alltube\Test; namespace Alltube\Test;
use Alltube\VideoDownload; use Alltube\VideoDownload;
/** /**
* Unit tests for the VideoDownload class * Unit tests for the VideoDownload class.
*/ */
class VideoDownloadTest extends \PHPUnit_Framework_TestCase class VideoDownloadTest extends \PHPUnit_Framework_TestCase
{ {
/** /**
* VideoDownload instance * VideoDownload instance.
*
* @var VideoDownload * @var VideoDownload
*/ */
private $download; private $download;
/** /**
* Initialize properties used by test * Initialize properties used by test.
*/ */
protected function setUp() protected function setUp()
{ {
@ -26,7 +27,7 @@ class VideoDownloadTest extends \PHPUnit_Framework_TestCase
} }
/** /**
* Destroy properties after test * Destroy properties after test.
*/ */
protected function tearDown() protected function tearDown()
{ {
@ -34,7 +35,7 @@ class VideoDownloadTest extends \PHPUnit_Framework_TestCase
} }
/** /**
* Test listExtractors function * Test listExtractors function.
* *
* @return void * @return void
*/ */
@ -45,7 +46,7 @@ class VideoDownloadTest extends \PHPUnit_Framework_TestCase
} }
/** /**
* Test getURL function * Test getURL function.
* *
* @param string $url URL * @param string $url URL
* @param string $format Format * @param string $format Format
@ -62,7 +63,7 @@ class VideoDownloadTest extends \PHPUnit_Framework_TestCase
} }
/** /**
* Test getURL function errors * Test getURL function errors.
* *
* @param string $url URL * @param string $url URL
* *
@ -76,62 +77,62 @@ class VideoDownloadTest extends \PHPUnit_Framework_TestCase
} }
/** /**
* Provides URLs for tests * Provides URLs for tests.
* *
* @return array[] * @return array[]
*/ */
public function urlProvider() public function urlProvider()
{ {
return array( return [
array( [
'https://www.youtube.com/watch?v=M7IpKCZ47pU', null, 'https://www.youtube.com/watch?v=M7IpKCZ47pU', null,
"It's Not Me, It's You - Hearts Under Fire-M7IpKCZ47pU.mp4", "It's Not Me, It's You - Hearts Under Fire-M7IpKCZ47pU.mp4",
'googlevideo.com', 'googlevideo.com',
"It's Not Me, It's You - Hearts Under Fire-M7IpKCZ47pU.mp3" "It's Not Me, It's You - Hearts Under Fire-M7IpKCZ47pU.mp3",
), ],
array( [
'https://www.youtube.com/watch?v=RJJ6FCAXvKg', 22, 'https://www.youtube.com/watch?v=RJJ6FCAXvKg', 22,
"'Heart Attack' - Demi Lovato ". "'Heart Attack' - Demi Lovato ".
"(Sam Tsui & Against The Current)-RJJ6FCAXvKg.mp4", '(Sam Tsui & Against The Current)-RJJ6FCAXvKg.mp4',
'googlevideo.com', 'googlevideo.com',
"'Heart Attack' - Demi Lovato ". "'Heart Attack' - Demi Lovato ".
"(Sam Tsui & Against The Current)-RJJ6FCAXvKg.mp3" '(Sam Tsui & Against The Current)-RJJ6FCAXvKg.mp3',
), ],
array( [
'https://vimeo.com/24195442', null, 'https://vimeo.com/24195442', null,
"Carving the Mountains-24195442.mp4", 'Carving the Mountains-24195442.mp4',
'vimeocdn.com', 'vimeocdn.com',
"Carving the Mountains-24195442.mp3" 'Carving the Mountains-24195442.mp3',
), ],
array( [
'http://www.bbc.co.uk/programmes/b039g8p7', 'bestaudio/best', 'http://www.bbc.co.uk/programmes/b039g8p7', 'bestaudio/best',
"Leonard Cohen, Kaleidoscope - BBC Radio 4-b039d07m.flv", 'Leonard Cohen, Kaleidoscope - BBC Radio 4-b039d07m.flv',
'bbcodspdns.fcod.llnwd.net', 'bbcodspdns.fcod.llnwd.net',
"Leonard Cohen, Kaleidoscope - BBC Radio 4-b039d07m.mp3" 'Leonard Cohen, Kaleidoscope - BBC Radio 4-b039d07m.mp3',
), ],
array( [
'http://www.rtl2.de/sendung/grip-das-motormagazin/folge/folge-203-0', 'bestaudio/best', 'http://www.rtl2.de/sendung/grip-das-motormagazin/folge/folge-203-0', 'bestaudio/best',
"GRIP sucht den Sommerkönig-folge-203-0.f4v", 'GRIP sucht den Sommerkönig-folge-203-0.f4v',
'edgefcs.net', 'edgefcs.net',
"GRIP sucht den Sommerkönig-folge-203-0.mp3" 'GRIP sucht den Sommerkönig-folge-203-0.mp3',
) ],
); ];
} }
/** /**
* Provides incorrect URLs for tests * Provides incorrect URLs for tests.
* *
* @return array[] * @return array[]
*/ */
public function errorUrlProvider() public function errorUrlProvider()
{ {
return array( return [
array('http://example.com/video') ['http://example.com/video'],
); ];
} }
/** /**
* Test getJSON function * Test getJSON function.
* *
* @param string $url URL * @param string $url URL
* @param string $format Format * @param string $format Format
@ -151,7 +152,7 @@ class VideoDownloadTest extends \PHPUnit_Framework_TestCase
} }
/** /**
* Test getJSON function errors * Test getJSON function errors.
* *
* @param string $url URL * @param string $url URL
* *
@ -165,7 +166,7 @@ class VideoDownloadTest extends \PHPUnit_Framework_TestCase
} }
/** /**
* Test getFilename function * Test getFilename function.
* *
* @param string $url URL * @param string $url URL
* @param string $format Format * @param string $format Format
@ -181,7 +182,7 @@ class VideoDownloadTest extends \PHPUnit_Framework_TestCase
} }
/** /**
* Test getFilename function errors * Test getFilename function errors.
* *
* @param string $url URL * @param string $url URL
* *
@ -195,7 +196,7 @@ class VideoDownloadTest extends \PHPUnit_Framework_TestCase
} }
/** /**
* Test getAudioFilename function * Test getAudioFilename function.
* *
* @param string $url URL * @param string $url URL
* @param string $format Format * @param string $format Format
@ -213,7 +214,7 @@ class VideoDownloadTest extends \PHPUnit_Framework_TestCase
} }
/** /**
* Test getAudioStream function * Test getAudioStream function.
* *
* @param string $url URL * @param string $url URL
* @param string $format Format * @param string $format Format
@ -229,7 +230,7 @@ class VideoDownloadTest extends \PHPUnit_Framework_TestCase
} }
/** /**
* Test getAudioStream function without avconv * Test getAudioStream function without avconv.
* *
* @param string $url URL * @param string $url URL
* @param string $format Format * @param string $format Format
@ -246,7 +247,7 @@ class VideoDownloadTest extends \PHPUnit_Framework_TestCase
} }
/** /**
* Test getAudioStream function without curl or rtmpdump * Test getAudioStream function without curl or rtmpdump.
* *
* @param string $url URL * @param string $url URL
* @param string $format Format * @param string $format Format