mirror of
https://github.com/xfgryujk/blivedm.git
synced 2025-01-28 05:10:11 +08:00
拆出模型模块
This commit is contained in:
parent
0404f97134
commit
104a080167
@ -1,3 +1,3 @@
|
|||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
from .blivedm import *
|
from .blivedm import *
|
||||||
|
from .models import *
|
||||||
|
@ -1,17 +1,18 @@
|
|||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
import asyncio
|
import asyncio
|
||||||
|
import collections
|
||||||
|
import enum
|
||||||
import json
|
import json
|
||||||
import logging
|
import logging
|
||||||
import ssl as ssl_
|
import ssl as ssl_
|
||||||
import struct
|
import struct
|
||||||
import zlib
|
import zlib
|
||||||
from collections import namedtuple
|
|
||||||
from enum import IntEnum
|
|
||||||
from typing import *
|
from typing import *
|
||||||
|
|
||||||
import aiohttp
|
import aiohttp
|
||||||
|
|
||||||
|
from . import models
|
||||||
|
|
||||||
logger = logging.getLogger('blivedm')
|
logger = logging.getLogger('blivedm')
|
||||||
|
|
||||||
ROOM_INIT_URL = 'https://api.live.bilibili.com/xlive/web-room/v1/index/getInfoByRoom'
|
ROOM_INIT_URL = 'https://api.live.bilibili.com/xlive/web-room/v1/index/getInfoByRoom'
|
||||||
@ -21,14 +22,14 @@ DEFAULT_DANMAKU_SERVER_LIST = [
|
|||||||
]
|
]
|
||||||
|
|
||||||
HEADER_STRUCT = struct.Struct('>I2H2I')
|
HEADER_STRUCT = struct.Struct('>I2H2I')
|
||||||
HeaderTuple = namedtuple('HeaderTuple', ('pack_len', 'raw_header_size', 'ver', 'operation', 'seq_id'))
|
HeaderTuple = collections.namedtuple('HeaderTuple', ('pack_len', 'raw_header_size', 'ver', 'operation', 'seq_id'))
|
||||||
WS_BODY_PROTOCOL_VERSION_INFLATE = 0
|
WS_BODY_PROTOCOL_VERSION_INFLATE = 0
|
||||||
WS_BODY_PROTOCOL_VERSION_NORMAL = 1
|
WS_BODY_PROTOCOL_VERSION_NORMAL = 1
|
||||||
WS_BODY_PROTOCOL_VERSION_DEFLATE = 2
|
WS_BODY_PROTOCOL_VERSION_DEFLATE = 2
|
||||||
|
|
||||||
|
|
||||||
# go-common\app\service\main\broadcast\model\operation.go
|
# go-common\app\service\main\broadcast\model\operation.go
|
||||||
class Operation(IntEnum):
|
class Operation(enum.IntEnum):
|
||||||
HANDSHAKE = 0
|
HANDSHAKE = 0
|
||||||
HANDSHAKE_REPLY = 1
|
HANDSHAKE_REPLY = 1
|
||||||
HEARTBEAT = 2
|
HEARTBEAT = 2
|
||||||
@ -56,270 +57,28 @@ class InitError(Exception):
|
|||||||
"""初始化失败"""
|
"""初始化失败"""
|
||||||
|
|
||||||
|
|
||||||
class DanmakuMessage:
|
|
||||||
def __init__(self, mode, font_size, color, timestamp, rnd, uid_crc32, msg_type, bubble,
|
|
||||||
msg,
|
|
||||||
uid, uname, admin, vip, svip, urank, mobile_verify, uname_color,
|
|
||||||
medal_level, medal_name, runame, room_id, mcolor, special_medal,
|
|
||||||
user_level, ulevel_color, ulevel_rank,
|
|
||||||
old_title, title,
|
|
||||||
privilege_type):
|
|
||||||
"""
|
|
||||||
:param mode: 弹幕显示模式(滚动、顶部、底部)
|
|
||||||
:param font_size: 字体尺寸
|
|
||||||
:param color: 颜色
|
|
||||||
:param timestamp: 时间戳
|
|
||||||
:param rnd: 随机数
|
|
||||||
:param uid_crc32: 用户ID文本的CRC32
|
|
||||||
:param msg_type: 是否礼物弹幕(节奏风暴)
|
|
||||||
:param bubble: 右侧评论栏气泡
|
|
||||||
|
|
||||||
: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 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舰长
|
|
||||||
"""
|
|
||||||
self.mode = mode
|
|
||||||
self.font_size = font_size
|
|
||||||
self.color = color
|
|
||||||
self.timestamp = timestamp
|
|
||||||
self.rnd = rnd
|
|
||||||
self.uid_crc32 = uid_crc32
|
|
||||||
self.msg_type = msg_type
|
|
||||||
self.bubble = bubble
|
|
||||||
|
|
||||||
self.msg = msg
|
|
||||||
|
|
||||||
self.uid = uid
|
|
||||||
self.uname = uname
|
|
||||||
self.admin = admin
|
|
||||||
self.vip = vip
|
|
||||||
self.svip = svip
|
|
||||||
self.urank = urank
|
|
||||||
self.mobile_verify = mobile_verify
|
|
||||||
self.uname_color = uname_color
|
|
||||||
|
|
||||||
self.medal_level = medal_level
|
|
||||||
self.medal_name = medal_name
|
|
||||||
self.runame = runame
|
|
||||||
self.room_id = room_id
|
|
||||||
self.mcolor = mcolor
|
|
||||||
self.special_medal = special_medal
|
|
||||||
|
|
||||||
self.user_level = user_level
|
|
||||||
self.ulevel_color = ulevel_color
|
|
||||||
self.ulevel_rank = ulevel_rank
|
|
||||||
|
|
||||||
self.old_title = old_title
|
|
||||||
self.title = title
|
|
||||||
|
|
||||||
self.privilege_type = privilege_type
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def from_command(cls, info: dict):
|
|
||||||
return cls(
|
|
||||||
info[0][1], info[0][2], info[0][3], info[0][4], info[0][5], info[0][7], info[0][9], info[0][10],
|
|
||||||
info[1],
|
|
||||||
*info[2][:8],
|
|
||||||
*(info[3][:6] or (0, '', '', 0, 0, 0)),
|
|
||||||
info[4][0], info[4][2], info[4][3],
|
|
||||||
*info[5][:2],
|
|
||||||
info[7]
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
class GiftMessage:
|
|
||||||
def __init__(self, gift_name, num, uname, face, guard_level, uid, timestamp, gift_id,
|
|
||||||
gift_type, action, price, rnd, coin_type, total_coin):
|
|
||||||
"""
|
|
||||||
: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: 随机数
|
|
||||||
:param coin_type: 瓜子类型,'silver'或'gold'
|
|
||||||
:param total_coin: 总瓜子数
|
|
||||||
"""
|
|
||||||
self.gift_name = gift_name
|
|
||||||
self.num = num
|
|
||||||
self.uname = uname
|
|
||||||
self.face = face
|
|
||||||
self.guard_level = guard_level
|
|
||||||
self.uid = uid
|
|
||||||
self.timestamp = timestamp
|
|
||||||
self.gift_id = gift_id
|
|
||||||
self.gift_type = gift_type
|
|
||||||
self.action = action
|
|
||||||
self.price = price
|
|
||||||
self.rnd = rnd
|
|
||||||
self.coin_type = coin_type
|
|
||||||
self.total_coin = total_coin
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def from_command(cls, data: dict):
|
|
||||||
return cls(
|
|
||||||
data['giftName'], data['num'], data['uname'], data['face'], data['guard_level'],
|
|
||||||
data['uid'], data['timestamp'], data['giftId'], data['giftType'],
|
|
||||||
data['action'], data['price'], data['rnd'], data['coin_type'], data['total_coin']
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
class GuardBuyMessage:
|
|
||||||
def __init__(self, uid, username, guard_level, num, price, gift_id, gift_name,
|
|
||||||
start_time, end_time):
|
|
||||||
"""
|
|
||||||
: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: 结束时间戳?
|
|
||||||
"""
|
|
||||||
self.uid = uid
|
|
||||||
self.username = username
|
|
||||||
self.guard_level = guard_level
|
|
||||||
self.num = num
|
|
||||||
self.price = price
|
|
||||||
self.gift_id = gift_id
|
|
||||||
self.gift_name = gift_name
|
|
||||||
self.start_time = start_time
|
|
||||||
self.end_time = end_time
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def from_command(cls, data: dict):
|
|
||||||
return cls(
|
|
||||||
data['uid'], data['username'], data['guard_level'], data['num'], data['price'],
|
|
||||||
data['gift_id'], data['gift_name'], data['start_time'], data['end_time']
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
class SuperChatMessage:
|
|
||||||
def __init__(self, price, message, message_jpn, start_time, end_time, time, id_,
|
|
||||||
gift_id, gift_name, uid, uname, face, guard_level, user_level,
|
|
||||||
background_bottom_color, background_color, background_icon, background_image,
|
|
||||||
background_price_color):
|
|
||||||
"""
|
|
||||||
:param price: 价格(人民币)
|
|
||||||
:param message: 消息
|
|
||||||
:param message_jpn: 消息日文翻译(目前只出现在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: 底部背景色
|
|
||||||
:param background_color: 背景色
|
|
||||||
:param background_icon: 背景图标
|
|
||||||
:param background_image: 背景图
|
|
||||||
:param background_price_color: 背景价格颜色
|
|
||||||
"""
|
|
||||||
self.price = price
|
|
||||||
self.message = message
|
|
||||||
self.message_jpn = message_jpn
|
|
||||||
self.start_time = start_time
|
|
||||||
self.end_time = end_time
|
|
||||||
self.time = time
|
|
||||||
self.id = id_
|
|
||||||
self.gift_id = gift_id
|
|
||||||
self.gift_name = gift_name
|
|
||||||
self.uid = uid
|
|
||||||
self.uname = uname
|
|
||||||
self.face = face
|
|
||||||
self.guard_level = guard_level
|
|
||||||
self.user_level = user_level
|
|
||||||
self.background_bottom_color = background_bottom_color
|
|
||||||
self.background_color = background_color
|
|
||||||
self.background_icon = background_icon
|
|
||||||
self.background_image = background_image
|
|
||||||
self.background_price_color = background_price_color
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def from_command(cls, data: dict):
|
|
||||||
return cls(
|
|
||||||
data['price'], data['message'], data['message_trans'], data['start_time'],
|
|
||||||
data['end_time'], data['time'], data['id'], data['gift']['gift_id'],
|
|
||||||
data['gift']['gift_name'], data['uid'], data['user_info']['uname'],
|
|
||||||
data['user_info']['face'], data['user_info']['guard_level'],
|
|
||||||
data['user_info']['user_level'], data['background_bottom_color'],
|
|
||||||
data['background_color'], data['background_icon'], data['background_image'],
|
|
||||||
data['background_price_color']
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
class SuperChatDeleteMessage:
|
|
||||||
def __init__(self, ids):
|
|
||||||
"""
|
|
||||||
:param ids: 消息ID数组
|
|
||||||
"""
|
|
||||||
self.ids = ids
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def from_command(cls, data: dict):
|
|
||||||
return cls(
|
|
||||||
data['ids']
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
class BLiveClient:
|
class BLiveClient:
|
||||||
_COMMAND_HANDLERS: Dict[str, Optional[Callable[['BLiveClient', dict], Awaitable]]] = {
|
_COMMAND_HANDLERS: Dict[str, Optional[Callable[['BLiveClient', dict], Awaitable]]] = {
|
||||||
# 收到弹幕
|
# 收到弹幕
|
||||||
# go-common\app\service\live\live-dm\service\v1\send.go
|
# go-common\app\service\live\live-dm\service\v1\send.go
|
||||||
'DANMU_MSG': lambda client, command: client._on_receive_danmaku(
|
'DANMU_MSG': lambda client, command: client._on_receive_danmaku( # noqa
|
||||||
DanmakuMessage.from_command(command['info'])
|
models.DanmakuMessage.from_command(command['info'])
|
||||||
),
|
),
|
||||||
# 有人送礼
|
# 有人送礼
|
||||||
'SEND_GIFT': lambda client, command: client._on_receive_gift(
|
'SEND_GIFT': lambda client, command: client._on_receive_gift( # noqa
|
||||||
GiftMessage.from_command(command['data'])
|
models.GiftMessage.from_command(command['data'])
|
||||||
),
|
),
|
||||||
# 有人上舰
|
# 有人上舰
|
||||||
'GUARD_BUY': lambda client, command: client._on_buy_guard(
|
'GUARD_BUY': lambda client, command: client._on_buy_guard( # noqa
|
||||||
GuardBuyMessage.from_command(command['data'])
|
models.GuardBuyMessage.from_command(command['data'])
|
||||||
),
|
),
|
||||||
# 醒目留言
|
# 醒目留言
|
||||||
'SUPER_CHAT_MESSAGE': lambda client, command: client._on_super_chat(
|
'SUPER_CHAT_MESSAGE': lambda client, command: client._on_super_chat( # noqa
|
||||||
SuperChatMessage.from_command(command['data'])
|
models.SuperChatMessage.from_command(command['data'])
|
||||||
),
|
),
|
||||||
# 删除醒目留言
|
# 删除醒目留言
|
||||||
'SUPER_CHAT_MESSAGE_DELETE': lambda client, command: client._on_super_chat_delete(
|
'SUPER_CHAT_MESSAGE_DELETE': lambda client, command: client._on_super_chat_delete( # noqa
|
||||||
SuperChatDeleteMessage.from_command(command['data'])
|
models.SuperChatDeleteMessage.from_command(command['data'])
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
# 其他常见命令
|
# 其他常见命令
|
||||||
@ -332,7 +91,7 @@ class BLiveClient:
|
|||||||
_COMMAND_HANDLERS[cmd] = None
|
_COMMAND_HANDLERS[cmd] = None
|
||||||
del cmd
|
del cmd
|
||||||
|
|
||||||
def __init__(self, room_id, uid=0, session: aiohttp.ClientSession=None,
|
def __init__(self, room_id, uid=0, session: aiohttp.ClientSession = None,
|
||||||
heartbeat_interval=30, ssl=True, loop=None):
|
heartbeat_interval=30, ssl=True, loop=None):
|
||||||
"""
|
"""
|
||||||
:param room_id: URL中的房间ID,可以为短ID
|
:param room_id: URL中的房间ID,可以为短ID
|
||||||
@ -354,8 +113,7 @@ class BLiveClient:
|
|||||||
if loop is not None:
|
if loop is not None:
|
||||||
self._loop = loop
|
self._loop = loop
|
||||||
elif session is not None:
|
elif session is not None:
|
||||||
# noinspection PyDeprecation
|
self._loop = session.loop # noqa
|
||||||
self._loop = session.loop
|
|
||||||
else:
|
else:
|
||||||
self._loop = asyncio.get_event_loop()
|
self._loop = asyncio.get_event_loop()
|
||||||
self._future = None
|
self._future = None
|
||||||
@ -366,13 +124,11 @@ class BLiveClient:
|
|||||||
else:
|
else:
|
||||||
self._session = session
|
self._session = session
|
||||||
self._own_session = False
|
self._own_session = False
|
||||||
# noinspection PyDeprecation
|
if self._session.loop is not self._loop: # noqa
|
||||||
if self._session.loop is not self._loop:
|
|
||||||
raise RuntimeError('BLiveClient and session has to use same event loop')
|
raise RuntimeError('BLiveClient and session has to use same event loop')
|
||||||
|
|
||||||
self._heartbeat_interval = heartbeat_interval
|
self._heartbeat_interval = heartbeat_interval
|
||||||
# noinspection PyProtectedMember
|
self._ssl = ssl if ssl else ssl_._create_unverified_context() # noqa
|
||||||
self._ssl = ssl if ssl else ssl_._create_unverified_context()
|
|
||||||
self._websocket = None
|
self._websocket = None
|
||||||
self._heartbeat_timer_handle = None
|
self._heartbeat_timer_handle = None
|
||||||
|
|
||||||
@ -556,7 +312,8 @@ class BLiveClient:
|
|||||||
)
|
)
|
||||||
|
|
||||||
# 处理消息
|
# 处理消息
|
||||||
async for message in websocket: # type: aiohttp.WSMessage
|
message: aiohttp.WSMessage
|
||||||
|
async for message in websocket:
|
||||||
retry_count = 0
|
retry_count = 0
|
||||||
if message.type != aiohttp.WSMsgType.BINARY:
|
if message.type != aiohttp.WSMsgType.BINARY:
|
||||||
logger.warning('room %d 未知的websocket消息:type=%s %s', self.room_id,
|
logger.warning('room %d 未知的websocket消息:type=%s %s', self.room_id,
|
||||||
@ -567,7 +324,7 @@ class BLiveClient:
|
|||||||
await self._handle_message(message.data)
|
await self._handle_message(message.data)
|
||||||
except asyncio.CancelledError:
|
except asyncio.CancelledError:
|
||||||
raise
|
raise
|
||||||
except Exception:
|
except Exception: # noqa
|
||||||
logger.exception('room %d 处理消息时发生错误:', self.room_id)
|
logger.exception('room %d 处理消息时发生错误:', self.room_id)
|
||||||
|
|
||||||
except asyncio.CancelledError:
|
except asyncio.CancelledError:
|
||||||
@ -659,31 +416,31 @@ class BLiveClient:
|
|||||||
"""
|
"""
|
||||||
pass
|
pass
|
||||||
|
|
||||||
async def _on_receive_danmaku(self, danmaku: DanmakuMessage):
|
async def _on_receive_danmaku(self, danmaku: models.DanmakuMessage):
|
||||||
"""
|
"""
|
||||||
收到弹幕
|
收到弹幕
|
||||||
"""
|
"""
|
||||||
pass
|
pass
|
||||||
|
|
||||||
async def _on_receive_gift(self, gift: GiftMessage):
|
async def _on_receive_gift(self, gift: models.GiftMessage):
|
||||||
"""
|
"""
|
||||||
收到礼物
|
收到礼物
|
||||||
"""
|
"""
|
||||||
pass
|
pass
|
||||||
|
|
||||||
async def _on_buy_guard(self, message: GuardBuyMessage):
|
async def _on_buy_guard(self, message: models.GuardBuyMessage):
|
||||||
"""
|
"""
|
||||||
有人上舰
|
有人上舰
|
||||||
"""
|
"""
|
||||||
pass
|
pass
|
||||||
|
|
||||||
async def _on_super_chat(self, message: SuperChatMessage):
|
async def _on_super_chat(self, message: models.SuperChatMessage):
|
||||||
"""
|
"""
|
||||||
醒目留言
|
醒目留言
|
||||||
"""
|
"""
|
||||||
pass
|
pass
|
||||||
|
|
||||||
async def _on_super_chat_delete(self, message: SuperChatDeleteMessage):
|
async def _on_super_chat_delete(self, message: models.SuperChatDeleteMessage):
|
||||||
"""
|
"""
|
||||||
删除醒目留言
|
删除醒目留言
|
||||||
"""
|
"""
|
||||||
|
417
blivedm/models.py
Normal file
417
blivedm/models.py
Normal file
@ -0,0 +1,417 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
from typing import *
|
||||||
|
|
||||||
|
__all__ = (
|
||||||
|
'DanmakuMessage',
|
||||||
|
'GiftMessage',
|
||||||
|
'GuardBuyMessage',
|
||||||
|
'SuperChatMessage',
|
||||||
|
'SuperChatDeleteMessage',
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class DanmakuMessage:
|
||||||
|
"""
|
||||||
|
弹幕消息
|
||||||
|
|
||||||
|
:param mode: 弹幕显示模式(滚动、顶部、底部)
|
||||||
|
:param font_size: 字体尺寸
|
||||||
|
:param color: 颜色
|
||||||
|
:param timestamp: 时间戳(毫秒)
|
||||||
|
:param rnd: 随机数
|
||||||
|
:param uid_crc32: 用户ID文本的CRC32
|
||||||
|
:param msg_type: 是否礼物弹幕(节奏风暴)
|
||||||
|
:param bubble: 右侧评论栏气泡
|
||||||
|
|
||||||
|
: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__(
|
||||||
|
self,
|
||||||
|
mode: int = None,
|
||||||
|
font_size: int = None,
|
||||||
|
color: int = None,
|
||||||
|
timestamp: int = None,
|
||||||
|
rnd: int = None,
|
||||||
|
uid_crc32: str = None,
|
||||||
|
msg_type: int = None,
|
||||||
|
bubble: int = None,
|
||||||
|
|
||||||
|
msg: str = None,
|
||||||
|
|
||||||
|
uid: int = None,
|
||||||
|
uname: str = None,
|
||||||
|
admin: int = None,
|
||||||
|
vip: int = None,
|
||||||
|
svip: int = None,
|
||||||
|
urank: int = None,
|
||||||
|
mobile_verify: int = None,
|
||||||
|
uname_color: str = None,
|
||||||
|
|
||||||
|
medal_level: str = None,
|
||||||
|
medal_name: str = None,
|
||||||
|
runame: str = None,
|
||||||
|
medal_room_id: int = None,
|
||||||
|
mcolor: int = None,
|
||||||
|
special_medal: str = None,
|
||||||
|
|
||||||
|
user_level: int = None,
|
||||||
|
ulevel_color: int = None,
|
||||||
|
ulevel_rank: str = None,
|
||||||
|
|
||||||
|
old_title: str = None,
|
||||||
|
title: str = None,
|
||||||
|
|
||||||
|
privilege_type: int = None,
|
||||||
|
):
|
||||||
|
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.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
|
||||||
|
def from_command(cls, info: dict):
|
||||||
|
if len(info[3]) != 0:
|
||||||
|
medal_level = info[3][0]
|
||||||
|
medal_name = info[3][1]
|
||||||
|
runame = info[3][2]
|
||||||
|
room_id = info[3][3]
|
||||||
|
mcolor = info[3][4]
|
||||||
|
special_medal = info[3][5]
|
||||||
|
else:
|
||||||
|
medal_level = 0
|
||||||
|
medal_name = ''
|
||||||
|
runame = ''
|
||||||
|
room_id = 0
|
||||||
|
mcolor = 0
|
||||||
|
special_medal = 0
|
||||||
|
|
||||||
|
return cls(
|
||||||
|
mode=info[0][1],
|
||||||
|
font_size=info[0][2],
|
||||||
|
color=info[0][3],
|
||||||
|
timestamp=info[0][4],
|
||||||
|
rnd=info[0][5],
|
||||||
|
uid_crc32=info[0][7],
|
||||||
|
msg_type=info[0][9],
|
||||||
|
bubble=info[0][10],
|
||||||
|
|
||||||
|
msg=info[1],
|
||||||
|
|
||||||
|
uid=info[2][0],
|
||||||
|
uname=info[2][1],
|
||||||
|
admin=info[2][2],
|
||||||
|
vip=info[2][3],
|
||||||
|
svip=info[2][4],
|
||||||
|
urank=info[2][5],
|
||||||
|
mobile_verify=info[2][6],
|
||||||
|
uname_color=info[2][7],
|
||||||
|
|
||||||
|
medal_level=medal_level,
|
||||||
|
medal_name=medal_name,
|
||||||
|
runame=runame,
|
||||||
|
medal_room_id=room_id,
|
||||||
|
mcolor=mcolor,
|
||||||
|
special_medal=special_medal,
|
||||||
|
|
||||||
|
user_level=info[4][0],
|
||||||
|
ulevel_color=info[4][2],
|
||||||
|
ulevel_rank=info[4][3],
|
||||||
|
|
||||||
|
old_title=info[5][0],
|
||||||
|
title=info[5][1],
|
||||||
|
|
||||||
|
privilege_type=info[7],
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
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: 随机数,估计是去重用的
|
||||||
|
:param coin_type: 瓜子类型,'silver'或'gold'
|
||||||
|
:param total_coin: 总瓜子数
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(
|
||||||
|
self,
|
||||||
|
gift_name: str = None,
|
||||||
|
num: int = None,
|
||||||
|
uname: str = None,
|
||||||
|
face: str = None,
|
||||||
|
guard_level: int = None,
|
||||||
|
uid: int = None,
|
||||||
|
timestamp: int = None,
|
||||||
|
gift_id: int = None,
|
||||||
|
gift_type: int = None,
|
||||||
|
action: str = None,
|
||||||
|
price: int = None,
|
||||||
|
rnd: str = None,
|
||||||
|
coin_type: str = None,
|
||||||
|
total_coin: int = None,
|
||||||
|
):
|
||||||
|
self.gift_name = gift_name
|
||||||
|
self.num = num
|
||||||
|
self.uname = uname
|
||||||
|
self.face = face
|
||||||
|
self.guard_level = guard_level
|
||||||
|
self.uid = uid
|
||||||
|
self.timestamp = timestamp
|
||||||
|
self.gift_id = gift_id
|
||||||
|
self.gift_type = gift_type
|
||||||
|
self.action = action
|
||||||
|
self.price = price
|
||||||
|
self.rnd = rnd
|
||||||
|
self.coin_type = coin_type
|
||||||
|
self.total_coin = total_coin
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def from_command(cls, data: dict):
|
||||||
|
return cls(
|
||||||
|
gift_name=data['giftName'],
|
||||||
|
num=data['num'],
|
||||||
|
uname=data['uname'],
|
||||||
|
face=data['face'],
|
||||||
|
guard_level=data['guard_level'],
|
||||||
|
uid=data['uid'],
|
||||||
|
timestamp=data['timestamp'],
|
||||||
|
gift_id=data['giftId'],
|
||||||
|
gift_type=data['giftType'],
|
||||||
|
action=data['action'],
|
||||||
|
price=data['price'],
|
||||||
|
rnd=data['rnd'],
|
||||||
|
coin_type=data['coin_type'],
|
||||||
|
total_coin=data['total_coin'],
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
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__(
|
||||||
|
self,
|
||||||
|
uid: int = None,
|
||||||
|
username: str = None,
|
||||||
|
guard_level: int = None,
|
||||||
|
num: int = None,
|
||||||
|
price: int = None,
|
||||||
|
gift_id: int = None,
|
||||||
|
gift_name: str = None,
|
||||||
|
start_time: int = None,
|
||||||
|
end_time: int = None,
|
||||||
|
):
|
||||||
|
self.uid: int = uid
|
||||||
|
self.username: str = username
|
||||||
|
self.guard_level: int = guard_level
|
||||||
|
self.num: int = num
|
||||||
|
self.price: int = price
|
||||||
|
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
|
||||||
|
def from_command(cls, data: dict):
|
||||||
|
return cls(
|
||||||
|
uid=data['uid'],
|
||||||
|
username=data['username'],
|
||||||
|
guard_level=data['guard_level'],
|
||||||
|
num=data['num'],
|
||||||
|
price=data['price'],
|
||||||
|
gift_id=data['gift_id'],
|
||||||
|
gift_name=data['gift_name'],
|
||||||
|
start_time=data['start_time'],
|
||||||
|
end_time=data['end_time'],
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class SuperChatMessage:
|
||||||
|
"""
|
||||||
|
醒目留言消息
|
||||||
|
|
||||||
|
:param price: 价格(人民币)
|
||||||
|
:param message: 消息
|
||||||
|
:param message_jpn: 消息日文翻译(目前只出现在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__(
|
||||||
|
self,
|
||||||
|
price: int = None,
|
||||||
|
message: str = None,
|
||||||
|
message_jpn: str = None,
|
||||||
|
start_time: int = None,
|
||||||
|
end_time: int = None,
|
||||||
|
time: int = None,
|
||||||
|
id_: int = None,
|
||||||
|
gift_id: int = None,
|
||||||
|
gift_name: str = None,
|
||||||
|
uid: int = None,
|
||||||
|
uname: str = None,
|
||||||
|
face: str = None,
|
||||||
|
guard_level: int = None,
|
||||||
|
user_level: int = None,
|
||||||
|
background_bottom_color: str = None,
|
||||||
|
background_color: str = None,
|
||||||
|
background_icon: str = None,
|
||||||
|
background_image: str = None,
|
||||||
|
background_price_color: str = None,
|
||||||
|
):
|
||||||
|
self.price: int = price
|
||||||
|
self.message: str = message
|
||||||
|
self.message_jpn: str = message_jpn
|
||||||
|
self.start_time: int = start_time
|
||||||
|
self.end_time: int = end_time
|
||||||
|
self.time: int = time
|
||||||
|
self.id: int = id_
|
||||||
|
self.gift_id: int = gift_id
|
||||||
|
self.gift_name: str = gift_name
|
||||||
|
self.uid: int = uid
|
||||||
|
self.uname: str = uname
|
||||||
|
self.face: str = face
|
||||||
|
self.guard_level: int = guard_level
|
||||||
|
self.user_level: int = user_level
|
||||||
|
self.background_bottom_color: str = background_bottom_color
|
||||||
|
self.background_color: str = background_color
|
||||||
|
self.background_icon: str = background_icon
|
||||||
|
self.background_image: str = background_image
|
||||||
|
self.background_price_color: str = background_price_color
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def from_command(cls, data: dict):
|
||||||
|
return cls(
|
||||||
|
price=data['price'],
|
||||||
|
message=data['message'],
|
||||||
|
message_jpn=data['message_trans'],
|
||||||
|
start_time=data['start_time'],
|
||||||
|
end_time=data['end_time'],
|
||||||
|
time=data['time'],
|
||||||
|
id_=data['id'],
|
||||||
|
gift_id=data['gift']['gift_id'],
|
||||||
|
gift_name=data['gift']['gift_name'],
|
||||||
|
uid=data['uid'],
|
||||||
|
uname=data['user_info']['uname'],
|
||||||
|
face=data['user_info']['face'],
|
||||||
|
guard_level=data['user_info']['guard_level'],
|
||||||
|
user_level=data['user_info']['user_level'],
|
||||||
|
background_bottom_color=data['background_bottom_color'],
|
||||||
|
background_color=data['background_color'],
|
||||||
|
background_icon=data['background_icon'],
|
||||||
|
background_image=data['background_image'],
|
||||||
|
background_price_color=data['background_price_color'],
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class SuperChatDeleteMessage:
|
||||||
|
"""
|
||||||
|
删除醒目留言消息
|
||||||
|
|
||||||
|
:param ids: 醒目留言ID数组
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(
|
||||||
|
self,
|
||||||
|
ids: List[int] = None,
|
||||||
|
):
|
||||||
|
self.ids: List[int] = ids
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def from_command(cls, data: dict):
|
||||||
|
return cls(
|
||||||
|
ids=data['ids'],
|
||||||
|
)
|
31
sample.py
31
sample.py
@ -1,10 +1,24 @@
|
|||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
import asyncio
|
import asyncio
|
||||||
|
|
||||||
import blivedm
|
import blivedm
|
||||||
|
|
||||||
|
|
||||||
|
async def main():
|
||||||
|
# 直播间ID的取值看直播间URL
|
||||||
|
# 如果SSL验证失败就把ssl设为False,B站真的有过忘续证书的情况
|
||||||
|
client = MyBLiveClient(room_id=21224291, ssl=True)
|
||||||
|
future = client.start()
|
||||||
|
try:
|
||||||
|
# 5秒后停止,测试用
|
||||||
|
# await asyncio.sleep(5)
|
||||||
|
# future = client.stop()
|
||||||
|
|
||||||
|
await future
|
||||||
|
finally:
|
||||||
|
await client.close()
|
||||||
|
|
||||||
|
|
||||||
class MyBLiveClient(blivedm.BLiveClient):
|
class MyBLiveClient(blivedm.BLiveClient):
|
||||||
# 演示如何自定义handler
|
# 演示如何自定义handler
|
||||||
_COMMAND_HANDLERS = blivedm.BLiveClient._COMMAND_HANDLERS.copy()
|
_COMMAND_HANDLERS = blivedm.BLiveClient._COMMAND_HANDLERS.copy()
|
||||||
@ -29,20 +43,5 @@ class MyBLiveClient(blivedm.BLiveClient):
|
|||||||
print(f'醒目留言 ¥{message.price} {message.uname}:{message.message}')
|
print(f'醒目留言 ¥{message.price} {message.uname}:{message.message}')
|
||||||
|
|
||||||
|
|
||||||
async def main():
|
|
||||||
# 直播间ID的取值看直播间URL
|
|
||||||
# 如果SSL验证失败就把ssl设为False,B站真的有过忘续证书的情况
|
|
||||||
client = MyBLiveClient(room_id=21449083, ssl=True)
|
|
||||||
future = client.start()
|
|
||||||
try:
|
|
||||||
# 5秒后停止,测试用
|
|
||||||
# await asyncio.sleep(5)
|
|
||||||
# future = client.stop()
|
|
||||||
|
|
||||||
await future
|
|
||||||
finally:
|
|
||||||
await client.close()
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
asyncio.get_event_loop().run_until_complete(main())
|
asyncio.get_event_loop().run_until_complete(main())
|
||||||
|
Loading…
Reference in New Issue
Block a user