@sjtdev/koishi-plugin-dota2tracker 1.2.17 → 1.2.18-beta.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.
package/lib/index.js CHANGED
@@ -50,13 +50,13 @@ __export(utils_exports, {
50
50
  formatNumber: () => formatNumber,
51
51
  getFormattedMatchData: () => getFormattedMatchData,
52
52
  getImageUrl: () => getImageUrl,
53
+ init: () => init,
53
54
  playerisValid: () => playerisValid,
54
55
  query: () => query,
55
56
  queryHeroFromValve: () => queryHeroFromValve,
56
57
  readDirectoryFilesSync: () => readDirectoryFilesSync,
57
58
  roundToDecimalPlaces: () => roundToDecimalPlaces,
58
59
  sec2time: () => sec2time,
59
- setHttp: () => setHttp,
60
60
  winRateColor: () => winRateColor
61
61
  });
62
62
  var import_fs = __toESM(require("fs"));
@@ -70,10 +70,10 @@ __export(queries_exports, {
70
70
  CURRENT_GAMEVERSION: () => CURRENT_GAMEVERSION,
71
71
  HERO_INFO: () => HERO_INFO,
72
72
  HERO_MATCHUP_WINRATE: () => HERO_MATCHUP_WINRATE,
73
- MATCHES_FOR_DAILY: () => MATCHES_FOR_DAILY,
74
73
  MATCH_INFO: () => MATCH_INFO,
75
74
  PLAYERS_INFO_WITH_10_MATCHES_FOR_GUILD: () => PLAYERS_INFO_WITH_10_MATCHES_FOR_GUILD,
76
75
  PLAYERS_LASTMATCH_RANKINFO: () => PLAYERS_LASTMATCH_RANKINFO,
76
+ PLAYERS_MATCHES_FOR_DAILY: () => PLAYERS_MATCHES_FOR_DAILY,
77
77
  PLAYER_EXTRA_INFO: () => PLAYER_EXTRA_INFO,
78
78
  PLAYER_INFO_WITH_25_MATCHES: () => PLAYER_INFO_WITH_25_MATCHES,
79
79
  REQUEST_MATCH_DATA_ANALYSIS: () => REQUEST_MATCH_DATA_ANALYSIS,
@@ -221,10 +221,10 @@ function MATCH_INFO(matchId) {
221
221
  `;
222
222
  }
223
223
  __name(MATCH_INFO, "MATCH_INFO");
224
- function MATCHES_FOR_DAILY(steamAccountIds, seconds) {
224
+ function PLAYERS_MATCHES_FOR_DAILY(steamAccountIds, seconds) {
225
225
  return `
226
226
  {
227
- players(steamAccountIds:${JSON.stringify(steamAccountIds)}) {
227
+ players(steamAccountIds:[${steamAccountIds.join(",")}]) {
228
228
  steamAccount{id name avatar}
229
229
  matches(request:{startDateTime:${seconds} take:50}){
230
230
  id
@@ -246,7 +246,7 @@ function MATCHES_FOR_DAILY(steamAccountIds, seconds) {
246
246
  }
247
247
  `;
248
248
  }
249
- __name(MATCHES_FOR_DAILY, "MATCHES_FOR_DAILY");
249
+ __name(PLAYERS_MATCHES_FOR_DAILY, "PLAYERS_MATCHES_FOR_DAILY");
250
250
  function VERIFYING_PLAYER(steamAccountId) {
251
251
  return `
252
252
  {
@@ -261,7 +261,7 @@ __name(VERIFYING_PLAYER, "VERIFYING_PLAYER");
261
261
  function PLAYERS_LASTMATCH_RANKINFO(steamAccountIds) {
262
262
  return `
263
263
  {
264
- players(steamAccountIds:${JSON.stringify(steamAccountIds)}) {
264
+ players(steamAccountIds:[${steamAccountIds.join(",")}]) {
265
265
  steamAccount{
266
266
  id
267
267
  name
@@ -530,11 +530,12 @@ __name(REQUEST_MATCH_DATA_ANALYSIS, "REQUEST_MATCH_DATA_ANALYSIS");
530
530
  // src/utils.ts
531
531
  var CONFIGS = { STRATZ_API: { URL: "https://api.stratz.com/graphql", TOKEN: "" } };
532
532
  var http = null;
533
- function setHttp(newHttp) {
533
+ function init(newHttp, setTimeout2) {
534
534
  http = newHttp;
535
+ setTimeout2 = setTimeout2;
535
536
  }
536
- __name(setHttp, "setHttp");
537
- async function query(query_str) {
537
+ __name(init, "init");
538
+ async function fetchData(query_str) {
538
539
  return await http.post(CONFIGS.STRATZ_API.URL, query_str, {
539
540
  responseType: "json",
540
541
  headers: {
@@ -544,6 +545,27 @@ async function query(query_str) {
544
545
  }
545
546
  });
546
547
  }
548
+ __name(fetchData, "fetchData");
549
+ async function query(query_func, ...args) {
550
+ if (query_func.name.startsWith("PLAYERS") && args[0].length > 5) {
551
+ const playerIds = args[0];
552
+ const chunkSize = 5;
553
+ let allPlayers = [];
554
+ for (let i = 0; i < playerIds.length; i += chunkSize) {
555
+ const chunk = playerIds.slice(i, i + chunkSize);
556
+ const query_str = query_func(chunk, ...args.slice(1));
557
+ const result = await new Promise((resolve) => setTimeout(() => resolve(fetchData(query_str)), 100));
558
+ if (result.data && result.data.players) {
559
+ allPlayers = allPlayers.concat(result.data.players);
560
+ }
561
+ }
562
+ return { data: { players: allPlayers } };
563
+ } else {
564
+ const query_str = query_func(...args);
565
+ const result = await fetchData(query_str);
566
+ return result || {};
567
+ }
568
+ }
547
569
  __name(query, "query");
548
570
  async function queryHeroFromValve(heroId) {
549
571
  return (await http.get(`https://www.dota2.com/datafeed/herodata?language=schinese&hero_id=${heroId}`)).result.data.heroes[0];
@@ -1252,7 +1274,7 @@ var Config = import_koishi.Schema.intersect([
1252
1274
  import_koishi.Schema.object({
1253
1275
  rankBroadSwitch: import_koishi.Schema.const(true).required(),
1254
1276
  rankBroadStar: import_koishi.Schema.boolean().default(true).description("星级变动播报"),
1255
- rankBroadLeader: import_koishi.Schema.boolean().default(true).description("名词变动播报"),
1277
+ rankBroadLeader: import_koishi.Schema.boolean().default(true).description("冠绝名次变动播报"),
1256
1278
  rankBroadFun: import_koishi.Schema.boolean().default(false).description("整活播报模板")
1257
1279
  }),
1258
1280
  import_koishi.Schema.object({})
@@ -1292,7 +1314,7 @@ var pendingMatches = [];
1292
1314
  var random = new import_koishi2.Random(() => Math.random());
1293
1315
  async function apply(ctx, config) {
1294
1316
  CONFIGS.STRATZ_API.TOKEN = config.STRATZ_API_TOKEN;
1295
- setHttp(ctx.http);
1317
+ init(ctx.http, ctx.setTimeout);
1296
1318
  ctx.command("订阅本群", "订阅后还需玩家在本群绑定SteamID").usage("订阅后还需玩家在本群绑定SteamID,BOT将订阅本群中已绑定玩家的新比赛数据,在STRATZ比赛解析完成后将比赛数据生成为图片战报发布至本群中。").action(async ({ session }) => {
1297
1319
  if (session.guild) {
1298
1320
  let currentGuild = (await ctx.database.get("dt_subscribed_guilds", { guildId: session.event.channel.id, platform: session.event.platform }))[0];
@@ -1388,15 +1410,19 @@ async function apply(ctx, config) {
1388
1410
  }
1389
1411
  if (subscribedPlayers.length <= 20) {
1390
1412
  try {
1391
- const memberList = await session.bot.getGuildMemberList(session.event.channel.id);
1413
+ let memberList;
1414
+ try {
1415
+ memberList = await session.bot?.getGuildMemberList(session.event.channel.id);
1416
+ } catch (error) {
1417
+ }
1392
1418
  async function getUsers(subscribedPlayers2, utils, queries, memberList2) {
1393
1419
  const playerSteamIds = subscribedPlayers2.map((player) => player.steamId);
1394
- const queryResult = await utils.query(queries.PLAYERS_INFO_WITH_10_MATCHES_FOR_GUILD(playerSteamIds));
1420
+ const queryResult = await utils.query(queries.PLAYERS_INFO_WITH_10_MATCHES_FOR_GUILD, playerSteamIds);
1395
1421
  const playersInfo = queryResult.data.players;
1396
1422
  const users2 = [];
1397
1423
  for (const subscribedPlayer of subscribedPlayers2) {
1398
1424
  const queryPlayer = playersInfo.find((player) => player.steamAccount.id == subscribedPlayer.steamId);
1399
- const queryMember = memberList2.data.find((member) => member.user?.id == subscribedPlayer.userId);
1425
+ const queryMember = memberList2?.data.find((member) => member.user?.id == subscribedPlayer.userId);
1400
1426
  users2.push({ ...subscribedPlayer, ...queryPlayer, ...queryMember });
1401
1427
  }
1402
1428
  return users2;
@@ -1419,7 +1445,7 @@ async function apply(ctx, config) {
1419
1445
  match = queryLocal[0].data;
1420
1446
  ctx.database.set("dt_previous_query_results", match.id, { queryTime: /* @__PURE__ */ new Date() });
1421
1447
  } else {
1422
- match = getFormattedMatchData((await query(MATCH_INFO(matchId))).data);
1448
+ match = getFormattedMatchData((await query(MATCH_INFO, matchId)).data);
1423
1449
  }
1424
1450
  if (match && (match.parsedDateTime || import_moment.default.unix(match.endDateTime).isBefore((0, import_moment.default)().subtract(config.dataParsingTimeoutMinutes, "minutes")))) {
1425
1451
  session.send((ctx.config.urlInMessageType.some((type) => type == "match") ? "https://stratz.com/matches/" + matchId : "") + await ctx.puppeteer.render(genImageHTML(match, config.template_match, "match" /* Match */)));
@@ -1441,7 +1467,6 @@ async function apply(ctx, config) {
1441
1467
  session.send("请输入比赛ID。");
1442
1468
  return;
1443
1469
  }
1444
- JSON.stringify;
1445
1470
  if (!/^\d{10}$/.test(match_id)) {
1446
1471
  session.send("比赛ID无效。");
1447
1472
  return;
@@ -1467,9 +1492,10 @@ async function apply(ctx, config) {
1467
1492
  let lastMatchId = 0;
1468
1493
  try {
1469
1494
  session.send("正在搜索对局详情,请稍后...");
1470
- lastMatchId = (await query(PLAYERS_LASTMATCH_RANKINFO(parseInt(flagBindedPlayer?.steamId ?? input_data)))).data.player.matches[0].id;
1471
- } catch {
1495
+ lastMatchId = (await query(PLAYERS_LASTMATCH_RANKINFO, [parseInt(flagBindedPlayer?.steamId ?? input_data)])).data.players[0].matches[0].id;
1496
+ } catch (error) {
1472
1497
  session.send("获取玩家最近比赛失败。");
1498
+ ctx.logger.error(error);
1473
1499
  return;
1474
1500
  }
1475
1501
  queryMatchAndSend(session, lastMatchId);
@@ -1497,8 +1523,8 @@ async function apply(ctx, config) {
1497
1523
  let steamId = flagBindedPlayer?.steamId ?? input_data;
1498
1524
  let player;
1499
1525
  try {
1500
- player = (await query(PLAYER_INFO_WITH_25_MATCHES(steamId, hero?.id))).data.player;
1501
- let playerExtra = (await query(PLAYER_EXTRA_INFO(steamId, player.matchCount, Object.keys(dotaconstants3.heroes).length, hero?.id))).data.player;
1526
+ player = (await query(PLAYER_INFO_WITH_25_MATCHES, steamId, hero?.id)).data.player;
1527
+ let playerExtra = (await query(PLAYER_EXTRA_INFO, steamId, player.matchCount, Object.keys(dotaconstants3.heroes).length, hero?.id)).data.player;
1502
1528
  let filteredDotaPlus = {};
1503
1529
  playerExtra.dotaPlus.forEach((item) => {
1504
1530
  if (!filteredDotaPlus[item.heroId] || filteredDotaPlus[item.heroId].level < item.level) {
@@ -1646,7 +1672,7 @@ async function apply(ctx, config) {
1646
1672
  return;
1647
1673
  }
1648
1674
  try {
1649
- let heroStats = (await query(HERO_MATCHUP_WINRATE(hero.id))).data.heroStats;
1675
+ let heroStats = (await query(HERO_MATCHUP_WINRATE, hero.id)).data.heroStats;
1650
1676
  let withTopFive = heroStats.matchUp[0].with.filter((item) => item.matchCount / heroStats.matchUp[0].matchCountWith > Math.max(0, Math.min(5, options.filter)) / 100).map((item) => {
1651
1677
  const winRate = item.winCount / item.matchCount;
1652
1678
  return { ...item, winRate: winRate.toFixed(3) };
@@ -1720,7 +1746,7 @@ async function apply(ctx, config) {
1720
1746
  const subscribedPlayersSteamIds = subscribedPlayersInGuild.map((player) => player.steamId).filter(function(value, index, self) {
1721
1747
  return self.indexOf(value) === index;
1722
1748
  });
1723
- const players = (await query(PLAYERS_LASTMATCH_RANKINFO(subscribedPlayersSteamIds))).data.players;
1749
+ const players = (await query(PLAYERS_LASTMATCH_RANKINFO, subscribedPlayersSteamIds)).data.players;
1724
1750
  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));
1725
1751
  const sendedMatchesIds = (await ctx.database.get("dt_sended_match_id", { matchId: lastMatches.map((match) => match.id) }, ["matchId"])).map((match) => match.matchId);
1726
1752
  lastMatches.filter((match) => !sendedMatchesIds.includes(match.id)).forEach((match) => {
@@ -1735,7 +1761,7 @@ async function apply(ctx, config) {
1735
1761
  });
1736
1762
  });
1737
1763
  pendingMatches.push({ matchId: match.id, guilds: tempGuilds });
1738
- query(REQUEST_MATCH_DATA_ANALYSIS(match.id));
1764
+ query(REQUEST_MATCH_DATA_ANALYSIS, match.id);
1739
1765
  ctx.logger.info(
1740
1766
  tempGuilds.map((guild) => `追踪到来自群组${guild.platform}:${guild.guildId}的用户${guild.players.map((player) => `[${player.nickName ?? ""}(${player.steamId})]`).join("、")}的尚未播报过的最新比赛 ${match.id}。`).join("")
1741
1767
  );
@@ -1763,7 +1789,6 @@ async function apply(ctx, config) {
1763
1789
  if (prevRank.medal !== currRank.medal || prevRank.star !== currRank.star && config.rankBroadStar || prevRank.leader !== currRank.leader && config.rankBroadLeader) {
1764
1790
  const guildMember = await ctx.bots.find((bot) => bot.platform == subPlayer.platform)?.getGuildMember?.(subPlayer.guildId, subPlayer.userId);
1765
1791
  const name2 = subPlayer.nickName ?? guildMember?.nick ?? players.find((player) => player.steamAccount.id == subPlayer.steamId)?.steamAccount.name ?? subPlayer.steamId;
1766
- const message = `群友 ${name2} 段位变动:${rank[prevRank.medal]}${prevRank.star} → ${rank[currRank.medal]}${currRank.star} `;
1767
1792
  if (config.rankBroadFun === true) {
1768
1793
  const img = await ctx.puppeteer.render(
1769
1794
  genImageHTML(
@@ -1780,10 +1805,11 @@ async function apply(ctx, config) {
1780
1805
  );
1781
1806
  await ctx.broadcast([`${subPlayer.platform}:${subPlayer.guildId}`], img);
1782
1807
  } else {
1808
+ const message = `群友 ${name2} 段位变动:${rank[prevRank.medal]}${prevRank.star} → ${rank[currRank.medal]}${currRank.star} `;
1783
1809
  const img = await ctx.puppeteer.render(genImageHTML(currRank, "rank" + (config.rankBroadFun ? "2" : ""), "rank" /* Rank */));
1784
1810
  await ctx.broadcast([`${subPlayer.platform}:${subPlayer.guildId}`], message + img);
1785
1811
  }
1786
- ctx.logger.info(`向${subPlayer.platform}:${subPlayer.guildId}发布段位变动播报信息。`);
1812
+ ctx.logger.info(`向 ${subPlayer.platform}:${subPlayer.guildId} 发布段位变动播报信息。`);
1787
1813
  }
1788
1814
  }
1789
1815
  }
@@ -1800,7 +1826,7 @@ async function apply(ctx, config) {
1800
1826
  if (queryLocal.length > 0) {
1801
1827
  match = queryLocal[0].data;
1802
1828
  ctx.database.set("dt_previous_query_results", match.id, { queryTime: /* @__PURE__ */ new Date() });
1803
- } else match = getFormattedMatchData((await query(MATCH_INFO(pendingMatch.matchId))).data);
1829
+ } else match = getFormattedMatchData((await query(MATCH_INFO, pendingMatch.matchId)).data);
1804
1830
  if (match.parsedDateTime || import_moment.default.unix(match.endDateTime).isBefore(now.subtract(config.dataParsingTimeoutMinutes, "minutes"))) {
1805
1831
  pendingMatches = pendingMatches.filter((item) => item.matchId != match.id);
1806
1832
  const img = await ctx.puppeteer.render(genImageHTML(match, config.template_match, "match" /* Match */));
@@ -1842,10 +1868,9 @@ KDA:${((player.kills + player.assists) / (player.deaths || 1)).toFixed(2)} [${
1842
1868
  const subscribedGuilds = await ctx.database.get("dt_subscribed_guilds", void 0);
1843
1869
  const subscribedPlayersInGuild = (await ctx.database.get("dt_subscribed_players", void 0)).filter((player) => subscribedGuilds.some((guild) => guild.guildId == player.guildId));
1844
1870
  const players = (await query(
1845
- MATCHES_FOR_DAILY(
1846
- subscribedPlayersInGuild.map((player) => player.steamId).filter((value, index, self) => self.indexOf(value) === index),
1847
- timeAgo
1848
- )
1871
+ PLAYERS_MATCHES_FOR_DAILY,
1872
+ subscribedPlayersInGuild.map((player) => player.steamId).filter((value, index, self) => self.indexOf(value) === index),
1873
+ timeAgo
1849
1874
  )).data.players.filter((player) => player.matches.length > 0);
1850
1875
  const matches = players.map((player) => player.matches.map((match) => match)).flat().filter((item, index, self) => index === self.findIndex((t) => t.id === item.id));
1851
1876
  for (let subPlayer of subscribedPlayersInGuild) {
@@ -1936,6 +1961,7 @@ function genImageHTML(data, template, type) {
1936
1961
  dotaconstants: dotaconstants3,
1937
1962
  moment: import_moment.default,
1938
1963
  escapeHTML: /* @__PURE__ */ __name(function escapeHTML(str) {
1964
+ if (str == null) return "";
1939
1965
  return str.replace(/[&<>"']/g, function(match) {
1940
1966
  const escape = {
1941
1967
  "&": "&amp;",
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.17",
4
+ "version": "1.2.18-beta.1",
5
5
  "main": "lib/index.js",
6
6
  "typings": "lib/index.d.ts",
7
7
  "files": [
@@ -0,0 +1,27 @@
1
+ <!DOCTYPE html>
2
+ <html lang="zh">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>获取文件目录</title>
7
+ <script>
8
+ function showDirectory() {
9
+ // 获取当前页面的 URL
10
+ const url = window.location.href;
11
+ // 使用 URL 对象来解析当前 URL
12
+ const urlObj = new URL(url);
13
+ // 获取目录部分
14
+ const directory = urlObj.pathname.substring(0, urlObj.pathname.lastIndexOf('/'));
15
+ // 输出目录
16
+ document.getElementById('directory').innerText = directory;
17
+
18
+
19
+ console.log(directory)
20
+ }
21
+ </script>
22
+ </head>
23
+ <body onload="showDirectory()">
24
+ <h1>当前文件所在目录</h1>
25
+ <p id="directory"></p>
26
+ </body>
27
+ </html>
@@ -1,109 +0,0 @@
1
- <!DOCTYPE html>
2
- <html>
3
- <head>
4
- <meta charset="UTF-8" />
5
- <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
- <title>Document</title>
7
- <style>
8
- * {
9
- margin: 0;
10
- padding: 0;
11
- }
12
- html {
13
- width: 1024px;
14
- height: 768px;
15
- }
16
- body.xi {
17
- background: url(../images/xi.jpg) no-repeat center center / cover;
18
- }
19
- body.bei {
20
- background: url(../images/bei.jpg) no-repeat center center / cover;
21
- }
22
- .wrapper {
23
- padding: 80px;
24
- padding-top: 180px;
25
- }
26
- .wrapper > p {
27
- font-size: 32px;
28
- line-height: 48px;
29
- height: 48px;
30
- text-align: center;
31
- }
32
- body.xi p.bei,
33
- body.bei p.xi {
34
- display: none;
35
- }
36
- .wrapper > p > span {
37
- margin: 0 10px;
38
- }
39
- .wrapper > p > span.prev {
40
- color: gray;
41
- }
42
- .wrapper > p > span.curr {
43
- font-weight: bold;
44
- color: red;
45
- }
46
-
47
- .wrapper > p > img {
48
- width: 48px;
49
- height: 48px;
50
- vertical-align: middle;
51
- line-height: 48px;
52
- }
53
-
54
- .ranks {
55
- margin-top: 40px;
56
- display: flex;
57
- width: 100%;
58
- height: 256px;
59
- justify-content: space-evenly;
60
- }
61
-
62
- div.rank {
63
- position: relative;
64
- width: 256px;
65
- height: 256px;
66
- }
67
-
68
- div.rank > img {
69
- position: absolute;
70
- }
71
-
72
- div.rank.prev {
73
- filter: grayscale(1);
74
- }
75
- div.rank.curr {
76
- transform: scale(1.25);
77
- }
78
- div.rank p {
79
- font-size: 36px;
80
- bottom: 20px;
81
- width: 100%;
82
- text-align: center;
83
- color: #fff;
84
- position: absolute;
85
- }
86
- </style>
87
- </head>
88
- <body class="bei">
89
- <div class="wrapper">
90
- <p class="xi">热烈祝贺群友 <img src="" alt="" />12414124141 在天梯中再获进步,</p>
91
- <p class="xi">由<span class="rank prev">先锋2</span>升为<span class="rank curr">先锋2</span>,再接再厉,再创辉煌!</p>
92
- <p class="bei"><img src="" alt="" /></p>
93
- <p class="bei">寄</p>
94
- <div class="ranks">
95
- <div class="rank prev">
96
- <img src="../images/medal_8.png" alt="" />
97
- <img src="../images/star_2.png" alt="" />
98
- <p>1111</p>
99
- </div>
100
- <div class="rank curr">
101
- <img src="../images/medal_8.png" alt="" />
102
- <img src="../images/star_1.png" alt="" />
103
- <p>1111</p>
104
- </div>
105
- </div>
106
- <p style="text-align: right; margin-top: 40px;">—— 2024/11/11 00点00分</p>
107
- </div>
108
- </body>
109
- </html>