Files
sistema_funcionando_lastwar/create_message.php

621 lines
28 KiB
PHP
Executable File

<?php
require_once __DIR__ . '/includes/session_check.php';
require_once __DIR__ . '/includes/db.php';
// Fetch all recipients and group by platform
$recipients_by_platform = ['discord' => ['channels' => [], 'users' => []], 'telegram' => ['channels' => [], 'users' => []]];
try {
$stmt = $pdo->query("SELECT id, name, type, platform FROM recipients ORDER BY platform, type, name ASC");
while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
if (isset($recipients_by_platform[$row['platform']])) {
if ($row['type'] === 'channel') {
$recipients_by_platform[$row['platform']]['channels'][] = $row;
} else {
$recipients_by_platform[$row['platform']]['users'][] = $row;
}
}
}
} catch (PDOException $e) {
die("Error: No se pudieron cargar los destinatarios: " . $e->getMessage());
}
// Fetch recurrent message templates
$templates = [];
try {
$stmt = $pdo->query("SELECT id, name, message_content FROM recurrent_messages ORDER BY name ASC");
$templates = $stmt->fetchAll(PDO::FETCH_ASSOC);
} catch (PDOException $e) {
die("Error: No se pudieron cargar las plantillas de mensajes recurrentes.");
}
// Initialize variables
$isEditing = false;
$scheduleId = null;
$pageTitle = 'Crear Notificación';
$submitButtonText = 'Guardar y Enviar';
$submitButtonIcon = 'bi-send-fill';
$submitAction = 'send';
$platform = 'discord'; // Default platform
$reuseContent = '';
$recipientId = '';
$recipientType = 'channel';
$scheduleType = 'now';
$recurringDays = [];
// Set default times in Mexico City timezone
$timezone = new DateTimeZone('America/Mexico_City');
$now = new DateTime('now', $timezone);
$recurringTime = $now->format('H:i');
$scheduleDateTime = $now->format('Y-m-d\TH:i');
// Check for reuse action from sent_messages.php
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['action']) && $_POST['action'] === 'reuse') {
$reuseContent = $_POST['messageContent'] ?? '';
$recipientId = $_POST['recipientId'] ?? '';
$recipientType = $_POST['recipientType'] ?? 'channel';
// Set schedule to default for a new message
$scheduleType = 'now';
// Set default schedule time to current time in Mexico City timezone
$timezone = new DateTimeZone('America/Mexico_City');
$now = new DateTime('now', $timezone);
$scheduleDateTime = $now->format('Y-m-d\TH:i');
$recurringDays = [];
$recurringTime = $now->format('H:i');
}
// Check for edit action
if (isset($_GET['action']) && $_GET['action'] === 'edit' && isset($_GET['schedule_id'])) {
$isEditing = true;
$scheduleId = $_GET['schedule_id'];
$pageTitle = 'Editar Notificación';
$submitButtonText = 'Actualizar Mensaje';
$submitButtonIcon = 'bi-pencil-square';
$submitAction = 'update';
$stmt = $pdo->prepare(
"SELECT
s.recipient_id,
s.send_time,
s.is_recurring,
s.recurring_days,
s.recurring_time,
m.content,
r.type as recipient_type,
r.platform
FROM schedules s
JOIN messages m ON s.message_id = m.id
JOIN recipients r ON s.recipient_id = r.id
WHERE s.id = ?"
);
$stmt->execute([$scheduleId]);
$message_data = $stmt->fetch(PDO::FETCH_ASSOC);
if ($message_data) {
$reuseContent = $message_data['content'];
$recipientId = $message_data['recipient_id'];
$recipientType = $message_data['recipient_type'];
$platform = $message_data['platform'];
if ($message_data['is_recurring']) {
$scheduleType = 'recurring';
$recurringDays = !empty($message_data['recurring_days']) ? explode(',', $message_data['recurring_days']) : [];
$recurringTime = substr($message_data['recurring_time'], 0, 5);
} else {
$scheduleType = 'later';
if ($message_data['send_time']) {
$scheduleDateTime = date('Y-m-d\TH:i', strtotime($message_data['send_time']));
}
}
} else {
die("Error: Mensaje programado no encontrado.");
}
}
require_once __DIR__ . '/templates/header.php';
?>
<!-- Summernote CSS -->
<link href="<?php echo asset('css/summernote-bs5.min.css'); ?>" rel="stylesheet">
<div class="container-fluid">
<h1 data-translate="true" class="mt-4" ><?php echo $pageTitle; ?></h1>
<form action="includes/message_handler.php" method="POST" id="createMessageForm">
<?php if ($isEditing): ?>
<input type="hidden" name="schedule_id" value="<?php echo htmlspecialchars($scheduleId); ?>">
<?php endif; ?>
<!-- Template Selection -->
<div class="mb-3">
<label for="templateSelector" class="form-label" data-translate="true">Cargar desde Plantilla</label>
<select class="form-select" id="templateSelector">
<option value="" data-translate="true">-- Selecciona una plantilla --</option>
<?php foreach ($templates as $template): ?>
<option value="<?php echo $template['id']; ?>" data-content="<?php echo htmlspecialchars($template['message_content']); ?>">
<?php echo htmlspecialchars($template['name']); ?>
</option>
<?php endforeach; ?>
</select>
</div>
<!-- Message Content -->
<div class="mb-3">
<label data-translate="true" for="messageContent" class="form-label">Contenido del Mensaje</label>
<textarea id="messageContent" name="messageContent" class="form-control"><?php echo htmlspecialchars($reuseContent); ?></textarea>
<div id="characterCount" class="text-muted text-end mt-1">0 caracteres</div>
</div>
<!-- Translation Option -->
<div class="mb-3 form-check">
<input type="checkbox" class="form-check-input" id="enableTranslation" name="enableTranslation" value="true" checked>
<label class="form-check-label" for="enableTranslation" data-translate="true">Habilitar traducción automática (Español/Portugués)</label>
</div>
<!-- Platform Selection -->
<div class="mb-3">
<label data-translate="true" class="form-label">Plataforma</label>
<div>
<input type="radio" id="platformDiscord" name="platform" value="discord" <?php echo ($platform === 'discord') ? 'checked' : ''; ?>>
<label for="platformDiscord" class="me-3" data-translate="true">Discord</label>
<input type="radio" id="platformTelegram" name="platform" value="telegram" <?php echo ($platform === 'telegram') ? 'checked' : ''; ?>>
<label for="platformTelegram" data-translate="true">Telegram</label>
</div>
</div>
<!-- Recipient Selection -->
<div class="mb-3">
<label data-translate="true" class="form-label">Tipo de Destinatario</label>
<div>
<input type="radio" id="recipientTypeChannel" name="recipientType" value="channel" <?php echo $recipientType === 'channel' ? 'checked' : ''; ?>>
<label for="recipientTypeChannel" class="me-3" data-translate="true">Canal</label>
<input type="radio" id="recipientTypeUser" name="recipientType" value="user" <?php echo $recipientType === 'user' ? 'checked' : ''; ?>>
<label for="recipientTypeUser" data-translate="true">Usuario</label>
</div>
</div>
<!-- Channel/User Selection -->
<div class="mb-3">
<label data-translate="true" for="recipientId" class="form-label">Seleccionar Destinatario</label>
<div id="discord-recipients">
<select class="form-select" id="recipientId_discord_channel" name="recipientId_discord_channel">
<option value="" data-translate="true">Selecciona un canal de Discord</option>
<?php foreach ($recipients_by_platform['discord']['channels'] as $channel): ?>
<option value="<?php echo $channel['id']; ?>"><?php echo htmlspecialchars($channel['name']); ?></option>
<?php endforeach; ?>
</select>
<select class="form-select d-none" id="recipientId_discord_user" name="recipientId_discord_user[]" multiple>
<option value="" data-translate="true">Selecciona un usuario de Discord</option>
<?php foreach ($recipients_by_platform['discord']['users'] as $user): ?>
<option value="<?php echo $user['id']; ?>"><?php echo htmlspecialchars($user['name']); ?></option>
<?php endforeach; ?>
</select>
</div>
<div id="telegram-recipients" class="d-none">
<select class="form-select" id="recipientId_telegram_channel" name="recipientId_telegram_channel">
<option value="" data-translate="true">Selecciona un canal de Telegram</option>
<?php foreach ($recipients_by_platform['telegram']['channels'] as $channel): ?>
<option value="<?php echo $channel['id']; ?>"><?php echo htmlspecialchars($channel['name']); ?></option>
<?php endforeach; ?>
</select>
<select class="form-select d-none" id="recipientId_telegram_user" name="recipientId_telegram_user[]" multiple>
<option value="" data-translate="true" data-translate="true">Selecciona un usuario de Telegram</option>
<?php foreach ($recipients_by_platform['telegram']['users'] as $user): ?>
<option value="<?php echo $user['id']; ?>"><?php echo htmlspecialchars($user['name']); ?></option>
<?php endforeach; ?>
</select>
</div>
</div>
<!-- Schedule Options -->
<div class="mb-3">
<label class="form-label" data-translate="true">Programación</label>
<div class="form-check">
<input class="form-check-input" type="radio" name="scheduleType" id="scheduleNow" value="now" <?php echo $scheduleType === 'now' ? 'checked' : ''; ?>>
<label class="form-check-label" for="scheduleNow">
<span data-translate="true">Enviar ahora</span>
</label>
</div>
<div class="form-check">
<input class="form-check-input" type="radio" name="scheduleType" id="scheduleLater" value="later" <?php echo $scheduleType === 'later' ? 'checked' : ''; ?>>
<label class="form-check-label" for="scheduleLater">
<span data-translate="true">Programar para más tarde</span>
</label>
</div>
<div class="form-check">
<input class="form-check-input" type="radio" name="scheduleType" id="scheduleRecurring" value="recurring" <?php echo $scheduleType === 'recurring' ? 'checked' : ''; ?>>
<label class="form-check-label" for="scheduleRecurring">
<span data-translate="true">Programación recurrente</span>
</label>
</div>
</div>
<!-- Schedule Later Options -->
<div class="mb-3" id="scheduleLaterOptions" style="display: <?php echo $scheduleType === 'later' ? 'block' : 'none'; ?>;">
<label for="scheduleDateTime" class="form-label" data-translate="true">Fecha y Hora de Envío</label>
<input type="datetime-local" class="form-control" id="scheduleDateTime" name="scheduleDateTime"
min="<?php echo date('Y-m-d\TH:i'); ?>"
value="<?php echo $scheduleDateTime; ?>">
</div>
<!-- Recurring Schedule Options -->
<div class="mb-3" id="recurringOptions" style="display: <?php echo $scheduleType === 'recurring' ? 'block' : 'none'; ?>;">
<div class="mb-2">
<label class="form-label" data-translate="true">Días de la Semana</label>
<div class="d-flex flex-wrap gap-3">
<?php
$days = [
['value' => '1', 'label' => '<span data-translate="true">Lun</span>'],
['value' => '2', 'label' => '<span data-translate="true">Mar</span>'],
['value' => '3', 'label' => '<span data-translate="true">Mié</span>'],
['value' => '4', 'label' => '<span data-translate="true">Jue</span>'],
['value' => '5', 'label' => '<span data-translate="true">Vie</span>'],
['value' => '6', 'label' => '<span data-translate="true">Sáb</span>'],
['value' => '0', 'label' => '<span data-translate="true">Dom</span>']
];
foreach ($days as $day):
$isChecked = in_array($day['value'], $recurringDays) ? 'checked' : '';
?>
<div class="form-check">
<input class="form-check-input day-checkbox" type="checkbox"
name="recurringDays[]" value="<?php echo $day['value']; ?>"
id="day<?php echo $day['value']; ?>" <?php echo $isChecked; ?>>
<label class="form-check-label" for="day<?php echo $day['value']; ?>">
<?php echo $day['label']; ?>
</label>
</div>
<?php endforeach; ?>
</div>
</div>
<div class="mb-2">
<label for="recurringTime" class="form-label" data-translate="true">Hora de Envío (cada día seleccionado)</label>
<input type="time" class="form-control" id="recurringTime" name="recurringTime"
value="<?php echo $recurringTime; ?>">
</div>
</div>
<!-- Submit Button -->
<button type="submit" value="<?php echo $submitAction; ?>" class="btn btn-success">
<i class="bi <?php echo $submitButtonIcon; ?> me-1"></i> <?php echo $submitButtonText; ?>
</button>
</form>
</div>
<?php require_once __DIR__ . '/templates/footer.php'; ?>
<!-- Gallery Modal -->
<div class="modal fade" id="galleryModal" tabindex="-1" aria-labelledby="galleryModalLabel" aria-hidden="true">
<div class="modal-dialog modal-xl modal-dialog-scrollable">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="galleryModalLabel" data-translate="true">Galería de Imágenes</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
<div class="row">
<?php
$gallery_path = __DIR__ . '/galeria';
$files = array_diff(scandir($gallery_path), array('.', '..'));
if (empty($files)) {
echo '<p class="text-center text-muted" data-translate="true">No hay imágenes en la galería.</p>';
} else {
foreach ($files as $file) {
if (is_file($gallery_path . '/' . $file)) {
echo '<div class="col-lg-3 col-md-4 col-sm-6 mb-4 text-center"><img src="' . site_url('galeria/' . $file) . '" class="img-fluid img-thumbnail gallery-item" style="cursor:pointer;" alt="' . htmlspecialchars($file) . '"><p class="small text-muted mt-1">' . htmlspecialchars($file) . '</p></div>';
}
}
}
?>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Cerrar</button>
<button type="button" class="btn btn-primary" id="insertImageFromGallery">Insertar Imagen</button>
</div>
</div>
</div>
</div>
<script>
$(document).ready(function() {
// Custom Gallery Button
var GalleryButton = function (context) {
var ui = $.summernote.ui;
var button = ui.button({
contents: '<i class="bi bi-images"></i> Galería',
tooltip: 'Insertar imagen desde la galería',
click: function () {
$('#galleryModal').modal('show');
}
});
return button.render();
}
// Initialize Summernote
$('#messageContent').summernote({
placeholder: 'Escribe tu mensaje aquí...',
tabsize: 2,
height: 300,
toolbar: [
['style', ['style']],
['font', ['bold', 'underline', 'clear']],
['color', ['color']],
['para', ['ul', 'ol', 'paragraph']],
['table', ['table']],
['insert', ['picture']],
['view', ['codeview']],
['mybutton', ['gallery']]
],
buttons: {
gallery: GalleryButton
},
popover: {
image: [
['image', ['resizeFull', 'resizeHalf', 'resizeQuarter', 'resizeNone']],
['float', ['floatLeft', 'floatRight', 'floatNone']],
['remove', ['removeMedia']]
],
link: [
['link', ['linkDialogShow', 'unlink']]
],
table: [
['add', ['addRowDown', 'addRowUp', 'addColLeft', 'addColRight']],
['delete', ['deleteRow', 'deleteCol', 'deleteTable']],
],
air: [
['color', ['color']],
['font', ['bold', 'underline', 'clear']],
['para', ['ul', 'paragraph']],
['table', ['table']],
['insert', ['link', 'picture']]
]
},
callbacks: {
onImageUpload: function(files) {
var editor = $(this);
var data = new FormData();
data.append("file", files[0]);
$.ajax({
url: 'upload_editor_image.php',
method: 'POST',
data: data,
processData: false,
contentType: false,
success: function(response) {
if (response.url) {
editor.summernote('insertImage', response.url);
} else {
alert(response.error || 'Error al subir la imagen.');
}
},
error: function() {
alert('Error: No se pudo comunicar con el servidor para subir la imagen.');
}
});
},
onPaste: function(e) {
var bufferText = ((e.originalEvent || e).clipboardData || window.clipboardData).getData('Text');
e.preventDefault();
// Firefox fix
setTimeout(function () {
document.execCommand('insertText', false, bufferText);
}, 10);
},
onKeyup: function(e) {
updateCharacterCount();
},
onInit: function() {
updateCharacterCount();
}
}
});
// Handle template selection
$('#templateSelector').change(function() {
var selectedOption = $(this).find('option:selected');
var content = selectedOption.data('content');
if (content) {
$('#messageContent').summernote('code', content);
} else {
$('#messageContent').summernote('code', ''); // Clear if no content
}
updateCharacterCount(); // Update count after template load
});
// Function to update character count
function updateCharacterCount() {
// Get the text directly from the editable area of Summernote
var text = $('#messageContent').next('.note-editor').find('.note-editable').text();
var count = text.length;
console.log("Summernote text (from note-editable):", text);
console.log("Character count:", count);
$('#characterCount').text(count + ' caracteres');
}
// Handle image selection in modal
$(document).on('click', '.gallery-item', function() {
$(this).toggleClass('border-primary');
});
// Handle image insertion
$('#insertImageFromGallery').click(function() {
$('.gallery-item.border-primary').each(function(){
var imageUrl = $(this).attr('src');
$('#messageContent').summernote('insertImage', imageUrl);
});
$('#galleryModal').modal('hide');
$('.gallery-item').removeClass('border-primary');
});
// Toggle between channel and user selection
const recipientTypeChannel = document.getElementById('recipientTypeChannel');
const recipientTypeUser = document.getElementById('recipientTypeUser');
const platformDiscord = document.getElementById('platformDiscord');
const platformTelegram = document.getElementById('platformTelegram');
const discordRecipients = document.getElementById('discord-recipients');
const telegramRecipients = document.getElementById('telegram-recipients');
const discordChannelSelect = document.getElementById('recipientId_discord_channel');
const discordUserSelect = document.getElementById('recipientId_discord_user');
const telegramChannelSelect = document.getElementById('recipientId_telegram_channel');
const telegramUserSelect = document.getElementById('recipientId_telegram_user');
function updateRecipientVisibility() {
const isDiscord = platformDiscord.checked;
const isTelegram = platformTelegram.checked;
const isChannel = recipientTypeChannel.checked;
const isUser = recipientTypeUser.checked;
// Show/hide platform containers
discordRecipients.classList.toggle('d-none', !isDiscord);
telegramRecipients.classList.toggle('d-none', !isTelegram);
if (isDiscord) {
// Handle Discord recipients
discordChannelSelect.classList.toggle('d-none', !isChannel);
discordChannelSelect.disabled = !isChannel;
discordChannelSelect.required = isChannel;
discordUserSelect.classList.toggle('d-none', !isUser);
discordUserSelect.disabled = !isUser;
discordUserSelect.required = isUser;
// Disable Telegram selects
telegramChannelSelect.disabled = true;
telegramUserSelect.disabled = true;
} else if (isTelegram) {
// Handle Telegram recipients
telegramChannelSelect.classList.toggle('d-none', !isChannel);
telegramChannelSelect.disabled = !isChannel;
telegramChannelSelect.required = isChannel;
telegramUserSelect.classList.toggle('d-none', !isUser);
telegramUserSelect.disabled = !isUser;
telegramUserSelect.required = isUser;
// Disable Discord selects
discordChannelSelect.disabled = true;
discordUserSelect.disabled = true;
}
}
platformDiscord.addEventListener('change', updateRecipientVisibility);
platformTelegram.addEventListener('change', updateRecipientVisibility);
recipientTypeChannel.addEventListener('change', updateRecipientVisibility);
recipientTypeUser.addEventListener('change', updateRecipientVisibility);
// Initial call to set the correct state
updateRecipientVisibility();
// Toggle schedule options
const scheduleNow = document.getElementById('scheduleNow');
const scheduleLater = document.getElementById('scheduleLater');
const scheduleRecurring = document.getElementById('scheduleRecurring');
const scheduleLaterOptions = document.getElementById('scheduleLaterOptions');
const recurringOptions = document.getElementById('recurringOptions');
function updateScheduleOptions() {
const scheduleLaterOptions = document.getElementById('scheduleLaterOptions');
const scheduleDateTime = document.getElementById('scheduleDateTime');
const recurringOptions = document.getElementById('recurringOptions');
const recurringTime = document.getElementById('recurringTime');
const recurringDays = document.querySelectorAll('.day-checkbox');
if (scheduleNow.checked) {
scheduleLaterOptions.style.display = 'none';
scheduleDateTime.disabled = true;
recurringOptions.style.display = 'none';
recurringTime.disabled = true;
recurringDays.forEach(day => day.disabled = true);
} else if (scheduleLater.checked) {
scheduleLaterOptions.style.display = 'block';
scheduleDateTime.disabled = false;
recurringOptions.style.display = 'none';
recurringTime.disabled = true;
recurringDays.forEach(day => day.disabled = true);
} else if (scheduleRecurring.checked) {
scheduleLaterOptions.style.display = 'none';
scheduleDateTime.disabled = true;
recurringOptions.style.display = 'block';
recurringTime.disabled = false;
recurringDays.forEach(day => day.disabled = false);
}
}
if (scheduleNow && scheduleLater && scheduleRecurring) {
scheduleNow.addEventListener('change', updateScheduleOptions);
scheduleLater.addEventListener('change', updateScheduleOptions);
scheduleRecurring.addEventListener('change', updateScheduleOptions);
updateScheduleOptions();
}
// Form validation
const form = document.getElementById('createMessageForm');
if (form) {
form.addEventListener('submit', function(e) {
// Prevent default submission to perform validation and data preparation
e.preventDefault();
// 1. Validate Summernote content
if ($('#messageContent').summernote('isEmpty')) {
alert('El contenido del mensaje no puede estar vacío.');
return false;
}
// Get message content from Summernote
let messageContent = $('#messageContent').summernote('code');
// Check if translation is enabled
const enableTranslationCheckbox = document.getElementById('enableTranslation');
if (enableTranslationCheckbox && enableTranslationCheckbox.checked) {
// Add data-translate attribute to the message content
// This will be picked up by process_queue.php
messageContent = '<div data-translate="true">' + messageContent + '</div>';
}
// Add hidden field for messageContent
$('<input>').attr({ type: 'hidden', name: 'messageContent', value: messageContent }).appendTo(form);
let channelIds = [];
let userIds = [];
const isDiscord = platformDiscord.checked;
const isTelegram = platformTelegram.checked;
const isChannel = recipientTypeChannel.checked;
const isUser = recipientTypeUser.checked;
if (isDiscord) {
if (isChannel) {
channelIds.push(discordChannelSelect.value);
} else if (isUser) {
userIds = $(discordUserSelect).val() || [];
}
} else if (isTelegram) {
if (isChannel) {
channelIds.push(telegramChannelSelect.value);
} else if (isUser) {
userIds = $(telegramUserSelect).val() || [];
}
}
if (channelIds.length === 0 && userIds.length === 0) {
alert('Por favor selecciona al menos un destinatario.');
return false;
}
// Add hidden fields to the form
$('<input>').attr({ type: 'hidden', name: 'channelIds', value: JSON.stringify(channelIds) }).appendTo(form);
$('<input>').attr({ type: 'hidden', name: 'userIds', value: JSON.stringify(userIds) }).appendTo(form);
// If all validation passes, submit the form
form.submit();
});
}
});
</script>