koishi-plugin-ciyi 1.2.8 → 1.2.9

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.d.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  import { Context, Schema, Session } from "koishi";
2
2
  import { History } from "./view";
3
3
  export declare const name = "ciyi";
4
- export declare const usage = "## \u4F7F\u7528\n\n\u8BBE\u7F6E\u6307\u4EE4\u522B\u540D\u540E\uFF0C\u53D1\u9001 `ciyi` \u67E5\u770B\u73A9\u6CD5\u3002\u6BCF\u65E5\u85CF\u4E00\u4E2A\u4E24\u5B57\u8BCD\uFF0C\u4F7F\u7528 `ciyi.\u731C <\u8BCD>` \u63D0\u4EA4\u7B2C\u4E00\u6B21\u731C\u6D4B\u5E76\u5F00\u9898\uFF1B\u5F00\u9898\u540E\u53EF\u76F4\u63A5\u53D1\u9001\u4E24\u5B57\u8BCD\u7EE7\u7EED\u731C\u6D4B\u3002\n\n## \u6307\u4EE4\n\n| \u6307\u4EE4 | \u8BF4\u660E |\n| --- | --- |\n| `ciyi` | \u73A9\u6CD5\u8BF4\u660E |\n| `ciyi.\u731C <\u8BCD>` | \u5F00\u59CB\u4ECA\u65E5\u6E38\u620F\u5E76\u63D0\u4EA4\u731C\u6D4B |\n| `ciyi.\u6392\u884C\u699C` | \u731C\u4E2D\u6B21\u6570\u699C |";
4
+ export declare const usage = "## \u4F7F\u7528\n\n\u8BBE\u7F6E\u6307\u4EE4\u522B\u540D\u540E\uFF0C\u53D1\u9001 `ciyi` \u67E5\u770B\u73A9\u6CD5\u3002\u6BCF\u65E5\u85CF\u4E00\u4E2A\u4E24\u5B57\u8BCD\uFF0C\u4F7F\u7528 `ciyi.\u731C <\u8BCD>` \u63D0\u4EA4\u7B2C\u4E00\u6B21\u731C\u6D4B\u5E76\u5F00\u9898\uFF1B\u5F00\u9898\u540E\u53EF\u76F4\u63A5\u53D1\u9001\u4E24\u5B57\u8BCD\u7EE7\u7EED\u731C\u6D4B\u3002`ciyi.\u88F8\u8BCD` \u53EF\u5728\u5F53\u524D\u7FA4\u4E34\u65F6\u5207\u6362\u8FD9\u4E00\u884C\u4E3A\uFF0C\u4E0D\u6539\u63D2\u4EF6\u914D\u7F6E\uFF0C\u91CD\u542F\u540E\u81EA\u52A8\u590D\u539F\u3002\n\n## \u6307\u4EE4\n\n| \u6307\u4EE4 | \u8BF4\u660E |\n| --- | --- |\n| `ciyi` | \u73A9\u6CD5\u8BF4\u660E |\n| `ciyi.\u731C <\u8BCD>` | \u5F00\u59CB\u4ECA\u65E5\u6E38\u620F\u5E76\u63D0\u4EA4\u731C\u6D4B |\n| `ciyi.\u88F8\u8BCD [\u5F00/\u5173]` | \u4E34\u65F6\u5207\u6362\u672C\u7FA4\u88F8\u8BCD\u7EED\u731C |\n| `ciyi.\u6392\u884C\u699C` | \u731C\u4E2D\u6B21\u6570\u699C |";
5
5
  export declare const inject: {
6
6
  required: string[];
7
7
  optional: string[];
@@ -46,4 +46,20 @@ export type { History };
46
46
  export declare function getMiddlewareGuess(session: Session): string | null;
47
47
  /** 裸词只能加入已开始且未封题的游戏,不能开题,也不重复提交旧猜测。 */
48
48
  export declare function canHandleMiddlewareGuess(game: Ciyi | null | undefined, guess: string): boolean;
49
+ export type MiddlewareSwitch = {
50
+ error: string;
51
+ } | {
52
+ /** 写回本群覆盖表的新值;undefined 表示清除覆盖,回到插件配置 */
53
+ override: boolean | undefined;
54
+ /** 切换后的生效状态 */
55
+ on: boolean;
56
+ /** 本次是否清除了本群已有的临时改动 */
57
+ reverted: boolean;
58
+ };
59
+ /**
60
+ * 裸词开关是「插件配置」与「本群临时相反」之间的往返:本群从不保留与配置相同的冗余覆盖,
61
+ * 状态只有两种来历 —— 本群临时改动,或跟随插件配置,回复也因此总能如实相告。
62
+ * 无参调用是切换,显式 开/关 与配置同值时视作复原,状态 只查不改。
63
+ */
64
+ export declare function resolveMiddlewareSwitch(config: boolean, override: boolean | undefined, action: string | null | undefined): MiddlewareSwitch;
49
65
  export declare function apply(ctx: Context, cfg: Config): void;
package/lib/index.js CHANGED
@@ -26,6 +26,7 @@ __export(index_exports, {
26
26
  getMiddlewareGuess: () => getMiddlewareGuess,
27
27
  inject: () => inject,
28
28
  name: () => name,
29
+ resolveMiddlewareSwitch: () => resolveMiddlewareSwitch,
29
30
  usage: () => usage
30
31
  });
31
32
  module.exports = __toCommonJS(index_exports);
@@ -565,7 +566,7 @@ function renderBoardCard(service, opts) {
565
566
  __name(renderBoardCard, "renderBoardCard");
566
567
  function renderIntroCard(service, opts) {
567
568
  const innerW = s(720);
568
- const innerH = s(688);
569
+ const innerH = s(716);
569
570
  return toPng(service, innerW, innerH, (ctx, ix, iy, iw, ih) => {
570
571
  let y = iy + drawHeader(ctx, ix, iy, iw, "按意思远近找词 · 每日一题", {
571
572
  big: opts.words.toLocaleString(),
@@ -574,7 +575,7 @@ function renderIntroCard(service, opts) {
574
575
  y += s(20);
575
576
  y += drawSectionTitle(ctx, ix + s(22), y, iw - s(44), "玩法");
576
577
  y += s(11);
577
- const p1h = s(76);
578
+ const p1h = s(104);
578
579
  drawPanel(ctx, ix + s(22), y, iw - s(44), p1h);
579
580
  textLeft(ctx, "开始", ix + s(38), y + s(24), `${s(14)}px ${FONT_SERIF}`, C.seal);
580
581
  textLeft(ctx, "ciyi.猜 山水", ix + s(96), y + s(24), `${s(13.5)}px ${FONT_NUM}`, C.ink);
@@ -587,9 +588,20 @@ function renderIntroCard(service, opts) {
587
588
  `${s(14)}px ${FONT_SERIF}`,
588
589
  C.ink
589
590
  );
590
- textLeft(ctx, "排行", ix + s(38), y + s(52), `${s(14)}px ${FONT_SERIF}`, C.seal);
591
- textLeft(ctx, "ciyi.排行榜", ix + s(96), y + s(52), `${s(13.5)}px ${FONT_NUM}`, C.ink);
592
- textLeft(ctx, "看谁猜中得最多", ix + s(230), y + s(52), `${s(14)}px ${FONT_SERIF}`, C.ink);
591
+ textLeft(ctx, "切换", ix + s(38), y + s(52), `${s(14)}px ${FONT_SERIF}`, C.seal);
592
+ textLeft(ctx, "ciyi.裸词 开/关", ix + s(96), y + s(52), `${s(13.5)}px ${FONT_NUM}`, C.ink);
593
+ textLeftFit(
594
+ ctx,
595
+ "临时改本群的续猜方式",
596
+ ix + s(230),
597
+ y + s(52),
598
+ iw - s(268),
599
+ `${s(14)}px ${FONT_SERIF}`,
600
+ C.ink
601
+ );
602
+ textLeft(ctx, "排行", ix + s(38), y + s(80), `${s(14)}px ${FONT_SERIF}`, C.seal);
603
+ textLeft(ctx, "ciyi.排行榜", ix + s(96), y + s(80), `${s(13.5)}px ${FONT_NUM}`, C.ink);
604
+ textLeft(ctx, "看谁猜中得最多", ix + s(230), y + s(80), `${s(14)}px ${FONT_SERIF}`, C.ink);
593
605
  y += p1h + s(19);
594
606
  y += drawSectionTitle(ctx, ix + s(22), y, iw - s(44), "读板");
595
607
  y += s(11);
@@ -871,7 +883,7 @@ __name(renderRankCard, "renderRankCard");
871
883
  var name = "ciyi";
872
884
  var usage = `## 使用
873
885
 
874
- 设置指令别名后,发送 \`ciyi\` 查看玩法。每日藏一个两字词,使用 \`ciyi.猜 <词>\` 提交第一次猜测并开题;开题后可直接发送两字词继续猜测。
886
+ 设置指令别名后,发送 \`ciyi\` 查看玩法。每日藏一个两字词,使用 \`ciyi.猜 <词>\` 提交第一次猜测并开题;开题后可直接发送两字词继续猜测。\`ciyi.裸词\` 可在当前群临时切换这一行为,不改插件配置,重启后自动复原。
875
887
 
876
888
  ## 指令
877
889
 
@@ -879,12 +891,15 @@ var usage = `## 使用
879
891
  | --- | --- |
880
892
  | \`ciyi\` | 玩法说明 |
881
893
  | \`ciyi.猜 <词>\` | 开始今日游戏并提交猜测 |
894
+ | \`ciyi.裸词 [开/关]\` | 临时切换本群裸词续猜 |
882
895
  | \`ciyi.排行榜\` | 猜中次数榜 |`;
883
896
  var inject = { required: ["database"], optional: ["canvas"] };
884
897
  var Config = import_koishi.Schema.object({
885
898
  atReply: import_koishi.Schema.boolean().default(false).description("响应时 @"),
886
899
  quoteReply: import_koishi.Schema.boolean().default(false).description("响应时引用"),
887
- isEnableMiddleware: import_koishi.Schema.boolean().default(true).description("是否启用中间件(若启用,已开题时可以不使用指令直接猜测)"),
900
+ isEnableMiddleware: import_koishi.Schema.boolean().default(true).description(
901
+ "是否启用中间件(若启用,已开题时可以不使用指令直接猜测;ciyi.裸词 指令可在单个群内临时切换)"
902
+ ),
888
903
  renderImage: import_koishi.Schema.boolean().default(true).description("渲染图片(复用 Koishi Canvas 服务;不可用时使用等价文本)"),
889
904
  maxHistory: import_koishi.Schema.number().default(10).min(0).description("猜测板最多列出的历史条数(最新一次猜测始终会列出)"),
890
905
  maxRank: import_koishi.Schema.number().default(10).min(0).description("最大排行榜人数")
@@ -911,6 +926,24 @@ function canHandleMiddlewareGuess(game, guess) {
911
926
  return guess === game.answer || game.rankList?.includes(guess) === true;
912
927
  }
913
928
  __name(canHandleMiddlewareGuess, "canHandleMiddlewareGuess");
929
+ function resolveMiddlewareSwitch(config, override, action) {
930
+ const arg = action?.trim();
931
+ if (!arg) {
932
+ return override === void 0 ? { override: !config, on: !config, reverted: false } : { override: void 0, on: config, reverted: true };
933
+ }
934
+ if (arg === "状态") {
935
+ return { override, on: override ?? config, reverted: false };
936
+ }
937
+ const on = arg === "开" || arg === "开启";
938
+ if (!on && arg !== "关" && arg !== "关闭") {
939
+ return { error: "裸词开关只认 开 / 关 / 状态" };
940
+ }
941
+ if (on === config) {
942
+ return { override: void 0, on: config, reverted: override !== void 0 };
943
+ }
944
+ return { override: on, on, reverted: false };
945
+ }
946
+ __name(resolveMiddlewareSwitch, "resolveMiddlewareSwitch");
914
947
  function apply(ctx, cfg) {
915
948
  ctx.model.extend(
916
949
  "ciyi",
@@ -940,25 +973,26 @@ function apply(ctx, cfg) {
940
973
  const logger = ctx.logger("ciyi");
941
974
  const random = new import_koishi.Random(() => Math.random());
942
975
  const RULE = "────────────";
943
- if (cfg.isEnableMiddleware) {
944
- ctx.middleware(async (session, next) => {
945
- const guess = getMiddlewareGuess(session);
946
- if (!guess || !session.channelId) return await next();
947
- try {
948
- const [game] = await ctx.database.get("ciyi", {
949
- channelId: session.channelId
950
- });
951
- if (!canHandleMiddlewareGuess(game, guess)) return await next();
952
- } catch (error) {
953
- logger.warn(
954
- "中间件读取游戏状态失败,本次消息不作猜测:%s",
955
- error?.message ?? error
956
- );
957
- return await next();
958
- }
959
- return await session.execute(`ciyi.猜 ${guess}`);
960
- });
961
- }
976
+ const middlewareOverrides = /* @__PURE__ */ new Map();
977
+ const middlewareOn = /* @__PURE__ */ __name((channelId) => channelId === void 0 ? cfg.isEnableMiddleware : middlewareOverrides.get(channelId) ?? cfg.isEnableMiddleware, "middlewareOn");
978
+ ctx.middleware(async (session, next) => {
979
+ if (!session.channelId || !middlewareOn(session.channelId)) return await next();
980
+ const guess = getMiddlewareGuess(session);
981
+ if (!guess) return await next();
982
+ try {
983
+ const [game] = await ctx.database.get("ciyi", {
984
+ channelId: session.channelId
985
+ });
986
+ if (!canHandleMiddlewareGuess(game, guess)) return await next();
987
+ } catch (error) {
988
+ logger.warn(
989
+ "中间件读取游戏状态失败,本次消息不作猜测:%s",
990
+ error instanceof Error ? error.message : String(error)
991
+ );
992
+ return await next();
993
+ }
994
+ return await session.execute(`ciyi.猜 ${guess}`);
995
+ });
962
996
  ctx.command("ciyi", "词意(猜词游戏)").action(async ({ session }) => {
963
997
  return await wf(session);
964
998
  });
@@ -968,6 +1002,26 @@ function apply(ctx, cfg) {
968
1002
  ctx.command("ciyi.排行榜", "累计猜中次数榜").action(async ({ session }) => {
969
1003
  return await phb(session);
970
1004
  });
1005
+ ctx.command("ciyi.裸词 [state:string]", "临时开关本群的裸词续猜").usage("例:ciyi.裸词(切换)· ciyi.裸词 开 · ciyi.裸词 关 · ciyi.裸词 状态").action(async ({ session }, state) => {
1006
+ const result = resolveMiddlewareSwitch(
1007
+ cfg.isEnableMiddleware,
1008
+ session.channelId === void 0 ? void 0 : middlewareOverrides.get(session.channelId),
1009
+ state
1010
+ );
1011
+ if ("error" in result) {
1012
+ return await sendMsg(session, `⚠️ ${result.error}。例:ciyi.裸词 开`);
1013
+ }
1014
+ if (result.override === void 0) middlewareOverrides.delete(session.channelId);
1015
+ else middlewareOverrides.set(session.channelId, result.override);
1016
+ return await sendMsg(
1017
+ session,
1018
+ middlewareSwitchText({
1019
+ on: result.on,
1020
+ temporary: result.override !== void 0,
1021
+ reverted: result.reverted
1022
+ })
1023
+ );
1024
+ });
971
1025
  function getNewUniqueAnswer(oldGuessedWords) {
972
1026
  const usedWordsSet = new Set(oldGuessedWords);
973
1027
  const availableWords = questionList_default.filter(
@@ -1053,14 +1107,15 @@ function apply(ctx, cfg) {
1053
1107
  );
1054
1108
  }
1055
1109
  __name(boardText, "boardText");
1056
- function introText() {
1110
+ function introText(channelOn) {
1057
1111
  return textCard(
1058
1112
  "词意 · 按意思远近找词",
1059
1113
  `每天藏起一个两字词。你报词,我回它与答案的语义排名 —— 名次越小越近,#1 就是答案本身。`,
1060
1114
  [
1061
1115
  `开始 ciyi.猜 山水  开题并报一个两字词`,
1062
- cfg.isEnableMiddleware ? `续猜 直接发送两字词 仅限已开题且未结束` : null,
1063
- `排行 ciyi.排行榜  看谁猜中得最多`
1116
+ channelOn ? `续猜 直接发送两字词 仅限已开题且未结束` : null,
1117
+ `排行 ciyi.排行榜  看谁猜中得最多`,
1118
+ `切换 ciyi.裸词 开/关  临时改本群续猜方式`
1064
1119
  ].filter(Boolean),
1065
1120
  [
1066
1121
  `读板 ?好)企业(地? #467 · 沾边`,
@@ -1076,6 +1131,20 @@ function apply(ctx, cfg) {
1076
1131
  );
1077
1132
  }
1078
1133
  __name(introText, "introText");
1134
+ function middlewareSwitchText(o) {
1135
+ const mark = o.on ? "✅" : "⛔";
1136
+ const state = o.on ? "开启" : "停用";
1137
+ const config = cfg.isEnableMiddleware ? "开启" : "停用";
1138
+ if (!o.temporary) {
1139
+ return `${mark} 裸词续猜 · ${o.reverted ? "已复原," : ""}跟随插件配置(${state})`;
1140
+ }
1141
+ const hint = o.on ? "开题后直接发送两字词即可续猜" : "续猜请用 ciyi.猜 山水";
1142
+ return [
1143
+ `${mark} 裸词续猜 · 本群临时${state}(插件配置:${config})`,
1144
+ `${hint};再次发送 ciyi.裸词 复原`
1145
+ ].join("\n");
1146
+ }
1147
+ __name(middlewareSwitchText, "middlewareSwitchText");
1079
1148
  function winText(o) {
1080
1149
  return textCard(
1081
1150
  "猜中了 · 今日已封题",
@@ -1130,14 +1199,15 @@ function apply(ctx, cfg) {
1130
1199
  }
1131
1200
  __name(sendCard, "sendCard");
1132
1201
  async function wf(session) {
1202
+ const channelOn = middlewareOn(session.channelId);
1133
1203
  return await sendCard(
1134
1204
  session,
1135
1205
  () => renderIntroCard(ctx.canvas, {
1136
1206
  total: allWords_default.length,
1137
1207
  words: allWords_default.length,
1138
- middleware: cfg.isEnableMiddleware
1208
+ middleware: channelOn
1139
1209
  }),
1140
- introText()
1210
+ introText(channelOn)
1141
1211
  );
1142
1212
  }
1143
1213
  __name(wf, "wf");
@@ -1331,5 +1401,6 @@ __name(apply, "apply");
1331
1401
  getMiddlewareGuess,
1332
1402
  inject,
1333
1403
  name,
1404
+ resolveMiddlewareSwitch,
1334
1405
  usage
1335
1406
  });
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "koishi-plugin-ciyi",
3
3
  "description": "Koishi 的词意猜词插件。",
4
- "version": "1.2.8",
4
+ "version": "1.2.9",
5
5
  "main": "lib/index.js",
6
6
  "typings": "lib/index.d.ts",
7
7
  "files": [
package/readme.md CHANGED
@@ -8,7 +8,7 @@ Koishi 的词意猜词插件。
8
8
 
9
9
  ## 使用
10
10
 
11
- 设置指令别名后,发送 `ciyi` 查看玩法。每日藏一个两字词,使用 `ciyi.猜 <词>` 提交第一次猜测并开题;开题后可直接发送两字词继续猜测。
11
+ 设置指令别名后,发送 `ciyi` 查看玩法。每日藏一个两字词,使用 `ciyi.猜 <词>` 提交第一次猜测并开题;开题后可直接发送两字词继续猜测。`ciyi.裸词` 可在当前群临时切换这一行为,不改插件配置,重启后自动复原。
12
12
 
13
13
  ## 指令
14
14
 
@@ -16,6 +16,7 @@ Koishi 的词意猜词插件。
16
16
  | --- | --- |
17
17
  | `ciyi` | 玩法说明 |
18
18
  | `ciyi.猜 <词>` | 开始今日游戏并提交猜测 |
19
+ | `ciyi.裸词 [开/关]` | 临时切换本群裸词续猜 |
19
20
  | `ciyi.排行榜` | 猜中次数榜 |
20
21
 
21
22
  ## QQ 群