mirai-js 2.8.0 → 2.8.3

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.
@@ -93,8 +93,8 @@ export class Bot implements BotConfigGetable {
93
93
  * @param callback 必选,回调函数
94
94
  * @returns handle 事件处理器的标识,用于移除该处理器
95
95
  */
96
- on<U extends EventType>(eventType: U, callback: Processor<[U]>): number;
97
- on<U extends EventType[]>(eventType: U, callback: Processor<U>): number[];
96
+ on<U extends EventType, E>(eventType: U, callback: Processor<[U], E>): number;
97
+ on<U extends EventType[], E>(eventType: U, callback: Processor<U, E>): number[];
98
98
 
99
99
  /**
100
100
  * @description 添加一个一次性事件处理器,回调一次后自动移除
@@ -298,6 +298,14 @@ export class Bot implements BotConfigGetable {
298
298
  */
299
299
  sendCommand({ command }: Bot.SendCommandOptions): Promise<Bot.MiraiConsoleMessage>;
300
300
 
301
+ /**
302
+ * @description 通过 messageId 获取消息
303
+ * @param {number} target 可选, 目标 qq 号/群号, mah v2.6.0+ 新增该参数
304
+ * @param {number} messageId 必选, 消息 id
305
+ * @returns
306
+ */
307
+ getMessageById({ messageId, target }: Bot.GetMessageByIdOptions): Promise<Bot.MessageFromMessageId>
308
+
301
309
  // 类方法
302
310
  /**
303
311
  * @description 检测该账号是否已经在 mirai-console 登录
@@ -532,6 +540,21 @@ declare namespace Bot {
532
540
  command: string[];
533
541
  }
534
542
 
543
+ interface GetMessageByIdOptions {
544
+ messageId: number;
545
+ target?: number;
546
+ }
547
+
548
+ interface MessageFromMessageId {
549
+ type: 'FriendMessage' | 'GroupMessage' | 'TempMessage';
550
+ messageChain: MessageType[];
551
+ sender: {
552
+ id?: number;
553
+ nickname?: string;
554
+ remark?: string;
555
+ }
556
+ }
557
+
535
558
  interface IsBotLoggedInOptions {
536
559
  baseUrl: string;
537
560
  verifyKey: string;
package/dist/node/Bot.js CHANGED
@@ -67,6 +67,8 @@ const _setGroupConfig = require('./core/setGroupConfig');
67
67
 
68
68
  const _setEssence = require('./core/setEssence');
69
69
 
70
+ const _messageFromId = require('./core/messageFromId');
71
+
70
72
  const {
71
73
  wsStartListening: _startListening,
72
74
  wsStopListening: _stopListening
@@ -1603,6 +1605,39 @@ class Bot extends BotConfigGetable {
1603
1605
  }).reduce((acc, cur) => acc.addText(cur), new Message()).messageChain
1604
1606
  });
1605
1607
  }
1608
+ /**
1609
+ * @description 通过 messageId 获取消息
1610
+ * @param {number} target 可选, 目标 qq 号/群号, mah v2.6.0+ 新增该参数
1611
+ * @param {number} messageId 必选, 消息 id
1612
+ * @returns {Object} 结构 { type, messageChain, sender }
1613
+ */
1614
+
1615
+
1616
+ async getMessageById({
1617
+ messageId,
1618
+ target
1619
+ }) {
1620
+ // 检查对象状态
1621
+ if (!this.config) {
1622
+ throw new Error('getMessageById 请先调用 open,建立一个会话');
1623
+ } // 检查参数
1624
+
1625
+
1626
+ if (!messageId) {
1627
+ throw new Error('getMessageById 缺少必要的 messageId 参数');
1628
+ }
1629
+
1630
+ const {
1631
+ baseUrl,
1632
+ sessionKey
1633
+ } = this.config;
1634
+ return await _messageFromId({
1635
+ baseUrl,
1636
+ sessionKey,
1637
+ target,
1638
+ messageId
1639
+ });
1640
+ }
1606
1641
  /**
1607
1642
  * @description 检测该账号是否已经在 mirai-console 登录
1608
1643
  * @param {string} baseUrl 必选,mirai-api-http server 的地址
@@ -1,7 +1,8 @@
1
- import { Processor, EventType } from './BaseType';
1
+ import { Processor, EventType, MessageChainElementTypes, MessageType } from './BaseType';
2
2
  import { Bot } from './Bot';
3
+ import { ArrayToValuesUnion } from './typeHelpers';
3
4
 
4
- export class Middleware {
5
+ export class Middleware<CTX = { [key: string]: any }> {
5
6
  private middleware: ((data: any, next: Middleware.NextMiddlewareCaller) => any)[];
6
7
  private catcher: (error: any) => any;
7
8
 
@@ -12,44 +13,44 @@ export class Middleware {
12
13
  * @param verifyKey mirai-api-http server 设置的 verifyKey
13
14
  * @param password 欲重新登陆的 qq 密码
14
15
  */
15
- autoReLogin({ bot, baseUrl, verifyKey, password }: Middleware.AutoReLoginOptions): Middleware;
16
+ autoReLogin({ bot, baseUrl, verifyKey, password }: Middleware.AutoReLoginOptions): Middleware<CTX>;
16
17
 
17
18
  /**
18
19
  * @description 自动重建 ws 连接
19
20
  * @param bot 欲重连的 Bot 实例
20
21
  */
21
- autoReconnection(bot: Bot): Middleware;
22
+ autoReconnection(bot: Bot): Middleware<CTX>;
22
23
 
23
24
  /**
24
25
  * @description 过滤出指定类型的消息,消息类型为 key,对应类型的
25
26
  * message 数组为 value,置于 data.classified
26
27
  * @param typeArr message 的类型,例如 Plain Image Voice
27
28
  */
28
- messageProcessor(typeArr: string[]): Middleware;
29
+ messageProcessor<U extends MessageChainElementTypes[]>(typeArr: U): Middleware<CTX & { classified: { [type in ArrayToValuesUnion<U>]: any[] } }>;
29
30
 
30
31
  /**
31
32
  * @description 过滤出字符串类型的 message,并拼接在一起,置于 data.text
32
33
  */
33
- textProcessor(): Middleware;
34
+ textProcessor(): Middleware<CTX & { text: string }>;
34
35
 
35
36
  /**
36
37
  * @description 过滤出消息 id,置于 data.messageId
37
38
  */
38
- messageIdProcessor(): Middleware;
39
+ messageIdProcessor(): Middleware<CTX & { messageId: string }>;
39
40
 
40
41
  /**
41
42
  * @description 过滤指定的群消息
42
43
  * @param groupArr 允许通过的群号数组
43
44
  * @param allow 允许通过还是禁止通过
44
45
  */
45
- groupFilter(groupArr: number[], allow?: boolean): Middleware;
46
+ groupFilter(groupArr: number[], allow?: boolean): Middleware<CTX>;
46
47
 
47
48
  /**
48
49
  * @description 过滤指定的好友消息
49
50
  * @param friendArr 好友 qq 号数组
50
51
  * @param allow 允许通过还是禁止通过
51
52
  */
52
- friendFilter(friendArr: number[], allow?: boolean): Middleware;
53
+ friendFilter(friendArr: number[], allow?: boolean): Middleware<CTX>;
53
54
 
54
55
  /**
55
56
  * @description 过滤指定群的群成员的消息
@@ -57,32 +58,32 @@ export class Middleware {
57
58
  * @param allow 允许通过还是禁止通过
58
59
  * 结构 { number => number[], } key 为允许通过的群号,value 为该群允许通过的成员 qq
59
60
  */
60
- groupMemberFilter(groupMemberMap: Middleware.GroupMemberMap, allow?: boolean): Middleware;
61
+ groupMemberFilter(groupMemberMap: Middleware.GroupMemberMap, allow?: boolean): Middleware<CTX>;
61
62
 
62
63
  /**
63
64
  * @description 这是一个对话锁,保证群中同一成员不能在中途触发处理器
64
65
  * @use 在你需要保护的过程结束后调用 data.unlock 即可
65
66
  */
66
- memberLock({ autoUnlock }?: Middleware.LockOptions): Middleware;
67
+ memberLock({ autoUnlock }?: Middleware.LockOptions): Middleware<CTX & { unlock: () => void }>;
67
68
 
68
69
  /**
69
70
  * @description 这是一个对话锁,保证同一好友不能在中途触发处理器
70
71
  * @use 在你需要保护的过程结束后调用 data.unlock 即可
71
72
  */
72
- friendLock({ autoUnlock }?: Middleware.LockOptions): Middleware;
73
+ friendLock({ autoUnlock }?: Middleware.LockOptions): Middleware<CTX & { unlock: () => void }>;
73
74
 
74
75
  /**
75
76
  * @description 过滤包含指定 @ 信息的消息
76
77
  * @param atArr 必选,qq 号数组
77
78
  * @param allow 可选,允许通过还是禁止通过
78
79
  */
79
- atFilter(friendArr: number[], allow?: boolean): Middleware;
80
+ atFilter(friendArr: number[], allow?: boolean): Middleware<CTX>;
80
81
 
81
82
  /**
82
83
  * @description 用于 NewFriendRequestEvent 的中间件,经过该中间件后,将在 data 下放置三个方法
83
84
  * agree、refuse、refuseAndAddBlacklist,调用后将分别进行好友请求的 同意、拒绝和拒绝并加入黑名单
84
85
  */
85
- friendRequestProcessor(): Middleware;
86
+ friendRequestProcessor(): Middleware<CTX & { agree: () => void, refuse: () => void, refuseAndAddBlacklist: () => void }>;
86
87
 
87
88
  /**
88
89
  * ! mirai-core 的问题,有时候收不到 MemberJoinRequestEvent 事件
@@ -93,9 +94,11 @@ export class Middleware {
93
94
  * ignore 忽略
94
95
  * refuseAndAddBlacklist 拒绝并移入黑名单
95
96
  * ignoreAndAddBlacklist 忽略并移入黑名单
96
- * @param bot 必选,Bot 实例
97
97
  */
98
- memberJoinRequestProcessor(): Middleware;
98
+ memberJoinRequestProcessor(): Middleware<CTX & {
99
+ agree: () => void, refuse: () => void, ignore: () => void,
100
+ refuseAndAddBlacklist: () => void, ignoreAndAddBlacklist: () => void,
101
+ }>;
99
102
 
100
103
  /**
101
104
  * ! 目前被邀请入群不会触发 BotInvitedJoinGroupRequestEvent 事件
@@ -103,32 +106,47 @@ export class Middleware {
103
106
  * @description 用于 BotInvitedJoinGroupRequestEvent 的中间件,经过该中间件后,将在 data 下放置两个方法
104
107
  * agree 同意
105
108
  * refuse 拒绝
106
- * @param bot 必选,Bot 实例
107
109
  */
108
- invitedJoinGroupRequestProcessor(): Middleware;
110
+ invitedJoinGroupRequestProcessor(): Middleware<CTX & { agree: () => void, refuse: () => void }>;
109
111
 
110
112
  /**
111
113
  * @description Waiter 的包装器,提供方便的同步 IO 方式
112
114
  */
113
- syncWrapper(): Middleware;
115
+ syncWrapper(): Middleware<CTX & {
116
+ waitFor: {
117
+ groupMember: (qq: number) => {
118
+ messageChain: () => Promise<MessageType[]>,
119
+ text: () => Promise<string>,
120
+ custom: <R>(processor: () => R) => Promise<R>,
121
+ },
122
+ friend: (qq) => {
123
+ messageChain: () => Promise<MessageType[]>,
124
+ text: () => Promise<string>,
125
+ custom: <R>(processor: () => R) => Promise<R>,
126
+ },
127
+ messageChain: () => Promise<MessageType[]>,
128
+ text: Promise<string>,
129
+ custom: <R>(processor: () => R) => Promise<R>,
130
+ }
131
+ }>;
114
132
 
115
133
  /**
116
134
  * @description 添加一个自定义中间件
117
135
  * @param callback (data, next) => void
118
136
  */
119
- use(callback: (data: any, next: Middleware.NextMiddlewareCaller) => any): Middleware;
137
+ use(callback: (data: CTX, next: Middleware.NextMiddlewareCaller) => any): Middleware<CTX>;
120
138
 
121
139
  /**
122
140
  * @description 使用错误处理器
123
141
  * @param catcher 错误处理器 (err) => void
124
142
  */
125
- catch(catcher: (error: any) => any): Middleware;
143
+ catch(catcher: (error: any) => any): Middleware<CTX>;
126
144
 
127
145
  /**
128
146
  * @description 生成一个带有中间件的事件处理器
129
147
  * @param callback 事件处理器
130
148
  */
131
- done<E extends EventType[] | EventType>(callback: Processor<E extends EventType ? [E] : E>): Processor<E extends EventType ? [E] : E>;
149
+ done<E extends EventType[]>(callback: Processor<E, CTX>): Processor<E, CTX>;
132
150
 
133
151
  }
