|
|
@ -25,7 +25,7 @@ DEALINGS IN THE SOFTWARE. |
|
|
|
from __future__ import annotations |
|
|
|
|
|
|
|
import datetime |
|
|
|
from typing import List, TYPE_CHECKING |
|
|
|
from typing import Any, Dict, List, Optional, TYPE_CHECKING, Union |
|
|
|
|
|
|
|
from .asset import Asset |
|
|
|
from .enums import ActivityType, try_enum |
|
|
@ -121,10 +121,10 @@ class BaseActivity: |
|
|
|
__slots__ = ('_created_at',) |
|
|
|
|
|
|
|
def __init__(self, **kwargs): |
|
|
|
self._created_at = kwargs.pop('created_at', None) |
|
|
|
self._created_at: Optional[float] = kwargs.pop('created_at', None) |
|
|
|
|
|
|
|
@property |
|
|
|
def created_at(self): |
|
|
|
def created_at(self) -> Optional[datetime.datetime]: |
|
|
|
"""Optional[:class:`datetime.datetime`]: When the user started doing this activity in UTC. |
|
|
|
|
|
|
|
.. versionadded:: 1.3 |
|
|
@ -147,17 +147,17 @@ class Activity(BaseActivity): |
|
|
|
|
|
|
|
Attributes |
|
|
|
------------ |
|
|
|
application_id: :class:`int` |
|
|
|
application_id: Optional[:class:`int`] |
|
|
|
The application ID of the game. |
|
|
|
name: :class:`str` |
|
|
|
name: Optional[:class:`str`] |
|
|
|
The name of the activity. |
|
|
|
url: :class:`str` |
|
|
|
url: Optional[:class:`str`] |
|
|
|
A stream URL that the activity could be doing. |
|
|
|
type: :class:`ActivityType` |
|
|
|
The type of activity currently being done. |
|
|
|
state: :class:`str` |
|
|
|
state: Optional[:class:`str`] |
|
|
|
The user's current state. For example, "In Game". |
|
|
|
details: :class:`str` |
|
|
|
details: Optional[:class:`str`] |
|
|
|
The detail of the user's current activity. |
|
|
|
timestamps: :class:`dict` |
|
|
|
A dictionary of timestamps. It contains the following optional keys: |
|
|
@ -214,29 +214,28 @@ class Activity(BaseActivity): |
|
|
|
|
|
|
|
def __init__(self, **kwargs): |
|
|
|
super().__init__(**kwargs) |
|
|
|
self.state = kwargs.pop('state', None) |
|
|
|
self.details = kwargs.pop('details', None) |
|
|
|
self.state: Optional[str] = kwargs.pop('state', None) |
|
|
|
self.details: Optional[str] = kwargs.pop('details', None) |
|
|
|
self.timestamps: ActivityTimestamps = kwargs.pop('timestamps', {}) |
|
|
|
self.assets: ActivityAssets = kwargs.pop('assets', {}) |
|
|
|
self.party: ActivityParty = kwargs.pop('party', {}) |
|
|
|
self.application_id = _get_as_snowflake(kwargs, 'application_id') |
|
|
|
self.name = kwargs.pop('name', None) |
|
|
|
self.url = kwargs.pop('url', None) |
|
|
|
self.flags = kwargs.pop('flags', 0) |
|
|
|
self.sync_id = kwargs.pop('sync_id', None) |
|
|
|
self.session_id = kwargs.pop('session_id', None) |
|
|
|
self.application_id: Optional[int] = _get_as_snowflake(kwargs, 'application_id') |
|
|
|
self.name: Optional[str] = kwargs.pop('name', None) |
|
|
|
self.url: Optional[str] = kwargs.pop('url', None) |
|
|
|
self.flags: int = kwargs.pop('flags', 0) |
|
|
|
self.sync_id: Optional[str] = kwargs.pop('sync_id', None) |
|
|
|
self.session_id: Optional[str] = kwargs.pop('session_id', None) |
|
|
|
self.buttons: List[ActivityButton] = kwargs.pop('buttons', []) |
|
|
|
|
|
|
|
activity_type = kwargs.pop('type', -1) |
|
|
|
self.type = activity_type if isinstance(activity_type, ActivityType) else try_enum(ActivityType, activity_type) |
|
|
|
self.type: ActivityType = ( |
|
|
|
activity_type if isinstance(activity_type, ActivityType) else try_enum(ActivityType, activity_type) |
|
|
|
) |
|
|
|
|
|
|
|
emoji = kwargs.pop('emoji', None) |
|
|
|
if emoji is not None: |
|
|
|
self.emoji = PartialEmoji.from_dict(emoji) |
|
|
|
else: |
|
|
|
self.emoji = None |
|
|
|
self.emoji: Optional[PartialEmoji] = PartialEmoji.from_dict(emoji) if emoji is not None else None |
|
|
|
|
|
|
|
def __repr__(self): |
|
|
|
def __repr__(self) -> str: |
|
|
|
attrs = ( |
|
|
|
('type', self.type), |
|
|
|
('name', self.name), |
|
|
@ -249,8 +248,8 @@ class Activity(BaseActivity): |
|
|
|
inner = ' '.join('%s=%r' % t for t in attrs) |
|
|
|
return f'<Activity {inner}>' |
|
|
|
|
|
|
|
def to_dict(self): |
|
|
|
ret = {} |
|
|
|
def to_dict(self) -> Dict[str, Any]: |
|
|
|
ret: Dict[str, Any] = {} |
|
|
|
for attr in self.__slots__: |
|
|
|
value = getattr(self, attr, None) |
|
|
|
if value is None: |
|
|
@ -266,7 +265,7 @@ class Activity(BaseActivity): |
|
|
|
return ret |
|
|
|
|
|
|
|
@property |
|
|
|
def start(self): |
|
|
|
def start(self) -> Optional[datetime.datetime]: |
|
|
|
"""Optional[:class:`datetime.datetime`]: When the user started doing this activity in UTC, if applicable.""" |
|
|
|
try: |
|
|
|
timestamp = self.timestamps['start'] / 1000 |
|
|
@ -276,7 +275,7 @@ class Activity(BaseActivity): |
|
|
|
return datetime.datetime.utcfromtimestamp(timestamp).replace(tzinfo=datetime.timezone.utc) |
|
|
|
|
|
|
|
@property |
|
|
|
def end(self): |
|
|
|
def end(self) -> Optional[datetime.datetime]: |
|
|
|
"""Optional[:class:`datetime.datetime`]: When the user will stop doing this activity in UTC, if applicable.""" |
|
|
|
try: |
|
|
|
timestamp = self.timestamps['end'] / 1000 |
|
|
@ -286,7 +285,7 @@ class Activity(BaseActivity): |
|
|
|
return datetime.datetime.utcfromtimestamp(timestamp).replace(tzinfo=datetime.timezone.utc) |
|
|
|
|
|
|
|
@property |
|
|
|
def large_image_url(self): |
|
|
|
def large_image_url(self) -> Optional[str]: |
|
|
|
"""Optional[:class:`str`]: Returns a URL pointing to the large image asset of this activity if applicable.""" |
|
|
|
if self.application_id is None: |
|
|
|
return None |
|
|
@ -299,7 +298,7 @@ class Activity(BaseActivity): |
|
|
|
return Asset.BASE + f'/app-assets/{self.application_id}/{large_image}.png' |
|
|
|
|
|
|
|
@property |
|
|
|
def small_image_url(self): |
|
|
|
def small_image_url(self) -> Optional[str]: |
|
|
|
"""Optional[:class:`str`]: Returns a URL pointing to the small image asset of this activity if applicable.""" |
|
|
|
if self.application_id is None: |
|
|
|
return None |
|
|
@ -312,12 +311,12 @@ class Activity(BaseActivity): |
|
|
|
return Asset.BASE + f'/app-assets/{self.application_id}/{small_image}.png' |
|
|
|
|
|
|
|
@property |
|
|
|
def large_image_text(self): |
|
|
|
def large_image_text(self) -> Optional[str]: |
|
|
|
"""Optional[:class:`str`]: Returns the large image asset hover text of this activity if applicable.""" |
|
|
|
return self.assets.get('large_text', None) |
|
|
|
|
|
|
|
@property |
|
|
|
def small_image_text(self): |
|
|
|
def small_image_text(self) -> Optional[str]: |
|
|
|
"""Optional[:class:`str`]: Returns the small image asset hover text of this activity if applicable.""" |
|
|
|
return self.assets.get('small_text', None) |
|
|
|
|
|
|
@ -358,9 +357,9 @@ class Game(BaseActivity): |
|
|
|
|
|
|
|
__slots__ = ('name', '_end', '_start') |
|
|
|
|
|
|
|
def __init__(self, name, **extra): |
|
|
|
def __init__(self, name: str, **extra): |
|
|
|
super().__init__(**extra) |
|
|
|
self.name = name |
|
|
|
self.name: str = name |
|
|
|
|
|
|
|
try: |
|
|
|
timestamps: ActivityTimestamps = extra['timestamps'] |
|
|
@ -372,7 +371,7 @@ class Game(BaseActivity): |
|
|
|
self._end = timestamps.get('end', 0) |
|
|
|
|
|
|
|
@property |
|
|
|
def type(self): |
|
|
|
def type(self) -> ActivityType: |
|
|
|
""":class:`ActivityType`: Returns the game's type. This is for compatibility with :class:`Activity`. |
|
|
|
|
|
|
|
It always returns :attr:`ActivityType.playing`. |
|
|
@ -380,27 +379,27 @@ class Game(BaseActivity): |
|
|
|
return ActivityType.playing |
|
|
|
|
|
|
|
@property |
|
|
|
def start(self): |
|
|
|
def start(self) -> Optional[datetime.datetime]: |
|
|
|
"""Optional[:class:`datetime.datetime`]: When the user started playing this game in UTC, if applicable.""" |
|
|
|
if self._start: |
|
|
|
return datetime.datetime.utcfromtimestamp(self._start / 1000).replace(tzinfo=datetime.timezone.utc) |
|
|
|
return None |
|
|
|
|
|
|
|
@property |
|
|
|
def end(self): |
|
|
|
def end(self) -> Optional[datetime.datetime]: |
|
|
|
"""Optional[:class:`datetime.datetime`]: When the user will stop playing this game in UTC, if applicable.""" |
|
|
|
if self._end: |
|
|
|
return datetime.datetime.utcfromtimestamp(self._end / 1000).replace(tzinfo=datetime.timezone.utc) |
|
|
|
return None |
|
|
|
|
|
|
|
def __str__(self): |
|
|
|
def __str__(self) -> str: |
|
|
|
return str(self.name) |
|
|
|
|
|
|
|
def __repr__(self): |
|
|
|
def __repr__(self) -> str: |
|
|
|
return f'<Game name={self.name!r}>' |
|
|
|
|
|
|
|
def to_dict(self): |
|
|
|
timestamps = {} |
|
|
|
def to_dict(self) -> Dict[str, Any]: |
|
|
|
timestamps: Dict[str, Any] = {} |
|
|
|
if self._start: |
|
|
|
timestamps['start'] = self._start |
|
|
|
|
|
|
@ -415,13 +414,13 @@ class Game(BaseActivity): |
|
|
|
} |
|
|
|
# fmt: on |
|
|
|
|
|
|
|
def __eq__(self, other): |
|
|
|
def __eq__(self, other: Any) -> bool: |
|
|
|
return isinstance(other, Game) and other.name == self.name |
|
|
|
|
|
|
|
def __ne__(self, other): |
|
|
|
def __ne__(self, other: Any) -> bool: |
|
|
|
return not self.__eq__(other) |
|
|
|
|
|
|
|
def __hash__(self): |
|
|
|
def __hash__(self) -> int: |
|
|
|
return hash(self.name) |
|
|
|
|
|
|
|
|
|
|
@ -450,7 +449,7 @@ class Streaming(BaseActivity): |
|
|
|
|
|
|
|
Attributes |
|
|
|
----------- |
|
|
|
platform: :class:`str` |
|
|
|
platform: Optional[:class:`str`] |
|
|
|
Where the user is streaming from (ie. YouTube, Twitch). |
|
|
|
|
|
|
|
.. versionadded:: 1.3 |
|
|
@ -472,27 +471,27 @@ class Streaming(BaseActivity): |
|
|
|
|
|
|
|
__slots__ = ('platform', 'name', 'game', 'url', 'details', 'assets') |
|
|
|
|
|
|
|
def __init__(self, *, name, url, **extra): |
|
|
|
def __init__(self, *, name: Optional[str], url: str, **extra: Any): |
|
|
|
super().__init__(**extra) |
|
|
|
self.platform = name |
|
|
|
self.name = extra.pop('details', name) |
|
|
|
self.game = extra.pop('state', None) |
|
|
|
self.url = url |
|
|
|
self.details = extra.pop('details', self.name) # compatibility |
|
|
|
self.platform: Optional[str] = name |
|
|
|
self.name: Optional[str] = extra.pop('details', name) |
|
|
|
self.game: Optional[str] = extra.pop('state', None) |
|
|
|
self.url: str = url |
|
|
|
self.details: Optional[str] = extra.pop('details', self.name) # compatibility |
|
|
|
self.assets: ActivityAssets = extra.pop('assets', {}) |
|
|
|
|
|
|
|
@property |
|
|
|
def type(self): |
|
|
|
def type(self) -> ActivityType: |
|
|
|
""":class:`ActivityType`: Returns the game's type. This is for compatibility with :class:`Activity`. |
|
|
|
|
|
|
|
It always returns :attr:`ActivityType.streaming`. |
|
|
|
""" |
|
|
|
return ActivityType.streaming |
|
|
|
|
|
|
|
def __str__(self): |
|
|
|
def __str__(self) -> str: |
|
|
|
return str(self.name) |
|
|
|
|
|
|
|
def __repr__(self): |
|
|
|
def __repr__(self) -> str: |
|
|
|
return f'<Streaming name={self.name!r}>' |
|
|
|
|
|
|
|
@property |
|
|
@ -510,9 +509,9 @@ class Streaming(BaseActivity): |
|
|
|
else: |
|
|
|
return name[7:] if name[:7] == 'twitch:' else None |
|
|
|
|
|
|
|
def to_dict(self): |
|
|
|
def to_dict(self) -> Dict[str, Any]: |
|
|
|
# fmt: off |
|
|
|
ret = { |
|
|
|
ret: Dict[str, Any] = { |
|
|
|
'type': ActivityType.streaming.value, |
|
|
|
'name': str(self.name), |
|
|
|
'url': str(self.url), |
|
|
@ -523,13 +522,13 @@ class Streaming(BaseActivity): |
|
|
|
ret['details'] = self.details |
|
|
|
return ret |
|
|
|
|
|
|
|
def __eq__(self, other): |
|
|
|
def __eq__(self, other: Any) -> bool: |
|
|
|
return isinstance(other, Streaming) and other.name == self.name and other.url == self.url |
|
|
|
|
|
|
|
def __ne__(self, other): |
|
|
|
def __ne__(self, other: Any) -> bool: |
|
|
|
return not self.__eq__(other) |
|
|
|
|
|
|
|
def __hash__(self): |
|
|
|
def __hash__(self) -> int: |
|
|
|
return hash(self.name) |
|
|
|
|
|
|
|
|
|
|
@ -559,17 +558,17 @@ class Spotify: |
|
|
|
__slots__ = ('_state', '_details', '_timestamps', '_assets', '_party', '_sync_id', '_session_id', '_created_at') |
|
|
|
|
|
|
|
def __init__(self, **data): |
|
|
|
self._state = data.pop('state', None) |
|
|
|
self._details = data.pop('details', None) |
|
|
|
self._timestamps = data.pop('timestamps', {}) |
|
|
|
self._assets = data.pop('assets', {}) |
|
|
|
self._party = data.pop('party', {}) |
|
|
|
self._sync_id = data.pop('sync_id') |
|
|
|
self._session_id = data.pop('session_id') |
|
|
|
self._created_at = data.pop('created_at', None) |
|
|
|
self._state: str = data.pop('state', '') |
|
|
|
self._details: str = data.pop('details', '') |
|
|
|
self._timestamps: Dict[str, int] = data.pop('timestamps', {}) |
|
|
|
self._assets: ActivityAssets = data.pop('assets', {}) |
|
|
|
self._party: ActivityParty = data.pop('party', {}) |
|
|
|
self._sync_id: str = data.pop('sync_id') |
|
|
|
self._session_id: str = data.pop('session_id') |
|
|
|
self._created_at: Optional[float] = data.pop('created_at', None) |
|
|
|
|
|
|
|
@property |
|
|
|
def type(self): |
|
|
|
def type(self) -> ActivityType: |
|
|
|
""":class:`ActivityType`: Returns the activity's type. This is for compatibility with :class:`Activity`. |
|
|
|
|
|
|
|
It always returns :attr:`ActivityType.listening`. |
|
|
@ -577,7 +576,7 @@ class Spotify: |
|
|
|
return ActivityType.listening |
|
|
|
|
|
|
|
@property |
|
|
|
def created_at(self): |
|
|
|
def created_at(self) -> Optional[datetime.datetime]: |
|
|
|
"""Optional[:class:`datetime.datetime`]: When the user started listening in UTC. |
|
|
|
|
|
|
|
.. versionadded:: 1.3 |
|
|
@ -586,20 +585,20 @@ class Spotify: |
|
|
|
return datetime.datetime.utcfromtimestamp(self._created_at / 1000).replace(tzinfo=datetime.timezone.utc) |
|
|
|
|
|
|
|
@property |
|
|
|
def colour(self): |
|
|
|
def colour(self) -> Colour: |
|
|
|
""":class:`Colour`: Returns the Spotify integration colour, as a :class:`Colour`. |
|
|
|
|
|
|
|
There is an alias for this named :attr:`color`""" |
|
|
|
return Colour(0x1DB954) |
|
|
|
|
|
|
|
@property |
|
|
|
def color(self): |
|
|
|
def color(self) -> Colour: |
|
|
|
""":class:`Colour`: Returns the Spotify integration colour, as a :class:`Colour`. |
|
|
|
|
|
|
|
There is an alias for this named :attr:`colour`""" |
|
|
|
return self.colour |
|
|
|
|
|
|
|
def to_dict(self): |
|
|
|
def to_dict(self) -> Dict[str, Any]: |
|
|
|
return { |
|
|
|
'flags': 48, # SYNC | PLAY |
|
|
|
'name': 'Spotify', |
|
|
@ -613,11 +612,11 @@ class Spotify: |
|
|
|
} |
|
|
|
|
|
|
|
@property |
|
|
|
def name(self): |
|
|
|
def name(self) -> str: |
|
|
|
""":class:`str`: The activity's name. This will always return "Spotify".""" |
|
|
|
return 'Spotify' |
|
|
|
|
|
|
|
def __eq__(self, other): |
|
|
|
def __eq__(self, other: Any) -> bool: |
|
|
|
return ( |
|
|
|
isinstance(other, Spotify) |
|
|
|
and other._session_id == self._session_id |
|
|
@ -625,30 +624,30 @@ class Spotify: |
|
|
|
and other.start == self.start |
|
|
|
) |
|
|
|
|
|
|
|
def __ne__(self, other): |
|
|
|
def __ne__(self, other: Any) -> bool: |
|
|
|
return not self.__eq__(other) |
|
|
|
|
|
|
|
def __hash__(self): |
|
|
|
def __hash__(self) -> int: |
|
|
|
return hash(self._session_id) |
|
|
|
|
|
|
|
def __str__(self): |
|
|
|
def __str__(self) -> str: |
|
|
|
return 'Spotify' |
|
|
|
|
|
|
|
def __repr__(self): |
|
|
|
def __repr__(self) -> str: |
|
|
|
return f'<Spotify title={self.title!r} artist={self.artist!r} track_id={self.track_id!r}>' |
|
|
|
|
|
|
|
@property |
|
|
|
def title(self): |
|
|
|
def title(self) -> str: |
|
|
|
""":class:`str`: The title of the song being played.""" |
|
|
|
return self._details |
|
|
|
|
|
|
|
@property |
|
|
|
def artists(self): |
|
|
|
def artists(self) -> List[str]: |
|
|
|
"""List[:class:`str`]: The artists of the song being played.""" |
|
|
|
return self._state.split('; ') |
|
|
|
|
|
|
|
@property |
|
|
|
def artist(self): |
|
|
|
def artist(self) -> str: |
|
|
|
""":class:`str`: The artist of the song being played. |
|
|
|
|
|
|
|
This does not attempt to split the artist information into |
|
|
@ -657,12 +656,12 @@ class Spotify: |
|
|
|
return self._state |
|
|
|
|
|
|
|
@property |
|
|
|
def album(self): |
|
|
|
def album(self) -> str: |
|
|
|
""":class:`str`: The album that the song being played belongs to.""" |
|
|
|
return self._assets.get('large_text', '') |
|
|
|
|
|
|
|
@property |
|
|
|
def album_cover_url(self): |
|
|
|
def album_cover_url(self) -> str: |
|
|
|
""":class:`str`: The album cover image URL from Spotify's CDN.""" |
|
|
|
large_image = self._assets.get('large_image', '') |
|
|
|
if large_image[:8] != 'spotify:': |
|
|
@ -671,35 +670,35 @@ class Spotify: |
|
|
|
return 'https://i.scdn.co/image/' + album_image_id |
|
|
|
|
|
|
|
@property |
|
|
|
def track_id(self): |
|
|
|
def track_id(self) -> str: |
|
|
|
""":class:`str`: The track ID used by Spotify to identify this song.""" |
|
|
|
return self._sync_id |
|
|
|
|
|
|
|
|
|
|
|
@property |
|
|
|
def track_url(self) -> str: |
|
|
|
""":class:`str`: The track URL to listen on Spotify. |
|
|
|
|
|
|
|
|
|
|
|
.. versionadded:: 2.0 |
|
|
|
""" |
|
|
|
return f'https://open.spotify.com/track/{self.track_id}' |
|
|
|
|
|
|
|
@property |
|
|
|
def start(self): |
|
|
|
def start(self) -> datetime.datetime: |
|
|
|
""":class:`datetime.datetime`: When the user started playing this song in UTC.""" |
|
|
|
return datetime.datetime.utcfromtimestamp(self._timestamps['start'] / 1000).replace(tzinfo=datetime.timezone.utc) |
|
|
|
|
|
|
|
@property |
|
|
|
def end(self): |
|
|
|
def end(self) -> datetime.datetime: |
|
|
|
""":class:`datetime.datetime`: When the user will stop playing this song in UTC.""" |
|
|
|
return datetime.datetime.utcfromtimestamp(self._timestamps['end'] / 1000).replace(tzinfo=datetime.timezone.utc) |
|
|
|
|
|
|
|
@property |
|
|
|
def duration(self): |
|
|
|
def duration(self) -> datetime.timedelta: |
|
|
|
""":class:`datetime.timedelta`: The duration of the song being played.""" |
|
|
|
return self.end - self.start |
|
|
|
|
|
|
|
@property |
|
|
|
def party_id(self): |
|
|
|
def party_id(self) -> str: |
|
|
|
""":class:`str`: The party ID of the listening party.""" |
|
|
|
return self._party.get('id', '') |
|
|
|
|
|
|
@ -737,13 +736,14 @@ class CustomActivity(BaseActivity): |
|
|
|
|
|
|
|
__slots__ = ('name', 'emoji', 'state') |
|
|
|
|
|
|
|
def __init__(self, name, *, emoji=None, **extra): |
|
|
|
def __init__(self, name: Optional[str], *, emoji: Optional[PartialEmoji] = None, **extra: Any): |
|
|
|
super().__init__(**extra) |
|
|
|
self.name = name |
|
|
|
self.state = extra.pop('state', None) |
|
|
|
self.name: Optional[str] = name |
|
|
|
self.state: Optional[str] = extra.pop('state', None) |
|
|
|
if self.name == 'Custom Status': |
|
|
|
self.name = self.state |
|
|
|
|
|
|
|
self.emoji: Optional[PartialEmoji] |
|
|
|
if emoji is None: |
|
|
|
self.emoji = emoji |
|
|
|
elif isinstance(emoji, dict): |
|
|
@ -756,14 +756,14 @@ class CustomActivity(BaseActivity): |
|
|
|
raise TypeError(f'Expected str, PartialEmoji, or None, received {type(emoji)!r} instead.') |
|
|
|
|
|
|
|
@property |
|
|
|
def type(self): |
|
|
|
def type(self) -> ActivityType: |
|
|
|
""":class:`ActivityType`: Returns the activity's type. This is for compatibility with :class:`Activity`. |
|
|
|
|
|
|
|
It always returns :attr:`ActivityType.custom`. |
|
|
|
""" |
|
|
|
return ActivityType.custom |
|
|
|
|
|
|
|
def to_dict(self): |
|
|
|
def to_dict(self) -> Dict[str, Any]: |
|
|
|
if self.name == self.state: |
|
|
|
o = { |
|
|
|
'type': ActivityType.custom.value, |
|
|
@ -780,16 +780,16 @@ class CustomActivity(BaseActivity): |
|
|
|
o['emoji'] = self.emoji.to_dict() |
|
|
|
return o |
|
|
|
|
|
|
|
def __eq__(self, other): |
|
|
|
def __eq__(self, other: Any) -> bool: |
|
|
|
return isinstance(other, CustomActivity) and other.name == self.name and other.emoji == self.emoji |
|
|
|
|
|
|
|
def __ne__(self, other): |
|
|
|
def __ne__(self, other: Any) -> bool: |
|
|
|
return not self.__eq__(other) |
|
|
|
|
|
|
|
def __hash__(self): |
|
|
|
def __hash__(self) -> int: |
|
|
|
return hash((self.name, str(self.emoji))) |
|
|
|
|
|
|
|
def __str__(self): |
|
|
|
def __str__(self) -> str: |
|
|
|
if self.emoji: |
|
|
|
if self.name: |
|
|
|
return f'{self.emoji} {self.name}' |
|
|
@ -797,11 +797,11 @@ class CustomActivity(BaseActivity): |
|
|
|
else: |
|
|
|
return str(self.name) |
|
|
|
|
|
|
|
def __repr__(self): |
|
|
|
def __repr__(self) -> str: |
|
|
|
return f'<CustomActivity name={self.name!r} emoji={self.emoji!r}>' |
|
|
|
|
|
|
|
|
|
|
|
def create_activity(data): |
|
|
|
def create_activity(data: Optional[Dict[str, Any]]) -> Optional[Union[Activity, Game, CustomActivity, Streaming, Spotify]]: |
|
|
|
if not data: |
|
|
|
return None |
|
|
|
|
|
|
|