-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathhot-reloader.js
More file actions
209 lines (209 loc) · 33.7 KB
/
hot-reloader.js
File metadata and controls
209 lines (209 loc) · 33.7 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const ScriptManager_1 = require("jvm-types/net/ccbluex/liquidbounce/script/ScriptManager");
const HttpServer_1 = require("jvm-types/com/sun/net/httpserver/HttpServer");
const InetSocketAddress_1 = require("jvm-types/java/net/InetSocketAddress");
const InputStreamReader_1 = require("jvm-types/java/io/InputStreamReader");
const BufferedReader_1 = require("jvm-types/java/io/BufferedReader");
const script = registerScript.apply({
name: "hot-reloader",
version: "1.0.0",
authors: ["commandblock2"]
});
script.registerModule({
name: "ScriptHotReloader",
description: "Reloads updated scripts on HTTP POST to /reload (send JSON array of updated script names/paths).",
category: "Client",
settings: {
port: Setting.int({
name: "Port",
default: 18470,
range: [1024, 65535],
suffix: ""
}),
reenableModules: Setting.boolean({
name: "Reenable Modules",
default: true,
})
},
}, (mod) => {
let server = null;
function readBodyAsString(exchange) {
const inputStream = exchange.getRequestBody();
const reader = new BufferedReader_1.BufferedReader(new InputStreamReader_1.InputStreamReader(inputStream, "UTF-8"));
let lines = [];
let line = null;
while ((line = reader.readLine()) !== null) {
lines.push(line);
}
reader.close();
return lines.join("\n");
}
function reloadMatchingScripts(idList) {
try {
const scripts = ScriptManager_1.ScriptManager.INSTANCE.scripts.toArray();
const reloaded = [];
for (let i = 0; i < scripts.length; ++i) {
const script_ = scripts[i];
if (script_ == script)
continue; // Do not reload ourself xD
const f = script_.file;
const filePath = f ? (f.getAbsolutePath ? f.getAbsolutePath() : f.toString()) : "";
const simpleFile = f ? (f.getName ? f.getName() : "") : "";
const scriptName = script_.scriptName || "";
for (let id of idList) {
if (id === filePath.replace(".js", "") || id === simpleFile.replace(".js", "") || id === scriptName) {
// Store enabled module states if re-enable setting is on
const enabledModules = [];
if (mod.settings.reenableModules.getValue()) {
// Access the registered modules field using reflection
try {
// @ts-expect-error
const registeredModulesField = script_.getClass().getDeclaredField("registeredModules");
registeredModulesField.setAccessible(true);
const modules = registeredModulesField.get(script_);
if (modules && modules.toArray) {
const moduleArray = modules.toArray();
for (const module of moduleArray) {
if (module.enabled) {
enabledModules.push(module.baseKey);
}
}
}
}
catch (e) {
Client.displayChatMessage(`§e[HotReload] §fError accessing modules: ${e}`);
}
}
// Unload and reload the script
ScriptManager_1.ScriptManager.INSTANCE.unloadScript(script_);
const reloadedScript = ScriptManager_1.ScriptManager.INSTANCE.loadScript(script_.file, script_.language, script_.debugOptions);
reloadedScript.enable();
// Re-enable modules if needed
if (mod.settings.reenableModules.getValue() && enabledModules.length > 0) {
try {
// @ts-expect-error
const registeredModulesField = reloadedScript.getClass().getDeclaredField("registeredModules");
registeredModulesField.setAccessible(true);
const modules = registeredModulesField.get(reloadedScript);
if (modules && modules.toArray) {
const moduleArray = modules.toArray();
for (const module of moduleArray) {
if (enabledModules.includes(module.baseKey)) {
module.enable();
}
}
}
Client.displayChatMessage(`§e[HotReload] §fRe-enabled ${enabledModules.length} modules for ${scriptName}`);
}
catch (e) {
Client.displayChatMessage(`§e[HotReload] §fError re-enabling modules: ${e}`);
}
}
// For this part claude-3-7 out smarted me,
// I on my own removed that part and stored the client modules objects are an array I was trying to simply re-enable those modules directly
// but after reloading the script the original client modules were gc'ed
// so there will be `org.graalvm.polyglot.PolyglotException: Context execution was cancelled.`
reloaded.push(scriptName || simpleFile || filePath);
break;
}
}
}
return reloaded;
}
catch (e) {
Client.displayChatMessage(`§e[HotReload] §fError in reloadMatchingScripts: ${e}`);
return [];
}
}
function outResp(exchange, code, msg) {
exchange.sendResponseHeaders(code, msg.length);
const os = exchange.getResponseBody();
// @ts-expect-error
os.write(new java.lang.String(msg).getBytes());
os.close();
}
// Add these at the module level
let scriptIdsToReload = [];
let pendingReload = false;
let pendingExchange = null;
// Update the reload handler
mod.on("enable", () => {
const port = mod.settings.port.getValue();
try {
server = HttpServer_1.HttpServer.create(new InetSocketAddress_1.InetSocketAddress(port), 0);
const reloadHandler = {
// @ts-expect-error
handle: (exchange) => {
if (exchange.getRequestMethod() === "POST") {
const body = readBodyAsString(exchange);
let ids = [];
try {
ids = JSON.parse(body);
}
catch (_a) {
outResp(exchange, 400, "Invalid JSON array.");
Client.displayChatMessage("§e[HotReload] §fReceived malformed POST to /reload (not a JSON array)");
return;
}
if (!Array.isArray(ids) || ids.length === 0) {
outResp(exchange, 200, "No scripts to reload.");
return;
}
// Queue the reload request for the render thread
scriptIdsToReload = ids;
pendingReload = true;
pendingExchange = exchange;
// Inform user that reload is pending
Client.displayChatMessage("§e[HotReload] §fScript reload request queued for next render frame");
}
else {
exchange.sendResponseHeaders(405, -1);
exchange.close();
}
}
};
server.createContext("/reload", reloadHandler);
server.start();
Client.displayChatMessage(`§e[HotReload] §fHTTP server started on port ${port}, POST /reload (with JSON array in body) to reload only updated scripts.`);
}
catch (e) {
Client.displayChatMessage(`§e[HotReload] §fFailed to start HTTP server on port ${port}: ${e}`);
}
});
// Add a worldrender event to handle script reloading on the render thread
mod.on("worldrender", () => {
if (pendingReload && pendingExchange) {
try {
// Now we're on the render thread, it's safe to reload scripts
const reloaded = reloadMatchingScripts(scriptIdsToReload);
const resp = reloaded.length > 0
? `Reloaded scripts: ${reloaded.join(", ")}`
: `No matching scripts found to reload. Script ids requested from endpoint: ${scriptIdsToReload}`;
// Respond to the HTTP request
outResp(pendingExchange, 200, resp);
Client.displayChatMessage(`§e[HotReload] §f${resp}`);
}
catch (e) {
if (pendingExchange) {
outResp(pendingExchange, 500, `Error: ${e}`);
Client.displayChatMessage(`§e[HotReload] §fError during reload: ${e}`);
}
}
finally {
// Reset the pending state
pendingReload = false;
pendingExchange = null;
scriptIdsToReload = [];
}
}
});
mod.on("disable", () => {
if (server !== null) {
server.stop(0);
server = null;
Client.displayChatMessage("§e[HotReload] §fHTTP server stopped.");
}
});
});
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaG90LXJlbG9hZGVyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vc3JjL2hvdC1yZWxvYWRlci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOztBQUFBLDJGQUF3RjtBQUN4Riw0RUFBeUU7QUFDekUsNEVBQXlFO0FBSXpFLDJFQUF3RTtBQUN4RSxxRUFBa0U7QUFNbEUsTUFBTSxNQUFNLEdBQUcsY0FBYyxDQUFDLEtBQUssQ0FBQztJQUNoQyxJQUFJLEVBQUUsY0FBYztJQUNwQixPQUFPLEVBQUUsT0FBTztJQUNoQixPQUFPLEVBQUUsQ0FBQyxlQUFlLENBQUM7Q0FDN0IsQ0FBQyxDQUFDO0FBRUgsTUFBTSxDQUFDLGNBQWMsQ0FBQztJQUNsQixJQUFJLEVBQUUsbUJBQW1CO0lBQ3pCLFdBQVcsRUFBRSxrR0FBa0c7SUFDL0csUUFBUSxFQUFFLFFBQVE7SUFDbEIsUUFBUSxFQUFFO1FBQ04sSUFBSSxFQUFFLE9BQU8sQ0FBQyxHQUFHLENBQUM7WUFDZCxJQUFJLEVBQUUsTUFBTTtZQUNaLE9BQU8sRUFBRSxLQUFLO1lBQ2QsS0FBSyxFQUFFLENBQUMsSUFBSSxFQUFFLEtBQUssQ0FBQztZQUNwQixNQUFNLEVBQUUsRUFBRTtTQUNiLENBQUM7UUFDRixlQUFlLEVBQUUsT0FBTyxDQUFDLE9BQU8sQ0FBQztZQUM3QixJQUFJLEVBQUUsa0JBQWtCO1lBQ3hCLE9BQU8sRUFBRSxJQUFJO1NBQ2hCLENBQUM7S0FFTDtDQUNKLEVBQUUsQ0FBQyxHQUFHLEVBQUUsRUFBRTtJQUNQLElBQUksTUFBTSxHQUFzQixJQUFJLENBQUM7SUFFckMsU0FBUyxnQkFBZ0IsQ0FBQyxRQUFzQjtRQUM1QyxNQUFNLFdBQVcsR0FBZ0IsUUFBUSxDQUFDLGNBQWMsRUFBRSxDQUFDO1FBQzNELE1BQU0sTUFBTSxHQUFHLElBQUksK0JBQWMsQ0FBQyxJQUFJLHFDQUFpQixDQUFDLFdBQVcsRUFBRSxPQUFPLENBQUMsQ0FBQyxDQUFDO1FBQy9FLElBQUksS0FBSyxHQUFhLEVBQUUsQ0FBQztRQUN6QixJQUFJLElBQUksR0FBa0IsSUFBSSxDQUFDO1FBQy9CLE9BQU8sQ0FBQyxJQUFJLEdBQUcsTUFBTSxDQUFDLFFBQVEsRUFBRSxDQUFDLEtBQUssSUFBSSxFQUFFLENBQUM7WUFDekMsS0FBSyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQztRQUNyQixDQUFDO1FBQ0QsTUFBTSxDQUFDLEtBQUssRUFBRSxDQUFDO1FBQ2YsT0FBTyxLQUFLLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDO0lBQzVCLENBQUM7SUFFRCxTQUFTLHFCQUFxQixDQUFDLE1BQWdCO1FBQzNDLElBQUksQ0FBQztZQUNELE1BQU0sT0FBTyxHQUFJLDZCQUFhLENBQUMsUUFBUSxDQUFDLE9BQWUsQ0FBQyxPQUFPLEVBQTJCLENBQUM7WUFDM0YsTUFBTSxRQUFRLEdBQWEsRUFBRSxDQUFDO1lBQzlCLEtBQUssSUFBSSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsR0FBRyxPQUFPLENBQUMsTUFBTSxFQUFFLEVBQUUsQ0FBQyxFQUFFLENBQUM7Z0JBQ3RDLE1BQU0sT0FBTyxHQUFHLE9BQU8sQ0FBQyxDQUFDLENBQUMsQ0FBQztnQkFFM0IsSUFBSSxPQUFPLElBQUksTUFBTTtvQkFDakIsU0FBUyxDQUFDLDJCQUEyQjtnQkFFekMsTUFBTSxDQUFDLEdBQUcsT0FBTyxDQUFDLElBQUksQ0FBQztnQkFDdkIsTUFBTSxRQUFRLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxlQUFlLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxlQUFlLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLFFBQVEsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQztnQkFDbkYsTUFBTSxVQUFVLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxPQUFPLEVBQUUsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQztnQkFDM0QsTUFBTSxVQUFVLEdBQUcsT0FBTyxDQUFDLFVBQVUsSUFBSSxFQUFFLENBQUM7Z0JBQzVDLEtBQUssSUFBSSxFQUFFLElBQUksTUFBTSxFQUFFLENBQUM7b0JBQ3BCLElBQUksRUFBRSxLQUFLLFFBQVEsQ0FBQyxPQUFPLENBQUMsS0FBSyxFQUFFLEVBQUUsQ0FBQyxJQUFJLEVBQUUsS0FBSyxVQUFVLENBQUMsT0FBTyxDQUFDLEtBQUssRUFBRSxFQUFFLENBQUMsSUFBSSxFQUFFLEtBQUssVUFBVSxFQUFFLENBQUM7d0JBQ2xHLHlEQUF5RDt3QkFDekQsTUFBTSxjQUFjLEdBQWEsRUFBRSxDQUFDO3dCQUNwQyxJQUFJLEdBQUcsQ0FBQyxRQUFRLENBQUMsZUFBZSxDQUFDLFFBQVEsRUFBRSxFQUFFLENBQUM7NEJBQzFDLHVEQUF1RDs0QkFDdkQsSUFBSSxDQUFDO2dDQUNELG1CQUFtQjtnQ0FDbkIsTUFBTSxzQkFBc0IsR0FBRyxPQUFPLENBQUMsUUFBUSxFQUFFLENBQUMsZ0JBQWdCLENBQUMsbUJBQW1CLENBQUMsQ0FBQztnQ0FDeEYsc0JBQXNCLENBQUMsYUFBYSxDQUFDLElBQUksQ0FBQyxDQUFDO2dDQUMzQyxNQUFNLE9BQU8sR0FBRyxzQkFBc0IsQ0FBQyxHQUFHLENBQUMsT0FBTyxDQUFRLENBQUM7Z0NBRTNELElBQUksT0FBTyxJQUFJLE9BQU8sQ0FBQyxPQUFPLEVBQUUsQ0FBQztvQ0FDN0IsTUFBTSxXQUFXLEdBQUcsT0FBTyxDQUFDLE9BQU8sRUFBeUIsQ0FBQztvQ0FDN0QsS0FBSyxNQUFNLE1BQU0sSUFBSSxXQUFXLEVBQUUsQ0FBQzt3Q0FDL0IsSUFBSSxNQUFNLENBQUMsT0FBTyxFQUFFLENBQUM7NENBQ2pCLGNBQWMsQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLE9BQU8sQ0FBQyxDQUFDO3dDQUN4QyxDQUFDO29DQUNMLENBQUM7Z0NBQ0wsQ0FBQzs0QkFDTCxDQUFDOzRCQUFDLE9BQU8sQ0FBQyxFQUFFLENBQUM7Z0NBQ1QsTUFBTSxDQUFDLGtCQUFrQixDQUFDLDRDQUE0QyxDQUFDLEVBQUUsQ0FBQyxDQUFDOzRCQUMvRSxDQUFDO3dCQUNMLENBQUM7d0JBRUQsK0JBQStCO3dCQUMvQiw2QkFBYSxDQUFDLFFBQVEsQ0FBQyxZQUFZLENBQUMsT0FBTyxDQUFDLENBQUM7d0JBQzdDLE1BQU0sY0FBYyxHQUFHLDZCQUFhLENBQUMsUUFBUSxDQUFDLFVBQVUsQ0FBQyxPQUFPLENBQUMsSUFBSSxFQUFFLE9BQU8sQ0FBQyxRQUFRLEVBQUUsT0FBTyxDQUFDLFlBQVksQ0FBQyxDQUFDO3dCQUMvRyxjQUFjLENBQUMsTUFBTSxFQUFFLENBQUM7d0JBRXhCLDhCQUE4Qjt3QkFDOUIsSUFBSSxHQUFHLENBQUMsUUFBUSxDQUFDLGVBQWUsQ0FBQyxRQUFRLEVBQUUsSUFBSSxjQUFjLENBQUMsTUFBTSxHQUFHLENBQUMsRUFBRSxDQUFDOzRCQUN2RSxJQUFJLENBQUM7Z0NBQ0QsbUJBQW1CO2dDQUNuQixNQUFNLHNCQUFzQixHQUFHLGNBQWMsQ0FBQyxRQUFRLEVBQUUsQ0FBQyxnQkFBZ0IsQ0FBQyxtQkFBbUIsQ0FBQyxDQUFDO2dDQUMvRixzQkFBc0IsQ0FBQyxhQUFhLENBQUMsSUFBSSxDQUFDLENBQUM7Z0NBQzNDLE1BQU0sT0FBTyxHQUFHLHNCQUFzQixDQUFDLEdBQUcsQ0FBQyxjQUFjLENBQVEsQ0FBQztnQ0FFbEUsSUFBSSxPQUFPLElBQUksT0FBTyxDQUFDLE9BQU8sRUFBRSxDQUFDO29DQUM3QixNQUFNLFdBQVcsR0FBRyxPQUFPLENBQUMsT0FBTyxFQUF5QixDQUFDO29DQUM3RCxLQUFLLE1BQU0sTUFBTSxJQUFJLFdBQVcsRUFBRSxDQUFDO3dDQUMvQixJQUFJLGNBQWMsQ0FBQyxRQUFRLENBQUMsTUFBTSxDQUFDLE9BQU8sQ0FBQyxFQUFFLENBQUM7NENBQzFDLE1BQU0sQ0FBQyxNQUFNLEVBQUUsQ0FBQzt3Q0FDcEIsQ0FBQztvQ0FDTCxDQUFDO2dDQUNMLENBQUM7Z0NBRUQsTUFBTSxDQUFDLGtCQUFrQixDQUFDLDhCQUE4QixjQUFjLENBQUMsTUFBTSxnQkFBZ0IsVUFBVSxFQUFFLENBQUMsQ0FBQzs0QkFDL0csQ0FBQzs0QkFBQyxPQUFPLENBQUMsRUFBRSxDQUFDO2dDQUNULE1BQU0sQ0FBQyxrQkFBa0IsQ0FBQyw4Q0FBOEMsQ0FBQyxFQUFFLENBQUMsQ0FBQzs0QkFDakYsQ0FBQzt3QkFDTCxDQUFDO3dCQUNELDRDQUE0Qzt3QkFDNUMsMklBQTJJO3dCQUMzSSx3RUFBd0U7d0JBQ3hFLDhGQUE4Rjt3QkFFOUYsUUFBUSxDQUFDLElBQUksQ0FBQyxVQUFVLElBQUksVUFBVSxJQUFJLFFBQVEsQ0FBQyxDQUFDO3dCQUNwRCxNQUFNO29CQUNWLENBQUM7Z0JBQ0wsQ0FBQztZQUNMLENBQUM7WUFDRCxPQUFPLFFBQVEsQ0FBQztRQUNwQixDQUFDO1FBQUMsT0FBTyxDQUFDLEVBQUUsQ0FBQztZQUNULE1BQU0sQ0FBQyxrQkFBa0IsQ0FBQyxtREFBbUQsQ0FBQyxFQUFFLENBQUMsQ0FBQztZQUNsRixPQUFPLEVBQUUsQ0FBQztRQUNkLENBQUM7SUFDTCxDQUFDO0lBR0QsU0FBUyxPQUFPLENBQUMsUUFBc0IsRUFBRSxJQUFZLEVBQUUsR0FBVztRQUM5RCxRQUFRLENBQUMsbUJBQW1CLENBQUMsSUFBSSxFQUFFLEdBQUcsQ0FBQyxNQUFNLENBQUMsQ0FBQztRQUMvQyxNQUFNLEVBQUUsR0FBRyxRQUFRLENBQUMsZUFBZSxFQUFFLENBQUM7UUFDdEMsbUJBQW1CO1FBQ25CLEVBQUUsQ0FBQyxLQUFLLENBQUMsSUFBSSxJQUFJLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsQ0FBQyxRQUFRLEVBQUUsQ0FBQyxDQUFDO1FBQy9DLEVBQUUsQ0FBQyxLQUFLLEVBQUUsQ0FBQztJQUNmLENBQUM7SUFFRCxnQ0FBZ0M7SUFDaEMsSUFBSSxpQkFBaUIsR0FBYSxFQUFFLENBQUM7SUFDckMsSUFBSSxhQUFhLEdBQUcsS0FBSyxDQUFDO0lBQzFCLElBQUksZUFBZSxHQUF3QixJQUFJLENBQUM7SUFFaEQsNEJBQTRCO0lBQzVCLEdBQUcsQ0FBQyxFQUFFLENBQUMsUUFBUSxFQUFFLEdBQUcsRUFBRTtRQUNsQixNQUFNLElBQUksR0FBRyxHQUFHLENBQUMsUUFBUSxDQUFDLElBQUksQ0FBQyxRQUFRLEVBQUUsQ0FBQztRQUUxQyxJQUFJLENBQUM7WUFDRCxNQUFNLEdBQUcsdUJBQVUsQ0FBQyxNQUFNLENBQUMsSUFBSSxxQ0FBaUIsQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQztZQUMzRCxNQUFNLGFBQWEsR0FBZ0I7Z0JBQy9CLG1CQUFtQjtnQkFDbkIsTUFBTSxFQUFFLENBQUMsUUFBc0IsRUFBRSxFQUFFO29CQUMvQixJQUFJLFFBQVEsQ0FBQyxnQkFBZ0IsRUFBRSxLQUFLLE1BQU0sRUFBRSxDQUFDO3dCQUN6QyxNQUFNLElBQUksR0FBRyxnQkFBZ0IsQ0FBQyxRQUFRLENBQUMsQ0FBQzt3QkFDeEMsSUFBSSxHQUFHLEdBQWEsRUFBRSxDQUFDO3dCQUN2QixJQUFJLENBQUM7NEJBQ0QsR0FBRyxHQUFHLElBQUksQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLENBQUM7d0JBQzNCLENBQUM7d0JBQUMsV0FBTSxDQUFDOzRCQUNMLE9BQU8sQ0FBQyxRQUFRLEVBQUUsR0FBRyxFQUFFLHFCQUFxQixDQUFDLENBQUM7NEJBQzlDLE1BQU0sQ0FBQyxrQkFBa0IsQ0FBQyx1RUFBdUUsQ0FBQyxDQUFDOzRCQUNuRyxPQUFPO3dCQUNYLENBQUM7d0JBQ0QsSUFBSSxDQUFDLEtBQUssQ0FBQyxPQUFPLENBQUMsR0FBRyxDQUFDLElBQUksR0FBRyxDQUFDLE1BQU0sS0FBSyxDQUFDLEVBQUUsQ0FBQzs0QkFDMUMsT0FBTyxDQUFDLFFBQVEsRUFBRSxHQUFHLEVBQUUsdUJBQXVCLENBQUMsQ0FBQzs0QkFDaEQsT0FBTzt3QkFDWCxDQUFDO3dCQUVELGlEQUFpRDt3QkFDakQsaUJBQWlCLEdBQUcsR0FBRyxDQUFDO3dCQUN4QixhQUFhLEdBQUcsSUFBSSxDQUFDO3dCQUNyQixlQUFlLEdBQUcsUUFBUSxDQUFDO3dCQUUzQixxQ0FBcUM7d0JBQ3JDLE1BQU0sQ0FBQyxrQkFBa0IsQ0FBQyxvRUFBb0UsQ0FBQyxDQUFDO29CQUNwRyxDQUFDO3lCQUFNLENBQUM7d0JBQ0osUUFBUSxDQUFDLG1CQUFtQixDQUFDLEdBQUcsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDO3dCQUN0QyxRQUFRLENBQUMsS0FBSyxFQUFFLENBQUM7b0JBQ3JCLENBQUM7Z0JBQ0wsQ0FBQzthQUNKLENBQUM7WUFDRixNQUFNLENBQUMsYUFBYSxDQUFDLFNBQVMsRUFBRSxhQUFhLENBQUMsQ0FBQztZQUMvQyxNQUFNLENBQUMsS0FBSyxFQUFFLENBQUM7WUFDZixNQUFNLENBQUMsa0JBQWtCLENBQUMsK0NBQStDLElBQUksMEVBQTBFLENBQUMsQ0FBQztRQUM3SixDQUFDO1FBQUMsT0FBTyxDQUFDLEVBQUUsQ0FBQztZQUNULE1BQU0sQ0FBQyxrQkFBa0IsQ0FBQyx1REFBdUQsSUFBSSxLQUFLLENBQUMsRUFBRSxDQUFDLENBQUM7UUFDbkcsQ0FBQztJQUNMLENBQUMsQ0FBQyxDQUFDO0lBRUgsMEVBQTBFO0lBQzFFLEdBQUcsQ0FBQyxFQUFFLENBQUMsYUFBYSxFQUFFLEdBQUcsRUFBRTtRQUN2QixJQUFJLGFBQWEsSUFBSSxlQUFlLEVBQUUsQ0FBQztZQUNuQyxJQUFJLENBQUM7Z0JBQ0QsOERBQThEO2dCQUM5RCxNQUFNLFFBQVEsR0FBRyxxQkFBcUIsQ0FBQyxpQkFBaUIsQ0FBQyxDQUFDO2dCQUMxRCxNQUFNLElBQUksR0FBRyxRQUFRLENBQUMsTUFBTSxHQUFHLENBQUM7b0JBQzVCLENBQUMsQ0FBQyxxQkFBcUIsUUFBUSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsRUFBRTtvQkFDNUMsQ0FBQyxDQUFDLDRFQUE0RSxpQkFBaUIsRUFBRSxDQUFDO2dCQUV0Ryw4QkFBOEI7Z0JBQzlCLE9BQU8sQ0FBQyxlQUFlLEVBQUUsR0FBRyxFQUFFLElBQUksQ0FBQyxDQUFDO2dCQUNwQyxNQUFNLENBQUMsa0JBQWtCLENBQUMsbUJBQW1CLElBQUksRUFBRSxDQUFDLENBQUM7WUFDekQsQ0FBQztZQUFDLE9BQU8sQ0FBQyxFQUFFLENBQUM7Z0JBQ1QsSUFBSSxlQUFlLEVBQUUsQ0FBQztvQkFDbEIsT0FBTyxDQUFDLGVBQWUsRUFBRSxHQUFHLEVBQUUsVUFBVSxDQUFDLEVBQUUsQ0FBQyxDQUFDO29CQUM3QyxNQUFNLENBQUMsa0JBQWtCLENBQUMsd0NBQXdDLENBQUMsRUFBRSxDQUFDLENBQUM7Z0JBQzNFLENBQUM7WUFDTCxDQUFDO29CQUFTLENBQUM7Z0JBQ1AsMEJBQTBCO2dCQUMxQixhQUFhLEdBQUcsS0FBSyxDQUFDO2dCQUN0QixlQUFlLEdBQUcsSUFBSSxDQUFDO2dCQUN2QixpQkFBaUIsR0FBRyxFQUFFLENBQUM7WUFDM0IsQ0FBQztRQUNMLENBQUM7SUFDTCxDQUFDLENBQUMsQ0FBQztJQUVILEdBQUcsQ0FBQyxFQUFFLENBQUMsU0FBUyxFQUFFLEdBQUcsRUFBRTtRQUNuQixJQUFJLE1BQU0sS0FBSyxJQUFJLEVBQUUsQ0FBQztZQUNsQixNQUFNLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDO1lBQ2YsTUFBTSxHQUFHLElBQUksQ0FBQztZQUNkLE1BQU0sQ0FBQyxrQkFBa0IsQ0FBQyxzQ0FBc0MsQ0FBQyxDQUFDO1FBQ3RFLENBQUM7SUFDTCxDQUFDLENBQUMsQ0FBQztBQUNQLENBQUMsQ0FBQyxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgU2NyaXB0TWFuYWdlciB9IGZyb20gXCJqdm0tdHlwZXMvbmV0L2NjYmx1ZXgvbGlxdWlkYm91bmNlL3NjcmlwdC9TY3JpcHRNYW5hZ2VyXCI7XG5pbXBvcnQgeyBIdHRwU2VydmVyIH0gZnJvbSBcImp2bS10eXBlcy9jb20vc3VuL25ldC9odHRwc2VydmVyL0h0dHBTZXJ2ZXJcIjtcbmltcG9ydCB7IEluZXRTb2NrZXRBZGRyZXNzIH0gZnJvbSBcImp2bS10eXBlcy9qYXZhL25ldC9JbmV0U29ja2V0QWRkcmVzc1wiO1xuaW1wb3J0IHsgSHR0cEhhbmRsZXIgfSBmcm9tIFwianZtLXR5cGVzL2NvbS9zdW4vbmV0L2h0dHBzZXJ2ZXIvSHR0cEhhbmRsZXJcIjtcbmltcG9ydCB7IEh0dHBFeGNoYW5nZSB9IGZyb20gXCJqdm0tdHlwZXMvY29tL3N1bi9uZXQvaHR0cHNlcnZlci9IdHRwRXhjaGFuZ2VcIjtcbmltcG9ydCB7IElucHV0U3RyZWFtIH0gZnJvbSBcImp2bS10eXBlcy9qYXZhL2lvL0lucHV0U3RyZWFtXCI7XG5pbXBvcnQgeyBJbnB1dFN0cmVhbVJlYWRlciB9IGZyb20gXCJqdm0tdHlwZXMvamF2YS9pby9JbnB1dFN0cmVhbVJlYWRlclwiO1xuaW1wb3J0IHsgQnVmZmVyZWRSZWFkZXIgfSBmcm9tIFwianZtLXR5cGVzL2phdmEvaW8vQnVmZmVyZWRSZWFkZXJcIjtcbmltcG9ydCB7IFVuaXQgfSBmcm9tIFwianZtLXR5cGVzL2tvdGxpbi9Vbml0XCI7XG5pbXBvcnQgeyBQb2x5Z2xvdFNjcmlwdCB9IGZyb20gXCJqdm0tdHlwZXMvbmV0L2NjYmx1ZXgvbGlxdWlkYm91bmNlL3NjcmlwdC9Qb2x5Z2xvdFNjcmlwdFwiO1xuaW1wb3J0IHsgRnVuY3Rpb24wIH0gZnJvbSBcImp2bS10eXBlcy9rb3RsaW4vanZtL2Z1bmN0aW9ucy9GdW5jdGlvbjBcIjtcbmltcG9ydCB7IENsaWVudE1vZHVsZSB9IGZyb20gXCJqdm0tdHlwZXMvbmV0L2NjYmx1ZXgvbGlxdWlkYm91bmNlL2ZlYXR1cmVzL21vZHVsZS9DbGllbnRNb2R1bGVcIjtcblxuY29uc3Qgc2NyaXB0ID0gcmVnaXN0ZXJTY3JpcHQuYXBwbHkoe1xuICAgIG5hbWU6IFwiaG90LXJlbG9hZGVyXCIsXG4gICAgdmVyc2lvbjogXCIxLjAuMFwiLFxuICAgIGF1dGhvcnM6IFtcImNvbW1hbmRibG9jazJcIl1cbn0pO1xuXG5zY3JpcHQucmVnaXN0ZXJNb2R1bGUoe1xuICAgIG5hbWU6IFwiU2NyaXB0SG90UmVsb2FkZXJcIixcbiAgICBkZXNjcmlwdGlvbjogXCJSZWxvYWRzIHVwZGF0ZWQgc2NyaXB0cyBvbiBIVFRQIFBPU1QgdG8gL3JlbG9hZCAoc2VuZCBKU09OIGFycmF5IG9mIHVwZGF0ZWQgc2NyaXB0IG5hbWVzL3BhdGhzKS5cIixcbiAgICBjYXRlZ29yeTogXCJDbGllbnRcIixcbiAgICBzZXR0aW5nczoge1xuICAgICAgICBwb3J0OiBTZXR0aW5nLmludCh7XG4gICAgICAgICAgICBuYW1lOiBcIlBvcnRcIixcbiAgICAgICAgICAgIGRlZmF1bHQ6IDE4NDcwLFxuICAgICAgICAgICAgcmFuZ2U6IFsxMDI0LCA2NTUzNV0sXG4gICAgICAgICAgICBzdWZmaXg6IFwiXCJcbiAgICAgICAgfSksXG4gICAgICAgIHJlZW5hYmxlTW9kdWxlczogU2V0dGluZy5ib29sZWFuKHtcbiAgICAgICAgICAgIG5hbWU6IFwiUmVlbmFibGUgTW9kdWxlc1wiLFxuICAgICAgICAgICAgZGVmYXVsdDogdHJ1ZSxcbiAgICAgICAgfSlcblxuICAgIH0sXG59LCAobW9kKSA9PiB7XG4gICAgbGV0IHNlcnZlcjogSHR0cFNlcnZlciB8IG51bGwgPSBudWxsO1xuXG4gICAgZnVuY3Rpb24gcmVhZEJvZHlBc1N0cmluZyhleGNoYW5nZTogSHR0cEV4Y2hhbmdlKTogc3RyaW5nIHtcbiAgICAgICAgY29uc3QgaW5wdXRTdHJlYW06IElucHV0U3RyZWFtID0gZXhjaGFuZ2UuZ2V0UmVxdWVzdEJvZHkoKTtcbiAgICAgICAgY29uc3QgcmVhZGVyID0gbmV3IEJ1ZmZlcmVkUmVhZGVyKG5ldyBJbnB1dFN0cmVhbVJlYWRlcihpbnB1dFN0cmVhbSwgXCJVVEYtOFwiKSk7XG4gICAgICAgIGxldCBsaW5lczogc3RyaW5nW10gPSBbXTtcbiAgICAgICAgbGV0IGxpbmU6IHN0cmluZyB8IG51bGwgPSBudWxsO1xuICAgICAgICB3aGlsZSAoKGxpbmUgPSByZWFkZXIucmVhZExpbmUoKSkgIT09IG51bGwpIHtcbiAgICAgICAgICAgIGxpbmVzLnB1c2gobGluZSk7XG4gICAgICAgIH1cbiAgICAgICAgcmVhZGVyLmNsb3NlKCk7XG4gICAgICAgIHJldHVybiBsaW5lcy5qb2luKFwiXFxuXCIpO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIHJlbG9hZE1hdGNoaW5nU2NyaXB0cyhpZExpc3Q6IHN0cmluZ1tdKTogc3RyaW5nW10ge1xuICAgICAgICB0cnkge1xuICAgICAgICAgICAgY29uc3Qgc2NyaXB0cyA9IChTY3JpcHRNYW5hZ2VyLklOU1RBTkNFLnNjcmlwdHMgYXMgYW55KS50b0FycmF5KCkgYXMgQXJyYXk8UG9seWdsb3RTY3JpcHQ+O1xuICAgICAgICAgICAgY29uc3QgcmVsb2FkZWQ6IHN0cmluZ1tdID0gW107XG4gICAgICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IHNjcmlwdHMubGVuZ3RoOyArK2kpIHtcbiAgICAgICAgICAgICAgICBjb25zdCBzY3JpcHRfID0gc2NyaXB0c1tpXTtcbiAgICBcbiAgICAgICAgICAgICAgICBpZiAoc2NyaXB0XyA9PSBzY3JpcHQpXG4gICAgICAgICAgICAgICAgICAgIGNvbnRpbnVlOyAvLyBEbyBub3QgcmVsb2FkIG91cnNlbGYgeERcbiAgICBcbiAgICAgICAgICAgICAgICBjb25zdCBmID0gc2NyaXB0Xy5maWxlO1xuICAgICAgICAgICAgICAgIGNvbnN0IGZpbGVQYXRoID0gZiA/IChmLmdldEFic29sdXRlUGF0aCA/IGYuZ2V0QWJzb2x1dGVQYXRoKCkgOiBmLnRvU3RyaW5nKCkpIDogXCJcIjtcbiAgICAgICAgICAgICAgICBjb25zdCBzaW1wbGVGaWxlID0gZiA/IChmLmdldE5hbWUgPyBmLmdldE5hbWUoKSA6IFwiXCIpIDogXCJcIjtcbiAgICAgICAgICAgICAgICBjb25zdCBzY3JpcHROYW1lID0gc2NyaXB0Xy5zY3JpcHROYW1lIHx8IFwiXCI7XG4gICAgICAgICAgICAgICAgZm9yIChsZXQgaWQgb2YgaWRMaXN0KSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChpZCA9PT0gZmlsZVBhdGgucmVwbGFjZShcIi5qc1wiLCBcIlwiKSB8fCBpZCA9PT0gc2ltcGxlRmlsZS5yZXBsYWNlKFwiLmpzXCIsIFwiXCIpIHx8IGlkID09PSBzY3JpcHROYW1lKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBTdG9yZSBlbmFibGVkIG1vZHVsZSBzdGF0ZXMgaWYgcmUtZW5hYmxlIHNldHRpbmcgaXMgb25cbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGVuYWJsZWRNb2R1bGVzOiBzdHJpbmdbXSA9IFtdO1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKG1vZC5zZXR0aW5ncy5yZWVuYWJsZU1vZHVsZXMuZ2V0VmFsdWUoKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIEFjY2VzcyB0aGUgcmVnaXN0ZXJlZCBtb2R1bGVzIGZpZWxkIHVzaW5nIHJlZmxlY3Rpb25cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBAdHMtZXhwZWN0LWVycm9yXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHJlZ2lzdGVyZWRNb2R1bGVzRmllbGQgPSBzY3JpcHRfLmdldENsYXNzKCkuZ2V0RGVjbGFyZWRGaWVsZChcInJlZ2lzdGVyZWRNb2R1bGVzXCIpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZWdpc3RlcmVkTW9kdWxlc0ZpZWxkLnNldEFjY2Vzc2libGUodHJ1ZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IG1vZHVsZXMgPSByZWdpc3RlcmVkTW9kdWxlc0ZpZWxkLmdldChzY3JpcHRfKSBhcyBhbnk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAobW9kdWxlcyAmJiBtb2R1bGVzLnRvQXJyYXkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IG1vZHVsZUFycmF5ID0gbW9kdWxlcy50b0FycmF5KCkgYXMgQXJyYXk8Q2xpZW50TW9kdWxlPjtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZvciAoY29uc3QgbW9kdWxlIG9mIG1vZHVsZUFycmF5KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKG1vZHVsZS5lbmFibGVkKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVuYWJsZWRNb2R1bGVzLnB1c2gobW9kdWxlLmJhc2VLZXkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgQ2xpZW50LmRpc3BsYXlDaGF0TWVzc2FnZShgwqdlW0hvdFJlbG9hZF0gwqdmRXJyb3IgYWNjZXNzaW5nIG1vZHVsZXM6ICR7ZX1gKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICBcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIFVubG9hZCBhbmQgcmVsb2FkIHRoZSBzY3JpcHRcbiAgICAgICAgICAgICAgICAgICAgICAgIFNjcmlwdE1hbmFnZXIuSU5TVEFOQ0UudW5sb2FkU2NyaXB0KHNjcmlwdF8pO1xuICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgcmVsb2FkZWRTY3JpcHQgPSBTY3JpcHRNYW5hZ2VyLklOU1RBTkNFLmxvYWRTY3JpcHQoc2NyaXB0Xy5maWxlLCBzY3JpcHRfLmxhbmd1YWdlLCBzY3JpcHRfLmRlYnVnT3B0aW9ucyk7XG4gICAgICAgICAgICAgICAgICAgICAgICByZWxvYWRlZFNjcmlwdC5lbmFibGUoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIFxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gUmUtZW5hYmxlIG1vZHVsZXMgaWYgbmVlZGVkXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAobW9kLnNldHRpbmdzLnJlZW5hYmxlTW9kdWxlcy5nZXRWYWx1ZSgpICYmIGVuYWJsZWRNb2R1bGVzLmxlbmd0aCA+IDApIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBAdHMtZXhwZWN0LWVycm9yXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHJlZ2lzdGVyZWRNb2R1bGVzRmllbGQgPSByZWxvYWRlZFNjcmlwdC5nZXRDbGFzcygpLmdldERlY2xhcmVkRmllbGQoXCJyZWdpc3RlcmVkTW9kdWxlc1wiKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVnaXN0ZXJlZE1vZHVsZXNGaWVsZC5zZXRBY2Nlc3NpYmxlKHRydWUpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBtb2R1bGVzID0gcmVnaXN0ZXJlZE1vZHVsZXNGaWVsZC5nZXQocmVsb2FkZWRTY3JpcHQpIGFzIGFueTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChtb2R1bGVzICYmIG1vZHVsZXMudG9BcnJheSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgbW9kdWxlQXJyYXkgPSBtb2R1bGVzLnRvQXJyYXkoKSBhcyBBcnJheTxDbGllbnRNb2R1bGU+O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZm9yIChjb25zdCBtb2R1bGUgb2YgbW9kdWxlQXJyYXkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoZW5hYmxlZE1vZHVsZXMuaW5jbHVkZXMobW9kdWxlLmJhc2VLZXkpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1vZHVsZS5lbmFibGUoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIENsaWVudC5kaXNwbGF5Q2hhdE1lc3NhZ2UoYMKnZVtIb3RSZWxvYWRdIMKnZlJlLWVuYWJsZWQgJHtlbmFibGVkTW9kdWxlcy5sZW5ndGh9IG1vZHVsZXMgZm9yICR7c2NyaXB0TmFtZX1gKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIENsaWVudC5kaXNwbGF5Q2hhdE1lc3NhZ2UoYMKnZVtIb3RSZWxvYWRdIMKnZkVycm9yIHJlLWVuYWJsaW5nIG1vZHVsZXM6ICR7ZX1gKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBGb3IgdGhpcyBwYXJ0IGNsYXVkZS0zLTcgb3V0IHNtYXJ0ZWQgbWUsIFxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gSSBvbiBteSBvd24gcmVtb3ZlZCB0aGF0IHBhcnQgYW5kIHN0b3JlZCB0aGUgY2xpZW50IG1vZHVsZXMgb2JqZWN0cyBhcmUgYW4gYXJyYXkgSSB3YXMgdHJ5aW5nIHRvIHNpbXBseSByZS1lbmFibGUgdGhvc2UgbW9kdWxlcyBkaXJlY3RseVxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gYnV0IGFmdGVyIHJlbG9hZGluZyB0aGUgc2NyaXB0IHRoZSBvcmlnaW5hbCBjbGllbnQgbW9kdWxlcyB3ZXJlIGdjJ2VkXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBzbyB0aGVyZSB3aWxsIGJlIGBvcmcuZ3JhYWx2bS5wb2x5Z2xvdC5Qb2x5Z2xvdEV4Y2VwdGlvbjogQ29udGV4dCBleGVjdXRpb24gd2FzIGNhbmNlbGxlZC5gXG4gICAgICAgICAgICAgICAgICAgICAgICBcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlbG9hZGVkLnB1c2goc2NyaXB0TmFtZSB8fCBzaW1wbGVGaWxlIHx8IGZpbGVQYXRoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIHJlbG9hZGVkO1xuICAgICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgICAgICBDbGllbnQuZGlzcGxheUNoYXRNZXNzYWdlKGDCp2VbSG90UmVsb2FkXSDCp2ZFcnJvciBpbiByZWxvYWRNYXRjaGluZ1NjcmlwdHM6ICR7ZX1gKTtcbiAgICAgICAgICAgIHJldHVybiBbXTtcbiAgICAgICAgfVxuICAgIH1cbiAgICBcblxuICAgIGZ1bmN0aW9uIG91dFJlc3AoZXhjaGFuZ2U6IEh0dHBFeGNoYW5nZSwgY29kZTogbnVtYmVyLCBtc2c6IHN0cmluZykge1xuICAgICAgICBleGNoYW5nZS5zZW5kUmVzcG9uc2VIZWFkZXJzKGNvZGUsIG1zZy5sZW5ndGgpO1xuICAgICAgICBjb25zdCBvcyA9IGV4Y2hhbmdlLmdldFJlc3BvbnNlQm9keSgpO1xuICAgICAgICAvLyBAdHMtZXhwZWN0LWVycm9yXG4gICAgICAgIG9zLndyaXRlKG5ldyBqYXZhLmxhbmcuU3RyaW5nKG1zZykuZ2V0Qnl0ZXMoKSk7XG4gICAgICAgIG9zLmNsb3NlKCk7XG4gICAgfVxuXG4gICAgLy8gQWRkIHRoZXNlIGF0IHRoZSBtb2R1bGUgbGV2ZWxcbiAgICBsZXQgc2NyaXB0SWRzVG9SZWxvYWQ6IHN0cmluZ1tdID0gW107XG4gICAgbGV0IHBlbmRpbmdSZWxvYWQgPSBmYWxzZTtcbiAgICBsZXQgcGVuZGluZ0V4Y2hhbmdlOiBIdHRwRXhjaGFuZ2UgfCBudWxsID0gbnVsbDtcblxuICAgIC8vIFVwZGF0ZSB0aGUgcmVsb2FkIGhhbmRsZXJcbiAgICBtb2Qub24oXCJlbmFibGVcIiwgKCkgPT4ge1xuICAgICAgICBjb25zdCBwb3J0ID0gbW9kLnNldHRpbmdzLnBvcnQuZ2V0VmFsdWUoKTtcblxuICAgICAgICB0cnkge1xuICAgICAgICAgICAgc2VydmVyID0gSHR0cFNlcnZlci5jcmVhdGUobmV3IEluZXRTb2NrZXRBZGRyZXNzKHBvcnQpLCAwKTtcbiAgICAgICAgICAgIGNvbnN0IHJlbG9hZEhhbmRsZXI6IEh0dHBIYW5kbGVyID0ge1xuICAgICAgICAgICAgICAgIC8vIEB0cy1leHBlY3QtZXJyb3JcbiAgICAgICAgICAgICAgICBoYW5kbGU6IChleGNoYW5nZTogSHR0cEV4Y2hhbmdlKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChleGNoYW5nZS5nZXRSZXF1ZXN0TWV0aG9kKCkgPT09IFwiUE9TVFwiKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBib2R5ID0gcmVhZEJvZHlBc1N0cmluZyhleGNoYW5nZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICBsZXQgaWRzOiBzdHJpbmdbXSA9IFtdO1xuICAgICAgICAgICAgICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZHMgPSBKU09OLnBhcnNlKGJvZHkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSBjYXRjaCB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgb3V0UmVzcChleGNoYW5nZSwgNDAwLCBcIkludmFsaWQgSlNPTiBhcnJheS5cIik7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgQ2xpZW50LmRpc3BsYXlDaGF0TWVzc2FnZShcIsKnZVtIb3RSZWxvYWRdIMKnZlJlY2VpdmVkIG1hbGZvcm1lZCBQT1NUIHRvIC9yZWxvYWQgKG5vdCBhIEpTT04gYXJyYXkpXCIpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICghQXJyYXkuaXNBcnJheShpZHMpIHx8IGlkcy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBvdXRSZXNwKGV4Y2hhbmdlLCAyMDAsIFwiTm8gc2NyaXB0cyB0byByZWxvYWQuXCIpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gUXVldWUgdGhlIHJlbG9hZCByZXF1ZXN0IGZvciB0aGUgcmVuZGVyIHRocmVhZFxuICAgICAgICAgICAgICAgICAgICAgICAgc2NyaXB0SWRzVG9SZWxvYWQgPSBpZHM7XG4gICAgICAgICAgICAgICAgICAgICAgICBwZW5kaW5nUmVsb2FkID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHBlbmRpbmdFeGNoYW5nZSA9IGV4Y2hhbmdlO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBJbmZvcm0gdXNlciB0aGF0IHJlbG9hZCBpcyBwZW5kaW5nXG4gICAgICAgICAgICAgICAgICAgICAgICBDbGllbnQuZGlzcGxheUNoYXRNZXNzYWdlKFwiwqdlW0hvdFJlbG9hZF0gwqdmU2NyaXB0IHJlbG9hZCByZXF1ZXN0IHF1ZXVlZCBmb3IgbmV4dCByZW5kZXIgZnJhbWVcIik7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBleGNoYW5nZS5zZW5kUmVzcG9uc2VIZWFkZXJzKDQwNSwgLTEpO1xuICAgICAgICAgICAgICAgICAgICAgICAgZXhjaGFuZ2UuY2xvc2UoKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH07XG4gICAgICAgICAgICBzZXJ2ZXIuY3JlYXRlQ29udGV4dChcIi9yZWxvYWRcIiwgcmVsb2FkSGFuZGxlcik7XG4gICAgICAgICAgICBzZXJ2ZXIuc3RhcnQoKTtcbiAgICAgICAgICAgIENsaWVudC5kaXNwbGF5Q2hhdE1lc3NhZ2UoYMKnZVtIb3RSZWxvYWRdIMKnZkhUVFAgc2VydmVyIHN0YXJ0ZWQgb24gcG9ydCAke3BvcnR9LCBQT1NUIC9yZWxvYWQgKHdpdGggSlNPTiBhcnJheSBpbiBib2R5KSB0byByZWxvYWQgb25seSB1cGRhdGVkIHNjcmlwdHMuYCk7XG4gICAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgICAgIENsaWVudC5kaXNwbGF5Q2hhdE1lc3NhZ2UoYMKnZVtIb3RSZWxvYWRdIMKnZkZhaWxlZCB0byBzdGFydCBIVFRQIHNlcnZlciBvbiBwb3J0ICR7cG9ydH06ICR7ZX1gKTtcbiAgICAgICAgfVxuICAgIH0pO1xuXG4gICAgLy8gQWRkIGEgd29ybGRyZW5kZXIgZXZlbnQgdG8gaGFuZGxlIHNjcmlwdCByZWxvYWRpbmcgb24gdGhlIHJlbmRlciB0aHJlYWRcbiAgICBtb2Qub24oXCJ3b3JsZHJlbmRlclwiLCAoKSA9PiB7XG4gICAgICAgIGlmIChwZW5kaW5nUmVsb2FkICYmIHBlbmRpbmdFeGNoYW5nZSkge1xuICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICAvLyBOb3cgd2UncmUgb24gdGhlIHJlbmRlciB0aHJlYWQsIGl0J3Mgc2FmZSB0byByZWxvYWQgc2NyaXB0c1xuICAgICAgICAgICAgICAgIGNvbnN0IHJlbG9hZGVkID0gcmVsb2FkTWF0Y2hpbmdTY3JpcHRzKHNjcmlwdElkc1RvUmVsb2FkKTtcbiAgICAgICAgICAgICAgICBjb25zdCByZXNwID0gcmVsb2FkZWQubGVuZ3RoID4gMFxuICAgICAgICAgICAgICAgICAgICA/IGBSZWxvYWRlZCBzY3JpcHRzOiAke3JlbG9hZGVkLmpvaW4oXCIsIFwiKX1gXG4gICAgICAgICAgICAgICAgICAgIDogYE5vIG1hdGNoaW5nIHNjcmlwdHMgZm91bmQgdG8gcmVsb2FkLiBTY3JpcHQgaWRzIHJlcXVlc3RlZCBmcm9tIGVuZHBvaW50OiAke3NjcmlwdElkc1RvUmVsb2FkfWA7XG5cbiAgICAgICAgICAgICAgICAvLyBSZXNwb25kIHRvIHRoZSBIVFRQIHJlcXVlc3RcbiAgICAgICAgICAgICAgICBvdXRSZXNwKHBlbmRpbmdFeGNoYW5nZSwgMjAwLCByZXNwKTtcbiAgICAgICAgICAgICAgICBDbGllbnQuZGlzcGxheUNoYXRNZXNzYWdlKGDCp2VbSG90UmVsb2FkXSDCp2Yke3Jlc3B9YCk7XG4gICAgICAgICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgICAgICAgICAgaWYgKHBlbmRpbmdFeGNoYW5nZSkge1xuICAgICAgICAgICAgICAgICAgICBvdXRSZXNwKHBlbmRpbmdFeGNoYW5nZSwgNTAwLCBgRXJyb3I6ICR7ZX1gKTtcbiAgICAgICAgICAgICAgICAgICAgQ2xpZW50LmRpc3BsYXlDaGF0TWVzc2FnZShgwqdlW0hvdFJlbG9hZF0gwqdmRXJyb3IgZHVyaW5nIHJlbG9hZDogJHtlfWApO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0gZmluYWxseSB7XG4gICAgICAgICAgICAgICAgLy8gUmVzZXQgdGhlIHBlbmRpbmcgc3RhdGVcbiAgICAgICAgICAgICAgICBwZW5kaW5nUmVsb2FkID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgcGVuZGluZ0V4Y2hhbmdlID0gbnVsbDtcbiAgICAgICAgICAgICAgICBzY3JpcHRJZHNUb1JlbG9hZCA9IFtdO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfSk7XG5cbiAgICBtb2Qub24oXCJkaXNhYmxlXCIsICgpID0+IHtcbiAgICAgICAgaWYgKHNlcnZlciAhPT0gbnVsbCkge1xuICAgICAgICAgICAgc2VydmVyLnN0b3AoMCk7XG4gICAgICAgICAgICBzZXJ2ZXIgPSBudWxsO1xuICAgICAgICAgICAgQ2xpZW50LmRpc3BsYXlDaGF0TWVzc2FnZShcIsKnZVtIb3RSZWxvYWRdIMKnZkhUVFAgc2VydmVyIHN0b3BwZWQuXCIpO1xuICAgICAgICB9XG4gICAgfSk7XG59KTtcbiJdfQ==