koishi-plugin-booth-get 5.2.2 → 5.2.4
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 +87 -34
- package/package.json +1 -1
package/lib/index.js
CHANGED
|
@@ -347,7 +347,7 @@ async function getBoothItem(id) {
|
|
|
347
347
|
fetch(`https://booth.pm/zh-cn/items/${id}.json`),
|
|
348
348
|
fetch(`https://accounts.booth.pm/wish_lists.json?item_ids%5B%5D=${id}`)
|
|
349
349
|
]);
|
|
350
|
-
|
|
350
|
+
|
|
351
351
|
const itemData = await itemRes.json();
|
|
352
352
|
const wishData = await wishRes.json();
|
|
353
353
|
|
|
@@ -360,7 +360,7 @@ async function getBoothItem(id) {
|
|
|
360
360
|
category: itemData.category?.name,
|
|
361
361
|
parent_category: itemData.category?.parent?.name,
|
|
362
362
|
author: itemData.shop?.name,
|
|
363
|
-
author_thumbnail_url: itemData.shop?.
|
|
363
|
+
author_thumbnail_url: itemData.shop?.thumbnail_url,
|
|
364
364
|
likes: wishData.wishlists_counts[id] || 0,
|
|
365
365
|
tags: itemData.tags
|
|
366
366
|
};
|
|
@@ -393,21 +393,21 @@ async function captureCard(ctx, id) {
|
|
|
393
393
|
if (!item) return null;
|
|
394
394
|
|
|
395
395
|
const relatedItems = await fetchRelatedItems(item.author);
|
|
396
|
-
|
|
396
|
+
|
|
397
397
|
const html = generateCardHTML(item, relatedItems);
|
|
398
398
|
|
|
399
399
|
const page = await ctx.puppeteer.page();
|
|
400
400
|
try {
|
|
401
401
|
await page.setRequestInterception(true);
|
|
402
402
|
page.on('request', (request) => request.continue());
|
|
403
|
-
|
|
404
|
-
await page.setContent(html, {
|
|
403
|
+
|
|
404
|
+
await page.setContent(html, {
|
|
405
405
|
waitUntil: 'domcontentloaded',
|
|
406
406
|
timeout: ctx.config.loadTimeout || import_koishi.Time.second * 10
|
|
407
407
|
});
|
|
408
|
-
|
|
408
|
+
|
|
409
409
|
await new Promise(resolve => setTimeout(resolve, 2000));
|
|
410
|
-
|
|
410
|
+
|
|
411
411
|
await page.setViewport({ width: 640, height: 1200 });
|
|
412
412
|
const container = await page.$('.container');
|
|
413
413
|
return await container.screenshot({
|
|
@@ -438,65 +438,118 @@ function apply(ctx, config) {
|
|
|
438
438
|
}
|
|
439
439
|
});
|
|
440
440
|
|
|
441
|
-
|
|
441
|
+
ctx.command("摊位名称 <query>")
|
|
442
442
|
.action(async ({ session }, query) => {
|
|
443
|
-
if (!query) return "
|
|
443
|
+
if (!query) return "请输入搜索关键词";
|
|
444
444
|
|
|
445
|
-
const tags = ['Vrchat'];
|
|
445
|
+
const tags = ['3Dモデル', 'Vrchat'];
|
|
446
446
|
const tagsParams = tags.map(tag => `tags[]=${encodeURIComponent(tag)}`).join('&');
|
|
447
|
-
const searchUrl = `https://booth.pm/zh-cn/search/${encodeURIComponent(query)}?${tagsParams}&min_price=
|
|
448
|
-
|
|
447
|
+
const searchUrl = `https://booth.pm/zh-cn/search/${encodeURIComponent(query)}?${tagsParams}&min_price=4500`;
|
|
448
|
+
|
|
449
449
|
const page = await ctx.puppeteer.page();
|
|
450
450
|
|
|
451
|
+
await page.setRequestInterception(true);
|
|
452
|
+
page.on('request', (request) => {
|
|
453
|
+
const resourceType = request.resourceType();
|
|
454
|
+
if (['image', 'stylesheet', 'font'].includes(resourceType)) {
|
|
455
|
+
request.abort();
|
|
456
|
+
} else {
|
|
457
|
+
request.continue();
|
|
458
|
+
}
|
|
459
|
+
});
|
|
460
|
+
|
|
451
461
|
try {
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
462
|
+
let retries = 3;
|
|
463
|
+
while (retries > 0) {
|
|
464
|
+
try {
|
|
465
|
+
await page.goto(searchUrl, { waitUntil: 'networkidle0', timeout: ctx.config.loadTimeout || import_koishi.Time.second * 10 });
|
|
466
|
+
break;
|
|
467
|
+
} catch (error) {
|
|
468
|
+
retries--;
|
|
469
|
+
if (retries === 0) throw error;
|
|
470
|
+
logger.warn(`页面加载失败,重试中... (剩余重试次数: ${retries})`);
|
|
471
|
+
await new Promise(resolve => setTimeout(resolve, 2000));
|
|
472
|
+
}
|
|
473
|
+
}
|
|
461
474
|
|
|
462
|
-
const
|
|
463
|
-
|
|
464
|
-
|
|
475
|
+
const content = await page.content();
|
|
476
|
+
const regex = /item-card__wrap"[\s\S]*?id="item_(\d+)"/;
|
|
477
|
+
const match = content.match(regex);
|
|
478
|
+
|
|
479
|
+
if (!match) {
|
|
480
|
+
if (content.includes('検索結果はありません') ||
|
|
481
|
+
content.includes('没有找到') ||
|
|
482
|
+
content.includes('検索条件に合致する作品は見つかりませんでした') ||
|
|
483
|
+
content.includes('該当する作品はありません')) {
|
|
484
|
+
return "没有找到相关商品";
|
|
485
|
+
}
|
|
486
|
+
return "没有找到相关商品";
|
|
487
|
+
}
|
|
488
|
+
|
|
489
|
+
const itemId = match[1];
|
|
490
|
+
|
|
491
|
+
try {
|
|
492
|
+
const buffer = await captureCard(ctx, itemId);
|
|
493
|
+
if (!buffer) {
|
|
494
|
+
return "卡片生成失败";
|
|
495
|
+
}
|
|
496
|
+
return import_koishi.h.image(buffer, "image/png");
|
|
497
|
+
} catch (error) {
|
|
498
|
+
logger.error('卡片生成失败:', error);
|
|
499
|
+
return "卡片生成失败";
|
|
500
|
+
}
|
|
465
501
|
} catch (error) {
|
|
466
|
-
logger.error(
|
|
467
|
-
|
|
502
|
+
logger.error('搜索失败:', error);
|
|
503
|
+
if (error.message.includes('ERR_EMPTY_RESPONSE') || error.message.includes('net::ERR_CONNECTION_TIMED_OUT')) {
|
|
504
|
+
return "搜索失败,连接BOOTH网站超时,请稍后再试";
|
|
505
|
+
}
|
|
506
|
+
return "搜索失败";
|
|
468
507
|
} finally {
|
|
469
508
|
await page.close();
|
|
470
509
|
}
|
|
471
510
|
});
|
|
472
|
-
|
|
511
|
+
|
|
473
512
|
function getSimilarity(a, b) {
|
|
474
513
|
if (a === b) return 1;
|
|
475
514
|
if (a.length < 2 || b.length < 2) return 0;
|
|
476
|
-
|
|
515
|
+
|
|
477
516
|
const bigramsA = new Set();
|
|
478
517
|
for (let i = 0; i < a.length - 1; i++) {
|
|
479
518
|
bigramsA.add(a.substring(i, i + 2));
|
|
480
519
|
}
|
|
481
|
-
|
|
520
|
+
|
|
482
521
|
let matches = 0;
|
|
483
522
|
for (let i = 0; i < b.length - 1; i++) {
|
|
484
523
|
if (bigramsA.has(b.substring(i, i + 2))) matches++;
|
|
485
524
|
}
|
|
486
|
-
|
|
525
|
+
|
|
487
526
|
return (2 * matches) / (a.length + b.length - 2);
|
|
488
527
|
}
|
|
489
528
|
|
|
490
529
|
ctx.middleware(async (session, next) => {
|
|
491
530
|
const boothUrlRegex = /https:\/\/booth.pm\/[\w-]+\/items\/(\d+)/;
|
|
492
531
|
const match = session.content.match(boothUrlRegex);
|
|
493
|
-
|
|
532
|
+
|
|
494
533
|
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
|
+
const itemId = match[1];
|
|
495
542
|
try {
|
|
496
|
-
const buffer = await captureCard(ctx,
|
|
497
|
-
|
|
543
|
+
const buffer = await captureCard(ctx, itemId);
|
|
544
|
+
if (buffer) {
|
|
545
|
+
await session.send(import_koishi.h.image(buffer, "image/png"));
|
|
546
|
+
return;
|
|
547
|
+
} else {
|
|
548
|
+
return "商品解析失败";
|
|
549
|
+
}
|
|
498
550
|
} catch (error) {
|
|
499
|
-
logger.warn(error);
|
|
551
|
+
logger.warn("链接解析失败:", error);
|
|
552
|
+
return "商品解析失败";
|
|
500
553
|
}
|
|
501
554
|
}
|
|
502
555
|
return next();
|