Saltar al contenido principal
A veces resulta muy útil tener listeners para las peticiones, lo que te permite implementar funcionalidades que deben ejecutarse cada vez que “algo” ocurre en tu aplicación. Para este propósito se han añadido dos tipos de listeners.

Capture Listener

Por ejemplo, imagina que cada vez que se realiza una petición a la ruta ‘/logs’, mi código ejecuta una tarea que comprueba si los nuevos logs difieren de los anteriores. Bueno, veamos cómo se puede hacer esto:
import squarecloud as square
from squarecloud import Endpoint

@app.capture(endpoint=Endpoint.logs())
async def on_logs_request(before, after):
    if after != before:
        print(f'New logs!!! {after}')

async def main():
    client = square.Client('your api key')
    app = await client.app('application_id')

    await app.logs()  # True
    await app.logs()  # False
Como se ve arriba, al usar el decorador app.capture sobre una función, esta función será llamada cada vez que se realice una petición al endpoint especificado en el decorador. Los endpoints aceptados son APP_STATUS, LOGS o BACKUP. Esta función debe recibir dos parámetros:
  • before(representa el estado antes de la petición)
  • after(representa el estado después de la petición)
El tipo de dato devuelto por before y after depende de qué endpoint esté “escuchando” el listener. Si es la ruta APP_STATUS, recibirá un StatusData, LOGS recibirá un LogsData y BACKUP recibirá un BackupData. Como habrás notado en el ejemplo anterior, la primera vez que ocurre la comparación entre los logs, after != before devuelve True. Esto sucede precisamente porque after es igual a LogsData(logs=''), ya que aún no hay nada almacenado en la caché internamente.
  • Si usas discord.py o algún fork (probablemente lo uses), debes saber que lo que diferencia los eventos es el nombre de las funciones que el decorador envuelve, pero aquí es diferente. Para saber a qué ruta de la API debe “escuchar” el decorador, usamos el parámetro endpopint, que recibe una clase Endpoint, por lo que el nombre de la función que el decorador envuelve depende de ti.
  • La función que el decorador envuelve puede ser en realidad cualquier cosa que sea un callable. Esto incluye funciones normales, corrutinas e incluso clases (se llamará a __init__).
  • Si el endpoint no es un [Endpoint.app_status()], [Endpoint.logs()] o [Endpoint.backup()], solo se devolverá un parámetro response (de tipo squarecloud.http.Response).
Puedes usar el parámetro avoid_listener=True para que el listener de la aplicación no sea llamado.

Request Listener

Los “request listeners” hacen prácticamente lo mismo. Pero aquí usas el [Client], y el retorno de todos los endpoints son objetos squarecloud.http.Response.
import squarecloud as square
from squarecloud import Endpoint

@client.on_request(endpoint=Endpoint.logs())
async def on_logs_request(response):
    print(1, response)

async def main():
    client = square.Client('your api key')
    await client.get_logs(app_id='application_id')  # 1, Response(success)

Pasar argumentos adicionales

Puedes pasar a algunos métodos un argumento de palabra clave llamado extra, y este será pasado a tu listener
import squarecloud as square
from squarecloud import Endpoint

@client.on_request(Endpoint.status())
async def get_extra_param(before, after, extra: dict[str, str]):
    print(extra)

async def main():
    client = square.Client('your api key')
    await client.app_status('application_id', extra={'name': 'robertinho'})
Puedes obtener algunas funcionalidades geniales en los listeners usando pydantic en tu proyecto, echa un vistazo a using pydantic