@sjtdev/koishi-plugin-dota2tracker 2.2.0 → 2.2.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@sjtdev/koishi-plugin-dota2tracker",
3
3
  "description": "koishi插件-追踪群友的DOTA2对局",
4
- "version": "2.2.0",
4
+ "version": "2.2.2",
5
5
  "main": "lib/index.js",
6
6
  "typings": "lib/index.d.ts",
7
7
  "files": [
@@ -27,11 +27,17 @@
27
27
  "dota2"
28
28
  ],
29
29
  "dependencies": {
30
+ "axios": "^1.13.2",
30
31
  "dotaconstants": "^9.5.0",
31
32
  "ejs": "^3.1.10",
33
+ "https-proxy-agent": "^7.0.6",
32
34
  "luxon": "^3.8.0-alpha.1"
33
35
  },
36
+ "devDependencies": {
37
+ "@koishijs/client": "^5.30.11"
38
+ },
34
39
  "peerDependencies": {
40
+ "@koishijs/plugin-console": "^5.30.11",
35
41
  "koishi": "^4.18.9"
36
42
  },
37
43
  "koishi": {
@@ -41,7 +47,6 @@
41
47
  },
42
48
  "service": {
43
49
  "required": [
44
- "http",
45
50
  "database",
46
51
  "puppeteer",
47
52
  "cache"
@@ -55,4 +60,4 @@
55
60
  "en-US"
56
61
  ]
57
62
  }
58
- }
63
+ }
@@ -27,6 +27,15 @@
27
27
 
28
28
  return darkenedHex;
29
29
  } %>
30
+ <% function calcFacetNameFontSize(name) {
31
+ if (name) {
32
+ if (name.length <= 4) return "11px";
33
+ else if (name.length == 5) return "8px";
34
+ else if (name.length >= 6) return "7px";
35
+ }
36
+ return "10px"
37
+ }
38
+ %>
30
39
  <nav>
31
40
  <div class="match_id">
32
41
  <p><%= $t("dota2tracker.template.match_id_").slice(0, -1) %> <%-match.id%></p>
@@ -87,7 +96,7 @@
87
96
  <% if (player.facet) { %>
88
97
  <img src="<%- getImageUrl(player.facet.icon, ImageType.IconsFacets) %>">
89
98
  <% } %>
90
- <span <%- `style="font-size: ${player.facet?.displayName?.length > 4 ? 8 : 11}px;"`%>>
99
+ <span <%- `style="font-size: ${calcFacetNameFontSize(player.facet?.displayName)};"`%>>
91
100
  <p><%= player.facet?.displayName ?? '?' %></p>
92
101
  </span>
93
102
  </div>
@@ -140,8 +140,11 @@
140
140
  fill="none"
141
141
  stroke="rgba(100, 100, 100, 0.3)"
142
142
  stroke-width="1"/>
143
-
143
+ <% if (match.odParsed) { %>
144
+ <text x="30" y="7" fill="#ccc" font-size="12"><%= $t("dota2tracker.template.opendota.gold_t") %></text>
145
+ <% } else { %>
144
146
  <text x="30" y="7" font-size="12"><%= $t("dota2tracker.template.networth") %></text>
147
+ <% } %>
145
148
  </g>
146
149
 
147
150
  <!-- 经验(折线2) -->
@@ -179,9 +182,27 @@
179
182
  yScale = (svgHeight - padding * 2) / maxNetworth;
180
183
  %>
181
184
  <!-- 新增的经济图表 -->
