floating-live 0.17.0-alpha.13 → 0.17.0-alpha.14

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE CHANGED
@@ -1,9 +1,9 @@
1
- MIT License
2
-
3
- Copyright (c) 2023 Minteea
4
-
5
- Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
6
-
7
- The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
8
-
1
+ MIT License
2
+
3
+ Copyright (c) 2023 Minteea
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
6
+
7
+ The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
8
+
9
9
  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
package/README.md CHANGED
@@ -1,36 +1,36 @@
1
- # Floating Live
2
-
3
- 一个用于处理和保存直播弹幕的 Web 小工具,开箱即用。
4
-
5
- 本体无弹幕获取功能,需要配合[floating-live-plugins](https://github.com/Minteea/floating-live-plugins)中的插件使用。
6
-
7
- 目前插件库支持 bilibili 和 AcFun 的直播弹幕,不同平台的弹幕会转换为同一种格式便于保存。
8
-
9
- 项目仍在开发中,功能尚未完善,目前除了记录保存直播弹幕外暂时没有别的用处啦,敬请期待。
10
-
11
- 注意:当前项目未进入正式版本阶段,程序结构及导出数据结构可能随时改动,**非常不建议用于正式项目中**。
12
-
13
- GUI 版本:[Minteea/floating-live-gui](https://github.com/Minteea/floating-live-gui)
14
-
15
- ## 使用方法
16
-
17
- ### npm 安装
18
-
19
- ```
20
- npm install floating-live
21
- ```
22
-
23
- ```javascript
24
- // 导入FloatingLive本体
25
- import { FloatingLive } from "floating-live";
26
- // 导入bilibili房间生成插件
27
- import bilibili from "@floating-live/bilibili";
28
-
29
- // 创建一个FloatingLive实例
30
- const live = new FloatingLive();
31
- // 注册插件
32
- live.plugin.register(bilibili);
33
-
34
- // 添加房间并自动打开
35
- live.room.add("bilibili", 6, true);
36
- ```
1
+ # Floating Live
2
+
3
+ 一个用于处理和保存直播弹幕的 Web 小工具,开箱即用。
4
+
5
+ 本体无弹幕获取功能,需要配合[floating-live-plugins](https://github.com/Minteea/floating-live-plugins)中的插件使用。
6
+
7
+ 目前插件库支持 bilibili 和 AcFun 的直播弹幕,不同平台的弹幕会转换为同一种格式便于保存。
8
+
9
+ 项目仍在开发中,功能尚未完善,目前除了记录保存直播弹幕外暂时没有别的用处啦,敬请期待。
10
+
11
+ 注意:当前项目未进入正式版本阶段,程序结构及导出数据结构可能随时改动,**非常不建议用于正式项目中**。
12
+
13
+ GUI 版本:[Minteea/floating-live-gui](https://github.com/Minteea/floating-live-gui)
14
+
15
+ ## 使用方法
16
+
17
+ ### npm 安装
18
+
19
+ ```
20
+ npm install floating-live
21
+ ```
22
+
23
+ ```javascript
24
+ // 导入FloatingLive本体
25
+ import { FloatingLive } from "floating-live";
26
+ // 导入bilibili房间生成插件
27
+ import bilibili from "@floating-live/bilibili";
28
+
29
+ // 创建一个FloatingLive实例
30
+ const live = new FloatingLive();
31
+ // 注册插件
32
+ live.plugin.register(bilibili);
33
+
34
+ // 添加房间并自动打开
35
+ live.room.add("bilibili", 6, true);
36
+ ```
@@ -1,4 +1,9 @@
1
1
  import { appError } from "../error/index.js";
2
+ // 错误列表
3
+ // command:notFound 命令不存在
4
+ // command:alreadyExists 命令已存在
5
+ // command:aliasNotFound 命令别名指向的命令不存在
6
+ // command:aliasTargetUncallable 命令别名不可指向其他命令别名
2
7
  export class CommandManager {
3
8
  /** 功能列表 */
4
9
  list = new Map();
@@ -31,9 +36,10 @@ export class CommandManager {
31
36
  callWithOptions(name, options, ...args) {
32
37
  const command = this.list.get(name);
33
38
  if (!command) {
34
- throw appError("command:call_unexist", {
39
+ throw appError("command:notFound", {
35
40
  message: `命令不存在[${name}]`,
36
41
  target: `command/${name}`,
42
+ action: "command.call",
37
43
  });
38
44
  }
39
45
  else {
@@ -50,17 +56,19 @@ export class CommandManager {
50
56
  _callAliasWithOptions(name, targetName, options, ...args) {
51
57
  const tcommand = this.list.get(targetName);
52
58
  if (!tcommand) {
53
- throw appError("command:alias_unexist", {
59
+ throw appError("command:aliasNotFound", {
54
60
  message: `命令别名[${name}]指向的命令不存在[${targetName}]`,
55
61
  target: `command/${name}>${targetName}`,
62
+ action: "command.call",
56
63
  });
57
64
  }
58
65
  else {
59
66
  const { call } = tcommand;
60
67
  if (!call) {
61
- throw appError("command:alias_target_uncallable", {
68
+ throw appError("command:aliasTargetUncallable", {
62
69
  message: `命令别名[${name}]不可指向其他命令别名[${targetName}]`,
63
70
  target: `command/${name}>${targetName}>${tcommand.targetName}`,
71
+ action: "command.call",
64
72
  });
65
73
  }
66
74
  return call({ source: options.source, client: options.client }, ...args);
@@ -8,6 +8,8 @@ export interface AppError extends Error {
8
8
  target?: string;
9
9
  /** 错误原因 */
10
10
  reason?: string | Error | AppError;
11
+ /** 调用行为 */
12
+ action?: string;
11
13
  };
12
14
  }
13
15
  export interface AppErrorOptions {
@@ -17,8 +19,10 @@ export interface AppErrorOptions {
17
19
  target?: string;
18
20
  /** 错误原因 */
19
21
  reason?: string | Error | AppError;
22
+ /** 调用行为 */
23
+ action?: string;
20
24
  /** 错误构造函数 */
21
25
  errorConstructor?: ErrorConstructor;
22
26
  [key: string]: unknown;
23
27
  }
24
- export declare function appError(code: string, { message, target, reason, errorConstructor }: AppErrorOptions): AppError;
28
+ export declare function appError(code: string, { message, target, reason, action, errorConstructor, }: AppErrorOptions): AppError;
@@ -1,10 +1,14 @@
1
1
  export * from "./types.js";
2
- export function appError(code, { message, target, reason, errorConstructor = Error }) {
2
+ export function appError(code, { message, target, reason, action, errorConstructor = Error, }) {
3
3
  return new errorConstructor(message, {
4
4
  cause: {
5
5
  code,
6
6
  target,
7
7
  reason,
8
+ action,
8
9
  },
9
10
  });
10
11
  }
12
+ // 错误码分类
13
+ // http:xxx http状态码
14
+ // node:xxx nodejs错误码
@@ -1,4 +1,7 @@
1
1
  import { appError } from "../error/index.js";
2
+ // 错误列表
3
+ // hook:functionAlreadyExists 钩子函数已存在
4
+ // hook:functionNotFound 钩子函数不存在
2
5
  export class HookManager {
3
6
  list = new Map();
4
7
  pluginMap = new Map();
@@ -16,10 +19,10 @@ export class HookManager {
16
19
  this.list.set(name, hooks);
17
20
  }
18
21
  else if (hooks.includes(call)) {
19
- throw appError("hook:use_duplicate", {
20
- message: `钩子函数挂载失败: ${name}`,
21
- reason: "重复挂载同一函数",
22
+ throw appError("hook:functionAlreadyExists", {
23
+ message: `无法重复挂载同一钩子函数: ${name}`,
22
24
  target: `hook/${name}`,
25
+ action: "hook.use",
23
26
  });
24
27
  }
25
28
  hooks.push({ call, pluginName });
@@ -29,10 +32,10 @@ export class HookManager {
29
32
  let hooks = this.list.get(name);
30
33
  const index = hooks?.findIndex((item) => item.call == call) ?? -1;
31
34
  if (!hooks || index < 0)
32
- throw appError("hook:unuse_unexist", {
33
- message: `钩子函数卸载失败: ${name}`,
34
- reason: "卸载不存在的钩子函数",
35
+ throw appError("hook:functionNotFound", {
36
+ message: `无法卸载不存在的钩子函数: ${name}`,
35
37
  target: `hook/${name}`,
38
+ action: "hook.unuse",
36
39
  });
37
40
  hooks.splice(index, 1);
38
41
  }
@@ -1,5 +1,7 @@
1
1
  import { DanmakuMode, UserInfo, ImageInfo, GiftInfo, UserType } from "./messageInfo.js";
2
2
  import { LiveRoomStatus, LiveRoomStatsInfo, LiveRoomDetailInfo } from "./room.js";
3
+ export interface LiveMessageExtensions {
4
+ }
3
5
  export declare namespace LiveMessage {
4
6
  interface Base {
5
7
  /** 平台名称 */
@@ -12,10 +14,17 @@ export declare namespace LiveMessage {
12
14
  type: string;
13
15
  /** 时间戳 */
14
16
  timestamp: number;
15
- /** 消息id */
17
+ /** 消息id
18
+ *
19
+ * 须保证不重复性,规范id格式如下:
20
+ *
21
+ * 用户相关消息:platform:roomId-type:userId-uniqueId
22
+ *
23
+ * 房间相关消息:platform:roomId-type-uniqueId
24
+ * */
16
25
  id: string;
17
- /** 其他属性 */
18
- [attr: string]: any;
26
+ /** 拓展属性 */
27
+ extension?: LiveMessageExtensions;
19
28
  }
20
29
  /** 聊天消息 */
21
30
  interface Comment extends Base {
@@ -81,8 +90,8 @@ export declare namespace LiveMessage {
81
90
  interface Superchat extends Base {
82
91
  type: "superchat";
83
92
  info: {
84
- /** 留言id */
85
- id: string | number;
93
+ /** 留言代码,用于撤回消息 */
94
+ token: string | number;
86
95
  /** 用户信息 */
87
96
  user: UserInfo;
88
97
  /** 文本内容 */
@@ -129,6 +138,7 @@ export declare namespace LiveMessage {
129
138
  info: {
130
139
  /** 切断消息 */
131
140
  message: string;
141
+ status: LiveRoomStatus;
132
142
  };
133
143
  }
134
144
  /** 直播数据更新 */
@@ -141,57 +151,5 @@ export declare namespace LiveMessage {
141
151
  type: "live_detail";
142
152
  info: LiveRoomDetailInfo;
143
153
  }
144
- /** 主播抽奖 */
145
- interface Lottery extends Base {
146
- type: "lottery";
147
- info: {
148
- title: string;
149
- role: "user" | "anchor";
150
- user?: UserInfo;
151
- gift?: GiftInfo;
152
- id: string | number;
153
- award?: GiftInfo | GiftInfo[];
154
- value?: number;
155
- valueType?: string | number;
156
- price?: number;
157
- currency?: string;
158
- };
159
- }
160
- /** 主播抽奖结果 */
161
- interface LotteryResult extends Base {
162
- type: "lottery_result";
163
- info: {
164
- title: string;
165
- role: "user" | "anchor";
166
- id: string | number;
167
- result: {
168
- user: UserInfo;
169
- award: GiftInfo | GiftInfo[];
170
- }[];
171
- };
172
- }
173
- /** 发送红包 */
174
- interface Redpacket extends Base {
175
- type: "redpacket";
176
- info: {
177
- id: string | number;
178
- gifts?: GiftInfo[];
179
- value?: number;
180
- currency?: string | number;
181
- };
182
- }
183
- /** 红包抽奖结果 */
184
- interface RedpacketResult extends Base {
185
- type: "redpacket_result";
186
- info: {
187
- id: string | number;
188
- result: {
189
- user: UserInfo;
190
- gift?: GiftInfo;
191
- value?: number;
192
- currency?: string | number;
193
- }[];
194
- };
195
- }
196
- type All = Comment | Gift | Interact | Membership | Superchat | Block | LiveStart | LiveEnd | LiveCut | LiveDetail | LiveStats | Lottery | LotteryResult;
154
+ type All = Comment | Gift | Interact | Membership | Superchat | Block | LiveStart | LiveEnd | LiveCut | LiveDetail | LiveStats;
197
155
  }
@@ -13,8 +13,8 @@ export interface UserInfo {
13
13
  type?: UserType;
14
14
  /** 粉丝vip等级 */
15
15
  membership?: boolean | number;
16
- /** vip等级 */
17
- vip?: boolean | number;
16
+ /** 平台vip等级 */
17
+ premium?: boolean | number;
18
18
  /** 用户等级 */
19
19
  level?: number;
20
20
  }
@@ -50,10 +50,12 @@ export interface GiftInfo {
50
50
  num: number;
51
51
  /** 礼物价值(总价,按平台货币计算) */
52
52
  value?: number;
53
- /** 价值类型 */
54
- valueType?: string | number;
53
+ /** 显示的礼物价值 */
54
+ displayValue?: number;
55
+ /** 平台货币类型 */
56
+ coinType?: string | number;
55
57
  /** 平台货币名称 */
56
- valueName?: string;
58
+ coinName?: string;
57
59
  /** 礼物连击数 */
58
60
  combo?: number;
59
61
  /** 礼物连击id */
@@ -2,7 +2,7 @@ export interface LivePlatformInfo {
2
2
  /** 平台名称 */
3
3
  name: string;
4
4
  /** 平台vip信息 */
5
- vip?: {
5
+ premium?: {
6
6
  /** 平台vip对应id */
7
7
  id: string;
8
8
  /** 平台vip名称 */
@@ -10,8 +10,8 @@ export declare abstract class LiveRoom extends CustomEventEmitter implements Liv
10
10
  get service(): string;
11
11
  /** 平台 */
12
12
  abstract readonly platform: string;
13
- /** api服务 */
14
- readonly serviceName: string;
13
+ /** 服务分支 */
14
+ readonly serviceBranch: string;
15
15
  /** 房间id */
16
16
  abstract readonly id: string | number;
17
17
  /** 房间详情 */
@@ -68,7 +68,7 @@ export declare class InvalidLiveRoom implements LiveRoomData {
68
68
  });
69
69
  readonly platform: string;
70
70
  readonly id: string | number;
71
- readonly serviceName: string;
71
+ readonly serviceBranch: string;
72
72
  pending: boolean;
73
73
  detail: LiveRoomDetailInfo;
74
74
  stats?: LiveRoomStatsInfo;
@@ -100,11 +100,11 @@ export interface LiveRoomData {
100
100
  /** 房间有效性 */
101
101
  valid: boolean;
102
102
  /** 房间待定状态 */
103
- pending: boolean;
103
+ pending?: boolean;
104
104
  /** 平台id */
105
105
  platform: string;
106
- /** API服务 */
107
- serviceName: string;
106
+ /** 服务分支 */
107
+ serviceBranch: string;
108
108
  /** 房间id */
109
109
  id: number | string;
110
110
  /** API服务id */
package/dist/live/room.js CHANGED
@@ -11,12 +11,12 @@ export class LiveRoom extends CustomEventEmitter {
11
11
  return false;
12
12
  }
13
13
  get service() {
14
- return this.serviceName
15
- ? `${this.platform}.${this.serviceName}`
14
+ return this.serviceBranch
15
+ ? `${this.platform}.${this.serviceBranch}`
16
16
  : this.platform;
17
17
  }
18
- /** api服务 */
19
- serviceName = "";
18
+ /** 服务分支 */
19
+ serviceBranch = "";
20
20
  /** 统计信息 */
21
21
  stats;
22
22
  /** 直播状态 */
@@ -66,11 +66,11 @@ export class LiveRoom extends CustomEventEmitter {
66
66
  break;
67
67
  case "live_end":
68
68
  case "live_cut":
69
- this.status = msg.status || LiveRoomStatus.off;
69
+ this.status = msg.info.status || LiveRoomStatus.off;
70
70
  this.timestamp = msg.timestamp;
71
71
  this.emit("message", { message: msg });
72
72
  this.emit("status", {
73
- status: msg.status || LiveRoomStatus.off,
73
+ status: msg.info.status || LiveRoomStatus.off,
74
74
  timestamp: msg.timestamp,
75
75
  liveId: this.liveId,
76
76
  });
@@ -88,7 +88,7 @@ export class LiveRoom extends CustomEventEmitter {
88
88
  valid: this.valid,
89
89
  pending: this.pending,
90
90
  platform: this.platform,
91
- serviceName: this.serviceName,
91
+ serviceBranch: this.serviceBranch,
92
92
  id: this.id,
93
93
  detail: this.detail,
94
94
  stats: this.stats,
@@ -114,21 +114,21 @@ export class InvalidLiveRoom {
114
114
  return false;
115
115
  }
116
116
  get service() {
117
- return this.serviceName
118
- ? `${this.platform}.${this.serviceName}`
117
+ return this.serviceBranch
118
+ ? `${this.platform}.${this.serviceBranch}`
119
119
  : this.platform;
120
120
  }
121
121
  constructor(service, id, { pending = false, error = null } = {}) {
122
122
  const [platform, ...serviceIdArr] = service.split(".");
123
123
  this.platform = platform;
124
124
  this.id = id;
125
- this.serviceName = serviceIdArr.join(".");
125
+ this.serviceBranch = serviceIdArr.join(".");
126
126
  this.pending = pending;
127
127
  this.error = error;
128
128
  }
129
129
  platform;
130
130
  id;
131
- serviceName;
131
+ serviceBranch;
132
132
  pending;
133
133
  detail = {};
134
134
  stats;
@@ -149,7 +149,7 @@ export class InvalidLiveRoom {
149
149
  valid: this.valid,
150
150
  pending: this.pending,
151
151
  platform: this.platform,
152
- serviceName: this.serviceName,
152
+ serviceBranch: this.serviceBranch,
153
153
  id: this.id,
154
154
  detail: this.detail,
155
155
  stats: this.stats,
@@ -1,5 +1,7 @@
1
1
  import { appError } from "../../error/index.js";
2
2
  import { CommonPluginContext } from "./CommonPluginContext.js";
3
+ // 错误列表
4
+ // plugin:noPermission 插件权限不足
3
5
  export class SafePluginContext extends CommonPluginContext {
4
6
  get safe() {
5
7
  return true;
@@ -10,7 +12,7 @@ export class SafePluginContext extends CommonPluginContext {
10
12
  this.#permissions = options.permissions;
11
13
  }
12
14
  throwNotPermitted(permission, reason) {
13
- throw appError("plugin:no_permission", {
15
+ throw appError("plugin:noPermission", {
14
16
  message: "插件权限不足",
15
17
  reason,
16
18
  permission,
@@ -1,6 +1,13 @@
1
1
  import { CommonPluginContext } from "./context/CommonPluginContext.js";
2
2
  import { bindCommand } from "../utils/index.js";
3
3
  import { appError } from "../error/index.js";
4
+ // 错误列表
5
+ // plugin:missingName 插件pluginName字段缺失
6
+ // plugin:duplicateName 已存在相同名称的插件
7
+ // plugin:unremovable 插件不可移除
8
+ // plugin:registerFailed 插件注册失败
9
+ // plugin:notFound 插件不存在
10
+ // app:hookPrevented 被钩子函数阻止
4
11
  export class PluginManager {
5
12
  /** 插件列表 */
6
13
  list = new Map();
@@ -14,15 +21,17 @@ export class PluginManager {
14
21
  const pluginName = pluginConstructor.pluginName;
15
22
  const role = pluginConstructor.role || "";
16
23
  if (!pluginName) {
17
- throw appError("plugin:register_id_missing", {
24
+ throw appError("plugin:missingName", {
18
25
  message: "插件注册失败: 插件缺少pluginName字段",
19
26
  target: "plugin/#unnamed",
27
+ action: "plugin.registerSync",
20
28
  });
21
29
  }
22
30
  if (this.list.has(pluginName)) {
23
- throw appError("plugin:register_id_duplicate", {
24
- message: `插件注册失败[${pluginName}]: 已存在相同id的插件`,
31
+ throw appError("plugin:duplicateName", {
32
+ message: `插件注册失败[${pluginName}]: 已存在相同名称的插件`,
25
33
  target: `plugin/${pluginName}`,
34
+ action: "plugin.registerSync",
26
35
  });
27
36
  }
28
37
  const registerCtx = { pluginName, options };
@@ -30,9 +39,10 @@ export class PluginManager {
30
39
  try {
31
40
  const ctx = this.app.callHookSync("plugin.register", registerCtx);
32
41
  if (ctx.defaultPrevented)
33
- throw appError("plugin:register_hook_prevented", {
42
+ throw appError("app:hookPrevented", {
34
43
  message: `插件注册失败${pluginName}: 插件注册被钩子函数阻止`,
35
44
  target: `plugin/${pluginName}`,
45
+ action: "plugin.registerSync",
36
46
  });
37
47
  // 执行插件函数
38
48
  const plugin = new pluginConstructor(pluginCtx, registerCtx.options || {});
@@ -68,10 +78,11 @@ export class PluginManager {
68
78
  return plugin;
69
79
  }
70
80
  catch (err) {
71
- throw appError("plugin:register_fail", {
81
+ throw appError("plugin:registerFailed", {
72
82
  message: `插件注册失败: ${pluginName}`,
73
83
  reason: err,
74
84
  target: `plugin/${pluginName}`,
85
+ action: "plugin.registerSync",
75
86
  });
76
87
  }
77
88
  }
@@ -80,15 +91,17 @@ export class PluginManager {
80
91
  const pluginName = pluginConstructor.pluginName;
81
92
  const role = pluginConstructor.role || "";
82
93
  if (!pluginName) {
83
- throw appError("plugin:register_id_missing", {
94
+ throw appError("plugin:missingName", {
84
95
  message: "插件注册失败: 插件缺少pluginName字段",
85
96
  target: "plugin/#unnamed",
97
+ action: "plugin.register",
86
98
  });
87
99
  }
88
100
  if (this.list.has(pluginName)) {
89
- throw appError("plugin:register_id_duplicate", {
90
- message: `插件注册失败[${pluginName}]: 已存在相同id的插件`,
101
+ throw appError("plugin:duplicateName", {
102
+ message: `插件注册失败[${pluginName}]: 已存在相同名称的插件`,
91
103
  target: `plugin/${pluginName}`,
104
+ action: "plugin.register",
92
105
  });
93
106
  }
94
107
  const registerCtx = { pluginName, options };
@@ -97,9 +110,10 @@ export class PluginManager {
97
110
  .callHook("plugin.register", registerCtx)
98
111
  .then(async (ctx) => {
99
112
  if (ctx.defaultPrevented)
100
- throw appError("plugin:register_hook_prevented", {
113
+ throw appError("app:hookPrevented", {
101
114
  message: `插件注册失败${pluginName}: 插件注册被钩子函数阻止`,
102
115
  target: `plugin/${pluginName}`,
116
+ action: "plugin.register",
103
117
  });
104
118
  // 执行插件函数
105
119
  const plugin = new pluginConstructor(pluginCtx, registerCtx.options || {});
@@ -134,10 +148,11 @@ export class PluginManager {
134
148
  return plugin;
135
149
  })
136
150
  .catch((err) => {
137
- throw appError("plugin:register_fail", {
151
+ throw appError("plugin:registerFailed", {
138
152
  message: `插件注册失败: ${pluginName}`,
139
153
  reason: err,
140
154
  target: `plugin/${pluginName}`,
155
+ action: "plugin.register",
141
156
  });
142
157
  });
143
158
  }
@@ -146,17 +161,19 @@ export class PluginManager {
146
161
  const pluginData = this.list.get(pluginName);
147
162
  // 检测插件是否存在
148
163
  if (!pluginData) {
149
- throw appError("plugin:unregister_unexist", {
164
+ throw appError("plugin:notFound", {
150
165
  message: `插件移除失败[${pluginName}]: 插件不存在`,
151
166
  target: `plugin/${pluginName}`,
167
+ action: "plugin.unregister",
152
168
  });
153
169
  }
154
170
  else {
155
171
  const { plugin, context, unremovable, role } = pluginData;
156
172
  if (unremovable) {
157
- throw appError("plugin:unregister_unremovable", {
173
+ throw appError("plugin:unremovable", {
158
174
  message: `插件移除失败[${pluginName}]: 该插件已配置为不可移除`,
159
175
  target: `plugin/${pluginName}`,
176
+ action: "plugin.unregister",
160
177
  });
161
178
  }
162
179
  // 调用插件和上下文的destroy钩子
@@ -11,8 +11,10 @@ export class Platform extends BasePlugin {
11
11
  /** 注册直播平台信息 */
12
12
  register(name, info, signal) {
13
13
  if (this.list.has(name)) {
14
- throw appError("platform:register_duplicated", {
15
- message: "平台信息重复注册",
14
+ throw appError("platform:alreadyExists", {
15
+ message: "平台信息已存在",
16
+ target: `platform/${name}`,
17
+ action: "platform.register",
16
18
  });
17
19
  }
18
20
  this.list.set(name, info);
@@ -25,8 +27,10 @@ export class Platform extends BasePlugin {
25
27
  /** 解除注册直播平台信息 */
26
28
  unregister(name) {
27
29
  if (!this.list.has(name)) {
28
- throw appError("platform:unregister_unexisted", {
30
+ throw appError("platform:notFound", {
29
31
  message: "无法解除不存在的平台信息注册",
32
+ target: `platform/${name}`,
33
+ action: "platform.unregister",
30
34
  });
31
35
  }
32
36
  this.list.delete(name);
@@ -49,9 +49,10 @@ export class Room extends BasePlugin {
49
49
  attach(room, open) {
50
50
  const key = room.key;
51
51
  if (this.map.has(key)) {
52
- throw appError("room:add_exist", {
52
+ throw appError("room:alreadyExists", {
53
53
  message: `房间已存在[${key}]`,
54
54
  target: `room/${key}`,
55
+ action: "room.add",
55
56
  });
56
57
  }
57
58
  this.map.set(key, room);
@@ -68,9 +69,10 @@ export class Room extends BasePlugin {
68
69
  detach(key) {
69
70
  const room = this.map.get(key);
70
71
  if (!room) {
71
- throw appError("room:remove_unexist", {
72
+ throw appError("room:notFound", {
72
73
  message: `房间不存在[${key}]`,
73
74
  target: `room/${key}`,
75
+ action: "room.remove",
74
76
  });
75
77
  }
76
78
  this.map.delete(key); // 从表中删除房间
@@ -214,15 +216,18 @@ export class Room extends BasePlugin {
214
216
  const res = await this.ctx
215
217
  .callHook("room.create", ctx)
216
218
  .catch((reason) => {
217
- throw appError("room:create_hook_error", {
219
+ throw appError("app:hookError", {
218
220
  message: `无法创建房间监听实例[${service}:${id}]: 调用钩子函数出错`,
219
221
  target: `room/${service}:${id}`,
222
+ action: "room.create",
223
+ reason,
220
224
  });
221
225
  });
222
226
  if (res.defaultPrevented) {
223
- throw appError("room:create_hook_prevented", {
227
+ throw appError("app:hookPrevented", {
224
228
  message: `无法创建房间监听实例[${service}:${id}]: 房间添加被钩子函数阻止`,
225
229
  target: `room/${service}:${id}`,
230
+ action: "room.create",
226
231
  });
227
232
  }
228
233
  }
@@ -243,10 +248,11 @@ export class Room extends BasePlugin {
243
248
  room = new InvalidLiveRoom(service, id);
244
249
  }
245
250
  else {
246
- throw appError("room:create_fail", {
251
+ throw appError("room:createFailed", {
247
252
  message: `创建房间监听实例失败[${service}:${id}]`,
248
253
  reason: e,
249
254
  target: `room/${service}:${id}`,
255
+ action: "room.create",
250
256
  });
251
257
  }
252
258
  }
@@ -260,10 +266,11 @@ export class Room extends BasePlugin {
260
266
  room.destroy?.();
261
267
  }
262
268
  catch (e) {
263
- throw appError("room:destroy_fail", {
269
+ throw appError("room:destroyFailed", {
264
270
  message: `销毁房间实例失败[${key}]`,
265
271
  reason: e,
266
272
  target: `room/${key}`,
273
+ action: "room.remove",
267
274
  });
268
275
  }
269
276
  }
@@ -272,15 +279,17 @@ export class Room extends BasePlugin {
272
279
  async validate(key, options) {
273
280
  let invalidRoom = this.map.get(key);
274
281
  if (!invalidRoom) {
275
- throw appError("room:validate_unexist", {
282
+ throw appError("room:notFound", {
276
283
  message: `房间不存在[${key}]`,
277
284
  target: `room/${key}`,
285
+ action: "room.validate",
278
286
  });
279
287
  }
280
288
  if (invalidRoom.valid == true) {
281
- throw appError("room:validate_valid", {
289
+ throw appError("room:alreadyValid", {
282
290
  message: `无法使已经有效的房间生效[${key}]`,
283
291
  target: `room/${key}`,
292
+ action: "room.validate",
284
293
  });
285
294
  }
286
295
  const { service, id } = invalidRoom;
@@ -299,15 +308,17 @@ export class Room extends BasePlugin {
299
308
  invalidate(key) {
300
309
  let room = this.map.get(key);
301
310
  if (!room) {
302
- throw appError("room:invalidate_unexist", {
311
+ throw appError("room:notFound", {
303
312
  message: `房间不存在[${key}]`,
304
313
  target: `room/${key}`,
314
+ action: "room.invalidate",
305
315
  });
306
316
  }
307
317
  if (!room.valid) {
308
- throw appError("room:invalidate_invalid", {
318
+ throw appError("room:alreadyInvalid", {
309
319
  message: `无法使已经无效的房间失效[${key}]`,
310
320
  target: `room/${key}`,
321
+ action: "room.invalidate",
311
322
  });
312
323
  }
313
324
  // 用无效房间替换掉原房间
@@ -322,10 +333,11 @@ export class Room extends BasePlugin {
322
333
  room.destroy?.();
323
334
  }
324
335
  catch (e) {
325
- throw appError("room:destroy_fail", {
336
+ throw appError("room:destroyFailed", {
326
337
  message: `销毁房间实例失败[${key}]`,
327
338
  reason: e,
328
339
  target: `room/${key}`,
340
+ action: "room.invalidate",
329
341
  });
330
342
  }
331
343
  }
@@ -358,15 +370,17 @@ export class Room extends BasePlugin {
358
370
  open(key) {
359
371
  let room = this.map.get(key);
360
372
  if (!room) {
361
- throw appError("room:open_unexist", {
373
+ throw appError("room:notFound", {
362
374
  message: "要打开的房间不存在",
363
375
  target: `room/${key}`,
376
+ action: "room.open",
364
377
  });
365
378
  }
366
379
  if (!room.valid) {
367
- throw appError("room:open_invalid", {
380
+ throw appError("room:invalid", {
368
381
  message: "要打开的房间无效",
369
382
  target: `room/${key}`,
383
+ action: "room.open",
370
384
  });
371
385
  }
372
386
  room.open();
@@ -375,15 +389,17 @@ export class Room extends BasePlugin {
375
389
  close(key) {
376
390
  let room = this.map.get(key);
377
391
  if (!room) {
378
- throw appError("room:close_unexist", {
392
+ throw appError("room:notFound", {
379
393
  message: "关闭的房间不存在",
380
394
  target: `room/${key}`,
395
+ action: "room.close",
381
396
  });
382
397
  }
383
398
  if (!room.valid) {
384
- throw appError("room:close_invalid", {
399
+ throw appError("room:invalid", {
385
400
  message: "要关闭的房间无效",
386
401
  target: `room/${key}`,
402
+ action: "room.close",
387
403
  });
388
404
  }
389
405
  room.close();
@@ -393,9 +409,10 @@ export class Room extends BasePlugin {
393
409
  const arr = [...this.map];
394
410
  const index = arr.findIndex(([k]) => k == key);
395
411
  if (index == -1) {
396
- throw appError("room:move_unexist", {
412
+ throw appError("room:notFound", {
397
413
  message: "要移动的房间不存在",
398
414
  target: `room/${key}`,
415
+ action: "room.move",
399
416
  });
400
417
  }
401
418
  const [item] = arr.splice(index, 1);
@@ -408,9 +425,10 @@ export class Room extends BasePlugin {
408
425
  const arr = [...this.map];
409
426
  const index = arr.findIndex(([k]) => k == oldKey);
410
427
  if (index == -1) {
411
- throw appError("room:changekey_unexist", {
428
+ throw appError("room:notFound", {
412
429
  message: "要更改key的房间不存在",
413
430
  target: `room/${oldKey}`,
431
+ action: "room.changeKey",
414
432
  });
415
433
  }
416
434
  let room = arr[index][1];
@@ -1,5 +1,8 @@
1
1
  import { appError } from "../error/index.js";
2
2
  import { bindCommand } from "../utils/index.js";
3
+ // 错误列表
4
+ // value:notFound 值不存在
5
+ // value:alreadyExists 值已存在
3
6
  export class ValueManager {
4
7
  list = new Map();
5
8
  app;
@@ -9,6 +12,13 @@ export class ValueManager {
9
12
  }
10
13
  /** 注册值 */
11
14
  register(name, { get, set, pluginName }) {
15
+ if (this.list.has(name)) {
16
+ throw appError("value:alreadyExists", {
17
+ message: "值已存在",
18
+ target: `value/${name}`,
19
+ action: "value.register",
20
+ });
21
+ }
12
22
  this.list.set(name, { get, set, pluginName });
13
23
  this.app.emit("value:register", { name, value: get() }, { source: `plugin:${pluginName}` });
14
24
  return {
@@ -19,15 +29,26 @@ export class ValueManager {
19
29
  }
20
30
  /** 注销值 */
21
31
  unregister(name) {
22
- this.list.delete(name);
23
- this.app.emit("value:unregister", { name });
32
+ const result = this.list.delete(name);
33
+ if (!result) {
34
+ throw appError("value:notFound", {
35
+ message: "无法注销未注册的值",
36
+ target: `value/${name}`,
37
+ action: "value.unregister",
38
+ });
39
+ }
40
+ else {
41
+ this.app.emit("value:unregister", { name });
42
+ }
24
43
  }
25
44
  /** 获取值 */
26
45
  get(name, options) {
27
46
  const item = this.list.get(name);
28
47
  if (!item)
29
- throw appError("value:get_unexist", {
48
+ throw appError("value:notFound", {
30
49
  message: "无法获取未注册的值",
50
+ target: `value/${name}`,
51
+ action: "value.get",
31
52
  });
32
53
  return item.get(options);
33
54
  }
@@ -39,7 +60,7 @@ export class ValueManager {
39
60
  set(name, value, options) {
40
61
  const valueItem = this.list.get(name);
41
62
  if (valueItem?.set) {
42
- valueItem?.set(value, options);
63
+ valueItem.set(value, options);
43
64
  return true;
44
65
  }
45
66
  else {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "floating-live",
3
- "version": "0.17.0-alpha.13",
3
+ "version": "0.17.0-alpha.14",
4
4
  "type": "module",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",