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

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

Complexity

Conditions 1

Size

Total Lines 34
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 11
nop 4
dl 0
loc 34
rs 9.85
c 0
b 0
f 0
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})
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))
0 ignored issues
show
introduced by
closing parenthesis ')' does not match opening parenthesis '{' (<unknown>, line 556)
Loading history...
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
        for member in member:
625
            yield GuildMember.from_dict(construct_client_dict(self._client, data))
626
        
627
628
    async def search_guild_members(
629
        self, 
630
        query: str,
631
        limit: Optional[int] = None
632
    ) -> List[GuildMember]:
633
        """|coro|
634
        Returns a list of guild member objects whose username or nickname starts with a provided string.
635
636
        Parameters
637
        ----------
638
        query : str
639
            Query string to match username(s) and nickname(s) against.
640
        limit : Optional[int]
641
            max number of members to return (1-1000) |default| :data:`1`
642
        Returns
643
        -------
644
        List[:class:`~pincer.objects.guild.member.GuildMember`]
645
            list of guild member objects
646
        """
647
648
        data = await self._http.get(
649
            f"guilds/{id}/members/search?{query=!s}"
650
            f"&{limit}" if limit else ""
651
        )
652
653
        for member in data:
654
            yield GuildMember.from_dict(construct_client_dict(self._client, member))
655
656
    @overload
657
    async def add_guild_member(
658
        self, *,
659
        user_id: Snowflake,
660
        access_token: str,
661
        nick: Optional[str] = None,
662
        roles: Optional[List[Snowflake]] = None,
663
        mute: Optional[bool] = None,
664
        deaf: Optional[bool] = None,
665
        reason: Optional[str] = None,
666
    ) -> Optional[GuildMember]:
667
        """|coro|
668
        Adds a user to the guild, provided you have a valid oauth2 access token for the user with the guilds.join scope.
669
670
        Parameters
671
        ----------
672
        user_id : str
673
            id of the user to be added
674
        access_token : str
675
            an oauth2 access token granted with the guilds.join to 
676
            the bot's application for the user you want to add to the guild
677
        nick : Optional[str]
678
        	value to set users nickname to
679
        roles : Optional[List[:class:`~pincer.utils.snowflake.Snowflake`]]
680
        	array of role ids the member is assigned
681
        mute : Optional[bool]
682
        	whether the user is muted in voice channels
683
        deaf : Optional[bool]
684
        	whether the user is deafened in voice channels
685
        reason : Optional[:class:`str`]
686
            audit log reason |default| :data:`None`
687
        Returns
688
        -------
689
        :class:`~pincer.objects.guild.member.GuildMember`
690
            If the user is not in the guild
691
        None
692
            If the user is in the guild
693
        """
694
695
    async def add_guild_member(
696
        self,
697
        user_id, 
698
        reason=None, 
699
        **kwargs
700
    ):
701
        data = await self._http.put(
702
            f"guilds/{self.id}/members/{user_id}", 
703
            data=kwargs,
704
            headers=remove_none({"X-Audit-Log-Reason":reason))
705
        )
706
707
        return GuildMember.from_dict(construct_client_dict(self._client, data)) if data else None
708
709
    async def modify_current_member(
710
        self, 
711
        nick: str, 
712
        reason: Optional[str] = None
713
    ) -> GuildMember:
714
        """|coro|
715
        Modifies the current member in a guild.
716
717
        Parameters
718
        ----------
719
        nick : str
720
            value to set users nickname to
721
        reason : Optional[:class:`str`]
722
            audit log reason |default| :data:`None`
723
        Returns
724
        -------
725
        class:`~pincer.objects.guild.member.GuildMember
726
            current guild member
727
        """
728
        data = self._http.patch(
729
            f"guilds/{self.id}/members/@me", 
730
            {"nick": nick}, 
731
            headers=remove_none({"X-Audit-Log-Reason":reason))
732
        )
733
        return GuildMember.from_dict(construct_client_dict(self._client, data))
734
735
    async def add_guild_member_role(
736
        self,
737
        user_id: int,
738
        role_id: int,
739
        reason: Optional[str] = None
740
    ) -> None:
741
        """|coro|
742
        Adds a role to a guild member.
743
744
        Parameters
745
        ----------
746
        user_id : int
747
            id of the user to give a role to
748
        role_id : int
749
            id of a role
750
        reason : Optional[:class:`str`]
751
            audit log reason |default| :data:`None`
752
        """
753
        data = await self._http.put(
754
            f"guilds/{self.id}/{user_id}/roles/{role_id}",
755
            headers=remove_none({"X-Audit-Log-Reason":reason))
756
        )
757
758
    async def remove_guild_member_role(
759
        self, 
760
        user_id: int,
761
        role_id: int
762
    ) -> None:
763
        """|coro|
764
        Removes a role from a guild member.
765
766
        Parameters
767
        ----------
768
        user_id : int
769
            id of the user to remove a role from
770
        role_id : int
771
            id of a role
772
        reason : Optional[:class:`str`]
773
            audit log reason |default| :data:`None`
774
        """
775
        await self._http.delete(
776
            f"guilds/{self.id}/{user_id}/roles/{role_id}",
777
            headers=remove_none({"X-Audit-Log-Reason":reason))
778
        )
779
780
    async def remove_guild_member(
781
        self,
782
        user_id: int,
783
        reason: Optional[str] = None
784
    ) -> None:
785
        """|coro|
786
        Remove a member from a guild.
787
788
        Parameters
789
        ----------
790
        user_id : int
791
            id of the user to remove from the guild
792
        reason : Optional[:class:`str`]
793
            audit log reason |default| :data:`None`
794
        """
795
        await self._http.delete(
796
            f"guilds/{self.id}/members/{user_id}",
797
            headers=remove_none({"X-Audit-Log-Reason":reason))
798
        )
799
800
    async def ban(
801
        self,
802
        member_id: int,
803
        reason: str = None,
804
        delete_message_days: int = None
805
    ):
