Passed
Push — main ( 93a68d...86d0d3 )
by Yohann
02:00 queued 12s
created

pincer.objects.app_command   A

Complexity

Total Complexity 14

Size/Duplication

Total Lines 313
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
wmc 14
eloc 107
dl 0
loc 313
rs 10
c 0
b 0
f 0

5 Methods

Rating   Name   Duplication   Size   Complexity  
A AppCommandOption.__post_init__() 0 11 1
A AppCommandInteractionDataOption.__post_init__() 0 6 1
A AppCommand.__post_init__() 0 13 2
B AppCommand.__eq__() 0 22 8
A AppCommand.add_option() 0 10 2
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
0 ignored issues
show
Unused Code introduced by
Unused Optional imported from typing
Loading history...
30
31
from ..utils import (
32
    APIObject, APINullable, Coro, convert,
33
    MISSING, Snowflake, get_index
34
)
35
36
37
class AppCommandType(IntEnum):
38
    """
39
    Defines the different types of application commands.
40
41
    :param CHAT_INPUT:
42
        Slash commands; a text-based command that shows up when a user
43
        types /
44
45
    :param USER:
46
        A UI-based command that shows up when you right click or tap on
47
        a user
48
49
    :param MESSAGE:
50
        A UI-based command that shows up when you right click or tap on
51
        a message
52
    """
53
    CHAT_INPUT = 1
54
    USER = 2
55
    MESSAGE = 3
56
57
58
class AppCommandOptionType(IntEnum):
59
    """
60
    Represents a parameter type.
61
62
    :param SUB_COMMAND:
63
        The parameter will be a subcommand.
64
65
    :param SUB_COMMAND_GROUP:
66
        The parameter will be a group of subcommands.
67
68
    :param STRING:
69
        The parameter will be a string.
70
71
    :param INTEGER:
72
        The parameter will be an integer/number. (-2^53 and 2^53)
73
74
    :param BOOLEAN:
75
        The parameter will be a boolean.
76
77
    :param USER:
78
        The parameter will be a Discord user object.
79
80
    :param CHANNEL:
81
        The parameter will be a Discord channel object.
82
83
    :param ROLE:
84
        The parameter will be a Discord role object.
85
86
    :param MENTIONABLE:
87
        The parameter will be mentionable.
88
89
    :param NUMBER:
90
        The parameter will be a float. (-2^53 and 2^53)
91
    """
92
    SUB_COMMAND = 1
93
    SUB_COMMAND_GROUP = 2
94
    STRING = 3
95
    INTEGER = 4  # 54-bit
96
    BOOLEAN = 5
97
    USER = 6
98
    CHANNEL = 7
99
    ROLE = 8
100
    MENTIONABLE = 9
101
    NUMBER = 10  # 54-bit
102
103
104
@dataclass
105
class AppCommandInteractionDataOption(APIObject):
106
    """
107
    Represents a Discord Application Command Interaction Data Option
108
109
    :param name:
110
        the name of the parameter
111
112
    :param type:
113
        value of application command option type
114
115
    :param value:
116
        the value of the pair
117
118
    :param options:
119
        present if this option is a group or subcommand
120
    """
121
    name: str
122
    value: APINullable[str] = MISSING
123
    type: APINullable[AppCommandOptionType] = MISSING
124
    options: APINullable[
125
        List[AppCommandInteractionDataOption]] = MISSING
126
127
    def __post_init__(self):
128
        self.type = convert(self.type, AppCommandOptionType)
129
        self.options = convert(
130
            self.options,
131
            AppCommandInteractionDataOption.from_dict,
132
            AppCommandInteractionDataOption
133
        )
134
135
136
@dataclass
137
class AppCommandOptionChoice(APIObject):
138
    """
139
    Represents a Discord Application Command Option Choice object
140
141
    :param name:
142
        1-100 character choice name
143
144
    :param value:
145
        value of the choice, up to 100 characters if string
146
    """
147
    name: str
148
    value: Union[str, int, float]
149
150
151
@dataclass
152
class AppCommandOption(APIObject):
153
    """
154
    Represents a Discord Application Command Option object
155
156
    :param type:
157
        the type of option
158
159
    :param name:
160
        1-32 lowercase character name matching `^[\\w-]{1,32}$`
161
162
    :param description:
163
        1-100 character description
164
165
    :param required:
166
        if the parameter is required or optional--default `False`
167
168
    :param choices:
169
        choices for `STRING`, `INTEGER`, and `NUMBER`
170
        types for the user to pick from, max 25
171
172
    :param options:
173
        if the option is a subcommand or subcommand group type,
174
        this nested options will be the parameters
175
    """
