> ## 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.

# Listeners

> Aprenda como usar listeners em sua aplicação usando o SDK Python da Square Cloud.

Às vezes é muito útil ter listeners para requisições, permitindo implementar funcionalidades que precisam ser acionadas sempre que "algo" acontece em sua aplicação.

Dois tipos de listeners foram adicionados para esse propósito.

## Listener de Captura

Por exemplo, imagine que toda vez que é feita uma requisição à rota '/logs', seu código execute uma tarefa que verifica se os novos logs diferem dos anteriores. Vamos ver como isso pode ser feito:

```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'Novos logs!!! {after}')

async def main():
    client = square.Client(api_key='CHAVE_API')
    app = await client.app('id_aplicacao')

    await app.logs()  # True
    await app.logs()  # False
```

Como visto acima, ao usar o decorator app.capture em uma função, ela será chamada sempre que for feita uma requisição ao endpoint especificado. Os endpoints aceitos são `APP_STATUS`, `LOGS` ou `BACKUP`. Essa função deve receber dois parâmetros:

\-- `before` (representa o estado antes da requisição)
\-- `after` (representa o estado após a requisição)

O tipo de dado retornado por `before` e `after` depende do endpoint que o listener está observando. Se for a rota **APP\_STATUS**, receberá um `StatusData`; **LOGS** receberá um `LogsData`; e **BACKUP** receberá um `BackupData`.

Como você deve ter notado no exemplo acima, na primeira comparação de logs, `after != before` retorna True. Isso ocorre porque `after` é igual a `LogsData(logs='')`, já que ainda não há nada armazenado no cache interno.

<Accordion title="Informações adicionais sobre este decorator">
  * Se você usa discord.py ou algum fork, sabe que o que diferencia eventos é o nome
    das funções ao redor das quais o decorator é aplicado, mas aqui é diferente. Para
    saber qual rota da API o decorator deve observar, usamos o parâmetro `endpoint`,
    que recebe uma classe `Endpoint`. Portanto, o nome da função decorada fica a seu
    critério.
  * A função decorada pode ser qualquer tipo de callable: funções comuns,
    corrotinas ou até classes (`__init__` será chamado).
  * Se o endpoint não for \[Endpoint.app\_status()], \[Endpoint.logs()] ou \[Endpoint.backup()],
    será retornado apenas um parâmetro `response` (do tipo `squarecloud.http.Response`).
</Accordion>

<Tip>
  Você pode usar o parâmetro `avoid_listener=True` para que o listener da aplicação não seja chamado.
</Tip>

## Listener de Requisição

Os "request listeners" fazem praticamente a mesma coisa. Aqui você usa o \[Client], e o retorno de todos os endpoints são objetos `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(api_key='CHAVE_API')
    await client.get_logs(app_id='id_aplicacao')  # 1, Response(success)
```

## Passando argumentos extras

Você pode passar alguns métodos o argumento nomeado `extra`, que será repassado ao seu listener

```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(api_key='CHAVE_API')
    await client.app_status('id_aplicacao', extra={'name': 'robertinho'})
```

<Tip>Você pode obter recursos legais em listeners usando pydantic em seu projeto, veja [usando pydantic](./using_pydantic)</Tip>
