feat: never-expire Telegram session + logout confirmation on both channels

- STATE_TTL: 7200s → 315360000s (10 years) so sessions survive indefinitely
- Telegram: "salir"/"/salir" now shows inline confirmation keyboard instead of going straight to menu; "Cerrar sesión" button added to main menu; logout_ask/logout_confirm/confirmLogout() handler clears state and returns to email prompt
- Web chat: "Cerrar sesión" button in main menu; clicking it shows a confirmation message with "Sí, cerrar sesión" / "No, quedarme" buttons; only the confirmed action calls cerrarSesion()

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Lizandro
2026-07-14 19:32:06 +00:00
co-authored by Claude Sonnet 4.6
parent 80dd7ee9ca
commit 9a13bad235
2 changed files with 65 additions and 4 deletions
+43 -4
View File
@@ -31,7 +31,7 @@ use Illuminate\Support\Str;
class TelegramBotService
{
private const STATE_TTL = 7200; // 2 hours
private const STATE_TTL = 315360000; // 10 years — session never expires automatically
private ?int $convId = null;
@@ -63,10 +63,20 @@ class TelegramBotService
$lower = strtolower(trim($text));
// "salir" siempre pide confirmación de cierre de sesión
if (in_array($lower, ['salir', '/salir'])) {
if ($state['user_id'] ?? null) {
$this->showLogoutConfirmation($chatId);
} else {
$this->askEmail($chatId);
}
return;
}
// Palabras que siempre regresan al menú, desde cualquier punto del flujo
$menuTriggers = [
'/start', '/menu', '/salir', '/inicio', '/cancelar',
'menu', 'menú', 'inicio', 'hola', 'salir', 'volver',
'/start', '/menu', '/inicio', '/cancelar',
'menu', 'menú', 'inicio', 'hola', 'volver',
'regresar', 'cancelar', 'empezar', 'comenzar', 'start',
];
@@ -118,7 +128,9 @@ class TelegramBotService
$action = $parts[0];
match ($action) {
'menu' => $this->showMainMenu($chatId),
'menu' => $this->showMainMenu($chatId),
'logout_ask' => $this->showLogoutConfirmation($chatId),
'logout_confirm' => $this->confirmLogout($chatId),
'svc_list' => $this->listServices($chatId),
'svc_view' => $this->viewService($chatId, (int) ($parts[1] ?? 0)),
'buy_start' => $this->startPurchase($chatId, (int) ($parts[1] ?? 0)),
@@ -497,6 +509,30 @@ class TelegramBotService
// ─── Main menu ────────────────────────────────────────────
private function showLogoutConfirmation(string $chatId): void
{
$this->sendWithKeyboard(
$chatId,
"⚠️ ¿Deseas cerrar sesión?\nDeberás volver a ingresar tu correo y código para continuar.",
[
[
['text' => '✅ Sí, cerrar sesión', 'callback_data' => 'logout_confirm'],
['text' => '❌ No, quedarme', 'callback_data' => 'menu'],
],
]
);
}
private function confirmLogout(string $chatId): void
{
$state = $this->getState($chatId);
unset($state['user_id'], $state['conv_id'], $state['step'], $state['data']);
$state['step'] = 'await_email';
$this->setState($chatId, $state);
$this->send($chatId, "👋 Sesión cerrada. Hasta pronto.");
$this->askEmail($chatId);
}
private function showMainMenu(string $chatId): void
{
$state = $this->getState($chatId);
@@ -520,6 +556,9 @@ class TelegramBotService
[
['text' => '🧑 Hablar con asesor', 'callback_data' => 'agent'],
],
[
['text' => '🚪 Cerrar sesión', 'callback_data' => 'logout_ask'],
],
]);
}