36
36
from .asset import Asset
37
37
from .utils import MISSING
38
38
from .user import BaseUser , ClientUser , User , _UserTag
39
- from .activity import create_activity , ActivityTypes
40
39
from .permissions import Permissions
41
- from .enums import Status , try_enum
40
+ from .enums import Status
42
41
from .errors import ClientException
43
42
from .colour import Colour
44
43
from .object import Object
45
44
from .flags import MemberFlags
45
+ from .presences import ClientStatus
46
46
47
47
__all__ = (
48
48
'VoiceState' ,
57
57
from .channel import DMChannel , VoiceChannel , StageChannel
58
58
from .flags import PublicUserFlags
59
59
from .guild import Guild
60
- from .types .activity import (
61
- ClientStatus as ClientStatusPayload ,
62
- PartialPresenceUpdate ,
63
- )
60
+ from .activity import ActivityTypes
61
+ from .presences import RawPresenceUpdateEvent
64
62
from .types .member import (
65
63
MemberWithUser as MemberWithUserPayload ,
66
64
Member as MemberPayload ,
@@ -168,46 +166,6 @@ def __repr__(self) -> str:
168
166
return f'<{ self .__class__ .__name__ } { inner } >'
169
167
170
168
171
- class _ClientStatus :
172
- __slots__ = ('_status' , 'desktop' , 'mobile' , 'web' )
173
-
174
- def __init__ (self ):
175
- self ._status : str = 'offline'
176
-
177
- self .desktop : Optional [str ] = None
178
- self .mobile : Optional [str ] = None
179
- self .web : Optional [str ] = None
180
-
181
- def __repr__ (self ) -> str :
182
- attrs = [
183
- ('_status' , self ._status ),
184
- ('desktop' , self .desktop ),
185
- ('mobile' , self .mobile ),
186
- ('web' , self .web ),
187
- ]
188
- inner = ' ' .join ('%s=%r' % t for t in attrs )
189
- return f'<{ self .__class__ .__name__ } { inner } >'
190
-
191
- def _update (self , status : str , data : ClientStatusPayload , / ) -> None :
192
- self ._status = status
193
-
194
- self .desktop = data .get ('desktop' )
195
- self .mobile = data .get ('mobile' )
196
- self .web = data .get ('web' )
197
-
198
- @classmethod
199
- def _copy (cls , client_status : Self , / ) -> Self :
200
- self = cls .__new__ (cls ) # bypass __init__
201
-
202
- self ._status = client_status ._status
203
-
204
- self .desktop = client_status .desktop
205
- self .mobile = client_status .mobile
206
- self .web = client_status .web
207
-
208
- return self
209
-
210
-
211
169
def flatten_user (cls : T ) -> T :
212
170
for attr , value in itertools .chain (BaseUser .__dict__ .items (), User .__dict__ .items ()):
213
171
# ignore private/special methods
@@ -306,6 +264,10 @@ class Member(discord.abc.Messageable, _UserTag):
306
264
This will be set to ``None`` or a time in the past if the user is not timed out.
307
265
308
266
.. versionadded:: 2.0
267
+ client_status: :class:`ClientStatus`
268
+ Model which holds information about the status of the member on various clients/platforms via presence updates.
269
+
270
+ .. versionadded:: 2.5
309
271
"""
310
272
311
273
__slots__ = (
@@ -318,7 +280,7 @@ class Member(discord.abc.Messageable, _UserTag):
318
280
'nick' ,
319
281
'timed_out_until' ,
320
282
'_permissions' ,
321
- '_client_status ' ,
283
+ 'client_status ' ,
322
284
'_user' ,
323
285
'_state' ,
324
286
'_avatar' ,
@@ -354,7 +316,7 @@ def __init__(self, *, data: MemberWithUserPayload, guild: Guild, state: Connecti
354
316
self .joined_at : Optional [datetime .datetime ] = utils .parse_time (data .get ('joined_at' ))
355
317
self .premium_since : Optional [datetime .datetime ] = utils .parse_time (data .get ('premium_since' ))
356
318
self ._roles : utils .SnowflakeList = utils .SnowflakeList (map (int , data ['roles' ]))
357
- self ._client_status : _ClientStatus = _ClientStatus ()
319
+ self .client_status : ClientStatus = ClientStatus ()
358
320
self .activities : Tuple [ActivityTypes , ...] = ()
359
321
self .nick : Optional [str ] = data .get ('nick' , None )
360
322
self .pending : bool = data .get ('pending' , False )
@@ -430,7 +392,7 @@ def _copy(cls, member: Self) -> Self:
430
392
self ._roles = utils .SnowflakeList (member ._roles , is_sorted = True )
431
393
self .joined_at = member .joined_at
432
394
self .premium_since = member .premium_since
433
- self ._client_status = _ClientStatus . _copy ( member ._client_status )
395
+ self .client_status = member .client_status
434
396
self .guild = member .guild
435
397
self .nick = member .nick
436
398
self .pending = member .pending
@@ -473,13 +435,12 @@ def _update(self, data: GuildMemberUpdateEvent) -> None:
473
435
self ._flags = data .get ('flags' , 0 )
474
436
self ._avatar_decoration_data = data .get ('avatar_decoration_data' )
475
437
476
- def _presence_update (self , data : PartialPresenceUpdate , user : UserPayload ) -> Optional [Tuple [User , User ]]:
477
- self .activities = tuple ( create_activity ( d , self . _state ) for d in data [ ' activities' ])
478
- self ._client_status . _update ( data [ 'status' ], data [ ' client_status' ])
438
+ def _presence_update (self , raw : RawPresenceUpdateEvent , user : UserPayload ) -> Optional [Tuple [User , User ]]:
439
+ self .activities = raw . activities
440
+ self .client_status = raw . client_status
479
441
480
442
if len (user ) > 1 :
481
443
return self ._update_inner_user (user )
482
- return None
483
444
484
445
def _update_inner_user (self , user : UserPayload ) -> Optional [Tuple [User , User ]]:
485
446
u = self ._user
@@ -518,39 +479,44 @@ def _update_inner_user(self, user: UserPayload) -> Optional[Tuple[User, User]]:
518
479
@property
519
480
def status (self ) -> Status :
520
481
""":class:`Status`: The member's overall status. If the value is unknown, then it will be a :class:`str` instead."""
521
- return try_enum ( Status , self ._client_status . _status )
482
+ return self .client_status . status
522
483
523
484
@property
524
485
def raw_status (self ) -> str :
525
486
""":class:`str`: The member's overall status as a string value.
526
487
527
488
.. versionadded:: 1.5
528
489
"""
529
- return self ._client_status ._status
490
+ return self .client_status ._status
530
491
531
492
@status .setter
532
493
def status (self , value : Status ) -> None :
533
494
# internal use only
534
- self ._client_status ._status = str (value )
495
+ self .client_status ._status = str (value )
535
496
536
497
@property
537
498
def mobile_status (self ) -> Status :
538
499
""":class:`Status`: The member's status on a mobile device, if applicable."""
539
- return try_enum ( Status , self ._client_status . mobile or 'offline' )
500
+ return self .client_status . mobile_status
540
501
541
502
@property
542
503
def desktop_status (self ) -> Status :
543
504
""":class:`Status`: The member's status on the desktop client, if applicable."""
544
- return try_enum ( Status , self ._client_status . desktop or 'offline' )
505
+ return self .client_status . desktop_status
545
506
546
507
@property
547
508
def web_status (self ) -> Status :
548
509
""":class:`Status`: The member's status on the web client, if applicable."""
549
- return try_enum ( Status , self ._client_status . web or 'offline' )
510
+ return self .client_status . web_status
550
511
551
512
def is_on_mobile (self ) -> bool :
552
- """:class:`bool`: A helper function that determines if a member is active on a mobile device."""
553
- return self ._client_status .mobile is not None
513
+ """A helper function that determines if a member is active on a mobile device.
514
+
515
+ Returns
516
+ -------
517
+ :class:`bool`
518
+ """
519
+ return self .client_status .is_on_mobile ()
554
520
555
521
@property
556
522
def colour (self ) -> Colour :
0 commit comments