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