Skip to main content

better-interactions

Discord PyPI - Downloads

Better interactions for discord-py-interactions

Join the Discord server to ask questions, get help, or to discuss the project!

Installation:

pip install -U better-interactions

What is this library?

This is better-interactions, a library for discord-py-interactions which modifies component callbacks, and adds useful helper functions.

What does this have?

Listed below are all the features this library currently has:

  • Subcommands that you can create easily
  • Component callbacks are modified so you can enable checking if the custom_id of the component starts with the one provided in the decorator
  • ActionRow function which enables usage of ActionRow(...)
  • Component functions for Button and SelectMenu that has checks so you never have to incorrectly use Button(...) or SelectMenu(...)
  • spread_to_rows function which allows components to be spread to multiple ActionRows

Subcommands

Subcommands are technically options for commands, meaning to make subcommands, you may need long chains of options and if/elif/else conditionals.

This library provides a way to make subcommands, similar to subcommands in discord-py-interactions<=3.0.2.

How to use:

Here's some examples of subcommand usage:

from interactions.ext.better_interactions import base
...
# sets up bot.base, optional
bot.load("interactions.ext.better_interactions")
...
# create a base command:
the_base = bot.base("the_base", scope=874781880489222154)
# Or without loading:
the_base = base(bot, "the_base", scope=874781880489222154)

# create a subcommand with an optional group and required name:
@the_base.subcommand(
    group="the_group",
    name="the_name",
    description="A simple subcommand",
)
async def the_group(
    ctx: interactions.CommandContext,
):
    await ctx.send("1")

# another subcommand in the same group:
@the_base.subcommand(
    group="the_group",
    name="the_name2",
    description="A simple subcommand",
)
async def the_group2(
    ctx: interactions.CommandContext,
):
    await ctx.send("2")

# another subcommand in the same group with some options:
@the_base.subcommand(
    group="the_group",
    name="the_name3",
    description="A simple subcommand",
    options=[
        interactions.Option(
            type=interactions.OptionType.STRING,
            name="the_string",
            description="A string",
            required=True,
        ),
    ],
)
async def the_group3(
    ctx: interactions.CommandContext,
    the_string,
):
    await ctx.send(f"3 {the_string}")

# a subcommand in a different group:
@the_base.subcommand(
    group="the_group2",
    name="the_name4",
    description="A simple subcommand4",
)
async def the_group24(
    ctx: interactions.CommandContext,
):
    await ctx.send("4")

# a subcommand with no group:
@the_base.subcommand(
    name="the_name5",
    description="A simple subcommand5",
)
async def the_name5(
    ctx: interactions.CommandContext,
):
    await ctx.send("5")

# finishes the command:
the_base.finish()

This approach that I took is similar to the one in discord-py-interactions<=3.0.2, and the least complicated way to do it.

How to use inside of extensions:

main.py:

import interactions

bot = interactions.Bot(...)
bot.load("interactions.ext.better_interactions")  # optional

...

# load cog before bot.start()
bot.load("cog")

bot.start()

cog.py:

from interactions.ext.better_interactions import (
    extension_base,
    BetterExtension,
)


class Cog(BetterExtension):
    def __init__(self, bot):
        self.bot = bot

    the_base = extension_base("the_base", scope=874781880489222154)

    @the_base.subcommand(name="name1", description="subcommand")
    async def b(self, ctx):
        await ctx.send("You used /the_base name1")

    @the_base.subcommand(group="group1", name="name2", description="group subcommand")
    async def c(self, ctx):
        await ctx.send("You used /the_base group1 name2")

    the_base.finish()


def setup(bot):
    return Cog(bot)

New component callback

The new component callbacks are modified so you can enable checking if the custom_id of the component starts with the one provided in the decorator.

How to use:

In your bot, you must use this line:

bot = interactions.Client(...)
bot.load("interactions.ext.better_interactions")

Then, you can use the decorator!

If you want to use interactions-wait-for with this extension, you must add its respective keyword arguments into the setup function as well.

Below is an example of a component callback.

@bot.component("test", startswith=True)
async def startswith_custom_id(ctx):
    await ctx.send(ctx.data.custom_id)

The startswith=True keyword argument is optional, and if it is not provided, it will default to False and will be used like the normal component callbacks.

If you want to check if the custom_id of the component starts with the one provided in the decorator, you can use the startswith=True keyword argument.

By setting startswith=True, the component callback now fires when the custom_id of the component starts with the one provided in the decorator.

For example, if you have a component with a custom_id of "test", and you set startswith=True, the component callback will fire when the custom_id of the component starts with "test".

