Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save WellingtonFonseca/3b66183da7a0150cfcd80716be627a57 to your computer and use it in GitHub Desktop.
Save WellingtonFonseca/3b66183da7a0150cfcd80716be627a57 to your computer and use it in GitHub Desktop.
Classe simples para interagir com a api da Comtele
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