Upload via GUI (90 Dateien)
This commit is contained in:
@@ -2,7 +2,7 @@
|
||||
/**
|
||||
* Plugin Name: AeroMC Freunde
|
||||
* Description: Backend für das Freundesystem des AeroMC Launchers - meldet, wer gerade online/im Spiel ist, und verwaltet Freundschaftsanfragen. Keine eigene Anmeldung: der Launcher meldet sich direkt mit der Minecraft-UUID des jeweiligen Kontos.
|
||||
* Version: 1.0.0
|
||||
* Version: 1.1.0
|
||||
* Author: M_Viper
|
||||
*/
|
||||
|
||||
@@ -10,9 +10,10 @@ if (!defined('ABSPATH')) {
|
||||
exit; // kein direkter Aufruf der Datei
|
||||
}
|
||||
|
||||
define('AEROMC_FRIENDS_VERSION', '1.0.0');
|
||||
define('AEROMC_FRIENDS_VERSION', '1.1.0');
|
||||
define('AEROMC_FRIENDS_PRESENCE_TABLE', 'aeromc_presence');
|
||||
define('AEROMC_FRIENDS_FRIENDS_TABLE', 'aeromc_friends');
|
||||
define('AEROMC_FRIENDS_INVITES_TABLE', 'aeromc_invites');
|
||||
|
||||
/**
|
||||
* Legt die beiden Tabellen an (bzw. bringt sie bei einem Update auf den
|
||||
@@ -23,6 +24,7 @@ function aeromc_friends_install() {
|
||||
$charset_collate = $wpdb->get_charset_collate();
|
||||
$presence_table = $wpdb->prefix . AEROMC_FRIENDS_PRESENCE_TABLE;
|
||||
$friends_table = $wpdb->prefix . AEROMC_FRIENDS_FRIENDS_TABLE;
|
||||
$invites_table = $wpdb->prefix . AEROMC_FRIENDS_INVITES_TABLE;
|
||||
|
||||
require_once ABSPATH . 'wp-admin/includes/upgrade.php';
|
||||
|
||||
@@ -34,6 +36,7 @@ function aeromc_friends_install() {
|
||||
username varchar(32) NOT NULL,
|
||||
instance_name varchar(128) DEFAULT NULL,
|
||||
server_label varchar(128) DEFAULT NULL,
|
||||
mc_version varchar(32) DEFAULT NULL,
|
||||
last_seen datetime NOT NULL,
|
||||
PRIMARY KEY (uuid)
|
||||
) $charset_collate;";
|
||||
@@ -50,7 +53,31 @@ function aeromc_friends_install() {
|
||||
KEY uuid_b (uuid_b)
|
||||
) $charset_collate;";
|
||||
dbDelta($sql_friends);
|
||||
|
||||
// Einladungen "Komm auf meinen Server" - gelten nur ein paar Minuten
|
||||
$sql_invites = "CREATE TABLE $invites_table (
|
||||
id bigint(20) unsigned NOT NULL AUTO_INCREMENT,
|
||||
from_uuid varchar(32) NOT NULL,
|
||||
to_uuid varchar(32) NOT NULL,
|
||||
server varchar(128) NOT NULL,
|
||||
mc_version varchar(32) DEFAULT NULL,
|
||||
created_at datetime NOT NULL,
|
||||
PRIMARY KEY (id),
|
||||
KEY to_uuid (to_uuid)
|
||||
) $charset_collate;";
|
||||
dbDelta($sql_invites);
|
||||
|
||||
update_option('aeromc_friends_db_version', AEROMC_FRIENDS_VERSION);
|
||||
}
|
||||
register_activation_hook(__FILE__, 'aeromc_friends_install');
|
||||
|
||||
// Beim Ersetzen der Plugin-Dateien (Update per Upload) läuft der
|
||||
// Aktivierungs-Hook NICHT erneut - neue Spalten/Tabellen deshalb anlegen,
|
||||
// sobald die gespeicherte DB-Version nicht mehr zur Plugin-Version passt.
|
||||
add_action('plugins_loaded', function () {
|
||||
if (get_option('aeromc_friends_db_version') !== AEROMC_FRIENDS_VERSION) {
|
||||
aeromc_friends_install();
|
||||
}
|
||||
});
|
||||
|
||||
require_once plugin_dir_path(__FILE__) . 'includes/routes.php';
|
||||
|
||||
@@ -20,7 +20,38 @@ if (!defined('ABSPATH')) {
|
||||
define('AEROMC_FRIENDS_ONLINE_SECONDS', 180);
|
||||
// Häufigere Herzschläge als das werden ignoriert (Schutz gegen Missbrauch/
|
||||
// versehentliche Anfrageflut) - der Launcher selbst sendet ohnehin nur alle 60s.
|
||||
// Ausnahme: hat sich der Server geändert, wird sofort gespeichert ("Beitreten").
|
||||
define('AEROMC_FRIENDS_HEARTBEAT_MIN_GAP', 20);
|
||||
// So lange ist eine Einladung "Komm auf meinen Server" gültig.
|
||||
define('AEROMC_FRIENDS_INVITE_SECONDS', 600);
|
||||
// Frühestens nach so vielen Sekunden darf derselbe Freund erneut eingeladen werden.
|
||||
define('AEROMC_FRIENDS_INVITE_MIN_GAP', 30);
|
||||
|
||||
function aeromc_friends_invites_table() {
|
||||
global $wpdb;
|
||||
return $wpdb->prefix . AEROMC_FRIENDS_INVITES_TABLE;
|
||||
}
|
||||
|
||||
/** Server-Adresse (Host oder IP, optional :Port) - nur harmlose Zeichen. */
|
||||
function aeromc_friends_valid_server($server) {
|
||||
return is_string($server) && preg_match('/^[A-Za-z0-9.\-_:\[\]]{1,128}$/', $server);
|
||||
}
|
||||
|
||||
/** Minecraft-Version wie "1.21.1", "24w14a" oder "1.20.1-pre2". */
|
||||
function aeromc_friends_clean_version($version) {
|
||||
$version = (string) $version;
|
||||
return preg_match('/^[A-Za-z0-9.\-_ ]{1,32}$/', $version) ? $version : '';
|
||||
}
|
||||
|
||||
/** Sind die beiden befreundet (Anfrage angenommen)? */
|
||||
function aeromc_friends_are_friends($a, $b) {
|
||||
global $wpdb;
|
||||
$friends_table = aeromc_friends_friends_table();
|
||||
return (bool) $wpdb->get_var($wpdb->prepare(
|
||||
"SELECT id FROM $friends_table WHERE ((uuid_a = %s AND uuid_b = %s) OR (uuid_a = %s AND uuid_b = %s)) AND status = 'accepted'",
|
||||
$a, $b, $b, $a
|
||||
));
|
||||
}
|
||||
|
||||
function aeromc_friends_presence_table() {
|
||||
global $wpdb;
|
||||
@@ -89,9 +120,24 @@ add_action('rest_api_init', function () {
|
||||
'callback' => 'aeromc_friends_route_remove',
|
||||
'permission_callback' => '__return_true',
|
||||
]);
|
||||
register_rest_route('aeromc/v1', '/friends/invite', [
|
||||
'methods' => 'POST',
|
||||
'callback' => 'aeromc_friends_route_invite',
|
||||
'permission_callback' => '__return_true',
|
||||
]);
|
||||
register_rest_route('aeromc/v1', '/friends/invites', [
|
||||
'methods' => 'GET',
|
||||
'callback' => 'aeromc_friends_route_invites',
|
||||
'permission_callback' => '__return_true',
|
||||
]);
|
||||
register_rest_route('aeromc/v1', '/friends/invites/dismiss', [
|
||||
'methods' => 'POST',
|
||||
'callback' => 'aeromc_friends_route_invite_dismiss',
|
||||
'permission_callback' => '__return_true',
|
||||
]);
|
||||
});
|
||||
|
||||
/** POST /presence {uuid, username, instance, server} */
|
||||
/** POST /presence {uuid, username, instance, server, version} */
|
||||
function aeromc_friends_route_presence($request) {
|
||||
global $wpdb;
|
||||
$uuid = aeromc_friends_normalize_uuid($request->get_param('uuid'));
|
||||
@@ -101,12 +147,14 @@ function aeromc_friends_route_presence($request) {
|
||||
}
|
||||
$instance = sanitize_text_field((string) $request->get_param('instance'));
|
||||
$server = sanitize_text_field((string) $request->get_param('server'));
|
||||
$version = aeromc_friends_clean_version($request->get_param('version'));
|
||||
$table = aeromc_friends_presence_table();
|
||||
|
||||
$letzte = $wpdb->get_var($wpdb->prepare(
|
||||
"SELECT last_seen FROM $table WHERE uuid = %s", $uuid
|
||||
$letzte = $wpdb->get_row($wpdb->prepare(
|
||||
"SELECT last_seen, server_label FROM $table WHERE uuid = %s", $uuid
|
||||
));
|
||||
if ($letzte && (time() - strtotime($letzte)) < AEROMC_FRIENDS_HEARTBEAT_MIN_GAP) {
|
||||
$server_gleich = $letzte && (string) $letzte->server_label === (string) $server;
|
||||
if ($letzte && $server_gleich && (time() - strtotime($letzte->last_seen)) < AEROMC_FRIENDS_HEARTBEAT_MIN_GAP) {
|
||||
return ['ok' => true]; // zu häufig - stillschweigend ignoriert
|
||||
}
|
||||
|
||||
@@ -118,11 +166,11 @@ function aeromc_friends_route_presence($request) {
|
||||
// Zeitzone praktisch nie als offline erkannt worden wäre.
|
||||
$jetzt_utc = current_time('mysql', true);
|
||||
$wpdb->query($wpdb->prepare(
|
||||
"INSERT INTO $table (uuid, username, instance_name, server_label, last_seen)
|
||||
VALUES (%s, %s, %s, %s, %s)
|
||||
ON DUPLICATE KEY UPDATE username = %s, instance_name = %s, server_label = %s, last_seen = %s",
|
||||
$uuid, $username, $instance ?: null, $server ?: null, $jetzt_utc,
|
||||
$username, $instance ?: null, $server ?: null, $jetzt_utc
|
||||
"INSERT INTO $table (uuid, username, instance_name, server_label, mc_version, last_seen)
|
||||
VALUES (%s, %s, %s, %s, %s, %s)
|
||||
ON DUPLICATE KEY UPDATE username = %s, instance_name = %s, server_label = %s, mc_version = %s, last_seen = %s",
|
||||
$uuid, $username, $instance ?: null, $server ?: null, $version ?: null, $jetzt_utc,
|
||||
$username, $instance ?: null, $server ?: null, $version ?: null, $jetzt_utc
|
||||
));
|
||||
return ['ok' => true];
|
||||
}
|
||||
@@ -147,7 +195,7 @@ function aeromc_friends_route_list($request) {
|
||||
$ergebnis = [];
|
||||
foreach ($rows as $row) {
|
||||
$p = $wpdb->get_row($wpdb->prepare(
|
||||
"SELECT username, instance_name, server_label, last_seen FROM $presence_table WHERE uuid = %s",
|
||||
"SELECT username, instance_name, server_label, mc_version, last_seen FROM $presence_table WHERE uuid = %s",
|
||||
$row->other_uuid
|
||||
));
|
||||
$online = $p && (time() - strtotime($p->last_seen)) < AEROMC_FRIENDS_ONLINE_SECONDS;
|
||||
@@ -157,6 +205,7 @@ function aeromc_friends_route_list($request) {
|
||||
'online' => (bool) $online,
|
||||
'instance' => $online ? $p->instance_name : null,
|
||||
'server' => $online ? $p->server_label : null,
|
||||
'version' => $online ? $p->mc_version : null,
|
||||
];
|
||||
}
|
||||
return $ergebnis;
|
||||
@@ -301,3 +350,87 @@ function aeromc_friends_route_remove($request) {
|
||||
));
|
||||
return ['ok' => true];
|
||||
}
|
||||
|
||||
/** POST /friends/invite {uuid, targetUuid, server, version} - "Komm auf meinen Server" */
|
||||
function aeromc_friends_route_invite($request) {
|
||||
global $wpdb;
|
||||
$uuid = aeromc_friends_normalize_uuid($request->get_param('uuid'));
|
||||
$target = aeromc_friends_normalize_uuid($request->get_param('targetUuid'));
|
||||
$server = (string) $request->get_param('server');
|
||||
$version = aeromc_friends_clean_version($request->get_param('version'));
|
||||
if (!$uuid || !$target || !aeromc_friends_valid_server($server)) {
|
||||
return new WP_Error('aeromc_invalid', 'Ungültige uuid/targetUuid/server.', ['status' => 400]);
|
||||
}
|
||||
if (!aeromc_friends_are_friends($uuid, $target)) {
|
||||
return new WP_Error('aeromc_not_friends', 'Ihr seid nicht befreundet.', ['status' => 403]);
|
||||
}
|
||||
$table = aeromc_friends_invites_table();
|
||||
|
||||
$letzte = $wpdb->get_var($wpdb->prepare(
|
||||
"SELECT created_at FROM $table WHERE from_uuid = %s AND to_uuid = %s ORDER BY id DESC LIMIT 1",
|
||||
$uuid, $target
|
||||
));
|
||||
if ($letzte && (time() - strtotime($letzte)) < AEROMC_FRIENDS_INVITE_MIN_GAP) {
|
||||
return new WP_Error('aeromc_too_fast', 'Du hast diesen Freund gerade erst eingeladen.', ['status' => 429]);
|
||||
}
|
||||
|
||||
// ältere Einladung an denselben Freund ersetzen
|
||||
$wpdb->query($wpdb->prepare(
|
||||
"DELETE FROM $table WHERE from_uuid = %s AND to_uuid = %s", $uuid, $target
|
||||
));
|
||||
$wpdb->insert($table, [
|
||||
'from_uuid' => $uuid,
|
||||
'to_uuid' => $target,
|
||||
'server' => $server,
|
||||
'mc_version' => $version ?: null,
|
||||
'created_at' => current_time('mysql', true),
|
||||
]);
|
||||
return ['ok' => true];
|
||||
}
|
||||
|
||||
/** GET /friends/invites?uuid= - an mich gerichtete, noch gültige Einladungen */
|
||||
function aeromc_friends_route_invites($request) {
|
||||
global $wpdb;
|
||||
$uuid = aeromc_friends_normalize_uuid($request->get_param('uuid'));
|
||||
if (!$uuid) {
|
||||
return new WP_Error('aeromc_invalid', 'Ungültige uuid.', ['status' => 400]);
|
||||
}
|
||||
$table = aeromc_friends_invites_table();
|
||||
$presence_table = aeromc_friends_presence_table();
|
||||
|
||||
// abgelaufene Einladungen (aller Spieler) wegräumen
|
||||
$grenze = gmdate('Y-m-d H:i:s', time() - AEROMC_FRIENDS_INVITE_SECONDS);
|
||||
$wpdb->query($wpdb->prepare("DELETE FROM $table WHERE created_at < %s", $grenze));
|
||||
|
||||
$rows = $wpdb->get_results($wpdb->prepare(
|
||||
"SELECT i.id, i.from_uuid, p.username AS from_username, i.server, i.mc_version, i.created_at
|
||||
FROM $table i
|
||||
LEFT JOIN $presence_table p ON p.uuid = i.from_uuid
|
||||
WHERE i.to_uuid = %s
|
||||
ORDER BY i.id DESC",
|
||||
$uuid
|
||||
));
|
||||
return array_map(function ($r) {
|
||||
return [
|
||||
'id' => (int) $r->id,
|
||||
'fromUuid' => $r->from_uuid,
|
||||
'fromUsername' => $r->from_username,
|
||||
'server' => $r->server,
|
||||
'version' => $r->mc_version,
|
||||
'createdAt' => $r->created_at,
|
||||
];
|
||||
}, $rows);
|
||||
}
|
||||
|
||||
/** POST /friends/invites/dismiss {uuid, id} - Einladung erledigt/abgelehnt */
|
||||
function aeromc_friends_route_invite_dismiss($request) {
|
||||
global $wpdb;
|
||||
$uuid = aeromc_friends_normalize_uuid($request->get_param('uuid'));
|
||||
$id = (int) $request->get_param('id');
|
||||
if (!$uuid || $id <= 0) {
|
||||
return new WP_Error('aeromc_invalid', 'Ungültige uuid/id.', ['status' => 400]);
|
||||
}
|
||||
$table = aeromc_friends_invites_table();
|
||||
$wpdb->query($wpdb->prepare("DELETE FROM $table WHERE id = %d AND to_uuid = %s", $id, $uuid));
|
||||
return ['ok' => true];
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user