Primer subida completa
This commit is contained in:
206
bot/TelegramBot.php
Executable file
206
bot/TelegramBot.php
Executable file
@@ -0,0 +1,206 @@
|
||||
<?php
|
||||
|
||||
require_once __DIR__ . '/../config/config.php';
|
||||
require_once __DIR__ . '/../src/Asignacion.php';
|
||||
require_once __DIR__ . '/../src/User.php';
|
||||
|
||||
class TelegramBot {
|
||||
private $token;
|
||||
private $apiUrl;
|
||||
|
||||
public function __construct() {
|
||||
$config = require __DIR__ . '/../config/config.php';
|
||||
$this->token = $config['telegram_bot_token'];
|
||||
$this->apiUrl = "https://api.telegram.org/bot{$this->token}";
|
||||
}
|
||||
|
||||
private function request($method, $data = []) {
|
||||
$url = "{$this->apiUrl}/{$method}";
|
||||
$ch = curl_init($url);
|
||||
curl_setopt($ch, CURLOPT_POST, true);
|
||||
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));
|
||||
curl_setopt($ch, CURLOPT_HTTPHEADER, ['Content-Type: application/json']);
|
||||
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
|
||||
$response = curl_exec($ch);
|
||||
curl_close($ch);
|
||||
return json_decode($response, true);
|
||||
}
|
||||
|
||||
public function sendMessage($chatId, $text, $parseMode = 'HTML', $replyMarkup = null) {
|
||||
$data = [
|
||||
'chat_id' => $chatId,
|
||||
'text' => $text,
|
||||
'parse_mode' => $parseMode
|
||||
];
|
||||
if ($replyMarkup) {
|
||||
$data['reply_markup'] = $replyMarkup;
|
||||
}
|
||||
return $this->request('sendMessage', $data);
|
||||
}
|
||||
|
||||
public function getMe() {
|
||||
return $this->request('getMe');
|
||||
}
|
||||
|
||||
public function getUpdates($offset = 0) {
|
||||
return $this->request('getUpdates', ['offset' => $offset, 'timeout' => 60]);
|
||||
}
|
||||
|
||||
public function sendKeyboard($chatId, $text) {
|
||||
$keyboard = [
|
||||
'inline_keyboard' => [
|
||||
[
|
||||
['text' => 'Ver Turnos', 'callback_data' => 'ver_turnos'],
|
||||
['text' => 'Semana Actual', 'callback_data' => 'semana_actual']
|
||||
],
|
||||
[
|
||||
['text' => '🔍 Buscar por Nombre', 'callback_data' => 'buscar_nombre']
|
||||
]
|
||||
]
|
||||
];
|
||||
|
||||
return $this->sendMessage($chatId, $text, 'HTML', json_encode($keyboard));
|
||||
}
|
||||
|
||||
public function answerCallback($callbackId, $text, $showAlert = false) {
|
||||
return $this->request('answerCallbackQuery', [
|
||||
'callback_query_id' => $callbackId,
|
||||
'text' => $text,
|
||||
'show_alert' => $showAlert
|
||||
]);
|
||||
}
|
||||
|
||||
public function deleteMessage($chatId, $messageId) {
|
||||
return $this->request('deleteMessage', [
|
||||
'chat_id' => $chatId,
|
||||
'message_id' => $messageId
|
||||
]);
|
||||
}
|
||||
|
||||
public function editMessage($chatId, $messageId, $text, $keyboard = null) {
|
||||
$data = [
|
||||
'chat_id' => $chatId,
|
||||
'message_id' => $messageId,
|
||||
'text' => $text,
|
||||
'parse_mode' => 'HTML'
|
||||
];
|
||||
if ($keyboard) {
|
||||
$data['reply_markup'] = $keyboard;
|
||||
}
|
||||
return $this->request('editMessageText', $data);
|
||||
}
|
||||
|
||||
public function getTablaTurnos($semanas = 4) {
|
||||
$asignacion = new Asignacion();
|
||||
$ayudantes = $asignacion->getAyudantesPorOrden();
|
||||
|
||||
if (empty($ayudantes)) {
|
||||
return "No hay ayudantes configurados.";
|
||||
}
|
||||
|
||||
$hoy = new DateTime();
|
||||
$diaSemana = (int)$hoy->format('w');
|
||||
$domingo = clone $hoy;
|
||||
$domingo->modify('-' . $diaSemana . ' days');
|
||||
|
||||
$tabla = "<b>TABLA DE TURNOS</b>\n\n";
|
||||
$tabla .= "<code>";
|
||||
$tabla .= str_pad("Semana", 10) . " | " . str_pad("Ayudante", 12) . " | Periodo\n";
|
||||
$tabla .= str_repeat("-", 45) . "\n";
|
||||
|
||||
for ($i = 0; $i < $semanas; $i++) {
|
||||
$domingoSemana = clone $domingo;
|
||||
$domingoSemana->modify("+{$i} weeks");
|
||||
$viernesSemana = clone $domingoSemana;
|
||||
$viernesSemana->modify('+5 days');
|
||||
|
||||
$posicion = ($i % count($ayudantes));
|
||||
$ayudante = $ayudantes[$posicion];
|
||||
|
||||
$semanaNum = $i + 1;
|
||||
$periodo = $domingoSemana->format('d/m') . '-' . $viernesSemana->format('d/m');
|
||||
|
||||
$tabla .= str_pad("Sem $semanaNum", 10) . " | " .
|
||||
str_pad(substr($ayudante['nombre'], 0, 10), 12) . " | $periodo\n";
|
||||
}
|
||||
|
||||
$tabla .= "</code>";
|
||||
$tabla .= "\n\nCiclo: " . implode(' -> ', array_column($ayudantes, 'nombre'));
|
||||
|
||||
return $tabla;
|
||||
}
|
||||
|
||||
public function getSemanaActual() {
|
||||
$asignacion = new Asignacion();
|
||||
|
||||
$hoy = new DateTime();
|
||||
$diaSemana = (int)$hoy->format('w');
|
||||
$domingo = clone $hoy;
|
||||
$domingo->modify('-' . $diaSemana . ' days');
|
||||
|
||||
$asignacionActual = $asignacion->getAsignacionPorSemana($domingo->format('Y-m-d'));
|
||||
|
||||
if ($asignacionActual) {
|
||||
return "<b>SEMANA ACTUAL</b>\n\n" .
|
||||
"Asignado: <b>{$asignacionActual['nombre']}</b>\n" .
|
||||
"Periodo: " . date('d/m/Y', strtotime($asignacionActual['semana_inicio'])) .
|
||||
" - " . date('d/m/Y', strtotime($asignacionActual['semana_fin'])) . "\n" .
|
||||
"Dias: Domingo a Viernes";
|
||||
} else {
|
||||
return "No hay asignacion para esta semana.";
|
||||
}
|
||||
}
|
||||
|
||||
public function getTurnosAyudante($nombre) {
|
||||
$config = require __DIR__ . '/../config/config.php';
|
||||
|
||||
try {
|
||||
$pdo = new PDO(
|
||||
"mysql:host={$config['db']['host']};port={$config['db']['port']};dbname={$config['db']['database']};charset=utf8mb4",
|
||||
$config['db']['username'],
|
||||
$config['db']['password'],
|
||||
[PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION]
|
||||
);
|
||||
} catch (Exception $e) {
|
||||
return "Error de conexion.";
|
||||
}
|
||||
|
||||
$stmt = $pdo->prepare("SELECT * FROM users WHERE nombre LIKE ? AND rol = 'ayudante' AND activo = 1 LIMIT 1");
|
||||
$stmt->execute(["%$nombre%"]);
|
||||
$user = $stmt->fetch();
|
||||
|
||||
if (!$user) {
|
||||
$ayudantes = (new Asignacion())->getAyudantesPorOrden();
|
||||
$nombres = implode(', ', array_map(fn($a) => $a['nombre'], $ayudantes));
|
||||
return "No encontre '$nombre'.\n\nAyudantes: $nombres";
|
||||
}
|
||||
|
||||
$stmt = $pdo->prepare("
|
||||
SELECT semana_inicio, semana_fin
|
||||
FROM asignaciones_turnos
|
||||
WHERE user_id = ? AND semana_inicio >= CURDATE()
|
||||
ORDER BY semana_inicio
|
||||
LIMIT 4
|
||||
");
|
||||
$stmt->execute([$user['id']]);
|
||||
$turnos = $stmt->fetchAll();
|
||||
|
||||
if (empty($turnos)) {
|
||||
return "{$user['nombre']} no tiene turnos proximos.";
|
||||
}
|
||||
|
||||
$result = "<b>TURNOS DE {$user['nombre']}</b>\n\n";
|
||||
|
||||
foreach ($turnos as $turno) {
|
||||
$result .= date('d/m/Y', strtotime($turno['semana_inicio'])) .
|
||||
" - " . date('d/m/Y', strtotime($turno['semana_fin'])) . "\n";
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
public function getListaAyudantesParaBusqueda() {
|
||||
$ayudantes = (new Asignacion())->getAyudantesPorOrden();
|
||||
return array_map(fn($a) => $a['nombre'], $ayudantes);
|
||||
}
|
||||
}
|
||||
49
bot/setup_webhook.php
Executable file
49
bot/setup_webhook.php
Executable file
@@ -0,0 +1,49 @@
|
||||
#!/usr/bin/env php
|
||||
<?php
|
||||
/**
|
||||
* Script para configurar el webhook de Telegram
|
||||
*
|
||||
* Uso: php setup_webhook.php <url_webhook>
|
||||
*
|
||||
* Ejemplo: php setup_webhook.php https://contenedor-test.local:82/bot/webhook.php
|
||||
*
|
||||
* Requiere: TELEGRAM_BOT_TOKEN configurado en .env
|
||||
*/
|
||||
|
||||
require_once __DIR__ . '/../config/config.php';
|
||||
|
||||
$config = require __DIR__ . '/../config/config.php';
|
||||
$token = $config['telegram_bot_token'];
|
||||
|
||||
if (empty($token)) {
|
||||
echo "ERROR: TELEGRAM_BOT_TOKEN no configurado en .env\n";
|
||||
exit(1);
|
||||
}
|
||||
|
||||
$urlWebhook = $argv[1] ?? "https://contenedor-test.local:82/bot/webhook.php";
|
||||
|
||||
echo "Configurando webhook...\n";
|
||||
echo "URL: {$urlWebhook}\n\n";
|
||||
|
||||
$url = "https://api.telegram.org/bot{$token}/setWebhook";
|
||||
$ch = curl_init($url);
|
||||
curl_setopt($ch, CURLOPT_POST, true);
|
||||
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode([
|
||||
'url' => $urlWebhook,
|
||||
'allowed_updates' => ['message', 'callback_query']
|
||||
]));
|
||||
curl_setopt($ch, CURLOPT_HTTPHEADER, ['Content-Type: application/json']);
|
||||
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
|
||||
$response = curl_exec($ch);
|
||||
curl_close($ch);
|
||||
|
||||
$result = json_decode($response, true);
|
||||
|
||||
if ($result && $result['ok']) {
|
||||
echo "Webhook configurado correctamente!\n\n";
|
||||
echo "Ahora ve a Telegram y envia /start al bot\n";
|
||||
} else {
|
||||
echo "Error al configurar webhook:\n";
|
||||
print_r($result);
|
||||
exit(1);
|
||||
}
|
||||
127
bot/webhook.php
Executable file
127
bot/webhook.php
Executable file
@@ -0,0 +1,127 @@
|
||||
<?php
|
||||
|
||||
// Configurar logging de errores
|
||||
error_reporting(E_ALL);
|
||||
ini_set('log_errors', 1);
|
||||
ini_set('error_log', __DIR__ . '/../logs/bot_error.log');
|
||||
|
||||
require_once __DIR__ . '/../config/config.php';
|
||||
require_once __DIR__ . '/TelegramBot.php';
|
||||
|
||||
class TurnoBot {
|
||||
private $bot;
|
||||
private $config;
|
||||
|
||||
public function __construct() {
|
||||
$this->config = require __DIR__ . '/../config/config.php';
|
||||
$this->bot = new TelegramBot();
|
||||
}
|
||||
|
||||
public function handleUpdate($update) {
|
||||
try {
|
||||
// Manejar callback de botones inline
|
||||
if (isset($update['callback_query'])) {
|
||||
$this->handleCallback($update['callback_query']);
|
||||
return;
|
||||
}
|
||||
|
||||
// Manejar mensajes normales
|
||||
if (!isset($update['message'])) {
|
||||
return;
|
||||
}
|
||||
|
||||
$message = $update['message'];
|
||||
$chatId = $message['chat']['id'];
|
||||
$text = trim($message['text'] ?? '');
|
||||
|
||||
if (empty($text)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$textLower = mb_strtolower($text, 'UTF-8');
|
||||
|
||||
// Comandos
|
||||
if ($textLower === '/start' || $textLower === '/menu' || $textLower === 'menu') {
|
||||
$this->sendMenu($chatId);
|
||||
} elseif ($textLower === '/turnos' || $textLower === 'turnos') {
|
||||
$this->bot->sendMessage($chatId, $this->bot->getTablaTurnos(8));
|
||||
} elseif ($textLower === '/semana' || $textLower === 'semana' || $textLower === 'hoy') {
|
||||
$this->bot->sendMessage($chatId, $this->bot->getSemanaActual());
|
||||
} elseif ($textLower === '/ayudantes' || $textLower === 'ayudantes') {
|
||||
$ayudantes = $this->bot->getListaAyudantesParaBusqueda();
|
||||
$this->bot->sendMessage($chatId, "<b>AYUDANTES DISPONIBLES:</b>\n\n" . implode("\n", $ayudantes));
|
||||
} else {
|
||||
// Buscar por nombre
|
||||
$this->bot->sendMessage($chatId, $this->bot->getTurnosAyudante($text));
|
||||
}
|
||||
} catch (Exception $e) {
|
||||
error_log("Error en handleUpdate: " . $e->getMessage());
|
||||
if (isset($update['message']['chat']['id'])) {
|
||||
$this->bot->sendMessage($update['message']['chat']['id'], "Error: " . $e->getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private function handleCallback($callback) {
|
||||
try {
|
||||
$callbackId = $callback['id'];
|
||||
$data = $callback['data'];
|
||||
$message = $callback['message'];
|
||||
$chatId = $message['chat']['id'];
|
||||
$messageId = $message['message_id'];
|
||||
|
||||
switch ($data) {
|
||||
case 'ver_turnos':
|
||||
$this->bot->answerCallback($callbackId, 'Cargando turnos...');
|
||||
$this->bot->editMessage($chatId, $messageId, $this->bot->getTablaTurnos(8));
|
||||
break;
|
||||
|
||||
case 'semana_actual':
|
||||
$this->bot->answerCallback($callbackId, 'Cargando semana actual...');
|
||||
$this->bot->editMessage($chatId, $messageId, $this->bot->getSemanaActual());
|
||||
break;
|
||||
|
||||
case 'buscar_nombre':
|
||||
$this->bot->answerCallback($callbackId, '');
|
||||
$this->bot->deleteMessage($chatId, $messageId);
|
||||
$this->bot->sendMessage($chatId, "🔍 <b>Buscar por Nombre</b>\n\nEscribe el nombre del ayudante que buscas:");
|
||||
break;
|
||||
|
||||
case 'mi_turno':
|
||||
$this->bot->answerCallback($callbackId, 'Enviando tu turno...');
|
||||
$this->bot->editMessage($chatId, $messageId, "Por favor ingresa tu nombre para ver tu turno:");
|
||||
break;
|
||||
|
||||
default:
|
||||
$this->bot->answerCallback($callbackId, 'Opcion no reconocida');
|
||||
}
|
||||
} catch (Exception $e) {
|
||||
error_log("Error en handleCallback: " . $e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
private function sendMenu($chatId) {
|
||||
$mensaje = "<b>BOT DE TURNOS - CONTENEDOR IBIZA</b>\n\n";
|
||||
$mensaje .= "Selecciona una opcion del menu:\n\n";
|
||||
$mensaje .= "Ver Turnos - Tabla completa de asignaciones\n";
|
||||
$mensaje .= "Semana Actual - Quien tiene turno esta semana\n";
|
||||
$mensaje .= "Buscar por Nombre - Consultar un ayudante especifico\n";
|
||||
$mensaje .= "Mi Turno - Ver tu proximo turno";
|
||||
|
||||
$this->bot->sendKeyboard($chatId, $mensaje);
|
||||
}
|
||||
}
|
||||
|
||||
// Recibir actualización
|
||||
$update = json_decode(file_get_contents('php://input'), true);
|
||||
|
||||
// Log para debugging
|
||||
error_log("Webhook recibido: " . json_encode($update));
|
||||
|
||||
if ($update) {
|
||||
$bot = new TurnoBot();
|
||||
$bot->handleUpdate($update);
|
||||
} else {
|
||||
http_response_code(200);
|
||||
echo "Webhook activo. Usa /start para ver el menu.";
|
||||
}
|
||||
Reference in New Issue
Block a user