Zum Hauptinhalt springen
Manchmal ist es sehr nützlich, Listener für Anfragen zu haben, mit denen du Funktionen umsetzen kannst, die immer dann aufgerufen werden müssen, wenn in deiner Anwendung “etwas” passiert. Zu diesem Zweck wurden zwei Arten von Listenern hinzugefügt.

Capture Listener

Stell dir zum Beispiel vor, dass mein Code jedes Mal, wenn eine Anfrage an die Route ‘/logs’ gestellt wird, eine Aufgabe ausführt, die prüft, ob sich die neuen Logs von den alten unterscheiden. Sehen wir uns an, wie das umgesetzt werden kann:
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
Wie oben zu sehen, wird eine Funktion, auf die der Decorator app.capture angewendet wird, jedes Mal aufgerufen, wenn eine Anfrage an den im Decorator angegebenen Endpoint gestellt wird. Die akzeptierten Endpoints sind APP_STATUS, LOGS oder BACKUP. Diese Funktion sollte zwei Parameter annehmen:
  • before (repräsentiert den Zustand vor der Anfrage)
  • after (repräsentiert den Zustand nach der Anfrage)
Der von before und after zurückgegebene Datentyp hängt davon ab, auf welchen Endpoint der Listener “hört”. Handelt es sich um die Route APP_STATUS, erhält er StatusData, LOGS erhält LogsData und BACKUP erhält BackupData. Wie du im Beispiel oben vielleicht bemerkt hast, gibt beim ersten Vergleich der Logs after != before True zurück. Das passiert genau deshalb, weil after gleich LogsData(logs='') ist, da intern noch nichts im Cache gespeichert wurde.
  • Wenn du discord.py oder einen Fork davon verwendest (was du wahrscheinlich tust), weißt du, dass Events durch den Namen der Funktionen unterschieden werden, die der Decorator umschließt, aber hier ist das anders. Um zu wissen, auf welche API-Route der Decorator “hören” muss, verwenden wir den Parameter endpopint, der eine Endpoint-Klasse erhält, sodass der Name der Funktion, die der Decorator umschließt, dir überlassen bleibt.
  • Die Funktion, die der Decorator umschließt, kann tatsächlich alles sein, was aufrufbar ist. Das umfasst reguläre Funktionen, Coroutinen und sogar Klassen (__init__ wird aufgerufen).
  • Wenn der Endpoint kein [Endpoint.app_status()], [Endpoint.logs()] oder [Endpoint.backup()] ist, wird nur ein response-Parameter (vom Typ squarecloud.http.Response) zurückgegeben.
Du kannst den Parameter avoid_listener=True verwenden, damit der Listener der Anwendung nicht aufgerufen wird.

Request Listener

Die “Request Listener” machen im Grunde dasselbe. Aber hier verwendest du den [Client], und der Rückgabewert aller Endpoints sind squarecloud.http.Response-Objekte.
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)

Zusätzliche Argumente übergeben

Du kannst an einige Methoden ein Schlüsselwortargument namens extra übergeben, das dann an deinen Listener weitergereicht wird
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'})
Du kannst in Listenern einige nützliche Funktionen nutzen, indem du pydantic in deinem Projekt einsetzt, wirf einen Blick auf pydantic verwenden