fix: send media with file path for local files

This commit is contained in:
Davidson Gomes 2024-11-19 18:26:32 -03:00
parent d52b156db5
commit 8561b03bfe
8 changed files with 211 additions and 77 deletions

BIN
arquivo.pdf Normal file

Binary file not shown.

View File

@ -1,4 +1,5 @@
import requests import requests
from requests_toolbelt import MultipartEncoder
from .exceptions import EvolutionAuthenticationError, EvolutionNotFoundError, EvolutionAPIError from .exceptions import EvolutionAuthenticationError, EvolutionNotFoundError, EvolutionAPIError
from .services.instance import InstanceService from .services.instance import InstanceService
from .services.instance_operations import InstanceOperationsService from .services.instance_operations import InstanceOperationsService
@ -62,11 +63,43 @@ class EvolutionClient:
response = requests.get(url, headers=self._get_headers(instance_token)) response = requests.get(url, headers=self._get_headers(instance_token))
return self._handle_response(response) return self._handle_response(response)
def post(self, endpoint: str, data: dict = None, instance_token: str = None): def post(self, endpoint: str, data: dict = None, instance_token: str = None, files: dict = None):
"""Faz uma requisição POST.""" url = f'{self.base_url}/{endpoint}'
url = self._get_full_url(endpoint) headers = self._get_headers(instance_token)
response = requests.post(url, headers=self._get_headers(instance_token), json=data)
return self._handle_response(response) if files:
# Remove o Content-Type do header quando enviando arquivos
if 'Content-Type' in headers:
del headers['Content-Type']
# Prepara os campos do multipart
fields = {}
# Adiciona os campos do data
for key, value in data.items():
fields[key] = str(value) if not isinstance(value, (int, float)) else (None, str(value), 'text/plain')
# Adiciona o arquivo
file_tuple = files['file']
fields['file'] = (file_tuple[0], file_tuple[1], file_tuple[2])
# Cria o multipart encoder
multipart = MultipartEncoder(fields=fields)
headers['Content-Type'] = multipart.content_type
response = requests.post(
url,
headers=headers,
data=multipart
)
else:
response = requests.post(
url,
headers=headers,
json=data
)
return response.json()
def put(self, endpoint, data=None): def put(self, endpoint, data=None):
"""Faz uma requisição PUT.""" """Faz uma requisição PUT."""

View File

