Passed
Pull Request — main (#158)
by
unknown
01:29
created

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

Complexity

Conditions 1

Size

Total Lines 2
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 2
dl 0
loc 2
rs 10
c 0
b 0
f 0
cc 1
nop 3
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
        """|coro|
239
240
        Delete the current channel.
241
242
        Parameters
243
        ----------
244
        reason Optional[:class:`str`]
245
            The reason of the channel delete.
246
        channel_id :class:`~.pincer.utils.Snowflake`
247
            The id of the channel, defaults to the current object id.
248
        """
249
        channel_id = channel_id or self.id
250
251
        headers = {}
252
253
        if reason:
254
            headers["X-Audit-Log-Reason"] = str(reason)
255
256
        await self._http.delete(
257
            f"channels/{channel_id}",
258
            headers
259
        )
260
261
    async def __post_send_handler(self, message: Message):
262
        """Process a message after it was sent.
263
264
        Parameters
265
        ----------
266
        message :class:`~.pincer.objects.message.message.Message`
267
            The message.
268
        """
269
270
        if getattr(message, "delete_after", None):
271
            await sleep(message.delete_after)
272
            await self.delete()
273
274
    def __post_sent(
275
            self,
276
            message: Message
277
    ):
278
        """Ensure the `__post_send_handler` method its future.
279
280
        Parameters
281
        ----------
282
        message :class:`~.pincer.objects.message.message.Message`
283
            The message.
284
        """
285
        ensure_future(self.__post_send_handler(message))
286
287
    async def send(self, message: Union[Embed, Message, str]) -> UserMessage:
288
        """|coro|
289
290
        Send a message in the channel.
291
292
        Parameters
293
        ----------
294
        message :class:`~.pincer.objects.message.message.Message`
295
            The message which must be sent
296
297
        Returns
298
        -------
299
        :class:`~.pincer.objects.message.user_message.UserMessage`
300
            The message that was sent.
301
        """
302
        # TODO: Write docs
303
        content_type, data = convert_message(self._client, message).serialize()
304
305
        resp = await self._http.post(
306
            f"channels/{self.id}/messages",
307
            data,
308
            content_type=content_type
309
        )
310
        msg = UserMessage.from_dict(resp)
311
        self.__post_sent(msg)
312
        return msg
313
314
    def __str__(self):
315
        """return the discord tag when object gets used as a string."""
316
        return self.name or str(self.id)
317
318
319
class TextChannel(Channel):
320
    @overload
321
    async def edit(
322
            self, name: str = None, type: ChannelType = None,
323
            position: int = None, topic: str = None, nsfw: bool = None,
324
            rate_limit_per_user: int = None,
325
            permissions_overwrites: List[Overwrite] = None,
326
            parent_id: Snowflake = None,
327
            default_auto_archive_duration: int = None
328
    ) -> Union[TextChannel, NewsChannel]:
329
        ...
330
331
    async def edit(self, **kwargs):
332
        return await super().edit(**kwargs)
333
334
    @property
335
    def mention(self) -> str:
336
        """Return a channel mention."""
337
        return f"<#{self.id}>"
338
339
340
class VoiceChannel(Channel):
341
    @overload
342
    async def edit(
343
            self, name: str = None, position: int = None, bitrate: int = None,
344
            user_limit: int = None,
345
            permissions_overwrites: List[Overwrite] = None,
346
            rtc_region: str = None, video_quality_mod: int = None
347
    ) -> VoiceChannel:
348
        ...
349
350
    async def edit(self, **kwargs):
351
        return await super().edit(**kwargs)
352
353
354
class CategoryChannel(Channel):
355
    pass
356
357
358
class NewsChannel(Channel):
359
    @overload
360
    async def edit(
361
            self, name: str = None, type: ChannelType = None,
362
            position: int = None, topic: str = None, nsfw: bool = None,
363
            permissions_overwrites: List[Overwrite] = None,
364
            parent_id: Snowflake = None,
365
            default_auto_archive_duration: int = None
366
    ) -> Union[TextChannel, NewsChannel]:
367
        ...
368
369
    async def edit(self, **kwargs):
370
        return await super().edit(**kwargs)
371
372
373
@dataclass
374
class ChannelMention(APIObject):
375
    """
376
    Represents a Discord Channel Mention object
377
378
    :param id:
379
        id of the channel
380
381
    :param guild_id:
382
        id of the guild containing the channel
383
384
    :param type:
385
        the type of channel
386
387
    :param name:
388
        the name of the channel
389
    """
390
    id: Snowflake
391
    guild_id: Snowflake
392
    type: ChannelType
393
    name: str
394
395
396
# noinspection PyTypeChecker
397
_channel_type_map: Dict[ChannelType, Channel] = {
398
    ChannelType.GUILD_TEXT: TextChannel,
399
    ChannelType.GUILD_VOICE: VoiceChannel,
400
    ChannelType.GUILD_CATEGORY: CategoryChannel,
401
    ChannelType.GUILD_NEWS: NewsChannel
402
}
403