182
- <svg width="<%= svgWidth %>" height="<%= svgHeight %>" xmlns="http://www.w3.org/2000/svg">
183
- <text x="50%" y="30" text-anchor="middle" font-size="16" font-weight="bold"><%= $t("dota2tracker.template.networth") %></text>
184
- <!-- 横轴线与标签 -->
185
+ <svg width="<%= svgWidth %>" height="<%= svgHeight %>" xmlns="http://www.w3.org/2000/svg">
186
+ <%# 检查数据源是否为 OpenDota %>
187
+ <% if (match.odParsed) { %>
188
+ <%# OpenDota 分支:显示灰色标题和居中提示 %>
189
+ <text x="50%" y="30" text-anchor="middle" font-size="16" font-weight="bold" fill="#ccc">
190
+ <%# 标题:保持原始位置,修改文本和颜色 %>
191
+ <%= $t("dota2tracker.template.opendota.networth_unavailable") %>
192
+ </text>
193
+ <text x="50%" y="<%= svgHeight / 2 + 10 %>" text-anchor="middle" font-size="12" fill="#ccc">
194
+ <%# 提示:水平居中,大致垂直居中,灰色 %>
195
+ <%= $t("dota2tracker.template.opendota.networth_unavailable_reason") %>
196
+ </text>
197
+
198
+ <% } else { %>
199
+
200
+ <%# 非 OpenDota 分支(例如 Stratz):渲染完整的图表 %>
201
+ <text x="50%" y="30" text-anchor="middle" font-size="16" font-weight="bold">
202
+ <%= $t("dota2tracker.template.networth") %> <%# 原始标题 %>
203
+ </text>
204
+
205
+ <%# --- 你现有的图表绘制代码开始 --- %>
185
206
  <% for (let i = 0; i < 5; i++) { %>
186
207
  <% const y = padding + i * ((svgHeight - padding * 2) / 4) %>
187
208
  <line x1="<%= padding %>" y1="<%= y %>" x2="<%= svgWidth - padding %>" y2="<%= y %>" stroke="gray" stroke-width="1" />
@@ -233,5 +254,8 @@
233
254
  />
234
255
  <% }) %>
235
256
  </g>
236
- </svg>
257
+ <%# --- 你现有的图表绘制代码结束 --- %>
258
+
259
+ <% } %>
260
+ </svg>
237
261
  </div>
@@ -52,6 +52,7 @@ body {
52
52
  }
53
53
 
