A discord.py extension for sending, receiving and handling ui interactions in discord

Overview

discord-ui

A discord.py extension for using discord ui/interaction features
pip package โ–ช read the docs โ–ช examples

Downloads PyPI PyPI - Python Version Codacy Badge

Introduction

This is a discord.py ui extension made by 404kuso and RedstoneZockt for using discord's newest ui features like buttons, slash commands and context commands.

Documentation

Installation

Windows

py -m pip install discord-ui

Linux

python3 -m pip install discord-ui

License

This project is under MIT License

Issues

If you find any issues, please report them

https://github.com/discord-py-ui/discord-ui/issues

Note

If you want to use slash commands, in the oauth2 invite link generation, you have to check both bot and application.commands fields

Example

Example for creating a simple slash command

import discord
from discord.ext import commands
from discord_ui import UI, SlashOption

client = commands.Bot(" ")
ui = UI(client)

@ui.slash.command("hello_world", options=[SlashOption(bool, "cool", "whether this libary is cool", required=False)], guild_ids=[785567635802816595])
async def command(ctx, cool=True):
    """This is a simple slash command"""
    # you can use docstrings for the slash command description too
    await ctx.respond("You said this libary is " + str(cool))

client.run("your_token")

Example for creating a user-context command

import discord
from discord.ext import commands
from discurd_ui import UI

client = commands.Bot(" ")
ui = UI(client)

@ui.slash.user_command("avatar", guild_ids=[785567635802816595])
async def avatar(ctx, user: discord.Member):
    """Sends the avatar of a user"""
    await ctx.respond(embed=discord.Embed(description=user.display_name).set_image(url=user.avatar_url))

client.run("your_token")

Example for autocompletion of choices

import discord
from discord_ui import UI, SlashOption, AutocompleteInteraction

async def generator(ctx: AutocompleteInteraction):
    available_choices = ["hmm", "this", "is", "a", "an", "test", "testing"]
    return [(x, x) for x in available_choices if x.startswith(ctx.value_query)]

@ui.slash.command("search_word", options=[SlashOption(str, "query", choice_generator=generator)])
async def search_word(ctx, query):
    await ctx.send("got " + query + " for query")

client.run("your_token")

Example for sending a button and receiving it

import discord
from discord.ext import commands
from discord_ui import UI, LinkButton, Button

from asyncio import TimeoutError

client = commands.Bot(" ")
ui = UI(client)

@client.listen("on_message")
async def on_message(message: discord.Message):
    if message.content == "!btn":
        msg = await message.channel.send("you", components=[
            [Button("press me", color="green"), LinkButton("https://discord.com", emoji="๐Ÿ˜")],
            Button(custom_id="my_custom_id")
        ])
        try:
            btn = await msg.wait_for("button", client, by=message.author, timeout=20)
            await btn.respond("you pressed `" + btn.content + "`")
        except TimeoutError:
            await msg.delete()

client.run("your_token_here")

Example for sending Selectmenus and receiving them

import discord
from discord.ext import commands
from discord_ui import UI, SelectMenu, SelectOption

from asyncio import TimeoutError

client = commands.Bot(" ")
ui = UI(client)

@client.listen("on_message")
async def on_message(message: discord.Message):
    if message.content == "!sel":
        msg = await message.channel.send("you", components=[SelectMenu(options=[
            SelectOption("my_value", label="test", description="this is a test"),
            SelectOption("my_other_value", emoji="๐Ÿค—", description="this is a test too")
        ], "custom_id", max_values=2)])
        try:
            sel = await msg.wait_for("select", client, by=message.author, timeout=20)
            await sel.respond("you selected `" + str([x.content for x in sel.selected_options]) + "`")
        except TimeoutError:
            await msg.delete()

client.run("your_token_here")

Example for cogs

from discord.ext import commands
from discord_ui import UI
from discord_ui.cogs import slash_command, subslash_command, listening_component

bot = commands.Bot(" ")
ui = UI(bot)

class Example(commands.Cog):
    def __init__(self, bot):
        self.bot = bot
    
    @slash_command(name="example", guild_ids=[785567635802816595])
    async def example(self, ctx):
        await ctx.respond("gotchu")

    @subslash_command(base_names="example", name="command"):
    async def example_command(self, ctx):
        await ctx.respond("okayy")
    
bot.add_cog(Example(bot))
bot.run("your token")

You can find more (and better) examples here

Contact

You can contact us on discord

Changelog

