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:
messagemessage_deletemessage_editraw_message_deleteraw_message_edit
reaction_addreaction_removeraw_reaction_addraw_reaction_removereaction_clearreaction_clear_emojiraw_reaction_clearraw_reaction_clear_emoji
typingguild_channel_updateguild_channel_createguild_channel_deleteguild_channel_pins_updatewebhooks_update
guild_updateguild_joinguild_removeguild_integrations_updateguild_emojis_updateguild_availableguild_unavailable
member_updatemember_joinmember_removemember_ban_hookmember_unban_hook
guild_role_update_hookguild_role_create_hookguild_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):
...