koishi-plugin-dew-bot 1.0.250 → 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) {
@@ -895,7 +895,7 @@ function renderQQTransactionMarkdown(data, showGreeting) {
895
895
  const action = data.transaction && (item.content === "[是]确认交易" ? { command: "是", label: "确认交易" } : item.content === "[否]取消交易" ? { command: "否", label: "取消交易" } : void 0);
896
896
  if (action) {
897
897
  flushBody();
898
- actions.push(`[${action.command}](${inlineCommandUrl(action.command)}) ${action.label}`);
898
+ actions.push(`[${action.label}](${inlineCommandUrl(action.command)})`);
899
899
  continue;
900
900
  }
901
901
  flushActions();
@@ -920,6 +920,53 @@ async function sendQQTransaction(session, data) {
920
920
  }
921
921
  __name(sendQQTransaction, "sendQQTransaction");
922
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");
969
+
923
970
  // src/plugin/serverHandel/text.ts
924
971
  var handelr_text = class extends handel_base {
925
972
  static {
@@ -928,10 +975,11 @@ var handelr_text = class extends handel_base {
928
975
  async start(data) {
929
976
  const content = new AnalysisMsg().parse(data);
930
977
  const session = sessions_default.get(sessionKey(data.botId, data.userId, data.channelId));
931
- if ((data.transaction || data.pageNav) && canSendQQPage(session, data)) {
978
+ if ((data.commandHelp || data.transaction || data.pageNav) && canSendQQPage(session, data)) {
932
979
  const sendStartedAt = this.timing ? performance.now() : 0;
933
980
  try {
934
- if (data.transaction) await sendQQTransaction(session, data);
981
+ if (data.commandHelp) await sendQQCommand(session, data);
982
+ else if (data.transaction) await sendQQTransaction(session, data);
935
983
  else await sendQQPage(session, data);
936
984
  if (this.timing) {
937
985
  this.timing.delivery = "qq-markdown";
@@ -941,7 +989,7 @@ var handelr_text = class extends handel_base {
941
989
  } catch (error) {
942
990
  this.ctx.logger.warn("QQ Markdown 发送失败,改用普通文字", error instanceof Error ? error.message : error);
943
991
  }
944
- const commands = !data.transaction && data.pageNav ? pageCommandLines(data.pageNav) : [];
992
+ const commands = !data.commandHelp && !data.transaction && data.pageNav ? pageCommandLines(data.pageNav) : [];
945
993
  await this.send(data, commands.length ? `${content.trimEnd()}
946
994
  ${commands.join("\n")}` : content);
947
995
  return;
@@ -1014,7 +1062,7 @@ var import_tsrpc = require("tsrpc");
1014
1062
 
1015
1063
  // src/shared/bot/serviceProto.ts
1016
1064
  var serviceProto = {
1017
- "version": 12,
1065
+ "version": 13,
1018
1066
  "services": [
1019
1067
  {
1020
1068
  "id": 0,
@@ -1157,6 +1205,14 @@ var serviceProto = {
1157
1205
  },
1158
1206
  "optional": true
1159
1207
  },
1208
+ {
1209
+ "id": 9,
1210
+ "name": "commandHelp",
1211
+ "type": {
1212
+ "type": "Boolean"
1213
+ },
1214
+ "optional": true
1215
+ },
1160
1216
  {
1161
1217
  "id": 1,
1162
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>;
@@ -132,6 +132,8 @@ export interface IMessage {
132
132
  pageNav?: PageNavData;
133
133
  /** 通用交易确认、结果与失败消息;客户端可使用交易 Markdown 展示。 */
134
134
  transaction?: boolean;
135
+ /** 指令系统与指令提示;客户端可用 Markdown 展示可点击的方框指令。 */
136
+ commandHelp?: boolean;
135
137
  /** 消息项列表 **/
136
138
  line: IMessageItem[];
137
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.250",
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
+ }
@@ -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('·')
@@ -35,7 +35,7 @@ export function renderQQTransactionMarkdown(data: MsgMessage, showGreeting: bool
35
35
  : item.content === '[否]取消交易' ? { command: '否', label: '取消交易' } : undefined)
36
36
  if (action) {
37
37
  flushBody()
38
- actions.push(`[${action.command}](${inlineCommandUrl(action.command)}) ${action.label}`)
38
+ actions.push(`[${action.label}](${inlineCommandUrl(action.command)})`)
39
39
  continue
40
40
  }
41
41
  flushActions()
@@ -4,15 +4,17 @@ import sessions, { sessionKey } from '../sessions'
4
4
  import handel_base from './handel_base'
5
5
  import { canSendQQPage, pageCommandLines, sendQQPage } from './qqPageMessage'
6
6
  import { sendQQTransaction } from './qqTransactionMessage'
7
+ import { sendQQCommand } from './qqCommandMessage'
7
8
 
8
9
  export default class handelr_text extends handel_base {
9
10
  async start(data: MsgMessage) {
10
11
  const content = new AnalysisMsg().parse(data)
11
12
  const session = sessions.get(sessionKey(data.botId, data.userId, data.channelId))
12
- if ((data.transaction || data.pageNav) && canSendQQPage(session, data)) {
13
+ if ((data.commandHelp || data.transaction || data.pageNav) && canSendQQPage(session, data)) {
13
14
  const sendStartedAt = this.timing ? performance.now() : 0
14
15
  try {
15
- if (data.transaction) await sendQQTransaction(session, data)
16
+ if (data.commandHelp) await sendQQCommand(session, data)
17
+ else if (data.transaction) await sendQQTransaction(session, data)
16
18
  else await sendQQPage(session, data)
17
19
  if (this.timing) {
18
20
  this.timing.delivery = 'qq-markdown'
@@ -22,7 +24,7 @@ export default class handelr_text extends handel_base {
22
24
  } catch (error) {
23
25
  this.ctx.logger.warn('QQ Markdown 发送失败,改用普通文字', error instanceof Error ? error.message : error)
24
26
  }
25
- const commands = !data.transaction && data.pageNav ? pageCommandLines(data.pageNav) : []
27
+ const commands = !data.commandHelp && !data.transaction && data.pageNav ? pageCommandLines(data.pageNav) : []
26
28
  await this.send(data, commands.length ? `${content.trimEnd()}\n${commands.join('\n')}` : content)
27
29
  return
28
30
  }
@@ -20,7 +20,7 @@ export interface ServiceType {
20
20
  }
21
21
 
22
22
  export const serviceProto: ServiceProto<ServiceType> = {
23
- "version": 12,
23
+ "version": 13,
24
24
  "services": [
25
25
  {
26
26
  "id": 0,
@@ -163,6 +163,14 @@ export const serviceProto: ServiceProto<ServiceType> = {
163
163
  },
164
164
  "optional": true
165
165
  },
166
+ {
167
+ "id": 9,
168
+ "name": "commandHelp",
169
+ "type": {
170
+ "type": "Boolean"
171
+ },
172
+ "optional": true
173
+ },
166
174
  {
167
175
  "id": 1,
168
176
  "name": "line",
@@ -1058,4 +1066,4 @@ export const serviceProto: ServiceProto<ServiceType> = {
1058
1066
  ]
1059
1067
  }
1060
1068
  }
1061
- };
1069
+ };
@@ -105,6 +105,8 @@ export interface IMessage {
105
105
  pageNav?: PageNavData;
106
106
  /** 通用交易确认、结果与失败消息;客户端可使用交易 Markdown 展示。 */
107
107
  transaction?: boolean;
108
+ /** 指令系统与指令提示;客户端可用 Markdown 展示可点击的方框指令。 */
109
+ commandHelp?: boolean;
108
110
  /** 消息项列表 **/
109
111
  line: IMessageItem[];
110
112
  }