koishi-plugin-bilibili-notify 0.1.0 → 0.1.2

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.
@@ -1,30 +1,26 @@
1
- import { Context, Logger, Schema, Session } from "koishi";
1
+ import { Bot, Context, Logger, Schema, Session } from "koishi";
2
2
  declare class ComRegister {
3
3
  static inject: string[];
4
4
  logger: Logger;
5
5
  config: ComRegister.Config;
6
- id: number;
7
- sub: {
8
- id: number;
9
- uid: string;
10
- room_id: string;
11
- dynamic: number;
12
- video: 1;
13
- live: number;
14
- time: Date;
15
- };
6
+ num: number;
16
7
  subManager: {
8
+ id: number;
17
9
  uid: string;
18
10
  roomId: string;
11
+ targetId: string;
19
12
  live: boolean;
20
13
  dynamic: boolean;
21
14
  liveDispose: Function;
22
15
  dynamicDispose: Function;
23
16
  }[];
17
+ qqBot: Bot<Context>;
18
+ qqguildBot: Bot<Context>;
24
19
  constructor(ctx: Context, config: ComRegister.Config);
25
- dynamicDetect(ctx: Context, session: Session, uid: string): () => Promise<"账号未登录" | "未知错误">;
26
- liveDetect(ctx: Context, session: Session, roomId: string): () => Promise<void>;
20
+ dynamicDetect(ctx: Context, bot: Bot<Context>, groupId: string, uid: string): () => Promise<"账号未登录" | "未知错误">;
21
+ liveDetect(ctx: Context, bot: Bot<Context>, groupId: string, roomId: string): () => Promise<void>;
27
22
  checkIfNeedSub(comNeed: boolean, subType: string, session: Session, data?: any): Promise<boolean>;
23
+ getSubFromDatabase(ctx: Context): Promise<void>;
28
24
  }
