Files
sistema_funcionando_lastwar/admin/recipients.php

538 lines
30 KiB
PHP
Executable File

<?php
require_once __DIR__ . '/../includes/session_check.php';
require_once __DIR__ . '/../includes/db.php';
require_once __DIR__ . '/../includes/activity_logger.php';
// Admin-only access
if ($_SESSION['role'] !== 'admin') {
header('Location: ../index.php?error=unauthorized');
exit();
}
// Initialize variables for edit mode
$edit_mode = false;
$edit_recipient = [
'id' => null,
'name' => '',
'platform_id' => '',
'type' => 'channel',
'platform' => 'discord',
'language_code' => 'es'
];
// Handle form submissions
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$current_user_id = $_SESSION['user_id'];
$current_username = $_SESSION['username'];
$action = $_POST['action'] ?? null;
// Action: Add or Update Recipient
if (isset($_POST['add_recipient']) || isset($_POST['update_recipient'])) {
$platform = $_POST['platform'] ?? 'discord';
$type = $_POST['type'] ?? 'channel';
$name = $_POST['name'] ?? '';
$platform_id = $_POST['platform_id'] ?? '';
$language_code = $_POST['language_code'] ?? 'es';
$id = $_POST['id'] ?? null;
if (empty($name) || empty($platform_id) || empty($type) || empty($platform)) {
$error = "Todos los campos son obligatorios.";
} elseif (!is_numeric($platform_id)) {
$error = "El ID de Plataforma debe ser un número.";
} else {
try {
if (isset($_POST['update_recipient'])) { // UPDATE
$stmt = $pdo->prepare("UPDATE recipients SET name = ?, platform_id = ?, type = ?, platform = ?, language_code = ? WHERE id = ?");
$stmt->execute([$name, $platform_id, $type, $platform, $language_code, $id]);
$details = 'Admin ' . $current_username . ' updated recipient: ' . $name . ' (' . $platform . ':' . $platform_id . ')';
log_activity($current_user_id, 'Recipient Updated', $details);
header('Location: recipients.php?success=updated');
exit();
} else { // ADD
$stmt = $pdo->prepare("INSERT INTO recipients (name, platform_id, type, platform, language_code) VALUES (?, ?, ?, ?, ?)");
$stmt->execute([$name, $platform_id, $type, $platform, $language_code]);
$new_recipient_id = $pdo->lastInsertId();
$details = 'Admin ' . $current_username . ' added new recipient: ' . $name . ' (' . $platform . ':' . $platform_id . ')';
log_activity($current_user_id, 'Recipient Added', $details);
$success = "Destinatario añadido con éxito.";
}
} catch (PDOException $e) {
if ($e->errorInfo[1] == 1062) {
$error = "El ID de Plataforma ('$platform_id') ya existe.";
} else {
$error = "Error en la base de datos: " . $e->getMessage();
}
// Keep form data on error
$edit_mode = isset($_POST['update_recipient']);
$edit_recipient = ['id' => $id, 'name' => $name, 'platform_id' => $platform_id, 'type' => $type, 'platform' => $platform, 'language_code' => $language_code];
}
}
}
// Action: Delete Single Recipient
elseif (isset($_POST['delete_recipient'])) {
$id_to_delete = $_POST['id_to_delete'];
try {
$stmt_recipient = $pdo->prepare("SELECT name, platform, platform_id FROM recipients WHERE id = ?");
$stmt_recipient->execute([$id_to_delete]);
$recipient_info = $stmt_recipient->fetch(PDO::FETCH_ASSOC);
$details = 'Admin ' . $current_username . ' deleted recipient: ' . ($recipient_info['name'] ?? 'Unknown') . ' (' . ($recipient_info['platform'] ?? 'N/A') . ':' . ($recipient_info['platform_id'] ?? 'N/A') . ')';
$stmt = $pdo->prepare("DELETE FROM recipients WHERE id = ?");
$stmt->execute([$id_to_delete]);
log_activity($current_user_id, 'Recipient Deleted', $details);
$success = "Destinatario eliminado con éxito.";
} catch (PDOException $e) {
$error = "Error al eliminar. Es posible que el destinatario esté en uso.";
}
}
// Action: Kick Telegram User
elseif ($action === 'kick_telegram_user') {
$recipient_id_to_kick = $_POST['recipient_id_to_kick'] ?? null;
$chat_id_to_kick_from = $_POST['chat_id_to_kick_from'] ?? null;
if ($recipient_id_to_kick && $chat_id_to_kick_from) {
try {
// Get recipient's platform_id (Telegram user ID)
$stmt = $pdo->prepare("SELECT platform_id, name FROM recipients WHERE id = ? AND platform = 'telegram' AND type = 'user'");
$stmt->execute([$recipient_id_to_kick]);
$recipient_info = $stmt->fetch(PDO::FETCH_ASSOC);
$telegram_user_id = $recipient_info['platform_id'] ?? null;
$recipient_name = $recipient_info['name'] ?? 'Unknown';
if ($telegram_user_id) {
// Get bot token
$botToken = $_ENV['TELEGRAM_BOT_TOKEN'] ?? '';
if (empty($botToken)) {
throw new Exception("Token de bot de Telegram no configurado.");
}
// Telegram API URL for banning a chat member
$telegramApiUrl = "https://api.telegram.org/bot{$botToken}/banChatMember";
$params = [
'chat_id' => $chat_id_to_kick_from,
'user_id' => $telegram_user_id,
'until_date' => time() + 30 // Ban for 30 seconds to ensure they are removed, then they can rejoin
];
$options = [
'http' => [
'header' => "Content-type: application/x-www-form-urlencoded\r\n",
'method' => 'POST',
'content' => http_build_query($params),
],
];
$context = stream_context_create($options);
$result = file_get_contents($telegramApiUrl, false, $context);
$response = json_decode($result, true);
if ($response && $response['ok']) {
// If successful, unban immediately to allow re-entry
$unbanTelegramApiUrl = "https://api.telegram.org/bot{$botToken}/unbanChatMember";
$unbanParams = [
'chat_id' => $chat_id_to_kick_from,
'user_id' => $telegram_user_id,
'only_if_banned' => true // Only try to unban if they are actually banned
];
$unbanOptions = [
'http' => [
'header' => "Content-type: application/x-www-form-urlencoded\r\n",
'method' => 'POST',
'content' => http_build_query($unbanParams),
],
];
$unbanContext = stream_context_create($unbanOptions);
$unbanResult = file_get_contents($unbanTelegramApiUrl, false, $unbanContext);
$unbanResponse = json_decode($unbanResult, true);
if ($unbanResponse && $unbanResponse['ok']) {
$success = "Usuario de Telegram expulsado del grupo (permite reingreso) y eliminado de la base de datos.";
} else {
// Log unban error but still proceed with local deletion as kick was successful
error_log("Error al desbanear usuario de Telegram después de la expulsión: " . ($unbanResponse['description'] ?? 'Error desconocido'));
$success = "Usuario de Telegram expulsado del grupo (error al permitir reingreso) y eliminado de la base de datos.";
}
// Delete from local DB regardless of unban success, as the kick itself was successful
$stmt = $pdo->prepare("DELETE FROM recipients WHERE id = ?");
$stmt->execute([$recipient_id_to_kick]);
$details = 'Admin ' . $current_username . ' kicked Telegram user: ' . $recipient_name . ' (ID: ' . $telegram_user_id . ') from group ID: ' . $chat_id_to_kick_from;
log_activity($current_user_id, 'Telegram User Kicked', $details);
} else {
$error = "Error al expulsar usuario de Telegram: " . ($response['description'] ?? 'Error desconocido');
}
} else {
$error = "Usuario de Telegram no encontrado o no es un usuario válido para expulsar.";
}
} catch (Exception $e) {
$error = "Error al procesar la expulsión: " . $e->getMessage();
}
} else {
$error = "Faltan parámetros para expulsar al usuario de Telegram.";
}
}
// Action: Delete Multiple Recipients
elseif ($action === 'delete_selected' && !empty($_POST['selected_recipients'])) {
$deleted_count = 0;
$error_count = 0;
foreach ($_POST['selected_recipients'] as $recipient_id) {
try {
$stmt_recipient = $pdo->prepare("SELECT name, platform, platform_id FROM recipients WHERE id = ?");
$stmt_recipient->execute([$recipient_id]);
$recipient_info = $stmt_recipient->fetch(PDO::FETCH_ASSOC);
$details = 'Admin ' . $current_username . ' deleted recipient: ' . ($recipient_info['name'] ?? 'Unknown') . ' (' . ($recipient_info['platform'] ?? 'N/A') . ':' . ($recipient_info['platform_id'] ?? 'N/A') . ')';
$stmt = $pdo->prepare("DELETE FROM recipients WHERE id = ?");
$stmt->execute([$recipient_id]);
log_activity($current_user_id, 'Recipient Deleted', $details);
$deleted_count++;
} catch (PDOException $e) {
$error_count++;
error_log("Error al eliminar destinatario ID $recipient_id: " . $e->getMessage());
}
}
if ($deleted_count > 0) {
$success = "Se eliminaron $deleted_count destinatarios correctamente.";
if ($error_count > 0) {
$error = "Hubo errores al eliminar $error_count destinatarios.";
}
header('Location: recipients.php?success=deleted_multiple&deleted=' . $deleted_count . '&errors=' . $error_count);
exit();
} else if ($error_count > 0) {
$error = "No se pudo eliminar ningún destinatario. Por favor, inténtalo de nuevo.";
}
}
}
// Handle entering edit mode via GET request
if (isset($_GET['action']) && $_GET['action'] === 'edit' && isset($_GET['id'])) {
$edit_mode = true;
$stmt = $pdo->prepare("SELECT * FROM recipients WHERE id = ?");
$stmt->execute([$_GET['id']]);
$recipient_to_edit = $stmt->fetch();
if ($recipient_to_edit) {
$edit_recipient = $recipient_to_edit;
}
}
// Fetch all recipients to display
$recipients = $pdo->query("SELECT * FROM recipients ORDER BY platform, type, name ASC")->fetchAll();
$pageTitle = 'Gestionar Destinatarios';
require_once __DIR__ . '/../templates/header.php';
// Display feedback messages
if (isset($error)) echo "<div class='alert alert-danger'>$error</div>";
if (isset($success)) echo "<div class='alert alert-success'>$success</div>";
if (isset($_GET['success'])) {
if ($_GET['success'] === 'deleted_multiple') {
$deleted = isset($_GET['deleted']) ? (int)$_GET['deleted'] : 0;
$errors = isset($_GET['errors']) ? (int)$_GET['errors'] : 0;
if ($deleted > 0) {
echo '<div class="alert alert-success">Se eliminaron ' . $deleted . ' destinatarios correctamente.</div>';
}
if ($errors > 0) {
echo '<div class="alert alert-danger">Hubo errores al eliminar ' . $errors . ' destinatarios.</div>';
}
} else {
echo "<div class='alert alert-success'>Operación completada con éxito.</div>";
}
}
?>
<div class="container-fluid">
<h1 class="mt-4" data-translate="true">Gestionar Destinatarios</h1>
<!-- Add/Edit Recipient Form -->
<div class="card shadow-sm mb-4">
<div class="card-header">
<h5 class="mb-0" data-translate="true"><?= $edit_mode ? 'Editar Destinatario' : 'Añadir Nuevo Destinatario' ?></h5>
</div>
<div class="card-body">
<form action="recipients.php" method="POST">
<?php if ($edit_mode): ?><input type="hidden" name="id" value="<?= $edit_recipient['id'] ?>"><?php endif; ?>
<div class="row align-items-end">
<div class="col-md-2 mb-3">
<label for="platform" class="form-label" data-translate="true">Plataforma</label>
<select class="form-select" id="platform" name="platform" required>
<option value="discord" <?= ($edit_recipient['platform'] === 'discord') ? 'selected' : '' ?> data-translate="true">Discord</option>
<option value="telegram" <?= ($edit_recipient['platform'] === 'telegram') ? 'selected' : '' ?> data-translate="true">Telegram</option>
</select>
</div>
<div class="col-md-3 mb-3">
<label for="name" class="form-label" data-translate="true">Nombre (identificador)</label>
<input type="text" class="form-control" id="name" name="name" value="<?= htmlspecialchars($edit_recipient['name']) ?>" required>
</div>
<div class="col-md-2 mb-3">
<label for="platform_id" class="form-label" data-translate="true">ID de Plataforma</label>
<input type="text" class="form-control" id="platform_id" name="platform_id" value="<?= htmlspecialchars($edit_recipient['platform_id']) ?>" required>
</div>
<div class="col-md-2 mb-3">
<label for="type" class="form-label" data-translate="true">Tipo</label>
<select class="form-select" id="type" name="type" required>
<option value="channel" <?= ($edit_recipient['type'] === 'channel') ? 'selected' : '' ?> data-translate="true">Canal/Grupo</option>
<option value="user" <?= ($edit_recipient['type'] === 'user') ? 'selected' : '' ?> data-translate="true">Usuario</option>
</select>
</div>
<div class="col-md-1 mb-3">
<label for="language_code" class="form-label" data-translate="true">Idioma</label>
<select class="form-select" id="language_code" name="language_code" required>
<option value="es" <?= ($edit_recipient['language_code'] === 'es') ? 'selected' : '' ?>>ES</option>
<option value="en" <?= ($edit_recipient['language_code'] === 'en') ? 'selected' : '' ?>>EN</option>
<option value="fr" <?= ($edit_recipient['language_code'] === 'fr') ? 'selected' : '' ?>>FR</option>
<option value="de" <?= ($edit_recipient['language_code'] === 'de') ? 'selected' : '' ?>>DE</option>
<option value="it" <?= ($edit_recipient['language_code'] === 'it') ? 'selected' : '' ?>>IT</option>
<option value="pt" <?= ($edit_recipient['language_code'] === 'pt') ? 'selected' : '' ?>>PT</option>
<option value="ru" <?= ($edit_recipient['language_code'] === 'ru') ? 'selected' : '' ?>>RU</option>
<option value="ja" <?= ($edit_recipient['language_code'] === 'ja') ? 'selected' : '' ?>>JA</option>
<option value="zh" <?= ($edit_recipient['language_code'] === 'zh') ? 'selected' : '' ?>>ZH</option>
</select>
</div>
<div class="col-md-2 mb-3">
<?php if ($edit_mode): ?>
<button type="submit" name="update_recipient" class="btn btn-success w-100">
<i class="bi bi-save"></i> <span data-translate="true">Guardar</span>
</button>
<?php else: ?>
<button type="submit" name="add_recipient" class="btn btn-primary w-100">
<i class="bi bi-plus-circle"></i> <span data-translate="true">Añadir</span>
</button>
<?php endif; ?>
</div>
<?php if ($edit_mode): ?>
<div class="col-md-12"><a href="recipients.php" class="btn btn-sm btn-outline-secondary" data-translate="true">Cancelar Edición</a></div>
<?php endif; ?>
</div>
</form>
</div>
</div>
<!-- Recipients List -->
<div class="card shadow-sm">
<div class="card-header d-flex justify-content-between align-items-center">
<h5 class="mb-0" data-translate="true">Lista de Destinatarios</h5>
<div>
<button type="button" id="selectAllBtn" class="btn btn-sm btn-outline-secondary me-2">
<i class="bi bi-check2-square"></i> <span data-translate="true">Seleccionar todo</span>
</button>
<button type="button" id="deleteSelectedBtn" class="btn btn-sm btn-danger" disabled>
<i class="bi bi-trash"></i> <span data-translate="true">Eliminar seleccionados</span>
</button>
</div>
</div>
<div class="card-body">
<form id="recipientsForm" action="" method="POST" onsubmit="return confirm('¿Estás seguro de que quieres eliminar los destinatarios seleccionados?');">
<input type="hidden" name="action" value="delete_selected">
<input type="hidden" name="confirm_message" value="¿Estás seguro de que quieres eliminar los destinatarios seleccionados?" data-translate-confirm="¿Estás seguro de que quieres eliminar los destinatarios seleccionados?">
<div class="table-responsive">
<table class="table table-hover">
<thead class="table-light">
<tr>
<th width="40"><input type="checkbox" id="selectAll"></th>
<th data-translate="true">Plataforma</th>
<th data-translate="true">Nombre</th>
<th data-translate="true">ID de Plataforma</th>
<th data-translate="true">Tipo</th>
<th data-translate="true">Idioma</th>
<th data-translate="true">Añadido en</th>
<th class="text-center" data-translate="true">Acciones</th>
</tr>
</thead>
<tbody>
<?php foreach ($recipients as $recipient): ?>
<tr>
<td><input type="checkbox" name="selected_recipients[]" value="<?= $recipient['id'] ?>" class="recipient-checkbox"></td>
<td>
<span class="badge <?= $recipient['platform'] === 'discord' ? 'bg-primary' : 'bg-info' ?>">
<?= htmlspecialchars(ucfirst($recipient['platform'])) ?>
</span>
</td>
<td><?= htmlspecialchars($recipient['name']) ?></td>
<td><?= htmlspecialchars($recipient['platform_id']) ?></td>
<td><?= htmlspecialchars(ucfirst($recipient['type'])) ?></td>
<td><span class="badge bg-secondary"><?= strtoupper(htmlspecialchars($recipient['language_code'] ?? 'es')) ?></span></td>
<td><?= date('d/m/Y H:i', strtotime($recipient['created_at'])) ?></td>
<td class="text-center">
<div class="btn-group" role="group">
<a href="?action=edit&id=<?= $recipient['id'] ?>" class="btn btn-sm btn-primary" title="Editar">
<i class="bi bi-pencil"></i>
</a>
<form action="recipients.php" method="POST" onsubmit="return confirm(this.querySelector('[data-translate-confirm]').getAttribute('data-translate-confirm'));" class="d-inline ms-1">
<input type="hidden" name="id_to_delete" value="<?= $recipient['id'] ?>">
<input type="hidden" name="confirm_message" value="¿Estás seguro de que quieres eliminar este destinatario?" data-translate-confirm="¿Estás seguro de que quieres eliminar este destinatario?">
<button type="submit" name="delete_recipient" class="btn btn-sm btn-danger" title="Eliminar" data-translate-title="true">
<i class="bi bi-trash"></i>
</button>
</form>
<?php if ($recipient['platform'] === 'telegram' && $recipient['type'] === 'user'): ?>
<button type="button" class="btn btn-sm btn-warning ms-1 kick-telegram-user-btn"
data-bs-toggle="modal" data-bs-target="#kickUserModal"
data-recipient-id="<?= $recipient['id'] ?>"
title="Expulsar de Telegram y Eliminar" data-translate-title="true">
<i class="bi bi-person-x"></i>
</button>
<?php endif; ?>
</div>
</td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
</div>
</form>
</div>
</div>
</div>
<?php require_once __DIR__ . '/../templates/footer.php'; ?>
<!-- Modal para Expulsar Usuario de Telegram -->
<div class="modal fade" id="kickUserModal" tabindex="-1" aria-labelledby="kickUserModalLabel" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="kickUserModalLabel">Expulsar Usuario de Telegram</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<form id="kickUserForm" action="recipients.php" method="POST">
<div class="modal-body">
<input type="hidden" name="action" value="kick_telegram_user">
<input type="hidden" name="recipient_id_to_kick" id="modalRecipientId">
<p>Selecciona el grupo del que deseas expulsar a <strong id="modalUserName"></strong>:</p>
<div id="groupListContainer">
<!-- Los grupos se cargarán aquí dinámicamente -->
<p class="text-muted">Cargando grupos...</p>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Cancelar</button>
<button type="submit" class="btn btn-danger" id="confirmKickBtn" disabled>Expulsar y Eliminar</button>
</div>
</form>
</div>
</div>
</div>
<script>
document.addEventListener('DOMContentLoaded', function () {
// Selección múltiple
const selectAllCheckbox = document.getElementById('selectAll');
const recipientCheckboxes = document.querySelectorAll('.recipient-checkbox');
const deleteSelectedBtn = document.getElementById('deleteSelectedBtn');
const selectAllBtn = document.getElementById('selectAllBtn');
// Seleccionar/deseleccionar todos los checkboxes
if (selectAllCheckbox) {
selectAllCheckbox.addEventListener('change', function() {
const isChecked = this.checked;
recipientCheckboxes.forEach(checkbox => {
checkbox.checked = isChecked;
});
updateDeleteButton();
});
}
// Botón "Seleccionar todo"
if (selectAllBtn) {
selectAllBtn.addEventListener('click', function() {
const allChecked = Array.from(recipientCheckboxes).every(checkbox => checkbox.checked);
recipientCheckboxes.forEach(checkbox => {
checkbox.checked = !allChecked;
});
selectAllCheckbox.checked = !allChecked;
updateDeleteButton();
});
}
// Actualizar el estado del botón de eliminar seleccionados
function updateDeleteButton() {
const checkedBoxes = document.querySelectorAll('.recipient-checkbox:checked');
deleteSelectedBtn.disabled = checkedBoxes.length === 0;
}
// Actualizar el checkbox "Seleccionar todo" cuando se marcan/desmarcan checkboxes individuales
recipientCheckboxes.forEach(checkbox => {
checkbox.addEventListener('change', function() {
updateDeleteButton();
selectAllCheckbox.checked = Array.from(recipientCheckboxes).every(checkbox => checkbox.checked);
});
});
// Manejar el clic en el botón de eliminar seleccionados
if (deleteSelectedBtn) {
deleteSelectedBtn.addEventListener('click', function() {
if (confirm('¿Estás seguro de que quieres eliminar los destinatarios seleccionados?')) {
document.getElementById('recipientsForm').submit();
}
});
}
// Lógica para el modal de expulsar usuario de Telegram
const kickUserModal = document.getElementById('kickUserModal');
const modalRecipientId = document.getElementById('modalRecipientId');
const modalUserName = document.getElementById('modalUserName');
const groupListContainer = document.getElementById('groupListContainer');
const confirmKickBtn = document.getElementById('confirmKickBtn');
const kickUserForm = document.getElementById('kickUserForm');
kickUserModal.addEventListener('show.bs.modal', function (event) {
const button = event.relatedTarget; // Botón que activó el modal
const recipientId = button.getAttribute('data-recipient-id');
modalRecipientId.value = recipientId;
modalUserName.textContent = 'Cargando...';
groupListContainer.innerHTML = '<p class="text-muted">Cargando grupos...</p>';
confirmKickBtn.disabled = true;
// Cargar los grupos del usuario vía AJAX
fetch(`get_user_groups.php?recipient_id=${recipientId}`)
.then(response => response.json())
.then(data => {
if (data.success) {
modalUserName.textContent = data.userName;
if (data.groups.length > 0) {
let groupsHtml = '';
data.groups.forEach(group => {
groupsHtml += `
<div class="form-check">
<input class="form-check-input" type="radio" name="chat_id_to_kick_from" id="group_${group.chat_id}" value="${group.chat_id}">
<label class="form-check-label" for="group_${group.chat_id}">
${group.group_name} (ID: ${group.chat_id})
</label>
</div>
`;
});
groupListContainer.innerHTML = groupsHtml;
// Habilitar el botón de confirmar cuando se selecciona un radio
groupListContainer.querySelectorAll('input[type="radio"]').forEach(radio => {
radio.addEventListener('change', () => {
confirmKickBtn.disabled = false;
});
});
} else {
groupListContainer.innerHTML = '<p class="text-info">Este usuario no está registrado en ningún grupo de Telegram.</p>';
}
} else {
groupListContainer.innerHTML = `<p class="text-danger">Error al cargar grupos: ${data.error}</p>`;
}
})
.catch(error => {
console.error('Error fetching groups:', error);
groupListContainer.innerHTML = '<p class="text-danger">Error de red al cargar grupos.</p>';
});
});
// Confirmación final antes de enviar el formulario de expulsión
kickUserForm.addEventListener('submit', function(event) {
if (!confirm('¿Estás seguro de que quieres expulsar a este usuario del grupo seleccionado y eliminarlo de la base de datos?')) {
event.preventDefault();
}
});
});
</script>