@sjtdev/koishi-plugin-dota2tracker 1.2.3 → 1.2.5-fix2
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/changelog.md +13 -2
- package/lib/index.js +47 -20
- package/package.json +2 -1
- package/template/hero/hero_1.ejs +0 -4
- package/template/player/player_1.ejs +11 -9
package/changelog.md
CHANGED
|
@@ -1,6 +1,17 @@
|
|
|
1
|
+
### 1.2.5-fix
|
|
2
|
+
**修复**:使用临时替代方案修复由koishi-4.17.9的bug引起的无法主动发送消息(播报战报等),待koishi更新修复后回滚此改动。
|
|
3
|
+
|
|
4
|
+
### 1.2.5
|
|
5
|
+
**改进**:优化`查询玩家`图片中近期战绩列表内未解析比赛的显示效果
|
|
6
|
+
**修复**:修复`查询英雄`图片技能属性名多显示了一个冒号的问题
|
|
7
|
+
|
|
8
|
+
### 1.2.4
|
|
9
|
+
**修复**:修正调用help指令时本插件某些指令的说明错误
|
|
10
|
+
**修复**:修复`取消订阅`指令失效的问题
|
|
11
|
+
|
|
1
12
|
### 1.2.3
|
|
2
13
|
**修复**:修复了比赛战报图片中称号`摸`判定不正确的问题
|
|
3
|
-
|
|
14
|
+
**改进**:微调了比赛战报图片模板`match_2`中称号的显示样式
|
|
4
15
|
|
|
5
16
|
### 1.2.2
|
|
6
17
|
**移除**:取消`查询英雄`的缓存功能,原因为valve的API返回的数据可能包含未本地化的字段(例如这次的7.36b更新后获取到的很多改动后技能说明暂时都是英文),这些数据无法根据版本判断是否需要更新缓存。
|
|
@@ -82,4 +93,4 @@
|
|
|
82
93
|
|
|
83
94
|
### 1.1.0
|
|
84
95
|
**改进**:使用ejs重写模板相关代码使其模块化,使新增模板更方便
|
|
85
|
-
**新增**:为比赛信息添加了仿MAX+模板,效果可见[match_2](
|
|
96
|
+
**新增**:为比赛信息添加了仿MAX+模板,效果可见[match_2](https://github.com/sjtdev/koishi-plugin-dota2tracker/wiki/match_2),可在插件配置中切换
|
package/lib/index.js
CHANGED
|
@@ -302,6 +302,7 @@ function PLAYER_INFO_WITH_25_MATCHES(steamAccountId, heroId) {
|
|
|
302
302
|
lobbyType
|
|
303
303
|
gameMode
|
|
304
304
|
startDateTime
|
|
305
|
+
parsedDateTime
|
|
305
306
|
durationSeconds
|
|
306
307
|
didRadiantWin
|
|
307
308
|
topLaneOutcome
|
|
@@ -1232,14 +1233,14 @@ async function apply(ctx, config) {
|
|
|
1232
1233
|
if (session.guild) {
|
|
1233
1234
|
let cancelingGuild = (await ctx.database.get("dt_subscribed_guilds", { guildId: session.event.channel.id, platform: session.event.platform }))[0];
|
|
1234
1235
|
if (cancelingGuild) {
|
|
1235
|
-
ctx.database.remove("dt_subscribed_guilds", session.event.channel.id);
|
|
1236
|
+
ctx.database.remove("dt_subscribed_guilds", { guildId: session.event.channel.id, platform: session.event.platform });
|
|
1236
1237
|
session.send("取消订阅成功。");
|
|
1237
1238
|
return;
|
|
1238
1239
|
}
|
|
1239
1240
|
} else
|
|
1240
1241
|
session.send("本群尚未订阅,无需取消订阅。");
|
|
1241
1242
|
});
|
|
1242
|
-
ctx.command("绑定 <steam_id> [nick_name]", "绑定SteamID,并起一个别名(也可以不起)").usage("将你的SteamID与你的账号绑定,若本群已订阅将会实时获取你的新比赛数据发布至群中。").example("
|
|
1243
|
+
ctx.command("绑定 <steam_id> [nick_name]", "绑定SteamID,并起一个别名(也可以不起)").usage("将你的SteamID与你的账号绑定,若本群已订阅将会实时获取你的新比赛数据发布至群中。").example("绑定 123456789").example("绑定 123456789 张三").action(async ({ session }, steam_id, nick_name) => {
|
|
1243
1244
|
if (session.guild) {
|
|
1244
1245
|
if (!steam_id || !/^\d{1,11}$/.test(steam_id)) {
|
|
1245
1246
|
session.send("SteamID无效。");
|
|
@@ -1286,7 +1287,7 @@ async function apply(ctx, config) {
|
|
|
1286
1287
|
session.send("尚未绑定,无需取消绑定。");
|
|
1287
1288
|
}
|
|
1288
1289
|
});
|
|
1289
|
-
ctx.command("改名 <nick_name>", "修改绑定时设定的别名").example("
|
|
1290
|
+
ctx.command("改名 <nick_name>", "修改绑定时设定的别名").example("改名 李四").action(async ({ session }, nick_name) => {
|
|
1290
1291
|
if (session.guild) {
|
|
1291
1292
|
let sessionPlayer = (await ctx.database.get("dt_subscribed_players", { guildId: session.event.channel.id, platform: session.event.platform, userId: session.event.user.id }))[0];
|
|
1292
1293
|
if (sessionPlayer) {
|
|
@@ -1363,7 +1364,7 @@ async function apply(ctx, config) {
|
|
|
1363
1364
|
}
|
|
1364
1365
|
}
|
|
1365
1366
|
__name(queryAndDisplayMatch, "queryAndDisplayMatch");
|
|
1366
|
-
ctx.command("查询比赛 <match_id>", "查询比赛ID").usage("查询指定比赛ID的比赛数据,生成图片发布。").example("
|
|
1367
|
+
ctx.command("查询比赛 <match_id>", "查询比赛ID").usage("查询指定比赛ID的比赛数据,生成图片发布。").example("查询比赛 1234567890").action(async ({ session }, match_id) => {
|
|
1367
1368
|
if (!match_id) {
|
|
1368
1369
|
session.send("请输入比赛ID。");
|
|
1369
1370
|
return;
|
|
@@ -1376,7 +1377,7 @@ async function apply(ctx, config) {
|
|
|
1376
1377
|
session.send("正在搜索对局详情,请稍后...");
|
|
1377
1378
|
queryAndDisplayMatch(session, match_id);
|
|
1378
1379
|
});
|
|
1379
|
-
ctx.command("查询最近比赛 [input_data]", "查询玩家的最近比赛").usage("查询指定玩家的最近一场比赛的比赛数据,生成图片发布。\n参数可输入该玩家的SteamID或已在本群绑定玩家的别名,无参数时尝试查询调用指令玩家的SteamID").example("
|
|
1380
|
+
ctx.command("查询最近比赛 [input_data]", "查询玩家的最近比赛").usage("查询指定玩家的最近一场比赛的比赛数据,生成图片发布。\n参数可输入该玩家的SteamID或已在本群绑定玩家的别名,无参数时尝试查询调用指令玩家的SteamID").example("查询最近比赛 123456789").example("查询最近比赛 张三").action(async ({ session }, input_data) => {
|
|
1380
1381
|
if (session.guild) {
|
|
1381
1382
|
let sessionPlayer;
|
|
1382
1383
|
if (!input_data) {
|
|
@@ -1402,7 +1403,7 @@ async function apply(ctx, config) {
|
|
|
1402
1403
|
queryAndDisplayMatch(session, lastMatchId);
|
|
1403
1404
|
}
|
|
1404
1405
|
});
|
|
1405
|
-
ctx.command("查询玩家 <input_data>", "查询玩家信息,可指定英雄").usage("查询指定玩家的个人信息与最近战绩,生成图片发布。\n参数可输入该玩家的SteamID或已在本群绑定玩家的别名,无参数时尝试查询调用指令玩家的SteamID").option("hero", "-o <value:string> 查询玩家指定英雄使用情况(同其他英雄查询,可用简称与ID)").example("
|
|
1406
|
+
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) => {
|
|
1406
1407
|
if (session.guild) {
|
|
1407
1408
|
let sessionPlayer;
|
|
1408
1409
|
if (!input_data) {
|
|
@@ -1469,7 +1470,7 @@ async function apply(ctx, config) {
|
|
|
1469
1470
|
}
|
|
1470
1471
|
}
|
|
1471
1472
|
});
|
|
1472
|
-
ctx.command("查询英雄 <input_data>", "查询英雄技能/面板信息").usage("查询英雄的技能说明与各项数据,生成图片发布。\n参数可输入英雄ID、英雄名、英雄常用别名").option("random", "-r 随机选择英雄").example("
|
|
1473
|
+
ctx.command("查询英雄 <input_data>", "查询英雄技能/面板信息").usage("查询英雄的技能说明与各项数据,生成图片发布。\n参数可输入英雄ID、英雄名、英雄常用别名").option("random", "-r 随机选择英雄").example("查询英雄 15").example("查询英雄 雷泽").example("查询英雄 电魂").action(async ({ session, options }, input_data) => {
|
|
1473
1474
|
if (options.random)
|
|
1474
1475
|
input_data = random.pick(Object.keys(HEROES_CHINESE));
|
|
1475
1476
|
if (input_data) {
|
|
@@ -1558,7 +1559,7 @@ async function apply(ctx, config) {
|
|
|
1558
1559
|
session.send("请输入参数。");
|
|
1559
1560
|
}
|
|
1560
1561
|
});
|
|
1561
|
-
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("
|
|
1562
|
+
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) => {
|
|
1562
1563
|
if (input_data) {
|
|
1563
1564
|
let hero = findingHero(input_data);
|
|
1564
1565
|
if (!hero) {
|
|
@@ -1689,17 +1690,23 @@ async function apply(ctx, config) {
|
|
|
1689
1690
|
}
|
|
1690
1691
|
});
|
|
1691
1692
|
const combinations = Array.from(combinationsMap.values());
|
|
1692
|
-
|
|
1693
|
-
|
|
1694
|
-
|
|
1695
|
-
|
|
1696
|
-
|
|
1697
|
-
|
|
1698
|
-
|
|
1699
|
-
|
|
1700
|
-
"\n"
|
|
1701
|
-
|
|
1702
|
-
|
|
1693
|
+
try {
|
|
1694
|
+
await sendMessageToChannel(
|
|
1695
|
+
ctx,
|
|
1696
|
+
guild.guildId,
|
|
1697
|
+
// [`${guild.platform}:${guild.guildId}`],
|
|
1698
|
+
`昨日总结:
|
|
1699
|
+
${currentsubscribedPlayers.map(
|
|
1700
|
+
(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}`
|
|
1701
|
+
).join("\n")}
|
|
1702
|
+
${combinations.map((combi) => `组合[${combi.name}]: ${combi.winCount}胜${combi.matches.length - combi.winCount}负 胜率${Math.round(combi.winCount / combi.matches.length * 100)}%`).join("\n")}`.replace(
|
|
1703
|
+
/\s*\n\s*/g,
|
|
1704
|
+
"\n"
|
|
1705
|
+
)
|
|
1706
|
+
);
|
|
1707
|
+
} catch (error) {
|
|
1708
|
+
ctx.logger.error(error);
|
|
1709
|
+
}
|
|
1703
1710
|
}
|
|
1704
1711
|
}
|
|
1705
1712
|
});
|
|
@@ -1765,7 +1772,7 @@ async function apply(ctx, config) {
|
|
|
1765
1772
|
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)}%`;
|
|
1766
1773
|
broadMatchMessage += broadPlayerMessage + "\n";
|
|
1767
1774
|
}
|
|
1768
|
-
await ctx
|
|
1775
|
+
await sendMessageToChannel(ctx, commingGuild, broadMatchMessage + img);
|
|
1769
1776
|
ctx.logger.info(`${match.id}${match.parsedDateTime ? "已解析," : "已结束超过1小时仍未被解析,放弃解析直接"}生成图片并发布于${commingGuild.platform}:${commingGuild.guildId}。`);
|
|
1770
1777
|
}
|
|
1771
1778
|
if (match.parsedDateTime)
|
|
@@ -1806,6 +1813,26 @@ function genImageHTML(data, template, type) {
|
|
|
1806
1813
|
return result;
|
|
1807
1814
|
}
|
|
1808
1815
|
__name(genImageHTML, "genImageHTML");
|
|
1816
|
+
async function sendMessageToChannel(ctx, commingGuild, broadMatchMessage) {
|
|
1817
|
+
try {
|
|
1818
|
+
const targetChannels = await ctx.database.get("channel", { id: commingGuild.guildId, platform: commingGuild.platform });
|
|
1819
|
+
if (targetChannels.length === 1) {
|
|
1820
|
+
const bot = ctx.bots.find((bot2) => bot2.userId === targetChannels[0].assignee);
|
|
1821
|
+
if (bot) {
|
|
1822
|
+
await bot.sendMessage(commingGuild.guildId, broadMatchMessage);
|
|
1823
|
+
} else {
|
|
1824
|
+
throw new Error("指定的bot未找到。");
|
|
1825
|
+
}
|
|
1826
|
+
} else if (targetChannels.length > 1) {
|
|
1827
|
+
throw new Error("有复数个bot存在于该群组/频道,请移除多余bot。");
|
|
1828
|
+
} else {
|
|
1829
|
+
throw new Error("未找到目标群组/频道。");
|
|
1830
|
+
}
|
|
1831
|
+
} catch (error) {
|
|
1832
|
+
throw error;
|
|
1833
|
+
}
|
|
1834
|
+
}
|
|
1835
|
+
__name(sendMessageToChannel, "sendMessageToChannel");
|
|
1809
1836
|
// Annotate the CommonJS export names for ESM import in node:
|
|
1810
1837
|
0 && (module.exports = {
|
|
1811
1838
|
Config,
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sjtdev/koishi-plugin-dota2tracker",
|
|
3
3
|
"description": "koishi插件-追踪群友的DOTA2对局",
|
|
4
|
-
"version": "1.2.
|
|
4
|
+
"version": "1.2.5-fix2",
|
|
5
5
|
"main": "lib/index.js",
|
|
6
6
|
"typings": "lib/index.d.ts",
|
|
7
7
|
"files": [
|
|
@@ -39,6 +39,7 @@
|
|
|
39
39
|
"zh": "追踪群友的DOTA2对局"
|
|
40
40
|
},
|
|
41
41
|
"required": [
|
|
42
|
+
"http",
|
|
42
43
|
"database",
|
|
43
44
|
"puppeteer",
|
|
44
45
|
"cron"
|
package/template/hero/hero_1.ejs
CHANGED
|
@@ -503,25 +503,27 @@
|
|
|
503
503
|
</tr>
|
|
504
504
|
</thead>
|
|
505
505
|
<tbody>
|
|
506
|
-
<%- player.matches.map((match) =>
|
|
507
|
-
|
|
508
|
-
|
|
506
|
+
<%- player.matches.map((match) => {
|
|
507
|
+
const innerPlayer = match.players[0];
|
|
508
|
+
return `
|
|
509
|
+
<tr class="match ${match.didRadiantWin == innerPlayer.isRadiant ? "win" : "lose"}">
|
|
510
|
+
<td>${match.parsedDateTime ? match.id : `<p>${match.id}</p><p>(未解析)</p>`}</td>
|
|
509
511
|
<td>
|
|
510
512
|
<p>${d2a.lobbyTypes[match.lobbyType] || match.lobbyType}</p>
|
|
511
513
|
<p>${d2a.gameMode[match.gameMode] || match.gameMode}</p>
|
|
512
514
|
</td>
|
|
513
|
-
<td><img alt="" src="${utils.getImageUrl(
|
|
515
|
+
<td><img alt="" src="${utils.getImageUrl(innerPlayer.hero.shortName, ImageType.HeroIcons)}" /></td>
|
|
514
516
|
<td style="line-height: 20px">
|
|
515
|
-
<p>${((
|
|
516
|
-
(match
|
|
517
|
-
<p>${
|
|
517
|
+
<p>${((innerPlayer.kills + innerPlayer.assists) / Math.max(1, innerPlayer.deaths)).toFixed(2)} (${match.parsedDateTime?((((innerPlayer.kills + innerPlayer.assists) /
|
|
518
|
+
(match[(innerPlayer.isRadiant ? "radiant" : "dire")+"Kills"]?.reduce((acc, cva) => acc + cva, 0))) * 100)?.toFixed(0)):"?"}%)</p>
|
|
519
|
+
<p>${innerPlayer.kills}/${innerPlayer.deaths}/${innerPlayer.assists}</p>
|
|
518
520
|
</td>
|
|
519
521
|
<td><div class="player_lane ${match.laneResult}">${laneSVG[match.laneResult]}</div></td>
|
|
520
522
|
<td style="line-height: 20px">${moment(new Date(match.startDateTime * 1000)).format("YYYY-MM-DD HH:mm:ss").slice(2)}</td>
|
|
521
523
|
<td>${utils.sec2time(match.durationSeconds)}</td>
|
|
522
|
-
<td>${(
|
|
524
|
+
<td>${innerPlayer.imp ? ((innerPlayer.imp > 0 ? "+" : "") + innerPlayer.imp) : "?"}</td>
|
|
523
525
|
<td><img class="medal" src="${utils.getImageUrl("medal_" + match.rank?.toString().split("")[0])}" style="width: 100%" /></td>
|
|
524
|
-
</tr>`).join("")%>
|
|
526
|
+
</tr>`}).join("")%>
|
|
525
527
|
</tbody>
|
|
526
528
|
</table>
|
|
527
529
|
<div class="plus">
|