Gears

Gears are a modular event handling system in Pycord that allow you to organize your event listeners into reusable components. They provide a clean way to structure event-driven code and enable composition by allowing gears to be attached to other gears or to the bot itself.

Gear

Attributes
class discord.gears.Gear[source]

A gear is a modular component that can listen to and handle events.

You can subclass this class to create your own gears and attach them to your bot or other gears.

Example

@listen(once=False)[source]
Parameters:
  • event (type[TypeVar(E, bound= Event, covariant=True)] | Undefined)

  • once (bool)

Return type:

Callable[[Callable[[Any, TypeVar(E, bound= Event, covariant=True)], Awaitable[None]]], Callable[[Any, TypeVar(E, bound= Event, covariant=True)], Awaitable[None]]]

attach_gear(gear)[source]

Attaches a gear to this gear.

This will propagate all events from the attached gear to this gear.

Parameters:

gear (Gear) – The gear to attach.

Return type:

None

detach_gear(gear)[source]

Detaches a gear from this gear.

Parameters:

gear (Gear) – The gear to detach.

Raises:

KeyError – If the gear is not attached.

Return type:

None

add_listener(callback, *, event=Undefined.MISSING, is_instance_function=False, once=False)[source]

Adds an event listener to the gear.

Parameters:
  • callback (Callable[[TypeVar(E, bound= Event, covariant=True)], Awaitable[None]]) – The callback function to be called when the event is emitted.

  • event (type[TypeVar(E, bound= Event, covariant=True)] | Undefined) – The type of event to listen for. If not provided, it will be inferred from the callback signature.

  • once (bool) – Whether the listener should be removed after being called once.

  • is_instance_function (bool) – Whether the callback is an instance method (i.e., it takes the gear instance as the first argument).

Raises:

TypeError – If the event type cannot be inferred from the callback signature.

Return type:

None

remove_listener(callback, event=Undefined.MISSING, is_instance_function=False)[source]

Removes an event listener from the gear.

Parameters:
  • callback (Callable[[TypeVar(E, bound= Event, covariant=True)], Awaitable[None]]) – The callback function to be removed.

  • event (type[TypeVar(E, bound= Event, covariant=True)] | Undefined) – The type of event the listener was registered for. If not provided, it will be inferred from the callback signature.

  • is_instance_function (bool) – Whether the callback is an instance method (i.e., it takes the gear instance as the first argument).

Raises:
  • TypeError – If the event type cannot be inferred from the callback signature.

  • KeyError – If the listener is not found.

Return type:

None

Basic Usage

Creating a Gear

You can create a gear by subclassing discord.gears.Gear and using the listen() decorator to register event listeners:

from discord.gears import Gear
from discord.events import Ready, MessageCreate

class MyGear(Gear):
    @Gear.listen()
    async def on_ready(self, event: Ready) -> None:
        print(f"Bot is ready!")

    @Gear.listen()
    async def on_message(self, event: MessageCreate) -> None:
        print(f"Message: {event.content}")

Attaching Gears

Gears can be attached to a Client or Bot using the attach_gear() method:

bot = discord.Bot()
my_gear = MyGear()
bot.attach_gear(my_gear)

You can also attach gears to other gears, creating a hierarchy:

parent_gear = MyGear()
child_gear = AnotherGear()
parent_gear.attach_gear(child_gear)

Instance Listeners

You can also add listeners to a gear instance dynamically:

my_gear = MyGear()

@my_gear.listen()
async def on_guild_join(event: GuildJoin) -> None:
    print(f"Joined guild: {event.guild.name}")

Advanced Usage

One-Time Listeners

Use the once parameter to create listeners that are automatically removed after being called once:

class MyGear(Gear):
    @Gear.listen(once=True)
    async def on_first_message(self, event: MessageCreate) -> None:
        print("This will only run once!")

Manual Listener Management

You can manually add and remove listeners using add_listener() and remove_listener():

from discord.events import MessageCreate

async def my_listener(event: MessageCreate) -> None:
    print(f"Message: {event.content}")

gear = MyGear()
gear.add_listener(my_listener, event=MessageCreate)

# Later, remove it
gear.remove_listener(my_listener, event=MessageCreate)

Detaching Gears

Remove a gear using detach_gear():

bot.detach_gear(my_gear)

Client and Bot Integration

Both Client and Bot provide gear-related methods:

These methods work identically to their Gear counterparts.

Example: Modular Bot Structure

Here’s an example of using gears to create a modular bot:

from discord import Bot
from discord.gears import Gear
from discord.events import Ready, MessageCreate, GuildJoin

class LoggingGear(Gear):
    @Gear.listen()
    async def log_ready(self, event: Ready) -> None:
        print("Bot started!")

    @Gear.listen()
    async def log_messages(self, event: MessageCreate) -> None:
        print(f"[{event.channel.name}] {event.author}: {event.content}")

class ModerationGear(Gear):
    @Gear.listen()
    async def welcome_new_guilds(self, event: GuildJoin) -> None:
        system_channel = event.guild.system_channel
        if system_channel:
            await system_channel.send("Thanks for adding me!")

bot = Bot()

# Attach gears to the bot
bot.attach_gear(LoggingGear())
bot.attach_gear(ModerationGear())

bot.run("TOKEN")