54
54
  .lane_outcome {
55
+ position: relative;
55
56
  display: flex;
56
57
  flex-direction: column;
57
58
  width: 386px;
@@ -85,11 +86,11 @@ body {
85
86
  height: 32px;
86
87
  }
87
88
 
88
- .lane_outcome .panel .lane > .title > p:nth-child(1){
89
+ .lane_outcome .panel .lane > .title > p:nth-child(1) {
89
90
  font-size: 12px;
90
91
  }
91
92
 
92
- .lane_outcome .panel .lane > .title > p:nth-child(2){
93
+ .lane_outcome .panel .lane > .title > p:nth-child(2) {
93
94
  font-size: 14px;
94
95
  }
95
96
 
@@ -104,7 +105,7 @@ body {
104
105
  align-items: center;
105
106
  }
106
107
 
107
- .lane_outcome .panel .lane img.hero{
108
+ .lane_outcome .panel .lane img.hero {
108
109
  width: 24px;
109
110
  height: 24px;
110
111
  }
@@ -129,3 +130,14 @@ body {
129
130
  dominant-baseline: middle; /* 垂直居中 */
130
131
  white-space: nowrap; /* 防止换行 */
131
132
  }
133
+
134
+ .lane_outcome .subtitle {
135
+ position: absolute;
136
+ inset: 0;
137
+ top: 36px;
138
+ text-align: center;
139
+ color: #ccc;
140
+ font-size: 12px;
141
+ margin: 0;
142
+ z-index: 1;
143
+ }
@@ -60,13 +60,24 @@ function generateLevelCircle(xp) {
60
60
 
61
61
  function generateDetails(rivals) {
62
62
  const svgHeight = 32;
63
-
64
63
  rivals.sort((a, b) => b.isRadiant - a.isRadiant);
64
+
65
65
  const gold = { radiant: rivals[0].stats.networthPerMinute.at(Math.min(10, rivals[0].stats.networthPerMinute.length - 1)), dire: rivals[1].stats.networthPerMinute.at(Math.min(10, rivals[1].stats.networthPerMinute.length - 1)) };
66
- const kills = { radiant: rivals[0].stats.killEvents?.filter(e => e.time <= 600).length || 0, dire: rivals[1].stats.killEvents?.filter(e => e.time <= 600).length || 0 }
67
- const deaths = { radiant: rivals[0].stats.deathEvents?.filter(e => e.time <= 600).length || 0, dire: rivals[1].stats.deathEvents?.filter(e => e.time <= 600).length || 0 }
68
- const assists = { radiant: rivals[0].stats.assistEvents?.filter(e => e.time <= 600).length || 0, dire: rivals[1].stats.assistEvents?.filter(e => e.time <= 600).length || 0 }
69
- const goldSplit = gold.radiant / (gold.radiant + gold.dire);
66
+ let kills = { radiant: 0, dire: 0 };
67
+ let deaths = { radiant: 0, dire: 0 };
68
+ let assists = { radiant: 0, dire: 0 };
69
+ let xp = { radiant: 0, dire: 0 };
70
+ const totalGold = gold.radiant + gold.dire;
71
+ const goldSplit = gold.radiant / (totalGold || 1);
72
+ if (match.odParsed) {
73
+ kills = { radiant: "-", dire: "-" };
74
+ deaths = { radiant: "-", dire: "-" };
75
+ assists = { radiant: "-", dire: "-" };
76
+ } else {
77
+ kills = { radiant: rivals[0].stats.killEvents?.filter(e => e.time <= 600).length || 0, dire: rivals[1].stats.killEvents?.filter(e => e.time <= 600).length || 0 }
78
+ deaths = { radiant: rivals[0].stats.deathEvents?.filter(e => e.time <= 600).length || 0, dire: rivals[1].stats.deathEvents?.filter(e => e.time <= 600).length || 0 }
79
+ assists = { radiant: rivals[0].stats.assistEvents?.filter(e => e.time <= 600).length || 0, dire: rivals[1].stats.assistEvents?.filter(e => e.time <= 600).length || 0 }
80
+ }
70
81
  return `
71
82
  <div class="details">
72
83
  <img src="${getImageUrl(rivals[0].hero.shortName, ImageType.HeroIcons)}" class="hero radiant" />
@@ -87,14 +98,14 @@ ${generateLevelCircle(rivals[0].stats.experiencePerMinute.slice(0, Math.min(11,
87
98
  dominant-baseline="middle"
88
99
  fill="#fff"
89
100
  font-size="10"
90
- text-anchor="start">${gold.radiant}</text>
101
+ text-anchor="start">${match.odParsed ? "~" : ""}${gold.radiant}</text>
91
102
 
92
103
  <!-- 右侧数值(夜魇) -->
93
104
  <text x="175" y="50%"
94
105
  dominant-baseline="middle"
95
106
  fill="#fff"
96
107
  font-size="10"
97
- text-anchor="end">${gold.dire}</text>
108
+ text-anchor="end">${match.odParsed ? "~" : ""}${gold.dire}</text>
98
109
 
99
110
  <!-- 差值(上方) -->
100
111
  <text x="${180 * goldSplit}"
@@ -115,6 +126,9 @@ ${generateLevelCircle(rivals[1].stats.experiencePerMinute.slice(0, Math.min(11,
115
126
  %>
116
127
  <div class="lane_outcome">
117
128
  <h4 class="title"><%= $t("dota2tracker.template.lane") %></h4>
129
+ <% if (match.odParsed) { %>
130
+ <p class="subtitle"><%= $t("dota2tracker.template.opendota.lane_outcome_tip") %></p>
131
+ <% } %>
118
132
  <div class="panel">
119
133
  <div class="lane">
120
134
  <div class="title">
@@ -90,30 +90,38 @@
90
90
  </head>
91
91
  <% const {name, avatar, isRising, prevRank, currRank, date} = data; %>
92
92
  <% const kind = isRising ? "xi" : "bei"; %>
93
- <% const rankInfo = {
94
- name,
95
- avatar: `<img src="${avatar}" />`,
96
- prev: `<span class="rank prev">${$t("dota2tracker.template.ranks."+prevRank.medal)}${prevRank.leader ?? prevRank.star}</span>`,
97
- curr: `<span class="rank curr">${$t("dota2tracker.template.ranks."+currRank.medal)}${currRank.leader ?? currRank.star}</span>`,
98
- } %>
93
+ <%
94
+ // 1. 准备好要注入的 HTML
95
+ const avatarHtml = `<img src="${avatar}" />`;
96
+ const prevHtml = `<span class="rank prev">${$t("dota2tracker.template.ranks."+prevRank.medal)}${prevRank.leader ?? prevRank.star}</span>`;
97
+ const currHtml = `<span class="rank curr">${$t("dota2tracker.template.ranks."+currRank.medal)}${currRank.leader ?? currRank.star}</span>`;
98
+
99
+ // 2. 先处理文本插值
100
+ const messageTemplate = isRising
101
+ ? $t("dota2tracker.template.rank_fun_up_message", { name: name })
102
+ : $t("dota2tracker.template.rank_fun_down_message", { name: name });
103
+
104
+ // 3. 手动将占位符替换为 HTML
105
+ const finalMessage = messageTemplate
106
+ .replace('AVATAR_PLACEHOLDER', avatarHtml)
107
+ .replace('PREV_PLACEHOLDER', prevHtml)
108
+ .replace('CURR_PLACEHOLDER', currHtml);
109
+ %>
99
110
  <body class="<%= kind %>" <%- `style="background-image: url( ${getImageUrl(kind, undefined, "jpg")} )"`%>>
100
111
  <div class="wrapper">
101
112
  <p class="<%= kind %>">
102
- <%- kind == "xi" ?
103
- $t("dota2tracker.template.rank_fun_up_message", rankInfo) :
104
- $t("dota2tracker.template.rank_fun_down_message", rankInfo)
105
- %>
113
+ <%- finalMessage %>
106
114
  </p>
107
115
  <p></p>
108
116
  <div class="ranks">
109
117
  <div class="rank prev">
110
- <img src="<%= getImageUrl('medal_' +(prevRank.inTop100 ?? prevRank.medal)) %>" alt="" />
111
- <img src="<%= getImageUrl('star_' + prevRank.star) %>" alt="" />
118
+ <img src="<%- getImageUrl('medal_' +(prevRank.inTop100 ?? prevRank.medal)) %>" alt="" />
119
+ <img src="<%- getImageUrl('star_' + prevRank.star) %>" alt="" />
112
120
  <p><%= prevRank.leader ?? "" %></p>
113
121
  </div>
114
122
  <div class="rank curr">
115
- <img src="<%= getImageUrl('medal_' +(currRank.inTop100 ?? currRank.medal)) %>" alt="" />
116
- <img src="<%= getImageUrl('star_' + currRank.star) %>" alt="" />
123
+ <img src="<%- getImageUrl('medal_' +(currRank.inTop100 ?? currRank.medal)) %>" alt="" />
124
+ <img src="<%- getImageUrl('star_' + currRank.star) %>" alt="" />
117
125
  <p><%= currRank.leader ?? "" %></p>
118
126
  </div>
119
127
  </div>
package/readme.md DELETED
@@ -1,70 +0,0 @@
1
- # [@sjtdev/koishi-plugin-dota2tracker](https://sjtdev.github.io/koishi-plugin-dota2tracker/)
2
-
3
- ### 完整使用文档
4
- [中文文档](https://sjtdev.github.io/koishi-plugin-dota2tracker/) | [English Documentation](https://sjtdev.github.io/koishi-plugin-dota2tracker/en-US/)
5
-
6
- [![GitHub Release](https://img.shields.io/github/v/release/sjtdev/koishi-plugin-dota2tracker?color=blue)](https://github.com/{username}/{repository}/releases/latest)
7
- [![npm downloads](https://img.shields.io/npm/dm/@sjtdev/koishi-plugin-dota2tracker.svg?style=flat-square)](https://www.npmjs.com/package/@sjtdev/koishi-plugin-dota2tracker)
8
-
9
- DOTA2Bot插件-提供自动追踪群友的最新对局的功能(需群友绑定),以及一系列查询功能。
10
- ### 安装
11
- 在koishi插件市场搜索安装
12
- 有关koishi的使用说明:([koishi官方文档](https://koishi.chat/))
13
-
14
- ### 使用
15
- 需在插件配置页填入STRATZ API TOKEN,否则无法使用。(配置中提供了API的获取链接)
16
- 在希望推送战报信息的群组(或频道)使用指令`订阅本群`,玩家可使用指令`绑定`来将自身账号与Steam账号绑定,bot会尝试追踪已订阅群组(或频道)中的绑定玩家的最新对局信息。
17
- 其他查询功能见下方指令说明。
18
- **直接调用help指令可获取更详细的说明,调用【指令 -h】还会有用法示例。(例如:订阅本群 -h)**
19
- **本插件使用的所有SteamID均为SteamID3类型(即DOTA2游戏内个人页面显示的好友ID与stratz登录后个人页面链接中显示的ID),有关SteamID类型见 https://steamid.tatlead.com/ (由[issue](../../issues/1)提供,感谢这位用户)**
20
-
21
- **更新日志见[changelog](changelog.md)**
22
-
23
- ### 插件更新提示
24
- **1.4.2**版本起,插件更新时会在Github发布一个无附件release,用于插件更新提醒。
25
- 如有需要可以使用 `Watch` 功能接收插件更新通知,以下为详细步骤:
26
- 1. 访问[仓库页面](https://github.com/sjtdev/koishi-plugin-dota2tracker)
27
- 2. 点击右上方的 "Watch" 按钮
28
- 3. 选择 "Custom" 选项
29
- 4. 在弹出的设置中勾选 "Releases" 选项
30
- 5. 点击 "Apply" 保存设置
31
-
32
- ### 指令
33
- 指令 <必填参数> [可选参数]
34
- ##### 订阅
35
- (bot仅向已订阅群组/频道推送信息)
36
- (若是使用Discord、KOOK频道类平台,订阅与绑定信息仅对单个频道生效,频道间相互独立)
37
- * `订阅本群`
38
- * `取消订阅`
39
- ##### 绑定
40
- (bot会追踪每位绑定玩家的最新对局)
41
- * `绑定 <玩家SteamID> [玩家别名]`
42
- * `取消绑定`
43
- * `改名 <新玩家别名>`
44
- ##### 查询
45
- * `查询玩家 [SteamID|别名] [<--hero|-o> <英雄ID|英雄名|英雄常用别名>]`
46
- 返回一张图片,包含玩家各类信息。(缺省参数时并且调用者已绑定将自查)(输入--hero或-o并跟上查询英雄的参数时,将查询玩家指定英雄)
47
- * `查询比赛 <比赛ID>`
48
- 返回一张图片,包含比赛对战信息。
49
- * `查询最近比赛 [SteamID|别名]`
50
- 查询指定玩家的最近一场比赛,效果同上。(缺省参数时并且调用者已绑定将自查)
51
- * `查询英雄 <英雄ID|英雄名|英雄常用别名>`
52
- 返回一张图片,包含英雄属性与技能详情。(此处英雄名为中文名)
53
- * <del>`查询英雄对战 <英雄ID|英雄名|英雄常用别名>`</del>
54
- 好像不是很实用
55
- * <del>`7.36 [英雄ID|英雄名|英雄常用别名] [--refresh|-r]`</del>
56
- <del>查询官网7.36更新日志中指定英雄的改动信息
57
- 无英雄参数时直接返回官网7.36更新日志网址
58
- 首次使用时将缓存更新日志网页,若读取失败或出错,可添加`--refresh`或`-r`指令重新缓存</del>
59
- `查询英雄`指令已适配7.36改动,所以此指令已废弃
60
-
61
- ### 英雄ID|英雄名|英雄常用别名 列表
62
- 可在`koishi-本地化`中定义,见[文档-自定义文本](https://sjtdev.github.io/koishi-plugin-dota2tracker/i18n.html#%E8%87%AA%E5%AE%9A%E4%B9%89%E6%96%87%E6%9C%AC)
63
-
64
- ### 图片模板列表
65
- 展示见[文档-模板展示](https://sjtdev.github.io/koishi-plugin-dota2tracker/template.html)
66
- 生成图片已使用ejs模板实现,所有模板都在[template]文件夹下,若是有大佬想自己设计模板欢迎联系我完善数据接口。(当前有很多在模板中后处理的数据,不是很友好)
67
-
68
- ## 灵感来源&鸣谢
69
- * 感谢[SonodaHanami](https://github.com/SonodaHanami)大佬的[Steam_watcher](https://github.com/SonodaHanami/Steam_watcher)项目,是本插件最重要的灵感来源,并授权提供了战报称号系统、英雄代称与播报信息的代码数据。
70
- * 也受到了[koishi-plugin-dota2track(npm)](https://www.npmjs.com/package/koishi-plugin-dota2track)的启发,为我的代码提供了一些思路。