@sjtdev/koishi-plugin-dota2tracker 1.1.2-hotfix.2 → 1.1.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 +163 -55
- package/package.json +3 -2
- package/readme.md +3 -3
- package/template/player/player_1.ejs +3 -2
package/lib/index.js
CHANGED
|
@@ -50,6 +50,7 @@ __export(utils_exports, {
|
|
|
50
50
|
playerisValid: () => playerisValid,
|
|
51
51
|
query: () => query,
|
|
52
52
|
readDirectoryFilesSync: () => readDirectoryFilesSync,
|
|
53
|
+
roundToDecimalPlaces: () => roundToDecimalPlaces,
|
|
53
54
|
sec2time: () => sec2time,
|
|
54
55
|
winRateColor: () => winRateColor
|
|
55
56
|
});
|
|
@@ -189,6 +190,32 @@ function MATCH_INFO(matchId) {
|
|
|
189
190
|
`;
|
|
190
191
|
}
|
|
191
192
|
__name(MATCH_INFO, "MATCH_INFO");
|
|
193
|
+
function MATCHES_FOR_DAILY(steamAccountIds, seconds) {
|
|
194
|
+
return `
|
|
195
|
+
{
|
|
196
|
+
players(steamAccountIds:${JSON.stringify(steamAccountIds)}) {
|
|
197
|
+
steamAccount{id name}
|
|
198
|
+
matches(request:{startDateTime:${seconds} take:50}){
|
|
199
|
+
id
|
|
200
|
+
didRadiantWin
|
|
201
|
+
parsedDateTime
|
|
202
|
+
startDateTime
|
|
203
|
+
players {
|
|
204
|
+
kills
|
|
205
|
+
deaths
|
|
206
|
+
assists
|
|
207
|
+
imp
|
|
208
|
+
isRadiant
|
|
209
|
+
steamAccount {
|
|
210
|
+
id
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
`;
|
|
217
|
+
}
|
|
218
|
+
__name(MATCHES_FOR_DAILY, "MATCHES_FOR_DAILY");
|
|
192
219
|
function VERIFYING_PLAYER(steamAccountId) {
|
|
193
220
|
return `
|
|
194
221
|
{
|
|
@@ -221,7 +248,7 @@ function PLAYERS_LASTMATCH(steamAccountIds) {
|
|
|
221
248
|
`;
|
|
222
249
|
}
|
|
223
250
|
__name(PLAYERS_LASTMATCH, "PLAYERS_LASTMATCH");
|
|
224
|
-
function PLAYER_INFO_WITH_25_MATCHES(steamAccountId) {
|
|
251
|
+
function PLAYER_INFO_WITH_25_MATCHES(steamAccountId, heroId) {
|
|
225
252
|
return `
|
|
226
253
|
{
|
|
227
254
|
player(steamAccountId: ${steamAccountId}) {
|
|
@@ -242,7 +269,7 @@ function PLAYER_INFO_WITH_25_MATCHES(steamAccountId) {
|
|
|
242
269
|
performance {
|
|
243
270
|
imp
|
|
244
271
|
}
|
|
245
|
-
heroesPerformance(take: 25, request: {matchGroupOrderBy: WIN_COUNT
|
|
272
|
+
heroesPerformance(take: 25, request: {matchGroupOrderBy: WIN_COUNT take: 25 ${heroId ? "heroIds:" + heroId : ""}}) {
|
|
246
273
|
hero {
|
|
247
274
|
id
|
|
248
275
|
shortName
|
|
@@ -251,7 +278,7 @@ function PLAYER_INFO_WITH_25_MATCHES(steamAccountId) {
|
|
|
251
278
|
winCount
|
|
252
279
|
matchCount
|
|
253
280
|
}
|
|
254
|
-
matches(request: {take: 25}) {
|
|
281
|
+
matches(request: {take: 25 ${heroId ? "heroIds:" + heroId : ""}}) {
|
|
255
282
|
id
|
|
256
283
|
rank
|
|
257
284
|
lobbyType
|
|
@@ -286,10 +313,10 @@ function PLAYER_INFO_WITH_25_MATCHES(steamAccountId) {
|
|
|
286
313
|
`;
|
|
287
314
|
}
|
|
288
315
|
__name(PLAYER_INFO_WITH_25_MATCHES, "PLAYER_INFO_WITH_25_MATCHES");
|
|
289
|
-
function PLAYER_EXTRA_INFO(steamAccountId, matchCount, totalHeroCount) {
|
|
316
|
+
function PLAYER_EXTRA_INFO(steamAccountId, matchCount, totalHeroCount, heroId) {
|
|
290
317
|
return `{
|
|
291
318
|
player(steamAccountId: ${steamAccountId}) {
|
|
292
|
-
heroesPerformance(take: ${totalHeroCount}, request: {matchGroupOrderBy: MATCH_COUNT, take: ${matchCount}}) {
|
|
319
|
+
heroesPerformance(take: ${totalHeroCount}, request: {matchGroupOrderBy: MATCH_COUNT, take: ${matchCount} ${heroId ? "heroIds:" + heroId : ""}}) {
|
|
293
320
|
hero {
|
|
294
321
|
id
|
|
295
322
|
shortName
|
|
@@ -778,6 +805,11 @@ async function playerisValid(steamAccountId) {
|
|
|
778
805
|
}
|
|
779
806
|
}
|
|
780
807
|
__name(playerisValid, "playerisValid");
|
|
808
|
+
function roundToDecimalPlaces(number, decimalPlaces) {
|
|
809
|
+
const factor = Math.pow(10, decimalPlaces);
|
|
810
|
+
return Math.round(number * factor) / factor;
|
|
811
|
+
}
|
|
812
|
+
__name(roundToDecimalPlaces, "roundToDecimalPlaces");
|
|
781
813
|
|
|
782
814
|
// src/index.ts
|
|
783
815
|
var import_fs2 = __toESM(require("fs"));
|
|
@@ -1055,12 +1087,24 @@ var dotaconstants_add_default = {
|
|
|
1055
1087
|
var import_koishi2 = require("koishi");
|
|
1056
1088
|
var ejs = __toESM(require("ejs"));
|
|
1057
1089
|
var name = "dota2tracker";
|
|
1058
|
-
var usage =
|
|
1090
|
+
var usage = `
|
|
1091
|
+
DOTA2Bot插件-提供自动追踪群友的最新对局的功能(需群友绑定),以及一系列查询功能。
|
|
1092
|
+
**更多信息请进入插件主页查看。**`;
|
|
1059
1093
|
var inject = ["database", "puppeteer", "cron"];
|
|
1060
1094
|
var Config = import_koishi.Schema.intersect([
|
|
1061
1095
|
import_koishi.Schema.object({
|
|
1062
1096
|
STRATZ_API_TOKEN: import_koishi.Schema.string().required().description("※必须。stratz.com的API TOKEN,可在 https://stratz.com/api 获取")
|
|
1063
1097
|
}).description("基础设置"),
|
|
1098
|
+
import_koishi.Schema.object({
|
|
1099
|
+
dailyReportSwitch: import_koishi.Schema.boolean().default(false).description("日报功能").experimental()
|
|
1100
|
+
}),
|
|
1101
|
+
import_koishi.Schema.union([
|
|
1102
|
+
import_koishi.Schema.object({
|
|
1103
|
+
dailyReportSwitch: import_koishi.Schema.const(true).required(),
|
|
1104
|
+
dailyReportHours: import_koishi.Schema.number().min(0).max(23).default(6).description("日报时间小时")
|
|
1105
|
+
}),
|
|
1106
|
+
import_koishi.Schema.object({})
|
|
1107
|
+
]),
|
|
1064
1108
|
import_koishi.Schema.object({
|
|
1065
1109
|
template_match: import_koishi.Schema.union([...readDirectoryFilesSync(`./node_modules/@sjtdev/koishi-plugin-${name}/template/match`)]).default("match_1").description("生成比赛信息图片使用的模板,见 https://github.com/sjtdev/koishi-plugin-dota2tracker/wiki 有模板展示。"),
|
|
1066
1110
|
template_player: import_koishi.Schema.union([...readDirectoryFilesSync(`./node_modules/@sjtdev/koishi-plugin-${name}/template/player`)]).default("player_1").description("生成玩家信息图片使用的模板。(目前仅有一张模板)"),
|
|
@@ -1254,7 +1298,7 @@ async function apply(ctx, config) {
|
|
|
1254
1298
|
queryAndDisplayMatch(session, lastMatchId);
|
|
1255
1299
|
}
|
|
1256
1300
|
});
|
|
1257
|
-
ctx.command("查询玩家 <input_data>", "
|
|
1301
|
+
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) => {
|
|
1258
1302
|
if (session.guild) {
|
|
1259
1303
|
let sessionPlayer;
|
|
1260
1304
|
if (!input_data) {
|
|
@@ -1270,15 +1314,16 @@ async function apply(ctx, config) {
|
|
|
1270
1314
|
return;
|
|
1271
1315
|
}
|
|
1272
1316
|
session.send("正在获取玩家数据,请稍后...");
|
|
1317
|
+
let hero = findingHero(options.hero);
|
|
1273
1318
|
let steamId = flagBindedPlayer?.steamId ?? input_data;
|
|
1274
1319
|
let player;
|
|
1275
1320
|
try {
|
|
1276
|
-
let queryRes = await query(PLAYER_INFO_WITH_25_MATCHES(steamId));
|
|
1321
|
+
let queryRes = await query(PLAYER_INFO_WITH_25_MATCHES(steamId, hero.id));
|
|
1277
1322
|
if (queryRes.status == 200) {
|
|
1278
1323
|
player = queryRes.data.data.player;
|
|
1279
1324
|
} else
|
|
1280
1325
|
throw 0;
|
|
1281
|
-
let queryRes2 = await query(PLAYER_EXTRA_INFO(steamId, player.matchCount, Object.keys(dotaconstants3.heroes).length));
|
|
1326
|
+
let queryRes2 = await query(PLAYER_EXTRA_INFO(steamId, player.matchCount, Object.keys(dotaconstants3.heroes).length, hero.id));
|
|
1282
1327
|
if (queryRes2.status == 200) {
|
|
1283
1328
|
let playerExtra = queryRes2.data.data.player;
|
|
1284
1329
|
let filteredDotaPlus = {};
|
|
@@ -1290,11 +1335,11 @@ async function apply(ctx, config) {
|
|
|
1290
1335
|
};
|
|
1291
1336
|
}
|
|
1292
1337
|
});
|
|
1293
|
-
playerExtra.heroesPerformance.forEach((
|
|
1294
|
-
if (filteredDotaPlus[
|
|
1295
|
-
filteredDotaPlus[
|
|
1296
|
-
filteredDotaPlus[
|
|
1297
|
-
filteredDotaPlus[
|
|
1338
|
+
playerExtra.heroesPerformance.forEach((hero2) => {
|
|
1339
|
+
if (filteredDotaPlus[hero2.hero.id]) {
|
|
1340
|
+
filteredDotaPlus[hero2.hero.id].shortName = hero2.hero.shortName;
|
|
1341
|
+
filteredDotaPlus[hero2.hero.id].winCount = hero2.winCount;
|
|
1342
|
+
filteredDotaPlus[hero2.hero.id].matchCount = hero2.matchCount;
|
|
1298
1343
|
}
|
|
1299
1344
|
});
|
|
1300
1345
|
player.dotaPlus = Object.values(filteredDotaPlus);
|
|
@@ -1307,6 +1352,7 @@ async function apply(ctx, config) {
|
|
|
1307
1352
|
player.heroesPerformanceTop10 = playerExtra.heroesPerformance.slice(0, 10);
|
|
1308
1353
|
} else
|
|
1309
1354
|
throw 0;
|
|
1355
|
+
player.genHero = hero ? true : false;
|
|
1310
1356
|
session.send(await ctx.puppeteer.render(genImageHTML(player, config.template_player, "player" /* Player */)));
|
|
1311
1357
|
} catch (error) {
|
|
1312
1358
|
ctx.logger.error(error);
|
|
@@ -1316,24 +1362,8 @@ async function apply(ctx, config) {
|
|
|
1316
1362
|
});
|
|
1317
1363
|
ctx.command("查询英雄 <input_data>", "查询英雄技能/面板信息").usage("查询英雄的技能说明与各项数据,生成图片发布。\n参数可输入英雄ID、英雄名、英雄常用别名").example("-查询英雄 15").example("-查询英雄 雷泽").example("-查询英雄 电魂").action(async ({ session }, input_data) => {
|
|
1318
1364
|
if (input_data) {
|
|
1319
|
-
let
|
|
1320
|
-
|
|
1321
|
-
id: parseInt(key),
|
|
1322
|
-
names_cn: HEROES_CHINESE[key]
|
|
1323
|
-
}));
|
|
1324
|
-
const mergedMap = /* @__PURE__ */ new Map();
|
|
1325
|
-
[dc_heroes, cn_heroes].forEach((array) => {
|
|
1326
|
-
array.forEach((item) => {
|
|
1327
|
-
const existingItem = mergedMap.get(item.id);
|
|
1328
|
-
if (existingItem)
|
|
1329
|
-
mergedMap.set(item.id, { ...existingItem, ...item });
|
|
1330
|
-
else
|
|
1331
|
-
mergedMap.set(item.id, item);
|
|
1332
|
-
});
|
|
1333
|
-
});
|
|
1334
|
-
let heroes3 = Array.from(mergedMap.values());
|
|
1335
|
-
let findingHero = heroes3.find((hero) => hero.names_cn.includes(input_data) || hero.shortName === input_data.toLowerCase() || hero.id == input_data);
|
|
1336
|
-
if (!findingHero) {
|
|
1365
|
+
let hero = findingHero(input_data);
|
|
1366
|
+
if (!hero) {
|
|
1337
1367
|
session.send("未找到输入的英雄,请确认后重新输入。");
|
|
1338
1368
|
return;
|
|
1339
1369
|
}
|
|
@@ -1356,11 +1386,11 @@ async function apply(ctx, config) {
|
|
|
1356
1386
|
}
|
|
1357
1387
|
} else
|
|
1358
1388
|
throw 0;
|
|
1359
|
-
let queryRes3 = await query(HERO_INFO(
|
|
1389
|
+
let queryRes3 = await query(HERO_INFO(hero.id));
|
|
1360
1390
|
if (queryRes3.status == 200) {
|
|
1361
|
-
let
|
|
1362
|
-
|
|
1363
|
-
await session.send(await ctx.puppeteer.render(genImageHTML(
|
|
1391
|
+
let hero2 = queryRes3.data.data.constants.hero;
|
|
1392
|
+
hero2.talents.forEach((talent) => talent.name_cn = AbilitiesConstantsCN.data.abilities.find((item) => item.id == talent.abilityId).language.displayName);
|
|
1393
|
+
await session.send(await ctx.puppeteer.render(genImageHTML(hero2, config.template_hero, "hero" /* Hero */)));
|
|
1364
1394
|
} else
|
|
1365
1395
|
throw 0;
|
|
1366
1396
|
} catch (error) {
|
|
@@ -1374,29 +1404,13 @@ async function apply(ctx, config) {
|
|
|
1374
1404
|
});
|
|
1375
1405
|
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) => {
|
|
1376
1406
|
if (input_data) {
|
|
1377
|
-
let
|
|
1378
|
-
|
|
1379
|
-
id: parseInt(key),
|
|
1380
|
-
names_cn: HEROES_CHINESE[key]
|
|
1381
|
-
}));
|
|
1382
|
-
const mergedMap = /* @__PURE__ */ new Map();
|
|
1383
|
-
[dc_heroes, cn_heroes].forEach((array) => {
|
|
1384
|
-
array.forEach((item) => {
|
|
1385
|
-
const existingItem = mergedMap.get(item.id);
|
|
1386
|
-
if (existingItem)
|
|
1387
|
-
mergedMap.set(item.id, { ...existingItem, ...item });
|
|
1388
|
-
else
|
|
1389
|
-
mergedMap.set(item.id, item);
|
|
1390
|
-
});
|
|
1391
|
-
});
|
|
1392
|
-
let heroes3 = Array.from(mergedMap.values());
|
|
1393
|
-
let findingHero = heroes3.find((hero) => hero.names_cn.includes(input_data) || hero.shortName === input_data.toLowerCase() || hero.id == input_data);
|
|
1394
|
-
if (!findingHero) {
|
|
1407
|
+
let hero = findingHero(input_data);
|
|
1408
|
+
if (!hero) {
|
|
1395
1409
|
session.send("未找到输入的英雄,请确认后重新输入。");
|
|
1396
1410
|
return;
|
|
1397
1411
|
}
|
|
1398
1412
|
try {
|
|
1399
|
-
let queryRes = await query(HERO_MATCHUP_WINRATE(
|
|
1413
|
+
let queryRes = await query(HERO_MATCHUP_WINRATE(hero.id));
|
|
1400
1414
|
if (queryRes.status == 200) {
|
|
1401
1415
|
let heroStats = queryRes.data.data.heroStats;
|
|
1402
1416
|
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) => {
|
|
@@ -1421,6 +1435,28 @@ async function apply(ctx, config) {
|
|
|
1421
1435
|
}
|
|
1422
1436
|
}
|
|
1423
1437
|
});
|
|
1438
|
+
function findingHero(input) {
|
|
1439
|
+
if (!input)
|
|
1440
|
+
return;
|
|
1441
|
+
let dc_heroes = Object.values(dotaconstants3.heroes).map((hero) => ({ id: hero["id"], name: hero["name"], shortName: hero["name"].match(/^npc_dota_hero_(.+)$/)[1] }));
|
|
1442
|
+
let cn_heroes = Object.keys(HEROES_CHINESE).map((key) => ({
|
|
1443
|
+
id: parseInt(key),
|
|
1444
|
+
names_cn: HEROES_CHINESE[key]
|
|
1445
|
+
}));
|
|
1446
|
+
const mergedMap = /* @__PURE__ */ new Map();
|
|
1447
|
+
[dc_heroes, cn_heroes].forEach((array) => {
|
|
1448
|
+
array.forEach((item) => {
|
|
1449
|
+
const existingItem = mergedMap.get(item.id);
|
|
1450
|
+
if (existingItem)
|
|
1451
|
+
mergedMap.set(item.id, { ...existingItem, ...item });
|
|
1452
|
+
else
|
|
1453
|
+
mergedMap.set(item.id, item);
|
|
1454
|
+
});
|
|
1455
|
+
});
|
|
1456
|
+
let heroes3 = Array.from(mergedMap.values());
|
|
1457
|
+
return heroes3.find((hero) => hero.names_cn.includes(input) || hero.shortName === input.toLowerCase() || hero.id == input);
|
|
1458
|
+
}
|
|
1459
|
+
__name(findingHero, "findingHero");
|
|
1424
1460
|
ctx.on("ready", async () => {
|
|
1425
1461
|
const tables = await ctx.database.tables;
|
|
1426
1462
|
if (!("dt_subscribed_guilds" in tables)) {
|
|
@@ -1443,6 +1479,78 @@ async function apply(ctx, config) {
|
|
|
1443
1479
|
ctx.database.remove("dt_sended_match_id", { sendTime: { $lt: oneMonthAgo } });
|
|
1444
1480
|
ctx.database.remove("dt_previous_query_results", { queryTime: { $lt: oneMonthAgo } });
|
|
1445
1481
|
});
|
|
1482
|
+
if (config.dailyReportSwitch) {
|
|
1483
|
+
ctx.cron(`0 ${config.dailyReportHours} * * *`, async function() {
|
|
1484
|
+
const oneDayAgo = (0, import_moment.default)().subtract(1, "days").unix();
|
|
1485
|
+
const subscribedGuilds = await ctx.database.get("dt_subscribed_guilds", void 0);
|
|
1486
|
+
const subscribedPlayersInGuild = (await ctx.database.get("dt_subscribed_players", void 0)).filter((player) => subscribedGuilds.some((guild) => guild.guildId == player.guildId));
|
|
1487
|
+
let queryRes = await query(
|
|
1488
|
+
MATCHES_FOR_DAILY(
|
|
1489
|
+
subscribedPlayersInGuild.map((player) => player.steamId).filter((value, index, self) => self.indexOf(value) === index),
|
|
1490
|
+
oneDayAgo
|
|
1491
|
+
)
|
|
1492
|
+
);
|
|
1493
|
+
const players = queryRes.data.data.players.filter((player) => player.matches.length > 0);
|
|
1494
|
+
const matches = players.map((player) => player.matches.map((match) => match)).flat().filter((item, index, self) => index === self.findIndex((t) => t.id === item.id));
|
|
1495
|
+
for (let subPlayer of subscribedPlayersInGuild) {
|
|
1496
|
+
let player = players.find((player2) => subPlayer.steamId == player2.steamAccount.id);
|
|
1497
|
+
if (!player)
|
|
1498
|
+
continue;
|
|
1499
|
+
const guildMember = await ctx.bots.find((bot) => bot.platform == subPlayer.platform)?.getGuildMember(subPlayer.guildId, subPlayer.userId);
|
|
1500
|
+
subPlayer.name = subPlayer.nickName || (guildMember?.nick ?? players.find((player2) => player2.steamAccount.id == subPlayer.steamId)?.steamAccount.name);
|
|
1501
|
+
player.winCount = player.matches.filter((match) => match.didRadiantWin == match.players.find((innerPlayer) => innerPlayer.steamAccount.id == player.steamAccount.id).isRadiant).length;
|
|
1502
|
+
player.loseCount = player.matches.length - player.winCount;
|
|
1503
|
+
player.avgKills = roundToDecimalPlaces(player.matches.reduce((acc, match) => acc + match.players.find((innerPlayer) => innerPlayer.steamAccount.id == player.steamAccount.id).kills, 0) / player.matches.length, 2);
|
|
1504
|
+
player.avgDeaths = roundToDecimalPlaces(player.matches.reduce((acc, match) => acc + match.players.find((innerPlayer) => innerPlayer.steamAccount.id == player.steamAccount.id).deaths, 0) / player.matches.length, 2);
|
|
1505
|
+
player.avgAssists = roundToDecimalPlaces(
|
|
1506
|
+
player.matches.reduce((acc, match) => acc + match.players.find((innerPlayer) => innerPlayer.steamAccount.id == player.steamAccount.id).assists, 0) / player.matches.length,
|
|
1507
|
+
2
|
|
1508
|
+
);
|
|
1509
|
+
player.avgKDA = roundToDecimalPlaces((player.avgKills + player.avgAssists) / (player.avgDeaths || 1), 2);
|
|
1510
|
+
player.avgImp = roundToDecimalPlaces(player.matches.reduce((acc, match) => acc + match.players.find((innerPlayer) => innerPlayer.steamAccount.id == player.steamAccount.id).imp, 0) / player.matches.length, 0);
|
|
1511
|
+
subPlayer = Object.assign(subPlayer, player);
|
|
1512
|
+
}
|
|
1513
|
+
for (let guild of subscribedGuilds) {
|
|
1514
|
+
const currentsubscribedPlayers = subscribedPlayersInGuild.filter((player) => player.platform == guild.platform && player.guildId == guild.guildId && player.matches?.length);
|
|
1515
|
+
if (currentsubscribedPlayers.length) {
|
|
1516
|
+
const currentsubscribedPlayersIds = currentsubscribedPlayers.map((player) => player.steamId);
|
|
1517
|
+
const combinationsMap = /* @__PURE__ */ new Map();
|
|
1518
|
+
matches.forEach((match) => {
|
|
1519
|
+
const sortedPlayerIds = match.players.map((player) => player.steamAccount.id).filter((id) => currentsubscribedPlayersIds.includes(id)).sort((a, b) => a.steamId - b.steamId);
|
|
1520
|
+
const key = sortedPlayerIds.join(",");
|
|
1521
|
+
if (!combinationsMap.has(key)) {
|
|
1522
|
+
const players2 = currentsubscribedPlayers.filter((subPlayer) => sortedPlayerIds.includes(subPlayer.steamId));
|
|
1523
|
+
if (players2.length > 0) {
|
|
1524
|
+
const name2 = players2.map((subPlayer) => subPlayer.name).join("/");
|
|
1525
|
+
combinationsMap.set(key, {
|
|
1526
|
+
players: players2,
|
|
1527
|
+
name: name2,
|
|
1528
|
+
winCount: match.didRadiantWin == match.players.find((innerPlayer) => innerPlayer.steamAccount.id == players2[0].steamId).isRadiant ? 1 : 0,
|
|
1529
|
+
matches: [match]
|
|
1530
|
+
});
|
|
1531
|
+
}
|
|
1532
|
+
} else {
|
|
1533
|
+
const combi = combinationsMap.get(key);
|
|
1534
|
+
combi.matches.push(match);
|
|
1535
|
+
combi.winCount += match.didRadiantWin == match.players.find((innerPlayer) => innerPlayer.steamAccount.id == combi.players[0].steamId).isRadiant ? 1 : 0;
|
|
1536
|
+
}
|
|
1537
|
+
});
|
|
1538
|
+
const combinations = Array.from(combinationsMap.values());
|
|
1539
|
+
await ctx.broadcast(
|
|
1540
|
+
[`${guild.platform}:${guild.guildId}`],
|
|
1541
|
+
`昨日总结:
|
|
1542
|
+
${currentsubscribedPlayers.map(
|
|
1543
|
+
(player) => `${player.name}: ${player.winCount}胜${player.loseCount}负 胜率${Math.round(player.winCount / player.matches.length * 100)}%,平均KDA: [${player.avgKills}/${player.avgDeaths}/${player.avgAssists}](${player.avgKDA}),平均表现: ${player.avgImp > 0 ? "+" : ""}${player.avgImp}`
|
|
1544
|
+
).join("\n")}
|
|
1545
|
+
${combinations.map((combi) => `组合[${combi.name}]: ${combi.winCount}胜${combi.matches.length - combi.winCount}负 胜率${Math.round(combi.winCount / combi.matches.length * 100)}%`).join("\n")}`.replace(
|
|
1546
|
+
/\s*\n\s*/g,
|
|
1547
|
+
"\n"
|
|
1548
|
+
)
|
|
1549
|
+
);
|
|
1550
|
+
}
|
|
1551
|
+
}
|
|
1552
|
+
});
|
|
1553
|
+
}
|
|
1446
1554
|
ctx.cron("* * * * *", async function() {
|
|
1447
1555
|
const subscribedGuilds = await ctx.database.get("dt_subscribed_guilds", void 0);
|
|
1448
1556
|
const subscribedPlayersInGuild = (await ctx.database.get("dt_subscribed_players", void 0)).filter((player) => subscribedGuilds.some((guild) => guild.guildId == player.guildId));
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sjtdev/koishi-plugin-dota2tracker",
|
|
3
3
|
"description": "",
|
|
4
|
-
"version": "1.1.
|
|
4
|
+
"version": "1.1.3",
|
|
5
5
|
"main": "lib/index.js",
|
|
6
6
|
"typings": "lib/index.d.ts",
|
|
7
7
|
"files": [
|
|
@@ -11,7 +11,8 @@
|
|
|
11
11
|
"template"
|
|
12
12
|
],
|
|
13
13
|
"contributors": [
|
|
14
|
-
"sjtdev <sh1j1n9ta0@foxmail.com>"
|
|
14
|
+
"sjtdev <sh1j1n9ta0@foxmail.com>",
|
|
15
|
+
"sjtdev"
|
|
15
16
|
],
|
|
16
17
|
"homepage": "https://github.com/sjtdev/koishi-plugin-dota2tracker",
|
|
17
18
|
"repository": {
|
package/readme.md
CHANGED
|
@@ -8,10 +8,10 @@ DOTA2Bot插件-提供自动追踪群友的最新对局的功能(需群友绑
|
|
|
8
8
|
|
|
9
9
|
### 使用
|
|
10
10
|
需在插件配置页填入STRATZ API TOKEN,否则无法使用。(配置中提供了API的获取链接)
|
|
11
|
-
|
|
11
|
+
在希望推送战报信息的群组使用指令`订阅本群`,玩家可使用指令`绑定`来将自身账号与Steam账号绑定,bot会尝试追踪已订阅群组中的绑定玩家的最新对局信息。
|
|
12
12
|
其他查询功能见下方指令说明。
|
|
13
|
-
**直接调用help指令可获取更详细的说明,调用【指令 -h】还会有用法示例。(例如:订阅本群 -h)**
|
|
14
|
-
**更新日志见[changelog](changelog.md)
|
|
13
|
+
**直接调用help指令可获取更详细的说明,调用【指令 -h】还会有用法示例。(例如:订阅本群 -h)**
|
|
14
|
+
**更新日志见[changelog](changelog.md)**
|
|
15
15
|
|
|
16
16
|
### 指令
|
|
17
17
|
指令 <必填参数> [可选参数]
|
|
@@ -530,13 +530,14 @@
|
|
|
530
530
|
</tbody>
|
|
531
531
|
</table>
|
|
532
532
|
<div class="plus">
|
|
533
|
-
<%- player.
|
|
533
|
+
<%- !player.genHero?
|
|
534
|
+
player.dotaPlus.map((hero) => `
|
|
534
535
|
<div class="hero">
|
|
535
536
|
<img src="${utils.getImageUrl(hero.shortName, ImageType.Heroes)}" alt="" />
|
|
536
537
|
<div class="level"><img src="${utils.getImageUrl("hero_badge_" + Math.ceil((hero.level + 1) / 6))}" alt="" /><span>${hero.level}</span></div>
|
|
537
538
|
<span>${((hero.winCount / hero.matchCount) * 100).toFixed(2)}%</span>
|
|
538
539
|
<span>${hero.matchCount}</span>
|
|
539
|
-
</div>`).join("") %>
|
|
540
|
+
</div>`).join(""):"" %>
|
|
540
541
|
</div>
|
|
541
542
|
</div>
|
|
542
543
|
</body>
|