@ -53,28 +53,34 @@ class MediaMessage(BaseMessage):
def __init__( def __init__(
self, self,
number: str, number: str,
mediatype: str, media: dict = None,
mimetype: str, mediatype: Optional[str] = None,
caption: str, caption: str = None,
media: str, mimetype: str = None,
fileName: str, fileName: str = None,
delay: Optional[int] = None, delay: Optional[Union[int, float, str]] = None,
quoted: Optional[QuotedMessage] = None, quoted: Optional[QuotedMessage] = None,
mentionsEveryOne: Optional[bool] = None, mentionsEveryOne: Optional[bool] = None,
mentioned: Optional[List[str]] = None mentioned: Optional[List[str]] = None
): ):
super().__init__( data = {
number=number, 'number': number,
mediatype=mediatype, 'mediatype': mediatype,
mimetype=mimetype, 'caption': caption,
caption=caption, 'mimetype': mimetype,
media=media, 'fileName': fileName,
fileName=fileName, 'quoted': quoted.__dict__ if quoted else None,
delay=delay, 'mentionsEveryOne': mentionsEveryOne,
quoted=quoted.__dict__ if quoted else None, 'mentioned': mentioned
mentionsEveryOne=mentionsEveryOne, }
mentioned=mentioned
) if delay is not None:
data['delay'] = delay
if media and media != {}:
data['media'] = media
super().__init__(**{k: v for k, v in data.items() if v is not None})
class StatusMessage(BaseMessage): class StatusMessage(BaseMessage):
def __init__( def __init__(

View File

@ -1,70 +1,118 @@
from typing import Union, BinaryIO from typing import Union, BinaryIO
from ..models.message import * from ..models.message import *
from requests_toolbelt import MultipartEncoder
import mimetypes
import requests
class MessageService: class MessageService:
def __init__(self, client): def __init__(self, client):
self.client = client self.client = client
def send_text(self, instance_id: str, message: TextMessage, instance_token: str): def send_text(self, instance_id: str, message: TextMessage, instance_token: str):
# Preparar os dados como JSON
data = {
'number': message.number,
'text': message.text
}
if hasattr(message, 'delay') and message.delay is not None:
data['delay'] = message.delay
# Usar o método post do cliente que já trata JSON corretamente
return self.client.post( return self.client.post(
f'message/sendText/{instance_id}', f'message/sendText/{instance_id}',
data=message.__dict__, data=data,
instance_token=instance_token instance_token=instance_token
) )
def send_media(self, instance_id: str, message: MediaMessage, instance_token: str, file: Union[BinaryIO, str] = None): def send_media(self, instance_id: str, message: MediaMessage, instance_token: str, file: Union[BinaryIO, str] = None):
payload = { # Preparar os dados do formulário
'data': message.__dict__, fields = {
'instance_token': instance_token 'number': (None, message.number, 'text/plain'),
'mediatype': (None, message.mediatype, 'text/plain'),
'mimetype': (None, message.mimetype, 'text/plain'),
'caption': (None, message.caption, 'text/plain'),
'fileName': (None, message.fileName, 'text/plain'),
} }
# Adicionar delay apenas se existir
if hasattr(message, 'delay') and message.delay is not None:
fields['delay'] = (None, str(message.delay), 'text/plain; type=number')
# Adicionar o arquivo se fornecido
if file: if file:
if isinstance(file, str): if isinstance(file, str):
with open(file, 'rb') as f: mime_type = mimetypes.guess_type(file)[0] or 'application/octet-stream'
payload['files'] = {'file': f} fields['file'] = ('file', open(file, 'rb'), mime_type)
else: else:
payload['files'] = {'file': file} fields['file'] = ('file', file, 'application/octet-stream')
return self.client.post( # Criar o multipart encoder
f'message/sendMedia/{instance_id}', multipart = MultipartEncoder(fields=fields)
**payload
# Preparar os headers
headers = self.client._get_headers(instance_token)
headers['Content-Type'] = multipart.content_type
# Fazer a requisição diretamente
url = f'{self.client.base_url}/message/sendMedia/{instance_id}'
response = requests.post(
url,
headers=headers,
data=multipart
) )
return response.json()
def send_ptv(self, instance_id: str, message: dict, instance_token: str, file: Union[BinaryIO, str] = None): def send_ptv(self, instance_id: str, message: dict, instance_token: str, file: Union[BinaryIO, str] = None):
payload = { fields = {}
'data': message,
'instance_token': instance_token # Adiciona todos os campos do message como text/plain
} for key, value in message.items():
if key == 'delay' and value is not None:
fields[key] = (None, str(value), 'text/plain; type=number')
else:
fields[key] = (None, str(value), 'text/plain')
if file: if file:
if isinstance(file, str): if isinstance(file, str):
with open(file, 'rb') as f: mime_type = mimetypes.guess_type(file)[0] or 'application/octet-stream'
payload['files'] = {'file': f} fields['file'] = ('file', open(file, 'rb'), mime_type)
else: else:
payload['files'] = {'file': file} fields['file'] = ('file', file, 'application/octet-stream')
return self.client.post( multipart = MultipartEncoder(fields=fields)
f'message/sendPtv/{instance_id}', headers = self.client._get_headers(instance_token)
**payload headers['Content-Type'] = multipart.content_type
)
url = f'{self.client.base_url}/message/sendPtv/{instance_id}'
response = requests.post(url, headers=headers, data=multipart)
return response.json()
def send_whatsapp_audio(self, instance_id: str, message: dict, instance_token: str, file: Union[BinaryIO, str] = None): def send_whatsapp_audio(self, instance_id: str, message: dict, instance_token: str, file: Union[BinaryIO, str] = None):
payload = { fields = {}
'data': message,
'instance_token': instance_token # Adiciona todos os campos do message como text/plain
} for key, value in message.items():
if key == 'delay' and value is not None:
fields[key] = (None, str(value), 'text/plain; type=number')
else:
fields[key] = (None, str(value), 'text/plain')
if file: if file:
if isinstance(file, str): if isinstance(file, str):
with open(file, 'rb') as f: mime_type = mimetypes.guess_type(file)[0] or 'application/octet-stream'
payload['files'] = {'file': f} fields['file'] = ('file', open(file, 'rb'), mime_type)
else: else:
payload['files'] = {'file': file} fields['file'] = ('file', file, 'application/octet-stream')
return self.client.post( multipart = MultipartEncoder(fields=fields)
f'message/sendWhatsAppAudio/{instance_id}', headers = self.client._get_headers(instance_token)
**payload headers['Content-Type'] = multipart.content_type
)
url = f'{self.client.base_url}/message/sendWhatsAppAudio/{instance_id}'
response = requests.post(url, headers=headers, data=multipart)
return response.json()
def send_status(self, instance_id: str, message: StatusMessage, instance_token: str): def send_status(self, instance_id: str, message: StatusMessage, instance_token: str):
return self.client.post( return self.client.post(
@ -73,17 +121,39 @@ class MessageService:
instance_token=instance_token instance_token=instance_token
) )
def send_sticker(self, instance_id: str, message: dict, instance_token: str): def send_sticker(self, instance_id: str, message: dict, instance_token: str, file: Union[BinaryIO, str] = None):
return self.client.post( fields = {}
f'message/sendSticker/{instance_id}',
data=message, # Adiciona todos os campos do message como text/plain
instance_token=instance_token for key, value in message.items():
) if key == 'delay' and value is not None:
fields[key] = (None, str(value), 'text/plain; type=number')
else:
fields[key] = (None, str(value), 'text/plain')
if file:
if isinstance(file, str):
mime_type = mimetypes.guess_type(file)[0] or 'application/octet-stream'
fields['file'] = ('file', open(file, 'rb'), mime_type)
else:
fields['file'] = ('file', file, 'application/octet-stream')
multipart = MultipartEncoder(fields=fields)
headers = self.client._get_headers(instance_token)
headers['Content-Type'] = multipart.content_type
url = f'{self.client.base_url}/message/sendSticker/{instance_id}'
response = requests.post(url, headers=headers, data=multipart)
return response.json()
def send_location(self, instance_id: str, message: LocationMessage, instance_token: str): def send_location(self, instance_id: str, message: LocationMessage, instance_token: str):
data = message.__dict__.copy()
if 'delay' in data and data['delay'] is not None:
data['delay'] = int(data['delay'])
return self.client.post( return self.client.post(
f'message/sendLocation/{instance_id}', f'message/sendLocation/{instance_id}',
data=message.__dict__, data=data,
instance_token=instance_token instance_token=instance_token
) )
@ -102,22 +172,34 @@ class MessageService:
) )
def send_poll(self, instance_id: str, message: PollMessage, instance_token: str): def send_poll(self, instance_id: str, message: PollMessage, instance_token: str):
data = message.__dict__.copy()
if 'delay' in data and data['delay'] is not None:
data['delay'] = int(data['delay'])
return self.client.post( return self.client.post(
f'message/sendPoll/{instance_id}', f'message/sendPoll/{instance_id}',
data=message.__dict__, data=data,
instance_token=instance_token instance_token=instance_token
) )
def send_list(self, instance_id: str, message: ListMessage, instance_token: str): def send_list(self, instance_id: str, message: ListMessage, instance_token: str):
data = message.__dict__.copy()
if 'delay' in data and data['delay'] is not None:
data['delay'] = int(data['delay'])
return self.client.post( return self.client.post(
f'message/sendList/{instance_id}', f'message/sendList/{instance_id}',
data=message.__dict__, data=data,
instance_token=instance_token instance_token=instance_token
) )
def send_buttons(self, instance_id: str, message: ButtonMessage, instance_token: str): def send_buttons(self, instance_id: str, message: ButtonMessage, instance_token: str):
data = message.__dict__.copy()
if 'delay' in data and data['delay'] is not None:
data['delay'] = int(data['delay'])
return self.client.post( return self.client.post(
f'message/sendButtons/{instance_id}', f'message/sendButtons/{instance_id}',
data=message.__dict__, data=data,
instance_token=instance_token instance_token=instance_token
) )

