升级blivedm

This commit is contained in:
John Smith 2021-12-19 18:46:32 +08:00
parent 2a22617c1a
commit 776b354517
3 changed files with 101 additions and 85 deletions

View File

@ -14,6 +14,7 @@ import tornado.websocket
import api.base import api.base
import blivedm.blivedm as blivedm import blivedm.blivedm as blivedm
import blivedm.blivedm.client as blivedm_client
import config import config
import models.avatar import models.avatar
import models.translate import models.translate
@ -42,64 +43,88 @@ def init():
room_manager = RoomManager() room_manager = RoomManager()
class Room(blivedm.BLiveClient): class Room(blivedm.BLiveClient, blivedm.BaseHandler):
HEARTBEAT_INTERVAL = 10 HEARTBEAT_INTERVAL = 10
# 重新定义parse_XXX是为了减少对字段名的依赖防止B站改字段名 # 重新定义XXX_callback是为了减少对字段名的依赖防止B站改字段名
def __parse_danmaku(self, command): def __danmu_msg_callback(self, client: blivedm.BLiveClient, command: dict):
info = command['info'] info = command['info']
if info[3]: if len(info[3]) != 0:
room_id = info[3][3]
medal_level = info[3][0] medal_level = info[3][0]
medal_room_id = info[3][3]
else: else:
room_id = medal_level = 0 medal_level = 0
return self._on_receive_danmaku(blivedm.DanmakuMessage( medal_room_id = 0
None, None, None, info[0][4], None, None, info[0][9], None,
info[1],
info[2][0], info[2][1], info[2][2], None, None, info[2][5], info[2][6], None,
medal_level, None, None, room_id, None, None,
info[4][0], None, None,
None, None,
info[7]
))
def __parse_gift(self, command): message = blivedm.DanmakuMessage(
timestamp=info[0][4],
msg_type=info[0][9],
msg=info[1],
uid=info[2][0],
uname=info[2][1],
admin=info[2][2],
urank=info[2][5],
mobile_verify=info[2][6],
medal_level=medal_level,
medal_room_id=medal_room_id,
user_level=info[4][0],
privilege_type=info[7],
)
return self._on_danmaku(client, message)
def __send_gift_callback(self, client: blivedm.BLiveClient, command: dict):
data = command['data'] data = command['data']
return self._on_receive_gift(blivedm.GiftMessage( message = blivedm.GiftMessage(
data['giftName'], data['num'], data['uname'], data['face'], None, gift_name=data['giftName'],
data['uid'], data['timestamp'], None, None, num=data['num'],
None, None, None, data['coin_type'], data['total_coin'] uname=data['uname'],
)) face=data['face'],
uid=data['uid'],
timestamp=data['timestamp'],
coin_type=data['coin_type'],
total_coin=data['total_coin'],
)
return self._on_gift(client, message)
def __parse_buy_guard(self, command): def __guard_buy_callback(self, client: blivedm.BLiveClient, command: dict):
data = command['data'] data = command['data']
return self._on_buy_guard(blivedm.GuardBuyMessage( message = blivedm.GuardBuyMessage(
data['uid'], data['username'], data['guard_level'], None, None, uid=data['uid'],
None, None, data['start_time'], None username=data['username'],
)) guard_level=data['guard_level'],
start_time=data['start_time'],
)
return self._on_buy_guard(client, message)
def __parse_super_chat(self, command): def __super_chat_message_callback(self, client: blivedm.BLiveClient, command: dict):
data = command['data'] data = command['data']
return self._on_super_chat(blivedm.SuperChatMessage( message = blivedm.SuperChatMessage(
data['price'], data['message'], None, data['start_time'], price=data['price'],
None, None, data['id'], None, message=data['message'],
None, data['uid'], data['user_info']['uname'], start_time=data['start_time'],
data['user_info']['face'], None, id_=data['id'],
None, None, uid=data['uid'],
None, None, None, uname=data['user_info']['uname'],
None face=data['user_info']['face'],
)) )
return self._on_super_chat(client, message)
_COMMAND_HANDLERS = { _CMD_CALLBACK_DICT = {
**blivedm.BLiveClient._COMMAND_HANDLERS, **blivedm.BaseHandler._CMD_CALLBACK_DICT,
'DANMU_MSG': __parse_danmaku, 'DANMU_MSG': __danmu_msg_callback,
'SEND_GIFT': __parse_gift, 'SEND_GIFT': __send_gift_callback,
'GUARD_BUY': __parse_buy_guard, 'GUARD_BUY': __guard_buy_callback,
'SUPER_CHAT_MESSAGE': __parse_super_chat 'SUPER_CHAT_MESSAGE': __super_chat_message_callback
} }
def __init__(self, room_id): def __init__(self, room_id):
super().__init__(room_id, session=_http_session, heartbeat_interval=self.HEARTBEAT_INTERVAL) super().__init__(room_id, session=_http_session, heartbeat_interval=self.HEARTBEAT_INTERVAL)
self.add_handler(self)
self.clients: List['ChatHandler'] = [] self.clients: List['ChatHandler'] = []
self.auto_translate_count = 0 self.auto_translate_count = 0
@ -107,13 +132,6 @@ class Room(blivedm.BLiveClient):
await super().init_room() await super().init_room()
return True return True
def stop_and_close(self):
if self.is_running:
future = self.stop()
future.add_done_callback(lambda _future: asyncio.ensure_future(self.close()))
else:
asyncio.ensure_future(self.close())
def send_message(self, cmd, data): def send_message(self, cmd, data):
body = json.dumps({'cmd': cmd, 'data': data}) body = json.dumps({'cmd': cmd, 'data': data})
for client in self.clients: for client in self.clients:
@ -130,22 +148,19 @@ class Room(blivedm.BLiveClient):
except tornado.websocket.WebSocketClosedError: except tornado.websocket.WebSocketClosedError:
room_manager.del_client(self.room_id, client) room_manager.del_client(self.room_id, client)
async def _on_receive_danmaku(self, danmaku: blivedm.DanmakuMessage): async def _on_danmaku(self, client: blivedm.BLiveClient, message: blivedm.DanmakuMessage):
asyncio.ensure_future(self.__on_receive_danmaku(danmaku)) if message.uid == self.room_owner_uid:
async def __on_receive_danmaku(self, danmaku: blivedm.DanmakuMessage):
if danmaku.uid == self.room_owner_uid:
author_type = 3 # 主播 author_type = 3 # 主播
elif danmaku.admin: elif message.admin:
author_type = 2 # 房管 author_type = 2 # 房管
elif danmaku.privilege_type != 0: # 1总督2提督3舰长 elif message.privilege_type != 0: # 1总督2提督3舰长
author_type = 1 # 舰队 author_type = 1 # 舰队
else: else:
author_type = 0 author_type = 0
need_translate = self._need_translate(danmaku.msg) need_translate = self._need_translate(message.msg)
if need_translate: if need_translate:
translation = models.translate.get_translation_from_cache(danmaku.msg) translation = models.translate.get_translation_from_cache(message.msg)
if translation is None: if translation is None:
# 没有缓存,需要后面异步翻译后通知 # 没有缓存,需要后面异步翻译后通知
translation = '' translation = ''
@ -157,41 +172,41 @@ class Room(blivedm.BLiveClient):
id_ = uuid.uuid4().hex id_ = uuid.uuid4().hex
# 为了节省带宽用list而不是dict # 为了节省带宽用list而不是dict
self.send_message(Command.ADD_TEXT, make_text_message( self.send_message(Command.ADD_TEXT, make_text_message(
await models.avatar.get_avatar_url(danmaku.uid), await models.avatar.get_avatar_url(message.uid),
int(danmaku.timestamp / 1000), int(message.timestamp / 1000),
danmaku.uname, message.uname,
author_type, author_type,
danmaku.msg, message.msg,
danmaku.privilege_type, message.privilege_type,
danmaku.msg_type, message.msg_type,
danmaku.user_level, message.user_level,
danmaku.urank < 10000, message.urank < 10000,
danmaku.mobile_verify, message.mobile_verify,
0 if danmaku.room_id != self.room_id else danmaku.medal_level, 0 if message.medal_room_id != self.room_id else message.medal_level,
id_, id_,
translation translation
)) ))
if need_translate: if need_translate:
await self._translate_and_response(danmaku.msg, id_) asyncio.ensure_future(self._translate_and_response(message.msg, id_))
async def _on_receive_gift(self, gift: blivedm.GiftMessage): async def _on_gift(self, client: blivedm.BLiveClient, message: blivedm.GiftMessage):
avatar_url = models.avatar.process_avatar_url(gift.face) avatar_url = models.avatar.process_avatar_url(message.face)
models.avatar.update_avatar_cache(gift.uid, avatar_url) models.avatar.update_avatar_cache(message.uid, avatar_url)
if gift.coin_type != 'gold': # 丢人 if message.coin_type != 'gold': # 丢人
return return
id_ = uuid.uuid4().hex id_ = uuid.uuid4().hex
self.send_message(Command.ADD_GIFT, { self.send_message(Command.ADD_GIFT, {
'id': id_, 'id': id_,
'avatarUrl': avatar_url, 'avatarUrl': avatar_url,
'timestamp': gift.timestamp, 'timestamp': message.timestamp,
'authorName': gift.uname, 'authorName': message.uname,
'totalCoin': gift.total_coin, 'totalCoin': message.total_coin,
'giftName': gift.gift_name, 'giftName': message.gift_name,
'num': gift.num 'num': message.num
}) })
async def _on_buy_guard(self, message: blivedm.GuardBuyMessage): async def _on_buy_guard(self, client: blivedm.BLiveClient, message: blivedm.GuardBuyMessage):
asyncio.ensure_future(self.__on_buy_guard(message)) asyncio.ensure_future(self.__on_buy_guard(message))
async def __on_buy_guard(self, message: blivedm.GuardBuyMessage): async def __on_buy_guard(self, message: blivedm.GuardBuyMessage):
@ -204,7 +219,7 @@ class Room(blivedm.BLiveClient):
'privilegeType': message.guard_level 'privilegeType': message.guard_level
}) })
async def _on_super_chat(self, message: blivedm.SuperChatMessage): async def _on_super_chat(self, client: blivedm.BLiveClient, message: blivedm.SuperChatMessage):
avatar_url = models.avatar.process_avatar_url(message.face) avatar_url = models.avatar.process_avatar_url(message.face)
models.avatar.update_avatar_cache(message.uid, avatar_url) models.avatar.update_avatar_cache(message.uid, avatar_url)
@ -233,7 +248,7 @@ class Room(blivedm.BLiveClient):
if need_translate: if need_translate:
asyncio.ensure_future(self._translate_and_response(message.message, id_)) asyncio.ensure_future(self._translate_and_response(message.message, id_))
async def _on_super_chat_delete(self, message: blivedm.SuperChatDeleteMessage): async def _on_super_chat_delete(self, client: blivedm.BLiveClient, message: blivedm.SuperChatDeleteMessage):
self.send_message(Command.ADD_SUPER_CHAT, { self.send_message(Command.ADD_SUPER_CHAT, {
'ids': list(map(str, message.ids)) 'ids': list(map(str, message.ids))
}) })
@ -360,7 +375,7 @@ class RoomManager:
logger.info('Removing room %d', room_id) logger.info('Removing room %d', room_id)
for client in room.clients: for client in room.clients:
client.close() client.close()
room.stop_and_close() asyncio.ensure_future(room.stop_and_close())
self._rooms.pop(room_id, None) self._rooms.pop(room_id, None)
logger.info('%d rooms', len(self._rooms)) logger.info('%d rooms', len(self._rooms))
@ -547,7 +562,7 @@ class ChatHandler(tornado.websocket.WebSocketHandler):
# noinspection PyAbstractClass # noinspection PyAbstractClass
class RoomInfoHandler(api.base.ApiHandler): class RoomInfoHandler(api.base.ApiHandler):
_host_server_list_cache = blivedm.DEFAULT_DANMAKU_SERVER_LIST _host_server_list_cache = blivedm_client.DEFAULT_DANMAKU_SERVER_LIST
async def get(self): async def get(self):
room_id = int(self.get_query_argument('roomId')) room_id = int(self.get_query_argument('roomId'))
@ -569,7 +584,7 @@ class RoomInfoHandler(api.base.ApiHandler):
@staticmethod @staticmethod
async def _get_room_info(room_id): async def _get_room_info(room_id):
try: try:
async with _http_session.get(blivedm.ROOM_INIT_URL, params={'room_id': room_id} async with _http_session.get(blivedm_client.ROOM_INIT_URL, params={'room_id': room_id}
) as res: ) as res:
if res.status != 200: if res.status != 200:
logger.warning('room %d _get_room_info failed: %d %s', room_id, logger.warning('room %d _get_room_info failed: %d %s', room_id,

@ -1 +1 @@
Subproject commit 4669b2c1c9a1654db340d02ff16c9f88be661d9f Subproject commit d8f7f6b7828069cb6c1fd13f756cfd891f0b1a46

View File

@ -1,4 +1,5 @@
aiohttp==3.7.4 aiohttp==3.7.4
Brotli==1.0.9
pycryptodome==3.10.1 pycryptodome==3.10.1
sqlalchemy==1.3.13 sqlalchemy==1.3.13
tornado==6.0.2 tornado==6.0.2