diff --git a/pulsecast.php b/pulsecast.php index c2d7011..2f326ee 100644 --- a/pulsecast.php +++ b/pulsecast.php @@ -3,7 +3,7 @@ * Plugin Name: PulseCast * Plugin URI: https://git.viper.ipv64.net/M_Viper/PulseCast/ * Description: Sende Broadcasts (sofort oder geplant) an deine StatusAPI direkt aus dem WordPress-Backend. Flexibel für Homenetzwerk, externe Server und gemischte Setups. - * Version: 1.0.2 + * Version: 1.0.3 * Author: M_Viper * Author URI: https://m-viper.de */ @@ -158,6 +158,63 @@ class PulseCast { add_menu_page('PulseCast', 'PulseCast', 'manage_options', 'pulsecast', [$this, 'page_main'], 'dashicons-megaphone', 55); } + /** + * Formatiert die Nachricht für die Ausgabe im WordPress-Backend. + * - Wandelt &-Farbcodes in HTML-Span um. + * - Macht URLs anklickbar. + */ + private function format_message_output($text) { + if (empty($text)) return ''; + + // Zuerst HTML escapen für Sicherheit + $text = esc_html($text); + + // Farben Map (Minecraft Classic) + $colors = [ + '0' => '#000000', '1' => '#0000AA', '2' => '#00AA00', '3' => '#00AAAA', + '4' => '#AA0000', '5' => '#AA00AA', '6' => '#FFAA00', '7' => '#AAAAAA', + '8' => '#555555', '9' => '#5555FF', 'a' => '#55FF55', 'b' => '#55FFFF', + 'c' => '#FF5555', 'd' => '#FF55FF', 'e' => '#FFFF55', 'f' => '#FFFFFF', + ]; + + // Formate Map + $formats = [ + 'l' => 'font-weight:bold;', // Bold + 'o' => 'font-style:italic;', // Italic + 'n' => 'text-decoration:underline;', // Underline + 'm' => 'text-decoration:line-through;', // Strikethrough + 'r' => '', // Reset + ]; + + // Regex findet &code (wegen des vorherigen esc_html) + $pattern = '/&([0-9a-fk-or])/i'; + + $formatted = preg_replace_callback($pattern, function($matches) use ($colors, $formats) { + $code = strtolower($matches[1]); + + // Reset (schließt alle offenen Tags) + if ($code === 'r') { + return ''; + } + + // Farben öffnen einen neuen Span + if (isset($colors[$code])) { + return ''; + } + + // Formate (fett, kursiv) - Wir öffnen ebenfalls einen Span + if (isset($formats[$code])) { + return ''; + } + + // Unbekannter Code (z.B. &k für obfuscated) - ignorieren oder Text lassen + return $matches[0]; + }, $text); + + // Links anklickbar machen (WordPress Funktion) + return make_clickable($formatted); + } + public function page_main() { if (!current_user_can('manage_options')) wp_die('Keine Berechtigung.'); @@ -583,7 +640,7 @@ class PulseCast { ?> - + format_message_output($s['message']); ?> @@ -943,6 +1000,7 @@ class PulseCast { public function handle_schedule_post() { if (!current_user_can('manage_options')) wp_die('Forbidden'); + // 1. Einstellungen speichern if (isset($_POST['_wpnonce']) && wp_verify_nonce($_POST['_wpnonce'], 'pulsecast_save_settings')) { check_admin_referer('pulsecast_save_settings'); $settings = get_option(self::OPTION_KEY, []); @@ -962,15 +1020,16 @@ class PulseCast { exit; } + // 2. Neuen Schedule planen check_admin_referer('pulsecast_schedule_new'); $message = sanitize_textarea_field($_POST['sched_message'] ?? ''); $timeRaw = sanitize_text_field($_POST['sched_time'] ?? ''); $recur = sanitize_text_field($_POST['sched_recur'] ?? 'none'); $type = 'global'; - $settings = get_option(self::OPTION_KEY, []); + // Farben aus den Formularwerten oder Standard $prefix = sanitize_text_field($_POST['sched_prefix'] ?? ''); $prefix_color = sanitize_text_field($_POST['sched_prefix_color'] ?? ''); $bracket_color = sanitize_text_field($_POST['sched_bracket_color'] ?? ''); @@ -986,15 +1045,30 @@ class PulseCast { exit; } + // --- FIX: UTC KONVERTIERUNG --- + // Wir nutzen DateTime mit der WordPress-Zeitzoneneinstellung $timeRaw = str_replace('T', ' ', $timeRaw); - $local_timestamp = strtotime($timeRaw); - if ($local_timestamp === false || $local_timestamp <= 0) { - wp_redirect(add_query_arg('pulsecast_error', urlencode('Ungültiges Zeitformat'), wp_get_referer())); + + try { + // Zeitzone aus WordPress Einstellungen holen + $wp_timezone = wp_timezone(); + + // Datum Objekt erstellen (interpretiert Input als WP Zeit) + $date = DateTime::createFromFormat('Y-m-d H:i', $timeRaw, $wp_timezone); + + if ($date === false) { + wp_redirect(add_query_arg('pulsecast_error', urlencode('Ungültiges Zeitformat'), wp_get_referer())); + exit; + } + + // Zeitzone auf UTC setzen und den Timestamp holen + $date->setTimezone(new DateTimeZone('UTC')); + $timestamp_utc = $date->getTimestamp(); + + } catch (Exception $e) { + wp_redirect(add_query_arg('pulsecast_error', urlencode('Zeitkonvertierungsfehler: ' . $e->getMessage()), wp_get_referer())); exit; } - - $utc_datetime = get_gmt_from_date(date('Y-m-d H:i:s', $local_timestamp), 'Y-m-d H:i:s'); - $timestamp_utc = strtotime($utc_datetime . ' UTC'); $schedules = get_option(self::SCHEDULES_KEY, []); $id = (string) time() . rand(1000,9999);