README.md 4.53 KB

Multimensajería

Este repositorio es un servicio web de Flask en Python3 cuyo propósito es mandar mensajes de todo tipo de formatos a todo tipo de plataformas que tengan una API para ese propósito. Implementa una base de datos de mensajes a enviar, usa la MAC address del host que pide mandar mensajes para diferenciar las consultas y permitir la posibilidad de que el mensaje venga encriptado.

Instalación

Los requerimientos del programa son tener Python3 y pip3, para luego instalar los módulos de Flask, sqlite3 y python-arptable. Si no quiere hacerlo manualmente hay un archivo install.sh.

Preparación

Para correr el servicio en el servidor simplemente hay que escribir en la consola

python3 deploy.py

Uso

Para enviar mensajes se puede usar dos formas, la forma encriptada o la forma sin encripción, ambas son similares.

myserver.com/key

Llame a esta ruta para conseguir la llave pública del servidor en caso de querer encriptar la data. Este paso es opcional.

myserver.com/data

Este link es usado para subir los datos a enviar, pero obligatoriamente debe estar en formato de archivo. Opcionalmente puede estar encriptado, en cuyo caso debe mandar una llave en formato de archivo, el procedimiento es el siguiente:

  • Crear una llave simétrica AES
  • Encriptar el archivo con la llave simétrica
  • Encriptar la llave simétrica con la llave pública dada por el servidor
  • Enviar el archivo encriptado con el nombre 'data' y la llave encriptada en formato de archivo con el nombre 'key' (data=@data.file, key=@key.file)

Si no se envía una llave se presume que el archivo no está encriptado.

/data devuelve un string de 16 caracteres que corresponde al mensaje, se usa en el siguiente paso.

Aclaración: el Content-Type debe ser multipart/form-data

myserver.com/msg

Llamando a este link se envían los parámetros de envío del mensaje pasado en data, y se procede a poner en la cola el mensaje. (POST)

  • Bajo 'id' se envía el string del paso anterior
  • Bajo 'serv' se envía el servicio a usar, por ahora solo hay 'wpp1' correspondiente a WhatsApp
  • Bajo 'dest' se envía el número de destino, el formato puede variar dependiendo del servicio y dicho formato será documentado, el de 'wpp1' es el formato internacional sin el '+' y sin espacios ni guiones
  • Bajo 'type' se envía el tipo de dato a enviar, por ahora solo se permite 'text', los nombres serán documentados.

En caso de que no exista el servicio o este no admita el tipo, o que el id no exista, se devolverá un mensaje de error con esa información. Caso contrario, se devolverá el id de base de datos del mensaje para futura consulta.

myserver.com/cons

Por este link se consulta el estado de los mensajes que se quieren enviar, mandando el id bajo 'id' (POST). Se devuelve 'queued' o 'delivered'. Si fue enviado el mensaje se archiva y no puede ser consultado nuevamente.

Contribuir

Para contribuir con el proyecto se debe popular el archivo services.py La forma de hacer esto consta de lo siguiente:

  • Para servicios existentes se pueden agregar tipos de datos, en cuyo caso deberán ser incluidos en la clase Datatypes con su respectivo chequeo de validez en validate y se deberá agregar, si se necesita, una nueva restricción de formato (o funcionalidad) para todos los servicios.
  • Para agregar nuevos servicios se debe hacer una nueva clase que derive de ServiceBase e implementar las funciones de dicha clase abstracta. Luego agregar el servicio a Services con su validación y expandir serviceFactory(serv) para que pueda devolver una instancia de la nueva clase

En el método

@abstractmethod
  def send(self,data):
    pass

data es un dictionario que contiene los datos del pedido guardados en la base de datos

  • En 'id' está el id del pedido, que coincide con el nombre del archivo a mandar
  • En 'dir' está el nombre del directorio bajo el cual se encuentra el archivo a enviar
  • En 'dest' se encuentra el destinatario
  • En 'type' se encuentra el formato de lo que queremos mandar
  • En 'state' se encuentra el estado del mensaje, que siempre será 'queued' y es completamente irrelevante a la operación

La función retorna un booleano del resultado.

El método

@abstractmethod
  def validate(self,datatype):
    pass

toma un string correspondiente al formato de los datos y retorna un booleano correspondiente a si el servicio soporta o no el tipo de dato. Es una buena práctica usar Datatypes.validate() para chequear que el formato existe.

Servicios

WhatsApp 1 - 'wpp1'

próximamente...

Telegram - telegram