176
    type: AppCommandOptionType
177
    name: str
178
    description: str
179
180
    required: APINullable[bool] = False
181
    choices: APINullable[List[AppCommandOptionChoice]] = MISSING
182
    options: APINullable[List[AppCommandOption]] = MISSING
183
184
    def __post_init__(self):
185
        self.type = AppCommandOptionType(self.type)
186
        self.choices = convert(
187
            self.choices,
188
            AppCommandOptionChoice.from_dict,
189
            AppCommandOptionChoice
190
        )
191
        self.options = convert(
192
            self.options,
193
            AppCommandOption.from_dict,
194
            AppCommandOption
195
        )
196
197
198
@dataclass
0 ignored issues
show
best-practice introduced by
Too many instance attributes (10/7)
Loading history...
199
class AppCommand(APIObject):
200
    """
201
    Represents a Discord Application Command object
202
203
    :param id:
204
        unique id of the command
205
206
    :param type:
207
        the type of command, defaults `1` if not set
208
209
    :param application_id:
210
        unique id of the parent application
211
212
    :param guild_id:
213
        guild id of the command, if not global
214
215
    :param name:
216
        1-32 character name
217
218
    :param description:
219
        1-100 character description for `CHAT_INPUT` commands,
220
        empty string for `USER` and `MESSAGE` commands
221
222
    :param options:
223
        the parameters for the command, max 25
224
225
    :param default_permission:
226
        whether the command is enabled by default
227
        when the app is added to a guild
228
229
    :param version:
230
        autoincrementing version identifier updated during substantial
231
        record changes
232
    """
233
    type: AppCommandType
234
    name: str
235
    description: str
236
237
    id: APINullable[Snowflake] = MISSING
238
    version: APINullable[Snowflake] = MISSING
239
    application_id: APINullable[Snowflake] = MISSING
240
    options: APINullable[List[AppCommandOption]] = MISSING
241
    guild_id: APINullable[Snowflake] = MISSING
242
    default_permission: APINullable[bool] = True
243
244
    _eq_props = [
245
        "type", "name", "description", "guild_id", "default_permission"
246
    ]
247
248
    def __post_init__(self):
249
        self.id = convert(self.id, Snowflake.from_string)
250
        self.version = convert(self.version, Snowflake.from_string)
251
        self.application_id = convert(self.application_id,
252
                                      Snowflake.from_string)
253
        self.options = convert(
254
            self.options,
255
            AppCommandOption.from_dict,
256
            AppCommandOption
257
        )
258
        self.guild_id = convert(self.guild_id, Snowflake.from_string)
259
260
        self.options = [] if self.options is MISSING else self.options
261
262
    def __eq__(self, other: Union[AppCommand, ClientCommandStructure]):
263
        if isinstance(other, ClientCommandStructure):
264
            other = other.app
265
266
        is_equal = all(
267
            self.__getattribute__(prop) == other.__getattribute__(prop)
268
            for prop in self._eq_props
269
        )
270
271
        if (
272
            (self.options is MISSING and other.options is not MISSING)
0 ignored issues
show
Coding Style introduced by
Wrong hanging indentation before block (add 4 spaces).
Loading history...
273
            or (self.options is not MISSING and other.options is MISSING)
0 ignored issues
show
Coding Style introduced by
Wrong hanging indentation before block (add 4 spaces).
Loading history...
274
            and not is_equal
0 ignored issues
show
Coding Style introduced by
Wrong hanging indentation before block (add 4 spaces).
Loading history...
275
        ):
276
            return False
277
278
        if len(other.options) != len(self.options):
279
            return False
280
281
        return not any(
282
            option != get_index(self.options, idx)
283
            for idx, option in enumerate(other.options)
284
        )
285
286
    def add_option(self, option: AppCommandOption):
287
        """
288
        Add a new option field to the current application command.
289
290
        :param option: The option which will be appended.
291
        """
292
        if self.options:
293
            self.options.append(option)
294
        else:
295
            self.options = [option]
296
297
298
@dataclass
299
class ClientCommandStructure:
300
    """
301
    Represents the structure of how the client saves the existing
302
    commands in the register.
303
304
    :param app:
305
        The command application.
306
307
    :param call:
308
        The coroutine which should be called when the command gets
309
        executed.
310
    """
311
    app: AppCommand
312
    call: Coro
313