koishi-plugin-ll-mc 3.1.10 → 3.1.11

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.
Files changed (2) hide show
  1. package/lib/index.js +10 -53
  2. package/package.json +1 -1
package/lib/index.js CHANGED
@@ -2462,7 +2462,7 @@ ${targetUserRecord[0].username}
2462
2462
  </div>`;
2463
2463
  }
2464
2464
  __name(buildLeaderboardRow, "buildLeaderboardRow");
2465
- function buildLeaderboardHtml(title, date, items, backgroundCss, fontFaces) {
2465
+ function buildLeaderboardHtml(title, date, items, backgroundCss) {
2466
2466
  const maxCount = Math.max(1, ...items.map((item) => item.count || 0));
2467
2467
  const rows = items.map((item, index) => buildLeaderboardRow(item, index, maxCount)).join("\n");
2468
2468
  return `<!DOCTYPE html>
@@ -2471,7 +2471,10 @@ ${targetUserRecord[0].username}
2471
2471
  <meta charset="UTF-8">
2472
2472
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
2473
2473
  <style>
2474
- ${fontFaces || ""}
2474
+ /* 只把"数字"锁定到内置文本字体:系统装了 emoji 字体(如 font-noto-emoji)时,
2475
+ emoji 字体里也带 0-9 字形(给 keycap 用)、字宽很宽,会导致数字被撑成 "2 9 1 7"。
2476
+ 用 unicode-range 只接管 0-9,其余字符照常走系统字体,emoji 也交给系统 emoji 字体。 */
2477
+ @font-face { font-family: 'LLMCDigits'; src: url('fonts/HarmonyOS_Sans_Medium.ttf') format('truetype'); unicode-range: U+0030-0039; }
2475
2478
  * { box-sizing: border-box; margin: 0; padding: 0; }
2476
2479
  html, body {
2477
2480
  width: 900px;
@@ -2480,7 +2483,7 @@ ${targetUserRecord[0].username}
2480
2483
  background-color: #F5F7FA;
2481
2484
  }
2482
2485
  body {
2483
- font-family: "PingFang SC", "Microsoft YaHei", "Noto Sans SC", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif, "NotoEmoji", "Apple Color Emoji", "Segoe UI Emoji", "Noto Color Emoji";
2486
+ font-family: "LLMCDigits", "PingFang SC", "Microsoft YaHei", "Noto Sans SC", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Noto Color Emoji";
2484
2487
  -webkit-font-smoothing: antialiased;
2485
2488
  }
2486
2489
  .card {
@@ -2524,10 +2527,9 @@ ${rows}
2524
2527
  if (typeof ctx.puppeteer?.page !== "function") return null;
2525
2528
  let page;
2526
2529
  try {
2527
- // 复用图表的内置字体(含纯 emoji 的 NotoEmoji),以相对路径 fonts/<file> 加载,
2528
- // 所以必须把模板写到 data/messageCounter/ 目录里再用 file:// 访问,相对路径才能解析。
2529
- const fontFaces = generateFontFacesCSS(["HarmonyOS_Sans_Medium.ttf", "NotoEmoji.ttf"]);
2530
- const html = buildLeaderboardHtml(title, date, items, backgroundCss, fontFaces);
2530
+ // 官机补丁:模板里的数字用内置文本字体通过 @font-face(unicode-range) 锁定,
2531
+ // 所以必须把模板写到 data/messageCounter/ 目录里再用 file:// 访问,相对路径 fonts/ 才能解析。
2532
+ const html = buildLeaderboardHtml(title, date, items, backgroundCss);
2531
2533
  page = await ctx.puppeteer.page();
2532
2534
  await page.setViewport({ width: 900, height: 400, deviceScaleFactor: 2 });
2533
2535
  const pageUrl = templateHtmlPath.includes(":") ? `file:///${templateHtmlPath}` : `file://${templateHtmlPath}`;
@@ -2546,54 +2548,9 @@ ${rows}
2546
2548
  } else {
2547
2549
  await page.setContent(html, { waitUntil: "networkidle0", timeout: 20000 }).catch(() => {});
2548
2550
  }
2549
- // 确保 emoji 字体就绪再截图
2551
+ // 确保字体就绪再截图
2550
2552
  await page.evaluate(() => document.fonts.ready).catch(() => {});
2551
2553
  await page.waitForSelector(".card").catch(() => {});
2552
- // 官机补丁:背景图右侧可能是深色人物,导致排在右下角的发言数字看不清。
2553
- // 这里对每个数字的位置采样一次背景亮度,凡是背景偏暗的数字改成白色(去掉全局描边)。
2554
- try {
2555
- const dpr = 2;
2556
- // 先隐藏所有文字以采样"纯背景"像素
2557
- await page.evaluate(() => {
2558
- document.querySelectorAll(".bar-content").forEach((el) => { el.style.visibility = "hidden"; });
2559
- });
2560
- const bgShot = await page.screenshot({ type: "png", fullPage: true });
2561
- await page.evaluate(() => {
2562
- document.querySelectorAll(".bar-content").forEach((el) => { el.style.visibility = ""; });
2563
- });
2564
- const bgDataUrl = `data:image/png;base64,${bgShot.toString("base64")}`;
2565
- const luminances = await page.evaluate(async (dataUrl) => {
2566
- const img = new Image();
2567
- img.src = dataUrl;
2568
- await img.decode();
2569
- const canvas = document.createElement("canvas");
2570
- canvas.width = img.naturalWidth;
2571
- canvas.height = img.naturalHeight;
2572
- const ctx = canvas.getContext("2d");
2573
- ctx.drawImage(img, 0, 0);
2574
- const scale = window.devicePixelRatio || 1;
2575
- const out = [];
2576
- document.querySelectorAll(".row-count").forEach((el) => {
2577
- const r = el.getBoundingClientRect();
2578
- const x = Math.max(0, Math.min(Math.round((r.left + r.width / 2) * scale), canvas.width - 1));
2579
- const y = Math.max(0, Math.min(Math.round((r.top + r.height / 2) * scale), canvas.height - 1));
2580
- const d = ctx.getImageData(x, y, 1, 1).data;
2581
- out.push(0.2126 * d[0] + 0.7152 * d[1] + 0.0722 * d[2]);
2582
- });
2583
- return out;
2584
- }, bgDataUrl);
2585
- await page.evaluate((lums) => {
2586
- const nodes = document.querySelectorAll(".row-count");
2587
- nodes.forEach((el, i) => {
2588
- const lum = lums[i];
2589
- if (lum !== undefined && lum < 120) {
2590
- el.style.color = "#FFFFFF";
2591
- }
2592
- });
2593
- }, luminances);
2594
- } catch (sampleError) {
2595
- logger.warn("背景亮度采样失败,使用默认数字颜色:", sampleError?.message);
2596
- }
2597
2554
  // 背景(自定义 CSS/API 背景)是加在 html 上的,必须截整页才能把卡片外的背景一起截进来;
2598
2555
  // body 高度由内容撑开(无 min-height),所以 fullPage 不会产生多余空白。
2599
2556
  const buf = await page.screenshot({ type: "png", fullPage: true });
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "koishi-plugin-ll-mc",
3
3
  "description": "消息数量统计插件(基于 koishi-plugin-message-counter 重做,官方QQ机器人兼容)",
4
- "version": "3.1.10",
4
+ "version": "3.1.11",
5
5
  "main": "lib/index.js",
6
6
  "typings": "lib/index.d.ts",
7
7
  "files": [