@sjtdev/koishi-plugin-dota2tracker 1.2.14 → 1.2.16-pre.1

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 (3) hide show
  1. package/lib/index.js +66 -93
  2. package/package.json +4 -4
  3. package/changelog.md +0 -256
package/lib/index.js CHANGED
@@ -73,9 +73,9 @@ __export(queries_exports, {
73
73
  MATCHES_FOR_DAILY: () => MATCHES_FOR_DAILY,
74
74
  MATCH_INFO: () => MATCH_INFO,
75
75
  PLAYERS_INFO_WITH_10_MATCHES_FOR_GUILD: () => PLAYERS_INFO_WITH_10_MATCHES_FOR_GUILD,
76
- PLAYERS_LASTMATCH: () => PLAYERS_LASTMATCH,
77
76
  PLAYER_EXTRA_INFO: () => PLAYER_EXTRA_INFO,
78
77
  PLAYER_INFO_WITH_25_MATCHES: () => PLAYER_INFO_WITH_25_MATCHES,
78
+ PLAYER_LASTMATCH: () => PLAYER_LASTMATCH,
79
79
  VERIFYING_PLAYER: () => VERIFYING_PLAYER
80
80
  });
81
81
  var dotaconstants = __toESM(require("dotaconstants"));
@@ -150,12 +150,6 @@ function MATCH_INFO(matchId) {
150
150
  stackCount
151
151
  }
152
152
  }
153
- playbackData {
154
- purchaseEvents {
155
- itemId
156
- time
157
- }
158
- }
159
153
  heroDamage
160
154
  towerDamage
