koishi-plugin-minecraft-notifier 1.9.0 → 1.9.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.cjs +125 -112
- package/lib/index.d.ts +1 -3
- package/lib/version-checker.d.ts +3 -0
- package/package.json +1 -1
- /package/lib/{git-platform-helper.d.ts → helper/git-platform-helper.d.ts} +0 -0
- /package/lib/{onebot-helper.d.ts → helper/onebot-helper.d.ts} +0 -0
- /package/lib/{web_helper.d.ts → helper/web-helper.d.ts} +0 -0
package/lib/index.cjs
CHANGED
|
@@ -35,7 +35,6 @@ __export(index_exports, {
|
|
|
35
35
|
name: () => name
|
|
36
36
|
});
|
|
37
37
|
module.exports = __toCommonJS(index_exports);
|
|
38
|
-
var import_axios4 = __toESM(require("axios"), 1);
|
|
39
38
|
var import_fs = __toESM(require("fs"), 1);
|
|
40
39
|
var import_koishi = require("koishi");
|
|
41
40
|
var import_node_fs2 = require("node:fs");
|
|
@@ -48,7 +47,7 @@ var import_axios3 = __toESM(require("axios"), 1);
|
|
|
48
47
|
var cheerio2 = __toESM(require("cheerio"), 1);
|
|
49
48
|
var import_turndown = __toESM(require("turndown"), 1);
|
|
50
49
|
|
|
51
|
-
// src/onebot-helper.ts
|
|
50
|
+
// src/helper/onebot-helper.ts
|
|
52
51
|
function createBotTextMsgNode(bot, content) {
|
|
53
52
|
return {
|
|
54
53
|
type: "node",
|
|
@@ -60,6 +59,44 @@ function createBotTextMsgNode(bot, content) {
|
|
|
60
59
|
};
|
|
61
60
|
}
|
|
62
61
|
|
|
62
|
+
// src/helper/web-helper.ts
|
|
63
|
+
var userAgents = [
|
|
64
|
+
// Chrome 桌面版本
|
|
65
|
+
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36",
|
|
66
|
+
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36",
|
|
67
|
+
"Mozilla/5.0 (Windows NT 11.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/121.0.0.0 Safari/537.36",
|
|
68
|
+
"Mozilla/5.0 (Macintosh; Intel Mac OS X 14_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/121.0.0.0 Safari/537.36",
|
|
69
|
+
"Mozilla/5.0 (Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36",
|
|
70
|
+
// Firefox 桌面版本
|
|
71
|
+
"Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/121.0",
|
|
72
|
+
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:109.0) Gecko/20100101 Firefox/121.0",
|
|
73
|
+
"Mozilla/5.0 (X11; Linux i686; rv:109.0) Gecko/20100101 Firefox/121.0",
|
|
74
|
+
"Mozilla/5.0 (X11; Linux x86_64; rv:115.0) Gecko/20100101 Firefox/115.0",
|
|
75
|
+
// Safari 桌面和移动版本
|
|
76
|
+
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.1 Safari/605.1.15",
|
|
77
|
+
"Mozilla/5.0 (Macintosh; Intel Mac OS X 14_2) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.2 Safari/605.1.15",
|
|
78
|
+
"Mozilla/5.0 (iPhone; CPU iPhone OS 17_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.1 Mobile/15E148 Safari/604.1",
|
|
79
|
+
"Mozilla/5.0 (iPad; CPU OS 17_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.1 Mobile/15E148 Safari/604.1",
|
|
80
|
+
"Mozilla/5.0 (iPhone; CPU iPhone OS 16_6 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.6 Mobile/15E148 Safari/604.1",
|
|
81
|
+
// Edge 浏览器
|
|
82
|
+
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36 Edg/120.0.0.0",
|
|
83
|
+
"Mozilla/5.0 (Windows NT 11.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/121.0.0.0 Safari/537.36 Edg/121.0.0.0",
|
|
84
|
+
// Android 移动设备
|
|
85
|
+
"Mozilla/5.0 (Linux; Android 13; SM-G998B) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Mobile Safari/537.36",
|
|
86
|
+
"Mozilla/5.0 (Linux; Android 12; SM-A536B) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Mobile Safari/537.36",
|
|
87
|
+
"Mozilla/5.0 (Linux; Android 14; Pixel 8) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/121.0.0.0 Mobile Safari/537.36",
|
|
88
|
+
"Mozilla/5.0 (Linux; Android 13; moto g(50) 5G) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Mobile Safari/537.36",
|
|
89
|
+
// 其他浏览器
|
|
90
|
+
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36 OPR/106.0.0.0",
|
|
91
|
+
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36 OPR/106.0.0.0",
|
|
92
|
+
"Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/118.0.0.0 Safari/537.36",
|
|
93
|
+
"Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36"
|
|
94
|
+
];
|
|
95
|
+
function getRandomUserAgent() {
|
|
96
|
+
const randomIndex = Math.floor(Math.random() * userAgents.length);
|
|
97
|
+
return userAgents[randomIndex];
|
|
98
|
+
}
|
|
99
|
+
|
|
63
100
|
// src/translation-fetcher.ts
|
|
64
101
|
var import_axios = __toESM(require("axios"), 1);
|
|
65
102
|
var cheerio = __toESM(require("cheerio"), 1);
|
|
@@ -366,50 +403,12 @@ As the Minecraft Update Log JSON Summary Specialist, you must adhere to the abov
|
|
|
366
403
|
`;
|
|
367
404
|
}
|
|
368
405
|
|
|
369
|
-
// src/web_helper.ts
|
|
370
|
-
var userAgents = [
|
|
371
|
-
// Chrome 桌面版本
|
|
372
|
-
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36",
|
|
373
|
-
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36",
|
|
374
|
-
"Mozilla/5.0 (Windows NT 11.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/121.0.0.0 Safari/537.36",
|
|
375
|
-
"Mozilla/5.0 (Macintosh; Intel Mac OS X 14_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/121.0.0.0 Safari/537.36",
|
|
376
|
-
"Mozilla/5.0 (Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36",
|
|
377
|
-
// Firefox 桌面版本
|
|
378
|
-
"Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/121.0",
|
|
379
|
-
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:109.0) Gecko/20100101 Firefox/121.0",
|
|
380
|
-
"Mozilla/5.0 (X11; Linux i686; rv:109.0) Gecko/20100101 Firefox/121.0",
|
|
381
|
-
"Mozilla/5.0 (X11; Linux x86_64; rv:115.0) Gecko/20100101 Firefox/115.0",
|
|
382
|
-
// Safari 桌面和移动版本
|
|
383
|
-
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.1 Safari/605.1.15",
|
|
384
|
-
"Mozilla/5.0 (Macintosh; Intel Mac OS X 14_2) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.2 Safari/605.1.15",
|
|
385
|
-
"Mozilla/5.0 (iPhone; CPU iPhone OS 17_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.1 Mobile/15E148 Safari/604.1",
|
|
386
|
-
"Mozilla/5.0 (iPad; CPU OS 17_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.1 Mobile/15E148 Safari/604.1",
|
|
387
|
-
"Mozilla/5.0 (iPhone; CPU iPhone OS 16_6 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.6 Mobile/15E148 Safari/604.1",
|
|
388
|
-
// Edge 浏览器
|
|
389
|
-
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36 Edg/120.0.0.0",
|
|
390
|
-
"Mozilla/5.0 (Windows NT 11.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/121.0.0.0 Safari/537.36 Edg/121.0.0.0",
|
|
391
|
-
// Android 移动设备
|
|
392
|
-
"Mozilla/5.0 (Linux; Android 13; SM-G998B) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Mobile Safari/537.36",
|
|
393
|
-
"Mozilla/5.0 (Linux; Android 12; SM-A536B) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Mobile Safari/537.36",
|
|
394
|
-
"Mozilla/5.0 (Linux; Android 14; Pixel 8) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/121.0.0.0 Mobile Safari/537.36",
|
|
395
|
-
"Mozilla/5.0 (Linux; Android 13; moto g(50) 5G) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Mobile Safari/537.36",
|
|
396
|
-
// 其他浏览器
|
|
397
|
-
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36 OPR/106.0.0.0",
|
|
398
|
-
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36 OPR/106.0.0.0",
|
|
399
|
-
"Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/118.0.0.0 Safari/537.36",
|
|
400
|
-
"Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36"
|
|
401
|
-
];
|
|
402
|
-
function getRandomUserAgent() {
|
|
403
|
-
const randomIndex = Math.floor(Math.random() * userAgents.length);
|
|
404
|
-
return userAgents[randomIndex];
|
|
405
|
-
}
|
|
406
|
-
|
|
407
406
|
// src/xaml-generator.ts
|
|
408
407
|
var import_autocorrect_node = require("autocorrect-node");
|
|
409
408
|
var import_node_fs = require("node:fs");
|
|
410
409
|
var import_node_path = __toESM(require("node:path"), 1);
|
|
411
410
|
|
|
412
|
-
// src/git-platform-helper.ts
|
|
411
|
+
// src/helper/git-platform-helper.ts
|
|
413
412
|
var import_axios2 = __toESM(require("axios"), 1);
|
|
414
413
|
var PLATFORM_CONFIG = {
|
|
415
414
|
["gitee" /* GITEE */]: {
|
|
@@ -1026,6 +1025,87 @@ async function fetchArticleContent(ctx, version, isSnapshot) {
|
|
|
1026
1025
|
}
|
|
1027
1026
|
}
|
|
1028
1027
|
|
|
1028
|
+
// src/version-checker.ts
|
|
1029
|
+
var import_axios4 = __toESM(require("axios"), 1);
|
|
1030
|
+
var loadData = async (ctx) => {
|
|
1031
|
+
const record = (await ctx.database.get("minecraft_notifier", 1))[0];
|
|
1032
|
+
if (record) {
|
|
1033
|
+
return {
|
|
1034
|
+
lastRelease: record.lastRelease,
|
|
1035
|
+
lastSnapshot: record.lastSnapshot
|
|
1036
|
+
};
|
|
1037
|
+
}
|
|
1038
|
+
return { lastRelease: "", lastSnapshot: "" };
|
|
1039
|
+
};
|
|
1040
|
+
var saveData = async (ctx, data) => {
|
|
1041
|
+
await ctx.database.upsert("minecraft_notifier", [
|
|
1042
|
+
{
|
|
1043
|
+
id: 1,
|
|
1044
|
+
lastRelease: data.lastRelease,
|
|
1045
|
+
lastSnapshot: data.lastSnapshot
|
|
1046
|
+
}
|
|
1047
|
+
]);
|
|
1048
|
+
};
|
|
1049
|
+
var getLatestVersions = async () => {
|
|
1050
|
+
let retries = 0;
|
|
1051
|
+
while (retries <= 3) {
|
|
1052
|
+
try {
|
|
1053
|
+
const response = await import_axios4.default.get(
|
|
1054
|
+
"https://launchermeta.mojang.com/mc/game/version_manifest.json",
|
|
1055
|
+
{
|
|
1056
|
+
timeout: 1e4
|
|
1057
|
+
}
|
|
1058
|
+
);
|
|
1059
|
+
const data = response.data;
|
|
1060
|
+
return {
|
|
1061
|
+
release: data.latest.release,
|
|
1062
|
+
snapshot: data.latest.snapshot
|
|
1063
|
+
};
|
|
1064
|
+
} catch (error) {
|
|
1065
|
+
retries++;
|
|
1066
|
+
if (retries <= 3) {
|
|
1067
|
+
await new Promise(
|
|
1068
|
+
(resolve) => setTimeout(resolve, Math.pow(2, retries) * 1e3)
|
|
1069
|
+
);
|
|
1070
|
+
}
|
|
1071
|
+
}
|
|
1072
|
+
}
|
|
1073
|
+
};
|
|
1074
|
+
var notifyReleaseVersion = async (ctx, cfg, version) => {
|
|
1075
|
+
const bot = ctx.bots[0];
|
|
1076
|
+
for (const channel of cfg.notifyChannel) {
|
|
1077
|
+
await bot.sendMessage(channel, `\u{1F4E2} Minecraft \u65B0\u6B63\u5F0F\u7248\u53D1\u5E03\u4E86\uFF1A${version}`);
|
|
1078
|
+
}
|
|
1079
|
+
};
|
|
1080
|
+
var notifySnapshotVersion = async (ctx, cfg, version) => {
|
|
1081
|
+
const bot = ctx.bots[0];
|
|
1082
|
+
for (const channel of cfg.notifyChannel) {
|
|
1083
|
+
await bot.sendMessage(channel, `\u{1F389} Minecraft \u65B0\u5FEB\u7167\u7248\u53D1\u5E03\u4E86\uFF1A${version}`);
|
|
1084
|
+
}
|
|
1085
|
+
};
|
|
1086
|
+
var checkMinecraftVersion = async (ctx, cfg) => {
|
|
1087
|
+
try {
|
|
1088
|
+
const versionData = await loadData(ctx);
|
|
1089
|
+
const latest = await getLatestVersions();
|
|
1090
|
+
let updatedData = { ...versionData };
|
|
1091
|
+
if (versionData.lastRelease !== latest.release) {
|
|
1092
|
+
await notifyReleaseVersion(ctx, cfg, latest.release);
|
|
1093
|
+
updatedData.lastRelease = latest.release;
|
|
1094
|
+
}
|
|
1095
|
+
if (versionData.lastSnapshot !== latest.snapshot && versionData.lastRelease != latest.snapshot) {
|
|
1096
|
+
await notifySnapshotVersion(ctx, cfg, latest.snapshot);
|
|
1097
|
+
updatedData.lastSnapshot = latest.snapshot;
|
|
1098
|
+
}
|
|
1099
|
+
await saveData(ctx, updatedData);
|
|
1100
|
+
await checkNewVersionArticle(ctx, cfg);
|
|
1101
|
+
} catch (error) {
|
|
1102
|
+
ctx.logger("minecraft-notifier").error(
|
|
1103
|
+
"Error checking Minecraft versions:",
|
|
1104
|
+
error
|
|
1105
|
+
);
|
|
1106
|
+
}
|
|
1107
|
+
};
|
|
1108
|
+
|
|
1029
1109
|
// src/index.ts
|
|
1030
1110
|
var name = "minecraft-notifier";
|
|
1031
1111
|
var inject = ["database", "server"];
|
|
@@ -1076,45 +1156,6 @@ function apply(ctx, cfg) {
|
|
|
1076
1156
|
},
|
|
1077
1157
|
{ primary: "id" }
|
|
1078
1158
|
);
|
|
1079
|
-
let lastRelease = "";
|
|
1080
|
-
let lastSnapshot = "";
|
|
1081
|
-
const loadData = async () => {
|
|
1082
|
-
const record = (await ctx.database.get("minecraft_notifier", 1))[0];
|
|
1083
|
-
if (record) {
|
|
1084
|
-
lastRelease = record.lastRelease;
|
|
1085
|
-
lastSnapshot = record.lastSnapshot;
|
|
1086
|
-
}
|
|
1087
|
-
};
|
|
1088
|
-
const saveData = async () => {
|
|
1089
|
-
await ctx.database.upsert("minecraft_notifier", [
|
|
1090
|
-
{ id: 1, lastRelease, lastSnapshot }
|
|
1091
|
-
]);
|
|
1092
|
-
};
|
|
1093
|
-
const getLatestVersions = async () => {
|
|
1094
|
-
let retries = 0;
|
|
1095
|
-
while (retries <= 3) {
|
|
1096
|
-
try {
|
|
1097
|
-
const response = await import_axios4.default.get(
|
|
1098
|
-
"https://launchermeta.mojang.com/mc/game/version_manifest.json",
|
|
1099
|
-
{
|
|
1100
|
-
timeout: 1e4
|
|
1101
|
-
}
|
|
1102
|
-
);
|
|
1103
|
-
const data = response.data;
|
|
1104
|
-
return {
|
|
1105
|
-
release: data.latest.release,
|
|
1106
|
-
snapshot: data.latest.snapshot
|
|
1107
|
-
};
|
|
1108
|
-
} catch (error) {
|
|
1109
|
-
retries++;
|
|
1110
|
-
if (retries <= 3) {
|
|
1111
|
-
await new Promise(
|
|
1112
|
-
(resolve) => setTimeout(resolve, Math.pow(2, retries) * 1e3)
|
|
1113
|
-
);
|
|
1114
|
-
}
|
|
1115
|
-
}
|
|
1116
|
-
}
|
|
1117
|
-
};
|
|
1118
1159
|
const xamlPath = import_node_path2.default.join(
|
|
1119
1160
|
ctx.baseDir,
|
|
1120
1161
|
"data",
|
|
@@ -1149,38 +1190,10 @@ function apply(ctx, cfg) {
|
|
|
1149
1190
|
}).action(async () => {
|
|
1150
1191
|
await checkNewVersionArticle(ctx, cfg);
|
|
1151
1192
|
});
|
|
1152
|
-
ctx.setInterval(
|
|
1153
|
-
|
|
1154
|
-
|
|
1155
|
-
|
|
1156
|
-
const bot = ctx.bots[0];
|
|
1157
|
-
if (lastRelease !== latest.release) {
|
|
1158
|
-
for (const channel of cfg.notifyChannel) {
|
|
1159
|
-
await bot.sendMessage(
|
|
1160
|
-
channel,
|
|
1161
|
-
`Minecraft \u65B0\u6B63\u5F0F\u7248\u53D1\u5E03\u4E86\uFF1A${latest.release}`
|
|
1162
|
-
);
|
|
1163
|
-
}
|
|
1164
|
-
lastRelease = latest.release;
|
|
1165
|
-
}
|
|
1166
|
-
if (lastSnapshot !== latest.snapshot && lastRelease != latest.snapshot) {
|
|
1167
|
-
for (const channel of cfg.notifyChannel) {
|
|
1168
|
-
await bot.sendMessage(
|
|
1169
|
-
channel,
|
|
1170
|
-
`Minecraft \u65B0\u5FEB\u7167\u7248\u53D1\u5E03\u4E86\uFF1A${latest.snapshot}`
|
|
1171
|
-
);
|
|
1172
|
-
}
|
|
1173
|
-
lastSnapshot = latest.snapshot;
|
|
1174
|
-
}
|
|
1175
|
-
await saveData();
|
|
1176
|
-
await checkNewVersionArticle(ctx, cfg);
|
|
1177
|
-
} catch (error) {
|
|
1178
|
-
ctx.logger("minecraft-notifier").error(
|
|
1179
|
-
"\u68C0\u67E5 Minecraft \u7248\u672C\u65F6\u51FA\u9519\uFF1A",
|
|
1180
|
-
error
|
|
1181
|
-
);
|
|
1182
|
-
}
|
|
1183
|
-
}, 6e4 * cfg.checkInterval);
|
|
1193
|
+
ctx.setInterval(
|
|
1194
|
+
async () => await checkMinecraftVersion(ctx, cfg),
|
|
1195
|
+
6e4 * cfg.checkInterval
|
|
1196
|
+
);
|
|
1184
1197
|
}
|
|
1185
1198
|
// Annotate the CommonJS export names for ESM import in node:
|
|
1186
1199
|
0 && (module.exports = {
|
package/lib/index.d.ts
CHANGED
|
@@ -43,6 +43,4 @@ export interface Config {
|
|
|
43
43
|
gitcodeRepo?: string;
|
|
44
44
|
}
|
|
45
45
|
export declare const Config: Schema<Config>;
|
|
46
|
-
export declare function apply(ctx: Context, cfg: Config
|
|
47
|
-
articleTracker: any;
|
|
48
|
-
}): void;
|
|
46
|
+
export declare function apply(ctx: Context, cfg: Config): void;
|
package/package.json
CHANGED
|
File without changes
|
|
File without changes
|
|
File without changes
|