mirror of
https://github.com/Rapptz/discord.py.git
synced 2025-04-21 00:07:51 +00:00
Add advanced startup example
shows setup_hook and async context manager use with examples approximating real world use cases
This commit is contained in:
parent
3433e13848
commit
a8a6bf4f6c
94
examples/advanced_startup.py
Normal file
94
examples/advanced_startup.py
Normal file
@ -0,0 +1,94 @@
|
||||
# This example covers advanced startup options and uses some real world examples for why you may need them.
|
||||
|
||||
import asyncio
|
||||
import logging
|
||||
import logging.handlers
|
||||
import os
|
||||
|
||||
from typing import List, Optional
|
||||
|
||||
import asyncpg # asyncpg is not a dependency of the discord.py, and is only included here for illustrative purposes.
|
||||
import discord
|
||||
from discord.ext import commands
|
||||
from aiohttp import ClientSession
|
||||
|
||||
|
||||
class CustomBot(commands.Bot):
|
||||
def __init__(
|
||||
self,
|
||||
*args,
|
||||
initial_extensions: List[str],
|
||||
db_pool: asyncpg.Pool,
|
||||
web_client: ClientSession,
|
||||
testing_guild_id: Optional[int] = None,
|
||||
**kwargs,
|
||||
):
|
||||
super().__init__(*args, **kwargs)
|
||||
self.db_pool = db_pool
|
||||
self.web_client = web_client
|
||||
self.testing_guild_id = testing_guild_id
|
||||
self.initial_extensions = initial_extensions
|
||||
|
||||
async def setup_hook(self) -> None:
|
||||
|
||||
# here, we are loading extensions prior to sync to ensure we are syncing interactions defined in those extensions.
|
||||
|
||||
for extension in self.initial_extensions:
|
||||
await self.load_extension(extension)
|
||||
|
||||
# In overriding setup hook,
|
||||
# we can do things that require a bot prior to starting to process events from the websocket.
|
||||
# In this case, we are using this to ensure that once we are connected, we sync for the testing guild.
|
||||
# You should not do this for every guild or for global sync, those should only be synced when changes happen.
|
||||
if self.testing_guild_id:
|
||||
guild = discord.Object(self.testing_guild_id)
|
||||
# We'll copy in the global commands to test with:
|
||||
self.tree.copy_global_to(guild=guild)
|
||||
# followed by syncing to the testing guild.
|
||||
await self.tree.sync(guild=guild)
|
||||
|
||||
# This would also be a good place to connect to our database and
|
||||
# load anything that should be in memory prior to handling events.
|
||||
|
||||
|
||||
async def main():
|
||||
|
||||
# When taking over how the bot process is run, you become responsible for a few additional things.
|
||||
|
||||
# 1. logging
|
||||
|
||||
# for this example, we're going to set up a rotating file logger.
|
||||
# for more info on setting up logging,
|
||||
# see https://discordpy.readthedocs.io/en/latest/logging.html and https://docs.python.org/3/howto/logging.html
|
||||
|
||||
logger = logging.getLogger('discord')
|
||||
logger.setLevel(logging.INFO)
|
||||
|
||||
handler = logging.handlers.RotatingFileHandler(
|
||||
filename='discord.log',
|
||||
encoding='utf-8',
|
||||
maxBytes=32 * 1024 * 1024, # 32 MiB
|
||||
backupCount=5, # Rotate through 5 files
|
||||
)
|
||||
dt_fmt = '%Y-%m-%d %H:%M:%S'
|
||||
formatter = logging.Formatter('[{asctime}] [{levelname:<8}] {name}: {message}', dt_fmt, style='{')
|
||||
handler.setFormatter(formatter)
|
||||
logger.addHandler(handler)
|
||||
|
||||
# One of the reasons to take over more of the process though
|
||||
# is to ensure use with other libraries or tools which also require their own cleanup.
|
||||
|
||||
# Here we have a web client and a database pool, both of which do cleanup at exit.
|
||||
# We also have our bot, which depends on both of these.
|
||||
|
||||
async with ClientSession() as our_client, asyncpg.create_pool(user='postgres', command_timeout=30) as pool:
|
||||
# 2. We become responsible for starting the bot.
|
||||
|
||||
exts = ['general', 'mod', 'dice']
|
||||
async with CustomBot(commands.when_mentioned, db_pool=pool, web_client=our_client, initial_extensions=exts) as bot:
|
||||
|
||||
await bot.start(os.getenv('TOKEN', ''))
|
||||
|
||||
|
||||
# For most use cases, after defining what needs to run, we can just tell asyncio to run it:
|
||||
asyncio.run(main())
|
Loading…
x
Reference in New Issue
Block a user