diff --git a/api/chat.py b/api/chat.py index 58509d0..eb71a1f 100644 --- a/api/chat.py +++ b/api/chat.py @@ -10,6 +10,7 @@ from typing import * import aiohttp import tornado.websocket +import yarl import api.base import blivedm.blivedm.clients.web as dm_web_cli @@ -327,23 +328,26 @@ class RoomInfoHandler(api.base.ApiHandler): async def get(self): room_id = int(self.get_query_argument('roomId')) logger.info('client=%s getting room info, room=%d', self.request.remote_ip, room_id) - room_id, owner_uid = await self._get_room_info(room_id) - # 连接其他host必须要key - host_server_list = dm_web_cli.DEFAULT_DANMAKU_SERVER_LIST - if owner_uid == 0: - # 缓存3分钟 - self.set_header('Cache-Control', 'private, max-age=180') - else: - # 缓存1天 - self.set_header('Cache-Control', 'private, max-age=86400') + + (room_id, owner_uid), (host_server_list, host_server_token), buvid = await asyncio.gather( + self._get_room_info(room_id), + self._get_server_host_list_and_token(room_id), + self._get_buvid() + ) + + # 缓存1分钟 + self.set_header('Cache-Control', 'private, max-age=60') self.write({ 'roomId': room_id, 'ownerUid': owner_uid, - 'hostServerList': host_server_list + 'hostServerList': host_server_list, + 'hostServerToken': host_server_token, + # 虽然没什么用但还是加上比较保险 + 'buvid': buvid, }) @staticmethod - async def _get_room_info(room_id): + async def _get_room_info(room_id) -> Tuple[int, int]: try: async with utils.request.http_session.get( dm_web_cli.ROOM_INIT_URL, @@ -372,6 +376,61 @@ class RoomInfoHandler(api.base.ApiHandler): room_info = data['data']['room_info'] return room_info['room_id'], room_info['uid'] + async def _get_server_host_list_and_token(self, room_id) -> Tuple[dict, Optional[str]]: + try: + async with utils.request.http_session.get( + dm_web_cli.DANMAKU_SERVER_CONF_URL, + headers={ + # token会对UA签名,要使用和客户端一样的UA + 'User-Agent': self.request.headers.get('User-Agent', '') + }, + params={ + 'id': room_id, + 'type': 0 + } + ) as res: + if res.status != 200: + logger.warning('room %d _get_server_host_list failed: %d %s', room_id, + res.status, res.reason) + return dm_web_cli.DEFAULT_DANMAKU_SERVER_LIST, None + data = await res.json() + except (aiohttp.ClientConnectionError, asyncio.TimeoutError): + logger.exception('room %d _get_server_host_list failed', room_id) + return dm_web_cli.DEFAULT_DANMAKU_SERVER_LIST, None + + if data['code'] != 0: + logger.warning('room %d _get_server_host_list failed: %s', room_id, data['message']) + return dm_web_cli.DEFAULT_DANMAKU_SERVER_LIST, None + + data = data['data'] + host_server_list = data['host_list'] + if not host_server_list: + logger.warning('room %d _get_server_host_list failed: host_server_list is empty') + return dm_web_cli.DEFAULT_DANMAKU_SERVER_LIST, None + + host_server_token = data.get('token', None) + return host_server_list, host_server_token + + async def _get_buvid(self): + buvid = self._do_get_buvid() + if buvid != '': + return buvid + + try: + async with utils.request.http_session.get(dm_web_cli.BUVID_INIT_URL): + pass + except (aiohttp.ClientConnectionError, asyncio.TimeoutError): + pass + return self._do_get_buvid() + + @staticmethod + def _do_get_buvid(): + cookies = utils.request.http_session.cookie_jar.filter_cookies(yarl.URL(dm_web_cli.BUVID_INIT_URL)) + buvid_cookie = cookies.get('buvid3', None) + if buvid_cookie is None: + return '' + return buvid_cookie.value + class AvatarHandler(api.base.ApiHandler): async def get(self): diff --git a/frontend/src/api/chat/ChatClientDirectWeb.js b/frontend/src/api/chat/ChatClientDirectWeb.js index c8e3f14..869fc06 100644 --- a/frontend/src/api/chat/ChatClientDirectWeb.js +++ b/frontend/src/api/chat/ChatClientDirectWeb.js @@ -16,6 +16,8 @@ export default class ChatClientDirectWeb extends ChatClientOfficialBase { this.hostServerList = [ { host: "broadcastlv.chat.bilibili.com", port: 2243, wss_port: 443, ws_port: 2244 } ] + this.hostServerToken = null + this.buvid = '' } async initRoom() { @@ -32,6 +34,8 @@ export default class ChatClientDirectWeb extends ChatClientOfficialBase { if (res.hostServerList.length !== 0) { this.hostServerList = res.hostServerList } + this.hostServerToken = res.hostServerToken + this.buvid = res.buvid return true } @@ -56,8 +60,10 @@ export default class ChatClientDirectWeb extends ChatClientOfficialBase { protover: 3, platform: 'web', type: 2, - buvid: '', - // TODO B站开始检查key了,有空时加上 + buvid: this.buvid, + } + if (this.hostServerToken !== null) { + authParams.key = this.hostServerToken } this.websocket.send(this.makePacket(authParams, base.OP_AUTH)) }