Parcourir la source

initial data commit

pull/1/head
DragonSkills99 il y a 6 ans
Parent
révision
132cf67cd7

+ 358
- 0
Plugin.php Voir le fichier

@@ -0,0 +1,358 @@
<?php
class MinecraftPaymentPlugin extends Plugin {
public static function get_plugin_name(): string {
return 'Minecraft Payment';
}

public function __construct( $_DB ) {
$this->require_class( 'RCon' );
}

public function has_page(): bool {
return true;
}

public function get_page_path() {
return [
'/minecraft-pay/' => [
'settings' => [
null => 'settings_view',
'/*' => 'server_settings_view'
],
'users' => [
null => 'users_view',
'/*' => 'user_view'
],
'grant' => 'grant_view',
'settle' => 'settle_view',
'balance' => 'balance_view',
'acredit' => 'acredit_view'
]
];
// return [ '/minecraft-pay/settings', '/minecraft-pay/settings/*', '/minecraft-pay/users', '/minecraft-pay/grant', '/minecraft-pay/settle', '/minecraft-pay/balance', '/minecraft-pay/users/*', '/minecraft-pay/acredit' ];
}

public function grant_view( string $url ) {
if ( !Permission::PERMITTED( 'Minecraft-Pay-Settings', 1 ) ) return;
$params = [];
if ( array_key_exists( 'GrantUserRights', $_POST ) && array_key_exists( 'ID', $_POST ) ) {
$u = User::GetByID( $_POST[ 'ID' ] );
$s = false;
if ( !is_null( $u ) ) {
$p = Permission::SEARCH( 'Minecraft-Possess-User' );
$s = $p->grant_user( $u->GetID(), true ); $s = true;
// echo $p;
// echo $s;
$params[ 'save_message' ] =
// $s ?
__( [ 'de' => 'Recht erfolgreich gew&auml;hrt', 'en' => 'Right granted successfully' ] ); // :
// __( [ 'de' => 'Recht konnte nicht gew&auml;hrt werden', 'en' => 'Right could not be granted' ] );
}
else $params[ 'save_message' ] = __( [ 'de' => 'Benutzer nicht gefunden', 'en' => 'Could not find user' ] );
$params[ 'save_success' ] = $s;
}
$this->show_template( 'GrantUser', $params );
}

public function settle_view( string $url ) {
$m = array_key_exists( 'month', $_GET ) ? $_GET[ 'month' ] : date( 'm' ) - 1;
$y = array_key_exists( 'month', $_GET ) ? $_GET[ 'month' ] : date( 'Y' );
if ( $m == '0' ) { $m = '12'; $y--; }

$mp = MinecraftMonthPaid::GetByUnique( 0, $m ,$y );
if ( $mp ) {
echo __( [ 'de' => 'Bereits abgerechnet', 'en' => 'Already settled' ] );
return;
}

$sum = 0;

foreach ( MinecraftServer::GetAll() as $server ) {
$m = strlen( $m ) == 2 ? $m : '0' . $m;
$f = "$y-$m-01";
$cap = date( 't', strtotime( $f ) );
$l = "$y-$m-$cap";
$sid = $server->ID;

$subscribers = MinecraftServerSubscription::GetAll( "ConcerningServerID = $sid AND SubscriptionDate BETWEEN '$f' AND '$l'" );
$subsCount = count( $subscribers );
$pot = $subsCount * $server->GetPerMonthPrice();
$potPart = ceil( ( $pot / $subsCount ) * 100 ) / 100;
if ( $pot == 0 ) continue;
$potPart *= -1;
if ( $pot > $server->GetMaxPerMonthPrice() ) $pot = $server->GetMaxPerMonthPrice();
$sum += $pot;
/* $dayssum = 0;

$subs = [];
$sum += $pot;
$potheap = 0;
$dayssumheap = 0;

foreach( $subscribers as $subscriber ) {
$days = date( 'd', strtotime( $subscriber->GetSubscriptionDate() ) );
$dayssum += $days;
$subs[] = [ $days, $subscriber ];
}

foreach ( $subs as $subscription ) {
$price = $pot * ( $dayssum / $subscription[ 0 ] )
}*/

foreach( $subscribers as $subscriber ) {
$u = $subscriber->GetUnlockedUser()->GetOwner();
$ac = new MinecraftUserAccount();
$ac->SetMod( $potPart );
$ac->SetDebtor( $u );
$ac->SetComment( 'Host-Relief for ' . $server->GetName() . ' for ' . $m . '-' . $y );
$ac->Save();
}

$server->ClearWhitelist();
}

$mp = new MinecraftMonthPaid();
$mp->SetAmount( $sum );
$mp->SetMonth( $m );
$mp->SetYear( $y );
if ( $mp->Save() ) {
echo __( [ 'de' => 'Abrechnung beendet', 'en' => 'Settled' ] );
}
}

public function acredit_view( string $url ) {
if ( !Permission::PERMITTED( 'Minecraft-Pay-Settings', 1 ) ) return;
$params = null;
if (
array_key_exists( 'AddAccountChange', $_POST ) &&
array_key_exists( 'Mod', $_POST ) &&
array_key_exists( 'DebtorID', $_POST ) &&
array_key_exists( 'Comment', $_POST )
) {
$ac = MinecraftUserAccount::FromPropertyArray( $_POST );
$ac->SetDebtor( User::GetByID( $_POST[ 'DebtorID' ] ) );
$params = [];
$params[ 'save_success' ] = $ac->Save();
$params[ 'save_message' ] =
$params[ 'save_success' ] ?
__( [ 'de' => 'Gutschrift erfolgreich', 'en' => 'Credit successful' ] ) :
__( [ 'de' => 'Gutschrift fehlgeschlagen', 'en' => 'Credit failed' ] );
}
$this->show_template( 'AlterAccount', $params );
}

public function balance_view( string $url ) {
if ( !Permission::PERMITTED( 'Minecraft-Possess-User', 1 ) ) return;
$this->show_template( 'AccountList', null );
}

public function users_view( string $url ) {
if ( !Permission::PERMITTED( 'Minecraft-Possess-User', 1 ) ) return;
if ( $url == '/minecraft-pay/users' ) {
$params = [];
if ( array_key_exists( 'CreateMinecraftUser', $_POST ) && array_key_exists( 'Username', $_POST ) ) {
$s = MinecraftUser::FromPropertyArray( $_POST );
$s->SetOwner( User::CURRENT() );
try {
$s->Save();
$params[ 'save_message' ] = __( [ 'de' => 'Minecraft Benutzer erfolgreich angelegt', 'en' => 'Created minecraft user successfully' ] );
$params[ 'save_success' ] = true;
} catch( Exception $ex ) {
$params[ 'save_message' ] = $ex->getMessage();
if ( startsWith( $params[ 'save_message' ], 'Duplicate entry' ) )
$params[ 'save_message' ] = __(
[
'de' => 'Doppelter Name oder es wurde bei einem anderen Server weder Domain noch Port angegeben',
'en' => 'Duplicated Name or another server has neither domain nor port'
]
);
$params[ 'save_success' ] = false;
}
}
if ( array_key_exists( 'DeleteMinecraftUser', $_POST ) && array_key_exists( 'ID', $_POST ) ) {
$s = MinecraftUser::GetByID( $_POST[ 'ID' ] );

if ( User::CURRENT()->GetID() != $s->GetOwner()->GetID() ) {
$params[ 'save_message' ] = __( [ 'de' => 'Dieser Benutzer geh&ouml;t Ihnen nicht!', 'en' => 'This user does not belong to you!' ] );
$params[ 'save_success' ] = false;
} else {
try {
$s->Delete();
$params[ 'save_message' ] = __( [ 'de' => 'Minecraft Benutzer erfolgreich gel&ouml;scht', 'en' => 'Deleted minecraft user successfully' ] );
$params[ 'save_success' ] = true;
} catch( Exception $ex ) {
$params[ 'save_message' ] = $ex->getMessage();
$params[ 'save_success' ] = false;
}
}
}
$this->show_template( 'UsersList', $params );
} else $this->user_view( $url );
}

public function user_view( string $url ) {
if ( !Permission::PERMITTED( 'Minecraft-Possess-User', 1 ) ) return;
if ( !preg_match( '/\/minecraft-pay\/users\/([0-9]+)/', $url, $m ) || is_null( MinecraftUser::GetByID( $m[ 1 ] ) ) ) {
Alert::SHOW( __( [ 'de' => 'Dieser Benutzer existiert nicht', 'en' => 'This user does not exist' ] ) );
return;
}

$params = [];

if ( array_key_exists( 'RUnlockUser', $_POST ) && array_key_exists( 'ID', $_POST ) ) {
$s = MinecraftServer::GetByID( $_POST[ 'ID' ] );
$u = MinecraftUser::GetByID( $m[ 1 ] );

if ( is_null( $s ) ) { $params[ 'save_message' ] = __( [ 'de' => 'Unbekannter Server', 'en' => 'Unknown server' ] ); $params[ 'save_success' ] = false; }
else if ( is_null( $u ) ) { $params[ 'save_message' ] = __( [ 'de' => 'Unbekannter Benutzer', 'en' => 'Unknown user' ] ); $params[ 'save_success' ] = false; }
else {
if ( $s->Unlock( $u ) ) {
if ( !$u->HasSubscripted( $s ) ) {
$ms = new MinecraftServerSubscription();
$ms->SetConcerningServer( $s );
$ms->SetUnlockedUser( $u );
$params[ 'save_success' ] = $ms->Save();
$params[ 'save_message' ] =
$params[ 'save_success' ] ?
__( [ 'de' => 'Erfolgreich freigeschaltet', 'en' => 'Unlock successful' ] ) :
__( [ 'de' => 'Freischaltung fehlgeschlagen', 'en' => 'Unlock failed' ] );
if ( !$params[ 'save_success' ] ) $s->Lock( $u );
} else { $params[ 'save_message' ] = __( [ 'de' => 'Erfolgreich freigeschaltet', 'en' => 'Unlock successful' ] ); $params[ 'save_success' ] = true; }
} else { $params[ 'save_message' ] = __( [ 'de' => 'Freischaltung fehlgeschlagen', 'en' => 'Unlock failed' ] ); $params[ 'save_success' ] = false; }
}
}

$params[ 'user' ] = MinecraftUser::GetByID( $m[ 1 ] );
$this->show_template( 'Users', $params );
}

public function settings_view( string $url ) {
if ( !Permission::PERMITTED( 'Minecraft-Pay-Settings', 1 ) ) return;
if ( $url == '/minecraft-pay/settings' ) {
$params = [];
if ( array_key_exists( 'CreateServer', $_POST ) && array_key_exists( 'Name', $_POST ) ) {
$s = MinecraftServer::FromPropertyArray( $_POST );
try {
$s->Save();
$params[ 'save_message' ] = __( [ 'de' => 'Server erfolgreich angelegt', 'en' => 'Created server successfully' ] );
$params[ 'save_success' ] = true;
} catch( Exception $ex ) {
$params[ 'save_message' ] = $ex->getMessage();
if ( startsWith( $params[ 'save_message' ], 'Duplicate entry' ) )
$params[ 'save_message' ] = __(
[
'de' => 'Doppelter Name oder es wurde bei einem anderen Server weder Domain noch Port angegeben',
'en' => 'Duplicated Name or another server has neither domain nor port'
]
);
$params[ 'save_success' ] = false;
}
}
if ( array_key_exists( 'DeleteServer', $_POST ) && array_key_exists( 'ID', $_POST ) ) {
$s = MinecraftServer::FromPropertyArray( $_POST );
try {
$s->Delete();
$params[ 'save_message' ] = __( [ 'de' => 'Server erfolgreich gel&ouml;scht', 'en' => 'Deleted server successfully' ] );
$params[ 'save_success' ] = true;
} catch( Exception $ex ) {
$params[ 'save_message' ] = $ex->getMessage();
$params[ 'save_success' ] = false;
}
}
$this->show_template( 'SettingsList', $params );
}
else $this->server_settings_view( $url );
// $this->show_template( 'Settings', [ 'settings' => (object) [ 'Server' => '', 'Port' => 35575, 'Password' => '' ] ] );
}

public function server_settings_view( string $url ) {
if ( !Permission::PERMITTED( 'Minecraft-Pay-Settings', 1 ) ) return;
if ( !preg_match( '/\/minecraft-pay\/settings\/([0-9]+)/', $url, $m ) || is_null( MinecraftServer::GetByID( $m[ 1 ] ) ) ) {
Alert::SHOW( __( [ 'de' => 'Dieser Server existiert nicht', 'en' => 'This server does not exist' ] ) );
return;
}
$params = [];
if (
array_key_exists( 'SaveServerSettings', $_POST ) &&
array_key_exists( 'Domain', $_POST ) &&
array_key_exists( 'Port', $_POST ) &&
array_key_exists( 'Password', $_POST ) &&
array_key_exists( 'ServerPath', $_POST )
) {
if ( !$_POST[ 'Port' ] ) $_POST[ 'Port' ] = null;
$o = MinecraftServer::GetByID( $m[ 1 ] );
$s = MinecraftServer::FromPropertyArray( $_POST );
$s->SetID( $o->GetID() );
$s->SetName( $o->GetName() );
try {
$s->Save();
$params[ 'save_message' ] = __( [ 'de' => 'Server erfolgreich gespeichert', 'en' => 'Saved server successfully' ] );
$params[ 'save_success' ] = true;
} catch( Exception $ex ) {
$params[ 'save_message' ] = $ex->getMessage();
if ( startsWith( $params[ 'save_message' ], 'Duplicate entry' ) )
$params[ 'save_message' ] = __(
[
'de' => 'Doppelte Domain noch Port Kombination',
'en' => 'Duplicated domain - port combination'
]
);
$params[ 'save_success' ] = false;
}
}
$params[ 'settings' ] = MinecraftServer::GetByID( $m[ 1 ] );
$this->show_template( 'Settings', $params );
}

public function load_plugin(): void {
if ( is_null( Permission::GetByUnique( 0, 'Minecraft-Pay-Settings' ) ) ) {
$p = Permission::FromArray( [], [] );
$p->SetName( 'Minecraft-Pay-Settings' );
$p->SetSlug( slugify( 'Minecraft-Pay-Settings' ) );
$p->Save();
}
if ( is_null( Permission::GetByUnique( 0, 'Minecraft-Possess-User' ) ) ) {
$p = Permission::FromArray( [], [] );
$p->SetName( 'Minecraft-Possess-User' );
$p->SetSlug( slugify( 'Minecraft-Possess-User' ) );
$p->Save();
}

if ( User::ONLINE() && Permission::PERMITTED( 'Minecraft-Possess-User' ) ) {
$me = new MenuEntry( 'Minecraft Payment' );
$me->addImageFromResource( 'minecraft.svg', MinecraftPaymentPlugin::get_plugin_name() );
$me->setFilter( 'none' );

if ( Permission::PERMITTED( 'Minecraft-Pay-Settings' ) ) {
$sub = new MenuEntry( 'Minecraft Payment', HOME_URL . 'minecraft-pay/settings' );
$sub->addImageFromResource( 'settings.svg', Plugin_Plugin::get_plugin_name() );
$me->addSubEntry( $sub );
}

$sub = new MenuEntry( [ 'de' => 'Minecraft Benutzer', 'en' => 'Minecraft Users' ], HOME_URL . 'minecraft-pay/users' );
$sub->addImageFromResource( 'users.svg', UserManager_Plugin::get_plugin_name() );
$me->addSubEntry( $sub );

if ( Permission::PERMITTED( 'Minecraft-Pay-Settings' ) ) {
$sub = new MenuEntry( [ 'de' => 'Gutschrift', 'en' => 'Credit' ], HOME_URL . 'minecraft-pay/acredit' );
$sub->addImageFromResource( 'cash.svg', MinecraftPaymentPlugin::get_plugin_name() );
$me->addSubEntry( $sub );
}

$sub = new MenuEntry( [ 'de' => 'Transaktionen', 'en' => 'Transactions' ], HOME_URL . 'minecraft-pay/balance' );
$sub->addImageFromResource( 'cash.svg', MinecraftPaymentPlugin::get_plugin_name() );
$me->addSubEntry( $sub );

if ( Permission::PERMITTED( 'Minecraft-Pay-Settings' ) ) {
$sub = new MenuEntry( [ 'de' => 'Recht gew&auml;hren', 'en' => 'Grant right' ], HOME_URL . 'minecraft-pay/grant' );
$sub->addImageFromResource( 'key.svg', MinecraftPaymentPlugin::get_plugin_name() );
$me->addSubEntry( $sub );
};

SideMenu::addMainMenuEntry( $me );
}
}
}

