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