diff --git a/composer.json b/composer.json old mode 100644 new mode 100755 index 032fd0a..244e7e3 --- a/composer.json +++ b/composer.json @@ -4,7 +4,8 @@ "illuminate/container": "^5.4", "illuminate/events": "^5.4", "illuminate/database": "^5.4", - "guzzlehttp/guzzle": "^6.3" + "guzzlehttp/guzzle": "^6.3", + "symfony/process": "^3.3" }, "autoload": { "psr-4": {"Zeropingheroes\\LancacheAutofill\\": "src/"} diff --git a/composer.lock b/composer.lock index 94b0207..5c30fb6 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,8 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", "This file is @generated automatically" ], - "content-hash": "e1529e3dd0cff1ebf8914eb2fc6bfafe", + "hash": "35f3b333ec7c89d8bef3ff8bac6eef61", + "content-hash": "b3718dd9de9285dd5e966d4ac8de92d6", "packages": [ { "name": "doctrine/inflector", @@ -71,7 +72,7 @@ "singularize", "string" ], - "time": "2017-07-22T12:18:28+00:00" + "time": "2017-07-22 12:18:28" }, { "name": "guzzlehttp/guzzle", @@ -136,7 +137,7 @@ "rest", "web service" ], - "time": "2017-06-22T18:50:49+00:00" + "time": "2017-06-22 18:50:49" }, { "name": "guzzlehttp/promises", @@ -187,7 +188,7 @@ "keywords": [ "promise" ], - "time": "2016-12-20T10:07:11+00:00" + "time": "2016-12-20 10:07:11" }, { "name": "guzzlehttp/psr7", @@ -252,7 +253,7 @@ "uri", "url" ], - "time": "2017-03-20T17:10:46+00:00" + "time": "2017-03-20 17:10:46" }, { "name": "illuminate/console", @@ -303,7 +304,7 @@ ], "description": "The Illuminate Console package.", "homepage": "https://laravel.com", - "time": "2017-06-10T13:11:18+00:00" + "time": "2017-06-10 13:11:18" }, { "name": "illuminate/container", @@ -346,7 +347,7 @@ ], "description": "The Illuminate Container package.", "homepage": "https://laravel.com", - "time": "2017-05-24T14:15:53+00:00" + "time": "2017-05-24 14:15:53" }, { "name": "illuminate/contracts", @@ -388,7 +389,7 @@ ], "description": "The Illuminate Contracts package.", "homepage": "https://laravel.com", - "time": "2017-04-19T20:17:43+00:00" + "time": "2017-04-19 20:17:43" }, { "name": "illuminate/database", @@ -448,7 +449,7 @@ "orm", "sql" ], - "time": "2017-06-15T19:07:41+00:00" + "time": "2017-06-15 19:07:41" }, { "name": "illuminate/events", @@ -493,7 +494,7 @@ ], "description": "The Illuminate Events package.", "homepage": "https://laravel.com", - "time": "2017-05-02T12:57:00+00:00" + "time": "2017-05-02 12:57:00" }, { "name": "illuminate/support", @@ -550,7 +551,7 @@ ], "description": "The Illuminate Support package.", "homepage": "https://laravel.com", - "time": "2017-06-15T12:35:32+00:00" + "time": "2017-06-15 12:35:32" }, { "name": "nesbot/carbon", @@ -603,7 +604,7 @@ "datetime", "time" ], - "time": "2017-01-16T07:55:07+00:00" + "time": "2017-01-16 07:55:07" }, { "name": "paragonie/random_compat", @@ -651,7 +652,7 @@ "pseudorandom", "random" ], - "time": "2017-03-13T16:27:32+00:00" + "time": "2017-03-13 16:27:32" }, { "name": "psr/http-message", @@ -701,7 +702,7 @@ "request", "response" ], - "time": "2016-08-06T14:39:51+00:00" + "time": "2016-08-06 14:39:51" }, { "name": "psr/log", @@ -748,7 +749,7 @@ "psr", "psr-3" ], - "time": "2016-10-10T12:19:37+00:00" + "time": "2016-10-10 12:19:37" }, { "name": "symfony/console", @@ -817,7 +818,7 @@ ], "description": "Symfony Console Component", "homepage": "https://symfony.com", - "time": "2017-07-29T21:27:59+00:00" + "time": "2017-07-29 21:27:59" }, { "name": "symfony/debug", @@ -873,20 +874,20 @@ ], "description": "Symfony Debug Component", "homepage": "https://symfony.com", - "time": "2017-07-28T15:27:31+00:00" + "time": "2017-07-28 15:27:31" }, { "name": "symfony/polyfill-mbstring", - "version": "v1.4.0", + "version": "v1.5.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-mbstring.git", - "reference": "f29dca382a6485c3cbe6379f0c61230167681937" + "reference": "7c8fae0ac1d216eb54349e6a8baa57d515fe8803" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/f29dca382a6485c3cbe6379f0c61230167681937", - "reference": "f29dca382a6485c3cbe6379f0c61230167681937", + "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/7c8fae0ac1d216eb54349e6a8baa57d515fe8803", + "reference": "7c8fae0ac1d216eb54349e6a8baa57d515fe8803", "shasum": "" }, "require": { @@ -898,7 +899,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "1.4-dev" + "dev-master": "1.5-dev" } }, "autoload": { @@ -932,7 +933,56 @@ "portable", "shim" ], - "time": "2017-06-09T14:24:12+00:00" + "time": "2017-06-14 15:44:48" + }, + { + "name": "symfony/process", + "version": "v3.3.6", + "source": { + "type": "git", + "url": "https://github.com/symfony/process.git", + "reference": "07432804942b9f6dd7b7377faf9920af5f95d70a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/process/zipball/07432804942b9f6dd7b7377faf9920af5f95d70a", + "reference": "07432804942b9f6dd7b7377faf9920af5f95d70a", + "shasum": "" + }, + "require": { + "php": ">=5.5.9" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.3-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\Process\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony Process Component", + "homepage": "https://symfony.com", + "time": "2017-07-13 13:05:09" }, { "name": "symfony/translation", @@ -997,7 +1047,7 @@ ], "description": "Symfony Translation Component", "homepage": "https://symfony.com", - "time": "2017-06-24T16:45:30+00:00" + "time": "2017-06-24 16:45:30" } ], "packages-dev": [], diff --git a/lancache-autofill b/lancache-autofill index 3a7b05b..99862a4 100755 --- a/lancache-autofill +++ b/lancache-autofill @@ -8,7 +8,7 @@ use Illuminate\Events\Dispatcher; use Illuminate\Database\Capsule\Manager as Capsule; // Import available commands -use Zeropingheroes\LancacheAutofill\Console\Commands\Steam\{UpdateAppList, SearchApps, QueueApp, ShowQueue}; +use Zeropingheroes\LancacheAutofill\Console\Commands\Steam\{UpdateAppList, SearchApps, QueueApp, ShowQueue, StartDownloading}; use Zeropingheroes\LancacheAutofill\Console\Commands\CreateDatabase; // Load Composer's autoloader @@ -36,6 +36,7 @@ $app->add(new UpdateAppList); $app->add(new SearchApps); $app->add(new QueueApp); $app->add(new ShowQueue); +$app->add(new StartDownloading); // Run the console app $app->run(); \ No newline at end of file diff --git a/src/Console/Commands/Steam/StartDownloading.php b/src/Console/Commands/Steam/StartDownloading.php new file mode 100755 index 0000000..1cc4a82 --- /dev/null +++ b/src/Console/Commands/Steam/StartDownloading.php @@ -0,0 +1,120 @@ +queuedItems() == 0 ) + { + $this->error('Queue is empty - nothing to download'); + die(); + } + + // Loop through all apps to process + while( $app = $this->nextApp() ) { + + $this->info('Starting download of ' . $app->name ); + + try { + $arguments = + [ + 'login' => 'anonymous', + '@sSteamCmdForcePlatformType' => 'windows', + 'force_install_dir' => '/tmp/steam/'.$app->appid, + 'app_license_request' => $app->appid, + 'app_update' => $app->appid, + 'quit' => null, + ]; + + $argumentString = null; + + // Build argument string + foreach($arguments as $argument => $value) { + $argumentString .= "+$argument $value "; + } + + // Start SteamCMD with the arguments, using "unbuffer" + // as SteamCMD buffers output when it is not run in a + // tty, which prevents us showing output line by line + $process = new Process('unbuffer steamcmd.sh '.$argumentString); + + // Set a long timeout as downloading could take a while + $process->setTimeout(14400); + + // Show SteamCMD output line by line + $process->run(function ($type, $buffer) { + $this->line(str_replace(["\r", "\n"], '', $buffer)); + }); + + if (!$process->isSuccessful()) + throw new ProcessFailedException($process); + + $this->info('Successfully completed download of ' . $app->name ); + $this->updateQueueItemStatus($app->id, 'completed'); + + } catch (ProcessFailedException $e) { + if($process->getExitCode() == 127) { + $this->error('SteamCMD not found - please ensure it is in your $PATH'); + die(); + } + + // Create an array of SteamCMD's output (removing excess newlines) + $lines = explode(PHP_EOL,trim($process->getOutput())); + + // Get the last line (removing ANSI codes) + $lastLine = preg_replace('#\x1b\[[0-9;]*[a-zA-Z]#', '', end($lines)); + + $this->error('Failed to download ' . $app->name ); + $this->updateQueueItemStatus($app->id, 'failed', $lastLine ); + + } + } + } + + private function nextApp() + { + return Capsule::table('steam_queue') + ->where('status', 'queued') + ->first(); + } + + private function updateQueueItemStatus( $id, $status, $message = null ) + { + return Capsule::table('steam_queue') + ->where('id', $id) + ->update(['status' => $status, 'message' => $message]); + } + + private function queuedItems() + { + return Capsule::table('steam_queue') + ->where('status', 'queued') + ->count(); + } +} \ No newline at end of file