koishi-plugin-starfx-bot 0.19.3 → 0.19.6
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 +1 -0
- package/lib/index.js +452 -416
- package/lib/plugins/currencySearch.d.ts +22 -0
- package/lib/plugins/drawHead.d.ts +39 -0
- package/lib/plugins/getOriginImg.d.ts +7 -0
- package/lib/utils.d.ts +1 -63
- package/package.json +1 -1
- package/readme.md +29 -32
package/lib/index.d.ts
CHANGED
package/lib/index.js
CHANGED
|
@@ -40,17 +40,18 @@ var require_zh_CN = __commonJS({
|
|
|
40
40
|
// src/index.ts
|
|
41
41
|
var src_exports = {};
|
|
42
42
|
__export(src_exports, {
|
|
43
|
-
Config: () =>
|
|
43
|
+
Config: () => Config3,
|
|
44
44
|
apply: () => apply,
|
|
45
45
|
assetsDir: () => assetsDir,
|
|
46
|
-
baseDir: () =>
|
|
46
|
+
baseDir: () => baseDir2,
|
|
47
|
+
inject: () => inject,
|
|
47
48
|
name: () => name,
|
|
48
49
|
repeatContextMap: () => repeatContextMap,
|
|
49
50
|
starfxLogger: () => starfxLogger,
|
|
50
51
|
usage: () => usage
|
|
51
52
|
});
|
|
52
53
|
module.exports = __toCommonJS(src_exports);
|
|
53
|
-
var
|
|
54
|
+
var import_koishi5 = require("koishi");
|
|
54
55
|
var fs2 = __toESM(require("fs"));
|
|
55
56
|
|
|
56
57
|
// src/utils.ts
|
|
@@ -58,18 +59,7 @@ var import_koishi = require("koishi");
|
|
|
58
59
|
var import_fs = __toESM(require("fs"));
|
|
59
60
|
var import_node_path = __toESM(require("node:path"));
|
|
60
61
|
var import_sharp = __toESM(require("sharp"));
|
|
61
|
-
var import_jimp = require("jimp");
|
|
62
|
-
var import_rss_parser = __toESM(require("rss-parser"));
|
|
63
62
|
var import_chartjs_adapter_dayjs_3 = require("chartjs-adapter-dayjs-3");
|
|
64
|
-
var cheerio = __toESM(require("cheerio"));
|
|
65
|
-
var import_http_proxy_agent = require("http-proxy-agent");
|
|
66
|
-
var import_https_proxy_agent = require("https-proxy-agent");
|
|
67
|
-
var import_axios = __toESM(require("axios"));
|
|
68
|
-
var import_chart = require("chart.js");
|
|
69
|
-
var import_skia_canvas = require("skia-canvas");
|
|
70
|
-
import_chart.Chart.register(
|
|
71
|
-
...import_chart.registerables
|
|
72
|
-
);
|
|
73
63
|
async function addRecord(ctx, gid, avatarUrl) {
|
|
74
64
|
const recordDir = `${assetsDir}/record/${gid}`;
|
|
75
65
|
const avatarBuffer = await ctx.http.get(avatarUrl, { responseType: "arraybuffer" });
|
|
@@ -186,117 +176,6 @@ async function getImageSrc(session, param, option) {
|
|
|
186
176
|
return "";
|
|
187
177
|
}
|
|
188
178
|
__name(getImageSrc, "getImageSrc");
|
|
189
|
-
async function handleBanGDreamConfig(options) {
|
|
190
|
-
const types = {
|
|
191
|
-
cool: ["cool", "blue", "蓝", "蓝色"],
|
|
192
|
-
powerful: ["powerful", "red", "红", "红色"],
|
|
193
|
-
pure: ["pure", "green", "绿", "绿色"],
|
|
194
|
-
happy: ["happy", "orange", "橙", "橙色"]
|
|
195
|
-
};
|
|
196
|
-
const bands = {
|
|
197
|
-
ppp: ["ppp", "poppin'Party", "破琵琶", "步品破茶", "poppin", "popipa", "poppinparty", "ポピパ"],
|
|
198
|
-
ag: ["ag", "afterglow", "夕阳红", "悪蓋愚狼"],
|
|
199
|
-
pp: ["pp", "pastel*palettes", "pastel*palettes", "pastelPalettes", "怕死怕累", "pastel", "palettes", "pasupare", "パスパレ", "破巣照破烈斗"],
|
|
200
|
-
hhw: ["hhw", "ハロー、ハッピーワールド!", "hello,happyworld!", "hellohappyworld", "ハロハピ", "hello,happyworld!", "harohapi", "破狼法被威悪怒", "儿歌团", "好好玩"],
|
|
201
|
-
r: ["r", "roselia", "露世里恶", "萝", "露世裏悪", "ロゼリア", "r组", "相声团", "相声组"],
|
|
202
|
-
ras: ["ras", "raiseasuilen", "raise", "suilen", "ラス", "零図悪酔恋", "睡莲", "麗厨唖睡蓮", "睡蓮"],
|
|
203
|
-
mnk: ["mnk", "モニカ", "蝶团", "蝶", "morfonica", "毛二力", "monika", "monica"],
|
|
204
|
-
go: ["go", "mygo!!!!!", "mygo!!!!!", "mygo", "我去!!!!!", "我去!!!!!", "我去", "卖狗"]
|
|
205
|
-
};
|
|
206
|
-
const trains = {
|
|
207
|
-
"color_star": ["花后", "1", "彩", "true"],
|
|
208
|
-
"normal_star": ["花前", "0", "false"]
|
|
209
|
-
};
|
|
210
|
-
const drawConfig = {
|
|
211
|
-
color: "",
|
|
212
|
-
band: "",
|
|
213
|
-
starType: "",
|
|
214
|
-
starNum: 0,
|
|
215
|
-
border: ""
|
|
216
|
-
};
|
|
217
|
-
if (options?.color) {
|
|
218
|
-
for (const [type, aliases] of Object.entries(types)) {
|
|
219
|
-
if (aliases.includes(options.color.toLowerCase())) {
|
|
220
|
-
drawConfig.color = type;
|
|
221
|
-
break;
|
|
222
|
-
}
|
|
223
|
-
}
|
|
224
|
-
}
|
|
225
|
-
if (options?.band) {
|
|
226
|
-
for (const [band, aliases] of Object.entries(bands)) {
|
|
227
|
-
if (aliases.includes(options.band.toLowerCase())) {
|
|
228
|
-
drawConfig.band = band;
|
|
229
|
-
break;
|
|
230
|
-
}
|
|
231
|
-
}
|
|
232
|
-
}
|
|
233
|
-
const starNum = options?.starNum ? parseInt(options.starNum) : 0;
|
|
234
|
-
drawConfig.starNum = starNum > 0 && starNum < 10 ? starNum : 0;
|
|
235
|
-
if (options?.train) {
|
|
236
|
-
for (const [train, aliases] of Object.entries(trains)) {
|
|
237
|
-
if (aliases.includes(options.train.toLowerCase())) {
|
|
238
|
-
drawConfig.starType = train;
|
|
239
|
-
break;
|
|
240
|
-
}
|
|
241
|
-
}
|
|
242
|
-
}
|
|
243
|
-
return drawConfig;
|
|
244
|
-
}
|
|
245
|
-
__name(handleBanGDreamConfig, "handleBanGDreamConfig");
|
|
246
|
-
async function drawLock(ctx, baseImage) {
|
|
247
|
-
const image = await getImageFromUrl(ctx, baseImage);
|
|
248
|
-
if (image === -1) {
|
|
249
|
-
return "发生错误";
|
|
250
|
-
} else if (image === -2) {
|
|
251
|
-
return "输入无效";
|
|
252
|
-
}
|
|
253
|
-
const imageMetadata = await image.metadata();
|
|
254
|
-
const lockUrl = `${baseDir}/data/starfx-bot/assets/lock.png`;
|
|
255
|
-
const size1 = Math.min(imageMetadata.width, imageMetadata.height);
|
|
256
|
-
image.resize({ width: size1, height: size1, fit: "cover" });
|
|
257
|
-
const overlay = (0, import_sharp.default)(lockUrl).png();
|
|
258
|
-
overlay.resize({ width: size1 });
|
|
259
|
-
image.composite([{ input: await overlay.toBuffer() }]);
|
|
260
|
-
return import_koishi.h.image(await image.png().toBuffer(), "image/png");
|
|
261
|
-
}
|
|
262
|
-
__name(drawLock, "drawLock");
|
|
263
|
-
async function drawSold(ctx, baseImage) {
|
|
264
|
-
const image = await getImageFromUrl(ctx, baseImage);
|
|
265
|
-
if (image === -1) {
|
|
266
|
-
return "发生错误";
|
|
267
|
-
} else if (image === -2) {
|
|
268
|
-
return "输入无效";
|
|
269
|
-
}
|
|
270
|
-
const imageMetadata = await image.metadata();
|
|
271
|
-
const size1 = Math.min(imageMetadata.width, imageMetadata.height);
|
|
272
|
-
image.resize({ width: size1, height: size1, fit: "cover" });
|
|
273
|
-
const middle = (0, import_sharp.default)({
|
|
274
|
-
create: {
|
|
275
|
-
width: size1,
|
|
276
|
-
height: size1,
|
|
277
|
-
channels: 4,
|
|
278
|
-
background: { r: 255, g: 255, b: 255, alpha: 0.4 }
|
|
279
|
-
}
|
|
280
|
-
}).png();
|
|
281
|
-
const soldUrl = `${assetsDir}/sold.png`;
|
|
282
|
-
const overlay = (0, import_sharp.default)(soldUrl).png();
|
|
283
|
-
const overlaySize = Math.round(size1 * 182 / 240);
|
|
284
|
-
overlay.resize({
|
|
285
|
-
width: overlaySize,
|
|
286
|
-
height: overlaySize
|
|
287
|
-
});
|
|
288
|
-
const topLeft = Math.round(overlaySize * 29 / 182);
|
|
289
|
-
image.composite([
|
|
290
|
-
{ input: await middle.toBuffer() },
|
|
291
|
-
{
|
|
292
|
-
input: await overlay.toBuffer(),
|
|
293
|
-
top: topLeft,
|
|
294
|
-
left: topLeft
|
|
295
|
-
}
|
|
296
|
-
]);
|
|
297
|
-
return import_koishi.h.image(await image.png().toBuffer(), "image/png");
|
|
298
|
-
}
|
|
299
|
-
__name(drawSold, "drawSold");
|
|
300
179
|
async function getImageFromUrl(ctx, url) {
|
|
301
180
|
if (!url) return -2;
|
|
302
181
|
let image;
|
|
@@ -352,150 +231,6 @@ async function iLoveYou(cfg, session, elements) {
|
|
|
352
231
|
}
|
|
353
232
|
}
|
|
354
233
|
__name(iLoveYou, "iLoveYou");
|
|
355
|
-
async function drawBanGDream(avatar, inputOptions) {
|
|
356
|
-
if (!avatar) {
|
|
357
|
-
return "";
|
|
358
|
-
}
|
|
359
|
-
const colors = ["cool", "pure", "happy", "powerful"];
|
|
360
|
-
const bands = ["ppp", "ag", "pp", "r", "hhw", "ras", "mnk", "go"];
|
|
361
|
-
const starTypes = ["normal_star", "color_star"];
|
|
362
|
-
const starNums = [1, 2, 3, 4, 5];
|
|
363
|
-
const options = {
|
|
364
|
-
color: inputOptions.color || import_koishi.Random.pick(colors),
|
|
365
|
-
band: inputOptions.band || import_koishi.Random.pick(bands),
|
|
366
|
-
starNum: inputOptions.starNum || import_koishi.Random.pick(starNums),
|
|
367
|
-
starType: inputOptions.starType || "",
|
|
368
|
-
border: inputOptions.border || ""
|
|
369
|
-
};
|
|
370
|
-
options.starType ||= options.starNum < 3 ? starTypes[0] : import_koishi.Random.pick(starTypes);
|
|
371
|
-
options.border ||= `card-${starNums.includes(options.starNum) ? options.starNum : 5}${options.starNum == 1 ? `-${options.color}` : ""}`;
|
|
372
|
-
let image;
|
|
373
|
-
try {
|
|
374
|
-
image = await import_jimp.Jimp.read(avatar);
|
|
375
|
-
} catch (e) {
|
|
376
|
-
starfxLogger.error(e);
|
|
377
|
-
return;
|
|
378
|
-
}
|
|
379
|
-
const [colorImage, bandImage, starImage, borderImage] = await Promise.all([
|
|
380
|
-
import_jimp.Jimp.read(`${assetsDir}/bangborder/${options.color}.png`),
|
|
381
|
-
import_jimp.Jimp.read(`${assetsDir}/bangborder/${options.band}.png`),
|
|
382
|
-
import_jimp.Jimp.read(`${assetsDir}/bangborder/${options.starType}.png`),
|
|
383
|
-
import_jimp.Jimp.read(`${assetsDir}/bangborder/${options.border}.png`)
|
|
384
|
-
]);
|
|
385
|
-
const zoom = 2;
|
|
386
|
-
image.cover({ w: 500 * zoom, h: 500 * zoom });
|
|
387
|
-
borderImage.cover({ w: 500 * zoom, h: 500 * zoom });
|
|
388
|
-
image.composite(borderImage);
|
|
389
|
-
colorImage.cover({ w: 130 * zoom, h: 130 * zoom });
|
|
390
|
-
image.composite(colorImage, image.width - colorImage.width - 3 * zoom, 5.5);
|
|
391
|
-
bandImage.width > bandImage.height ? bandImage.resize({ w: 120 * zoom }) : bandImage.resize({ h: 120 * zoom });
|
|
392
|
-
image.composite(bandImage, 15 * zoom, 15 * zoom);
|
|
393
|
-
starImage.resize({ w: 90 * zoom });
|
|
394
|
-
const step = 60 * zoom;
|
|
395
|
-
let hei = 410 * zoom;
|
|
396
|
-
let times = options.starNum;
|
|
397
|
-
while (times > 0) {
|
|
398
|
-
image.composite(starImage, 10 * zoom, hei);
|
|
399
|
-
hei -= step;
|
|
400
|
-
times--;
|
|
401
|
-
}
|
|
402
|
-
return `data:image/png;base64,${(await image.getBuffer("image/jpeg")).toString("base64")}`;
|
|
403
|
-
}
|
|
404
|
-
__name(drawBanGDream, "drawBanGDream");
|
|
405
|
-
async function intervalGetExchangeRate(ctx, cfg, session, searchString, exchangeRatePath) {
|
|
406
|
-
}
|
|
407
|
-
__name(intervalGetExchangeRate, "intervalGetExchangeRate");
|
|
408
|
-
async function parseNaturalCurrency(searchString) {
|
|
409
|
-
const index = await getCurrencyCodesMap();
|
|
410
|
-
const s = searchString.replace(/\s+/g, "");
|
|
411
|
-
const match = s.match(/(.+?)(兑|对)(.+)/);
|
|
412
|
-
if (match) {
|
|
413
|
-
const from = index[match[1]];
|
|
414
|
-
const to = index[match[3]];
|
|
415
|
-
if (from && to) {
|
|
416
|
-
return from + to;
|
|
417
|
-
}
|
|
418
|
-
}
|
|
419
|
-
if (index[s]) {
|
|
420
|
-
return index[s];
|
|
421
|
-
}
|
|
422
|
-
return null;
|
|
423
|
-
}
|
|
424
|
-
__name(parseNaturalCurrency, "parseNaturalCurrency");
|
|
425
|
-
async function getExchangeRate(ctx, cfg, session, searchString, raw, retryTimes = 1) {
|
|
426
|
-
const apiKey = retryTimes ? await getMvpAPIKey() : await updateMvpAPIKey();
|
|
427
|
-
try {
|
|
428
|
-
let guids = [];
|
|
429
|
-
if (searchString) {
|
|
430
|
-
const parsed = await parseNaturalCurrency(searchString);
|
|
431
|
-
if (parsed) {
|
|
432
|
-
searchString = parsed;
|
|
433
|
-
}
|
|
434
|
-
}
|
|
435
|
-
if (raw && /^([a-z0-9]{6})([,\s]([a-z0-9]{6}))*$/.test(raw)) {
|
|
436
|
-
guids = raw.split(",");
|
|
437
|
-
} else if (/^([a-zA-Z]{3}|[a-zA-Z]{6})([,\s]([a-zA-Z]{3}|[a-zA-Z]{6}))*$/.test(searchString)) {
|
|
438
|
-
const currencies = await getCurrencyCodes();
|
|
439
|
-
const codes = searchString.split(/[,\s]+/);
|
|
440
|
-
const invalidCodes = [];
|
|
441
|
-
let search6Strings = [];
|
|
442
|
-
codes.forEach((code) => {
|
|
443
|
-
const first = code.slice(0, 3).toUpperCase();
|
|
444
|
-
const second = code.length === 3 ? "CNY" : code.slice(3, 6).toUpperCase();
|
|
445
|
-
search6Strings.push(code.length === 3 ? first + second : code);
|
|
446
|
-
if (!currencies.some((c) => c.code === first)) invalidCodes.push(first);
|
|
447
|
-
if (code.length === 6 && !currencies.some((c) => c.code === second)) invalidCodes.push(second);
|
|
448
|
-
});
|
|
449
|
-
if (invalidCodes.length > 0) {
|
|
450
|
-
throw new Error(`输入的货币代码不合法: ${invalidCodes.join(", ")}`);
|
|
451
|
-
}
|
|
452
|
-
guids = await getExchangeGuids(search6Strings.join(","), apiKey);
|
|
453
|
-
}
|
|
454
|
-
if (!guids.length || guids.every((g) => !g)) {
|
|
455
|
-
throw new Error(`输入无效: ${searchString}`);
|
|
456
|
-
}
|
|
457
|
-
const result = [];
|
|
458
|
-
for (const guid of guids) {
|
|
459
|
-
if (!guid) throw new Error("GUID not found");
|
|
460
|
-
const nowPriceArr = await getQuotes(guid, apiKey);
|
|
461
|
-
const monthPriceArr = await getMonthMSNClosePrices(guid, apiKey);
|
|
462
|
-
const nowPrice = nowPriceArr?.[0];
|
|
463
|
-
const oneMonthPrice = monthPriceArr?.[0];
|
|
464
|
-
if (!nowPrice || !oneMonthPrice) {
|
|
465
|
-
throw new Error("Failed to fetch price");
|
|
466
|
-
}
|
|
467
|
-
const chartBuffer = await drawOneMonthChartSkia(oneMonthPrice.prices, oneMonthPrice.timeStamps, `1 ${nowPrice.fromCurrency} to 1 ${nowPrice.currency}`);
|
|
468
|
-
const imgSrc = "data:image/png;base64," + chartBuffer.toString("base64");
|
|
469
|
-
result.push({
|
|
470
|
-
name: nowPrice.symbolName,
|
|
471
|
-
fromCurrency: nowPrice.fromCurrency,
|
|
472
|
-
currency: nowPrice.currency,
|
|
473
|
-
nowPrice: nowPrice.price,
|
|
474
|
-
oneMonthChart: import_koishi.h.image(imgSrc)
|
|
475
|
-
});
|
|
476
|
-
}
|
|
477
|
-
for (const item of result) {
|
|
478
|
-
await session.send([
|
|
479
|
-
import_koishi.h.text(`
|
|
480
|
-
${(/* @__PURE__ */ new Date()).toLocaleString()}
|
|
481
|
-
${item.name}
|
|
482
|
-
(${item.fromCurrency}/${item.currency})
|
|
483
|
-
当前价格: ${item.nowPrice}
|
|
484
|
-
近30天价格走势:
|
|
485
|
-
`),
|
|
486
|
-
item.oneMonthChart
|
|
487
|
-
]);
|
|
488
|
-
}
|
|
489
|
-
} catch (err) {
|
|
490
|
-
if (retryTimes === 0) {
|
|
491
|
-
const message = err instanceof Error ? err.message : typeof err === "string" ? err : JSON.stringify(err);
|
|
492
|
-
await session.send(`查询失败:${message}`);
|
|
493
|
-
} else {
|
|
494
|
-
await getExchangeRate(ctx, cfg, session, searchString, raw, retryTimes - 1);
|
|
495
|
-
}
|
|
496
|
-
}
|
|
497
|
-
}
|
|
498
|
-
__name(getExchangeRate, "getExchangeRate");
|
|
499
234
|
function parseJsonControl(text) {
|
|
500
235
|
try {
|
|
501
236
|
return JSON.parse(text);
|
|
@@ -578,78 +313,6 @@ async function undo(cfg, session) {
|
|
|
578
313
|
}
|
|
579
314
|
}
|
|
580
315
|
__name(undo, "undo");
|
|
581
|
-
async function getXUrl(urls) {
|
|
582
|
-
const regex = /https:\/\/x\.com\/([^\/]+)\/status\/(\d+)/g;
|
|
583
|
-
let match;
|
|
584
|
-
const results = [];
|
|
585
|
-
while ((match = regex.exec(urls)) !== null) {
|
|
586
|
-
const [fullUrl] = match;
|
|
587
|
-
results.push(fullUrl);
|
|
588
|
-
}
|
|
589
|
-
return results;
|
|
590
|
-
}
|
|
591
|
-
__name(getXUrl, "getXUrl");
|
|
592
|
-
var parser = new import_rss_parser.default({
|
|
593
|
-
customFields: {
|
|
594
|
-
item: ["description", "link"]
|
|
595
|
-
}
|
|
596
|
-
});
|
|
597
|
-
async function getXNum(session) {
|
|
598
|
-
return session.content.trim().split(" ").slice(1).filter((item) => !isNaN(+item) && item).map((str) => Number(str) - 1);
|
|
599
|
-
}
|
|
600
|
-
__name(getXNum, "getXNum");
|
|
601
|
-
async function getXImage(rssUrl, xUrls) {
|
|
602
|
-
const xUrlsArray = Array.isArray(xUrls) ? xUrls : [xUrls];
|
|
603
|
-
const feed = await parser.parseURL(rssUrl);
|
|
604
|
-
const allImageUrls = [];
|
|
605
|
-
for (const xUrl of xUrlsArray) {
|
|
606
|
-
const item = feed.items.find((i) => i.link === xUrl);
|
|
607
|
-
if (item) {
|
|
608
|
-
const $ = cheerio.load(item.description);
|
|
609
|
-
$("img").each((_, el) => {
|
|
610
|
-
const src = $(el).attr("src");
|
|
611
|
-
if (src) allImageUrls.push(src);
|
|
612
|
-
});
|
|
613
|
-
}
|
|
614
|
-
}
|
|
615
|
-
return allImageUrls;
|
|
616
|
-
}
|
|
617
|
-
__name(getXImage, "getXImage");
|
|
618
|
-
function chunk(arr, size) {
|
|
619
|
-
const res = [];
|
|
620
|
-
for (let i = 0; i < arr.length; i += size) {
|
|
621
|
-
res.push(arr.slice(i, i + size));
|
|
622
|
-
}
|
|
623
|
-
return res;
|
|
624
|
-
}
|
|
625
|
-
__name(chunk, "chunk");
|
|
626
|
-
async function sendImages(session, cfg, imageUrls) {
|
|
627
|
-
const chunks = chunk(imageUrls, 10);
|
|
628
|
-
for (const group of chunks) {
|
|
629
|
-
const messages = await Promise.all(
|
|
630
|
-
group.map(async (url) => import_koishi.h.image(await getXImageBase64(url, cfg)))
|
|
631
|
-
);
|
|
632
|
-
if (messages.length > 0) {
|
|
633
|
-
const message = messages.join("");
|
|
634
|
-
await session.send(message);
|
|
635
|
-
} else {
|
|
636
|
-
await session.send("未找到图片,请引用包含图片且处于RSS列表中的的推特链接");
|
|
637
|
-
}
|
|
638
|
-
}
|
|
639
|
-
}
|
|
640
|
-
__name(sendImages, "sendImages");
|
|
641
|
-
async function getXImageBase64(url, cfg) {
|
|
642
|
-
const httpAgent = new import_http_proxy_agent.HttpProxyAgent(cfg.proxyUrl);
|
|
643
|
-
const httpsAgent = new import_https_proxy_agent.HttpsProxyAgent(cfg.proxyUrl);
|
|
644
|
-
import_axios.default.defaults.httpAgent = httpAgent;
|
|
645
|
-
import_axios.default.defaults.httpsAgent = httpsAgent;
|
|
646
|
-
const res = await import_axios.default.get(url, { responseType: "arraybuffer" });
|
|
647
|
-
const base64 = Buffer.from(res.data, "binary").toString("base64");
|
|
648
|
-
const dataUrl = `data:image/png;base64,${base64}`;
|
|
649
|
-
console.log("success");
|
|
650
|
-
return dataUrl;
|
|
651
|
-
}
|
|
652
|
-
__name(getXImageBase64, "getXImageBase64");
|
|
653
316
|
function safeQuote(str, useQuote) {
|
|
654
317
|
let unquoted = str.trim();
|
|
655
318
|
if (unquoted.startsWith('"')) {
|
|
@@ -717,6 +380,135 @@ function ready(session, cfg, param, readyMap) {
|
|
|
717
380
|
return returnMessage;
|
|
718
381
|
}
|
|
719
382
|
__name(ready, "ready");
|
|
383
|
+
|
|
384
|
+
// src/plugins/currencySearch.ts
|
|
385
|
+
var cheerio = __toESM(require("cheerio"));
|
|
386
|
+
var import_node_path2 = __toESM(require("node:path"));
|
|
387
|
+
var import_koishi2 = require("koishi");
|
|
388
|
+
var import_chart = require("chart.js");
|
|
389
|
+
var import_skia_canvas = require("skia-canvas");
|
|
390
|
+
import_chart.Chart.register(
|
|
391
|
+
...import_chart.registerables
|
|
392
|
+
);
|
|
393
|
+
var mvpAPIKey;
|
|
394
|
+
var currencyCodes = [];
|
|
395
|
+
var currencyCodesMap = {};
|
|
396
|
+
async function intervalGetExchangeRate(ctx, cfg, session, searchString, exchangeRatePath) {
|
|
397
|
+
}
|
|
398
|
+
__name(intervalGetExchangeRate, "intervalGetExchangeRate");
|
|
399
|
+
async function parseNaturalCurrency(searchString) {
|
|
400
|
+
const index = await getCurrencyCodesMap();
|
|
401
|
+
const s = searchString.replace(/\s+/g, "");
|
|
402
|
+
const match = s.match(/(.+?)(兑|对)(.+)/);
|
|
403
|
+
if (match) {
|
|
404
|
+
const from = index[match[1]];
|
|
405
|
+
const to = index[match[3]];
|
|
406
|
+
if (from && to) {
|
|
407
|
+
return from + to;
|
|
408
|
+
}
|
|
409
|
+
}
|
|
410
|
+
if (index[s]) {
|
|
411
|
+
return index[s];
|
|
412
|
+
}
|
|
413
|
+
return null;
|
|
414
|
+
}
|
|
415
|
+
__name(parseNaturalCurrency, "parseNaturalCurrency");
|
|
416
|
+
async function getExchangeRate(ctx, cfg, session, searchString, raw, retryTimes = 1) {
|
|
417
|
+
const apiKey = retryTimes ? await getMvpAPIKey() : await updateMvpAPIKey();
|
|
418
|
+
try {
|
|
419
|
+
let guids = [];
|
|
420
|
+
if (searchString) {
|
|
421
|
+
const parsed = await parseNaturalCurrency(searchString);
|
|
422
|
+
if (parsed) {
|
|
423
|
+
searchString = parsed;
|
|
424
|
+
}
|
|
425
|
+
}
|
|
426
|
+
if (raw && /^([a-z0-9]{6})([,\s]([a-z0-9]{6}))*$/.test(raw)) {
|
|
427
|
+
guids = raw.split(",");
|
|
428
|
+
} else if (/^([a-zA-Z]{3}|[a-zA-Z]{6})([,\s]([a-zA-Z]{3}|[a-zA-Z]{6}))*$/.test(searchString)) {
|
|
429
|
+
const currencies = await getCurrencyCodes();
|
|
430
|
+
const codes = searchString.split(/[,\s]+/);
|
|
431
|
+
const invalidCodes = [];
|
|
432
|
+
let search6Strings = [];
|
|
433
|
+
codes.forEach((code) => {
|
|
434
|
+
const first = code.slice(0, 3).toUpperCase();
|
|
435
|
+
const second = code.length === 3 ? "CNY" : code.slice(3, 6).toUpperCase();
|
|
436
|
+
search6Strings.push(code.length === 3 ? first + second : code);
|
|
437
|
+
if (!currencies.some((c) => c.code === first)) invalidCodes.push(first);
|
|
438
|
+
if (code.length === 6 && !currencies.some((c) => c.code === second)) invalidCodes.push(second);
|
|
439
|
+
});
|
|
440
|
+
if (invalidCodes.length > 0) {
|
|
441
|
+
throw new Error(`输入的货币代码不合法: ${invalidCodes.join(", ")}`);
|
|
442
|
+
}
|
|
443
|
+
guids = await getExchangeGuids(search6Strings.join(","), apiKey);
|
|
444
|
+
}
|
|
445
|
+
if (!guids.length || guids.every((g) => !g)) {
|
|
446
|
+
throw new Error(`输入无效: ${searchString}`);
|
|
447
|
+
}
|
|
448
|
+
const result = [];
|
|
449
|
+
for (const guid of guids) {
|
|
450
|
+
if (!guid) throw new Error("GUID not found");
|
|
451
|
+
const nowPriceArr = await getQuotes(guid, apiKey);
|
|
452
|
+
const monthPriceArr = await getMSNPrices(guid, apiKey, "1M1H");
|
|
453
|
+
const day5PriceArr = await getMSNPrices(guid, apiKey, "5D");
|
|
454
|
+
const nowPrice = nowPriceArr?.[0];
|
|
455
|
+
const oneMonthPrice = monthPriceArr?.[0];
|
|
456
|
+
const fiveDayPrice = day5PriceArr?.[0];
|
|
457
|
+
if (!nowPrice || !oneMonthPrice || !fiveDayPrice) {
|
|
458
|
+
throw new Error("Failed to fetch price");
|
|
459
|
+
}
|
|
460
|
+
const monthChartBuffer = await drawCurrencyChartSkia(oneMonthPrice.prices, oneMonthPrice.timeStamps, `1 ${nowPrice.fromCurrency} to 1 ${nowPrice.currency}`);
|
|
461
|
+
const day5ChartBuffer = await drawCurrencyChartSkia(fiveDayPrice.prices, fiveDayPrice.timeStamps, `1 ${nowPrice.fromCurrency} to 1 ${nowPrice.currency}`);
|
|
462
|
+
const mergeImgSrc = "data:image/png;base64," + (await mergeBuffersVertical(day5ChartBuffer, monthChartBuffer)).toString("base64");
|
|
463
|
+
result.push({
|
|
464
|
+
name: nowPrice.symbolName,
|
|
465
|
+
fromCurrency: nowPrice.fromCurrency,
|
|
466
|
+
currency: nowPrice.currency,
|
|
467
|
+
nowPrice: nowPrice.price,
|
|
468
|
+
// oneMonthChart: h.image(monthImgSrc),
|
|
469
|
+
// fiveDayChart: h.image(day5ImgSrc),
|
|
470
|
+
currencyChart: import_koishi2.h.image(mergeImgSrc)
|
|
471
|
+
});
|
|
472
|
+
}
|
|
473
|
+
for (const item of result) {
|
|
474
|
+
await session.send([
|
|
475
|
+
import_koishi2.h.text(`
|
|
476
|
+
${(/* @__PURE__ */ new Date()).toLocaleString()}
|
|
477
|
+
${item.name}
|
|
478
|
+
(${item.fromCurrency}/${item.currency})
|
|
479
|
+
当前价格: ${item.nowPrice}
|
|
480
|
+
近5天/近1个月价格走势:
|
|
481
|
+
`),
|
|
482
|
+
item.currencyChart
|
|
483
|
+
// item.fiveDayChart,
|
|
484
|
+
// h.text(`
|
|
485
|
+
// 近30天价格走势:
|
|
486
|
+
// `),
|
|
487
|
+
// item.oneMonthChart
|
|
488
|
+
]);
|
|
489
|
+
}
|
|
490
|
+
} catch (err) {
|
|
491
|
+
if (retryTimes === 0) {
|
|
492
|
+
const message = err instanceof Error ? err.message : typeof err === "string" ? err : JSON.stringify(err);
|
|
493
|
+
await session.send(`查询失败:${message}`);
|
|
494
|
+
} else {
|
|
495
|
+
await getExchangeRate(ctx, cfg, session, searchString, raw, retryTimes - 1);
|
|
496
|
+
}
|
|
497
|
+
}
|
|
498
|
+
}
|
|
499
|
+
__name(getExchangeRate, "getExchangeRate");
|
|
500
|
+
async function mergeBuffersVertical(buf1, buf2) {
|
|
501
|
+
const img1 = await (0, import_skia_canvas.loadImage)(buf1);
|
|
502
|
+
const img2 = await (0, import_skia_canvas.loadImage)(buf2);
|
|
503
|
+
const width = img1.width;
|
|
504
|
+
const height = img1.height + img2.height;
|
|
505
|
+
const canvas = new import_skia_canvas.Canvas(width, height);
|
|
506
|
+
const ctx = canvas.getContext("2d");
|
|
507
|
+
ctx.drawImage(img1, 0, 0);
|
|
508
|
+
ctx.drawImage(img2, 0, img1.height);
|
|
509
|
+
return await canvas.toBuffer("png");
|
|
510
|
+
}
|
|
511
|
+
__name(mergeBuffersVertical, "mergeBuffersVertical");
|
|
720
512
|
async function updateMvpAPIKey() {
|
|
721
513
|
try {
|
|
722
514
|
const htmlResp = await fetch("https://www.msn.com/zh-cn/money/tools/currencyconverter");
|
|
@@ -754,7 +546,6 @@ async function updateMvpAPIKey() {
|
|
|
754
546
|
}
|
|
755
547
|
}
|
|
756
548
|
__name(updateMvpAPIKey, "updateMvpAPIKey");
|
|
757
|
-
var mvpAPIKey;
|
|
758
549
|
async function getMvpAPIKey() {
|
|
759
550
|
return mvpAPIKey ? mvpAPIKey : updateMvpAPIKey();
|
|
760
551
|
}
|
|
@@ -808,8 +599,8 @@ async function getQuotes(ids, apiKey) {
|
|
|
808
599
|
}
|
|
809
600
|
}
|
|
810
601
|
__name(getQuotes, "getQuotes");
|
|
811
|
-
async function
|
|
812
|
-
const url = `https://assets.msn.com/service/Finance/QuoteSummary?apikey=${apiKey}&ids=${ids}&intents=Charts,Exchanges&type
|
|
602
|
+
async function getMSNPrices(ids, apiKey, type = "1M1H") {
|
|
603
|
+
const url = `https://assets.msn.com/service/Finance/QuoteSummary?apikey=${apiKey}&ids=${ids}&intents=Charts,Exchanges&type=${type}&wrapodata=false`;
|
|
813
604
|
const res = await fetch(url);
|
|
814
605
|
if (!res.ok) throw new Error(`HTTP error! status: ${res.status}`);
|
|
815
606
|
let data = await res.json();
|
|
@@ -827,8 +618,8 @@ async function getMonthMSNClosePrices(ids, apiKey) {
|
|
|
827
618
|
};
|
|
828
619
|
});
|
|
829
620
|
}
|
|
830
|
-
__name(
|
|
831
|
-
async function
|
|
621
|
+
__name(getMSNPrices, "getMSNPrices");
|
|
622
|
+
async function drawCurrencyChartSkia(prices, timeStamps, title = "兑换汇率", width = 1200, height = 600) {
|
|
832
623
|
if (!prices.length || !timeStamps.length || prices.length !== timeStamps.length) return;
|
|
833
624
|
const dataPoints = timeStamps.map((t, i) => ({ x: new Date(t), y: prices[i] }));
|
|
834
625
|
const canvas = new import_skia_canvas.Canvas(width, height);
|
|
@@ -896,15 +687,13 @@ async function drawOneMonthChartSkia(prices, timeStamps, title = "兑换汇率",
|
|
|
896
687
|
});
|
|
897
688
|
return await canvas.toBuffer("png");
|
|
898
689
|
}
|
|
899
|
-
__name(
|
|
900
|
-
var currencyCodes = [];
|
|
690
|
+
__name(drawCurrencyChartSkia, "drawCurrencyChartSkia");
|
|
901
691
|
async function getCurrencyCodes() {
|
|
902
692
|
if (currencyCodes?.length) return currencyCodes;
|
|
903
|
-
currencyCodes = require(
|
|
693
|
+
currencyCodes = require(import_node_path2.default.resolve(assetsDir, "./currency.json"));
|
|
904
694
|
return currencyCodes;
|
|
905
695
|
}
|
|
906
696
|
__name(getCurrencyCodes, "getCurrencyCodes");
|
|
907
|
-
var currencyCodesMap = {};
|
|
908
697
|
async function getCurrencyCodesMap() {
|
|
909
698
|
if (Object.keys(currencyCodesMap)?.length) return currencyCodesMap;
|
|
910
699
|
currencyCodesMap = await buildCurrencyIndex();
|
|
@@ -924,8 +713,254 @@ async function buildCurrencyIndex() {
|
|
|
924
713
|
}
|
|
925
714
|
__name(buildCurrencyIndex, "buildCurrencyIndex");
|
|
926
715
|
|
|
716
|
+
// src/plugins/getOriginImg.ts
|
|
717
|
+
var import_rss_parser = __toESM(require("rss-parser"));
|
|
718
|
+
var import_koishi3 = require("koishi");
|
|
719
|
+
var cheerio2 = __toESM(require("cheerio"));
|
|
720
|
+
var import_http_proxy_agent = require("http-proxy-agent");
|
|
721
|
+
var import_https_proxy_agent = require("https-proxy-agent");
|
|
722
|
+
var import_axios = __toESM(require("axios"));
|
|
723
|
+
async function getXUrl(urls) {
|
|
724
|
+
const regex = /https:\/\/x\.com\/([^\/]+)\/status\/(\d+)/g;
|
|
725
|
+
let match;
|
|
726
|
+
const results = [];
|
|
727
|
+
while ((match = regex.exec(urls)) !== null) {
|
|
728
|
+
const [fullUrl] = match;
|
|
729
|
+
results.push(fullUrl);
|
|
730
|
+
}
|
|
731
|
+
return results;
|
|
732
|
+
}
|
|
733
|
+
__name(getXUrl, "getXUrl");
|
|
734
|
+
var parser = new import_rss_parser.default({
|
|
735
|
+
customFields: {
|
|
736
|
+
item: ["description", "link"]
|
|
737
|
+
}
|
|
738
|
+
});
|
|
739
|
+
async function getXNum(session) {
|
|
740
|
+
return session.content.trim().split(" ").slice(1).filter((item) => !isNaN(+item) && item).map((str) => Number(str) - 1);
|
|
741
|
+
}
|
|
742
|
+
__name(getXNum, "getXNum");
|
|
743
|
+
async function getXImage(rssUrl, xUrls) {
|
|
744
|
+
const xUrlsArray = Array.isArray(xUrls) ? xUrls : [xUrls];
|
|
745
|
+
const feed = await parser.parseURL(rssUrl);
|
|
746
|
+
const allImageUrls = [];
|
|
747
|
+
for (const xUrl of xUrlsArray) {
|
|
748
|
+
const item = feed.items.find((i) => i.link === xUrl);
|
|
749
|
+
if (item) {
|
|
750
|
+
const $ = cheerio2.load(item.description);
|
|
751
|
+
$("img").each((_, el) => {
|
|
752
|
+
const src = $(el).attr("src");
|
|
753
|
+
if (src) allImageUrls.push(src);
|
|
754
|
+
});
|
|
755
|
+
}
|
|
756
|
+
}
|
|
757
|
+
return allImageUrls;
|
|
758
|
+
}
|
|
759
|
+
__name(getXImage, "getXImage");
|
|
760
|
+
function chunk(arr, size) {
|
|
761
|
+
const res = [];
|
|
762
|
+
for (let i = 0; i < arr.length; i += size) {
|
|
763
|
+
res.push(arr.slice(i, i + size));
|
|
764
|
+
}
|
|
765
|
+
return res;
|
|
766
|
+
}
|
|
767
|
+
__name(chunk, "chunk");
|
|
768
|
+
async function sendImages(session, cfg, imageUrls) {
|
|
769
|
+
const chunks = chunk(imageUrls, 10);
|
|
770
|
+
for (const group of chunks) {
|
|
771
|
+
const messages = await Promise.all(
|
|
772
|
+
group.map(async (url) => import_koishi3.h.image(await getXImageBase64(url, cfg)))
|
|
773
|
+
);
|
|
774
|
+
if (messages.length > 0) {
|
|
775
|
+
const message = messages.join("");
|
|
776
|
+
await session.send(message);
|
|
777
|
+
} else {
|
|
778
|
+
await session.send("未找到图片,请引用包含图片且处于RSS列表中的的推特链接");
|
|
779
|
+
}
|
|
780
|
+
}
|
|
781
|
+
}
|
|
782
|
+
__name(sendImages, "sendImages");
|
|
783
|
+
async function getXImageBase64(url, cfg) {
|
|
784
|
+
const httpAgent = new import_http_proxy_agent.HttpProxyAgent(cfg.proxyUrl);
|
|
785
|
+
const httpsAgent = new import_https_proxy_agent.HttpsProxyAgent(cfg.proxyUrl);
|
|
786
|
+
import_axios.default.defaults.httpAgent = httpAgent;
|
|
787
|
+
import_axios.default.defaults.httpsAgent = httpsAgent;
|
|
788
|
+
const res = await import_axios.default.get(url, { responseType: "arraybuffer" });
|
|
789
|
+
const base64 = Buffer.from(res.data, "binary").toString("base64");
|
|
790
|
+
const dataUrl = `data:image/png;base64,${base64}`;
|
|
791
|
+
console.log("success");
|
|
792
|
+
return dataUrl;
|
|
793
|
+
}
|
|
794
|
+
__name(getXImageBase64, "getXImageBase64");
|
|
795
|
+
|
|
796
|
+
// src/plugins/drawHead.ts
|
|
797
|
+
var import_koishi4 = require("koishi");
|
|
798
|
+
var import_sharp2 = __toESM(require("sharp"));
|
|
799
|
+
var import_jimp = require("jimp");
|
|
800
|
+
async function handleBanGDreamConfig(options) {
|
|
801
|
+
const types = {
|
|
802
|
+
cool: ["cool", "blue", "蓝", "蓝色"],
|
|
803
|
+
powerful: ["powerful", "red", "红", "红色"],
|
|
804
|
+
pure: ["pure", "green", "绿", "绿色"],
|
|
805
|
+
happy: ["happy", "orange", "橙", "橙色"]
|
|
806
|
+
};
|
|
807
|
+
const bands = {
|
|
808
|
+
ppp: ["ppp", "poppin'Party", "破琵琶", "步品破茶", "poppin", "popipa", "poppinparty", "ポピパ"],
|
|
809
|
+
ag: ["ag", "afterglow", "夕阳红", "悪蓋愚狼"],
|
|
810
|
+
pp: ["pp", "pastel*palettes", "pastel*palettes", "pastelPalettes", "怕死怕累", "pastel", "palettes", "pasupare", "パスパレ", "破巣照破烈斗"],
|
|
811
|
+
hhw: ["hhw", "ハロー、ハッピーワールド!", "hello,happyworld!", "hellohappyworld", "ハロハピ", "hello,happyworld!", "harohapi", "破狼法被威悪怒", "儿歌团", "好好玩"],
|
|
812
|
+
r: ["r", "roselia", "露世里恶", "萝", "露世裏悪", "ロゼリア", "r组", "相声团", "相声组"],
|
|
813
|
+
ras: ["ras", "raiseasuilen", "raise", "suilen", "ラス", "零図悪酔恋", "睡莲", "麗厨唖睡蓮", "睡蓮"],
|
|
814
|
+
mnk: ["mnk", "モニカ", "蝶团", "蝶", "morfonica", "毛二力", "monika", "monica"],
|
|
815
|
+
go: ["go", "mygo!!!!!", "mygo!!!!!", "mygo", "我去!!!!!", "我去!!!!!", "我去", "卖狗"]
|
|
816
|
+
};
|
|
817
|
+
const trains = {
|
|
818
|
+
"color_star": ["花后", "1", "彩", "true"],
|
|
819
|
+
"normal_star": ["花前", "0", "false"]
|
|
820
|
+
};
|
|
821
|
+
const drawConfig = {
|
|
822
|
+
color: "",
|
|
823
|
+
band: "",
|
|
824
|
+
starType: "",
|
|
825
|
+
starNum: 0,
|
|
826
|
+
border: ""
|
|
827
|
+
};
|
|
828
|
+
if (options?.color) {
|
|
829
|
+
for (const [type, aliases] of Object.entries(types)) {
|
|
830
|
+
if (aliases.includes(options.color.toLowerCase())) {
|
|
831
|
+
drawConfig.color = type;
|
|
832
|
+
break;
|
|
833
|
+
}
|
|
834
|
+
}
|
|
835
|
+
}
|
|
836
|
+
if (options?.band) {
|
|
837
|
+
for (const [band, aliases] of Object.entries(bands)) {
|
|
838
|
+
if (aliases.includes(options.band.toLowerCase())) {
|
|
839
|
+
drawConfig.band = band;
|
|
840
|
+
break;
|
|
841
|
+
}
|
|
842
|
+
}
|
|
843
|
+
}
|
|
844
|
+
const starNum = options?.starNum ? parseInt(options.starNum) : 0;
|
|
845
|
+
drawConfig.starNum = starNum > 0 && starNum < 10 ? starNum : 0;
|
|
846
|
+
if (options?.train) {
|
|
847
|
+
for (const [train, aliases] of Object.entries(trains)) {
|
|
848
|
+
if (aliases.includes(options.train.toLowerCase())) {
|
|
849
|
+
drawConfig.starType = train;
|
|
850
|
+
break;
|
|
851
|
+
}
|
|
852
|
+
}
|
|
853
|
+
}
|
|
854
|
+
return drawConfig;
|
|
855
|
+
}
|
|
856
|
+
__name(handleBanGDreamConfig, "handleBanGDreamConfig");
|
|
857
|
+
async function drawLock(ctx, baseImage) {
|
|
858
|
+
const image = await getImageFromUrl(ctx, baseImage);
|
|
859
|
+
if (image === -1) {
|
|
860
|
+
return "发生错误";
|
|
861
|
+
} else if (image === -2) {
|
|
862
|
+
return "输入无效";
|
|
863
|
+
}
|
|
864
|
+
const imageMetadata = await image.metadata();
|
|
865
|
+
const lockUrl = `${baseDir2}/data/starfx-bot/assets/lock.png`;
|
|
866
|
+
const size1 = Math.min(imageMetadata.width, imageMetadata.height);
|
|
867
|
+
image.resize({ width: size1, height: size1, fit: "cover" });
|
|
868
|
+
const overlay = (0, import_sharp2.default)(lockUrl).png();
|
|
869
|
+
overlay.resize({ width: size1 });
|
|
870
|
+
image.composite([{ input: await overlay.toBuffer() }]);
|
|
871
|
+
return import_koishi4.h.image(await image.png().toBuffer(), "image/png");
|
|
872
|
+
}
|
|
873
|
+
__name(drawLock, "drawLock");
|
|
874
|
+
async function drawSold(ctx, baseImage) {
|
|
875
|
+
const image = await getImageFromUrl(ctx, baseImage);
|
|
876
|
+
if (image === -1) {
|
|
877
|
+
return "发生错误";
|
|
878
|
+
} else if (image === -2) {
|
|
879
|
+
return "输入无效";
|
|
880
|
+
}
|
|
881
|
+
const imageMetadata = await image.metadata();
|
|
882
|
+
const size1 = Math.min(imageMetadata.width, imageMetadata.height);
|
|
883
|
+
image.resize({ width: size1, height: size1, fit: "cover" });
|
|
884
|
+
const middle = (0, import_sharp2.default)({
|
|
885
|
+
create: {
|
|
886
|
+
width: size1,
|
|
887
|
+
height: size1,
|
|
888
|
+
channels: 4,
|
|
889
|
+
background: { r: 255, g: 255, b: 255, alpha: 0.4 }
|
|
890
|
+
}
|
|
891
|
+
}).png();
|
|
892
|
+
const soldUrl = `${assetsDir}/sold.png`;
|
|
893
|
+
const overlay = (0, import_sharp2.default)(soldUrl).png();
|
|
894
|
+
const overlaySize = Math.round(size1 * 182 / 240);
|
|
895
|
+
overlay.resize({
|
|
896
|
+
width: overlaySize,
|
|
897
|
+
height: overlaySize
|
|
898
|
+
});
|
|
899
|
+
const topLeft = Math.round(overlaySize * 29 / 182);
|
|
900
|
+
image.composite([
|
|
901
|
+
{ input: await middle.toBuffer() },
|
|
902
|
+
{
|
|
903
|
+
input: await overlay.toBuffer(),
|
|
904
|
+
top: topLeft,
|
|
905
|
+
left: topLeft
|
|
906
|
+
}
|
|
907
|
+
]);
|
|
908
|
+
return import_koishi4.h.image(await image.png().toBuffer(), "image/png");
|
|
909
|
+
}
|
|
910
|
+
__name(drawSold, "drawSold");
|
|
911
|
+
async function drawBanGDream(avatar, inputOptions) {
|
|
912
|
+
if (!avatar) {
|
|
913
|
+
return "";
|
|
914
|
+
}
|
|
915
|
+
const colors = ["cool", "pure", "happy", "powerful"];
|
|
916
|
+
const bands = ["ppp", "ag", "pp", "r", "hhw", "ras", "mnk", "go"];
|
|
917
|
+
const starTypes = ["normal_star", "color_star"];
|
|
918
|
+
const starNums = [1, 2, 3, 4, 5];
|
|
919
|
+
const options = {
|
|
920
|
+
color: inputOptions.color || import_koishi4.Random.pick(colors),
|
|
921
|
+
band: inputOptions.band || import_koishi4.Random.pick(bands),
|
|
922
|
+
starNum: inputOptions.starNum || import_koishi4.Random.pick(starNums),
|
|
923
|
+
starType: inputOptions.starType || "",
|
|
924
|
+
border: inputOptions.border || ""
|
|
925
|
+
};
|
|
926
|
+
options.starType ||= options.starNum < 3 ? starTypes[0] : import_koishi4.Random.pick(starTypes);
|
|
927
|
+
options.border ||= `card-${starNums.includes(options.starNum) ? options.starNum : 5}${options.starNum == 1 ? `-${options.color}` : ""}`;
|
|
928
|
+
let image;
|
|
929
|
+
try {
|
|
930
|
+
image = await import_jimp.Jimp.read(avatar);
|
|
931
|
+
} catch (e) {
|
|
932
|
+
starfxLogger.error(e);
|
|
933
|
+
return;
|
|
934
|
+
}
|
|
935
|
+
const [colorImage, bandImage, starImage, borderImage] = await Promise.all([
|
|
936
|
+
import_jimp.Jimp.read(`${assetsDir}/bangborder/${options.color}.png`),
|
|
937
|
+
import_jimp.Jimp.read(`${assetsDir}/bangborder/${options.band}.png`),
|
|
938
|
+
import_jimp.Jimp.read(`${assetsDir}/bangborder/${options.starType}.png`),
|
|
939
|
+
import_jimp.Jimp.read(`${assetsDir}/bangborder/${options.border}.png`)
|
|
940
|
+
]);
|
|
941
|
+
const zoom = 2;
|
|
942
|
+
image.cover({ w: 500 * zoom, h: 500 * zoom });
|
|
943
|
+
borderImage.cover({ w: 500 * zoom, h: 500 * zoom });
|
|
944
|
+
image.composite(borderImage);
|
|
945
|
+
colorImage.cover({ w: 130 * zoom, h: 130 * zoom });
|
|
946
|
+
image.composite(colorImage, image.width - colorImage.width - 3 * zoom, 5.5);
|
|
947
|
+
bandImage.width > bandImage.height ? bandImage.resize({ w: 120 * zoom }) : bandImage.resize({ h: 120 * zoom });
|
|
948
|
+
image.composite(bandImage, 15 * zoom, 15 * zoom);
|
|
949
|
+
starImage.resize({ w: 90 * zoom });
|
|
950
|
+
const step = 60 * zoom;
|
|
951
|
+
let hei = 410 * zoom;
|
|
952
|
+
let times = options.starNum;
|
|
953
|
+
while (times > 0) {
|
|
954
|
+
image.composite(starImage, 10 * zoom, hei);
|
|
955
|
+
hei -= step;
|
|
956
|
+
times--;
|
|
957
|
+
}
|
|
958
|
+
return `data:image/png;base64,${(await image.getBuffer("image/jpeg")).toString("base64")}`;
|
|
959
|
+
}
|
|
960
|
+
__name(drawBanGDream, "drawBanGDream");
|
|
961
|
+
|
|
927
962
|
// src/index.ts
|
|
928
|
-
var
|
|
963
|
+
var import_node_path3 = __toESM(require("node:path"));
|
|
929
964
|
var import_mime_types = __toESM(require("mime-types"));
|
|
930
965
|
|
|
931
966
|
// package.json
|
|
@@ -935,7 +970,7 @@ var package_default = {
|
|
|
935
970
|
contributors: [
|
|
936
971
|
"StarFreedomX <starfreedomx@outlook.com>"
|
|
937
972
|
],
|
|
938
|
-
version: "0.19.
|
|
973
|
+
version: "0.19.6",
|
|
939
974
|
main: "lib/index.js",
|
|
940
975
|
typings: "lib/index.d.ts",
|
|
941
976
|
files: [
|
|
@@ -985,71 +1020,72 @@ var package_default = {
|
|
|
985
1020
|
|
|
986
1021
|
// src/index.ts
|
|
987
1022
|
var name = "starfx-bot";
|
|
988
|
-
var
|
|
1023
|
+
var inject = ["database"];
|
|
1024
|
+
var baseDir2;
|
|
989
1025
|
var assetsDir;
|
|
990
|
-
var starfxLogger = new
|
|
1026
|
+
var starfxLogger = new import_koishi5.Logger("starfx-bot");
|
|
991
1027
|
var repeatContextMap = /* @__PURE__ */ new Map();
|
|
992
|
-
var
|
|
993
|
-
|
|
994
|
-
openLock:
|
|
995
|
-
openSold:
|
|
996
|
-
bangdreamBorder:
|
|
1028
|
+
var Config3 = import_koishi5.Schema.intersect([
|
|
1029
|
+
import_koishi5.Schema.object({
|
|
1030
|
+
openLock: import_koishi5.Schema.boolean().default(true).description("开启明日方舟封印功能"),
|
|
1031
|
+
openSold: import_koishi5.Schema.boolean().default(true).description('开启闲鱼"卖掉了"功能'),
|
|
1032
|
+
bangdreamBorder: import_koishi5.Schema.boolean().default(true).description("开启BanG Dream!边框功能")
|
|
997
1033
|
}).description("绘图功能"),
|
|
998
|
-
|
|
999
|
-
record:
|
|
1000
|
-
tagWeight:
|
|
1001
|
-
recordLink:
|
|
1002
|
-
linkGroup:
|
|
1003
|
-
linkWeight:
|
|
1034
|
+
import_koishi5.Schema.object({
|
|
1035
|
+
record: import_koishi5.Schema.boolean().default(true).description("开启群语录功能"),
|
|
1036
|
+
tagWeight: import_koishi5.Schema.number().default(5).min(1).description("tag匹配时的权重,越高权重越大"),
|
|
1037
|
+
recordLink: import_koishi5.Schema.dict(import_koishi5.Schema.object({
|
|
1038
|
+
linkGroup: import_koishi5.Schema.string(),
|
|
1039
|
+
linkWeight: import_koishi5.Schema.number()
|
|
1004
1040
|
})).role("table").description("群组链接,使得群可以调用被链接群的语录,<br>可以配置权重,作为键的群自身的权重为100(注意格式为平台名:群组名)"),
|
|
1005
|
-
saveArchive:
|
|
1041
|
+
saveArchive: import_koishi5.Schema.boolean().default(false).description("开启入典功能").hidden()
|
|
1006
1042
|
}).description("语录记录功能"),
|
|
1007
|
-
|
|
1008
|
-
roll:
|
|
1009
|
-
undo:
|
|
1010
|
-
echo:
|
|
1011
|
-
echoBanner:
|
|
1012
|
-
ready:
|
|
1013
|
-
saveReadyAsFile:
|
|
1014
|
-
roomNumber:
|
|
1015
|
-
saveRoomAsFile:
|
|
1016
|
-
forward:
|
|
1017
|
-
searchExchangeRate:
|
|
1018
|
-
intervalGetExchangeRate:
|
|
1043
|
+
import_koishi5.Schema.object({
|
|
1044
|
+
roll: import_koishi5.Schema.boolean().default(true).description("开启roll随机数功能"),
|
|
1045
|
+
undo: import_koishi5.Schema.boolean().default(true).description("机器人撤回消息功能(只测试了qq的onebot适配器)"),
|
|
1046
|
+
echo: import_koishi5.Schema.boolean().default(true).description("echo回声洞功能"),
|
|
1047
|
+
echoBanner: import_koishi5.Schema.array(String).role("table").description("echo屏蔽词,对文本生效"),
|
|
1048
|
+
ready: import_koishi5.Schema.boolean().default(false).description("待机人数记录功能"),
|
|
1049
|
+
saveReadyAsFile: import_koishi5.Schema.string().description("写入待机人数的本地地址,留空则不写入"),
|
|
1050
|
+
roomNumber: import_koishi5.Schema.boolean().default(false).description("主跑房间号记录功能"),
|
|
1051
|
+
saveRoomAsFile: import_koishi5.Schema.string().description("写入房间号的本地地址,留空则不写入"),
|
|
1052
|
+
forward: import_koishi5.Schema.boolean().default(true).description("消息转发功能"),
|
|
1053
|
+
searchExchangeRate: import_koishi5.Schema.boolean().default(false).description("查汇率功能"),
|
|
1054
|
+
intervalGetExchangeRate: import_koishi5.Schema.boolean().default(false).description("汇率定时推送功能").hidden()
|
|
1019
1055
|
}).description("指令小功能"),
|
|
1020
|
-
|
|
1021
|
-
atNotSay:
|
|
1022
|
-
atNotSayProperty:
|
|
1023
|
-
atNotSayOther:
|
|
1024
|
-
atNotSayOtherProperty:
|
|
1025
|
-
iLoveYou:
|
|
1026
|
-
replyBot:
|
|
1056
|
+
import_koishi5.Schema.object({
|
|
1057
|
+
atNotSay: import_koishi5.Schema.boolean().default(true).description("开启‘艾特我又不说话’功能"),
|
|
1058
|
+
atNotSayProperty: import_koishi5.Schema.number().role("slider").min(0).max(1).step(0.01).default(0.5).description("'艾特我又不说话'回复概率"),
|
|
1059
|
+
atNotSayOther: import_koishi5.Schema.boolean().default(true).description("开启‘艾特他又不说话’功能"),
|
|
1060
|
+
atNotSayOtherProperty: import_koishi5.Schema.number().role("slider").min(0).max(1).step(0.01).default(0.5).description("'艾特他又不说话'回复概率"),
|
|
1061
|
+
iLoveYou: import_koishi5.Schema.boolean().default(true).description("开启‘我喜欢你’功能"),
|
|
1062
|
+
replyBot: import_koishi5.Schema.union(["关闭", "无需at", "必须at"]).default("无需at").description("回复‘我才不是机器人!’功能")
|
|
1027
1063
|
}).description("特定回应功能"),
|
|
1028
|
-
|
|
1029
|
-
sendLocalImage:
|
|
1030
|
-
hiddenInHelp:
|
|
1031
|
-
imgPath:
|
|
1064
|
+
import_koishi5.Schema.object({
|
|
1065
|
+
sendLocalImage: import_koishi5.Schema.dict(import_koishi5.Schema.object({
|
|
1066
|
+
hiddenInHelp: import_koishi5.Schema.boolean(),
|
|
1067
|
+
imgPath: import_koishi5.Schema.string()
|
|
1032
1068
|
})).role("table").description("特定指令发送本地图片功能,其中键是指令名称,imgPath是图片文件的绝对路径")
|
|
1033
1069
|
}),
|
|
1034
|
-
|
|
1035
|
-
openRepeat:
|
|
1036
|
-
minRepeatTimes:
|
|
1037
|
-
repeatPossibility:
|
|
1070
|
+
import_koishi5.Schema.object({
|
|
1071
|
+
openRepeat: import_koishi5.Schema.boolean().default(true).description("开启复读功能"),
|
|
1072
|
+
minRepeatTimes: import_koishi5.Schema.number().default(2).description("最少重复次数"),
|
|
1073
|
+
repeatPossibility: import_koishi5.Schema.number().role("slider").min(0).max(1).step(0.01).default(0.3).description("复读发生概率")
|
|
1038
1074
|
}).description("复读功能"),
|
|
1039
|
-
|
|
1040
|
-
filePathToBase64:
|
|
1041
|
-
originImg:
|
|
1075
|
+
import_koishi5.Schema.object({
|
|
1076
|
+
filePathToBase64: import_koishi5.Schema.boolean().default(false).description("在消息发送前检查是否有file://,如果有那么转换为base64再发送"),
|
|
1077
|
+
originImg: import_koishi5.Schema.boolean().default(false).description("根据链接获取原图开关")
|
|
1042
1078
|
}).description("自用功能"),
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
originImg:
|
|
1046
|
-
originImgRSSUrl:
|
|
1047
|
-
proxyUrl:
|
|
1079
|
+
import_koishi5.Schema.union([
|
|
1080
|
+
import_koishi5.Schema.object({
|
|
1081
|
+
originImg: import_koishi5.Schema.const(true).required(),
|
|
1082
|
+
originImgRSSUrl: import_koishi5.Schema.string().required().description("推特列表rss地址"),
|
|
1083
|
+
proxyUrl: import_koishi5.Schema.string().default("http://127.0.0.1:7890").description("代理地址")
|
|
1048
1084
|
}),
|
|
1049
|
-
|
|
1085
|
+
import_koishi5.Schema.object({})
|
|
1050
1086
|
]),
|
|
1051
|
-
|
|
1052
|
-
featureControl:
|
|
1087
|
+
import_koishi5.Schema.object({
|
|
1088
|
+
featureControl: import_koishi5.Schema.string().role("textarea", { rows: [15] }).default("{\n\n}").description(`黑/白名单配置,语法为JSON格式(可以不缩进),<br>
|
|
1053
1089
|
可配置功能键及语法详见 [项目地址](https://github.com/StarFreedomX/starfx-bot)或[npm发布页](https://www.npmjs.com/package/koishi-plugin-bangdream-ccg)`)
|
|
1054
1090
|
}).description("高级配置")
|
|
1055
1091
|
]);
|
|
@@ -1057,7 +1093,7 @@ var usage = `<h2>StarFreedomX的自用插件 放了一些小功能</h2>
|
|
|
1057
1093
|
`;
|
|
1058
1094
|
function apply(ctx, cfg) {
|
|
1059
1095
|
ctx.i18n.define("zh-CN", require_zh_CN());
|
|
1060
|
-
|
|
1096
|
+
baseDir2 = ctx.baseDir;
|
|
1061
1097
|
assetsDir = `${ctx.baseDir}/data/starfx-bot/assets`;
|
|
1062
1098
|
initAssets();
|
|
1063
1099
|
const controlJson = parseJsonControl(cfg.featureControl);
|
|
@@ -1120,7 +1156,7 @@ function apply(ctx, cfg) {
|
|
|
1120
1156
|
if (!imgSrc?.length) return "输入无效";
|
|
1121
1157
|
const imageBase64 = await drawBanGDream(imgSrc, drawConfig);
|
|
1122
1158
|
if (!imageBase64?.length) return "输入无效";
|
|
1123
|
-
await session.send(
|
|
1159
|
+
await session.send(import_koishi5.h.image(imageBase64));
|
|
1124
1160
|
}
|
|
1125
1161
|
});
|
|
1126
1162
|
}
|
|
@@ -1149,14 +1185,14 @@ function apply(ctx, cfg) {
|
|
|
1149
1185
|
const filepath = await getRecord(cfg, session.gid.replaceAll(":", "_"), tag);
|
|
1150
1186
|
starfxLogger.info(`send record: ${filepath}`);
|
|
1151
1187
|
if (!filepath) return "暂无语录呢";
|
|
1152
|
-
await session.send(
|
|
1188
|
+
await session.send(import_koishi5.h.image(filepath));
|
|
1153
1189
|
}
|
|
1154
1190
|
});
|
|
1155
1191
|
}
|
|
1156
1192
|
for (const key in cfg.sendLocalImage) {
|
|
1157
1193
|
ctx.command(key, { hidden: cfg.sendLocalImage[key].hiddenInHelp }).action(async ({ session }) => {
|
|
1158
1194
|
if (detectControl(controlJson, session.guildId, "sendLocalImage") && detectControl(controlJson, session.guildId, key))
|
|
1159
|
-
return
|
|
1195
|
+
return import_koishi5.h.image(safeQuote(cfg.sendLocalImage[key].imgPath, false));
|
|
1160
1196
|
});
|
|
1161
1197
|
}
|
|
1162
1198
|
if (cfg.roomNumber) {
|
|
@@ -1203,7 +1239,7 @@ function apply(ctx, cfg) {
|
|
|
1203
1239
|
if (cfg.forward) {
|
|
1204
1240
|
ctx.command("forward").option("group", "-g <group:string>").option("platform", "-p <platform:string>").usage("转发消息").action(async ({ session, options }) => {
|
|
1205
1241
|
if (detectControl(controlJson, session.guildId, "forward")) {
|
|
1206
|
-
const mapPath =
|
|
1242
|
+
const mapPath = import_node_path3.default.join(assetsDir, "forward.json");
|
|
1207
1243
|
const groupMap = readMap(mapPath);
|
|
1208
1244
|
if (options.group) {
|
|
1209
1245
|
if (["0", "clear", "del"].includes(options.group)) {
|
|
@@ -1250,7 +1286,7 @@ function apply(ctx, cfg) {
|
|
|
1250
1286
|
if (cfg.intervalGetExchangeRate) {
|
|
1251
1287
|
ctx.command("开启汇率推送 [exchangeParam:string]").action(async ({ session }, exchangeParam) => {
|
|
1252
1288
|
if (detectControl(controlJson, session.guildId, "exchangeRate")) {
|
|
1253
|
-
const exchangeRatePath =
|
|
1289
|
+
const exchangeRatePath = import_node_path3.default.join(assetsDir, "exchangeRate.json");
|
|
1254
1290
|
return await intervalGetExchangeRate(ctx, cfg, session, exchangeParam, exchangeRatePath);
|
|
1255
1291
|
}
|
|
1256
1292
|
});
|
|
@@ -1300,7 +1336,7 @@ function apply(ctx, cfg) {
|
|
|
1300
1336
|
if (!ctxArr || ctxArr[0] !== content) {
|
|
1301
1337
|
repeatContextMap.set(session.gid, [content, 1]);
|
|
1302
1338
|
} else {
|
|
1303
|
-
if (ctxArr[1] !== -1 && ++ctxArr[1] >= cfg.minRepeatTimes &&
|
|
1339
|
+
if (ctxArr[1] !== -1 && ++ctxArr[1] >= cfg.minRepeatTimes && import_koishi5.Random.bool(cfg.repeatPossibility)) {
|
|
1304
1340
|
ctxArr[1] = -1;
|
|
1305
1341
|
await session.send(content);
|
|
1306
1342
|
}
|
|
@@ -1315,18 +1351,17 @@ function apply(ctx, cfg) {
|
|
|
1315
1351
|
return next();
|
|
1316
1352
|
});
|
|
1317
1353
|
if (process.env.NODE_ENV === "development") {
|
|
1318
|
-
ctx.command("test").action(async ({ session }) => {
|
|
1319
|
-
await session.send(" d d ");
|
|
1354
|
+
ctx.command("test [params]").action(async ({ session, options }, params) => {
|
|
1320
1355
|
});
|
|
1321
1356
|
ctx.middleware(async (session, next) => {
|
|
1322
1357
|
return next();
|
|
1323
1358
|
});
|
|
1324
1359
|
}
|
|
1325
1360
|
function initAssets() {
|
|
1326
|
-
const defaultAssetsDir =
|
|
1327
|
-
assetsDir =
|
|
1361
|
+
const defaultAssetsDir = import_node_path3.default.join(__dirname, "../assets");
|
|
1362
|
+
assetsDir = import_node_path3.default.join(ctx.baseDir, "data/starfx-bot/assets");
|
|
1328
1363
|
if (!fs2.existsSync(assetsDir)) fs2.mkdirSync(assetsDir, { recursive: true });
|
|
1329
|
-
const versionFile =
|
|
1364
|
+
const versionFile = import_node_path3.default.join(assetsDir, "plugin_version.json");
|
|
1330
1365
|
let localVersion = "0";
|
|
1331
1366
|
if (fs2.existsSync(versionFile)) {
|
|
1332
1367
|
try {
|
|
@@ -1355,6 +1390,7 @@ __name(apply, "apply");
|
|
|
1355
1390
|
apply,
|
|
1356
1391
|
assetsDir,
|
|
1357
1392
|
baseDir,
|
|
1393
|
+
inject,
|
|
1358
1394
|
name,
|
|
1359
1395
|
repeatContextMap,
|
|
1360
1396
|
starfxLogger,
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { Config } from "../index";
|
|
2
|
+
import { Context, Session } from "koishi";
|
|
3
|
+
interface CurrencyCode {
|
|
4
|
+
"country": string;
|
|
5
|
+
"currencyCn": string;
|
|
6
|
+
"code": string;
|
|
7
|
+
}
|
|
8
|
+
export declare function intervalGetExchangeRate(ctx: Context, cfg: Config, session: Session, searchString: string, exchangeRatePath: string): Promise<void>;
|
|
9
|
+
export declare function getExchangeRate(ctx: Context, cfg: Config, session: Session, searchString?: string, raw?: string, retryTimes?: number): Promise<void>;
|
|
10
|
+
/**
|
|
11
|
+
* 绘制走势图
|
|
12
|
+
* @param prices 收盘价数组
|
|
13
|
+
* @param timeStamps ISO 时间戳数组
|
|
14
|
+
* @param title 图表标题
|
|
15
|
+
* @param width 图表宽度
|
|
16
|
+
* @param height 图表高度
|
|
17
|
+
* @returns buffer
|
|
18
|
+
*/
|
|
19
|
+
export declare function drawCurrencyChartSkia(prices: number[], timeStamps: string[], title?: string, width?: number, height?: number): Promise<Buffer>;
|
|
20
|
+
export declare function getCurrencyCodes(): Promise<CurrencyCode[]>;
|
|
21
|
+
export declare function getCurrencyCodesMap(): Promise<Record<string, string>>;
|
|
22
|
+
export {};
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { Context, h } from "koishi";
|
|
2
|
+
/**
|
|
3
|
+
* 将options的参数转换为drawBanGDreamBorder的配置
|
|
4
|
+
* @param options
|
|
5
|
+
* @return 适用于边框绘制的参数
|
|
6
|
+
*/
|
|
7
|
+
export declare function handleBanGDreamConfig(options: any): Promise<{
|
|
8
|
+
color: string;
|
|
9
|
+
band: string;
|
|
10
|
+
starType: string;
|
|
11
|
+
starNum: number;
|
|
12
|
+
border: string;
|
|
13
|
+
}>;
|
|
14
|
+
/**
|
|
15
|
+
* "封印"绘图功能
|
|
16
|
+
* @param ctx Context
|
|
17
|
+
* @param baseImage 被封印的图片url
|
|
18
|
+
* @return 画完的图片 h对象
|
|
19
|
+
*/
|
|
20
|
+
export declare function drawLock(ctx: Context, baseImage: string): Promise<"发生错误" | "输入无效" | h>;
|
|
21
|
+
/**
|
|
22
|
+
* "卖掉了"绘图函数
|
|
23
|
+
* @param ctx
|
|
24
|
+
* @param baseImage
|
|
25
|
+
* @return 画完的图片 h对象
|
|
26
|
+
*/
|
|
27
|
+
export declare function drawSold(ctx: Context, baseImage: string): Promise<"发生错误" | "输入无效" | h>;
|
|
28
|
+
/**
|
|
29
|
+
* BanG Dream!边框绘制功能
|
|
30
|
+
* @param avatar 要绘制的底图
|
|
31
|
+
* @param inputOptions 输入参数,接受color band starType starNum border
|
|
32
|
+
*/
|
|
33
|
+
export declare function drawBanGDream(avatar: string, inputOptions?: {
|
|
34
|
+
color: string;
|
|
35
|
+
band: string;
|
|
36
|
+
starType: string;
|
|
37
|
+
starNum: number;
|
|
38
|
+
border: string;
|
|
39
|
+
}): Promise<string>;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { Session } from "koishi";
|
|
2
|
+
import { Config } from "../index";
|
|
3
|
+
export declare function getXUrl(urls: string): Promise<any[]>;
|
|
4
|
+
export declare function getXNum(session: Session): Promise<number[]>;
|
|
5
|
+
export declare function getXImage(rssUrl: string, xUrls: string | string[]): Promise<string[]>;
|
|
6
|
+
export declare function chunk<T>(arr: T[], size: number): T[][];
|
|
7
|
+
export declare function sendImages(session: Session, cfg: Config, imageUrls: string[]): Promise<void>;
|
package/lib/utils.d.ts
CHANGED
|
@@ -63,32 +63,6 @@ export declare function getImageSrc(session: Session, param: string, option?: {
|
|
|
63
63
|
noParam?: boolean;
|
|
64
64
|
quote?: boolean;
|
|
65
65
|
}): Promise<string>;
|
|
66
|
-
/**
|
|
67
|
-
* 将options的参数转换为drawBanGDreamBorder的配置
|
|
68
|
-
* @param options
|
|
69
|
-
* @return 适用于边框绘制的参数
|
|
70
|
-
*/
|
|
71
|
-
export declare function handleBanGDreamConfig(options: any): Promise<{
|
|
72
|
-
color: string;
|
|
73
|
-
band: string;
|
|
74
|
-
starType: string;
|
|
75
|
-
starNum: number;
|
|
76
|
-
border: string;
|
|
77
|
-
}>;
|
|
78
|
-
/**
|
|
79
|
-
* "封印"绘图功能
|
|
80
|
-
* @param ctx Context
|
|
81
|
-
* @param baseImage 被封印的图片url
|
|
82
|
-
* @return 画完的图片 h对象
|
|
83
|
-
*/
|
|
84
|
-
export declare function drawLock(ctx: Context, baseImage: string): Promise<"发生错误" | "输入无效" | h>;
|
|
85
|
-
/**
|
|
86
|
-
* "卖掉了"绘图函数
|
|
87
|
-
* @param ctx
|
|
88
|
-
* @param baseImage
|
|
89
|
-
* @return 画完的图片 h对象
|
|
90
|
-
*/
|
|
91
|
-
export declare function drawSold(ctx: Context, baseImage: string): Promise<"发生错误" | "输入无效" | h>;
|
|
92
66
|
/**
|
|
93
67
|
* 从url下载图片并返回sharp对象
|
|
94
68
|
* @param ctx Context
|
|
@@ -117,20 +91,6 @@ export declare function replyBot(cfg: Config, session: Session, elements: h[]):
|
|
|
117
91
|
* @param elements 当前消息elements
|
|
118
92
|
*/
|
|
119
93
|
export declare function iLoveYou(cfg: Config, session: Session, elements: h[]): Promise<void>;
|
|
120
|
-
/**
|
|
121
|
-
* BanG Dream!边框绘制功能
|
|
122
|
-
* @param avatar 要绘制的底图
|
|
123
|
-
* @param inputOptions 输入参数,接受color band starType starNum border
|
|
124
|
-
*/
|
|
125
|
-
export declare function drawBanGDream(avatar: string, inputOptions?: {
|
|
126
|
-
color: string;
|
|
127
|
-
band: string;
|
|
128
|
-
starType: string;
|
|
129
|
-
starNum: number;
|
|
130
|
-
border: string;
|
|
131
|
-
}): Promise<string>;
|
|
132
|
-
export declare function intervalGetExchangeRate(ctx: Context, cfg: Config, session: Session, searchString: string, exchangeRatePath: string): Promise<void>;
|
|
133
|
-
export declare function getExchangeRate(ctx: Context, cfg: Config, session: Session, searchString?: string, raw?: string, retryTimes?: number): Promise<void>;
|
|
134
94
|
export declare function parseJsonControl(text: string): FeatureControl | null;
|
|
135
95
|
export declare function detectControl(controlJson: FeatureControl, guildId: string, funName: string): boolean;
|
|
136
96
|
export declare function handleRoll(session: Session): string;
|
|
@@ -140,31 +100,9 @@ export declare function handleRoll(session: Session): string;
|
|
|
140
100
|
* @param session session
|
|
141
101
|
*/
|
|
142
102
|
export declare function undo(cfg: Config, session: Session): Promise<void>;
|
|
143
|
-
export declare function getXUrl(urls: string): Promise<any[]>;
|
|
144
|
-
export declare function getXNum(session: Session): Promise<number[]>;
|
|
145
|
-
export declare function getXImage(rssUrl: string, xUrls: string | string[]): Promise<string[]>;
|
|
146
|
-
export declare function chunk<T>(arr: T[], size: number): T[][];
|
|
147
|
-
export declare function sendImages(session: Session, cfg: Config, imageUrls: string[]): Promise<void>;
|
|
148
103
|
export declare function safeQuote(str: string, useQuote: boolean): string;
|
|
149
|
-
export declare function test(url: string): Promise<void>;
|
|
150
104
|
export declare function writeMap(map: Map<any, any>, dest: string): void;
|
|
151
105
|
export declare function readMap(url: string): Map<any, any>;
|
|
152
106
|
export declare function ready(session: Session, cfg: Config, param: string, readyMap: Map<string, string[]>): string;
|
|
153
|
-
|
|
154
|
-
* 绘制近一个月收盘价走势图
|
|
155
|
-
* @param prices 收盘价数组
|
|
156
|
-
* @param timeStamps ISO 时间戳数组
|
|
157
|
-
* @param title 图表标题
|
|
158
|
-
* @param width 图表宽度
|
|
159
|
-
* @param height 图表高度
|
|
160
|
-
* @returns buffer
|
|
161
|
-
*/
|
|
162
|
-
export declare function drawOneMonthChartSkia(prices: number[], timeStamps: string[], title?: string, width?: number, height?: number): Promise<Buffer>;
|
|
163
|
-
interface CurrencyCode {
|
|
164
|
-
"country": string;
|
|
165
|
-
"currencyCn": string;
|
|
166
|
-
"code": string;
|
|
167
|
-
}
|
|
168
|
-
export declare function getCurrencyCodes(): Promise<CurrencyCode[]>;
|
|
169
|
-
export declare function getCurrencyCodesMap(): Promise<Record<string, string>>;
|
|
107
|
+
export declare function test(url: string): Promise<void>;
|
|
170
108
|
export {};
|
package/package.json
CHANGED
package/readme.md
CHANGED
|
@@ -89,35 +89,32 @@ StarFreedomX机器人的小功能,自用
|
|
|
89
89
|
## 更新日志
|
|
90
90
|
|
|
91
91
|
|
|
92
|
-
| 版本 | 更新日志
|
|
93
|
-
|
|
94
|
-
| `0.0.1` | 加入封印功能
|
|
95
|
-
| `0.1.0` | 加入"卖掉了"功能
|
|
96
|
-
| `0.2.0` | 加入"艾特我又不说话"回复功能
|
|
97
|
-
| `0.3.0` | 加入"我喜欢你"和"我才不是机器人!"回复功能
|
|
98
|
-
| `0.4.0` | 更改处理库为sharp
|
|
99
|
-
| `0.5.0` | 加入BanG Dream!边框功能
|
|
100
|
-
| `0.6.0` | 加入群语录功能,修复一处bangdream绘制的bug
|
|
101
|
-
| `0.7.0` | 加入复读功能
|
|
102
|
-
| `0.8.0` | 将各个工具函数封装在utils.ts中,更改语录的触发方式
|
|
103
|
-
| `0.9.0` | 添加白名单/黑名单模式,对每个功能做过滤
|
|
104
|
-
| `0.10.0` | 添加随机数功能
|
|
105
|
-
| `0.11.0` | 增加适配于onebot(主要是qq)的撤回功能
|
|
106
|
-
| `0.12.0` | 加入echo功能
|
|
107
|
-
| `0.13.0` | 语录支持tag以及调整权重
|
|
108
|
-
| `0.14.0` | echo增加对引用消息的支持,且支持有at触发
|
|
109
|
-
| `0.15.0` | 自用rss获取推特原图
|
|
110
|
-
| `0.16.0` | 新增自定义指令发送本地图片功能(其实网络图片也行)
|
|
111
|
-
| `0.16.
|
|
112
|
-
| `0.
|
|
113
|
-
| `0.
|
|
114
|
-
| `0.
|
|
115
|
-
| `0.
|
|
116
|
-
| `0.
|
|
117
|
-
| `0.
|
|
118
|
-
| `0.
|
|
119
|
-
| `0.
|
|
120
|
-
| `0.19.
|
|
121
|
-
| `0.19.1` | 查汇率适配更多语法 |
|
|
122
|
-
| `0.19.2` | 查汇率修复文件缺失 |
|
|
123
|
-
| `0.19.3` | 转移currency.json到assets |
|
|
92
|
+
| 版本 | 更新日志 |
|
|
93
|
+
|----------|-----------------------------------|
|
|
94
|
+
| `0.0.1` | 加入封印功能 |
|
|
95
|
+
| `0.1.0` | 加入"卖掉了"功能 |
|
|
96
|
+
| `0.2.0` | 加入"艾特我又不说话"回复功能 |
|
|
97
|
+
| `0.3.0` | 加入"我喜欢你"和"我才不是机器人!"回复功能 |
|
|
98
|
+
| `0.4.0` | 更改处理库为sharp |
|
|
99
|
+
| `0.5.0` | 加入BanG Dream!边框功能 |
|
|
100
|
+
| `0.6.0` | 加入群语录功能,修复一处bangdream绘制的bug |
|
|
101
|
+
| `0.7.0` | 加入复读功能 |
|
|
102
|
+
| `0.8.0` | 将各个工具函数封装在utils.ts中,更改语录的触发方式 |
|
|
103
|
+
| `0.9.0` | 添加白名单/黑名单模式,对每个功能做过滤 |
|
|
104
|
+
| `0.10.0` | 添加随机数功能 |
|
|
105
|
+
| `0.11.0` | 增加适配于onebot(主要是qq)的撤回功能 |
|
|
106
|
+
| `0.12.0` | 加入echo功能 |
|
|
107
|
+
| `0.13.0` | 语录支持tag以及调整权重 |
|
|
108
|
+
| `0.14.0` | echo增加对引用消息的支持,且支持有at触发 |
|
|
109
|
+
| `0.15.0` | 自用rss获取推特原图 |
|
|
110
|
+
| `0.16.0` | 新增自定义指令发送本地图片功能(其实网络图片也行) |
|
|
111
|
+
| `0.16.3` | 发送文件前转为使用base64 |
|
|
112
|
+
| `0.17.0` | 语录功能新增链接,可以配置权重 |
|
|
113
|
+
| `0.18.0` | 新增定时echo |
|
|
114
|
+
| `0.19.0` | 新增查汇率功能 |
|
|
115
|
+
| `0.19.1` | 查汇率适配更多语法 |
|
|
116
|
+
| `0.19.2` | 查汇率修复文件缺失 |
|
|
117
|
+
| `0.19.3` | 转移currency.json到assets |
|
|
118
|
+
| `0.19.4` | inject database for ctx.broadcast |
|
|
119
|
+
| `0.19.5` | 提取代码量较大的功能为单独插件 |
|
|
120
|
+
| `0.19.6` | 查汇率支持近5d |
|