Created
November 22, 2023 17:21
-
-
Save WellingtonFonseca/3b66183da7a0150cfcd80716be627a57 to your computer and use it in GitHub Desktop.
Classe simples para interagir com a api da Comtele
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import requests | |
import json | |
import os | |
from typing import Optional, Any | |
class Comtele: | |
""" | |
python 3.10 | |
A API da Comtele é construída no padrão REST. Nossa API possui URLs previsíveis de acordo com todos recursos servidos por cada endpoint, aceita requisições e retorna utilizando padrão JSON e também usa códigos de resposta HTTP padrão, a autenticação é feita via Header e todas as requisições também devem conter ‘Content-Type’: 'application/json’. | |
""" | |
class WithoutReceivers(Exception): | |
""" | |
É necessário informar ao menos um destinatário que irá receber o SMS. | |
""" | |
def __init__( | |
self, | |
msg="É necessário informar ao menos um destinatário que irá receber o SMS.", | |
*args, | |
**kwargs, | |
): | |
super().__init__(msg, *args, **kwargs) | |
class WithoutContent(Exception): | |
""" | |
É necessário informar o conteúdo da mensagem. | |
""" | |
def __init__( | |
self, | |
msg="É necessário informar o conteúdo da mensagem", | |
*args, | |
**kwargs, | |
): | |
super().__init__(msg, *args, **kwargs) | |
class BadRequest(Exception): | |
""" | |
HTTP Status: 400 | |
Este erro geralmente ocorre quando algum recurso é acessado sem algum parâmetro necessário ser informado. | |
""" | |
def __init__( | |
self, | |
msg="Este erro geralmente ocorre quando algum recurso é acessado sem algum parâmetro necessário ser informado.", | |
*args, | |
**kwargs, | |
): | |
super().__init__(msg, *args, **kwargs) | |
class InvalidCredentials(Exception): | |
""" | |
HTTP Status: 401 | |
Erro relacionado a chave de API, pode ter sido informada de maneira incorreta ou não ter sido informada. | |
""" | |
def __init__( | |
self, | |
msg="Erro relacionado a chave de API, pode ter sido informada de maneira incorreta ou não ter sido informada.", | |
*args, | |
**kwargs, | |
): | |
super().__init__(msg, *args, **kwargs) | |
class NotFound(Exception): | |
""" | |
HTTP Status: 404 | |
Recurso inexistente, o endpoint informado provavelmente está incorreto. | |
""" | |
def __init__( | |
self, | |
msg="Recurso inexistente, o endpoint informado provavelmente está incorreto.", | |
*args, | |
**kwargs, | |
): | |
super().__init__(msg, *args, **kwargs) | |
class MethodNotAllowed(Exception): | |
""" | |
HTTP Status: 405 | |
Este erro está relacionado quando algum recurso é acessado por um método não disponível. | |
""" | |
def __init__( | |
self, | |
msg="Este erro está relacionado quando algum recurso é acessado por um método não disponível.", | |
*args, | |
**kwargs, | |
): | |
super().__init__(msg, *args, **kwargs) | |
class TooManyRequests(Exception): | |
""" | |
HTTP Status: 429 | |
Este erro ocorre, quando é feita uma quantidade excessiva de requisições na API em um curto período de tempo. | |
""" | |
def __init__( | |
self, | |
msg="Este erro ocorre, quando é feita uma quantidade excessiva de requisições na API em um curto período de tempo.", | |
*args, | |
**kwargs, | |
): | |
super().__init__(msg, *args, **kwargs) | |
class RequestTimeout(Exception): | |
""" | |
HTTP Status: 500 | |
houve um time out na requisição ao efetuar a conexão com o endpoint. | |
""" | |
def __init__( | |
self, | |
msg="houve um time out na requisição ao efetuar a conexão com o endpoint.", | |
*args, | |
**kwargs, | |
): | |
super().__init__(msg, *args, **kwargs) | |
class ServerError(Exception): | |
""" | |
HTTP Status: 503 | |
Algum problema com o servidor em que está o recurso acessado, neste caso, tente acessar novamente. | |
""" | |
def __init__( | |
self, | |
msg="Algum problema com o servidor em que está o recurso acessado, neste caso, tente acessar novamente.", | |
*args, | |
**kwargs, | |
): | |
super().__init__(msg, *args, **kwargs) | |
class SendResult(object): | |
""" | |
Attributes | |
---------- | |
success: | |
Pode ser retornado true para sucesso ou false para erro, este campo é o resultado da operação. | |
objectt: | |
Class que contém os atributos de 'Object' | |
message: | |
Neste campo é retornado mais detalhes sobre o resultado da operação do recurso que foi utilizado. | |
""" | |
class SendObject(object): | |
""" | |
Attributes | |
---------- | |
request_unique_id: | |
Este campo é o ID da sua requisição. | |
""" | |
request_unique_id: str | |
def __init__( | |
self, | |
response: Optional[dict[str, Any]], | |
): | |
if response is None: | |
response = {} | |
response_unique_id = response.get("requestUniqueId", None) | |
self.request_unique_id = response_unique_id | |
success: bool | |
objectt: SendObject | |
message: Optional[str] | |
def __init__( | |
self, | |
response: dict[str, Any], | |
): | |
response_success = response.get("Success", None) | |
self.success = response_success | |
response_message = response.get("Message", None) | |
self.message = response_message | |
response_object = response.get("Object", None) | |
self.objectt = self.SendObject(response=response_object) | |
url_comtele: str | |
url_comtele = "https://sms.comtele.com.br/api/v2/" | |
headers: dict[str, str] | |
def __init__( | |
self, | |
auth_key: str, | |
): | |
""" | |
Parameters | |
---------- | |
auth_key | |
Chave de integração está disponível na sua conta em https://sms.comtele.com.br. No menu lateral, dentro da seção API, clique em Chave de API e você irá para a página de Informações do Desenvolvedor e lá irá encontrar o campo nomeado como Sua Chave de API | |
""" | |
self.headers = { | |
"content-type": "application/json", | |
"auth-key": auth_key, | |
} | |
def send( | |
self, | |
receivers: str, | |
content: str, | |
sender: Optional[str] = None, | |
) -> SendResult: | |
""" | |
Com este recurso, é possivel enviar SMS de forma instantânea. | |
Importante! | |
. NUNCA! Faça envio de urls com destino 404 Not Found | |
Parameters | |
---------- | |
receivers: str | |
Destinatários que irão receber o SMS. Para dois ou mais destinatários, separe por uma vírgula os telefones, formato: DDD + Número, pode-se enviar para ate 100 telefones dessa forma. | |
content: str | |
Conteúdo da mensagem que vai ser recebida pelo número que o SMS será enviado. Nos casos que o conteúdo do SMS superar 160 caracteres, será tarifado mais de um crédito a cada 153 caracteres. Algumas operadoras como a Oi e Sercomtel não suportam concatenação da mensagens, então serão recebidos SMS separadamente. | |
sender: str, optional | |
Este campo é usado só internamente, e geralmente é bem util para controle. Por exemplo você pode informar um id interno, que ele será exibido no relatório, dispensamdo que você faça “de para” dos ids da Comtele com o sistema que está integrando. | |
Returns | |
------- | |
SendResult: | |
Objeto parametrizado com informações do retorno da api | |
Raises | |
------ | |
BadRequest | |
Este erro geralmente ocorre quando algum recurso é acessado sem algum parâmetro necessário ser informado. | |
InvalidCredentials | |
Erro relacionado a chave de API, pode ter sido informada de maneira incorreta ou não ter sido informada. | |
NotFound | |
Recurso inexistente, o endpoint informado provavelmente está incorreto. | |
MethodNotAllowed | |
Este erro está relacionado quando algum recurso é acessado por um método não disponível. | |
TooManyRequests | |
Este erro ocorre, quando é feita uma quantidade excessiva de requisições na API em um curto período de tempo. | |
RequestTimeout | |
houve um time out na requisição ao efetuar a conexão com o endpoint. | |
ServerError | |
Algum problema com o servidor em que está o recurso acessado, neste caso, tente acessar novamente. | |
""" | |
if receivers == "": | |
raise self.WithoutReceivers() | |
if content == "": | |
raise self.WithoutContent() | |
api_url = os.path.join(self.url_comtele, "send") | |
data = { | |
"Receivers": receivers, | |
"Content": content, | |
} | |
if sender is not None: | |
data.update({"Sender": sender}) | |
response = requests.post( | |
api_url, | |
data=json.dumps(data), | |
headers=self.headers, | |
) | |
status_code: int | |
status_code = response.status_code | |
match status_code: | |
case 400: | |
raise self.BadRequest() | |
case 401: | |
raise self.InvalidCredentials() | |
case 404: | |
raise self.NotFound() | |
case 405: | |
raise self.MethodNotAllowed() | |
case 429: | |
raise self.TooManyRequests() | |
case 500: | |
raise self.RequestTimeout() | |
case 503: | |
raise self.ServerError() | |
case _: | |
return self.SendResult(response=response.json()) | |
class CreditsResult(object): | |
""" | |
Attributes | |
---------- | |
success: | |
Pode ser retornado true para sucesso ou false para erro, este campo é o resultado da operação. | |
credits: | |
Class que contém os atributos de 'Object' | |
""" | |
success: bool | |
credits: int | |
def __init__( | |
self, | |
response: dict[str, Any], | |
): | |
response_success = response.get("Success", None) | |
self.success = response_success | |
response_object = response.get("Object", None) | |
self.credits = response_object | |
def credits( | |
self, | |
sub_account: Optional[str] = None, | |
) -> CreditsResult: | |
""" | |
Com este recurso, é possivel consultar a quantidade de saldo disponível em sua conta ou subcontas. | |
Parameters | |
---------- | |
sub_account: str, optional | |
Se não for informado username, será retornado o saldo da conta que está relacionada a chave de integração que está sendo utilizada. A funcionalidade de consultar saldo de uma subconta só está disponível para contas do tipo revenda, que possui funcionalidades administrativas em suas subcontas. | |
Returns | |
------- | |
CreditsResult: | |
Objeto parametrizado com informações do retorno da api | |
Raises | |
------ | |
BadRequest | |
Este erro geralmente ocorre quando algum recurso é acessado sem algum parâmetro necessário ser informado. | |
InvalidCredentials | |
Erro relacionado a chave de API, pode ter sido informada de maneira incorreta ou não ter sido informada. | |
NotFound | |
Recurso inexistente, o endpoint informado provavelmente está incorreto. | |
MethodNotAllowed | |
Este erro está relacionado quando algum recurso é acessado por um método não disponível. | |
TooManyRequests | |
Este erro ocorre, quando é feita uma quantidade excessiva de requisições na API em um curto período de tempo. | |
RequestTimeout | |
houve um time out na requisição ao efetuar a conexão com o endpoint. | |
ServerError | |
Algum problema com o servidor em que está o recurso acessado, neste caso, tente acessar novamente. | |
""" | |
api_url = os.path.join(self.url_comtele, "credits") | |
if sub_account is not None: | |
api_url = os.path.join(self.url_comtele, sub_account) | |
response = requests.get( | |
api_url, | |
headers=self.headers, | |
) | |
status_code: int | |
status_code = response.status_code | |
match status_code: | |
case 400: | |
raise self.BadRequest() | |
case 401: | |
raise self.InvalidCredentials() | |
case 404: | |
raise self.NotFound() | |
case 405: | |
raise self.MethodNotAllowed() | |
case 429: | |
raise self.TooManyRequests() | |
case 500: | |
raise self.RequestTimeout() | |
case 503: | |
raise self.ServerError() | |
case _: | |
return self.CreditsResult(response=response.json()) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment