Update from Git Manager GUI
This commit is contained in:
@@ -2,12 +2,72 @@
|
||||
if ( ! defined( 'ABSPATH' ) ) exit;
|
||||
|
||||
class WBF_Ajax {
|
||||
// ── Discord-Rollen-Sync manuell anstoßen ────────────────────────────────
|
||||
public static function handle_manual_discord_sync() {
|
||||
self::verify();
|
||||
$user = WBF_Auth::get_current_user();
|
||||
if (!$user || WBF_Roles::level($user->role) < 80) {
|
||||
wp_send_json_error(['message' => 'Keine Berechtigung.']);
|
||||
}
|
||||
if (!function_exists('wbf_run_discord_role_sync')) {
|
||||
wp_send_json_error(['message' => 'Sync-Funktion nicht gefunden.']);
|
||||
}
|
||||
// Sync anstoßen (läuft synchron, kann bei vielen Usern etwas dauern)
|
||||
wbf_run_discord_role_sync();
|
||||
wp_send_json_success(['message' => 'Discord-Rollen-Sync wurde ausgeführt.']);
|
||||
}
|
||||
|
||||
// ── Discord-Rollen-Sync für einzelnen Nutzer ─────────────────────────────
|
||||
public static function handle_discord_sync_user() {
|
||||
self::verify();
|
||||
$admin = WBF_Auth::get_current_user();
|
||||
if ( ! $admin || WBF_Roles::level( $admin->role ) < 80 ) {
|
||||
wp_send_json_error( [ 'message' => 'Keine Berechtigung.' ] );
|
||||
}
|
||||
|
||||
$target_id = (int) ( $_POST['user_id'] ?? 0 );
|
||||
if ( ! $target_id ) {
|
||||
wp_send_json_error( [ 'message' => 'Keine Nutzer-ID.' ] );
|
||||
}
|
||||
|
||||
$s = function_exists( 'wbf_get_settings' ) ? wbf_get_settings() : [];
|
||||
$token = trim( $s['discord_bot_token'] ?? '' );
|
||||
$guild = trim( $s['discord_guild_id'] ?? '' );
|
||||
$role_map = json_decode( $s['discord_role_map'] ?? '{}', true ) ?: [];
|
||||
|
||||
if ( ! $token || ! $guild || empty( $role_map ) ) {
|
||||
wp_send_json_error( [ 'message' => 'Discord nicht konfiguriert.' ] );
|
||||
}
|
||||
|
||||
global $wpdb;
|
||||
$discord_uid = $wpdb->get_var( $wpdb->prepare(
|
||||
"SELECT meta_value FROM {$wpdb->prefix}forum_user_meta
|
||||
WHERE user_id = %d AND meta_key = 'discord_user_id'",
|
||||
$target_id
|
||||
) );
|
||||
|
||||
if ( ! $discord_uid ) {
|
||||
wp_send_json_error( [ 'message' => 'Nutzer hat kein verknüpftes Discord-Konto.' ] );
|
||||
}
|
||||
|
||||
// Beide Richtungen: Discord → Forum
|
||||
if ( function_exists( 'wbf_sync_discord_role_for_user' ) ) {
|
||||
wbf_sync_discord_role_for_user( $target_id, $discord_uid, $token, $guild, $role_map );
|
||||
}
|
||||
|
||||
// Frisch geladene Rolle zurückgeben damit die UI sofort aktualisiert werden kann
|
||||
$updated = WBF_DB::get_user( $target_id );
|
||||
wp_send_json_success( [
|
||||
'message' => 'Sync abgeschlossen.',
|
||||
'new_role' => $updated ? $updated->role : '',
|
||||
] );
|
||||
}
|
||||
|
||||
public static function init() {
|
||||
$actions = [
|
||||
'wbf_login', 'wbf_register', 'wbf_logout',
|
||||
'wbf_new_thread', 'wbf_new_post', 'wbf_toggle_like',
|
||||
'wbf_update_profile', 'wbf_upload_avatar', 'wbf_upload_post_image',
|
||||
'wbf_update_profile', 'wbf_upload_avatar', 'wbf_upload_banner', 'wbf_upload_post_image',
|
||||
'wbf_forgot_password', 'wbf_reset_password', 'wbf_load_more_messages',
|
||||
'wbf_create_invite', 'wbf_delete_invite',
|
||||
'wbf_toggle_subscribe', 'wbf_restore_content', 'wbf_toggle_profile_visibility',
|
||||
@@ -21,6 +81,11 @@ class WBF_Ajax {
|
||||
'wbf_toggle_ignore',
|
||||
'wbf_change_email',
|
||||
'wbf_save_notification_prefs',
|
||||
'wbf_save_discord',
|
||||
'wbf_discord_send_code',
|
||||
'wbf_discord_verify_code',
|
||||
'wbf_manual_discord_sync',
|
||||
'wbf_discord_sync_user',
|
||||
];
|
||||
foreach ($actions as $action) {
|
||||
add_action('wp_ajax_nopriv_' . $action, [__CLASS__, str_replace('wbf_','handle_',$action)]);
|
||||
@@ -507,6 +572,56 @@ class WBF_Ajax {
|
||||
wp_send_json_success(['avatar_url'=>$url]);
|
||||
}
|
||||
|
||||
// ── Banner Upload ────────────────────────────────────────────────────────
|
||||
|
||||
public static function handle_upload_banner() {
|
||||
self::verify();
|
||||
$user = WBF_Auth::get_current_user();
|
||||
if (!$user) wp_send_json_error(['message'=>'Nicht eingeloggt.']);
|
||||
if (empty($_FILES['banner'])) wp_send_json_error(['message'=>'Keine Datei.']);
|
||||
|
||||
$allowed_types = ['image/jpeg','image/png','image/gif','image/webp'];
|
||||
|
||||
// Max 4 MB für Banner (größer als Avatar)
|
||||
if ( $_FILES['banner']['size'] > 4 * 1024 * 1024 ) {
|
||||
wp_send_json_error(['message'=>'Maximale Dateigröße: 4 MB.']);
|
||||
}
|
||||
|
||||
// Server-seitige MIME-Typ-Prüfung
|
||||
$tmp = $_FILES['banner']['tmp_name'] ?? '';
|
||||
if ( ! $tmp || ! is_uploaded_file( $tmp ) ) {
|
||||
wp_send_json_error(['message'=>'Ungültiger Datei-Upload.']);
|
||||
}
|
||||
if ( function_exists('finfo_open') ) {
|
||||
$finfo = finfo_open( FILEINFO_MIME_TYPE );
|
||||
$real_mime = finfo_file( $finfo, $tmp );
|
||||
finfo_close( $finfo );
|
||||
} else {
|
||||
$et_map = [
|
||||
IMAGETYPE_JPEG => 'image/jpeg',
|
||||
IMAGETYPE_PNG => 'image/png',
|
||||
IMAGETYPE_GIF => 'image/gif',
|
||||
IMAGETYPE_WEBP => 'image/webp',
|
||||
];
|
||||
$et = @exif_imagetype( $tmp );
|
||||
$real_mime = $et_map[$et] ?? '';
|
||||
}
|
||||
if ( ! in_array( $real_mime, $allowed_types, true ) ) {
|
||||
wp_send_json_error(['message'=>'Nur JPG, PNG, GIF und WebP erlaubt.']);
|
||||
}
|
||||
|
||||
require_once ABSPATH . 'wp-admin/includes/image.php';
|
||||
require_once ABSPATH . 'wp-admin/includes/file.php';
|
||||
require_once ABSPATH . 'wp-admin/includes/media.php';
|
||||
|
||||
$id = media_handle_upload('banner', 0);
|
||||
if (is_wp_error($id)) wp_send_json_error(['message'=>$id->get_error_message()]);
|
||||
|
||||
$url = wp_get_attachment_url($id);
|
||||
WBF_DB::update_user($user->id, ['banner_url'=>$url]);
|
||||
wp_send_json_success(['banner_url'=>$url]);
|
||||
}
|
||||
|
||||
// ── Report ────────────────────────────────────────────────────────────────
|
||||
|
||||
public static function handle_report_post() {
|
||||
@@ -1447,6 +1562,182 @@ class WBF_Ajax {
|
||||
] );
|
||||
}
|
||||
|
||||
// ── Discord: Verifikations-Code per Bot-DM senden ─────────────────────────
|
||||
|
||||
public static function handle_discord_send_code() {
|
||||
self::verify();
|
||||
$user = WBF_Auth::get_current_user();
|
||||
if ( ! $user ) wp_send_json_error(['message' => 'Nicht eingeloggt.']);
|
||||
|
||||
$s = wbf_get_settings();
|
||||
$token = trim($s['discord_bot_token'] ?? '');
|
||||
$guild = trim($s['discord_guild_id'] ?? '');
|
||||
|
||||
if ( ! $token ) {
|
||||
wp_send_json_error(['message' => 'Discord-Bot ist noch nicht konfiguriert. Bitte wende dich an einen Admin.']);
|
||||
}
|
||||
|
||||
$username_input = sanitize_text_field($_POST['discord_username'] ?? '');
|
||||
if ( ! $username_input ) {
|
||||
wp_send_json_error(['message' => 'Bitte Discord-Benutzername eingeben.']);
|
||||
}
|
||||
|
||||
// Nutzer auf dem Guild suchen (nach Username oder per Search)
|
||||
$discord_user_id = self::discord_find_user_id($username_input, $token, $guild);
|
||||
if ( ! $discord_user_id ) {
|
||||
wp_send_json_error(['message' => 'Discord-Nutzer nicht auf dem Server gefunden. Stelle sicher, dass du Mitglied des Servers bist.']);
|
||||
}
|
||||
|
||||
// Verifikations-Code generieren (6-stellig)
|
||||
$code = strtoupper(substr(md5(uniqid(mt_rand(), true)), 0, 6));
|
||||
$expires = time() + 600; // 10 Minuten
|
||||
|
||||
// Code + Discord-User-ID temporär speichern
|
||||
WBF_DB::set_user_meta($user->id, 'discord_verify_code', $code);
|
||||
WBF_DB::set_user_meta($user->id, 'discord_verify_expires', (string)$expires);
|
||||
WBF_DB::set_user_meta($user->id, 'discord_verify_pending_id', $discord_user_id);
|
||||
|
||||
// DM senden
|
||||
$sent = self::discord_send_dm($discord_user_id, $token,
|
||||
"🔐 **Dein Verifikationscode für " . get_bloginfo('name') . ":**\n\n" .
|
||||
"```" . $code . "```\n" .
|
||||
"Gib diesen Code im Forum ein. Er ist **10 Minuten** gültig.\n" .
|
||||
"_Falls du diese Nachricht nicht erwartet hast, ignoriere sie einfach._"
|
||||
);
|
||||
|
||||
if ( ! $sent ) {
|
||||
wp_send_json_error(['message' => 'DM konnte nicht gesendet werden. Stelle sicher, dass du DMs von Server-Mitgliedern zulässt.']);
|
||||
}
|
||||
|
||||
wp_send_json_success(['message' => '✅ Code gesendet! Prüfe deine Discord-DMs und gib den 6-stelligen Code ein.', 'step' => 'enter_code']);
|
||||
}
|
||||
|
||||
// ── Discord: Code überprüfen + Verbindung herstellen ─────────────────────
|
||||
|
||||
public static function handle_discord_verify_code() {
|
||||
self::verify();
|
||||
$user = WBF_Auth::get_current_user();
|
||||
if ( ! $user ) wp_send_json_error(['message' => 'Nicht eingeloggt.']);
|
||||
|
||||
$code_input = strtoupper(sanitize_text_field($_POST['verify_code'] ?? ''));
|
||||
$meta = WBF_DB::get_user_meta($user->id);
|
||||
|
||||
$stored_code = strtoupper($meta['discord_verify_code'] ?? '');
|
||||
$expires = (int)($meta['discord_verify_expires'] ?? 0);
|
||||
$discord_uid = $meta['discord_verify_pending_id'] ?? '';
|
||||
|
||||
if ( ! $stored_code || ! $discord_uid ) {
|
||||
wp_send_json_error(['message' => 'Kein offener Verifizierungs-Vorgang. Bitte erneut starten.']);
|
||||
}
|
||||
if ( time() > $expires ) {
|
||||
wp_send_json_error(['message' => 'Code abgelaufen. Bitte erneut einen Code anfordern.']);
|
||||
}
|
||||
if ( ! hash_equals($stored_code, $code_input) ) {
|
||||
wp_send_json_error(['message' => 'Falscher Code. Bitte erneut versuchen.']);
|
||||
}
|
||||
|
||||
// Discord-Username abrufen (für Anzeige)
|
||||
$s = wbf_get_settings();
|
||||
$token = trim($s['discord_bot_token'] ?? '');
|
||||
$display_name = $discord_uid;
|
||||
if ( $token ) {
|
||||
$res = wp_remote_get("https://discord.com/api/v10/users/{$discord_uid}", [
|
||||
'timeout' => 5,
|
||||
'headers' => ['Authorization' => 'Bot ' . $token],
|
||||
]);
|
||||
if ( ! is_wp_error($res) && wp_remote_retrieve_response_code($res) === 200 ) {
|
||||
$d = json_decode(wp_remote_retrieve_body($res), true);
|
||||
$display_name = $d['global_name'] ?? $d['username'] ?? $discord_uid;
|
||||
}
|
||||
}
|
||||
|
||||
// Speichern
|
||||
WBF_DB::set_user_meta($user->id, 'discord_user_id', $discord_uid);
|
||||
WBF_DB::set_user_meta($user->id, 'discord_username', $display_name);
|
||||
// Temp-Daten löschen
|
||||
WBF_DB::set_user_meta($user->id, 'discord_verify_code', '');
|
||||
WBF_DB::set_user_meta($user->id, 'discord_verify_expires', '');
|
||||
WBF_DB::set_user_meta($user->id, 'discord_verify_pending_id', '');
|
||||
|
||||
// Rollen-Sync direkt nach Verifikation
|
||||
$guild = trim($s['discord_guild_id'] ?? '');
|
||||
$role_map = json_decode($s['discord_role_map'] ?? '{}', true) ?: [];
|
||||
if ( ($s['discord_role_sync'] ?? '0') === '1' && $token && $guild && $role_map ) {
|
||||
wbf_sync_discord_role_for_user($user->id, $discord_uid, $token, $guild, $role_map);
|
||||
}
|
||||
|
||||
wp_send_json_success([
|
||||
'message' => '🎉 Discord erfolgreich verknüpft!',
|
||||
'connected' => true,
|
||||
'display_name' => esc_html($display_name),
|
||||
]);
|
||||
}
|
||||
|
||||
// ── Discord: Verbindung trennen ───────────────────────────────────────────
|
||||
|
||||
public static function handle_save_discord() {
|
||||
self::verify();
|
||||
$user = WBF_Auth::get_current_user();
|
||||
if ( ! $user ) wp_send_json_error(['message' => 'Nicht eingeloggt.']);
|
||||
|
||||
$action = sanitize_key( $_POST['sub_action'] ?? 'save' );
|
||||
|
||||
if ( $action === 'disconnect' ) {
|
||||
WBF_DB::set_user_meta($user->id, 'discord_username', '');
|
||||
WBF_DB::set_user_meta($user->id, 'discord_user_id', '');
|
||||
wp_send_json_success(['message' => 'Discord-Verbindung getrennt.', 'connected' => false]);
|
||||
}
|
||||
|
||||
wp_send_json_error(['message' => 'Unbekannte Aktion.']);
|
||||
}
|
||||
|
||||
// ── Discord Hilfsmethoden ─────────────────────────────────────────────────
|
||||
|
||||
private static function discord_find_user_id($username_input, $token, $guild) {
|
||||
if ( ! $guild ) return null;
|
||||
// Guild-Member-Search (max. 1 Treffer)
|
||||
$search = rawurlencode($username_input);
|
||||
$res = wp_remote_get("https://discord.com/api/v10/guilds/{$guild}/members/search?query={$search}&limit=5", [
|
||||
'timeout' => 6,
|
||||
'headers' => ['Authorization' => 'Bot ' . $token],
|
||||
]);
|
||||
if ( is_wp_error($res) || wp_remote_retrieve_response_code($res) !== 200 ) return null;
|
||||
$members = json_decode(wp_remote_retrieve_body($res), true);
|
||||
if ( empty($members) ) return null;
|
||||
// Exakten Treffer bevorzugen
|
||||
$input_lower = strtolower($username_input);
|
||||
foreach ( $members as $m ) {
|
||||
$uname = strtolower($m['user']['username'] ?? '');
|
||||
$global = strtolower($m['user']['global_name'] ?? '');
|
||||
if ( $uname === $input_lower || $global === $input_lower ) {
|
||||
return $m['user']['id'];
|
||||
}
|
||||
}
|
||||
// Erster Treffer als Fallback
|
||||
return $members[0]['user']['id'] ?? null;
|
||||
}
|
||||
|
||||
private static function discord_send_dm($user_id, $token, $message) {
|
||||
// DM-Channel erstellen
|
||||
$ch_res = wp_remote_post('https://discord.com/api/v10/users/@me/channels', [
|
||||
'timeout' => 6,
|
||||
'headers' => ['Authorization' => 'Bot ' . $token, 'Content-Type' => 'application/json'],
|
||||
'body' => json_encode(['recipient_id' => $user_id]),
|
||||
]);
|
||||
if ( is_wp_error($ch_res) || wp_remote_retrieve_response_code($ch_res) !== 200 ) return false;
|
||||
$channel = json_decode(wp_remote_retrieve_body($ch_res), true);
|
||||
$ch_id = $channel['id'] ?? '';
|
||||
if ( ! $ch_id ) return false;
|
||||
|
||||
// Nachricht senden
|
||||
$msg_res = wp_remote_post("https://discord.com/api/v10/channels/{$ch_id}/messages", [
|
||||
'timeout' => 6,
|
||||
'headers' => ['Authorization' => 'Bot ' . $token, 'Content-Type' => 'application/json'],
|
||||
'body' => json_encode(['content' => $message]),
|
||||
]);
|
||||
return ( ! is_wp_error($msg_res) && wp_remote_retrieve_response_code($msg_res) === 200 );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
add_action( 'init', [ 'WBF_Ajax', 'init' ] );
|
||||
Reference in New Issue
Block a user