koishi-plugin-booth-get 6.0.1 → 6.0.3

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.
@@ -315,228 +315,38 @@ class CardGenerator {
315
315
  </html>`;
316
316
  }
317
317
 
318
- generateDiscountCardHTML(item) {
319
- const savedAmount = item.original_price - item.price;
320
-
321
- return `
322
- <html>
323
- <head>
324
- <meta charset="utf-8">
325
- <style>
326
- @import url('https://fonts.googleapis.com/css2?family=Noto+Sans+SC:wght@300;400;500;700&family=Montserrat:wght@600;700;800&display=swap');
327
- body {
328
- margin: 0;
329
- padding: 0;
330
- font-family: 'Noto Sans SC', sans-serif;
331
- background: linear-gradient(135deg, #ff6b6b 0%, #ffa502 100%);
332
- display: flex;
333
- justify-content: center;
334
- align-items: center;
335
- min-height: 100vh;
336
- }
337
- .container {
338
- width: 500px;
339
- background: white;
340
- border-radius: 20px;
341
- overflow: hidden;
342
- box-shadow: 0 25px 50px -12px rgba(0, 0, 0, 0.25);
343
- }
344
- .header {
345
- background: linear-gradient(90deg, #ff6b6b, #ffa502);
346
- padding: 20px;
347
- text-align: center;
348
- color: white;
349
- position: relative;
350
- }
351
- .discount-badge {
352
- position: absolute;
353
- top: 15px;
354
- right: 15px;
355
- background: #e74c3c;
356
- color: white;
357
- padding: 8px 12px;
358
- border-radius: 20px;
359
- font-weight: 700;
360
- font-size: 14px;
361
- box-shadow: 0 4px 8px rgba(0,0,0,0.2);
362
- }
363
- .new-badge {
364
- position: absolute;
365
- top: 15px;
366
- left: 15px;
367
- background: #27ae60;
368
- color: white;
369
- padding: 8px 12px;
370
- border-radius: 20px;
371
- font-weight: 700;
372
- font-size: 14px;
373
- box-shadow: 0 4px 8px rgba(0,0,0,0.2);
374
- }
375
- .booth-logo {
376
- font-family: 'Montserrat', sans-serif;
377
- font-weight: 800;
378
- font-size: 28px;
379
- letter-spacing: 2px;
380
- }
381
- .content {
382
- padding: 25px;
383
- }
384
- .main-image {
385
- width: 100%;
386
- height: 250px;
387
- background: #f0f0f0 url('${item.image_url}') center/cover;
388
- border-radius: 12px;
389
- margin-bottom: 20px;
390
- box-shadow: 0 8px 16px rgba(0,0,0,0.1);
391
- }
392
- .product-title {
393
- font-size: 20px;
394
- margin: 0 0 15px 0;
395
- color: #2c3e50;
396
- font-weight: 700;
397
- line-height: 1.4;
398
- }
399
- .author-section {
400
- display: flex;
401
- align-items: center;
402
- gap: 12px;
403
- margin-bottom: 20px;
404
- padding: 12px;
405
- background: #f8f9fa;
406
- border-radius: 10px;
407
- }
408
- .author-avatar {
409
- width: 50px;
410
- height: 50px;
411
- border-radius: 50%;
412
- border: 2px solid #fff;
413
- box-shadow: 0 4px 8px rgba(0,0,0,0.1);
414
- object-fit: cover;
415
- }
416
- .author-info {
417
- flex: 1;
418
- }
419
- .author-name {
420
- font-size: 16px;
421
- font-weight: 600;
422
- color: #2c3e50;
423
- }
424
- .price-section {
425
- display: flex;
426
- align-items: center;
427
- justify-content: space-between;
428
- margin-bottom: 15px;
429
- padding: 15px;
430
- background: #fff9f9;
431
- border-radius: 10px;
432
- border: 2px dashed #e74c3c;
433
- }
434
- .original-price {
435
- font-size: 18px;
436
- color: #7f8c8d;
437
- text-decoration: line-through;
438
- }
439
- .current-price {
440
- font-size: 24px;
441
- font-weight: 700;
442
- color: #e74c3c;
443
- }
444
- .savings {
445
- text-align: center;
446
- font-size: 16px;
447
- color: #27ae60;
448
- font-weight: 600;
449
- margin-bottom: 15px;
450
- }
451
- .tags {
452
- display: flex;
453
- flex-wrap: wrap;
454
- gap: 6px;
455
- margin-bottom: 20px;
456
- }
457
- .tag {
458
- background: #e1f0fa;
459
- color: #3498db;
460
- padding: 4px 10px;
461
- border-radius: 15px;
462
- font-size: 12px;
463
- font-weight: 500;
464
- }
465
- .footer {
466
- background: #2c3e50;
467
- padding: 15px;
468
- text-align: center;
469
- color: #ecf0f1;
470
- font-size: 12px;
471
- }
472
- .link {
473
- color: #3498db;
474
- text-decoration: none;
475
- font-weight: 500;
476
- }
477
- </style>
478
- </head>
479
- <body>
480
- <div class="container">
481
- <div class="header">
482
- <div class="new-badge">NEW</div>
483
- <div class="discount-badge">-${item.discount_rate}%</div>
484
- <div class="booth-logo">BOOTH</div>
485
- <div style="margin-top: 8px; font-size: 14px;">最新折扣商品</div>
486
- </div>
487
-
488
- <div class="content">
489
- <div class="main-image"></div>
490
- <h1 class="product-title">${item.title}</h1>
491
-
492
- <div class="author-section">
493
- <img src="${item.author_thumbnail_url || 'https://s2.booth.pm/static-images/user/guest-32.png'}"
494
- class="author-avatar"
495
- alt="作者头像" onerror="this.src='https://s2.booth.pm/static-images/user/guest-32.png'">
496
- <div class="author-info">
497
- <div class="author-name">${item.author}</div>
498
- </div>
499
- </div>
318
+ generateDiscountText(item) {
319
+ const savedAmount = item.original_price - item.price;
320
+ const discountRate = Math.round((1 - item.price/item.original_price)*100);
321
+
322
+ return `🔥 BOOTH 折扣商品推送 🔥
500
323
 
501
- <div class="price-section">
502
- <div class="original-price">¥${item.original_price.toLocaleString()}</div>
503
- <div class="current-price">¥${item.price.toLocaleString()}</div>
504
- </div>
505
-
506
- <div class="savings">
507
- 节省 ¥${savedAmount.toLocaleString()} (${item.discount_rate}% 折扣)
508
- </div>
509
-
510
- ${item.tags && item.tags.length > 0 ? `
511
- <div class="tags">
512
- ${item.tags.slice(0, 5).map(tag => `<div class="tag">${tag.name}</div>`).join('')}
513
- </div>
514
- ` : ''}
515
- </div>
324
+ 📌 商品名称: ${item.title}
325
+ 👤 作者: ${item.author}
326
+ 💰 价格: ¥${item.price.toLocaleString()} (原价: ¥${item.original_price.toLocaleString()})
327
+ 💥 折扣: -${discountRate}% (节省 ¥${savedAmount.toLocaleString()})
328
+ ❤️ 收藏数: ${item.likes || 0}
329
+ 🏷️ 分类: ${item.category || '未分类'}
330
+ #${item.id}
516
331
 
517
- <div class="footer">
518
- 由VRCBBS提供 | BOOTH链接:
519
- <a href="https://booth.pm/zh-cn/items/${item.id}"
520
- class="link">
521
- https://booth.pm/zh-cn/items/${item.id}
522
- </a>
523
- </div>
524
- </div>
525
- </body>
526
- </html>`;
527
- }
332
+ 📝 商品简介:
333
+ ${(item.description || "").slice(0, 200)}${(item.description||"").length > 200 ? '...' : ''}
334
+
335
+ 🔗 商品链接: https://booth.pm/zh-cn/items/${item.id}`;
336
+ }
528
337
 
529
338
  async captureCardHTML(html, config) {
530
339
  const page = await this.ctx.puppeteer.page();
531
340
  try {
532
-
341
+ page.setDefaultTimeout(config.loadTimeout || 30000);
342
+
533
343
  await page.setContent(html, {
534
- waitUntil: 'networkidle0',
344
+ waitUntil: 'networkidle0',
535
345
  timeout: config.loadTimeout || 30000
536
346
  });
537
347
 
538
348
  await new Promise(resolve => setTimeout(resolve, 2000));
539
-
349
+
540
350
  await page.setViewport({ width: 640, height: 1200 });
541
351
  const container = await page.$('.container') || await page.$('body');
542
352
  return await container.screenshot({
@@ -376,67 +376,49 @@ class DiscountTracker {
376
376
  this.lastDiscountItems = discountItems.slice();
377
377
  }
378
378
 
379
- async sendItemsToGroups(items) {
380
- const logger = this.ctx.logger('booth-discount');
381
- const cardGenerator = require('./card-generator');
382
-
383
- for (const item of items) {
384
- try {
385
- const html = cardGenerator.generateDiscountCardHTML(item);
386
- const buffer = await cardGenerator.captureCardHTML(html, this.config);
387
-
388
- if (!buffer) {
389
- logger.warn(`生成卡片失败: ${item.title}`);
390
- continue;
391
- }
392
-
393
- const savedAmount = (item.original_price || 0) - (item.price || 0);
394
- let message = `🎉 发现折扣商品!\n\n${item.title}\n作者:${item.author || ''}\n`;
395
-
396
- if (item.has_discount_keyword) {
397
- message += `🔍 折扣关键词: ${item.discount_keyword}\n`;
398
- }
399
-
400
- message += `💰 价格:¥${(item.price||0).toLocaleString()}(原价:¥${(item.original_price||0).toLocaleString()})\n`;
401
- message += `🎊 折扣:${item.discount_rate}% OFF\n`;
402
- message += `💵 节省:¥${savedAmount.toLocaleString()}\n`;
403
- message += `🔗 链接:${item.url}`;
404
-
405
- for (const channelId of this.config.targetGroups) {
406
- try {
407
- if (channelId.includes(':')) {
408
- const [platform, id] = channelId.split(':', 2);
409
- for (const bot of this.ctx.bots) {
410
- if (bot.platform === platform) {
411
- await bot.sendMessage(id, [message, h.image(buffer, 'image/png')]);
412
- break;
379
+ async sendItemsToGroups(items) {
380
+ const logger = this.ctx.logger('booth-discount');
381
+ const cardGenerator = require('./card-generator');
382
+
383
+ for (const item of items) {
384
+ try {
385
+ const message = cardGenerator.generateDiscountText(item);
386
+
387
+ for (const channelId of this.config.targetGroups) {
388
+ try {
389
+ if (channelId.includes(':')) {
390
+ const [platform, id] = channelId.split(':', 2);
391
+ for (const bot of this.ctx.bots) {
392
+ if (bot.platform === platform) {
393
+ await bot.sendMessage(id, message);
394
+ break;
395
+ }
413
396
  }
414
- }
415
- } else {
416
- for (const bot of this.ctx.bots) {
417
- try {
418
- await bot.sendMessage(channelId, [message, h.image(buffer, 'image/png')]);
419
- break;
420
- } catch (e) {
421
- continue;
397
+ } else {
398
+ for (const bot of this.ctx.bots) {
399
+ try {
400
+ await bot.sendMessage(channelId, message);
401
+ break;
402
+ } catch (e) {
403
+ continue;
404
+ }
422
405
  }
423
406
  }
407
+ await new Promise(r => setTimeout(r, 2000));
408
+ } catch (e) {
409
+ logger.warn(`推送失败 ${channelId}: ${e.message}`);
424
410
  }
425
- await new Promise(r => setTimeout(r, 2000));
426
- } catch (e) {
427
- logger.warn(`推送失败 ${channelId}: ${e.message}`);
428
411
  }
429
- }
430
412
 
431
- this.recentlyPushed.set(item.id, Date.now());
432
- this.discountCache.set(item.id, Date.now());
433
- await new Promise(r => setTimeout(r, 3000));
413
+ this.recentlyPushed.set(item.id, Date.now());
414
+ this.discountCache.set(item.id, Date.now());
415
+ await new Promise(r => setTimeout(r, 3000));
434
416
 
435
- } catch (err) {
436
- logger.error(`推送错误: ${err.message}`);
417
+ } catch (err) {
418
+ logger.error(`推送错误: ${err.message}`);
419
+ }
437
420
  }
438
421
  }
439
- }
440
422
 
441
423
  startDiscountTracking() {
442
424
  const logger = this.ctx.logger('booth-discount');
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "koishi-plugin-booth-get",
3
3
  "description": "通过url与名称检查摊位物品并反馈用户搜索的图片",
4
- "version": "6.0.1",
4
+ "version": "6.0.3",
5
5
  "contributors": [
6
6
  "rixiang <1148147857@qq.com>"
7
7
  ],