@sjtdev/koishi-plugin-dota2tracker 1.2.20-pre.1 → 1.2.20-pre.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.
package/lib/index.js CHANGED
@@ -5,6 +5,9 @@ var __getOwnPropNames = Object.getOwnPropertyNames;
5
5
  var __getProtoOf = Object.getPrototypeOf;
6
6
  var __hasOwnProp = Object.prototype.hasOwnProperty;
7
7
  var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
8
+ var __commonJS = (cb, mod) => function __require() {
9
+ return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
10
+ };
8
11
  var __export = (target, all) => {
9
12
  for (var name2 in all)
10
13
  __defProp(target, name2, { get: all[name2], enumerable: true });
@@ -27,6 +30,20 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
27
30
  ));
28
31
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
32
 
33
+ // src/locales/zh-CN.yml
34
+ var require_zh_CN = __commonJS({
35
+ "src/locales/zh-CN.yml"(exports2, module2) {
36
+ module2.exports = { dota2tracker: { position: { "1": "优势路", "2": "中路", "3": "烈士路", "4": "采灵芝", "5": "工具人" }, heroes: { "0": '请严格遵循 "", "" 格式填写(如下方默认数据,注意是英文半角符号),如果格式有误将仅使用英雄默认名称。可以不包含英雄默认名称。', "1": '"敌法师", "敌法", "AM"', "2": '"斧王"', "3": '"祸乱之源", "祸乱", "水桶腰"', "4": '"血魔"', "5": '"水晶室女", "冰女", "CM"', "6": '"卓尔游侠", "小黑"', "7": '"撼地者", "小牛", "牛头"', "8": '"主宰", "剑圣", "jugg", "奶棒人"', "9": '"米拉娜", "白虎", "pom"', "10": '"变体精灵", "水人"', "11": '"影魔", "影魔王", "SF", "影儿魔儿"', "12": '"幻影长矛手", "PL"', "13": '"帕克"', "14": '"帕吉", "屠夫", "扒鸡", "啪唧"', "15": '"雷泽", "电魂", "电棍"', "16": '"沙王", "SK"', "17": '"风暴之灵", "蓝猫"', "18": '"斯温", "流浪剑客", "流浪"', "19": '"小小"', "20": '"复仇之魂", "复仇", "VS"', "21": '"风行者", "风行", "WR"', "22": '"宙斯"', "23": '"昆卡", "船长"', "25": '"莉娜", "火女"', "26": '"莱恩", "恶魔巫师", "Lion"', "27": '"暗影萨满", "小Y", "小歪"', "28": '"斯拉达", "大鱼", "大鱼人"', "29": '"潮汐猎人", "潮汐", "西瓜皮"', "30": '"巫医"', "31": '"巫妖"', "32": '"力丸", "隐形刺客", "隐刺"', "33": '"谜团"', "34": '"修补匠", "TK", "Tinker"', "35": '"狙击手", "矮人火枪手", "火枪", "传说哥"', "36": '"瘟疫法师", "死灵法", "NEC"', "37": '"术士", "Warlock"', "38": '"兽王"', "39": '"痛苦女王", "女王", "QOP"', "40": '"剧毒术士", "剧毒"', "41": '"虚空假面", "虚空", "JB脸"', "42": '"冥魂大帝", "骷髅王"', "43": '"死亡先知", "DP"', "44": '"幻影刺客", "幻刺", "PA"', "45": '"帕格纳", "骨法", "湮灭法师"', "46": '"圣堂刺客", "圣堂", "TA"', "47": '"冥界亚龙", "毒龙", "Viper"', "48": '"露娜", "月骑", "Luna"', "49": '"龙骑士", "龙骑"', "50": '"戴泽", "暗影牧师", "暗牧"', "51": '"发条技师", "发条"', "52": '"拉席克", "老鹿"', "53": '"先知"', "54": '"噬魂鬼", "小狗"', "55": '"黑暗贤者", "黑贤"', "56": '"克林克兹", "小骷髅"', "57": '"全能骑士", "全能"', "58": '"魅惑魔女", "小鹿"', "59": '"哈斯卡", "神灵", "神灵武士"', "60": '"暗夜魔王", "夜魔"', "61": '"育母蜘蛛", "蜘蛛"', "62": '"赏金猎人", "赏金"', "63": '"编织者", "蚂蚁"', "64": '"杰奇洛", "双头龙"', "65": '"蝙蝠骑士", "蝙蝠"', "66": '"陈", "老陈"', "67": '"幽鬼", "SPE", "UG"', "68": '"远古冰魄", "冰魂"', "69": '"末日使者", "末日", "Doom"', "70": '"熊战士", "拍拍", "拍拍熊"', "71": '"裂魂人", "白牛", "sb"', "72": '"矮人直升机", "飞机"', "73": '"炼金术士", "炼金"', "74": '"祈求者", "卡尔"', "75": '"沉默术士", "沉默"', "76": '"殁境神蚀者", "黑鸟"', "77": '"狼人"', "78": '"酒仙", "熊猫", "熊猫酒仙"', "79": '"暗影恶魔", "毒狗"', "80": '"德鲁伊", "熊德"', "81": '"混沌骑士", "混沌", "CK"', "82": '"米波"', "83": '"树精卫士", "大树", "树精"', "84": '"食人魔魔法师", "蓝胖"', "85": '"不朽尸王", "尸王"', "86": '"拉比克"', "87": '"干扰者", "萨尔"', "88": '"司夜刺客", "小强"', "89": '"娜迦海妖", "小娜迦"', "90": '"光之守卫", "光法"', "91": '"艾欧", "小精灵", "精灵", "IO"', "92": '"维萨吉", "死灵龙", "死灵飞龙"', "93": '"斯拉克", "小鱼", "小鱼人"', "94": '"美杜莎", "一姐", "美杜莎"', "95": '"巨魔战将", "巨魔", "巨馍蘸酱"', "96": '"半人马战行者", "人马", "半人马"', "97": '"马格纳斯", "猛犸"', "98": '"伐木机", "花母鸡"', "99": '"钢背兽", "钢背"', "100": '"巨牙海民", "海民"', "101": '"天怒法师", "天怒"', "102": '"亚巴顿"', "103": '"上古巨神", "大牛"', "104": '"军团指挥官", "军团"', "105": '"工程师", "炸弹", "炸弹人"', "106": '"灰烬之灵", "火猫"', "107": '"大地之灵", "土猫"', "108": '"孽主", "大屁股"', "109": '"恐怖利刃", "TB"', "110": '"凤凰", "烧鸡"', "111": '"神谕者", "神谕"', "112": '"寒冬飞龙", "冰龙"', "113": '"天穹守望者", "电狗"', "114": '"齐天大圣", "大圣"', "119": '"邪影芳灵", "小仙女", "花仙子"', "120": '"石鳞剑士", "滚滚"', "121": '"天涯墨客", "墨客"', "123": '"森海飞霞", "松鼠", "小松鼠", "小松许"', "126": '"虚无之灵", "紫猫"', "128": '"电炎绝手", "老奶奶"', "129": '"玛尔斯"', "131": '"百戏大王"', "135": '"破晓辰星", "大锤"', "136": '"玛西"', "137": '"獸", "畜"', "138": '"琼英碧灵", "奶绿", "绿奶奶"', "145": '"凯", "鸟人"' } } };
37
+ }
38
+ });
39
+
40
+ // src/locales/en-US.yml
41
+ var require_en_US = __commonJS({
42
+ "src/locales/en-US.yml"(exports2, module2) {
43
+ module2.exports = { dota2tracker: { position: { "1": "Safe Lane", "2": "Mid Lane", "3": "Off Lane", "4": "Soft Support", "5": "Hard Support" }, heroes: { "0": 'Please strictly follow the format of "", "" when filling out, if the format is incorrect, only the default name of the hero will be used. The default name of the hero may be omitted.', "1": '"Anti-Mage"', "2": '"Axe"', "3": '"Bane"', "4": '"Bloodseeker"', "5": '"Crystal Maiden"', "6": '"Drow Ranger"', "7": '"Earthshaker"', "8": '"Juggernaut"', "9": '"Mirana"', "10": '"Morphling"', "11": '"Shadow Fiend"', "12": '"Phantom Lancer"', "13": '"Puck"', "14": '"Pudge"', "15": '"Razor"', "16": '"Sand King"', "17": '"Storm Spirit"', "18": '"Sven"', "19": '"Tiny"', "20": '"Vengeful Spirit"', "21": '"Windranger"', "22": '"Zeus"', "23": '"Kunkka"', "25": '"Lina"', "26": '"Lion"', "27": '"Shadow Shaman"', "28": '"Slardar"', "29": '"Tidehunter"', "30": '"Witch Doctor"', "31": '"Lich"', "32": '"Riki"', "33": '"Enigma"', "34": '"Tinker"', "35": '"Sniper"', "36": '"Necrophos"', "37": '"Warlock"', "38": '"Beastmaster"', "39": '"Queen of Pain"', "40": '"Venomancer"', "41": '"Faceless Void"', "42": '"Wraith King"', "43": '"Death Prophet"', "44": '"Phantom Assassin"', "45": '"Pugna"', "46": '"Templar Assassin"', "47": '"Viper"', "48": '"Luna"', "49": '"Dragon Knight"', "50": '"Dazzle"', "51": '"Clockwerk"', "52": '"Leshrac"', "53": `"Nature's Prophet"`, "54": '"Lifestealer"', "55": '"Dark Seer"', "56": '"Clinkz"', "57": '"Omniknight"', "58": '"Enchantress"', "59": '"Huskar"', "60": '"Night Stalker"', "61": '"Broodmother"', "62": '"Bounty Hunter"', "63": '"Weaver"', "64": '"Jakiro"', "65": '"Batrider"', "66": '"Chen"', "67": '"Spectre"', "68": '"Ancient Apparition"', "69": '"Doom"', "70": '"Ursa"', "71": '"Spirit Breaker"', "72": '"Gyrocopter"', "73": '"Alchemist"', "74": '"Invoker"', "75": '"Silencer"', "76": '"Outworld Devourer"', "77": '"Lycan"', "78": '"Brewmaster"', "79": '"Shadow Demon"', "80": '"Lone Druid"', "81": '"Chaos Knight"', "82": '"Meepo"', "83": '"Treant Protector"', "84": '"Ogre Magi"', "85": '"Undying"', "86": '"Rubick"', "87": '"Disruptor"', "88": '"Nyx Assassin"', "89": '"Naga Siren"', "90": '"Keeper of the Light"', "91": '"Io"', "92": '"Visage"', "93": '"Slark"', "94": '"Medusa"', "95": '"Troll Warlord"', "96": '"Centaur Warrunner"', "97": '"Magnus"', "98": '"Timbersaw"', "99": '"Bristleback"', "100": '"Tusk"', "101": '"Skywrath Mage"', "102": '"Abaddon"', "103": '"Elder Titan"', "104": '"Legion Commander"', "105": '"Techies"', "106": '"Ember Spirit"', "107": '"Earth Spirit"', "108": '"Underlord"', "109": '"Terrorblade"', "110": '"Phoenix"', "111": '"Oracle"', "112": '"Winter Wyvern"', "113": '"Arc Warden"', "114": '"Monkey King"', "119": '"Dark Willow"', "120": '"Pangolier"', "121": '"Grimstroke"', "123": '"Hoodwink"', "126": '"Void Spirit"', "128": '"Snapfire"', "129": '"Mars"', "131": '"Ring Master"', "135": '"Dawnbreaker"', "136": '"Marci"', "137": '"Primal Beast"', "138": '"Muerta"', "145": '"Kez"' } } };
44
+ }
45
+ });
46
+
30
47
  // src/index.ts