View File

@ -14,22 +14,35 @@ client = EvolutionClient(
instance_token = "429683C4C977415CAAFCCE10F7D57E11" instance_token = "429683C4C977415CAAFCCE10F7D57E11"
instance_id = "teste" instance_id = "teste"
text_message = TextMessage( # text_message = TextMessage(
# number="557499879409",
# text="Olá, como vai?",
# delay=1200
# )
# response = client.messages.send_text(instance_id, text_message, instance_token)
# print("Mensagem de texto enviada")
# print(response)
media_message = MediaMessage(
number="557499879409", number="557499879409",
text="Olá, como vai?", mediatype="document",
delay=1200 mimetype="application/pdf",
caption="Olá, como vai?",
fileName="arquivo.pdf"
) )
response = client.messages.send_text(instance_id, text_message, instance_token) response = client.messages.send_media(instance_id, media_message, instance_token, "arquivo.pdf")
print("Mensagem enviada") print("Mensagem de mídia enviada")
print(response) print(response)
print("Buscando instâncias") # print("Buscando instâncias")
instances = client.instances.fetch_instances() # instances = client.instances.fetch_instances()
print("Instâncias encontradas") # print("Instâncias encontradas")
print(instances) # print(instances)
# print("Criando instância") # print("Criando instância")
# config = InstanceConfig( # config = InstanceConfig(