koishi-plugin-bilibili-notify 3.0.0-alpha.6 → 3.0.0-alpha.8

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/lib/biliAPI.js CHANGED
@@ -1,4 +1,10 @@
1
1
  "use strict";
2
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
3
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
4
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
5
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
6
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
7
+ };
2
8
  var __importDefault = (this && this.__importDefault) || function (mod) {
3
9
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
10
  };
@@ -14,6 +20,7 @@ const tough_cookie_1 = require("tough-cookie");
14
20
  const axios_cookiejar_support_1 = require("axios-cookiejar-support");
15
21
  const jsdom_1 = require("jsdom");
16
22
  const luxon_1 = require("luxon");
23
+ const retry_1 = __importDefault(require("./utils/retry"));
17
24
  const mixinKeyEncTab = [
18
25
  46, 47, 18, 2, 53, 8, 23, 32, 15, 50, 10, 31, 58, 3, 45, 35, 27, 43, 5, 49,
19
26
  33, 9, 42, 19, 29, 28, 14, 39, 12, 38, 41, 13, 37, 48, 7, 16, 24, 55, 40,
@@ -108,183 +115,113 @@ class BiliAPI extends koishi_1.Service {
108
115
  }
109
116
  // BA API
110
117
  async getTheUserWhoIsLiveStreaming() {
111
- try {
112
- // 获取直播间信息流密钥
113
- const { data: { live_users } } = await this.client.get(GET_LATEST_UPDATED_UPS);
114
- // 返回data
115
- return live_users;
116
- }
117
- catch (e) {
118
- throw new Error('网络异常,本次请求失败!');
119
- }
118
+ // 获取直播间信息流密钥
119
+ const { data: { live_users } } = await this.client.get(GET_LATEST_UPDATED_UPS);
120
+ // 返回data
121
+ return live_users;
120
122
  }
121
123
  async getLiveRoomInfoStreamKey(roomId) {
122
- try {
123
- // 获取直播间信息流密钥
124
- const { data } = await this.client.get(`${GET_LIVE_ROOM_INFO_STREAM_KEY}?id=${roomId}`);
125
- // 返回data
126
- return data;
127
- }
128
- catch (e) {
129
- throw new Error('网络异常,本次请求失败!');
130
- }
124
+ // 获取直播间信息流密钥
125
+ const { data } = await this.client.get(`${GET_LIVE_ROOM_INFO_STREAM_KEY}?id=${roomId}`);
126
+ // 返回data
127
+ return data;
131
128
  }
132
129
  async getServerUTCTime() {
133
- try {
134
- const { data } = await this.client.get(GET_SERVER_UTC_TIME);
135
- const regex = /Date\.UTC\((.*?)\)/;
136
- const match = data.match(regex);
137
- if (match) {
138
- const timestamp = new Function(`return Date.UTC(${match[1]})`)();
139
- return timestamp / 1000;
140
- }
141
- else {
142
- throw new Error('解析服务器时间失败!');
143
- }
130
+ const { data } = await this.client.get(GET_SERVER_UTC_TIME);
131
+ const regex = /Date\.UTC\((.*?)\)/;
132
+ const match = data.match(regex);
133
+ if (match) {
134
+ const timestamp = new Function(`return Date.UTC(${match[1]})`)();
135
+ return timestamp / 1000;
144
136
  }
145
- catch (e) {
146
- throw new Error('网络异常,本次请求失败!');
137
+ else {
138
+ throw new Error('解析服务器时间失败!');
147
139
  }
148
140
  }
149
141
  async getTimeNow() {
150
- try {
151
- const { data } = await this.client.get(GET_TIME_NOW);
152
- return data;
153
- }
154
- catch (e) {
155
- throw new Error('网络异常,本次请求失败!');
156
- }
142
+ const { data } = await this.client.get(GET_TIME_NOW);
143
+ return data;
157
144
  }
158
145
  async getAllGroup() {
159
- try {
160
- const { data } = await this.client.get(GET_ALL_GROUP);
161
- return data;
162
- }
163
- catch (e) {
164
- throw new Error('网络异常,本次请求失败!');
165
- }
146
+ const { data } = await this.client.get(GET_ALL_GROUP);
147
+ return data;
166
148
  }
167
149
  async removeUserFromGroup(mid) {
168
150
  // 获取csrf
169
151
  const csrf = this.getCSRF();
170
- try {
171
- // 将用户mid添加到groupId
172
- const { data } = await this.client.post(MODIFY_GROUP_MEMBER, {
173
- fids: mid,
174
- tagids: 0,
175
- csrf
176
- }, {
177
- headers: {
178
- 'Content-Type': 'application/x-www-form-urlencoded',
179
- }
180
- });
181
- return data;
182
- }
183
- catch (e) {
184
- throw new Error('网络异常,本次请求失败!');
185
- }
152
+ // 将用户mid添加到groupId
153
+ const { data } = await this.client.post(MODIFY_GROUP_MEMBER, {
154
+ fids: mid,
155
+ tagids: 0,
156
+ csrf
157
+ }, {
158
+ headers: {
159
+ 'Content-Type': 'application/x-www-form-urlencoded',
160
+ }
161
+ });
162
+ return data;
186
163
  }
187
164
  async copyUserToGroup(mid, groupId) {
188
165
  // 获取csrf
189
166
  const csrf = this.getCSRF();
190
- try {
191
- // 将用户mid添加到groupId
192
- const { data } = await this.client.post(COPY_USER_TO_GROUP, {
193
- fids: mid,
194
- tagids: groupId,
195
- csrf
196
- }, {
197
- headers: {
198
- 'Content-Type': 'application/x-www-form-urlencoded',
199
- }
200
- });
201
- return data;
202
- }
203
- catch (e) {
204
- throw new Error('网络异常,本次请求失败!');
205
- }
167
+ // 将用户mid添加到groupId
168
+ const { data } = await this.client.post(COPY_USER_TO_GROUP, {
169
+ fids: mid,
170
+ tagids: groupId,
171
+ csrf
172
+ }, {
173
+ headers: {
174
+ 'Content-Type': 'application/x-www-form-urlencoded',
175
+ }
176
+ });
177
+ return data;
206
178
  }
207
179
  async getUserSpaceDynamic(mid) {
208
- try {
209
- const { data } = await this.client.get(`${GET_USER_SPACE_DYNAMIC_LIST}?host_mid=${mid}`);
210
- return data;
211
- }
212
- catch (e) {
213
- throw new Error('网络异常,本次请求失败!');
214
- }
180
+ const { data } = await this.client.get(`${GET_USER_SPACE_DYNAMIC_LIST}?host_mid=${mid}`);
181
+ return data;
215
182
  }
216
183
  async createGroup(tag) {
217
- try {
218
- const { data } = await this.client.post(CREATE_GROUP, {
219
- tag,
220
- csrf: this.getCSRF()
221
- }, {
222
- headers: {
223
- 'Content-Type': 'application/x-www-form-urlencoded',
224
- }
225
- });
226
- return data;
227
- }
228
- catch (e) {
229
- throw new Error('网络异常,本次请求失败!');
230
- }
184
+ const { data } = await this.client.post(CREATE_GROUP, {
185
+ tag,
186
+ csrf: this.getCSRF()
187
+ }, {
188
+ headers: {
189
+ 'Content-Type': 'application/x-www-form-urlencoded',
190
+ }
191
+ });
192
+ return data;
231
193
  }
232
194
  async getAllDynamic(updateBaseline) {
233
195
  let url = GET_ALL_DYNAMIC_LIST;
234
196
  updateBaseline && (url += `?update_baseline=${updateBaseline}`);
235
- try {
236
- const { data } = await this.client.get(url);
237
- return data;
238
- }
239
- catch (e) {
240
- throw new Error('网络异常,本次请求失败!');
241
- }
197
+ const { data } = await this.client.get(url);
198
+ return data;
242
199
  }
243
200
  async hasNewDynamic(updateBaseline) {
244
- try {
245
- const { data } = await this.client.get(`${HAS_NEW_DYNAMIC}?update_baseline=${updateBaseline}`);
246
- return data;
247
- }
248
- catch (e) {
249
- throw new Error('网络异常,本次请求失败!');
250
- }
201
+ const { data } = await this.client.get(`${HAS_NEW_DYNAMIC}?update_baseline=${updateBaseline}`);
202
+ return data;
251
203
  }
252
204
  async follow(fid) {
253
- try {
254
- const { data } = await this.client.post(MODIFY_RELATION, {
255
- fid,
256
- act: 1,
257
- re_src: 11,
258
- csrf: this.getCSRF()
259
- }, {
260
- headers: {
261
- 'Content-Type': 'application/x-www-form-urlencoded',
262
- }
263
- });
264
- return data;
265
- }
266
- catch (e) {
267
- throw new Error('网络异常,本次请求失败!');
268
- }
205
+ const { data } = await this.client.post(MODIFY_RELATION, {
206
+ fid,
207
+ act: 1,
208
+ re_src: 11,
209
+ csrf: this.getCSRF()
210
+ }, {
211
+ headers: {
212
+ 'Content-Type': 'application/x-www-form-urlencoded',
213
+ }
214
+ });
215
+ return data;
269
216
  }
270
217
  async getRelationGroupDetail(tagid) {
271
- try {
272
- const { data } = await this.client.get(`${GET_RELATION_GROUP_DETAIL}?tagid=${tagid}`);
273
- return data;
274
- }
275
- catch (e) {
276
- throw new Error('网络异常,本次请求失败!');
277
- }
218
+ const { data } = await this.client.get(`${GET_RELATION_GROUP_DETAIL}?tagid=${tagid}`);
219
+ return data;
278
220
  }
279
221
  // Check if Token need refresh
280
222
  async getCookieInfo(refreshToken) {
281
- try {
282
- const { data } = await this.client.get(`${GET_COOKIES_INFO}?csrf=${refreshToken}`);
283
- return data;
284
- }
285
- catch (e) {
286
- throw new Error('网络异常,本次请求失败!');
287
- }
223
+ const { data } = await this.client.get(`${GET_COOKIES_INFO}?csrf=${refreshToken}`);
224
+ return data;
288
225
  }
289
226
  async getUserInfo(mid) {
290
227
  //如果为番剧出差的UID,则不从远程接口拉取数据,直接传回一段精简过的有效数据
@@ -292,15 +229,9 @@ class BiliAPI extends koishi_1.Service {
292
229
  console.log("检测到番剧出差UID,跳过远程用户接口访问");
293
230
  return bangumiTripData;
294
231
  }
295
- try {
296
- const wbi = await this.getWbi({ mid });
297
- const { data } = await this.client.get(`${GET_USER_INFO}?${wbi}`);
298
- return data;
299
- }
300
- catch (e) {
301
- console.warn(e);
302
- throw new Error('网络异常,本次请求失败!');
303
- }
232
+ const wbi = await this.getWbi({ mid });
233
+ const { data } = await this.client.get(`${GET_USER_INFO}?${wbi}`);
234
+ return data;
304
235
  }
305
236
  // 获取最新的 img_key 和 sub_key
306
237
  async getWbiKeys() {
@@ -312,49 +243,24 @@ class BiliAPI extends koishi_1.Service {
312
243
  };
313
244
  }
314
245
  async getMyselfInfo() {
315
- try {
316
- const { data } = await this.client.get(GET_MYSELF_INFO);
317
- return data;
318
- }
319
- catch (e) {
320
- throw new Error('网络异常,本次请求失败!');
321
- }
246
+ const { data } = await this.client.get(GET_MYSELF_INFO);
247
+ return data;
322
248
  }
323
249
  async getLoginQRCode() {
324
- try {
325
- const { data } = await this.client.get(GET_LOGIN_QRCODE);
326
- return data;
327
- }
328
- catch (e) {
329
- throw new Error('网络异常,本次请求失败!');
330
- }
250
+ const { data } = await this.client.get(GET_LOGIN_QRCODE);
251
+ return data;
331
252
  }
332
253
  async getLoginStatus(qrcodeKey) {
333
- try {
334
- const { data } = await this.client.get(`${GET_LOGIN_STATUS}?qrcode_key=${qrcodeKey}`);
335
- return data;
336
- }
337
- catch (e) {
338
- throw new Error('网络异常,本次请求失败!');
339
- }
254
+ const { data } = await this.client.get(`${GET_LOGIN_STATUS}?qrcode_key=${qrcodeKey}`);
255
+ return data;
340
256
  }
341
257
  async getLiveRoomInfo(roomId) {
342
- try {
343
- const { data } = await this.client.get(`${GET_LIVE_ROOM_INFO}?room_id=${roomId}`);
344
- return data;
345
- }
346
- catch (e) {
347
- throw new Error('网络异常,本次请求失败!');
348
- }
258
+ const { data } = await this.client.get(`${GET_LIVE_ROOM_INFO}?room_id=${roomId}`);
259
+ return data;
349
260
  }
350
261
  async getMasterInfo(mid) {
351
- try {
352
- const { data } = await this.client.get(`${GET_MASTER_INFO}?uid=${mid}`);
353
- return data;
354
- }
355
- catch (e) {
356
- throw new Error('网络异常,本次请求失败!');
357
- }
262
+ const { data } = await this.client.get(`${GET_MASTER_INFO}?uid=${mid}`);
263
+ return data;
358
264
  }
359
265
  disposeNotifier() { if (this.loginNotifier)
360
266
  this.loginNotifier.dispose(); }
@@ -644,6 +550,174 @@ class BiliAPI extends koishi_1.Service {
644
550
  // 没有问题,cookies已更新完成
645
551
  }
646
552
  }
553
+ __decorate([
554
+ (0, retry_1.default)({
555
+ attempts: 3,
556
+ onFailure(error, attempts) {
557
+ this.logger.error(`getTheUserWhoIsLiveStreaming() 第${attempts}次失败: ${error.message}`);
558
+ },
559
+ })
560
+ ], BiliAPI.prototype, "getTheUserWhoIsLiveStreaming", null);
561
+ __decorate([
562
+ (0, retry_1.default)({
563
+ attempts: 3,
564
+ onFailure(error, attempts) {
565
+ this.logger.error(`getLiveRoomInfoStreamKey() 第${attempts}次失败: ${error.message}`);
566
+ },
567
+ })
568
+ ], BiliAPI.prototype, "getLiveRoomInfoStreamKey", null);
569
+ __decorate([
570
+ (0, retry_1.default)({
571
+ attempts: 3,
572
+ onFailure(error, attempts) {
573
+ this.logger.error(`getServerUTCTime() 第${attempts}次失败: ${error.message}`);
574
+ },
575
+ })
576
+ ], BiliAPI.prototype, "getServerUTCTime", null);
577
+ __decorate([
578
+ (0, retry_1.default)({
579
+ attempts: 3,
580
+ onFailure(error, attempts) {
581
+ this.logger.error(`getTimeNow() 第${attempts}次失败: ${error.message}`);
582
+ },
583
+ })
584
+ ], BiliAPI.prototype, "getTimeNow", null);
585
+ __decorate([
586
+ (0, retry_1.default)({
587
+ attempts: 3,
588
+ onFailure(error, attempts) {
589
+ this.logger.error(`getAllGroup() 第${attempts}次失败: ${error.message}`);
590
+ },
591
+ })
592
+ ], BiliAPI.prototype, "getAllGroup", null);
593
+ __decorate([
594
+ (0, retry_1.default)({
595
+ attempts: 3,
596
+ onFailure(error, attempts) {
597
+ this.logger.error(`removeUserFromGroup() 第${attempts}次失败: ${error.message}`);
598
+ },
599
+ })
600
+ ], BiliAPI.prototype, "removeUserFromGroup", null);
601
+ __decorate([
602
+ (0, retry_1.default)({
603
+ attempts: 3,
604
+ onFailure(error, attempts) {
605
+ this.logger.error(`copyUserToGroup() 第${attempts}次失败: ${error.message}`);
606
+ },
607
+ })
608
+ ], BiliAPI.prototype, "copyUserToGroup", null);
609
+ __decorate([
610
+ (0, retry_1.default)({
611
+ attempts: 3,
612
+ onFailure(error, attempts) {
613
+ this.logger.error(`getUserSpaceDynamic() 第${attempts}次失败: ${error.message}`);
614
+ },
615
+ })
616
+ ], BiliAPI.prototype, "getUserSpaceDynamic", null);
617
+ __decorate([
618
+ (0, retry_1.default)({
619
+ attempts: 3,
620
+ onFailure(error, attempts) {
621
+ this.logger.error(`createGroup() 第${attempts}次失败: ${error.message}`);
622
+ },
623
+ })
624
+ ], BiliAPI.prototype, "createGroup", null);
625
+ __decorate([
626
+ (0, retry_1.default)({
627
+ attempts: 3,
628
+ onFailure(error, attempts) {
629
+ this.logger.error(`getAllDynamic() 第${attempts}次失败: ${error.message}`);
630
+ },
631
+ })
632
+ ], BiliAPI.prototype, "getAllDynamic", null);
633
+ __decorate([
634
+ (0, retry_1.default)({
635
+ attempts: 3,
636
+ onFailure(error, attempts) {
637
+ this.logger.error(`hasNewDynamic() 第${attempts}次失败: ${error.message}`);
638
+ },
639
+ })
640
+ ], BiliAPI.prototype, "hasNewDynamic", null);
641
+ __decorate([
642
+ (0, retry_1.default)({
643
+ attempts: 3,
644
+ onFailure(error, attempts) {
645
+ this.logger.error(`follow() 第${attempts}次失败: ${error.message}`);
646
+ },
647
+ })
648
+ ], BiliAPI.prototype, "follow", null);
649
+ __decorate([
650
+ (0, retry_1.default)({
651
+ attempts: 3,
652
+ onFailure(error, attempts) {
653
+ this.logger.error(`getRelationGroupDetail() 第${attempts}次失败: ${error.message}`);
654
+ },
655
+ })
656
+ ], BiliAPI.prototype, "getRelationGroupDetail", null);
657
+ __decorate([
658
+ (0, retry_1.default)({
659
+ attempts: 3,
660
+ onFailure(error, attempts) {
661
+ this.logger.error(`getCookieInfo() 第${attempts}次失败: ${error.message}`);
662
+ },
663
+ })
664
+ ], BiliAPI.prototype, "getCookieInfo", null);
665
+ __decorate([
666
+ (0, retry_1.default)({
667
+ attempts: 3,
668
+ onFailure(error, attempts) {
669
+ this.logger.error(`getUserInfo() 第${attempts}次失败: ${error.message}`);
670
+ },
671
+ })
672
+ ], BiliAPI.prototype, "getUserInfo", null);
673
+ __decorate([
674
+ (0, retry_1.default)({
675
+ attempts: 3,
676
+ onFailure(error, attempts) {
677
+ this.logger.error(`getWbiKeys() 第${attempts}次失败: ${error.message}`);
678
+ },
679
+ })
680
+ ], BiliAPI.prototype, "getWbiKeys", null);
681
+ __decorate([
682
+ (0, retry_1.default)({
683
+ attempts: 3,
684
+ onFailure(error, attempts) {
685
+ this.logger.error(`getMyselfInfo() 第${attempts}次失败: ${error.message}`);
686
+ },
687
+ })
688
+ ], BiliAPI.prototype, "getMyselfInfo", null);
689
+ __decorate([
690
+ (0, retry_1.default)({
691
+ attempts: 3,
692
+ onFailure(error, attempts) {
693
+ this.logger.error(`getLoginQRCode() 第${attempts}次失败: ${error.message}`);
694
+ },
695
+ })
696
+ ], BiliAPI.prototype, "getLoginQRCode", null);
697
+ __decorate([
698
+ (0, retry_1.default)({
699
+ attempts: 3,
700
+ onFailure(error, attempts) {
701
+ this.logger.error(`getLoginStatus() 第${attempts}次失败: ${error.message}`);
702
+ },
703
+ })
704
+ ], BiliAPI.prototype, "getLoginStatus", null);
705
+ __decorate([
706
+ (0, retry_1.default)({
707
+ attempts: 3,
708
+ onFailure(error, attempts) {
709
+ this.logger.error(`getLiveRoomInfo() 第${attempts}次失败: ${error.message}`);
710
+ },
711
+ })
712
+ ], BiliAPI.prototype, "getLiveRoomInfo", null);
713
+ __decorate([
714
+ (0, retry_1.default)({
715
+ attempts: 3,
716
+ onFailure(error, attempts) {
717
+ this.logger.error(`getMasterInfo() 第${attempts}次失败: ${error.message}`);
718
+ },
719
+ })
720
+ ], BiliAPI.prototype, "getMasterInfo", null);
647
721
  (function (BiliAPI) {
648
722
  BiliAPI.Config = koishi_1.Schema.object({
649
723
  userAgent: koishi_1.Schema.string(),
@@ -165,6 +165,8 @@ class ComRegister {
165
165
  }]);
166
166
  // 销毁定时器
167
167
  this.loginTimer();
168
+ // 订阅手动订阅中的订阅
169
+ await this.loadSubFromConfig(config.sub);
168
170
  // 订阅之前的订阅
169
171
  await this.loadSubFromDatabase();
170
172
  // 清除控制台通知
@@ -175,7 +177,6 @@ class ComRegister {
175
177
  await session.execute('bili show');
176
178
  // 开启cookies刷新检测
177
179
  ctx.ba.enableRefreshCookiesDetect();
178
- return;
179
180
  }
180
181
  }
181
182
  finally {
@@ -439,23 +440,23 @@ class ComRegister {
439
440
  this.logger.error('bili sub指令 getMasterInfo() 发生了错误,错误为:' + e.message);
440
441
  return '订阅出错啦,请重试';
441
442
  }
443
+ const liveDetectModeSelector = {
444
+ API: async () => {
445
+ // 判断是否已开启直播检测
446
+ if (!this.liveDispose) { // 未开启直播检测
447
+ // 开启直播检测并保存销毁函数
448
+ this.liveDispose = await this.liveDetectWithAPI();
449
+ }
450
+ },
451
+ WS: async () => {
452
+ // 连接到服务器
453
+ await this.liveDetectWithListener(roomId, target);
454
+ }
455
+ };
442
456
  // 订阅直播
443
457
  if (liveMsg) {
444
458
  // 判断直播订阅方式
445
- switch (this.config.liveDetectMode) {
446
- case "API": {
447
- // 判断是否已开启直播检测
448
- if (!this.liveDispose) { // 未开启直播检测
449
- // 开启直播检测并保存销毁函数
450
- this.liveDispose = await this.liveDetectWithAPI();
451
- }
452
- break;
453
- }
454
- case "WS": {
455
- // 连接到服务器
456
- await this.liveDetectWithListener(roomId, target);
457
- }
458
- }
459
+ await liveDetectModeSelector[this.config.liveDetectMode]();
459
460
  // 发送订阅消息通知
460
461
  await session.send(`订阅${userData.info.uname}直播通知`);
461
462
  }
@@ -463,6 +464,7 @@ class ComRegister {
463
464
  if (dynamicMsg) {
464
465
  // 判断是否开启动态监测
465
466
  if (!this.dynamicDispose) {
467
+ // 开启动态监测
466
468
  this.enableDynamicDetect();
467
469
  }
468
470
  // 发送订阅消息通知
@@ -1391,10 +1393,18 @@ class ComRegister {
1391
1393
  // 定义弹幕存放数组
1392
1394
  const currentLiveDanmakuArr = [];
1393
1395
  const temporaryLiveDanmakuArr = [];
1396
+ // 定义开播状态
1397
+ let liveStatus = false;
1394
1398
  // 处理target
1399
+ // 定义channelIdArr总长度
1400
+ let channelIdArrLen = 0;
1395
1401
  // 找到频道/群组对应的
1396
1402
  const danmakuPushTargetArr = target.map(channel => {
1403
+ // 获取符合条件的target
1397
1404
  const liveDanmakuArr = channel.channelIdArr.filter(channelId => channelId.liveDanmaku);
1405
+ // 将当前liveDanmakuArr的长度+到channelIdArrLen中
1406
+ channelIdArrLen += liveDanmakuArr.length;
1407
+ // 返回符合的target
1398
1408
  return {
1399
1409
  channelIdArr: liveDanmakuArr,
1400
1410
  platform: channel.platform
@@ -1422,7 +1432,7 @@ class ComRegister {
1422
1432
  // 定义弹幕推送函数
1423
1433
  const danmakuPushFunc = () => {
1424
1434
  // 判断数组是否有内容
1425
- if (danmakuPushTargetArr.length > 0 && temporaryLiveDanmakuArr.length > 0) {
1435
+ if (channelIdArrLen > 0 && temporaryLiveDanmakuArr.length > 0) {
1426
1436
  // 发送消息
1427
1437
  this.sendMsg(danmakuPushTargetArr, temporaryLiveDanmakuArr.join('\n'));
1428
1438
  // 将临时消息数组清空
@@ -1462,6 +1472,9 @@ class ComRegister {
1462
1472
  temporaryLiveDanmakuArr.push(content);
1463
1473
  },
1464
1474
  onLiveStart: async () => {
1475
+ // 判断是否已经开播
1476
+ if (liveStatus)
1477
+ return;
1465
1478
  // 获取直播间信息
1466
1479
  const liveRoomInfo = await this.useLiveRoomInfo(roomId);
1467
1480
  // 获取主播信息
@@ -1473,7 +1486,7 @@ class ComRegister {
1473
1486
  .replace('-name', masterInfo.username)
1474
1487
  .replace('-time', await this.ctx.gi.getTimeDifference(liveTime))
1475
1488
  .replace('-link', `https://live.bilibili.com/${liveRoomInfo.short_id === 0 ? liveRoomInfo.room_id : liveRoomInfo.short_id}`) : null;
1476
- // 推送下播通知
1489
+ // 推送开播通知
1477
1490
  await this.sendLiveNotifyCard({
1478
1491
  username: masterInfo.username,
1479
1492
  userface: masterInfo.userface,
@@ -1485,6 +1498,8 @@ class ComRegister {
1485
1498
  // 开始直播,开启定时器
1486
1499
  pushAtTimeTimer = this.ctx.setInterval(pushAtTimeFunc, this.config.pushTime * 1000 * 60 * 60);
1487
1500
  }
1501
+ // 设置开播状态为true
1502
+ liveStatus = true;
1488
1503
  },
1489
1504
  onLiveEnd: async () => {
1490
1505
  // 获取直播间消息
@@ -1508,6 +1523,8 @@ class ComRegister {
1508
1523
  pushAtTimeTimer();
1509
1524
  // 将推送定时器变量置空
1510
1525
  pushAtTimeTimer = null;
1526
+ // 将直播状态设置为false
1527
+ liveStatus = false;
1511
1528
  }
1512
1529
  };
1513
1530
  // 启动直播间弹幕监测
@@ -1536,6 +1553,8 @@ class ComRegister {
1536
1553
  // 开始直播,开启定时器
1537
1554
  pushAtTimeTimer = this.ctx.setInterval(pushAtTimeFunc, this.config.pushTime * 1000 * 60 * 60);
1538
1555
  }
1556
+ // 设置直播状态为true
1557
+ liveStatus = true;
1539
1558
  }
1540
1559
  }
1541
1560
  subShow() {
@@ -1735,23 +1754,24 @@ class ComRegister {
1735
1754
  // 发送提示
1736
1755
  this.logger.warn(`UID:${sub.uid} 用户没有开通直播间,无法订阅直播!`);
1737
1756
  }
1738
- // 判断是否订阅直播
1739
- if (sub.live) {
1740
- // 判断直播订阅方式
1741
- switch (this.config.liveDetectMode) {
1742
- case "API": {
1743
- // 判断是否已开启直播检测
1744
- if (!this.liveDispose) { // 未开启直播检测
1745
- // 开启直播检测并保存销毁函数
1746
- this.liveDispose = await this.liveDetectWithAPI();
1747
- }
1748
- break;
1749
- }
1750
- case "WS": {
1751
- // 连接到服务器
1752
- await this.liveDetectWithListener(data.live_room.roomid, sub.target);
1757
+ //
1758
+ const liveDetectModeSelector = {
1759
+ API: async () => {
1760
+ // 判断是否已开启直播检测
1761
+ if (!this.liveDispose) { // 未开启直播检测
1762
+ // 开启直播检测并保存销毁函数
1763
+ this.liveDispose = await this.liveDetectWithAPI();
1753
1764
  }
1765
+ },
1766
+ WS: async () => {
1767
+ // 连接到服务器
1768
+ await this.liveDetectWithListener(data.live_room.roomid, sub.target);
1754
1769
  }
1770
+ };
1771
+ // 判断是否订阅直播
1772
+ if (sub.live) {
1773
+ // 启动直播监测
1774
+ await liveDetectModeSelector[this.config.liveDetectMode]();
1755
1775
  }
1756
1776
  }
1757
1777
  // 在B站中订阅该对象
@@ -1872,36 +1892,37 @@ class ComRegister {
1872
1892
  dynamic: sub.dynamic === 1 ? true : false,
1873
1893
  liveDispose: null
1874
1894
  };
1875
- // 判断是否订阅直播
1876
- if (sub.live) {
1877
- // 判断直播检测方式
1878
- switch (this.config.liveDetectMode) {
1879
- case "API": {
1880
- // 判断是否已开启直播检测
1881
- if (!this.liveDispose) { // 未开启直播检测
1882
- // 开启直播检测并保存销毁函数
1883
- this.liveDispose = await this.liveDetectWithAPI();
1884
- }
1885
- break;
1895
+ // 定义直播模式监测器
1896
+ const liveDetectModeSelector = {
1897
+ API: async () => {
1898
+ // 判断是否已开启直播检测
1899
+ if (!this.liveDispose) { // 未开启直播检测
1900
+ // 开启直播检测并保存销毁函数
1901
+ this.liveDispose = await this.liveDetectWithAPI();
1886
1902
  }
1887
- case "WS": {
1888
- // 判断订阅直播数是否超过限制
1889
- if (!this.config.unlockSubLimits && liveSubNum >= 3) {
1890
- // 将live改为false
1891
- subManagerItem.live = false;
1892
- // log
1893
- this.logger.warn(`UID:${sub.uid} 订阅直播数超过限制,自动取消订阅`);
1894
- // 发送错误消息
1895
- await this.sendPrivateMsg(`UID:${sub.uid} 订阅直播数超过限制,自动取消订阅`);
1896
- }
1897
- else {
1898
- // 直播订阅数+1
1899
- liveSubNum++;
1900
- // 订阅直播,开始循环检测
1901
- await this.liveDetectWithListener(sub.room_id, target);
1902
- }
1903
+ },
1904
+ WS: async () => {
1905
+ // 判断订阅直播数是否超过限制
1906
+ if (!this.config.unlockSubLimits && liveSubNum >= 3) {
1907
+ // 将live改为false
1908
+ subManagerItem.live = false;
1909
+ // log
1910
+ this.logger.warn(`UID:${sub.uid} 订阅直播数超过限制,自动取消订阅`);
1911
+ // 发送错误消息
1912
+ await this.sendPrivateMsg(`UID:${sub.uid} 订阅直播数超过限制,自动取消订阅`);
1913
+ }
1914
+ else {
1915
+ // 直播订阅数+1
1916
+ liveSubNum++;
1917
+ // 订阅直播,开始循环检测
1918
+ await this.liveDetectWithListener(sub.room_id, target);
1903
1919
  }
1904
1920
  }
1921
+ };
1922
+ // 判断是否订阅直播
1923
+ if (sub.live) {
1924
+ // 启动直播监测
1925
+ await liveDetectModeSelector[this.config.liveDetectMode]();
1905
1926
  }
1906
1927
  // 保存新订阅对象
1907
1928
  this.subManager.push(subManagerItem);
@@ -0,0 +1,6 @@
1
+ interface RetryOptions {
2
+ attempts: number;
3
+ onFailure?: (error: Error, attempts: number) => Promise<void> | void;
4
+ }
5
+ declare function Retry(options?: RetryOptions): MethodDecorator;
6
+ export default Retry;
@@ -0,0 +1,24 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ function Retry(options = { attempts: 3 }) {
4
+ return function (target, propertyKey, descriptor) {
5
+ const originalMethod = descriptor.value;
6
+ descriptor.value = async function (...args) {
7
+ let lastError;
8
+ for (let i = 0; i < options.attempts; i++) {
9
+ try {
10
+ return await originalMethod.apply(this, args);
11
+ }
12
+ catch (error) {
13
+ lastError = error;
14
+ if (options.onFailure) {
15
+ await options.onFailure.call(this, lastError, i + 1);
16
+ }
17
+ }
18
+ }
19
+ throw lastError;
20
+ };
21
+ return descriptor;
22
+ };
23
+ }
24
+ exports.default = Retry;
@@ -0,0 +1,7 @@
1
+ /**
2
+ * 高阶函数:为函数添加锁机制
3
+ * @param {Function} fn - 需要包装的原始函数
4
+ * @returns {Function} 带锁功能的函数
5
+ */
6
+ declare function withLock(fn: any): (...args: any[]) => void;
7
+ export default withLock;
@@ -0,0 +1,59 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ /**
4
+ * 高阶函数:为函数添加锁机制
5
+ * @param {Function} fn - 需要包装的原始函数
6
+ * @returns {Function} 带锁功能的函数
7
+ */
8
+ function withLock(fn) {
9
+ // 判断是否是异步函数
10
+ const isAsync = fn.constructor.name === 'AsyncFunction';
11
+ // 定义锁标志
12
+ let locked = false;
13
+ // 判断是否为异步函数
14
+ if (isAsync) {
15
+ // 变为Promise
16
+ return function (...args) {
17
+ // 已加锁则跳过执行
18
+ if (locked)
19
+ return;
20
+ // 获取锁
21
+ locked = true;
22
+ // 将异步函数转为Promise链
23
+ Promise.resolve(fn(...args))
24
+ .catch(err => {
25
+ // 打印错误
26
+ console.error("Execution error:", err);
27
+ // 重新抛出错误
28
+ throw err;
29
+ })
30
+ .finally(() => {
31
+ // 确保释放锁
32
+ locked = false;
33
+ });
34
+ };
35
+ }
36
+ // 不是异步函数
37
+ return function (...args) {
38
+ // 已加锁则跳过执行
39
+ if (locked)
40
+ return;
41
+ // 获取锁
42
+ locked = true;
43
+ try {
44
+ // 执行函数
45
+ fn(...args);
46
+ }
47
+ catch (err) {
48
+ // 打印错误
49
+ console.error("Execution error:", err);
50
+ // 重新抛出错误
51
+ throw err;
52
+ }
53
+ finally {
54
+ // 无论成功失败都释放锁
55
+ locked = false;
56
+ }
57
+ };
58
+ }
59
+ exports.default = withLock;
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "koishi-plugin-bilibili-notify",
3
3
  "description": "Koishi bilibili notify plugin",
4
- "version": "3.0.0-alpha.6",
4
+ "version": "3.0.0-alpha.8",
5
5
  "contributors": [
6
6
  "Akokko <admin@akokko.com>"
7
7
  ],
package/readme.md CHANGED
@@ -218,6 +218,8 @@
218
218
  - ver 3.0.0-alpha.4 修复:使用了手动订阅,数据库中的订阅不会加载
219
219
  - ver 3.0.0-alpha.5 修复:订阅的直播开播后,未开启弹幕推送会一直报错、主播开播推送下播卡片,直播时长显示NaN; 新增:直播检测模式选项; 优化:下播卡片内容
220
220
  - ver 3.0.0-alpha.6 修复:连续发送两次直播中通知卡片; 优化:下播通知卡片
221
+ - ver 3.0.0-alpha.7 修复:`ver 3.0.0-alpha.5` 未能解决的bug; 优化:ba代码结构
222
+ - ver 3.0.0-alpha.8 修复:开播通知连续发送两次,登录后不会加载手动订阅中的订阅; 优化:网络请求报错
221
223
 
222
224
  ## 交流群
223
225