diff --git a/CHANGELOG.md b/CHANGELOG.md index e95d08c840..0a6293f50e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,8 @@ These changes are available on the `master` branch, but have not yet been releas ### Added +- Added possibility to start bot via async context manager. + ([#1801](https://github.com/Pycord-Development/pycord/pull/1801)) - Added new parameters (`author`, `footer`, `image`, `thumbnail`) to `discord.Embed`. ([#1996](https://github.com/Pycord-Development/pycord/pull/1996)) - Added new events `on_bridge_command`, `on_bridge_command_completion`, and diff --git a/discord/client.py b/discord/client.py index 654219a0bd..27e94d7c2f 100644 --- a/discord/client.py +++ b/discord/client.py @@ -30,6 +30,7 @@ import signal import sys import traceback +from types import TracebackType from typing import TYPE_CHECKING, Any, Callable, Coroutine, Generator, Sequence, TypeVar import aiohttp @@ -253,6 +254,27 @@ def __init__( VoiceClient.warn_nacl = False _log.warning("PyNaCl is not installed, voice will NOT be supported") + async def __aenter__(self) -> Client: + loop = asyncio.get_running_loop() + self.loop = loop + self.http.loop = loop + self._connection.loop = loop + + self._ready = asyncio.Event() + + return self + + async def __aexit__( + self, + exc_t: BaseException | None, + exc_v: BaseException | None, + exc_tb: TracebackType | None, + ) -> None: + if not self.is_closed(): + await self.close() + + # internals + def _get_websocket( self, guild_id: int | None = None, *, shard_id: int | None = None ) -> DiscordWebSocket: diff --git a/examples/basic_async_bot.py b/examples/basic_async_bot.py new file mode 100644 index 0000000000..a72859fb37 --- /dev/null +++ b/examples/basic_async_bot.py @@ -0,0 +1,29 @@ +import asyncio + +import discord +from discord.ext import commands + +bot = commands.Bot( + command_prefix=commands.when_mentioned_or("!"), + intents=discord.Intents.default(), +) + + +@bot.event +async def on_ready(): + print(f"Logged in as {bot.user} (ID: {bot.user.id})") + print("------") + + +@bot.slash_command(guild_ids=[...]) # Create a slash command. +async def hello(ctx: discord.ApplicationContext): + """Say hello to the bot""" # The command description can be supplied as the docstring + await ctx.respond(f"Hello {ctx.author.mention}!") + + +async def main(): + async with bot: + await bot.start("TOKEN") + + +asyncio.run(main())