mirror of
https://github.com/xfgryujk/blivedm.git
synced 2025-01-13 13:50:25 +08:00
拆出模型模块
This commit is contained in:
parent
0404f97134
commit
104a080167
@ -1,3 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
from .blivedm import *
|
||||
from .models import *
|
||||
|
@ -1,17 +1,18 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
import asyncio
|
||||
import collections
|
||||
import enum
|
||||
import json
|
||||
import logging
|
||||
import ssl as ssl_
|
||||
import struct
|
||||
import zlib
|
||||
from collections import namedtuple
|
||||
from enum import IntEnum
|
||||
from typing import *
|
||||
|
||||
import aiohttp
|
||||
|
||||
from . import models
|
||||
|
||||
logger = logging.getLogger('blivedm')
|
||||
|
||||
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')
|
||||
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_NORMAL = 1
|
||||
WS_BODY_PROTOCOL_VERSION_DEFLATE = 2
|
||||
|
||||
|
||||
# go-common\app\service\main\broadcast\model\operation.go
|
||||
class Operation(IntEnum):
|
||||
class Operation(enum.IntEnum):
|
||||
HANDSHAKE = 0
|
||||
HANDSHAKE_REPLY = 1
|
||||
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:
|
||||
_COMMAND_HANDLERS: Dict[str, Optional[Callable[['BLiveClient', dict], Awaitable]]] = {
|
||||
# 收到弹幕
|
||||
# go-common\app\service\live\live-dm\service\v1\send.go
|
||||
'DANMU_MSG': lambda client, command: client._on_receive_danmaku(
|
||||
DanmakuMessage.from_command(command['info'])
|
||||
'DANMU_MSG': lambda client, command: client._on_receive_danmaku( # noqa
|
||||
models.DanmakuMessage.from_command(command['info'])
|
||||
),
|
||||
# 有人送礼
|
||||
'SEND_GIFT': lambda client, command: client._on_receive_gift(
|
||||
GiftMessage.from_command(command['data'])
|
||||
'SEND_GIFT': lambda client, command: client._on_receive_gift( # noqa
|
||||
models.GiftMessage.from_command(command['data'])
|
||||
),
|
||||
# 有人上舰
|
||||
'GUARD_BUY': lambda client, command: client._on_buy_guard(
|
||||
GuardBuyMessage.from_command(command['data'])
|
||||
'GUARD_BUY': lambda client, command: client._on_buy_guard( # noqa
|
||||
models.GuardBuyMessage.from_command(command['data'])
|
||||
),
|
||||
# 醒目留言
|
||||
'SUPER_CHAT_MESSAGE': lambda client, command: client._on_super_chat(
|
||||
SuperChatMessage.from_command(command['data'])
|
||||
'SUPER_CHAT_MESSAGE': lambda client, command: client._on_super_chat( # noqa
|
||||
models.SuperChatMessage.from_command(command['data'])
|
||||
),
|
||||
# 删除醒目留言
|
||||
'SUPER_CHAT_MESSAGE_DELETE': lambda client, command: client._on_super_chat_delete(
|
||||
SuperChatDeleteMessage.from_command(command['data'])
|
||||
'SUPER_CHAT_MESSAGE_DELETE': lambda client, command: client._on_super_chat_delete( # noqa
|
||||
models.SuperChatDeleteMessage.from_command(command['data'])
|
||||
)
|
||||
}
|
||||
# 其他常见命令
|
||||
@ -332,7 +91,7 @@ class BLiveClient:
|
||||
_COMMAND_HANDLERS[cmd] = None
|
||||
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):
|
||||
"""
|
||||
:param room_id: URL中的房间ID,可以为短ID
|
||||
@ -354,8 +113,7 @@ class BLiveClient:
|
||||
if loop is not None:
|
||||
self._loop = loop
|
||||
elif session is not None:
|
||||
# noinspection PyDeprecation
|
||||
self._loop = session.loop
|
||||
self._loop = session.loop # noqa
|
||||
else:
|
||||
self._loop = asyncio.get_event_loop()
|
||||
self._future = None
|
||||
@ -366,13 +124,11 @@ class BLiveClient:
|
||||
else:
|
||||
self._session = session
|
||||
self._own_session = False
|
||||
# noinspection PyDeprecation
|
||||
if self._session.loop is not self._loop:
|
||||
if self._session.loop is not self._loop: # noqa
|
||||
raise RuntimeError('BLiveClient and session has to use same event loop')
|
||||
|
||||
self._heartbeat_interval = heartbeat_interval
|
||||
# noinspection PyProtectedMember
|
||||
self._ssl = ssl if ssl else ssl_._create_unverified_context()
|
||||
self._ssl = ssl if ssl else ssl_._create_unverified_context() # noqa
|
||||
self._websocket = 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
|
||||
if message.type != aiohttp.WSMsgType.BINARY:
|
||||
logger.warning('room %d 未知的websocket消息:type=%s %s', self.room_id,
|
||||
@ -567,7 +324,7 @@ class BLiveClient:
|
||||
await self._handle_message(message.data)
|
||||
except asyncio.CancelledError:
|
||||
raise
|
||||
except Exception:
|
||||
except Exception: # noqa
|
||||
logger.exception('room %d 处理消息时发生错误:', self.room_id)
|
||||
|
||||
except asyncio.CancelledError:
|
||||
@ -659,31 +416,31 @@ class BLiveClient:
|
||||
"""
|
||||
pass
|
||||
|
||||
async def _on_receive_danmaku(self, danmaku: DanmakuMessage):
|
||||
async def _on_receive_danmaku(self, danmaku: models.DanmakuMessage):
|
||||
"""
|
||||
收到弹幕
|
||||
"""
|
||||
pass
|
||||
|
||||
async def _on_receive_gift(self, gift: GiftMessage):
|
||||
async def _on_receive_gift(self, gift: models.GiftMessage):
|
||||
"""
|
||||
收到礼物
|
||||
"""
|
||||
pass
|
||||
|
||||
async def _on_buy_guard(self, message: GuardBuyMessage):
|
||||
async def _on_buy_guard(self, message: models.GuardBuyMessage):
|
||||
"""
|
||||
有人上舰
|
||||
"""
|
||||
pass
|
||||
|
||||
async def _on_super_chat(self, message: SuperChatMessage):
|
||||
async def _on_super_chat(self, message: models.SuperChatMessage):
|
||||
"""
|
||||
醒目留言
|
||||
"""
|
||||
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 -*-
|
||||
|
||||
import asyncio
|
||||
|
||||
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):
|
||||
# 演示如何自定义handler
|
||||
_COMMAND_HANDLERS = blivedm.BLiveClient._COMMAND_HANDLERS.copy()
|
||||
@ -29,20 +43,5 @@ class MyBLiveClient(blivedm.BLiveClient):
|
||||
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__':
|
||||
asyncio.get_event_loop().run_until_complete(main())
|
||||
|
Loading…
Reference in New Issue
Block a user