> ## 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 在你的应用中使用监听器。

有时候为请求设置监听器非常有用，让你能够实现那些需要在应用中“发生某事”时被调用的功能。

为此我们添加了两种类型的监听器。

## 捕获监听器（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 装饰器，每当向装饰器中指定的 endpoint 发起请求时，该函数就会被调用。可接受的 endpoint 有 `APP_STATUS`、`LOGS` 或 `BACKUP`。该函数应接受两个参数：

* `before`（表示请求之前的状态）
* `after`（表示请求之后的状态）

`before` 和 `after` 返回的数据类型取决于监听器所“监听”的 endpoint。如果是 **APP\_STATUS** 路由，将接收到 `StatusData`；**LOGS** 将接收到 `LogsData`；**BACKUP** 将接收到 `BackupData`。

正如你在上面的示例中可能已经注意到的，第一次进行日志之间的比较时，`after != before` 返回 True。这正是因为此时 after 等于 `LogsData(logs='')`，因为内部缓存中还没有存储任何内容。

<Accordion title="关于该装饰器的补充信息">
  * 如果你使用 discord.py 或它的某个分支（你很可能在用），你应该
    知道区分事件的是装饰器所包装的函数
    的名称，但在这里则不同。为了知道
    装饰器需要“监听”哪个
    API 路由，我们使用 `endpopint` 参数，它
    接收一个 `Endpoint` 类，因此装饰器所
    包装的函数名称由你自行决定。
  * 装饰器所包装的对象实际上可以是任何
    可调用对象。这包括普通函数、协程，甚至是
    类（会调用 `__init__`）。
  * 如果 endpoint 不是 \[Endpoint.app\_status()]、\[Endpoint.logs()] 或 \[Endpoint.backup()]，
    则只会返回一个 `response` 参数（类型为 `squarecloud.http.Response`）。
</Accordion>

<Tip>
  你可以使用 `avoid_listener=True` 参数，使应用监听器不被调用。
</Tip>

## 请求监听器（Request Listener）

“请求监听器”所做的事情基本相同。但在这里你使用的是 \[Client]，并且所有 endpoint 返回的都是 `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，可以在监听器中获得一些很酷的特性，请查看 [使用 pydantic](./using_pydantic)</Tip>
