Source code for curious.dataclasses.presence

# This file is part of curious.
#
# curious is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# curious is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with curious.  If not, see <http://www.gnu.org/licenses/>.

"""
Wrappers for Status objects.

.. currentmodule:: curious.dataclasses.presence
"""

import enum
from typing import List


[docs]class Status(enum.Enum): """ Represents a Member's status. """ #: Corresponds to online (green dot). ONLINE = 'online' #: Corresponds to offline (gray dot). OFFLINE = 'offline' #: Corresponds to idle (yellow dot). IDLE = 'idle' #: Corresponds to Do Not Disturb (red dot). DND = 'dnd' #: Corresponds to invisible (gray dot). INVISIBLE = 'invisible' @property def strength(self) -> int: """ :return: The strength of the presence, when computing the final presence on multiple \ connections. """ return strengths.index(self)
strengths = [Status.OFFLINE, Status.INVISIBLE, Status.IDLE, Status.DND, Status.ONLINE]
[docs]class GameType(enum.IntEnum): """ Represents a game's type. """ #: Shows the ``Playing`` text. PLAYING = 0 #: Shows the ``Streaming`` text. STREAMING = 1 #: Shows the ``Listening to`` text. LISTENING_TO = 2 #: Shows the ``Watching`` text. WATCHING = 3
[docs]class Game(object): """ Represents a game object. """ __slots__ = "type", "url", "name" def __init__(self, **kwargs) -> None: """ :param name: The name for the game. 100 characters max. :param url: The URL for the game, if streaming. :param type: A :class:`.GameType` for this game. """ #: The type of game this is. self.type = GameType.PLAYING # type: GameType try: self.type = GameType(kwargs.get("type", 0)) except ValueError: self.type = kwargs.get("type", 0) #: The stream URL this game is for. self.url = kwargs.get("url", None) # type: str #: The name of the game being played. self.name = kwargs.get("name", None) # type: str
[docs] def to_dict(self) -> dict: """ :return: The dict representation of this object. """ d = { "name": self.name, "type": self.type, } if self.url is not None: d["url"] = self.url return d
def __repr__(self) -> str: return "<Game name='{}' type={} url={}>".format(self.name, self.type, self.url)
[docs]class Presence(object): """ Represents a presence on a member. """ __slots__ = "_status", "_game" def __init__(self, **kwargs) -> None: """ :param status: The :class:`.Status` for this presence. :param game: The :class:`.Game` for this presence. """ #: The :class:~.Status` for this presence. self._status = None # type: Status # prevent dupe code by using our setter self.status = kwargs.get("status", Status.OFFLINE) game = kwargs.get("game", None) #: The :class:`.Game` for this presence. self._game = None # type: Game # NB: this does a property set to ensure the types are right. self.game = game def __repr__(self): return "<Presence status={} game='{}'>".format(self.status, self.game) @property def status(self) -> Status: """ :return: The :class:`.Status` associated with this presence. """ return self._status @status.setter def status(self, value): if value is None: return if not isinstance(value, Status): value = Status(value) self._status = value @property def game(self) -> Game: """ :return: The :class:`.Game` associated with this presence. """ return self._game @game.setter def game(self, value): if value is None: self._game = None return if not isinstance(value, Game): value = Game(**value) self._game = value @property def strength(self) -> int: """ :return: The strength for this status. """ return self.status.strength
def _make_property(field: str, doc: str = None, max_size: int = None) -> property: def _getter(self): return self._rich_fields.get(field) def _setter(self, value: str): if max_size is not None and len(value) > max_size: raise ValueError("Field '{}' cannot be longer than {} characters" .format(field, max_size)) self._rich_fields[field] = value prop = property(_getter, _setter, doc=doc) return prop
[docs]class RichPresence(object): """ Represents a Rich Presence. This class can be created safely for usage with :class:`.IPCClient`. """ # typedef struct DiscordRichPresence { # const char* state; /* max 128 bytes */ # const char* details; /* max 128 bytes */ # int64_t startTimestamp; # int64_t endTimestamp; # const char* largeImageKey; /* max 32 bytes */ # const char* largeImageText; /* max 128 bytes */ # const char* smallImageKey; /* max 32 bytes */ # const char* smallImageText; /* max 128 bytes */ # const char* partyId; /* max 128 bytes */ # int partySize; # int partyMax; # const char* matchSecret; /* max 128 bytes */ # const char* joinSecret; /* max 128 bytes */ # const char* spectateSecret; /* max 128 bytes */ # int8_t instance; # } DiscordRichPresence; def __init__(self, **fields): """ :param fields: The rich presence fields. """ self._rich_fields = fields state = _make_property("state", "The state for this presence.", 128) details = _make_property("details", "The details for this presence.", 128) @property def assets(self) -> dict: """ The assets for this rich presence. Returns a dict of (large_image, large_text, small_image, small_text). """ return self._rich_fields.get("assets", {}) @assets.setter def assets(self, value: dict): for key in value.keys(): if key not in ('large_image', 'large_text', 'small_image', 'small_text'): raise ValueError("Bad asset key: {}".format(key)) self._rich_fields["assets"] = value @property def party_id(self) -> str: """ The party ID for this rich presence. """ return self._rich_fields.get("party", {}).get("id") @party_id.setter def party_id(self, value): if "party" not in self._rich_fields: self._rich_fields["party"] = {"id": value} else: self._rich_fields["party"]["id"] = value @property def party_size(self) -> List[int]: """ The size of the party for this rich presence. An array of [size, max]. """ return self._rich_fields.get("party", {}).get("size") @party_size.setter def party_size(self, size: List[int]): if "party" not in self._rich_fields: self._rich_fields["party"] = {"size": size} else: self._rich_fields["party"]["size"] = size