Advanced Patterns and Experiments
This section covers features that may not be immediately obvious to power users.
Additionally, this section will showcase how customizable ScurryPy is.
Using HTTP directly
As of 0.19.0, ScurryPy exposes its HTTP layer via HTTPClient for public consumption.
This layer handles rate limiting and still adheres to Discord's spec requirements.
This feature is useful for accessing endpoints that may not be exposed through ScurryPy's public interface.
Demonstrates using ScurryPy's HTTP client directly:
| from scurrypy import Client, EventTypes, UserModel
client = Client(TOKEN)
async def on_ready(event):
data = await client.http.request('GET', f'/users/{APP_ID}')
user = UserModel.from_dict(data)
print(user)
client.add_event_listener(EventTypes.READY, on_ready)
client.run()
|
Command Registration
See ScurryKit's commands pattern.
Caching
See ScurryKit's channel cache pattern.
Builder
See ScurryKit's action row builder pattern.
Running Two Bots In One Process
Demonstrates running two separate bots on the same process.
| from scurrypy import Client, EventTypes, ReadyEvent
class Bot:
def __init__(self, token: str):
self.bot = Client(token)
self.bot.add_event_listener(EventTypes.READY, self.on_ready)
self.task = asyncio.create_task(self.bot.start())
async def on_ready(self, event: ReadyEvent):
print(f"{event.user.username} is ready!")
import asyncio
async def main():
try:
await asyncio.gather(*(Bot(t).task for t in TOKENS))
except asyncio.CancelledError:
print("Bots are shutting down...")
asyncio.run(main())
|
DB Access
Demonstrates an example DB addon.
| from scurrypy import Client
import asyncpg
class PostgresDB:
def __init__(self, client: Client, user: str, database: str, password: str):
self.bot = client
from urllib.parse import quote
self.dsn = f"postgresql://{user}:{quote(password)}@localhost:5432/{database}"
self.pool: asyncpg.Pool = None
client.add_startup_hook(self.start_db)
client.add_shutdown_hook(self.close_db)
async def start_db(self):
self.pool = await asyncpg.create_pool(self.dsn)
async def close_db(self):
await self.pool.close()
async def get_connection(self) -> asyncpg.Connection:
return await self.pool.acquire()
|
Stress Testing
Curious to know how ScurryPy handles high traffic? ScurryPy can handle abuse without getting Discord angry.
This example creates C_COUNT channels, sends M_COUNT messages to each channel, and edits each message for maximum spam!
Notice: Not one rate limit error!
Danger
This example should NOT be run in a public server.
Consider running it in a server with just you and the bot!
| client = Client(TOKEN)
M_COUNT = 30
C_COUNT = 4
async def spam_messages(channel: Channel):
for i in range(M_COUNT):
msg = await channel.send(f'Testing {i}!')
await client.message(msg.channel_id, msg.id).edit(content='Edited!')
async def on_test(event):
for i in range(C_COUNT):
ch = await client.guild(GUILD_ID).create_channel(...)
asyncio.create_task(spam_messages(client.channel(ch.id)))
client.add_event_listener(EventTypes.READY, on_test)
client.run()
|