@alemonjs/qq-bot 2.1.33 → 2.1.35

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 (132) hide show
  1. package/README.md +46 -8
  2. package/dist/assets/index.css +1 -1
  3. package/dist/assets/index.js +12 -5
  4. package/dist/index.html +1 -1
  5. package/lib/config.d.ts +44 -19
  6. package/lib/config.js +39 -35
  7. package/lib/desktop.d.ts +4 -1
  8. package/lib/desktop.js +53 -57
  9. package/lib/format.d.ts +26 -5
  10. package/lib/format.js +84 -101
  11. package/lib/hook.d.ts +82 -65
  12. package/lib/hook.js +35 -32
  13. package/lib/index.d.ts +6 -4
  14. package/lib/index.js +13 -16
  15. package/lib/index.webhook.d.ts +4 -1
  16. package/lib/index.webhook.js +12 -14
  17. package/lib/index.websoket.d.ts +6 -3
  18. package/lib/index.websoket.js +131 -41
  19. package/lib/message/AT_MESSAGE_CREATE.d.ts +36 -33
  20. package/lib/message/AT_MESSAGE_CREATE.js +1 -1
  21. package/lib/message/CHANNEL_CREATE.d.ts +17 -14
  22. package/lib/message/CHANNEL_CREATE.js +1 -1
  23. package/lib/message/CHANNEL_DELETE.d.ts +22 -14
  24. package/lib/message/CHANNEL_DELETE.js +1 -1
  25. package/lib/message/CHANNEL_UPDATE.d.ts +22 -14
  26. package/lib/message/CHANNEL_UPDATE.js +1 -1
  27. package/lib/message/DIRECT_MESSAGE_CREATE.d.ts +35 -27
  28. package/lib/message/DIRECT_MESSAGE_CREATE.js +1 -1
  29. package/lib/message/DIRECT_MESSAGE_DELETE.d.ts +23 -15
  30. package/lib/message/DIRECT_MESSAGE_DELETE.js +1 -1
  31. package/lib/message/ERROR.d.ts +4 -1
  32. package/lib/message/ERROR.js +1 -1
  33. package/lib/message/GUILD_CREATE.d.ts +22 -14
  34. package/lib/message/GUILD_CREATE.js +1 -1
  35. package/lib/message/GUILD_DELETE.d.ts +22 -14
  36. package/lib/message/GUILD_DELETE.js +1 -1
  37. package/lib/message/GUILD_MEMBER_ADD.d.ts +21 -13
  38. package/lib/message/GUILD_MEMBER_ADD.js +1 -1
  39. package/lib/message/GUILD_MEMBER_REMOVE.d.ts +21 -13
  40. package/lib/message/GUILD_MEMBER_REMOVE.js +1 -1
  41. package/lib/message/GUILD_MEMBER_UPDATE.d.ts +21 -13
  42. package/lib/message/GUILD_MEMBER_UPDATE.js +1 -1
  43. package/lib/message/GUILD_UPDATE.d.ts +22 -14
  44. package/lib/message/GUILD_UPDATE.js +1 -1
  45. package/lib/message/INTERACTION_CREATE.d.ts +52 -44
  46. package/lib/message/INTERACTION_CREATE.js +1 -1
  47. package/lib/message/MESSAGE_CREATE.d.ts +12 -1
  48. package/lib/message/MESSAGE_CREATE.js +1 -1
  49. package/lib/message/MESSAGE_DELETE.d.ts +12 -1
  50. package/lib/message/MESSAGE_DELETE.js +1 -1
  51. package/lib/message/MESSAGE_REACTION_ADD.d.ts +15 -12
  52. package/lib/message/MESSAGE_REACTION_ADD.js +1 -1
  53. package/lib/message/MESSAGE_REACTION_REMOVE.d.ts +15 -12
  54. package/lib/message/MESSAGE_REACTION_REMOVE.js +1 -1
  55. package/lib/message/PUBLIC_MESSAGE_DELETE.d.ts +20 -13
  56. package/lib/message/PUBLIC_MESSAGE_DELETE.js +1 -1
  57. package/lib/message/READY.d.ts +11 -5
  58. package/lib/message/READY.js +1 -1
  59. package/lib/message/group/C2C_MESSAGE_CREATE.d.ts +18 -15
  60. package/lib/message/group/C2C_MESSAGE_CREATE.js +1 -1
  61. package/lib/message/group/C2C_MSG_RECEIVE.d.ts +13 -3
  62. package/lib/message/group/C2C_MSG_RECEIVE.js +1 -1
  63. package/lib/message/group/C2C_MSG_REJECT.d.ts +9 -3
  64. package/lib/message/group/C2C_MSG_REJECT.js +1 -1
  65. package/lib/message/group/FRIEND_ADD.d.ts +13 -3
  66. package/lib/message/group/FRIEND_ADD.js +1 -1
  67. package/lib/message/group/FRIEND_DEL.d.ts +9 -3
  68. package/lib/message/group/FRIEND_DEL.js +1 -1
  69. package/lib/message/group/GROUP_ADD_ROBOT.d.ts +23 -4
  70. package/lib/message/group/GROUP_ADD_ROBOT.js +1 -1
  71. package/lib/message/group/GROUP_AT_MESSAGE_CREATE.d.ts +38 -32
  72. package/lib/message/group/GROUP_AT_MESSAGE_CREATE.js +1 -1
  73. package/lib/message/group/GROUP_DEL_ROBOT.d.ts +19 -4
  74. package/lib/message/group/GROUP_DEL_ROBOT.js +1 -1
  75. package/lib/message/group/GROUP_JOIN_REQUEST.d.ts +83 -22
  76. package/lib/message/group/GROUP_JOIN_REQUEST.js +1 -1
  77. package/lib/message/group/GROUP_MEMBER_ADD.d.ts +8 -5
  78. package/lib/message/group/GROUP_MEMBER_ADD.js +1 -1
  79. package/lib/message/group/GROUP_MEMBER_REMOVE.d.ts +8 -5
  80. package/lib/message/group/GROUP_MEMBER_REMOVE.js +1 -1
  81. package/lib/message/group/GROUP_MESSAGE_CREATE.d.ts +38 -32
  82. package/lib/message/group/GROUP_MESSAGE_CREATE.js +1 -1
  83. package/lib/message/group/GROUP_MSG_RECEIVE.d.ts +14 -4
  84. package/lib/message/group/GROUP_MSG_RECEIVE.js +1 -1
  85. package/lib/message/group/GROUP_MSG_REJECT.d.ts +10 -4
  86. package/lib/message/group/GROUP_MSG_REJECT.js +1 -1
  87. package/lib/message/group/MESSAGE_AUDIT_PASS.d.ts +12 -6
  88. package/lib/message/group/MESSAGE_AUDIT_PASS.js +1 -1
  89. package/lib/message/group/MESSAGE_AUDIT_REJECT.d.ts +12 -6
  90. package/lib/message/group/MESSAGE_AUDIT_REJECT.js +1 -1
  91. package/lib/register.d.ts +12 -9
  92. package/lib/register.js +1246 -1404
  93. package/lib/sdk/api.d.ts +937 -306
  94. package/lib/sdk/api.js +1481 -893
  95. package/lib/sdk/client.webhook.d.ts +25 -8
  96. package/lib/sdk/client.webhook.js +185 -189
  97. package/lib/sdk/client.websoket.d.ts +31 -9
  98. package/lib/sdk/client.websoket.js +369 -392
  99. package/lib/sdk/config.d.ts +6 -2
  100. package/lib/sdk/config.js +9 -6
  101. package/lib/sdk/instance.d.ts +11 -3
  102. package/lib/sdk/instance.js +72 -84
  103. package/lib/sdk/intents.d.ts +89 -3
  104. package/lib/sdk/intents.js +116 -33
  105. package/lib/sdk/message.d.ts +7 -4
  106. package/lib/sdk/message.group.d.ts +38 -35
  107. package/lib/sdk/message.group.js +1 -1
  108. package/lib/sdk/message.guild.d.ts +40 -37
  109. package/lib/sdk/message.guild.js +1 -1
  110. package/lib/sdk/message.js +1 -1
  111. package/lib/sdk/message.public.d.ts +8 -5
  112. package/lib/sdk/message.public.js +1 -1
  113. package/lib/sdk/qr-auth.d.ts +55 -0
  114. package/lib/sdk/qr-auth.js +166 -0
  115. package/lib/sdk/registry.d.ts +34 -24
  116. package/lib/sdk/registry.js +134 -114
  117. package/lib/sdk/session.d.ts +19 -15
  118. package/lib/sdk/session.js +51 -54
  119. package/lib/sdk/typing.d.ts +410 -184
  120. package/lib/sdk/typing.js +1 -1
  121. package/lib/sdk/webhook.secret.d.ts +33 -13
  122. package/lib/sdk/webhook.secret.js +50 -36
  123. package/lib/sends.d.ts +42 -25
  124. package/lib/sends.js +519 -541
  125. package/lib/types.d.ts +52 -41
  126. package/lib/types.js +1 -1
  127. package/lib/upload.d.ts +47 -18
  128. package/lib/upload.js +80 -51
  129. package/lib/utils.d.ts +9 -1
  130. package/lib/utils.js +10 -5
  131. package/package.json +10 -7
  132. package/LICENSE +0 -21
