最低支持的Python版本升级到3.8
This commit is contained in:
parent
61e6825d4e
commit
924b99eed6
@ -1,15 +1,18 @@
|
|||||||
# blivedm
|
# blivedm
|
||||||
Python 3获取bilibili直播弹幕,使用websocket协议
|
|
||||||
|
Python获取bilibili直播弹幕的库,使用WebSocket协议
|
||||||
|
|
||||||
[协议解释](https://blog.csdn.net/xfgryujk/article/details/80306776)(有点过时了,总体是没错的)
|
[协议解释](https://blog.csdn.net/xfgryujk/article/details/80306776)(有点过时了,总体是没错的)
|
||||||
|
|
||||||
基于本库开发的一个应用:[blivechat](https://github.com/xfgryujk/blivechat)
|
基于本库开发的一个应用:[blivechat](https://github.com/xfgryujk/blivechat)
|
||||||
|
|
||||||
|
|
||||||
## 使用说明
|
## 使用说明
|
||||||
1. 需要Python 3.6及以上版本
|
|
||||||
|
1. 需要Python 3.8及以上版本
|
||||||
2. 安装依赖
|
2. 安装依赖
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
pip install -r requirements.txt
|
pip install -r requirements.txt
|
||||||
```
|
```
|
||||||
|
|
||||||
3. 例程看[sample.py](./sample.py)
|
3. 例程看[sample.py](./sample.py)
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
import asyncio
|
import asyncio
|
||||||
import collections
|
|
||||||
import enum
|
import enum
|
||||||
import json
|
import json
|
||||||
import logging
|
import logging
|
||||||
@ -26,7 +25,14 @@ DEFAULT_DANMAKU_SERVER_LIST = [
|
|||||||
]
|
]
|
||||||
|
|
||||||
HEADER_STRUCT = struct.Struct('>I2H2I')
|
HEADER_STRUCT = struct.Struct('>I2H2I')
|
||||||
HeaderTuple = collections.namedtuple('HeaderTuple', ('pack_len', 'raw_header_size', 'ver', 'operation', 'seq_id'))
|
|
||||||
|
|
||||||
|
class HeaderTuple(NamedTuple):
|
||||||
|
pack_len: int
|
||||||
|
raw_header_size: int
|
||||||
|
ver: int
|
||||||
|
operation: int
|
||||||
|
seq_id: int
|
||||||
|
|
||||||
|
|
||||||
# WS_BODY_PROTOCOL_VERSION
|
# WS_BODY_PROTOCOL_VERSION
|
||||||
@ -95,8 +101,8 @@ class BLiveClient:
|
|||||||
heartbeat_interval=30,
|
heartbeat_interval=30,
|
||||||
ssl: Union[bool, ssl_.SSLContext] = True,
|
ssl: Union[bool, ssl_.SSLContext] = True,
|
||||||
):
|
):
|
||||||
# 用来init_room的临时房间ID,可以用短ID
|
|
||||||
self._tmp_room_id = room_id
|
self._tmp_room_id = room_id
|
||||||
|
"""用来init_room的临时房间ID,可以用短ID"""
|
||||||
self._uid = uid
|
self._uid = uid
|
||||||
|
|
||||||
if session is None:
|
if session is None:
|
||||||
@ -110,29 +116,31 @@ class BLiveClient:
|
|||||||
self._heartbeat_interval = heartbeat_interval
|
self._heartbeat_interval = heartbeat_interval
|
||||||
self._ssl = ssl if ssl else ssl_._create_unverified_context() # noqa
|
self._ssl = ssl if ssl else ssl_._create_unverified_context() # noqa
|
||||||
|
|
||||||
# 消息处理器,可动态增删
|
|
||||||
self._handlers: List[handlers.HandlerInterface] = []
|
self._handlers: List[handlers.HandlerInterface] = []
|
||||||
|
"""消息处理器,可动态增删"""
|
||||||
|
|
||||||
# 在调用init_room后初始化的字段
|
# 在调用init_room后初始化的字段
|
||||||
# 真实房间ID
|
|
||||||
self._room_id = None
|
self._room_id = None
|
||||||
# 房间短ID,没有则为0
|
"""真实房间ID"""
|
||||||
self._room_short_id = None
|
self._room_short_id = None
|
||||||
# 主播用户ID
|
"""房间短ID,没有则为0"""
|
||||||
self._room_owner_uid = None
|
self._room_owner_uid = None
|
||||||
# 弹幕服务器列表
|
"""主播用户ID"""
|
||||||
# [{host: "tx-bj4-live-comet-04.chat.bilibili.com", port: 2243, wss_port: 443, ws_port: 2244}, ...]
|
|
||||||
self._host_server_list: Optional[List[dict]] = None
|
self._host_server_list: Optional[List[dict]] = None
|
||||||
# 连接弹幕服务器用的token
|
"""
|
||||||
|
弹幕服务器列表
|
||||||
|
[{host: "tx-bj4-live-comet-04.chat.bilibili.com", port: 2243, wss_port: 443, ws_port: 2244}, ...]
|
||||||
|
"""
|
||||||
self._host_server_token = None
|
self._host_server_token = None
|
||||||
|
"""连接弹幕服务器用的token"""
|
||||||
|
|
||||||
# 在运行时初始化的字段
|
# 在运行时初始化的字段
|
||||||
# websocket连接
|
|
||||||
self._websocket: Optional[aiohttp.ClientWebSocketResponse] = None
|
self._websocket: Optional[aiohttp.ClientWebSocketResponse] = None
|
||||||
# 网络协程的future
|
"""WebSocket连接"""
|
||||||
self._network_future: Optional[asyncio.Future] = None
|
self._network_future: Optional[asyncio.Future] = None
|
||||||
# 发心跳包定时器的handle
|
"""网络协程的future"""
|
||||||
self._heartbeat_timer_handle: Optional[asyncio.TimerHandle] = None
|
self._heartbeat_timer_handle: Optional[asyncio.TimerHandle] = None
|
||||||
|
"""发心跳包定时器的handle"""
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def is_running(self) -> bool:
|
def is_running(self) -> bool:
|
||||||
@ -192,7 +200,7 @@ class BLiveClient:
|
|||||||
logger.warning('room=%s client is running, cannot start() again', self.room_id)
|
logger.warning('room=%s client is running, cannot start() again', self.room_id)
|
||||||
return
|
return
|
||||||
|
|
||||||
self._network_future = asyncio.ensure_future(self._network_coroutine_wrapper())
|
self._network_future = asyncio.create_task(self._network_coroutine_wrapper())
|
||||||
|
|
||||||
def stop(self):
|
def stop(self):
|
||||||
"""
|
"""
|
||||||
@ -355,7 +363,7 @@ class BLiveClient:
|
|||||||
except asyncio.CancelledError:
|
except asyncio.CancelledError:
|
||||||
# 正常停止
|
# 正常停止
|
||||||
pass
|
pass
|
||||||
except Exception as e: # noqa
|
except Exception: # noqa
|
||||||
logger.exception('room=%s _network_coroutine() finished with exception:', self.room_id)
|
logger.exception('room=%s _network_coroutine() finished with exception:', self.room_id)
|
||||||
finally:
|
finally:
|
||||||
logger.debug('room=%s _network_coroutine() finished', self.room_id)
|
logger.debug('room=%s _network_coroutine() finished', self.room_id)
|
||||||
@ -416,7 +424,7 @@ class BLiveClient:
|
|||||||
|
|
||||||
async def _on_ws_connect(self):
|
async def _on_ws_connect(self):
|
||||||
"""
|
"""
|
||||||
websocket连接成功
|
WebSocket连接成功
|
||||||
"""
|
"""
|
||||||
await self._send_auth()
|
await self._send_auth()
|
||||||
self._heartbeat_timer_handle = asyncio.get_running_loop().call_later(
|
self._heartbeat_timer_handle = asyncio.get_running_loop().call_later(
|
||||||
@ -425,7 +433,7 @@ class BLiveClient:
|
|||||||
|
|
||||||
async def _on_ws_close(self):
|
async def _on_ws_close(self):
|
||||||
"""
|
"""
|
||||||
websocket连接断开
|
WebSocket连接断开
|
||||||
"""
|
"""
|
||||||
if self._heartbeat_timer_handle is not None:
|
if self._heartbeat_timer_handle is not None:
|
||||||
self._heartbeat_timer_handle.cancel()
|
self._heartbeat_timer_handle.cancel()
|
||||||
@ -457,7 +465,7 @@ class BLiveClient:
|
|||||||
self._heartbeat_timer_handle = asyncio.get_running_loop().call_later(
|
self._heartbeat_timer_handle = asyncio.get_running_loop().call_later(
|
||||||
self._heartbeat_interval, self._on_send_heartbeat
|
self._heartbeat_interval, self._on_send_heartbeat
|
||||||
)
|
)
|
||||||
asyncio.ensure_future(self._send_heartbeat())
|
asyncio.create_task(self._send_heartbeat())
|
||||||
|
|
||||||
async def _send_heartbeat(self):
|
async def _send_heartbeat(self):
|
||||||
"""
|
"""
|
||||||
@ -475,9 +483,9 @@ class BLiveClient:
|
|||||||
|
|
||||||
async def _on_ws_message(self, message: aiohttp.WSMessage):
|
async def _on_ws_message(self, message: aiohttp.WSMessage):
|
||||||
"""
|
"""
|
||||||
收到websocket消息
|
收到WebSocket消息
|
||||||
|
|
||||||
:param message: websocket消息
|
:param message: WebSocket消息
|
||||||
"""
|
"""
|
||||||
if message.type != aiohttp.WSMsgType.BINARY:
|
if message.type != aiohttp.WSMsgType.BINARY:
|
||||||
logger.warning('room=%d unknown websocket message type=%s, data=%s', self.room_id,
|
logger.warning('room=%d unknown websocket message type=%s, data=%s', self.room_id,
|
||||||
@ -494,9 +502,9 @@ class BLiveClient:
|
|||||||
|
|
||||||
async def _parse_ws_message(self, data: bytes):
|
async def _parse_ws_message(self, data: bytes):
|
||||||
"""
|
"""
|
||||||
解析websocket消息
|
解析WebSocket消息
|
||||||
|
|
||||||
:param data: websocket消息数据
|
:param data: WebSocket消息数据
|
||||||
"""
|
"""
|
||||||
offset = 0
|
offset = 0
|
||||||
try:
|
try:
|
||||||
|
@ -12,7 +12,6 @@ __all__ = (
|
|||||||
|
|
||||||
logger = logging.getLogger('blivedm')
|
logger = logging.getLogger('blivedm')
|
||||||
|
|
||||||
# 常见可忽略的cmd
|
|
||||||
IGNORED_CMDS = (
|
IGNORED_CMDS = (
|
||||||
'COMBO_SEND',
|
'COMBO_SEND',
|
||||||
'ENTRY_EFFECT',
|
'ENTRY_EFFECT',
|
||||||
@ -38,9 +37,10 @@ IGNORED_CMDS = (
|
|||||||
'SUPER_CHAT_MESSAGE_JPN',
|
'SUPER_CHAT_MESSAGE_JPN',
|
||||||
'WIDGET_BANNER',
|
'WIDGET_BANNER',
|
||||||
)
|
)
|
||||||
|
"""常见可忽略的cmd"""
|
||||||
|
|
||||||
# 已打日志的未知cmd
|
|
||||||
logged_unknown_cmds = set()
|
logged_unknown_cmds = set()
|
||||||
|
"""已打日志的未知cmd"""
|
||||||
|
|
||||||
|
|
||||||
class HandlerInterface:
|
class HandlerInterface:
|
||||||
@ -75,7 +75,6 @@ class BaseHandler(HandlerInterface):
|
|||||||
def __super_chat_message_delete_callback(self, client: client_.BLiveClient, command: dict):
|
def __super_chat_message_delete_callback(self, client: client_.BLiveClient, command: dict):
|
||||||
return self._on_super_chat_delete(client, models.SuperChatDeleteMessage.from_command(command['data']))
|
return self._on_super_chat_delete(client, models.SuperChatDeleteMessage.from_command(command['data']))
|
||||||
|
|
||||||
# cmd -> 处理回调
|
|
||||||
_CMD_CALLBACK_DICT: Dict[
|
_CMD_CALLBACK_DICT: Dict[
|
||||||
str,
|
str,
|
||||||
Optional[Callable[
|
Optional[Callable[
|
||||||
@ -97,6 +96,7 @@ class BaseHandler(HandlerInterface):
|
|||||||
# 删除醒目留言
|
# 删除醒目留言
|
||||||
'SUPER_CHAT_MESSAGE_DELETE': __super_chat_message_delete_callback,
|
'SUPER_CHAT_MESSAGE_DELETE': __super_chat_message_delete_callback,
|
||||||
}
|
}
|
||||||
|
"""cmd -> 处理回调"""
|
||||||
# 忽略其他常见cmd
|
# 忽略其他常见cmd
|
||||||
for cmd in IGNORED_CMDS:
|
for cmd in IGNORED_CMDS:
|
||||||
_CMD_CALLBACK_DICT[cmd] = None
|
_CMD_CALLBACK_DICT[cmd] = None
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
|
import dataclasses
|
||||||
import json
|
import json
|
||||||
from typing import *
|
from typing import *
|
||||||
|
|
||||||
@ -12,18 +13,14 @@ __all__ = (
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@dataclasses.dataclass
|
||||||
class HeartbeatMessage:
|
class HeartbeatMessage:
|
||||||
"""
|
"""
|
||||||
心跳消息
|
心跳消息
|
||||||
|
|
||||||
:param popularity: 人气值
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(
|
popularity: int = None
|
||||||
self,
|
"""人气值"""
|
||||||
popularity: int = None,
|
|
||||||
):
|
|
||||||
self.popularity: int = popularity
|
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def from_command(cls, data: dict):
|
def from_command(cls, data: dict):
|
||||||
@ -32,132 +29,84 @@ class HeartbeatMessage:
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@dataclasses.dataclass
|
||||||
class DanmakuMessage:
|
class DanmakuMessage:
|
||||||
"""
|
"""
|
||||||
弹幕消息
|
弹幕消息
|
||||||
|
|
||||||
:param mode: 弹幕显示模式(滚动、顶部、底部)
|
|
||||||
:param font_size: 字体尺寸
|
|
||||||
:param color: 颜色
|
|
||||||
:param timestamp: 时间戳(毫秒)
|
|
||||||
:param rnd: 随机数,前端叫作弹幕ID,可能是去重用的
|
|
||||||
:param uid_crc32: 用户ID文本的CRC32
|
|
||||||
:param msg_type: 是否礼物弹幕(节奏风暴)
|
|
||||||
:param bubble: 右侧评论栏气泡
|
|
||||||
:param dm_type: 弹幕类型,0文本,1表情,2语音
|
|
||||||
:param emoticon_options: 表情参数
|
|
||||||
:param voice_config: 语音参数
|
|
||||||
:param mode_info: 一些附加参数
|
|
||||||
|
|
||||||
:param msg: 弹幕内容
|
|
||||||
|
|
||||||
:param uid: 用户ID
|
|
||||||
:param uname: 用户名
|
|
||||||
:param admin: 是否房管
|
|
||||||
:param vip: 是否月费老爷
|
|
||||||
:param svip: 是否年费老爷
|
|
||||||
:param urank: 用户身份,用来判断是否正式会员,猜测非正式会员为5000,正式会员为10000
|
|
||||||
:param mobile_verify: 是否绑定手机
|
|
||||||
:param uname_color: 用户名颜色
|
|
||||||
|
|
||||||
:param medal_level: 勋章等级
|
|
||||||
:param medal_name: 勋章名
|
|
||||||
:param runame: 勋章房间主播名
|
|
||||||
:param medal_room_id: 勋章房间ID
|
|
||||||
:param mcolor: 勋章颜色
|
|
||||||
:param special_medal: 特殊勋章
|
|
||||||
|
|
||||||
:param user_level: 用户等级
|
|
||||||
:param ulevel_color: 用户等级颜色
|
|
||||||
:param ulevel_rank: 用户等级排名,>50000时为'>50000'
|
|
||||||
|
|
||||||
:param old_title: 旧头衔
|
|
||||||
:param title: 头衔
|
|
||||||
|
|
||||||
:param privilege_type: 舰队类型,0非舰队,1总督,2提督,3舰长
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(
|
mode: int = None
|
||||||
self,
|
"""弹幕显示模式(滚动、顶部、底部)"""
|
||||||
mode: int = None,
|
font_size: int = None
|
||||||
font_size: int = None,
|
"""字体尺寸"""
|
||||||
color: int = None,
|
color: int = None
|
||||||
timestamp: int = None,
|
"""颜色"""
|
||||||
rnd: int = None,
|
timestamp: int = None
|
||||||
uid_crc32: str = None,
|
"""时间戳(毫秒)"""
|
||||||
msg_type: int = None,
|
rnd: int = None
|
||||||
bubble: int = None,
|
"""随机数,前端叫作弹幕ID,可能是去重用的"""
|
||||||
dm_type: int = None,
|
uid_crc32: str = None
|
||||||
emoticon_options: Union[dict, str] = None,
|
"""用户ID文本的CRC32"""
|
||||||
voice_config: Union[dict, str] = None,
|
msg_type: int = None
|
||||||
mode_info: dict = None,
|
"""是否礼物弹幕(节奏风暴)"""
|
||||||
|
bubble: int = None
|
||||||
|
"""右侧评论栏气泡"""
|
||||||
|
dm_type: int = None
|
||||||
|
"""弹幕类型,0文本,1表情,2语音"""
|
||||||
|
emoticon_options: Union[dict, str] = None
|
||||||
|
"""表情参数"""
|
||||||
|
voice_config: Union[dict, str] = None
|
||||||
|
"""语音参数"""
|
||||||
|
mode_info: dict = None
|
||||||
|
"""一些附加参数"""
|
||||||
|
|
||||||
msg: str = None,
|
msg: str = None
|
||||||
|
"""弹幕内容"""
|
||||||
|
|
||||||
uid: int = None,
|
uid: int = None
|
||||||
uname: str = None,
|
"""用户ID"""
|
||||||
admin: int = None,
|
uname: str = None
|
||||||
vip: int = None,
|
"""用户名"""
|
||||||
svip: int = None,
|
admin: int = None
|
||||||
urank: int = None,
|
"""是否房管"""
|
||||||
mobile_verify: int = None,
|
vip: int = None
|
||||||
uname_color: str = None,
|
"""是否月费老爷"""
|
||||||
|
svip: int = None
|
||||||
|
"""是否年费老爷"""
|
||||||
|
urank: int = None
|
||||||
|
"""用户身份,用来判断是否正式会员,猜测非正式会员为5000,正式会员为10000"""
|
||||||
|
mobile_verify: int = None
|
||||||
|
"""是否绑定手机"""
|
||||||
|
uname_color: str = None
|
||||||
|
"""用户名颜色"""
|
||||||
|
|
||||||
medal_level: str = None,
|
medal_level: str = None
|
||||||
medal_name: str = None,
|
"""勋章等级"""
|
||||||
runame: str = None,
|
medal_name: str = None
|
||||||
medal_room_id: int = None,
|
"""勋章名"""
|
||||||
mcolor: int = None,
|
runame: str = None
|
||||||
special_medal: str = None,
|
"""勋章房间主播名"""
|
||||||
|
medal_room_id: int = None
|
||||||
|
"""勋章房间ID"""
|
||||||
|
mcolor: int = None
|
||||||
|
"""勋章颜色"""
|
||||||
|
special_medal: str = None
|
||||||
|
"""特殊勋章"""
|
||||||
|
|
||||||
user_level: int = None,
|
user_level: int = None
|
||||||
ulevel_color: int = None,
|
"""用户等级"""
|
||||||
ulevel_rank: str = None,
|
ulevel_color: int = None
|
||||||
|
"""用户等级颜色"""
|
||||||
|
ulevel_rank: str = None
|
||||||
|
"""用户等级排名,>50000时为'>50000'"""
|
||||||
|
|
||||||
old_title: str = None,
|
old_title: str = None
|
||||||
title: str = None,
|
"""旧头衔"""
|
||||||
|
title: str = None
|
||||||
|
"""头衔"""
|
||||||
|
|
||||||
privilege_type: int = None,
|
privilege_type: int = None
|
||||||
):
|
"""舰队类型,0非舰队,1总督,2提督,3舰长"""
|
||||||
self.mode: int = mode
|
|
||||||
self.font_size: int = font_size
|
|
||||||
self.color: int = color
|
|
||||||
self.timestamp: int = timestamp
|
|
||||||
self.rnd: int = rnd
|
|
||||||
self.uid_crc32: str = uid_crc32
|
|
||||||
self.msg_type: int = msg_type
|
|
||||||
self.bubble: int = bubble
|
|
||||||
self.dm_type: int = dm_type
|
|
||||||
self.emoticon_options: Union[dict, str] = emoticon_options
|
|
||||||
self.voice_config: Union[dict, str] = voice_config
|
|
||||||
self.mode_info: dict = mode_info
|
|
||||||
|
|
||||||
self.msg: str = msg
|
|
||||||
|
|
||||||
self.uid: int = uid
|
|
||||||
self.uname: str = uname
|
|
||||||
self.admin: int = admin
|
|
||||||
self.vip: int = vip
|
|
||||||
self.svip: int = svip
|
|
||||||
self.urank: int = urank
|
|
||||||
self.mobile_verify: int = mobile_verify
|
|
||||||
self.uname_color: str = uname_color
|
|
||||||
|
|
||||||
self.medal_level: str = medal_level
|
|
||||||
self.medal_name: str = medal_name
|
|
||||||
self.runame: str = runame
|
|
||||||
self.medal_room_id: int = medal_room_id
|
|
||||||
self.mcolor: int = mcolor
|
|
||||||
self.special_medal: str = special_medal
|
|
||||||
|
|
||||||
self.user_level: int = user_level
|
|
||||||
self.ulevel_color: int = ulevel_color
|
|
||||||
self.ulevel_rank: str = ulevel_rank
|
|
||||||
|
|
||||||
self.old_title: str = old_title
|
|
||||||
self.title: str = title
|
|
||||||
|
|
||||||
self.privilege_type: int = privilege_type
|
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def from_command(cls, info: dict):
|
def from_command(cls, info: dict):
|
||||||
@ -250,60 +199,42 @@ class DanmakuMessage:
|
|||||||
return {}
|
return {}
|
||||||
|
|
||||||
|
|
||||||
|
@dataclasses.dataclass
|
||||||
class GiftMessage:
|
class GiftMessage:
|
||||||
"""
|
"""
|
||||||
礼物消息
|
礼物消息
|
||||||
|
|
||||||
:param gift_name: 礼物名
|
|
||||||
:param num: 数量
|
|
||||||
:param uname: 用户名
|
|
||||||
:param face: 用户头像URL
|
|
||||||
:param guard_level: 舰队等级,0非舰队,1总督,2提督,3舰长
|
|
||||||
:param uid: 用户ID
|
|
||||||
:param timestamp: 时间戳
|
|
||||||
:param gift_id: 礼物ID
|
|
||||||
:param gift_type: 礼物类型(未知)
|
|
||||||
:param action: 目前遇到的有'喂食'、'赠送'
|
|
||||||
:param price: 礼物单价瓜子数
|
|
||||||
:param rnd: 随机数,可能是去重用的。有时是时间戳+去重ID,有时是UUID
|
|
||||||
:param coin_type: 瓜子类型,'silver'或'gold',1000金瓜子 = 1元
|
|
||||||
:param total_coin: 总瓜子数
|
|
||||||
:param tid: 可能是事务ID,有时和rnd相同
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(
|
gift_name: str = None
|
||||||
self,
|
"""礼物名"""
|
||||||
gift_name: str = None,
|
num: int = None
|
||||||
num: int = None,
|
"""数量"""
|
||||||
uname: str = None,
|
uname: str = None
|
||||||
face: str = None,
|
"""用户名"""
|
||||||
guard_level: int = None,
|
face: str = None
|
||||||
uid: int = None,
|
"""用户头像URL"""
|
||||||
timestamp: int = None,
|
guard_level: int = None
|
||||||
gift_id: int = None,
|
"""舰队等级,0非舰队,1总督,2提督,3舰长"""
|
||||||
gift_type: int = None,
|
uid: int = None
|
||||||
action: str = None,
|
"""用户ID"""
|
||||||
price: int = None,
|
timestamp: int = None
|
||||||
rnd: str = None,
|
"""时间戳"""
|
||||||
coin_type: str = None,
|
gift_id: int = None
|
||||||
total_coin: int = None,
|
"""礼物ID"""
|
||||||
tid: str = None,
|
gift_type: int = None
|
||||||
):
|
"""礼物类型(未知)"""
|
||||||
self.gift_name = gift_name
|
action: str = None
|
||||||
self.num = num
|
"""目前遇到的有'喂食'、'赠送'"""
|
||||||
self.uname = uname
|
price: int = None
|
||||||
self.face = face
|
"""礼物单价瓜子数"""
|
||||||
self.guard_level = guard_level
|
rnd: str = None
|
||||||
self.uid = uid
|
"""随机数,可能是去重用的。有时是时间戳+去重ID,有时是UUID"""
|
||||||
self.timestamp = timestamp
|
coin_type: str = None
|
||||||
self.gift_id = gift_id
|
"""瓜子类型,'silver'或'gold',1000金瓜子 = 1元"""
|
||||||
self.gift_type = gift_type
|
total_coin: int = None
|
||||||
self.action = action
|
"""总瓜子数"""
|
||||||
self.price = price
|
tid: str = None
|
||||||
self.rnd = rnd
|
"""可能是事务ID,有时和rnd相同"""
|
||||||
self.coin_type = coin_type
|
|
||||||
self.total_coin = total_coin
|
|
||||||
self.tid = tid
|
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def from_command(cls, data: dict):
|
def from_command(cls, data: dict):
|
||||||
@ -326,42 +257,30 @@ class GiftMessage:
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@dataclasses.dataclass
|
||||||
class GuardBuyMessage:
|
class GuardBuyMessage:
|
||||||
"""
|
"""
|
||||||
上舰消息
|
上舰消息
|
||||||
|
|
||||||
:param uid: 用户ID
|
|
||||||
:param username: 用户名
|
|
||||||
:param guard_level: 舰队等级,0非舰队,1总督,2提督,3舰长
|
|
||||||
:param num: 数量
|
|
||||||
:param price: 单价金瓜子数
|
|
||||||
:param gift_id: 礼物ID
|
|
||||||
:param gift_name: 礼物名
|
|
||||||
:param start_time: 开始时间戳,和结束时间戳相同
|
|
||||||
:param end_time: 结束时间戳,和开始时间戳相同
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(
|
uid: int = None
|
||||||
self,
|
"""用户ID"""
|
||||||
uid: int = None,
|
username: str = None
|
||||||
username: str = None,
|
"""用户名"""
|
||||||
guard_level: int = None,
|
guard_level: int = None
|
||||||
num: int = None,
|
"""舰队等级,0非舰队,1总督,2提督,3舰长"""
|
||||||
price: int = None,
|
num: int = None
|
||||||
gift_id: int = None,
|
"""数量"""
|
||||||
gift_name: str = None,
|
price: int = None
|
||||||
start_time: int = None,
|
"""单价金瓜子数"""
|
||||||
end_time: int = None,
|
gift_id: int = None
|
||||||
):
|
"""礼物ID"""
|
||||||
self.uid: int = uid
|
gift_name: str = None
|
||||||
self.username: str = username
|
"""礼物名"""
|
||||||
self.guard_level: int = guard_level
|
start_time: int = None
|
||||||
self.num: int = num
|
"""开始时间戳,和结束时间戳相同"""
|
||||||
self.price: int = price
|
end_time: int = None
|
||||||
self.gift_id: int = gift_id
|
"""结束时间戳,和开始时间戳相同"""
|
||||||
self.gift_name: str = gift_name
|
|
||||||
self.start_time: int = start_time
|
|
||||||
self.end_time: int = end_time
|
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def from_command(cls, data: dict):
|
def from_command(cls, data: dict):
|
||||||
@ -378,72 +297,50 @@ class GuardBuyMessage:
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@dataclasses.dataclass
|
||||||
class SuperChatMessage:
|
class SuperChatMessage:
|
||||||
"""
|
"""
|
||||||
醒目留言消息
|
醒目留言消息
|
||||||
|
|
||||||
:param price: 价格(人民币)
|
|
||||||
:param message: 消息
|
|
||||||
:param message_trans: 消息日文翻译(目前只出现在SUPER_CHAT_MESSAGE_JPN)
|
|
||||||
:param start_time: 开始时间戳
|
|
||||||
:param end_time: 结束时间戳
|
|
||||||
:param time: 剩余时间(约等于 结束时间戳 - 开始时间戳)
|
|
||||||
:param id_: str,醒目留言ID,删除时用
|
|
||||||
:param gift_id: 礼物ID
|
|
||||||
:param gift_name: 礼物名
|
|
||||||
:param uid: 用户ID
|
|
||||||
:param uname: 用户名
|
|
||||||
:param face: 用户头像URL
|
|
||||||
:param guard_level: 舰队等级,0非舰队,1总督,2提督,3舰长
|
|
||||||
:param user_level: 用户等级
|
|
||||||
:param background_bottom_color: 底部背景色,'#rrggbb'
|
|
||||||
:param background_color: 背景色,'#rrggbb'
|
|
||||||
:param background_icon: 背景图标
|
|
||||||
:param background_image: 背景图URL
|
|
||||||
:param background_price_color: 背景价格颜色,'#rrggbb'
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(
|
price: int = None
|
||||||
self,
|
"""价格(人民币)"""
|
||||||
price: int = None,
|
message: str = None
|
||||||
message: str = None,
|
"""消息"""
|
||||||
message_trans: str = None,
|
message_trans: str = None
|
||||||
start_time: int = None,
|
"""消息日文翻译(目前只出现在SUPER_CHAT_MESSAGE_JPN)"""
|
||||||
end_time: int = None,
|
start_time: int = None
|
||||||
time: int = None,
|
"""开始时间戳"""
|
||||||
id_: int = None,
|
end_time: int = None
|
||||||
gift_id: int = None,
|
"""结束时间戳"""
|
||||||
gift_name: str = None,
|
time: int = None
|
||||||
uid: int = None,
|
"""剩余时间(约等于 结束时间戳 - 开始时间戳)"""
|
||||||
uname: str = None,
|
id: int = None
|
||||||
face: str = None,
|
"""醒目留言ID,删除时用"""
|
||||||
guard_level: int = None,
|
gift_id: int = None
|
||||||
user_level: int = None,
|
"""礼物ID"""
|
||||||
background_bottom_color: str = None,
|
gift_name: str = None
|
||||||
background_color: str = None,
|
"""礼物名"""
|
||||||
background_icon: str = None,
|
uid: int = None
|
||||||
background_image: str = None,
|
"""用户ID"""
|
||||||
background_price_color: str = None,
|
uname: str = None
|
||||||
):
|
"""用户名"""
|
||||||
self.price: int = price
|
face: str = None
|
||||||
self.message: str = message
|
"""用户头像URL"""
|
||||||
self.message_trans: str = message_trans
|
guard_level: int = None
|
||||||
self.start_time: int = start_time
|
"""舰队等级,0非舰队,1总督,2提督,3舰长"""
|
||||||
self.end_time: int = end_time
|
user_level: int = None
|
||||||
self.time: int = time
|
"""用户等级"""
|
||||||
self.id: int = id_
|
background_bottom_color: str = None
|
||||||
self.gift_id: int = gift_id
|
"""底部背景色,'#rrggbb'"""
|
||||||
self.gift_name: str = gift_name
|
background_color: str = None
|
||||||
self.uid: int = uid
|
"""背景色,'#rrggbb'"""
|
||||||
self.uname: str = uname
|
background_icon: str = None
|
||||||
self.face: str = face
|
"""背景图标"""
|
||||||
self.guard_level: int = guard_level
|
background_image: str = None
|
||||||
self.user_level: int = user_level
|
"""背景图URL"""
|
||||||
self.background_bottom_color: str = background_bottom_color
|
background_price_color: str = None
|
||||||
self.background_color: str = background_color
|
"""背景价格颜色,'#rrggbb'"""
|
||||||
self.background_icon: str = background_icon
|
|
||||||
self.background_image: str = background_image
|
|
||||||
self.background_price_color: str = background_price_color
|
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def from_command(cls, data: dict):
|
def from_command(cls, data: dict):
|
||||||
@ -454,7 +351,7 @@ class SuperChatMessage:
|
|||||||
start_time=data['start_time'],
|
start_time=data['start_time'],
|
||||||
end_time=data['end_time'],
|
end_time=data['end_time'],
|
||||||
time=data['time'],
|
time=data['time'],
|
||||||
id_=data['id'],
|
id=data['id'],
|
||||||
gift_id=data['gift']['gift_id'],
|
gift_id=data['gift']['gift_id'],
|
||||||
gift_name=data['gift']['gift_name'],
|
gift_name=data['gift']['gift_name'],
|
||||||
uid=data['uid'],
|
uid=data['uid'],
|
||||||
@ -470,18 +367,14 @@ class SuperChatMessage:
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@dataclasses.dataclass
|
||||||
class SuperChatDeleteMessage:
|
class SuperChatDeleteMessage:
|
||||||
"""
|
"""
|
||||||
删除醒目留言消息
|
删除醒目留言消息
|
||||||
|
|
||||||
:param ids: 醒目留言ID数组
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(
|
ids: List[int] = None
|
||||||
self,
|
"""醒目留言ID数组"""
|
||||||
ids: List[int] = None,
|
|
||||||
):
|
|
||||||
self.ids: List[int] = ids
|
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def from_command(cls, data: dict):
|
def from_command(cls, data: dict):
|
||||||
|
Loading…
Reference in New Issue
Block a user