512 lines
20 KiB
PHP
Executable File
512 lines
20 KiB
PHP
Executable File
<?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 = [], $httpMethod = 'POST') {
|
|
$url = "{$this->apiUrl}/{$method}";
|
|
$ch = curl_init();
|
|
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
|
|
|
|
// --- MEJORAS ---
|
|
// 1. Forzar el uso de IPv4.
|
|
curl_setopt($ch, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4);
|
|
|
|
// 2. Añadir timeouts de seguridad.
|
|
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 5); // 5 segundos para conectar
|
|
curl_setopt($ch, CURLOPT_TIMEOUT, 10); // 10 segundos para la transferencia total
|
|
|
|
// 3. (ÚLTIMO INTENTO) Forzar versión de TLS.
|
|
curl_setopt($ch, CURLOPT_SSLVERSION, CURL_SSLVERSION_TLSv1_2);
|
|
|
|
if ($httpMethod === 'POST') {
|
|
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_URL, $url);
|
|
} else { // GET request
|
|
$url .= empty($data) ? '' : '?' . http_build_query($data);
|
|
curl_setopt($ch, CURLOPT_URL, $url);
|
|
}
|
|
|
|
$response = curl_exec($ch);
|
|
|
|
// Añadir manejo de errores de cURL
|
|
if (curl_errno($ch)) {
|
|
error_log("cURL Error en {$method}: " . curl_error($ch));
|
|
curl_close($ch);
|
|
return null;
|
|
}
|
|
|
|
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', [], 'GET');
|
|
}
|
|
|
|
public function getUpdates($offset = 0) {
|
|
return $this->request('getUpdates', ['offset' => $offset, 'timeout' => 60], 'GET');
|
|
}
|
|
|
|
// --- NUEVOS MÉTODOS PARA CENTRALIZAR COMUNICACIONES ---
|
|
public function getWebhookInfo() {
|
|
return $this->request('getWebhookInfo', [], 'GET');
|
|
}
|
|
|
|
public function deleteWebhook() {
|
|
return $this->request('deleteWebhook', []);
|
|
}
|
|
|
|
public function setWebhook($webhookUrl, $allowedUpdates = ['message', 'callback_query']) {
|
|
return $this->request('setWebhook', [
|
|
'url' => $webhookUrl,
|
|
'allowed_updates' => $allowedUpdates
|
|
]);
|
|
}
|
|
|
|
|
|
public function sendKeyboard($chatId, $text) {
|
|
$keyboard = [
|
|
'inline_keyboard' => [
|
|
[
|
|
['text' => 'Ver Turnos', 'callback_data' => 'ver_turnos'],
|
|
['text' => 'Semana Actual', 'callback_data' => 'semana_actual']
|
|
],
|
|
[
|
|
['text' => '📄 Horarios PDF', 'callback_data' => 'mi_pdf']
|
|
],
|
|
[
|
|
['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' OR rol = 'coordinador') 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);
|
|
}
|
|
|
|
public function sendPDF($chatId, $userId) {
|
|
require_once __DIR__ . '/../src/PDFGenerator.php';
|
|
require_once __DIR__ . '/../src/User.php';
|
|
require_once __DIR__ . '/../src/DiasHorarios.php';
|
|
require_once __DIR__ . '/../src/Asignacion.php';
|
|
require_once __DIR__ . '/../src/Database.php';
|
|
|
|
$userModel = new User();
|
|
$userData = $userModel->getById($userId);
|
|
|
|
if (!$userData) {
|
|
$this->sendMessage($chatId, "Usuario no encontrado.");
|
|
return;
|
|
}
|
|
|
|
$horariosModel = new DiasHorarios();
|
|
$asignacionModel = new Asignacion();
|
|
$db = \Database::getInstance()->getConnection();
|
|
|
|
$horarios = $horariosModel->getActivos();
|
|
$ayudantes = $asignacionModel->getAyudantesPorOrden();
|
|
|
|
$semanasFuturas = [];
|
|
$hoy = new DateTime();
|
|
$diaSemana = (int)$hoy->format('w');
|
|
$domingoEstaSemana = clone $hoy;
|
|
$domingoEstaSemana->modify('-' . $diaSemana . ' days');
|
|
|
|
for ($i = 0; $i <= 4; $i++) {
|
|
$semanaDomingo = clone $domingoEstaSemana;
|
|
$semanaDomingo->modify("+{$i} weeks");
|
|
$semanaInicio = $semanaDomingo->format('Y-m-d');
|
|
$asignacionesSemana = $asignacionModel->getTodasAsignacionesPorSemana($semanaInicio);
|
|
$semanasFuturas[] = [
|
|
'inicio' => $semanaInicio,
|
|
'fin' => date('Y-m-d', strtotime('+5 days', strtotime($semanaInicio))),
|
|
'asignaciones' => $asignacionesSemana,
|
|
];
|
|
}
|
|
|
|
$diasNombres = [
|
|
'domingo' => 'Domingo', 'lunes' => 'Lunes', 'martes' => 'Martes',
|
|
'miercoles' => 'Miercoles', 'jueves' => 'Jueves', 'viernes' => 'Viernes', 'sabado' => 'Sabado'
|
|
];
|
|
$diasOrden = ['domingo', 'lunes', 'martes', 'miercoles', 'jueves', 'viernes', 'sabado'];
|
|
|
|
$html = PDFGenerator::getStyles();
|
|
$html .= PDFGenerator::getHeader('Horarios y Turnos - ' . $userData['nombre']);
|
|
|
|
$html .= '<h2>Mis Turnos</h2>';
|
|
$html .= '<table><thead><tr><th>Semana</th><th>Periodo</th><th>Estado</th></tr></thead><tbody>';
|
|
|
|
foreach ($semanasFuturas as $index => $semana) {
|
|
$esMiTurno = !empty($semana['asignaciones']) && in_array($userId, array_column($semana['asignaciones'], 'id'));
|
|
$html .= '<tr class="' . ($esMiTurno ? 'table-success' : '') . '">';
|
|
$html .= '<td>' . date('d/m/Y', strtotime($semana['inicio']));
|
|
if ($index === 0) {
|
|
$html .= ' <span class="badge badge-primary">Actual</span>';
|
|
}
|
|
if ($esMiTurno) {
|
|
$html .= ' <span class="badge badge-success">Tu turno</span>';
|
|
}
|
|
$html .= '</td>';
|
|
$html .= '<td>' . date('d/m/Y', strtotime($semana['inicio'])) . ' - ' . date('d/m/Y', strtotime($semana['fin'])) . '</td>';
|
|
$html .= '<td>' . ($esMiTurno ? 'Asignado' : 'Sin asignar') . '</td>';
|
|
$html .= '</tr>';
|
|
}
|
|
$html .= '</tbody></table>';
|
|
|
|
$html .= '<h2>Horarios por Semana</h2>';
|
|
$html .= '<table><thead><tr><th>Semana</th>';
|
|
foreach ($diasOrden as $dia) {
|
|
$html .= '<th class="text-center">' . $diasNombres[$dia] . '</th>';
|
|
}
|
|
$html .= '</tr></thead><tbody>';
|
|
|
|
foreach ($semanasFuturas as $index => $semana) {
|
|
$esMiTurno = !empty($semana['asignaciones']) && in_array($userId, array_column($semana['asignaciones'], 'id'));
|
|
$html .= '<tr class="' . ($esMiTurno ? 'table-success' : '') . '">';
|
|
$html .= '<td>' . date('d/m', strtotime($semana['inicio']));
|
|
if ($index === 0) {
|
|
$html .= ' <span class="badge badge-primary">Actual</span>';
|
|
}
|
|
$html .= '</td>';
|
|
|
|
foreach ($diasOrden as $dia) {
|
|
$horarioDia = null;
|
|
foreach ($horarios as $h) {
|
|
if ($h['dia_semana'] === $dia) {
|
|
$horarioDia = $h;
|
|
break;
|
|
}
|
|
}
|
|
$esActivo = $horarioDia && $horarioDia['activo'];
|
|
|
|
if ($esMiTurno && $esActivo) {
|
|
$html .= '<td class="text-center" style="background-color: #198754; color: white;">';
|
|
$html .= date('H:i', strtotime($horarioDia['hora_apertura'])) . '<br>' . date('H:i', strtotime($horarioDia['hora_cierre']));
|
|
$html .= '</td>';
|
|
} elseif (!$esActivo) {
|
|
$html .= '<td class="text-center text-muted">Cerrado</td>';
|
|
} else {
|
|
$html .= '<td class="text-center">' . date('H:i', strtotime($horarioDia['hora_apertura'])) . '<br>' . date('H:i', strtotime($horarioDia['hora_cierre'])) . '</td>';
|
|
}
|
|
}
|
|
$html .= '</tr>';
|
|
}
|
|
$html .= '</tbody></table>';
|
|
$html .= PDFGenerator::getFooter();
|
|
|
|
$pdfGenerator = new PDFGenerator();
|
|
$pdfContent = $pdfGenerator->generateFromHtml($html);
|
|
|
|
$pdfFile = tempnam(sys_get_temp_dir(), 'turnos');
|
|
file_put_contents($pdfFile, $pdfContent);
|
|
|
|
$this->sendDocument($chatId, $pdfFile, 'mis-turnos-' . date('Y-m-d') . '.pdf');
|
|
|
|
unlink($pdfFile);
|
|
}
|
|
|
|
public function sendDocument($chatId, $documentPath, $filename) {
|
|
$url = "{$this->apiUrl}/sendDocument";
|
|
$postFields = [
|
|
'chat_id' => $chatId,
|
|
'document' => new CURLFile($documentPath, 'application/pdf', $filename)
|
|
];
|
|
|
|
$ch = curl_init($url);
|
|
curl_setopt($ch, CURLOPT_POST, true);
|
|
curl_setopt($ch, CURLOPT_POSTFIELDS, $postFields);
|
|
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
|
|
curl_exec($ch);
|
|
curl_close($ch);
|
|
}
|
|
|
|
public function sendPDFGeneral($chatId) {
|
|
require_once __DIR__ . '/../src/PDFGenerator.php';
|
|
require_once __DIR__ . '/../src/User.php';
|
|
require_once __DIR__ . '/../src/DiasHorarios.php';
|
|
require_once __DIR__ . '/../src/Asignacion.php';
|
|
require_once __DIR__ . '/../src/Database.php';
|
|
|
|
$userModel = new User();
|
|
$horariosModel = new DiasHorarios();
|
|
$asignacionModel = new Asignacion();
|
|
$db = \Database::getInstance()->getConnection();
|
|
|
|
$horarios = $horariosModel->getActivos();
|
|
$ayudantes = $asignacionModel->getAyudantesPorOrden();
|
|
|
|
$semanasFuturas = [];
|
|
$hoy = new DateTime();
|
|
$diaSemana = (int)$hoy->format('w');
|
|
$domingoEstaSemana = clone $hoy;
|
|
$domingoEstaSemana->modify('-' . $diaSemana . ' days');
|
|
|
|
for ($i = 0; $i <= 4; $i++) {
|
|
$semanaDomingo = clone $domingoEstaSemana;
|
|
$semanaDomingo->modify("+{$i} weeks");
|
|
$semanaInicio = $semanaDomingo->format('Y-m-d');
|
|
$asignacionesSemana = $asignacionModel->getTodasAsignacionesPorSemana($semanaInicio);
|
|
$semanasFuturas[] = [
|
|
'inicio' => $semanaInicio,
|
|
'fin' => date('Y-m-d', strtotime('+5 days', strtotime($semanaInicio))),
|
|
'asignaciones' => $asignacionesSemana,
|
|
];
|
|
}
|
|
|
|
$diasNombres = [
|
|
'domingo' => 'Domingo', 'lunes' => 'Lunes', 'martes' => 'Martes',
|
|
'miercoles' => 'Miercoles', 'jueves' => 'Jueves', 'viernes' => 'Viernes', 'sabado' => 'Sabado'
|
|
];
|
|
$diasOrden = ['domingo', 'lunes', 'martes', 'miercoles', 'jueves', 'viernes', 'sabado'];
|
|
|
|
$html = PDFGenerator::getStyles();
|
|
$html .= PDFGenerator::getHeader('Horarios y Turnos - Todos los Ayudantes');
|
|
|
|
$html .= '<h2>Turnos de Ayudantes</h2>';
|
|
$html .= '<table><thead><tr><th>Ayudante</th><th>Fecha 1</th><th>Fecha 2</th><th>Fecha 3</th><th>Fecha 4</th></tr></thead><tbody>';
|
|
|
|
foreach ($ayudantes as $ayudante) {
|
|
$stmt = $db->prepare("SELECT semana_inicio, semana_fin FROM asignaciones_turnos WHERE user_id = ? AND semana_inicio >= CURDATE() ORDER BY semana_inicio LIMIT 4");
|
|
$stmt->execute([$ayudante['id']]);
|
|
$turnos = $stmt->fetchAll();
|
|
|
|
$html .= '<tr>';
|
|
$html .= '<td>' . htmlspecialchars($ayudante['nombre']) . '</td>';
|
|
for ($i = 0; $i < 4; $i++) {
|
|
if (isset($turnos[$i])) {
|
|
$html .= '<td class="text-center">' . date('d/m/Y', strtotime($turnos[$i]['semana_inicio'])) . ' - ' . date('d/m/Y', strtotime($turnos[$i]['semana_fin'])) . '</td>';
|
|
} else {
|
|
$html .= '<td class="text-center text-muted">-</td>';
|
|
}
|
|
}
|
|
$html .= '</tr>';
|
|
}
|
|
$html .= '</tbody></table>';
|
|
|
|
$html .= '<h2>Horarios por Semana</h2>';
|
|
$html .= '<table><thead><tr><th>Semana</th>';
|
|
foreach ($diasOrden as $dia) {
|
|
$html .= '<th class="text-center">' . $diasNombres[$dia] . '</th>';
|
|
}
|
|
$html .= '</tr></thead><tbody>';
|
|
|
|
foreach ($semanasFuturas as $index => $semana) {
|
|
$html .= '<tr>';
|
|
$html .= '<td>' . date('d/m', strtotime($semana['inicio']));
|
|
if ($index === 0) {
|
|
$html .= ' <span class="badge badge-primary">Actual</span>';
|
|
}
|
|
$html .= '</td>';
|
|
|
|
foreach ($diasOrden as $dia) {
|
|
$horarioDia = null;
|
|
foreach ($horarios as $h) {
|
|
if ($h['dia_semana'] === $dia) {
|
|
$horarioDia = $h;
|
|
break;
|
|
}
|
|
}
|
|
$esActivo = $horarioDia && $horarioDia['activo'];
|
|
|
|
if ($esActivo) {
|
|
$html .= '<td class="text-center">' . date('H:i', strtotime($horarioDia['hora_apertura'])) . '<br>' . date('H:i', strtotime($horarioDia['hora_cierre'])) . '</td>';
|
|
} else {
|
|
$html .= '<td class="text-center text-muted">Cerrado</td>';
|
|
}
|
|
}
|
|
$html .= '</tr>';
|
|
}
|
|
$html .= '</tbody></table>';
|
|
|
|
$html .= '<h2>Horarios de Apertura</h2>';
|
|
$html .= '<table><thead><tr><th>Dia</th><th>Hora Apertura</th><th>Hora Cierre</th><th>Estado</th></tr></thead><tbody>';
|
|
foreach ($horarios as $h) {
|
|
$html .= '<tr>';
|
|
$html .= '<td>' . ucfirst($h['dia_semana']) . '</td>';
|
|
$html .= '<td>' . date('H:i', strtotime($h['hora_apertura'])) . '</td>';
|
|
$html .= '<td>' . date('H:i', strtotime($h['hora_cierre'])) . '</td>';
|
|
$html .= '<td>' . ($h['activo'] ? 'Abierto' : 'Cerrado') . '</td>';
|
|
$html .= '</tr>';
|
|
}
|
|
$html .= '</tbody></table>';
|
|
$html .= PDFGenerator::getFooter();
|
|
|
|
$pdfGenerator = new PDFGenerator();
|
|
$pdfContent = $pdfGenerator->generateFromHtml($html);
|
|
|
|
$pdfFile = tempnam(sys_get_temp_dir(), 'turnos');
|
|
file_put_contents($pdfFile, $pdfContent);
|
|
|
|
$this->sendDocument($chatId, $pdfFile, 'turnos-contenedor-' . date('Y-m-d') . '.pdf');
|
|
|
|
unlink($pdfFile);
|
|
}
|
|
}
|