package/lib/sends.js CHANGED
@@ -1,599 +1,577 @@
1
- import { readFileSync } from 'fs';
2
- import { createResult, ResultCode, logger } from 'alemonjs';
3
- import axios from 'axios';
4
- import { dataEnumToText, markdownToText, buttonsToText } from './format.js';
5
- import { getQQBotConfig } from './config.js';
1
+ import { getQQBotConfig } from "./config.js";
2
+ import { buttonsToText, dataEnumToText, markdownToText } from "./format.js";
3
+ import { ResultCode, createResult, logger } from "alemonjs";
4
+ import { readFileSync } from "fs";
5
+ import axios from "axios";
6
6
 
7
+ //#region src/sends.ts
8
+ /** QQ Bot 平台按钮限制:最多 5 行,每行最多 5 个按钮 */
7
9
  const MAX_BUTTON_ROWS = 5;
8
10
  const MAX_BUTTONS_PER_ROW = 5;
11
+ /**
12
+ * QQ-Bot 按钮样式(render_data.style):
13
+ * 0 灰色线框 / 1 蓝色线框 / 3 红框 / 4 蓝底白字
14
+ */
9
15
  const BUTTON_STYLE_MAP = {
10
- gray: 0,
11
- blue: 1,
12
- red: 3,
13
- 'blue-fill': 4
16
+ gray: 0,
17
+ blue: 1,
18
+ red: 3,
19
+ "blue-fill": 4
14
20
  };
21
+ /** 解析按钮样式:支持样式名与数字(含数字字符串),默认灰框 0 */
15
22
  const resolveButtonStyle = (style) => {
16
- if (typeof style === 'number') {
17
- return style;
18
- }
19
- if (typeof style === 'string') {
20
- if (BUTTON_STYLE_MAP[style] !== undefined) {
21
- return BUTTON_STYLE_MAP[style];
22
- }
23
- if (style.trim() !== '' && !Number.isNaN(Number(style))) {
24
- return Number(style);
25
- }
26
- }
27
- return 0;
23
+ if (typeof style === "number") return style;
24
+ if (typeof style === "string") {
25
+ if (BUTTON_STYLE_MAP[style] !== void 0) return BUTTON_STYLE_MAP[style];
26
+ if (style.trim() !== "" && !Number.isNaN(Number(style))) return Number(style);
27
+ }
28
+ return 0;
28
29
  };
29
30
  const createButtonsData = (rows, startId = 0) => {
30
- let id = startId;
31
- const clippedRows = rows.slice(0, MAX_BUTTON_ROWS);
32
- return {
33
- rows: clippedRows.map(row => ({
34
- buttons: row.value.slice(0, MAX_BUTTONS_PER_ROW).map(button => {
35
- const value = button.value;
36
- const options = button.options;
37
- id++;
38
- const typing = options?.type ?? 'command';
39
- const typeMap = { command: 2, link: 0, call: 1 };
40
- const rowData = options?.rawData ?? {};
41
- const data = options?.data;
42
- const modal = options?.modal ??
43
- (typeof data === 'object' && data
44
- ? {
45
- content: data.click,
46
- confirmText: data.confirm,
47
- cancelText: data.cancel
48
- }
49
- : undefined);
50
- const action = {
51
- type: typeMap[typing],
52
- permission: {
53
- type: typeof options.permission?.type === 'undefined' ? 2 : options?.permission?.type,
54
- specify_user_ids: options?.permission?.userIds,
55
- specify_role_ids: options?.permission?.roleIds
56
- },
57
- unsupport_tips: options?.toolTip ?? '',
58
- data: typeof data === 'string' ? data : '',
59
- at_bot_show_channel_list: options?.atBotShowChannelList ?? false,
60
- enter: options?.autoEnter ?? false,
61
- reply: options?.reply ?? false,
62
- anchor: options?.anchor ?? 0,
63
- click_limit: options?.clickLimit
64
- };
65
- if (modal) {
66
- action.modal = {
67
- content: modal.content ?? '是否确认操作?',
68
- confirm_text: modal.confirmText ?? '是',
69
- cancel_text: modal.cancelText ?? '否'
70
- };
71
- }
72
- return {
73
- id: String(id),
74
- render_data: {
75
- label: value,
76
- visited_label: value,
77
- style: resolveButtonStyle(options?.style)
78
- },
79
- action,
80
- ...rowData
81
- };
82
- })
83
- })),
84
- nextId: id
85
- };
31
+ let id = startId;
32
+ return {
33
+ rows: rows.slice(0, MAX_BUTTON_ROWS).map((row) => ({ buttons: row.value.slice(0, MAX_BUTTONS_PER_ROW).map((button) => {
34
+ const value = button.value;
35
+ const options = button.options;
36
+ id++;
37
+ const typing = options?.type ?? "command";
38
+ const typeMap = {
39
+ command: 2,
40
+ link: 0,
41
+ call: 1
42
+ };
43
+ const rowData = options?.rawData ?? {};
44
+ const data = options?.data;
45
+ const modal = options?.modal ?? (typeof data === "object" && data ? {
46
+ content: data.click,
47
+ confirmText: data.confirm,
48
+ cancelText: data.cancel
49
+ } : void 0);
50
+ const action = {
51
+ type: typeMap[typing],
52
+ permission: {
53
+ type: typeof options.permission?.type === "undefined" ? 2 : options?.permission?.type,
54
+ specify_user_ids: options?.permission?.userIds,
55
+ specify_role_ids: options?.permission?.roleIds
56
+ },
57
+ unsupport_tips: options?.toolTip ?? "",
58
+ data: typeof data === "string" ? data : "",
59
+ at_bot_show_channel_list: options?.atBotShowChannelList ?? false,
60
+ enter: options?.autoEnter ?? false,
61
+ reply: options?.reply ?? false,
62
+ anchor: options?.anchor ?? 0,
63
+ click_limit: options?.clickLimit
64
+ };
65
+ if (modal) action.modal = {
66
+ content: modal.content ?? "是否确认操作?",
67
+ confirm_text: modal.confirmText ?? "是",
68
+ cancel_text: modal.cancelText ?? "否"
69
+ };
70
+ return {
71
+ id: String(id),
72
+ render_data: {
73
+ label: value,
74
+ visited_label: value,
75
+ style: resolveButtonStyle(options?.style)
76
+ },
77
+ action,
78
+ ...rowData
79
+ };
80
+ }) })),
81
+ nextId: id
82
+ };
86
83
  };
