diff --git a/arquivo.pdf b/arquivo.pdf new file mode 100644 index 0000000..9425af3 Binary files /dev/null and b/arquivo.pdf differ diff --git a/evolutionapi/__pycache__/client.cpython-310.pyc b/evolutionapi/__pycache__/client.cpython-310.pyc index e426ac5..5834b25 100644 Binary files a/evolutionapi/__pycache__/client.cpython-310.pyc and b/evolutionapi/__pycache__/client.cpython-310.pyc differ diff --git a/evolutionapi/client.py b/evolutionapi/client.py index 991d756..7bfdbd7 100644 --- a/evolutionapi/client.py +++ b/evolutionapi/client.py @@ -1,4 +1,5 @@ import requests +from requests_toolbelt import MultipartEncoder from .exceptions import EvolutionAuthenticationError, EvolutionNotFoundError, EvolutionAPIError from .services.instance import InstanceService from .services.instance_operations import InstanceOperationsService @@ -62,11 +63,43 @@ class EvolutionClient: response = requests.get(url, headers=self._get_headers(instance_token)) return self._handle_response(response) - def post(self, endpoint: str, data: dict = None, instance_token: str = None): - """Faz uma requisição POST.""" - url = self._get_full_url(endpoint) - response = requests.post(url, headers=self._get_headers(instance_token), json=data) - return self._handle_response(response) + def post(self, endpoint: str, data: dict = None, instance_token: str = None, files: dict = None): + url = f'{self.base_url}/{endpoint}' + headers = self._get_headers(instance_token) + + 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): """Faz uma requisição PUT.""" diff --git a/evolutionapi/models/__pycache__/message.cpython-310.pyc b/evolutionapi/models/__pycache__/message.cpython-310.pyc index 2db0c9d..e4b054f 100644 Binary files a/evolutionapi/models/__pycache__/message.cpython-310.pyc and b/evolutionapi/models/__pycache__/message.cpython-310.pyc differ diff --git a/evolutionapi/models/message.py b/evolutionapi/models/message.py index 739460f..cd4a82a 100644 --- a/evolutionapi/models/message.py +++ b/evolutionapi/models/message.py @@ -53,28 +53,34 @@ class MediaMessage(BaseMessage): def __init__( self, number: str, - mediatype: str, - mimetype: str, - caption: str, - media: str, - fileName: str, - delay: Optional[int] = None, + media: dict = None, + mediatype: Optional[str] = None, + caption: str = None, + mimetype: str = None, + fileName: str = None, + delay: Optional[Union[int, float, str]] = None, quoted: Optional[QuotedMessage] = None, mentionsEveryOne: Optional[bool] = None, mentioned: Optional[List[str]] = None ): - super().__init__( - number=number, - mediatype=mediatype, - mimetype=mimetype, - caption=caption, - media=media, - fileName=fileName, - delay=delay, - quoted=quoted.__dict__ if quoted else None, - mentionsEveryOne=mentionsEveryOne, - mentioned=mentioned - ) + data = { + 'number': number, + 'mediatype': mediatype, + 'caption': caption, + 'mimetype': mimetype, + 'fileName': fileName, + 'quoted': quoted.__dict__ if quoted else None, + '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): def __init__( diff --git a/evolutionapi/services/__pycache__/message.cpython-310.pyc b/evolutionapi/services/__pycache__/message.cpython-310.pyc index 4fb2c21..5918b50 100644 Binary files a/evolutionapi/services/__pycache__/message.cpython-310.pyc and b/evolutionapi/services/__pycache__/message.cpython-310.pyc differ diff --git a/evolutionapi/services/message.py b/evolutionapi/services/message.py index f151259..79efaae 100644 --- a/evolutionapi/services/message.py +++ b/evolutionapi/services/message.py @@ -1,70 +1,118 @@ from typing import Union, BinaryIO from ..models.message import * +from requests_toolbelt import MultipartEncoder +import mimetypes +import requests class MessageService: def __init__(self, client): self.client = client 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( f'message/sendText/{instance_id}', - data=message.__dict__, + data=data, instance_token=instance_token ) def send_media(self, instance_id: str, message: MediaMessage, instance_token: str, file: Union[BinaryIO, str] = None): - payload = { - 'data': message.__dict__, - 'instance_token': instance_token + # Preparar os dados do formulário + fields = { + '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 isinstance(file, str): - with open(file, 'rb') as f: - payload['files'] = {'file': f} + mime_type = mimetypes.guess_type(file)[0] or 'application/octet-stream' + fields['file'] = ('file', open(file, 'rb'), mime_type) else: - payload['files'] = {'file': file} - - return self.client.post( - f'message/sendMedia/{instance_id}', - **payload + fields['file'] = ('file', file, 'application/octet-stream') + + # Criar o multipart encoder + multipart = MultipartEncoder(fields=fields) + + # 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): - payload = { - 'data': message, - 'instance_token': instance_token - } + fields = {} + + # 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 isinstance(file, str): - with open(file, 'rb') as f: - payload['files'] = {'file': f} + mime_type = mimetypes.guess_type(file)[0] or 'application/octet-stream' + fields['file'] = ('file', open(file, 'rb'), mime_type) else: - payload['files'] = {'file': file} - - return self.client.post( - f'message/sendPtv/{instance_id}', - **payload - ) + 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/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): - payload = { - 'data': message, - 'instance_token': instance_token - } + fields = {} + + # 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 isinstance(file, str): - with open(file, 'rb') as f: - payload['files'] = {'file': f} + mime_type = mimetypes.guess_type(file)[0] or 'application/octet-stream' + fields['file'] = ('file', open(file, 'rb'), mime_type) else: - payload['files'] = {'file': file} - - return self.client.post( - f'message/sendWhatsAppAudio/{instance_id}', - **payload - ) + 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/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): return self.client.post( @@ -73,17 +121,39 @@ class MessageService: instance_token=instance_token ) - def send_sticker(self, instance_id: str, message: dict, instance_token: str): - return self.client.post( - f'message/sendSticker/{instance_id}', - data=message, - instance_token=instance_token - ) + def send_sticker(self, instance_id: str, message: dict, instance_token: str, file: Union[BinaryIO, str] = None): + fields = {} + + # 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 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): + data = message.__dict__.copy() + if 'delay' in data and data['delay'] is not None: + data['delay'] = int(data['delay']) + return self.client.post( f'message/sendLocation/{instance_id}', - data=message.__dict__, + data=data, instance_token=instance_token ) @@ -102,22 +172,34 @@ class MessageService: ) 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( f'message/sendPoll/{instance_id}', - data=message.__dict__, + data=data, instance_token=instance_token ) 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( f'message/sendList/{instance_id}', - data=message.__dict__, + data=data, instance_token=instance_token ) 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( f'message/sendButtons/{instance_id}', - data=message.__dict__, + data=data, instance_token=instance_token ) \ No newline at end of file diff --git a/test_evolution.py b/test_evolution.py index 6d52708..61baf36 100644 --- a/test_evolution.py +++ b/test_evolution.py @@ -14,22 +14,35 @@ client = EvolutionClient( instance_token = "429683C4C977415CAAFCCE10F7D57E11" 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", - text="Olá, como vai?", - delay=1200 + mediatype="document", + 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("Buscando instâncias") -instances = client.instances.fetch_instances() +# print("Buscando instâncias") +# instances = client.instances.fetch_instances() -print("Instâncias encontradas") -print(instances) +# print("Instâncias encontradas") +# print(instances) # print("Criando instância") # config = InstanceConfig(