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

> Learn how to use listeners in your application using the squarecloud python sdk.

Sometimes it's very useful to have listeners for requests, allowing you to implement features that need to be called whenever "something" happens in your application.

Two types of listeners have been added for this purpose.

## Capture Listener

For example, imagine that every time a request to the '/logs' route is made, my code performs a task that checks if the new logs differ from the old ones. Well, let's see how this can be done:

```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
```

As seen above, by using the app.capture decorator on a function, this function will be called every time a request is made to the endpoint specified in the decorator. The accepted endpoints are `APP_STATUS`, `LOGS`, or `BACKUP`. This function should take two parameters:

* `before`(represents the state before the request)
* `after`(represents the state after the request)

The data type returned by `before` and `after` depends on which endpoint the listener is "listening" to. If it is the **APP\_STATUS** route, it will receive a `StatusData`, **LOGS** will receive a `LogsData`, and **BACKUP** will receive a `BackupData`.

As you may have noticed in the example above, the first time the comparison between the logs occurs, `after != before` returns True. This happens precisely because after is equal to `LogsData(logs='')`, as there is still nothing stored in the cache internally.

<Accordion title="Additional information about this decorator">
  * If you use discord.py or some fork (you probably use), you should
    know that what differentiates events is the name
    of the functions that the decorator wraps, but here it differs. To know
    which
    API route the decorator needs to "listen" to, we use the `endpopint` parameter, it
    receives an `Endpoint` class, so the name of the function that the decorator
    wraps is up to you.
  * The function that the decorator wraps can actually be anything that is
    a callable. This includes regular functions, coroutines, and even
    classes (`__init__` will be called).
  * If the endpoint is not an \[Endpoint.app\_status()], \[Endpoint.logs()], or \[Endpoint.backup()],
    only a `response` parameter (of type `squarecloud.http.Response`) will
    be returned.
</Accordion>

<Tip>
  You can use the `avoid_listener=True` parameter so that the application listener is not called.
</Tip>

## Request Listener

The "request listeners" do pretty much the same thing. But here you use the \[Client], and the return of all endpoints is `squarecloud.http.Response` objects.

```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)
```

## Passing extra arguments

You can pass to some methods keyword argument called `extra`, and this will be passed to your 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('your api key')
    await client.app_status('application_id', extra={'name': 'robertinho'})
```

<Tip>You can get some cool features in listeners using pydantic in your project, take a look at [using pydantic](./using_pydantic)</Tip>