806
        """
807
        Parameters
808
        ----------
809
        member_id : :class:`int`
810
            ID of the guild member to ban.
811
        reason : Optional[:class:`str`]
812
            Reason for the kick.
813
        delete_message_days : Optional[:class:`int`]
814
            Number of days to delete messages for (0-7)
815
        """
816
        headers = {}
817
818
        if reason is not None:
819
            headers["X-Audit-Log-Reason"] = reason
820
821
        data = {}
822
823
        if delete_message_days is not None:
824
            data["delete_message_days"] = delete_message_days
825
826
        await self._http.put(
827
            f"/guilds/{self.id}/bans/{member_id}",
828
            data=data,
829
            headers=headers
830
        )
831
832
    async def kick(self, member_id: int, reason: Optional[str] = None):
833
        """|coro|
834
        Kicks a guild member.
835
        Parameters
836
        ----------
837
        member_id : :class:`int`
838
            ID of the guild member to kick.
839
        reason : Optional[:class:`str`]
840
            Reason for the kick.
841
        """
842
843
        headers = {}
844
845
        if reason is not None:
846
            headers["X-Audit-Log-Reason"] = reason
847
848
        await self._http.delete(
849
            f"/guilds/{self.id}/members/{member_id}",
850
            header=headers
851
        )
852
853
    async def get_roles(self) -> AsyncGenerator[Role, None]:
854
        """|coro|
855
        Fetches all the roles in the guild.
856
857
        Yields
858
        -------
859
        AsyncGenerator[:class:`~pincer.objects.guild.role.Role`, :data:`None`]
860
            An async generator of Role objects.
861
        """
862
        data = await self._http.get(f"guilds/{self.id}/roles")
863
        for role_data in data:
864
            yield Role.from_dict(construct_client_dict(self._client, role_data))
865
866
    @overload
867
    async def create_role(
868
        self,
869
        reason: Optional[str] = None,
870
        *,
871
        name: Optional[str] = "new role",
872
        permissions: Optional[str] = None,
873
        color: Optional[int] = 0,
874
        hoist: Optional[bool] = False,
875
        icon: Optional[str] = None,
876
        unicode_emoji: Optional[str] = None,
877
        mentionable: Optional[bool] = False,
878
    ) -> Role:
879
        """|coro|
880
        Creates a new role for the guild.
881
        Requires the ``MANAGE_ROLES`` permission.
882
883
        Parameters
884
        ----------
885
        reason : Optional[:class:`str`]
886
            Reason for creating the role. |default| :data:`None`
887
        name : Optional[:class:`str`]
888
            name of the role |default| :data:`"new role"`
889
        permissions : Optional[:class:`str`]
890
            bitwise value of the enabled/disabled
891
            permissions, set to @everyone permissions
892
            by default |default| :data:`None`
893
        color : Optional[:class:`int`]
894
            RGB color value |default| :data:`0`
895
        hoist : Optional[:class:`bool`]
896
            whether the role should be displayed
897
            separately in the sidebar |default| :data:`False`
898
        icon : Optional[:class:`str`]
899
            the role's icon image (if the guild has
900
            the ``ROLE_ICONS`` feature) |default| :data:`None`
901
        unicode_emoji : Optional[:class:`str`]
902
            the role's unicode emoji as a standard emoji (if the guild
903
            has the ``ROLE_ICONS`` feature) |default| :data:`None`
904
        mentionable : Optional[:class:`bool`]
905
            whether the role should be mentionable |default| :data:`False`
906
907
        Returns
908
        -------
909
        :class:`~pincer.objects.guild.role.Role`
910
            The new role object.
911
        """
912
        ...
913
914
    async def create_role(
915
        self,
916
        reason: Optional[str] = None,
917
        **kwargs
918
    ) -> Role:
919
        return Role.from_dict(
920
            construct_client_dict(
921
                self._client,
922
                await self._http.post(
923
                    f"guilds/{self.id}/roles",
924
                    data=kwargs,
925
                    headers=remove_none({"X-Audit-Log-Reason": reason})
926
                ),
927
            )
928
        )
929
930
    async def edit_role_position(
931
        self,
932
        id: Snowflake,
933
        reason: Optional[str] = None,
934
        position: Optional[int] = None
935
    ) -> AsyncGenerator[Role, None]:
936
        """|coro|
937
        Edits the position of a role.
938
939
        Parameters
940
        ----------
941
        id : :class:`~pincer.utils.snowflake.Snowflake`
942
            The role ID
943
        reason : Optional[:class:`str`]
944
            Reason for editing the role position. |default| :data:`None`
945
        position : Optional[:class:`int`]
946
            Sorting position of the role |default| :data:`None`
947
948
        Yields
949
        -------
950
        AsyncGenerator[:class:`~pincer.objects.guild.role.Role`, :data:`None`]
951
            An async generator of all of the guild's role objects.
952
        """
953
        data = await self._http.patch(
954
            f"guilds/{self.id}/roles",
955
            data={"id": id, "position": position},
956
            headers=remove_none({"X-Audit-Log-Reason": reason})
957
        )
958
        for role_data in data:
959
            yield Role.from_dict(construct_client_dict(self._client, role_data))
960
961
    @overload
962
    async def edit_role(
963
        self,
964
        id: Snowflake,
965
        reason: Optional[str] = None,
966
        *,
967
        name: Optional[str] = None,
968
        permissions: Optional[str] = None,
969
        color: Optional[int] = None,
970
        hoist: Optional[bool] = None,
971
        icon: Optional[str] = None,
972
        unicode_emoji: Optional[str] = None,
973
        mentionable: Optional[bool] = None,
974
    ) -> Role:
