Merge branch 'release-0.7.2-beta2'

This commit is contained in:
Pierre Rudloff 2017-04-02 20:37:58 +02:00
commit 8c58c379de
20 changed files with 1145 additions and 251 deletions

View file

@ -6,6 +6,7 @@ install:
- composer install - composer install
before_install: before_install:
- npm install -g npm@3 - npm install -g npm@3
script: vendor/bin/phpunit
after_success: after_success:
- bash <(curl -s https://codecov.io/bash) - bash <(curl -s https://codecov.io/bash)
before_deploy: before_deploy:

View file

@ -5,12 +5,12 @@ RUN apt-get install -y libicu-dev xz-utils git zlib1g-dev python nodejs
RUN docker-php-ext-install mbstring RUN docker-php-ext-install mbstring
RUN docker-php-ext-install intl RUN docker-php-ext-install intl
RUN docker-php-ext-install zip RUN docker-php-ext-install zip
RUN npm install -g bower grunt-cli
RUN a2enmod rewrite RUN a2enmod rewrite
RUN curl -sS https://getcomposer.org/installer | php RUN curl -sS https://getcomposer.org/installer | php
COPY php.ini /usr/local/etc/php/ COPY php.ini /usr/local/etc/php/
COPY . /var/www/html/ COPY . /var/www/html/
RUN php composer.phar install --prefer-dist RUN php composer.phar install --prefer-dist
RUN npm install RUN npm install
RUN bower --allow-root install RUN ./node_modules/.bin/bower --allow-root install
RUN grunt RUN ./node_modules/.bin/grunt
ENV CONVERT=1

76
FAQ.md
View file

@ -12,15 +12,15 @@ You can ususally download the video by doing *File > Save to* or *ctrl + S*.
You need to create a YAML file called `config.yml` at the root of your project. You need to create a YAML file called `config.yml` at the root of your project.
Here are the parameters that you can set: Here are the parameters that you can set:
* youtubedl: path to your youtube-dl binary * `youtubedl`: path to your youtube-dl binary
* python: path to your python binary * `python`: path to your python binary
* params: an array of parameters to pass to youtube-dl * `params`: an array of parameters to pass to youtube-dl
* curl_params: an array of parameters to pass to curl * `curl_params`: an array of parameters to pass to curl
* convert: true to enable audio conversion * `convert`: true to enable audio conversion
* avconv: path to your avconv or ffmpeg binary * `avconv`: path to your avconv or ffmpeg binary
* rtmpdump: path to your rtmpdump binary * `rtmpdump`: path to your rtmpdump binary
See [config.example.yml](config.example.yml) for default values. See [`config.example.yml`](config.example.yml) for default values.
## How do I enable audio conversion? ## How do I enable audio conversion?
@ -61,7 +61,7 @@ Some websites generate an unique video URL for each IP address. When using Alltu
There are two known workarounds: There are two known workarounds:
* You can run Alltube locally on your computer. * You can run Alltube locally on your computer.
* You can use the experimental `feature/stream` branch which streams the video through the server in order to bypass IP restrictions. * You can enable streaming videos through the server (see below).
Please note that this can use a lot of resources on the server (which is why we won't enable it on alltubedownload.net). Please note that this can use a lot of resources on the server (which is why we won't enable it on alltubedownload.net).
## CSS and JavaScript files are missing ## CSS and JavaScript files are missing
@ -71,3 +71,61 @@ You need to either:
* Use a [release package](https://github.com/Rudloff/alltube/releases) * Use a [release package](https://github.com/Rudloff/alltube/releases)
* Run `npm install` (see detailed instructions in the [README](README.md#from-git)) * Run `npm install` (see detailed instructions in the [README](README.md#from-git))
## I get a 404 error on every page except the index
This is probably because your server does not have mod_rewrite or AllowOverride is disabled.
You can work around this by adding this to your `config.yml` file:
```yaml
uglyUrls: true
```
## How do I enable streaming videos through the server?
You need to add this to your `config.yml` file:
```yaml
stream: true
```
Note that this can use a lot of ressources on your server.
## I want to download M3U videos
You need to enable streaming (see above).
## The downloaded videos have a strange name like `videoplayback.mp4`
Alltube can rename videos automatically if you enable streaming (see above).
## I want to download a video that isn't available in my country
If the video is available in the server's country, you can download it if you enable streaming (see above).
## How do I run the Docker image?
```bash
docker run -p 8080:80 rudloff/alltube
```
## How do I 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
```

View file

@ -33,6 +33,16 @@ chmod 777 templates_c/
If your web server is Apache, you need to set the `AllowOverride` setting to `All` or `FileInfo`. If your web server is Apache, you need to set the `AllowOverride` setting to `All` or `FileInfo`.
#### Update
When updating from Git, you need to run npm and Composer again:
```bash
git pull
npm install
composer install
```
## Config ## Config
If you want to use a custom config, you need to create a config file: If you want to use a custom config, you need to create a config file:

View file

@ -38,7 +38,7 @@ class Config
* *
* @var array * @var array
*/ */
public $params = ['--no-playlist', '--no-warnings', '-f best[protocol^=http]', '--playlist-end', 1]; public $params = ['--no-playlist', '--no-warnings', '--playlist-end', 1];
/** /**
* Enable audio conversion. * Enable audio conversion.
@ -82,6 +82,13 @@ class Config
*/ */
public $uglyUrls = false; public $uglyUrls = false;
/**
* Stream downloaded files trough server?
*
* @var bool
*/
public $stream = false;
/** /**
* YAML config file path. * YAML config file path.
* *

View file

@ -295,4 +295,33 @@ class VideoDownload
return popen($chain->getProcess()->getCommandLine(), 'r'); return popen($chain->getProcess()->getCommandLine(), 'r');
} }
/**
* Get video stream from an M3U playlist.
*
* @param \stdClass $video Video object returned by getJSON
*
* @return resource popen stream
*/
public function getM3uStream(\stdClass $video)
{
if (!shell_exec('which '.$this->config->avconv)) {
throw(new \Exception('Can\'t find avconv or ffmpeg'));
}
$procBuilder = ProcessBuilder::create(
[
$this->config->avconv,
'-v', 'quiet',
'-i', $video->url,
'-f', $video->ext,
'-c', 'copy',
'-bsf:a', 'aac_adtstoasc',
'-movflags', 'frag_keyframe+empty_moov',
'pipe:1',
]
);
return popen($procBuilder->getProcess()->getCommandLine(), 'r');
}
} }

View file

@ -12,6 +12,8 @@
"symfony/process": "~3.2.0", "symfony/process": "~3.2.0",
"ptachoire/process-builder-chain": "~1.2.0", "ptachoire/process-builder-chain": "~1.2.0",
"rudloff/smarty-plugin-noscheme": "~0.1.0", "rudloff/smarty-plugin-noscheme": "~0.1.0",
"guzzlehttp/guzzle": "~6.2.0",
"rudloff/rtmpdump-bin": "~2.3",
"aura/session": "~2.1.0" "aura/session": "~2.1.0"
}, },
"require-dev": { "require-dev": {
@ -19,7 +21,7 @@
"squizlabs/php_codesniffer": "~2.7.0", "squizlabs/php_codesniffer": "~2.7.0",
"phpunit/phpunit": "~5.7.2", "phpunit/phpunit": "~5.7.2",
"ffmpeg/ffmpeg": "dev-release", "ffmpeg/ffmpeg": "dev-release",
"rg3/youtube-dl": "~2017.01.10", "rg3/youtube-dl": "~2017.03.07",
"rudloff/rtmpdump-bin": "~2.3", "rudloff/rtmpdump-bin": "~2.3",
"heroku/heroku-buildpack-php": "*" "heroku/heroku-buildpack-php": "*"
}, },
@ -35,10 +37,10 @@
"type": "package", "type": "package",
"package": { "package": {
"name": "rg3/youtube-dl", "name": "rg3/youtube-dl",
"version": "2017.01.10", "version": "2017.03.07",
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://github.com/rg3/youtube-dl/archive/2017.01.10.zip" "url": "https://github.com/rg3/youtube-dl/archive/2017.03.07.zip"
} }
} }
}, },
@ -48,7 +50,7 @@
"name": "ffmpeg/ffmpeg", "name": "ffmpeg/ffmpeg",
"version": "dev-release", "version": "dev-release",
"dist": { "dist": {
"url": "http://johnvansickle.com/ffmpeg/releases/ffmpeg-release-64bit-static.tar.xz", "url": "https://johnvansickle.com/ffmpeg/releases/ffmpeg-release-64bit-static.tar.xz",
"type": "xz" "type": "xz"
}, },
"bin": [ "bin": [
@ -77,9 +79,6 @@
"Alltube\\Controller\\": "controllers/" "Alltube\\Controller\\": "controllers/"
} }
}, },
"config": {
"secure-http": false
},
"scripts": { "scripts": {
"compile": "composer install --dev" "compile": "composer install --dev"
} }

495
composer.lock generated
View file

@ -4,7 +4,7 @@
"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"
], ],
"content-hash": "16268cc5135ed42aedf75446f4e39bd7", "content-hash": "1ac742cf7c2832a7af628c157ced2dbc",
"packages": [ "packages": [
{ {
"name": "aura/session", "name": "aura/session",
@ -70,18 +70,21 @@
}, },
{ {
"name": "container-interop/container-interop", "name": "container-interop/container-interop",
"version": "1.1.0", "version": "1.2.0",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/container-interop/container-interop.git", "url": "https://github.com/container-interop/container-interop.git",
"reference": "fc08354828f8fd3245f77a66b9e23a6bca48297e" "reference": "79cbf1341c22ec75643d841642dd5d6acd83bdb8"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/container-interop/container-interop/zipball/fc08354828f8fd3245f77a66b9e23a6bca48297e", "url": "https://api.github.com/repos/container-interop/container-interop/zipball/79cbf1341c22ec75643d841642dd5d6acd83bdb8",
"reference": "fc08354828f8fd3245f77a66b9e23a6bca48297e", "reference": "79cbf1341c22ec75643d841642dd5d6acd83bdb8",
"shasum": "" "shasum": ""
}, },
"require": {
"psr/container": "^1.0"
},
"type": "library", "type": "library",
"autoload": { "autoload": {
"psr-4": { "psr-4": {
@ -93,7 +96,186 @@
"MIT" "MIT"
], ],
"description": "Promoting the interoperability of container objects (DIC, SL, etc.)", "description": "Promoting the interoperability of container objects (DIC, SL, etc.)",
"time": "2014-12-30T15:22:37+00:00" "homepage": "https://github.com/container-interop/container-interop",
"time": "2017-02-14T19:40:03+00:00"
},
{
"name": "guzzlehttp/guzzle",
"version": "6.2.3",
"source": {
"type": "git",
"url": "https://github.com/guzzle/guzzle.git",
"reference": "8d6c6cc55186db87b7dc5009827429ba4e9dc006"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/guzzle/guzzle/zipball/8d6c6cc55186db87b7dc5009827429ba4e9dc006",
"reference": "8d6c6cc55186db87b7dc5009827429ba4e9dc006",
"shasum": ""
},
"require": {
"guzzlehttp/promises": "^1.0",
"guzzlehttp/psr7": "^1.4",
"php": ">=5.5"
},
"require-dev": {
"ext-curl": "*",
"phpunit/phpunit": "^4.0",
"psr/log": "^1.0"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "6.2-dev"
}
},
"autoload": {
"files": [
"src/functions_include.php"
],
"psr-4": {
"GuzzleHttp\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Michael Dowling",
"email": "mtdowling@gmail.com",
"homepage": "https://github.com/mtdowling"
}
],
"description": "Guzzle is a PHP HTTP client library",
"homepage": "http://guzzlephp.org/",
"keywords": [
"client",
"curl",
"framework",
"http",
"http client",
"rest",
"web service"
],
"time": "2017-02-28T22:50:30+00:00"
},
{
"name": "guzzlehttp/promises",
"version": "v1.3.1",
"source": {
"type": "git",
"url": "https://github.com/guzzle/promises.git",
"reference": "a59da6cf61d80060647ff4d3eb2c03a2bc694646"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/guzzle/promises/zipball/a59da6cf61d80060647ff4d3eb2c03a2bc694646",
"reference": "a59da6cf61d80060647ff4d3eb2c03a2bc694646",
"shasum": ""
},
"require": {
"php": ">=5.5.0"
},
"require-dev": {
"phpunit/phpunit": "^4.0"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.4-dev"
}
},
"autoload": {
"psr-4": {
"GuzzleHttp\\Promise\\": "src/"
},
"files": [
"src/functions_include.php"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Michael Dowling",
"email": "mtdowling@gmail.com",
"homepage": "https://github.com/mtdowling"
}
],
"description": "Guzzle promises library",
"keywords": [
"promise"
],
"time": "2016-12-20T10:07:11+00:00"
},
{
"name": "guzzlehttp/psr7",
"version": "1.4.1",
"source": {
"type": "git",
"url": "https://github.com/guzzle/psr7.git",
"reference": "0d6c7ca039329247e4f0f8f8f6506810e8248855"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/guzzle/psr7/zipball/0d6c7ca039329247e4f0f8f8f6506810e8248855",
"reference": "0d6c7ca039329247e4f0f8f8f6506810e8248855",
"shasum": ""
},
"require": {
"php": ">=5.4.0",
"psr/http-message": "~1.0"
},
"provide": {
"psr/http-message-implementation": "1.0"
},
"require-dev": {
"phpunit/phpunit": "~4.0"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.4-dev"
}
},
"autoload": {
"psr-4": {
"GuzzleHttp\\Psr7\\": "src/"
},
"files": [
"src/functions_include.php"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Michael Dowling",
"email": "mtdowling@gmail.com",
"homepage": "https://github.com/mtdowling"
},
{
"name": "Tobias Schultze",
"homepage": "https://github.com/Tobion"
}
],
"description": "PSR-7 message implementation that also provides common utility methods",
"keywords": [
"http",
"message",
"request",
"response",
"stream",
"uri",
"url"
],
"time": "2017-02-27T10:51:17+00:00"
}, },
{ {
"name": "jeremykendall/php-domain-parser", "name": "jeremykendall/php-domain-parser",
@ -273,16 +455,16 @@
}, },
{ {
"name": "nikic/fast-route", "name": "nikic/fast-route",
"version": "v1.1.0", "version": "v1.2.0",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/nikic/FastRoute.git", "url": "https://github.com/nikic/FastRoute.git",
"reference": "f3dcf5130e634b6123d40727d612ec6aa4f61fb3" "reference": "b5f95749071c82a8e0f58586987627054400cdf6"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/nikic/FastRoute/zipball/f3dcf5130e634b6123d40727d612ec6aa4f61fb3", "url": "https://api.github.com/repos/nikic/FastRoute/zipball/b5f95749071c82a8e0f58586987627054400cdf6",
"reference": "f3dcf5130e634b6123d40727d612ec6aa4f61fb3", "reference": "b5f95749071c82a8e0f58586987627054400cdf6",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -312,7 +494,7 @@
"router", "router",
"routing" "routing"
], ],
"time": "2016-10-20T17:36:47+00:00" "time": "2017-01-19T11:35:12+00:00"
}, },
{ {
"name": "pimple/pimple", "name": "pimple/pimple",
@ -360,6 +542,55 @@
], ],
"time": "2015-09-11T15:10:35+00:00" "time": "2015-09-11T15:10:35+00:00"
}, },
{
"name": "psr/container",
"version": "1.0.0",
"source": {
"type": "git",
"url": "https://github.com/php-fig/container.git",
"reference": "b7ce3b176482dbbc1245ebf52b181af44c2cf55f"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/php-fig/container/zipball/b7ce3b176482dbbc1245ebf52b181af44c2cf55f",
"reference": "b7ce3b176482dbbc1245ebf52b181af44c2cf55f",
"shasum": ""
},
"require": {
"php": ">=5.3.0"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.0.x-dev"
}
},
"autoload": {
"psr-4": {
"Psr\\Container\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "PHP-FIG",
"homepage": "http://www.php-fig.org/"
}
],
"description": "Common Container Interface (PHP FIG PSR-11)",
"homepage": "https://github.com/php-fig/container",
"keywords": [
"PSR-11",
"container",
"container-interface",
"container-interop",
"psr"
],
"time": "2017-02-14T16:28:37+00:00"
},
{ {
"name": "psr/http-message", "name": "psr/http-message",
"version": "1.0.1", "version": "1.0.1",
@ -446,6 +677,34 @@
"description": "Add ability to chain symfony processes", "description": "Add ability to chain symfony processes",
"time": "2016-04-10T08:33:20+00:00" "time": "2016-04-10T08:33:20+00:00"
}, },
{
"name": "rudloff/rtmpdump-bin",
"version": "2.3",
"source": {
"type": "git",
"url": "https://github.com/Rudloff/rtmpdump-bin.git",
"reference": "133cdd80e3bab66593e88a5276158596383afd97"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/Rudloff/rtmpdump-bin/zipball/133cdd80e3bab66593e88a5276158596383afd97",
"reference": "133cdd80e3bab66593e88a5276158596383afd97",
"shasum": ""
},
"require-dev": {
"rtmpdump/rtmpdump": "2.3"
},
"bin": [
"rtmpdump"
],
"type": "library",
"notification-url": "https://packagist.org/downloads/",
"license": [
"GPL-2.0"
],
"description": "rtmpdump binary for Linux 64 bit",
"time": "2016-04-12T19:17:32+00:00"
},
{ {
"name": "rudloff/smarty-plugin-noscheme", "name": "rudloff/smarty-plugin-noscheme",
"version": "0.1.1", "version": "0.1.1",
@ -612,16 +871,16 @@
}, },
{ {
"name": "symfony/process", "name": "symfony/process",
"version": "v3.2.1", "version": "v3.2.6",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/symfony/process.git", "url": "https://github.com/symfony/process.git",
"reference": "02ea84847aad71be7e32056408bb19f3a616cdd3" "reference": "68bfa8c83f24c0ac04ea7193bcdcda4519f41892"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/symfony/process/zipball/02ea84847aad71be7e32056408bb19f3a616cdd3", "url": "https://api.github.com/repos/symfony/process/zipball/68bfa8c83f24c0ac04ea7193bcdcda4519f41892",
"reference": "02ea84847aad71be7e32056408bb19f3a616cdd3", "reference": "68bfa8c83f24c0ac04ea7193bcdcda4519f41892",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -657,20 +916,20 @@
], ],
"description": "Symfony Process Component", "description": "Symfony Process Component",
"homepage": "https://symfony.com", "homepage": "https://symfony.com",
"time": "2016-11-24T10:40:28+00:00" "time": "2017-03-04T12:23:14+00:00"
}, },
{ {
"name": "symfony/yaml", "name": "symfony/yaml",
"version": "v3.2.1", "version": "v3.2.6",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/symfony/yaml.git", "url": "https://github.com/symfony/yaml.git",
"reference": "a7095af4b97a0955f85c8989106c249fa649011f" "reference": "093e416ad096355149e265ea2e4cc1f9ee40ab1a"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/symfony/yaml/zipball/a7095af4b97a0955f85c8989106c249fa649011f", "url": "https://api.github.com/repos/symfony/yaml/zipball/093e416ad096355149e265ea2e4cc1f9ee40ab1a",
"reference": "a7095af4b97a0955f85c8989106c249fa649011f", "reference": "093e416ad096355149e265ea2e4cc1f9ee40ab1a",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -712,7 +971,7 @@
], ],
"description": "Symfony Yaml Component", "description": "Symfony Yaml Component",
"homepage": "https://symfony.com", "homepage": "https://symfony.com",
"time": "2016-12-10T10:07:06+00:00" "time": "2017-03-07T16:47:02+00:00"
} }
], ],
"packages-dev": [ "packages-dev": [
@ -775,7 +1034,7 @@
"version": "dev-release", "version": "dev-release",
"dist": { "dist": {
"type": "xz", "type": "xz",
"url": "http://johnvansickle.com/ffmpeg/releases/ffmpeg-release-64bit-static.tar.xz", "url": "https://johnvansickle.com/ffmpeg/releases/ffmpeg-release-64bit-static.tar.xz",
"reference": null, "reference": null,
"shasum": null "shasum": null
}, },
@ -786,16 +1045,16 @@
}, },
{ {
"name": "heroku/heroku-buildpack-php", "name": "heroku/heroku-buildpack-php",
"version": "v117", "version": "v120",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/heroku/heroku-buildpack-php.git", "url": "https://github.com/heroku/heroku-buildpack-php.git",
"reference": "960199a978308c75926fd9bb4775f7113bf1d777" "reference": "e0499a7fdffd56f46534a037a6c48d65cef4e645"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/heroku/heroku-buildpack-php/zipball/960199a978308c75926fd9bb4775f7113bf1d777", "url": "https://api.github.com/repos/heroku/heroku-buildpack-php/zipball/e0499a7fdffd56f46534a037a6c48d65cef4e645",
"reference": "960199a978308c75926fd9bb4775f7113bf1d777", "reference": "e0499a7fdffd56f46534a037a6c48d65cef4e645",
"shasum": "" "shasum": ""
}, },
"bin": [ "bin": [
@ -826,20 +1085,20 @@
"nginx", "nginx",
"php" "php"
], ],
"time": "2016-12-09T19:37:38+00:00" "time": "2017-02-20T15:05:49+00:00"
}, },
{ {
"name": "myclabs/deep-copy", "name": "myclabs/deep-copy",
"version": "1.5.5", "version": "1.6.0",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/myclabs/DeepCopy.git", "url": "https://github.com/myclabs/DeepCopy.git",
"reference": "399c1f9781e222f6eb6cc238796f5200d1b7f108" "reference": "5a5a9fc8025a08d8919be87d6884d5a92520cefe"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/399c1f9781e222f6eb6cc238796f5200d1b7f108", "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/5a5a9fc8025a08d8919be87d6884d5a92520cefe",
"reference": "399c1f9781e222f6eb6cc238796f5200d1b7f108", "reference": "5a5a9fc8025a08d8919be87d6884d5a92520cefe",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -868,7 +1127,7 @@
"object", "object",
"object graph" "object graph"
], ],
"time": "2016-10-31T17:19:45+00:00" "time": "2017-01-26T22:05:40+00:00"
}, },
{ {
"name": "phpdocumentor/reflection-common", "name": "phpdocumentor/reflection-common",
@ -1018,27 +1277,27 @@
}, },
{ {
"name": "phpspec/prophecy", "name": "phpspec/prophecy",
"version": "v1.6.2", "version": "v1.7.0",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/phpspec/prophecy.git", "url": "https://github.com/phpspec/prophecy.git",
"reference": "6c52c2722f8460122f96f86346600e1077ce22cb" "reference": "93d39f1f7f9326d746203c7c056f300f7f126073"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/phpspec/prophecy/zipball/6c52c2722f8460122f96f86346600e1077ce22cb", "url": "https://api.github.com/repos/phpspec/prophecy/zipball/93d39f1f7f9326d746203c7c056f300f7f126073",
"reference": "6c52c2722f8460122f96f86346600e1077ce22cb", "reference": "93d39f1f7f9326d746203c7c056f300f7f126073",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
"doctrine/instantiator": "^1.0.2", "doctrine/instantiator": "^1.0.2",
"php": "^5.3|^7.0", "php": "^5.3|^7.0",
"phpdocumentor/reflection-docblock": "^2.0|^3.0.2", "phpdocumentor/reflection-docblock": "^2.0|^3.0.2",
"sebastian/comparator": "^1.1", "sebastian/comparator": "^1.1|^2.0",
"sebastian/recursion-context": "^1.0|^2.0" "sebastian/recursion-context": "^1.0|^2.0|^3.0"
}, },
"require-dev": { "require-dev": {
"phpspec/phpspec": "^2.0", "phpspec/phpspec": "^2.5|^3.2",
"phpunit/phpunit": "^4.8 || ^5.6.5" "phpunit/phpunit": "^4.8 || ^5.6.5"
}, },
"type": "library", "type": "library",
@ -1077,39 +1336,39 @@
"spy", "spy",
"stub" "stub"
], ],
"time": "2016-11-21T14:58:47+00:00" "time": "2017-03-02T20:05:34+00:00"
}, },
{ {
"name": "phpunit/php-code-coverage", "name": "phpunit/php-code-coverage",
"version": "4.0.4", "version": "4.0.7",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/sebastianbergmann/php-code-coverage.git", "url": "https://github.com/sebastianbergmann/php-code-coverage.git",
"reference": "c14196e64a78570034afd0b7a9f3757ba71c2a0a" "reference": "09e2277d14ea467e5a984010f501343ef29ffc69"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/c14196e64a78570034afd0b7a9f3757ba71c2a0a", "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/09e2277d14ea467e5a984010f501343ef29ffc69",
"reference": "c14196e64a78570034afd0b7a9f3757ba71c2a0a", "reference": "09e2277d14ea467e5a984010f501343ef29ffc69",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
"ext-dom": "*",
"ext-xmlwriter": "*",
"php": "^5.6 || ^7.0", "php": "^5.6 || ^7.0",
"phpunit/php-file-iterator": "~1.3", "phpunit/php-file-iterator": "^1.3",
"phpunit/php-text-template": "~1.2", "phpunit/php-text-template": "^1.2",
"phpunit/php-token-stream": "^1.4.2", "phpunit/php-token-stream": "^1.4.2 || ^2.0",
"sebastian/code-unit-reverse-lookup": "~1.0", "sebastian/code-unit-reverse-lookup": "^1.0",
"sebastian/environment": "^1.3.2 || ^2.0", "sebastian/environment": "^1.3.2 || ^2.0",
"sebastian/version": "~1.0|~2.0" "sebastian/version": "^1.0 || ^2.0"
}, },
"require-dev": { "require-dev": {
"ext-xdebug": ">=2.1.4", "ext-xdebug": "^2.1.4",
"phpunit/phpunit": "^5.4" "phpunit/phpunit": "^5.7"
}, },
"suggest": { "suggest": {
"ext-dom": "*", "ext-xdebug": "^2.5.1"
"ext-xdebug": ">=2.4.0",
"ext-xmlwriter": "*"
}, },
"type": "library", "type": "library",
"extra": { "extra": {
@ -1140,7 +1399,7 @@
"testing", "testing",
"xunit" "xunit"
], ],
"time": "2016-12-20T15:22:42+00:00" "time": "2017-03-01T09:12:17+00:00"
}, },
{ {
"name": "phpunit/php-file-iterator", "name": "phpunit/php-file-iterator",
@ -1232,25 +1491,30 @@
}, },
{ {
"name": "phpunit/php-timer", "name": "phpunit/php-timer",
"version": "1.0.8", "version": "1.0.9",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/sebastianbergmann/php-timer.git", "url": "https://github.com/sebastianbergmann/php-timer.git",
"reference": "38e9124049cf1a164f1e4537caf19c99bf1eb260" "reference": "3dcf38ca72b158baf0bc245e9184d3fdffa9c46f"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/38e9124049cf1a164f1e4537caf19c99bf1eb260", "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/3dcf38ca72b158baf0bc245e9184d3fdffa9c46f",
"reference": "38e9124049cf1a164f1e4537caf19c99bf1eb260", "reference": "3dcf38ca72b158baf0bc245e9184d3fdffa9c46f",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
"php": ">=5.3.3" "php": "^5.3.3 || ^7.0"
}, },
"require-dev": { "require-dev": {
"phpunit/phpunit": "~4|~5" "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.0"
}, },
"type": "library", "type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.0-dev"
}
},
"autoload": { "autoload": {
"classmap": [ "classmap": [
"src/" "src/"
@ -1272,20 +1536,20 @@
"keywords": [ "keywords": [
"timer" "timer"
], ],
"time": "2016-05-12T18:03:57+00:00" "time": "2017-02-26T11:10:40+00:00"
}, },
{ {
"name": "phpunit/php-token-stream", "name": "phpunit/php-token-stream",
"version": "1.4.9", "version": "1.4.11",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/sebastianbergmann/php-token-stream.git", "url": "https://github.com/sebastianbergmann/php-token-stream.git",
"reference": "3b402f65a4cc90abf6e1104e388b896ce209631b" "reference": "e03f8f67534427a787e21a385a67ec3ca6978ea7"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/3b402f65a4cc90abf6e1104e388b896ce209631b", "url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/e03f8f67534427a787e21a385a67ec3ca6978ea7",
"reference": "3b402f65a4cc90abf6e1104e388b896ce209631b", "reference": "e03f8f67534427a787e21a385a67ec3ca6978ea7",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -1321,20 +1585,20 @@
"keywords": [ "keywords": [
"tokenizer" "tokenizer"
], ],
"time": "2016-11-15T14:06:22+00:00" "time": "2017-02-27T10:12:30+00:00"
}, },
{ {
"name": "phpunit/phpunit", "name": "phpunit/phpunit",
"version": "5.7.5", "version": "5.7.16",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/sebastianbergmann/phpunit.git", "url": "https://github.com/sebastianbergmann/phpunit.git",
"reference": "50fd2be8f3e23e91da825f36f08e5f9633076ffe" "reference": "dafc78e2a7d12139b0e97078d1082326bd09363d"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/50fd2be8f3e23e91da825f36f08e5f9633076ffe", "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/dafc78e2a7d12139b0e97078d1082326bd09363d",
"reference": "50fd2be8f3e23e91da825f36f08e5f9633076ffe", "reference": "dafc78e2a7d12139b0e97078d1082326bd09363d",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -1346,19 +1610,19 @@
"myclabs/deep-copy": "~1.3", "myclabs/deep-copy": "~1.3",
"php": "^5.6 || ^7.0", "php": "^5.6 || ^7.0",
"phpspec/prophecy": "^1.6.2", "phpspec/prophecy": "^1.6.2",
"phpunit/php-code-coverage": "^4.0.3", "phpunit/php-code-coverage": "^4.0.4",
"phpunit/php-file-iterator": "~1.4", "phpunit/php-file-iterator": "~1.4",
"phpunit/php-text-template": "~1.2", "phpunit/php-text-template": "~1.2",
"phpunit/php-timer": "^1.0.6", "phpunit/php-timer": "^1.0.6",
"phpunit/phpunit-mock-objects": "^3.2", "phpunit/phpunit-mock-objects": "^3.2",
"sebastian/comparator": "~1.2.2", "sebastian/comparator": "^1.2.4",
"sebastian/diff": "~1.2", "sebastian/diff": "~1.2",
"sebastian/environment": "^1.3.4 || ^2.0", "sebastian/environment": "^1.3.4 || ^2.0",
"sebastian/exporter": "~2.0", "sebastian/exporter": "~2.0",
"sebastian/global-state": "^1.0 || ^2.0", "sebastian/global-state": "^1.1",
"sebastian/object-enumerator": "~2.0", "sebastian/object-enumerator": "~2.0",
"sebastian/resource-operations": "~1.0", "sebastian/resource-operations": "~1.0",
"sebastian/version": "~1.0|~2.0", "sebastian/version": "~1.0.3|~2.0",
"symfony/yaml": "~2.1|~3.0" "symfony/yaml": "~2.1|~3.0"
}, },
"conflict": { "conflict": {
@ -1403,7 +1667,7 @@
"testing", "testing",
"xunit" "xunit"
], ],
"time": "2016-12-28T07:18:51+00:00" "time": "2017-03-15T13:02:34+00:00"
}, },
{ {
"name": "phpunit/phpunit-mock-objects", "name": "phpunit/phpunit-mock-objects",
@ -1466,62 +1730,34 @@
}, },
{ {
"name": "rg3/youtube-dl", "name": "rg3/youtube-dl",
"version": "2017.01.10", "version": "2017.03.07",
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://github.com/rg3/youtube-dl/archive/2017.01.10.zip", "url": "https://github.com/rg3/youtube-dl/archive/2017.03.07.zip",
"reference": null, "reference": null,
"shasum": null "shasum": null
}, },
"type": "library" "type": "library"
}, },
{
"name": "rudloff/rtmpdump-bin",
"version": "2.3",
"source": {
"type": "git",
"url": "https://github.com/Rudloff/rtmpdump-bin.git",
"reference": "133cdd80e3bab66593e88a5276158596383afd97"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/Rudloff/rtmpdump-bin/zipball/133cdd80e3bab66593e88a5276158596383afd97",
"reference": "133cdd80e3bab66593e88a5276158596383afd97",
"shasum": ""
},
"require-dev": {
"rtmpdump/rtmpdump": "2.3"
},
"bin": [
"rtmpdump"
],
"type": "library",
"notification-url": "https://packagist.org/downloads/",
"license": [
"GPL-2.0"
],
"description": "rtmpdump binary for Linux 64 bit",
"time": "2016-04-12T19:17:32+00:00"
},
{ {
"name": "sebastian/code-unit-reverse-lookup", "name": "sebastian/code-unit-reverse-lookup",
"version": "1.0.0", "version": "1.0.1",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/sebastianbergmann/code-unit-reverse-lookup.git", "url": "https://github.com/sebastianbergmann/code-unit-reverse-lookup.git",
"reference": "c36f5e7cfce482fde5bf8d10d41a53591e0198fe" "reference": "4419fcdb5eabb9caa61a27c7a1db532a6b55dd18"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/code-unit-reverse-lookup/zipball/c36f5e7cfce482fde5bf8d10d41a53591e0198fe", "url": "https://api.github.com/repos/sebastianbergmann/code-unit-reverse-lookup/zipball/4419fcdb5eabb9caa61a27c7a1db532a6b55dd18",
"reference": "c36f5e7cfce482fde5bf8d10d41a53591e0198fe", "reference": "4419fcdb5eabb9caa61a27c7a1db532a6b55dd18",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
"php": ">=5.6" "php": "^5.6 || ^7.0"
}, },
"require-dev": { "require-dev": {
"phpunit/phpunit": "~5" "phpunit/phpunit": "^5.7 || ^6.0"
}, },
"type": "library", "type": "library",
"extra": { "extra": {
@ -1546,20 +1782,20 @@
], ],
"description": "Looks up which function or method a line of code belongs to", "description": "Looks up which function or method a line of code belongs to",
"homepage": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/", "homepage": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/",
"time": "2016-02-13T06:45:14+00:00" "time": "2017-03-04T06:30:41+00:00"
}, },
{ {
"name": "sebastian/comparator", "name": "sebastian/comparator",
"version": "1.2.2", "version": "1.2.4",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/sebastianbergmann/comparator.git", "url": "https://github.com/sebastianbergmann/comparator.git",
"reference": "6a1ed12e8b2409076ab22e3897126211ff8b1f7f" "reference": "2b7424b55f5047b47ac6e5ccb20b2aea4011d9be"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/6a1ed12e8b2409076ab22e3897126211ff8b1f7f", "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/2b7424b55f5047b47ac6e5ccb20b2aea4011d9be",
"reference": "6a1ed12e8b2409076ab22e3897126211ff8b1f7f", "reference": "2b7424b55f5047b47ac6e5ccb20b2aea4011d9be",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -1610,7 +1846,7 @@
"compare", "compare",
"equality" "equality"
], ],
"time": "2016-11-19T09:18:40+00:00" "time": "2017-01-29T09:50:25+00:00"
}, },
{ {
"name": "sebastian/diff", "name": "sebastian/diff",
@ -1834,16 +2070,16 @@
}, },
{ {
"name": "sebastian/object-enumerator", "name": "sebastian/object-enumerator",
"version": "2.0.0", "version": "2.0.1",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/sebastianbergmann/object-enumerator.git", "url": "https://github.com/sebastianbergmann/object-enumerator.git",
"reference": "96f8a3f257b69e8128ad74d3a7fd464bcbaa3b35" "reference": "1311872ac850040a79c3c058bea3e22d0f09cbb7"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/96f8a3f257b69e8128ad74d3a7fd464bcbaa3b35", "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/1311872ac850040a79c3c058bea3e22d0f09cbb7",
"reference": "96f8a3f257b69e8128ad74d3a7fd464bcbaa3b35", "reference": "1311872ac850040a79c3c058bea3e22d0f09cbb7",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -1876,7 +2112,7 @@
], ],
"description": "Traverses array structures and object graphs to enumerate all referenced objects", "description": "Traverses array structures and object graphs to enumerate all referenced objects",
"homepage": "https://github.com/sebastianbergmann/object-enumerator/", "homepage": "https://github.com/sebastianbergmann/object-enumerator/",
"time": "2016-11-19T07:35:10+00:00" "time": "2017-02-18T15:18:39+00:00"
}, },
{ {
"name": "sebastian/recursion-context", "name": "sebastian/recursion-context",
@ -2155,22 +2391,25 @@
}, },
{ {
"name": "symfony/var-dumper", "name": "symfony/var-dumper",
"version": "v3.2.1", "version": "v3.2.6",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/symfony/var-dumper.git", "url": "https://github.com/symfony/var-dumper.git",
"reference": "f722532b0966e9b6fc631e682143c07b2cf583a0" "reference": "4100f347aff890bc16b0b4b42843b599db257b2d"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/symfony/var-dumper/zipball/f722532b0966e9b6fc631e682143c07b2cf583a0", "url": "https://api.github.com/repos/symfony/var-dumper/zipball/4100f347aff890bc16b0b4b42843b599db257b2d",
"reference": "f722532b0966e9b6fc631e682143c07b2cf583a0", "reference": "4100f347aff890bc16b0b4b42843b599db257b2d",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
"php": ">=5.5.9", "php": ">=5.5.9",
"symfony/polyfill-mbstring": "~1.0" "symfony/polyfill-mbstring": "~1.0"
}, },
"conflict": {
"phpunit/phpunit": "<4.8.35|<5.4.3,>=5.0"
},
"require-dev": { "require-dev": {
"twig/twig": "~1.20|~2.0" "twig/twig": "~1.20|~2.0"
}, },
@ -2214,7 +2453,7 @@
"debug", "debug",
"dump" "dump"
], ],
"time": "2016-12-11T14:34:22+00:00" "time": "2017-02-20T13:45:48+00:00"
}, },
{ {
"name": "webmozart/assert", "name": "webmozart/assert",

View file

@ -3,7 +3,6 @@ python: /usr/bin/python
params: params:
- --no-playlist - --no-playlist
- --no-warnings - --no-warnings
- -f best[protocol^=http]
- --playlist-end - --playlist-end
- 1 - 1
curl_params: curl_params:
@ -12,3 +11,4 @@ avconv: vendor/bin/ffmpeg
rtmpdump: vendor/bin/rtmpdump rtmpdump: vendor/bin/rtmpdump
curl: /usr/bin/curl curl: /usr/bin/curl
uglyUrls: false uglyUrls: false
stream: false

View file

@ -54,6 +54,13 @@ class FrontController
*/ */
private $view; private $view;
/**
* Default youtube-dl format.
*
* @var string
*/
private $defaultFormat = 'best[protocol^=http]';
/** /**
* FrontController constructor. * FrontController constructor.
* *
@ -68,6 +75,9 @@ class FrontController
$session_factory = new \Aura\Session\SessionFactory(); $session_factory = new \Aura\Session\SessionFactory();
$session = $session_factory->newInstance($_COOKIE); $session = $session_factory->newInstance($_COOKIE);
$this->sessionSegment = $session->getSegment('Alltube\Controller\FrontController'); $this->sessionSegment = $session->getSegment('Alltube\Controller\FrontController');
if ($this->config->stream) {
$this->defaultFormat = 'best';
}
} }
/** /**
@ -76,10 +86,11 @@ class FrontController
* @param Request $request PSR-7 request * @param Request $request PSR-7 request
* @param Response $response PSR-7 response * @param Response $response PSR-7 response
* *
* @return void * @return Response HTTP response
*/ */
public function index(Request $request, Response $response) public function index(Request $request, Response $response)
{ {
$uri = $request->getUri();
$this->view->render( $this->view->render(
$response, $response,
'index.tpl', 'index.tpl',
@ -88,8 +99,12 @@ class FrontController
'uglyUrls' => $this->config->uglyUrls, 'uglyUrls' => $this->config->uglyUrls,
'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.',
'domain' => $uri->getScheme().'://'.$uri->getAuthority(),
'canonical' => $this->getCanonicalUrl($request),
] ]
); );
return $response;
} }
/** /**
@ -98,7 +113,7 @@ class FrontController
* @param Request $request PSR-7 request * @param Request $request PSR-7 request
* @param Response $response PSR-7 response * @param Response $response PSR-7 response
* *
* @return void * @return Response HTTP response
*/ */
public function extractors(Request $request, Response $response) public function extractors(Request $request, Response $response)
{ {
@ -111,8 +126,11 @@ class FrontController
'title' => 'Supported websites', 'title' => 'Supported websites',
'description' => 'List of all supported websites from which Alltube Download '. 'description' => 'List of all supported websites from which Alltube Download '.
'can extract video or audio files', 'can extract video or audio files',
'canonical' => $this->getCanonicalUrl($request),
] ]
); );
return $response;
} }
/** /**
@ -132,8 +150,89 @@ class FrontController
'class' => 'password', 'class' => 'password',
'title' => 'Password prompt', 'title' => 'Password prompt',
'description' => 'You need a password in order to download this video with Alltube Download', 'description' => 'You need a password in order to download this video with Alltube Download',
'canonical' => $this->getCanonicalUrl($request),
] ]
); );
return $response;
}
/**
* Return the converted MP3 file.
*
* @param Request $request PSR-7 request
* @param Response $response PSR-7 response
* @param array $params GET query parameters
* @param string $password Video password
*
* @return Response HTTP response
*/
private function getAudioResponse(Request $request, Response $response, array $params, $password = null)
{
try {
if ($this->config->stream) {
return $this->getStream($params['url'], 'mp3', $response, $request, $password);
} else {
$url = $this->download->getURL($params['url'], 'mp3[protocol^=http]', $password);
return $response->withRedirect($url);
}
} catch (PasswordException $e) {
return $this->password($request, $response);
} catch (\Exception $e) {
$response = $response->withHeader(
'Content-Disposition',
'attachment; filename="'.
$this->download->getAudioFilename($params['url'], 'bestaudio/best', $password).'"'
);
$response = $response->withHeader('Content-Type', 'audio/mpeg');
if ($request->isGet() || $request->isPost()) {
$process = $this->download->getAudioStream($params['url'], 'bestaudio/best', $password);
$response = $response->withBody(new Stream($process));
}
return $response;
}
}
/**
* Return the video description page.
*
* @param Request $request PSR-7 request
* @param Response $response PSR-7 response
* @param array $params GET query parameters
* @param string $password Video password
*
* @return Response HTTP response
*/
private function getVideoResponse(Request $request, Response $response, array $params, $password = null)
{
try {
$video = $this->download->getJSON($params['url'], $this->defaultFormat, $password);
} catch (PasswordException $e) {
return $this->password($request, $response);
}
if ($this->config->stream) {
$protocol = '';
} else {
$protocol = '[protocol^=http]';
}
$this->view->render(
$response,
'video.tpl',
[
'video' => $video,
'class' => 'video',
'title' => $video->title,
'description' => 'Download "'.$video->title.'" from '.$video->extractor_key,
'protocol' => $protocol,
'config' => $this->config,
'canonical' => $this->getCanonicalUrl($request),
]
);
return $response;
} }
/** /**
@ -153,43 +252,9 @@ class FrontController
$this->sessionSegment->setFlash($params['url'], $password); $this->sessionSegment->setFlash($params['url'], $password);
} }
if (isset($params['audio'])) { if (isset($params['audio'])) {
try { return $this->getAudioResponse($request, $response, $params, $password);
$url = $this->download->getURL($params['url'], 'mp3[protocol^=http]', $password);
return $response->withRedirect($url);
} catch (PasswordException $e) {
return $this->password($request, $response);
} catch (\Exception $e) {
$response = $response->withHeader(
'Content-Disposition',
'attachment; filename="'.
$this->download->getAudioFilename($params['url'], 'bestaudio/best', $password).'"'
);
$response = $response->withHeader('Content-Type', 'audio/mpeg');
if ($request->isGet() || $request->isPost()) {
$process = $this->download->getAudioStream($params['url'], 'bestaudio/best', $password);
$response = $response->withBody(new Stream($process));
}
return $response;
}
} else { } else {
try { return $this->getVideoResponse($request, $response, $params, $password);
$video = $this->download->getJSON($params['url'], null, $password);
} catch (PasswordException $e) {
return $this->password($request, $response);
}
$this->view->render(
$response,
'video.tpl',
[
'video' => $video,
'class' => 'video',
'title' => $video->title,
'description' => 'Download "'.$video->title.'" from '.$video->extractor_key,
]
);
} }
} else { } else {
return $response->withRedirect($this->container->get('router')->pathFor('index')); return $response->withRedirect($this->container->get('router')->pathFor('index'));
@ -214,12 +279,47 @@ class FrontController
'errors' => $exception->getMessage(), 'errors' => $exception->getMessage(),
'class' => 'video', 'class' => 'video',
'title' => 'Error', 'title' => 'Error',
'canonical' => $this->getCanonicalUrl($request),
] ]
); );
return $response->withStatus(500); return $response->withStatus(500);
} }
/**
* Get a video/audio stream piped through the server.
*
* @param string $url URL of the video
* @param string $format Requested format
* @param Response $response PSR-7 response
* @param Request $request PSR-7 request
* @param string $password Video password
*
* @return Response HTTP response
*/
private function getStream($url, $format, $response, $request, $password = null)
{
$video = $this->download->getJSON($url, $format, $password);
if ($video->protocol == 'm3u8') {
$stream = $this->download->getM3uStream($video);
$response = $response->withHeader('Content-Type', 'video/'.$video->ext);
if ($request->isGet()) {
$response = $response->withBody(new Stream($stream));
}
} else {
$client = new \GuzzleHttp\Client();
$stream = $client->request('GET', $video->url, ['stream' => true]);
$response = $response->withHeader('Content-Type', $stream->getHeader('Content-Type'));
$response = $response->withHeader('Content-Length', $stream->getHeader('Content-Length'));
if ($request->isGet()) {
$response = $response->withBody($stream->getBody());
}
}
$response = $response->withHeader('Content-Disposition', 'attachment; filename="'.$video->_filename.'"');
return $response;
}
/** /**
* Redirect to video file. * Redirect to video file.
* *
@ -231,15 +331,30 @@ 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['format'])) {
$format = $params['format'];
} else {
$format = $this->defaultFormat;
}
if (isset($params['url'])) { if (isset($params['url'])) {
try { try {
if ($this->config->stream) {
return $this->getStream(
$params['url'],
$format,
$response,
$request,
$this->sessionSegment->getFlash($params['url'])
);
} else {
$url = $this->download->getURL( $url = $this->download->getURL(
$params['url'], $params['url'],
$request->getParam('format'), $format,
$this->sessionSegment->getFlash($params['url']) $this->sessionSegment->getFlash($params['url'])
); );
return $response->withRedirect($url); return $response->withRedirect($url);
}
} catch (PasswordException $e) { } catch (PasswordException $e) {
return $response->withRedirect( return $response->withRedirect(
$this->container->get('router')->pathFor('video').'?url='.urlencode($params['url']) $this->container->get('router')->pathFor('video').'?url='.urlencode($params['url'])
@ -247,32 +362,35 @@ class FrontController
} 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')->withStatus(500);
} }
} else {
return $response->withRedirect($this->container->get('router')->pathFor('index'));
} }
} }
/** /**
* Output JSON info about the video. * Generate the canonical URL of the current page.
* *
* @param Request $request PSR-7 request * @param Request $request PSR-7 Request
* @param Response $response PSR-7 response
* *
* @return Response HTTP response * @return string URL
*/ */
public function json(Request $request, Response $response) private function getCanonicalUrl(Request $request)
{ {
$params = $request->getQueryParams(); $uri = $request->getUri();
if (isset($params['url'])) { $return = 'https://alltubedownload.net/';
try {
$video = $this->download->getJSON($params['url']);
return $response->withJson($video); $path = $uri->getPath();
} catch (\Exception $e) { if ($path != '/') {
return $response->withJson( $return .= $path;
['success' => false, 'error' => $e->getMessage()]
);
} }
$query = $uri->getQuery();
if (!empty($query)) {
$return .= '?'.$query;
} }
return $return;
} }
} }

View file

@ -48,8 +48,4 @@ $app->get(
'/redirect', '/redirect',
[$controller, 'redirect'] [$controller, 'redirect']
)->setName('redirect'); )->setName('redirect');
$app->get(
'/json',
[$controller, 'json']
);
$app->run(); $app->run();

View file

@ -1,17 +1,17 @@
{ {
"name": "alltube", "name": "alltube",
"description": "HTML GUI for youtube-dl", "description": "HTML GUI for youtube-dl",
"version": "0.7.2-beta", "version": "0.7.2-beta2",
"author": "Pierre Rudloff", "author": "Pierre Rudloff",
"bugs": "https://github.com/Rudloff/alltube/issues", "bugs": "https://github.com/Rudloff/alltube/issues",
"dependencies": { "dependencies": {
"bower": "~1.8.0", "bower": "~1.8.0",
"grunt": "~1.0.1", "grunt": "~1.0.1",
"grunt-contrib-cssmin": "~1.0.0", "grunt-contrib-cssmin": "~2.0.0",
"grunt-contrib-uglify": "~2.0.0" "grunt-contrib-uglify": "~2.2.0"
}, },
"devDependencies": { "devDependencies": {
"grunt-contrib-compress": "~1.3.0", "grunt-contrib-compress": "~1.4.1",
"grunt-contrib-watch": "~1.0.0", "grunt-contrib-watch": "~1.0.0",
"grunt-fixpack": "~0.1.0", "grunt-fixpack": "~0.1.0",
"grunt-githash": "~0.1.3", "grunt-githash": "~0.1.3",
@ -27,7 +27,7 @@
"homepage": "https://www.alltubedownload.net/", "homepage": "https://www.alltubedownload.net/",
"keywords": [ "keywords": [
"alltube", "alltube",
"dowload", "download",
"video", "video",
"youtube" "youtube"
], ],

View file

@ -1,7 +1,8 @@
<phpunit bootstrap="vendor/autoload.php"> <phpunit bootstrap="tests/bootstrap.php">
<filter> <filter>
<whitelist> <whitelist>
<directory>classes/</directory> <directory>classes/</directory>
<directory>controllers/</directory>
</whitelist> </whitelist>
</filter> </filter>
<testsuites> <testsuites>

View file

@ -10,7 +10,7 @@
{/if} {/if}
<link rel="stylesheet" href="{base_url|noscheme}/dist/main.css" /> <link rel="stylesheet" href="{base_url|noscheme}/dist/main.css" />
<title>AllTube Download{if isset($title)} - {$title|escape}{/if}</title> <title>AllTube Download{if isset($title)} - {$title|escape}{/if}</title>
<link rel="canonical" href="//{$smarty.server.HTTP_HOST|cat:$smarty.server.REQUEST_URI|replace:{base_url|noscheme}:'http://www.alltubedownload.net'}" /> <link rel="canonical" href="{$canonical}" />
<link rel="icon" href="{base_url|noscheme}/img/favicon.png" /> <link rel="icon" href="{base_url|noscheme}/img/favicon.png" />
<meta property="og:title" content="AllTube Download{if isset($title)} - {$title|escape}{/if}" /> <meta property="og:title" content="AllTube Download{if isset($title)} - {$title|escape}{/if}" />
<meta property="og:image" content="{base_url}/img/logo.png" /> <meta property="og:image" content="{base_url}/img/logo.png" />

View file

@ -12,7 +12,7 @@
<input class="URLinput" type="url" name="url" id="url" <input class="URLinput" type="url" name="url" id="url"
required autofocus placeholder="http://example.com/video" /> required autofocus placeholder="http://example.com/video" />
</span> </span>
{if uglyUrls} {if $uglyUrls}
<input type="hidden" name="page" value="video" /> <input type="hidden" name="page" value="video" />
{/if} {/if}
<input class="downloadBtn" type="submit" value="Download" /><br/> <input class="downloadBtn" type="submit" value="Download" /><br/>
@ -28,7 +28,7 @@
<a class="combatiblelink" href="{path_for name="extractors"}">See all supported websites</a> <a class="combatiblelink" href="{path_for name="extractors"}">See all supported websites</a>
<div id="bookmarklet" class="bookmarklet_wrapper"> <div id="bookmarklet" class="bookmarklet_wrapper">
<p> Drag this to your bookmarks bar: </p> <p> Drag this to your bookmarks bar: </p>
<a class="bookmarklet" href="javascript:window.location='{base_url|noscheme}{path_for name='video'}?url='+encodeURIComponent(location.href);">Bookmarklet</a> <a class="bookmarklet" href="javascript:window.location='{$domain}{path_for name='video'}?url='+encodeURIComponent(location.href);">Bookmarklet</a>
</div> </div>
</div> </div>

View file

@ -29,18 +29,18 @@
{/if} {/if}
<select name="format" id="format" class="formats monospace"> <select name="format" id="format" class="formats monospace">
<optgroup label="Generic formats"> <optgroup label="Generic formats">
<option value="best[protocol^=http]"> <option value="best{$protocol}">
{strip} {strip}
Best ({$video->ext}) Best ({$video->ext})
{/strip} {/strip}
</option> </option>
<option value="worst[protocol^=http]"> <option value="worst{$protocol}">
Worst Worst
</option> </option>
</optgroup> </optgroup>
<optgroup label="Detailed formats" class="monospace"> <optgroup label="Detailed formats" class="monospace">
{foreach $video->formats as $format} {foreach $video->formats as $format}
{if $format->protocol|in_array:array('http', 'https')} {if $config->stream || $format->protocol|in_array:array('http', 'https')}
{strip} {strip}
<option value="{$format->format_id}"> <option value="{$format->format_id}">
{$format->ext} {$format->ext}
@ -80,7 +80,7 @@
<input class="downloadBtn" type="submit" value="Download" /><br/> <input class="downloadBtn" type="submit" value="Download" /><br/>
</form> </form>
{else} {else}
<input type="hidden" name="format" value="best[protocol^=http]" /> <input type="hidden" name="format" value="best{$protocol}" />
<a class="downloadBtn" <a class="downloadBtn"
href="{$video->url|escape}">Download</a><br/> href="{$video->url|escape}">Download</a><br/>
{/if} {/if}

View file

@ -0,0 +1,370 @@
<?php
/**
* FrontControllerTest class.
*/
namespace Alltube\Test;
use Alltube\Config;
use Alltube\Controller\FrontController;
use Slim\Container;
use Slim\Http\Environment;
use Slim\Http\Request;
use Slim\Http\Response;
/**
* Unit tests for the FrontController class.
*/
class FrontControllerTest extends \PHPUnit_Framework_TestCase
{
/**
* Slim dependency container.
*
* @var Container
*/
private $container;
/**
* Mock HTTP request.
*
* @var Request
*/
private $request;
/**
* Mock HTTP response.
*
* @var Response
*/
private $response;
/**
* FrontController instance used in tests.
*
* @var FrontController
*/
private $controller;
/**
* Prepare tests.
*/
protected function setUp()
{
$this->container = new Container();
$this->request = Request::createFromEnvironment(Environment::mock());
$this->response = new Response();
$this->container['view'] = function ($c) {
$view = new \Slim\Views\Smarty(__DIR__.'/../templates/');
$smartyPlugins = new \Slim\Views\SmartyPlugins($c['router'], $this->request->getUri());
$view->registerPlugin('function', 'path_for', [$smartyPlugins, 'pathFor']);
$view->registerPlugin('function', 'base_url', [$smartyPlugins, 'baseUrl']);
$view->registerPlugin('modifier', 'noscheme', 'Smarty_Modifier_noscheme');
return $view;
};
$this->controller = new FrontController($this->container);
$this->container['router']->map(['GET'], '/', [$this->controller, 'index'])
->setName('index');
$this->container['router']->map(['GET'], '/video', [$this->controller, 'video'])
->setName('video');
$this->container['router']->map(['GET'], '/extractors', [$this->controller, 'extractors'])
->setName('extractors');
$this->container['router']->map(['GET'], '/redirect', [$this->controller, 'redirect'])
->setName('redirect');
}
/**
* Destroy properties after test.
*/
protected function tearDown()
{
Config::destroyInstance();
}
/**
* Test the constructor with streams enabled.
*
* @return void
*/
public function testConstructorWithStream()
{
$config = Config::getInstance();
$config->stream = true;
$controller = new FrontController($this->container);
$this->assertInstanceOf(FrontController::class, $controller);
}
/**
* Test the index() function.
*
* @return void
*/
public function testIndex()
{
$result = $this->controller->index($this->request, $this->response);
$this->assertTrue($result->isOk());
}
/**
* Test the index() function with a custom URI.
*
* @return void
*/
public function testIndexWithCustomUri()
{
$result = $this->controller->index(
Request::createFromEnvironment(
Environment::mock(['REQUEST_URI'=>'/foo', 'QUERY_STRING'=>'foo=bar'])
),
$this->response
);
$this->assertTrue($result->isOk());
}
/**
* Test the extractors() function.
*
* @return void
*/
public function testExtractors()
{
$result = $this->controller->extractors($this->request, $this->response);
$this->assertTrue($result->isOk());
}
/**
* Test the password() function.
*
* @return void
*/
public function testPassword()
{
$result = $this->controller->password($this->request, $this->response);
$this->assertTrue($result->isOk());
}
/**
* Test the video() function without the url parameter.
*
* @return void
*/
public function testVideoWithoutUrl()
{
$result = $this->controller->video($this->request, $this->response);
$this->assertTrue($result->isRedirect());
}
/**
* Test the video() function.
*
* @return void
*/
public function testVideo()
{
$result = $this->controller->video(
$this->request->withQueryParams(['url'=>'https://www.youtube.com/watch?v=M7IpKCZ47pU']),
$this->response
);
$this->assertTrue($result->isOk());
}
/**
* Test the video() function with audio conversion.
*
* @return void
*/
public function testVideoWithAudio()
{
$result = $this->controller->video(
$this->request->withQueryParams(['url'=>'https://www.youtube.com/watch?v=M7IpKCZ47pU', 'audio'=>true]),
$this->response
);
$this->assertTrue($result->isOk());
}
/**
* Test the video() function with audio enabled and an URL that doesn't need to be converted.
*
* @return void
*/
public function testVideoWithUnconvertedAudio()
{
$result = $this->controller->video(
$this->request->withQueryParams(
['url' => 'https://soundcloud.com/verwandlungskuenstler/metamorphosis-by-franz-kafka-1',
'audio'=> true, ]
),
$this->response
);
$this->assertTrue($result->isRedirect());
}
/**
* Test the video() function with a password.
*
* @return void
*/
public function testVideoWithPassword()
{
$result = $this->controller->video(
$this->request->withQueryParams(['url'=>'http://vimeo.com/68375962'])
->withParsedBody(['password'=>'youtube-dl']),
$this->response
);
$this->assertTrue($result->isOk());
}
/**
* Test the video() function with a missing password.
*
* @return void
*/
public function testVideoWithMissingPassword()
{
$result = $this->controller->video(
$this->request->withQueryParams(['url'=>'http://vimeo.com/68375962']),
$this->response
);
$this->assertTrue($result->isOk());
$result = $this->controller->video(
$this->request->withQueryParams(['url'=>'http://vimeo.com/68375962', 'audio'=>true]),
$this->response
);
$this->assertTrue($result->isOk());
}
/**
* Test the video() function with streams enabled.
*
* @return void
*/
public function testVideoWithStream()
{
$config = Config::getInstance();
$config->stream = true;
$result = $this->controller->video(
$this->request->withQueryParams(['url'=>'https://www.youtube.com/watch?v=M7IpKCZ47pU']),
$this->response
);
$this->assertTrue($result->isOk());
$result = $this->controller->video(
$this->request->withQueryParams(['url'=>'https://www.youtube.com/watch?v=M7IpKCZ47pU', 'audio'=>true]),
$this->response
);
$this->assertTrue($result->isOk());
}
/**
* Test the error() function.
*
* @return void
*/
public function testError()
{
$result = $this->controller->error($this->request, $this->response, new \Exception('foo'));
$this->assertTrue($result->isServerError());
}
/**
* Test the redirect() function without the URL parameter.
*
* @return void
*/
public function testRedirectWithoutUrl()
{
$result = $this->controller->redirect($this->request, $this->response);
$this->assertTrue($result->isRedirect());
}
/**
* Test the redirect() function.
*
* @return void
*/
public function testRedirect()
{
$result = $this->controller->redirect(
$this->request->withQueryParams(['url'=>'https://www.youtube.com/watch?v=M7IpKCZ47pU']),
$this->response
);
$this->assertTrue($result->isRedirect());
}
/**
* Test the redirect() function with a specific format.
*
* @return void
*/
public function testRedirectWithFormat()
{
$result = $this->controller->redirect(
$this->request->withQueryParams(['url'=>'https://www.youtube.com/watch?v=M7IpKCZ47pU', 'format'=>'worst']),
$this->response
);
$this->assertTrue($result->isRedirect());
}
/**
* Test the redirect() function with streams enabled.
*
* @return void
*/
public function testRedirectWithStream()
{
$config = Config::getInstance();
$config->stream = true;
$result = $this->controller->redirect(
$this->request->withQueryParams(['url'=>'https://www.youtube.com/watch?v=M7IpKCZ47pU']),
$this->response
);
$this->assertTrue($result->isOk());
}
/**
* Test the redirect() function with an M3U stream.
*
* @return void
*/
public function testRedirectWithM3uStream()
{
$config = Config::getInstance();
$config->stream = true;
//We need to create a new controller instance in order to apply the custom config
$controller = new FrontController($this->container);
$result = $controller->redirect(
$this->request->withQueryParams(['url'=>'https://twitter.com/verge/status/813055465324056576/video/1']),
$this->response
);
$this->assertTrue($result->isOk());
}
/**
* Test the redirect() function with a missing password.
*
* @return void
*/
public function testRedirectWithMissingPassword()
{
$result = $this->controller->redirect(
$this->request->withQueryParams(['url'=>'http://vimeo.com/68375962']),
$this->response
);
$this->assertTrue($result->isRedirect());
}
/**
* Test the redirect() function with an error.
*
* @return void
*/
public function testRedirectWithError()
{
$result = $this->controller->redirect(
$this->request->withQueryParams(['url'=>'http://example.com/foo']),
$this->response
);
$this->assertTrue($result->isServerError());
}
}

View file

@ -7,10 +7,7 @@ namespace Alltube\Test;
use Alltube\UglyRouter; use Alltube\UglyRouter;
use Slim\Http\Environment; use Slim\Http\Environment;
use Slim\Http\Headers;
use Slim\Http\Request; use Slim\Http\Request;
use Slim\Http\Stream;
use Slim\Http\Uri;
/** /**
* Unit tests for the UglyRouter class. * Unit tests for the UglyRouter class.
@ -43,13 +40,13 @@ class UglyRouterTest extends \PHPUnit_Framework_TestCase
$this->assertEquals( $this->assertEquals(
[1, 'route0', []], [1, 'route0', []],
$this->router->dispatch( $this->router->dispatch(
new Request( Request::createFromEnvironment(
'GET', Environment::mock(
Uri::createFromString('http://example.com/?page=foo'), [
Headers::createFromEnvironment(new Environment()), 'REQUEST_METHOD' => 'GET',
[], 'QUERY_STRING' => 'page=foo',
[], ]
new Stream(fopen('php://temp', 'r')) )
) )
) )
); );

View file

@ -146,7 +146,7 @@ class VideoDownloadTest extends \PHPUnit_Framework_TestCase
{ {
return [ return [
[ [
'https://www.youtube.com/watch?v=M7IpKCZ47pU', null, 'https://www.youtube.com/watch?v=M7IpKCZ47pU', 'best[protocol^=http]',
"It's Not Me, It's You - Hearts Under Fire-M7IpKCZ47pU", "It's Not Me, It's You - Hearts Under Fire-M7IpKCZ47pU",
'mp4', 'mp4',
'googlevideo.com', 'googlevideo.com',
@ -159,7 +159,7 @@ class VideoDownloadTest extends \PHPUnit_Framework_TestCase
'googlevideo.com', 'googlevideo.com',
], ],
[ [
'https://vimeo.com/24195442', null, 'https://vimeo.com/24195442', 'best[protocol^=http]',
'Carving the Mountains-24195442', 'Carving the Mountains-24195442',
'mp4', 'mp4',
'vimeocdn.com', 'vimeocdn.com',
@ -179,6 +179,23 @@ class VideoDownloadTest extends \PHPUnit_Framework_TestCase
]; ];
} }
/**
* Provides M3U8 URLs for tests.
*
* @return array[]
*/
public function m3uUrlProvider()
{
return [
[
'https://twitter.com/verge/status/813055465324056576/video/1', 'best',
'The Verge - This tiny origami robot can self-fold and complete tasks-813055465324056576',
'mp4',
'video.twimg.com',
],
];
}
/** /**
* Provides incorrect URLs for tests. * Provides incorrect URLs for tests.
* *
@ -199,6 +216,7 @@ class VideoDownloadTest extends \PHPUnit_Framework_TestCase
* *
* @return void * @return void
* @dataProvider URLProvider * @dataProvider URLProvider
* @dataProvider m3uUrlProvider
*/ */
public function testGetJSON($url, $format) public function testGetJSON($url, $format)
{ {
@ -207,6 +225,7 @@ class VideoDownloadTest extends \PHPUnit_Framework_TestCase
$this->assertObjectHasAttribute('url', $info); $this->assertObjectHasAttribute('url', $info);
$this->assertObjectHasAttribute('ext', $info); $this->assertObjectHasAttribute('ext', $info);
$this->assertObjectHasAttribute('title', $info); $this->assertObjectHasAttribute('title', $info);
$this->assertObjectHasAttribute('extractor_key', $info);
$this->assertObjectHasAttribute('formats', $info); $this->assertObjectHasAttribute('formats', $info);
$this->assertObjectHasAttribute('_filename', $info); $this->assertObjectHasAttribute('_filename', $info);
} }
@ -222,7 +241,7 @@ class VideoDownloadTest extends \PHPUnit_Framework_TestCase
*/ */
public function testGetJSONError($url) public function testGetJSONError($url)
{ {
$videoURL = $this->download->getJSON($url); $this->download->getJSON($url);
} }
/** /**
@ -235,6 +254,7 @@ class VideoDownloadTest extends \PHPUnit_Framework_TestCase
* *
* @return void * @return void
* @dataProvider urlProvider * @dataProvider urlProvider
* @dataProvider m3uUrlProvider
*/ */
public function testGetFilename($url, $format, $filename, $extension) public function testGetFilename($url, $format, $filename, $extension)
{ {
@ -262,11 +282,10 @@ class VideoDownloadTest extends \PHPUnit_Framework_TestCase
* @param string $url URL * @param string $url URL
* @param string $format Format * @param string $format Format
* @param string $filename Filename * @param string $filename Filename
* @param string $domain Domain
* @param string $audioFilename MP3 audio file name
* *
* @return void * @return void
* @dataProvider urlProvider * @dataProvider urlProvider
* @dataProvider m3uUrlProvider
*/ */
public function testGetAudioFilename($url, $format, $filename) public function testGetAudioFilename($url, $format, $filename)
{ {
@ -302,7 +321,7 @@ class VideoDownloadTest extends \PHPUnit_Framework_TestCase
*/ */
public function testGetAudioStreamAvconvError($url, $format) public function testGetAudioStreamAvconvError($url, $format)
{ {
$config = \Alltube\Config::getInstance(); $config = Config::getInstance();
$config->avconv = 'foobar'; $config->avconv = 'foobar';
$this->download->getAudioStream($url, $format); $this->download->getAudioStream($url, $format);
} }
@ -319,7 +338,7 @@ class VideoDownloadTest extends \PHPUnit_Framework_TestCase
*/ */
public function testGetAudioStreamCurlError($url, $format) public function testGetAudioStreamCurlError($url, $format)
{ {
$config = \Alltube\Config::getInstance(); $config = Config::getInstance();
$config->curl = 'foobar'; $config->curl = 'foobar';
$config->rtmpdump = 'foobar'; $config->rtmpdump = 'foobar';
$this->download->getAudioStream($url, $format); $this->download->getAudioStream($url, $format);
@ -328,11 +347,50 @@ class VideoDownloadTest extends \PHPUnit_Framework_TestCase
/** /**
* Test getAudioStream function with a M3U8 file. * Test getAudioStream function with a M3U8 file.
* *
* @param string $url URL
* @param string $format Format
*
* @return void * @return void
* @expectedException Exception * @expectedException Exception
* @dataProvider m3uUrlProvider
*/ */
public function testGetAudioStreamM3uError() public function testGetAudioStreamM3uError($url, $format)
{ {
$this->download->getAudioStream('https://twitter.com/verge/status/813055465324056576/video/1', 'best'); $this->download->getAudioStream($url, $format);
}
/**
* Test getM3uStream function.
*
* @param string $url URL
* @param string $format Format
*
* @return void
* @dataProvider m3uUrlProvider
*/
public function testGetM3uStream($url, $format)
{
$video = $this->download->getJSON($url, $format);
$stream = $this->download->getM3uStream($video);
$this->assertInternalType('resource', $stream);
$this->assertFalse(feof($stream));
}
/**
* Test getM3uStream function without avconv.
*
* @param string $url URL
* @param string $format Format
*
* @return void
* @expectedException Exception
* @dataProvider m3uUrlProvider
*/
public function testGetM3uStreamAvconvError($url, $format)
{
$config = \Alltube\Config::getInstance();
$config->avconv = 'foobar';
$video = $this->download->getJSON($url, $format);
$this->download->getM3uStream($video);
} }
} }

11
tests/bootstrap.php Normal file
View file

@ -0,0 +1,11 @@
<?php
/**
* File used to bootstrap tests.
*/
/**
* Composer autoload.
*/
require_once __DIR__.'/../vendor/autoload.php';
session_start();