737 lines
29 KiB
PHP
Executable File
737 lines
29 KiB
PHP
Executable File
<?php
|
|
session_start();
|
|
|
|
// Habilitar logging para depuración
|
|
ini_set('display_errors', 1);
|
|
ini_set('display_startup_errors', 1);
|
|
error_reporting(E_ALL);
|
|
|
|
require_once __DIR__ . '/../../../shared/utils/helpers.php';
|
|
require_once __DIR__ . '/../../../shared/auth/jwt.php';
|
|
require_once __DIR__ . '/../../../shared/database/connection.php';
|
|
|
|
$userData = JWTAuth::requireAuth();
|
|
|
|
// Verificar permiso para enviar mensajes
|
|
if (!hasPermission('send_messages', 'discord')) {
|
|
die('No tienes permiso para crear y enviar mensajes de Discord.');
|
|
}
|
|
|
|
$db = getDB();
|
|
|
|
// Obtener plantillas para el selector
|
|
$stmt = $db->query("SELECT id, nombre, contenido FROM plantillas_discord ORDER BY nombre ASC");
|
|
$plantillas = $stmt->fetchAll();
|
|
|
|
// Obtener destinatarios guardados (si existen)
|
|
$stmt = $db->query("SELECT id, nombre, discord_id as identificador, tipo FROM destinatarios_discord ORDER BY nombre ASC");
|
|
$destinatarios = $stmt->fetchAll();
|
|
?>
|
|
<!DOCTYPE html>
|
|
<html lang="<?php echo $userData->idioma ?? 'es'; ?>">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
<title>Crear Mensaje Discord - Sistema de Bots</title>
|
|
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
|
|
<link href="https://cdn.jsdelivr.net/npm/summernote@0.8.18/dist/summernote-lite.min.css" rel="stylesheet">
|
|
<link href="https://cdn.jsdelivr.net/npm/select2@4.1.0-rc.0/dist/css/select2.min.css" rel="stylesheet" />
|
|
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/flag-icon-css/4.1.5/css/flag-icons.min.css" />
|
|
<style>
|
|
/* Estilos para los botones de traducción */
|
|
.translation-buttons {
|
|
margin-bottom: 10px;
|
|
padding: 5px;
|
|
border: 1px solid #e0e0e0;
|
|
border-radius: 4px;
|
|
background-color: #f8f9fa;
|
|
display: flex;
|
|
flex-wrap: wrap;
|
|
gap: 5px;
|
|
}
|
|
|
|
.translation-buttons .btn-translate {
|
|
border: 1px solid #dee2e6;
|
|
border-radius: 4px;
|
|
padding: 2px 8px;
|
|
font-size: 12px;
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 5px;
|
|
background: white;
|
|
transition: all 0.2s;
|
|
}
|
|
|
|
.translation-buttons .btn-translate:hover {
|
|
background-color: #e9ecef;
|
|
transform: translateY(-1px);
|
|
}
|
|
|
|
.translation-buttons .btn-translate:active {
|
|
transform: translateY(0);
|
|
}
|
|
|
|
.translation-buttons .flag-icon {
|
|
width: 16px;
|
|
height: 12px;
|
|
border-radius: 2px;
|
|
box-shadow: 0 0 1px rgba(0,0,0,0.3);
|
|
}
|
|
|
|
.translation-buttons .loading {
|
|
opacity: 0.7;
|
|
pointer-events: none;
|
|
}
|
|
|
|
:root {
|
|
--discord-color: #5865F2;
|
|
--discord-dark: #4752C4;
|
|
}
|
|
|
|
* {
|
|
margin: 0;
|
|
padding: 0;
|
|
box-sizing: border-box;
|
|
}
|
|
|
|
body {
|
|
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
|
|
background: linear-gradient(135deg, var(--discord-color) 0%, var(--discord-dark) 100%);
|
|
min-height: 100vh;
|
|
padding: 20px;
|
|
}
|
|
|
|
.header {
|
|
background: white;
|
|
border-radius: 15px;
|
|
padding: 20px 30px;
|
|
margin-bottom: 30px;
|
|
display: flex;
|
|
justify-content: space-between;
|
|
align-items: center;
|
|
box-shadow: 0 5px 20px rgba(0, 0, 0, 0.1);
|
|
}
|
|
|
|
.header h1 {
|
|
color: var(--discord-color);
|
|
font-size: 24px;
|
|
}
|
|
|
|
.container {
|
|
max-width: 1000px;
|
|
margin: 0 auto;
|
|
}
|
|
|
|
.form-container {
|
|
background: white;
|
|
border-radius: 15px;
|
|
padding: 40px;
|
|
box-shadow: 0 5px 20px rgba(0, 0, 0, 0.1);
|
|
}
|
|
|
|
.form-group {
|
|
margin-bottom: 25px;
|
|
}
|
|
|
|
.form-group label {
|
|
display: block;
|
|
margin-bottom: 8px;
|
|
color: #333;
|
|
font-weight: 600;
|
|
font-size: 14px;
|
|
}
|
|
|
|
.form-control {
|
|
width: 100%;
|
|
padding: 12px 15px;
|
|
border: 2px solid #e0e0e0;
|
|
border-radius: 8px;
|
|
font-size: 15px;
|
|
transition: border-color 0.3s;
|
|
}
|
|
|
|
.form-control:focus {
|
|
outline: none;
|
|
border-color: var(--discord-color);
|
|
}
|
|
|
|
.form-help {
|
|
font-size: 13px;
|
|
color: #666;
|
|
margin-top: 5px;
|
|
}
|
|
|
|
.btn {
|
|
padding: 12px 24px;
|
|
border-radius: 8px;
|
|
text-decoration: none;
|
|
transition: all 0.2s;
|
|
border: none;
|
|
cursor: pointer;
|
|
font-size: 15px;
|
|
font-weight: 600;
|
|
}
|
|
|
|
.btn-primary {
|
|
background: var(--discord-color);
|
|
color: white;
|
|
}
|
|
|
|
.btn-primary:hover {
|
|
background: var(--discord-dark);
|
|
transform: translateY(-2px);
|
|
}
|
|
|
|
.btn-secondary {
|
|
background: #6c757d;
|
|
color: white;
|
|
}
|
|
|
|
.btn-secondary:hover {
|
|
background: #5a6268;
|
|
}
|
|
|
|
.btn-success {
|
|
background: #28a745;
|
|
color: white;
|
|
}
|
|
|
|
.form-actions {
|
|
display: flex;
|
|
gap: 15px;
|
|
margin-top: 30px;
|
|
border-top: 1px solid #eee;
|
|
padding-top: 20px;
|
|
}
|
|
|
|
/* Select2 Customization */
|
|
.select2-container--default .select2-selection--single {
|
|
height: 45px;
|
|
border: 2px solid #e0e0e0;
|
|
border-radius: 8px;
|
|
}
|
|
|
|
.select2-container--default .select2-selection--single .select2-selection__rendered {
|
|
line-height: 45px;
|
|
padding-left: 15px;
|
|
}
|
|
|
|
.select2-container--default .select2-selection--single .select2-selection__arrow {
|
|
height: 43px;
|
|
}
|
|
|
|
/* Modal Galería */
|
|
.modal {
|
|
display: none;
|
|
position: fixed;
|
|
z-index: 9999;
|
|
left: 0;
|
|
top: 0;
|
|
width: 100%;
|
|
height: 100%;
|
|
background: rgba(0, 0, 0, 0.7);
|
|
}
|
|
|
|
.modal-content {
|
|
background: white;
|
|
margin: 50px auto;
|
|
padding: 30px;
|
|
border-radius: 15px;
|
|
width: 90%;
|
|
max-width: 900px;
|
|
max-height: 80vh;
|
|
overflow-y: auto;
|
|
}
|
|
|
|
.gallery-grid {
|
|
display: grid;
|
|
grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
|
|
gap: 15px;
|
|
margin-top: 20px;
|
|
}
|
|
|
|
.gallery-item {
|
|
cursor: pointer;
|
|
border: 3px solid transparent;
|
|
border-radius: 10px;
|
|
overflow: hidden;
|
|
transition: all 0.3s;
|
|
}
|
|
|
|
.gallery-item:hover {
|
|
border-color: var(--discord-color);
|
|
transform: scale(1.05);
|
|
}
|
|
|
|
.gallery-item img {
|
|
width: 100%;
|
|
height: 150px;
|
|
object-fit: cover;
|
|
display: block;
|
|
}
|
|
|
|
.close {
|
|
float: right;
|
|
font-size: 28px;
|
|
font-weight: bold;
|
|
cursor: pointer;
|
|
}
|
|
</style>
|
|
</head>
|
|
<body>
|
|
<div class="header">
|
|
<h1><i class="fas fa-paper-plane"></i> Crear Mensaje Discord</h1>
|
|
<a href="/discord/dashboard_discord.php" class="btn btn-secondary">
|
|
<i class="fas fa-arrow-left"></i> Volver
|
|
</a>
|
|
</div>
|
|
|
|
<div class="container">
|
|
<div class="form-container">
|
|
<form id="messageForm">
|
|
<div class="form-group">
|
|
<label for="destinatario_id">Destinatarios (Canal ID o Usuario ID) *</label>
|
|
<div style="display: flex; gap: 10px;">
|
|
<div style="flex-grow: 1;">
|
|
<select id="destinatario_select" class="form-control" style="width: 100%;" multiple="multiple">
|
|
<?php foreach ($destinatarios as $dest): ?>
|
|
<option value="<?php echo htmlspecialchars($dest['identificador']); ?>">
|
|
<?php echo htmlspecialchars($dest['nombre']); ?> (<?php echo $dest['tipo']; ?>)
|
|
</option>
|
|
<?php endforeach; ?>
|
|
</select>
|
|
</div>
|
|
<div style="flex-grow: 1;">
|
|
<input type="text" id="destinatario_manual" name="destinatario_manual" class="form-control" placeholder="O pega IDs manualmente aquí, separados por comas">
|
|
</div>
|
|
</div>
|
|
<div class="form-help">Selecciona uno o varios destinatarios guardados, o ingresa IDs manualmente separados por comas.</div>
|
|
</div>
|
|
|
|
<div class="form-group">
|
|
<label for="plantilla_id">Cargar Plantilla (Opcional)</label>
|
|
<select id="plantilla_id" class="form-control" onchange="loadTemplate(this.value)">
|
|
<option value="">-- Seleccionar Plantilla --</option>
|
|
<?php foreach ($plantillas as $plantilla): ?>
|
|
<option value="<?php echo htmlspecialchars($plantilla['id']); ?>">
|
|
<?php echo htmlspecialchars($plantilla['nombre']); ?>
|
|
</option>
|
|
<?php endforeach; ?>
|
|
</select>
|
|
</div>
|
|
|
|
<div class="form-group">
|
|
<label for="contenido">Contenido del Mensaje *</label>
|
|
<div id="translation-buttons" class="translation-buttons" style="margin-bottom: 10px; display: flex; gap: 5px;">
|
|
<!-- Los botones se cargarán dinámicamente con JavaScript -->
|
|
</div>
|
|
<button type="button" onclick="openGallery()" class="btn btn-success" style="margin-bottom: 10px; padding: 5px 10px; font-size: 12px;">
|
|
<i class="fas fa-images"></i> Insertar Imagen
|
|
</button>
|
|
<textarea id="contenido" name="contenido" class="form-control" rows="10" required></textarea>
|
|
</div>
|
|
|
|
<div class="form-group">
|
|
<label>Tipo de Envío *</label>
|
|
<div>
|
|
<input type="radio" id="send_immediate" name="send_type" value="inmediato" checked>
|
|
<label for="send_immediate">Inmediato</label>
|
|
|
|
<input type="radio" id="send_scheduled" name="send_type" value="programado" class="ml-3">
|
|
<label for="send_scheduled">Programado</label>
|
|
|
|
<input type="radio" id="send_recurring" name="send_type" value="recurrente" class="ml-3">
|
|
<label for="send_recurring">Recurrente</label>
|
|
</div>
|
|
</div>
|
|
|
|
<div id="scheduled_options" class="form-group" style="display: none;">
|
|
<label for="schedule_datetime">Fecha y Hora de Envío *</label>
|
|
<input type="datetime-local" id="schedule_datetime" name="schedule_datetime" class="form-control">
|
|
</div>
|
|
|
|
<div id="recurring_options" class="form-group" style="display: none;">
|
|
<label for="recurrence_frequency">Frecuencia de Recurrencia *</label>
|
|
<select id="recurrence_frequency" name="recurrence_frequency" class="form-control">
|
|
<option value="diario">Diario</option>
|
|
<option value="semanal">Semanal</option>
|
|
<option value="mensual">Mensual</option>
|
|
</select>
|
|
|
|
<div id="recurring_details" style="margin-top: 15px;">
|
|
<!-- Detalles específicos de recurrencia (día de la semana, día del mes) -->
|
|
<div id="weekly_options" style="display: none;">
|
|
<label for="recurrence_day_of_week">Día de la Semana</label>
|
|
<select id="recurrence_day_of_week" name="recurrence_day_of_week" class="form-control">
|
|
<option value="1">Lunes</option>
|
|
<option value="2">Martes</option>
|
|
<option value="3">Miércoles</option>
|
|
<option value="4">Jueves</option>
|
|
<option value="5">Viernes</option>
|
|
<option value="6">Sábado</option>
|
|
<option value="7">Domingo</option>
|
|
</select>
|
|
</div>
|
|
<div id="monthly_options" style="display: none;">
|
|
<label for="recurrence_day_of_month">Día del Mes</label>
|
|
<input type="number" id="recurrence_day_of_month" name="recurrence_day_of_month" class="form-control" min="1" max="31">
|
|
</div>
|
|
<label for="recurrence_time">Hora de Envío</label>
|
|
<input type="time" id="recurrence_time" name="recurrence_time" class="form-control">
|
|
</div>
|
|
</div>
|
|
|
|
<div class="form-actions">
|
|
<button type="submit" class="btn btn-primary" id="btnEnviar">
|
|
<i class="fas fa-paper-plane"></i> Enviar Ahora
|
|
</button>
|
|
<button type="button" class="btn btn-secondary" onclick="previewMessage()">
|
|
<i class="fas fa-eye"></i> Vista Previa
|
|
</button>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Modal Galería -->
|
|
<div id="galleryModal" class="modal">
|
|
<div class="modal-content">
|
|
<span class="close" onclick="closeGallery()">×</span>
|
|
<h2>Galería de Imágenes</h2>
|
|
<div class="gallery-grid" id="galleryGrid"></div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Templates Data Hidden -->
|
|
<script>
|
|
const templates = <?php echo json_encode($plantillas); ?>;
|
|
</script>
|
|
|
|
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
|
|
<script src="https://cdn.jsdelivr.net/npm/summernote@0.8.18/dist/summernote-lite.min.js"></script>
|
|
<script src="https://cdn.jsdelivr.net/npm/select2@4.1.0-rc.0/dist/js/select2.min.js"></script>
|
|
|
|
<script>
|
|
// Función para cargar los idiomas activos
|
|
function loadActiveLanguages() {
|
|
return fetch('/shared/languages/get_active.php')
|
|
.then(response => response.json())
|
|
.then(data => {
|
|
if (data.success && data.languages) {
|
|
return data.languages;
|
|
}
|
|
return [];
|
|
})
|
|
.catch(error => {
|
|
console.error('Error cargando idiomas:', error);
|
|
return [];
|
|
});
|
|
}
|
|
|
|
// Función para crear botones de traducción
|
|
function createTranslationButtons(languages) {
|
|
const container = $('#translation-buttons');
|
|
container.empty();
|
|
|
|
languages.forEach(lang => {
|
|
if (lang.codigo !== 'es') { // No mostramos el botón para español (idioma original)
|
|
const button = $(`
|
|
<button type="button" class="btn btn-sm btn-outline-secondary translate-btn"
|
|
data-lang="${lang.codigo}"
|
|
title="Traducir a ${lang.nombre}">
|
|
<span class="flag-icon flag-icon-${lang.bandera || 'globe'}"></span>
|
|
</button>
|
|
`);
|
|
container.append(button);
|
|
}
|
|
});
|
|
|
|
// Manejador de eventos para los botones de traducción
|
|
$('.translate-btn').on('click', async function() {
|
|
const targetLang = $(this).data('lang');
|
|
const content = $('#contenido').val();
|
|
|
|
if (!content) {
|
|
alert('Por favor, ingrese un mensaje para traducir.');
|
|
return;
|
|
}
|
|
|
|
try {
|
|
const response = await fetch('/shared/translations/translate.php', {
|
|
method: 'POST',
|
|
headers: {
|
|
'Content-Type': 'application/json',
|
|
},
|
|
body: JSON.stringify({
|
|
text: content,
|
|
target: targetLang,
|
|
source: 'es' // Asumimos que el texto original está en español
|
|
})
|
|
});
|
|
|
|
const data = await response.json();
|
|
|
|
if (data.success) {
|
|
// Agregar la traducción al final del contenido
|
|
const translatedText = `\n\n--- Traducción a ${targetLang.toUpperCase()} ---\n${data.translatedText}`;
|
|
$('#contenido').val(content + translatedText);
|
|
|
|
// Eliminar el botón de traducción
|
|
$(this).remove();
|
|
} else {
|
|
alert('Error al traducir: ' + (data.error || 'Error desconocido'));
|
|
}
|
|
} catch (error) {
|
|
console.error('Error al traducir:', error);
|
|
alert('Error al conectar con el servicio de traducción.');
|
|
}
|
|
});
|
|
}
|
|
|
|
// Cargar los botones de traducción al iniciar
|
|
$(document).ready(function() {
|
|
loadActiveLanguages().then(languages => {
|
|
createTranslationButtons(languages);
|
|
});
|
|
$('#contenido').summernote({
|
|
height: 300,
|
|
toolbar: [
|
|
['style', ['style']],
|
|
['font', ['bold', 'underline', 'clear']],
|
|
['color', ['color']],
|
|
['para', ['ul', 'ol', 'paragraph']],
|
|
['insert', ['link']],
|
|
['view', ['fullscreen', 'codeview', 'help']]
|
|
]
|
|
});
|
|
|
|
// Inicializar Select2 para selección múltiple
|
|
$('#destinatario_select').select2({
|
|
placeholder: "-- Seleccionar Destinatarios Guardados --",
|
|
allowClear: true // Permite deseleccionar
|
|
});
|
|
|
|
// Sincronizar select con input manual
|
|
$('#destinatario_select').on('change', function() {
|
|
const selectedIds = $(this).val(); // Array de IDs del select2
|
|
const manualIds = $('#destinatario_manual').val().split(',').map(id => id.trim()).filter(id => id !== '');
|
|
|
|
// Combinar y eliminar duplicados
|
|
const combinedIds = [...new Set([...selectedIds, ...manualIds])];
|
|
|
|
// Actualizar el campo manual para reflejar todas las selecciones y entradas manuales
|
|
$('#destinatario_manual').val(combinedIds.join(', '));
|
|
});
|
|
|
|
$('#destinatario_manual').on('input', function() {
|
|
const manualIds = $(this).val().split(',').map(id => id.trim()).filter(id => id !== '');
|
|
const selectedIds = $('#destinatario_select').val(); // IDs del select2
|
|
|
|
// Asegurarse de que el select2 no se deseleccione si se añade manualmente
|
|
// Esto es complejo si se quiere mantener el estado exacto en ambos sentidos.
|
|
// Para simplificar, solo aseguramos que el input manual tenga todos los IDs.
|
|
const combinedIds = [...new Set([...manualIds, ...selectedIds])];
|
|
// Intentar seleccionar en select2 lo que está en manual si existe
|
|
$('#destinatario_select').val(manualIds).trigger('change');
|
|
});
|
|
});
|
|
|
|
function loadTemplate(id) {
|
|
if (!id) return;
|
|
const template = templates.find(t => t.id == id);
|
|
if (template) {
|
|
if (confirm('¿Reemplazar el contenido actual con la plantilla?')) {
|
|
$('#contenido').summernote('code', template.contenido);
|
|
}
|
|
}
|
|
}
|
|
|
|
function openGallery() {
|
|
$('#galleryModal').show();
|
|
loadGalleryImages();
|
|
}
|
|
|
|
function closeGallery() {
|
|
$('#galleryModal').hide();
|
|
}
|
|
|
|
async function loadGalleryImages() {
|
|
try {
|
|
const response = await fetch('/gallery/api/list.php');
|
|
const data = await response.json();
|
|
|
|
const grid = document.getElementById('galleryGrid');
|
|
if (data.success && data.images.length > 0) {
|
|
grid.innerHTML = data.images.map(img => `
|
|
<div class="gallery-item" onclick="insertImage('${img.url}')">
|
|
<img src="${img.url_thumbnail}" alt="${img.nombre_original}">
|
|
</div>
|
|
`).join('');
|
|
} else {
|
|
grid.innerHTML = '<p>No hay imágenes.</p>';
|
|
}
|
|
} catch (e) {
|
|
console.error(e);
|
|
}
|
|
}
|
|
|
|
function insertImage(url) {
|
|
const fullUrl = window.location.origin + url;
|
|
$('#contenido').summernote('insertImage', fullUrl);
|
|
closeGallery();
|
|
}
|
|
|
|
function previewMessage() {
|
|
const content = $('#contenido').summernote('code');
|
|
const win = window.open('', 'Preview', 'width=800,height=600');
|
|
win.document.write('<div style="padding:20px;font-family:sans-serif;">' + content + '</div>');
|
|
}
|
|
|
|
// Cerrar modal click fuera
|
|
window.onclick = function(event) {
|
|
if (event.target == document.getElementById('galleryModal')) {
|
|
closeGallery();
|
|
}
|
|
}
|
|
|
|
// Lógica para mostrar/ocultar campos de programación/recurrencia
|
|
const sendTypeRadios = document.querySelectorAll('input[name="send_type"]');
|
|
const scheduledOptions = document.getElementById('scheduled_options');
|
|
const recurringOptions = document.getElementById('recurring_options');
|
|
const recurrenceFrequency = document.getElementById('recurrence_frequency');
|
|
const weeklyOptions = document.getElementById('weekly_options');
|
|
const monthlyOptions = document.getElementById('monthly_options');
|
|
|
|
function toggleSendTypeOptions() {
|
|
const selectedSendType = document.querySelector('input[name="send_type"]:checked').value;
|
|
scheduledOptions.style.display = 'none';
|
|
recurringOptions.style.display = 'none';
|
|
|
|
if (selectedSendType === 'programado') {
|
|
scheduledOptions.style.display = 'block';
|
|
} else if (selectedSendType === 'recurrente') {
|
|
recurringOptions.style.display = 'block';
|
|
toggleRecurringDetails(); // Mostrar detalles específicos al cargar
|
|
}
|
|
}
|
|
|
|
function toggleRecurringDetails() {
|
|
const selectedFrequency = recurrenceFrequency.value;
|
|
weeklyOptions.style.display = 'none';
|
|
monthlyOptions.style.display = 'none';
|
|
|
|
if (selectedFrequency === 'semanal') {
|
|
weeklyOptions.style.display = 'block';
|
|
} else if (selectedFrequency === 'mensual') {
|
|
monthlyOptions.style.display = 'block';
|
|
}
|
|
}
|
|
|
|
// Inicializar al cargar la página
|
|
toggleSendTypeOptions();
|
|
|
|
// Escuchar cambios en los tipos de envío
|
|
sendTypeRadios.forEach(radio => {
|
|
radio.addEventListener('change', toggleSendTypeOptions);
|
|
});
|
|
|
|
// Escuchar cambios en la frecuencia de recurrencia
|
|
recurrenceFrequency.addEventListener('change', toggleRecurringDetails);
|
|
|
|
$('#messageForm').on('submit', async function(e) {
|
|
e.preventDefault();
|
|
|
|
const selectedDestinatarios = $('#destinatario_select').val() || []; // Array de IDs del select2
|
|
const manualDestinatarios = $('#destinatario_manual').val()
|
|
.split(',')
|
|
.map(id => id.trim())
|
|
.filter(id => id !== '');
|
|
|
|
// Combinar y eliminar duplicados de ambos orígenes
|
|
const destinatarios = [...new Set([...selectedDestinatarios, ...manualDestinatarios])];
|
|
|
|
const contenido = $('#contenido').summernote('code');
|
|
const sendType = document.querySelector('input[name="send_type"]:checked').value;
|
|
let scheduleData = {};
|
|
|
|
if (destinatarios.length === 0 || !contenido) {
|
|
alert('Por favor selecciona al menos un destinatario y escribe un mensaje.');
|
|
return;
|
|
}
|
|
|
|
if (sendType === 'programado') {
|
|
const scheduleDatetime = $('#schedule_datetime').val();
|
|
if (!scheduleDatetime) {
|
|
alert('Por favor, selecciona la fecha y hora de envío programado.');
|
|
return;
|
|
}
|
|
scheduleData = {
|
|
fecha_envio: scheduleDatetime
|
|
};
|
|
} else if (sendType === 'recurrente') {
|
|
const recurrenceFrequencyVal = $('#recurrence_frequency').val();
|
|
const recurrenceTime = $('#recurrence_time').val();
|
|
|
|
if (!recurrenceFrequencyVal || !recurrenceTime) {
|
|
alert('Por favor, completa la frecuencia y hora de envío recurrente.');
|
|
return;
|
|
}
|
|
|
|
scheduleData = {
|
|
frecuencia: recurrenceFrequencyVal,
|
|
hora_envio: recurrenceTime
|
|
};
|
|
|
|
if (recurrenceFrequencyVal === 'semanal') {
|
|
const dayOfWeek = $('#recurrence_day_of_week').val();
|
|
if (!dayOfWeek) {
|
|
alert('Por favor, selecciona el día de la semana para el envío recurrente.');
|
|
return;
|
|
}
|
|
scheduleData.dia_semana = dayOfWeek;
|
|
} else if (recurrenceFrequencyVal === 'mensual') {
|
|
const dayOfMonth = $('#recurrence_day_of_month').val();
|
|
if (!dayOfMonth || dayOfMonth < 1 || dayOfMonth > 31) {
|
|
alert('Por favor, ingresa un día válido del mes (1-31) para el envío recurrente.');
|
|
return;
|
|
}
|
|
scheduleData.dia_mes = dayOfMonth;
|
|
}
|
|
}
|
|
|
|
if (!confirm(`¿Enviar mensaje (${sendType}) a ${destinatarios.length} destinatario(s)?`)) return;
|
|
|
|
$('#btnEnviar').prop('disabled', true).html('<i class="fas fa-spinner fa-spin"></i> Enviando...');
|
|
|
|
try {
|
|
const response = await fetch('/discord/api/messages/send.php', {
|
|
method: 'POST',
|
|
headers: { 'Content-Type': 'application/json' },
|
|
body: JSON.stringify({
|
|
destinatario_id: destinatarios, // Ahora puede ser un array
|
|
contenido: contenido,
|
|
tipo_envio: sendType,
|
|
...scheduleData // Añadir datos de programación/recurrencia
|
|
})
|
|
});
|
|
|
|
const result = await response.json();
|
|
|
|
if (result.success) {
|
|
alert('¡Mensaje enviado correctamente!');
|
|
window.location.href = '/discord/views/messages/sent.php';
|
|
} else {
|
|
alert('Error: ' + (result.error || 'Error desconocido'));
|
|
}
|
|
} catch (error) {
|
|
console.error(error);
|
|
alert('Error de conexión');
|
|
} finally {
|
|
$('#btnEnviar').prop('disabled', false).html('<i class="fas fa-paper-plane"></i> Enviar Ahora');
|
|
}
|
|
});
|
|
|
|
</script>
|
|
</body>
|
|
</html>
|