|
|
@@ -112,15 +112,21 @@ class WhatsAppMessage(models.Model):
|
|
|
def _send_message(self, with_commit=False):
|
|
|
|
|
|
url = ''
|
|
|
+ session_name = ''
|
|
|
+ api_key = ''
|
|
|
|
|
|
if self.wa_account_id and self.wa_account_id.whatsapp_web_url:
|
|
|
url = self.wa_account_id.whatsapp_web_url
|
|
|
- _logger.info('WHATSAPP WEB SEND MESSAGE' + url)
|
|
|
+ session_name = self.wa_account_id.whatsapp_web_login or ''
|
|
|
+ api_key = self.wa_account_id.whatsapp_web_api_key or ''
|
|
|
+ _logger.info('WHATSAPP WEB SEND MESSAGE - URL: %s, Session: %s', url, session_name)
|
|
|
|
|
|
group = ''
|
|
|
|
|
|
- if not url:
|
|
|
+ if not url or not session_name or not api_key:
|
|
|
+ # Si no hay configuración de WhatsApp Web, usar método original
|
|
|
super()._send_message(with_commit)
|
|
|
+ return
|
|
|
|
|
|
for whatsapp_message in self:
|
|
|
# Determinar destinatario final usando solo la nueva lógica
|
|
|
@@ -211,18 +217,13 @@ class WhatsAppMessage(models.Model):
|
|
|
|
|
|
number = number + '@c.us'
|
|
|
|
|
|
- # ENVIO DE MENSAJE
|
|
|
- # Headers de la petición, si es necesario
|
|
|
- headers = {
|
|
|
- "Content-Type": "application/json"
|
|
|
- }
|
|
|
-
|
|
|
- #$wa::sendMessage("521{$fields_data[$settings['borax_whatsapp_mobile']]}@c.us", ['type' => 'MessageMedia', 'args' => [mime_content_type($file), base64_encode(file_get_contents($file)), $filename, $filesize]], ['caption' => $borax_whatsapp_mensaje]);
|
|
|
+ # ENVIO DE MENSAJE - Nueva API Gateway
|
|
|
parent_message_id = ''
|
|
|
if whatsapp_message.mail_message_id and whatsapp_message.mail_message_id.parent_id:
|
|
|
parent_id = whatsapp_message.mail_message_id.parent_id.wa_message_ids
|
|
|
if parent_id:
|
|
|
parent_message_id = parent_id[0].msg_uid
|
|
|
+
|
|
|
# Validar que tenemos un destinatario válido
|
|
|
if not number:
|
|
|
_logger.error("No se pudo determinar el destinatario para el mensaje")
|
|
|
@@ -233,43 +234,120 @@ class WhatsAppMessage(models.Model):
|
|
|
_logger.error("Cuerpo del mensaje inválido: %s", body)
|
|
|
body = "Mensaje de WhatsApp"
|
|
|
|
|
|
- # Log del payload para debugging
|
|
|
- _logger.info("Enviando mensaje a %s: %s", number, body[:50] + "..." if len(body) > 50 else body)
|
|
|
+ # Determinar si es grupo
|
|
|
+ is_group = number.endswith('@g.us') if number else False
|
|
|
+
|
|
|
+ # Construir URL base
|
|
|
+ base_url = url.rstrip('/')
|
|
|
+ endpoint = 'send-message'
|
|
|
+
|
|
|
+ # Headers con autenticación
|
|
|
+ headers = {
|
|
|
+ "Content-Type": "application/json",
|
|
|
+ "X-API-Key": api_key
|
|
|
+ }
|
|
|
|
|
|
+ # Preparar payload según tipo de mensaje
|
|
|
if attachment:
|
|
|
+ # Determinar endpoint según tipo de archivo
|
|
|
+ mimetype = attachment.mimetype or 'application/octet-stream'
|
|
|
+ if mimetype.startswith('image/'):
|
|
|
+ endpoint = 'send-image'
|
|
|
+ elif mimetype.startswith('video/'):
|
|
|
+ endpoint = 'send-video'
|
|
|
+ elif mimetype.startswith('audio/'):
|
|
|
+ endpoint = 'send-voice'
|
|
|
+ else:
|
|
|
+ endpoint = 'send-file'
|
|
|
+
|
|
|
+ # Convertir archivo a base64 con prefijo data URI
|
|
|
+ file_base64 = base64.b64encode(attachment.raw).decode('utf-8')
|
|
|
+ base64_with_prefix = f"data:{mimetype};base64,{file_base64}"
|
|
|
+
|
|
|
payload = {
|
|
|
- "method": "sendMessage",
|
|
|
- "args": [number, {'type': 'MessageMedia', 'args': [attachment.mimetype, base64.b64encode(attachment.raw).decode('utf-8'), attachment.name, attachment.file_size]}, {'caption': body}]
|
|
|
+ "phone": [number], # Array para send-image/send-file
|
|
|
+ "base64": base64_with_prefix,
|
|
|
+ "filename": attachment.name or "file",
|
|
|
+ "caption": body,
|
|
|
+ "isGroup": is_group
|
|
|
}
|
|
|
- else:
|
|
|
+
|
|
|
+ if parent_message_id:
|
|
|
+ payload["quotedMessageId"] = parent_message_id
|
|
|
+ else:
|
|
|
+ # Mensaje de texto
|
|
|
payload = {
|
|
|
- "method": "sendMessage",
|
|
|
- "args": [number, body, {}]
|
|
|
+ "phone": number, # String para send-message
|
|
|
+ "message": body,
|
|
|
+ "isGroup": is_group
|
|
|
}
|
|
|
-
|
|
|
- if parent_message_id:
|
|
|
- payload['args'][2]['quotedMessageId'] = parent_message_id
|
|
|
-
|
|
|
- # Realizando la petición POST
|
|
|
- response = requests.post(url, data=json.dumps(payload), headers=headers)
|
|
|
-
|
|
|
- # Verificando si la respuesta contiene data->id
|
|
|
- if response.status_code == 200:
|
|
|
- try:
|
|
|
- response_json = response.json()
|
|
|
- except ValueError:
|
|
|
- _logger.error("La respuesta no es JSON válido: %s", response.text)
|
|
|
- response_json = {}
|
|
|
- if "_data" in response_json and "id" in response_json["_data"]:
|
|
|
- _logger.info(f"Petición exitosa. ID: {response_json['_data']['id']['id']}")
|
|
|
+
|
|
|
+ if parent_message_id:
|
|
|
+ payload["quotedMessageId"] = parent_message_id
|
|
|
+
|
|
|
+ # Construir URL completa
|
|
|
+ full_url = f"{base_url}/api/v1/{session_name}/{endpoint}"
|
|
|
+
|
|
|
+ # Log del payload para debugging
|
|
|
+ _logger.info("Enviando mensaje a %s (%s) usando endpoint %s", number, "grupo" if is_group else "contacto", endpoint)
|
|
|
+
|
|
|
+ # Realizar petición POST
|
|
|
+ try:
|
|
|
+ response = requests.post(full_url, json=payload, headers=headers, timeout=60)
|
|
|
+
|
|
|
+ # Procesar respuesta
|
|
|
+ if response.status_code == 200:
|
|
|
+ try:
|
|
|
+ response_json = response.json()
|
|
|
+
|
|
|
+ # La nueva API puede devolver jobId (mensaje encolado) o id (enviado directamente)
|
|
|
+ if 'jobId' in response_json:
|
|
|
+ # Mensaje encolado
|
|
|
+ _logger.info("Mensaje encolado. Job ID: %s", response_json.get('jobId'))
|
|
|
+ whatsapp_message.write({
|
|
|
+ 'state': 'outgoing', # Mantener 'outgoing' para compatibilidad
|
|
|
+ 'msg_uid': response_json.get('jobId')
|
|
|
+ })
|
|
|
+ self._cr.commit()
|
|
|
+ elif 'id' in response_json:
|
|
|
+ # Mensaje enviado directamente
|
|
|
+ msg_id = response_json.get('id')
|
|
|
+ if isinstance(msg_id, dict) and '_serialized' in msg_id:
|
|
|
+ msg_uid = msg_id['_serialized']
|
|
|
+ elif isinstance(msg_id, str):
|
|
|
+ msg_uid = msg_id
|
|
|
+ else:
|
|
|
+ msg_uid = str(msg_id)
|
|
|
+
|
|
|
+ _logger.info("Mensaje enviado exitosamente. ID: %s", msg_uid)
|
|
|
+ whatsapp_message.write({
|
|
|
+ 'state': 'sent',
|
|
|
+ 'msg_uid': msg_uid
|
|
|
+ })
|
|
|
+ self._cr.commit()
|
|
|
+ else:
|
|
|
+ _logger.warning("Respuesta exitosa pero sin jobId ni id: %s", response_json)
|
|
|
+ whatsapp_message.write({
|
|
|
+ 'state': 'outgoing'
|
|
|
+ })
|
|
|
+ self._cr.commit()
|
|
|
+ except ValueError:
|
|
|
+ _logger.error("La respuesta no es JSON válido: %s", response.text)
|
|
|
+ whatsapp_message.write({
|
|
|
+ 'state': 'error'
|
|
|
+ })
|
|
|
+ self._cr.commit()
|
|
|
+ else:
|
|
|
+ _logger.error("Error en la petición. Código: %s, Respuesta: %s", response.status_code, response.text)
|
|
|
whatsapp_message.write({
|
|
|
- 'state': 'sent',
|
|
|
- 'msg_uid': response_json['_data']['id']['_serialized']
|
|
|
+ 'state': 'error'
|
|
|
})
|
|
|
self._cr.commit()
|
|
|
- else:
|
|
|
- _logger.info("La respuesta no contiene 'data->id'.")
|
|
|
- else:
|
|
|
- _logger.info(f"Error en la petición. Código de estado: {response.status_code}")
|
|
|
+ except requests.exceptions.RequestException as e:
|
|
|
+ _logger.error("Error de conexión al enviar mensaje: %s", str(e))
|
|
|
+ whatsapp_message.write({
|
|
|
+ 'state': 'error'
|
|
|
+ })
|
|
|
+ self._cr.commit()
|
|
|
|
|
|
time.sleep(random.randint(3, 7))
|