975
        """|coro|
976
        Edits a role.
977
        Requires the ``MANAGE_ROLES`` permission.
978
979
        Parameters
980
        ----------
981
        id : :class:`~pincer.utils.snowflake.Snowflake`
982
            The role ID
983
        reason : Optional[:class:`str`]
984
            Reason for editing the role |default| :data:`None`
985
        name : Optional[:class:`str`]
986
            Name of the role |default| :data:`None`
987
        permissions : Optional[:class:`str`]
988
            Bitwise value of the enabled/disabled
989
            permissions |default| :data:`None`
990
        color : Optional[:class:`int`]
991
            RGB color value |default| :data:`None`
992
        hoist : Optional[:class:`bool`]
993
            Whether the role should be displayed
994
            separately in the sidebar |default| :data:`None`
995
        icon : Optional[:class:`str`]
996
            The role's icon image (if the guild has
997
            the ``ROLE_ICONS`` feature) |default| :data:`None`
998
        unicode_emoji : Optional[:class:`str`]
999
            The role's unicode emoji as a standard emoji (if the guild
1000
            has the ``ROLE_ICONS`` feature) |default| :data:`None`
1001
        mentionable : Optional[:class:`bool`]
1002
            Whether the role should be mentionable |default| :data:`None`
1003
1004
        Returns
1005
        -------
1006
        :class:`~pincer.objects.guild.role.Role`
1007
            The edited role object.
1008
        """
1009
        ...
1010
1011
    async def edit_role(
1012
        self,
1013
        id: Snowflake,
1014
        reason: Optional[str] = None,
1015
        **kwargs
1016
    ) -> Role:
1017
        return Role.from_dict(
1018
            construct_client_dict(
1019
                self._client,
1020
                await self._http.patch(
1021
                    f"guilds/{self.id}/roles/{id}",
1022
                    data=kwargs,
1023
                    headers=remove_none({"X-Audit-Log-Reason": reason})
1024
                ),
1025
            )
1026
        )
1027
1028
    async def delete_role(self, id: Snowflake, reason: Optional[str] = None):
1029
        """|coro|
1030
        Deletes a role.
1031
        Requires the `MANAGE_ROLES` permission.
1032
1033
        Parameters
1034
        ----------
1035
        id : :class:`~pincer.utils.snowflake.Snowflake`
1036
            The role ID
1037
        reason : Optional[:class:`str`]
1038
            The reason for deleting the role |default| :data:`None`
1039
        """
1040
        await self._http.delete(
1041
            f"guilds/{self.id}/roles/{id}",
1042
            headers=remove_none({"X-Audit-Log-Reason": reason})
1043
        )
1044
1045
    async def get_bans(self) -> AsyncGenerator[Ban, None]:
1046
        """|coro|
1047
        Fetches all the bans in the guild.
1048
1049
        Yields
1050
        -------
1051
        AsyncGenerator[:class:`~pincer.objects.guild.ban.Ban`, :data:`None`]
1052
            An async generator of Ban objects.
1053
        """
1054
        data = await self._http.get(f"guilds/{self.id}/bans")
1055
        for ban_data in data:
1056
            yield Ban.from_dict(construct_client_dict(self._client, ban_data))
1057
1058
    async def get_ban(self, id: Snowflake) -> Ban:
1059
        """|coro|
1060
        Fetches a ban from the guild.
1061
1062
        Parameters
1063
        ----------
1064
        id : :class:`~pincer.utils.snowflake.Snowflake`
1065
            The user ID
1066
1067
        Returns
1068
        -------
1069
        :class:`~pincer.objects.guild.ban.Ban`
1070
            The Ban object.
1071
        """
1072
        return Ban.from_dict(
1073
            construct_client_dict(
1074
                self._client,
1075
                await self._http.get(f"guilds/{self.id}/bans/{id}"),
1076
            )
1077
        )
1078
1079
    async def unban(self, id: Snowflake, reason: Optional[str] = None):
1080
        """|coro|
1081
        Unbans a user from the guild.
1082
1083
        Parameters
1084
        ----------
1085
        id : :class:`~pincer.utils.snowflake.Snowflake`
1086
            The user ID
1087
        reason : Optional[:class:`str`]
1088
            The reason for unbanning the user |default| :data:`None`
1089
        """
1090
        await self._http.delete(
1091
            f"guilds/{self.id}/bans/{id}",
1092
            headers=remove_none({"X-Audit-Log-Reason": reason})
1093
        )
1094
1095
    @overload
1096
    async def edit(
1097
        self,
1098
        *,
1099
        name: Optional[str] = None,
1100
        region: Optional[str] = None,
1101
        verification_level: Optional[int] = None,
1102
        default_message_notifications: Optional[int] = None,
1103
        explicit_content_filter: Optional[int] = None,
1104
        afk_channel_id: Optional[Snowflake] = None,
1105
        afk_timeout: Optional[int] = None,
1106
        icon: Optional[str] = None,
1107
        owner_id: Optional[Snowflake] = None,
1108
        splash: Optional[str] = None,
1109
        discovery_splash: Optional[str] = None,
1110
        banner: Optional[str] = None,
1111
        system_channel_id: Optional[Snowflake] = None,
1112
        system_channel_flags: Optional[int] = None,
1113
        rules_channel_id: Optional[Snowflake] = None,
1114
        public_updates_channel_id: Optional[Snowflake] = None,
1115
        preferred_locale: Optional[str] = None,
1116
        features: Optional[List[GuildFeature]] = None,
1117
        description: Optional[str] = None,
1118
    ) -> Guild:
1119
        """|coro|
1120
        Modifies the guild
1121
1122
        Parameters
1123
        ----------
1124
        name : Optional[:class:`str`]
1125
            Guild name |default| :data:`None`
1126
        region : Optional[:class:`str`]
1127
            Guild voice region ID |default| :data:`None`
1128
        verification_level : Optional[:class:`int`]
1129
            Verification level |default| :data:`None`
1130
        default_message_notifications : Optional[:class:`int`]
1131
            Default message notification level |default| :data:`None`
1132
        explicit_content_filter : Optional[:class:`int`]
1133
            Explicit content filter level |default| :data:`None`
1134
        afk_channel_id : Optional[:class:`~pincer.utils.snowflake.Snowflake`]
1135
            ID for AFK channel |default| :data:`None`
1136
        afk_timeout : Optional[:class:`int`]
1137
            AFK timeout in seconds |default| :data:`None`
1138
        icon : Optional[:class:`str`]
1139
            base64 1024x1024 png/jpeg/gif image for the guild icon
1140
            (can be animated gif when the server
1141
            has the `ANIMATED_ICON` feature) |default| :data:`None`
1142
        owner_id : Optional[:class:`~pincer.utils.snowflake.Snowflake`]
1143
            User ID to transfer guild ownership to (must be owner) |default| :data:`None`
1144
        splash : Optional[:class:`str`]
1145
            base64 16:9 png/jpeg image for the guild splash (when the
1146
            server has the `INVITE_SPLASH` feature) |default| :data:`None`
1147
        discovery_splash : Optional[:class:`str`]
1148
            base64 16:9 png/jpeg image for the guild discovery splash
1149
            (when the server has the `DISCOVERABLE` feature) |default| :data:`None`
1150
        banner : Optional[:class:`str`]
1151
            base64 16:9 png/jpeg image for the guild banner (when the
1152
            server has the `BANNER` feature) |default| :data:`None`
1153
        system_channel_id : Optional[:class:`~pincer.utils.snowflake.Snowflake`]
1154
            The ID of the channel where guild notices such as welcome
1155
            messages and boost events are posted |default| :data:`None`
1156
        system_channel_flags : Optional[:class:`int`]
1157
            System channel flags |default| :data:`None`
1158
        rules_channel_id : Optional[:class:`~pincer.utils.snowflake.Snowflake`]
1159
            The ID of the channel where Community guilds display rules
1160
            and/or guidelines |default| :data:`None`
1161
        public_updates_channel_id : Optional[:class:`~pincer.utils.snowflake.Snowflake`]
1162
            The ID of the channel where admins and moderators of
1163
            Community guilds receive notices from Discord |default| :data:`None`
1164
        preferred_locale : Optional[:class:`str`]
1165
            The preferred locale of a Community guild used in server
1166
            discovery and notices from Discord; defaults to "en-US" |default| :data:`None`
1167
        features : Optional[List[:class:`GuildFeature`]]
1168
            Enabled guild features |default| :data:`None`
1169
        description : Optional[:class:`str`]
1170
            The description for the guild, if the guild is discoverable |default| :data:`None`
1171
1172
        Returns
1173
        -------
1174
        :class:`~pincer.objects.guild.Guild`
1175
            The modified guild object.
1176
        """
1177
        ...
1178
1179
    async def edit(self, **kwargs) -> Guild:
1180
        g = await self._http.patch(f"guilds/{self.id}", data=kwargs)
1181
        return Guild.from_dict(construct_client_dict(self._client, g))
1182
1183
    async def preview(self) -> GuildPreview:
1184
        """|coro|
1185
        Previews the guild.
1186
1187
        Returns
1188
        -------
1189
        :class:`~pincer.objects.guild.guild.GuildPreview`
1190
            The guild preview object.
1191
        """
1192
        data = await self._http.get(f"guilds/{self.id}/preview")
1193
        return GuildPreview.from_dict(data)
1194
1195
    async def delete(self):
1196
        """|coro|
1197
        Deletes the guild. Returns `204 No Content` on success.
1198
        """
1199
        await self._http.delete(f"guilds/{self.id}")
1200
1201
    async def prune_count(
1202
        self,
1203
        days: Optional[int] = 7,
1204
        include_roles: Optional[str] = None
1205
    ) -> int:
1206
        """|coro|
1207
        Returns the number of members that
1208
        would be removed in a prune operation.
1209
        Requires the ``KICK_MEMBERS`` permission.
1210
1211
        Parameters
1212
        ----------
1213
        days : Optional[:class:`int`]
1214
            Number of days to count prune for (1-30) |default| :data:`7`
1215
        include_roles : Optional[:class:`str`]
1216
            Comma-delimited array of Snowflakes;
1217
            role(s) to include |default| :data:`None`
1218
1219
        Returns
1220
        -------
1221
        :class:`int`
1222
            The number of members that would be removed.
1223
        """
1224
        return await self._http.get(
1225
            f"guilds/{self.id}/prune?{days=}&{include_roles=!s}"
1226
        )["pruned"]
1227
1228
    async def prune(
1229
        self,
1230
        days: Optional[int] = 7,
1231
        compute_prune_days: Optional[bool] = True,
1232
        include_roles: Optional[List[Snowflake]] = None,
1233
        reason: Optional[str] = None
1234
    ) -> int:
1235
        """|coro|
1236
        Prunes members from the guild. Requires the ``KICK_MEMBERS`` permission.
1237
1238
        Parameters
1239
1240
        Parameters
1241
        ----------
1242
        days : Optional[:class:`int`]
1243
            Number of days to prune (1-30) |default| :data:`7`
1244
        compute_prune_days : Optional[:class:`bool`]
1245
            Whether ``pruned`` is returned, discouraged for large guilds
1246
            |default| :data:`True`
1247
        include_roles : Optional[List[:class:`~pincer.utils.snowflake.Snowflake`]]
1248
            role(s) to include |default| :data:`None`
1249
        reason : Optional[:class:`str`]
1250
            Reason for the prune |default| :data:`None`
1251
1252
        Returns
1253
        -------
1254
        :class:`int`
1255
            The number of members that were removed.
1256
        """
1257
        return await self._http.post(
1258
            f"guilds/{self.id}/prune",
1259
            data={
1260
                "days": days,
1261
                "compute_prune_days": compute_prune_days,
1262
                "include_roles": include_roles
1263
            },
1264
            headers=remove_none({"X-Audit-Log-Reason": reason})
1265
        )["pruned"]
