@sjtdev/koishi-plugin-dota2tracker 1.2.16 → 1.2.18-beta.1
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 +148 -60
- package/package.json +1 -1
- package/template/images/bei.jpg +0 -0
- package/template/images/xi.jpg +0 -0
- package/template/rank/rank.ejs +35 -0
- package/template/rank/rank_fun.ejs +108 -0
- package/template/rank/temp.ejs +27 -0
package/lib/index.js
CHANGED
|
@@ -50,13 +50,13 @@ __export(utils_exports, {
|
|
|
50
50
|
formatNumber: () => formatNumber,
|
|
51
51
|
getFormattedMatchData: () => getFormattedMatchData,
|
|
52
52
|
getImageUrl: () => getImageUrl,
|
|
53
|
+
init: () => init,
|
|
53
54
|
playerisValid: () => playerisValid,
|
|
54
55
|
query: () => query,
|
|
55
56
|
queryHeroFromValve: () => queryHeroFromValve,
|
|
56
57
|
readDirectoryFilesSync: () => readDirectoryFilesSync,
|
|
57
58
|
roundToDecimalPlaces: () => roundToDecimalPlaces,
|
|
58
59
|
sec2time: () => sec2time,
|
|
59
|
-
setHttp: () => setHttp,
|
|
60
60
|
winRateColor: () => winRateColor
|
|
61
61
|
});
|
|
62
62
|
var import_fs = __toESM(require("fs"));
|
|
@@ -70,12 +70,13 @@ __export(queries_exports, {
|
|
|
70
70
|
CURRENT_GAMEVERSION: () => CURRENT_GAMEVERSION,
|
|
71
71
|
HERO_INFO: () => HERO_INFO,
|
|
72
72
|
HERO_MATCHUP_WINRATE: () => HERO_MATCHUP_WINRATE,
|
|
73
|
-
MATCHES_FOR_DAILY: () => MATCHES_FOR_DAILY,
|
|
74
73
|
MATCH_INFO: () => MATCH_INFO,
|
|
75
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,
|
|
76
77
|
PLAYER_EXTRA_INFO: () => PLAYER_EXTRA_INFO,
|
|
77
78
|
PLAYER_INFO_WITH_25_MATCHES: () => PLAYER_INFO_WITH_25_MATCHES,
|
|
78
|
-
|
|
79
|
+
REQUEST_MATCH_DATA_ANALYSIS: () => REQUEST_MATCH_DATA_ANALYSIS,
|
|
79
80
|
VERIFYING_PLAYER: () => VERIFYING_PLAYER
|
|
80
81
|
});
|
|
81
82
|
var dotaconstants = __toESM(require("dotaconstants"));
|
|
@@ -220,10 +221,10 @@ function MATCH_INFO(matchId) {
|
|
|
220
221
|
`;
|
|
221
222
|
}
|
|
222
223
|
__name(MATCH_INFO, "MATCH_INFO");
|
|
223
|
-
function
|
|
224
|
+
function PLAYERS_MATCHES_FOR_DAILY(steamAccountIds, seconds) {
|
|
224
225
|
return `
|
|
225
226
|
{
|
|
226
|
-
players(steamAccountIds
|
|
227
|
+
players(steamAccountIds:[${steamAccountIds.join(",")}]) {
|
|
227
228
|
steamAccount{id name avatar}
|
|
228
229
|
matches(request:{startDateTime:${seconds} take:50}){
|
|
229
230
|
id
|
|
@@ -245,7 +246,7 @@ function MATCHES_FOR_DAILY(steamAccountIds, seconds) {
|
|
|
245
246
|
}
|
|
246
247
|
`;
|
|
247
248
|
}
|
|
248
|
-
__name(
|
|
249
|
+
__name(PLAYERS_MATCHES_FOR_DAILY, "PLAYERS_MATCHES_FOR_DAILY");
|
|
249
250
|
function VERIFYING_PLAYER(steamAccountId) {
|
|
250
251
|
return `
|
|
251
252
|
{
|
|
@@ -257,29 +258,33 @@ function VERIFYING_PLAYER(steamAccountId) {
|
|
|
257
258
|
`;
|
|
258
259
|
}
|
|
259
260
|
__name(VERIFYING_PLAYER, "VERIFYING_PLAYER");
|
|
260
|
-
function
|
|
261
|
+
function PLAYERS_LASTMATCH_RANKINFO(steamAccountIds) {
|
|
261
262
|
return `
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
steamAccount {
|
|
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
273
|
id
|
|
274
|
+
parsedDateTime
|
|
275
|
+
startDateTime
|
|
276
|
+
players{
|
|
277
|
+
steamAccount{
|
|
278
|
+
id
|
|
279
|
+
}
|
|
280
|
+
}
|
|
274
281
|
}
|
|
275
282
|
}
|
|
276
283
|
}
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
`;
|
|
284
|
+
|
|
285
|
+
`;
|
|
281
286
|
}
|
|
282
|
-
__name(
|
|
287
|
+
__name(PLAYERS_LASTMATCH_RANKINFO, "PLAYERS_LASTMATCH_RANKINFO");
|
|
283
288
|
function PLAYER_INFO_WITH_25_MATCHES(steamAccountId, heroId) {
|
|
284
289
|
return `
|
|
285
290
|
{
|
|
@@ -517,15 +522,20 @@ function HERO_MATCHUP_WINRATE(heroId) {
|
|
|
517
522
|
`;
|
|
518
523
|
}
|
|
519
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");
|
|
520
529
|
|
|
521
530
|
// src/utils.ts
|
|
522
531
|
var CONFIGS = { STRATZ_API: { URL: "https://api.stratz.com/graphql", TOKEN: "" } };
|
|
523
532
|
var http = null;
|
|
524
|
-
function
|
|
533
|
+
function init(newHttp, setTimeout2) {
|
|
525
534
|
http = newHttp;
|
|
535
|
+
setTimeout2 = setTimeout2;
|
|
526
536
|
}
|
|
527
|
-
__name(
|
|
528
|
-
async function
|
|
537
|
+
__name(init, "init");
|
|
538
|
+
async function fetchData(query_str) {
|
|
529
539
|
return await http.post(CONFIGS.STRATZ_API.URL, query_str, {
|
|
530
540
|
responseType: "json",
|
|
531
541
|
headers: {
|
|
@@ -535,6 +545,27 @@ async function query(query_str) {
|
|
|
535
545
|
}
|
|
536
546
|
});
|
|
537
547
|
}
|
|
548
|
+
__name(fetchData, "fetchData");
|
|
549
|
+
async function query(query_func, ...args) {
|
|
550
|
+
if (query_func.name.startsWith("PLAYERS") && args[0].length > 5) {
|
|
551
|
+
const playerIds = args[0];
|
|
552
|
+
const chunkSize = 5;
|
|
553
|
+
let allPlayers = [];
|
|
554
|
+
for (let i = 0; i < playerIds.length; i += chunkSize) {
|
|
555
|
+
const chunk = playerIds.slice(i, i + chunkSize);
|
|
556
|
+
const query_str = query_func(chunk, ...args.slice(1));
|
|
557
|
+
const result = await new Promise((resolve) => setTimeout(() => resolve(fetchData(query_str)), 100));
|
|
558
|
+
if (result.data && result.data.players) {
|
|
559
|
+
allPlayers = allPlayers.concat(result.data.players);
|
|
560
|
+
}
|
|
561
|
+
}
|
|
562
|
+
return { data: { players: allPlayers } };
|
|
563
|
+
} else {
|
|
564
|
+
const query_str = query_func(...args);
|
|
565
|
+
const result = await fetchData(query_str);
|
|
566
|
+
return result || {};
|
|
567
|
+
}
|
|
568
|
+
}
|
|
538
569
|
__name(query, "query");
|
|
539
570
|
async function queryHeroFromValve(heroId) {
|
|
540
571
|
return (await http.get(`https://www.dota2.com/datafeed/herodata?language=schinese&hero_id=${heroId}`)).result.data.heroes[0];
|
|
@@ -566,7 +597,7 @@ function getImageUrl(image, type = "local" /* Local */, format = "png" /* png */
|
|
|
566
597
|
if (type === "local" /* Local */) {
|
|
567
598
|
try {
|
|
568
599
|
if (format === "svg" /* svg */) return import_fs.default.readFileSync(`./node_modules/@sjtdev/koishi-plugin-dota2tracker/template/images/${image}.svg`);
|
|
569
|
-
const imageData = import_fs.default.readFileSync(`./node_modules/@sjtdev/koishi-plugin-dota2tracker/template/images/${image}
|
|
600
|
+
const imageData = import_fs.default.readFileSync(`./node_modules/@sjtdev/koishi-plugin-dota2tracker/template/images/${image}.${format}`);
|
|
570
601
|
const base64Data = imageData.toString("base64");
|
|
571
602
|
return `data:image/png;base64,${base64Data}`;
|
|
572
603
|
} catch (error) {
|
|
@@ -1235,6 +1266,20 @@ var Config = import_koishi.Schema.intersect([
|
|
|
1235
1266
|
])
|
|
1236
1267
|
).role("checkbox").description("在消息中附带链接,<br/>请选择消息类型:")
|
|
1237
1268
|
}).description("基础设置"),
|
|
1269
|
+
import_koishi.Schema.intersect([
|
|
1270
|
+
import_koishi.Schema.object({
|
|
1271
|
+
rankBroadSwitch: import_koishi.Schema.boolean().default(false).description("段位变动播报")
|
|
1272
|
+
}),
|
|
1273
|
+
import_koishi.Schema.union([
|
|
1274
|
+
import_koishi.Schema.object({
|
|
1275
|
+
rankBroadSwitch: import_koishi.Schema.const(true).required(),
|
|
1276
|
+
rankBroadStar: import_koishi.Schema.boolean().default(true).description("星级变动播报"),
|
|
1277
|
+
rankBroadLeader: import_koishi.Schema.boolean().default(true).description("冠绝名次变动播报"),
|
|
1278
|
+
rankBroadFun: import_koishi.Schema.boolean().default(false).description("整活播报模板")
|
|
1279
|
+
}),
|
|
1280
|
+
import_koishi.Schema.object({})
|
|
1281
|
+
])
|
|
1282
|
+
]),
|
|
1238
1283
|
import_koishi.Schema.intersect([
|
|
1239
1284
|
import_koishi.Schema.object({
|
|
1240
1285
|
dailyReportSwitch: import_koishi.Schema.boolean().default(false).description("日报功能")
|
|
@@ -1269,7 +1314,7 @@ var pendingMatches = [];
|
|
|
1269
1314
|
var random = new import_koishi2.Random(() => Math.random());
|
|
1270
1315
|
async function apply(ctx, config) {
|
|
1271
1316
|
CONFIGS.STRATZ_API.TOKEN = config.STRATZ_API_TOKEN;
|
|
1272
|
-
|
|
1317
|
+
init(ctx.http, ctx.setTimeout);
|
|
1273
1318
|
ctx.command("订阅本群", "订阅后还需玩家在本群绑定SteamID").usage("订阅后还需玩家在本群绑定SteamID,BOT将订阅本群中已绑定玩家的新比赛数据,在STRATZ比赛解析完成后将比赛数据生成为图片战报发布至本群中。").action(async ({ session }) => {
|
|
1274
1319
|
if (session.guild) {
|
|
1275
1320
|
let currentGuild = (await ctx.database.get("dt_subscribed_guilds", { guildId: session.event.channel.id, platform: session.event.platform }))[0];
|
|
@@ -1365,15 +1410,19 @@ async function apply(ctx, config) {
|
|
|
1365
1410
|
}
|
|
1366
1411
|
if (subscribedPlayers.length <= 20) {
|
|
1367
1412
|
try {
|
|
1368
|
-
|
|
1413
|
+
let memberList;
|
|
1414
|
+
try {
|
|
1415
|
+
memberList = await session.bot?.getGuildMemberList(session.event.channel.id);
|
|
1416
|
+
} catch (error) {
|
|
1417
|
+
}
|
|
1369
1418
|
async function getUsers(subscribedPlayers2, utils, queries, memberList2) {
|
|
1370
1419
|
const playerSteamIds = subscribedPlayers2.map((player) => player.steamId);
|
|
1371
|
-
const queryResult = await utils.query(queries.PLAYERS_INFO_WITH_10_MATCHES_FOR_GUILD
|
|
1420
|
+
const queryResult = await utils.query(queries.PLAYERS_INFO_WITH_10_MATCHES_FOR_GUILD, playerSteamIds);
|
|
1372
1421
|
const playersInfo = queryResult.data.players;
|
|
1373
1422
|
const users2 = [];
|
|
1374
1423
|
for (const subscribedPlayer of subscribedPlayers2) {
|
|
1375
1424
|
const queryPlayer = playersInfo.find((player) => player.steamAccount.id == subscribedPlayer.steamId);
|
|
1376
|
-
const queryMember = memberList2
|
|
1425
|
+
const queryMember = memberList2?.data.find((member) => member.user?.id == subscribedPlayer.userId);
|
|
1377
1426
|
users2.push({ ...subscribedPlayer, ...queryPlayer, ...queryMember });
|
|
1378
1427
|
}
|
|
1379
1428
|
return users2;
|
|
@@ -1396,7 +1445,7 @@ async function apply(ctx, config) {
|
|
|
1396
1445
|
match = queryLocal[0].data;
|
|
1397
1446
|
ctx.database.set("dt_previous_query_results", match.id, { queryTime: /* @__PURE__ */ new Date() });
|
|
1398
1447
|
} else {
|
|
1399
|
-
match = getFormattedMatchData((await query(MATCH_INFO
|
|
1448
|
+
match = getFormattedMatchData((await query(MATCH_INFO, matchId)).data);
|
|
1400
1449
|
}
|
|
1401
1450
|
if (match && (match.parsedDateTime || import_moment.default.unix(match.endDateTime).isBefore((0, import_moment.default)().subtract(config.dataParsingTimeoutMinutes, "minutes")))) {
|
|
1402
1451
|
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 */)));
|
|
@@ -1418,7 +1467,6 @@ async function apply(ctx, config) {
|
|
|
1418
1467
|
session.send("请输入比赛ID。");
|
|
1419
1468
|
return;
|
|
1420
1469
|
}
|
|
1421
|
-
JSON.stringify;
|
|
1422
1470
|
if (!/^\d{10}$/.test(match_id)) {
|
|
1423
1471
|
session.send("比赛ID无效。");
|
|
1424
1472
|
return;
|
|
@@ -1444,9 +1492,10 @@ async function apply(ctx, config) {
|
|
|
1444
1492
|
let lastMatchId = 0;
|
|
1445
1493
|
try {
|
|
1446
1494
|
session.send("正在搜索对局详情,请稍后...");
|
|
1447
|
-
lastMatchId = (await query(
|
|
1448
|
-
} catch {
|
|
1495
|
+
lastMatchId = (await query(PLAYERS_LASTMATCH_RANKINFO, [parseInt(flagBindedPlayer?.steamId ?? input_data)])).data.players[0].matches[0].id;
|
|
1496
|
+
} catch (error) {
|
|
1449
1497
|
session.send("获取玩家最近比赛失败。");
|
|
1498
|
+
ctx.logger.error(error);
|
|
1450
1499
|
return;
|
|
1451
1500
|
}
|
|
1452
1501
|
queryMatchAndSend(session, lastMatchId);
|
|
@@ -1474,8 +1523,8 @@ async function apply(ctx, config) {
|
|
|
1474
1523
|
let steamId = flagBindedPlayer?.steamId ?? input_data;
|
|
1475
1524
|
let player;
|
|
1476
1525
|
try {
|
|
1477
|
-
player = (await query(PLAYER_INFO_WITH_25_MATCHES
|
|
1478
|
-
let playerExtra = (await query(PLAYER_EXTRA_INFO
|
|
1526
|
+
player = (await query(PLAYER_INFO_WITH_25_MATCHES, steamId, hero?.id)).data.player;
|
|
1527
|
+
let playerExtra = (await query(PLAYER_EXTRA_INFO, steamId, player.matchCount, Object.keys(dotaconstants3.heroes).length, hero?.id)).data.player;
|
|
1479
1528
|
let filteredDotaPlus = {};
|
|
1480
1529
|
playerExtra.dotaPlus.forEach((item) => {
|
|
1481
1530
|
if (!filteredDotaPlus[item.heroId] || filteredDotaPlus[item.heroId].level < item.level) {
|
|
@@ -1623,7 +1672,7 @@ async function apply(ctx, config) {
|
|
|
1623
1672
|
return;
|
|
1624
1673
|
}
|
|
1625
1674
|
try {
|
|
1626
|
-
let heroStats = (await query(HERO_MATCHUP_WINRATE
|
|
1675
|
+
let heroStats = (await query(HERO_MATCHUP_WINRATE, hero.id)).data.heroStats;
|
|
1627
1676
|
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) => {
|
|
1628
1677
|
const winRate = item.winCount / item.matchCount;
|
|
1629
1678
|
return { ...item, winRate: winRate.toFixed(3) };
|
|
@@ -1669,19 +1718,10 @@ async function apply(ctx, config) {
|
|
|
1669
1718
|
}
|
|
1670
1719
|
__name(findingHero, "findingHero");
|
|
1671
1720
|
ctx.on("ready", async () => {
|
|
1672
|
-
|
|
1673
|
-
|
|
1674
|
-
|
|
1675
|
-
}
|
|
1676
|
-
if (!("dt_subscribed_players" in tables)) {
|
|
1677
|
-
ctx.model.extend("dt_subscribed_players", { id: "unsigned", userId: "string", guildId: "string", platform: "string", steamId: "integer", nickName: "string" }, { autoInc: true });
|
|
1678
|
-
}
|
|
1679
|
-
if (!("dt_sended_match_id" in tables)) {
|
|
1680
|
-
ctx.model.extend("dt_sended_match_id", { matchId: "unsigned", sendTime: "timestamp" }, { primary: "matchId" });
|
|
1681
|
-
}
|
|
1682
|
-
if (!("dt_previous_query_results" in tables)) {
|
|
1683
|
-
ctx.model.extend("dt_previous_query_results", { matchId: "unsigned", data: "json", queryTime: "timestamp" }, { primary: "matchId" });
|
|
1684
|
-
}
|
|
1721
|
+
ctx.model.extend("dt_subscribed_guilds", { id: "unsigned", guildId: "string", platform: "string" }, { autoInc: true });
|
|
1722
|
+
ctx.model.extend("dt_subscribed_players", { id: "unsigned", userId: "string", guildId: "string", platform: "string", steamId: "integer", nickName: "string", rank: "json" }, { autoInc: true });
|
|
1723
|
+
ctx.model.extend("dt_sended_match_id", { matchId: "unsigned", sendTime: "timestamp" }, { primary: "matchId" });
|
|
1724
|
+
ctx.model.extend("dt_previous_query_results", { matchId: "unsigned", data: "json", queryTime: "timestamp" }, { primary: "matchId" });
|
|
1685
1725
|
ctx.cron("0 */6 * * *", () => {
|
|
1686
1726
|
const oneMonthAgo = (0, import_moment.default)().subtract(1, "months").toDate();
|
|
1687
1727
|
ctx.database.remove("dt_sended_match_id", { sendTime: { $lt: oneMonthAgo } });
|
|
@@ -1706,10 +1746,7 @@ async function apply(ctx, config) {
|
|
|
1706
1746
|
const subscribedPlayersSteamIds = subscribedPlayersInGuild.map((player) => player.steamId).filter(function(value, index, self) {
|
|
1707
1747
|
return self.indexOf(value) === index;
|
|
1708
1748
|
});
|
|
1709
|
-
const players =
|
|
1710
|
-
for (let id of subscribedPlayersSteamIds) {
|
|
1711
|
-
players.push((await query(PLAYER_LASTMATCH(id))).data.player);
|
|
1712
|
-
}
|
|
1749
|
+
const players = (await query(PLAYERS_LASTMATCH_RANKINFO, subscribedPlayersSteamIds)).data.players;
|
|
1713
1750
|
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));
|
|
1714
1751
|
const sendedMatchesIds = (await ctx.database.get("dt_sended_match_id", { matchId: lastMatches.map((match) => match.id) }, ["matchId"])).map((match) => match.matchId);
|
|
1715
1752
|
lastMatches.filter((match) => !sendedMatchesIds.includes(match.id)).forEach((match) => {
|
|
@@ -1724,10 +1761,61 @@ async function apply(ctx, config) {
|
|
|
1724
1761
|
});
|
|
1725
1762
|
});
|
|
1726
1763
|
pendingMatches.push({ matchId: match.id, guilds: tempGuilds });
|
|
1764
|
+
query(REQUEST_MATCH_DATA_ANALYSIS, match.id);
|
|
1727
1765
|
ctx.logger.info(
|
|
1728
1766
|
tempGuilds.map((guild) => `追踪到来自群组${guild.platform}:${guild.guildId}的用户${guild.players.map((player) => `[${player.nickName ?? ""}(${player.steamId})]`).join("、")}的尚未播报过的最新比赛 ${match.id}。`).join("")
|
|
1729
1767
|
);
|
|
1730
1768
|
});
|
|
1769
|
+
const rankMap = players.reduce((map, player) => {
|
|
1770
|
+
map[player.steamAccount.id] = { rank: player.steamAccount.seasonRank, leader: player.steamAccount.seasonLeaderboardRank };
|
|
1771
|
+
return map;
|
|
1772
|
+
}, {});
|
|
1773
|
+
for (let subPlayer of subscribedPlayersInGuild) {
|
|
1774
|
+
if (subPlayer.rank.rank !== rankMap[subPlayer.steamId].rank || subPlayer.rank.leader !== rankMap[subPlayer.steamId].board) {
|
|
1775
|
+
if (Object.keys(subPlayer.rank).length != 0) {
|
|
1776
|
+
if (config.rankBroadSwitch) {
|
|
1777
|
+
const ranks = ["prevRank", "currRank"].reduce((acc, key) => {
|
|
1778
|
+
const source = key === "prevRank" ? subPlayer.rank : rankMap[subPlayer.steamId];
|
|
1779
|
+
acc[key] = {
|
|
1780
|
+
medal: parseInt(source.rank?.toString().split("")[0] ?? "0"),
|
|
1781
|
+
star: parseInt(source.rank?.toString().split("")[1] ?? "0"),
|
|
1782
|
+
leader: source.leader,
|
|
1783
|
+
inTop100: source.leader ? source.leader <= 10 ? "8c" : source.leader <= 100 ? "8b" : void 0 : void 0
|
|
1784
|
+
};
|
|
1785
|
+
return acc;
|
|
1786
|
+
}, {});
|
|
1787
|
+
const prevRank = ranks["prevRank"];
|
|
1788
|
+
const currRank = ranks["currRank"];
|
|
1789
|
+
if (prevRank.medal !== currRank.medal || prevRank.star !== currRank.star && config.rankBroadStar || prevRank.leader !== currRank.leader && config.rankBroadLeader) {
|
|
1790
|
+
const guildMember = await ctx.bots.find((bot) => bot.platform == subPlayer.platform)?.getGuildMember?.(subPlayer.guildId, subPlayer.userId);
|
|
1791
|
+
const name2 = subPlayer.nickName ?? guildMember?.nick ?? players.find((player) => player.steamAccount.id == subPlayer.steamId)?.steamAccount.name ?? subPlayer.steamId;
|
|
1792
|
+
if (config.rankBroadFun === true) {
|
|
1793
|
+
const img = await ctx.puppeteer.render(
|
|
1794
|
+
genImageHTML(
|
|
1795
|
+
{
|
|
1796
|
+
name: name2,
|
|
1797
|
+
avatar: guildMember?.avatar ?? players.find((player) => subPlayer.steamId == player.steamAccount.id).steamAccount.avatar,
|
|
1798
|
+
isRising: rankMap[subPlayer.steamId].rank > subPlayer.rank.rank || rankMap[subPlayer.steamId].rank == subPlayer.rank.rank && rankMap[subPlayer.steamId].leader < subPlayer.rank.leader || rankMap[subPlayer.steamId].leader > 0 && subPlayer.rank.leader == null,
|
|
1799
|
+
prevRank,
|
|
1800
|
+
currRank
|
|
1801
|
+
},
|
|
1802
|
+
"rank" + (config.rankBroadFun ? "_fun" : ""),
|
|
1803
|
+
"rank" /* Rank */
|
|
1804
|
+
)
|
|
1805
|
+
);
|
|
1806
|
+
await ctx.broadcast([`${subPlayer.platform}:${subPlayer.guildId}`], img);
|
|
1807
|
+
} else {
|
|
1808
|
+
const message = `群友 ${name2} 段位变动:${rank[prevRank.medal]}${prevRank.star} → ${rank[currRank.medal]}${currRank.star} `;
|
|
1809
|
+
const img = await ctx.puppeteer.render(genImageHTML(currRank, "rank" + (config.rankBroadFun ? "2" : ""), "rank" /* Rank */));
|
|
1810
|
+
await ctx.broadcast([`${subPlayer.platform}:${subPlayer.guildId}`], message + img);
|
|
1811
|
+
}
|
|
1812
|
+
ctx.logger.info(`向 ${subPlayer.platform}:${subPlayer.guildId} 发布段位变动播报信息。`);
|
|
1813
|
+
}
|
|
1814
|
+
}
|
|
1815
|
+
}
|
|
1816
|
+
ctx.database.set("dt_subscribed_players", subPlayer.id, { rank: rankMap[subPlayer.steamId] });
|
|
1817
|
+
}
|
|
1818
|
+
}
|
|
1731
1819
|
}
|
|
1732
1820
|
if (pendingMatches.length > 0) {
|
|
1733
1821
|
const now = (0, import_moment.default)();
|
|
@@ -1738,7 +1826,7 @@ async function apply(ctx, config) {
|
|
|
1738
1826
|
if (queryLocal.length > 0) {
|
|
1739
1827
|
match = queryLocal[0].data;
|
|
1740
1828
|
ctx.database.set("dt_previous_query_results", match.id, { queryTime: /* @__PURE__ */ new Date() });
|
|
1741
|
-
} else match = getFormattedMatchData((await query(MATCH_INFO
|
|
1829
|
+
} else match = getFormattedMatchData((await query(MATCH_INFO, pendingMatch.matchId)).data);
|
|
1742
1830
|
if (match.parsedDateTime || import_moment.default.unix(match.endDateTime).isBefore(now.subtract(config.dataParsingTimeoutMinutes, "minutes"))) {
|
|
1743
1831
|
pendingMatches = pendingMatches.filter((item) => item.matchId != match.id);
|
|
1744
1832
|
const img = await ctx.puppeteer.render(genImageHTML(match, config.template_match, "match" /* Match */));
|
|
@@ -1780,10 +1868,9 @@ KDA:${((player.kills + player.assists) / (player.deaths || 1)).toFixed(2)} [${
|
|
|
1780
1868
|
const subscribedGuilds = await ctx.database.get("dt_subscribed_guilds", void 0);
|
|
1781
1869
|
const subscribedPlayersInGuild = (await ctx.database.get("dt_subscribed_players", void 0)).filter((player) => subscribedGuilds.some((guild) => guild.guildId == player.guildId));
|
|
1782
1870
|
const players = (await query(
|
|
1783
|
-
|
|
1784
|
-
|
|
1785
|
-
|
|
1786
|
-
)
|
|
1871
|
+
PLAYERS_MATCHES_FOR_DAILY,
|
|
1872
|
+
subscribedPlayersInGuild.map((player) => player.steamId).filter((value, index, self) => self.indexOf(value) === index),
|
|
1873
|
+
timeAgo
|
|
1787
1874
|
)).data.players.filter((player) => player.matches.length > 0);
|
|
1788
1875
|
const matches = players.map((player) => player.matches.map((match) => match)).flat().filter((item, index, self) => index === self.findIndex((t) => t.id === item.id));
|
|
1789
1876
|
for (let subPlayer of subscribedPlayersInGuild) {
|
|
@@ -1874,6 +1961,7 @@ function genImageHTML(data, template, type) {
|
|
|
1874
1961
|
dotaconstants: dotaconstants3,
|
|
1875
1962
|
moment: import_moment.default,
|
|
1876
1963
|
escapeHTML: /* @__PURE__ */ __name(function escapeHTML(str) {
|
|
1964
|
+
if (str == null) return "";
|
|
1877
1965
|
return str.replace(/[&<>"']/g, function(match) {
|
|
1878
1966
|
const escape = {
|
|
1879
1967
|
"&": "&",
|
package/package.json
CHANGED
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
<% const rank = data; %>
|
|
2
|
+
<head>
|
|
3
|
+
<style>
|
|
4
|
+
html,
|
|
5
|
+
body {
|
|
6
|
+
width: 128px;
|
|
7
|
+
height: 128px;
|
|
8
|
+
margin: 0;
|
|
9
|
+
padding: 0;
|
|
10
|
+
background-color: #0000;
|
|
11
|
+
}
|
|
12
|
+
div {
|
|
13
|
+
width: 128px;
|
|
14
|
+
height: 128px;
|
|
15
|
+
position: relative;
|
|
16
|
+
}
|
|
17
|
+
div > * {
|
|
18
|
+
position: absolute;
|
|
19
|
+
width: 100%;
|
|
20
|
+
}
|
|
21
|
+
p {
|
|
22
|
+
margin: 0;
|
|
23
|
+
text-align: center;
|
|
24
|
+
color: #fff;
|
|
25
|
+
bottom: 8px;
|
|
26
|
+
font-size: 20px;
|
|
27
|
+
text-shadow: -2px -2px 0 rgba(0, 0, 0, 0.5), 2px -2px 0 rgba(0, 0, 0, 0.5), -2px 2px 0 rgba(0, 0, 0, 0.5), 2px 2px 0 rgba(0, 0, 0, 0.5); /* 描边效果 */
|
|
28
|
+
}
|
|
29
|
+
</style>
|
|
30
|
+
</head>
|
|
31
|
+
<div>
|
|
32
|
+
<img src="<%= utils.getImageUrl('medal_' + (rank.inTop100 ?? rank.medal)) %>" />
|
|
33
|
+
<img src="<%= utils.getImageUrl("star_" + rank.star) %>" />
|
|
34
|
+
<p><%= rank.leader %></p>
|
|
35
|
+
</div>
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html>
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8" />
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
6
|
+
<title>Document</title>
|
|
7
|
+
<style>
|
|
8
|
+
* {
|
|
9
|
+
margin: 0;
|
|
10
|
+
padding: 0;
|
|
11
|
+
}
|
|
12
|
+
html {
|
|
13
|
+
width: 1024px;
|
|
14
|
+
height: 768px;
|
|
15
|
+
}
|
|
16
|
+
<%= ["xi","bei"].map(kind=>`body.${kind} {background: url(${utils.getImageUrl(kind, undefined, "jpg")}) no-repeat center center / cover;}`).join("\n") %>
|
|
17
|
+
.wrapper {
|
|
18
|
+
padding: 80px;
|
|
19
|
+
padding-top: 180px;
|
|
20
|
+
}
|
|
21
|
+
.wrapper > p {
|
|
22
|
+
font-size: 32px;
|
|
23
|
+
line-height: 48px;
|
|
24
|
+
height: 48px;
|
|
25
|
+
text-align: center;
|
|
26
|
+
}
|
|
27
|
+
body.xi p.bei,
|
|
28
|
+
body.bei p.xi {
|
|
29
|
+
display: none;
|
|
30
|
+
}
|
|
31
|
+
.wrapper > p > span {
|
|
32
|
+
margin: 0 10px;
|
|
33
|
+
}
|
|
34
|
+
.wrapper > p > span.prev {
|
|
35
|
+
color: gray;
|
|
36
|
+
}
|
|
37
|
+
.wrapper > p > span.curr {
|
|
38
|
+
font-weight: bold;
|
|
39
|
+
color: red;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
.wrapper > p > img {
|
|
43
|
+
width: 48px;
|
|
44
|
+
height: 48px;
|
|
45
|
+
vertical-align: middle;
|
|
46
|
+
line-height: 48px;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
.ranks {
|
|
50
|
+
margin-top: 40px;
|
|
51
|
+
display: flex;
|
|
52
|
+
width: 100%;
|
|
53
|
+
height: 256px;
|
|
54
|
+
justify-content: space-evenly;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
div.rank {
|
|
58
|
+
position: relative;
|
|
59
|
+
width: 256px;
|
|
60
|
+
height: 256px;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
div.rank > img {
|
|
64
|
+
position: absolute;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
div.rank.prev {
|
|
68
|
+
filter: grayscale(1);
|
|
69
|
+
}
|
|
70
|
+
div.rank.curr {
|
|
71
|
+
transform: scale(1.25);
|
|
72
|
+
}
|
|
73
|
+
div.rank p {
|
|
74
|
+
font-size: 36px;
|
|
75
|
+
bottom: 20px;
|
|
76
|
+
width: 100%;
|
|
77
|
+
text-align: center;
|
|
78
|
+
color: #fff;
|
|
79
|
+
position: absolute;
|
|
80
|
+
}
|
|
81
|
+
</style>
|
|
82
|
+
</head>
|
|
83
|
+
<% const {name, avatar, isRising, prevRank, currRank} = data; %>
|
|
84
|
+
<body class="<%= isRising ? "xi" : "bei" %>">
|
|
85
|
+
<div class="wrapper">
|
|
86
|
+
<p class="xi">热烈祝贺群友 <img src="<%= avatar %>" /><%= name %> 在天梯中再获进步,</p>
|
|
87
|
+
<p class="xi">由
|
|
88
|
+
<span class="rank prev"><%= d2a.rank[prevRank.medal] %><%= prevRank.leader ?? prevRank.star %></span>升为
|
|
89
|
+
<span class="rank curr"><%= d2a.rank[currRank.medal] %><%= currRank.leader ?? currRank.star %></span>,再接再厉,再创辉煌!
|
|
90
|
+
</p>
|
|
91
|
+
<p class="bei"><img src="<%= avatar %>" /></p>
|
|
92
|
+
<p class="bei">寄</p>
|
|
93
|
+
<div class="ranks">
|
|
94
|
+
<div class="rank prev">
|
|
95
|
+
<img src="<%= utils.getImageUrl('medal_' +(prevRank.inTop100 ?? prevRank.medal)) %>" alt="" />
|
|
96
|
+
<img src="<%= utils.getImageUrl('star_' + prevRank.star) %>" alt="" />
|
|
97
|
+
<p><%= prevRank.leader ?? "" %></p>
|
|
98
|
+
</div>
|
|
99
|
+
<div class="rank curr">
|
|
100
|
+
<img src="<%= utils.getImageUrl('medal_' +(currRank.inTop100 ?? currRank.medal)) %>" alt="" />
|
|
101
|
+
<img src="<%= utils.getImageUrl('star_' + currRank.star) %>" alt="" />
|
|
102
|
+
<p><%= currRank.leader ?? "" %></p>
|
|
103
|
+
</div>
|
|
104
|
+
</div>
|
|
105
|
+
<p style="text-align: right; margin-top: 40px;">—— <%= moment().format('YYYY/MM/DD HH点mm分') %></p>
|
|
106
|
+
</div>
|
|
107
|
+
</body>
|
|
108
|
+
</html>
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html lang="zh">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8">
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
6
|
+
<title>获取文件目录</title>
|
|
7
|
+
<script>
|
|
8
|
+
function showDirectory() {
|
|
9
|
+
// 获取当前页面的 URL
|
|
10
|
+
const url = window.location.href;
|
|
11
|
+
// 使用 URL 对象来解析当前 URL
|
|
12
|
+
const urlObj = new URL(url);
|
|
13
|
+
// 获取目录部分
|
|
14
|
+
const directory = urlObj.pathname.substring(0, urlObj.pathname.lastIndexOf('/'));
|
|
15
|
+
// 输出目录
|
|
16
|
+
document.getElementById('directory').innerText = directory;
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
console.log(directory)
|
|
20
|
+
}
|
|
21
|
+
</script>
|
|
22
|
+
</head>
|
|
23
|
+
<body onload="showDirectory()">
|
|
24
|
+
<h1>当前文件所在目录</h1>
|
|
25
|
+
<p id="directory"></p>
|
|
26
|
+
</body>
|
|
27
|
+
</html>
|