From 8fd7cb467a7e0d0e6ff122e6cd5bc70423756c22 Mon Sep 17 00:00:00 2001 From: John Smith Date: Sun, 22 Dec 2024 23:39:16 +0800 Subject: [PATCH] =?UTF-8?q?web=E6=8E=A5=E5=8F=A3=E6=B7=BB=E5=8A=A0?= =?UTF-8?q?=E8=BF=9B=E5=85=A5=E6=88=BF=E9=97=B4=E6=B6=88=E6=81=AF=E3=80=81?= =?UTF-8?q?=E5=8F=A6=E4=B8=80=E4=B8=AA=E4=B8=8A=E8=88=B0=E6=B6=88=E6=81=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- blivedm/handlers.py | 97 +++++++++++++++++-------------------------- blivedm/models/web.py | 85 ++++++++++++++++++++++++++++++++++++- sample.py | 20 +++++---- 3 files changed, 133 insertions(+), 69 deletions(-) diff --git a/blivedm/handlers.py b/blivedm/handlers.py index 5cdbe90..531f2b9 100644 --- a/blivedm/handlers.py +++ b/blivedm/handlers.py @@ -17,7 +17,6 @@ logged_unknown_cmds = { 'ENTRY_EFFECT', 'HOT_RANK_CHANGED', 'HOT_RANK_CHANGED_V2', - 'INTERACT_WORD', 'LIVE', 'LIVE_INTERACTIVE_GAME', 'NOTICE_MSG', @@ -35,6 +34,7 @@ logged_unknown_cmds = { 'ROOM_REAL_TIME_MESSAGE_UPDATE', 'STOP_LIVE_ROOM_LIST', 'SUPER_CHAT_MESSAGE_JPN', + 'USER_TOAST_MSG', 'WIDGET_BANNER', } """已打日志的未知cmd""" @@ -75,30 +75,36 @@ class BaseHandler(HandlerInterface): ['BaseHandler', ws_base.WebSocketClientBase, dict], Any ]] - ] = { + ] + """cmd -> 处理回调""" + _CMD_CALLBACK_DICT = { # 收到心跳包,这是blivedm自造的消息,原本的心跳包格式不一样 '_HEARTBEAT': _make_msg_callback('_on_heartbeat', web_models.HeartbeatMessage), - # 收到弹幕 + # 弹幕 # go-common\app\service\live\live-dm\service\v1\send.go 'DANMU_MSG': __danmu_msg_callback, - # 有人送礼 + # 礼物 'SEND_GIFT': _make_msg_callback('_on_gift', web_models.GiftMessage), - # 有人上舰 + # 上舰 'GUARD_BUY': _make_msg_callback('_on_buy_guard', web_models.GuardBuyMessage), + # 另一个上舰消息 + 'USER_TOAST_MSG_V2': _make_msg_callback('_on_user_toast_v2', web_models.UserToastV2Message), # 醒目留言 'SUPER_CHAT_MESSAGE': _make_msg_callback('_on_super_chat', web_models.SuperChatMessage), # 删除醒目留言 'SUPER_CHAT_MESSAGE_DELETE': _make_msg_callback('_on_super_chat_delete', web_models.SuperChatDeleteMessage), + # 进入房间、关注主播等互动消息 + 'INTERACT_WORD': _make_msg_callback('_on_interact_word', web_models.InteractWordMessage), # # 开放平台消息 # - # 收到弹幕 + # 弹幕 'LIVE_OPEN_PLATFORM_DM': _make_msg_callback('_on_open_live_danmaku', open_models.DanmakuMessage), - # 有人送礼 + # 礼物 'LIVE_OPEN_PLATFORM_SEND_GIFT': _make_msg_callback('_on_open_live_gift', open_models.GiftMessage), - # 有人上舰 + # 上舰 'LIVE_OPEN_PLATFORM_GUARD': _make_msg_callback('_on_open_live_buy_guard', open_models.GuardBuyMessage), # 醒目留言 'LIVE_OPEN_PLATFORM_SUPER_CHAT': _make_msg_callback('_on_open_live_super_chat', open_models.SuperChatMessage), @@ -115,7 +121,6 @@ class BaseHandler(HandlerInterface): # 结束直播 'LIVE_OPEN_PLATFORM_LIVE_END': _make_msg_callback('_on_open_live_end_live', open_models.LiveEndMessage), } - """cmd -> 处理回调""" def handle(self, client: ws_base.WebSocketClientBase, command: dict): cmd = command.get('cmd', '') @@ -135,86 +140,58 @@ class BaseHandler(HandlerInterface): callback(self, client, command) def _on_heartbeat(self, client: ws_base.WebSocketClientBase, message: web_models.HeartbeatMessage): - """ - 收到心跳包 - """ + """收到心跳包""" def _on_danmaku(self, client: ws_base.WebSocketClientBase, message: web_models.DanmakuMessage): - """ - 收到弹幕 - """ + """弹幕""" def _on_gift(self, client: ws_base.WebSocketClientBase, message: web_models.GiftMessage): - """ - 收到礼物 - """ + """礼物""" def _on_buy_guard(self, client: ws_base.WebSocketClientBase, message: web_models.GuardBuyMessage): - """ - 有人上舰 - """ + """上舰""" + + def _on_user_toast_v2(self, client: ws_base.WebSocketClientBase, message: web_models.UserToastV2Message): + """另一个上舰消息""" def _on_super_chat(self, client: ws_base.WebSocketClientBase, message: web_models.SuperChatMessage): - """ - 醒目留言 - """ + """醒目留言""" - def _on_super_chat_delete( - self, client: ws_base.WebSocketClientBase, message: web_models.SuperChatDeleteMessage - ): - """ - 删除醒目留言 - """ + def _on_super_chat_delete(self, client: ws_base.WebSocketClientBase, message: web_models.SuperChatDeleteMessage): + """删除醒目留言""" + + def _on_interact_word(self, client: ws_base.WebSocketClientBase, message: web_models.InteractWordMessage): + """进入房间、关注主播等互动消息""" # # 开放平台消息 # def _on_open_live_danmaku(self, client: ws_base.WebSocketClientBase, message: open_models.DanmakuMessage): - """ - 收到弹幕 - """ + """弹幕""" def _on_open_live_gift(self, client: ws_base.WebSocketClientBase, message: open_models.GiftMessage): - """ - 收到礼物 - """ + """礼物""" def _on_open_live_buy_guard(self, client: ws_base.WebSocketClientBase, message: open_models.GuardBuyMessage): - """ - 有人上舰 - """ + """上舰""" - def _on_open_live_super_chat( - self, client: ws_base.WebSocketClientBase, message: open_models.SuperChatMessage - ): - """ - 醒目留言 - """ + def _on_open_live_super_chat(self, client: ws_base.WebSocketClientBase, message: open_models.SuperChatMessage): + """醒目留言""" def _on_open_live_super_chat_delete( self, client: ws_base.WebSocketClientBase, message: open_models.SuperChatDeleteMessage ): - """ - 删除醒目留言 - """ + """删除醒目留言""" def _on_open_live_like(self, client: ws_base.WebSocketClientBase, message: open_models.LikeMessage): - """ - 点赞 - """ + """点赞""" def _on_open_live_enter_room(self, client: ws_base.WebSocketClientBase, message: open_models.RoomEnterMessage): - """ - 进入房间 - """ + """进入房间""" def _on_open_live_start_live(self, client: ws_base.WebSocketClientBase, message: open_models.LiveStartMessage): - """ - 开始直播 - """ + """开始直播""" def _on_open_live_end_live(self, client: ws_base.WebSocketClientBase, message: open_models.LiveEndMessage): - """ - 结束直播 - """ + """结束直播""" diff --git a/blivedm/models/web.py b/blivedm/models/web.py index 1473f49..9aab924 100644 --- a/blivedm/models/web.py +++ b/blivedm/models/web.py @@ -276,7 +276,7 @@ class GuardBuyMessage: """用户名""" guard_level: int = 0 """舰队等级,0非舰队,1总督,2提督,3舰长""" - num: int = 0 + num: int = 0 # 可以理解为礼物数量? """数量""" price: int = 0 """单价金瓜子数""" @@ -304,6 +304,57 @@ class GuardBuyMessage: ) +@dataclasses.dataclass +class UserToastV2Message: + """ + 另一个上舰消息,包含的数据更多 + """ + + uid: int = 0 + """用户ID""" + username: str = '' + """用户名""" + guard_level: int = 0 + """舰队等级,0非舰队,1总督,2提督,3舰长""" + num: int = 0 # 可以理解为礼物数量? + """数量""" + price: int = 0 + """单价金瓜子数""" + unit: str = '' + """单位,根据开放平台的文档,正常单位为“月”,如为其他内容,无视`guard_num`以本字段内容为准,例如`*3天`""" + gift_id: int = 0 + """礼物ID""" + start_time: int = 0 + """开始时间戳,和结束时间戳相同""" + end_time: int = 0 + """结束时间戳,和开始时间戳相同""" + source: int = 0 + """猜测0是自己买的,2是别人送的,这个只影响是否播动画""" + toast_msg: str = '' + """提示信息("<%XXX%> 在主播XXX的直播间续费了舰长,今天是TA陪伴主播的第XXX天")""" + + @classmethod + def from_command(cls, data: dict): + sender_info = data['sender_uinfo'] + guard_info = data['guard_info'] + pay_info = data['pay_info'] + gift_info = data['gift_info'] + option = data['option'] + return cls( + uid=sender_info['uid'], + username=sender_info['base']['name'], + guard_level=guard_info['guard_level'], + num=pay_info['num'], + price=pay_info['price'], + unit=pay_info['unit'], + gift_id=gift_info['gift_id'], + start_time=guard_info['start_time'], + end_time=guard_info['end_time'], + source=option['source'], + toast_msg=data['toast_msg'], + ) + + @dataclasses.dataclass class SuperChatMessage: """ @@ -315,7 +366,7 @@ class SuperChatMessage: message: str = '' """消息""" message_trans: str = '' - """消息日文翻译(目前只出现在SUPER_CHAT_MESSAGE_JPN)""" + """消息日文翻译""" start_time: int = 0 """开始时间戳""" end_time: int = 0 @@ -388,3 +439,33 @@ class SuperChatDeleteMessage: return cls( ids=data['ids'], ) + + +@dataclasses.dataclass +class InteractWordMessage: + """ + 进入房间、关注主播等互动消息 + """ + + uid: int = 0 + """用户ID""" + username: str = '' + """用户名""" + face: str = '' + """用户头像URL""" + timestamp: int = 0 + """时间戳""" + msg_type: int = 0 + """`{1: '进入', 2: '关注了', 3: '分享了', 4: '特别关注了', 5: '互粉了', 6: '为主播点赞了'}`""" + + @classmethod + def from_command(cls, data: dict): + user_info = data['uinfo'] + user_base_info = user_info['base'] + return cls( + uid=user_info['uid'], + username=user_base_info['name'], + face=user_base_info['face'], + timestamp=data['timestamp'], + msg_type=data['msg_type'], + ) diff --git a/sample.py b/sample.py index 976e434..b2fe1c9 100644 --- a/sample.py +++ b/sample.py @@ -87,11 +87,10 @@ class MyHandler(blivedm.BaseHandler): # # 演示如何添加自定义回调 # _CMD_CALLBACK_DICT = blivedm.BaseHandler._CMD_CALLBACK_DICT.copy() # - # # 入场消息回调 - # def __interact_word_callback(self, client: blivedm.BLiveClient, command: dict): - # print(f"[{client.room_id}] INTERACT_WORD: self_type={type(self).__name__}, room_id={client.room_id}," - # f" uname={command['data']['uname']}") - # _CMD_CALLBACK_DICT['INTERACT_WORD'] = __interact_word_callback # noqa + # # 看过数消息回调 + # def __watched_change_callback(self, client: blivedm.BLiveClient, command: dict): + # print(f'[{client.room_id}] WATCHED_CHANGE: {command}') + # _CMD_CALLBACK_DICT['WATCHED_CHANGE'] = __watched_change_callback # noqa def _on_heartbeat(self, client: blivedm.BLiveClient, message: web_models.HeartbeatMessage): print(f'[{client.room_id}] 心跳') @@ -103,12 +102,19 @@ class MyHandler(blivedm.BaseHandler): print(f'[{client.room_id}] {message.uname} 赠送{message.gift_name}x{message.num}' f' ({message.coin_type}瓜子x{message.total_coin})') - def _on_buy_guard(self, client: blivedm.BLiveClient, message: web_models.GuardBuyMessage): - print(f'[{client.room_id}] {message.username} 购买{message.gift_name}') + # def _on_buy_guard(self, client: blivedm.BLiveClient, message: web_models.GuardBuyMessage): + # print(f'[{client.room_id}] {message.username} 上舰,guard_level={message.guard_level}') + + def _on_user_toast_v2(self, client: blivedm.BLiveClient, message: web_models.UserToastV2Message): + print(f'[{client.room_id}] {message.username} 上舰,guard_level={message.guard_level}') def _on_super_chat(self, client: blivedm.BLiveClient, message: web_models.SuperChatMessage): print(f'[{client.room_id}] 醒目留言 ¥{message.price} {message.uname}:{message.message}') + # def _on_interact_word(self, client: blivedm.BLiveClient, message: web_models.InteractWordMessage): + # if message.msg_type == 1: + # print(f'[{client.room_id}] {message.username} 进入房间') + if __name__ == '__main__': asyncio.run(main())