koishi-plugin-booth-get 5.2.4 → 5.2.5
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.js +85 -16
- package/package.json +1 -1
package/lib/index.js
CHANGED
|
@@ -438,13 +438,27 @@ function apply(ctx, config) {
|
|
|
438
438
|
}
|
|
439
439
|
});
|
|
440
440
|
|
|
441
|
-
ctx.command("摊位名称 <query>")
|
|
442
|
-
.
|
|
441
|
+
ctx.command("摊位名称 <query:text>")
|
|
442
|
+
.option('author', '-a <author> 指定作者名称')
|
|
443
|
+
.action(async ({ session, options }, query) => {
|
|
443
444
|
if (!query) return "请输入搜索关键词";
|
|
444
445
|
|
|
446
|
+
let searchQuery = query;
|
|
447
|
+
let authorFilter = options.author;
|
|
448
|
+
|
|
449
|
+
if (!authorFilter && query.includes(' ')) {
|
|
450
|
+
const parts = query.split(' ');
|
|
451
|
+
if (parts.length >= 2) {
|
|
452
|
+
authorFilter = parts.pop();
|
|
453
|
+
searchQuery = parts.join(' ');
|
|
454
|
+
}
|
|
455
|
+
}
|
|
456
|
+
|
|
457
|
+
let searchUrl = `https://booth.pm/zh-cn/search/${encodeURIComponent(searchQuery)}?in_stock=true`;
|
|
458
|
+
|
|
445
459
|
const tags = ['3Dモデル', 'Vrchat'];
|
|
446
460
|
const tagsParams = tags.map(tag => `tags[]=${encodeURIComponent(tag)}`).join('&');
|
|
447
|
-
|
|
461
|
+
searchUrl += `&${tagsParams}&min_price=4500`;
|
|
448
462
|
|
|
449
463
|
const page = await ctx.puppeteer.page();
|
|
450
464
|
|
|
@@ -473,10 +487,30 @@ function apply(ctx, config) {
|
|
|
473
487
|
}
|
|
474
488
|
|
|
475
489
|
const content = await page.content();
|
|
476
|
-
|
|
477
|
-
const
|
|
490
|
+
|
|
491
|
+
const itemRegex = /item-card__wrap"[\s\S]*?id="item_(\d+)"[\s\S]*?<h2[^>]*class="[^"]*item-card__title[^"]*"[^>]*>([^<]+)<\/h2>/g;
|
|
492
|
+
let matches = [];
|
|
493
|
+
let match;
|
|
494
|
+
|
|
495
|
+
while ((match = itemRegex.exec(content)) !== null) {
|
|
496
|
+
matches.push({
|
|
497
|
+
id: match[1],
|
|
498
|
+
title: match[2].trim()
|
|
499
|
+
});
|
|
500
|
+
}
|
|
501
|
+
|
|
502
|
+
if (matches.length === 0) {
|
|
503
|
+
const simpleRegex = /item-card__wrap"[\s\S]*?id="item_(\d+)"/g;
|
|
504
|
+
let simpleMatch;
|
|
505
|
+
while ((simpleMatch = simpleRegex.exec(content)) !== null) {
|
|
506
|
+
matches.push({
|
|
507
|
+
id: simpleMatch[1],
|
|
508
|
+
title: '未知商品'
|
|
509
|
+
});
|
|
510
|
+
}
|
|
511
|
+
}
|
|
478
512
|
|
|
479
|
-
if (
|
|
513
|
+
if (matches.length === 0) {
|
|
480
514
|
if (content.includes('検索結果はありません') ||
|
|
481
515
|
content.includes('没有找到') ||
|
|
482
516
|
content.includes('検索条件に合致する作品は見つかりませんでした') ||
|
|
@@ -486,10 +520,30 @@ function apply(ctx, config) {
|
|
|
486
520
|
return "没有找到相关商品";
|
|
487
521
|
}
|
|
488
522
|
|
|
489
|
-
|
|
523
|
+
let selectedItemId;
|
|
524
|
+
if (authorFilter) {
|
|
525
|
+
for (const item of matches) {
|
|
526
|
+
try {
|
|
527
|
+
const itemDetail = await getBoothItem(item.id);
|
|
528
|
+
if (itemDetail && itemDetail.author &&
|
|
529
|
+
itemDetail.author.toLowerCase().includes(authorFilter.toLowerCase())) {
|
|
530
|
+
selectedItemId = item.id;
|
|
531
|
+
break;
|
|
532
|
+
}
|
|
533
|
+
} catch (err) {
|
|
534
|
+
continue;
|
|
535
|
+
}
|
|
536
|
+
}
|
|
537
|
+
|
|
538
|
+
if (!selectedItemId) {
|
|
539
|
+
return `找不到作者"${authorFilter}"的相关商品`;
|
|
540
|
+
}
|
|
541
|
+
} else {
|
|
542
|
+
selectedItemId = matches[0].id;
|
|
543
|
+
}
|
|
490
544
|
|
|
491
545
|
try {
|
|
492
|
-
const buffer = await captureCard(ctx,
|
|
546
|
+
const buffer = await captureCard(ctx, selectedItemId);
|
|
493
547
|
if (!buffer) {
|
|
494
548
|
return "卡片生成失败";
|
|
495
549
|
}
|
|
@@ -528,22 +582,17 @@ function apply(ctx, config) {
|
|
|
528
582
|
|
|
529
583
|
ctx.middleware(async (session, next) => {
|
|
530
584
|
const boothUrlRegex = /https:\/\/booth.pm\/[\w-]+\/items\/(\d+)/;
|
|
585
|
+
const boothAuthorUrlRegex = /https:\/\/([\w-]+)\.booth\.pm\/items(?:\/(\d+))?/;
|
|
531
586
|
const match = session.content.match(boothUrlRegex);
|
|
587
|
+
const authorMatch = session.content.match(boothAuthorUrlRegex);
|
|
532
588
|
|
|
533
589
|
if (match) {
|
|
534
|
-
if (session.onebot) {
|
|
535
|
-
session.onebot._sned = session.send;
|
|
536
|
-
session.send = function (...args) {
|
|
537
|
-
return this._sned.apply(this, args);
|
|
538
|
-
};
|
|
539
|
-
}
|
|
540
|
-
|
|
541
590
|
const itemId = match[1];
|
|
542
591
|
try {
|
|
543
592
|
const buffer = await captureCard(ctx, itemId);
|
|
544
593
|
if (buffer) {
|
|
545
594
|
await session.send(import_koishi.h.image(buffer, "image/png"));
|
|
546
|
-
return;
|
|
595
|
+
return "";
|
|
547
596
|
} else {
|
|
548
597
|
return "商品解析失败";
|
|
549
598
|
}
|
|
@@ -551,6 +600,26 @@ function apply(ctx, config) {
|
|
|
551
600
|
logger.warn("链接解析失败:", error);
|
|
552
601
|
return "商品解析失败";
|
|
553
602
|
}
|
|
603
|
+
} else if (authorMatch) {
|
|
604
|
+
const authorName = authorMatch[1];
|
|
605
|
+
const itemId = authorMatch[2];
|
|
606
|
+
|
|
607
|
+
try {
|
|
608
|
+
if (itemId) {
|
|
609
|
+
const buffer = await captureCard(ctx, itemId);
|
|
610
|
+
if (buffer) {
|
|
611
|
+
await session.send(import_koishi.h.image(buffer, "image/png"));
|
|
612
|
+
return "";
|
|
613
|
+
} else {
|
|
614
|
+
return "商品解析失败";
|
|
615
|
+
}
|
|
616
|
+
} else {
|
|
617
|
+
return `检测到作者"${authorName}"的主页链接。请使用"摊位名称 <商品名> ${authorName}"来搜索该作者的商品。`;
|
|
618
|
+
}
|
|
619
|
+
} catch (error) {
|
|
620
|
+
logger.warn("作者链接解析失败:", error);
|
|
621
|
+
return "作者链接解析失败";
|
|
622
|
+
}
|
|
554
623
|
}
|
|
555
624
|
return next();
|
|
556
625
|
});
|