mirror of
https://github.com/NamelessMC/Nameless
synced 2026-08-18 06:29:04 -04:00
253 lines
8.6 KiB
PHP
253 lines
8.6 KiB
PHP
<?php
|
|
/**
|
|
* MinecraftIntegration class
|
|
*
|
|
* @package Modules\Core\Integrations
|
|
* @author Partydragen
|
|
* @version 2.1.0
|
|
* @license MIT
|
|
*/
|
|
class MinecraftIntegration extends IntegrationBase {
|
|
|
|
protected Language $_language;
|
|
private string $_uuid;
|
|
|
|
public function __construct(Language $language) {
|
|
$this->_name = 'Minecraft';
|
|
$this->_icon = 'fas fa-cubes';
|
|
$this->_language = $language;
|
|
$this->_settings = ROOT_PATH . '/modules/Core/includes/admin_integrations/minecraft.php';
|
|
|
|
parent::__construct();
|
|
}
|
|
|
|
private function flashVerifyCommand(string $verification_code): void {
|
|
$verification_command = Output::getClean(Settings::get('minecraft_verify_command', '/verify'));
|
|
$message = $this->_language->get('user', 'validate_account_command', ['command' => $verification_command . ' ' . $verification_code]);
|
|
Session::flash('connections_success', $message);
|
|
}
|
|
|
|
public function onLinkRequest(User $user) {
|
|
$username = $user->data()->username;
|
|
|
|
// Validate username
|
|
if (!$this->validateUsername($username)) {
|
|
return;
|
|
}
|
|
|
|
$result = $this->getUuidByUsername($username);
|
|
if (count($this->getErrors())) {
|
|
return;
|
|
}
|
|
$this->_uuid = $result['uuid'];
|
|
|
|
// Validate identifier
|
|
if (!$this->validateIdentifier($this->_uuid)) {
|
|
return;
|
|
}
|
|
|
|
$code = SecureRandom::alphanumeric();
|
|
|
|
$integrationUser = new IntegrationUser($this);
|
|
$integrationUser->linkIntegration($user, $this->_uuid, $username, false, $code);
|
|
|
|
$this->flashVerifyCommand($code);
|
|
}
|
|
|
|
public function onVerifyRequest(User $user) {
|
|
$integrationUser = new IntegrationUser($this, $user->data()->id, 'user_id');
|
|
|
|
$code = $integrationUser->data()->code;
|
|
if ($code === null) {
|
|
$code = SecureRandom::alphanumeric();
|
|
|
|
$integrationUser->update([
|
|
'code' => $code
|
|
]);
|
|
}
|
|
|
|
$this->flashVerifyCommand($code);
|
|
}
|
|
|
|
public function onUnlinkRequest(User $user) {
|
|
$integrationUser = new IntegrationUser($this, $user->data()->id, 'user_id');
|
|
$integrationUser->unlinkIntegration();
|
|
|
|
Session::flash('connections_success', $this->_language->get('user', 'integration_unlinked', ['integration' => Output::getClean($this->_name)]));
|
|
}
|
|
|
|
public function onSuccessfulVerification(IntegrationUser $integrationUser) {
|
|
// Nothing to do here
|
|
}
|
|
|
|
public function validateUsername(string $username, int $integration_user_id = 0): bool {
|
|
$validation = Validate::check(['username' => $username], [
|
|
'username' => [
|
|
Validate::REQUIRED => true,
|
|
Validate::MIN => 3,
|
|
Validate::MAX => 20
|
|
]
|
|
])->messages([
|
|
'username' => [
|
|
Validate::REQUIRED => $this->_language->get('admin', 'integration_username_required', ['integration' => $this->getName()]),
|
|
Validate::MIN => $this->_language->get('user', 'mcname_minimum_3'),
|
|
Validate::MAX => $this->_language->get('user', 'mcname_maximum_20')
|
|
]
|
|
]);
|
|
|
|
if (count($validation->errors())) {
|
|
// Validation errors
|
|
foreach ($validation->errors() as $error) {
|
|
$this->addError($error);
|
|
}
|
|
} else {
|
|
// Ensure identifier doesn't already exist
|
|
$exists = DB::getInstance()->query("SELECT * FROM nl2_users_integrations WHERE integration_id = ? AND username = ? AND id <> ?", [$this->data()->id, $username, $integration_user_id]);
|
|
if ($exists->count()) {
|
|
$this->addError($this->_language->get('user', 'integration_username_already_linked', ['integration' => $this->getName()]));
|
|
return false;
|
|
}
|
|
}
|
|
|
|
return $validation->passed();
|
|
}
|
|
|
|
public function validateIdentifier(string $identifier, int $integration_user_id = 0): bool {
|
|
$validation = Validate::check(['identifier' => $identifier], [
|
|
'identifier' => [
|
|
Validate::REQUIRED => true,
|
|
Validate::MIN => 32,
|
|
Validate::MAX => 32
|
|
]
|
|
])->messages([
|
|
'identifier' => [
|
|
Validate::REQUIRED => $this->_language->get('admin', 'integration_identifier_required', ['integration' => $this->getName()]),
|
|
Validate::MIN => $this->_language->get('admin', 'integration_identifier_invalid', ['integration' => $this->getName()]),
|
|
Validate::MAX => $this->_language->get('admin', 'integration_identifier_invalid', ['integration' => $this->getName()]),
|
|
]
|
|
]);
|
|
|
|
if (count($validation->errors())) {
|
|
// Validation errors
|
|
foreach ($validation->errors() as $error) {
|
|
$this->addError($error);
|
|
}
|
|
} else {
|
|
// Ensure identifier doesn't already exist
|
|
$exists = DB::getInstance()->query("SELECT * FROM nl2_users_integrations WHERE integration_id = ? AND identifier = ? AND id <> ?", [$this->data()->id, $identifier, $integration_user_id]);
|
|
if ($exists->count()) {
|
|
$this->addError($this->_language->get('user', 'integration_identifier_already_linked', ['integration' => $this->getName()]));
|
|
return false;
|
|
}
|
|
}
|
|
|
|
return $validation->passed();
|
|
}
|
|
|
|
public function onRegistrationPageLoad(Fields $fields) {
|
|
if (Settings::get('mc_username_registration', '1', 'Minecraft Integration') != '1') {
|
|
return;
|
|
}
|
|
|
|
$username_value = ((isset($_POST['username']) && $_POST['username']) ? Output::getClean(Input::get('username')) : '');
|
|
|
|
$fields->add('username', Fields::TEXT, $this->_language->get('user', 'minecraft_username'), true, $username_value, null, null, 1);
|
|
}
|
|
|
|
public function beforeRegistrationValidation(Validate $validate) {
|
|
// Nothing to do here
|
|
}
|
|
|
|
public function afterRegistrationValidation() {
|
|
if (Settings::get('mc_username_registration', '1', 'Minecraft Integration') != '1') {
|
|
return;
|
|
}
|
|
|
|
$username = Input::get('username');
|
|
|
|
// Validate username
|
|
if (!$this->validateUsername($username)) {
|
|
return;
|
|
}
|
|
|
|
// Get minecraft UUID
|
|
$result = $this->getUuidByUsername($username);
|
|
if (count($this->getErrors())) {
|
|
return;
|
|
}
|
|
$this->_uuid = $result['uuid'];
|
|
|
|
// Validate identifier
|
|
if (!$this->validateIdentifier($this->_uuid)) {
|
|
return;
|
|
}
|
|
}
|
|
|
|
public function successfulRegistration(User $user) {
|
|
if (Settings::get('mc_username_registration', '1', 'Minecraft Integration') != '1') {
|
|
return;
|
|
}
|
|
|
|
$code = SecureRandom::alphanumeric();
|
|
|
|
$integrationUser = new IntegrationUser($this);
|
|
$integrationUser->linkIntegration($user, $this->_uuid, Input::get('username'), false, $code);
|
|
}
|
|
|
|
public function syncIntegrationUser(IntegrationUser $integration_user): bool {
|
|
$profile = ProfileUtils::getProfile($integration_user->data()->identifier);
|
|
|
|
if ($profile) {
|
|
$result = $profile->getUsername();
|
|
|
|
if (!empty($result)) {
|
|
$integration_user->update([
|
|
'username' => $result,
|
|
'last_sync' => date('U')
|
|
]);
|
|
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* Get minecraft UUID by username
|
|
*
|
|
* @param string $username
|
|
* @return array
|
|
*/
|
|
public function getUuidByUsername(string $username): array {
|
|
if (Settings::get('uuid_linking')) {
|
|
return $this->getOnlineModeUuid($username);
|
|
}
|
|
|
|
return ProfileUtils::getOfflineModeUuid($username);
|
|
}
|
|
|
|
/**
|
|
* Query mojang api to get online-mode UUID.
|
|
*
|
|
* @param string $username
|
|
* @return array
|
|
*/
|
|
public function getOnlineModeUuid(string $username): array {
|
|
$profile = ProfileUtils::getProfile(str_replace(' ', '%20', $username));
|
|
|
|
$mcname_result = $profile ? $profile->getProfileAsArray() : [];
|
|
if (isset($mcname_result['username'], $mcname_result['uuid']) && !empty($mcname_result['username']) && !empty($mcname_result['uuid'])) {
|
|
// Valid
|
|
return [
|
|
'uuid' => $mcname_result['uuid'],
|
|
'username' => $mcname_result['username']
|
|
];
|
|
}
|
|
|
|
// Invalid
|
|
$this->addError($this->_language->get('user', 'invalid_mcname'));
|
|
|
|
return [];
|
|
}
|
|
}
|