381 lines
13 KiB
PHP
381 lines
13 KiB
PHP
<?php
|
|
declare(strict_types=1);
|
|
|
|
ini_set('display_errors', '1');
|
|
error_reporting(E_ALL);
|
|
session_start();
|
|
|
|
if (!isset($_SESSION['user_id'])) {
|
|
header('Location: ../login.php');
|
|
exit;
|
|
}
|
|
|
|
require_once __DIR__ . '/../auth_helpers.php';
|
|
|
|
$config = require __DIR__ . '/../../config/database.php';
|
|
$telegramConfig = require __DIR__ . '/../../config/telegram.php';
|
|
require_once __DIR__ . '/lib/message_footer.php';
|
|
require_once __DIR__ . '/lib/http.php';
|
|
|
|
$dsn = sprintf(
|
|
'mysql:host=%s;dbname=%s;charset=%s',
|
|
$config['host'],
|
|
$config['dbname'],
|
|
$config['charset'] ?? 'utf8mb4'
|
|
);
|
|
|
|
$pdo = new PDO(
|
|
$dsn,
|
|
$config['user'],
|
|
$config['pass'],
|
|
[
|
|
PDO::ATTR_ERRMODE => 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 an Nutzer mit verknüpftem Telegram-Konto 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 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 `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 Nutzer mit verknüpftem Telegram-Konto.';
|
|
}
|
|
|
|
$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 Empfänger erfolgreich erreicht.',
|
|
$successCount,
|
|
count($targetRecipients)
|
|
);
|
|
}
|
|
}
|
|
?>
|
|
<?php require __DIR__ . '/../header.php'; ?>
|
|
|
|
<?php if ($successMessage !== ''): ?>
|
|
<p class="msg-success"><?= h($successMessage) ?></p>
|
|
<?php endif; ?>
|
|
|
|
<?php if (!empty($errors)): ?>
|
|
<ul class="msg-error">
|
|
<?php foreach ($errors as $error): ?>
|
|
<li><?= h($error) ?></li>
|
|
<?php endforeach; ?>
|
|
</ul>
|
|
<?php endif; ?>
|
|
|
|
<div class="grid-2">
|
|
<div class="card">
|
|
<h2>Testnachricht senden</h2>
|
|
<p class="hint">
|
|
Diese Seite sendet Testnachrichten an alle aktiven Nutzer mit hinterlegter Telegram-Chat-ID.
|
|
</p>
|
|
|
|
<table class="data-table mb-lg">
|
|
<tr><td>Nutzer mit Telegram verknüpft</td><td><?= count($recipients) ?></td></tr>
|
|
<tr><td>Bot</td><td><?= h(($telegramConfig['bot_username'] ?? '') !== '' ? '@' . (string) $telegramConfig['bot_username'] : 'nicht konfiguriert') ?></td></tr>
|
|
</table>
|
|
|
|
<form method="post" action="" class="form-stack">
|
|
<input type="hidden" name="action" value="send_broadcast">
|
|
<input type="hidden" name="csrf_token" value="<?= h($_SESSION['telegram_broadcast_csrf']) ?>">
|
|
|
|
<div class="form-group">
|
|
<label>Empfänger</label>
|
|
<label>
|
|
<input type="radio" name="send_mode" value="self" <?= $sendMode === 'self' ? 'checked' : '' ?>>
|
|
Nur an mich senden
|
|
</label>
|
|
<label>
|
|
<input type="radio" name="send_mode" value="selected" <?= $sendMode === 'selected' ? 'checked' : '' ?>>
|
|
An ausgewählte Nutzer senden
|
|
</label>
|
|
<label>
|
|
<input type="radio" name="send_mode" value="all" <?= $sendMode === 'all' ? 'checked' : '' ?>>
|
|
An alle verknüpften Nutzer senden
|
|
</label>
|
|
</div>
|
|
|
|
<div class="form-group">
|
|
<label for="recipient_ids">Auswahl für "ausgewählte Nutzer"</label>
|
|
<select id="recipient_ids" name="recipient_ids[]" multiple size="8">
|
|
<?php foreach ($recipients as $recipient): ?>
|
|
<?php $recipientId = (int) $recipient['id']; ?>
|
|
<?php $recipientLabel = ($recipient['display_name'] !== '' ? $recipient['display_name'] : $recipient['username']) . ' (' . $recipient['username'] . ')'; ?>
|
|
<option value="<?= $recipientId ?>" <?= in_array($recipientId, $selectedRecipientIds, true) ? 'selected' : '' ?>>
|
|
<?= h($recipientLabel) ?>
|
|
</option>
|
|
<?php endforeach; ?>
|
|
</select>
|
|
<p class="hint">Mit gedrueckter Strg-Taste lassen sich mehrere Benutzer markieren.</p>
|
|
</div>
|
|
|
|
<div class="form-group">
|
|
<label for="message_text">Nachricht</label>
|
|
<textarea
|
|
id="message_text"
|
|
name="message_text"
|
|
rows="8"
|
|
maxlength="4000"
|
|
required
|
|
><?= h($messageText) ?></textarea>
|
|
</div>
|
|
|
|
<button type="submit" class="btn btn-primary">Testnachricht senden</button>
|
|
</form>
|
|
</div>
|
|
|
|
<div class="card">
|
|
<h2>Empfänger</h2>
|
|
<?php if (empty($recipients)): ?>
|
|
<p class="hint">Noch keine Nutzer mit verknüpftem Telegram-Konto vorhanden.</p>
|
|
<?php else: ?>
|
|
<table class="data-table">
|
|
<thead>
|
|
<tr>
|
|
<th>Benutzer</th>
|
|
<th>Telegram</th>
|
|
<th>Chat-ID</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<?php foreach ($recipients as $recipient): ?>
|
|
<tr>
|
|
<td>
|
|
<strong><?= h($recipient['display_name'] !== '' ? $recipient['display_name'] : $recipient['username']) ?></strong><br>
|
|
<span class="hint"><?= h($recipient['username']) ?></span>
|
|
</td>
|
|
<td><?= h(($recipient['telegram_username'] ?? '') !== '' ? '@' . ltrim((string) $recipient['telegram_username'], '@') : '—') ?></td>
|
|
<td><?= h((string) $recipient['telegram_chat_id']) ?></td>
|
|
</tr>
|
|
<?php endforeach; ?>
|
|
</tbody>
|
|
</table>
|
|
<?php endif; ?>
|
|
</div>
|
|
</div>
|
|
|
|
<?php if (!empty($resultRows)): ?>
|
|
<div class="card">
|
|
<h2>Versandprotokoll</h2>
|
|
<table class="data-table">
|
|
<thead>
|
|
<tr>
|
|
<th>Benutzer</th>
|
|
<th>Chat-ID</th>
|
|
<th>Status</th>
|
|
<th>Rueckmeldung</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<?php foreach ($resultRows as $row): ?>
|
|
<tr>
|
|
<td><?= h($row['display_name'] !== '' ? $row['display_name'] : $row['username']) ?></td>
|
|
<td><?= h($row['chat_id']) ?></td>
|
|
<td><?= $row['ok'] ? 'OK' : 'Fehler' ?></td>
|
|
<td><?= h($row['description'] !== '' ? $row['description'] : 'Nachricht gesendet.') ?></td>
|
|
</tr>
|
|
<?php endforeach; ?>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
<?php endif; ?>
|
|
|
|
<?php require __DIR__ . '/../footer.php'; ?>
|