A Python wrapper for discord slash-commands, designed to extend discord.py.

Overview

dislash.py

Discord PyPi Python

An extending library for discord.py that allows to build awesome slash-commands.

โญ Star us on GitHub - we do really need your feedback and help!

Installation

Run any of these commands in terminal:

pip install dislash.py
python -m pip install dislash.py

Features

  • Supports automatic registration of slash-commands
  • Supports manual and automatic sharding
  • Convenient decorator-based interface
  • OOP-based slash-command constructor

Examples

๐Ÿ’ก This library does require discord.py installed.

Creating a slash-command

In this example registration is automatic. If you want to register slash-commands separately, see examples below.

from discord.ext import commands
from dislash import slash_commands
from dislash.interactions import *

client = commands.Bot(command_prefix="!")
slash = slash_commands.SlashClient(client)
test_guilds = [12345, 98765]

@slash.command(
    name="hello", # Defaults to function name
    description="Says hello",
    guild_ids=test_guilds # If not specified, the command is registered globally
    # Global registration takes more than 1 hour
)
async def hello(inter):
    await inter.reply("Hello!")

client.run("BOT_TOKEN")

Registering a slash-command

This example only shows how to register a slash-command.

from discord.ext import commands
from dislash import slash_commands
from dislash.interactions import *

client = commands.Bot(command_prefix="!")
slash = slash_commands.SlashClient(client)
test_guild_ID = 12345

@slash.event
async def on_ready():
    sc = SlashCommand(
        name="random",
        description="Returns a random number from the given range",
        options=[
            Option(
                name="start",
                description="Enter a number",
                required=True,
                type=Type.INTEGER
            ),
            Option(
                name="end",
                description="Enter a number",
                required=True,
                type=Type.INTEGER
            )
        ]
    )
    await slash.register_global_slash_command(sc)
    # Discord API uploads GLOBAL commands for more than 1 hour
    # That's why I highly recommend .register_guild_slash_command for testing:
    await slash.register_guild_slash_command(test_guild_id, sc)

client.run("BOT_TOKEN")

You should register a slash-command only once in order to make it work. You can always edit it if you want, using .edit_global_slash_command / .edit_guild_slash_command methods.

Responding to a slash-command

It's assumed that you've already registered the command.

from random import randint
from discord.ext import commands
from dislash import slash_commands
from dislash.interactions import *

client = commands.Bot(command_prefix="!")
slash = slash_commands.SlashClient(client)

@slash.command()
async def random(interaction):
    # interaction is instance of `interactions.Interaction`
    # It's pretty much the same as "ctx" from discord.py
    # except  attribute is replaced by 
    a = interaction.data.get_option('start').value
    b = interaction.data.get_option('end').value
    if b < a: a, b = b, a
    await interaction.reply(randint(a, b))

client.run("BOT_TOKEN")

Links

Documentation

PyPi

Our Discord