Let's say a button with custom_id of "test1" is clicked. Since it starts with "test", the component callback will fire.

However, if something like "tes" is clicked, the component callback will not fire.

To sum it up, the component callback will fire when the custom_id of the component starts with the one provided in the decorator.

Why should I use this?

This is useful if you want to check if the custom_id of the component starts with the one provided in the decorator. In discord-py-interactions, the component callbacks are only fired when they are the exact same custom_id as the one provided in the decorator. This is not that useful, since you waste a lot of data you could have stored in the component custom IDs. The callbacks provided from interactions-better-components fix the aforementioned issue.


ActionRow function

The ActionRow function enables usage of ActionRow(...) instead of ActionRow(components=[...]).

How to use:

Below is an example of ActionRow usage:

@bot.command(
    name="test", description="Test command",
)
async def test(ctx):
    await ctx.send("test", components=[
        ActionRow(select1),
        ActionRow(button1, button2, button3),
    ]
)

Why should I use this?

This is only for aesthetics, making the code look cleaner. Using ActionRow(...) is the same as using ActionRow(components=[...]), however, it is more readable.


Button and SelectMenu

The Button and SelectMenu functions are made so you never have to incorrectly use Button(...) or SelectMenu(...).

How to use:

Below is an example of Button usage:

from interactions.ext.better_interactions import Button

@bot.command(
    name="test", description="Test command",
)
async def test(ctx):
    await ctx.send("test", components=[
        Button(
            style=1,
            custom_id="test1",
            label="Test 1",
        ),
    ]
)

You can import Button and SelectMenu from better_interactions and use them like you would use Button(...) and SelectMenu(...) from discord-py-interactions.


spread_to_rows function

The spread_to_rows function allows components to be spread to multiple ActionRows with an optional max_in_row argument.

How to use:

You use the function like this: spread_to_rows(*components, max_in_row=3).

max_in_row=5 by default.

Separate components by None to explicitly start a new row.

Below is an example of spread_to_rows usage that spreads components to 2 ActionRows with 5 components each:

@bot.command(
    name="test", description="Test command",
)
async def test(ctx):
    await ctx.send("test", components=spread_to_rows(
        button1, button2, button3, button4, button5, button6, button7, button8, button9, button10,
    )
)

Credits

  • Catalyst4 for helping me solve countless issues
  • The devs of discord-py-interactions

Metadata

Release files for better-interactions 2.1.2

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for better-interactions 2.1.2
File Size Uploaded Provenance Actions
better-interactions-2.1.2.tar.gz 10.6 kB Without provenance Details for better-interactions-2.1.2.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for better-interactions 2.1.2
File Interpreter ABI Platform Actions
better_interactions-2.1.2-py3-none-any.whl Python 3 none any Details for better_interactions-2.1.2-py3-none-any.whl

Total release size: 22.6 kB

Release files / better-interactions-2.1.2.tar.gz

Download URL better-interactions-2.1.2.tar.gz
Size 10.6 kB
Tags Source
SHA-256 checksum
How to use checksums
ee87017ceb20d3e82a4a6a59fe10138aa65ce66adc3af34cd9ca9c40894ee92b
BLAKE2b-256 checksum
How to use checksums
7d8c8b022ea2a4f017d6e317af2b123275c24725abea1d6f892cc715da732a43
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/3.8.0 pkginfo/1.8.2 readme-renderer/32.0 requests/2.27.1 requests-toolbelt/0.9.1 urllib3/1.26.8 tqdm/4.62.3 importlib-metadata/4.11.0 keyring/23.5.0 rfc3986/2.0.0 colorama/0.4.4 CPython/3.9.10

Release files / better_interactions-2.1.2-py3-none-any.whl

Download URL better_interactions-2.1.2-py3-none-any.whl
Size 11.9 kB
Tags Python 3
SHA-256 checksum
How to use checksums
cdce4dd95a8e5cd7b253757f96be774a18ec60a80007429f4bfce00599d513f9
BLAKE2b-256 checksum
How to use checksums
0c9c55f20da13932fc02703c97a6d17b673ada334670f8c2d27f03ef9000d9eb
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/3.8.0 pkginfo/1.8.2 readme-renderer/32.0 requests/2.27.1 requests-toolbelt/0.9.1 urllib3/1.26.8 tqdm/4.62.3 importlib-metadata/4.11.0 keyring/23.5.0 rfc3986/2.0.0 colorama/0.4.4 CPython/3.9.10

Security for better-interactions 2.1.2

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page