Quickstart¶
Short Examples¶
Import¶
from discord.ext import reactioncommands
or specific things
from discord.ext.reactioncommands import reaction_command, reaction_group
Create a ReactionBot¶
bot = reactioncommands.ReactionBot(prefix, prefix_emoji, listening_emoji)
prefix_emoji: Similar tocommand_prefixbut for reaction commands. Will start a “listening session” where the bot listens for raw reaction add/remove withwait_for()and finds the matching command from the emojis added/removed.listening_emojiIf set, this emoji will be added after the user reacts with theprefix_emojito let the user know the “listening session” has started. Also used for invoking subcommands.
Use decorators to add commands¶
reaction_command>()
@bot.reaction_command("🤔")
async def something(ctx):
pass
If you’re in a cog
class ReactionCog(commands.Cog):
@reaction_command("🤔")
async def something(self, ctx):
pass
Short-ish code examples¶
Simple command¶
from discord.ext import reactioncommands
bot = reactioncommands.ReactionBot(command_prefix="!",
prefix_emoji="🤔"),
listening_emoij="👀",
listen_timeout=30
)
@bot.reaction_command("👋")
async def hi(ctx):
await ctx.send(f"Hi {ctx.author}")
Cogs¶
import discord
from discord.ext import commands, reactioncommands
class MyCog(commands.Cog):
def __init__(self, bot):
self.bot = bot
@reactioncommands.reaction_command("🎉")
@commands.guild_only()
async def tada(self, ctx, member:discord.Member):
# member will always be None when
# invoked from reactions.
member = member or ctx.author
await ctx.send(f"🎉🎉 {member.id} 🎉🎉")
Multiple emojis or aliases¶
@bot.reaction_command("👋👋👋👋👋"])
async def bye(ctx):
await ctx.send("👋*5")
@bot.reaction_command(["👋👋", "👋👋👋"])
async def hi(ctx):
# ctx.invoked_with will be which emoji(s) the user
# invoked the command with, so "👋👋" or "👋👋👋".
await ctx.send(f"{ctx.invoked_with} {ctx.author}")
Groups¶
@bot.reaction_group("👋", invoke_without_command=True)
async def hi(ctx):
await ctx.send(f"Hi {ctx.author}")
@hi.reaction_command("🚶")
async def bye(ctx):
await ctx.send(f"Oh! Sorry to see you go {ctx.author} :(")
Mixing ReactionGroups with Commands¶
# can be invoked with messages or reactions
@bot.reaction_group("👋", invoke_without_command=True)
async def hi(ctx):
await ctx.send(f"Hi {ctx.author}")
# normal command that can only be invoked with a message
@hi.command()
async def hihi(ctx):
await ctx.send(f"HiHiHi there {ctx.author}")
# reaction command that can only be invoked with reactions
@hi.reaction_command("🇭🇮", invoke_with_message=False)
async def _hihi(ctx):
await ctx.send("🇭🇮 👋")
Case insensitive¶
from discord.ext import reactioncommands
bot = reactioncommands.ReactionBot(command_prefix="!",
prefix_emoji="🤔"),
listening_emoij="👀",
case_insensitive=True
)
# can be invoked with any of 👍,👍🏻,👍🏼,👍🏽,👍🏾,👍🏿
@bot.reaction_command("👍")
async def hi(ctx):
await ctx.send(f"Send that {ctx.invoked_with} {ctx.author} 👍👍👍")
Commands without emoji prefix¶
# invoke_without_prefix=True means this command will be invoked for any
# 👋 reaction. Be careful when using this.
@bot.reaction_command("👋", invoke_without_prefix=True)
async def hi(ctx):
await ctx.reply(f"{ctx.author} says hi 👋👋👋")
Limited custom emoji support¶
Doesn’t seem like a good way to do this currently. Better custom emoji support will probably require a rewrite.
# Must use the full <:name:id> format.
# Breaks if the emoji ever changes name and becomes unusable if the emoji
# is deleted.
@bot.reaction_command("<:python:596577462335307777>")
async def python(ctx):
await ctx.send("Python is fun")
Anyways, here’s a huge wall of example code¶
Code with comments that explain what some stuff does.
import asyncio
import discord
from discord.ext import commands, reactioncommands
intents = discord.Intents.default()
intents.members = True
# 'prefix ' is the normal command_prefix for message commands.
# '🤔' is the reaction prefix. It must be added to start listening for prefix emojis.
# A user can only have 1 listening session at once.
# If they mess up the command they must end the session by removing
# 🤔(reaction prefix) and adding the reaction prefix again.
# '👀' will be added to let the user know the bot is listening for
# reaction events and for separating groups from subcommands.
bot = reactioncommands.ReactionBot('prefix ', '🤔', '👀',
intents=intents)
# prefix_emoji and listening_emoji support callables like `get_emoji_prefix(bot, payload)`
# All the normal Bot kwargs will work also.
# To invoke this command you would react 🤔 on a message.
# The bot will add 👀, then you can add reactions to invoke the command.
# '👋👋' is what needs to be added/removed to invoke this command.
# In total, you would follow this reaction order:
# + is add reaction, - is remove reaction
# +🤔(prefix) > +👋 > -👋
@bot.reaction_command('👋👋', name='hi')
async def not_hi(ctx):
"""Says hi!"""
await ctx.send(f'Hi {ctx.author.mention}!')
# You can also invoke this with a message with content 'prefix hi'.
# Works with normal @commands.command() kwargs.
# Groups works too!
# To invoke the subcommand 'sub', you could react:
# +🤔(prefix) > +👍🏾 > +👀(listen for subcommand) > -👍🏾 > +👍🏾
# 👀 (listening_emoji) separates parent reactions from subcommand reactions
# case_insensitive will try to ignore different skin color/gender modifiers.
# You can also invoke the subcommand with:
# +🤔(prefix) > +👍🏾 > +👀(listen for subcommand) > +👍 > -👍
@bot.reaction_group('👍🏾', case_insensitive=True)
async def parent(ctx):
await ctx.send(f'In parent command **{ctx.command}**!\n' \
'{ctx.invoked_subcommand.name=}\n' \
'{ctx.subcommand_passed=}\n{"-"*10}')
# invoke_with_message=False means the command can
# only be invoked from reactions (default is True).
@parent.reaction_command('👍🏾👍🏾', invoke_with_message=False)
async def sub(ctx):
"""
Groups are hard to use with reactions.
This feature mainly exists to be compatible with normal Groups,
since reaction commands can be invoked with a message.
"""
await ctx.send(f'In sub command **{ctx.command}**!\n' \
'{ctx.invoked_subcommand=}---{ctx.subcommand_passed=}\n' \
'{ctx.command.parent.name=}')
# Supports checks, cooldowns, max_concurrency,
# before and after invoke, and local error handlers
@commands.guild_only()
@commands.cooldown(1, 60, commands.BucketType.user)
@commands.max_concurrency(1)
# You can pass a list/tuple of strings to, similar to aliases.
# This command can be invoked with:
# +🤔(prefix) > +🥺
# or
# +🤔(prefix) > +🥺 > -🥺
@bot.reaction_command(['🥺', '🥺🥺'])
async def please(ctx):
text = 'ctx.message will be a PartialMessageif invoked from reactions\n' \
'To get a full message, you can use ctx.get() which searches message cache' \
'or ctx.fetch() which is a shortcut to PartialMessage.fetch()\n'
'ctx.author is NOT the same as ctx.message.author for reaction commands\n' \
'ctx.message is the message reactions were added to\n' \
'ctx.author is the user who added reactions, not message.author\n' \
'Lots of things broken, ex: args will only be default value or None'
await ctx.trigger_typing()
await asyncio.sleep(9)
await ctx.message.reply(text)
with open('definitely-not-my-token', 'r') as f:
token = f.read()
bot.run(token)