1266
1267
    async def get_voice_regions(self) -> AsyncGenerator[VoiceRegion, None]:
1268
        """|coro|
1269
        Returns an async generator of voice regions.
1270
1271
        Yields
1272
        -------
1273
        AsyncGenerator[:class:`~pincer.objects.voice.VoiceRegion`, :data:`None`]
1274
            An async generator of voice regions.
1275
        """
1276
        data = await self._http.get(f"guilds/{self.id}/regions")
1277
        for voice_region_data in data:
1278
            yield VoiceRegion.from_dict(construct_client_dict(self._client, voice_region_data))
1279
1280
    async def get_invites(self) -> AsyncGenerator[Invite, None]:
1281
        """|coro|
1282
        Returns an async generator of invites for the guild.
1283
        Requires the ``MANAGE_GUILD`` permission.
1284
1285
        Yields
1286
        -------
1287
        AsyncGenerator[:class:`~pincer.objects.invite.Invite`, :data:`None`]
1288
            An async generator of invites.
1289
        """
1290
        data = await self._http.get(f"guilds/{self.id}/invites")
1291
        for invite_data in data:
1292
            yield Invite.from_dict(construct_client_dict(self._client, invite_data))
1293
1294
    async def get_integrations(self) -> AsyncGenerator[Integration, None]:
1295
        """|coro|
1296
        Returns an async generator of integrations for the guild.
1297
        Requires the ``MANAGE_GUILD`` permission.
1298
1299
        Yields
1300
        -------
1301
        AsyncGenerator[:class:`~pincer.objects.integration.Integration`, :data:`None`]
1302
            An async generator of integrations.
1303
        """
1304
        data = await self._http.get(f"guilds/{self.id}/integrations")
1305
        for integration_data in data:
1306
            yield Integration.from_dict(construct_client_dict(self._client, integration_data))
1307
1308
    async def delete_integration(
1309
        self,
1310
        integration: Integration,
1311
        reason: Optional[str] = None
1312
    ):
1313
        """|coro|
1314
        Deletes an integration.
1315
        Requires the ``MANAGE_GUILD`` permission.
1316
1317
        Parameters
1318
        ----------
1319
        integration : :class:`~pincer.objects.integration.Integration`
1320
            The integration to delete.
1321
        reason : Optional[:class:`str`]
1322
            Reason for the deletion |default| :data:`None`
1323
        """
1324
        await self._http.delete(
1325
            f"guilds/{self.id}/integrations/{integration.id}",
1326
            headers=remove_none({"X-Audit-Log-Reason": reason})
1327
        )
1328
1329
    async def get_widget_settings(self) -> GuildWidget:
1330
        """|coro|
1331
        Returns the guild widget settings.
1332
        Requires the ``MANAGE_GUILD`` permission.
1333
1334
        Returns
1335
        -------
1336
        :class:`~pincer.objects.guild.widget.GuildWidget`
1337
            The guild widget settings.
1338
        """
1339
        return GuildWidget.from_dict(
1340
            construct_client_dict(
1341
                self._client,
1342
                await self._http.get(f"guilds/{self.id}/widget")
1343
            )
1344
        )
1345
1346
    async def modify_widget(
1347
        self,
1348
        reason: Optional[str] = None,
1349
        **kwargs
1350
    ) -> GuildWidget:
1351
        """|coro|
1352
        Modifies the guild widget for the guild.
1353
        Requires the ``MANAGE_GUILD`` permission.
1354
1355
        Parameters
1356
        ----------
1357
        reason : Optional[:class:`str`]
1358
            Reason for the modification |default| :data:`None`
1359
        \\*\\*kwargs
1360
            The widget settings to modify
1361
1362
        Returns
1363
        -------
1364
        :class:`~pincer.objects.guild.widget.GuildWidget`
1365
            The updated GuildWidget object
1366
        """
1367
        data = await self._http.patch(
1368
            f"guilds/{self.id}/widget",
1369
            data=kwargs,
1370
            headers=remove_none({"X-Audit-Log-Reason": reason})
1371
        )
1372
        return GuildWidget.from_dict(construct_client_dict(self._client, data))
1373
1374
    async def get_widget(self) -> Dict[str, JSONSerializable]:
1375
        """|coro|
1376
        Returns the widget for the guild
1377
        """
1378
        return await self._http.get(f"guilds/{self.id}/widget.json")
1379
1380
    @property
1381
    async def vanity_url(self) -> Invite:
1382
        """|coro|
1383
        Returns the Vanity URL for the guild.
1384
        Requires the ``MANAGE_GUILD`` permission.
1385
        ``code`` will be null if a vanity URL has not been set.
1386
1387
        Returns
1388
        -------
1389
        :class:`~pincer.objects.guild.invite.Invite`
1390
            The vanity url for the guild.
1391
        """
1392
        data = await self._http.get(f"guilds/{self.id}/vanity-url")
1393
        return Invite.from_dict(construct_client_dict(self._client, data))
1394
1395
    async def get_widget_image(self, style: Optional[str] = "shield") -> str:  # TODO Replace str with ImageURL object
1396
        """|coro|
1397
        Returns a PNG image widget for the guild.
1398
        Requires no permissions or authentication.
1399
1400
        Widget Style Options
1401
        -------------------
1402
        * [``shield``](https://discord.com/api/guilds/81384788765712384/widget.png?style=shield)
1403
          shield style widget with Discord icon and guild members online count
1404
        * [``banner1``](https://discord.com/api/guilds/81384788765712384/widget.png?style=banner1)
1405
          large image with guild icon, name and online count.
1406
          "POWERED BY DISCORD" as the footer of the widget
1407
        * [``banner2``](https://discord.com/api/guilds/81384788765712384/widget.png?style=banner2)
1408
          smaller widget style with guild icon, name and online count.
1409
          Split on the right with Discord logo
1410
        * [``banner3``](https://discord.com/api/guilds/81384788765712384/widget.png?style=banner3)
1411
          large image with guild icon, name and online count.
1412
          In the footer, Discord logo on the
1413
          left and "Chat Now" on the right
1414
        * [``banner4``](https://discord.com/api/guilds/81384788765712384/widget.png?style=banner4)
1415
          large Discord logo at the top of the widget.
1416
          Guild icon, name and online count in the middle portion
1417
          of the widget and a "JOIN MY SERVER" button at the bottom
1418
1419
        Parameters
1420
        ----------
1421
        style : Optional[:class:`str`]
1422
            Style of the widget image returned |default| :data:`"shield"`
1423
1424
        Returns
1425
        -------
1426
        :class:`str`
1427
            A PNG image of the guild widget.
1428
        """
