up
This commit is contained in:
+5
-73
@@ -165,54 +165,7 @@ class WhatsAppWebhook {
|
|||||||
$mimeType = $message['image']['mime_type'] ?? null;
|
$mimeType = $message['image']['mime_type'] ?? null;
|
||||||
$filename = $message['image']['filename'] ?? null;
|
$filename = $message['image']['filename'] ?? null;
|
||||||
|
|
||||||
// Intentar descargar y almacenar imagen localmente
|
|
||||||
try {
|
|
||||||
$ms = new MediaService();
|
|
||||||
$res = null;
|
|
||||||
if ($mediaUrl && preg_match('#^https?://#i', $mediaUrl)) {
|
|
||||||
// Si venía URL directa, descargar desde URL
|
|
||||||
$content = $ms->downloadUrl($mediaUrl);
|
|
||||||
if ($content !== false) {
|
|
||||||
$subdir = date('Y/m');
|
|
||||||
$dir = 'uploads/media/' . $subdir;
|
|
||||||
if (!is_dir(__DIR__ . '/../' . $dir)) mkdir(__DIR__ . '/../' . $dir, 0755, true);
|
|
||||||
$ext = $ms->extensionFromMime($mimeType) ?: pathinfo(parse_url($mediaUrl, PHP_URL_PATH), PATHINFO_EXTENSION) ?: 'jpg';
|
|
||||||
$fname = uniqid('m_') . '.' . $ext;
|
|
||||||
$path = __DIR__ . '/../' . $dir . '/' . $fname;
|
|
||||||
file_put_contents($path, $content);
|
|
||||||
$res = ['local_file' => $dir . '/' . $fname];
|
|
||||||
// crear thumb
|
|
||||||
if ($ms->isImageMime($mimeType)) {
|
|
||||||
$thumbPath = __DIR__ . '/../' . $dir . '/thumb_' . $fname . '.jpg';
|
|
||||||
if ($ms->createThumbnail($path, $thumbPath)) {
|
|
||||||
$res['local_thumb'] = $dir . '/thumb_' . $fname . '.jpg';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} elseif ($mediaUrl) {
|
|
||||||
// mediaUrl probablemente es media id -> usar fetchAndStoreFromGraph
|
|
||||||
$res = $ms->fetchAndStoreFromGraph($mediaUrl, date('Y/m'));
|
|
||||||
}
|
|
||||||
if ($res) {
|
|
||||||
$localFile = $res['local_file'] ?? null;
|
|
||||||
$localThumb = $res['local_thumb'] ?? null;
|
|
||||||
}
|
|
||||||
} catch (Exception $e) {
|
|
||||||
error_log('Media download failed: ' . $e->getMessage());
|
|
||||||
// Encolar para reintento si tenemos un media id (no descargar documentos aquí)
|
|
||||||
try {
|
|
||||||
if ($mediaUrl && !preg_match('#^https?://#i', $mediaUrl)) {
|
|
||||||
$this->db->insert('media_queue', [
|
|
||||||
'media_id' => $mediaUrl,
|
|
||||||
'subdir' => date('Y/m'),
|
|
||||||
'status' => 'pending',
|
|
||||||
'created_at' => date('Y-m-d H:i:s')
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
} catch (Exception $e2) {
|
|
||||||
error_log('Failed to enqueue media download: ' . $e2->getMessage());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
} elseif (isset($message['audio'])) {
|
} elseif (isset($message['audio'])) {
|
||||||
$messageType = 'audio';
|
$messageType = 'audio';
|
||||||
@@ -220,18 +173,7 @@ class WhatsAppWebhook {
|
|||||||
$mimeType = $message['audio']['mime_type'] ?? null;
|
$mimeType = $message['audio']['mime_type'] ?? null;
|
||||||
$filename = $message['audio']['filename'] ?? null;
|
$filename = $message['audio']['filename'] ?? null;
|
||||||
|
|
||||||
// Descargar audio y guardar local (opcional)
|
|
||||||
try {
|
|
||||||
$ms = new MediaService();
|
|
||||||
if ($mediaUrl && !preg_match('#^https?://#i', $mediaUrl)) {
|
|
||||||
$res = $ms->fetchAndStoreFromGraph($mediaUrl, date('Y/m'));
|
|
||||||
if ($res) {
|
|
||||||
$localFile = $res['local_file'] ?? null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (Exception $e) {
|
|
||||||
error_log('Audio download failed: ' . $e->getMessage());
|
|
||||||
}
|
|
||||||
|
|
||||||
} elseif (isset($message['video'])) {
|
} elseif (isset($message['video'])) {
|
||||||
$messageText = $message['video']['caption'] ?? '';
|
$messageText = $message['video']['caption'] ?? '';
|
||||||
@@ -240,18 +182,7 @@ class WhatsAppWebhook {
|
|||||||
$mimeType = $message['video']['mime_type'] ?? null;
|
$mimeType = $message['video']['mime_type'] ?? null;
|
||||||
$filename = $message['video']['filename'] ?? null;
|
$filename = $message['video']['filename'] ?? null;
|
||||||
|
|
||||||
// Descargar video y guardar local (opcional)
|
|
||||||
try {
|
|
||||||
$ms = new MediaService();
|
|
||||||
if ($mediaUrl && !preg_match('#^https?://#i', $mediaUrl)) {
|
|
||||||
$res = $ms->fetchAndStoreFromGraph($mediaUrl, date('Y/m'));
|
|
||||||
if ($res) {
|
|
||||||
$localFile = $res['local_file'] ?? null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (Exception $e) {
|
|
||||||
error_log('Video download failed: ' . $e->getMessage());
|
|
||||||
}
|
|
||||||
|
|
||||||
} elseif (isset($message['document'])) {
|
} elseif (isset($message['document'])) {
|
||||||
$messageText = $message['document']['filename'] ?? '';
|
$messageText = $message['document']['filename'] ?? '';
|
||||||
@@ -305,7 +236,8 @@ class WhatsAppWebhook {
|
|||||||
|
|
||||||
// Filtrar campos según columnas existentes para evitar errores en esquemas antiguos
|
// Filtrar campos según columnas existentes para evitar errores en esquemas antiguos
|
||||||
$saveData = $this->filterColumns('conversations', $saveData);
|
$saveData = $this->filterColumns('conversations', $saveData);
|
||||||
$this->saveMessage($saveData);
|
// Guardar mensaje y conservar el id de la conversación para posibles encolamientos
|
||||||
|
$conversationId = $this->saveMessage($saveData);
|
||||||
|
|
||||||
// Crear notificación para UI (nuevo mensaje entrante)
|
// Crear notificación para UI (nuevo mensaje entrante)
|
||||||
try {
|
try {
|
||||||
|
|||||||
@@ -72,6 +72,37 @@ class MediaService {
|
|||||||
return $result;
|
return $result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Nuevo: descargar y almacenar desde una URL directa
|
||||||
|
public function fetchAndStoreFromUrl($url, $subdir = '') {
|
||||||
|
$content = $this->downloadUrl($url);
|
||||||
|
if ($content === false) {
|
||||||
|
$content = $this->downloadUrl($url, ['Referer: https://graph.facebook.com']);
|
||||||
|
}
|
||||||
|
if ($content === false) throw new Exception('Failed to download media content from url ' . $url);
|
||||||
|
|
||||||
|
// intentar inferir mime
|
||||||
|
$mime = null;
|
||||||
|
$ext = pathinfo(parse_url($url, PHP_URL_PATH), PATHINFO_EXTENSION) ?: 'bin';
|
||||||
|
$dir = $this->uploadsDir . ($subdir ? '/' . trim($subdir, '/') : '');
|
||||||
|
if (!is_dir($dir)) mkdir($dir, 0755, true);
|
||||||
|
$filename = uniqid('m_') . '.' . $ext;
|
||||||
|
$fullPath = $dir . '/' . $filename;
|
||||||
|
file_put_contents($fullPath, $content);
|
||||||
|
|
||||||
|
$result = ['local_file' => 'uploads/media' . ($subdir ? '/' . trim($subdir, '/') : '') . '/' . $filename, 'mime_type' => $mime, 'size' => filesize($fullPath)];
|
||||||
|
|
||||||
|
// Si parece imagen, intentar crear thumb
|
||||||
|
if (preg_match('#jpe?g|png|gif#i', $ext)) {
|
||||||
|
$thumbPath = $dir . '/thumb_' . $filename . '.jpg';
|
||||||
|
$thumbRel = dirname($result['local_file']) . '/thumb_' . $filename . '.jpg';
|
||||||
|
if ($this->createThumbnail($fullPath, $thumbPath)) {
|
||||||
|
$result['local_thumb'] = $thumbRel;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
|
||||||
public function downloadUrl($url, $extraHeaders = []) {
|
public function downloadUrl($url, $extraHeaders = []) {
|
||||||
// Incluir Authorization Bearer si está configurado (necesario para algunos endpoints)
|
// Incluir Authorization Bearer si está configurado (necesario para algunos endpoints)
|
||||||
$authHeader = [];
|
$authHeader = [];
|
||||||
|
|||||||
@@ -0,0 +1,4 @@
|
|||||||
|
-- Add conversation reference and media_url to media_queue
|
||||||
|
ALTER TABLE media_queue
|
||||||
|
ADD COLUMN conversation_id INT NULL DEFAULT NULL,
|
||||||
|
ADD COLUMN media_url VARCHAR(1000) NULL DEFAULT NULL;
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
<?php
|
||||||
|
require_once __DIR__ . '/../config/config.php';
|
||||||
|
$db = Database::getInstance();
|
||||||
|
$rows = $db->fetchAll("SELECT id, message_type, media_url, filename, message_id, created_at FROM conversations WHERE (message_type IN ('image','video','audio')) AND (local_file IS NULL OR local_file = '') AND (media_url IS NOT NULL AND media_url != '') ORDER BY created_at DESC LIMIT 200");
|
||||||
|
$inserted = 0;
|
||||||
|
foreach ($rows as $r) {
|
||||||
|
$media = $r['media_url'];
|
||||||
|
$data = ['conversation_id' => $r['id'], 'subdir' => date('Y/m'), 'status' => 'pending', 'created_at' => date('Y-m-d H:i:s')];
|
||||||
|
if (preg_match('#^https?://#i', $media)) {
|
||||||
|
$data['media_url'] = $media;
|
||||||
|
} else {
|
||||||
|
// assume media id
|
||||||
|
$data['media_id'] = $media;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
$db->insert('media_queue', $data);
|
||||||
|
$inserted++;
|
||||||
|
} catch (Exception $e) {
|
||||||
|
// ignore duplicates
|
||||||
|
}
|
||||||
|
}
|
||||||
|
echo "Inserted: $inserted jobs\n";
|
||||||
@@ -10,9 +10,25 @@ $rows = $db->fetchAll('SELECT * FROM media_queue WHERE status = ? ORDER BY creat
|
|||||||
$ms = new MediaService();
|
$ms = new MediaService();
|
||||||
foreach ($rows as $r) {
|
foreach ($rows as $r) {
|
||||||
try {
|
try {
|
||||||
|
$res = null;
|
||||||
|
if (!empty($r['media_id'])) {
|
||||||
$res = $ms->fetchAndStoreFromGraph($r['media_id'], $r['subdir'] ?? date('Y/m'));
|
$res = $ms->fetchAndStoreFromGraph($r['media_id'], $r['subdir'] ?? date('Y/m'));
|
||||||
|
} elseif (!empty($r['media_url'])) {
|
||||||
|
$res = $ms->fetchAndStoreFromUrl($r['media_url'], $r['subdir'] ?? date('Y/m'));
|
||||||
|
}
|
||||||
|
|
||||||
if ($res) {
|
if ($res) {
|
||||||
|
// Actualizar fila media_queue
|
||||||
$db->update('media_queue', ['status' => 'done', 'result' => json_encode($res)], 'id = :id', ['id' => $r['id']]);
|
$db->update('media_queue', ['status' => 'done', 'result' => json_encode($res)], 'id = :id', ['id' => $r['id']]);
|
||||||
|
// Actualizar conversations si tenemos conversation_id
|
||||||
|
if (!empty($r['conversation_id'])) {
|
||||||
|
$update = [];
|
||||||
|
if (!empty($res['local_file'])) $update['local_file'] = $res['local_file'];
|
||||||
|
if (!empty($res['local_thumb'])) $update['local_thumb'] = $res['local_thumb'];
|
||||||
|
if (!empty($update)) {
|
||||||
|
$db->update('conversations', $update, 'id = :id', ['id' => $r['conversation_id']]);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} catch (Exception $e) {
|
} catch (Exception $e) {
|
||||||
$db->update('media_queue', ['status' => 'failed', 'result' => json_encode(['error' => $e->getMessage()])], 'id = :id', ['id' => $r['id']]);
|
$db->update('media_queue', ['status' => 'failed', 'result' => json_encode(['error' => $e->getMessage()])], 'id = :id', ['id' => $r['id']]);
|
||||||
|
|||||||
@@ -0,0 +1,5 @@
|
|||||||
|
<?php
|
||||||
|
require_once __DIR__ . '/../config/config.php';
|
||||||
|
$db = Database::getInstance();
|
||||||
|
$rows = $db->fetchAll('SELECT id,media_id,media_url,conversation_id,status,created_at FROM media_queue ORDER BY created_at ASC LIMIT 100');
|
||||||
|
echo json_encode($rows, JSON_PRETTY_PRINT) . "\n";
|
||||||
Reference in New Issue
Block a user