@mrlingxd/koishi-plugin-adapter-onebot 0.1.0 → 0.2.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.
Files changed (44) hide show
  1. package/lib/bot/cqcode.d.ts +204 -5
  2. package/lib/bot/cqcode.js +1 -1
  3. package/lib/bot/index.d.ts +35 -19
  4. package/lib/bot/index.js +89 -53
  5. package/lib/bot/message.d.ts +4 -4
  6. package/lib/bot/message.js +58 -57
  7. package/lib/http.d.ts +5 -6
  8. package/lib/http.js +5 -7
  9. package/lib/index.d.ts +12 -8
  10. package/lib/index.js +2 -3
  11. package/lib/internal.d.ts +132 -0
  12. package/lib/{types.js → internal.js} +6 -57
  13. package/lib/types/device.d.ts +8 -0
  14. package/lib/types/device.js +1 -0
  15. package/lib/types/enum.d.ts +65 -0
  16. package/lib/types/enum.js +70 -0
  17. package/lib/types/event/base.d.ts +26 -0
  18. package/lib/types/event/base.js +20 -0
  19. package/lib/types/event/message.d.ts +44 -0
  20. package/lib/types/event/message.js +11 -0
  21. package/lib/types/event/meta.d.ts +34 -0
  22. package/lib/types/event/meta.js +1 -0
  23. package/lib/types/event/notice.d.ts +256 -0
  24. package/lib/types/event/notice.js +40 -0
  25. package/lib/types/event/request.d.ts +30 -0
  26. package/lib/types/event/request.js +11 -0
  27. package/lib/types/group.d.ts +43 -0
  28. package/lib/types/group.js +1 -0
  29. package/lib/types/index.d.ts +334 -0
  30. package/lib/types/index.js +10 -0
  31. package/lib/types/sender.d.ts +43 -0
  32. package/lib/types/sender.js +10 -0
  33. package/lib/types/user.d.ts +16 -0
  34. package/lib/types/user.js +1 -0
  35. package/lib/utils.d.ts +15 -11
  36. package/lib/utils.js +210 -200
  37. package/lib/ws.d.ts +9 -10
  38. package/lib/ws.js +2 -4
  39. package/package.json +6 -9
  40. package/lib/bot/base.d.ts +0 -36
  41. package/lib/bot/base.js +0 -66
  42. package/lib/bot/qqguild.d.ts +0 -31
  43. package/lib/bot/qqguild.js +0 -66
  44. package/lib/types.d.ts +0 -474
@@ -1,13 +1,212 @@
1
1
  import { Dict, h } from "koishi";
2
2
  export declare function CQCode(type: string, attrs: Dict<string>): string;