1429
        return await self._http.get(f"guilds/{self.id}/widget.png?{style=!s}")
1430
1431
    async def get_welcome_screen(self) -> WelcomeScreen:
1432
        """Returns the welcome screen for the guild.
1433
1434
        Returns
1435
        -------
1436
        :class:`~pincer.objects.guild.welcome_screen.WelcomeScreen`
1437
            The welcome screen for the guild.
1438
        """
1439
        data = await self._http.get(f"guilds/{self.id}/welcome-screen")
1440
        return WelcomeScreen.from_dict(construct_client_dict(self._client, data))
1441
1442
    async def modify_welcome_screen(
1443
        self,
1444
        enabled: Optional[bool] = None,
1445
        welcome_channels: Optional[List[WelcomeScreenChannel]] = None,
1446
        description: Optional[str] = None,
1447
        reason: Optional[str] = None
1448
    ) -> WelcomeScreen:
1449
        """|coro|
1450
        Modifies the guild's Welcome Screen.
1451
        Requires the ``MANAGE_GUILD`` permission.
1452
1453
        Parameters
1454
        ----------
1455
        enabled : Optional[:class:`bool`]
1456
            Whether the welcome screen is enabled |default| :data:`None`
1457
        welcome_channels : Optional[List[:class:`~pincer.objects.guild.welcome_screen.WelcomeScreenChannel`]]
1458
            Channels linked in the welcome screen and
1459
            their display options |default| :data:`None`
1460
        description : Optional[:class:`str`]
1461
            The server description to show
1462
            in the welcome screen |default| :data:`None`
1463
        reason : Optional[:class:`str`]
1464
            Reason for the modification |default| :data:`None`
1465
1466
        Returns
1467
        -------
1468
        :class:`~pincer.objects.guild.welcome_screen.WelcomeScreen`
1469
            The updated WelcomeScreen object
1470
        """
1471
        data = await self._http.patch(
1472
            f"guilds/{self.id}/welcome-screen",
1473
            data={
1474
                "enabled": enabled,
1475
                "welcome_channels": welcome_channels,
1476
                "description": description
1477
            },
1478
            headers=remove_none({"X-Audit-Log-Reason": reason})
1479
        )
1480
        return WelcomeScreen.from_dict(construct_client_dict(self._client, data))
1481
1482
    async def modify_current_user_voice_state(
1483
        self,
1484
        channel_id: Snowflake,
1485
        suppress: Optional[bool] = None,
1486
        request_to_speak_timestamp: Optional[Timestamp] = None
1487
    ):
1488
        """|coro|
1489
        Updates the current user's voice state.
1490
1491
        There are currently several caveats for this endpoint:
1492
        * ``channel_id`` must currently point to a stage channel
1493
        * current user must already have joined ``channel_id``
1494
        * You must have the ``MUTE_MEMBERS`` permission to
1495
          unsuppress yourself. You can always suppress yourself.
1496
        * You must have the ``REQUEST_TO_SPEAK`` permission to request
1497
          to speak. You can always clear your own request to speak.
1498
        * You are able to set ``request_to_speak_timestamp`` to any
1499
          present or future time.
1500
1501
        Parameters
1502
        ----------
1503
        channel_id : :class:`~pincer.utils.snowflake.Snowflake`
1504
            The ID of the channel the user is currently in
1505
        suppress : Optional[:class:`bool`]
1506
            Toggles the user's suppress state |default| :data:`None`
1507
        request_to_speak_timestamp : Optional[:class:`~pincer.utils.timestamp.Timestamp`]
1508
            Sets the user's request to speak
1509
        """
1510
        await self._http.patch(
1511
            f"guilds/{self.id}/voice-states/@me",
1512
            data={
1513
                "channel_id": channel_id,
1514
                "suppress": suppress,
1515
                "request_to_speak_timestamp": request_to_speak_timestamp
1516
            }
1517
        )
1518
1519
    async def modify_user_voice_state(
1520
        self,
1521
        user: User,
1522
        channel_id: Snowflake,
1523
        suppress: Optional[bool] = None
1524
    ):
1525
        """|coro|
1526
        Updates another user's voice state.
1527
1528
        There are currently several caveats for this endpoint:
1529
        * ``channel_id`` must currently point to a stage channel
1530
        * User must already have joined ``channel_id``
1531
        * You must have the ``MUTE_MEMBERS`` permission.
1532
          (Since suppression is the only thing that is available currently.)
1533
        * When unsuppressed, non-bot users will have their
1534
          ``request_to_speak_timestamp`` set to the current time.
1535
          Bot users will not.
1536
        * When suppressed, the user will have their
1537
          ``request_to_speak_timestamp`` removed.
1538
1539
        Parameters
1540
        ----------
1541
        user : :class:`~pincer.objects.guild.member.Member`
1542
            The user to update
1543
        channel_id : :class:`~pincer.utils.snowflake.Snowflake`
1544
            The ID of the channel the user is currently in
1545
        suppress : Optional[:class:`bool`]
1546
            Toggles the user's suppress state |default| :data:`None`
1547
        """
