Passed
Pull Request — main (#275)
by
unknown
01:42
created

pincer.objects.guild.guild.Guild.edit_template()   A

Complexity

Conditions 1

Size

Total Lines 36
Code Lines 13

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 13
dl 0
loc 36
rs 9.75
c 0
b 0
f 0
cc 1
nop 5
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 dataclasses import dataclass, field
7
from enum import IntEnum
8
from typing import AsyncGenerator, overload, TYPE_CHECKING
9
10
from .invite import Invite
11
from .channel import Channel
12
from ..message.emoji import Emoji
13
from ..message.file import File
14
from ...exceptions import UnavailableGuildError
15
from ...utils.api_object import APIObject
16
from ...utils.conversion import construct_client_dict, remove_none
17
from ...utils.types import MISSING
18
19
20
if TYPE_CHECKING:
21
    from typing import Any, Dict, List, Optional, Tuple, Union, Generator
22
    from .channel import PublicThread, PrivateThread, ChannelType
23
24
    from .audit_log import AuditLog
25
    from .ban import Ban
26
    from .member import GuildMember
27
    from .features import GuildFeature
28
    from .overwrite import Overwrite
29
    from .role import Role
30
    from .stage import StageInstance
31
    from .template import GuildTemplate
32
    from .welcome_screen import WelcomeScreen, WelcomeScreenChannel
33
    from .widget import GuildWidget
34
    from .webhook import Webhook
35
    from ..user.user import User
36
    from ..user.integration import Integration
37
    from ..voice.region import VoiceRegion
38
    from ..events.presence import PresenceUpdateEvent
39
    from ..message.sticker import Sticker
40
    from ..user.voice_state import VoiceState
41
    from ...client import Client
42
    from ...utils.timestamp import Timestamp
43
    from ...utils.types import APINullable, JSONSerializable
44
    from ...utils.snowflake import Snowflake
45
46
47
class PremiumTier(IntEnum):
48
    """Represents the boost tier of a guild.
49
    Attributes
50
    ----------
51
    NONE:
52
        Guild has not unlocked any Server Boost perks.
53
    TIER_1:
54
        Guild has unlocked Server Boost level 1 perks.
55
    TIER_2:
56
        Guild has unlocked Server Boost level 2 perks.
57
    TIER_3:
58
        Guild has unlocked Server Boost level 3 perks.
59
    """
60
61
    NONE = 0
62
    TIER_1 = 1
63
    TIER_2 = 2
64
    TIER_3 = 3
65
66
67
class GuildNSFWLevel(IntEnum):
68
    """Represents the NSFW level of a guild.
69
    Attributes
70
    ----------
71
    DEFAULT:
72
        Default NSFW level.
73
    EXPLICIT:
74
        Explicit NSFW level.
75
    SAFE:
76
        SAFE NSFW level.
77
    AGE_RESTRICTED:
78
        Age restricted NSFW level.
79
    """
80
81
    DEFAULT = 0
82
    EXPLICIT = 1
83
    SAFE = 2
84
    AGE_RESTRICTED = 3
85
86
87
class ExplicitContentFilterLevel(IntEnum):
88
    """Represents the filter content level of a guild.
89
    Attributes
90
    ----------
91
    DISABLED:
92
        Media content will not be scanned.
93
    MEMBERS_WITHOUT_ROLES:
94
        Media content sent by members without roles will be scanned.
95
    ALL_MEMBERS:
96
        Media content sent by all members will be scanned.
97
    """
98
99
    DISABLED = 0
100
    MEMBERS_WITHOUT_ROLES = 1
101
    ALL_MEMBERS = 2
102
103
104
class MFALevel(IntEnum):
105
    """Represents the multi factor authentication level of a guild.
106
    Attributes
107
    ----------
108
    NONE:
109
        Guild has no MFA/2FA requirement for moderation actions.
110
    ELEVATED:
111
        Guild has a 2FA requirement for moderation actions
112
    """
113
114
    NONE = 0
115
    ELEVATED = 1
116
117
118
class VerificationLevel(IntEnum):
119
    """Represents the verification level of a guild.
120
    Attributes
121
    ----------
122
    NONE:
123
        Unrestricted.
124
    LOW:
125
        Must have verified email on account.
126
    MEDIUM:
127
        Must be registered on Discord for longer than 5 minutes.
128
    HIGH:
129
        Must be a member of the server for longer than 10 minutes.
130
    VERY_HIGH:
131
        Must have a verified phone number.
132
    """
133
134
    NONE = 0
135
    LOW = 1
136
    MEDIUM = 2
137
    HIGH = 3
138
    VERY_HIGH = 4
139
140
141
class DefaultMessageNotificationLevel(IntEnum):
142
    """Represents the default message notification level of a guild.
143
    Attributes
144
    ----------
145
    ALL_MESSAGES:
146
        Members will receive notifications for all messages by default.
147
    ONLY_MENTIONS:
148
        Members will receive notifications only for messages that @mention them by default.
149
    """
150
151
    # noqa: E501
152
    ALL_MESSAGES = 0
153
    ONLY_MENTIONS = 1
154
155
156
class SystemChannelFlags(IntEnum):
157
    """Represents the system channel flags of a guild.
158
    Attributes
159
    ----------
160
    SUPPRESS_JOIN_NOTIFICATIONS:
161
        Suppress member join notifications.
162
    SUPPRESS_PREMIUM_SUBSCRIPTIONS:
163
        Suppress server boost notifications.
164
    SUPPRESS_GUILD_REMINDER_NOTIFICATIONS:
165
        Suppress server setup tips.
166
    SUPPRESS_JOIN_NOTIFICATION_REPLIES:
167
        Hide member join sticker reply buttons
168
    """
169
170
    SUPPRESS_JOIN_NOTIFICATIONS = 1 << 0
171
    SUPPRESS_PREMIUM_SUBSCRIPTIONS = 1 << 1
172
    SUPPRESS_GUILD_REMINDER_NOTIFICATIONS = 1 << 2
173
    SUPPRESS_JOIN_NOTIFICATION_REPLIES = 1 << 3
174
175
176
@dataclass(repr=False)
177
class GuildPreview(APIObject):
178
    """Represents a guild preview.
179
    Attributes
180
    ----------
181
    id: :class:`Snowflake`
182
        The guild ID.
183
    name: :class:`str`
184
        The guild name.
185
    icon: :class:`str`
186
        The guild icon hash.
187
    splash: :class:`str`
188
        The guild splash hash.
189
    discovery_splash: :class:`str`
190
        The guild discovery splash hash.
191
    emojis: :class:`List[Emoji]`
192
        The guild emojis.
193
    features: :class:`List[GuildFeature]`
194
        The guild features.
195
    approximate_member_count: :class:`int`
196
        The approximate member count.
197
    approximate_presence_count: :class:`int`
198
        The approximate number of online members in this guild
199
    description: :class:`str`
200
        The guild description.
201
    """
202
203
    id: Snowflake
204
    name: str
205
    emojis: List[Emoji]
206
    features: List[GuildFeature]
207
    approximate_member_count: int
208
    approximate_presence_count: int
209
210
    icon: APINullable[str] = MISSING
211
    splash: APINullable[str] = MISSING
212
    discovery_splash: APINullable[str] = MISSING
213
    description: APINullable[str] = MISSING
214
215
216
@dataclass(repr=False)
217
class Guild(APIObject):
218
    """Represents a Discord guild/server in which your client resides.
219
    Attributes
220
    ----------
221
    afk_channel_id: Optional[:class:`~pincer.utils.snowflake.Snowflake`]
222
        Id of afk channel
223
    afk_timeout: :class:`int`
224
        Afk timeout in seconds
225
    application_id: Optional[:class:`~pincer.utils.snowflake.Snowflake`]
226
        Application id of the guild creator if it is bot-created
227
    banner: Optional[:class:`str`]
228
        Banner hash
229
    default_message_notifications: :class:`~pincer.objects.guild.guild.DefaultMessageNotificationLevel`
230
        Default message notifications level
231
    description: Optional[:class:`str`]
232
        The description of a Community guild
233
    discovery_splash: Optional[:class:`str`]
234
        Discovery splash hash;
235
        only present for guilds with the "DISCOVERABLE" feature
236
    emojis: List[:class:`~pincer.objects.message.emoji.Emoji`]
237
        Custom guild emojis
238
    explicit_content_filter: :class:`~pincer.objects.guild.guild.ExplicitContentFilterLevel`
239
        Explicit content filter level
240
    features: List[:class:`~pincer.objects.guild.features.GuildFeature`]
241
        Enabled guild features
242
    id: :class:`~pincer.utils.snowflake.Snowflake`
243
        Guild id
244
    icon: Optional[:class:`str`]
245
        Icon hash
246
    mfa_level: :class:`~pincer.objects.guild.guild.MFALevel`
247
        Required MFA level for the guild
248
    name: :class:`str`
249
        Guild name (2-100 characters, excluding trailing and leading
250
        whitespace)
251
    nsfw_level: :class:`~pincer.objects.guild.guild.NSFWLevel`
252
        Guild NSFW level
253
    owner_id: :class:`~pincer.utils.snowflake.Snowflake`
254
        Id of owner
255
    preferred_locale: :class:`str`
256
        The preferred locale of a Community guild;
257
        used in server discovery and notices from Discord;
258
        defaults to "en-US"
259
    premium_tier: :class:`~pincer.objects.guild.guild.PremiumTier`
260
        Premium tier (Server Boost level)
261
    public_updates_channel_id: Optional[:class:`~pincer.utils.snowflake.Snowflake`]
262
        The id of the channel where admins
263
        and moderators of Community guilds receive notices from Discord
264
    roles: List[:class:`~pincer.objects.guild.role.Role`]
265
        Roles in the guild
266
    rules_channel_id: Optional[:class:`~pincer.utils.snowflake.Snowflake`]
267
        The id of the channel where Community guilds can display rules
268
        and/or guidelines
269
    splash: Optional[:class:`str`]
270
        Splash hash
271
    system_channel_flags: :class:`~pincer.objects.guild.guild.SystemChannelFlags`
272
        System channel flags
273
    system_channel_id: Optional[:class:`~pincer.utils.snowflake.Snowflake`]
274
        The id of the channel where guild notices
275
        such as welcome messages and boost events are posted
276
    vanity_url_code: Optional[:class:`str`]
277
        The vanity url code for the guild
278
    verification_level: :class:`~pincer.objects.guild.guild.VerificationLevel`
279
        Verification level required for the guild
280
    approximate_member_count: APINullable[:class:`int`]
281
        Approximate number of members in this guild, returned from the
282
        `GET /guilds/<id>` endpoint when with_counts is true
283
    approximate_presence_count: APINullable[:class:`int`]
284
        Approximate number of non-offline members in this guild,
285
        returned from the `GET /guilds/<id>`
286
        endpoint when with_counts is true
287
    channels: APINullable[List[:class:`~pincer.objects.guild.channel.Channel`]]
288
        Channels in the guild
289
    icon_hash: APINullable[Optional[:class:`str`]]
290
        Icon hash, returned when in the template object
291
    joined_at: APINullable[:class:`~pincer.utils.timestamp.Timestamp`]
292
        When this guild was joined at
293
    large: APINullable[:class:`bool`]
294
        True if this is considered a large guild
295
    max_members: APINullable[:class:`int`]
296
        The maximum number of members for the guild
297
    max_presences: APINullable[Optional[:class:`int`]]
298
        The maximum number of presences for the guild
299
        (null is always returned, apart from the largest of guilds)
300
    max_video_channel_users: APINullable[:class:`int`]
301
        The maximum amount of users in a video channel
302
    members: APINullable[List[:class:`~pincer.objects.guild.member.GuildMember`]]
303
        Users in the guild
304
    member_count: APINullable[:class:`bool`]
305
        Total number of members in this guild
306
    nsfw: APINullable[:class:`bool`]
307
        Boolean if the server is NSFW
308
    owner: APINullable[:class:`bool`]
309
        True if the user is the owner of the guild
310
    permissions: APINullable[:class:`str`]
311
        Total permissions for the user in the guild
312
        (excludes overwrites)
313
    premium_subscription_count: APINullable[:class:`int`]
314
        The number of boosts this guild currently has
315
    presences: APINullable[List[:class:`~pincer.objects.events.presence.PresenceUpdateEvent`]]
316
        Presences of the members in the guild,
317
        will only include non-offline members if the size is greater
318
        than large threshold
319
    stage_instances: APINullable[List[:class:`~pincer.objects.guild.stage.StageInstance`]]
320
        Stage instances in the guild
321
    stickers: Optional[List[:class:`~pincer.objects.message.sticker.Sticker`]]
322
        Custom guild stickers
323
    region: APINullable[Optional[:class:`str`]]
324
        Voice region id for the guild (deprecated)
325
    threads: APINullable[List[:class:`~pincer.objects.guild.channel.Channel`]]
326
        All active threads in the guild that current user
327
        has permission to view
328
    unavailable: APINullable[:class:`bool`]
329
        True if this guild is unavailable due to an outage
330
    voice_states: APINullable[List[:class:`~pincer.objects.user.voice_state.VoiceState`]]
331
        States of members currently in voice channels;
332
        lacks the guild_id key
333
    widget_enabled: APINullable[:class:`bool`]
334
        True if the server widget is enabled
335
    widget_channel_id: APINullable[Optional[:class:`~pincer.utils.snowflake.Snowflake`]]
336
        The channel id that the widget will generate an invite to,
337
        or null if set to no invite
338
    welcome_screen: APINullable[:class:`~pincer.objects.guild.welcome_screen.WelcomeScreen`]
339
        The welcome screen of a Community guild, shown to new members,
340
        returned in an Invite's guild object
341
    """
342
343
    # noqa: E501
344
    features: List[GuildFeature]
345
    id: Snowflake
346
    name: str
347
    nsfw_level: GuildNSFWLevel
348
    verification_level: VerificationLevel
349
350
    # Guild invites missing
351
    system_channel_flags: APINullable[SystemChannelFlags] = MISSING
352
    explicit_content_filter: APINullable[ExplicitContentFilterLevel] = MISSING
353
    premium_tier: APINullable[PremiumTier] = MISSING
354
    default_message_notifications: APINullable[DefaultMessageNotificationLevel] = MISSING
355
    mfa_level: APINullable[MFALevel] = MISSING
356
    owner_id: APINullable[Snowflake] = MISSING
357
    afk_timeout: APINullable[int] = MISSING
358
    emojis: APINullable[List[Emoji]] = MISSING
359
    preferred_locale: APINullable[str] = MISSING
360
    roles: APINullable[List[Role]] = MISSING
361
362
    guild_scheduled_events: APINullable[List] = MISSING
363
    lazy: APINullable[bool] = MISSING
364
    premium_progress_bar_enabled: APINullable[bool] = MISSING
365
    guild_hashes: APINullable[Dict] = MISSING
366
    afk_channel_id: APINullable[Snowflake] = MISSING
367
    application_id: APINullable[Snowflake] = MISSING
368
    embedded_activities: APINullable[List] = MISSING
369
    banner: APINullable[str] = MISSING
370
    description: APINullable[str] = MISSING
371
    discovery_splash: APINullable[str] = MISSING
372
    icon: APINullable[str] = MISSING
373
    public_updates_channel_id: APINullable[Snowflake] = MISSING
374
    rules_channel_id: APINullable[Snowflake] = MISSING
375
    splash: APINullable[str] = MISSING
376
    system_channel_id: APINullable[Snowflake] = MISSING
377
    vanity_url_code: APINullable[str] = MISSING
378
379
    application_command_counts: APINullable[Dict] = MISSING
380
    application_command_count: APINullable[int] = MISSING
381
    approximate_member_count: APINullable[int] = MISSING
382
    approximate_presence_count: APINullable[int] = MISSING
383
    channels: APINullable[List[Channel]] = field(default_factory=list)
384
    # TODO: Add type when type is known
385
    hub_type: APINullable[Any] = MISSING
386
    icon_hash: APINullable[Optional[str]] = MISSING
387
    joined_at: APINullable[Timestamp] = MISSING
388
    large: APINullable[bool] = MISSING
389
    max_members: APINullable[int] = MISSING
390
    max_presences: APINullable[Optional[int]] = MISSING
391
    max_video_channel_users: APINullable[int] = MISSING
392
    members: APINullable[List[GuildMember]] = MISSING
393
    member_count: APINullable[bool] = MISSING
394
    nsfw: APINullable[bool] = MISSING
395
    # Note: This is missing from discord's docs but in the api
396
    owner: APINullable[bool] = MISSING
397
    permissions: APINullable[str] = MISSING
398
    premium_subscription_count: APINullable[int] = MISSING
399
    presences: APINullable[List[PresenceUpdateEvent]] = MISSING
400
    stage_instances: APINullable[List[StageInstance]] = MISSING
401
    stickers: APINullable[List[Sticker]] = MISSING
402
    region: APINullable[Optional[str]] = MISSING
403
    threads: APINullable[List[Channel]] = MISSING
404
    # Guilds are considered available unless otherwise specified
405
    unavailable: APINullable[bool] = False
406
    voice_states: APINullable[List[VoiceState]] = MISSING
407
    widget_enabled: APINullable[bool] = MISSING
408
    widget_channel_id: APINullable[Optional[Snowflake]] = MISSING
409
    welcome_screen: APINullable[WelcomeScreen] = MISSING
410
411
    @classmethod
412
    async def from_id(cls, client: Client, _id: Union[int, Snowflake]) -> Guild:
413
        """
414
        Parameters
415
        ----------
416
        client : :class:`~pincer.Client`
417
            Client object to use the http gateway from.
418
        _id : :class:`pincer.utils.snowflake.Snowflake`
419
            Guild ID.
420
        Returns
421
        -------
422
        :class:`~pincer.objects.guild.guild.Guild`
423
            The new guild object.
424
        """
425
        data = await client.http.get(f"/guilds/{_id}")
426
        channel_data = await client.http.get(f"/guilds/{_id}/channels")
427
428
        data["channels"]: List[Channel] = [
429
            Channel.from_dict(construct_client_dict(client, i))
430
            for i in (channel_data or [])
431
        ]
432
433
        return Guild.from_dict(construct_client_dict(client, data))
434
435
    async def get_member(self, _id: int) -> GuildMember:
436
        """|coro|
437
        Fetches a GuildMember from its identifier
438
439
        Parameters
440
        ----------
441
        _id: int
442
            The id of the guild member which should be fetched from the Discord
443
            gateway.
444
        Returns
445
        -------
446
        :class:`~pincer.objects.guild.member.GuildMember`
447
            A GuildMember object.
448
        """
449
        return await GuildMember.from_id(self._client, self.id, _id)
450
451
    @overload
452
    async def modify_member(
453
        self,
454
        *,
455
        _id: int,
456
        nick: Optional[str] = None,
457
        roles: Optional[List[Snowflake]] = None,
458
        mute: Optional[bool] = None,
459
        deaf: Optional[bool] = None,
460
        channel_id: Optional[Snowflake] = None,
461
        reason: Optional[str] = None
462
    ) -> GuildMember:
463
        """|coro|
464
        Modifies a member in the guild from its identifier and based on the
465
        keyword arguments provided.
466
        Parameters
467
        ----------
468
        _id : int
469
            Id of the member to modify
470
        nick : Optional[:class:`str`]
471
            New nickname for the member |default| :data:`None`
472
        roles : Optional[List[:class:`~pincer.utils.snowflake.Snowflake]]
473
            New roles for the member |default| :data:`None`
474
        mute : Optional[:class:`bool`]
475
            Whether the member is muted |default| :data:`None`
476
        deaf : Optional[:class:`bool`]
477
            Whether the member is deafened |default| :data:`None`
478
        channel_id : Optional[:class:`~pincer.utils.snowflake.Snowflake]
479
            Voice channel id to move to |default| :data:`None`
480
        reason : Optional[:class:`str`]
481
            audit log reason |default| :data:`None`
482
            
483
        Returns
484
        -------
485
        :class:`~pincer.objects.guild.member.GuildMember`
486
            The new member object.
487
        """
488
        ...
489
490
    async def modify_member(self, _id: int, reason=None, **kwargs) -> GuildMember:
491
        data = await self._http.patch(
492
            f"guilds/{self.id}/members/{_id}",
493
            data=kwargs,
494
            headers=remove_none({"X-Audit-Log-Reason":reason))
0 ignored issues
show
introduced by
closing parenthesis ')' does not match opening parenthesis '{' (<unknown>, line 494)
Loading history...
495
        )
496
        return GuildMember.from_dict(construct_client_dict(self._client, data))
497
498
      
499
    @overload
500
    async def create_channel(
501
        self, 
502
        name: str,               
503
        type: Optional[ChannelType] = None,
504
        topic: Optional[str] = None,
505
        bitrate: Optional[int] = None,
506
        user_limit: Optional[int] = None,
507
        rate_limit_per_user: Optional[int] = None,
508
        position: Optional[int] = None,
509
        permission_overwrites: Optional[List[Overwrite]] = None,
510
        parent_id: Optional[Snowflake] = None,
511
        nsfw: Optional[bool] = None
512
    ) -> Channel:
513
        """|coro|
514
        Create a new channel object for the guild.
515
516
        Parameters
517
        ----------
518
        name : str
519
            channel name (1-100 characters)
520
        type : Optional[:class:int`]
521
            the type of channel
522
        topic : Optional[:class:str`]
523
            channel topic (0-1024 characters)
524
        bitrate : Optional[:class:`int`]
525
            the bitrate (in bits) of the voice channel (voice only)
526
        user_limit : Optional[:class:`int`]
527
            the user limit of the voice channel (voice only)
528
        rate_limit_per_user : Optional[:class:`int`]
529
            amount of seconds a user has to wait before sending another message (0-21600)
530
            bots, as well as users with the permission manage_messages or manage_channel, are unaffected
531
        position : Optional[:class:`int`]
532
            sorting position of the channel
533
        permission_overwrites : Optional[List[:class:`~pincer.objects.guild.overwrite.Overwrite`]]
534
            the channel's permission overwrites
535
        parent_id : Optional[:class:`~pincer.utils.snowflake.Snowflake`]
536
            id of the parent category for a channel
537
        nsfw : Optional[:class:`bool`]
538
            whether the channel is nsfw
539
        reason : Optional[:class:`str`]
540
            audit log reason |default| :data:`None`
541
        Returns
542
        -------
543
        :class:`~pincer.objects.guild.channel.Channel`
544
            The new channel object.
545
        """
546
        ...
547
548
    async def create_channel(
549
        self,
550
        reason: Optional[str] = None,
551
        **kwargs
552
    ):
553
        data = await self._http.post(
554
            f"guilds/{self.id}/channels",
555
            data=kwargs,
556
            headers=remove_none({"X-Audit-Log-Reason":reason))
557
        )
558
        return Channel.from_dict(construct_client_dict(self._client, data))
559
560
    async def modify_channel_positions(
561
        self, 
562
        reason: Optional[str] = None,
563
        *channel: Dict[str, Optional[Union[int, bool, Snowflake]]]
564
    ):
565
        """|coro|
566
        Create a new channel object for the guild.
567
568
        Parameters
569
        ----------
570
        reason : Optional[:class:`str`]
571
            audit log reason |default| :data:`None`
572
        \\*channel : Dict[str, Optional[Union[int, bool, :class:`~pincer.utils.snowflake.Snowflake`]
573
            Keys:
574
                - id : :class:`~pincer.utils.snowflake.Snowflake`
575
                - position : Optional[:class:`int`]
576
                - lock_permissions : Optional[:class:`bool`]
577
                - parent_id : Optional[:class:`~pincer.utils.snowflake.Snowflake`]
578
        """
579
        await self._http.patch(
580
            f"guilds/{self.id}/channels",
581
            data=channel,
582
            headers=remove_none({"X-Audit-Log-Reason":reason))
583
        )
584
585
    async def list_active_threads(self) -> Tuple[
586
        Generator[Union[PublicThread, PrivateThread]], Generator[GuildMember]]:
587
        """|coro|
588
        Returns all active threads in the guild, including public and private threads.
589
        
590
        Returns
591
        -------
592
        Generator[Union[:class:`~pincer.objects.guild.channel.PublicThread`, :class:`~pincer.objects.guild.channel.PrivateThread`]], Generator[:class:`~pincer.objects.guild.member.GuildMember`]]
593
            The new member object.
594
        """
595
        data = await self._http.get(f"guilds/{self.id}/threads/active")
596
597
        threads = (
598
            Channel.from_dict(construct_client_dict(self._client, data))
599
            for channel in data["threads"]
600
        )
601
        members = (
602
            GuildMember.from_dict(construct_client_dict(self._client, data))
603
            for member in data["members"]
604
        )
605
606
        return threads, members
607
608
    async def list_guild_members(self, limit: int = 1, after: int = 0):
609
        """|coro|
610
        Returns a list of guild member objects that are members of the guild.
611
612
        Parameters
613
        ----------
614
        limit : int
615
            max number of members to return (1-1000) |default| :data:`1`
616
        after : int
617
            the highest user id in the previous page |default| :data:`0`
618
        """
619
620
        members = await self._http.get(
621
            f"guilds/{self.id}/members?{limit=!s}&{after=!s}"
622
        )
623
        
624
        return (GuildMember.from_dict(construct_client_dict(self._client, data)) for member in members)
625
626
    async def search_guild_members(
627
        self, 
628
        query: str,
629
        limit: Optional[int] = None
630
    ) -> List[GuildMember]:
631
        """|coro|
632
        Returns a list of guild member objects whose username or nickname starts with a provided string.
633
634
        Parameters
635
        ----------
636
        query : str
637
            Query string to match username(s) and nickname(s) against.
638
        limit : Optional[int]
639
            max number of members to return (1-1000) |default| :data:`1`
640
        Returns
641
        -------
642
        List[:class:`~pincer.objects.guild.member.GuildMember`]
643
            list of guild member objects
644
        """
645
646
        data = await self._http.get(
647
            f"guilds/{id}/members/search?{query=!s}"
648
            f"&{limit}" if limit else ""
649
        )
650
651
        return (GuildMember.from_dict(member) for member in data)
652
653
    @overload
654
    async def add_guild_member(
655
        self, *,
656
        user_id: Snowflake,
657
        access_token: str,
658
        nick: Optional[str] = None,
659
        roles: Optional[List[Snowflake]] = None,
660
        mute: Optional[bool] = None,
661
        deaf: Optional[bool] = None,
662
        reason: Optional[str] = None,
663
    ) -> Optional[GuildMember]:
664
        """|coro|
665
        Adds a user to the guild, provided you have a valid oauth2 access token for the user with the guilds.join scope.
666
667
        Parameters
668
        ----------
669
        user_id : str
670
            id of the user to be added
671
        access_token : str
672
            an oauth2 access token granted with the guilds.join to 
673
            the bot's application for the user you want to add to the guild
674
        nick : Optional[str]
675
        	value to set users nickname to
676
        roles : Optional[List[:class:`~pincer.utils.snowflake.Snowflake`]]
677
        	array of role ids the member is assigned
678
        mute : Optional[bool]
679
        	whether the user is muted in voice channels
680
        deaf : Optional[bool]
681
        	whether the user is deafened in voice channels
682
        reason : Optional[:class:`str`]
683
            audit log reason |default| :data:`None`
684
        Returns
685
        -------
686
        :class:`~pincer.objects.guild.member.GuildMember`
687
            If the user is not in the guild
688
        None
689
            If the user is in the guild
690
        """
691
692
    async def add_guild_member(
693
        self,
694
        user_id, 
695
        reason=None, 
696
        **kwargs
697
    ):
698
        data = await self._http.put(
699
            f"guilds/{self.id}/members/{user_id}", 
700
            data=kwargs,
701
            headers=remove_none({"X-Audit-Log-Reason":reason))
702
        )
703
704
        return GuildMember.from_dict(data) if data else None
705
706
    async def modify_current_member(
707
        self, 
708
        nick: str, 
709
        reason: Optional[str] = None
710
    ) -> GuildMember:
711
        """|coro|
712
        Modifies the current member in a guild.
713
714
        Parameters
715
        ----------
716
        nick : str
717
            value to set users nickname to
718
        reason : Optional[:class:`str`]
719
            audit log reason |default| :data:`None`
720
        Returns
721
        -------
722
        class:`~pincer.objects.guild.member.GuildMember
723
            current guild member
724
        """
725
        data = self._http.patch(
726
            f"guilds/{self.id}/members/@me", 
727
            {"nick": nick}, 
728
            headers=remove_none({"X-Audit-Log-Reason":reason))
729
        )
730
        return GuildMember.from_dict(construct_client_dict(self._client, data))
731
732
    async def add_guild_member_role(
733
        self,
734
        user_id: int,
735
        role_id: int,
736
        reason: Optional[str] = None
737
    ) -> None:
738
        """|coro|
739
        Adds a role to a guild member.
740
741
        Parameters
742
        ----------
743
        user_id : int
744
            id of the user to give a role to
745
        role_id : int
746
            id of a role
747
        reason : Optional[:class:`str`]
748
            audit log reason |default| :data:`None`
749
        """
750
        data = await self._http.put(
751
            f"guilds/{self.id}/{user_id}/roles/{role_id}",
752
            headers=remove_none({"X-Audit-Log-Reason":reason))
753
        )
754
755
    async def remove_guild_member_role(
756
        self, 
757
        user_id: int,
758
        role_id: int
759
    ) -> None:
760
        """|coro|
761
        Removes a role from a guild member.
762
763
        Parameters
764
        ----------
765
        user_id : int
766
            id of the user to remove a role from
767
        role_id : int
768
            id of a role
769
        reason : Optional[:class:`str`]
770
            audit log reason |default| :data:`None`
771
        """
772
        await self._http.delete(
773
            f"guilds/{self.id}/{user_id}/roles/{role_id}",
774
            headers=remove_none({"X-Audit-Log-Reason":reason))
775
        )
776
777
    async def remove_guild_member(
778
        self,
779
        user_id: int,
780
        reason: Optional[str] = None
781
    ) -> None:
782
        """|coro|
783
        Remove a member from a guild.
784
785
        Parameters
786
        ----------
787
        user_id : int
788
            id of the user to remove from the guild
789
        reason : Optional[:class:`str`]
790
            audit log reason |default| :data:`None`
791
        """
792
        await self._http.delete(
793
            f"guilds/{self.id}/members/{user_id}",
794
            headers=remove_none({"X-Audit-Log-Reason":reason))
795
        )
796
797
    async def ban(
798
        self,
799
        member_id: int,
800
        reason: str = None,
801
        delete_message_days: int = None
802
    ):
803
        """
804
        Parameters
805
        ----------
806
        member_id : :class:`int`
807
            ID of the guild member to ban.
808
        reason : Optional[:class:`str`]
809
            Reason for the kick.
810
        delete_message_days : Optional[:class:`int`]
811
            Number of days to delete messages for (0-7)
812
        """
813
        headers = {}
814
815
        if reason is not None:
816
            headers["X-Audit-Log-Reason"] = reason
817
818
        data = {}
819
820
        if delete_message_days is not None:
821
            data["delete_message_days"] = delete_message_days
822
823
        await self._http.put(
824
            f"/guilds/{self.id}/bans/{member_id}",
825
            data=data,
826
            headers=headers
827
        )
828
829
    async def kick(self, member_id: int, reason: Optional[str] = None):
830
        """|coro|
831
        Kicks a guild member.
832
        Parameters
833
        ----------
834
        member_id : :class:`int`
835
            ID of the guild member to kick.
836
        reason : Optional[:class:`str`]
837
            Reason for the kick.
838
        """
839
840
        headers = {}
841
842
        if reason is not None:
843
            headers["X-Audit-Log-Reason"] = reason
844
845
        await self._http.delete(
846
            f"/guilds/{self.id}/members/{member_id}",
847
            header=headers
848
        )
849
850
    async def get_roles(self) -> AsyncGenerator[Role, None]:
851
        """|coro|
852
        Fetches all the roles in the guild.
853
854
        Yields
855
        -------
856
        AsyncGenerator[:class:`~pincer.objects.guild.role.Role`, :data:`None`]
857
            An async generator of Role objects.
858
        """
859
        data = await self._http.get(f"guilds/{self.id}/roles")
860
        for role_data in data:
861
            yield Role.from_dict(construct_client_dict(self._client, role_data))
862
863
    @overload
864
    async def create_role(
865
        self,
866
        reason: Optional[str] = None,
867
        *,
868
        name: Optional[str] = "new role",
869
        permissions: Optional[str] = None,
870
        color: Optional[int] = 0,
871
        hoist: Optional[bool] = False,
872
        icon: Optional[str] = None,
873
        unicode_emoji: Optional[str] = None,
874
        mentionable: Optional[bool] = False,
875
    ) -> Role:
876
        """|coro|
877
        Creates a new role for the guild.
878
        Requires the ``MANAGE_ROLES`` permission.
879
880
        Parameters
881
        ----------
882
        reason : Optional[:class:`str`]
883
            Reason for creating the role. |default| :data:`None`
884
        name : Optional[:class:`str`]
885
            name of the role |default| :data:`"new role"`
886
        permissions : Optional[:class:`str`]
887
            bitwise value of the enabled/disabled
888
            permissions, set to @everyone permissions
889
            by default |default| :data:`None`
890
        color : Optional[:class:`int`]
891
            RGB color value |default| :data:`0`
892
        hoist : Optional[:class:`bool`]
893
            whether the role should be displayed
894
            separately in the sidebar |default| :data:`False`
895
        icon : Optional[:class:`str`]
896
            the role's icon image (if the guild has
897
            the ``ROLE_ICONS`` feature) |default| :data:`None`
898
        unicode_emoji : Optional[:class:`str`]
899
            the role's unicode emoji as a standard emoji (if the guild
900
            has the ``ROLE_ICONS`` feature) |default| :data:`None`
901
        mentionable : Optional[:class:`bool`]
902
            whether the role should be mentionable |default| :data:`False`
903
904
        Returns
905
        -------
906
        :class:`~pincer.objects.guild.role.Role`
907
            The new role object.
908
        """
909
        ...
910
911
    async def create_role(
912
        self,
913
        reason: Optional[str] = None,
914
        **kwargs
915
    ) -> Role:
916
        return Role.from_dict(
917
            construct_client_dict(
918
                self._client,
919
                await self._http.post(
920
                    f"guilds/{self.id}/roles",
921
                    data=kwargs,
922
                    headers=remove_none({"X-Audit-Log-Reason": reason})
923
                ),
924
            )
925
        )
926
927
    async def edit_role_position(
928
        self,
929
        id: Snowflake,
930
        reason: Optional[str] = None,
931
        position: Optional[int] = None
932
    ) -> AsyncGenerator[Role, None]:
933
        """|coro|
934
        Edits the position of a role.
935
936
        Parameters
937
        ----------
938
        id : :class:`~pincer.utils.snowflake.Snowflake`
939
            The role ID
940
        reason : Optional[:class:`str`]
941
            Reason for editing the role position. |default| :data:`None`
942
        position : Optional[:class:`int`]
943
            Sorting position of the role |default| :data:`None`
944
945
        Yields
946
        -------
947
        AsyncGenerator[:class:`~pincer.objects.guild.role.Role`, :data:`None`]
948
            An async generator of all of the guild's role objects.
949
        """
950
        data = await self._http.patch(
951
            f"guilds/{self.id}/roles",
952
            data={"id": id, "position": position},
953
            headers=remove_none({"X-Audit-Log-Reason": reason})
954
        )
955
        for role_data in data:
956
            yield Role.from_dict(construct_client_dict(self._client, role_data))
957
958
    @overload
959
    async def edit_role(
960
        self,
961
        id: Snowflake,
962
        reason: Optional[str] = None,
963
        *,
964
        name: Optional[str] = None,
965
        permissions: Optional[str] = None,
966
        color: Optional[int] = None,
967
        hoist: Optional[bool] = None,
968
        icon: Optional[str] = None,
969
        unicode_emoji: Optional[str] = None,
970
        mentionable: Optional[bool] = None,
971
    ) -> Role:
972
        """|coro|
973
        Edits a role.
974
        Requires the ``MANAGE_ROLES`` permission.
975
976
        Parameters
977
        ----------
978
        id : :class:`~pincer.utils.snowflake.Snowflake`
979
            The role ID
980
        reason : Optional[:class:`str`]
981
            Reason for editing the role |default| :data:`None`
982
        name : Optional[:class:`str`]
983
            Name of the role |default| :data:`None`
984
        permissions : Optional[:class:`str`]
985
            Bitwise value of the enabled/disabled
986
            permissions |default| :data:`None`
987
        color : Optional[:class:`int`]
988
            RGB color value |default| :data:`None`
989
        hoist : Optional[:class:`bool`]
990
            Whether the role should be displayed
991
            separately in the sidebar |default| :data:`None`
992
        icon : Optional[:class:`str`]
993
            The role's icon image (if the guild has
994
            the ``ROLE_ICONS`` feature) |default| :data:`None`
995
        unicode_emoji : Optional[:class:`str`]
996
            The role's unicode emoji as a standard emoji (if the guild
997
            has the ``ROLE_ICONS`` feature) |default| :data:`None`
998
        mentionable : Optional[:class:`bool`]
999
            Whether the role should be mentionable |default| :data:`None`
1000
1001
        Returns
1002
        -------
1003
        :class:`~pincer.objects.guild.role.Role`
1004
            The edited role object.
1005
        """
1006
        ...
1007
1008
    async def edit_role(
1009
        self,
1010
        id: Snowflake,
1011
        reason: Optional[str] = None,
1012
        **kwargs
1013
    ) -> Role:
1014
        return Role.from_dict(
1015
            construct_client_dict(
1016
                self._client,
1017
                await self._http.patch(
1018
                    f"guilds/{self.id}/roles/{id}",
1019
                    data=kwargs,
1020
                    headers=remove_none({"X-Audit-Log-Reason": reason})
1021
                ),
1022
            )
1023
        )
1024
1025
    async def delete_role(self, id: Snowflake, reason: Optional[str] = None):
1026
        """|coro|
1027
        Deletes a role.
1028
        Requires the `MANAGE_ROLES` permission.
1029
1030
        Parameters
1031
        ----------
1032
        id : :class:`~pincer.utils.snowflake.Snowflake`
1033
            The role ID
1034
        reason : Optional[:class:`str`]
1035
            The reason for deleting the role |default| :data:`None`
1036
        """
1037
        await self._http.delete(
1038
            f"guilds/{self.id}/roles/{id}",
1039
            headers=remove_none({"X-Audit-Log-Reason": reason})
1040
        )
1041
1042
    async def get_bans(self) -> AsyncGenerator[Ban, None]:
1043
        """|coro|
1044
        Fetches all the bans in the guild.
1045
1046
        Yields
1047
        -------
1048
        AsyncGenerator[:class:`~pincer.objects.guild.ban.Ban`, :data:`None`]
1049
            An async generator of Ban objects.
1050
        """
1051
        data = await self._http.get(f"guilds/{self.id}/bans")
1052
        for ban_data in data:
1053
            yield Ban.from_dict(construct_client_dict(self._client, ban_data))
1054
1055
    async def get_ban(self, id: Snowflake) -> Ban:
1056
        """|coro|
1057
        Fetches a ban from the guild.
1058
1059
        Parameters
1060
        ----------
1061
        id : :class:`~pincer.utils.snowflake.Snowflake`
1062
            The user ID
1063
1064
        Returns
1065
        -------
1066
        :class:`~pincer.objects.guild.ban.Ban`
1067
            The Ban object.
1068
        """
1069
        return Ban.from_dict(
1070
            construct_client_dict(
1071
                self._client,
1072
                await self._http.get(f"guilds/{self.id}/bans/{id}"),
1073
            )
1074
        )
1075
1076
    async def unban(self, id: Snowflake, reason: Optional[str] = None):
1077
        """|coro|
1078
        Unbans a user from the guild.
1079
1080
        Parameters
1081
        ----------
1082
        id : :class:`~pincer.utils.snowflake.Snowflake`
1083
            The user ID
1084
        reason : Optional[:class:`str`]
1085
            The reason for unbanning the user |default| :data:`None`
1086
        """
1087
        await self._http.delete(
1088
            f"guilds/{self.id}/bans/{id}",
1089
            headers=remove_none({"X-Audit-Log-Reason": reason})
1090
        )
1091
1092
    @overload
1093
    async def edit(
1094
        self,
1095
        *,
1096
        name: Optional[str] = None,
1097
        region: Optional[str] = None,
1098
        verification_level: Optional[int] = None,
1099
        default_message_notifications: Optional[int] = None,
1100
        explicit_content_filter: Optional[int] = None,
1101
        afk_channel_id: Optional[Snowflake] = None,
1102
        afk_timeout: Optional[int] = None,
1103
        icon: Optional[str] = None,
1104
        owner_id: Optional[Snowflake] = None,
1105
        splash: Optional[str] = None,
1106
        discovery_splash: Optional[str] = None,
1107
        banner: Optional[str] = None,
1108
        system_channel_id: Optional[Snowflake] = None,
1109
        system_channel_flags: Optional[int] = None,
1110
        rules_channel_id: Optional[Snowflake] = None,
1111
        public_updates_channel_id: Optional[Snowflake] = None,
1112
        preferred_locale: Optional[str] = None,
1113
        features: Optional[List[GuildFeature]] = None,
1114
        description: Optional[str] = None,
1115
    ) -> Guild:
1116
        """|coro|
1117
        Modifies the guild
1118
1119
        Parameters
1120
        ----------
1121
        name : Optional[:class:`str`]
1122
            Guild name |default| :data:`None`
1123
        region : Optional[:class:`str`]
1124
            Guild voice region ID |default| :data:`None`
1125
        verification_level : Optional[:class:`int`]
1126
            Verification level |default| :data:`None`
1127
        default_message_notifications : Optional[:class:`int`]
1128
            Default message notification level |default| :data:`None`
1129
        explicit_content_filter : Optional[:class:`int`]
1130
            Explicit content filter level |default| :data:`None`
1131
        afk_channel_id : Optional[:class:`~pincer.utils.snowflake.Snowflake`]
1132
            ID for AFK channel |default| :data:`None`
1133
        afk_timeout : Optional[:class:`int`]
1134
            AFK timeout in seconds |default| :data:`None`
1135
        icon : Optional[:class:`str`]
1136
            base64 1024x1024 png/jpeg/gif image for the guild icon
1137
            (can be animated gif when the server
1138
            has the `ANIMATED_ICON` feature) |default| :data:`None`
1139
        owner_id : Optional[:class:`~pincer.utils.snowflake.Snowflake`]
1140
            User ID to transfer guild ownership to (must be owner) |default| :data:`None`
1141
        splash : Optional[:class:`str`]
1142
            base64 16:9 png/jpeg image for the guild splash (when the
1143
            server has the `INVITE_SPLASH` feature) |default| :data:`None`
1144
        discovery_splash : Optional[:class:`str`]
1145
            base64 16:9 png/jpeg image for the guild discovery splash
1146
            (when the server has the `DISCOVERABLE` feature) |default| :data:`None`
1147
        banner : Optional[:class:`str`]
1148
            base64 16:9 png/jpeg image for the guild banner (when the
1149
            server has the `BANNER` feature) |default| :data:`None`
1150
        system_channel_id : Optional[:class:`~pincer.utils.snowflake.Snowflake`]
1151
            The ID of the channel where guild notices such as welcome
1152
            messages and boost events are posted |default| :data:`None`
1153
        system_channel_flags : Optional[:class:`int`]
1154
            System channel flags |default| :data:`None`
1155
        rules_channel_id : Optional[:class:`~pincer.utils.snowflake.Snowflake`]
1156
            The ID of the channel where Community guilds display rules
1157
            and/or guidelines |default| :data:`None`
1158
        public_updates_channel_id : Optional[:class:`~pincer.utils.snowflake.Snowflake`]
1159
            The ID of the channel where admins and moderators of
1160
            Community guilds receive notices from Discord |default| :data:`None`
1161
        preferred_locale : Optional[:class:`str`]
1162
            The preferred locale of a Community guild used in server
1163
            discovery and notices from Discord; defaults to "en-US" |default| :data:`None`
1164
        features : Optional[List[:class:`GuildFeature`]]
1165
            Enabled guild features |default| :data:`None`
1166
        description : Optional[:class:`str`]
1167
            The description for the guild, if the guild is discoverable |default| :data:`None`
1168
1169
        Returns
1170
        -------
1171
        :class:`~pincer.objects.guild.Guild`
1172
            The modified guild object.
1173
        """
1174
        ...
1175
1176
    async def edit(self, **kwargs) -> Guild:
1177
        g = await self._http.patch(f"guilds/{self.id}", data=kwargs)
1178
        return Guild.from_dict(construct_client_dict(self._client, g))
1179
1180
    async def preview(self) -> GuildPreview:
1181
        """|coro|
1182
        Previews the guild.
1183
1184
        Returns
1185
        -------
1186
        :class:`~pincer.objects.guild.guild.GuildPreview`
1187
            The guild preview object.
1188
        """
1189
        data = await self._http.get(f"guilds/{self.id}/preview")
1190
        return GuildPreview.from_dict(data)
1191
1192
    async def delete(self):
1193
        """|coro|
1194
        Deletes the guild. Returns `204 No Content` on success.
1195
        """
1196
        await self._http.delete(f"guilds/{self.id}")
1197
1198
    async def prune_count(
1199
        self,
1200
        days: Optional[int] = 7,
1201
        include_roles: Optional[str] = None
1202
    ) -> int:
1203
        """|coro|
1204
        Returns the number of members that
1205
        would be removed in a prune operation.
1206
        Requires the ``KICK_MEMBERS`` permission.
1207
1208
        Parameters
1209
        ----------
1210
        days : Optional[:class:`int`]
1211
            Number of days to count prune for (1-30) |default| :data:`7`
1212
        include_roles : Optional[:class:`str`]
1213
            Comma-delimited array of Snowflakes;
1214
            role(s) to include |default| :data:`None`
1215
1216
        Returns
1217
        -------
1218
        :class:`int`
1219
            The number of members that would be removed.
1220
        """
1221
        return await self._http.get(
1222
            f"guilds/{self.id}/prune?{days=}&{include_roles=!s}"
1223
        )["pruned"]
1224
1225
    async def prune(
1226
        self,
1227
        days: Optional[int] = 7,
1228
        compute_prune_days: Optional[bool] = True,
1229
        include_roles: Optional[List[Snowflake]] = None,
1230
        reason: Optional[str] = None
1231
    ) -> int:
1232
        """|coro|
1233
        Prunes members from the guild. Requires the ``KICK_MEMBERS`` permission.
1234
1235
        Parameters
1236
1237
        Parameters
1238
        ----------
1239
        days : Optional[:class:`int`]
1240
            Number of days to prune (1-30) |default| :data:`7`
1241
        compute_prune_days : Optional[:class:`bool`]
1242
            Whether ``pruned`` is returned, discouraged for large guilds
1243
            |default| :data:`True`
1244
        include_roles : Optional[List[:class:`~pincer.utils.snowflake.Snowflake`]]
1245
            role(s) to include |default| :data:`None`
1246
        reason : Optional[:class:`str`]
1247
            Reason for the prune |default| :data:`None`
1248
1249
        Returns
1250
        -------
1251
        :class:`int`
1252
            The number of members that were removed.
1253
        """
1254
        return await self._http.post(
1255
            f"guilds/{self.id}/prune",
1256
            data={
1257
                "days": days,
1258
                "compute_prune_days": compute_prune_days,
1259
                "include_roles": include_roles
1260
            },
1261
            headers=remove_none({"X-Audit-Log-Reason": reason})
1262
        )["pruned"]
1263
1264
    async def get_voice_regions(self) -> AsyncGenerator[VoiceRegion, None]:
1265
        """|coro|
1266
        Returns an async generator of voice regions.
1267
1268
        Yields
1269
        -------
1270
        AsyncGenerator[:class:`~pincer.objects.voice.VoiceRegion`, :data:`None`]
1271
            An async generator of voice regions.
1272
        """
1273
        data = await self._http.get(f"guilds/{self.id}/regions")
1274
        for voice_region_data in data:
1275
            yield VoiceRegion.from_dict(construct_client_dict(self._client, voice_region_data))
1276
1277
    async def get_invites(self) -> AsyncGenerator[Invite, None]:
1278
        """|coro|
1279
        Returns an async generator of invites for the guild.
1280
        Requires the ``MANAGE_GUILD`` permission.
1281
1282
        Yields
1283
        -------
1284
        AsyncGenerator[:class:`~pincer.objects.invite.Invite`, :data:`None`]
1285
            An async generator of invites.
1286
        """
1287
        data = await self._http.get(f"guilds/{self.id}/invites")
1288
        for invite_data in data:
1289
            yield Invite.from_dict(construct_client_dict(self._client, invite_data))
1290
1291
    async def get_integrations(self) -> AsyncGenerator[Integration, None]:
1292
        """|coro|
1293
        Returns an async generator of integrations for the guild.
1294
        Requires the ``MANAGE_GUILD`` permission.
1295
1296
        Yields
1297
        -------
1298
        AsyncGenerator[:class:`~pincer.objects.integration.Integration`, :data:`None`]
1299
            An async generator of integrations.
1300
        """
1301
        data = await self._http.get(f"guilds/{self.id}/integrations")
1302
        for integration_data in data:
1303
            yield Integration.from_dict(construct_client_dict(self._client, integration_data))
1304
1305
    async def delete_integration(
1306
        self,
1307
        integration: Integration,
1308
        reason: Optional[str] = None
1309
    ):
1310
        """|coro|
1311
        Deletes an integration.
1312
        Requires the ``MANAGE_GUILD`` permission.
1313
1314
        Parameters
1315
        ----------
1316
        integration : :class:`~pincer.objects.integration.Integration`
1317
            The integration to delete.
1318
        reason : Optional[:class:`str`]
1319
            Reason for the deletion |default| :data:`None`
1320
        """
1321
        await self._http.delete(
1322
            f"guilds/{self.id}/integrations/{integration.id}",
1323
            headers=remove_none({"X-Audit-Log-Reason": reason})
1324
        )
1325
1326
    async def get_widget_settings(self) -> GuildWidget:
1327
        """|coro|
1328
        Returns the guild widget settings.
1329
        Requires the ``MANAGE_GUILD`` permission.
1330
1331
        Returns
1332
        -------
1333
        :class:`~pincer.objects.guild.widget.GuildWidget`
1334
            The guild widget settings.
1335
        """
1336
        return GuildWidget.from_dict(
1337
            construct_client_dict(
1338
                self._client,
1339
                await self._http.get(f"guilds/{self.id}/widget")
1340
            )
1341
        )
1342
1343
    async def modify_widget(
1344
        self,
1345
        reason: Optional[str] = None,
1346
        **kwargs
1347
    ) -> GuildWidget:
1348
        """|coro|
1349
        Modifies the guild widget for the guild.
1350
        Requires the ``MANAGE_GUILD`` permission.
1351
1352
        Parameters
1353
        ----------
1354
        reason : Optional[:class:`str`]
1355
            Reason for the modification |default| :data:`None`
1356
        \\*\\*kwargs
1357
            The widget settings to modify
1358
1359
        Returns
1360
        -------
1361
        :class:`~pincer.objects.guild.widget.GuildWidget`
1362
            The updated GuildWidget object
1363
        """
1364
        data = await self._http.patch(
1365
            f"guilds/{self.id}/widget",
1366
            data=kwargs,
1367
            headers=remove_none({"X-Audit-Log-Reason": reason})
1368
        )
1369
        return GuildWidget.from_dict(construct_client_dict(self._client, data))
1370
1371
    async def get_widget(self) -> Dict[str, JSONSerializable]:
1372
        """|coro|
1373
        Returns the widget for the guild
1374
        """
1375
        return await self._http.get(f"guilds/{self.id}/widget.json")
1376
1377
    @property
1378
    async def vanity_url(self) -> Invite:
1379
        """|coro|
1380
        Returns the Vanity URL for the guild.
1381
        Requires the ``MANAGE_GUILD`` permission.
1382
        ``code`` will be null if a vanity URL has not been set.
1383
1384
        Returns
1385
        -------
1386
        :class:`~pincer.objects.guild.invite.Invite`
1387
            The vanity url for the guild.
1388
        """
1389
        data = await self._http.get(f"guilds/{self.id}/vanity-url")
1390
        return Invite.from_dict(construct_client_dict(self._client, data))
1391
1392
    async def get_widget_image(self, style: Optional[str] = "shield") -> str:  # TODO Replace str with ImageURL object
1393
        """|coro|
1394
        Returns a PNG image widget for the guild.
1395
        Requires no permissions or authentication.
1396
1397
        Widget Style Options
1398
        -------------------
1399
        * [``shield``](https://discord.com/api/guilds/81384788765712384/widget.png?style=shield)
1400
          shield style widget with Discord icon and guild members online count
1401
        * [``banner1``](https://discord.com/api/guilds/81384788765712384/widget.png?style=banner1)
1402
          large image with guild icon, name and online count.
1403
          "POWERED BY DISCORD" as the footer of the widget
1404
        * [``banner2``](https://discord.com/api/guilds/81384788765712384/widget.png?style=banner2)
1405
          smaller widget style with guild icon, name and online count.
1406
          Split on the right with Discord logo
1407
        * [``banner3``](https://discord.com/api/guilds/81384788765712384/widget.png?style=banner3)
1408
          large image with guild icon, name and online count.
1409
          In the footer, Discord logo on the
1410
          left and "Chat Now" on the right
1411
        * [``banner4``](https://discord.com/api/guilds/81384788765712384/widget.png?style=banner4)
1412
          large Discord logo at the top of the widget.
1413
          Guild icon, name and online count in the middle portion
1414
          of the widget and a "JOIN MY SERVER" button at the bottom
1415
1416
        Parameters
1417
        ----------
1418
        style : Optional[:class:`str`]
1419
            Style of the widget image returned |default| :data:`"shield"`
1420
1421
        Returns
1422
        -------
1423
        :class:`str`
1424
            A PNG image of the guild widget.
1425
        """
1426
        return await self._http.get(f"guilds/{self.id}/widget.png?{style=!s}")
1427
1428
    async def get_welcome_screen(self) -> WelcomeScreen:
1429
        """Returns the welcome screen for the guild.
1430
1431
        Returns
1432
        -------
1433
        :class:`~pincer.objects.guild.welcome_screen.WelcomeScreen`
1434
            The welcome screen for the guild.
1435
        """
1436
        data = await self._http.get(f"guilds/{self.id}/welcome-screen")
1437
        return WelcomeScreen.from_dict(construct_client_dict(self._client, data))
1438
1439
    async def modify_welcome_screen(
1440
        self,
1441
        enabled: Optional[bool] = None,
1442
        welcome_channels: Optional[List[WelcomeScreenChannel]] = None,
1443
        description: Optional[str] = None,
1444
        reason: Optional[str] = None
1445
    ) -> WelcomeScreen:
1446
        """|coro|
1447
        Modifies the guild's Welcome Screen.
1448
        Requires the ``MANAGE_GUILD`` permission.
1449
1450
        Parameters
1451
        ----------
1452
        enabled : Optional[:class:`bool`]
1453
            Whether the welcome screen is enabled |default| :data:`None`
1454
        welcome_channels : Optional[List[:class:`~pincer.objects.guild.welcome_screen.WelcomeScreenChannel`]]
1455
            Channels linked in the welcome screen and
1456
            their display options |default| :data:`None`
1457
        description : Optional[:class:`str`]
1458
            The server description to show
1459
            in the welcome screen |default| :data:`None`
1460
        reason : Optional[:class:`str`]
1461
            Reason for the modification |default| :data:`None`
1462
1463
        Returns
1464
        -------
1465
        :class:`~pincer.objects.guild.welcome_screen.WelcomeScreen`
1466
            The updated WelcomeScreen object
1467
        """
1468
        data = await self._http.patch(
1469
            f"guilds/{self.id}/welcome-screen",
1470
            data={
1471
                "enabled": enabled,
1472
                "welcome_channels": welcome_channels,
1473
                "description": description
1474
            },
1475
            headers=remove_none({"X-Audit-Log-Reason": reason})
1476
        )
1477
        return WelcomeScreen.from_dict(construct_client_dict(self._client, data))
1478
1479
    async def modify_current_user_voice_state(
1480
        self,
1481
        channel_id: Snowflake,
1482
        suppress: Optional[bool] = None,
1483
        request_to_speak_timestamp: Optional[Timestamp] = None
1484
    ):
1485
        """|coro|
1486
        Updates the current user's voice state.
1487
1488
        There are currently several caveats for this endpoint:
1489
        * ``channel_id`` must currently point to a stage channel
1490
        * current user must already have joined ``channel_id``
1491
        * You must have the ``MUTE_MEMBERS`` permission to
1492
          unsuppress yourself. You can always suppress yourself.
1493
        * You must have the ``REQUEST_TO_SPEAK`` permission to request
1494
          to speak. You can always clear your own request to speak.
1495
        * You are able to set ``request_to_speak_timestamp`` to any
1496
          present or future time.
1497
1498
        Parameters
1499
        ----------
1500
        channel_id : :class:`~pincer.utils.snowflake.Snowflake`
1501
            The ID of the channel the user is currently in
1502
        suppress : Optional[:class:`bool`]
1503
            Toggles the user's suppress state |default| :data:`None`
1504
        request_to_speak_timestamp : Optional[:class:`~pincer.utils.timestamp.Timestamp`]
1505
            Sets the user's request to speak
1506
        """
1507
        await self._http.patch(
1508
            f"guilds/{self.id}/voice-states/@me",
1509
            data={
1510
                "channel_id": channel_id,
1511
                "suppress": suppress,
1512
                "request_to_speak_timestamp": request_to_speak_timestamp
1513
            }
1514
        )
1515
1516
    async def modify_user_voice_state(
1517
        self,
1518
        user: User,
1519
        channel_id: Snowflake,
1520
        suppress: Optional[bool] = None
1521
    ):
1522
        """|coro|
1523
        Updates another user's voice state.
1524
1525
        There are currently several caveats for this endpoint:
1526
        * ``channel_id`` must currently point to a stage channel
1527
        * User must already have joined ``channel_id``
1528
        * You must have the ``MUTE_MEMBERS`` permission.
1529
          (Since suppression is the only thing that is available currently.)
1530
        * When unsuppressed, non-bot users will have their
1531
          ``request_to_speak_timestamp`` set to the current time.
1532
          Bot users will not.
1533
        * When suppressed, the user will have their
1534
          ``request_to_speak_timestamp`` removed.
1535
1536
        Parameters
1537
        ----------
1538
        user : :class:`~pincer.objects.guild.member.Member`
1539
            The user to update
1540
        channel_id : :class:`~pincer.utils.snowflake.Snowflake`
1541
            The ID of the channel the user is currently in
1542
        suppress : Optional[:class:`bool`]
1543
            Toggles the user's suppress state |default| :data:`None`
1544
        """
1545
        await self._http.patch(
1546
            f"guilds/{self.id}/voice-states/{user.id}",
1547
            data={
1548
                "channel_id": channel_id,
1549
                "suppress": suppress
1550
            }
1551
        )
1552
1553
    async def get_audit_log(self) -> AuditLog:
1554
        """|coro|
1555
        Returns an audit log object for the guild.
1556
        Requires the ``VIEW_AUDIT_LOG`` permission.
1557
1558
        Returns
1559
        -------
1560
        :class:`~pincer.objects.guild.audit_log.AuditLog`
1561
            The audit log object for the guild.
1562
        """
1563
        return AuditLog.from_dict(
1564
            construct_client_dict(
1565
                self._client,
1566
                await self._http.get(f"guilds/{self.id}/audit-logs")
1567
            )
1568
        )
1569
1570
    async def get_emojis(self) -> AsyncGenerator[Emoji, None]:
1571
        """|coro|
1572
        Returns an async generator of the emojis in the guild.
1573
1574
        Yields
1575
        ------
1576
        :class:`~pincer.objects.guild.emoji.Emoji`
1577
            The emoji object.
1578
        """
1579
        data = await self._http.get(f"guilds/{self.id}/emojis")
1580
        for emoji_data in data:
1581
            yield Emoji.from_dict(
1582
                construct_client_dict(self._client, emoji_data)
1583
            )
1584
1585
    async def get_emoji(self, id: Snowflake) -> Emoji:
1586
        """|coro|
1587
        Returns an emoji object for the given ID.
1588
1589
        Parameters
1590
        ----------
1591
        id : :class:`~pincer.utils.snowflake.Snowflake`
1592
            The ID of the emoji
1593
1594
        Returns
1595
        -------
1596
        :class:`~pincer.objects.guild.emoji.Emoji`
1597
            The emoji object.
1598
        """
1599
        return Emoji.from_dict(
1600
            construct_client_dict(
1601
                self._client,
1602
                await self._http.get(f"guilds/{self.id}/emojis/{id}")
1603
            )
1604
        )
1605
1606
    async def create_emoji(
1607
        self,
1608
        *,
1609
        name: str,
1610
        image: File,
1611
        roles: List[Snowflake] = [],
1612
        reason: Optional[str] = None
1613
    ) -> Emoji:
1614
        """|coro|
1615
        Creates a new emoji for the guild.
1616
        Requires the ``MANAGE_EMOJIS_AND_STICKERS`` permission.
1617
1618
        Emojis and animated emojis have a maximum file size of 256kb.
1619
        Attempting to upload an emoji larger than this limit will fail.
1620
1621
        Parameters
1622
        ----------
1623
        name : :class:`str`
1624
            Name of the emoji
1625
        image : :class:`~pincer.objects.message.file.File`
1626
            The File for the 128x128 emoji image data
1627
        roles : List[:class:`~pincer.utils.snowflake.Snowflake`]
1628
            Roles allowed to use this emoji |default| :data:`[]`
1629
        reason : Optional[:class:`str`]
1630
            The reason for creating the emoji |default| :data:`None`
1631
1632
        Returns
1633
        -------
1634
        :class:`~pincer.objects.guild.emoji.Emoji`
1635
            The newly created emoji object.
1636
        """
1637
        data = await self._http.post(
1638
            f"guilds/{self.id}/emojis",
1639
            data={
1640
                "name": name,
1641
                "image": image.uri,
1642
                "roles": roles
1643
            },
1644
            headers=remove_none({"X-Audit-Log-Reason": reason})
1645
        )
1646
        return Emoji.from_dict(
1647
            construct_client_dict(self._client, data)
1648
        )
1649
1650
    async def edit_emoji(
1651
        self,
1652
        id: Snowflake,
1653
        *,
1654
        name: Optional[str] = None,
1655
        roles: Optional[List[Snowflake]] = None,
1656
        reason: Optional[str] = None
1657
    ) -> Emoji:
1658
        """|coro|
1659
        Modifies the given emoji.
1660
        Requires the ``MANAGE_EMOJIS_AND_STICKERS`` permission.
1661
1662
        Parameters
1663
        ----------
1664
        id : :class:`~pincer.utils.snowflake.Snowflake`
1665
            The ID of the emoji
1666
        name : Optional[:class:`str`]
1667
            Name of the emoji |default| :data:`None`
1668
        roles : Optional[List[:class:`~pincer.utils.snowflake.Snowflake`]]
1669
            Roles allowed to use this emoji |default| :data:`None`
1670
        reason : Optional[:class:`str`]
1671
            The reason for editing the emoji |default| :data:`None`
1672
1673
        Returns
1674
        -------
1675
        :class:`~pincer.objects.guild.emoji.Emoji`
1676
            The modified emoji object.
1677
        """
1678
        data = await self._http.patch(
1679
            f"guilds/{self.id}/emojis/{id}",
1680
            data={
1681
                "name": name,
1682
                "roles": roles
1683
            },
1684
            headers=remove_none({"X-Audit-Log-Reason": reason})
1685
        )
1686
        return Emoji.from_dict(
1687
            construct_client_dict(self._client, data)
1688
        )
1689
1690
    async def delete_emoji(
1691
        self,
1692
        id: Snowflake,
1693
        *,
1694
        reason: Optional[str] = None
1695
    ):
1696
        """|coro|
1697
        Deletes the given emoji.
1698
        Requires the ``MANAGE_EMOJIS_AND_STICKERS`` permission.
1699
1700
        Parameters
1701
        ----------
1702
        id : :class:`~pincer.utils.snowflake.Snowflake`
1703
            The ID of the emoji
1704
        reason : Optional[:class:`str`]
1705
            The reason for deleting the emoji |default| :data:`None`
1706
        """
1707
        await self._http.delete(
1708
            f"guilds/{self.id}/emojis/{id}",
1709
            headers=remove_none({"X-Audit-Log-Reason": reason})
1710
        )
1711
1712
    async def get_templates(self) -> AsyncGenerator[GuildTemplate, None]:
1713
        """|coro|
1714
        Returns an async generator of the guild templates.
1715
1716
        Yields
1717
        -------
1718
        AsyncGenerator[:class:`~pincer.objects.guild.template.GuildTemplate`, :data:`None`]
1719
            The guild template object.
1720
        """
1721
        data = await self._http.get(f"guilds/{self.id}/templates")
1722
        for template_data in data:
1723
            yield GuildTemplate.from_dict(
1724
                construct_client_dict(self._client, template_data)
1725
            )
1726
1727
    async def create_template(
1728
        self,
1729
        name: str,
1730
        description: Optional[str] = None
1731
    ) -> GuildTemplate:
1732
        """|coro|
1733
        Creates a new template for the guild.
1734
        Requires the ``MANAGE_GUILD`` permission.
1735
1736
        Parameters
1737
        ----------
1738
        name : :class:`str`
1739
            Name of the template (1-100 characters)
1740
        description : Optional[:class:`str`]
1741
            Description of the template
1742
            (0-120 characters) |default| :data:`None`
1743
        Returns
1744
        -------
1745
        :class:`~pincer.objects.guild.template.GuildTemplate`
1746
            The newly created template object.
1747
        """
1748
        data = await self._http.post(
1749
            f"guilds/{self.id}/templates",
1750
            data={
1751
                "name": name,
1752
                "description": description
1753
            }
1754
        )
1755
        return GuildTemplate.from_dict(
1756
            construct_client_dict(self._client, data)
1757
        )
1758
1759
    async def sync_template(
1760
        self,
1761
        template: GuildTemplate
1762
    ) -> GuildTemplate:
1763
        """|coro|
1764
        Syncs the given template.
1765
        Requires the ``MANAGE_GUILD`` permission.
1766
1767
        Parameters
1768
        ----------
1769
        template : :class:`~pincer.objects.guild.template.GuildTemplate`
1770
            The template to sync
1771
1772
        Returns
1773
        -------
1774
        :class:`~pincer.objects.guild.template.GuildTemplate`
1775
            The synced template object.
1776
        """
1777
        data = await self._http.put(
1778
            f"guilds/{self.id}/templates/{template.code}"
1779
        )
1780
        return GuildTemplate.from_dict(
1781
            construct_client_dict(self._client, data)
1782
        )
1783
1784
    async def edit_template(
1785
        self,
1786
        template: GuildTemplate,
1787
        *,
1788
        name: Optional[str] = None,
1789
        description: Optional[str] = None
1790
    ) -> GuildTemplate:
1791
        """|coro|
1792
        Modifies the template's metadata.
1793
        Requires the ``MANAGE_GUILD`` permission.
1794
1795
        Parameters
1796
        ----------
1797
        template : :class:`~pincer.objects.guild.template.GuildTemplate`
1798
            The template to edit
1799
        name : Optional[:class:`str`]
1800
            Name of the template (1-100 characters)
1801
            |default| :data:`None`
1802
        description : Optional[:class:`str`]
1803
            Description of the template (0-120 characters)
1804
            |default| :data:`None`
1805
1806
        Returns
1807
        -------
1808
        :class:`~pincer.objects.guild.template.GuildTemplate`
1809
            The edited template object.
1810
        """
1811
        data = await self._http.patch(
1812
            f"guilds/{self.id}/templates/{template.code}",
1813
            data={
1814
                "name": name,
1815
                "description": description
1816
            }
1817
        )
1818
        return GuildTemplate.from_dict(
1819
            construct_client_dict(self._client, data)
1820
        )
1821
1822
    async def delete_template(
1823
        self,
1824
        template: GuildTemplate
1825
    ) -> GuildTemplate:
1826
        """|coro|
1827
        Deletes the given template.
1828
        Requires the ``MANAGE_GUILD`` permission.
1829
1830
        Parameters
1831
        ----------
1832
        template : :class:`~pincer.objects.guild.template.GuildTemplate`
1833
            The template to delete
1834
        
1835
        Returns
1836
        -------
1837
        :class:`~pincer.objects.guild.template.GuildTemplate`
1838
            The deleted template object.
1839
        """
1840
        data = await self._http.delete(
1841
            f"guilds/{self.id}/templates/{template.code}"
1842
        )
1843
        return GuildTemplate.from_dict(
1844
            construct_client_dict(self._client, data)
1845
        )
1846
1847
    async def get_webhooks(self) -> AsyncGenerator[Webhook, None]:
1848
        """|coro|
1849
        Returns an async generator of the guild webhooks.
1850
1851
        Yields
1852
        -------
1853
        AsyncGenerator[:class:`~pincer.objects.guild.webhook.Webhook`, None]
1854
            The guild webhook object.
1855
        """
1856
        data = await self._http.get(f"guilds/{self.id}/webhooks")
1857
        for webhook_data in data:
1858
            yield Webhook.from_dict(
1859
                construct_client_dict(self._client, webhook_data)
1860
            )
1861
1862
    @classmethod
1863
    def from_dict(cls, data) -> Guild:
1864
        """
1865
        Parameters
1866
        ----------
1867
        data : :class:`Dict`
1868
            Guild data received from the discord API.
1869
        Returns
1870
        -------
1871
        :class:`~pincer.objects.guild.guild.Guild`
1872
            The new guild object.
1873
        Raises
1874
        :class:`~pincer.exceptions.UnavailableGuildError`
1875
            The guild is unavailable due to a discord outage.
1876
        """
1877
        if data.get("unavailable", False):
1878
            raise UnavailableGuildError(
1879
                f"Guild \"{data['id']}\" is unavailable due to a discord"
1880
                " outage."
1881
            )
1882
1883
        return super().from_dict(data)
1884
1885
1886
@dataclass(repr=False)
1887
class UnavailableGuild(APIObject):
1888
    id: Snowflake
1889
    unavailable: bool = True
1890