koishi-plugin-ciyi 1.2.6 → 1.2.8
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 +9 -2
- package/lib/index.js +69 -26
- package/package.json +8 -3
- package/readme.md +1 -1
package/lib/index.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { Context, Schema } from "koishi";
|
|
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\u7B2C\u4E00\u6B21\u731C\u6D4B\
|
|
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 |";
|
|
5
5
|
export declare const inject: {
|
|
6
6
|
required: string[];
|
|
7
7
|
optional: string[];
|
|
@@ -39,4 +39,11 @@ export interface CiyiRank {
|
|
|
39
39
|
score: number;
|
|
40
40
|
}
|
|
41
41
|
export type { History };
|
|
42
|
+
/**
|
|
43
|
+
* 裸词中间件只接受一条完整、无修饰的两字中文纯文本消息。
|
|
44
|
+
* 引用、@、图片、富文本以及机器人消息都可能只是普通聊天的一部分,不能据此猜词。
|
|
45
|
+
*/
|
|
46
|
+
export declare function getMiddlewareGuess(session: Session): string | null;
|
|
47
|
+
/** 裸词只能加入已开始且未封题的游戏,不能开题,也不重复提交旧猜测。 */
|
|
48
|
+
export declare function canHandleMiddlewareGuess(game: Ciyi | null | undefined, guess: string): boolean;
|
|
42
49
|
export declare function apply(ctx: Context, cfg: Config): void;
|
package/lib/index.js
CHANGED
|
@@ -22,6 +22,8 @@ var index_exports = {};
|
|
|
22
22
|
__export(index_exports, {
|
|
23
23
|
Config: () => Config,
|
|
24
24
|
apply: () => apply,
|
|
25
|
+
canHandleMiddlewareGuess: () => canHandleMiddlewareGuess,
|
|
26
|
+
getMiddlewareGuess: () => getMiddlewareGuess,
|
|
25
27
|
inject: () => inject,
|
|
26
28
|
name: () => name,
|
|
27
29
|
usage: () => usage
|
|
@@ -578,7 +580,7 @@ function renderIntroCard(service, opts) {
|
|
|
578
580
|
textLeft(ctx, "ciyi.猜 山水", ix + s(96), y + s(24), `${s(13.5)}px ${FONT_NUM}`, C.ink);
|
|
579
581
|
textLeftFit(
|
|
580
582
|
ctx,
|
|
581
|
-
`开题并报一个两字词${opts.middleware ? "
|
|
583
|
+
`开题并报一个两字词${opts.middleware ? ";开题后可直接发词" : ""}`,
|
|
582
584
|
ix + s(230),
|
|
583
585
|
y + s(24),
|
|
584
586
|
iw - s(268),
|
|
@@ -733,7 +735,9 @@ function renderWinCard(service, opts) {
|
|
|
733
735
|
}
|
|
734
736
|
__name(renderWinCard, "renderWinCard");
|
|
735
737
|
function renderRankCard(service, opts) {
|
|
736
|
-
const innerW = s(
|
|
738
|
+
const innerW = s(640);
|
|
739
|
+
const rankPadX = s(32);
|
|
740
|
+
const rankInnerPad = s(20);
|
|
737
741
|
const headerH = s(87);
|
|
738
742
|
const contentGap = s(20);
|
|
739
743
|
const rowH = s(52);
|
|
@@ -744,17 +748,21 @@ function renderRankCard(service, opts) {
|
|
|
744
748
|
const contentH = opts.entries.length ? opts.entries.length * rowH + hiddenH : emptyH;
|
|
745
749
|
const innerH = headerH + contentGap + contentH + footerGap + footerH;
|
|
746
750
|
return toPng(service, innerW, innerH, (ctx, ix, iy, iw, ih) => {
|
|
751
|
+
const panelX = ix + rankPadX;
|
|
752
|
+
const panelW = iw - rankPadX * 2;
|
|
753
|
+
const contentLeft = panelX + rankInnerPad;
|
|
754
|
+
const contentRight = panelX + panelW - rankInnerPad;
|
|
747
755
|
let y = iy + drawHeader(ctx, ix, iy, iw, "每日挑战 · 累计猜中", {
|
|
748
756
|
big: String(opts.players),
|
|
749
757
|
cap: "上榜人数"
|
|
750
758
|
});
|
|
751
759
|
y += s(20);
|
|
760
|
+
drawPanel(ctx, panelX, y, panelW, contentH);
|
|
752
761
|
if (!opts.entries.length) {
|
|
753
|
-
drawPanel(ctx, ix + s(22), y, iw - s(44), emptyH);
|
|
754
762
|
textCenter(
|
|
755
763
|
ctx,
|
|
756
764
|
"榜上无名。",
|
|
757
|
-
|
|
765
|
+
panelX + panelW / 2,
|
|
758
766
|
y + s(31),
|
|
759
767
|
`${s(13.5)}px ${FONT_SERIF}`,
|
|
760
768
|
C.ink3
|
|
@@ -762,7 +770,7 @@ function renderRankCard(service, opts) {
|
|
|
762
770
|
textCenter(
|
|
763
771
|
ctx,
|
|
764
772
|
"今日第一个猜中的人,会写在这里。",
|
|
765
|
-
|
|
773
|
+
panelX + panelW / 2,
|
|
766
774
|
y + s(61),
|
|
767
775
|
`${s(13.5)}px ${FONT_SERIF}`,
|
|
768
776
|
C.ink3
|
|
@@ -774,17 +782,17 @@ function renderRankCard(service, opts) {
|
|
|
774
782
|
const midY = ry + rowH / 2;
|
|
775
783
|
if (e.me) {
|
|
776
784
|
ctx.fillStyle = "rgba(178,58,46,0.055)";
|
|
777
|
-
ctx.fillRect(
|
|
785
|
+
ctx.fillRect(panelX, ry, panelW, rowH);
|
|
778
786
|
}
|
|
779
787
|
if (i > 0) {
|
|
780
788
|
ctx.strokeStyle = C.rule;
|
|
781
789
|
ctx.beginPath();
|
|
782
|
-
ctx.moveTo(
|
|
783
|
-
ctx.lineTo(
|
|
790
|
+
ctx.moveTo(contentLeft, ry);
|
|
791
|
+
ctx.lineTo(contentRight, ry);
|
|
784
792
|
ctx.stroke();
|
|
785
793
|
}
|
|
786
794
|
const posSize = s(30);
|
|
787
|
-
const px =
|
|
795
|
+
const px = contentLeft;
|
|
788
796
|
const py = midY - posSize / 2;
|
|
789
797
|
const posColors = [
|
|
790
798
|
{ bg: C.seal, fg: "#F7F1E5", border: C.seal },
|
|
@@ -801,12 +809,15 @@ function renderRankCard(service, opts) {
|
|
|
801
809
|
const nameX = px + posSize + s(14);
|
|
802
810
|
const nameFont = `${s(15)}px ${FONT_SERIF}`;
|
|
803
811
|
const score = String(e.score);
|
|
804
|
-
const
|
|
805
|
-
const
|
|
812
|
+
const unitFont = s(11.5);
|
|
813
|
+
const unitW = textWidth("次", unitFont);
|
|
814
|
+
const scoreFont = s(19);
|
|
815
|
+
const scoreRight = contentRight - unitW - s(8);
|
|
816
|
+
const scoreLeft = scoreRight - textWidth(score, scoreFont);
|
|
806
817
|
const meWidth = e.me ? textWidth("我", s(10.5)) + s(18) : 0;
|
|
807
818
|
const fittedName = ellipsize(
|
|
808
819
|
name2,
|
|
809
|
-
Math.max(0, scoreLeft - s(
|
|
820
|
+
Math.max(0, scoreLeft - s(16) - nameX - meWidth),
|
|
810
821
|
s(15)
|
|
811
822
|
);
|
|
812
823
|
textLeft(ctx, fittedName, nameX, midY, nameFont, C.ink);
|
|
@@ -819,17 +830,17 @@ function renderRankCard(service, opts) {
|
|
|
819
830
|
score,
|
|
820
831
|
scoreRight,
|
|
821
832
|
midY,
|
|
822
|
-
`700 ${
|
|
833
|
+
`700 ${scoreFont}px ${FONT_NUM}`,
|
|
823
834
|
C.ink
|
|
824
835
|
);
|
|
825
|
-
textRight(ctx, "次",
|
|
836
|
+
textRight(ctx, "次", contentRight, midY, `${unitFont}px ${FONT_SERIF}`, C.ink3);
|
|
826
837
|
ry += rowH;
|
|
827
838
|
}
|
|
828
839
|
if (opts.hidden > 0) {
|
|
829
840
|
textLeft(
|
|
830
841
|
ctx,
|
|
831
842
|
`⋯ 另有 ${opts.hidden} 人在榜`,
|
|
832
|
-
|
|
843
|
+
contentLeft,
|
|
833
844
|
ry + s(16),
|
|
834
845
|
`${s(11.5)}px ${FONT_SERIF}`,
|
|
835
846
|
C.ink3
|
|
@@ -847,7 +858,7 @@ function renderRankCard(service, opts) {
|
|
|
847
858
|
textLeft(
|
|
848
859
|
ctx,
|
|
849
860
|
"每猜中一日之词,记一次",
|
|
850
|
-
|
|
861
|
+
panelX,
|
|
851
862
|
iy + ih - s(30),
|
|
852
863
|
`${s(11.5)}px ${FONT_SERIF}`,
|
|
853
864
|
C.ink3
|
|
@@ -860,7 +871,7 @@ __name(renderRankCard, "renderRankCard");
|
|
|
860
871
|
var name = "ciyi";
|
|
861
872
|
var usage = `## 使用
|
|
862
873
|
|
|
863
|
-
设置指令别名后,发送 \`ciyi\`
|
|
874
|
+
设置指令别名后,发送 \`ciyi\` 查看玩法。每日藏一个两字词,使用 \`ciyi.猜 <词>\` 提交第一次猜测并开题;开题后可直接发送两字词继续猜测。
|
|
864
875
|
|
|
865
876
|
## 指令
|
|
866
877
|
|
|
@@ -873,11 +884,33 @@ var inject = { required: ["database"], optional: ["canvas"] };
|
|
|
873
884
|
var Config = import_koishi.Schema.object({
|
|
874
885
|
atReply: import_koishi.Schema.boolean().default(false).description("响应时 @"),
|
|
875
886
|
quoteReply: import_koishi.Schema.boolean().default(false).description("响应时引用"),
|
|
876
|
-
isEnableMiddleware: import_koishi.Schema.boolean().default(true).description("
|
|
887
|
+
isEnableMiddleware: import_koishi.Schema.boolean().default(true).description("是否启用中间件(若启用,已开题时可以不使用指令直接猜测)"),
|
|
877
888
|
renderImage: import_koishi.Schema.boolean().default(true).description("渲染图片(复用 Koishi Canvas 服务;不可用时使用等价文本)"),
|
|
878
889
|
maxHistory: import_koishi.Schema.number().default(10).min(0).description("猜测板最多列出的历史条数(最新一次猜测始终会列出)"),
|
|
879
890
|
maxRank: import_koishi.Schema.number().default(10).min(0).description("最大排行榜人数")
|
|
880
891
|
});
|
|
892
|
+
function getMiddlewareGuess(session) {
|
|
893
|
+
const message = session.event.message;
|
|
894
|
+
if (!message || message.quote || session.event.user?.isBot || message.user?.isBot) {
|
|
895
|
+
return null;
|
|
896
|
+
}
|
|
897
|
+
const elements = message.elements ?? [];
|
|
898
|
+
if (elements.length !== 1 || elements[0].type !== "text") {
|
|
899
|
+
return null;
|
|
900
|
+
}
|
|
901
|
+
const text = elements[0].attrs.content;
|
|
902
|
+
if (typeof text !== "string" || text !== text.trim() || Array.from(text).length !== 2 || !/^\p{Script=Han}{2}$/u.test(text) || !allWords_default.includes(text)) {
|
|
903
|
+
return null;
|
|
904
|
+
}
|
|
905
|
+
return text;
|
|
906
|
+
}
|
|
907
|
+
__name(getMiddlewareGuess, "getMiddlewareGuess");
|
|
908
|
+
function canHandleMiddlewareGuess(game, guess) {
|
|
909
|
+
if (!game || game.isOver) return false;
|
|
910
|
+
if (game.guessedHistoryInOneGame?.includes(guess)) return false;
|
|
911
|
+
return guess === game.answer || game.rankList?.includes(guess) === true;
|
|
912
|
+
}
|
|
913
|
+
__name(canHandleMiddlewareGuess, "canHandleMiddlewareGuess");
|
|
881
914
|
function apply(ctx, cfg) {
|
|
882
915
|
ctx.model.extend(
|
|
883
916
|
"ciyi",
|
|
@@ -909,14 +942,21 @@ function apply(ctx, cfg) {
|
|
|
909
942
|
const RULE = "────────────";
|
|
910
943
|
if (cfg.isEnableMiddleware) {
|
|
911
944
|
ctx.middleware(async (session, next) => {
|
|
912
|
-
const
|
|
913
|
-
if (
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
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
|
+
);
|
|
917
957
|
return await next();
|
|
918
958
|
}
|
|
919
|
-
return await session.execute(`ciyi.猜 ${
|
|
959
|
+
return await session.execute(`ciyi.猜 ${guess}`);
|
|
920
960
|
});
|
|
921
961
|
}
|
|
922
962
|
ctx.command("ciyi", "词意(猜词游戏)").action(async ({ session }) => {
|
|
@@ -1018,9 +1058,10 @@ function apply(ctx, cfg) {
|
|
|
1018
1058
|
"词意 · 按意思远近找词",
|
|
1019
1059
|
`每天藏起一个两字词。你报词,我回它与答案的语义排名 —— 名次越小越近,#1 就是答案本身。`,
|
|
1020
1060
|
[
|
|
1021
|
-
`开始 ciyi.猜 山水
|
|
1061
|
+
`开始 ciyi.猜 山水 开题并报一个两字词`,
|
|
1062
|
+
cfg.isEnableMiddleware ? `续猜 直接发送两字词 仅限已开题且未结束` : null,
|
|
1022
1063
|
`排行 ciyi.排行榜 看谁猜中得最多`
|
|
1023
|
-
],
|
|
1064
|
+
].filter(Boolean),
|
|
1024
1065
|
[
|
|
1025
1066
|
`读板 ?好)企业(地? #467 · 沾边`,
|
|
1026
1067
|
` #467 是「企业」与答案的相近名次`,
|
|
@@ -1286,6 +1327,8 @@ __name(apply, "apply");
|
|
|
1286
1327
|
0 && (module.exports = {
|
|
1287
1328
|
Config,
|
|
1288
1329
|
apply,
|
|
1330
|
+
canHandleMiddlewareGuess,
|
|
1331
|
+
getMiddlewareGuess,
|
|
1289
1332
|
inject,
|
|
1290
1333
|
name,
|
|
1291
1334
|
usage
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "koishi-plugin-ciyi",
|
|
3
|
-
"description": "Koishi
|
|
4
|
-
"version": "1.2.
|
|
3
|
+
"description": "Koishi 的词意猜词插件。",
|
|
4
|
+
"version": "1.2.8",
|
|
5
5
|
"main": "lib/index.js",
|
|
6
6
|
"typings": "lib/index.d.ts",
|
|
7
7
|
"files": [
|
|
@@ -41,7 +41,12 @@
|
|
|
41
41
|
"词意"
|
|
42
42
|
],
|
|
43
43
|
"devDependencies": {
|
|
44
|
-
"@koishijs/canvas": "^0.2.0"
|
|
44
|
+
"@koishijs/canvas": "^0.2.0",
|
|
45
|
+
"koishi": "^4.18.11",
|
|
46
|
+
"tsx": "^4.23.13"
|
|
47
|
+
},
|
|
48
|
+
"scripts": {
|
|
49
|
+
"test": "tsx --test test/*.test.ts"
|
|
45
50
|
},
|
|
46
51
|
"peerDependencies": {
|
|
47
52
|
"koishi": "^4.18.11"
|