Passed
Push — main ( 572bd1...cd7b53 )
by
unknown
01:37
created

pincer.objects.application_command   A

Complexity

Total Complexity 17

Size/Duplication

Total Lines 310
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
wmc 17
eloc 106
dl 0
loc 310
rs 10
c 0
b 0
f 0

5 Methods

Rating   Name   Duplication   Size   Complexity  
A AppCommandInteractionDataOption.__post_init__() 0 6 1
A AppCommandOption.__post_init__() 0 11 1
A AppCommand.add_option() 0 10 2
A AppCommand.__post_init__() 0 13 2
C AppCommand.__eq__() 0 22 11
1
# -*- coding: utf-8 -*-
0 ignored issues
show
introduced by
Missing module docstring
Loading history...
2
# MIT License
3
#
4
# Copyright (c) 2021 Pincer
5
#
6
# Permission is hereby granted, free of charge, to any person obtaining
7
# a copy of this software and associated documentation files
8
# (the "Software"), to deal in the Software without restriction,
9
# including without limitation the rights to use, copy, modify, merge,
10
# publish, distribute, sublicense, and/or sell copies of the Software,
11
# and to permit persons to whom the Software is furnished to do so,
12
# subject to the following conditions:
13
#
14
# The above copyright notice and this permission notice shall be
15
# included in all copies or substantial portions of the Software.
16
#
17
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
20
# IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
21
# CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
22
# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
23
# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24
25
from __future__ import annotations
26
27
from dataclasses import dataclass
28
from enum import IntEnum
29
from typing import List, Union, Optional
30
31
from ..utils import APIObject, APINullable, Coro, convert, MISSING, Snowflake, \
32
    get_index
33
34
35
class AppCommandType(IntEnum):
36
    """
37
    Defines the different types of application commands.
38
39
    :param CHAT_INPUT:
40
        Slash commands; a text-based command that shows up when a user
41
        types /
42
43
    :param USER:
44
        A UI-based command that shows up when you right click or tap on
45
        a user
46
47
    :param MESSAGE:
48
        A UI-based command that shows up when you right click or tap on
49
        a message
50
    """
51
    CHAT_INPUT = 1
52
    USER = 2
53
    MESSAGE = 3
54
55
56
class AppCommandOptionType(IntEnum):
57
    """
58
    Represents a parameter type.
59
60
    :param SUB_COMMAND:
61
        The parameter will be a subcommand.
62
63
    :param SUB_COMMAND_GROUP:
64
        The parameter will be a group of subcommands.
65
66
    :param STRING:
67
        The parameter will be a string.
68
69
    :param INTEGER:
70
        The parameter will be an integer/number. (-2^53 and 2^53)
71
72
    :param BOOLEAN:
73
        The parameter will be a boolean.
74
75
    :param USER:
76
        The parameter will be a Discord user object.
77
78
    :param CHANNEL:
79
        The parameter will be a Discord channel object.
80
81
    :param ROLE:
82
        The parameter will be a Discord role object.
83
84
    :param MENTIONABLE:
85
        The parameter will be mentionable.
86
87
    :param NUMBER:
88
        The parameter will be a float. (-2^53 and 2^53)
89
    """
90
    SUB_COMMAND = 1
91
    SUB_COMMAND_GROUP = 2
92
    STRING = 3
93
    INTEGER = 4  # 54-bit
94
    BOOLEAN = 5
95
    USER = 6
96
    CHANNEL = 7
97
    ROLE = 8
98
    MENTIONABLE = 9
99
    NUMBER = 10  # 54-bit
100
101
102
@dataclass
103
class AppCommandInteractionDataOption(APIObject):
104
    """
105
    Represents a Discord Application Command Interaction Data Option
106
107
    :param name:
108
        the name of the parameter
109
110
    :param type:
111
        value of application command option type
112
113
    :param value:
114
        the value of the pair
115
116
    :param options:
117
        present if this option is a group or subcommand
118
    """
119
    name: str
120
    value: APINullable[str] = MISSING
121
    type: APINullable[AppCommandOptionType] = MISSING
122
    options: APINullable[
123
        List[AppCommandInteractionDataOption]] = MISSING
124
125
    def __post_init__(self):
126
        self.type = convert(self.type, AppCommandOptionType)
127
        self.options = convert(
128
            self.options,
129
            AppCommandInteractionDataOption.from_dict,
130
            AppCommandInteractionDataOption
131
        )
132
133
134
@dataclass
135
class AppCommandOptionChoice(APIObject):
136
    """
137
    Represents a Discord Application Command Option Choice object
138
139
    :param name:
140
        1-100 character choice name
141
142
    :param value:
143
        value of the choice, up to 100 characters if string
144
    """
145
    name: str