This will be moved to https://discord-py-ui.github.io/discord-ui/

  • 5.1.2

    Fixed

    • commands.nuke
    • nextcord import issue (#112)
  • 5.1.0

    Breaking changes

    • Component custom ids are now optional, if no custom id is passed, a 100 characters long random string will be used and because of that the order of Component init params changed
    • The order of SelectMenus init params changed, custom_id comes now after options
    SelectMenu("my_custom_id", [options...here])
    # is now
    SelectMenu([options...here], "my_custom_id")
    • Same for Buttons
    Button("my_custom_id", "label")
    # is now
    Button("label", "my_custom_id")
    • ButtonStyles is now ButtonStyle
    • renamed cog decorators, the old ones still work but they will show a deprecation warning: slash_command -> slash_command, subslash_command -> subslash_command, context_cog -> context_command, listening_component -> listening_component
    • Removed Slash.edit_command and Slash.edit_subcommand, "moved" to Command.edit
    • SlashedCommand is now SlashInteraction, SlashedSubCommand is now SubSlashInteraction and SlashedContext is now ContextInteraction
    • The command attributes of CommandInteractions (SlashedCommand, ...) are now moved to Interaction.command. (the .command attribute is a reference to the real command, if you change properties of the command they will be updated)
    • The component attributes of an interaction are now moved to .component
    • ContextCommands .param attribute is now .target

    Changed

    • argument_type in SlashOption is now type
    • ButtonStyle value names changed: color names are now capitalized and Danger is now Destructive
    • Listener.target_user is now Listener.target_users and can take users, members and ids as the value
    • BaseCommand.options and SlashOption.options is now of type SlashOptionCollection, which allows you to acces options by index and name
    my_command.options["option name"]
    # or
    my_command.options[0]

    You can also use some methods like .get, .set (which will return itself after it set something, so SlashOption.set(key, value).set(key, value) would work) and SlashOption.options + SlashOption.option will add both SlashOptions together

    • If an invalid guild id was passed to a slashcommand, no exception will be raised anymore, it will just be printed into the console and ignored logging.error()
    • Moved the discord_ui.ext.py module into a folder
    • on_button_press and on_menu_select is now on_button and on_select. The old event names will still work but will be removed in the next release

    Fixed

    • disable_action_row
    • ActionRow.disable
    • no interaction events being dispatched because subclasses of dpy2 commands.Bot instances wouldn't get overriden which lead to not enabling needed debug events
    • when no matching component listener in Listener could be found, the events for components events wouldn't be dispatched
    • delete_after keyword in message send override not working
    • mentionable type in slashoptions not being parsed to objects
    • @discord.ext.commands.Cooldown not working on cog slashcommands

    Added

    • **fields to all functions that edit the message components (like .disable_components, .disable_component, ...). The **fields parameter can be used to edit other properties of the message without using .edit again and send a "useless" request
    • @Lister.on_error and @Listener.wrong_user decorators for handling Exceptions in Listeners
    • When no keyword was passed to @Listener.button or @Listener.select, the function will be called on every button/slect
    • channel_type to SlashOption, list of discord.ChannelType. This will restrict the shown channels for channel slash options to this list.
    • support for nextcord. Other libs should work too, but they are not tested.
    • Mentionable type for SlashOptions
    • description for short slashoptions. If you set the options for a slash command via callback params, you can add a description (and a type) to them with your docstring. There are 3 different styles you can use:
    # style 1
    @ui.slash.command()
    async def my_command(ctx, my_option, my_other_option):
        """This is my command description
    
        my_option: `int`:
            This is the description for the my_option parameter
        my_other_option: `str`:
            This is the description for another option
        """
        ...
    
    # style 2
    @ui.slash.command()
    async def my_command(ctx, my_option: int, my_other_option: str):
        """This is my command description
    
        my_option: This is the description for the my_option parameter
        my_other_option: This is the description for another option
        """
        ...
    
    # style 3
    @ui.slash.command()
    async def my_command(ctx, my_option, my_other_option: str):
        """This is my command description
    
    
        `int`: This is the description for the my_option parameter
    
        This is the description for another option
        """
        ...

    Note: You don't have to use `type`, you can just use type

    • Empty descriptions for slashcommands and slashoptions. The default description value is now \u200b which is an "empty" char
    • Modifying slashcommand options is now WWAAYYYY easier. You can just do .options[name or index].name = "new name" and the option will be updated
    • You can set the autocomplete choice generator with a decorator now
    ui.slash.command(options=[SlashOption(str, "my_option")])
    async def my_command(ctx, my_option):
        ...
    
    
    @my_command.options["my_option"].autocomplete_function
    async def my_generator(ctx):
        ...
    # or
    @my_command.options[0].autocomplete_function
    async def my_generator(ctx):
        ...
    • All apllication command decorators will now return the created Command
    @ui.slash.command(...)
    async my_command(ctx):
        ...
    type(my_command) # SlashCommand
    • Added edit and delete method to slashcommand. You can use this for editing or deleting the command later
    # edit
    await my_command.edit(name="test")
    # delete
    await my_command.delete()
    • id to SlashCommand
    • commands_synced event which will be dispatched when all commands where synced with the api (UI.Slash.sync_commands)
    • BaseCommmand.update method which updates the api command with the lcoal changes
    • SlashSubCommand.base, which will be shared among all subslashcommands with the same base

    Removed

    • discord.ext.commands.Bot override for enabling the debug event, this will be enabled when creating a UI instance from the bot
  • 5.0.1

    Fixed

    • Choices not working
  • 5.0.0

    Fixed

    • Roles not being parsed correctly

    Changed

    • default_permission

    default_permission can now be of type discord.Permissions but the api doesn't support that yet.

    • slash http

    some code changes to slash-http features

    Added

    • ChoiceGeneratorContext

    Context class for choice generation

    • SlashOption

    choice_generator keyword and autocomplete keyword. autocomplete is not needed if you pass choice_generator

    • File sending

    You are now able to send hidden files

  • 4.3.8

    Fixed

    • Issue with SlashOptions

    required is now false by default again

  • 4.3.7

    Changed

    • SlashOption

    Required is now True by default

    Fixed

    • AttributeError: 'LinkButton' object has no attribute 'component_type'

    Removed

    • decompressing

    The lib now doesn't decompress byte data anymore, which means everything before the dpy commit 848d752 doesn't work with this lib.

    message reference in discordpy discord server

  • 4.3.6

    Fixed

    • Slashcommand comparing
    • Ephemeralmessage keyerror exception
  • 4.3.5

    Fixed

    • send function issues
  • 4.3.4

    Fixed

    • SlashOption not accepting tuple
  • 4.3.3

    Fixed

    • fixed TypeError: 'NoneType' object is not iterable
  • 4.3.2

    Fixed

    • Could not find a matching option type for parameter ' '
  • 4.3.1

    Removed

    • unused parameter
  • 4.3.0

    Fixed

    • Message.wait_for

    by keyword doesn't work properly

    Removed

    • Hash

    Removed the hash property from Buttons and SelectMenus due to the removal of it from the api

    Added

    • discord_ui.ext

    A module with useful tools and decorators to use more information

    • BaseCommand

    BaseCommand (the superclass for all applicationcommands) has now some extra properties:

    - is_chat_input
    > Whether this command is a slash command
    
    - is_message_context
    > Whether this command is a message context command
    
    - is_user_context
    > Whether this command is a user context command
    
    • SlashedCommand

    Added properties:

    - is_alias
    > Whether the invoked command is an alias or not
    
    - aliases
    > All the available aliases for the command
    
    • Listeners

    Listeners are something that you can use for a better processing of received components. You could see them as a cog to the message components more information

    Changed

    • SelectInteraction

    SelectInteraction.selected_values are not the raw values that were selected, SelectMenu.selected_options are the options of type SlashOption that were selected

    • MISSING => None

    All instance values that were MISSING by default are now None

  • 4.2.15

    Fixed

    • #97
  • 4.2.14

    Fixed

    • small SelectOption issues
    • context commands

    Changed

    • allow context commands to have names with spaces
  • 4.2.13

    Fixed

    • TypeError: 'EMPTY' is not a callable object in context commands
  • 4.2.12

    Fixed

    • context commands
  • 4.2.11

    Fixed

    • cog context commands returned wrong type
  • 4.2.10

    Fixed

    • cog context commands typo with guild_permission keyword
  • 4.2.8

    Added

    • edit_subcomand

    Fixed

    • print statements

    Fixed

    • #94 (again ๐Ÿ’€ )
    • received subcommands

    The base_names and the name will be now set to the right value

  • 4.2.7

    Added

    • on_component

    There is now an event with the name component that will be dispatched whenever a component was received If you use Message.wait_for, there is now a new event choice with the name component (message.wait_for("component", client))

    Fixed

    • #94

    DM issue with deleting messages

    Changed

    • edit

    Edit now takes "content" as not positional (.edit("the content") works now)

    • component lenght

    You are now able to set component values with the right max lenght

  • 4.2.6

    Fixed

    • emebds

    there was an issue with sending embeds

  • 4.2.5

    Fixed

    • listening_components

    There was an issue with listening components that they needed two parameters but only one was passed Another issue was TypeError: __init__() missing 1 required positional argument: 'custom_id'?

    • emebds

    there was an issue with sending embeds

  • 4.2.2

    Changed

    • sync_commands

    the delete_unused keyword is now optional, if you don't pass a parameter, slash.delete_unused will be used (from the __init__ function)

  • 4.2.1

    Fixed

    • cannot import name 'InteractionResponseType' from 'discord.enums'
  • 4.2.0

    Added

    • cog_remove sync

    when you remove a cog the slash commands will now get deleted if you set delete_unused to True and set sync_on_cog to True

    • alternativ slash options

    you don't have to specify options in one of the slash decorators anymore. Instead, you can set them in your callback function Example

    @ui.slash.command()
    async def greet(ctx, user):                         # This will add an required option with the name "user" of type "user"
        """Greets a user
        
        You can use multiline docstrings, because only the first line will be used for the description
        """
        ...
    
    @ui.slash.command()
    async def tag(ctx, target: discord.User = None):    # This will add an optional option with the name "target" of type "user"
                                                        # Note: you could also use target: "user" = None or anything else you would use in SlashOption for the type
        ...

    Fixed

    • sync_commands

    if you would sync the commands after the first sync, it threw an error

  • 4.1.4

    Fixed

    • slashcommands in forbidden guilds

    when trying to get slash commands in a guild with no appication.commands permission, it won't throw an exepction anymore

  • 4.1.2

    Fixed

    • Subcommands editing

    subcommand checks were wrong and this would result in errors like In options.0.options.2: Option name 'name' is already used in these options

  • 4.1.1

    Fixed

    • Interaction.author.voice

    For some reason the voice property of the creator or the interaction would be set

    • Global slashcommands

    They wouldn't be registered to the api

  • 4.1.0

    Added

    • py 3.6 < support

    You should be able to use this package with python 3.6 or newer

    Fixed

    • print

    Forgot to remove print statements ๐Ÿ’€

  • 4.0.4

    Fixed

    • slashcommand

    when a user was passed in an option, its guild was always None

    • context commands

    if no name passed, the context command wouldn't take the callback name as the name of the command

  • 4.0.3

    Fixed

    • Message.wait_for
  • 4.0.2

    Fixed

    • Issue with receiving context commands
  • 4.0.1

    Fixed

    • discord.ext import error
  • 4.0.0

    Added

    You now have much more control over your slash commands!

    • Permissions

    You can update your permissions with the Slash.update_permissions function

    • Creating commands

    You can now create slash commands without the decorator in a much more eaisier way! Check out the Slash.add_command function

    • Edit commands

    You can edit commands in code with the Slash.edit_command function

    • Listening components

    You can add and remove listening components now with the Components.add_listening_component, Components.remove_listening_component and Components.remove_listening_components functions

    • Cogs

    You can now use cog decorators like slash_command, subslash_command and listening_component

    Fixed

    • SlashCommand

    Slash commands wouldn't be updated if only default_permission was changed

    Changed

    • wait_for

    Message.wait_for now takes by and check as parameters and event_name and client switched place (wait_for(client, "event_name") is now wait_for("event_name", client))

    • listening components

    You can specify listening_components now more presicely, you can add messages, users, and a check to filter

    • Interaction.member

    Interaction.member is now Interaction.author

    • listening comonents

    Listening component callback functions now only take one parameter, the used component

    • on_button_press and on_menu_select

    These events now take a sole parameter, the used component. If you want to acces to message, use passed_component.message

    Removed

    • ResponseMessage

    Removed ResponseMessage

  • 3.3.5

    Fixed

    • SelectMenu

    SelectMenu issue when creating it from data

  • 3.3.4

    Changed

    • edit

    Message.edit now takes a embed parameter

    Fixed

    • print

    Forgot to remove some print statements

  • 3.3.3

    Added

    • class representation

    classes have now a __repr__ function

    • UI(override_dpy)

    You can now choose whether you want to override some of dpy objects and functions (default is True) (see the override module for more information) This also appeals to the Components class (Components(override_dpy)) note: if you don't want to create a UI object, you can instead override dpy with the override_dpy method

    from discord_ui import override_dpy
    
    override_dpy()

    Fixed

    • dpy2

    discord.py v2 now auto-decompresses socket data and passes a string instead of the uncompressed data.

    • override dpy message

    when overriding dpy message object, the components would mix

  • 3.3.2

    Added

    • EphemeralResponseMessage

    You can now edit a ephemeral message which was created from an interaction (ex. when a button in a hidden message was pressed)

  • 3.3.1

    Added

    • interaction

    Interaction.channel and Interaction.guild

  • 3.3.0

    Fixed

    • interaction usage in dms
  • 3.2.9

    Added

    • ratelimit fix

    The lib will now retry after the ratelimit reset and doesn't throw an HTTPException anymore

    Fixed

    • sync_commands

    Got KeyError exception while syncing commands

  • 3.2.8

    Fixed

    • hidden responding

    When a hidden response was about to be send without defering the interaction it would thrown an error

  • 3.2.7

    Added

    • warnings
      • When a guild_permission with an invalid guild id is passed, it will throw an exception when syncing the commands
      • When the value of a guild_permission is not of type SlashPermission it will throw an exception
    • context-commands

    You can now have context commands with the same name as a normal slash command

    • slashcommand description

    You can use docstrings """docstring""" for setting the description of a slash commmand by setting the dosctring for the callback function

    Changed

    • auto_defer

    auto_defer is now disabled by default

    • slash sync

    You can now disable auto_sync for slash commmands and sync them by yourself with Slash.sync_commands(delete_unused)

    • Interacion.defer

    Interaction._deferred is not Interaction.deferred and Interaction.defer() doesn't throw an exception anymore, it will just log the error with logging.error()

    Fixed

    • try

    There was a try/catch in the Interaction.respond function that would allow the code to continue when an exception occured while responding with ninja_mode

    • context commands

    There was an issue adding context-commands

    • Command checking

    Now, the libary only edits commands when changes were made

  • 3.2.6

    Added

    • auto ninja_mode

    If you use .respond(), the function will try to use ninja_mode automatically

    Changed

    • project

    Moved git-project to https://github.com/discord-py-ui/discord-ui

    Fixed

    • ninja_mode response

    responding with ninja_mode would end up in an exception

    • file sending

    fixed another file sending issue with slash commands

  • 3.2.5

    Fixed

    • #89 (thanks for reporting)
  • 3.2.4
    • Fixed version issues with the package
  • 3.2.2

    Fixed

    • #85: AttributeError: module 'discord' has no attribute '_Components__version'
  • 3.2.0

    Fixed

    I'm really sorry for all the issues this libary got, if you still find issues, please report them in https://github.com/discord-py-ui/discord-ui/issues

    • SelectOpion

    There was an issue with emojis not being set in SelectOptions

    • LinkButton

    There was an issue with setting the url not being set

    • SlashCommands

    There was an issue with creating commands that don't already exist

    Changed

    • SelectInteraction

    .values is not .selected_values

    Added

    • Interaction

    Buttons and SelectMenus have a .message property for the message where their interaction was creted ResponseMessages have a .interaction property for the received interaction

    • Events

    We added a interaction_received event for all interactions that are received

  • 3.1.0

    Added

    • discordpy 2 support

    We added support for discord.py v2, so you can stay loyal to our libary and use it together with discord.py v2!

    • Exceptions

    Added own Exceptions for errors

    • ParseMethod

    You can change the way the extension parses interaction data. You can choose between different Methods

    • Auto-defer

    The libary will autodefer all interactions public. If you want to change that, take a look at the documentation for this feature

    • slashcommand edit check

    Slash commands will only be edited if there were some changes, so you won't get a invalid interaction error in discord after starting the bot If only permissions were changed, just the permissions will be edited and not the whole command like before

    Fixed

    • slash commands

    I finally fixed the damn slashcommand system, it should work now

    • Parsing

    The resolving, fetching and pulling from the cache methods should all work

  • 3.0.1

    Fixed

    • small project issues
  • 3.0.0

    Added

    • context commands

    Context commands are now available

    Changed

    • Project name

    The project's name was changed from discord-message-components to discord-ui

    • Extension is now UI
  • 2.1.0

    Added

    • Webhook support

    You are now able to use webhooks together with message components, to send a webhook message with the components, use the Components.send_webhook function. The standart webhook function is also overriden with the new component function

    • Float type

    You can now use float as the argument type for a slash command option

    • Auto empty names

    Buttons, LinkButtons and SelectOptions labels are now by default \u200b, which is an "empty" char

    Changed

    • Code documentation to more be more informative

    Fixed

    • Fixed small code issues (they were already fixed in previous versions, but I just wanna list this here)

    • Docs are now working

  • 2.0.2

    Fixed

    • SelectOption

    Select option threw an exception if it was smaller than 1 or higher than 100

  • 2.0.0

    Added

    • Slashcomamnd support

      • Slash class for slash commands
      • Slash.command, Slash.subcommand and Slash.subcommand_groups are available for creating slash commands
      • SlashedCommand and SlashedSubCommand are there for used slash commands
    • Message

      • disable_action_row(row_numbers: int | range, disable: bool)

      disables (enables) component row(s) in the message

      • disable_components(disable: bool)

      disables (enables) all componentss

    • overrides

      • Messageable.send returns Message instead of discord.Message and takes components parameter
      • override_client function added
    • interaction.send, creates followup messages which can be hidden

    • Component.listening_component

    A listening component with a callback function that will always be executed whenever a component with the specified custom_id was used

    Changed

    • Message

      • All Message objects don't use the client object anymore
      • Message.wait_for now needs the client as the first parameter

    Fixed

    • Interaction

    All interaction responses work now

    • A lot of issues I fogor ๐Ÿ’€
  • 1.2.2

    Fixed

    • Docs fixed
  • 1.2.1

    Fixed

    • Small code fixes
  • 1.2.0

    Added

  • 1.1.2

    Fixed

    • Small code fixes
  • 1.1.1

    Added

    • Message.edit()

      You can now edit messages with button support

  • 1.1.0

    Changed

    • Major changes to request code, now using the client's request
    • ResponseMessage.acknowledge() -> ResponseMessage.defer()

      Changed the name of the function + changed ResponseMessage.acknowledged -> ResponseMessage.deferred

    • ResponseMessage.defer() => await ResponseMessage.defer()

      defer (acknowledge) is now async and needs to be awaited

    Added

    • hidden responses

      You can now send responses only visible to the user

    Fixed

    • ResponseMessage.respond()

      Now doesn't show a failed interaction

  • 1.0.5

    Fixed

    • ResponseMessage.respond()

      responding now doesn't fail after sending the message, it will now defer the interaction by it self if not already deferred and then send the message

  • 1.0.4

    Added

    • ResponseMessage.acknowledged

      Whether the message was acknowledged with the ResponseMessage.acknowledged() function

    Changed

    • ResponseMessage.respond() => await ResponseMessage.respond()

      respond() function is now async and needs to be awaited

    • ResponseMessage.respond() -> None => ResponseMessage.respond() -> Message or None

      respond() now returns the sent message or None if ninja_mode is true

  • 1.0.3

    Added

    • Button.hash

      Buttons have now a custom hash property, generated by the discord api

Comments
  • ctx.author.send() gives a 404

    ctx.author.send() gives a 404 "Unknown Channel" error

    When using discord-ui, any attempt to perform an await ctx.author.send(...) results in the following error:

    File "/opt/homebrew/lib/python3.9/site-packages/discord_ui/override.py", line 50, in send
        r = await self._state.http.request(route, json=payload)
      File "/opt/homebrew/lib/python3.9/site-packages/discord/http.py", line 250, in request
        raise NotFound(r, data)
    discord.errors.NotFound: 404 Not Found (error code: 10003): Unknown Channel
    
    The above exception was the direct cause of the following exception:
    
    Traceback (most recent call last):
      File "/opt/homebrew/lib/python3.9/site-packages/discord/ext/commands/bot.py", line 939, in invoke
        await ctx.command.invoke(ctx)
      File "/opt/homebrew/lib/python3.9/site-packages/discord/ext/commands/core.py", line 863, in invoke
        await injected(*ctx.args, **ctx.kwargs)
      File "/opt/homebrew/lib/python3.9/site-packages/discord/ext/commands/core.py", line 94, in wrapped
        raise CommandInvokeError(exc) from exc
    discord.ext.commands.errors.CommandInvokeError: Command raised an exception: NotFound: 404 Not Found (error code: 10003): Unknown Channel
    

    Currently, I'm working around it by manually creating a DM channel, but it's an ugly kludge.

    bug 
    opened by tiltowait 7
  • Nextcord does not work with discord-ui

    Nextcord does not work with discord-ui

    Hey, I tried today to rewrite my Discord bot to Nextcord but somehow I can't because discord-ui requires discord.py and the lib of Discord-UI doesn't support Nextcord, is there any way to fix this?

    Before the question comes up, I am using discord-ui version 5.1.5

    opened by CraftDev222 5
  • discord_ui.Message.wait_for(

    discord_ui.Message.wait_for("select" ...) returns a ComponentContext, not SelectedMenu

    According to the docs, discord_ui.Message.wait_for("select", ...) returns a SelectedMenu item; however, in my testing, it returns a ComponentContext object. Importantly, the latter lacks a selected_values item; in order to access the selection, I have to use component.data["values"].

    This discrepancy also affects this line in the example code.

    bug 
    opened by tiltowait 4
  • Replies are broken

    Replies are broken

    Performing a simple await ctx.reply() does not actually reply. The message is sent without tying it to the appropriate message/context.

    The same is true for await ctx.message.reply().

    bug 
    opened by tiltowait 4
  • Lacking support for split files

    Lacking support for split files

    Motivation

    The official discord.py library supports loading extension commands from other files, so I think it is a good idea for discord_ui to have it as well. Otherwise, large bots can easily get to tens of thousands of lines in a single file.

    Reference code

    To put this conveniently, here is the bot.load_extension() method definition:

    # In the Bot class
    def load_extension(
            self,
            name: str,
            *,
            package: Optional[str] = None,
            extras: Optional[Dict[str, Any]] = None
        ) -> None:
                name = self._resolve_name(name, package)
                if name in self.__extensions:
                    raise errors.ExtensionAlreadyLoaded(name)
            
                spec = importlib.util.find_spec(name)
                if spec is None:
                    raise errors.ExtensionNotFound(name)
            
                self._load_from_module_spec(spec, name, extras=extras)
    
    opened by johann-lau 3
  • AttributeError when creating extension instance inside custom Bot class

    AttributeError when creating extension instance inside custom Bot class

    When creating the extension as part of a custom bot class, you get an AttributeError. I'm using Python 3.9.6, discord.py version 1.7.3 and discord-ui version 3.1.0.

    Traceback (most recent call last):
      File "main.py", line 10, in <module>
        bot = CustomBot(command_prefix="!")
      File "main.py", line 8, in __init__
        self.ui = UI(self)
      File "discord_ui/client.py", line 1038, in __init__
        self.components = Components(client, auto_defer=auto_defer)
      File "discord_ui/client.py", line 810, in __init__
        elif discord.__version.startswith("1"):
    AttributeError: module 'discord' has no attribute '_Components__version'
    

    (I removed unnecessary parts of the paths)

    Here's the code:

    from discord.ext import commands
    from discord_ui import *
    
    class CustomBot(commands.Bot):
        def __init__(self, **options):
            super().__init__(**options)
            self.ui = UI(self)
    
    bot = CustomBot(command_prefix="!")
    bot.run("token here")
    
    

    The documentation suggests that it has to be a commands.Bot, but I don't see how this would break it. Additionally, this only started happening once I updated to 3.1.0.

    bug 
    opened by Mabi19 3
  • Unable to remove embeds from a message

    Unable to remove embeds from a message

    Per the dpy docs, await msg.edit(embed=None) is supposed to remove an embed from a message. However, I receive the following error:

    Traceback (most recent call last):
      File "/opt/homebrew/lib/python3.9/site-packages/discord/client.py", line 343, in _run_event
        await coro(*args, **kwargs)
      File "/opt/homebrew/lib/python3.9/site-packages/discord_ui/client.py", line 257, in _on_response
        await x.invoke(context, **options)
      File "/opt/homebrew/lib/python3.9/site-packages/discord_ui/cogs.py", line 98, in invoke
        raise ex
      File "/opt/homebrew/lib/python3.9/site-packages/discord_ui/cogs.py", line 93, in invoke
        await self.callback(self.cog, ctx, *args, **kwargs)
      File "/Users/tiltowait/Developer/inconnu/interface/characters.py", line 104, in delete_character
        await inconnu.delete.prompt(ctx, character)
      File "/Users/tiltowait/Developer/inconnu/inconnu/delete.py", line 28, in prompt
        await msg.edit(embed=None)
      File "/opt/homebrew/lib/python3.9/site-packages/discord_ui/receive.py", line 668, in edit
        self._update(await self._state.http.request(r, json=jsonifyMessage(*args, **fields)))
      File "/opt/homebrew/lib/python3.9/site-packages/discord_ui/http.py", line 70, in jsonifyMessage
        raise WrongType("embeds", embeds, 'list[discord.Embed]')
    discord_ui.errors.WrongType: 'embeds' must be of type list[discord.Embed], not <class 'list'>
    

    Out of curiosity, I tried embeds=None but got a different error:

    Traceback (most recent call last):
      File "/opt/homebrew/lib/python3.9/site-packages/discord/client.py", line 343, in _run_event
        await coro(*args, **kwargs)
      File "/opt/homebrew/lib/python3.9/site-packages/discord_ui/client.py", line 257, in _on_response
        await x.invoke(context, **options)
      File "/opt/homebrew/lib/python3.9/site-packages/discord_ui/cogs.py", line 98, in invoke
        raise ex
      File "/opt/homebrew/lib/python3.9/site-packages/discord_ui/cogs.py", line 93, in invoke
        await self.callback(self.cog, ctx, *args, **kwargs)
      File "/Users/tiltowait/Developer/inconnu/interface/characters.py", line 104, in delete_character
        await inconnu.delete.prompt(ctx, character)
      File "/Users/tiltowait/Developer/inconnu/inconnu/delete.py", line 28, in prompt
        await msg.edit(embeds=None)
      File "/opt/homebrew/lib/python3.9/site-packages/discord_ui/receive.py", line 668, in edit
        self._update(await self._state.http.request(r, json=jsonifyMessage(*args, **fields)))
      File "/opt/homebrew/lib/python3.9/site-packages/discord_ui/http.py", line 69, in jsonifyMessage
        if not all(isinstance(x, discord.Embed) for x in embeds):
    TypeError: 'NoneType' object is not iterable
    
    bug 
    opened by tiltowait 2
  • Cannot send embeds in preview release

    Cannot send embeds in preview release

    Error message: discord.errors.HTTPException: 400 Bad Request (error code: 50006): Cannot send an empty message Posting here for the sake of organization.

    opened by brotherelric 1
  • Ninja mode gives 404 Not Found

    Ninja mode gives 404 Not Found

    Responding to a select menu interaction using ninja mode gives a 404 Not Found, with error code 10062 (Unknown interaction). I tested with sending a message, and it works. (I'm receiving the event through a @commands.Cog.listener("on_menu_select") decorated function, since I couldn't find a way to use the other ways with cogs; actually, better support for cogs would be great). Sorry for not providing an example, I'm in a hurry right now.

    bug 
    opened by Mabi19 1
  • Cannot send files alongside a message

    Cannot send files alongside a message

    When overridden, ctx.send does raises an exception if you pass in a file or files kwarg, while the regular discord.py ctx.send does not. After peeking at the source, it seems that the jsonifyMessage function wants the discord.Attachment class - which is the class for an attachment on an already existing message. It also tries to put it in the attachments field of the payload object, which the Discord API does not support (according to https://discord.com/developers/docs/resources/channel#create-message-jsonform-params)

    bug 
    opened by Mabi19 1
  • Guild command can only be used once

    Guild command can only be used once

    (Please point out any mistakes, if I get too confused.) I created a guild-only slash command, as follows:

    bs = Slash(bot)
    ...
    @bs.command(name= "test",
                description= "Foo bar", guild_ids= [880686520678371369],
                default_permission= False,
                guild_permissions= {880686520678371369: ui.SlashPermission(allowed= {ui.SlashPermission.USER: [687474789342117900]})}
    )
    async def tester(ctx):
        await ctx.respond("Test")
    # 687474789342117900 is my user ID
    

    I invoked this slash command. Immediately after that, the command gets removed from the list of other commands. All other commands continued to work, so I believe it is not a fatal bug. I tried looking into the module's code but I cannot find anything - I think it might be the bot wrongly deleting the command?

    opened by johann-lau 7
Releases(v5.1.6)
  • v5.1.6(Dec 19, 2021)

  • v5.1.5(Dec 12, 2021)

  • v5.1.4(Dec 12, 2021)

  • v5.1.3(Dec 12, 2021)

  • v5.1.2(Dec 10, 2021)

    https://pypi.org/project/discord-ui/5.1.2/

    Fixed

    • commands.nuke not working
    • nextcord import issues (#112 + some more)
    • command comparing: commands won't get edited anymore if there were no changes
    Source code(tar.gz)
    Source code(zip)
  • v5.1.1(Nov 27, 2021)

  • v5.1.0(Nov 27, 2021)

    https://pypi.org/project/discord-ui/5.1.0/

    Breaking changes

    • Component custom ids are now optional, if no custom id is passed, a 100 characters long random string will be used and because of that the order of Component init params changed
    • The order of SelectMenus init params changed, custom_id comes now after options
    SelectMenu("my_custom_id", [options...here])
    # is now
    SelectMenu([options...here], "my_custom_id")
    
    • Same for Buttons
    Button("my_custom_id", "label")
    # is now
    Button("label", "my_custom_id")
    
    • ButtonStyles is now ButtonStyle
    • renamed cog decorators, the old ones still work but they will show a deprecation warning: slash_command -> slash_command, subslash_command -> subslash_command, context_cog -> context_command, listening_component -> listening_component
    • Removed Slash.edit_command and Slash.edit_subcommand, "moved" to Command.edit
    • SlashedCommand is now SlashInteraction, SlashedSubCommand is now SubSlashInteraction and SlashedContext is now ContextInteraction
    • The command attributes of CommandInteractions (SlashedCommand, ...) are now moved to Interaction.command. (the .command attribute is a reference to the real command, if you change properties of the command they will be updated)
    • The component attributes of an interaction are now moved to .component
    • ContextCommands .param attribute is now .target

    Changed

    • argument_type in SlashOption is now type
    • ButtonStyle value names changed: color names are now capitalized and Danger is now Destructive
    • Listener.target_user is now Listener.target_users and can take users, members and ids as the value
    • BaseCommand.options and SlashOption.options is now of type SlashOptionCollection, which allows you to acces options by index and name
    my_command.options["option name"]
    # or
    my_command.options[0]
    

    You can also use some methods like .get, .set (which will return itself after it set something, so SlashOption.set(key, value).set(key, value) would work) and SlashOption.options + SlashOption.option will add both SlashOptions together

    • If an invalid guild id was passed to a slashcommand, no exception will be raised anymore, it will just be printed into the console and ignored logging.error()
    • Moved the discord_ui.ext.py module into a folder
    • on_button_press and on_menu_select is now on_button and on_select. The old event names will still work but will be removed in the next release

    Fixed

    • disable_action_row
    • ActionRow.disable
    • no interaction events being dispatched because subclasses of dpy2 commands.Bot instances wouldn't get overriden which lead to not enabling needed debug events
    • when no matching component listener in Listener could be found, the events for components events wouldn't be dispatched
    • delete_after keyword in message send override not working
    • mentionable type in slashoptions not being parsed to objects
    • @discord.ext.commands.Cooldown not working on cog slashcommands

    Added

    • **fields to all functions that edit the message components (like .disable_components, .disable_component, ...). The **fields parameter can be used to edit other properties of the message without using .edit again and send a "useless" request
    • @Lister.on_error and @Listener.wrong_user decorators for handling Exceptions in Listeners
    • When no keyword was passed to @Listener.button or @Listener.select, the function will be called on every button/slect
    • channel_type to SlashOption, list of discord.ChannelType. This will restrict the shown channels for channel slash options to this list.
    • support for nextcord. Other libs should work too, but they are not tested.
    • Mentionable type for SlashOptions
    • description for short slashoptions. If you set the options for a slash command via callback params, you can add a description (and a type) to them with your docstring. There are 3 different styles you can use:
    # style 1
    @ui.slash.command()
    async def my_command(ctx, my_option, my_other_option):
        """This is my command description
    
        my_option: `int`:
            This is the description for the my_option parameter
        my_other_option: `str`:
            This is the description for another option
        """
        ...
    
    # style 2
    @ui.slash.command()
    async def my_command(ctx, my_option: int, my_other_option: str):
        """This is my command description
    
        my_option: This is the description for the my_option parameter
        my_other_option: This is the description for another option
        """
        ...
    
    # style 3
    @ui.slash.command()
    async def my_command(ctx, my_option, my_other_option: str):
        """This is my command description
    
    
        `int`: This is the description for the my_option parameter
    
        This is the description for another option
        """
        ...
    

    Note: You don't have to use `type`, you can just use type

    • Empty descriptions for slashcommands and slashoptions. The default description value is now \u200b which is an "empty" char
    • Modifying slashcommand options is now WWAAYYYY easier. You can just do .options[name or index].name = "new name" and the option will be updated
    • You can set the autocomplete choice generator with a decorator now
    ui.slash.command(options=[SlashOption(str, "my_option")])
    async def my_command(ctx, my_option):
        ...
    
    
    @my_command.options["my_option"].autocomplete_function
    async def my_generator(ctx):
        ...
    # or
    @my_command.options[0].autocomplete_function
    async def my_generator(ctx):
        ...
    
    • All apllication command decorators will now return the created Command
    @ui.slash.command(...)
    async my_command(ctx):
        ...
    type(my_command) # SlashCommand
    
    • Added edit and delete method to slashcommand. You can use this for editing or deleting the command later
    # edit
    await my_command.edit(name="test")
    # delete
    await my_command.delete()
    
    • id to SlashCommand
    • commands_synced event which will be dispatched when all commands where synced with the api (UI.Slash.sync_commands)
    • BaseCommmand.update method which updates the api command with the lcoal changes
    • SlashSubCommand.base, which will be shared among all subslashcommands with the same base
    Source code(tar.gz)
    Source code(zip)
  • v5.0.2(Sep 25, 2021)

  • v5.0.1(Sep 23, 2021)

  • v5.0.0(Sep 23, 2021)

    https://pypi.org/project/discord-ui/5.0.0

    Fixed

    • Roles not being parsed correctly

    Changed

    • default_permission

    default_permission can now be of type discord.Permissions but the api doesn't support that yet. Documentation reference.

    • slash http

    some code changes to slash-http features

    Added

    • ChoiceGeneratorContext

    Context class for choice generation

    • SlashOption

    choice_generator keyword and autocomplete keyword. autocomplete is not needed if you pass choice_generator

    Note that the autocompletion is currently limited to desktop clients

    • File sending

    You are now able to send hidden files

    Note

    Some of the features mentioned above are not finished in the api yet, so there can occur some issues
    
    Source code(tar.gz)
    Source code(zip)
  • v4.3.8(Sep 15, 2021)

  • v4.3.7(Sep 15, 2021)

    https://pypi.org/project/discord-ui/4.3.7/

    Changed

    • SlashOption

    Required is now True by default

    Fixed

    • AttributeError: 'LinkButton' object has no attribute 'component_type'

    Removed

    • decompressing

    The lib now doesn't decompress byte data anymore, which means everything before the dpy commit 848d752 doesn't work with this lib. This is removed because the on_socket_raw event which was needed in order to receive interaction now returns the message with the type str, not bytes anymore which had to be decompressed. There were some problems with decompressing and that's why we removed it

    message reference to the change in the discord.py discord server

    Source code(tar.gz)
    Source code(zip)
  • v4.3.6(Sep 12, 2021)

  • v4.3.5(Sep 12, 2021)

  • v4.3.4(Sep 11, 2021)

  • v4.3.3(Sep 11, 2021)

  • v4.3.2(Sep 11, 2021)

  • v4.3.1(Sep 10, 2021)

  • v4.3(Sep 10, 2021)

    https://pypi.org/project/discord-ui/4.3.0/

    Fixed

    • Message.wait_for

    by keyword doesn't work properly

    Removed

    • Hash

    Removed the hash property from Buttons and SelectMenus due to the removal of it from the api

    Added

    • discord_ui.ext

    A module with usefull tools and decorators to use more information

    • BaseCommand

    BaseCommand (the superclass for all applicationcommands) has now some extra properties:

    - is_chat_input
    > Whether this command is a slash command
    
    - is_message_context
    > Whether this command is a message context command
    
    - is_user_context
    > Whether this command is a user context command
    
    • SlashedCommand

    Added properties:

    - is_alias
    > Whether the invoked command is an alias or not
    
    - aliases
    > All the available aliases for the command
    
    • Listeners

    Listeners are something that you can use for a better processing of received components. You could see them as a cog to the message components more information

    Changed

    • SelectedMenu

    SelectedMenu.selected_values are not the raw values that were selected, SelectMenu.selected_options are the options of type SlashOption that were selected

    • MISSING => None

    All instance values that were MISSING by default are now None

    Source code(tar.gz)
    Source code(zip)
  • v4.2.15(Sep 8, 2021)

  • v4.2.14(Sep 5, 2021)

    https://pypi.org/project/discord-ui/4.2.14

    Fixed

    • #96, thx for reporting
    • context commands not working properly

    Added

    • context commands can now take spaces in their names
    Source code(tar.gz)
    Source code(zip)
  • v4.2.13(Sep 5, 2021)

  • v4.2.12(Sep 5, 2021)

  • v4.2.11(Sep 5, 2021)

  • v4.2.10(Sep 5, 2021)

  • v4.2.9(Sep 4, 2021)

  • v4.2.8(Sep 4, 2021)

    https://pypi.org/project/discord-ui/4.2.8

    Fixed

    • #94 (again ๐Ÿ’€)
    • received subcommands

    The base_names and the name will be now set to the right value

    Source code(tar.gz)
    Source code(zip)
  • v4.2.7(Sep 4, 2021)

    https://pypi.org/project/discord-ui/4.2.7

    Added

    • on_component

    There is now an event with the name component that will be dispatched whenever a component was received If you use Message.wait_for, there is now a new event choice with the name component (message.wait_for("component", client))

    Fixed

    • #94

    DM issue with components

    Changed

    • edit

    Edit now takes "content" as not positional (.edit("the content") works now)

    • component lenght

    You are now able to set component values with the right max lenght

    Source code(tar.gz)
    Source code(zip)
  • v4.2.6(Sep 4, 2021)

  • v4.2.5(Sep 4, 2021)

    https://pypi.org/project/discord-ui/4.2.5

    Fixed

    • listening_components

    There was an issue with listening components that they needed two parameters but only one was passed Another issue was TypeError: __init__() missing 1 required positional argument: 'custom_id'?

    • emebds

    there was an issue with sending embeds

    Source code(tar.gz)
    Source code(zip)
A small Python app to create Notion pages from Jira issues

Jira to Notion This little program will capture a Jira issue and create a corresponding Notion subpage. Mac users can fetch the current issue from the

Dr. Kerem Koseoglu 12 Oct 27, 2022
A simple telegram bot to recognize lengthy voice files to text and vice versa with multiple language support.

Voicebot A simple Telegram bot to convert lengthy voice clips to text and vice versa with supporting languages. Mandatory Variables API_HASH - Yo

Renjith Mangal 12 Oct 21, 2022
๐Ÿ“ท An Instagram bot written in Python using Selenium on Google Chrome

๐Ÿ“ท An Instagram bot written in Python using Selenium on Google Chrome. It will go through posts in hashtag(s) and like and comment on them.

anniedotexe 47 Dec 19, 2022
Build better AWS infrastructure

Sceptre About Sceptre is a tool to drive AWS CloudFormation. It automates the mundane, repetitive and error-prone tasks, enabling you to concentrate o

sceptre 1.4k Jan 04, 2023
Scratch2py or S2py is a easy to use, versatile tool to communicate with the Scratch API Based of Scratch2py

Scratch2py Scratch2py or S2py is a easy to use, versatile tool to communicate with the Scratch API Based of Scratch2py Installation Run this command i

2 Jan 13, 2022
A simple bot that lives in your Telegram group, logging messages to a Postgresql database and serving statistical tables and plots to users as Telegram messages.

telegram-stats-bot Telegram-stats-bot is a simple bot that lives in your Telegram group, logging messages to a Postgresql database and serving statist

22 Dec 26, 2022
Simple python program to execute terminal commands on telegram chats directly.

Small python code which can be handy when using telegram and you don't want to use VPS again and again. By configuring the code in your VPS, You can execute commands and get your output within telegr

Veshraj Ghimire 34 Dec 05, 2022
Bot Maker For Discord - Python Edition

BMFD-PE Bot Maker For Discord - Python Edition BMFD-PE is a new version of BMFD write in Python The Version of BMFD-PE is : alpha0.1 Longer support :

Tรฉo 2 Dec 22, 2021
Fortnite Dumper for anyone's Save the World profiles.

Anyone's Fortnite Save the World Profile Dumper This program allows you to dump anyone's Fortnite Save the World Profiles. How to use it? After starti

PRO100KatYT 6 Apr 13, 2022
Simple Telegram webscrap bot

webscrap-bot Simple Telegram webscrap bot Configs TOKEN - Get bot token from @BotFather API_ID - From my.telegram.org API_HASH - From my.telegram.org

lokaman chendekar 10 Oct 21, 2022
Create light scenes , voice control, ifttt, fuzzywuzzy speech correction and much more with Tuya light bulbs.

LightBox Features: Auto discover tuya lights Set and create moods (aka: light profiles) Change moods via IFTTT List moods via IFTTT FuzzyWuzzy, speech

Robert Nagtegaal 1 Dec 20, 2021
An anime themed telegram bot that can convert telegram media.

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

25 Aug 14, 2022
A generative art library for NFT avatar and collectible projects.

Generative NFT Art Introduction The generative-art-nft repository is a library for creating generative art. It was developed for the purpose of creati

Rounak Banik 657 Jan 02, 2023
Stack overflow search API

Stack overflow search API

Vikash Karodiya 1 Nov 15, 2021
LoL API is a Python application made to serve League of Legends data.

LoL API is a Python application made to serve League of Legends data.

Caique Cunha Pereira 1 Nov 06, 2021
Token Manager written in Python

Discord-API-Token-Entrance Description This is a Token Manager that allows your token to enter your discord server, written in python. Packages Requir

Tootle 1 Apr 15, 2022
tfquery: Run SQL queries on your Terraform infrastructure. Query resources and analyze its configuration using a SQL-powered framework.

๐ŸŒฉ๏ธ tfquery ๐ŸŒฉ๏ธ Run SQL queries on your Terraform infrastructure. Ask questions that are hard to answer ๐Ÿš€ What is tfquery? tfquery is a framework tha

Mazin Ahmed 311 Dec 21, 2022
Easy & powerful bot to check if your all Telegram bots are working or not. This bot status bot updates every 45 minutes & runs for 24x7 hours.

PowerfulBotStatus-IDN-C-X Easy & powerful bot to check if your all Telegram bots are working or not. This bot status bot updates every 45 minutes & ru

IDNCoderX 5 Oct 06, 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
Telegram bot that let's you flip a coin in a dialog

coin_flip Telegram bot that let's you flip a coin in a dialog Report issue ยท Request feature About Software development tool that lets you finally dec

Ivan Akostelov 2 Dec 12, 2021