@nlabs/reaktor 0.3.0 → 0.4.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/actions/conversations.d.ts +14 -0
- package/lib/actions/conversations.js +333 -0
- package/lib/actions/dynamodb.js +155 -0
- package/lib/actions/email.js +177 -0
- package/lib/actions/files.js +319 -0
- package/lib/{data → actions}/groups.d.ts +4 -3
- package/lib/actions/groups.js +282 -0
- package/lib/actions/images.d.ts +22 -0
- package/lib/actions/images.js +682 -0
- package/lib/actions/index.js +40 -0
- package/lib/{data → actions}/ios.d.ts +2 -1
- package/lib/actions/ios.js +179 -0
- package/lib/actions/locations.js +112 -0
- package/lib/actions/messages.d.ts +13 -0
- package/lib/actions/messages.js +216 -0
- package/lib/actions/notifications.js +63 -0
- package/lib/{data → actions}/payments.d.ts +2 -2
- package/lib/actions/payments.js +491 -0
- package/lib/actions/posts.d.ts +19 -0
- package/lib/actions/posts.js +538 -0
- package/lib/actions/reactions.d.ts +30 -0
- package/lib/actions/reactions.js +340 -0
- package/lib/{data → actions}/s3.d.ts +1 -1
- package/lib/actions/s3.js +122 -0
- package/lib/{data → actions}/search.d.ts +2 -2
- package/lib/actions/search.js +99 -0
- package/lib/actions/sms.js +76 -0
- package/lib/actions/statistics.d.ts +2 -0
- package/lib/actions/statistics.js +63 -0
- package/lib/actions/subscription.js +209 -0
- package/lib/actions/tags.d.ts +26 -0
- package/lib/actions/tags.js +340 -0
- package/lib/actions/users.d.ts +44 -0
- package/lib/actions/users.js +571 -0
- package/lib/{data → actions}/websockets.d.ts +1 -1
- package/lib/actions/websockets.js +156 -0
- package/lib/config.d.ts +2 -3
- package/lib/config.js +120 -0
- package/lib/index.d.ts +1 -1
- package/lib/index.js +23 -0
- package/lib/templates/email/layout.d.ts +2 -0
- package/lib/templates/email/layout.js +292 -0
- package/lib/templates/email/passwordForgot.d.ts +2 -0
- package/lib/templates/email/passwordForgot.js +28 -0
- package/lib/templates/email/passwordRecovery.d.ts +2 -0
- package/lib/templates/email/passwordRecovery.js +25 -0
- package/lib/templates/email/verifyEmail.d.ts +2 -0
- package/lib/templates/email/verifyEmail.js +28 -0
- package/lib/templates/email/welcome.d.ts +2 -0
- package/lib/templates/email/welcome.js +28 -0
- package/lib/templates/sms/passwordForgot.d.ts +2 -0
- package/lib/templates/sms/passwordForgot.js +14 -0
- package/lib/templates/sms/passwordRecovery.d.ts +2 -0
- package/lib/templates/sms/passwordRecovery.js +14 -0
- package/lib/templates/sms/verifyEmail.d.ts +2 -0
- package/lib/templates/sms/verifyEmail.js +14 -0
- package/lib/templates/sms/verifyPhone.d.ts +2 -0
- package/lib/templates/sms/verifyPhone.js +14 -0
- package/lib/templates/sms/welcome.d.ts +2 -0
- package/lib/templates/sms/welcome.js +14 -0
- package/lib/types/apps.d.ts +2 -2
- package/lib/types/apps.js +4 -0
- package/lib/types/arangodb.js +4 -0
- package/lib/types/auth.d.ts +4 -8
- package/lib/types/auth.js +4 -0
- package/lib/types/conversations.d.ts +5 -3
- package/lib/types/conversations.js +4 -0
- package/lib/types/email.d.ts +2 -2
- package/lib/types/email.js +4 -0
- package/lib/types/files.js +4 -0
- package/lib/types/google.js +4 -0
- package/lib/types/groups.d.ts +2 -1
- package/lib/types/groups.js +4 -0
- package/lib/types/images.d.ts +8 -5
- package/lib/types/images.js +4 -0
- package/lib/types/index.d.ts +1 -1
- package/lib/types/index.js +37 -0
- package/lib/types/locations.js +4 -0
- package/lib/types/messages.d.ts +12 -2
- package/lib/types/messages.js +4 -0
- package/lib/types/notifications.d.ts +2 -2
- package/lib/types/notifications.js +4 -0
- package/lib/types/payments.js +4 -0
- package/lib/types/posts.d.ts +18 -1
- package/lib/types/posts.js +4 -0
- package/lib/types/statistics.d.ts +3 -0
- package/lib/types/statistics.js +4 -0
- package/lib/types/tags.d.ts +6 -0
- package/lib/types/tags.js +4 -0
- package/lib/types/users.d.ts +15 -10
- package/lib/types/users.js +4 -0
- package/lib/utils/analytics.d.ts +7 -0
- package/lib/utils/analytics.js +107 -0
- package/lib/utils/arangodb.d.ts +1 -1
- package/lib/utils/arangodb.js +122 -0
- package/lib/utils/auth.js +78 -0
- package/lib/utils/graphql.js +40 -0
- package/lib/utils/index.d.ts +1 -1
- package/lib/utils/index.js +26 -0
- package/lib/utils/objects.js +53 -0
- package/lib/utils/session.d.ts +18 -0
- package/lib/utils/session.js +42 -0
- package/package.json +35 -33
- package/lib/data/conversations.d.ts +0 -8
- package/lib/data/images.d.ts +0 -21
- package/lib/data/messages.d.ts +0 -9
- package/lib/data/posts.d.ts +0 -23
- package/lib/data/reactions.d.ts +0 -14
- package/lib/data/tags.d.ts +0 -14
- package/lib/data/users.d.ts +0 -17
- package/lib/types/reactions.d.ts +0 -15
- package/lib/utils/redis.d.ts +0 -1
- package/templates/email/layout.html +0 -279
- package/templates/email/passwordForgot.html +0 -15
- package/templates/email/passwordRecovery.html +0 -12
- package/templates/email/verifyEmail.html +0 -15
- package/templates/sms/passwordForgot.txt +0 -1
- package/templates/sms/passwordRecovery.txt +0 -1
- package/templates/sms/verifyEmail.txt +0 -1
- package/templates/sms/verifyPhone.txt +0 -1
- /package/lib/{data → actions}/dynamodb.d.ts +0 -0
- /package/lib/{data → actions}/email.d.ts +0 -0
- /package/lib/{data → actions}/files.d.ts +0 -0
- /package/lib/{data → actions}/index.d.ts +0 -0
- /package/lib/{data → actions}/locations.d.ts +0 -0
- /package/lib/{data → actions}/notifications.d.ts +0 -0
- /package/lib/{data → actions}/sms.d.ts +0 -0
- /package/lib/{data → actions}/subscription.d.ts +0 -0
|
@@ -0,0 +1,682 @@
|
|
|
1
|
+
var __create = Object.create;
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __defProps = Object.defineProperties;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
|
|
6
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
7
|
+
var __getOwnPropSymbols = Object.getOwnPropertySymbols;
|
|
8
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
9
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
10
|
+
var __propIsEnum = Object.prototype.propertyIsEnumerable;
|
|
11
|
+
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
12
|
+
var __spreadValues = (a, b) => {
|
|
13
|
+
for (var prop in b || (b = {}))
|
|
14
|
+
if (__hasOwnProp.call(b, prop))
|
|
15
|
+
__defNormalProp(a, prop, b[prop]);
|
|
16
|
+
if (__getOwnPropSymbols)
|
|
17
|
+
for (var prop of __getOwnPropSymbols(b)) {
|
|
18
|
+
if (__propIsEnum.call(b, prop))
|
|
19
|
+
__defNormalProp(a, prop, b[prop]);
|
|
20
|
+
}
|
|
21
|
+
return a;
|
|
22
|
+
};
|
|
23
|
+
var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
|
|
24
|
+
var __markAsModule = (target) => __defProp(target, "__esModule", { value: true });
|
|
25
|
+
var __export = (target, all) => {
|
|
26
|
+
__markAsModule(target);
|
|
27
|
+
for (var name in all)
|
|
28
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
29
|
+
};
|
|
30
|
+
var __reExport = (target, module2, desc) => {
|
|
31
|
+
if (module2 && typeof module2 === "object" || typeof module2 === "function") {
|
|
32
|
+
for (let key of __getOwnPropNames(module2))
|
|
33
|
+
if (!__hasOwnProp.call(target, key) && key !== "default")
|
|
34
|
+
__defProp(target, key, { get: () => module2[key], enumerable: !(desc = __getOwnPropDesc(module2, key)) || desc.enumerable });
|
|
35
|
+
}
|
|
36
|
+
return target;
|
|
37
|
+
};
|
|
38
|
+
var __toModule = (module2) => {
|
|
39
|
+
return __reExport(__markAsModule(__defProp(module2 != null ? __create(__getProtoOf(module2)) : {}, "default", module2 && module2.__esModule && "default" in module2 ? { get: () => module2.default, enumerable: true } : { value: module2, enumerable: true })), module2);
|
|
40
|
+
};
|
|
41
|
+
__export(exports, {
|
|
42
|
+
addImage: () => addImage,
|
|
43
|
+
addImageEdge: () => addImageEdge,
|
|
44
|
+
deleteImage: () => deleteImage,
|
|
45
|
+
getAppImageUrl: () => getAppImageUrl,
|
|
46
|
+
getImage: () => getImage,
|
|
47
|
+
getImageCountByItem: () => getImageCountByItem,
|
|
48
|
+
getImageOptional: () => getImageOptional,
|
|
49
|
+
getImagesByGroup: () => getImagesByGroup,
|
|
50
|
+
getImagesByItem: () => getImagesByItem,
|
|
51
|
+
getImagesByReactions: () => getImagesByReactions,
|
|
52
|
+
getImagesByUser: () => getImagesByUser,
|
|
53
|
+
getPathUserImages: () => getPathUserImages,
|
|
54
|
+
getUserImageUrl: () => getUserImageUrl,
|
|
55
|
+
parseImageOptions: () => parseImageOptions,
|
|
56
|
+
resizeSaveImage: () => resizeSaveImage,
|
|
57
|
+
updateImage: () => updateImage
|
|
58
|
+
});
|
|
59
|
+
var import_rip_hunter = __toModule(require("@nlabs/rip-hunter"));
|
|
60
|
+
var import_utils = __toModule(require("@nlabs/utils"));
|
|
61
|
+
var import_arangojs = __toModule(require("arangojs"));
|
|
62
|
+
var import_file_type = __toModule(require("file-type"));
|
|
63
|
+
var import_gm = __toModule(require("gm"));
|
|
64
|
+
var import_cloneDeep = __toModule(require("lodash/cloneDeep"));
|
|
65
|
+
var import_isEmpty = __toModule(require("lodash/isEmpty"));
|
|
66
|
+
var import_luxon = __toModule(require("luxon"));
|
|
67
|
+
var import_config = __toModule(require("../config"));
|
|
68
|
+
var import_utils2 = __toModule(require("../utils"));
|
|
69
|
+
var import_groups = __toModule(require("./groups"));
|
|
70
|
+
var import_s32 = __toModule(require("./s3"));
|
|
71
|
+
const eventCategory = "images";
|
|
72
|
+
const parseImageOptions = (options = {}) => {
|
|
73
|
+
const {
|
|
74
|
+
from = 0,
|
|
75
|
+
to = 30,
|
|
76
|
+
type = "default"
|
|
77
|
+
} = options;
|
|
78
|
+
return {
|
|
79
|
+
limit: (0, import_utils2.getLimit)(from, to),
|
|
80
|
+
type: (0, import_utils.parseChar)(type, 32)
|
|
81
|
+
};
|
|
82
|
+
};
|
|
83
|
+
const getImageOptional = (fields = []) => fields.reduce((selects, field) => {
|
|
84
|
+
if (field.includes("Count")) {
|
|
85
|
+
return (0, import_utils2.selectReactionCountByType)("images", "i", field, selects);
|
|
86
|
+
}
|
|
87
|
+
switch (field) {
|
|
88
|
+
case "reactions": {
|
|
89
|
+
selects.queries.push(`LET reactions = (
|
|
90
|
+
FOR image, r IN INBOUND i._id reactions
|
|
91
|
+
COLLECT reactionName = r.value INTO reactionItems
|
|
92
|
+
RETURN {name: reactionName, count: LENGTH(reactionItems[*].r.value)}
|
|
93
|
+
)`);
|
|
94
|
+
selects.objects.push("reactions:reactions");
|
|
95
|
+
return selects;
|
|
96
|
+
}
|
|
97
|
+
case "tags": {
|
|
98
|
+
selects.queries.push(`LET tags = (
|
|
99
|
+
FOR t, pl IN INBOUND i._id isTagged
|
|
100
|
+
RETURN t
|
|
101
|
+
)`);
|
|
102
|
+
selects.objects.push("tags:tags");
|
|
103
|
+
return selects;
|
|
104
|
+
}
|
|
105
|
+
case "user": {
|
|
106
|
+
selects.queries.push(`LET user = FIRST(
|
|
107
|
+
FOR u IN users
|
|
108
|
+
FILTER i.userId == u._key
|
|
109
|
+
LIMIT 1
|
|
110
|
+
RETURN u
|
|
111
|
+
)`);
|
|
112
|
+
selects.objects.push("user:user");
|
|
113
|
+
return selects;
|
|
114
|
+
}
|
|
115
|
+
default: {
|
|
116
|
+
return selects;
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
}, { objects: [], queries: [] });
|
|
120
|
+
const getImagesByUser = (context, userId, from, to) => {
|
|
121
|
+
const action = "getImagesByUser";
|
|
122
|
+
const { database } = context;
|
|
123
|
+
const formatUserId = (0, import_utils.parseId)(userId);
|
|
124
|
+
const limit = (0, import_utils2.getLimit)(from, to);
|
|
125
|
+
const aqlQry = `FOR i IN images
|
|
126
|
+
FILTER i.userId == "${formatUserId}"
|
|
127
|
+
LET user = FIRST(
|
|
128
|
+
FOR u IN users
|
|
129
|
+
FILTER u._key == i.userId
|
|
130
|
+
LIMIT 1
|
|
131
|
+
RETURN u
|
|
132
|
+
)
|
|
133
|
+
${limit.aql}
|
|
134
|
+
SORT i.added
|
|
135
|
+
RETURN MERGE(i, {user:user})`;
|
|
136
|
+
return database.query(aqlQry).then((cursor) => cursor.all()).catch((error) => (0, import_utils2.logError)({
|
|
137
|
+
action,
|
|
138
|
+
category: eventCategory,
|
|
139
|
+
label: "db_error"
|
|
140
|
+
}, error, context).then(() => null));
|
|
141
|
+
};
|
|
142
|
+
const getImageCountByItem = (context, itemId) => {
|
|
143
|
+
const action = "getImageCountByItem";
|
|
144
|
+
const { database } = context;
|
|
145
|
+
const formatItemId = (0, import_utils.parseArangoId)(itemId);
|
|
146
|
+
const aqlQry = import_arangojs.aql`FOR i IN hasImages
|
|
147
|
+
FILTER i._to == ${formatItemId}
|
|
148
|
+
RETURN {count: COUNT(i)}`;
|
|
149
|
+
return database.query(aqlQry).then((cursor) => cursor.next()).then(({ count } = { count: 0 }) => count).catch((error) => (0, import_utils2.logError)({
|
|
150
|
+
action,
|
|
151
|
+
category: eventCategory,
|
|
152
|
+
label: "db_error"
|
|
153
|
+
}, error, context).then(() => 0));
|
|
154
|
+
};
|
|
155
|
+
const getImagesByItem = async (context, itemId, options = {}) => {
|
|
156
|
+
const action = "getImagesByItem";
|
|
157
|
+
const { database, fields = [] } = context;
|
|
158
|
+
const formatItemId = (0, import_utils.parseArangoId)(itemId);
|
|
159
|
+
const { limit } = parseImageOptions(options);
|
|
160
|
+
const { objects: selectObjects, queries: selectQueries } = getImageOptional(fields);
|
|
161
|
+
const aqlQry = `FOR i, l IN 1..1 OUTBOUND "${formatItemId}" hasImages
|
|
162
|
+
FILTER NOT IS_NULL(i)
|
|
163
|
+
${selectQueries.join("\n")}
|
|
164
|
+
SORT i.added
|
|
165
|
+
${limit.aql}
|
|
166
|
+
RETURN MERGE(i, {${selectObjects.join(", ")}})`;
|
|
167
|
+
return database.query(aqlQry).then((cursor) => cursor.all()).catch((error) => (0, import_utils2.logError)({
|
|
168
|
+
action,
|
|
169
|
+
category: eventCategory,
|
|
170
|
+
label: "db_error"
|
|
171
|
+
}, error, context).then(() => null));
|
|
172
|
+
};
|
|
173
|
+
const getImagesByGroup = (context, params) => {
|
|
174
|
+
const action = "getImagesByGroup";
|
|
175
|
+
const { database, session: { userId: sessionId } } = context;
|
|
176
|
+
const { filters = [], groupId, from, to } = params;
|
|
177
|
+
const formatGroupId = (0, import_utils.parseId)(groupId);
|
|
178
|
+
const limit = (0, import_utils2.getLimit)(from, to);
|
|
179
|
+
filters.map((filter) => {
|
|
180
|
+
const { conditional, name, value } = filter;
|
|
181
|
+
let formatCond = conditional;
|
|
182
|
+
if (conditional !== ">=" && conditional !== "<=" && conditional !== ">" && conditional !== "<") {
|
|
183
|
+
formatCond = "==";
|
|
184
|
+
}
|
|
185
|
+
switch (name) {
|
|
186
|
+
case "added":
|
|
187
|
+
return `p.added ${formatCond} ${(0, import_utils.parseNum)(value)}`;
|
|
188
|
+
default:
|
|
189
|
+
return "";
|
|
190
|
+
}
|
|
191
|
+
});
|
|
192
|
+
return (0, import_groups.getGroupDetails)(context, formatGroupId).then((group) => {
|
|
193
|
+
if (group.privacy === "public") {
|
|
194
|
+
filters.push(`p.groupId == "${groupId}"`);
|
|
195
|
+
const filterStr = filters.join(" && ");
|
|
196
|
+
const aqlQry = `FOR i IN
|
|
197
|
+
FLATTEN(
|
|
198
|
+
FOR p IN posts
|
|
199
|
+
FILTER ${filterStr}
|
|
200
|
+
LET images = (
|
|
201
|
+
FOR i, e IN INBOUND p._id hasImages
|
|
202
|
+
RETURN i
|
|
203
|
+
)
|
|
204
|
+
SORT p.added DESC
|
|
205
|
+
RETURN images
|
|
206
|
+
)
|
|
207
|
+
SORT i.added DESC
|
|
208
|
+
${limit.aql}
|
|
209
|
+
RETURN i`;
|
|
210
|
+
return database.query(aqlQry).then((cursor) => cursor.all()).catch((error) => (0, import_utils2.logError)({
|
|
211
|
+
action,
|
|
212
|
+
category: eventCategory,
|
|
213
|
+
label: "db_error"
|
|
214
|
+
}, error, context).then(() => null));
|
|
215
|
+
}
|
|
216
|
+
return (0, import_groups.isGrouped)(database, sessionId, groupId).then((grouped) => {
|
|
217
|
+
if (grouped.isValid) {
|
|
218
|
+
filters.push(`p.groupId == "${grouped.groupId}"`);
|
|
219
|
+
const filterList = filters.join(" && ");
|
|
220
|
+
const aqlQry = `FOR p IN post
|
|
221
|
+
FILTER ${filterList}
|
|
222
|
+
FOR f IN p.files
|
|
223
|
+
FILTER f.type == "image/jpeg" || f.type == "image/png"
|
|
224
|
+
${limit.aql}
|
|
225
|
+
SORT p.added DESC
|
|
226
|
+
RETURN f`;
|
|
227
|
+
return database.query(aqlQry).then((cursor) => cursor.all()).catch((error) => (0, import_utils2.logError)({
|
|
228
|
+
action,
|
|
229
|
+
category: eventCategory,
|
|
230
|
+
label: "db_error"
|
|
231
|
+
}, error, context).then(() => null));
|
|
232
|
+
}
|
|
233
|
+
return [];
|
|
234
|
+
});
|
|
235
|
+
});
|
|
236
|
+
};
|
|
237
|
+
const getImagesByReactions = (context, reactions = [], options) => {
|
|
238
|
+
const action = "getUsersByImage";
|
|
239
|
+
const { database, fields = [], session: { userId: sessionId } } = context;
|
|
240
|
+
const { limit } = parseImageOptions(options);
|
|
241
|
+
const { objects: selectObjects, queries: selectQueries } = getImageOptional(fields);
|
|
242
|
+
const formatSessionId = `users/${sessionId}`;
|
|
243
|
+
const formatReactions = reactions.map((reactionName) => (0, import_utils.parseChar)(reactionName, 32));
|
|
244
|
+
const filterBy = [
|
|
245
|
+
'r.type == "images"',
|
|
246
|
+
`POSITION(${JSON.stringify(formatReactions)}, LOWER(r.name))`
|
|
247
|
+
];
|
|
248
|
+
const aqlQry = `FOR i, r IN OUTBOUND "${formatSessionId}" hasReactions
|
|
249
|
+
OPTIONS {vertexCollections: "images"}
|
|
250
|
+
${selectQueries.join("\n")}
|
|
251
|
+
FILTER ${filterBy.join(" && ")}
|
|
252
|
+
${limit.aql}
|
|
253
|
+
RETURN MERGE(i, {${selectObjects.join(", ")}})`;
|
|
254
|
+
return database.query(aqlQry).then((cursor) => cursor.all()).catch((error) => (0, import_utils2.logError)({
|
|
255
|
+
action,
|
|
256
|
+
category: eventCategory,
|
|
257
|
+
label: "db_error"
|
|
258
|
+
}, error, context).then(() => []));
|
|
259
|
+
};
|
|
260
|
+
const getImage = (context, id) => {
|
|
261
|
+
const action = "getItem";
|
|
262
|
+
const { database } = context;
|
|
263
|
+
const formatId = (0, import_utils.parseId)(id);
|
|
264
|
+
const aqlQry = import_arangojs.aql`FOR i IN images
|
|
265
|
+
FILTER i._key==${formatId}
|
|
266
|
+
LIMIT 1
|
|
267
|
+
RETURN i`;
|
|
268
|
+
return database.query(aqlQry).then((cursor) => cursor.next()).then((image = {}) => image).catch((error) => (0, import_utils2.logError)({
|
|
269
|
+
action,
|
|
270
|
+
category: eventCategory,
|
|
271
|
+
label: "db_error"
|
|
272
|
+
}, error, context).then(() => null));
|
|
273
|
+
};
|
|
274
|
+
const getPathUserImages = (userId, imageId, type, dir = "images") => {
|
|
275
|
+
let filename = imageId;
|
|
276
|
+
switch (type) {
|
|
277
|
+
case "image/png":
|
|
278
|
+
filename = `${imageId}.png`;
|
|
279
|
+
break;
|
|
280
|
+
default:
|
|
281
|
+
filename = `${imageId}.jpg`;
|
|
282
|
+
break;
|
|
283
|
+
}
|
|
284
|
+
return `users/${userId}/${dir}/${filename}`;
|
|
285
|
+
};
|
|
286
|
+
const getAppImageUrl = (data) => {
|
|
287
|
+
const { imageId, directory = "images", imageType = "profile", isThumb, type, typeId } = data;
|
|
288
|
+
const host = import_config.Config.get("environment") === "prod" ? `https://box.${import_config.Config.get("app.url")}` : `https://s3.amazonaws.com/dev.${import_config.Config.get("app.url")}`;
|
|
289
|
+
const suffix = isThumb ? "-th" : "";
|
|
290
|
+
if (imageId) {
|
|
291
|
+
switch (type) {
|
|
292
|
+
case "apps":
|
|
293
|
+
return `${host}/${type}/${directory}/${imageId}${suffix}.jpg`;
|
|
294
|
+
case "users":
|
|
295
|
+
return `${host}/${type}/${typeId}/${directory}/${imageId}${suffix}.jpg`;
|
|
296
|
+
}
|
|
297
|
+
if (imageType === "profile") {
|
|
298
|
+
return `${host}/defaults/${type}_bk${suffix}.jpg`;
|
|
299
|
+
}
|
|
300
|
+
return `${host}/defaults/${type}_wh${suffix}.jpg`;
|
|
301
|
+
}
|
|
302
|
+
return "";
|
|
303
|
+
};
|
|
304
|
+
const getUserImageUrl = (data) => {
|
|
305
|
+
const { bucket, imageId, isThumb = false, userId } = data;
|
|
306
|
+
const imgDir = isThumb ? "thumbs" : "images";
|
|
307
|
+
if (imageId) {
|
|
308
|
+
const imageKey = `users/${userId}/${imgDir}/${imageId}.jpg`;
|
|
309
|
+
return (0, import_s32.s3GetSignedUrl)({ Bucket: bucket, Key: imageKey, Expires: 900 });
|
|
310
|
+
}
|
|
311
|
+
return "";
|
|
312
|
+
};
|
|
313
|
+
const resizeSaveImage = (context, imageId, buffer, type = "image/jpeg", s3Options) => {
|
|
314
|
+
const action = "resizeSaveImage";
|
|
315
|
+
const { session: { userId: sessionId } } = context;
|
|
316
|
+
const imgW = import_config.Config.get("image.imgSize");
|
|
317
|
+
const imgQ = import_config.Config.get("image.imgQuality");
|
|
318
|
+
let photo = {};
|
|
319
|
+
const format = type.split("/")[1];
|
|
320
|
+
console.log({ buffer, format, imgW, imgQ });
|
|
321
|
+
return new Promise((resolve) => {
|
|
322
|
+
(0, import_gm.default)(buffer, "img").setFormat(format).quality(imgQ).autoOrient().resize(imgW, imgW, ">").identify({ bufferStream: true }, (error, val = {}) => {
|
|
323
|
+
if (error) {
|
|
324
|
+
(0, import_utils2.logError)({
|
|
325
|
+
action,
|
|
326
|
+
category: eventCategory,
|
|
327
|
+
label: "image_save",
|
|
328
|
+
value: "gm_image_identify"
|
|
329
|
+
}, error, context).catch((error2) => {
|
|
330
|
+
throw error2;
|
|
331
|
+
});
|
|
332
|
+
} else {
|
|
333
|
+
const formatVals = (0, import_utils2.lowerCaseKeys)(val);
|
|
334
|
+
const { make: cameraMake, model: cameraModel, datetimeoriginal: taken } = formatVals;
|
|
335
|
+
photo = __spreadProps(__spreadValues({}, (0, import_cloneDeep.default)(photo)), {
|
|
336
|
+
make: cameraMake,
|
|
337
|
+
model: cameraModel,
|
|
338
|
+
taken: taken ? import_luxon.DateTime.fromMillis(taken).millisecond : null
|
|
339
|
+
});
|
|
340
|
+
const stats = formatVals["channel statistics"];
|
|
341
|
+
if (stats) {
|
|
342
|
+
let { red, green, blue, mean } = stats;
|
|
343
|
+
if (red) {
|
|
344
|
+
mean = red["standard deviation"] || red.mean;
|
|
345
|
+
red = mean ? +mean.split(" ")[0].substring(0, 3) : 0;
|
|
346
|
+
} else {
|
|
347
|
+
red = 0;
|
|
348
|
+
}
|
|
349
|
+
if (green) {
|
|
350
|
+
mean = green["standard deviation"] || green.mean;
|
|
351
|
+
green = mean ? +mean.split(" ")[0].substring(0, 3) : 0;
|
|
352
|
+
} else {
|
|
353
|
+
green = 0;
|
|
354
|
+
}
|
|
355
|
+
if (blue) {
|
|
356
|
+
mean = blue["standard deviation"] || blue.mean;
|
|
357
|
+
blue = mean ? +mean.split(" ")[0].substring(0, 3) : 0;
|
|
358
|
+
} else {
|
|
359
|
+
blue = 0;
|
|
360
|
+
}
|
|
361
|
+
const rgb = blue | green << 8 | red << 16;
|
|
362
|
+
const color = rgb.toString(16);
|
|
363
|
+
photo.color = color === "0" ? "000000" : color;
|
|
364
|
+
}
|
|
365
|
+
}
|
|
366
|
+
}).stream((error, stdout) => {
|
|
367
|
+
if (error) {
|
|
368
|
+
(0, import_utils2.logError)({
|
|
369
|
+
action,
|
|
370
|
+
category: eventCategory,
|
|
371
|
+
isInternal: true,
|
|
372
|
+
label: "image_save",
|
|
373
|
+
value: "gm_image_stream"
|
|
374
|
+
}, error, context).then(() => null);
|
|
375
|
+
} else {
|
|
376
|
+
let imageBuffer = Buffer.from("");
|
|
377
|
+
stdout.on("data", (data) => {
|
|
378
|
+
imageBuffer = Buffer.concat([imageBuffer, data]);
|
|
379
|
+
});
|
|
380
|
+
stdout.on("end", () => {
|
|
381
|
+
photo.fileSize = imageBuffer.length;
|
|
382
|
+
const imageObj = __spreadProps(__spreadValues({
|
|
383
|
+
ACL: "authenticated-read",
|
|
384
|
+
Body: imageBuffer,
|
|
385
|
+
Bucket: null,
|
|
386
|
+
ContentType: type
|
|
387
|
+
}, s3Options || {}), {
|
|
388
|
+
Key: getPathUserImages(sessionId, imageId, type, "images")
|
|
389
|
+
});
|
|
390
|
+
(0, import_s32.s3Put)(imageObj).then(() => {
|
|
391
|
+
const thmW = import_config.Config.get("image.thmSize");
|
|
392
|
+
const thmQ = import_config.Config.get("image.thmQuality");
|
|
393
|
+
(0, import_gm.default)(imageBuffer, "img").setFormat("jpeg").size((thumbError, resizeVal) => {
|
|
394
|
+
if (!thumbError) {
|
|
395
|
+
const { height, width } = resizeVal;
|
|
396
|
+
photo = __spreadProps(__spreadValues({}, (0, import_cloneDeep.default)(photo)), { height, width });
|
|
397
|
+
}
|
|
398
|
+
}).gravity("Center").resize(thmW, thmW, "^").extent(thmW, thmW).quality(thmQ).stream((streamError, thumbStdout) => {
|
|
399
|
+
if (streamError) {
|
|
400
|
+
(0, import_utils2.logError)({
|
|
401
|
+
action,
|
|
402
|
+
category: eventCategory,
|
|
403
|
+
label: "image_save",
|
|
404
|
+
value: "gm_thumbnail_steam"
|
|
405
|
+
}, streamError, context).catch((error2) => {
|
|
406
|
+
throw error2;
|
|
407
|
+
});
|
|
408
|
+
} else {
|
|
409
|
+
let thumbBuffer = Buffer.from("");
|
|
410
|
+
thumbStdout.on("data", (data) => {
|
|
411
|
+
thumbBuffer = Buffer.concat([thumbBuffer, data]);
|
|
412
|
+
});
|
|
413
|
+
thumbStdout.on("end", () => {
|
|
414
|
+
const thumbObj = __spreadProps(__spreadValues({
|
|
415
|
+
ACL: "authenticated-read",
|
|
416
|
+
Body: thumbBuffer,
|
|
417
|
+
Bucket: null,
|
|
418
|
+
ContentType: type
|
|
419
|
+
}, s3Options || {}), {
|
|
420
|
+
Key: getPathUserImages(sessionId, imageId, type, "thumbs")
|
|
421
|
+
});
|
|
422
|
+
(0, import_s32.s3Put)(thumbObj).then(() => {
|
|
423
|
+
resolve(photo);
|
|
424
|
+
}).catch((s3PutError) => (0, import_utils2.logError)({
|
|
425
|
+
action,
|
|
426
|
+
category: eventCategory,
|
|
427
|
+
label: "image_save",
|
|
428
|
+
value: "s3_put_image"
|
|
429
|
+
}, s3PutError, context).catch((error2) => {
|
|
430
|
+
throw error2;
|
|
431
|
+
}));
|
|
432
|
+
});
|
|
433
|
+
}
|
|
434
|
+
});
|
|
435
|
+
}).catch((s3Error) => (0, import_utils2.logError)({
|
|
436
|
+
action,
|
|
437
|
+
category: eventCategory,
|
|
438
|
+
isInternal: true,
|
|
439
|
+
label: "image_save",
|
|
440
|
+
value: "s3_image_save"
|
|
441
|
+
}, s3Error, context).then(() => null));
|
|
442
|
+
});
|
|
443
|
+
}
|
|
444
|
+
});
|
|
445
|
+
});
|
|
446
|
+
};
|
|
447
|
+
const addImage = (context, image, s3Options) => {
|
|
448
|
+
const action = "addImage";
|
|
449
|
+
const { database, session: { userId: sessionId } } = context;
|
|
450
|
+
const { imageId, description, buffer, fileType } = image;
|
|
451
|
+
const now = Date.now();
|
|
452
|
+
return resizeSaveImage(context, imageId, buffer, fileType, s3Options).then((resizedImage) => {
|
|
453
|
+
const insert = __spreadProps(__spreadValues({}, resizedImage), {
|
|
454
|
+
_key: imageId,
|
|
455
|
+
added: now,
|
|
456
|
+
description,
|
|
457
|
+
fileType,
|
|
458
|
+
modified: now,
|
|
459
|
+
userId: sessionId
|
|
460
|
+
});
|
|
461
|
+
const aqlQry = import_arangojs.aql`INSERT ${insert} IN images RETURN NEW`;
|
|
462
|
+
return database.query(aqlQry).then((cursor) => cursor.next()).then(import_utils2.defaultObject).catch((error) => (0, import_utils2.logError)({
|
|
463
|
+
action,
|
|
464
|
+
category: eventCategory,
|
|
465
|
+
isInternal: true,
|
|
466
|
+
label: "db_error"
|
|
467
|
+
}, error, context).then(() => null));
|
|
468
|
+
}).catch((error) => (0, import_utils2.logError)({
|
|
469
|
+
action,
|
|
470
|
+
category: eventCategory,
|
|
471
|
+
isInternal: true,
|
|
472
|
+
label: "image_resize"
|
|
473
|
+
}, error, context).then(() => null));
|
|
474
|
+
};
|
|
475
|
+
const addImageEdge = async (context, imageEdge) => {
|
|
476
|
+
const action = "addImageEdge";
|
|
477
|
+
const { database, session: { userId: sessionId } } = context;
|
|
478
|
+
const { imageId, itemId, itemType } = imageEdge;
|
|
479
|
+
const now = Date.now();
|
|
480
|
+
const edgeCollection = database.collection("hasImages");
|
|
481
|
+
const edgeId = (0, import_utils.createHash)(`hasImages-${imageId}-${itemId}-${sessionId}`);
|
|
482
|
+
const formatItemType = (0, import_utils.parseChar)(itemType).toLowerCase();
|
|
483
|
+
const formatItemId = (0, import_utils.parseId)(itemId);
|
|
484
|
+
let itemDocId;
|
|
485
|
+
const formatImgId = (0, import_utils.parseId)(imageId);
|
|
486
|
+
const fileDocId = `images/${formatImgId}`;
|
|
487
|
+
switch (formatItemType) {
|
|
488
|
+
case "groups":
|
|
489
|
+
itemDocId = `groups/${formatItemId}`;
|
|
490
|
+
break;
|
|
491
|
+
case "posts":
|
|
492
|
+
itemDocId = `posts/${formatItemId}`;
|
|
493
|
+
break;
|
|
494
|
+
case "users":
|
|
495
|
+
case "profile":
|
|
496
|
+
itemDocId = `users/${formatItemId}`;
|
|
497
|
+
break;
|
|
498
|
+
default:
|
|
499
|
+
itemDocId = "";
|
|
500
|
+
break;
|
|
501
|
+
}
|
|
502
|
+
const edge = {
|
|
503
|
+
_from: itemDocId,
|
|
504
|
+
_key: edgeId,
|
|
505
|
+
_to: fileDocId,
|
|
506
|
+
added: now,
|
|
507
|
+
type: itemType
|
|
508
|
+
};
|
|
509
|
+
if (!(0, import_isEmpty.default)(itemDocId)) {
|
|
510
|
+
return edgeCollection.save(edge, { returnNew: true }).then((fileEdge) => edgeCollection.document(fileEdge)).catch((error) => (0, import_utils2.logError)({
|
|
511
|
+
action,
|
|
512
|
+
category: eventCategory,
|
|
513
|
+
isInternal: true,
|
|
514
|
+
label: "db_error",
|
|
515
|
+
params: {
|
|
516
|
+
edge,
|
|
517
|
+
fileDocId,
|
|
518
|
+
imageId,
|
|
519
|
+
itemDocId,
|
|
520
|
+
itemId,
|
|
521
|
+
itemType
|
|
522
|
+
}
|
|
523
|
+
}, error, context).then(() => null));
|
|
524
|
+
}
|
|
525
|
+
return {};
|
|
526
|
+
};
|
|
527
|
+
const updateImage = async (context, image, s3Options) => {
|
|
528
|
+
const action = "updateImage";
|
|
529
|
+
const { database, session: { userId: sessionId } } = context;
|
|
530
|
+
const {
|
|
531
|
+
base64 = "",
|
|
532
|
+
buffer: imageBuffer,
|
|
533
|
+
description = "",
|
|
534
|
+
imageId,
|
|
535
|
+
itemId,
|
|
536
|
+
itemType,
|
|
537
|
+
fileType,
|
|
538
|
+
url = ""
|
|
539
|
+
} = image;
|
|
540
|
+
const now = Date.now();
|
|
541
|
+
const formatImageId = imageId || (0, import_utils.createHash)(`image-${sessionId}`);
|
|
542
|
+
const formatItemId = (0, import_utils.parseId)(itemId);
|
|
543
|
+
const formatItemType = (0, import_utils.parseChar)(itemType, 16).toLowerCase();
|
|
544
|
+
const customParams = {
|
|
545
|
+
description,
|
|
546
|
+
imageId: formatImageId,
|
|
547
|
+
userId: sessionId
|
|
548
|
+
};
|
|
549
|
+
if (!(0, import_isEmpty.default)(base64) || imageBuffer) {
|
|
550
|
+
let buffer = imageBuffer;
|
|
551
|
+
if (!(0, import_isEmpty.default)(base64)) {
|
|
552
|
+
const formatBase64 = base64.substr(base64.indexOf(",") + 1);
|
|
553
|
+
buffer = Buffer.from(formatBase64, "base64");
|
|
554
|
+
}
|
|
555
|
+
let updatedFileType = fileType;
|
|
556
|
+
if (!fileType) {
|
|
557
|
+
const fileMime = await import_file_type.default.fromBuffer(buffer);
|
|
558
|
+
const { mime } = fileMime;
|
|
559
|
+
updatedFileType = mime;
|
|
560
|
+
}
|
|
561
|
+
const imgParams = __spreadProps(__spreadValues({}, customParams), {
|
|
562
|
+
buffer,
|
|
563
|
+
fileType: updatedFileType
|
|
564
|
+
});
|
|
565
|
+
return addImage(context, imgParams, s3Options).then((image2) => {
|
|
566
|
+
if (formatItemId && formatItemType) {
|
|
567
|
+
const imageEdge = {
|
|
568
|
+
imageId: formatImageId,
|
|
569
|
+
itemId: formatItemId,
|
|
570
|
+
itemType: formatItemType
|
|
571
|
+
};
|
|
572
|
+
return addImageEdge(context, imageEdge).then(() => image2);
|
|
573
|
+
}
|
|
574
|
+
return image2;
|
|
575
|
+
}).catch((error) => (0, import_utils2.logError)({
|
|
576
|
+
action,
|
|
577
|
+
category: eventCategory,
|
|
578
|
+
label: "image_save_error"
|
|
579
|
+
}, error, context).then(() => null));
|
|
580
|
+
} else if (url !== "") {
|
|
581
|
+
let contentType;
|
|
582
|
+
return (0, import_rip_hunter.get)(url).then((res) => {
|
|
583
|
+
if (res.status !== 200) {
|
|
584
|
+
return (0, import_utils2.logException)({
|
|
585
|
+
action,
|
|
586
|
+
category: eventCategory,
|
|
587
|
+
label: "fetch_image_url",
|
|
588
|
+
value: res.statusText
|
|
589
|
+
}, context).then(() => null);
|
|
590
|
+
}
|
|
591
|
+
contentType = res.headers.get("content-type");
|
|
592
|
+
return res;
|
|
593
|
+
}).then((res) => res.buffer()).then((buffer) => {
|
|
594
|
+
const imgParams = __spreadProps(__spreadValues({}, customParams), {
|
|
595
|
+
buffer,
|
|
596
|
+
fileType: contentType
|
|
597
|
+
});
|
|
598
|
+
return addImage(context, imgParams, s3Options).then((image2) => {
|
|
599
|
+
if (formatItemId && formatItemType) {
|
|
600
|
+
const imageEdge = { imageId: formatImageId, itemId: formatItemId, itemType: formatItemType };
|
|
601
|
+
return addImageEdge(context, imageEdge).then(() => image2);
|
|
602
|
+
}
|
|
603
|
+
return image2;
|
|
604
|
+
});
|
|
605
|
+
}).catch((error) => (0, import_utils2.logError)({
|
|
606
|
+
action,
|
|
607
|
+
category: eventCategory,
|
|
608
|
+
label: "fetch_error"
|
|
609
|
+
}, error, context).then(() => null));
|
|
610
|
+
} else if (imageId !== "") {
|
|
611
|
+
const update = {
|
|
612
|
+
description,
|
|
613
|
+
modified: now
|
|
614
|
+
};
|
|
615
|
+
const aqlQry = import_arangojs.aql`UPDATE {_key: ${formatImageId}} WITH ${update} IN images RETURN NEW`;
|
|
616
|
+
return database.query(aqlQry).then((cursor) => cursor.next()).catch((error) => (0, import_utils2.logError)({
|
|
617
|
+
action,
|
|
618
|
+
category: eventCategory,
|
|
619
|
+
label: "db_error",
|
|
620
|
+
params: {
|
|
621
|
+
aqlQry,
|
|
622
|
+
formatImageId,
|
|
623
|
+
update
|
|
624
|
+
}
|
|
625
|
+
}, error, context).then(() => null));
|
|
626
|
+
}
|
|
627
|
+
return null;
|
|
628
|
+
};
|
|
629
|
+
const deleteImage = async (context, imageId) => {
|
|
630
|
+
const action = "delete";
|
|
631
|
+
const { database, session: { userId: sessionId } } = context;
|
|
632
|
+
const formatImageId = (0, import_utils.parseId)(imageId);
|
|
633
|
+
const removeEdgeQuery = import_arangojs.aql`FOR hi IN hasImages
|
|
634
|
+
FILTER hi._from == ${formatImageId}
|
|
635
|
+
REMOVE hi IN hasImages
|
|
636
|
+
RETURN OLD`;
|
|
637
|
+
await database.query(removeEdgeQuery);
|
|
638
|
+
const aqlQuery = import_arangojs.aql`FOR i IN images
|
|
639
|
+
FILTER i._key == ${formatImageId} && i.userId == ${sessionId}
|
|
640
|
+
REMOVE i IN images
|
|
641
|
+
RETURN OLD`;
|
|
642
|
+
const image = await database.query(aqlQuery).then((cursor) => cursor.next()).catch((error) => (0, import_utils2.logError)({
|
|
643
|
+
action,
|
|
644
|
+
category: eventCategory,
|
|
645
|
+
label: "db_error"
|
|
646
|
+
}, error, context).then(() => null));
|
|
647
|
+
if (!(0, import_isEmpty.default)(image)) {
|
|
648
|
+
const { _key: imageKey } = image;
|
|
649
|
+
const params = {
|
|
650
|
+
Bucket: null,
|
|
651
|
+
Delete: {
|
|
652
|
+
Objects: [
|
|
653
|
+
{ Key: `users/${sessionId}/images/${imageKey}.jpg` },
|
|
654
|
+
{ Key: `users/${sessionId}/thumbs/${imageKey}.jpg` }
|
|
655
|
+
],
|
|
656
|
+
Quiet: true
|
|
657
|
+
}
|
|
658
|
+
};
|
|
659
|
+
return (0, import_s32.s3DeleteList)(params).then(() => image);
|
|
660
|
+
}
|
|
661
|
+
return {};
|
|
662
|
+
};
|
|
663
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
664
|
+
0 && (module.exports = {
|
|
665
|
+
addImage,
|
|
666
|
+
addImageEdge,
|
|
667
|
+
deleteImage,
|
|
668
|
+
getAppImageUrl,
|
|
669
|
+
getImage,
|
|
670
|
+
getImageCountByItem,
|
|
671
|
+
getImageOptional,
|
|
672
|
+
getImagesByGroup,
|
|
673
|
+
getImagesByItem,
|
|
674
|
+
getImagesByReactions,
|
|
675
|
+
getImagesByUser,
|
|
676
|
+
getPathUserImages,
|
|
677
|
+
getUserImageUrl,
|
|
678
|
+
parseImageOptions,
|
|
679
|
+
resizeSaveImage,
|
|
680
|
+
updateImage
|
|
681
|
+
});
|
|
682
|
+
//# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsiLi4vLi4vc3JjL2FjdGlvbnMvaW1hZ2VzLnRzIl0sCiAgInNvdXJjZXNDb250ZW50IjogWyIvKipcbiAqIENvcHlyaWdodCAoYykgMjAxOS1QcmVzZW50LCBOaXRyb2dlbiBMYWJzLCBJbmMuXG4gKiBDb3B5cmlnaHRzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgTGljZW5zZS4gU2VlIHRoZSBhY2NvbXBhbnlpbmcgTElDRU5TRSBmaWxlIGZvciB0ZXJtcy5cbiAqL1xuaW1wb3J0IHtnZXQgYXMgaHR0cEdldH0gZnJvbSAnQG5sYWJzL3JpcC1odW50ZXInO1xuaW1wb3J0IHtjcmVhdGVIYXNoLCBwYXJzZUFyYW5nb0lkLCBwYXJzZUNoYXIsIHBhcnNlSWQsIHBhcnNlTnVtfSBmcm9tICdAbmxhYnMvdXRpbHMnO1xuaW1wb3J0IHthcWx9IGZyb20gJ2FyYW5nb2pzJztcbmltcG9ydCB7QXFsUXVlcnl9IGZyb20gJ2FyYW5nb2pzL2FxbCc7XG5pbXBvcnQge0VkZ2VDb2xsZWN0aW9ufSBmcm9tICdhcmFuZ29qcy9jb2xsZWN0aW9uJztcbmltcG9ydCB7QXJyYXlDdXJzb3J9IGZyb20gJ2FyYW5nb2pzL2N1cnNvcic7XG5pbXBvcnQge0RlbGV0ZU9iamVjdHNSZXF1ZXN0LCBQdXRPYmplY3RSZXF1ZXN0fSBmcm9tICdhd3Mtc2RrL2NsaWVudHMvczMnO1xuaW1wb3J0IEZpbGVUeXBlLCB7RmlsZVR5cGVSZXN1bHR9IGZyb20gJ2ZpbGUtdHlwZSc7XG5pbXBvcnQgZ20gZnJvbSAnZ20nO1xuaW1wb3J0IGNsb25lRGVlcCBmcm9tICdsb2Rhc2gvY2xvbmVEZWVwJztcbmltcG9ydCBpc0VtcHR5IGZyb20gJ2xvZGFzaC9pc0VtcHR5JztcbmltcG9ydCB7RGF0ZVRpbWV9IGZyb20gJ2x1eG9uJztcblxuaW1wb3J0IHtDb25maWd9IGZyb20gJy4uL2NvbmZpZyc7XG5pbXBvcnQge1xuICBBcGlDb250ZXh0LFxuICBBcmFuZ29EQkxpbWl0LFxuICBHcm91cFR5cGUsXG4gIEdyb3VwVXNlcixcbiAgSW1hZ2VFZGdlVHlwZSxcbiAgSW1hZ2VJZGVudGlmeVR5cGUsXG4gIEltYWdlT3B0aW9ucyxcbiAgSW1hZ2VUeXBlLFxuICBJbWFnZVVybERhdGEsXG4gIFF1ZXJ5RmlsdGVyXG59IGZyb20gJy4uL3R5cGVzJztcbmltcG9ydCB7ZGVmYXVsdE9iamVjdCwgZ2V0TGltaXQsIGxvZ0Vycm9yLCBsb2dFeGNlcHRpb24sIGxvd2VyQ2FzZUtleXMsIHNlbGVjdFJlYWN0aW9uQ291bnRCeVR5cGV9IGZyb20gJy4uL3V0aWxzJztcbmltcG9ydCB7Z2V0R3JvdXBEZXRhaWxzLCBpc0dyb3VwZWR9IGZyb20gJy4vZ3JvdXBzJztcbmltcG9ydCB7czNEZWxldGVMaXN0LCBzM0dldFNpZ25lZFVybCwgczNQdXR9IGZyb20gJy4vczMnO1xuXG5jb25zdCBldmVudENhdGVnb3J5OiBzdHJpbmcgPSAnaW1hZ2VzJztcblxuZXhwb3J0IGNvbnN0IHBhcnNlSW1hZ2VPcHRpb25zID0gKG9wdGlvbnM6IEltYWdlT3B0aW9ucyA9IHt9KSA9PiB7XG4gIGNvbnN0IHtcbiAgICBmcm9tID0gMCxcbiAgICB0byA9IDMwLFxuICAgIHR5cGUgPSAnZGVmYXVsdCdcbiAgfSA9IG9wdGlvbnM7XG5cbiAgcmV0dXJuIHtcbiAgICBsaW1pdDogZ2V0TGltaXQoZnJvbSwgdG8pLFxuICAgIHR5cGU6IHBhcnNlQ2hhcih0eXBlLCAzMilcbiAgfTtcbn07XG5cbmV4cG9ydCBjb25zdCBnZXRJbWFnZU9wdGlvbmFsID0gKGZpZWxkczogc3RyaW5nW10gPSBbXSkgPT5cbiAgZmllbGRzLnJlZHVjZSgoc2VsZWN0czogYW55LCBmaWVsZDogc3RyaW5nKSA9PiB7XG4gICAgaWYoZmllbGQuaW5jbHVkZXMoJ0NvdW50JykpIHtcbiAgICAgIHJldHVybiBzZWxlY3RSZWFjdGlvbkNvdW50QnlUeXBlKCdpbWFnZXMnLCAnaScsIGZpZWxkLCBzZWxlY3RzKTtcbiAgICB9XG5cbiAgICBzd2l0Y2goZmllbGQpIHtcbiAgICAgIGNhc2UgJ3JlYWN0aW9ucyc6IHtcbiAgICAgICAgc2VsZWN0cy5xdWVyaWVzLnB1c2goYExFVCByZWFjdGlvbnMgPSAoXG4gICAgICAgICAgRk9SIGltYWdlLCByIElOIElOQk9VTkQgaS5faWQgcmVhY3Rpb25zXG4gICAgICAgICAgQ09MTEVDVCByZWFjdGlvbk5hbWUgPSByLnZhbHVlIElOVE8gcmVhY3Rpb25JdGVtc1xuICAgICAgICAgIFJFVFVSTiB7bmFtZTogcmVhY3Rpb25OYW1lLCBjb3VudDogTEVOR1RIKHJlYWN0aW9uSXRlbXNbKl0uci52YWx1ZSl9XG4gICAgICAgIClgKTtcbiAgICAgICAgc2VsZWN0cy5vYmplY3RzLnB1c2goJ3JlYWN0aW9uczpyZWFjdGlvbnMnKTtcbiAgICAgICAgcmV0dXJuIHNlbGVjdHM7XG4gICAgICB9XG4gICAgICBjYXNlICd0YWdzJzoge1xuICAgICAgICBzZWxlY3RzLnF1ZXJpZXMucHVzaChgTEVUIHRhZ3MgPSAoXG4gICAgICAgICAgRk9SIHQsIHBsIElOIElOQk9VTkQgaS5faWQgaXNUYWdnZWRcbiAgICAgICAgICBSRVRVUk4gdFxuICAgICAgICApYCk7XG4gICAgICAgIHNlbGVjdHMub2JqZWN0cy5wdXNoKCd0YWdzOnRhZ3MnKTtcbiAgICAgICAgcmV0dXJuIHNlbGVjdHM7XG4gICAgICB9XG4gICAgICBjYXNlICd1c2VyJzoge1xuICAgICAgICBzZWxlY3RzLnF1ZXJpZXMucHVzaChgTEVUIHVzZXIgPSBGSVJTVChcbiAgICAgICAgICBGT1IgdSBJTiB1c2Vyc1xuICAgICAgICAgIEZJTFRFUiBpLnVzZXJJZCA9PSB1Ll9rZXlcbiAgICAgICAgICBMSU1JVCAxXG4gICAgICAgICAgUkVUVVJOIHVcbiAgICAgICAgKWApO1xuICAgICAgICBzZWxlY3RzLm9iamVjdHMucHVzaCgndXNlcjp1c2VyJyk7XG4gICAgICAgIHJldHVybiBzZWxlY3RzO1xuICAgICAgfVxuICAgICAgZGVmYXVsdDoge1xuICAgICAgICByZXR1cm4gc2VsZWN0cztcbiAgICAgIH1cbiAgICB9XG4gIH0sIHtvYmplY3RzOiBbXSwgcXVlcmllczogW119KTtcblxuZXhwb3J0IGNvbnN0IGdldEltYWdlc0J5VXNlciA9IChcbiAgY29udGV4dDogQXBpQ29udGV4dCxcbiAgdXNlcklkOiBzdHJpbmcsXG4gIGZyb206IG51bWJlcixcbiAgdG86IG51bWJlclxuKTogUHJvbWlzZTxJbWFnZVR5cGVbXT4gPT4ge1xuICBjb25zdCBhY3Rpb246IHN0cmluZyA9ICdnZXRJbWFnZXNCeVVzZXInO1xuICBjb25zdCB7ZGF0YWJhc2V9ID0gY29udGV4dDtcbiAgY29uc3QgZm9ybWF0VXNlcklkOiBzdHJpbmcgPSBwYXJzZUlkKHVzZXJJZCk7XG4gIGNvbnN0IGxpbWl0OiBBcmFuZ29EQkxpbWl0ID0gZ2V0TGltaXQoZnJvbSwgdG8pO1xuICBjb25zdCBhcWxRcnk6IHN0cmluZyA9IGBGT1IgaSBJTiBpbWFnZXNcbiAgICAgIEZJTFRFUiBpLnVzZXJJZCA9PSBcIiR7Zm9ybWF0VXNlcklkfVwiXG4gICAgICBMRVQgdXNlciA9IEZJUlNUKFxuICAgICAgICBGT1IgdSBJTiB1c2Vyc1xuICAgICAgICBGSUxURVIgdS5fa2V5ID09IGkudXNlcklkXG4gICAgICAgIExJTUlUIDFcbiAgICAgICAgUkVUVVJOIHVcbiAgICAgIClcbiAgICAgICR7bGltaXQuYXFsfVxuICAgICAgU09SVCBpLmFkZGVkXG4gICAgICBSRVRVUk4gTUVSR0UoaSwge3VzZXI6dXNlcn0pYDtcblxuICByZXR1cm4gZGF0YWJhc2UucXVlcnkoYXFsUXJ5KVxuICAgIC50aGVuKChjdXJzb3I6IEFycmF5Q3Vyc29yKSA9PiBjdXJzb3IuYWxsKCkpXG4gICAgLmNhdGNoKChlcnJvcjogRXJyb3IpID0+IGxvZ0Vycm9yKHtcbiAgICAgIGFjdGlvbixcbiAgICAgIGNhdGVnb3J5OiBldmVudENhdGVnb3J5LFxuICAgICAgbGFiZWw6ICdkYl9lcnJvcidcbiAgICB9LCBlcnJvciwgY29udGV4dCkudGhlbigoKSA9PiBudWxsKSk7XG59O1xuXG5leHBvcnQgY29uc3QgZ2V0SW1hZ2VDb3VudEJ5SXRlbSA9IChjb250ZXh0OiBBcGlDb250ZXh0LCBpdGVtSWQ6IHN0cmluZyk6IFByb21pc2U8bnVtYmVyPiA9PiB7XG4gIGNvbnN0IGFjdGlvbjogc3RyaW5nID0gJ2dldEltYWdlQ291bnRCeUl0ZW0nO1xuICBjb25zdCB7ZGF0YWJhc2V9ID0gY29udGV4dDtcbiAgY29uc3QgZm9ybWF0SXRlbUlkOiBzdHJpbmcgPSBwYXJzZUFyYW5nb0lkKGl0ZW1JZCk7XG4gIGNvbnN0IGFxbFFyeTogQXFsUXVlcnkgPSBhcWxgRk9SIGkgSU4gaGFzSW1hZ2VzXG4gICAgICBGSUxURVIgaS5fdG8gPT0gJHtmb3JtYXRJdGVtSWR9XG4gICAgICBSRVRVUk4ge2NvdW50OiBDT1VOVChpKX1gO1xuXG4gIHJldHVybiBkYXRhYmFzZS5xdWVyeShhcWxRcnkpXG4gICAgLnRoZW4oKGN1cnNvcjogQXJyYXlDdXJzb3IpID0+IGN1cnNvci5uZXh0KCkpXG4gICAgLnRoZW4oKHtjb3VudH0gPSB7Y291bnQ6IDB9KSA9PiBjb3VudClcbiAgICAuY2F0Y2goKGVycm9yOiBFcnJvcikgPT4gbG9nRXJyb3Ioe1xuICAgICAgYWN0aW9uLFxuICAgICAgY2F0ZWdvcnk6IGV2ZW50Q2F0ZWdvcnksXG4gICAgICBsYWJlbDogJ2RiX2Vycm9yJ1xuICAgIH0sIGVycm9yLCBjb250ZXh0KS50aGVuKCgpID0+IDApKTtcbn07XG5cbmV4cG9ydCBjb25zdCBnZXRJbWFnZXNCeUl0ZW0gPSBhc3luYyAoXG4gIGNvbnRleHQ6IEFwaUNvbnRleHQsXG4gIGl0ZW1JZDogc3RyaW5nLFxuICBvcHRpb25zOiBJbWFnZU9wdGlvbnMgPSB7fVxuKTogUHJvbWlzZTxJbWFnZVR5cGVbXT4gPT4ge1xuICBjb25zdCBhY3Rpb246IHN0cmluZyA9ICdnZXRJbWFnZXNCeUl0ZW0nO1xuICBjb25zdCB7ZGF0YWJhc2UsIGZpZWxkcyA9IFtdfSA9IGNvbnRleHQ7XG4gIGNvbnN0IGZvcm1hdEl0ZW1JZDogc3RyaW5nID0gcGFyc2VBcmFuZ29JZChpdGVtSWQpO1xuICBjb25zdCB7bGltaXR9ID0gcGFyc2VJbWFnZU9wdGlvbnMob3B0aW9ucyk7XG4gIGNvbnN0IHtvYmplY3RzOiBzZWxlY3RPYmplY3RzLCBxdWVyaWVzOiBzZWxlY3RRdWVyaWVzfSA9IGdldEltYWdlT3B0aW9uYWwoZmllbGRzKTtcbiAgY29uc3QgYXFsUXJ5OiBzdHJpbmcgPSBgRk9SIGksIGwgSU4gMS4uMSBPVVRCT1VORCBcIiR7Zm9ybWF0SXRlbUlkfVwiIGhhc0ltYWdlc1xuICAgIEZJTFRFUiBOT1QgSVNfTlVMTChpKVxuICAgICR7c2VsZWN0UXVlcmllcy5qb2luKCdcXG4nKX1cbiAgICBTT1JUIGkuYWRkZWRcbiAgICAke2xpbWl0LmFxbH1cbiAgICBSRVRVUk4gTUVSR0UoaSwgeyR7c2VsZWN0T2JqZWN0cy5qb2luKCcsICcpfX0pYDtcblxuICByZXR1cm4gZGF0YWJhc2UucXVlcnkoYXFsUXJ5KVxuICAgIC50aGVuKChjdXJzb3I6IEFycmF5Q3Vyc29yKSA9PiBjdXJzb3IuYWxsKCkpXG4gICAgLmNhdGNoKChlcnJvcjogRXJyb3IpID0+IGxvZ0Vycm9yKHtcbiAgICAgIGFjdGlvbixcbiAgICAgIGNhdGVnb3J5OiBldmVudENhdGVnb3J5LFxuICAgICAgbGFiZWw6ICdkYl9lcnJvcidcbiAgICB9LCBlcnJvciwgY29udGV4dCkudGhlbigoKSA9PiBudWxsKSk7XG59O1xuXG5leHBvcnQgY29uc3QgZ2V0SW1hZ2VzQnlHcm91cCA9IChjb250ZXh0OiBBcGlDb250ZXh0LCBwYXJhbXMpOiBQcm9taXNlPEltYWdlVHlwZVtdPiA9PiB7XG4gIGNvbnN0IGFjdGlvbjogc3RyaW5nID0gJ2dldEltYWdlc0J5R3JvdXAnO1xuICBjb25zdCB7ZGF0YWJhc2UsIHNlc3Npb246IHt1c2VySWQ6IHNlc3Npb25JZH19ID0gY29udGV4dDtcbiAgY29uc3Qge2ZpbHRlcnMgPSBbXSwgZ3JvdXBJZCwgZnJvbSwgdG99ID0gcGFyYW1zO1xuICBjb25zdCBmb3JtYXRHcm91cElkOiBzdHJpbmcgPSBwYXJzZUlkKGdyb3VwSWQpO1xuICBjb25zdCBsaW1pdCA9IGdldExpbWl0KGZyb20sIHRvKTtcblxuICBmaWx0ZXJzXG4gICAgLm1hcCgoZmlsdGVyOiBRdWVyeUZpbHRlcikgPT4ge1xuICAgICAgY29uc3Qge2NvbmRpdGlvbmFsLCBuYW1lLCB2YWx1ZX0gPSBmaWx0ZXI7XG4gICAgICBsZXQgZm9ybWF0Q29uZDogc3RyaW5nID0gY29uZGl0aW9uYWw7XG5cbiAgICAgIGlmKGNvbmRpdGlvbmFsICE9PSAnPj0nICYmIGNvbmRpdGlvbmFsICE9PSAnPD0nICYmIGNvbmRpdGlvbmFsICE9PSAnPicgJiYgY29uZGl0aW9uYWwgIT09ICc8Jykge1xuICAgICAgICBmb3JtYXRDb25kID0gJz09JztcbiAgICAgIH1cblxuICAgICAgc3dpdGNoKG5hbWUpIHtcbiAgICAgICAgY2FzZSAnYWRkZWQnOlxuICAgICAgICAgIHJldHVybiBgcC5hZGRlZCAke2Zvcm1hdENvbmR9ICR7cGFyc2VOdW0odmFsdWUpfWA7XG4gICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgcmV0dXJuICcnO1xuICAgICAgfVxuICAgIH0pO1xuXG4gIHJldHVybiBnZXRHcm91cERldGFpbHMoY29udGV4dCwgZm9ybWF0R3JvdXBJZClcbiAgICAudGhlbigoZ3JvdXA6IEdyb3VwVHlwZSkgPT4ge1xuICAgICAgaWYoZ3JvdXAucHJpdmFjeSA9PT0gJ3B1YmxpYycpIHtcbiAgICAgICAgZmlsdGVycy5wdXNoKGBwLmdyb3VwSWQgPT0gXCIke2dyb3VwSWR9XCJgKTtcbiAgICAgICAgY29uc3QgZmlsdGVyU3RyID0gZmlsdGVycy5qb2luKCcgJiYgJyk7XG4gICAgICAgIGNvbnN0IGFxbFFyeTogc3RyaW5nID0gYEZPUiBpIElOXG4gICAgICAgICAgRkxBVFRFTihcbiAgICAgICAgICAgIEZPUiBwIElOIHBvc3RzXG4gICAgICAgICAgICBGSUxURVIgJHtmaWx0ZXJTdHJ9XG4gICAgICAgICAgICBMRVQgaW1hZ2VzID0gKFxuICAgICAgICAgICAgICBGT1IgaSwgZSBJTiBJTkJPVU5EIHAuX2lkIGhhc0ltYWdlc1xuICAgICAgICAgICAgICBSRVRVUk4gaVxuICAgICAgICAgICAgKVxuICAgICAgICAgICAgU09SVCBwLmFkZGVkIERFU0NcbiAgICAgICAgICAgIFJFVFVSTiBpbWFnZXNcbiAgICAgICAgICApXG4gICAgICAgICAgU09SVCBpLmFkZGVkIERFU0NcbiAgICAgICAgICAke2xpbWl0LmFxbH1cbiAgICAgICAgICBSRVRVUk4gaWA7XG5cbiAgICAgICAgcmV0dXJuIGRhdGFiYXNlLnF1ZXJ5KGFxbFFyeSlcbiAgICAgICAgICAudGhlbigoY3Vyc29yOiBBcnJheUN1cnNvcikgPT4gY3Vyc29yLmFsbCgpKVxuICAgICAgICAgIC5jYXRjaCgoZXJyb3I6IEVycm9yKSA9PiBsb2dFcnJvcih7XG4gICAgICAgICAgICBhY3Rpb24sXG4gICAgICAgICAgICBjYXRlZ29yeTogZXZlbnRDYXRlZ29yeSxcbiAgICAgICAgICAgIGxhYmVsOiAnZGJfZXJyb3InXG4gICAgICAgICAgfSwgZXJyb3IsIGNvbnRleHQpLnRoZW4oKCkgPT4gbnVsbCkpO1xuICAgICAgfVxuICAgICAgcmV0dXJuIGlzR3JvdXBlZChkYXRhYmFzZSwgc2Vzc2lvbklkLCBncm91cElkKVxuICAgICAgICAudGhlbigoZ3JvdXBlZDogR3JvdXBVc2VyKSA9PiB7XG4gICAgICAgICAgaWYoZ3JvdXBlZC5pc1ZhbGlkKSB7XG4gICAgICAgICAgICBmaWx0ZXJzLnB1c2goYHAuZ3JvdXBJZCA9PSBcIiR7Z3JvdXBlZC5ncm91cElkfVwiYCk7XG4gICAgICAgICAgICBjb25zdCBmaWx0ZXJMaXN0OiBzdHJpbmcgPSBmaWx0ZXJzLmpvaW4oJyAmJiAnKTtcbiAgICAgICAgICAgIGNvbnN0IGFxbFFyeTogc3RyaW5nID0gYEZPUiBwIElOIHBvc3RcbiAgICAgICAgICAgICAgICBGSUxURVIgJHtmaWx0ZXJMaXN0fVxuICAgICAgICAgICAgICAgIEZPUiBmIElOIHAuZmlsZXNcbiAgICAgICAgICAgICAgICBGSUxURVIgZi50eXBlID09IFwiaW1hZ2UvanBlZ1wiIHx8IGYudHlwZSA9PSBcImltYWdlL3BuZ1wiXG4gICAgICAgICAgICAgICAgJHtsaW1pdC5hcWx9XG4gICAgICAgICAgICAgICAgU09SVCBwLmFkZGVkIERFU0NcbiAgICAgICAgICAgICAgICBSRVRVUk4gZmA7XG5cbiAgICAgICAgICAgIHJldHVybiBkYXRhYmFzZS5xdWVyeShhcWxRcnkpXG4gICAgICAgICAgICAgIC50aGVuKChjdXJzb3I6IEFycmF5Q3Vyc29yKSA9PiBjdXJzb3IuYWxsKCkpXG4gICAgICAgICAgICAgIC5jYXRjaCgoZXJyb3I6IEVycm9yKSA9PiBsb2dFcnJvcih7XG4gICAgICAgICAgICAgICAgYWN0aW9uLFxuICAgICAgICAgICAgICAgIGNhdGVnb3J5OiBldmVudENhdGVnb3J5LFxuICAgICAgICAgICAgICAgIGxhYmVsOiAnZGJfZXJyb3InXG4gICAgICAgICAgICAgIH0sIGVycm9yLCBjb250ZXh0KS50aGVuKCgpID0+IG51bGwpKTtcbiAgICAgICAgICB9XG4gICAgICAgICAgcmV0dXJuIFtdO1xuICAgICAgICB9KTtcbiAgICB9KTtcbn07XG5cbmV4cG9ydCBjb25zdCBnZXRJbWFnZXNCeVJlYWN0aW9ucyA9IChcbiAgY29udGV4dDogQXBpQ29udGV4dCxcbiAgcmVhY3Rpb25zOiBzdHJpbmdbXSA9IFtdLFxuICBvcHRpb25zPzogSW1hZ2VPcHRpb25zXG4pOiBQcm9taXNlPEltYWdlVHlwZVtdPiA9PiB7XG4gIGNvbnN0IGFjdGlvbjogc3RyaW5nID0gJ2dldFVzZXJzQnlJbWFnZSc7XG4gIGNvbnN0IHtkYXRhYmFzZSwgZmllbGRzID0gW10sIHNlc3Npb246IHt1c2VySWQ6IHNlc3Npb25JZH19ID0gY29udGV4dDtcbiAgY29uc3Qge2xpbWl0fSA9IHBhcnNlSW1hZ2VPcHRpb25zKG9wdGlvbnMpO1xuICBjb25zdCB7b2JqZWN0czogc2VsZWN0T2JqZWN0cywgcXVlcmllczogc2VsZWN0UXVlcmllc30gPSBnZXRJbWFnZU9wdGlvbmFsKGZpZWxkcyk7XG5cbiAgY29uc3QgZm9ybWF0U2Vzc2lvbklkOiBzdHJpbmcgPSBgdXNlcnMvJHtzZXNzaW9uSWR9YDtcbiAgY29uc3QgZm9ybWF0UmVhY3Rpb25zOiBzdHJpbmdbXSA9IHJlYWN0aW9ucy5tYXAoKHJlYWN0aW9uTmFtZSkgPT4gcGFyc2VDaGFyKHJlYWN0aW9uTmFtZSwgMzIpKTtcbiAgY29uc3QgZmlsdGVyQnk6IHN0cmluZ1tdID0gW1xuICAgICdyLnR5cGUgPT0gXCJpbWFnZXNcIicsXG4gICAgYFBPU0lUSU9OKCR7SlNPTi5zdHJpbmdpZnkoZm9ybWF0UmVhY3Rpb25zKX0sIExPV0VSKHIubmFtZSkpYF07XG5cbiAgLy8gR2V0IGRhdGEgZnJvbSBkYXRhYmFzZVxuICBjb25zdCBhcWxRcnk6IHN0cmluZyA9IGBGT1IgaSwgciBJTiBPVVRCT1VORCBcIiR7Zm9ybWF0U2Vzc2lvbklkfVwiIGhhc1JlYWN0aW9uc1xuICAgIE9QVElPTlMge3ZlcnRleENvbGxlY3Rpb25zOiBcImltYWdlc1wifVxuICAgICR7c2VsZWN0UXVlcmllcy5qb2luKCdcXG4nKX1cbiAgICBGSUxURVIgJHtmaWx0ZXJCeS5qb2luKCcgJiYgJyl9XG4gICAgJHtsaW1pdC5hcWx9XG4gICAgUkVUVVJOIE1FUkdFKGksIHske3NlbGVjdE9iamVjdHMuam9pbignLCAnKX19KWA7XG5cbiAgcmV0dXJuIGRhdGFiYXNlLnF1ZXJ5KGFxbFFyeSlcbiAgICAudGhlbigoY3Vyc29yOiBBcnJheUN1cnNvcikgPT4gY3Vyc29yLmFsbCgpKVxuICAgIC5jYXRjaCgoZXJyb3I6IEVycm9yKSA9PiBsb2dFcnJvcih7XG4gICAgICBhY3Rpb24sXG4gICAgICBjYXRlZ29yeTogZXZlbnRDYXRlZ29yeSxcbiAgICAgIGxhYmVsOiAnZGJfZXJyb3InXG4gICAgfSwgZXJyb3IsIGNvbnRleHQpLnRoZW4oKCkgPT4gW10pKTtcbn07XG5cbmV4cG9ydCBjb25zdCBnZXRJbWFnZSA9IChjb250ZXh0OiBBcGlDb250ZXh0LCBpZDogc3RyaW5nKTogUHJvbWlzZTxJbWFnZVR5cGU+ID0+IHtcbiAgY29uc3QgYWN0aW9uOiBzdHJpbmcgPSAnZ2V0SXRlbSc7XG4gIGNvbnN0IHtkYXRhYmFzZX0gPSBjb250ZXh0O1xuICBjb25zdCBmb3JtYXRJZDogc3RyaW5nID0gcGFyc2VJZChpZCk7XG4gIGNvbnN0IGFxbFFyeTogQXFsUXVlcnkgPSBhcWxgRk9SIGkgSU4gaW1hZ2VzXG4gICAgRklMVEVSIGkuX2tleT09JHtmb3JtYXRJZH1cbiAgICBMSU1JVCAxXG4gICAgUkVUVVJOIGlgO1xuXG4gIHJldHVybiBkYXRhYmFzZS5xdWVyeShhcWxRcnkpXG4gICAgLnRoZW4oKGN1cnNvcjogQXJyYXlDdXJzb3IpID0+IGN1cnNvci5uZXh0KCkpXG4gICAgLnRoZW4oKGltYWdlOiBJbWFnZVR5cGUgPSB7fSkgPT4gaW1hZ2UpXG4gICAgLmNhdGNoKChlcnJvcjogRXJyb3IpID0+IGxvZ0Vycm9yKHtcbiAgICAgIGFjdGlvbixcbiAgICAgIGNhdGVnb3J5OiBldmVudENhdGVnb3J5LFxuICAgICAgbGFiZWw6ICdkYl9lcnJvcidcbiAgICB9LCBlcnJvciwgY29udGV4dCkudGhlbigoKSA9PiBudWxsKSk7XG59O1xuXG5leHBvcnQgY29uc3QgZ2V0UGF0aFVzZXJJbWFnZXMgPSAodXNlcklkOiBzdHJpbmcsIGltYWdlSWQ6IHN0cmluZywgdHlwZTogc3RyaW5nLCBkaXI6IHN0cmluZyA9ICdpbWFnZXMnKTogc3RyaW5nID0+IHtcbiAgbGV0IGZpbGVuYW1lOiBzdHJpbmcgPSBpbWFnZUlkO1xuXG4gIHN3aXRjaCh0eXBlKSB7XG4gICAgY2FzZSAnaW1hZ2UvcG5nJzpcbiAgICAgIGZpbGVuYW1lID0gYCR7aW1hZ2VJZH0ucG5nYDtcbiAgICAgIGJyZWFrO1xuICAgIGRlZmF1bHQ6XG4gICAgICBmaWxlbmFtZSA9IGAke2ltYWdlSWR9LmpwZ2A7XG4gICAgICBicmVhaztcbiAgfVxuXG4gIHJldHVybiBgdXNlcnMvJHt1c2VySWR9LyR7ZGlyfS8ke2ZpbGVuYW1lfWA7XG59O1xuXG5leHBvcnQgY29uc3QgZ2V0QXBwSW1hZ2VVcmwgPSAoZGF0YTogSW1hZ2VVcmxEYXRhKTogc3RyaW5nID0+IHtcbiAgY29uc3Qge2ltYWdlSWQsIGRpcmVjdG9yeSA9ICdpbWFnZXMnLCBpbWFnZVR5cGUgPSAncHJvZmlsZScsIGlzVGh1bWIsIHR5cGUsIHR5cGVJZH0gPSBkYXRhO1xuICBjb25zdCBob3N0OiBzdHJpbmcgPSBDb25maWcuZ2V0KCdlbnZpcm9ubWVudCcpID09PSAncHJvZCdcbiAgICA/IGBodHRwczovL2JveC4ke0NvbmZpZy5nZXQoJ2FwcC51cmwnKX1gXG4gICAgOiBgaHR0cHM6Ly9zMy5hbWF6b25hd3MuY29tL2Rldi4ke0NvbmZpZy5nZXQoJ2FwcC51cmwnKX1gO1xuICBjb25zdCBzdWZmaXg6IHN0cmluZyA9IGlzVGh1bWIgPyAnLXRoJyA6ICcnO1xuXG4gIGlmKGltYWdlSWQpIHtcbiAgICBzd2l0Y2godHlwZSkge1xuICAgICAgY2FzZSAnYXBwcyc6XG4gICAgICAgIC8vIGh0dHBzOi8vYm94LnJlYWt0b3IuaW8vbXlBcHAvYXBwL2ltYWdlcy8xMjMuanBnXG4gICAgICAgIHJldHVybiBgJHtob3N0fS8ke3R5cGV9LyR7ZGlyZWN0b3J5fS8ke2ltYWdlSWR9JHtzdWZmaXh9LmpwZ2A7XG4gICAgICBjYXNlICd1c2Vycyc6XG4gICAgICAgIC8vIGh0dHBzOi8vYm94LnJlYWt0b3IuaW8vbXlBcHAvdXNlcnMvZGVtb1VzZXIvaW1hZ2VzLzEyMy5qcGdcbiAgICAgICAgcmV0dXJuIGAke2hvc3R9LyR7dHlwZX0vJHt0eXBlSWR9LyR7ZGlyZWN0b3J5fS8ke2ltYWdlSWR9JHtzdWZmaXh9LmpwZ2A7XG4gICAgfVxuXG4gICAgaWYoaW1hZ2VUeXBlID09PSAncHJvZmlsZScpIHtcbiAgICAgIHJldHVybiBgJHtob3N0fS9kZWZhdWx0cy8ke3R5cGV9X2JrJHtzdWZmaXh9LmpwZ2A7XG4gICAgfVxuXG4gICAgcmV0dXJuIGAke2hvc3R9L2RlZmF1bHRzLyR7dHlwZX1fd2gke3N1ZmZpeH0uanBnYDtcbiAgfVxuXG4gIHJldHVybiAnJztcbn07XG5cbmV4cG9ydCBjb25zdCBnZXRVc2VySW1hZ2VVcmwgPSAoZGF0YTogSW1hZ2VVcmxEYXRhKTogc3RyaW5nID0+IHtcbiAgY29uc3Qge2J1Y2tldCwgaW1hZ2VJZCwgaXNUaHVtYiA9IGZhbHNlLCB1c2VySWR9ID0gZGF0YTtcbiAgY29uc3QgaW1nRGlyOiBzdHJpbmcgPSBpc1RodW1iID8gJ3RodW1icycgOiAnaW1hZ2VzJztcblxuICBpZihpbWFnZUlkKSB7XG4gICAgY29uc3QgaW1hZ2VLZXk6IHN0cmluZyA9IGB1c2Vycy8ke3VzZXJJZH0vJHtpbWdEaXJ9LyR7aW1hZ2VJZH0uanBnYDtcbiAgICByZXR1cm4gczNHZXRTaWduZWRVcmwoe0J1Y2tldDogYnVja2V0LCBLZXk6IGltYWdlS2V5LCBFeHBpcmVzOiA5MDB9KTtcbiAgfVxuXG4gIHJldHVybiAnJztcbn07XG5cbmV4cG9ydCBjb25zdCByZXNpemVTYXZlSW1hZ2UgPSAoXG4gIGNvbnRleHQ6IEFwaUNvbnRleHQsXG4gIGltYWdlSWQ6IHN0cmluZyxcbiAgYnVmZmVyOiBCdWZmZXIsXG4gIHR5cGU6IHN0cmluZyA9ICdpbWFnZS9qcGVnJywgczNPcHRpb25zPzogUHV0T2JqZWN0UmVxdWVzdCk6IFByb21pc2U8SW1hZ2VUeXBlPiA9PiB7XG4gIGNvbnN0IGFjdGlvbjogc3RyaW5nID0gJ3Jlc2l6ZVNhdmVJbWFnZSc7XG4gIGNvbnN0IHtzZXNzaW9uOiB7dXNlcklkOiBzZXNzaW9uSWR9fSA9IGNvbnRleHQ7XG4gIGNvbnN0IGltZ1c6IG51bWJlciA9IENvbmZpZy5nZXQoJ2ltYWdlLmltZ1NpemUnKTtcbiAgY29uc3QgaW1nUTogbnVtYmVyID0gQ29uZmlnLmdldCgnaW1hZ2UuaW1nUXVhbGl0eScpO1xuICBsZXQgcGhvdG86IEltYWdlVHlwZSA9IHt9O1xuICBjb25zdCBmb3JtYXQ6IHN0cmluZyA9ICh0eXBlLnNwbGl0KCcvJykpWzFdO1xuXG4gIGNvbnNvbGUubG9nKHtidWZmZXIsIGZvcm1hdCwgaW1nVywgaW1nUX0pO1xuICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUpID0+IHtcbiAgICBnbShidWZmZXIsICdpbWcnKVxuICAgICAgLnNldEZvcm1hdChmb3JtYXQpXG4gICAgICAucXVhbGl0eShpbWdRKVxuICAgICAgLmF1dG9PcmllbnQoKVxuICAgICAgLnJlc2l6ZShpbWdXLCBpbWdXLCAnPicpXG4gICAgICAuaWRlbnRpZnkoe2J1ZmZlclN0cmVhbTogdHJ1ZX0sIChlcnJvcjogRXJyb3IsIHZhbDogSW1hZ2VJZGVudGlmeVR5cGUgPSB7fSk6IGFueSA9PiB7XG4gICAgICAgIGlmKGVycm9yKSB7XG4gICAgICAgICAgbG9nRXJyb3Ioe1xuICAgICAgICAgICAgYWN0aW9uLFxuICAgICAgICAgICAgY2F0ZWdvcnk6IGV2ZW50Q2F0ZWdvcnksXG4gICAgICAgICAgICBsYWJlbDogJ2ltYWdlX3NhdmUnLFxuICAgICAgICAgICAgdmFsdWU6ICdnbV9pbWFnZV9pZGVudGlmeSdcbiAgICAgICAgICB9LCBlcnJvciwgY29udGV4dCkuY2F0Y2goKGVycm9yKSA9PiB7XG4gICAgICAgICAgICB0aHJvdyBlcnJvcjtcbiAgICAgICAgICB9KTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBjb25zdCBmb3JtYXRWYWxzID0gbG93ZXJDYXNlS2V5cyh2YWwpO1xuICAgICAgICAgIGNvbnN0IHttYWtlOiBjYW1lcmFNYWtlLCBtb2RlbDogY2FtZXJhTW9kZWwsIGRhdGV0aW1lb3JpZ2luYWw6IHRha2VufTogSW1hZ2VJZGVudGlmeVR5cGUgPSBmb3JtYXRWYWxzO1xuICAgICAgICAgIHBob3RvID0ge1xuICAgICAgICAgICAgLi4uY2xvbmVEZWVwKHBob3RvKSxcbiAgICAgICAgICAgIG1ha2U6IGNhbWVyYU1ha2UsXG4gICAgICAgICAgICBtb2RlbDogY2FtZXJhTW9kZWwsXG4gICAgICAgICAgICB0YWtlbjogdGFrZW4gPyBEYXRlVGltZS5mcm9tTWlsbGlzKHRha2VuKS5taWxsaXNlY29uZCA6IG51bGxcbiAgICAgICAgICB9O1xuXG4gICAgICAgICAgLy8gSWYgbm8gYmFja2dyb3VuZCBjb2xvciwgZ2V0IHRoZSBtZWFuIGNvbG9yIHZhbHVlXG4gICAgICAgICAgY29uc3Qgc3RhdHMgPSBmb3JtYXRWYWxzWydjaGFubmVsIHN0YXRpc3RpY3MnXTtcblxuICAgICAgICAgIGlmKHN0YXRzKSB7XG4gICAgICAgICAgICBsZXQge3JlZCwgZ3JlZW4sIGJsdWUsIG1lYW59ID0gc3RhdHM7XG5cbiAgICAgICAgICAgIGlmKHJlZCkge1xuICAgICAgICAgICAgICBtZWFuID0gcmVkWydzdGFuZGFyZCBkZXZpYXRpb24nXSB8fCByZWQubWVhbjtcbiAgICAgICAgICAgICAgcmVkID0gbWVhbiA/ICsoKG1lYW4uc3BsaXQoJyAnKVswXSkuc3Vic3RyaW5nKDAsIDMpKSA6IDA7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICByZWQgPSAwO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZihncmVlbikge1xuICAgICAgICAgICAgICBtZWFuID0gZ3JlZW5bJ3N0YW5kYXJkIGRldmlhdGlvbiddIHx8IGdyZWVuLm1lYW47XG4gICAgICAgICAgICAgIGdyZWVuID0gbWVhbiA/ICsoKG1lYW4uc3BsaXQoJyAnKVswXSkuc3Vic3RyaW5nKDAsIDMpKSA6IDA7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICBncmVlbiA9IDA7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmKGJsdWUpIHtcbiAgICAgICAgICAgICAgbWVhbiA9IGJsdWVbJ3N0YW5kYXJkIGRldmlhdGlvbiddIHx8IGJsdWUubWVhbjtcbiAgICAgICAgICAgICAgYmx1ZSA9IG1lYW4gPyArKChtZWFuLnNwbGl0KCcgJylbMF0pLnN1YnN0cmluZygwLCAzKSkgOiAwO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgYmx1ZSA9IDA7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGNvbnN0IHJnYiA9IGJsdWUgfCAoZ3JlZW4gPDwgOCkgfCAocmVkIDw8IDE2KTtcbiAgICAgICAgICAgIGNvbnN0IGNvbG9yID0gcmdiLnRvU3RyaW5nKDE2KTtcbiAgICAgICAgICAgIHBob3RvLmNvbG9yID0gY29sb3IgPT09ICcwJyA/ICcwMDAwMDAnIDogY29sb3I7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9KVxuICAgICAgLnN0cmVhbSgoZXJyb3I6IEVycm9yLCBzdGRvdXQpOiBhbnkgPT4ge1xuICAgICAgICBpZihlcnJvcikge1xuICAgICAgICAgIGxvZ0Vycm9yKHtcbiAgICAgICAgICAgIGFjdGlvbixcbiAgICAgICAgICAgIGNhdGVnb3J5OiBldmVudENhdGVnb3J5LFxuICAgICAgICAgICAgaXNJbnRlcm5hbDogdHJ1ZSxcbiAgICAgICAgICAgIGxhYmVsOiAnaW1hZ2Vfc2F2ZScsXG4gICAgICAgICAgICB2YWx1ZTogJ2dtX2ltYWdlX3N0cmVhbSdcbiAgICAgICAgICB9LCBlcnJvciwgY29udGV4dCkudGhlbigoKSA9PiBudWxsKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBsZXQgaW1hZ2VCdWZmZXI6IEJ1ZmZlciA9IEJ1ZmZlci5mcm9tKCcnKTtcblxuICAgICAgICAgIHN0ZG91dC5vbignZGF0YScsIChkYXRhKSA9PiB7XG4gICAgICAgICAgICBpbWFnZUJ1ZmZlciA9IEJ1ZmZlci5jb25jYXQoW2ltYWdlQnVmZmVyLCBkYXRhXSk7XG4gICAgICAgICAgfSk7XG5cbiAgICAgICAgICBzdGRvdXQub24oJ2VuZCcsICgpID0+IHtcbiAgICAgICAgICAgIC8vIEdldCBmaWxlIHNpemVcbiAgICAgICAgICAgIHBob3RvLmZpbGVTaXplID0gaW1hZ2VCdWZmZXIubGVuZ3RoO1xuXG4gICAgICAgICAgICAvLyBVcGxvYWQgZGF0YVxuICAgICAgICAgICAgY29uc3QgaW1hZ2VPYmo6IFB1dE9iamVjdFJlcXVlc3QgPSB7XG4gICAgICAgICAgICAgIEFDTDogJ2F1dGhlbnRpY2F0ZWQtcmVhZCcsXG4gICAgICAgICAgICAgIEJvZHk6IGltYWdlQnVmZmVyLFxuICAgICAgICAgICAgICBCdWNrZXQ6IG51bGwsXG4gICAgICAgICAgICAgIENvbnRlbnRUeXBlOiB0eXBlLFxuICAgICAgICAgICAgICAuLi5zM09wdGlvbnMgfHwge30sXG4gICAgICAgICAgICAgIEtleTogZ2V0UGF0aFVzZXJJbWFnZXMoc2Vzc2lvbklkLCBpbWFnZUlkLCB0eXBlLCAnaW1hZ2VzJylcbiAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgIHMzUHV0KGltYWdlT2JqKVxuICAgICAgICAgICAgICAudGhlbigoKSA9PiB7XG4gICAgICAgICAgICAgICAgY29uc3QgdGhtVyA9IENvbmZpZy5nZXQoJ2ltYWdlLnRobVNpemUnKTtcbiAgICAgICAgICAgICAgICBjb25zdCB0aG1RID0gQ29uZmlnLmdldCgnaW1hZ2UudGhtUXVhbGl0eScpO1xuXG4gICAgICAgICAgICAgICAgLy8gVXBsb2FkIHRodW1ibmFpbFxuICAgICAgICAgICAgICAgIGdtKGltYWdlQnVmZmVyLCAnaW1nJylcbiAgICAgICAgICAgICAgICAgIC5zZXRGb3JtYXQoJ2pwZWcnKVxuICAgICAgICAgICAgICAgICAgLnNpemUoKHRodW1iRXJyb3I6IEVycm9yLCByZXNpemVWYWwpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgaWYoIXRodW1iRXJyb3IpIHtcbiAgICAgICAgICAgICAgICAgICAgICAvLyBHZXQgdXBkYXRlZCByZXNpemUgdmFsdWVzXG4gICAgICAgICAgICAgICAgICAgICAgY29uc3Qge2hlaWdodCwgd2lkdGh9ID0gcmVzaXplVmFsO1xuICAgICAgICAgICAgICAgICAgICAgIHBob3RvID0gey4uLmNsb25lRGVlcChwaG90byksIGhlaWdodCwgd2lkdGh9O1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICB9KVxuICAgICAgICAgICAgICAgICAgLmdyYXZpdHkoJ0NlbnRlcicpXG4gICAgICAgICAgICAgICAgICAucmVzaXplKHRobVcsIHRobVcsICdeJylcbiAgICAgICAgICAgICAgICAgIC5leHRlbnQodGhtVywgdGhtVylcbiAgICAgICAgICAgICAgICAgIC5xdWFsaXR5KHRobVEpXG4gICAgICAgICAgICAgICAgICAuc3RyZWFtKChzdHJlYW1FcnJvcjogRXJyb3IsIHRodW1iU3Rkb3V0KTogYW55ID0+IHtcbiAgICAgICAgICAgICAgICAgICAgaWYoc3RyZWFtRXJyb3IpIHtcbiAgICAgICAgICAgICAgICAgICAgICBsb2dFcnJvcih7XG4gICAgICAgICAgICAgICAgICAgICAgICBhY3Rpb24sXG4gICAgICAgICAgICAgICAgICAgICAgICBjYXRlZ29yeTogZXZlbnRDYXRlZ29yeSxcbiAgICAgICAgICAgICAgICAgICAgICAgIGxhYmVsOiAnaW1hZ2Vfc2F2ZScsXG4gICAgICAgICAgICAgICAgICAgICAgICB2YWx1ZTogJ2dtX3RodW1ibmFpbF9zdGVhbSdcbiAgICAgICAgICAgICAgICAgICAgICB9LCBzdHJlYW1FcnJvciwgY29udGV4dClcbiAgICAgICAgICAgICAgICAgICAgICAgIC5jYXRjaCgoZXJyb3IpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgdGhyb3cgZXJyb3I7XG4gICAgICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICBsZXQgdGh1bWJCdWZmZXI6IEJ1ZmZlciA9IEJ1ZmZlci5mcm9tKCcnKTtcblxuICAgICAgICAgICAgICAgICAgICAgIHRodW1iU3Rkb3V0Lm9uKCdkYXRhJywgKGRhdGEpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRodW1iQnVmZmVyID0gQnVmZmVyLmNvbmNhdChbdGh1bWJCdWZmZXIsIGRhdGFdKTtcbiAgICAgICAgICAgICAgICAgICAgICB9KTtcblxuICAgICAgICAgICAgICAgICAgICAgIHRodW1iU3Rkb3V0Lm9uKCdlbmQnLCAoKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBVcGxvYWQgZGF0YVxuICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgdGh1bWJPYmo6IFB1dE9iamVjdFJlcXVlc3QgPSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgIEFDTDogJ2F1dGhlbnRpY2F0ZWQtcmVhZCcsXG4gICAgICAgICAgICAgICAgICAgICAgICAgIEJvZHk6IHRodW1iQnVmZmVyLFxuICAgICAgICAgICAgICAgICAgICAgICAgICBCdWNrZXQ6IG51bGwsXG4gICAgICAgICAgICAgICAgICAgICAgICAgIENvbnRlbnRUeXBlOiB0eXBlLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAuLi5zM09wdGlvbnMgfHwge30sXG4gICAgICAgICAgICAgICAgICAgICAgICAgIEtleTogZ2V0UGF0aFVzZXJJbWFnZXMoc2Vzc2lvbklkLCBpbWFnZUlkLCB0eXBlLCAndGh1bWJzJylcbiAgICAgICAgICAgICAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIHMzUHV0KHRodW1iT2JqKVxuICAgICAgICAgICAgICAgICAgICAgICAgICAudGhlbigoKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVzb2x2ZShwaG90byk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAgICAgICAgICAgICAgIC5jYXRjaCgoczNQdXRFcnJvcikgPT4gbG9nRXJyb3Ioe1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFjdGlvbixcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXRlZ29yeTogZXZlbnRDYXRlZ29yeSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBsYWJlbDogJ2ltYWdlX3NhdmUnLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhbHVlOiAnczNfcHV0X2ltYWdlJ1xuICAgICAgICAgICAgICAgICAgICAgICAgICB9LCBzM1B1dEVycm9yLCBjb250ZXh0KVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC5jYXRjaCgoZXJyb3IpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRocm93IGVycm9yO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pKTtcbiAgICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAgIC5jYXRjaCgoczNFcnJvcikgPT4gbG9nRXJyb3Ioe1xuICAgICAgICAgICAgICAgIGFjdGlvbixcbiAgICAgICAgICAgICAgICBjYXRlZ29yeTogZXZlbnRDYXRlZ29yeSxcbiAgICAgICAgICAgICAgICBpc0ludGVybmFsOiB0cnVlLFxuICAgICAgICAgICAgICAgIGxhYmVsOiAnaW1hZ2Vfc2F2ZScsXG4gICAgICAgICAgICAgICAgdmFsdWU6ICdzM19pbWFnZV9zYXZlJ1xuICAgICAgICAgICAgICB9LCBzM0Vycm9yLCBjb250ZXh0KS50aGVuKCgpID0+IG51bGwpKTtcbiAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgICAgfSk7XG4gIH0pO1xufTtcblxuZXhwb3J0IGNvbnN0IGFkZEltYWdlID0gKGNvbnRleHQ6IEFwaUNvbnRleHQsIGltYWdlOiBJbWFnZVR5cGUsIHMzT3B0aW9ucz86IFB1dE9iamVjdFJlcXVlc3QpOiBQcm9taXNlPEltYWdlVHlwZT4gPT4ge1xuICBjb25zdCBhY3Rpb246IHN0cmluZyA9ICdhZGRJbWFnZSc7XG4gIGNvbnN0IHtkYXRhYmFzZSwgc2Vzc2lvbjoge3VzZXJJZDogc2Vzc2lvbklkfX0gPSBjb250ZXh0O1xuICBjb25zdCB7aW1hZ2VJZCwgZGVzY3JpcHRpb24sIGJ1ZmZlciwgZmlsZVR5cGV9ID0gaW1hZ2U7XG4gIGNvbnN0IG5vdzogbnVtYmVyID0gRGF0ZS5ub3coKTtcblxuICByZXR1cm4gcmVzaXplU2F2ZUltYWdlKGNvbnRleHQsIGltYWdlSWQsIGJ1ZmZlciwgZmlsZVR5cGUsIHMzT3B0aW9ucylcbiAgICAudGhlbigocmVzaXplZEltYWdlOiBhbnkpID0+IHtcbiAgICAgIGNvbnN0IGluc2VydDogSW1hZ2VUeXBlID0ge1xuICAgICAgICAuLi5yZXNpemVkSW1hZ2UsXG4gICAgICAgIF9rZXk6IGltYWdlSWQsXG4gICAgICAgIGFkZGVkOiBub3csXG4gICAgICAgIGRlc2NyaXB0aW9uLFxuICAgICAgICBmaWxlVHlwZSxcbiAgICAgICAgbW9kaWZpZWQ6IG5vdyxcbiAgICAgICAgdXNlcklkOiBzZXNzaW9uSWRcbiAgICAgIH07XG5cbiAgICAgIGNvbnN0IGFxbFFyeTogQXFsUXVlcnkgPSBhcWxgSU5TRVJUICR7aW5zZXJ0fSBJTiBpbWFnZXMgUkVUVVJOIE5FV2A7XG5cbiAgICAgIHJldHVybiBkYXRhYmFzZS5xdWVyeShhcWxRcnkpXG4gICAgICAgIC50aGVuKChjdXJzb3I6IEFycmF5Q3Vyc29yKSA9PiBjdXJzb3IubmV4dCgpKVxuICAgICAgICAudGhlbihkZWZhdWx0T2JqZWN0KVxuICAgICAgICAuY2F0Y2goKGVycm9yOiBFcnJvcikgPT4gbG9nRXJyb3Ioe1xuICAgICAgICAgIGFjdGlvbixcbiAgICAgICAgICBjYXRlZ29yeTogZXZlbnRDYXRlZ29yeSxcbiAgICAgICAgICBpc0ludGVybmFsOiB0cnVlLFxuICAgICAgICAgIGxhYmVsOiAnZGJfZXJyb3InXG4gICAgICAgIH0sIGVycm9yLCBjb250ZXh0KS50aGVuKCgpID0+IG51bGwpKTtcbiAgICB9KVxuICAgIC5jYXRjaCgoZXJyb3I6IEVycm9yKSA9PiBsb2dFcnJvcih7XG4gICAgICBhY3Rpb24sXG4gICAgICBjYXRlZ29yeTogZXZlbnRDYXRlZ29yeSxcbiAgICAgIGlzSW50ZXJuYWw6IHRydWUsXG4gICAgICBsYWJlbDogJ2ltYWdlX3Jlc2l6ZSdcbiAgICB9LCBlcnJvciwgY29udGV4dCkudGhlbigoKSA9PiBudWxsKSk7XG59O1xuXG5leHBvcnQgY29uc3QgYWRkSW1hZ2VFZGdlID0gYXN5bmMgKGNvbnRleHQ6IEFwaUNvbnRleHQsIGltYWdlRWRnZTogSW1hZ2VFZGdlVHlwZSk6IFByb21pc2U8b2JqZWN0PiA9PiB7XG4gIGNvbnN0IGFjdGlvbjogc3RyaW5nID0gJ2FkZEltYWdlRWRnZSc7XG4gIGNvbnN0IHtkYXRhYmFzZSwgc2Vzc2lvbjoge3VzZXJJZDogc2Vzc2lvbklkfX0gPSBjb250ZXh0O1xuICBjb25zdCB7aW1hZ2VJZCwgaXRlbUlkLCBpdGVtVHlwZX0gPSBpbWFnZUVkZ2U7XG4gIGNvbnN0IG5vdzogbnVtYmVyID0gRGF0ZS5ub3coKTtcbiAgY29uc3QgZWRnZUNvbGxlY3Rpb246IEVkZ2VDb2xsZWN0aW9uID0gZGF0YWJhc2UuY29sbGVjdGlvbignaGFzSW1hZ2VzJyk7XG4gIGNvbnN0IGVkZ2VJZDogc3RyaW5nID0gY3JlYXRlSGFzaChgaGFzSW1hZ2VzLSR7aW1hZ2VJZH0tJHtpdGVtSWR9LSR7c2Vzc2lvbklkfWApO1xuICBjb25zdCBmb3JtYXRJdGVtVHlwZTogc3RyaW5nID0gcGFyc2VDaGFyKGl0ZW1UeXBlKS50b0xvd2VyQ2FzZSgpO1xuICBjb25zdCBmb3JtYXRJdGVtSWQ6IHN0cmluZyA9IHBhcnNlSWQoaXRlbUlkKTtcbiAgbGV0IGl0ZW1Eb2NJZDogc3RyaW5nO1xuICBjb25zdCBmb3JtYXRJbWdJZDogc3RyaW5nID0gcGFyc2VJZChpbWFnZUlkKTtcbiAgY29uc3QgZmlsZURvY0lkOiBzdHJpbmcgPSBgaW1hZ2VzLyR7Zm9ybWF0SW1nSWR9YDtcblxuICBzd2l0Y2goZm9ybWF0SXRlbVR5cGUpIHtcbiAgICBjYXNlICdncm91cHMnOlxuICAgICAgaXRlbURvY0lkID0gYGdyb3Vwcy8ke2Zvcm1hdEl0ZW1JZH1gO1xuICAgICAgYnJlYWs7XG4gICAgY2FzZSAncG9zdHMnOlxuICAgICAgaXRlbURvY0lkID0gYHBvc3RzLyR7Zm9ybWF0SXRlbUlkfWA7XG4gICAgICBicmVhaztcbiAgICBjYXNlICd1c2Vycyc6XG4gICAgY2FzZSAncHJvZmlsZSc6XG4gICAgICBpdGVtRG9jSWQgPSBgdXNlcnMvJHtmb3JtYXRJdGVtSWR9YDtcbiAgICAgIGJyZWFrO1xuICAgIGRlZmF1bHQ6XG4gICAgICBpdGVtRG9jSWQgPSAnJztcbiAgICAgIGJyZWFrO1xuICB9XG4gIGNvbnN0IGVkZ2U6IGFueSA9IHtcbiAgICBfZnJvbTogaXRlbURvY0lkLFxuICAgIF9rZXk6IGVkZ2VJZCxcbiAgICBfdG86IGZpbGVEb2NJZCxcbiAgICBhZGRlZDogbm93LFxuICAgIHR5cGU6IGl0ZW1UeXBlXG4gIH07XG5cbiAgaWYoIWlzRW1wdHkoaXRlbURvY0lkKSkge1xuICAgIHJldHVybiBlZGdlQ29sbGVjdGlvbi5zYXZlKGVkZ2UsIHtyZXR1cm5OZXc6IHRydWV9KVxuICAgICAgLnRoZW4oKGZpbGVFZGdlKSA9PiBlZGdlQ29sbGVjdGlvbi5kb2N1bWVudChmaWxlRWRnZSkpXG4gICAgICAuY2F0Y2goKGVycm9yOiBFcnJvcikgPT4gbG9nRXJyb3Ioe1xuICAgICAgICBhY3Rpb24sXG4gICAgICAgIGNhdGVnb3J5OiBldmVudENhdGVnb3J5LFxuICAgICAgICBpc0ludGVybmFsOiB0cnVlLFxuICAgICAgICBsYWJlbDogJ2RiX2Vycm9yJyxcbiAgICAgICAgcGFyYW1zOiB7XG4gICAgICAgICAgZWRnZSxcbiAgICAgICAgICBmaWxlRG9jSWQsXG4gICAgICAgICAgaW1hZ2VJZCxcbiAgICAgICAgICBpdGVtRG9jSWQsXG4gICAgICAgICAgaXRlbUlkLFxuICAgICAgICAgIGl0ZW1UeXBlXG4gICAgICAgIH1cbiAgICAgIH0sIGVycm9yLCBjb250ZXh0KS50aGVuKCgpID0+IG51bGwpKTtcbiAgfVxuXG4gIHJldHVybiB7fTtcbn07XG5cbmV4cG9ydCBjb25zdCB1cGRhdGVJbWFnZSA9IGFzeW5jIChcbiAgY29udGV4dDogQXBpQ29udGV4dCxcbiAgaW1hZ2U6IEltYWdlVHlwZSxcbiAgczNPcHRpb25zPzogUHV0T2JqZWN0UmVxdWVzdFxuKTogUHJvbWlzZTxJbWFnZVR5cGU+ID0+IHtcbiAgY29uc3QgYWN0aW9uOiBzdHJpbmcgPSAndXBkYXRlSW1hZ2UnO1xuICBjb25zdCB7ZGF0YWJhc2UsIHNlc3Npb246IHt1c2VySWQ6IHNlc3Npb25JZH19ID0gY29udGV4dDtcblxuICAvLyBJdGVtIHByb3BzXG4gIGNvbnN0IHtcbiAgICBiYXNlNjQgPSAnJyxcbiAgICBidWZmZXI6IGltYWdlQnVmZmVyLFxuICAgIGRlc2NyaXB0aW9uID0gJycsXG4gICAgaW1hZ2VJZCxcbiAgICBpdGVtSWQsXG4gICAgaXRlbVR5cGUsXG4gICAgZmlsZVR5cGUsXG4gICAgdXJsID0gJydcbiAgfSA9IGltYWdlO1xuXG4gIC8vIFNhdmUgQmFzZTY0IGRhdGFcbiAgY29uc3Qgbm93OiBudW1iZXIgPSBEYXRlLm5vdygpO1xuICBjb25zdCBmb3JtYXRJbWFnZUlkOiBzdHJpbmcgPSBpbWFnZUlkIHx8IGNyZWF0ZUhhc2goYGltYWdlLSR7c2Vzc2lvbklkfWApO1xuICBjb25zdCBmb3JtYXRJdGVtSWQ6IHN0cmluZyA9IHBhcnNlSWQoaXRlbUlkKTtcbiAgY29uc3QgZm9ybWF0SXRlbVR5cGU6IHN0cmluZyA9IHBhcnNlQ2hhcihpdGVtVHlwZSwgMTYpLnRvTG93ZXJDYXNlKCk7XG4gIGNvbnN0IGN1c3RvbVBhcmFtczogSW1hZ2VUeXBlID0ge1xuICAgIGRlc2NyaXB0aW9uLFxuICAgIGltYWdlSWQ6IGZvcm1hdEltYWdlSWQsXG4gICAgdXNlcklkOiBzZXNzaW9uSWRcbiAgfTtcblxuICBpZighaXNFbXB0eShiYXNlNjQpIHx8IGltYWdlQnVmZmVyKSB7XG4gICAgbGV0IGJ1ZmZlcjogQnVmZmVyID0gaW1hZ2VCdWZmZXI7XG5cbiAgICAvLyBQYXJzZSBCYXNlNjQgZGF0YVxuICAgIGlmKCFpc0VtcHR5KGJhc2U2NCkpIHtcbiAgICAgIGNvbnN0IGZvcm1hdEJhc2U2NDogc3RyaW5nID0gYmFzZTY0LnN1YnN0cihiYXNlNjQuaW5kZXhPZignLCcpICsgMSk7XG4gICAgICBidWZmZXIgPSBCdWZmZXIuZnJvbShmb3JtYXRCYXNlNjQsICdiYXNlNjQnKTtcbiAgICB9XG5cbiAgICBsZXQgdXBkYXRlZEZpbGVUeXBlID0gZmlsZVR5cGU7XG5cbiAgICBpZighZmlsZVR5cGUpIHtcbiAgICAgIGNvbnN0IGZpbGVNaW1lOiBGaWxlVHlwZVJlc3VsdCA9IGF3YWl0IEZpbGVUeXBlLmZyb21CdWZmZXIoYnVmZmVyKTtcbiAgICAgIGNvbnN0IHttaW1lfSA9IGZpbGVNaW1lO1xuICAgICAgdXBkYXRlZEZpbGVUeXBlID0gbWltZTtcbiAgICB9XG5cbiAgICBjb25zdCBpbWdQYXJhbXM6IEltYWdlVHlwZSA9IHtcbiAgICAgIC4uLmN1c3RvbVBhcmFtcyxcbiAgICAgIGJ1ZmZlcixcbiAgICAgIGZpbGVUeXBlOiB1cGRhdGVkRmlsZVR5cGVcbiAgICB9O1xuXG4gICAgcmV0dXJuIGFkZEltYWdlKGNvbnRleHQsIGltZ1BhcmFtcywgczNPcHRpb25zKVxuICAgICAgLnRoZW4oKGltYWdlOiBJbWFnZVR5cGUpID0+IHtcbiAgICAgICAgaWYoZm9ybWF0SXRlbUlkICYmIGZvcm1hdEl0ZW1UeXBlKSB7XG4gICAgICAgICAgY29uc3QgaW1hZ2VFZGdlOiBJbWFnZUVkZ2VUeXBlID0ge1xuICAgICAgICAgICAgaW1hZ2VJZDogZm9ybWF0SW1hZ2VJZCxcbiAgICAgICAgICAgIGl0ZW1JZDogZm9ybWF0SXRlbUlkLFxuICAgICAgICAgICAgaXRlbVR5cGU6IGZvcm1hdEl0ZW1UeXBlXG4gICAgICAgICAgfTtcbiAgICAgICAgICByZXR1cm4gYWRkSW1hZ2VFZGdlKGNvbnRleHQsIGltYWdlRWRnZSkudGhlbigoKSA9PiBpbWFnZSk7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gaW1hZ2U7XG4gICAgICB9KVxuICAgICAgLmNhdGNoKChlcnJvcikgPT4gbG9nRXJyb3Ioe1xuICAgICAgICBhY3Rpb24sXG4gICAgICAgIGNhdGVnb3J5OiBldmVudENhdGVnb3J5LFxuICAgICAgICBsYWJlbDogJ2ltYWdlX3NhdmVfZXJyb3InXG4gICAgICB9LCBlcnJvciwgY29udGV4dCkudGhlbigoKSA9PiBudWxsKSk7XG4gIH0gZWxzZSBpZih1cmwgIT09ICcnKSB7XG4gICAgLy8gRG93bmxvYWQgaW1hZ2UgZnJvbSB0aGUgd2ViXG4gICAgbGV0IGNvbnRlbnRUeXBlOiBzdHJpbmc7XG5cbiAgICByZXR1cm4gaHR0cEdldCh1cmwpXG4gICAgICAudGhlbigocmVzOiBSZXNwb25zZSkgPT4ge1xuICAgICAgICBpZihyZXMuc3RhdHVzICE9PSAyMDApIHtcbiAgICAgICAgICByZXR1cm4gbG9nRXhjZXB0aW9uKHtcbiAgICAgICAgICAgIGFjdGlvbixcbiAgICAgICAgICAgIGNhdGVnb3J5OiBldmVudENhdGVnb3J5LFxuICAgICAgICAgICAgbGFiZWw6ICdmZXRjaF9pbWFnZV91cmwnLFxuICAgICAgICAgICAgdmFsdWU6IHJlcy5zdGF0dXNUZXh0XG4gICAgICAgICAgfSwgY29udGV4dCkudGhlbigoKSA9PiBudWxsKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnRlbnRUeXBlID0gcmVzLmhlYWRlcnMuZ2V0KCdjb250ZW50LXR5cGUnKTtcblxuICAgICAgICByZXR1cm4gcmVzO1xuICAgICAgfSlcbiAgICAgIC50aGVuKChyZXMpID0+IHJlcy5idWZmZXIoKSlcbiAgICAgIC50aGVuKChidWZmZXI6IEJ1ZmZlcikgPT4ge1xuICAgICAgICBjb25zdCBpbWdQYXJhbXM6IEltYWdlVHlwZSA9IHtcbiAgICAgICAgICAuLi5jdXN0b21QYXJhbXMsXG4gICAgICAgICAgYnVmZmVyLFxuICAgICAgICAgIGZpbGVUeXBlOiBjb250ZW50VHlwZVxuICAgICAgICB9O1xuXG4gICAgICAgIHJldHVybiBhZGRJbWFnZShjb250ZXh0LCBpbWdQYXJhbXMsIHMzT3B0aW9ucykudGhlbigoaW1hZ2U6IEltYWdlVHlwZSkgPT4ge1xuICAgICAgICAgIGlmKGZvcm1hdEl0ZW1JZCAmJiBmb3JtYXRJdGVtVHlwZSkge1xuICAgICAgICAgICAgY29uc3QgaW1hZ2VFZGdlOiBJbWFnZUVkZ2VUeXBlID0ge2ltYWdlSWQ6IGZvcm1hdEltYWdlSWQsIGl0ZW1JZDogZm9ybWF0SXRlbUlkLCBpdGVtVHlwZTogZm9ybWF0SXRlbVR5cGV9O1xuICAgICAgICAgICAgcmV0dXJuIGFkZEltYWdlRWRnZShjb250ZXh0LCBpbWFnZUVkZ2UpLnRoZW4oKCkgPT4gaW1hZ2UpO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIHJldHVybiBpbWFnZTtcbiAgICAgICAgfSk7XG4gICAgICB9KVxuICAgICAgLmNhdGNoKChlcnJvcjogRXJyb3IpID0+IGxvZ0Vycm9yKHtcbiAgICAgICAgYWN0aW9uLFxuICAgICAgICBjYXRlZ29yeTogZXZlbnRDYXRlZ29yeSxcbiAgICAgICAgbGFiZWw6ICdmZXRjaF9lcnJvcidcbiAgICAgIH0sIGVycm9yLCBjb250ZXh0KS50aGVuKCgpID0+IG51bGwpKTtcbiAgfSBlbHNlIGlmKGltYWdlSWQgIT09ICcnKSB7XG4gICAgLy8gVXBkYXRlIG1ldGFkYXRhXG4gICAgY29uc3QgdXBkYXRlOiBhbnkgPSB7XG4gICAgICBkZXNjcmlwdGlvbixcbiAgICAgIG1vZGlmaWVkOiBub3dcbiAgICB9O1xuICAgIGNvbnN0IGFxbFFyeTogQXFsUXVlcnkgPSBhcWxgVVBEQVRFIHtfa2V5OiAke2Zvcm1hdEltYWdlSWR9fSBXSVRIICR7dXBkYXRlfSBJTiBpbWFnZXMgUkVUVVJOIE5FV2A7XG5cbiAgICByZXR1cm4gZGF0YWJhc2UucXVlcnkoYXFsUXJ5KVxuICAgICAgLnRoZW4oKGN1cnNvcjogQXJyYXlDdXJzb3IpID0+IGN1cnNvci5uZXh0KCkpXG4gICAgICAuY2F0Y2goKGVycm9yOiBFcnJvcikgPT4gbG9nRXJyb3Ioe1xuICAgICAgICBhY3Rpb24sXG4gICAgICAgIGNhdGVnb3J5OiBldmVudENhdGVnb3J5LFxuICAgICAgICBsYWJlbDogJ2RiX2Vycm9yJyxcbiAgICAgICAgcGFyYW1zOiB7XG4gICAgICAgICAgYXFsUXJ5LFxuICAgICAgICAgIGZvcm1hdEltYWdlSWQsXG4gICAgICAgICAgdXBkYXRlXG4gICAgICAgIH1cbiAgICAgIH0sIGVycm9yLCBjb250ZXh0KS50aGVuKCgpID0+IG51bGwpKTtcbiAgfVxuXG4gIHJldHVybiBudWxsO1xufTtcblxuZXhwb3J0IGNvbnN0IGRlbGV0ZUltYWdlID0gYXN5bmMgKGNvbnRleHQ6IEFwaUNvbnRleHQsIGltYWdlSWQ6IHN0cmluZyk6IFByb21pc2U8SW1hZ2VUeXBlPiA9PiB7XG4gIGNvbnN0IGFjdGlvbjogc3RyaW5nID0gJ2RlbGV0ZSc7XG4gIGNvbnN0IHtkYXRhYmFzZSwgc2Vzc2lvbjoge3VzZXJJZDogc2Vzc2lvbklkfX0gPSBjb250ZXh0O1xuICBjb25zdCBmb3JtYXRJbWFnZUlkID0gcGFyc2VJZChpbWFnZUlkKTtcblxuICBjb25zdCByZW1vdmVFZGdlUXVlcnkgPSBhcWxgRk9SIGhpIElOIGhhc0ltYWdlc1xuICAgIEZJTFRFUiBoaS5fZnJvbSA9PSAke2Zvcm1hdEltYWdlSWR9XG4gICAgUkVNT1ZFIGhpIElOIGhhc0ltYWdlc1xuICAgIFJFVFVSTiBPTERgO1xuXG4gIGF3YWl0IGRhdGFiYXNlLnF1ZXJ5KHJlbW92ZUVkZ2VRdWVyeSk7XG5cbiAgY29uc3QgYXFsUXVlcnkgPSBhcWxgRk9SIGkgSU4gaW1hZ2VzXG4gICAgRklMVEVSIGkuX2tleSA9PSAke2Zvcm1hdEltYWdlSWR9ICYmIGkudXNlcklkID09ICR7c2Vzc2lvbklkfVxuICAgIFJFTU9WRSBpIElOIGltYWdlc1xuICAgIFJFVFVSTiBPTERgO1xuXG4gIGNvbnN0IGltYWdlID0gYXdhaXQgZGF0YWJhc2UucXVlcnkoYXFsUXVlcnkpXG4gICAgLnRoZW4oKGN1cnNvcjogQXJyYXlDdXJzb3IpID0+IGN1cnNvci5uZXh0KCkpXG4gICAgLmNhdGNoKChlcnJvcjogRXJyb3IpID0+IGxvZ0Vycm9yKHtcbiAgICAgIGFjdGlvbixcbiAgICAgIGNhdGVnb3J5OiBldmVudENhdGVnb3J5LFxuICAgICAgbGFiZWw6ICdkYl9lcnJvcidcbiAgICB9LCBlcnJvciwgY29udGV4dCkudGhlbigoKSA9PiBudWxsKSk7XG5cbiAgaWYoIWlzRW1wdHkoaW1hZ2UpKSB7XG4gICAgY29uc3Qge19rZXk6IGltYWdlS2V5fSA9IGltYWdlO1xuICAgIGNvbnN0IHBhcmFtczogRGVsZXRlT2JqZWN0c1JlcXVlc3QgPSB7XG4gICAgICBCdWNrZXQ6IG51bGwsXG4gICAgICBEZWxldGU6IHtcbiAgICAgICAgT2JqZWN0czogW1xuICAgICAgICAgIHtLZXk6IGB1c2Vycy8ke3Nlc3Npb25JZH0vaW1hZ2VzLyR7aW1hZ2VLZXl9LmpwZ2B9LFxuICAgICAgICAgIHtLZXk6IGB1c2Vycy8ke3Nlc3Npb25JZH0vdGh1bWJzLyR7aW1hZ2VLZXl9LmpwZ2B9XG4gICAgICAgIF0sXG4gICAgICAgIFF1aWV0OiB0cnVlXG4gICAgICB9XG4gICAgfTtcblxuICAgIHJldHVybiBzM0RlbGV0ZUxpc3QocGFyYW1zKS50aGVuKCgpID0+IGltYWdlKTtcbiAgfVxuXG4gIHJldHVybiB7fTtcbn07XG4iXSwKICAibWFwcGluZ3MiOiAiOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBSUEsd0JBQTZCO0FBQzdCLG1CQUFzRTtBQUN0RSxzQkFBa0I7QUFLbEIsdUJBQXVDO0FBQ3ZDLGdCQUFlO0FBQ2YsdUJBQXNCO0FBQ3RCLHFCQUFvQjtBQUNwQixtQkFBdUI7QUFFdkIsb0JB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
|