Examples

All aiocord terminal commands assume you either:

  • Set the DISCORD_TOKEN environment variable

  • Use the --token <TOKEN> flag before any subcommands

Widgets

Make a blep/__init__.py python package:

import aiocord

async def __load__(info):
    print('loaded', __name__)

async def __drop__(info):
    print('dropped', __name__)

@aiocord.widget.callback(aiocord.events.CreateMessage)
async def _callback_create_message(info, core_event):
    print('message created!', core_event.message.content)

@aiocord.widget.interact('blep')
async def _interact_blep(info, core_event):
    users = core_event.interaction.data.resolved.users
    blepping = ' '.join(user.mention() for user in users)
    return aiocord.model.protocols.InteractionResponse(
        type = aiocord.model.enums.InteractionResponseType.channel_message_with_source,
        data = aiocord.model.protocols.MessageInteractionResponse(
            content = f'blep {blepping}'
        )
    )

Note

Relative imports of package level are allowed.

Note

Loading other modules using aiocord.widget.load() is allowed.

Then, run the following:

aiocord start blep

Integration

Finer control over starting, loading, dropping and stopping.

import asyncio
import aiocord

async def start(client):
    await client.start()
    await client.ready()
    await aiocord.widget.load(client, 'blep', './modules')

async def stop(client):
    await aiocord.widget.drop(client, 'blep')
    await client.stop()

loop = asyncio.get_event_loop()

client = aiocord.client.Client(token = ...)

loop.run_until_complete(start(client))

try:
    loop.run_forever()
except KeyboardInterrupt:
    pass
finally:
    loop.run_until_complete(stop(client))

Commands

Make a commands.py python script and define a commands variable:

import aiocord

commands = [
    aiocord.model.protocols.ApplicationCommand(
        name = 'blep',
        type = aiocord.model.enums.ApplicationCommandType.chat_input,
        description = 'blep someone',
        options = [
            aiocord.model.protocols.ApplicationCommandOption(
                name = 'user',
                description = 'the user to blep',
                type = aiocord.model.enums.ApplicationCommandOptionType.user
            )
        ]
    )
]

Then, run the following:

aiocord update commands

A commands.json will be created and the application’s commands will be updated with its contents.

Interactions

Naive Approach

Creating a shop command routine for buying sweets and potentially gifting them.

import aiocord
import secrets