146
    value: Union[str, int, float]
147
148
149
@dataclass
150
class AppCommandOption(APIObject):
151
    """
152
    Represents a Discord Application Command Option object
153
154
    :param type:
155
        the type of option
156
157
    :param name:
158
        1-32 lowercase character name matching `^[\\w-]{1,32}$`
159
160
    :param description:
161
        1-100 character description
162
163
    :param required:
164
        if the parameter is required or optional--default `False`
165
166
    :param choices:
167
        choices for `STRING`, `INTEGER`, and `NUMBER`
168
        types for the user to pick from, max 25
169
170
    :param options:
171
        if the option is a subcommand or subcommand group type,
172
        this nested options will be the parameters
173
    """
174
    type: AppCommandOptionType
175
    name: str
176
    description: str
177
178
    required: APINullable[bool] = False
179
    choices: APINullable[List[AppCommandOptionChoice]] = MISSING
180
    options: APINullable[List[AppCommandOption]] = MISSING
181
182
    def __post_init__(self):
183
        self.type = AppCommandOptionType(self.type)
184
        self.choices = convert(
185
            self.choices,
186
            AppCommandOptionChoice.from_dict,
187
            AppCommandOptionChoice
188
        )
189
        self.options = convert(
190
            self.options,
191
            AppCommandOption.from_dict,
192
            AppCommandOption
193
        )
194
195
196
@dataclass
0 ignored issues
show
best-practice introduced by
Too many instance attributes (10/7)
Loading history...
197
class AppCommand(APIObject):
198
    """
199
    Represents a Discord Application Command object
200
201
    :param id:
202
        unique id of the command
203
204
    :param type:
205
        the type of command, defaults `1` if not set
206
207
    :param application_id:
208
        unique id of the parent application
209
210
    :param guild_id:
211
        guild id of the command, if not global
212
213
    :param name:
214
        1-32 character name
215
216
    :param description:
217
        1-100 character description for `CHAT_INPUT` commands,
218
        empty string for `USER` and `MESSAGE` commands
219
220
    :param options:
221
        the parameters for the command, max 25
222
223
    :param default_permission:
224
        whether the command is enabled by default
225
        when the app is added to a guild
226
227
    :param version:
228
        autoincrementing version identifier updated during substantial
229
        record changes
230
    """
231
    type: AppCommandType
232
    name: str
233
    description: str
234
235
    id: APINullable[Snowflake] = MISSING
236
    version: APINullable[Snowflake] = MISSING
237
    application_id: APINullable[Snowflake] = MISSING
238
    options: APINullable[List[AppCommandOption]] = MISSING
239
    guild_id: APINullable[Snowflake] = MISSING
240
    default_permission: APINullable[bool] = True
241
242
    _eq_props = [
243
        "type", "name", "description", "guild_id", "default_permission"
244
    ]
245
246
    def __post_init__(self):
247
        self.id = convert(self.id, Snowflake.from_string)
248
        self.version = convert(self.version, Snowflake.from_string)
249
        self.application_id = convert(self.application_id,
250
                                      Snowflake.from_string)
251
        self.options = convert(
252
            self.options,
253
            AppCommandOption.from_dict,
254
            AppCommandOption
255
        )
256
        self.guild_id = convert(self.guild_id, Snowflake.from_string)
257
258
        self.options = [] if self.options is MISSING else self.options
259
260
    def __eq__(self, other: Union[AppCommand, ClientCommandStructure]):
261
        if isinstance(other, ClientCommandStructure):
262
            other = other.app
263
264
        is_equal = all(
265
            self.__getattribute__(prop) == other.__getattribute__(prop)
266
            for prop in self._eq_props
267
        )
268
269
        if (self.options is MISSING and other.options is not MISSING) or \
270
                (self.options is not MISSING and other.options is MISSING):
271
            return False
272
273
        if is_equal and len(other.options) == len(self.options):
274
            for idx, option in enumerate(other.options):
275
                option_comp: Optional[AppCommandOption] = \
276
                    get_index(self.options, idx)
277
278
                if not option_comp or option != option_comp:
279
                    is_equal = False
280
281
        return is_equal
282
283
    def add_option(self, option: AppCommandOption):
284
        """
285
        Add a new option field to the current application command.
286
287
        :param option: The option which will be appended.
288
        """
289
        if self.options:
290
            self.options.append(option)
291
        else:
292
            self.options = [option]
293
294
295
@dataclass
296
class ClientCommandStructure:
297
    """
298
    Represents the structure of how the client saves the existing
299
    commands in the register.
300
301
    :param app:
302
        The command application.
303
304
    :param call:
305
        The coroutine which should be called when the command gets
306
        executed.
307
    """
308
    app: AppCommand
309
    call: Coro
310