koishi-plugin-starfx-bot 0.5.1 → 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/index.d.ts +24 -2
- package/lib/index.js +128 -22
- package/package.json +1 -1
- package/readme.md +16 -14
package/lib/index.d.ts
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
|
-
import { Context, h, Schema, Session } from 'koishi';
|
|
1
|
+
import { Context, h, Logger, Schema, Session } from 'koishi';
|
|
2
2
|
export declare const name = "starfx-bot";
|
|
3
3
|
export declare let baseDir: string;
|
|
4
4
|
export declare let assetsDir: string;
|
|
5
|
+
export declare const starfxLogger: Logger;
|
|
6
|
+
export declare const repeatContextMap: Map<string, [string, number]>;
|
|
5
7
|
export interface Config {
|
|
6
8
|
openLock: boolean;
|
|
7
9
|
openSold: boolean;
|
|
@@ -10,6 +12,10 @@ export interface Config {
|
|
|
10
12
|
atNotSayOther: boolean;
|
|
11
13
|
atNotSayProperty: number;
|
|
12
14
|
atNotSayOtherProperty: number;
|
|
15
|
+
record: boolean;
|
|
16
|
+
openRepeat: boolean;
|
|
17
|
+
minRepeatTimes: number;
|
|
18
|
+
repeatPossibility: number;
|
|
13
19
|
replyBot: string;
|
|
14
20
|
iLoveYou: boolean;
|
|
15
21
|
}
|
|
@@ -17,26 +23,42 @@ export declare const Config: Schema<Schemastery.ObjectS<{
|
|
|
17
23
|
openLock: Schema<boolean, boolean>;
|
|
18
24
|
openSold: Schema<boolean, boolean>;
|
|
19
25
|
bangdreamBorder: Schema<boolean, boolean>;
|
|
26
|
+
record: Schema<boolean, boolean>;
|
|
20
27
|
atNotSay: Schema<boolean, boolean>;
|
|
21
28
|
atNotSayProperty: Schema<number, number>;
|
|
22
29
|
atNotSayOther: Schema<boolean, boolean>;
|
|
23
30
|
atNotSayOtherProperty: Schema<number, number>;
|
|
31
|
+
openRepeat: Schema<boolean, boolean>;
|
|
32
|
+
minRepeatTimes: Schema<number, number>;
|
|
33
|
+
repeatPossibility: Schema<number, number>;
|
|
24
34
|
iLoveYou: Schema<boolean, boolean>;
|
|
25
35
|
replyBot: Schema<"关闭" | "无需at" | "必须at", "关闭" | "无需at" | "必须at">;
|
|
26
36
|
}>, {
|
|
27
37
|
openLock: boolean;
|
|
28
38
|
openSold: boolean;
|
|
29
39
|
bangdreamBorder: boolean;
|
|
40
|
+
record: boolean;
|
|
30
41
|
atNotSay: boolean;
|
|
31
42
|
atNotSayProperty: number;
|
|
32
43
|
atNotSayOther: boolean;
|
|
33
44
|
atNotSayOtherProperty: number;
|
|
45
|
+
openRepeat: boolean;
|
|
46
|
+
minRepeatTimes: number;
|
|
47
|
+
repeatPossibility: number;
|
|
34
48
|
iLoveYou: boolean;
|
|
35
49
|
replyBot: "关闭" | "无需at" | "必须at";
|
|
36
50
|
} & import("cosmokit").Dict>;
|
|
37
51
|
export declare const usage = "<h5>StarFreedomX\u7684\u81EA\u7528\u63D2\u4EF6 \u653E\u4E86\u4E00\u4E9B\u5C0F\u529F\u80FD</h5>\n ";
|
|
38
52
|
export declare function apply(ctx: Context, cfg: Config): void;
|
|
39
|
-
export declare function
|
|
53
|
+
export declare function addRecord(ctx: Context, gid: string, avatarUrl: string): Promise<string>;
|
|
54
|
+
export declare function getRecord(gid: string): Promise<string>;
|
|
55
|
+
export declare function getImageSrc(session: Session, param: string, option?: {
|
|
56
|
+
number?: boolean;
|
|
57
|
+
img?: boolean;
|
|
58
|
+
at?: boolean;
|
|
59
|
+
noParam?: boolean;
|
|
60
|
+
quote?: boolean;
|
|
61
|
+
}): Promise<string>;
|
|
40
62
|
export declare function handleBanGDreamConfig(ctx: Context, options: any): Promise<{
|
|
41
63
|
color: string;
|
|
42
64
|
band: string;
|
package/lib/index.js
CHANGED
|
@@ -41,14 +41,18 @@ var require_zh_CN = __commonJS({
|
|
|
41
41
|
var src_exports = {};
|
|
42
42
|
__export(src_exports, {
|
|
43
43
|
Config: () => Config,
|
|
44
|
+
addRecord: () => addRecord,
|
|
44
45
|
apply: () => apply,
|
|
45
46
|
assetsDir: () => assetsDir,
|
|
46
47
|
baseDir: () => baseDir,
|
|
47
48
|
drawLock: () => drawLock,
|
|
48
49
|
drawSold: () => drawSold,
|
|
49
50
|
getImageSrc: () => getImageSrc,
|
|
51
|
+
getRecord: () => getRecord,
|
|
50
52
|
handleBanGDreamConfig: () => handleBanGDreamConfig,
|
|
51
53
|
name: () => name,
|
|
54
|
+
repeatContextMap: () => repeatContextMap,
|
|
55
|
+
starfxLogger: () => starfxLogger,
|
|
52
56
|
usage: () => usage
|
|
53
57
|
});
|
|
54
58
|
module.exports = __toCommonJS(src_exports);
|
|
@@ -56,18 +60,25 @@ var import_koishi = require("koishi");
|
|
|
56
60
|
var import_sharp = __toESM(require("sharp"));
|
|
57
61
|
var fs = __toESM(require("fs"));
|
|
58
62
|
var import_jimp = require("jimp");
|
|
63
|
+
var import_node_path = __toESM(require("node:path"));
|
|
59
64
|
var name = "starfx-bot";
|
|
60
65
|
var baseDir;
|
|
61
66
|
var assetsDir;
|
|
67
|
+
var starfxLogger = new import_koishi.Logger("starfx-bot");
|
|
68
|
+
var repeatContextMap = /* @__PURE__ */ new Map();
|
|
62
69
|
var Config = import_koishi.Schema.intersect([
|
|
63
70
|
import_koishi.Schema.object({
|
|
64
71
|
openLock: import_koishi.Schema.boolean().default(true).description("开启明日方舟封印功能"),
|
|
65
72
|
openSold: import_koishi.Schema.boolean().default(true).description('开启闲鱼"卖掉了"功能'),
|
|
66
73
|
bangdreamBorder: import_koishi.Schema.boolean().default(true).description("开启BanG Dream!边框功能"),
|
|
74
|
+
record: import_koishi.Schema.boolean().default(true).description("开启群语录功能"),
|
|
67
75
|
atNotSay: import_koishi.Schema.boolean().default(true).description("开启‘艾特我又不说话’功能"),
|
|
68
76
|
atNotSayProperty: import_koishi.Schema.number().role("slider").min(0).max(1).step(0.01).default(0.5).description("'艾特我又不说话'回复概率"),
|
|
69
77
|
atNotSayOther: import_koishi.Schema.boolean().default(true).description("开启‘艾特他又不说话’功能"),
|
|
70
78
|
atNotSayOtherProperty: import_koishi.Schema.number().role("slider").min(0).max(1).step(0.01).default(0.5).description("'艾特他又不说话'回复概率"),
|
|
79
|
+
openRepeat: import_koishi.Schema.boolean().default(true).description("开启复读功能"),
|
|
80
|
+
minRepeatTimes: import_koishi.Schema.number().default(2).description("最少重复次数"),
|
|
81
|
+
repeatPossibility: import_koishi.Schema.number().role("slider").min(0).max(1).step(0.01).default(0.3).description("复读发生概率"),
|
|
71
82
|
iLoveYou: import_koishi.Schema.boolean().default(true).description("开启‘我喜欢你’功能"),
|
|
72
83
|
replyBot: import_koishi.Schema.union(["关闭", "无需at", "必须at"]).default("无需at").description("回复‘我才不是机器人!’功能")
|
|
73
84
|
})
|
|
@@ -98,11 +109,49 @@ function apply(ctx, cfg) {
|
|
|
98
109
|
return import_koishi.h.image(imageBase64);
|
|
99
110
|
});
|
|
100
111
|
}
|
|
112
|
+
if (cfg.record) {
|
|
113
|
+
ctx.command("投稿 [param]").action(async ({ session }, param) => {
|
|
114
|
+
const imageSrc = await getImageSrc(
|
|
115
|
+
session,
|
|
116
|
+
param,
|
|
117
|
+
{
|
|
118
|
+
img: true,
|
|
119
|
+
at: false,
|
|
120
|
+
quote: true,
|
|
121
|
+
noParam: false,
|
|
122
|
+
number: false
|
|
123
|
+
}
|
|
124
|
+
);
|
|
125
|
+
if (!imageSrc) {
|
|
126
|
+
return "请发送带图片的指令消息或引用图片消息进行投稿";
|
|
127
|
+
}
|
|
128
|
+
return await addRecord(ctx, session.gid.replace(":", "_"), imageSrc);
|
|
129
|
+
});
|
|
130
|
+
}
|
|
101
131
|
ctx.middleware(async (session, next) => {
|
|
102
132
|
const elements = session.elements;
|
|
133
|
+
if (cfg.openRepeat) {
|
|
134
|
+
const gid = session.gid;
|
|
135
|
+
const content = session.content;
|
|
136
|
+
const groupMap = repeatContextMap.get(gid);
|
|
137
|
+
if (!groupMap || groupMap[0] !== content) {
|
|
138
|
+
repeatContextMap.set(gid, [content, 1]);
|
|
139
|
+
} else {
|
|
140
|
+
if (groupMap[1] !== -1 && ++groupMap[1] >= cfg.minRepeatTimes && import_koishi.Random.bool(cfg.repeatPossibility)) {
|
|
141
|
+
groupMap[1] = -1;
|
|
142
|
+
await session.send(content);
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
}
|
|
103
146
|
await atNotSayReply(cfg, session, elements);
|
|
104
147
|
await replyBot(cfg, session, elements);
|
|
105
148
|
await iLoveYou(cfg, session, elements);
|
|
149
|
+
if (cfg.record && session.content?.startsWith("语录")) {
|
|
150
|
+
const filepath = await getRecord(session.gid.replace(":", "_"));
|
|
151
|
+
starfxLogger.info(`send record: ${filepath}`);
|
|
152
|
+
if (!filepath) return "暂无语录呢";
|
|
153
|
+
return import_koishi.h.image(filepath);
|
|
154
|
+
}
|
|
106
155
|
return next();
|
|
107
156
|
});
|
|
108
157
|
function initAssets() {
|
|
@@ -121,27 +170,80 @@ function apply(ctx, cfg) {
|
|
|
121
170
|
__name(initAssets, "initAssets");
|
|
122
171
|
}
|
|
123
172
|
__name(apply, "apply");
|
|
124
|
-
async function
|
|
125
|
-
|
|
173
|
+
async function addRecord(ctx, gid, avatarUrl) {
|
|
174
|
+
const recordDir = `${assetsDir}/record/${gid}`;
|
|
175
|
+
const avatarBuffer = await ctx.http.get(avatarUrl, { responseType: "arraybuffer" });
|
|
176
|
+
saveImage(avatarBuffer, recordDir);
|
|
177
|
+
return "添加成功!";
|
|
178
|
+
}
|
|
179
|
+
__name(addRecord, "addRecord");
|
|
180
|
+
async function getRecord(gid) {
|
|
181
|
+
const recordDir = `${assetsDir}/record/${gid}`;
|
|
182
|
+
const files = fs.readdirSync(recordDir);
|
|
183
|
+
return files?.length ? import_node_path.default.join(recordDir, import_koishi.Random.pick(files)) : null;
|
|
184
|
+
}
|
|
185
|
+
__name(getRecord, "getRecord");
|
|
186
|
+
function getTodayPrefix() {
|
|
187
|
+
const now = /* @__PURE__ */ new Date();
|
|
188
|
+
const yyyy = now.getFullYear();
|
|
189
|
+
const mm = String(now.getMonth() + 1).padStart(2, "0");
|
|
190
|
+
const dd = String(now.getDate()).padStart(2, "0");
|
|
191
|
+
return `${yyyy}${mm}${dd}`;
|
|
192
|
+
}
|
|
193
|
+
__name(getTodayPrefix, "getTodayPrefix");
|
|
194
|
+
function getNextSequenceNumber(directory, prefix) {
|
|
195
|
+
const files = fs.existsSync(directory) ? fs.readdirSync(directory) : [];
|
|
196
|
+
const regex = new RegExp(`^${prefix}-(\\d+)\\.jpg$`);
|
|
197
|
+
let maxNum = 0;
|
|
198
|
+
files.forEach((file) => {
|
|
199
|
+
const match = file.match(regex);
|
|
200
|
+
if (match) {
|
|
201
|
+
const num = parseInt(match[1], 10);
|
|
202
|
+
if (num > maxNum) {
|
|
203
|
+
maxNum = num;
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
});
|
|
207
|
+
return maxNum + 1;
|
|
208
|
+
}
|
|
209
|
+
__name(getNextSequenceNumber, "getNextSequenceNumber");
|
|
210
|
+
function saveImage(arrayBuffer, directory) {
|
|
211
|
+
const prefix = getTodayPrefix();
|
|
212
|
+
const seq = getNextSequenceNumber(directory, prefix);
|
|
213
|
+
const filename = `${prefix}-${seq}.jpg`;
|
|
214
|
+
const filepath = import_node_path.default.join(directory, filename);
|
|
215
|
+
if (!fs.existsSync(directory)) {
|
|
216
|
+
fs.mkdirSync(directory, { recursive: true });
|
|
217
|
+
}
|
|
218
|
+
const buffer = Buffer.from(arrayBuffer);
|
|
219
|
+
fs.writeFileSync(filepath, buffer);
|
|
220
|
+
console.log(`已保存图片:${filepath}`);
|
|
221
|
+
}
|
|
222
|
+
__name(saveImage, "saveImage");
|
|
223
|
+
async function getImageSrc(session, param, option) {
|
|
224
|
+
const number = option?.number ?? true, img = option?.img ?? true, at = option?.at ?? true, noParam = option?.noParam ?? true, quote = option?.quote ?? true;
|
|
225
|
+
if (number && param?.length && param?.length === String(Number(param))?.length) {
|
|
126
226
|
return `https://q1.qlogo.cn/g?b=qq&nk=${param}&s=640`;
|
|
127
|
-
} else if (!param?.length) {
|
|
227
|
+
} else if (noParam && !param?.length) {
|
|
128
228
|
return `https://q1.qlogo.cn/g?b=qq&nk=${session.userId}&s=640`;
|
|
129
229
|
}
|
|
130
230
|
const elementArray = session.elements;
|
|
131
231
|
for (const element of elementArray) {
|
|
132
|
-
if (element?.type === "img") {
|
|
232
|
+
if (img && element?.type === "img") {
|
|
133
233
|
return element?.attrs?.src;
|
|
134
|
-
} else if (element?.type === "at" && element?.attrs?.id) {
|
|
234
|
+
} else if (at && element?.type === "at" && element?.attrs?.id) {
|
|
135
235
|
return `https://q1.qlogo.cn/g?b=qq&nk=${element.attrs.id}&s=640`;
|
|
136
236
|
}
|
|
137
237
|
}
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
238
|
+
if (quote) {
|
|
239
|
+
const quoteElementArray = session?.quote?.elements;
|
|
240
|
+
if (quoteElementArray?.length) {
|
|
241
|
+
for (const element of quoteElementArray) {
|
|
242
|
+
if (img && element?.type === "img") {
|
|
243
|
+
return element?.attrs?.src;
|
|
244
|
+
} else if (at && element?.type === "at" && element?.attrs?.id && element.attrs.id !== session.selfId) {
|
|
245
|
+
return `https://q1.qlogo.cn/g?b=qq&nk=${element?.attrs?.id}&s=640`;
|
|
246
|
+
}
|
|
145
247
|
}
|
|
146
248
|
}
|
|
147
249
|
}
|
|
@@ -156,14 +258,14 @@ async function handleBanGDreamConfig(ctx, options) {
|
|
|
156
258
|
happy: ["happy", "orange", "橙", "橙色"]
|
|
157
259
|
};
|
|
158
260
|
const bands = {
|
|
159
|
-
ppp: ["ppp", "
|
|
160
|
-
ag: ["ag", "
|
|
161
|
-
pp: ["pp", "
|
|
162
|
-
hhw: ["hhw", "ハロー、ハッピーワールド!", "
|
|
163
|
-
r: ["r", "
|
|
164
|
-
ras: ["ras", "
|
|
165
|
-
mnk: ["mnk", "モニカ", "蝶团", "蝶", "
|
|
166
|
-
go: ["go", "
|
|
261
|
+
ppp: ["ppp", "poppin'Party", "破琵琶", "步品破茶", "poppin", "popipa", "poppinparty", "ポピパ"],
|
|
262
|
+
ag: ["ag", "afterglow", "夕阳红", "悪蓋愚狼"],
|
|
263
|
+
pp: ["pp", "pastel*palettes", "pastel*palettes", "pastelPalettes", "怕死怕累", "pastel", "palettes", "pasupare", "パスパレ", "破巣照破烈斗"],
|
|
264
|
+
hhw: ["hhw", "ハロー、ハッピーワールド!", "hello,happyworld!", "hellohappyworld", "ハロハピ", "hello,happyworld!", "harohapi", "破狼法被威悪怒", "儿歌团", "好好玩"],
|
|
265
|
+
r: ["r", "roselia", "露世里恶", "萝", "露世裏悪", "ロゼリア", "r组", "相声团", "相声组"],
|
|
266
|
+
ras: ["ras", "raiseasuilen", "raise", "suilen", "ラス", "零図悪酔恋", "睡莲", "麗厨唖睡蓮", "睡蓮"],
|
|
267
|
+
mnk: ["mnk", "モニカ", "蝶团", "蝶", "morfonica", "毛二力", "monika", "monica"],
|
|
268
|
+
go: ["go", "mygo!!!!!", "mygo!!!!!", "mygo", "我去!!!!!", "我去!!!!!", "我去", "卖狗"]
|
|
167
269
|
};
|
|
168
270
|
const trains = {
|
|
169
271
|
"color_star": ["花后", "1", "彩", "true"],
|
|
@@ -194,9 +296,9 @@ async function handleBanGDreamConfig(ctx, options) {
|
|
|
194
296
|
}
|
|
195
297
|
const starNum = options.starNum ? parseInt(options.starNum) : 0;
|
|
196
298
|
drawConfig.starNum = starNum > 0 && starNum < 10 ? starNum : 0;
|
|
197
|
-
if (
|
|
299
|
+
if (options.train) {
|
|
198
300
|
for (const [train, aliases] of Object.entries(trains)) {
|
|
199
|
-
if (aliases.includes(options.
|
|
301
|
+
if (aliases.includes(options.train.toLowerCase())) {
|
|
200
302
|
drawConfig.starType = train;
|
|
201
303
|
break;
|
|
202
304
|
}
|
|
@@ -360,13 +462,17 @@ __name(drawBanGDream, "drawBanGDream");
|
|
|
360
462
|
// Annotate the CommonJS export names for ESM import in node:
|
|
361
463
|
0 && (module.exports = {
|
|
362
464
|
Config,
|
|
465
|
+
addRecord,
|
|
363
466
|
apply,
|
|
364
467
|
assetsDir,
|
|
365
468
|
baseDir,
|
|
366
469
|
drawLock,
|
|
367
470
|
drawSold,
|
|
368
471
|
getImageSrc,
|
|
472
|
+
getRecord,
|
|
369
473
|
handleBanGDreamConfig,
|
|
370
474
|
name,
|
|
475
|
+
repeatContextMap,
|
|
476
|
+
starfxLogger,
|
|
371
477
|
usage
|
|
372
478
|
});
|
package/package.json
CHANGED
package/readme.md
CHANGED
|
@@ -13,17 +13,19 @@ StarFreedomX机器人的小功能,自用
|
|
|
13
13
|
* 我也喜欢你!
|
|
14
14
|
|
|
15
15
|
# 更新日志
|
|
16
|
-
| 版本 | 更新日志
|
|
17
|
-
|
|
18
|
-
| `0.0.1` | 加入封印功能
|
|
19
|
-
| `0.1.0` | 加入"卖掉了"功能
|
|
20
|
-
| `0.2.0` | 加入"艾特我又不说话"回复功能
|
|
21
|
-
| `0.3.0` | 加入"我喜欢你"和"我才不是机器人!"回复功能
|
|
22
|
-
| `0.3.3` | 修订添加"我才不是机器人"是否需要at
|
|
23
|
-
| `0.3.4` | 分离"艾特我/他又不说话"的两个选项为单独的开关
|
|
24
|
-
| `0.3.5` | 修复丢失的assets
|
|
25
|
-
| `0.3.6` | 添加"艾特我/他又不说话"的概率配置
|
|
26
|
-
| `0.4.0` | 更改处理库为sharp
|
|
27
|
-
| `0.4.1` | 修复sharp处理w>h的图报错的bug
|
|
28
|
-
| `0.5.0` | 加入BanG Dream!边框功能
|
|
29
|
-
| `0.5.1` | 对边框的参数做了限定,修复了异常输入导致的报错
|
|
16
|
+
| 版本 | 更新日志 |
|
|
17
|
+
|---------|-----------------------------|
|
|
18
|
+
| `0.0.1` | 加入封印功能 |
|
|
19
|
+
| `0.1.0` | 加入"卖掉了"功能 |
|
|
20
|
+
| `0.2.0` | 加入"艾特我又不说话"回复功能 |
|
|
21
|
+
| `0.3.0` | 加入"我喜欢你"和"我才不是机器人!"回复功能 |
|
|
22
|
+
| `0.3.3` | 修订添加"我才不是机器人"是否需要at |
|
|
23
|
+
| `0.3.4` | 分离"艾特我/他又不说话"的两个选项为单独的开关 |
|
|
24
|
+
| `0.3.5` | 修复丢失的assets |
|
|
25
|
+
| `0.3.6` | 添加"艾特我/他又不说话"的概率配置 |
|
|
26
|
+
| `0.4.0` | 更改处理库为sharp |
|
|
27
|
+
| `0.4.1` | 修复sharp处理w>h的图报错的bug |
|
|
28
|
+
| `0.5.0` | 加入BanG Dream!边框功能 |
|
|
29
|
+
| `0.5.1` | 对边框的参数做了限定,修复了异常输入导致的报错 |
|
|
30
|
+
| `0.6.0` | 加入群语录功能,修复一处bangdream绘制的bug |
|
|
31
|
+
| `0.6.0` | 加入复读功能 |
|