@aiocord.widget.interact('shop')
async def _interact_shop(info: aiocord.widget.Info, core_event: aiocord.events.CreateInteraction):
    # define the stock
    stock = {
        'ice-cream': {
            'name': 'Ice Cream',
            'emoji': '🍦'
        },
        'cake': {
            'name': 'Cake',
            'emoji': '🍰'
        }, 
        'waffle': {
            'name': 'Waffle',
            'emoji': '🧇'
        }
    }
    # unique identifier
    select_custom_id = secrets.token_hex(16)
    # compose the response
    response = aiocord.model.protocols.InteractionResponse(
        type = aiocord.model.enums.InteractionResponseType.channel_message_with_source,
        data = aiocord.model.protocols.MessageInteractionResponse(
            content = 'What would you like to buy?',
            components = [
                aiocord.model.protocols.MessageActionRowComponent(
                    type = aiocord.model.enums.MessageComponentType.action_row,
                    components = [
                        aiocord.model.protocols.MessageSelectMenuComponent(
                            custom_id = select_custom_id,
                            type = aiocord.model.enums.MessageComponentType.string_select,
                            options = [
                                aiocord.model.protocols.MessageSelectMenuComponentOption(
                                    value = key,
                                    label = item['name'],
                                    description = 'Sweet, fluffy, chunky and super tasty.',
                                    emoji = aiocord.model.protocols.Emoji(
                                        name = item['emoji']
                                    )
                                )
                                for key, item in stock.items()
                            ]
                        )
                    ]
                )
            ],
            # ensure only the invoker can see this
            flags = aiocord.model.enums.MessageFlags.ephemeral
        )
    )
    # condition for the expected interaction
    async def check(core_event: aiocord.events.CreateInteraction):
        # only accept an interaction to the identifer
        return core_event.interaction.type == aiocord.model.enums.InteractionType.message_component and core_event.interaction.data.custom_id == select_custom_id
    # make the waiter
    sentinel = info.client.wait(aiocord.events.CreateInteraction, check)
    # send the response
    await info.client.create_interaction_response(core_event.interaction.id, core_event.interaction.token, **response)
    # wait the interaction
    core_event = await sentinel
    # resolve the picked item
    item = stock[core_event.interaction.data.values[0]]['name']
    # unique identifiers
    negative_button_custom_id = secrets.token_hex(16)
    positive_button_custom_id = secrets.token_hex(16)
    # compose the response
    response = aiocord.model.protocols.InteractionResponse(
        type = aiocord.model.enums.InteractionResponseType.channel_message_with_source,
        data = aiocord.model.protocols.MessageInteractionResponse(
            content = 'Is it a gift for someone?',
            components = [
                aiocord.model.protocols.MessageActionRowComponent(
                    type = aiocord.model.enums.MessageComponentType.action_row,
                    components = [
                        aiocord.model.protocols.MessageButtonComponent(
                            custom_id = positive_button_custom_id,
                            type = aiocord.model.enums.MessageComponentType.button,
                            label = 'Yes',
                            style = aiocord.model.enums.MessageButtonComponentStyle.primary
                        ),
                        aiocord.model.protocols.MessageButtonComponent(
                            custom_id = negative_button_custom_id,
                            type = aiocord.model.enums.MessageComponentType.button,
                            label = 'No',
                            style = aiocord.model.enums.MessageButtonComponentStyle.secondary
                        )
                    ]
                )
            ],
            # ensure only the invoker can see this
            flags = aiocord.model.enums.MessageFlags.ephemeral
        )
    )
    # unique identifier group
    custom_id_button_group = [negative_button_custom_id, positive_button_custom_id]
    # condition for the expected interaction
    async def check(core_event: aiocord.events.CreateInteraction):
        # only accept an interaction to the identifers
        return core_event.interaction.type == aiocord.model.enums.InteractionType.message_component and core_event.interaction.data.custom_id in custom_id_button_group
    # make the waiter
    sentinel = info.client.wait(aiocord.events.CreateInteraction, check)
    # send the response
    await info.client.create_interaction_response(core_event.interaction.id, core_event.interaction.token, **response)
    # wait the interaction
    core_event = await sentinel
    # resolve whether positive
    is_gift = custom_id_button_group.index(core_event.interaction.data.custom_id)
    # ...is it?
    if is_gift:
        # unique identifier
        select_custom_id = secrets.token_hex(16)
        # compose the response
        response = aiocord.model.protocols.InteractionResponse(
            type = aiocord.model.enums.InteractionResponseType.channel_message_with_source,
            data = aiocord.model.protocols.MessageInteractionResponse(
                content = 'Who is this a gift for?',
                components = [
                    aiocord.model.protocols.MessageActionRowComponent(
                        type = aiocord.model.enums.MessageComponentType.action_row,
                        components = [
                            aiocord.model.protocols.MessageSelectMenuComponent(
                                custom_id = select_custom_id,
                                type = aiocord.model.enums.MessageComponentType.user_select
                            )
                        ]
                    )
                ],
                flags = aiocord.model.enums.MessageFlags.ephemeral
            )
        )
        # condition for the expected interaction
        async def check(core_event: aiocord.events.CreateInteraction):
            return core_event.interaction.type == aiocord.model.enums.InteractionType.message_component and core_event.interaction.data.custom_id == select_custom_id
        # make the waiter
        sentinel = info.client.wait(aiocord.events.CreateInteraction, check)
        # send the response
        await info.client.create_interaction_response(core_event.interaction.id, core_event.interaction.token, **response)
        # wait the interaction
        core_event = await sentinel
        # resolve the recipients
        recipient = ' '.join(aiocord.model.mentions.user(user_id) for user_id in core_event.interaction.data.values)
    else:
        recipient = 'themselves'
    # compose the response
    response = aiocord.model.protocols.InteractionResponse(
        type = aiocord.model.enums.InteractionResponseType.channel_message_with_source,
        data = aiocord.model.protocols.MessageInteractionResponse(
            # anyone can see this
            content = f'{info.client.cache.user.mention()} bought {item} for {recipient}!'
        )
    )
    # send the response
    await info.client.create_interaction_response(core_event.interaction.id, core_event.interaction.token, **response)

