chore: format code style and update linting configuration

This commit is contained in:
Megghy
2025-10-02 10:38:23 +08:00
parent 6fd046adcd
commit 758549d29d
253 changed files with 16258 additions and 15833 deletions

View File

@@ -1,53 +1,54 @@
import type { KeepLiveWS } from 'bilibili-live-ws/browser' // 导入 bilibili-live-ws 库
// BaseDanmakuClient.ts
import { EventModel, EventDataTypes } from '@/api/api-models'; // 导入事件模型和类型枚举
import { KeepLiveWS } from 'bilibili-live-ws/browser'; // 导入 bilibili-live-ws 库
import type { EventModel } from '@/api/api-models'
// 导入事件模型和类型枚举
// 定义基础弹幕客户端抽象类
export default abstract class BaseDanmakuClient {
constructor() {
this.client = null; // 初始化客户端实例为 null
this.client = null // 初始化客户端实例为 null
// 初始化两套事件监听器存储
this.eventsAsModel = this.createEmptyEventModelListeners();
this.eventsRaw = this.createEmptyRawEventlisteners();
this.eventsAsModel = this.createEmptyEventModelListeners()
this.eventsRaw = this.createEmptyRawEventlisteners()
}
// WebSocket 客户端实例
public client: KeepLiveWS | null;
public client: KeepLiveWS | null
// 客户端连接状态
public state: 'padding' | 'connected' | 'connecting' | 'disconnected' =
'padding';
public state: 'padding' | 'connected' | 'connecting' | 'disconnected'
= 'padding'
// 客户端类型 (由子类实现)
public abstract type: 'openlive' | 'direct';
public abstract type: 'openlive' | 'direct'
// 目标服务器地址 (由子类实现)
public abstract serverUrl: string;
public abstract serverUrl: string
// --- 事件系统 1: 使用 EventModel ---
// 事件监听器集合 (统一使用 EventModel)
public eventsAsModel: {
danmaku: ((arg1: EventModel, arg2?: any) => void)[];
gift: ((arg1: EventModel, arg2?: any) => void)[];
sc: ((arg1: EventModel, arg2?: any) => void)[];
guard: ((arg1: EventModel, arg2?: any) => void)[];
enter: ((arg1: EventModel, arg2?: any) => void)[]; // 新增: 用户进入事件
scDel: ((arg1: EventModel, arg2?: any) => void)[]; // 新增: SC 删除事件
all: ((arg1: any) => void)[]; // 'all' 事件监听器接收原始消息或特定事件包
follow: ((arg1: EventModel, arg2?: any) => void)[]; // 新增: 关注事件
};
danmaku: ((arg1: EventModel, arg2?: any) => void)[]
gift: ((arg1: EventModel, arg2?: any) => void)[]
sc: ((arg1: EventModel, arg2?: any) => void)[]
guard: ((arg1: EventModel, arg2?: any) => void)[]
enter: ((arg1: EventModel, arg2?: any) => void)[] // 新增: 用户进入事件
scDel: ((arg1: EventModel, arg2?: any) => void)[] // 新增: SC 删除事件
all: ((arg1: any) => void)[] // 'all' 事件监听器接收原始消息或特定事件包
follow: ((arg1: EventModel, arg2?: any) => void)[] // 新增: 关注事件
}
// --- 事件系统 2: 使用原始数据类型 ---
// 事件监听器集合 (使用原始数据结构, 类型设为 any, 由具体实现和调用者保证)
public eventsRaw: {
danmaku: ((arg1: any, arg2?: any) => void)[];
gift: ((arg1: any, arg2?: any) => void)[];
sc: ((arg1: any, arg2?: any) => void)[];
guard: ((arg1: any, arg2?: any) => void)[];
enter: ((arg1: any, arg2?: any) => void)[]; // 新增: 用户进入事件
scDel: ((arg1: any, arg2?: any) => void)[]; // 新增: SC 删除事件
all: ((arg1: any) => void)[]; // 'all' 事件监听器接收原始消息或特定事件包
follow: ((arg1: any, arg2?: any) => void)[]; // 新增: 关注事件
};
danmaku: ((arg1: any, arg2?: any) => void)[]
gift: ((arg1: any, arg2?: any) => void)[]
sc: ((arg1: any, arg2?: any) => void)[]
guard: ((arg1: any, arg2?: any) => void)[]
enter: ((arg1: any, arg2?: any) => void)[] // 新增: 用户进入事件
scDel: ((arg1: any, arg2?: any) => void)[] // 新增: SC 删除事件
all: ((arg1: any) => void)[] // 'all' 事件监听器接收原始消息或特定事件包
follow: ((arg1: any, arg2?: any) => void)[] // 新增: 关注事件
}
// 创建空的 EventModel 监听器对象
public createEmptyEventModelListeners() {
@@ -60,7 +61,7 @@ export default abstract class BaseDanmakuClient {
scDel: [],
all: [],
follow: [], // 初始化 follow 事件
};
}
}
// 创建空的 RawEvent 监听器对象
@@ -74,63 +75,65 @@ export default abstract class BaseDanmakuClient {
scDel: [],
all: [],
follow: [], // 初始化 follow 事件
};
}
}
/**
* 启动弹幕客户端连接
* @returns Promise<{ success: boolean; message: string }> 启动结果
*/
public async Start(): Promise<{ success: boolean; message: string; }> {
public async Start(): Promise<{ success: boolean, message: string }> {
// 如果已连接,直接返回成功
if (this.state === 'connected') {
return {
success: true,
message: '弹幕客户端已启动',
};
}
}
// 如果正在连接中,返回提示
if (this.state === 'connecting') {
return {
success: false,
message: '弹幕客户端正在启动',
};
}
}
// 设置状态为连接中
this.state = 'connecting';
this.state = 'connecting'
try {
// 确保 client 为 null 才初始化
if (!this.client) {
console.log(`[${this.type}] 正在启动弹幕客户端`);
console.log(`[${this.type}] 正在启动弹幕客户端`)
// 调用子类实现的初始化方法
const result = await this.initClient();
const result = await this.initClient()
if (result.success) {
this.state = 'connected';
console.log(`[${this.type}] 弹幕客户端已完成启动`);
this.state = 'connected'
console.log(`[${this.type}] 弹幕客户端已完成启动`)
} else {
this.state = 'disconnected';
console.error(`[${this.type}] 弹幕客户端启动失败: ${result.message}`);
this.state = 'disconnected'
console.error(`[${this.type}] 弹幕客户端启动失败: ${result.message}`)
}
return result;
return result
} else {
console.warn(`[${this.type}] 客户端实例已存在但状态异常,尝试重置状态`);
this.state = 'disconnected';
console.warn(`[${this.type}] 客户端实例已存在但状态异常,尝试重置状态`)
this.state = 'disconnected'
return {
success: false,
message: '客户端实例状态异常,请尝试重新启动',
};
}
}
} catch (err: any) {
console.error(`[${this.type}] 启动过程中发生异常:`, err);
this.state = 'disconnected';
console.error(`[${this.type}] 启动过程中发生异常:`, err)
this.state = 'disconnected'
if (this.client) {
try { this.client.close(); } catch { }
this.client = null;
try {
this.client.close()
} catch { }
this.client = null
}
return {
success: false,
message: err?.message || err?.toString() || '未知错误',
};
}
}
}
@@ -140,24 +143,24 @@ export default abstract class BaseDanmakuClient {
public Stop() {
// 如果已断开,则无需操作
if (this.state === 'disconnected') {
return;
return
}
// 设置状态为已断开
this.state = 'disconnected';
this.state = 'disconnected'
if (this.client) {
console.log(`[${this.type}] 正在停止弹幕客户端`);
console.log(`[${this.type}] 正在停止弹幕客户端`)
try {
this.client.close(); // 关闭 WebSocket 连接
this.client.close() // 关闭 WebSocket 连接
} catch (err) {
console.error(`[${this.type}] 关闭客户端时发生错误:`, err);
console.error(`[${this.type}] 关闭客户端时发生错误:`, err)
}
this.client = null; // 将客户端实例置为 null
this.client = null // 将客户端实例置为 null
} else {
console.warn(`[${this.type}] 弹幕客户端未被启动, 忽略停止操作`);
console.warn(`[${this.type}] 弹幕客户端未被启动, 忽略停止操作`)
}
// 注意: 清空所有事件监听器
//this.eventsAsModel = this.createEmptyEventModelListeners();
//this.eventsRaw = this.createEmptyRawEventlisteners();
// this.eventsAsModel = this.createEmptyEventModelListeners();
// this.eventsRaw = this.createEmptyRawEventlisteners();
}
/**
@@ -165,9 +168,9 @@ export default abstract class BaseDanmakuClient {
* @returns Promise<{ success: boolean; message: string }> 初始化结果
*/
protected abstract initClient(): Promise<{
success: boolean;
message: string;
}>;
success: boolean
message: string
}>
/**
* 内部通用的客户端事件绑定和连接状态等待逻辑
@@ -175,66 +178,70 @@ export default abstract class BaseDanmakuClient {
* @returns Promise<{ success: boolean; message: string }> 连接结果
*/
protected async initClientInner(
chatClient: KeepLiveWS
): Promise<{ success: boolean; message: string; }> {
let isConnected = false; // 标记是否连接成功
let isError = false; // 标记是否发生错误
let errorMsg = ''; // 存储错误信息
chatClient: KeepLiveWS,
): Promise<{ success: boolean, message: string }> {
let isConnected = false // 标记是否连接成功
let isError = false // 标记是否发生错误
let errorMsg = '' // 存储错误信息
// 监听错误事件
chatClient.on('error', (err: any) => {
console.error(`[${this.type}] 客户端发生错误:`, err);
isError = true;
errorMsg = err?.message || err?.toString() || '未知错误';
});
console.error(`[${this.type}] 客户端发生错误:`, err)
isError = true
errorMsg = err?.message || err?.toString() || '未知错误'
})
// 监听连接成功事件
chatClient.on('live', () => {
console.log(`[${this.type}] 弹幕客户端连接成功`);
isConnected = true;
});
console.log(`[${this.type}] 弹幕客户端连接成功`)
isConnected = true
})
// 监听连接关闭事件
chatClient.on('close', () => {
console.log(`[${this.type}] 弹幕客户端连接已关闭`);
console.log(`[${this.type}] 弹幕客户端连接已关闭`)
if (this.state !== 'disconnected') {
this.state = 'disconnected';
this.client = null;
this.state = 'disconnected'
this.client = null
}
isConnected = false; // 标记为未连接
});
isConnected = false // 标记为未连接
})
// 监听原始消息事件 (通用)
// 注意: 子类可能也会监听特定事件名, 这里的 'msg' 是备用或处理未被特定监听器捕获的事件
chatClient.on('msg', (command: any) => this.onRawMessage(command));
chatClient.on('msg', (command: any) => this.onRawMessage(command))
this.client = chatClient; // 保存客户端实例
this.client = chatClient // 保存客户端实例
// 等待连接成功或发生错误
const timeout = 30000; // 30 秒超时
const startTime = Date.now();
const timeout = 30000 // 30 秒超时
const startTime = Date.now()
while (!isConnected && !isError) {
if (Date.now() - startTime > timeout) {
isError = true;
errorMsg = '连接超时';
console.error(`[${this.type}] ${errorMsg}`);
break;
isError = true
errorMsg = '连接超时'
console.error(`[${this.type}] ${errorMsg}`)
break
}
await new Promise((resolve) => { setTimeout(resolve, 500); });
await new Promise((resolve) => {
setTimeout(resolve, 500)
})
}
// 如果连接过程中发生错误,清理客户端实例
if (isError && this.client) {
try { this.client.close(); } catch { }
this.client = null;
this.state = 'disconnected';
try {
this.client.close()
} catch { }
this.client = null
this.state = 'disconnected'
}
// 返回连接结果
return {
success: isConnected && !isError,
message: errorMsg,
};
}
}
/**
@@ -244,12 +251,16 @@ export default abstract class BaseDanmakuClient {
public onRawMessage = (command: any) => {
// 触发 'all' 事件监听器 (两套系统都触发)
try {
this.eventsAsModel.all?.forEach((listener) => { listener(command); });
this.eventsRaw.all?.forEach((listener) => { listener(command); });
this.eventsAsModel.all?.forEach((listener) => {
listener(command)
})
this.eventsRaw.all?.forEach((listener) => {
listener(command)
})
} catch (err) {
console.error(`[${this.type}] 处理 'all' 事件监听器时出错:`, err, command);
console.error(`[${this.type}] 处理 'all' 事件监听器时出错:`, err, command)
}
};
}
// --- 抽象处理方法 (子类实现) ---
// 这些方法负责接收原始数据, 触发 RawEvent, 转换数据, 触发 ModelEvent
@@ -259,98 +270,96 @@ export default abstract class BaseDanmakuClient {
* @param data - 原始消息数据部分 (any 类型)
* @param rawCommand - 完整的原始消息对象 (可选, any 类型)
*/
public abstract onDanmaku(comand: any): void;
public abstract onDanmaku(comand: any): void
/**
* 处理礼物消息 (子类实现)
* @param data - 原始消息数据部分 (any 类型)
* @param rawCommand - 完整的原始消息对象 (可选, any 类型)
*/
public abstract onGift(comand: any): void;
public abstract onGift(comand: any): void
/**
* 处理 Super Chat 消息 (子类实现)
* @param data - 原始消息数据部分 (any 类型)
* @param rawCommand - 完整的原始消息对象 (可选, any 类型)
*/
public abstract onSC(comand: any): void;
public abstract onSC(comand: any): void
/**
* 处理上舰/舰队消息 (子类实现)
* @param data - 原始消息数据部分 (any 类型)
* @param rawCommand - 完整的原始消息对象 (可选, any 类型)
*/
public abstract onGuard(comand: any): void;
public abstract onGuard(comand: any): void
/**
* 处理用户进入消息 (子类实现)
* @param data - 原始消息数据部分 (any 类型)
* @param rawCommand - 完整的原始消息对象 (可选, any 类型)
*/
public abstract onEnter(comand: any): void;
public abstract onEnter(comand: any): void
/**
* 处理 SC 删除消息 (子类实现)
* @param data - 原始消息数据部分 (any 类型) - 通常可能只包含 message_id
* @param rawCommand - 完整的原始消息对象 (可选, any 类型)
*/
public abstract onScDel(comand: any): void;
* 处理 SC 删除消息 (子类实现)
* @param data - 原始消息数据部分 (any 类型) - 通常可能只包含 message_id
* @param rawCommand - 完整的原始消息对象 (可选, any 类型)
*/
public abstract onScDel(comand: any): void
// --- 事件系统 1: on/off (使用 EventModel) ---
public onEvent(eventName: 'danmaku', listener: (arg1: EventModel, arg2?: any) => void): this;
public onEvent(eventName: 'gift', listener: (arg1: EventModel, arg2?: any) => void): this;
public onEvent(eventName: 'sc', listener: (arg1: EventModel, arg2?: any) => void): this;
public onEvent(eventName: 'guard', listener: (arg1: EventModel, arg2?: any) => void): this;
public onEvent(eventName: 'enter', listener: (arg1: EventModel, arg2?: any) => void): this; // 新增
public onEvent(eventName: 'scDel', listener: (arg1: EventModel, arg2?: any) => void): this; // 新增
public onEvent(eventName: 'all', listener: (arg1: any) => void): this;
public onEvent(eventName: 'follow', listener: (arg1: EventModel, arg2?: any) => void): this; // 新增
public onEvent(eventName: 'danmaku', listener: (arg1: EventModel, arg2?: any) => void): this
public onEvent(eventName: 'gift', listener: (arg1: EventModel, arg2?: any) => void): this
public onEvent(eventName: 'sc', listener: (arg1: EventModel, arg2?: any) => void): this
public onEvent(eventName: 'guard', listener: (arg1: EventModel, arg2?: any) => void): this
public onEvent(eventName: 'enter', listener: (arg1: EventModel, arg2?: any) => void): this // 新增
public onEvent(eventName: 'scDel', listener: (arg1: EventModel, arg2?: any) => void): this // 新增
public onEvent(eventName: 'all', listener: (arg1: any) => void): this
public onEvent(eventName: 'follow', listener: (arg1: EventModel, arg2?: any) => void): this // 新增
public onEvent(eventName: keyof BaseDanmakuClient['eventsAsModel'], listener: (...args: any[]) => void): this {
if (!this.eventsAsModel[eventName]) {
// @ts-ignore
this.eventsAsModel[eventName] = [];
this.eventsAsModel[eventName] = []
}
// @ts-ignore
this.eventsAsModel[eventName].push(listener);
return this;
this.eventsAsModel[eventName].push(listener)
return this
}
public offEvent(eventName: keyof BaseDanmakuClient['eventsAsModel'], listener: (...args: any[]) => void): this {
if (this.eventsAsModel[eventName]?.length) {
// @ts-ignore
const index = this.eventsAsModel[eventName].indexOf(listener);
const index = this.eventsAsModel[eventName].indexOf(listener)
if (index > -1) {
this.eventsAsModel[eventName].splice(index, 1);
this.eventsAsModel[eventName].splice(index, 1)
}
}
return this;
return this
}
// --- 事件系统 2: on/off (使用原始数据) ---
// 注意: listener 的 arg1 类型为 any, 需要调用者根据 eventName 自行转换或处理
public on(eventName: 'danmaku', listener: (arg1: any, arg2?: any) => void): this;
public on(eventName: 'gift', listener: (arg1: any, arg2?: any) => void): this;
public on(eventName: 'sc', listener: (arg1: any, arg2?: any) => void): this;
public on(eventName: 'guard', listener: (arg1: any, arg2?: any) => void): this;
public on(eventName: 'enter', listener: (arg1: any, arg2?: any) => void): this; // 新增
public on(eventName: 'scDel', listener: (arg1: any, arg2?: any) => void): this; // 新增
public on(eventName: 'all', listener: (arg1: any) => void): this;
public on(eventName: 'follow', listener: (arg1: any, arg2?: any) => void): this; // 新增
public on(eventName: 'danmaku', listener: (arg1: any, arg2?: any) => void): this
public on(eventName: 'gift', listener: (arg1: any, arg2?: any) => void): this
public on(eventName: 'sc', listener: (arg1: any, arg2?: any) => void): this
public on(eventName: 'guard', listener: (arg1: any, arg2?: any) => void): this
public on(eventName: 'enter', listener: (arg1: any, arg2?: any) => void): this // 新增
public on(eventName: 'scDel', listener: (arg1: any, arg2?: any) => void): this // 新增
public on(eventName: 'all', listener: (arg1: any) => void): this
public on(eventName: 'follow', listener: (arg1: any, arg2?: any) => void): this // 新增
public on(eventName: keyof BaseDanmakuClient['eventsRaw'], listener: (...args: any[]) => void): this {
if (!this.eventsRaw[eventName]) {
// @ts-ignore
this.eventsRaw[eventName] = [];
this.eventsRaw[eventName] = []
}
// @ts-ignore
this.eventsRaw[eventName].push(listener);
return this;
this.eventsRaw[eventName].push(listener)
return this
}
public off(eventName: keyof BaseDanmakuClient['eventsRaw'], listener: (...args: any[]) => void): this {
if (this.eventsRaw[eventName]?.length) {
// @ts-ignore
const index = this.eventsRaw[eventName].indexOf(listener);
const index = this.eventsRaw[eventName].indexOf(listener)
if (index > -1) {
this.eventsRaw[eventName].splice(index, 1);
this.eventsRaw[eventName].splice(index, 1)
}
}
return this;
return this
}
}
}