+ 211
- 0
classes/RCon.class.php Voir le fichier

@@ -0,0 +1,211 @@
<?php
/**
* See https://developer.valvesoftware.com/wiki/Source_RCON_Protocol for
* more information about Source RCON Packets
*
* PHP Version 7
*
* @copyright 2013-2017 Chris Churchwell
* @author thedudeguy
* @link https://github.com/thedudeguy/PHP-Minecraft-Rcon
*/

class Rcon
{
private $host;
private $port;
private $password;
private $timeout;

private $socket;

private $authorized = false;
private $lastResponse = '';

const PACKET_AUTHORIZE = 5;
const PACKET_COMMAND = 6;

const SERVERDATA_AUTH = 3;
const SERVERDATA_AUTH_RESPONSE = 2;
const SERVERDATA_EXECCOMMAND = 2;
const SERVERDATA_RESPONSE_VALUE = 0;

/**
* Create a new instance of the Rcon class.
*
* @param string $host
* @param integer $port
* @param string $password
* @param integer $timeout
*/
public function __construct($host, $port, $password, $timeout)
{
$this->host = $host;
$this->port = $port;
$this->password = $password;
$this->timeout = $timeout;
}

/**
* Get the latest response from the server.
*
* @return string
*/
public function getResponse()
{
return $this->lastResponse;
}

/**
* Connect to a server.
*
* @return boolean
*/
public function connect()
{
$this->socket = fsockopen($this->host, $this->port, $errno, $errstr, $this->timeout);

if (!$this->socket) {
$this->lastResponse = $errstr;
return false;
}

//set timeout
stream_set_timeout($this->socket, 3, 0);

// check authorization
return $this->authorize();
}

/**
* Disconnect from server.
*
* @return void
*/
public function disconnect()
{
if ($this->socket) {
fclose($this->socket);
}
$this->authorized = false;
}

/**
* True if socket is connected and authorized.
*
* @return boolean
*/
public function isConnected()
{
return $this->authorized;
}

/**
* Send a command to the connected server.
*
* @param string $command
*
* @return boolean|mixed
*/
public function sendCommand($command)
{
if (!$this->isConnected()) {
return false;
}

// send command packet
$this->writePacket(self::PACKET_COMMAND, self::SERVERDATA_EXECCOMMAND, $command);

// get response
$response_packet = $this->readPacket();
if ($response_packet['id'] == self::PACKET_COMMAND) {
if ($response_packet['type'] == self::SERVERDATA_RESPONSE_VALUE) {
$this->lastResponse = $response_packet['body'];

return $response_packet['body'];
}
}

return false;
}

/**
* Log into the server with the given credentials.
*
* @return boolean
*/
private function authorize()
{
$this->writePacket(self::PACKET_AUTHORIZE, self::SERVERDATA_AUTH, $this->password);
$response_packet = $this->readPacket();

if ($response_packet['type'] == self::SERVERDATA_AUTH_RESPONSE) {
if ($response_packet['id'] == self::PACKET_AUTHORIZE) {
$this->authorized = true;

return true;
}
}

$this->disconnect();
return false;
}

/**
* Writes a packet to the socket stream.
*
* @param $packetId
* @param $packetType
* @param string $packetBody
*
* @return void
*/
private function writePacket($packetId, $packetType, $packetBody)
{
/*
Size 32-bit little-endian Signed Integer Varies, see below.
ID 32-bit little-endian Signed Integer Varies, see below.
Type 32-bit little-endian Signed Integer Varies, see below.
Body Null-terminated ASCII String Varies, see below.
Empty String Null-terminated ASCII String 0x00
*/

//create packet
$packet = pack('VV', $packetId, $packetType);
$packet = $packet.$packetBody."\x00";
$packet = $packet."\x00";

// get packet size.
$packet_size = strlen($packet);

// attach size to packet.
$packet = pack('V', $packet_size).$packet;

// write packet.
fwrite($this->socket, $packet, strlen($packet));
}

/**
* Read a packet from the socket stream.
*
* @return array
*/
private function readPacket()
{
//get packet size.
$size_data = fread($this->socket, 4);
$size_pack = unpack('V1size', $size_data);
$size = $size_pack['size'];

// if size is > 4096, the response will be in multiple packets.
// this needs to be address. get more info about multi-packet responses
// from the RCON protocol specification at
// https://developer.valvesoftware.com/wiki/Source_RCON_Protocol
// currently, this script does not support multi-packet responses.

$packet_data = fread($this->socket, $size);
$packet_pack = unpack('V1id/V1type/a*body', $packet_data);

return $packet_pack;
}
}

