Skip to content
This repository was archived by the owner on Dec 6, 2019. It is now read-only.

Commit 85d920e

Browse files
committed
Add skin download methods
1 parent 31e5590 commit 85d920e

File tree

12 files changed

+162
-47
lines changed

12 files changed

+162
-47
lines changed
File renamed without changes.

.travis.yml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,20 @@
22
# which runs independent from the client system
33
language: php
44

5+
## Cache composer bits
6+
cache:
7+
directories:
8+
- $HOME/.composer/cache
9+
510
# Our server is 7.0
611
php: [7.0]
712

813
env:
914
- DB=mysql
1015

16+
before_script:
17+
- cp .env.travis .env
18+
1119
# Commands to be run in order to setup the environment.
1220
install:
1321
# According to the travis site the composer build be very old, so update it to prevent bugs

_ide_helper.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<?php
22
/**
33
* A helper file for Laravel 5, to provide autocomplete information to your IDE
4-
* Generated for Laravel 5.2.31 on 2016-05-11.
4+
* Generated for Laravel 5.2.31 on 2016-05-16.
55
*
66
* @author Barry vd. Heuvel <barryvdh@gmail.com>
77
* @see https://github.com/barryvdh/laravel-ide-helper

app/Console/Commands/NameHistory.php

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,6 @@ class NameHistory extends Command {
99
protected $signature = 'app:namehistory {uuid}';
1010
protected $description = 'Command description';
1111

12-
/**
13-
* Execute the console command.
14-
*
15-
* @return mixed
16-
*/
1712
public function handle() {
1813
//
1914
}

app/Console/Commands/NameResolve.php

Lines changed: 37 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,22 +3,52 @@
33
namespace App\Console\Commands;
44

55
use Illuminate\Console\Command;
6+
use \App\Player;
67

