@sjtdev/koishi-plugin-dota2tracker 1.2.20-pre.3 → 1.3.0-pre.2
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 +995 -626
- package/package.json +4 -3
- package/queries/Constants.graphql +16 -0
- package/queries/MatchInfo.graphql +2 -8
- package/readme.md +4 -3
- package/template/guild_member/guild_member.ejs +3 -3
- package/template/hero/hero_1.ejs +175 -114
- package/template/match/match_1.ejs +24 -46
- package/template/match/match_2.ejs +30 -30
- package/template/player/player_1.ejs +79 -52
- package/template/rank/rank_fun.ejs +111 -108
- package/template/rank/temp.ejs +0 -27
package/lib/index.js
CHANGED
|
@@ -5,6 +5,11 @@ 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 __glob = (map) => (path3) => {
|
|
9
|
+
var fn = map[path3];
|
|
10
|
+
if (fn) return fn();
|
|
11
|
+
throw new Error("Module not found in bundle: " + path3);
|
|
12
|
+
};
|
|
8
13
|
var __commonJS = (cb, mod) => function __require() {
|
|
9
14
|
return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
|
|
10
15
|
};
|
|
@@ -30,17 +35,571 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
30
35
|
));
|
|
31
36
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
32
37
|
|
|
33
|
-
// src/locales/
|
|
34
|
-
var
|
|
35
|
-
"src/locales/
|
|
36
|
-
module2.exports = {
|
|
38
|
+
// src/locales/en-US.constants.json
|
|
39
|
+
var require_en_US_constants = __commonJS({
|
|
40
|
+
"src/locales/en-US.constants.json"(exports2, module2) {
|
|
41
|
+
module2.exports = {
|
|
42
|
+
dota2tracker: {
|
|
43
|
+
template: {
|
|
44
|
+
game_modes: {
|
|
45
|
+
NONE: "None",
|
|
46
|
+
ALL_PICK: "All Pick",
|
|
47
|
+
CAPTAINS_MODE: "Captains Mode",
|
|
48
|
+
RANDOM_DRAFT: "Random Draft",
|
|
49
|
+
SINGLE_DRAFT: "Single Draft",
|
|
50
|
+
ALL_RANDOM: "All Random",
|
|
51
|
+
INTRO: "Intro",
|
|
52
|
+
THE_DIRETIDE: "The Diretide",
|
|
53
|
+
REVERSE_CAPTAINS_MODE: "Reverse Captains Mode",
|
|
54
|
+
THE_GREEVILING: "The Greeviling",
|
|
55
|
+
TUTORIAL: "Tutorial",
|
|
56
|
+
MID_ONLY: "Mid Only",
|
|
57
|
+
LEAST_PLAYED: "Least Played",
|
|
58
|
+
NEW_PLAYER_POOL: "New Player Pool",
|
|
59
|
+
COMPENDIUM_MATCHMAKING: "Compendium Matchmaking",
|
|
60
|
+
CUSTOM: "Custom",
|
|
61
|
+
CAPTAINS_DRAFT: "Captains Draft",
|
|
62
|
+
BALANCED_DRAFT: "Balanced Draft",
|
|
63
|
+
ABILITY_DRAFT: "Ability Draft",
|
|
64
|
+
EVENT: "Event",
|
|
65
|
+
ALL_RANDOM_DEATH_MATCH: "All Random Death Match",
|
|
66
|
+
SOLO_MID: "Solo Mid",
|
|
67
|
+
ALL_PICK_RANKED: "All Pick",
|
|
68
|
+
TURBO: "Turbo",
|
|
69
|
+
MUTATION: "Mutation",
|
|
70
|
+
UNKNOWN: "Unknown"
|
|
71
|
+
},
|
|
72
|
+
lobby_types: {
|
|
73
|
+
INVALID: "Invalid",
|
|
74
|
+
UNRANKED: "Unranked",
|
|
75
|
+
PRACTICE: "Practice",
|
|
76
|
+
TOURNAMENT: "Tournament",
|
|
77
|
+
TUTORIAL: "Tutorial",
|
|
78
|
+
COOP_VS_BOTS: "Coop Vs Bots",
|
|
79
|
+
TEAM_MATCH: "Team Match",
|
|
80
|
+
SOLO_QUEUE: "Solo Queue",
|
|
81
|
+
RANKED: "Ranked",
|
|
82
|
+
SOLO_MID: "Solo Mid",
|
|
83
|
+
BATTLE_CUP: "Battle Cup",
|
|
84
|
+
EVENT: "Event",
|
|
85
|
+
NEW_PLAYER_POOL: "New Player Pool"
|
|
86
|
+
},
|
|
87
|
+
regions: {
|
|
88
|
+
"1": "US West",
|
|
89
|
+
"2": "US East",
|
|
90
|
+
"3": "Europe West",
|
|
91
|
+
"5": "SE Asia",
|
|
92
|
+
"6": "Dubai",
|
|
93
|
+
"7": "Australia",
|
|
94
|
+
"8": "Russia",
|
|
95
|
+
"9": "EU East",
|
|
96
|
+
"10": "South America",
|
|
97
|
+
"11": "South Africa",
|
|
98
|
+
"12": "China",
|
|
99
|
+
"13": "China",
|
|
100
|
+
"14": "Chile",
|
|
101
|
+
"15": "Peru",
|
|
102
|
+
"16": "India",
|
|
103
|
+
"17": "China",
|
|
104
|
+
"18": "China",
|
|
105
|
+
"19": "Japan",
|
|
106
|
+
"20": "China",
|
|
107
|
+
"25": "China",
|
|
108
|
+
"37": "Taiwan",
|
|
109
|
+
"38": "Argentina"
|
|
110
|
+
},
|
|
111
|
+
ranks: {
|
|
112
|
+
"0": "Unknown",
|
|
113
|
+
"1": "Herald",
|
|
114
|
+
"2": "Guardian",
|
|
115
|
+
"3": "Crusader",
|
|
116
|
+
"4": "Archon",
|
|
117
|
+
"5": "Legend",
|
|
118
|
+
"6": "Ancient",
|
|
119
|
+
"7": "Divine",
|
|
120
|
+
"8": "Immortal"
|
|
121
|
+
},
|
|
122
|
+
roles: {
|
|
123
|
+
"0": "Carry",
|
|
124
|
+
"1": "Support",
|
|
125
|
+
"2": "Nuker",
|
|
126
|
+
"3": "Disabler",
|
|
127
|
+
"4": "Jungler",
|
|
128
|
+
"5": "Durable",
|
|
129
|
+
"6": "Escape",
|
|
130
|
+
"7": "Pusher",
|
|
131
|
+
"8": "Initiator"
|
|
132
|
+
},
|
|
133
|
+
hero_names: {
|
|
134
|
+
"1": "Anti-Mage",
|
|
135
|
+
"2": "Axe",
|
|
136
|
+
"3": "Bane",
|
|
137
|
+
"4": "Bloodseeker",
|
|
138
|
+
"5": "Crystal Maiden",
|
|
139
|
+
"6": "Drow Ranger",
|
|
140
|
+
"7": "Earthshaker",
|
|
141
|
+
"8": "Juggernaut",
|
|
142
|
+
"9": "Mirana",
|
|
143
|
+
"10": "Morphling",
|
|
144
|
+
"11": "Shadow Fiend",
|
|
145
|
+
"12": "Phantom Lancer",
|
|
146
|
+
"13": "Puck",
|
|
147
|
+
"14": "Pudge",
|
|
148
|
+
"15": "Razor",
|
|
149
|
+
"16": "Sand King",
|
|
150
|
+
"17": "Storm Spirit",
|
|
151
|
+
"18": "Sven",
|
|
152
|
+
"19": "Tiny",
|
|
153
|
+
"20": "Vengeful Spirit",
|
|
154
|
+
"21": "Windranger",
|
|
155
|
+
"22": "Zeus",
|
|
156
|
+
"23": "Kunkka",
|
|
157
|
+
"25": "Lina",
|
|
158
|
+
"26": "Lion",
|
|
159
|
+
"27": "Shadow Shaman",
|
|
160
|
+
"28": "Slardar",
|
|
161
|
+
"29": "Tidehunter",
|
|
162
|
+
"30": "Witch Doctor",
|
|
163
|
+
"31": "Lich",
|
|
164
|
+
"32": "Riki",
|
|
165
|
+
"33": "Enigma",
|
|
166
|
+
"34": "Tinker",
|
|
167
|
+
"35": "Sniper",
|
|
168
|
+
"36": "Necrophos",
|
|
169
|
+
"37": "Warlock",
|
|
170
|
+
"38": "Beastmaster",
|
|
171
|
+
"39": "Queen of Pain",
|
|
172
|
+
"40": "Venomancer",
|
|
173
|
+
"41": "Faceless Void",
|
|
174
|
+
"42": "Wraith King",
|
|
175
|
+
"43": "Death Prophet",
|
|
176
|
+
"44": "Phantom Assassin",
|
|
177
|
+
"45": "Pugna",
|
|
178
|
+
"46": "Templar Assassin",
|
|
179
|
+
"47": "Viper",
|
|
180
|
+
"48": "Luna",
|
|
181
|
+
"49": "Dragon Knight",
|
|
182
|
+
"50": "Dazzle",
|
|
183
|
+
"51": "Clockwerk",
|
|
184
|
+
"52": "Leshrac",
|
|
185
|
+
"53": "Nature's Prophet",
|
|
186
|
+
"54": "Lifestealer",
|
|
187
|
+
"55": "Dark Seer",
|
|
188
|
+
"56": "Clinkz",
|
|
189
|
+
"57": "Omniknight",
|
|
190
|
+
"58": "Enchantress",
|
|
191
|
+
"59": "Huskar",
|
|
192
|
+
"60": "Night Stalker",
|
|
193
|
+
"61": "Broodmother",
|
|
194
|
+
"62": "Bounty Hunter",
|
|
195
|
+
"63": "Weaver",
|
|
196
|
+
"64": "Jakiro",
|
|
197
|
+
"65": "Batrider",
|
|
198
|
+
"66": "Chen",
|
|
199
|
+
"67": "Spectre",
|
|
200
|
+
"68": "Ancient Apparition",
|
|
201
|
+
"69": "Doom",
|
|
202
|
+
"70": "Ursa",
|
|
203
|
+
"71": "Spirit Breaker",
|
|
204
|
+
"72": "Gyrocopter",
|
|
205
|
+
"73": "Alchemist",
|
|
206
|
+
"74": "Invoker",
|
|
207
|
+
"75": "Silencer",
|
|
208
|
+
"76": "Outworld Devourer",
|
|
209
|
+
"77": "Lycan",
|
|
210
|
+
"78": "Brewmaster",
|
|
211
|
+
"79": "Shadow Demon",
|
|
212
|
+
"80": "Lone Druid",
|
|
213
|
+
"81": "Chaos Knight",
|
|
214
|
+
"82": "Meepo",
|
|
215
|
+
"83": "Treant Protector",
|
|
216
|
+
"84": "Ogre Magi",
|
|
217
|
+
"85": "Undying",
|
|
218
|
+
"86": "Rubick",
|
|
219
|
+
"87": "Disruptor",
|
|
220
|
+
"88": "Nyx Assassin",
|
|
221
|
+
"89": "Naga Siren",
|
|
222
|
+
"90": "Keeper of the Light",
|
|
223
|
+
"91": "Io",
|
|
224
|
+
"92": "Visage",
|
|
225
|
+
"93": "Slark",
|
|
226
|
+
"94": "Medusa",
|
|
227
|
+
"95": "Troll Warlord",
|
|
228
|
+
"96": "Centaur Warrunner",
|
|
229
|
+
"97": "Magnus",
|
|
230
|
+
"98": "Timbersaw",
|
|
231
|
+
"99": "Bristleback",
|
|
232
|
+
"100": "Tusk",
|
|
233
|
+
"101": "Skywrath Mage",
|
|
234
|
+
"102": "Abaddon",
|
|
235
|
+
"103": "Elder Titan",
|
|
236
|
+
"104": "Legion Commander",
|
|
237
|
+
"105": "Techies",
|
|
238
|
+
"106": "Ember Spirit",
|
|
239
|
+
"107": "Earth Spirit",
|
|
240
|
+
"108": "Underlord",
|
|
241
|
+
"109": "Terrorblade",
|
|
242
|
+
"110": "Phoenix",
|
|
243
|
+
"111": "Oracle",
|
|
244
|
+
"112": "Winter Wyvern",
|
|
245
|
+
"113": "Arc Warden",
|
|
246
|
+
"114": "Monkey King",
|
|
247
|
+
"119": "Dark Willow",
|
|
248
|
+
"120": "Pangolier",
|
|
249
|
+
"121": "Grimstroke",
|
|
250
|
+
"123": "Hoodwink",
|
|
251
|
+
"126": "Void Spirit",
|
|
252
|
+
"128": "Snapfire",
|
|
253
|
+
"129": "Mars",
|
|
254
|
+
"131": "Ring Master",
|
|
255
|
+
"135": "Dawnbreaker",
|
|
256
|
+
"136": "Marci",
|
|
257
|
+
"137": "Primal Beast",
|
|
258
|
+
"138": "Muerta",
|
|
259
|
+
"145": "Kez"
|
|
260
|
+
},
|
|
261
|
+
behavior: {
|
|
262
|
+
"Unit Target": "Unit Target",
|
|
263
|
+
Channeled: "Channeled",
|
|
264
|
+
Hidden: "Hidden",
|
|
265
|
+
Passive: "Passive",
|
|
266
|
+
"No Target": "No Target",
|
|
267
|
+
Autocast: "Autocast",
|
|
268
|
+
"Instant Cast": "Instant Cast",
|
|
269
|
+
"Point Target": "Point Target",
|
|
270
|
+
"Attack Modifier": "Attack Modifier",
|
|
271
|
+
AOE: "AOE"
|
|
272
|
+
},
|
|
273
|
+
target_team: {
|
|
274
|
+
Enemy: "Enemy",
|
|
275
|
+
Both: "Both",
|
|
276
|
+
Friendly: "Friendly"
|
|
277
|
+
},
|
|
278
|
+
ability: "Ability: ",
|
|
279
|
+
affects: "Affects:",
|
|
280
|
+
damage_type: "Damage Type: ",
|
|
281
|
+
damage_type_Physical: "Physical",
|
|
282
|
+
damage_type_Magical: "Magical",
|
|
283
|
+
damage_type_Pure: "Pure",
|
|
284
|
+
dispellable: "Dispellable: ",
|
|
285
|
+
Yes: "Yes",
|
|
286
|
+
No: "No",
|
|
287
|
+
dispellable_Strong: "Strong Dispels Only",
|
|
288
|
+
bkbpierce: "Pierces Debuff Imminity: ",
|
|
289
|
+
innate: "Innate",
|
|
290
|
+
scepter: "Aghanim's Scepter",
|
|
291
|
+
shard: "Aghanim's Shard",
|
|
292
|
+
attack: "ATTACK",
|
|
293
|
+
defense: "DEFENSE",
|
|
294
|
+
mobility: "MOBILITY"
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
};
|
|
298
|
+
}
|
|
299
|
+
});
|
|
300
|
+
|
|
301
|
+
// src/locales/zh-CN.constants.json
|
|
302
|
+
var require_zh_CN_constants = __commonJS({
|
|
303
|
+
"src/locales/zh-CN.constants.json"(exports2, module2) {
|
|
304
|
+
module2.exports = {
|
|
305
|
+
dota2tracker: {
|
|
306
|
+
template: {
|
|
307
|
+
game_modes: {
|
|
308
|
+
NONE: "",
|
|
309
|
+
ALL_PICK: "全英雄选择",
|
|
310
|
+
CAPTAINS_MODE: "队长模式",
|
|
311
|
+
RANDOM_DRAFT: "随机征召",
|
|
312
|
+
SINGLE_DRAFT: "单一征召",
|
|
313
|
+
ALL_RANDOM: "全英雄随机",
|
|
314
|
+
INTRO: "",
|
|
315
|
+
THE_DIRETIDE: "",
|
|
316
|
+
REVERSE_CAPTAINS_MODE: "",
|
|
317
|
+
THE_GREEVILING: "",
|
|
318
|
+
TUTORIAL: "教程模式",
|
|
319
|
+
MID_ONLY: "",
|
|
320
|
+
LEAST_PLAYED: "",
|
|
321
|
+
NEW_PLAYER_POOL: "",
|
|
322
|
+
COMPENDIUM_MATCHMAKING: "",
|
|
323
|
+
CUSTOM: "",
|
|
324
|
+
CAPTAINS_DRAFT: "",
|
|
325
|
+
BALANCED_DRAFT: "",
|
|
326
|
+
ABILITY_DRAFT: "",
|
|
327
|
+
EVENT: "",
|
|
328
|
+
ALL_RANDOM_DEATH_MATCH: "",
|
|
329
|
+
SOLO_MID: "",
|
|
330
|
+
ALL_PICK_RANKED: "全英雄选择",
|
|
331
|
+
TURBO: "加速模式",
|
|
332
|
+
MUTATION: "",
|
|
333
|
+
UNKNOWN: ""
|
|
334
|
+
},
|
|
335
|
+
lobby_types: {
|
|
336
|
+
INVALID: "",
|
|
337
|
+
UNRANKED: "非天梯",
|
|
338
|
+
PRACTICE: "",
|
|
339
|
+
TOURNAMENT: "",
|
|
340
|
+
TUTORIAL: "",
|
|
341
|
+
COOP_VS_BOTS: "",
|
|
342
|
+
TEAM_MATCH: "",
|
|
343
|
+
SOLO_QUEUE: "",
|
|
344
|
+
RANKED: "天梯比赛",
|
|
345
|
+
SOLO_MID: "",
|
|
346
|
+
BATTLE_CUP: "",
|
|
347
|
+
EVENT: "",
|
|
348
|
+
NEW_PLAYER_POOL: ""
|
|
349
|
+
},
|
|
350
|
+
regions: {
|
|
351
|
+
"1": "US WEST",
|
|
352
|
+
"2": "US EAST",
|
|
353
|
+
"3": "EUROPE",
|
|
354
|
+
"5": "新加坡",
|
|
355
|
+
"6": "DUBAI",
|
|
356
|
+
"7": "AUSTRALIA",
|
|
357
|
+
"8": "STOCKHOLM",
|
|
358
|
+
"9": "AUSTRIA",
|
|
359
|
+
"10": "BRAZIL",
|
|
360
|
+
"11": "SOUTHAFRICA",
|
|
361
|
+
"12": "电信(上海)",
|
|
362
|
+
"13": "联通(一)",
|
|
363
|
+
"14": "CHILE",
|
|
364
|
+
"15": "PERU",
|
|
365
|
+
"16": "INDIA",
|
|
366
|
+
"17": "电信(广东)",
|
|
367
|
+
"18": "电信(浙江)",
|
|
368
|
+
"19": "日本",
|
|
369
|
+
"20": "电信(华中)",
|
|
370
|
+
"25": "联通(二)",
|
|
371
|
+
"37": "TAIWAN",
|
|
372
|
+
"38": "ARGENTINA"
|
|
373
|
+
},
|
|
374
|
+
ranks: {
|
|
375
|
+
"0": "未知",
|
|
376
|
+
"1": "先锋",
|
|
377
|
+
"2": "卫士",
|
|
378
|
+
"3": "中军",
|
|
379
|
+
"4": "统帅",
|
|
380
|
+
"5": "传奇",
|
|
381
|
+
"6": "万古流芳",
|
|
382
|
+
"7": "超凡入圣",
|
|
383
|
+
"8": "冠绝一世"
|
|
384
|
+
},
|
|
385
|
+
roles: {
|
|
386
|
+
"0": "核心",
|
|
387
|
+
"1": "辅助",
|
|
388
|
+
"2": "爆发",
|
|
389
|
+
"3": "控制",
|
|
390
|
+
"4": "打野",
|
|
391
|
+
"5": "耐久",
|
|
392
|
+
"6": "逃生",
|
|
393
|
+
"7": "推进",
|
|
394
|
+
"8": "先手"
|
|
395
|
+
},
|
|
396
|
+
hero_names: {
|
|
397
|
+
"1": "敌法师",
|
|
398
|
+
"2": "斧王",
|
|
399
|
+
"3": "祸乱之源",
|
|
400
|
+
"4": "血魔",
|
|
401
|
+
"5": "水晶室女",
|
|
402
|
+
"6": "卓尔游侠",
|
|
403
|
+
"7": "撼地者",
|
|
404
|
+
"8": "主宰",
|
|
405
|
+
"9": "米拉娜",
|
|
406
|
+
"10": "变体精灵",
|
|
407
|
+
"11": "影魔",
|
|
408
|
+
"12": "幻影长矛手",
|
|
409
|
+
"13": "帕克",
|
|
410
|
+
"14": "帕吉",
|
|
411
|
+
"15": "雷泽",
|
|
412
|
+
"16": "沙王",
|
|
413
|
+
"17": "风暴之灵",
|
|
414
|
+
"18": "斯温",
|
|
415
|
+
"19": "小小",
|
|
416
|
+
"20": "复仇之魂",
|
|
417
|
+
"21": "风行者",
|
|
418
|
+
"22": "宙斯",
|
|
419
|
+
"23": "昆卡",
|
|
420
|
+
"25": "莉娜",
|
|
421
|
+
"26": "莱恩",
|
|
422
|
+
"27": "暗影萨满",
|
|
423
|
+
"28": "斯拉达",
|
|
424
|
+
"29": "潮汐猎人",
|
|
425
|
+
"30": "巫医",
|
|
426
|
+
"31": "巫妖",
|
|
427
|
+
"32": "力丸",
|
|
428
|
+
"33": "谜团",
|
|
429
|
+
"34": "修补匠",
|
|
430
|
+
"35": "狙击手",
|
|
431
|
+
"36": "瘟疫法师",
|
|
432
|
+
"37": "术士",
|
|
433
|
+
"38": "兽王",
|
|
434
|
+
"39": "痛苦女王",
|
|
435
|
+
"40": "剧毒术士",
|
|
436
|
+
"41": "虚空假面",
|
|
437
|
+
"42": "冥魂大帝",
|
|
438
|
+
"43": "死亡先知",
|
|
439
|
+
"44": "幻影刺客",
|
|
440
|
+
"45": "帕格纳",
|
|
441
|
+
"46": "圣堂刺客",
|
|
442
|
+
"47": "冥界亚龙",
|
|
443
|
+
"48": "露娜",
|
|
444
|
+
"49": "龙骑士",
|
|
445
|
+
"50": "戴泽",
|
|
446
|
+
"51": "发条技师",
|
|
447
|
+
"52": "拉席克",
|
|
448
|
+
"53": "先知",
|
|
449
|
+
"54": "噬魂鬼",
|
|
450
|
+
"55": "黑暗贤者",
|
|
451
|
+
"56": "克林克兹",
|
|
452
|
+
"57": "全能骑士",
|
|
453
|
+
"58": "魅惑魔女",
|
|
454
|
+
"59": "哈斯卡",
|
|
455
|
+
"60": "暗夜魔王",
|
|
456
|
+
"61": "育母蜘蛛",
|
|
457
|
+
"62": "赏金猎人",
|
|
458
|
+
"63": "编织者",
|
|
459
|
+
"64": "杰奇洛",
|
|
460
|
+
"65": "蝙蝠骑士",
|
|
461
|
+
"66": "陈",
|
|
462
|
+
"67": "幽鬼",
|
|
463
|
+
"68": "远古冰魄",
|
|
464
|
+
"69": "末日使者",
|
|
465
|
+
"70": "熊战士",
|
|
466
|
+
"71": "裂魂人",
|
|
467
|
+
"72": "矮人直升机",
|
|
468
|
+
"73": "炼金术士",
|
|
469
|
+
"74": "祈求者",
|
|
470
|
+
"75": "沉默术士",
|
|
471
|
+
"76": "殁境神蚀者",
|
|
472
|
+
"77": "狼人",
|
|
473
|
+
"78": "酒仙",
|
|
474
|
+
"79": "暗影恶魔",
|
|
475
|
+
"80": "德鲁伊",
|
|
476
|
+
"81": "混沌骑士",
|
|
477
|
+
"82": "米波",
|
|
478
|
+
"83": "树精卫士",
|
|
479
|
+
"84": "食人魔魔法师",
|
|
480
|
+
"85": "不朽尸王",
|
|
481
|
+
"86": "拉比克",
|
|
482
|
+
"87": "干扰者",
|
|
483
|
+
"88": "司夜刺客",
|
|
484
|
+
"89": "娜迦海妖",
|
|
485
|
+
"90": "光之守卫",
|
|
486
|
+
"91": "艾欧",
|
|
487
|
+
"92": "维萨吉",
|
|
488
|
+
"93": "斯拉克",
|
|
489
|
+
"94": "美杜莎",
|
|
490
|
+
"95": "巨魔战将",
|
|
491
|
+
"96": "半人马战行者",
|
|
492
|
+
"97": "马格纳斯",
|
|
493
|
+
"98": "伐木机",
|
|
494
|
+
"99": "钢背兽",
|
|
495
|
+
"100": "巨牙海民",
|
|
496
|
+
"101": "天怒法师",
|
|
497
|
+
"102": "亚巴顿",
|
|
498
|
+
"103": "上古巨神",
|
|
499
|
+
"104": "军团指挥官",
|
|
500
|
+
"105": "工程师",
|
|
501
|
+
"106": "灰烬之灵",
|
|
502
|
+
"107": "大地之灵",
|
|
503
|
+
"108": "孽主",
|
|
504
|
+
"109": "恐怖利刃",
|
|
505
|
+
"110": "凤凰",
|
|
506
|
+
"111": "神谕者",
|
|
507
|
+
"112": "寒冬飞龙",
|
|
508
|
+
"113": "天穹守望者",
|
|
509
|
+
"114": "齐天大圣",
|
|
510
|
+
"119": "邪影芳灵",
|
|
511
|
+
"120": "石鳞剑士",
|
|
512
|
+
"121": "天涯墨客",
|
|
513
|
+
"123": "森海飞霞",
|
|
514
|
+
"126": "虚无之灵",
|
|
515
|
+
"128": "电炎绝手",
|
|
516
|
+
"129": "玛尔斯",
|
|
517
|
+
"131": "百戏大王",
|
|
518
|
+
"135": "破晓辰星",
|
|
519
|
+
"136": "玛西",
|
|
520
|
+
"137": "獸",
|
|
521
|
+
"138": "琼英碧灵",
|
|
522
|
+
"145": "凯"
|
|
523
|
+
},
|
|
524
|
+
behavior: {
|
|
525
|
+
"Unit Target": "单位目标",
|
|
526
|
+
Channeled: "持续施法",
|
|
527
|
+
Hidden: "默认隐藏",
|
|
528
|
+
Passive: "被动",
|
|
529
|
+
"No Target": "无目标",
|
|
530
|
+
Autocast: "自动施法",
|
|
531
|
+
"Instant Cast": "即时施法",
|
|
532
|
+
"Point Target": "点目标",
|
|
533
|
+
"Attack Modifier": "攻击特效",
|
|
534
|
+
AOE: "范围生效"
|
|
535
|
+
},
|
|
536
|
+
target_team: {
|
|
537
|
+
Enemy: "敌方单位",
|
|
538
|
+
Both: "单位",
|
|
539
|
+
Friendly: "友方单位"
|
|
540
|
+
},
|
|
541
|
+
ability: "技能:",
|
|
542
|
+
affects: "影响:",
|
|
543
|
+
damage_type: "伤害类型:",
|
|
544
|
+
damage_type_Physical: "物理",
|
|
545
|
+
damage_type_Magical: "魔法",
|
|
546
|
+
damage_type_Pure: "纯粹",
|
|
547
|
+
dispellable: "能否驱散:",
|
|
548
|
+
Yes: "是",
|
|
549
|
+
No: "否",
|
|
550
|
+
dispellable_Strong: "仅强驱散",
|
|
551
|
+
bkbpierce: "无视减益免疫:",
|
|
552
|
+
innate: "先天技能",
|
|
553
|
+
scepter: "阿哈利姆神杖",
|
|
554
|
+
shard: "阿哈利姆魔晶",
|
|
555
|
+
attack: "进攻",
|
|
556
|
+
defense: "防守",
|
|
557
|
+
mobility: "机动"
|
|
558
|
+
}
|
|
559
|
+
}
|
|
560
|
+
};
|
|
561
|
+
}
|
|
562
|
+
});
|
|
563
|
+
|
|
564
|
+
// src/locales/en-US.command.yml
|
|
565
|
+
var require_en_US_command = __commonJS({
|
|
566
|
+
"src/locales/en-US.command.yml"(exports2, module2) {
|
|
567
|
+
module2.exports = { commands: { subscribe: { description: "After subscribing, players need to bind their Steam ID to this group.", usage: "After subscribing, players need to bind their Steam ID to this group. BOT will subscribe to the new game data of bound players in this group. After the STRATZ game analysis is completed, the game data will be generated into a picture battle report and published to this group.", messages: { subscribe_success: "Subscription successful.", subscribed: "This Channel has been subscribed, no need to subscribe again." } }, unsubscribe: { description: "Unsubscribe from this group.", messages: { unsubscribe_success: "Unsubscription successful.", not_subscribed: "This Channel has not been subscribed yet, so there is no need to unsubscribe." } } } };
|
|
568
|
+
}
|
|
569
|
+
});
|
|
570
|
+
|
|
571
|
+
// src/locales/en-US.template.yml
|
|
572
|
+
var require_en_US_template = __commonJS({
|
|
573
|
+
"src/locales/en-US.template.yml"(exports2, module2) {
|
|
574
|
+
module2.exports = { dota2tracker: { template: { radiant: "Radiant", dire: "Dire", won: "Won", lost: "Lost", match_id_: "Match ID: {0}", game_mode_: "Mode: {0}", start_time_: "Start Time: {0}", end_time_: "End Time: {0}", pick_order: "#{0}", random: "R", hero_damage_: "Damage: {0}", building_damage_: "Building: {0}", damage_received_: "Received: {0}", lasthit_: "LastHit: {0}", deny_: "Deny: {0}", "lh/dn_": "LH/DN: {0}", GPM: "GPM", XPM: "XPM", heal_: "Heal: {0}", crowd_control_duration_: "CCD: {0}", "GPM/XPM_": "GPM/XPM: {0}", lane: "Lane", lane_: "Lane: ", lane_advantage: "Lane +", lane_disadvantage: "Lane -", lane_jungle: "Jungle", lane_stomp: "Lane+++", lane_stomped: "Lane---", lane_tie: "Lane ==", analysis_successful: "Analysis successful", analysis_incomplete: "Analysis incomplete", kill: "Kill", kill_contribution_: "KC: {0}", position: "Position", position_: "Position: ", position_1: "Carry", position_2: "Mid", position_3: "OffLane", position_4: "Softsup", position_5: "Hardsup", dire_won: "Dire Won", radiant_won: "Radiant Won", total_damage: "Damage", total_experience: "Exp.", total_gold: "Gold", region_: "Region: {0}", duration_: "Duration: {0}", position_undefined: "?", top10_: "Top 10 Heroes by Matches: ", match_count_: "Matches: ", last25matches_: "Last 25 Matches: ", winrate_: "Winrate: ", imp_: "IMP: ", lane_advantage_rate_: "Lane Advantage Rate: ", hero: "Hero", all_matches_: "All Matches: ", match_count: "Matches", winrate: "Winrate", imp: "IMP", win_count: "Wins", lose_count: "Losses", recently_heroes: "Heroes used more than once recently: ", recently_positions: "Performance in the last 25 matches across all positions: ", winning_streak: "Winning Streak", losing_streak: "Losing Streak", id: "ID", mode: "Mode", kda_kc: "KDA(KC)", time: "Time", duration: "Duration", rank: "Rank", un_parsed: "(Unparsed)" } } };
|
|
37
575
|
}
|
|
38
576
|
});
|
|
39
577
|
|
|
40
578
|
// src/locales/en-US.yml
|
|
41
579
|
var require_en_US = __commonJS({
|
|
42
580
|
"src/locales/en-US.yml"(exports2, module2) {
|
|
43
|
-
module2.exports = { dota2tracker: {
|
|
581
|
+
module2.exports = { dota2tracker: { heroes_nicknames: { "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"' }, broadcast: { WIN_NEGATIVE: `"Won the match by sheer luck", "Won the match by a stroke of bad luck", "Coasted to victory", "Didn't even show up for the team fight, but my teammates won 4v5"`, WIN_POSITIVE: '"Led the team to victory", "Dominated the opponents and secured the win", "Carried the game to victory", "Treated the opponents like pigs and won", "Won again; this game is just so monotonous and dull", "Simply achieved a win in the match"', LOSE_NEGATIVE: '"Got crushed and lost the match", "Lost the match miserably", "Got my head knocked sideways and lost the match with a blown mindset", "Went fishing but got eaten by the fish, lost the match", "Played terribly", "Simply suffered a loss in the match"', LOSE_POSITIVE: `"Lost the match with no way to turn it around", "Gave it my all, but still lost the match", "Though we lost, we still have honor", "Couldn't carry my teammates, lost the match", "Lost again, it hurts; I'd rather it be me losing"`, message: "{name}'s {hero_name} {comment}.\nKDA: {kda}, GPM/XPM: {gpm_xpm}, Last Hits/Denies: {lh_dn}, Damage/Tower Damage: {damage}, Kill/Death Contribution Rate: {kc_dc}" } } };
|
|
582
|
+
}
|
|
583
|
+
});
|
|
584
|
+
|
|
585
|
+
// src/locales/zh-CN.command.yml
|
|
586
|
+
var require_zh_CN_command = __commonJS({
|
|
587
|
+
"src/locales/zh-CN.command.yml"(exports2, module2) {
|
|
588
|
+
module2.exports = { commands: { subscribe: { description: "订阅后还需玩家在本群绑定SteamID", usage: "订阅后还需玩家在本群绑定SteamID,BOT将订阅本群中已绑定玩家的新比赛数据,在STRATZ比赛解析完成后将比赛数据生成为图片战报发布至本群中。", messages: { subscribed: "本群已订阅,无需重复订阅。", subscribe_success: "订阅成功。" } }, unsubscribe: { description: "取消订阅本群。", messages: { unsubscribe_success: "取消订阅成功。", not_subscribed: "本群尚未订阅,无需取消订阅。" } } } };
|
|
589
|
+
}
|
|
590
|
+
});
|
|
591
|
+
|
|
592
|
+
// src/locales/zh-CN.template.yml
|
|
593
|
+
var require_zh_CN_template = __commonJS({
|
|
594
|
+
"src/locales/zh-CN.template.yml"(exports2, module2) {
|
|
595
|
+
module2.exports = { dota2tracker: { template: { radiant: "天辉", dire: "夜魇", won: "获胜", lost: "失败", match_id_: "比赛编号:{0}", game_mode_: "模式:{0}", start_time_: "起始时间:{0}", end_time_: "结束时间:{0}", pick_order: "第{0}手", random: "随机", hero_damage_: "英雄伤害:{0}", building_damage_: "建筑伤害:{0}", damage_received_: "受到伤害:{0}", lasthit_: "补刀:{0}", deny_: "反补:{0}", "lh/dn_": "补刀:{0}/{1}", GPM: "GPM", XPM: "XPM", heal_: "治疗量:{0}", crowd_control_duration_: "控制时间:{0}", "GPM/XPM_": "GPM/XPM:{0}", lane: "对线", lane_: "对线:", lane_advantage: "对线优势", lane_disadvantage: "对线劣势", lane_stomp: "对线碾压", lane_stomped: "对线被碾", lane_tie: "对线平手", lane_jungle: "野区霸主", analysis_successful: "录像分析成功", analysis_incomplete: "分析结果不完整", kill: "击杀", kill_contribution_: "参战率:{0}", position: "位置", position_: "位置:", position_1: "优势路", position_2: "中路", position_3: "烈士路", position_4: "采灵芝", position_5: "工具人", position_undefined: "?", total_damage: "总伤害", total_gold: "总经济", total_experience: "总经验", radiant_won: "天辉获胜", dire_won: "夜魇获胜", duration_: "持续时间:{0}", region_: "地区:{0}", match_count_: "场次:", last25matches_: "最近25场:", winrate_: "胜率:", imp_: "表现:", lane_advantage_rate_: "线优率:", top10_: "全期场次前十的英雄:", hero: "英雄", all_matches_: "全期场次:", match_count: "场次", winrate: "胜率", imp: "表现", win_count: "胜场", lose_count: "败场", recently_heroes: "近期使用场次大于1的英雄:", recently_positions: "近25场各个位置的表现:", winning_streak: "连胜", losing_streak: "连败", id: "ID", mode: "模式", kda_kc: "KDA(参战率)", time: "时间", duration: "时长", rank: "段位", un_parsed: "(未解析)" } } };
|
|
596
|
+
}
|
|
597
|
+
});
|
|
598
|
+
|
|
599
|
+
// src/locales/zh-CN.yml
|
|
600
|
+
var require_zh_CN = __commonJS({
|
|
601
|
+
"src/locales/zh-CN.yml"(exports2, module2) {
|
|
602
|
+
module2.exports = { dota2tracker: { heroes_nicknames: { "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": '"凯", "鸟人"' }, broadcast: { WIN_NEGATIVE: '"侥幸赢得了比赛", "走狗屎运赢得了比赛", "躺赢了比赛", "打团都没来, 队友4V5赢得了比赛"', WIN_POSITIVE: '"带领团队走向了胜利", "暴打对面后赢得了胜利", " CARRY全场赢得了胜利", "把对面当猪宰了, 赢得了胜利", "又赢了, 这游戏就是这么枯燥, 且乏味", "直接进行一个比赛的赢"', LOSE_NEGATIVE: '"被人按在地上摩擦, 输掉了这场比赛", "悲惨地输掉了比赛", "头都被打歪了, 心态爆炸地输掉了比赛", "捕鱼被鱼吃了, 输掉了比赛", "打的是个几把", "直接进行一个比赛的输"', LOSE_POSITIVE: '"无力回天输掉了比赛", "尽力了, 但还是输了比赛", "背靠世界树, 虽败犹荣", "带不动队友, 输了比赛", "又输了, 很难受, 宁愿输的是我"', message: "{name}的{hero_name}{comment}。\nKDA:{kda},GPM/XPM:{gpm_xpm},补刀/反补:{lh_dn},伤害/塔伤:{damage},参战/参葬率:{kc_dc}" } } };
|
|
44
603
|
}
|
|
45
604
|
});
|
|
46
605
|
|
|
@@ -82,9 +641,10 @@ var import_path = __toESM(require("path"));
|
|
|
82
641
|
var CONFIGS = { STRATZ_API: { URL: "https://api.stratz.com/graphql", TOKEN: "" } };
|
|
83
642
|
var http = null;
|
|
84
643
|
var setTimeout;
|
|
85
|
-
function init(newHttp, newSetTimeout) {
|
|
644
|
+
function init(newHttp, newSetTimeout, APIKEY) {
|
|
86
645
|
http = newHttp;
|
|
87
646
|
setTimeout = newSetTimeout;
|
|
647
|
+
CONFIGS.STRATZ_API.TOKEN = APIKEY;
|
|
88
648
|
}
|
|
89
649
|
__name(init, "init");
|
|
90
650
|
async function fetchData(query2) {
|
|
@@ -148,6 +708,7 @@ var ImageType = /* @__PURE__ */ ((ImageType2) => {
|
|
|
148
708
|
ImageType2["IconsFacets"] = "icons/facets";
|
|
149
709
|
ImageType2["Heroes"] = "heroes";
|
|
150
710
|
ImageType2["HeroIcons"] = "heroes/icons";
|
|
711
|
+
ImageType2["HeroStats"] = "heroes/stats";
|
|
151
712
|
ImageType2["Items"] = "items";
|
|
152
713
|
ImageType2["Abilities"] = "abilities";
|
|
153
714
|
ImageType2["Local"] = "local";
|
|
@@ -172,11 +733,11 @@ function getImageUrl(image, type = "local" /* Local */, format = "png" /* png */
|
|
|
172
733
|
} else return `https://cdn.cloudflare.steamstatic.com/apps/dota2/images/dota_react/${type}/${image}.${format}`;
|
|
173
734
|
}
|
|
174
735
|
__name(getImageUrl, "getImageUrl");
|
|
175
|
-
function getFormattedMatchData(
|
|
176
|
-
const match =
|
|
177
|
-
const constants =
|
|
736
|
+
function getFormattedMatchData(matchQuery, constantsQuery) {
|
|
737
|
+
const match = matchQuery.match;
|
|
738
|
+
const constants = constantsQuery.constants;
|
|
178
739
|
["radiant", "dire"].forEach((team) => {
|
|
179
|
-
match[team] = { killsCount: match[team + "Kills"]?.reduce((acc, cva) => acc + cva, 0) ?? 0, damageReceived: 0, heroDamage: 0, networth: 0, experience: 0 };
|
|
740
|
+
match[team] = { killsCount: match?.[team + "Kills"]?.reduce((acc, cva) => acc + cva, 0) ?? 0, damageReceived: 0, heroDamage: 0, networth: 0, experience: 0 };
|
|
180
741
|
});
|
|
181
742
|
if (!match.parsedDateTime) {
|
|
182
743
|
match.players.reduce((acc, player) => {
|
|
@@ -198,11 +759,11 @@ function getFormattedMatchData(data) {
|
|
|
198
759
|
let processLaneOutcome = /* @__PURE__ */ __name(function(outcome) {
|
|
199
760
|
switch (outcome) {
|
|
200
761
|
case "RADIANT_VICTORY":
|
|
201
|
-
return { radiant: "
|
|
762
|
+
return { radiant: "advantage", dire: "disadvantage" };
|
|
202
763
|
case "RADIANT_STOMP":
|
|
203
764
|
return { radiant: "stomp", dire: "stomped" };
|
|
204
765
|
case "DIRE_VICTORY":
|
|
205
|
-
return { radiant: "
|
|
766
|
+
return { radiant: "disadvantage", dire: "advantage" };
|
|
206
767
|
case "DIRE_STOMP":
|
|
207
768
|
return { radiant: "stomped", dire: "stomp" };
|
|
208
769
|
default:
|
|
@@ -222,7 +783,7 @@ function getFormattedMatchData(data) {
|
|
|
222
783
|
inTop100: player.steamAccount.seasonLeaderboardRank ? player.steamAccount.seasonLeaderboardRank <= 10 ? "8c" : player.steamAccount.seasonLeaderboardRank <= 100 ? "8b" : void 0 : void 0
|
|
223
784
|
};
|
|
224
785
|
player.killContribution = (player.kills + player.assists) / match[player.team].killsCount;
|
|
225
|
-
player.deathContribution = player.deaths / match[player.team === "radiant" ? "dire" :
|
|
786
|
+
player.deathContribution = player.deaths / match[player.team === "radiant" ? "dire" : "radiant"].killsCount;
|
|
226
787
|
player.damageReceived = (player.stats?.heroDamageReport?.receivedTotal?.physicalDamage ?? 0) + (player.stats?.heroDamageReport?.receivedTotal?.magicalDamage ?? 0) + (player.stats?.heroDamageReport?.receivedTotal?.pureDamage ?? 0);
|
|
227
788
|
match[player.team].heroDamage = (match[player.team].heroDamage ?? 0) + player.heroDamage;
|
|
228
789
|
match[player.team].damageReceived = (match[player.team].damageReceived ?? 0) + player.damageReceived;
|
|
@@ -419,7 +980,7 @@ function getFormattedMatchData(data) {
|
|
|
419
980
|
)?.titles.push({ name: "魂", color: "#6cf" });
|
|
420
981
|
findMaxByProperty("networth")?.titles.push({ name: "富", color: "#FFD700" });
|
|
421
982
|
findMaxByProperty("experiencePerMinute")?.titles.push({ name: "睿", color: "#8888FF" });
|
|
422
|
-
if (match.parsedDateTime) {
|
|
983
|
+
if (match.parsedDateTime && match.players.every((player) => player?.stats?.heroDamageReport?.dealtTotal)) {
|
|
423
984
|
match.players.reduce(
|
|
424
985
|
(max, player) => player.stats.heroDamageReport.dealtTotal.stunDuration + player.stats.heroDamageReport.dealtTotal.disableDuration / 2 + player.stats.heroDamageReport.dealtTotal.slowDuration / 4 > max.stats.heroDamageReport.dealtTotal.stunDuration + max.stats.heroDamageReport.dealtTotal.disableDuration / 2 + max.stats.heroDamageReport.dealtTotal.slowDuration / 4 ? player : max
|
|
425
986
|
).titles.push({ name: "控", color: "#FF00FF" });
|
|
@@ -546,417 +1107,47 @@ var import_fs2 = __toESM(require("fs"));
|
|
|
546
1107
|
var import_path2 = __toESM(require("path"));
|
|
547
1108
|
var import_moment = __toESM(require("moment"));
|
|
548
1109
|
var dotaconstants2 = __toESM(require("dotaconstants"));
|
|
1110
|
+
var import_koishi2 = require("koishi");
|
|
1111
|
+
var ejs = __toESM(require("ejs"));
|
|
549
1112
|
|
|
550
|
-
// src/
|
|
551
|
-
var
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
1113
|
+
// require("./locales/**/*.constants.json") in src/index.ts
|
|
1114
|
+
var globRequire_locales_constants_json = __glob({
|
|
1115
|
+
"./locales/en-US.constants.json": () => require_en_US_constants(),
|
|
1116
|
+
"./locales/zh-CN.constants.json": () => require_zh_CN_constants()
|
|
1117
|
+
});
|
|
1118
|
+
|
|
1119
|
+
// require("./locales/**/*.yml") in src/index.ts
|
|
1120
|
+
var globRequire_locales_yml = __glob({
|
|
1121
|
+
"./locales/en-US.command.yml": () => require_en_US_command(),
|
|
1122
|
+
"./locales/en-US.template.yml": () => require_en_US_template(),
|
|
1123
|
+
"./locales/en-US.yml": () => require_en_US(),
|
|
1124
|
+
"./locales/zh-CN.command.yml": () => require_zh_CN_command(),
|
|
1125
|
+
"./locales/zh-CN.template.yml": () => require_zh_CN_template(),
|
|
1126
|
+
"./locales/zh-CN.yml": () => require_zh_CN()
|
|
1127
|
+
});
|
|
1128
|
+
|
|
1129
|
+
// require("./locales/**/*.command.yml") in src/index.ts
|
|
1130
|
+
var globRequire_locales_command_yml = __glob({
|
|
1131
|
+
"./locales/en-US.command.yml": () => require_en_US_command(),
|
|
1132
|
+
"./locales/zh-CN.command.yml": () => require_zh_CN_command()
|
|
1133
|
+
});
|
|
1134
|
+
|
|
1135
|
+
// require("./locales/**/*.template.yml") in src/index.ts
|
|
1136
|
+
var globRequire_locales_template_yml = __glob({
|
|
1137
|
+
"./locales/en-US.template.yml": () => require_en_US_template(),
|
|
1138
|
+
"./locales/zh-CN.template.yml": () => require_zh_CN_template()
|
|
568
1139
|
});
|
|
569
|
-
var gameMode = {
|
|
570
|
-
NONE: "",
|
|
571
|
-
ALL_PICK: "全英雄选择",
|
|
572
|
-
CAPTAINS_MODE: "队长模式",
|
|
573
|
-
RANDOM_DRAFT: "随机征召",
|
|
574
|
-
SINGLE_DRAFT: "单一征召",
|
|
575
|
-
ALL_RANDOM: "全英雄随机",
|
|
576
|
-
INTRO: "",
|
|
577
|
-
THE_DIRETIDE: "",
|
|
578
|
-
REVERSE_CAPTAINS_MODE: "",
|
|
579
|
-
THE_GREEVILING: "",
|
|
580
|
-
TUTORIAL: "教程模式",
|
|
581
|
-
MID_ONLY: "",
|
|
582
|
-
LEAST_PLAYED: "",
|
|
583
|
-
NEW_PLAYER_POOL: "",
|
|
584
|
-
COMPENDIUM_MATCHMAKING: "",
|
|
585
|
-
CUSTOM: "",
|
|
586
|
-
CAPTAINS_DRAFT: "",
|
|
587
|
-
BALANCED_DRAFT: "",
|
|
588
|
-
ABILITY_DRAFT: "",
|
|
589
|
-
EVENT: "",
|
|
590
|
-
ALL_RANDOM_DEATH_MATCH: "",
|
|
591
|
-
SOLO_MID: "",
|
|
592
|
-
ALL_PICK_RANKED: "全英雄选择",
|
|
593
|
-
TURBO: "加速模式",
|
|
594
|
-
MUTATION: "",
|
|
595
|
-
UNKNOWN: ""
|
|
596
|
-
};
|
|
597
|
-
var lobbyTypes = {
|
|
598
|
-
INVALID: "",
|
|
599
|
-
UNRANKED: "非天梯",
|
|
600
|
-
PRACTICE: "",
|
|
601
|
-
TOURNAMENT: "",
|
|
602
|
-
TUTORIAL: "",
|
|
603
|
-
COOP_VS_BOTS: "",
|
|
604
|
-
TEAM_MATCH: "",
|
|
605
|
-
SOLO_QUEUE: "",
|
|
606
|
-
RANKED: "天梯比赛",
|
|
607
|
-
SOLO_MID: "",
|
|
608
|
-
BATTLE_CUP: "",
|
|
609
|
-
EVENT: "",
|
|
610
|
-
NEW_PLAYER_POOL: ""
|
|
611
|
-
};
|
|
612
|
-
var region = {
|
|
613
|
-
"1": "US WEST",
|
|
614
|
-
"2": "US EAST",
|
|
615
|
-
"3": "EUROPE",
|
|
616
|
-
"5": "新加坡",
|
|
617
|
-
"6": "DUBAI",
|
|
618
|
-
"7": "AUSTRALIA",
|
|
619
|
-
"8": "STOCKHOLM",
|
|
620
|
-
"9": "AUSTRIA",
|
|
621
|
-
"10": "BRAZIL",
|
|
622
|
-
"11": "SOUTHAFRICA",
|
|
623
|
-
"12": "电信(上海)",
|
|
624
|
-
"13": "联通(一)",
|
|
625
|
-
"14": "CHILE",
|
|
626
|
-
"15": "PERU",
|
|
627
|
-
"16": "INDIA",
|
|
628
|
-
"17": "电信(广东)",
|
|
629
|
-
"18": "电信(浙江)",
|
|
630
|
-
"19": "日本",
|
|
631
|
-
"20": "电信(华中)",
|
|
632
|
-
"25": "联通(二)",
|
|
633
|
-
"37": "TAIWAN",
|
|
634
|
-
"38": "ARGENTINA"
|
|
635
|
-
};
|
|
636
|
-
var position = {
|
|
637
|
-
"1": "优势路",
|
|
638
|
-
"2": "中路",
|
|
639
|
-
"3": "烈士路",
|
|
640
|
-
"4": "采灵芝",
|
|
641
|
-
"5": "工具人"
|
|
642
|
-
};
|
|
643
|
-
var rank = {
|
|
644
|
-
"0": "未知",
|
|
645
|
-
"1": "先锋",
|
|
646
|
-
"2": "卫士",
|
|
647
|
-
"3": "中军",
|
|
648
|
-
"4": "统帅",
|
|
649
|
-
"5": "传奇",
|
|
650
|
-
"6": "万古流芳",
|
|
651
|
-
"7": "超凡入圣",
|
|
652
|
-
"8": "冠绝一世"
|
|
653
|
-
};
|
|
654
|
-
var roles = ["核心", "辅助", "爆发", "控制", "打野", "耐久", "逃生", "推进", "先手"];
|
|
655
|
-
var primary_attrs = { "3": "hero_universal", "0": "hero_strength", "1": "hero_agility", "2": "hero_intelligence" };
|
|
656
|
-
var behavior = {
|
|
657
|
-
"Unit Target": "单位目标",
|
|
658
|
-
Channeled: "持续施法",
|
|
659
|
-
Hidden: "默认隐藏",
|
|
660
|
-
Passive: "被动",
|
|
661
|
-
"No Target": "无目标",
|
|
662
|
-
Autocast: "自动施法",
|
|
663
|
-
"Instant Cast": "即时施法",
|
|
664
|
-
"Point Target": "点目标",
|
|
665
|
-
"Attack Modifier": "攻击特效",
|
|
666
|
-
AOE: "范围生效"
|
|
667
|
-
};
|
|
668
|
-
var target_team = { Enemy: "敌方单位", Both: "单位", Friendly: "友方单位" };
|
|
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
|
-
}
|
|
926
|
-
};
|
|
927
|
-
var WIN_NEGATIVE = ["侥幸赢得了比赛", "走狗屎运赢得了比赛", "躺赢了比赛", "打团都没来, 队友4V5赢得了比赛"];
|
|
928
|
-
var WIN_POSITIVE = ["带领团队走向了胜利", "暴打对面后赢得了胜利", " CARRY全场赢得了胜利", "把对面当猪宰了, 赢得了胜利", "又赢了, 这游戏就是这么枯燥, 且乏味", "直接进行一个比赛的赢"];
|
|
929
|
-
var LOSE_NEGATIVE = ["被人按在地上摩擦, 输掉了这场比赛", "悲惨地输掉了比赛", "头都被打歪了, 心态爆炸地输掉了比赛", "捕鱼被鱼吃了, 输掉了比赛", "打的是个几把", "直接进行一个比赛的输"];
|
|
930
|
-
var LOSE_POSITIVE = ["无力回天输掉了比赛", "尽力了, 但还是输了比赛", "背靠世界树, 虽败犹荣", "带不动队友, 输了比赛", "又输了, 很难受, 宁愿输的是我"];
|
|
931
|
-
var dotaconstants_add_default = {
|
|
932
|
-
gameMode,
|
|
933
|
-
lobbyTypes,
|
|
934
|
-
region,
|
|
935
|
-
position,
|
|
936
|
-
rank,
|
|
937
|
-
roles,
|
|
938
|
-
primary_attrs,
|
|
939
|
-
behavior,
|
|
940
|
-
target_team,
|
|
941
|
-
HEROES_NAMES,
|
|
942
|
-
WIN_NEGATIVE,
|
|
943
|
-
WIN_POSITIVE,
|
|
944
|
-
LOSE_NEGATIVE,
|
|
945
|
-
LOSE_POSITIVE
|
|
946
|
-
};
|
|
947
1140
|
|
|
948
1141
|
// src/index.ts
|
|
949
|
-
var import_koishi2 = require("koishi");
|
|
950
|
-
var ejs = __toESM(require("ejs"));
|
|
951
1142
|
var name = "dota2tracker";
|
|
952
1143
|
var usage = `
|
|
953
1144
|
DOTA2Bot插件-提供自动追踪群友的最新对局的功能(需群友绑定),以及一系列查询功能。
|
|
954
|
-
[本地化/dota2tracker](../../locales/dota2tracker)
|
|
1145
|
+
[本地化/dota2tracker](../../locales/dota2tracker)可以自定义英雄别名和位置代称等文本内容
|
|
955
1146
|
**更多信息请进入[插件主页](https://github.com/sjtdev/koishi-plugin-dota2tracker)与[更新日志](https://github.com/sjtdev/koishi-plugin-dota2tracker/blob/master/changelog.md)查看。**`;
|
|
956
|
-
var inject = ["http", "database", "cron", "puppeteer"];
|
|
1147
|
+
var inject = ["http", "database", "cron", "puppeteer", "cache"];
|
|
957
1148
|
var Config = import_koishi.Schema.intersect([
|
|
958
1149
|
import_koishi.Schema.object({
|
|
959
|
-
STRATZ_API_TOKEN: import_koishi.Schema.string().required().description("※必须。stratz.com的API TOKEN,可在 https://stratz.com/api 获取。"),
|
|
1150
|
+
STRATZ_API_TOKEN: import_koishi.Schema.string().required().role("secret").description("※必须。stratz.com的API TOKEN,可在 https://stratz.com/api 获取。"),
|
|
960
1151
|
dataParsingTimeoutMinutes: import_koishi.Schema.number().default(60).min(0).max(1440).description("等待比赛数据解析的时间(单位:分钟)。如果数据解析时间超过等待时间,将直接生成战报而不再等待解析完成。"),
|
|
961
1152
|
urlInMessageType: import_koishi.Schema.array(
|
|
962
1153
|
import_koishi.Schema.union([
|
|
@@ -1012,36 +1203,56 @@ var Config = import_koishi.Schema.intersect([
|
|
|
1012
1203
|
]);
|
|
1013
1204
|
var pendingMatches = [];
|
|
1014
1205
|
var random = new import_koishi2.Random(() => Math.random());
|
|
1206
|
+
var days_30 = 2592e6;
|
|
1207
|
+
var GraphqlLanguageEnum = /* @__PURE__ */ ((GraphqlLanguageEnum2) => {
|
|
1208
|
+
GraphqlLanguageEnum2["en-US"] = "ENGLISH";
|
|
1209
|
+
GraphqlLanguageEnum2["zh-CN"] = "S_CHINESE";
|
|
1210
|
+
return GraphqlLanguageEnum2;
|
|
1211
|
+
})(GraphqlLanguageEnum || {});
|
|
1212
|
+
var constantLocales = {};
|
|
1015
1213
|
async function apply(ctx, config) {
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1214
|
+
init(ctx.http, ctx.setTimeout, config.STRATZ_API_TOKEN);
|
|
1215
|
+
for (const supportLanguageTag of Object.keys(GraphqlLanguageEnum)) {
|
|
1216
|
+
constantLocales[supportLanguageTag] = globRequire_locales_constants_json(`./locales/${supportLanguageTag}.constants.json`);
|
|
1217
|
+
ctx.i18n.define(supportLanguageTag, globRequire_locales_yml(`./locales/${supportLanguageTag}.yml`));
|
|
1218
|
+
ctx.i18n.define(supportLanguageTag, globRequire_locales_command_yml(`./locales/${supportLanguageTag}.command.yml`));
|
|
1219
|
+
ctx.i18n.define(supportLanguageTag, globRequire_locales_template_yml(`./locales/${supportLanguageTag}.template.yml`));
|
|
1220
|
+
}
|
|
1221
|
+
const getLanguageTag = /* @__PURE__ */ __name(async function(session, channel, channelId) {
|
|
1222
|
+
const resolvedChannel = channel ?? (await ctx.database.get("channel", { id: session?.event.channel.id ?? channelId }))?.at(0);
|
|
1223
|
+
return ctx.i18n.fallback((resolvedChannel?.locales ?? []).concat(Object.values(ctx.i18n.locales).map((locale) => Object.keys(locale).at(0)))).find((locale) => Object.keys(GraphqlLanguageEnum).some((language) => locale == language));
|
|
1025
1224
|
}, "getLanguageTag");
|
|
1026
|
-
ctx.command("
|
|
1225
|
+
ctx.command("subscribe").alias("订阅本群").action(async ({ session }) => {
|
|
1027
1226
|
if (session.guild) {
|
|
1028
|
-
let currentGuild = (await ctx.database.get("dt_subscribed_guilds", {
|
|
1029
|
-
|
|
1227
|
+
let currentGuild = (await ctx.database.get("dt_subscribed_guilds", {
|
|
1228
|
+
guildId: session.event.channel.id,
|
|
1229
|
+
platform: session.event.platform
|
|
1230
|
+
}))[0];
|
|
1231
|
+
if (currentGuild) session.send(session.text(".subscribed"));
|
|
1030
1232
|
else {
|
|
1031
|
-
ctx.database.create("dt_subscribed_guilds", {
|
|
1032
|
-
|
|
1233
|
+
ctx.database.create("dt_subscribed_guilds", {
|
|
1234
|
+
guildId: session.event.channel.id,
|
|
1235
|
+
platform: session.event.platform
|
|
1236
|
+
});
|
|
1237
|
+
session.send(session.text(".subscribe_success"));
|
|
1033
1238
|
}
|
|
1034
1239
|
}
|
|
1035
1240
|
});
|
|
1036
|
-
ctx.command("
|
|
1241
|
+
ctx.command("unsubscribe").alias("取消订阅").action(async ({ session }) => {
|
|
1037
1242
|
if (session.guild) {
|
|
1038
|
-
let cancelingGuild = (await ctx.database.get("dt_subscribed_guilds", {
|
|
1243
|
+
let cancelingGuild = (await ctx.database.get("dt_subscribed_guilds", {
|
|
1244
|
+
guildId: session.event.channel.id,
|
|
1245
|
+
platform: session.event.platform
|
|
1246
|
+
}))[0];
|
|
1039
1247
|
if (cancelingGuild) {
|
|
1040
|
-
ctx.database.remove("dt_subscribed_guilds", {
|
|
1041
|
-
|
|
1248
|
+
ctx.database.remove("dt_subscribed_guilds", {
|
|
1249
|
+
guildId: session.event.channel.id,
|
|
1250
|
+
platform: session.event.platform
|
|
1251
|
+
});
|
|
1252
|
+
session.send(session.text(".cancel_success"));
|
|
1042
1253
|
return;
|
|
1043
1254
|
}
|
|
1044
|
-
} else session.send("
|
|
1255
|
+
} else session.send(session.text(".not_subscribed"));
|
|
1045
1256
|
});
|
|
1046
1257
|
ctx.command("绑定 <steam_id> [nick_name]", "绑定SteamID,并起一个别名(也可以不起)").usage("将你的SteamID与你的账号绑定,若本群已订阅将会实时获取你的新比赛数据发布至群中。").example("绑定 123456789").example("绑定 123456789 张三").action(async ({ session }, steam_id, nick_name) => {
|
|
1047
1258
|
if (session.guild) {
|
|
@@ -1049,7 +1260,11 @@ async function apply(ctx, config) {
|
|
|
1049
1260
|
session.send("SteamID无效。");
|
|
1050
1261
|
return;
|
|
1051
1262
|
}
|
|
1052
|
-
let sessionPlayer = (await ctx.database.get("dt_subscribed_players", {
|
|
1263
|
+
let sessionPlayer = (await ctx.database.get("dt_subscribed_players", {
|
|
1264
|
+
guildId: session.event.channel.id,
|
|
1265
|
+
platform: session.event.platform,
|
|
1266
|
+
userId: session.event.user.id
|
|
1267
|
+
}))[0];
|
|
1053
1268
|
if (sessionPlayer) {
|
|
1054
1269
|
session.send(
|
|
1055
1270
|
`
|
|
@@ -1077,12 +1292,22 @@ async function apply(ctx, config) {
|
|
|
1077
1292
|
别名:${nick_name || ""}
|
|
1078
1293
|
SteamID:${steam_id}`.replace(/\n\s+/g, " ")
|
|
1079
1294
|
);
|
|
1080
|
-
ctx.database.create("dt_subscribed_players", {
|
|
1295
|
+
ctx.database.create("dt_subscribed_players", {
|
|
1296
|
+
userId: session.event.user.id,
|
|
1297
|
+
guildId: session.event.channel.id,
|
|
1298
|
+
platform: session.event.platform,
|
|
1299
|
+
steamId: parseInt(steam_id),
|
|
1300
|
+
nickName: nick_name || null
|
|
1301
|
+
});
|
|
1081
1302
|
}
|
|
1082
1303
|
});
|
|
1083
1304
|
ctx.command("取消绑定", "取消绑定你的个人信息").action(async ({ session }) => {
|
|
1084
1305
|
if (session.guild) {
|
|
1085
|
-
let sessionPlayer = (await ctx.database.get("dt_subscribed_players", {
|
|
1306
|
+
let sessionPlayer = (await ctx.database.get("dt_subscribed_players", {
|
|
1307
|
+
guildId: session.event.channel.id,
|
|
1308
|
+
platform: session.event.platform,
|
|
1309
|
+
userId: session.event.user.id
|
|
1310
|
+
}))[0];
|
|
1086
1311
|
if (sessionPlayer) {
|
|
1087
1312
|
await ctx.database.remove("dt_subscribed_players", sessionPlayer.id);
|
|
1088
1313
|
session.send("取消绑定成功。");
|
|
@@ -1091,7 +1316,11 @@ async function apply(ctx, config) {
|
|
|
1091
1316
|
});
|
|
1092
1317
|
ctx.command("改名 <nick_name>", "修改绑定时设定的别名").example("改名 李四").action(async ({ session }, nick_name) => {
|
|
1093
1318
|
if (session.guild) {
|
|
1094
|
-
let sessionPlayer = (await ctx.database.get("dt_subscribed_players", {
|
|
1319
|
+
let sessionPlayer = (await ctx.database.get("dt_subscribed_players", {
|
|
1320
|
+
guildId: session.event.channel.id,
|
|
1321
|
+
platform: session.event.platform,
|
|
1322
|
+
userId: session.event.user.id
|
|
1323
|
+
}))[0];
|
|
1095
1324
|
if (sessionPlayer) {
|
|
1096
1325
|
if (!nick_name) {
|
|
1097
1326
|
session.send("请输入你的别名。");
|
|
@@ -1111,7 +1340,11 @@ async function apply(ctx, config) {
|
|
|
1111
1340
|
});
|
|
1112
1341
|
ctx.command("查询群友", "查询本群已绑定的玩家").action(async ({ session }) => {
|
|
1113
1342
|
if (session.guild) {
|
|
1114
|
-
const
|
|
1343
|
+
const languageTag = await getLanguageTag(session);
|
|
1344
|
+
const subscribedPlayers = await ctx.database.get("dt_subscribed_players", {
|
|
1345
|
+
guildId: session.event.channel.id,
|
|
1346
|
+
platform: session.platform
|
|
1347
|
+
});
|
|
1115
1348
|
if (!subscribedPlayers.length) {
|
|
1116
1349
|
session.send("本群尚无绑定玩家。");
|
|
1117
1350
|
return;
|
|
@@ -1124,20 +1357,26 @@ async function apply(ctx, config) {
|
|
|
1124
1357
|
} catch (error) {
|
|
1125
1358
|
}
|
|
1126
1359
|
async function getUsers(subscribedPlayers2, memberList2) {
|
|
1127
|
-
const playerSteamIds = {
|
|
1360
|
+
const playerSteamIds = {
|
|
1361
|
+
steamAccountIds: subscribedPlayers2.map((player) => player.steamId)
|
|
1362
|
+
};
|
|
1128
1363
|
const queryResult = await query("PlayersInfoWith10MatchesForGuild", playerSteamIds);
|
|
1129
1364
|
const playersInfo = queryResult.players;
|
|
1130
1365
|
const users2 = [];
|
|
1131
1366
|
for (const subscribedPlayer of subscribedPlayers2) {
|
|
1132
1367
|
const queryPlayer = playersInfo.find((player) => player.steamAccount.id == subscribedPlayer.steamId);
|
|
1133
1368
|
const queryMember = memberList2?.data.find((member) => member.user?.id == subscribedPlayer.userId);
|
|
1134
|
-
users2.push({
|
|
1369
|
+
users2.push({
|
|
1370
|
+
...subscribedPlayer,
|
|
1371
|
+
...queryPlayer,
|
|
1372
|
+
...queryMember
|
|
1373
|
+
});
|
|
1135
1374
|
}
|
|
1136
1375
|
return users2;
|
|
1137
1376
|
}
|
|
1138
1377
|
__name(getUsers, "getUsers");
|
|
1139
1378
|
const users = await getUsers(subscribedPlayers, memberList);
|
|
1140
|
-
session.send(await ctx.puppeteer.render(genImageHTML(users, "guild_member" /* GuildMember */, "guild_member" /* GuildMember
|
|
1379
|
+
session.send(await ctx.puppeteer.render(await genImageHTML(users, "guild_member" /* GuildMember */, "guild_member" /* GuildMember */, ctx, languageTag)));
|
|
1141
1380
|
} catch (error) {
|
|
1142
1381
|
ctx.logger.error(error);
|
|
1143
1382
|
session.send("查询群友失败。");
|
|
@@ -1145,53 +1384,118 @@ async function apply(ctx, config) {
|
|
|
1145
1384
|
}
|
|
1146
1385
|
}
|
|
1147
1386
|
});
|
|
1148
|
-
async function
|
|
1387
|
+
async function queryMatchData(matchId) {
|
|
1149
1388
|
try {
|
|
1389
|
+
let queryLocal = await ctx.cache.get("dt_previous_query_results", String(matchId));
|
|
1150
1390
|
let matchQuery;
|
|
1151
|
-
|
|
1152
|
-
|
|
1153
|
-
matchQuery
|
|
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);
|
|
1159
|
-
if (match && (match.parsedDateTime || import_moment.default.unix(match.endDateTime).isBefore((0, import_moment.default)().subtract(config.dataParsingTimeoutMinutes, "minutes")))) {
|
|
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 */)));
|
|
1391
|
+
if (queryLocal) {
|
|
1392
|
+
matchQuery = queryLocal;
|
|
1393
|
+
ctx.cache.set("dt_previous_query_results", String(matchQuery.match.id), queryLocal, days_30);
|
|
1161
1394
|
} else {
|
|
1162
|
-
|
|
1163
|
-
|
|
1395
|
+
matchQuery = await query("MatchInfo", { matchId });
|
|
1396
|
+
if (matchQuery.match?.parsedDateTime && matchQuery.match.players.filter((player) => player?.stats?.heroDamageReport?.dealtTotal).length > 0)
|
|
1397
|
+
ctx.cache.set("dt_previous_query_results", String(matchQuery.match.id), matchQuery, days_30);
|
|
1164
1398
|
}
|
|
1399
|
+
return matchQuery;
|
|
1165
1400
|
} catch (error) {
|
|
1166
|
-
ctx.
|
|
1167
|
-
|
|
1168
|
-
await ctx.database.remove("dt_previous_query_results", { matchId });
|
|
1401
|
+
await ctx.cache.delete("dt_previous_query_results", String(matchId));
|
|
1402
|
+
throw new Error("比赛数据查询阶段出错:", { cause: error });
|
|
1169
1403
|
}
|
|
1170
1404
|
}
|
|
1171
|
-
__name(
|
|
1172
|
-
|
|
1405
|
+
__name(queryMatchData, "queryMatchData");
|
|
1406
|
+
async function formatMatchData(matchQuery, languageTag) {
|
|
1407
|
+
try {
|
|
1408
|
+
let constantsQuery = await ctx.cache.get("dt_facets_constants", languageTag);
|
|
1409
|
+
if (!constantsQuery || // 缓存中没有 constants
|
|
1410
|
+
!matchQuery.constants.gameVersions?.[0]?.id || // 当前版本信息无效
|
|
1411
|
+
!constantsQuery.constants.gameVersions?.[0]?.id || // 缓存版本信息无效
|
|
1412
|
+
matchQuery.constants.gameVersions[0].id !== constantsQuery.constants.gameVersions[0].id)
|
|
1413
|
+
constantsQuery = await query("Constants", { language: GraphqlLanguageEnum[languageTag] });
|
|
1414
|
+
ctx.cache.set("dt_facets_constants", languageTag, constantsQuery, days_30);
|
|
1415
|
+
const match = getFormattedMatchData(matchQuery, constantsQuery);
|
|
1416
|
+
return match;
|
|
1417
|
+
} catch (error) {
|
|
1418
|
+
await ctx.cache.delete("dt_previous_query_results", String(matchQuery.match.id));
|
|
1419
|
+
throw new Error("比赛数据扩展阶段出错:", { cause: error });
|
|
1420
|
+
}
|
|
1421
|
+
}
|
|
1422
|
+
__name(formatMatchData, "formatMatchData");
|
|
1423
|
+
async function generateMatchMessage(match, languageTag, guild) {
|
|
1424
|
+
let broadMatchMessage = "";
|
|
1425
|
+
let idsToFind = guild.players.map((player) => player.steamId);
|
|
1426
|
+
let broadPlayers = match.players.filter((item) => idsToFind.includes(item.steamAccountId));
|
|
1427
|
+
for (let player of broadPlayers) {
|
|
1428
|
+
const random2 = new import_koishi2.Random(() => enhancedSimpleHashToSeed(`${match.id}-${player.steamAccountId}-${player.playerSlot}`));
|
|
1429
|
+
let comment;
|
|
1430
|
+
if (player.isRadiant == match.didRadiantWin) {
|
|
1431
|
+
if (player.deathContribution < 0.2 || player.killContribution > 0.75 || player.heroDamage / player.networth > 1.5 || player.towerDamage > 1e4 || player.imp > 0)
|
|
1432
|
+
comment = random2.pick(customConvertArrayOfString($t(languageTag, "dota2tracker.broadcast.WIN_POSITIVE")));
|
|
1433
|
+
else comment = random2.pick(customConvertArrayOfString($t(languageTag, "dota2tracker.broadcast.WIN_NEGATIVE")));
|
|
1434
|
+
} else {
|
|
1435
|
+
if (player.deathContribution < 0.25 || player.killContribution > 0.75 || player.heroDamage / player.networth > 1 || player.towerDamage > 5e3 || player.imp > 0)
|
|
1436
|
+
comment = random2.pick(customConvertArrayOfString($t(languageTag, "dota2tracker.broadcast.LOSE_NEGATIVE")));
|
|
1437
|
+
else comment = random2.pick(customConvertArrayOfString($t(languageTag, "dota2tracker.broadcast.LOSE_NEGATIVE")));
|
|
1438
|
+
}
|
|
1439
|
+
let broadPlayerMessage = $t(languageTag, "dota2tracker.broadcast.message", {
|
|
1440
|
+
name: player.steamAccount.name,
|
|
1441
|
+
hero_name: random2.pick(getHeroNicknames(player.hero.id, languageTag)),
|
|
1442
|
+
comment,
|
|
1443
|
+
kda: `${((player.kills + player.assists) / (player.deaths || 1)).toFixed(2)} [${player.kills}/${player.deaths}/${player.assists}]`,
|
|
1444
|
+
GPM_XPM: `${player.goldPerMinute}/${player.experiencePerMinute}`,
|
|
1445
|
+
lh_dn: `${player.numLastHits}/${player.numDenies}`,
|
|
1446
|
+
damage: `${player.heroDamage}/${player.towerDamage}`,
|
|
1447
|
+
kc_dc: `${(player.killContribution * 100).toFixed(2)}%/${(player.deathContribution * 100).toFixed(2)}%`
|
|
1448
|
+
});
|
|
1449
|
+
broadMatchMessage += broadPlayerMessage + "\n";
|
|
1450
|
+
}
|
|
1451
|
+
return broadMatchMessage;
|
|
1452
|
+
}
|
|
1453
|
+
__name(generateMatchMessage, "generateMatchMessage");
|
|
1454
|
+
async function generateMatchImage(match, languageTag) {
|
|
1455
|
+
const imageHTML = await genImageHTML(match, ctx.config.template_match, "match" /* Match */, ctx, languageTag);
|
|
1456
|
+
return await ctx.puppeteer.render(imageHTML);
|
|
1457
|
+
}
|
|
1458
|
+
__name(generateMatchImage, "generateMatchImage");
|
|
1459
|
+
ctx.command("查询比赛 <match_id>", "查询比赛ID").alias("querymatch").usage("查询指定比赛ID的比赛数据,生成图片发布。").example("查询比赛 1234567890").action(async ({ session }, match_id) => {
|
|
1173
1460
|
if (!match_id) {
|
|
1174
1461
|
session.send("请输入比赛ID。");
|
|
1175
1462
|
return;
|
|
1176
1463
|
}
|
|
1177
|
-
if (!/^\d{
|
|
1464
|
+
if (!/^\d{1,11}$/.test(match_id)) {
|
|
1178
1465
|
session.send("比赛ID无效。");
|
|
1179
1466
|
return;
|
|
1180
1467
|
}
|
|
1181
|
-
session.send("正在搜索对局详情,请稍后...");
|
|
1182
|
-
|
|
1468
|
+
await session.send("正在搜索对局详情,请稍后...");
|
|
1469
|
+
try {
|
|
1470
|
+
const languageTag = await getLanguageTag(session);
|
|
1471
|
+
const matchQuery = await queryMatchData(Number(match_id));
|
|
1472
|
+
const match = await formatMatchData(matchQuery, languageTag);
|
|
1473
|
+
const image = await generateMatchImage(match, languageTag);
|
|
1474
|
+
session.send((ctx.config.urlInMessageType.some((type) => type == "match") ? "https://stratz.com/matches/" + match.id : "") + image);
|
|
1475
|
+
} catch (error) {
|
|
1476
|
+
session.send("获取比赛信息失败。");
|
|
1477
|
+
ctx.logger.error(error);
|
|
1478
|
+
}
|
|
1183
1479
|
});
|
|
1184
1480
|
ctx.command("查询最近比赛 [input_data]", "查询玩家的最近比赛").usage("查询指定玩家的最近一场比赛的比赛数据,生成图片发布。\n参数可输入该玩家的SteamID或已在本群绑定玩家的别名,无参数时尝试查询调用指令玩家的SteamID").example("查询最近比赛 123456789").example("查询最近比赛 张三").action(async ({ session }, input_data) => {
|
|
1185
1481
|
if (session.guild || !session.guild && input_data) {
|
|
1186
1482
|
let sessionPlayer;
|
|
1187
1483
|
if (!input_data) {
|
|
1188
|
-
sessionPlayer = (await ctx.database.get("dt_subscribed_players", {
|
|
1484
|
+
sessionPlayer = (await ctx.database.get("dt_subscribed_players", {
|
|
1485
|
+
guildId: session.event.channel.id,
|
|
1486
|
+
platform: session.event.platform,
|
|
1487
|
+
userId: session.event.user.id
|
|
1488
|
+
}))[0];
|
|
1189
1489
|
if (!sessionPlayer) {
|
|
1190
1490
|
session.send("无参数时默认从已绑定SteamID玩家中寻找你的信息,但你似乎并没有绑定。\n请在本群绑定SteamID。(可输入【-绑定 -h】获取帮助)\n或在指令后跟上希望查询的SteamID或已绑定玩家的别名。");
|
|
1191
1491
|
return;
|
|
1192
1492
|
}
|
|
1193
1493
|
}
|
|
1194
|
-
let flagBindedPlayer = sessionPlayer || (await ctx.database.get("dt_subscribed_players", {
|
|
1494
|
+
let flagBindedPlayer = sessionPlayer || (await ctx.database.get("dt_subscribed_players", {
|
|
1495
|
+
guildId: session.event.channel.id,
|
|
1496
|
+
platform: session.event.platform,
|
|
1497
|
+
nickName: input_data
|
|
1498
|
+
}))[0];
|
|
1195
1499
|
if (!(flagBindedPlayer || /^\d{1,11}$/.test(input_data))) {
|
|
1196
1500
|
session.send("SteamID不合法并且未在本群找到此玩家。");
|
|
1197
1501
|
return;
|
|
@@ -1199,13 +1503,19 @@ async function apply(ctx, config) {
|
|
|
1199
1503
|
let lastMatchId = 0;
|
|
1200
1504
|
try {
|
|
1201
1505
|
session.send("正在搜索对局详情,请稍后...");
|
|
1202
|
-
lastMatchId = (await query("PlayersLastmatchRankinfo", {
|
|
1506
|
+
lastMatchId = (await query("PlayersLastmatchRankinfo", {
|
|
1507
|
+
steamAccountIds: [parseInt(flagBindedPlayer?.steamId ?? input_data)]
|
|
1508
|
+
})).players[0].matches[0].id;
|
|
1203
1509
|
} catch (error) {
|
|
1204
1510
|
session.send("获取玩家最近比赛失败。");
|
|
1205
1511
|
ctx.logger.error(error);
|
|
1206
1512
|
return;
|
|
1207
1513
|
}
|
|
1208
|
-
|
|
1514
|
+
const languageTag = await getLanguageTag(session);
|
|
1515
|
+
const matchQuery = await queryMatchData(lastMatchId);
|
|
1516
|
+
const match = await formatMatchData(matchQuery, languageTag);
|
|
1517
|
+
const image = await generateMatchImage(match, languageTag);
|
|
1518
|
+
session.send((ctx.config.urlInMessageType.some((type) => type == "match") ? "https://stratz.com/matches/" + match.id : "") + image);
|
|
1209
1519
|
} else {
|
|
1210
1520
|
session.send("<p>指令调用失败。</p><p>当前不属于群聊状态,必须提供指定玩家的SteamID。</p>");
|
|
1211
1521
|
}
|
|
@@ -1213,14 +1523,23 @@ async function apply(ctx, config) {
|
|
|
1213
1523
|
ctx.command("查询玩家 <input_data>", "查询玩家信息,可指定英雄").usage("查询指定玩家的个人信息与最近战绩,生成图片发布。\n参数可输入该玩家的SteamID或已在本群绑定玩家的别名,无参数时尝试查询调用指令玩家的SteamID").option("hero", "-o <value:string> 查询玩家指定英雄使用情况(同其他英雄查询,可用简称与ID)").example("查询玩家 123456789").example("查询玩家 张三").example("查询玩家 张三 hero 敌法师").action(async ({ session, options }, input_data) => {
|
|
1214
1524
|
if (session.guild || !session.guild && input_data) {
|
|
1215
1525
|
let sessionPlayer;
|
|
1526
|
+
const languageTag = await getLanguageTag(session);
|
|
1216
1527
|
if (!input_data) {
|
|
1217
|
-
sessionPlayer = (await ctx.database.get("dt_subscribed_players", {
|
|
1528
|
+
sessionPlayer = (await ctx.database.get("dt_subscribed_players", {
|
|
1529
|
+
guildId: session.event.channel.id,
|
|
1530
|
+
platform: session.event.platform,
|
|
1531
|
+
userId: session.event.user.id
|
|
1532
|
+
}))[0];
|
|
1218
1533
|
if (!sessionPlayer) {
|
|
1219
1534
|
session.send("无参数时默认从已绑定SteamID玩家中寻找你的信息,但你似乎并没有绑定。\n请在本群绑定SteamID。(可输入【-绑定 -h】获取帮助)\n或在指令后跟上希望查询的SteamID或已绑定玩家的别名。");
|
|
1220
1535
|
return;
|
|
1221
1536
|
}
|
|
1222
1537
|
}
|
|
1223
|
-
let flagBindedPlayer = sessionPlayer || (await ctx.database.get("dt_subscribed_players", {
|
|
1538
|
+
let flagBindedPlayer = sessionPlayer || (await ctx.database.get("dt_subscribed_players", {
|
|
1539
|
+
guildId: session.event.channel.id,
|
|
1540
|
+
platform: session.event.platform,
|
|
1541
|
+
nickName: input_data
|
|
1542
|
+
}))[0];
|
|
1224
1543
|
if (!(flagBindedPlayer || /^\d{1,11}$/.test(input_data))) {
|
|
1225
1544
|
session.send("SteamID不合法并且未在本群找到此玩家。");
|
|
1226
1545
|
return;
|
|
@@ -1230,7 +1549,10 @@ async function apply(ctx, config) {
|
|
|
1230
1549
|
let steamId = flagBindedPlayer?.steamId ?? input_data;
|
|
1231
1550
|
let player;
|
|
1232
1551
|
try {
|
|
1233
|
-
player = (await query("PlayerInfoWith25Matches", {
|
|
1552
|
+
player = (await query("PlayerInfoWith25Matches", {
|
|
1553
|
+
steamAccountId: steamId,
|
|
1554
|
+
heroIds: heroId
|
|
1555
|
+
})).player;
|
|
1234
1556
|
let playerExtra = (await query("PlayerExtraInfo", {
|
|
1235
1557
|
steamAccountId: steamId,
|
|
1236
1558
|
matchCount: player.matchCount,
|
|
@@ -1273,10 +1595,12 @@ async function apply(ctx, config) {
|
|
|
1273
1595
|
player.winCount = winCount;
|
|
1274
1596
|
player.performance.imp = imp;
|
|
1275
1597
|
player.dotaPlus = player.dotaPlus.filter((dpHero) => dpHero.heroId == heroId);
|
|
1598
|
+
player.genHero = {
|
|
1599
|
+
name: constantLocales[languageTag].dota2tracker.template.hero_names[heroId]
|
|
1600
|
+
};
|
|
1276
1601
|
}
|
|
1277
|
-
player.genHero = { name: HEROES_NAMES[(await session.getChannel(session.event.channel.id)).locales?.at(0) ?? "zh-CN"][heroId] };
|
|
1278
1602
|
session.send(
|
|
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
|
|
1603
|
+
(ctx.config.urlInMessageType.some((type) => type == "player") ? "https://stratz.com/players/" + player.steamAccount.id : "") + await ctx.puppeteer.render(await genImageHTML(player, config.template_player, "player" /* Player */, ctx, languageTag))
|
|
1280
1604
|
);
|
|
1281
1605
|
} catch (error) {
|
|
1282
1606
|
ctx.logger.error(error);
|
|
@@ -1288,7 +1612,7 @@ async function apply(ctx, config) {
|
|
|
1288
1612
|
});
|
|
1289
1613
|
ctx.command("查询英雄 <input_data>", "查询英雄技能/面板信息").usage("查询英雄的技能说明与各项数据,生成图片发布。\n参数可输入英雄ID、英雄名、英雄常用别名").option("random", "-r 随机选择英雄").example("查询英雄 15").example("查询英雄 雷泽").example("查询英雄 电魂").action(async ({ session, options }, input_data) => {
|
|
1290
1614
|
const languageTag = await getLanguageTag(session);
|
|
1291
|
-
if (options.random) input_data = random.pick(Object.keys(
|
|
1615
|
+
if (options.random) input_data = random.pick(Object.keys(dotaconstants2.heroes));
|
|
1292
1616
|
if (input_data) {
|
|
1293
1617
|
let heroId = findingHero(input_data);
|
|
1294
1618
|
if (!heroId) {
|
|
@@ -1303,7 +1627,12 @@ async function apply(ctx, config) {
|
|
|
1303
1627
|
fa.abilities.forEach((ab) => {
|
|
1304
1628
|
if (!hero.facets[i].abilities) hero.facets[i].abilities = [];
|
|
1305
1629
|
if (hero.facets[i].description_loc !== ab.desc_loc)
|
|
1306
|
-
hero.facets[i].abilities.push({
|
|
1630
|
+
hero.facets[i].abilities.push({
|
|
1631
|
+
id: ab.id,
|
|
1632
|
+
name: ab.name,
|
|
1633
|
+
name_loc: ab.name_loc,
|
|
1634
|
+
description_ability_loc: formatHeroDesc(ab.desc_loc, ab.special_values, "facet" /* Facet */)
|
|
1635
|
+
});
|
|
1307
1636
|
else hero.facets[i].description_loc = formatHeroDesc(hero.facets[i].description_loc, ab.special_values, "facet" /* Facet */);
|
|
1308
1637
|
ab.ability_is_facet = true;
|
|
1309
1638
|
ab.facet = hero.facets[i];
|
|
@@ -1318,7 +1647,13 @@ async function apply(ctx, config) {
|
|
|
1318
1647
|
if (i < 0) return;
|
|
1319
1648
|
if (facet) {
|
|
1320
1649
|
if (!hero.facets[i].abilities) hero.facets[i].abilities = [];
|
|
1321
|
-
hero.facets[i].abilities.push({
|
|
1650
|
+
hero.facets[i].abilities.push({
|
|
1651
|
+
id: ab.id,
|
|
1652
|
+
name: ab.name,
|
|
1653
|
+
name_loc: ab.name_loc,
|
|
1654
|
+
description_ability_loc: formatHeroDesc(facet, ab.special_values, "facet" /* Facet */),
|
|
1655
|
+
attributes: []
|
|
1656
|
+
});
|
|
1322
1657
|
}
|
|
1323
1658
|
});
|
|
1324
1659
|
hero.facets.forEach((facet) => {
|
|
@@ -1326,7 +1661,11 @@ async function apply(ctx, config) {
|
|
|
1326
1661
|
svs.forEach((sv) => {
|
|
1327
1662
|
if (sv.heading_loc) {
|
|
1328
1663
|
if (!facet.abilities) facet.abilities = [];
|
|
1329
|
-
facet.abilities.find((ability) => ab.id == ability.id)?.attributes.push({
|
|
1664
|
+
facet.abilities.find((ability) => ab.id == ability.id)?.attributes.push({
|
|
1665
|
+
heading_loc: sv.heading_loc,
|
|
1666
|
+
values: [...sv.facet_bonus.values],
|
|
1667
|
+
is_percentage: sv.is_percentage
|
|
1668
|
+
});
|
|
1330
1669
|
}
|
|
1331
1670
|
});
|
|
1332
1671
|
facet.description_loc = formatHeroDesc(facet.description_loc, svs, "facet" /* Facet */);
|
|
@@ -1355,7 +1694,10 @@ async function apply(ctx, config) {
|
|
|
1355
1694
|
const specialValue = specialValues.find((sv) => sv.name === String(match2[1]));
|
|
1356
1695
|
const replacement = specialValue?.bonuses.find((bonus) => bonus.name === talent.name)?.value;
|
|
1357
1696
|
if (replacement !== void 0) {
|
|
1358
|
-
replacements.push({
|
|
1697
|
+
replacements.push({
|
|
1698
|
+
original: match2[0],
|
|
1699
|
+
replacement
|
|
1700
|
+
});
|
|
1359
1701
|
}
|
|
1360
1702
|
}
|
|
1361
1703
|
replacements.forEach(({ original, replacement }) => {
|
|
@@ -1366,7 +1708,7 @@ async function apply(ctx, config) {
|
|
|
1366
1708
|
}
|
|
1367
1709
|
});
|
|
1368
1710
|
await session.send(
|
|
1369
|
-
(ctx.config.urlInMessageType.some((type) => type == "hero") ? `https://wiki.dota2.com.cn/hero/${hero.
|
|
1711
|
+
(ctx.config.urlInMessageType.some((type) => type == "hero") ? `https://wiki.dota2.com.cn/hero/${hero["name"].match(/^npc_dota_hero_(.+)$/)[1]}.html` : "") + await ctx.puppeteer.render(await genImageHTML(hero, config.template_hero, "hero" /* Hero */, ctx, languageTag))
|
|
1370
1712
|
);
|
|
1371
1713
|
} catch (error) {
|
|
1372
1714
|
ctx.logger.error(error);
|
|
@@ -1376,55 +1718,18 @@ async function apply(ctx, config) {
|
|
|
1376
1718
|
session.send("请输入参数。");
|
|
1377
1719
|
}
|
|
1378
1720
|
});
|
|
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) => {
|
|
1380
|
-
if (input_data) {
|
|
1381
|
-
const languageTag = await getLanguageTag(session);
|
|
1382
|
-
let heroId = findingHero(input_data);
|
|
1383
|
-
if (!heroId) {
|
|
1384
|
-
session.send("未找到输入的英雄,请确认后重新输入。");
|
|
1385
|
-
return;
|
|
1386
|
-
}
|
|
1387
|
-
try {
|
|
1388
|
-
let heroStats = (await query("HeroMatchupWinrate", { heroId, take: Object.keys(dotaconstants2.heroes).length - 1 })).heroStats;
|
|
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) => {
|
|
1390
|
-
const winRate = item.winCount / item.matchCount;
|
|
1391
|
-
return { ...item, winRate: winRate.toFixed(3) };
|
|
1392
|
-
}).sort((a, b) => b.winRate - a.winRate).slice(0, Math.max(1, Math.min(Object.keys(dotaconstants2.heroes).length - 1, options.limit)));
|
|
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) => {
|
|
1394
|
-
const winRate = item.winCount / item.matchCount;
|
|
1395
|
-
return { ...item, winRate: winRate.toFixed(3) };
|
|
1396
|
-
}).sort((a, b) => a.winRate - b.winRate).slice(0, Math.max(1, Math.min(Object.keys(dotaconstants2.heroes).length - 1, options.limit)));
|
|
1397
|
-
session.send(
|
|
1398
|
-
`你查询的英雄是${HEROES_NAMES[heroStats.matchUp[0].heroId][0]}(ID:${heroStats.matchUp[0].heroId}),
|
|
1399
|
-
以下是7天内传奇-万古分段比赛数据总结而来的搭档与克制关系
|
|
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("、")}`
|
|
1402
|
-
);
|
|
1403
|
-
} catch (error) {
|
|
1404
|
-
ctx.logger.error(error);
|
|
1405
|
-
session.send("获取数据失败");
|
|
1406
|
-
return;
|
|
1407
|
-
}
|
|
1408
|
-
}
|
|
1409
|
-
});
|
|
1410
1721
|
function findingHero(input) {
|
|
1411
1722
|
const heroIds = Object.keys(dotaconstants2.heroes).map((id) => parseInt(id));
|
|
1412
1723
|
let tid;
|
|
1413
|
-
for (const loc of Object.keys(
|
|
1724
|
+
for (const loc of Object.keys(GraphqlLanguageEnum)) {
|
|
1414
1725
|
for (const id_nicknames of getHeroNicknames(heroIds, loc)) {
|
|
1415
1726
|
for (const [id, nicknames] of Object.entries(id_nicknames)) {
|
|
1416
|
-
|
|
1417
|
-
|
|
1418
|
-
if (input == nickname) return Number(id);
|
|
1419
|
-
}
|
|
1420
|
-
} catch {
|
|
1421
|
-
continue;
|
|
1727
|
+
for (const nickname of nicknames) {
|
|
1728
|
+
if (input == nickname) return Number(id);
|
|
1422
1729
|
}
|
|
1423
1730
|
}
|
|
1424
1731
|
}
|
|
1425
|
-
|
|
1426
|
-
for (const names of Object.values(HEROES_NAMES)) {
|
|
1427
|
-
for (const [id, name2] of Object.entries(names)) {
|
|
1732
|
+
for (const [id, name2] of Object.entries(constantLocales[loc].dota2tracker.template.hero_names)) {
|
|
1428
1733
|
if (input == name2) return Number(id);
|
|
1429
1734
|
if (input == id) tid = input;
|
|
1430
1735
|
}
|
|
@@ -1432,34 +1737,41 @@ async function apply(ctx, config) {
|
|
|
1432
1737
|
return tid;
|
|
1433
1738
|
}
|
|
1434
1739
|
__name(findingHero, "findingHero");
|
|
1435
|
-
function getHeroNicknames(heroIds, languageTag
|
|
1740
|
+
function getHeroNicknames(heroIds, languageTag) {
|
|
1436
1741
|
if (heroIds === void 0) return [];
|
|
1437
1742
|
const heroIdArray = Array.isArray(heroIds) ? heroIds : [heroIds];
|
|
1438
1743
|
const result = [];
|
|
1439
1744
|
for (const heroId of heroIdArray) {
|
|
1440
1745
|
let content = [];
|
|
1441
1746
|
try {
|
|
1442
|
-
const rawContent = ctx.i18n.render([languageTag], [`dota2tracker.
|
|
1747
|
+
const rawContent = ctx.i18n.render([languageTag], [`dota2tracker.heroes_nicknames.${heroId}`], {}).at(0)?.attrs?.content ?? "";
|
|
1443
1748
|
content = JSON.parse(`[${rawContent}]`);
|
|
1444
1749
|
} catch (error) {
|
|
1445
1750
|
ctx.logger.error(`Failed to parse heroId ${heroId} content: ${error.message}`);
|
|
1446
1751
|
content = [];
|
|
1447
1752
|
}
|
|
1448
|
-
result.push({
|
|
1753
|
+
result.push({
|
|
1754
|
+
[heroId]: Array.from(/* @__PURE__ */ new Set([$t(languageTag, "dota2tracker.template.hero_names." + heroId), ...content]))
|
|
1755
|
+
});
|
|
1449
1756
|
}
|
|
1450
1757
|
return Array.isArray(heroIds) ? result : result[0][heroIds];
|
|
1451
1758
|
}
|
|
1452
1759
|
__name(getHeroNicknames, "getHeroNicknames");
|
|
1453
1760
|
ctx.on("ready", async () => {
|
|
1454
1761
|
ctx.model.extend("dt_subscribed_guilds", { id: "unsigned", guildId: "string", platform: "string" }, { autoInc: true });
|
|
1455
|
-
ctx.model.extend(
|
|
1456
|
-
|
|
1457
|
-
|
|
1458
|
-
|
|
1459
|
-
|
|
1460
|
-
|
|
1461
|
-
|
|
1462
|
-
|
|
1762
|
+
ctx.model.extend(
|
|
1763
|
+
"dt_subscribed_players",
|
|
1764
|
+
{
|
|
1765
|
+
id: "unsigned",
|
|
1766
|
+
userId: "string",
|
|
1767
|
+
guildId: "string",
|
|
1768
|
+
platform: "string",
|
|
1769
|
+
steamId: "integer",
|
|
1770
|
+
nickName: "string",
|
|
1771
|
+
rank: "json"
|
|
1772
|
+
},
|
|
1773
|
+
{ autoInc: true }
|
|
1774
|
+
);
|
|
1463
1775
|
if (config.dailyReportSwitch) {
|
|
1464
1776
|
ctx.cron(`0 ${config.dailyReportHours} * * *`, async function() {
|
|
1465
1777
|
const oneDayAgo = (0, import_moment.default)().subtract(1, "days").unix();
|
|
@@ -1479,30 +1791,64 @@ async function apply(ctx, config) {
|
|
|
1479
1791
|
const subscribedPlayersSteamIds = subscribedPlayersInGuild.map((player) => player.steamId).filter(function(value, index, self) {
|
|
1480
1792
|
return self.indexOf(value) === index;
|
|
1481
1793
|
});
|
|
1482
|
-
const players = (await query("PlayersLastmatchRankinfo", {
|
|
1794
|
+
const players = (await query("PlayersLastmatchRankinfo", {
|
|
1795
|
+
steamAccountIds: subscribedPlayersSteamIds
|
|
1796
|
+
})).players;
|
|
1483
1797
|
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));
|
|
1484
|
-
const sendedMatchesIds =
|
|
1485
|
-
|
|
1486
|
-
|
|
1487
|
-
|
|
1488
|
-
|
|
1489
|
-
|
|
1490
|
-
|
|
1491
|
-
|
|
1492
|
-
|
|
1493
|
-
|
|
1798
|
+
const sendedMatchesIds = [];
|
|
1799
|
+
for await (const sendedMatchesId of ctx.cache.keys("dt_sended_match_id")) {
|
|
1800
|
+
sendedMatchesIds.push(Number(sendedMatchesId));
|
|
1801
|
+
}
|
|
1802
|
+
await Promise.all(
|
|
1803
|
+
lastMatches.filter((match) => !sendedMatchesIds.includes(match.id)).map(async (match) => {
|
|
1804
|
+
const tempGuildsByLanguage = {};
|
|
1805
|
+
for (const player of match.players) {
|
|
1806
|
+
const subscribedPlayers = subscribedPlayersInGuild.filter((subscribedPlayer) => subscribedPlayer.steamId === player.steamAccount.id);
|
|
1807
|
+
await Promise.all(
|
|
1808
|
+
subscribedPlayers.map(async (subscribedPlayer) => {
|
|
1809
|
+
if (subscribedPlayer) {
|
|
1810
|
+
const languageTag = await getLanguageTag(void 0, void 0, subscribedPlayer.guildId);
|
|
1811
|
+
if (!tempGuildsByLanguage[languageTag]) {
|
|
1812
|
+
tempGuildsByLanguage[languageTag] = [];
|
|
1813
|
+
}
|
|
1814
|
+
const tempGuild = tempGuildsByLanguage[languageTag].find((guild) => guild.guildId === subscribedPlayer.guildId && guild.platform === subscribedPlayer.platform);
|
|
1815
|
+
if (tempGuild) {
|
|
1816
|
+
tempGuild.players.push(subscribedPlayer);
|
|
1817
|
+
} else {
|
|
1818
|
+
tempGuildsByLanguage[languageTag].push({
|
|
1819
|
+
guildId: subscribedPlayer.guildId,
|
|
1820
|
+
platform: subscribedPlayer.platform,
|
|
1821
|
+
players: [subscribedPlayer]
|
|
1822
|
+
});
|
|
1823
|
+
}
|
|
1824
|
+
}
|
|
1825
|
+
})
|
|
1826
|
+
);
|
|
1827
|
+
}
|
|
1828
|
+
pendingMatches.push({
|
|
1829
|
+
matchId: match.id,
|
|
1830
|
+
guilds: tempGuildsByLanguage,
|
|
1831
|
+
queryTime: /* @__PURE__ */ new Date()
|
|
1494
1832
|
});
|
|
1495
|
-
|
|
1496
|
-
|
|
1497
|
-
|
|
1498
|
-
|
|
1499
|
-
|
|
1500
|
-
|
|
1501
|
-
|
|
1502
|
-
|
|
1503
|
-
|
|
1833
|
+
Object.entries(tempGuildsByLanguage).forEach(([languageTag, guilds]) => {
|
|
1834
|
+
ctx.logger.info(
|
|
1835
|
+
guilds.map(
|
|
1836
|
+
(guild) => `追踪到来自语言 ${languageTag} 群组 ${guild.platform}:${guild.guildId} 的用户 ${guild.players.map((player) => `[${player.nickName ?? ""}(${player.steamId})]`).join("、")} 的尚未播报过的最新比赛 ${match.id}。`
|
|
1837
|
+
).join("")
|
|
1838
|
+
);
|
|
1839
|
+
});
|
|
1840
|
+
if (!match.parsedDateTime) {
|
|
1841
|
+
query("RequestMatchDataAnalysis", {
|
|
1842
|
+
matchId: match.id
|
|
1843
|
+
}).then((response) => ctx.logger.info(`比赛 ${match.id} 的` + (response.stratz.matchRetry ? "解析请求已成功发送至STRATZ服务器。" : "解析请求发送失败。")));
|
|
1844
|
+
}
|
|
1845
|
+
})
|
|
1846
|
+
);
|
|
1504
1847
|
const rankMap = players.reduce((map, player) => {
|
|
1505
|
-
map[player.steamAccount.id] = {
|
|
1848
|
+
map[player.steamAccount.id] = {
|
|
1849
|
+
rank: player.steamAccount.seasonRank,
|
|
1850
|
+
leader: player.steamAccount.seasonLeaderboardRank
|
|
1851
|
+
};
|
|
1506
1852
|
return map;
|
|
1507
1853
|
}, {});
|
|
1508
1854
|
for (let subPlayer of subscribedPlayersInGuild) {
|
|
@@ -1524,9 +1870,10 @@ async function apply(ctx, config) {
|
|
|
1524
1870
|
if (prevRank.medal !== currRank.medal || prevRank.star !== currRank.star && config.rankBroadStar || prevRank.leader !== currRank.leader && config.rankBroadLeader) {
|
|
1525
1871
|
const guildMember = await ctx.bots.find((bot) => bot.platform == subPlayer.platform)?.getGuildMember?.(subPlayer.guildId, subPlayer.userId);
|
|
1526
1872
|
const name2 = subPlayer.nickName ?? guildMember?.nick ?? players.find((player) => player.steamAccount.id == subPlayer.steamId)?.steamAccount.name ?? subPlayer.steamId;
|
|
1873
|
+
const languageTag = await getLanguageTag(void 0, void 0, subPlayer.guildId);
|
|
1527
1874
|
if (config.rankBroadFun === true) {
|
|
1528
1875
|
const img = await ctx.puppeteer.render(
|
|
1529
|
-
genImageHTML(
|
|
1876
|
+
await genImageHTML(
|
|
1530
1877
|
{
|
|
1531
1878
|
name: name2,
|
|
1532
1879
|
avatar: guildMember?.avatar ?? players.find((player) => subPlayer.steamId == player.steamAccount.id).steamAccount.avatar,
|
|
@@ -1535,13 +1882,15 @@ async function apply(ctx, config) {
|
|
|
1535
1882
|
currRank
|
|
1536
1883
|
},
|
|
1537
1884
|
"rank" + (config.rankBroadFun ? "_fun" : ""),
|
|
1538
|
-
"rank" /* Rank
|
|
1885
|
+
"rank" /* Rank */,
|
|
1886
|
+
ctx,
|
|
1887
|
+
languageTag
|
|
1539
1888
|
)
|
|
1540
1889
|
);
|
|
1541
1890
|
await ctx.broadcast([`${subPlayer.platform}:${subPlayer.guildId}`], img);
|
|
1542
1891
|
} else {
|
|
1543
|
-
const message = `群友 ${name2} 段位变动:${
|
|
1544
|
-
const img = await ctx.puppeteer.render(genImageHTML(currRank, "rank" + (config.rankBroadFun ? "2" : ""), "rank" /* Rank
|
|
1892
|
+
const message = `群友 ${name2} 段位变动:${$t(languageTag, "dota2tracker.template.ranks." + prevRank.medal)}${prevRank.star} → ${$t(languageTag, "dota2tracker.template.ranks." + currRank.medal)}${currRank.star} `;
|
|
1893
|
+
const img = await ctx.puppeteer.render(await genImageHTML(currRank, "rank" + (config.rankBroadFun ? "2" : ""), "rank" /* Rank */, ctx, languageTag));
|
|
1545
1894
|
await ctx.broadcast([`${subPlayer.platform}:${subPlayer.guildId}`], message + img);
|
|
1546
1895
|
}
|
|
1547
1896
|
ctx.logger.info(`向 ${subPlayer.platform}:${subPlayer.guildId} 发布段位变动播报信息。`);
|
|
@@ -1556,47 +1905,26 @@ async function apply(ctx, config) {
|
|
|
1556
1905
|
const now = (0, import_moment.default)();
|
|
1557
1906
|
const pendingMatch = pendingMatches[(now.hours() * 60 + now.minutes()) % pendingMatches.length];
|
|
1558
1907
|
try {
|
|
1559
|
-
|
|
1560
|
-
|
|
1561
|
-
|
|
1562
|
-
|
|
1563
|
-
|
|
1564
|
-
|
|
1565
|
-
|
|
1566
|
-
|
|
1567
|
-
|
|
1568
|
-
|
|
1569
|
-
|
|
1570
|
-
|
|
1571
|
-
const img = await ctx.puppeteer.render(genImageHTML(match, config.template_match, "match" /* Match */));
|
|
1572
|
-
for (let commingGuild of pendingMatch.guilds) {
|
|
1573
|
-
let broadMatchMessage = "";
|
|
1574
|
-
let idsToFind = commingGuild.players.map((player) => player.steamId);
|
|
1575
|
-
let broadPlayers = match.players.filter((item) => idsToFind.includes(item.steamAccountId));
|
|
1576
|
-
for (let player of broadPlayers) {
|
|
1577
|
-
const random2 = new import_koishi2.Random(() => enhancedSimpleHashToSeed(`${match.id}-${player.steamAccountId}-${player.playerSlot}`));
|
|
1578
|
-
let broadPlayerMessage = `${player.steamAccount.name}的${random2.pick(getHeroNicknames(player.hero.id, languageTag))}`;
|
|
1579
|
-
if (player.isRadiant == match.didRadiantWin) {
|
|
1580
|
-
if (player.deathContribution < 0.2 || player.killContribution > 0.75 || player.heroDamage / player.networth > 1.5 || player.towerDamage > 1e4 || player.imp > 0)
|
|
1581
|
-
broadPlayerMessage += random2.pick(WIN_POSITIVE);
|
|
1582
|
-
else broadPlayerMessage += random2.pick(WIN_NEGATIVE);
|
|
1583
|
-
} else {
|
|
1584
|
-
if (player.deathContribution < 0.25 || player.killContribution > 0.75 || player.heroDamage / player.networth > 1 || player.towerDamage > 5e3 || player.imp > 0)
|
|
1585
|
-
broadPlayerMessage += random2.pick(LOSE_POSITIVE);
|
|
1586
|
-
else broadPlayerMessage += random2.pick(LOSE_NEGATIVE);
|
|
1587
|
-
}
|
|
1588
|
-
broadPlayerMessage += `。
|
|
1589
|
-
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)}%`;
|
|
1590
|
-
broadMatchMessage += broadPlayerMessage + "\n";
|
|
1908
|
+
let matchQuery = await queryMatchData(pendingMatch.matchId);
|
|
1909
|
+
if (matchQuery.match.parsedDateTime && matchQuery.match.players.filter((player) => player?.stats?.heroDamageReport?.dealtTotal).length > 0 || import_moment.default.unix(matchQuery.match.endDateTime).isBefore(now.subtract(config.dataParsingTimeoutMinutes, "minutes"))) {
|
|
1910
|
+
for (const languageTag of Object.keys(pendingMatch.guilds)) {
|
|
1911
|
+
let match = await formatMatchData(matchQuery, languageTag);
|
|
1912
|
+
const img = await generateMatchImage(match, languageTag);
|
|
1913
|
+
for (let commingGuild of pendingMatch.guilds[languageTag]) {
|
|
1914
|
+
let broadMatchMessage = await generateMatchMessage(match, languageTag, commingGuild);
|
|
1915
|
+
await ctx.broadcast(
|
|
1916
|
+
[`${commingGuild.platform}:${commingGuild.guildId}`],
|
|
1917
|
+
broadMatchMessage + (ctx.config.urlInMessageType.some((type) => type == "match") ? "https://stratz.com/matches/" + match.id : "") + img
|
|
1918
|
+
);
|
|
1919
|
+
ctx.logger.info(`比赛 ${match.id} ${match.parsedDateTime ? "已解析," : "已结束超过1小时仍未被解析,放弃等待解析直接"}生成图片并发布于${commingGuild.platform}:${commingGuild.guildId}。`);
|
|
1591
1920
|
}
|
|
1592
|
-
await ctx.broadcast([`${commingGuild.platform}:${commingGuild.guildId}`], broadMatchMessage + (ctx.config.urlInMessageType.some((type) => type == "match") ? "https://stratz.com/matches/" + match.id : "") + img);
|
|
1593
|
-
ctx.logger.info(`${match.id}${match.parsedDateTime ? "已解析," : "已结束超过1小时仍未被解析,放弃等待解析直接"}生成图片并发布于${commingGuild.platform}:${commingGuild.guildId}。`);
|
|
1594
1921
|
}
|
|
1595
|
-
ctx.
|
|
1922
|
+
ctx.cache.set("dt_sended_match_id", String(pendingMatch.matchId), void 0, days_30);
|
|
1923
|
+
pendingMatches = pendingMatches.filter((item) => item.matchId != pendingMatch.matchId);
|
|
1596
1924
|
} else ctx.logger.info("比赛 %d 尚未解析完成,继续等待。", matchQuery.match.id);
|
|
1597
1925
|
} catch (error) {
|
|
1598
1926
|
ctx.logger.error(error);
|
|
1599
|
-
ctx.
|
|
1927
|
+
await ctx.cache.delete("dt_previous_query_results", String(pendingMatch.matchId));
|
|
1600
1928
|
}
|
|
1601
1929
|
}
|
|
1602
1930
|
});
|
|
@@ -1658,7 +1986,7 @@ KDA:${((player.kills + player.assists) / (player.deaths || 1)).toFixed(2)} [${
|
|
|
1658
1986
|
await ctx.broadcast(
|
|
1659
1987
|
[`${guild.platform}:${guild.guildId}`],
|
|
1660
1988
|
await ctx.puppeteer.render(
|
|
1661
|
-
genImageHTML(
|
|
1989
|
+
await genImageHTML(
|
|
1662
1990
|
{
|
|
1663
1991
|
title,
|
|
1664
1992
|
players: currentsubscribedPlayers.sort((a, b) => {
|
|
@@ -1670,7 +1998,9 @@ KDA:${((player.kills + player.assists) / (player.deaths || 1)).toFixed(2)} [${
|
|
|
1670
1998
|
showCombi
|
|
1671
1999
|
},
|
|
1672
2000
|
"daily",
|
|
1673
|
-
"report" /* Report
|
|
2001
|
+
"report" /* Report */,
|
|
2002
|
+
ctx,
|
|
2003
|
+
await getLanguageTag(void 0, void 0, guild.guildId)
|
|
1674
2004
|
)
|
|
1675
2005
|
)
|
|
1676
2006
|
);
|
|
@@ -1684,41 +2014,58 @@ KDA:${((player.kills + player.assists) / (player.deaths || 1)).toFixed(2)} [${
|
|
|
1684
2014
|
__name(report, "report");
|
|
1685
2015
|
ctx.on("dispose", async () => {
|
|
1686
2016
|
});
|
|
1687
|
-
|
|
1688
|
-
|
|
1689
|
-
|
|
1690
|
-
|
|
1691
|
-
|
|
1692
|
-
|
|
1693
|
-
|
|
1694
|
-
|
|
1695
|
-
|
|
1696
|
-
|
|
1697
|
-
|
|
1698
|
-
|
|
1699
|
-
|
|
1700
|
-
|
|
1701
|
-
|
|
1702
|
-
|
|
1703
|
-
|
|
1704
|
-
|
|
1705
|
-
|
|
1706
|
-
|
|
1707
|
-
|
|
1708
|
-
|
|
1709
|
-
|
|
2017
|
+
function $t(languageTag, key, param) {
|
|
2018
|
+
const keys = Array.isArray(key) ? key : key.split(".");
|
|
2019
|
+
const params = Array.isArray(param) ? param : [param];
|
|
2020
|
+
const constantTranslation = keys.reduce((result2, k) => {
|
|
2021
|
+
return result2?.[k] ?? null;
|
|
2022
|
+
}, constantLocales[languageTag] || {});
|
|
2023
|
+
if (constantTranslation) {
|
|
2024
|
+
if (Array.isArray(params)) {
|
|
2025
|
+
return constantTranslation.replace(/\{(\d+)\}/g, (_, index) => params[+index] || "");
|
|
2026
|
+
}
|
|
2027
|
+
if (typeof params === "object" && params !== null) {
|
|
2028
|
+
return constantTranslation.replace(/\{(\w+)\}/g, (_, key2) => params[key2] || "");
|
|
2029
|
+
}
|
|
2030
|
+
return constantTranslation;
|
|
2031
|
+
}
|
|
2032
|
+
const originalKey = Array.isArray(key) ? key : [key];
|
|
2033
|
+
const result = ctx.i18n.render([languageTag], originalKey, param ?? {}).map((element) => element?.attrs?.content).join("") ?? "";
|
|
2034
|
+
if (result == key) return;
|
|
2035
|
+
return result;
|
|
2036
|
+
}
|
|
2037
|
+
__name($t, "$t");
|
|
2038
|
+
async function genImageHTML(data, template, type, ctx2, languageTag) {
|
|
2039
|
+
const templatePath = import_path2.default.join(`./node_modules/@sjtdev/koishi-plugin-${name}/template/${type}`, template + ".ejs");
|
|
2040
|
+
const templateData = {
|
|
2041
|
+
data,
|
|
2042
|
+
utils: utils_exports,
|
|
2043
|
+
ImageType,
|
|
2044
|
+
ImageFormat,
|
|
2045
|
+
dotaconstants: dotaconstants2,
|
|
2046
|
+
moment: import_moment.default,
|
|
2047
|
+
eh: escapeHTML,
|
|
2048
|
+
$t: templateI18nHelper,
|
|
2049
|
+
languageTag
|
|
2050
|
+
};
|
|
2051
|
+
function templateI18nHelper(key, param) {
|
|
2052
|
+
return $t(languageTag, key, param);
|
|
2053
|
+
}
|
|
2054
|
+
__name(templateI18nHelper, "templateI18nHelper");
|
|
2055
|
+
try {
|
|
2056
|
+
const html = await ejs.renderFile(templatePath, templateData, {
|
|
2057
|
+
strict: false
|
|
1710
2058
|
});
|
|
1711
|
-
|
|
1712
|
-
|
|
1713
|
-
|
|
1714
|
-
|
|
1715
|
-
|
|
1716
|
-
|
|
1717
|
-
}
|
|
1718
|
-
|
|
1719
|
-
return result;
|
|
2059
|
+
if (process.env.NODE_ENV === "development") import_fs2.default.writeFileSync("./node_modules/@sjtdev/koishi-plugin-dota2tracker/temp.html", html);
|
|
2060
|
+
return html;
|
|
2061
|
+
} catch (err) {
|
|
2062
|
+
ctx2.logger.error("Error rendering EJS template:", err);
|
|
2063
|
+
throw err;
|
|
2064
|
+
}
|
|
2065
|
+
}
|
|
2066
|
+
__name(genImageHTML, "genImageHTML");
|
|
1720
2067
|
}
|
|
1721
|
-
__name(
|
|
2068
|
+
__name(apply, "apply");
|
|
1722
2069
|
function enhancedSimpleHashToSeed(inputString) {
|
|
1723
2070
|
const encoded = btoa(inputString);
|
|
1724
2071
|
let total = 0;
|
|
@@ -1732,6 +2079,28 @@ function enhancedSimpleHashToSeed(inputString) {
|
|
|
1732
2079
|
return total % 1e3 / 1e3;
|
|
1733
2080
|
}
|
|
1734
2081
|
__name(enhancedSimpleHashToSeed, "enhancedSimpleHashToSeed");
|
|
2082
|
+
function escapeHTML(str) {
|
|
2083
|
+
if (str == null) return "";
|
|
2084
|
+
return str.replace(/[&<>"']/g, function(match) {
|
|
2085
|
+
const escape = {
|
|
2086
|
+
"&": "&",
|
|
2087
|
+
"<": "<",
|
|
2088
|
+
">": ">",
|
|
2089
|
+
'"': """,
|
|
2090
|
+
"'": "'"
|
|
2091
|
+
};
|
|
2092
|
+
return escape[match];
|
|
2093
|
+
});
|
|
2094
|
+
}
|
|
2095
|
+
__name(escapeHTML, "escapeHTML");
|
|
2096
|
+
function customConvertArrayOfString(str) {
|
|
2097
|
+
try {
|
|
2098
|
+
return JSON.parse(`[${str}]`);
|
|
2099
|
+
} catch (error) {
|
|
2100
|
+
throw error;
|
|
2101
|
+
}
|
|
2102
|
+
}
|
|
2103
|
+
__name(customConvertArrayOfString, "customConvertArrayOfString");
|
|
1735
2104
|
// Annotate the CommonJS export names for ESM import in node:
|
|
1736
2105
|
0 && (module.exports = {
|
|
1737
2106
|
Config,
|