+ 1
- 0
imgs/cash.svg Voir le fichier

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><path d="M32 96v256h448V96H32zm160.5 224h-80.4c0-26.6-21.5-48.1-48.1-48.1V192c35.3 0 64-28.7 64-64h64.5c-19.9 23.5-32.5 57.8-32.5 96s12.6 72.5 32.5 96zM448 271.9c-26 0-48 21.5-48 48.1h-80.5c19.9-23.5 32.5-57.8 32.5-96s-12.6-72.5-32.5-96H384c0 35.3 28.7 64 64 64v79.9zM32 384h448v32H32z"/></svg>

+ 1
- 0
imgs/credit-card.svg Voir le fichier

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><path d="M435.2 80H76.8c-24.9 0-44.6 19.6-44.6 44L32 388c0 24.4 19.9 44 44.8 44h358.4c24.9 0 44.8-19.6 44.8-44V124c0-24.4-19.9-44-44.8-44zm0 308H76.8V256h358.4v132zm0-220H76.8v-44h358.4v44z"/></svg>

+ 1
- 0
imgs/key.svg Voir le fichier

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><path d="M249.2 224c-14.2-40.2-55.1-72-100.2-72-57.2 0-101 46.8-101 104s45.8 104 103 104c45.1 0 84.1-31.8 98.2-72H352v64h69.1v-64H464v-64H249.2zm-97.6 66.5c-19 0-34.5-15.5-34.5-34.5s15.5-34.5 34.5-34.5 34.5 15.5 34.5 34.5-15.5 34.5-34.5 34.5z"/></svg>