78
class NameResolve extends Command {
89

9-
const UUID_URL = "https://api.mojang.com/users/profiles/minecraft/<username>?at=<timestamp>";
10+
const UUID_URL = "https://api.mojang.com/users/profiles/minecraft/<username>";
11+
const UUID_TIME_URL = "https://api.mojang.com/users/profiles/minecraft/<username>?at=<timestamp>";
1012
const MULTIPLE_UUID_URL = "https://api.mojang.com/profiles/minecraft";
1113

1214
protected $signature = 'app:uuid {playerName}';
1315

1416
protected $description = 'Get the UUID from a playername';
1517

16-
/**
17-
* Execute the console command.
18-
*
19-
* @return mixed
20-
*/
2118
public function handle() {
22-
//
19+
$this->info("Getting UUID");
20+
21+
$name = $this->argument("playerName");
22+
$this->downloadUUID($name);
23+
}
24+
25+
function downloadUUID($name) {
26+
$url = str_replace("<username>", $name, self::UUID_URL);
27+
28+
$request = curl_init();
29+
curl_setopt($request, CURLOPT_RETURNTRANSFER, TRUE);
30+
curl_setopt($request, CURLOPT_FOLLOWLOCATION, TRUE);
31+
curl_setopt($request, CURLOPT_URL, $url);
32+
try {
33+
$response = curl_exec($request);
34+
35+
$curl_info = curl_getinfo($request);
36+
if ($curl_info['http_code'] !== 200) {
37+
$this->error("Return code: " . $curl_info['http_code']);
38+
return;
39+
}
40+
41+
$data = json_decode($response, true);
42+
$player = new Player();
43+
$player->uuid = $data['id'];
44+
$player->name = $data['name'];
45+
46+
$player->save();
47+
$this->info("Resolved " . $player);
48+
} catch (Exception $ex) {
49+
$this->error($ex);
50+
} finally {
51+
curl_close($request);
52+
}
2353
}
2454
}
Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
<?php
2+
3+
namespace App\Console\Commands;
4+
5+
use Illuminate\Console\Command;
6+
use \App\Skin;
7+
use \File;
8+
use \Exception;
9+
use \MinecraftSkins\MinecraftSkins;
10+
11+
class SkinDownload extends Command {
12+
13+
const SKIN_URL = "http://sessionserver.mojang.com/session/minecraft/profile/<uuid>?unsigned=false";
14+
15+
protected $signature = 'app:skin {uuid}';
16+
protected $description = 'Download and save a skin';
17+
18+
public function handle() {
19+
$this->info("Downloading skins");
20+
21+
$uuid = $this->argument("uuid");
22+
$this->downloadSkin($uuid);
23+
}
24+
25+
function downloadSkin($uuid) {
26+
$url = str_replace("<uuid>", $uuid, self::SKIN_URL);
27+
28+
$request = curl_init();
29+
curl_setopt($request, CURLOPT_RETURNTRANSFER, TRUE);
30+
curl_setopt($request, CURLOPT_FOLLOWLOCATION, TRUE);
31+
curl_setopt($request, CURLOPT_URL, $url);
32+
try {
33+
$response = curl_exec($request);
34+
35+
$curl_info = curl_getinfo($request);
36+
if ($curl_info['http_code'] !== 200) {
37+
$this->error("Return code: " . $curl_info['http_code']);
38+
return;
39+
}
40+
41+
$data = json_decode($response, true);
42+
$skinProperties = $data['properties'][0];
43+
44+
$skin = new Skin();
45+
$skin->signature = base64_decode($skinProperties['signature']);
46+
47+
$skinData = json_decode(base64_decode($skinProperties['value']), true);
48+
$skin->timestamp = $skinData['timestamp'];
49+
$skin->profile_id = $skinData['profileId'];
50+
$skin->profile_name = $skinData['profileName'];
51+
52+
$textures = $skinData['textures'];
53+
if (!isset($textures['SKIN'])) {
54+
$this->error("User has no skin set");
55+
return;
56+
}
57+
58+
$skinTextures = $textures['SKIN'];
59+
$skin->skin_url = $skinTextures['url'];
60+
$skin->slim_model = isset($skinTextures['metadata']);
61+
$this->saveRendered($uuid, $skin->skin_url);
62+
63+
if (isset($textures['CAPE'])) {
64+
//user has a cape
65+
$skin->cape_url = $textures['CAPE']['url'];
66+
}
67+
68+
$skin->save();
69+
} catch (Exception $ex) {
70+
$this->error($ex);
71+
} finally {
72+
curl_close($request);
73+
}
74+
}
75+
76+
function saveRendered($uuid, $url) {
77+
$rawSkin = imagecreatefromstring(file_get_contents($url));
78+
$head = MinecraftSkins::head($rawSkin, 8);
79+
$skin = MinecraftSkins::skin($rawSkin, 8);
80+
81+
$path = public_path() . "/img/head/$uuid.png";
82+
//check if it's still the same folder
83+
if (File::dirname($path) == public_path() . "/img/head") {
84+
imagepng($head, $path);
85+
}
86+
87+
$path = public_path() . "/img/skin/$uuid.png";
88+
if (File::dirname($path) == public_path() . "/img/skin") {
89+
imagepng($skin, $path);
90+
}
91+
}
92+
}

app/Console/Kernel.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,9 @@ class Kernel extends ConsoleKernel {
1616
// Commands\Inspire::class,
1717
Commands\Ping::class,
1818
Commands\Query::class,
19-
// Commands\NameResolve::class,
20-
// Commands\NameHistory::class,
19+
Commands\NameResolve::class,
20+
Commands\NameHistory::class,
21+
Commands\SkinDownload::class,
2122
];
2223

