mirror of
https://github.com/xfgryujk/blivechat.git
synced 2025-04-17 23:12:39 +08:00
前端支持使用身份码
This commit is contained in:
parent
cad573312b
commit
68f8ab3a92
api
frontend/src
services
@ -63,7 +63,6 @@ def make_text_message_data(
|
||||
translation: str = '',
|
||||
content_type: int = ContentType.TEXT,
|
||||
content_type_params: list = None,
|
||||
text_emoticons: Iterable[Tuple[str, str]] = None
|
||||
):
|
||||
# 为了节省带宽用list而不是dict
|
||||
return [
|
||||
@ -98,7 +97,7 @@ def make_text_message_data(
|
||||
# 14: contentTypeParams
|
||||
content_type_params if content_type_params is not None else [],
|
||||
# 15: textEmoticons
|
||||
text_emoticons if text_emoticons is not None else [],
|
||||
[], # 已废弃,保留
|
||||
]
|
||||
|
||||
|
||||
@ -295,13 +294,11 @@ class ChatHandler(tornado.websocket.WebSocketHandler):
|
||||
self.send_cmd_data(Command.ADD_TEXT, text_data)
|
||||
text_data[4] = 'te[dog]st'
|
||||
text_data[11] = uuid.uuid4().hex
|
||||
text_data[15] = [('[dog]', 'http://i0.hdslb.com/bfs/live/4428c84e694fbf4e0ef6c06e958d9352c3582740.png')]
|
||||
self.send_cmd_data(Command.ADD_TEXT, text_data)
|
||||
text_data[2] = '主播'
|
||||
text_data[3] = 3
|
||||
text_data[4] = "I can eat glass, it doesn't hurt me."
|
||||
text_data[11] = uuid.uuid4().hex
|
||||
text_data[15] = []
|
||||
self.send_cmd_data(Command.ADD_TEXT, text_data)
|
||||
self.send_cmd_data(Command.ADD_MEMBER, member_data)
|
||||
self.send_cmd_data(Command.ADD_SUPER_CHAT, sc_data)
|
||||
|
@ -42,20 +42,14 @@ class BusinessError(Exception):
|
||||
return self.data['code']
|
||||
|
||||
|
||||
async def request_open_live_or_common_server(open_live_url, common_server_url, body: Union[dict, str, bytes]) -> dict:
|
||||
async def request_open_live_or_common_server(open_live_url, common_server_url, body: dict) -> dict:
|
||||
"""如果配置了开放平台,则直接请求,否则转发请求到公共服务器的内部接口"""
|
||||
cfg = config.get_config()
|
||||
if cfg.is_open_live_configured:
|
||||
return await _request_open_live(open_live_url, body)
|
||||
|
||||
post_params = {'headers': {'Content-Type': 'application/json'}}
|
||||
if isinstance(body, dict):
|
||||
post_params['json'] = body
|
||||
else:
|
||||
post_params['data'] = body
|
||||
req_ctx_mgr = utils.request.http_session.post(common_server_url, **post_params)
|
||||
|
||||
try:
|
||||
req_ctx_mgr = utils.request.http_session.post(common_server_url, json=body)
|
||||
return await _read_response(req_ctx_mgr)
|
||||
except TransportError:
|
||||
logger.exception('Request common server failed:')
|
||||
@ -65,17 +59,11 @@ async def request_open_live_or_common_server(open_live_url, common_server_url, b
|
||||
raise
|
||||
|
||||
|
||||
async def _request_open_live(url, body: Union[dict, str, bytes]) -> dict:
|
||||
async def _request_open_live(url, body: dict) -> dict:
|
||||
cfg = config.get_config()
|
||||
assert cfg.is_open_live_configured
|
||||
|
||||
if isinstance(body, dict):
|
||||
body_bytes = json.dumps(body).encode('utf-8')
|
||||
elif isinstance(body, str):
|
||||
body_bytes = body.encode('utf-8')
|
||||
else:
|
||||
body_bytes = body
|
||||
|
||||
body_bytes = json.dumps(body).encode('utf-8')
|
||||
headers = {
|
||||
'x-bili-accesskeyid': cfg.open_live_access_key_id,
|
||||
'x-bili-content-md5': hashlib.md5(body_bytes).hexdigest(),
|
||||
@ -96,9 +84,9 @@ async def _request_open_live(url, body: Union[dict, str, bytes]) -> dict:
|
||||
|
||||
headers['Content-Type'] = 'application/json'
|
||||
headers['Accept'] = 'application/json'
|
||||
req_ctx_mgr = utils.request.http_session.post(url, headers=headers, data=body_bytes)
|
||||
|
||||
try:
|
||||
req_ctx_mgr = utils.request.http_session.post(url, headers=headers, data=body_bytes)
|
||||
return await _read_response(req_ctx_mgr)
|
||||
except TransportError:
|
||||
logger.exception('Request open live failed:')
|
||||
@ -124,9 +112,13 @@ async def _read_response(req_ctx_mgr: AsyncContextManager[aiohttp.ClientResponse
|
||||
class _OpenLiveHandlerBase(api.base.ApiHandler):
|
||||
def prepare(self):
|
||||
super().prepare()
|
||||
# 做一些简单的检查
|
||||
if not isinstance(self.json_args, dict):
|
||||
raise tornado.web.MissingArgumentError('body')
|
||||
|
||||
if 'app_id' in self.json_args:
|
||||
cfg = config.get_config()
|
||||
self.json_args['app_id'] = cfg.open_live_app_id
|
||||
|
||||
logger.info('client=%s requesting open live, cls=%s', self.request.remote_ip, type(self).__name__)
|
||||
|
||||
|
||||
@ -138,7 +130,7 @@ class _PublicHandlerBase(_OpenLiveHandlerBase):
|
||||
async def post(self):
|
||||
try:
|
||||
res = await request_open_live_or_common_server(
|
||||
self._OPEN_LIVE_URL, self._COMMON_SERVER_URL, self.request.body
|
||||
self._OPEN_LIVE_URL, self._COMMON_SERVER_URL, self.json_args
|
||||
)
|
||||
except TransportError:
|
||||
raise tornado.web.HTTPError(500)
|
||||
@ -157,7 +149,7 @@ class _PrivateHandlerBase(_OpenLiveHandlerBase):
|
||||
raise tornado.web.HTTPError(501)
|
||||
|
||||
try:
|
||||
res = await _request_open_live(self._OPEN_LIVE_URL, self.request.body)
|
||||
res = await _request_open_live(self._OPEN_LIVE_URL, self.json_args)
|
||||
except TransportError:
|
||||
raise tornado.web.HTTPError(500)
|
||||
except BusinessError as e:
|
||||
|
@ -13,8 +13,8 @@ const CONTENT_TYPE_EMOTICON = 1
|
||||
const RECEIVE_TIMEOUT = 15 * 1000
|
||||
|
||||
export default class ChatClientRelay {
|
||||
constructor(roomId, autoTranslate) {
|
||||
this.roomId = roomId
|
||||
constructor(roomKey, autoTranslate) {
|
||||
this.roomKey = roomKey
|
||||
this.autoTranslate = autoTranslate
|
||||
|
||||
this.onAddText = null
|
||||
@ -58,7 +58,7 @@ export default class ChatClientRelay {
|
||||
this.websocket.send(JSON.stringify({
|
||||
cmd: COMMAND_JOIN_ROOM,
|
||||
data: {
|
||||
roomId: this.roomId,
|
||||
roomKey: this.roomKey,
|
||||
config: {
|
||||
autoTranslate: this.autoTranslate
|
||||
}
|
||||
|
@ -9,9 +9,12 @@ export default {
|
||||
home: {
|
||||
roomIdEmpty: "Room ID can't be empty",
|
||||
roomIdInteger: 'Room ID must be positive integer',
|
||||
authCodeEmpty: "Identity code can't be empty",
|
||||
|
||||
general: 'General',
|
||||
room: 'Room',
|
||||
roomId: 'Room ID',
|
||||
authCode: 'Identity code',
|
||||
showDanmaku: 'Show messages',
|
||||
showGift: 'Show Super Chats',
|
||||
showGiftName: 'Show gift name',
|
||||
|
@ -9,9 +9,12 @@ export default {
|
||||
home: {
|
||||
roomIdEmpty: 'ルームのIDを空白にすることはできません',
|
||||
roomIdInteger: 'ルームは正の整数でなければなりません',
|
||||
authCodeEmpty: 'アイデンティティコードを空白にすることはできません',
|
||||
|
||||
general: '常規',
|
||||
room: 'ルーム',
|
||||
roomId: 'ルームID',
|
||||
authCode: 'アイデンティティコード',
|
||||
showDanmaku: 'コメントを表示する',
|
||||
showGift: 'スーパーチャットと新メンバーを表示する',
|
||||
showGiftName: 'ギフト名を表示する',
|
||||
|
@ -9,9 +9,12 @@ export default {
|
||||
home: {
|
||||
roomIdEmpty: '房间ID不能为空',
|
||||
roomIdInteger: '房间ID必须为正整数',
|
||||
authCodeEmpty: '身份码不能为空',
|
||||
|
||||
general: '常规',
|
||||
room: '房间',
|
||||
roomId: '房间ID',
|
||||
authCode: '身份码',
|
||||
showDanmaku: '显示弹幕',
|
||||
showGift: '显示打赏和新舰长',
|
||||
showGiftName: '显示礼物名',
|
||||
|
@ -77,15 +77,22 @@ const router = new VueRouter({
|
||||
props: route => ({ strConfig: route.query })
|
||||
},
|
||||
{
|
||||
path: '/room/:roomId',
|
||||
path: '/room/:roomKeyValue',
|
||||
name: 'room',
|
||||
component: Room,
|
||||
props(route) {
|
||||
let roomId = parseInt(route.params.roomId)
|
||||
if (isNaN(roomId)) {
|
||||
roomId = null
|
||||
let roomKeyType = parseInt(route.query.roomKeyType) || 1
|
||||
if (roomKeyType < 1 || roomKeyType > 2) {
|
||||
roomKeyType = 1
|
||||
}
|
||||
return { roomId, strConfig: route.query }
|
||||
|
||||
let roomKeyValue = route.params.roomKeyValue
|
||||
if (roomKeyType === 1) {
|
||||
roomKeyValue = parseInt(roomKeyValue) || null
|
||||
} else {
|
||||
roomKeyValue = roomKeyValue || null
|
||||
}
|
||||
return { roomKeyType, roomKeyValue, strConfig: route.query }
|
||||
}
|
||||
},
|
||||
{ path: '*', component: NotFound }
|
||||
|
@ -1,16 +1,31 @@
|
||||
<template>
|
||||
<div>
|
||||
<p>
|
||||
<el-form :model="form" ref="form" label-width="150px" :rules="{
|
||||
roomId: [
|
||||
{required: true, message: $t('home.roomIdEmpty'), trigger: 'blur'},
|
||||
{type: 'integer', min: 1, message: $t('home.roomIdInteger'), trigger: 'blur'}
|
||||
]
|
||||
}">
|
||||
<el-form :model="form" ref="form" label-width="150px">
|
||||
<el-tabs type="border-card">
|
||||
<el-tab-pane :label="$t('home.general')">
|
||||
<el-form-item :label="$t('home.roomId')" required prop="roomId">
|
||||
<el-input v-model.number="form.roomId" type="number" min="1"></el-input>
|
||||
<el-form-item :label="$t('home.room')" required :prop="form.roomKeyType === 1 ? 'roomId' : 'authCode'">
|
||||
<el-row>
|
||||
<el-col :span="6">
|
||||
<el-select v-model="form.roomKeyType" style="width: 100%">
|
||||
<el-option :label="$t('home.authCode')" :value="2"></el-option>
|
||||
<el-option :label="$t('home.roomId')" :value="1"></el-option>
|
||||
</el-select>
|
||||
</el-col>
|
||||
<el-col :span="18">
|
||||
<el-input v-if="form.roomKeyType === 1"
|
||||
v-model.number="form.roomId" type="number" min="1" :rules="[
|
||||
{required: true, message: $t('home.roomIdEmpty'), trigger: 'blur'},
|
||||
{type: 'integer', min: 1, message: $t('home.roomIdInteger'), trigger: 'blur'}
|
||||
]"
|
||||
></el-input>
|
||||
<el-input v-else
|
||||
v-model.number="form.authCode" :rules="[
|
||||
{required: true, message: $t('home.authCodeEmpty'), trigger: 'blur'}
|
||||
]"
|
||||
></el-input>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-form-item>
|
||||
<el-row :gutter="20">
|
||||
<el-col :xs="24" :sm="8">
|
||||
@ -184,11 +199,20 @@ export default {
|
||||
},
|
||||
form: {
|
||||
...chatConfig.getLocalConfig(),
|
||||
roomId: parseInt(window.localStorage.roomId || '1')
|
||||
roomKeyType: parseInt(window.localStorage.roomKeyType || '2'),
|
||||
roomId: parseInt(window.localStorage.roomId || '1'),
|
||||
authCode: window.localStorage.authCode || '',
|
||||
}
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
roomKeyValue() {
|
||||
if (this.form.roomKeyType === 1) {
|
||||
return this.form.roomId
|
||||
} else {
|
||||
return this.form.authCode
|
||||
}
|
||||
},
|
||||
roomUrl() {
|
||||
return this.getRoomUrl(false)
|
||||
},
|
||||
@ -206,7 +230,9 @@ export default {
|
||||
},
|
||||
watch: {
|
||||
roomUrl: _.debounce(function() {
|
||||
window.localStorage.roomKeyType = this.form.roomKeyType
|
||||
window.localStorage.roomId = this.form.roomId
|
||||
window.localStorage.authCode = this.form.authCode
|
||||
chatConfig.setLocalConfig(this.form)
|
||||
}, 500)
|
||||
},
|
||||
@ -256,13 +282,13 @@ export default {
|
||||
},
|
||||
|
||||
enterRoom() {
|
||||
window.open(this.roomUrl, `room ${this.form.roomId}`, 'menubar=0,location=0,scrollbars=0,toolbar=0,width=600,height=600')
|
||||
window.open(this.roomUrl, `room ${this.roomKeyValue}`, 'menubar=0,location=0,scrollbars=0,toolbar=0,width=600,height=600')
|
||||
},
|
||||
enterTestRoom() {
|
||||
window.open(this.getRoomUrl(true), 'test room', 'menubar=0,location=0,scrollbars=0,toolbar=0,width=600,height=600')
|
||||
},
|
||||
getRoomUrl(isTestRoom) {
|
||||
if (!isTestRoom && this.form.roomId === '') {
|
||||
if (!isTestRoom && !this.roomKeyValue) {
|
||||
return ''
|
||||
}
|
||||
|
||||
@ -272,12 +298,13 @@ export default {
|
||||
lang: this.$i18n.locale
|
||||
}
|
||||
delete query.roomId
|
||||
delete query.authCode
|
||||
|
||||
let resolved
|
||||
if (isTestRoom) {
|
||||
resolved = this.$router.resolve({ name: 'test_room', query })
|
||||
} else {
|
||||
resolved = this.$router.resolve({ name: 'room', params: { roomId: this.form.roomId }, query })
|
||||
resolved = this.$router.resolve({ name: 'room', params: { roomKeyValue: this.roomKeyValue }, query })
|
||||
}
|
||||
return `${window.location.protocol}//${window.location.host}${resolved.href}`
|
||||
},
|
||||
@ -314,7 +341,9 @@ export default {
|
||||
chatConfig.sanitizeConfig(cfg)
|
||||
this.form = {
|
||||
...cfg,
|
||||
roomId: this.form.roomId
|
||||
roomKeyType: this.form.roomKeyType,
|
||||
roomId: this.form.roomId,
|
||||
authCode: this.form.authCode
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -21,8 +21,12 @@ export default {
|
||||
ChatRenderer
|
||||
},
|
||||
props: {
|
||||
roomId: {
|
||||
roomKeyType: {
|
||||
type: Number,
|
||||
default: 1
|
||||
},
|
||||
roomKeyValue: {
|
||||
type: [Number, String],
|
||||
default: null
|
||||
},
|
||||
strConfig: {
|
||||
@ -139,13 +143,20 @@ export default {
|
||||
}
|
||||
},
|
||||
initChatClient() {
|
||||
if (this.roomId === null) {
|
||||
if (this.roomKeyValue === null) {
|
||||
this.chatClient = new ChatClientTest()
|
||||
} else if (this.config.relayMessagesByServer) {
|
||||
let roomKey = {
|
||||
type: this.roomKeyType,
|
||||
value: this.roomKeyValue
|
||||
}
|
||||
this.chatClient = new ChatClientRelay(roomKey, this.config.autoTranslate)
|
||||
} else {
|
||||
if (!this.config.relayMessagesByServer) {
|
||||
this.chatClient = new ChatClientDirect(this.roomId)
|
||||
if (this.roomKeyType === 1) {
|
||||
this.chatClient = new ChatClientDirect(this.roomKeyValue)
|
||||
} else {
|
||||
this.chatClient = new ChatClientRelay(this.roomId, this.config.autoTranslate)
|
||||
// TODO 支持authCode
|
||||
// this.chatClient = new ChatClientDirect(this.roomKeyValue)
|
||||
}
|
||||
}
|
||||
this.chatClient.onAddText = this.onAddText
|
||||
|
270
services/chat.py
270
services/chat.py
@ -1,9 +1,6 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
import asyncio
|
||||
import base64
|
||||
import binascii
|
||||
import enum
|
||||
import json
|
||||
import logging
|
||||
import uuid
|
||||
from typing import *
|
||||
@ -11,8 +8,8 @@ from typing import *
|
||||
import api.chat
|
||||
import api.open_live as api_open_live
|
||||
import blivedm.blivedm as blivedm
|
||||
import blivedm.blivedm.models.open_live as dm_open_models
|
||||
import blivedm.blivedm.models.web as dm_web_models
|
||||
import blivedm.blivedm.models.pb as dm_pb_models
|
||||
import config
|
||||
import services.avatar
|
||||
import services.translate
|
||||
@ -368,106 +365,13 @@ class ClientRoom:
|
||||
|
||||
|
||||
class LiveMsgHandler(blivedm.BaseHandler):
|
||||
# 重新定义XXX_callback是为了减少对字段名的依赖,防止B站改字段名
|
||||
def __danmu_msg_callback(self, client: LiveClientType, command: dict):
|
||||
info = command['info']
|
||||
dm_v2 = command.get('dm_v2', '')
|
||||
|
||||
proto: Optional[dm_pb_models.SimpleDm] = None
|
||||
if dm_v2 != '':
|
||||
try:
|
||||
proto = dm_pb_models.SimpleDm.loads(base64.b64decode(dm_v2))
|
||||
except (binascii.Error, KeyError, TypeError, ValueError):
|
||||
pass
|
||||
if proto is not None:
|
||||
face = proto.user.face
|
||||
else:
|
||||
face = ''
|
||||
|
||||
if len(info[3]) != 0:
|
||||
medal_level = info[3][0]
|
||||
medal_room_id = info[3][3]
|
||||
else:
|
||||
medal_level = 0
|
||||
medal_room_id = 0
|
||||
|
||||
message = dm_web_models.DanmakuMessage(
|
||||
timestamp=info[0][4],
|
||||
msg_type=info[0][9],
|
||||
dm_type=info[0][12],
|
||||
emoticon_options=info[0][13],
|
||||
mode_info=info[0][15],
|
||||
|
||||
msg=info[1],
|
||||
|
||||
uid=info[2][0],
|
||||
uname=info[2][1],
|
||||
face=face,
|
||||
admin=info[2][2],
|
||||
urank=info[2][5],
|
||||
mobile_verify=info[2][6],
|
||||
|
||||
medal_level=medal_level,
|
||||
medal_room_id=medal_room_id,
|
||||
|
||||
user_level=info[4][0],
|
||||
|
||||
privilege_type=info[7],
|
||||
)
|
||||
return self._on_danmaku(client, message)
|
||||
|
||||
def __send_gift_callback(self, client: LiveClientType, command: dict):
|
||||
data = command['data']
|
||||
message = dm_web_models.GiftMessage(
|
||||
gift_name=data['giftName'],
|
||||
num=data['num'],
|
||||
uname=data['uname'],
|
||||
face=data['face'],
|
||||
uid=data['uid'],
|
||||
timestamp=data['timestamp'],
|
||||
coin_type=data['coin_type'],
|
||||
total_coin=data['total_coin'],
|
||||
)
|
||||
return self._on_gift(client, message)
|
||||
|
||||
def __guard_buy_callback(self, client: LiveClientType, command: dict):
|
||||
data = command['data']
|
||||
message = dm_web_models.GuardBuyMessage(
|
||||
uid=data['uid'],
|
||||
username=data['username'],
|
||||
guard_level=data['guard_level'],
|
||||
start_time=data['start_time'],
|
||||
)
|
||||
return self._on_buy_guard(client, message)
|
||||
|
||||
def __super_chat_message_callback(self, client: LiveClientType, command: dict):
|
||||
data = command['data']
|
||||
message = dm_web_models.SuperChatMessage(
|
||||
price=data['price'],
|
||||
message=data['message'],
|
||||
start_time=data['start_time'],
|
||||
id=data['id'],
|
||||
uid=data['uid'],
|
||||
uname=data['user_info']['uname'],
|
||||
face=data['user_info']['face'],
|
||||
)
|
||||
return self._on_super_chat(client, message)
|
||||
|
||||
_CMD_CALLBACK_DICT = {
|
||||
**blivedm.BaseHandler._CMD_CALLBACK_DICT,
|
||||
'DANMU_MSG': __danmu_msg_callback,
|
||||
'SEND_GIFT': __send_gift_callback,
|
||||
'GUARD_BUY': __guard_buy_callback,
|
||||
'SUPER_CHAT_MESSAGE': __super_chat_message_callback
|
||||
}
|
||||
|
||||
def on_client_stopped(self, client: LiveClientType, exception: Optional[Exception]):
|
||||
_live_client_manager.del_live_client(client.room_key)
|
||||
|
||||
def _on_danmaku(self, client: LiveClientType, message: dm_web_models.DanmakuMessage):
|
||||
def _on_danmaku(self, client: WebLiveClient, message: dm_web_models.DanmakuMessage):
|
||||
asyncio.create_task(self.__on_danmaku(client, message))
|
||||
|
||||
async def __on_danmaku(self, client: LiveClientType, message: dm_web_models.DanmakuMessage):
|
||||
async def __on_danmaku(self, client: WebLiveClient, message: dm_web_models.DanmakuMessage):
|
||||
avatar_url = message.face
|
||||
if avatar_url != '':
|
||||
services.avatar.update_avatar_cache_if_expired(message.uid, avatar_url)
|
||||
@ -497,8 +401,6 @@ class LiveMsgHandler(blivedm.BaseHandler):
|
||||
content_type = api.chat.ContentType.TEXT
|
||||
content_type_params = None
|
||||
|
||||
text_emoticons = self._parse_text_emoticons(message)
|
||||
|
||||
need_translate = (
|
||||
content_type != api.chat.ContentType.EMOTICON and self._need_translate(message.msg, room, client)
|
||||
)
|
||||
@ -529,30 +431,12 @@ class LiveMsgHandler(blivedm.BaseHandler):
|
||||
translation=translation,
|
||||
content_type=content_type,
|
||||
content_type_params=content_type_params,
|
||||
text_emoticons=text_emoticons,
|
||||
))
|
||||
|
||||
if need_translate:
|
||||
await self._translate_and_response(message.msg, room.room_key, msg_id)
|
||||
|
||||
@staticmethod
|
||||
def _parse_text_emoticons(message: dm_web_models.DanmakuMessage):
|
||||
try:
|
||||
extra = json.loads(message.mode_info['extra'])
|
||||
# {"[dog]":{"emoticon_id":208,"emoji":"[dog]","descript":"[dog]","url":"http://i0.hdslb.com/bfs/live/4428c8
|
||||
# 4e694fbf4e0ef6c06e958d9352c3582740.png","width":20,"height":20,"emoticon_unique":"emoji_208","count":1}}
|
||||
emoticons = extra['emots']
|
||||
if emoticons is None:
|
||||
return []
|
||||
res = [
|
||||
(emoticon['descript'], emoticon['url'])
|
||||
for emoticon in emoticons.values()
|
||||
]
|
||||
return res
|
||||
except (json.JSONDecodeError, TypeError, KeyError):
|
||||
return []
|
||||
|
||||
def _on_gift(self, client: LiveClientType, message: dm_web_models.GiftMessage):
|
||||
def _on_gift(self, client: WebLiveClient, message: dm_web_models.GiftMessage):
|
||||
avatar_url = services.avatar.process_avatar_url(message.face)
|
||||
services.avatar.update_avatar_cache_if_expired(message.uid, avatar_url)
|
||||
|
||||
@ -574,11 +458,11 @@ class LiveMsgHandler(blivedm.BaseHandler):
|
||||
'num': message.num
|
||||
})
|
||||
|
||||
def _on_buy_guard(self, client: LiveClientType, 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))
|
||||
|
||||
@staticmethod
|
||||
async def __on_buy_guard(client: LiveClientType, message: dm_web_models.GuardBuyMessage):
|
||||
async def __on_buy_guard(client: WebLiveClient, message: dm_web_models.GuardBuyMessage):
|
||||
# 先异步调用再获取房间,因为返回时房间可能已经不存在了
|
||||
avatar_url = await services.avatar.get_avatar_url(message.uid)
|
||||
|
||||
@ -594,7 +478,7 @@ class LiveMsgHandler(blivedm.BaseHandler):
|
||||
'privilegeType': message.guard_level
|
||||
})
|
||||
|
||||
def _on_super_chat(self, client: LiveClientType, 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)
|
||||
services.avatar.update_avatar_cache_if_expired(message.uid, avatar_url)
|
||||
|
||||
@ -629,7 +513,7 @@ class LiveMsgHandler(blivedm.BaseHandler):
|
||||
message.message, room.room_key, msg_id, services.translate.Priority.HIGH
|
||||
))
|
||||
|
||||
def _on_super_chat_delete(self, client: LiveClientType, message: dm_web_models.SuperChatDeleteMessage):
|
||||
def _on_super_chat_delete(self, client: WebLiveClient, message: dm_web_models.SuperChatDeleteMessage):
|
||||
room = client_room_manager.get_room(client.room_key)
|
||||
if room is None:
|
||||
return
|
||||
@ -667,4 +551,140 @@ class LiveMsgHandler(blivedm.BaseHandler):
|
||||
)
|
||||
)
|
||||
|
||||
# TODO 开放平台消息处理
|
||||
#
|
||||
# 开放平台消息
|
||||
#
|
||||
|
||||
def _on_open_live_danmaku(self, client: OpenLiveClient, message: dm_open_models.DanmakuMessage):
|
||||
avatar_url = message.uface
|
||||
services.avatar.update_avatar_cache_if_expired(message.uid, avatar_url)
|
||||
|
||||
room = client_room_manager.get_room(client.room_key)
|
||||
if room is None:
|
||||
return
|
||||
|
||||
if message.uid == client.room_owner_uid:
|
||||
author_type = 3 # 主播
|
||||
elif message.guard_level != 0: # 1总督,2提督,3舰长
|
||||
author_type = 1 # 舰队
|
||||
else:
|
||||
author_type = 0
|
||||
|
||||
if message.dm_type == 1:
|
||||
content_type = api.chat.ContentType.EMOTICON
|
||||
content_type_params = api.chat.make_emoticon_params(message.emoji_img_url)
|
||||
else:
|
||||
content_type = api.chat.ContentType.TEXT
|
||||
content_type_params = None
|
||||
|
||||
need_translate = (
|
||||
content_type != api.chat.ContentType.EMOTICON and self._need_translate(message.msg, room, client)
|
||||
)
|
||||
if need_translate:
|
||||
translation = services.translate.get_translation_from_cache(message.msg)
|
||||
if translation is None:
|
||||
# 没有缓存,需要后面异步翻译后通知
|
||||
translation = ''
|
||||
else:
|
||||
need_translate = False
|
||||
else:
|
||||
translation = ''
|
||||
|
||||
room.send_cmd_data(api.chat.Command.ADD_TEXT, api.chat.make_text_message_data(
|
||||
avatar_url=avatar_url,
|
||||
timestamp=message.timestamp,
|
||||
author_name=message.uname,
|
||||
author_type=author_type,
|
||||
content=message.msg,
|
||||
privilege_type=message.guard_level,
|
||||
medal_level=0 if not message.fans_medal_wearing_status else message.fans_medal_level,
|
||||
id_=message.msg_id,
|
||||
translation=translation,
|
||||
content_type=content_type,
|
||||
content_type_params=content_type_params,
|
||||
))
|
||||
|
||||
if need_translate:
|
||||
asyncio.create_task(self._translate_and_response(message.msg, room.room_key, message.msg_id))
|
||||
|
||||
def _on_open_live_gift(self, client: OpenLiveClient, message: dm_open_models.GiftMessage):
|
||||
avatar_url = services.avatar.process_avatar_url(message.uface)
|
||||
services.avatar.update_avatar_cache_if_expired(message.uid, avatar_url)
|
||||
|
||||
# 丢人
|
||||
if not message.paid:
|
||||
return
|
||||
|
||||
room = client_room_manager.get_room(client.room_key)
|
||||
if room is None:
|
||||
return
|
||||
|
||||
room.send_cmd_data(api.chat.Command.ADD_GIFT, {
|
||||
'id': message.msg_id,
|
||||
'avatarUrl': avatar_url,
|
||||
'timestamp': message.timestamp,
|
||||
'authorName': message.uname,
|
||||
'totalCoin': message.price,
|
||||
'giftName': message.gift_name,
|
||||
'num': message.gift_num
|
||||
})
|
||||
|
||||
def _on_open_live_buy_guard(self, client: OpenLiveClient, message: dm_open_models.GuardBuyMessage):
|
||||
avatar_url = message.user_info.uface
|
||||
services.avatar.update_avatar_cache_if_expired(message.user_info.uid, avatar_url)
|
||||
|
||||
room = client_room_manager.get_room(client.room_key)
|
||||
if room is None:
|
||||
return
|
||||
|
||||
room.send_cmd_data(api.chat.Command.ADD_MEMBER, {
|
||||
'id': message.msg_id,
|
||||
'avatarUrl': avatar_url,
|
||||
'timestamp': message.timestamp,
|
||||
'authorName': message.user_info.uname,
|
||||
'privilegeType': message.guard_level
|
||||
})
|
||||
|
||||
def _on_open_live_super_chat(self, client: OpenLiveClient, message: dm_open_models.SuperChatMessage):
|
||||
avatar_url = services.avatar.process_avatar_url(message.uface)
|
||||
services.avatar.update_avatar_cache_if_expired(message.uid, avatar_url)
|
||||
|
||||
room = client_room_manager.get_room(client.room_key)
|
||||
if room is None:
|
||||
return
|
||||
|
||||
need_translate = self._need_translate(message.message, room, client)
|
||||
if need_translate:
|
||||
translation = services.translate.get_translation_from_cache(message.message)
|
||||
if translation is None:
|
||||
# 没有缓存,需要后面异步翻译后通知
|
||||
translation = ''
|
||||
else:
|
||||
need_translate = False
|
||||
else:
|
||||
translation = ''
|
||||
|
||||
msg_id = str(message.message_id)
|
||||
room.send_cmd_data(api.chat.Command.ADD_SUPER_CHAT, {
|
||||
'id': msg_id,
|
||||
'avatarUrl': avatar_url,
|
||||
'timestamp': message.start_time,
|
||||
'authorName': message.uname,
|
||||
'price': message.rmb,
|
||||
'content': message.message,
|
||||
'translation': translation
|
||||
})
|
||||
|
||||
if need_translate:
|
||||
asyncio.create_task(self._translate_and_response(
|
||||
message.message, room.room_key, msg_id, services.translate.Priority.HIGH
|
||||
))
|
||||
|
||||
def _on_open_live_super_chat_delete(self, client: OpenLiveClient, message: dm_open_models.SuperChatDeleteMessage):
|
||||
room = client_room_manager.get_room(client.room_key)
|
||||
if room is None:
|
||||
return
|
||||
|
||||
room.send_cmd_data(api.chat.Command.DEL_SUPER_CHAT, {
|
||||
'ids': list(map(str, message.message_ids))
|
||||
})
|
||||
|
Loading…
Reference in New Issue
Block a user