+ 1
- 0
imgs/lock.svg Voir le fichier

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><path d="M376 186h-20v-40c0-55-45-100-100-100S156 91 156 146v40h-20c-22.002 0-40 17.998-40 40v200c0 22.002 17.998 40 40 40h240c22.002 0 40-17.998 40-40V226c0-22.002-17.998-40-40-40zM256 368c-22.002 0-40-17.998-40-40s17.998-40 40-40 40 17.998 40 40-17.998 40-40 40zm62.002-182H193.998v-40c0-34.004 28.003-62.002 62.002-62.002 34.004 0 62.002 27.998 62.002 62.002v40z"/></svg>

+ 1
- 0
imgs/minecraft.svg Voir le fichier

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="480" height="480" viewBox="0 0 48 48"><path fill="#8BC34A" d="M11 7L21 7 20 11 23 11 21 16 25 16 27 11 30 11 31 7 41 7 35 33 3 33z"/><path fill="#263238" d="M40.754,6H40h-9h-0.74l-1.182,5H27.5h-1.299l-0.509,1.854L20.785,6H20h-7.266H11h-0.359h-0.01L2,33l8.908,9h0.229h2.004h7.982l1.523-6.172L23.698,37h2.62l4.104,5H30.6h1.784h8.538L46,17L40.754,6z M31.333,8h8.133l-1.808,8h-3.754l1.086-4.402c0.029-0.146-0.009-0.299-0.104-0.415C34.792,11.067,34.649,11,34.5,11h-3.908L31.333,8z M27.5,11.916V12h6.39l-1.012,4h-6.581l1.087-3.66L27.5,11.916z M18.887,11h-7.715l0.938-3h7.688L18.887,11z M12.334,33.042H4.369L4.328,33H4.297l3.125-10h1.915L7.52,29.362c-0.043,0.151-0.014,0.313,0.081,0.438C7.695,29.927,7.843,30,8,30h5.217L12.334,33.042z M9.52,26h4.858l-0.871,3H8.663L9.52,26z M25.094,33l2.628-11h-2.094h-1.121l-1.352,5H17.4l1.354-5h-3.215l-0.871,3H9.806l0.675-2.362c0.043-0.151,0.014-0.313-0.081-0.438C10.305,22.073,10.157,22,10,22H7.734l3.125-10h7.725H19h2.292l-1.354,5H25h1h11.432l-3.615,16H25.094z"/><path fill="#8D6E63" d="M18.841 40L12.334 33 4.328 33 11.182 40zM38.801 40L33.816 33 25.094 33 30.764 40zM23.036 33L23 33 24.117 28.324 23.084 27 17.484 27 24.071 35.001 24.678 35.001z"/></svg>

