koishi-plugin-sky-blessing 0.2.2 → 0.2.3-beta.1

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/api.d.ts CHANGED
@@ -1,25 +1,41 @@
1
1
  import { Context } from 'koishi';
2
- import { BlessingResult, PluginConfig, ParamMapping } from './types';
2
+ import { BlessingResult, PluginConfig, ParamMapping, BlessingStats } from './types';
3
3
  import { SkyLogger } from './logger';
4
4
  export declare class BlessingAPI {
5
5
  private ctx;
6
6
  private config;
7
7
  private logger;
8
+ private stats;
8
9
  constructor(ctx: Context, // 📡 Koishi 上下文
9
10
  config: PluginConfig);
10
11
  /**
11
12
  * 设置日志器实例
12
13
  */
13
14
  setLogger(logger: SkyLogger): void;
15
+ /**
16
+ * ✅ 验证配置合法性
17
+ */
18
+ private validateConfig;
19
+ /**
20
+ * 📊 记录抽签统计数据
21
+ */
22
+ private recordStats;
23
+ /**
24
+ * 📈 获取统计摘要
25
+ */
26
+ getStatsSummary(): {
27
+ total: number;
28
+ recent: BlessingStats[];
29
+ };
14
30
  /**
15
31
  * 🔄 根据映射配置解析参数值
16
32
  * ⚠️ 重复的 key 只有第一个启用的生效
17
33
  */
18
34
  resolveParams(mappings: ParamMapping[], session: any): Record<string, string>;
19
35
  /**
20
- * 📡 调用 /blessing 端点
36
+ * 📡 调用 /blessing 端点(带计时和统计)
21
37
  */
22
- fetchBlessing(type: 'image' | 'json' | 'json_without_image', params?: Record<string, string>): Promise<BlessingResult | Buffer>;
38
+ fetchBlessing(type: 'image' | 'json' | 'json_without_image', params?: Record<string, string>, commandType?: 'image' | 'text' | 'qq-markdown'): Promise<BlessingResult | Buffer>;
23
39
  /**
24
40
  * 🔄 将 buffer 转为 base64 data URI 格式
25
41
  */
package/lib/index.d.ts CHANGED
@@ -2,7 +2,7 @@ import { Context } from 'koishi';
2
2
  import { PluginConfig } from './types';
3
3
  import { SkyLogger } from './logger';
4
4
  export declare const name = "sky-blessing";
5
- export declare const usage = "\n<h1>Koishi \u63D2\u4EF6\uFF1Asky-blessing \u5149\u9047\u7948\u798F\u7B7E</h1>\n<h2>\uD83C\uDFAF \u529F\u80FD\u7B80\u4ECB</h2>\n<p>\u968F\u673A\u751F\u6210\u5149\u9047\u7948\u798F\u7B7E\u56FE\u7247\u7684 Koishi \u63D2\u4EF6\uFF0C\u652F\u6301\u4E09\u79CD\u8F93\u51FA\u6A21\u5F0F\uFF1A</p>\n<ul>\n <li>\uD83D\uDDBC\uFE0F <b>\u5149\u9047\u62BD\u7B7E\u56FE</b> - \u4EC5\u53D1\u9001\u7948\u798F\u7B7E\u56FE\u7247</li>\n <li>\uD83D\uDCDC <b>\u5149\u9047\u62BD\u7B7E</b> - \u53D1\u9001\u56FE\u7247 + \u6587\u5B57\u5185\u5BB9\uFF08\u8FD0\u52BF\u7B49\u7EA7\u3001\u7ED3\u7F18\u7269\u3001\u7F18\u5F69\u3001\u795D\u798F\u8BED\u7B49\uFF09</li>\n <li>\uD83D\uDCDD <b>\u5149\u9047\u62BD\u7B7Emd</b> - \u53D1\u9001\u56FE\u7247 + Markdown\u683C\u5F0F\uFF08\uD83D\uDCA1 \u4EC5\u9650 QQ \u5E73\u53F0\u53EF\u7528\uFF09</li>\n</ul>\n\n<h2>\uD83D\uDCAC \u4EA4\u6D41\u7FA4\u7EC4</h2>\n<p><del>\uD83D\uDCAC \u63D2\u4EF6\u4F7F\u7528\u95EE\u9898 / \uD83D\uDC1B Bug\u53CD\u9988 / \uD83D\uDC68\u200D \u63D2\u4EF6\u5F00\u53D1\u4EA4\u6D41\uFF0C\u6B22\u8FCE\u52A0\u5165QQ\u7FA4\uFF1A<b>259248174</b> \uD83C\uDF89\uFF08\u8FD9\u4E2A\u7FA4G\u4E86\uFF09</del></p>\n<p>\uD83D\uDCAC \u63D2\u4EF6\u4F7F\u7528\u95EE\u9898 / \uD83D\uDC1B Bug\u53CD\u9988 / \uD83D\uDC68\u200D\uD83D\uDCBB \u63D2\u4EF6\u5F00\u53D1\u4EA4\u6D41\uFF0C\u6B22\u8FCE\u52A0\u5165\u65B0QQ\u7FA4\uFF1A<b>1085190201</b> \uD83C\uDF89</p>\n<p>\uD83D\uDCA1 \u5728\u7FA4\u91CC\u76F4\u63A5\u827E\u7279\u6211\uFF0C\u56DE\u590D\u7684\u66F4\u5FEB\u54E6~ \u2728</p>\n\n<hr>\n\n<h3 style=\"color: #e74c3c;\">\u2699\uFE0F \u524D\u7F6E\u4F9D\u8D56</h3>\n<p>\u672C\u63D2\u4EF6\u9700\u8981\u4EE5\u4E0B\u4F9D\u8D56\u624D\u80FD\u6B63\u5E38\u5DE5\u4F5C\uFF1A</p>\n<ul>\n <li><b style=\"color: #e74c3c;\">http</b> - Koishi \u5185\u7F6E\u670D\u52A1\uFF0C\u7528\u4E8EHTTP\u8BF7\u6C42\u540E\u7AEFAPI <span style=\"color: #e74c3c;\">\u3010\u5FC5\u987B\u3011</span></li>\n</ul>\n\n<h3 style=\"color: #3498db;\">\uD83D\uDD17 \u540E\u7AEF\u670D\u52A1</h3>\n<p>\u672C\u63D2\u4EF6\u9700\u8981\u914D\u5408\u540E\u7AEF\u670D\u52A1\u4F7F\u7528\uFF0C\u8BF7\u5148\u90E8\u7F72\u540E\u7AEF\uFF1A</p>\n<ul>\n <li><a href=\"https://github.com/VincentZyuApps/skyblessings-fastapi-pillow\">GitHub \u540E\u7AEF\u4ED3\u5E93</a></li>\n <li><a href=\"https://gitee.com/vincent-zyu/skyblessings-fastapi-pillow\">Gitee \u540E\u7AEF\u4ED3\u5E93</a></li>\n</ul>\n<p>\u90E8\u7F72\u5B8C\u6210\u540E\uFF0C\u5728\u63D2\u4EF6\u914D\u7F6E\u4E2D\u586B\u5199 <code>backendUrl</code> \u4E3A\u540E\u7AEF\u670D\u52A1\u5730\u5740\u3002</p>\n\n<h3 style=\"color: #2ecc71;\">\uD83C\uDFAE \u547D\u4EE4\u5217\u8868</h3>\n<table border=\"1\" cellpadding=\"5\" cellspacing=\"0\">\n <tr>\n <th>\u547D\u4EE4</th>\n <th>\u63CF\u8FF0</th>\n <th>\u5E73\u53F0\u9650\u5236</th>\n </tr>\n <tr>\n <td><code>\u5149\u9047\u62BD\u7B7E\u56FE</code></td>\n <td>\u83B7\u53D6\u7948\u798F\u7B7E\u56FE\u7247</td>\n <td>\u65E0</td>\n </tr>\n <tr>\n <td><code>\u5149\u9047\u62BD\u7B7E</code></td>\n <td>\u83B7\u53D6\u7948\u798F\u7B7E\u56FE\u7247 + \u6587\u5B57\u8BE6\u60C5</td>\n <td>\u65E0</td>\n </tr>\n <tr>\n <td><code>\u5149\u9047\u62BD\u7B7Emd</code></td>\n <td>\u83B7\u53D6\u7948\u798F\u7B7E\u56FE\u7247 + Markdown\u683C\u5F0F</td>\n <td>\u4EC5QQ\u5E73\u53F0</td>\n </tr>\n</table>\n\n<h3 style=\"color: #f39c12;\">\u2699\uFE0F \u53C2\u6570\u6620\u5C04\u8BF4\u660E</h3>\n<p>\u53EF\u901A\u8FC7\u914D\u7F6E\u5C06 a~e \u4E94\u4E2A\u53C2\u6570\u952E\u6620\u5C04\u5230\u4E0D\u540C\u7684\u4F1A\u8BDD\u4FE1\u606F\uFF0C\u7528\u4E8E\u6784\u5EFA\u540E\u7AEF\u8BF7\u6C42\u7684\u79CD\u5B50\uFF1A</p>\n<ul>\n <li>\uD83C\uDF10 <b>platform</b> - \u5E73\u53F0\u540D\u79F0\uFF08\u5982 onebot\u3001discord\uFF09</li>\n <li>\uD83C\uDD94 <b>userid</b> - \u7528\u6237ID</li>\n <li>\uD83D\uDCC5 <b>date</b> - \u5F53\u524D\u65E5\u671F\uFF08YYYY-MM-DD\uFF09</li>\n <li>\uD83D\uDC64 <b>nickname</b> - \u7528\u6237\u6635\u79F0</li>\n <li>\uD83D\uDDBC\uFE0F <b>avatar_hash</b> - \u5934\u50CFMD5\u54C8\u5E0C\u503C</li>\n</ul>\n<p>\u9ED8\u8BA4\u914D\u7F6E\uFF1Aabc \u542F\u7528\uFF0Cde \u7981\u7528\u3002\u91CD\u590D\u7684 key \u53EA\u6709\u7B2C\u4E00\u4E2A\u542F\u7528\u7684\u4F1A\u751F\u6548\u3002</p>\n\n<h3 style=\"color: #9b59b6;\">\uD83D\uDCCA \u8FD4\u56DE\u5B57\u6BB5\u8BF4\u660E</h3>\n<ul>\n <li><b>fortune_level</b> - \u8FD0\u52BF\u7B49\u7EA7\uFF08\u5982\uFF1A\u5927\u5409\u3001\u4E2D\u5409\u3001\u5C0F\u5409\uFF09</li>\n <li><b>dordas</b> - \u7ED3\u7F18\u7269\uFF08\u5982\uFF1A\u7ED3\u7F18\u7269\uFF1A\u9065\u9CB2\uFF09</li>\n <li><b>dordas_color</b> - \u7F18\u5F69\uFF08\u5982\uFF1A\u7F18\u5F69\uFF1A\u68A7\u679D\u7EFF\uFF09</li>\n <li><b>color_hex</b> - \u989C\u8272\u5341\u516D\u8FDB\u5236\u503C\uFF08\u5982\uFF1A#4fd69e\uFF09</li>\n <li><b>blessing</b> - \u795D\u798F\u8BED</li>\n <li><b>entry</b> - \u5B9C\u5FCC\u63D0\u793A\uFF08\u5982\uFF1A\u5FCC\uFF1A\u4E00\u610F\u5B64\u884C\uFF09</li>\n</ul>\n";
5
+ export declare const usage = "\n<h1>Koishi \u63D2\u4EF6\uFF1Asky-blessing \u5149\u9047\u7948\u798F\u7B7E</h1>\n<h2>\uD83C\uDFAF \u529F\u80FD\u7B80\u4ECB</h2>\n<p>\u968F\u673A\u751F\u6210\u5149\u9047\u7948\u798F\u7B7E\u56FE\u7247\u7684 Koishi \u63D2\u4EF6\uFF0C\u652F\u6301\u4E09\u79CD\u8F93\u51FA\u6A21\u5F0F\uFF1A</p>\n<ul>\n <li>\uD83D\uDDBC\uFE0F <b>\u5149\u9047\u62BD\u7B7E\u56FE</b> - \u4EC5\u53D1\u9001\u7948\u798F\u7B7E\u56FE\u7247</li>\n <li>\uD83D\uDCDC <b>\u5149\u9047\u62BD\u7B7E</b> - \u53D1\u9001\u56FE\u7247 + \u6587\u5B57\u5185\u5BB9\uFF08\u8FD0\u52BF\u7B49\u7EA7\u3001\u7ED3\u7F18\u7269\u3001\u7F18\u5F69\u3001\u795D\u798F\u8BED\u7B49\uFF09</li>\n <li>\uD83D\uDCDD <b>\u5149\u9047\u62BD\u7B7Emd</b> - \u53D1\u9001\u56FE\u7247 + Markdown\u683C\u5F0F\uFF08\uD83D\uDCA1 \u4EC5\u9650 QQ \u5E73\u53F0\u53EF\u7528\uFF09</li>\n</ul>\n\n<h2>\uD83D\uDCAC \u4EA4\u6D41\u7FA4\u7EC4</h2>\n<p><del>\uD83D\uDCAC \u63D2\u4EF6\u4F7F\u7528\u95EE\u9898 / \uD83D\uDC1B Bug\u53CD\u9988 / \uD83D\uDC68\u200D \u63D2\u4EF6\u5F00\u53D1\u4EA4\u6D41\uFF0C\u6B22\u8FCE\u52A0\u5165QQ\u7FA4\uFF1A<b>259248174</b> \uD83C\uDF89\uFF08\u8FD9\u4E2A\u7FA4G\u4E86\uFF09</del></p>\n<p>\uD83D\uDCAC \u63D2\u4EF6\u4F7F\u7528\u95EE\u9898 / \uD83D\uDC1B Bug\u53CD\u9988 / \uD83D\uDC68\u200D\uD83D\uDCBB \u63D2\u4EF6\u5F00\u53D1\u4EA4\u6D41\uFF0C\u6B22\u8FCE\u52A0\u5165\u65B0QQ\u7FA4\uFF1A<b>1085190201</b> \uD83C\uDF89</p>\n<p>\uD83D\uDCA1 \u5728\u7FA4\u91CC\u76F4\u63A5\u827E\u7279\u6211\uFF0C\u56DE\u590D\u7684\u66F4\u5FEB\u54E6~ \u2728</p>\n\n<hr>\n\n<h3 style=\"color: #e74c3c;\">\u2699\uFE0F \u524D\u7F6E\u4F9D\u8D56</h3>\n<p>\u672C\u63D2\u4EF6\u9700\u8981\u4EE5\u4E0B\u4F9D\u8D56\u624D\u80FD\u6B63\u5E38\u5DE5\u4F5C\uFF1A</p>\n<ul>\n <li><b style=\"color: #e74c3c;\">http</b> - Koishi \u5185\u7F6E\u670D\u52A1\uFF0C\u7528\u4E8EHTTP\u8BF7\u6C42\u540E\u7AEFAPI <span style=\"color: #e74c3c;\">\u3010\u5FC5\u987B\u3011</span></li>\n</ul>\n\n<h3 style=\"color: #3498db;\">\uD83D\uDD17 \u540E\u7AEF\u670D\u52A1</h3>\n<p>\u672C\u63D2\u4EF6\u9700\u8981\u914D\u5408\u540E\u7AEF\u670D\u52A1\u4F7F\u7528\uFF0C\u8BF7\u5148\u90E8\u7F72\u540E\u7AEF\uFF1A</p>\n<p>\n <a href=\"https://github.com/VincentZyuApps/skyblessings-fastapi-pillow\">\n <img src=\"https://img.shields.io/badge/GitHub_Backend-181717?style=for-the-badge&logo=github&logoColor=white\" alt=\"GitHub Backend\"/>\n </a>\n <a href=\"https://gitee.com/vincent-zyu/skyblessings-fastapi-pillow\">\n <img src=\"https://img.shields.io/badge/Gitee_Backend-C71D23?style=for-the-badge&logo=gitee&logoColor=white\" alt=\"Gitee Backend\"/>\n </a>\n</p>\n<p>\u90E8\u7F72\u5B8C\u6210\u540E\uFF0C\u5728\u63D2\u4EF6\u914D\u7F6E\u4E2D\u586B\u5199 <code>backendUrl</code> \u4E3A\u540E\u7AEF\u670D\u52A1\u5730\u5740\u3002</p>\n\n<h3 style=\"color: #2ecc71;\">\uD83C\uDFAE \u547D\u4EE4\u5217\u8868</h3>\n<table border=\"1\" cellpadding=\"5\" cellspacing=\"0\">\n <tr>\n <th>\u547D\u4EE4</th>\n <th>\u63CF\u8FF0</th>\n <th>\u5E73\u53F0\u9650\u5236</th>\n </tr>\n <tr>\n <td><code>\u5149\u9047\u62BD\u7B7E\u56FE</code></td>\n <td>\u83B7\u53D6\u7948\u798F\u7B7E\u56FE\u7247</td>\n <td>\u65E0</td>\n </tr>\n <tr>\n <td><code>\u5149\u9047\u62BD\u7B7E</code></td>\n <td>\u83B7\u53D6\u7948\u798F\u7B7E\u56FE\u7247 + \u6587\u5B57\u8BE6\u60C5</td>\n <td>\u65E0</td>\n </tr>\n <tr>\n <td><code>\u5149\u9047\u62BD\u7B7Emd</code></td>\n <td>\u83B7\u53D6\u7948\u798F\u7B7E\u56FE\u7247(\u53EF\u9009) + Markdown\u683C\u5F0F</td>\n <td>\u4EC5QQ\u5E73\u53F0</td>\n </tr>\n</table>\n\n<h3 style=\"color: #f39c12;\">\u2699\uFE0F \u53C2\u6570\u6620\u5C04\u8BF4\u660E</h3>\n<p>\u53EF\u901A\u8FC7\u914D\u7F6E\u5C06 a~e \u4E94\u4E2A\u53C2\u6570\u952E\u6620\u5C04\u5230\u4E0D\u540C\u7684\u4F1A\u8BDD\u4FE1\u606F\uFF0C\u7528\u4E8E\u6784\u5EFA\u540E\u7AEF\u8BF7\u6C42\u7684\u79CD\u5B50\uFF1A</p>\n<ul>\n <li>\uD83C\uDF10 <b>platform</b> - \u5E73\u53F0\u540D\u79F0\uFF08\u5982 onebot\u3001discord\uFF09</li>\n <li>\uD83C\uDD94 <b>userid</b> - \u7528\u6237ID</li>\n <li>\uD83D\uDCC5 <b>date</b> - \u5F53\u524D\u65E5\u671F\uFF08YYYY-MM-DD\uFF09</li>\n <li>\uD83D\uDC64 <b>nickname</b> - \u7528\u6237\u6635\u79F0</li>\n <li>\uD83D\uDDBC\uFE0F <b>avatar_hash</b> - \u5934\u50CFMD5\u54C8\u5E0C\u503C</li>\n</ul>\n<p>\u9ED8\u8BA4\u914D\u7F6E\uFF1Aabc \u542F\u7528\uFF0Cde \u7981\u7528\u3002\u91CD\u590D\u7684 key \u53EA\u6709\u7B2C\u4E00\u4E2A\u542F\u7528\u7684\u4F1A\u751F\u6548\u3002</p>\n\n<h3 style=\"color: #9b59b6;\">\uD83D\uDCCA \u8FD4\u56DE\u5B57\u6BB5\u8BF4\u660E</h3>\n<ul>\n <li><b>fortune_level</b> - \u8FD0\u52BF\u7B49\u7EA7\uFF08\u5982\uFF1A\u5927\u5409\u3001\u4E2D\u5409\u3001\u5C0F\u5409\uFF09</li>\n <li><b>dordas</b> - \u7ED3\u7F18\u7269\uFF08\u5982\uFF1A\u7ED3\u7F18\u7269\uFF1A\u9065\u9CB2\uFF09</li>\n <li><b>dordas_color</b> - \u7F18\u5F69\uFF08\u5982\uFF1A\u7F18\u5F69\uFF1A\u68A7\u679D\u7EFF\uFF09</li>\n <li><b>color_hex</b> - \u989C\u8272\u5341\u516D\u8FDB\u5236\u503C\uFF08\u5982\uFF1A#4fd69e\uFF09</li>\n <li><b>blessing</b> - \u795D\u798F\u8BED</li>\n <li><b>entry</b> - \u5B9C\u5FCC\u63D0\u793A\uFF08\u5982\uFF1A\u5FCC\uFF1A\u4E00\u610F\u5B64\u884C\uFF09</li>\n</ul>\n";
6
6
  export declare const inject: {
7
7
  required: string[];
8
8
  };
package/lib/index.js CHANGED
@@ -70,9 +70,9 @@ var ConfigSchema = import_koishi.Schema.intersect([
70
70
  // 🌐 后端连接设置
71
71
  import_koishi.Schema.object({
72
72
  backendUrl: import_koishi.Schema.string().default("http://127.0.0.1:51205").description("🔗 后端服务地址\n\n💡 可以去这里部署后端: `https://gitee.com/vincent-zyu/skyblessings-fastapi-pillow`"),
73
- sendBase64: import_koishi.Schema.boolean().default(false).description("🖼️ 是否将图片 Base64 编码后发送(关闭则发送 URL 链接)"),
74
73
  enableQuote: import_koishi.Schema.boolean().default(true).description("💬 开启后,本插件发送的所有消息都会引用(回复)触发指令的消息"),
75
- qqMarkdownSendImage: import_koishi.Schema.boolean().default(true).description("🖼️ 「光遇抽签md」命令是否同时发送图片(关闭则仅发送 Markdown 文本)")
74
+ qqMarkdownSendImage: import_koishi.Schema.boolean().default(true).description("🖼️ 「光遇抽签md」命令是否同时发送图片(关闭则仅发送 Markdown 文本)"),
75
+ alignWithTab: import_koishi.Schema.boolean().default(true).description("📏 文字对齐:在冒号前后添加制表符使文本对齐(⚠️ 仅对「光遇抽签」和「光遇抽签md」的文字部分生效,不影响图片)")
76
76
  }).description("🌐 后端设置"),
77
77
  // 📊 参数映射表设置
78
78
  import_koishi.Schema.object({
@@ -114,10 +114,14 @@ var USAGE = `
114
114
 
115
115
  <h3 style="color: #3498db;">🔗 后端服务</h3>
116
116
  <p>本插件需要配合后端服务使用,请先部署后端:</p>
117
- <ul>
118
- <li><a href="https://github.com/VincentZyuApps/skyblessings-fastapi-pillow">GitHub 后端仓库</a></li>
119
- <li><a href="https://gitee.com/vincent-zyu/skyblessings-fastapi-pillow">Gitee 后端仓库</a></li>
120
- </ul>
117
+ <p>
118
+ <a href="https://github.com/VincentZyuApps/skyblessings-fastapi-pillow">
119
+ <img src="https://img.shields.io/badge/GitHub_Backend-181717?style=for-the-badge&logo=github&logoColor=white" alt="GitHub Backend"/>
120
+ </a>
121
+ <a href="https://gitee.com/vincent-zyu/skyblessings-fastapi-pillow">
122
+ <img src="https://img.shields.io/badge/Gitee_Backend-C71D23?style=for-the-badge&logo=gitee&logoColor=white" alt="Gitee Backend"/>
123
+ </a>
124
+ </p>
121
125
  <p>部署完成后,在插件配置中填写 <code>backendUrl</code> 为后端服务地址。</p>
122
126
 
123
127
  <h3 style="color: #2ecc71;">🎮 命令列表</h3>
@@ -139,7 +143,7 @@ var USAGE = `
139
143
  </tr>
140
144
  <tr>
141
145
  <td><code>光遇抽签md</code></td>
142
- <td>获取祈福签图片 + Markdown格式</td>
146
+ <td>获取祈福签图片(可选) + Markdown格式</td>
143
147
  <td>仅QQ平台</td>
144
148
  </tr>
145
149
  </table>
@@ -235,6 +239,7 @@ __name(createLogger, "createLogger");
235
239
  // src/api.ts
236
240
  var crypto = __toESM(require("crypto"));
237
241
  var BlessingAPI = class {
242
+ // 📊 统计数据存储
238
243
  constructor(ctx, config) {
239
244
  this.ctx = ctx;
240
245
  this.config = config;
@@ -244,11 +249,62 @@ var BlessingAPI = class {
244
249
  __name(this, "BlessingAPI");
245
250
  }
246
251
  logger;
252
+ stats = [];
247
253
  /**
248
254
  * 设置日志器实例
249
255
  */
250
256
  setLogger(logger) {
251
257
  this.logger = logger;
258
+ this.validateConfig();
259
+ }
260
+ /**
261
+ * ✅ 验证配置合法性
262
+ */
263
+ validateConfig() {
264
+ try {
265
+ const url = new URL(this.config.backendUrl);
266
+ if (!["http:", "https:"].includes(url.protocol)) {
267
+ this.logger.error(`❌ backendUrl 协议无效: ${this.config.backendUrl} (必须是 http:// 或 https://)`);
268
+ } else {
269
+ this.logger.info(`✅ backendUrl 格式验证通过: ${this.config.backendUrl}`);
270
+ }
271
+ } catch (error) {
272
+ this.logger.error(`❌ backendUrl 格式无效: ${this.config.backendUrl} (${error instanceof Error ? error.message : "未知错误"})`);
273
+ }
274
+ const enabledMappings = this.config.paramMappings.filter((m) => m.enabled);
275
+ const keyMap = /* @__PURE__ */ new Map();
276
+ for (let i = 0; i < enabledMappings.length; i++) {
277
+ const mapping = enabledMappings[i];
278
+ if (keyMap.has(mapping.key)) {
279
+ const firstIndex = keyMap.get(mapping.key);
280
+ this.logger.warn(
281
+ `⚠️ 参数映射存在重复的 key "${mapping.key}":第 ${firstIndex + 1} 行和第 ${i + 1} 行冲突,只有第 ${firstIndex + 1} 行会生效`
282
+ );
283
+ } else {
284
+ keyMap.set(mapping.key, i);
285
+ }
286
+ }
287
+ this.logger.info(`✅ 配置验证完成`);
288
+ }
289
+ /**
290
+ * 📊 记录抽签统计数据
291
+ */
292
+ recordStats(stats) {
293
+ this.stats.push(stats);
294
+ this.logger.debug(`📊 统计数据已记录 (总计: ${this.stats.length} 次抽签)`);
295
+ if (this.stats.length > 1e3) {
296
+ this.stats = this.stats.slice(-1e3);
297
+ }
298
+ }
299
+ /**
300
+ * 📈 获取统计摘要
301
+ */
302
+ getStatsSummary() {
303
+ return {
304
+ total: this.stats.length,
305
+ recent: this.stats.slice(-10)
306
+ // 返回最近10条
307
+ };
252
308
  }
253
309
  /**
254
310
  * 🔄 根据映射配置解析参数值
@@ -257,59 +313,87 @@ var BlessingAPI = class {
257
313
  resolveParams(mappings, session) {
258
314
  const params = {};
259
315
  const seenKeys = /* @__PURE__ */ new Set();
260
- this.logger.info(`[BlessingAPI] 🔍 resolveParams: ${mappings.length} 条映射, session.platform=${session.platform}, userId=${session.userId}`);
316
+ this.logger.debug(`[BlessingAPI] 🔍 resolveParams: ${mappings.length} 条映射, session.platform=${session.platform}, userId=${session.userId}`);
261
317
  for (const mapping of mappings) {
262
318
  if (!mapping.enabled || seenKeys.has(mapping.key)) {
263
- this.logger.info(`[BlessingAPI] ⏭️ 跳过 key=${mapping.key} (enabled=${mapping.enabled}, seen=${seenKeys.has(mapping.key)})`);
319
+ this.logger.debug(`[BlessingAPI] ⏭️ 跳过 key=${mapping.key} (enabled=${mapping.enabled}, seen=${seenKeys.has(mapping.key)})`);
264
320
  continue;
265
321
  }
266
322
  seenKeys.add(mapping.key);
267
323
  switch (mapping.value) {
268
324
  case "platform":
269
325
  params[mapping.key] = session.platform ?? "";
270
- this.logger.info(`[BlessingAPI] 🌐 ${mapping.key}=platform -> "${params[mapping.key]}"`);
326
+ this.logger.debug(`[BlessingAPI] 🌐 ${mapping.key}=platform -> "${params[mapping.key]}"`);
271
327
  break;
272
328
  case "userid":
273
329
  params[mapping.key] = String(session.userId ?? "");
274
- this.logger.info(`[BlessingAPI] 🆔 ${mapping.key}=userid -> "${params[mapping.key]}"`);
330
+ this.logger.debug(`[BlessingAPI] 🆔 ${mapping.key}=userid -> "${params[mapping.key]}"`);
275
331
  break;
276
332
  case "date":
277
333
  params[mapping.key] = (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
278
- this.logger.info(`[BlessingAPI] 📅 ${mapping.key}=date -> "${params[mapping.key]}"`);
334
+ this.logger.debug(`[BlessingAPI] 📅 ${mapping.key}=date -> "${params[mapping.key]}"`);
279
335
  break;
280
336
  case "nickname":
281
337
  params[mapping.key] = session.username ?? "";
282
- this.logger.info(`[BlessingAPI] 👤 ${mapping.key}=nickname -> "${params[mapping.key]}"`);
338
+ this.logger.debug(`[BlessingAPI] 👤 ${mapping.key}=nickname -> "${params[mapping.key]}"`);
283
339
  break;
284
340
  case "avatar_hash":
285
341
  params[mapping.key] = session.avatar ? crypto.createHash("md5").update(session.avatar).digest("hex") : "";
286
- this.logger.info(`[BlessingAPI] 🖼️ ${mapping.key}=avatar_hash -> "${params[mapping.key].substring(0, 8)}..."`);
342
+ this.logger.debug(`[BlessingAPI] 🖼️ ${mapping.key}=avatar_hash -> "${params[mapping.key].substring(0, 8)}..."`);
287
343
  break;
288
344
  }
289
345
  }
290
- this.logger.info(`[BlessingAPI] ✅ 最终参数: ${JSON.stringify(params)}`);
346
+ this.logger.debug(`[BlessingAPI] ✅ 最终参数: ${JSON.stringify(params)}`);
291
347
  return params;
292
348
  }
293
349
  /**
294
- * 📡 调用 /blessing 端点
350
+ * 📡 调用 /blessing 端点(带计时和统计)
295
351
  */
296
- async fetchBlessing(type, params = {}) {
352
+ async fetchBlessing(type, params = {}, commandType = "image") {
297
353
  const url = `${this.config.backendUrl}/blessing`;
298
- this.logger.info(`[BlessingAPI] 🚀 fetchBlessing type=${type} url=${url}`);
299
- if (type === "image") {
300
- const response = await this.ctx.http.get(url, {
301
- responseType: "arraybuffer",
302
- params: { type, ...params }
303
- });
304
- const buf = Buffer.from(response);
305
- this.logger.info(`[BlessingAPI] 🖼️ 图片响应: ${buf.length} bytes`);
306
- return buf;
354
+ const startTime = Date.now();
355
+ this.logger.debug(`[BlessingAPI] 🚀 fetchBlessing type=${type} url=${url}`);
356
+ try {
357
+ let result;
358
+ if (type === "image") {
359
+ const response = await this.ctx.http.get(url, {
360
+ responseType: "arraybuffer",
361
+ params: { type, ...params }
362
+ });
363
+ result = Buffer.from(response);
364
+ this.logger.debug(`[BlessingAPI] 🖼️ 图片响应: ${result.length} bytes`);
365
+ } else {
366
+ const data = await this.ctx.http.get(url, {
367
+ params: { type, ...params }
368
+ });
369
+ result = data;
370
+ const responseTime = Date.now() - startTime;
371
+ if ("fortune_level" in data) {
372
+ const stats = {
373
+ timestamp: Date.now(),
374
+ userId: params.b || "",
375
+ platform: params.a || "",
376
+ username: params.d || void 0,
377
+ fortune_level: data.fortune_level,
378
+ dordas: data.dordas,
379
+ dordas_color: data.dordas_color,
380
+ entry: data.entry,
381
+ responseTime,
382
+ commandType
383
+ };
384
+ this.recordStats(stats);
385
+ this.logger.info(`✨ 抽签结果: ${data.fortune_level} | 结缘物: ${data.dordas} | 耗时: ${responseTime}ms`);
386
+ }
387
+ this.logger.debug(`[BlessingAPI] 📄 JSON响应: fortune_level=${data.fortune_level}`);
388
+ }
389
+ const totalTime = Date.now() - startTime;
390
+ this.logger.debug(`[BlessingAPI] ✅ API 请求成功,总耗时: ${totalTime}ms`);
391
+ return result;
392
+ } catch (error) {
393
+ const totalTime = Date.now() - startTime;
394
+ this.logger.error(`[BlessingAPI] ❌ API 请求失败 (耗时: ${totalTime}ms): ${error instanceof Error ? error.message : String(error)}`);
395
+ throw error;
307
396
  }
308
- const data = await this.ctx.http.get(url, {
309
- params: { type, ...params }
310
- });
311
- this.logger.info(`[BlessingAPI] 📄 JSON响应: fortune_level=${data.fortune_level}`);
312
- return data;
313
397
  }
314
398
  /**
315
399
  * 🔄 将 buffer 转为 base64 data URI 格式
@@ -324,21 +408,15 @@ var import_koishi2 = require("koishi");
324
408
  function registerImageCommand(ctx, config, api, logger) {
325
409
  ctx.command(config.commandNames.image).action(async ({ session }) => {
326
410
  logger.info(`[光遇抽签图] 🎯 命令触发, userId=${session.userId}, platform=${session.platform}`);
327
- logger.info(`[光遇抽签图] ⚙️ 配置: backendUrl=${config.backendUrl}, sendBase64=${config.sendBase64}`);
411
+ logger.info(`[光遇抽签图] ⚙️ 配置: backendUrl=${config.backendUrl}`);
328
412
  logger.info(`[光遇抽签图] 📋 paramMappings: ${JSON.stringify(config.paramMappings)}`);
329
413
  try {
330
414
  const params = api.resolveParams(config.paramMappings, session);
331
415
  logger.info(`[光遇抽签图] ✅ 解析参数: ${JSON.stringify(params)}`);
332
- const imageBuffer = await api.fetchBlessing("image", params);
416
+ const imageBuffer = await api.fetchBlessing("image", params, "image");
333
417
  logger.info(`[光遇抽签图] 🖼️ 图片接收成功, 大小=${imageBuffer.length} bytes`);
334
- let message;
335
- if (config.sendBase64) {
336
- message = (0, import_koishi2.h)("image", { url: api.toBase64Image(imageBuffer) });
337
- } else {
338
- const url = `${config.backendUrl}/blessing?type=image&${new URLSearchParams(params)}`;
339
- logger.info(`[光遇抽签图] 🔗 图片URL: ${url}`);
340
- message = import_koishi2.h.image(url);
341
- }
418
+ const message = (0, import_koishi2.h)("image", { url: api.toBase64Image(imageBuffer) });
419
+ logger.info(`[光遇抽签图] 🖼️ 图片已转换为Base64`);
342
420
  logger.info(`[光遇抽签图] 📤 发送消息中...`);
343
421
  const quotePart = config.enableQuote ? import_koishi2.h.quote(session.messageId) : "";
344
422
  await session.send(`${quotePart}${message}`);
@@ -358,30 +436,27 @@ var import_koishi3 = require("koishi");
358
436
  function registerTextCommand(ctx, config, api, logger) {
359
437
  ctx.command(config.commandNames.text).action(async ({ session }) => {
360
438
  logger.info(`[光遇抽签] 🎯 命令触发, userId=${session.userId}, platform=${session.platform}`);
361
- logger.info(`[光遇抽签] ⚙️ 配置: backendUrl=${config.backendUrl}, sendBase64=${config.sendBase64}`);
439
+ logger.info(`[光遇抽签] ⚙️ 配置: backendUrl=${config.backendUrl}`);
362
440
  try {
363
441
  const params = api.resolveParams(config.paramMappings, session);
364
442
  logger.info(`[光遇抽签] ✅ 解析参数: ${JSON.stringify(params)}`);
365
- const result = await api.fetchBlessing("json", params);
443
+ const result = await api.fetchBlessing("json", params, "text");
366
444
  logger.info(`[光遇抽签] 📄 JSON结果: fortune_level=${result.fortune_level}, dordas=${result.dordas}`);
445
+ const TAB = config.alignWithTab ? " " : "";
367
446
  const textParts = [
368
- `🎋 ${result.fortune_level}`,
369
- result.dordas,
370
- `${result.dordas_color}`,
371
- `「${result.blessing}」`,
372
- `${result.entry}`
447
+ `🎋 ${result.fortune_level} ✨`,
448
+ `${result.dordas.split(":")[0]}:${TAB}${result.dordas.split(":")[1] || ""}`,
449
+ `${result.dordas_color.split(":")[0]}:${TAB}${result.dordas_color.split(":")[1] || ""}`,
450
+ `背景色:${TAB}\`${result.color_hex}\``,
451
+ "",
452
+ `「${result.blessing}」
453
+ `,
454
+ `${result.entry.split(":")[0]}:${TAB}${result.entry.split(":")[1] || ""}`
373
455
  ];
374
- let imageSegment;
375
- if (config.sendBase64 && result.image_base64) {
376
- logger.info(`[光遇抽签] 🖼️ 使用 JSON 中的 base64 图片`);
377
- imageSegment = (0, import_koishi3.h)("image", {
378
- url: `data:image/png;base64,${result.image_base64}`
379
- });
380
- } else {
381
- logger.info(`[光遇抽签] 📡 单独请求图片`);
382
- const imageBuffer = await api.fetchBlessing("image", params);
383
- imageSegment = (0, import_koishi3.h)("image", { url: api.toBase64Image(imageBuffer) });
384
- }
456
+ logger.info(`[光遇抽签] 🖼️ 使用 JSON 中的 base64 图片`);
457
+ const imageSegment = (0, import_koishi3.h)("image", {
458
+ url: `data:image/png;base64,${result.image_base64}`
459
+ });
385
460
  logger.info(`[光遇抽签] 📤 发送消息中...`);
386
461
  const quotePart = config.enableQuote ? import_koishi3.h.quote(session.messageId) : "";
387
462
  await session.send(`${quotePart}${imageSegment}
@@ -411,7 +486,7 @@ function registerQQMarkdownCommand(ctx, config, api, logger) {
411
486
  try {
412
487
  const params = api.resolveParams(config.paramMappings, session);
413
488
  logger.info(`[光遇抽签md] ✅ 解析参数: ${JSON.stringify(params)}`);
414
- const result = await api.fetchBlessing("json", params);
489
+ const result = await api.fetchBlessing("json", params, "qq-markdown");
415
490
  logger.info(`[光遇抽签md] 📄 JSON结果: fortune_level=${result.fortune_level}`);
416
491
  const extractLabelAndValue = /* @__PURE__ */ __name((text) => {
417
492
  const idx = text.indexOf(":");
@@ -421,25 +496,21 @@ function registerQQMarkdownCommand(ctx, config, api, logger) {
421
496
  const [dordasLabel, dordasValue] = extractLabelAndValue(result.dordas);
422
497
  const [colorLabel, colorValue] = extractLabelAndValue(result.dordas_color);
423
498
  const [entryLabel, entryValue] = extractLabelAndValue(result.entry);
424
- const markdownContent = `# 🎋 ${result.fortune_level}
499
+ const TAB = config.alignWithTab ? " " : "";
500
+ const markdownContent = `# 🎋 ${result.fortune_level} ✨
425
501
 
426
- **${dordasLabel}**:${dordasValue}
427
- **${colorLabel}**:${colorValue}
428
- **🎨 色值**:\`${result.color_hex}\`
502
+ **${dordasLabel}**:${TAB}${dordasValue}
503
+ **${colorLabel}**:${TAB}${colorValue}
504
+ **背景色**:${TAB}\`${result.color_hex}\`
429
505
 
430
- > ${result.blessing}
506
+ > 「${result.blessing}
431
507
 
432
- **${entryLabel}**:${entryValue}`;
508
+ **${entryLabel}**:${TAB}${entryValue}`;
433
509
  logger.info(`[光遇抽签md] 📄 Markdown内容: ${markdownContent}`);
434
- let imageSegment;
435
- if (config.sendBase64 && result.image_base64) {
436
- imageSegment = (0, import_koishi4.h)("image", {
437
- url: `data:image/png;base64,${result.image_base64}`
438
- });
439
- } else {
440
- const imageBuffer = await api.fetchBlessing("image", params);
441
- imageSegment = (0, import_koishi4.h)("image", { url: api.toBase64Image(imageBuffer) });
442
- }
510
+ logger.info(`[光遇抽签md] 🖼️ 使用 JSON 中的 base64 图片`);
511
+ const imageSegment = (0, import_koishi4.h)("image", {
512
+ url: `data:image/png;base64,${result.image_base64}`
513
+ });
443
514
  logger.info(`[光遇抽签md] 📤 发送图片中...`);
444
515
  const quotePart = config.enableQuote ? import_koishi4.h.quote(session.messageId) : "";
445
516
  await session.send(`${quotePart}${imageSegment}`);
package/lib/types.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- export declare const USAGE = "\n<h1>Koishi \u63D2\u4EF6\uFF1Asky-blessing \u5149\u9047\u7948\u798F\u7B7E</h1>\n<h2>\uD83C\uDFAF \u529F\u80FD\u7B80\u4ECB</h2>\n<p>\u968F\u673A\u751F\u6210\u5149\u9047\u7948\u798F\u7B7E\u56FE\u7247\u7684 Koishi \u63D2\u4EF6\uFF0C\u652F\u6301\u4E09\u79CD\u8F93\u51FA\u6A21\u5F0F\uFF1A</p>\n<ul>\n <li>\uD83D\uDDBC\uFE0F <b>\u5149\u9047\u62BD\u7B7E\u56FE</b> - \u4EC5\u53D1\u9001\u7948\u798F\u7B7E\u56FE\u7247</li>\n <li>\uD83D\uDCDC <b>\u5149\u9047\u62BD\u7B7E</b> - \u53D1\u9001\u56FE\u7247 + \u6587\u5B57\u5185\u5BB9\uFF08\u8FD0\u52BF\u7B49\u7EA7\u3001\u7ED3\u7F18\u7269\u3001\u7F18\u5F69\u3001\u795D\u798F\u8BED\u7B49\uFF09</li>\n <li>\uD83D\uDCDD <b>\u5149\u9047\u62BD\u7B7Emd</b> - \u53D1\u9001\u56FE\u7247 + Markdown\u683C\u5F0F\uFF08\uD83D\uDCA1 \u4EC5\u9650 QQ \u5E73\u53F0\u53EF\u7528\uFF09</li>\n</ul>\n\n<h2>\uD83D\uDCAC \u4EA4\u6D41\u7FA4\u7EC4</h2>\n<p><del>\uD83D\uDCAC \u63D2\u4EF6\u4F7F\u7528\u95EE\u9898 / \uD83D\uDC1B Bug\u53CD\u9988 / \uD83D\uDC68\u200D \u63D2\u4EF6\u5F00\u53D1\u4EA4\u6D41\uFF0C\u6B22\u8FCE\u52A0\u5165QQ\u7FA4\uFF1A<b>259248174</b> \uD83C\uDF89\uFF08\u8FD9\u4E2A\u7FA4G\u4E86\uFF09</del></p>\n<p>\uD83D\uDCAC \u63D2\u4EF6\u4F7F\u7528\u95EE\u9898 / \uD83D\uDC1B Bug\u53CD\u9988 / \uD83D\uDC68\u200D\uD83D\uDCBB \u63D2\u4EF6\u5F00\u53D1\u4EA4\u6D41\uFF0C\u6B22\u8FCE\u52A0\u5165\u65B0QQ\u7FA4\uFF1A<b>1085190201</b> \uD83C\uDF89</p>\n<p>\uD83D\uDCA1 \u5728\u7FA4\u91CC\u76F4\u63A5\u827E\u7279\u6211\uFF0C\u56DE\u590D\u7684\u66F4\u5FEB\u54E6~ \u2728</p>\n\n<hr>\n\n<h3 style=\"color: #e74c3c;\">\u2699\uFE0F \u524D\u7F6E\u4F9D\u8D56</h3>\n<p>\u672C\u63D2\u4EF6\u9700\u8981\u4EE5\u4E0B\u4F9D\u8D56\u624D\u80FD\u6B63\u5E38\u5DE5\u4F5C\uFF1A</p>\n<ul>\n <li><b style=\"color: #e74c3c;\">http</b> - Koishi \u5185\u7F6E\u670D\u52A1\uFF0C\u7528\u4E8EHTTP\u8BF7\u6C42\u540E\u7AEFAPI <span style=\"color: #e74c3c;\">\u3010\u5FC5\u987B\u3011</span></li>\n</ul>\n\n<h3 style=\"color: #3498db;\">\uD83D\uDD17 \u540E\u7AEF\u670D\u52A1</h3>\n<p>\u672C\u63D2\u4EF6\u9700\u8981\u914D\u5408\u540E\u7AEF\u670D\u52A1\u4F7F\u7528\uFF0C\u8BF7\u5148\u90E8\u7F72\u540E\u7AEF\uFF1A</p>\n<ul>\n <li><a href=\"https://github.com/VincentZyuApps/skyblessings-fastapi-pillow\">GitHub \u540E\u7AEF\u4ED3\u5E93</a></li>\n <li><a href=\"https://gitee.com/vincent-zyu/skyblessings-fastapi-pillow\">Gitee \u540E\u7AEF\u4ED3\u5E93</a></li>\n</ul>\n<p>\u90E8\u7F72\u5B8C\u6210\u540E\uFF0C\u5728\u63D2\u4EF6\u914D\u7F6E\u4E2D\u586B\u5199 <code>backendUrl</code> \u4E3A\u540E\u7AEF\u670D\u52A1\u5730\u5740\u3002</p>\n\n<h3 style=\"color: #2ecc71;\">\uD83C\uDFAE \u547D\u4EE4\u5217\u8868</h3>\n<table border=\"1\" cellpadding=\"5\" cellspacing=\"0\">\n <tr>\n <th>\u547D\u4EE4</th>\n <th>\u63CF\u8FF0</th>\n <th>\u5E73\u53F0\u9650\u5236</th>\n </tr>\n <tr>\n <td><code>\u5149\u9047\u62BD\u7B7E\u56FE</code></td>\n <td>\u83B7\u53D6\u7948\u798F\u7B7E\u56FE\u7247</td>\n <td>\u65E0</td>\n </tr>\n <tr>\n <td><code>\u5149\u9047\u62BD\u7B7E</code></td>\n <td>\u83B7\u53D6\u7948\u798F\u7B7E\u56FE\u7247 + \u6587\u5B57\u8BE6\u60C5</td>\n <td>\u65E0</td>\n </tr>\n <tr>\n <td><code>\u5149\u9047\u62BD\u7B7Emd</code></td>\n <td>\u83B7\u53D6\u7948\u798F\u7B7E\u56FE\u7247 + Markdown\u683C\u5F0F</td>\n <td>\u4EC5QQ\u5E73\u53F0</td>\n </tr>\n</table>\n\n<h3 style=\"color: #f39c12;\">\u2699\uFE0F \u53C2\u6570\u6620\u5C04\u8BF4\u660E</h3>\n<p>\u53EF\u901A\u8FC7\u914D\u7F6E\u5C06 a~e \u4E94\u4E2A\u53C2\u6570\u952E\u6620\u5C04\u5230\u4E0D\u540C\u7684\u4F1A\u8BDD\u4FE1\u606F\uFF0C\u7528\u4E8E\u6784\u5EFA\u540E\u7AEF\u8BF7\u6C42\u7684\u79CD\u5B50\uFF1A</p>\n<ul>\n <li>\uD83C\uDF10 <b>platform</b> - \u5E73\u53F0\u540D\u79F0\uFF08\u5982 onebot\u3001discord\uFF09</li>\n <li>\uD83C\uDD94 <b>userid</b> - \u7528\u6237ID</li>\n <li>\uD83D\uDCC5 <b>date</b> - \u5F53\u524D\u65E5\u671F\uFF08YYYY-MM-DD\uFF09</li>\n <li>\uD83D\uDC64 <b>nickname</b> - \u7528\u6237\u6635\u79F0</li>\n <li>\uD83D\uDDBC\uFE0F <b>avatar_hash</b> - \u5934\u50CFMD5\u54C8\u5E0C\u503C</li>\n</ul>\n<p>\u9ED8\u8BA4\u914D\u7F6E\uFF1Aabc \u542F\u7528\uFF0Cde \u7981\u7528\u3002\u91CD\u590D\u7684 key \u53EA\u6709\u7B2C\u4E00\u4E2A\u542F\u7528\u7684\u4F1A\u751F\u6548\u3002</p>\n\n<h3 style=\"color: #9b59b6;\">\uD83D\uDCCA \u8FD4\u56DE\u5B57\u6BB5\u8BF4\u660E</h3>\n<ul>\n <li><b>fortune_level</b> - \u8FD0\u52BF\u7B49\u7EA7\uFF08\u5982\uFF1A\u5927\u5409\u3001\u4E2D\u5409\u3001\u5C0F\u5409\uFF09</li>\n <li><b>dordas</b> - \u7ED3\u7F18\u7269\uFF08\u5982\uFF1A\u7ED3\u7F18\u7269\uFF1A\u9065\u9CB2\uFF09</li>\n <li><b>dordas_color</b> - \u7F18\u5F69\uFF08\u5982\uFF1A\u7F18\u5F69\uFF1A\u68A7\u679D\u7EFF\uFF09</li>\n <li><b>color_hex</b> - \u989C\u8272\u5341\u516D\u8FDB\u5236\u503C\uFF08\u5982\uFF1A#4fd69e\uFF09</li>\n <li><b>blessing</b> - \u795D\u798F\u8BED</li>\n <li><b>entry</b> - \u5B9C\u5FCC\u63D0\u793A\uFF08\u5982\uFF1A\u5FCC\uFF1A\u4E00\u610F\u5B64\u884C\uFF09</li>\n</ul>\n";
1
+ export declare const USAGE = "\n<h1>Koishi \u63D2\u4EF6\uFF1Asky-blessing \u5149\u9047\u7948\u798F\u7B7E</h1>\n<h2>\uD83C\uDFAF \u529F\u80FD\u7B80\u4ECB</h2>\n<p>\u968F\u673A\u751F\u6210\u5149\u9047\u7948\u798F\u7B7E\u56FE\u7247\u7684 Koishi \u63D2\u4EF6\uFF0C\u652F\u6301\u4E09\u79CD\u8F93\u51FA\u6A21\u5F0F\uFF1A</p>\n<ul>\n <li>\uD83D\uDDBC\uFE0F <b>\u5149\u9047\u62BD\u7B7E\u56FE</b> - \u4EC5\u53D1\u9001\u7948\u798F\u7B7E\u56FE\u7247</li>\n <li>\uD83D\uDCDC <b>\u5149\u9047\u62BD\u7B7E</b> - \u53D1\u9001\u56FE\u7247 + \u6587\u5B57\u5185\u5BB9\uFF08\u8FD0\u52BF\u7B49\u7EA7\u3001\u7ED3\u7F18\u7269\u3001\u7F18\u5F69\u3001\u795D\u798F\u8BED\u7B49\uFF09</li>\n <li>\uD83D\uDCDD <b>\u5149\u9047\u62BD\u7B7Emd</b> - \u53D1\u9001\u56FE\u7247 + Markdown\u683C\u5F0F\uFF08\uD83D\uDCA1 \u4EC5\u9650 QQ \u5E73\u53F0\u53EF\u7528\uFF09</li>\n</ul>\n\n<h2>\uD83D\uDCAC \u4EA4\u6D41\u7FA4\u7EC4</h2>\n<p><del>\uD83D\uDCAC \u63D2\u4EF6\u4F7F\u7528\u95EE\u9898 / \uD83D\uDC1B Bug\u53CD\u9988 / \uD83D\uDC68\u200D \u63D2\u4EF6\u5F00\u53D1\u4EA4\u6D41\uFF0C\u6B22\u8FCE\u52A0\u5165QQ\u7FA4\uFF1A<b>259248174</b> \uD83C\uDF89\uFF08\u8FD9\u4E2A\u7FA4G\u4E86\uFF09</del></p>\n<p>\uD83D\uDCAC \u63D2\u4EF6\u4F7F\u7528\u95EE\u9898 / \uD83D\uDC1B Bug\u53CD\u9988 / \uD83D\uDC68\u200D\uD83D\uDCBB \u63D2\u4EF6\u5F00\u53D1\u4EA4\u6D41\uFF0C\u6B22\u8FCE\u52A0\u5165\u65B0QQ\u7FA4\uFF1A<b>1085190201</b> \uD83C\uDF89</p>\n<p>\uD83D\uDCA1 \u5728\u7FA4\u91CC\u76F4\u63A5\u827E\u7279\u6211\uFF0C\u56DE\u590D\u7684\u66F4\u5FEB\u54E6~ \u2728</p>\n\n<hr>\n\n<h3 style=\"color: #e74c3c;\">\u2699\uFE0F \u524D\u7F6E\u4F9D\u8D56</h3>\n<p>\u672C\u63D2\u4EF6\u9700\u8981\u4EE5\u4E0B\u4F9D\u8D56\u624D\u80FD\u6B63\u5E38\u5DE5\u4F5C\uFF1A</p>\n<ul>\n <li><b style=\"color: #e74c3c;\">http</b> - Koishi \u5185\u7F6E\u670D\u52A1\uFF0C\u7528\u4E8EHTTP\u8BF7\u6C42\u540E\u7AEFAPI <span style=\"color: #e74c3c;\">\u3010\u5FC5\u987B\u3011</span></li>\n</ul>\n\n<h3 style=\"color: #3498db;\">\uD83D\uDD17 \u540E\u7AEF\u670D\u52A1</h3>\n<p>\u672C\u63D2\u4EF6\u9700\u8981\u914D\u5408\u540E\u7AEF\u670D\u52A1\u4F7F\u7528\uFF0C\u8BF7\u5148\u90E8\u7F72\u540E\u7AEF\uFF1A</p>\n<p>\n <a href=\"https://github.com/VincentZyuApps/skyblessings-fastapi-pillow\">\n <img src=\"https://img.shields.io/badge/GitHub_Backend-181717?style=for-the-badge&logo=github&logoColor=white\" alt=\"GitHub Backend\"/>\n </a>\n <a href=\"https://gitee.com/vincent-zyu/skyblessings-fastapi-pillow\">\n <img src=\"https://img.shields.io/badge/Gitee_Backend-C71D23?style=for-the-badge&logo=gitee&logoColor=white\" alt=\"Gitee Backend\"/>\n </a>\n</p>\n<p>\u90E8\u7F72\u5B8C\u6210\u540E\uFF0C\u5728\u63D2\u4EF6\u914D\u7F6E\u4E2D\u586B\u5199 <code>backendUrl</code> \u4E3A\u540E\u7AEF\u670D\u52A1\u5730\u5740\u3002</p>\n\n<h3 style=\"color: #2ecc71;\">\uD83C\uDFAE \u547D\u4EE4\u5217\u8868</h3>\n<table border=\"1\" cellpadding=\"5\" cellspacing=\"0\">\n <tr>\n <th>\u547D\u4EE4</th>\n <th>\u63CF\u8FF0</th>\n <th>\u5E73\u53F0\u9650\u5236</th>\n </tr>\n <tr>\n <td><code>\u5149\u9047\u62BD\u7B7E\u56FE</code></td>\n <td>\u83B7\u53D6\u7948\u798F\u7B7E\u56FE\u7247</td>\n <td>\u65E0</td>\n </tr>\n <tr>\n <td><code>\u5149\u9047\u62BD\u7B7E</code></td>\n <td>\u83B7\u53D6\u7948\u798F\u7B7E\u56FE\u7247 + \u6587\u5B57\u8BE6\u60C5</td>\n <td>\u65E0</td>\n </tr>\n <tr>\n <td><code>\u5149\u9047\u62BD\u7B7Emd</code></td>\n <td>\u83B7\u53D6\u7948\u798F\u7B7E\u56FE\u7247(\u53EF\u9009) + Markdown\u683C\u5F0F</td>\n <td>\u4EC5QQ\u5E73\u53F0</td>\n </tr>\n</table>\n\n<h3 style=\"color: #f39c12;\">\u2699\uFE0F \u53C2\u6570\u6620\u5C04\u8BF4\u660E</h3>\n<p>\u53EF\u901A\u8FC7\u914D\u7F6E\u5C06 a~e \u4E94\u4E2A\u53C2\u6570\u952E\u6620\u5C04\u5230\u4E0D\u540C\u7684\u4F1A\u8BDD\u4FE1\u606F\uFF0C\u7528\u4E8E\u6784\u5EFA\u540E\u7AEF\u8BF7\u6C42\u7684\u79CD\u5B50\uFF1A</p>\n<ul>\n <li>\uD83C\uDF10 <b>platform</b> - \u5E73\u53F0\u540D\u79F0\uFF08\u5982 onebot\u3001discord\uFF09</li>\n <li>\uD83C\uDD94 <b>userid</b> - \u7528\u6237ID</li>\n <li>\uD83D\uDCC5 <b>date</b> - \u5F53\u524D\u65E5\u671F\uFF08YYYY-MM-DD\uFF09</li>\n <li>\uD83D\uDC64 <b>nickname</b> - \u7528\u6237\u6635\u79F0</li>\n <li>\uD83D\uDDBC\uFE0F <b>avatar_hash</b> - \u5934\u50CFMD5\u54C8\u5E0C\u503C</li>\n</ul>\n<p>\u9ED8\u8BA4\u914D\u7F6E\uFF1Aabc \u542F\u7528\uFF0Cde \u7981\u7528\u3002\u91CD\u590D\u7684 key \u53EA\u6709\u7B2C\u4E00\u4E2A\u542F\u7528\u7684\u4F1A\u751F\u6548\u3002</p>\n\n<h3 style=\"color: #9b59b6;\">\uD83D\uDCCA \u8FD4\u56DE\u5B57\u6BB5\u8BF4\u660E</h3>\n<ul>\n <li><b>fortune_level</b> - \u8FD0\u52BF\u7B49\u7EA7\uFF08\u5982\uFF1A\u5927\u5409\u3001\u4E2D\u5409\u3001\u5C0F\u5409\uFF09</li>\n <li><b>dordas</b> - \u7ED3\u7F18\u7269\uFF08\u5982\uFF1A\u7ED3\u7F18\u7269\uFF1A\u9065\u9CB2\uFF09</li>\n <li><b>dordas_color</b> - \u7F18\u5F69\uFF08\u5982\uFF1A\u7F18\u5F69\uFF1A\u68A7\u679D\u7EFF\uFF09</li>\n <li><b>color_hex</b> - \u989C\u8272\u5341\u516D\u8FDB\u5236\u503C\uFF08\u5982\uFF1A#4fd69e\uFF09</li>\n <li><b>blessing</b> - \u795D\u798F\u8BED</li>\n <li><b>entry</b> - \u5B9C\u5FCC\u63D0\u793A\uFF08\u5982\uFF1A\u5FCC\uFF1A\u4E00\u610F\u5B64\u884C\uFF09</li>\n</ul>\n";
2
2
  export interface BlessingResult {
3
3
  fortune_level: string;
4
4
  background_id: string;
@@ -21,9 +21,21 @@ export interface PluginConfig {
21
21
  qqMarkdown: string;
22
22
  };
23
23
  backendUrl: string;
24
- sendBase64: boolean;
25
24
  enableQuote: boolean;
26
25
  qqMarkdownSendImage: boolean;
26
+ alignWithTab: boolean;
27
27
  logLevel: 'silent' | 'error' | 'warn' | 'info' | 'debug';
28
28
  paramMappings: ParamMapping[];
29
29
  }
30
+ export interface BlessingStats {
31
+ timestamp: number;
32
+ userId: string;
33
+ platform: string;
34
+ username?: string;
35
+ fortune_level: string;
36
+ dordas: string;
37
+ dordas_color: string;
38
+ entry: string;
39
+ responseTime: number;
40
+ commandType: 'image' | 'text' | 'qq-markdown';
41
+ }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "koishi-plugin-sky-blessing",
3
- "description": "光遇抽签,对接后端",
4
- "version": "0.2.2",
3
+ "description": "🎋 Koishi光遇祈福签插件 | 随机生成Sky: Children of the Light风格祈福签图片 🖼️ 支持三种输出模式:仅图片/图片+文字/QQ原生Markdown 📱 可配置参数映射构建个性化种子 🔧 内置日志级别控制",
4
+ "version": "0.2.3-beta.1+20260408",
5
5
  "main": "lib/index.js",
6
6
  "typings": "lib/index.d.ts",
7
7
  "files": [