Initial commit - Last War messaging system
This commit is contained in:
421
create_message.php
Executable file
421
create_message.php
Executable file
@@ -0,0 +1,421 @@
|
||||
<?php
|
||||
require_once __DIR__ . '/includes/db.php';
|
||||
require_once __DIR__ . '/includes/session_check.php';
|
||||
checkSession();
|
||||
require_once __DIR__ . '/includes/message_handler.php';
|
||||
require_once __DIR__ . '/includes/schedule_helpers.php';
|
||||
require_once __DIR__ . '/common/helpers/sender_factory.php';
|
||||
require_once __DIR__ . '/common/helpers/converter_factory.php';
|
||||
|
||||
function getTranslationButtons(PDO $pdo, string $text): array
|
||||
{
|
||||
$stmt = $pdo->query("SELECT language_code, flag_emoji FROM supported_languages WHERE is_active = 1");
|
||||
$languages = $stmt->fetchAll();
|
||||
|
||||
if (count($languages) <= 1) {
|
||||
return [];
|
||||
}
|
||||
|
||||
return [
|
||||
'telegram' => buildTelegramTranslationButtons($pdo, $languages, $text),
|
||||
'discord' => buildDiscordTranslationButtons($languages, $text)
|
||||
];
|
||||
}
|
||||
|
||||
function buildTelegramTranslationButtons(PDO $pdo, array $languages, string $text): array
|
||||
{
|
||||
if (count($languages) <= 1) {
|
||||
return [];
|
||||
}
|
||||
|
||||
// Guardar texto en la base de datos con hash consistente
|
||||
$textHash = md5($text);
|
||||
$stmt = $pdo->prepare("INSERT INTO translation_cache (text_hash, original_text) VALUES (?, ?) ON DUPLICATE KEY UPDATE original_text = VALUES(original_text)");
|
||||
$stmt->execute([$textHash, $text]);
|
||||
|
||||
$buttons = [];
|
||||
|
||||
foreach ($languages as $lang) {
|
||||
$buttons[] = [
|
||||
'text' => $lang['flag_emoji'] . ' ' . strtoupper($lang['language_code']),
|
||||
'callback_data' => 'translate:' . $lang['language_code'] . ':' . $textHash
|
||||
];
|
||||
}
|
||||
|
||||
return [
|
||||
'inline_keyboard' => array_chunk($buttons, 3)
|
||||
];
|
||||
}
|
||||
|
||||
function buildDiscordTranslationButtons(array $languages, string $text): array
|
||||
{
|
||||
$buttons = [];
|
||||
|
||||
$textHash = md5($text);
|
||||
|
||||
foreach ($languages as $lang) {
|
||||
$buttons[] = [
|
||||
'label' => $lang['flag_emoji'] . ' ' . strtoupper($lang['language_code']),
|
||||
'custom_id' => 'translate_' . $lang['language_code'] . ':' . $textHash,
|
||||
'style' => 1
|
||||
];
|
||||
}
|
||||
|
||||
return [
|
||||
[
|
||||
'type' => 1,
|
||||
'components' => array_slice($buttons, 0, 5)
|
||||
]
|
||||
];
|
||||
}
|
||||
|
||||
$pageTitle = 'Crear Mensaje - Sistema de Mensajería';
|
||||
|
||||
$recipients = [];
|
||||
$templates = [];
|
||||
$galleryImages = [];
|
||||
|
||||
try {
|
||||
$pdo = getDbConnection();
|
||||
|
||||
$stmt = $pdo->query("SELECT * FROM recipients ORDER BY platform, name");
|
||||
$recipients = $stmt->fetchAll();
|
||||
|
||||
$stmt = $pdo->query("SELECT * FROM recurrent_messages ORDER BY name");
|
||||
$templates = $stmt->fetchAll();
|
||||
|
||||
// Cargar imágenes de la galería
|
||||
$galleryPath = __DIR__ . '/galeria';
|
||||
if (is_dir($galleryPath)) {
|
||||
$files = scandir($galleryPath);
|
||||
foreach ($files as $file) {
|
||||
if (in_array(strtolower(pathinfo($file, PATHINFO_EXTENSION)), ['jpg', 'jpeg', 'png', 'gif', 'webp'])) {
|
||||
$galleryImages[] = $file;
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (Exception $e) {
|
||||
$error = $e->getMessage();
|
||||
}
|
||||
|
||||
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['action']) && $_POST['action'] === 'create') {
|
||||
$result = handleCreateMessage($_POST);
|
||||
|
||||
if ($result['success']) {
|
||||
// Si es "enviar ahora", procesar inmediatamente
|
||||
if ($_POST['send_type'] === 'now') {
|
||||
$scheduleId = $result['schedule_id'];
|
||||
|
||||
// Obtener datos del schedule
|
||||
$stmt = $pdo->prepare("
|
||||
SELECT s.*, m.content, r.platform_id, r.platform, r.name as recipient_name
|
||||
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]);
|
||||
$schedule = $stmt->fetch();
|
||||
|
||||
if ($schedule) {
|
||||
$stmt = $pdo->prepare("UPDATE schedules SET status = 'processing' WHERE id = ?");
|
||||
$stmt->execute([$schedule['id']]);
|
||||
|
||||
try {
|
||||
$sender = \Common\Helpers\SenderFactory::create($schedule['platform']);
|
||||
|
||||
// Obtener botones de traducción (convertir HTML a texto plano)
|
||||
$plainText = html_entity_decode(strip_tags($schedule['content']), ENT_QUOTES | ENT_HTML5, 'UTF-8');
|
||||
$plainText = preg_replace('/\s+/', ' ', $plainText);
|
||||
$translationButtons = getTranslationButtons($pdo, $plainText);
|
||||
|
||||
$segments = $sender->parseContent($schedule['content']);
|
||||
$messageCount = 0;
|
||||
|
||||
foreach ($segments as $segment) {
|
||||
if ($segment['type'] === 'text') {
|
||||
$textContent = \Common\Helpers\ConverterFactory::convert($schedule['platform'], $segment['content']);
|
||||
if (!empty(trim($textContent))) {
|
||||
// Agregar botones de traducción al último segmento de texto
|
||||
$buttons = null;
|
||||
if ($segment === end($segments)) {
|
||||
$buttons = $schedule['platform'] === 'telegram'
|
||||
? $translationButtons['telegram']
|
||||
: $translationButtons['discord'];
|
||||
}
|
||||
|
||||
if ($schedule['platform'] === 'telegram') {
|
||||
$sender->sendMessage($schedule['platform_id'], $textContent, $buttons);
|
||||
} else {
|
||||
$sender->sendMessage($schedule['platform_id'], $textContent, null, $buttons);
|
||||
}
|
||||
$messageCount++;
|
||||
}
|
||||
} elseif ($segment['type'] === 'image') {
|
||||
$imagePath = $segment['src'];
|
||||
$imgPath = parse_url($imagePath, PHP_URL_PATH) ?: $imagePath;
|
||||
|
||||
if (file_exists($imgPath)) {
|
||||
$sender->sendMessageWithAttachments($schedule['platform_id'], '', [$imgPath]);
|
||||
$messageCount++;
|
||||
} elseif (strpos($imagePath, 'http') === 0) {
|
||||
$embed = ['image' => ['url' => $imagePath]];
|
||||
$sender->sendMessage($schedule['platform_id'], '', $embed);
|
||||
$messageCount++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$stmt = $pdo->prepare("
|
||||
INSERT INTO sent_messages (schedule_id, recipient_id, platform_message_id, message_count, sent_at)
|
||||
VALUES (?, ?, '', ?, NOW())
|
||||
");
|
||||
$stmt->execute([$schedule['id'], $schedule['recipient_id'], $messageCount]);
|
||||
|
||||
$stmt = $pdo->prepare("UPDATE schedules SET status = 'sent', sent_at = NOW() WHERE id = ?");
|
||||
$stmt->execute([$schedule['id']]);
|
||||
|
||||
} catch (Exception $e) {
|
||||
$stmt = $pdo->prepare("UPDATE schedules SET status = 'failed', error_message = ? WHERE id = ?");
|
||||
$stmt->execute([$e->getMessage(), $schedule['id']]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
header('Location: scheduled_messages.php?success=1');
|
||||
exit;
|
||||
} else {
|
||||
$error = $result['error'];
|
||||
}
|
||||
}
|
||||
|
||||
require_once __DIR__ . '/templates/header.php';
|
||||
?>
|
||||
|
||||
<div class="d-flex justify-content-between align-items-center mb-4">
|
||||
<h2><i class="bi bi-plus-circle"></i> Crear Mensaje</h2>
|
||||
<div class="btn-group">
|
||||
<a href="preview_message.php" class="btn btn-outline-secondary" target="_blank">
|
||||
<i class="bi bi-eye"></i> Previsualizar
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<?php if (isset($error)): ?>
|
||||
<div class="alert alert-danger"><?= htmlspecialchars($error) ?></div>
|
||||
<?php endif; ?>
|
||||
|
||||
<form method="POST" id="messageForm">
|
||||
<input type="hidden" name="action" value="create">
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-8">
|
||||
<div class="card border-0 shadow-sm mb-4">
|
||||
<div class="card-header bg-white border-0">
|
||||
<h5 class="mb-0">Contenido del Mensaje</h5>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="mb-3">
|
||||
<label class="form-label">Plantilla (opcional)</label>
|
||||
<select class="form-select" id="templateSelect">
|
||||
<option value="">-- Seleccionar plantilla --</option>
|
||||
<?php foreach ($templates as $template): ?>
|
||||
<option value="<?= htmlspecialchars($template['message_content']) ?>">
|
||||
<?= htmlspecialchars($template['name']) ?>
|
||||
</option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<label class="form-label">Mensaje</label>
|
||||
<textarea name="content" id="messageContent" class="form-control" rows="12"></textarea>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-md-4">
|
||||
<div class="card border-0 shadow-sm mb-4">
|
||||
<div class="card-header bg-white border-0">
|
||||
<h5 class="mb-0">Destinatario</h5>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="mb-3">
|
||||
<label class="form-label">Plataforma</label>
|
||||
<select name="platform" id="platformSelect" class="form-select" required>
|
||||
<option value="">-- Seleccionar --</option>
|
||||
<option value="discord">Discord</option>
|
||||
<option value="telegram">Telegram</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<label class="form-label">Destinatario</label>
|
||||
<select name="recipient_id" id="recipientSelect" class="form-select" required disabled>
|
||||
<option value="">Selecciona una plataforma primero</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card border-0 shadow-sm mb-4">
|
||||
<div class="card-header bg-white border-0">
|
||||
<h5 class="mb-0">Programación</h5>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="mb-3">
|
||||
<label class="form-label">Tipo de envío</label>
|
||||
<select name="send_type" id="sendType" class="form-select" required>
|
||||
<option value="now">Enviar ahora</option>
|
||||
<option value="later">Programar para después</option>
|
||||
<option value="recurring">Recurrente</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="mb-3" id="datetimeField" style="display: none;">
|
||||
<label class="form-label">Fecha y hora</label>
|
||||
<input type="datetime-local" name="send_datetime" class="form-control">
|
||||
</div>
|
||||
|
||||
<div id="recurringFields" style="display: none;">
|
||||
<div class="mb-3">
|
||||
<label class="form-label">Días</label>
|
||||
<select name="recurring_days" class="form-select">
|
||||
<option value="monday">Lunes</option>
|
||||
<option value="tuesday">Martes</option>
|
||||
<option value="wednesday">Miércoles</option>
|
||||
<option value="thursday">Jueves</option>
|
||||
<option value="friday">Viernes</option>
|
||||
<option value="saturday">Sábado</option>
|
||||
<option value="sunday">Domingo</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label class="form-label">Hora</label>
|
||||
<input type="time" name="recurring_time" class="form-control" value="09:00">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="d-grid gap-2">
|
||||
<button type="submit" class="btn btn-primary btn-lg">
|
||||
<i class="bi bi-send"></i> Enviar
|
||||
</button>
|
||||
<a href="index.php" class="btn btn-outline-secondary">Cancelar</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<!-- Modal de Galería -->
|
||||
<div class="modal fade" id="galleryModal" tabindex="-1">
|
||||
<div class="modal-dialog modal-lg modal-dialog-scrollable">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title"><i class="bi bi-images"></i> Galería de Imágenes</h5>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div class="row g-3">
|
||||
<?php if (empty($galleryImages)): ?>
|
||||
<div class="col-12 text-center text-muted py-5">
|
||||
<i class="bi bi-images" style="font-size: 3rem;"></i>
|
||||
<p class="mt-3">No hay imágenes en la galería</p>
|
||||
</div>
|
||||
<?php else: ?>
|
||||
<?php foreach ($galleryImages as $image): ?>
|
||||
<div class="col-md-3 col-sm-4 col-6">
|
||||
<div class="card h-100 cursor-pointer" onclick="insertImage('galeria/<?= urlencode($image) ?>')" style="cursor: pointer;">
|
||||
<img src="galeria/<?= urlencode($image) ?>" class="card-img-top" alt="<?= htmlspecialchars($image) ?>" style="height: 120px; object-fit: cover;">
|
||||
<div class="card-body p-2">
|
||||
<small class="text-muted text-truncate d-block"><?= htmlspecialchars($image) ?></small>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<?php endforeach; ?>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<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>
|
||||
const recipients = <?= json_encode($recipients) ?>;
|
||||
|
||||
$(document).ready(function() {
|
||||
// Inicializar Summernote con botón de galería personalizado
|
||||
$('#messageContent').summernote({
|
||||
height: 350,
|
||||
toolbar: [
|
||||
['style', ['bold', 'italic', 'underline', 'clear']],
|
||||
['font', ['strikethrough', 'superscript', 'subscript']],
|
||||
['fontsize', ['fontsize']],
|
||||
['color', ['color']],
|
||||
['para', ['ul', 'ol', 'paragraph']],
|
||||
['height', ['height']],
|
||||
['insert', ['link', 'video', 'gallery']], // 'gallery' es nuestro botón personalizado
|
||||
['view', ['fullscreen', 'codeview']]
|
||||
],
|
||||
buttons: {
|
||||
gallery: function() {
|
||||
return $.summernote.ui.button({
|
||||
contents: '<i class="bi bi-images"></i> Galería',
|
||||
tooltip: 'Insertar imagen desde galería',
|
||||
click: function() {
|
||||
$('#galleryModal').modal('show');
|
||||
}
|
||||
}).render();
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
function insertImage(url) {
|
||||
const imgTag = '<img src="' + url + '" style="max-width: 100%; height: auto;">';
|
||||
$('#messageContent').summernote('editor.pasteHTML', imgTag);
|
||||
$('#galleryModal').modal('hide');
|
||||
}
|
||||
|
||||
document.getElementById('templateSelect').addEventListener('change', function() {
|
||||
if (this.value) {
|
||||
$('#messageContent').summernote('code', this.value);
|
||||
}
|
||||
});
|
||||
|
||||
document.getElementById('platformSelect').addEventListener('change', function() {
|
||||
const platform = this.value;
|
||||
const recipientSelect = document.getElementById('recipientSelect');
|
||||
|
||||
recipientSelect.innerHTML = '<option value="">-- Seleccionar --</option>';
|
||||
|
||||
if (platform) {
|
||||
const filtered = recipients.filter(r => r.platform === platform);
|
||||
filtered.forEach(r => {
|
||||
const option = document.createElement('option');
|
||||
option.value = r.id;
|
||||
option.textContent = r.name + ' (' + r.type + ')';
|
||||
recipientSelect.appendChild(option);
|
||||
});
|
||||
recipientSelect.disabled = false;
|
||||
} else {
|
||||
recipientSelect.disabled = true;
|
||||
recipientSelect.innerHTML = '<option value="">Selecciona una plataforma primero</option>';
|
||||
}
|
||||
});
|
||||
|
||||
document.getElementById('sendType').addEventListener('change', function() {
|
||||
const datetimeField = document.getElementById('datetimeField');
|
||||
const recurringFields = document.getElementById('recurringFields');
|
||||
|
||||
datetimeField.style.display = this.value === 'later' ? 'block' : 'none';
|
||||
recurringFields.style.display = this.value === 'recurring' ? 'block' : 'none';
|
||||
});
|
||||
</script>
|
||||
|
||||
<?php require_once __DIR__ . '/templates/footer.php'; ?>
|
||||
Reference in New Issue
Block a user