koishi-plugin-sky-blessing 0.2.2
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 +27 -0
- package/lib/commands/image.d.ts +5 -0
- package/lib/commands/qq-markdown.d.ts +5 -0
- package/lib/commands/text.d.ts +5 -0
- package/lib/config.d.ts +3 -0
- package/lib/index.d.ts +15 -0
- package/lib/index.js +499 -0
- package/lib/logger.d.ts +47 -0
- package/lib/types.d.ts +29 -0
- package/package.json +20 -0
- package/readme.md +91 -0
package/lib/api.d.ts
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { Context } from 'koishi';
|
|
2
|
+
import { BlessingResult, PluginConfig, ParamMapping } from './types';
|
|
3
|
+
import { SkyLogger } from './logger';
|
|
4
|
+
export declare class BlessingAPI {
|
|
5
|
+
private ctx;
|
|
6
|
+
private config;
|
|
7
|
+
private logger;
|
|
8
|
+
constructor(ctx: Context, // 📡 Koishi 上下文
|
|
9
|
+
config: PluginConfig);
|
|
10
|
+
/**
|
|
11
|
+
* 设置日志器实例
|
|
12
|
+
*/
|
|
13
|
+
setLogger(logger: SkyLogger): void;
|
|
14
|
+
/**
|
|
15
|
+
* 🔄 根据映射配置解析参数值
|
|
16
|
+
* ⚠️ 重复的 key 只有第一个启用的生效
|
|
17
|
+
*/
|
|
18
|
+
resolveParams(mappings: ParamMapping[], session: any): Record<string, string>;
|
|
19
|
+
/**
|
|
20
|
+
* 📡 调用 /blessing 端点
|
|
21
|
+
*/
|
|
22
|
+
fetchBlessing(type: 'image' | 'json' | 'json_without_image', params?: Record<string, string>): Promise<BlessingResult | Buffer>;
|
|
23
|
+
/**
|
|
24
|
+
* 🔄 将 buffer 转为 base64 data URI 格式
|
|
25
|
+
*/
|
|
26
|
+
toBase64Image(buffer: Buffer): string;
|
|
27
|
+
}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { Context } from 'koishi';
|
|
2
|
+
import { PluginConfig } from '../types';
|
|
3
|
+
import { BlessingAPI } from '../api';
|
|
4
|
+
import { SkyLogger } from '../logger';
|
|
5
|
+
export declare function registerImageCommand(ctx: Context, config: PluginConfig, api: BlessingAPI, logger: SkyLogger): void;
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { Context } from 'koishi';
|
|
2
|
+
import { PluginConfig } from '../types';
|
|
3
|
+
import { BlessingAPI } from '../api';
|
|
4
|
+
import { SkyLogger } from '../logger';
|
|
5
|
+
export declare function registerQQMarkdownCommand(ctx: Context, config: PluginConfig, api: BlessingAPI, logger: SkyLogger): void;
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { Context } from 'koishi';
|
|
2
|
+
import { PluginConfig } from '../types';
|
|
3
|
+
import { BlessingAPI } from '../api';
|
|
4
|
+
import { SkyLogger } from '../logger';
|
|
5
|
+
export declare function registerTextCommand(ctx: Context, config: PluginConfig, api: BlessingAPI, logger: SkyLogger): void;
|
package/lib/config.d.ts
ADDED
package/lib/index.d.ts
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { Context } from 'koishi';
|
|
2
|
+
import { PluginConfig } from './types';
|
|
3
|
+
import { SkyLogger } from './logger';
|
|
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";
|
|
6
|
+
export declare const inject: {
|
|
7
|
+
required: string[];
|
|
8
|
+
};
|
|
9
|
+
export declare const reusable = true;
|
|
10
|
+
export declare const Config: import("schemastery")<PluginConfig>;
|
|
11
|
+
export declare function apply(ctx: Context, config: PluginConfig): void;
|
|
12
|
+
/**
|
|
13
|
+
* 获取全局 logger 实例
|
|
14
|
+
*/
|
|
15
|
+
export declare function getLogger(): SkyLogger | null;
|
package/lib/index.js
ADDED
|
@@ -0,0 +1,499 @@
|
|
|
1
|
+
var __create = Object.create;
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
6
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
7
|
+
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
|
|
8
|
+
var __export = (target, all) => {
|
|
9
|
+
for (var name2 in all)
|
|
10
|
+
__defProp(target, name2, { get: all[name2], enumerable: true });
|
|
11
|
+
};
|
|
12
|
+
var __copyProps = (to, from, except, desc) => {
|
|
13
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
14
|
+
for (let key of __getOwnPropNames(from))
|
|
15
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
16
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
17
|
+
}
|
|
18
|
+
return to;
|
|
19
|
+
};
|
|
20
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
21
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
22
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
23
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
24
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
25
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
26
|
+
mod
|
|
27
|
+
));
|
|
28
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
29
|
+
|
|
30
|
+
// src/index.ts
|
|
31
|
+
var src_exports = {};
|
|
32
|
+
__export(src_exports, {
|
|
33
|
+
Config: () => Config,
|
|
34
|
+
apply: () => apply,
|
|
35
|
+
getLogger: () => getLogger,
|
|
36
|
+
inject: () => inject,
|
|
37
|
+
name: () => name,
|
|
38
|
+
reusable: () => reusable,
|
|
39
|
+
usage: () => usage
|
|
40
|
+
});
|
|
41
|
+
module.exports = __toCommonJS(src_exports);
|
|
42
|
+
|
|
43
|
+
// src/config.ts
|
|
44
|
+
var import_koishi = require("koishi");
|
|
45
|
+
var PARAM_KEY_OPTIONS = ["a", "b", "c", "d", "e"];
|
|
46
|
+
var PARAM_VALUE_LABELS = [
|
|
47
|
+
{ label: "🌐 平台 (platform)", value: "platform" },
|
|
48
|
+
{ label: "🆔 用户ID (userid)", value: "userid" },
|
|
49
|
+
{ label: "📅 日期 (date)", value: "date" },
|
|
50
|
+
{ label: "👤 昵称 (nickname)", value: "nickname" },
|
|
51
|
+
{ label: "🖼️ 头像哈希 (avatar_hash)", value: "avatar_hash" }
|
|
52
|
+
];
|
|
53
|
+
var DEFAULT_MAPPINGS = [
|
|
54
|
+
{ enabled: true, key: "a", value: "platform" },
|
|
55
|
+
{ enabled: true, key: "b", value: "userid" },
|
|
56
|
+
{ enabled: true, key: "c", value: "date" },
|
|
57
|
+
{ enabled: false, key: "d", value: "nickname" },
|
|
58
|
+
{ enabled: false, key: "e", value: "avatar_hash" }
|
|
59
|
+
];
|
|
60
|
+
var LOG_LEVEL_OPTIONS = ["silent", "error", "warn", "info", "debug"];
|
|
61
|
+
var ConfigSchema = import_koishi.Schema.intersect([
|
|
62
|
+
// 🔧 命令名称设置
|
|
63
|
+
import_koishi.Schema.object({
|
|
64
|
+
commandNames: import_koishi.Schema.object({
|
|
65
|
+
image: import_koishi.Schema.string().default("光遇抽签图").description("🖼️ 仅发送图片的命令名称"),
|
|
66
|
+
text: import_koishi.Schema.string().default("光遇抽签").description("📜 发送图片 + 文字内容的命令名称"),
|
|
67
|
+
qqMarkdown: import_koishi.Schema.string().default("光遇抽签md").description("📝 发送图片 + Markdown 格式的命令名称(💡 仅限 QQ 平台可用)")
|
|
68
|
+
}).description("⚙️ 命令名称设置")
|
|
69
|
+
}).description("⚙️ 命令设置"),
|
|
70
|
+
// 🌐 后端连接设置
|
|
71
|
+
import_koishi.Schema.object({
|
|
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
|
+
enableQuote: import_koishi.Schema.boolean().default(true).description("💬 开启后,本插件发送的所有消息都会引用(回复)触发指令的消息"),
|
|
75
|
+
qqMarkdownSendImage: import_koishi.Schema.boolean().default(true).description("🖼️ 「光遇抽签md」命令是否同时发送图片(关闭则仅发送 Markdown 文本)")
|
|
76
|
+
}).description("🌐 后端设置"),
|
|
77
|
+
// 📊 参数映射表设置
|
|
78
|
+
import_koishi.Schema.object({
|
|
79
|
+
paramMappings: import_koishi.Schema.array(import_koishi.Schema.object({
|
|
80
|
+
enabled: import_koishi.Schema.boolean().default(true).description("✅ 是否启用此行"),
|
|
81
|
+
key: import_koishi.Schema.union(PARAM_KEY_OPTIONS).role("radio").description("🔑 参数键名(a ~ e 五选一)"),
|
|
82
|
+
value: import_koishi.Schema.union(PARAM_VALUE_LABELS.map((o) => o.value)).role("radio").description("📦 参数值来源字段")
|
|
83
|
+
})).role("table").default(DEFAULT_MAPPINGS).description("📋 参数映射表:将 a~e 映射到平台/用户ID/日期等。\n\n⚠️ 重复的 key 只有第一个启用的会生效哦,未启用的行会被自动忽略~")
|
|
84
|
+
}).description("📊 参数映射设置"),
|
|
85
|
+
// 🔧 调试设置
|
|
86
|
+
import_koishi.Schema.object({
|
|
87
|
+
logLevel: import_koishi.Schema.union(LOG_LEVEL_OPTIONS).role("radio").default("info").description("🔊 插件日志级别:silent(静默)/ error(仅错误)/ warn(警告+错误)/ info(常规信息)/ debug(详细调试)")
|
|
88
|
+
}).description("🔧 调试设置")
|
|
89
|
+
]);
|
|
90
|
+
|
|
91
|
+
// src/types.ts
|
|
92
|
+
var USAGE = `
|
|
93
|
+
<h1>Koishi 插件:sky-blessing 光遇祈福签</h1>
|
|
94
|
+
<h2>🎯 功能简介</h2>
|
|
95
|
+
<p>随机生成光遇祈福签图片的 Koishi 插件,支持三种输出模式:</p>
|
|
96
|
+
<ul>
|
|
97
|
+
<li>🖼️ <b>光遇抽签图</b> - 仅发送祈福签图片</li>
|
|
98
|
+
<li>📜 <b>光遇抽签</b> - 发送图片 + 文字内容(运势等级、结缘物、缘彩、祝福语等)</li>
|
|
99
|
+
<li>📝 <b>光遇抽签md</b> - 发送图片 + Markdown格式(💡 仅限 QQ 平台可用)</li>
|
|
100
|
+
</ul>
|
|
101
|
+
|
|
102
|
+
<h2>💬 交流群组</h2>
|
|
103
|
+
<p><del>💬 插件使用问题 / 🐛 Bug反馈 / 👨 插件开发交流,欢迎加入QQ群:<b>259248174</b> 🎉(这个群G了)</del></p>
|
|
104
|
+
<p>💬 插件使用问题 / 🐛 Bug反馈 / 👨💻 插件开发交流,欢迎加入新QQ群:<b>1085190201</b> 🎉</p>
|
|
105
|
+
<p>💡 在群里直接艾特我,回复的更快哦~ ✨</p>
|
|
106
|
+
|
|
107
|
+
<hr>
|
|
108
|
+
|
|
109
|
+
<h3 style="color: #e74c3c;">⚙️ 前置依赖</h3>
|
|
110
|
+
<p>本插件需要以下依赖才能正常工作:</p>
|
|
111
|
+
<ul>
|
|
112
|
+
<li><b style="color: #e74c3c;">http</b> - Koishi 内置服务,用于HTTP请求后端API <span style="color: #e74c3c;">【必须】</span></li>
|
|
113
|
+
</ul>
|
|
114
|
+
|
|
115
|
+
<h3 style="color: #3498db;">🔗 后端服务</h3>
|
|
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>
|
|
121
|
+
<p>部署完成后,在插件配置中填写 <code>backendUrl</code> 为后端服务地址。</p>
|
|
122
|
+
|
|
123
|
+
<h3 style="color: #2ecc71;">🎮 命令列表</h3>
|
|
124
|
+
<table border="1" cellpadding="5" cellspacing="0">
|
|
125
|
+
<tr>
|
|
126
|
+
<th>命令</th>
|
|
127
|
+
<th>描述</th>
|
|
128
|
+
<th>平台限制</th>
|
|
129
|
+
</tr>
|
|
130
|
+
<tr>
|
|
131
|
+
<td><code>光遇抽签图</code></td>
|
|
132
|
+
<td>获取祈福签图片</td>
|
|
133
|
+
<td>无</td>
|
|
134
|
+
</tr>
|
|
135
|
+
<tr>
|
|
136
|
+
<td><code>光遇抽签</code></td>
|
|
137
|
+
<td>获取祈福签图片 + 文字详情</td>
|
|
138
|
+
<td>无</td>
|
|
139
|
+
</tr>
|
|
140
|
+
<tr>
|
|
141
|
+
<td><code>光遇抽签md</code></td>
|
|
142
|
+
<td>获取祈福签图片 + Markdown格式</td>
|
|
143
|
+
<td>仅QQ平台</td>
|
|
144
|
+
</tr>
|
|
145
|
+
</table>
|
|
146
|
+
|
|
147
|
+
<h3 style="color: #f39c12;">⚙️ 参数映射说明</h3>
|
|
148
|
+
<p>可通过配置将 a~e 五个参数键映射到不同的会话信息,用于构建后端请求的种子:</p>
|
|
149
|
+
<ul>
|
|
150
|
+
<li>🌐 <b>platform</b> - 平台名称(如 onebot、discord)</li>
|
|
151
|
+
<li>🆔 <b>userid</b> - 用户ID</li>
|
|
152
|
+
<li>📅 <b>date</b> - 当前日期(YYYY-MM-DD)</li>
|
|
153
|
+
<li>👤 <b>nickname</b> - 用户昵称</li>
|
|
154
|
+
<li>🖼️ <b>avatar_hash</b> - 头像MD5哈希值</li>
|
|
155
|
+
</ul>
|
|
156
|
+
<p>默认配置:abc 启用,de 禁用。重复的 key 只有第一个启用的会生效。</p>
|
|
157
|
+
|
|
158
|
+
<h3 style="color: #9b59b6;">📊 返回字段说明</h3>
|
|
159
|
+
<ul>
|
|
160
|
+
<li><b>fortune_level</b> - 运势等级(如:大吉、中吉、小吉)</li>
|
|
161
|
+
<li><b>dordas</b> - 结缘物(如:结缘物:遥鲲)</li>
|
|
162
|
+
<li><b>dordas_color</b> - 缘彩(如:缘彩:梧枝绿)</li>
|
|
163
|
+
<li><b>color_hex</b> - 颜色十六进制值(如:#4fd69e)</li>
|
|
164
|
+
<li><b>blessing</b> - 祝福语</li>
|
|
165
|
+
<li><b>entry</b> - 宜忌提示(如:忌:一意孤行)</li>
|
|
166
|
+
</ul>
|
|
167
|
+
`;
|
|
168
|
+
|
|
169
|
+
// src/logger.ts
|
|
170
|
+
var LOG_LEVELS = {
|
|
171
|
+
silent: 0,
|
|
172
|
+
error: 1,
|
|
173
|
+
warn: 2,
|
|
174
|
+
info: 3,
|
|
175
|
+
debug: 4
|
|
176
|
+
};
|
|
177
|
+
var SkyLogger = class {
|
|
178
|
+
constructor(ctx, config) {
|
|
179
|
+
this.ctx = ctx;
|
|
180
|
+
this.level = LOG_LEVELS[config.logLevel] ?? LOG_LEVELS.info;
|
|
181
|
+
}
|
|
182
|
+
static {
|
|
183
|
+
__name(this, "SkyLogger");
|
|
184
|
+
}
|
|
185
|
+
level;
|
|
186
|
+
/**
|
|
187
|
+
* 更新日志级别
|
|
188
|
+
*/
|
|
189
|
+
setLevel(level) {
|
|
190
|
+
this.level = LOG_LEVELS[level] ?? LOG_LEVELS.info;
|
|
191
|
+
}
|
|
192
|
+
/**
|
|
193
|
+
* 🔇 静默级别 - 不输出任何日志
|
|
194
|
+
*/
|
|
195
|
+
silent(_message, ..._args) {
|
|
196
|
+
}
|
|
197
|
+
/**
|
|
198
|
+
* ❌ 错误级别
|
|
199
|
+
*/
|
|
200
|
+
error(message, ...args) {
|
|
201
|
+
if (this.level >= LOG_LEVELS.error) {
|
|
202
|
+
this.ctx.logger.error(message, ...args);
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
/**
|
|
206
|
+
* ⚠️ 警告级别
|
|
207
|
+
*/
|
|
208
|
+
warn(message, ...args) {
|
|
209
|
+
if (this.level >= LOG_LEVELS.warn) {
|
|
210
|
+
this.ctx.logger.warn(message, ...args);
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
/**
|
|
214
|
+
* ℹ️ 信息级别
|
|
215
|
+
*/
|
|
216
|
+
info(message, ...args) {
|
|
217
|
+
if (this.level >= LOG_LEVELS.info) {
|
|
218
|
+
this.ctx.logger.info(message, ...args);
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
/**
|
|
222
|
+
* 🐛 调试级别
|
|
223
|
+
*/
|
|
224
|
+
debug(message, ...args) {
|
|
225
|
+
if (this.level >= LOG_LEVELS.debug) {
|
|
226
|
+
this.ctx.logger.info(`[DEBUG] ${message}`, ...args);
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
};
|
|
230
|
+
function createLogger(ctx, config) {
|
|
231
|
+
return new SkyLogger(ctx, config);
|
|
232
|
+
}
|
|
233
|
+
__name(createLogger, "createLogger");
|
|
234
|
+
|
|
235
|
+
// src/api.ts
|
|
236
|
+
var crypto = __toESM(require("crypto"));
|
|
237
|
+
var BlessingAPI = class {
|
|
238
|
+
constructor(ctx, config) {
|
|
239
|
+
this.ctx = ctx;
|
|
240
|
+
this.config = config;
|
|
241
|
+
this.logger = null;
|
|
242
|
+
}
|
|
243
|
+
static {
|
|
244
|
+
__name(this, "BlessingAPI");
|
|
245
|
+
}
|
|
246
|
+
logger;
|
|
247
|
+
/**
|
|
248
|
+
* 设置日志器实例
|
|
249
|
+
*/
|
|
250
|
+
setLogger(logger) {
|
|
251
|
+
this.logger = logger;
|
|
252
|
+
}
|
|
253
|
+
/**
|
|
254
|
+
* 🔄 根据映射配置解析参数值
|
|
255
|
+
* ⚠️ 重复的 key 只有第一个启用的生效
|
|
256
|
+
*/
|
|
257
|
+
resolveParams(mappings, session) {
|
|
258
|
+
const params = {};
|
|
259
|
+
const seenKeys = /* @__PURE__ */ new Set();
|
|
260
|
+
this.logger.info(`[BlessingAPI] 🔍 resolveParams: ${mappings.length} 条映射, session.platform=${session.platform}, userId=${session.userId}`);
|
|
261
|
+
for (const mapping of mappings) {
|
|
262
|
+
if (!mapping.enabled || seenKeys.has(mapping.key)) {
|
|
263
|
+
this.logger.info(`[BlessingAPI] ⏭️ 跳过 key=${mapping.key} (enabled=${mapping.enabled}, seen=${seenKeys.has(mapping.key)})`);
|
|
264
|
+
continue;
|
|
265
|
+
}
|
|
266
|
+
seenKeys.add(mapping.key);
|
|
267
|
+
switch (mapping.value) {
|
|
268
|
+
case "platform":
|
|
269
|
+
params[mapping.key] = session.platform ?? "";
|
|
270
|
+
this.logger.info(`[BlessingAPI] 🌐 ${mapping.key}=platform -> "${params[mapping.key]}"`);
|
|
271
|
+
break;
|
|
272
|
+
case "userid":
|
|
273
|
+
params[mapping.key] = String(session.userId ?? "");
|
|
274
|
+
this.logger.info(`[BlessingAPI] 🆔 ${mapping.key}=userid -> "${params[mapping.key]}"`);
|
|
275
|
+
break;
|
|
276
|
+
case "date":
|
|
277
|
+
params[mapping.key] = (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
|
|
278
|
+
this.logger.info(`[BlessingAPI] 📅 ${mapping.key}=date -> "${params[mapping.key]}"`);
|
|
279
|
+
break;
|
|
280
|
+
case "nickname":
|
|
281
|
+
params[mapping.key] = session.username ?? "";
|
|
282
|
+
this.logger.info(`[BlessingAPI] 👤 ${mapping.key}=nickname -> "${params[mapping.key]}"`);
|
|
283
|
+
break;
|
|
284
|
+
case "avatar_hash":
|
|
285
|
+
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)}..."`);
|
|
287
|
+
break;
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
this.logger.info(`[BlessingAPI] ✅ 最终参数: ${JSON.stringify(params)}`);
|
|
291
|
+
return params;
|
|
292
|
+
}
|
|
293
|
+
/**
|
|
294
|
+
* 📡 调用 /blessing 端点
|
|
295
|
+
*/
|
|
296
|
+
async fetchBlessing(type, params = {}) {
|
|
297
|
+
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;
|
|
307
|
+
}
|
|
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
|
+
}
|
|
314
|
+
/**
|
|
315
|
+
* 🔄 将 buffer 转为 base64 data URI 格式
|
|
316
|
+
*/
|
|
317
|
+
toBase64Image(buffer) {
|
|
318
|
+
return `data:image/png;base64,${buffer.toString("base64")}`;
|
|
319
|
+
}
|
|
320
|
+
};
|
|
321
|
+
|
|
322
|
+
// src/commands/image.ts
|
|
323
|
+
var import_koishi2 = require("koishi");
|
|
324
|
+
function registerImageCommand(ctx, config, api, logger) {
|
|
325
|
+
ctx.command(config.commandNames.image).action(async ({ session }) => {
|
|
326
|
+
logger.info(`[光遇抽签图] 🎯 命令触发, userId=${session.userId}, platform=${session.platform}`);
|
|
327
|
+
logger.info(`[光遇抽签图] ⚙️ 配置: backendUrl=${config.backendUrl}, sendBase64=${config.sendBase64}`);
|
|
328
|
+
logger.info(`[光遇抽签图] 📋 paramMappings: ${JSON.stringify(config.paramMappings)}`);
|
|
329
|
+
try {
|
|
330
|
+
const params = api.resolveParams(config.paramMappings, session);
|
|
331
|
+
logger.info(`[光遇抽签图] ✅ 解析参数: ${JSON.stringify(params)}`);
|
|
332
|
+
const imageBuffer = await api.fetchBlessing("image", params);
|
|
333
|
+
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
|
+
}
|
|
342
|
+
logger.info(`[光遇抽签图] 📤 发送消息中...`);
|
|
343
|
+
const quotePart = config.enableQuote ? import_koishi2.h.quote(session.messageId) : "";
|
|
344
|
+
await session.send(`${quotePart}${message}`);
|
|
345
|
+
logger.info(`[光遇抽签图] ✅ 发送成功`);
|
|
346
|
+
} catch (error) {
|
|
347
|
+
logger.error(`[光遇抽签图] ❌ 错误: ${error?.message || error}`);
|
|
348
|
+
logger.error(`[光遇抽签图] 📚 堆栈: ${error?.stack}`);
|
|
349
|
+
const quotePart = config.enableQuote ? import_koishi2.h.quote(session.messageId) : "";
|
|
350
|
+
await session.send(`${quotePart}图片获取失败了呢~`);
|
|
351
|
+
}
|
|
352
|
+
});
|
|
353
|
+
}
|
|
354
|
+
__name(registerImageCommand, "registerImageCommand");
|
|
355
|
+
|
|
356
|
+
// src/commands/text.ts
|
|
357
|
+
var import_koishi3 = require("koishi");
|
|
358
|
+
function registerTextCommand(ctx, config, api, logger) {
|
|
359
|
+
ctx.command(config.commandNames.text).action(async ({ session }) => {
|
|
360
|
+
logger.info(`[光遇抽签] 🎯 命令触发, userId=${session.userId}, platform=${session.platform}`);
|
|
361
|
+
logger.info(`[光遇抽签] ⚙️ 配置: backendUrl=${config.backendUrl}, sendBase64=${config.sendBase64}`);
|
|
362
|
+
try {
|
|
363
|
+
const params = api.resolveParams(config.paramMappings, session);
|
|
364
|
+
logger.info(`[光遇抽签] ✅ 解析参数: ${JSON.stringify(params)}`);
|
|
365
|
+
const result = await api.fetchBlessing("json", params);
|
|
366
|
+
logger.info(`[光遇抽签] 📄 JSON结果: fortune_level=${result.fortune_level}, dordas=${result.dordas}`);
|
|
367
|
+
const textParts = [
|
|
368
|
+
`🎋 ${result.fortune_level}`,
|
|
369
|
+
result.dordas,
|
|
370
|
+
`${result.dordas_color}`,
|
|
371
|
+
`「${result.blessing}」`,
|
|
372
|
+
`${result.entry}`
|
|
373
|
+
];
|
|
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
|
+
}
|
|
385
|
+
logger.info(`[光遇抽签] 📤 发送消息中...`);
|
|
386
|
+
const quotePart = config.enableQuote ? import_koishi3.h.quote(session.messageId) : "";
|
|
387
|
+
await session.send(`${quotePart}${imageSegment}
|
|
388
|
+
${textParts.join("\n")}`);
|
|
389
|
+
logger.info(`[光遇抽签] ✅ 发送成功`);
|
|
390
|
+
} catch (error) {
|
|
391
|
+
logger.error(`[光遇抽签] ❌ 错误: ${error?.message || error}`);
|
|
392
|
+
logger.error(`[光遇抽签] 📚 堆栈: ${error?.stack}`);
|
|
393
|
+
const quotePart = config.enableQuote ? import_koishi3.h.quote(session.messageId) : "";
|
|
394
|
+
await session.send(`${quotePart}抽签失败了呢~`);
|
|
395
|
+
}
|
|
396
|
+
});
|
|
397
|
+
}
|
|
398
|
+
__name(registerTextCommand, "registerTextCommand");
|
|
399
|
+
|
|
400
|
+
// src/commands/qq-markdown.ts
|
|
401
|
+
var import_koishi4 = require("koishi");
|
|
402
|
+
function registerQQMarkdownCommand(ctx, config, api, logger) {
|
|
403
|
+
ctx.command(config.commandNames.qqMarkdown).action(async ({ session }) => {
|
|
404
|
+
logger.info(`[光遇抽签md] 🎯 命令触发, platform=${session.platform}`);
|
|
405
|
+
if (session.platform !== "qq") {
|
|
406
|
+
logger.warn(`[光遇抽签md] ⛔ 平台拒绝: platform=${session.platform} (非QQ)`);
|
|
407
|
+
const quotePart = config.enableQuote ? import_koishi4.h.quote(session.messageId) : "";
|
|
408
|
+
await session.send(`${quotePart}此命令仅在QQ官方bot平台可用哦~`);
|
|
409
|
+
return;
|
|
410
|
+
}
|
|
411
|
+
try {
|
|
412
|
+
const params = api.resolveParams(config.paramMappings, session);
|
|
413
|
+
logger.info(`[光遇抽签md] ✅ 解析参数: ${JSON.stringify(params)}`);
|
|
414
|
+
const result = await api.fetchBlessing("json", params);
|
|
415
|
+
logger.info(`[光遇抽签md] 📄 JSON结果: fortune_level=${result.fortune_level}`);
|
|
416
|
+
const extractLabelAndValue = /* @__PURE__ */ __name((text) => {
|
|
417
|
+
const idx = text.indexOf(":");
|
|
418
|
+
if (idx === -1) return ["", text];
|
|
419
|
+
return [text.substring(0, idx), text.substring(idx + 1)];
|
|
420
|
+
}, "extractLabelAndValue");
|
|
421
|
+
const [dordasLabel, dordasValue] = extractLabelAndValue(result.dordas);
|
|
422
|
+
const [colorLabel, colorValue] = extractLabelAndValue(result.dordas_color);
|
|
423
|
+
const [entryLabel, entryValue] = extractLabelAndValue(result.entry);
|
|
424
|
+
const markdownContent = `# 🎋 ${result.fortune_level}
|
|
425
|
+
|
|
426
|
+
**${dordasLabel}**:${dordasValue}
|
|
427
|
+
**${colorLabel}**:${colorValue}
|
|
428
|
+
**🎨 色值**:\`${result.color_hex}\`
|
|
429
|
+
|
|
430
|
+
> ${result.blessing}
|
|
431
|
+
|
|
432
|
+
**${entryLabel}**:${entryValue}`;
|
|
433
|
+
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
|
+
}
|
|
443
|
+
logger.info(`[光遇抽签md] 📤 发送图片中...`);
|
|
444
|
+
const quotePart = config.enableQuote ? import_koishi4.h.quote(session.messageId) : "";
|
|
445
|
+
await session.send(`${quotePart}${imageSegment}`);
|
|
446
|
+
logger.info(`[光遇抽签md] 📤 发送Markdown中...`);
|
|
447
|
+
await session.bot.internal.sendMessage(session.channelId, {
|
|
448
|
+
msg_id: session.messageId,
|
|
449
|
+
msg_type: 2,
|
|
450
|
+
markdown: {
|
|
451
|
+
content: markdownContent
|
|
452
|
+
}
|
|
453
|
+
});
|
|
454
|
+
logger.info(`[光遇抽签md] ✅ 发送成功`);
|
|
455
|
+
} catch (error) {
|
|
456
|
+
logger.error(`[光遇抽签md] ❌ 错误: ${error?.message || error}`);
|
|
457
|
+
logger.error(`[光遇抽签md] 📚 堆栈: ${error?.stack}`);
|
|
458
|
+
const quotePart = config.enableQuote ? import_koishi4.h.quote(session.messageId) : "";
|
|
459
|
+
await session.send(`${quotePart}抽签失败了呢~`);
|
|
460
|
+
}
|
|
461
|
+
});
|
|
462
|
+
}
|
|
463
|
+
__name(registerQQMarkdownCommand, "registerQQMarkdownCommand");
|
|
464
|
+
|
|
465
|
+
// src/index.ts
|
|
466
|
+
var name = "sky-blessing";
|
|
467
|
+
var usage = USAGE;
|
|
468
|
+
var inject = {
|
|
469
|
+
required: ["http"]
|
|
470
|
+
};
|
|
471
|
+
var reusable = true;
|
|
472
|
+
var Config = ConfigSchema;
|
|
473
|
+
var globalLogger = null;
|
|
474
|
+
function apply(ctx, config) {
|
|
475
|
+
globalLogger = createLogger(ctx, config);
|
|
476
|
+
globalLogger.info("[sky-blessing] 🚀 插件加载中...");
|
|
477
|
+
globalLogger.debug(`[sky-blessing] ⚙️ 完整配置: ${JSON.stringify(config, null, 2)}`);
|
|
478
|
+
const api = new BlessingAPI(ctx, config);
|
|
479
|
+
api.setLogger(globalLogger);
|
|
480
|
+
registerImageCommand(ctx, config, api, globalLogger);
|
|
481
|
+
registerTextCommand(ctx, config, api, globalLogger);
|
|
482
|
+
registerQQMarkdownCommand(ctx, config, api, globalLogger);
|
|
483
|
+
globalLogger.info("[sky-blessing] ✅ 光遇抽签插件已加载");
|
|
484
|
+
}
|
|
485
|
+
__name(apply, "apply");
|
|
486
|
+
function getLogger() {
|
|
487
|
+
return globalLogger;
|
|
488
|
+
}
|
|
489
|
+
__name(getLogger, "getLogger");
|
|
490
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
491
|
+
0 && (module.exports = {
|
|
492
|
+
Config,
|
|
493
|
+
apply,
|
|
494
|
+
getLogger,
|
|
495
|
+
inject,
|
|
496
|
+
name,
|
|
497
|
+
reusable,
|
|
498
|
+
usage
|
|
499
|
+
});
|
package/lib/logger.d.ts
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { Context } from 'koishi';
|
|
2
|
+
import { PluginConfig } from './types';
|
|
3
|
+
declare const LOG_LEVELS: {
|
|
4
|
+
readonly silent: 0;
|
|
5
|
+
readonly error: 1;
|
|
6
|
+
readonly warn: 2;
|
|
7
|
+
readonly info: 3;
|
|
8
|
+
readonly debug: 4;
|
|
9
|
+
};
|
|
10
|
+
type LogLevel = keyof typeof LOG_LEVELS;
|
|
11
|
+
/**
|
|
12
|
+
* 📝 自定义 Logger 类,支持按级别过滤日志
|
|
13
|
+
*/
|
|
14
|
+
export declare class SkyLogger {
|
|
15
|
+
private ctx;
|
|
16
|
+
private level;
|
|
17
|
+
constructor(ctx: Context, config: PluginConfig);
|
|
18
|
+
/**
|
|
19
|
+
* 更新日志级别
|
|
20
|
+
*/
|
|
21
|
+
setLevel(level: LogLevel): void;
|
|
22
|
+
/**
|
|
23
|
+
* 🔇 静默级别 - 不输出任何日志
|
|
24
|
+
*/
|
|
25
|
+
silent(_message?: any, ..._args: any[]): void;
|
|
26
|
+
/**
|
|
27
|
+
* ❌ 错误级别
|
|
28
|
+
*/
|
|
29
|
+
error(message: any, ...args: any[]): void;
|
|
30
|
+
/**
|
|
31
|
+
* ⚠️ 警告级别
|
|
32
|
+
*/
|
|
33
|
+
warn(message: any, ...args: any[]): void;
|
|
34
|
+
/**
|
|
35
|
+
* ℹ️ 信息级别
|
|
36
|
+
*/
|
|
37
|
+
info(message: any, ...args: any[]): void;
|
|
38
|
+
/**
|
|
39
|
+
* 🐛 调试级别
|
|
40
|
+
*/
|
|
41
|
+
debug(message: any, ...args: any[]): void;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* 🏭 Logger 工厂函数
|
|
45
|
+
*/
|
|
46
|
+
export declare function createLogger(ctx: Context, config: PluginConfig): SkyLogger;
|
|
47
|
+
export {};
|
package/lib/types.d.ts
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
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";
|
|
2
|
+
export interface BlessingResult {
|
|
3
|
+
fortune_level: string;
|
|
4
|
+
background_id: string;
|
|
5
|
+
dordas: string;
|
|
6
|
+
blessing: string;
|
|
7
|
+
entry: string;
|
|
8
|
+
dordas_color: string;
|
|
9
|
+
color_hex: string;
|
|
10
|
+
image_base64?: string;
|
|
11
|
+
}
|
|
12
|
+
export interface ParamMapping {
|
|
13
|
+
enabled: boolean;
|
|
14
|
+
key: 'a' | 'b' | 'c' | 'd' | 'e';
|
|
15
|
+
value: 'platform' | 'userid' | 'date' | 'nickname' | 'avatar_hash';
|
|
16
|
+
}
|
|
17
|
+
export interface PluginConfig {
|
|
18
|
+
commandNames: {
|
|
19
|
+
image: string;
|
|
20
|
+
text: string;
|
|
21
|
+
qqMarkdown: string;
|
|
22
|
+
};
|
|
23
|
+
backendUrl: string;
|
|
24
|
+
sendBase64: boolean;
|
|
25
|
+
enableQuote: boolean;
|
|
26
|
+
qqMarkdownSendImage: boolean;
|
|
27
|
+
logLevel: 'silent' | 'error' | 'warn' | 'info' | 'debug';
|
|
28
|
+
paramMappings: ParamMapping[];
|
|
29
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "koishi-plugin-sky-blessing",
|
|
3
|
+
"description": "光遇抽签,对接后端",
|
|
4
|
+
"version": "0.2.2",
|
|
5
|
+
"main": "lib/index.js",
|
|
6
|
+
"typings": "lib/index.d.ts",
|
|
7
|
+
"files": [
|
|
8
|
+
"lib",
|
|
9
|
+
"dist"
|
|
10
|
+
],
|
|
11
|
+
"license": "MIT",
|
|
12
|
+
"keywords": [
|
|
13
|
+
"chatbot",
|
|
14
|
+
"koishi",
|
|
15
|
+
"plugin"
|
|
16
|
+
],
|
|
17
|
+
"peerDependencies": {
|
|
18
|
+
"koishi": "^4.18.7"
|
|
19
|
+
}
|
|
20
|
+
}
|
package/readme.md
ADDED
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+

|
|
2
|
+
|
|
3
|
+
# koishi-plugin-sky-blessing
|
|
4
|
+
|
|
5
|
+
[](https://www.npmjs.com/package/koishi-plugin-sky-blessing)
|
|
6
|
+
[](https://www.npmjs.com/package/koishi-plugin-sky-blessing)
|
|
7
|
+
[](https://github.com/VincentZyuApps/sky-blessing)
|
|
8
|
+
[](https://gitee.com/vincent-zyu/sky-blessing)
|
|
9
|
+
|
|
10
|
+
<p><del>💬 插件使用问题 / 🐛 Bug反馈 / 👨💻 插件开发交流,欢迎加入QQ群:<b>259248174</b> 🎉(这个群G了)</del></p>
|
|
11
|
+
<p>💬 插件使用问题 / 🐛 Bug反馈 / 👨💻 插件开发交流,欢迎加入新QQ群:<b>1085190201</b> 🎉</p>
|
|
12
|
+
<p>💡 在群里直接艾特我,回复的更快哦~ ✨</p>
|
|
13
|
+
|
|
14
|
+
## 后端服务
|
|
15
|
+
|
|
16
|
+
本插件需要配合后端服务使用:
|
|
17
|
+
|
|
18
|
+
- [](https://github.com/VincentZyuApps/skyblessings-fastapi-pillow)
|
|
19
|
+
- [](https://gitee.com/vincent-zyu/skyblessings-fastapi-pillow)
|
|
20
|
+
|
|
21
|
+
> 💡 请先部署后端服务,然后在插件配置中填写 `backendUrl`
|
|
22
|
+
|
|
23
|
+
## 🎯 功能特性
|
|
24
|
+
|
|
25
|
+
- 🖼️ **光遇抽签图** - 仅发送祈福签图片
|
|
26
|
+
- 📜 **光遇抽签** - 发送图片 + 文字内容(运势等级、结缘物、缘彩、祝福语等)
|
|
27
|
+
- 📝 **光遇抽签md** - 发送图片 + Markdown格式(💡 仅限 QQ 平台可用)
|
|
28
|
+
|
|
29
|
+
## ⚙️ 配置说明
|
|
30
|
+
|
|
31
|
+
### 命令名称设置
|
|
32
|
+
- `光遇抽签图` - 仅发送图片的命令名
|
|
33
|
+
- `光遇抽签` - 发送图片+文字的命令名
|
|
34
|
+
- `光遇抽签md` - 发送图片+Markdown的命令名(仅QQ)
|
|
35
|
+
|
|
36
|
+
### 后端设置
|
|
37
|
+
- `backendUrl` - 后端服务地址(默认: `http://127.0.0.1:51205`)
|
|
38
|
+
- `sendBase64` - 是否将图片 Base64 编码后发送
|
|
39
|
+
- `enableQuote` - 开启后,所有消息都会引用回复触发指令的消息
|
|
40
|
+
|
|
41
|
+
### 参数映射设置
|
|
42
|
+
可配置 a~e 五个参数键的值来源:
|
|
43
|
+
- 🌐 平台 (platform)
|
|
44
|
+
- 🆔 用户ID (userid)
|
|
45
|
+
- 📅 日期 (date)
|
|
46
|
+
- 👤 昵称 (nickname)
|
|
47
|
+
- 🖼️ 头像哈希 (avatar_hash)
|
|
48
|
+
|
|
49
|
+
默认配置:abc 启用,de 禁用
|
|
50
|
+
|
|
51
|
+
## 📸 效果预览
|
|
52
|
+
|
|
53
|
+
### 光遇抽签图
|
|
54
|
+

|
|
55
|
+
|
|
56
|
+
### 光遇抽签
|
|
57
|
+

|
|
58
|
+
|
|
59
|
+
### 光遇抽签md(QQ原生Markdown)
|
|
60
|
+

|
|
61
|
+
|
|
62
|
+
## 🔧 安装方式
|
|
63
|
+
|
|
64
|
+
### 通过 Koishi 市场安装
|
|
65
|
+
在 Koishi 控制台搜索 `sky-blessing` 并安装
|
|
66
|
+
|
|
67
|
+
### 手动安装
|
|
68
|
+
```bash
|
|
69
|
+
cd /path/to/your/koishi/project
|
|
70
|
+
npm install koishi-plugin-sky-blessing
|
|
71
|
+
yarn add koishi-plugin-sky-blessing
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
## 🚀 快速开始
|
|
75
|
+
|
|
76
|
+
1. 部署后端服务(参考后端仓库 README)
|
|
77
|
+
2. 在 Koishi 控制台安装本插件
|
|
78
|
+
3. 配置 `backendUrl` 为后端服务地址
|
|
79
|
+
4. 根据需要调整参数映射配置
|
|
80
|
+
5. 使用命令测试:
|
|
81
|
+
- `光遇抽签图` - 获取图片
|
|
82
|
+
- `光遇抽签` - 获取图片+文字
|
|
83
|
+
- `光遇抽签md` - 获取图片+Markdown(QQ专用)
|
|
84
|
+
|
|
85
|
+
## 📋 API 说明
|
|
86
|
+
|
|
87
|
+
后端提供 `/blessing` 接口:
|
|
88
|
+
- `type=image` - 返回 PNG 图片
|
|
89
|
+
- `type=json` - 返回 JSON(含 base64 图片)
|
|
90
|
+
- `type=json_without_image` - 返回 JSON(不含图片)
|
|
91
|
+
- `a/b/c/d/e` - 可选种子参数,相同组合返回相同结果
|