87
84
  const createArkCardData = (value) => ({
88
- template_id: 24,
89
- kv: [
90
- { key: '#DESC#', value: value.decs },
91
- { key: '#PROMPT#', value: value.prompt },
92
- { key: '#TITLE#', value: value.title },
93
- { key: '#METADESC#', value: value.metadecs },
94
- { key: '#IMG#', value: value.cover },
95
- { key: '#LINK#', value: value.link },
96
- { key: '#SUBTITLE#', value: value.subtitle }
97
- ]
85
+ template_id: 24,
86
+ kv: [
87
+ {
88
+ key: "#DESC#",
89
+ value: value.decs
90
+ },
91
+ {
92
+ key: "#PROMPT#",
93
+ value: value.prompt
94
+ },
95
+ {
96
+ key: "#TITLE#",
97
+ value: value.title
98
+ },
99
+ {
100
+ key: "#METADESC#",
101
+ value: value.metadecs
102
+ },
103
+ {
104
+ key: "#IMG#",
105
+ value: value.cover
106
+ },
107
+ {
108
+ key: "#LINK#",
109
+ value: value.link
110
+ },
111
+ {
112
+ key: "#SUBTITLE#",
113
+ value: value.subtitle
114
+ }
115
+ ]
98
116
  });
99
117
  const createArkBigCardData = (value) => ({
100
- template_id: 37,
101
- kv: [
102
- { key: '#PROMPT#', value: value.prompt },
103
- { key: '#METATITLE#', value: value.title },
104
- { key: '#METASUBTITLE#', value: value.subtitle },
105
- { key: '#METACOVER#', value: value.cover },
106
- { key: '#METAURL#', value: value.link }
107
- ]
118
+ template_id: 37,
119
+ kv: [
120
+ {
121
+ key: "#PROMPT#",
122
+ value: value.prompt
123
+ },
124
+ {
125
+ key: "#METATITLE#",
126
+ value: value.title
127
+ },
128
+ {
129
+ key: "#METASUBTITLE#",
130
+ value: value.subtitle
131
+ },
132
+ {
133
+ key: "#METACOVER#",
134
+ value: value.cover
135
+ },
136
+ {
137
+ key: "#METAURL#",
138
+ value: value.link
139
+ }
140
+ ]
108
141
  });
109
142
  const createArkListData = (value) => {
110
- const [tip, data] = value;
111
- return {
112
- template_id: 23,
113
- kv: [
114
- { key: '#DESC#', value: tip.value.desc },
115
- { key: '#PROMPT#', value: tip.value.prompt },
116
- {
117
- key: '#LIST#',
118
- obj: data.value.map(item => {
119
- const v = item.value;
120
- if (typeof v === 'string') {
121
- return { obj_kv: [{ key: 'desc', value: v }] };
122
- }
123
- return {
124
- obj_kv: [
125
- { key: 'desc', value: v.title },
126
- { key: 'link', value: v.link }
127
- ]
128
- };
129
- })
130
- }
131
- ]
132
- };
143
+ const [tip, data] = value;
144
+ return {
145
+ template_id: 23,
146
+ kv: [
147
+ {
148
+ key: "#DESC#",
149
+ value: tip.value.desc
150
+ },
151
+ {
152
+ key: "#PROMPT#",
153
+ value: tip.value.prompt
154
+ },
155
+ {
156
+ key: "#LIST#",
157
+ obj: data.value.map((item) => {
158
+ const v = item.value;
159
+ if (typeof v === "string") return { obj_kv: [{
160
+ key: "desc",
161
+ value: v
162
+ }] };
163
+ return { obj_kv: [{
164
+ key: "desc",
165
+ value: v.title
166
+ }, {
167
+ key: "link",
168
+ value: v.link
169
+ }] };
170
+ })
171
+ }
172
+ ]
173
+ };
133
174
  };
134
175
  const mdFormatters = {
135
- 'MD.title': value => `# ${value} `,
136
- 'MD.subtitle': value => `## ${value} `,
137
- 'MD.text': value => `${value} `,
138
- 'MD.bold': value => `**${value}** `,
139
- 'MD.divider': () => '\n***\n',
140
- 'MD.italic': value => `__${value}__ `,
141
- 'MD.italicStar': value => `*${value}* `,
142
- 'MD.strikethrough': value => `~~${value}~~ `,
143
- 'MD.blockquote': value => `\n> ${value} `,
144
- 'MD.newline': () => '\n',
145
- 'MD.link': value => {
146
- if (!value?.text && !value?.url) {
147
- return '';
148
- }
149
- if (!value?.text || !value?.url) {
150
- return `<${value?.url ?? value?.text}> `;
151
- }
152
- return `[🔗${value?.text}](${value?.url}) `;
153
- },
154
- 'MD.image': (value, options) => `\n![text #${options?.width || 208}px #${options?.height || 320}px](${value})\n`,
155
- 'MD.mention': (value, options) => {
156
- const { belong } = options || {};
157
- if (belong === 'channel') {
158
- return '';
159
- }
160
- if (belong === 'user') {
161
- return `<qqbot-at-user id="${value}" />`;
162
- }
163
- if (value === 'everyone') {
164
- return '<qqbot-at-everyone />';
165
- }
166
- return `<qqbot-at-user id="${value}" />`;
167
- },
168
- 'MD.content': value => `${value}`,
169
- 'MD.button': (title, options) => {
170
- const { data, autoEnter } = options || {};
171
- if (autoEnter) {
172
- return `<qqbot-cmd-enter text="${data}" show="${title}" />`;
173
- }
174
- return `<qqbot-cmd-input text="${data}" show="${title}" />`;
175
- }
176
+ "MD.title": (value) => `# ${value} `,
177
+ "MD.subtitle": (value) => `## ${value} `,
178
+ "MD.text": (value) => `${value} `,
179
+ "MD.bold": (value) => `**${value}** `,
180
+ "MD.divider": () => "\n***\n",
181
+ "MD.italic": (value) => `__${value}__ `,
182
+ "MD.italicStar": (value) => `*${value}* `,
183
+ "MD.strikethrough": (value) => `~~${value}~~ `,
184
+ "MD.blockquote": (value) => `\n> ${value} `,
185
+ "MD.newline": () => "\n",
186
+ "MD.link": (value) => {
187
+ if (!value?.text && !value?.url) return "";
188
+ if (!value?.text || !value?.url) return `<${value?.url ?? value?.text}> `;
189
+ return `[🔗${value?.text}](${value?.url}) `;
190
+ },
191
+ "MD.image": (value, options) => `\n![text #${options?.width || 208}px #${options?.height || 320}px](${value})\n`,
192
+ "MD.mention": (value, options) => {
193
+ const { belong } = options || {};
194
+ if (belong === "channel") return "";
195
+ if (belong === "user") return `<qqbot-at-user id="${value}" />`;
196
+ if (value === "everyone") return "<qqbot-at-everyone />";
197
+ return `<qqbot-at-user id="${value}" />`;
198
+ },
199
+ "MD.content": (value) => `${value}`,
200
+ "MD.button": (title, options) => {
201
+ const { data, autoEnter } = options || {};
202
+ if (autoEnter) return `<qqbot-cmd-enter text="${data}" show="${title}" />`;
203
+ return `<qqbot-cmd-input text="${data}" show="${title}" />`;
204
+ }
176
205
  };
