koishi-plugin-dew-bot 1.0.249 → 1.0.251

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/lib/index.js CHANGED
@@ -749,7 +749,7 @@ function renderQQPageMarkdown(data, showGreeting) {
749
749
  const summaryLine = data.line.find((item) => item.type === 1 /* line */ && pagePattern.test(item.content));
750
750
  const summary = summaryLine && pagePattern.exec(summaryLine.content);
751
751
  const listCount = data.line.filter((item) => item.type === 1 /* line */ && listPattern.test(item.content)).length;
752
- const count = summary?.[1] ?? (nav?.total === 1 ? String(listCount) : void 0);
752
+ const count = summary?.[1] ?? (nav?.total === 1 && listCount > 0 ? String(listCount) : void 0);
753
753
  const countUnit = summary?.[2] ?? "项";
754
754
  const isLeaderboardDirectory = !!nav?.entries?.length && /^(?:🏆)?排行榜$/u.test(compactDisplayText(title?.content ?? ""));
755
755
  const sections = [];
@@ -820,8 +820,8 @@ function renderQQPageMarkdown(data, showGreeting) {
820
820
  flush();
821
821
  if (nav && !hasPageSummary && (nav.total > 1 || nav.previousCommand || nav.nextCommand))
822
822
  pageFooter = `**第${nav.current}/${nav.total}页**`;
823
- const previousLink = nav?.previousCommand ? `[上一页](${inlineCommandUrl(nav.previousCommand)})` : void 0;
824
- const nextLink = nav?.nextCommand ? `[下一页](${inlineCommandUrl(nav.nextCommand)})` : void 0;
823
+ const previousLink = nav?.previousCommand ? `[${nav.previousCommand === "上一个" ? "上一个" : "上一页"}](${inlineCommandUrl(nav.previousCommand)})` : void 0;
824
+ const nextLink = nav?.nextCommand ? `[${nav.nextCommand === "下一个" ? "下一个" : "下一页"}](${inlineCommandUrl(nav.nextCommand)})` : void 0;
825
825
  const helpLink = hasHelp ? `[指令](${inlineCommandUrl("指令")})` : void 0;
826
826
  const footer = pageFooter ? [pageFooter, previousLink, nextLink, helpLink].filter(Boolean).join("·") : helpLink ? `更多操作:${helpLink}` : void 0;
827
827
  if (footer) {
@@ -839,8 +839,12 @@ function canSendQQPage(session, data) {
839
839
  }
840
840
  __name(canSendQQPage, "canSendQQPage");
841
841
  async function sendQQPage(session, data) {
842
- const internal = session.bot.internal;
843
842
  const markdown = renderQQPageMarkdown(data, session.event?.channel?.type === 0);
843
+ await sendQQMarkdown(session, markdown);
844
+ }
845
+ __name(sendQQPage, "sendQQPage");
846
+ async function sendQQMarkdown(session, markdown) {
847
+ const internal = session.bot.internal;
844
848
  const request = {
845
849
  // With msg_type=2, QQ requires the ordinary content field to be empty.
846
850
  content: "",
@@ -858,7 +862,110 @@ async function sendQQPage(session, data) {
858
862
  const pendingAudit = response?.code === 304023 && !!response.data?.message_audit?.audit_id;
859
863
  if (!response?.id && !response?.audit_id && !pendingAudit) throw new Error("QQ 未确认消息已接收");
860
864
  }
861
- __name(sendQQPage, "sendQQPage");
865
+ __name(sendQQMarkdown, "sendQQMarkdown");
866
+
867
+ // src/plugin/serverHandel/qqTransactionMessage.ts
868
+ function renderQQTransactionMarkdown(data, showGreeting) {
869
+ const sections = [];
870
+ const bodyLines = [];
871
+ const actions = [];
872
+ const flushBody = /* @__PURE__ */ __name(() => {
873
+ if (bodyLines.length) sections.push(bodyLines.splice(0).join(" \n"));
874
+ }, "flushBody");
875
+ const flushActions = /* @__PURE__ */ __name(() => {
876
+ if (actions.length) sections.push(actions.splice(0).join(" · "));
877
+ }, "flushActions");
878
+ const flush = /* @__PURE__ */ __name(() => {
879
+ flushBody();
880
+ flushActions();
881
+ }, "flush");
882
+ if (showGreeting) sections.push(escapeMarkdown("Ciallo~(∠・ω< )"));
883
+ for (const item of data.line) {
884
+ if (item.type === 0 /* title */) {
885
+ flush();
886
+ sections.push(`**${escapeMarkdown(item.content)}**`);
887
+ continue;
888
+ }
889
+ if (item.type === 2 /* error */) {
890
+ flush();
891
+ sections.push(`❌ 出错了!错误原因:${escapeMarkdown(item.content)},请反馈至联系开发者`);
892
+ continue;
893
+ }
894
+ if (item.type !== 1 /* line */) continue;
895
+ const action = data.transaction && (item.content === "[是]确认交易" ? { command: "是", label: "确认交易" } : item.content === "[否]取消交易" ? { command: "否", label: "取消交易" } : void 0);
896
+ if (action) {
897
+ flushBody();
898
+ actions.push(`[${action.label}](${inlineCommandUrl(action.command)})`);
899
+ continue;
900
+ }
901
+ flushActions();
902
+ if (!item.content.trim()) {
903
+ flushBody();
904
+ continue;
905
+ }
906
+ const section = /^┄━═(.+)═━┄$/.exec(item.content);
907
+ if (section || item.content === "【还缺】") {
908
+ flushBody();
909
+ sections.push(`**${escapeMarkdown(section?.[1] ?? "还缺")}**`);
910
+ } else {
911
+ bodyLines.push(escapeMarkdown(item.content));
912
+ }
913
+ }
914
+ flush();
915
+ return sections.join("\n\n") || " ";
916
+ }
917
+ __name(renderQQTransactionMarkdown, "renderQQTransactionMarkdown");
918
+ async function sendQQTransaction(session, data) {
919
+ await sendQQMarkdown(session, renderQQTransactionMarkdown(data, session.event?.channel?.type === 0));
920
+ }
921
+ __name(sendQQTransaction, "sendQQTransaction");
922
+
923
+ // src/plugin/serverHandel/qqCommandMessage.ts
924
+ function renderCommandLine(content, commandHelp) {
925
+ if (!commandHelp || !/^\s*\[[^\[\]\r\n]+\]/.test(content)) return escapeMarkdown(content);
926
+ const parts = [];
927
+ let offset = 0;
928
+ for (const match of content.matchAll(/\[([^\[\]\r\n]+)\]/g)) {
929
+ parts.push(escapeMarkdown(content.slice(offset, match.index)));
930
+ const command = match[1].split(/[++]/, 1)[0].trim();
931
+ parts.push(command ? `[${escapeMarkdown(match[1])}](${inlineCommandUrl(command)})` : escapeMarkdown(match[0]));
932
+ offset = match.index + match[0].length;
933
+ }
934
+ parts.push(escapeMarkdown(content.slice(offset)));
935
+ return parts.join("");
936
+ }
937
+ __name(renderCommandLine, "renderCommandLine");
938
+ function renderQQCommandMarkdown(data, showGreeting) {
939
+ const sections = [];
940
+ const bodyLines = [];
941
+ const flushBody = /* @__PURE__ */ __name(() => {
942
+ if (bodyLines.length) sections.push(bodyLines.splice(0).join(" \n"));
943
+ }, "flushBody");
944
+ if (showGreeting) sections.push(escapeMarkdown("Ciallo~(∠・ω< )"));
945
+ for (const item of data.line) {
946
+ switch (item.type) {
947
+ case 0 /* title */:
948
+ flushBody();
949
+ sections.push(`**${escapeMarkdown(item.content)}**`);
950
+ break;
951
+ case 1 /* line */:
952
+ if (!item.content.trim()) flushBody();
953
+ else bodyLines.push(renderCommandLine(item.content, !!data.commandHelp));
954
+ break;
955
+ case 2 /* error */:
956
+ flushBody();
957
+ sections.push(`❌ 出错了!错误原因:${escapeMarkdown(item.content)},请反馈至联系开发者`);
958
+ break;
959
+ }
960
+ }
961
+ flushBody();
962
+ return sections.join("\n\n") || " ";
963
+ }
964
+ __name(renderQQCommandMarkdown, "renderQQCommandMarkdown");
965
+ async function sendQQCommand(session, data) {
966
+ await sendQQMarkdown(session, renderQQCommandMarkdown(data, session.event?.channel?.type === 0));
967
+ }
968
+ __name(sendQQCommand, "sendQQCommand");
862
969
 
863
970
  // src/plugin/serverHandel/text.ts
864
971
  var handelr_text = class extends handel_base {
@@ -868,10 +975,12 @@ var handelr_text = class extends handel_base {
868
975
  async start(data) {
869
976
  const content = new AnalysisMsg().parse(data);
870
977
  const session = sessions_default.get(sessionKey(data.botId, data.userId, data.channelId));
871
- if (data.pageNav && canSendQQPage(session, data)) {
978
+ if ((data.commandHelp || data.transaction || data.pageNav) && canSendQQPage(session, data)) {
872
979
  const sendStartedAt = this.timing ? performance.now() : 0;
873
980
  try {
874
- await sendQQPage(session, data);
981
+ if (data.commandHelp) await sendQQCommand(session, data);
982
+ else if (data.transaction) await sendQQTransaction(session, data);
983
+ else await sendQQPage(session, data);
875
984
  if (this.timing) {
876
985
  this.timing.delivery = "qq-markdown";
877
986
  this.timing.sendMs = performance.now() - sendStartedAt;
@@ -880,7 +989,7 @@ var handelr_text = class extends handel_base {
880
989
  } catch (error) {
881
990
  this.ctx.logger.warn("QQ Markdown 发送失败,改用普通文字", error instanceof Error ? error.message : error);
882
991
  }
883
- const commands = pageCommandLines(data.pageNav);
992
+ const commands = !data.commandHelp && !data.transaction && data.pageNav ? pageCommandLines(data.pageNav) : [];
884
993
  await this.send(data, commands.length ? `${content.trimEnd()}
885
994
  ${commands.join("\n")}` : content);
886
995
  return;
@@ -953,7 +1062,7 @@ var import_tsrpc = require("tsrpc");
953
1062
 
954
1063
  // src/shared/bot/serviceProto.ts
955
1064
  var serviceProto = {
956
- "version": 11,
1065
+ "version": 13,
957
1066
  "services": [
958
1067
  {
959
1068
  "id": 0,
@@ -1088,6 +1197,22 @@ var serviceProto = {
1088
1197
  },
1089
1198
  "optional": true
1090
1199
  },
1200
+ {
1201
+ "id": 8,
1202
+ "name": "transaction",
1203
+ "type": {
1204
+ "type": "Boolean"
1205
+ },
1206
+ "optional": true
1207
+ },
1208
+ {
1209
+ "id": 9,
1210
+ "name": "commandHelp",
1211
+ "type": {
1212
+ "type": "Boolean"
1213
+ },
1214
+ "optional": true
1215
+ },
1091
1216
  {
1092
1217
  "id": 1,
1093
1218
  "name": "line",
@@ -0,0 +1,5 @@
1
+ import type { Session } from 'koishi';
2
+ import type { MsgMessage } from '../../shared/bot/MsgMessage';
3
+ /** Keep help text intact while making its explicitly boxed commands clickable. */
4
+ export declare function renderQQCommandMarkdown(data: MsgMessage, showGreeting: boolean): string;
5
+ export declare function sendQQCommand(session: Session, data: MsgMessage): Promise<void>;
@@ -1,9 +1,14 @@
1
1
  import type { Session } from 'koishi';
2
2
  import { type PageNavData } from '../../shared/face';
3
3
  import type { MsgMessage } from '../../shared/bot/MsgMessage';
4
+ /** Escape server-provided lines before embedding them in native QQ Markdown. */
5
+ export declare function escapeMarkdown(value: string): string;
6
+ export declare function inlineCommandUrl(command: string): string;
4
7
  export declare function pageCommandLines(nav: PageNavData): string[];
5
8
  export declare function renderQQPageMarkdown(data: MsgMessage, showGreeting: boolean): string;
6
9
  /** Returns false if this is not the matching QQ session or the adapter has no native API. */
7
10
  export declare function canSendQQPage(session: Session | undefined, data: MsgMessage): session is Session;
8
11
  /** Send a native QQ Markdown page with inline command links. */
9
12
  export declare function sendQQPage(session: Session, data: MsgMessage): Promise<void>;
13
+ /** Reuse the adapter's native reply API for structured Markdown messages. */
14
+ export declare function sendQQMarkdown(session: Session, markdown: string): Promise<void>;
@@ -0,0 +1,5 @@
1
+ import type { Session } from 'koishi';
2
+ import type { MsgMessage } from '../../shared/bot/MsgMessage';
3
+ /** Render only explicitly marked transactions; line content never enables this channel. */
4
+ export declare function renderQQTransactionMarkdown(data: MsgMessage, showGreeting: boolean): string;
5
+ export declare function sendQQTransaction(session: Session, data: MsgMessage): Promise<void>;
@@ -130,6 +130,10 @@ export interface IMessage {
130
130
  equipmentCard?: EquipmentCardData;
131
131
  leaderboard?: LeaderboardImageData;
132
132
  pageNav?: PageNavData;
133
+ /** 通用交易确认、结果与失败消息;客户端可使用交易 Markdown 展示。 */
134
+ transaction?: boolean;
135
+ /** 指令系统与指令提示;客户端可用 Markdown 展示可点击的方框指令。 */
136
+ commandHelp?: boolean;
133
137
  /** 消息项列表 **/
134
138
  line: IMessageItem[];
135
139
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "koishi-plugin-dew-bot",
3
3
  "description": "基于《无限恐怖》小说改编的 RPG 机器人。踏入主神空间,与伙伴迎接轮回试炼,书写属于你的无限冒险。",
4
- "version": "1.0.249",
4
+ "version": "1.0.251",
5
5
  "main": "lib/index.js",
6
6
  "typings": "lib/index.d.ts",
7
7
  "files": [
@@ -0,0 +1,54 @@
1
+ import type { Session } from 'koishi'
2
+ import { MessageType } from '../../shared/face'
3
+ import type { MsgMessage } from '../../shared/bot/MsgMessage'
4
+ import { escapeMarkdown, inlineCommandUrl, sendQQMarkdown } from './qqPageMessage'
5
+
6
+ function renderCommandLine(content: string, commandHelp: boolean): string {
7
+ // Only explicit command-description rows enable links. Unknown input and
8
+ // other prose remain display text, even when they contain square brackets.
9
+ if (!commandHelp || !/^\s*\[[^\[\]\r\n]+\]/.test(content)) return escapeMarkdown(content)
10
+ const parts: string[] = []
11
+ let offset = 0
12
+ for (const match of content.matchAll(/\[([^\[\]\r\n]+)\]/g)) {
13
+ parts.push(escapeMarkdown(content.slice(offset, match.index)))
14
+ const command = match[1].split(/[++]/, 1)[0].trim()
15
+ parts.push(command
16
+ ? `[${escapeMarkdown(match[1])}](${inlineCommandUrl(command)})`
17
+ : escapeMarkdown(match[0]))
18
+ offset = match.index! + match[0].length
19
+ }
20
+ parts.push(escapeMarkdown(content.slice(offset)))
21
+ return parts.join('')
22
+ }
23
+
24
+ /** Keep help text intact while making its explicitly boxed commands clickable. */
25
+ export function renderQQCommandMarkdown(data: MsgMessage, showGreeting: boolean): string {
26
+ const sections: string[] = []
27
+ const bodyLines: string[] = []
28
+ const flushBody = () => {
29
+ if (bodyLines.length) sections.push(bodyLines.splice(0).join(' \n'))
30
+ }
31
+ if (showGreeting) sections.push(escapeMarkdown('Ciallo~(∠・ω< )'))
32
+ for (const item of data.line) {
33
+ switch (item.type) {
34
+ case MessageType.title:
35
+ flushBody()
36
+ sections.push(`**${escapeMarkdown(item.content)}**`)
37
+ break
38
+ case MessageType.line:
39
+ if (!item.content.trim()) flushBody()
40
+ else bodyLines.push(renderCommandLine(item.content, !!data.commandHelp))
41
+ break
42
+ case MessageType.error:
43
+ flushBody()
44
+ sections.push(`❌ 出错了!错误原因:${escapeMarkdown(item.content)},请反馈至联系开发者`)
45
+ break
46
+ }
47
+ }
48
+ flushBody()
49
+ return sections.join('\n\n') || ' '
50
+ }
51
+
52
+ export async function sendQQCommand(session: Session, data: MsgMessage): Promise<void> {
53
+ await sendQQMarkdown(session, renderQQCommandMarkdown(data, session.event?.channel?.type === 0))
54
+ }
@@ -23,7 +23,7 @@ type QQResponse = {
23
23
  }
24
24
 
25
25
  /** Escape server-provided lines before embedding them in native QQ Markdown. */
26
- function escapeMarkdown(value: string): string {
26
+ export function escapeMarkdown(value: string): string {
27
27
  return value.replace(/[\\`*_{}\[\]()#+\-.!|>~<&]/g, '\\$&')
28
28
  }
29
29
 
@@ -44,7 +44,7 @@ function compactListLabel(value: string): string {
44
44
  : label
45
45
  }
46
46
 
47
- function inlineCommandUrl(command: string): string {
47
+ export function inlineCommandUrl(command: string): string {
48
48
  // encodeURIComponent leaves parentheses unescaped, which would close the
49
49
  // surrounding Markdown link if an item ID ever contained one.
50
50
  const encoded = encodeURIComponent(command).replace(/[!'()*]/g, character =>
@@ -68,7 +68,7 @@ export function renderQQPageMarkdown(data: MsgMessage, showGreeting: boolean): s
68
68
  const summaryLine = data.line.find(item => item.type === MessageType.line && pagePattern.test(item.content))
69
69
  const summary = summaryLine && pagePattern.exec(summaryLine.content)
70
70
  const listCount = data.line.filter(item => item.type === MessageType.line && listPattern.test(item.content)).length
71
- const count = summary?.[1] ?? (nav?.total === 1 ? String(listCount) : undefined)
71
+ const count = summary?.[1] ?? (nav?.total === 1 && listCount > 0 ? String(listCount) : undefined)
72
72
  const countUnit = summary?.[2] ?? '项'
73
73
  const isLeaderboardDirectory = !!nav?.entries?.length
74
74
  && /^(?:🏆)?排行榜$/u.test(compactDisplayText(title?.content ?? ''))
@@ -144,8 +144,12 @@ export function renderQQPageMarkdown(data: MsgMessage, showGreeting: boolean): s
144
144
  flush()
145
145
  if (nav && !hasPageSummary && (nav.total > 1 || nav.previousCommand || nav.nextCommand))
146
146
  pageFooter = `**第${nav.current}/${nav.total}页**`
147
- const previousLink = nav?.previousCommand ? `[上一页](${inlineCommandUrl(nav.previousCommand)})` : undefined
148
- const nextLink = nav?.nextCommand ? `[下一页](${inlineCommandUrl(nav.nextCommand)})` : undefined
147
+ const previousLink = nav?.previousCommand
148
+ ? `[${nav.previousCommand === '上一个' ? '上一个' : '上一页'}](${inlineCommandUrl(nav.previousCommand)})`
149
+ : undefined
150
+ const nextLink = nav?.nextCommand
151
+ ? `[${nav.nextCommand === '下一个' ? '下一个' : '下一页'}](${inlineCommandUrl(nav.nextCommand)})`
152
+ : undefined
149
153
  const helpLink = hasHelp ? `[指令](${inlineCommandUrl('指令')})` : undefined
150
154
  const footer = pageFooter
151
155
  ? [pageFooter, previousLink, nextLink, helpLink].filter(Boolean).join('·')
@@ -167,8 +171,13 @@ export function canSendQQPage(session: Session | undefined, data: MsgMessage): s
167
171
 
168
172
  /** Send a native QQ Markdown page with inline command links. */
169
173
  export async function sendQQPage(session: Session, data: MsgMessage): Promise<void> {
170
- const internal = (session.bot as typeof session.bot & { internal: QQInternal }).internal
171
174
  const markdown = renderQQPageMarkdown(data, session.event?.channel?.type === 0)
175
+ await sendQQMarkdown(session, markdown)
176
+ }
177
+
178
+ /** Reuse the adapter's native reply API for structured Markdown messages. */
179
+ export async function sendQQMarkdown(session: Session, markdown: string): Promise<void> {
180
+ const internal = (session.bot as typeof session.bot & { internal: QQInternal }).internal
172
181
  const request: QQRequest = {
173
182
  // With msg_type=2, QQ requires the ordinary content field to be empty.
174
183
  content: '',
@@ -0,0 +1,62 @@
1
+ import type { Session } from 'koishi'
2
+ import { MessageType } from '../../shared/face'
3
+ import type { MsgMessage } from '../../shared/bot/MsgMessage'
4
+ import { escapeMarkdown, inlineCommandUrl, sendQQMarkdown } from './qqPageMessage'
5
+
6
+ /** Render only explicitly marked transactions; line content never enables this channel. */
7
+ export function renderQQTransactionMarkdown(data: MsgMessage, showGreeting: boolean): string {
8
+ const sections: string[] = []
9
+ const bodyLines: string[] = []
10
+ const actions: string[] = []
11
+ const flushBody = () => {
12
+ if (bodyLines.length) sections.push(bodyLines.splice(0).join(' \n'))
13
+ }
14
+ const flushActions = () => {
15
+ if (actions.length) sections.push(actions.splice(0).join(' · '))
16
+ }
17
+ const flush = () => { flushBody(); flushActions() }
18
+ if (showGreeting) sections.push(escapeMarkdown('Ciallo~(∠・ω< )'))
19
+ for (const item of data.line) {
20
+ if (item.type === MessageType.title) {
21
+ flush()
22
+ sections.push(`**${escapeMarkdown(item.content)}**`)
23
+ continue
24
+ }
25
+ if (item.type === MessageType.error) {
26
+ flush()
27
+ sections.push(`❌ 出错了!错误原因:${escapeMarkdown(item.content)},请反馈至联系开发者`)
28
+ continue
29
+ }
30
+ if (item.type !== MessageType.line) continue
31
+ // These are the common trade actions. Names, reasons and arbitrary bracketed
32
+ // material text remain escaped display text rather than executable commands.
33
+ const action = data.transaction && (item.content === '[是]确认交易'
34
+ ? { command: '是', label: '确认交易' }
35
+ : item.content === '[否]取消交易' ? { command: '否', label: '取消交易' } : undefined)
36
+ if (action) {
37
+ flushBody()
38
+ actions.push(`[${action.label}](${inlineCommandUrl(action.command)})`)
39
+ continue
40
+ }
41
+ flushActions()
42
+ if (!item.content.trim()) {
43
+ flushBody()
44
+ continue
45
+ }
46
+ const section = /^┄━═(.+)═━┄$/.exec(item.content)
47
+ if (section || item.content === '【还缺】') {
48
+ flushBody()
49
+ sections.push(`**${escapeMarkdown(section?.[1] ?? '还缺')}**`)
50
+ } else {
51
+ // Preserve the server's quoted amounts, names and descriptions verbatim
52
+ // apart from Markdown escaping; rendering never recalculates payments.
53
+ bodyLines.push(escapeMarkdown(item.content))
54
+ }
55
+ }
56
+ flush()
57
+ return sections.join('\n\n') || ' '
58
+ }
59
+
60
+ export async function sendQQTransaction(session: Session, data: MsgMessage): Promise<void> {
61
+ await sendQQMarkdown(session, renderQQTransactionMarkdown(data, session.event?.channel?.type === 0))
62
+ }
@@ -3,15 +3,19 @@ import { MsgMessage } from '../../shared/bot/MsgMessage'
3
3
  import sessions, { sessionKey } from '../sessions'
4
4
  import handel_base from './handel_base'
5
5
  import { canSendQQPage, pageCommandLines, sendQQPage } from './qqPageMessage'
6
+ import { sendQQTransaction } from './qqTransactionMessage'
7
+ import { sendQQCommand } from './qqCommandMessage'
6
8
 
7
9
  export default class handelr_text extends handel_base {
8
10
  async start(data: MsgMessage) {
9
11
  const content = new AnalysisMsg().parse(data)
10
12
  const session = sessions.get(sessionKey(data.botId, data.userId, data.channelId))
11
- if (data.pageNav && canSendQQPage(session, data)) {
13
+ if ((data.commandHelp || data.transaction || data.pageNav) && canSendQQPage(session, data)) {
12
14
  const sendStartedAt = this.timing ? performance.now() : 0
13
15
  try {
14
- await sendQQPage(session, data)
16
+ if (data.commandHelp) await sendQQCommand(session, data)
17
+ else if (data.transaction) await sendQQTransaction(session, data)
18
+ else await sendQQPage(session, data)
15
19
  if (this.timing) {
16
20
  this.timing.delivery = 'qq-markdown'
17
21
  this.timing.sendMs = performance.now() - sendStartedAt
@@ -20,7 +24,7 @@ export default class handelr_text extends handel_base {
20
24
  } catch (error) {
21
25
  this.ctx.logger.warn('QQ Markdown 发送失败,改用普通文字', error instanceof Error ? error.message : error)
22
26
  }
23
- const commands = pageCommandLines(data.pageNav)
27
+ const commands = !data.commandHelp && !data.transaction && data.pageNav ? pageCommandLines(data.pageNav) : []
24
28
  await this.send(data, commands.length ? `${content.trimEnd()}\n${commands.join('\n')}` : content)
25
29
  return
26
30
  }
@@ -20,7 +20,7 @@ export interface ServiceType {
20
20
  }
21
21
 
22
22
  export const serviceProto: ServiceProto<ServiceType> = {
23
- "version": 11,
23
+ "version": 13,
24
24
  "services": [
25
25
  {
26
26
  "id": 0,
@@ -155,6 +155,22 @@ export const serviceProto: ServiceProto<ServiceType> = {
155
155
  },
156
156
  "optional": true
157
157
  },
158
+ {
159
+ "id": 8,
160
+ "name": "transaction",
161
+ "type": {
162
+ "type": "Boolean"
163
+ },
164
+ "optional": true
165
+ },
166
+ {
167
+ "id": 9,
168
+ "name": "commandHelp",
169
+ "type": {
170
+ "type": "Boolean"
171
+ },
172
+ "optional": true
173
+ },
158
174
  {
159
175
  "id": 1,
160
176
  "name": "line",
@@ -1050,4 +1066,4 @@ export const serviceProto: ServiceProto<ServiceType> = {
1050
1066
  ]
1051
1067
  }
1052
1068
  }
1053
- };
1069
+ };
@@ -103,6 +103,10 @@ export interface IMessage {
103
103
  equipmentCard?: EquipmentCardData;
104
104
  leaderboard?: LeaderboardImageData;
105
105
  pageNav?: PageNavData;
106
+ /** 通用交易确认、结果与失败消息;客户端可使用交易 Markdown 展示。 */
107
+ transaction?: boolean;
108
+ /** 指令系统与指令提示;客户端可用 Markdown 展示可点击的方框指令。 */
109
+ commandHelp?: boolean;
106
110
  /** 消息项列表 **/
107
111
  line: IMessageItem[];
108
112
  }