1548
        await self._http.patch(
1549
            f"guilds/{self.id}/voice-states/{user.id}",
1550
            data={
1551
                "channel_id": channel_id,
1552
                "suppress": suppress
1553
            }
1554
        )
1555
1556
    async def get_audit_log(self) -> AuditLog:
1557
        """|coro|
1558
        Returns an audit log object for the guild.
1559
        Requires the ``VIEW_AUDIT_LOG`` permission.
1560
1561
        Returns
1562
        -------
1563
        :class:`~pincer.objects.guild.audit_log.AuditLog`
1564
            The audit log object for the guild.
1565
        """
1566
        return AuditLog.from_dict(
1567
            construct_client_dict(
1568
                self._client,
1569
                await self._http.get(f"guilds/{self.id}/audit-logs")
1570
            )
1571
        )
1572
1573
    async def get_emojis(self) -> AsyncGenerator[Emoji, None]:
1574
        """|coro|
1575
        Returns an async generator of the emojis in the guild.
1576
1577
        Yields
1578
        ------
1579
        :class:`~pincer.objects.guild.emoji.Emoji`
1580
            The emoji object.
1581
        """
1582
        data = await self._http.get(f"guilds/{self.id}/emojis")
1583
        for emoji_data in data:
1584
            yield Emoji.from_dict(
1585
                construct_client_dict(self._client, emoji_data)
1586
            )
1587
1588
    async def get_emoji(self, id: Snowflake) -> Emoji:
1589
        """|coro|
1590
        Returns an emoji object for the given ID.
1591
1592
        Parameters
1593
        ----------
1594
        id : :class:`~pincer.utils.snowflake.Snowflake`
1595
            The ID of the emoji
1596
1597
        Returns
1598
        -------
1599
        :class:`~pincer.objects.guild.emoji.Emoji`
1600
            The emoji object.
1601
        """
1602
        return Emoji.from_dict(
1603
            construct_client_dict(
1604
                self._client,
1605
                await self._http.get(f"guilds/{self.id}/emojis/{id}")
1606
            )
1607
        )
1608
1609
    async def create_emoji(
1610
        self,
1611
        *,
1612
        name: str,
1613
        image: File,
1614
        roles: List[Snowflake] = [],
1615
        reason: Optional[str] = None
1616
    ) -> Emoji:
1617
        """|coro|
1618
        Creates a new emoji for the guild.
1619
        Requires the ``MANAGE_EMOJIS_AND_STICKERS`` permission.
1620
1621
        Emojis and animated emojis have a maximum file size of 256kb.
1622
        Attempting to upload an emoji larger than this limit will fail.
1623
1624
        Parameters
1625
        ----------
1626
        name : :class:`str`
1627
            Name of the emoji
1628
        image : :class:`~pincer.objects.message.file.File`
1629
            The File for the 128x128 emoji image data
1630
        roles : List[:class:`~pincer.utils.snowflake.Snowflake`]
1631
            Roles allowed to use this emoji |default| :data:`[]`
1632
        reason : Optional[:class:`str`]
1633
            The reason for creating the emoji |default| :data:`None`
1634
1635
        Returns
1636
        -------
1637
        :class:`~pincer.objects.guild.emoji.Emoji`
1638
            The newly created emoji object.
1639
        """
1640
        data = await self._http.post(
1641
            f"guilds/{self.id}/emojis",
1642
            data={
1643
                "name": name,
1644
                "image": image.uri,
1645
                "roles": roles
1646
            },
1647
            headers=remove_none({"X-Audit-Log-Reason": reason})
1648
        )
1649
        return Emoji.from_dict(
1650
            construct_client_dict(self._client, data)
1651
        )
1652
1653
    async def edit_emoji(
1654
        self,
1655
        id: Snowflake,
1656
        *,
1657
        name: Optional[str] = None,
1658
        roles: Optional[List[Snowflake]] = None,
1659
        reason: Optional[str] = None
1660
    ) -> Emoji:
1661
        """|coro|
1662
        Modifies the given emoji.
1663
        Requires the ``MANAGE_EMOJIS_AND_STICKERS`` permission.
1664
1665
        Parameters
1666
        ----------
1667
        id : :class:`~pincer.utils.snowflake.Snowflake`
1668
            The ID of the emoji
1669
        name : Optional[:class:`str`]
1670
            Name of the emoji |default| :data:`None`
1671
        roles : Optional[List[:class:`~pincer.utils.snowflake.Snowflake`]]
1672
            Roles allowed to use this emoji |default| :data:`None`
1673
        reason : Optional[:class:`str`]
1674
            The reason for editing the emoji |default| :data:`None`
1675
1676
        Returns
1677
        -------
1678
        :class:`~pincer.objects.guild.emoji.Emoji`
1679
            The modified emoji object.
1680
        """
1681
        data = await self._http.patch(
1682
            f"guilds/{self.id}/emojis/{id}",
1683
            data={
1684
                "name": name,
1685
                "roles": roles
1686
            },
1687
            headers=remove_none({"X-Audit-Log-Reason": reason})
1688
        )
1689
        return Emoji.from_dict(
1690
            construct_client_dict(self._client, data)
1691
        )
1692
1693
    async def delete_emoji(
1694
        self,
1695
        id: Snowflake,
1696
        *,
1697
        reason: Optional[str] = None
1698
    ):
1699
        """|coro|
1700
        Deletes the given emoji.
1701
        Requires the ``MANAGE_EMOJIS_AND_STICKERS`` permission.
1702
1703
        Parameters
1704
        ----------
1705
        id : :class:`~pincer.utils.snowflake.Snowflake`
1706
            The ID of the emoji
1707
        reason : Optional[:class:`str`]
1708
            The reason for deleting the emoji |default| :data:`None`
1709
        """
1710
        await self._http.delete(
1711
            f"guilds/{self.id}/emojis/{id}",
1712
            headers=remove_none({"X-Audit-Log-Reason": reason})
1713
        )