177
206
  const createMarkdownText = (data) => {
178
- return data
179
- .map(mdItem => {
180
- if (mdFormatters[mdItem.type]) {
181
- return mdFormatters[mdItem.type](mdItem?.value, mdItem?.options);
182
- }
183
- if (mdItem.type === 'MD.list' && typeof mdItem.value !== 'string') {
184
- const listStr = mdItem.value.map(listItem => {
185
- return typeof listItem.value === 'object' ? `\n${listItem.value.index}. ${listItem.value.text}` : `\n- ${listItem.value}`;
186
- });
187
- return `${listStr.join('')}\n`;
188
- }
189
- if (mdItem.type === 'MD.code') {
190
- const language = mdItem?.options?.language || '';
191
- return `\n\`\`\`${language}\n${mdItem.value}\n\`\`\`\n`;
192
- }
193
- return String(mdItem['value'] || '');
194
- })
195
- .join('');
207
+ return data.map((mdItem) => {
208
+ if (mdFormatters[mdItem.type]) return mdFormatters[mdItem.type](mdItem?.value, mdItem?.options);
209
+ if (mdItem.type === "MD.list" && typeof mdItem.value !== "string") return `${mdItem.value.map((listItem) => {
210
+ return typeof listItem.value === "object" ? `\n${listItem.value.index}. ${listItem.value.text}` : `\n- ${listItem.value}`;
211
+ }).join("")}\n`;
212
+ if (mdItem.type === "MD.code") return `\n\`\`\`${mdItem?.options?.language || ""}\n${mdItem.value}\n\`\`\`\n`;
213
+ return String(mdItem["value"] || "");
214
+ }).join("");
196
215
  };
197
216
  const formatMention = (item, mode) => {
198
- if (mode === 'guild-direct') {
199
- return '';
200
- }
201
- const value = item.value;
202
- const isEmptyMention = value === 'everyone' || value === 'all' || value === '' || typeof value !== 'string';
203
- if (mode === 'guild-public') {
204
- if (isEmptyMention) {
205
- return '@everyone';
206
- }
207
- if (item.options?.belong === 'user') {
208
- return `<@!${value}>`;
209
- }
210
- if (item.options?.belong === 'channel') {
211
- return `<#${value}>`;
212
- }
213
- return '';
214
- }
215
- if (isEmptyMention) {
216
- return '';
217
- }
218
- if (item.options?.belong === 'user') {
219
- return `<@${value}>`;
220
- }
221
- return '';
217
+ if (mode === "guild-direct") return "";
218
+ const value = item.value;
219
+ const isEmptyMention = value === "everyone" || value === "all" || value === "" || typeof value !== "string";
220
+ if (mode === "guild-public") {
221
+ if (isEmptyMention) return "@everyone";
222
+ if (item.options?.belong === "user") return `<@!${value}>`;
223
+ if (item.options?.belong === "channel") return `<#${value}>`;
224
+ return "";
225
+ }
226
+ if (isEmptyMention) return "";
227
+ if (item.options?.belong === "user") return `<@${value}>`;
228
+ return "";
222
229
  };
230
+ /** 从消息数据中提取文本内容 */
223
231
  const extractContent = (val, mode) => {
224
- const nativeTypes = new Set([
225
- 'Mention',
226
- 'Text',
227
- 'Link',
228
- 'Image',
229
- 'ImageFile',
230
- 'ImageURL',
231
- 'Audio',
232
- 'Video',
233
- 'Attachment',
234
- 'Markdown',
235
- 'MarkdownOriginal',
236
- 'BT.group',
237
- 'ButtonTemplate',
238
- 'Ark.list',
239
- 'Ark.Card',
240
- 'Ark.BigCard'
241
- ]);
242
- const nativeText = val
243
- .filter(item => item.type === 'Mention' || item.type === 'Text' || item.type === 'Link')
244
- .map(item => {
245
- if (item.type === 'Link') {
246
- return `[${item.value}](${item?.options?.link})`;
247
- }
248
- if (item.type === 'Mention') {
249
- return formatMention(item, mode);
250
- }
251
- if (item.type === 'Text') {
252
- return item.value;
253
- }
254
- return '';
255
- })
256
- .join('');
257
- const config = getQQBotConfig();
258
- const hide = config.hideUnsupported;
259
- const fallbackText = val
260
- .filter(item => !nativeTypes.has(item.type))
261
- .map(item => dataEnumToText(item, hide))
262
- .filter(Boolean)
263
- .join('\n');
264
- return [nativeText, fallbackText].filter(Boolean).join('\n');
232
+ const nativeTypes = /* @__PURE__ */ new Set([
233
+ "Mention",
234
+ "Text",
235
+ "Link",
236
+ "Image",
237
+ "ImageFile",
238
+ "ImageURL",
239
+ "Audio",
240
+ "Video",
241
+ "Attachment",
242
+ "Markdown",
243
+ "MarkdownOriginal",
244
+ "BT.group",
245
+ "ButtonTemplate",
246
+ "Ark.list",
247
+ "Ark.Card",
248
+ "Ark.BigCard"
249
+ ]);
250
+ const nativeText = val.filter((item) => item.type === "Mention" || item.type === "Text" || item.type === "Link").map((item) => {
251
+ if (item.type === "Link") return `[${item.value}](${item?.options?.link})`;
252
+ if (item.type === "Mention") return formatMention(item, mode);
253
+ if (item.type === "Text") return item.value;
254
+ return "";
255
+ }).join("");
256
+ const hide = getQQBotConfig().hideUnsupported;
257
+ return [nativeText, val.filter((item) => !nativeTypes.has(item.type)).map((item) => dataEnumToText(item, hide)).filter(Boolean).join("\n")].filter(Boolean).join("\n");
265
258
  };
259
+ /**
260
+ * notice 事件中平台支持以 event_id 被动回复的 tag
261
+ * (群聊:GROUP_ADD_ROBOT / GROUP_MSG_RECEIVE;单聊:C2C_MSG_RECEIVE / FRIEND_ADD)
262
+ */
263
+ const NOTICE_EVENT_REPLY_TAGS = /* @__PURE__ */ new Set([
264
+ "GROUP_ADD_ROBOT",
265
+ "GROUP_MSG_RECEIVE",
266
+ "C2C_MSG_RECEIVE",
267
+ "FRIEND_ADD"
268
+ ]);
269
+ /** 构建 baseParams(event_id 或 msg_id) */
266
270
  const buildBaseParams = (tag, messageId, interactionTag) => {
267
- if (tag === interactionTag) {
268
- return { event_id: messageId };
269
- }
270
- return { msg_id: messageId };
271
+ if (tag && NOTICE_EVENT_REPLY_TAGS.has(tag) || tag === interactionTag) return { event_id: messageId };
272
+ return { msg_id: messageId };
271
273
  };
