Passed
Pull Request — main (#158)
by
unknown
02:08
created

pincer.objects.guild.channel.NewsChannel.edit()   A

Complexity

Conditions 1

Size

Total Lines 9
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 2
dl 0
loc 9
rs 10
c 0
b 0
f 0
cc 1
nop 2
1
# Copyright Pincer 2021-Present
2
# Full MIT License can be found in `LICENSE` at the project root.
3
4
from __future__ import annotations
5
6
from asyncio import sleep, ensure_future
7
from dataclasses import dataclass
8
from enum import IntEnum
9
from typing import Dict, Optional, List, TYPE_CHECKING, Union, overload
10
11
from ..message.embed import Embed
12
from ..message.user_message import UserMessage
13
from ..._config import GatewayConfig
14
from ...utils.api_object import APIObject
15
from ...utils.conversion import construct_client_dict
16
from ...utils.convert_message import convert_message
17
from ...utils.types import MISSING
18
19
if TYPE_CHECKING:
20
    from ..message import Message
21
    from ..guild.overwrite import Overwrite
22
    from ..guild.thread import ThreadMetadata
23
    from ..guild.member import GuildMember
24
    from ..user import User
25
    from ... import Client
26
    from ...utils import APINullable, Snowflake, Timestamp
27
28
29
class ChannelType(IntEnum):
30
    """Represents a channel its type."""
31
    GUILD_TEXT = 0
32
    DM = 1
33
    GUILD_VOICE = 2
34
    GROUP_DM = 3
35
    GUILD_CATEGORY = 4
36
    GUILD_NEWS = 5
37
    GUILD_STORE = 6
38
39
    if GatewayConfig.version >= 9:
40
        GUILD_NEWS_THREAD = 10
41
        GUILD_PUBLIC_THREAD = 11
42
        GUILD_PRIVATE_THREAD = 12
43
44
    GUILD_STAGE_VOICE = 13
45
46
47
@dataclass
48
class Channel(APIObject):
49
    """
50
    Represents a Discord Channel Mention object
51
52
    :param id:
53
        the id of this channel
54
55
    :param type:
56
        the type of channel
57
58
    :param application_id:
59
        application id of the group DM creator if it is bot-created
60
61
    :param bitrate:
62
        the bitrate (in bits) of the voice channel
63
64
    :param default_auto_archive_duration:
65
        default duration for newly created threads, in minutes, to
66
        automatically archive the thread after recent activity, can be set to:
67
        60, 1440, 4320, 10080
68
69
    :param guild_id:
70
        the id of the guild (may be missing for some channel objects received
71
        over gateway guild dispatches)
72
73
    :param icon:
74
        icon hash
75
76
    :param last_message_id:
77
        the id of the last message sent in this channel (may not point to an
78
        existing or valid message)
79
80
    :param last_pin_timestamp:
81
        when the last pinned message was pinned. This may be null in events
82
        such as GUILD_CREATE when a message is not pinned.
83
84
    :param member:
85
        thread member object for the current user, if they have joined the
86
        thread, only included on certain API endpoints
87
88
    :param member_count:
89
        an approximate count of users in a thread, stops counting at 50
90
91
    :param message_count:
92
        an approximate count of messages in a thread, stops counting at 50
93
94
    :param name:
95
        the name of the channel (1-100 characters)
96
97
    :param nsfw:
98
        whether the channel is nsfw
99
100
    :param owner_id:
101
        id of the creator of the group DM or thread
102
103
    :param parent_id:
104
        for guild channels: id of the parent category for a channel (each
105
        parent category can contain up to 50 channels), for threads: id of the
106
        text channel this thread was created
107
108
    :param permissions:
109
        computed permissions for the invoking user in the channel, including
110
        overwrites, only included when part of the resolved data received on a
111
        slash command interaction
112
113
    :param permission_overwrites:
114
        explicit permission overwrites for members and roles
115
116
    :param position:
117
        sorting position of the channel
118
119
    :param rate_limit_per_user:
120
        amount of seconds a user has to wait before sending another message
121
        (0-21600); bots, as well as users with the permission manage_messages
122
        or manage_channel, are unaffected
123
124
    :param recipients:
125
        the recipients of the DM
126
127
    :param rtc_region:
128
        voice region id for the voice channel, automatic when set to null
129
130
    :param thread_metadata:
131
        thread-specific fields not needed by other channels
132
133
    :param topic:
134
        the channel topic (0-1024 characters)
135
136
    :param user_limit:
137
        the user limit of the voice channel
138
139
    :param video_quality_mode:
140
        the camera video quality mode of the voice channel, 1 when not present
141
142
    :param mention:
143
        structures a string to mention the channel
144
    """
145
    id: Snowflake
146
    type: ChannelType
147
148
    application_id: APINullable[Snowflake] = MISSING
149
    bitrate: APINullable[int] = MISSING
150
    default_auto_archive_duration: APINullable[int] = MISSING
151
    guild_id: APINullable[Snowflake] = MISSING
152
    icon: APINullable[Optional[str]] = MISSING
153
154
    last_message_id: APINullable[Optional[Snowflake]] = MISSING
155
    last_pin_timestamp: APINullable[Optional[Timestamp]] = MISSING
156
    member: APINullable[GuildMember] = MISSING
157
158
    member_count: APINullable[int] = MISSING
159
160
    message_count: APINullable[int] = MISSING
161
162
    name: APINullable[str] = MISSING
163
    nsfw: APINullable[bool] = MISSING
164
    owner_id: APINullable[Snowflake] = MISSING
165
    parent_id: APINullable[Optional[Snowflake]] = MISSING
166
    permissions: APINullable[str] = MISSING
167
    permission_overwrites: APINullable[List[Overwrite]] = MISSING
168
    position: APINullable[int] = MISSING
169
    rate_limit_per_user: APINullable[int] = MISSING
170
    recipients: APINullable[List[User]] = MISSING
171
    rtc_region: APINullable[Optional[str]] = MISSING
172
    thread_metadata: APINullable[ThreadMetadata] = MISSING
173
    topic: APINullable[Optional[str]] = MISSING
174
    user_limit: APINullable[int] = MISSING
175
    video_quality_mode: APINullable[int] = MISSING
176
177
    @property
178
    def mention(self):
179
        return f"<#{self.id}>"
180
181
    @classmethod
182
    async def from_id(cls, client: Client, channel_id: int) -> Channel:
183
        # TODO: Write docs
184
        data = (await client.http.get(f"channels/{channel_id}")) or {}
185
186
        data.update(construct_client_dict(
187
            client,
188
            {"type": ChannelType(data.pop("type"))}
189
        ))
190
191
        channel_cls = _channel_type_map.get(data["type"], Channel)
192
        return channel_cls.from_dict(data)
193
194
    @overload
195
    async def edit(
196
            self, *, name: str = None,
197
            type: ChannelType = None,
198
            position: int = None, topic: str = None, nsfw: bool = None,
199
            rate_limit_per_user: int = None, bitrate: int = None,
200
            user_limit: int = None,
201
            permissions_overwrites: List[Overwrite] = None,
202
            parent_id: Snowflake = None, rtc_region: str = None,
203
            video_quality_mod: int = None,
204
            default_auto_archive_duration: int = None
205
    ) -> Channel:
206
        ...
207
208
    async def edit(
209
            self,
210
            reason: Optional[str] = None,
211
            **kwargs
212
    ):
213
        # TODO: Write docs
214
215
        headers = {}
216
217
        if reason:
218
            headers["X-Audit-Log-Reason"] = str(reason)
219
220
        data = await self._http.patch(
221
            f"channels/{self.id}",
222
            kwargs,
223
            headers=headers
224
        )
225
        data.update(construct_client_dict(
226
            self._client,
227
            {"type": ChannelType(data.pop("type"))}
228
        ))
229
        channel_cls = _channel_type_map.get(data["type"], Channel)
230
        return channel_cls.from_dict(data)
231
232
    async def delete(
233
            self,
234
            reason: Optional[str] = None,
235
            /,
0 ignored issues
show
introduced by
invalid syntax (<unknown>, line 235)
Loading history...
236
            channel_id: Optional[Snowflake] = None
237
    ):
238
        # TODO: Write docs
239
        channel_id = channel_id or self.id
240
241
        headers = {}
242
243
        if reason:
244
            headers["X-Audit-Log-Reason"] = str(reason)
245
246
        await self._http.delete(
247
            f"channels/{channel_id}",
248
            headers
249
        )
250
251
    async def __post_send_handler(self, message: Message):
252
        """
253
        Process a message after it was sent.
254
255
        :param message:
256
            The message.
257
        """
258
259
        if getattr(message, "delete_after", None):
260
            await sleep(message.delete_after)
261
            await self.delete()
262
263
    def __post_sent(
264
            self,
265
            message: Message
266
    ):
267
        """
268
        Ensure the `__post_send_handler` method its future.
269
270
        :param message:
271
            The message.
272
        """
273
        ensure_future(self.__post_send_handler(message))
274
275
    async def send(self, message: Union[Embed, Message, str]) -> UserMessage:
276
        # TODO: Write docs
277
        content_type, data = convert_message(self._client, message).serialize()
278
279
        resp = await self._http.post(
280
            f"channels/{self.id}/messages",
281
            data,
282
            content_type=content_type
283
        )
284
        msg = UserMessage.from_dict(resp)
285
        self.__post_sent(msg)
286
        return msg
287
288
    def __str__(self):
289
        """return the discord tag when object gets used as a string."""
290
        return self.name or str(self.id)
291
292
293
class TextChannel(Channel):
294
    @overload
295
    async def edit(
296
            self, name: str = None, type: ChannelType = None,
297
            position: int = None, topic: str = None, nsfw: bool = None,
298
            rate_limit_per_user: int = None,
299
            permissions_overwrites: List[Overwrite] = None,
300
            parent_id: Snowflake = None,
301
            default_auto_archive_duration: int = None
302
    ) -> Union[TextChannel, NewsChannel]:
303
        ...
304
305
    async def edit(self, **kwargs):
306
        return await super().edit(**kwargs)
307
308
    @property
309
    def mention(self) -> str:
310
        """Return a channel mention."""
311
        return f"<#{self.id}>"
312
313
314
class VoiceChannel(Channel):
315
    @overload
316
    async def edit(
317
            self, name: str = None, position: int = None, bitrate: int = None,
318
            user_limit: int = None,
319
            permissions_overwrites: List[Overwrite] = None,
320
            rtc_region: str = None, video_quality_mod: int = None
321
    ) -> VoiceChannel:
322
        ...
323
324
    async def edit(self, **kwargs):
325
        return await super().edit(**kwargs)
326
327
328
class CategoryChannel(Channel):
329
    pass
330
331
332
class NewsChannel(Channel):
333
    @overload
334
    async def edit(
335
            self, name: str = None, type: ChannelType = None,
336
            position: int = None, topic: str = None, nsfw: bool = None,
337
            permissions_overwrites: List[Overwrite] = None,
338
            parent_id: Snowflake = None,
339
            default_auto_archive_duration: int = None
340
    ) -> Union[TextChannel, NewsChannel]:
341
        ...
342
343
    async def edit(self, **kwargs):
344
        return await super().edit(**kwargs)
345
346
347
@dataclass
348
class ChannelMention(APIObject):
349
    """
350
    Represents a Discord Channel Mention object
351
352
    :param id:
353
        id of the channel
354
355
    :param guild_id:
356
        id of the guild containing the channel
357
358
    :param type:
359
        the type of channel
360
361
    :param name:
362
        the name of the channel
363
    """
364
    id: Snowflake
365
    guild_id: Snowflake
366
    type: ChannelType
367
    name: str
368
369
370
# noinspection PyTypeChecker
371
_channel_type_map: Dict[ChannelType, Channel] = {
372
    ChannelType.GUILD_TEXT: TextChannel,
373
    ChannelType.GUILD_VOICE: VoiceChannel,
374
    ChannelType.GUILD_CATEGORY: CategoryChannel,
375
    ChannelType.GUILD_NEWS: NewsChannel
376
}
377