3
- export interface CQCode {
4
- type: string;
5
- data: Dict<string>;
6
- capture?: RegExpExecArray;
3
+ export interface CQCode<T extends string = string, D = Dict<string>> {
4
+ type: T;
5
+ data: D;
7
6
  }
8
7
  export declare namespace CQCode {
8
+ /** 文字 */
9
+ interface Text extends CQCode<"text", {
10
+ /** 文字内容 */
11
+ text: string;
12
+ /** 更多字段 */
13
+ [property: string]: unknown;
14
+ }> {
15
+ }
16
+ /** 图片 */
17
+ interface Image extends CQCode<"image", {
18
+ /** 图片链接/名字 */
19
+ file: string;
20
+ /** 图片链接 */
21
+ url?: string;
22
+ /** 更多字段 */
23
+ [property: string]: unknown;
24
+ }> {
25
+ }
26
+ /** 表情 */
27
+ interface Face extends CQCode<"face", {
28
+ /** 表情 ID */
29
+ id: string;
30
+ /** 更多字段 */
31
+ [property: string]: unknown;
32
+ }> {
33
+ }
34
+ /** 音乐 */
35
+ interface Music extends CQCode<"music", {
36
+ /** 音乐类型 */
37
+ type: "qq" | "163" | "xm" | string;
38
+ /** 音乐 ID */
39
+ id: string | number;
40
+ /** 更多字段 */
41
+ [property: string]: unknown;
42
+ }> {
43
+ }
44
+ /** 自定义音乐 */
45
+ interface CustomMusic extends CQCode<"music", {
46
+ /** 音乐类型 */
47
+ type: "custom";
48
+ /** 音乐 URL */
49
+ url: string;
50
+ /** 音乐音频 URL */
51
+ audio: string;
52
+ /** 音乐标题 */
53
+ title: string;
54
+ /** 音乐描述 */
55
+ content?: string;
56
+ /** 音乐图片 URL */
57
+ image?: string;
58
+ /** 更多字段 */
59
+ [property: string]: unknown;
60
+ }> {
61
+ }
62
+ /** 视频 */
63
+ interface Video extends CQCode<"video", {
64
+ /** 视频文件名 */
65
+ file: string;
66
+ /** 视频链接 */
67
+ url?: string;
68
+ /** 更多字段 */
69
+ [property: string]: unknown;
70
+ }> {
71
+ }
72
+ /**
73
+ * 语音
74
+ */
75
+ interface Record extends CQCode<"record", {
76
+ /** 语音文件名 */
77
+ file: string;
78
+ /** 语音链接 */
79
+ url?: string;
80
+ /** 更多字段 */
81
+ [property: string]: unknown;
82
+ }> {
83
+ }
84
+ /**
85
+ * 艾特
86
+ */
87
+ interface At extends CQCode<"at", {
88
+ /** 被艾特的 QQ 号 */
89
+ qq: string;
90
+ /** 被艾特的昵称 */
91
+ name?: string;
92
+ /** 更多字段 */
93
+ [property: string]: unknown;
94
+ }> {
95
+ }
96
+ /**
97
+ * 文件(未完全定义)
98
+ *
99
+ * 请根据实现端补全字段
100
+ */
101
+ interface File extends CQCode<"file", {
102
+ /** 图片链接 */
103
+ file: string;
104
+ /** 文件链接 */
105
+ url?: string;
106
+ /** 更多字段 */
107
+ [property: string]: unknown;
108
+ }> {
109
+ }
110
+ /**
111
+ * 回复
112
+ */
113
+ interface Reply extends CQCode<"reply", {
114
+ /** 消息 ID */
115
+ id: string;
116
+ /** 更多字段 */
117
+ [property: string]: unknown;
118
+ }> {
119
+ }
120
+ /**
121
+ * 转发消息
122
+ */
123
+ interface Forward extends CQCode<"forward", {
124
+ /** 转发 ID */
125
+ id: string;
126
+ /** 更多字段 */
127
+ [property: string]: unknown;
128
+ }> {
129
+ }
130
+ /**
131
+ * 回复
132
+ */
133
+ interface Reply extends CQCode<"reply", {
134
+ /** 消息 ID */
135
+ id: string;
136
+ /** 更多字段 */
137
+ [property: string]: unknown;
138
+ }> {
139
+ }
140
+ /**
141
+ * 戳一戳
142
+ */
143
+ interface Poke extends CQCode<"poke", {
144
+ /** 戳一戳类型 */
145
+ type: string;
146
+ /** 戳一戳 ID */
147
+ id: string;
148
+ /** 更多字段 */
149
+ [property: string]: unknown;
150
+ }> {
151
+ }
152
+ /**
153
+ * 商城表情
154
+ */
155
+ interface Mface extends CQCode<"mface", {
156
+ /** 表情 Url */
157
+ url?: string;
158
+ /** 表情包/组 ID */
159
+ emoji_package_id: string;
160
+ /** 表情 ID */
161
+ emoji_id: string;
162
+ /** 表情 key */
163
+ key: string;
164
+ /** 表情说明 */
165
+ summary: string;
166
+ /** 更多字段 */
167
+ [property: string]: unknown;
168
+ }> {
169
+ }
170
+ /**
171
+ * 合并消息
172
+ */
173
+ interface MergeForward extends CQCode<"node", {
174
+ /** 用户 ID */
175
+ user_id: string;
176
+ /** 昵称 */
177
+ nickname: string;
178
+ /** 消息内容 */
179
+ content: CQCodeUnion[];
180
+ /** 更多字段 */
181
+ [property: string]: unknown;
182
+ }> {
183
+ }
184
+ /**
185
+ * Json 消息
186
+ */
187
+ interface Json extends CQCode<"json", {
188
+ /** Json 内容 */
189
+ data: string | object;
190
+ /** 更多字段 */
191
+ [property: string]: unknown;
192
+ }> {
193
+ }
194
+ /**
195
+ * XML 消息
196
+ */
197
+ interface Xml extends CQCode<"xml", {
198
+ /** XML 内容 */
199
+ data: string;
200
+ /** 更多字段 */
201
+ [property: string]: unknown;
202
+ }> {
203
+ }
204
+ /** 联合类型 */
205
+ type CQCodeUnion = Text | Image | Face | Music | CustomMusic | Video | Record | At | File | Reply | Forward | Poke | Mface | MergeForward | Json;
9
206
  function escape(source: any, inline?: boolean): string;
10
207
  function unescape(source: string): string;
11
- function from(source: string): CQCode;
208
+ function from(source: string): CQCode & {
209
+ capture: RegExpExecArray;
210
+ };
12
211
  function parse(source: string | CQCode[]): h[];
13
212
  }
package/lib/bot/cqcode.js CHANGED
@@ -40,7 +40,7 @@ export function CQCode(type, attrs) {
40
40
  CQCode.from = from;
41
41
  function parse(source) {
42
42
  if (typeof source !== "string") {
43
- return source.map(({ type, data }) => h(type === "text" ? "text" : type, type === "text" ? { content: data.text } : data));
43
+ return source.map(({ type, data }) => h(type, data));
44
44
  }
45
45
  const elements = [];
46
46
  let result;
@@ -1,37 +1,53 @@
1
- import { Context, Schema, Session } from "koishi";
1
+ import { Bot, Context, Schema, Session, Universal } from "koishi";
2
2
  import { HttpServer } from "../http";
3
+ import { Internal } from "../internal";
3
4
  import { WsClient, WsServer } from "../ws";
4
- import { BaseBot } from "./base";
5
- import { QQGuildBot } from "./qqguild";
6
- export * from "./base";
7
- export * from "./cqcode";
8
- export * from "./message";
9
- export * from "./qqguild";
10
- export declare class OneBotBot<C extends Context, T extends OneBotBot.Config = OneBotBot.Config> extends BaseBot<C, T> {
11
- guildBot: QQGuildBot<C>;
12
- constructor(ctx: C, config: T);
5
+ import { OneBotMessageEncoder } from "./message";
6
+ export declare class OneBot<C extends Context = Context> extends Bot<C> {
7
+ static MessageEncoder: typeof OneBotMessageEncoder;
8
+ static inject: string[];
9
+ parent?: OneBot;
10
+ internal: Internal;
11
+ constructor(ctx: C, config: OneBot.Config);
13
12
  stop(): Promise<void>;
14
13
  initialize(): Promise<void>;
15
- setupGuildService(): Promise<void>;
16
- getChannel(channelId: string): Promise<import("@satorijs/protocol").Channel>;
17
- getGuild(guildId: string): Promise<import("@satorijs/protocol").Guild>;
14
+ createDirectChannel(userId: string): Promise<{
15
+ id: string;
16
+ type: Universal.Channel.Type;
17
+ }>;
18
+ getMessage(channelId: string, messageId: string): Promise<Universal.Message>;
19
+ deleteMessage(channelId: string, messageId: string): Promise<void>;
20
+ getLogin(): Promise<Universal.Login>;
21
+ getUser(userId: string): Promise<Universal.User>;
22
+ getFriendList(): Promise<{
23
+ data: Universal.User[];
24
+ }>;
25
+ handleFriendRequest(messageId: string, approve: boolean, comment?: string): Promise<void>;
26
+ handleGuildRequest(messageId: string, approve: boolean, comment?: string): Promise<void>;
27
+ handleGuildMemberRequest(messageId: string, approve: boolean, comment?: string): Promise<void>;
28
+ deleteFriend(userId: string): Promise<void>;
29
+ getMessageList(channelId: string, next?: string, direction?: Universal.Direction): Promise<{
30
+ data: Universal.Message[];
31
+ }>;
32
+ getChannel(channelId: string): Promise<Universal.Channel>;
33
+ getGuild(guildId: string): Promise<Universal.Guild>;
18
34
  getGuildList(): Promise<{
19
- data: import("@satorijs/protocol").Guild[];
35
+ data: Universal.Guild[];
20
36
  }>;
21
37
  getChannelList(guildId: string): Promise<{
22
- data: import("@satorijs/protocol").Channel[];
38
+ data: Universal.Channel[];
23
39
  }>;
24
- getGuildMember(guildId: string, userId: string): Promise<import("@satorijs/protocol").GuildMember>;
40
+ getGuildMember(guildId: string, userId: string): Promise<Universal.GuildMember>;
25
41
  getGuildMemberList(guildId: string): Promise<{
26
- data: import("@satorijs/protocol").GuildMember[];
42
+ data: Universal.GuildMember[];
27
43
  }>;
28
44
  kickGuildMember(guildId: string, userId: string, permanent?: boolean): Promise<void>;
29
45
  muteGuildMember(guildId: string, userId: string, duration: number): Promise<void>;
30
46
  muteChannel(channelId: string, guildId?: string, enable?: boolean): Promise<void>;
31
47
  checkPermission(name: string, session: Partial<Session>): Promise<boolean>;
32
48
  }
33
- export declare namespace OneBotBot {
34
- interface BaseConfig extends BaseBot.Config {
49
+ export declare namespace OneBot {
50
+ interface BaseConfig {
35
51
  selfId: string;
36
52
  password?: string;
37
53
  token?: string;
package/lib/bot/index.js CHANGED
@@ -1,82 +1,123 @@
1
- import { noop, Schema } from "koishi";
1
+ import { Bot, Schema } from "koishi";
2
2
  import { HttpServer } from "../http";
3
- import * as OneBot from "../utils";
3
+ import { Internal } from "../internal";
4
+ import { adaptChannel, adaptGuild, convertUser, decodeGuildMember, decodeMessage } from "../utils";
4
5
  import { WsClient, WsServer } from "../ws";
5
- import { BaseBot } from "./base";
6
- import { QQGuildBot } from "./qqguild";
7
- export * from "./base";
8
- export * from "./cqcode";
9
- export * from "./message";
10
- export * from "./qqguild";
11
- export class OneBotBot extends BaseBot {
12
- guildBot;
6
+ import { OneBotMessageEncoder, PRIVATE_PFX } from "./message";
7
+ export class OneBot extends Bot {
8
+ static MessageEncoder = OneBotMessageEncoder;
9
+ static inject = ["http"];
10
+ parent;
11
+ internal;
13
12
  constructor(ctx, config) {
14
13
  super(ctx, config, "onebot");
15
14
  this.selfId = config.selfId;
16
- this.internal = new OneBot.Internal(this);
17
15
  this.user.avatar = `http://q.qlogo.cn/headimg_dl?dst_uin=${config.selfId}&spec=640`;
16
+ this.internal = new Internal(this);
18
17
  if (config.protocol === "http") {
19
18
  ctx.plugin(HttpServer, this);
20
19
  }
21
- else if (config.protocol === "ws") {
20
+ else if (config.protocol === "ws" && config.responseTimeout) {
22
21
  ctx.plugin(WsClient, this);
23
22
  }
24
- else if (config.protocol === "ws-reverse") {
23
+ else if (config.protocol === "ws-reverse" && config.responseTimeout && config.path) {
25
24
  ctx.plugin(WsServer, this);
26
25
  }
27
26
  }
28
27
  async stop() {
29
- if (this.guildBot) {
30
- // QQGuild stub bot should also be removed
31
- delete this.ctx.bots[this.guildBot.sid];
32
- }
33
28
  await super.stop();
34
29
  }
35
30
  async initialize() {
36
- await Promise.all([this.getLogin(), this.setupGuildService().catch(noop)]).then(() => this.online(), (error) => this.offline(error));
37
- }
38
- async setupGuildService() {
39
- const profile = await this.internal.getGuildServiceProfile();
40
- // guild service is not supported in this account
41
- if (!profile?.tiny_id || profile.tiny_id === "0")
42
- return;
43
- this.ctx.plugin(QQGuildBot, {
44
- profile,
45
- parent: this,
46
- advanced: this.config.advanced
47
- });
31
+ await Promise.all([this.getLogin()]).then(() => this.online(), (error) => this.offline(error));
32
+ }
33
+ async createDirectChannel(userId) {
34
+ return { id: `${PRIVATE_PFX}${userId}`, type: 1 /* Universal.Channel.Type.DIRECT */ };
35
+ }
36
+ async getMessage(channelId, messageId) {
37
+ const data = await this.internal.getMsg(Number(messageId));
38
+ return await decodeMessage(this, data);
39
+ }
40
+ async deleteMessage(channelId, messageId) {
41
+ await this.internal.deleteMsg(Number(messageId));
42
+ }
43
+ async getLogin() {
44
+ const data = await this.internal.getLoginInfo();
45
+ this.user = {
46
+ id: data.user_id.toString(),
47
+ username: data.nickname,
48
+ avatar: `http://q.qlogo.cn/headimg_dl?dst_uin=${data.user_id}&spec=640`,
49
+ isBot: true
50
+ };
51
+ return this.toJSON();
52
+ }
53
+ async getUser(userId) {
54
+ const data = await this.internal.getStrangerInfo(Number(userId));
55
+ return convertUser(data, this.selfId === data.user_id.toString());
56
+ }
57
+ async getFriendList() {
58
+ const data = await this.internal.getFriendList();
59
+ return { data: data.map((item) => convertUser(item, this.selfId === item.user_id.toString())) };
60
+ }
61
+ async handleFriendRequest(messageId, approve, comment) {
62
+ await this.internal.setFriendAddRequest(messageId, approve, comment);
63
+ }
64
+ async handleGuildRequest(messageId, approve, comment) {
65
+ await this.internal.setGroupAddRequest(messageId, "invite", approve, comment);
66
+ }
67
+ async handleGuildMemberRequest(messageId, approve, comment) {
68
+ await this.internal.setGroupAddRequest(messageId, "add", approve, comment);
69
+ }
70
+ async deleteFriend(userId) {
71
+ await this.internal.deleteFriend(Number(userId));
72
+ }
73
+ async getMessageList(channelId, next, direction = "before") {
74
+ if (direction !== "before")
75
+ throw new Error("Unsupported direction.");
76
+ // include `before` message
77
+ let list;
78
+ if (next) {
79
+ const msg = await this.internal.getMsg(Number(next));
80
+ if (msg?.message_seq) {
81
+ list = (await this.internal.getGroupMsgHistory(Number(channelId), msg.message_id)).messages;
82
+ }
83
+ }
84
+ else {
85
+ list = (await this.internal.getGroupMsgHistory(Number(channelId))).messages;
86
+ }
87
+ // 从旧到新
88
+ return { data: await Promise.all(list.map((item) => decodeMessage(this, item))) };
48
89
  }
49
90
  async getChannel(channelId) {
50
- const data = await this.internal.getGroupInfo(channelId);
51
- return OneBot.adaptChannel(data);
91
+ const data = await this.internal.getGroupInfo(Number(channelId));
92
+ return adaptChannel(data);
52
93
  }
53
94
  async getGuild(guildId) {
54
- const data = await this.internal.getGroupInfo(guildId);
55
- return OneBot.adaptGuild(data);
95
+ const data = await this.internal.getGroupInfo(Number(guildId));
96
+ return adaptGuild(data);
56
97
  }
57
98
  async getGuildList() {
58
99
  const data = await this.internal.getGroupList();
59
- return { data: data.map(OneBot.adaptGuild) };
100
+ return { data: data.map(adaptGuild) };
60
101
  }
61
102
  async getChannelList(guildId) {
62
103
  return { data: [await this.getChannel(guildId)] };
63
104
  }
64
105
  async getGuildMember(guildId, userId) {
65
- const data = await this.internal.getGroupMemberInfo(guildId, userId);
66
- return OneBot.decodeGuildMember(data);
106
+ const data = await this.internal.getGroupMemberInfo(Number(guildId), Number(userId));
107
+ return decodeGuildMember(data);
67
108
  }
68
109
  async getGuildMemberList(guildId) {
69
- const data = await this.internal.getGroupMemberList(guildId);
70
- return { data: data.map(OneBot.decodeGuildMember) };
110
+ const data = await this.internal.getGroupMemberList(Number(guildId));
111
+ return { data: data.map((item) => decodeGuildMember(item)) };
71
112
  }
72
113
  async kickGuildMember(guildId, userId, permanent) {
73
- return this.internal.setGroupKick(guildId, userId, permanent);
114
+ return this.internal.setGroupKick(Number(guildId), Number(userId), permanent);
74
115
  }
75
116
  async muteGuildMember(guildId, userId, duration) {
76
- return this.internal.setGroupBan(guildId, userId, Math.round(duration / 1000));
117
+ return this.internal.setGroupBan(Number(guildId), Number(userId), Math.round(duration / 1000));
77
118
  }
78
119
  async muteChannel(channelId, guildId, enable) {
79
- return this.internal.setGroupWholeBan(channelId, enable);
120
+ return this.internal.setGroupWholeBan(Number(channelId), enable);
80
121
  }
81
122
  async checkPermission(name, session) {
82
123
  if (name === "onebot.group.admin") {
@@ -88,21 +129,16 @@ export class OneBotBot extends BaseBot {
88
129
  return super.checkPermission(name, session);
89
130
  }
90
131
  }
91
- (function (OneBotBot) {
92
- OneBotBot.BaseConfig = Schema.object({
132
+ (function (OneBot) {
133
+ OneBot.BaseConfig = Schema.object({
93
134
  selfId: Schema.string().description("机器人的账号。").required(),
94
135
  token: Schema.string()
95
136
  .role("secret")
96
137
  .description("发送信息时用于验证的字段,应与 OneBot 配置文件中的 `access_token` 保持一致。"),
97
- protocol: process.env.KOISHI_ENV === "browser"
98
- ? Schema.const("ws").default("ws")
99
- : Schema.union(["http", "ws", "ws-reverse"]).description("选择要使用的协议。").default("ws-reverse")
138
+ protocol: Schema.union(["http", "ws", "ws-reverse"]).description("选择要使用的协议。").default("ws-reverse")
100
139
  });
101
- OneBotBot.Config = Schema.intersect([
102
- OneBotBot.BaseConfig,
103
- Schema.union([HttpServer.Options, WsClient.Options, WsServer.Options]),
104
- Schema.object({
105
- advanced: BaseBot.AdvancedConfig
106
- })
140
+ OneBot.Config = Schema.intersect([
141
+ OneBot.BaseConfig,
142
+ Schema.union([HttpServer.Options, WsClient.Options, WsServer.Options])
107
143
  ]);
108
- })(OneBotBot || (OneBotBot = {}));
144
+ })(OneBot || (OneBot = {}));
@@ -1,5 +1,5 @@
1
1
  import { Context, h, MessageEncoder, Universal } from "koishi";
2
- import { BaseBot } from "./base";
2
+ import { OneBot } from ".";
3
3
  import { CQCode } from "./cqcode";
4
4
  export interface Author extends Universal.User {
5
5
  time?: string | number;
@@ -8,13 +8,13 @@ export interface Author extends Universal.User {
8
8
  declare class State {
9
9
  type: "message" | "forward" | "reply";
10
10
  author: Partial<Author>;
11
- children: CQCode[];
11
+ children: CQCode.CQCodeUnion[];
12
12
  constructor(type: "message" | "forward" | "reply");
13
13
  }
14
14
  export declare const PRIVATE_PFX = "private:";
15
- export declare class OneBotMessageEncoder<C extends Context = Context> extends MessageEncoder<C, BaseBot<C>> {
15
+ export declare class OneBotMessageEncoder<C extends Context = Context> extends MessageEncoder<C, OneBot<C>> {
16
16
  stack: State[];
17
- children: CQCode[];
17
+ children: CQCode.CQCodeUnion[];
18
18
  prepare(): Promise<void>;
19
19
  forward(): Promise<void>;
20
20
  flush(): Promise<void>;