29
25
  declare namespace ComRegister {
30
26
  interface Config {
@@ -16,12 +16,20 @@ class ComRegister {
16
16
  static inject = ['biliAPI', 'gimg', 'wbi', 'database'];
17
17
  logger;
18
18
  config;
19
- id = 1;
20
- sub;
19
+ num = 0;
21
20
  subManager = [];
21
+ // QQ群机器人
22
+ qqBot;
23
+ // QQ频道机器人
24
+ qqguildBot;
22
25
  constructor(ctx, config) {
23
26
  this.logger = ctx.logger('commandRegister');
24
27
  this.config = config;
28
+ // 拿到QQ群机器人
29
+ this.qqBot = ctx.bots[ctx.bots.findIndex(bot => bot.platform === 'qq')];
30
+ // 拿到QQ频道机器人
31
+ this.qqguildBot = ctx.bots[ctx.bots.findIndex(bot => bot.platform === 'qqguild')];
32
+ this.getSubFromDatabase(ctx);
25
33
  ctx.command('test')
26
34
  .subcommand('.cookies')
27
35
  .usage('测试指令,用于测试从数据库读取cookies')
@@ -77,6 +85,20 @@ class ComRegister {
77
85
  .action(() => {
78
86
  console.log(this.subManager);
79
87
  });
88
+ ctx.command('test')
89
+ .subcommand('.group')
90
+ .usage('查看session groupId')
91
+ .example('test group')
92
+ .action(({ session }) => {
93
+ console.log(session.event.channel);
94
+ });
95
+ ctx.command('test')
96
+ .subcommand('.session')
97
+ .usage('查看seesion')
98
+ .example('test session')
99
+ .action(({ session }) => {
100
+ console.log(session);
101
+ });
80
102
  ctx.command('bili', 'bili-notify插件相关指令')
81
103
  .subcommand('.login', '登录B站之后才可以进行之后的操作')
82
104
  .usage('使用二维码登录,登录B站之后才可以进行之后的操作')
@@ -132,23 +154,66 @@ class ComRegister {
132
154
  }, 1000);
133
155
  });
134
156
  ctx.command('bili')
135
- .subcommand('.sub <mid:string> [groupid:string]')
157
+ .subcommand('.unsub <uid:string>')
158
+ .usage('取消订阅')
159
+ .example('bili unsub 用户UID')
160
+ .action(async ({ session }, uid) => {
161
+ this.logger.info('调用bili.unsub指令');
162
+ // 若用户UID为空则直接返回
163
+ if (!uid)
164
+ return '用户UID不能为空';
165
+ // 定义是否存在
166
+ let exist;
167
+ await Promise.all(this.subManager.map(async (sub, i) => {
168
+ if (sub.uid === uid) {
169
+ // 执行dispose方法,销毁定时器
170
+ this.subManager[i].dynamicDispose();
171
+ this.subManager[i].liveDispose();
172
+ // 从数据库中删除订阅
173
+ await ctx.database.remove('bilibili', { uid: this.subManager[i].uid });
174
+ // 将该订阅对象从订阅管理对象中移除
175
+ this.subManager = this.subManager.splice(i, i);
176
+ // id--
177
+ this.num--;
178
+ // 发送成功通知
179
+ session.send('已取消订阅该用户');
180
+ // 将存在flag设置为true
181
+ exist = true;
182
+ }
183
+ }));
184
+ // 未订阅该用户,无需取消订阅
185
+ !exist && session.send('未订阅该用户,无需取消订阅');
186
+ });
187
+ ctx.command('bili')
188
+ .subcommand('.show')
189
+ .usage('展示订阅对象')
190
+ .example('bili show')
191
+ .action(async ({ session }) => {
192
+ let table = ``;
193
+ this.subManager.forEach(sub => {
194
+ table += 'UID:' + sub.uid + ' RoomID:' + sub.roomId + '\n';
195
+ });
196
+ !table && session.send('没有订阅任何UP');
197
+ table && session.send(table);
198
+ });
199
+ ctx.command('bili')
200
+ .subcommand('.sub <mid:string> [guildId:string]')
136
201
  .option('live', '-l')
137
202
  .option('dynamic', '-d')
138
203
  .usage('订阅用户动态和直播通知,若需要订阅直播请加上-l,需要订阅动态则加上-d。若没有加任何参数,之后会向你单独询问,<>中为必选参数,[]中为可选参数,目标群号若不填,则默认为当前群聊')
139
204
  .example('bili sub 用户uid 目标QQ群号(暂不支持) -l -d')
140
- .action(async ({ session, options }, mid, groupid) => {
205
+ .action(async ({ session, options }, mid, guildId) => {
141
206
  this.logger.info('调用bili.sub指令');
207
+ // 如果订阅人数超过三个则直接返回
208
+ if (this.num >= 3)
209
+ return '目前最多只能订阅三个人';
142
210
  // 检查必选参数是否有值
143
- if (mid === undefined) {
211
+ if (!mid)
144
212
  return '请输入用户uid';
145
- }
146
213
  // 判断要订阅的用户是否已经存在于订阅管理对象中
147
- this.subManager && this.subManager.forEach((sub) => {
148
- // 已订阅该用户
149
- if (sub.uid === mid)
150
- return session.send('已订阅该用户,请勿重复订阅');
151
- });
214
+ if (this.subManager && this.subManager.some(sub => sub.uid === mid)) {
215
+ return '已订阅该用户,请勿重复订阅';
216
+ }
152
217
  // 定义是否需要直播通知,动态订阅,视频推送
153
218
  let liveMsg, dynamicMsg;
154
219
  // 获取用户信息
@@ -179,99 +244,142 @@ class ComRegister {
179
244
  liveMsg = await this.checkIfNeedSub(options.live, '直播', session, data);
180
245
  // 判断是否需要订阅动态
181
246
  dynamicMsg = await this.checkIfNeedSub(options.dynamic, '动态', session);
182
- // 构造订阅对象
183
- this.sub = {
184
- id: this.id,
247
+ // 判断是哪个平台
248
+ let platform;
249
+ if (!guildId) { // 没有输入群号,默认当前聊天环境
250
+ switch (session.event.platform) {
251
+ case 'qqguild':
252
+ guildId = session.event.channel.id;
253
+ break;
254
+ case 'qq':
255
+ guildId = session.event.guild.id;
256
+ break;
257
+ default: return '暂不支持该平台';
258
+ }
259
+ }
260
+ // 定义Bot
261
+ let bot;
262
+ // 判断是哪个聊天平台
263
+ switch (session.event.platform) {
264
+ case 'qqguild': {
265
+ bot = this.qqguildBot;
266
+ platform = 'qqguild';
267
+ break;
268
+ }
269
+ case 'qq': {
270
+ bot = this.qqBot;
271
+ platform = 'qq';
272
+ break;
273
+ }
274
+ default: return '暂不支持该平台';
275
+ }
276
+ // 保存到数据库中
277
+ const sub = await ctx.database.create('bilibili', {
185
278
  uid: mid,
186
279
  room_id: data.live_room.roomid.toString(),
187
280
  dynamic: dynamicMsg ? 1 : 0,
188
281
  video: 1,
189
282
  live: liveMsg ? 1 : 0,
283
+ targetId: guildId,
284
+ platform,
190
285
  time: new Date()
191
- };
192
- // 保存到数据库中
193
- await ctx.database.upsert('bilibili', [this.sub]);
194
- // 让id自增
195
- this.id++;
286
+ });
287
+ // 订阅数+1
288
+ this.num++;
196
289
  // 开始订阅
197
290
  // 保存新订阅对象
198
291
  this.subManager.push({
292
+ id: sub.id,
199
293
  uid: mid,
294
+ targetId: guildId,
200
295
  roomId: data.live_room.roomid.toString(),
201
296
  live: liveMsg,
202
297
  dynamic: dynamicMsg,
203
298
  liveDispose: null,
204
299
  dynamicDispose: null
205
300
  });
301
+ // 获取用户信息
302
+ const { data: userData } = await ctx.biliAPI.getMasterInfo(sub.uid);
206
303
  // 需要订阅直播
207
- if (liveMsg)
208
- await session.execute(`bili live ${data.live_room.roomid}`);
304
+ if (liveMsg) {
305
+ await session.execute(`bili live ${data.live_room.roomid} ${guildId} -b ${platform}`);
306
+ // 发送订阅消息通知
307
+ await bot.sendMessage(sub.targetId, `订阅${userData.info.uname}直播通知`);
308
+ }
209
309
  // 需要订阅动态
210
- if (dynamicMsg)
211
- await session.execute(`bili dynamic ${mid}`);
212
- // 发送订阅成功通知
310
+ if (dynamicMsg) {
311
+ await session.execute(`bili dynamic ${mid} ${guildId} -b ${platform}`);
312
+ // 发送订阅消息通知
313
+ await bot.sendMessage(sub.targetId, `订阅${userData.info.uname}动态通知`);
314
+ }
213
315
  });
214
316
  ctx.command('bili')
215
317
  .subcommand('.dynamic <uid:string>')
318
+ .option('bot', '-b <type:string>')
216
319
  .usage('订阅用户动态推送')
217
320
  .example('bili dynamic 1')
218
- .action(async ({ session }, uid) => {
321
+ .action(async ({ session, options }, uid, guildId) => {
219
322
  this.logger.info('调用bili.dynamic指令');
220
323
  // 如果uid为空则返回
221
- if (!uid) {
222
- await session.send('用户uid不能为空');
223
- return;
224
- }
225
- // 定义订阅对象索引
226
- let index;
227
- // 定义要订阅的对象是否存在于订阅管理对象中
228
- let exist;
324
+ if (!uid)
325
+ return '用户uid不能为空';
326
+ if (!options.bot)
327
+ return '非法调用';
229
328
  // 保存到订阅管理对象
230
- this.subManager.forEach((sub, i) => {
231
- if (sub.uid === uid) {
232
- exist = true;
233
- index = i;
234
- }
235
- });
329
+ const index = this.subManager.findIndex(sub => sub.uid === uid);
236
330
  // 不存在则直接返回
237
- if (!exist) {
331
+ if (index === -1) {
238
332
  session.send('请勿直接调用该指令');
239
333
  return;
240
334
  }
335
+ // 获取对应Bot
336
+ let bot;
337
+ switch (options.bot) {
338
+ case 'qq':
339
+ bot = this.qqBot;
340
+ break;
341
+ case 'qqguild':
342
+ bot = this.qqguildBot;
343
+ break;
344
+ default: return '非法调用';
345
+ }
241
346
  // 开始循环检测
242
- const dispose = ctx.setInterval(this.dynamicDetect(ctx, session, uid), 60000);
347
+ const dispose = ctx.setInterval(this.dynamicDetect(ctx, bot, guildId, uid), 60000);
243
348
  // 将销毁函数保存到订阅管理对象
244
349
  this.subManager[index].dynamicDispose = dispose;
245
350
  });
246
351
  ctx.command('bili')
247
- .subcommand('.live <roomId:string>')
352
+ .subcommand('.live <roomId:string> <guildId:string>')
353
+ .option('bot', '-b <type:string>')
248
354
  .usage('订阅主播开播通知')
249
355
  .example('bili live 732')
250
- .action(async ({ session }, roomId) => {
356
+ .action(async ({ session, options }, roomId, guildId) => {
251
357
  this.logger.info('调用bili.live指令');
252
358
  // 如果room_id为空则返回
253
- if (!roomId) {
254
- await session.send('订阅主播房间号不能为空');
255
- return;
256
- }
257
- // 定义订阅对象索引
258
- let index;
259
- // 定义要订阅的对象是否存在于订阅管理对象中
260
- let exist;
359
+ if (!roomId)
360
+ return '订阅主播房间号不能为空';
361
+ if (!guildId)
362
+ return '目标群组或频道不能为空';
363
+ if (!options.bot)
364
+ return '非法调用';
261
365
  // 保存到订阅管理对象
262
- this.subManager.forEach((sub, i) => {
263
- if (sub.roomId === roomId) {
264
- exist = true;
265
- index = i;
266
- }
267
- });
366
+ const index = this.subManager.findIndex(sub => sub.roomId === roomId);
268
367
  // 要订阅的对象不在订阅管理对象中,直接返回
269
- if (!exist) {
270
- await session.send('请勿直接调用该指令');
271
- return;
368
+ if (index === -1)
369
+ return '请勿直接调用该指令';
370
+ // 获取对应Bot
371
+ let bot;
372
+ switch (options.bot) {
373
+ case 'qq':
374
+ bot = this.qqBot;
375
+ break;
376
+ case 'qqguild':
377
+ bot = this.qqguildBot;
378
+ break;
379
+ default: return '非法调用';
272
380
  }
273
381
  // 开始循环检测
274
- const dispose = ctx.setInterval(this.liveDetect(ctx, session, roomId), 5000);
382
+ const dispose = ctx.setInterval(this.liveDetect(ctx, bot, guildId, roomId), 5000);
275
383
  // 保存销毁函数
276
384
  this.subManager[index].liveDispose = dispose;
277
385
  });
@@ -303,16 +411,12 @@ class ComRegister {
303
411
  session.send(string);
304
412
  });
305
413
  }
306
- dynamicDetect(ctx, session, uid) {
414
+ dynamicDetect(ctx, bot, groupId, uid) {
307
415
  let firstSubscription = true;
308
416
  let timePoint;
309
417
  return async () => {
310
- // 第一次的判断
418
+ // 第一次订阅判断
311
419
  if (firstSubscription) {
312
- // 获取用户信息
313
- const { data: userData } = await ctx.biliAPI.getMasterInfo(uid);
314
- // 发送订阅消息通知
315
- session.send(`订阅${userData.info.uname}动态通知!`);
316
420
  // 设置第一次的时间点
317
421
  timePoint = Date.now();
318
422
  // 设置第一次为false
@@ -354,33 +458,28 @@ class ComRegister {
354
458
  }
355
459
  // 推送该条动态
356
460
  const [pic] = await ctx.gimg.generateDynamicImg(items[num]);
357
- session.send(pic);
461
+ await bot.sendMessage(groupId, pic);
358
462
  }
359
463
  }
360
464
  };
361
465
  }
362
- liveDetect(ctx, session, roomId) {
466
+ liveDetect(ctx, bot, groupId, roomId) {
363
467
  let firstSubscription = true;
364
468
  let timer = 0;
365
469
  let open = false;
366
470
  let liveTime;
367
471
  let uData;
368
472
  return async () => {
369
- // Test code
370
- /* console.log('===========================>');
371
- console.log(timer);
372
- console.log(open);
373
- console.log('===========================>'); */
374
473
  // 发送请求检测直播状态
375
474
  const content = await ctx.biliAPI.getLiveRoomInfo(roomId);
376
475
  const { data } = content;
377
476
  // B站出问题了
378
477
  if (content.code !== 0) {
379
478
  if (content.msg === '未找到该房间') {
380
- session.send('未找到该房间!');
479
+ await bot.sendMessage(groupId, '未找到该房间!');
381
480
  }
382
481
  else {
383
- session.send('未知错误,请呼叫管理员检查问题!');
482
+ await bot.sendMessage(groupId, '未知错误,请呼叫管理员检查问题!');
384
483
  }
385
484
  // dispose
386
485
  return;
@@ -391,15 +490,14 @@ class ComRegister {
391
490
  const { data: userData } = await ctx.biliAPI.getMasterInfo(data.uid);
392
491
  // 主播信息不会变,请求一次即可
393
492
  uData = userData;
394
- // 发送订阅消息通知
395
- session.send(`订阅${userData.info.uname}直播通知`);
493
+ // 判断直播状态
396
494
  if (data.live_status === 1) { // 当前正在直播
397
- // 改变开播状态
398
- open = true;
399
495
  // 推送直播信息
400
- await session.send(await ctx
496
+ await bot.sendMessage(groupId, await ctx
401
497
  .gimg
402
498
  .generateLiveImg(data, uData, LiveType.LiveBroadcast));
499
+ // 改变开播状态
500
+ open = true;
403
501
  } // 未开播,直接返回
404
502
  return;
405
503
  }
@@ -413,7 +511,7 @@ class ComRegister {
413
511
  // 下播了将定时器清零
414
512
  timer = 0;
415
513
  // 发送下播通知
416
- session.send(`${uData.info.uname}下播啦,本次直播了${ctx.gimg.getTimeDifference(liveTime)}`);
514
+ bot.sendMessage(groupId, `${uData.info.uname}下播啦,本次直播了${ctx.gimg.getTimeDifference(liveTime)}`);
417
515
  }
418
516
  // 未进循环,还未开播,继续循环
419
517
  break;
@@ -429,7 +527,7 @@ class ComRegister {
429
527
  // 主播信息不会变,开播时刷新一次即可
430
528
  uData = userData;
431
529
  // 发送直播通知
432
- await session.send(await ctx.gimg.generateLiveImg(data, uData, LiveType.StartBroadcasting));
530
+ await bot.sendMessage(groupId, await ctx.gimg.generateLiveImg(data, uData, LiveType.StartBroadcasting));
433
531
  }
434
532
  else { // 还在直播
435
533
  if (this.config.pushTime > 0) {
@@ -439,7 +537,7 @@ class ComRegister {
439
537
  // 到时间重新计时
440
538
  timer = 0;
441
539
  // 发送状态信息
442
- session.send(await ctx
540
+ bot.sendMessage(groupId, await ctx
443
541
  .gimg
444
542
  .generateLiveImg(data, uData, LiveType.LiveBroadcast));
445
543
  }
@@ -484,6 +582,54 @@ class ComRegister {
484
582
  }
485
583
  }
486
584
  }
585
+ async getSubFromDatabase(ctx) {
586
+ // 从数据库中获取数据
587
+ const subData = await ctx.database.get('bilibili', { id: { $gt: 0 } });
588
+ // 设定订阅数量
589
+ this.num = subData.length;
590
+ // 如果订阅数量超过三个则被非法修改数据库
591
+ // 向管理员发送重新订阅通知
592
+ if (this.num > 3)
593
+ return;
594
+ // 定义Bot
595
+ let bot;
596
+ // 循环遍历
597
+ subData.forEach(sub => {
598
+ // 拿到对应bot
599
+ switch (sub.platform) {
600
+ case 'qq': bot = this.qqBot;
601
+ case 'qqguild': bot = this.qqguildBot;
602
+ }
603
+ // 构建订阅对象
604
+ let subManagerItem = {
605
+ id: sub.id,
606
+ uid: sub.uid,
607
+ roomId: sub.room_id,
608
+ targetId: sub.targetId,
609
+ live: +sub.live === 1 ? true : false,
610
+ dynamic: +sub.dynamic === 1 ? true : false,
611
+ liveDispose: null,
612
+ dynamicDispose: null
613
+ };
614
+ // 判断需要订阅的服务
615
+ if (sub.dynamic) { // 需要订阅动态
616
+ // 开始循环检测
617
+ const dispose = ctx.setInterval(this.dynamicDetect(ctx, bot, sub.targetId, sub.uid), 60000);
618
+ // 保存销毁函数
619
+ subManagerItem.dynamicDispose = dispose;
620
+ }
621
+ if (sub.live) { // 需要订阅动态
622
+ // 开始循环检测
623
+ const dispose = ctx.setInterval(this.liveDetect(ctx, bot, sub.targetId, sub.room_id), 5000);
624
+ // 保存销毁函数
625
+ subManagerItem.liveDispose = dispose;
626
+ }
627
+ // 保存新订阅对象
628
+ this.subManager.push(subManagerItem);
629
+ // 发送订阅成功通知
630
+ bot.sendMessage(sub.targetId, '重新加载测试发送');
631
+ });
632
+ }
487
633
  }
488
634
  (function (ComRegister) {
489
635
  ComRegister.Config = koishi_1.Schema.object({
package/lib/database.d.ts CHANGED
@@ -12,6 +12,8 @@ export interface Bilibili {
12
12
  dynamic: number;
13
13
  video: number;
14
14
  live: number;
15
+ targetId: string;
16
+ platform: string;
15
17
  time: Date;
16
18
  }
17
19
  export interface LoginBili {
package/lib/database.js CHANGED
@@ -17,7 +17,9 @@ function apply(ctx) {
17
17
  dynamic: 'unsigned',
18
18
  video: 'unsigned',
19
19
  live: 'unsigned',
20
+ targetId: 'string',
21
+ platform: 'string',
20
22
  time: 'timestamp'
21
- });
23
+ }, { autoInc: true });
22
24
  }
23
25
  exports.apply = apply;
@@ -206,22 +206,26 @@ class GenerateImg extends koishi_1.Service {
206
206
  // 最基本的图文处理
207
207
  function basicDynamic() {
208
208
  const module_dynamic = dynamicMajorData.modules.module_dynamic;
209
- const richText = module_dynamic.desc.rich_text_nodes.reduce((accumulator, currentValue) => {
210
- if (currentValue.emoji) {
211
- return accumulator + `<img style="width:22px; height:22px;" src="${currentValue.emoji.icon_url}"/>`;
212
- }
213
- else {
214
- return accumulator + currentValue.text;
209
+ if (module_dynamic.desc) {
210
+ const richText = module_dynamic.desc.rich_text_nodes.reduce((accumulator, currentValue) => {
211
+ if (currentValue.emoji) {
212
+ return accumulator + `<img style="width:22px; height:22px;" src="${currentValue.emoji.icon_url}"/>`;
213
+ }
214
+ else {
215
+ return accumulator + currentValue.text;
216
+ }
217
+ }, '');
218
+ // 查找\n
219
+ const text = richText.replace(/\n/g, '<br>');
220
+ // 拼接字符串
221
+ if (text) {
222
+ main += `
223
+ <div class="card-details">
224
+ ${text}
225
+ </div>
226
+ `;
215
227
  }
216
- }, '');
217
- // 查找\n
218
- const text = richText.replace(/\n/g, '<br>');
219
- // 拼接字符串
220
- text && (main += `
221
- <div class="card-details">
222
- ${text}
223
- </div>
224
- `);
228
+ }
225
229
  // 图片
226
230
  let major = '';
227
231
  if (module_dynamic.major && module_dynamic.major.draw) {
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": "0.1.0",
4
+ "version": "0.1.2",
5
5
  "contributors": [
6
6
  "Akokko <admin@akokko.com>"
7
7
  ],