274
+ /** 构建 Markdown 和按钮参数 */
272
275
  const buildMdAndButtonsParams = (val) => {
273
- const items = val.filter(item => item.type === 'Markdown' || item.type === 'MarkdownOriginal' || item.type === 'BT.group' || item.type === 'ButtonTemplate');
274
- if (items.length === 0) {
275
- return null;
276
- }
277
- const params = {};
278
- let keyboardExtra;
279
- for (const item of items) {
280
- if (item.type === 'ButtonTemplate') {
281
- if (item?.value) {
282
- params['keyboard'] = { id: item.value };
283
- }
284
- }
285
- else if (item.type === 'BT.group' && typeof item?.value !== 'string') {
286
- const groupOptions = item?.options ?? {};
287
- if (groupOptions.smallButton || groupOptions.rawData) {
288
- keyboardExtra = {
289
- smallButton: keyboardExtra?.smallButton || groupOptions.smallButton,
290
- rawData: groupOptions.rawData
291
- };
292
- }
293
- if (params['keyboard']?.content?.rows) {
294
- const existingRows = params['keyboard'].content.rows;
295
- const currentId = params['keyboard'].content.nextId ?? existingRows.length;
296
- const remaining = MAX_BUTTON_ROWS - existingRows.length;
297
- if (remaining > 0) {
298
- const { rows: newRows, nextId } = createButtonsData(item.value.slice(0, remaining), currentId);
299
- existingRows.push(...newRows);
300
- params['keyboard'].content.nextId = nextId;
301
- }
302
- }
303
- else {
304
- const result = createButtonsData(item.value);
305
- params['keyboard'] = { content: result };
306
- }
307
- }
308
- else if (item.type === 'Markdown' && typeof item?.value !== 'string') {
309
- const content = createMarkdownText(item.value);
310
- if (content) {
311
- if (params['markdown']?.content) {
312
- params['markdown'].content += content;
313
- }
314
- else {
315
- params['markdown'] = { content };
316
- }
317
- }
318
- }
319
- else if (item.type === 'MarkdownOriginal' && typeof item?.value === 'string') {
320
- if (params['markdown']?.content) {
321
- params['markdown'].content += '\n' + item.value;
322
- }
323
- else {
324
- params['markdown'] = { content: item.value };
325
- }
326
- }
327
- }
328
- if (keyboardExtra && params['keyboard']?.content) {
329
- if (keyboardExtra.smallButton) {
330
- params['keyboard'].content.style = { font_size: 'small' };
331
- }
332
- if (keyboardExtra.rawData) {
333
- Object.assign(params['keyboard'].content, keyboardExtra.rawData);
334
- }
335
- }
336
- if (params['keyboard']?.content?.nextId !== undefined) {
337
- delete params['keyboard'].content.nextId;
338
- }
339
- return params;
276
+ const items = val.filter((item) => item.type === "Markdown" || item.type === "MarkdownOriginal" || item.type === "BT.group" || item.type === "ButtonTemplate");
277
+ if (items.length === 0) return null;
278
+ const params = {};
279
+ let keyboardExtra;
280
+ for (const item of items) if (item.type === "ButtonTemplate") {
281
+ if (item?.value) params["keyboard"] = { id: item.value };
282
+ } else if (item.type === "BT.group" && typeof item?.value !== "string") {
283
+ const groupOptions = item?.options ?? {};
284
+ if (groupOptions.smallButton || groupOptions.rawData) keyboardExtra = {
285
+ smallButton: keyboardExtra?.smallButton || groupOptions.smallButton,
286
+ rawData: groupOptions.rawData
287
+ };
288
+ if (params["keyboard"]?.content?.rows) {
289
+ const existingRows = params["keyboard"].content.rows;
290
+ const currentId = params["keyboard"].content.nextId ?? existingRows.length;
291
+ const remaining = MAX_BUTTON_ROWS - existingRows.length;
292
+ if (remaining > 0) {
293
+ const { rows: newRows, nextId } = createButtonsData(item.value.slice(0, remaining), currentId);
294
+ existingRows.push(...newRows);
295
+ params["keyboard"].content.nextId = nextId;
296
+ }
297
+ } else params["keyboard"] = { content: createButtonsData(item.value) };
298
+ } else if (item.type === "Markdown" && typeof item?.value !== "string") {
299
+ const content = createMarkdownText(item.value);
300
+ if (content) {
301
+ if (params["markdown"]?.content) params["markdown"].content += content;
302
+ else params["markdown"] = { content };
303
+ }
304
+ } else if (item.type === "MarkdownOriginal" && typeof item?.value === "string") {
305
+ if (params["markdown"]?.content) params["markdown"].content += "\n" + item.value;
306
+ else params["markdown"] = { content: item.value };
307
+ }
308
+ if (keyboardExtra && params["keyboard"]?.content) {
309
+ if (keyboardExtra.smallButton) params["keyboard"].content.style = { font_size: "small" };
310
+ if (keyboardExtra.rawData) Object.assign(params["keyboard"].content, keyboardExtra.rawData);
311
+ }
312
+ if (params["keyboard"]?.content?.nextId !== void 0) delete params["keyboard"].content.nextId;
313
+ return params;
340
314
  };
315
+ /** 构建 Ark 参数 */
341
316
  const buildArkParams = (val) => {
342
- const items = val.filter(item => item.type === 'Ark.BigCard' || item.type === 'Ark.Card' || item.type === 'Ark.list');
343
- if (items.length === 0) {
344
- return null;
345
- }
346
- const params = {};
347
- for (const item of items) {
348
- if (item.type === 'Ark.Card' && typeof item?.value !== 'string') {
349
- params['ark'] = createArkCardData(item.value);
350
- }
351
- else if (item.type === 'Ark.BigCard' && typeof item?.value !== 'string') {
352
- params['ark'] = createArkBigCardData(item.value);
353
- }
354
- else if (item.type === 'Ark.list' && typeof item?.value !== 'string') {
355
- params['ark'] = createArkListData(item.value);
356
- }
357
- }
358
- return params;
317
+ const items = val.filter((item) => item.type === "Ark.BigCard" || item.type === "Ark.Card" || item.type === "Ark.list");
318
+ if (items.length === 0) return null;
319
+ const params = {};
320
+ for (const item of items) if (item.type === "Ark.Card" && typeof item?.value !== "string") params["ark"] = createArkCardData(item.value);
321
+ else if (item.type === "Ark.BigCard" && typeof item?.value !== "string") params["ark"] = createArkBigCardData(item.value);
322
+ else if (item.type === "Ark.list" && typeof item?.value !== "string") params["ark"] = createArkListData(item.value);
323
+ return params;
359
324
  };
325
+ /**
326
+ * 富媒体类型 → QQ file_type 映射
327
+ * 1 图片 / 2 视频 / 3 语音 / 4 文件
328
+ */
360
329
  const MEDIA_FILE_TYPE = {
361
- Image: 1,
362
- ImageFile: 1,
363
- ImageURL: 1,
364
- Video: 2,
365
- Audio: 3,
366
- Attachment: 4
330
+ Image: 1,
331
+ ImageFile: 1,
332
+ ImageURL: 1,
333
+ Video: 2,
334
+ Audio: 3,
335
+ Attachment: 4
367
336
  };
337
+ /** 过滤富媒体数据(图片/视频/音频/文件) */
368
338
  const filterMedia = (val) => {
369
- return val.filter(item => MEDIA_FILE_TYPE[item.type] !== undefined);
339
+ return val.filter((item) => MEDIA_FILE_TYPE[item.type] !== void 0);
370
340
  };
