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
This commit is contained in:
Luna Mendes 2018-09-26 18:08:12 -03:00
parent 14d3149f50
commit d242ef230a
5 changed files with 55 additions and 19 deletions

View File

@ -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,

View File

@ -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']

View File

@ -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 []
}
)

View File

@ -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,
},

View File

@ -257,8 +257,6 @@ class Storage:
res = await self._channels_extra(drow)
print(res)
res['permission_overwrites'] = \
list(await self._chan_overwrites(row['id']))