Smart Approach

Using the following:

Trivializes the following:

Additionally, code organization and readability improve.

import aiocord
import functools

async def _interact_shop_respond(item, recipient, info: aiocord.widget.Info, core_event: aiocord.events.CreateInteraction):

    response = aiocord.model.protocols.InteractionResponse(
        type = aiocord.model.enums.InteractionResponseType.channel_message_with_source,
        data = aiocord.model.protocols.MessageInteractionResponse(
            content = f'{core_event.interaction.member.user.mention()} bought {item} for {recipient}!'
        )
    )

    return response

async def _interact_shop_item_gifting_select(item, info: aiocord.widget.Info, core_event: aiocord.events.CreateInteraction):
    # ignore timeouts
    if core_event is None:
        return
    # compose the recipient
    recipient = ' '.join(aiocord.model.mentions.user(user_id) for user_id in core_event.interaction.data.values)
    # get the response
    response = await _interact_shop_respond(item, recipient, info, core_event)
    # send the response
    return response

async def _interact_shop_item_gifting_accept(item, info: aiocord.widget.Info, core_event: aiocord.events.CreateInteraction):
    # ignore timeouts
    if core_event is None:
        return
    # compose the response
    response = aiocord.model.protocols.InteractionResponse(
        type = aiocord.model.enums.InteractionResponseType.channel_message_with_source,
        data = aiocord.model.protocols.MessageInteractionResponse(
            content = 'Who is this a gift for?',
            components = [
                aiocord.model.protocols.MessageActionRowComponent(
                    type = aiocord.model.enums.MessageComponentType.action_row,
                    components = [
                        aiocord.utils.interact(
                            info.client,
                            functools.partial(_interact_shop_item_gifting_select, item, info),
                            aiocord.model.protocols.MessageSelectMenuComponent(
                                type = aiocord.model.enums.MessageComponentType.user_select
                            )
                        )
                    ]
                )
            ],
            flags = aiocord.model.enums.MessageFlags.ephemeral
        )
    )
    # send the response
    return response

async def _interact_shop_item_gifting_reject(item, info: aiocord.widget.Info, core_event: aiocord.events.CreateInteraction):
    # ignore timeouts
    if core_event is None:
        return
    # compose the recipient
    recipient = 'themselves'
    # get the response
    response = await _interact_shop_respond(item, recipient, info, core_event)
    # send the response
    return response

async def _interact_shop_stock_select(stock, info: aiocord.widget.Info, core_event: aiocord.events.CreateInteraction):
    # ignore timeouts
    if core_event is None:
        return
    # get the item name from stock
    item = stock[core_event.interaction.data.values[0]]['name']
    # compose the response
    response = aiocord.model.protocols.InteractionResponse(
        type = aiocord.model.enums.InteractionResponseType.channel_message_with_source,
        data = aiocord.model.protocols.MessageInteractionResponse(
            content = 'Is it a gift for someone?',
            components = [
                aiocord.model.protocols.MessageActionRowComponent(
                    type = aiocord.model.enums.MessageComponentType.action_row,
                    components = [
                        aiocord.utils.interact(
                            info.client,
                            functools.partial(_interact_shop_item_gifting_accept, item, info),
                            aiocord.model.protocols.MessageButtonComponent(
                                type = aiocord.model.enums.MessageComponentType.button,
                                label = 'Yes',
                                style = aiocord.model.enums.MessageButtonComponentStyle.primary
                            )
                        ),
                        aiocord.utils.interact(
                            info.client,
                            functools.partial(_interact_shop_item_gifting_reject, item, info),
                            aiocord.model.protocols.MessageButtonComponent(
                                type = aiocord.model.enums.MessageComponentType.button,
                                label = 'No',
                                style = aiocord.model.enums.MessageButtonComponentStyle.secondary
                            )
                        ),
                    ]
                )
            ],
            flags = aiocord.model.enums.MessageFlags.ephemeral
        )
    )
    # send the response
    return response

