A globally accessible context object for discord.py events.
Able to be used in both base clients and the commands extension.
pip install discord.ext.context
- Python 3.7+
- discord.py 1.6+
Subclass the context.ContextClient
base class, ensuring that it's first in inheritance order.
import discord
from discord.ext import context
class Client(context.ContextClient, discord.Client):
...
Import context.ctx
from anywhere, and it'll have its attributes set based on the event that your call stack originates from.
import discord
from discord.ext.context import ctx
async def log_reaction():
await ctx.channel.send(f"{ctx.user} reacted with {ctx.emoji}")
client = discord.Client()
@client.event
async def on_raw_reaction_add():
await log_reaction()
Accessing a context value before it's set will have this exception raised. To have a fallback value used instead, use the contextmanager with ctx.default():
.
ctx.message
: discord.PartialMessage
Should always be a PartialMessage
. If a Message
instance is needed, an up to date copy can be retrieved with PartialMessage.fetch()
.
ctx.emoji
: discord.Emoji
or discord.PartialEmoji
Often representing a reaction interacted with by a user; useful for user interactions that use reaction-based sessions.
ctx.channel
: discord.abc.Messageable
Will always be a text channel or user-type object that's possible to send messages to. Does not include voice channels.
ctx.user
: discord.Member
or discord.User
If setting a discord.User
instance and the user shares only a single guild with the client, it'll replace it with the discord.Member
instance.
ctx.guild
: discord.Guild
Will only be set on guild-specific events.
ctx.cmd_ctx
: discord.ext.commands.Context
Will only be set on the command event, with other EventContext values being set using it.
The name of the event type this context originates from.
ctx.client
: discord.Client
The instance of the discord.py client being hooked into.
ctx.bot
: discord.Client
Alias for ctx.client
.
Sets the values for the current context to be used across future call stacks. Won't impact asynchronous calls from other events.
Decorator for registering an event to be handled by the decorated function. Will override existing hooks if a duplicate exists.
ctx.default(all_default, *, message=_NoValue, emoji=_NoValue, user=_NoValue, channel=_NoValue, guild=_NoValue, cmd_ext=_NoValue)
Context manager for registering default values to be used if a value isn't set. On leaving the context manager's scope, ctx
will revert to original state.
Use all_default
to set all the available ctx.values to the one value. This can be useful for allowing None to be returned for nonset contexts.
with ctx.default(None):
if ctx.channel:
await ctx.channel.send("Yes")
with ctx.default(channel=fallback_channel, user=None):
if ctx.user:
await ctx.channel.send(f"{ctx.user.display_name}")
If ctx.channel
or ctx.user
is not yet set, it'll be assigned the fallback arguments. This includes being able to set a value to None
instead of raising ContextNotSet
.
It can also be used as a decorator for a function.
@ctx.default(channel=fallback_channel, user=None)
async def show_name():
if ctx.user:
await ctx.channel.send(f"{ctx.user.display_name}")
ctx.ephemeral(*, message=_NoValue, emoji=_NoValue, user=_NoValue, channel=_NoValue, guild=_NoValue, cmd_ext=_NoValue)
Context manager for overriding context values. On leaving the context manager's scope, ctx
will revert to original state.
with ctx.ephemeral(channel=log_channel, user=None):
if ctx.user:
await ctx.channel.send(f"{ctx.user.display_name} did a thing.")
If ctx.channel
or ctx.user
is not yet set, it'll be assigned the fallback arguments. This includes being able to set a value to None
instead of raising ContextNotSet
.
It can also be used as a decorator for a function.
@ctx.ephemeral(channel=log_channel, user=None)
async def show_name():
if ctx.user:
await ctx.channel.send(f"{ctx.user.display_name} did a thing.")
By default, the following events are hooked by EventContext:
message
message_delete
message_edit
raw_message_delete
raw_message_edit
reaction_add
reaction_remove
raw_reaction_add
raw_reaction_remove
reaction_clear
reaction_clear_emoji
raw_reaction_clear
raw_reaction_clear_emoji
typing
guild_channel_update
guild_channel_create
guild_channel_delete
guild_channel_pins_update
webhooks_update
guild_update
guild_join
guild_remove
guild_integrations_update
guild_emojis_update
guild_available
guild_unavailable
member_update
member_join
member_remove
member_ban_hook
member_unban_hook
guild_role_update_hook
guild_role_create_hook
guild_role_delete_hook
command
You can add more event hooks or replace the default ones with the decorator:
@EventContext.register_hook(event_name)
def event_hook(*args, **kwargs):
...