mirror of
https://github.com/xfgryujk/blivechat.git
synced 2025-04-03 16:10:35 +08:00
添加更多插件接口
This commit is contained in:
parent
0f9fcddde8
commit
be5b49fae4
15
api/chat.py
15
api/chat.py
@ -199,21 +199,10 @@ class ChatHandler(tornado.websocket.WebSocketHandler):
|
|||||||
|
|
||||||
room_key_dict = data.get('roomKey', None)
|
room_key_dict = data.get('roomKey', None)
|
||||||
if room_key_dict is not None:
|
if room_key_dict is not None:
|
||||||
room_key_type = services.chat.RoomKeyType(room_key_dict['type'])
|
self.room_key = services.chat.RoomKey.from_dict(room_key_dict)
|
||||||
room_key_value = room_key_dict['value']
|
|
||||||
if room_key_type == services.chat.RoomKeyType.ROOM_ID:
|
|
||||||
if not isinstance(room_key_value, int):
|
|
||||||
raise TypeError(f'Room key value type error, value={room_key_value}')
|
|
||||||
elif room_key_type == services.chat.RoomKeyType.AUTH_CODE:
|
|
||||||
if not isinstance(room_key_value, str):
|
|
||||||
raise TypeError(f'Room key value type error, value={room_key_value}')
|
|
||||||
else:
|
|
||||||
raise ValueError(f'Unknown RoomKeyType={room_key_type}')
|
|
||||||
else:
|
else:
|
||||||
# 兼容旧版客户端 TODO 过几个版本可以移除
|
# 兼容旧版客户端 TODO 过几个版本可以移除
|
||||||
room_key_type = services.chat.RoomKeyType.ROOM_ID
|
self.room_key = services.chat.RoomKey(services.chat.RoomKeyType.ROOM_ID, int(data['roomId']))
|
||||||
room_key_value = int(data['roomId'])
|
|
||||||
self.room_key = services.chat.RoomKey(room_key_type, room_key_value)
|
|
||||||
logger.info('client=%s joining room %s', self.request.remote_ip, self.room_key)
|
logger.info('client=%s joining room %s', self.request.remote_ip, self.room_key)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
@ -8,7 +8,10 @@ import tornado.web
|
|||||||
import tornado.websocket
|
import tornado.websocket
|
||||||
|
|
||||||
import api.base
|
import api.base
|
||||||
|
import api.chat
|
||||||
import blcsdk.models as models
|
import blcsdk.models as models
|
||||||
|
import services.avatar
|
||||||
|
import services.chat
|
||||||
import services.plugin
|
import services.plugin
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
@ -93,15 +96,61 @@ class PluginWsHandler(_PluginHandlerBase, tornado.websocket.WebSocketHandler):
|
|||||||
try:
|
try:
|
||||||
body = json.loads(message)
|
body = json.loads(message)
|
||||||
cmd = int(body['cmd'])
|
cmd = int(body['cmd'])
|
||||||
|
data = body['data']
|
||||||
|
|
||||||
if cmd == models.Command.HEARTBEAT:
|
if cmd == models.Command.HEARTBEAT:
|
||||||
self._refresh_receive_timeout_timer()
|
self._refresh_receive_timeout_timer()
|
||||||
|
elif cmd == models.Command.LOG_REQ:
|
||||||
|
logger.log(int(data['level']), '[%s] %s', self.plugin.id, data['msg'])
|
||||||
|
elif cmd == models.Command.ADD_TEXT_REQ:
|
||||||
|
self._on_add_text_req(data)
|
||||||
else:
|
else:
|
||||||
logger.warning('plugin=%s unknown cmd=%d, body=%s', self.plugin.id, cmd, body)
|
logger.warning('plugin=%s unknown cmd=%d, body=%s', self.plugin.id, cmd, body)
|
||||||
|
|
||||||
except Exception: # noqa
|
except Exception: # noqa
|
||||||
logger.exception('plugin=%s on_message error, message=%s', self.plugin.id, message)
|
logger.exception('plugin=%s on_message error, message=%s', self.plugin.id, message)
|
||||||
|
|
||||||
|
def _on_add_text_req(self, data: dict):
|
||||||
|
room_key_dict = data['roomKey']
|
||||||
|
if room_key_dict is not None:
|
||||||
|
room_key = services.chat.RoomKey.from_dict(room_key_dict)
|
||||||
|
room = services.chat.client_room_manager.get_room(room_key)
|
||||||
|
if room is not None:
|
||||||
|
rooms = [room]
|
||||||
|
else:
|
||||||
|
rooms = []
|
||||||
|
else:
|
||||||
|
rooms = list(services.chat.client_room_manager.iter_rooms())
|
||||||
|
if not rooms:
|
||||||
|
return
|
||||||
|
|
||||||
|
author_name = str(data['authorName'])
|
||||||
|
if author_name == '':
|
||||||
|
author_name = self.plugin.id
|
||||||
|
uid = int(data['uid'])
|
||||||
|
avatar_url = str(data['avatarUrl'])
|
||||||
|
if avatar_url == '':
|
||||||
|
avatar_url = services.avatar.get_default_avatar_url(uid, author_name)
|
||||||
|
|
||||||
|
data_to_send = api.chat.make_text_message_data(
|
||||||
|
content=str(data['content']),
|
||||||
|
author_name=author_name,
|
||||||
|
uid=uid,
|
||||||
|
avatar_url=avatar_url,
|
||||||
|
author_type=int(data['authorType']),
|
||||||
|
privilege_type=int(data['guardLevel']),
|
||||||
|
medal_level=int(data['medalLevel']),
|
||||||
|
translation=str(data['translation']),
|
||||||
|
)
|
||||||
|
|
||||||
|
body_for_room = api.chat.make_message_body(api.chat.Command.ADD_TEXT, data_to_send)
|
||||||
|
for room in rooms:
|
||||||
|
room.send_body_no_raise(body_for_room)
|
||||||
|
|
||||||
|
extra = services.chat.make_plugin_msg_extra_from_client_room(room)
|
||||||
|
extra['isFromPlugin'] = True
|
||||||
|
services.plugin.broadcast_cmd_data(models.Command.ADD_TEXT, data_to_send, extra)
|
||||||
|
|
||||||
def send_cmd_data(self, cmd, data, extra: Optional[dict] = None):
|
def send_cmd_data(self, cmd, data, extra: Optional[dict] = None):
|
||||||
self.send_body_no_raise(make_message_body(cmd, data, extra))
|
self.send_body_no_raise(make_message_body(cmd, data, extra))
|
||||||
|
|
||||||
@ -112,6 +161,19 @@ class PluginWsHandler(_PluginHandlerBase, tornado.websocket.WebSocketHandler):
|
|||||||
self.close()
|
self.close()
|
||||||
|
|
||||||
|
|
||||||
|
class RoomsHandler(api.base.ApiHandler):
|
||||||
|
async def get(self):
|
||||||
|
rooms = [
|
||||||
|
{
|
||||||
|
'roomId': live_client.room_id,
|
||||||
|
'roomKey': live_client.room_key.to_dict(),
|
||||||
|
}
|
||||||
|
for live_client in services.chat.iter_live_clients()
|
||||||
|
]
|
||||||
|
self.write({'rooms': rooms})
|
||||||
|
|
||||||
|
|
||||||
ROUTES = [
|
ROUTES = [
|
||||||
(r'/api/plugin/websocket', PluginWsHandler),
|
(r'/api/plugin/websocket', PluginWsHandler),
|
||||||
|
(r'/api/plugin/rooms', RoomsHandler),
|
||||||
]
|
]
|
||||||
|
157
blcsdk/api.py
157
blcsdk/api.py
@ -1,5 +1,6 @@
|
|||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
import asyncio
|
import asyncio
|
||||||
|
import dataclasses
|
||||||
import logging
|
import logging
|
||||||
import os
|
import os
|
||||||
import re
|
import re
|
||||||
@ -20,12 +21,21 @@ __all__ = (
|
|||||||
'shut_down',
|
'shut_down',
|
||||||
'set_msg_handler',
|
'set_msg_handler',
|
||||||
'is_sdk_version_compatible',
|
'is_sdk_version_compatible',
|
||||||
|
'get_blc_port',
|
||||||
|
'get_blc_version',
|
||||||
|
'get_blc_sdk_version',
|
||||||
|
'get_plugin_id',
|
||||||
|
'log',
|
||||||
|
'send_text',
|
||||||
|
'get_rooms',
|
||||||
)
|
)
|
||||||
|
|
||||||
logger = logging.getLogger('blcsdk')
|
logger = logging.getLogger('blcsdk')
|
||||||
|
|
||||||
# 环境变量
|
# 环境变量
|
||||||
_base_url = ''
|
_blc_port = 0
|
||||||
|
"""服务器端口"""
|
||||||
|
_blc_base_url = ''
|
||||||
"""HTTP API的URL"""
|
"""HTTP API的URL"""
|
||||||
_token = ''
|
_token = ''
|
||||||
"""插件认证用的token"""
|
"""插件认证用的token"""
|
||||||
@ -54,15 +64,16 @@ async def init():
|
|||||||
在调用除了set_msg_handler以外的其他接口之前必须先调用这个。如果抛出任何异常,应该退出当前程序
|
在调用除了set_msg_handler以外的其他接口之前必须先调用这个。如果抛出任何异常,应该退出当前程序
|
||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
global _base_url, _token, _init_future, _init_msg, _http_session, _plugin_client, _msg_handler_wrapper
|
global _blc_port, _blc_base_url, _token, _init_future, _init_msg, _http_session, _plugin_client, \
|
||||||
|
_msg_handler_wrapper
|
||||||
if _init_future is not None:
|
if _init_future is not None:
|
||||||
raise exc.InitError('Cannot call init() again')
|
raise exc.InitError('Cannot call init() again')
|
||||||
_init_future = asyncio.get_running_loop().create_future()
|
_init_future = asyncio.get_running_loop().create_future()
|
||||||
|
|
||||||
# 初始化环境变量信息
|
# 初始化环境变量信息
|
||||||
blc_port = int(os.environ['BLC_PORT'])
|
_blc_port = int(os.environ['BLC_PORT'])
|
||||||
_base_url = f'http://localhost:{blc_port}'
|
_blc_base_url = f'http://localhost:{_blc_port}'
|
||||||
blc_ws_url = f'ws://localhost:{blc_port}/api/plugin/websocket'
|
blc_ws_url = f'ws://localhost:{_blc_port}/api/plugin/websocket'
|
||||||
_token = os.environ['BLC_TOKEN']
|
_token = os.environ['BLC_TOKEN']
|
||||||
|
|
||||||
_http_session = aiohttp.ClientSession(
|
_http_session = aiohttp.ClientSession(
|
||||||
@ -134,11 +145,10 @@ def is_sdk_version_compatible():
|
|||||||
|
|
||||||
如果不兼容,建议退出当前程序。如果继续执行有可能不能正常工作
|
如果不兼容,建议退出当前程序。如果继续执行有可能不能正常工作
|
||||||
"""
|
"""
|
||||||
if _init_msg is None:
|
assert _init_msg is not None, 'Please call init() first'
|
||||||
raise exc.SdkError('Please call init() first')
|
|
||||||
|
|
||||||
major_ver_pattern = r'(\d+)\.\d+\.\d+'
|
major_ver_pattern = r'(\d+)\.\d+\.\d+'
|
||||||
remote_ver = _init_msg['sdkVersion']
|
remote_ver = get_blc_sdk_version()
|
||||||
|
|
||||||
m = re.match(major_ver_pattern, remote_ver)
|
m = re.match(major_ver_pattern, remote_ver)
|
||||||
if m is None:
|
if m is None:
|
||||||
@ -154,3 +164,134 @@ def is_sdk_version_compatible():
|
|||||||
if not res:
|
if not res:
|
||||||
logger.warning('SDK version is not compatible, remote=%s, local=%s', remote_ver, __version__)
|
logger.warning('SDK version is not compatible, remote=%s, local=%s', remote_ver, __version__)
|
||||||
return res
|
return res
|
||||||
|
|
||||||
|
|
||||||
|
def get_blc_port():
|
||||||
|
"""取blivechat服务器监听的端口"""
|
||||||
|
assert _blc_port != 0, 'Please call init() first'
|
||||||
|
return _blc_port
|
||||||
|
|
||||||
|
|
||||||
|
def get_blc_version() -> str:
|
||||||
|
"""取blivechat版本"""
|
||||||
|
assert _init_msg is not None, 'Please call init() first'
|
||||||
|
return _init_msg['blcVersion']
|
||||||
|
|
||||||
|
|
||||||
|
def get_blc_sdk_version() -> str:
|
||||||
|
"""取blivechat用的SDK版本。是主进程用的版本,不是这个包的__version__"""
|
||||||
|
assert _init_msg is not None, 'Please call init() first'
|
||||||
|
return _init_msg['sdkVersion']
|
||||||
|
|
||||||
|
|
||||||
|
def get_plugin_id() -> str:
|
||||||
|
"""取当前插件的ID"""
|
||||||
|
assert _init_msg is not None, 'Please call init() first'
|
||||||
|
return _init_msg['pluginId']
|
||||||
|
|
||||||
|
|
||||||
|
async def _blc_ws_send_cmd_data(cmd: models.Command, data: dict):
|
||||||
|
assert _plugin_client is not None, 'Please call init() first'
|
||||||
|
|
||||||
|
try:
|
||||||
|
await _plugin_client.send_cmd_data(cmd, data)
|
||||||
|
except (ConnectionResetError, aiohttp.ClientError) as e:
|
||||||
|
raise exc.TransportError(str(e)) from e
|
||||||
|
|
||||||
|
|
||||||
|
def _blc_get(rel_url, *, params=None):
|
||||||
|
return _blc_http_request('GET', rel_url, params=params)
|
||||||
|
|
||||||
|
|
||||||
|
def _blc_post(rel_url, *, params=None, json=None):
|
||||||
|
return _blc_http_request('POST', rel_url, params=params, json=json)
|
||||||
|
|
||||||
|
|
||||||
|
async def _blc_http_request(method, rel_url, **kwargs):
|
||||||
|
assert _http_session is not None, 'Please call init() first'
|
||||||
|
|
||||||
|
try:
|
||||||
|
async with _http_session.request(method, _blc_base_url + rel_url, **kwargs) as r:
|
||||||
|
if r.ok:
|
||||||
|
return await r.json()
|
||||||
|
|
||||||
|
try:
|
||||||
|
data = await r.json()
|
||||||
|
except aiohttp.ContentTypeError:
|
||||||
|
data = None
|
||||||
|
raise exc.ResponseError(r.status, r.reason, data)
|
||||||
|
except aiohttp.ClientError as e:
|
||||||
|
raise exc.TransportError(str(e)) from e
|
||||||
|
|
||||||
|
|
||||||
|
async def log(msg, level=logging.INFO):
|
||||||
|
"""
|
||||||
|
输出日志到blivechat
|
||||||
|
|
||||||
|
blivechat不会分离插件的控制台,所以直接输出到标准输出流、标准错误流也能看到日志,但是通过这个接口输出的还会写到blivechat的日志文件
|
||||||
|
"""
|
||||||
|
await _blc_ws_send_cmd_data(models.Command.LOG_REQ, {
|
||||||
|
'msg': str(msg),
|
||||||
|
'level': level,
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
async def send_text(
|
||||||
|
content: str,
|
||||||
|
author_name: str = '',
|
||||||
|
*,
|
||||||
|
uid: int = 0,
|
||||||
|
avatar_url: str = '',
|
||||||
|
author_type: int = models.AuthorType.NORMAL.value,
|
||||||
|
guard_level: int = models.GuardLevel.NONE.value,
|
||||||
|
medal_level: int = 0,
|
||||||
|
translation: str = '',
|
||||||
|
room_key: Optional[models.RoomKey] = None,
|
||||||
|
):
|
||||||
|
"""
|
||||||
|
发送文字消息
|
||||||
|
|
||||||
|
当前插件也会收到这条消息,注意避免死循环
|
||||||
|
|
||||||
|
:param content: 内容
|
||||||
|
:param author_name: 用户名,默认为当前插件ID
|
||||||
|
:param uid: 用户ID
|
||||||
|
:param avatar_url: 用户头像URL,默认自动生成
|
||||||
|
:param author_type: 用户类型,见AuthorType
|
||||||
|
:param guard_level: 舰队等级,见GuardLevel
|
||||||
|
:param medal_level: 勋章等级
|
||||||
|
:param translation: 内容翻译
|
||||||
|
:param room_key: 发送到哪个房间,默认发送到所有房间
|
||||||
|
"""
|
||||||
|
await _blc_ws_send_cmd_data(models.Command.ADD_TEXT_REQ, {
|
||||||
|
'content': content,
|
||||||
|
'authorName': author_name,
|
||||||
|
'uid': uid,
|
||||||
|
'avatarUrl': avatar_url,
|
||||||
|
'authorType': author_type,
|
||||||
|
'guardLevel': guard_level,
|
||||||
|
'medalLevel': medal_level,
|
||||||
|
'translation': translation,
|
||||||
|
'roomKey': room_key.to_dict() if room_key is not None else None,
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
@dataclasses.dataclass
|
||||||
|
class GetRoomsRes:
|
||||||
|
room_id: Optional[int]
|
||||||
|
"""房间ID,初始化之前是None"""
|
||||||
|
room_key: models.RoomKey
|
||||||
|
"""blivechat用来标识一个房间的key"""
|
||||||
|
|
||||||
|
|
||||||
|
async def get_rooms() -> List[GetRoomsRes]:
|
||||||
|
"""取当前已创建的房间列表"""
|
||||||
|
rsp = await _blc_get('/api/plugin/rooms')
|
||||||
|
rooms = [
|
||||||
|
GetRoomsRes(
|
||||||
|
room_id=room_dict['roomId'],
|
||||||
|
room_key=models.RoomKey.from_dict(room_dict['roomKey']),
|
||||||
|
)
|
||||||
|
for room_dict in rsp['rooms']
|
||||||
|
]
|
||||||
|
return rooms
|
||||||
|
@ -1,7 +1,11 @@
|
|||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
|
from typing import *
|
||||||
|
|
||||||
__all__ = (
|
__all__ = (
|
||||||
'SdkError',
|
'SdkError',
|
||||||
'InitError',
|
'InitError',
|
||||||
|
'TransportError',
|
||||||
|
'ResponseError',
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@ -11,3 +15,16 @@ class SdkError(Exception):
|
|||||||
|
|
||||||
class InitError(SdkError):
|
class InitError(SdkError):
|
||||||
"""初始化失败"""
|
"""初始化失败"""
|
||||||
|
|
||||||
|
|
||||||
|
class TransportError(SdkError):
|
||||||
|
"""通信错误"""
|
||||||
|
|
||||||
|
|
||||||
|
class ResponseError(SdkError):
|
||||||
|
"""响应代码错误"""
|
||||||
|
def __init__(self, code: int, msg: str, data: Optional[dict] = None):
|
||||||
|
super().__init__(f'code={code}, msg={msg}, data={data}')
|
||||||
|
self.code = code
|
||||||
|
self.msg = msg
|
||||||
|
self.data = data
|
||||||
|
@ -46,6 +46,9 @@ class BaseHandler(HandlerInterface):
|
|||||||
models.Command.ADD_ROOM: _make_msg_callback('_on_add_room', models.AddRoomMsg),
|
models.Command.ADD_ROOM: _make_msg_callback('_on_add_room', models.AddRoomMsg),
|
||||||
models.Command.ROOM_INIT: _make_msg_callback('_on_room_init', models.RoomInitMsg),
|
models.Command.ROOM_INIT: _make_msg_callback('_on_room_init', models.RoomInitMsg),
|
||||||
models.Command.DEL_ROOM: _make_msg_callback('_on_del_room', models.DelRoomMsg),
|
models.Command.DEL_ROOM: _make_msg_callback('_on_del_room', models.DelRoomMsg),
|
||||||
|
models.Command.OPEN_PLUGIN_ADMIN_UI: _make_msg_callback(
|
||||||
|
'_on_open_plugin_admin_ui', models.OpenPluginAdminUiMsg
|
||||||
|
),
|
||||||
models.Command.ADD_TEXT: _make_msg_callback('_on_add_text', models.AddTextMsg),
|
models.Command.ADD_TEXT: _make_msg_callback('_on_add_text', models.AddTextMsg),
|
||||||
models.Command.ADD_GIFT: _make_msg_callback('_on_add_gift', models.AddGiftMsg),
|
models.Command.ADD_GIFT: _make_msg_callback('_on_add_gift', models.AddGiftMsg),
|
||||||
models.Command.ADD_MEMBER: _make_msg_callback('_on_add_member', models.AddMemberMsg),
|
models.Command.ADD_MEMBER: _make_msg_callback('_on_add_member', models.AddMemberMsg),
|
||||||
@ -70,6 +73,11 @@ class BaseHandler(HandlerInterface):
|
|||||||
def _on_del_room(self, client: cli.BlcPluginClient, message: models.DelRoomMsg, extra: models.ExtraData):
|
def _on_del_room(self, client: cli.BlcPluginClient, message: models.DelRoomMsg, extra: models.ExtraData):
|
||||||
"""删除房间"""
|
"""删除房间"""
|
||||||
|
|
||||||
|
def _on_open_plugin_admin_ui(
|
||||||
|
self, client: cli.BlcPluginClient, message: models.OpenPluginAdminUiMsg, extra: models.ExtraData
|
||||||
|
):
|
||||||
|
"""用户请求打开当前插件的管理界面"""
|
||||||
|
|
||||||
def _on_add_text(self, client: cli.BlcPluginClient, message: models.AddTextMsg, extra: models.ExtraData):
|
def _on_add_text(self, client: cli.BlcPluginClient, message: models.AddTextMsg, extra: models.ExtraData):
|
||||||
"""收到弹幕"""
|
"""收到弹幕"""
|
||||||
|
|
||||||
|
@ -7,6 +7,11 @@ __all__ = (
|
|||||||
'RoomKeyType',
|
'RoomKeyType',
|
||||||
'RoomKey',
|
'RoomKey',
|
||||||
'Command',
|
'Command',
|
||||||
|
'ExtraData',
|
||||||
|
'AddRoomMsg',
|
||||||
|
'RoomInitMsg',
|
||||||
|
'DelRoomMsg',
|
||||||
|
'OpenPluginAdminUiMsg',
|
||||||
'AuthorType',
|
'AuthorType',
|
||||||
'GuardLevel',
|
'GuardLevel',
|
||||||
'ContentType',
|
'ContentType',
|
||||||
@ -37,6 +42,21 @@ class RoomKey(NamedTuple):
|
|||||||
return res
|
return res
|
||||||
__repr__ = __str__
|
__repr__ = __str__
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def from_dict(cls, data: dict):
|
||||||
|
type_ = RoomKeyType(data['type'])
|
||||||
|
value = data['value']
|
||||||
|
if type_ == RoomKeyType.ROOM_ID:
|
||||||
|
if not isinstance(value, int):
|
||||||
|
raise TypeError(f'Type of value is {type(value)}, value={value}')
|
||||||
|
elif type_ == RoomKeyType.AUTH_CODE:
|
||||||
|
if not isinstance(value, str):
|
||||||
|
raise TypeError(f'Type of value is {type(value)}, value={value}')
|
||||||
|
return cls(type=type_, value=value)
|
||||||
|
|
||||||
|
def to_dict(self):
|
||||||
|
return {'type': self.type, 'value': self.value}
|
||||||
|
|
||||||
|
|
||||||
class Command(enum.IntEnum):
|
class Command(enum.IntEnum):
|
||||||
HEARTBEAT = 0
|
HEARTBEAT = 0
|
||||||
@ -44,13 +64,19 @@ class Command(enum.IntEnum):
|
|||||||
ADD_ROOM = 2
|
ADD_ROOM = 2
|
||||||
ROOM_INIT = 3
|
ROOM_INIT = 3
|
||||||
DEL_ROOM = 4
|
DEL_ROOM = 4
|
||||||
|
OPEN_PLUGIN_ADMIN_UI = 5
|
||||||
|
|
||||||
ADD_TEXT = 20
|
# 从插件发送到blivechat的请求
|
||||||
ADD_GIFT = 21
|
LOG_REQ = 30
|
||||||
ADD_MEMBER = 22
|
ADD_TEXT_REQ = 31
|
||||||
ADD_SUPER_CHAT = 23
|
|
||||||
DEL_SUPER_CHAT = 24
|
# 房间内消息
|
||||||
UPDATE_TRANSLATION = 25
|
ADD_TEXT = 50
|
||||||
|
ADD_GIFT = 51
|
||||||
|
ADD_MEMBER = 52
|
||||||
|
ADD_SUPER_CHAT = 53
|
||||||
|
DEL_SUPER_CHAT = 54
|
||||||
|
UPDATE_TRANSLATION = 55
|
||||||
|
|
||||||
|
|
||||||
@dataclasses.dataclass
|
@dataclasses.dataclass
|
||||||
@ -62,16 +88,17 @@ class ExtraData:
|
|||||||
room_key: Optional[RoomKey] = None
|
room_key: Optional[RoomKey] = None
|
||||||
"""blivechat用来标识一个房间的key"""
|
"""blivechat用来标识一个房间的key"""
|
||||||
is_from_plugin: bool = False
|
is_from_plugin: bool = False
|
||||||
"""消息是插件生成的"""
|
"""
|
||||||
|
消息是插件生成的
|
||||||
|
|
||||||
|
如果你的插件既要监听消息,又要生成消息,注意判断这个以避免死循环
|
||||||
|
"""
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def from_dict(cls, data: dict):
|
def from_dict(cls, data: dict):
|
||||||
room_key_dict = data.get('roomKey', None)
|
room_key_dict = data.get('roomKey', None)
|
||||||
if room_key_dict is not None:
|
if room_key_dict is not None:
|
||||||
room_key = RoomKey(
|
room_key = RoomKey.from_dict(room_key_dict)
|
||||||
type=RoomKeyType(room_key_dict['type']),
|
|
||||||
value=room_key_dict['value'],
|
|
||||||
)
|
|
||||||
else:
|
else:
|
||||||
room_key = None
|
room_key = None
|
||||||
|
|
||||||
@ -83,17 +110,20 @@ class ExtraData:
|
|||||||
|
|
||||||
|
|
||||||
@dataclasses.dataclass
|
@dataclasses.dataclass
|
||||||
class AddRoomMsg:
|
class _EmptyMsg:
|
||||||
|
@classmethod
|
||||||
|
def from_command(cls, _data: dict):
|
||||||
|
return cls()
|
||||||
|
|
||||||
|
|
||||||
|
@dataclasses.dataclass
|
||||||
|
class AddRoomMsg(_EmptyMsg):
|
||||||
"""
|
"""
|
||||||
添加房间消息。房间信息在extra里
|
添加房间消息。房间信息在extra里
|
||||||
|
|
||||||
此时room_id是None,因为还没有初始化
|
此时room_id是None,因为还没有初始化
|
||||||
"""
|
"""
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def from_command(cls, _data: dict):
|
|
||||||
return cls()
|
|
||||||
|
|
||||||
|
|
||||||
@dataclasses.dataclass
|
@dataclasses.dataclass
|
||||||
class RoomInitMsg:
|
class RoomInitMsg:
|
||||||
@ -113,16 +143,17 @@ class RoomInitMsg:
|
|||||||
|
|
||||||
|
|
||||||
@dataclasses.dataclass
|
@dataclasses.dataclass
|
||||||
class DelRoomMsg:
|
class DelRoomMsg(_EmptyMsg):
|
||||||
"""
|
"""
|
||||||
删除房间消息。房间信息在extra里
|
删除房间消息。房间信息在extra里
|
||||||
|
|
||||||
注意此时room_id可能是None
|
注意此时room_id可能是None
|
||||||
"""
|
"""
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def from_command(cls, _data: dict):
|
@dataclasses.dataclass
|
||||||
return cls()
|
class OpenPluginAdminUiMsg(_EmptyMsg):
|
||||||
|
"""用户请求打开当前插件的管理界面消息"""
|
||||||
|
|
||||||
|
|
||||||
class AuthorType(enum.IntEnum):
|
class AuthorType(enum.IntEnum):
|
||||||
|
@ -3,14 +3,14 @@ import __main__
|
|||||||
import datetime
|
import datetime
|
||||||
import logging
|
import logging
|
||||||
import os
|
import os
|
||||||
|
import sys
|
||||||
from typing import *
|
from typing import *
|
||||||
|
|
||||||
import blcsdk
|
import blcsdk
|
||||||
import blcsdk.models as sdk_models
|
import blcsdk.models as sdk_models
|
||||||
import config
|
import config
|
||||||
from blcsdk import client as cli
|
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger('msg-logging.' + __name__)
|
||||||
|
|
||||||
_msg_handler: Optional['MsgHandler'] = None
|
_msg_handler: Optional['MsgHandler'] = None
|
||||||
_id_room_dict: Dict[int, 'Room'] = {}
|
_id_room_dict: Dict[int, 'Room'] = {}
|
||||||
@ -21,34 +21,59 @@ async def init():
|
|||||||
_msg_handler = MsgHandler()
|
_msg_handler = MsgHandler()
|
||||||
blcsdk.set_msg_handler(_msg_handler)
|
blcsdk.set_msg_handler(_msg_handler)
|
||||||
|
|
||||||
# TODO 创建已有的房间
|
# 创建已有的房间。这一步失败了也没关系,只是有消息时才会创建文件
|
||||||
|
try:
|
||||||
|
blc_rooms = await blcsdk.get_rooms()
|
||||||
|
for blc_room in blc_rooms:
|
||||||
|
if blc_room.room_id is not None:
|
||||||
|
_get_or_add_room(blc_room.room_id)
|
||||||
|
except blcsdk.SdkError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
def shut_down():
|
def shut_down():
|
||||||
blcsdk.set_msg_handler(None)
|
blcsdk.set_msg_handler(None)
|
||||||
while _id_room_dict:
|
while len(_id_room_dict) != 0:
|
||||||
room_id = next(iter(_id_room_dict))
|
room_id = next(iter(_id_room_dict))
|
||||||
_del_room(room_id)
|
_del_room(room_id)
|
||||||
|
|
||||||
|
|
||||||
class MsgHandler(blcsdk.BaseHandler):
|
class MsgHandler(blcsdk.BaseHandler):
|
||||||
def on_client_stopped(self, client: cli.BlcPluginClient, exception: Optional[Exception]):
|
def on_client_stopped(self, client: blcsdk.BlcPluginClient, exception: Optional[Exception]):
|
||||||
logger.info('blivechat disconnected')
|
logger.info('blivechat disconnected')
|
||||||
__main__.start_shut_down()
|
__main__.start_shut_down()
|
||||||
|
|
||||||
def _on_room_init(self, client: cli.BlcPluginClient, message: sdk_models.RoomInitMsg, extra: sdk_models.ExtraData):
|
def _on_open_plugin_admin_ui(
|
||||||
|
self, client: blcsdk.BlcPluginClient, message: sdk_models.OpenPluginAdminUiMsg, extra: sdk_models.ExtraData
|
||||||
|
):
|
||||||
|
if sys.platform == 'win32':
|
||||||
|
os.startfile(config.LOG_PATH)
|
||||||
|
else:
|
||||||
|
logger.info('Log path is "%s"', config.LOG_PATH)
|
||||||
|
|
||||||
|
def _on_room_init(
|
||||||
|
self, client: blcsdk.BlcPluginClient, message: sdk_models.RoomInitMsg, extra: sdk_models.ExtraData
|
||||||
|
):
|
||||||
|
if extra.is_from_plugin:
|
||||||
|
return
|
||||||
if message.is_success:
|
if message.is_success:
|
||||||
_get_or_add_room(extra.room_id)
|
_get_or_add_room(extra.room_id)
|
||||||
|
|
||||||
def _on_del_room(self, client: cli.BlcPluginClient, message: sdk_models.DelRoomMsg, extra: sdk_models.ExtraData):
|
def _on_del_room(self, client: blcsdk.BlcPluginClient, message: sdk_models.DelRoomMsg, extra: sdk_models.ExtraData):
|
||||||
|
if extra.is_from_plugin:
|
||||||
|
return
|
||||||
if extra.room_id is not None:
|
if extra.room_id is not None:
|
||||||
_del_room(extra.room_id)
|
_del_room(extra.room_id)
|
||||||
|
|
||||||
def _on_add_text(self, client: cli.BlcPluginClient, message: sdk_models.AddTextMsg, extra: sdk_models.ExtraData):
|
def _on_add_text(self, client: blcsdk.BlcPluginClient, message: sdk_models.AddTextMsg, extra: sdk_models.ExtraData):
|
||||||
|
if extra.is_from_plugin:
|
||||||
|
return
|
||||||
room = _get_or_add_room(extra.room_id)
|
room = _get_or_add_room(extra.room_id)
|
||||||
room.log(f'[dm] {message.author_name}:{message.content}')
|
room.log(f'[dm] {message.author_name}:{message.content}')
|
||||||
|
|
||||||
def _on_add_gift(self, client: cli.BlcPluginClient, message: sdk_models.AddGiftMsg, extra: sdk_models.ExtraData):
|
def _on_add_gift(self, client: blcsdk.BlcPluginClient, message: sdk_models.AddGiftMsg, extra: sdk_models.ExtraData):
|
||||||
|
if extra.is_from_plugin:
|
||||||
|
return
|
||||||
room = _get_or_add_room(extra.room_id)
|
room = _get_or_add_room(extra.room_id)
|
||||||
room.log(
|
room.log(
|
||||||
f'[gift] {message.author_name} 赠送了 {message.gift_name} x {message.num},'
|
f'[gift] {message.author_name} 赠送了 {message.gift_name} x {message.num},'
|
||||||
@ -56,8 +81,10 @@ class MsgHandler(blcsdk.BaseHandler):
|
|||||||
)
|
)
|
||||||
|
|
||||||
def _on_add_member(
|
def _on_add_member(
|
||||||
self, client: cli.BlcPluginClient, message: sdk_models.AddMemberMsg, extra: sdk_models.ExtraData
|
self, client: blcsdk.BlcPluginClient, message: sdk_models.AddMemberMsg, extra: sdk_models.ExtraData
|
||||||
):
|
):
|
||||||
|
if extra.is_from_plugin:
|
||||||
|
return
|
||||||
room = _get_or_add_room(extra.room_id)
|
room = _get_or_add_room(extra.room_id)
|
||||||
if message.privilege_type == sdk_models.GuardLevel.LV1:
|
if message.privilege_type == sdk_models.GuardLevel.LV1:
|
||||||
guard_name = '舰长'
|
guard_name = '舰长'
|
||||||
@ -71,8 +98,10 @@ class MsgHandler(blcsdk.BaseHandler):
|
|||||||
room.log(f'[guard] {message.author_name} 购买了 {guard_name}')
|
room.log(f'[guard] {message.author_name} 购买了 {guard_name}')
|
||||||
|
|
||||||
def _on_add_super_chat(
|
def _on_add_super_chat(
|
||||||
self, client: cli.BlcPluginClient, message: sdk_models.AddSuperChatMsg, extra: sdk_models.ExtraData
|
self, client: blcsdk.BlcPluginClient, message: sdk_models.AddSuperChatMsg, extra: sdk_models.ExtraData
|
||||||
):
|
):
|
||||||
|
if extra.is_from_plugin:
|
||||||
|
return
|
||||||
room = _get_or_add_room(extra.room_id)
|
room = _get_or_add_room(extra.room_id)
|
||||||
room.log(f'[superchat] {message.author_name} 发送了 {message.price} 元的醒目留言:{message.content}')
|
room.log(f'[superchat] {message.author_name} 发送了 {message.price} 元的醒目留言:{message.content}')
|
||||||
|
|
||||||
@ -80,6 +109,8 @@ class MsgHandler(blcsdk.BaseHandler):
|
|||||||
def _get_or_add_room(room_id):
|
def _get_or_add_room(room_id):
|
||||||
ctx = _id_room_dict.get(room_id, None)
|
ctx = _id_room_dict.get(room_id, None)
|
||||||
if ctx is None:
|
if ctx is None:
|
||||||
|
if room_id is None:
|
||||||
|
raise TypeError('room_id is None')
|
||||||
ctx = _id_room_dict[room_id] = Room(room_id)
|
ctx = _id_room_dict[room_id] = Room(room_id)
|
||||||
return ctx
|
return ctx
|
||||||
|
|
||||||
@ -92,19 +123,17 @@ def _del_room(room_id):
|
|||||||
|
|
||||||
class Room:
|
class Room:
|
||||||
def __init__(self, room_id):
|
def __init__(self, room_id):
|
||||||
self.room_id = room_id
|
|
||||||
|
|
||||||
cur_time = datetime.datetime.now()
|
cur_time = datetime.datetime.now()
|
||||||
time_str = cur_time.strftime('%Y%m%d_%H%M%S')
|
time_str = cur_time.strftime('%Y%m%d_%H%M%S')
|
||||||
filename = f'room_{room_id}-{time_str}.log'
|
filename = f'room_{room_id}-{time_str}.txt'
|
||||||
self.file = open(os.path.join(config.LOG_PATH, filename), 'a', encoding='utf-8-sig')
|
self._file = open(os.path.join(config.LOG_PATH, filename), 'a', encoding='utf-8-sig')
|
||||||
|
|
||||||
def close(self):
|
def close(self):
|
||||||
self.file.close()
|
self._file.close()
|
||||||
|
|
||||||
def log(self, content):
|
def log(self, content):
|
||||||
cur_time = datetime.datetime.now()
|
cur_time = datetime.datetime.now()
|
||||||
time_str = cur_time.strftime('%Y-%m-%d %H:%M:%S')
|
time_str = cur_time.strftime('%Y-%m-%d %H:%M:%S')
|
||||||
text = f'{time_str} {content}\n'
|
text = f'{time_str} {content}\n'
|
||||||
self.file.write(text)
|
self._file.write(text)
|
||||||
self.file.flush()
|
self._file.flush()
|
||||||
|
110
services/chat.py
110
services/chat.py
@ -39,6 +39,21 @@ class RoomKey(NamedTuple):
|
|||||||
return res
|
return res
|
||||||
__repr__ = __str__
|
__repr__ = __str__
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def from_dict(cls, data: dict):
|
||||||
|
type_ = RoomKeyType(data['type'])
|
||||||
|
value = data['value']
|
||||||
|
if type_ == RoomKeyType.ROOM_ID:
|
||||||
|
if not isinstance(value, int):
|
||||||
|
raise TypeError(f'Type of value is {type(value)}, value={value}')
|
||||||
|
elif type_ == RoomKeyType.AUTH_CODE:
|
||||||
|
if not isinstance(value, str):
|
||||||
|
raise TypeError(f'Type of value is {type(value)}, value={value}')
|
||||||
|
return cls(type=type_, value=value)
|
||||||
|
|
||||||
|
def to_dict(self):
|
||||||
|
return {'type': self.type, 'value': self.value}
|
||||||
|
|
||||||
|
|
||||||
# 用于类型标注的类型别名
|
# 用于类型标注的类型别名
|
||||||
LiveClientType = Union['WebLiveClient', 'OpenLiveClient']
|
LiveClientType = Union['WebLiveClient', 'OpenLiveClient']
|
||||||
@ -65,14 +80,27 @@ async def shut_down():
|
|||||||
await _live_client_manager.shut_down()
|
await _live_client_manager.shut_down()
|
||||||
|
|
||||||
|
|
||||||
def make_plugin_msg_extra(live_client: LiveClientType):
|
def iter_live_clients() -> Iterable[LiveClientType]:
|
||||||
room_key = live_client.room_key
|
return _live_client_manager.iter_live_clients()
|
||||||
|
|
||||||
|
|
||||||
|
def make_plugin_msg_extra_from_live_client(live_client: LiveClientType):
|
||||||
return {
|
return {
|
||||||
'roomId': live_client.room_id, # init_room之前是None
|
'roomId': live_client.room_id, # init_room之前是None
|
||||||
'roomKey': {
|
'roomKey': live_client.room_key.to_dict(),
|
||||||
'type': room_key.type,
|
}
|
||||||
'value': room_key.value,
|
|
||||||
},
|
|
||||||
|
def make_plugin_msg_extra_from_client_room(room: 'ClientRoom'):
|
||||||
|
room_key = room.room_key
|
||||||
|
live_client = _live_client_manager.get_live_client(room_key)
|
||||||
|
if live_client is not None:
|
||||||
|
room_id = live_client.room_id
|
||||||
|
else:
|
||||||
|
room_id = None
|
||||||
|
return {
|
||||||
|
'roomId': room_id, # init_room之前是None
|
||||||
|
'roomKey': room_key.to_dict(),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -92,6 +120,9 @@ class LiveClientManager:
|
|||||||
def get_live_client(self, room_key: RoomKey):
|
def get_live_client(self, room_key: RoomKey):
|
||||||
return self._live_clients.get(room_key, None)
|
return self._live_clients.get(room_key, None)
|
||||||
|
|
||||||
|
def iter_live_clients(self):
|
||||||
|
return self._live_clients.values()
|
||||||
|
|
||||||
def add_live_client(self, room_key: RoomKey):
|
def add_live_client(self, room_key: RoomKey):
|
||||||
if room_key in self._live_clients:
|
if room_key in self._live_clients:
|
||||||
return
|
return
|
||||||
@ -105,7 +136,9 @@ class LiveClientManager:
|
|||||||
|
|
||||||
logger.info('room=%s live client created, %d live clients', room_key, len(self._live_clients))
|
logger.info('room=%s live client created, %d live clients', room_key, len(self._live_clients))
|
||||||
|
|
||||||
services.plugin.broadcast_cmd_data(sdk_models.Command.ADD_ROOM, {}, make_plugin_msg_extra(live_client))
|
services.plugin.broadcast_cmd_data(
|
||||||
|
sdk_models.Command.ADD_ROOM, {}, make_plugin_msg_extra_from_live_client(live_client)
|
||||||
|
)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def _create_live_client(room_key: RoomKey):
|
def _create_live_client(room_key: RoomKey):
|
||||||
@ -131,7 +164,9 @@ class LiveClientManager:
|
|||||||
|
|
||||||
client_room_manager.del_room(room_key)
|
client_room_manager.del_room(room_key)
|
||||||
|
|
||||||
services.plugin.broadcast_cmd_data(sdk_models.Command.DEL_ROOM, {}, make_plugin_msg_extra(live_client))
|
services.plugin.broadcast_cmd_data(
|
||||||
|
sdk_models.Command.DEL_ROOM, {}, make_plugin_msg_extra_from_live_client(live_client)
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
RECONNECT_POLICY = dm_utils.make_linear_retry_policy(1, 2, 10)
|
RECONNECT_POLICY = dm_utils.make_linear_retry_policy(1, 2, 10)
|
||||||
@ -164,7 +199,7 @@ class WebLiveClient(blivedm.BLiveClient):
|
|||||||
services.plugin.broadcast_cmd_data(
|
services.plugin.broadcast_cmd_data(
|
||||||
sdk_models.Command.ROOM_INIT,
|
sdk_models.Command.ROOM_INIT,
|
||||||
{'isSuccess': True}, # 降级也算成功
|
{'isSuccess': True}, # 降级也算成功
|
||||||
make_plugin_msg_extra(self),
|
make_plugin_msg_extra_from_live_client(self),
|
||||||
)
|
)
|
||||||
|
|
||||||
# 允许降级
|
# 允许降级
|
||||||
@ -201,7 +236,7 @@ class OpenLiveClient(blivedm.OpenLiveClient):
|
|||||||
services.plugin.broadcast_cmd_data(
|
services.plugin.broadcast_cmd_data(
|
||||||
sdk_models.Command.ROOM_INIT,
|
sdk_models.Command.ROOM_INIT,
|
||||||
{'isSuccess': res},
|
{'isSuccess': res},
|
||||||
make_plugin_msg_extra(self),
|
make_plugin_msg_extra_from_live_client(self),
|
||||||
)
|
)
|
||||||
|
|
||||||
return res
|
return res
|
||||||
@ -318,6 +353,9 @@ class ClientRoomManager:
|
|||||||
def get_room(self, room_key: RoomKey):
|
def get_room(self, room_key: RoomKey):
|
||||||
return self._rooms.get(room_key, None)
|
return self._rooms.get(room_key, None)
|
||||||
|
|
||||||
|
def iter_rooms(self) -> Iterable['ClientRoom']:
|
||||||
|
return self._rooms.values()
|
||||||
|
|
||||||
def _get_or_add_room(self, room_key: RoomKey):
|
def _get_or_add_room(self, room_key: RoomKey):
|
||||||
room = self._rooms.get(room_key, None)
|
room = self._rooms.get(room_key, None)
|
||||||
if room is None:
|
if room is None:
|
||||||
@ -415,6 +453,10 @@ class ClientRoom:
|
|||||||
for client in filter(filterer, self._clients):
|
for client in filter(filterer, self._clients):
|
||||||
client.send_body_no_raise(body)
|
client.send_body_no_raise(body)
|
||||||
|
|
||||||
|
def send_body_no_raise(self, body):
|
||||||
|
for client in self._clients:
|
||||||
|
client.send_body_no_raise(body)
|
||||||
|
|
||||||
|
|
||||||
class LiveMsgHandler(blivedm.BaseHandler):
|
class LiveMsgHandler(blivedm.BaseHandler):
|
||||||
def on_client_stopped(self, client: LiveClientType, exception: Optional[Exception]):
|
def on_client_stopped(self, client: LiveClientType, exception: Optional[Exception]):
|
||||||
@ -486,7 +528,9 @@ class LiveMsgHandler(blivedm.BaseHandler):
|
|||||||
uid=message.uid
|
uid=message.uid
|
||||||
)
|
)
|
||||||
room.send_cmd_data(api.chat.Command.ADD_TEXT, data)
|
room.send_cmd_data(api.chat.Command.ADD_TEXT, data)
|
||||||
services.plugin.broadcast_cmd_data(sdk_models.Command.ADD_TEXT, data, make_plugin_msg_extra(client))
|
services.plugin.broadcast_cmd_data(
|
||||||
|
sdk_models.Command.ADD_TEXT, data, make_plugin_msg_extra_from_live_client(client)
|
||||||
|
)
|
||||||
|
|
||||||
if need_translate:
|
if need_translate:
|
||||||
await self._translate_and_response(message.msg, room.room_key, msg_id)
|
await self._translate_and_response(message.msg, room.room_key, msg_id)
|
||||||
@ -514,7 +558,9 @@ class LiveMsgHandler(blivedm.BaseHandler):
|
|||||||
'uid': message.uid
|
'uid': message.uid
|
||||||
}
|
}
|
||||||
room.send_cmd_data(api.chat.Command.ADD_GIFT, data)
|
room.send_cmd_data(api.chat.Command.ADD_GIFT, data)
|
||||||
services.plugin.broadcast_cmd_data(sdk_models.Command.ADD_GIFT, data, make_plugin_msg_extra(client))
|
services.plugin.broadcast_cmd_data(
|
||||||
|
sdk_models.Command.ADD_GIFT, data, make_plugin_msg_extra_from_live_client(client)
|
||||||
|
)
|
||||||
|
|
||||||
def _on_buy_guard(self, client: WebLiveClient, message: dm_web_models.GuardBuyMessage):
|
def _on_buy_guard(self, client: WebLiveClient, message: dm_web_models.GuardBuyMessage):
|
||||||
asyncio.create_task(self.__on_buy_guard(client, message))
|
asyncio.create_task(self.__on_buy_guard(client, message))
|
||||||
@ -537,7 +583,9 @@ class LiveMsgHandler(blivedm.BaseHandler):
|
|||||||
'uid': message.uid
|
'uid': message.uid
|
||||||
}
|
}
|
||||||
room.send_cmd_data(api.chat.Command.ADD_MEMBER, data)
|
room.send_cmd_data(api.chat.Command.ADD_MEMBER, data)
|
||||||
services.plugin.broadcast_cmd_data(sdk_models.Command.ADD_MEMBER, data, make_plugin_msg_extra(client))
|
services.plugin.broadcast_cmd_data(
|
||||||
|
sdk_models.Command.ADD_MEMBER, data, make_plugin_msg_extra_from_live_client(client)
|
||||||
|
)
|
||||||
|
|
||||||
def _on_super_chat(self, client: WebLiveClient, message: dm_web_models.SuperChatMessage):
|
def _on_super_chat(self, client: WebLiveClient, message: dm_web_models.SuperChatMessage):
|
||||||
avatar_url = services.avatar.process_avatar_url(message.face)
|
avatar_url = services.avatar.process_avatar_url(message.face)
|
||||||
@ -570,7 +618,9 @@ class LiveMsgHandler(blivedm.BaseHandler):
|
|||||||
'uid': message.uid
|
'uid': message.uid
|
||||||
}
|
}
|
||||||
room.send_cmd_data(api.chat.Command.ADD_SUPER_CHAT, data)
|
room.send_cmd_data(api.chat.Command.ADD_SUPER_CHAT, data)
|
||||||
services.plugin.broadcast_cmd_data(sdk_models.Command.ADD_SUPER_CHAT, data, make_plugin_msg_extra(client))
|
services.plugin.broadcast_cmd_data(
|
||||||
|
sdk_models.Command.ADD_SUPER_CHAT, data, make_plugin_msg_extra_from_live_client(client)
|
||||||
|
)
|
||||||
|
|
||||||
if need_translate:
|
if need_translate:
|
||||||
asyncio.create_task(self._translate_and_response(
|
asyncio.create_task(self._translate_and_response(
|
||||||
@ -586,7 +636,9 @@ class LiveMsgHandler(blivedm.BaseHandler):
|
|||||||
'ids': list(map(str, message.ids))
|
'ids': list(map(str, message.ids))
|
||||||
}
|
}
|
||||||
room.send_cmd_data(api.chat.Command.DEL_SUPER_CHAT, data)
|
room.send_cmd_data(api.chat.Command.DEL_SUPER_CHAT, data)
|
||||||
services.plugin.broadcast_cmd_data(sdk_models.Command.DEL_SUPER_CHAT, data, make_plugin_msg_extra(client))
|
services.plugin.broadcast_cmd_data(
|
||||||
|
sdk_models.Command.DEL_SUPER_CHAT, data, make_plugin_msg_extra_from_live_client(client)
|
||||||
|
)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def _need_translate(text, room: ClientRoom, client: LiveClientType):
|
def _need_translate(text, room: ClientRoom, client: LiveClientType):
|
||||||
@ -615,11 +667,9 @@ class LiveMsgHandler(blivedm.BaseHandler):
|
|||||||
data
|
data
|
||||||
)
|
)
|
||||||
|
|
||||||
live_client = _live_client_manager.get_live_client(room_key)
|
services.plugin.broadcast_cmd_data(
|
||||||
if live_client is not None:
|
sdk_models.Command.UPDATE_TRANSLATION, data, make_plugin_msg_extra_from_client_room(room)
|
||||||
services.plugin.broadcast_cmd_data(
|
)
|
||||||
sdk_models.Command.UPDATE_TRANSLATION, data, make_plugin_msg_extra(live_client)
|
|
||||||
)
|
|
||||||
|
|
||||||
#
|
#
|
||||||
# 开放平台消息
|
# 开放平台消息
|
||||||
@ -675,7 +725,9 @@ class LiveMsgHandler(blivedm.BaseHandler):
|
|||||||
uid=message.uid
|
uid=message.uid
|
||||||
)
|
)
|
||||||
room.send_cmd_data(api.chat.Command.ADD_TEXT, data)
|
room.send_cmd_data(api.chat.Command.ADD_TEXT, data)
|
||||||
services.plugin.broadcast_cmd_data(sdk_models.Command.ADD_TEXT, data, make_plugin_msg_extra(client))
|
services.plugin.broadcast_cmd_data(
|
||||||
|
sdk_models.Command.ADD_TEXT, data, make_plugin_msg_extra_from_live_client(client)
|
||||||
|
)
|
||||||
|
|
||||||
if need_translate:
|
if need_translate:
|
||||||
asyncio.create_task(self._translate_and_response(message.msg, room.room_key, message.msg_id))
|
asyncio.create_task(self._translate_and_response(message.msg, room.room_key, message.msg_id))
|
||||||
@ -703,7 +755,9 @@ class LiveMsgHandler(blivedm.BaseHandler):
|
|||||||
'uid': message.uid
|
'uid': message.uid
|
||||||
}
|
}
|
||||||
room.send_cmd_data(api.chat.Command.ADD_GIFT, data)
|
room.send_cmd_data(api.chat.Command.ADD_GIFT, data)
|
||||||
services.plugin.broadcast_cmd_data(sdk_models.Command.ADD_GIFT, data, make_plugin_msg_extra(client))
|
services.plugin.broadcast_cmd_data(
|
||||||
|
sdk_models.Command.ADD_GIFT, data, make_plugin_msg_extra_from_live_client(client)
|
||||||
|
)
|
||||||
|
|
||||||
def _on_open_live_buy_guard(self, client: OpenLiveClient, message: dm_open_models.GuardBuyMessage):
|
def _on_open_live_buy_guard(self, client: OpenLiveClient, message: dm_open_models.GuardBuyMessage):
|
||||||
avatar_url = message.user_info.uface
|
avatar_url = message.user_info.uface
|
||||||
@ -722,7 +776,9 @@ class LiveMsgHandler(blivedm.BaseHandler):
|
|||||||
'uid': message.user_info.uid
|
'uid': message.user_info.uid
|
||||||
}
|
}
|
||||||
room.send_cmd_data(api.chat.Command.ADD_MEMBER, data)
|
room.send_cmd_data(api.chat.Command.ADD_MEMBER, data)
|
||||||
services.plugin.broadcast_cmd_data(sdk_models.Command.ADD_MEMBER, data, make_plugin_msg_extra(client))
|
services.plugin.broadcast_cmd_data(
|
||||||
|
sdk_models.Command.ADD_MEMBER, data, make_plugin_msg_extra_from_live_client(client)
|
||||||
|
)
|
||||||
|
|
||||||
def _on_open_live_super_chat(self, client: OpenLiveClient, message: dm_open_models.SuperChatMessage):
|
def _on_open_live_super_chat(self, client: OpenLiveClient, message: dm_open_models.SuperChatMessage):
|
||||||
avatar_url = services.avatar.process_avatar_url(message.uface)
|
avatar_url = services.avatar.process_avatar_url(message.uface)
|
||||||
@ -755,7 +811,9 @@ class LiveMsgHandler(blivedm.BaseHandler):
|
|||||||
'uid': message.uid
|
'uid': message.uid
|
||||||
}
|
}
|
||||||
room.send_cmd_data(api.chat.Command.ADD_SUPER_CHAT, data)
|
room.send_cmd_data(api.chat.Command.ADD_SUPER_CHAT, data)
|
||||||
services.plugin.broadcast_cmd_data(sdk_models.Command.ADD_SUPER_CHAT, data, make_plugin_msg_extra(client))
|
services.plugin.broadcast_cmd_data(
|
||||||
|
sdk_models.Command.ADD_SUPER_CHAT, data, make_plugin_msg_extra_from_live_client(client)
|
||||||
|
)
|
||||||
|
|
||||||
if need_translate:
|
if need_translate:
|
||||||
asyncio.create_task(self._translate_and_response(
|
asyncio.create_task(self._translate_and_response(
|
||||||
@ -771,4 +829,6 @@ class LiveMsgHandler(blivedm.BaseHandler):
|
|||||||
'ids': list(map(str, message.message_ids))
|
'ids': list(map(str, message.message_ids))
|
||||||
}
|
}
|
||||||
room.send_cmd_data(api.chat.Command.DEL_SUPER_CHAT, data)
|
room.send_cmd_data(api.chat.Command.DEL_SUPER_CHAT, data)
|
||||||
services.plugin.broadcast_cmd_data(sdk_models.Command.DEL_SUPER_CHAT, data, make_plugin_msg_extra(client))
|
services.plugin.broadcast_cmd_data(
|
||||||
|
sdk_models.Command.DEL_SUPER_CHAT, data, make_plugin_msg_extra_from_live_client(client)
|
||||||
|
)
|
||||||
|
@ -75,6 +75,7 @@ def iter_plugins() -> Iterable['Plugin']:
|
|||||||
def get_plugin_by_token(token):
|
def get_plugin_by_token(token):
|
||||||
if token == '':
|
if token == '':
|
||||||
return None
|
return None
|
||||||
|
# 应该最多就十几个插件吧,偷懒用遍历了
|
||||||
for plugin in _plugins.values():
|
for plugin in _plugins.values():
|
||||||
if plugin.token == token:
|
if plugin.token == token:
|
||||||
return plugin
|
return plugin
|
||||||
|
Loading…
Reference in New Issue
Block a user