Add Activity.buttons

This commit is contained in:
Nadir Chowdhury 2021-04-24 05:27:47 +01:00 committed by GitHub
parent 91c473db57
commit 829c2d4a1a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 75 additions and 17 deletions

View File

@ -22,7 +22,10 @@ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE. DEALINGS IN THE SOFTWARE.
""" """
from __future__ import annotations
import datetime import datetime
from typing import List, TYPE_CHECKING
from .asset import Asset from .asset import Asset
from .enums import ActivityType, try_enum from .enums import ActivityType, try_enum
@ -71,6 +74,9 @@ type: int
sync_id: str sync_id: str
session_id: str session_id: str
flags: int flags: int
buttons: list[dict]
label: str (max: 32)
url: str (max: 512)
There are also activity flags which are mostly uninteresting for the library atm. There are also activity flags which are mostly uninteresting for the library atm.
@ -84,6 +90,15 @@ t.ActivityFlags = {
} }
""" """
if TYPE_CHECKING:
from .types.activity import (
ActivityTimestamps,
ActivityParty,
ActivityAssets,
ActivityButton,
)
class BaseActivity: class BaseActivity:
"""The base activity that all user-settable activities inherit from. """The base activity that all user-settable activities inherit from.
A user-settable activity is one that can be used in :meth:`Client.change_presence`. A user-settable activity is one that can be used in :meth:`Client.change_presence`.
@ -102,6 +117,7 @@ class BaseActivity:
.. versionadded:: 1.3 .. versionadded:: 1.3
""" """
__slots__ = ('_created_at',) __slots__ = ('_created_at',)
def __init__(self, **kwargs): def __init__(self, **kwargs):
@ -116,6 +132,7 @@ class BaseActivity:
if self._created_at is not None: if self._created_at is not None:
return datetime.datetime.utcfromtimestamp(self._created_at / 1000) return datetime.datetime.utcfromtimestamp(self._created_at / 1000)
class Activity(BaseActivity): class Activity(BaseActivity):
"""Represents an activity in Discord. """Represents an activity in Discord.
@ -164,27 +181,51 @@ class Activity(BaseActivity):
- ``id``: A string representing the party ID. - ``id``: A string representing the party ID.
- ``size``: A list of up to two integer elements denoting (current_size, maximum_size). - ``size``: A list of up to two integer elements denoting (current_size, maximum_size).
buttons: List[:class:`dict`]
An list of dictionaries representing custom buttons shown in a rich presence.
Each dictionary contains the following keys:
- ``label``: A string representing the text shown on the button.
- ``url``: A string representing the URL opened upon clicking the button.
.. versionadded:: 2.0
emoji: Optional[:class:`PartialEmoji`] emoji: Optional[:class:`PartialEmoji`]
The emoji that belongs to this activity. The emoji that belongs to this activity.
""" """
__slots__ = ('state', 'details', '_created_at', 'timestamps', 'assets', 'party', __slots__ = (
'flags', 'sync_id', 'session_id', 'type', 'name', 'url', 'state',
'application_id', 'emoji') 'details',
'_created_at',
'timestamps',
'assets',
'party',
'flags',
'sync_id',
'session_id',
'type',
'name',
'url',
'application_id',
'emoji',
'buttons',
)
def __init__(self, **kwargs): def __init__(self, **kwargs):
super().__init__(**kwargs) super().__init__(**kwargs)
self.state = kwargs.pop('state', None) self.state = kwargs.pop('state', None)
self.details = kwargs.pop('details', None) self.details = kwargs.pop('details', None)
self.timestamps = kwargs.pop('timestamps', {}) self.timestamps: ActivityTimestamps = kwargs.pop('timestamps', {})
self.assets = kwargs.pop('assets', {}) self.assets: ActivityAssets = kwargs.pop('assets', {})
self.party = kwargs.pop('party', {}) self.party: ActivityParty = kwargs.pop('party', {})
self.application_id = _get_as_snowflake(kwargs, 'application_id') self.application_id = _get_as_snowflake(kwargs, 'application_id')
self.name = kwargs.pop('name', None) self.name = kwargs.pop('name', None)
self.url = kwargs.pop('url', None) self.url = kwargs.pop('url', None)
self.flags = kwargs.pop('flags', 0) self.flags = kwargs.pop('flags', 0)
self.sync_id = kwargs.pop('sync_id', None) self.sync_id = kwargs.pop('sync_id', None)
self.session_id = kwargs.pop('session_id', None) self.session_id = kwargs.pop('session_id', None)
self.buttons: List[ActivityButton] = kwargs.pop('buttons', [])
activity_type = kwargs.pop('type', -1) activity_type = kwargs.pop('type', -1)
self.type = activity_type if isinstance(activity_type, ActivityType) else try_enum(ActivityType, activity_type) self.type = activity_type if isinstance(activity_type, ActivityType) else try_enum(ActivityType, activity_type)
@ -269,6 +310,7 @@ class Activity(BaseActivity):
return None return None
else: else:
return Asset.BASE + f'/app-assets/{self.application_id}/{small_image}.png' return Asset.BASE + f'/app-assets/{self.application_id}/{small_image}.png'
@property @property
def large_image_text(self): def large_image_text(self):
"""Optional[:class:`str`]: Returns the large image asset hover text of this activity if applicable.""" """Optional[:class:`str`]: Returns the large image asset hover text of this activity if applicable."""
@ -321,7 +363,7 @@ class Game(BaseActivity):
self.name = name self.name = name
try: try:
timestamps = extra['timestamps'] timestamps: ActivityTimestamps = extra['timestamps']
except KeyError: except KeyError:
self._start = 0 self._start = 0
self._end = 0 self._end = 0
@ -365,11 +407,13 @@ class Game(BaseActivity):
if self._end: if self._end:
timestamps['end'] = self._end timestamps['end'] = self._end
# fmt: off
return { return {
'type': ActivityType.playing.value, 'type': ActivityType.playing.value,
'name': str(self.name), 'name': str(self.name),
'timestamps': timestamps 'timestamps': timestamps
} }
# fmt: on
def __eq__(self, other): def __eq__(self, other):
return isinstance(other, Game) and other.name == self.name return isinstance(other, Game) and other.name == self.name
@ -380,6 +424,7 @@ class Game(BaseActivity):
def __hash__(self): def __hash__(self):
return hash(self.name) return hash(self.name)
class Streaming(BaseActivity): class Streaming(BaseActivity):
"""A slimmed down version of :class:`Activity` that represents a Discord streaming status. """A slimmed down version of :class:`Activity` that represents a Discord streaming status.
@ -434,7 +479,7 @@ class Streaming(BaseActivity):
self.game = extra.pop('state', None) self.game = extra.pop('state', None)
self.url = url self.url = url
self.details = extra.pop('details', self.name) # compatibility self.details = extra.pop('details', self.name) # compatibility
self.assets = extra.pop('assets', {}) self.assets: ActivityAssets = extra.pop('assets', {})
@property @property
def type(self): def type(self):
@ -466,12 +511,14 @@ class Streaming(BaseActivity):
return name[7:] if name[:7] == 'twitch:' else None return name[7:] if name[:7] == 'twitch:' else None
def to_dict(self): def to_dict(self):
# fmt: off
ret = { ret = {
'type': ActivityType.streaming.value, 'type': ActivityType.streaming.value,
'name': str(self.name), 'name': str(self.name),
'url': str(self.url), 'url': str(self.url),
'assets': self.assets 'assets': self.assets
} }
# fmt: on
if self.details: if self.details:
ret['details'] = self.details ret['details'] = self.details
return ret return ret
@ -485,6 +532,7 @@ class Streaming(BaseActivity):
def __hash__(self): def __hash__(self):
return hash(self.name) return hash(self.name)
class Spotify: class Spotify:
"""Represents a Spotify listening activity from Discord. This is a special case of """Represents a Spotify listening activity from Discord. This is a special case of
:class:`Activity` that makes it easier to work with the Spotify integration. :class:`Activity` that makes it easier to work with the Spotify integration.
@ -508,8 +556,7 @@ class Spotify:
Returns the string 'Spotify'. Returns the string 'Spotify'.
""" """
__slots__ = ('_state', '_details', '_timestamps', '_assets', '_party', '_sync_id', '_session_id', __slots__ = ('_state', '_details', '_timestamps', '_assets', '_party', '_sync_id', '_session_id', '_created_at')
'_created_at')
def __init__(self, **data): def __init__(self, **data):
self._state = data.pop('state', None) self._state = data.pop('state', None)
@ -543,7 +590,7 @@ class Spotify:
""":class:`Colour`: Returns the Spotify integration colour, as a :class:`Colour`. """:class:`Colour`: Returns the Spotify integration colour, as a :class:`Colour`.
There is an alias for this named :attr:`color`""" There is an alias for this named :attr:`color`"""
return Colour(0x1db954) return Colour(0x1DB954)
@property @property
def color(self): def color(self):
@ -562,7 +609,7 @@ class Spotify:
'session_id': self._session_id, 'session_id': self._session_id,
'timestamps': self._timestamps, 'timestamps': self._timestamps,
'details': self._details, 'details': self._details,
'state': self._state 'state': self._state,
} }
@property @property
@ -571,8 +618,12 @@ class Spotify:
return 'Spotify' return 'Spotify'
def __eq__(self, other): def __eq__(self, other):
return (isinstance(other, Spotify) and other._session_id == self._session_id return (
and other._sync_id == self._sync_id and other.start == self.start) isinstance(other, Spotify)
and other._session_id == self._session_id
and other._sync_id == self._sync_id
and other.start == self.start
)
def __ne__(self, other): def __ne__(self, other):
return not self.__eq__(other) return not self.__eq__(other)
@ -644,6 +695,7 @@ class Spotify:
""":class:`str`: The party ID of the listening party.""" """:class:`str`: The party ID of the listening party."""
return self._party.get('id', '') return self._party.get('id', '')
class CustomActivity(BaseActivity): class CustomActivity(BaseActivity):
"""Represents a Custom activity from Discord. """Represents a Custom activity from Discord.
@ -721,7 +773,7 @@ class CustomActivity(BaseActivity):
return o return o
def __eq__(self, other): def __eq__(self, other):
return (isinstance(other, CustomActivity) and other.name == self.name and other.emoji == self.emoji) return isinstance(other, CustomActivity) and other.name == self.name and other.emoji == self.emoji
def __ne__(self, other): def __ne__(self, other):
return not self.__eq__(other) return not self.__eq__(other)

View File

@ -78,6 +78,11 @@ class ActivityEmoji(_ActivityEmojiOptional):
name: str name: str
class ActivityButton(TypedDict):
label: str
url: str
class _SendableActivityOptional(TypedDict, total=False): class _SendableActivityOptional(TypedDict, total=False):
url: Optional[str] url: Optional[str]
@ -106,3 +111,4 @@ class Activity(_BaseActivity, total=False):
secrets: ActivitySecrets secrets: ActivitySecrets
session_id: Optional[str] session_id: Optional[str]
instance: bool instance: bool
buttons: List[ActivityButton]