134
152
 
@@ -0,0 +1,71 @@
1
+ "use strict";
2
+
3
+ const {
4
+ errCodeMap
5
+ } = require('../util/errCode');
6
+
7
+ const axios = require('axios');
8
+
9
+ const {
10
+ URL
11
+ } = require('../polyfill/URL');
12
+
13
+ const errorHandler = require('../util/errorHandler');
14
+
15
+ const path = require('path');
16
+
17
+ const {
18
+ isBrowserEnv
19
+ } = require('../util/isBrowserEnv');
20
+
21
+ const locationStr = !isBrowserEnv() ? `core.${path.basename(__filename, path.extname(__filename))}` : 'borwser';
22
+ /**
23
+ * @description 通过 messageId 获取消息
24
+ * @param {string} baseUrl mirai-api-http server 的地址
25
+ * @param {string} sessionKey 会话标识
26
+ * @param {number} target qq 号/群号
27
+ * @param {number} messageId 消息 id
28
+ * @returns {Object} 结构 { type, messageChain, sender }
29
+ */
30
+
31
+ module.exports = async ({
32
+ baseUrl,
33
+ sessionKey,
34
+ target,
35
+ messageId
36
+ }) => {
37
+ try {
38
+ // 拼接 url
39
+ const url = new URL('/messageFromId', baseUrl).toString(); // 请求
40
+
41
+ const responseData = await axios.get(url, {
42
+ params: {
43
+ sessionKey,
44
+ target,
45
+ messageId
46
+ }
47
+ });
48
+
49
+ try {
50
+ var {
51
+ data: {
52
+ msg: message,
53
+ code,
54
+ data
55
+ }
56
+ } = responseData;
57
+ } catch (error) {
58
+ throw new Error('请求返回格式出错,请检查 mirai-console');
59
+ } // 抛出 mirai 的异常,到 catch 中处理后再抛出
60
+
61
+
62
+ if (code in errCodeMap) {
63
+ throw new Error(message);
64
+ }
65
+
66
+ return data;
67
+ } catch (error) {
68
+ console.error(`mirai-js: error ${locationStr}`);
69
+ errorHandler(error);
70
+ }
71
+ };
package/index.ts ADDED
@@ -0,0 +1,5 @@
1
+ function fun<T extends string, R extends T>(arr: T[]): R extends T ? R : never {
2
+
3
+ }
4
+
5
+ const r = fun(['a', 'b'])
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mirai-js",
3
- "version": "2.8.0",
3
+ "version": "2.8.3",
4
4
  "description": "QQ robot development framework based on Mirai-api-http.",
