Passed
Pull Request — main (#297)
by
unknown
01:50
created

pincer.objects.app.command   A

Complexity

Total Complexity 10

Size/Duplication

Total Lines 219
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
wmc 10
eloc 86
dl 0
loc 219
rs 10
c 0
b 0
f 0

5 Methods

Rating   Name   Duplication   Size   Complexity  
A AppCommand.__hash__() 0 2 1
A AppCommand.add_option() 0 12 2
A AppCommand.__post_init__() 0 5 3
A AppCommandOptionChoice.__post_init__() 0 3 1
A AppCommand.__eq__() 0 25 3
1
# Copyright Pincer 2021-Present
0 ignored issues
show
introduced by
Missing module docstring
Loading history...
2
# Full MIT License can be found in `LICENSE` at the project root.
3
4
from __future__ import annotations
5
6
from dataclasses import dataclass
7
from typing import List, Union, TYPE_CHECKING
8
9
10
from ...commands.groups import Group, Subgroup
11
from .command_types import AppCommandOptionType, AppCommandType
12
from ...objects.guild.channel import ChannelType
13
from ...utils.api_object import APIObject, GuildProperty
14
from ...utils.snowflake import Snowflake
15
from ...utils.types import Coro, choice_value_types
16
from ...utils.types import MISSING
17
18
if TYPE_CHECKING:
19
    from ...utils.types import APINullable
20
    from ..app.throttle_scope import ThrottleScope
21
22
23
@dataclass(repr=False)
24
class AppCommandInteractionDataOption(APIObject):
25
    """Represents a Discord Application Command Interaction Data Option
26
27
    Attributes
28
    ----------
29
    name: :class:`str`
30
        The name of the parameter
31
    value: :class:`str`
32
        The value of the pair
33
    type: APINullable[:class:`str`]
34
        Value of application command option type
35
    options: APINullable[List[:data:`~pincer.objects.app.command.AppCommandInteractionDataOption`]]
36
        Present if this option is a group or subcommand
37
    """
38
    # noqa: E501
39
    name: str
40
    value: APINullable[str] = MISSING
41
    type: APINullable[AppCommandOptionType] = MISSING
42
    options: APINullable[
43
        List[AppCommandInteractionDataOption]] = MISSING
44
45
46
@dataclass(repr=False)
47
class AppCommandOptionChoice(APIObject):
48
    """Represents a Discord Application Command Option Choice object
49
50
    Attributes
51
    ----------
52
    name: :class:`str`
53
        1-100 character choice name
54
    value: Union[:data:`~pincer.utils.types.choice_value_types`]
55
        Value of the choice, up to 100 characters if string
56
    """
57
    name: str
58
    value: choice_value_types
59
60
    def __post_init__(self):
61
        # APIObject __post_init_ causes issues by converting `value` to a string
62
        self.name = str(self.name)
63
64
65
@dataclass(repr=False)
66
class AppCommandOption(APIObject):
0 ignored issues
show
best-practice introduced by
Too many instance attributes (10/7)
Loading history...
67
    """Represents a Discord Application Command Option object
68
69
    Attributes
70
    ----------
71
    type: :class:`~pincer.objects.AppCommandOptionType`
72
        The type of option
73
    name: :class:`str`
74
        1-32 lowercase character name matching `^[\\w-]{1,32}$`
75
    description: :class:`str`
76
        1-100 character description
77
    required: APINullable[:class:`bool`]
78
        If the parameter is required or optional |default| :data:`False`
79
    choices: APINullable[List[:class:`~pincer.objects.app.command.AppCommandOptionChoice`]]
80
        Choices for ``STRING``, ``INTEGER``, and ``NUMBER``
81
        types for the user to pick from, max 25
82
    options: APINullable[List[:class:`~pincer.objects.app.command.AppCommandOptionChoice`]]
83
        If the option is a subcommand or subcommand group type,
84
        this nested options will be the parameters
85
    """
86
    # noqa: E501
87
    type: AppCommandOptionType
88
    name: str
89
    description: str
90
91
    required: bool = False
92
    autocomplete: APINullable[bool] = MISSING
93
    choices: APINullable[List[AppCommandOptionChoice]] = MISSING
94
    options: APINullable[List[AppCommandOption]] = MISSING
95
    channel_types: APINullable[List[ChannelType]] = MISSING
96
    min_value: APINullable[Union[int, float]] = MISSING
97
    max_value: APINullable[Union[int, float]] = MISSING
98
99
100
@dataclass(repr=False)
101
class AppCommand(APIObject, GuildProperty):
0 ignored issues
show
best-practice introduced by
Too many instance attributes (11/7)
Loading history...
102
    """Represents a Discord Application Command object
103
104
    Attributes
105
    ----------
106
    type: :class:`~pincer.objects.app.command.AppCommandType`
107
        The type of command, defaults ``1`` if not set
108
    name: :class:`str`
109
        1-32 character name
110
    description: :class:`str`
111
        1-100 character description for ``CHAT_INPUT`` commands,
112
        empty string for ``USER`` and ``MESSAGE`` commands
113
    id: APINullable[:class:`~pincer.utils.snowflake.Snowflake`]
114
        Unique id of the command
115
    version: APINullable[:class:`~pincer.utils.snowflake.Snowflake`]
116
        Auto-incrementing version identifier updated during substantial
117
        record changes
118
    application_id: APINullable[:class:`~pincer.utils.snowflake.Snowflake`]
119
        Unique id of the parent application
120
    options: APINullable[List[:class:`~pincer.objects.app.command.AppCommandOption`]]
121
        The parameters for the command, max 25
122
    guild_id: APINullable[:class:`~pincer.utils.snowflake.Snowflake`]
123
        Guild id of the command, if not global
124
    default_permission: APINullable[:class:`bool`]
125
        Whether the command is enabled by default
126
        when the app is added to a guild
127
    """
128
    # noqa: E501
129
    type: AppCommandType
130
    name: str
131
    description: str
132
133
    id: APINullable[Snowflake] = MISSING
134
    version: APINullable[Snowflake] = MISSING
135
    application_id: APINullable[Snowflake] = MISSING
136
    options: APINullable[List[AppCommandOption]] = MISSING
137
    guild_id: APINullable[Snowflake] = MISSING
138
    default_permission: APINullable[bool] = True
139
    default_member_permissions: APINullable[None] = None
140
    dm_permission: APINullable[None] = None
141
142
    def __post_init__(self):
143
        super().__post_init__()
144
145
        if self.options is MISSING and self.type is AppCommandType.MESSAGE:
146
            self.options = []
147
148
    def __eq__(self, other: object) -> bool:
149
        if isinstance(other, ClientCommandStructure):
150
            other = other.app
151
152
        if not isinstance(other, AppCommand):
153
            return False
154
155
156
        # `description` and `options` are tested for equality with a custom check
157
        eq_props = (
158
            "type", "name", "guild_id", "default_permission", "options"
159
        )
160
161
        eq = (
162
            self.__getattribute__(prop) == other.__getattribute__(prop)
163
            for prop in eq_props
164
        )
165
166
        return all(
167
            (
168
                *eq,
169
                self.description == other.description
170
                # If this command has a MISSING description, Discord would return
171
                # registered the command with the description ''
172
                or self.description is MISSING and not other.description
173
            )
174
        )
175
176
    def __hash__(self):
177
        return hash((self.id, self.name, self.guild_id, self.type))
178
179
    def add_option(self, option: AppCommandOption):
180
        """Add a new option field to the current application command.
181
182
        Parameters
183
        ----------
184
        option : :class:`~pincer.objects.app.command.AppCommandOption`
185
            The option which will be appended.
186
        """
187
        if self.options:
188
            self.options.append(option)
189
        else:
190
            self.options = [option]
191
192
193
@dataclass(repr=False)
194
class ClientCommandStructure:
195
    """Represents the structure of how the client saves the existing
196
    commands in the register.
197
198
    Attributes
199
    ----------
200
    app: :class:`~pincer.objects.app.command.AppCommand`
201
        The command application.
202
    call: :class:`~pincer.utils.types.Coro`
203
        The coroutine which should be called when the command gets
204
        executed.
205
    cooldown: :class:`int`
206
        Amount of times for cooldown
207
    cooldown_scale: :class:`float`
208
        Search time for cooldown
209
    cooldown_scope: :class:`~pincer.objects.app.throttle_scope.ThrottleScope`
210
        The type of cooldown
211
    """
212
    app: AppCommand
213
    call: Coro
214
    cooldown: int
215
    cooldown_scale: float
216
    cooldown_scope: ThrottleScope
217
    group: APINullable[Group] = MISSING
218
    sub_group: APINullable[Subgroup] = MISSING
219