2324
/**
@@ -31,7 +32,6 @@ protected function schedule(Schedule $schedule) {
3132
// ->hourly();
3233
$schedule->command('app:ping')->everyThirtyMinutes()->sendOutputTo(storage_path() . '/logs/ping.log', true);
3334
$schedule->command('app:query')->weekly()->sendOutputTo(storage_path() . '/logs/query.log', true);
34-
3535
// $schedule->command('queue:work --daemon')->everyMinute()->withoutOverlapping();
3636
}
3737
}

app/Http/Controllers/PlayerController.php

Lines changed: 10 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,8 @@
22

33
namespace App\Http\Controllers;
44

5-
use App\Console\Commands\Ping;
65
use App\Player;
76
use Illuminate\Http\Request;
8-
use App\Server;
97
use App\Http\Controllers\Controller;
108

119
class PlayerController extends Controller {
@@ -17,31 +15,27 @@ public function index() {
1715

1816
public function addPlayer(Request $request) {
1917
$rules = array(
20-
'address' => array('required', 'regex:' . Player::VALID_USERNAME),
18+
'name' => array('required', 'regex:' . Player::VALID_USERNAME),
2119
'g-recaptcha-response' => 'required|recaptcha',
2220
);
2321

22+
$name = $request->input("name");
23+
2424
$validator = validator()->make($request->input(), $rules);
2525
if ($validator->passes()) {
26-
$name = $request->input("name");
27-
$uuid = Ping::constructOfflinePlayerUuid($name);
28-
logger("Adding player", ["name" => $name, "uuid" => $uuid]);
26+
logger("Adding player", ["name" => $name]);
2927

30-
$exists = Player::where("uuid", '=', $uuid)->exists();
28+
$exists = Player::where("name", '=', $name)->exists();
3129
if ($exists) {
32-
return view("player.add")->with(["uuid" => $uuid, "name" => $name])->withErrors(['Player already exists']);
30+
return view("player.add")->with(["name" => $name])->withErrors(['Player already exists']);
3331
} else {
34-
$player = new Player();
35-
$player->uuid = $uuid;
36-
$player->name = $name;
37-
$player->save();
38-
39-
logger()->info("Added player: " . $name . " : " . $uuid);
32+
\Artisan::call("app:uuid", ["playerName" => $name]);
4033

41-
return redirect()->action("PlayerController@getPlayerByUUID", [$uuid]);
34+
logger()->info("Added player: " . $name . " : ");
35+
return redirect()->action("PlayerController@getPlayerByUsername", [$name]);
4236
}
4337
} else {
44-
return view("player.add")->with(["uuid" => $uuid, "name" => $name])->withErrors($validator);
38+
return view("player.add")->with(["name" => $name])->withErrors($validator);
4539
}
4640
}
4741

app/Http/routes.php

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -35,10 +35,8 @@
3535

3636
Route::get('/player/search', "SearchController@searchPlayer");
3737

38-
Route::get('/player/{uuid}', "PlayerController@getPlayerByUUID")
39-
->where("uuid", "[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}");
40-
Route::get('/player/{username}', "PlayerController@getPlayerByUsername")
41-
->where("username", "\w{2,16}");
38+
Route::get('/player/{username}', "PlayerController@getPlayerByUsername")->where("username", "\w{2,16}");
39+
Route::get('/player/{uuid}', "PlayerController@getPlayerByUUID");
4240

4341
//general
4442
Route::get('/privacy', 'BaseController@privacy');
@@ -61,14 +59,12 @@
6159

6260
//Player
6361
Route::get('/player', 'ApiController@playerIndex');
64-
Route::get('/player/{uuid}', 'ApiController@getPlayerByUUID')
65-
->where("uuid", "[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}");
6662
Route::get('/player/{username}', 'ApiController@getPlayerByName')->where("username", "\w{2,16}");
63+
Route::get('/player/{uuid}', 'ApiController@getPlayerByUUID');
6764

6865
//todo: rendered skin routes
69-
Route::get('/skin/{uuid}', 'ApiController@getSkinByUUID')
70-
->where("uuid", "[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}");
7166
Route::get('/skin/{name}', 'ApiController@getSkinByName')->where("username", "\w{2,16}");
67+
Route::get('/skin/{uuid}', 'ApiController@getSkinByUUID');
7268

7369
Route::get('/stats', 'ApiController@stats');
7470
});

database/seeds/PlayerTableSeeder.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,19 +11,19 @@ class PlayerTableSeeder extends Seeder {
1111
*/
1212
public function run() {
1313
App\Player::create([
14-
"uuid" => "069a79f4-44e9-4726-a5be-fca90e38aaf5",
14+
"uuid" => "069a79f444e94726a5befca90e38aaf5",
1515
"name" => "Notch"
1616
])->save();
1717

1818
App\Player::create([
19-
"uuid" => "61699b2e-d327-4a01-9f1e-0ea8c3f06bc6",
19+
"uuid" => "61699b2ed3274a019f1e0ea8c3f06bc6",
2020
"name" => "Dinnerbone"
2121
])->save();
2222

2323
//this account really exists
2424
/* @var $changed App\Player */
2525
$changed = App\Player::create([
26-
"uuid" => "173d39fd-987a-4a62-9673-b1a08c1d6dcf",
26+
"uuid" => "173d39fd987a4a629673b1a08c1d6dcf",
2727
"name" => "Invalid"
2828
]);
2929

0 commit comments

Comments
 (0)