Skip to content

Examples


The following example demonstrates what it looks like to use of ScurryPy itself.

Advanced Usage

For most bots, ScurryKit is recommended, which provides decorators, routing, and simplified interaction handling.

Setting Up

These examples assume you've already seen Setting Up.

Minimal Event Listener


Demonstrates listening for the READY event.

class MyAddon:
    def __init__(self, client: scurrypy.Client):

        self.bot = client

        # register this addon's functions to the client
        client.add_event_listener('READY', self.on_ready)

    async def on_ready(self, event: scurrypy.ReadyEvent):
        self.bot.logger.log_info("Bot is ready!")

client = scurrypy.Client(token=TOKEN, application_id=APP_ID)

# register addon with client
my_addon = MyAddon(client)

client.run()

Minimal Addon


Demonstrates addon setup. Feel free to use this as a reference!

class MyAddon:
    """Your custom addon."""

    def __init__(self, client: scurrypy.Client):
        self.bot = client

        # some handlers
        client.add_startup_hook(self.my_opening_handler)
        client.add_event_listener(self.my_event_listener)
        client.add_shutdown_hook(self.my_closing_handler)

    def my_opening_handler(self): # handlers can be sync or async
        """Custom startup hooks."""

    async def my_event_listener(self, event):
        """Handle your event here!"""

    def my_closing_handler(self):
        """Custom shutdown hooks."""

About Addons

Addons only add convenient patterns and never change the Discord API itself. You can optionally use Addon as a marker or typing convenience.

Event Routing


Demonstrates registering and listening to messages for commands via the MESSAGE_CREATE event.

class MyAddon:
    def __init__(self, client: scurrypy.Client, prefix: str):

        if not scurrypy.Intents.has(client.intents, scurrypy.Intents.MESSAGE_CONTENT):
            raise ValueError("Missing Intent.MESSAGE_CONTENT for scanning messages.")

        self.bot = client

        self._prefix = prefix
        self._commands = {}

        # fill contract with client
        client.add_event_listener("MESSAGE_CREATE", self.on_message_create)

    async def on_message_create(self, event: scurrypy.MessageCreateEvent):

        # filter non-command messages
        if not event.content.lower().startswith(self._prefix):
            return

        # dont let the bot respond to itself (possible infinite looping)
        if event.author.id == APP_ID:
            return

        # fetch handler based on command
        command = event.content.lower().removeprefix(self._prefix)
        handler = self._commands.get(command)

        # make sure there's a handler
        if not handler:
            raise ValueError(f"No handler matches {command}!")

        # pass relevent resource to user handler
        res = self.bot.message(event.channel_id, event.id, context=event)
        await handler(self.bot, res)

    def prefix(self, name: str):

        # make commands case-insensitive
        cmd = name.lower()

        def decorator(func):
            import inspect
            params_len = len(inspect.signature(func).parameters)
            if params_len != 2:
                raise ValueError(f"Prefix command '{cmd}' expects parameters (bot, message).")
            self._commands[cmd] = func

        self.bot.logger.log_info(f"Prefix command '{cmd}' registered!")

        return decorator

client = scurrypy.Client(
    token=TOKEN, 
    application_id=APP_ID, 
    intents=scurrypy.Intents.set(message_content=True)
)

my_addon = MyAddon(client, '!')

@my_addon.prefix("ping")
async def on_ping(bot: scurrypy.Client, message: scurrypy.Message):
    await message.send('Pong!')

client.run()

Basic Slash Command


Demonstrates registering and responding to a slash command.

class MyAddon:
    def __init__(self, client: scurrypy.Client):
        self.bot = client

        self.slash_commands = {}

        client.add_startup_hook(self.on_start)
        client.add_event_listener("INTERACTION_CREATE", self.on_interaction)

    async def on_start(self):
        """Register commands and routes."""

        commands = [
            scurrypy.SlashCommand('hello', 'Say hello!')
        ]

        await self.bot.register_guild_commands(commands, guild_id=GUILD_ID)

        self.slash_commands['hello'] = self.on_hello

        self.bot.logger.log_info("Commands ready!")

    async def on_hello(self, interaction: scurrypy.Interaction):
        """Demo interaction response."""

        await interaction.respond("You got it!")

    async def on_interaction(self, event: scurrypy.InteractionEvent):
        """Handles routing event by interaction type."""
        if event.type != scurrypy.InteractionTypes.APPLICATION_COMMAND:
            return

        handler = self.slash_commands.get(event.data.name)

        res = self.bot.interaction(event.id, event.token, context=event)
        if handler:
            await handler(res)
        else:
            await res.respond("Command not found!", ephemeral=True)

client = scurrypy.Client(token=TOKEN, application_id=APP_ID)

my_addon = MyAddon(client)

client.run()