From d242ef230a3f1b1840c347451b5cbc9ed80e21c7 Mon Sep 17 00:00:00 2001 From: Luna Mendes Date: Wed, 26 Sep 2018 18:08:12 -0300 Subject: [PATCH] gateway.websocket: various fixes to presence - handle BadRequest instead of passing raise_err=False - handle status.activities - ready: call update_status BEFORE subscribing and dispatching_ready presence: - better presence object on guild_presences schema: - handle activities, change required to false in game --- litecord/dispatcher.py | 4 ++-- litecord/gateway/websocket.py | 38 +++++++++++++++++++++++++++-------- litecord/presence.py | 27 +++++++++++++++++++------ litecord/schemas.py | 3 ++- litecord/storage.py | 2 -- 5 files changed, 55 insertions(+), 19 deletions(-) diff --git a/litecord/dispatcher.py b/litecord/dispatcher.py index e8f523e..128fa94 100644 --- a/litecord/dispatcher.py +++ b/litecord/dispatcher.py @@ -35,8 +35,8 @@ class EventDispatcher: users = self.guild_buckets[guild_id] dispatched = 0 - log.info('Dispatching {} {!r} to {} users', - guild_id, event_name, len(users)) + log.debug('Dispatching {} {!r} to {} users', + guild_id, event_name, len(users)) for user_id in set(users): # fetch all connections that are tied to the guild, diff --git a/litecord/gateway/websocket.py b/litecord/gateway/websocket.py index b209682..2e33801 100644 --- a/litecord/gateway/websocket.py +++ b/litecord/gateway/websocket.py @@ -15,6 +15,7 @@ from .errors import DecodeError, UnknownOPCode, \ InvalidShard, ShardingRequired from .opcodes import OP from .state import GatewayState +from ..errors import BadRequest from ..schemas import validate, GW_STATUS_UPDATE @@ -279,6 +280,7 @@ class GatewayWebsocket: async def subscribe_guilds(self): """Subscribe to all available guilds""" guild_ids = await self._guild_ids() + log.info('subscribing to {} guilds', len(guild_ids)) self.ext.dispatcher.sub_many(self.state.user_id, guild_ids) async def update_status(self, status: dict): @@ -296,13 +298,31 @@ class GatewayWebsocket: self.state.presence = status - status = validate(status, GW_STATUS_UPDATE, False) - - if not status: - # invalid status, must ignore + try: + status = validate(status, GW_STATUS_UPDATE) + except BadRequest as err: + log.warning(f'Invalid payload: {err}') return + # try to extract game from activities + # when game not provided + if not status.get('game'): + try: + game = status['activities'][0] + except (KeyError, IndexError): + game = None + + # construct final status + status = { + 'afk': status.get('afk', False), + 'status': status.get('status', 'online'), + 'game': game, + 'since': status.get('since', 0), + } + self.state.presence = status + log.info(f'Updating presence status={status["status"]} for ' + f'uid={self.state.user_id}') await self.ext.presence.dispatch_pres(self.state.user_id, self.state.presence) @@ -350,11 +370,9 @@ class GatewayWebsocket: await self._check_shards() self.ext.state_manager.insert(self.state) - await self.dispatch_ready() - await self.subscribe_guilds() - - # dispatch presence only after subscribing await self.update_status(presence) + await self.subscribe_guilds() + await self.dispatch_ready() async def handle_3(self, payload: Dict[str, Any]): """Handle OP 3 Status Update.""" @@ -593,6 +611,10 @@ class GatewayWebsocket: guild_presences = await self.presence.guild_presences(member_ids, guild_id) + pprint.pprint(guild_presences) + + log.info('loading {} presences for guild', len(guild_presences)) + online = [{'member': p} for p in guild_presences if p['status'] == 'online'] diff --git a/litecord/presence.py b/litecord/presence.py index c1d4367..86dfc28 100644 --- a/litecord/presence.py +++ b/litecord/presence.py @@ -19,14 +19,24 @@ class PresenceManager: member = await self.storage.get_member_data_one( guild_id, state.user_id) - presences.append({**member, **{ - # NOTE: maybe remove guild_id? + game = state.presence.get('game', None) + + print('state:', state) + print('state.presence:', state.presence) + + # only use the data we need. + presences.append({ + 'user': member['user'], + 'roles': member['roles'], 'guild_id': guild_id, # basic presence - 'game': state.presence.get('game', None), - 'status': state.presence.get('status', None), - }}) + 'status': state.presence['status'], + + # game is an activity object, for rich presence + 'game': game, + 'activities': [game] if game else [] + }) return presences @@ -40,14 +50,19 @@ class PresenceManager: member = await self.storage.get_member_data_one(guild_id, user_id) + game = state['game'] + await self.dispatcher.dispatch_guild( guild_id, 'PRESENCE_UPDATE', { 'user': member['user'], 'roles': member['roles'], 'guild_id': guild_id, - 'game': state['game'], 'status': state['status'], + + # rich presence stuff + 'game': game, + 'activities': [game] if game else [] } ) diff --git a/litecord/schemas.py b/litecord/schemas.py index 8057565..1dadf0a 100644 --- a/litecord/schemas.py +++ b/litecord/schemas.py @@ -163,12 +163,13 @@ GW_ACTIVITY = { GW_STATUS_UPDATE = { 'status': {'type': 'status_external', 'required': False}, + 'activities': {'type': 'list', 'schema': GW_ACTIVITY}, 'afk': {'type': 'boolean', 'required': False}, 'since': {'type': 'number', 'required': True, 'nullable': True}, 'game': { 'type': 'dict', - 'required': True, + 'required': False, 'nullable': True, 'schema': GW_ACTIVITY, }, diff --git a/litecord/storage.py b/litecord/storage.py index 92e3acf..b5a15a4 100644 --- a/litecord/storage.py +++ b/litecord/storage.py @@ -257,8 +257,6 @@ class Storage: res = await self._channels_extra(drow) - print(res) - res['permission_overwrites'] = \ list(await self._chan_overwrites(row['id']))