From d60d73ebfdff51fd8068b8b23ef4f265fabef152 Mon Sep 17 00:00:00 2001 From: davfsa Date: Sun, 26 Sep 2021 09:33:29 +0200 Subject: [PATCH 1/5] Add new channel_types field to CommandOption --- hikari/commands.py | 6 ++++++ hikari/impl/entity_factory.py | 10 ++++++---- hikari/messages.py | 4 ++-- 3 files changed, 14 insertions(+), 6 deletions(-) diff --git a/hikari/commands.py b/hikari/commands.py index cc42d5003b..fff06c3adb 100644 --- a/hikari/commands.py +++ b/hikari/commands.py @@ -44,6 +44,7 @@ from hikari.internal import enums if typing.TYPE_CHECKING: + from hikari import channels from hikari import guilds @@ -136,6 +137,11 @@ class CommandOption: options: typing.Optional[typing.Sequence[CommandOption]] = attr.field(default=None, repr=False) """Sequence of up to (and including) 25 of the options for this command option.""" + channel_types: typing.Optional[typing.Sequence[typing.Union[channels.ChannelType, int]]] = attr.field( + default=None, repr=False + ) + """If a channel type option, the valid channel types that this option will accept.""" + @attr_extensions.with_copy @attr.define(hash=True, kw_only=True, weakref_slot=False) diff --git a/hikari/impl/entity_factory.py b/hikari/impl/entity_factory.py index d464b9999f..7cdb729566 100644 --- a/hikari/impl/entity_factory.py +++ b/hikari/impl/entity_factory.py @@ -1742,16 +1742,17 @@ def _deserialize_interaction_command_option( if raw_suboptions := payload.get("options"): suboptions = [self._deserialize_interaction_command_option(suboption) for suboption in raw_suboptions] + channel_types: typing.Optional[typing.Sequence[typing.Union[channel_models.ChannelType, int]]] = None + if raw_channel_types := payload.get("channel_types"): + channel_types = [channel_models.ChannelType(channel_type) for channel_type in raw_channel_types] + option_type = commands.OptionType(payload["type"]) value = payload.get("value") if modifier := _interaction_option_type_mapping.get(option_type): value = modifier(value) return command_interactions.CommandInteractionOption( - name=payload["name"], - type=option_type, - value=value, - options=suboptions, + name=payload["name"], type=option_type, value=value, options=suboptions, channel_types=channel_types ) def _deserialize_interaction_member( @@ -1887,6 +1888,7 @@ def serialize_command_option(self, option: commands.CommandOption) -> data_bindi "name": option.name, "description": option.description, "required": option.is_required, + "channel_types": option.channel_types, } if option.choices is not None: diff --git a/hikari/messages.py b/hikari/messages.py index d79523acf1..4bc194c36d 100644 --- a/hikari/messages.py +++ b/hikari/messages.py @@ -608,7 +608,7 @@ class ButtonComponent(PartialComponent): """Custom or unicode emoji which appears on the button.""" custom_id: typing.Optional[str] = attr.field(hash=True) - """Developer defined identifier for this button (will be >= 100 characters). + """Developer defined identifier for this button (will be <= 100 characters). !!! note This is required for the following button styles: @@ -656,7 +656,7 @@ class SelectMenuComponent(PartialComponent): """ custom_id: str = attr.field(hash=True) - """Developer defined identifier for this menu (will be >= 100 characters).""" + """Developer defined identifier for this menu (will be <= 100 characters).""" options: typing.Sequence[SelectMenuOption] = attr.field(eq=False) """Sequence of up to 25 of the options set for this menu.""" From c3adeea85f0a73619c155d838c38505495276e90 Mon Sep 17 00:00:00 2001 From: davfsa Date: Sun, 26 Sep 2021 09:52:19 +0200 Subject: [PATCH 2/5] Add changelog fragment --- CHANGELOG.md | 2 +- changes/800.feature.md | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) create mode 100644 changes/800.feature.md diff --git a/CHANGELOG.md b/CHANGELOG.md index 7ca446e162..f7dbc841dd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -48,7 +48,7 @@ Bugfixes - `is_webhook` will now return `undefined.UNDEFINED` if the information is not available - Fix logic in `is_human` to account for the changes in the typing - Set `PartialMessage.member` to `undefined.UNDEFINED` when Discord edit the message to display an embed/attachment ([#783](https://github.com/hikari-py/hikari/issues/783)) -- `CommandOption.value` will now be cast to a `Snowflake` for types 6-9 ([#785](https://github.com/hikari-py/hikari/issues/785)) +- `CommandInteractionOption.value` will now be cast to a `Snowflake` for types 6-9 ([#785](https://github.com/hikari-py/hikari/issues/785)) Improved Documentation diff --git a/changes/800.feature.md b/changes/800.feature.md new file mode 100644 index 0000000000..7adf3e8ef7 --- /dev/null +++ b/changes/800.feature.md @@ -0,0 +1 @@ +Support new `channel_types` field in `CommandOption` From a6cad488d7fba095359b4748d000e0e66f85a6e2 Mon Sep 17 00:00:00 2001 From: davfsa Date: Sun, 26 Sep 2021 10:04:25 +0200 Subject: [PATCH 3/5] Add tests --- hikari/impl/entity_factory.py | 18 ++++++++++++------ tests/hikari/impl/test_entity_factory.py | 19 +++++++++++++++++++ 2 files changed, 31 insertions(+), 6 deletions(-) diff --git a/hikari/impl/entity_factory.py b/hikari/impl/entity_factory.py index 7cdb729566..e5fb70079f 100644 --- a/hikari/impl/entity_factory.py +++ b/hikari/impl/entity_factory.py @@ -1669,6 +1669,10 @@ def _deserialize_command_option(self, payload: data_binding.JSONObject) -> comma if raw_options := payload.get("options"): suboptions = [self._deserialize_command_option(option) for option in raw_options] + channel_types: typing.Optional[typing.Sequence[typing.Union[channel_models.ChannelType, int]]] = None + if raw_channel_types := payload.get("channel_types"): + channel_types = [channel_models.ChannelType(channel_type) for channel_type in raw_channel_types] + return commands.CommandOption( type=commands.OptionType(payload["type"]), name=payload["name"], @@ -1676,6 +1680,7 @@ def _deserialize_command_option(self, payload: data_binding.JSONObject) -> comma is_required=payload.get("required", False), choices=choices, options=suboptions, + channel_types=channel_types, ) def deserialize_command( @@ -1742,17 +1747,16 @@ def _deserialize_interaction_command_option( if raw_suboptions := payload.get("options"): suboptions = [self._deserialize_interaction_command_option(suboption) for suboption in raw_suboptions] - channel_types: typing.Optional[typing.Sequence[typing.Union[channel_models.ChannelType, int]]] = None - if raw_channel_types := payload.get("channel_types"): - channel_types = [channel_models.ChannelType(channel_type) for channel_type in raw_channel_types] - option_type = commands.OptionType(payload["type"]) value = payload.get("value") if modifier := _interaction_option_type_mapping.get(option_type): value = modifier(value) return command_interactions.CommandInteractionOption( - name=payload["name"], type=option_type, value=value, options=suboptions, channel_types=channel_types + name=payload["name"], + type=option_type, + value=value, + options=suboptions, ) def _deserialize_interaction_member( @@ -1888,9 +1892,11 @@ def serialize_command_option(self, option: commands.CommandOption) -> data_bindi "name": option.name, "description": option.description, "required": option.is_required, - "channel_types": option.channel_types, } + if option.channel_types is not None: + payload["channel_types"] = option.channel_types + if option.choices is not None: payload["choices"] = [{"name": choice.name, "value": choice.value} for choice in option.choices] diff --git a/tests/hikari/impl/test_entity_factory.py b/tests/hikari/impl/test_entity_factory.py index 90dcc97c9c..5b47d35682 100644 --- a/tests/hikari/impl/test_entity_factory.py +++ b/tests/hikari/impl/test_entity_factory.py @@ -3091,6 +3091,25 @@ def test_deserialize_interaction_handles_unknown_type(self, entity_factory_impl) with pytest.raises(errors.UnrecognisedEntityError): entity_factory_impl.deserialize_interaction({"type": -999}) + def test_serialize_command_option_with_channel_type(self, entity_factory_impl): + option = commands.CommandOption( + type=commands.OptionType.INTEGER, + name="a name", + description="go away", + is_required=True, + channel_types=[channel_models.ChannelType.GUILD_STAGE, channel_models.ChannelType.GUILD_TEXT, 100], + ) + + result = entity_factory_impl.serialize_command_option(option) + + assert result == { + "type": 4, + "name": "a name", + "description": "go away", + "required": True, + "channel_types": [13, 0, 100], + } + def test_serialize_command_option_with_choices(self, entity_factory_impl): option = commands.CommandOption( type=commands.OptionType.INTEGER, From 2e6fa7704816fd31331c453284c12918f2a01577 Mon Sep 17 00:00:00 2001 From: davfsa Date: Sun, 26 Sep 2021 17:27:40 +0200 Subject: [PATCH 4/5] Fix wording in docstring Co-authored-by: Lucina --- hikari/commands.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hikari/commands.py b/hikari/commands.py index fff06c3adb..e83242f5f1 100644 --- a/hikari/commands.py +++ b/hikari/commands.py @@ -140,7 +140,7 @@ class CommandOption: channel_types: typing.Optional[typing.Sequence[typing.Union[channels.ChannelType, int]]] = attr.field( default=None, repr=False ) - """If a channel type option, the valid channel types that this option will accept.""" + """If a channel type option, the channel types that this option will accept.""" @attr_extensions.with_copy From 535f9f31b8eb99d67eb20f2fa608bf96ff863b5b Mon Sep 17 00:00:00 2001 From: davfsa Date: Wed, 29 Sep 2021 14:18:48 +0200 Subject: [PATCH 5/5] Document `None` channel_types will allow all types --- hikari/commands.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/hikari/commands.py b/hikari/commands.py index e83242f5f1..b0f2f32677 100644 --- a/hikari/commands.py +++ b/hikari/commands.py @@ -140,7 +140,10 @@ class CommandOption: channel_types: typing.Optional[typing.Sequence[typing.Union[channels.ChannelType, int]]] = attr.field( default=None, repr=False ) - """If a channel type option, the channel types that this option will accept.""" + """The channel types that this option will accept. + + If `builtins.None`, then all channel types will be accepted. + """ @attr_extensions.with_copy