Passed
Pull Request — main (#158)
by
unknown
01:27
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
        """|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
        # TODO: Write docs
298
        content_type, data = convert_message(self._client, message).serialize()
299
300
        resp = await self._http.post(
301
            f"channels/{self.id}/messages",
302
            data,
303
            content_type=content_type
304
        )
305
        msg = UserMessage.from_dict(resp)
306
        self.__post_sent(msg)
307
        return msg
308
309
    def __str__(self):
310
        """return the discord tag when object gets used as a string."""
311
        return self.name or str(self.id)
312
313
314
class TextChannel(Channel):
315
    @overload
316
    async def edit(
317
            self, name: str = None, type: ChannelType = None,
318
            position: int = None, topic: str = None, nsfw: bool = None,
319
            rate_limit_per_user: int = None,
320
            permissions_overwrites: List[Overwrite] = None,
321
            parent_id: Snowflake = None,
322
            default_auto_archive_duration: int = None
323
    ) -> Union[TextChannel, NewsChannel]:
324
        ...
325
326
    async def edit(self, **kwargs):
327
        return await super().edit(**kwargs)
328
329
    @property
330
    def mention(self) -> str:
331
        """Return a channel mention."""
332
        return f"<#{self.id}>"
333
334
335
class VoiceChannel(Channel):
336
    @overload
337
    async def edit(
338
            self, name: str = None, position: int = None, bitrate: int = None,
339
            user_limit: int = None,
340
            permissions_overwrites: List[Overwrite] = None,
341
            rtc_region: str = None, video_quality_mod: int = None
342
    ) -> VoiceChannel:
343
        ...
344
345
    async def edit(self, **kwargs):
346
        return await super().edit(**kwargs)
347
348
349
class CategoryChannel(Channel):
350
    pass
351
352
353
class NewsChannel(Channel):
354
    @overload
355
    async def edit(
356
            self, name: str = None, type: ChannelType = None,
357
            position: int = None, topic: str = None, nsfw: bool = None,
358
            permissions_overwrites: List[Overwrite] = None,
359
            parent_id: Snowflake = None,
360
            default_auto_archive_duration: int = None
361
    ) -> Union[TextChannel, NewsChannel]:
362
        ...
363
364
    async def edit(self, **kwargs):
365
        return await super().edit(**kwargs)
366
367
368
@dataclass
369
class ChannelMention(APIObject):
370
    """
371
    Represents a Discord Channel Mention object
372
373
    :param id:
374
        id of the channel
375
376
    :param guild_id:
377
        id of the guild containing the channel
378
379
    :param type:
380
        the type of channel
381
382
    :param name:
383
        the name of the channel
384
    """
385
    id: Snowflake
386
    guild_id: Snowflake
387
    type: ChannelType
388
    name: str
389
390
391
# noinspection PyTypeChecker
392
_channel_type_map: Dict[ChannelType, Channel] = {
393
    ChannelType.GUILD_TEXT: TextChannel,
394
    ChannelType.GUILD_VOICE: VoiceChannel,
395
    ChannelType.GUILD_CATEGORY: CategoryChannel,
396
    ChannelType.GUILD_NEWS: NewsChannel
397
}
398