Skip to content

Commit 83655a5

Browse files
authored
Merge pull request #441 from BobDotCom/timeout
baseholder implementation for timeouts
2 parents d4f5576 + 76bc770 commit 83655a5

File tree

2 files changed

+84
-13
lines changed

2 files changed

+84
-13
lines changed

discord/member.py

Lines changed: 83 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -252,6 +252,10 @@ class Member(discord.abc.Messageable, _UserTag):
252252
premium_since: Optional[:class:`datetime.datetime`]
253253
An aware datetime object that specifies the date and time in UTC when the member used their
254254
"Nitro boost" on the guild, if available. This could be ``None``.
255+
communication_disabled_until: Optional[:class:`datetime.datetime`]
256+
An aware datetime object that specifies the date and time in UTC when the member will be removed from timeout.
257+
258+
.. versionadded:: 2.0
255259
"""
256260

257261
__slots__ = (
@@ -266,6 +270,7 @@ class Member(discord.abc.Messageable, _UserTag):
266270
'_user',
267271
'_state',
268272
'_avatar',
273+
'communication_disabled_until',
269274
)
270275

271276
if TYPE_CHECKING:
@@ -284,6 +289,7 @@ class Member(discord.abc.Messageable, _UserTag):
284289
banner: Optional[Asset]
285290
accent_color: Optional[Colour]
286291
accent_colour: Optional[Colour]
292+
communication_disabled_until: Optional[datetime.datetime]
287293

288294
def __init__(self, *, data: MemberWithUserPayload, guild: Guild, state: ConnectionState):
289295
self._state: ConnectionState = state
@@ -297,6 +303,7 @@ def __init__(self, *, data: MemberWithUserPayload, guild: Guild, state: Connecti
297303
self.nick: Optional[str] = data.get('nick', None)
298304
self.pending: bool = data.get('pending', False)
299305
self._avatar: Optional[str] = data.get('avatar')
306+
self.communication_disabled_until: Optional[datetime.datetime] = utils.parse_time(data.get('communication_disabled_until'))
300307

301308
def __str__(self) -> str:
302309
return str(self._user)
@@ -354,6 +361,7 @@ def _copy(cls: Type[M], member: M) -> M:
354361
self.activities = member.activities
355362
self._state = member._state
356363
self._avatar = member._avatar
364+
self.communication_disabled_until = member.communication_disabled_until
357365

358366
# Reference will not be copied unless necessary by PRESENCE_UPDATE
359367
# See below
@@ -380,6 +388,7 @@ def _update(self, data: MemberPayload) -> None:
380388
self.premium_since = utils.parse_time(data.get('premium_since'))
381389
self._roles = utils.SnowflakeList(map(int, data['roles']))
382390
self._avatar = data.get('avatar')
391+
self.communication_disabled_until = utils.parse_time(data.get('communication_disabled_until'))
383392

384393
def _presence_update(self, data: PartialPresenceUpdate, user: UserPayload) -> Optional[Tuple[User, User]]:
385394
self.activities = tuple(map(create_activity, data['activities']))
@@ -645,26 +654,29 @@ async def edit(
645654
roles: List[discord.abc.Snowflake] = MISSING,
646655
voice_channel: Optional[VocalGuildChannel] = MISSING,
647656
reason: Optional[str] = None,
657+
communication_disabled_until: Optional[datetime.datetime] = MISSING,
648658
) -> Optional[Member]:
649659
"""|coro|
650660
651661
Edits the member's data.
652662
653663
Depending on the parameter passed, this requires different permissions listed below:
654664
655-
+---------------+--------------------------------------+
656-
| Parameter | Permission |
657-
+---------------+--------------------------------------+
658-
| nick | :attr:`Permissions.manage_nicknames` |
659-
+---------------+--------------------------------------+
660-
| mute | :attr:`Permissions.mute_members` |
661-
+---------------+--------------------------------------+
662-
| deafen | :attr:`Permissions.deafen_members` |
663-
+---------------+--------------------------------------+
664-
| roles | :attr:`Permissions.manage_roles` |
665-
+---------------+--------------------------------------+
666-
| voice_channel | :attr:`Permissions.move_members` |
667-
+---------------+--------------------------------------+
665+
+------------------------------+--------------------------------------+
666+
| Parameter | Permission |
667+
+------------------------------+--------------------------------------+
668+
| nick | :attr:`Permissions.manage_nicknames` |
669+
+------------------------------+--------------------------------------+
670+
| mute | :attr:`Permissions.mute_members` |
671+
+------------------------------+--------------------------------------+
672+
| deafen | :attr:`Permissions.deafen_members` |
673+
+------------------------------+--------------------------------------+
674+
| roles | :attr:`Permissions.manage_roles` |
675+
+------------------------------+--------------------------------------+
676+
| voice_channel | :attr:`Permissions.move_members` |
677+
+------------------------------+--------------------------------------+
678+
| communication_disabled_until | :attr:`Permissions.manage_members` |
679+
+------------------------------+--------------------------------------+
668680
669681
All parameters are optional.
670682
@@ -694,7 +706,11 @@ async def edit(
694706
Pass ``None`` to kick them from voice.
695707
reason: Optional[:class:`str`]
696708
The reason for editing this member. Shows up on the audit log.
709+
communication_disabled_until: Optional[:class:`datetime.datetime`]
710+
Temporarily puts the member in timeout until this time. If the value is ``None``, then the user is removed
711+
from timeout.
697712
713+
.. versionadded:: 2.0
698714
Raises
699715
-------
700716
Forbidden
@@ -748,10 +764,64 @@ async def edit(
748764
if roles is not MISSING:
749765
payload['roles'] = tuple(r.id for r in roles)
750766

767+
if communication_disabled_until is not MISSING:
768+
if communication_disabled_until is not None:
769+
payload['communication_disabled_until'] = communication_disabled_until.isoformat()
770+
else:
771+
payload['communication_disabled_until'] = communication_disabled_until
772+
751773
if payload:
752774
data = await http.edit_member(guild_id, self.id, reason=reason, **payload)
753775
return Member(data=data, guild=self.guild, state=self._state)
754776

777+
async def timeout(self, until: Optional[datetime.datetime], reason: str = None) -> None:
778+
"""|coro|
779+
780+
Timeouts a member from the guild for the set duration.
781+
782+
You must have the :attr:`~Permissions.manage_members` permission to
783+
timeout a member.
784+
785+
Parameters
786+
-----------
787+
until: :class:`datetime.datetime`
788+
The date and time to timeout the member for. If this is ``None`` then the member is removed from timeout.
789+
reason: Optional[:class:`str`]
790+
The reason for doing this action. Shows up on the audit log.
791+
792+
Raises
793+
-------
794+
Forbidden
795+
You do not have permissions to timeout members.
796+
HTTPException
797+
An error occurred doing the request.
798+
"""
799+
await self.edit(communication_disabled_until=until, reason=reason)
800+
801+
async def remove_timeout(self, reason: str = None) -> None:
802+
"""|coro|
803+
804+
Removes the timeout from a member.
805+
806+
You must have the :attr:`~Permissions.manage_members` permission to
807+
remove the timeout.
808+
809+
This is equivalent to calling :meth:`~.timeout` and passing ``None`` to :param:`~.timeout.until`.
810+
811+
Parameters
812+
-----------
813+
reason: Optional[:class:`str`]
814+
The reason for doing this action. Shows up on the audit log.
815+
816+
Raises
817+
-------
818+
Forbidden
819+
You do not have permissions to remove the timeout.
820+
HTTPException
821+
An error occurred doing the request.
822+
"""
823+
await self.edit(communication_disabled_until=None, reason=reason)
824+
755825
async def request_to_speak(self) -> None:
756826
"""|coro|
757827

discord/types/member.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ class Member(PartialMember, total=False):
4646
premium_since: str
4747
pending: bool
4848
permissions: str
49+
communication_disabled_until: str
4950

5051

5152
class _OptionalMemberWithUser(PartialMember, total=False):

0 commit comments

Comments
 (0)