5
5
  "main": "dist/node/index.js",
6
6
  "scripts": {
package/src/BaseType.d.ts CHANGED
@@ -87,7 +87,7 @@ type MessageId = number;
87
87
  * @see https://github.com/project-mirai/mirai-api-http/blob/master/docs/EventType.md
88
88
  */
89
89
 
90
- type MessageChainElementTypes =
90
+ export type MessageChainElementTypes =
91
91
  | 'Source'
92
92
  | 'Quote'
93
93
  | 'At'
@@ -113,26 +113,6 @@ interface EventBaseType {
113
113
  }
114
114
 
115
115
  // Middleware
116
- interface MessageExtendType {
117
- text?: string;
118
- classified?: {
119
- [key in MessageChainElementTypes]?: any[];
120
- };
121
- messageId?: number;
122
- waitFor?: any
123
- unlock?: () => void;
124
- }
125
- type RequestEventMethods =
126
- | 'agree'
127
- | 'refuse'
128
- | 'ignore'
129
- | 'refuseAndAddBlacklist'
130
- | 'ignoreAndAddBlacklist';
131
-
132
- type RequestEventExtendType = {
133
- [key in RequestEventMethods]?: () => void;
134
- };
135
-
136
116
  interface Member {
137
117
  id: number;
138
118
  memberName: string;
@@ -169,14 +149,12 @@ interface EventEntityMap {
169
149
  type: 'GroupMessage';
170
150
  sender: Member & { group: GroupSenderType },
171
151
  messageChain: MessageType[];
172
- } & EventBaseType &
173
- MessageExtendType,
152
+ } & EventBaseType,
174
153
  FriendMessage: {
175
154
  type: 'FriendMessage';
176
155
  messageChain: MessageType[];
177
156
  sender: Friend
178
- } & EventBaseType &
179
- MessageExtendType,
157
+ } & EventBaseType,
180
158
  BotOnlineEvent: {
181
159
  type: 'BotOnlineEvent',
182
160
  qq: number
@@ -334,7 +312,7 @@ interface EventEntityMap {
334
312
  groupId: number,
335
313
  nick: string,
336
314
  message: string
337
- } & RequestEventExtendType & EventBaseType;
315
+ } & EventBaseType;
338
316
  MemberJoinRequestEvent: {
339
317
  type: 'MemberJoinRequestEvent',
340
318
  eventId: number,
@@ -343,7 +321,7 @@ interface EventEntityMap {
343
321
  groupName: string,
344
322
  nick: string,
345
323
  message: string
346
- } & RequestEventExtendType & EventBaseType;
324
+ } & EventBaseType;
347
325
  BotInvitedJoinGroupRequestEvent: {
348
326
  type: 'MemberJoinRequestEvent',
349
327
  eventId: number,
@@ -352,7 +330,7 @@ interface EventEntityMap {
352
330
  groupName: string,
353
331
  nick: string,
354
332
  message: string
355
- } & RequestEventExtendType & EventBaseType;
333
+ } & EventBaseType;
356
334
  }
