koishi-plugin-ciyi 1.4.0 → 2.0.0
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/README.md +1 -1
- package/lib/index.d.ts +3 -2
- package/lib/index.js +96 -60
- package/package.json +1 -1
package/README.md
CHANGED
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\u53D1\u9001 `ciyi` \u67E5\u770B\u73A9\u6CD5\u3002\u6BCF\u65E5\u85CF\u4E00\u4E2A\u4E24\u5B57\u8BCD\uFF0C\u7528 `ciyi.\u731C <\u8BCD>` \u5F00\u9898\uFF0C\u4E4B\u540E\u53EF\u4EE5\u76F4\u63A5\u53D1\u9001\u4E24\u5B57\u8BCD\u7EE7\u7EED\u731C\u3002\u88F8\u8BCD\u8BBE\u7F6E\u53EA\u5BF9\u5F53\u524D\u9891\u9053\u751F\u6548\uFF0C\u91CD\u542F\u540E\u6062\u590D\u9ED8\u8BA4\u3002\n\n## \u6307\u4EE4\n\n| \u6307\u4EE4 | \u8BF4\u660E |\n| --- | --- |\n| `ciyi` | \u73A9\u6CD5 |\n| `ciyi.\u731C <\u8BCD>` | \u5F00\u59CB\u4ECA\u65E5\
|
|
4
|
+
export declare const usage = "## \u4F7F\u7528\n\n\u53D1\u9001 `ciyi` \u67E5\u770B\u73A9\u6CD5\u3002\u6BCF\u65E5\u85CF\u4E00\u4E2A\u4E24\u5B57\u8BCD\uFF0C\u7528 `ciyi.\u731C <\u8BCD>` \u5F00\u9898\uFF0C\u4E4B\u540E\u53EF\u4EE5\u76F4\u63A5\u53D1\u9001\u4E24\u5B57\u8BCD\u7EE7\u7EED\u731C\u3002\u88F8\u8BCD\u8BBE\u7F6E\u53EA\u5BF9\u5F53\u524D\u9891\u9053\u751F\u6548\uFF0C\u91CD\u542F\u540E\u6062\u590D\u9ED8\u8BA4\u3002\n\n## \u6307\u4EE4\n\n| \u6307\u4EE4 | \u8BF4\u660E |\n| --- | --- |\n| `ciyi` | \u73A9\u6CD5 |\n| `ciyi.\u731C <\u8BCD>` | \u5F00\u59CB\u4ECA\u65E5\u5BF9\u5C40\u5E76\u62A5\u4E00\u4E2A\u4E24\u5B57\u8BCD |\n| `ciyi.\u88F8\u8BCD [\u5F00/\u5173]` | \u5F00\u5173\u672C\u9891\u9053\u7684\u65E0\u524D\u7F00\u7EED\u731C |\n| `ciyi.\u6392\u884C\u699C` | \u7D2F\u8BA1\u731C\u4E2D\u6392\u884C\u699C |";
|
|
5
5
|
export declare const inject: {
|
|
6
6
|
required: string[];
|
|
7
7
|
optional: string[];
|
|
@@ -9,10 +9,11 @@ export declare const inject: {
|
|
|
9
9
|
export interface Config {
|
|
10
10
|
atReply: boolean;
|
|
11
11
|
quoteReply: boolean;
|
|
12
|
-
|
|
12
|
+
enableDirectInput: boolean;
|
|
13
13
|
renderImage: boolean;
|
|
14
14
|
maxHistory: number;
|
|
15
15
|
maxRank: number;
|
|
16
|
+
retractDelay: number;
|
|
16
17
|
}
|
|
17
18
|
export declare const Config: Schema<Config>;
|
|
18
19
|
declare module "koishi" {
|
package/lib/index.js
CHANGED
|
@@ -430,7 +430,7 @@ function drawWordGrid(ctx, x, y, word, size, mask) {
|
|
|
430
430
|
const gap = s(g.gap);
|
|
431
431
|
const chars = Array.from(word || "");
|
|
432
432
|
if (chars.length === 0) {
|
|
433
|
-
textCenter(ctx, "—", x + s(14), y + cell / 2, `${s(13)}px ${FONT_SANS}`, C.
|
|
433
|
+
textCenter(ctx, "—", x + s(14), y + cell / 2, `${s(13)}px ${FONT_SANS}`, C.onSurfaceVariant);
|
|
434
434
|
return s(28);
|
|
435
435
|
}
|
|
436
436
|
let cx = x;
|
|
@@ -472,7 +472,7 @@ function drawHeader(ctx, innerX, innerY, innerW, sub, right) {
|
|
|
472
472
|
brandX,
|
|
473
473
|
innerY + padTop + s(36),
|
|
474
474
|
`italic ${s(10)}px ${FONT_NUM}`,
|
|
475
|
-
C.
|
|
475
|
+
C.onSurfaceVariant
|
|
476
476
|
);
|
|
477
477
|
const subRight = right ? innerX + innerW - padX - s(150) : innerX + innerW - padX;
|
|
478
478
|
textLeftFit(
|
|
@@ -487,7 +487,7 @@ function drawHeader(ctx, innerX, innerY, innerW, sub, right) {
|
|
|
487
487
|
if (right) {
|
|
488
488
|
const rx = innerX + innerW - padX;
|
|
489
489
|
textRight(ctx, right.big, rx, innerY + padTop + s(16), `700 ${s(31)}px ${FONT_NUM}`, C.primary);
|
|
490
|
-
textRight(ctx, right.cap, rx, innerY + padTop + s(44), `${s(10.5)}px ${FONT_SANS}`, C.
|
|
490
|
+
textRight(ctx, right.cap, rx, innerY + padTop + s(44), `${s(10.5)}px ${FONT_SANS}`, C.onSurfaceVariant);
|
|
491
491
|
}
|
|
492
492
|
const lineY = innerY + h2;
|
|
493
493
|
ctx.strokeStyle = C.outlineVariant;
|
|
@@ -527,7 +527,7 @@ function drawFooter(ctx, innerX, y, innerW, legendItems, tip) {
|
|
|
527
527
|
lx += s(9) + s(6);
|
|
528
528
|
textLeft(ctx, tier.name, lx, cy, `${s(11.5)}px ${FONT_SANS}`, C.onSurfaceVariant);
|
|
529
529
|
lx += textWidth(tier.name, s(11.5)) + s(4);
|
|
530
|
-
textLeft(ctx, range, lx, cy, `${s(11)}px ${FONT_NUM}`, C.
|
|
530
|
+
textLeft(ctx, range, lx, cy, `${s(11)}px ${FONT_NUM}`, C.onSurfaceVariant);
|
|
531
531
|
lx += textWidth(range, s(11)) + s(13);
|
|
532
532
|
}
|
|
533
533
|
const tipFont = `${s(11.5)}px ${FONT_SANS}`;
|
|
@@ -538,7 +538,7 @@ function drawFooter(ctx, innerX, y, innerW, legendItems, tip) {
|
|
|
538
538
|
innerX + innerW - padX,
|
|
539
539
|
cy,
|
|
540
540
|
tipFont,
|
|
541
|
-
C.
|
|
541
|
+
C.onSurfaceVariant
|
|
542
542
|
);
|
|
543
543
|
return h2 + padY * 2;
|
|
544
544
|
}
|
|
@@ -552,8 +552,8 @@ function drawLegendFull(ctx, x, y, w) {
|
|
|
552
552
|
const cy = y + Math.floor(i / 2) * rowH;
|
|
553
553
|
fillRound(ctx, cx, cy - s(4.5), s(9), s(9), s(SHAPE.full), t.color);
|
|
554
554
|
textLeft(ctx, t.name, cx + s(15), cy, `${s(11.5)}px ${FONT_SANS}`, C.onSurfaceVariant);
|
|
555
|
-
textLeft(ctx, tierRange(i), cx + s(52), cy, `${s(11)}px ${FONT_NUM}`, C.
|
|
556
|
-
textLeft(ctx, t.note, cx + s(100), cy, `${s(11.5)}px ${FONT_SANS}`, C.
|
|
555
|
+
textLeft(ctx, tierRange(i), cx + s(52), cy, `${s(11)}px ${FONT_NUM}`, C.onSurfaceVariant);
|
|
556
|
+
textLeft(ctx, t.note, cx + s(100), cy, `${s(11.5)}px ${FONT_SANS}`, C.onSurfaceVariant);
|
|
557
557
|
}
|
|
558
558
|
return rowH * Math.ceil(TIERS.length / 2) + s(8);
|
|
559
559
|
}
|
|
@@ -637,12 +637,12 @@ function drawBoardTable(ctx, x, y, w, opts, rowH) {
|
|
|
637
637
|
const mtX = mt0 + Math.max(0, (cols.mt - meterBlockW) / 2);
|
|
638
638
|
const headY = y;
|
|
639
639
|
const fs = s(10.5);
|
|
640
|
-
textLeft(ctx, "序", noX, headY, `${fs}px ${FONT_SANS}`, C.
|
|
641
|
-
textCenter(ctx, "更近 ◀", nb0 + cols.nb / 2, headY, `${fs}px ${FONT_SANS}`, C.
|
|
642
|
-
textCenter(ctx, "猜测", gw0 + cols.gw / 2, headY, `${fs}px ${FONT_SANS}`, C.
|
|
643
|
-
textCenter(ctx, "▶ 更远", nb1 + cols.nb / 2, headY, `${fs}px ${FONT_SANS}`, C.
|
|
644
|
-
textCenter(ctx, "排名", rk0 + cols.rk / 2, headY, `${fs}px ${FONT_SANS}`, C.
|
|
645
|
-
textCenter(ctx, "亲疏", mt0 + cols.mt / 2, headY, `${fs}px ${FONT_SANS}`, C.
|
|
640
|
+
textLeft(ctx, "序", noX, headY, `${fs}px ${FONT_SANS}`, C.onSurfaceVariant);
|
|
641
|
+
textCenter(ctx, "更近 ◀", nb0 + cols.nb / 2, headY, `${fs}px ${FONT_SANS}`, C.onSurfaceVariant);
|
|
642
|
+
textCenter(ctx, "猜测", gw0 + cols.gw / 2, headY, `${fs}px ${FONT_SANS}`, C.onSurfaceVariant);
|
|
643
|
+
textCenter(ctx, "▶ 更远", nb1 + cols.nb / 2, headY, `${fs}px ${FONT_SANS}`, C.onSurfaceVariant);
|
|
644
|
+
textCenter(ctx, "排名", rk0 + cols.rk / 2, headY, `${fs}px ${FONT_SANS}`, C.onSurfaceVariant);
|
|
645
|
+
textCenter(ctx, "亲疏", mt0 + cols.mt / 2, headY, `${fs}px ${FONT_SANS}`, C.onSurfaceVariant);
|
|
646
646
|
let ry = y + s(22);
|
|
647
647
|
let ordinal = 0;
|
|
648
648
|
for (const row of opts.rows) {
|
|
@@ -650,11 +650,11 @@ function drawBoardTable(ctx, x, y, w, opts, rowH) {
|
|
|
650
650
|
ry += s(8);
|
|
651
651
|
textCenter(
|
|
652
652
|
ctx,
|
|
653
|
-
|
|
653
|
+
`…… 另有 ${row.gapBefore} 词未列`,
|
|
654
654
|
cx + tableW / 2,
|
|
655
655
|
ry + s(10),
|
|
656
656
|
`${s(11.5)}px ${FONT_SANS}`,
|
|
657
|
-
C.
|
|
657
|
+
C.onSurfaceVariant
|
|
658
658
|
);
|
|
659
659
|
ctx.strokeStyle = C.outlineVariant;
|
|
660
660
|
ctx.beginPath();
|
|
@@ -684,7 +684,7 @@ function drawBoardTable(ctx, x, y, w, opts, rowH) {
|
|
|
684
684
|
noX,
|
|
685
685
|
midY,
|
|
686
686
|
`${s(13)}px ${FONT_NUM}`,
|
|
687
|
-
C.
|
|
687
|
+
C.onSurfaceVariant
|
|
688
688
|
);
|
|
689
689
|
const nbX = nb0 + (cols.nb - gridWidth(history.leftHint, "sm")) / 2;
|
|
690
690
|
drawWordGrid(ctx, nbX, midY - s(13), history.leftHint, "sm", 0);
|
|
@@ -698,7 +698,7 @@ function drawBoardTable(ctx, x, y, w, opts, rowH) {
|
|
|
698
698
|
const hashW = textWidth("#", s(13));
|
|
699
699
|
const rankBlock = hashW + s(3) + rankWidth;
|
|
700
700
|
const rankLeft = rk0 + (cols.rk - rankBlock) / 2;
|
|
701
|
-
textLeft(ctx, "#", rankLeft, midY, `${s(13)}px ${FONT_NUM}`, C.
|
|
701
|
+
textLeft(ctx, "#", rankLeft, midY, `${s(13)}px ${FONT_NUM}`, C.onSurfaceVariant);
|
|
702
702
|
textLeft(ctx, rankText, rankLeft + hashW + s(3), midY, rankFont, tier.color);
|
|
703
703
|
drawNearBar(ctx, mtX, midY, pct, tier);
|
|
704
704
|
ry += rowH;
|
|
@@ -755,7 +755,7 @@ function renderIntroCard(service, opts) {
|
|
|
755
755
|
textLeft(ctx, "ciyi.裸词 开/关", ix + s(96), y + s(52), `${s(13.5)}px ${FONT_NUM}`, C.onSurface);
|
|
756
756
|
textLeftFit(
|
|
757
757
|
ctx,
|
|
758
|
-
"
|
|
758
|
+
"临时改本频道的续猜方式",
|
|
759
759
|
ix + s(230),
|
|
760
760
|
y + s(52),
|
|
761
761
|
iw - s(268),
|
|
@@ -789,7 +789,7 @@ function renderIntroCard(service, opts) {
|
|
|
789
789
|
ix + s(38),
|
|
790
790
|
y + s(104),
|
|
791
791
|
`${s(12)}px ${FONT_SANS}`,
|
|
792
|
-
C.
|
|
792
|
+
C.onSurfaceVariant
|
|
793
793
|
);
|
|
794
794
|
textLeft(
|
|
795
795
|
ctx,
|
|
@@ -797,7 +797,7 @@ function renderIntroCard(service, opts) {
|
|
|
797
797
|
ix + s(38),
|
|
798
798
|
y + s(126),
|
|
799
799
|
`${s(12)}px ${FONT_SANS}`,
|
|
800
|
-
C.
|
|
800
|
+
C.onSurfaceVariant
|
|
801
801
|
);
|
|
802
802
|
textLeft(
|
|
803
803
|
ctx,
|
|
@@ -828,7 +828,7 @@ function renderIntroCard(service, opts) {
|
|
|
828
828
|
ix + s(22),
|
|
829
829
|
iy + ih - s(30),
|
|
830
830
|
`${s(11.5)}px ${FONT_SANS}`,
|
|
831
|
-
C.
|
|
831
|
+
C.onSurfaceVariant
|
|
832
832
|
);
|
|
833
833
|
});
|
|
834
834
|
}
|
|
@@ -842,11 +842,11 @@ function renderWinCard(service, opts) {
|
|
|
842
842
|
const revealH = s(130);
|
|
843
843
|
drawPanel(ctx, ix + s(22), y, iw - s(44), revealH);
|
|
844
844
|
drawSeal(ctx, ix + iw - s(80), y - s(13), s(42), ["中"]);
|
|
845
|
-
textLeft(ctx, "今日答案", ix + s(38), y + s(24), `${s(11.5)}px ${FONT_SANS}`, C.
|
|
845
|
+
textLeft(ctx, "今日答案", ix + s(38), y + s(24), `${s(11.5)}px ${FONT_SANS}`, C.onSurfaceVariant);
|
|
846
846
|
drawWordGrid(ctx, ix + s(38), y + s(40), opts.answer, "lg");
|
|
847
847
|
const ax = ix + iw - s(310);
|
|
848
848
|
if (opts.neighbors.length) {
|
|
849
|
-
textLeft(ctx, "意思最近的几个词", ax, y + s(24), `${s(11.5)}px ${FONT_SANS}`, C.
|
|
849
|
+
textLeft(ctx, "意思最近的几个词", ax, y + s(24), `${s(11.5)}px ${FONT_SANS}`, C.onSurfaceVariant);
|
|
850
850
|
let nx = ax;
|
|
851
851
|
let ny = y + s(48);
|
|
852
852
|
const chipFont = `${s(14)}px ${FONT_SANS}`;
|
|
@@ -888,7 +888,7 @@ function renderWinCard(service, opts) {
|
|
|
888
888
|
if (stats[i].u) {
|
|
889
889
|
textLeft(ctx, stats[i].u, sx + s(14) + textWidth(stats[i].n, s(23)) + s(3), y + s(26), `${s(12)}px ${FONT_SANS}`, C.onSurfaceVariant);
|
|
890
890
|
}
|
|
891
|
-
textLeft(ctx, stats[i].c, sx + s(14), y + s(44), `${s(10.5)}px ${FONT_SANS}`, C.
|
|
891
|
+
textLeft(ctx, stats[i].c, sx + s(14), y + s(44), `${s(10.5)}px ${FONT_SANS}`, C.onSurfaceVariant);
|
|
892
892
|
}
|
|
893
893
|
const quip = opts.closest === null ? "一击即中,今日无需第二次落笔" : `从 #${opts.closest} 一步跨到 #1`;
|
|
894
894
|
const footerTip = opts.canStartToday ? "ciyi.猜 山水 · 开启今日新题" : "明日零点换新题 · ciyi.排行榜";
|
|
@@ -945,7 +945,7 @@ function renderRankCard(service, opts) {
|
|
|
945
945
|
panelX + panelW / 2,
|
|
946
946
|
y + s(31),
|
|
947
947
|
`${s(13.5)}px ${FONT_SANS}`,
|
|
948
|
-
C.
|
|
948
|
+
C.onSurfaceVariant
|
|
949
949
|
);
|
|
950
950
|
textCenter(
|
|
951
951
|
ctx,
|
|
@@ -953,7 +953,7 @@ function renderRankCard(service, opts) {
|
|
|
953
953
|
panelX + panelW / 2,
|
|
954
954
|
y + s(61),
|
|
955
955
|
`${s(13.5)}px ${FONT_SANS}`,
|
|
956
|
-
C.
|
|
956
|
+
C.onSurfaceVariant
|
|
957
957
|
);
|
|
958
958
|
} else {
|
|
959
959
|
let ry = y;
|
|
@@ -1005,17 +1005,17 @@ function renderRankCard(service, opts) {
|
|
|
1005
1005
|
`700 ${scoreFont}px ${FONT_NUM}`,
|
|
1006
1006
|
C.onSurface
|
|
1007
1007
|
);
|
|
1008
|
-
textRight(ctx, "次", contentRight, midY, `${unitFont}px ${FONT_SANS}`, C.
|
|
1008
|
+
textRight(ctx, "次", contentRight, midY, `${unitFont}px ${FONT_SANS}`, C.onSurfaceVariant);
|
|
1009
1009
|
ry += rowH;
|
|
1010
1010
|
}
|
|
1011
1011
|
if (opts.hidden > 0) {
|
|
1012
1012
|
textLeft(
|
|
1013
1013
|
ctx,
|
|
1014
|
-
|
|
1014
|
+
`…… 另有 ${opts.hidden} 人在榜`,
|
|
1015
1015
|
contentLeft,
|
|
1016
1016
|
ry + s(16),
|
|
1017
1017
|
`${s(11.5)}px ${FONT_SANS}`,
|
|
1018
|
-
C.
|
|
1018
|
+
C.onSurfaceVariant
|
|
1019
1019
|
);
|
|
1020
1020
|
}
|
|
1021
1021
|
}
|
|
@@ -1033,7 +1033,7 @@ function renderRankCard(service, opts) {
|
|
|
1033
1033
|
panelX,
|
|
1034
1034
|
iy + ih - s(30),
|
|
1035
1035
|
`${s(11.5)}px ${FONT_SANS}`,
|
|
1036
|
-
C.
|
|
1036
|
+
C.onSurfaceVariant
|
|
1037
1037
|
);
|
|
1038
1038
|
});
|
|
1039
1039
|
}
|
|
@@ -1050,19 +1050,20 @@ var usage = `## 使用
|
|
|
1050
1050
|
| 指令 | 说明 |
|
|
1051
1051
|
| --- | --- |
|
|
1052
1052
|
| \`ciyi\` | 玩法 |
|
|
1053
|
-
| \`ciyi.猜 <词>\` |
|
|
1053
|
+
| \`ciyi.猜 <词>\` | 开始今日对局并报一个两字词 |
|
|
1054
1054
|
| \`ciyi.裸词 [开/关]\` | 开关本频道的无前缀续猜 |
|
|
1055
1055
|
| \`ciyi.排行榜\` | 累计猜中排行榜 |`;
|
|
1056
1056
|
var inject = { required: ["database"], optional: ["canvas"] };
|
|
1057
1057
|
var Config = import_koishi.Schema.object({
|
|
1058
1058
|
atReply: import_koishi.Schema.boolean().default(false).description("回复时 @ 用户。"),
|
|
1059
1059
|
quoteReply: import_koishi.Schema.boolean().default(false).description("回复时引用消息。"),
|
|
1060
|
-
|
|
1061
|
-
"
|
|
1060
|
+
enableDirectInput: import_koishi.Schema.boolean().default(true).description(
|
|
1061
|
+
"对局中直接发送两字词即可续猜,无需指令前缀。各频道可用「ciyi.裸词」临时切换。"
|
|
1062
1062
|
),
|
|
1063
1063
|
renderImage: import_koishi.Schema.boolean().default(true).description("把猜测板渲染成图片,复用 Koishi Canvas 服务。服务不可用时自动回退为等价文本。"),
|
|
1064
1064
|
maxHistory: import_koishi.Schema.number().default(10).min(0).description("猜测板最多列出的历史条数。最新一次猜测始终会列出。"),
|
|
1065
|
-
maxRank: import_koishi.Schema.number().default(10).min(0).description("排行榜最多显示的人数。")
|
|
1065
|
+
maxRank: import_koishi.Schema.number().default(10).min(0).description("排行榜最多显示的人数。"),
|
|
1066
|
+
retractDelay: import_koishi.Schema.number().min(0).default(0).description("自动撤回延迟(秒),0 表示不撤回。")
|
|
1066
1067
|
});
|
|
1067
1068
|
function getMiddlewareGuess(session) {
|
|
1068
1069
|
const message = session.event.message;
|
|
@@ -1128,9 +1129,9 @@ function apply(ctx, cfg) {
|
|
|
1128
1129
|
);
|
|
1129
1130
|
const logger = ctx.logger("ciyi");
|
|
1130
1131
|
const random = new import_koishi.Random(() => Math.random());
|
|
1131
|
-
const
|
|
1132
|
+
const busy = /* @__PURE__ */ new Set();
|
|
1132
1133
|
const middlewareOverrides = /* @__PURE__ */ new Map();
|
|
1133
|
-
const middlewareOn = /* @__PURE__ */ __name((channelId) => channelId === void 0 ? cfg.
|
|
1134
|
+
const middlewareOn = /* @__PURE__ */ __name((channelId) => channelId === void 0 ? cfg.enableDirectInput : middlewareOverrides.get(channelId) ?? cfg.enableDirectInput, "middlewareOn");
|
|
1134
1135
|
ctx.middleware(async (session, next) => {
|
|
1135
1136
|
if (!session.channelId || !middlewareOn(session.channelId)) return await next();
|
|
1136
1137
|
const guess = getMiddlewareGuess(session);
|
|
@@ -1152,7 +1153,7 @@ function apply(ctx, cfg) {
|
|
|
1152
1153
|
ctx.command("ciyi", "词意 · 按意思远近找词").action(async ({ session }) => {
|
|
1153
1154
|
return await wf(session);
|
|
1154
1155
|
});
|
|
1155
|
-
ctx.command("ciyi.猜 <guess:string>", "
|
|
1156
|
+
ctx.command("ciyi.猜 <guess:string>", "开题并报一个两字词").usage("例:ciyi.猜 山水").action(async ({ session }, guess) => {
|
|
1156
1157
|
return await c(session, guess?.trim());
|
|
1157
1158
|
});
|
|
1158
1159
|
ctx.command("ciyi.排行榜", "查看累计猜中排行榜").action(async ({ session }) => {
|
|
@@ -1160,7 +1161,7 @@ function apply(ctx, cfg) {
|
|
|
1160
1161
|
});
|
|
1161
1162
|
ctx.command("ciyi.裸词 [state:string]", "开关本频道的无前缀续猜").usage("例:ciyi.裸词(切换)· ciyi.裸词 开 · ciyi.裸词 关 · ciyi.裸词 状态").action(async ({ session }, state) => {
|
|
1162
1163
|
const result = resolveMiddlewareSwitch(
|
|
1163
|
-
cfg.
|
|
1164
|
+
cfg.enableDirectInput,
|
|
1164
1165
|
session.channelId === void 0 ? void 0 : middlewareOverrides.get(session.channelId),
|
|
1165
1166
|
state
|
|
1166
1167
|
);
|
|
@@ -1235,7 +1236,7 @@ function apply(ctx, cfg) {
|
|
|
1235
1236
|
__name(bestRank, "bestRank");
|
|
1236
1237
|
function textCard(title, ...sections) {
|
|
1237
1238
|
const body = sections.map((s2) => Array.isArray(s2) ? s2.filter(Boolean).join("\n") : s2).filter((s2) => !!s2 && !!s2.trim()).join("\n\n");
|
|
1238
|
-
return [`▍${title}`,
|
|
1239
|
+
return [`▍${title}`, body].filter(Boolean).join("\n");
|
|
1239
1240
|
}
|
|
1240
1241
|
__name(textCard, "textCard");
|
|
1241
1242
|
function neighborText(hint, side) {
|
|
@@ -1246,7 +1247,7 @@ function apply(ctx, cfg) {
|
|
|
1246
1247
|
function boardText(rows, hidden, attempts) {
|
|
1247
1248
|
const lines = [];
|
|
1248
1249
|
rows.forEach((row, i) => {
|
|
1249
|
-
if (row.gapBefore) lines.push(`
|
|
1250
|
+
if (row.gapBefore) lines.push(` …… 另有 ${row.gapBefore} 词未列`);
|
|
1250
1251
|
const { guess, rank, leftHint, rightHint } = row.history;
|
|
1251
1252
|
const mark = row.fresh ? "▸" : " ";
|
|
1252
1253
|
lines.push(
|
|
@@ -1259,7 +1260,7 @@ function apply(ctx, cfg) {
|
|
|
1259
1260
|
`词意 · 第 ${attempts} 次猜测`,
|
|
1260
1261
|
best === null ? null : `当前最佳 #${best} · ${tierOf(best).name}(${tierOf(best).note})`,
|
|
1261
1262
|
lines,
|
|
1262
|
-
hidden > 0 && !tail ? `
|
|
1263
|
+
hidden > 0 && !tail ? ` …… 另有 ${hidden} 词未列` : null,
|
|
1263
1264
|
"左邻更近答案,右邻更远;? 为隐去的字"
|
|
1264
1265
|
);
|
|
1265
1266
|
}
|
|
@@ -1267,12 +1268,16 @@ function apply(ctx, cfg) {
|
|
|
1267
1268
|
function introText(channelOn) {
|
|
1268
1269
|
return textCard(
|
|
1269
1270
|
"词意 · 按意思远近找词",
|
|
1270
|
-
|
|
1271
|
+
[
|
|
1272
|
+
`每天藏起一个两字词。`,
|
|
1273
|
+
`报一个两字词,回它与答案的语义排名。`,
|
|
1274
|
+
`名次越小越近,#1 就是答案本身。`
|
|
1275
|
+
],
|
|
1271
1276
|
[
|
|
1272
1277
|
`开始 ciyi.猜 山水 开题并报一个两字词`,
|
|
1273
1278
|
channelOn ? `续猜 直接发送两字词 仅限已开题且未结束` : null,
|
|
1274
|
-
|
|
1275
|
-
`切换 ciyi.裸词 开/关
|
|
1279
|
+
`排行榜 ciyi.排行榜 看谁猜中得最多`,
|
|
1280
|
+
`切换 ciyi.裸词 开/关 临时改本频道续猜方式`
|
|
1276
1281
|
].filter(Boolean),
|
|
1277
1282
|
[
|
|
1278
1283
|
`读板 ?好)企业(地? #467 · 沾边`,
|
|
@@ -1284,21 +1289,22 @@ function apply(ctx, cfg) {
|
|
|
1284
1289
|
`亲疏 咫尺 ≤10 毗邻 ≤50 相近 ≤200`,
|
|
1285
1290
|
` 沾边 ≤1000 疏远 ≤5000 天涯 5000+`
|
|
1286
1291
|
],
|
|
1287
|
-
`词库 ${allWords_default.length.toLocaleString()}
|
|
1292
|
+
`词库 ${allWords_default.length.toLocaleString()} 词,一日一词。`
|
|
1288
1293
|
);
|
|
1289
1294
|
}
|
|
1290
1295
|
__name(introText, "introText");
|
|
1291
1296
|
function middlewareSwitchText(o) {
|
|
1292
1297
|
const mark = "✅";
|
|
1293
1298
|
const state = o.on ? "开启" : "停用";
|
|
1294
|
-
const config = cfg.
|
|
1299
|
+
const config = cfg.enableDirectInput ? "开启" : "停用";
|
|
1295
1300
|
if (!o.temporary) {
|
|
1296
|
-
return `${mark} 裸词续猜 ·
|
|
1301
|
+
return `${mark} 裸词续猜 · 跟随插件配置
|
|
1302
|
+
当前${state}。${o.reverted ? "本次已复原。" : ""}`;
|
|
1297
1303
|
}
|
|
1298
1304
|
const hint = o.on ? "开题后直接发送两字词即可续猜" : "续猜改用「ciyi.猜 山水」";
|
|
1299
1305
|
return [
|
|
1300
|
-
`${mark} 裸词续猜 · 本频道临时${state}
|
|
1301
|
-
`${hint};再次发送「ciyi.裸词」复原`
|
|
1306
|
+
`${mark} 裸词续猜 · 本频道临时${state}`,
|
|
1307
|
+
`${hint};插件配置为${config};再次发送「ciyi.裸词」复原`
|
|
1302
1308
|
].join("\n");
|
|
1303
1309
|
}
|
|
1304
1310
|
__name(middlewareSwitchText, "middlewareSwitchText");
|
|
@@ -1312,23 +1318,24 @@ function apply(ctx, cfg) {
|
|
|
1312
1318
|
`累计 ${o.username} 已猜中 ${o.score} 次`,
|
|
1313
1319
|
o.neighbors.length ? `近旁 ${o.neighbors.join(" · ")}` : null
|
|
1314
1320
|
].filter(Boolean),
|
|
1315
|
-
o.canStartToday ? "
|
|
1321
|
+
o.canStartToday ? "继续发送「ciyi.猜 山水」开启今日新题" : "明日零点换新题 · 发送「ciyi.排行榜」看战绩"
|
|
1316
1322
|
);
|
|
1317
1323
|
}
|
|
1318
1324
|
__name(winText, "winText");
|
|
1319
1325
|
function rankText(entries, hidden) {
|
|
1320
1326
|
if (!entries.length) {
|
|
1321
1327
|
return textCard(
|
|
1322
|
-
"
|
|
1323
|
-
"
|
|
1328
|
+
"📋 排行榜还空着",
|
|
1329
|
+
"第一个猜中的人,名字会写在这里。",
|
|
1330
|
+
"发送「ciyi.猜 山水」开一局。"
|
|
1324
1331
|
);
|
|
1325
1332
|
}
|
|
1326
1333
|
return textCard(
|
|
1327
|
-
"词意每日挑战排行榜",
|
|
1334
|
+
"📋 词意每日挑战排行榜",
|
|
1328
1335
|
entries.map(
|
|
1329
1336
|
(e, i) => `${String(i + 1).padStart(2, "0")}. ${e.username || "无名氏"} ${e.score} 次`
|
|
1330
1337
|
),
|
|
1331
|
-
hidden > 0 ?
|
|
1338
|
+
hidden > 0 ? `…… 另有 ${hidden} 人在榜` : null
|
|
1332
1339
|
);
|
|
1333
1340
|
}
|
|
1334
1341
|
__name(rankText, "rankText");
|
|
@@ -1343,16 +1350,33 @@ function apply(ctx, cfg) {
|
|
|
1343
1350
|
}
|
|
1344
1351
|
}
|
|
1345
1352
|
__name(renderCard, "renderCard");
|
|
1353
|
+
const lastMessage = /* @__PURE__ */ new Map();
|
|
1354
|
+
async function send(session, content) {
|
|
1355
|
+
const ids = await session.send(content);
|
|
1356
|
+
const messageId = ids?.[0];
|
|
1357
|
+
if (!cfg.retractDelay || !messageId) return;
|
|
1358
|
+
const previous = lastMessage.get(session.channelId);
|
|
1359
|
+
if (previous) {
|
|
1360
|
+
const passed = Date.now() - previous.timestamp;
|
|
1361
|
+
if (passed < 118e3) {
|
|
1362
|
+
ctx.setTimeout(() => {
|
|
1363
|
+
session.bot.deleteMessage(session.channelId, previous.id).catch((error) => logger.debug("撤回消息 %s 失败:%s", previous.id, error.message));
|
|
1364
|
+
}, Math.max(0, cfg.retractDelay * 1e3 - passed));
|
|
1365
|
+
}
|
|
1366
|
+
}
|
|
1367
|
+
lastMessage.set(session.channelId, { id: messageId, timestamp: Date.now() });
|
|
1368
|
+
}
|
|
1369
|
+
__name(send, "send");
|
|
1346
1370
|
async function sendCard(session, render, fallback) {
|
|
1347
1371
|
const image = await renderCard(render);
|
|
1348
1372
|
const prefix = [];
|
|
1349
1373
|
if (cfg.quoteReply && session.messageId) prefix.push(import_koishi.h.quote(session.messageId));
|
|
1350
1374
|
if (cfg.atReply) prefix.push(import_koishi.h.at(session.userId), (0, import_koishi.h)("p"));
|
|
1351
1375
|
if (image) {
|
|
1352
|
-
await
|
|
1376
|
+
await send(session, [...prefix, image]);
|
|
1353
1377
|
return;
|
|
1354
1378
|
}
|
|
1355
|
-
await
|
|
1379
|
+
await send(session, [...prefix, ...import_koishi.h.normalize(fallback)]);
|
|
1356
1380
|
}
|
|
1357
1381
|
__name(sendCard, "sendCard");
|
|
1358
1382
|
async function wf(session) {
|
|
@@ -1429,6 +1453,18 @@ function apply(ctx, cfg) {
|
|
|
1429
1453
|
return await sendMsg(session, `⚠️ 「${guess}」不在词库里
|
|
1430
1454
|
换个常见些的词试试。`);
|
|
1431
1455
|
}
|
|
1456
|
+
if (session.channelId && busy.has(session.channelId)) {
|
|
1457
|
+
return await sendMsg(session, "⏳ 上一手还在处理\n稍等再发一次。");
|
|
1458
|
+
}
|
|
1459
|
+
if (session.channelId) busy.add(session.channelId);
|
|
1460
|
+
try {
|
|
1461
|
+
return await guessOnce(session, guess);
|
|
1462
|
+
} finally {
|
|
1463
|
+
if (session.channelId) busy.delete(session.channelId);
|
|
1464
|
+
}
|
|
1465
|
+
}
|
|
1466
|
+
__name(c, "c");
|
|
1467
|
+
async function guessOnce(session, guess) {
|
|
1432
1468
|
const gameInfo = await getTodayGame(session);
|
|
1433
1469
|
if (!gameInfo) {
|
|
1434
1470
|
return await sendMsg(
|
|
@@ -1439,7 +1475,7 @@ function apply(ctx, cfg) {
|
|
|
1439
1475
|
if (gameInfo.isOver) {
|
|
1440
1476
|
return await sendMsg(
|
|
1441
1477
|
session,
|
|
1442
|
-
`💡 今日挑战已结束,答案是「${gameInfo.answer}
|
|
1478
|
+
`💡 今日挑战已结束,答案是「${gameInfo.answer}」
|
|
1443
1479
|
明日零点换新题,发送「ciyi.排行榜」看战绩。`
|
|
1444
1480
|
);
|
|
1445
1481
|
}
|
|
@@ -1499,7 +1535,7 @@ function apply(ctx, cfg) {
|
|
|
1499
1535
|
const entry = getHistory(guess, rankList);
|
|
1500
1536
|
if (!entry) {
|
|
1501
1537
|
logger.warn(`「${guess}」不在 ${gameInfo.answer} 的榜单中`);
|
|
1502
|
-
return await sendMsg(session, `⚠️ 「${guess}
|
|
1538
|
+
return await sendMsg(session, `⚠️ 「${guess}」不在今日的榜里
|
|
1503
1539
|
换个词试试。`);
|
|
1504
1540
|
}
|
|
1505
1541
|
const history = [...gameInfo.history, entry];
|
|
@@ -1524,7 +1560,7 @@ function apply(ctx, cfg) {
|
|
|
1524
1560
|
boardText(rows, hidden, history.length)
|
|
1525
1561
|
);
|
|
1526
1562
|
}
|
|
1527
|
-
__name(
|
|
1563
|
+
__name(guessOnce, "guessOnce");
|
|
1528
1564
|
async function fetchCiYi(word) {
|
|
1529
1565
|
const url = `https://ci-ying.oss-cn-zhangjiakou.aliyuncs.com/v1/ci-yi-list/${word}.txt`;
|
|
1530
1566
|
try {
|
|
@@ -1547,7 +1583,7 @@ function apply(ctx, cfg) {
|
|
|
1547
1583
|
const prefix = [];
|
|
1548
1584
|
if (cfg.quoteReply && session.messageId) prefix.push(import_koishi.h.quote(session.messageId));
|
|
1549
1585
|
if (cfg.atReply) prefix.push(import_koishi.h.at(session.userId), (0, import_koishi.h)("p"));
|
|
1550
|
-
await
|
|
1586
|
+
await send(session, [...prefix, ...import_koishi.h.normalize(msg)]);
|
|
1551
1587
|
}
|
|
1552
1588
|
__name(sendMsg, "sendMsg");
|
|
1553
1589
|
}
|