up
This commit is contained in:
+8
-4
@@ -62,7 +62,9 @@ RUN apk add --no-cache \
|
||||
libjpeg-turbo \
|
||||
libpng \
|
||||
mysql-client \
|
||||
redis
|
||||
redis \
|
||||
ffmpeg \
|
||||
openssl
|
||||
|
||||
# Copiar extensiones PHP desde builder
|
||||
COPY --from=builder /usr/local/lib/php/extensions/ /usr/local/lib/php/extensions/
|
||||
@@ -71,9 +73,10 @@ COPY --from=builder /usr/local/etc/php/conf.d/ /usr/local/etc/php/conf.d/
|
||||
# Copiar Composer desde builder
|
||||
COPY --from=composer:2 /usr/bin/composer /usr/bin/composer
|
||||
|
||||
# Crear usuario para la aplicación
|
||||
# Crear usuario para la aplicación y configurar grupos
|
||||
RUN addgroup -g 1000 -S www && \
|
||||
adduser -u 1000 -S www -G www
|
||||
adduser -u 1000 -S www -G www && \
|
||||
addgroup www nginx
|
||||
|
||||
# Configurar PHP
|
||||
COPY docker/php/php.ini /usr/local/etc/php/conf.d/custom.ini
|
||||
@@ -94,6 +97,7 @@ RUN mkdir -p \
|
||||
/var/www/html/uploads \
|
||||
/var/log/supervisor \
|
||||
/run/php \
|
||||
/etc/nginx/ssl \
|
||||
&& chown -R www:www /var/www/html \
|
||||
&& chown -R www:www /var/log/supervisor
|
||||
|
||||
@@ -118,7 +122,7 @@ HEALTHCHECK --interval=30s --timeout=5s --start-period=30s --retries=3 \
|
||||
CMD curl -f http://localhost/health.php || exit 1
|
||||
|
||||
# Exponer puertos
|
||||
EXPOSE 80 9000
|
||||
EXPOSE 80 443 9000
|
||||
|
||||
# Script de inicio
|
||||
COPY docker/entrypoint.sh /usr/local/bin/entrypoint.sh
|
||||
|
||||
@@ -14,6 +14,7 @@ RUN apk add --no-cache \
|
||||
bash \
|
||||
mysql-client \
|
||||
redis \
|
||||
ffmpeg \
|
||||
# Dependencias para XDebug y desarrollo
|
||||
autoconf \
|
||||
g++ \
|
||||
@@ -68,6 +69,8 @@ RUN { \
|
||||
echo 'upload_max_filesize = 100M'; \
|
||||
echo 'post_max_size = 100M'; \
|
||||
echo 'date.timezone = America/Bogota'; \
|
||||
# Habilitar shell_exec para conversión de audio
|
||||
echo 'disable_functions = '; \
|
||||
# Desactivar OPcache para hot-reload
|
||||
echo 'opcache.enable = 0'; \
|
||||
echo 'opcache.enable_cli = 0'; \
|
||||
|
||||
@@ -0,0 +1,57 @@
|
||||
## ✅ Problema del Error 500 Corregido
|
||||
|
||||
### 🐛 Causa del Error:
|
||||
Al pegar una imagen desde el portapapeles y enviarla, las peticiones `fetch` a los endpoints de API **NO estaban enviando las cookies de sesión**, causando que:
|
||||
1. `upload_media.php` rechazara la petición → Error 401
|
||||
2. Nginx devolviera error 500 por fallo en PHP
|
||||
|
||||
### 🔧 Solución Aplicada:
|
||||
|
||||
Agregué `credentials: 'same-origin'` a ambos fetch en `sendMediaMessage()`:
|
||||
|
||||
```javascript
|
||||
// 1. Upload del archivo
|
||||
const uploadResponse = await fetch('api/upload_media.php', {
|
||||
method: 'POST',
|
||||
credentials: 'same-origin', // ✅ Enviar cookies de sesión
|
||||
body: formData
|
||||
});
|
||||
|
||||
// 2. Envío del mensaje
|
||||
const sendResponse = await fetch('api/send_media_message.php', {
|
||||
method: 'POST',
|
||||
credentials: 'same-origin', // ✅ Enviar cookies de sesión
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({...})
|
||||
});
|
||||
```
|
||||
|
||||
### 📋 Cómo Funciona Ahora:
|
||||
|
||||
1. **Copias una imagen** (Ctrl+C o Cmd+C)
|
||||
2. **Haces click en el input de mensaje**
|
||||
3. **Pegas** (Ctrl+V o Cmd+V)
|
||||
4. ✅ Aparece el preview de la imagen
|
||||
5. ✅ Haces click en "Enviar"
|
||||
6. ✅ Se sube el archivo con autenticación correcta
|
||||
7. ✅ Se envía por WhatsApp
|
||||
8. ✅ Aparece en la conversación
|
||||
|
||||
### 🧪 Probar Ahora:
|
||||
|
||||
1. Recarga la página: http://localhost:8080/conversations.php
|
||||
2. Abre una conversación
|
||||
3. Copia una imagen desde cualquier lugar
|
||||
4. Haz click en el input de texto
|
||||
5. Presiona Ctrl+V (o Cmd+V en Mac)
|
||||
6. Debe aparecer el preview sin errores
|
||||
7. Haz click en enviar
|
||||
8. Debe enviarse correctamente
|
||||
|
||||
### 📝 Nota Técnica:
|
||||
|
||||
Por defecto, `fetch()` **NO envía cookies** a menos que especifiques:
|
||||
- `credentials: 'same-origin'` → Envía cookies al mismo dominio
|
||||
- `credentials: 'include'` → Envía cookies incluso en CORS
|
||||
|
||||
El endpoint `upload_media.php` usa `requireAuthentication()` que verifica la sesión en cookies, por eso fallaba antes.
|
||||
@@ -41,6 +41,8 @@ try {
|
||||
lm.content AS last_message,
|
||||
lm.direction AS direction,
|
||||
lm.message_type AS message_type,
|
||||
lm.local_file AS last_local_file,
|
||||
lm.local_thumb AS last_local_thumb,
|
||||
lm.created_at AS last_time,
|
||||
IFNULL(SUM(CASE WHEN c.direction = 'incoming' AND (c.is_read IS NULL OR c.is_read = 0) THEN 1 ELSE 0 END), 0) AS unread_count
|
||||
FROM users u
|
||||
@@ -86,6 +88,8 @@ try {
|
||||
'last_time' => $conv['last_time'] ?? null,
|
||||
'direction' => $conv['direction'] ?? 'incoming',
|
||||
'message_type' => $conv['message_type'] ?? 'text',
|
||||
'last_local_file' => $conv['last_local_file'] ?? null,
|
||||
'last_local_thumb' => $conv['last_local_thumb'] ?? null,
|
||||
'unread_count' => intval($conv['unread_count'] ?? 0),
|
||||
'bot_enabled' => isset($conv['bot_enabled']) ? (bool)$conv['bot_enabled'] : true,
|
||||
'on_hold' => isset($conv['on_hold']) ? (bool)$conv['on_hold'] : false,
|
||||
|
||||
@@ -59,6 +59,9 @@ try {
|
||||
c.content as content,
|
||||
c.message_id as message_id,
|
||||
c.media_url,
|
||||
c.local_file,
|
||||
c.filename,
|
||||
c.mime_type,
|
||||
u.phone_number as user_phone,
|
||||
c.direction as direction,
|
||||
c.message_type as message_type,
|
||||
@@ -145,6 +148,10 @@ try {
|
||||
message_text as content,
|
||||
direction,
|
||||
message_type,
|
||||
media_url,
|
||||
local_file,
|
||||
filename,
|
||||
mime_type,
|
||||
status,
|
||||
created_at
|
||||
FROM conversations
|
||||
@@ -179,7 +186,6 @@ try {
|
||||
'message_id' => $msg['message_id'] ?? null,
|
||||
'media_url' => null,
|
||||
'local_file' => $msg['local_file'] ?? null,
|
||||
'local_thumb' => $msg['local_thumb'] ?? null,
|
||||
'media_url_external' => $external,
|
||||
'filename' => $msg['filename'] ?? null,
|
||||
'mime_type' => $msg['mime_type'] ?? null,
|
||||
|
||||
@@ -355,6 +355,39 @@ try {
|
||||
// Datos base para insertar
|
||||
// content: nombre de archivo o caption (nunca JSON)
|
||||
// media_url: ID de WhatsApp si está disponible, sino la URL original
|
||||
// local_file: ruta relativa del archivo local si existe
|
||||
// local_thumb: miniatura (por ahora usar mismo archivo para imágenes/videos)
|
||||
|
||||
// Intentar determinar ruta local desde mediaUrl si no se definió antes
|
||||
if (!isset($localFilePath) && $mediaUrl) {
|
||||
try {
|
||||
error_log("send_media_message.php - Intentando extraer local_file desde mediaUrl: " . $mediaUrl);
|
||||
$parsedUrl = parse_url($mediaUrl);
|
||||
$path = $parsedUrl['path'] ?? '';
|
||||
error_log("send_media_message.php - Path extraído: " . $path);
|
||||
// Si la URL apunta a /uploads/, construir ruta local
|
||||
if (strpos($path, '/uploads/') === 0) {
|
||||
$uploadDir = __DIR__ . '/../uploads/';
|
||||
$filename_from_url = basename($path);
|
||||
$testPath = $uploadDir . $filename_from_url;
|
||||
error_log("send_media_message.php - Testeando archivo local: " . $testPath);
|
||||
if (file_exists($testPath)) {
|
||||
$localFilePath = $testPath;
|
||||
error_log("send_media_message.php - ✅ Archivo local encontrado: " . $localFilePath);
|
||||
} else {
|
||||
error_log("send_media_message.php - ❌ Archivo local NO existe: " . $testPath);
|
||||
}
|
||||
}
|
||||
} catch (Exception $e) {
|
||||
error_log("send_media_message.php - Error parseando mediaUrl: " . $e->getMessage());
|
||||
}
|
||||
} else {
|
||||
error_log("send_media_message.php - localFilePath ya definido o mediaUrl vacío. localFilePath=" . (isset($localFilePath) ? $localFilePath : 'NULL') . ", mediaUrl=" . ($mediaUrl ?? 'NULL'));
|
||||
}
|
||||
|
||||
$localFileRelative = (isset($localFilePath) && file_exists($localFilePath)) ? str_replace(__DIR__ . '/../', '', $localFilePath) : null;
|
||||
error_log("send_media_message.php - local_file relativo para BD: " . ($localFileRelative ?? 'NULL'));
|
||||
|
||||
$conversationData = [
|
||||
'user_id' => $user['id'],
|
||||
'message_id' => $sentMessageId,
|
||||
@@ -363,6 +396,9 @@ try {
|
||||
'content' => $content,
|
||||
'media_url' => isset($uploaded_media_id) ? $uploaded_media_id : $mediaUrl,
|
||||
'whatsapp_media_id' => $uploaded_media_id ?? null,
|
||||
'local_file' => $localFileRelative,
|
||||
'local_thumb' => ($mediaType === 'image' || $mediaType === 'video') ? $localFileRelative : null,
|
||||
'filename' => $filename ?? null,
|
||||
'status' => 'sent',
|
||||
'created_at' => date('Y-m-d H:i:s')
|
||||
];
|
||||
@@ -372,8 +408,10 @@ try {
|
||||
error_log(" - content: " . $content);
|
||||
error_log(" - media_url: " . ($conversationData['media_url'] ?? 'null'));
|
||||
error_log(" - whatsapp_media_id: " . ($conversationData['whatsapp_media_id'] ?? 'null'));
|
||||
error_log(" - local_file: " . ($conversationData['local_file'] ?? 'null'));
|
||||
error_log(" - local_thumb: " . ($conversationData['local_thumb'] ?? 'null'));
|
||||
error_log(" - media_type: " . $mediaType);
|
||||
smm_log("Saving to DB - content: {$content}, media_url: " . ($conversationData['media_url'] ?? 'null'));
|
||||
smm_log("Saving to DB - content: {$content}, media_url: " . ($conversationData['media_url'] ?? 'null') . ", local_file: " . ($conversationData['local_file'] ?? 'null') . ", local_thumb: " . ($conversationData['local_thumb'] ?? 'null'));
|
||||
|
||||
try {
|
||||
$db->insert('conversations', $conversationData);
|
||||
|
||||
@@ -60,3 +60,150 @@
|
||||
[2026-01-27 23:37:46] Send media by id response: {"messaging_product":"whatsapp","contacts":[{"input":"573022548060","wa_id":"573022548060"}],"messages":[{"id":"wamid.HBgMNTczMDIyNTQ4MDYwFQIAERgSNUU0NTQ4OURGNjYyQTkwQUI5AA=="}]}
|
||||
[2026-01-27 23:37:46] WhatsApp response (successful): {"messaging_product":"whatsapp","contacts":[{"input":"573022548060","wa_id":"573022548060"}],"messages":[{"id":"wamid.HBgMNTczMDIyNTQ4MDYwFQIAERgSNUU0NTQ4OURGNjYyQTkwQUI5AA=="}]}
|
||||
[2026-01-27 23:37:46] Saving to DB - content: survey.xlsx, media_url: 1374639530630158
|
||||
[2026-01-27 23:57:57] Raw input: {"recipient":"573168950803","media_url":"http://localhost:8080/uploads/media_69799753b67d83.17233125.webm","media_type":"audio","caption":null,"filename":"record_1769576272869.webm"}
|
||||
[2026-01-27 23:57:57] Input decoded: {"recipient":"573168950803","media_url":"http:\/\/localhost:8080\/uploads\/media_69799753b67d83.17233125.webm","media_type":"audio","caption":null,"filename":"record_1769576272869.webm"}
|
||||
[2026-01-27 23:58:23] Raw input: {"recipient":"573168950803","media_url":"http://localhost:8080/uploads/media_6979976dc5ecb2.11097928.xlsx","media_type":"document","caption":null,"filename":"survey.xlsx"}
|
||||
[2026-01-27 23:58:23] Input decoded: {"recipient":"573168950803","media_url":"http:\/\/localhost:8080\/uploads\/media_6979976dc5ecb2.11097928.xlsx","media_type":"document","caption":null,"filename":"survey.xlsx"}
|
||||
[2026-01-27 23:58:24] Upload result: {"id":"1873321179980667"}
|
||||
[2026-01-27 23:58:24] Media ID obtained: 1873321179980667
|
||||
[2026-01-27 23:58:25] Send media by id response: {"messaging_product":"whatsapp","contacts":[{"input":"573168950803","wa_id":"573168950803"}],"messages":[{"id":"wamid.HBgMNTczMTY4OTUwODAzFQIAERgSMEE2QzEyRUE2NTAxRjJDODQwAA=="}]}
|
||||
[2026-01-27 23:58:25] WhatsApp response (successful): {"messaging_product":"whatsapp","contacts":[{"input":"573168950803","wa_id":"573168950803"}],"messages":[{"id":"wamid.HBgMNTczMTY4OTUwODAzFQIAERgSMEE2QzEyRUE2NTAxRjJDODQwAA=="}]}
|
||||
[2026-01-27 23:58:25] Saving to DB - content: survey.xlsx, media_url: 1873321179980667
|
||||
[2026-01-28 00:02:10] Raw input: {"recipient":"573168950803","media_url":"http://localhost:8080/uploads/media_69799850802746.13854941.xlsx","media_type":"document","caption":null,"filename":"survey.xlsx"}
|
||||
[2026-01-28 00:02:10] Input decoded: {"recipient":"573168950803","media_url":"http:\/\/localhost:8080\/uploads\/media_69799850802746.13854941.xlsx","media_type":"document","caption":null,"filename":"survey.xlsx"}
|
||||
[2026-01-28 00:02:11] Upload result: {"id":"3100504000137603"}
|
||||
[2026-01-28 00:02:11] Media ID obtained: 3100504000137603
|
||||
[2026-01-28 00:02:12] Send media by id response: {"messaging_product":"whatsapp","contacts":[{"input":"573168950803","wa_id":"573168950803"}],"messages":[{"id":"wamid.HBgMNTczMTY4OTUwODAzFQIAERgSQzQ3RDRCQTFERThERjM2QTgxAA=="}]}
|
||||
[2026-01-28 00:02:12] WhatsApp response (successful): {"messaging_product":"whatsapp","contacts":[{"input":"573168950803","wa_id":"573168950803"}],"messages":[{"id":"wamid.HBgMNTczMTY4OTUwODAzFQIAERgSQzQ3RDRCQTFERThERjM2QTgxAA=="}]}
|
||||
[2026-01-28 00:02:13] Saving to DB - content: survey.xlsx, media_url: 3100504000137603
|
||||
[2026-01-28 00:06:46] Raw input: {"recipient":"573168950803","media_url":"http://localhost:8080/uploads/media_69799964926f58.72435045.jpg","media_type":"image","caption":null,"filename":"media-url.jpg"}
|
||||
[2026-01-28 00:06:46] Input decoded: {"recipient":"573168950803","media_url":"http:\/\/localhost:8080\/uploads\/media_69799964926f58.72435045.jpg","media_type":"image","caption":null,"filename":"media-url.jpg"}
|
||||
[2026-01-28 00:06:47] Upload result: {"id":"876668735219378"}
|
||||
[2026-01-28 00:06:47] Media ID obtained: 876668735219378
|
||||
[2026-01-28 00:06:48] Send media by id response: {"messaging_product":"whatsapp","contacts":[{"input":"573168950803","wa_id":"573168950803"}],"messages":[{"id":"wamid.HBgMNTczMTY4OTUwODAzFQIAERgSQjlGNzZFODBDOTg3REQxRDZDAA=="}]}
|
||||
[2026-01-28 00:06:48] WhatsApp response (successful): {"messaging_product":"whatsapp","contacts":[{"input":"573168950803","wa_id":"573168950803"}],"messages":[{"id":"wamid.HBgMNTczMTY4OTUwODAzFQIAERgSQjlGNzZFODBDOTg3REQxRDZDAA=="}]}
|
||||
[2026-01-28 00:06:48] Saving to DB - content: media-url.jpg, media_url: 876668735219378
|
||||
[2026-01-28 00:08:44] Raw input: {"recipient":"573168950803","media_url":"http://localhost:8080/uploads/media_697999dadb01c6.63157521.webm","media_type":"audio","caption":null,"filename":"record_1769576919723.webm"}
|
||||
[2026-01-28 00:08:44] Input decoded: {"recipient":"573168950803","media_url":"http:\/\/localhost:8080\/uploads\/media_697999dadb01c6.63157521.webm","media_type":"audio","caption":null,"filename":"record_1769576919723.webm"}
|
||||
[2026-01-28 00:14:59] Raw input: {"recipient":"573168950803","media_url":"http://localhost:8080/uploads/media_69799b51530038.79115661.webm","media_type":"audio","caption":null,"filename":"record_1769576919723.webm"}
|
||||
[2026-01-28 00:14:59] Input decoded: {"recipient":"573168950803","media_url":"http:\/\/localhost:8080\/uploads\/media_69799b51530038.79115661.webm","media_type":"audio","caption":null,"filename":"record_1769576919723.webm"}
|
||||
[2026-01-28 00:15:54] Raw input: {"recipient":"573168950803","media_url":"http://localhost:8080/uploads/media_69799b891e3c11.09600349.webm","media_type":"audio","caption":null,"filename":"record_1769577348725.webm"}
|
||||
[2026-01-28 00:15:54] Input decoded: {"recipient":"573168950803","media_url":"http:\/\/localhost:8080\/uploads\/media_69799b891e3c11.09600349.webm","media_type":"audio","caption":null,"filename":"record_1769577348725.webm"}
|
||||
[2026-01-28 00:17:05] Raw input: {"recipient":"573168950803","media_url":"http://localhost:8080/uploads/media_69799bcfb8b031.52674216.webm","media_type":"audio","caption":null,"filename":"record_1769577421621.webm"}
|
||||
[2026-01-28 00:17:05] Input decoded: {"recipient":"573168950803","media_url":"http:\/\/localhost:8080\/uploads\/media_69799bcfb8b031.52674216.webm","media_type":"audio","caption":null,"filename":"record_1769577421621.webm"}
|
||||
[2026-01-28 00:20:06] Raw input: {"recipient":"573168950803","media_url":"http://localhost:8080/uploads/media_69799c846ada20.81906873.webm","media_type":"audio","caption":null,"filename":"record_1769577601944.webm"}
|
||||
[2026-01-28 00:20:06] Input decoded: {"recipient":"573168950803","media_url":"http:\/\/localhost:8080\/uploads\/media_69799c846ada20.81906873.webm","media_type":"audio","caption":null,"filename":"record_1769577601944.webm"}
|
||||
[2026-01-28 00:21:20] Raw input: {"recipient":"573022548060","media_url":"http://localhost:8080/uploads/media_69799ccf1bb225.76804681.webm","media_type":"audio","caption":null,"filename":"record_1769577675811.webm"}
|
||||
[2026-01-28 00:21:20] Input decoded: {"recipient":"573022548060","media_url":"http:\/\/localhost:8080\/uploads\/media_69799ccf1bb225.76804681.webm","media_type":"audio","caption":null,"filename":"record_1769577675811.webm"}
|
||||
[2026-01-28 00:24:06] Raw input: {"recipient":"573168950803","media_url":"http://localhost:8080/uploads/media_69799d735ae469.91287547.ogg","media_type":"audio","caption":null,"filename":"record_1769577841134.webm"}
|
||||
[2026-01-28 00:24:06] Input decoded: {"recipient":"573168950803","media_url":"http:\/\/localhost:8080\/uploads\/media_69799d735ae469.91287547.ogg","media_type":"audio","caption":null,"filename":"record_1769577841134.webm"}
|
||||
[2026-01-28 00:24:07] Upload result: {"id":"903170332106418"}
|
||||
[2026-01-28 00:24:07] Media ID obtained: 903170332106418
|
||||
[2026-01-28 00:24:09] Send media by id response: {"messaging_product":"whatsapp","contacts":[{"input":"573168950803","wa_id":"573168950803"}],"messages":[{"id":"wamid.HBgMNTczMTY4OTUwODAzFQIAERgSMUU0QTg1RUMwMkE0OTUyMDM2AA=="}]}
|
||||
[2026-01-28 00:24:09] WhatsApp response (successful): {"messaging_product":"whatsapp","contacts":[{"input":"573168950803","wa_id":"573168950803"}],"messages":[{"id":"wamid.HBgMNTczMTY4OTUwODAzFQIAERgSMUU0QTg1RUMwMkE0OTUyMDM2AA=="}]}
|
||||
[2026-01-28 00:24:09] Saving to DB - content: record_1769577841134.webm, media_url: 903170332106418
|
||||
[2026-01-28 00:27:47] Raw input: {"recipient":"573168950803","media_url":"http://localhost:8080/uploads/media_69799e51c56f53.56537824.ogg","media_type":"audio","caption":null,"filename":"record_1769578062431.webm"}
|
||||
[2026-01-28 00:27:47] Input decoded: {"recipient":"573168950803","media_url":"http:\/\/localhost:8080\/uploads\/media_69799e51c56f53.56537824.ogg","media_type":"audio","caption":null,"filename":"record_1769578062431.webm"}
|
||||
[2026-01-28 00:27:48] Upload result: {"id":"2590254688014534"}
|
||||
[2026-01-28 00:27:49] Media ID obtained: 2590254688014534
|
||||
[2026-01-28 00:27:49] Send media by id response: {"messaging_product":"whatsapp","contacts":[{"input":"573168950803","wa_id":"573168950803"}],"messages":[{"id":"wamid.HBgMNTczMTY4OTUwODAzFQIAERgSNzkwNEYzQTdFQjkwNjQ1NzQ2AA=="}]}
|
||||
[2026-01-28 00:27:49] WhatsApp response (successful): {"messaging_product":"whatsapp","contacts":[{"input":"573168950803","wa_id":"573168950803"}],"messages":[{"id":"wamid.HBgMNTczMTY4OTUwODAzFQIAERgSNzkwNEYzQTdFQjkwNjQ1NzQ2AA=="}]}
|
||||
[2026-01-28 00:27:50] Saving to DB - content: record_1769578062431.webm, media_url: 2590254688014534, local_file: uploads/media_69799e51c56f53.56537824.ogg
|
||||
[2026-01-28 00:28:17] Raw input: {"recipient":"573168950803","media_url":"http://localhost:8080/uploads/media_69799e6fd863b7.25583571.jpg","media_type":"image","caption":null,"filename":"media-url.jpg"}
|
||||
[2026-01-28 00:28:17] Input decoded: {"recipient":"573168950803","media_url":"http:\/\/localhost:8080\/uploads\/media_69799e6fd863b7.25583571.jpg","media_type":"image","caption":null,"filename":"media-url.jpg"}
|
||||
[2026-01-28 00:28:19] Upload result: {"id":"1375898793748917"}
|
||||
[2026-01-28 00:28:19] Media ID obtained: 1375898793748917
|
||||
[2026-01-28 00:28:20] Send media by id response: {"messaging_product":"whatsapp","contacts":[{"input":"573168950803","wa_id":"573168950803"}],"messages":[{"id":"wamid.HBgMNTczMTY4OTUwODAzFQIAERgSREYxQzNCQUZGMTA3NEVBN0I5AA=="}]}
|
||||
[2026-01-28 00:28:20] WhatsApp response (successful): {"messaging_product":"whatsapp","contacts":[{"input":"573168950803","wa_id":"573168950803"}],"messages":[{"id":"wamid.HBgMNTczMTY4OTUwODAzFQIAERgSREYxQzNCQUZGMTA3NEVBN0I5AA=="}]}
|
||||
[2026-01-28 00:28:20] Saving to DB - content: media-url.jpg, media_url: 1375898793748917, local_file: uploads/media_69799e6fd863b7.25583571.jpg
|
||||
[2026-01-28 00:30:22] Raw input: {"recipient":"573168950803","media_url":"http://localhost:8080/uploads/media_69799eec0f6949.58637457.ogg","media_type":"audio","caption":null,"filename":"record_1769578217833.webm"}
|
||||
[2026-01-28 00:30:22] Input decoded: {"recipient":"573168950803","media_url":"http:\/\/localhost:8080\/uploads\/media_69799eec0f6949.58637457.ogg","media_type":"audio","caption":null,"filename":"record_1769578217833.webm"}
|
||||
[2026-01-28 00:30:23] Upload result: {"id":"882480841336174"}
|
||||
[2026-01-28 00:30:23] Media ID obtained: 882480841336174
|
||||
[2026-01-28 00:30:24] Send media by id response: {"messaging_product":"whatsapp","contacts":[{"input":"573168950803","wa_id":"573168950803"}],"messages":[{"id":"wamid.HBgMNTczMTY4OTUwODAzFQIAERgSQTJBMDQwMTU1REUxRTBBMjI5AA=="}]}
|
||||
[2026-01-28 00:30:24] WhatsApp response (successful): {"messaging_product":"whatsapp","contacts":[{"input":"573168950803","wa_id":"573168950803"}],"messages":[{"id":"wamid.HBgMNTczMTY4OTUwODAzFQIAERgSQTJBMDQwMTU1REUxRTBBMjI5AA=="}]}
|
||||
[2026-01-28 00:30:25] Saving to DB - content: record_1769578217833.webm, media_url: 882480841336174, local_file: uploads/media_69799eec0f6949.58637457.ogg
|
||||
[2026-01-28 00:30:42] Raw input: {"recipient":"573168950803","media_url":"http://localhost:8080/uploads/media_69799f01048d32.15387881.jpg","media_type":"image","caption":null,"filename":"media-url.jpg"}
|
||||
[2026-01-28 00:30:42] Input decoded: {"recipient":"573168950803","media_url":"http:\/\/localhost:8080\/uploads\/media_69799f01048d32.15387881.jpg","media_type":"image","caption":null,"filename":"media-url.jpg"}
|
||||
[2026-01-28 00:30:44] Upload result: {"id":"2331604630676404"}
|
||||
[2026-01-28 00:30:44] Media ID obtained: 2331604630676404
|
||||
[2026-01-28 00:30:44] Send media by id response: {"messaging_product":"whatsapp","contacts":[{"input":"573168950803","wa_id":"573168950803"}],"messages":[{"id":"wamid.HBgMNTczMTY4OTUwODAzFQIAERgSMzNCNjY1RUMyNTNCNEYzM0MwAA=="}]}
|
||||
[2026-01-28 00:30:44] WhatsApp response (successful): {"messaging_product":"whatsapp","contacts":[{"input":"573168950803","wa_id":"573168950803"}],"messages":[{"id":"wamid.HBgMNTczMTY4OTUwODAzFQIAERgSMzNCNjY1RUMyNTNCNEYzM0MwAA=="}]}
|
||||
[2026-01-28 00:30:45] Saving to DB - content: media-url.jpg, media_url: 2331604630676404, local_file: uploads/media_69799f01048d32.15387881.jpg
|
||||
[2026-01-28 00:31:45] Raw input: {"recipient":"573022548060","media_url":"http://localhost:8080/uploads/media_69799f4019c754.81016370.jpg","media_type":"image","caption":null,"filename":"media-url.jpg"}
|
||||
[2026-01-28 00:31:45] Input decoded: {"recipient":"573022548060","media_url":"http:\/\/localhost:8080\/uploads\/media_69799f4019c754.81016370.jpg","media_type":"image","caption":null,"filename":"media-url.jpg"}
|
||||
[2026-01-28 00:31:47] Upload result: {"id":"1983961412192518"}
|
||||
[2026-01-28 00:31:47] Media ID obtained: 1983961412192518
|
||||
[2026-01-28 00:31:48] Send media by id response: {"messaging_product":"whatsapp","contacts":[{"input":"573022548060","wa_id":"573022548060"}],"messages":[{"id":"wamid.HBgMNTczMDIyNTQ4MDYwFQIAERgSMDcxNUZFNDM1RDA2RkUyQzdGAA=="}]}
|
||||
[2026-01-28 00:31:48] WhatsApp response (successful): {"messaging_product":"whatsapp","contacts":[{"input":"573022548060","wa_id":"573022548060"}],"messages":[{"id":"wamid.HBgMNTczMDIyNTQ4MDYwFQIAERgSMDcxNUZFNDM1RDA2RkUyQzdGAA=="}]}
|
||||
[2026-01-28 00:31:48] Saving to DB - content: media-url.jpg, media_url: 1983961412192518, local_file: uploads/media_69799f4019c754.81016370.jpg
|
||||
[2026-01-28 00:36:06] Raw input: {"recipient":"573022548060","media_url":"http://localhost:8080/uploads/media_6979a044c17079.66378227.ogg","media_type":"audio","caption":null,"filename":"record_1769578561744.webm"}
|
||||
[2026-01-28 00:36:06] Input decoded: {"recipient":"573022548060","media_url":"http:\/\/localhost:8080\/uploads\/media_6979a044c17079.66378227.ogg","media_type":"audio","caption":null,"filename":"record_1769578561744.webm"}
|
||||
[2026-01-28 00:36:08] Upload result: {"id":"1551128883003002"}
|
||||
[2026-01-28 00:36:08] Media ID obtained: 1551128883003002
|
||||
[2026-01-28 00:36:09] Send media by id response: {"messaging_product":"whatsapp","contacts":[{"input":"573022548060","wa_id":"573022548060"}],"messages":[{"id":"wamid.HBgMNTczMDIyNTQ4MDYwFQIAERgSNjFFMjczMzcwMjdGRjZEMTIyAA=="}]}
|
||||
[2026-01-28 00:36:09] WhatsApp response (successful): {"messaging_product":"whatsapp","contacts":[{"input":"573022548060","wa_id":"573022548060"}],"messages":[{"id":"wamid.HBgMNTczMDIyNTQ4MDYwFQIAERgSNjFFMjczMzcwMjdGRjZEMTIyAA=="}]}
|
||||
[2026-01-28 00:36:09] Saving to DB - content: record_1769578561744.webm, media_url: 1551128883003002, local_file: uploads/media_6979a044c17079.66378227.ogg, local_thumb: null
|
||||
[2026-01-28 00:36:27] Raw input: {"recipient":"573022548060","media_url":"http://localhost:8080/uploads/media_6979a05981b3e3.76655176.jpg","media_type":"image","caption":null,"filename":"media-url.jpg"}
|
||||
[2026-01-28 00:36:27] Input decoded: {"recipient":"573022548060","media_url":"http:\/\/localhost:8080\/uploads\/media_6979a05981b3e3.76655176.jpg","media_type":"image","caption":null,"filename":"media-url.jpg"}
|
||||
[2026-01-28 00:36:28] Upload result: {"id":"3480062748838248"}
|
||||
[2026-01-28 00:36:28] Media ID obtained: 3480062748838248
|
||||
[2026-01-28 00:36:29] Send media by id response: {"messaging_product":"whatsapp","contacts":[{"input":"573022548060","wa_id":"573022548060"}],"messages":[{"id":"wamid.HBgMNTczMDIyNTQ4MDYwFQIAERgSRDM2RDA3ODc3RTBBMkU2OTRDAA=="}]}
|
||||
[2026-01-28 00:36:29] WhatsApp response (successful): {"messaging_product":"whatsapp","contacts":[{"input":"573022548060","wa_id":"573022548060"}],"messages":[{"id":"wamid.HBgMNTczMDIyNTQ4MDYwFQIAERgSRDM2RDA3ODc3RTBBMkU2OTRDAA=="}]}
|
||||
[2026-01-28 00:36:29] Saving to DB - content: media-url.jpg, media_url: 3480062748838248, local_file: uploads/media_6979a05981b3e3.76655176.jpg, local_thumb: uploads/media_6979a05981b3e3.76655176.jpg
|
||||
[2026-01-28 00:47:02] Raw input: {"recipient":"573022548060","media_url":"http://localhost:8080/uploads/media_6979a2d407f105.12184484.jpg","media_type":"image","caption":null,"filename":"media-url.jpg"}
|
||||
[2026-01-28 00:47:02] Input decoded: {"recipient":"573022548060","media_url":"http:\/\/localhost:8080\/uploads\/media_6979a2d407f105.12184484.jpg","media_type":"image","caption":null,"filename":"media-url.jpg"}
|
||||
[2026-01-28 00:47:03] Upload result: {"id":"1953117515284557"}
|
||||
[2026-01-28 00:47:03] Media ID obtained: 1953117515284557
|
||||
[2026-01-28 00:47:04] Send media by id response: {"messaging_product":"whatsapp","contacts":[{"input":"573022548060","wa_id":"573022548060"}],"messages":[{"id":"wamid.HBgMNTczMDIyNTQ4MDYwFQIAERgSRTNCREM3QzczMDkzRDA1MzJEAA=="}]}
|
||||
[2026-01-28 00:47:04] WhatsApp response (successful): {"messaging_product":"whatsapp","contacts":[{"input":"573022548060","wa_id":"573022548060"}],"messages":[{"id":"wamid.HBgMNTczMDIyNTQ4MDYwFQIAERgSRTNCREM3QzczMDkzRDA1MzJEAA=="}]}
|
||||
[2026-01-28 00:47:05] Saving to DB - content: media-url.jpg, media_url: 1953117515284557, local_file: uploads/media_6979a2d407f105.12184484.jpg, local_thumb: uploads/media_6979a2d407f105.12184484.jpg
|
||||
[2026-01-28 00:51:04] Raw input: {"recipient":"573022548060","media_url":"http://localhost:8080/uploads/media_6979a3c5b236e8.04274010.ogg","media_type":"audio","caption":null,"filename":"record_1769579459198.webm"}
|
||||
[2026-01-28 00:51:04] Input decoded: {"recipient":"573022548060","media_url":"http:\/\/localhost:8080\/uploads\/media_6979a3c5b236e8.04274010.ogg","media_type":"audio","caption":null,"filename":"record_1769579459198.webm"}
|
||||
[2026-01-28 00:51:05] Upload result: {"id":"893454973089562"}
|
||||
[2026-01-28 00:51:05] Media ID obtained: 893454973089562
|
||||
[2026-01-28 00:51:06] Send media by id response: {"messaging_product":"whatsapp","contacts":[{"input":"573022548060","wa_id":"573022548060"}],"messages":[{"id":"wamid.HBgMNTczMDIyNTQ4MDYwFQIAERgSQUYzRjE5QjE3OUE3OEIwQzlFAA=="}]}
|
||||
[2026-01-28 00:51:06] WhatsApp response (successful): {"messaging_product":"whatsapp","contacts":[{"input":"573022548060","wa_id":"573022548060"}],"messages":[{"id":"wamid.HBgMNTczMDIyNTQ4MDYwFQIAERgSQUYzRjE5QjE3OUE3OEIwQzlFAA=="}]}
|
||||
[2026-01-28 00:51:06] Saving to DB - content: record_1769579459198.webm, media_url: 893454973089562, local_file: uploads/media_6979a3c5b236e8.04274010.ogg, local_thumb: null
|
||||
[2026-01-28 00:54:15] Raw input: {"recipient":"573022548060","media_url":"http://localhost:8080/uploads/media_6979a485787858.65742730.ogg","media_type":"audio","caption":null,"filename":"record_1769579651401.webm"}
|
||||
[2026-01-28 00:54:15] Input decoded: {"recipient":"573022548060","media_url":"http:\/\/localhost:8080\/uploads\/media_6979a485787858.65742730.ogg","media_type":"audio","caption":null,"filename":"record_1769579651401.webm"}
|
||||
[2026-01-28 00:54:17] Upload result: {"id":"759892943831328"}
|
||||
[2026-01-28 00:54:17] Media ID obtained: 759892943831328
|
||||
[2026-01-28 00:54:18] Send media by id response: {"messaging_product":"whatsapp","contacts":[{"input":"573022548060","wa_id":"573022548060"}],"messages":[{"id":"wamid.HBgMNTczMDIyNTQ4MDYwFQIAERgSODM5NEYwRDc2NjMxQUFEMzc2AA=="}]}
|
||||
[2026-01-28 00:54:18] WhatsApp response (successful): {"messaging_product":"whatsapp","contacts":[{"input":"573022548060","wa_id":"573022548060"}],"messages":[{"id":"wamid.HBgMNTczMDIyNTQ4MDYwFQIAERgSODM5NEYwRDc2NjMxQUFEMzc2AA=="}]}
|
||||
[2026-01-28 00:54:18] Saving to DB - content: record_1769579651401.webm, media_url: 759892943831328, local_file: uploads/media_6979a485787858.65742730.ogg, local_thumb: null
|
||||
[2026-01-28 00:59:18] Raw input: {"recipient":"573022548060","media_url":"http://localhost:8080/uploads/media_6979a5b4690f83.69035164.ogg","media_type":"audio","caption":null,"filename":"record_1769579952844.webm"}
|
||||
[2026-01-28 00:59:18] Input decoded: {"recipient":"573022548060","media_url":"http:\/\/localhost:8080\/uploads\/media_6979a5b4690f83.69035164.ogg","media_type":"audio","caption":null,"filename":"record_1769579952844.webm"}
|
||||
[2026-01-28 00:59:19] Upload result: {"id":"1334972502008596"}
|
||||
[2026-01-28 00:59:19] Media ID obtained: 1334972502008596
|
||||
[2026-01-28 00:59:20] Send media by id response: {"messaging_product":"whatsapp","contacts":[{"input":"573022548060","wa_id":"573022548060"}],"messages":[{"id":"wamid.HBgMNTczMDIyNTQ4MDYwFQIAERgSRTgyNEZEN0EwOTgzODI3RTlBAA=="}]}
|
||||
[2026-01-28 00:59:20] WhatsApp response (successful): {"messaging_product":"whatsapp","contacts":[{"input":"573022548060","wa_id":"573022548060"}],"messages":[{"id":"wamid.HBgMNTczMDIyNTQ4MDYwFQIAERgSRTgyNEZEN0EwOTgzODI3RTlBAA=="}]}
|
||||
[2026-01-28 00:59:21] Saving to DB - content: record_1769579952844.webm, media_url: 1334972502008596, local_file: uploads/media_6979a5b4690f83.69035164.ogg, local_thumb: null
|
||||
[2026-01-28 01:16:06] Raw input: {"recipient":"573022548060","media_url":"http://localhost:8080/uploads/media_6979a9a3d39a72.62917885.ogg","media_type":"audio","caption":null,"filename":"record_1769580961330.webm"}
|
||||
[2026-01-28 01:16:06] Input decoded: {"recipient":"573022548060","media_url":"http:\/\/localhost:8080\/uploads\/media_6979a9a3d39a72.62917885.ogg","media_type":"audio","caption":null,"filename":"record_1769580961330.webm"}
|
||||
[2026-01-28 01:16:07] Upload result: {"id":"1601261651067176"}
|
||||
[2026-01-28 01:16:07] Media ID obtained: 1601261651067176
|
||||
[2026-01-28 01:16:08] Send media by id response: {"messaging_product":"whatsapp","contacts":[{"input":"573022548060","wa_id":"573022548060"}],"messages":[{"id":"wamid.HBgMNTczMDIyNTQ4MDYwFQIAERgSNEJDQ0YzQUZENTU4RjVERDI5AA=="}]}
|
||||
[2026-01-28 01:16:08] WhatsApp response (successful): {"messaging_product":"whatsapp","contacts":[{"input":"573022548060","wa_id":"573022548060"}],"messages":[{"id":"wamid.HBgMNTczMDIyNTQ4MDYwFQIAERgSNEJDQ0YzQUZENTU4RjVERDI5AA=="}]}
|
||||
[2026-01-28 01:16:08] Saving to DB - content: record_1769580961330.webm, media_url: 1601261651067176, local_file: uploads/media_6979a9a3d39a72.62917885.ogg, local_thumb: null
|
||||
[2026-01-28 01:25:23] Raw input: {"recipient":"573022548060","media_url":"http://localhost:8080/uploads/media_6979abd12b8131.97353205.ogg","media_type":"audio","caption":null,"filename":"record_1769581518627.webm"}
|
||||
[2026-01-28 01:25:23] Input decoded: {"recipient":"573022548060","media_url":"http:\/\/localhost:8080\/uploads\/media_6979abd12b8131.97353205.ogg","media_type":"audio","caption":null,"filename":"record_1769581518627.webm"}
|
||||
[2026-01-28 01:25:24] Upload result: {"id":"1043532494648003"}
|
||||
[2026-01-28 01:25:24] Media ID obtained: 1043532494648003
|
||||
[2026-01-28 01:25:25] Send media by id response: {"messaging_product":"whatsapp","contacts":[{"input":"573022548060","wa_id":"573022548060"}],"messages":[{"id":"wamid.HBgMNTczMDIyNTQ4MDYwFQIAERgSMDE3NzA2RUU4QTcyMDYyQzZFAA=="}]}
|
||||
[2026-01-28 01:25:25] WhatsApp response (successful): {"messaging_product":"whatsapp","contacts":[{"input":"573022548060","wa_id":"573022548060"}],"messages":[{"id":"wamid.HBgMNTczMDIyNTQ4MDYwFQIAERgSMDE3NzA2RUU4QTcyMDYyQzZFAA=="}]}
|
||||
[2026-01-28 01:25:26] Saving to DB - content: record_1769581518627.webm, media_url: 1043532494648003, local_file: uploads/media_6979abd12b8131.97353205.ogg, local_thumb: null
|
||||
[2026-01-28 01:49:36] Raw input: {"recipient":"573022548060","media_url":"http://localhost:8080/uploads/media_6979b17f07a0f4.63241756.mp4","media_type":"video","caption":null,"filename":"WhatsApp Video 2026-01-22 at 10.53.30.mp4"}
|
||||
[2026-01-28 01:49:36] Input decoded: {"recipient":"573022548060","media_url":"http:\/\/localhost:8080\/uploads\/media_6979b17f07a0f4.63241756.mp4","media_type":"video","caption":null,"filename":"WhatsApp Video 2026-01-22 at 10.53.30.mp4"}
|
||||
[2026-01-28 01:49:38] Upload result: {"id":"2079449202816102"}
|
||||
[2026-01-28 01:49:38] Media ID obtained: 2079449202816102
|
||||
[2026-01-28 01:49:39] Send media by id response: {"messaging_product":"whatsapp","contacts":[{"input":"573022548060","wa_id":"573022548060"}],"messages":[{"id":"wamid.HBgMNTczMDIyNTQ4MDYwFQIAERgSMjNGNDM0MzkxM0QxNURBODExAA=="}]}
|
||||
[2026-01-28 01:49:39] WhatsApp response (successful): {"messaging_product":"whatsapp","contacts":[{"input":"573022548060","wa_id":"573022548060"}],"messages":[{"id":"wamid.HBgMNTczMDIyNTQ4MDYwFQIAERgSMjNGNDM0MzkxM0QxNURBODExAA=="}]}
|
||||
[2026-01-28 01:49:39] Saving to DB - content: WhatsApp Video 2026-01-22 at 10.53.30.mp4, media_url: 2079449202816102, local_file: uploads/media_6979b17f07a0f4.63241756.mp4, local_thumb: uploads/media_6979b17f07a0f4.63241756.mp4
|
||||
[2026-01-28 01:51:40] Raw input: {"recipient":"573022548060","media_url":"http://localhost:8080/uploads/media_6979b1fb55d5a8.95537352.png","media_type":"image","caption":null,"filename":"image.png"}
|
||||
[2026-01-28 01:51:40] Input decoded: {"recipient":"573022548060","media_url":"http:\/\/localhost:8080\/uploads\/media_6979b1fb55d5a8.95537352.png","media_type":"image","caption":null,"filename":"image.png"}
|
||||
[2026-01-28 01:51:42] Upload result: {"id":"928500006280411"}
|
||||
[2026-01-28 01:51:42] Media ID obtained: 928500006280411
|
||||
[2026-01-28 01:51:43] Send media by id response: {"messaging_product":"whatsapp","contacts":[{"input":"573022548060","wa_id":"573022548060"}],"messages":[{"id":"wamid.HBgMNTczMDIyNTQ4MDYwFQIAERgSMUM4NTYwOTc0QjBCQUJGQjBDAA=="}]}
|
||||
[2026-01-28 01:51:43] WhatsApp response (successful): {"messaging_product":"whatsapp","contacts":[{"input":"573022548060","wa_id":"573022548060"}],"messages":[{"id":"wamid.HBgMNTczMDIyNTQ4MDYwFQIAERgSMUM4NTYwOTc0QjBCQUJGQjBDAA=="}]}
|
||||
[2026-01-28 01:51:43] Saving to DB - content: image.png, media_url: 928500006280411, local_file: uploads/media_6979b1fb55d5a8.95537352.png, local_thumb: uploads/media_6979b1fb55d5a8.95537352.png
|
||||
|
||||
+32
-18
@@ -63,9 +63,9 @@ try {
|
||||
$allowedTypes = [
|
||||
// Imágenes
|
||||
'image/jpeg', 'image/jpg', 'image/png', 'image/webp',
|
||||
// Videos
|
||||
'video/mp4', 'video/3gpp', 'video/quicktime',
|
||||
// Audios
|
||||
// Videos (webm será convertido a mp4)
|
||||
'video/mp4', 'video/3gpp', 'video/quicktime', 'video/webm',
|
||||
// Audios (webm será convertido a ogg)
|
||||
'audio/aac', 'audio/mp3', 'audio/mpeg', 'audio/ogg', 'audio/amr', 'audio/webm',
|
||||
// Documentos
|
||||
'application/pdf',
|
||||
@@ -97,38 +97,52 @@ try {
|
||||
throw new Exception('Error al guardar el archivo en el servidor');
|
||||
}
|
||||
|
||||
// Si es audio WebM, intentar convertir a OGG/Opus (formatos más compatibles con WhatsApp)
|
||||
// Convertir archivos WebM (audio y video) a formatos compatibles con WhatsApp
|
||||
$converted = false;
|
||||
$conversion_error = null;
|
||||
if (strpos($fileType, 'audio/webm') === 0) {
|
||||
|
||||
if (strpos($fileType, 'audio/webm') === 0 || strpos($fileType, 'video/webm') === 0) {
|
||||
// Evitar fatal si shell_exec está deshabilitado en el hosting
|
||||
if (function_exists('shell_exec')) {
|
||||
$ffmpeg = trim(@shell_exec('which ffmpeg 2>/dev/null'));
|
||||
if ($ffmpeg) {
|
||||
try {
|
||||
$convertedName = uniqid('media_', true) . '.ogg';
|
||||
$convertedPath = $uploadDir . $convertedName;
|
||||
// Convertir a Opus (bitrate moderado). Forzamos formato OGG, mono 48kHz y mapeamos la primera pista de audio.
|
||||
// Esto ayuda a evitar contenedores/streams extra que pueden causar que el archivo suene como ruido.
|
||||
$cmd = escapeshellcmd($ffmpeg) . ' -y -i ' . escapeshellarg($uploadPath) . ' -map 0:a:0 -c:a libopus -b:a 64k -vbr on -ar 48000 -ac 1 -f ogg ' . escapeshellarg($convertedPath) . ' 2>&1';
|
||||
if (strpos($fileType, 'audio/webm') === 0) {
|
||||
// Audio WebM -> OGG/Opus
|
||||
$convertedName = uniqid('media_', true) . '.ogg';
|
||||
$convertedPath = $uploadDir . $convertedName;
|
||||
// Convertir a Opus (bitrate moderado). Forzamos formato OGG, mono 48kHz y mapeamos la primera pista de audio.
|
||||
$cmd = escapeshellcmd($ffmpeg) . ' -y -i ' . escapeshellarg($uploadPath) . ' -map 0:a:0 -c:a libopus -b:a 64k -vbr on -ar 48000 -ac 1 -f ogg ' . escapeshellarg($convertedPath) . ' 2>&1';
|
||||
$newType = 'audio/ogg';
|
||||
$logType = 'Audio';
|
||||
} else {
|
||||
// Video WebM -> MP4
|
||||
$convertedName = uniqid('media_', true) . '.mp4';
|
||||
$convertedPath = $uploadDir . $convertedName;
|
||||
// Convertir a MP4 con H.264 (compatible con WhatsApp)
|
||||
$cmd = escapeshellcmd($ffmpeg) . ' -y -i ' . escapeshellarg($uploadPath) . ' -c:v libx264 -preset fast -crf 23 -c:a aac -b:a 128k -movflags +faststart ' . escapeshellarg($convertedPath) . ' 2>&1';
|
||||
$newType = 'video/mp4';
|
||||
$logType = 'Video';
|
||||
}
|
||||
|
||||
$out = @shell_exec($cmd);
|
||||
// Añadir comprobación diagnóstica con "ffmpeg -i" sobre el archivo convertido para registrar detalles del stream
|
||||
// Añadir comprobación diagnóstica con "ffmpeg -i" sobre el archivo convertido
|
||||
$probe = @shell_exec(escapeshellcmd($ffmpeg) . ' -i ' . escapeshellarg($convertedPath) . ' 2>&1');
|
||||
|
||||
if (file_exists($convertedPath) && filesize($convertedPath) > 0) {
|
||||
// Reemplazar archivo original por el convertido
|
||||
@unlink($uploadPath);
|
||||
$uploadPath = $convertedPath;
|
||||
$uniqueName = $convertedName;
|
||||
$fileType = 'audio/ogg';
|
||||
$fileType = $newType;
|
||||
$converted = true;
|
||||
error_log('upload_media.php - Audio convertido a OGG/Opus: ' . $convertedName);
|
||||
error_log("upload_media.php - $logType convertido: $convertedName");
|
||||
error_log('upload_media.php - ffmpeg output: ' . substr($out ?: '', 0, 2000));
|
||||
error_log('upload_media.php - ffmpeg probe:
|
||||
' . substr($probe ?: '', 0, 2000));
|
||||
error_log('upload_media.php - ffmpeg probe: ' . substr($probe ?: '', 0, 2000));
|
||||
} else {
|
||||
$conversion_error = 'Conversion failed or no output';
|
||||
error_log('upload_media.php - Falló conversión con ffmpeg. Output: ' . substr($out ?: '', 0, 2000));
|
||||
error_log('upload_media.php - ffmpeg probe after failure:\n' . substr($probe ?: '', 0, 2000));
|
||||
error_log('upload_media.php - ffmpeg probe after failure: ' . substr($probe ?: '', 0, 2000));
|
||||
}
|
||||
} catch (Exception $ex) {
|
||||
$conversion_error = 'Conversion exception: ' . $ex->getMessage();
|
||||
@@ -136,11 +150,11 @@ try {
|
||||
}
|
||||
} else {
|
||||
$conversion_error = 'ffmpeg not found';
|
||||
error_log('upload_media.php - ffmpeg no encontrado, no se puede convertir audio/webm.');
|
||||
error_log('upload_media.php - ffmpeg no encontrado, no se puede convertir webm.');
|
||||
}
|
||||
} else {
|
||||
$conversion_error = 'shell_exec disabled';
|
||||
error_log('upload_media.php - shell_exec disabled, no se puede convertir audio/webm.');
|
||||
error_log('upload_media.php - shell_exec disabled, no se puede convertir webm.');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -103,3 +103,160 @@
|
||||
[2026-01-27 23:46:42] Graph API request to https://graph.facebook.com/v22.0/1217156256734654
|
||||
[2026-01-27 23:46:42] Proxying Facebook media URL with Authorization to https://lookaside.fbsbx.com/whatsapp_business/attachments/?mid=1217156256734654&source=getMedia&ext=1769575902&hash=ARlgJj9uEQBbCft9SWvCsd7Muroo_d46iIYJwmdSwrQWLw
|
||||
[2026-01-27 23:46:42] Resolved media URL from Graph for mid 2371342336638440: https://lookaside.fbsbx.com/whatsapp_business/attachments/?mid=2371342336638440&source=getMedia&ext=1769575902&hash=ARmC7xUghrqeNvaMeZgme9RMrbd771C1nty9RLOqJVItWA
|
||||
[2026-01-28 00:02:21] Request: GET /api/version/media-url.php?id=3100504000137603&download=1 GET:{"id":"3100504000137603","download":"1"} POST:[]
|
||||
[2026-01-28 00:02:21] Graph API request to https://graph.facebook.com/v22.0/3100504000137603
|
||||
[2026-01-28 00:12:36] Request: GET /api/version/media-url.php?id=876668735219378 GET:{"id":"876668735219378"} POST:[]
|
||||
[2026-01-28 00:12:36] Graph API request to https://graph.facebook.com/v22.0/876668735219378
|
||||
[2026-01-28 00:12:36] Proxying Facebook media URL with Authorization to https://lookaside.fbsbx.com/whatsapp_business/attachments/?mid=876668735219378&source=getMedia&ext=1769577456&hash=ARmwFAN3qFOa9P44SrNAZBwNzLXLvix1Q6GCMlOZFsqrzA
|
||||
[2026-01-28 00:21:12] Request: GET /api/version/media-url.php?id=1217156256734654 GET:{"id":"1217156256734654"} POST:[]
|
||||
[2026-01-28 00:21:12] Graph API request to https://graph.facebook.com/v22.0/1217156256734654
|
||||
[2026-01-28 00:21:12] Request: GET /api/version/media-url.php?url=https%3A%2F%2Flookaside.fbsbx.com%2Fwhatsapp_business%2Fattachments%2F%3Fmid%3D2371342336638440%26source%3Dwebhook%26ext%3D1769575796%26hash%3DARndVKdw1p0CCx3_DpTblR2aOVkb_W5mbTqGFPSOK77cjA GET:{"url":"https:\/\/lookaside.fbsbx.com\/whatsapp_business\/attachments\/?mid=2371342336638440&source=webhook&ext=1769575796&hash=ARndVKdw1p0CCx3_DpTblR2aOVkb_W5mbTqGFPSOK77cjA"} POST:[]
|
||||
[2026-01-28 00:21:12] Proxying Facebook media URL with Authorization to https://lookaside.fbsbx.com/whatsapp_business/attachments/?mid=1217156256734654&source=getMedia&ext=1769577972&hash=ARmoanU8Nd36LwQ6xNz7eG63SBVvGepjczzi4M--a98BDg
|
||||
[2026-01-28 00:21:12] Resolved media URL from Graph for mid 2371342336638440: https://lookaside.fbsbx.com/whatsapp_business/attachments/?mid=2371342336638440&source=getMedia&ext=1769577972&hash=ARl9BUAyWrmYag5aPXEyUWVVcM1w-zbjTOpuX5j7YfzG4A
|
||||
[2026-01-28 00:31:03] Request: GET /api/version/media-url.php?url=https%3A%2F%2Flookaside.fbsbx.com%2Fwhatsapp_business%2Fattachments%2F%3Fmid%3D2371342336638440%26source%3Dwebhook%26ext%3D1769575796%26hash%3DARndVKdw1p0CCx3_DpTblR2aOVkb_W5mbTqGFPSOK77cjA GET:{"url":"https:\/\/lookaside.fbsbx.com\/whatsapp_business\/attachments\/?mid=2371342336638440&source=webhook&ext=1769575796&hash=ARndVKdw1p0CCx3_DpTblR2aOVkb_W5mbTqGFPSOK77cjA"} POST:[]
|
||||
[2026-01-28 00:31:03] Request: GET /api/version/media-url.php?id=1217156256734654 GET:{"id":"1217156256734654"} POST:[]
|
||||
[2026-01-28 00:31:03] Graph API request to https://graph.facebook.com/v22.0/1217156256734654
|
||||
[2026-01-28 00:31:03] Resolved media URL from Graph for mid 2371342336638440: https://lookaside.fbsbx.com/whatsapp_business/attachments/?mid=2371342336638440&source=getMedia&ext=1769578563&hash=ARlRqx01CwGl-djJAkY2I4g-P5m7smHw95Wlm1kBJSiSDA
|
||||
[2026-01-28 00:31:03] Proxying Facebook media URL with Authorization to https://lookaside.fbsbx.com/whatsapp_business/attachments/?mid=1217156256734654&source=getMedia&ext=1769578563&hash=ARmRofVHmPDUfJd1iAsyrPYbxenS2CgxlZKyZHE9Q76DqQ
|
||||
[2026-01-28 00:31:18] Request: GET /api/version/media-url.php?url=https%3A%2F%2Flookaside.fbsbx.com%2Fwhatsapp_business%2Fattachments%2F%3Fmid%3D2371342336638440%26source%3Dwebhook%26ext%3D1769575796%26hash%3DARndVKdw1p0CCx3_DpTblR2aOVkb_W5mbTqGFPSOK77cjA GET:{"url":"https:\/\/lookaside.fbsbx.com\/whatsapp_business\/attachments\/?mid=2371342336638440&source=webhook&ext=1769575796&hash=ARndVKdw1p0CCx3_DpTblR2aOVkb_W5mbTqGFPSOK77cjA"} POST:[]
|
||||
[2026-01-28 00:31:18] Request: GET /api/version/media-url.php?id=1217156256734654 GET:{"id":"1217156256734654"} POST:[]
|
||||
[2026-01-28 00:31:18] Graph API request to https://graph.facebook.com/v22.0/1217156256734654
|
||||
[2026-01-28 00:31:18] Resolved media URL from Graph for mid 2371342336638440: https://lookaside.fbsbx.com/whatsapp_business/attachments/?mid=2371342336638440&source=getMedia&ext=1769578578&hash=ARnVWo2U8tL_Yq7kNT0S7iXoCbZSIz9bLJkah-zCi3_8UA
|
||||
[2026-01-28 00:31:18] Proxying Facebook media URL with Authorization to https://lookaside.fbsbx.com/whatsapp_business/attachments/?mid=1217156256734654&source=getMedia&ext=1769578578&hash=ARkDgAhqSzlVEdZj9OnaTFiddRAO4GN39Xpsd2XdUL3Ycw
|
||||
[2026-01-28 00:31:52] Request: GET /api/version/media-url.php?url=https%3A%2F%2Flookaside.fbsbx.com%2Fwhatsapp_business%2Fattachments%2F%3Fmid%3D2371342336638440%26source%3Dwebhook%26ext%3D1769575796%26hash%3DARndVKdw1p0CCx3_DpTblR2aOVkb_W5mbTqGFPSOK77cjA GET:{"url":"https:\/\/lookaside.fbsbx.com\/whatsapp_business\/attachments\/?mid=2371342336638440&source=webhook&ext=1769575796&hash=ARndVKdw1p0CCx3_DpTblR2aOVkb_W5mbTqGFPSOK77cjA"} POST:[]
|
||||
[2026-01-28 00:31:52] Resolved media URL from Graph for mid 2371342336638440: https://lookaside.fbsbx.com/whatsapp_business/attachments/?mid=2371342336638440&source=getMedia&ext=1769578612&hash=ARkn0okswwjwqUMNGWslpAzw_X5imoSyIt14oVH7j56AOw
|
||||
[2026-01-28 00:32:15] Request: GET /api/version/media-url.php?id=1983961412192518 GET:{"id":"1983961412192518"} POST:[]
|
||||
[2026-01-28 00:32:15] Graph API request to https://graph.facebook.com/v22.0/1983961412192518
|
||||
[2026-01-28 00:32:15] Proxying Facebook media URL with Authorization to https://lookaside.fbsbx.com/whatsapp_business/attachments/?mid=1983961412192518&source=getMedia&ext=1769578635&hash=ARl8bnodHLay57oSohSgIppcpZ1x0NRoRzoeCufGANhUuA
|
||||
[2026-01-28 00:35:55] Request: GET /api/version/media-url.php?url=https%3A%2F%2Flookaside.fbsbx.com%2Fwhatsapp_business%2Fattachments%2F%3Fmid%3D2371342336638440%26source%3Dwebhook%26ext%3D1769575796%26hash%3DARndVKdw1p0CCx3_DpTblR2aOVkb_W5mbTqGFPSOK77cjA GET:{"url":"https:\/\/lookaside.fbsbx.com\/whatsapp_business\/attachments\/?mid=2371342336638440&source=webhook&ext=1769575796&hash=ARndVKdw1p0CCx3_DpTblR2aOVkb_W5mbTqGFPSOK77cjA"} POST:[]
|
||||
[2026-01-28 00:35:55] Request: GET /api/version/media-url.php?id=1217156256734654 GET:{"id":"1217156256734654"} POST:[]
|
||||
[2026-01-28 00:35:55] Graph API request to https://graph.facebook.com/v22.0/1217156256734654
|
||||
[2026-01-28 00:35:56] Resolved media URL from Graph for mid 2371342336638440: https://lookaside.fbsbx.com/whatsapp_business/attachments/?mid=2371342336638440&source=getMedia&ext=1769578856&hash=ARl46VfeoC_hpowfcJ8uwH4Bu6RKKGeMG-SdRCmDyEpAlg
|
||||
[2026-01-28 00:35:56] Proxying Facebook media URL with Authorization to https://lookaside.fbsbx.com/whatsapp_business/attachments/?mid=1217156256734654&source=getMedia&ext=1769578856&hash=ARkbJHqldIyUkRCtH85bL0HgIoErQ8zBKtzpeuLl_Olxuw
|
||||
[2026-01-28 00:36:12] Request: GET /api/version/media-url.php?url=https%3A%2F%2Flookaside.fbsbx.com%2Fwhatsapp_business%2Fattachments%2F%3Fmid%3D2371342336638440%26source%3Dwebhook%26ext%3D1769575796%26hash%3DARndVKdw1p0CCx3_DpTblR2aOVkb_W5mbTqGFPSOK77cjA GET:{"url":"https:\/\/lookaside.fbsbx.com\/whatsapp_business\/attachments\/?mid=2371342336638440&source=webhook&ext=1769575796&hash=ARndVKdw1p0CCx3_DpTblR2aOVkb_W5mbTqGFPSOK77cjA"} POST:[]
|
||||
[2026-01-28 00:36:13] Resolved media URL from Graph for mid 2371342336638440: https://lookaside.fbsbx.com/whatsapp_business/attachments/?mid=2371342336638440&source=getMedia&ext=1769578873&hash=ARmQJn2gapAIIEOwHDt6s7kI1g0IHYc0x2ChKjKSU_R7FA
|
||||
[2026-01-28 00:36:32] Request: GET /api/version/media-url.php?url=https%3A%2F%2Flookaside.fbsbx.com%2Fwhatsapp_business%2Fattachments%2F%3Fmid%3D2371342336638440%26source%3Dwebhook%26ext%3D1769575796%26hash%3DARndVKdw1p0CCx3_DpTblR2aOVkb_W5mbTqGFPSOK77cjA GET:{"url":"https:\/\/lookaside.fbsbx.com\/whatsapp_business\/attachments\/?mid=2371342336638440&source=webhook&ext=1769575796&hash=ARndVKdw1p0CCx3_DpTblR2aOVkb_W5mbTqGFPSOK77cjA"} POST:[]
|
||||
[2026-01-28 00:36:33] Resolved media URL from Graph for mid 2371342336638440: https://lookaside.fbsbx.com/whatsapp_business/attachments/?mid=2371342336638440&source=getMedia&ext=1769578893&hash=ARmoYK93esbPfBmwtIcgZ_3J-9DQfmwnT_5A-SXbay5crw
|
||||
[2026-01-28 00:36:59] Request: GET /api/version/media-url.php?id=3480062748838248 GET:{"id":"3480062748838248"} POST:[]
|
||||
[2026-01-28 00:36:59] Graph API request to https://graph.facebook.com/v22.0/3480062748838248
|
||||
[2026-01-28 00:36:59] Proxying Facebook media URL with Authorization to https://lookaside.fbsbx.com/whatsapp_business/attachments/?mid=3480062748838248&source=getMedia&ext=1769578919&hash=ARnnGogjEuOzgaECbYMz20tpgiudo_nyTmLtnXOI4vPgqw
|
||||
[2026-01-28 00:39:29] Request: GET /api/version/media-url.php?id=1217156256734654 GET:{"id":"1217156256734654"} POST:[]
|
||||
[2026-01-28 00:39:29] Graph API request to https://graph.facebook.com/v22.0/1217156256734654
|
||||
[2026-01-28 00:39:30] Proxying Facebook media URL with Authorization to https://lookaside.fbsbx.com/whatsapp_business/attachments/?mid=1217156256734654&source=getMedia&ext=1769579070&hash=ARkKPaxFRIZGRlwW9mNRyF3oUAtq4Q-zr989V8MwIBzyLw
|
||||
[2026-01-28 00:39:30] Request: GET /api/version/media-url.php?url=https%3A%2F%2Flookaside.fbsbx.com%2Fwhatsapp_business%2Fattachments%2F%3Fmid%3D2371342336638440%26source%3Dwebhook%26ext%3D1769575796%26hash%3DARndVKdw1p0CCx3_DpTblR2aOVkb_W5mbTqGFPSOK77cjA GET:{"url":"https:\/\/lookaside.fbsbx.com\/whatsapp_business\/attachments\/?mid=2371342336638440&source=webhook&ext=1769575796&hash=ARndVKdw1p0CCx3_DpTblR2aOVkb_W5mbTqGFPSOK77cjA"} POST:[]
|
||||
[2026-01-28 00:39:30] Resolved media URL from Graph for mid 2371342336638440: https://lookaside.fbsbx.com/whatsapp_business/attachments/?mid=2371342336638440&source=getMedia&ext=1769579070&hash=ARmTcu9TN2oxQK2RIP960qWtzYwsbK9HNN56QveOc6GpIw
|
||||
[2026-01-28 00:42:27] Request: GET /api/version/media-url.php?id=1217156256734654 GET:{"id":"1217156256734654"} POST:[]
|
||||
[2026-01-28 00:42:27] Graph API request to https://graph.facebook.com/v22.0/1217156256734654
|
||||
[2026-01-28 00:42:27] Proxying Facebook media URL with Authorization to https://lookaside.fbsbx.com/whatsapp_business/attachments/?mid=1217156256734654&source=getMedia&ext=1769579247&hash=ARkY9LAAA7csYlYr-SW3f3GlOKJnR9KGm_Ck3Q3YzUl07Q
|
||||
[2026-01-28 00:42:28] Request: GET /api/version/media-url.php?url=https%3A%2F%2Flookaside.fbsbx.com%2Fwhatsapp_business%2Fattachments%2F%3Fmid%3D2371342336638440%26source%3Dwebhook%26ext%3D1769575796%26hash%3DARndVKdw1p0CCx3_DpTblR2aOVkb_W5mbTqGFPSOK77cjA GET:{"url":"https:\/\/lookaside.fbsbx.com\/whatsapp_business\/attachments\/?mid=2371342336638440&source=webhook&ext=1769575796&hash=ARndVKdw1p0CCx3_DpTblR2aOVkb_W5mbTqGFPSOK77cjA"} POST:[]
|
||||
[2026-01-28 00:42:28] Resolved media URL from Graph for mid 2371342336638440: https://lookaside.fbsbx.com/whatsapp_business/attachments/?mid=2371342336638440&source=getMedia&ext=1769579248&hash=ARkP81S6ZYYxl_m5jEnb5ILAMfdGBHKRFQBckN9exlZYZA
|
||||
[2026-01-28 00:46:44] Request: GET /api/version/media-url.php?id=1217156256734654 GET:{"id":"1217156256734654"} POST:[]
|
||||
[2026-01-28 00:46:44] Graph API request to https://graph.facebook.com/v22.0/1217156256734654
|
||||
[2026-01-28 00:46:44] Request: GET /api/version/media-url.php?url=https%3A%2F%2Flookaside.fbsbx.com%2Fwhatsapp_business%2Fattachments%2F%3Fmid%3D2371342336638440%26source%3Dwebhook%26ext%3D1769575796%26hash%3DARndVKdw1p0CCx3_DpTblR2aOVkb_W5mbTqGFPSOK77cjA GET:{"url":"https:\/\/lookaside.fbsbx.com\/whatsapp_business\/attachments\/?mid=2371342336638440&source=webhook&ext=1769575796&hash=ARndVKdw1p0CCx3_DpTblR2aOVkb_W5mbTqGFPSOK77cjA"} POST:[]
|
||||
[2026-01-28 00:46:44] Resolved media URL from Graph for mid 2371342336638440: https://lookaside.fbsbx.com/whatsapp_business/attachments/?mid=2371342336638440&source=getMedia&ext=1769579504&hash=ARmTFmCOFSKbhtRfAK92DvtWo4GPZjeaeiJUsFy5hDbtEQ
|
||||
[2026-01-28 00:46:45] Proxying Facebook media URL with Authorization to https://lookaside.fbsbx.com/whatsapp_business/attachments/?mid=1217156256734654&source=getMedia&ext=1769579505&hash=ARk0PxLzqiGSL5obxGtS5BU09ARd5uqK6XJKL1_Sw5WSRg
|
||||
[2026-01-28 00:47:08] Request: GET /api/version/media-url.php?url=https%3A%2F%2Flookaside.fbsbx.com%2Fwhatsapp_business%2Fattachments%2F%3Fmid%3D2371342336638440%26source%3Dwebhook%26ext%3D1769575796%26hash%3DARndVKdw1p0CCx3_DpTblR2aOVkb_W5mbTqGFPSOK77cjA GET:{"url":"https:\/\/lookaside.fbsbx.com\/whatsapp_business\/attachments\/?mid=2371342336638440&source=webhook&ext=1769575796&hash=ARndVKdw1p0CCx3_DpTblR2aOVkb_W5mbTqGFPSOK77cjA"} POST:[]
|
||||
[2026-01-28 00:47:08] Resolved media URL from Graph for mid 2371342336638440: https://lookaside.fbsbx.com/whatsapp_business/attachments/?mid=2371342336638440&source=getMedia&ext=1769579528&hash=ARmRbSE47_fis_BjpvpeQbA-00ywmKSUuZQjIAWvoAIlcQ
|
||||
[2026-01-28 00:49:35] Request: GET /api/version/media-url.php?id=1217156256734654 GET:{"id":"1217156256734654"} POST:[]
|
||||
[2026-01-28 00:49:35] Graph API request to https://graph.facebook.com/v22.0/1217156256734654
|
||||
[2026-01-28 00:49:35] Request: GET /api/version/media-url.php?url=https%3A%2F%2Flookaside.fbsbx.com%2Fwhatsapp_business%2Fattachments%2F%3Fmid%3D2371342336638440%26source%3Dwebhook%26ext%3D1769575796%26hash%3DARndVKdw1p0CCx3_DpTblR2aOVkb_W5mbTqGFPSOK77cjA GET:{"url":"https:\/\/lookaside.fbsbx.com\/whatsapp_business\/attachments\/?mid=2371342336638440&source=webhook&ext=1769575796&hash=ARndVKdw1p0CCx3_DpTblR2aOVkb_W5mbTqGFPSOK77cjA"} POST:[]
|
||||
[2026-01-28 00:49:35] Resolved media URL from Graph for mid 2371342336638440: https://lookaside.fbsbx.com/whatsapp_business/attachments/?mid=2371342336638440&source=getMedia&ext=1769579675&hash=ARkIayYGe-1jZ0mTJeA7M893JUhie6RGrFzeDetowshI5w
|
||||
[2026-01-28 00:49:35] Proxying Facebook media URL with Authorization to https://lookaside.fbsbx.com/whatsapp_business/attachments/?mid=1217156256734654&source=getMedia&ext=1769579675&hash=ARnUJ8I9qM_rzdz7BWv-22oSEXi7SFVI5QGFjUwCHz_3kA
|
||||
[2026-01-28 00:50:34] Request: GET /api/version/media-url.php?id=1551128883003002&download=1 GET:{"id":"1551128883003002","download":"1"} POST:[]
|
||||
[2026-01-28 00:50:34] Graph API request to https://graph.facebook.com/v22.0/1551128883003002
|
||||
[2026-01-28 00:51:09] Request: GET /api/version/media-url.php?url=https%3A%2F%2Flookaside.fbsbx.com%2Fwhatsapp_business%2Fattachments%2F%3Fmid%3D2371342336638440%26source%3Dwebhook%26ext%3D1769575796%26hash%3DARndVKdw1p0CCx3_DpTblR2aOVkb_W5mbTqGFPSOK77cjA GET:{"url":"https:\/\/lookaside.fbsbx.com\/whatsapp_business\/attachments\/?mid=2371342336638440&source=webhook&ext=1769575796&hash=ARndVKdw1p0CCx3_DpTblR2aOVkb_W5mbTqGFPSOK77cjA"} POST:[]
|
||||
[2026-01-28 00:51:09] Resolved media URL from Graph for mid 2371342336638440: https://lookaside.fbsbx.com/whatsapp_business/attachments/?mid=2371342336638440&source=getMedia&ext=1769579769&hash=ARl25XtRezFQE4LNk2ltWGpUCH8fGtGyGhMjVSRFLbeVLg
|
||||
[2026-01-28 00:53:47] Request: GET /api/version/media-url.php?id=1217156256734654 GET:{"id":"1217156256734654"} POST:[]
|
||||
[2026-01-28 00:53:47] Request: GET /api/version/media-url.php?url=https%3A%2F%2Flookaside.fbsbx.com%2Fwhatsapp_business%2Fattachments%2F%3Fmid%3D2371342336638440%26source%3Dwebhook%26ext%3D1769575796%26hash%3DARndVKdw1p0CCx3_DpTblR2aOVkb_W5mbTqGFPSOK77cjA GET:{"url":"https:\/\/lookaside.fbsbx.com\/whatsapp_business\/attachments\/?mid=2371342336638440&source=webhook&ext=1769575796&hash=ARndVKdw1p0CCx3_DpTblR2aOVkb_W5mbTqGFPSOK77cjA"} POST:[]
|
||||
[2026-01-28 00:53:47] Graph API request to https://graph.facebook.com/v22.0/1217156256734654
|
||||
[2026-01-28 00:53:47] Resolved media URL from Graph for mid 2371342336638440: https://lookaside.fbsbx.com/whatsapp_business/attachments/?mid=2371342336638440&source=getMedia&ext=1769579927&hash=ARnKJqihLQvUOsIMvDxRl6_ToIWFolgiMwv0EpQtAce_WQ
|
||||
[2026-01-28 00:53:47] Proxying Facebook media URL with Authorization to https://lookaside.fbsbx.com/whatsapp_business/attachments/?mid=1217156256734654&source=getMedia&ext=1769579927&hash=ARmluaFcjYAHj3AUqm9kT96xYB2wn-NMyVSa36eFyj6jkQ
|
||||
[2026-01-28 00:54:22] Request: GET /api/version/media-url.php?url=https%3A%2F%2Flookaside.fbsbx.com%2Fwhatsapp_business%2Fattachments%2F%3Fmid%3D2371342336638440%26source%3Dwebhook%26ext%3D1769575796%26hash%3DARndVKdw1p0CCx3_DpTblR2aOVkb_W5mbTqGFPSOK77cjA GET:{"url":"https:\/\/lookaside.fbsbx.com\/whatsapp_business\/attachments\/?mid=2371342336638440&source=webhook&ext=1769575796&hash=ARndVKdw1p0CCx3_DpTblR2aOVkb_W5mbTqGFPSOK77cjA"} POST:[]
|
||||
[2026-01-28 00:54:22] Resolved media URL from Graph for mid 2371342336638440: https://lookaside.fbsbx.com/whatsapp_business/attachments/?mid=2371342336638440&source=getMedia&ext=1769579962&hash=ARmKutEdaebPLIDdbo5NFxqUgqL_itap2Rs-929uRkbm1w
|
||||
[2026-01-28 00:54:55] Request: GET /api/version/media-url.php?local=uploads%2Fmedia_6979a2d407f105.12184484.jpg GET:{"local":"uploads\/media_6979a2d407f105.12184484.jpg"} POST:[]
|
||||
[2026-01-28 00:55:25] Request: GET /api/version/media-url.php?local=uploads%2Fmedia_6979a2d407f105.12184484.jpg GET:{"local":"uploads\/media_6979a2d407f105.12184484.jpg"} POST:[]
|
||||
[2026-01-28 00:55:33] Request: GET /api/version/media-url.php?local=uploads%2Fmedia_6979a2d407f105.12184484.jpg GET:{"local":"uploads\/media_6979a2d407f105.12184484.jpg"} POST:[]
|
||||
[2026-01-28 00:58:18] Request: GET /api/version/media-url.php?local=uploads%2Fmedia_6979a2d407f105.12184484.jpg GET:{"local":"uploads\/media_6979a2d407f105.12184484.jpg"} POST:[]
|
||||
[2026-01-28 00:59:02] Request: GET /api/version/media-url.php?url=https%3A%2F%2Flookaside.fbsbx.com%2Fwhatsapp_business%2Fattachments%2F%3Fmid%3D2371342336638440%26source%3Dwebhook%26ext%3D1769575796%26hash%3DARndVKdw1p0CCx3_DpTblR2aOVkb_W5mbTqGFPSOK77cjA GET:{"url":"https:\/\/lookaside.fbsbx.com\/whatsapp_business\/attachments\/?mid=2371342336638440&source=webhook&ext=1769575796&hash=ARndVKdw1p0CCx3_DpTblR2aOVkb_W5mbTqGFPSOK77cjA"} POST:[]
|
||||
[2026-01-28 00:59:02] Request: GET /api/version/media-url.php?id=1217156256734654 GET:{"id":"1217156256734654"} POST:[]
|
||||
[2026-01-28 00:59:02] Graph API request to https://graph.facebook.com/v22.0/1217156256734654
|
||||
[2026-01-28 00:59:02] Resolved media URL from Graph for mid 2371342336638440: https://lookaside.fbsbx.com/whatsapp_business/attachments/?mid=2371342336638440&source=getMedia&ext=1769580242&hash=ARlmivoTwZhpdMULc1VdeSk_2GQXSHx9_SXYGbF7AJ9Fag
|
||||
[2026-01-28 00:59:02] Proxying Facebook media URL with Authorization to https://lookaside.fbsbx.com/whatsapp_business/attachments/?mid=1217156256734654&source=getMedia&ext=1769580242&hash=ARmenndhGQKTEctc9p9lc9F4cGFTr6IMx88N3iL_RuT3Zw
|
||||
[2026-01-28 00:59:24] Request: GET /api/version/media-url.php?url=https%3A%2F%2Flookaside.fbsbx.com%2Fwhatsapp_business%2Fattachments%2F%3Fmid%3D2371342336638440%26source%3Dwebhook%26ext%3D1769575796%26hash%3DARndVKdw1p0CCx3_DpTblR2aOVkb_W5mbTqGFPSOK77cjA GET:{"url":"https:\/\/lookaside.fbsbx.com\/whatsapp_business\/attachments\/?mid=2371342336638440&source=webhook&ext=1769575796&hash=ARndVKdw1p0CCx3_DpTblR2aOVkb_W5mbTqGFPSOK77cjA"} POST:[]
|
||||
[2026-01-28 00:59:25] Resolved media URL from Graph for mid 2371342336638440: https://lookaside.fbsbx.com/whatsapp_business/attachments/?mid=2371342336638440&source=getMedia&ext=1769580265&hash=ARnOU-1V45VtKJI2XzRFHD6BSyGBjUSTIqGJdBzs933bAw
|
||||
[2026-01-28 01:03:12] Request: GET /api/version/media-url.php?id=1217156256734654 GET:{"id":"1217156256734654"} POST:[]
|
||||
[2026-01-28 01:03:12] Graph API request to https://graph.facebook.com/v22.0/1217156256734654
|
||||
[2026-01-28 01:03:12] Request: GET /api/version/media-url.php?url=https%3A%2F%2Flookaside.fbsbx.com%2Fwhatsapp_business%2Fattachments%2F%3Fmid%3D2371342336638440%26source%3Dwebhook%26ext%3D1769575796%26hash%3DARndVKdw1p0CCx3_DpTblR2aOVkb_W5mbTqGFPSOK77cjA GET:{"url":"https:\/\/lookaside.fbsbx.com\/whatsapp_business\/attachments\/?mid=2371342336638440&source=webhook&ext=1769575796&hash=ARndVKdw1p0CCx3_DpTblR2aOVkb_W5mbTqGFPSOK77cjA"} POST:[]
|
||||
[2026-01-28 01:03:12] Proxying Facebook media URL with Authorization to https://lookaside.fbsbx.com/whatsapp_business/attachments/?mid=1217156256734654&source=getMedia&ext=1769580492&hash=ARn93MHvoEKXeawiU3sBI9u3xVB0plX3bNOc6FHj9WVFog
|
||||
[2026-01-28 01:03:12] Resolved media URL from Graph for mid 2371342336638440: https://lookaside.fbsbx.com/whatsapp_business/attachments/?mid=2371342336638440&source=getMedia&ext=1769580492&hash=ARnWkfo-X22eZ-dKOhkni6yzUXhTOsS38uIW7LG8F_Grng
|
||||
[2026-01-28 01:08:42] Request: GET /api/version/media-url.php?url=https%3A%2F%2Flookaside.fbsbx.com%2Fwhatsapp_business%2Fattachments%2F%3Fmid%3D2371342336638440%26source%3Dwebhook%26ext%3D1769575796%26hash%3DARndVKdw1p0CCx3_DpTblR2aOVkb_W5mbTqGFPSOK77cjA GET:{"url":"https:\/\/lookaside.fbsbx.com\/whatsapp_business\/attachments\/?mid=2371342336638440&source=webhook&ext=1769575796&hash=ARndVKdw1p0CCx3_DpTblR2aOVkb_W5mbTqGFPSOK77cjA"} POST:[]
|
||||
[2026-01-28 01:08:42] Request: GET /api/version/media-url.php?id=1217156256734654 GET:{"id":"1217156256734654"} POST:[]
|
||||
[2026-01-28 01:08:42] Graph API request to https://graph.facebook.com/v22.0/1217156256734654
|
||||
[2026-01-28 01:08:42] Resolved media URL from Graph for mid 2371342336638440: https://lookaside.fbsbx.com/whatsapp_business/attachments/?mid=2371342336638440&source=getMedia&ext=1769580822&hash=ARmzjPWWs1VtMhON00noHMjb2S7Z2NzzMXQS6kRVWz_GMw
|
||||
[2026-01-28 01:08:42] Proxying Facebook media URL with Authorization to https://lookaside.fbsbx.com/whatsapp_business/attachments/?mid=1217156256734654&source=getMedia&ext=1769580822&hash=ARmsky0v0oPn3oem400y-tAQQ6n44y-Pr5A0Fy4_ym08Sw
|
||||
[2026-01-28 01:10:45] Request: GET /api/version/media-url.php?id=1217156256734654 GET:{"id":"1217156256734654"} POST:[]
|
||||
[2026-01-28 01:10:45] Request: GET /api/version/media-url.php?url=https%3A%2F%2Flookaside.fbsbx.com%2Fwhatsapp_business%2Fattachments%2F%3Fmid%3D2371342336638440%26source%3Dwebhook%26ext%3D1769575796%26hash%3DARndVKdw1p0CCx3_DpTblR2aOVkb_W5mbTqGFPSOK77cjA GET:{"url":"https:\/\/lookaside.fbsbx.com\/whatsapp_business\/attachments\/?mid=2371342336638440&source=webhook&ext=1769575796&hash=ARndVKdw1p0CCx3_DpTblR2aOVkb_W5mbTqGFPSOK77cjA"} POST:[]
|
||||
[2026-01-28 01:10:45] Graph API request to https://graph.facebook.com/v22.0/1217156256734654
|
||||
[2026-01-28 01:10:45] Proxying Facebook media URL with Authorization to https://lookaside.fbsbx.com/whatsapp_business/attachments/?mid=1217156256734654&source=getMedia&ext=1769580945&hash=ARk25aum1ipZPmiCLuvdicHJb9ex0rx8OaT5Z0NPRd3GZw
|
||||
[2026-01-28 01:10:45] Resolved media URL from Graph for mid 2371342336638440: https://lookaside.fbsbx.com/whatsapp_business/attachments/?mid=2371342336638440&source=getMedia&ext=1769580945&hash=ARmIfLoMEJXUbvwj3h6IgyLZDGarDY5dvQtTZtWbpqJYxA
|
||||
[2026-01-28 01:15:57] Request: GET /api/version/media-url.php?url=https%3A%2F%2Flookaside.fbsbx.com%2Fwhatsapp_business%2Fattachments%2F%3Fmid%3D2371342336638440%26source%3Dwebhook%26ext%3D1769575796%26hash%3DARndVKdw1p0CCx3_DpTblR2aOVkb_W5mbTqGFPSOK77cjA GET:{"url":"https:\/\/lookaside.fbsbx.com\/whatsapp_business\/attachments\/?mid=2371342336638440&source=webhook&ext=1769575796&hash=ARndVKdw1p0CCx3_DpTblR2aOVkb_W5mbTqGFPSOK77cjA"} POST:[]
|
||||
[2026-01-28 01:15:57] Request: GET /api/version/media-url.php?id=1217156256734654 GET:{"id":"1217156256734654"} POST:[]
|
||||
[2026-01-28 01:15:57] Graph API request to https://graph.facebook.com/v22.0/1217156256734654
|
||||
[2026-01-28 01:15:57] Resolved media URL from Graph for mid 2371342336638440: https://lookaside.fbsbx.com/whatsapp_business/attachments/?mid=2371342336638440&source=getMedia&ext=1769581257&hash=ARnrEU19RUEQsZDRQEZQS0vD9QujFwJ4sA02YqQJ-37OVg
|
||||
[2026-01-28 01:15:57] Proxying Facebook media URL with Authorization to https://lookaside.fbsbx.com/whatsapp_business/attachments/?mid=1217156256734654&source=getMedia&ext=1769581257&hash=ARnlPUXu741I3wXzXm6Ns1UjsSVnJuh5AJaHUnDk7TuUug
|
||||
[2026-01-28 01:16:11] Request: GET /api/version/media-url.php?url=https%3A%2F%2Flookaside.fbsbx.com%2Fwhatsapp_business%2Fattachments%2F%3Fmid%3D2371342336638440%26source%3Dwebhook%26ext%3D1769575796%26hash%3DARndVKdw1p0CCx3_DpTblR2aOVkb_W5mbTqGFPSOK77cjA GET:{"url":"https:\/\/lookaside.fbsbx.com\/whatsapp_business\/attachments\/?mid=2371342336638440&source=webhook&ext=1769575796&hash=ARndVKdw1p0CCx3_DpTblR2aOVkb_W5mbTqGFPSOK77cjA"} POST:[]
|
||||
[2026-01-28 01:16:12] Resolved media URL from Graph for mid 2371342336638440: https://lookaside.fbsbx.com/whatsapp_business/attachments/?mid=2371342336638440&source=getMedia&ext=1769581272&hash=ARkFqWHyaasxAljVpFWiD6HLQKSQ4D_yd8JsDrVUREalQQ
|
||||
[2026-01-28 01:18:55] Request: GET /api/version/media-url.php?id=1217156256734654 GET:{"id":"1217156256734654"} POST:[]
|
||||
[2026-01-28 01:18:55] Graph API request to https://graph.facebook.com/v22.0/1217156256734654
|
||||
[2026-01-28 01:18:55] Request: GET /api/version/media-url.php?url=https%3A%2F%2Flookaside.fbsbx.com%2Fwhatsapp_business%2Fattachments%2F%3Fmid%3D2371342336638440%26source%3Dwebhook%26ext%3D1769575796%26hash%3DARndVKdw1p0CCx3_DpTblR2aOVkb_W5mbTqGFPSOK77cjA GET:{"url":"https:\/\/lookaside.fbsbx.com\/whatsapp_business\/attachments\/?mid=2371342336638440&source=webhook&ext=1769575796&hash=ARndVKdw1p0CCx3_DpTblR2aOVkb_W5mbTqGFPSOK77cjA"} POST:[]
|
||||
[2026-01-28 01:18:55] Proxying Facebook media URL with Authorization to https://lookaside.fbsbx.com/whatsapp_business/attachments/?mid=1217156256734654&source=getMedia&ext=1769581435&hash=ARnFdlxA1CZ7s6df99Lvrksxj0tPcjzREd7IzTEHuGfF2A
|
||||
[2026-01-28 01:18:55] Resolved media URL from Graph for mid 2371342336638440: https://lookaside.fbsbx.com/whatsapp_business/attachments/?mid=2371342336638440&source=getMedia&ext=1769581435&hash=ARlLQ93XXsVGb4xTDoy6pa5bceRwLUBQ2Tb58-5qx8tcRA
|
||||
[2026-01-28 01:19:33] Request: GET /api/version/media-url.php?id=1601261651067176&download=1 GET:{"id":"1601261651067176","download":"1"} POST:[]
|
||||
[2026-01-28 01:19:33] Graph API request to https://graph.facebook.com/v22.0/1601261651067176
|
||||
[2026-01-28 01:19:42] Request: GET /api/version/media-url.php?local=uploads%2Fmedia_6979a2d407f105.12184484.jpg GET:{"local":"uploads\/media_6979a2d407f105.12184484.jpg"} POST:[]
|
||||
[2026-01-28 01:20:39] Request: GET /api/version/media-url.php?id=1217156256734654 GET:{"id":"1217156256734654"} POST:[]
|
||||
[2026-01-28 01:20:39] Graph API request to https://graph.facebook.com/v22.0/1217156256734654
|
||||
[2026-01-28 01:20:39] Proxying Facebook media URL with Authorization to https://lookaside.fbsbx.com/whatsapp_business/attachments/?mid=1217156256734654&source=getMedia&ext=1769581539&hash=ARn5A34U8V_qmSuZQJl7xYix7Lr-CC8DI-K36SgrcqJyRA
|
||||
[2026-01-28 01:22:26] Request: GET /api/version/media-url.php?url=https%3A%2F%2Flookaside.fbsbx.com%2Fwhatsapp_business%2Fattachments%2F%3Fmid%3D2371342336638440%26source%3Dwebhook%26ext%3D1769575796%26hash%3DARndVKdw1p0CCx3_DpTblR2aOVkb_W5mbTqGFPSOK77cjA GET:{"url":"https:\/\/lookaside.fbsbx.com\/whatsapp_business\/attachments\/?mid=2371342336638440&source=webhook&ext=1769575796&hash=ARndVKdw1p0CCx3_DpTblR2aOVkb_W5mbTqGFPSOK77cjA"} POST:[]
|
||||
[2026-01-28 01:22:26] Request: GET /api/version/media-url.php?id=1217156256734654 GET:{"id":"1217156256734654"} POST:[]
|
||||
[2026-01-28 01:22:26] Graph API request to https://graph.facebook.com/v22.0/1217156256734654
|
||||
[2026-01-28 01:22:26] Resolved media URL from Graph for mid 2371342336638440: https://lookaside.fbsbx.com/whatsapp_business/attachments/?mid=2371342336638440&source=getMedia&ext=1769581646&hash=ARnEOR2YXK9c-xUeehKuZrowGgZ5KIuC8VZjf2Xr0IIpAQ
|
||||
[2026-01-28 01:22:26] Proxying Facebook media URL with Authorization to https://lookaside.fbsbx.com/whatsapp_business/attachments/?mid=1217156256734654&source=getMedia&ext=1769581646&hash=ARlhztt7jCFwChEJOM-PvQ47LBfjik-w6ljnvfuI9i8efw
|
||||
[2026-01-28 01:24:47] Request: GET /api/version/media-url.php?id=1217156256734654 GET:{"id":"1217156256734654"} POST:[]
|
||||
[2026-01-28 01:24:47] Graph API request to https://graph.facebook.com/v22.0/1217156256734654
|
||||
[2026-01-28 01:24:47] Proxying Facebook media URL with Authorization to https://lookaside.fbsbx.com/whatsapp_business/attachments/?mid=1217156256734654&source=getMedia&ext=1769581787&hash=ARnzH0guEPfWRWU51ldsgxmZs966Qd8Qfle7rEW1nLggaQ
|
||||
[2026-01-28 01:24:47] Request: GET /api/version/media-url.php?url=https%3A%2F%2Flookaside.fbsbx.com%2Fwhatsapp_business%2Fattachments%2F%3Fmid%3D2371342336638440%26source%3Dwebhook%26ext%3D1769575796%26hash%3DARndVKdw1p0CCx3_DpTblR2aOVkb_W5mbTqGFPSOK77cjA GET:{"url":"https:\/\/lookaside.fbsbx.com\/whatsapp_business\/attachments\/?mid=2371342336638440&source=webhook&ext=1769575796&hash=ARndVKdw1p0CCx3_DpTblR2aOVkb_W5mbTqGFPSOK77cjA"} POST:[]
|
||||
[2026-01-28 01:24:47] Resolved media URL from Graph for mid 2371342336638440: https://lookaside.fbsbx.com/whatsapp_business/attachments/?mid=2371342336638440&source=getMedia&ext=1769581787&hash=ARnFw0RXJtxRRVYmhMD3oeFTJiGiMxb-G4tV3pBjNL6_SQ
|
||||
[2026-01-28 01:25:29] Request: GET /api/version/media-url.php?url=https%3A%2F%2Flookaside.fbsbx.com%2Fwhatsapp_business%2Fattachments%2F%3Fmid%3D2371342336638440%26source%3Dwebhook%26ext%3D1769575796%26hash%3DARndVKdw1p0CCx3_DpTblR2aOVkb_W5mbTqGFPSOK77cjA GET:{"url":"https:\/\/lookaside.fbsbx.com\/whatsapp_business\/attachments\/?mid=2371342336638440&source=webhook&ext=1769575796&hash=ARndVKdw1p0CCx3_DpTblR2aOVkb_W5mbTqGFPSOK77cjA"} POST:[]
|
||||
[2026-01-28 01:25:29] Resolved media URL from Graph for mid 2371342336638440: https://lookaside.fbsbx.com/whatsapp_business/attachments/?mid=2371342336638440&source=getMedia&ext=1769581829&hash=ARlRzKB6IF46_AlDA7o7gapnrQFJPQ8sDJgCHWB8iHILJQ
|
||||
[2026-01-28 01:30:00] Request: GET /api/version/media-url.php?id=1217156256734654 GET:{"id":"1217156256734654"} POST:[]
|
||||
[2026-01-28 01:30:00] Graph API request to https://graph.facebook.com/v22.0/1217156256734654
|
||||
[2026-01-28 01:30:00] Request: GET /api/version/media-url.php?url=https%3A%2F%2Flookaside.fbsbx.com%2Fwhatsapp_business%2Fattachments%2F%3Fmid%3D2371342336638440%26source%3Dwebhook%26ext%3D1769575796%26hash%3DARndVKdw1p0CCx3_DpTblR2aOVkb_W5mbTqGFPSOK77cjA GET:{"url":"https:\/\/lookaside.fbsbx.com\/whatsapp_business\/attachments\/?mid=2371342336638440&source=webhook&ext=1769575796&hash=ARndVKdw1p0CCx3_DpTblR2aOVkb_W5mbTqGFPSOK77cjA"} POST:[]
|
||||
[2026-01-28 01:30:00] Resolved media URL from Graph for mid 2371342336638440: https://lookaside.fbsbx.com/whatsapp_business/attachments/?mid=2371342336638440&source=getMedia&ext=1769582100&hash=ARkKkePqgcaQambyFaT-q7fmcItK9CRzre9LqZ99MY2tRQ
|
||||
[2026-01-28 01:30:00] Proxying Facebook media URL with Authorization to https://lookaside.fbsbx.com/whatsapp_business/attachments/?mid=1217156256734654&source=getMedia&ext=1769582100&hash=ARkk8hsjClEX4fhebbWogS6yUSnR0tf6xibLB3OFl_m8yw
|
||||
[2026-01-28 01:49:29] Request: GET /api/version/media-url.php?id=1217156256734654 GET:{"id":"1217156256734654"} POST:[]
|
||||
[2026-01-28 01:49:29] Graph API request to https://graph.facebook.com/v22.0/1217156256734654
|
||||
[2026-01-28 01:49:29] Request: GET /api/version/media-url.php?url=https%3A%2F%2Flookaside.fbsbx.com%2Fwhatsapp_business%2Fattachments%2F%3Fmid%3D2371342336638440%26source%3Dwebhook%26ext%3D1769575796%26hash%3DARndVKdw1p0CCx3_DpTblR2aOVkb_W5mbTqGFPSOK77cjA GET:{"url":"https:\/\/lookaside.fbsbx.com\/whatsapp_business\/attachments\/?mid=2371342336638440&source=webhook&ext=1769575796&hash=ARndVKdw1p0CCx3_DpTblR2aOVkb_W5mbTqGFPSOK77cjA"} POST:[]
|
||||
[2026-01-28 01:49:29] Resolved media URL from Graph for mid 2371342336638440: https://lookaside.fbsbx.com/whatsapp_business/attachments/?mid=2371342336638440&source=getMedia&ext=1769583269&hash=ARlsuHrQo0NV1y3mLfDFwu6VKo6zw0Vft-xdrNbqwNDKSw
|
||||
[2026-01-28 01:49:30] Proxying Facebook media URL with Authorization to https://lookaside.fbsbx.com/whatsapp_business/attachments/?mid=1217156256734654&source=getMedia&ext=1769583269&hash=ARl8a7X-B2EJZVDbLlIu-9SHY0U7d-qv_iJm7eG75GiYCA
|
||||
[2026-01-28 01:49:42] Request: GET /api/version/media-url.php?url=https%3A%2F%2Flookaside.fbsbx.com%2Fwhatsapp_business%2Fattachments%2F%3Fmid%3D2371342336638440%26source%3Dwebhook%26ext%3D1769575796%26hash%3DARndVKdw1p0CCx3_DpTblR2aOVkb_W5mbTqGFPSOK77cjA GET:{"url":"https:\/\/lookaside.fbsbx.com\/whatsapp_business\/attachments\/?mid=2371342336638440&source=webhook&ext=1769575796&hash=ARndVKdw1p0CCx3_DpTblR2aOVkb_W5mbTqGFPSOK77cjA"} POST:[]
|
||||
[2026-01-28 01:49:43] Resolved media URL from Graph for mid 2371342336638440: https://lookaside.fbsbx.com/whatsapp_business/attachments/?mid=2371342336638440&source=getMedia&ext=1769583283&hash=ARkFBlfW7vGkyhucCoWVgirgWMi4rSfVsXmiPIqExxtM8A
|
||||
[2026-01-28 01:51:22] Request: GET /api/version/media-url.php?id=1217156256734654 GET:{"id":"1217156256734654"} POST:[]
|
||||
[2026-01-28 01:51:22] Request: GET /api/version/media-url.php?url=https%3A%2F%2Flookaside.fbsbx.com%2Fwhatsapp_business%2Fattachments%2F%3Fmid%3D2371342336638440%26source%3Dwebhook%26ext%3D1769575796%26hash%3DARndVKdw1p0CCx3_DpTblR2aOVkb_W5mbTqGFPSOK77cjA GET:{"url":"https:\/\/lookaside.fbsbx.com\/whatsapp_business\/attachments\/?mid=2371342336638440&source=webhook&ext=1769575796&hash=ARndVKdw1p0CCx3_DpTblR2aOVkb_W5mbTqGFPSOK77cjA"} POST:[]
|
||||
[2026-01-28 01:51:22] Graph API request to https://graph.facebook.com/v22.0/1217156256734654
|
||||
[2026-01-28 01:51:22] Proxying Facebook media URL with Authorization to https://lookaside.fbsbx.com/whatsapp_business/attachments/?mid=1217156256734654&source=getMedia&ext=1769583382&hash=ARlNJc4-zhtmMDC6ZX5YvLG-QZlcNIjMX7IpNB6Z6YzdOA
|
||||
[2026-01-28 01:51:22] Resolved media URL from Graph for mid 2371342336638440: https://lookaside.fbsbx.com/whatsapp_business/attachments/?mid=2371342336638440&source=getMedia&ext=1769583382&hash=ARlZV7UnYDg_jagmLF6YEbGh8v50rUfxYFEw-yLNBBgbHg
|
||||
[2026-01-28 01:51:46] Request: GET /api/version/media-url.php?url=https%3A%2F%2Flookaside.fbsbx.com%2Fwhatsapp_business%2Fattachments%2F%3Fmid%3D2371342336638440%26source%3Dwebhook%26ext%3D1769575796%26hash%3DARndVKdw1p0CCx3_DpTblR2aOVkb_W5mbTqGFPSOK77cjA GET:{"url":"https:\/\/lookaside.fbsbx.com\/whatsapp_business\/attachments\/?mid=2371342336638440&source=webhook&ext=1769575796&hash=ARndVKdw1p0CCx3_DpTblR2aOVkb_W5mbTqGFPSOK77cjA"} POST:[]
|
||||
[2026-01-28 01:51:47] Resolved media URL from Graph for mid 2371342336638440: https://lookaside.fbsbx.com/whatsapp_business/attachments/?mid=2371342336638440&source=getMedia&ext=1769583407&hash=ARnwqEl9qw2RK6Yd9gAXYj8TNbqqqMGIspUjWdE6nqhL1Q
|
||||
[2026-01-28 01:52:04] Request: GET /api/version/media-url.php?url=https%3A%2F%2Flookaside.fbsbx.com%2Fwhatsapp_business%2Fattachments%2F%3Fmid%3D2371342336638440%26source%3Dwebhook%26ext%3D1769575796%26hash%3DARndVKdw1p0CCx3_DpTblR2aOVkb_W5mbTqGFPSOK77cjA GET:{"url":"https:\/\/lookaside.fbsbx.com\/whatsapp_business\/attachments\/?mid=2371342336638440&source=webhook&ext=1769575796&hash=ARndVKdw1p0CCx3_DpTblR2aOVkb_W5mbTqGFPSOK77cjA"} POST:[]
|
||||
[2026-01-28 01:52:04] Resolved media URL from Graph for mid 2371342336638440: https://lookaside.fbsbx.com/whatsapp_business/attachments/?mid=2371342336638440&source=getMedia&ext=1769583424&hash=ARl_asnI_rejXyYQaCO7NAYFbfQpBDdRxmWzt-CmmJUrCg
|
||||
[2026-01-28 02:00:11] Request: GET /api/version/media-url.php?id=1217156256734654 GET:{"id":"1217156256734654"} POST:[]
|
||||
[2026-01-28 02:00:11] Graph API request to https://graph.facebook.com/v22.0/1217156256734654
|
||||
[2026-01-28 02:00:11] Request: GET /api/version/media-url.php?url=https%3A%2F%2Flookaside.fbsbx.com%2Fwhatsapp_business%2Fattachments%2F%3Fmid%3D2371342336638440%26source%3Dwebhook%26ext%3D1769575796%26hash%3DARndVKdw1p0CCx3_DpTblR2aOVkb_W5mbTqGFPSOK77cjA GET:{"url":"https:\/\/lookaside.fbsbx.com\/whatsapp_business\/attachments\/?mid=2371342336638440&source=webhook&ext=1769575796&hash=ARndVKdw1p0CCx3_DpTblR2aOVkb_W5mbTqGFPSOK77cjA"} POST:[]
|
||||
[2026-01-28 02:00:11] Proxying Facebook media URL with Authorization to https://lookaside.fbsbx.com/whatsapp_business/attachments/?mid=1217156256734654&source=getMedia&ext=1769583911&hash=ARkOiy7N3swvb64kubAAcPhyEaoXC5Pf96qQK8dlGjfZRw
|
||||
[2026-01-28 02:00:11] Resolved media URL from Graph for mid 2371342336638440: https://lookaside.fbsbx.com/whatsapp_business/attachments/?mid=2371342336638440&source=getMedia&ext=1769583911&hash=ARnR5vosdyiSyrizuAG-OROPmxikGRc-vT-PPe2VbT13Xg
|
||||
[2026-01-28 02:00:25] Request: GET /api/version/media-url.php?id=1217156256734654 GET:{"id":"1217156256734654"} POST:[]
|
||||
[2026-01-28 02:00:25] Graph API request to https://graph.facebook.com/v22.0/1217156256734654
|
||||
[2026-01-28 02:00:25] Request: GET /api/version/media-url.php?url=https%3A%2F%2Flookaside.fbsbx.com%2Fwhatsapp_business%2Fattachments%2F%3Fmid%3D2371342336638440%26source%3Dwebhook%26ext%3D1769575796%26hash%3DARndVKdw1p0CCx3_DpTblR2aOVkb_W5mbTqGFPSOK77cjA GET:{"url":"https:\/\/lookaside.fbsbx.com\/whatsapp_business\/attachments\/?mid=2371342336638440&source=webhook&ext=1769575796&hash=ARndVKdw1p0CCx3_DpTblR2aOVkb_W5mbTqGFPSOK77cjA"} POST:[]
|
||||
[2026-01-28 02:00:26] Resolved media URL from Graph for mid 2371342336638440: https://lookaside.fbsbx.com/whatsapp_business/attachments/?mid=2371342336638440&source=getMedia&ext=1769583926&hash=ARkwnC8kELAgDSp4Qy8qvU3cY6trphM71K08Ebb3rQDeXg
|
||||
[2026-01-28 02:00:26] Proxying Facebook media URL with Authorization to https://lookaside.fbsbx.com/whatsapp_business/attachments/?mid=1217156256734654&source=getMedia&ext=1769583926&hash=ARk42Fz7IB5FhjLHoVW-GF05cM0WjbFZU0NerKLOUo1W9g
|
||||
|
||||
@@ -37,6 +37,8 @@ function isValidMediaUrl(u) {
|
||||
function ensureProxyUrl(u, download = false) {
|
||||
if (!isValidMediaUrl(u)) return '';
|
||||
if (u.startsWith('/') || u.indexOf('/api/version/media-url.php') === 0) return u;
|
||||
// Si empieza con api/ agregar / al inicio
|
||||
if (u.startsWith('api/')) return '/' + u;
|
||||
try {
|
||||
const parsed = new URL(u);
|
||||
const host = parsed.host.toLowerCase();
|
||||
@@ -84,7 +86,8 @@ function renderMediaMessage(msg) {
|
||||
// Full URL for opening (prefer local file then external with id or url)
|
||||
let fullUrl = '';
|
||||
if (isValidMediaUrl(localFile)) {
|
||||
fullUrl = `/api/version/media-url.php?local=${encodeURIComponent(localFile)}`;
|
||||
// Usar archivo local directamente sin proxy
|
||||
fullUrl = localFile.startsWith('/') ? localFile : `/${localFile}`;
|
||||
} else if (isValidMediaUrl(mediaExternal)) {
|
||||
let mid = '';
|
||||
if (mediaExternal.indexOf('api/get_media.php?id=') !== -1) {
|
||||
@@ -108,16 +111,28 @@ function renderMediaMessage(msg) {
|
||||
return `<div class="text-muted"><em>Imagen no disponible</em></div>`;
|
||||
}
|
||||
case 'video': {
|
||||
const src = ensureProxyUrl(effective || msg.media_url || '');
|
||||
// Priorizar local_file sobre otras fuentes
|
||||
let src = '';
|
||||
if (isValidMediaUrl(localFile)) {
|
||||
src = localFile.startsWith('/') ? localFile : `/${localFile}`;
|
||||
} else {
|
||||
src = ensureProxyUrl(effective || msg.media_url || '');
|
||||
}
|
||||
if (src) return `<div class="message-media"><video controls><source src="${escapeHtml(src)}" type="video/mp4">Tu navegador no soporta video.</video></div>${content?`<div>${escapeHtml(content)}</div>`:''}`;
|
||||
return `<div class="text-muted"><em>Video no disponible</em></div>`;
|
||||
}
|
||||
case 'audio': {
|
||||
const src = ensureProxyUrl(effective || msg.media_url || '');
|
||||
// Priorizar local_file sobre otras fuentes
|
||||
let src = '';
|
||||
if (isValidMediaUrl(localFile)) {
|
||||
src = localFile.startsWith('/') ? localFile : `/${localFile}`;
|
||||
} else {
|
||||
src = ensureProxyUrl(effective || msg.media_url || '');
|
||||
}
|
||||
if (!src) return `<div class="text-muted"><em>Audio no disponible</em></div>`;
|
||||
// build download link when possible (api/get_media.php?id=... or direct url or local file)
|
||||
let audioDownload = null;
|
||||
const candidate = isValidMediaUrl(effective) ? effective : (isValidMediaUrl(msg.media_url) ? msg.media_url : (isValidMediaUrl(localFile) ? localFile : null));
|
||||
const candidate = isValidMediaUrl(localFile) ? localFile : (isValidMediaUrl(effective) ? effective : (isValidMediaUrl(msg.media_url) ? msg.media_url : null));
|
||||
if (candidate && candidate.indexOf && candidate.indexOf('api/get_media.php?id=') !== -1) {
|
||||
const parts = candidate.split('id=');
|
||||
const mid = parts[1] ? parts[1] : '';
|
||||
@@ -125,7 +140,8 @@ function renderMediaMessage(msg) {
|
||||
} else if (candidate && /^https?:\/\//i.test(candidate)) {
|
||||
audioDownload = `/api/version/media-url.php?url=${encodeURIComponent(candidate)}&download=1`;
|
||||
} else if (candidate && candidate === localFile) {
|
||||
audioDownload = `/api/version/media-url.php?local=${encodeURIComponent(candidate)}&download=1`;
|
||||
// Usar archivo local directamente sin proxy
|
||||
audioDownload = localFile.startsWith('/') ? localFile : `/${localFile}`;
|
||||
}
|
||||
|
||||
let html = `<div class="message-media"><audio controls><source src="${escapeHtml(src)}" type="audio/mpeg">Tu navegador no soporta audio.</audio></div>`;
|
||||
@@ -143,7 +159,8 @@ function renderMediaMessage(msg) {
|
||||
} else if (isValidMediaUrl(mediaExternal) && /^https?:\/\//i.test(mediaExternal)) {
|
||||
docUrl = `/api/version/media-url.php?url=${encodeURIComponent(mediaExternal)}&download=1`;
|
||||
} else if (isValidMediaUrl(localFile)) {
|
||||
docUrl = `/api/version/media-url.php?local=${encodeURIComponent(localFile)}&download=1`;
|
||||
// Usar archivo local directamente sin proxy
|
||||
docUrl = localFile.startsWith('/') ? localFile : `/${localFile}`;
|
||||
}
|
||||
if (docUrl) return `<a href="${docUrl}" class="message-document" target="_blank" rel="noopener noreferrer"><i class="fas fa-file-pdf"></i><span>${escapeHtml(filename)}</span></a>`;
|
||||
return `<div class="message-document" style="opacity:0.6;"><i class="fas fa-file-pdf"></i><span>${escapeHtml(filename)} (No disponible)</span></div>`;
|
||||
|
||||
+6
-6
@@ -5,12 +5,12 @@
|
||||
* Fecha: 4 de enero de 2026 - Sistema de autenticación unificado
|
||||
*/
|
||||
|
||||
// Configuración de la base de datos (compatible con cPanel)
|
||||
define('DB_HOST', '77.37.126.126');
|
||||
define('DB_PORT', '3306');
|
||||
define('DB_NAME', 'usite_whatsapp_bot');
|
||||
define('DB_USER', 'usite_whatsapp_user');
|
||||
define('DB_PASS', '6q!Vio0fn@PFmsLyHjH5'); // Se generará automáticamente en la instalación
|
||||
// Configuración de la base de datos - usa variables de entorno si están disponibles
|
||||
define('DB_HOST', getenv('DB_HOST') ?: '77.37.126.126');
|
||||
define('DB_PORT', getenv('DB_PORT') ?: '3306');
|
||||
define('DB_NAME', getenv('DB_NAME') ?: 'usite_whatsapp_bot');
|
||||
define('DB_USER', getenv('DB_USER') ?: 'usite_whatsapp_user');
|
||||
define('DB_PASS', getenv('DB_PASS') ?: '6q!Vio0fn@PFmsLyHjH5');
|
||||
define('DB_CHARSET', 'utf8mb4');
|
||||
|
||||
// Configuración de autenticación (LEGACY - migrado a BD)
|
||||
|
||||
+115
-58
@@ -1425,6 +1425,9 @@ if (!isset($_SESSION['user_id'])) {
|
||||
// Solo incrementar unread_count si no es la conversación activa
|
||||
if (String(this.currentUserId) !== String(userId)) {
|
||||
conv.unread_count = (conv.unread_count || 0) + 1;
|
||||
} else {
|
||||
// Si es la conversación activa, mantener unread_count en 0
|
||||
conv.unread_count = 0;
|
||||
}
|
||||
|
||||
// Mover al inicio de la lista
|
||||
@@ -1445,8 +1448,7 @@ if (!isset($_SESSION['user_id'])) {
|
||||
|
||||
// Re-renderizar solo la lista de conversaciones
|
||||
console.log('🔄 Re-renderizando lista de conversaciones...');
|
||||
console.log('🔍 Verificando this:', this);
|
||||
console.log('🔍 this.renderConversations existe?', typeof this.renderConversations);
|
||||
console.log('🔍 Filtro activo:', this.conversationFilter);
|
||||
console.log('🔍 this.conversations:', this.conversations);
|
||||
|
||||
if (typeof this.renderConversations === 'function') {
|
||||
@@ -2252,8 +2254,14 @@ if (!isset($_SESSION['user_id'])) {
|
||||
filterSelect.value = this.conversationFilter;
|
||||
filterSelect.addEventListener('change', (e) => {
|
||||
this.conversationFilter = e.target.value || 'all';
|
||||
// reload conversations from first page
|
||||
this.loadConversations(1, false);
|
||||
console.log('🔍 Filtro cambiado a:', this.conversationFilter);
|
||||
// Re-renderizar la lista actual sin recargar desde el servidor
|
||||
this.renderConversations();
|
||||
// También recargar desde el servidor para asegurar datos actualizados
|
||||
// (pero esto es secundario y puede ser en background)
|
||||
this.loadConversations(1, false).catch(err => {
|
||||
console.warn('Error recargando conversaciones después de cambiar filtro:', err);
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -2505,8 +2513,16 @@ if (!isset($_SESSION['user_id'])) {
|
||||
}
|
||||
|
||||
console.log('✅ Container encontrado:', container);
|
||||
console.log('🔍 Filtro activo:', this.conversationFilter);
|
||||
|
||||
if (this.conversations.length === 0) {
|
||||
// Aplicar filtro de no leídos
|
||||
let conversationsToShow = this.conversations;
|
||||
if (this.conversationFilter === 'unread') {
|
||||
conversationsToShow = this.conversations.filter(c => (c.unread_count || 0) > 0);
|
||||
console.log(`🔍 Filtro 'unread' aplicado: ${conversationsToShow.length} de ${this.conversations.length} conversaciones`);
|
||||
}
|
||||
|
||||
if (conversationsToShow.length === 0) {
|
||||
const emptyMsg = this.conversationFilter === 'unread' ? 'No hay conversaciones no leídas' : 'No hay conversaciones aún';
|
||||
container.innerHTML = `
|
||||
<div class="text-center p-4">
|
||||
@@ -2518,13 +2534,35 @@ if (!isset($_SESSION['user_id'])) {
|
||||
return;
|
||||
}
|
||||
|
||||
console.log('📋 Generando HTML para', this.conversations.length, 'conversaciones');
|
||||
console.log('📋 Generando HTML para', conversationsToShow.length, 'conversaciones');
|
||||
|
||||
// Ahora el backend devuelve por usuario: last_message, last_time, unread_count y avatar_url
|
||||
const html = this.conversations.map(conv => {
|
||||
const html = conversationsToShow.map(conv => {
|
||||
const isActive = conv.user_id == this.currentUserId ? 'active' : '';
|
||||
const time = this.formatTime(conv.last_time);
|
||||
const preview = this.truncateText(conv.last_message || 'Sin mensajes', 50);
|
||||
|
||||
// Mostrar miniatura si el último mensaje es multimedia y tiene archivo local
|
||||
let preview = '';
|
||||
const hasLocalMedia = conv.last_local_file || conv.last_local_thumb;
|
||||
const isMediaType = conv.message_type && ['image', 'video', 'audio', 'document'].includes(conv.message_type);
|
||||
|
||||
if (hasLocalMedia && isMediaType) {
|
||||
const thumbSrc = conv.last_local_thumb || conv.last_local_file;
|
||||
const mediaIcon = {
|
||||
'image': '🖼️',
|
||||
'video': '🎥',
|
||||
'audio': '🎵',
|
||||
'document': '📎'
|
||||
}[conv.message_type] || '📎';
|
||||
|
||||
if (conv.message_type === 'image' || conv.message_type === 'video') {
|
||||
preview = `<img src="/${thumbSrc}" alt="media" style="width:40px; height:40px; object-fit:cover; border-radius:4px; margin-right:8px; vertical-align:middle;"> ${mediaIcon} ${conv.last_message || 'Multimedia'}`;
|
||||
} else {
|
||||
preview = `${mediaIcon} ${conv.last_message || 'Archivo'}`;
|
||||
}
|
||||
} else {
|
||||
preview = this.truncateText(conv.last_message || 'Sin mensajes', 50);
|
||||
}
|
||||
|
||||
const avatar = conv.avatar_url ? `<img src="${conv.avatar_url}" alt="avatar" class="conversation-avatar-img">` : `<div class="conversation-avatar">${this.getInitials(conv.name)}</div>`;
|
||||
|
||||
@@ -2555,7 +2593,7 @@ if (!isset($_SESSION['user_id'])) {
|
||||
|
||||
console.log('📄 HTML generado, longitud:', html.length, 'caracteres');
|
||||
|
||||
// Detectar nuevas notificaciones: comparar unread counts previos
|
||||
// Detectar nuevas notificaciones: comparar unread counts previos (usar todas las conversaciones, no solo las filtradas)
|
||||
if (!this._prevConversations) this._prevConversations = {};
|
||||
this.conversations.forEach(c => {
|
||||
const prev = this._prevConversations[c.user_id] || { unread_count: 0 };
|
||||
@@ -2690,6 +2728,14 @@ if (!isset($_SESSION['user_id'])) {
|
||||
// Clear any staged messages from a previous conversation and hide indicator
|
||||
try { if (this._stagedMessageIds) { this._stagedMessageIds.clear(); this._stagedCount = 0; this.hideNewMessagesIndicator(); } } catch(e) {}
|
||||
|
||||
// Actualizar inmediatamente el contador de no leídos a 0 en la lista local
|
||||
const conv = this.conversations.find(c => c.user_id === userId);
|
||||
if (conv) {
|
||||
conv.unread_count = 0;
|
||||
// Re-renderizar la lista para reflejar el cambio inmediatamente
|
||||
this.renderConversations();
|
||||
}
|
||||
|
||||
// Actualizar UI
|
||||
document.getElementById('no-conversation').style.display = 'none';
|
||||
document.getElementById('chat-area').style.display = 'flex';
|
||||
@@ -2706,8 +2752,7 @@ if (!isset($_SESSION['user_id'])) {
|
||||
});
|
||||
document.querySelector(`[data-user-id="${userId}"]`)?.classList.add('active');
|
||||
|
||||
// Actualizar estado del toggle del bot según datos de la conversación
|
||||
const conv = this.conversations.find(c => c.user_id === userId);
|
||||
// Actualizar estado del toggle del bot según datos de la conversación (ya obtuvimos conv arriba)
|
||||
if (conv) {
|
||||
const btn = document.getElementById('bot-toggle');
|
||||
const holdIndicator = document.getElementById('hold-indicator');
|
||||
@@ -4744,6 +4789,7 @@ if (!isset($_SESSION['user_id'])) {
|
||||
|
||||
const uploadResponse = await fetch('api/upload_media.php', {
|
||||
method: 'POST',
|
||||
credentials: 'same-origin', // Enviar cookies de sesión
|
||||
body: formData
|
||||
});
|
||||
const uploadContentType = uploadResponse.headers.get('content-type') || '';
|
||||
@@ -4769,6 +4815,7 @@ if (!isset($_SESSION['user_id'])) {
|
||||
|
||||
const sendResponse = await fetch('api/send_media_message.php', {
|
||||
method: 'POST',
|
||||
credentials: 'same-origin', // Enviar cookies de sesión
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
@@ -4834,9 +4881,13 @@ if (!isset($_SESSION['user_id'])) {
|
||||
}
|
||||
|
||||
// Éxito
|
||||
console.log('✅ Archivo enviado exitosamente, recargando mensajes...');
|
||||
this.cancelMediaUpload();
|
||||
await this.loadconversations(this.currentUserId, false);
|
||||
// SSE actualizará las conversaciones automáticamente
|
||||
|
||||
// Recargar mensajes para mostrar el multimedia recién enviado
|
||||
await this.loadMessages(this.currentUserId, true, true);
|
||||
|
||||
// SSE actualizará las conversaciones en la lista automáticamente
|
||||
// this.loadConversations();
|
||||
|
||||
} catch (error) {
|
||||
@@ -4867,27 +4918,60 @@ if (!isset($_SESSION['user_id'])) {
|
||||
renderMediaMessage(message) {
|
||||
if (!message) return '';
|
||||
const mediaType = message.message_type || message.media_type || 'text';
|
||||
const mediaUrl = message.media_url || message.media_url_external || '';
|
||||
const mediaUrl = message.media_url || '';
|
||||
const mediaUrlExternal = message.media_url_external || '';
|
||||
const caption = message.content || '';
|
||||
const localFile = message.local_file || '';
|
||||
const localThumb = message.local_thumb || '';
|
||||
const thumb = localThumb ? (`/${localThumb}`) : (localFile ? (`/${localFile}`) : (message.media_url_external || mediaUrl));
|
||||
|
||||
const messageId = message.id || message.message_id || '';
|
||||
|
||||
// Debug completo del mensaje
|
||||
if (mediaType === 'audio' || mediaType === 'image' || mediaType === 'video') {
|
||||
console.log(`🎵 Media message (${mediaType}) - Datos completos:`, {
|
||||
id: messageId,
|
||||
localFile: localFile,
|
||||
localThumb: localThumb,
|
||||
mediaUrl: mediaUrl,
|
||||
mediaUrlExternal: mediaUrlExternal,
|
||||
hasLocalFile: !!localFile,
|
||||
messageType: mediaType
|
||||
});
|
||||
}
|
||||
|
||||
// Prioridad: archivo local > proxy con DB id > media_url_external > URL externa
|
||||
let full = '';
|
||||
let thumb = '';
|
||||
|
||||
if (localFile) {
|
||||
full = `/api/version/media-url.php?local=${encodeURIComponent(localFile)}`;
|
||||
} else if (message.media_url_external) {
|
||||
if (message.media_url_external.indexOf('api/get_media.php?id=') !== -1) {
|
||||
const parts = message.media_url_external.split('id=');
|
||||
const mid = parts[1] ? decodeURIComponent(parts[1]) : '';
|
||||
full = `/api/version/media-url.php?id=${encodeURIComponent(mid)}`;
|
||||
} else if (/^https?:\/\//i.test(message.media_url_external)) {
|
||||
full = message.media_url_external;
|
||||
} else {
|
||||
full = `/api/version/media-url.php?url=${encodeURIComponent(message.media_url_external)}`;
|
||||
}
|
||||
// ✅ PRIORIDAD 1: Archivo local guardado
|
||||
full = `/${localFile}`;
|
||||
thumb = localThumb ? `/${localThumb}` : `/${localFile}`;
|
||||
console.log('✅ Usando archivo local:', full);
|
||||
} else if (messageId && !mediaUrlExternal) {
|
||||
// ⚠️ PRIORIDAD 2: Usar proxy con el ID de la base de datos solo si no hay media_url_external
|
||||
full = `/api/version/media-url.php?id=${encodeURIComponent(messageId)}`;
|
||||
thumb = full;
|
||||
console.log('⚠️ No hay local_file, usando proxy con messageId:', messageId);
|
||||
} else if (mediaUrlExternal) {
|
||||
// 🔄 PRIORIDAD 3: Usar media_url_external (puede ser api/get_media.php o URL directa)
|
||||
full = mediaUrlExternal.startsWith('/') ? mediaUrlExternal : `/${mediaUrlExternal}`;
|
||||
thumb = full;
|
||||
console.log('🔄 Usando media_url_external:', full);
|
||||
} else if (mediaUrl && /^\d+$/.test(mediaUrl)) {
|
||||
// 📱 PRIORIDAD 4: Es un ID de WhatsApp (solo números)
|
||||
full = `/api/get_media.php?id=${encodeURIComponent(mediaUrl)}`;
|
||||
thumb = full;
|
||||
console.log('📱 Usando whatsapp_media_id con get_media.php:', mediaUrl);
|
||||
} else if (mediaUrl && /^https?:\/\//i.test(mediaUrl)) {
|
||||
// 🌐 PRIORIDAD 5: URL externa directa (puede estar caducada)
|
||||
full = mediaUrl;
|
||||
thumb = mediaUrl;
|
||||
console.log('🌐 Usando URL externa:', full);
|
||||
} else {
|
||||
full = mediaUrl || '';
|
||||
// ❌ Fallback: sin media disponible
|
||||
console.warn('❌ No hay fuente de media disponible para el mensaje', messageId);
|
||||
full = '';
|
||||
thumb = '';
|
||||
}
|
||||
|
||||
switch (mediaType) {
|
||||
@@ -4913,22 +4997,8 @@ if (!isset($_SESSION['user_id'])) {
|
||||
${caption ? `<div>${escapeHtml(caption)}</div>` : ''}
|
||||
`;
|
||||
case 'audio': {
|
||||
let audioSrc = '';
|
||||
if (localFile) {
|
||||
audioSrc = `/${localFile}`;
|
||||
} else if (message.media_url_external) {
|
||||
if (message.media_url_external.indexOf('api/get_media.php?id=') !== -1) {
|
||||
const parts = message.media_url_external.split('id=');
|
||||
const mid = parts[1] ? decodeURIComponent(parts[1]) : '';
|
||||
audioSrc = `/api/version/media-url.php?id=${encodeURIComponent(mid)}`;
|
||||
} else if (/^https?:\/\//i.test(message.media_url_external)) {
|
||||
audioSrc = message.media_url_external;
|
||||
} else {
|
||||
audioSrc = `/api/version/media-url.php?url=${encodeURIComponent(message.media_url_external)}`;
|
||||
}
|
||||
} else {
|
||||
audioSrc = mediaUrl;
|
||||
}
|
||||
// Para audio, usar la misma lógica de full
|
||||
let audioSrc = full;
|
||||
return `
|
||||
<div class="message-media">
|
||||
<audio controls>
|
||||
@@ -4939,20 +5009,7 @@ if (!isset($_SESSION['user_id'])) {
|
||||
`;
|
||||
}
|
||||
case 'document': {
|
||||
let docUrl = '';
|
||||
if (localFile) {
|
||||
docUrl = `/api/version/media-url.php?local=${encodeURIComponent(localFile)}&download=1`;
|
||||
} else if (message.media_url_external) {
|
||||
if (message.media_url_external.indexOf('api/get_media.php?id=') !== -1) {
|
||||
const parts = message.media_url_external.split('id=');
|
||||
const mid = parts[1] ? decodeURIComponent(parts[1]) : '';
|
||||
docUrl = `/api/version/media-url.php?id=${encodeURIComponent(mid)}&download=1`;
|
||||
} else if (/^https?:\/\//i.test(message.media_url_external)) {
|
||||
docUrl = `/api/version/media-url.php?url=${encodeURIComponent(message.media_url_external)}&download=1`;
|
||||
} else {
|
||||
docUrl = `/api/version/media-url.php?url=${encodeURIComponent(message.media_url_external)}&download=1`;
|
||||
}
|
||||
}
|
||||
let docUrl = full;
|
||||
if (!docUrl) {
|
||||
return `
|
||||
<div class="message-document disabled">
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
# Netscape HTTP Cookie File
|
||||
# https://curl.se/docs/http-cookies.html
|
||||
# This file was generated by libcurl! Edit at your own risk.
|
||||
|
||||
#HttpOnly_localhost FALSE / FALSE 0 PHPSESSID daf8a8bcba369b9a7059dea53de6e56d
|
||||
File diff suppressed because one or more lines are too long
Executable
+394
@@ -0,0 +1,394 @@
|
||||
#!/bin/bash
|
||||
|
||||
#############################################################
|
||||
# DEPLOY SCRIPT PARA VPS - WhatsApp Bot
|
||||
#
|
||||
# Uso: ./deploy-vps.sh [opciones]
|
||||
#
|
||||
# Opciones:
|
||||
# --install Primera instalación (instala Docker, etc)
|
||||
# --update Solo actualizar código y reiniciar
|
||||
# --ssl Generar/renovar certificados SSL
|
||||
# --logs Ver logs de la aplicación
|
||||
# --status Ver estado de los contenedores
|
||||
#############################################################
|
||||
|
||||
set -e
|
||||
|
||||
# ==================== CONFIGURACIÓN ====================
|
||||
# Modificar estos valores según tu VPS
|
||||
|
||||
DOMAIN="bot.u-s.app" # Tu dominio
|
||||
EMAIL="admin@u-s.app" # Email para Let's Encrypt
|
||||
APP_DIR="/var/www/whatsapp" # Directorio de la app en VPS
|
||||
COMPOSE_FILE="docker-compose.prod.yml"
|
||||
|
||||
# Colores para output
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
BLUE='\033[0;34m'
|
||||
NC='\033[0m' # No Color
|
||||
|
||||
# ==================== FUNCIONES ====================
|
||||
|
||||
log_info() {
|
||||
echo -e "${BLUE}[INFO]${NC} $1"
|
||||
}
|
||||
|
||||
log_success() {
|
||||
echo -e "${GREEN}[OK]${NC} $1"
|
||||
}
|
||||
|
||||
log_warn() {
|
||||
echo -e "${YELLOW}[WARN]${NC} $1"
|
||||
}
|
||||
|
||||
log_error() {
|
||||
echo -e "${RED}[ERROR]${NC} $1"
|
||||
}
|
||||
|
||||
# Verificar que se ejecuta como root o con sudo
|
||||
check_root() {
|
||||
if [ "$EUID" -ne 0 ]; then
|
||||
log_error "Este script debe ejecutarse como root o con sudo"
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
# Instalar Docker y Docker Compose
|
||||
install_docker() {
|
||||
log_info "Instalando Docker..."
|
||||
|
||||
# Verificar si Docker ya está instalado
|
||||
if command -v docker &> /dev/null; then
|
||||
log_success "Docker ya está instalado: $(docker --version)"
|
||||
else
|
||||
curl -fsSL https://get.docker.com | sh
|
||||
systemctl enable docker
|
||||
systemctl start docker
|
||||
log_success "Docker instalado correctamente"
|
||||
fi
|
||||
|
||||
# Verificar Docker Compose
|
||||
if command -v docker-compose &> /dev/null || docker compose version &> /dev/null; then
|
||||
log_success "Docker Compose disponible"
|
||||
else
|
||||
log_info "Instalando Docker Compose plugin..."
|
||||
apt-get update
|
||||
apt-get install -y docker-compose-plugin
|
||||
log_success "Docker Compose instalado"
|
||||
fi
|
||||
}
|
||||
|
||||
# Instalar Certbot para SSL
|
||||
install_certbot() {
|
||||
log_info "Instalando Certbot para SSL..."
|
||||
|
||||
if command -v certbot &> /dev/null; then
|
||||
log_success "Certbot ya está instalado"
|
||||
else
|
||||
apt-get update
|
||||
apt-get install -y certbot
|
||||
log_success "Certbot instalado"
|
||||
fi
|
||||
}
|
||||
|
||||
# Generar certificados SSL con Let's Encrypt
|
||||
generate_ssl() {
|
||||
log_info "Generando certificados SSL para ${DOMAIN}..."
|
||||
|
||||
# Detener contenedores que usan puerto 80
|
||||
cd "$APP_DIR"
|
||||
docker compose -f "$COMPOSE_FILE" down 2>/dev/null || true
|
||||
|
||||
# Generar certificado
|
||||
certbot certonly \
|
||||
--standalone \
|
||||
--preferred-challenges http \
|
||||
--agree-tos \
|
||||
--email "$EMAIL" \
|
||||
-d "$DOMAIN" \
|
||||
--non-interactive
|
||||
|
||||
if [ -f "/etc/letsencrypt/live/${DOMAIN}/fullchain.pem" ]; then
|
||||
log_success "Certificado SSL generado correctamente"
|
||||
|
||||
# Crear directorio y copiar certificados
|
||||
mkdir -p "$APP_DIR/docker/ssl"
|
||||
cp "/etc/letsencrypt/live/${DOMAIN}/fullchain.pem" "$APP_DIR/docker/ssl/server.crt"
|
||||
cp "/etc/letsencrypt/live/${DOMAIN}/privkey.pem" "$APP_DIR/docker/ssl/server.key"
|
||||
chmod 600 "$APP_DIR/docker/ssl/server.key"
|
||||
|
||||
log_success "Certificados copiados a docker/ssl/"
|
||||
else
|
||||
log_error "Error generando certificado SSL"
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
# Renovar certificados SSL
|
||||
renew_ssl() {
|
||||
log_info "Renovando certificados SSL..."
|
||||
|
||||
cd "$APP_DIR"
|
||||
docker compose -f "$COMPOSE_FILE" stop app 2>/dev/null || true
|
||||
|
||||
certbot renew --standalone
|
||||
|
||||
# Copiar certificados actualizados
|
||||
if [ -f "/etc/letsencrypt/live/${DOMAIN}/fullchain.pem" ]; then
|
||||
cp "/etc/letsencrypt/live/${DOMAIN}/fullchain.pem" "$APP_DIR/docker/ssl/server.crt"
|
||||
cp "/etc/letsencrypt/live/${DOMAIN}/privkey.pem" "$APP_DIR/docker/ssl/server.key"
|
||||
log_success "Certificados renovados"
|
||||
fi
|
||||
|
||||
docker compose -f "$COMPOSE_FILE" start app
|
||||
}
|
||||
|
||||
# Configurar cron para renovación automática de SSL
|
||||
setup_ssl_cron() {
|
||||
log_info "Configurando renovación automática de SSL..."
|
||||
|
||||
CRON_CMD="0 3 * * * cd $APP_DIR && docker compose -f $COMPOSE_FILE stop app && certbot renew --quiet && docker compose -f $COMPOSE_FILE start app"
|
||||
|
||||
# Añadir al crontab si no existe
|
||||
(crontab -l 2>/dev/null | grep -v "certbot renew"; echo "$CRON_CMD") | crontab -
|
||||
|
||||
log_success "Cron configurado para renovar SSL cada día a las 3am"
|
||||
}
|
||||
|
||||
# Crear archivo .env si no existe
|
||||
create_env_file() {
|
||||
if [ ! -f "$APP_DIR/.env" ]; then
|
||||
log_info "Creando archivo .env..."
|
||||
|
||||
cat > "$APP_DIR/.env" << 'EOF'
|
||||
# ============================================
|
||||
# CONFIGURACIÓN DE PRODUCCIÓN
|
||||
# ============================================
|
||||
|
||||
# Base de datos
|
||||
DB_HOST=77.37.126.126
|
||||
DB_PORT=3306
|
||||
DB_NAME=usite_whatsapp_bot
|
||||
DB_USER=usite_whatsapp_user
|
||||
DB_PASS=6q!Vio0fn@PFmsLyHjH5
|
||||
|
||||
# Redis (opcional, dejar vacío si no usa password)
|
||||
REDIS_PASSWORD=
|
||||
|
||||
# WhatsApp API (obtener de Facebook Developer)
|
||||
WHATSAPP_TOKEN=
|
||||
WHATSAPP_PHONE_NUMBER_ID=
|
||||
WEBHOOK_VERIFY_TOKEN=
|
||||
EOF
|
||||
|
||||
log_warn "Archivo .env creado. ¡EDITA LAS CREDENCIALES antes de continuar!"
|
||||
log_warn "Ejecuta: nano $APP_DIR/.env"
|
||||
else
|
||||
log_success "Archivo .env ya existe"
|
||||
fi
|
||||
}
|
||||
|
||||
# Crear directorios necesarios
|
||||
create_directories() {
|
||||
log_info "Creando directorios..."
|
||||
|
||||
mkdir -p "$APP_DIR/logs"
|
||||
mkdir -p "$APP_DIR/uploads"
|
||||
mkdir -p "$APP_DIR/docker/ssl"
|
||||
|
||||
# Permisos
|
||||
chown -R www-data:www-data "$APP_DIR/logs" 2>/dev/null || true
|
||||
chown -R www-data:www-data "$APP_DIR/uploads" 2>/dev/null || true
|
||||
chmod -R 755 "$APP_DIR/logs"
|
||||
chmod -R 755 "$APP_DIR/uploads"
|
||||
|
||||
log_success "Directorios creados"
|
||||
}
|
||||
|
||||
# Construir y levantar contenedores
|
||||
deploy() {
|
||||
log_info "Desplegando aplicación..."
|
||||
|
||||
cd "$APP_DIR"
|
||||
|
||||
# Construir imágenes
|
||||
log_info "Construyendo imágenes Docker..."
|
||||
docker compose -f "$COMPOSE_FILE" build --no-cache
|
||||
|
||||
# Detener contenedores existentes
|
||||
log_info "Deteniendo contenedores anteriores..."
|
||||
docker compose -f "$COMPOSE_FILE" down --remove-orphans 2>/dev/null || true
|
||||
|
||||
# Levantar nuevos contenedores
|
||||
log_info "Levantando contenedores..."
|
||||
docker compose -f "$COMPOSE_FILE" up -d
|
||||
|
||||
# Esperar a que estén listos
|
||||
log_info "Esperando a que los servicios estén listos..."
|
||||
sleep 10
|
||||
|
||||
# Verificar estado
|
||||
if docker compose -f "$COMPOSE_FILE" ps | grep -q "Up"; then
|
||||
log_success "Contenedores ejecutándose correctamente"
|
||||
else
|
||||
log_error "Error iniciando contenedores"
|
||||
docker compose -f "$COMPOSE_FILE" logs --tail=50
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
# Actualizar código y reiniciar
|
||||
update() {
|
||||
log_info "Actualizando aplicación..."
|
||||
|
||||
cd "$APP_DIR"
|
||||
|
||||
# Si es un repo git, hacer pull
|
||||
if [ -d ".git" ]; then
|
||||
log_info "Actualizando desde Git..."
|
||||
git pull origin main || git pull origin master
|
||||
fi
|
||||
|
||||
# Reconstruir y reiniciar
|
||||
docker compose -f "$COMPOSE_FILE" build
|
||||
docker compose -f "$COMPOSE_FILE" up -d
|
||||
|
||||
log_success "Aplicación actualizada"
|
||||
}
|
||||
|
||||
# Ver logs
|
||||
show_logs() {
|
||||
cd "$APP_DIR"
|
||||
docker compose -f "$COMPOSE_FILE" logs -f --tail=100
|
||||
}
|
||||
|
||||
# Ver estado
|
||||
show_status() {
|
||||
cd "$APP_DIR"
|
||||
|
||||
echo ""
|
||||
echo "==================== ESTADO DE CONTENEDORES ===================="
|
||||
docker compose -f "$COMPOSE_FILE" ps
|
||||
|
||||
echo ""
|
||||
echo "==================== USO DE RECURSOS ===================="
|
||||
docker stats --no-stream --format "table {{.Name}}\t{{.CPUPerc}}\t{{.MemUsage}}"
|
||||
|
||||
echo ""
|
||||
echo "==================== VERIFICACIÓN DE SERVICIOS ===================="
|
||||
|
||||
# Verificar HTTP
|
||||
HTTP_STATUS=$(curl -s -o /dev/null -w "%{http_code}" "http://localhost/health.php" 2>/dev/null || echo "ERROR")
|
||||
if [ "$HTTP_STATUS" = "200" ]; then
|
||||
log_success "HTTP: OK (status $HTTP_STATUS)"
|
||||
else
|
||||
log_error "HTTP: FALLO (status $HTTP_STATUS)"
|
||||
fi
|
||||
|
||||
# Verificar HTTPS
|
||||
HTTPS_STATUS=$(curl -sk -o /dev/null -w "%{http_code}" "https://localhost/health.php" 2>/dev/null || echo "ERROR")
|
||||
if [ "$HTTPS_STATUS" = "200" ]; then
|
||||
log_success "HTTPS: OK (status $HTTPS_STATUS)"
|
||||
else
|
||||
log_warn "HTTPS: $HTTPS_STATUS (puede necesitar certificados SSL)"
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo "==================== URLS ===================="
|
||||
echo " App: https://${DOMAIN}"
|
||||
echo " Health: https://${DOMAIN}/health.php"
|
||||
}
|
||||
|
||||
# Primera instalación completa
|
||||
full_install() {
|
||||
check_root
|
||||
|
||||
echo ""
|
||||
echo "=========================================="
|
||||
echo " INSTALACIÓN COMPLETA - WhatsApp Bot"
|
||||
echo "=========================================="
|
||||
echo ""
|
||||
|
||||
install_docker
|
||||
install_certbot
|
||||
create_directories
|
||||
create_env_file
|
||||
|
||||
echo ""
|
||||
log_warn "ANTES DE CONTINUAR:"
|
||||
log_warn "1. Edita el archivo .env con tus credenciales"
|
||||
log_warn "2. Asegúrate que el dominio ${DOMAIN} apunta a este servidor"
|
||||
echo ""
|
||||
read -p "¿Continuar con el deploy? (s/n): " -n 1 -r
|
||||
echo ""
|
||||
|
||||
if [[ $REPLY =~ ^[Ss]$ ]]; then
|
||||
generate_ssl
|
||||
setup_ssl_cron
|
||||
deploy
|
||||
show_status
|
||||
else
|
||||
log_info "Deploy cancelado. Ejecuta './deploy-vps.sh' cuando estés listo."
|
||||
fi
|
||||
}
|
||||
|
||||
# Mostrar ayuda
|
||||
show_help() {
|
||||
echo ""
|
||||
echo "Uso: ./deploy-vps.sh [opción]"
|
||||
echo ""
|
||||
echo "Opciones:"
|
||||
echo " --install Primera instalación completa"
|
||||
echo " --update Actualizar código y reiniciar"
|
||||
echo " --ssl Generar/renovar certificados SSL"
|
||||
echo " --logs Ver logs en tiempo real"
|
||||
echo " --status Ver estado de servicios"
|
||||
echo " --help Mostrar esta ayuda"
|
||||
echo ""
|
||||
echo "Ejemplos:"
|
||||
echo " sudo ./deploy-vps.sh --install # Primera vez"
|
||||
echo " sudo ./deploy-vps.sh --update # Actualizar"
|
||||
echo " ./deploy-vps.sh --logs # Ver logs"
|
||||
echo ""
|
||||
}
|
||||
|
||||
# ==================== MAIN ====================
|
||||
|
||||
case "${1:-}" in
|
||||
--install)
|
||||
full_install
|
||||
;;
|
||||
--update)
|
||||
update
|
||||
;;
|
||||
--ssl)
|
||||
check_root
|
||||
generate_ssl
|
||||
;;
|
||||
--renew-ssl)
|
||||
check_root
|
||||
renew_ssl
|
||||
;;
|
||||
--logs)
|
||||
show_logs
|
||||
;;
|
||||
--status)
|
||||
show_status
|
||||
;;
|
||||
--help|-h)
|
||||
show_help
|
||||
;;
|
||||
*)
|
||||
# Sin argumentos, hacer deploy normal
|
||||
if [ ! -d "$APP_DIR" ] || [ ! -f "$APP_DIR/$COMPOSE_FILE" ]; then
|
||||
log_error "Directorio de aplicación no encontrado: $APP_DIR"
|
||||
log_info "Para primera instalación usa: sudo ./deploy-vps.sh --install"
|
||||
exit 1
|
||||
fi
|
||||
deploy
|
||||
show_status
|
||||
;;
|
||||
esac
|
||||
+69
-11
@@ -2,6 +2,31 @@
|
||||
# Uso: docker-compose -f docker-compose.dev.yml up -d
|
||||
|
||||
services:
|
||||
# MySQL Database
|
||||
mysql:
|
||||
image: mysql:8.0
|
||||
container_name: whatsapp-dev-mysql
|
||||
restart: unless-stopped
|
||||
ports:
|
||||
- "3306:3306"
|
||||
environment:
|
||||
MYSQL_ROOT_PASSWORD: ${DB_ROOT_PASSWORD:-root_password_2026}
|
||||
MYSQL_DATABASE: ${DB_NAME:-usite_whatsapp_bot}
|
||||
MYSQL_USER: ${DB_USER:-usite_whatsapp_user}
|
||||
MYSQL_PASSWORD: ${DB_PASS:-6q!Vio0fn@PFmsLyHjH5}
|
||||
volumes:
|
||||
- mysql-dev-data:/var/lib/mysql
|
||||
- ./database:/docker-entrypoint-initdb.d:ro
|
||||
command: --default-authentication-plugin=mysql_native_password --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci
|
||||
networks:
|
||||
- whatsapp-dev-network
|
||||
healthcheck:
|
||||
test: ["CMD", "mysqladmin", "ping", "-h", "localhost", "-u", "root", "-p${DB_ROOT_PASSWORD:-root_password_2026}"]
|
||||
interval: 10s
|
||||
timeout: 5s
|
||||
retries: 5
|
||||
start_period: 30s
|
||||
|
||||
# Aplicación PHP con Nginx - MODO DEV
|
||||
app:
|
||||
build:
|
||||
@@ -13,25 +38,28 @@ services:
|
||||
restart: unless-stopped
|
||||
working_dir: /var/www/html
|
||||
ports:
|
||||
- "8080:80" # Aplicación web
|
||||
- "8080:80" # HTTP
|
||||
- "8443:443" # HTTPS
|
||||
- "9003:9003" # XDebug (para IDEs)
|
||||
volumes:
|
||||
# Hot-reload: cambios en código se reflejan inmediatamente
|
||||
- ./:/var/www/html
|
||||
- ./logs:/var/www/html/logs
|
||||
- ./uploads:/var/www/html/uploads
|
||||
- ./docker/nginx/ssl.conf:/etc/nginx/http.d/ssl.conf:ro
|
||||
- ssl-certs:/etc/nginx/ssl
|
||||
- php-socket:/run/php
|
||||
environment:
|
||||
# Entorno de desarrollo
|
||||
- APP_ENV=development
|
||||
- APP_DEBUG=true
|
||||
|
||||
# Base de datos
|
||||
- DB_HOST=${DB_HOST}
|
||||
# Base de datos - apuntar a MySQL local
|
||||
- DB_HOST=mysql
|
||||
- DB_PORT=${DB_PORT:-3306}
|
||||
- DB_NAME=${DB_NAME}
|
||||
- DB_USER=${DB_USER}
|
||||
- DB_PASS=${DB_PASS}
|
||||
- DB_NAME=${DB_NAME:-usite_whatsapp_bot}
|
||||
- DB_USER=${DB_USER:-usite_whatsapp_user}
|
||||
- DB_PASS=${DB_PASS:-6q!Vio0fn@PFmsLyHjH5}
|
||||
|
||||
# Redis
|
||||
- REDIS_HOST=redis
|
||||
@@ -62,6 +90,8 @@ services:
|
||||
depends_on:
|
||||
redis:
|
||||
condition: service_healthy
|
||||
mysql:
|
||||
condition: service_healthy
|
||||
networks:
|
||||
- whatsapp-dev-network
|
||||
healthcheck:
|
||||
@@ -109,11 +139,11 @@ services:
|
||||
environment:
|
||||
- APP_ENV=development
|
||||
- APP_DEBUG=true
|
||||
- DB_HOST=${DB_HOST}
|
||||
- DB_HOST=mysql
|
||||
- DB_PORT=${DB_PORT:-3306}
|
||||
- DB_NAME=${DB_NAME}
|
||||
- DB_USER=${DB_USER}
|
||||
- DB_PASS=${DB_PASS}
|
||||
- DB_NAME=${DB_NAME:-usite_whatsapp_bot}
|
||||
- DB_USER=${DB_USER:-usite_whatsapp_user}
|
||||
- DB_PASS=${DB_PASS:-6q!Vio0fn@PFmsLyHjH5}
|
||||
- REDIS_HOST=redis
|
||||
- REDIS_PORT=6379
|
||||
- REDIS_PASSWORD=${REDIS_PASSWORD:-}
|
||||
@@ -123,6 +153,8 @@ services:
|
||||
depends_on:
|
||||
redis:
|
||||
condition: service_healthy
|
||||
mysql:
|
||||
condition: service_healthy
|
||||
networks:
|
||||
- whatsapp-dev-network
|
||||
command: php worker.php --daemon
|
||||
@@ -161,14 +193,40 @@ services:
|
||||
ports:
|
||||
- "8083:8080"
|
||||
environment:
|
||||
- ADMINER_DEFAULT_SERVER=${DB_HOST}
|
||||
- ADMINER_DEFAULT_SERVER=mysql
|
||||
- ADMINER_DESIGN=nette
|
||||
depends_on:
|
||||
mysql:
|
||||
condition: service_healthy
|
||||
networks:
|
||||
- whatsapp-dev-network
|
||||
|
||||
# phpMyAdmin - Gestor de base de datos alternativo
|
||||
phpmyadmin:
|
||||
image: phpmyadmin:latest
|
||||
container_name: whatsapp-dev-phpmyadmin
|
||||
restart: unless-stopped
|
||||
ports:
|
||||
- "8084:80"
|
||||
environment:
|
||||
PMA_HOST: mysql
|
||||
PMA_PORT: 3306
|
||||
PMA_USER: ${DB_USER:-usite_whatsapp_user}
|
||||
PMA_PASSWORD: ${DB_PASS:-6q!Vio0fn@PFmsLyHjH5}
|
||||
UPLOAD_LIMIT: 100M
|
||||
depends_on:
|
||||
mysql:
|
||||
condition: service_healthy
|
||||
networks:
|
||||
- whatsapp-dev-network
|
||||
|
||||
volumes:
|
||||
mysql-dev-data:
|
||||
driver: local
|
||||
redis-dev-data:
|
||||
driver: local
|
||||
ssl-certs:
|
||||
driver: local
|
||||
php-socket:
|
||||
driver: local
|
||||
|
||||
|
||||
@@ -0,0 +1,124 @@
|
||||
# Docker Compose para PRODUCCIÓN
|
||||
# Uso: docker-compose -f docker-compose.prod.yml up -d
|
||||
|
||||
services:
|
||||
# Aplicación PHP con Nginx - MODO PRODUCCIÓN
|
||||
app:
|
||||
build:
|
||||
context: .
|
||||
dockerfile: Dockerfile
|
||||
args:
|
||||
- APP_ENV=production
|
||||
container_name: whatsapp-app
|
||||
restart: always
|
||||
ports:
|
||||
- "80:80"
|
||||
- "443:443"
|
||||
volumes:
|
||||
- ./logs:/var/www/html/logs
|
||||
- ./uploads:/var/www/html/uploads
|
||||
- ./docker/nginx/ssl.conf:/etc/nginx/http.d/ssl.conf:ro
|
||||
- /etc/letsencrypt:/etc/letsencrypt:ro
|
||||
- ssl-certs:/etc/nginx/ssl
|
||||
environment:
|
||||
# Entorno
|
||||
- APP_ENV=production
|
||||
- APP_DEBUG=false
|
||||
|
||||
# Base de datos - usar base de datos externa (producción actual)
|
||||
- DB_HOST=${DB_HOST:-77.37.126.126}
|
||||
- DB_PORT=${DB_PORT:-3306}
|
||||
- DB_NAME=${DB_NAME:-usite_whatsapp_bot}
|
||||
- DB_USER=${DB_USER:-usite_whatsapp_user}
|
||||
- DB_PASS=${DB_PASS}
|
||||
|
||||
# Redis
|
||||
- REDIS_HOST=redis
|
||||
- REDIS_PORT=6379
|
||||
- REDIS_PASSWORD=${REDIS_PASSWORD:-}
|
||||
|
||||
# WhatsApp API
|
||||
- WHATSAPP_TOKEN=${WHATSAPP_TOKEN}
|
||||
- WHATSAPP_PHONE_NUMBER_ID=${WHATSAPP_PHONE_NUMBER_ID}
|
||||
- WEBHOOK_VERIFY_TOKEN=${WEBHOOK_VERIFY_TOKEN}
|
||||
|
||||
# Configuración de producción
|
||||
- LOG_LEVEL=WARNING
|
||||
- ENABLE_RATE_LIMIT=true
|
||||
- DISPLAY_ERRORS=0
|
||||
- ERROR_REPORTING=0
|
||||
|
||||
# PHP optimizado para producción
|
||||
- PHP_MEMORY_LIMIT=256M
|
||||
- PHP_MAX_EXECUTION_TIME=60
|
||||
- PHP_OPCACHE_ENABLE=1
|
||||
|
||||
depends_on:
|
||||
redis:
|
||||
condition: service_healthy
|
||||
networks:
|
||||
- whatsapp-network
|
||||
healthcheck:
|
||||
test: ["CMD", "curl", "-f", "http://localhost/health.php"]
|
||||
interval: 30s
|
||||
timeout: 5s
|
||||
retries: 3
|
||||
start_period: 30s
|
||||
|
||||
# Redis para colas y caché
|
||||
redis:
|
||||
image: redis:7-alpine
|
||||
container_name: whatsapp-redis
|
||||
restart: always
|
||||
command: >
|
||||
redis-server
|
||||
--appendonly yes
|
||||
--maxmemory 128mb
|
||||
--maxmemory-policy allkeys-lru
|
||||
volumes:
|
||||
- redis-data:/data
|
||||
networks:
|
||||
- whatsapp-network
|
||||
healthcheck:
|
||||
test: ["CMD", "redis-cli", "ping"]
|
||||
interval: 10s
|
||||
timeout: 3s
|
||||
retries: 5
|
||||
|
||||
# Workers para procesamiento en background
|
||||
worker:
|
||||
build:
|
||||
context: .
|
||||
dockerfile: Dockerfile.worker
|
||||
container_name: whatsapp-worker
|
||||
restart: always
|
||||
volumes:
|
||||
- ./logs:/var/www/html/logs
|
||||
environment:
|
||||
- APP_ENV=production
|
||||
- APP_DEBUG=false
|
||||
- DB_HOST=${DB_HOST:-77.37.126.126}
|
||||
- DB_PORT=${DB_PORT:-3306}
|
||||
- DB_NAME=${DB_NAME:-usite_whatsapp_bot}
|
||||
- DB_USER=${DB_USER:-usite_whatsapp_user}
|
||||
- DB_PASS=${DB_PASS}
|
||||
- REDIS_HOST=redis
|
||||
- REDIS_PORT=6379
|
||||
- REDIS_PASSWORD=${REDIS_PASSWORD:-}
|
||||
- LOG_LEVEL=WARNING
|
||||
depends_on:
|
||||
redis:
|
||||
condition: service_healthy
|
||||
networks:
|
||||
- whatsapp-network
|
||||
command: php worker.php --daemon
|
||||
|
||||
volumes:
|
||||
redis-data:
|
||||
driver: local
|
||||
ssl-certs:
|
||||
driver: local
|
||||
|
||||
networks:
|
||||
whatsapp-network:
|
||||
driver: bridge
|
||||
@@ -17,6 +17,11 @@ echo "📁 Creando directorios..."
|
||||
mkdir -p /var/www/html/logs
|
||||
mkdir -p /var/www/html/uploads
|
||||
mkdir -p /run/php
|
||||
mkdir -p /var/lib/nginx/tmp/client_body
|
||||
mkdir -p /var/lib/nginx/tmp/proxy
|
||||
mkdir -p /var/lib/nginx/tmp/fastcgi
|
||||
mkdir -p /var/lib/nginx/tmp/uwsgi
|
||||
mkdir -p /var/lib/nginx/tmp/scgi
|
||||
|
||||
# Establecer permisos
|
||||
echo "🔐 Configurando permisos..."
|
||||
@@ -24,6 +29,8 @@ chown -R www-data:www-data /var/www/html/logs
|
||||
chown -R www-data:www-data /var/www/html/uploads
|
||||
chmod -R 755 /var/www/html/logs
|
||||
chmod -R 755 /var/www/html/uploads
|
||||
chown -R nginx:nginx /var/lib/nginx/tmp
|
||||
chmod -R 755 /var/lib/nginx/tmp
|
||||
|
||||
# Información de desarrollo
|
||||
echo ""
|
||||
|
||||
+51
-11
@@ -13,16 +13,25 @@ until redis-cli -h ${REDIS_HOST:-redis} ping 2>/dev/null; do
|
||||
done
|
||||
echo "✅ Redis conectado"
|
||||
|
||||
# Esperar a que MySQL esté disponible (solo si no es localhost ni IP interna)
|
||||
if [ "${DB_HOST}" != "localhost" ] && [ "${DB_HOST}" != "127.0.0.1" ] && [ "${DB_HOST}" != "db" ]; then
|
||||
echo "ℹ️ Usando base de datos externa (${DB_HOST}), omitiendo verificación de conectividad..."
|
||||
else
|
||||
echo "⏳ Esperando MySQL..."
|
||||
until mysql -h ${DB_HOST:-db} -u ${DB_USER:-whatsapp_user} -p${DB_PASS} -e "SELECT 1" >/dev/null 2>&1; do
|
||||
echo " MySQL no disponible, esperando..."
|
||||
# Esperar a que MySQL esté disponible
|
||||
if [ "${DB_HOST}" = "mysql" ] || [ "${DB_HOST}" = "db" ]; then
|
||||
echo "⏳ Esperando MySQL local..."
|
||||
MAX_RETRIES=30
|
||||
RETRY=0
|
||||
until mariadb -h "${DB_HOST:-mysql}" -u "${DB_USER:-whatsapp_user}" -p"${DB_PASS}" --skip-ssl -e "SELECT 1" >/dev/null 2>&1; do
|
||||
RETRY=$((RETRY + 1))
|
||||
if [ $RETRY -ge $MAX_RETRIES ]; then
|
||||
echo "⚠️ MySQL no disponible después de $MAX_RETRIES intentos, continuando..."
|
||||
break
|
||||
fi
|
||||
echo " MySQL no disponible, intento $RETRY/$MAX_RETRIES..."
|
||||
sleep 2
|
||||
done
|
||||
echo "✅ MySQL conectado"
|
||||
if [ $RETRY -lt $MAX_RETRIES ]; then
|
||||
echo "✅ MySQL conectado"
|
||||
fi
|
||||
elif [ "${DB_HOST}" != "localhost" ] && [ "${DB_HOST}" != "127.0.0.1" ]; then
|
||||
echo "ℹ️ Usando base de datos externa (${DB_HOST}), omitiendo verificación de conectividad..."
|
||||
fi
|
||||
|
||||
# Crear directorios si no existen
|
||||
@@ -30,12 +39,43 @@ mkdir -p /var/www/html/logs
|
||||
mkdir -p /var/www/html/uploads
|
||||
mkdir -p /var/cache/nginx
|
||||
mkdir -p /run/php
|
||||
mkdir -p /var/lib/nginx/tmp/client_body
|
||||
mkdir -p /var/lib/nginx/tmp/proxy
|
||||
mkdir -p /var/lib/nginx/tmp/fastcgi
|
||||
mkdir -p /var/lib/nginx/tmp/uwsgi
|
||||
mkdir -p /var/lib/nginx/tmp/scgi
|
||||
|
||||
# Establecer permisos
|
||||
# Establecer permisos ANTES de iniciar servicios
|
||||
chown -R www:www /var/www/html/logs
|
||||
chown -R www:www /var/www/html/uploads
|
||||
chmod -R 755 /var/www/html/logs
|
||||
chmod -R 755 /var/www/html/uploads
|
||||
chmod -R 775 /var/www/html/logs
|
||||
chmod -R 775 /var/www/html/uploads
|
||||
|
||||
# IMPORTANTE: nginx necesita acceso a sus directorios temporales
|
||||
# Usar grupo nginx para compartir acceso entre nginx y www
|
||||
chown -R nginx:nginx /var/lib/nginx
|
||||
chmod -R 775 /var/lib/nginx/tmp
|
||||
|
||||
# Generar certificados SSL si no existen
|
||||
SSL_DIR="/etc/nginx/ssl"
|
||||
if [ ! -f "$SSL_DIR/server.crt" ] || [ ! -f "$SSL_DIR/server.key" ]; then
|
||||
echo "🔐 Generando certificados SSL autofirmados..."
|
||||
mkdir -p "$SSL_DIR"
|
||||
openssl req -x509 -nodes -days 365 -newkey rsa:2048 \
|
||||
-keyout "$SSL_DIR/server.key" \
|
||||
-out "$SSL_DIR/server.crt" \
|
||||
-subj "/C=CO/ST=Cundinamarca/L=Bogota/O=U-Site/OU=WhatsApp Bot/CN=bot.u-s.app" \
|
||||
-addext "subjectAltName=DNS:bot.u-s.app,DNS:localhost,DNS:*.u-s.app,IP:127.0.0.1" 2>/dev/null || \
|
||||
openssl req -x509 -nodes -days 365 -newkey rsa:2048 \
|
||||
-keyout "$SSL_DIR/server.key" \
|
||||
-out "$SSL_DIR/server.crt" \
|
||||
-subj "/C=CO/ST=Cundinamarca/L=Bogota/O=U-Site/OU=WhatsApp Bot/CN=bot.u-s.app"
|
||||
chmod 600 "$SSL_DIR/server.key"
|
||||
chmod 644 "$SSL_DIR/server.crt"
|
||||
echo "✅ Certificados SSL generados para bot.u-s.app"
|
||||
else
|
||||
echo "✅ Certificados SSL existentes encontrados"
|
||||
fi
|
||||
|
||||
# Ejecutar migraciones de BD (si existen)
|
||||
if [ -f /var/www/html/database/migrate.php ]; then
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
#!/bin/bash
|
||||
# Script para corregir permisos después de que nginx inicie
|
||||
|
||||
sleep 2
|
||||
|
||||
# Corregir permisos de directorios nginx
|
||||
chown -R nginx:nginx /var/lib/nginx
|
||||
chmod -R 755 /var/lib/nginx/tmp
|
||||
|
||||
echo "✅ Permisos de nginx corregidos"
|
||||
@@ -1,4 +1,4 @@
|
||||
user www;
|
||||
user nginx;
|
||||
worker_processes auto;
|
||||
error_log /var/log/nginx/error.log warn;
|
||||
pid /var/run/nginx.pid;
|
||||
|
||||
@@ -0,0 +1,97 @@
|
||||
# Configuración HTTPS para producción con Let's Encrypt
|
||||
# Este archivo se monta en: /etc/nginx/http.d/ssl.conf
|
||||
|
||||
# Redirigir HTTP a HTTPS
|
||||
server {
|
||||
listen 80;
|
||||
listen [::]:80;
|
||||
server_name bot.u-s.app;
|
||||
|
||||
# Permitir verificación de Let's Encrypt
|
||||
location /.well-known/acme-challenge/ {
|
||||
root /var/www/html;
|
||||
}
|
||||
|
||||
# Redirigir todo lo demás a HTTPS
|
||||
location / {
|
||||
return 301 https://$host$request_uri;
|
||||
}
|
||||
}
|
||||
|
||||
# HTTPS Server
|
||||
server {
|
||||
listen 443 ssl;
|
||||
listen [::]:443 ssl;
|
||||
server_name bot.u-s.app;
|
||||
|
||||
# Certificados SSL de Let's Encrypt
|
||||
ssl_certificate /etc/letsencrypt/live/bot.u-s.app/fullchain.pem;
|
||||
ssl_certificate_key /etc/letsencrypt/live/bot.u-s.app/privkey.pem;
|
||||
|
||||
# Configuración SSL moderna
|
||||
ssl_protocols TLSv1.2 TLSv1.3;
|
||||
ssl_prefer_server_ciphers on;
|
||||
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384;
|
||||
|
||||
# HSTS (descomentar en producción después de verificar que SSL funciona)
|
||||
# add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
|
||||
|
||||
# Headers de seguridad
|
||||
add_header X-Frame-Options "SAMEORIGIN" always;
|
||||
add_header X-Content-Type-Options "nosniff" always;
|
||||
add_header X-XSS-Protection "1; mode=block" always;
|
||||
|
||||
# Root y configuración PHP
|
||||
root /var/www/html;
|
||||
index index.php index.html;
|
||||
|
||||
# Tamaño máximo de upload
|
||||
client_max_body_size 50M;
|
||||
|
||||
# Logs
|
||||
access_log /var/log/nginx/ssl_access.log;
|
||||
error_log /var/log/nginx/ssl_error.log;
|
||||
|
||||
# PHP-FPM
|
||||
location ~ \.php$ {
|
||||
try_files $uri =404;
|
||||
fastcgi_split_path_info ^(.+\.php)(/.+)$;
|
||||
fastcgi_pass unix:/run/php/php-fpm.sock;
|
||||
fastcgi_index index.php;
|
||||
include fastcgi_params;
|
||||
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
|
||||
fastcgi_param PATH_INFO $fastcgi_path_info;
|
||||
fastcgi_param HTTPS on;
|
||||
fastcgi_read_timeout 300;
|
||||
}
|
||||
|
||||
# API endpoints
|
||||
location /api/ {
|
||||
try_files $uri $uri/ /api/index.php?$query_string;
|
||||
}
|
||||
|
||||
# Webhook
|
||||
location /webhook {
|
||||
try_files $uri $uri/ /webhook.php?$query_string;
|
||||
}
|
||||
|
||||
# Archivos estáticos - cache agresivo
|
||||
location ~* \.(css|js|jpg|jpeg|png|gif|ico|svg|woff|woff2|ttf|eot)$ {
|
||||
expires 30d;
|
||||
add_header Cache-Control "public, immutable";
|
||||
}
|
||||
|
||||
# Denegar acceso a archivos sensibles
|
||||
location ~ /\. {
|
||||
deny all;
|
||||
}
|
||||
|
||||
location ~ /(config|logs|backups|database)/ {
|
||||
deny all;
|
||||
}
|
||||
|
||||
# Fallback
|
||||
location / {
|
||||
try_files $uri $uri/ /index.php?$query_string;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,185 @@
|
||||
# Configuración SSL para bot.u-s.app
|
||||
server {
|
||||
listen 443 ssl http2;
|
||||
listen [::]:443 ssl http2;
|
||||
server_name bot.u-s.app localhost;
|
||||
root /var/www/html;
|
||||
index index.php index.html;
|
||||
|
||||
# SSL Certificates
|
||||
ssl_certificate /etc/nginx/ssl/server.crt;
|
||||
ssl_certificate_key /etc/nginx/ssl/server.key;
|
||||
|
||||
# SSL Configuration
|
||||
ssl_session_timeout 1d;
|
||||
ssl_session_cache shared:SSL:50m;
|
||||
ssl_session_tickets off;
|
||||
|
||||
# Modern TLS configuration
|
||||
ssl_protocols TLSv1.2 TLSv1.3;
|
||||
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384;
|
||||
ssl_prefer_server_ciphers off;
|
||||
|
||||
# Security headers
|
||||
add_header X-Frame-Options "SAMEORIGIN" always;
|
||||
add_header X-Content-Type-Options "nosniff" always;
|
||||
add_header X-XSS-Protection "1; mode=block" always;
|
||||
add_header Referrer-Policy "no-referrer-when-downgrade" always;
|
||||
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
|
||||
|
||||
# Logs
|
||||
access_log /var/log/nginx/whatsapp-ssl-access.log;
|
||||
error_log /var/log/nginx/whatsapp-ssl-error.log warn;
|
||||
|
||||
# Aumentar timeouts para webhook
|
||||
fastcgi_read_timeout 300;
|
||||
fastcgi_send_timeout 300;
|
||||
proxy_read_timeout 300;
|
||||
proxy_send_timeout 300;
|
||||
|
||||
# Root location
|
||||
location / {
|
||||
try_files $uri $uri/ /index.php?$query_string;
|
||||
}
|
||||
|
||||
# PHP files
|
||||
location ~ \.php$ {
|
||||
try_files $uri =404;
|
||||
fastcgi_split_path_info ^(.+\.php)(/.+)$;
|
||||
fastcgi_pass 127.0.0.1:9000;
|
||||
fastcgi_index index.php;
|
||||
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
|
||||
include fastcgi_params;
|
||||
|
||||
# FastCGI buffers
|
||||
fastcgi_buffers 16 16k;
|
||||
fastcgi_buffer_size 32k;
|
||||
|
||||
# Importante para que webhook responda rápido
|
||||
fastcgi_buffering off;
|
||||
}
|
||||
|
||||
# Webhook endpoint
|
||||
location ~ ^/api/webhook(_optimized)?\.php$ {
|
||||
fastcgi_pass 127.0.0.1:9000;
|
||||
fastcgi_index webhook_optimized.php;
|
||||
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
|
||||
include fastcgi_params;
|
||||
|
||||
fastcgi_buffering off;
|
||||
fastcgi_request_buffering off;
|
||||
fastcgi_read_timeout 60;
|
||||
fastcgi_send_timeout 60;
|
||||
|
||||
add_header Cache-Control "no-store, no-cache, must-revalidate";
|
||||
expires off;
|
||||
}
|
||||
|
||||
# Health check endpoint
|
||||
location /health.php {
|
||||
fastcgi_pass 127.0.0.1:9000;
|
||||
fastcgi_param SCRIPT_FILENAME $document_root/health.php;
|
||||
include fastcgi_params;
|
||||
access_log off;
|
||||
}
|
||||
|
||||
# Static assets caching
|
||||
location ~* \.(jpg|jpeg|png|gif|ico|css|js|svg|woff|woff2|ttf|eot)$ {
|
||||
expires 30d;
|
||||
add_header Cache-Control "public, immutable";
|
||||
access_log off;
|
||||
}
|
||||
|
||||
# Deny access to hidden files
|
||||
location ~ /\. {
|
||||
deny all;
|
||||
access_log off;
|
||||
log_not_found off;
|
||||
}
|
||||
|
||||
# Deny access to sensitive files
|
||||
location ~ /(?:composer\.json|composer\.lock|package\.json|\.env|\.git) {
|
||||
deny all;
|
||||
access_log off;
|
||||
log_not_found off;
|
||||
}
|
||||
|
||||
# Uploads directory
|
||||
location ^~ /uploads/ {
|
||||
alias /var/www/html/uploads/;
|
||||
autoindex off;
|
||||
|
||||
# Security: solo permitir ciertos tipos de archivo
|
||||
location ~* \.(php|phtml|php3|php4|php5|pl|py|cgi|sh)$ {
|
||||
deny all;
|
||||
}
|
||||
}
|
||||
|
||||
# SSE endpoint
|
||||
location ~ ^/api/sse.*\.php$ {
|
||||
fastcgi_pass 127.0.0.1:9000;
|
||||
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
|
||||
include fastcgi_params;
|
||||
|
||||
fastcgi_buffering off;
|
||||
fastcgi_cache off;
|
||||
proxy_buffering off;
|
||||
chunked_transfer_encoding off;
|
||||
|
||||
fastcgi_read_timeout 3600;
|
||||
fastcgi_send_timeout 3600;
|
||||
keepalive_timeout 3600;
|
||||
|
||||
add_header Content-Type text/event-stream;
|
||||
add_header Cache-Control no-cache;
|
||||
add_header X-Accel-Buffering no;
|
||||
}
|
||||
}
|
||||
|
||||
# Redirección HTTP a HTTPS
|
||||
server {
|
||||
listen 80;
|
||||
listen [::]:80;
|
||||
server_name _;
|
||||
|
||||
# Para desarrollo, mantener HTTP disponible
|
||||
# Descomentar las siguientes líneas para forzar HTTPS:
|
||||
# return 301 https://$host$request_uri;
|
||||
|
||||
# Por ahora, servir también en HTTP
|
||||
root /var/www/html;
|
||||
index index.php index.html;
|
||||
|
||||
location / {
|
||||
try_files $uri $uri/ /index.php?$query_string;
|
||||
}
|
||||
|
||||
location ~ \.php$ {
|
||||
try_files $uri =404;
|
||||
fastcgi_split_path_info ^(.+\.php)(/.+)$;
|
||||
fastcgi_pass 127.0.0.1:9000;
|
||||
fastcgi_index index.php;
|
||||
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
|
||||
include fastcgi_params;
|
||||
fastcgi_buffers 16 16k;
|
||||
fastcgi_buffer_size 32k;
|
||||
fastcgi_buffering off;
|
||||
}
|
||||
|
||||
location /health.php {
|
||||
fastcgi_pass 127.0.0.1:9000;
|
||||
fastcgi_param SCRIPT_FILENAME $document_root/health.php;
|
||||
include fastcgi_params;
|
||||
access_log off;
|
||||
}
|
||||
|
||||
location ~* \.(jpg|jpeg|png|gif|ico|css|js|svg|woff|woff2|ttf|eot)$ {
|
||||
expires 30d;
|
||||
add_header Cache-Control "public, immutable";
|
||||
access_log off;
|
||||
}
|
||||
|
||||
location ~ /\. {
|
||||
deny all;
|
||||
}
|
||||
}
|
||||
@@ -21,7 +21,8 @@ php_admin_value[error_log] = /var/log/php-fpm-error.log
|
||||
|
||||
; Security
|
||||
; Nota: curl_exec y curl_multi_exec son necesarios para WhatsApp API
|
||||
php_admin_value[disable_functions] = exec,passthru,shell_exec,system,proc_open,popen,parse_ini_file,show_source
|
||||
; shell_exec habilitado para conversión de medios con ffmpeg
|
||||
php_admin_value[disable_functions] = exec,passthru,system,proc_open,popen,parse_ini_file,show_source
|
||||
|
||||
; Performance
|
||||
request_terminate_timeout = 300s
|
||||
|
||||
@@ -20,6 +20,7 @@ date.timezone = America/Bogota
|
||||
expose_php = Off
|
||||
allow_url_fopen = On
|
||||
allow_url_include = Off
|
||||
disable_functions =
|
||||
|
||||
; Session
|
||||
session.save_handler = redis
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
#!/bin/sh
|
||||
# Script para generar certificados SSL autofirmados para desarrollo
|
||||
|
||||
SSL_DIR="/etc/nginx/ssl"
|
||||
|
||||
# Crear directorio si no existe
|
||||
mkdir -p "$SSL_DIR"
|
||||
|
||||
# Verificar si ya existen los certificados
|
||||
if [ -f "$SSL_DIR/server.crt" ] && [ -f "$SSL_DIR/server.key" ]; then
|
||||
echo "✅ Certificados SSL ya existen en $SSL_DIR"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
echo "🔐 Generando certificados SSL autofirmados para desarrollo..."
|
||||
|
||||
# Generar clave privada y certificado autofirmado
|
||||
openssl req -x509 -nodes -days 365 -newkey rsa:2048 \
|
||||
-keyout "$SSL_DIR/server.key" \
|
||||
-out "$SSL_DIR/server.crt" \
|
||||
-subj "/C=CO/ST=Cundinamarca/L=Bogota/O=WhatsApp Bot Dev/OU=Development/CN=localhost" \
|
||||
-addext "subjectAltName=DNS:localhost,DNS:*.localhost,IP:127.0.0.1"
|
||||
|
||||
# Establecer permisos correctos
|
||||
chmod 600 "$SSL_DIR/server.key"
|
||||
chmod 644 "$SSL_DIR/server.crt"
|
||||
|
||||
echo "✅ Certificados SSL generados exitosamente:"
|
||||
echo " - Certificado: $SSL_DIR/server.crt"
|
||||
echo " - Clave: $SSL_DIR/server.key"
|
||||
echo ""
|
||||
echo "⚠️ NOTA: Estos son certificados autofirmados para DESARROLLO."
|
||||
echo " Los navegadores mostrarán advertencias de seguridad."
|
||||
echo " Para producción, usa certificados de Let's Encrypt u otra CA."
|
||||
@@ -0,0 +1,28 @@
|
||||
<?php
|
||||
/**
|
||||
* Script para actualizar local_thumb en mensajes existentes
|
||||
* que tienen local_file pero no tienen local_thumb
|
||||
*/
|
||||
|
||||
require_once __DIR__ . '/classes/Database.php';
|
||||
|
||||
try {
|
||||
$db = new Database();
|
||||
|
||||
// Actualizar mensajes de tipo image/video que tienen local_file pero no local_thumb
|
||||
$sql = "UPDATE conversations
|
||||
SET local_thumb = local_file
|
||||
WHERE message_type IN ('image', 'video')
|
||||
AND local_file IS NOT NULL
|
||||
AND local_file != ''
|
||||
AND (local_thumb IS NULL OR local_thumb = '')";
|
||||
|
||||
$affected = $db->execute($sql);
|
||||
|
||||
echo "✅ Actualizados {$affected} registros\n";
|
||||
echo "Los mensajes multimedia ahora usan sus archivos locales como miniatura\n";
|
||||
|
||||
} catch (Exception $e) {
|
||||
echo "❌ Error: " . $e->getMessage() . "\n";
|
||||
exit(1);
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
-- Migration: Add whatsapp_media_id column to conversations
|
||||
-- This column stores the WhatsApp Media ID returned when uploading files
|
||||
-- Date: 27 de enero de 2026
|
||||
|
||||
ALTER TABLE conversations
|
||||
ADD COLUMN whatsapp_media_id VARCHAR(255) NULL AFTER media_url,
|
||||
ADD INDEX idx_whatsapp_media (whatsapp_media_id);
|
||||
Executable
+66
@@ -0,0 +1,66 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Script para probar envío de archivos multimedia
|
||||
# Verifica que se guarden correctamente en la BD
|
||||
|
||||
echo "🧪 Prueba de Envío de Archivos Multimedia"
|
||||
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
||||
echo ""
|
||||
|
||||
# Verificar estructura de BD
|
||||
echo "1️⃣ Verificando columnas de la tabla conversations..."
|
||||
docker exec whatsapp-dev-app php -r "
|
||||
require 'config/config.php';
|
||||
\$db = Database::getInstance();
|
||||
\$cols = \$db->fetchAll('DESCRIBE conversations');
|
||||
\$important = ['whatsapp_media_id', 'media_url', 'local_file', 'local_thumb', 'filename', 'mime_type'];
|
||||
echo 'Columnas importantes:' . PHP_EOL;
|
||||
foreach (\$cols as \$col) {
|
||||
if (in_array(\$col['Field'], \$important)) {
|
||||
echo ' ✅ ' . \$col['Field'] . ' (' . \$col['Type'] . ')' . PHP_EOL;
|
||||
}
|
||||
}
|
||||
" || { echo "❌ Error verificando BD"; exit 1; }
|
||||
|
||||
echo ""
|
||||
echo "2️⃣ Últimos 3 mensajes multimedia enviados:"
|
||||
docker exec whatsapp-dev-app php -r "
|
||||
require 'config/config.php';
|
||||
\$db = Database::getInstance();
|
||||
\$messages = \$db->fetchAll(
|
||||
'SELECT id, user_id, message_type, content, media_url, whatsapp_media_id,
|
||||
local_file, filename, created_at
|
||||
FROM conversations
|
||||
WHERE message_type IN (\"image\", \"video\", \"audio\", \"document\")
|
||||
AND direction = \"outgoing\"
|
||||
ORDER BY created_at DESC
|
||||
LIMIT 3'
|
||||
);
|
||||
|
||||
if (empty(\$messages)) {
|
||||
echo ' ℹ️ No hay mensajes multimedia en la BD aún' . PHP_EOL;
|
||||
} else {
|
||||
foreach (\$messages as \$msg) {
|
||||
echo PHP_EOL;
|
||||
echo ' 📎 ID: ' . \$msg['id'] . PHP_EOL;
|
||||
echo ' Tipo: ' . \$msg['message_type'] . PHP_EOL;
|
||||
echo ' Contenido: ' . substr(\$msg['content'], 0, 50) . PHP_EOL;
|
||||
echo ' Media ID WA: ' . (\$msg['whatsapp_media_id'] ?: 'null') . PHP_EOL;
|
||||
echo ' Archivo Local: ' . (\$msg['local_file'] ?: 'null') . PHP_EOL;
|
||||
echo ' Fecha: ' . \$msg['created_at'] . PHP_EOL;
|
||||
}
|
||||
}
|
||||
"
|
||||
|
||||
echo ""
|
||||
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
||||
echo "✅ Pruebas completadas"
|
||||
echo ""
|
||||
echo "📝 Cómo probar:"
|
||||
echo " 1. Abre http://localhost:8080/conversations.php"
|
||||
echo " 2. Selecciona una conversación"
|
||||
echo " 3. Haz click en el botón adjuntar (📎)"
|
||||
echo " 4. Selecciona una imagen o documento"
|
||||
echo " 5. Envía el archivo"
|
||||
echo " 6. Ejecuta este script de nuevo para ver si se guardó"
|
||||
echo ""
|
||||
@@ -0,0 +1 @@
|
||||
<?php session_start(); $_SESSION["user_id"] = 1; ?>
|
||||
Reference in New Issue
Block a user