341
+ /** 过滤图片数据(仅图片,频道路径使用) */
371
342
  const filterImages = (val) => {
372
- return val.filter(item => item.type === 'Image' || item.type === 'ImageFile' || item.type === 'ImageURL');
343
+ return val.filter((item) => item.type === "Image" || item.type === "ImageFile" || item.type === "ImageURL");
373
344
  };
345
+ /** 将媒体数据解析为 base64(支持 URL / file:// / base64:// / buffer:// / Buffer / 裸 base64) */
374
346
  const resolveFileData = async (item) => {
375
- if (item.type === 'ImageURL') {
376
- return await axios.get(item.value, { responseType: 'arraybuffer' }).then(res => Buffer.from(res.data, 'binary').toString('base64'));
377
- }
378
- if (item.type === 'ImageFile') {
379
- return readFileSync(item.value, 'base64');
380
- }
381
- const value = item.value;
382
- if (typeof value === 'string') {
383
- if (value.startsWith('https://') || value.startsWith('http://')) {
384
- return await axios.get(value, { responseType: 'arraybuffer' }).then(res => Buffer.from(res.data, 'binary').toString('base64'));
385
- }
386
- if (value.startsWith('buffer://')) {
387
- return value.replace('buffer://', '');
388
- }
389
- if (value.startsWith('file://')) {
390
- return readFileSync(value.replace('file://', ''), 'base64');
391
- }
392
- if (value.startsWith('base64://')) {
393
- return value.replace('base64://', '');
394
- }
395
- return value;
396
- }
397
- if (Buffer.isBuffer(value)) {
398
- return value.toString('base64');
399
- }
400
- return undefined;
347
+ if (item.type === "ImageURL") return await axios.get(item.value, { responseType: "arraybuffer" }).then((res) => Buffer.from(res.data, "binary").toString("base64"));
348
+ if (item.type === "ImageFile") return readFileSync(item.value, "base64");
349
+ const value = item.value;
350
+ if (typeof value === "string") {
351
+ if (value.startsWith("https://") || value.startsWith("http://")) return await axios.get(value, { responseType: "arraybuffer" }).then((res) => Buffer.from(res.data, "binary").toString("base64"));
352
+ if (value.startsWith("buffer://")) return value.replace("buffer://", "");
353
+ if (value.startsWith("file://")) return readFileSync(value.replace("file://", ""), "base64");
354
+ if (value.startsWith("base64://")) return value.replace("base64://", "");
355
+ return value;
356
+ }
357
+ if (Buffer.isBuffer(value)) return value.toString("base64");
401
358
  };
359
+ /**
360
+ * 通过富媒体上传获取 file_info(图片/视频/音频/文件)
361
+ * 按 MEDIA_FILE_TYPE 自动选择 file_type,超出 10MB 的文件自动走分片上传
362
+ */
402
363
  const resolveMediaUrl = async (media, uploadMedia) => {
403
- for (const item of media) {
404
- const fileData = await resolveFileData(item);
405
- if (fileData) {
406
- const fileInfo = await uploadMedia({ file_type: MEDIA_FILE_TYPE[item.type] ?? 1, file_data: fileData }).then(res => res?.file_info);
407
- if (fileInfo) {
408
- return fileInfo;
409
- }
410
- }
411
- }
412
- return undefined;
364
+ for (const item of media) {
365
+ const fileData = await resolveFileData(item);
366
+ if (fileData) {
367
+ const fileInfo = await uploadMedia({
368
+ file_type: MEDIA_FILE_TYPE[item.type] ?? 1,
369
+ file_data: fileData
370
+ }).then((res) => res?.file_info);
371
+ if (fileInfo) return fileInfo;
372
+ }
373
+ }
413
374
  };
414
- const stripMediaPlaceholders = (text) => text
415
- .replace(/\[附件[^\]]*\]/g, '')
416
- .replace(/\[音频\]/g, '')
417
- .replace(/\[视频\]/g, '')
418
- .replace(/\n{2,}/g, '\n')
419
- .trim();
375
+ /** 移除富媒体占位符(dataEnumToText 降级产生的 [视频]/[音频]/[附件]) */
376
+ const stripMediaPlaceholders = (text) => text.replace(/\[附件[^\]]*\]/g, "").replace(/\[音频\]/g, "").replace(/\[视频\]/g, "").replace(/\n{2,}/g, "\n").trim();
377
+ /** 当 markdownToText 选项开启时,将 Markdown 和按钮降级为纯文本并追加到 content */
420
378
  const flattenMdToText = (content, val) => {
421
- const mdItems = val.filter(item => item.type === 'Markdown');
422
- const btnItems = val.filter(item => item.type === 'BT.group');
423
- const parts = [content];
424
- for (const item of mdItems) {
425
- if (item.type === 'Markdown' && typeof item.value !== 'string') {
426
- parts.push(markdownToText(item.value));
427
- }
428
- }
429
- for (const item of btnItems) {
430
- if (item.type === 'BT.group' && typeof item.value !== 'string') {
431
- parts.push(buttonsToText(item.value));
432
- }
433
- }
434
- return parts
435
- .filter(Boolean)
436
- .join('\n')
437
- .replace(/^[^\S\n\r]+|[^\S\n\r]+$/g, '');
379
+ const mdItems = val.filter((item) => item.type === "Markdown");
380
+ const btnItems = val.filter((item) => item.type === "BT.group");
381
+ const parts = [content];
382
+ for (const item of mdItems) if (item.type === "Markdown" && typeof item.value !== "string") parts.push(markdownToText(item.value));
383
+ for (const item of btnItems) if (item.type === "BT.group" && typeof item.value !== "string") parts.push(buttonsToText(item.value));
384
+ return parts.filter(Boolean).join("\n").replace(/^[^\S\n\r]+|[^\S\n\r]+$/g, "");
438
385
  };
