@sjtdev/koishi-plugin-dota2tracker 1.1.5 → 1.1.6-hotfix

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 CHANGED
@@ -525,11 +525,21 @@ function getFormattedMatchData(match) {
525
525
  ["radiant", "dire"].forEach((team) => {
526
526
  match[team] = { killsCount: match[team + "Kills"]?.reduce((acc, cva) => acc + cva, 0) ?? 0, damageReceived: 0, heroDamage: 0, networth: 0, experience: 0 };
527
527
  });
528
+ if (!match.parsedDateTime) {
529
+ match.players.reduce((acc, player) => {
530
+ if (player.isRadiant) {
531
+ acc.radiant.killsCount += player.kills;
532
+ } else {
533
+ acc.dire.killsCount += player.kills;
534
+ }
535
+ return acc;
536
+ }, match);
537
+ }
528
538
  match.party = {};
529
539
  let party_index = 0;
530
540
  const party_mark = ["I", "II", "III", "IV"];
531
541
  let heroOrderList = {};
532
- for (let hero of match.pickBans) {
542
+ for (let hero of match.pickBans ?? []) {
533
543
  if (hero.isPick)
534
544
  heroOrderList[hero.heroId] = hero.order;
535
545
  }
@@ -561,27 +571,29 @@ function getFormattedMatchData(match) {
561
571
  };
562
572
  player.killContribution = (player.kills + player.assists) / match[player.team].killsCount;
563
573
  player.deathContribution = player.deaths / match[player.team === "radiant" ? "dire" : player.team].killsCount;
564
- player.damageReceived = player.stats?.heroDamageReport?.receivedTotal.physicalDamage + player.stats?.heroDamageReport?.receivedTotal.magicalDamage + player.stats?.heroDamageReport?.receivedTotal.pureDamage;
574
+ player.damageReceived = (player.stats?.heroDamageReport?.receivedTotal?.physicalDamage ?? 0) + (player.stats?.heroDamageReport?.receivedTotal?.magicalDamage ?? 0) + (player.stats?.heroDamageReport?.receivedTotal?.pureDamage ?? 0);
565
575
  match[player.team].heroDamage = (match[player.team].heroDamage ?? 0) + player.heroDamage;
566
576
  match[player.team].damageReceived = (match[player.team].damageReceived ?? 0) + player.damageReceived;
567
577
  match[player.team].networth += player.networth;
568
578
  match[player.team].experience += Math.floor(player.experiencePerMinute / 60 * match.durationSeconds);
569
579
  player.titles = [];
570
580
  player.mvpScore = // 计算MVP分数
571
- player.kills * 5 + player.assists * 3 + player.stats.heroDamageReport.dealtTotal.stunDuration / 100 * 0.1 + player.stats.heroDamageReport.dealtTotal.disableDuration / 100 * 0.05 + player.stats.heroDamageReport.dealtTotal.slowDuration / 100 * 0.025 + player.heroDamage * 1e-3 + player.towerDamage * 0.01 + player.heroHealing * 2e-3 + player.imp * 0.25;
581
+ player.kills * 5 + player.assists * 3 + (player.stats.heroDamageReport?.dealtTotal.stunDuration ?? 0) / 100 * 0.1 + (player.stats.heroDamageReport?.dealtTotal.disableDuration ?? 0) / 100 * 0.05 + (player.stats.heroDamageReport?.dealtTotal.slowDuration ?? 0) / 100 * 0.025 + player.heroDamage * 1e-3 + player.towerDamage * 0.01 + player.heroHealing * 2e-3 + player.imp * 0.25;
572
582
  player.order = heroOrderList[player.hero.id];
573
583
  if (player.partyId != null) {
574
584
  if (!match.party[player.partyId])
575
585
  match.party[player.partyId] = party_mark[party_index++];
576
586
  }
577
- const maxStackCountsByAbilityOrItem = player.stats.matchPlayerBuffEvent.reduce((acc, event) => {
578
- const key = event.abilityId !== null ? `ability-${event.abilityId}` : `item-${event.itemId}`;
579
- if (!acc[key] || event.stackCount > acc[key].stackCount) {
580
- acc[key] = event;
581
- }
582
- return acc;
583
- }, {});
584
- player.stats.matchPlayerBuffEvent.splice(0, player.stats.matchPlayerBuffEvent.length, ...Object.values(maxStackCountsByAbilityOrItem));
587
+ if (match.parsedDateTime) {
588
+ const maxStackCountsByAbilityOrItem = player.stats.matchPlayerBuffEvent.reduce((acc, event) => {
589
+ const key = event.abilityId !== null ? `ability-${event.abilityId}` : `item-${event.itemId}`;
590
+ if (!acc[key] || event.stackCount > acc[key].stackCount) {
591
+ acc[key] = event;
592
+ }
593
+ return acc;
594
+ }, {});
595
+ player.stats.matchPlayerBuffEvent.splice(0, player.stats.matchPlayerBuffEvent.length, ...Object.values(maxStackCountsByAbilityOrItem));
596
+ }
585
597
  switch (player.lane) {
586
598
  case "SAFE_LANE":
587
599
  player.laneResult = laneResult[player.isRadiant ? "bottom" : "top"][player.team];
@@ -726,18 +738,20 @@ function getFormattedMatchData(match) {
726
738
  ).titles.push({ name: "魂", color: "#6cf" });
727
739
  findMaxByProperty("networth").titles.push({ name: "富", color: "#FFD700" });
728
740
  findMaxByProperty("experiencePerMinute").titles.push({ name: "睿", color: "#8888FF" });
729
- match.players.reduce(
730
- (max, player) => player.stats.heroDamageReport.dealtTotal.stunDuration + player.stats.heroDamageReport.dealtTotal.disableDuration / 2 + player.stats.heroDamageReport.dealtTotal.slowDuration / 4 > max.stats.heroDamageReport.dealtTotal.stunDuration + max.stats.heroDamageReport.dealtTotal.disableDuration / 2 + max.stats.heroDamageReport.dealtTotal.slowDuration / 4 ? player : max
731
- ).titles.push({ name: "控", color: "#FF00FF" });
741
+ if (match.parsedDateTime) {
742
+ match.players.reduce(
743
+ (max, player) => player.stats.heroDamageReport.dealtTotal.stunDuration + player.stats.heroDamageReport.dealtTotal.disableDuration / 2 + player.stats.heroDamageReport.dealtTotal.slowDuration / 4 > max.stats.heroDamageReport.dealtTotal.stunDuration + max.stats.heroDamageReport.dealtTotal.disableDuration / 2 + max.stats.heroDamageReport.dealtTotal.slowDuration / 4 ? player : max
744
+ ).titles.push({ name: "控", color: "#FF00FF" });
745
+ match.players.reduce(
746
+ (max, player) => player.stats.heroDamageReport.receivedTotal.physicalDamage + player.stats.heroDamageReport.receivedTotal.magicalDamage + player.stats.heroDamageReport.receivedTotal.pureDamage > max.stats.heroDamageReport.receivedTotal.physicalDamage + max.stats.heroDamageReport.receivedTotal.magicalDamage + max.stats.heroDamageReport.receivedTotal.pureDamage ? player : max
747
+ ).titles.push({ name: "耐", color: "#84A1C7" });
748
+ }
732
749
  findMaxByProperty("heroDamage").titles.push({ name: "爆", color: "#CC0088" });
733
750
  findMaxByProperty("kills", "heroDamage").titles.push({ name: "破", color: "#DD0000" });
734
751
  findMaxByProperty("deaths", "networth", void 0, void 0, "min" /* Min */).titles.push({ name: "鬼", color: "#CCCCCC" });
735
752
  findMaxByProperty("assists", "heroDamage").titles.push({ name: "助", color: "#006400" });
736
753
  findMaxByProperty("towerDamage", "heroDamage").titles.push({ name: "拆", color: "#FEDCBA" });
737
754
  findMaxByProperty("heroHealing").titles.push({ name: "奶", color: "#00FF00" });
738
- match.players.reduce(
739
- (max, player) => player.stats.heroDamageReport.receivedTotal.physicalDamage + player.stats.heroDamageReport.receivedTotal.magicalDamage + player.stats.heroDamageReport.receivedTotal.pureDamage > max.stats.heroDamageReport.receivedTotal.physicalDamage + max.stats.heroDamageReport.receivedTotal.magicalDamage + max.stats.heroDamageReport.receivedTotal.pureDamage ? player : max
740
- ).titles.push({ name: "耐", color: "#84A1C7" });
741
755
  match.players.reduce((lowest, player) => {
742
756
  const currentContribution = (player.kills + player.assists) / match[player.team].KillsCount;
743
757
  const lowestContribution = (lowest.kills + lowest.assists) / match[lowest.team].KillsCount;
@@ -1249,9 +1263,10 @@ async function apply(ctx, config) {
1249
1263
  match = getFormattedMatchData(queryRes.data.data.match);
1250
1264
  }
1251
1265
  }
1252
- if (match && match.parsedDateTime) {
1266
+ if (match && (match.parsedDateTime || import_moment.default.unix(match.endDateTime).isBefore((0, import_moment.default)().subtract(1, "hours")))) {
1253
1267
  session.send(await ctx.puppeteer.render(genImageHTML(match, config.template_match, "match" /* Match */)));
1254
- ctx.database.upsert("dt_previous_query_results", (row) => [{ matchId: match.id, data: match, queryTime: /* @__PURE__ */ new Date() }]);
1268
+ if (match.parsedDateTime)
1269
+ ctx.database.upsert("dt_previous_query_results", (row) => [{ matchId: match.id, data: match, queryTime: /* @__PURE__ */ new Date() }]);
1255
1270
  } else {
1256
1271
  pendingMatches.push({ matchId, guilds: [{ platform: session.event.platform, guildId: session.event.guild.id, players: [] }] });
1257
1272
  session.send("比赛尚未解析,将在解析完成后发布。");
@@ -1477,7 +1492,7 @@ async function apply(ctx, config) {
1477
1492
  });
1478
1493
  });
1479
1494
  let heroes3 = Array.from(mergedMap.values());
1480
- return heroes3.find((hero) => hero.names_cn.includes(input) || hero.shortName === input.toLowerCase() || hero.id == input);
1495
+ return heroes3.find((hero) => hero.names_cn.some((cn) => cn.toLowerCase() == input.toLowerCase()) || hero.shortName === input.toLowerCase() || hero.id == input);
1481
1496
  }
1482
1497
  __name(findingHero, "findingHero");
1483
1498
  ctx.command("7.36 <input_data>", "查询7.36改动").option("refresh", "-r 重新获取数据").usage("可查询英雄改动并生成图片返回").example("7.36 小松许").action(async ({ session, options }, input_data) => {
@@ -1574,9 +1589,6 @@ async function apply(ctx, config) {
1574
1589
  } else
1575
1590
  session.send("https://www.dota2.com/patches/7.36");
1576
1591
  });
1577
- ctx.command("test <input_data>").option("a", "a").action(async ({ session, options }, input_data) => {
1578
- console.log((await ctx.database.get("dt_7_36", [0]))[0].data);
1579
- });
1580
1592
  ctx.on("ready", async () => {
1581
1593
  const tables = await ctx.database.tables;
1582
1594
  if (!("dt_subscribed_guilds" in tables)) {
@@ -1713,10 +1725,10 @@ async function apply(ctx, config) {
1713
1725
  } else {
1714
1726
  let queryRes = await query(MATCH_INFO(pendingMatch.matchId));
1715
1727
  if (queryRes.status == 200) {
1716
- match = queryRes.data.data.match.parsedDateTime ? getFormattedMatchData(queryRes.data.data.match) : queryRes.data.data.match;
1728
+ match = getFormattedMatchData(queryRes.data.data.match);
1717
1729
  }
1718
1730
  }
1719
- if (match.parsedDateTime || import_moment.default.unix(match.startDateTime).isBefore((0, import_moment.default)().subtract(1, "years"))) {
1731
+ if (match.parsedDateTime || import_moment.default.unix(match.endDateTime).isBefore((0, import_moment.default)().subtract(1, "hours"))) {
1720
1732
  pendingMatches = pendingMatches.filter((item) => item.matchId != match.id);
1721
1733
  const img = await ctx.puppeteer.render(genImageHTML(match, config.template_match, "match" /* Match */));
1722
1734
  for (let commingGuild of pendingMatch.guilds) {
@@ -1743,7 +1755,8 @@ KDA:${((player.kills + player.assists) / (player.deaths || 1)).toFixed(2)} [${
1743
1755
  await ctx.broadcast([`${commingGuild.platform}:${commingGuild.guildId}`], broadMatchMessage + img);
1744
1756
  ctx.logger.info(`已解析${match.id}并发布于${commingGuild.platform}:${commingGuild.guildId}。`);
1745
1757
  }
1746
- ctx.database.upsert("dt_previous_query_results", (row) => [{ matchId: match.id, data: match, queryTime: /* @__PURE__ */ new Date() }]);
1758
+ if (match.parsedDateTime)
1759
+ ctx.database.upsert("dt_previous_query_results", (row) => [{ matchId: match.id, data: match, queryTime: /* @__PURE__ */ new Date() }]);
1747
1760
  ctx.database.create("dt_sended_match_id", { matchId: match.id, sendTime: /* @__PURE__ */ new Date() });
1748
1761
  } else
1749
1762
  ctx.logger.info("比赛 %d 尚未解析完成,继续等待。", match.id);
@@ -1769,7 +1782,7 @@ function genImageHTML(data, template, type) {
1769
1782
  moment: import_moment.default
1770
1783
  };
1771
1784
  let result = "";
1772
- ejs.renderFile(templatePath, templateData, (err, html) => {
1785
+ ejs.renderFile(templatePath, templateData, { strict: false }, (err, html) => {
1773
1786
  if (err)
1774
1787
  throw err;
1775
1788
  else
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@sjtdev/koishi-plugin-dota2tracker",
3
3
  "description": "",
4
- "version": "1.1.5",
4
+ "version": "1.1.6-hotfix",
5
5
  "main": "lib/index.js",
6
6
  "typings": "lib/index.d.ts",
7
7
  "files": [
package/readme.md CHANGED
@@ -17,27 +17,35 @@ DOTA2Bot插件-提供自动追踪群友的最新对局的功能(需群友绑
17
17
  指令 <必填参数> [可选参数]
18
18
  ##### 订阅
19
19
  (bot仅向已订阅群组推送信息)
20
- * <input type="checkbox" checked>`订阅本群`
21
- * <input type="checkbox" checked>`取消订阅`
20
+ * `订阅本群`
21
+ * `取消订阅`
22
22
  ##### 绑定
23
23
  (bot会追踪每位绑定玩家的最新对局)
24
- * <input type="checkbox" checked>`绑定 <玩家SteamID> [玩家别名]`
25
- * <input type="checkbox" checked>`取消绑定`
26
- * <input type="checkbox" checked>`改名 <新玩家别名>`
24
+ * `绑定 <玩家SteamID> [玩家别名]`
25
+ * `取消绑定`
26
+ * `改名 <新玩家别名>`
27
27
  ##### 查询
28
- * <input type="checkbox" checked>`查询玩家 [SteamID|别名] [<--hero|-o> <英雄ID|英雄名|英雄常用别名>]`
28
+ * `查询玩家 [SteamID|别名] [<--hero|-o> <英雄ID|英雄名|英雄常用别名>]`
29
29
  返回一张图片,包含玩家各类信息。(缺省参数时并且调用者已绑定将自查)(输入--hero或-o并跟上查询英雄的参数时,将查询玩家指定英雄)
30
- * <input type="checkbox" checked>`查询比赛 <比赛ID>`
30
+ * `查询比赛 <比赛ID>`
31
31
  返回一张图片,包含比赛对战信息。
32
- * <input type="checkbox" checked>`查询最近比赛 [SteamID|别名]`
32
+ * `查询最近比赛 [SteamID|别名]`
33
33
  查询指定玩家的最近一场比赛,效果同上。(缺省参数时并且调用者已绑定将自查)
34
- * <input type="checkbox" checked>`查询英雄 <英雄ID|英雄名|英雄常用别名>`
34
+ * `查询英雄 <英雄ID|英雄名|英雄常用别名>`
35
35
  返回一张图片,包含英雄属性与技能详情。(此处英雄名为中文名)
36
- * <input type="checkbox" checked><del>`查询英雄对战 <英雄ID|英雄名|英雄常用别名>`</del>
36
+ * <del>`查询英雄对战 <英雄ID|英雄名|英雄常用别名>`</del>
37
37
  好像不是很实用
38
+ * `7.36 [英雄ID|英雄名|英雄常用别名] [--refresh|-r]`
39
+ 查询官网7.36更新日志中指定英雄的改动信息
40
+ 无英雄参数时直接返回官网7.36更新日志网址
41
+ 首次使用时将缓存更新日志网页,若读取失败或出错,可添加`--refresh`或`-r`指令重新缓存
42
+
43
+ ### 英雄ID|英雄名|英雄常用别名 列表
44
+ [dotaconstants_add.json](https://github.com/sjtdev/koishi-plugin-dota2tracker/blob/master/src/dotaconstants_add.json#L102-L226)
45
+ 补充或纠错请提issue
38
46
 
39
47
  ### 图片模板列表
40
- 展示见[wiki](./wiki)
48
+ 展示见[wiki](https://github.com/sjtdev/koishi-plugin-dota2tracker/wiki)
41
49
  生成图片已使用ejs模板实现,所有模板都在[template]文件夹下,若是有大佬想自己设计模板欢迎联系我完善数据接口。(当前有很多在模板中后处理的数据,不是很友好)
42
50
 
43
51
  ### 其他问题
@@ -718,7 +718,7 @@
718
718
  <img alt="" src="${utils.getImageUrl(player.hero.shortName, ImageType.Heroes)}" />
719
719
  <p class="party_line${player.partyId != null ? " party_" + match.party[player.partyId] : ""}"></p>
720
720
  <p class="party_mark${player.partyId != null ? " party_" + match.party[player.partyId] : ""}"></p>
721
- <p class="position p${Math.floor(player.order / 4) + 1}">${player.isRandom ? "随机" : `第<span>${player.order == null ? "-" : player.order + 1}</span>手`}<br/>${d2a.position[player.position?.slice(-1)]}</p>
721
+ <p class="position p${Math.floor(player.order / 4) + 1}">${player.isRandom ? "随机" : `第<span>${player.order == null ? "-" : player.order + 1}</span>手`}<br/>${d2a.position[player.position?.slice(-1)]??""}</p>
722
722
  <p class="level">${player.level}</p>
723
723
  </div>
724
724
  <div class="player_info">
@@ -804,7 +804,7 @@
804
804
  <p>${buff.stackCount ?? ""}</p>
805
805
  </div>`
806
806
  )
807
- .join("")}
807
+ .join("")??""}
808
808
  </section>
809
809
  <section>
810
810
  <div class="support_item"${player.supportItemsCount[30] > 0 ? "" : ' style="display:none"'}>
@@ -946,19 +946,19 @@
946
946
  <section>英雄伤害:<span class="hero_damage">${player.heroDamage}</span></section>
947
947
  <section>建筑伤害:<span class="building_damage">${player.towerDamage}</span></section>
948
948
  <section>受到伤害(减免后):<span class="tak">${
949
- player.stats?.heroDamageReport?.receivedTotal.physicalDamage + player.stats?.heroDamageReport?.receivedTotal.magicalDamage + player.stats?.heroDamageReport?.receivedTotal.pureDamage
949
+ (player.stats?.heroDamageReport?.receivedTotal.physicalDamage??0) + (player.stats?.heroDamageReport?.receivedTotal.magicalDamage??0) + (player.stats?.heroDamageReport?.receivedTotal.pureDamage??0)
950
950
  }</span></section>
951
951
  <section>补刀:<span class="lh">${player.numLastHits}</span>/<span class="dn">${player.numDenies}</span></section>
952
952
  <section>GPM/XPM:<span class="gpm">${player.goldPerMinute}</span>/<span class="xpm">${player.experiencePerMinute}</span></section>
953
953
  <section>治疗量:<span class="heal">${player.heroHealing}</span></section>
954
- <section>控制时间:<span class="building_damage">${(player.stats?.heroDamageReport?.dealtTotal.stunDuration / 100).toFixed(2)}/${(player.stats?.heroDamageReport?.dealtTotal.slowDuration / 100).toFixed(2)}/${(
955
- player.stats?.heroDamageReport?.dealtTotal.disableDuration / 100
954
+ <section>控制时间:<span class="building_damage">${((player.stats?.heroDamageReport?.dealtTotal.stunDuration ?? 0) / 100).toFixed(2)}/${((player.stats?.heroDamageReport?.dealtTotal.slowDuration ?? 0) / 100).toFixed(2)}/${(
955
+ (player.stats?.heroDamageReport?.dealtTotal.disableDuration ?? 0) / 100
956
956
  ).toFixed(2)}</span>s</section>
957
957
  </div>
958
958
  </div>`).join("") %>
959
959
  </div>
960
960
  <div class="ban_list">
961
- <%- match.pickBans
961
+ <%- (match.pickBans??[])
962
962
  .filter((hero) => !hero.isPick)
963
963
  .map((hero) => `<div class="ban_hero"><img src="${utils.getImageUrl(/^npc_dota_hero_(?<name>.+)$/.exec(dotaconstants.heroes[hero.bannedHeroId].name)[1], ImageType.Heroes)}" alt="" /></div>`)
964
964
  .join("") %>
@@ -396,11 +396,11 @@
396
396
  (${(player.heroDamage / player.networth)?.toFixed(2)})
397
397
  </p>
398
398
  <p class="hero_damage">造成伤害:${player.heroDamage} (${(player.heroDamage/match[player.team].heroDamage*100).toFixed(2)}%)</p>
399
- <p class="damage_received">承受伤害:${player.damageReceived} (${(player.damageReceived/match[player.team].damageReceived*100).toFixed(2)}%)</p>
399
+ <p class="damage_received">承受伤害:${player.damageReceived} (${match[player.team].damageReceived>0?((player.damageReceived/match[player.team].damageReceived*100).toFixed(2)):"0.00"}%)</p>
400
400
  <p class="tower_damage">建筑伤害:${player.towerDamage}</p>
401
401
  <p class="kda row-1">${player.kills}/${player.deaths}/${player.assists} (${((player.kills + player.assists) / (player.deaths || 1)).toFixed(2)})</p>
402
402
  <p class="kill_contribution">参战率:${(player.killContribution * 100).toFixed(2)}%</p>
403
- <p class="stun_duration">控制时间:${(player.stats.heroDamageReport.dealtTotal.stunDuration / 100).toFixed(2)}s</p>
403
+ <p class="stun_duration">控制时间:${((player.stats.heroDamageReport?.dealtTotal.stunDuration ?? 0)/ 100).toFixed(2)}s</p>
404
404
  <p class="heal">治疗量:${player.heroHealing}</p>
405
405
  <div class="items row-1">
406
406
  <div class="normal">
@@ -430,8 +430,8 @@
430
430
  </div>
431
431
  <div class="neutral_item row-1" style="background-image: url(${utils.getImageUrl(dotaconstants.item_ids[player.neutral0Id], ImageType.Items)})"></div>
432
432
  <div class="ahgs row-1">
433
- <img src="${utils.getImageUrl("scepter_"+((player.items.concat(player.backpacks).find(item=>item?.id==108)||player.stats.matchPlayerBuffEvent.find(buff=>buff.itemId==108))?1:0))}" alt="" />
434
- <img src="${utils.getImageUrl("shard_"+(player.stats.matchPlayerBuffEvent.find(buff=>buff.itemId==609)?1:0))}" alt="" />
433
+ <img src="${utils.getImageUrl("scepter_"+((player.items.concat(player.backpacks).find(item=>item?.id==108)||(player.stats?.matchPlayerBuffEvent||[]).find(buff=>buff.itemId==108))?1:0))}" alt="" />
434
+ <img src="${utils.getImageUrl("shard_"+((player.stats?.matchPlayerBuffEvent||[]).find(buff=>buff.itemId==609)?1:0))}" alt="" />
435
435
  </div>
436
436
  </div>
437
437
  `).join("") %>