Passed
Pull Request — main (#281)
by
unknown
01:47
created

pincer.objects.guild.webhook.Webhook.delete()   A

Complexity

Conditions 2

Size

Total Lines 13
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 4
dl 0
loc 13
rs 10
c 0
b 0
f 0
cc 2
nop 2
1
# Copyright Pincer 2021-Present
0 ignored issues
show
introduced by
Missing module docstring
Loading history...
2
# Full MIT License can be found in `LICENSE` at the project root.
3
4
from __future__ import annotations
5
6
from dataclasses import dataclass
7
from enum import Enum, IntEnum
8
from typing import TYPE_CHECKING, overload
9
10
from ...exceptions import EmbedOverflow
11
from ...utils.api_object import APIObject
12
from ...utils.conversion import construct_client_dict
13
from ...utils.types import MISSING
14
15
if TYPE_CHECKING:
16
    from typing import List, Optional
17
18
    from ..message.attachment import Attachment
19
    from ..message.component import MessageComponent
20
    from ..message.embed import Embed
21
    from ..message.user_message import UserMessage
22
    from ..message.user_message import AllowedMentions
23
    from ..user.user import User
24
    from ..guild.guild import Guild
25
    from ..guild.channel import Channel
26
    from ...utils.types import APINullable
27
    from ...utils.snowflake import Snowflake
28
    from ...client import Client
29
30
31
class WebhookCompatibility(Enum):
0 ignored issues
show
introduced by
Missing class docstring
Loading history...
32
    GitHub = "github"
33
    Slack = "slack"
34
    Default = ""
35
36
37
class WebhookType(IntEnum):
38
    """Represents the type of a webhook.
39
40
    Attributes
41
    ----------
42
    INCOMING:
43
        Incoming Webhooks can post messages to channels with a
44
        generated token.
45
    CHANNEL_FOLLOWER:
46
        Channel Follower Webhooks are internal webhooks used with
47
        Channel Following to post new messages into channels.
48
    APPLICATION:
49
        Application webhooks are webhooks used with Interactions
50
    """
51
    INCOMING = 1
52
    CHANNEL_FOLLOWER = 2
53
    APPLICATION = 3
54
55
56
@dataclass
57
class Webhook(APIObject):
0 ignored issues
show
best-practice introduced by
Too many instance attributes (12/7)
Loading history...
58
    """Represents a Discord channel webhook.
59
60
    Attributes
61
    ----------
62
    id: :class:`~pincer.utils.snowflake.Snowflake`
63
        The id of the webhook
64
    type: :class:`~pincer.objects.guild.webhook.WebhookType`
65
        The type of the webhook
66
    channel_id: Optional[:class:`~pincer.utils.snowflake.Snowflake`]
67
        The channel id this webhook is for, if any
68
    name: Optional[:class:`str`]
69
        The default name of the webhook
70
    avatar: Optional[:class:`str`]
71
        The default user avatar hash of the webhook
72
    application_id: Optional[:class:`~pincer.utils.snowflake.Snowflake`]
73
        The bot/OAuth2 application that created this webhook
74
    user: APINullable[:class:`~pincer.objects.user.user.User`]
75
        The user this webhook was created by
76
        (not returned when getting a webhook with its token)
77
    token: APINullable[:class:`str`]
78
        The secure token of the webhook
79
        (returned for Incoming Webhooks)
80
    source_guild: APINullable[:class:`~pincer.objects.guild.guild.Guild`]
81
        The guild of the channel that this webhook is following
82
        (returned for Channel Follower Webhooks)
83
    source_channel: APINullable[:class:`~pincer.objects.guild.channel.Channel`]
84
        The channel that this webhook is following
85
        (returned for Channel Follower Webhooks)
86
    url: APINullable[:class:`str`]
87
        The url used for executing the webhook
88
        (returned by the webhooks OAuth2 flow)
89
    guild_id: APINullable[Optional[:class:`~pincer.objects.guild.guild.Guild`]]
90
        The guild id this webhook is for, if any
91
    """
92
    id: Snowflake
93
    type: WebhookType
94
95
    channel_id: Optional[Snowflake] = None
96
    name: Optional[str] = None
97
    avatar: Optional[str] = None
98
    application_id: Optional[Snowflake] = None
99
100
    user: APINullable[User] = MISSING
101
    token: APINullable[str] = MISSING
102
    source_guild: APINullable[Guild] = MISSING
103
    source_channel: APINullable[Channel] = MISSING
104
    url: APINullable[str] = MISSING
105
106
    guild_id: APINullable[Optional[Snowflake]] = MISSING
107
108
    async def edit(
109
        self,
0 ignored issues
show
Coding Style introduced by
Wrong hanging indentation before block (add 4 spaces).
Loading history...
110
        *,
0 ignored issues
show
Coding Style introduced by
Wrong hanging indentation before block (add 4 spaces).
Loading history...
111
        name: Optional[str] = None,
0 ignored issues
show
Coding Style introduced by
Wrong hanging indentation before block (add 4 spaces).
Loading history...
112
        avatar: Optional[str] = None,
0 ignored issues
show
Coding Style introduced by
Wrong hanging indentation before block (add 4 spaces).
Loading history...
113
        channel_id: Optional[Snowflake] = None,
0 ignored issues
show
Coding Style introduced by
Wrong hanging indentation before block (add 4 spaces).
Loading history...
114
        token: Optional[str] = None
0 ignored issues
show
Coding Style introduced by
Wrong hanging indentation before block (add 4 spaces).
Loading history...
115
    ) -> Webhook:
116
        """
117
        Modifies a webhook and returns it.
118
        Requires the ``MANAGE_WEBHOOKS`` permission.
119
120
        Parameters
121
        ----------
122
        name: Optional[:class:`str`]
123
            The new name of the webhook
124
        avatar: Optional[:class:`str`]
125
            The new avatar hash of the webhook
126
        channel_id: Optional[:class:`~pincer.utils.snowflake.Snowflake`]
127
            The new channel id this webhook is for
128
        token: Optional[:class:`str`]
129
            The new token of the webhook
130
        """
131
        request_route = (
132
            f"webhooks/{self.id}"
133
            + (f"/{token}" if token else "")
134
        )
135
        request_data = {
136
            "name": name,
137
            "avatar": avatar,
138
            "channel_id": channel_id
139
        }
140
141
        if token:
142
            del request_data["channel_id"]
143
144
        data = await self._http.patch(
145
            request_route,
146
            data=request_data
147
        )
148
        return Webhook.from_dict(
149
            construct_client_dict(self._client, data)
150
        )
151
152
    async def delete(self, token: Optional[str] = None):
153
        """
154
        Deletes a webhook.
155
        Requires the ``MANAGE_WEBHOOKS`` permission.
156
157
        Parameters
158
        ----------
159
        token: Optional[:class:`str`]
160
            The token of the webhook
161
        """
162
        await self._http.delete(
163
            f"webhooks/{self.id}"
164
            + (f"/{token}" if token else "")
165
        )
166
167
    @overload
168
    async def execute(
169
        self,
0 ignored issues
show
Coding Style introduced by
Wrong hanging indentation before block (add 4 spaces).
Loading history...
170
        webhook_compatibility: WebhookCompatibility = WebhookCompatibility.Default,  # noqa: E501
0 ignored issues
show
Coding Style introduced by
Wrong hanging indentation before block (add 4 spaces).
Loading history...
171
        *,
0 ignored issues
show
Coding Style introduced by
Wrong hanging indentation before block (add 4 spaces).
Loading history...
172
        thread_id: Optional[Snowflake] = None,
0 ignored issues
show
Coding Style introduced by
Wrong hanging indentation before block (add 4 spaces).
Loading history...
173
        wait: Optional[bool] = None,
0 ignored issues
show
Coding Style introduced by
Wrong hanging indentation before block (add 4 spaces).
Loading history...
174
        content: Optional[str] = None,
0 ignored issues
show
Coding Style introduced by
Wrong hanging indentation before block (add 4 spaces).
Loading history...
175
        username: Optional[str] = None,
0 ignored issues
show
Coding Style introduced by
Wrong hanging indentation before block (add 4 spaces).
Loading history...
176
        avatar_url: Optional[str] = None,
0 ignored issues
show
Coding Style introduced by
Wrong hanging indentation before block (add 4 spaces).
Loading history...
177
        tts: Optional[bool] = None,
0 ignored issues
show
Coding Style introduced by
Wrong hanging indentation before block (add 4 spaces).
Loading history...
178
        embeds: Optional[List[Embed]] = None,
0 ignored issues
show
Coding Style introduced by
Wrong hanging indentation before block (add 4 spaces).
Loading history...
179
        allowed_mentions: Optional[AllowedMentions] = None,
0 ignored issues
show
Coding Style introduced by
Wrong hanging indentation before block (add 4 spaces).
Loading history...
180
        components: Optional[List[MessageComponent]] = None,
0 ignored issues
show
Coding Style introduced by
Wrong hanging indentation before block (add 4 spaces).
Loading history...
181
        files: Optional[str] = None,  # TODO: Add support for files
0 ignored issues
show
Coding Style introduced by
Wrong hanging indentation before block (add 4 spaces).
Loading history...
Coding Style introduced by
TODO and FIXME comments should generally be avoided.
Loading history...
182
        payload_json: Optional[str] = None,
0 ignored issues
show
Coding Style introduced by
Wrong hanging indentation before block (add 4 spaces).
Loading history...
183
        attachments: Optional[List[Attachment]] = None
0 ignored issues
show
Coding Style introduced by
Wrong hanging indentation before block (add 4 spaces).
Loading history...
184
    ):
185
        """|coro|
186
        Executes a webhook.
187
188
        Note that when sending a message, you must provide a value
189
        for at least one of ``content``, ``embeds``, or ``file``.
190
191
        Parameters
192
        ----------
193
        webhook_compatibility: :class:`~pincer.objects.guild.webhook.WebhookCompatibility`
194
            The compatibility of the webhook
195
        thread_id: Optional[:class:`~pincer.utils.snowflake.Snowflake`]
196
            ID of the thread to send message in
197
        wait: Optional[:class:`bool`]
198
            Waits for server confirmation of message send before
199
            response (defaults to ``true``, when ``false`` a message
200
            that is not saved does not return an error)
201
        content: Optional[:class:`str`]
202
            The message contents (up to 2000 characters)
203
        username: Optional[:class:`str`]
204
            Override the default username of the webhook
205
        avatar_url: Optional[:class:`str`]
206
            Override the default avatar of the webhook
207
        tts: Optional[:class:`bool`]
208
            True if this is a TTS message
209
        embeds: Optional[List[:class:`~pincer.objects.message.embed.Embed`]]
210
            Embedded ``rich`` content, up to 10 embeds
211
        allowed_mentions: Optional[:class:`~pincer.objects.message.user_message.AllowedMentions`]
212
            Allowed mentions for the message
213
        components: Optional[List[:class:`~pincer.objects.message.component.MessageComponent`]]
214
            The components to include in the message
215
        files: Optional[:class:`str`]
216
            The contents of the file being sent
217
        payload_json: Optional[:class:`str`]
218
            JSON encoded body of non-file params
219
        attachments: Optional[List[:class:`~pincer.objects.message.attachment.Attachment`]]
220
            Attachment objects with filename and description
221
        """
222
        ...
223
224
    async def execute(
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
225
        self,
0 ignored issues
show
Coding Style introduced by
Wrong hanging indentation before block (add 4 spaces).
Loading history...
226
        webhook_compatibility: WebhookCompatibility = WebhookCompatibility.Default,  # noqa: E501
0 ignored issues
show
Coding Style introduced by
Wrong hanging indentation before block (add 4 spaces).
Loading history...
227
        *,
0 ignored issues
show
Coding Style introduced by
Wrong hanging indentation before block (add 4 spaces).
Loading history...
228
        thread_id: Optional[Snowflake] = None,
0 ignored issues
show
Coding Style introduced by
Wrong hanging indentation before block (add 4 spaces).
Loading history...
229
        wait: Optional[bool] = None,
0 ignored issues
show
Coding Style introduced by
Wrong hanging indentation before block (add 4 spaces).
Loading history...
230
        **kwargs
0 ignored issues
show
Coding Style introduced by
Wrong hanging indentation before block (add 4 spaces).
Loading history...
231
    ):
232
        if len(kwargs.get("embeds", [])) > 10:
233
            raise EmbedOverflow("You can only include up to 10 embeds")
234
235
        request_route = f"webhooks/{self.id}/{self.token}"
236
237
        # Adding the subdirectory
238
        if webhook_compatibility.value:
239
            request_route += f"/{webhook_compatibility.value}"
240
241
        # Adding query params
242
        if wait is not None:
243
            request_route += f"?{wait=}"
244
        if thread_id is not None:
245
            request_route += "&?"[wait is None] + f"{thread_id=}"
246
247
        if webhook_compatibility == WebhookCompatibility.Default:
248
            request_data = kwargs
249
        else:
250
            request_data = None
251
252
        await self._http.post(request_route, data=request_data)
253
254
    async def execute_github(
255
        self,
0 ignored issues
show
Coding Style introduced by
Wrong hanging indentation before block (add 4 spaces).
Loading history...
256
        *,
0 ignored issues
show
Coding Style introduced by
Wrong hanging indentation before block (add 4 spaces).
Loading history...
257
        thread_id: Optional[Snowflake] = None,
0 ignored issues
show
Coding Style introduced by
Wrong hanging indentation before block (add 4 spaces).
Loading history...
258
        wait: Optional[bool] = None
0 ignored issues
show
Coding Style introduced by
Wrong hanging indentation before block (add 4 spaces).
Loading history...
259
    ):
260
        """|coro|
261
        Executes a GitHub compatible webhook.
262
263
        Parameters
264
        ----------
265
        thread_id: Optional[:class:`~pincer.utils.snowflake.Snowflake`]
266
            ID of the thread to send message in
267
        wait: Optional[:class:`bool`]
268
            Waits for server confirmation of message send before
269
            response (defaults to ``true``, when ``false`` a message
270
            that is not saved does not return an error)
271
        """
272
        await self.execute(
273
            WebhookCompatibility.GitHub,
274
            thread_id=thread_id,
275
            wait=wait
276
        )
277
278
    async def execute_slack(
279
        self,
0 ignored issues
show
Coding Style introduced by
Wrong hanging indentation before block (add 4 spaces).
Loading history...
280
        *,
0 ignored issues
show
Coding Style introduced by
Wrong hanging indentation before block (add 4 spaces).
Loading history...
281
        thread_id: Optional[Snowflake] = None,
0 ignored issues
show
Coding Style introduced by
Wrong hanging indentation before block (add 4 spaces).
Loading history...
282
        wait: Optional[bool] = None
0 ignored issues
show
Coding Style introduced by
Wrong hanging indentation before block (add 4 spaces).
Loading history...
283
    ):
284
        """|coro|
285
        Executes a Slack compatible webhook.
286
287
        Parameters
288
        ----------
289
        thread_id: Optional[:class:`~pincer.utils.snowflake.Snowflake`]
290
            ID of the thread to send message in
291
        wait: Optional[:class:`bool`]
292
            Waits for server confirmation of message send before
293
            response (defaults to ``true``, when ``false`` a message
294
            that is not saved does not return an error)
295
        """
296
        await self.execute(
297
            WebhookCompatibility.Slack,
298
            thread_id=thread_id,
299
            wait=wait
300
        )
301
302
    async def get_message(
303
        self,
0 ignored issues
show
Coding Style introduced by
Wrong hanging indentation before block (add 4 spaces).
Loading history...
304
        message_id: Snowflake,
0 ignored issues
show
Coding Style introduced by
Wrong hanging indentation before block (add 4 spaces).
Loading history...
305
        thread_id: Snowflake
0 ignored issues
show
Coding Style introduced by
Wrong hanging indentation before block (add 4 spaces).
Loading history...
306
    ) -> UserMessage:
307
        """|coro|
308
        Returns a previously-sent webhook message from the same token.
309
310
        Parameters
311
        ----------
312
        message_id: :class:`~pincer.utils.snowflake.Snowflake`
313
            The ID of the message to get
314
        thread_id: :class:`~pincer.utils.snowflake.Snowflake`
315
            The ID of the thread to get the message from
316
317
        Returns
318
        -------
319
        :class:`~pincer.objects.message.message.Message`
320
            The message
321
        """
322
        return UserMessage.from_dict(
323
            construct_client_dict(
324
                self._client,
325
                await self._http.get(
326
                    f"webhooks/{self.id}/{self.token}/messages/{message_id}"
327
                    + (f"?{thread_id=}" if thread_id else "")
328
                )
329
            )
330
        )
331
332
    async def delete_message(
333
        self,
0 ignored issues
show
Coding Style introduced by
Wrong hanging indentation before block (add 4 spaces).
Loading history...
334
        message_id: Snowflake,
0 ignored issues
show
Coding Style introduced by
Wrong hanging indentation before block (add 4 spaces).
Loading history...
335
        thread_id: Snowflake
0 ignored issues
show
Coding Style introduced by
Wrong hanging indentation before block (add 4 spaces).
Loading history...
336
    ):
337
        """|coro|
338
        Deletes a message created by a webhook.
339
340
        Parameters
341
        ----------
342
        message_id: :class:`~pincer.utils.snowflake.Snowflake`
343
            The ID of the message to delete
344
        thread_id: :class:`~pincer.utils.snowflake.Snowflake`
345
            The ID of the thread to delete the message from
346
        """
347
        await self._http.delete(
348
            f"webhooks/{self.id}/{self.token}/messages/{message_id}"
349
            + (f"?{thread_id=}" if thread_id else "")
350
        )
351
352
    @overload
353
    async def edit_message(
354
        self,
0 ignored issues
show
Coding Style introduced by
Wrong hanging indentation before block (add 4 spaces).
Loading history...
355
        message_id: Snowflake,
0 ignored issues
show
Coding Style introduced by
Wrong hanging indentation before block (add 4 spaces).
Loading history...
356
        *,
0 ignored issues
show
Coding Style introduced by
Wrong hanging indentation before block (add 4 spaces).
Loading history...
357
        thread_id: Optional[Snowflake] = None,
0 ignored issues
show
Coding Style introduced by
Wrong hanging indentation before block (add 4 spaces).
Loading history...
358
        content: Optional[str] = None,
0 ignored issues
show
Coding Style introduced by
Wrong hanging indentation before block (add 4 spaces).
Loading history...
359
        embeds: Optional[List[Embed]] = None,
0 ignored issues
show
Coding Style introduced by
Wrong hanging indentation before block (add 4 spaces).
Loading history...
360
        allowed_mentions: Optional[AllowedMentions] = None,
0 ignored issues
show
Coding Style introduced by
Wrong hanging indentation before block (add 4 spaces).
Loading history...
361
        components: Optional[List[MessageComponent]] = None,
0 ignored issues
show
Coding Style introduced by
Wrong hanging indentation before block (add 4 spaces).
Loading history...
362
        files: Optional[str] = None,  # TODO: Add support for files
0 ignored issues
show
Coding Style introduced by
Wrong hanging indentation before block (add 4 spaces).
Loading history...
Coding Style introduced by
TODO and FIXME comments should generally be avoided.
Loading history...
363
        payload_json: Optional[str] = None,
0 ignored issues
show
Coding Style introduced by
Wrong hanging indentation before block (add 4 spaces).
Loading history...
364
        attachments: Optional[List[Attachment]] = None
0 ignored issues
show
Coding Style introduced by
Wrong hanging indentation before block (add 4 spaces).
Loading history...
365
    ) -> UserMessage:
366
        """|coro|
367
        Edits a previously-sent webhook message from the same token.
368
369
        Parameters
370
        ----------
371
        message_id: :class:`~pincer.utils.snowflake.Snowflake`
372
            The ID of the message to edit
373
        thread_id: Optional[:class:`~pincer.utils.snowflake.Snowflake`]
374
            ID of the thread the message is in
375
        content: Optional[:class:`str`]
376
            The new content of the message (up to 2000 characters)
377
        embeds: Optional[List[:class:`~pincer.objects.message.embed.Embed`]]
378
            Embedded ``rich`` content, up to 10 embeds
379
        allowed_mentions: Optional[:class:`~pincer.objects.message.user_message.AllowedMentions`]
380
            Allowed mentions for the message
381
        components: Optional[List[:class:`~pincer.objects.message.component.MessageComponent`]]
382
            The components to include in the message
383
        files: Optional[:class:`str`]
384
            The contents of the file being sent/edited
385
        payload_json: Optional[:class:`str`]
386
            JSON encoded body of non-file params
387
            (multipart/form-data only)
388
        attachments: Optional[List[:class:`~pincer.objects.message.attachment.Attachment`]]
389
            Attached files to keep and
390
            possible descriptions for new files
391
        """
392
        ...
393
394
    async def edit_message(
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
395
        self,
0 ignored issues
show
Coding Style introduced by
Wrong hanging indentation before block (add 4 spaces).
Loading history...
396
        message_id: Snowflake,
0 ignored issues
show
Coding Style introduced by
Wrong hanging indentation before block (add 4 spaces).
Loading history...
397
        *,
0 ignored issues
show
Coding Style introduced by
Wrong hanging indentation before block (add 4 spaces).
Loading history...
398
        thread_id: Optional[Snowflake] = None,
0 ignored issues
show
Coding Style introduced by
Wrong hanging indentation before block (add 4 spaces).
Loading history...
399
        **kwargs
0 ignored issues
show
Coding Style introduced by
Wrong hanging indentation before block (add 4 spaces).
Loading history...
400
    ) -> UserMessage:
401
        if len(kwargs.get("embeds", [])) > 10:
402
            raise EmbedOverflow("You can only include up to 10 embeds")
403
404
        data = await self._http.patch(
405
            f"webhooks/{self.id}/{self.token}/messages/{message_id}"
406
            + (f"?{thread_id=}" if thread_id else ""),
407
            data=kwargs
408
        )
409
        return UserMessage.from_dict(
410
            construct_client_dict(self._client, data)
411
        )
412
413
    @classmethod
414
    async def from_id(
415
        cls,
0 ignored issues
show
Coding Style introduced by
Wrong hanging indentation before block (add 4 spaces).
Loading history...
416
        client: Client,
0 ignored issues
show
Coding Style introduced by
Wrong hanging indentation before block (add 4 spaces).
Loading history...
417
        id: Snowflake,
0 ignored issues
show
Coding Style introduced by
Wrong hanging indentation before block (add 4 spaces).
Loading history...
Bug Best Practice introduced by
This seems to re-define the built-in id.

It is generally discouraged to redefine built-ins as this makes code very hard to read.

Loading history...
418
        token: Optional[str] = None
0 ignored issues
show
Coding Style introduced by
Wrong hanging indentation before block (add 4 spaces).
Loading history...
419
    ) -> Webhook:
420
        """|coro|
421
        Gets a webhook by its ID.
422
423
        Parameters
424
        ----------
425
        client: `~pincer.client.Client`
426
            The client to use to make the request.
427
        id: `~pincer.utils.snowflake.Snowflake`
428
            The ID of the webhook to get.
429
        token: Optional[:class:`str`]
430
            The token of the webhook to get.
431
432
        Returns
433
        -------
434
        `~pincer.objects.guild.webhook.Webhook`
435
            The webhook with the given ID.
436
        """
437
        return cls.from_dict(
438
            construct_client_dict(
439
                client,
440
                await client.http.get(
441
                    f"webhooks/{id}"
442
                    + (f"/{token}" if token else "")
443
                )
444
            )
445
        )
446