Comments
  • Use versions for pip packages

    Use versions for pip packages

    As long as you use "latest" without a version, we need to uninstall and reinstall the dislash.py entirely to get the latest features, such as ContextMenus.

    opened by f11y11 4
  • Slash command interaction is expired on arrival

    Slash command interaction is expired on arrival

    When testing a simple slash command using dislash, when i get to the callback that handles the slash command, the interaction is already expired. The code i'm using to test this:

        @slash_commands.command(
            name="maybe_this_works",
            description="testing slash commands",
            guild_ids=[GUILD_ID]
        )
        async def maybe_this_works(self, inter:Interaction):
            logger.debug(inter)
            logger.debug("snowflake time: " + inter.created_at.isoformat())
            logger.debug("current time: " + dt.datetime.utcnow().isoformat())
            logger.debug("is expired: " + str(inter.expired))
            logger.debug("is sent: " + str(inter._sent))
            await inter.reply("hello!")
    

    Output in discord: image Output in logs:

        vote     | maybe_this_works |   47 | DEBUG    | snowflake time: 2021-08-04T15:21:41.611000
        vote     | maybe_this_works |   48 | DEBUG    | current time: 2021-08-04T18:21:41.803420
        vote     | maybe_this_works |   49 | DEBUG    | is expired: True
        vote     | maybe_this_works |   50 | DEBUG    | is sent: False
    

    Result of the logs show that the time being reported by interaction.created_at is not calculated as UTC.

    It seems interaction.expired uses interaction.created_at which in turn uses a dislash.py specific implementation of snowflake_time that does not force the timestamp to be created in UTC+0: https://github.com/EQUENOS/dislash.py/blob/5b6d6b19ec078c914c9110b8c1a6a333145ec785/dislash/interactions/interaction.py#L15-L18 https://github.com/EQUENOS/dislash.py/blob/5b6d6b19ec078c914c9110b8c1a6a333145ec785/dislash/interactions/interaction.py#L98-L110

    This differs from discord.py's implementation, which forces the timestamp to be calculated in UTC+0:

    def snowflake_time(id: int) -> datetime.datetime:
        """
        Parameters
        -----------
        id: :class:`int`
            The snowflake ID.
        Returns
        --------
        :class:`datetime.datetime`
            An aware datetime in UTC representing the creation time of the snowflake.
        """
        timestamp = ((id >> 22) + DISCORD_EPOCH) / 1000
        return datetime.datetime.fromtimestamp(timestamp, tz=datetime.timezone.utc)
    

    If I change dislash's function to use either datetime.datetime.utcfromtimestamp, or discord.py's implementation of snowflake_time, the problem goes away and the interaction is no longer considered expired on arrival.

    I can make a pull request to fix that if it would help, I just needed to know which route would you rather use to fix that (change dislash.py's implementation or adopt discord.py's function instead).

    opened by diogoriba 4
  • Unknown Webhook when ApplicationID no equal UserID

    Unknown Webhook when ApplicationID no equal UserID

    I've only messed with Buttons, but I consistently get Unknown Webhook on one bot. Someone else suggested that it is likely due to the Bot's UserID not being the same as the ApplicationID. In this case, that is true. The App was originally personal but was moved to a team, so that is likely when it changed. Maybe I'm missing something, I haven't fully explored everything yet

    Jun 16 02:15:32 python[407319]: Traceback (most recent call last):
    Jun 16 02:15:32 python[407319]:   File "/mnt/discord/red-data/scgc/cogs/CogManager/cogs/rps/rps.py", line 143, in on_rock
    Jun 16 02:15:32 python[407319]:     await inter.reply(type=ResponseType.DeferredUpdateMessage)
    Jun 16 02:15:32 python[407319]:   File "/mnt/discord/red-data/scgc/cogs/Downloader/lib/dislash/interactions/interaction.py", line 204, in reply
    Jun 16 02:15:32 python[407319]:     return await self.fetch_initial_response()
    Jun 16 02:15:32 python[407319]:   File "/mnt/discord/red-data/scgc/cogs/Downloader/lib/dislash/interactions/interaction.py", line 392, in fetch_initial_response
    Jun 16 02:15:32 python[407319]:     data = await self._client.http.request(
    Jun 16 02:15:32 python[407319]:   File "/home/red/envs/scgc/lib/python3.8/site-packages/discord/http.py", line 250, in request
    Jun 16 02:15:32 python[407319]:     raise NotFound(r, data)
    Jun 16 02:15:32 python[407319]: discord.errors.NotFound: 404 Not Found (error code: 10015): Unknown Webhook
    
    bug good first issue 
    opened by yamikaitou 4
  • Slash Command duplicate and wont change name

    Slash Command duplicate and wont change name

    So i tried to made a slash command code:

    #Slash Command
    
    slash=SlashClient(Tango())
    
    @slash.command(
        name="echo",
    	description="Echo word that you specified",
        options=[
            Option("word", "Specify a word that will get send", Type.STRING, required=True)
        ]
    )
    async def echo(inter, *,word):
    	await inter.reply(word, allowed_mentions=discord.AllowedMentions(everyone=False, users=False, roles=False, replied_user=True))
    

    and it work but, i may found or cause a bug. The slash command name is echo and basically echo an argument but, i accidentally duplicate the command. The echo command and its duplicate work fine but if i remove the command, both name still registered in the bot data and the slash command wont change name if i change the function name, and of course cause errors, one of them is "This interaction failed" and "Invalid interaction application command". My question is, how did the command duplicate and how do i remove it from the bot data? slash_command

    opened by TheGenocides 3
  • TypeError: emoji() takes 1 positional argument but 2 were given

    TypeError: emoji() takes 1 positional argument but 2 were given

        @inter_client.slash_command(guild_ids=bonbot_support)
        async def emoji(ctx):
            pass
        @emoji.sub_command(description="steal an emoji with an option to lock it to a role", options=[Option("emoji", "an emoji to steal", OptionType.STRING, required=True),
        Option("role", "A role to lock this emoji to. (User must have this role to use emoji)", OptionType.ROLE)], guild_ids=bonbot_support)
        @slash_commands.guild_only()
        @slash_commands.has_permissions(manage_emojis=True)
        async def steal(self, ctx, emoji, role):
            c = commands.EmojiConverter() # create instance
            emoji_final = await c.convert(emoji) 
            # fetch the emoji asset and read it as bytes.
            emoji_bytes = await emoji_final.read()
    
            emoji_roles = [role]
            await ctx.guild.create_custom_emoji(name=emoji_final.name, image=emoji_bytes, roles=emoji_roles)
            await ctx.send("Created emoji!", ephemeral=True)
    

    I get this error when I run this code, I even added print("number") after every step and it doesn't print anything. Not sure what is happening, I have asked for help in several servers and nobody can figure it out. When I run the same code as a regular command, (removing the components parts) it works flawlessly. Full error: https://mystb.in/UrwPutsGarlic.apache

    opened by eltaylor1104 2
  • TypeError: object of type 'ActionRow' has no len()

    TypeError: object of type 'ActionRow' has no len()

    NOTE: ONLY HAPPENS IN COGS The Code:

    from dislash import *
    @commands.command()
    async def cmd(self,ctx,arg):
    	row = ActionRow(
    		Button(style=ButtonStyle.green, label="My Label Here!!", custom_id="tx")
    	)
    	def check(inter):
    		return inter.author == ctx.author and inter.author.guild_permissions.manage_emojis
    	try:
    		# SOME SHIT HERE!!
    	except:
    		# COUNTER
    
    

    Precise Output in the Terminal:

    File "/MY_DIRS/python/lib/python3.9/site-packages/dislash/application_commands/_modifications/old.py", line 105, in send_with_components
         if len(components) > 5:
    TypeError: object of type 'ActionRow' has no len()
    

    EDIT: Markdown changes

    opened by v1s1t0r999 2
  • Reset Cooldown Doesn't Work

    Reset Cooldown Doesn't Work

    I try to use slash_core.BaseSlashCommand.reset_cooldown(inter) to reset the cooldown. But it shows this error: reset_cooldown() missing 1 required positional argument: 'inter'

    Then I try this: slash_core.BaseSlashCommand.reset_cooldown(self, inter) But it still shows the error: 'SlashCommand' object has no attribute '_buckets'

    opened by LextYi 2
  • Patch to fix decorators in between @slash_commands.command decorator and final function

    Patch to fix decorators in between @slash_commands.command decorator and final function

    Previously if an additional decorator was in between the @slash_commands.command decorator and command function, the provided options would not be unpacked.

    The issue arises from: https://github.com/EQUENOS/dislash.py/blob/ef33dee6b5b95ec77fa4ffd9201e2b689020d108/dislash/slash_commands/slash_core.py#L97-L103 Specifically where __code__ is called. __code__ represents the decorated code, even if functools.wraps is used - and thus the calculated argcount is from the wrapper function - not the internal one. This causes _uses_ui to evaluate to false and params set to be equal to {} as shown here: https://github.com/EQUENOS/dislash.py/blob/ef33dee6b5b95ec77fa4ffd9201e2b689020d108/dislash/slash_commands/slash_core.py#L123-L126 The solution is to use inspect to unwrap the function beforehand (inspect.unwrap(func) so that __code__ correctly points to the code of the actual function

    opened by dob9601 2
  • Allow for decorator chaining when a decorator modifies the kwargs

    Allow for decorator chaining when a decorator modifies the kwargs

    I've got a decorator that adds an additional kwarg to a function and have been using this with the default discord.py framework. This decorator helps integrate django with discord.py by using the user id in the context to fetch the user object from the django database. However, due to the code shown here: https://github.com/EQUENOS/dislash.py/blob/6aa5f28c6c43799d9af089a2b98cf61affb978f7/dislash/slash_commands/slash_core.py#L365-L374 That kwarg never actually reaches the function. Would it be possible to add support for additional custom kwargs by exposing all additional kwargs to the command function?

    opened by dob9601 2
  • Interaction is subscriptable now

    Interaction is subscriptable now

    I haven't tested this yet, but it should work fine. Old syntax:

    inter.get('option_name')
    inter.option_at(1).value
    

    New syntax:

    inter['option_name']
    inter[1]
    
    opened by m1raynee 2
  • ModuleNotFoundError when trying to import dislash

    ModuleNotFoundError when trying to import dislash

    When trying to import dislash.py, a ModuleNotFoundError: No module named 'discord.webhook.async_' is raised.

    Full traceback: Traceback (most recent call last): File "main.py", line 2, in import threading, dislash File "/opt/virtualenvs/python3/lib/python3.8/site-packages/dislash/init.py", line 4, in from .interactions import * File "/opt/virtualenvs/python3/lib/python3.8/site-packages/dislash/interactions/init.py", line 1, in from .interaction import * File "/opt/virtualenvs/python3/lib/python3.8/site-packages/dislash/interactions/interaction.py", line 13, in from discord.webhook.async_ import WebhookMessage ModuleNotFoundError: No module named 'discord.webhook.async_'

    opened by rf20008 1
  • typing mismatch python version

    typing mismatch python version

    dislash/interactions/types.py

    attempts to import TypedDict which was added in 3.8 does not match the python ver requirement in setup.py for python_requires='>=3.6`

    opened by MujyKun 0
  • ERROR IN DOCS

    ERROR IN DOCS

    Here is what I found in the docs of dislash.py

        def check(inter):
            # inter is instance of MessageInteraction
            # read more about it in "Objects and methods" section
            if inter.author == ctx.author
        # Wait for a menu click under the message you've just sent
        inter = await msg.wait_for_dropdown(check)
        # Tell which options you received
        labels = [option.label for option in inter.select_menu.selected_options]
        await inter.reply(f"Your choices: {', '.join(labels)}")
    

    It is noticible that there is no colon after if inter.author ==ctx.author nor the indentation level is equal

    opened by prakarsh17 0
  • Error when I start the server

    Error when I start the server

    I get this error when I start the server. The 1st request doesn't work. When I print the ctx, the channel is None for the 1st request but isn't for the next ones. Then I have this error when I use : await ctx.send(...)

    Ignoring exception in on_socket_response
    Traceback (most recent call last):
      File "/opt/anaconda3/envs/project/lib/python3.9/site-packages/discord/client.py", line 343, in _run_event
        await coro(*args, **kwargs)
      File "/opt/anaconda3/envs/project/lib/python3.9/site-packages/dislash/slash_commands/slash_client.py", line 1050, in _on_socket_response
        await self._process_interaction(payload["d"])
      File "/opt/anaconda3/envs/project/lib/python3.9/site-packages/dislash/slash_commands/slash_client.py", line 1137, in _process_interaction
        raise err
      File "/opt/anaconda3/envs/project/lib/python3.9/site-packages/dislash/slash_commands/slash_client.py", line 1134, in _process_interaction
        await slash_parent.invoke(inter)
      File "opt/anaconda3/envs/project/lib/python3.9/site-packages/dislash/slash_commands/slash_core.py", line 342, in invoke
        raise err
      File "/opt/anaconda3/envs/project/lib/python3.9/site-packages/dislash/slash_commands/slash_core.py", line 338, in invoke
        await self._maybe_cog_call(self._cog, interaction, interaction.data)
      File "/opt/anaconda3/envs/project/lib/python3.9/site-packages/dislash/slash_commands/slash_core.py", line 131, in _maybe_cog_call
        return await self(inter, **params)
      File "/opt/anaconda3/envs/project/lib/python3.9/site-packages/dislash/slash_commands/slash_core.py", line 95, in __call__
        return await self.func(*args, **kwargs)
      File "project/src/main.py", line 473, in add_notif
        await msg.delete()
      File "/opt/anaconda3/envs/project/lib/python3.9/site-packages/discord/message.py", line 1023, in delete
        await self._state.http.delete_message(self.channel.id, self.id)
    AttributeError: 'NoneType' object has no attribute 'id'
    

    I tried with bot.command and it works

    @bot.command(
        name="add_notif"
    )
    

    But not when I use slash.command

    
    @slash.command(
        name="add_notif"
    )
    
    opened by YoanGab 6
Releases(v1.4.8)
Owner
I'm a student of Moscow State University, studying math. I love searching simple solutions of hard problems.
A really easy way to display your spotify listening status on spotify.

Spotify playing README A really easy way to display your spotify listening status on READMEs and Websites too! Demo Here's the embed from the site. Cu

Sunrit Jana 21 Nov 06, 2022
Template to create a telegram bot in python

Template for Telegram Bot Template to create a telegram bot in python. How to Run First add src to PYTHONPATH: export PYTHONPATH=${PWD} Then run: pyt

Ali Hejazizo 12 Dec 24, 2022
๐Ÿ” Google Search unofficial API for Python with no external dependencies

Python Google Search API Unofficial Google Search API for Python. It uses web scraping in the background and is compatible with both Python 2 and 3. W

Avi Aryan 204 Dec 28, 2022
A Simple Telegram Inline Torrent Search Bot by @AbirHasan2005

A Simple Telegram Inline Torrent Search Bot by @AbirHasan2005

Abir Hasan 61 Oct 28, 2022
Projeto com o objetivo de aprender o funcionamento de Consumo de APIs.

Consumindo API SuperHero Projeto com o objetivo de aprender o funcionamento de Consumo de APIs.

Deivisson Henrique 1 Dec 30, 2021
GitPython is a python library used to interact with Git repositories.

Gitoxide: A peek into the futureโ€ฆ I started working on GitPython in 2009, back in the days when Python was 'my thing' and I had great plans with it. O

3.8k Jan 03, 2023
Python bindings for BigML.io

BigML Python Bindings BigML makes machine learning easy by taking care of the details required to add data-driven decisions and predictive power to yo

BigML Inc, Machine Learning made easy 271 Dec 27, 2022
EpikCord.py - This is an API Wrapper for Discord's API for Python

EpikCord.py - This is an API Wrapper for Discord's API for Python! We've decided not to fork discord.py and start completely from scratch for a new, better structuring system!

EpikHost 28 Oct 10, 2022
Plataforma para atendimento a outras empresas que necessitam de atendimento tรฉcnico.

Plataforma para atendimento a outras empresas que necessitam de atendimento tรฉcnico. ร‰ possรญvel que os usuarios de empresas parceiras registrem solici

Kelvin Alisson Cantarino 2 Jun 29, 2022
Visualize size of directories, s3 buckets.

Dir Sizer This is a work in progress, right now consider this an Alpha or Proof of Concept level. dir_sizer is a utility to visualize the size of a di

Scott Seligman 13 Dec 08, 2022
An anime themed telegram bot that can convert telegram media.

ShoukoKomiRobot โ€ข ๐•Ž๐•ฃ๐•š๐•ฅ๐•ฅ๐•–๐•Ÿ ๐•€๐•Ÿ Python3 โ€ข ๐•ƒ๐•š๐•“๐•ฃ๐•’๐•ฃ๐•ช ๐•Œ๐•ค๐•–๐•• Pyrogram โ€ข ๐•Š๐• ๐•—๐•ฅ๐•จ๐•’๐•ฃ๐•– ๐•Œ๐•ค๐•–๐•• Ebook-convert Deploy ๐”ฝ๐• ๐•ฃ๐•œ ๐•ฅ๐•™๐•š๐•ค ๐•ฃ

25 Aug 14, 2022
A Python SDK for connecting devices to Microsoft Azure IoT services

V2 - We are now GA! This repository contains code for the Azure IoT SDKs for Python. This enables python developers to easily create IoT device soluti

Microsoft Azure 381 Dec 30, 2022
Actively maintained, pure Python wrapper for the Twitter API. Supports both normal and streaming Twitter APIs.

Twython Twython is a Python library providing an easy way to access Twitter data. Supports Python 3. It's been battle tested by companies, educational

Ryan McGrath 1.9k Jan 02, 2023
Shiny Wechat Pay SDK for Python

WeChat third-party Python SDK master: Read the Documentation Features Common public platforms passively respond and actively call APIs WeChat Pay API

Obrisk 18 Sep 05, 2022
light wrapper for indeed.com api

Simple wrapper for indeed api. go to indeed.com - register for api publisher token example from indeed import IndeedApi token = 'your token' api =

16 Sep 21, 2022
A smart tool to backup members ๐Ÿ“ˆ So you even after a raid/ ban you can easily restore them in seconds ๐ŸŽฒ

๐Ÿค‘ Discord-backer ๐Ÿค‘ A open-source Discord member backup and restore tool for your server. This can help you get all your members in 5 Seconds back af

John 29 Dec 21, 2022
music recommend chat bot

Your Song A chat bot who can recommend music for you. Project Documents https://drive.google.com/drive/folders/1zbHbuRyrUgMrO-LtDXrXwqycN_ysuAUx Dir I

4 Mar 27, 2022
Watches your earnings on EarnApp and notifies you when you earned balance or received an payout.

EarnApp-Earning-Monitor Watches your earnings on EarnApp and notifies you when you earned balance or received an payout. Installation Install Python3

Yariya 21 Oct 17, 2022
Bot inspirado no Baidu Antivรญrus

Baidu Bot Bot inspirado no lendรกrio Baidu Antivรญrus Informaรงรตes O programa foi inteiramente feito em Python, sinta-se livre para fazer qualquer altera

Caio Eduardo de Albuquerque Magalhรฃes 1 Dec 18, 2021
Async ShareX uploader written in python

Async ShareX uploader written in python

Jacob 2 Jan 07, 2022