mirror of
https://github.com/xfgryujk/blivechat.git
synced 2026-08-19 09:43:28 +08:00
267 lines
7.4 KiB
JavaScript
267 lines
7.4 KiB
JavaScript
import { apiClient as axios } from '@/api/base'
|
||
import * as chat from '.'
|
||
import * as chatModels from './models'
|
||
import * as base from './ChatClientOfficialBase'
|
||
import ChatClientOfficialBase from './ChatClientOfficialBase'
|
||
|
||
export default class ChatClientDirectWeb extends ChatClientOfficialBase {
|
||
constructor(roomId) {
|
||
super()
|
||
this.CMD_CALLBACK_MAP = CMD_CALLBACK_MAP
|
||
|
||
// 调用initRoom后初始化,如果失败,使用这里的默认值
|
||
this.roomId = roomId
|
||
this.roomOwnerUid = -1
|
||
this.hostServerList = [
|
||
{ host: "broadcastlv.chat.bilibili.com", port: 2243, wss_port: 443, ws_port: 2244 }
|
||
]
|
||
this.hostServerToken = null
|
||
this.buvid = ''
|
||
}
|
||
|
||
async initRoom() {
|
||
let res
|
||
try {
|
||
res = (await axios.get('/api/room_info', { params: {
|
||
roomId: this.roomId
|
||
} })).data
|
||
} catch {
|
||
return true
|
||
}
|
||
this.roomId = res.roomId
|
||
this.roomOwnerUid = res.ownerUid
|
||
if (res.hostServerList.length !== 0) {
|
||
this.hostServerList = res.hostServerList
|
||
}
|
||
this.hostServerToken = res.hostServerToken
|
||
this.buvid = res.buvid
|
||
return true
|
||
}
|
||
|
||
async onBeforeWsConnect() {
|
||
// 重连次数太多则重新init_room,保险
|
||
let reinitPeriod = Math.max(3, (this.hostServerList || []).length)
|
||
if (this.retryCount > 0 && this.retryCount % reinitPeriod === 0) {
|
||
this.needInitRoom = true
|
||
}
|
||
return super.onBeforeWsConnect()
|
||
}
|
||
|
||
getWsUrl() {
|
||
let hostServer = this.hostServerList[this.retryCount % this.hostServerList.length]
|
||
return `wss://${hostServer.host}:${hostServer.wss_port}/sub`
|
||
}
|
||
|
||
sendAuth() {
|
||
let authParams = {
|
||
uid: 0,
|
||
roomid: this.roomId,
|
||
protover: 3,
|
||
platform: 'web',
|
||
type: 2,
|
||
buvid: this.buvid,
|
||
}
|
||
if (this.hostServerToken !== null) {
|
||
authParams.key = this.hostServerToken
|
||
}
|
||
this.websocket.send(this.makePacket(authParams, base.OP_AUTH))
|
||
}
|
||
|
||
async danmuMsgMirrorCallback(command) {
|
||
command._isMirror = true
|
||
this.danmuMsgCallback(command)
|
||
}
|
||
|
||
async danmuMsgCallback(command) {
|
||
let info = command.info
|
||
|
||
let modeInfo = info[0][15]
|
||
let avatarUrl = modeInfo?.user?.base?.face ?? ''
|
||
if (!avatarUrl) {
|
||
avatarUrl = await chat.getAvatarUrl(uid, authorName)
|
||
}
|
||
|
||
let medalRoomId, medalLevel, medalName
|
||
if (info[3]) {
|
||
medalRoomId = info[3][3]
|
||
medalLevel = info[3][0]
|
||
medalName = info[3][1]
|
||
} else {
|
||
medalRoomId = medalLevel = 0
|
||
medalName = ''
|
||
}
|
||
|
||
let uid = info[2][0]
|
||
let isAdmin = info[2][2]
|
||
let privilegeType = info[7]
|
||
let authorType
|
||
if (uid === this.roomOwnerUid) {
|
||
authorType = 3
|
||
} else if (isAdmin) {
|
||
authorType = 2
|
||
} else if (privilegeType !== 0) {
|
||
authorType = 1
|
||
} else {
|
||
authorType = 0
|
||
}
|
||
|
||
let extra
|
||
try {
|
||
extra = modeInfo.extra
|
||
if (typeof extra !== 'object') {
|
||
extra = JSON.parse(extra)
|
||
}
|
||
} catch {
|
||
extra = {}
|
||
}
|
||
|
||
let content = info[1]
|
||
let replyUname = extra.reply_uname ?? ''
|
||
let showContent = content
|
||
if (replyUname !== '') {
|
||
showContent = `@${replyUname} ${showContent}`
|
||
}
|
||
|
||
let authorName = info[2][1]
|
||
let data = new chatModels.AddTextMsg({
|
||
avatarUrl: avatarUrl,
|
||
timestamp: info[0][4] / 1000,
|
||
authorName: authorName,
|
||
authorType: authorType,
|
||
content: showContent,
|
||
privilegeType: privilegeType,
|
||
isGiftDanmaku: Boolean(info[0][9]) || chat.isGiftDanmakuByContent(content),
|
||
authorLevel: info[4][0],
|
||
isNewbie: info[2][5] < 10000,
|
||
isMobileVerified: Boolean(info[2][6]),
|
||
medalLevel: medalRoomId === this.roomId ? medalLevel : 0,
|
||
emoticon: info[0][13].url || null,
|
||
isMirror: Boolean(command._isMirror),
|
||
// 给模板用的字段
|
||
uid: info[2][0] ? info[2][0].toString() : authorName,
|
||
medalName: medalRoomId === this.roomId ? medalName : '',
|
||
})
|
||
this.msgHandler.onAddText(data)
|
||
}
|
||
|
||
sendGiftCallback(command) {
|
||
let data = command.data
|
||
let isPaidGift = data.coin_type === 'gold'
|
||
|
||
let medalRuid, medalLevel, medalName
|
||
if (data.medal_info) {
|
||
medalRuid = data.medal_info.target_id
|
||
medalLevel = data.medal_info.medal_level
|
||
medalName = data.medal_info.medal_name
|
||
} else {
|
||
medalRuid = medalLevel = 0
|
||
medalName = ''
|
||
}
|
||
|
||
data = new chatModels.AddGiftMsg({
|
||
avatarUrl: chat.processAvatarUrl(data.face),
|
||
timestamp: data.timestamp,
|
||
authorName: data.uname,
|
||
totalCoin: isPaidGift ? data.total_coin : 0,
|
||
totalFreeCoin: !isPaidGift ? data.total_coin : 0,
|
||
giftName: data.giftName,
|
||
num: data.num,
|
||
// 给模板用的字段
|
||
giftId: data.giftId,
|
||
giftIconUrl: data.gift_info.img_basic,
|
||
uid: data.uid ? data.uid.toString() : data.uname,
|
||
privilegeType: data.guard_level,
|
||
medalLevel: medalRuid === this.roomOwnerUid ? medalLevel : 0,
|
||
medalName: medalRuid === this.roomOwnerUid ? medalName : '',
|
||
})
|
||
this.msgHandler.onAddGift(data)
|
||
}
|
||
|
||
async userToastV2Callback(command) {
|
||
let data = command.data
|
||
// 官方的评论栏不会显示2的消息
|
||
if (data.option.source == 2) {
|
||
return
|
||
}
|
||
|
||
let {
|
||
sender_uinfo: {
|
||
uid,
|
||
base: {
|
||
name: username,
|
||
},
|
||
},
|
||
guard_info: {
|
||
start_time: timestamp,
|
||
guard_level: guardLevel,
|
||
},
|
||
pay_info: {
|
||
num,
|
||
unit,
|
||
price,
|
||
},
|
||
} = data
|
||
data = new chatModels.AddMemberMsg({
|
||
avatarUrl: await chat.getAvatarUrl(uid, username),
|
||
timestamp: timestamp,
|
||
authorName: username,
|
||
privilegeType: guardLevel,
|
||
// 给模板用的字段
|
||
num: num,
|
||
unit: unit,
|
||
total_coin: price * num,
|
||
uid: uid ? uid.toString() : username,
|
||
medalLevel: 0,
|
||
medalName: '',
|
||
})
|
||
this.msgHandler.onAddMember(data)
|
||
}
|
||
|
||
superChatMessageCallback(command) {
|
||
let data = command.data
|
||
|
||
let medalRoomId, medalLevel, medalName
|
||
if (data.medal_info) {
|
||
medalRoomId = data.medal_info.anchor_roomid
|
||
medalLevel = data.medal_info.medal_level
|
||
medalName = data.medal_info.medal_name
|
||
} else {
|
||
medalRoomId = medalLevel = 0
|
||
medalName = ''
|
||
}
|
||
|
||
data = new chatModels.AddSuperChatMsg({
|
||
id: data.id.toString(),
|
||
avatarUrl: chat.processAvatarUrl(data.user_info.face),
|
||
timestamp: data.start_time,
|
||
authorName: data.user_info.uname,
|
||
price: data.price,
|
||
content: data.message,
|
||
// 给模板用的字段
|
||
uid: data.uid ? data.uid.toString() : data.user_info.uname,
|
||
privilegeType: data.user_info.guard_level,
|
||
medalLevel: medalRoomId === this.roomId ? medalLevel : 0,
|
||
medalName: medalRoomId === this.roomId ? medalName : '',
|
||
})
|
||
this.msgHandler.onAddSuperChat(data)
|
||
}
|
||
|
||
superChatMessageDeleteCallback(command) {
|
||
let ids = []
|
||
for (let id of command.data.ids) {
|
||
ids.push(id.toString())
|
||
}
|
||
let data = new chatModels.DelSuperChatMsg({ ids })
|
||
this.msgHandler.onDelSuperChat(data)
|
||
}
|
||
}
|
||
|
||
const CMD_CALLBACK_MAP = {
|
||
DANMU_MSG: ChatClientDirectWeb.prototype.danmuMsgCallback,
|
||
DANMU_MSG_MIRROR: ChatClientDirectWeb.prototype.danmuMsgMirrorCallback,
|
||
SEND_GIFT: ChatClientDirectWeb.prototype.sendGiftCallback,
|
||
USER_TOAST_MSG_V2: ChatClientDirectWeb.prototype.userToastV2Callback,
|
||
SUPER_CHAT_MESSAGE: ChatClientDirectWeb.prototype.superChatMessageCallback,
|
||
SUPER_CHAT_MESSAGE_DELETE: ChatClientDirectWeb.prototype.superChatMessageDeleteCallback
|
||
}
|