Last active
September 1, 2016 18:26
-
-
Save MineTheCube/f244b1933e755ac39d2a52b1d377542c to your computer and use it in GitHub Desktop.
Display head of player from his username or uuid using MojangAPI (github project)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
/** | |
* Informations | |
* -------------------------------------- | |
* | |
* This script use MojangAPI to display head of player from his username or uuid | |
* | |
* Parameters: | |
* user = username or UUID | |
* size = size in pixels, optional | |
* | |
* E.g.: /head.php?user=Notch | |
* E.g.: /head.php?user=069a79f4-44e9-4726-a5be-fca90e38aaf5&size=200 | |
* | |
* Please check the configuration below to ensure everything will work | |
*/ | |
/* Configuration | |
--------------------------------------*/ | |
// debug = true : in case of errors we print them | |
// debug = false : if we have errors we print default steve avatar instead | |
define('DEBUG', true); | |
// How many seconds skin is cached | |
define('CACHE_TIMEOUT', 86400); | |
// Default size of avatar if not provided | |
define('DEFAULT_SIZE', 100); | |
// Minimum size allowed | |
define('MINIMUM_SIZE', 10); | |
// And maximum size allowed | |
define('MAXIMUM_SIZE', 300); | |
// Where database should be | |
define('DATABASE_LOCATION', __DIR__ . '/cache/skins.sqlite'); | |
// And where MojangApi is located | |
define('MOJANGAPI_LOCATION', __DIR__ . '/libraries/mojang-api.class.php'); | |
// If we try to download MojangAPI if missing | |
define('AUTO_INSTALL', true); | |
/* White page ? | |
* Uncomment these 2 lines | |
--------------------------------------*/ | |
// error_reporting(E_ALL); | |
// ini_set('display_errors', true); | |
/* URL Rewriting | |
--------------------------------------*/ | |
/* If you want nice urls like: /head/Notch/100, create a file named ".htaccess" in the same directory with this: | |
# --------- .htaccess --------- | |
RewriteEngine on | |
# If you have 500 internal errors, remove the # and put the current directory from this line: | |
# RewriteBase /current-directory/ | |
# Redirect "/head/Notch/100", "head/Notch" or "head/Notch.png" to the script | |
# So url is "/head/<username or uuid>/<size>", with size and .png extension being optional | |
RewriteRule ^head/([^/]+?)(?:/([^/]+?))?/?(?:\.png)?$ head.php?user=$1&size=$2 [L] | |
# --------- end of file --------- | |
*/ | |
// ------------------------------------------------------------------------------------- // | |
// YOU DON'T NEED TO READ BELOW, IT IS ONLY SCRIPT AND PROCESSING PART // | |
// ------------------------------------------------------------------------------------- // | |
/* Requirements | |
--------------------------------------*/ | |
// Check PDO Sqlite | |
if (!function_exists('extension_loaded') or !extension_loaded('pdo_sqlite')) { | |
echo '<h2>Installation required</h2>'; | |
echo 'The extension <b>pdo_sqlite</b> is not enabled. ' | |
. 'Contact your webhost or enable it yourself to use this script. ' | |
. 'More informations can be found <a href="http://php.net/manual/ref.pdo-sqlite.php" target="_blank">here</a>.'; | |
exit; | |
} | |
// Check Mojang API class | |
if (!is_file(MOJANGAPI_LOCATION)) { | |
// Try to download it | |
$parentFolder = dirname(MOJANGAPI_LOCATION); | |
$parentOfParent = dirname($parentFolder); | |
if (AUTO_INSTALL === true and is_dir($parentOfParent)) { | |
$mojangApi = @file_get_contents('https://raw.githubusercontent.com/MineTheCube/MojangAPI/master/mojang-api.class.php'); | |
if (strlen($mojangApi) > 20000) { | |
if (!is_dir($parentFolder)) mkdir($parentFolder); | |
file_put_contents(MOJANGAPI_LOCATION, $mojangApi); | |
} | |
} | |
// MojangAPI is still missing | |
if (!is_file(MOJANGAPI_LOCATION)) { | |
echo '<h2>Installation required</h2>'; | |
echo 'You need to <a href="https://github.com/MineTheCube/MojangAPI" target="_blank">download <b>mojang-api.class.php</b></a>' | |
. ' in the following folder: <b>' . htmlentities(str_replace('\\', '/', dirname(DATABASE_LOCATION))) . '/</b>'; | |
exit; | |
} | |
} | |
// Check database | |
if (!is_dir(dirname(DATABASE_LOCATION))) { | |
// Try to create folder | |
if (AUTO_INSTALL === true) { | |
$parentFolder = dirname(DATABASE_LOCATION); | |
$parentOfParent = dirname($parentFolder); | |
if (AUTO_INSTALL === true and is_dir($parentOfParent)) { | |
mkdir($parentFolder); | |
} | |
} | |
// Folder still not created | |
if (!is_dir(dirname(DATABASE_LOCATION))) { | |
echo '<h2>Installation required</h2>'; | |
echo 'You need to create the following folder: <b>' . htmlentities(str_replace('\\', '/', dirname(DATABASE_LOCATION))) . '/</b>'; | |
exit; | |
} | |
} | |
/* Initialization | |
--------------------------------------*/ | |
// Require MojangAPI | |
require_once MOJANGAPI_LOCATION; | |
// Get query parameters | |
// User can be either username or UUID | |
$user = !empty($_GET['user']) ? (string) $_GET['user'] : null; | |
$size = !empty($_GET['size']) ? (int) $_GET['size'] : DEFAULT_SIZE; | |
// Start database connection | |
try { | |
// We'll create a new database | |
$initDatabase = !is_file(DATABASE_LOCATION); | |
// Ensure we have write access | |
if ($initDatabase) chmod(dirname(DATABASE_LOCATION), 0755); | |
// Try to connect | |
$pdo = new PDO('sqlite:' . DATABASE_LOCATION, null, null, array(PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION)); | |
// And ensure we can write to it | |
if ($initDatabase) chmod(DATABASE_LOCATION, 0666); | |
} catch (PDOException $e) { | |
// Nope, giving up here.. | |
echo '<h2>Cannot connect to database</h2>'; | |
echo 'The following error happened when trying to connect to sqlite database:'; | |
echo '<pre>' . $e->getMessage() . '</pre>'; | |
exit; | |
} | |
// Create table if missing | |
$pdo->exec('CREATE TABLE IF NOT EXISTS cache (username TEXT NOT NULL, uuid TEXT NOT NULL, skin TEXT NOT NULL, time INTEGER NOT NULL)'); | |
// Delete old skin data | |
$time = time() - CACHE_TIMEOUT; | |
$stmt = $pdo->prepare('DELETE FROM cache WHERE time < ?'); | |
$stmt->execute(array($time)); | |
// One out 20 requests, we do a VACUUM to free unused space | |
if (rand(0, 20) === 0) $pdo->exec('VACUUM'); | |
$errors = array(); | |
/* Verify parameters | |
--------------------------------------*/ | |
// Ensure size is correct | |
if ($size >= MINIMUM_SIZE and $size <= MAXIMUM_SIZE) { | |
if (MojangAPI::isValidUuid($user)) { | |
// We have a correct UUID | |
$uuid = MojangAPI::minifyUuid($user); | |
$username = null; | |
$field = 'uuid'; | |
$value = $uuid; | |
} else if (MojangAPI::isValidUsername($user)) { | |
// We have a correct username | |
$username = $user; | |
$uuid = null; | |
$field = 'username'; | |
$value = strtolower($username); | |
} else { | |
$errors[] = 'No valid UUID or username given'; | |
} | |
/* Get skin | |
--------------------------------------*/ | |
// We have both field and value defined | |
if (isset($field) and isset($value)) { | |
$skin = null; | |
$stmt = $pdo->prepare('SELECT skin FROM cache WHERE ' . $field . ' = ?'); | |
$stmt->execute(array($value)); | |
$result = $stmt->fetch(); | |
// If no cache available | |
if (empty($result)) { | |
// Let's fetch the uuid or username missing | |
if (!empty($uuid)) { | |
$username = MojangAPI::getUsername($uuid); | |
} else { | |
$profile = MojangAPI::getProfile($username); | |
if (!empty($profile)) { | |
$username = $profile['name']; | |
$uuid = $profile['id']; | |
} | |
} | |
// We should have both now | |
if (!empty($username) and !empty($uuid)) { | |
// Fetch the skin from Mojang's server | |
$skin = MojangAPI::getSkin($uuid); | |
// User exists but hasn't a skin | |
if (is_null($skin)) { | |
$skin = MojangAPI::isAlex($uuid) ? MojangAPI::getAlexSkin() : MojangAPI::getSteveSkin(); | |
} | |
if (!empty($skin)) { | |
// Cache result | |
$stmt = $pdo->prepare('INSERT INTO cache VALUES(?, ?, ?, ?)'); | |
$stmt->execute(array(strtolower($username), $uuid, base64_encode($skin), time())); | |
} else { | |
$errors[] = 'Cannot get skin from Mojang'; | |
} | |
} else { | |
$errors[] = 'Cannot get UUID or username from Mojang'; | |
} | |
} else { | |
// Get from cache | |
$skin = base64_decode($result['skin']); | |
} | |
/* Display it | |
--------------------------------------*/ | |
if (!empty($skin)) { | |
// Get head from skin | |
$head = MojangAPI::getPlayerHeadFromSkin($skin, $size); | |
// Print it with browser caching | |
MojangAPI::printImage($head, CACHE_TIMEOUT); | |
exit; | |
} | |
} | |
} else { | |
// Going to default size | |
$size = DEFAULT_SIZE; | |
$errors[] = 'Invalid size'; | |
} | |
/* An error happened | |
--------------------------------------*/ | |
if (DEBUG === true) { | |
// Display errors | |
echo '<h2>Something went wrong</h2>'; | |
echo '<ul><li>'; | |
echo implode('</li><li>', $errors); | |
echo '</li></ul>'; | |
} else { | |
// If we have an uuid, it may be alex | |
$head = (!empty($uuid) and MojangAPI::isAlex($uuid)) ? MojangAPI::getAlexHead($size) : MojangAPI::getSteveHead($size); | |
// Display default skin, with 15min caching | |
MojangAPI::printImage($head, 900); | |
} | |
// Exit to ensure nothing will be displayed after the image | |
exit; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment