> ## Documentation Index
> Fetch the complete documentation index at: https://docs.squarecloud.app/llms.txt
> Use this file to discover all available pages before exploring further.

# リスナー

> squarecloud python SDK を使ってアプリケーションでリスナーを利用する方法を学びます。

リクエストに対するリスナーを持つことは非常に便利で、アプリケーション内で「何か」が起きるたびに呼び出す必要がある機能を実装できます。

この目的のために、2 種類のリスナーが追加されました。

## Capture Listener

たとえば、'/logs' ルートへのリクエストが行われるたびに、新しいログが古いものと異なるかどうかをチェックするタスクをコードで実行したいとします。では、これをどのように実現できるか見てみましょう。

```python theme={null}
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
```

上記のように、関数に app.capture デコレータを使うと、デコレータで指定したエンドポイントへのリクエストが行われるたびにこの関数が呼び出されます。受け付けられるエンドポイントは `APP_STATUS`、`LOGS`、または `BACKUP` です。この関数は 2 つのパラメータを取る必要があります。

* `before`（リクエスト前の状態を表します）
* `after`（リクエスト後の状態を表します）

`before` と `after` が返すデータ型は、リスナーが「リッスン」しているエンドポイントによって異なります。**APP\_STATUS** ルートであれば `StatusData` を、**LOGS** であれば `LogsData` を、**BACKUP** であれば `BackupData` を受け取ります。

上記の例で気づいたかもしれませんが、ログ同士の比較が初めて行われるとき、`after != before` は True を返します。これはまさに、after が `LogsData(logs='')` に等しいためで、内部のキャッシュにはまだ何も保存されていないからです。

<Accordion title="このデコレータに関する追加情報">
  * discord.py またはそのフォーク（おそらく使っているでしょう）を使ったことがあれば、
    イベントを区別するのはデコレータがラップする関数の名前だと
    知っているはずですが、ここでは異なります。デコレータがどの
    API ルートを「リッスン」する必要があるかを知るために、`endpopint` パラメータを使います。これは
    `Endpoint` クラスを受け取るので、デコレータがラップする関数の名前は
    あなた次第です。
  * デコレータがラップする関数は、実際には callable であれば何でも
    構いません。これには通常の関数、コルーチン、さらには
    クラス（`__init__` が呼び出されます）も含まれます。
  * エンドポイントが \[Endpoint.app\_status()]、\[Endpoint.logs()]、または \[Endpoint.backup()] でない場合、
    `response` パラメータ（`squarecloud.http.Response` 型）のみが
    返されます。
</Accordion>

<Tip>
  `avoid_listener=True` パラメータを使うと、アプリケーションのリスナーが呼び出されないようにできます。
</Tip>

## Request Listener

「request listener」はほぼ同じことを行います。ただしここでは \[Client] を使い、すべてのエンドポイントの戻り値は `squarecloud.http.Response` オブジェクトになります。

```python theme={null}
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)
```

## 追加の引数を渡す

一部のメソッドには `extra` というキーワード引数を渡すことができ、これがリスナーに渡されます。

```python theme={null}
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'})
```

<Tip>プロジェクトで pydantic を使うと、リスナーで便利な機能を利用できます。[using pydantic](./using_pydantic) をご覧ください。</Tip>
