# Bots


<!-- WARNING: THIS FILE WAS AUTOGENERATED! DO NOT EDIT! -->

``` python
from IPython.display import Audio

import wave
```

``` python
dc = DiscordClient()
gld = await dc.guild('1327046393453613076')
chs = await gld.channels()
vch = chs[3]
intents = (1 << 0) | (1 << 7) | (1 << 9) | (1 << 15) # GUILDS | VOICE_EVENTS | GUILD_MESSAGES | MESSAGE_CONTENT
```

[`Bot`](https://AnswerDotAI.github.io/cordslite/bot.html#bot) ties
together
[`DiscordClient`](https://AnswerDotAI.github.io/cordslite/core.html#discordclient)
(REST) and
[`GatewayClient`](https://AnswerDotAI.github.io/cordslite/gateway.html#gatewayclient)
(events) into a single object with a decorator-based command router.
Commands are registered with `@bot.cmd` — the function name becomes the
command name, prefixed with `!` in Discord. So `def echo` responds to
`!echo`. Every command handler takes two arguments: the
[`Message`](https://AnswerDotAI.github.io/cordslite/core.html#message)
object and a string of everything the user typed after the command name
(empty string if nothing).

The `_on_msg` handler ignores messages from the bot itself to prevent
infinite loops — a common gotcha with Discord bots. It splits the
message into command name + args, so `!echo hello world` passes
`"hello world"` as the `args` string to the handler.

------------------------------------------------------------------------

<a
href="https://github.com/AnswerDotAI/cordslite/blob/main/cordslite/bot.py#L19"
target="_blank" style="float:right; font-size:smaller">source</a>

### Bot

``` python
def Bot(
    intents, **kw
):
```

*Discord bot with command routing*

``` python
bot = Bot(intents)
await bot.start()
```

Commands can be registered at any time — even after `bot.start()`. This
works because `@bot.cmd` just adds the function to a dict; the message
handler looks up commands dynamically on each message.

``` python
@bot.cmd
async def echo(msg, args): await (await msg.channel()).send(f'You said: {args}')
```

``` python
bot
```

    Bot(cmds=['echo'])

Errors in command handlers are caught and stored in `bot.errors` —
useful for debugging in dynamic environments like solveit where you can
inspect the list after the fact. For real-time handling (e.g. notifying
the user in Discord), register a handler with `@bot.on_error`. Both
mechanisms work simultaneously.

------------------------------------------------------------------------

<a
href="https://github.com/AnswerDotAI/cordslite/blob/main/cordslite/bot.py#L56"
target="_blank" style="float:right; font-size:smaller">source</a>

### Bot.on_error

``` python
def on_error(
    f
):
```

*Call self as a function.*

``` python
@bot.on_error
async def handle_err(msg, e): print('error')
```

``` python
@bot.cmd
def err(msg): raise Exception('test')
```

``` python
bot.errors
```

    []

Voice integration reuses the existing
[`VoiceClient`](https://AnswerDotAI.github.io/cordslite/voice.html#voiceclient)
— [`Bot`](https://AnswerDotAI.github.io/cordslite/bot.html#bot) just
provides convenience methods to manage the lifecycle. The bot can only
be in one voice channel at a time.

------------------------------------------------------------------------

<a
href="https://github.com/AnswerDotAI/cordslite/blob/main/cordslite/bot.py#L69"
target="_blank" style="float:right; font-size:smaller">source</a>

### Bot.leave_voice

``` python
async def leave_voice():
```

*Leave the current voice channel*

------------------------------------------------------------------------

<a
href="https://github.com/AnswerDotAI/cordslite/blob/main/cordslite/bot.py#L62"
target="_blank" style="float:right; font-size:smaller">source</a>

### Bot.join_voice

``` python
async def join_voice(
    channel
):
```

*Join a voice channel and return VoiceClient*

``` python
vc = await bot.join_voice(vch); vc
```

    VoiceClient(self.ch=Channel(id=1327046393453613080, name='General', type=2))

    voice json 11 {'user_ids': ['346450717025894400']}
    voice json 18 {'user_id': '346450717025894400', 'flags': 2}
    voice json 20 {'user_id': '346450717025894400', 'platform': 0}
    voice json 15 {'any': 100}

``` python
vc.start_recording()
```

    '/tmp/recording.mp3'

``` python
pth = vc.stop_recording()
await bot.leave_voice()
```

``` python
# Audio(pth)
```