@aiocord.widget.interact('shop')
async def _interact_shop(info: aiocord.widget.Info, core_event: aiocord.events.CreateInteraction):
    # define the stock
    stock = {
        'ice-cream': {
            'name': 'Ice Cream',
            'emoji': '🍦'
        },
        'cake': {
            'name': 'Cake',
            'emoji': '🍰'
        }, 
        'waffle': {
            'name': 'Waffle',
            'emoji': '🧇'
        }, 
    }
    # compose the response
    response = aiocord.model.protocols.InteractionResponse(
        type = aiocord.model.enums.InteractionResponseType.channel_message_with_source,
        data = aiocord.model.protocols.MessageInteractionResponse(
            content = 'What would you like to buy?',
            components = [
                aiocord.model.protocols.MessageActionRowComponent(
                    type = aiocord.model.enums.MessageComponentType.action_row,
                    components = [
                        aiocord.utils.interact(
                            info.client,
                            functools.partial(_interact_shop_stock_select, stock, info),
                            aiocord.model.protocols.MessageSelectMenuComponent(
                                type = aiocord.model.enums.MessageComponentType.string_select,
                                options = [
                                    aiocord.model.protocols.MessageSelectMenuComponentOption(
                                        value = key,
                                        label = item['name'],
                                        description = 'Sweet, fluffy, chunky and super tasty.',
                                        emoji = aiocord.model.protocols.Emoji(
                                            name = item['emoji']
                                        )
                                    )
                                    for key, item in stock.items()
                                ]
                            )
                        )
                    ]
                )
            ],
            flags = aiocord.model.enums.MessageFlags.ephemeral
        )
    )
    # send the response
    return response

Note

Since aiocord.utils.interact() only passes the event to the callback, functools.partial() is necessary for carrying information (such as stock and item) along the routine.

HTTP-Only

Invoking HTTP routes without connecting to the gateway.

import asyncio
import aiocord

async def main(client):
    message = await client.create_message('864902189816273146', content = 'hello!')
    await client.create_reaction(message.channel_id, message.id, '🤠')

loop = asyncio.get_event_loop()

client = aiocord.client.Client(token = ...)

loop.run_until_complete(main(client))

Voice

Joining a voice channel and playing music via a local file.

import asyncio
import aiocord

async def start(client):
    await client.start()
    await client.ready()

async def main(client):
    voice = await client.start_voice('506536485156739358', '543273600667152384')
    audio = aiocord.voice.audio.Audio(source = './song.mp3')
    await voice.player.start(audio)

async def stop(client):
    await client.stop()

loop = asyncio.get_event_loop()

client = aiocord.client.Client(token = ...)

loop.run_until_complete(start(client))

try:
    loop.run_until_complete(main(client))
except KeyboardInterrupt:
    pass
finally:
    loop.run_until_complete(stop(client))

Audio data may be directly fed programatically.

with open('./song.mp3', 'rb') as file:
    data = file.read()

async def main(client):
    voice = await client.start_voice('506536485156739358', '543273600667152384')
    audio = aiocord.voice.audio.Audio()
    audio.feed(data)
    await voice.player.start(audio)

Note

For linux and macos, ffmpeg can be installed with homebrew via brew install ffmpeg. Since this creates a shell command, there is no need to specify the executable location.

For windows, ffmpeg.exe must be on the system. It can be found here. To avoid having to specify the executable location with Audio(executable = ...), it can be added to the PATH.