PDO::ERRMODE_EXCEPTION, PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC, ] ); $currentUserId = (int) $_SESSION['user_id']; $loggedIn = true; $publicBasePath = '../'; $pageTitle = 'Telegram-Testversand - AstroTools'; $headerIntroPre = 'Administration'; $headerIntroTitle = 'Telegram-Testversand'; $headerIntroSub = 'Testnachrichten nur an verknuepfte Master-Konten senden.'; $errors = []; $successMessage = ''; $resultRows = []; $messageText = "Testnachricht von SkyView\n\nDer Telegram-Bot ist jetzt erfolgreich verbunden."; $sendMode = 'self'; $selectedRecipientIds = []; function h(?string $value): string { return htmlspecialchars((string) $value, ENT_QUOTES, 'UTF-8'); } function textLength(string $value): int { if (function_exists('mb_strlen')) { return mb_strlen($value); } return strlen($value); } function telegramHttpPostJson(string $url, array $payload): array { $jsonPayload = json_encode($payload, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES); if ($jsonPayload === false) { return [ 'ok' => false, 'status_code' => 0, 'body' => null, 'error' => 'Die Telegram-Anfrage konnte nicht als JSON kodiert werden.', ]; } if (DIRECTORY_SEPARATOR === '\\' && function_exists('shell_exec')) { $urlBase64 = base64_encode($url); $payloadBase64 = base64_encode($jsonPayload); $powerShellScript = str_replace( ['__URL_BASE64__', '__PAYLOAD_BASE64__'], [$urlBase64, $payloadBase64], <<<'PS' $ErrorActionPreference = 'Stop' $url = [System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String('__URL_BASE64__')) $body = [System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String('__PAYLOAD_BASE64__')) try { $response = Invoke-RestMethod -Method Post -Uri $url -ContentType 'application/json' -Body $body [PSCustomObject]@{ ok = $true body = ($response | ConvertTo-Json -Depth 20 -Compress) error = '' } | ConvertTo-Json -Compress } catch { $stream = $null $responseBody = '' if ($_.Exception.Response) { try { $stream = $_.Exception.Response.GetResponseStream() if ($stream) { $reader = New-Object System.IO.StreamReader($stream) $responseBody = $reader.ReadToEnd() } } catch { } finally { if ($stream) { $stream.Dispose() } } } [PSCustomObject]@{ ok = $false body = $responseBody error = $_.Exception.Message } | ConvertTo-Json -Compress } PS ); $encodedCommandBinary = function_exists('iconv') ? iconv('UTF-8', 'UTF-16LE', $powerShellScript) : $powerShellScript; $encodedCommand = base64_encode($encodedCommandBinary === false ? $powerShellScript : $encodedCommandBinary); $command = 'powershell -NoProfile -ExecutionPolicy Bypass -EncodedCommand ' . $encodedCommand; $rawOutput = shell_exec($command); if ($rawOutput !== null && trim($rawOutput) !== '') { $decodedShell = json_decode(trim($rawOutput), true); if (is_array($decodedShell)) { return [ 'ok' => (bool) ($decodedShell['ok'] ?? false), 'status_code' => 0, 'body' => $decodedShell['body'] ?? null, 'error' => $decodedShell['error'] ?? null, ]; } } } if (function_exists('curl_init')) { $ch = curl_init($url); curl_setopt_array($ch, [ CURLOPT_POST => true, CURLOPT_RETURNTRANSFER => true, CURLOPT_HTTPHEADER => [ 'Content-Type: application/json', 'Content-Length: ' . strlen($jsonPayload), ], CURLOPT_POSTFIELDS => $jsonPayload, CURLOPT_TIMEOUT => 20, ]); $body = curl_exec($ch); $curlError = curl_error($ch); $statusCode = (int) curl_getinfo($ch, CURLINFO_RESPONSE_CODE); curl_close($ch); if ($body === false) { return [ 'ok' => false, 'status_code' => $statusCode, 'body' => null, 'error' => $curlError !== '' ? $curlError : 'Die Telegram-Anfrage ist fehlgeschlagen.', ]; } return [ 'ok' => true, 'status_code' => $statusCode, 'body' => $body, 'error' => null, ]; } $context = stream_context_create([ 'http' => [ 'method' => 'POST', 'header' => implode("\r\n", [ 'Content-Type: application/json', 'Content-Length: ' . strlen($jsonPayload), ]), 'content' => $jsonPayload, 'timeout' => 20, 'ignore_errors' => true, ], ]); $body = @file_get_contents($url, false, $context); $statusCode = 0; $responseHeaders = function_exists('http_get_last_response_headers') ? http_get_last_response_headers() : ($http_response_header ?? null); if (is_array($responseHeaders)) { foreach ($responseHeaders as $headerLine) { if (preg_match('/^HTTP\/\S+\s+(\d{3})\b/', $headerLine, $matches) === 1) { $statusCode = (int) $matches[1]; break; } } } if ($body === false) { return [ 'ok' => false, 'status_code' => $statusCode, 'body' => null, 'error' => 'Die Telegram-Anfrage ist fehlgeschlagen. Auf diesem Server ist moeglicherweise weder cURL noch der HTTPS-Stream-Wrapper verfuegbar.', ]; } return [ 'ok' => true, 'status_code' => $statusCode, 'body' => $body, 'error' => null, ]; } function sendTelegramMessage(string $botToken, string $chatId, string $messageText): array { $response = telegramHttpPostJson( 'https://api.telegram.org/bot' . $botToken . '/sendMessage', [ 'chat_id' => $chatId, 'text' => appendTelegramServiceFooter($messageText), ] ); if (!$response['ok']) { return [ 'ok' => false, 'description' => (string) ($response['error'] ?? 'Telegram konnte nicht erreicht werden.'), ]; } $decoded = json_decode((string) $response['body'], true); if (!is_array($decoded)) { return [ 'ok' => false, 'description' => 'Telegram hat keine gültige JSON-Antwort geliefert.', ]; } return [ 'ok' => (bool) ($decoded['ok'] ?? false), 'description' => (string) ($decoded['description'] ?? ''), ]; } if (empty($_SESSION['telegram_broadcast_csrf'])) { $_SESSION['telegram_broadcast_csrf'] = bin2hex(random_bytes(16)); } $stmtCurrentUser = $pdo->prepare(" SELECT `id`, `username`, `display_name`, `role`, `is_active`, `telegram_chat_id` FROM `app_users` WHERE `id` = :id LIMIT 1 "); $stmtCurrentUser->execute([':id' => $currentUserId]); $currentUser = $stmtCurrentUser->fetch(); if ( !$currentUser || !isMasterRole((string) $currentUser['role']) || (int) $currentUser['is_active'] !== 1 ) { $_SESSION = []; session_destroy(); header('Location: ../login.php'); exit; } $stmtRecipients = $pdo->query(" SELECT `id`, `username`, `display_name`, `role`, `telegram_username`, `telegram_chat_id`, `telegram_connected_at` FROM `app_users` WHERE `is_active` = 1 AND `role` = 'master' AND `telegram_chat_id` IS NOT NULL AND `telegram_chat_id` <> '' ORDER BY COALESCE(`display_name`, `username`) ASC, `id` ASC "); $recipients = $stmtRecipients->fetchAll(); $recipientIndex = []; foreach ($recipients as $recipient) { $recipientIndex[(int) $recipient['id']] = $recipient; } if ($_SERVER['REQUEST_METHOD'] === 'POST') { $action = (string) ($_POST['action'] ?? ''); $csrfToken = (string) ($_POST['csrf_token'] ?? ''); $messageText = trim((string) ($_POST['message_text'] ?? '')); $sendMode = (string) ($_POST['send_mode'] ?? 'self'); $selectedRecipientIds = array_values(array_unique(array_map( static fn ($value): int => (int) $value, is_array($_POST['recipient_ids'] ?? null) ? $_POST['recipient_ids'] : [] ))); if (!hash_equals($_SESSION['telegram_broadcast_csrf'], $csrfToken)) { $errors[] = 'Die Sitzung ist abgelaufen. Bitte die Seite neu laden.'; } if ($action !== 'send_broadcast') { $errors[] = 'Die angeforderte Aktion ist ungültig.'; } if ($messageText === '') { $errors[] = 'Bitte eine Nachricht eingeben.'; } elseif (textLength($messageText) > 4000) { $errors[] = 'Die Nachricht ist zu lang. Bitte auf maximal 4000 Zeichen kuerzen.'; } $botToken = trim((string) ($telegramConfig['bot_token'] ?? '')); if ($botToken === '') { $errors[] = 'In config/telegram.php ist noch kein Bot-Token hinterlegt.'; } if (empty($recipients)) { $errors[] = 'Es gibt derzeit keine verknuepften Master-Konten mit Telegram.'; } $targetRecipients = []; if (empty($errors)) { if ($sendMode === 'self') { if (empty($currentUser['telegram_chat_id'])) { $errors[] = 'Dein Administrationskonto ist noch nicht mit Telegram verknuepft.'; } else { foreach ($recipients as $recipient) { if ((int) $recipient['id'] === $currentUserId) { $targetRecipients[] = $recipient; break; } } if (empty($targetRecipients)) { $targetRecipients[] = [ 'id' => $currentUserId, 'username' => (string) $currentUser['username'], 'display_name' => (string) ($currentUser['display_name'] ?? ''), 'telegram_username' => '', 'telegram_chat_id' => (string) $currentUser['telegram_chat_id'], 'telegram_connected_at' => null, ]; } } } elseif ($sendMode === 'selected') { if (empty($selectedRecipientIds)) { $errors[] = 'Bitte mindestens einen Empfänger auswählen.'; } else { foreach ($selectedRecipientIds as $recipientId) { if (isset($recipientIndex[$recipientId])) { $targetRecipients[] = $recipientIndex[$recipientId]; } } if (empty($targetRecipients)) { $errors[] = 'Die ausgewählten Empfänger konnten nicht geladen werden.'; } } } elseif ($sendMode === 'all') { $targetRecipients = $recipients; } else { $errors[] = 'Der Versandmodus ist ungültig.'; } } if (empty($errors)) { $successCount = 0; foreach ($targetRecipients as $recipient) { $chatId = trim((string) ($recipient['telegram_chat_id'] ?? '')); $sendResult = sendTelegramMessage($botToken, $chatId, $messageText); $wasSuccessful = (bool) ($sendResult['ok'] ?? false); if ($wasSuccessful) { $successCount++; } $resultRows[] = [ 'username' => (string) ($recipient['username'] ?? ''), 'display_name' => (string) ($recipient['display_name'] ?? ''), 'telegram_username' => (string) ($recipient['telegram_username'] ?? ''), 'chat_id' => $chatId, 'ok' => $wasSuccessful, 'description' => (string) ($sendResult['description'] ?? ''), ]; } $successMessage = sprintf( 'Versand abgeschlossen: %d von %d Master-Konten erfolgreich erreicht.', $successCount, count($targetRecipients) ); } } ?>

Testnachricht senden

Diese Seite sendet Testnachrichten ausschliesslich an aktive Master-Konten mit hinterlegter Telegram-Chat-ID.

Verknüpfte Master-Konten
Bot

Mit gedrueckter Strg-Taste lassen sich mehrere Benutzer markieren.

Empfänger

Noch keine verknuepften Master-Konten vorhanden.

Benutzer Telegram Chat-ID

Versandprotokoll

Benutzer Chat-ID Status Rueckmeldung