386
+ /** Open API 通用发送逻辑(群组 / C2C) */
439
387
  const sendOpenApiMessage = async (content, val, baseParams, uploadMedia, sendMessage, label, options) => {
440
- const config = getQQBotConfig();
441
- const mdToText = config.markdownToText === true;
442
- const media = filterMedia(val);
443
- if (media.length > 0) {
444
- const fileInfo = await resolveMediaUrl(media, uploadMedia);
445
- if (!fileInfo) {
446
- return [createResult(ResultCode.Fail, '媒体上传失败', null)];
447
- }
448
- const mediaContent = stripMediaPlaceholders(flattenMdToText(content, val));
449
- const res = await sendMessage({
450
- content: mediaContent,
451
- media: { file_info: fileInfo },
452
- msg_type: 7,
453
- ...baseParams
454
- });
455
- return [createResult(ResultCode.Ok, label, { id: res.id })];
456
- }
457
- if (config.hideUnsupported === true && !content && !buildMdAndButtonsParams(val) && !buildArkParams(val)) {
458
- logger.info('[qq-bot] hideUnsupported: 消息内容转换后为空,跳过发送');
459
- return [];
460
- }
461
- if (mdToText) {
462
- const textContent = flattenMdToText(content, val);
463
- if (textContent) {
464
- const res = await sendMessage({ content: textContent, msg_type: 0, ...baseParams });
465
- return [createResult(ResultCode.Ok, label, { id: res.id })];
466
- }
467
- return [];
468
- }
469
- const mdParams = buildMdAndButtonsParams(val);
470
- if (mdParams) {
471
- if (mdParams.markdown?.content && content) {
472
- mdParams.markdown.content = content + '\n' + mdParams.markdown.content;
473
- }
474
- const res = await sendMessage({ content, msg_type: 2, ...mdParams, ...baseParams, force_verify_image_resource: options?.forceVerifyImageResource });
475
- return [createResult(ResultCode.Ok, label, { id: res.id })];
476
- }
477
- const arkParams = buildArkParams(val);
478
- if (arkParams) {
479
- const res = await sendMessage({ content, msg_type: 3, ...arkParams, ...baseParams });
480
- return [createResult(ResultCode.Ok, label, { id: res.id })];
481
- }
482
- if (content) {
483
- const res = await sendMessage({ content, msg_type: 0, ...baseParams });
484
- return [createResult(ResultCode.Ok, label, { id: res.id })];
485
- }
486
- return [];
388
+ const config = getQQBotConfig();
389
+ const mdToText = config.markdownToText === true;
390
+ const media = filterMedia(val);
391
+ if (media.length > 0) {
392
+ const fileInfo = await resolveMediaUrl(media, uploadMedia);
393
+ if (!fileInfo) return [createResult(ResultCode.Fail, "媒体上传失败", null)];
394
+ const res = await sendMessage({
395
+ content: stripMediaPlaceholders(flattenMdToText(content, val)),
396
+ media: { file_info: fileInfo },
397
+ msg_type: 7,
398
+ ...baseParams
399
+ });
400
+ return [createResult(ResultCode.Ok, label, { id: res.id })];
401
+ }
402
+ if (config.hideUnsupported === true && !content && !buildMdAndButtonsParams(val) && !buildArkParams(val)) {
403
+ logger.info("[qq-bot] hideUnsupported: 消息内容转换后为空,跳过发送");
404
+ return [];
405
+ }
406
+ if (mdToText) {
407
+ const textContent = flattenMdToText(content, val);
408
+ if (textContent) {
409
+ const res = await sendMessage({
410
+ content: textContent,
411
+ msg_type: 0,
412
+ ...baseParams
413
+ });
414
+ return [createResult(ResultCode.Ok, label, { id: res.id })];
415
+ }
416
+ return [];
417
+ }
418
+ const mdParams = buildMdAndButtonsParams(val);
419
+ if (mdParams) {
420
+ if (mdParams.markdown?.content && content) mdParams.markdown.content = content + "\n" + mdParams.markdown.content;
421
+ const res = await sendMessage({
422
+ content,
423
+ msg_type: 2,
424
+ ...mdParams,
425
+ ...baseParams,
426
+ force_verify_image_resource: options?.forceVerifyImageResource
427
+ });
428
+ return [createResult(ResultCode.Ok, label, { id: res.id })];
429
+ }
430
+ const arkParams = buildArkParams(val);
431
+ if (arkParams) {
432
+ const res = await sendMessage({
433
+ content,
434
+ msg_type: 3,
435
+ ...arkParams,
436
+ ...baseParams
437
+ });
438
+ return [createResult(ResultCode.Ok, label, { id: res.id })];
439
+ }
440
+ if (content) {
441
+ const res = await sendMessage({
442
+ content,
443
+ msg_type: 0,
444
+ ...baseParams
445
+ });
446
+ return [createResult(ResultCode.Ok, label, { id: res.id })];
447
+ }
448
+ return [];
487
449
  };
450
+ /** 将图片数据解析为 Buffer */
488
451
  const resolveImageBuffer = async (images) => {
489
- for (const item of images) {
490
- if (item.type === 'ImageURL') {
491
- return await axios.get(item.value, { responseType: 'arraybuffer' }).then(res => res?.data);
492
- }
493
- if (item.type === 'ImageFile') {
494
- return readFileSync(item.value);
495
- }
496
- if (typeof item.value === 'string') {
497
- if (item.value.startsWith('https://') || item.value.startsWith('http://')) {
498
- return await axios.get(item.value, { responseType: 'arraybuffer' }).then(res => res?.data);
499
- }
500
- if (item.value.startsWith('base64://')) {
501
- return Buffer.from(item.value.replace('base64://', ''), 'base64');
502
- }
503
- if (item.value.startsWith('file://')) {
504
- return readFileSync(item.value.replace('file://', ''));
505
- }
506
- return Buffer.from(item.value, 'base64');
507
- }
508
- if (Buffer.isBuffer(item.value)) {
509
- return item.value;
510
- }
511
- }
512
- return null;
452
+ for (const item of images) {
453
+ if (item.type === "ImageURL") return await axios.get(item.value, { responseType: "arraybuffer" }).then((res) => res?.data);
454
+ if (item.type === "ImageFile") return readFileSync(item.value);
455
+ if (typeof item.value === "string") {
456
+ if (item.value.startsWith("https://") || item.value.startsWith("http://")) return await axios.get(item.value, { responseType: "arraybuffer" }).then((res) => res?.data);
457
+ if (item.value.startsWith("base64://")) return Buffer.from(item.value.replace("base64://", ""), "base64");
458
+ if (item.value.startsWith("file://")) return readFileSync(item.value.replace("file://", ""));
459
+ return Buffer.from(item.value, "base64");
460
+ }
461
+ if (Buffer.isBuffer(item.value)) return item.value;
462
+ }
463
+ return null;
513
464
  };
465
+ /** Guild API 通用发送逻辑(频道公聊 / 频道私聊) */
514
466
  const sendGuildMessage = async (content, val, baseParams, sendMessage, label) => {
515
- const config = getQQBotConfig();
516
- const mdToText = config.markdownToText === true;
517
- const images = filterImages(val);
518
- if (images.length > 0) {
519
- const imageBuffer = await resolveImageBuffer(images);
520
- const imgContent = flattenMdToText(content, val);
521
- const res = await sendMessage({ content: imgContent, ...baseParams }, imageBuffer);
522
- return [createResult(ResultCode.Ok, label, { id: res?.id })];
523
- }
524
- if (config.hideUnsupported && !content && !buildMdAndButtonsParams(val) && !buildArkParams(val)) {
525
- logger.info('[qq-bot] hideUnsupported: 消息内容转换后为空,跳过发送');
526
- return [];
527
- }
528
- if (mdToText) {
529
- const textContent = flattenMdToText(content, val);
530
- if (textContent) {
531
- const res = await sendMessage({ content: textContent, ...baseParams });
532
- return [createResult(ResultCode.Ok, label, { id: res?.id })];
533
- }
534
- return [];
535
- }
536
- const mdParams = buildMdAndButtonsParams(val);
537
- if (mdParams) {
538
- if (mdParams.markdown?.content && content) {
539
- mdParams.markdown.content = content + '\n' + mdParams.markdown.content;
540
- }
541
- const res = await sendMessage({ content: '', ...mdParams, ...baseParams });
542
- return [createResult(ResultCode.Ok, label, { id: res.id })];
543
- }
544
- const arkParams = buildArkParams(val);
545
- if (arkParams) {
546
- const res = await sendMessage({ content, ...arkParams, ...baseParams });
547
- return [createResult(ResultCode.Ok, label, { id: res.id })];
548
- }
549
- if (content) {
550
- const res = await sendMessage({ content, ...baseParams });
551
- return [createResult(ResultCode.Ok, label, { id: res?.id })];
552
- }
553
- return [];
467
+ const config = getQQBotConfig();
468
+ const mdToText = config.markdownToText === true;
469
+ const images = filterImages(val);
470
+ if (images.length > 0) {
471
+ const imageBuffer = await resolveImageBuffer(images);
472
+ const res = await sendMessage({
473
+ content: flattenMdToText(content, val),
474
+ ...baseParams
475
+ }, imageBuffer);
476
+ return [createResult(ResultCode.Ok, label, { id: res?.id })];
477
+ }
478
+ if (config.hideUnsupported && !content && !buildMdAndButtonsParams(val) && !buildArkParams(val)) {
479
+ logger.info("[qq-bot] hideUnsupported: 消息内容转换后为空,跳过发送");
480
+ return [];
481
+ }
482
+ if (mdToText) {
483
+ const textContent = flattenMdToText(content, val);
484
+ if (textContent) {
485
+ const res = await sendMessage({
486
+ content: textContent,
487
+ ...baseParams
488
+ });
489
+ return [createResult(ResultCode.Ok, label, { id: res?.id })];
490
+ }
491
+ return [];
492
+ }
493
+ const mdParams = buildMdAndButtonsParams(val);
494
+ if (mdParams) {
495
+ if (mdParams.markdown?.content && content) mdParams.markdown.content = content + "\n" + mdParams.markdown.content;
496
+ const res = await sendMessage({
497
+ content: "",
498
+ ...mdParams,
499
+ ...baseParams
500
+ });
501
+ return [createResult(ResultCode.Ok, label, { id: res.id })];
502
+ }
503
+ const arkParams = buildArkParams(val);
504
+ if (arkParams) {
505
+ const res = await sendMessage({
506
+ content,
507
+ ...arkParams,
508
+ ...baseParams
509
+ });
510
+ return [createResult(ResultCode.Ok, label, { id: res.id })];
511
+ }
512
+ if (content) {
513
+ const res = await sendMessage({
514
+ content,
515
+ ...baseParams
516
+ });
517
+ return [createResult(ResultCode.Ok, label, { id: res?.id })];
518
+ }
519
+ return [];
554
520
  };
