async def get_token(self) -> typing.Optional[objects.TokenResponse]: identifier = self.get_secure_cookie('identifier') token_response_data = await self.bot.redis.hget('tokens', identifier) if not token_response_data: return None token_response = objects.TokenResponse( data=json.loads(token_response_data.decode())) if token_response.has_expired: url = 'https://discord.com/api/oauth2/token' headers = {'Content-Type': 'application/x-www-form-urlencoded'} data = { 'client_secret': self.bot.config.client_secret, 'client_id': self.bot.config.client_id, 'redirect_uri': self.bot.config.redirect_uri, 'refresh_token': token_response.refresh_token, 'grant_type': 'refresh_token', 'scope': 'identify guilds', } async with self.bot.session.post(url, data=data, headers=headers) as response: if 200 < response.status > 206: raise exceptions.HTTPError( json.dumps(await response.json())) data = await response.json() if data.get('error'): raise exceptions.HTTPError(json.dumps(data)) token_response = objects.TokenResponse(data=data) await self.bot.redis.hset('tokens', identifier, token_response.json) return token_response
async def get_token(self): identifier = self.get_secure_cookie('identifier') token_response = await self.bot.redis.hget('tokens', identifier) if not token_response: return None token_response = objects.TokenResponse( data=json.loads(token_response.decode())) if token_response.has_expired: url = f'https://discord.com/api/oauth2/token' headers = {'Content-Type': 'application/x-www-form-urlencoded'} data = { 'client_secret': self.bot.config.client_secret, 'redirect_uri': self.bot.config.redirect_uri, 'client_id': self.bot.config.client_id, 'grant_type': 'refresh_token', 'scope': 'identify guilds', 'refresh_token': token_response.refresh_token } async with self.bot.session.post(url, data=data, headers=headers) as response: data = await response.json() error = data.get('error') if error is not None: self.set_status(400) return await self.finish({'error': error}) token_response = objects.TokenResponse(data=data) await self.bot.redis.hset('tokens', identifier, token_response.json) return token_response
async def get(self): identifier = self.get_secure_cookie('identifier') user_state = self.get_secure_cookie('state') auth_state = self.get_query_argument('state', None) code = self.get_query_argument('code', None) if not code or not auth_state or not user_state: state = binascii.hexlify(os.urandom(16)).decode() self.set_secure_cookie('state', state) url = f'https://discord.com/api/oauth2/authorize?client_id={self.bot.config.client_id}&response_type=code' \ f'&scope=identify%20guilds&redirect_uri={self.bot.config.login_redirect_uri}&state={state}' return self.redirect(url) if not auth_state == user_state.decode(): self.set_status(400) return await self.finish( {'error': 'user state and server state must match.'}) self.clear_cookie('state') url = f'https://discord.com/api/oauth2/token' headers = {'Content-Type': 'application/x-www-form-urlencoded'} data = { 'client_secret': self.bot.config.client_secret, 'redirect_uri': self.bot.config.redirect_uri, 'client_id': self.bot.config.client_id, 'grant_type': 'authorization_code', 'scope': 'identify guilds', 'code': code } async with self.bot.session.post(url, data=data, headers=headers) as response: data = await response.json() error = data.get('error') if error is not None: self.set_status(400) return await self.finish({'error': error}) token_response = objects.TokenResponse(data=data) await self.bot.redis.hset('tokens', identifier, token_response.json) return self.redirect(f'/profile')
async def on_message(self, message): try: message = json.loads(message) except json.JSONDecodeError: return self.close( code=4001, reason='invalid payload format. payloads must be json.') op = message.get('op') if op == 0: # DISPATCH return self.close( code=4002, reason='invalid op code. code 0 is receive only.') elif op == 1: # HELLO return self.close( code=4002, reason='invalid op code. code 1 is receive only.') elif op == 2: # IDENTIFY if self.authenticated is True: return self.close(code=4005, reason='already authenticated.') data = message.get('data') guild = self.bot.get_guild(int(data.get('guild_id'))) if not guild: return self.close(code=4004, reason='invalid guild id.') identifier = decode_signed_value( secret=self.application.settings["cookie_secret"], name='identifier', value=data.get('identifier').strip('"')) if identifier is None: identifier = data.get('identifier') token_response = await self.bot.redis.hget('tokens', identifier) if not token_response: return self.close( code=4003, reason= 'not logged in. must log in with discord on the site at least once.' ) token_response = objects.TokenResponse( data=json.loads(token_response.decode())) if token_response.has_expired: url = f'https://discord.com/api/oauth2/token' headers = {'Content-Type': 'application/x-www-form-urlencoded'} data = { 'client_secret': self.bot.config.client_secret, 'redirect_uri': self.bot.config.redirect_uri, 'client_id': self.bot.config.client_id, 'grant_type': 'refresh_token', 'scope': 'identify guilds', 'refresh_token': token_response.refresh_token } async with self.bot.session.post(url, data=data, headers=headers) as response: data = await response.json() error = data.get('error') if error is not None: return self.close(code=4000, reason=error) token_response = objects.TokenResponse(data=data) await self.bot.redis.hset('tokens', data.get('token'), token_response.json) self.authenticated = True self.guild = guild self.player = self.bot.diorite.get_player(guild, cls=Player) self.send_current_task = asyncio.create_task(self.send_current()) self.send_player_task = asyncio.create_task(self.send_player()) self.send_position_task = asyncio.create_task(self.send_position()) elif self.authenticated is False: return self.close(code=4006, reason='not authorized.')
async def on_message(self, message) -> None: try: message = json.loads(message) except json.JSONDecodeError: return self.close( code=4001, reason='invalid payload format. payloads must be json.') op = message.get('op') if op == 0: # DISPATCH return self.close( code=4002, reason='invalid op code. code 0 "DISPATCH" is receive only.') elif op == 1: # HELLO return self.close( code=4002, reason='invalid op code. code 1 "HELLO" is receive only.') elif op == 2: # IDENTIFY if self.authenticated is True: return self.close(code=4005, reason='already authenticated.') data = message.get('data') guild = self.bot.get_guild(int(data.get('guild_id'))) if not guild: return self.close(code=4004, reason='invalid guild id.') identifier = decode_signed_value( secret=self.application.settings["cookie_secret"], name='identifier', value=data.get('identifier').strip('"')) if identifier is None: identifier = data.get('identifier') token_response = await self.bot.redis.hget('tokens', identifier) if not token_response: return self.close( code=4003, reason= 'not logged in. must log in with discord on the site at least once.' ) token_response = objects.TokenResponse( data=json.loads(token_response.decode())) if token_response.has_expired: url = 'https://discord.com/api/oauth2/token' headers = {'Content-Type': 'application/x-www-form-urlencoded'} data = { 'client_secret': self.bot.config.client_secret, 'client_id': self.bot.config.client_id, 'redirect_uri': self.bot.config.redirect_uri, 'refresh_token': token_response.refresh_token, 'grant_type': 'refresh_token', 'scope': 'identify guilds', } async with self.bot.session.post(url, data=data, headers=headers) as response: if 200 < response.status > 206: raise exceptions.HTTPError( json.dumps(await response.json())) data = await response.json() if data.get('error'): raise exceptions.HTTPError(json.dumps(data)) token_response = objects.TokenResponse(data=data) await self.bot.redis.hset('tokens', identifier, token_response.json) self.authenticated = True self.guild = guild self.ready_task = asyncio.create_task(self.send_ready()) self.position_task = asyncio.create_task(self.send_position()) self.bot.add_listener(self.handle_event, 'on_lavalink_track_start') self.bot.add_listener(self.handle_event, 'on_lavalink_track_end') self.bot.add_listener(self.handle_event, 'on_lavalink_track_exception') self.bot.add_listener(self.handle_event, 'on_lavalink_track_stuck') self.bot.add_listener(self.handle_event, 'on_lavalink_player_connected') self.bot.add_listener(self.handle_event, 'on_lavalink_player_disconnected') self.bot.add_listener(self.handle_event, 'on_lavalink_player_queue_update') elif self.authenticated is False: return self.close(code=4006, reason='not authorized.')