357
335
 
358
336
  type EventType = keyof EventEntityMap;
@@ -366,8 +344,7 @@ type GroupPermission = 'OWNER' | 'ADMINISTRATOR' | 'MEMBER';
366
344
  type SEX = 'UNKNOWN' | 'MALE' | 'FEMALE';
367
345
 
368
346
  // 消息处理器
369
- type Processor<U extends EventType[] | 'UnknownEventType' = 'UnknownEventType'> =
370
- (data: U extends 'UnknownEventType' ? EventBaseType : EventEntityMap[ArrayToValuesUnion<U extends 'UnknownEventType' ? never : U>]) => Awaitable<void | any>;
347
+ type Processor<U extends EventType[] = [], Extend = { [key: string]: any }> = (data: EventEntityMap[ArrayToValuesUnion<U>] & Extend) => Awaitable<void | any>;
371
348
 
372
349
  // QQ 自带表情
373
350
  type FaceType =
package/src/Bot.d.ts CHANGED
@@ -93,8 +93,8 @@ export class Bot implements BotConfigGetable {
93
93
  * @param callback 必选,回调函数
94
94
  * @returns handle 事件处理器的标识,用于移除该处理器
95
95
  */
96
- on<U extends EventType>(eventType: U, callback: Processor<[U]>): number;
97
- on<U extends EventType[]>(eventType: U, callback: Processor<U>): number[];
96
+ on<U extends EventType, E>(eventType: U, callback: Processor<[U], E>): number;
97
+ on<U extends EventType[], E>(eventType: U, callback: Processor<U, E>): number[];
98
98
 
99
99
  /**
100
100
  * @description 添加一个一次性事件处理器,回调一次后自动移除
@@ -298,6 +298,14 @@ export class Bot implements BotConfigGetable {
298
298
  */
299
299
  sendCommand({ command }: Bot.SendCommandOptions): Promise<Bot.MiraiConsoleMessage>;
300
300
 
301
+ /**
302
+ * @description 通过 messageId 获取消息
303
+ * @param {number} target 可选, 目标 qq 号/群号, mah v2.6.0+ 新增该参数
304
+ * @param {number} messageId 必选, 消息 id
305
+ * @returns
306
+ */
307
+ getMessageById({ messageId, target }: Bot.GetMessageByIdOptions): Promise<Bot.MessageFromMessageId>
308
+
301
309
  // 类方法
302
310
  /**
303
311
  * @description 检测该账号是否已经在 mirai-console 登录
@@ -532,6 +540,21 @@ declare namespace Bot {
532
540
  command: string[];
533
541
  }
534
542
 
543
+ interface GetMessageByIdOptions {
544
+ messageId: number;
545
+ target?: number;
546
+ }
547
+
548
+ interface MessageFromMessageId {
549
+ type: 'FriendMessage' | 'GroupMessage' | 'TempMessage';
550
+ messageChain: MessageType[];
551
+ sender: {
552
+ id?: number;
553
+ nickname?: string;
554
+ remark?: string;
555
+ }
556
+ }
557
+
535
558
  interface IsBotLoggedInOptions {
536
559
  baseUrl: string;
537
560
  verifyKey: string;
package/src/Bot.js CHANGED
@@ -32,6 +32,7 @@ const _quitGroup = require('./core/quitGroup');
32
32
  const _getGroupConfig = require('./core/getGroupConfig');
33
33
  const _setGroupConfig = require('./core/setGroupConfig');
34
34
  const _setEssence = require('./core/setEssence');
35
+ const _messageFromId = require('./core/messageFromId');
35
36
  const { wsStartListening: _startListening, wsStopListening: _stopListening } = require('./polyfill/wsListener');
36
37
 
37
38
  // 其他
@@ -1143,6 +1144,27 @@ class Bot extends BotConfigGetable {
1143
1144
  });
1144
1145
  }
1145
1146
 
1147
+ /**
1148
+ * @description 通过 messageId 获取消息
1149
+ * @param {number} target 可选, 目标 qq 号/群号, mah v2.6.0+ 新增该参数
1150
+ * @param {number} messageId 必选, 消息 id
1151
+ * @returns {Object} 结构 { type, messageChain, sender }
1152
+ */
1153
+ async getMessageById({ messageId, target }) {
1154
+ // 检查对象状态
1155
+ if (!this.config) {
1156
+ throw new Error('getMessageById 请先调用 open,建立一个会话');
1157
+ }
1158
+
1159
+ // 检查参数
1160
+ if (!messageId) {
1161
+ throw new Error('getMessageById 缺少必要的 messageId 参数');
1162
+ }
1163
+
1164
+ const { baseUrl, sessionKey } = this.config;
1165
+ return await _messageFromId({ baseUrl, sessionKey, target, messageId });
1166
+ }
1167
+
1146
1168
  /**
1147
1169
  * @description 检测该账号是否已经在 mirai-console 登录
1148
1170
  * @param {string} baseUrl 必选,mirai-api-http server 的地址