fix inconsistent presence objects

adds default values to presence.mobile and presence.client_status, as we
don't add any checks for them

client_status is presented on ae03e00ed2 (diff-b307d936b736f302bc7cc153f0d8a0a3)

mobile isn't shown anywhere but was used for mobile indicators. more on
https://luna.gitlab.io/discord-unofficial-docs/mobile_indicator.html
This commit is contained in:
Luna 2019-05-05 17:49:58 -03:00
parent 268b921961
commit 2c7c313a53
2 changed files with 48 additions and 30 deletions

View File

@ -17,13 +17,15 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
""" """
from typing import List, Dict, Any from typing import List, Dict, Any, Iterable
from random import choice from random import choice
from logbook import Logger from logbook import Logger
log = Logger(__name__) log = Logger(__name__)
Presence = Dict[str, Any]
def status_cmp(status: str, other_status: str) -> bool: def status_cmp(status: str, other_status: str) -> bool:
"""Compare if `status` is better than the `other_status` """Compare if `status` is better than the `other_status`
@ -67,19 +69,44 @@ def _best_presence(shards):
return None if not best['status'] else best return None if not best['status'] else best
def fill_presence(presence: dict, *, game=None) -> dict:
"""Fill a given presence object with some specific fields."""
presence['client_status'] = {}
presence['mobile'] = False
if 'since' not in presence:
presence['since'] = 0
# fill game and activities array depending if game
# is there or not
game = game or presence.get('game')
# casting to bool since a game of {} is still invalid
if game:
presence['game'] = game
presence['activities'] = [game]
else:
presence['game'] = None
presence['activities'] = []
return presence
async def _pres(storage, user_id: int, status_obj: dict) -> dict: async def _pres(storage, user_id: int, status_obj: dict) -> dict:
"""Convert a given status into a presence, given the User ID and the """Convert a given status into a presence, given the User ID and the
:class:`Storage` instance. :class:`Storage` instance."""
This adds the required `presences` array, that isn't used, due to Litecord's
lack of Rich Presence.
"""
ext = { ext = {
'user': await storage.get_user(user_id), 'user': await storage.get_user(user_id),
'activities': [], 'activities': [],
# NOTE: we are purposefully overwriting the fields, as there
# isn't any push for us to actually implement mobile detection, or
# web detection, etc.
'client_status': {},
'mobile': False,
} }
return {**status_obj, **ext} return fill_presence({**status_obj, **ext})
class PresenceManager: class PresenceManager:
@ -97,6 +124,9 @@ class PresenceManager:
async def guild_presences(self, member_ids: List[int], async def guild_presences(self, member_ids: List[int],
guild_id: int) -> List[Dict[Any, str]]: guild_id: int) -> List[Dict[Any, str]]:
"""Fetch all presences in a guild.""" """Fetch all presences in a guild."""
# this works via fetching all connected GatewayState on a guild
# then fetching its respective member and merging that info with
# the state's set presence.
states = self.state_manager.guild_states(member_ids, guild_id) states = self.state_manager.guild_states(member_ids, guild_id)
presences = [] presences = []
@ -108,18 +138,15 @@ class PresenceManager:
game = state.presence.get('game', None) game = state.presence.get('game', None)
# only use the data we need. # only use the data we need.
presences.append({ presences.append(fill_presence({
'user': member['user'], 'user': member['user'],
'roles': member['roles'], 'roles': member['roles'],
'guild_id': str(guild_id), 'guild_id': str(guild_id),
# basic presence # if a state is connected to the guild
# we assume its online.
'status': state.presence.get('status', 'online'), 'status': state.presence.get('status', 'online'),
}, game=game))
# game is an activity object, for rich presence
'game': game,
'activities': [game] if game else []
})
return presences return presences
@ -157,17 +184,12 @@ class PresenceManager:
if member_list.channel_id == member_list.guild_id: if member_list.channel_id == member_list.guild_id:
in_lazy.extend(session_ids) in_lazy.extend(session_ids)
pres_update_payload = { pres_update_payload = fill_presence({
'guild_id': str(guild_id),
'user': member['user'], 'user': member['user'],
'roles': member['roles'], 'roles': member['roles'],
'guild_id': str(guild_id),
'status': state['status'], 'status': state['status'],
}, game=game)
# rich presence stuff
'game': game,
'activities': [game] if game else []
}
# given a session id, return if the session id actually connects to # given a session id, return if the session id actually connects to
# a given user, and if the state has not been dispatched via lazy guild. # a given user, and if the state has not been dispatched via lazy guild.
@ -213,16 +235,12 @@ class PresenceManager:
game = state['game'] game = state['game']
await self.dispatcher.dispatch( await self.dispatcher.dispatch(
'friend', user_id, 'PRESENCE_UPDATE', { 'friend', user_id, 'PRESENCE_UPDATE', fill_presence({
'user': user, 'user': user,
'status': state['status'], 'status': state['status'],
}, game=game))
# rich presence stuff async def friend_presences(self, friend_ids: Iterable[int]) -> List[Presence]:
'game': game,
'activities': [game] if game else []
})
async def friend_presences(self, friend_ids: int) -> List[Dict[str, Any]]:
"""Fetch presences for a group of users. """Fetch presences for a group of users.
This assumes the users are friends and so This assumes the users are friends and so

View File

@ -42,11 +42,11 @@ from litecord.permissions import (
from litecord.utils import index_by_func from litecord.utils import index_by_func
from litecord.utils import mmh3 from litecord.utils import mmh3
from litecord.gateway.state import GatewayState from litecord.gateway.state import GatewayState
from litecord.presence import Presence
log = Logger(__name__) log = Logger(__name__)
GroupID = Union[int, str] GroupID = Union[int, str]
Presence = Dict[str, Any]
# TODO: move this constant out of the lazy_guild module # TODO: move this constant out of the lazy_guild module
MAX_ROLES = 250 MAX_ROLES = 250