+ 1
- 0
imgs/unlock.svg Voir le fichier

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><path d="M376 186h-20v-40c0-55-45-100-100-100S156 91 156 146h37.998c0-34.004 28.003-62.002 62.002-62.002 34.004 0 62.002 27.998 62.002 62.002H318v40H136c-22.002 0-40 17.998-40 40v200c0 22.002 17.998 40 40 40h240c22.002 0 40-17.998 40-40V226c0-22.002-17.998-40-40-40zM256 368c-22.002 0-40-17.998-40-40s17.998-40 40-40 40 17.998 40 40-17.998 40-40 40z"/></svg>

+ 37
- 0
orm_schemas/MinecraftMonthPaid.class.php Voir le fichier

@@ -0,0 +1,37 @@
<?php
/**
* @Name minecraft_month_paid
* @Unique Month, Year
*/
class MinecraftMonthPaid extends Entity {
/**
* @DB-Column
* @Name ID
* @Type INT
* @Primary
* @AutoIncrement
* @NotNull
*/
public $ID;
/**
* @DB-Column
* @Name Amount
* @Type DECIMAL(10,2)
* @NotNull
*/
public $Amount;
/**
* @DB-Column
* @Name Month
* @Type INT(4)
* @NotNull
*/
public $Month;
/**
* @DB-Column
* @Name Year
* @Type INT
* @NotNull
*/
public $Year;
}

+ 132
- 0
orm_schemas/MinecraftServer.class.php Voir le fichier

@@ -0,0 +1,132 @@
<?php
/**
* @Name minecraft_server
* @Unique Name
* @Unique Domain, Port
*/
class MinecraftServer extends Entity {
/**
* @DB-Column
* @Name ID
* @Type INT
* @Primary
* @AutoIncrement
* @NotNull
*/
public $ID;
/**
* @DB-Column
* @Name Name
* @Type VARCHAR(256)
* @NotNull
*/
public $Name;
/**
* @DB-Column
* @Name Domain
* @Type VARCHAR(256)
*/
public $Domain = null;
/**
* @DB-Column
* @Name Port
* @Type INT(4)
*/
public $Port = null;
/**
* @DB-Column
* @Name Password
* @Type VARCHAR(256)
*/
public $Password = null;
/**
* @DB-Column
* @Name ServerPath
* @Type VARCHAR(256)
*/
public $ServerPath = null;
/**
* @DB-Column
* @Name PerMonthPrice
* @Type INT(4)
*/
public $PerMonthPrice = null;
/**
* @DB-Column
* @Name MaxPerMonthPrice
* @Type INT(4)
*/
public $MaxPerMonthPrice = null;
/**
* @DB-Relation
* @Field ID
* @FieldName SubscriptionID
* @OneToMany
* @OnUpdate CASCADE
* @OnDelete CASCADE
* @var MinecraftServer[]
*/
public $Subscriptions;

public function IsUnlocked( MinecraftUser $user ): bool {
return in_array( strtolower( $user->GetUsername() ), $this->GetWhitelistedNames() );
}

private $RCon = null;

private function GetRCon() {
if ( $this->RCon == null ) $this->RCon = new Rcon( $this->GetDomain(), $this->GetPort(), $this->GetPassword(), 1500 );
return $this->RCon;
}

public function Unlock( MinecraftUser $user, bool $keepOpen = false ): bool {
$rcon = $this->GetRCon();
if ( !$rcon->isConnected() ) $rcon->connect();
$rcon->sendCommand( 'whitelist add ' . $user->GetUsername() );
$res = $rcon->getResponse();
if ( !$keepOpen ) $rcon->disconnect();
return $this->IsUnlocked( $user );
}

public function Lock( MinecraftUser $user, bool $keepOpen = false ): bool {
$rcon = $this->GetRCon();
if ( !$rcon->isConnected() ) $rcon->connect();
$rcon->sendCommand( 'whitelist remove ' . $user->GetUsername() );
$res = $rcon->getResponse();
if ( !$keepOpen ) $rcon->disconnect();
return !$this->IsUnlocked( $user );
}

public function GetWhitelistedNames( bool $keepOpen = false ) {
// There are 1 whitelisted players: DragonSkills99
$rcon = $this->GetRCon();
if ( !$rcon->isConnected() ) $rcon->connect();
$rcon->sendCommand( 'whitelist list' );
$res = $rcon->getResponse();
if ( !$keepOpen ) $rcon->disconnect();
if ( nocase_compare( 'There are no whitelisted players', trim( $res ) ) ) return [];
preg_match( '/^There are [0-9]+ whitelisted players: (.*)/', trim( $res ), $m );
if ( !isset( $m[ 1 ] ) ) return [];
$players = explode( ', ', strtolower( $m[ 1 ] ) );
if ( trim( $players[ 0 ] ) == '' ) return [];
else return $players;
}

public function ClearWhitelist( int $tries = 3 ) {
$rcon = $this->GetRCon();
$players = $this->GetWhitelistedNames( true );
if ( !count( $players ) ) { $rcon->disconnect(); return true; }

foreach( $players as $player ) {
$rcon->sendCommand( "whitelist remove $player" );
}

$nplayers = $this->GetWhitelistedNames( true );
if ( count( $nplayers ) ) {
if ( $tries > 0 ) $this->ClearWhitelist( $tries - 1 );
else { $rcon->disconnect(); return false; }
}
$rcon->disconnect();
return true;
}
}