161
155
  stats {
@@ -173,6 +167,10 @@ function MATCH_INFO(matchId) {
173
167
  experiencePerMinute
174
168
  heroHealing
175
169
  stats {
170
+ itemPurchases{
171
+ itemId
172
+ time
173
+ }
176
174
  campStack
177
175
  heroDamageReport {
178
176
  dealtTotal {
@@ -259,27 +257,29 @@ function VERIFYING_PLAYER(steamAccountId) {
259
257
  `;
260
258
  }
261
259
  __name(VERIFYING_PLAYER, "VERIFYING_PLAYER");
262
- function PLAYERS_LASTMATCH(steamAccountIds) {
260
+ function PLAYER_LASTMATCH(steamAccountId) {
263
261
  return `
264
- {
265
- players(steamAccountIds:${JSON.stringify(steamAccountIds)}) {
266
- steamAccount{id}
267
- matches(request:{take:1}){
262
+ {
263
+ player(steamAccountId: ${steamAccountId}) {
264
+ steamAccount {
265
+ id
266
+ }
267
+ matches(request: {take: 1}) {
268
+ id
269
+ parsedDateTime
270
+ startDateTime
271
+ players {
272
+ steamAccount {
268
273
  id
269
- parsedDateTime
270
- startDateTime
271
- players{
272
- steamAccount{
273
- id
274
- }
275
- }
276
274
  }
277
275
  }
278
276
  }
279
-
280
- `;
277
+ }
278
+ }
279
+
280
+ `;
281
281
  }
282
- __name(PLAYERS_LASTMATCH, "PLAYERS_LASTMATCH");
282
+ __name(PLAYER_LASTMATCH, "PLAYER_LASTMATCH");
283
283
  function PLAYER_INFO_WITH_25_MATCHES(steamAccountId, heroId) {
284
284
  return `
285
285
  {
@@ -529,6 +529,7 @@ async function query(query_str) {
529
529
  return await http.post(CONFIGS.STRATZ_API.URL, query_str, {
530
530
  responseType: "json",
531
531
  headers: {
532
+ "User-Agent": "STRATZ_API",
532
533
  "Content-Type": "application/graphql",
533
534
  Authorization: `Bearer ${CONFIGS.STRATZ_API.TOKEN}`
534
535
  }
@@ -564,8 +565,7 @@ var ImageFormat = /* @__PURE__ */ ((ImageFormat2) => {
564
565
  function getImageUrl(image, type = "local" /* Local */, format = "png" /* png */) {
565
566
  if (type === "local" /* Local */) {
566
567
  try {
567
- if (format === "svg" /* svg */)
568
- return import_fs.default.readFileSync(`./node_modules/@sjtdev/koishi-plugin-dota2tracker/template/images/${image}.svg`);
568
+ if (format === "svg" /* svg */) return import_fs.default.readFileSync(`./node_modules/@sjtdev/koishi-plugin-dota2tracker/template/images/${image}.svg`);
569
569
  const imageData = import_fs.default.readFileSync(`./node_modules/@sjtdev/koishi-plugin-dota2tracker/template/images/${image}.png`);
570
570
  const base64Data = imageData.toString("base64");
571
571
  return `data:image/png;base64,${base64Data}`;
@@ -573,8 +573,7 @@ function getImageUrl(image, type = "local" /* Local */, format = "png" /* png */
573
573
  console.error(error);
574
574
  return "";
575
575
  }
576
- } else
577
- return `https://cdn.cloudflare.steamstatic.com/apps/dota2/images/dota_react/${type}/${image}.${format}`;
576
+ } else return `https://cdn.cloudflare.steamstatic.com/apps/dota2/images/dota_react/${type}/${image}.${format}`;
578
577
  }
579
578
  __name(getImageUrl, "getImageUrl");
580
579
  function getFormattedMatchData(data) {
@@ -597,8 +596,7 @@ function getFormattedMatchData(data) {
597
596
  const party_mark = ["I", "II", "III", "IV"];
598
597
  let heroOrderList = {};
599
598
  for (let hero of match.pickBans ?? []) {
600
- if (hero.isPick)
601
- heroOrderList[hero.heroId] = hero.order;
599
+ if (hero.isPick) heroOrderList[hero.heroId] = hero.order;
602
600
  }
603
601
  let processLaneOutcome = /* @__PURE__ */ __name(function(outcome) {
604
602
  switch (outcome) {
@@ -638,8 +636,7 @@ function getFormattedMatchData(data) {
638
636
  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;
639
637
  player.order = heroOrderList[player.hero.id];
640
638
  if (player.partyId != null) {
641
- if (!match.party[player.partyId])
642
- match.party[player.partyId] = party_mark[party_index++];
639
+ if (!match.party[player.partyId]) match.party[player.partyId] = party_mark[party_index++];
643
640
  }
644
641
  if (player.stats.matchPlayerBuffEvent) {
645
642
  const maxStackCountsByAbilityOrItem = player.stats.matchPlayerBuffEvent.reduce((acc, event) => {
@@ -671,7 +668,7 @@ function getFormattedMatchData(data) {
671
668
  obj[key] = 0;
672
669
  return obj;
673
670
  }, {});
674
- if (player.playbackData) {
671
+ if (player.stats?.itemPurchases) {
675
672
  const getNextElement = /* @__PURE__ */ __name(function() {
676
673
  let currentIndex = 0;
677
674
  return function() {
@@ -683,7 +680,7 @@ function getFormattedMatchData(data) {
683
680
  return element;
684
681
  };
685
682
  }, "getNextElement");
686
- for (let item of player.playbackData.purchaseEvents) {
683
+ for (let item of player.stats.itemPurchases) {
687
684
  if (!supportItemIds.includes(item.itemId)) {
688
685
  if (!items_timelist[item.itemId]) {
689
686
  items_timelist[item.itemId] = [];
@@ -896,10 +893,8 @@ __name(winRateColor, "winRateColor");
896
893
  async function playerisValid(steamAccountId) {
897
894
  try {
898
895
  let queryRes = await query(VERIFYING_PLAYER(steamAccountId));
899
- if (queryRes.data.player.matchCount != null)
900
- return { isValid: true };
901
- else
902
- return { isValid: false, reason: "SteamID无效或无任何场次。" };
896
+ if (queryRes.data.player.matchCount != null) return { isValid: true };
897
+ else return { isValid: false, reason: "SteamID无效或无任何场次。" };
903
898
  } catch (error) {
904
899
  console.error(error);
905
900
  return { isValid: false, reason: "网络状况不佳SteamID验证失败,请稍后重试。" };
@@ -1196,7 +1191,8 @@ var HEROES_CHINESE = {
1196
1191
  "135": ["破晓辰星", "大锤"],
1197
1192
  "136": ["玛西"],
1198
1193
  "137": ["獸", "畜"],
1199
- "138": ["琼英碧灵", "奶绿", "绿奶奶"]
1194
+ "138": ["琼英碧灵", "奶绿", "绿奶奶"],
1195
+ "145": ["凯"]
1200
1196
  };
1201
1197
  var WIN_NEGATIVE = ["侥幸赢得了比赛", "走狗屎运赢得了比赛", "躺赢了比赛", "打团都没来, 队友4V5赢得了比赛"];
1202
1198
  var WIN_POSITIVE = ["带领团队走向了胜利", "暴打对面后赢得了胜利", " CARRY全场赢得了胜利", "把对面当猪宰了, 赢得了胜利", "又赢了, 这游戏就是这么枯燥, 且乏味", "直接进行一个比赛的赢"];
@@ -1277,8 +1273,7 @@ async function apply(ctx, config) {
1277
1273
  ctx.command("订阅本群", "订阅后还需玩家在本群绑定SteamID").usage("订阅后还需玩家在本群绑定SteamID,BOT将订阅本群中已绑定玩家的新比赛数据,在STRATZ比赛解析完成后将比赛数据生成为图片战报发布至本群中。").action(async ({ session }) => {
1278
1274
  if (session.guild) {
1279
1275
  let currentGuild = (await ctx.database.get("dt_subscribed_guilds", { guildId: session.event.channel.id, platform: session.event.platform }))[0];
1280
- if (currentGuild)
1281
- session.send("本群已订阅,无需重复订阅。");
1276
+ if (currentGuild) session.send("本群已订阅,无需重复订阅。");
1282
1277
  else {
1283
1278
  ctx.database.create("dt_subscribed_guilds", { guildId: session.event.channel.id, platform: session.event.platform });
1284
1279
  session.send("订阅成功。");
@@ -1293,8 +1288,7 @@ async function apply(ctx, config) {
1293
1288
  session.send("取消订阅成功。");
1294
1289
  return;
1295
1290
  }
1296
- } else
1297
- session.send("本群尚未订阅,无需取消订阅。");
1291
+ } else session.send("本群尚未订阅,无需取消订阅。");
1298
1292
  });
1299
1293
  ctx.command("绑定 <steam_id> [nick_name]", "绑定SteamID,并起一个别名(也可以不起)").usage("将你的SteamID与你的账号绑定,若本群已订阅将会实时获取你的新比赛数据发布至群中。").example("绑定 123456789").example("绑定 123456789 张三").action(async ({ session }, steam_id, nick_name) => {
1300
1294
  if (session.guild) {
@@ -1339,8 +1333,7 @@ async function apply(ctx, config) {
1339
1333
  if (sessionPlayer) {
1340
1334
  await ctx.database.remove("dt_subscribed_players", sessionPlayer.id);
1341
1335
  session.send("取消绑定成功。");
1342
- } else
1343
- session.send("尚未绑定,无需取消绑定。");
1336
+ } else session.send("尚未绑定,无需取消绑定。");
1344
1337
  }
1345
1338
  });
1346
1339
  ctx.command("改名 <nick_name>", "修改绑定时设定的别名").example("改名 李四").action(async ({ session }, nick_name) => {
@@ -1451,7 +1444,7 @@ async function apply(ctx, config) {
1451
1444
  let lastMatchId = 0;
1452
1445
  try {
1453
1446
  session.send("正在搜索对局详情,请稍后...");
1454
- lastMatchId = (await query(PLAYERS_LASTMATCH([parseInt(flagBindedPlayer ? flagBindedPlayer.steamId : input_data)]))).data.players[0].matches[0].id;
1447
+ lastMatchId = (await query(PLAYER_LASTMATCH(parseInt(flagBindedPlayer?.steamId ?? input_data)))).data.player.matches[0].id;
1455
1448
  } catch {
1456
1449
  session.send("获取玩家最近比赛失败。");
1457
1450
  return;
@@ -1533,8 +1526,7 @@ async function apply(ctx, config) {
1533
1526
  }
1534
1527
  });
1535
1528
  ctx.command("查询英雄 <input_data>", "查询英雄技能/面板信息").usage("查询英雄的技能说明与各项数据,生成图片发布。\n参数可输入英雄ID、英雄名、英雄常用别名").option("random", "-r 随机选择英雄").example("查询英雄 15").example("查询英雄 雷泽").example("查询英雄 电魂").action(async ({ session, options }, input_data) => {
1536
- if (options.random)
1537
- input_data = random.pick(Object.keys(HEROES_CHINESE));
1529
+ if (options.random) input_data = random.pick(Object.keys(HEROES_CHINESE));
1538
1530
  if (input_data) {
1539
1531
  let hero = findingHero(input_data);
1540
1532
  if (!hero) {
@@ -1548,12 +1540,10 @@ async function apply(ctx, config) {
1548
1540
  hero.facet_abilities.forEach((fa, i) => {
1549
1541
  if (fa.abilities.length) {
1550
1542
  fa.abilities.forEach((ab) => {
1551
- if (!hero.facets[i].abilities)
1552
- hero.facets[i].abilities = [];
1543
+ if (!hero.facets[i].abilities) hero.facets[i].abilities = [];
1553
1544
  if (hero.facets[i].description_loc !== ab.desc_loc)
1554
1545
  hero.facets[i].abilities.push({ id: ab.id, name: ab.name, name_loc: ab.name_loc, description_ability_loc: formatHeroDesc(ab.desc_loc, ab.special_values, "facet" /* Facet */) });
1555
- else
1556
- hero.facets[i].description_loc = formatHeroDesc(hero.facets[i].description_loc, ab.special_values, "facet" /* Facet */);
1546
+ else hero.facets[i].description_loc = formatHeroDesc(hero.facets[i].description_loc, ab.special_values, "facet" /* Facet */);
1557
1547
  ab.ability_is_facet = true;
1558
1548
  ab.facet = hero.facets[i];
1559
1549
  hero.abilities.push(ab);
@@ -1564,11 +1554,9 @@ async function apply(ctx, config) {
1564
1554
  hero.abilities.forEach((ab) => {
1565
1555
  ab.facets_loc.forEach((facet, i) => {
1566
1556
  i = i + (hero.facets.length - ab.facets_loc.length);
1567
- if (i < 0)
1568
- return;
1557
+ if (i < 0) return;
1569
1558
  if (facet) {
1570
- if (!hero.facets[i].abilities)
1571
- hero.facets[i].abilities = [];
1559
+ if (!hero.facets[i].abilities) hero.facets[i].abilities = [];
1572
1560
  hero.facets[i].abilities.push({ id: ab.id, name: ab.name, name_loc: ab.name_loc, description_ability_loc: formatHeroDesc(facet, ab.special_values, "facet" /* Facet */), attributes: [] });
1573
1561
  }
1574
1562
  });
@@ -1576,8 +1564,7 @@ async function apply(ctx, config) {
1576
1564
  const svs = ab.special_values.filter((sv) => sv.facet_bonus.name === facet.name);
1577
1565
  svs.forEach((sv) => {
1578
1566
  if (sv.heading_loc) {
1579
- if (!facet.abilities)
1580
- facet.abilities = [];
1567
+ if (!facet.abilities) facet.abilities = [];
1581
1568
  facet.abilities.find((ability) => ab.id == ability.id)?.attributes.push({ heading_loc: sv.heading_loc, values: [...sv.facet_bonus.values], is_percentage: sv.is_percentage });
1582
1569
  }
1583
1570
  });
@@ -1585,10 +1572,8 @@ async function apply(ctx, config) {
1585
1572
  });
1586
1573
  ab.desc_loc = formatHeroDesc(ab.desc_loc, ab.special_values, ab.ability_is_facet ? "facet" /* Facet */ : void 0);
1587
1574
  ab.notes_loc = ab.notes_loc.map((note) => formatHeroDesc(note, ab.special_values));
1588
- if (ab.ability_has_scepter)
1589
- ab.scepter_loc = formatHeroDesc(ab.scepter_loc, ab.special_values, "scepter" /* Scepter */);
1590
- if (ab.ability_has_shard)
1591
- ab.shard_loc = formatHeroDesc(ab.shard_loc, ab.special_values, "shard" /* Shard */);
1575
+ if (ab.ability_has_scepter) ab.scepter_loc = formatHeroDesc(ab.scepter_loc, ab.special_values, "scepter" /* Scepter */);
1576
+ if (ab.ability_has_shard) ab.shard_loc = formatHeroDesc(ab.shard_loc, ab.special_values, "shard" /* Shard */);
1592
1577
  });
1593
1578
  hero.talents.forEach((talent) => {
1594
1579
  const regex = /\{s:(.*?)\}/g;
@@ -1661,8 +1646,7 @@ async function apply(ctx, config) {
1661
1646
  }
1662
1647
  });
1663
1648
  function findingHero(input) {
1664
- if (!input)
1665
- return;
1649
+ if (!input) return;
1666
1650
  let dc_heroes = Object.values(dotaconstants3.heroes).map((hero) => ({
1667
1651
  id: hero["id"],
1668
1652
  name: hero["name"],
@@ -1676,10 +1660,8 @@ async function apply(ctx, config) {
1676
1660
  [dc_heroes, cn_heroes].forEach((array) => {
1677
1661
  array.forEach((item) => {
1678
1662
  const existingItem = mergedMap.get(item.id);
1679
- if (existingItem)
1680
- mergedMap.set(item.id, { ...existingItem, ...item });
1681
- else
1682
- mergedMap.set(item.id, item);
1663
+ if (existingItem) mergedMap.set(item.id, { ...existingItem, ...item });
1664
+ else mergedMap.set(item.id, item);
1683
1665
  });
1684
1666
  });
1685
1667
  let heroes3 = Array.from(mergedMap.values());
@@ -1724,7 +1706,11 @@ async function apply(ctx, config) {
1724
1706
  const subscribedPlayersSteamIds = subscribedPlayersInGuild.map((player) => player.steamId).filter(function(value, index, self) {
1725
1707
  return self.indexOf(value) === index;
1726
1708
  });
1727
- const lastMatches = (await query(PLAYERS_LASTMATCH(subscribedPlayersSteamIds))).data.players.map((player) => player.matches[0]).filter((item, index, self) => index === self.findIndex((t) => t.id === item.id)).filter((match) => import_moment.default.unix(match.startDateTime).isAfter((0, import_moment.default)().subtract(1, "days"))).filter((match) => !pendingMatches.some((pendingMatch) => pendingMatch.matchId == match.id));
1709
+ const players = [];
1710
+ for (let id of subscribedPlayersSteamIds) {
1711
+ players.push((await query(PLAYER_LASTMATCH(id))).data.player);
1712
+ }
1713
+ const lastMatches = players.map((player) => player.matches[0]).filter((item, index, self) => index === self.findIndex((t) => t.id === item.id)).filter((match) => import_moment.default.unix(match.startDateTime).isAfter((0, import_moment.default)().subtract(1, "days"))).filter((match) => !pendingMatches.some((pendingMatch) => pendingMatch.matchId == match.id));
1728
1714
  const sendedMatchesIds = (await ctx.database.get("dt_sended_match_id", { matchId: lastMatches.map((match) => match.id) }, ["matchId"])).map((match) => match.matchId);
1729
1715
  lastMatches.filter((match) => !sendedMatchesIds.includes(match.id)).forEach((match) => {
1730
1716
  const tempGuilds = [];
@@ -1732,10 +1718,8 @@ async function apply(ctx, config) {
1732
1718
  subscribedPlayersInGuild.filter((subscribedPlayer) => subscribedPlayer.steamId === player.steamAccount.id).forEach((subscribedPlayer) => {
1733
1719
  if (subscribedPlayer) {
1734
1720
  const tempGuild = tempGuilds.find((guild) => guild.guildId == subscribedPlayer.guildId && guild.platform == subscribedPlayer.platform);
1735
- if (tempGuild)
1736
- tempGuild.players.push(subscribedPlayer);
1737
- else
1738
- tempGuilds.push({ guildId: subscribedPlayer.guildId, platform: subscribedPlayer.platform, players: [subscribedPlayer] });
1721
+ if (tempGuild) tempGuild.players.push(subscribedPlayer);
1722
+ else tempGuilds.push({ guildId: subscribedPlayer.guildId, platform: subscribedPlayer.platform, players: [subscribedPlayer] });
1739
1723
  }
1740
1724
  });
1741
1725
  });
@@ -1754,8 +1738,7 @@ async function apply(ctx, config) {
1754
1738
  if (queryLocal.length > 0) {
1755
1739
  match = queryLocal[0].data;
1756
1740
  ctx.database.set("dt_previous_query_results", match.id, { queryTime: /* @__PURE__ */ new Date() });
1757
- } else
1758
- match = getFormattedMatchData((await query(MATCH_INFO(pendingMatch.matchId))).data);
1741
+ } else match = getFormattedMatchData((await query(MATCH_INFO(pendingMatch.matchId))).data);
1759
1742
  if (match.parsedDateTime || import_moment.default.unix(match.endDateTime).isBefore(now.subtract(config.dataParsingTimeoutMinutes, "minutes"))) {
1760
1743
  pendingMatches = pendingMatches.filter((item) => item.matchId != match.id);
1761
1744
  const img = await ctx.puppeteer.render(genImageHTML(match, config.template_match, "match" /* Match */));
@@ -1769,13 +1752,11 @@ async function apply(ctx, config) {
1769
1752
  if (player.isRadiant == match.didRadiantWin) {
1770
1753
  if (player.deathContribution < 0.2 || player.killContribution > 0.75 || player.heroDamage / player.networth > 1.5 || player.towerDamage > 1e4 || player.imp > 0)
1771
1754
  broadPlayerMessage += random2.pick(WIN_POSITIVE);
1772
- else
1773
- broadPlayerMessage += random2.pick(WIN_NEGATIVE);
1755
+ else broadPlayerMessage += random2.pick(WIN_NEGATIVE);
1774
1756
  } else {
1775
1757
  if (player.deathContribution < 0.25 || player.killContribution > 0.75 || player.heroDamage / player.networth > 1 || player.towerDamage > 5e3 || player.imp > 0)
1776
1758
  broadPlayerMessage += random2.pick(LOSE_POSITIVE);
1777
- else
1778
- broadPlayerMessage += random2.pick(LOSE_NEGATIVE);
1759
+ else broadPlayerMessage += random2.pick(LOSE_NEGATIVE);
1779
1760
  }
1780
1761
  broadPlayerMessage += `。
1781
1762
  KDA:${((player.kills + player.assists) / (player.deaths || 1)).toFixed(2)} [${player.kills}/${player.deaths}/${player.assists}],GPM/XPM:${player.goldPerMinute}/${player.experiencePerMinute},补刀数:${player.numLastHits}/${player.numDenies},伤害/塔伤:${player.heroDamage}/${player.towerDamage},参战/参葬率:${(player.killContribution * 100).toFixed(2)}%/${(player.deathContribution * 100).toFixed(2)}%`;
@@ -1787,8 +1768,7 @@ KDA:${((player.kills + player.assists) / (player.deaths || 1)).toFixed(2)} [${
1787
1768
  if (match.parsedDateTime)
1788
1769
  ctx.database.upsert("dt_previous_query_results", (row) => [{ matchId: match.id, data: match, queryTime: /* @__PURE__ */ new Date() }]);
1789
1770
  ctx.database.create("dt_sended_match_id", { matchId: match.id, sendTime: /* @__PURE__ */ new Date() });
1790
- } else
1791
- ctx.logger.info("比赛 %d 尚未解析完成,继续等待。", match.id);
1771
+ } else ctx.logger.info("比赛 %d 尚未解析完成,继续等待。", match.id);
1792
1772
  } catch (error) {
1793
1773
  ctx.logger.error(error);
1794
1774
  ctx.database.remove("dt_previous_query_results", { matchId: pendingMatch.matchId });
@@ -1808,8 +1788,7 @@ KDA:${((player.kills + player.assists) / (player.deaths || 1)).toFixed(2)} [${
1808
1788
  const matches = players.map((player) => player.matches.map((match) => match)).flat().filter((item, index, self) => index === self.findIndex((t) => t.id === item.id));
1809
1789
  for (let subPlayer of subscribedPlayersInGuild) {
1810
1790
  let player = players.find((player2) => subPlayer.steamId == player2.steamAccount.id);
1811
- if (!player)
1812
- continue;
1791
+ if (!player) continue;
1813
1792
  let guildMember;
1814
1793
  try {
1815
1794
  guildMember = await ctx.bots.find((bot) => bot.platform == subPlayer.platform)?.getGuildMember(subPlayer.guildId, subPlayer.userId);
@@ -1860,12 +1839,9 @@ KDA:${((player.kills + player.assists) / (player.deaths || 1)).toFixed(2)} [${
1860
1839
  {
1861
1840
  title,
1862
1841
  players: currentsubscribedPlayers.sort((a, b) => {
1863
- if (a.matches.length > b.matches.length)
1864
- return -1;
1865
- else if (a.matches.length < b.matches.length)
1866
- return 1;
1867
- else
1868
- return a.steamAccount.id - b.steamAccount.id;
1842
+ if (a.matches.length > b.matches.length) return -1;
1843
+ else if (a.matches.length < b.matches.length) return 1;
1844
+ else return a.steamAccount.id - b.steamAccount.id;
1869
1845
  }),
1870
1846
  combinations,
1871
1847
  showCombi
@@ -1912,13 +1888,10 @@ function genImageHTML(data, template, type) {
1912
1888
  };
1913
1889
  let result = "";
1914
1890
  ejs.renderFile(templatePath, templateData, { strict: false }, (err, html) => {
1915
- if (err)
1916
- throw err;
1917
- else
1918
- result = html;
1891
+ if (err) throw err;
1892
+ else result = html;
1919
1893
  });
1920
- if (process.env.NODE_ENV === "development")
1921
- import_fs2.default.writeFileSync("./node_modules/@sjtdev/koishi-plugin-dota2tracker/temp.html", result);
1894
+ if (process.env.NODE_ENV === "development") import_fs2.default.writeFileSync("./node_modules/@sjtdev/koishi-plugin-dota2tracker/temp.html", result);
1922
1895
  return result;
1923
1896
  }
1924
1897
  __name(genImageHTML, "genImageHTML");
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@sjtdev/koishi-plugin-dota2tracker",
3
3
  "description": "koishi插件-追踪群友的DOTA2对局",
4
- "version": "1.2.14",
4
+ "version": "1.2.16-pre.1",
5
5
  "main": "lib/index.js",
6
6
  "typings": "lib/index.d.ts",
7
7
  "files": [
@@ -26,12 +26,12 @@
26
26
  "dota2"
27
27
  ],
28
28
  "dependencies": {
29
- "dotaconstants": "^8.11.0",
29
+ "dotaconstants": "^8.13.0",
30
30
  "ejs": "^3.1.10",
31
31
  "moment": "^2.30.1"
32
32
  },
33
33
  "peerDependencies": {
34
- "koishi": "^4.17.10"
34
+ "koishi": "^4.18.1"
35
35
  },
36
36
  "koishi": {
37
37
  "preview": "true",
@@ -48,4 +48,4 @@
48
48
  "zh"
49
49
  ]
50
50
  }
51
- }
51
+ }
package/changelog.md DELETED
@@ -1,256 +0,0 @@
1
- # 1.2.14
2
- **修复**:
3
- - 修复插件配置中`周报功能`与`日报功能`错误地成为必须项的问题,感谢[issue](../../issues/1)捉虫!
4
-
5
- # 1.2.13
6
- **新增&改进**:
7
- - 战报模板`match_1`追加显示命石名,并调整了其他信息的显示效果以适配此改动。
8
-
9
- # 1.2.12
10
- **新增&改进**:
11
- - 战报模板`match_2`追加显示命石名,并调整了其他信息的显示效果以适配此改动。
12
-
13
- # 1.2.11
14
- **新增&改进**:
15
- - 对战报模板添加命石显示,微调了其他信息的显示效果以适配此改动。
16
-
17
- # 1.2.10
18
- **新增**:
19
- - 添加对新英雄`百戏大王`的支持。(战报播报、查询英雄等)
20
-
21
- **修复**:
22
- - 修复`查询英雄`图片中英雄的“基础攻击间隔”显示有误的问题。
23
- - 修复战报图中若玩家名有html标签会导致图片排版错乱的问题。
24
- - 修复周报与日报中评分条样式不正确的问题。
25
-
26
- **改进**:
27
- - 调整了总结模板和玩家信息模板中胜负字体颜色样式,使其看起来更清晰。
28
- - 优化了总结模板中胜负数和胜率的样式。
29
-
30
- <details>
31
- <summary><b>1.2.10-pre更新日志</b></summary>
32
-
33
- ### 1.2.10-pre.2
34
- **改进**:
35
- - 调整了总结模板和玩家信息模板中胜负字体颜色样式,使其看起来更清晰。
36
- - 优化了总结模板中胜负数和胜率的样式。
37
-
38
- ### 1.2.10-pre
39
- **修复**:
40
- - 修复战报图中若玩家名有html标签会导致图片排版错乱的问题。
41
- - 修复周报与日报中评分条样式不正确的问题。
42
- </details>
43
-
44
- # 1.2.9
45
- **改进**:
46
- - 现在周报与日报改为图片版,依旧由`ejs`生成。去除配置页中周报与日报的“实验性”标识。(目前周报与日报使用同一模板,未来可能会设计数据更丰富的周报,也可能不会_(:3」∠)_
47
- - 优化播报评语随机选择算法离散性,以避免此前若是有多位玩家的随机种子相近则这些玩家选择结果总是相同。
48
- - 优化追踪比赛逻辑:在追踪到群友比赛后等待解析时,此前为按添加顺序等待队列中的比赛,现在修改了判断逻辑,对当前时间分钟数与等待队列的长度进行取余,周期性访问队列中每一场比赛,这样可以优先发送已解析完成的比赛而不会被早加入但迟迟未解析的比赛阻塞。
49
- - 现在可在战报模板`match_1`和玩家信息模板中正确显示打野玩家的对线结果为“野区霸主”并有对应的图标,而不是跟随默认的中路对线结果。([wiki/match_1](https://github.com/sjtdev/koishi-plugin-dota2tracker/wiki/match_1)也已更新。)
50
- - `查询英雄`:命石技能的技能名栏位添加对应命石图标与背景色用于标识。
51
-
52
- **修复**:
53
- - `查询英雄`:修复DOTA2 7.37版本更新后API变动导致部分英雄查询报错。
54
-
55
- <details>
56
- <summary><b>1.2.9-pre更新日志</b></summary>
57
-
58
- ### 1.2.9-pre.3
59
- **改进**:
60
- - 尝试修改逻辑:在追踪到群友比赛后等待解析时,此前为按添加顺序等待队列中的比赛,现在修改了判断逻辑,对当前时间分钟数与等待队列的长度进行取余,周期性访问队列中每一场比赛,这样可以优先发送已解析完成的比赛而不会被早加入但迟迟未解析的比赛阻塞。
61
-
62
- ### 1.2.9-pre.2
63
- **改进**:
64
- - 现在可在战报模板`match_1`和玩家信息模板中正确显示打野玩家的对线结果为“野区霸主”并有对应的图标,而不是跟随默认的中路对线结果。([wiki/match_1](https://github.com/sjtdev/koishi-plugin-dota2tracker/wiki/match_1)也已更新。)
65
-
66
- ### 1.2.9-pre
67
- **修复&改进**:
68
- - `查询英雄`:尝试修复DOTA2 7.37版本更新后API变动导致部分英雄查询报错。
69
- - `查询英雄`:命石技能的技能名栏位添加对应命石图标与背景色用于标识。
70
- </details>
71
-
72
- # 1.2.8
73
- **新增**:
74
- - 新增周报功能,效果等同日报。
75
- - 日报与周报中新增可关闭总结中显示组合的功能。
76
-
77
- **改进**:
78
- - 现在`查询玩家`与`查询最近比赛`指令可在私聊状态下使用,必须提供SteamID参数。
79
- - 将战报中的播报评语由随机选取改为固定种子:比赛ID+玩家SteamID+玩家位置,确保在不同调用时刻、次数及平台下,对同一场比赛中的玩家评语保持一致。
80
- - `查询玩家`指令图片中,玩家近期比赛表中未解析的场次参战率由"?%"改为估算值,显示为"≈xx%"。
81
- - `查询英雄`指令图片中,由于命石带来的属性数值无法确定作用方式(增加或是替换等),去除命石属性前的“+”,请结合命石说明自行判断。(7.37版本更新带来的API变动,导致使用指令查询某些英雄报错问题,暂无法解决)
82
- - 战报模板`match_2`中,现在冠绝排名数字位置更准确了。
83
- - 战报模板`match_2`中,比赛段位可以显示星级了。
84
-
85
- <details>
86
- <summary>为什么未解析的比赛需要“估算”?</summary>
87
- 比赛未解析无法获取“团队击杀数”,若是将己方所有玩家的击杀数相加,则会漏掉那些由小兵、防御塔等非玩家单位击杀数;若是将敌方所有玩家的死亡数相加,又会多出送野、自杀等不应算在己方战果中的计数。<br>目前程序采用将己方所有击杀数累加的方式来估算参战率,可能会略高于实际值。
88
- </details>
89
-
90
- <details>
91
- <summary><b>1.2.8-pre更新日志</b></summary>
92
-
93
- ### 1.2.8-pre
94
- **改进**:
95
- - 现在`查询玩家`可在私聊状态使用,必须提供SteamID参数。
96
- - 将战报中的播报评语由随机选取改为固定种子:比赛ID+玩家SteamID,确保在不同调用时刻、次数及平台下,对同一场比赛中的玩家评语保持一致。
97
- - `查询玩家`指令图片中,玩家近期比赛表中未解析的场次参战率由"?%"改为估算值,显示为"≈xx%"
98
-
99
- ##### pre.2
100
- **改进**:
101
- - 战报模板`match_2`中,现在冠绝排名数字位置更准确了。
102
- - 战报模板`match_2`中,比赛段位可以显示星级了。
103
- </details>
104
-
105
- # 1.2.7
106
- ##### 于1.2.7-beta中尝试修复的功能均已正常工作,正式发布1.2.7
107
- ##### 以下为包括beta版更新内容在内的所有改动
108
- ##### **新增**:
109
- - 可在配置页设置查询比赛与发布战报时附带stratz比赛链接、查询玩家信息时附带stratz玩家页面链接、查询英雄数据信息时附带刀塔百科对应英雄页面链接,这些选项均默认关闭。
110
- ##### **修复**:
111
- - 修复当同一个steamId在多个已订阅群组中绑定时,仅会向最早绑定的群组发送战报的问题。
112
- - 现在若所有玩家某项属性都为0时不会错误地将对应称号赋予玩家1,而是取消此称号赋予。(此版本前例如所有玩家治疗量都为0,玩家1会获得“奶”称号,而现在将不会有玩家获得“奶”称号)
113
- - 修复无法获取群组相关信息导致的日报功能失效。
114
- - 修复日报功能中统计组合有可能出现重复的问题。
115
- <details>
116
- <summary><b>1.2.7-beta更新日志</b></summary>
117
-
118
- ### 1.2.7-beta
119
- ##### **新增**:
120
- - 可在配置页设置发布战报时附带stratz比赛链接、查询玩家信息时附带stratz玩家页面链接,这些选项均默认关闭。
121
- ##### **修复**:
122
- - (beta测试中) 尝试修复当同一个steamId在多个已订阅群组中绑定时,仅会向最早绑定的群组发送战报的问题。
123
- - 现在若所有玩家某项属性都为0时不会错误地将对应称号赋予玩家1,而是取消此称号赋予。(此版本前例如所有玩家治疗量都为0,玩家1会获得“奶”称号,而现在将不会有玩家获得“奶”称号)
124
-
125
- #### beta.2
126
- **修复**:尝试修复无法获取群组相关信息导致的日报功能失效。
127
-
128
- #### beta.3
129
- **修复**:尝试修复日报功能中统计组合有可能出现重复的问题。
130
-
131
- </details>
132
-
133
- # 1.2.6
134
- ##### 因koishi更新至4.17.10修复了主动发送消息的函数,本插件的发送消息方式也换回之前的方案以避免可能的代码问题。(功能使用上与1.2.6-pre3版本一致)
135
-
136
- **改进&修复**:修复了`查询英雄`图片中 技能数值未被正确替换、全才英雄基础攻击力显示错误的问题,并优化了命石描述显示方式
137
- **改进**:调整比赛战报图片样式:解析失败时显示的“第-手”改为“第?手”
138
- **改进**:为英雄`艾欧`添加别名:["艾欧", "小精灵"] → ["艾欧", "小精灵", "精灵", "IO"]
139
- **修复**:修复`查询玩家`图片中场次表现评分为0时显示为?的问题
140
-
141
- <details>
142
- <summary><b>1.2.6-pre更新日志</b></summary>
143
-
144
- ### 1.2.6-pre
145
- ##### (因koishi尚未更新发布pre版)
146
- **改进&修复**:修复了`查询英雄`图片中 技能数值未被正确替换、全才英雄基础攻击力显示错误的问题,并优化了命石描述显示方式
147
- **改进**:调整比赛战报图片样式:解析失败时显示的“第-手”改为“第?手”
148
- **修复**:修复`查询玩家`图片中场次表现评分为0时显示为?的问题
149
-
150
- #### pre2
151
- **改进&修复**:彻底完善了`查询英雄`图片中所有由命石、神杖、魔晶提供或改变的数值说明,修复命石说明中技能数值为百分数时未带百分号的问题。
152
-
153
- #### pre3
154
- **改进&修复**:继续优化`查询英雄`代码结构使由命石、神杖、魔晶改变的技能属性更直观;修复某些技能数据中有旧天赋加成数据留存、导致的天赋数值未被正确填充。
155
- **改进**:为英雄`艾欧`添加别名:["艾欧", "小精灵"] → ["艾欧", "小精灵", "精灵", "IO"]
156
-
157
- </details>
158
-
159
- # 1.2.5
160
- **改进**:优化`查询玩家`图片中近期战绩列表内未解析比赛的显示效果
161
- **修复**:修复`查询英雄`图片技能属性名多显示了一个冒号的问题
162
-
163
- #### fix
164
- **修复**:使用临时替代方案修复由koishi-4.17.9的bug引起的无法主动发送消息(播报战报等),待koishi更新修复后回滚此改动。
165
- #### fix3
166
- **修复**:修复使用替代方案导致日报失效的问题。
167
-
168
- # 1.2.4
169
- **修复**:修正调用help指令时本插件某些指令的说明错误
170
- **修复**:修复`取消订阅`指令失效的问题
171
-
172
- # 1.2.3
173
- **修复**:修复了比赛战报图片中称号`摸`判定不正确的问题
174
- **改进**:微调了比赛战报图片模板`match_2`中称号的显示样式
175
-
176
- # 1.2.2
177
- **移除**:取消`查询英雄`的缓存功能,原因为valve的API返回的数据可能包含未本地化的字段(例如这次的7.36b更新后获取到的很多改动后技能说明暂时都是英文),这些数据无法根据版本判断是否需要更新缓存。
178
- **修复**:修复了`查询英雄`图片中某些命石提供技能可能被判定为先天技能的问题。
179
-
180
- # 1.2.1
181
- **改进**:优化比赛战报图片中,对多个同种物品(例如双护腕双挂件一类)的出装时间显示进行优化,原先都将显示为最后一件此种物品的购买时间,现在可以显示不同的时间。
182
- > 从第一件购买时间算起,例如火枪于1:00 2:00 3:00购买了三个系带,游戏结束前卖出其中之一,则剩余两个则显示为1:00 2:00
183
-
184
- **改进**:出于实用性考虑,比赛战报图片中将不再显示辅助道具的购买时间。
185
-
186
- # 1.2.0
187
- **改进**:对`查询英雄`模板代码进行了调整与部分重写,完成7.36版本的英雄数据匹配,现在可正常使用。
188
- > (人话说就是先天技能和命石适配完成了)
189
-
190
- **移除**:因`查询英雄`指令已适配7.36版本,`7.36`指令退役。(删除)
191
- #### hotfix
192
- **修复**:删除一些留存的测试用代码
193
-
194
- # 1.1.10
195
- **修复**:修复`7.36`指令因DOTA2官网的cdn链接变动导致获取失败的问题,并优化了加载速度。
196
- **修复**:修复每次在koishi重新启动后,使用指令`7.36`都会重新获取数据的问题。
197
- #### hotfix
198
- **修复**:修复一处编译问题导致`7.36`指令无法使用的问题
199
-
200
- # 1.1.9
201
- **新增**:v1.1.6加入的功能等待解析时间现在可以配置,位于插件页配置项`dataParsingTimeoutMinutes`
202
- **修复**:修复因v1.1.8修改数据获取方式导致的`绑定`指令失效
203
- **修复**:修复指令`查询英雄`报错问题(数据仍为7.35d,等待上游API更新)
204
- **改进**:兼容Discord、KOOK等频道类平台,将订阅与绑定存储时群组(guild)改为频道(channel),对onebot(qq)类无影响(出现使用问题请联系我)
205
- <details>
206
- <summary>若此前已在使用频道类平台……</summary>
207
- 此版本前频道类平台应该无法使用战报功能与日报功能。此版本在订阅本群与绑定玩家时将存储channelId而不是guildID,对于非频道类平台这两个值是一样的,不会造成影响。但频道类平台应该会彻底失效,解决方案只有操作数据库,将channelId填入原先guildId处(兼容原因,未修改数据库字段名[guildId],但实际上存入的已经是channel的ID了;guildId和channelId可参考数据库表channel中的数据),或重新订阅与绑定。(若是重新订阅与绑定,不会覆盖原先存储guildId的数据,也就是说旧数据依然会存在,可根据需求选择是否删除)
208
- </details>
209
-
210
- # 1.1.8
211
- **改进**:将数据获取方式从 npm 包 `axios` 切换为 Koishi 提供的 `http` 服务,并简化了相关代码(用户体验无差别)。
212
- **改进**:为 `match_2` 模板添加了玩家小队标识(效果与 `match_1` 模板中的相同功能一致,但在显示上进行了微调)。
213
-
214
- # 1.1.7
215
- **改进**:玩家信息模板中代表位置的图标替换为简约风格图标
216
- **修复**:于v1.1.5新增的`7.36`指令生成英雄改动图片时会额外产生的测试用的`remainingContent.html`文件,现已不再生成。(如果之前使用了该命令并产生了此文件,可根据需要手动删除。位于`koishi/node_modules/@sjtdev/koishi-plugin-dota2tracker/`)
217
-
218
- # 1.1.6
219
- 由于近期stratz网站问题,比赛数据无法自动解析,导致bot会一直等待解析后的战报数据而无法发送。
220
- **新增**:现在调整为比赛结束1小时后仍然未解析时将直接发出缺失部分数据的战报(缺失包括BP顺序、出装时间、英雄受到伤害等)
221
- #### hotfix
222
- **修复**:修复引发播报未解析比赛战报失败的一个小问题
223
-
224
- # 1.1.5
225
- **新增**:为新版本7.36添加新指令`7.36`
226
- `7.36 <英雄ID|英雄名|英雄常用别名>`可查询对应英雄的改动信息,未输入英雄查询参数时直接返回官网7.36更新日志链接
227
- 添加`--refresh|-r`参数可强制重新获取数据,如`7.36 -r`,也可在查询时使用,如`7.36 敌法师 -r`
228
-
229
- # 1.1.4
230
- **改进**:完善查询玩家指定英雄的生成模板
231
-
232
- # 1.1.3
233
- **新增**:新增实验性功能【日报昨日总结】,在指定时间播报昨日已订阅群组中已绑定群友的战绩(简略文字),默认关闭,可在插件配置中打开
234
- `查询玩家`指令新增功能,现在额外输入参数`--hero <英雄ID|英雄名|英雄常用别名>`可查询目标玩家指定英雄的详情(--hero可替换为-o)
235
- 例如:
236
- * `查询玩家 123456789 --hero 敌法师`
237
- * `查询玩家 -o 敌法师` (仍可缺省玩家参数以自查)
238
-
239
- # 1.1.2
240
- **改进**:完成查询群友功能
241
- **修复**:修复玩家模板中显示NaN的部分
242
- #### hotfix
243
- **修复**:修复查询远古玩家账号时可能意外失败的问题
244
- **改进**:调整mvp中的控制分与[控]称号算法
245
- #### hotfix.2
246
- **修复**:修复初次使用查询英雄指令时,技能名初始化失败导致的错误
247
-
248
- ### 1.1.2-beta
249
- **改进**:为`查询群友`添加模板,还在调整布局中
250
-
251
- # 1.1.1
252
- **改进**:玩家信息模板添加近25场内各个位置表现展示
253
-
254
- # 1.1.0
255
- **改进**:使用ejs重写模板相关代码使其模块化,使新增模板更方便
256
- **新增**:为比赛信息添加了仿MAX+模板,效果可见[match_2](https://github.com/sjtdev/koishi-plugin-dota2tracker/wiki/match_2),可在插件配置中切换