From 26afe6c2c499c0048b4bc0e0122344435f9bb043 Mon Sep 17 00:00:00 2001 From: John Smith Date: Tue, 10 Oct 2023 23:11:11 +0800 Subject: [PATCH] =?UTF-8?q?=E5=89=8D=E7=AB=AF=E5=B0=81=E8=A3=85=E6=B6=88?= =?UTF-8?q?=E6=81=AF=E6=A8=A1=E5=9E=8B=EF=BC=8C=E9=98=B2=E6=AD=A2=E4=BB=A5?= =?UTF-8?q?=E5=90=8E=E5=8A=A0=E6=96=B0=E7=9A=84=E5=AD=97=E6=AE=B5=E6=97=B6?= =?UTF-8?q?=E6=BC=8F=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/api/chat/ChatClientDirectOpenLive.js | 55 +++----- frontend/src/api/chat/ChatClientDirectWeb.js | 52 +++----- .../api/chat/ChatClientOfficialBase/index.js | 14 +- frontend/src/api/chat/ChatClientRelay.js | 56 +++----- frontend/src/api/chat/ChatClientTest.js | 65 +++------- frontend/src/api/chat/index.js | 15 ++- frontend/src/api/chat/models.js | 120 ++++++++++++++++++ frontend/src/views/Room.vue | 21 +-- 8 files changed, 214 insertions(+), 184 deletions(-) create mode 100644 frontend/src/api/chat/models.js diff --git a/frontend/src/api/chat/ChatClientDirectOpenLive.js b/frontend/src/api/chat/ChatClientDirectOpenLive.js index 4f48050..3c6a163 100644 --- a/frontend/src/api/chat/ChatClientDirectOpenLive.js +++ b/frontend/src/api/chat/ChatClientDirectOpenLive.js @@ -1,6 +1,7 @@ import axios from 'axios' import * as chat from '.' +import * as chatModels from './models' import * as base from './ChatClientOfficialBase' import ChatClientOfficialBase from './ChatClientOfficialBase' @@ -54,13 +55,13 @@ export default class ChatClientDirectOpenLive extends ChatClientOfficialBase { let msg = `code=${res.code}, message=${res.message}, request_id=${res.request_id}` if (res.code === 7007) { // 身份码错误 - throw new chat.ChatClientFatalError(chat.FATAL_ERROR_TYPE_AUTH_CODE_ERROR, msg) + throw new chatModels.ChatClientFatalError(chatModels.FATAL_ERROR_TYPE_AUTH_CODE_ERROR, msg) } throw Error(msg) } } catch (e) { console.error('startGame failed:', e) - if (e instanceof chat.ChatClientFatalError) { + if (e instanceof chatModels.ChatClientFatalError) { throw e } return false @@ -148,9 +149,6 @@ export default class ChatClientDirectOpenLive extends ChatClientOfficialBase { } async dmCallback(command) { - if (!this.onAddText) { - return - } let data = command.data let authorType @@ -167,7 +165,7 @@ export default class ChatClientDirectOpenLive extends ChatClientOfficialBase { emoticon = data.emoji_img_url } - data = { + data = new chatModels.AddTextMsg({ avatarUrl: chat.processAvatarUrl(data.uface), timestamp: data.timestamp, authorName: data.uname, @@ -175,27 +173,20 @@ export default class ChatClientDirectOpenLive extends ChatClientOfficialBase { content: data.msg, privilegeType: data.guard_level, isGiftDanmaku: chat.isGiftDanmakuByContent(data.msg), - authorLevel: 1, - isNewbie: false, - isMobileVerified: true, medalLevel: data.fans_medal_wearing_status ? data.fans_medal_level : 0, id: data.msg_id, - translation: '', emoticon: emoticon, - } - this.onAddText(data) + }) + this.msgHandler.onAddText(data) } sendGiftCallback(command) { - if (!this.onAddGift) { - return - } let data = command.data if (!data.paid) { // 丢人 return } - data = { + data = new chatModels.AddGiftMsg({ id: data.msg_id, avatarUrl: chat.processAvatarUrl(data.uface), timestamp: data.timestamp, @@ -203,54 +194,42 @@ export default class ChatClientDirectOpenLive extends ChatClientOfficialBase { totalCoin: data.price * data.gift_num, giftName: data.gift_name, num: data.gift_num - } - this.onAddGift(data) + }) + this.msgHandler.onAddGift(data) } async guardCallback(command) { - if (!this.onAddMember) { - return - } - let data = command.data - data = { + data = new chatModels.AddMemberMsg({ id: data.msg_id, avatarUrl: chat.processAvatarUrl(data.user_info.uface), timestamp: data.timestamp, authorName: data.user_info.uname, privilegeType: data.guard_level - } - this.onAddMember(data) + }) + this.msgHandler.onAddMember(data) } superChatCallback(command) { - if (!this.onAddSuperChat) { - return - } - let data = command.data - data = { + data = new chatModels.AddSuperChatMsg({ id: data.message_id.toString(), avatarUrl: chat.processAvatarUrl(data.uface), timestamp: data.start_time, authorName: data.uname, price: data.rmb, content: data.message, - translation: '' - } - this.onAddSuperChat(data) + }) + this.msgHandler.onAddSuperChat(data) } superChatDelCallback(command) { - if (!this.onDelSuperChat) { - return - } - let ids = [] for (let id of command.data.message_ids) { ids.push(id.toString()) } - this.onDelSuperChat({ ids }) + let data = new chatModels.DelSuperChatMsg({ ids }) + this.msgHandler.onDelSuperChat(data) } } diff --git a/frontend/src/api/chat/ChatClientDirectWeb.js b/frontend/src/api/chat/ChatClientDirectWeb.js index 414f38e..44c3e13 100644 --- a/frontend/src/api/chat/ChatClientDirectWeb.js +++ b/frontend/src/api/chat/ChatClientDirectWeb.js @@ -1,7 +1,7 @@ import axios from 'axios' -import { getUuid4Hex } from '@/utils' import * as chat from '.' +import * as chatModels from './models' import * as base from './ChatClientOfficialBase' import ChatClientOfficialBase from './ChatClientOfficialBase' @@ -62,9 +62,6 @@ export default class ChatClientDirectWeb extends ChatClientOfficialBase { } async danmuMsgCallback(command) { - if (!this.onAddText) { - return - } let info = command.info let roomId, medalLevel @@ -91,7 +88,7 @@ export default class ChatClientDirectWeb extends ChatClientOfficialBase { let authorName = info[2][1] let content = info[1] - let data = { + let data = new chatModels.AddTextMsg({ avatarUrl: await chat.getAvatarUrl(uid, authorName), timestamp: info[0][4] / 1000, authorName: authorName, @@ -103,78 +100,59 @@ export default class ChatClientDirectWeb extends ChatClientOfficialBase { isNewbie: info[2][5] < 10000, isMobileVerified: Boolean(info[2][6]), medalLevel: roomId === this.roomId ? medalLevel : 0, - id: getUuid4Hex(), - translation: '', emoticon: info[0][13].url || null, - } - this.onAddText(data) + }) + this.msgHandler.onAddText(data) } sendGiftCallback(command) { - if (!this.onAddGift) { - return - } let data = command.data if (data.coin_type !== 'gold') { // 丢人 return } - data = { - id: getUuid4Hex(), + data = new chatModels.AddGiftMsg({ avatarUrl: chat.processAvatarUrl(data.face), timestamp: data.timestamp, authorName: data.uname, totalCoin: data.total_coin, giftName: data.giftName, num: data.num - } - this.onAddGift(data) + }) + this.msgHandler.onAddGift(data) } async guardBuyCallback(command) { - if (!this.onAddMember) { - return - } - let data = command.data - data = { - id: getUuid4Hex(), + data = new chatModels.AddMemberMsg({ avatarUrl: await chat.getAvatarUrl(data.uid, data.username), timestamp: data.start_time, authorName: data.username, privilegeType: data.guard_level - } - this.onAddMember(data) + }) + this.msgHandler.onAddMember(data) } superChatMessageCallback(command) { - if (!this.onAddSuperChat) { - return - } - let data = command.data - data = { + 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, - translation: '' - } - this.onAddSuperChat(data) + }) + this.msgHandler.onAddSuperChat(data) } superChatMessageDeleteCallback(command) { - if (!this.onDelSuperChat) { - return - } - let ids = [] for (let id of command.data.ids) { ids.push(id.toString()) } - this.onDelSuperChat({ ids }) + let data = new chatModels.DelSuperChatMsg({ ids }) + this.msgHandler.onDelSuperChat(data) } } diff --git a/frontend/src/api/chat/ChatClientOfficialBase/index.js b/frontend/src/api/chat/ChatClientOfficialBase/index.js index 21ab439..a03910c 100644 --- a/frontend/src/api/chat/ChatClientOfficialBase/index.js +++ b/frontend/src/api/chat/ChatClientOfficialBase/index.js @@ -2,6 +2,7 @@ import { BrotliDecode } from './brotli_decode' import { inflate } from 'pako' import * as chat from '..' +import * as chatModels from '../models' const HEADER_SIZE = 16 @@ -45,14 +46,7 @@ export default class ChatClientOfficialBase { constructor() { this.CMD_CALLBACK_MAP = {} - this.onAddText = null - this.onAddGift = null - this.onAddMember = null - this.onAddSuperChat = null - this.onDelSuperChat = null - this.onUpdateTranslation = null - - this.onFatalError = null + this.msgHandler = chat.getDefaultMsgHandler() this.needInitRoom = true this.websocket = null @@ -126,8 +120,8 @@ export default class ChatClientOfficialBase { } catch (e) { res = false console.error('initRoom exception:', e) - if (e instanceof chat.ChatClientFatalError && this.onFatalError) { - this.onFatalError(e) + if (e instanceof chatModels.ChatClientFatalError) { + this.msgHandler.onFatalError(e) } } diff --git a/frontend/src/api/chat/ChatClientRelay.js b/frontend/src/api/chat/ChatClientRelay.js index 57bce6a..479c0fa 100644 --- a/frontend/src/api/chat/ChatClientRelay.js +++ b/frontend/src/api/chat/ChatClientRelay.js @@ -1,4 +1,5 @@ import * as chat from '.' +import * as chatModels from './models' const COMMAND_HEARTBEAT = 0 const COMMAND_JOIN_ROOM = 1 @@ -20,14 +21,7 @@ export default class ChatClientRelay { this.roomKey = roomKey this.autoTranslate = autoTranslate - this.onAddText = null - this.onAddGift = null - this.onAddMember = null - this.onAddSuperChat = null - this.onDelSuperChat = null - this.onUpdateTranslation = null - - this.onFatalError = null + this.msgHandler = chat.getDefaultMsgHandler() this.websocket = null this.retryCount = 0 @@ -122,10 +116,6 @@ export default class ChatClientRelay { break } case COMMAND_ADD_TEXT: { - if (!this.onAddText) { - break - } - let emoticon = null let contentType = data[13] let contentTypeParams = data[14] @@ -134,7 +124,7 @@ export default class ChatClientRelay { } let content = data[4] - data = { + data = new chatModels.AddTextMsg({ avatarUrl: data[0], timestamp: data[1], authorName: data[2], @@ -149,51 +139,41 @@ export default class ChatClientRelay { id: data[11], translation: data[12], emoticon: emoticon - } - this.onAddText(data) + }) + this.msgHandler.onAddText(data) break } case COMMAND_ADD_GIFT: { - if (this.onAddGift) { - this.onAddGift(data) - } + data = new chatModels.AddGiftMsg(data) + this.msgHandler.onAddGift(data) break } case COMMAND_ADD_MEMBER: { - if (this.onAddMember) { - this.onAddMember(data) - } + data = new chatModels.AddMemberMsg(data) + this.msgHandler.onAddMember(data) break } case COMMAND_ADD_SUPER_CHAT: { - if (this.onAddSuperChat) { - this.onAddSuperChat(data) - } + data = new chatModels.AddSuperChatMsg(data) + this.msgHandler.onAddSuperChat(data) break } case COMMAND_DEL_SUPER_CHAT: { - if (this.onDelSuperChat) { - this.onDelSuperChat(data) - } + data = new chatModels.DelSuperChatMsg(data) + this.msgHandler.onDelSuperChat(data) break } case COMMAND_UPDATE_TRANSLATION: { - if (!this.onUpdateTranslation) { - break - } - data = { + data = new chatModels.UpdateTranslationMsg({ id: data[0], translation: data[1] - } - this.onUpdateTranslation(data) + }) + this.msgHandler.onUpdateTranslation(data) break } case COMMAND_FATAL_ERROR: { - if (!this.onFatalError) { - break - } - let error = new chat.ChatClientFatalError(data.type, data.msg) - this.onFatalError(error) + let error = new chatModels.ChatClientFatalError(data.type, data.msg) + this.msgHandler.onFatalError(error) break } } diff --git a/frontend/src/api/chat/ChatClientTest.js b/frontend/src/api/chat/ChatClientTest.js index ea70265..5d58f36 100644 --- a/frontend/src/api/chat/ChatClientTest.js +++ b/frontend/src/api/chat/ChatClientTest.js @@ -1,6 +1,6 @@ -import { getUuid4Hex } from '@/utils' import * as constants from '@/components/ChatRenderer/constants' import * as chat from '.' +import * as chatModels from './models' const NAMES = [ '光羊', @@ -102,21 +102,16 @@ const MESSAGE_GENERATORS = [ value() { return { type: constants.MESSAGE_TYPE_TEXT, - message: { + message: new chatModels.AddTextMsg({ ...randGuardInfo(), - avatarUrl: chat.DEFAULT_AVATAR_URL, - timestamp: new Date().getTime() / 1000, authorName: randomChoose(NAMES), content: randomChoose(CONTENTS), isGiftDanmaku: randInt(1, 10) <= 1, - authorLevel: randInt(0, 60), + authorLevel: randInt(1, 60), isNewbie: randInt(1, 10) <= 1, isMobileVerified: randInt(1, 10) <= 9, medalLevel: randInt(0, 40), - id: getUuid4Hex(), - translation: '', - emoticon: null, - } + }) } } }, @@ -126,21 +121,15 @@ const MESSAGE_GENERATORS = [ value() { return { type: constants.MESSAGE_TYPE_TEXT, - message: { + message: new chatModels.AddTextMsg({ ...randGuardInfo(), - avatarUrl: chat.DEFAULT_AVATAR_URL, - timestamp: new Date().getTime() / 1000, authorName: randomChoose(NAMES), - content: '', - isGiftDanmaku: false, - authorLevel: randInt(0, 60), + authorLevel: randInt(1, 60), isNewbie: randInt(1, 10) <= 1, isMobileVerified: randInt(1, 10) <= 9, medalLevel: randInt(0, 40), - id: getUuid4Hex(), - translation: '', emoticon: randomChoose(EMOTICONS), - } + }) } } }, @@ -150,14 +139,10 @@ const MESSAGE_GENERATORS = [ value() { return { type: constants.MESSAGE_TYPE_GIFT, - message: { + message: new chatModels.AddGiftMsg({ ...randomChoose(GIFT_INFO_LIST), - id: getUuid4Hex(), - avatarUrl: chat.DEFAULT_AVATAR_URL, - timestamp: new Date().getTime() / 1000, authorName: randomChoose(NAMES), - num: 1 - } + }) } } }, @@ -167,15 +152,11 @@ const MESSAGE_GENERATORS = [ value() { return { type: constants.MESSAGE_TYPE_SUPER_CHAT, - message: { - id: getUuid4Hex(), - avatarUrl: chat.DEFAULT_AVATAR_URL, - timestamp: new Date().getTime() / 1000, + message: new chatModels.AddSuperChatMsg({ authorName: randomChoose(NAMES), price: randomChoose(SC_PRICES), content: randomChoose(CONTENTS), - translation: '' - } + }) } } }, @@ -185,13 +166,10 @@ const MESSAGE_GENERATORS = [ value() { return { type: constants.MESSAGE_TYPE_MEMBER, - message: { - id: getUuid4Hex(), - avatarUrl: chat.DEFAULT_AVATAR_URL, - timestamp: new Date().getTime() / 1000, + message: new chatModels.AddMemberMsg({ authorName: randomChoose(NAMES), privilegeType: randInt(1, 3) - } + }) } } } @@ -231,14 +209,7 @@ function randInt(min, max) { export default class ChatClientTest { constructor() { - this.onAddText = null - this.onAddGift = null - this.onAddMember = null - this.onAddSuperChat = null - this.onDelSuperChat = null - this.onUpdateTranslation = null - - this.onFatalError = null + this.msgHandler = chat.getDefaultMsgHandler() this.timerId = null } @@ -274,16 +245,16 @@ export default class ChatClientTest { let { type, message } = randomChoose(MESSAGE_GENERATORS)() switch (type) { case constants.MESSAGE_TYPE_TEXT: - this.onAddText(message) + this.msgHandler.onAddText(message) break case constants.MESSAGE_TYPE_GIFT: - this.onAddGift(message) + this.msgHandler.onAddGift(message) break case constants.MESSAGE_TYPE_MEMBER: - this.onAddMember(message) + this.msgHandler.onAddMember(message) break case constants.MESSAGE_TYPE_SUPER_CHAT: - this.onAddSuperChat(message) + this.msgHandler.onAddSuperChat(message) break } } diff --git a/frontend/src/api/chat/index.js b/frontend/src/api/chat/index.js index 0b3d6ce..700973e 100644 --- a/frontend/src/api/chat/index.js +++ b/frontend/src/api/chat/index.js @@ -1,11 +1,16 @@ import axios from 'axios' -export const FATAL_ERROR_TYPE_AUTH_CODE_ERROR = 1 +export function getDefaultMsgHandler() { + let dummyFunc = () => {} + return { + onAddText: dummyFunc, + onAddGift: dummyFunc, + onAddMember: dummyFunc, + onAddSuperChat: dummyFunc, + onDelSuperChat: dummyFunc, + onUpdateTranslation: dummyFunc, -export class ChatClientFatalError extends Error { - constructor(type, message) { - super(message) - this.type = type + onFatalError: dummyFunc, } } diff --git a/frontend/src/api/chat/models.js b/frontend/src/api/chat/models.js new file mode 100644 index 0000000..1b9c855 --- /dev/null +++ b/frontend/src/api/chat/models.js @@ -0,0 +1,120 @@ +import { getUuid4Hex } from '@/utils' +import * as constants from '@/components/ChatRenderer/constants' +import * as chat from '.' + +export class AddTextMsg { + constructor({ + avatarUrl = chat.DEFAULT_AVATAR_URL, + timestamp = new Date().getTime() / 1000, + authorName = '', + authorType = constants.AUTHOR_TYPE_NORMAL, + content = '', + privilegeType = 0, + isGiftDanmaku = false, + authorLevel = 1, + isNewbie = false, + isMobileVerified = true, + medalLevel = 0, + id = getUuid4Hex(), + translation = '', + emoticon = null, + } = {}) { + this.avatarUrl = avatarUrl + this.timestamp = timestamp + this.authorName = authorName + this.authorType = authorType + this.content = content + this.privilegeType = privilegeType + this.isGiftDanmaku = isGiftDanmaku + this.authorLevel = authorLevel + this.isNewbie = isNewbie + this.isMobileVerified = isMobileVerified + this.medalLevel = medalLevel + this.id = id + this.translation = translation + this.emoticon = emoticon + } +} + +export class AddGiftMsg { + constructor({ + id = getUuid4Hex(), + avatarUrl = chat.DEFAULT_AVATAR_URL, + timestamp = new Date().getTime() / 1000, + authorName = '', + totalCoin = 0, + giftName = '', + num = 1, + } = {}) { + this.id = id + this.avatarUrl = avatarUrl + this.timestamp = timestamp + this.authorName = authorName + this.totalCoin = totalCoin + this.giftName = giftName + this.num = num + } +} + +export class AddMemberMsg { + constructor({ + id = getUuid4Hex(), + avatarUrl = chat.DEFAULT_AVATAR_URL, + timestamp = new Date().getTime() / 1000, + authorName = '', + privilegeType = 1, + } = {}) { + this.id = id + this.avatarUrl = avatarUrl + this.timestamp = timestamp + this.authorName = authorName + this.privilegeType = privilegeType + } +} + +export class AddSuperChatMsg { + constructor({ + id = getUuid4Hex(), + avatarUrl = chat.DEFAULT_AVATAR_URL, + timestamp = new Date().getTime() / 1000, + authorName = '', + price = 0, + content = '', + translation = '', + } = {}) { + this.id = id + this.avatarUrl = avatarUrl + this.timestamp = timestamp + this.authorName = authorName + this.price = price + this.content = content + this.translation = translation + } +} + +export class DelSuperChatMsg { + constructor({ + ids = [], + } = {}) { + this.ids = ids + } +} + +export class UpdateTranslationMsg { + constructor({ + id = getUuid4Hex(), + translation = '', + } = {}) { + this.id = id + this.translation = translation + } +} + +export const FATAL_ERROR_TYPE_AUTH_CODE_ERROR = 1 + +export class ChatClientFatalError extends Error { + constructor(type, message) { + super(message) + this.type = type + } +} diff --git a/frontend/src/views/Room.vue b/frontend/src/views/Room.vue index 24dcc75..1d2b97b 100644 --- a/frontend/src/views/Room.vue +++ b/frontend/src/views/Room.vue @@ -9,6 +9,7 @@ import * as trie from '@/utils/trie' import * as pronunciation from '@/utils/pronunciation' import * as chatConfig from '@/api/chatConfig' import * as chat from '@/api/chat' +import * as chatModels from '@/api/chat/models' import ChatRenderer from '@/components/ChatRenderer' import * as constants from '@/components/ChatRenderer/constants' @@ -198,13 +199,8 @@ export default { this.chatClient = new ChatClientDirectOpenLive(this.roomKeyValue) } } - this.chatClient.onAddText = this.onAddText - this.chatClient.onAddGift = this.onAddGift - this.chatClient.onAddMember = this.onAddMember - this.chatClient.onAddSuperChat = this.onAddSuperChat - this.chatClient.onDelSuperChat = this.onDelSuperChat - this.chatClient.onUpdateTranslation = this.onUpdateTranslation - this.chatClient.onFatalError = this.onFatalError + + this.chatClient.msgHandler = this this.chatClient.start() }, async initTextEmoticons() { @@ -236,6 +232,7 @@ export default { } }, + /** @param {chatModels.AddTextMsg} data */ onAddText(data) { if (!this.config.showDanmaku || !this.filterTextMessage(data) || this.mergeSimilarText(data.content)) { return @@ -255,6 +252,7 @@ export default { } this.$refs.renderer.addMessage(message) }, + /** @param {chatModels.AddGiftMsg} data */ onAddGift(data) { if (!this.config.showGift) { return @@ -279,6 +277,7 @@ export default { } this.$refs.renderer.addMessage(message) }, + /** @param {chatModels.AddMemberMsg} data */ onAddMember(data) { if (!this.config.showGift || !this.filterNewMemberMessage(data)) { return @@ -295,6 +294,7 @@ export default { } this.$refs.renderer.addMessage(message) }, + /** @param {chatModels.AddSuperChatMsg} data */ onAddSuperChat(data) { if (!this.config.showGift || !this.filterSuperChatMessage(data)) { return @@ -315,15 +315,18 @@ export default { } this.$refs.renderer.addMessage(message) }, + /** @param {chatModels.DelSuperChatMsg} data */ onDelSuperChat(data) { this.$refs.renderer.delMessages(data.ids) }, + /** @param {chatModels.UpdateTranslationMsg} data */ onUpdateTranslation(data) { if (!this.config.autoTranslate) { return } this.$refs.renderer.updateMessage(data.id, { translation: data.translation }) }, + /** @param {chatModels.ChatClientFatalError} error */ onFatalError(error) { this.$message.error({ message: error.toString(), @@ -331,7 +334,7 @@ export default { }) this.chatClient.stop() - if (error.type === chat.FATAL_ERROR_TYPE_AUTH_CODE_ERROR) { + if (error.type === chatModels.FATAL_ERROR_TYPE_AUTH_CODE_ERROR) { // Read The Fucking Manual this.$router.push({ name: 'help' }) } @@ -391,7 +394,7 @@ export default { getRichContent(data) { let richContent = [] - // B站官方表情 + // 官方的非文本表情 if (data.emoticon !== null) { richContent.push({ type: constants.CONTENT_TYPE_IMAGE,