+ 43
- 0
orm_schemas/MinecraftServerSubscription.class.php Voir le fichier

@@ -0,0 +1,43 @@
<?php
/**
* @Name minecraft_server_subscription
*/
class MinecraftServerSubscription extends Entity {
/**
* @DB-Column
* @Name ID
* @Type INT
* @Primary
* @AutoIncrement
* @NotNull
*/
public $ID;
/**
* @DB-Relation
* @Field ID
* @FieldName ConcerningServerID
* @ManyToOne
* @OnUpdate CASCADE
* @OnDelete CASCADE
* @var MinecraftServer
*/
public $ConcerningServer;
/**
* @DB-Relation
* @Field ID
* @FieldName UnlockedUserID
* @ManyToOne
* @OnUpdate CASCADE
* @OnDelete CASCADE
* @var MinecraftUser
*/
public $UnlockedUser;
/**
* @DB-Column
* @Name SubscriptionDate
* @Default CURRENT_TIMESTAMP
* @Type TIMESTAMP
* @NotNull
*/
public $SubscriptionDate;
}

+ 53
- 0
orm_schemas/MinecraftUser.class.php Voir le fichier

@@ -0,0 +1,53 @@
<?php
/**
* @Name minecraft_user
* @Unique Username
*/
class MinecraftUser extends Entity {
/**
* @DB-Column
* @Name ID
* @Type INT
* @Primary
* @AutoIncrement
* @NotNull
*/
public $ID;
/**
* @DB-Column
* @Name Username
* @Type VARCHAR(256)
* @NotNull
* @Pattern /^[a-zA-Z0-9_]{3,16}$/
* @Pattern-Missmatch-Comment [ 'de' => 'Der Benutzername ist nur 3-16 Zeichen lang und enth&auml;lt a-z, A-Z, 0-9, _', 'en' => 'The Username is only 3-16 chars long and contains only a-z, A-Z, 0-9, _' ]
*/
public $Username;
/**
* @DB-Relation
* @Field ID
* @FieldName SubscriptionID
* @OneToMany
* @OnUpdate CASCADE
* @OnDelete CASCADE
* @var MinecraftServer[]
*/
public $Subscriptions;
/**
* @DB-Relation
* @Field ID
* @FieldName OwnerID
* @ManyToOne
* @OnUpdate CASCADE
* @OnDelete CASCADE
* @var User
*/
public $Owner;

public function HasSubscripted( MinecraftServer $server ) {
$f = date( 'Y-m-01' ); $l = date( 'Y-m-t' );
$uid = $this->GetID();
$sid = $server->GetID();
$earlier = MinecraftServerSubscription::GetAll( "SubscriptionDate BETWEEN '$f' AND '$l' AND UnlockedUserID = $uid AND ConcerningServerID = $sid" );
return !!count( $earlier );
}
}

+ 51
- 0
orm_schemas/MinecraftUserAccount.class.php Voir le fichier

@@ -0,0 +1,51 @@
<?php
/**
* @Name minecraft_user_account
*/
class MinecraftUserAccount extends Entity {
/**
* @DB-Column
* @Name ID
* @Type INT
* @Primary
* @AutoIncrement
* @NotNull
*/
public $ID;
/**
* @DB-Column
* @Name Modifier
* @Type DECIMAL(10,2)
* @NotNull
*/
public $Mod;
/**
* @DB-Column
* @Name Comment
* @Type TEXT
*/
public $Comment;
/**
* @DB-Relation
* @Field ID
* @FieldName DebtorID
* @ManyToOne
* @OnUpdate CASCADE
* @OnDelete CASCADE
* @var User
*/
public $Debtor;
/**
* @DB-Column
* @Name Occurence
* @Type TIMESTAMP
* @Default CURRENT_TIMESTAMP
* @NotNull
*/
public $Occurence;

public static function ACCOUNT() {
if ( User::ONLINE() ) return defaulted( MinecraftUserAccount::SUM( 'Modifier', [ 'DebtorID' => User::CURRENT()->ID ] ), '0' );
return '0';
}
}

+ 4
- 0
templates/Account.Template.php Voir le fichier

@@ -0,0 +1,4 @@
<meta log-in />
<div style="width: 100%; text-align: right; border: 1px solid white; border-radius: 1rem; padding: 1rem; margin: 1rem 0; box-sizing: border-box;">
<span>Account: <a eval-innerText="MinecraftUserAccount::ACCOUNT() . ' &euro;'"></a></span>
</div>

