gateway.websocket: add voice state property fetch

- gateway.websocket: handle when vsu.channel_id and vsu.guild_id are
    none
This commit is contained in:
Luna 2019-03-01 17:29:40 -03:00
parent 5d2869b53c
commit e22deb316f
2 changed files with 51 additions and 14 deletions

View File

@ -47,6 +47,8 @@ from litecord.gateway.errors import (
DecodeError, UnknownOPCode, InvalidShard, ShardingRequired DecodeError, UnknownOPCode, InvalidShard, ShardingRequired
) )
from litecord.storage import int_, bool_
log = Logger(__name__) log = Logger(__name__)
WebsocketProperties = collections.namedtuple( WebsocketProperties = collections.namedtuple(
@ -645,23 +647,60 @@ class GatewayWebsocket:
# all checks passed. # all checks passed.
return True return True
async def _move_voice(self, guild_id, channel_id): async def _vsu_get_prop(self, state, data):
"""Get voice state properties from data, fallbacking to
user settings."""
try:
# TODO: fetch from settings if not provided
self_deaf = bool(data['self_deaf'])
self_mute = bool(data['self_mute'])
except (KeyError, ValueError):
pass
return {
'deaf': state.deaf,
'mute': state.mute,
'self_deaf': self_deaf,
'self_mute': self_mute,
}
async def _move_voice(self, guild_id, channel_id, state, data):
"""Move an existing voice state to the given target.""" """Move an existing voice state to the given target."""
# first case: consider when the user is leaving the
# voice channel.
if channel_id is None: if channel_id is None:
return await self.ext.voice.del_state(self.voice_key) return await self.ext.voice.del_state(self.voice_key)
# second case: an update of voice state while being in
# the same channel
if channel_id == state.channel_id:
# we are moving to the same channel, so a simple update
# to the self_deaf / self_mute should suffice.
prop = await self._vsu_get_prop(state, data)
return await self.ext.voice.update_state(
self.voice_key, prop)
# third case: moving between channels, check if the
# user can join the targeted channel first
if not await self._voice_check(guild_id, channel_id): if not await self._voice_check(guild_id, channel_id):
return return
# if they can join, move the state to there.
await self.ext.voice.move_state( await self.ext.voice.move_state(
self.voice_key, guild_id, channel_id) self.voice_key, guild_id, channel_id)
async def _create_voice(self, guild_id, channel_id): async def _create_voice(self, guild_id, channel_id, _state, data):
"""Create a voice state.""" """Create a voice state."""
# we ignore the given existing state as it'll be basically
# none, lol.
# check if we can join the channel
if not await self._voice_check(guild_id, channel_id): if not await self._voice_check(guild_id, channel_id):
return return
await self.ext.voice.create_state(self.voice_key, guild_id, channel_id) # if yes, create the state
await self.ext.voice.create_state(
self.voice_key, guild_id, channel_id, data)
async def handle_4(self, payload: Dict[str, Any]): async def handle_4(self, payload: Dict[str, Any]):
"""Handle OP 4 Voice Status Update.""" """Handle OP 4 Voice Status Update."""
@ -670,24 +709,16 @@ class GatewayWebsocket:
if not self.state: if not self.state:
return return
try: channel_id = int_(data.get('channel_id'))
channel_id = int(data['channel_id']) guild_id = int_(data.get('guild_id'))
guild_id = int(data['guild_id'])
# TODO: fetch from settings if not provided
# self_deaf = bool(data['self_deaf'])
# self_mute = bool(data['self_mute'])
# NOTE: self_video is NOT handled.
except (KeyError, ValueError):
pass
# fetch an existing voice state # fetch an existing voice state
user_id, session_id = self.state.user_id, self.state.session_id user_id, session_id = self.state.user_id, self.state.session_id
voice_state = await self.ext.voice.fetch_state(user_id, session_id) voice_state = await self.ext.voice.fetch_state(user_id, session_id)
func = self._move_voice if voice_state else self._create_voice func = self._move_voice if voice_state else self._create_voice
await func(guild_id, channel_id) await func(guild_id, channel_id, voice_state, data)
async def _handle_5(self, payload: Dict[str, Any]): async def _handle_5(self, payload: Dict[str, Any]):
"""Handle OP 5 Voice Server Ping. """Handle OP 5 Voice Server Ping.

View File

@ -52,6 +52,12 @@ def str_(val):
return maybe(str, val) return maybe(str, val)
def int_(val):
return maybe(int, val)
def bool_(val):
return maybe(int, val)
def _filter_recipients(recipients: List[Dict[str, Any]], user_id: int): def _filter_recipients(recipients: List[Dict[str, Any]], user_id: int):
"""Filter recipients in a list of recipients, removing """Filter recipients in a list of recipients, removing
the one that is reundant (ourselves).""" the one that is reundant (ourselves)."""