diff --git a/.gitignore b/.gitignore index 7a3db24..0823947 100644 --- a/.gitignore +++ b/.gitignore @@ -9,6 +9,7 @@ ffmpeg-*/ alltube-*.zip coverage/ bower_components/ -config.yml +config/config.yml docs/ clover.xml +i18n/*/LC_MESSAGES/*.mo diff --git a/.htaccess b/.htaccess index 32a41b4..6487a7c 100644 --- a/.htaccess +++ b/.htaccess @@ -1,4 +1,4 @@ - + AddType application/x-web-app-manifest+json .webapp Addtype font/truetype .ttf @@ -15,13 +15,15 @@ FileETag None -RewriteEngine On + + RewriteEngine On -RewriteCond %{HTTP_HOST} ^alltube\.herokuapp\.com$ [NC] -RewriteRule ^(.*)$ https://www.alltubedownload.net/$1 [R=301,L] + RewriteCond %{HTTP_HOST} ^alltube\.herokuapp\.com$ [NC] + RewriteRule ^(.*)$ https://www.alltubedownload.net/$1 [R=301,L] -RewriteCond %{REQUEST_FILENAME} !-f -RewriteRule ^ index.php [QSA,L] + RewriteCond %{REQUEST_FILENAME} !-f + RewriteRule ^ index.php [QSA,L] + AddOutputFilterByType DEFLATE text/css text/html application/javascript font/truetype diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 898a247..44ae7fa 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,6 +1,9 @@ +# Contributing + ## 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 read the [README](README.md) and the [FAQ](resources/FAQ.md). * You can provide **logs**. diff --git a/Dockerfile b/Dockerfile index 211291d..209d2e7 100644 --- a/Dockerfile +++ b/Dockerfile @@ -7,7 +7,7 @@ RUN docker-php-ext-install intl RUN docker-php-ext-install zip RUN a2enmod rewrite RUN curl -sS https://getcomposer.org/installer | php -COPY php.ini /usr/local/etc/php/ +COPY resources/php.ini /usr/local/etc/php/ COPY . /var/www/html/ RUN php composer.phar install --prefer-dist RUN npm install diff --git a/Gruntfile.js b/Gruntfile.js index dcc42ff..0ee71c0 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -68,7 +68,7 @@ module.exports = function (grunt) { options: { archive: 'alltube-<%= githash.main.tag %>.zip' }, - src: ['*.php', '!config.yml', 'dist/**', '.htaccess', 'img/**', 'LICENSE', 'README.md', 'robots.txt', 'sitemap.xml', 'templates/**', 'templates_c/', 'vendor/**', 'classes/**', 'controllers/**', 'bower_components/**', '!vendor/ffmpeg/**', '!vendor/bin/ffmpeg', '!vendor/phpunit/**', '!vendor/squizlabs/**'] + src: ['*.php', '!config/config.yml', 'dist/**', '.htaccess', 'img/**', 'LICENSE', 'README.md', 'robots.txt', 'resources/sitemap.xml', 'templates/**', 'templates_c/', 'vendor/**', 'classes/**', 'controllers/**', 'bower_components/**', '!vendor/ffmpeg/**', '!vendor/bin/ffmpeg', '!vendor/phpunit/**', '!vendor/squizlabs/**'] } }, phpdocumentor: { @@ -80,7 +80,7 @@ module.exports = function (grunt) { }, jsonlint: { manifests: { - src: ['*.json', '*.webapp'], + src: ['*.json', 'resources/*.json'], options: { format: true } @@ -90,6 +90,26 @@ module.exports = function (grunt) { package: { src: 'package.json' } + }, + potomo: { + dist: { + options: { + poDel: false + }, + files: { + 'i18n/fr_FR/LC_MESSAGES/Alltube.mo': 'i18n/fr_FR/LC_MESSAGES/Alltube.po', + 'i18n/zh_CN/LC_MESSAGES/Alltube.mo': 'i18n/zh_CN/LC_MESSAGES/Alltube.po' + } + } + }, + csslint: { + options: { + 'box-sizing': false, + 'bulletproof-font-face': false + }, + css: { + src: 'css/*' + } } } ); @@ -105,9 +125,11 @@ module.exports = function (grunt) { grunt.loadNpmTasks('grunt-phpdocumentor'); grunt.loadNpmTasks('grunt-jsonlint'); grunt.loadNpmTasks('grunt-fixpack'); + grunt.loadNpmTasks('grunt-potomo'); + grunt.loadNpmTasks('grunt-contrib-csslint'); - grunt.registerTask('default', ['uglify', 'cssmin']); - grunt.registerTask('lint', ['jslint', 'fixpack', 'jsonlint', 'phpcs']); + grunt.registerTask('default', ['uglify', 'cssmin', 'potomo']); + grunt.registerTask('lint', ['jslint', 'csslint', 'fixpack', 'jsonlint', 'phpcs']); grunt.registerTask('test', ['phpunit']); grunt.registerTask('doc', ['phpdocumentor']); grunt.registerTask('release', ['default', 'githash', 'compress']); diff --git a/README.md b/README.md index 776aca9..6bf447e 100644 --- a/README.md +++ b/README.md @@ -43,12 +43,16 @@ npm install composer install ``` +### On Heroku + +[![Deploy](https://www.herokucdn.com/deploy/button.svg)](https://heroku.com/deploy) + ## Config If you want to use a custom config, you need to create a config file: ```bash -cp config.example.yml config.yml +cp config/config.example.yml config/config.yml ``` ## PHP requirements @@ -168,7 +172,7 @@ You can also have a look at this [example project](https://github.com/Rudloff/al ## FAQ -Please read the [FAQ](FAQ.md) before reporting any issue. +Please read the [FAQ](resources/FAQ.md) before reporting any issue. ## License diff --git a/app.json b/app.json new file mode 100644 index 0000000..b9584fe --- /dev/null +++ b/app.json @@ -0,0 +1,38 @@ +{ + "name": "AllTube Download", + "description": "HTML GUI for youtube-dl", + "repository": "https://github.com/Rudloff/alltube.git", + "logo": "https://alltubedownload.net/img/logo.png", + "keywords": [ + "alltube", + "download", + "video", + "youtube", + "php" + ], + "buildpacks": [ + { + "url": "https://github.com/piotras/heroku-buildpack-gettext.git" + }, + { + "url": "heroku/nodejs" + }, + { + "url": "heroku/python" + }, + { + "url": "heroku/php" + } + ], + "env": { + "CONVERT": { + "description": "Enable audio conversion", + "value": "true" + }, + "PYTHON": { + "description": "Path to python binary", + "value": "/app/.heroku/python/bin/python" + } + }, + "website": "https://alltubedownload.net/" +} diff --git a/classes/Config.php b/classes/Config.php index be22a3e..6226f26 100644 --- a/classes/Config.php +++ b/classes/Config.php @@ -38,7 +38,7 @@ class Config * * @var array */ - public $params = ['--no-warnings', '--ignore-errors', '--flat-playlist']; + public $params = ['--no-warnings', '--ignore-errors', '--flat-playlist', '--restrict-filenames']; /** * Enable audio conversion. @@ -126,13 +126,13 @@ class Config * * @return Config */ - public static function getInstance($yamlfile = 'config.yml') + public static function getInstance($yamlfile = 'config/config.yml') { $yamlPath = __DIR__.'/../'.$yamlfile; if (is_null(self::$instance) || self::$instance->file != $yamlfile) { if (is_file($yamlfile)) { $options = Yaml::parse(file_get_contents($yamlPath)); - } elseif ($yamlfile == 'config.yml' || empty($yamlfile)) { + } elseif ($yamlfile == 'config/config.yml' || empty($yamlfile)) { /* Allow for the default file to be missing in order to not surprise users that did not create a config file diff --git a/classes/Locale.php b/classes/Locale.php new file mode 100644 index 0000000..cf6f602 --- /dev/null +++ b/classes/Locale.php @@ -0,0 +1,95 @@ +language = $parse[1]['language']; + $this->region = $parse[1]['region']; + } + + /** + * Convert the locale to a string. + * + * @return string ISO 15897 code + */ + public function __toString() + { + return $this->getIso15897(); + } + + /** + * Get the full name of the locale. + * + * @return string + */ + public function getFullName() + { + return \Locale::getDisplayName($this->getIso15897(), $this->getIso15897()); + } + + /** + * Get the ISO 15897 code. + * + * @return string + */ + public function getIso15897() + { + return $this->language.'_'.$this->region; + } + + /** + * Get the BCP 47 code. + * + * @return string + */ + public function getBcp47() + { + return $this->language.'-'.$this->region; + } + + /** + * Get the ISO 3166 code. + * + * @return string + */ + public function getIso3166() + { + return strtolower($this->region); + } + + public function getCountry() + { + return country($this->getIso3166()); + } +} diff --git a/classes/LocaleManager.php b/classes/LocaleManager.php new file mode 100644 index 0000000..d822588 --- /dev/null +++ b/classes/LocaleManager.php @@ -0,0 +1,87 @@ +newInstance($cookies); + $this->sessionSegment = $session->getSegment('Alltube\LocaleManager'); + $cookieLocale = $this->sessionSegment->get('locale'); + if (isset($cookieLocale)) { + $this->setLocale(new Locale($cookieLocale)); + } + } + + /** + * Get a list of supported locales. + * + * @return Locale[] + */ + public function getSupportedLocales() + { + $return = []; + foreach ($this->supportedLocales as $supportedLocale) { + $return[] = new Locale($supportedLocale); + } + + return $return; + } + + /** + * Get the current locale. + * + * @return Locale + */ + public function getLocale() + { + return $this->curLocale; + } + + /** + * Set the current locale. + * + * @param Locale $locale Locale + */ + public function setLocale(Locale $locale) + { + putenv('LANG='.$locale); + setlocale(LC_ALL, [$locale, $locale.'.utf8']); + $this->curLocale = $locale; + $this->sessionSegment->set('locale', $locale); + } +} diff --git a/classes/LocaleMiddleware.php b/classes/LocaleMiddleware.php new file mode 100644 index 0000000..51dfe6e --- /dev/null +++ b/classes/LocaleMiddleware.php @@ -0,0 +1,80 @@ +localeManager = $container->get('locale'); + } + + /** + * Test if a locale can be used for the current user. + * + * @param array $proposedLocale Locale array created by AcceptLanguage::parse() + * + * @return string Locale name if chosen, nothing otherwise + */ + public function testLocale(array $proposedLocale) + { + foreach ($this->localeManager->getSupportedLocales() as $locale) { + $parsedLocale = AcceptLanguage::parse($locale); + if (isset($proposedLocale['language']) + && $parsedLocale[1]['language'] == $proposedLocale['language'] + && $parsedLocale[1]['region'] == $proposedLocale['region'] + ) { + return new Locale($proposedLocale['language'].'_'.$proposedLocale['region']); + } + } + } + + /** + * Main middleware function. + * + * @param Request $request PSR request + * @param Response $response PSR response + * @param callable $next Next middleware + * + * @return Response + */ + public function __invoke(Request $request, Response $response, callable $next) + { + $headers = $request->getHeader('Accept-Language'); + $curLocale = $this->localeManager->getLocale(); + if (!isset($curLocale)) { + if (isset($headers[0])) { + $this->localeManager->setLocale( + AcceptLanguage::detect([$this, 'testLocale'], new Locale('en_US'), $headers[0]) + ); + } else { + $this->localeManager->setLocale(new Locale('en_US')); + } + } + + return $next($request, $response); + } +} diff --git a/classes/PlaylistArchiveStream.php b/classes/PlaylistArchiveStream.php new file mode 100644 index 0000000..b12867d --- /dev/null +++ b/classes/PlaylistArchiveStream.php @@ -0,0 +1,201 @@ +client = new \GuzzleHttp\Client(); + $this->download = new VideoDownload(); + } + + /** + * Add data to the archive. + * + * @param string $data Data + * + * @return void + */ + protected function send($data) + { + $pos = ftell($this->buffer); + fwrite($this->buffer, $data); + fseek($this->buffer, $pos); + } + + /** + * Called when fopen() is used on the stream. + * + * @param string $path Playlist path (should be playlist://url1;url2;.../format) + * + * @return bool + */ + public function stream_open($path) + { + $this->format = ltrim(parse_url($path, PHP_URL_PATH), '/'); + $this->buffer = fopen('php://temp', 'r+'); + foreach (explode(';', parse_url($path, PHP_URL_HOST)) as $url) { + $this->files[] = [ + 'url' => urldecode($url), + 'headersSent'=> false, + 'complete' => false, + 'stream' => null, + ]; + } + + return true; + } + + /** + * Called when fwrite() is used on the stream. + * + * @return int + */ + public function stream_write() + { + //We don't support writing to a stream + return 0; + } + + /** + * Called when fstat() is used on the stream. + * + * @return array + */ + public function stream_stat() + { + //We need this so Slim won't try to get the size of the stream + return [ + 'mode'=> 0010000, + ]; + } + + /** + * Called when ftell() is used on the stream. + * + * @return int + */ + public function stream_tell() + { + return ftell($this->buffer); + } + + /** + * Called when fseek() is used on the stream. + * + * @param int $offset Offset + * + * @return bool + */ + public function stream_seek($offset) + { + return fseek($this->buffer, $offset) == 0; + } + + /** + * Called when feof() is used on the stream. + * + * @return bool + */ + public function stream_eof() + { + foreach ($this->files as $file) { + if (!$file['complete']) { + return false; + } + } + + return true; + } + + /** + * Called when fread() is used on the stream. + * + * @param int $count Number of bytes to read + * + * @return string + */ + public function stream_read($count) + { + if (!$this->files[$this->curFile]['headersSent']) { + $urls = $this->download->getUrl($this->files[$this->curFile]['url'], $this->format); + $response = $this->client->request('GET', $urls[0], ['stream' => true]); + + $contentLengthHeaders = $response->getHeader('Content-Length'); + $this->init_file_stream_transfer( + $this->download->getFilename($this->files[$this->curFile]['url'], $this->format), + $contentLengthHeaders[0] + ); + + $this->files[$this->curFile]['headersSent'] = true; + $this->files[$this->curFile]['stream'] = $response->getBody(); + } elseif (!$this->files[$this->curFile]['stream']->eof()) { + $this->stream_file_part($this->files[$this->curFile]['stream']->read($count)); + } elseif (!$this->files[$this->curFile]['complete']) { + $this->complete_file_stream(); + $this->files[$this->curFile]['complete'] = true; + } elseif (isset($this->files[$this->curFile])) { + $this->curFile += 1; + } + + return fread($this->buffer, $count); + } +} diff --git a/classes/VideoDownload.php b/classes/VideoDownload.php index 0d42a97..a1c45a2 100644 --- a/classes/VideoDownload.php +++ b/classes/VideoDownload.php @@ -218,9 +218,9 @@ class VideoDownload * * @return \Symfony\Component\Process\Process Process */ - private function getRtmpProcess($video) + private function getRtmpProcess(\stdClass $video) { - if (!shell_exec('which '.$this->config->rtmpdump)) { + if (!$this->checkCommand([$this->config->rtmpdump, '--help'])) { throw(new \Exception('Can\'t find rtmpdump')); } $builder = new ProcessBuilder( @@ -240,6 +240,22 @@ class VideoDownload return $builder->getProcess(); } + /** + * Check if a command runs successfully. + * + * @param array $command Command and arguments + * + * @return bool False if the command returns an error, true otherwise + */ + private function checkCommand(array $command) + { + $builder = ProcessBuilder::create($command); + $process = $builder->getProcess(); + $process->run(); + + return $process->isSuccessful(); + } + /** * Get a process that runs avconv in order to convert a video to MP3. * @@ -249,11 +265,11 @@ class VideoDownload */ private function getAvconvMp3Process($url) { - if (!shell_exec('which '.$this->config->avconv)) { + if (!$this->checkCommand([$this->config->avconv, '-version'])) { throw(new \Exception('Can\'t find avconv or ffmpeg')); } - return ProcessBuilder::create( + $builder = ProcessBuilder::create( [ $this->config->avconv, '-v', 'quiet', @@ -265,6 +281,8 @@ class VideoDownload 'pipe:1', ] ); + + return $builder->getProcess(); } /** @@ -292,7 +310,7 @@ class VideoDownload } else { $avconvProc = $this->getAvconvMp3Process($video->url); - return popen($avconvProc->getProcess()->getCommandLine(), 'r'); + return popen($avconvProc->getCommandLine(), 'r'); } } @@ -305,7 +323,7 @@ class VideoDownload */ public function getM3uStream(\stdClass $video) { - if (!shell_exec('which '.$this->config->avconv)) { + if (!$this->checkCommand([$this->config->avconv, '-version'])) { throw(new \Exception('Can\'t find avconv or ffmpeg')); } @@ -362,4 +380,23 @@ class VideoDownload { return popen($this->getRtmpProcess($video)->getCommandLine(), 'r'); } + + /** + * Get a Tar stream containing every video in the playlist piped through the server. + * + * @param object $video Video object returned by youtube-dl + * @param string $format Requested format + * + * @return Response HTTP response + */ + public function getPlaylistArchiveStream(\stdClass $video, $format) + { + $playlistItems = []; + foreach ($video->entries as $entry) { + $playlistItems[] = urlencode($entry->url); + } + $stream = fopen('playlist://'.implode(';', $playlistItems).'/'.$format, 'r'); + + return $stream; + } } diff --git a/composer.json b/composer.json index 94d0b81..310215c 100644 --- a/composer.json +++ b/composer.json @@ -12,22 +12,25 @@ "symfony/process": "~3.2.0", "ptachoire/process-builder-chain": "~1.2.0", "guzzlehttp/guzzle": "~6.2.0", - "rudloff/rtmpdump-bin": "~2.3", - "aura/session": "~2.1.0" + "aura/session": "~2.1.0", + "barracudanetworks/archivestream-php": "~1.0.5", + "smarty-gettext/smarty-gettext": "~1.5.1", + "zonuexe/http-accept-language": "~0.4.1", + "rinvex/country": "~2.0.0" }, "require-dev": { "symfony/var-dumper": "~3.2.0", - "squizlabs/php_codesniffer": "~2.8.0", + "squizlabs/php_codesniffer": "~3.0.0", "phpunit/phpunit": "~5.7.2", "ffmpeg/ffmpeg": "dev-release", - "rg3/youtube-dl": "~2017.04.28", - "rudloff/rtmpdump-bin": "~2.3", + "rg3/youtube-dl": "~2017.05.09", + "rudloff/rtmpdump-bin": "~2.3.0", "heroku/heroku-buildpack-php": "*" }, "extra": { "paas": { "nginx-includes": [ - "nginx.conf" + "resources/nginx.conf" ] } }, @@ -36,10 +39,10 @@ "type": "package", "package": { "name": "rg3/youtube-dl", - "version": "2017.04.28", + "version": "2017.05.09", "dist": { "type": "zip", - "url": "https://github.com/rg3/youtube-dl/archive/2017.04.28.zip" + "url": "https://github.com/rg3/youtube-dl/archive/2017.05.09.zip" } } }, diff --git a/composer.lock b/composer.lock index 7568e3b..c5368cc 100644 --- a/composer.lock +++ b/composer.lock @@ -4,8 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", "This file is @generated automatically" ], - "hash": "0a4bd158955df2e3f5ea89714ba9e740", - "content-hash": "cb0e773496b6f26caf1c8591f23488f5", + "content-hash": "22e16312bcf339c90850660d9e5923e7", "packages": [ { "name": "aura/session", @@ -67,7 +66,47 @@ "session", "sessions" ], - "time": "2016-10-03 20:28:32" + "time": "2016-10-03T20:28:32+00:00" + }, + { + "name": "barracudanetworks/archivestream-php", + "version": "1.0.5", + "source": { + "type": "git", + "url": "https://github.com/barracudanetworks/ArchiveStream-php.git", + "reference": "1bf98097d1e9b137fd40081f26abb0a17b097ef7" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/barracudanetworks/ArchiveStream-php/zipball/1bf98097d1e9b137fd40081f26abb0a17b097ef7", + "reference": "1bf98097d1e9b137fd40081f26abb0a17b097ef7", + "shasum": "" + }, + "require": { + "ext-gmp": "*", + "ext-mbstring": "*", + "php": ">=5.1.2" + }, + "type": "library", + "autoload": { + "psr-4": { + "Barracuda\\ArchiveStream\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "A library for dynamically streaming dynamic tar or zip files without the need to have the complete file stored on the server.", + "homepage": "https://github.com/barracudanetworks/ArchiveStream-php", + "keywords": [ + "archive", + "php", + "stream", + "tar", + "zip" + ], + "time": "2017-01-13T14:52:38+00:00" }, { "name": "container-interop/container-interop", @@ -98,7 +137,7 @@ ], "description": "Promoting the interoperability of container objects (DIC, SL, etc.)", "homepage": "https://github.com/container-interop/container-interop", - "time": "2017-02-14 19:40:03" + "time": "2017-02-14T19:40:03+00:00" }, { "name": "guzzlehttp/guzzle", @@ -160,7 +199,7 @@ "rest", "web service" ], - "time": "2017-02-28 22:50:30" + "time": "2017-02-28T22:50:30+00:00" }, { "name": "guzzlehttp/promises", @@ -211,7 +250,7 @@ "keywords": [ "promise" ], - "time": "2016-12-20 10:07:11" + "time": "2016-12-20T10:07:11+00:00" }, { "name": "guzzlehttp/psr7", @@ -276,7 +315,7 @@ "uri", "url" ], - "time": "2017-03-20 17:10:46" + "time": "2017-03-20T17:10:46+00:00" }, { "name": "mathmarques/smarty-view", @@ -326,7 +365,7 @@ "template", "view" ], - "time": "2016-08-25 19:04:49" + "time": "2016-08-25T19:04:49+00:00" }, { "name": "nikic/fast-route", @@ -369,7 +408,7 @@ "router", "routing" ], - "time": "2017-01-19 11:35:12" + "time": "2017-01-19T11:35:12+00:00" }, { "name": "pimple/pimple", @@ -415,7 +454,7 @@ "container", "dependency injection" ], - "time": "2015-09-11 15:10:35" + "time": "2015-09-11T15:10:35+00:00" }, { "name": "psr/container", @@ -464,7 +503,7 @@ "container-interop", "psr" ], - "time": "2017-02-14 16:28:37" + "time": "2017-02-14T16:28:37+00:00" }, { "name": "psr/http-message", @@ -514,7 +553,7 @@ "request", "response" ], - "time": "2016-08-06 14:39:51" + "time": "2016-08-06T14:39:51+00:00" }, { "name": "ptachoire/process-builder-chain", @@ -550,35 +589,81 @@ } ], "description": "Add ability to chain symfony processes", - "time": "2016-04-10 08:33:20" + "time": "2016-04-10T08:33:20+00:00" }, { - "name": "rudloff/rtmpdump-bin", - "version": "2.3", + "name": "rinvex/country", + "version": "v2.0.0", "source": { "type": "git", - "url": "https://github.com/Rudloff/rtmpdump-bin.git", - "reference": "133cdd80e3bab66593e88a5276158596383afd97" + "url": "https://github.com/rinvex/country.git", + "reference": "9405da035644bc76671bfba0c282fef8fd3408e1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Rudloff/rtmpdump-bin/zipball/133cdd80e3bab66593e88a5276158596383afd97", - "reference": "133cdd80e3bab66593e88a5276158596383afd97", + "url": "https://api.github.com/repos/rinvex/country/zipball/9405da035644bc76671bfba0c282fef8fd3408e1", + "reference": "9405da035644bc76671bfba0c282fef8fd3408e1", "shasum": "" }, - "require-dev": { - "rtmpdump/rtmpdump": "2.3" + "require": { + "php": ">=5.5.9" + }, + "require-dev": { + "phpunit/phpunit": "^5.2.0" }, - "bin": [ - "rtmpdump" - ], "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0-dev" + } + }, + "autoload": { + "files": [ + "src/helpers.php" + ], + "psr-4": { + "Rinvex\\Country\\": "src/" + } + }, "notification-url": "https://packagist.org/downloads/", "license": [ - "GPL-2.0" + "MIT" ], - "description": "rtmpdump binary for Linux 64 bit", - "time": "2016-04-12 19:17:32" + "authors": [ + { + "name": "Rinvex LLC", + "email": "help@rinvex.com", + "homepage": "https://rinvex.com" + }, + { + "name": "Abdelrahman Omran", + "email": "me@omranic.com", + "homepage": "https://omranic.com", + "role": "Project Lead" + }, + { + "name": "The Generous Laravel Community", + "homepage": "https://github.com/rinvex/country/contributors" + } + ], + "description": "Rinvex Country is a simple and lightweight package for retrieving country details with flexibility. A whole bunch of data including name, demonym, capital, iso codes, dialling codes, geo data, currencies, flags, emoji, and other attributes for all 250 countries worldwide at your fingertips.", + "homepage": "https://rinvex.com", + "keywords": [ + "Flexible", + "Simple", + "countries", + "country", + "currencies", + "demonym", + "dialling", + "emoji", + "flags", + "geographic", + "languages", + "rinvex", + "svg" + ], + "time": "2016-11-27T05:53:11+00:00" }, { "name": "slim/slim", @@ -649,7 +734,61 @@ "micro", "router" ], - "time": "2017-03-19 17:55:20" + "time": "2017-03-19T17:55:20+00:00" + }, + { + "name": "smarty-gettext/smarty-gettext", + "version": "1.5.1", + "source": { + "type": "git", + "url": "https://github.com/smarty-gettext/smarty-gettext.git", + "reference": "00fe2fcbc41e24e0245cd9d73f96bc7b0337972d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/smarty-gettext/smarty-gettext/zipball/00fe2fcbc41e24e0245cd9d73f96bc7b0337972d", + "reference": "00fe2fcbc41e24e0245cd9d73f96bc7b0337972d", + "shasum": "" + }, + "require": { + "ext-gettext": "*", + "ext-pcre": "*", + "php": "~5.3|~7.0" + }, + "require-dev": { + "azatoth/php-pgettext": "~1.0", + "smarty/smarty": "3.1.*" + }, + "suggest": { + "azatoth/php-pgettext": "Support msgctxt for {t} via context parameter" + }, + "bin": [ + "tsmarty2c.php" + ], + "type": "library", + "autoload": { + "files": [ + "block.t.php", + "function.locale.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "LGPL-2.1+" + ], + "authors": [ + { + "name": "Sagi Bashari", + "email": "sagi@boom.org.il" + }, + { + "name": "Elan Ruusamäe", + "email": "glen@delfi.ee" + } + ], + "description": "Gettext plugin enabling internationalization in Smarty Package files", + "homepage": "https://github.com/smarty-gettext/smarty-gettext", + "time": "2017-05-12T12:14:46+00:00" }, { "name": "smarty/smarty", @@ -702,20 +841,20 @@ "keywords": [ "templating" ], - "time": "2016-12-14 21:57:25" + "time": "2016-12-14T21:57:25+00:00" }, { "name": "symfony/process", - "version": "v3.2.8", + "version": "v3.2.9", "source": { "type": "git", "url": "https://github.com/symfony/process.git", - "reference": "999c2cf5061e627e6cd551dc9ebf90dd1d11d9f0" + "reference": "36774717bbd1631be2d0a45acf48aecd5836c867" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/process/zipball/999c2cf5061e627e6cd551dc9ebf90dd1d11d9f0", - "reference": "999c2cf5061e627e6cd551dc9ebf90dd1d11d9f0", + "url": "https://api.github.com/repos/symfony/process/zipball/36774717bbd1631be2d0a45acf48aecd5836c867", + "reference": "36774717bbd1631be2d0a45acf48aecd5836c867", "shasum": "" }, "require": { @@ -751,20 +890,20 @@ ], "description": "Symfony Process Component", "homepage": "https://symfony.com", - "time": "2017-04-12 14:13:17" + "time": "2017-05-08T01:51:21+00:00" }, { "name": "symfony/yaml", - "version": "v3.2.8", + "version": "v3.2.9", "source": { "type": "git", "url": "https://github.com/symfony/yaml.git", - "reference": "acec26fcf7f3031e094e910b94b002fa53d4e4d6" + "reference": "4cdb9fec28fba88203a71f6d095018867f7a2065" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/yaml/zipball/acec26fcf7f3031e094e910b94b002fa53d4e4d6", - "reference": "acec26fcf7f3031e094e910b94b002fa53d4e4d6", + "url": "https://api.github.com/repos/symfony/yaml/zipball/4cdb9fec28fba88203a71f6d095018867f7a2065", + "reference": "4cdb9fec28fba88203a71f6d095018867f7a2065", "shasum": "" }, "require": { @@ -806,7 +945,48 @@ ], "description": "Symfony Yaml Component", "homepage": "https://symfony.com", - "time": "2017-05-01 14:55:58" + "time": "2017-05-25T23:42:36+00:00" + }, + { + "name": "zonuexe/http-accept-language", + "version": "0.4.1", + "source": { + "type": "git", + "url": "https://github.com/BaguettePHP/http-accept-language.git", + "reference": "f71422b1200737aa9d7c7fa83f07cbe4616198d5" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/BaguettePHP/http-accept-language/zipball/f71422b1200737aa9d7c7fa83f07cbe4616198d5", + "reference": "f71422b1200737aa9d7c7fa83f07cbe4616198d5", + "shasum": "" + }, + "require": { + "ext-intl": "*" + }, + "require-dev": { + "phploc/phploc": "*", + "phpunit/phpunit": "4.1.*", + "theseer/phpdox": "0.6.*" + }, + "type": "library", + "autoload": { + "psr-4": { + "Teto\\HTTP\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "USAMI Kenta", + "email": "tadsan@zonu.me" + } + ], + "description": "HTTP Accept-Language Header parser", + "time": "2014-10-19T09:22:18+00:00" } ], "packages-dev": [ @@ -862,7 +1042,7 @@ "constructor", "instantiate" ], - "time": "2015-06-14 21:17:01" + "time": "2015-06-14T21:17:01+00:00" }, { "name": "ffmpeg/ffmpeg", @@ -920,7 +1100,7 @@ "nginx", "php" ], - "time": "2017-03-27 23:33:27" + "time": "2017-03-27T23:33:27+00:00" }, { "name": "myclabs/deep-copy", @@ -962,7 +1142,7 @@ "object", "object graph" ], - "time": "2017-04-12 18:52:22" + "time": "2017-04-12T18:52:22+00:00" }, { "name": "phpdocumentor/reflection-common", @@ -1016,7 +1196,7 @@ "reflection", "static analysis" ], - "time": "2015-12-27 11:43:31" + "time": "2015-12-27T11:43:31+00:00" }, { "name": "phpdocumentor/reflection-docblock", @@ -1061,7 +1241,7 @@ } ], "description": "With this component, a library can provide support for annotations via DocBlocks or otherwise retrieve information that is embedded in a DocBlock.", - "time": "2016-09-30 07:12:33" + "time": "2016-09-30T07:12:33+00:00" }, { "name": "phpdocumentor/type-resolver", @@ -1108,7 +1288,7 @@ "email": "me@mikevanriel.com" } ], - "time": "2016-11-25 06:54:22" + "time": "2016-11-25T06:54:22+00:00" }, { "name": "phpspec/prophecy", @@ -1171,7 +1351,7 @@ "spy", "stub" ], - "time": "2017-03-02 20:05:34" + "time": "2017-03-02T20:05:34+00:00" }, { "name": "phpunit/php-code-coverage", @@ -1234,7 +1414,7 @@ "testing", "xunit" ], - "time": "2017-04-02 07:44:40" + "time": "2017-04-02T07:44:40+00:00" }, { "name": "phpunit/php-file-iterator", @@ -1281,7 +1461,7 @@ "filesystem", "iterator" ], - "time": "2016-10-03 07:40:28" + "time": "2016-10-03T07:40:28+00:00" }, { "name": "phpunit/php-text-template", @@ -1322,7 +1502,7 @@ "keywords": [ "template" ], - "time": "2015-06-21 13:50:34" + "time": "2015-06-21T13:50:34+00:00" }, { "name": "phpunit/php-timer", @@ -1371,7 +1551,7 @@ "keywords": [ "timer" ], - "time": "2017-02-26 11:10:40" + "time": "2017-02-26T11:10:40+00:00" }, { "name": "phpunit/php-token-stream", @@ -1420,20 +1600,20 @@ "keywords": [ "tokenizer" ], - "time": "2017-02-27 10:12:30" + "time": "2017-02-27T10:12:30+00:00" }, { "name": "phpunit/phpunit", - "version": "5.7.19", + "version": "5.7.20", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "69c4f49ff376af2692bad9cebd883d17ebaa98a1" + "reference": "3cb94a5f8c07a03c8b7527ed7468a2926203f58b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/69c4f49ff376af2692bad9cebd883d17ebaa98a1", - "reference": "69c4f49ff376af2692bad9cebd883d17ebaa98a1", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/3cb94a5f8c07a03c8b7527ed7468a2926203f58b", + "reference": "3cb94a5f8c07a03c8b7527ed7468a2926203f58b", "shasum": "" }, "require": { @@ -1451,7 +1631,7 @@ "phpunit/php-timer": "^1.0.6", "phpunit/phpunit-mock-objects": "^3.2", "sebastian/comparator": "^1.2.4", - "sebastian/diff": "~1.2", + "sebastian/diff": "^1.4.3", "sebastian/environment": "^1.3.4 || ^2.0", "sebastian/exporter": "~2.0", "sebastian/global-state": "^1.1", @@ -1502,7 +1682,7 @@ "testing", "xunit" ], - "time": "2017-04-03 02:22:27" + "time": "2017-05-22T07:42:55+00:00" }, { "name": "phpunit/phpunit-mock-objects", @@ -1561,19 +1741,47 @@ "mock", "xunit" ], - "time": "2016-12-08 20:27:08" + "time": "2016-12-08T20:27:08+00:00" }, { "name": "rg3/youtube-dl", - "version": "2017.04.28", + "version": "2017.05.09", "dist": { "type": "zip", - "url": "https://github.com/rg3/youtube-dl/archive/2017.04.28.zip", + "url": "https://github.com/rg3/youtube-dl/archive/2017.05.09.zip", "reference": null, "shasum": null }, "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", "version": "1.0.1", @@ -1617,7 +1825,7 @@ ], "description": "Looks up which function or method a line of code belongs to", "homepage": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/", - "time": "2017-03-04 06:30:41" + "time": "2017-03-04T06:30:41+00:00" }, { "name": "sebastian/comparator", @@ -1681,27 +1889,27 @@ "compare", "equality" ], - "time": "2017-01-29 09:50:25" + "time": "2017-01-29T09:50:25+00:00" }, { "name": "sebastian/diff", - "version": "1.4.1", + "version": "1.4.3", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/diff.git", - "reference": "13edfd8706462032c2f52b4b862974dd46b71c9e" + "reference": "7f066a26a962dbe58ddea9f72a4e82874a3975a4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/13edfd8706462032c2f52b4b862974dd46b71c9e", - "reference": "13edfd8706462032c2f52b4b862974dd46b71c9e", + "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/7f066a26a962dbe58ddea9f72a4e82874a3975a4", + "reference": "7f066a26a962dbe58ddea9f72a4e82874a3975a4", "shasum": "" }, "require": { - "php": ">=5.3.3" + "php": "^5.3.3 || ^7.0" }, "require-dev": { - "phpunit/phpunit": "~4.8" + "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.0" }, "type": "library", "extra": { @@ -1733,7 +1941,7 @@ "keywords": [ "diff" ], - "time": "2015-12-08 07:14:41" + "time": "2017-05-22T07:24:03+00:00" }, { "name": "sebastian/environment", @@ -1783,7 +1991,7 @@ "environment", "hhvm" ], - "time": "2016-11-26 07:53:53" + "time": "2016-11-26T07:53:53+00:00" }, { "name": "sebastian/exporter", @@ -1850,7 +2058,7 @@ "export", "exporter" ], - "time": "2016-11-19 08:54:04" + "time": "2016-11-19T08:54:04+00:00" }, { "name": "sebastian/global-state", @@ -1901,7 +2109,7 @@ "keywords": [ "global state" ], - "time": "2015-10-12 03:26:01" + "time": "2015-10-12T03:26:01+00:00" }, { "name": "sebastian/object-enumerator", @@ -1947,7 +2155,7 @@ ], "description": "Traverses array structures and object graphs to enumerate all referenced objects", "homepage": "https://github.com/sebastianbergmann/object-enumerator/", - "time": "2017-02-18 15:18:39" + "time": "2017-02-18T15:18:39+00:00" }, { "name": "sebastian/recursion-context", @@ -2000,7 +2208,7 @@ ], "description": "Provides functionality to recursively process PHP variables", "homepage": "http://www.github.com/sebastianbergmann/recursion-context", - "time": "2016-11-19 07:33:16" + "time": "2016-11-19T07:33:16+00:00" }, { "name": "sebastian/resource-operations", @@ -2042,7 +2250,7 @@ ], "description": "Provides a list of PHP built-in functions that operate on resources", "homepage": "https://www.github.com/sebastianbergmann/resource-operations", - "time": "2015-07-28 20:34:47" + "time": "2015-07-28T20:34:47+00:00" }, { "name": "sebastian/version", @@ -2085,68 +2293,41 @@ ], "description": "Library that helps with managing the version number of Git-hosted PHP projects", "homepage": "https://github.com/sebastianbergmann/version", - "time": "2016-10-03 07:35:21" + "time": "2016-10-03T07:35:21+00:00" }, { "name": "squizlabs/php_codesniffer", - "version": "2.8.1", + "version": "3.0.0", "source": { "type": "git", "url": "https://github.com/squizlabs/PHP_CodeSniffer.git", - "reference": "d7cf0d894e8aa4c73712ee4a331cc1eaa37cdc7d" + "reference": "b95ff2c3b122a3ee4b57d149a57d2afce65522c3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/squizlabs/PHP_CodeSniffer/zipball/d7cf0d894e8aa4c73712ee4a331cc1eaa37cdc7d", - "reference": "d7cf0d894e8aa4c73712ee4a331cc1eaa37cdc7d", + "url": "https://api.github.com/repos/squizlabs/PHP_CodeSniffer/zipball/b95ff2c3b122a3ee4b57d149a57d2afce65522c3", + "reference": "b95ff2c3b122a3ee4b57d149a57d2afce65522c3", "shasum": "" }, "require": { "ext-simplexml": "*", "ext-tokenizer": "*", "ext-xmlwriter": "*", - "php": ">=5.1.2" + "php": ">=5.4.0" }, "require-dev": { "phpunit/phpunit": "~4.0" }, "bin": [ - "scripts/phpcs", - "scripts/phpcbf" + "bin/phpcs", + "bin/phpcbf" ], "type": "library", "extra": { "branch-alias": { - "dev-master": "2.x-dev" + "dev-master": "3.x-dev" } }, - "autoload": { - "classmap": [ - "CodeSniffer.php", - "CodeSniffer/CLI.php", - "CodeSniffer/Exception.php", - "CodeSniffer/File.php", - "CodeSniffer/Fixer.php", - "CodeSniffer/Report.php", - "CodeSniffer/Reporting.php", - "CodeSniffer/Sniff.php", - "CodeSniffer/Tokens.php", - "CodeSniffer/Reports/", - "CodeSniffer/Tokenizers/", - "CodeSniffer/DocGenerators/", - "CodeSniffer/Standards/AbstractPatternSniff.php", - "CodeSniffer/Standards/AbstractScopeSniff.php", - "CodeSniffer/Standards/AbstractVariableSniff.php", - "CodeSniffer/Standards/IncorrectPatternException.php", - "CodeSniffer/Standards/Generic/Sniffs/", - "CodeSniffer/Standards/MySource/Sniffs/", - "CodeSniffer/Standards/PEAR/Sniffs/", - "CodeSniffer/Standards/PSR1/Sniffs/", - "CodeSniffer/Standards/PSR2/Sniffs/", - "CodeSniffer/Standards/Squiz/Sniffs/", - "CodeSniffer/Standards/Zend/Sniffs/" - ] - }, "notification-url": "https://packagist.org/downloads/", "license": [ "BSD-3-Clause" @@ -2163,7 +2344,7 @@ "phpcs", "standards" ], - "time": "2017-03-01 22:17:45" + "time": "2017-05-04T00:33:04+00:00" }, { "name": "symfony/polyfill-mbstring", @@ -2222,20 +2403,20 @@ "portable", "shim" ], - "time": "2016-11-14 01:06:16" + "time": "2016-11-14T01:06:16+00:00" }, { "name": "symfony/var-dumper", - "version": "v3.2.8", + "version": "v3.2.9", "source": { "type": "git", "url": "https://github.com/symfony/var-dumper.git", - "reference": "fa47963ac7979ddbd42b2d646d1b056bddbf7bb8" + "reference": "eda0d0891a0b60a25015f7b85ea8040b51d72e1e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/var-dumper/zipball/fa47963ac7979ddbd42b2d646d1b056bddbf7bb8", - "reference": "fa47963ac7979ddbd42b2d646d1b056bddbf7bb8", + "url": "https://api.github.com/repos/symfony/var-dumper/zipball/eda0d0891a0b60a25015f7b85ea8040b51d72e1e", + "reference": "eda0d0891a0b60a25015f7b85ea8040b51d72e1e", "shasum": "" }, "require": { @@ -2290,7 +2471,7 @@ "debug", "dump" ], - "time": "2017-05-01 14:55:58" + "time": "2017-05-15T12:02:31+00:00" }, { "name": "webmozart/assert", @@ -2340,7 +2521,7 @@ "check", "validate" ], - "time": "2016-11-23 20:04:58" + "time": "2016-11-23T20:04:58+00:00" } ], "aliases": [], diff --git a/config.example.yml b/config/config.example.yml similarity index 100% rename from config.example.yml rename to config/config.example.yml diff --git a/config_test.yml b/config/config_test.yml similarity index 100% rename from config_test.yml rename to config/config_test.yml diff --git a/controllers/FrontController.php b/controllers/FrontController.php index 16d22ee..3318048 100644 --- a/controllers/FrontController.php +++ b/controllers/FrontController.php @@ -6,6 +6,7 @@ namespace Alltube\Controller; use Alltube\Config; +use Alltube\Locale; use Alltube\PasswordException; use Alltube\VideoDownload; use Psr\Container\ContainerInterface; @@ -61,6 +62,13 @@ class FrontController */ private $defaultFormat = 'best[protocol^=http]'; + /** + * LocaleManager instance. + * + * @var LocaleManager + */ + private $localeManager; + /** * FrontController constructor. * @@ -78,6 +86,7 @@ class FrontController $this->download = new VideoDownload(); $this->container = $container; $this->view = $this->container->get('view'); + $this->localeManager = $this->container->get('locale'); $session_factory = new \Aura\Session\SessionFactory(); $session = $session_factory->newInstance($cookies); $this->sessionSegment = $session->getSegment('Alltube\Controller\FrontController'); @@ -101,18 +110,35 @@ class FrontController $response, 'index.tpl', [ - 'convert' => $this->config->convert, - 'uglyUrls' => $this->config->uglyUrls, - 'class' => 'index', - 'description' => 'Easily download videos from Youtube, Dailymotion, Vimeo and other websites.', - 'domain' => $uri->getScheme().'://'.$uri->getAuthority(), - 'canonical' => $this->getCanonicalUrl($request), + 'config' => $this->config, + 'class' => 'index', + 'description' => 'Easily download videos from Youtube, Dailymotion, Vimeo and other websites.', + 'domain' => $uri->getScheme().'://'.$uri->getAuthority(), + 'canonical' => $this->getCanonicalUrl($request), + 'supportedLocales' => $this->localeManager->getSupportedLocales(), + 'locale' => $this->localeManager->getLocale(), ] ); return $response; } + /** + * Switch locale. + * + * @param Request $request PSR-7 request + * @param Response $response PSR-7 response + * @param array $data Query parameters + * + * @return Response + */ + public function locale(Request $request, Response $response, array $data) + { + $this->localeManager->setLocale(new Locale($data['locale'])); + + return $response->withRedirect($this->container->get('router')->pathFor('index')); + } + /** * Display a list of extractors. * @@ -133,6 +159,7 @@ class FrontController 'description' => 'List of all supported websites from which Alltube Download '. 'can extract video or audio files', 'canonical' => $this->getCanonicalUrl($request), + 'locale' => $this->localeManager->getLocale(), ] ); @@ -157,6 +184,7 @@ class FrontController 'title' => 'Password prompt', 'description' => 'You need a password in order to download this video with Alltube Download', 'canonical' => $this->getCanonicalUrl($request), + 'locale' => $this->localeManager->getLocale(), ] ); @@ -247,8 +275,7 @@ class FrontController 'protocol' => $protocol, 'config' => $this->config, 'canonical' => $this->getCanonicalUrl($request), - 'uglyUrls' => $this->config->uglyUrls, - 'remux' => $this->config->remux, + 'locale' => $this->localeManager->getLocale(), ] ); @@ -300,6 +327,7 @@ class FrontController 'class' => 'video', 'title' => 'Error', 'canonical' => $this->getCanonicalUrl($request), + 'locale' => $this->localeManager->getLocale(), ] ); @@ -320,26 +348,32 @@ class FrontController private function getStream($url, $format, Response $response, Request $request, $password = null) { $video = $this->download->getJSON($url, $format, $password); - if ($video->protocol == 'rtmp') { + if (isset($video->entries)) { + $stream = $this->download->getPlaylistArchiveStream($video, $format); + $response = $response->withHeader('Content-Type', 'application/x-tar'); + $response = $response->withHeader( + 'Content-Disposition', + 'attachment; filename="'.$video->title.'.tar"' + ); + + return $response->withBody(new Stream($stream)); + } elseif ($video->protocol == 'rtmp') { $stream = $this->download->getRtmpStream($video); $response = $response->withHeader('Content-Type', 'video/'.$video->ext); - if ($request->isGet()) { - $response = $response->withBody(new Stream($stream)); - } + $body = new Stream($stream); } elseif ($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)); - } + $body = 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()); - } + $body = $stream->getBody(); + } + if ($request->isGet()) { + $response = $response->withBody($body); } $response = $response->withHeader( 'Content-Disposition', @@ -353,7 +387,7 @@ class FrontController /** * Get a remuxed stream piped through the server. * - * @param array $urls URLs of the video and audio files + * @param string[] $urls URLs of the video and audio files * @param string $format Requested format * @param Response $response PSR-7 response * @param Request $request PSR-7 request @@ -429,6 +463,10 @@ class FrontController $this->sessionSegment->getFlash($url) ); } else { + if (empty($videoUrls[0])) { + throw new \Exception("Can't find URL of video"); + } + return $response->withRedirect($videoUrls[0]); } } diff --git a/css/fonts.css b/css/fonts.css index 1eb4f61..da1e849 100644 --- a/css/fonts.css +++ b/css/fonts.css @@ -10,3 +10,11 @@ font-weight: 400; src: local('Open Sans'), local('OpenSans'), url(../bower_components/opensans-googlefont/OpenSans-Regular.ttf); } + +.small-font { + font-size: 13px; +} + +.large-font { + font-size:24px; +} diff --git a/css/style.css b/css/style.css index a055a97..eb886dc 100644 --- a/css/style.css +++ b/css/style.css @@ -1,119 +1,118 @@ body { - text-align:center; background-color: #EBEBEB; background-image:url('../img/fond.jpg'); font-family: 'Open Sans', sans-serif; font-weight:400; + text-align:center; } -/************************HEADER******************************/ +/* Header */ header { - position:absolute; - top:0; - text-align:right; - width:100%; padding:0; - } + position:absolute; + text-align:right; + top:0; + width:100%; +} -.social -{padding-right:21px;} +.social { + padding-right:21px; +} -header a -{ -overflow:hidden; -height:38px; -width:38px; -position:relative; -float:right; -margin-top:13px; -margin-left:13px; -margin-right:0; -background-position:0 0; -background-repeat:no-repeat; - -webkit-transition: all 0.1s ease-in; - -moz-transition: all 0.1s ease-in; - -o-transition: all 0.1s ease-in; +header .social a { + background-position:0 0; + background-repeat:no-repeat; + float:right; + height:38px; + margin-left:13px; + margin-right:0; + margin-top:13px; + overflow:hidden; + position:relative; + -webkit-transition: all 0.1s ease-in; + -moz-transition: all 0.1s ease-in; + -o-transition: all 0.1s ease-in; + width:38px; } header a:focus, -header a:hover -{ - outline:none; +header a:hover { background-position:0 100%; - -webkit-transition: all 0.1s ease-in; - -moz-transition: all 0.1s ease-in; - -o-transition: all 0.1s ease-in; + outline:none; + -webkit-transition: all 0.1s ease-in; + -moz-transition: all 0.1s ease-in; + -o-transition: all 0.1s ease-in; } -.share -{background-image:url('../img/share.png');} - -.sharemask -{ -height:38px; -width:38px; -position:absolute; -top:0; -left:0; -z-index:10; -background-image:url('../img/sharemask.png'); -background-position:top left; -background-repeat:no-repeat; +.share { + background-image:url('../img/share.png'); } -.facebook -{background-image:url('../img/facebook.png');} +.sharemask { + background-image:url('../img/sharemask.png'); + background-position:top left; + background-repeat:no-repeat; + height:38px; + left:0; + position:absolute; + top:0; + width:38px; + z-index:10; -.facebookmask -{ -height:38px; -width:38px; -position:absolute; -top:0; -left:0; -z-index:10; -background-image:url('../img/facebookmask.png'); -background-position:top left; -background-repeat:no-repeat; } -.twitter -{background-image:url('../img/twitter.png');} +.facebook { + background-image:url('../img/facebook.png'); +} -.twittermask -{ -height:38px; -width:38px; -position:absolute; -top:0; -left:0; -z-index:10; -background-image:url('../img/twittermask.png'); -background-position:top left; -background-repeat:no-repeat; +.facebookmask { + background-image:url('../img/facebookmask.png'); + background-position:top left; + background-repeat:no-repeat; + height:38px; + left:0; + position:absolute; + top:0; + width:38px; + z-index:10; +} + +.twitter { + background-image:url('../img/twitter.png'); +} + +.twittermask { + background-image:url('../img/twittermask.png'); + background-position:top left; + background-repeat:no-repeat; + height:38px; + left:0; + position:absolute; + top:0; + width:38px; + z-index:10; } -/*************************FOOTER****************************/ +/* Footer */ footer { - position:fixed; + background-image:url('../img/fondfooter.png'); + background-position:top left; + background-repeat:repeat-x; bottom:0; + color:#adadad; + padding-top:20px; + position:fixed; text-align:center; width:100%; - background-image:url('../img/fondfooter.png'); - background-repeat:repeat-x; - background-position:top left; - padding-top:20px; - color:#adadad; - font-size:12px; z-index:11; } @@ -123,20 +122,19 @@ footer { footer a{ color:#adadad; - -webkit-transition: all 0.1s ease-in; - -moz-transition: all 0.1s ease-in; - -o-transition: all 0.1s ease-in; - text-decoration:none; + text-decoration:none; + -webkit-transition: all 0.1s ease-in; + -moz-transition: all 0.1s ease-in; + -o-transition: all 0.1s ease-in; } footer a:focus, -footer a:hover -{ +footer a:hover { + color:#f2084a; outline:none; -color:#f2084a; - -webkit-transition: all 0.1s ease-in; - -moz-transition: all 0.1s ease-in; - -o-transition: all 0.1s ease-in; + -webkit-transition: all 0.1s ease-in; + -moz-transition: all 0.1s ease-in; + -o-transition: all 0.1s ease-in; } @@ -144,52 +142,47 @@ color:#f2084a; -/*************************CONTENT ACCUEIL****************************/ +/* Home content */ .logo { padding-bottom:55px; } -.labelurl -{ -position:relative; -color:#3f3f3f; -font-size:19px; - +.labelurl { + color:#3f3f3f; + font-size:19px; + position:relative; } -.champs -{ -position:relative; -margin-bottom:70px; -margin-top:8px; +.champs { + margin-bottom:70px; + margin-top:8px; + position:relative; } .downloadBtn { - position:relative; background-color:#3A3A3A; border: 3px solid #a5a5a5; - color:#dedede; border-radius:10px; - padding: 12px 14px; - font-size:24px; - font-weight:800; + color:#dedede; cursor:pointer; + display:inline-block; + font-weight:800; + padding: 12px 14px; + position:relative; + text-decoration:none; -webkit-transition: all 0.1s ease-in; -moz-transition: all 0.1s ease-in; -o-transition: all 0.1s ease-in; - text-decoration:none; - display:inline-block; } .downloadBtn:focus, -.downloadBtn:hover -{ - outline:none; +.downloadBtn:hover { background-color:#f2084a; - -webkit-transition: all 0.1s ease-in; - -moz-transition: all 0.1s ease-in; - -o-transition: all 0.1s ease-in; + outline:none; + -webkit-transition: all 0.1s ease-in; + -moz-transition: all 0.1s ease-in; + -o-transition: all 0.1s ease-in; } .downloadBtn::-moz-focus-inner { @@ -197,22 +190,21 @@ margin-top:8px; } .URLinput{ - position:relative; background-color:#fff; border: 3px solid #a5a5a5; - color:#3F3F3F; border-radius:10px; - padding: 12px 12px 12px 12px; - min-width:426px; - font-size:24px; + color:#3F3F3F; font-weight:800; margin-right:8px; + min-width:426px; + padding: 12px 12px 12px 12px; + position:relative; } .URLinput:focus { - outline: none; border-color:#3A3A3A; + outline: none; } .URLinput:-webkit-input-placeholder{ @@ -223,176 +215,163 @@ margin-top:8px; } .combatiblelink { -position:relative; -color:#a5a5a5; -font-size:13px; -z-index:10; -text-decoration:none; -background-image:url('../img/compatiblerouage.png'); -background-position:0 100%; -background-repeat:no-repeat; -padding-left:41px; -padding-top:10px; -padding-bottom:10px; - -webkit-transition: all 0.1s ease-in; - -moz-transition: all 0.1s ease-in; - -o-transition: all 0.1s ease-in; + background-image:url('../img/compatiblerouage.png'); + background-position:0 100%; + background-repeat:no-repeat; + color:#a5a5a5; + padding-bottom:10px; + padding-left:41px; + padding-top:10px; + position:relative; + text-decoration:none; + -webkit-transition: all 0.1s ease-in; + -moz-transition: all 0.1s ease-in; + -o-transition: all 0.1s ease-in; + z-index:10; } .combatiblelink:focus, -.combatiblelink:hover -{ +.combatiblelink:hover { + background-position:0 0; + color:#f2084a; outline:none; -background-position:0 0; -color:#f2084a; - -webkit-transition: all 0.1s ease-in; - -moz-transition: all 0.1s ease-in; - -o-transition: all 0.1s ease-in; + -webkit-transition: all 0.1s ease-in; + -moz-transition: all 0.1s ease-in; + -o-transition: all 0.1s ease-in; } -#bookmarklet{ -padding:15px; -} - -.bookmarklet{ -position:relative; -font-size:13px; -color:gray; -z-index:10; -text-decoration:none; -padding-left:30px; -padding-right:30px; -padding-top:10px; -padding-bottom:10px; -border: 2px dotted; -} - -.mp3 -{ +.bookmarklet { + border: 2px dotted; + color:gray; + padding:10px 30px; position:relative; + text-decoration:none; + z-index:10; +} + +.mp3 { background-color:#cecece; - color:#696969; border-radius:6px; - width:622px; - font-size:14px; + color:#696969; height:26px; margin-top:12px; + position:relative; text-align:left; - font-weight:300; + width:622px; } -.mp3 p -{ -padding:3px; +.mp3 p { + padding:3px; } - /* - Demo CSS code - */ +.audio:not(:checked), +.audio:checked { + left: -9999px; + position: absolute; +} +.audio:not(:checked) + label, +.audio:checked + label { + cursor: pointer; + line-height:22px; + padding-left: 82px; + position: relative; +} +.audio:not(:checked) + label:before, +.audio:checked + label:before, +.audio:not(:checked) + label:after, +.audio:checked + label:after { + content: ''; + position: absolute; +} +.audio:not(:checked) + label:before, +.audio:checked + label:before { + background: #ffffff; + border-radius: 6px; + height: 20px; + left:0; + top: -1px; + -webkit-transition: background-color .2s; + -moz-transition: background-color .2s; + -ms-transition: background-color .2s; + -o-transition: background-color .2s; + transition: background-color .2s; + width: 45px; +} +.audio:not(:checked) + label:after, +.audio:checked + label:after { + background: #3a3a3a; + border-radius: 6px; + height: 16px; + left: 2px; + top: 1px; + -webkit-transition: all .2s; + -moz-transition: all .2s; + -ms-transition: all .2s; + -o-transition: all .2s; + transition: all .2s; + width: 16px; +} - .audio:not(:checked), - .audio:checked { - position: absolute; - left: -9999px; - } - .audio:not(:checked) + label, - .audio:checked + label { - position: relative; - padding-left: 82px; - cursor: pointer; - line-height:22px; - } - .audio:not(:checked) + label:before, - .audio:checked + label:before, - .audio:not(:checked) + label:after, - .audio:checked + label:after { - content: ''; - position: absolute; - } - .audio:not(:checked) + label:before, - .audio:checked + label:before { - left:0; top: -1px; - width: 45px; height: 20px; - background: #ffffff; - border-radius: 6px; - -webkit-transition: background-color .2s; - -moz-transition: background-color .2s; - -ms-transition: background-color .2s; - -o-transition: background-color .2s; - transition: background-color .2s; - } - .audio:not(:checked) + label:after, - .audio:checked + label:after { - width: 16px; height: 16px; - -webkit-transition: all .2s; - -moz-transition: all .2s; - -ms-transition: all .2s; - -o-transition: all .2s; - transition: all .2s; - border-radius: 6px; - background: #3a3a3a; - top: 1px; left: 2px; - } +.audio:focus + label { + color:black; +} - .audio:focus + label { - color:black; - } +/* on checked */ +.audio:checked + label:before { + background:#f2084a; +} +.audio:checked + label:after { + background: #fff; + left: 27px; + top: 1px; +} - /* on checked */ - .audio:checked + label:before { - background:#f2084a; - } - .audio:checked + label:after { - background: #fff; - top: 1px; left: 27px; - } - - .audio:checked + label .ui, - .audio:not(:checked) + label .ui:before, - .audio:checked + label .ui:after { - position: absolute; - left: 3px; - width: 45px; - border-radius: 15px; - font-size: 11px; - font-weight: bold; - line-height: 17px; - height:20px; - -webkit-transition: all .2s; - -moz-transition: all .2s; - -ms-transition: all .2s; - -o-transition: all .2s; - transition: all .2s; - } - .audio:not(:checked) + label .ui:before { - content: "no"; - left: 0; - padding-left:23px; - padding-top:2px; - background-image:url('../img/mp3hover.png'); - background-repeat:no-repeat; - background-position:right top; - width:56px; - -webkit-transition: all .2s; - -moz-transition: all .2s; - -ms-transition: all .2s; - -o-transition: all .2s; - transition: all .2s; - } - .audio:checked + label .ui:after { - content: "yes"; - color: #fff; - background-image:url('../img/mp3.png'); - background-repeat:no-repeat; - background-position:right top; - width:73px; - -webkit-transition: all .2s; - -moz-transition: all .2s; - -ms-transition: all .2s; - -o-transition: all .2s; - transition: all .2s; - } +.audio:checked + label .ui, +.audio:not(:checked) + label .ui:before, +.audio:checked + label .ui:after { + border-radius: 15px; + font-size: 11px; + font-weight: bold; + height:20px; + left: 3px; + line-height: 17px; + position: absolute; + -webkit-transition: all .2s; + -moz-transition: all .2s; + -ms-transition: all .2s; + -o-transition: all .2s; + transition: all .2s; + width: 45px; +} +.audio:not(:checked) + label .ui:before { + background-image:url('../img/mp3hover.png'); + background-position:right top; + background-repeat:no-repeat; + content: "no"; + left: 0; + min-width:56px; + padding-left:23px; + padding-top:2px; + -webkit-transition: all .2s; + -moz-transition: all .2s; + -ms-transition: all .2s; + -o-transition: all .2s; + transition: all .2s; +} +.audio:checked + label .ui:after { + background-image:url('../img/mp3.png'); + background-position:right top; + background-repeat:no-repeat; + color: #fff; + content: "yes"; + -webkit-transition: all .2s; + -moz-transition: all .2s; + -ms-transition: all .2s; + -o-transition: all .2s; + transition: all .2s; + width:73px; +} @@ -410,120 +389,114 @@ padding:3px; width: 600px; } -.playlist-entry h3 { +.playlist-entry-title { margin-top: 0; } -.playlist-entry h3 a { +.playlist-entry-title a { text-decoration: none; } -.playlist-entry h3 a:hover { +.playlist-entry-title a:hover { text-decoration: underline; } .playlist-entry .downloadBtn { - font-size: 16px; border-width: 2px; + font-size: 16px; } -/*************************CONTENT COMPATIBLES****************************/ +/* Supported websites list */ -.logobis -{ -width:447px; -height:107px; -position:relative; -margin:0 auto 10px auto; +.logobis { + height:107px; + margin:0 auto 10px auto; + position:relative; + width:447px; } -.logocompatible -{ -width:447px; -height:107px; -background-image:url('../img/logocompatible.png'); -background-repeat:repeat-y; -background-position:0 0; - -webkit-transition: all 0.1s ease-in; - -moz-transition: all 0.1s ease-in; - -o-transition: all 0.1s ease-in; -display:block; +.logocompatible { + background-image:url('../img/logocompatible.png'); + background-position:0 0; + background-repeat:repeat-y; + display:block; + height:107px; + -webkit-transition: all 0.1s ease-in; + -moz-transition: all 0.1s ease-in; + -o-transition: all 0.1s ease-in; + width:447px; } .logocompatible:focus, .logocompatible:hover { - outline:none; background-position:0 100%; - -webkit-transition: all 0.1s ease-in; - -moz-transition: all 0.1s ease-in; - -o-transition: all 0.1s ease-in;} - - -.logocompatiblemask -{ -z-index:10; -position:absolute; -top:0; -left:0; -width:447px; -height:107px; -background-image:url('../img/logocompatiblemask.png'); -background-position:0 100%; -background-repeat:no-repeat; -} - -.titre -{ -font-family: 'Open Sans', sans-serif; -font-weight:300; -color:#383838; -font-size:48px; -} - -.tripleliste -{ -margin-top:80px; -width:800px; -position:relative; -margin-left:auto; -margin-right:auto; + outline:none; + -webkit-transition: all 0.1s ease-in; + -moz-transition: all 0.1s ease-in; + -o-transition: all 0.1s ease-in; } -.tripleliste ul -{ -margin-bottom:1em; -width:600px; -margin-left:120px;} +.logocompatiblemask { + background-image:url('../img/logocompatiblemask.png'); + background-position:0 100%; + background-repeat:no-repeat; + height:107px; + left:0; + position:absolute; + top:0; + width:447px; + z-index:10; +} -.tripleliste ul li -{text-align:left; -List-Style-Type:none; -color:#383838; -font-size:16px; +.titre { + color:#383838; + font-family: 'Open Sans', sans-serif; + font-size:48px; + font-weight:300; +} -width:200px; -float:left; -position:relative; +.tripleliste { + margin-left:auto; + margin-right:auto; + margin-top:80px; + position:relative; + width:800px; +} + + +.tripleliste ul { + margin-bottom:1em; + margin-left:120px; + width:600px; +} + +.tripleliste ul li { + color:#383838; + float:left; + list-style-type:none; + position:relative; + text-align:left; + width:200px; } html, body { - margin:0; height:100%; + margin:0; } .wrapper { - height:100%; - display:table; - margin:auto; - padding-bottom:110px; -moz-box-sizing: border-box; -webkit-box-sizing: border-box; box-sizing: border-box; + display:table; + height:100%; + margin:auto; + padding-bottom:110px; } .main { display:table-cell; @@ -595,6 +568,65 @@ h1 { font-family:monospace; } +.locales { + float: left; + padding-left: 1em; + padding-top: 1em; + text-align: left; +} + +.locales a, +.locales a:visited { + color: #696969; + text-decoration: none; +} + +.supportedLocales { + background-color: #fff; + list-style-type: none; + margin: 0; + opacity: 0; + padding-left: 0; + transition: visibility 0.5s; + visibility: hidden; +} + +.supportedLocales li { + border-bottom: thin solid #E1E1E1; +} + +.supportedLocales li:last-child { + border-bottom: none; +} + +.supportedLocales li a { + display: block; + padding: 1em; + padding-right: 2em; +} + +.supportedLocales li:hover { + background-color: #cecece; +} + +.localesBtn { + background-color: transparent; + border: none; + cursor: pointer; + display: inline-block; + padding: 1em; +} + +.localesBtn:focus { + background-color: #fff; + pointer-events: none; +} + +.localesBtn:focus + .supportedLocales { + opacity: 1; + visibility: visible; +} + @media (max-width: 640px) { .formats, .thumb { @@ -619,9 +651,9 @@ h1 { .champs, .URLinput, .mp3 { - width:90%; - margin:auto; height:auto; + margin:auto; + width:90%; } .logo { @@ -629,8 +661,8 @@ h1 { } .logocompatible img { - width:100%; height: auto; + width:100%; } .downloadBtn { @@ -646,9 +678,9 @@ h1 { .tripleliste ul, .tripleliste { - width:auto; margin-left:auto; margin-top:auto; + width:auto; } .logocompatiblemask { @@ -656,9 +688,9 @@ h1 { } .logocompatible { - height:auto; - background-image:none; background-color:#4F4F4F; + background-image:none; + height:auto; } .logocompatiblemask, diff --git a/i18n/fr_FR/LC_MESSAGES/Alltube.po b/i18n/fr_FR/LC_MESSAGES/Alltube.po new file mode 100644 index 0000000..8fcb988 --- /dev/null +++ b/i18n/fr_FR/LC_MESSAGES/Alltube.po @@ -0,0 +1,134 @@ +msgid "" +msgstr "" +"Project-Id-Version: \n" +"POT-Creation-Date: \n" +"PO-Revision-Date: \n" +"Last-Translator: Pierre Rudloff \n" +"Language-Team: \n" +"Language: fr_FR\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Generator: Poedit 1.6.10\n" +"Plural-Forms: nplurals=2; plural=(n > 1);\n" + +#: templates/error.tpl:5 +msgid "An error occured" +msgstr "Une erreur est survenue" + +#: templates/error.tpl:6 +msgid "Please check the URL of your video." +msgstr "Veuillez vérifier l'URL de votre vidéo" + +#: templates/playlist.tpl:5 +msgid "Videos extracted from" +msgstr "Vidéos extraites depuis" + +#: templates/playlist.tpl:7 +msgid ":" +msgstr " :" + +#: templates/playlist.tpl:26 templates/password.tpl:10 templates/video.tpl:85 +#: templates/video.tpl:88 templates/index.tpl:18 +msgid "Download" +msgstr "Télécharger" + +#: templates/playlist.tpl:27 +msgid "More options" +msgstr "Plus d'options" + +#: templates/password.tpl:5 +msgid "This video is protected" +msgstr "Cette vidéo est protégée" + +#: templates/password.tpl:6 +msgid "You need a password in order to download this video." +msgstr "L'accès à cette vidéo nécessite un mot de passe." + +#: templates/password.tpl:8 +msgid "Video password" +msgstr "Mot de passe de la vidéo" + +#: templates/extractors.tpl:4 +msgid "Supported websites" +msgstr "Sites web supportés" + +#: templates/video.tpl:6 +msgid "You are going to download" +msgstr "Vous allez télécharger" + +#: templates/video.tpl:26 +msgid "Available formats:" +msgstr "Formats disponibles :" + +#: templates/video.tpl:31 +msgid "Generic formats" +msgstr "Formats génériques" + +#: templates/video.tpl:34 +msgid "Best" +msgstr "Meilleure qualité" + +#: templates/video.tpl:39 +msgid "Remux best video with best audio" +msgstr "Combiner la meilleure vidéo avec le meilleur audio" + +#: templates/video.tpl:43 +msgid "Worst" +msgstr "Pire qualité" + +#: templates/video.tpl:46 +msgid "Detailed formats" +msgstr "Formats détaillés" + +#: templates/inc/footer.tpl:4 +msgid "Code by" +msgstr "Développé par" + +#: templates/inc/footer.tpl:6 +msgid "Design by" +msgstr "Designé par" + +#: templates/inc/footer.tpl:12 +msgid "AllTube Download on Facebook" +msgstr "AllTube Download sur Facebook" + +#: templates/inc/footer.tpl:12 +msgid "Like us on Facebook" +msgstr "Suivez-nous sur Facebook" + +#: templates/inc/footer.tpl:14 +msgid "Get the code" +msgstr "Obtenir le code" + +#: templates/inc/footer.tpl:16 +msgid "Based on" +msgstr "Basé sur" + +#: templates/inc/header.tpl:4 +msgid "Share on Twitter" +msgstr "Partager sur Twitter" + +#: templates/inc/header.tpl:5 +msgid "Share on Facebook" +msgstr "Partager sur Facebook" + +#: templates/index.tpl:8 +msgid "Copy here the URL of your video (Youtube, Dailymotion, etc.)" +msgstr "Copiez ici l'URL de votre vidéo (Youtube, Dailymotion, etc.)" + +#: templates/index.tpl:23 +msgid "Audio only (MP3)" +msgstr "Audio uniquement (MP3)" + +#: templates/index.tpl:28 +msgid "See all supported websites" +msgstr "Voir tous les sites supportés" + +#: templates/index.tpl:30 +msgid "Drag this to your bookmarks bar:" +msgstr "Glissez ce lien dans votre barre de favoris :" + +#: templates/index.tpl:31 +msgid "Bookmarklet" +msgstr "Bookmarklet" diff --git a/i18n/template.pot b/i18n/template.pot new file mode 100644 index 0000000..7db980d --- /dev/null +++ b/i18n/template.pot @@ -0,0 +1,123 @@ +msgid "" +msgstr "Content-Type: text/plain; charset=UTF-8\n" + +#: templates/error.tpl:5 +msgid "An error occured" +msgstr "" + +#: templates/error.tpl:6 +msgid "Please check the URL of your video." +msgstr "" + +#: templates/playlist.tpl:5 +msgid "Videos extracted from" +msgstr "" + +#: templates/playlist.tpl:7 +msgid ":" +msgstr "" + +#: templates/playlist.tpl:26 templates/password.tpl:10 templates/video.tpl:85 +#: templates/video.tpl:88 templates/index.tpl:18 +msgid "Download" +msgstr "" + +#: templates/playlist.tpl:27 +msgid "More options" +msgstr "" + +#: templates/password.tpl:5 +msgid "This video is protected" +msgstr "" + +#: templates/password.tpl:6 +msgid "You need a password in order to download this video." +msgstr "" + +#: templates/password.tpl:8 +msgid "Video password" +msgstr "" + +#: templates/extractors.tpl:4 +msgid "Supported websites" +msgstr "" + +#: templates/video.tpl:6 +msgid "You are going to download" +msgstr "" + +#: templates/video.tpl:26 +msgid "Available formats:" +msgstr "" + +#: templates/video.tpl:31 +msgid "Generic formats" +msgstr "" + +#: templates/video.tpl:34 +msgid "Best" +msgstr "" + +#: templates/video.tpl:39 +msgid "Remux best video with best audio" +msgstr "" + +#: templates/video.tpl:43 +msgid "Worst" +msgstr "" + +#: templates/video.tpl:46 +msgid "Detailed formats" +msgstr "" + +#: templates/inc/footer.tpl:4 +msgid "Code by" +msgstr "" + +#: templates/inc/footer.tpl:6 +msgid "Design by" +msgstr "" + +#: templates/inc/footer.tpl:12 +msgid "AllTube Download on Facebook" +msgstr "" + +#: templates/inc/footer.tpl:12 +msgid "Like us on Facebook" +msgstr "" + +#: templates/inc/footer.tpl:14 +msgid "Get the code" +msgstr "" + +#: templates/inc/footer.tpl:16 +msgid "Based on" +msgstr "" + +#: templates/inc/header.tpl:4 +msgid "Share on Twitter" +msgstr "" + +#: templates/inc/header.tpl:5 +msgid "Share on Facebook" +msgstr "" + +#: templates/index.tpl:8 +msgid "Copy here the URL of your video (Youtube, Dailymotion, etc.)" +msgstr "" + +#: templates/index.tpl:23 +msgid "Audio only (MP3)" +msgstr "" + +#: templates/index.tpl:28 +msgid "See all supported websites" +msgstr "" + +#: templates/index.tpl:30 +msgid "Drag this to your bookmarks bar:" +msgstr "" + +#: templates/index.tpl:31 +msgid "Bookmarklet" +msgstr "" diff --git a/i18n/zh_CN/LC_MESSAGES/Alltube.po b/i18n/zh_CN/LC_MESSAGES/Alltube.po new file mode 100644 index 0000000..d0bc3e0 --- /dev/null +++ b/i18n/zh_CN/LC_MESSAGES/Alltube.po @@ -0,0 +1,135 @@ +msgid "" +msgstr "" +"Project-Id-Version: \n" +"POT-Creation-Date: \n" +"PO-Revision-Date: \n" +"Last-Translator: Shiqiang Yu \n" +"Language-Team: \n" +"Language: zh_CN\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Generator: Poedit 2.0.2\n" +"Plural-Forms: nplurals=1; plural=0;\n" + +#: ..\..\..\templates/error.tpl:5 +msgid "An error occured" +msgstr "出错了" + +#: ..\..\..\templates/error.tpl:6 +msgid "Please check the URL of your video." +msgstr "请检查您的视频的 URL。" + +#: ..\..\..\templates/extractors.tpl:4 +msgid "Supported websites" +msgstr "支持的网站" + +#: ..\..\..\templates/inc/footer.tpl:4 +msgid "Code by" +msgstr "代码来自" + +#: ..\..\..\templates/inc/footer.tpl:6 +msgid "Design by" +msgstr "设计来自" + +#: ..\..\..\templates/inc/footer.tpl:12 +msgid "AllTube Download on Facebook" +msgstr "去Alltube Download的Facebook页面" + +#: ..\..\..\templates/inc/footer.tpl:12 +msgid "Like us on Facebook" +msgstr "在Facebook关注我们" + +#: ..\..\..\templates/inc/footer.tpl:14 +msgid "Get the code" +msgstr "获取代码" + +#: ..\..\..\templates/inc/footer.tpl:16 +msgid "Based on" +msgstr "基于" + +#: ..\..\..\templates/inc/header.tpl:4 +msgid "Share on Twitter" +msgstr "分享到 Twitter" + +#: ..\..\..\templates/inc/header.tpl:5 +msgid "Share on Facebook" +msgstr "分享到 Facebook" + +#: ..\..\..\templates/index.tpl:9 +msgid "Copy here the URL of your video (Youtube, Dailymotion, etc.)" +msgstr "在这里复制您的视频 (Youtube、 Dailymotion 等) 的 URL" + +#: ..\..\..\templates/index.tpl:19 ..\..\..\templates/password.tpl:10 +#: ..\..\..\templates/playlist.tpl:23 ..\..\..\templates/video.tpl:85 +#: ..\..\..\templates/video.tpl:90 +msgid "Download" +msgstr "下载" + +#: ..\..\..\templates/index.tpl:24 +msgid "Audio only (MP3)" +msgstr "仅限音频(mp3)" + +#: ..\..\..\templates/index.tpl:29 +msgid "See all supported websites" +msgstr "请参阅支持的所有网站" + +#: ..\..\..\templates/index.tpl:31 +msgid "Drag this to your bookmarks bar:" +msgstr "把这个拖到你的书签:" + +#: ..\..\..\templates/index.tpl:32 +msgid "Bookmarklet" +msgstr "书签工具" + +#: ..\..\..\templates/password.tpl:5 +msgid "This video is protected" +msgstr "这个视频受保护" + +#: ..\..\..\templates/password.tpl:6 +msgid "You need a password in order to download this video." +msgstr "你需要密码才能下载这个视频。" + +#: ..\..\..\templates/password.tpl:8 +msgid "Video password" +msgstr "视频密码" + +#: ..\..\..\templates/playlist.tpl:5 +msgid "Videos extracted from the" +msgstr "视频从" + +#: ..\..\..\templates/playlist.tpl:7 +msgid "playlist:" +msgstr "播放列表提取:" + +#: ..\..\..\templates/playlist.tpl:24 +msgid "More options" +msgstr "更多选项" + +#: ..\..\..\templates/video.tpl:6 +msgid "You are going to download" +msgstr "你即将下载" + +#: ..\..\..\templates/video.tpl:24 +msgid "Available formats:" +msgstr "可用的格式︰" + +#: ..\..\..\templates/video.tpl:31 +msgid "Generic formats" +msgstr "通用格式" + +#: ..\..\..\templates/video.tpl:34 +msgid "Best" +msgstr "最佳" + +#: ..\..\..\templates/video.tpl:39 +msgid "Remux best video with best audio" +msgstr "重新封装最佳视频与最佳音频" + +#: ..\..\..\templates/video.tpl:43 +msgid "Worst" +msgstr "最差" + +#: ..\..\..\templates/video.tpl:46 +msgid "Detailed formats" +msgstr "详细格式" diff --git a/index.php b/index.php index 0bb2c6e..89d76e9 100644 --- a/index.php +++ b/index.php @@ -3,6 +3,9 @@ require_once __DIR__.'/vendor/autoload.php'; use Alltube\Config; use Alltube\Controller\FrontController; +use Alltube\LocaleManager; +use Alltube\LocaleMiddleware; +use Alltube\PlaylistArchiveStream; use Alltube\UglyRouter; use Alltube\ViewFactory; use Slim\App; @@ -12,6 +15,8 @@ if (isset($_SERVER['REQUEST_URI']) && strpos($_SERVER['REQUEST_URI'], '/index.ph die; } +stream_wrapper_register('playlist', PlaylistArchiveStream::class); + $app = new App(); $container = $app->getContainer(); $config = Config::getInstance(); @@ -19,6 +24,8 @@ if ($config->uglyUrls) { $container['router'] = new UglyRouter(); } $container['view'] = ViewFactory::create($container); +$container['locale'] = new LocaleManager($_COOKIE); +$app->add(new LocaleMiddleware($container)); $controller = new FrontController($container, null, $_COOKIE); @@ -40,4 +47,8 @@ $app->get( '/redirect', [$controller, 'redirect'] )->setName('redirect'); +$app->get( + '/locale/{locale}', + [$controller, 'locale'] +)->setName('locale'); $app->run(); diff --git a/js/cast.js b/js/cast.js index 0cc0bd3..f693a92 100644 --- a/js/cast.js +++ b/js/cast.js @@ -33,10 +33,10 @@ var castModule = (function () { function sessionListener(e) { session = e; - session.addMediaListener(onMediaDiscovered.bind(this, 'addMediaListener')); - session.addUpdateListener(updateListener.bind(this)); + session.addMediaListener(onMediaDiscovered); + session.addUpdateListener(updateListener); if (session.media.length !== 0) { - onMediaDiscovered('onRequestSessionSuccess', session.media[0]); + onMediaDiscovered(); } } @@ -52,7 +52,7 @@ var castModule = (function () { function onRequestSessionSuccess(e) { session = e; var videoLink = document.getElementById('video_link'), videoURL = videoLink.dataset.video, mediaInfo = new chrome.cast.media.MediaInfo(videoURL, 'video/' + videoLink.dataset.ext), request = new chrome.cast.media.LoadRequest(mediaInfo); - session.loadMedia(request, onMediaDiscovered.bind(this, 'loadMedia'), onMediaError); + session.loadMedia(request, onMediaDiscovered, onMediaError); } function onLaunchError(e) { @@ -80,7 +80,8 @@ var castModule = (function () { } function initializeCastApi() { - var sessionRequest = new chrome.cast.SessionRequest(chrome.cast.media.DEFAULT_MEDIA_RECEIVER_APP_ID), apiConfig = new chrome.cast.ApiConfig(sessionRequest, sessionListener, receiverListener, chrome.cast.AutoJoinPolicy.ORIGIN_SCOPED); + var sessionRequest = new chrome.cast.SessionRequest(chrome.cast.media.DEFAULT_MEDIA_RECEIVER_APP_ID), + apiConfig = new chrome.cast.ApiConfig(sessionRequest, sessionListener, receiverListener, chrome.cast.AutoJoinPolicy.ORIGIN_SCOPED); chrome.cast.initialize(apiConfig, onInitSuccess, onError); } @@ -103,4 +104,6 @@ var castModule = (function () { }; }()); -window.addEventListener('load', castModule.init, false); +if (typeof window === 'object') { + window.addEventListener('load', castModule.init, false); +} diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..71c775c --- /dev/null +++ b/package-lock.json @@ -0,0 +1,1603 @@ +{ + "name": "alltube", + "version": "0.9.0", + "lockfileVersion": 1, + "dependencies": { + "abbrev": { + "version": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.0.tgz", + "integrity": "sha1-0FVMIlZjbi9W58LlrRg/hZQo2B8=" + }, + "ajv": { + "version": "4.11.8", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-4.11.8.tgz", + "integrity": "sha1-gv+wKynmYq5TvcIK8VlHcGc5xTY=", + "dev": true, + "optional": true + }, + "alce": { + "version": "https://registry.npmjs.org/alce/-/alce-1.0.0.tgz", + "integrity": "sha1-QmGEyY7iiNDurHf9Y/7WgLZnyrY=", + "dev": true, + "dependencies": { + "esprima": { + "version": "https://registry.npmjs.org/esprima/-/esprima-1.0.4.tgz", + "integrity": "sha1-n1V+CPw7TSbs6d00+Pv0drYlha0=", + "dev": true + } + } + }, + "ansi-regex": { + "version": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=" + }, + "ansi-styles": { + "version": "file:node_shrinkwrap/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=" + }, + "aproba": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.1.1.tgz", + "integrity": "sha1-ldNgDwdxCqDpKYxyatXs8urLq6s=", + "dev": true, + "optional": true + }, + "archiver": { + "version": "https://registry.npmjs.org/archiver/-/archiver-1.3.0.tgz", + "integrity": "sha1-TyGU1tj5nfP1MeaIHxTxXVX6ryI=", + "dev": true, + "dependencies": { + "async": { + "version": "https://registry.npmjs.org/async/-/async-2.4.1.tgz", + "integrity": "sha1-YqVrJ5yYoR0JhwlqAcw+6463u9c=", + "dev": true + }, + "lodash": { + "version": "https://registry.npmjs.org/lodash/-/lodash-4.17.4.tgz", + "integrity": "sha1-eCA6TRwyiuHYbcpkYONptX9AVa4=", + "dev": true + } + } + }, + "archiver-utils": { + "version": "https://registry.npmjs.org/archiver-utils/-/archiver-utils-1.3.0.tgz", + "integrity": "sha1-5QtMCccL89aA4y/xt5lOn52JUXQ=", + "dev": true, + "dependencies": { + "lodash": { + "version": "https://registry.npmjs.org/lodash/-/lodash-4.17.4.tgz", + "integrity": "sha1-eCA6TRwyiuHYbcpkYONptX9AVa4=", + "dev": true + } + } + }, + "are-we-there-yet": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.4.tgz", + "integrity": "sha1-u13KOCu5TwXhUZQ3PRb9O6HKEQ0=", + "dev": true, + "optional": true + }, + "argparse": { + "version": "https://registry.npmjs.org/argparse/-/argparse-1.0.9.tgz", + "integrity": "sha1-c9g7wmP4bpf4zE9rrhsOkKfSLIY=" + }, + "array-find-index": { + "version": "https://registry.npmjs.org/array-find-index/-/array-find-index-1.0.2.tgz", + "integrity": "sha1-3wEKoSh+Fku9pvlyOwqWoexBh6E=" + }, + "asn1": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.3.tgz", + "integrity": "sha1-2sh4dxPJlmhJ/IGAd36+nB3fO4Y=", + "dev": true, + "optional": true + }, + "assert-plus": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-0.2.0.tgz", + "integrity": "sha1-104bh+ev/A24qttwIfP+SBAasjQ=", + "dev": true, + "optional": true + }, + "async": { + "version": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", + "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=" + }, + "asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=", + "dev": true, + "optional": true + }, + "aws-sign2": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.6.0.tgz", + "integrity": "sha1-FDQt0428yU0OW4fXY81jYSwOeU8=", + "dev": true, + "optional": true + }, + "aws4": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.6.0.tgz", + "integrity": "sha1-g+9cqGCysy5KDe7e6MdxudtXRx4=", + "dev": true, + "optional": true + }, + "balanced-match": { + "version": "file:node_shrinkwrap/balanced-match-0.4.2.tgz", + "integrity": "sha1-yz8+PHMtwPAe5wtAPzAuYddwmDg=" + }, + "bcrypt-pbkdf": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.1.tgz", + "integrity": "sha1-Y7xdy2EzG5K8Bf1SiVPDNGKgb40=", + "dev": true, + "optional": true + }, + "bl": { + "version": "https://registry.npmjs.org/bl/-/bl-1.2.1.tgz", + "integrity": "sha1-ysMo977kVzDUBLaSID/LWQ4XLV4=", + "dev": true + }, + "block-stream": { + "version": "0.0.9", + "resolved": "https://registry.npmjs.org/block-stream/-/block-stream-0.0.9.tgz", + "integrity": "sha1-E+v+d4oDIFz+A3UUgeu0szAMEmo=", + "dev": true + }, + "bluebird": { + "version": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.0.tgz", + "integrity": "sha1-eRQg1/VR7qKJdFOop3ZT+WYG1nw=", + "dev": true + }, + "body-parser": { + "version": "https://registry.npmjs.org/body-parser/-/body-parser-1.14.2.tgz", + "integrity": "sha1-EBXLH+LEQ4WCWVgdtTMy+NDPUPk=", + "dev": true, + "dependencies": { + "iconv-lite": { + "version": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.13.tgz", + "integrity": "sha1-H4irpKsLFQjoMSrMOTRfNumS4vI=", + "dev": true + }, + "qs": { + "version": "https://registry.npmjs.org/qs/-/qs-5.2.0.tgz", + "integrity": "sha1-qfMRQq9GjLcrJbMBNrokVoNJFr4=", + "dev": true + } + } + }, + "boom": { + "version": "2.10.1", + "resolved": "https://registry.npmjs.org/boom/-/boom-2.10.1.tgz", + "integrity": "sha1-OciRjO/1eZ+D+UkqhI9iWt0Mdm8=", + "dev": true + }, + "bower": { + "version": "https://registry.npmjs.org/bower/-/bower-1.8.0.tgz", + "integrity": "sha1-Vdvr7wrZFVOC2enT5JfBNyNFtEo=" + }, + "brace-expansion": { + "version": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.7.tgz", + "integrity": "sha1-Pv/DxQ4ABTH7cg6v+A8K6O8jz1k=" + }, + "browserify-zlib": { + "version": "file:node_shrinkwrap/browserify-zlib-0.1.4.tgz", + "integrity": "sha1-uzX4pRn2AOD6a4SFJByXnQFB+y0=" + }, + "buffer-crc32": { + "version": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", + "integrity": "sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI=", + "dev": true + }, + "buffer-shims": { + "version": "file:node_shrinkwrap/buffer-shims-1.0.0.tgz", + "integrity": "sha1-mXjOMXOIxkmth5MCjDR37wRKi1E=" + }, + "builtin-modules": { + "version": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz", + "integrity": "sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8=" + }, + "bytes": { + "version": "https://registry.npmjs.org/bytes/-/bytes-2.2.0.tgz", + "integrity": "sha1-/TVGSkA/b5EXwt42Cez/nK4ABYg=", + "dev": true + }, + "camelcase": { + "version": "https://registry.npmjs.org/camelcase/-/camelcase-2.1.1.tgz", + "integrity": "sha1-fB0W1nmhu+WcoCys7PsBHiAfWh8=" + }, + "camelcase-keys": { + "version": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-2.1.0.tgz", + "integrity": "sha1-MIvur/3ygRkFHvodkyITyRuPkuc=" + }, + "caseless": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", + "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=", + "dev": true, + "optional": true + }, + "chalk": { + "version": "file:node_shrinkwrap/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=" + }, + "clean-css": { + "version": "https://registry.npmjs.org/clean-css/-/clean-css-4.1.3.tgz", + "integrity": "sha1-B8/omA7bINRV3cI6rc8eBMblCc4=" + }, + "clone": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.1.tgz", + "integrity": "sha1-0hfR6WERjjrJpLi7oyhVU79kfNs=" + }, + "co": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", + "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=", + "dev": true, + "optional": true + }, + "code-point-at": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", + "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=", + "dev": true + }, + "coffee-script": { + "version": "https://registry.npmjs.org/coffee-script/-/coffee-script-1.10.0.tgz", + "integrity": "sha1-EpOLz5vhlI+gBvkuDEyegXBRCMA=" + }, + "colors": { + "version": "https://registry.npmjs.org/colors/-/colors-1.1.2.tgz", + "integrity": "sha1-FopHAXVran9RoSzgyXv6KMCE7WM=" + }, + "combined-stream": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.5.tgz", + "integrity": "sha1-k4NwpXtKUd6ix3wV1cX9+JUWQAk=", + "dev": true + }, + "commander": { + "version": "file:node_shrinkwrap/commander-2.9.0.tgz", + "integrity": "sha1-nJkJQXbhIkDLItbFFGCYQA/g99Q=" + }, + "compress-commons": { + "version": "https://registry.npmjs.org/compress-commons/-/compress-commons-1.2.0.tgz", + "integrity": "sha1-WFhwku8g03y1i68AARLJJ4/3O58=", + "dev": true + }, + "concat-map": { + "version": "file:node_shrinkwrap/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" + }, + "concat-stream": { + "version": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.0.tgz", + "integrity": "sha1-CqxmL9Ur54lk1VMvaUeE5wEQrPc=" + }, + "console-control-strings": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", + "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=", + "dev": true + }, + "content-type": { + "version": "https://registry.npmjs.org/content-type/-/content-type-1.0.2.tgz", + "integrity": "sha1-t9ETrueo3Se9IRM8TcJSnfFyHu0=", + "dev": true + }, + "core-util-is": { + "version": "file:node_shrinkwrap/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" + }, + "crc": { + "version": "https://registry.npmjs.org/crc/-/crc-3.4.4.tgz", + "integrity": "sha1-naHpgOO9RPxck79as9ozeNheRms=", + "dev": true + }, + "crc32-stream": { + "version": "https://registry.npmjs.org/crc32-stream/-/crc32-stream-2.0.0.tgz", + "integrity": "sha1-483TtN8xaN10494/u8t7KX/pCPQ=", + "dev": true + }, + "cryptiles": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/cryptiles/-/cryptiles-2.0.5.tgz", + "integrity": "sha1-O9/s3GCBR8HGcgL6KR59ylnqo7g=", + "dev": true, + "optional": true + }, + "csslint": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/csslint/-/csslint-1.0.5.tgz", + "integrity": "sha1-Gcw+2jIhYP0/cjKvHLKjYOiYouk=" + }, + "currently-unhandled": { + "version": "https://registry.npmjs.org/currently-unhandled/-/currently-unhandled-0.4.1.tgz", + "integrity": "sha1-mI3zP+qxke95mmE2nddsF635V+o=" + }, + "dashdash": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", + "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", + "dev": true, + "optional": true, + "dependencies": { + "assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", + "dev": true, + "optional": true + } + } + }, + "dateformat": { + "version": "https://registry.npmjs.org/dateformat/-/dateformat-1.0.12.tgz", + "integrity": "sha1-nxJLZ1lMk3/3BpMuSmQsyo27/uk=" + }, + "debug": { + "version": "file:node_shrinkwrap/debug-2.2.0.tgz", + "integrity": "sha1-+HBX6ZWxofauaklgZkE3vFbwOdo=", + "dev": true + }, + "decamelize": { + "version": "file:node_shrinkwrap/decamelize-1.2.0.tgz", + "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=" + }, + "deep-extend": { + "version": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.2.11.tgz", + "integrity": "sha1-eha6aXKRMjQFBhcElLyD9wdv4I8=", + "dev": true + }, + "delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", + "dev": true + }, + "delegates": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", + "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=", + "dev": true, + "optional": true + }, + "depd": { + "version": "https://registry.npmjs.org/depd/-/depd-1.1.0.tgz", + "integrity": "sha1-4b2Cxqq2ztlluXuIsX7T5SjKGMM=", + "dev": true + }, + "duplexer": { + "version": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.1.tgz", + "integrity": "sha1-rOb/gIwc5mtX0ev5eXessCM0z8E=" + }, + "ecc-jsbn": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.1.tgz", + "integrity": "sha1-D8c6ntXw1Tw4GTOYUj735UN3dQU=", + "dev": true, + "optional": true + }, + "ee-first": { + "version": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=", + "dev": true + }, + "end-of-stream": { + "version": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.0.tgz", + "integrity": "sha1-epDYM+/abPpurA9JSduw+tOmMgY=", + "dev": true + }, + "error-ex": { + "version": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.1.tgz", + "integrity": "sha1-+FWobOYa3E6GIcPNoh56dhLDqNw=" + }, + "escape-string-regexp": { + "version": "file:node_shrinkwrap/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=" + }, + "esprima": { + "version": "https://registry.npmjs.org/esprima/-/esprima-2.7.3.tgz", + "integrity": "sha1-luO3DVd59q1JzQMmc9HDEnZ7pYE=" + }, + "estraverse": { + "version": "https://registry.npmjs.org/estraverse/-/estraverse-1.3.2.tgz", + "integrity": "sha1-N8K4k+8T1yPydth41g2FNRUqbEI=", + "dev": true + }, + "eventemitter2": { + "version": "https://registry.npmjs.org/eventemitter2/-/eventemitter2-0.4.14.tgz", + "integrity": "sha1-j2G3XN4BKy6esoTUVFWDtWQ7Yas=" + }, + "exit": { + "version": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", + "integrity": "sha1-BjJjj42HfMghB9MKD/8aF8uhzQw=" + }, + "extend": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.1.tgz", + "integrity": "sha1-p1Xqe8Gt/MWjHOfnYtuq3F5jZEQ=", + "dev": true, + "optional": true + }, + "extend-object": { + "version": "https://registry.npmjs.org/extend-object/-/extend-object-1.0.0.tgz", + "integrity": "sha1-QlFPhAFdE1bK9Rh5ad+yvBvaCCM=", + "dev": true + }, + "extsprintf": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.0.2.tgz", + "integrity": "sha1-4QgOBljjALBilJkMxw4VAiNf1VA=", + "dev": true + }, + "faye-websocket": { + "version": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.10.0.tgz", + "integrity": "sha1-TkkvjQTftviQA1B/btvy1QHnxvQ=", + "dev": true + }, + "figures": { + "version": "file:node_shrinkwrap/figures-1.7.0.tgz", + "integrity": "sha1-y+Hjr/zxzUS4DK3+0o3Hk6lwHS4=" + }, + "find-up": { + "version": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", + "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=" + }, + "findup-sync": { + "version": "https://registry.npmjs.org/findup-sync/-/findup-sync-0.3.0.tgz", + "integrity": "sha1-N5MKpdgWt3fANEXhlmzGeQpMCxY=", + "dependencies": { + "glob": { + "version": "file:node_shrinkwrap/glob-5.0.15.tgz", + "integrity": "sha1-G8k2ueAvSmA/zCIuz3Yz0wuLk7E=" + } + } + }, + "fixpack": { + "version": "https://registry.npmjs.org/fixpack/-/fixpack-2.3.1.tgz", + "integrity": "sha1-U/A9iKq31RIyWSgvAIipo7GYNsI=", + "dev": true + }, + "forever-agent": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", + "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=", + "dev": true, + "optional": true + }, + "form-data": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.1.4.tgz", + "integrity": "sha1-M8GDrPGTJ27KqYFDpp6Uv+4XUNE=", + "dev": true, + "optional": true + }, + "fs.realpath": { + "version": "file:node_shrinkwrap/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" + }, + "fstream": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/fstream/-/fstream-1.0.11.tgz", + "integrity": "sha1-XB+x8RdHcRTwYyoOtLcbPLD9MXE=", + "dev": true + }, + "fstream-ignore": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/fstream-ignore/-/fstream-ignore-1.0.5.tgz", + "integrity": "sha1-nDHa40dnAY/h0kmyTa2mfQktoQU=", + "dev": true, + "optional": true + }, + "gauge": { + "version": "2.7.4", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", + "integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=", + "dev": true, + "optional": true + }, + "gaze": { + "version": "https://registry.npmjs.org/gaze/-/gaze-1.1.2.tgz", + "integrity": "sha1-hHIkZ3rbiHDWeSV+0ziP22HkAQU=", + "dev": true + }, + "get-stdin": { + "version": "https://registry.npmjs.org/get-stdin/-/get-stdin-4.0.1.tgz", + "integrity": "sha1-uWjGsKBDhDJJAui/Gl3zJXmkUP4=" + }, + "getobject": { + "version": "https://registry.npmjs.org/getobject/-/getobject-0.1.0.tgz", + "integrity": "sha1-BHpEl4n6Fg0Bj1SG7ZEyC27HiFw=" + }, + "getpass": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", + "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", + "dev": true, + "optional": true, + "dependencies": { + "assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", + "dev": true, + "optional": true + } + } + }, + "git-rev-2": { + "version": "https://registry.npmjs.org/git-rev-2/-/git-rev-2-0.1.0.tgz", + "integrity": "sha1-dIFlqMhPsB6mdGf/Fas+N6zkBkw=", + "dev": true + }, + "glob": { + "version": "https://registry.npmjs.org/glob/-/glob-7.0.6.tgz", + "integrity": "sha1-IRuvr0nlJbjNkyYNFKsTYVKz9Xo=" + }, + "globule": { + "version": "https://registry.npmjs.org/globule/-/globule-1.1.0.tgz", + "integrity": "sha1-xJNS5NwYPYWJPuglOF65lLtt9F8=", + "dev": true, + "dependencies": { + "glob": { + "version": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", + "integrity": "sha1-wZyd+aAocC1nhhI4SmVSQExjbRU=", + "dev": true + }, + "lodash": { + "version": "https://registry.npmjs.org/lodash/-/lodash-4.16.6.tgz", + "integrity": "sha1-0iyaxmAojzhD4Wun0rXQbMon13c=", + "dev": true + } + } + }, + "graceful-fs": { + "version": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", + "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=" + }, + "graceful-readlink": { + "version": "file:node_shrinkwrap/graceful-readlink-1.0.1.tgz", + "integrity": "sha1-TK+tdrxi8C+gObL5Tpo906ORpyU=" + }, + "grunt": { + "version": "https://registry.npmjs.org/grunt/-/grunt-1.0.1.tgz", + "integrity": "sha1-6HeHZOlEsY8yuw8QuQeEdcnftWs=", + "dependencies": { + "grunt-cli": { + "version": "https://registry.npmjs.org/grunt-cli/-/grunt-cli-1.2.0.tgz", + "integrity": "sha1-VisRnrsGndtGSs4oRVAb6Xs1tqg=" + } + } + }, + "grunt-contrib-compress": { + "version": "https://registry.npmjs.org/grunt-contrib-compress/-/grunt-contrib-compress-1.4.3.tgz", + "integrity": "sha1-Ac7/ucY39S5wgfRjdQmD0KOw+nM=", + "dev": true, + "dependencies": { + "lodash": { + "version": "https://registry.npmjs.org/lodash/-/lodash-4.17.4.tgz", + "integrity": "sha1-eCA6TRwyiuHYbcpkYONptX9AVa4=", + "dev": true + }, + "pretty-bytes": { + "version": "https://registry.npmjs.org/pretty-bytes/-/pretty-bytes-4.0.2.tgz", + "integrity": "sha1-sr+C5zUNZcbDOqlaqlpPYyf2HNk=", + "dev": true + } + } + }, + "grunt-contrib-csslint": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/grunt-contrib-csslint/-/grunt-contrib-csslint-2.0.0.tgz", + "integrity": "sha1-MSnZTf5Qc1fyMzfSSunpqkudV98=", + "dependencies": { + "lodash": { + "version": "4.17.4", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.4.tgz", + "integrity": "sha1-eCA6TRwyiuHYbcpkYONptX9AVa4=" + }, + "strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=" + } + } + }, + "grunt-contrib-cssmin": { + "version": "https://registry.npmjs.org/grunt-contrib-cssmin/-/grunt-contrib-cssmin-2.2.0.tgz", + "integrity": "sha1-ct70BijujiE62adoBNEx22ZgSkE=" + }, + "grunt-contrib-uglify": { + "version": "https://registry.npmjs.org/grunt-contrib-uglify/-/grunt-contrib-uglify-3.0.1.tgz", + "integrity": "sha1-/etfk4pMgEL46Grkb2NVTo6VEcs=", + "dependencies": { + "gzip-size": { + "version": "https://registry.npmjs.org/gzip-size/-/gzip-size-1.0.0.tgz", + "integrity": "sha1-Zs+LEBBHInuVus5uodoMF37Vwi8=" + }, + "maxmin": { + "version": "https://registry.npmjs.org/maxmin/-/maxmin-1.1.0.tgz", + "integrity": "sha1-cTZehKmd2Piz99X94vANHn9zvmE=" + }, + "pretty-bytes": { + "version": "https://registry.npmjs.org/pretty-bytes/-/pretty-bytes-1.0.4.tgz", + "integrity": "sha1-CiLoIQYJrTVUL4yNXSFZr/B1HIQ=" + } + } + }, + "grunt-contrib-watch": { + "version": "https://registry.npmjs.org/grunt-contrib-watch/-/grunt-contrib-watch-1.0.0.tgz", + "integrity": "sha1-hKGnodar0m7VaEE0lscxM+mQAY8=", + "dev": true + }, + "grunt-fixpack": { + "version": "https://registry.npmjs.org/grunt-fixpack/-/grunt-fixpack-0.1.0.tgz", + "integrity": "sha1-4pVT51NbPT/872ulVu1cloTMrOA=", + "dev": true + }, + "grunt-githash": { + "version": "https://registry.npmjs.org/grunt-githash/-/grunt-githash-0.1.3.tgz", + "integrity": "sha1-F8e8dRKbZ4+xh6T8/4NVLkBIm1Y=", + "dev": true + }, + "grunt-jslint": { + "version": "https://registry.npmjs.org/grunt-jslint/-/grunt-jslint-1.1.14.tgz", + "integrity": "sha1-gVKC6cAn8P4IN3Smoe2UHX53yeE=", + "dev": true + }, + "grunt-jsonlint": { + "version": "https://registry.npmjs.org/grunt-jsonlint/-/grunt-jsonlint-1.1.0.tgz", + "integrity": "sha1-ox7pckCu4/NDyiY8Rb1TIGMSfbI=", + "dev": true, + "dependencies": { + "strip-json-comments": { + "version": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", + "dev": true + } + } + }, + "grunt-known-options": { + "version": "https://registry.npmjs.org/grunt-known-options/-/grunt-known-options-1.1.0.tgz", + "integrity": "sha1-pCdO6zL6dl2lp6OxcSYXzjsUQUk=" + }, + "grunt-legacy-log": { + "version": "https://registry.npmjs.org/grunt-legacy-log/-/grunt-legacy-log-1.0.0.tgz", + "integrity": "sha1-+4bxgJhHvAfcR4Q/ns1srLYt8tU=" + }, + "grunt-legacy-log-utils": { + "version": "https://registry.npmjs.org/grunt-legacy-log-utils/-/grunt-legacy-log-utils-1.0.0.tgz", + "integrity": "sha1-p7ji0Ps1taUPSvmG/BEnSevJbz0=", + "dependencies": { + "lodash": { + "version": "https://registry.npmjs.org/lodash/-/lodash-4.3.0.tgz", + "integrity": "sha1-79nEpuxT87BUEkKZFcPkgk5NJaQ=" + } + } + }, + "grunt-legacy-util": { + "version": "https://registry.npmjs.org/grunt-legacy-util/-/grunt-legacy-util-1.0.0.tgz", + "integrity": "sha1-OGqnjcbtUJhsKxiVcmWxtIq7m4Y=", + "dependencies": { + "lodash": { + "version": "https://registry.npmjs.org/lodash/-/lodash-4.3.0.tgz", + "integrity": "sha1-79nEpuxT87BUEkKZFcPkgk5NJaQ=" + } + } + }, + "grunt-phpcs": { + "version": "https://registry.npmjs.org/grunt-phpcs/-/grunt-phpcs-0.4.0.tgz", + "integrity": "sha1-oI1iX8ZEZeRTsr2T+BCyqB6Uvao=", + "dev": true + }, + "grunt-phpdocumentor": { + "version": "https://registry.npmjs.org/grunt-phpdocumentor/-/grunt-phpdocumentor-0.4.1.tgz", + "integrity": "sha1-UTpc79iATUV5LqNd37yyRx4wcUE=", + "dev": true + }, + "grunt-phpunit": { + "version": "https://registry.npmjs.org/grunt-phpunit/-/grunt-phpunit-0.3.6.tgz", + "integrity": "sha1-DnW+5rXC5l/aRQdWcqBs6yzs2Gk=", + "dev": true + }, + "grunt-potomo": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/grunt-potomo/-/grunt-potomo-3.5.0.tgz", + "integrity": "sha1-WtjG9+djrVtRg55cbTI1gGLHN5U=" + }, + "gzip-size": { + "version": "https://registry.npmjs.org/gzip-size/-/gzip-size-3.0.0.tgz", + "integrity": "sha1-VGGI6b3DN/Zzdy+BZgRks4nc5SA=" + }, + "har-schema": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-1.0.5.tgz", + "integrity": "sha1-0mMTX0MwfALGAq/I/pWXDAFRNp4=", + "dev": true, + "optional": true + }, + "har-validator": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-4.2.1.tgz", + "integrity": "sha1-M0gdDxu/9gDdID11gSpqX7oALio=", + "dev": true, + "optional": true + }, + "has-ansi": { + "version": "file:node_shrinkwrap/has-ansi-2.0.0.tgz", + "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=" + }, + "has-color": { + "version": "file:node_shrinkwrap/has-color-0.1.7.tgz", + "integrity": "sha1-ZxRKUmDDT8PMpnfQQdr1L+e3iy8=", + "dev": true + }, + "has-unicode": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", + "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=", + "dev": true, + "optional": true + }, + "hawk": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/hawk/-/hawk-3.1.3.tgz", + "integrity": "sha1-B4REvXwWQLD+VA0sm3PVlnjo4cQ=", + "dev": true, + "optional": true + }, + "hoek": { + "version": "2.16.3", + "resolved": "https://registry.npmjs.org/hoek/-/hoek-2.16.3.tgz", + "integrity": "sha1-ILt0A9POo5jpHcRxCo/xuCdKJe0=", + "dev": true + }, + "hooker": { + "version": "https://registry.npmjs.org/hooker/-/hooker-0.2.3.tgz", + "integrity": "sha1-uDT3I8xKJCqmWWNFnfbZhMXT2Vk=" + }, + "hosted-git-info": { + "version": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.4.2.tgz", + "integrity": "sha1-AHa59GonBQbduq6lZJaJdGBhKmc=" + }, + "http-errors": { + "version": "https://registry.npmjs.org/http-errors/-/http-errors-1.3.1.tgz", + "integrity": "sha1-GX4izevUGYWF6GlO9nhhl7ke2UI=", + "dev": true + }, + "http-signature": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.1.1.tgz", + "integrity": "sha1-33LiZwZs0Kxn+3at+OE0qPvPkb8=", + "dev": true, + "optional": true + }, + "iconv-lite": { + "version": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.17.tgz", + "integrity": "sha1-T9qjs4rLwsAxsEXQ7c3+HsqxjI0=" + }, + "iltorb": { + "version": "https://registry.npmjs.org/iltorb/-/iltorb-1.3.0.tgz", + "integrity": "sha1-uasnEdf+fHSS42wDtukH399tpYw=", + "dev": true, + "optional": true + }, + "indent-string": { + "version": "https://registry.npmjs.org/indent-string/-/indent-string-2.1.0.tgz", + "integrity": "sha1-ji1INIdCEhtKghi3oTfppSBJ3IA=" + }, + "inflight": { + "version": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=" + }, + "inherits": { + "version": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" + }, + "ini": { + "version": "https://registry.npmjs.org/ini/-/ini-1.3.4.tgz", + "integrity": "sha1-BTfLedr1m1mhpRff9wbIbsA5Fi4=", + "dev": true + }, + "interpret": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.0.3.tgz", + "integrity": "sha1-y8NcYu7uc/Gat7EKgBURQBr8D5A=" + }, + "is-arrayish": { + "version": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=" + }, + "is-builtin-module": { + "version": "https://registry.npmjs.org/is-builtin-module/-/is-builtin-module-1.0.0.tgz", + "integrity": "sha1-VAVy0096wxGfj3bDDLwbHgN6/74=" + }, + "is-finite": { + "version": "https://registry.npmjs.org/is-finite/-/is-finite-1.0.2.tgz", + "integrity": "sha1-zGZ3aVYCvlUO8R6LSqYwU0K20Ko=" + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "dev": true + }, + "is-typedarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", + "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=", + "dev": true, + "optional": true + }, + "is-utf8": { + "version": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz", + "integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=" + }, + "isarray": { + "version": "file:node_shrinkwrap/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + }, + "isexe": { + "version": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=" + }, + "isstream": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", + "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=", + "dev": true, + "optional": true + }, + "jodid25519": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/jodid25519/-/jodid25519-1.0.2.tgz", + "integrity": "sha1-BtSRIlUJNBlHfUJWM2BuDpB4KWc=", + "dev": true, + "optional": true + }, + "js-yaml": { + "version": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.5.5.tgz", + "integrity": "sha1-A3fDgBfKvHMisNH7zSWkkWQfL74=" + }, + "jsbn": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", + "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=", + "dev": true, + "optional": true + }, + "jslint": { + "version": "https://registry.npmjs.org/jslint/-/jslint-0.8.1.tgz", + "integrity": "sha1-1EW1gmxlNmygYFufVD3OjVElrRA=", + "dev": true, + "dependencies": { + "glob": { + "version": "https://registry.npmjs.org/glob/-/glob-4.5.3.tgz", + "integrity": "sha1-xstz0yJsHv7wTePFbQEvAzd+4V8=", + "dev": true + }, + "isarray": { + "version": "file:node_shrinkwrap/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", + "dev": true + }, + "minimatch": { + "version": "file:node_shrinkwrap/minimatch-2.0.10.tgz", + "integrity": "sha1-jQh8OcazjAAbl/ynzm0OHoCvusc=", + "dev": true + }, + "readable-stream": { + "version": "file:node_shrinkwrap/readable-stream-1.0.34.tgz", + "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", + "dev": true + }, + "string_decoder": { + "version": "file:node_shrinkwrap/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", + "dev": true + } + } + }, + "json-schema": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", + "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=", + "dev": true, + "optional": true + }, + "json-stable-stringify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz", + "integrity": "sha1-mnWdOcXy/1A/1TAGRu1EX4jE+a8=", + "dev": true, + "optional": true + }, + "json-stringify-safe": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", + "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=", + "dev": true, + "optional": true + }, + "jsonify": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.0.tgz", + "integrity": "sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM=", + "dev": true, + "optional": true + }, + "jsonlint": { + "version": "https://registry.npmjs.org/jsonlint/-/jsonlint-1.6.2.tgz", + "integrity": "sha1-VzcEUIX1XrRVxosf9OvAG9UOiDA=", + "dev": true + }, + "jsprim": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.0.tgz", + "integrity": "sha1-o7h+QCmNjDgFUtjMdiigu5WiKRg=", + "dev": true, + "optional": true, + "dependencies": { + "assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", + "dev": true, + "optional": true + } + } + }, + "JSV": { + "version": "https://registry.npmjs.org/JSV/-/JSV-4.0.2.tgz", + "integrity": "sha1-0Hf2glVx+CEy+d/67Vh7QCn+/1c=", + "dev": true + }, + "lazystream": { + "version": "https://registry.npmjs.org/lazystream/-/lazystream-1.0.0.tgz", + "integrity": "sha1-9plf4PggOS9hOWvolGJAe7dxaOQ=", + "dev": true + }, + "livereload-js": { + "version": "https://registry.npmjs.org/livereload-js/-/livereload-js-2.2.2.tgz", + "integrity": "sha1-bIclfmSKtHW8JOoldFftzB+NC8I=", + "dev": true + }, + "load-json-file": { + "version": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", + "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=" + }, + "lodash": { + "version": "https://registry.npmjs.org/lodash/-/lodash-3.10.1.tgz", + "integrity": "sha1-W/Rejkm6QYnhfUgnid/RW9FAt7Y=" + }, + "loud-rejection": { + "version": "https://registry.npmjs.org/loud-rejection/-/loud-rejection-1.6.0.tgz", + "integrity": "sha1-W0b4AUft7leIcPCG0Eghz5mOVR8=" + }, + "map-obj": { + "version": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz", + "integrity": "sha1-2TPOuSBdgr3PSIb2dCvcK03qFG0=" + }, + "maxmin": { + "version": "https://registry.npmjs.org/maxmin/-/maxmin-2.1.0.tgz", + "integrity": "sha1-TTsiCQPZXu5+t6x/qGTnLcCaMWY=" + }, + "media-typer": { + "version": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=", + "dev": true + }, + "meow": { + "version": "https://registry.npmjs.org/meow/-/meow-3.7.0.tgz", + "integrity": "sha1-cstmi0JSKCkKu/qFaJJYcwioAfs=" + }, + "mime-db": { + "version": "https://registry.npmjs.org/mime-db/-/mime-db-1.27.0.tgz", + "integrity": "sha1-gg9XIpa70g7CXtVeW13oaeVDbrE=", + "dev": true + }, + "mime-types": { + "version": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.15.tgz", + "integrity": "sha1-pOv1BkCUVpI3uM9wBGd20J/JKu0=", + "dev": true + }, + "minimatch": { + "version": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha1-UWbihkV/AzBgZL5Ul+jbsMPTIIM=" + }, + "minimist": { + "version": "file:node_shrinkwrap/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=" + }, + "mkdirp": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", + "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", + "dev": true, + "dependencies": { + "minimist": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", + "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", + "dev": true + } + } + }, + "ms": { + "version": "file:node_shrinkwrap/ms-0.7.1.tgz", + "integrity": "sha1-nNE8A62/8ltl7/3nzoZO6VIBcJg=", + "dev": true + }, + "nan": { + "version": "https://registry.npmjs.org/nan/-/nan-2.6.2.tgz", + "integrity": "sha1-5P805slf37WuzAjeZZb0NgWn20U=", + "dev": true, + "optional": true + }, + "node-pre-gyp": { + "version": "0.6.36", + "resolved": "https://registry.npmjs.org/node-pre-gyp/-/node-pre-gyp-0.6.36.tgz", + "integrity": "sha1-22BBEst04NR3VU6bUFsXq936t4Y=", + "dev": true, + "optional": true, + "dependencies": { + "deep-extend": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.4.2.tgz", + "integrity": "sha1-SLaZwn4zS/ifEIkr5DL25MfTSn8=", + "dev": true, + "optional": true + }, + "nopt": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-4.0.1.tgz", + "integrity": "sha1-0NRoWv1UFRk8jHUFYC0NF81kR00=", + "dev": true, + "optional": true + }, + "rc": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.1.tgz", + "integrity": "sha1-LgPo5C7kULjLPc5lvhv4l04d/ZU=", + "dev": true, + "optional": true + }, + "rimraf": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.1.tgz", + "integrity": "sha1-wjOOxkPfeht/5cVPqG9XQopV8z0=", + "dev": true, + "optional": true + }, + "strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", + "dev": true, + "optional": true + } + } + }, + "nomnom": { + "version": "https://registry.npmjs.org/nomnom/-/nomnom-1.8.1.tgz", + "integrity": "sha1-IVH3Ikcrp55Qp2/BJbuMjy5Nwqc=", + "dev": true, + "dependencies": { + "ansi-styles": { + "version": "file:node_shrinkwrap/ansi-styles-1.0.0.tgz", + "integrity": "sha1-yxAt8cVvUSPquLZ817mAJ6AnkXg=", + "dev": true + }, + "chalk": { + "version": "file:node_shrinkwrap/chalk-0.4.0.tgz", + "integrity": "sha1-UZmj3c0MHv4jvAjBsCewYXbgxk8=", + "dev": true + }, + "strip-ansi": { + "version": "file:node_shrinkwrap/strip-ansi-0.1.1.tgz", + "integrity": "sha1-OeipjQRNFQZgq+SmgIrPcLt7yZE=", + "dev": true + } + } + }, + "nopt": { + "version": "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz", + "integrity": "sha1-xkZdvwirzU2zWTF/eaxopkayj/k=" + }, + "normalize-package-data": { + "version": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.3.8.tgz", + "integrity": "sha1-2Bntoqne29H/pWPqQHHZNngilbs=" + }, + "normalize-path": { + "version": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", + "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", + "dev": true + }, + "npmlog": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.0.tgz", + "integrity": "sha512-ocolIkZYZt8UveuiDS0yAkkIjid1o7lPG8cYm05yNYzBn8ykQtaiPMEGp8fY9tKdDgm8okpdKzkvu1y9hUYugA==", + "dev": true, + "optional": true + }, + "number-is-nan": { + "version": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", + "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=" + }, + "oauth-sign": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.8.2.tgz", + "integrity": "sha1-Rqarfwrq2N6unsBWV4C31O/rnUM=", + "dev": true, + "optional": true + }, + "object-assign": { + "version": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=" + }, + "on-finished": { + "version": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", + "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", + "dev": true + }, + "once": { + "version": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=" + }, + "os-homedir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", + "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=", + "dev": true, + "optional": true + }, + "os-tmpdir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", + "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", + "dev": true, + "optional": true + }, + "osenv": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/osenv/-/osenv-0.1.4.tgz", + "integrity": "sha1-Qv5tWVPfBsgGS+bxdsPQWqqjRkQ=", + "dev": true, + "optional": true + }, + "pako": { + "version": "file:node_shrinkwrap/pako-0.2.9.tgz", + "integrity": "sha1-8/dSL073gjSNqBYbrZ7P1Rv4OnU=" + }, + "parse-json": { + "version": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", + "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=" + }, + "parserlib": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/parserlib/-/parserlib-1.1.1.tgz", + "integrity": "sha1-pkz6ckBiQ0/fw1HJpOwtkrlMBvQ=" + }, + "parseurl": { + "version": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.1.tgz", + "integrity": "sha1-yKuMkiO6NIiKpkopeyiFO+wY2lY=", + "dev": true + }, + "path-exists": { + "version": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", + "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=" + }, + "path-is-absolute": { + "version": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=" + }, + "path-type": { + "version": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz", + "integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=" + }, + "performance-now": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-0.2.0.tgz", + "integrity": "sha1-M+8wxcd9TqIcWlOGnZG1bY8lVeU=", + "dev": true, + "optional": true + }, + "pify": { + "version": "file:node_shrinkwrap/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=" + }, + "pinkie": { + "version": "file:node_shrinkwrap/pinkie-2.0.4.tgz", + "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=" + }, + "pinkie-promise": { + "version": "file:node_shrinkwrap/pinkie-promise-2.0.1.tgz", + "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=" + }, + "pretty-bytes": { + "version": "https://registry.npmjs.org/pretty-bytes/-/pretty-bytes-3.0.1.tgz", + "integrity": "sha1-J9AAjXeAY6C0gRuzXHnxvV1fvM8=" + }, + "process-nextick-args": { + "version": "file:node_shrinkwrap/process-nextick-args-1.0.7.tgz", + "integrity": "sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M=" + }, + "punycode": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", + "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=", + "dev": true, + "optional": true + }, + "qs": { + "version": "https://registry.npmjs.org/qs/-/qs-5.1.0.tgz", + "integrity": "sha1-TZMuXH6kEcynajEtOaYGIA/VDNk=", + "dev": true + }, + "raw-body": { + "version": "https://registry.npmjs.org/raw-body/-/raw-body-2.1.7.tgz", + "integrity": "sha1-rf6s4uT7MJgFgBTQjActzFl1h3Q=", + "dev": true, + "dependencies": { + "bytes": { + "version": "https://registry.npmjs.org/bytes/-/bytes-2.4.0.tgz", + "integrity": "sha1-fZcZb51br39pNeJZhVSe3SpsIzk=", + "dev": true + }, + "iconv-lite": { + "version": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.13.tgz", + "integrity": "sha1-H4irpKsLFQjoMSrMOTRfNumS4vI=", + "dev": true + } + } + }, + "rc": { + "version": "https://registry.npmjs.org/rc/-/rc-0.6.0.tgz", + "integrity": "sha1-4ckwBZr4MchUE/4nWuL0D048U3E=", + "dev": true, + "dependencies": { + "minimist": { + "version": "https://registry.npmjs.org/minimist/-/minimist-0.0.10.tgz", + "integrity": "sha1-3j+YVD2/lggr5IrRoMfNqDYwHc8=", + "dev": true + } + } + }, + "read-pkg": { + "version": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz", + "integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=" + }, + "read-pkg-up": { + "version": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz", + "integrity": "sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=" + }, + "readable-stream": { + "version": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.2.9.tgz", + "integrity": "sha1-z3jsb0ptHrQ9JkiMrJfwQudLf8g=" + }, + "rechoir": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz", + "integrity": "sha1-hSBLVNuoLVdC4oyWdW70OvUOM4Q=" + }, + "redent": { + "version": "https://registry.npmjs.org/redent/-/redent-1.0.0.tgz", + "integrity": "sha1-z5Fqsf1fHxbfsggi3W7H9zDCr94=" + }, + "remove-trailing-separator": { + "version": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.0.1.tgz", + "integrity": "sha1-YV67lq9VlVLUv0BXyENtSGq2PMQ=", + "dev": true + }, + "repeating": { + "version": "https://registry.npmjs.org/repeating/-/repeating-2.0.1.tgz", + "integrity": "sha1-UhTFOpJtNVJwdSf7q0FdvAjQbdo=" + }, + "request": { + "version": "2.81.0", + "resolved": "https://registry.npmjs.org/request/-/request-2.81.0.tgz", + "integrity": "sha1-xpKJRqDgbF+Nb4qTM0af/aRimKA=", + "dev": true, + "optional": true, + "dependencies": { + "qs": { + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.4.0.tgz", + "integrity": "sha1-E+JtKK1rD/qpExLNO/cI7TUecjM=", + "dev": true, + "optional": true + } + } + }, + "resolve": { + "version": "file:node_shrinkwrap/resolve-1.1.7.tgz", + "integrity": "sha1-IDEU2CrSxe2ejgQRs5ModeiJ6Xs=" + }, + "rimraf": { + "version": "https://registry.npmjs.org/rimraf/-/rimraf-2.2.8.tgz", + "integrity": "sha1-5Dm+Kq7jJzIZUnMPmaiSnk/FBYI=" + }, + "safe-buffer": { + "version": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.0.1.tgz", + "integrity": "sha1-0mPKVGls2KMGtcplUekt5XkY++c=" + }, + "semver": { + "version": "https://registry.npmjs.org/semver/-/semver-5.3.0.tgz", + "integrity": "sha1-myzl094C0XxgEq0yaqa00M9U+U8=" + }, + "set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", + "dev": true, + "optional": true + }, + "shelljs": { + "version": "0.7.7", + "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.7.7.tgz", + "integrity": "sha1-svXHfvlxSPS09uImguELuoZnz/E=" + }, + "signal-exit": { + "version": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", + "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=" + }, + "sntp": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/sntp/-/sntp-1.0.9.tgz", + "integrity": "sha1-ZUEYTMkK7qbG57NeJlkIJEPGYZg=", + "dev": true, + "optional": true + }, + "source-map": { + "version": "file:node_shrinkwrap/source-map-0.5.6.tgz", + "integrity": "sha1-dc449SvwczxafwwRjYEzSiu19BI=" + }, + "spdx-correct": { + "version": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-1.0.2.tgz", + "integrity": "sha1-SzBz2TP/UfORLwOsVRlJikFQ20A=" + }, + "spdx-expression-parse": { + "version": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-1.0.4.tgz", + "integrity": "sha1-m98vIOH0DtRH++JzJmGR/O1RYmw=" + }, + "spdx-license-ids": { + "version": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-1.2.2.tgz", + "integrity": "sha1-yd96NCRZSt5r0RkA1ZZpbcBrrFc=" + }, + "sprintf-js": { + "version": "file:node_shrinkwrap/sprintf-js-1.0.3.tgz", + "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=" + }, + "sshpk": { + "version": "1.13.0", + "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.13.0.tgz", + "integrity": "sha1-/yo+T9BEl1Vf7Zezmg/YL6+zozw=", + "dev": true, + "optional": true, + "dependencies": { + "assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", + "dev": true, + "optional": true + } + } + }, + "statuses": { + "version": "https://registry.npmjs.org/statuses/-/statuses-1.3.1.tgz", + "integrity": "sha1-+vUbnrdKrvOzrPStX2Gr8ky3uT4=", + "dev": true + }, + "stream-buffers": { + "version": "https://registry.npmjs.org/stream-buffers/-/stream-buffers-2.2.0.tgz", + "integrity": "sha1-kdX1Ew0c75bc+n9yaUUYh0HQnuQ=", + "dev": true + }, + "string_decoder": { + "version": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.1.tgz", + "integrity": "sha1-YuIA8DmVWmgQ2N8KM//A8BNmLZg=" + }, + "string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "dev": true + }, + "stringstream": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/stringstream/-/stringstream-0.0.5.tgz", + "integrity": "sha1-TkhM1N5aC7vuGORjB3EKioFiGHg=", + "dev": true, + "optional": true + }, + "strip-ansi": { + "version": "file:node_shrinkwrap/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=" + }, + "strip-bom": { + "version": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", + "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=" + }, + "strip-indent": { + "version": "https://registry.npmjs.org/strip-indent/-/strip-indent-1.0.1.tgz", + "integrity": "sha1-DHlipq3vp7vUrDZkYKY4VSrhoKI=" + }, + "strip-json-comments": { + "version": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-0.1.3.tgz", + "integrity": "sha1-Fkxk43Coo8wAyeAbU55WmCPw7lQ=", + "dev": true + }, + "supports-color": { + "version": "file:node_shrinkwrap/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=" + }, + "tar": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/tar/-/tar-2.2.1.tgz", + "integrity": "sha1-jk0qJWwOIYXGsYrWlK7JaLg8sdE=", + "dev": true + }, + "tar-pack": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/tar-pack/-/tar-pack-3.4.0.tgz", + "integrity": "sha1-I74tf2cagzk3bL2wuP4/3r8xeYQ=", + "dev": true, + "optional": true, + "dependencies": { + "rimraf": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.1.tgz", + "integrity": "sha1-wjOOxkPfeht/5cVPqG9XQopV8z0=", + "dev": true, + "optional": true + } + } + }, + "tar-stream": { + "version": "https://registry.npmjs.org/tar-stream/-/tar-stream-1.5.4.tgz", + "integrity": "sha1-NlSc8E7RrumyowwBQyUiONr5QBY=", + "dev": true + }, + "tiny-lr": { + "version": "https://registry.npmjs.org/tiny-lr/-/tiny-lr-0.2.1.tgz", + "integrity": "sha1-s/26gC5dVqM8L28QeUsy5Hescp0=", + "dev": true + }, + "tough-cookie": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.3.2.tgz", + "integrity": "sha1-8IH3bkyFcg5sN6X6ztc3FQ2EByo=", + "dev": true, + "optional": true + }, + "trim-newlines": { + "version": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-1.0.0.tgz", + "integrity": "sha1-WIeWa7WCpFA6QetST301ARgVphM=" + }, + "tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", + "dev": true, + "optional": true + }, + "tweetnacl": { + "version": "0.14.5", + "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", + "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=", + "dev": true, + "optional": true + }, + "type-is": { + "version": "https://registry.npmjs.org/type-is/-/type-is-1.6.15.tgz", + "integrity": "sha1-yrEPtJCeRByChC6v4a1kbIGARBA=", + "dev": true + }, + "typedarray": { + "version": "file:node_shrinkwrap/typedarray-0.0.6.tgz", + "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=" + }, + "uglify-js": { + "version": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.0.11.tgz", + "integrity": "sha1-gfWUuaJNrXbjnakvjwbls7yMLhE=" + }, + "uid-number": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/uid-number/-/uid-number-0.0.6.tgz", + "integrity": "sha1-DqEOgDXo61uOREnwbaHHMGY7qoE=", + "dev": true, + "optional": true + }, + "underscore": { + "version": "https://registry.npmjs.org/underscore/-/underscore-1.6.0.tgz", + "integrity": "sha1-izixDKze9jM3uLJOT/htRa6lKag=", + "dev": true + }, + "underscore.string": { + "version": "https://registry.npmjs.org/underscore.string/-/underscore.string-3.2.3.tgz", + "integrity": "sha1-gGmSYzZl1eX8tNsfs6hi62jp5to=" + }, + "unpipe": { + "version": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=", + "dev": true + }, + "uri-path": { + "version": "https://registry.npmjs.org/uri-path/-/uri-path-1.0.0.tgz", + "integrity": "sha1-l0fwGDWJM8Md4PzP2C0TjmcmLjI=" + }, + "util-deprecate": { + "version": "file:node_shrinkwrap/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" + }, + "uuid": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.0.1.tgz", + "integrity": "sha1-ZUS7ot/ajBzxfmKaOjBeK7H+5sE=", + "dev": true, + "optional": true + }, + "validate-npm-package-license": { + "version": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.1.tgz", + "integrity": "sha1-KAS6vnEq0zeUWaz74kdGqywwP7w=" + }, + "verror": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/verror/-/verror-1.3.6.tgz", + "integrity": "sha1-z/XfEpRtKX0rqu+qJoniW+AcAFw=", + "dev": true, + "optional": true + }, + "walkdir": { + "version": "https://registry.npmjs.org/walkdir/-/walkdir-0.0.11.tgz", + "integrity": "sha1-oW0CXrkxvQO1LzCMrtD0D86+lTI=", + "dev": true + }, + "websocket-driver": { + "version": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.6.5.tgz", + "integrity": "sha1-XLJVbOuF9Dc8bYI4qmkchFThOjY=", + "dev": true + }, + "websocket-extensions": { + "version": "https://registry.npmjs.org/websocket-extensions/-/websocket-extensions-0.1.1.tgz", + "integrity": "sha1-domUmcGEtu91Q3fC27DNbLVdKec=", + "dev": true + }, + "which": { + "version": "https://registry.npmjs.org/which/-/which-1.2.14.tgz", + "integrity": "sha1-mofEN48D6CfOyvGs31bHNsAcFOU=" + }, + "wide-align": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.2.tgz", + "integrity": "sha512-ijDLlyQ7s6x1JgCLur53osjm/UXUYD9+0PbYKrBsYisYXzCxN+HC3mYDNy/dWdmf3AwqwU3CXwDCvsNgGK1S0w==", + "dev": true, + "optional": true + }, + "wrappy": { + "version": "file:node_shrinkwrap/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" + }, + "xtend": { + "version": "file:node_shrinkwrap/xtend-4.0.1.tgz", + "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=", + "dev": true + }, + "zip-stream": { + "version": "https://registry.npmjs.org/zip-stream/-/zip-stream-1.1.1.tgz", + "integrity": "sha1-Uha0i7tNJlH2TVxubwnrSnOZ1Vc=", + "dev": true, + "dependencies": { + "lodash": { + "version": "https://registry.npmjs.org/lodash/-/lodash-4.17.4.tgz", + "integrity": "sha1-eCA6TRwyiuHYbcpkYONptX9AVa4=", + "dev": true + } + } + } + } +} diff --git a/package.json b/package.json index 2c3b8e0..c9ce66c 100644 --- a/package.json +++ b/package.json @@ -1,14 +1,16 @@ { "name": "alltube", "description": "HTML GUI for youtube-dl", - "version": "0.9.0", + "version": "0.10.0", "author": "Pierre Rudloff", "bugs": "https://github.com/Rudloff/alltube/issues", "dependencies": { "bower": "~1.8.0", "grunt": "~1.0.1", - "grunt-contrib-cssmin": "~2.0.0", - "grunt-contrib-uglify": "~2.2.0" + "grunt-contrib-csslint": "~2.0.0", + "grunt-contrib-cssmin": "~2.2.0", + "grunt-contrib-uglify": "~3.0.0", + "grunt-potomo": "~3.5.0" }, "devDependencies": { "grunt-contrib-compress": "~1.4.1", diff --git a/FAQ.md b/resources/FAQ.md similarity index 98% rename from FAQ.md rename to resources/FAQ.md index 90e10c7..b5f01bc 100644 --- a/FAQ.md +++ b/resources/FAQ.md @@ -9,7 +9,7 @@ You can ususally download the video by doing *File > Save to* or *ctrl + S*. ## How do I change config parameters? -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` in the `config/` folder. Here are the parameters that you can set: * `youtubedl`: path to your youtube-dl binary diff --git a/error.html b/resources/error.html similarity index 100% rename from error.html rename to resources/error.html diff --git a/maintenance.html b/resources/maintenance.html similarity index 100% rename from maintenance.html rename to resources/maintenance.html diff --git a/manifest.json b/resources/manifest.json similarity index 100% rename from manifest.json rename to resources/manifest.json diff --git a/nginx.conf b/resources/nginx.conf similarity index 100% rename from nginx.conf rename to resources/nginx.conf diff --git a/php.ini b/resources/php.ini similarity index 100% rename from php.ini rename to resources/php.ini diff --git a/sitemap.xml b/resources/sitemap.xml similarity index 100% rename from sitemap.xml rename to resources/sitemap.xml diff --git a/robots.txt b/robots.txt index 48fbc65..d645b36 100644 --- a/robots.txt +++ b/robots.txt @@ -1 +1 @@ -Sitemap: http://alltubedownload.net/sitemap.xml +Sitemap: http://alltubedownload.net/resources/sitemap.xml diff --git a/templates/error.tpl b/templates/error.tpl index 67a0fae..ded9676 100644 --- a/templates/error.tpl +++ b/templates/error.tpl @@ -2,8 +2,8 @@
{include file="inc/logo.tpl"} -

An error occured

- Please check the URL of your video. +

{t}An error occured{/t}

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

{foreach $errors as $error} {$error|escape} diff --git a/templates/extractors.tpl b/templates/extractors.tpl index 4944193..fb85994 100644 --- a/templates/extractors.tpl +++ b/templates/extractors.tpl @@ -1,7 +1,7 @@ {include file='inc/head.tpl'} {include file='inc/header.tpl'} {include file='inc/logo.tpl'} -

Supported websites

+

{t}Supported websites{/t}

    {foreach $extractors as $extractor} diff --git a/templates/inc/footer.tpl b/templates/inc/footer.tpl index c5797fc..bcc7eb8 100644 --- a/templates/inc/footer.tpl +++ b/templates/inc/footer.tpl @@ -1,19 +1,19 @@
-