+ 20
- 0
templates/AccountList.Template.php Voir le fichier

@@ -0,0 +1,20 @@
<meta log-in permission="Minecraft-Possess-User" />
<div dyn-if="isset( $save_message )">
<div dyn-type="alert" eval-value="$save_message" eval-type="$save_success ? ALERT_SUCCESS : ALERT_DANGER"></div>
</div>
<table class="table">
<thead>
<tr>
<th eval-innerText="__( [ 'de' => 'Datum', 'en' => 'Date' ] )"></th>
<th style="width: 100%;" eval-innerText="__( [ 'de' => 'Kommentar', 'en' => 'Comment' ] )"></th>
<th eval-innerText="__( [ 'de' => 'Menge', 'en' => 'Amount' ] )"></th>
</tr>
</thead>
<tbody>
<tr dyn-for="[ 'credit', 'MinecraftUserAccount::GetAll( [ \'DebtorID\' => User::CURRENT()->ID ] )' ]">
<td eval-innerText="$credit->GetOccurence()"></td>
<td eval-innerText="$credit->GetComment()"></td>
<td style="text-align: right;" eval-innerText="$credit->GetMod() . '&nbsp;&euro;'"></td>
</tr>
</tbody>
</table>

+ 40
- 0
templates/AlterAccount.Template.php Voir le fichier

@@ -0,0 +1,40 @@
<meta log-in permission="Minecraft-Pay-Settings" />
<div dyn-if="isset( $save_message )">
<div dyn-type="alert" eval-value="$save_message" eval-type="$save_success ? ALERT_SUCCESS : ALERT_DANGER"></div>
</div>
<form method="POST">
<table>
<thead>
<tr>
<th innerText="Minecraft Payment" colspan="2"></th>
</tr>
</thead>
<tbody>
<tr>
<th eval-innerText="__([ 'de' => 'Benutzer', 'en' => 'User' ])"></th>
<td>
<select name="DebtorID">
<div dyn-for="[ 'user', 'User::GetAll()' ]"><option eval-value="$user->GetID()" eval-innerText="$user->GetUsername()"></option></div>
</select>
</td>
</tr>
<tr>
<th eval-innerText="__([ 'de' => 'Menge', 'en' => 'Amount' ])"></th>
<td>
<input type="number" step="0.01" name="Mod" value="0.00" />
</td>
</tr>
<tr>
<th eval-innerText="__([ 'de' => 'Kommentar', 'en' => 'Comment' ])"></th>
<td>
<input type="string" name="Comment" />
</td>
</tr>
<tr>
<td colspan="2">
<input type="submit" name="AddAccountChange" eval-value="__([ 'de' => 'Gutschreiben', 'en' => 'Credit' ])" />
</td>
</tr>
</tbody>
</table>
</form>

+ 28
- 0
templates/GrantUser.Template.php Voir le fichier

@@ -0,0 +1,28 @@
<meta log-in permission="Minecraft-Pay-Settings" />
<div dyn-if="isset( $save_message )">
<div dyn-type="alert" eval-value="$save_message" eval-type="$save_success ? ALERT_SUCCESS : ALERT_DANGER"></div>
</div>
<form method="POST">
<table>
<thead>
<tr>
<th innerText="Minecraft Payment" colspan="2"></th>
</tr>
</thead>
<tbody>
<tr>
<th eval-innerText="__([ 'de' => 'Benutzer', 'en' => 'User' ])"></th>
<td>
<select name="ID">
<div dyn-for="[ 'user', 'User::GetAll()' ]"><option eval-value="$user->GetID()" eval-innerText="$user->GetUsername()"></option></div>
</select>
</td>
</tr>
<tr>
<td colspan="2">
<input type="submit" name="GrantUserRights" eval-value="__([ 'de' => 'Als Minecraft Nutzer eintragte', 'en' => 'Enter as Minecraft User' ])" />
</td>
</tr>
</tbody>
</table>
</form>

+ 56
- 0
templates/Settings.Template.php Voir le fichier

@@ -0,0 +1,56 @@
<meta log-in permission="Minecraft-Pay-Settings" />
<div dyn-if="isset( $save_message )">
<div dyn-type="alert" eval-value="$save_message" eval-type="$save_success ? ALERT_SUCCESS : ALERT_DANGER"></div>
</div>
<form method="POST">
<table>
<thead>
<tr>
<th eval-innerText="'Minecraft Payment ' . __([ 'de' => 'Einstellungen', 'en' => 'Settings' ])" colspan="2"></th>
</tr>
</thead>
<tbody>
<tr>
<th eval-innerText="__([ 'de' => 'Dom&auml;ne', 'en' => 'Domain' ])"></th>
<td>
<input type="text" name="Domain" eval-value="$settings->GetDomain()" />
</td>
</tr>
<tr>
<th eval-innerText="__([ 'de' => 'Port', 'en' => 'Port' ])"></th>
<td>
<input type="number" name="Port" eval-value="$settings->GetPort()" />
</td>
</tr>
<tr>
<th eval-innerText="__([ 'de' => 'Passwort', 'en' => 'Password' ])"></th>
<td>
<input type="password" name="Password" eval-value="$settings->GetPassword()" />
</td>
</tr>
<tr>
<th eval-innerText="__([ 'de' => 'Server-Pfad', 'en' => 'Server-Path' ])"></th>
<td>
<input type="text" name="ServerPath" eval-value="$settings->GetServerPath()" />
</td>
</tr>
<tr>
<th eval-innerText="__([ 'de' => 'Preis/Monat', 'en' => 'Price/Month' ])"></th>
<td>
<input type="number" name="PerMonthPrice" eval-value="$settings->GetPerMonthPrice()" />
</td>
</tr>
<tr>
<th eval-innerText="__([ 'de' => 'Preis/Monat (Limit)', 'en' => 'Price/Month (Limit)' ])"></th>
<td>
<input type="number" name="MaxPerMonthPrice" eval-value="$settings->GetMaxPerMonthPrice()" />
</td>
</tr>
<tr>
<td colspan="2">
<input type="submit" name="SaveServerSettings" eval-value="__([ 'de' => 'Speichern', 'en' => 'Save' ])" />
</td>
</tr>
</tbody>
</table>
</form>