31
48
  var src_exports = {};
32
49
  __export(src_exports, {
@@ -60,474 +77,8 @@ __export(utils_exports, {
60
77
  winRateColor: () => winRateColor
61
78
  });
62
79
  var import_fs = __toESM(require("fs"));
63
- var dotaconstants2 = __toESM(require("dotaconstants"));
64
- var import_path = __toESM(require("path"));
65
-
66
- // src/queries.ts
67
- var queries_exports = {};
68
- __export(queries_exports, {
69
- ALL_ABILITIES_CHINESE_NAME: () => ALL_ABILITIES_CHINESE_NAME,
70
- CURRENT_GAMEVERSION: () => CURRENT_GAMEVERSION,
71
- HERO_INFO: () => HERO_INFO,
72
- HERO_MATCHUP_WINRATE: () => HERO_MATCHUP_WINRATE,
73
- MATCH_INFO: () => MATCH_INFO,
74
- PLAYERS_INFO_WITH_10_MATCHES_FOR_GUILD: () => PLAYERS_INFO_WITH_10_MATCHES_FOR_GUILD,
75
- PLAYERS_LASTMATCH_RANKINFO: () => PLAYERS_LASTMATCH_RANKINFO,
76
- PLAYERS_MATCHES_FOR_DAILY: () => PLAYERS_MATCHES_FOR_DAILY,
77
- PLAYER_EXTRA_INFO: () => PLAYER_EXTRA_INFO,
78
- PLAYER_INFO_WITH_25_MATCHES: () => PLAYER_INFO_WITH_25_MATCHES,
79
- REQUEST_MATCH_DATA_ANALYSIS: () => REQUEST_MATCH_DATA_ANALYSIS,
80
- VERIFYING_PLAYER: () => VERIFYING_PLAYER
81
- });
82
80
  var dotaconstants = __toESM(require("dotaconstants"));
83
- function MATCH_INFO(matchId) {
84
- return `
85
- {
86
- match(id: ${matchId}) {
87
- id
88
- didRadiantWin
89
- lobbyType
90
- gameMode
91
- regionId
92
- parsedDateTime
93
- startDateTime
94
- endDateTime
95
- actualRank
96
- rank
97
- averageRank
98
- durationSeconds
99
- topLaneOutcome
100
- midLaneOutcome
101
- bottomLaneOutcome
102
- radiantKills
103
- direKills
104
- players {
105
- steamAccountId
106
- steamAccount {
107
- name
108
- }
109
- level
110
- hero {
111
- id
112
- name
113
- shortName
114
- facets {
115
- facetId
116
- }
117
- }
118
- variant
119
- dotaPlus {
120
- level
121
- }
122
- leaverStatus
123
- partyId
124
- position
125
- playerSlot
126
- lane
127
- imp
128
- kills
129
- deaths
130
- assists
131
- isRadiant
132
- networth
133
- steamAccount {
134
- seasonRank
135
- seasonLeaderboardRank
136
- }
137
- item0Id
138
- item1Id
139
- item2Id
140
- item3Id
141
- item4Id
142
- item5Id
143
- backpack0Id
144
- backpack1Id
145
- backpack2Id
146
- neutral0Id
147
- stats {
148
- matchPlayerBuffEvent {
149
- abilityId
150
- itemId
151
- stackCount
152
- }
153
- }
154
- heroDamage
155
- towerDamage
156
- stats {
157
- heroDamageReport {
158
- receivedTotal {
159
- physicalDamage
160
- magicalDamage
161
- pureDamage
162
- }
163
- }
164
- }
165
- numLastHits
166
- numDenies
167
- goldPerMinute
168
- experiencePerMinute
169
- heroHealing
170
- stats {
171
- itemPurchases{
172
- itemId
173
- time
174
- }
175
- campStack
176
- heroDamageReport {
177
- dealtTotal {
178
- stunDuration
179
- stunCount
180
- slowDuration
181
- slowCount
182
- disableDuration
183
- disableCount
184
- }
185
- }
186
- }
187
- additionalUnit {
188
- item0Id
189
- item1Id
190
- item2Id
191
- item3Id
192
- item4Id
193
- item5Id
194
- backpack0Id
195
- backpack1Id
196
- backpack2Id
197
- neutral0Id
198
- }
199
- isRandom
200
- }
201
- pickBans {
202
- isPick
203
- bannedHeroId
204
- heroId
205
- order
206
- }
207
- }
208
- constants {
209
- facets (language: S_CHINESE) {
210
- name
211
- id
212
- color
213
- icon
214
- language {
215
- displayName
216
- }
217
- }
218
- }
219
- }
220
-
221
- `;
222
- }
223
- __name(MATCH_INFO, "MATCH_INFO");
224
- function PLAYERS_MATCHES_FOR_DAILY(steamAccountIds, seconds) {
225
- return `
226
- {
227
- players(steamAccountIds:[${steamAccountIds.join(",")}]) {
228
- steamAccount{id name avatar}
229
- matches(request:{startDateTime:${seconds} take:50}){
230
- id
231
- didRadiantWin
232
- parsedDateTime
233
- startDateTime
234
- players {
235
- kills
236
- deaths
237
- assists
238
- imp
239
- isRadiant
240
- steamAccount {
241
- id
242
- }
243
- }
244
- }
245
- }
246
- }
247
- `;
248
- }
249
- __name(PLAYERS_MATCHES_FOR_DAILY, "PLAYERS_MATCHES_FOR_DAILY");
250
- function VERIFYING_PLAYER(steamAccountId) {
251
- return `
252
- {
253
- player(steamAccountId: ${steamAccountId}) {
254
- matchCount
255
- }
256
- }
257
-
258
- `;
259
- }
260
- __name(VERIFYING_PLAYER, "VERIFYING_PLAYER");
261
- function PLAYERS_LASTMATCH_RANKINFO(steamAccountIds) {
262
- return `
263
- {
264
- players(steamAccountIds:[${steamAccountIds.join(",")}]) {
265
- steamAccount{
266
- id
267
- name
268
- avatar
269
- seasonRank
270
- seasonLeaderboardRank
271
- }
272
- matches(request:{take:1}){
273
- id
274
- parsedDateTime
275
- startDateTime
276
- players{
277
- steamAccount{
278
- id
279
- }
280
- }
281
- }
282
- }
283
- }
284
-
285
- `;
286
- }
287
- __name(PLAYERS_LASTMATCH_RANKINFO, "PLAYERS_LASTMATCH_RANKINFO");
288
- function PLAYER_INFO_WITH_25_MATCHES(steamAccountId, heroId) {
289
- return `
290
- {
291
- player(steamAccountId: ${steamAccountId}) {
292
- steamAccount {
293
- avatar
294
- name
295
- seasonRank
296
- seasonLeaderboardRank
297
- id
298
- }
299
- guildMember {
300
- guild {
301
- tag
302
- }
303
- }
304
- matchCount
305
- winCount
306
- performance {
307
- imp
308
- }
309
- heroesPerformance(take: 25, request: {matchGroupOrderBy: WIN_COUNT take: 25 ${heroId ? "heroIds:" + heroId : ""}}) {
310
- hero {
311
- id
312
- shortName
313
- }
314
- imp
315
- winCount
316
- matchCount
317
- }
318
- matches(request: {take: 25 ${heroId ? "heroIds:" + heroId : ""}}) {
319
- id
320
- rank
321
- lobbyType
322
- gameMode
323
- startDateTime
324
- parsedDateTime
325
- durationSeconds
326
- didRadiantWin
327
- topLaneOutcome
328
- midLaneOutcome
329
- bottomLaneOutcome
330
- radiantKills
331
- direKills
332
- players {
333
- steamAccount {
334
- id
335
- }
336
- isRadiant
337
- lane
338
- kills
339
- deaths
340
- assists
341
- position
342
- award
343
- imp
344
- hero {
345
- id
346
- shortName
347
- }
348
- }
349
- }
350
- }
351
-
352
- }
353
-
354
- `;
355
- }
356
- __name(PLAYER_INFO_WITH_25_MATCHES, "PLAYER_INFO_WITH_25_MATCHES");
357
- function PLAYER_EXTRA_INFO(steamAccountId, matchCount, totalHeroCount, heroId) {
358
- return `{
359
- player(steamAccountId: ${steamAccountId}) {
360
- heroesPerformance(take: ${totalHeroCount}, request: {matchGroupOrderBy: MATCH_COUNT, take: ${matchCount} ${heroId ? "heroIds:" + heroId : ""}}) {
361
- hero {
362
- id
363
- shortName
364
- }
365
- winCount
366
- matchCount
367
- imp
368
- }
369
- dotaPlus {
370
- heroId
371
- level
372
- }
373
- }
374
- }
375
- `;
376
- }
377
- __name(PLAYER_EXTRA_INFO, "PLAYER_EXTRA_INFO");
378
- function PLAYERS_INFO_WITH_10_MATCHES_FOR_GUILD(steamAccountIds) {
379
- return `{
380
- players(steamAccountIds: [${steamAccountIds.join()}]) {
381
- steamAccount {
382
- id
383
- avatar
384
- name
385
- seasonRank
386
- }
387
- matches(request: {take: 10}) {
388
- didRadiantWin
389
- startDateTime
390
- players {
391
- isRadiant
392
- kills
393
- deaths
394
- assists
395
- steamAccount {
396
- id
397
- }
398
- hero {
399
- shortName
400
- }
401
- imp
402
- }
403
- }
404
- }
405
- }
406
- `;
407
- }
408
- __name(PLAYERS_INFO_WITH_10_MATCHES_FOR_GUILD, "PLAYERS_INFO_WITH_10_MATCHES_FOR_GUILD");
409
- function CURRENT_GAMEVERSION() {
410
- return `
411
- {
412
- constants {
413
- gameVersions{name id}
414
- }
415
- }
416
-
417
- `;
418
- }
419
- __name(CURRENT_GAMEVERSION, "CURRENT_GAMEVERSION");
420
- function ALL_ABILITIES_CHINESE_NAME() {
421
- return `
422
- {
423
- constants {
424
- abilities(language:S_CHINESE){
425
- id
426
- language{displayName}
427
- }
428
- gameVersions{name id}
429
- }
430
- }
431
-
432
- `;
433
- }
434
- __name(ALL_ABILITIES_CHINESE_NAME, "ALL_ABILITIES_CHINESE_NAME");
435
- function HERO_INFO(heroId) {
436
- return `
437
- {
438
- constants {
439
- hero(id: ${heroId}, language: S_CHINESE) {
440
- id
441
- name
442
- shortName
443
- aliases
444
- roles {
445
- roleId
446
- level
447
- }
448
- language {
449
- displayName
450
- lore
451
- hype
452
- }
453
- abilities {
454
- ability(language: S_CHINESE) {
455
- name
456
- language {
457
- displayName
458
- description
459
- attributes
460
- lore
461
- aghanimDescription
462
- shardDescription
463
- notes
464
- }
465
- stat {
466
- type
467
- behavior
468
- unitTargetType
469
- unitTargetTeam
470
- unitTargetFlags
471
- unitDamageType
472
- cooldown
473
- manaCost
474
- spellImmunity
475
- isOnCastbar
476
- isGrantedByShard
477
- isGrantedByScepter
478
- hasShardUpgrade
479
- hasScepterUpgrade
480
- }
481
- }
482
- }
483
- talents {
484
- abilityId
485
- slot
486
- }
487
- }
488
- }
489
- }
490
-
491
- `;
492
- }
493
- __name(HERO_INFO, "HERO_INFO");
494
- function HERO_MATCHUP_WINRATE(heroId) {
495
- return `
496
- {
497
- heroStats {
498
- matchUp(heroId: ${heroId}, take: ${Object.keys(dotaconstants.heroes).length - 1},bracketBasicIds:LEGEND_ANCIENT) {
499
- heroId
500
- matchCountWith
501
- matchCountVs
502
- with {
503
- heroId1
504
- winRateHeroId1
505
- heroId2
506
- winRateHeroId2
507
- winCount
508
- matchCount
509
- }
510
- vs {
511
- heroId1
512
- winRateHeroId1
513
- heroId2
514
- winRateHeroId2
515
- winCount
516
- matchCount
517
- }
518
- }
519
- }
520
- }
521
-
522
- `;
523
- }
524
- __name(HERO_MATCHUP_WINRATE, "HERO_MATCHUP_WINRATE");
525
- function REQUEST_MATCH_DATA_ANALYSIS(matchId) {
526
- return `{stratz{matchRetry(id:${matchId})}}`;
527
- }
528
- __name(REQUEST_MATCH_DATA_ANALYSIS, "REQUEST_MATCH_DATA_ANALYSIS");
529
-
530
- // src/utils.ts
81
+ var import_path = __toESM(require("path"));
531
82
  var CONFIGS = { STRATZ_API: { URL: "https://api.stratz.com/graphql", TOKEN: "" } };
532
83
  var http = null;
533
84
  var setTimeout;
@@ -536,42 +87,53 @@ function init(newHttp, newSetTimeout) {
536
87
  setTimeout = newSetTimeout;
537
88
  }
538
89
  __name(init, "init");
539
- async function fetchData(query_str) {
540
- return await http.post(CONFIGS.STRATZ_API.URL, query_str, {
90
+ async function fetchData(query2) {
91
+ return await http.post(CONFIGS.STRATZ_API.URL, JSON.stringify(query2), {
541
92
  responseType: "json",
542
93
  headers: {
543
94
  "User-Agent": "STRATZ_API",
544
- "Content-Type": "application/graphql",
95
+ "Content-Type": "application/json",
545
96
  Authorization: `Bearer ${CONFIGS.STRATZ_API.TOKEN}`
546
97
  }
547
98
  });
548
99
  }
549
100
  __name(fetchData, "fetchData");
550
- async function query(query_func, ...args) {
551
- if (query_func.name.startsWith("PLAYERS") && args[0].length > 5) {
552
- const playerIds = args[0];
101
+ async function query(queryName, variables) {
102
+ if (queryName.startsWith("Players") && variables?.steamAccountIds.length > 5) {
103
+ const playerIds = variables?.steamAccountIds ?? [];
553
104
  const chunkSize = 5;
554
105
  let allPlayers = [];
555
106
  for (let i = 0; i < playerIds.length; i += chunkSize) {
556
107
  const chunk = playerIds.slice(i, i + chunkSize);
557
- const query_str = query_func(chunk, ...args.slice(1));
558
- const result = await new Promise((resolve) => setTimeout(async () => resolve(await fetchData(query_str)), 100));
559
- if (result.errors) throw { errors: result.errors };
108
+ variables.steamAccountIds = chunk;
109
+ const query_str = loadGraphqlFile(queryName);
110
+ const result = await new Promise((resolve) => setTimeout(async () => resolve(await fetchData({ query: query_str, variables })), 200));
111
+ if (result?.errors) throw { errors: result.errors };
560
112
  if (result.data && result.data.players) {
561
113
  allPlayers = allPlayers.concat(result.data.players);
562
114
  }
563
115
  }
564
- return { data: { players: allPlayers } };
116
+ return { players: allPlayers };
565
117
  } else {
566
- const query_str = query_func(...args);
567
- const result = await fetchData(query_str);
118
+ const query_str = loadGraphqlFile(queryName);
119
+ const result = await fetchData({ query: query_str, variables });
568
120
  if (result.errors) throw { errors: result.errors };
569
- return result || {};
121
+ return result.data;
570
122
  }
571
123
  }
572
124
  __name(query, "query");
573
- async function queryHeroFromValve(heroId) {
574
- return (await http.get(`https://www.dota2.com/datafeed/herodata?language=schinese&hero_id=${heroId}`)).result.data.heroes[0];
125
+ function loadGraphqlFile(queryName) {
126
+ const filepath = `./node_modules/@sjtdev/koishi-plugin-dota2tracker/queries/${queryName}.graphql`;
127
+ return import_fs.default.readFileSync(filepath, { encoding: "utf-8" }).replace(/[\r\n]+/g, " ");
128
+ }
129
+ __name(loadGraphqlFile, "loadGraphqlFile");
130
+ async function queryHeroFromValve(heroId, languageTag = "zh-CN") {
131
+ let language;
132
+ ((language2) => {
133
+ language2["zh-CN"] = "schinese";
134
+ language2["en-US"] = "english";
135
+ })(language || (language = {}));
136
+ return (await http.get(`https://www.dota2.com/datafeed/herodata?language=${language[languageTag]}&hero_id=${heroId}`)).result.data.heroes[0];
575
137
  }
576
138
  __name(queryHeroFromValve, "queryHeroFromValve");
577
139
  var HeroDescType = /* @__PURE__ */ ((HeroDescType2) => {
@@ -611,7 +173,8 @@ function getImageUrl(image, type = "local" /* Local */, format = "png" /* png */
611
173
  }
612
174
  __name(getImageUrl, "getImageUrl");
613
175
  function getFormattedMatchData(data) {
614
- const { match, constants } = data;
176
+ const match = data.match;
177
+ const constants = data.constants;
615
178
  ["radiant", "dire"].forEach((team) => {
616
179
  match[team] = { killsCount: match[team + "Kills"]?.reduce((acc, cva) => acc + cva, 0) ?? 0, damageReceived: 0, heroDamage: 0, networth: 0, experience: 0 };
617
180
  });
@@ -680,7 +243,10 @@ function getFormattedMatchData(data) {
680
243
  }
681
244
  return acc;
682
245
  }, {});
683
- player.stats.matchPlayerBuffEvent.splice(0, player.stats.matchPlayerBuffEvent.length, ...Object.values(maxStackCountsByAbilityOrItem));
246
+ player.buffs = Object.entries(maxStackCountsByAbilityOrItem).map(([key, event]) => ({
247
+ key,
248
+ event
249
+ }));
684
250
  }
685
251
  switch (player.lane) {
686
252
  case "SAFE_LANE":
@@ -741,8 +307,8 @@ function getFormattedMatchData(data) {
741
307
  const itemId = player[key];
742
308
  if (itemId === void 0 || itemId === null) {
743
309
  player.items.push(null);
744
- } else if (dotaconstants2.item_ids[itemId]) {
745
- const name2 = dotaconstants2.item_ids[itemId];
310
+ } else if (dotaconstants.item_ids[itemId]) {
311
+ const name2 = dotaconstants.item_ids[itemId];
746
312
  const isRecipe = name2.startsWith(prefix);
747
313
  const cleanName = isRecipe ? name2.substring(prefix.length) : name2;
748
314
  player.items.push({
@@ -760,8 +326,8 @@ function getFormattedMatchData(data) {
760
326
  const itemId = player[key];
761
327
  if (itemId === void 0 || itemId === null) {
762
328
  player.backpacks.push(null);
763
- } else if (dotaconstants2.item_ids[itemId]) {
764
- const name2 = dotaconstants2.item_ids[itemId];
329
+ } else if (dotaconstants.item_ids[itemId]) {
330
+ const name2 = dotaconstants.item_ids[itemId];
765
331
  const isRecipe = name2.startsWith(prefix);
766
332
  const cleanName = isRecipe ? name2.substring(prefix.length) : name2;
767
333
  player.backpacks.push({
@@ -783,8 +349,8 @@ function getFormattedMatchData(data) {
783
349
  const itemId = player.additionalUnit[key];
784
350
  if (itemId === void 0 || itemId === null) {
785
351
  player.unitItems.push(null);
786
- } else if (dotaconstants2.item_ids[itemId]) {
787
- const name2 = dotaconstants2.item_ids[itemId];
352
+ } else if (dotaconstants.item_ids[itemId]) {
353
+ const name2 = dotaconstants.item_ids[itemId];
788
354
  const isRecipe = name2.startsWith(prefix2);
789
355
  const cleanName = isRecipe ? name2.substring(prefix2.length) : name2;
790
356
  player.unitItems.push({
@@ -802,8 +368,8 @@ function getFormattedMatchData(data) {
802
368
  const itemId = player.additionalUnit[key];
803
369
  if (itemId === void 0 || itemId === null) {
804
370
  player.unitBackpacks.push(null);
805
- } else if (dotaconstants2.item_ids[itemId]) {
806
- const name2 = dotaconstants2.item_ids[itemId];
371
+ } else if (dotaconstants.item_ids[itemId]) {
372
+ const name2 = dotaconstants.item_ids[itemId];
807
373
  const isRecipe = name2.startsWith(prefix2);
808
374
  const cleanName = isRecipe ? name2.substring(prefix2.length) : name2;
809
375
  player.unitBackpacks.push({
@@ -926,7 +492,7 @@ function winRateColor(value) {
926
492
  __name(winRateColor, "winRateColor");
927
493
  async function playerisValid(steamAccountId) {
928
494
  try {
929
- let queryRes = await query(VERIFYING_PLAYER, steamAccountId);
495
+ let queryRes = await query("VerifyingPlayer", { steamAccountId });
930
496
  if (queryRes.data.player.matchCount != null) return { isValid: true };
931
497
  else return { isValid: false, reason: "SteamID无效或无任何场次。" };
932
498
  } catch (error) {
@@ -979,12 +545,12 @@ __name(formatHeroDesc, "formatHeroDesc");
979
545
  var import_fs2 = __toESM(require("fs"));
980
546
  var import_path2 = __toESM(require("path"));
981
547
  var import_moment = __toESM(require("moment"));
982
- var dotaconstants3 = __toESM(require("dotaconstants"));
548
+ var dotaconstants2 = __toESM(require("dotaconstants"));
983
549
 
984
- // src/dotaconstants_add.json
550
+ // src/data/dotaconstants_add.json
985
551
  var dotaconstants_add_exports = {};
986
552
  __export(dotaconstants_add_exports, {
987
- HEROES_CHINESE: () => HEROES_CHINESE,
553
+ HEROES_NAMES: () => HEROES_NAMES,
988
554
  LOSE_NEGATIVE: () => LOSE_NEGATIVE,
989
555
  LOSE_POSITIVE: () => LOSE_POSITIVE,
990
556
  WIN_NEGATIVE: () => WIN_NEGATIVE,
@@ -1100,133 +666,263 @@ var behavior = {
1100
666
  AOE: "范围生效"
1101
667
  };
1102
668
  var target_team = { Enemy: "敌方单位", Both: "单位", Friendly: "友方单位" };
1103
- var HEROES_CHINESE = {
1104
- "1": ["敌法师", "敌法", "AM"],
1105
- "2": ["斧王"],
1106
- "3": ["祸乱之源", "祸乱", "水桶腰"],
1107
- "4": ["血魔"],
1108
- "5": ["水晶室女", "冰女", "CM"],
1109
- "6": ["卓尔游侠", "小黑"],
1110
- "7": ["撼地者", "小牛", "牛头"],
1111
- "8": ["主宰", "剑圣", "jugg", "奶棒人"],
1112
- "9": ["米拉娜", "白虎", "pom"],
1113
- "10": ["变体精灵", "水人"],
1114
- "11": ["影魔", "影魔王", "SF", "影儿魔儿"],
1115
- "12": ["幻影长矛手", "PL"],
1116
- "13": ["帕克"],
1117
- "14": ["帕吉", "屠夫", "扒鸡", "啪唧"],
1118
- "15": ["雷泽", "电魂", "电棍"],
1119
- "16": ["沙王", "SK"],
1120
- "17": ["风暴之灵", "蓝猫"],
1121
- "18": ["斯温", "流浪剑客", "流浪"],
1122
- "19": ["小小"],
1123
- "20": ["复仇之魂", "复仇", "VS"],
1124
- "21": ["风行者", "风行", "WR"],
1125
- "22": ["宙斯"],
1126
- "23": ["昆卡", "船长"],
1127
- "25": ["莉娜", "火女"],
1128
- "26": ["莱恩", "恶魔巫师", "Lion"],
1129
- "27": ["暗影萨满", "小Y", "小歪"],
1130
- "28": ["斯拉达", "大鱼", "大鱼人"],
1131
- "29": ["潮汐猎人", "潮汐", "西瓜皮"],
1132
- "30": ["巫医"],
1133
- "31": ["巫妖"],
1134
- "32": ["力丸", "隐形刺客", "隐刺"],
1135
- "33": ["谜团"],
1136
- "34": ["修补匠", "TK", "Tinker"],
1137
- "35": ["狙击手", "矮人火枪手", "火枪", "传说哥"],
1138
- "36": ["瘟疫法师", "死灵法", "NEC"],
1139
- "37": ["术士", "Warlock"],
1140
- "38": ["兽王"],
1141
- "39": ["痛苦女王", "女王", "QOP"],
1142
- "40": ["剧毒术士", "剧毒"],
1143
- "41": ["虚空假面", "虚空", "JB脸"],
1144
- "42": ["冥魂大帝", "骷髅王"],
1145
- "43": ["死亡先知", "DP"],
1146
- "44": ["幻影刺客", "幻刺", "PA"],
1147
- "45": ["帕格纳", "骨法", "湮灭法师"],
1148
- "46": ["圣堂刺客", "圣堂", "TA"],
1149
- "47": ["冥界亚龙", "毒龙", "Viper"],
1150
- "48": ["露娜", "月骑", "Luna"],
1151
- "49": ["龙骑士", "龙骑"],
1152
- "50": ["戴泽", "暗影牧师", "暗牧"],
1153
- "51": ["发条技师", "发条"],
1154
- "52": ["拉席克", "老鹿"],
1155
- "53": ["先知"],
1156
- "54": ["噬魂鬼", "小狗"],
1157
- "55": ["黑暗贤者", "黑贤"],
1158
- "56": ["克林克兹", "小骷髅"],
1159
- "57": ["全能骑士", "全能"],
1160
- "58": ["魅惑魔女", "小鹿"],
1161
- "59": ["哈斯卡", "神灵", "神灵武士"],
1162
- "60": ["暗夜魔王", "夜魔"],
1163
- "61": ["育母蜘蛛", "蜘蛛"],
1164
- "62": ["赏金猎人", "赏金"],
1165
- "63": ["编织者", "蚂蚁"],
1166
- "64": ["杰奇洛", "双头龙"],
1167
- "65": ["蝙蝠骑士", "蝙蝠"],
1168
- "66": ["", "老陈"],
1169
- "67": ["幽鬼", "SPE", "UG"],
1170
- "68": ["远古冰魄", "冰魂"],
1171
- "69": ["末日使者", "末日", "Doom"],
1172
- "70": ["熊战士", "拍拍", "拍拍熊"],
1173
- "71": ["裂魂人", "白牛", "sb"],
1174
- "72": ["矮人直升机", "飞机"],
1175
- "73": ["炼金术士", "炼金"],
1176
- "74": ["祈求者", "卡尔"],
1177
- "75": ["沉默术士", "沉默"],
1178
- "76": ["殁境神蚀者", "黑鸟"],
1179
- "77": ["狼人"],
1180
- "78": ["酒仙", "熊猫", "熊猫酒仙"],
1181
- "79": ["暗影恶魔", "毒狗"],
1182
- "80": ["德鲁伊", "熊德"],
1183
- "81": ["混沌骑士", "混沌", "CK"],
1184
- "82": ["米波"],
1185
- "83": ["树精卫士", "大树", "树精"],
1186
- "84": ["食人魔魔法师", "蓝胖"],
1187
- "85": ["不朽尸王", "尸王"],
1188
- "86": ["拉比克"],
1189
- "87": ["干扰者", "萨尔"],
1190
- "88": ["司夜刺客", "小强"],
1191
- "89": ["娜迦海妖", "小娜迦"],
1192
- "90": ["光之守卫", "光法"],
1193
- "91": ["艾欧", "小精灵", "精灵", "IO"],
1194
- "92": ["维萨吉", "死灵龙", "死灵飞龙"],
1195
- "93": ["斯拉克", "小鱼", "小鱼人"],
1196
- "94": ["美杜莎", "一姐", "美杜莎"],
1197
- "95": ["巨魔战将", "巨魔", "巨馍蘸酱"],
1198
- "96": ["半人马战行者", "人马", "半人马"],
1199
- "97": ["马格纳斯", "猛犸"],
1200
- "98": ["伐木机", "花母鸡"],
1201
- "99": ["钢背兽", "钢背"],
1202
- "100": ["巨牙海民", "海民"],
1203
- "101": ["天怒法师", "天怒"],
1204
- "102": ["亚巴顿"],
1205
- "103": ["上古巨神", "大牛"],
1206
- "104": ["军团指挥官", "军团"],
1207
- "105": ["工程师", "炸弹", "炸弹人"],
1208
- "106": ["灰烬之灵", "火猫"],
1209
- "107": ["大地之灵", "土猫"],
1210
- "108": ["孽主", "大屁股"],
1211
- "109": ["恐怖利刃", "TB"],
1212
- "110": ["凤凰", "烧鸡"],
1213
- "111": ["神谕者", "神谕"],
1214
- "112": ["寒冬飞龙", "冰龙"],
1215
- "113": ["天穹守望者", "电狗"],
1216
- "114": ["齐天大圣", "大圣"],
1217
- "119": ["邪影芳灵", "小仙女", "花仙子"],
1218
- "120": ["石鳞剑士", "滚滚"],
1219
- "121": ["天涯墨客", "墨客"],
1220
- "123": ["森海飞霞", "松鼠", "小松鼠", "小松许"],
1221
- "126": ["虚无之灵", "紫猫"],
1222
- "128": ["电炎绝手", "老奶奶"],
1223
- "129": ["玛尔斯"],
1224
- "131": ["百戏大王"],
1225
- "135": ["破晓辰星", "大锤"],
1226
- "136": ["玛西"],
1227
- "137": ["", "畜"],
1228
- "138": ["琼英碧灵", "奶绿", "绿奶奶"],
1229
- "145": [""]
669
+ var HEROES_NAMES = {
670
+ "zh-CN": {
671
+ "1": "敌法师",
672
+ "2": "斧王",
673
+ "3": "祸乱之源",
674
+ "4": "血魔",
675
+ "5": "水晶室女",
676
+ "6": "卓尔游侠",
677
+ "7": "撼地者",
678
+ "8": "主宰",
679
+ "9": "米拉娜",
680
+ "10": "变体精灵",
681
+ "11": "影魔",
682
+ "12": "幻影长矛手",
683
+ "13": "帕克",
684
+ "14": "帕吉",
685
+ "15": "雷泽",
686
+ "16": "沙王",
687
+ "17": "风暴之灵",
688
+ "18": "斯温",
689
+ "19": "小小",
690
+ "20": "复仇之魂",
691
+ "21": "风行者",
692
+ "22": "宙斯",
693
+ "23": "昆卡",
694
+ "25": "莉娜",
695
+ "26": "莱恩",
696
+ "27": "暗影萨满",
697
+ "28": "斯拉达",
698
+ "29": "潮汐猎人",
699
+ "30": "巫医",
700
+ "31": "巫妖",
701
+ "32": "力丸",
702
+ "33": "谜团",
703
+ "34": "修补匠",
704
+ "35": "狙击手",
705
+ "36": "瘟疫法师",
706
+ "37": "术士",
707
+ "38": "兽王",
708
+ "39": "痛苦女王",
709
+ "40": "剧毒术士",
710
+ "41": "虚空假面",
711
+ "42": "冥魂大帝",
712
+ "43": "死亡先知",
713
+ "44": "幻影刺客",
714
+ "45": "帕格纳",
715
+ "46": "圣堂刺客",
716
+ "47": "冥界亚龙",
717
+ "48": "露娜",
718
+ "49": "龙骑士",
719
+ "50": "戴泽",
720
+ "51": "发条技师",
721
+ "52": "拉席克",
722
+ "53": "先知",
723
+ "54": "噬魂鬼",
724
+ "55": "黑暗贤者",
725
+ "56": "克林克兹",
726
+ "57": "全能骑士",
727
+ "58": "魅惑魔女",
728
+ "59": "哈斯卡",
729
+ "60": "暗夜魔王",
730
+ "61": "育母蜘蛛",
731
+ "62": "赏金猎人",
732
+ "63": "编织者",
733
+ "64": "杰奇洛",
734
+ "65": "蝙蝠骑士",
735
+ "66": "",
736
+ "67": "幽鬼",
737
+ "68": "远古冰魄",
738
+ "69": "末日使者",
739
+ "70": "熊战士",
740
+ "71": "裂魂人",
741
+ "72": "矮人直升机",
742
+ "73": "炼金术士",
743
+ "74": "祈求者",
744
+ "75": "沉默术士",
745
+ "76": "殁境神蚀者",
746
+ "77": "狼人",
747
+ "78": "酒仙",
748
+ "79": "暗影恶魔",
749
+ "80": "德鲁伊",
750
+ "81": "混沌骑士",
751
+ "82": "米波",
752
+ "83": "树精卫士",
753
+ "84": "食人魔魔法师",
754
+ "85": "不朽尸王",
755
+ "86": "拉比克",
756
+ "87": "干扰者",
757
+ "88": "司夜刺客",
758
+ "89": "娜迦海妖",
759
+ "90": "光之守卫",
760
+ "91": "艾欧",
761
+ "92": "维萨吉",
762
+ "93": "斯拉克",
763
+ "94": "美杜莎",
764
+ "95": "巨魔战将",
765
+ "96": "半人马战行者",
766
+ "97": "马格纳斯",
767
+ "98": "伐木机",
768
+ "99": "钢背兽",
769
+ "100": "巨牙海民",
770
+ "101": "天怒法师",
771
+ "102": "亚巴顿",
772
+ "103": "上古巨神",
773
+ "104": "军团指挥官",
774
+ "105": "工程师",
775
+ "106": "灰烬之灵",
776
+ "107": "大地之灵",
777
+ "108": "孽主",
778
+ "109": "恐怖利刃",
779
+ "110": "凤凰",
780
+ "111": "神谕者",
781
+ "112": "寒冬飞龙",
782
+ "113": "天穹守望者",
783
+ "114": "齐天大圣",
784
+ "119": "邪影芳灵",
785
+ "120": "石鳞剑士",
786
+ "121": "天涯墨客",
787
+ "123": "森海飞霞",
788
+ "126": "虚无之灵",
789
+ "128": "电炎绝手",
790
+ "129": "玛尔斯",
791
+ "131": "百戏大王",
792
+ "135": "破晓辰星",
793
+ "136": "玛西",
794
+ "137": "",
795
+ "138": "琼英碧灵",
796
+ "145": "凯"
797
+ },
798
+ "en-US": {
799
+ "1": "Anti-Mage",
800
+ "2": "Axe",
801
+ "3": "Bane",
802
+ "4": "Bloodseeker",
803
+ "5": "Crystal Maiden",
804
+ "6": "Drow Ranger",
805
+ "7": "Earthshaker",
806
+ "8": "Juggernaut",
807
+ "9": "Mirana",
808
+ "10": "Morphling",
809
+ "11": "Shadow Fiend",
810
+ "12": "Phantom Lancer",
811
+ "13": "Puck",
812
+ "14": "Pudge",
813
+ "15": "Razor",
814
+ "16": "Sand King",
815
+ "17": "Storm Spirit",
816
+ "18": "Sven",
817
+ "19": "Tiny",
818
+ "20": "Vengeful Spirit",
819
+ "21": "Windranger",
820
+ "22": "Zeus",
821
+ "23": "Kunkka",
822
+ "25": "Lina",
823
+ "26": "Lion",
824
+ "27": "Shadow Shaman",
825
+ "28": "Slardar",
826
+ "29": "Tidehunter",
827
+ "30": "Witch Doctor",
828
+ "31": "Lich",
829
+ "32": "Riki",
830
+ "33": "Enigma",
831
+ "34": "Tinker",
832
+ "35": "Sniper",
833
+ "36": "Necrophos",
834
+ "37": "Warlock",
835
+ "38": "Beastmaster",
836
+ "39": "Queen of Pain",
837
+ "40": "Venomancer",
838
+ "41": "Faceless Void",
839
+ "42": "Wraith King",
840
+ "43": "Death Prophet",
841
+ "44": "Phantom Assassin",
842
+ "45": "Pugna",
843
+ "46": "Templar Assassin",
844
+ "47": "Viper",
845
+ "48": "Luna",
846
+ "49": "Dragon Knight",
847
+ "50": "Dazzle",
848
+ "51": "Clockwerk",
849
+ "52": "Leshrac",
850
+ "53": "Nature's Prophet",
851
+ "54": "Lifestealer",
852
+ "55": "Dark Seer",
853
+ "56": "Clinkz",
854
+ "57": "Omniknight",
855
+ "58": "Enchantress",
856
+ "59": "Huskar",
857
+ "60": "Night Stalker",
858
+ "61": "Broodmother",
859
+ "62": "Bounty Hunter",
860
+ "63": "Weaver",
861
+ "64": "Jakiro",
862
+ "65": "Batrider",
863
+ "66": "Chen",
864
+ "67": "Spectre",
865
+ "68": "Ancient Apparition",
866
+ "69": "Doom",
867
+ "70": "Ursa",
868
+ "71": "Spirit Breaker",
869
+ "72": "Gyrocopter",
870
+ "73": "Alchemist",
871
+ "74": "Invoker",
872
+ "75": "Silencer",
873
+ "76": "Outworld Devourer",
874
+ "77": "Lycan",
875
+ "78": "Brewmaster",
876
+ "79": "Shadow Demon",
877
+ "80": "Lone Druid",
878
+ "81": "Chaos Knight",
879
+ "82": "Meepo",
880
+ "83": "Treant Protector",
881
+ "84": "Ogre Magi",
882
+ "85": "Undying",
883
+ "86": "Rubick",
884
+ "87": "Disruptor",
885
+ "88": "Nyx Assassin",
886
+ "89": "Naga Siren",
887
+ "90": "Keeper of the Light",
888
+ "91": "Io",
889
+ "92": "Visage",
890
+ "93": "Slark",
891
+ "94": "Medusa",
892
+ "95": "Troll Warlord",
893
+ "96": "Centaur Warrunner",
894
+ "97": "Magnus",
895
+ "98": "Timbersaw",
896
+ "99": "Bristleback",
897
+ "100": "Tusk",
898
+ "101": "Skywrath Mage",
899
+ "102": "Abaddon",
900
+ "103": "Elder Titan",
901
+ "104": "Legion Commander",
902
+ "105": "Techies",
903
+ "106": "Ember Spirit",
904
+ "107": "Earth Spirit",
905
+ "108": "Underlord",
906
+ "109": "Terrorblade",
907
+ "110": "Phoenix",
908
+ "111": "Oracle",
909
+ "112": "Winter Wyvern",
910
+ "113": "Arc Warden",
911
+ "114": "Monkey King",
912
+ "119": "Dark Willow",
913
+ "120": "Pangolier",
914
+ "121": "Grimstroke",
915
+ "123": "Hoodwink",
916
+ "126": "Void Spirit",
917
+ "128": "Snapfire",
918
+ "129": "Mars",
919
+ "131": "Ring Master",
920
+ "135": "Dawnbreaker",
921
+ "136": "Marci",
922
+ "137": "Primal Beast",
923
+ "138": "Muerta",
924
+ "145": "Kez"
925
+ }
1230
926
  };
1231
927
  var WIN_NEGATIVE = ["侥幸赢得了比赛", "走狗屎运赢得了比赛", "躺赢了比赛", "打团都没来, 队友4V5赢得了比赛"];
1232
928
  var WIN_POSITIVE = ["带领团队走向了胜利", "暴打对面后赢得了胜利", " CARRY全场赢得了胜利", "把对面当猪宰了, 赢得了胜利", "又赢了, 这游戏就是这么枯燥, 且乏味", "直接进行一个比赛的赢"];
@@ -1242,7 +938,7 @@ var dotaconstants_add_default = {
1242
938
  primary_attrs,
1243
939
  behavior,
1244
940
  target_team,
1245
- HEROES_CHINESE,
941
+ HEROES_NAMES,
1246
942
  WIN_NEGATIVE,
1247
943
  WIN_POSITIVE,
1248
944
  LOSE_NEGATIVE,
@@ -1255,6 +951,7 @@ var ejs = __toESM(require("ejs"));
1255
951
  var name = "dota2tracker";
1256
952
  var usage = `
1257
953
  DOTA2Bot插件-提供自动追踪群友的最新对局的功能(需群友绑定),以及一系列查询功能。
954
+ [本地化/dota2tracker](../../locales/dota2tracker)可以自定义英雄别名和位置代称
1258
955
  **更多信息请进入[插件主页](https://github.com/sjtdev/koishi-plugin-dota2tracker)与[更新日志](https://github.com/sjtdev/koishi-plugin-dota2tracker/blob/master/changelog.md)查看。**`;
1259
956
  var inject = ["http", "database", "cron", "puppeteer"];
1260
957
  var Config = import_koishi.Schema.intersect([
@@ -1318,6 +1015,14 @@ var random = new import_koishi2.Random(() => Math.random());
1318
1015
  async function apply(ctx, config) {
1319
1016
  CONFIGS.STRATZ_API.TOKEN = config.STRATZ_API_TOKEN;
1320
1017
  init(ctx.http, ctx.setTimeout);
1018
+ ctx.i18n.define("zh-CN", require_zh_CN());
1019
+ ctx.i18n.define("en-US", require_en_US());
1020
+ const koishiLanguageTag = ctx.i18n.fallback(void 0).at(2);
1021
+ const getLanguageTag = /* @__PURE__ */ __name(async function(session, channel) {
1022
+ if (!session && !channel) return koishiLanguageTag;
1023
+ const resolvedChannel = channel ?? await session?.getChannel(session.event.channel.id);
1024
+ return resolvedChannel?.locales?.at(0) ?? koishiLanguageTag;
1025
+ }, "getLanguageTag");
1321
1026
  ctx.command("订阅本群", "订阅后还需玩家在本群绑定SteamID").usage("订阅后还需玩家在本群绑定SteamID,BOT将订阅本群中已绑定玩家的新比赛数据,在STRATZ比赛解析完成后将比赛数据生成为图片战报发布至本群中。").action(async ({ session }) => {
1322
1027
  if (session.guild) {
1323
1028
  let currentGuild = (await ctx.database.get("dt_subscribed_guilds", { guildId: session.event.channel.id, platform: session.event.platform }))[0];
@@ -1418,10 +1123,10 @@ async function apply(ctx, config) {
1418
1123
  memberList = await session.bot?.getGuildMemberList(session.event.channel.id);
1419
1124
  } catch (error) {
1420
1125
  }
1421
- async function getUsers(subscribedPlayers2, utils, queries, memberList2) {
1422
- const playerSteamIds = subscribedPlayers2.map((player) => player.steamId);
1423
- const queryResult = await utils.query(queries.PLAYERS_INFO_WITH_10_MATCHES_FOR_GUILD, playerSteamIds);
1424
- const playersInfo = queryResult.data.players;
1126
+ async function getUsers(subscribedPlayers2, memberList2) {
1127
+ const playerSteamIds = { steamAccountIds: subscribedPlayers2.map((player) => player.steamId) };
1128
+ const queryResult = await query("PlayersInfoWith10MatchesForGuild", playerSteamIds);
1129
+ const playersInfo = queryResult.players;
1425
1130
  const users2 = [];
1426
1131
  for (const subscribedPlayer of subscribedPlayers2) {
1427
1132
  const queryPlayer = playersInfo.find((player) => player.steamAccount.id == subscribedPlayer.steamId);
@@ -1431,7 +1136,7 @@ async function apply(ctx, config) {
1431
1136
  return users2;
1432
1137
  }
1433
1138
  __name(getUsers, "getUsers");
1434
- const users = await getUsers(subscribedPlayers, utils_exports, queries_exports, memberList);
1139
+ const users = await getUsers(subscribedPlayers, memberList);
1435
1140
  session.send(await ctx.puppeteer.render(genImageHTML(users, "guild_member" /* GuildMember */, "guild_member" /* GuildMember */)));
1436
1141
  } catch (error) {
1437
1142
  ctx.logger.error(error);
@@ -1442,18 +1147,17 @@ async function apply(ctx, config) {
1442
1147
  });
1443
1148
  async function queryMatchAndSend(session, matchId) {
1444
1149
  try {
1445
- let match;
1150
+ let matchQuery;
1446
1151
  let queryLocal = await ctx.database.get("dt_previous_query_results", matchId, ["data"]);
1447
1152
  if (queryLocal.length > 0) {
1448
- match = queryLocal[0].data;
1449
- ctx.database.set("dt_previous_query_results", match.id, { queryTime: /* @__PURE__ */ new Date() });
1450
- } else {
1451
- match = getFormattedMatchData((await query(MATCH_INFO, matchId)).data);
1452
- }
1153
+ matchQuery = queryLocal[0].data;
1154
+ ctx.database.set("dt_previous_query_results", matchQuery.match.id, { queryTime: /* @__PURE__ */ new Date() });
1155
+ } else matchQuery = await query("MatchInfo", { matchId });
1156
+ if (matchQuery.match.parsedDateTime)
1157
+ ctx.database.upsert("dt_previous_query_results", (row) => [{ matchId: matchQuery.match.id, data: matchQuery, queryTime: /* @__PURE__ */ new Date() }]);
1158
+ let match = getFormattedMatchData(matchQuery);
1453
1159
  if (match && (match.parsedDateTime || import_moment.default.unix(match.endDateTime).isBefore((0, import_moment.default)().subtract(config.dataParsingTimeoutMinutes, "minutes")))) {
1454
1160
  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 */)));
1455
- if (match.parsedDateTime)
1456
- ctx.database.upsert("dt_previous_query_results", (row) => [{ matchId: match.id, data: match, queryTime: /* @__PURE__ */ new Date() }]);
1457
1161
  } else {
1458
1162
  pendingMatches.push({ matchId, guilds: [{ platform: session.event.platform, guildId: session.event.channel.id, players: [] }] });
1459
1163
  session.send("比赛尚未解析,将在解析完成后发布。");
@@ -1461,7 +1165,7 @@ async function apply(ctx, config) {
1461
1165
  } catch (error) {
1462
1166
  ctx.logger.error(error);
1463
1167
  session.send("获取比赛信息失败。");
1464
- ctx.database.remove("dt_previous_query_results", { matchId: parseInt(matchId) });
1168
+ await ctx.database.remove("dt_previous_query_results", { matchId });
1465
1169
  }
1466
1170
  }
1467
1171
  __name(queryMatchAndSend, "queryMatchAndSend");
@@ -1495,7 +1199,7 @@ async function apply(ctx, config) {
1495
1199
  let lastMatchId = 0;
1496
1200
  try {
1497
1201
  session.send("正在搜索对局详情,请稍后...");
1498
- lastMatchId = (await query(PLAYERS_LASTMATCH_RANKINFO, [parseInt(flagBindedPlayer?.steamId ?? input_data)])).data.players[0].matches[0].id;
1202
+ lastMatchId = (await query("PlayersLastmatchRankinfo", { steamAccountIds: [parseInt(flagBindedPlayer?.steamId ?? input_data)] })).players[0].matches[0].id;
1499
1203
  } catch (error) {
1500
1204
  session.send("获取玩家最近比赛失败。");
1501
1205
  ctx.logger.error(error);
@@ -1522,12 +1226,17 @@ async function apply(ctx, config) {
1522
1226
  return;
1523
1227
  }
1524
1228
  session.send("正在获取玩家数据,请稍后...");
1525
- let hero = findingHero(options.hero);
1229
+ let heroId = findingHero(options.hero);
1526
1230
  let steamId = flagBindedPlayer?.steamId ?? input_data;
1527
1231
  let player;
1528
1232
  try {
1529
- player = (await query(PLAYER_INFO_WITH_25_MATCHES, steamId, hero?.id)).data.player;
1530
- let playerExtra = (await query(PLAYER_EXTRA_INFO, steamId, player.matchCount, Object.keys(dotaconstants3.heroes).length, hero?.id)).data.player;
1233
+ player = (await query("PlayerInfoWith25Matches", { steamAccountId: steamId, heroIds: heroId })).player;
1234
+ let playerExtra = (await query("PlayerExtraInfo", {
1235
+ steamAccountId: steamId,
1236
+ matchCount: player.matchCount,
1237
+ totalHeroCount: Object.keys(dotaconstants2.heroes).length,
1238
+ heroIds: heroId
1239
+ })).player;
1531
1240
  let filteredDotaPlus = {};
1532
1241
  playerExtra.dotaPlus.forEach((item) => {
1533
1242
  if (!filteredDotaPlus[item.heroId] || filteredDotaPlus[item.heroId].level < item.level) {
@@ -1537,11 +1246,11 @@ async function apply(ctx, config) {
1537
1246
  };
1538
1247
  }
1539
1248
  });
1540
- playerExtra.heroesPerformance.forEach((hero2) => {
1541
- if (filteredDotaPlus[hero2.hero.id]) {
1542
- filteredDotaPlus[hero2.hero.id].shortName = hero2.hero.shortName;
1543
- filteredDotaPlus[hero2.hero.id].winCount = hero2.winCount;
1544
- filteredDotaPlus[hero2.hero.id].matchCount = hero2.matchCount;
1249
+ playerExtra.heroesPerformance.forEach((hero) => {
1250
+ if (filteredDotaPlus[hero.hero.id]) {
1251
+ filteredDotaPlus[hero.hero.id].shortName = hero.hero.shortName;
1252
+ filteredDotaPlus[hero.hero.id].winCount = hero.winCount;
1253
+ filteredDotaPlus[hero.hero.id].matchCount = hero.matchCount;
1545
1254
  }
1546
1255
  });
1547
1256
  player.rank = {
@@ -1558,14 +1267,14 @@ async function apply(ctx, config) {
1558
1267
  return a.heroId - b.heroId;
1559
1268
  });
1560
1269
  player.heroesPerformanceTop10 = playerExtra.heroesPerformance.slice(0, 10);
1561
- if (hero) {
1270
+ if (heroId) {
1562
1271
  const { matchCount, winCount, imp } = player.heroesPerformanceTop10[0];
1563
1272
  player.matchCount = matchCount;
1564
1273
  player.winCount = winCount;
1565
1274
  player.performance.imp = imp;
1566
- player.dotaPlus = player.dotaPlus.filter((dpHero) => dpHero.heroId == hero.id);
1275
+ player.dotaPlus = player.dotaPlus.filter((dpHero) => dpHero.heroId == heroId);
1567
1276
  }
1568
- player.genHero = hero;
1277
+ player.genHero = { name: HEROES_NAMES[(await session.getChannel(session.event.channel.id)).locales?.at(0) ?? "zh-CN"][heroId] };
1569
1278
  session.send(
1570
1279
  (ctx.config.urlInMessageType.some((type) => type == "player") ? "https://stratz.com/players/" + player.steamAccount.id : "") + await ctx.puppeteer.render(genImageHTML(player, config.template_player, "player" /* Player */))
1571
1280
  );
@@ -1578,17 +1287,17 @@ async function apply(ctx, config) {
1578
1287
  }
1579
1288
  });
1580
1289
  ctx.command("查询英雄 <input_data>", "查询英雄技能/面板信息").usage("查询英雄的技能说明与各项数据,生成图片发布。\n参数可输入英雄ID、英雄名、英雄常用别名").option("random", "-r 随机选择英雄").example("查询英雄 15").example("查询英雄 雷泽").example("查询英雄 电魂").action(async ({ session, options }, input_data) => {
1581
- if (options.random) input_data = random.pick(Object.keys(HEROES_CHINESE));
1290
+ const languageTag = await getLanguageTag(session);
1291
+ if (options.random) input_data = random.pick(Object.keys(HEROES_NAMES[languageTag]));
1582
1292
  if (input_data) {
1583
- let hero = findingHero(input_data);
1584
- if (!hero) {
1293
+ let heroId = findingHero(input_data);
1294
+ if (!heroId) {
1585
1295
  session.send("未找到输入的英雄,请确认后重新输入。");
1586
1296
  return;
1587
1297
  }
1588
1298
  await session.send("正在获取英雄数据,请稍后...");
1589
1299
  try {
1590
- const queryHero = await queryHeroFromValve(hero.id);
1591
- Object.assign(hero, queryHero);
1300
+ let hero = await queryHeroFromValve(heroId, languageTag);
1592
1301
  hero.facet_abilities.forEach((fa, i) => {
1593
1302
  if (fa.abilities.length) {
1594
1303
  fa.abilities.forEach((ab) => {
@@ -1669,26 +1378,27 @@ async function apply(ctx, config) {
1669
1378
  });
1670
1379
  ctx.command("查询英雄对战 <input_data:string>", "查询英雄近一周的最佳搭档与最佳克星英雄").usage("根据输入英雄查询最近一周比赛数据(传奇~万古分段)中与该英雄组合胜率最高英雄和与该英雄对抗胜率最低英雄。\n参数可输入英雄ID、英雄名、英雄常用别名").option("limit", "-l <value:number> 返回英雄个数(默认值 5)", { fallback: 5 }).option("filter", "-f <value:number> 过滤场数过低的组合(单位:%,默认值0.75)", { fallback: 0.5 }).example("查询英雄对战 敌法师 (无额外参数默认返回5个英雄,过滤舍弃场次占比0.75%以下)").example("查询英雄对战 敌法师 -l=10 -f=1 (返回10个英雄,过滤舍弃场次占比1%以下)").example("查询英雄对战 敌法师 -l 10 -f 1 (等同于上例,参数接空格也可使用)").action(async ({ session, options }, input_data) => {
1671
1380
  if (input_data) {
1672
- let hero = findingHero(input_data);
1673
- if (!hero) {
1381
+ const languageTag = await getLanguageTag(session);
1382
+ let heroId = findingHero(input_data);
1383
+ if (!heroId) {
1674
1384
  session.send("未找到输入的英雄,请确认后重新输入。");
1675
1385
  return;
1676
1386
  }
1677
1387
  try {
1678
- let heroStats = (await query(HERO_MATCHUP_WINRATE, hero.id)).data.heroStats;
1388
+ let heroStats = (await query("HeroMatchupWinrate", { heroId, take: Object.keys(dotaconstants2.heroes).length - 1 })).heroStats;
1679
1389
  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) => {
1680
1390
  const winRate = item.winCount / item.matchCount;
1681
1391
  return { ...item, winRate: winRate.toFixed(3) };
1682
- }).sort((a, b) => b.winRate - a.winRate).slice(0, Math.max(1, Math.min(Object.keys(dotaconstants3.heroes).length - 1, options.limit)));
1392
+ }).sort((a, b) => b.winRate - a.winRate).slice(0, Math.max(1, Math.min(Object.keys(dotaconstants2.heroes).length - 1, options.limit)));
1683
1393
  let vsBottomFive = heroStats.matchUp[0].vs.filter((item) => item.matchCount / heroStats.matchUp[0].matchCountVs > Math.max(0, Math.min(5, options.filter)) / 100).map((item) => {
1684
1394
  const winRate = item.winCount / item.matchCount;
1685
1395
  return { ...item, winRate: winRate.toFixed(3) };
1686
- }).sort((a, b) => a.winRate - b.winRate).slice(0, Math.max(1, Math.min(Object.keys(dotaconstants3.heroes).length - 1, options.limit)));
1396
+ }).sort((a, b) => a.winRate - b.winRate).slice(0, Math.max(1, Math.min(Object.keys(dotaconstants2.heroes).length - 1, options.limit)));
1687
1397
  session.send(
1688
- `你查询的英雄是${HEROES_CHINESE[heroStats.matchUp[0].heroId][0]}(ID:${heroStats.matchUp[0].heroId}),
1398
+ `你查询的英雄是${HEROES_NAMES[heroStats.matchUp[0].heroId][0]}(ID:${heroStats.matchUp[0].heroId}),
1689
1399
  以下是7天内传奇-万古分段比赛数据总结而来的搭档与克制关系
1690
- 最佳搭档(组合胜率前${options.limit}):${withTopFive.map((item) => `${HEROES_CHINESE[item.heroId2][0]}(胜率${(item.winRate * 100).toFixed(1)}%)`).join("、")}
1691
- 最佳克星(对抗胜率倒${options.limit}):${vsBottomFive.map((item) => `${HEROES_CHINESE[item.heroId2][0]}(胜率${(item.winRate * 100).toFixed(1)}%)`).join("、")}`
1400
+ 最佳搭档(组合胜率前${options.limit}):${withTopFive.map((item) => `${HEROES_NAMES[languageTag][item.heroId2][0]}(胜率${(item.winRate * 100).toFixed(1)}%)`).join("、")}
1401
+ 最佳克星(对抗胜率倒${options.limit}):${vsBottomFive.map((item) => `${HEROES_NAMES[languageTag][item.heroId2][0]}(胜率${(item.winRate * 100).toFixed(1)}%)`).join("、")}`
1692
1402
  );
1693
1403
  } catch (error) {
1694
1404
  ctx.logger.error(error);
@@ -1698,28 +1408,48 @@ async function apply(ctx, config) {
1698
1408
  }
1699
1409
  });
1700
1410
  function findingHero(input) {
1701
- if (!input) return;
1702
- let dc_heroes = Object.values(dotaconstants3.heroes).map((hero) => ({
1703
- id: hero["id"],
1704
- name: hero["name"],
1705
- shortName: hero["name"].match(/^npc_dota_hero_(.+)$/)[1]
1706
- }));
1707
- let cn_heroes = Object.keys(HEROES_CHINESE).map((key) => ({
1708
- id: parseInt(key),
1709
- names_cn: HEROES_CHINESE[key]
1710
- }));
1711
- const mergedMap = /* @__PURE__ */ new Map();
1712
- [dc_heroes, cn_heroes].forEach((array) => {
1713
- array.forEach((item) => {
1714
- const existingItem = mergedMap.get(item.id);
1715
- if (existingItem) mergedMap.set(item.id, { ...existingItem, ...item });
1716
- else mergedMap.set(item.id, item);
1717
- });
1718
- });
1719
- let heroes3 = Array.from(mergedMap.values());
1720
- return heroes3.find((hero) => hero.names_cn.some((cn) => cn.toLowerCase() == input.toLowerCase()) || hero.shortName === input.toLowerCase() || hero.id == input);
1411
+ const heroIds = Object.keys(dotaconstants2.heroes).map((id) => parseInt(id));
1412
+ let tid;
1413
+ for (const loc of Object.keys(HEROES_NAMES)) {
1414
+ for (const id_nicknames of getHeroNicknames(heroIds, loc)) {
1415
+ for (const [id, nicknames] of Object.entries(id_nicknames)) {
1416
+ try {
1417
+ for (const nickname of nicknames) {
1418
+ if (input == nickname) return Number(id);
1419
+ }
1420
+ } catch {
1421
+ continue;
1422
+ }
1423
+ }
1424
+ }
1425
+ }
1426
+ for (const names of Object.values(HEROES_NAMES)) {
1427
+ for (const [id, name2] of Object.entries(names)) {
1428
+ if (input == name2) return Number(id);
1429
+ if (input == id) tid = input;
1430
+ }
1431
+ }
1432
+ return tid;
1721
1433
  }
1722
1434
  __name(findingHero, "findingHero");
1435
+ function getHeroNicknames(heroIds, languageTag = koishiLanguageTag) {
1436
+ if (heroIds === void 0) return [];
1437
+ const heroIdArray = Array.isArray(heroIds) ? heroIds : [heroIds];
1438
+ const result = [];
1439
+ for (const heroId of heroIdArray) {
1440
+ let content = [];
1441
+ try {
1442
+ const rawContent = ctx.i18n.render([languageTag], [`dota2tracker.heroes.${heroId}`], {}).at(0)?.attrs?.content ?? "";
1443
+ content = JSON.parse(`[${rawContent}]`);
1444
+ } catch (error) {
1445
+ ctx.logger.error(`Failed to parse heroId ${heroId} content: ${error.message}`);
1446
+ content = [];
1447
+ }
1448
+ result.push({ [heroId]: content });
1449
+ }
1450
+ return Array.isArray(heroIds) ? result : result[0][heroIds];
1451
+ }
1452
+ __name(getHeroNicknames, "getHeroNicknames");
1723
1453
  ctx.on("ready", async () => {
1724
1454
  ctx.model.extend("dt_subscribed_guilds", { id: "unsigned", guildId: "string", platform: "string" }, { autoInc: true });
1725
1455
  ctx.model.extend("dt_subscribed_players", { id: "unsigned", userId: "string", guildId: "string", platform: "string", steamId: "integer", nickName: "string", rank: "json" }, { autoInc: true });
@@ -1749,7 +1479,7 @@ async function apply(ctx, config) {
1749
1479
  const subscribedPlayersSteamIds = subscribedPlayersInGuild.map((player) => player.steamId).filter(function(value, index, self) {
1750
1480
  return self.indexOf(value) === index;
1751
1481
  });
1752
- const players = (await query(PLAYERS_LASTMATCH_RANKINFO, subscribedPlayersSteamIds)).data.players;
1482
+ const players = (await query("PlayersLastmatchRankinfo", { steamAccountIds: subscribedPlayersSteamIds })).players;
1753
1483
  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));
1754
1484
  const sendedMatchesIds = (await ctx.database.get("dt_sended_match_id", { matchId: lastMatches.map((match) => match.id) }, ["matchId"])).map((match) => match.matchId);
1755
1485
  lastMatches.filter((match) => !sendedMatchesIds.includes(match.id)).forEach((match) => {
@@ -1764,7 +1494,9 @@ async function apply(ctx, config) {
1764
1494
  });
1765
1495
  });
1766
1496
  pendingMatches.push({ matchId: match.id, guilds: tempGuilds });
1767
- query(REQUEST_MATCH_DATA_ANALYSIS, match.id);
1497
+ query("RequestMatchDataAnalysis", { matchId: match.id }).then(
1498
+ (response) => ctx.logger.info(response.stratz.matchRetry ? "解析请求已成功发送至服务器。" : "解析请求发送失败。")
1499
+ );
1768
1500
  ctx.logger.info(
1769
1501
  tempGuilds.map((guild) => `追踪到来自群组${guild.platform}:${guild.guildId}的用户${guild.players.map((player) => `[${player.nickName ?? ""}(${player.steamId})]`).join("、")}的尚未播报过的最新比赛 ${match.id}。`).join("")
1770
1502
  );
@@ -1824,13 +1556,17 @@ async function apply(ctx, config) {
1824
1556
  const now = (0, import_moment.default)();
1825
1557
  const pendingMatch = pendingMatches[(now.hours() * 60 + now.minutes()) % pendingMatches.length];
1826
1558
  try {
1827
- let match;
1559
+ const languageTag = await getLanguageTag();
1560
+ let matchQuery;
1828
1561
  let queryLocal = await ctx.database.get("dt_previous_query_results", pendingMatch.matchId, ["data"]);
1829
1562
  if (queryLocal.length > 0) {
1830
- match = queryLocal[0].data;
1831
- ctx.database.set("dt_previous_query_results", match.id, { queryTime: /* @__PURE__ */ new Date() });
1832
- } else match = getFormattedMatchData((await query(MATCH_INFO, pendingMatch.matchId)).data);
1833
- if (match.parsedDateTime || import_moment.default.unix(match.endDateTime).isBefore(now.subtract(config.dataParsingTimeoutMinutes, "minutes"))) {
1563
+ matchQuery = queryLocal[0].data;
1564
+ ctx.database.set("dt_previous_query_results", matchQuery.match.id, { queryTime: /* @__PURE__ */ new Date() });
1565
+ } else matchQuery = await query("MatchInfo", { matchId: pendingMatch.matchId });
1566
+ if (matchQuery.match.parsedDateTime || import_moment.default.unix(matchQuery.match.endDateTime).isBefore(now.subtract(config.dataParsingTimeoutMinutes, "minutes"))) {
1567
+ if (matchQuery.match.parsedDateTime)
1568
+ ctx.database.upsert("dt_previous_query_results", (row) => [{ matchId: matchQuery.match.id, data: matchQuery, queryTime: /* @__PURE__ */ new Date() }]);
1569
+ let match = getFormattedMatchData(matchQuery);
1834
1570
  pendingMatches = pendingMatches.filter((item) => item.matchId != match.id);
1835
1571
  const img = await ctx.puppeteer.render(genImageHTML(match, config.template_match, "match" /* Match */));
1836
1572
  for (let commingGuild of pendingMatch.guilds) {
@@ -1839,7 +1575,7 @@ async function apply(ctx, config) {
1839
1575
  let broadPlayers = match.players.filter((item) => idsToFind.includes(item.steamAccountId));
1840
1576
  for (let player of broadPlayers) {
1841
1577
  const random2 = new import_koishi2.Random(() => enhancedSimpleHashToSeed(`${match.id}-${player.steamAccountId}-${player.playerSlot}`));
1842
- let broadPlayerMessage = `${player.steamAccount.name}的${random2.pick(HEROES_CHINESE[player.hero.id])}`;
1578
+ let broadPlayerMessage = `${player.steamAccount.name}的${random2.pick(getHeroNicknames(player.hero.id, languageTag))}`;
1843
1579
  if (player.isRadiant == match.didRadiantWin) {
1844
1580
  if (player.deathContribution < 0.2 || player.killContribution > 0.75 || player.heroDamage / player.networth > 1.5 || player.towerDamage > 1e4 || player.imp > 0)
1845
1581
  broadPlayerMessage += random2.pick(WIN_POSITIVE);
@@ -1856,10 +1592,8 @@ KDA:${((player.kills + player.assists) / (player.deaths || 1)).toFixed(2)} [${
1856
1592
  await ctx.broadcast([`${commingGuild.platform}:${commingGuild.guildId}`], broadMatchMessage + (ctx.config.urlInMessageType.some((type) => type == "match") ? "https://stratz.com/matches/" + match.id : "") + img);
1857
1593
  ctx.logger.info(`${match.id}${match.parsedDateTime ? "已解析," : "已结束超过1小时仍未被解析,放弃等待解析直接"}生成图片并发布于${commingGuild.platform}:${commingGuild.guildId}。`);
1858
1594
  }
1859
- if (match.parsedDateTime)
1860
- ctx.database.upsert("dt_previous_query_results", (row) => [{ matchId: match.id, data: match, queryTime: /* @__PURE__ */ new Date() }]);
1861
1595
  ctx.database.create("dt_sended_match_id", { matchId: match.id, sendTime: /* @__PURE__ */ new Date() });
1862
- } else ctx.logger.info("比赛 %d 尚未解析完成,继续等待。", match.id);
1596
+ } else ctx.logger.info("比赛 %d 尚未解析完成,继续等待。", matchQuery.match.id);
1863
1597
  } catch (error) {
1864
1598
  ctx.logger.error(error);
1865
1599
  ctx.database.remove("dt_previous_query_results", { matchId: pendingMatch.matchId });
@@ -1870,11 +1604,10 @@ KDA:${((player.kills + player.assists) / (player.deaths || 1)).toFixed(2)} [${
1870
1604
  async function report(timeAgo, title, showCombi) {
1871
1605
  const subscribedGuilds = await ctx.database.get("dt_subscribed_guilds", void 0);
1872
1606
  const subscribedPlayersInGuild = (await ctx.database.get("dt_subscribed_players", void 0)).filter((player) => subscribedGuilds.some((guild) => guild.guildId == player.guildId));
1873
- const players = (await query(
1874
- PLAYERS_MATCHES_FOR_DAILY,
1875
- subscribedPlayersInGuild.map((player) => player.steamId).filter((value, index, self) => self.indexOf(value) === index),
1876
- timeAgo
1877
- )).data.players.filter((player) => player.matches.length > 0);
1607
+ const players = (await query("PlayersMatchesForDaily", {
1608
+ steamAccountIds: subscribedPlayersInGuild.map((player) => player.steamId).filter((value, index, self) => self.indexOf(value) === index),
1609
+ seconds: timeAgo
1610
+ })).players.filter((player) => player.matches.length > 0);
1878
1611
  const matches = players.map((player) => player.matches.map((match) => match)).flat().filter((item, index, self) => index === self.findIndex((t) => t.id === item.id));
1879
1612
  for (let subPlayer of subscribedPlayersInGuild) {
1880
1613
  let player = players.find((player2) => subPlayer.steamId == player2.steamAccount.id);
@@ -1961,7 +1694,7 @@ function genImageHTML(data, template, type) {
1961
1694
  ImageType,
1962
1695
  ImageFormat,
1963
1696
  d2a: dotaconstants_add_exports,
1964
- dotaconstants: dotaconstants3,
1697
+ dotaconstants: dotaconstants2,
1965
1698
  moment: import_moment.default,
1966
1699
  escapeHTML: /* @__PURE__ */ __name(function escapeHTML(str) {
1967
1700
  if (str == null) return "";