Initial commit - Last War messaging system
This commit is contained in:
338
telegram/TelegramSender.php
Executable file
338
telegram/TelegramSender.php
Executable file
@@ -0,0 +1,338 @@
|
||||
<?php
|
||||
|
||||
namespace Telegram;
|
||||
|
||||
class TelegramSender
|
||||
{
|
||||
private string $token;
|
||||
private string $baseUrl = 'https://api.telegram.org/bot';
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->token = $_ENV['TELEGRAM_BOT_TOKEN'] ?? getenv('TELEGRAM_BOT_TOKEN');
|
||||
}
|
||||
|
||||
public function sendMessage(int $chatId, string $text, ?array $keyboard = null, ?string $parseMode = 'HTML'): array
|
||||
{
|
||||
$data = [
|
||||
'chat_id' => $chatId,
|
||||
'text' => $text,
|
||||
'parse_mode' => $parseMode
|
||||
];
|
||||
|
||||
if ($keyboard) {
|
||||
$data['reply_markup'] = json_encode($keyboard);
|
||||
}
|
||||
|
||||
return $this->request('sendMessage', $data);
|
||||
}
|
||||
|
||||
public function editMessageText(int $chatId, int $messageId, string $text, ?array $keyboard = null, ?string $parseMode = 'HTML'): array
|
||||
{
|
||||
$data = [
|
||||
'chat_id' => $chatId,
|
||||
'message_id' => $messageId,
|
||||
'text' => $text,
|
||||
'parse_mode' => $parseMode
|
||||
];
|
||||
|
||||
if ($keyboard) {
|
||||
$data['reply_markup'] = json_encode($keyboard);
|
||||
}
|
||||
|
||||
return $this->request('editMessageText', $data);
|
||||
}
|
||||
|
||||
public function sendPhoto(int $chatId, string $photo, ?string $caption = null, ?array $keyboard = null): array
|
||||
{
|
||||
$data = [
|
||||
'chat_id' => $chatId,
|
||||
'photo' => $photo
|
||||
];
|
||||
|
||||
if ($caption) {
|
||||
$data['caption'] = $caption;
|
||||
$data['parse_mode'] = 'HTML';
|
||||
}
|
||||
|
||||
if ($keyboard) {
|
||||
$data['reply_markup'] = json_encode($keyboard);
|
||||
}
|
||||
|
||||
return $this->request('sendPhoto', $data);
|
||||
}
|
||||
|
||||
public function sendMediaGroup(int $chatId, array $photos, ?string $caption = null): array
|
||||
{
|
||||
$media = [];
|
||||
foreach ($photos as $index => $photo) {
|
||||
$media[] = [
|
||||
'type' => 'photo',
|
||||
'media' => $photo,
|
||||
'caption' => $index === 0 ? $caption : null,
|
||||
'parse_mode' => 'HTML'
|
||||
];
|
||||
}
|
||||
|
||||
$data = [
|
||||
'chat_id' => $chatId,
|
||||
'media' => json_encode($media)
|
||||
];
|
||||
|
||||
return $this->request('sendMediaGroup', $data);
|
||||
}
|
||||
|
||||
public function deleteMessage(int $chatId, int $messageId): array
|
||||
{
|
||||
return $this->request('deleteMessage', [
|
||||
'chat_id' => $chatId,
|
||||
'message_id' => $messageId
|
||||
]);
|
||||
}
|
||||
|
||||
public function answerCallbackQuery(string $callbackQueryId, string $text, ?bool $showAlert = false)
|
||||
{
|
||||
return $this->request('answerCallbackQuery', [
|
||||
'callback_query_id' => $callbackQueryId,
|
||||
'text' => $text,
|
||||
'show_alert' => $showAlert
|
||||
]);
|
||||
}
|
||||
|
||||
public function getChat(int $chatId): array
|
||||
{
|
||||
return $this->request('getChat', ['chat_id' => $chatId]);
|
||||
}
|
||||
|
||||
public function getChatAdministrators(int $chatId): array
|
||||
{
|
||||
return $this->request('getChatAdministrators', ['chat_id' => $chatId]);
|
||||
}
|
||||
|
||||
public function leaveChat(int $chatId): array
|
||||
{
|
||||
return $this->request('leaveChat', ['chat_id' => $chatId]);
|
||||
}
|
||||
|
||||
public function setChatMenuButton(?int $chatId = null, ?array $menuButton = null): array
|
||||
{
|
||||
$data = [];
|
||||
|
||||
if ($chatId !== null) {
|
||||
$data['chat_id'] = $chatId;
|
||||
}
|
||||
|
||||
if ($menuButton !== null) {
|
||||
$data['menu_button'] = json_encode($menuButton);
|
||||
}
|
||||
|
||||
return $this->request('setChatMenuButton', $data);
|
||||
}
|
||||
|
||||
public function createInlineKeyboard(array $buttons): array
|
||||
{
|
||||
$keyboard = ['inline_keyboard' => []];
|
||||
|
||||
foreach ($buttons as $button) {
|
||||
$buttonData = ['text' => $button['text']];
|
||||
|
||||
if (isset($button['callback_data'])) {
|
||||
$buttonData['callback_data'] = $button['callback_data'];
|
||||
} elseif (isset($button['url'])) {
|
||||
$buttonData['url'] = $button['url'];
|
||||
}
|
||||
|
||||
$keyboard['inline_keyboard'][] = [$buttonData];
|
||||
}
|
||||
|
||||
return $keyboard;
|
||||
}
|
||||
|
||||
public function createReplyKeyboard(array $buttons, ?bool $resize = true, ?bool $oneTime = false): array
|
||||
{
|
||||
$keyboard = [
|
||||
'keyboard' => [],
|
||||
'resize_keyboard' => $resize,
|
||||
'one_time_keyboard' => $oneTime
|
||||
];
|
||||
|
||||
foreach ($buttons as $row) {
|
||||
$rowButtons = [];
|
||||
foreach ($row as $button) {
|
||||
$rowButtons[] = [
|
||||
'text' => $button['text'],
|
||||
'request_contact' => $button['request_contact'] ?? false,
|
||||
'request_location' => $button['request_location'] ?? false
|
||||
];
|
||||
}
|
||||
$keyboard['keyboard'][] = $rowButtons;
|
||||
}
|
||||
|
||||
return $keyboard;
|
||||
}
|
||||
|
||||
public function removeKeyboard(): array
|
||||
{
|
||||
return ['remove_keyboard' => true];
|
||||
}
|
||||
|
||||
private function request(string $method, array $data)
|
||||
{
|
||||
$url = $this->baseUrl . $this->token . '/' . $method;
|
||||
|
||||
$ch = curl_init($url);
|
||||
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
|
||||
curl_setopt($ch, CURLOPT_POST, true);
|
||||
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
|
||||
|
||||
$response = curl_exec($ch);
|
||||
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
|
||||
curl_close($ch);
|
||||
|
||||
// answerCallbackQuery returns true (boolean) on success
|
||||
if ($response === 'true') {
|
||||
return true;
|
||||
}
|
||||
|
||||
$result = json_decode($response, true);
|
||||
|
||||
if (!$result || !($result['ok'] ?? false)) {
|
||||
throw new \Exception("Telegram API Error: " . ($result['description'] ?? 'Unknown error'));
|
||||
}
|
||||
|
||||
return $result['result'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Parsear HTML y dividirlo en segmentos manteniendo el orden
|
||||
* Retorna array de ['type' => 'text|image', 'content' => '...', 'src' => '...']
|
||||
*/
|
||||
public function parseContent(string $html): array
|
||||
{
|
||||
$segments = [];
|
||||
|
||||
// Usar regex para encontrar todas las etiquetas <img>
|
||||
$pattern = '/<img[^>]+src=["\']([^"\']+)["\'][^>]*>/i';
|
||||
$parts = preg_split($pattern, $html, -1, PREG_SPLIT_DELIM_CAPTURE);
|
||||
|
||||
// El array parts alterna entre: [texto, src_imagen, texto, src_imagen, texto...]
|
||||
for ($i = 0; $i < count($parts); $i++) {
|
||||
if ($i % 2 === 0) {
|
||||
// Es texto
|
||||
$text = $this->htmlToPlainText($parts[$i]);
|
||||
if (!empty(trim($text))) {
|
||||
$segments[] = [
|
||||
'type' => 'text',
|
||||
'content' => $text
|
||||
];
|
||||
}
|
||||
} else {
|
||||
// Es una imagen (el src capturado)
|
||||
$segments[] = [
|
||||
'type' => 'image',
|
||||
'src' => $parts[$i],
|
||||
'content' => ''
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
return $segments;
|
||||
}
|
||||
|
||||
/**
|
||||
* Enviar contenido con texto e imágenes en el orden correcto
|
||||
*/
|
||||
public function sendContentWithOrderedImages(int $chatId, array $segments): void
|
||||
{
|
||||
foreach ($segments as $segment) {
|
||||
if ($segment['type'] === 'text') {
|
||||
// Enviar texto
|
||||
if (!empty(trim($segment['content']))) {
|
||||
$this->sendMessage($chatId, $segment['content']);
|
||||
}
|
||||
} elseif ($segment['type'] === 'image') {
|
||||
$imagePath = $segment['src'];
|
||||
|
||||
if (file_exists($imagePath)) {
|
||||
// Es un archivo local
|
||||
$this->sendPhoto($chatId, $imagePath);
|
||||
} elseif (strpos($imagePath, 'http') === 0) {
|
||||
// Es una URL remota
|
||||
$this->sendPhoto($chatId, $imagePath);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Convertir HTML a texto plano manteniendo saltos de línea
|
||||
*/
|
||||
private function htmlToPlainText(string $html): string
|
||||
{
|
||||
// Reemplazar <br>, <p>, etc. con saltos de línea
|
||||
$text = preg_replace('/<br\s*\/?>/i', "\n", $html);
|
||||
$text = preg_replace('/<\/p>/i', "\n", $text);
|
||||
$text = preg_replace('/<p[^>]*>/i', '', $text);
|
||||
$text = preg_replace('/<div[^>]*>/i', '', $text);
|
||||
$text = preg_replace('/<\/div>/i', "\n", $text);
|
||||
|
||||
// Eliminar otras etiquetas HTML
|
||||
$text = strip_tags($text);
|
||||
|
||||
// Decodificar entidades HTML
|
||||
$text = html_entity_decode($text, ENT_QUOTES | ENT_HTML5, 'UTF-8');
|
||||
|
||||
// Limpiar espacios múltiples y saltos de línea
|
||||
$text = preg_replace('/\n{3,}/', "\n\n", $text);
|
||||
$text = preg_replace('/[ \t]+/', ' ', $text);
|
||||
|
||||
return trim($text);
|
||||
}
|
||||
|
||||
public function extractImages(string $html): array
|
||||
{
|
||||
preg_match_all('/<img[^>]+src=["\']([^"\']+)["\'][^>]*>/i', $html, $matches);
|
||||
return $matches[1] ?? [];
|
||||
}
|
||||
|
||||
public function removeImages(string $html): string
|
||||
{
|
||||
return preg_replace('/<img[^>]+>/i', '', $html);
|
||||
}
|
||||
|
||||
public function splitMessage(string $content, int $maxLength = 4096): array
|
||||
{
|
||||
if (strlen($content) <= $maxLength) {
|
||||
return [$content];
|
||||
}
|
||||
|
||||
$parts = [];
|
||||
$lines = explode("\n", $content);
|
||||
$currentPart = '';
|
||||
|
||||
foreach ($lines as $line) {
|
||||
if (strlen($currentPart . "\n" . $line) > $maxLength) {
|
||||
if (!empty($currentPart)) {
|
||||
$parts[] = $currentPart;
|
||||
$currentPart = '';
|
||||
}
|
||||
|
||||
if (strlen($line) > $maxLength) {
|
||||
$chunks = str_split($line, $maxLength);
|
||||
$parts = array_merge($parts, array_slice($chunks, 0, -1));
|
||||
$currentPart = end($chunks);
|
||||
} else {
|
||||
$currentPart = $line;
|
||||
}
|
||||
} else {
|
||||
$currentPart .= (empty($currentPart) ? '' : "\n") . $line;
|
||||
}
|
||||
}
|
||||
|
||||
if (!empty($currentPart)) {
|
||||
$parts[] = $currentPart;
|
||||
}
|
||||
|
||||
return $parts;
|
||||
}
|
||||
}
|
||||
123
telegram/actions/TelegramActions.php
Executable file
123
telegram/actions/TelegramActions.php
Executable file
@@ -0,0 +1,123 @@
|
||||
<?php
|
||||
|
||||
namespace Telegram\Actions;
|
||||
|
||||
use Telegram\TelegramSender;
|
||||
use Telegram\Converters\HtmlToTelegramHtmlConverter;
|
||||
|
||||
class TelegramActions
|
||||
{
|
||||
private TelegramSender $sender;
|
||||
private HtmlToTelegramHtmlConverter $converter;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->sender = new TelegramSender();
|
||||
$this->converter = new HtmlToTelegramHtmlConverter();
|
||||
}
|
||||
|
||||
public function sendTemplate(int $chatId, string $htmlContent, ?string $command = null): array
|
||||
{
|
||||
$content = $this->converter->convert($htmlContent);
|
||||
$images = $this->converter->extractImages($htmlContent);
|
||||
|
||||
if (!empty($images)) {
|
||||
$contentWithoutImages = $this->converter->removeImages($htmlContent);
|
||||
$content = $this->converter->convert($contentWithoutImages);
|
||||
|
||||
if (count($images) === 1) {
|
||||
return $this->sender->sendPhoto($chatId, $images[0], $content);
|
||||
}
|
||||
|
||||
return $this->sender->sendMediaGroup($chatId, $images, $content);
|
||||
}
|
||||
|
||||
return $this->sender->sendMessage($chatId, $content);
|
||||
}
|
||||
|
||||
public function sendScheduledMessage(int $chatId, string $htmlContent, ?array $buttons = null): array
|
||||
{
|
||||
$content = $this->converter->convert($htmlContent);
|
||||
$images = $this->converter->extractImages($htmlContent);
|
||||
|
||||
if (!empty($images)) {
|
||||
$contentWithoutImages = $this->converter->removeImages($htmlContent);
|
||||
$content = $this->converter->convert($contentWithoutImages);
|
||||
|
||||
if ($buttons) {
|
||||
$keyboard = $this->sender->createInlineKeyboard($buttons);
|
||||
if (count($images) === 1) {
|
||||
return $this->sender->sendPhoto($chatId, $images[0], $content, $keyboard);
|
||||
}
|
||||
return $this->sender->sendMediaGroup($chatId, $images, $content);
|
||||
}
|
||||
|
||||
if (count($images) === 1) {
|
||||
return $this->sender->sendPhoto($chatId, $images[0], $content);
|
||||
}
|
||||
|
||||
return $this->sender->sendMediaGroup($chatId, $images, $content);
|
||||
}
|
||||
|
||||
return $this->sender->sendMessage($chatId, $content, $buttons);
|
||||
}
|
||||
|
||||
public function sendWithTranslation(int $chatId, string $htmlContent, array $translations): array
|
||||
{
|
||||
$content = $this->converter->convert($htmlContent);
|
||||
|
||||
$buttons = [];
|
||||
foreach ($translations as $lang => $translatedText) {
|
||||
$buttons[] = [
|
||||
'text' => "🌐 " . strtoupper($lang),
|
||||
'callback_data' => "translate:{$lang}"
|
||||
];
|
||||
}
|
||||
|
||||
$keyboard = $this->sender->createInlineKeyboard($buttons);
|
||||
|
||||
return $this->sender->sendMessage($chatId, $content, $keyboard);
|
||||
}
|
||||
|
||||
public function translateMessage(int $chatId, string $originalText, string $targetLang, string $translatedText): array
|
||||
{
|
||||
$message = "🌐 <b>Traducción (" . strtoupper($targetLang) . ")</b>\n\n";
|
||||
$message .= $translatedText;
|
||||
|
||||
$message .= "\n\n━━━━━━━━━━━━━━━━━\n";
|
||||
$message .= "<i>Original:</i>\n" . $originalText;
|
||||
|
||||
return $this->sender->sendMessage($chatId, $message);
|
||||
}
|
||||
|
||||
public function handleCallbackQuery(array $callbackData): array
|
||||
{
|
||||
$parts = explode(':', $callbackData['data']);
|
||||
$action = $parts[0] ?? '';
|
||||
|
||||
return match ($action) {
|
||||
'translate' => [
|
||||
'action' => 'translate',
|
||||
'lang' => $parts[1] ?? null
|
||||
],
|
||||
default => ['action' => 'unknown']
|
||||
};
|
||||
}
|
||||
|
||||
public function sendWelcomeMessage(int $chatId, string $userName, ?string $welcomeText = null, ?string $buttonText = null, ?string $groupLink = null): array
|
||||
{
|
||||
$message = $welcomeText ?? "¡Hola {$userName}! 👋\n\nUsa /comandos para ver los comandos disponibles.";
|
||||
|
||||
$buttons = [];
|
||||
if ($buttonText && $groupLink) {
|
||||
$buttons[] = [
|
||||
'text' => $buttonText,
|
||||
'url' => $groupLink
|
||||
];
|
||||
}
|
||||
|
||||
$keyboard = !empty($buttons) ? $this->sender->createInlineKeyboard($buttons) : null;
|
||||
|
||||
return $this->sender->sendMessage($chatId, $message, $keyboard);
|
||||
}
|
||||
}
|
||||
102
telegram/admin/telegram_bot_interactions.php
Executable file
102
telegram/admin/telegram_bot_interactions.php
Executable file
@@ -0,0 +1,102 @@
|
||||
<?php
|
||||
require_once __DIR__ . '/../../includes/db.php';
|
||||
require_once __DIR__ . '/../../includes/session_check.php';
|
||||
require_once __DIR__ . '/../../includes/activity_logger.php';
|
||||
|
||||
requireAdmin();
|
||||
|
||||
$pageTitle = 'Configuración del Bot de Telegram';
|
||||
|
||||
try {
|
||||
$pdo = getDbConnection();
|
||||
$stmt = $pdo->query("SELECT * FROM telegram_bot_messages WHERE id = 1");
|
||||
$config = $stmt->fetch();
|
||||
} catch (Exception $e) {
|
||||
$error = $e->getMessage();
|
||||
}
|
||||
|
||||
$success = '';
|
||||
|
||||
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
||||
$messageText = $_POST['message_text'] ?? '';
|
||||
$buttonText = $_POST['button_text'] ?? '';
|
||||
$groupInviteLink = $_POST['group_invite_link'] ?? '';
|
||||
$isActive = isset($_POST['is_active']) ? 1 : 0;
|
||||
$registerUsers = isset($_POST['register_users']) ? 1 : 0;
|
||||
|
||||
$stmt = $pdo->prepare("
|
||||
UPDATE telegram_bot_messages
|
||||
SET message_text = ?, button_text = ?, group_invite_link = ?, is_active = ?, register_users = ?
|
||||
WHERE id = 1
|
||||
");
|
||||
$stmt->execute([$messageText, $buttonText, $groupInviteLink, $isActive, $registerUsers]);
|
||||
|
||||
logActivity(getCurrentUserId(), 'update_telegram_config', 'Configuración del bot de Telegram actualizada');
|
||||
$success = 'Configuración guardada correctamente';
|
||||
|
||||
$stmt = $pdo->query("SELECT * FROM telegram_bot_messages WHERE id = 1");
|
||||
$config = $stmt->fetch();
|
||||
}
|
||||
|
||||
require_once __DIR__ . '/../../templates/header.php';
|
||||
?>
|
||||
|
||||
<div class="d-flex justify-content-between align-items-center mb-4">
|
||||
<h2><i class="bi bi-telegram"></i> Configuración del Bot de Telegram</h2>
|
||||
</div>
|
||||
|
||||
<?php if ($success): ?>
|
||||
<div class="alert alert-success"><?= htmlspecialchars($success) ?></div>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php if (isset($error)): ?>
|
||||
<div class="alert alert-danger"><?= htmlspecialchars($error) ?></div>
|
||||
<?php endif; ?>
|
||||
|
||||
<form method="POST">
|
||||
<div class="card border-0 shadow-sm mb-4">
|
||||
<div class="card-header bg-white border-0">
|
||||
<h5 class="mb-0">Mensaje de Bienvenida</h5>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="mb-3">
|
||||
<label class="form-label">Mensaje de bienvenida</label>
|
||||
<textarea name="message_text" class="form-control" rows="5"><?= htmlspecialchars($config['message_text'] ?? '') ?></textarea>
|
||||
<small class="text-muted">Usa <code>{user_name}</code> para el nombre del usuario</small>
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<label class="form-label">Texto del botón</label>
|
||||
<input type="text" name="button_text" class="form-control" value="<?= htmlspecialchars($config['button_text'] ?? '') ?>" placeholder="Unirse al grupo">
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<label class="form-label">Enlace de invitación al grupo</label>
|
||||
<input type="text" name="group_invite_link" class="form-control" value="<?= htmlspecialchars($config['group_invite_link'] ?? '') ?>" placeholder="https://t.me/...">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card border-0 shadow-sm mb-4">
|
||||
<div class="card-header bg-white border-0">
|
||||
<h5 class="mb-0">Opciones</h5>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="form-check form-switch mb-3">
|
||||
<input class="form-check-input" type="checkbox" name="is_active" id="isActive" <?= ($config['is_active'] ?? true) ? 'checked' : '' ?>>
|
||||
<label class="form-check-label" for="isActive">Mensaje de bienvenida activo</label>
|
||||
</div>
|
||||
|
||||
<div class="form-check form-switch">
|
||||
<input class="form-check-input" type="checkbox" name="register_users" id="registerUsers" <?= ($config['register_users'] ?? true) ? 'checked' : '' ?>>
|
||||
<label class="form-check-label" for="registerUsers">Registrar usuarios automáticamente</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<button type="submit" class="btn btn-primary">
|
||||
<i class="bi bi-save"></i> Guardar Configuración
|
||||
</button>
|
||||
</form>
|
||||
|
||||
<?php require_once __DIR__ . '/../../templates/footer.php'; ?>
|
||||
229
telegram/admin/telegram_welcome.php
Executable file
229
telegram/admin/telegram_welcome.php
Executable file
@@ -0,0 +1,229 @@
|
||||
<?php
|
||||
require_once __DIR__ . '/../../includes/db.php';
|
||||
require_once __DIR__ . '/../../includes/session_check.php';
|
||||
require_once __DIR__ . '/../../includes/activity_logger.php';
|
||||
|
||||
requireAdmin();
|
||||
|
||||
$pageTitle = 'Mensajes de Bienvenida por Grupo';
|
||||
|
||||
try {
|
||||
$pdo = getDbConnection();
|
||||
|
||||
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
||||
$action = $_POST['action'] ?? '';
|
||||
|
||||
if ($action === 'add') {
|
||||
$chatId = $_POST['chat_id'];
|
||||
$welcomeMessage = $_POST['welcome_message'];
|
||||
$buttonText = $_POST['button_text'];
|
||||
$groupInviteLink = $_POST['group_invite_link'];
|
||||
$languageCode = $_POST['language_code'];
|
||||
$languageName = $_POST['language_name'];
|
||||
$flagEmoji = $_POST['flag_emoji'];
|
||||
$isActive = isset($_POST['is_active']) ? 1 : 0;
|
||||
|
||||
$stmt = $pdo->prepare("
|
||||
INSERT INTO telegram_welcome_messages
|
||||
(chat_id, welcome_message, button_text, group_invite_link, language_code, language_name, flag_emoji, is_active)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?)
|
||||
");
|
||||
$stmt->execute([$chatId, $welcomeMessage, $buttonText, $groupInviteLink, $languageCode, $languageName, $flagEmoji, $isActive]);
|
||||
|
||||
logActivity(getCurrentUserId(), 'add_group_welcome', "Mensaje de bienvenida agregado para grupo: $chatId");
|
||||
header('Location: telegram_welcome.php');
|
||||
exit;
|
||||
|
||||
} elseif ($action === 'update') {
|
||||
$id = $_POST['id'];
|
||||
$welcomeMessage = $_POST['welcome_message'];
|
||||
$buttonText = $_POST['button_text'];
|
||||
$groupInviteLink = $_POST['group_invite_link'];
|
||||
$languageCode = $_POST['language_code'];
|
||||
$languageName = $_POST['language_name'];
|
||||
$flagEmoji = $_POST['flag_emoji'];
|
||||
$isActive = isset($_POST['is_active']) ? 1 : 0;
|
||||
|
||||
$stmt = $pdo->prepare("
|
||||
UPDATE telegram_welcome_messages
|
||||
SET welcome_message = ?, button_text = ?, group_invite_link = ?,
|
||||
language_code = ?, language_name = ?, flag_emoji = ?, is_active = ?
|
||||
WHERE id = ?
|
||||
");
|
||||
$stmt->execute([$welcomeMessage, $buttonText, $groupInviteLink, $languageCode, $languageName, $flagEmoji, $isActive, $id]);
|
||||
|
||||
logActivity(getCurrentUserId(), 'update_group_welcome', "Mensaje de bienvenida actualizado ID: $id");
|
||||
header('Location: telegram_welcome.php');
|
||||
exit;
|
||||
|
||||
} elseif ($action === 'delete') {
|
||||
$id = $_POST['id'];
|
||||
$stmt = $pdo->prepare("DELETE FROM telegram_welcome_messages WHERE id = ?");
|
||||
$stmt->execute([$id]);
|
||||
|
||||
logActivity(getCurrentUserId(), 'delete_group_welcome', "Mensaje de bienvenida eliminado ID: $id");
|
||||
header('Location: telegram_welcome.php');
|
||||
exit;
|
||||
}
|
||||
}
|
||||
|
||||
$stmt = $pdo->query("SELECT * FROM telegram_welcome_messages ORDER BY created_at DESC");
|
||||
$welcomeMessages = $stmt->fetchAll();
|
||||
|
||||
} catch (Exception $e) {
|
||||
$error = $e->getMessage();
|
||||
}
|
||||
|
||||
require_once __DIR__ . '/../../templates/header.php';
|
||||
?>
|
||||
|
||||
<div class="d-flex justify-content-between align-items-center mb-4">
|
||||
<h2><i class="bi bi-telegram"></i> Mensajes de Bienvenida por Grupo</h2>
|
||||
<button class="btn btn-primary" data-bs-toggle="modal" data-bs-target="#welcomeModal">
|
||||
<i class="bi bi-plus-circle"></i> Nuevo Mensaje
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<?php if (isset($error)): ?>
|
||||
<div class="alert alert-danger"><?= htmlspecialchars($error) ?></div>
|
||||
<?php endif; ?>
|
||||
|
||||
<div class="row">
|
||||
<?php if (empty($welcomeMessages)): ?>
|
||||
<div class="col-12">
|
||||
<p class="text-muted text-center py-4">No hay mensajes de bienvenida configurados</p>
|
||||
</div>
|
||||
<?php else: ?>
|
||||
<?php foreach ($welcomeMessages as $msg): ?>
|
||||
<div class="col-md-6 mb-4">
|
||||
<div class="card border-0 shadow-sm">
|
||||
<div class="card-header bg-white border-0 d-flex justify-content-between align-items-center">
|
||||
<h6 class="mb-0"><?= htmlspecialchars($msg['flag_emoji'] ?? '') ?> <?= htmlspecialchars($msg['language_name'] ?? 'Grupo') ?></h6>
|
||||
<div class="btn-group btn-group-sm">
|
||||
<button class="btn btn-outline-primary" data-bs-toggle="modal" data-bs-target="#editModal<?= $msg['id'] ?>">
|
||||
<i class="bi bi-pencil"></i>
|
||||
</button>
|
||||
<form method="POST" onsubmit="return confirm('¿Eliminar?');" class="d-inline">
|
||||
<input type="hidden" name="action" value="delete">
|
||||
<input type="hidden" name="id" value="<?= $msg['id'] ?>">
|
||||
<button type="submit" class="btn btn-outline-danger">
|
||||
<i class="bi bi-trash"></i>
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<p class="text-muted small mb-1">Chat ID: <?= $msg['chat_id'] ?></p>
|
||||
<p class="mb-1"><?= nl2br(htmlspecialchars($msg['welcome_message'] ?? '')) ?></p>
|
||||
<small class="text-muted"><?= $msg['is_active'] ? '✅ Activo' : '❌ Inactivo' ?></small>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="modal fade" id="editModal<?= $msg['id'] ?>" tabindex="-1">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<form method="POST">
|
||||
<input type="hidden" name="action" value="update">
|
||||
<input type="hidden" name="id" value="<?= $msg['id'] ?>">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title">Editar Mensaje</h5>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div class="mb-3">
|
||||
<label class="form-label">Mensaje de bienvenida</label>
|
||||
<textarea name="welcome_message" class="form-control" rows="3"><?= htmlspecialchars($msg['welcome_message'] ?? '') ?></textarea>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label class="form-label">Texto del botón</label>
|
||||
<input type="text" name="button_text" class="form-control" value="<?= htmlspecialchars($msg['button_text'] ?? '') ?>">
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label class="form-label">Enlace de invitación</label>
|
||||
<input type="text" name="group_invite_link" class="form-control" value="<?= htmlspecialchars($msg['group_invite_link'] ?? '') ?>">
|
||||
</div>
|
||||
<div class="row mb-3">
|
||||
<div class="col-4">
|
||||
<label class="form-label">Código idioma</label>
|
||||
<input type="text" name="language_code" class="form-control" value="<?= htmlspecialchars($msg['language_code'] ?? 'es') ?>">
|
||||
</div>
|
||||
<div class="col-4">
|
||||
<label class="form-label">Nombre idioma</label>
|
||||
<input type="text" name="language_name" class="form-control" value="<?= htmlspecialchars($msg['language_name'] ?? 'Español') ?>">
|
||||
</div>
|
||||
<div class="col-4">
|
||||
<label class="form-label">Flag</label>
|
||||
<input type="text" name="flag_emoji" class="form-control" value="<?= htmlspecialchars($msg['flag_emoji'] ?? '🇪🇸') ?>">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-check">
|
||||
<input class="form-check-input" type="checkbox" name="is_active" id="editActive<?= $msg['id'] ?>" <?= $msg['is_active'] ? 'checked' : '' ?>>
|
||||
<label class="form-check-label" for="editActive<?= $msg['id'] ?>">Activo</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="submit" class="btn btn-primary">Guardar</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<?php endforeach; ?>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
|
||||
<div class="modal fade" id="welcomeModal" tabindex="-1">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<form method="POST">
|
||||
<input type="hidden" name="action" value="add">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title">Nuevo Mensaje de Bienvenida</h5>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div class="mb-3">
|
||||
<label class="form-label">Chat ID del grupo</label>
|
||||
<input type="text" name="chat_id" class="form-control" required>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label class="form-label">Mensaje de bienvenida</label>
|
||||
<textarea name="welcome_message" class="form-control" rows="3" required></textarea>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label class="form-label">Texto del botón</label>
|
||||
<input type="text" name="button_text" class="form-control">
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label class="form-label">Enlace de invitación</label>
|
||||
<input type="text" name="group_invite_link" class="form-control">
|
||||
</div>
|
||||
<div class="row mb-3">
|
||||
<div class="col-4">
|
||||
<label class="form-label">Código idioma</label>
|
||||
<input type="text" name="language_code" class="form-control" value="es">
|
||||
</div>
|
||||
<div class="col-4">
|
||||
<label class="form-label">Nombre idioma</label>
|
||||
<input type="text" name="language_name" class="form-control" value="Español">
|
||||
</div>
|
||||
<div class="col-4">
|
||||
<label class="form-label">Flag</label>
|
||||
<input type="text" name="flag_emoji" class="form-control" value="🇪🇸">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-check">
|
||||
<input class="form-check-input" type="checkbox" name="is_active" id="newActive" checked>
|
||||
<label class="form-check-label" for="newActive">Activo</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="submit" class="btn btn-primary">Agregar</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<?php require_once __DIR__ . '/../../templates/footer.php'; ?>
|
||||
112
telegram/converters/HtmlToTelegramHtmlConverter.php
Executable file
112
telegram/converters/HtmlToTelegramHtmlConverter.php
Executable file
@@ -0,0 +1,112 @@
|
||||
<?php
|
||||
|
||||
namespace Telegram\Converters;
|
||||
|
||||
class HtmlToTelegramHtmlConverter
|
||||
{
|
||||
public function convert(string $html): string
|
||||
{
|
||||
$content = $html;
|
||||
|
||||
$content = $this->convertBold($content);
|
||||
$content = $this->convertItalic($content);
|
||||
$content = $this->convertUnderline($content);
|
||||
$content = $this->convertStrikethrough($content);
|
||||
$content = $this->convertCode($content);
|
||||
$content = $this->convertLinks($content);
|
||||
$content = $this->convertHeaders($content);
|
||||
$content = $this->convertLineBreaks($content);
|
||||
$content = $this->cleanUp($content);
|
||||
|
||||
return trim($content);
|
||||
}
|
||||
|
||||
private function convertBold(string $content): string
|
||||
{
|
||||
$content = preg_replace('/<strong[^>]*>(.*?)<\/strong>/is', '<b>$1</b>', $content);
|
||||
$content = preg_replace('/<b[^>]*>(.*?)<\/b>/is', '<b>$1</b>', $content);
|
||||
return $content;
|
||||
}
|
||||
|
||||
private function convertItalic(string $content): string
|
||||
{
|
||||
$content = preg_replace('/<em[^>]*>(.*?)<\/em>/is', '<i>$1</i>', $content);
|
||||
$content = preg_replace('/<i[^>]*>(.*?)<\/i>/is', '<i>$1</i>', $content);
|
||||
return $content;
|
||||
}
|
||||
|
||||
private function convertUnderline(string $content): string
|
||||
{
|
||||
$content = preg_replace('/<u[^>]*>(.*?)<\/u>/is', '<u>$1</u>', $content);
|
||||
return $content;
|
||||
}
|
||||
|
||||
private function convertStrikethrough(string $content): string
|
||||
{
|
||||
$content = preg_replace('/<s[^>]*>(.*?)<\/s>/is', '<s>$1</s>', $content);
|
||||
$content = preg_replace('/<strike[^>]*>(.*?)<\/strike>/is', '<s>$1</s>', $content);
|
||||
$content = preg_replace('/<del[^>]*>(.*?)<\/del>/is', '<s>$1</s>', $content);
|
||||
return $content;
|
||||
}
|
||||
|
||||
private function convertCode(string $content): string
|
||||
{
|
||||
$content = preg_replace('/<code[^>]*>(.*?)<\/code>/is', '<code>$1</code>', $content);
|
||||
$content = preg_replace('/<pre[^>]*>(.*?)<\/pre>/is', "<pre>\n$1\n</pre>", $content);
|
||||
return $content;
|
||||
}
|
||||
|
||||
private function convertLinks(string $content): string
|
||||
{
|
||||
$content = preg_replace('/<a[^>]+href=["\']([^"\']+)["\'][^>]*>(.*?)<\/a>/is', '<a href="$1">$2</a>', $content);
|
||||
return $content;
|
||||
}
|
||||
|
||||
private function convertHeaders(string $content): string
|
||||
{
|
||||
$content = preg_replace('/<h1[^>]*>(.*?)<\/h1>/is', "<b>$1</b>\n", $content);
|
||||
$content = preg_replace('/<h2[^>]*>(.*?)<\/h2>/is', "<b>$1</b>\n", $content);
|
||||
$content = preg_replace('/<h3[^>]*>(.*?)<\/h3>/is', "<b>$1</b>\n", $content);
|
||||
$content = preg_replace('/<h4[^>]*>(.*?)<\/h4>/is', "<b>$1</b>\n", $content);
|
||||
$content = preg_replace('/<h5[^>]*>(.*?)<\/h5>/is', "<b>$1</b>\n", $content);
|
||||
$content = preg_replace('/<h6[^>]*>(.*?)<\/h6>/is', "<b>$1</b>\n", $content);
|
||||
return $content;
|
||||
}
|
||||
|
||||
private function convertLineBreaks(string $content): string
|
||||
{
|
||||
$content = preg_replace('/<br\s*\/?>/i', "\n", $content);
|
||||
return $content;
|
||||
}
|
||||
|
||||
private function cleanUp(string $content): string
|
||||
{
|
||||
$content = preg_replace('/<p[^>]*>(.*?)<\/p>/is', "$1\n", $content);
|
||||
$content = preg_replace('/<div[^>]*>(.*?)<\/div>/is', "$1\n", $content);
|
||||
$content = preg_replace('/<span[^>]*>(.*?)<\/span>/is', '$1', $content);
|
||||
$content = preg_replace('/<li[^>]*>(.*?)<\/li>/is', "• $1\n", $content);
|
||||
|
||||
$content = strip_tags($content, '<b><i><u><s><code><pre><a>');
|
||||
|
||||
$content = preg_replace('/ /', ' ', $content);
|
||||
$content = preg_replace('/&/', '&', $content);
|
||||
$content = preg_replace('/</', '<', $content);
|
||||
$content = preg_replace('/>/', '>', $content);
|
||||
$content = preg_replace('/"/', '"', $content);
|
||||
|
||||
$content = preg_replace('/\n{3,}/', "\n\n", $content);
|
||||
|
||||
return $content;
|
||||
}
|
||||
|
||||
public function extractImages(string $html): array
|
||||
{
|
||||
preg_match_all('/<img[^>]+src=["\']([^"\']+)["\'][^>]*>/i', $html, $matches);
|
||||
return $matches[1] ?? [];
|
||||
}
|
||||
|
||||
public function removeImages(string $html): string
|
||||
{
|
||||
return preg_replace('/<img[^>]+>/i', '', $html);
|
||||
}
|
||||
}
|
||||
405
telegram/webhook/telegram_bot_webhook.php
Executable file
405
telegram/webhook/telegram_bot_webhook.php
Executable file
@@ -0,0 +1,405 @@
|
||||
<?php
|
||||
|
||||
require_once __DIR__ . '/../../includes/db.php';
|
||||
require_once __DIR__ . '/../../includes/env_loader.php';
|
||||
require_once __DIR__ . '/../TelegramSender.php';
|
||||
require_once __DIR__ . '/../actions/TelegramActions.php';
|
||||
require_once __DIR__ . '/../converters/HtmlToTelegramHtmlConverter.php';
|
||||
require_once __DIR__ . '/../../src/Translate.php';
|
||||
|
||||
$botToken = $_ENV['TELEGRAM_BOT_TOKEN'] ?? getenv('TELEGRAM_BOT_TOKEN');
|
||||
$webhookSecret = $_ENV['TELEGRAM_WEBHOOK_TOKEN'] ?? getenv('TELEGRAM_WEBHOOK_TOKEN');
|
||||
$receivedToken = $_GET['auth_token'] ?? '';
|
||||
|
||||
if ($webhookSecret !== $receivedToken) {
|
||||
http_response_code(403);
|
||||
exit('Unauthorized');
|
||||
}
|
||||
|
||||
$update = json_decode(file_get_contents('php://input'), true);
|
||||
|
||||
if (!$update) {
|
||||
exit('No update');
|
||||
}
|
||||
|
||||
try {
|
||||
$pdo = getDbConnection();
|
||||
$sender = new Telegram\TelegramSender();
|
||||
$actions = new Telegram\Actions\TelegramActions();
|
||||
$translator = new src\Translate();
|
||||
|
||||
if (isset($update['message'])) {
|
||||
$message = $update['message'];
|
||||
$chatId = $message['chat']['id'];
|
||||
$userId = $message['from']['id'] ?? null;
|
||||
$text = $message['text'] ?? '';
|
||||
$username = $message['from']['first_name'] ?? 'Usuario';
|
||||
|
||||
registerTelegramUser($pdo, $message['from']);
|
||||
|
||||
if (!isExistingTelegramUser($pdo, $userId)) {
|
||||
sendWelcomeMessage($pdo, $sender, $chatId, $username);
|
||||
}
|
||||
|
||||
if (str_starts_with($text, '/')) {
|
||||
handleTelegramCommand($sender, $pdo, $chatId, $userId, $text, $username);
|
||||
} elseif (str_starts_with($text, '#')) {
|
||||
$command = ltrim($text, '#');
|
||||
sendTemplateByCommand($pdo, $sender, $chatId, $command);
|
||||
} else {
|
||||
handleTelegramMessage($pdo, $sender, $chatId, $userId, $text);
|
||||
}
|
||||
|
||||
} elseif (isset($update['callback_query'])) {
|
||||
$callbackQuery = $update['callback_query'];
|
||||
$callbackData = $callbackQuery['data'];
|
||||
$chatId = $callbackQuery['message']['chat']['id'];
|
||||
$messageId = $callbackQuery['message']['message_id'];
|
||||
|
||||
handleTelegramCallback($pdo, $sender, $translator, $chatId, $messageId, $callbackQuery['id'], $callbackData);
|
||||
}
|
||||
|
||||
} catch (Exception $e) {
|
||||
error_log("Telegram Webhook Error: " . $e->getMessage());
|
||||
}
|
||||
|
||||
function registerTelegramUser(PDO $pdo, array $user): void
|
||||
{
|
||||
$stmt = $pdo->prepare("
|
||||
INSERT INTO recipients (platform_id, name, type, platform, language_code, chat_mode)
|
||||
VALUES (?, ?, 'user', 'telegram', ?, 'bot')
|
||||
ON DUPLICATE KEY UPDATE name = VALUES(name)
|
||||
");
|
||||
|
||||
$name = trim(($user['first_name'] ?? '') . ' ' . ($user['last_name'] ?? ''));
|
||||
$languageCode = $user['language_code'] ?? 'es';
|
||||
|
||||
$stmt->execute([$user['id'], $name, $languageCode]);
|
||||
}
|
||||
|
||||
function handleAutoTranslation(PDO $pdo, Telegram\TelegramSender $sender, src\Translate $translator, int $chatId, string $text): void
|
||||
{
|
||||
$keyboard = getTelegramTranslationButtons($pdo, $text);
|
||||
|
||||
if (!empty($keyboard)) {
|
||||
$message = "🌐 <b>Traducciones disponibles:</b>\nHaz clic en una bandera para ver la traducción";
|
||||
$sender->sendMessage($chatId, $message, $keyboard);
|
||||
}
|
||||
}
|
||||
|
||||
function getTelegramTranslationButtons(PDO $pdo, string $text, ?string $excludeLang = null): ?array
|
||||
{
|
||||
try {
|
||||
$stmt = $pdo->query("SELECT language_code, flag_emoji FROM supported_languages WHERE is_active = 1");
|
||||
$activeLanguages = $stmt->fetchAll();
|
||||
|
||||
if (count($activeLanguages) <= 1) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$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 ($activeLanguages as $lang) {
|
||||
if ($excludeLang && $lang['language_code'] === $excludeLang) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$callbackData = "translate:" . $lang['language_code'] . ":" . $textHash;
|
||||
|
||||
$buttons[] = [
|
||||
'text' => $lang['flag_emoji'] . ' ' . strtoupper($lang['language_code']),
|
||||
'callback_data' => $callbackData
|
||||
];
|
||||
}
|
||||
|
||||
if (empty($buttons)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return ['inline_keyboard' => array_chunk($buttons, 3)];
|
||||
} catch (Exception $e) {
|
||||
error_log("getTelegramTranslationButtons error: " . $e->getMessage());
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
function handleTelegramCommand(Telegram\TelegramSender $sender, PDO $pdo, int $chatId, int $userId, string $command, string $username): void
|
||||
{
|
||||
$command = str_replace(['/', '@botname'], '', $command);
|
||||
$parts = explode(' ', $command);
|
||||
$cmd = strtolower($parts[0]);
|
||||
$args = array_slice($parts, 1);
|
||||
|
||||
switch ($cmd) {
|
||||
case 'start':
|
||||
$stmt = $pdo->query("SELECT * FROM telegram_bot_messages WHERE id = 1");
|
||||
$config = $stmt->fetch();
|
||||
|
||||
if ($config && $config['is_active']) {
|
||||
$text = str_replace('{user_name}', $username, $config['message_text']);
|
||||
$buttons = [];
|
||||
|
||||
if ($config['button_text'] && $config['group_invite_link']) {
|
||||
$buttons[] = [
|
||||
'text' => $config['button_text'],
|
||||
'url' => $config['group_invite_link']
|
||||
];
|
||||
}
|
||||
|
||||
$keyboard = !empty($buttons) ? $sender->createInlineKeyboard($buttons) : null;
|
||||
$sender->sendMessage($chatId, $text, $keyboard);
|
||||
} else {
|
||||
$sender->sendMessage($chatId, "¡Hola {$username}! 👋\n\nUsa /comandos para ver los comandos disponibles.");
|
||||
}
|
||||
break;
|
||||
|
||||
case 'comandos':
|
||||
$message = "📋 <b>Comandos disponibles:</b>\n\n";
|
||||
$message .= "/start - Iniciar bot\n";
|
||||
$message .= "/comandos - Ver comandos\n";
|
||||
$message .= "/setlang [código] - Establecer idioma\n";
|
||||
$message .= "/bienvenida - Mensaje de bienvenida\n";
|
||||
$message .= "/agente - Cambiar modo de chat\n";
|
||||
$message .= "#comando - Enviar plantilla\n";
|
||||
$message .= "Escribe cualquier texto para traducir automáticamente";
|
||||
|
||||
$sender->sendMessage($chatId, $message);
|
||||
break;
|
||||
|
||||
case 'setlang':
|
||||
$langCode = $args[0] ?? 'es';
|
||||
$stmt = $pdo->prepare("UPDATE recipients SET language_code = ? WHERE platform_id = ? AND platform = 'telegram'");
|
||||
$stmt->execute([$langCode, $chatId]);
|
||||
|
||||
$sender->sendMessage($chatId, "✅ Idioma actualizado a: " . strtoupper($langCode));
|
||||
break;
|
||||
|
||||
case 'bienvenida':
|
||||
$stmt = $pdo->query("SELECT * FROM telegram_bot_messages WHERE id = 1");
|
||||
$config = $stmt->fetch();
|
||||
|
||||
if ($config && $config['is_active']) {
|
||||
$text = str_replace('{user_name}', $username, $config['message_text']);
|
||||
|
||||
// Agregar botones de traducción (convertir HTML a texto plano)
|
||||
$plainText = html_entity_decode(strip_tags($text), ENT_QUOTES | ENT_HTML5, 'UTF-8');
|
||||
$plainText = preg_replace('/\s+/', ' ', $plainText);
|
||||
$translationButtons = getTelegramTranslationButtons($pdo, $plainText);
|
||||
|
||||
if (!empty($translationButtons)) {
|
||||
$keyboard = $sender->createInlineKeyboard(array_map(function($btn) {
|
||||
return ['text' => $btn['flag'], 'callback_data' => $btn['callback_data']];
|
||||
}, $translationButtons));
|
||||
$sender->sendMessage($chatId, $text, $keyboard);
|
||||
} else {
|
||||
$sender->sendMessage($chatId, $text);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 'agente':
|
||||
$buttons = [
|
||||
[
|
||||
'text' => '🤖 Seguir con Bot',
|
||||
'callback_data' => 'chat_mode:bot:' . $userId
|
||||
],
|
||||
[
|
||||
'text' => '💬 Platicar con IA',
|
||||
'callback_data' => 'chat_mode:ia:' . $userId
|
||||
]
|
||||
];
|
||||
|
||||
$keyboard = $sender->createInlineKeyboard($buttons);
|
||||
$sender->sendMessage($chatId, "🤖 <b>Selecciona un modo de chat:</b>", $keyboard);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
function handleTelegramMessage(PDO $pdo, Telegram\TelegramSender $sender, int $chatId, int $userId, string $text): void
|
||||
{
|
||||
$stmt = $pdo->prepare("SELECT chat_mode FROM recipients WHERE platform_id = ? AND platform = 'telegram'");
|
||||
$stmt->execute([$userId]);
|
||||
$recipient = $stmt->fetch();
|
||||
|
||||
if ($recipient && $recipient['chat_mode'] === 'ia') {
|
||||
sendToN8NIA($sender, $chatId, $userId, $text);
|
||||
} else {
|
||||
require_once __DIR__ . '/../../src/Translate.php';
|
||||
$translator = new src\Translate();
|
||||
handleAutoTranslation($pdo, $sender, $translator, $chatId, $text);
|
||||
}
|
||||
}
|
||||
|
||||
function sendToN8NIA(Telegram\TelegramSender $sender, int $chatId, int $userId, string $userMessage): void
|
||||
{
|
||||
$useN8n = $_ENV['N8N_IA_WEBHOOK_URL'] ?? getenv('N8N_IA_WEBHOOK_URL') ?? '';
|
||||
$useN8n = trim($useN8n, '"');
|
||||
|
||||
if (!empty($useN8n)) {
|
||||
$data = [
|
||||
'user_id' => (string)$userId,
|
||||
'message' => $userMessage
|
||||
];
|
||||
|
||||
$ch = curl_init($useN8n);
|
||||
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
|
||||
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_TIMEOUT, 30);
|
||||
|
||||
$response = curl_exec($ch);
|
||||
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
|
||||
$error = curl_error($ch);
|
||||
curl_close($ch);
|
||||
|
||||
if ($httpCode < 200 || $httpCode >= 300) {
|
||||
$sender->sendMessage($chatId, "❌ Error HTTP: $httpCode");
|
||||
error_log("N8N IA Telegram Error: HTTP $httpCode - $error");
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
require_once __DIR__ . '/../../src/IA/Agent.php';
|
||||
$agent = new \IA\Agent();
|
||||
|
||||
try {
|
||||
$response = $agent->generateResponse($userMessage);
|
||||
$sender->sendMessage($chatId, $response);
|
||||
} catch (\Exception $e) {
|
||||
$sender->sendMessage($chatId, "❌ Error: " . $e->getMessage());
|
||||
error_log("IA Agent Error: " . $e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
function sendTemplateByCommand(PDO $pdo, Telegram\TelegramSender $sender, int $chatId, string $command): void
|
||||
{
|
||||
$stmt = $pdo->prepare("SELECT * FROM recurrent_messages WHERE telegram_command = ?");
|
||||
$stmt->execute([$command]);
|
||||
$template = $stmt->fetch();
|
||||
|
||||
if ($template) {
|
||||
$converter = new Telegram\Converters\HtmlToTelegramHtmlConverter();
|
||||
$content = $converter->convert($template['message_content']);
|
||||
|
||||
$plainText = $template['message_content'];
|
||||
$plainText = preg_replace('/<br\s*\/?>/i', "\n", $plainText);
|
||||
$plainText = preg_replace('/<\/p>/i', "\n", $plainText);
|
||||
$plainText = preg_replace('/<p[^>]*>/i', '', $plainText);
|
||||
$plainText = strip_tags($plainText);
|
||||
$plainText = html_entity_decode($plainText, ENT_QUOTES | ENT_HTML5, 'UTF-8');
|
||||
$plainText = trim($plainText);
|
||||
|
||||
$translationButtons = getTelegramTranslationButtons($pdo, $plainText);
|
||||
|
||||
if ($translationButtons) {
|
||||
$sender->sendMessage($chatId, $content, $translationButtons);
|
||||
} else {
|
||||
$sender->sendMessage($chatId, $content);
|
||||
}
|
||||
} else {
|
||||
$sender->sendMessage($chatId, "❌ Plantilla no encontrada: #{$command}");
|
||||
}
|
||||
}
|
||||
|
||||
function handleTelegramCallback(PDO $pdo, Telegram\TelegramSender $sender, src\Translate $translator, int $chatId, int $messageId, string $callbackQueryId, string $callbackData): void
|
||||
{
|
||||
$parts = explode(':', $callbackData, 3);
|
||||
$action = $parts[0] ?? '';
|
||||
|
||||
if ($action === 'translate') {
|
||||
$targetLang = $parts[1] ?? 'es';
|
||||
$textHash = $parts[2] ?? '';
|
||||
|
||||
// Recuperar texto de la base de datos
|
||||
$stmt = $pdo->prepare("SELECT original_text FROM translation_cache WHERE text_hash = ?");
|
||||
$stmt->execute([$textHash]);
|
||||
$row = $stmt->fetch();
|
||||
|
||||
if (!$row) {
|
||||
$sender->answerCallbackQuery($callbackQueryId, "❌ Error: Texto no encontrado");
|
||||
return;
|
||||
}
|
||||
|
||||
$originalText = $row['original_text'];
|
||||
|
||||
if (empty($originalText)) {
|
||||
$sender->answerCallbackQuery($callbackQueryId, "❌ Error: No se pudo recuperar el texto");
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
// Obtener el idioma original
|
||||
$sourceLang = $translator->detectLanguage($originalText) ?? 'es';
|
||||
|
||||
// Traducir
|
||||
$translated = $translator->translate($originalText, $sourceLang, $targetLang);
|
||||
|
||||
if ($translated) {
|
||||
$sender->answerCallbackQuery($callbackQueryId, "", false);
|
||||
|
||||
$keyboard = getTelegramTranslationButtons($pdo, $originalText, $targetLang);
|
||||
|
||||
$sender->editMessageText($chatId, $messageId, "🌐 <b>Traducción (" . strtoupper($targetLang) . "):</b>\n\n" . $translated, $keyboard);
|
||||
} else {
|
||||
$sender->answerCallbackQuery($callbackQueryId, "❌ Error al traducir el mensaje", false);
|
||||
}
|
||||
} catch (Exception $e) {
|
||||
error_log("Callback translation error: " . $e->getMessage());
|
||||
$sender->answerCallbackQuery($callbackQueryId, "❌ Error en la traducción", false);
|
||||
}
|
||||
} elseif ($action === 'chat_mode') {
|
||||
$mode = $parts[1] ?? 'bot';
|
||||
$userId = $parts[2] ?? '';
|
||||
|
||||
if (empty($userId)) {
|
||||
$sender->answerCallbackQuery($callbackQueryId, "❌ Error: Usuario no identificado");
|
||||
return;
|
||||
}
|
||||
|
||||
$chatMode = ($mode === 'ia') ? 'ia' : 'bot';
|
||||
$stmt = $pdo->prepare("UPDATE recipients SET chat_mode = ? WHERE platform_id = ? AND platform = 'telegram'");
|
||||
$stmt->execute([$chatMode, $userId]);
|
||||
|
||||
if ($chatMode === 'ia') {
|
||||
$sender->answerCallbackQuery($callbackQueryId, "✅ Modo IA activado. Ahora puedes platicar con la IA.", false);
|
||||
$sender->sendMessage($chatId, "✅ <b>Modo IA activado.</b>\n\nAhora puedes platicar conmigo. Escribe cualquier cosa y la enviaré a la IA.");
|
||||
} else {
|
||||
$sender->answerCallbackQuery($callbackQueryId, "✅ Modo Bot activado.", false);
|
||||
$sender->sendMessage($chatId, "✅ <b>Modo Bot activado.</b>\n\nAhora puedes usar comandos como #comando y traducción.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function isExistingTelegramUser(PDO $pdo, int $userId): bool
|
||||
{
|
||||
$stmt = $pdo->prepare("SELECT id FROM recipients WHERE platform_id = ? AND platform = 'telegram'");
|
||||
$stmt->execute([$userId]);
|
||||
return $stmt->fetch() !== false;
|
||||
}
|
||||
|
||||
function sendWelcomeMessage(PDO $pdo, Telegram\TelegramSender $sender, int $chatId, string $username): void
|
||||
{
|
||||
$stmt = $pdo->query("SELECT * FROM telegram_bot_messages WHERE id = 1");
|
||||
$config = $stmt->fetch();
|
||||
|
||||
if ($config && $config['is_active']) {
|
||||
$text = str_replace('{user_name}', $username, $config['message_text']);
|
||||
$buttons = [];
|
||||
|
||||
if ($config['button_text'] && $config['group_invite_link']) {
|
||||
$buttons[] = [
|
||||
'text' => $config['button_text'],
|
||||
'url' => $config['group_invite_link']
|
||||
];
|
||||
}
|
||||
|
||||
$keyboard = !empty($buttons) ? $sender->createInlineKeyboard($buttons) : null;
|
||||
$sender->sendMessage($chatId, $text, $keyboard);
|
||||
} else {
|
||||
$sender->sendMessage($chatId, "¡Hola {$username}! 👋\n\nUsa /comandos para ver los comandos disponibles.");
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user