521
+ /**
522
+ * 群组消息
523
+ */
555
524
  const GROUP_AT_MESSAGE_CREATE = async (client, event, val, options) => {
556
- const baseParams = buildBaseParams(event._tag, event.MessageId, 'INTERACTION_CREATE_GROUP');
557
- const content = extractContent(val, 'group');
558
- try {
559
- return await sendOpenApiMessage(content, val, baseParams, data => client.postRichMediaByGroup(event.ChannelId, data), data => client.groupOpenMessages(event.ChannelId, data), 'client.groupOpenMessages', options);
560
- }
561
- catch (err) {
562
- return [createResult(ResultCode.Fail, err?.response?.data ?? err?.message ?? err, null)];
563
- }
525
+ const baseParams = buildBaseParams(event._tag, event.MessageId, "INTERACTION_CREATE_GROUP");
526
+ const content = extractContent(val, "group");
527
+ try {
528
+ return await sendOpenApiMessage(content, val, baseParams, (data) => client.postRichMediaByGroup(event.ChannelId, data), (data) => client.groupOpenMessages(event.ChannelId, data), "client.groupOpenMessages", options);
529
+ } catch (err) {
530
+ return [createResult(ResultCode.Fail, err?.response?.data ?? err?.message ?? err, null)];
531
+ }
564
532
  };
533
+ /**
534
+ * 私聊消息
535
+ */
565
536
  const C2C_MESSAGE_CREATE = async (client, event, val, options) => {
566
- const baseParams = buildBaseParams(event._tag, event.MessageId, 'INTERACTION_CREATE_C2C');
567
- const content = extractContent(val, 'group');
568
- try {
569
- return await sendOpenApiMessage(content, val, baseParams, data => client.postRichMediaByUser(event.UserId, data), data => client.usersOpenMessages(event.UserId, data), 'client.usersOpenMessages', options);
570
- }
571
- catch (err) {
572
- return [createResult(ResultCode.Fail, err?.response?.data ?? err?.message ?? err, null)];
573
- }
537
+ const baseParams = buildBaseParams(event._tag, event.MessageId, "INTERACTION_CREATE_C2C");
538
+ const content = extractContent(val, "group");
539
+ try {
540
+ return await sendOpenApiMessage(content, val, baseParams, (data) => client.postRichMediaByUser(event.UserId, data), (data) => client.usersOpenMessages(event.UserId, data), "client.usersOpenMessages", options);
541
+ } catch (err) {
542
+ return [createResult(ResultCode.Fail, err?.response?.data ?? err?.message ?? err, null)];
543
+ }
574
544
  };
545
+ /**
546
+ * 频道私聊
547
+ */
575
548
  const DIRECT_MESSAGE_CREATE = async (client, event, val) => {
576
- const baseParams = buildBaseParams(event._tag, event.MessageId, 'INTERACTION_CREATE_GUILD');
577
- const content = extractContent(val, 'guild-direct');
578
- try {
579
- return await sendGuildMessage(content, val, baseParams, (data, buf) => client.dmsMessages(event.UserId, data, buf), 'client.dmsMessage');
580
- }
581
- catch (err) {
582
- return [createResult(ResultCode.Fail, err?.response?.data ?? err?.message ?? err, null)];
583
- }
549
+ const baseParams = buildBaseParams(event._tag, event.MessageId, "INTERACTION_CREATE_GUILD");
550
+ const content = extractContent(val, "guild-direct");
551
+ try {
552
+ return await sendGuildMessage(content, val, baseParams, (data, buf) => client.dmsMessages(event.UserId, data, buf), "client.dmsMessage");
553
+ } catch (err) {
554
+ return [createResult(ResultCode.Fail, err?.response?.data ?? err?.message ?? err, null)];
555
+ }
584
556
  };
557
+ /**
558
+ * 频道公聊
559
+ */
585
560
  const MESSAGE_CREATE = async (client, event, val) => {
586
- const baseParams = buildBaseParams(event._tag, event.MessageId, 'INTERACTION_CREATE_GUILD');
587
- const content = extractContent(val, 'guild-public');
588
- try {
589
- return await sendGuildMessage(content, val, baseParams, (data, buf) => client.channelsMessages(event.ChannelId, data, buf), 'client.channelsMessagesPost');
590
- }
591
- catch (err) {
592
- return [createResult(ResultCode.Fail, err?.response?.data ?? err?.message ?? err, null)];
593
- }
561
+ const baseParams = buildBaseParams(event._tag, event.MessageId, "INTERACTION_CREATE_GUILD");
562
+ const content = extractContent(val, "guild-public");
563
+ try {
564
+ return await sendGuildMessage(content, val, baseParams, (data, buf) => client.channelsMessages(event.ChannelId, data, buf), "client.channelsMessagesPost");
565
+ } catch (err) {
566
+ return [createResult(ResultCode.Fail, err?.response?.data ?? err?.message ?? err, null)];
567
+ }
594
568
  };
569
+ /**
570
+ * 频道公聊 @
571
+ */
595
572
  const AT_MESSAGE_CREATE = (client, event, val) => {
596
- return MESSAGE_CREATE(client, event, val);
573
+ return MESSAGE_CREATE(client, event, val);
597
574
  };
598
575
 
599
- export { AT_MESSAGE_CREATE, C2C_MESSAGE_CREATE, DIRECT_MESSAGE_CREATE, GROUP_AT_MESSAGE_CREATE, MESSAGE_CREATE };
576
+ //#endregion
577
+ export { AT_MESSAGE_CREATE, C2C_MESSAGE_CREATE, DIRECT_MESSAGE_CREATE, GROUP_AT_MESSAGE_CREATE, MESSAGE_CREATE };