182 lines
5.3 KiB
PHP
182 lines
5.3 KiB
PHP
<?php
|
|
declare(strict_types=1);
|
|
|
|
ini_set('display_errors', '1');
|
|
error_reporting(E_ALL);
|
|
|
|
$config = require __DIR__ . '/../../config/database.php';
|
|
$telegramConfig = require __DIR__ . '/../../config/telegram.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,
|
|
]
|
|
);
|
|
|
|
function telegramWebhookRespond(array $payload, int $statusCode = 200): never
|
|
{
|
|
http_response_code($statusCode);
|
|
header('Content-Type: application/json; charset=utf-8');
|
|
echo json_encode($payload, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
|
|
exit;
|
|
}
|
|
|
|
function telegramHttpPostJson(string $url, array $payload): bool
|
|
{
|
|
$jsonPayload = json_encode($payload, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
|
|
if ($jsonPayload === false) {
|
|
return false;
|
|
}
|
|
|
|
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 => 15,
|
|
]);
|
|
|
|
$body = curl_exec($ch);
|
|
curl_close($ch);
|
|
|
|
return $body !== false;
|
|
}
|
|
|
|
$context = stream_context_create([
|
|
'http' => [
|
|
'method' => 'POST',
|
|
'header' => implode("\r\n", [
|
|
'Content-Type: application/json',
|
|
'Content-Length: ' . strlen($jsonPayload),
|
|
]),
|
|
'content' => $jsonPayload,
|
|
'timeout' => 15,
|
|
'ignore_errors' => true,
|
|
],
|
|
]);
|
|
|
|
$body = @file_get_contents($url, false, $context);
|
|
|
|
return $body !== false;
|
|
}
|
|
|
|
function telegramSendBotMessage(array $telegramConfig, string $chatId, string $messageText): void
|
|
{
|
|
$botToken = trim((string) ($telegramConfig['bot_token'] ?? ''));
|
|
if ($botToken === '' || $chatId === '' || $messageText === '') {
|
|
return;
|
|
}
|
|
|
|
telegramHttpPostJson(
|
|
'https://api.telegram.org/bot' . $botToken . '/sendMessage',
|
|
[
|
|
'chat_id' => $chatId,
|
|
'text' => $messageText,
|
|
]
|
|
);
|
|
}
|
|
|
|
$expectedSecret = trim((string) ($telegramConfig['webhook_secret'] ?? ''));
|
|
if ($expectedSecret !== '') {
|
|
$providedSecret = (string) ($_SERVER['HTTP_X_TELEGRAM_BOT_API_SECRET_TOKEN'] ?? '');
|
|
if (!hash_equals($expectedSecret, $providedSecret)) {
|
|
telegramWebhookRespond(['ok' => false, 'error' => 'invalid_secret'], 403);
|
|
}
|
|
}
|
|
|
|
$rawBody = file_get_contents('php://input');
|
|
$update = json_decode((string) $rawBody, true);
|
|
if (!is_array($update)) {
|
|
telegramWebhookRespond(['ok' => false, 'error' => 'invalid_json'], 400);
|
|
}
|
|
|
|
$message = $update['message'] ?? $update['edited_message'] ?? null;
|
|
if (!is_array($message)) {
|
|
telegramWebhookRespond(['ok' => true, 'status' => 'ignored_no_message']);
|
|
}
|
|
|
|
$chatId = isset($message['chat']['id']) ? (string) $message['chat']['id'] : '';
|
|
$telegramUsername = trim((string) ($message['from']['username'] ?? ''));
|
|
$text = trim((string) ($message['text'] ?? ''));
|
|
|
|
if ($chatId === '' || $text === '') {
|
|
telegramWebhookRespond(['ok' => true, 'status' => 'ignored_missing_data']);
|
|
}
|
|
|
|
$token = null;
|
|
if (preg_match('/^\/start\s+connect_([A-Fa-f0-9]{32,128})$/', $text, $matches)) {
|
|
$token = strtolower($matches[1]);
|
|
} elseif (preg_match('/^connect_([A-Fa-f0-9]{32,128})$/', $text, $matches)) {
|
|
$token = strtolower($matches[1]);
|
|
}
|
|
|
|
if ($token === null) {
|
|
telegramWebhookRespond(['ok' => true, 'status' => 'ignored_no_connect_token']);
|
|
}
|
|
|
|
$stmtUser = $pdo->prepare("
|
|
SELECT `id`
|
|
FROM `app_users`
|
|
WHERE `telegram_link_token` = :token
|
|
AND `telegram_link_token_expires_at` IS NOT NULL
|
|
AND `telegram_link_token_expires_at` > NOW()
|
|
LIMIT 1
|
|
");
|
|
$stmtUser->execute([':token' => $token]);
|
|
$user = $stmtUser->fetch();
|
|
|
|
if (!$user) {
|
|
telegramWebhookRespond(['ok' => true, 'status' => 'token_not_found_or_expired']);
|
|
}
|
|
|
|
$stmtUpdate = $pdo->prepare("
|
|
UPDATE `app_users`
|
|
SET
|
|
`telegram_username` = :telegram_username,
|
|
`telegram_chat_id` = :telegram_chat_id,
|
|
`telegram_connected_at` = NOW(),
|
|
`telegram_link_token` = NULL,
|
|
`telegram_link_token_expires_at` = NULL,
|
|
`updated_at` = NOW()
|
|
WHERE `id` = :id
|
|
");
|
|
$stmtUpdate->execute([
|
|
':telegram_username' => $telegramUsername !== '' ? $telegramUsername : null,
|
|
':telegram_chat_id' => $chatId,
|
|
':id' => (int) $user['id'],
|
|
]);
|
|
|
|
$welcomeName = $telegramUsername !== '' ? '@' . ltrim($telegramUsername, '@') : 'bei Telegram';
|
|
$welcomeMessage = implode("\n", [
|
|
'Willkommen bei SkyView.',
|
|
'',
|
|
'Dein Telegram-Konto wurde erfolgreich mit deinem SkyView-Benutzer verbunden.',
|
|
'Du kannst jetzt spaeter Hinweise und Inhalte direkt vom Bot erhalten.',
|
|
'',
|
|
'Verbunden als: ' . $welcomeName,
|
|
]);
|
|
|
|
telegramSendBotMessage($telegramConfig, $chatId, $welcomeMessage);
|
|
|
|
telegramWebhookRespond([
|
|
'ok' => true,
|
|
'status' => 'connected',
|
|
'user_id' => (int) $user['id'],
|
|
]);
|