+ 42
- 0
templates/SettingsList.Template.php Voir le fichier

@@ -0,0 +1,42 @@
<meta log-in permission="Minecraft-Pay-Settings" />
<div dyn-if="isset( $save_message )">
<div dyn-type="alert" eval-value="$save_message" eval-type="$save_success ? ALERT_SUCCESS : ALERT_DANGER"></div>
</div>
<form method="POST">
<table class="table">
<tbody>
<tr>
<td><input type="text" name="Name" /></td>
<td><input type="submit" name="CreateServer" eval-value="__( [ 'de' => 'Server anlegen', 'en' => 'Create server' ] )" /></td>
</tr>
</tbody>
</table>
</form>
<hr />
<table class="table">
<thead>
<tr>
<th style="width: 100%;">Name</th>
<th colspan="2"></th>
</tr>
</thead>
<tbody>
<tr dyn-for="[ 'server', 'MinecraftServer::GetAll()' ]">
<td eval-innerText="$server->GetName()"></td>
<td>
<a style="cursor: pointer;" eval-href="HOME_URL . 'minecraft-pay/settings/' . $server->GetID()">
<input style="cursor: pointer;" type="button" eval-value="__( [ 'de' => 'Bearbeiten', 'en' => 'Edit' ] )" />
</a>
</td>
<td>
<form method="POST">
<input type="hidden" name="ID" eval-value="$server->GetID()" />
<input type="submit" name="DeleteServer" eval-value="__( [ 'de' => 'L&ouml;schen', 'en' => 'Delete' ] )" />
</form>
<a eval-href="">
</a>
</td>
</tr>
</tbody>
</table>

+ 38
- 0
templates/Users.Template.php Voir le fichier

@@ -0,0 +1,38 @@
<meta log-in permission="Minecraft-Possess-User" />
<div dyn-if="isset( $save_message )">
<div dyn-type="alert" eval-value="$save_message" eval-type="$save_success ? ALERT_SUCCESS : ALERT_DANGER"></div>
</div>
<form method="POST">
<table class="table">
<thead>
<tr>
<th eval-innerText="$user->GetUsername()" colspan="2"></th>
</tr>
</thead>
<tbody>
<tr>
<th colspan="2" eval-innerText="__([ 'de' => 'Server', 'en' => 'Server' ])"></th>
</tr>
<tr>
<td colspan="2">
<table class="table">
<tbody>
<tr dyn-for="[ 'server', 'MinecraftServer::GetAll()' ]">
<td style="vertical-align: middle; width: 100%" dyn-set="[ 'isUnlocked' => '$server->IsUnlocked( $user )' ]" eval-innerText="$server->GetName()"></td>
<td>
<form method="POST">
<input type="hidden" name="ID" eval-value="$server->GetID()" />
<input type="submit" dyn-if="!$isUnlocked" eval-name="( isset( $_POST[ 'UnlockUser' ] ) &amp;&amp; $_POST[ 'ID' ] == $server->GetID() ) ? 'RUnlockUser' : 'UnlockUser'"
eval-style="( isset( $_POST[ 'UnlockUser' ] ) &amp;&amp; $_POST[ 'ID' ] == $server->GetID() ) ? 'background-color: red' : ''"
eval-value="__( [ 'de' => 'Freischalten', 'en' => 'Unlock' ] ) . ' ~' . $server->GetPerMonthPrice() . ' &euro;'" />
</form>
</td>
<td><img style="height: 1em; filter: invert( 1 ); vertical-align: middle;" eval-src="HOME_URL . 'imgs/' . MinecraftPaymentPlugin::get_plugin_name() . '/' . ($isUnlocked ? 'unlock.svg' : 'lock.svg')" /></td>
</tr>
</tbody>
</table>
</td>
</tr>
</tbody>
</table>
</form>

+ 42
- 0
templates/UsersList.Template.php Voir le fichier

@@ -0,0 +1,42 @@
<meta log-in permission="Minecraft-Possess-User" />
<div dyn-if="isset( $save_message )">
<div dyn-type="alert" eval-value="$save_message" eval-type="$save_success ? ALERT_SUCCESS : ALERT_DANGER"></div>
</div>
<form method="POST">
<table class="table">
<tbody>
<tr>
<td><input type="text" name="Username" eval-placeholder="__( [ 'de' => 'Benutzername', 'en' => 'Username' ] )" /></td>
<td><input type="submit" name="CreateMinecraftUser" eval-value="__( [ 'de' => 'Minecraft Benutzer hinzuf&uuml;gen', 'en' => 'Add Minecraft User' ] )" /></td>
</tr>
</tbody>
</table>
</form>
<hr />
<table class="table">
<thead>
<tr>
<th style="width: 100%;">Name</th>
<th colspan="2"></th>
</tr>
</thead>
<tbody>
<tr dyn-for="[ 'user', 'MinecraftUser::GetAll( [ \'OwnerID\' => User::CURRENT()->GetID() ] )' ]">
<td eval-innerText="$user->GetUsername()"></td>
<td>
<a style="cursor: pointer;" eval-href="HOME_URL . 'minecraft-pay/users/' . $user->GetID()">
<input style="cursor: pointer;" type="button" eval-value="__( [ 'de' => 'Bearbeiten', 'en' => 'Edit' ] )" />
</a>
</td>
<td>
<form method="POST">
<input type="hidden" name="ID" eval-value="$user->GetID()" />
<input type="submit" name="DeleteMinecraftUser" eval-value="__( [ 'de' => 'L&ouml;schen', 'en' => 'Delete' ] )" />
</form>
<a eval-href="">
</a>
</td>
</tr>
</tbody>
</table>

Chargement…
Annuler
Enregistrer