1714
1715
    async def get_templates(self) -> AsyncGenerator[GuildTemplate, None]:
1716
        """|coro|
1717
        Returns an async generator of the guild templates.
1718
1719
        Yields
1720
        -------
1721
        AsyncGenerator[:class:`~pincer.objects.guild.template.GuildTemplate`, :data:`None`]
1722
            The guild template object.
1723
        """
1724
        data = await self._http.get(f"guilds/{self.id}/templates")
1725
        for template_data in data:
1726
            yield GuildTemplate.from_dict(
1727
                construct_client_dict(self._client, template_data)
1728
            )
1729
1730
    async def create_template(
1731
        self,
1732
        name: str,
1733
        description: Optional[str] = None
1734
    ) -> GuildTemplate:
1735
        """|coro|
1736
        Creates a new template for the guild.
1737
        Requires the ``MANAGE_GUILD`` permission.
1738
1739
        Parameters
1740
        ----------
1741
        name : :class:`str`
1742
            Name of the template (1-100 characters)
1743
        description : Optional[:class:`str`]
1744
            Description of the template
1745
            (0-120 characters) |default| :data:`None`
1746
        Returns
1747
        -------
1748
        :class:`~pincer.objects.guild.template.GuildTemplate`
1749
            The newly created template object.
1750
        """
1751
        data = await self._http.post(
1752
            f"guilds/{self.id}/templates",
1753
            data={
1754
                "name": name,
1755
                "description": description
1756
            }
1757
        )
1758
        return GuildTemplate.from_dict(
1759
            construct_client_dict(self._client, data)
1760
        )
1761
1762
    async def sync_template(
1763
        self,
1764
        template: GuildTemplate
1765
    ) -> GuildTemplate:
1766
        """|coro|
1767
        Syncs the given template.
1768
        Requires the ``MANAGE_GUILD`` permission.
1769
1770
        Parameters
1771
        ----------
1772
        template : :class:`~pincer.objects.guild.template.GuildTemplate`
1773
            The template to sync
1774
1775
        Returns
1776
        -------
1777
        :class:`~pincer.objects.guild.template.GuildTemplate`
1778
            The synced template object.
1779
        """
1780
        data = await self._http.put(
1781
            f"guilds/{self.id}/templates/{template.code}"
1782
        )
1783
        return GuildTemplate.from_dict(
1784
            construct_client_dict(self._client, data)
1785
        )
1786
1787
    async def edit_template(
1788
        self,
1789
        template: GuildTemplate,
1790
        *,
1791
        name: Optional[str] = None,
1792
        description: Optional[str] = None
1793
    ) -> GuildTemplate:
1794
        """|coro|
1795
        Modifies the template's metadata.
1796
        Requires the ``MANAGE_GUILD`` permission.
1797
1798
        Parameters
1799
        ----------
1800
        template : :class:`~pincer.objects.guild.template.GuildTemplate`
1801
            The template to edit
1802
        name : Optional[:class:`str`]
1803
            Name of the template (1-100 characters)
1804
            |default| :data:`None`
1805
        description : Optional[:class:`str`]
1806
            Description of the template (0-120 characters)
1807
            |default| :data:`None`
1808
1809
        Returns
1810
        -------
1811
        :class:`~pincer.objects.guild.template.GuildTemplate`
1812
            The edited template object.
1813
        """
1814
        data = await self._http.patch(
1815
            f"guilds/{self.id}/templates/{template.code}",
1816
            data={
1817
                "name": name,
1818
                "description": description
1819
            }
1820
        )
1821
        return GuildTemplate.from_dict(
1822
            construct_client_dict(self._client, data)
1823
        )
1824
1825
    async def delete_template(
1826
        self,
1827
        template: GuildTemplate
1828
    ) -> GuildTemplate:
1829
        """|coro|
1830
        Deletes the given template.
1831
        Requires the ``MANAGE_GUILD`` permission.
1832
1833
        Parameters
1834
        ----------
1835
        template : :class:`~pincer.objects.guild.template.GuildTemplate`
1836
            The template to delete
1837
        
1838
        Returns
1839
        -------
1840
        :class:`~pincer.objects.guild.template.GuildTemplate`
1841
            The deleted template object.
1842
        """
1843
        data = await self._http.delete(
1844
            f"guilds/{self.id}/templates/{template.code}"
1845
        )
1846
        return GuildTemplate.from_dict(
1847
            construct_client_dict(self._client, data)
1848
        )
1849
1850
    async def get_webhooks(self) -> AsyncGenerator[Webhook, None]:
1851
        """|coro|
1852
        Returns an async generator of the guild webhooks.
1853
1854
        Yields
1855
        -------
1856
        AsyncGenerator[:class:`~pincer.objects.guild.webhook.Webhook`, None]
1857
            The guild webhook object.
1858
        """
1859
        data = await self._http.get(f"guilds/{self.id}/webhooks")
1860
        for webhook_data in data:
1861
            yield Webhook.from_dict(
1862
                construct_client_dict(self._client, webhook_data)
1863
            )
1864
1865
    @classmethod
1866
    def from_dict(cls, data) -> Guild:
1867
        """
1868
        Parameters
1869
        ----------
1870
        data : :class:`Dict`
1871
            Guild data received from the discord API.
1872
        Returns
1873
        -------
1874
        :class:`~pincer.objects.guild.guild.Guild`
1875
            The new guild object.
1876
        Raises
1877
        :class:`~pincer.exceptions.UnavailableGuildError`
1878
            The guild is unavailable due to a discord outage.
1879
        """
1880
        if data.get("unavailable", False):
1881
            raise UnavailableGuildError(
1882
                f"Guild \"{data['id']}\" is unavailable due to a discord"
1883
                " outage."
1884
            )
1885
1886
        return super().from_dict(data)
1887
1888
1889
@dataclass(repr=False)
1890
class UnavailableGuild(APIObject):
1891
    id: Snowflake
1892
    unavailable: bool = True
1893