@discordeno/rest 22.0.1-next.fca3cbb → 22.0.1-next.fdb61e1

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.
@@ -0,0 +1,3711 @@
1
+ import { Buffer } from 'node:buffer';
2
+ import { processReactionString } from '@discordeno/utils';
3
+ /**
4
+ * @internal You are not supposed to use the functions in this object directly. Use the RestManager instead.
5
+ */ export const restEndpoints = {
6
+ /**
7
+ * Adds a reaction to a message.
8
+ *
9
+ * @param channelId - The ID of the channel the message to add a reaction to is in.
10
+ * @param messageId - The ID of the message to add a reaction to.
11
+ * @param reaction - The reaction to add to the message.
12
+ * @returns
13
+ *
14
+ * @remarks
15
+ * Requires the `READ_MESSAGE_HISTORY` permission.
16
+ *
17
+ * If nobody else has reacted to the message:
18
+ * - Requires the `ADD_REACTIONS` permission.
19
+ *
20
+ * Fires a _Message Reaction Add_ gateway event.
21
+ *
22
+ * @see {@link https://docs.discord.com/developers/resources/channel#create-reaction}
23
+ */ async addReaction (rest, channelId, messageId, reaction) {
24
+ reaction = processReactionString(reaction);
25
+ await rest.put(rest.routes.channels.reactions.bot(channelId, messageId, reaction));
26
+ },
27
+ /**
28
+ * Adds multiple a reaction to a message.
29
+ *
30
+ * This function uses the `addReaction()` helper behind the scenes.
31
+ *
32
+ * @param channelId - The ID of the channel the message to add reactions to is in.
33
+ * @param messageId - The ID of the message to add the reactions to.
34
+ * @param reactions - The reactions to add to the message.
35
+ * @param ordered - Whether the reactions must be added in order or not.
36
+ *
37
+ * @remarks
38
+ * Requires the `READ_MESSAGE_HISTORY` permission.
39
+ *
40
+ * If nobody else has reacted to the message:
41
+ * - Requires the `ADD_REACTIONS` permission.
42
+ *
43
+ * Fires a _Message Reaction Add_ gateway event for every reaction added.
44
+ */ async addReactions (rest, channelId, messageId, reactions, ordered) {
45
+ if (!ordered) {
46
+ await Promise.all(reactions.map(async (reaction)=>{
47
+ await rest.snake.addReaction(channelId, messageId, reaction);
48
+ }));
49
+ return;
50
+ }
51
+ for (const reaction of reactions){
52
+ await rest.snake.addReaction(channelId, messageId, reaction);
53
+ }
54
+ },
55
+ /**
56
+ * Adds a role to a member.
57
+ *
58
+ * @param guildId - The ID of the guild the member to add the role to is in.
59
+ * @param userId - The user ID of the member to add the role to.
60
+ * @param roleId - The ID of the role to add to the member.
61
+ * @param {string} [reason] - An optional reason for the action, to be included in the audit log.
62
+ *
63
+ * @remarks
64
+ * Requires the `MANAGE_ROLES` permission.
65
+ *
66
+ * Fires a _Guild Member Update_ gateway event.
67
+ *
68
+ * @see {@link https://docs.discord.com/developers/resources/guild#add-guild-member-role}
69
+ */ async addRole (rest, guildId, userId, roleId, reason) {
70
+ await rest.put(rest.routes.guilds.roles.member(guildId, userId, roleId), {
71
+ reason
72
+ });
73
+ },
74
+ /**
75
+ * Adds a member to a thread.
76
+ *
77
+ * @param channelId - The ID of the thread to add the member to.
78
+ * @param userId - The user ID of the member to add to the thread.
79
+ *
80
+ * @remarks
81
+ * Requires the ability to send messages in the thread.
82
+ * Requires the thread not be archived.
83
+ *
84
+ * Fires a _Thread Members Update_ gateway event.
85
+ *
86
+ * @see {@link https://docs.discord.com/developers/resources/channel#add-thread-member}
87
+ */ async addThreadMember (rest, channelId, userId) {
88
+ await rest.put(rest.routes.channels.threads.user(channelId, userId));
89
+ },
90
+ /**
91
+ * Adds a recipient to a group DM.
92
+ *
93
+ * @param channelId - The ID of the group dm to add the user to.
94
+ * @param userId - The user ID of the user to add to the group dm.
95
+ * @param options - The options for adding the user
96
+ *
97
+ * @remarks
98
+ * Requires an OAuth2 access token with the `gdm.join` scope
99
+ *
100
+ * @see {@link https://docs.discord.com/developers/resources/channel#group-dm-add-recipient}
101
+ */ async addDmRecipient (rest, channelId, userId, options) {
102
+ await rest.put(rest.routes.channels.dmRecipient(channelId, userId), {
103
+ body: options
104
+ });
105
+ },
106
+ /**
107
+ * Adds a member to a guild.
108
+ *
109
+ * @param guildId - The ID of the thread to add the member to.
110
+ * @param userId - The user ID of the member to add to the thread.
111
+ * @param options - The options for the add of a guild member
112
+ *
113
+ * @remarks
114
+ * Requires the bot to be in the specified server
115
+ * Requires an OAuth2 access token with the `guilds.join` scope
116
+ *
117
+ * Fires a _Guild Member Add_ gateway event.
118
+ *
119
+ * @see {@link https://docs.discord.com/developers/resources/guild#add-guild-member}
120
+ */ async addGuildMember (rest, guildId, userId, options) {
121
+ return await rest.put(rest.routes.guilds.members.member(guildId, userId), {
122
+ body: options
123
+ });
124
+ },
125
+ /**
126
+ * Creates an automod rule in a guild.
127
+ *
128
+ * @param guildId - The ID of the guild to create the rule in.
129
+ * @param options - The parameters for the creation of the rule.
130
+ * @param {string} [reason] - An optional reason for the action, to be included in the audit log.
131
+ * @returns An instance of the created {@link DiscordAutoModerationRule}.
132
+ *
133
+ * @remarks
134
+ * Requires the `MANAGE_GUILD` permission.
135
+ *
136
+ * Fires an _Auto Moderation Rule Create_ gateway event.
137
+ *
138
+ * @see {@link https://docs.discord.com/developers/resources/auto-moderation#create-auto-moderation-rule}
139
+ */ async createAutomodRule (rest, guildId, options, reason) {
140
+ return await rest.post(rest.routes.guilds.automod.rules(guildId), {
141
+ body: options,
142
+ reason
143
+ });
144
+ },
145
+ /**
146
+ * Creates a channel within a guild.
147
+ *
148
+ * @param guildId - The ID of the guild to create the channel within.
149
+ * @param options - The parameters for the creation of the channel.
150
+ * @param {string} [reason] - An optional reason for the action, to be included in the audit log.
151
+ * @returns An instance of the created {@link DiscordChannel}.
152
+ *
153
+ * @remarks
154
+ * Requires the `MANAGE_CHANNELS` permission.
155
+ *
156
+ * If setting permission overwrites, only the permissions the bot user has in the guild can be allowed or denied.
157
+ *
158
+ * Setting the `MANAGE_ROLES` permission is only possible for guild administrators.
159
+ *
160
+ * Fires a _Channel Create_ gateway event.
161
+ *
162
+ * @see {@link https://docs.discord.com/developers/resources/guild#create-guild-channel}
163
+ */ async createChannel (rest, guildId, options, reason) {
164
+ return await rest.post(rest.routes.guilds.channels(guildId), {
165
+ body: options,
166
+ reason
167
+ });
168
+ },
169
+ /**
170
+ * Creates an emoji in a guild.
171
+ *
172
+ * @param guildId - The ID of the guild in which to create the emoji.
173
+ * @param options - The parameters for the creation of the emoji.
174
+ * @param {string} [reason] - An optional reason for the action, to be included in the audit log.
175
+ * @returns An instance of the created {@link DiscordEmoji}.
176
+ *
177
+ * @remarks
178
+ * Requires the `CREATE_GUILD_EXPRESSIONS` permission.
179
+ *
180
+ * Emojis have a maximum file size of 256 kilobits. Attempting to upload a larger emoji will cause the route to return 400 Bad Request.
181
+ *
182
+ * Fires a _Guild Emojis Update_ gateway event.
183
+ *
184
+ * @see {@link https://docs.discord.com/developers/resources/emoji#create-guild-emoji}
185
+ */ async createEmoji (rest, guildId, options, reason) {
186
+ return await rest.post(rest.routes.guilds.emojis(guildId), {
187
+ body: options,
188
+ reason
189
+ });
190
+ },
191
+ /**
192
+ * Creates an emoji for the application.
193
+ *
194
+ * @param options - The parameters for the creation of the emoji.
195
+ * @returns An instance of the created {@link DiscordEmoji}.
196
+ *
197
+ * @see {@link https://docs.discord.com/developers/resources/emoji#create-application-emoji}
198
+ */ async createApplicationEmoji (rest, options) {
199
+ return await rest.post(rest.routes.applicationEmojis(rest.applicationId), {
200
+ body: options
201
+ });
202
+ },
203
+ /**
204
+ * Creates a new thread in a forum channel or media channel, and sends a message within the created thread.
205
+ *
206
+ * @param channelId - The ID of the forum channel to create the thread within.
207
+ * @param options - The parameters for the creation of the thread.
208
+ * @param {string} [reason] - An optional reason for the action, to be included in the audit log.
209
+ * @returns An instance of {@link DiscordChannel} with a nested {@link DiscordChannel} object.
210
+ *
211
+ * @remarks
212
+ * Requires the `CREATE_MESSAGES` permission.
213
+ *
214
+ * Fires a _Thread Create_ gateway event.
215
+ * Fires a _Message Create_ gateway event.
216
+ *
217
+ * @see {@link https://docs.discord.com/developers/resources/channel#start-thread-in-forum-or-media-channel}
218
+ */ async createForumThread (rest, channelId, options, reason) {
219
+ return await rest.post(rest.routes.channels.forum(channelId), {
220
+ body: options,
221
+ files: options.files,
222
+ reason
223
+ });
224
+ },
225
+ /**
226
+ * Creates an application command accessible globally; across different guilds and channels.
227
+ *
228
+ * @param command - The command to create.
229
+ * @param options - Additional options for the endpoint
230
+ * @returns An instance of the created {@link DiscordApplicationCommand}.
231
+ *
232
+ * @remarks
233
+ * ⚠️ Creating a command with the same name as an existing command for your application will overwrite the old command.
234
+ * ⚠️ Global commands once created are cached for periods of __an hour__, so changes made to existing commands will take an hour to surface.
235
+ * ⚠️ You can only create up to 200 _new_ commands daily.
236
+ *
237
+ * When using the bearer token the token needs the `applications.commands.update` scope and must be a `Client grant` token.
238
+ * You will be able to update only your own application commands
239
+ *
240
+ * @see {@link https://docs.discord.com/developers/interactions/application-commands#create-global-application-command}
241
+ */ async createGlobalApplicationCommand (rest, command, options) {
242
+ const restOptions = {
243
+ body: command
244
+ };
245
+ if (options?.bearerToken) {
246
+ restOptions.unauthorized = true;
247
+ restOptions.headers = {
248
+ authorization: `Bearer ${options.bearerToken}`
249
+ };
250
+ }
251
+ return await rest.post(rest.routes.interactions.commands.commands(rest.applicationId), restOptions);
252
+ },
253
+ /**
254
+ * Creates an application command only accessible in a specific guild.
255
+ *
256
+ * @param command - The command to create.
257
+ * @param guildId - The ID of the guild to create the command for.
258
+ * @param options - Additional options for the endpoint
259
+ * @returns An instance of the created {@link DiscordApplicationCommand}.
260
+ *
261
+ * @remarks
262
+ * ⚠️ Creating a command with the same name as an existing command for your application will overwrite the old command.
263
+ * ⚠️ You can only create up to 200 _new_ commands daily.
264
+ *
265
+ * When using the bearer token the token needs the `applications.commands.update` scope and must be a `Client grant` token.
266
+ * You will be able to update only your own application commands
267
+ *
268
+ * @see {@link https://docs.discord.com/developers/interactions/application-commands#create-guild-application-command}
269
+ */ async createGuildApplicationCommand (rest, command, guildId, options) {
270
+ const restOptions = {
271
+ body: command
272
+ };
273
+ if (options?.bearerToken) {
274
+ restOptions.unauthorized = true;
275
+ restOptions.headers = {
276
+ authorization: `Bearer ${options.bearerToken}`
277
+ };
278
+ }
279
+ return await rest.post(rest.routes.interactions.commands.guilds.all(rest.applicationId, guildId), restOptions);
280
+ },
281
+ /**
282
+ * Create a new sticker for the guild.
283
+ *
284
+ * @param guildId The ID of the guild to get
285
+ * @param {string} [reason] - An optional reason for the action, to be included in the audit log.
286
+ * @return A {@link DiscordSticker}
287
+ *
288
+ * @remarks
289
+ * Requires the `CREATE_GUILD_EXPRESSIONS` permission.
290
+ * Fires a Guild Stickers Update Gateway event.
291
+ * Every guilds has five free sticker slots by default, and each Boost level will grant access to more slots.
292
+ * Lottie stickers can only be uploaded on guilds that have either the `VERIFIED` and/or the `PARTNERED` guild feature.
293
+ *
294
+ * @see {@link https://docs.discord.com/developers/resources/sticker#create-guild-sticker}
295
+ */ async createGuildSticker (rest, guildId, options, reason) {
296
+ const form = new FormData();
297
+ form.append('file', options.file.blob, options.file.name);
298
+ form.append('name', options.name);
299
+ form.append('description', options.description);
300
+ form.append('tags', options.tags);
301
+ return await rest.post(rest.routes.guilds.stickers(guildId), {
302
+ body: form,
303
+ reason
304
+ });
305
+ },
306
+ /**
307
+ * Creates a template from a guild.
308
+ *
309
+ * @param guildId - The ID of the guild to create the template from.
310
+ * @param options - The parameters for the creation of the template.
311
+ * @returns An instance of the created {@link DiscordTemplate}.
312
+ *
313
+ * @remarks
314
+ * Requires the `MANAGE_GUILD` permission.
315
+ *
316
+ * Fires a _Guild Update_ gateway event.
317
+ *
318
+ * @see {@link https://docs.discord.com/developers/resources/guild-template#create-guild-template}
319
+ */ async createGuildTemplate (rest, guildId, options) {
320
+ return await rest.post(rest.routes.guilds.templates.all(guildId), {
321
+ body: options
322
+ });
323
+ },
324
+ /**
325
+ * Creates an invite to a channel in a guild.
326
+ *
327
+ * @param channelId - The ID of the channel to create the invite to.
328
+ * @param options - The parameters for the creation of the invite.
329
+ * @param {string} [reason] - An optional reason for the action, to be included in the audit log.
330
+ * @returns An instance of the created {@link DiscordInvite}.
331
+ *
332
+ * @remarks
333
+ * Requires the `CREATE_INSTANT_INVITE` permission.
334
+ *
335
+ * Fires an _Invite Create_ gateway event.
336
+ *
337
+ * @privateRemarks
338
+ * The request body is not optional, and an empty JSON object must be sent regardless of whether any fields are being transmitted.
339
+ *
340
+ * @see {@link https://docs.discord.com/developers/resources/channel#create-channel-invite}
341
+ */ async createInvite (rest, channelId, options, reason) {
342
+ options ??= {};
343
+ if (!options.targetUsersFile) {
344
+ return await rest.post(rest.routes.channels.invites(channelId), {
345
+ body: options,
346
+ reason
347
+ });
348
+ }
349
+ // When we have to upload a file, we need to use FormData, and all other fields need to be part of the payload_json field.
350
+ const form = new FormData();
351
+ form.append('payload_json', JSON.stringify(rest.changeToDiscordFormat({
352
+ ...options,
353
+ targetUsersFile: undefined
354
+ })));
355
+ form.append('target_users_file', options.targetUsersFile);
356
+ return await rest.post(rest.routes.channels.invites(channelId), {
357
+ body: form,
358
+ reason
359
+ });
360
+ },
361
+ /**
362
+ * Get guild role member counts
363
+ *
364
+ * Returns a map of role IDs to the number of members with the role. Does not include the \@everyone role.
365
+ *
366
+ * @param guildId - The ID of the guild to get role member counts for.
367
+ *
368
+ * @see {@link https://docs.discord.com/developers/resources/guild#get-guild-role-member-counts}
369
+ */ async getGuildRoleMemberCounts (rest, guildId) {
370
+ return await rest.get(rest.routes.guilds.roles.memberCounts(guildId));
371
+ },
372
+ /**
373
+ * Creates a role in a guild.
374
+ *
375
+ * @param guildId - The ID of the guild to create the role in.
376
+ * @param options - The parameters for the creation of the role.
377
+ * @param {string} [reason] - An optional reason for the action, to be included in the audit log.
378
+ * @returns An instance of the created {@link DiscordRole}.
379
+ *
380
+ * @remarks
381
+ * Requires the `MANAGE_ROLES` permission.
382
+ *
383
+ * Fires a _Guild Role Create_ gateway event.
384
+ *
385
+ * @see {@link https://docs.discord.com/developers/resources/guild#create-guild-role}
386
+ */ async createRole (rest, guildId, options, reason) {
387
+ return await rest.post(rest.routes.guilds.roles.all(guildId), {
388
+ body: options,
389
+ reason
390
+ });
391
+ },
392
+ /**
393
+ * Creates a scheduled event in a guild.
394
+ *
395
+ * @param guildId - The ID of the guild to create the scheduled event in.
396
+ * @param options - The parameters for the creation of the scheduled event.
397
+ * @param {string} [reason] - An optional reason for the action, to be included in the audit log.
398
+ * @returns An instance of the created {@link DiscordScheduledEvent}.
399
+ *
400
+ * @remarks
401
+ * Requires the `MANAGE_EVENTS` permission.
402
+ *
403
+ * A guild can only have a maximum of 100 events with a status of {@link ScheduledEventStatus}.Active or {@link ScheduledEventStatus}.Scheduled (inclusive).
404
+ *
405
+ * Fires a _Guild Scheduled Event Create_ gateway event.
406
+ *
407
+ * @see {@link https://docs.discord.com/developers/resources/guild-scheduled-event#create-guild-scheduled-event}
408
+ */ async createScheduledEvent (rest, guildId, options, reason) {
409
+ return await rest.post(rest.routes.guilds.events.events(guildId), {
410
+ body: options,
411
+ reason
412
+ });
413
+ },
414
+ /**
415
+ * Creates a stage instance associated with a stage channel.
416
+ *
417
+ * @param options - The parameters for the creation of the stage instance.
418
+ * @param {string} [reason] - An optional reason for the action, to be included in the audit log.
419
+ * @returns An instance of the created {@link DiscordStageInstance}.
420
+ *
421
+ * @remarks
422
+ * Requires the user to be a moderator of the stage channel.
423
+ *
424
+ * Fires a _Stage Instance Create_ gateway event.
425
+ *
426
+ * @see {@link https://docs.discord.com/developers/resources/stage-instance#create-stage-instance}
427
+ */ async createStageInstance (rest, options, reason) {
428
+ return await rest.post(rest.routes.channels.stages(), {
429
+ body: options,
430
+ reason
431
+ });
432
+ },
433
+ /**
434
+ * Creates a webhook.
435
+ *
436
+ * @param channelId - The ID of the channel to create the webhook in.
437
+ * @param options - The parameters for the creation of the webhook.
438
+ * @param {string} [reason] - An optional reason for the action, to be included in the audit log.
439
+ * @returns An instance of the created {@link DiscordWebhook}.
440
+ *
441
+ * @remarks
442
+ * Requires the `MANAGE_WEBHOOKS` permission.
443
+ *
444
+ * ⚠️ The webhook name must not contain the substrings 'clyde', or 'discord' (case-insensitive).
445
+ *
446
+ * Fires a _Webhooks Update_ gateway event.
447
+ *
448
+ * @see {@link https://docs.discord.com/developers/resources/webhook#create-webhook}
449
+ */ async createWebhook (rest, channelId, options, reason) {
450
+ return await rest.post(rest.routes.channels.webhooks(channelId), {
451
+ body: options,
452
+ reason
453
+ });
454
+ },
455
+ /**
456
+ * Deletes an automod rule.
457
+ *
458
+ * @param guildId - The ID of the guild to delete the rule from.
459
+ * @param ruleId - The ID of the automod rule to delete.
460
+ * @param {string} [reason] - An optional reason for the action, to be included in the audit log.
461
+ *
462
+ * @remarks
463
+ * Requires the `MANAGE_GUILD` permission.
464
+ *
465
+ * Fires an _Auto Moderation Rule Delete_ gateway event.
466
+ *
467
+ * @see {@link https://docs.discord.com/developers/resources/auto-moderation#delete-auto-moderation-rule}
468
+ */ async deleteAutomodRule (rest, guildId, ruleId, reason) {
469
+ await rest.delete(rest.routes.guilds.automod.rule(guildId, ruleId), {
470
+ reason
471
+ });
472
+ },
473
+ /**
474
+ * Set a voice channel’s status
475
+ *
476
+ * @param channelId - The ID of the channel to set the status of.
477
+ * @param options - The parameters for the status of the voice channel.
478
+ * @param {string} [reason] - An optional reason for the action, to be included in the audit log.
479
+ * @returns Nothing
480
+ *
481
+ * @remarks
482
+ * Requires the `SET_VOICE_CHANNEL_STATUS` permission, and additionally the `MANAGE_CHANNELS` permission if the current user is not connected to the voice channel.
483
+ *
484
+ * Fires a _Voice Channel Status Update_ Gateway event.
485
+ *
486
+ * @see {@link https://docs.discord.com/developers/resources/channel#set-voice-channel-status}
487
+ */ async setVoiceChannelStatus (rest, channelId, options, reason) {
488
+ await rest.put(rest.routes.channels.voiceStatus(channelId), {
489
+ body: options,
490
+ reason
491
+ });
492
+ },
493
+ /**
494
+ * Deletes a channel from within a guild.
495
+ *
496
+ * @param channelId - The ID of the channel to delete.
497
+ * @param {string} [reason] - An optional reason for the action, to be included in the audit log.
498
+ * @returns nothing
499
+ *
500
+ * @remarks
501
+ * For community guilds, the _Rules_, _Guidelines_ and _Community Update_ channels cannot be deleted.
502
+ *
503
+ * If the channel is a thread:
504
+ * - Requires the `MANAGE_THREADS` permission.
505
+ *
506
+ * - Fires a _Thread Delete_ gateway event.
507
+ *
508
+ * Otherwise:
509
+ * - Requires the `MANAGE_CHANNELS` permission.
510
+ *
511
+ * - ⚠️ Deleting a category channel does not delete its child channels.
512
+ * Instead, they will have their `parent_id` property removed, and a `Channel Update` gateway event will fire for each of them.
513
+ *
514
+ * - Fires a _Channel Delete_ gateway event.
515
+ *
516
+ * @see {@link https://docs.discord.com/developers/resources/channel#deleteclose-channel}
517
+ */ async deleteChannel (rest, channelId, reason) {
518
+ await rest.delete(rest.routes.channels.channel(channelId), {
519
+ reason
520
+ });
521
+ },
522
+ /**
523
+ * Deletes a permission override for a user or role in a channel.
524
+ *
525
+ * @param channelId - The ID of the channel to delete the permission override of.
526
+ * @param overwriteId - The ID of the permission override to delete.
527
+ * @param {string} [reason] - An optional reason for the action, to be included in the audit log.
528
+ *
529
+ * @remarks
530
+ * Requires the `MANAGE_ROLES` permission.
531
+ *
532
+ * Fires a _Channel Update_ gateway event.
533
+ *
534
+ * @see {@link https://docs.discord.com/developers/resources/channel#delete-channel-permission}
535
+ */ async deleteChannelPermissionOverride (rest, channelId, overwriteId, reason) {
536
+ await rest.delete(rest.routes.channels.overwrite(channelId, overwriteId), {
537
+ reason
538
+ });
539
+ },
540
+ /**
541
+ * Deletes an emoji from a guild.
542
+ *
543
+ * @param guildId - The ID of the guild from which to delete the emoji.
544
+ * @param id - The ID of the emoji to delete.
545
+ * @param {string} [reason] - An optional reason for the action, to be included in the audit log.
546
+ *
547
+ * @remarks
548
+ * For emojis created by the current user, requires either the `CREATE_GUILD_EXPRESSIONS` or `MANAGE_GUILD_EXPRESSIONS` permission.
549
+ * For other emojis, requires the `MANAGE_GUILD_EXPRESSIONS` permission.
550
+ *
551
+ * Fires a _Guild Emojis Update_ gateway event.
552
+ *
553
+ * @see {@link https://docs.discord.com/developers/resources/emoji#delete-guild-emoji}
554
+ */ async deleteEmoji (rest, guildId, id, reason) {
555
+ await rest.delete(rest.routes.guilds.emoji(guildId, id), {
556
+ reason
557
+ });
558
+ },
559
+ /**
560
+ * Deletes an emoji from the application.
561
+ *
562
+ * @param id - The ID of the emoji to delete.
563
+ *
564
+ * @see {@link https://docs.discord.com/developers/resources/emoji#delete-application-emoji}
565
+ */ async deleteApplicationEmoji (rest, id) {
566
+ await rest.delete(rest.routes.applicationEmoji(rest.applicationId, id));
567
+ },
568
+ /**
569
+ * Deletes a follow-up message to an interaction.
570
+ *
571
+ * @param token - The interaction token to use, provided in the original interaction.
572
+ * @param messageId - The ID of the message to delete.
573
+ *
574
+ * @remarks
575
+ * Unlike `deleteMessage()`, this endpoint allows the bot user to act without needing to see the channel the message is in.
576
+ *
577
+ * Fires a _Message Delete_ event.
578
+ *
579
+ * @see {@link https://docs.discord.com/developers/interactions/receiving-and-responding#delete-followup-message}
580
+ */ async deleteFollowupMessage (rest, token, messageId) {
581
+ await rest.delete(rest.routes.interactions.responses.message(rest.applicationId, token, messageId), {
582
+ unauthorized: true
583
+ });
584
+ },
585
+ /**
586
+ * Deletes an application command registered globally.
587
+ *
588
+ * @param commandId - The ID of the command to delete.
589
+ *
590
+ * @see {@link https://docs.discord.com/developers/interactions/application-commands#delete-global-application-command}
591
+ */ async deleteGlobalApplicationCommand (rest, commandId) {
592
+ await rest.delete(rest.routes.interactions.commands.command(rest.applicationId, commandId));
593
+ },
594
+ /**
595
+ * Deletes an application command registered in a guild.
596
+ *
597
+ * @param guildId - The ID of the guild to delete the command from.
598
+ * @param commandId - The ID of the command to delete from the guild.
599
+ *
600
+ * @see {@link https://docs.discord.com/developers/interactions/application-commands#delete-guild-application-command}
601
+ */ async deleteGuildApplicationCommand (rest, commandId, guildId) {
602
+ await rest.delete(rest.routes.interactions.commands.guilds.one(rest.applicationId, guildId, commandId));
603
+ },
604
+ /**
605
+ * Delete a new sticker for the guild.
606
+ *
607
+ * @param guildId The ID of the guild to get
608
+ * @param {string} [reason] - An optional reason for the action, to be included in the audit log.
609
+ * @return A {@link DiscordSticker}
610
+ *
611
+ * @remarks
612
+ * For stickers created by the current user, requires either the `CREATE_GUILD_EXPRESSIONS` or `MANAGE_GUILD_EXPRESSIONS` permission.
613
+ * For other stickers, requires the `MANAGE_GUILD_EXPRESSIONS` permission.
614
+ * Fires a Guild Stickers Update Gateway event.
615
+ * Every guilds has five free sticker slots by default, and each Boost level will grant access to more slots.
616
+ * Lottie stickers can only be uploaded on guilds that have either the `VERIFIED` and/or the `PARTNERED` guild feature.
617
+ *
618
+ * @see {@link https://docs.discord.com/developers/resources/sticker#delete-guild-sticker}
619
+ */ async deleteGuildSticker (rest, guildId, stickerId, reason) {
620
+ await rest.delete(rest.routes.guilds.sticker(guildId, stickerId), {
621
+ reason
622
+ });
623
+ },
624
+ /**
625
+ * Deletes a template from a guild.
626
+ *
627
+ * @param guildId - The ID of the guild to delete the template from.
628
+ * @param templateCode - The code of the template to delete.
629
+ *
630
+ * @remarks
631
+ * Requires the `MANAGE_GUILD` permission.
632
+ *
633
+ * Fires a _Guild Update_ gateway event.
634
+ *
635
+ * @see {@link https://docs.discord.com/developers/resources/guild-template#delete-guild-template}
636
+ */ async deleteGuildTemplate (rest, guildId, templateCode) {
637
+ await rest.delete(rest.routes.guilds.templates.guild(guildId, templateCode));
638
+ },
639
+ /**
640
+ * Deletes an integration attached to a guild.
641
+ *
642
+ * @param guildId - The ID of the guild from which to delete the integration.
643
+ * @param integrationId - The ID of the integration to delete from the guild.
644
+ * @param {string} [reason] - An optional reason for the action, to be included in the audit log.
645
+ *
646
+ * @remarks
647
+ * Requires the `MANAGE_GUILD` permission.
648
+ *
649
+ * Deletes all webhooks associated with the integration, and kicks the associated bot if there is one.
650
+ *
651
+ * Fires a _Guild Integrations Update_ gateway event.
652
+ * Fires a _Integration Delete_ gateway event.
653
+ *
654
+ * @see {@link https://docs.discord.com/developers/resources/guild#delete-guild-integration}
655
+ */ async deleteIntegration (rest, guildId, integrationId, reason) {
656
+ await rest.delete(rest.routes.guilds.integration(guildId, integrationId), {
657
+ reason
658
+ });
659
+ },
660
+ /**
661
+ * Deletes an invite to a channel.
662
+ *
663
+ * @param inviteCode - The invite code of the invite to delete.
664
+ * @param {string} [reason] - An optional reason for the action, to be included in the audit log.
665
+ *
666
+ * @remarks
667
+ * Requires the `MANAGE_CHANNELS` permission.
668
+ *
669
+ * Fires an _Invite Delete_ gateway event.
670
+ *
671
+ * @see {@link https://docs.discord.com/developers/resources/channel#delete-channel-invite}
672
+ */ async deleteInvite (rest, inviteCode, reason) {
673
+ await rest.delete(rest.routes.guilds.invite(inviteCode), {
674
+ reason
675
+ });
676
+ },
677
+ /**
678
+ * Gets the users allowed to see and accept this invite.
679
+ *
680
+ * @param inviteCode - The invite code of the invite to update.
681
+ * @returns CSV file containing the user IDs with the header `user_id` and each user ID from the original file
682
+ *
683
+ * @remarks
684
+ * Requires called to be the inviter, or have `MANAGE_GUILD` permission, or have `VIEW_AUDIT_LOG` permission.
685
+ *
686
+ * @see {@link https://docs.discord.com/developers/resources/invite#get-target-users}
687
+ */ async getTargetUsers (rest, inviteCode) {
688
+ return await rest.get(rest.routes.guilds.inviteTargetUsers(inviteCode));
689
+ },
690
+ /**
691
+ * Updates the users allowed to see and accept this invite.
692
+ *
693
+ * @param inviteCode - The invite code of the invite to update.
694
+ * @param targetUsersFile - A CSV file with a single column of user IDs for all the users able to accept this invite
695
+ *
696
+ * @remarks
697
+ * Requires the caller to be the inviter or have the `MANAGE_GUILD` permission.
698
+ *
699
+ * Uploading a file with invalid user IDs will result in a 400 with the invalid IDs described.
700
+ *
701
+ * @see {@link https://docs.discord.com/developers/resources/invite#update-target-users}
702
+ */ async updateTargetUsers (rest, inviteCode, targetUsersFile) {
703
+ const form = new FormData();
704
+ form.append('target_users_file', targetUsersFile);
705
+ await rest.put(rest.routes.guilds.inviteTargetUsers(inviteCode), {
706
+ body: form
707
+ });
708
+ },
709
+ /**
710
+ * Processing target users from a CSV when creating or updating an invite is done asynchronously. This endpoint allows you to check the status of that job.
711
+ *
712
+ * @param inviteCode - The invite code of the invite to check the target users job status for.
713
+ * @returns An object containing the status of the target users job.
714
+ *
715
+ * @remarks
716
+ * Requires the caller to be the inviter, or have `MANAGE_GUILD` permission, or have `VIEW_AUDIT_LOG` permission.
717
+ *
718
+ * @see {@link https://docs.discord.com/developers/resources/invite#get-target-users-job-status}
719
+ */ async getTargetUsersJobStatus (rest, inviteCode) {
720
+ return await rest.get(rest.routes.guilds.inviteTargetUsersJobStatus(inviteCode));
721
+ },
722
+ /**
723
+ * Deletes a message from a channel.
724
+ *
725
+ * @param channelId - The ID of the channel to delete the message from.
726
+ * @param messageId - The ID of the message to delete from the channel.
727
+ * @param {string} [reason] - An optional reason for the action, to be included in the audit log.
728
+ *
729
+ * @remarks
730
+ * If not deleting own message:
731
+ * - Requires the `MANAGE_MESSAGES` permission.
732
+ *
733
+ * Fires a _Message Delete_ gateway event.
734
+ *
735
+ * @see {@link https://docs.discord.com/developers/resources/channel#delete-message}
736
+ */ async deleteMessage (rest, channelId, messageId, reason) {
737
+ await rest.delete(rest.routes.channels.message(channelId, messageId), {
738
+ reason
739
+ });
740
+ },
741
+ /**
742
+ * Deletes multiple messages from a channel.
743
+ *
744
+ * @param channelId - The ID of the channel to delete the messages from.
745
+ * @param messageIds - The IDs of the messages to delete from the channel.
746
+ * @param {string} [reason] - An optional reason for the action, to be included in the audit log.
747
+ *
748
+ * @remarks
749
+ * Requires the `MANAGE_MESSAGES` permission.
750
+ *
751
+ * ⚠️ Messages older than 2 weeks old cannot be deleted.
752
+ *
753
+ * Fires a _Message Delete Bulk_ gateway event.
754
+ *
755
+ * @see {@link https://docs.discord.com/developers/resources/channel#bulk-delete-messages}
756
+ */ async deleteMessages (rest, channelId, messageIds, reason) {
757
+ await rest.post(rest.routes.channels.bulk(channelId), {
758
+ body: {
759
+ messages: messageIds.slice(0, 100).map((id)=>id.toString())
760
+ },
761
+ reason
762
+ });
763
+ },
764
+ /**
765
+ * Deletes the initial message response to an interaction.
766
+ *
767
+ * @param token - The interaction token to use, provided in the original interaction.
768
+ *
769
+ * @remarks
770
+ * Unlike `deleteMessage()`, this endpoint allows the bot user to act without needing to see the channel the message is in.
771
+ *
772
+ * Fires a _Message Delete_ event.
773
+ *
774
+ * @see {@link https://docs.discord.com/developers/interactions/receiving-and-responding#delete-original-interaction-response}
775
+ */ async deleteOriginalInteractionResponse (rest, token) {
776
+ await rest.delete(rest.routes.interactions.responses.original(rest.applicationId, token), {
777
+ unauthorized: true
778
+ });
779
+ },
780
+ /**
781
+ * Deletes a reaction added by the bot user from a message.
782
+ *
783
+ * @param channelId - The ID of the channel the message to delete the reaction from is in.
784
+ * @param messageId - The ID of the message to delete the reaction from.
785
+ * @param reaction - The reaction to delete from the message.
786
+ *
787
+ * @remarks
788
+ * Requires the `READ_MESSAGE_HISTORY` permission.
789
+ *
790
+ * Fires a _Message Reaction Remove_ gateway event.
791
+ *
792
+ * @see {@link https://docs.discord.com/developers/resources/channel#delete-own-reaction}
793
+ */ async deleteOwnReaction (rest, channelId, messageId, reaction) {
794
+ reaction = processReactionString(reaction);
795
+ await rest.delete(rest.routes.channels.reactions.bot(channelId, messageId, reaction));
796
+ },
797
+ /**
798
+ * Deletes all reactions for all emojis from a message.
799
+ *
800
+ * @param channelId - The ID of the channel the message to delete the reactions from is in.
801
+ * @param messageId - The ID of the message to delete the reactions from.
802
+ *
803
+ * @remarks
804
+ * Requires the `READ_MESSAGE_HISTORY` permission.
805
+ *
806
+ * Requires the `MANAGE_MESSAGES` permission.
807
+ *
808
+ * Fires a _Message Reaction Remove All_ gateway event.
809
+ *
810
+ * @see {@link https://docs.discord.com/developers/resources/channel#delete-all-reactions}
811
+ */ async deleteReactionsAll (rest, channelId, messageId) {
812
+ await rest.delete(rest.routes.channels.reactions.all(channelId, messageId));
813
+ },
814
+ /**
815
+ * Deletes all reactions for an emoji from a message.
816
+ *
817
+ * @param channelId - The ID of the channel the message to delete the reactions from is in.
818
+ * @param messageId - The ID of the message to delete the reactions from.
819
+ * @param reaction - The reaction to remove from the message.
820
+ *
821
+ * @remarks
822
+ * Requires the `READ_MESSAGE_HISTORY` permission.
823
+ *
824
+ * Requires the `MANAGE_MESSAGES` permission.
825
+ *
826
+ * Fires a _Message Reaction Remove Emoji_ gateway event.
827
+ *
828
+ * @see {@link https://docs.discord.com/developers/resources/channel#delete-all-reactions-for-emoji}
829
+ */ async deleteReactionsEmoji (rest, channelId, messageId, reaction) {
830
+ reaction = processReactionString(reaction);
831
+ await rest.delete(rest.routes.channels.reactions.emoji(channelId, messageId, reaction));
832
+ },
833
+ /**
834
+ * Deletes a role from a guild.
835
+ *
836
+ * @param guildId - The ID of the guild to delete the role from.
837
+ * @param roleId - The ID of the role to delete.
838
+ * @param {string} [reason] - An optional reason for the action, to be included in the audit log.
839
+ *
840
+ * @remarks
841
+ * Requires the `MANAGE_ROLES` permission.
842
+ *
843
+ * Fires a _Guild Role Delete_ gateway event.
844
+ *
845
+ * @see {@link https://docs.discord.com/developers/resources/guild#delete-guild-role}
846
+ */ async deleteRole (rest, guildId, roleId, reason) {
847
+ await rest.delete(rest.routes.guilds.roles.one(guildId, roleId), {
848
+ reason
849
+ });
850
+ },
851
+ /**
852
+ * Deletes a scheduled event from a guild.
853
+ *
854
+ * @param guildId - The ID of the guild to delete the scheduled event from.
855
+ * @param eventId - The ID of the scheduled event to delete.
856
+ *
857
+ * @remarks
858
+ * Requires the `MANAGE_EVENTS` permission.
859
+ *
860
+ * Fires a _Guild Scheduled Event Delete_ gateway event.
861
+ *
862
+ * @see {@link https://docs.discord.com/developers/resources/guild-scheduled-event#delete-guild-scheduled-event}
863
+ */ async deleteScheduledEvent (rest, guildId, eventId) {
864
+ await rest.delete(rest.routes.guilds.events.event(guildId, eventId));
865
+ },
866
+ /**
867
+ * Deletes the stage instance associated with a stage channel, if one exists.
868
+ *
869
+ * @param channelId - The ID of the stage channel the stage instance is associated with.
870
+ * @param {string} [reason] - An optional reason for the action, to be included in the audit log.
871
+ *
872
+ * @remarks
873
+ * Requires the user to be a moderator of the stage channel.
874
+ *
875
+ * Fires a _Stage Instance Delete_ gateway event.
876
+ *
877
+ * @see {@link https://docs.discord.com/developers/resources/stage-instance#delete-stage-instance}
878
+ */ async deleteStageInstance (rest, channelId, reason) {
879
+ await rest.delete(rest.routes.channels.stage(channelId), {
880
+ reason
881
+ });
882
+ },
883
+ /**
884
+ * Deletes a user's reaction from a message.
885
+ *
886
+ * @param channelId - The ID of the channel the message to delete the reaction from is in.
887
+ * @param messageId - The ID of the message to delete the reaction from.
888
+ * @param userId - The ID of the user whose reaction to delete.
889
+ * @param reaction - The reaction to delete from the message.
890
+ *
891
+ * @remarks
892
+ * Requires the `READ_MESSAGE_HISTORY` permission.
893
+ *
894
+ * Requires the `MANAGE_MESSAGES` permission.
895
+ *
896
+ * Fires a _Message Reaction Remove_ gateway event.
897
+ *
898
+ * @see {@link https://docs.discord.com/developers/resources/channel#delete-user-reaction}
899
+ */ async deleteUserReaction (rest, channelId, messageId, userId, reaction) {
900
+ reaction = processReactionString(reaction);
901
+ await rest.delete(rest.routes.channels.reactions.user(channelId, messageId, reaction, userId));
902
+ },
903
+ /**
904
+ * Deletes a webhook.
905
+ *
906
+ * @param webhookId - The ID of the webhook to delete.
907
+ *
908
+ * @remarks
909
+ * Requires the `MANAGE_WEBHOOKS` permission.
910
+ *
911
+ * Fires a _Webhooks Update_ gateway event.
912
+ *
913
+ * @see {@link https://docs.discord.com/developers/resources/webhook#delete-webhook}
914
+ */ async deleteWebhook (rest, webhookId, reason) {
915
+ await rest.delete(rest.routes.webhooks.id(webhookId), {
916
+ reason
917
+ });
918
+ },
919
+ /**
920
+ * Deletes a webhook message.
921
+ *
922
+ * @param webhookId - The ID of the webhook to delete the message belonging to.
923
+ * @param token - The webhook token, used to manage the webhook.
924
+ * @param messageId - The ID of the message to delete.
925
+ * @param options - The parameters for the deletion of the message.
926
+ *
927
+ * @remarks
928
+ * Fires a _Message Delete_ gateway event.
929
+ *
930
+ * @see {@link https://docs.discord.com/developers/resources/webhook#delete-webhook}
931
+ */ async deleteWebhookMessage (rest, webhookId, token, messageId, options) {
932
+ await rest.delete(rest.routes.webhooks.message(webhookId, token, messageId, options), {
933
+ unauthorized: true
934
+ });
935
+ },
936
+ /**
937
+ * Deletes a webhook message using the webhook token, thereby bypassing the need for authentication + permissions.
938
+ *
939
+ * @param webhookId - The ID of the webhook to delete the message belonging to.
940
+ * @param token - The webhook token, used to delete the webhook.
941
+ *
942
+ * @remarks
943
+ * Fires a _Message Delete_ gateway event.
944
+ *
945
+ * @see {@link https://docs.discord.com/developers/resources/webhook#delete-webhook-with-token}
946
+ */ async deleteWebhookWithToken (rest, webhookId, token) {
947
+ await rest.delete(rest.routes.webhooks.webhook(webhookId, token), {
948
+ unauthorized: true
949
+ });
950
+ },
951
+ /**
952
+ * Edits the permissions for a guild application command.
953
+ *
954
+ * @param guildId - The ID of the guild the command is registered in.
955
+ * @param commandId - The ID of the command to edit the permissions of.
956
+ * @param bearerToken - The bearer token to use to make the request.
957
+ * @param options - The parameters for the edit of the command permissions.
958
+ * @returns An instance of the edited {@link DiscordGuildApplicationCommandPermissions}.
959
+ *
960
+ * @remarks
961
+ * The bearer token requires the `applications.commands.permissions.update` scope to be enabled, and to have access to the guild whose ID has been provided in the parameters.
962
+ *
963
+ * @see {@link https://docs.discord.com/developers/interactions/application-commands#edit-application-command-permissions}
964
+ */ async editApplicationCommandPermissions (rest, guildId, commandId, bearerToken, options) {
965
+ return await rest.put(rest.routes.interactions.commands.permission(rest.applicationId, guildId, commandId), {
966
+ body: {
967
+ permissions: options
968
+ },
969
+ headers: {
970
+ authorization: `Bearer ${bearerToken}`
971
+ }
972
+ });
973
+ },
974
+ /**
975
+ * Edits an automod rule.
976
+ *
977
+ * @param guildId - The ID of the guild to edit the rule in.
978
+ * @param ruleId - The ID of the rule to edit.
979
+ * @param options - The parameters for the edit of the rule.
980
+ * @param {string} [reason] - An optional reason for the action, to be included in the audit log.
981
+ * @returns An instance of the edited {@link DiscordAutoModerationRule}.
982
+ *
983
+ * @remarks
984
+ * Requires the `MANAGE_GUILD` permission.
985
+ *
986
+ * Fires an _Auto Moderation Rule Update_ gateway event.
987
+ *
988
+ * @see {@link https://docs.discord.com/developers/resources/auto-moderation#modify-auto-moderation-rule}
989
+ */ async editAutomodRule (rest, guildId, ruleId, options, reason) {
990
+ return await rest.patch(rest.routes.guilds.automod.rule(guildId, ruleId), {
991
+ body: options,
992
+ reason
993
+ });
994
+ },
995
+ /**
996
+ * Modifies the bot's username, avatar or banner.
997
+ *
998
+ * @param options - The parameters for the edit of the bot's profile.
999
+ * @returns An instance of the edited {@link DiscordUser}.
1000
+ *
1001
+ * @remarks
1002
+ * Editing the `username` may cause the bot's discriminator to be randomized.
1003
+ *
1004
+ * `avatar` and `banner` must to be a Data URI scheme. {@link urlToBase64} from `@discordeno/utils` can be used to convert a URL to a Data URI scheme.
1005
+ *
1006
+ * @see {@link https://docs.discord.com/developers/resources/user#modify-current-user}
1007
+ */ async editBotProfile (rest, options) {
1008
+ return await rest.patch(rest.routes.currentUser(), {
1009
+ body: options
1010
+ });
1011
+ },
1012
+ /**
1013
+ * Edits a channel's settings.
1014
+ *
1015
+ * @param channelId - The ID of the channel to edit.
1016
+ * @param options - The parameters for the edit of the channel.
1017
+ * @param {string} [reason] - An optional reason for the action, to be included in the audit log.
1018
+ * @returns An instance of the edited {@link DiscordChannel}.
1019
+ *
1020
+ * @remarks
1021
+ * If editing a channel of type {@link ChannelTypes}.GroupDm:
1022
+ * - Fires a _Channel Update_ gateway event.
1023
+ *
1024
+ * If editing a thread channel:
1025
+ * - Requires the `MANAGE_THREADS` permission __unless__ if setting the `archived` property to `false` when the `locked` property is also `false`, in which case only the `SEND_MESSAGES` permission is required.
1026
+ *
1027
+ * - Fires a _Thread Update_ gateway event.
1028
+ *
1029
+ * If editing a guild channel:
1030
+ * - Requires the `MANAGE_CHANNELS` permission.
1031
+ *
1032
+ * - If modifying permission overrides:
1033
+ * - Requires the `MANAGE_ROLES` permission.
1034
+ *
1035
+ * - Only permissions the bot user has in the guild or parent channel can be allowed/denied __unless__ the bot user has a `MANAGE_ROLES` permission override in the channel.
1036
+ *
1037
+ * - If modifying a channel of type {@link ChannelTypes}.GuildCategory:
1038
+ * - Fires a _Channel Update_ gateway event for each child channel impacted in this change.
1039
+ * - Otherwise:
1040
+ * - Fires a _Channel Update_ gateway event.
1041
+ */ async editChannel (rest, channelId, options, reason) {
1042
+ return await rest.patch(rest.routes.channels.channel(channelId), {
1043
+ body: options,
1044
+ reason
1045
+ });
1046
+ },
1047
+ /**
1048
+ * Edits the permission overrides for a user or role in a channel.
1049
+ *
1050
+ * @param channelId - The ID of the channel to edit the permission overrides of.
1051
+ * @param options - The permission override.
1052
+ * @param {string} [reason] - An optional reason for the action, to be included in the audit log.
1053
+ *
1054
+ * @remarks
1055
+ * Requires the `MANAGE_ROLES` permission.
1056
+ *
1057
+ * Only permissions the bot user has in the guild or parent channel can be allowed/denied __unless__ the bot user has a `MANAGE_ROLES` permission override in the channel.
1058
+ *
1059
+ * Fires a _Channel Update_ gateway event.
1060
+ *
1061
+ * @see {@link https://docs.discord.com/developers/resources/channel#edit-channel-permissions}
1062
+ */ async editChannelPermissionOverrides (rest, channelId, options, reason) {
1063
+ await rest.put(rest.routes.channels.overwrite(channelId, options.id), {
1064
+ body: options,
1065
+ reason
1066
+ });
1067
+ },
1068
+ /**
1069
+ * Edits the positions of a set of channels in a guild.
1070
+ *
1071
+ * @param guildId - The ID of the guild in which to edit the positions of the channels.
1072
+ * @param channelPositions - A set of objects defining the updated positions of the channels.
1073
+ *
1074
+ * @remarks
1075
+ * Requires the `MANAGE_CHANNELS` permission.
1076
+ *
1077
+ * Fires a _Channel Update_ gateway event for every channel impacted in this change.
1078
+ *
1079
+ * At most one entry per request may change `parent_id`. A request that changes `parent_id` for more than one channel fails with a 400 response and error code 40009.
1080
+ *
1081
+ * Permissions are checked per entry, based on what the entry changes:
1082
+ * - An entry that only changes `position` requires the `MANAGE_CHANNELS` permission at the guild level (or on the channel's current parent category). It does **not** require access to the individual channel, so a full reordering may include channels the current user cannot view.
1083
+ * - An entry that changes `parent_id` requires the `MANAGE_CHANNELS` permission on that channel and on the destination (the new parent category, or the guild when moving the channel out of a category), and the current user must be able to view the channel. Otherwise the request fails with a `403` response and error code 50001. Setting `lock_permissions` additionally requires `MANAGE_ROLES`.
1084
+ *
1085
+ * @see {@link https://docs.discord.com/developers/resources/guild#modify-guild-channel-positions}
1086
+ */ async editChannelPositions (rest, guildId, channelPositions) {
1087
+ await rest.patch(rest.routes.guilds.channels(guildId), {
1088
+ body: channelPositions
1089
+ });
1090
+ },
1091
+ /**
1092
+ * Edits an emoji.
1093
+ *
1094
+ * @param guildId - The ID of the guild in which to edit the emoji.
1095
+ * @param id - The ID of the emoji to edit.
1096
+ * @param options - The parameters for the edit of the emoji.
1097
+ * @param {string} [reason] - An optional reason for the action, to be included in the audit log.
1098
+ * @returns An instance of the updated {@link DiscordEmoji}.
1099
+ *
1100
+ * @remarks
1101
+ * For emojis created by the current user, requires either the `CREATE_GUILD_EXPRESSIONS` or `MANAGE_GUILD_EXPRESSIONS` permission.
1102
+ * For other emojis, requires the `MANAGE_GUILD_EXPRESSIONS` permission.
1103
+ *
1104
+ * Fires a `Guild Emojis Update` gateway event.
1105
+ *
1106
+ * @see {@link https://docs.discord.com/developers/resources/emoji#modify-guild-emoji}
1107
+ */ async editEmoji (rest, guildId, id, options, reason) {
1108
+ return await rest.patch(rest.routes.guilds.emoji(guildId, id), {
1109
+ body: options,
1110
+ reason
1111
+ });
1112
+ },
1113
+ /**
1114
+ * Edits an application emoji.
1115
+ *
1116
+ * @param id - The ID of the emoji to edit.
1117
+ * @param options - The parameters for the edit of the emoji.
1118
+ * @returns An instance of the updated {@link DiscordEmoji}.
1119
+ *
1120
+ * @see {@link https://docs.discord.com/developers/resources/emoji#modify-application-emoji}
1121
+ */ async editApplicationEmoji (rest, id, options) {
1122
+ return await rest.patch(rest.routes.applicationEmoji(rest.applicationId, id), {
1123
+ body: options
1124
+ });
1125
+ },
1126
+ /**
1127
+ * Edits a follow-up message to an interaction.
1128
+ *
1129
+ * @param token - The interaction token to use, provided in the original interaction.
1130
+ * @param messageId - The ID of the message to edit.
1131
+ * @param options - The parameters for the edit of the message.
1132
+ * @returns An instance of the edited {@link DiscordMessage}.
1133
+ *
1134
+ * @remarks
1135
+ * Unlike `editMessage()`, this endpoint allows the bot user to act without needing to see the channel the message is in.
1136
+ *
1137
+ * Does not support ephemeral follow-up messages due to these being stateless.
1138
+ *
1139
+ * Fires a _Message Update_ event.
1140
+ *
1141
+ * @see {@link https://docs.discord.com/developers/interactions/receiving-and-responding#edit-followup-message}
1142
+ */ async editFollowupMessage (rest, token, messageId, options) {
1143
+ return await rest.patch(rest.routes.interactions.responses.message(rest.applicationId, token, messageId), {
1144
+ body: options,
1145
+ files: options.files,
1146
+ unauthorized: true
1147
+ });
1148
+ },
1149
+ /**
1150
+ * Edits a global application command.
1151
+ *
1152
+ * @param commandId - The ID of the command to edit.
1153
+ * @param options - The parameters for the edit of the command.
1154
+ * @returns An instance of the edited {@link DiscordApplicationCommand}.
1155
+ *
1156
+ * @see {@link https://docs.discord.com/developers/interactions/application-commands#edit-global-application-command}
1157
+ */ async editGlobalApplicationCommand (rest, commandId, options) {
1158
+ return await rest.patch(rest.routes.interactions.commands.command(rest.applicationId, commandId), {
1159
+ body: options
1160
+ });
1161
+ },
1162
+ /**
1163
+ * Edits a guild's settings.
1164
+ *
1165
+ * @param guildId - The ID of the guild to edit.
1166
+ * @param options - The parameters for the edit of the guild.
1167
+ * @param {string} [reason] - An optional reason for the action, to be included in the audit log.
1168
+ * @returns An instance of the edited {@link DiscordGuild}.
1169
+ *
1170
+ * @remarks
1171
+ * Requires the `MANAGE_GUILD` permission.
1172
+ *
1173
+ * If attempting to add or remove the {@link GuildFeatures}.Community feature:
1174
+ * - Requires the `ADMINISTRATOR` permission.
1175
+ *
1176
+ * Fires a _Guild Update_ gateway event.
1177
+ *
1178
+ * @see {@link https://docs.discord.com/developers/resources/guild#modify-guild}
1179
+ */ async editGuild (rest, guildId, options, reason) {
1180
+ return await rest.patch(rest.routes.guilds.guild(guildId), {
1181
+ body: options,
1182
+ reason
1183
+ });
1184
+ },
1185
+ /**
1186
+ * Edits an application command registered in a guild.
1187
+ *
1188
+ * @param guildId - The ID of the guild the command is registered in.
1189
+ * @param commandId - The ID of the command to edit.
1190
+ * @param options - The parameters for the edit of the command.
1191
+ * @returns An instance of the edited {@link DiscordApplicationCommand}.
1192
+ *
1193
+ * @see {@link https://docs.discord.com/developers/interactions/application-commands#edit-guild-application-command}
1194
+ */ async editGuildApplicationCommand (rest, commandId, guildId, options) {
1195
+ return await rest.patch(rest.routes.interactions.commands.guilds.one(rest.applicationId, guildId, commandId), {
1196
+ body: options
1197
+ });
1198
+ },
1199
+ /**
1200
+ * Edit the given sticker.
1201
+ *
1202
+ * @param guildId The ID of the guild to get
1203
+ * @param {string} [reason] - An optional reason for the action, to be included in the audit log.
1204
+ * @return A {@link DiscordSticker}
1205
+ *
1206
+ * @remarks
1207
+ * For stickers created by the current user, requires either the `CREATE_GUILD_EXPRESSIONS` or `MANAGE_GUILD_EXPRESSIONS` permission.
1208
+ * For other stickers, requires the `MANAGE_GUILD_EXPRESSIONS` permission.
1209
+ * Fires a Guild Stickers Update Gateway event.
1210
+ *
1211
+ * @see {@link https://docs.discord.com/developers/resources/sticker#modify-guild-sticker}
1212
+ */ async editGuildSticker (rest, guildId, stickerId, options, reason) {
1213
+ return await rest.patch(rest.routes.guilds.sticker(guildId, stickerId), {
1214
+ body: options,
1215
+ reason
1216
+ });
1217
+ },
1218
+ /**
1219
+ * Edits a template's settings.
1220
+ *
1221
+ * @param guildId - The ID of the guild to edit a template of.
1222
+ * @param templateCode - The code of the template to edit.
1223
+ * @param options - The parameters for the edit of the template.
1224
+ * @returns An instance of the edited {@link DiscordTemplate}.
1225
+ *
1226
+ * @remarks
1227
+ * Requires the `MANAGE_GUILD` permission.
1228
+ *
1229
+ * Fires a _Guild Update_ gateway event.
1230
+ *
1231
+ * @see {@link https://docs.discord.com/developers/resources/guild-template#modify-guild-template}
1232
+ */ async editGuildTemplate (rest, guildId, templateCode, options) {
1233
+ return await rest.patch(rest.routes.guilds.templates.guild(guildId, templateCode), {
1234
+ body: options
1235
+ });
1236
+ },
1237
+ /**
1238
+ * Edits a message.
1239
+ *
1240
+ * @param channelId - The ID of the channel to edit the message in.
1241
+ * @param messageId - The IDs of the message to edit.
1242
+ * @param options - The parameters for the edit of the message.
1243
+ * @returns An instance of the edited {@link DiscordMessage}.
1244
+ *
1245
+ * @remarks
1246
+ * If editing another user's message:
1247
+ * - Requires the `MANAGE_MESSAGES` permission.
1248
+ * - Only the {@link EditMessage.flags | flags} property of the options object parameter can be edited.
1249
+ *
1250
+ * Fires a _Message Update_ gateway event.
1251
+ *
1252
+ * @see {@link https://docs.discord.com/developers/resources/channel#edit-message}
1253
+ */ async editMessage (rest, channelId, messageId, options) {
1254
+ return await rest.patch(rest.routes.channels.message(channelId, messageId), {
1255
+ body: options,
1256
+ files: options.files
1257
+ });
1258
+ },
1259
+ /**
1260
+ * Edits the initial message response to an interaction.
1261
+ *
1262
+ * @param token - The interaction token to use, provided in the original interaction.
1263
+ * @param options - The parameters for the edit of the response.
1264
+ * @returns An instance of the edited {@link DiscordMessage}.
1265
+ *
1266
+ * @remarks
1267
+ * Unlike `editMessage()`, this endpoint allows the bot user to act without needing to see the channel the message is in.
1268
+ *
1269
+ * Does not support ephemeral follow-up messages due to these being stateless.
1270
+ *
1271
+ * Fires a _Message Update_ event.
1272
+ *
1273
+ * @see {@link https://docs.discord.com/developers/interactions/receiving-and-responding#edit-original-interaction-response}
1274
+ */ async editOriginalInteractionResponse (rest, token, options) {
1275
+ return await rest.patch(rest.routes.interactions.responses.original(rest.applicationId, token), {
1276
+ body: options,
1277
+ files: options.files,
1278
+ unauthorized: true
1279
+ });
1280
+ },
1281
+ /**
1282
+ * Edits the voice state of the bot user.
1283
+ *
1284
+ * @param guildId - The ID of the guild in which to edit the voice state of the bot user.
1285
+ * @param options - The parameters for the edit of the voice state.
1286
+ *
1287
+ * @remarks
1288
+ * The {@link EditOwnVoiceState.channelId | channelId} property of the options object parameter must point to a stage channel, and the bot user must already have joined it.
1289
+ *
1290
+ * If attempting to unmute oneself:
1291
+ * - Requires the `MUTE_MEMBERS` permission.
1292
+ *
1293
+ * If attempting to request to speak:
1294
+ * - Requires the `REQUEST_TO_SPEAK` permission.
1295
+ *
1296
+ * @see {@link https://docs.discord.com/developers/resources/voice#modify-current-user-voice-state}
1297
+ */ async editOwnVoiceState (rest, guildId, options) {
1298
+ await rest.patch(rest.routes.guilds.voice(guildId), {
1299
+ body: {
1300
+ ...options,
1301
+ requestToSpeakTimestamp: options.requestToSpeakTimestamp ? new Date(options.requestToSpeakTimestamp).toISOString() : options.requestToSpeakTimestamp
1302
+ }
1303
+ });
1304
+ },
1305
+ /**
1306
+ * Edits a role in a guild.
1307
+ *
1308
+ * @param guildId - The ID of the guild to edit the role in.
1309
+ * @param roleId - The ID of the role to edit.
1310
+ * @param options - The parameters for the edit of the role.
1311
+ * @param {string} [reason] - An optional reason for the action, to be included in the audit log.
1312
+ * @returns An instance of the edited {@link DiscordRole}.
1313
+ *
1314
+ * @remarks
1315
+ * Requires the `MANAGE_ROLES` permission.
1316
+ *
1317
+ * Fires a _Guild Role Update_ gateway event.
1318
+ *
1319
+ * @see {@link https://docs.discord.com/developers/resources/guild#modify-guild-role}
1320
+ */ async editRole (rest, guildId, roleId, options, reason) {
1321
+ return await rest.patch(rest.routes.guilds.roles.one(guildId, roleId), {
1322
+ body: options,
1323
+ reason
1324
+ });
1325
+ },
1326
+ /**
1327
+ * Edits the positions of a set of roles.
1328
+ *
1329
+ * @param guildId - The ID of the guild to edit the role positions in.
1330
+ * @param options - The parameters for the edit of the role positions.
1331
+ * @param {string} [reason] - An optional reason for the action, to be included in the audit log.
1332
+ * @returns A collection of {@link DiscordRole} objects assorted by role ID.
1333
+ *
1334
+ * @remarks
1335
+ * Requires the `MANAGE_ROLES` permission.
1336
+ *
1337
+ * Fires a _Guild Role Update_ gateway event for every role impacted in this change.
1338
+ *
1339
+ * @see {@link https://docs.discord.com/developers/resources/guild#modify-guild-role-positions}
1340
+ */ async editRolePositions (rest, guildId, options, reason) {
1341
+ return await rest.patch(rest.routes.guilds.roles.all(guildId), {
1342
+ body: options,
1343
+ reason
1344
+ });
1345
+ },
1346
+ /**
1347
+ * Edits a scheduled event.
1348
+ *
1349
+ * @param guildId - The ID of the guild to edit the scheduled event in.
1350
+ * @param eventId - The ID of the scheduled event to edit.
1351
+ * @param {string} [reason] - An optional reason for the action, to be included in the audit log.
1352
+ * @returns An instance of the edited {@link DiscordScheduledEvent}.
1353
+ *
1354
+ * @remarks
1355
+ * Requires the `MANAGE_EVENTS` permission.
1356
+ *
1357
+ * To start or end an event, modify the event's `status` property.
1358
+ *
1359
+ * The `entity_metadata` property is discarded for events whose `entity_type` is not {@link ScheduledEventEntityType}.External.
1360
+ *
1361
+ * Fires a _Guild Scheduled Event Update_ gateway event.
1362
+ *
1363
+ * @see {@link https://docs.discord.com/developers/resources/guild-scheduled-event#modify-guild-scheduled-event}
1364
+ */ async editScheduledEvent (rest, guildId, eventId, options, reason) {
1365
+ return await rest.patch(rest.routes.guilds.events.event(guildId, eventId), {
1366
+ body: options,
1367
+ reason
1368
+ });
1369
+ },
1370
+ /**
1371
+ * Edits a stage instance.
1372
+ *
1373
+ * @param channelId - The ID of the stage channel the stage instance is associated with.
1374
+ * @param topic - Topic of the Stage instance (1-120 characters).
1375
+ * @param {string} [reason] - An optional reason for the action, to be included in the audit log.
1376
+ * @returns An instance of the updated {@link DiscordStageInstance}.
1377
+ *
1378
+ * @remarks
1379
+ * Requires the user to be a moderator of the stage channel.
1380
+ *
1381
+ * Fires a _Stage Instance Update_ event.
1382
+ *
1383
+ * @see {@link https://docs.discord.com/developers/resources/stage-instance#modify-stage-instance}
1384
+ */ async editStageInstance (rest, channelId, topic, reason) {
1385
+ return await rest.patch(rest.routes.channels.stage(channelId), {
1386
+ body: {
1387
+ topic
1388
+ },
1389
+ reason
1390
+ });
1391
+ },
1392
+ /**
1393
+ * Edits the voice state of another user.
1394
+ *
1395
+ * @param guildId - The ID of the guild in which to edit the voice state of the bot user.
1396
+ * @param options - The parameters for the edit of the voice state.
1397
+ *
1398
+ * @remarks
1399
+ * The {@link EditOwnVoiceState.channelId | channelId} property of the options object parameter must point to a stage channel, and the user must already have joined it.
1400
+ *
1401
+ * Requires the `MUTE_MEMBERS` permission.
1402
+ *
1403
+ * @see {@link https://docs.discord.com/developers/resources/voice#modify-user-voice-state}
1404
+ */ async editUserVoiceState (rest, guildId, options) {
1405
+ await rest.patch(rest.routes.guilds.voice(guildId, options.userId), {
1406
+ body: options
1407
+ });
1408
+ },
1409
+ /**
1410
+ * Edit the current user application role connection for the application.
1411
+ *
1412
+ * @param bearerToken - The access token of the user
1413
+ * @param applicationId - The id of the application to edit the role connection
1414
+ * @param options - The options to edit
1415
+ * @returns {DiscordApplicationRoleConnection}
1416
+ *
1417
+ * @remarks
1418
+ * This requires the `role_connections.write` scope.
1419
+ *
1420
+ * @see {@link https://docs.discord.com/developers/resources/user#update-user-application-role-connection}
1421
+ */ async editUserApplicationRoleConnection (rest, bearerToken, applicationId, options) {
1422
+ return await rest.put(rest.routes.oauth2.roleConnections(applicationId), {
1423
+ body: options,
1424
+ headers: {
1425
+ authorization: `Bearer ${bearerToken}`
1426
+ },
1427
+ unauthorized: true
1428
+ });
1429
+ },
1430
+ /**
1431
+ * Deletes the application role connection for the user.
1432
+ *
1433
+ * @param bearerToken - The access token of the user
1434
+ * @param applicationId - The id of the application to delete the role connection
1435
+ *
1436
+ * @remarks
1437
+ * This requires the `role_connections.write` scope.
1438
+ *
1439
+ * @see {@link https://docs.discord.com/developers/resources/user#delete-current-user-application-role-connection}
1440
+ */ async deleteCurrentUserApplicationRoleConnection (rest, bearerToken, applicationId) {
1441
+ return await rest.delete(rest.routes.oauth2.roleConnections(applicationId), {
1442
+ headers: {
1443
+ authorization: `Bearer ${bearerToken}`
1444
+ },
1445
+ unauthorized: true
1446
+ });
1447
+ },
1448
+ /**
1449
+ * Edits a webhook.
1450
+ *
1451
+ * @param webhookId - The ID of the webhook to edit.
1452
+ * @param {string} [reason] - An optional reason for the action, to be included in the audit log.
1453
+ * @returns An instance of the edited {@link DiscordWebhook}.
1454
+ *
1455
+ * @remarks
1456
+ * Requires the `MANAGE_WEBHOOKS` permission.
1457
+ *
1458
+ * Fires a _Webhooks Update_ gateway event.
1459
+ *
1460
+ * @see {@link https://docs.discord.com/developers/resources/webhook#edit-webhook}
1461
+ */ async editWebhook (rest, webhookId, options, reason) {
1462
+ return await rest.patch(rest.routes.webhooks.id(webhookId), {
1463
+ body: options,
1464
+ reason
1465
+ });
1466
+ },
1467
+ /**
1468
+ * Edits a webhook message.
1469
+ *
1470
+ * @param webhookId - The ID of the webhook to edit the message of.
1471
+ * @param token - The webhook token, used to edit the message.
1472
+ * @param messageId - The ID of the message to edit.
1473
+ * @param options - The parameters for the edit of the message.
1474
+ * @returns An instance of the edited {@link DiscordMessage}.
1475
+ *
1476
+ * @remarks
1477
+ * Fires a _Message Update_ gateway event.
1478
+ *
1479
+ * @see {@link https://docs.discord.com/developers/resources/webhook#edit-webhook-message}
1480
+ */ async editWebhookMessage (rest, webhookId, token, messageId, options) {
1481
+ return await rest.patch(rest.routes.webhooks.message(webhookId, token, messageId, options), {
1482
+ body: options,
1483
+ files: options.files,
1484
+ unauthorized: true
1485
+ });
1486
+ },
1487
+ /**
1488
+ * Edits a webhook using the webhook token, thereby bypassing the need for authentication + permissions.
1489
+ *
1490
+ * @param webhookId - The ID of the webhook to edit.
1491
+ * @param token - The webhook token, used to edit the webhook.
1492
+ * @returns An instance of the edited {@link DiscordWebhook}.
1493
+ *
1494
+ * @remarks
1495
+ * Requires the `MANAGE_WEBHOOKS` permission.
1496
+ *
1497
+ * Fires a _Webhooks Update_ gateway event.
1498
+ *
1499
+ * @see {@link https://docs.discord.com/developers/resources/webhook#modify-webhook-with-token}
1500
+ */ async editWebhookWithToken (rest, webhookId, token, options) {
1501
+ return await rest.patch(rest.routes.webhooks.webhook(webhookId, token), {
1502
+ body: options,
1503
+ unauthorized: true
1504
+ });
1505
+ },
1506
+ /**
1507
+ * Edits a guild's welcome screen.
1508
+ *
1509
+ * @param guildId - The ID of the guild to edit the welcome screen of.
1510
+ * @param options - The parameters for the edit of the welcome screen.
1511
+ * @param {string} [reason] - An optional reason for the action, to be included in the audit log.
1512
+ * @returns An instance of the edited {@link DiscordWelcomeScreen}.
1513
+ *
1514
+ * @remarks
1515
+ * Requires the `MANAGE_GUILD` permission.
1516
+ *
1517
+ * Fires a _Guild Update_ gateway event.
1518
+ *
1519
+ * @see {@link https://docs.discord.com/developers/resources/guild#modify-guild-welcome-screen}
1520
+ */ async editWelcomeScreen (rest, guildId, options, reason) {
1521
+ return await rest.patch(rest.routes.guilds.welcome(guildId), {
1522
+ body: options,
1523
+ reason
1524
+ });
1525
+ },
1526
+ /**
1527
+ * Edits the settings of a guild's widget.
1528
+ *
1529
+ * @param guildId - The ID of the guild to edit the settings of the widget of.
1530
+ * @param {string} [reason] - An optional reason for the action, to be included in the audit log.
1531
+ * @returns An instance of the edited {@link DiscordGuildWidgetSettings}.
1532
+ *
1533
+ * @remarks
1534
+ * Requires the `MANAGE_GUILD` permission.
1535
+ *
1536
+ * Fires a _Guild Update_ gateway event.
1537
+ *
1538
+ * @see {@link https://docs.discord.com/developers/resources/guild#modify-guild-widget}
1539
+ */ async editWidgetSettings (rest, guildId, options, reason) {
1540
+ return await rest.patch(rest.routes.guilds.widget(guildId), {
1541
+ body: options,
1542
+ reason
1543
+ });
1544
+ },
1545
+ /**
1546
+ * Executes a webhook, causing a message to be posted in the channel configured for the webhook.
1547
+ *
1548
+ * @param webhookId - The ID of the webhook to execute.
1549
+ * @param token - The webhook token, used to execute the webhook.
1550
+ * @param options - The parameters for the execution of the webhook.
1551
+ * @returns An instance of the created {@link DiscordMessage}, or `undefined` if the {@link ExecuteWebhook.wait | wait} property of the options object parameter is set to `false`.
1552
+ *
1553
+ * @remarks
1554
+ * If the webhook channel is a forum channel, you must provide a value for either `threadId` or `threadName`.
1555
+ *
1556
+ * @see {@link https://docs.discord.com/developers/resources/webhook#execute-webhook}
1557
+ */ async executeWebhook (rest, webhookId, token, options) {
1558
+ return await rest.post(rest.routes.webhooks.webhook(webhookId, token, options), {
1559
+ body: options,
1560
+ unauthorized: true
1561
+ });
1562
+ },
1563
+ /**
1564
+ * Follows an announcement channel, allowing messages posted within it to be cross-posted into the target channel.
1565
+ *
1566
+ * @param sourceChannelId - The ID of the announcement channel to follow.
1567
+ * @param targetChannelId - The ID of the target channel - the channel to cross-post to.
1568
+ * @param {string} [reason] - An optional reason for the action, to be included in the audit log.
1569
+ * @returns An instance of {@link DiscordFollowedChannel}.
1570
+ *
1571
+ * @remarks
1572
+ * Requires the `MANAGE_WEBHOOKS` permission in the __target channel__.
1573
+ *
1574
+ * Fires a _Webhooks Update_ gateway event.
1575
+ *
1576
+ * @see {@link https://docs.discord.com/developers/resources/channel#follow-announcement-channel}
1577
+ */ async followAnnouncement (rest, sourceChannelId, targetChannelId, reason) {
1578
+ return await rest.post(rest.routes.channels.follow(sourceChannelId), {
1579
+ body: {
1580
+ webhookChannelId: targetChannelId
1581
+ },
1582
+ reason
1583
+ });
1584
+ },
1585
+ /**
1586
+ * Gets the list of all active threads for a guild.
1587
+ *
1588
+ * @param guildId - The ID of the guild to get the threads of.
1589
+ * @returns An instance of {@link DiscordListActiveThreads}.
1590
+ *
1591
+ * @remarks
1592
+ * Returns both public and private threads.
1593
+ *
1594
+ * Threads are ordered by the `id` property in descending order.
1595
+ *
1596
+ * @see {@link https://docs.discord.com/developers/resources/guild#list-active-guild-threads}
1597
+ */ async getActiveThreads (rest, guildId) {
1598
+ return await rest.get(rest.routes.channels.threads.active(guildId));
1599
+ },
1600
+ /** Get the applications info */ async getApplicationInfo (rest) {
1601
+ return await rest.get(rest.routes.oauth2.application());
1602
+ },
1603
+ /**
1604
+ * Edit properties of the app associated with the requesting bot user.
1605
+ *
1606
+ * @remarks
1607
+ * Only properties that are passed will be updated.
1608
+ */ async editApplicationInfo (rest, body) {
1609
+ return await rest.patch(rest.routes.application(), {
1610
+ body
1611
+ });
1612
+ },
1613
+ /**
1614
+ * Get the current authentication info for the authenticated user
1615
+ *
1616
+ * @param bearerToken - Any OAuth2 derived access token
1617
+ * @returns An instance of {@link DiscordCurrentAuthorization}
1618
+ *
1619
+ * @remarks
1620
+ * The user object is not defined if the scopes do not include `identify`.
1621
+ * In the user object, if defined, the email is not included if the scopes do not include `email`
1622
+ */ async getCurrentAuthenticationInfo (rest, bearerToken) {
1623
+ return await rest.get(rest.routes.oauth2.currentAuthorization(), {
1624
+ headers: {
1625
+ authorization: `Bearer ${bearerToken}`
1626
+ },
1627
+ unauthorized: true
1628
+ });
1629
+ },
1630
+ /**
1631
+ * Exchange the information to get a OAuth2 accessToken token
1632
+ *
1633
+ * @param clientId - Application's client id
1634
+ * @param clientSecret - application's client secret
1635
+ * @param options - The options to make the exchange with discord
1636
+ */ async exchangeToken (rest, clientId, clientSecret, options) {
1637
+ const basicCredentials = Buffer.from(`${clientId}:${clientSecret}`);
1638
+ const restOptions = {
1639
+ body: options,
1640
+ headers: {
1641
+ 'content-type': 'application/x-www-form-urlencoded',
1642
+ authorization: `Basic ${basicCredentials.toString('base64')}`
1643
+ },
1644
+ runThroughQueue: false,
1645
+ unauthorized: true
1646
+ };
1647
+ if (options.grantType === 'client_credentials') {
1648
+ restOptions.body.scope = options.scope.join(' ');
1649
+ }
1650
+ return await rest.post(rest.routes.oauth2.tokenExchange(), restOptions);
1651
+ },
1652
+ /**
1653
+ * Revoke an access_token
1654
+ *
1655
+ * @param clientId - Application's client id
1656
+ * @param clientSecret - application's client secret
1657
+ * @param options - The options to revoke the access_token
1658
+ */ async revokeToken (rest, clientId, clientSecret, options) {
1659
+ const basicCredentials = Buffer.from(`${clientId}:${clientSecret}`);
1660
+ await rest.post(rest.routes.oauth2.tokenRevoke(), {
1661
+ body: options,
1662
+ headers: {
1663
+ 'content-type': 'application/x-www-form-urlencoded',
1664
+ authorization: `Basic ${basicCredentials.toString('base64')}`
1665
+ },
1666
+ unauthorized: true
1667
+ });
1668
+ },
1669
+ /**
1670
+ * Gets the permissions of a guild application command.
1671
+ *
1672
+ * @param guildId - The ID of the guild the command is registered in.
1673
+ * @param commandId - The ID of the command to get the permissions of.
1674
+ * @param options - The OAuth2 related optional parameters for the endpoint
1675
+ * @returns An instance of {@link DiscordGuildApplicationCommandPermissions}.
1676
+ *
1677
+ * @remarks
1678
+ * Then specifying the options object the access token passed-in requires the OAuth2 scope `applications.commands.permissions.update`
1679
+ *
1680
+ * @see {@link https://docs.discord.com/developers/interactions/application-commands#get-application-command-permissions}
1681
+ */ async getApplicationCommandPermission (rest, guildId, commandId, options) {
1682
+ const restOptions = {};
1683
+ if (options?.accessToken) {
1684
+ restOptions.unauthorized = true;
1685
+ restOptions.headers = {
1686
+ authorization: `Bearer ${options.accessToken}`
1687
+ };
1688
+ }
1689
+ return await rest.get(rest.routes.interactions.commands.permission(options?.applicationId ?? rest.applicationId, guildId, commandId), restOptions);
1690
+ },
1691
+ /**
1692
+ * Gets the permissions of all application commands registered in a guild by the ID of the guild and optionally an external application.
1693
+ *
1694
+ * @param guildId - The ID of the guild to get the permissions objects of.
1695
+ * @param options - The OAuth2 related optional parameters for the endpoint
1696
+ * @returns A collection of {@link DiscordGuildApplicationCommandPermissions} objects assorted by command ID.
1697
+ *
1698
+ * @remarks
1699
+ * Then specifying the options object the access token passed-in requires the OAuth2 scope `applications.commands.permissions.update`
1700
+ *
1701
+ * @see {@link https://docs.discord.com/developers/interactions/application-commands#get-guild-application-command-permissions}
1702
+ */ async getApplicationCommandPermissions (rest, guildId, options) {
1703
+ const restOptions = {};
1704
+ if (options?.accessToken) {
1705
+ restOptions.unauthorized = true;
1706
+ restOptions.headers = {
1707
+ authorization: `Bearer ${options.accessToken}`
1708
+ };
1709
+ }
1710
+ return await rest.get(rest.routes.interactions.commands.permissions(options?.applicationId ?? rest.applicationId, guildId), restOptions);
1711
+ },
1712
+ /**
1713
+ * Gets a guild's audit log.
1714
+ *
1715
+ * @param guildId - The ID of the guild to get the audit log of.
1716
+ * @param options - The parameters for the fetching of the audit log.
1717
+ * @returns An instance of {@link DiscordAuditLog}.
1718
+ *
1719
+ * @remarks
1720
+ * Requires the `VIEW_AUDIT_LOG` permission.
1721
+ *
1722
+ * @see {@link https://docs.discord.com/developers/resources/audit-log#get-guild-audit-log}
1723
+ */ async getAuditLog (rest, guildId, options) {
1724
+ return await rest.get(rest.routes.guilds.auditlogs(guildId, options));
1725
+ },
1726
+ /**
1727
+ * Gets an automod rule by its ID.
1728
+ *
1729
+ * @param guildId - The ID of the guild to get the rule of.
1730
+ * @param ruleId - The ID of the rule to get.
1731
+ * @returns An instance of {@link DiscordAutoModerationRule}.
1732
+ *
1733
+ * @remarks
1734
+ * Requires the `MANAGE_GUILD` permission.
1735
+ *
1736
+ * @see {@link https://docs.discord.com/developers/resources/auto-moderation#get-auto-moderation-rule}
1737
+ */ async getAutomodRule (rest, guildId, ruleId) {
1738
+ return await rest.get(rest.routes.guilds.automod.rule(guildId, ruleId));
1739
+ },
1740
+ /**
1741
+ * Gets the list of automod rules for a guild.
1742
+ *
1743
+ * @param guildId - The ID of the guild to get the rules from.
1744
+ * @returns A collection of {@link DiscordAutoModerationRule} objects assorted by rule ID.
1745
+ *
1746
+ * @remarks
1747
+ * Requires the `MANAGE_GUILD` permission.
1748
+ *
1749
+ * @see {@link https://docs.discord.com/developers/resources/auto-moderation#list-auto-moderation-rules-for-guild}
1750
+ */ async getAutomodRules (rest, guildId) {
1751
+ return await rest.get(rest.routes.guilds.automod.rules(guildId));
1752
+ },
1753
+ /**
1754
+ * Gets the list of available voice regions.
1755
+ *
1756
+ * @returns A collection of {@link DiscordVoiceRegion} objects assorted by voice region ID.
1757
+ */ async getAvailableVoiceRegions (rest) {
1758
+ return await rest.get(rest.routes.regions());
1759
+ },
1760
+ /**
1761
+ * Gets a ban by user ID.
1762
+ *
1763
+ * @param guildId - The ID of the guild to get the ban from.
1764
+ * @param userId - The ID of the user to get the ban for.
1765
+ * @returns An instance of {@link DiscordBan}.
1766
+ *
1767
+ * @remarks
1768
+ * Requires the `BAN_MEMBERS` permission.
1769
+ *
1770
+ * @see {@link https://docs.discord.com/developers/resources/guild#get-guild-ban}
1771
+ */ async getBan (rest, guildId, userId) {
1772
+ return await rest.get(rest.routes.guilds.members.ban(guildId, userId));
1773
+ },
1774
+ /**
1775
+ * Gets the list of bans for a guild.
1776
+ *
1777
+ * @param guildId - The ID of the guild to get the list of bans for.
1778
+ * @param options - The parameters for the fetching of the list of bans.
1779
+ * @returns A collection of {@link DiscordBan} objects assorted by user ID.
1780
+ *
1781
+ * @remarks
1782
+ * Requires the `BAN_MEMBERS` permission.
1783
+ *
1784
+ * Users are ordered by their IDs in _ascending_ order.
1785
+ *
1786
+ * @see {@link https://docs.discord.com/developers/resources/guild#get-guild-bans}
1787
+ */ async getBans (rest, guildId, options) {
1788
+ return await rest.get(rest.routes.guilds.members.bans(guildId, options));
1789
+ },
1790
+ /**
1791
+ * Gets a channel by its ID.
1792
+ *
1793
+ * @param channelId - The ID of the channel to get.
1794
+ * @returns An instance of {@link DiscordChannel}.
1795
+ *
1796
+ * @remarks
1797
+ * If the channel is a thread, a {@link DiscordThreadMember} object is included in the result.
1798
+ *
1799
+ * @see {@link https://docs.discord.com/developers/resources/channel#get-channel}
1800
+ */ async getChannel (rest, channelId) {
1801
+ return await rest.get(rest.routes.channels.channel(channelId));
1802
+ },
1803
+ /**
1804
+ * Gets the list of invites for a channel.
1805
+ *
1806
+ * @param channelId - The ID of the channel to get the invites of.
1807
+ * @returns A collection of {@link DiscordInviteMetadata} objects assorted by invite code.
1808
+ *
1809
+ * @remarks
1810
+ * Requires the `MANAGE_CHANNELS` permission.
1811
+ *
1812
+ * Only usable for guild channels.
1813
+ *
1814
+ * @see {@link https://docs.discord.com/developers/resources/channel#get-channel-invites}
1815
+ */ async getChannelInvites (rest, channelId) {
1816
+ return await rest.get(rest.routes.channels.invites(channelId));
1817
+ },
1818
+ /**
1819
+ * Gets the list of channels for a guild.
1820
+ *
1821
+ * @param guildId - The ID of the guild to get the channels of.
1822
+ * @returns A collection of {@link DiscordChannel} objects assorted by channel ID.
1823
+ *
1824
+ * @remarks
1825
+ * Excludes threads.
1826
+ *
1827
+ * @see {@link https://docs.discord.com/developers/resources/guild#get-guild-channels}
1828
+ */ async getChannels (rest, guildId) {
1829
+ return await rest.get(rest.routes.guilds.channels(guildId));
1830
+ },
1831
+ /**
1832
+ * Gets a list of webhooks for a channel.
1833
+ *
1834
+ * @param channelId - The ID of the channel which to get the webhooks of.
1835
+ * @returns A collection of {@link DiscordWebhook} objects assorted by webhook ID.
1836
+ *
1837
+ * @remarks
1838
+ * Requires the `MANAGE_WEBHOOKS` permission.
1839
+ *
1840
+ * @see {@link https://docs.discord.com/developers/resources/webhook#get-channel-webhooks}
1841
+ */ async getChannelWebhooks (rest, channelId) {
1842
+ return await rest.get(rest.routes.channels.webhooks(channelId));
1843
+ },
1844
+ /**
1845
+ * Gets or creates a DM channel with a user.
1846
+ *
1847
+ * @param userId - The ID of the user to create the DM channel with.
1848
+ * @returns An instance of {@link DiscordChannel}.
1849
+ *
1850
+ * @see {@link https://docs.discord.com/developers/resources/user#create-dm}
1851
+ */ async getDmChannel (rest, userId) {
1852
+ return await rest.post(rest.routes.channels.dm(), {
1853
+ body: {
1854
+ recipientId: userId
1855
+ }
1856
+ });
1857
+ },
1858
+ /**
1859
+ * Create a new group DM channel with multiple users.
1860
+ *
1861
+ * @param options - The options for create a new group dm
1862
+ * @returns An instance of {@link DiscordChannel}.
1863
+ *
1864
+ * @remarks
1865
+ * The access tokens require to have the `gdm.join` scope
1866
+ *
1867
+ * This endpoint is limited to 10 active group DMs.
1868
+ *
1869
+ * Fires a _Channel create_ gateway event.
1870
+ *
1871
+ * @see {@link https://docs.discord.com/developers/resources/user#create-group-dm}
1872
+ */ async getGroupDmChannel (rest, options) {
1873
+ return await rest.post(rest.routes.channels.dm(), {
1874
+ body: options
1875
+ });
1876
+ },
1877
+ /**
1878
+ * Gets an emoji by its ID.
1879
+ *
1880
+ * @param guildId - The ID of the guild from which to get the emoji.
1881
+ * @param emojiId - The ID of the emoji to get.
1882
+ * @returns An instance of {@link DiscordEmoji}.
1883
+ *
1884
+ * @remarks
1885
+ * Includes the `user` field if the bot has the `MANAGE_GUILD_EXPRESSIONS` permission,
1886
+ * or if the bot created the emoji and has the `CREATE_GUILD_EXPRESSIONS` permission.
1887
+ *
1888
+ * @see {@link https://docs.discord.com/developers/resources/emoji#get-guild-emoji}
1889
+ */ async getEmoji (rest, guildId, emojiId) {
1890
+ return await rest.get(rest.routes.guilds.emoji(guildId, emojiId));
1891
+ },
1892
+ /**
1893
+ * Gets an application emoji by its ID.
1894
+ *
1895
+ * @param emojiId - The ID of the emoji to get.
1896
+ * @returns An instance of {@link DiscordEmoji}.
1897
+ *
1898
+ * @remarks
1899
+ * Always includes the `user` object for the team member that uploaded the emoji from the app's settings, or for the bot user if uploaded using the API.
1900
+ *
1901
+ * @see {@link https://docs.discord.com/developers/resources/emoji#get-application-emoji}
1902
+ */ async getApplicationEmoji (rest, emojiId) {
1903
+ return await rest.get(rest.routes.applicationEmoji(rest.applicationId, emojiId));
1904
+ },
1905
+ /**
1906
+ * Gets the list of emojis for a guild.
1907
+ *
1908
+ * @param guildId - The ID of the guild which to get the emojis of.
1909
+ * @returns A collection of {@link DiscordEmoji} objects assorted by emoji ID.
1910
+ *
1911
+ * @remarks
1912
+ * Includes `user` fields if the bot has the `CREATE_GUILD_EXPRESSIONS` or `MANAGE_GUILD_EXPRESSIONS` permission.
1913
+ *
1914
+ * @see {@link https://docs.discord.com/developers/resources/emoji#list-guild-emojis}
1915
+ */ async getEmojis (rest, guildId) {
1916
+ return await rest.get(rest.routes.guilds.emojis(guildId));
1917
+ },
1918
+ /**
1919
+ * Gets the list of emojis for an application.
1920
+ *
1921
+ * @returns An object with the array of {@link DiscordEmoji} objects.
1922
+ *
1923
+ * @remarks
1924
+ * Always includes the `user` object for the team member that uploaded the emoji from the app's settings, or for the bot user if uploaded using the API.
1925
+ *
1926
+ * @see {@link https://docs.discord.com/developers/resources/emoji#list-application-emojis}
1927
+ */ async getApplicationEmojis (rest) {
1928
+ return await rest.get(rest.routes.applicationEmojis(rest.applicationId));
1929
+ },
1930
+ /**
1931
+ * Gets a follow-up message to an interaction by the ID of the message.
1932
+ *
1933
+ * @param token - The interaction token to use, provided in the original interaction.
1934
+ * @param messageId - The ID of the message to get.
1935
+ * @returns An instance of {@link DiscordMessage}.
1936
+ *
1937
+ * @remarks
1938
+ * Unlike `getMessage()`, this endpoint allows the bot user to act without:
1939
+ * - Needing to be able to see the contents of the channel that the message is in. (`READ_MESSAGES` permission.)
1940
+ * - Requiring the `MESSAGE_CONTENT` intent.
1941
+ *
1942
+ * Does not support ephemeral follow-up messages due to these being stateless.
1943
+ *
1944
+ * @see {@link https://docs.discord.com/developers/interactions/receiving-and-responding#get-followup-message}
1945
+ */ async getFollowupMessage (rest, token, messageId) {
1946
+ return await rest.get(rest.routes.interactions.responses.message(rest.applicationId, token, messageId), {
1947
+ unauthorized: true
1948
+ });
1949
+ },
1950
+ /** Get the bots Gateway metadata that can help during the operation of large or sharded bots. */ async getGatewayBot (rest) {
1951
+ return await rest.get(rest.routes.gatewayBot());
1952
+ },
1953
+ /**
1954
+ * Gets a global application command by its ID.
1955
+ *
1956
+ * @param commandId - The ID of the command to get.
1957
+ * @returns An instance of {@link DiscordApplicationCommand}.
1958
+ *
1959
+ * @see {@link https://docs.discord.com/developers/interactions/application-commands#get-global-application-command}
1960
+ */ async getGlobalApplicationCommand (rest, commandId) {
1961
+ return await rest.get(rest.routes.interactions.commands.command(rest.applicationId, commandId));
1962
+ },
1963
+ /**
1964
+ * Gets the list of your bot's global application commands.
1965
+ *
1966
+ * @param options - The parameters for the fetching of global application commands
1967
+ * @returns A collection of {@link DiscordApplicationCommand} objects assorted by command ID.
1968
+ *
1969
+ * @see {@link https://docs.discord.com/developers/interactions/application-commands#get-global-application-commands}
1970
+ */ async getGlobalApplicationCommands (rest, options) {
1971
+ return await rest.get(rest.routes.interactions.commands.commands(rest.applicationId, options?.withLocalizations));
1972
+ },
1973
+ /**
1974
+ * Gets a guild by its ID.
1975
+ *
1976
+ * @param guildId - The ID of the guild to get.
1977
+ * @param options - The parameters for the fetching of the guild.
1978
+ * @returns An instance of {@link DiscordGuild}.
1979
+ *
1980
+ * @see {@link https://docs.discord.com/developers/resources/guild#get-guild}
1981
+ */ async getGuild (rest, guildId, options) {
1982
+ options ??= {
1983
+ counts: true
1984
+ };
1985
+ return await rest.get(rest.routes.guilds.guild(guildId, options.counts));
1986
+ },
1987
+ /**
1988
+ * Get the user guilds.
1989
+ *
1990
+ * @param bearerToken - The access token of the user, if unspecified the bot token is used instead
1991
+ * @param options - The parameters for the fetching of the guild.
1992
+ * @returns An array of partial {@link DiscordGuild}.
1993
+ *
1994
+ * @remarks
1995
+ * If used with an access token, the token needs to have the `guilds` scope
1996
+ *
1997
+ * @see {@link https://docs.discord.com/developers/resources/user#get-current-user-guilds}
1998
+ */ async getGuilds (rest, bearerToken, options) {
1999
+ const makeRequestOptions = bearerToken ? {
2000
+ headers: {
2001
+ authorization: `Bearer ${bearerToken}`
2002
+ },
2003
+ unauthorized: true
2004
+ } : undefined;
2005
+ return await rest.get(rest.routes.guilds.userGuilds(options), makeRequestOptions);
2006
+ },
2007
+ /**
2008
+ * Gets a guild application command by its ID.
2009
+ *
2010
+ * @param guildId - The ID of the guild the command is registered in.
2011
+ * @param commandId - The ID of the command to get.
2012
+ * @returns An instance of {@link DiscordApplicationCommand}.
2013
+ *
2014
+ * @see {@link https://docs.discord.com/developers/interactions/application-commands#get-guild-application-command}
2015
+ */ async getGuildApplicationCommand (rest, commandId, guildId) {
2016
+ return await rest.get(rest.routes.interactions.commands.guilds.one(rest.applicationId, guildId, commandId));
2017
+ },
2018
+ /**
2019
+ * Gets the list of application commands registered by your bot in a guild.
2020
+ *
2021
+ * @param guildId - The ID of the guild the commands are registered in.
2022
+ * @param options - The parameters for the fetching of guild application commands
2023
+ * @returns A collection of {@link DiscordApplicationCommand} objects assorted by command ID.
2024
+ *
2025
+ * @see {@link https://docs.discord.com/developers/interactions/application-commands#get-global-application-commandss}
2026
+ */ async getGuildApplicationCommands (rest, guildId, options) {
2027
+ return await rest.get(rest.routes.interactions.commands.guilds.all(rest.applicationId, guildId, options?.withLocalizations));
2028
+ },
2029
+ /**
2030
+ * Gets the preview of a guild by a guild's ID.
2031
+ *
2032
+ * @param guildId - The ID of the guild to get the preview of.
2033
+ * @returns An instance of {@link DiscordGuildPreview}.
2034
+ *
2035
+ * @remarks
2036
+ * If the bot user is not in the guild, the guild must be discoverable.
2037
+ *
2038
+ * @see {@link https://docs.discord.com/developers/resources/guild#get-guild-preview}
2039
+ */ async getGuildPreview (rest, guildId) {
2040
+ return await rest.get(rest.routes.guilds.preview(guildId));
2041
+ },
2042
+ /**
2043
+ * Returns a sticker object for the given guild and sticker IDs.
2044
+ *
2045
+ * @param guildId The ID of the guild to get
2046
+ * @param stickerId The ID of the sticker to get
2047
+ * @return A {@link DiscordSticker}
2048
+ *
2049
+ * @remarks Includes the user field if the bot has the `CREATE_GUILD_EXPRESSIONS` or `MANAGE_GUILD_EXPRESSIONS` permission.
2050
+ *
2051
+ * @see {@link https://docs.discord.com/developers/resources/sticker#get-guild-sticker}
2052
+ */ async getGuildSticker (rest, guildId, stickerId) {
2053
+ return await rest.get(rest.routes.guilds.sticker(guildId, stickerId));
2054
+ },
2055
+ /**
2056
+ * Returns an array of sticker objects for the given guild.
2057
+ *
2058
+ * @param guildId The ID of the guild to get
2059
+ * @returns A collection of {@link DiscordSticker} objects assorted by sticker ID.
2060
+ *
2061
+ * @remarks Includes user fields if the bot has the `CREATE_GUILD_EXPRESSIONS` or `MANAGE_GUILD_EXPRESSIONS` permission.
2062
+ *
2063
+ * @see {@link https://docs.discord.com/developers/resources/sticker#list-guild-stickers}
2064
+ */ async getGuildStickers (rest, guildId) {
2065
+ return await rest.get(rest.routes.guilds.stickers(guildId));
2066
+ },
2067
+ /**
2068
+ * Gets a template by its code.
2069
+ *
2070
+ * @param templateCode - The code of the template to get.
2071
+ * @returns An instance of {@link DiscordTemplate}.
2072
+ *
2073
+ * @remarks
2074
+ * Requires the `MANAGE_GUILD` permission.
2075
+ *
2076
+ * @see {@link https://docs.discord.com/developers/resources/guild-template#get-guild-template}
2077
+ */ async getGuildTemplate (rest, templateCode) {
2078
+ return await rest.get(rest.routes.guilds.templates.code(templateCode));
2079
+ },
2080
+ /**
2081
+ * Gets the list of templates for a guild.
2082
+ *
2083
+ * @param guildId - The ID of the guild to get the list of templates for.
2084
+ * @returns A collection of {@link DiscordTemplate} objects assorted by template code.
2085
+ *
2086
+ * @remarks
2087
+ * Requires the `MANAGE_GUILD` permission.
2088
+ *
2089
+ * @see {@link https://docs.discord.com/developers/resources/guild-template#get-guild-templates}
2090
+ */ async getGuildTemplates (rest, guildId) {
2091
+ return await rest.get(rest.routes.guilds.templates.all(guildId));
2092
+ },
2093
+ /**
2094
+ * Gets the list of webhooks for a guild.
2095
+ *
2096
+ * @param guildId - The ID of the guild to get the list of webhooks for.
2097
+ * @returns A collection of {@link DiscordWebhook} objects assorted by webhook ID.
2098
+ *
2099
+ * @remarks
2100
+ * Requires the `MANAGE_WEBHOOKS` permission.
2101
+ *
2102
+ * @see {@link https://docs.discord.com/developers/resources/webhook#get-guild-webhooks}
2103
+ */ async getGuildWebhooks (rest, guildId) {
2104
+ return await rest.get(rest.routes.guilds.webhooks(guildId));
2105
+ },
2106
+ /**
2107
+ * Gets the list of integrations attached to a guild.
2108
+ *
2109
+ * @param guildId - The ID of the guild to get the list of integrations from.
2110
+ * @returns A collection of {@link DiscordIntegration} objects assorted by integration ID.
2111
+ *
2112
+ * @remarks
2113
+ * Requires the `MANAGE_GUILD` permission.
2114
+ *
2115
+ * @see {@link https://docs.discord.com/developers/resources/guild#get-guild-integrations}
2116
+ */ async getIntegrations (rest, guildId) {
2117
+ return await rest.get(rest.routes.guilds.integrations(guildId));
2118
+ },
2119
+ /**
2120
+ * Gets an invite to a channel by its invite code.
2121
+ *
2122
+ * @param inviteCode - The invite code of the invite to get.
2123
+ * @param options - The parameters for the fetching of the invite.
2124
+ * @returns An instance of {@link DiscordInviteMetadata}.
2125
+ *
2126
+ * @see {@link https://docs.discord.com/developers/resources/invite#get-invite}
2127
+ */ async getInvite (rest, inviteCode, options) {
2128
+ return await rest.get(rest.routes.guilds.invite(inviteCode, options));
2129
+ },
2130
+ /**
2131
+ * Gets the list of invites for a guild.
2132
+ *
2133
+ * @param guildId - The ID of the guild to get the invites from.
2134
+ * @returns A collection of {@link DiscordInviteMetadata} objects assorted by invite code.
2135
+ *
2136
+ * @remarks
2137
+ * Requires the `MANAGE_GUILD` or `VIEW_AUDIT_LOG` permission.
2138
+ *
2139
+ * @see {@link https://docs.discord.com/developers/resources/invite#get-invites}
2140
+ */ async getInvites (rest, guildId) {
2141
+ return await rest.get(rest.routes.guilds.invites(guildId));
2142
+ },
2143
+ /**
2144
+ * Gets a message from a channel by the ID of the message.
2145
+ *
2146
+ * @param channelId - The ID of the channel from which to get the message.
2147
+ * @param messageId - The ID of the message to get.
2148
+ * @returns An instance of {@link DiscordMessage}.
2149
+ *
2150
+ * @remarks
2151
+ * Requires that the bot user be able to see the contents of the channel in which the message was posted.
2152
+ *
2153
+ * If getting a message from a guild channel:
2154
+ * - Requires the `READ_MESSAGE_HISTORY` permission.
2155
+ *
2156
+ * @see {@link https://docs.discord.com/developers/resources/channel#get-channel-message}
2157
+ */ async getMessage (rest, channelId, messageId) {
2158
+ return await rest.get(rest.routes.channels.message(channelId, messageId));
2159
+ },
2160
+ /**
2161
+ * Gets multiple messages from a channel.
2162
+ *
2163
+ * @param channelId - The ID of the channel from which to get the messages.
2164
+ * @param options - The parameters for the fetching of the messages.
2165
+ * @returns Returns an array of {@link DiscordMessage} objects from newest to oldest on success.
2166
+ *
2167
+ * @remarks
2168
+ * Requires that the bot user be able to see the contents of the channel in which the messages were posted.
2169
+ *
2170
+ * If getting a messages from a guild channel:
2171
+ * - Requires the `READ_MESSAGE_HISTORY` permission.
2172
+ *
2173
+ * @see {@link https://docs.discord.com/developers/resources/channel#get-channel-messages}
2174
+ */ async getMessages (rest, channelId, options) {
2175
+ return await rest.get(rest.routes.channels.messages(channelId, options));
2176
+ },
2177
+ /**
2178
+ * Search messages in a guild.
2179
+ *
2180
+ * @remarks
2181
+ * Requires `READ_MESSAGE_HISTORY` and is restricted by the `MESSAGE_CONTENT` intent.
2182
+ *
2183
+ * @see {@link https://docs.discord.com/developers/resources/message#search-guild-messages}
2184
+ */ async searchGuildMessages (rest, guildId, options) {
2185
+ return await rest.get(rest.routes.guilds.messagesSearch(guildId, options));
2186
+ },
2187
+ /**
2188
+ * Returns a sticker pack for the given ID.
2189
+ *
2190
+ * @returns A {@link DiscordStickerPack} object.
2191
+ *
2192
+ * @see {@link https://docs.discord.com/developers/resources/sticker#get-sticker-pack}
2193
+ */ async getStickerPack (rest, stickerPackId) {
2194
+ return await rest.get(rest.routes.stickerPack(stickerPackId));
2195
+ },
2196
+ /**
2197
+ * Returns the list of sticker packs available.
2198
+ *
2199
+ * @returns A collection of {@link DiscordStickerPack} objects assorted by sticker ID.
2200
+ *
2201
+ * @see {@link https://docs.discord.com/developers/resources/sticker#list-sticker-packs}
2202
+ */ async getStickerPacks (rest) {
2203
+ return await rest.get(rest.routes.stickerPacks());
2204
+ },
2205
+ /**
2206
+ * Gets the initial message response to an interaction.
2207
+ *
2208
+ * @param token - The interaction token to use, provided in the original interaction.
2209
+ * @returns An instance of {@link DiscordMessage}.
2210
+ *
2211
+ * @remarks
2212
+ * Unlike `getMessage()`, this endpoint allows the bot user to act without:
2213
+ * - Needing to be able to see the contents of the channel that the message is in. (`READ_MESSAGES` permission.)
2214
+ * - Requiring the `MESSAGE_CONTENT` intent.
2215
+ *
2216
+ * Does not support ephemeral follow-up messages due to these being stateless.
2217
+ *
2218
+ * @see {@link https://docs.discord.com/developers/interactions/receiving-and-responding#get-original-interaction-response}
2219
+ */ async getOriginalInteractionResponse (rest, token) {
2220
+ return await rest.get(rest.routes.interactions.responses.original(rest.applicationId, token), {
2221
+ unauthorized: true
2222
+ });
2223
+ },
2224
+ /**
2225
+ * Retrieves the list of pins in a channel.
2226
+ *
2227
+ * @param channelId - The ID of the channel to get the pins for.
2228
+ * @param options - The options for the fetching of the pins.
2229
+ * @returns A {@link DiscordGetChannelPins} objects
2230
+ *
2231
+ * @remarks
2232
+ * Requires the `VIEW_CHANNEL` permission.
2233
+ *
2234
+ * If the user is missing the `READ_MESSAGE_HISTORY` permission in the channel, then no pins will be returned.
2235
+ *
2236
+ * @see {@link https://docs.discord.com/developers/resources/message#get-channel-pins}
2237
+ */ async getChannelPins (rest, channelId, options) {
2238
+ return await rest.get(rest.routes.channels.messagePins(channelId, options));
2239
+ },
2240
+ /**
2241
+ * Gets the pinned messages for a channel.
2242
+ *
2243
+ * @param channelId - The ID of the channel to get the pinned messages for.
2244
+ * @returns A collection of {@link DiscordMessage} objects assorted by message ID.
2245
+ *
2246
+ * @remarks
2247
+ * Requires that the bot user be able to see the contents of the channel in which the messages were posted.
2248
+ *
2249
+ * If getting a message from a guild channel:
2250
+ * - Requires the `READ_MESSAGE_HISTORY` permission.
2251
+ *
2252
+ * @see {@link https://docs.discord.com/developers/resources/message#get-pinned-messages-deprecated}
2253
+ * @deprecated Use {@link getChannelPins} instead.
2254
+ */ async getPinnedMessages (rest, channelId) {
2255
+ return await rest.get(rest.routes.channels.pins(channelId));
2256
+ },
2257
+ /**
2258
+ * Gets the list of private archived threads for a channel.
2259
+ *
2260
+ * @param channelId - The ID of the channel to get the archived threads for.
2261
+ * @param options - The parameters for the fetching of threads.
2262
+ * @returns An instance of {@link DiscordListArchivedThreads}.
2263
+ *
2264
+ * @remarks
2265
+ * Requires the `READ_MESSAGE_HISTORY` permission.
2266
+ * Requires the `MANAGE_THREADS` permission.
2267
+ *
2268
+ * Returns threads of type {@link ChannelTypes}.GuildPrivateThread.
2269
+ *
2270
+ * Threads are ordered by the `archive_timestamp` property included in the metadata of the object in descending order.
2271
+ *
2272
+ * @see {@link https://docs.discord.com/developers/resources/channel#list-private-archived-threads}
2273
+ */ async getPrivateArchivedThreads (rest, channelId, options) {
2274
+ return await rest.get(rest.routes.channels.threads.private(channelId, options));
2275
+ },
2276
+ /**
2277
+ * Gets the list of private archived threads the bot is a member of for a channel.
2278
+ *
2279
+ * @param channelId - The ID of the channel to get the archived threads for.
2280
+ * @param options - The parameters for the fetching of threads.
2281
+ * @returns An instance of {@link DiscordListArchivedThreads}.
2282
+ *
2283
+ * @remarks
2284
+ * Requires the `READ_MESSAGE_HISTORY` permission.
2285
+ *
2286
+ * Returns threads of type {@link ChannelTypes}.GuildPrivateThread.
2287
+ *
2288
+ * Threads are ordered by the `id` property in descending order.
2289
+ *
2290
+ * @see {@link https://docs.discord.com/developers/resources/channel#list-joined-private-archived-threads}
2291
+ */ async getPrivateJoinedArchivedThreads (rest, channelId, options) {
2292
+ return await rest.get(rest.routes.channels.threads.joined(channelId, options));
2293
+ },
2294
+ /**
2295
+ * Gets the number of members that would be kicked from a guild during pruning.
2296
+ *
2297
+ * @param guildId - The ID of the guild to get the prune count of.
2298
+ * @param options - The parameters for the fetching of the prune count.
2299
+ * @returns A number indicating the number of members that would be kicked.
2300
+ *
2301
+ * @remarks
2302
+ * Requires the `MANAGE_GUILD` and `KICK_MEMBERS` permissions, unless the guild has the `PRUNE_REQUIRES_ADMIN` guild feature, in which case it requires the `ADMINISTRATOR` permission.
2303
+ *
2304
+ * @see {@link https://docs.discord.com/developers/resources/guild#get-guild-prune-count}
2305
+ */ async getPruneCount (rest, guildId, options) {
2306
+ return await rest.get(rest.routes.guilds.prune(guildId, options));
2307
+ },
2308
+ /**
2309
+ * Gets the list of public archived threads for a channel.
2310
+ *
2311
+ * @param channelId - The ID of the channel to get the archived threads for.
2312
+ * @param options - The parameters for the fetching of threads.
2313
+ * @returns An instance of {@link DiscordListArchivedThreads}.
2314
+ *
2315
+ * @remarks
2316
+ * Requires the `READ_MESSAGE_HISTORY` permission.
2317
+ *
2318
+ * If called on a channel of type {@link ChannelTypes}.GuildText, returns threads of type {@link ChannelTypes}.GuildPublicThread.
2319
+ * If called on a channel of type {@link ChannelTypes}.GuildNews, returns threads of type {@link ChannelTypes}.GuildNewsThread.
2320
+ *
2321
+ * Threads are ordered by the `archive_timestamp` property included in the metadata of the object in descending order.
2322
+ *
2323
+ * @see {@link https://docs.discord.com/developers/resources/channel#list-public-archived-threads}
2324
+ */ async getPublicArchivedThreads (rest, channelId, options) {
2325
+ return await rest.get(rest.routes.channels.threads.public(channelId, options));
2326
+ },
2327
+ /**
2328
+ * Gets the list of roles for a guild.
2329
+ *
2330
+ * @param guildId - The ID of the guild to get the list of roles for.
2331
+ * @returns A collection of {@link DiscordRole} objects assorted by role ID.
2332
+ *
2333
+ * @remarks
2334
+ * ⚠️ This endpoint should be used sparingly due to {@link DiscordRole} objects already being included in guild payloads.
2335
+ *
2336
+ * @see {@link https://docs.discord.com/developers/resources/guild#get-guild-roles}
2337
+ */ async getRoles (rest, guildId) {
2338
+ return await rest.get(rest.routes.guilds.roles.all(guildId));
2339
+ },
2340
+ /**
2341
+ * Gets a role by id for a guild.
2342
+ *
2343
+ * @param guildId - The ID of the guild to get role for.
2344
+ * @param roleId - The ID of the role.
2345
+ * @returns A {@link DiscordRole} object.
2346
+ *
2347
+ * @see {@link https://docs.discord.com/developers/resources/guild#get-guild-role}
2348
+ */ async getRole (rest, guildId, roleId) {
2349
+ return await rest.get(rest.routes.guilds.roles.one(guildId, roleId));
2350
+ },
2351
+ /**
2352
+ * Gets a scheduled event by its ID.
2353
+ *
2354
+ * @param guildId - The ID of the guild to get the scheduled event from.
2355
+ * @param eventId - The ID of the scheduled event to get.
2356
+ * @param options - The parameters for the fetching of the scheduled event.
2357
+ * @returns An instance of {@link DiscordScheduledEvent}.
2358
+ *
2359
+ * @see {@link https://docs.discord.com/developers/resources/guild-scheduled-event#get-guild-scheduled-event}
2360
+ */ async getScheduledEvent (rest, guildId, eventId, options) {
2361
+ return await rest.get(rest.routes.guilds.events.event(guildId, eventId, options?.withUserCount));
2362
+ },
2363
+ /**
2364
+ * Gets the list of scheduled events for a guild.
2365
+ *
2366
+ * @param guildId - The ID of the guild to get the scheduled events from.
2367
+ * @param options - The parameters for the fetching of the scheduled events.
2368
+ * @returns A collection of {@link DiscordScheduledEvent} objects assorted by event ID.
2369
+ *
2370
+ * @see {@link https://docs.discord.com/developers/resources/guild-scheduled-event#list-scheduled-events-for-guild}
2371
+ */ async getScheduledEvents (rest, guildId, options) {
2372
+ return await rest.get(rest.routes.guilds.events.events(guildId, options?.withUserCount));
2373
+ },
2374
+ /**
2375
+ * Gets the list of subscribers to a scheduled event from a guild.
2376
+ *
2377
+ * @param guildId - The ID of the guild to get the subscribers to the scheduled event from.
2378
+ * @param eventId - The ID of the scheduled event to get the subscribers of.
2379
+ * @param options - The parameters for the fetching of the subscribers.
2380
+ * @returns A collection of {@link DiscordUser} objects assorted by user ID.
2381
+ *
2382
+ * @remarks
2383
+ * Requires the `MANAGE_EVENTS` permission.
2384
+ *
2385
+ * Users are ordered by their IDs in _ascending_ order.
2386
+ *
2387
+ * @see {@link https://docs.discord.com/developers/resources/guild-scheduled-event#get-guild-scheduled-event-users}
2388
+ */ async getScheduledEventUsers (rest, guildId, eventId, options) {
2389
+ return await rest.get(rest.routes.guilds.events.users(guildId, eventId, options));
2390
+ },
2391
+ /** Get the bots Gateway metadata that can help during the operation of large or sharded bots. */ async getSessionInfo (rest) {
2392
+ return await rest.snake.getGatewayBot();
2393
+ },
2394
+ /**
2395
+ * Gets the stage instance associated with a stage channel, if one exists.
2396
+ *
2397
+ * @param channelId - The ID of the stage channel the stage instance is associated with.
2398
+ * @returns An instance of {@link DiscordStageInstance}.
2399
+ *
2400
+ * @see {@link https://docs.discord.com/developers/resources/stage-instance#get-stage-instance}
2401
+ */ async getStageInstance (rest, channelId) {
2402
+ return await rest.get(rest.routes.channels.stage(channelId));
2403
+ },
2404
+ /**
2405
+ * Returns the current user's voice state in the guild.
2406
+ *
2407
+ * @param guildId - The ID of the guild to get the voice state from.
2408
+ * @returns An instance of {@link DiscordVoiceState}.
2409
+ *
2410
+ * @see {@link https://docs.discord.com/developers/resources/voice#get-current-user-voice-state}
2411
+ */ async getOwnVoiceState (rest, guildId) {
2412
+ return await rest.get(rest.routes.guilds.voice(guildId));
2413
+ },
2414
+ /**
2415
+ * Returns the specified user's voice state in the guild.
2416
+ *
2417
+ * @param guildId - The ID of the guild to get the voice state from.
2418
+ * @param userId - The ID of the user to get the voice state from
2419
+ * @returns An instance of {@link DiscordVoiceState}.
2420
+ *
2421
+ * @remarks
2422
+ * If the specified user is connected to a voice channel, the current user must have permission to connect to the channel.
2423
+ *
2424
+ * @see {@link https://docs.discord.com/developers/resources/voice#get-user-voice-state}
2425
+ */ async getUserVoiceState (rest, guildId, userId) {
2426
+ return await rest.get(rest.routes.guilds.voice(guildId, userId));
2427
+ },
2428
+ /**
2429
+ * Returns a sticker object for the given sticker ID.
2430
+ *
2431
+ * @param stickerId The ID of the sticker to get
2432
+ * @returns A {@link DiscordSticker}
2433
+ *
2434
+ * @see {@link https://docs.discord.com/developers/resources/sticker#get-sticker}
2435
+ */ async getSticker (rest, stickerId) {
2436
+ return await rest.get(rest.routes.sticker(stickerId));
2437
+ },
2438
+ /**
2439
+ * Gets a thread member by their user ID.
2440
+ *
2441
+ * @param channelId - The ID of the thread to get the thread member of.
2442
+ * @param userId - The user ID of the thread member to get.
2443
+ * @param options - The parameters for the fetching of the thread member.
2444
+ * @returns An instance of {@link DiscordThreadMember}.
2445
+ *
2446
+ * @see {@link https://docs.discord.com/developers/resources/channel#get-thread-member}
2447
+ */ async getThreadMember (rest, channelId, userId, options) {
2448
+ return await rest.get(rest.routes.channels.threads.getUser(channelId, userId, options));
2449
+ },
2450
+ /**
2451
+ * Gets the list of thread members for a thread.
2452
+ *
2453
+ * @param channelId - The ID of the thread to get the thread members of.
2454
+ * @param options - The parameters for the fetching of the thread members.
2455
+ * @returns A collection of {@link DiscordThreadMember} assorted by user ID.
2456
+ *
2457
+ * @remarks
2458
+ * Requires the application to have the `GUILD_MEMBERS` privileged intent enabled.
2459
+ *
2460
+ * @see {@link https://docs.discord.com/developers/resources/channel#list-thread-members}
2461
+ */ async getThreadMembers (rest, channelId, options) {
2462
+ return await rest.get(rest.routes.channels.threads.members(channelId, options));
2463
+ },
2464
+ /**
2465
+ * Gets the list of users that reacted with an emoji to a message.
2466
+ *
2467
+ * @param channelId - The ID of the channel the message to get the users for is in.
2468
+ * @param messageId - The ID of the message to get the users for.
2469
+ * @param reaction - The reaction for which to get the users.
2470
+ * @param options - The parameters for the fetching of the users.
2471
+ * @returns A collection of {@link DiscordUser} objects assorted by user ID.
2472
+ *
2473
+ * @see {@link https://docs.discord.com/developers/resources/channel#get-reactions}
2474
+ */ async getReactions (rest, channelId, messageId, reaction, options) {
2475
+ return await rest.get(rest.routes.channels.reactions.message(channelId, messageId, reaction, options));
2476
+ },
2477
+ /**
2478
+ * Get a user's data from the api
2479
+ *
2480
+ * @param id The user's id
2481
+ * @returns {DiscordUser}
2482
+ */ async getUser (rest, id) {
2483
+ return await rest.get(rest.routes.user(id));
2484
+ },
2485
+ /**
2486
+ * Get the current user data.
2487
+ *
2488
+ * @param bearerToken - The access token of the user
2489
+ * @returns {DiscordUser}
2490
+ *
2491
+ * @remarks
2492
+ * This requires the `identify` scope.
2493
+ *
2494
+ * To get the mail this also requires the `email` scope
2495
+ */ async getCurrentUser (rest, bearerToken) {
2496
+ return await rest.get(rest.routes.currentUser(), {
2497
+ headers: {
2498
+ authorization: `Bearer ${bearerToken}`
2499
+ },
2500
+ unauthorized: true
2501
+ });
2502
+ },
2503
+ /**
2504
+ * Get the current user connections.
2505
+ *
2506
+ * @param bearerToken - The access token of the user
2507
+ * @returns {DiscordConnection[]}
2508
+ *
2509
+ * @remarks
2510
+ * This requires the `connections` scope.
2511
+ */ async getUserConnections (rest, bearerToken) {
2512
+ return await rest.get(rest.routes.oauth2.connections(), {
2513
+ headers: {
2514
+ authorization: `Bearer ${bearerToken}`
2515
+ },
2516
+ unauthorized: true
2517
+ });
2518
+ },
2519
+ /**
2520
+ * Get the current user application role connection for the application.
2521
+ *
2522
+ * @param bearerToken - The access token of the user
2523
+ * @param applicationId - The id of the application to get the role connection
2524
+ * @returns {DiscordApplicationRoleConnection}
2525
+ *
2526
+ * @remarks
2527
+ * The access token requires the `role_connections.write` scope.
2528
+ *
2529
+ * @see {@link https://docs.discord.com/developers/resources/user#get-user-application-role-connection}
2530
+ */ async getUserApplicationRoleConnection (rest, bearerToken, applicationId) {
2531
+ return await rest.get(rest.routes.oauth2.roleConnections(applicationId), {
2532
+ headers: {
2533
+ authorization: `Bearer ${bearerToken}`
2534
+ },
2535
+ unauthorized: true
2536
+ });
2537
+ },
2538
+ /**
2539
+ * Gets information about the vanity url of a guild.
2540
+ *
2541
+ * @param guildId - The ID of the guild to get the vanity url information for.
2542
+ * @returns An instance of {@link DiscordVanityUrl}.
2543
+ *
2544
+ * @remarks
2545
+ * Requires the `MANAGE_GUILD` permission.
2546
+ *
2547
+ * The `code` property will be `null` if the guild does not have a set vanity url.
2548
+ *
2549
+ * @see {@link https://docs.discord.com/developers/resources/guild#get-guild-vanity-url}
2550
+ */ async getVanityUrl (rest, guildId) {
2551
+ return await rest.get(rest.routes.guilds.vanity(guildId));
2552
+ },
2553
+ /**
2554
+ * Gets the list of voice regions for a guild.
2555
+ *
2556
+ * @param guildId - The ID of the guild to get the voice regions for.
2557
+ * @returns A collection of {@link DiscordVoiceRegion} objects assorted by voice region ID.
2558
+ *
2559
+ * @see {@link https://docs.discord.com/developers/resources/guild#get-guild-voice-regions}
2560
+ */ async getVoiceRegions (rest, guildId) {
2561
+ return await rest.get(rest.routes.guilds.regions(guildId));
2562
+ },
2563
+ /**
2564
+ * Gets a webhook by its ID.
2565
+ *
2566
+ * @param webhookId - The ID of the webhook to get.
2567
+ * @returns An instance of {@link DiscordWebhook}.
2568
+ *
2569
+ * @remarks
2570
+ * Requires the `MANAGE_WEBHOOKS` permission unless the application making the request owns the webhook.
2571
+ *
2572
+ * @see {@link https://docs.discord.com/developers/resources/webhook#get-webhook}
2573
+ */ async getWebhook (rest, webhookId) {
2574
+ return await rest.get(rest.routes.webhooks.id(webhookId));
2575
+ },
2576
+ /**
2577
+ * Gets a webhook message by its ID.
2578
+ *
2579
+ * @param webhookId - The ID of the webhook to get a message of.
2580
+ * @param token - The webhook token, used to get webhook messages.
2581
+ * @param messageId - the ID of the webhook message to get.
2582
+ * @param options - The parameters for the fetching of the message.
2583
+ * @returns An instance of {@link DiscordMessage}.
2584
+ *
2585
+ * @see {@link https://docs.discord.com/developers/resources/webhook#get-webhook-message}
2586
+ */ async getWebhookMessage (rest, webhookId, token, messageId, options) {
2587
+ return await rest.get(rest.routes.webhooks.message(webhookId, token, messageId, options), {
2588
+ unauthorized: true
2589
+ });
2590
+ },
2591
+ /**
2592
+ * Gets a webhook using the webhook token, thereby bypassing the need for authentication + permissions.
2593
+ *
2594
+ * @param webhookId - The ID of the webhook to get.
2595
+ * @param token - The webhook token, used to get the webhook.
2596
+ * @returns An instance of {@link DiscordWebhook}.
2597
+ *
2598
+ * @see {@link https://docs.discord.com/developers/resources/webhook#get-webhook-with-token}
2599
+ */ async getWebhookWithToken (rest, webhookId, token) {
2600
+ return await rest.get(rest.routes.webhooks.webhook(webhookId, token), {
2601
+ unauthorized: true
2602
+ });
2603
+ },
2604
+ /**
2605
+ * Gets the welcome screen for a guild.
2606
+ *
2607
+ * @param guildId - The ID of the guild to get the welcome screen for.
2608
+ * @returns An instance of {@link DiscordWelcomeScreen}.
2609
+ *
2610
+ * @remarks
2611
+ * If the welcome screen is not enabled:
2612
+ * - Requires the `MANAGE_GUILD` permission.
2613
+ *
2614
+ * @see {@link https://docs.discord.com/developers/resources/guild#get-guild-welcome-screen}
2615
+ */ async getWelcomeScreen (rest, guildId) {
2616
+ return await rest.get(rest.routes.guilds.welcome(guildId));
2617
+ },
2618
+ /**
2619
+ * Gets the guild widget by guild ID.
2620
+ *
2621
+ * @param guildId - The ID of the guild to get the widget of.
2622
+ * @returns An instance of {@link DiscordGuildWidget}.
2623
+ *
2624
+ * @remarks
2625
+ * Fires an `INVITE_CREATED` Gateway event when an invite channel is defined and a new `Invite` is generated.
2626
+ *
2627
+ * @see {@link https://docs.discord.com/developers/resources/guild#get-guild-widget}
2628
+ */ async getWidget (rest, guildId) {
2629
+ return await rest.get(rest.routes.guilds.widgetJson(guildId));
2630
+ },
2631
+ /**
2632
+ * Gets the settings of a guild's widget.
2633
+ *
2634
+ * @param guildId - The ID of the guild to get the widget of.
2635
+ * @returns An instance of {@link DiscordGuildWidgetSettings}.
2636
+ *
2637
+ * @remarks
2638
+ * Requires the `MANAGE_GUILD` permission.
2639
+ *
2640
+ * @see {@link https://docs.discord.com/developers/resources/guild#get-guild-widget-settings}
2641
+ */ async getWidgetSettings (rest, guildId) {
2642
+ return await rest.get(rest.routes.guilds.widget(guildId));
2643
+ },
2644
+ /**
2645
+ * Adds the bot user to a thread.
2646
+ *
2647
+ * @param channelId - The ID of the thread to add the bot user to.
2648
+ *
2649
+ * @remarks
2650
+ * Requires the thread not be archived.
2651
+ *
2652
+ * Fires a _Thread Members Update_ gateway event.
2653
+ *
2654
+ * @see {@link https://docs.discord.com/developers/resources/channel#join-thread}
2655
+ */ async joinThread (rest, channelId) {
2656
+ await rest.put(rest.routes.channels.threads.me(channelId));
2657
+ },
2658
+ /**
2659
+ * Leaves a guild.
2660
+ *
2661
+ * @param guildId - The ID of the guild to leave.
2662
+ *
2663
+ * @remarks
2664
+ * Fires a _Guild Delete_ event.
2665
+ *
2666
+ * @see {@link https://docs.discord.com/developers/resources/user#leave-guild}
2667
+ */ async leaveGuild (rest, guildId) {
2668
+ await rest.delete(rest.routes.guilds.leave(guildId));
2669
+ },
2670
+ /**
2671
+ * Removes the bot user from a thread.
2672
+ *
2673
+ * @param channelId - The ID of the thread to remove the bot user from.
2674
+ *
2675
+ * @remarks
2676
+ * Requires the thread not be archived.
2677
+ *
2678
+ * Fires a _Thread Members Update_ gateway event.
2679
+ *
2680
+ * @see {@link https://docs.discord.com/developers/resources/channel#leave-thread}
2681
+ */ async leaveThread (rest, channelId) {
2682
+ await rest.delete(rest.routes.channels.threads.me(channelId));
2683
+ },
2684
+ /**
2685
+ * Cross-posts a message posted in an announcement channel to subscribed channels.
2686
+ *
2687
+ * @param channelId - The ID of the announcement channel.
2688
+ * @param messageId - The ID of the message to cross-post.
2689
+ * @returns An instance of the cross-posted {@link DiscordMessage}.
2690
+ *
2691
+ * @remarks
2692
+ * Requires the `SEND_MESSAGES` permission.
2693
+ *
2694
+ * If not cross-posting own message:
2695
+ * - Requires the `MANAGE_MESSAGES` permission.
2696
+ *
2697
+ * Fires a _Message Create_ event in the guilds the subscribed channels are in.
2698
+ *
2699
+ * @see {@link https://docs.discord.com/developers/resources/channel#crosspost-message}
2700
+ */ async publishMessage (rest, channelId, messageId) {
2701
+ return await rest.post(rest.routes.channels.crosspost(channelId, messageId));
2702
+ },
2703
+ /**
2704
+ * Removes a role from a member.
2705
+ *
2706
+ * @param guildId - The ID of the guild the member to remove the role from is in.
2707
+ * @param userId - The user ID of the member to remove the role from.
2708
+ * @param roleId - The ID of the role to remove from the member.
2709
+ * @param {string} [reason] - An optional reason for the action, to be included in the audit log.
2710
+ *
2711
+ * @remarks
2712
+ * Requires the `MANAGE_ROLES` permission.
2713
+ *
2714
+ * Fires a _Guild Member Update_ gateway event.
2715
+ *
2716
+ * @see {@link https://docs.discord.com/developers/resources/guild#remove-guild-member-role}
2717
+ */ async removeRole (rest, guildId, userId, roleId, reason) {
2718
+ await rest.delete(rest.routes.guilds.roles.member(guildId, userId, roleId), {
2719
+ reason
2720
+ });
2721
+ },
2722
+ /**
2723
+ * Removes a member from a thread.
2724
+ *
2725
+ * @param channelId - The ID of the thread to remove the thread member of.
2726
+ * @param userId - The user ID of the thread member to remove.
2727
+ *
2728
+ * @remarks
2729
+ * If the thread is of type {@link ChannelTypes}.GuildPrivateThread, requires to be the creator of the thread.
2730
+ * Otherwise, requires the `MANAGE_THREADS` permission.
2731
+ *
2732
+ * Requires the thread not be archived.
2733
+ *
2734
+ * Fires a _Thread Members Update_ gateway event.
2735
+ *
2736
+ * @see {@link https://docs.discord.com/developers/resources/channel#remove-thread-member}
2737
+ */ async removeThreadMember (rest, channelId, userId) {
2738
+ await rest.delete(rest.routes.channels.threads.user(channelId, userId));
2739
+ },
2740
+ /**
2741
+ * Removes a member from a Group DM.
2742
+ *
2743
+ * @param channelId - The ID of the channel to remove the recipient user of.
2744
+ * @param userId - The user ID of the user to remove.
2745
+ *
2746
+ * @see {@link https://docs.discord.com/developers/resources/channel#group-dm-remove-recipient}
2747
+ */ async removeDmRecipient (rest, channelId, userId) {
2748
+ await rest.delete(rest.routes.channels.dmRecipient(channelId, userId));
2749
+ },
2750
+ /**
2751
+ * Sends a message to a channel.
2752
+ *
2753
+ * @param channelId - The ID of the channel to send the message in.
2754
+ * @param options - The parameters for the creation of the message.
2755
+ * @returns An instance of the created {@link DiscordMessage}.
2756
+ *
2757
+ * @remarks
2758
+ * Requires that the bot user be able to see the contents of the channel the message is to be sent in.
2759
+ *
2760
+ * If sending a message to a guild channel:
2761
+ * - Requires the `SEND_MESSAGES` permission.
2762
+ *
2763
+ * If sending a TTS message:
2764
+ * - Requires the `SEND_TTS_MESSAGES` permission.
2765
+ *
2766
+ * If sending a message as a reply to another message:
2767
+ * - Requires the `READ_MESSAGE_HISTORY` permission.
2768
+ * - The message being replied to cannot be a system message.
2769
+ *
2770
+ * ⚠️ The maximum size of a request (accounting for any attachments and message content) for bot users is _8 MiB_.
2771
+ *
2772
+ * Fires a _Message Create_ gateway event.
2773
+ *
2774
+ * @see {@link https://docs.discord.com/developers/resources/channel#create-message}
2775
+ */ async sendMessage (rest, channelId, options) {
2776
+ return await rest.post(rest.routes.channels.messages(channelId), {
2777
+ body: options,
2778
+ files: options.files
2779
+ });
2780
+ },
2781
+ /**
2782
+ * Sends a follow-up message to an interaction.
2783
+ *
2784
+ * @param token - The interaction token to use, provided in the original interaction.
2785
+ * @param options - The parameters for the creation of the message.
2786
+ * @returns An instance of the created {@link DiscordMessage}.
2787
+ *
2788
+ * @remarks
2789
+ * ⚠️ Interaction tokens are only valid for _15 minutes_.
2790
+ *
2791
+ * By default, mentions are suppressed. To enable mentions, pass a mention object with the callback data.
2792
+ *
2793
+ * Unlike `sendMessage()`, this endpoint allows the bot user to act without:
2794
+ * - Needing to be able to see the contents of the channel that the message is in. (`READ_MESSAGES` permission.)
2795
+ * - Requiring the `MESSAGE_CONTENT` intent.
2796
+ *
2797
+ * Apps are limited to 5 followup messages per interaction if it was initiated from a user-installed app and isn't installed in the server
2798
+ * You can check if it was initiated from a user-installed app that isn't installed in the server by checking if {@link DiscordInteraction.authorizing_integration_owners | authorizingIntegrationOwners} only contains {@link DiscordApplicationIntegrationType.UserInstall | UserInstall}.
2799
+ *
2800
+ * Fires a _Message Create_ event.
2801
+ *
2802
+ * @see {@link https://docs.discord.com/developers/interactions/receiving-and-responding#create-followup-message}
2803
+ */ async sendFollowupMessage (rest, token, options) {
2804
+ return await rest.post(rest.routes.webhooks.webhook(rest.applicationId, token), {
2805
+ body: options,
2806
+ files: options.files,
2807
+ unauthorized: true
2808
+ });
2809
+ },
2810
+ /**
2811
+ * Sends a response to an interaction.
2812
+ *
2813
+ * @param interactionId - The ID of the interaction to respond to.
2814
+ * @param token - The interaction token to use, provided in the original interaction.
2815
+ * @param options - The parameters for the creation of the message.
2816
+ * @param params - The query parameters for the response of the callback
2817
+ * @returns Nothing or the {@link DiscordInteractionCallbackResponse} if withResponse param is true
2818
+ *
2819
+ * @remarks
2820
+ * ⚠️ Interaction tokens are only valid for _15 minutes_.
2821
+ *
2822
+ * By default, mentions are suppressed. To enable mentions, pass a mention object with the callback data.
2823
+ *
2824
+ * Unlike `sendMessage()`, this endpoint allows the bot user to act without:
2825
+ * - Needing to be able to see the contents of the channel that the message is in. (`READ_MESSAGES` permission.)
2826
+ * - Requiring the `MESSAGE_CONTENT` intent.
2827
+ *
2828
+ * Fires a _Message Create_ event.
2829
+ *
2830
+ * @see {@link https://docs.discord.com/developers/interactions/receiving-and-responding#create-interaction-response}
2831
+ */ async sendInteractionResponse (rest, interactionId, token, options, params) {
2832
+ return await rest.post(rest.routes.interactions.responses.callback(interactionId, token, params), {
2833
+ body: options,
2834
+ files: options.data?.files,
2835
+ runThroughQueue: false,
2836
+ unauthorized: true
2837
+ });
2838
+ },
2839
+ /**
2840
+ * Creates a thread, using an existing message as its point of origin.
2841
+ *
2842
+ * @param channelId - The ID of the channel in which to create the thread.
2843
+ * @param messageId - The ID of the message to use as the thread's point of origin.
2844
+ * @param options - The parameters to use for the creation of the thread.
2845
+ * @param {string} [reason] - An optional reason for the action, to be included in the audit log.
2846
+ * @returns An instance of the created {@link DiscordChannel}.
2847
+ *
2848
+ * @remarks
2849
+ * If called on a channel of type {@link ChannelTypes}.GuildText, creates a {@link ChannelTypes}.GuildPublicThread.
2850
+ * If called on a channel of type {@link ChannelTypes}.GuildNews, creates a {@link ChannelTypes}.GuildNewsThread.
2851
+ * Does not work on channels of type {@link ChannelTypes}.GuildForum.
2852
+ *
2853
+ * The ID of the created thread will be the same as the ID of the source message.
2854
+ *
2855
+ * Fires a _Thread Create_ gateway event.
2856
+ *
2857
+ * @see {@link https://docs.discord.com/developers/resources/channel#start-thread-from-message}
2858
+ */ async startThreadWithMessage (rest, channelId, messageId, options, reason) {
2859
+ return await rest.post(rest.routes.channels.threads.message(channelId, messageId), {
2860
+ body: options,
2861
+ reason
2862
+ });
2863
+ },
2864
+ /**
2865
+ * Creates a thread without using a message as the thread's point of origin.
2866
+ *
2867
+ * @param channelId - The ID of the channel in which to create the thread.
2868
+ * @param options - The parameters to use for the creation of the thread.
2869
+ * @param {string} [reason] - An optional reason for the action, to be included in the audit log.
2870
+ * @returns An instance of the created {@link DiscordChannel | Thread}.
2871
+ *
2872
+ * @remarks
2873
+ * Creating a private thread requires the server to be boosted.
2874
+ *
2875
+ * Fires a _Thread Create_ gateway event.
2876
+ *
2877
+ * @see {@link https://docs.discord.com/developers/resources/channel#start-thread-without-message}
2878
+ */ async startThreadWithoutMessage (rest, channelId, options, reason) {
2879
+ return await rest.post(rest.routes.channels.threads.all(channelId), {
2880
+ body: options,
2881
+ reason
2882
+ });
2883
+ },
2884
+ /**
2885
+ * Get a list of users that voted for this specific answer.
2886
+ *
2887
+ * @param channelId - The ID of the channel in which the message with the poll lives
2888
+ * @param messageId - The ID of the message in which the poll lives
2889
+ * @param answerId - The ID of the answer to get the users that voted that answer
2890
+ * @param options - The options for the request
2891
+ * @returns The list of users that voted for the specific answer.
2892
+ */ async getPollAnswerVoters (rest, channelId, messageId, answerId, options) {
2893
+ return await rest.get(rest.routes.channels.polls.votes(channelId, messageId, answerId, options));
2894
+ },
2895
+ /**
2896
+ * Immediately ends the poll.
2897
+ *
2898
+ * @param channelId - The ID of the channel in which the message with the poll lives
2899
+ * @param messageId - The ID of the message in which the poll lives
2900
+ * @returns The message with the expired poll
2901
+ *
2902
+ * @remarks
2903
+ * You cannot end polls from other users.
2904
+ *
2905
+ * Fires a _Message Update_ gateway event
2906
+ */ async endPoll (rest, channelId, messageId) {
2907
+ return await rest.post(rest.routes.channels.polls.expire(channelId, messageId));
2908
+ },
2909
+ /**
2910
+ * Synchronises a template with the current state of a guild.
2911
+ *
2912
+ * @param guildId - The ID of the guild to synchronise a template of.
2913
+ * @returns An instance of the edited {@link DiscordTemplate}.
2914
+ *
2915
+ * @remarks
2916
+ * Requires the `MANAGE_GUILD` permission.
2917
+ *
2918
+ * Fires a _Guild Update_ gateway event.
2919
+ *
2920
+ * @see {@link https://docs.discord.com/developers/resources/guild-template#get-guild-templates}
2921
+ */ async syncGuildTemplate (rest, guildId) {
2922
+ return await rest.put(rest.routes.guilds.templates.all(guildId));
2923
+ },
2924
+ /**
2925
+ * Triggers a typing indicator for the specified channel, which expires after 10 seconds.
2926
+ *
2927
+ * @param channelId - The ID of the channel in which to trigger the typing indicator.
2928
+ *
2929
+ * @remarks
2930
+ * Generally bots should **not** use this route.
2931
+ * However, if a bot is responding to a command and expects the computation to take a few seconds,
2932
+ * this endpoint may be called to let the user know that the bot is processing their message.
2933
+ *
2934
+ * Fires a _Typing Start_ gateway event.
2935
+ *
2936
+ * @see {@link https://docs.discord.com/developers/resources/channel#trigger-typing-indicator}
2937
+ */ async triggerTypingIndicator (rest, channelId) {
2938
+ await rest.post(rest.routes.channels.typing(channelId));
2939
+ },
2940
+ /**
2941
+ * Re-registers the list of global application commands, overwriting the previous commands completely.
2942
+ *
2943
+ * @param commands - The list of commands to use to overwrite the previous list.
2944
+ * @param options - Additional options for the endpoint.
2945
+ * @returns A collection of {@link DiscordApplicationCommand} objects assorted by command ID.
2946
+ *
2947
+ * @remarks
2948
+ * ❗ Commands that are not present in the `commands` array will be __deleted__.
2949
+ *
2950
+ * ⚠️ Commands that do not already exist will count towards the daily limit of _200_ new commands.
2951
+ *
2952
+ * When using the bearer token the token needs the `applications.commands.update` scope and must be a `Client grant` token.
2953
+ * You will be able to update only your own application commands
2954
+ *
2955
+ * @see {@link https://docs.discord.com/developers/interactions/application-commands#bulk-overwrite-global-application-commands}
2956
+ */ async upsertGlobalApplicationCommands (rest, commands, options) {
2957
+ const restOptions = {
2958
+ body: commands
2959
+ };
2960
+ if (options?.bearerToken) {
2961
+ restOptions.unauthorized = true;
2962
+ restOptions.headers = {
2963
+ authorization: `Bearer ${options.bearerToken}`
2964
+ };
2965
+ }
2966
+ return await rest.put(rest.routes.interactions.commands.commands(rest.applicationId), restOptions);
2967
+ },
2968
+ /**
2969
+ * Re-registers the list of application commands registered in a guild, overwriting the previous commands completely.
2970
+ *
2971
+ * @param guildId - The ID of the guild whose list of commands to overwrite.
2972
+ * @param commands - The list of commands to use to overwrite the previous list.
2973
+ * @param options - Additional options for the endpoint.
2974
+ * @returns A collection of {@link DiscordApplicationCommand} objects assorted by command ID.
2975
+ *
2976
+ * @remarks
2977
+ * ❗ Commands that are not present in the `commands` array will be __deleted__.
2978
+ *
2979
+ * ⚠️ Commands that do not already exist will count towards the daily limit of _200_ new commands.
2980
+ *
2981
+ * When using the bearer token the token needs the `applications.commands.update` scope and must be a `Client grant` token.
2982
+ * You will be able to update only your own application commands
2983
+ *
2984
+ * @see {@link https://docs.discord.com/developers/interactions/application-commands#bulk-overwrite-guild-application-commands}
2985
+ */ async upsertGuildApplicationCommands (rest, guildId, commands, options) {
2986
+ const restOptions = {
2987
+ body: commands
2988
+ };
2989
+ if (options?.bearerToken) {
2990
+ restOptions.unauthorized = true;
2991
+ restOptions.headers = {
2992
+ authorization: `Bearer ${options.bearerToken}`
2993
+ };
2994
+ }
2995
+ return await rest.put(rest.routes.interactions.commands.guilds.all(rest.applicationId, guildId), restOptions);
2996
+ },
2997
+ /**
2998
+ * Bans a user from a guild.
2999
+ *
3000
+ * @param guildId - The ID of the guild to ban the user from.
3001
+ * @param userId - The ID of the user to ban from the guild.
3002
+ * @param options - The parameters for the creation of the ban.
3003
+ * @param {string} [reason] - An optional reason for the action, to be included in the audit log.
3004
+ *
3005
+ * @remarks
3006
+ * Requires the `BAN_MEMBERS` permission.
3007
+ *
3008
+ * Fires a _Guild Ban Add_ gateway event.
3009
+ *
3010
+ * @see {@link https://docs.discord.com/developers/resources/guild#create-guild-ban}
3011
+ */ async banMember (rest, guildId, userId, options, reason) {
3012
+ await rest.put(rest.routes.guilds.members.ban(guildId, userId), {
3013
+ body: options,
3014
+ reason
3015
+ });
3016
+ },
3017
+ /**
3018
+ * Bans up to 200 users from a guild.
3019
+ *
3020
+ * @param guildId - The ID of the guild to ban the users from.
3021
+ * @param options - The users to ban and the other options for the ban.
3022
+ * @param {string} [reason] - An optional reason for the action, to be included in the audit log.
3023
+ *
3024
+ * @remarks
3025
+ * Requires the `BAN_MEMBERS` and `MANAGE_GUILD` permissions.
3026
+ *
3027
+ * If all provided users fail to be banned, discord will respond with an error (code: `500000: Failed to ban users`)
3028
+ *
3029
+ * Fires as many _Guild Ban Add_ gateway events as many user where banned.
3030
+ *
3031
+ * @see {@link https://docs.discord.com/developers/resources/guild#bulk-guild-ban}
3032
+ */ async bulkBanMembers (rest, guildId, options, reason) {
3033
+ return await rest.post(rest.routes.guilds.members.bulkBan(guildId), {
3034
+ body: options,
3035
+ reason
3036
+ });
3037
+ },
3038
+ /**
3039
+ * Edits the nickname of the bot user.
3040
+ *
3041
+ * @param guildId - The ID of the guild to edit the nickname of the bot user in.
3042
+ * @param options - The parameters for the edit of the nickname.
3043
+ * @param {string} [reason] - An optional reason for the action, to be included in the audit log.
3044
+ * @returns An instance of the edited {@link DiscordMember}
3045
+ *
3046
+ * @remarks
3047
+ * Fires a _Guild Member Update_ gateway event.
3048
+ *
3049
+ * @see {@link https://docs.discord.com/developers/resources/guild#modify-current-member}
3050
+ */ async editCurrentMember (rest, guildId, options, reason) {
3051
+ return await rest.patch(rest.routes.guilds.members.bot(guildId), {
3052
+ body: options,
3053
+ reason
3054
+ });
3055
+ },
3056
+ /**
3057
+ * Edits a member's properties.
3058
+ *
3059
+ * @param guildId - The ID of the guild to edit the member of.
3060
+ * @param userId - The user ID of the member to edit.
3061
+ * @param {string} [reason] - An optional reason for the action, to be included in the audit log.
3062
+ * @param options - The parameters for the edit of the user.
3063
+ *
3064
+ * @remarks
3065
+ * This endpoint requires various permissions depending on what is edited about the member.
3066
+ * To find out the required permission to enact a change, read the documentation of this endpoint's {@link ModifyGuildMember | parameters}.
3067
+ *
3068
+ * Fires a _Guild Member Update_ gateway event.
3069
+ *
3070
+ * @see {@link https://docs.discord.com/developers/resources/guild#modify-guild-member}
3071
+ */ async editMember (rest, guildId, userId, options, reason) {
3072
+ return await rest.patch(rest.routes.guilds.members.member(guildId, userId), {
3073
+ body: options,
3074
+ reason
3075
+ });
3076
+ },
3077
+ /**
3078
+ * Gets the current member object.
3079
+ *
3080
+ * @param bearerToken - The access token of the user
3081
+ * @param guildId - The ID of the guild to get the member object for.
3082
+ * @returns An instance of {@link DiscordMemberWithUser}.
3083
+ *
3084
+ * @remarks
3085
+ * The access tokens needs the `guilds.members.read` scope
3086
+ *
3087
+ * @see {@link https://docs.discord.com/developers/resources/user#get-current-user-guild-member}
3088
+ */ async getCurrentMember (rest, guildId, bearerToken) {
3089
+ return await rest.get(rest.routes.guilds.members.currentMember(guildId), {
3090
+ headers: {
3091
+ authorization: `Bearer ${bearerToken}`
3092
+ },
3093
+ unauthorized: true
3094
+ });
3095
+ },
3096
+ /**
3097
+ * Gets the member object by user ID.
3098
+ *
3099
+
3100
+ * @param guildId - The ID of the guild to get the member object for.
3101
+ * @param userId - The ID of the user to get the member object for.
3102
+ * @returns An instance of {@link DiscordMemberWithUser}.
3103
+ *
3104
+ * @see {@link https://docs.discord.com/developers/resources/guild#get-guild-member}
3105
+ */ async getMember (rest, guildId, userId) {
3106
+ return await rest.get(rest.routes.guilds.members.member(guildId, userId));
3107
+ },
3108
+ /**
3109
+ * Gets the list of members for a guild.
3110
+ *
3111
+ * @param guildId - The ID of the guild to get the list of members for.
3112
+ * @param options - The parameters for the fetching of the members.
3113
+ * @returns A collection of {@link DiscordMemberWithUser} objects assorted by user ID.
3114
+ *
3115
+ * @remarks
3116
+ * Requires the `GUILD_MEMBERS` intent.
3117
+ *
3118
+ * ⚠️ It is not recommended to use this endpoint with very large bots. Instead, opt to use `fetchMembers()`:
3119
+ * REST communication only permits 50 requests to be made per second, while gateways allow for up to 120 requests
3120
+ * per minute per shard. For more information, read {@link https://docs.discord.com/developers/topics/rate-limits#rate-limits}.
3121
+ *
3122
+ * @see {@link https://docs.discord.com/developers/resources/guild#list-guild-members}
3123
+ * @see {@link https://docs.discord.com/developers/events/gateway-events#request-guild-members}
3124
+ * @see {@link https://docs.discord.com/developers/topics/rate-limits#rate-limits}
3125
+ */ async getMembers (rest, guildId, options) {
3126
+ return await rest.get(rest.routes.guilds.members.members(guildId, options));
3127
+ },
3128
+ /**
3129
+ * Returns a serialized activity instance, if it exists. Useful for preventing unwanted activity sessions.
3130
+ *
3131
+ * @param applicationId - The ID of the application
3132
+ * @param instanceId - The ID of the activity instance
3133
+ */ async getApplicationActivityInstance (rest, applicationId, instanceId) {
3134
+ return await rest.get(rest.routes.applicationActivityInstance(applicationId, instanceId));
3135
+ },
3136
+ /**
3137
+ * Kicks a member from a guild.
3138
+ *
3139
+
3140
+ * @param guildId - The ID of the guild to kick the member from.
3141
+ * @param userId - The user ID of the member to kick from the guild.
3142
+ * @param {string} [reason] - An optional reason for the action, to be included in the audit log.
3143
+ *
3144
+ * @remarks
3145
+ * Requires the `KICK_MEMBERS` permission.
3146
+ *
3147
+ * Fires a _Guild Member Remove_ gateway event.
3148
+ *
3149
+ * @see {@link https://docs.discord.com/developers/resources/guild#remove-guild-member}
3150
+ */ async kickMember (rest, guildId, userId, reason) {
3151
+ await rest.delete(rest.routes.guilds.members.member(guildId, userId), {
3152
+ reason
3153
+ });
3154
+ },
3155
+ /**
3156
+ * Pins a message in a channel.
3157
+ *
3158
+ * @param channelId - The ID of the channel where the message is to be pinned.
3159
+ * @param messageId - The ID of the message to pin.
3160
+ * @param {string} [reason] - An optional reason for the action, to be included in the audit log.
3161
+ *
3162
+ * @remarks
3163
+ * Requires the `PIN_MESSAGES` permission.
3164
+ *
3165
+ * Fires a _Channel Pins Update_ event.
3166
+ *
3167
+ * @see {@link https://docs.discord.com/developers/resources/message#pin-message}
3168
+ */ async pinMessage (rest, channelId, messageId, reason) {
3169
+ await rest.put(rest.routes.channels.messagePin(channelId, messageId), {
3170
+ reason
3171
+ });
3172
+ },
3173
+ /**
3174
+ * Initiates the process of pruning inactive members.
3175
+ *
3176
+
3177
+ * @param guildId - The ID of the guild to prune the members of.
3178
+ * @param options - The parameters for the pruning of members.
3179
+ * @param {string} [reason] - An optional reason for the action, to be included in the audit log.
3180
+ * @returns A number indicating how many members were pruned.
3181
+ *
3182
+ * @remarks
3183
+ * Requires the `MANAGE_GUILD` and `KICK_MEMBERS` permissions, unless the guild has the `PRUNE_REQUIRES_ADMIN` guild feature, in which case it requires the `ADMINISTRATOR` permission.
3184
+ *
3185
+ * ❗ Requests to this endpoint will time out for large guilds. To prevent this from happening, set the {@link BeginGuildPrune.computePruneCount} property of the options object parameter to `false`. This will begin the process of pruning, and immediately return `undefined`, rather than wait for the process to complete before returning the actual count of members that have been kicked.
3186
+ *
3187
+ * ⚠️ By default, this process will not remove members with a role. To include the members who have a _particular subset of roles_, specify the role(s) in the {@link BeginGuildPrune.includeRoles | includeRoles} property of the options object parameter.
3188
+ *
3189
+ * Fires a _Guild Member Remove_ gateway event for every member kicked.
3190
+ *
3191
+ * @see {@link https://docs.discord.com/developers/resources/guild#begin-guild-prune}
3192
+ */ async pruneMembers (rest, guildId, options, reason) {
3193
+ return await rest.post(rest.routes.guilds.members.prune(guildId), {
3194
+ body: options,
3195
+ reason
3196
+ });
3197
+ },
3198
+ /**
3199
+ * Gets the list of members whose usernames or nicknames start with a provided string.
3200
+ *
3201
+
3202
+ * @param guildId - The ID of the guild to search in.
3203
+ * @param query - The string to match usernames or nicknames against.
3204
+ * @param options - The parameters for searching through the members.
3205
+ * @returns A collection of {@link DiscordMember} objects assorted by user ID.
3206
+ *
3207
+ * @see {@link https://docs.discord.com/developers/resources/guild#search-guild-members}
3208
+ */ async searchMembers (rest, guildId, query, options) {
3209
+ return await rest.get(rest.routes.guilds.members.search(guildId, query, options));
3210
+ },
3211
+ /**
3212
+ * Unbans a user from a guild.
3213
+ *
3214
+ * @param guildId - The ID of the guild to unban the user in.
3215
+ * @param userId - The ID of the user to unban.
3216
+ * @param {string} [reason] - An optional reason for the action, to be included in the audit log.
3217
+ *
3218
+ * @remarks
3219
+ * Requires the `BAN_MEMBERS` permission.
3220
+ *
3221
+ * Fires a _Guild Ban Remove_ gateway event.
3222
+ *
3223
+ * @see {@link https://docs.discord.com/developers/resources/guild#remove-guild-ban}
3224
+ */ async unbanMember (rest, guildId, userId, reason) {
3225
+ await rest.delete(rest.routes.guilds.members.ban(guildId, userId), {
3226
+ reason
3227
+ });
3228
+ },
3229
+ /**
3230
+ * Unpin a message in a channel.
3231
+ *
3232
+ * @param channelId - The ID of the channel where the message is pinned.
3233
+ * @param messageId - The ID of the message to unpin.
3234
+ * @param {string} [reason] - An optional reason for the action, to be included in the audit log.
3235
+ *
3236
+ * @remarks
3237
+ * Requires the `PIN_MESSAGES` permission.
3238
+ *
3239
+ * Fires a _Channel Pins Update_ event.
3240
+ *
3241
+ * @see {@link https://docs.discord.com/developers/resources/message#unpin-message}
3242
+ */ async unpinMessage (rest, channelId, messageId, reason) {
3243
+ await rest.delete(rest.routes.channels.messagePin(channelId, messageId), {
3244
+ reason
3245
+ });
3246
+ },
3247
+ /**
3248
+ * Get the guild onboarding
3249
+ *
3250
+ * @param guildId - The guild to get the onboarding from
3251
+ */ async getGuildOnboarding (rest, guildId) {
3252
+ return await rest.get(rest.routes.guilds.onboarding(guildId));
3253
+ },
3254
+ /**
3255
+ * Modifies the onboarding configuration of the guild.
3256
+ *
3257
+ * @param guildId - The guild to edit the onboarding from
3258
+ * @param {string} [reason] - An optional reason for the action, to be included in the audit log.
3259
+ *
3260
+ * @remarks
3261
+ * Requires the `MANAGE_GUILD` and `MANAGE_ROLES` permissions.
3262
+ *
3263
+ * Onboarding enforces constraints when enabled. These constraints are:
3264
+ * - at least 7 default channels
3265
+ * - at least 5 of the 7 channels must allow sending messages to the \@everyone role
3266
+ *
3267
+ * The `mode` field modifies what is considered when enforcing these constraints.
3268
+ */ async editGuildOnboarding (rest, guildId, options, reason) {
3269
+ return await rest.put(rest.routes.guilds.onboarding(guildId), {
3270
+ body: options,
3271
+ reason
3272
+ });
3273
+ },
3274
+ /**
3275
+ * Modifies the incident actions of the guild.
3276
+ *
3277
+ * @param guildId - The guild to edit the incident actions from
3278
+ * @param options - The options for the incident actions
3279
+ *
3280
+ * @remarks
3281
+ * Requires the `MANAGE_GUILD` permission.
3282
+ */ async modifyGuildIncidentActions (rest, guildId, options) {
3283
+ return await rest.put(rest.routes.guilds.incidentActions(guildId), {
3284
+ body: options
3285
+ });
3286
+ },
3287
+ /**
3288
+ * Returns all entitlements for a given app, active and expired.
3289
+ *
3290
+ * @param applicationId - The id of the application to get the entitlements
3291
+ * @param {GetEntitlements} [options] - The optional query params for the endpoint
3292
+ */ async listEntitlements (rest, applicationId, options) {
3293
+ return await rest.get(rest.routes.monetization.entitlements(applicationId, options));
3294
+ },
3295
+ /**
3296
+ * Returns an entitlement.
3297
+ *
3298
+ * @param applicationId - The id of the application to get the entitlement
3299
+ * @param entitlementId - The id of the entitlement to get
3300
+ */ async getEntitlement (rest, applicationId, entitlementId) {
3301
+ return await rest.get(rest.routes.monetization.entitlement(applicationId, entitlementId));
3302
+ },
3303
+ /**
3304
+ * Creates a test entitlement to a given SKU for a given guild or user. Discord will act as though that user or guild has entitlement to your premium offering.
3305
+ *
3306
+ * @param applicationId - The id of the application to create the entitlement
3307
+ * @param body - The options for new entitlement
3308
+ *
3309
+ * @remarks
3310
+ * This endpoint returns a partial entitlement object.
3311
+ * It will not contain subscription_id, starts_at, or ends_at, as it's valid in perpetuity.
3312
+ */ async createTestEntitlement (rest, applicationId, body) {
3313
+ return await rest.post(rest.routes.monetization.entitlements(applicationId), {
3314
+ body
3315
+ });
3316
+ },
3317
+ /**
3318
+ * Deletes a currently-active test entitlement. Discord will act as though that user or guild no longer has entitlement to your premium offering.
3319
+ *
3320
+ * @param applicationId - The id of the application from where delete the entitlement
3321
+ * @param entitlementId - The id of the entitlement to delete
3322
+ */ async deleteTestEntitlement (rest, applicationId, entitlementId) {
3323
+ await rest.delete(rest.routes.monetization.entitlement(applicationId, entitlementId));
3324
+ },
3325
+ /**
3326
+ * For One-Time Purchase consumable SKUs, marks a given entitlement for the user as consumed. The entitlement will have `consumed: true` when using {@link listEntitlements | List Entitlements}
3327
+ *
3328
+ * @param applicationId - The id of the application to get the entitlement
3329
+ * @param entitlementId - The id of the entitlement to get
3330
+ */ async consumeEntitlement (rest, applicationId, entitlementId) {
3331
+ await rest.post(rest.routes.monetization.consumeEntitlement(applicationId, entitlementId));
3332
+ },
3333
+ /**
3334
+ * Returns all SKUs for a given application
3335
+ *
3336
+ * @param applicationId - The id of the application to get the SKUs
3337
+ */ async listSkus (rest, applicationId) {
3338
+ return await rest.get(rest.routes.monetization.skus(applicationId));
3339
+ },
3340
+ /**
3341
+ * Returns all subscriptions containing the SKU, filtered by user.
3342
+ *
3343
+ * @param skuId - The id of the sku of get the subscriptions for
3344
+ */ async listSubscriptions (rest, skuId, options) {
3345
+ return await rest.get(rest.routes.monetization.subscriptions(skuId, options));
3346
+ },
3347
+ /**
3348
+ * Get a subscription by its ID.
3349
+ *
3350
+ * @param skuId - The id of the sku of get the subscriptions for
3351
+ */ async getSubscription (rest, skuId, subscriptionId) {
3352
+ return await rest.get(rest.routes.monetization.subscription(skuId, subscriptionId));
3353
+ },
3354
+ /**
3355
+ * Send a soundboard sound to a voice channel the user is connected to.
3356
+ *
3357
+ * @param channelId - The id of the voice channel
3358
+ *
3359
+ * @remarks
3360
+ * Fires a _Voice Channel Effect Send_ Gateway event.
3361
+ *
3362
+ * Requires the `SPEAK` and `USE_SOUNDBOARD` permissions, and also the `USE_EXTERNAL_SOUNDS` permission if the sound is from a different server.
3363
+ * Additionally, requires the user to be connected to the voice channel, having a voice state without `deaf`, `self_deaf`, `mute`, or `suppress` enabled.
3364
+ */ async sendSoundboardSound (rest, channelId, options) {
3365
+ await rest.post(rest.routes.soundboard.sendSound(channelId), {
3366
+ body: options
3367
+ });
3368
+ },
3369
+ /** Returns an array of soundboard sound objects that can be used by all users. */ async listDefaultSoundboardSounds (rest) {
3370
+ return await rest.get(rest.routes.soundboard.listDefault());
3371
+ },
3372
+ /**
3373
+ * Returns a list of the guild's soundboard sounds.
3374
+ *
3375
+ * @param guildId - The guild to get the sounds from
3376
+ *
3377
+ * @remarks
3378
+ * Includes `user` fields if the bot has the `CREATE_GUILD_EXPRESSIONS` or `MANAGE_GUILD_EXPRESSIONS` permission.
3379
+ */ async listGuildSoundboardSounds (rest, guildId) {
3380
+ return await rest.get(rest.routes.soundboard.guildSounds(guildId));
3381
+ },
3382
+ /**
3383
+ * Returns a soundboard sound object for the given sound id.
3384
+ *
3385
+ * @param guildId - The guild to get the sounds from
3386
+ * @param soundId - The sound id
3387
+ *
3388
+ * @remarks
3389
+ * Includes `user` fields if the bot has the `CREATE_GUILD_EXPRESSIONS` or `MANAGE_GUILD_EXPRESSIONS` permission.
3390
+ */ async getGuildSoundboardSound (rest, guildId, soundId) {
3391
+ return await rest.get(rest.routes.soundboard.guildSound(guildId, soundId));
3392
+ },
3393
+ /**
3394
+ * Create a new soundboard sound for the guild.
3395
+ *
3396
+ * @param guildId - The guild to create the sounds in
3397
+ * @param options - The options to create the sound
3398
+ * @param reason - The audit log reason
3399
+ *
3400
+ * @remarks
3401
+ * Fires a _Guild Soundboard Sound Create_ Gateway event.
3402
+ *
3403
+ * Requires the `CREATE_GUILD_EXPRESSIONS` permission.
3404
+ */ async createGuildSoundboardSound (rest, guildId, options, reason) {
3405
+ return await rest.post(rest.routes.soundboard.guildSounds(guildId), {
3406
+ body: options,
3407
+ reason
3408
+ });
3409
+ },
3410
+ /**
3411
+ * Modify the given soundboard sound.
3412
+ *
3413
+ * @param guildId - The guild to create the sounds in
3414
+ * @param soundId - The sound id to update
3415
+ * @param options - The options to update the sound
3416
+ * @param reason - The audit log reason
3417
+ *
3418
+ * @remarks
3419
+ * Fires a _Guild Soundboard Sound Update_ Gateway event.
3420
+ *
3421
+ * For sounds created by the current user, requires either the `CREATE_GUILD_EXPRESSIONS` or `MANAGE_GUILD_EXPRESSIONS` permission.
3422
+ * For other sounds, requires the `MANAGE_GUILD_EXPRESSIONS` permission.
3423
+ */ async modifyGuildSoundboardSound (rest, guildId, soundId, options, reason) {
3424
+ return await rest.post(rest.routes.soundboard.guildSound(guildId, soundId), {
3425
+ body: options,
3426
+ reason
3427
+ });
3428
+ },
3429
+ /**
3430
+ * Delete the given soundboard sound.
3431
+ *
3432
+ * @param guildId - The guild to create the sounds in
3433
+ * @param soundId - The sound id to delete
3434
+ * @param reason - The audit log reason
3435
+ *
3436
+ * @remarks
3437
+ * Fires a _Guild Soundboard Sound Delete_ Gateway event.
3438
+ *
3439
+ * For sounds created by the current user, requires either the `CREATE_GUILD_EXPRESSIONS` or `MANAGE_GUILD_EXPRESSIONS` permission.
3440
+ * For other sounds, requires the `MANAGE_GUILD_EXPRESSIONS` permission.
3441
+ */ async deleteGuildSoundboardSound (rest, guildId, soundId, reason) {
3442
+ return await rest.delete(rest.routes.soundboard.guildSound(guildId, soundId), {
3443
+ reason
3444
+ });
3445
+ },
3446
+ /**
3447
+ * Returns a list of application role connection metadata objects for the given application.
3448
+ *
3449
+ * @param applicationId - The application to get the role connections from
3450
+ * @returns A list of application role connection metadata objects
3451
+ */ async listApplicationRoleConnectionsMetadataRecords (rest, applicationId) {
3452
+ return await rest.get(rest.routes.applicationRoleConnectionMetadata(applicationId));
3453
+ },
3454
+ /**
3455
+ * Updates and returns a list of application role connection metadata objects for the given application.
3456
+ *
3457
+ * @param applicationId - The application to get the role connections from
3458
+ * @param options - The options to update the role connections
3459
+ * @returns A list of application role connection metadata objects
3460
+ *
3461
+ * @remarks
3462
+ * An application can have a maximum of 5 metadata records.
3463
+ */ async updateApplicationRoleConnectionsMetadataRecords (rest, applicationId, options) {
3464
+ return await rest.put(rest.routes.applicationRoleConnectionMetadata(applicationId), {
3465
+ body: options
3466
+ });
3467
+ },
3468
+ /**
3469
+ * Creates a new lobby, adding any of the specified members to it, if provided.
3470
+ *
3471
+ * @param options - The options to create the lobby
3472
+ * @returns The created lobby
3473
+ */ async createLobby (rest, options) {
3474
+ return await rest.post(rest.routes.lobby.create(), {
3475
+ body: options
3476
+ });
3477
+ },
3478
+ /**
3479
+ * Creates a new lobby for the application identified by a `secret`, or joins the calling user to the existing lobby with that secret if one already exists.
3480
+ *
3481
+ * Updates lobby metadata and the calling member's metadata on join.
3482
+ *
3483
+ * @param options - The options to create or join the lobby
3484
+ * @returns - The created or joined lobby
3485
+ *
3486
+ * @remarks
3487
+ * Uses `Bearer` token for authorization with the `sdk.social_layer` scope.
3488
+ */ async createOrJoinLobby (rest, options) {
3489
+ return await rest.put(rest.routes.lobby.create(), {
3490
+ body: options
3491
+ });
3492
+ },
3493
+ /**
3494
+ * Returns a lobby object for the specified lobby id, if it exists.
3495
+ *
3496
+ * @param lobbyId - The ID of the lobby to get
3497
+ * @returns The lobby object
3498
+ */ async getLobby (rest, lobbyId) {
3499
+ return await rest.get(rest.routes.lobby.lobby(lobbyId));
3500
+ },
3501
+ /**
3502
+ * Modifies the specified lobby with new values, if provided.
3503
+ *
3504
+ * @param lobbyId - The ID of the lobby to modify
3505
+ * @param options - The options to modify the lobby
3506
+ * @returns The modified lobby
3507
+ */ async modifyLobby (rest, lobbyId, options) {
3508
+ return await rest.patch(rest.routes.lobby.lobby(lobbyId), {
3509
+ body: options
3510
+ });
3511
+ },
3512
+ /**
3513
+ * Deletes the specified lobby if it exists.
3514
+ *
3515
+ * It is safe to call even if the lobby is already deleted as well.
3516
+ *
3517
+ * @param lobbyId - The ID of the lobby to delete
3518
+ * @returns Nothing
3519
+ */ async deleteLobby (rest, lobbyId) {
3520
+ return await rest.delete(rest.routes.lobby.lobby(lobbyId));
3521
+ },
3522
+ /**
3523
+ * Adds the provided user to the specified lobby. If called when the user is already a member of the lobby will update fields such as metadata on that user instead.
3524
+ *
3525
+ * @param lobbyId - The ID of the lobby to add the user to
3526
+ * @param userId - The ID of the user to add to the lobby
3527
+ * @param options - The options to add the user to the lobby
3528
+ * @returns The lobby member object
3529
+ */ async addMemberToLobby (rest, lobbyId, userId, options) {
3530
+ return await rest.put(rest.routes.lobby.member(lobbyId, userId), {
3531
+ body: options
3532
+ });
3533
+ },
3534
+ /**
3535
+ * Adds, updates, or removes up to 25 members from the specified lobby in a single request.
3536
+ *
3537
+ * @param lobbyId - The ID of the lobby to add, update, or remove members from
3538
+ * @param options - The options to add, update, or remove members from the lobby
3539
+ * @returns Returns an array of lobby member objects for the upserted members. Removed members are not included in the response.
3540
+ *
3541
+ * @remarks
3542
+ * Members with `remove_member: false` (the default) are upserted — added if not present, or updated with the provided metadata and flags if already a member. Members with `remove_member: true` are removed.
3543
+ *
3544
+ * Users unknown to Discord will return a 404 UNKNOWN_USER error.
3545
+ * Users that fail permission checks or who have already reached the maximum number of lobbies per application (and are not already a member of this lobby) are silently dropped from the upsert set.
3546
+ *
3547
+ * @see {@link https://docs.discord.com/developers/resources/lobby#bulk-update-lobby-members}
3548
+ */ async bulkUpdateLobbyMembers (rest, lobbyId, options) {
3549
+ return await rest.post(rest.routes.lobby.membersBulk(lobbyId), {
3550
+ body: options
3551
+ });
3552
+ },
3553
+ /**
3554
+ * Removes the provided user from the specified lobby. It is safe to call this even if the user is no longer a member of the lobby, but will fail if the lobby does not exist.
3555
+ *
3556
+ * @param lobbyId - The ID of the lobby to remove the user from
3557
+ * @param userId - The ID of the user to remove from the lobby
3558
+ * @returns Nothing
3559
+ */ async removeMemberFromLobby (rest, lobbyId, userId) {
3560
+ return await rest.delete(rest.routes.lobby.member(lobbyId, userId));
3561
+ },
3562
+ /**
3563
+ * Removes the current user from the specified lobby. It is safe to call this even if the user is no longer a member of the lobby, but will fail if the lobby does not exist.
3564
+ *
3565
+ * @param lobbyId - The ID of the lobby to remove the user from
3566
+ * @param bearerToken - The access token of the user
3567
+ * @returns Nothing
3568
+ *
3569
+ * @remarks
3570
+ * This requires a bearer token for authorization
3571
+ */ async leaveLobby (rest, lobbyId, bearerToken) {
3572
+ return await rest.delete(rest.routes.lobby.leave(lobbyId), {
3573
+ headers: {
3574
+ authorization: `Bearer ${bearerToken}`
3575
+ },
3576
+ unauthorized: true
3577
+ });
3578
+ },
3579
+ /**
3580
+ * Links an existing text channel to a lobby.
3581
+ *
3582
+ * @param lobbyId - The ID of the lobby to link the channel to
3583
+ * @param bearerToken - The access token of the user
3584
+ * @param options - The options to link the channel to the lobby
3585
+ * @returns The updated lobby object
3586
+ *
3587
+ * @remarks
3588
+ * Uses bearer token for authorization and the user must be a lobby member with the CanLinkLobby lobby member flag.
3589
+ */ async linkChannelToLobby (rest, lobbyId, bearerToken, options) {
3590
+ return await rest.patch(rest.routes.lobby.link(lobbyId), {
3591
+ body: options,
3592
+ headers: {
3593
+ authorization: `Bearer ${bearerToken}`
3594
+ },
3595
+ unauthorized: true
3596
+ });
3597
+ },
3598
+ /**
3599
+ * Unlinks any currently linked channels from the specified lobby.
3600
+ *
3601
+ * @param lobbyId - The ID of the lobby to unlink the channel from
3602
+ * @param bearerToken - The access token of the user
3603
+ * @returns The updated lobby object
3604
+ *
3605
+ * @remarks
3606
+ * Uses bearer token for authorization and the user must be a lobby member with the CanLinkLobby lobby member flag.
3607
+ */ async unlinkChannelToLobby (rest, lobbyId, bearerToken) {
3608
+ return await rest.patch(rest.routes.lobby.link(lobbyId), {
3609
+ headers: {
3610
+ authorization: `Bearer ${bearerToken}`
3611
+ },
3612
+ unauthorized: true
3613
+ });
3614
+ },
3615
+ /**
3616
+ * Sets the moderation metadata for a lobby message. The metadata is app-scoped and delivered to active game clients via the Social SDK as a realtime message update.
3617
+ *
3618
+ * @param lobbyId - The ID of the lobby to set the moderation metadata
3619
+ * @param messageId - The ID of the message to set the moderation metadata
3620
+ * @param options - The moderation metadata to set
3621
+ *
3622
+ * @remarks
3623
+ * Uses `Bot` token for authorization.
3624
+ *
3625
+ * For the options: Free-form key–value pairs describing the moderation decision. Up to 5 keys; key length <= 1024 characters; value length <= 2000 characters
3626
+ *
3627
+ * @see {@link https://discord.com/developers/docs/game-sdk/social-sdk/chat-moderation#server-side-chat-moderation} for the full moderation flow.
3628
+ */ async updateLobbyMessageModerationMetadata (rest, lobbyId, messageId, options) {
3629
+ await rest.put(rest.routes.lobby.moderationMetadata(lobbyId, messageId), {
3630
+ body: options
3631
+ });
3632
+ },
3633
+ /**
3634
+ * Sends a message to the specified lobby. The calling user must be a member of the lobby.
3635
+ *
3636
+ * @param bearerToken - The access token of the user
3637
+ * @param lobbyId - The ID of the lobby to send the message to
3638
+ * @param options - The options to send the message
3639
+ * @returns Returns the created lobby message object.
3640
+ *
3641
+ * @remarks
3642
+ * Uses `Bearer` token for authorization with the `sdk.social_layer` scope.
3643
+ *
3644
+ * If the lobby has a linked channel, the message is also forwarded to that channel.
3645
+ * If forwarding fails (for example, due to AutoMod), the lobby message is still delivered to other lobby members.
3646
+ */ async sendLobbyMessage (rest, bearerToken, lobbyId, options) {
3647
+ return await rest.post(rest.routes.lobby.messages(lobbyId), {
3648
+ body: options,
3649
+ headers: {
3650
+ authorization: `Bearer ${bearerToken}`
3651
+ },
3652
+ unauthorized: true
3653
+ });
3654
+ },
3655
+ /**
3656
+ * Returns the most recent messages in the specified lobby. The calling user must be a member of the lobby.
3657
+ *
3658
+ * @param bearerToken - The access token of the user
3659
+ * @param lobbyId - The ID of the lobby to get the messages from
3660
+ * @param options - The options to get the messages
3661
+ * @returns Returns an array of lobby message objects
3662
+ *
3663
+ * @remarks
3664
+ * Uses `Bearer` token for authorization with the `sdk.social_layer` scope.
3665
+ */ async getLobbyMessages (rest, bearerToken, lobbyId, options) {
3666
+ return await rest.get(rest.routes.lobby.messages(lobbyId, options), {
3667
+ headers: {
3668
+ authorization: `Bearer ${bearerToken}`
3669
+ },
3670
+ unauthorized: true
3671
+ });
3672
+ },
3673
+ /**
3674
+ * Creates a single-use guild invite to the lobby's linked channel, targeted at the calling user.
3675
+ *
3676
+ *
3677
+ * @param bearerToken - The access token of the user
3678
+ * @param lobbyId - The ID of the lobby to create the invite for
3679
+ * @returns The created invite object
3680
+ *
3681
+ * @remarks
3682
+ * Uses `Bearer` token for authorization with the `sdk.social_layer` scope.
3683
+ *
3684
+ * The lobby must have a linked channel and the caller must be a member of the lobby.
3685
+ * The invite expires after one hour.
3686
+ */ async createLobbyChannelInviteForSelf (rest, bearerToken, lobbyId) {
3687
+ return rest.post(rest.routes.lobby.inviteSelf(lobbyId), {
3688
+ headers: {
3689
+ authorization: `Bearer ${bearerToken}`
3690
+ },
3691
+ unauthorized: true
3692
+ });
3693
+ },
3694
+ /**
3695
+ * Creates a single-use guild invite to the lobby's linked channel on behalf of an application, targeted at the specified user.
3696
+ *
3697
+ * @param lobbyId - The ID of the lobby to create the invite for
3698
+ * @param userId - The ID of the user to create the invite for
3699
+ * @returns The created invite object
3700
+ *
3701
+ * @remarks
3702
+ * Uses `Bot` token for authorization
3703
+ *
3704
+ * The lobby must have a linked channel.
3705
+ * The invite expires after one hour.
3706
+ */ async createLobbyChannelInviteForUser (rest, lobbyId, userId) {
3707
+ return rest.post(rest.routes.lobby.inviteUser(lobbyId, userId));
3708
+ }
3709
+ };
3710
+
3711
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uL3NyYy9lbmRwb2ludHMudHMiXSwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgQnVmZmVyIH0gZnJvbSAnbm9kZTpidWZmZXInO1xuaW1wb3J0IHR5cGUge1xuICBBZGREbVJlY2lwaWVudE9wdGlvbnMsXG4gIEFkZEd1aWxkTWVtYmVyT3B0aW9ucyxcbiAgQWRkTG9iYnlNZW1iZXIsXG4gIEF0TGVhc3RPbmUsXG4gIEJlZ2luR3VpbGRQcnVuZSxcbiAgQmlnU3RyaW5nLFxuICBCdWxrVXBkYXRlTG9iYnlNZW1iZXIsXG4gIENhbWVsaXplLFxuICBDaGFubmVsVHlwZXMsXG4gIENyZWF0ZUFwcGxpY2F0aW9uQ29tbWFuZCxcbiAgQ3JlYXRlQXBwbGljYXRpb25FbW9qaSxcbiAgQ3JlYXRlQXV0b01vZGVyYXRpb25SdWxlT3B0aW9ucyxcbiAgQ3JlYXRlQ2hhbm5lbEludml0ZSxcbiAgQ3JlYXRlRm9ydW1Qb3N0V2l0aE1lc3NhZ2UsXG4gIENyZWF0ZUdsb2JhbEFwcGxpY2F0aW9uQ29tbWFuZE9wdGlvbnMsXG4gIENyZWF0ZUdyb3VwRG1PcHRpb25zLFxuICBDcmVhdGVHdWlsZEFwcGxpY2F0aW9uQ29tbWFuZE9wdGlvbnMsXG4gIENyZWF0ZUd1aWxkQmFuLFxuICBDcmVhdGVHdWlsZEJ1bGtCYW4sXG4gIENyZWF0ZUd1aWxkQ2hhbm5lbCxcbiAgQ3JlYXRlR3VpbGRFbW9qaSxcbiAgQ3JlYXRlR3VpbGRSb2xlLFxuICBDcmVhdGVHdWlsZFNvdW5kYm9hcmRTb3VuZCxcbiAgQ3JlYXRlR3VpbGRTdGlja2VyT3B0aW9ucyxcbiAgQ3JlYXRlTG9iYnksXG4gIENyZWF0ZU1lc3NhZ2VPcHRpb25zLFxuICBDcmVhdGVPckpvaW5Mb2JieSxcbiAgQ3JlYXRlU2NoZWR1bGVkRXZlbnQsXG4gIENyZWF0ZVN0YWdlSW5zdGFuY2UsXG4gIENyZWF0ZVRlbXBsYXRlLFxuICBDcmVhdGVUZXN0RW50aXRsZW1lbnQsXG4gIENyZWF0ZVdlYmhvb2ssXG4gIERlbGV0ZVdlYmhvb2tNZXNzYWdlT3B0aW9ucyxcbiAgRGlzY29yZEFjY2Vzc1Rva2VuUmVzcG9uc2UsXG4gIERpc2NvcmRBY3Rpdml0eUluc3RhbmNlLFxuICBEaXNjb3JkQXBwbGljYXRpb24sXG4gIERpc2NvcmRBcHBsaWNhdGlvbkNvbW1hbmQsXG4gIERpc2NvcmRBcHBsaWNhdGlvbkNvbW1hbmRQZXJtaXNzaW9ucyxcbiAgRGlzY29yZEFwcGxpY2F0aW9uSW50ZWdyYXRpb25UeXBlLFxuICBEaXNjb3JkQXBwbGljYXRpb25Sb2xlQ29ubmVjdGlvbixcbiAgRGlzY29yZEFwcGxpY2F0aW9uUm9sZUNvbm5lY3Rpb25NZXRhZGF0YSxcbiAgRGlzY29yZEF1ZGl0TG9nLFxuICBEaXNjb3JkQXV0b01vZGVyYXRpb25SdWxlLFxuICBEaXNjb3JkQmFuLFxuICBEaXNjb3JkQnVsa0JhbixcbiAgRGlzY29yZENoYW5uZWwsXG4gIERpc2NvcmRDb25uZWN0aW9uLFxuICBEaXNjb3JkQ3VycmVudEF1dGhvcml6YXRpb24sXG4gIERpc2NvcmRFbW9qaSxcbiAgRGlzY29yZEVudGl0bGVtZW50LFxuICBEaXNjb3JkRm9sbG93ZWRDaGFubmVsLFxuICBEaXNjb3JkR2V0QW5zd2VyVm90ZXNSZXNwb25zZSxcbiAgRGlzY29yZEdldENoYW5uZWxQaW5zLFxuICBEaXNjb3JkR2V0R2F0ZXdheUJvdCxcbiAgRGlzY29yZEd1aWxkLFxuICBEaXNjb3JkR3VpbGRBcHBsaWNhdGlvbkNvbW1hbmRQZXJtaXNzaW9ucyxcbiAgRGlzY29yZEd1aWxkT25ib2FyZGluZyxcbiAgRGlzY29yZEd1aWxkUHJldmlldyxcbiAgRGlzY29yZEd1aWxkV2lkZ2V0LFxuICBEaXNjb3JkR3VpbGRXaWRnZXRTZXR0aW5ncyxcbiAgRGlzY29yZEluY2lkZW50c0RhdGEsXG4gIERpc2NvcmRJbnRlZ3JhdGlvbixcbiAgRGlzY29yZEludGVyYWN0aW9uLFxuICBEaXNjb3JkSW50ZXJhY3Rpb25DYWxsYmFja1Jlc3BvbnNlLFxuICBEaXNjb3JkSW52aXRlLFxuICBEaXNjb3JkSW52aXRlTWV0YWRhdGEsXG4gIERpc2NvcmRMaXN0QWN0aXZlVGhyZWFkcyxcbiAgRGlzY29yZExpc3RBcmNoaXZlZFRocmVhZHMsXG4gIERpc2NvcmRMb2JieSxcbiAgRGlzY29yZExvYmJ5SW52aXRlLFxuICBEaXNjb3JkTG9iYnlNZW1iZXIsXG4gIERpc2NvcmRMb2JieU1lc3NhZ2UsXG4gIERpc2NvcmRNZW1iZXIsXG4gIERpc2NvcmRNZW1iZXJXaXRoVXNlcixcbiAgRGlzY29yZE1lc3NhZ2UsXG4gIERpc2NvcmRQcnVuZWRDb3VudCxcbiAgRGlzY29yZFJvbGUsXG4gIERpc2NvcmRTY2hlZHVsZWRFdmVudCxcbiAgRGlzY29yZFNlYXJjaEd1aWxkTWVzc2FnZXMsXG4gIERpc2NvcmRTZWFyY2hHdWlsZE1lc3NhZ2VzSW5kZXhpbmcsXG4gIERpc2NvcmRTa3UsXG4gIERpc2NvcmRTb3VuZGJvYXJkU291bmQsXG4gIERpc2NvcmRTdGFnZUluc3RhbmNlLFxuICBEaXNjb3JkU3RpY2tlcixcbiAgRGlzY29yZFN0aWNrZXJQYWNrLFxuICBEaXNjb3JkU3Vic2NyaXB0aW9uLFxuICBEaXNjb3JkVGFyZ2V0VXNlcnNKb2JTdGF0dXMsXG4gIERpc2NvcmRUZW1wbGF0ZSxcbiAgRGlzY29yZFRocmVhZE1lbWJlcixcbiAgRGlzY29yZFRva2VuRXhjaGFuZ2UsXG4gIERpc2NvcmRUb2tlblJldm9jYXRpb24sXG4gIERpc2NvcmRVc2VyLFxuICBEaXNjb3JkVmFuaXR5VXJsLFxuICBEaXNjb3JkVm9pY2VSZWdpb24sXG4gIERpc2NvcmRWb2ljZVN0YXRlLFxuICBEaXNjb3JkV2ViaG9vayxcbiAgRGlzY29yZFdlbGNvbWVTY3JlZW4sXG4gIEVkaXRBcHBsaWNhdGlvbixcbiAgRWRpdEF1dG9Nb2RlcmF0aW9uUnVsZU9wdGlvbnMsXG4gIEVkaXRDaGFubmVsUGVybWlzc2lvbk92ZXJyaWRlc09wdGlvbnMsXG4gIEVkaXRHdWlsZE9uYm9hcmRpbmcsXG4gIEVkaXRHdWlsZFJvbGUsXG4gIEVkaXRHdWlsZFN0aWNrZXJPcHRpb25zLFxuICBFZGl0TWVzc2FnZSxcbiAgRWRpdE93blZvaWNlU3RhdGUsXG4gIEVkaXRTY2hlZHVsZWRFdmVudCxcbiAgRWRpdFVzZXJWb2ljZVN0YXRlLFxuICBFZGl0V2ViaG9va01lc3NhZ2VPcHRpb25zLFxuICBFeGVjdXRlV2ViaG9vayxcbiAgR2V0QXBwbGljYXRpb25Db21tYW5kUGVybWlzc2lvbk9wdGlvbnMsXG4gIEdldEJhbnMsXG4gIEdldENoYW5uZWxQaW5zT3B0aW9ucyxcbiAgR2V0RW50aXRsZW1lbnRzLFxuICBHZXRHbG9iYWxBcHBsaWNhdGlvbkNvbW1hbmRzT3B0aW9ucyxcbiAgR2V0R3VpbGRBcHBsaWNhdGlvbkNvbW1hbmRzT3B0aW9ucyxcbiAgR2V0R3VpbGRBdWRpdExvZyxcbiAgR2V0R3VpbGRQcnVuZUNvdW50UXVlcnksXG4gIEdldEludml0ZSxcbiAgR2V0TG9iYnlNZXNzYWdlcyxcbiAgR2V0TWVzc2FnZXNPcHRpb25zLFxuICBHZXRQb2xsQW5zd2VyVm90ZXMsXG4gIEdldFJlYWN0aW9ucyxcbiAgR2V0U2NoZWR1bGVkRXZlbnRzLFxuICBHZXRTY2hlZHVsZWRFdmVudFVzZXJzLFxuICBHZXRUaHJlYWRNZW1iZXIsXG4gIEdldFVzZXJHdWlsZHMsXG4gIEdldFdlYmhvb2tNZXNzYWdlT3B0aW9ucyxcbiAgR3VpbGRGZWF0dXJlcyxcbiAgSW50ZXJhY3Rpb25DYWxsYmFja0RhdGEsXG4gIEludGVyYWN0aW9uQ2FsbGJhY2tPcHRpb25zLFxuICBJbnRlcmFjdGlvblJlc3BvbnNlLFxuICBMaW5rQ2hhbm5lbFRvTG9iYnksXG4gIExpc3RBcmNoaXZlZFRocmVhZHMsXG4gIExpc3RHdWlsZE1lbWJlcnMsXG4gIExpc3RTa3VTdWJzY3JpcHRpb25zT3B0aW9ucyxcbiAgTGlzdFRocmVhZE1lbWJlcnMsXG4gIE1vZGlmeUFwcGxpY2F0aW9uRW1vamksXG4gIE1vZGlmeUNoYW5uZWwsXG4gIE1vZGlmeUN1cnJlbnRNZW1iZXIsXG4gIE1vZGlmeUd1aWxkLFxuICBNb2RpZnlHdWlsZENoYW5uZWxQb3NpdGlvbnMsXG4gIE1vZGlmeUd1aWxkRW1vamksXG4gIE1vZGlmeUd1aWxkSW5jaWRlbnRBY3Rpb25zLFxuICBNb2RpZnlHdWlsZE1lbWJlcixcbiAgTW9kaWZ5R3VpbGRTb3VuZGJvYXJkU291bmQsXG4gIE1vZGlmeUd1aWxkVGVtcGxhdGUsXG4gIE1vZGlmeUd1aWxkV2VsY29tZVNjcmVlbixcbiAgTW9kaWZ5TG9iYnksXG4gIE1vZGlmeVJvbGVQb3NpdGlvbnMsXG4gIE1vZGlmeVdlYmhvb2ssXG4gIFNjaGVkdWxlZEV2ZW50RW50aXR5VHlwZSxcbiAgU2NoZWR1bGVkRXZlbnRTdGF0dXMsXG4gIFNlYXJjaEd1aWxkTWVzc2FnZXNPcHRpb25zLFxuICBTZWFyY2hNZW1iZXJzLFxuICBTZW5kTG9iYnlNZXNzYWdlLFxuICBTZW5kU291bmRib2FyZFNvdW5kLFxuICBTZXRWb2ljZUNoYW5uZWxTdGF0dXMsXG4gIFN0YXJ0VGhyZWFkV2l0aE1lc3NhZ2UsXG4gIFN0YXJ0VGhyZWFkV2l0aG91dE1lc3NhZ2UsXG4gIFVwc2VydEdsb2JhbEFwcGxpY2F0aW9uQ29tbWFuZE9wdGlvbnMsXG4gIFVwc2VydEd1aWxkQXBwbGljYXRpb25Db21tYW5kT3B0aW9ucyxcbn0gZnJvbSAnQGRpc2NvcmRlbm8vdHlwZXMnO1xuaW1wb3J0IHsgcHJvY2Vzc1JlYWN0aW9uU3RyaW5nLCB1cmxUb0Jhc2U2NCB9IGZyb20gJ0BkaXNjb3JkZW5vL3V0aWxzJztcbmltcG9ydCB0eXBlIHsgTWFrZVJlcXVlc3RPcHRpb25zLCBSZXN0TWFuYWdlciB9IGZyb20gJy4vdHlwZXMuanMnO1xuXG4vKipcbiAqIEBpbnRlcm5hbCBZb3UgYXJlIG5vdCBzdXBwb3NlZCB0byB1c2UgdGhlIGZ1bmN0aW9ucyBpbiB0aGlzIG9iamVjdCBkaXJlY3RseS4gVXNlIHRoZSBSZXN0TWFuYWdlciBpbnN0ZWFkLlxuICovXG5leHBvcnQgY29uc3QgcmVzdEVuZHBvaW50cyA9IHtcbiAgLyoqXG4gICAqIEFkZHMgYSByZWFjdGlvbiB0byBhIG1lc3NhZ2UuXG4gICAqXG4gICAqIEBwYXJhbSBjaGFubmVsSWQgLSBUaGUgSUQgb2YgdGhlIGNoYW5uZWwgdGhlIG1lc3NhZ2UgdG8gYWRkIGEgcmVhY3Rpb24gdG8gaXMgaW4uXG4gICAqIEBwYXJhbSBtZXNzYWdlSWQgLSBUaGUgSUQgb2YgdGhlIG1lc3NhZ2UgdG8gYWRkIGEgcmVhY3Rpb24gdG8uXG4gICAqIEBwYXJhbSByZWFjdGlvbiAtIFRoZSByZWFjdGlvbiB0byBhZGQgdG8gdGhlIG1lc3NhZ2UuXG4gICAqIEByZXR1cm5zXG4gICAqXG4gICAqIEByZW1hcmtzXG4gICAqIFJlcXVpcmVzIHRoZSBgUkVBRF9NRVNTQUdFX0hJU1RPUllgIHBlcm1pc3Npb24uXG4gICAqXG4gICAqIElmIG5vYm9keSBlbHNlIGhhcyByZWFjdGVkIHRvIHRoZSBtZXNzYWdlOlxuICAgKiAtIFJlcXVpcmVzIHRoZSBgQUREX1JFQUNUSU9OU2AgcGVybWlzc2lvbi5cbiAgICpcbiAgICogRmlyZXMgYSBfTWVzc2FnZSBSZWFjdGlvbiBBZGRfIGdhdGV3YXkgZXZlbnQuXG4gICAqXG4gICAqIEBzZWUge0BsaW5rIGh0dHBzOi8vZG9jcy5kaXNjb3JkLmNvbS9kZXZlbG9wZXJzL3Jlc291cmNlcy9jaGFubmVsI2NyZWF0ZS1yZWFjdGlvbn1cbiAgICovXG4gIGFzeW5jIGFkZFJlYWN0aW9uKHJlc3Q6IFJlc3RNYW5hZ2VyLCBjaGFubmVsSWQ6IEJpZ1N0cmluZywgbWVzc2FnZUlkOiBCaWdTdHJpbmcsIHJlYWN0aW9uOiBzdHJpbmcpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICByZWFjdGlvbiA9IHByb2Nlc3NSZWFjdGlvblN0cmluZyhyZWFjdGlvbik7XG5cbiAgICBhd2FpdCByZXN0LnB1dChyZXN0LnJvdXRlcy5jaGFubmVscy5yZWFjdGlvbnMuYm90KGNoYW5uZWxJZCwgbWVzc2FnZUlkLCByZWFjdGlvbikpO1xuICB9LFxuICAvKipcbiAgICogQWRkcyBtdWx0aXBsZSBhIHJlYWN0aW9uIHRvIGEgbWVzc2FnZS5cbiAgICpcbiAgICogVGhpcyBmdW5jdGlvbiB1c2VzIHRoZSBgYWRkUmVhY3Rpb24oKWAgaGVscGVyIGJlaGluZCB0aGUgc2NlbmVzLlxuICAgKlxuICAgKiBAcGFyYW0gY2hhbm5lbElkIC0gVGhlIElEIG9mIHRoZSBjaGFubmVsIHRoZSBtZXNzYWdlIHRvIGFkZCByZWFjdGlvbnMgdG8gaXMgaW4uXG4gICAqIEBwYXJhbSBtZXNzYWdlSWQgLSBUaGUgSUQgb2YgdGhlIG1lc3NhZ2UgdG8gYWRkIHRoZSByZWFjdGlvbnMgdG8uXG4gICAqIEBwYXJhbSByZWFjdGlvbnMgLSBUaGUgcmVhY3Rpb25zIHRvIGFkZCB0byB0aGUgbWVzc2FnZS5cbiAgICogQHBhcmFtIG9yZGVyZWQgLSBXaGV0aGVyIHRoZSByZWFjdGlvbnMgbXVzdCBiZSBhZGRlZCBpbiBvcmRlciBvciBub3QuXG4gICAqXG4gICAqIEByZW1hcmtzXG4gICAqIFJlcXVpcmVzIHRoZSBgUkVBRF9NRVNTQUdFX0hJU1RPUllgIHBlcm1pc3Npb24uXG4gICAqXG4gICAqIElmIG5vYm9keSBlbHNlIGhhcyByZWFjdGVkIHRvIHRoZSBtZXNzYWdlOlxuICAgKiAtIFJlcXVpcmVzIHRoZSBgQUREX1JFQUNUSU9OU2AgcGVybWlzc2lvbi5cbiAgICpcbiAgICogRmlyZXMgYSBfTWVzc2FnZSBSZWFjdGlvbiBBZGRfIGdhdGV3YXkgZXZlbnQgZm9yIGV2ZXJ5IHJlYWN0aW9uIGFkZGVkLlxuICAgKi9cbiAgYXN5bmMgYWRkUmVhY3Rpb25zKHJlc3Q6IFJlc3RNYW5hZ2VyLCBjaGFubmVsSWQ6IEJpZ1N0cmluZywgbWVzc2FnZUlkOiBCaWdTdHJpbmcsIHJlYWN0aW9uczogc3RyaW5nW10sIG9yZGVyZWQ/OiBib29sZWFuKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgaWYgKCFvcmRlcmVkKSB7XG4gICAgICBhd2FpdCBQcm9taXNlLmFsbChcbiAgICAgICAgcmVhY3Rpb25zLm1hcChhc3luYyAocmVhY3Rpb24pID0+IHtcbiAgICAgICAgICBhd2FpdCByZXN0LnNuYWtlLmFkZFJlYWN0aW9uKGNoYW5uZWxJZCwgbWVzc2FnZUlkLCByZWFjdGlvbik7XG4gICAgICAgIH0pLFxuICAgICAgKTtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBmb3IgKGNvbnN0IHJlYWN0aW9uIG9mIHJlYWN0aW9ucykge1xuICAgICAgYXdhaXQgcmVzdC5zbmFrZS5hZGRSZWFjdGlvbihjaGFubmVsSWQsIG1lc3NhZ2VJZCwgcmVhY3Rpb24pO1xuICAgIH1cbiAgfSxcbiAgLyoqXG4gICAqIEFkZHMgYSByb2xlIHRvIGEgbWVtYmVyLlxuICAgKlxuICAgKiBAcGFyYW0gZ3VpbGRJZCAtIFRoZSBJRCBvZiB0aGUgZ3VpbGQgdGhlIG1lbWJlciB0byBhZGQgdGhlIHJvbGUgdG8gaXMgaW4uXG4gICAqIEBwYXJhbSB1c2VySWQgLSBUaGUgdXNlciBJRCBvZiB0aGUgbWVtYmVyIHRvIGFkZCB0aGUgcm9sZSB0by5cbiAgICogQHBhcmFtIHJvbGVJZCAtIFRoZSBJRCBvZiB0aGUgcm9sZSB0byBhZGQgdG8gdGhlIG1lbWJlci5cbiAgICogQHBhcmFtIHtzdHJpbmd9IFtyZWFzb25dIC0gQW4gb3B0aW9uYWwgcmVhc29uIGZvciB0aGUgYWN0aW9uLCB0byBiZSBpbmNsdWRlZCBpbiB0aGUgYXVkaXQgbG9nLlxuICAgKlxuICAgKiBAcmVtYXJrc1xuICAgKiBSZXF1aXJlcyB0aGUgYE1BTkFHRV9ST0xFU2AgcGVybWlzc2lvbi5cbiAgICpcbiAgICogRmlyZXMgYSBfR3VpbGQgTWVtYmVyIFVwZGF0ZV8gZ2F0ZXdheSBldmVudC5cbiAgICpcbiAgICogQHNlZSB7QGxpbmsgaHR0cHM6Ly9kb2NzLmRpc2NvcmQuY29tL2RldmVsb3BlcnMvcmVzb3VyY2VzL2d1aWxkI2FkZC1ndWlsZC1tZW1iZXItcm9sZX1cbiAgICovXG4gIGFzeW5jIGFkZFJvbGUocmVzdDogUmVzdE1hbmFnZXIsIGd1aWxkSWQ6IEJpZ1N0cmluZywgdXNlcklkOiBCaWdTdHJpbmcsIHJvbGVJZDogQmlnU3RyaW5nLCByZWFzb24/OiBzdHJpbmcpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBhd2FpdCByZXN0LnB1dChyZXN0LnJvdXRlcy5ndWlsZHMucm9sZXMubWVtYmVyKGd1aWxkSWQsIHVzZXJJZCwgcm9sZUlkKSwgeyByZWFzb24gfSk7XG4gIH0sXG4gIC8qKlxuICAgKiBBZGRzIGEgbWVtYmVyIHRvIGEgdGhyZWFkLlxuICAgKlxuICAgKiBAcGFyYW0gY2hhbm5lbElkIC0gVGhlIElEIG9mIHRoZSB0aHJlYWQgdG8gYWRkIHRoZSBtZW1iZXIgdG8uXG4gICAqIEBwYXJhbSB1c2VySWQgLSBUaGUgdXNlciBJRCBvZiB0aGUgbWVtYmVyIHRvIGFkZCB0byB0aGUgdGhyZWFkLlxuICAgKlxuICAgKiBAcmVtYXJrc1xuICAgKiBSZXF1aXJlcyB0aGUgYWJpbGl0eSB0byBzZW5kIG1lc3NhZ2VzIGluIHRoZSB0aHJlYWQuXG4gICAqIFJlcXVpcmVzIHRoZSB0aHJlYWQgbm90IGJlIGFyY2hpdmVkLlxuICAgKlxuICAgKiBGaXJlcyBhIF9UaHJlYWQgTWVtYmVycyBVcGRhdGVfIGdhdGV3YXkgZXZlbnQuXG4gICAqXG4gICAqIEBzZWUge0BsaW5rIGh0dHBzOi8vZG9jcy5kaXNjb3JkLmNvbS9kZXZlbG9wZXJzL3Jlc291cmNlcy9jaGFubmVsI2FkZC10aHJlYWQtbWVtYmVyfVxuICAgKi9cbiAgYXN5bmMgYWRkVGhyZWFkTWVtYmVyKHJlc3Q6IFJlc3RNYW5hZ2VyLCBjaGFubmVsSWQ6IEJpZ1N0cmluZywgdXNlcklkOiBCaWdTdHJpbmcpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBhd2FpdCByZXN0LnB1dChyZXN0LnJvdXRlcy5jaGFubmVscy50aHJlYWRzLnVzZXIoY2hhbm5lbElkLCB1c2VySWQpKTtcbiAgfSxcbiAgLyoqXG4gICAqIEFkZHMgYSByZWNpcGllbnQgdG8gYSBncm91cCBETS5cbiAgICpcbiAgICogQHBhcmFtIGNoYW5uZWxJZCAtIFRoZSBJRCBvZiB0aGUgZ3JvdXAgZG0gdG8gYWRkIHRoZSB1c2VyIHRvLlxuICAgKiBAcGFyYW0gdXNlcklkIC0gVGhlIHVzZXIgSUQgb2YgdGhlIHVzZXIgdG8gYWRkIHRvIHRoZSBncm91cCBkbS5cbiAgICogQHBhcmFtIG9wdGlvbnMgLSBUaGUgb3B0aW9ucyBmb3IgYWRkaW5nIHRoZSB1c2VyXG4gICAqXG4gICAqIEByZW1hcmtzXG4gICAqIFJlcXVpcmVzIGFuIE9BdXRoMiBhY2Nlc3MgdG9rZW4gd2l0aCB0aGUgYGdkbS5qb2luYCBzY29wZVxuICAgKlxuICAgKiBAc2VlIHtAbGluayBodHRwczovL2RvY3MuZGlzY29yZC5jb20vZGV2ZWxvcGVycy9yZXNvdXJjZXMvY2hhbm5lbCNncm91cC1kbS1hZGQtcmVjaXBpZW50fVxuICAgKi9cbiAgYXN5bmMgYWRkRG1SZWNpcGllbnQocmVzdDogUmVzdE1hbmFnZXIsIGNoYW5uZWxJZDogQmlnU3RyaW5nLCB1c2VySWQ6IEJpZ1N0cmluZywgb3B0aW9uczogQWRkRG1SZWNpcGllbnRPcHRpb25zKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgYXdhaXQgcmVzdC5wdXQocmVzdC5yb3V0ZXMuY2hhbm5lbHMuZG1SZWNpcGllbnQoY2hhbm5lbElkLCB1c2VySWQpLCB7IGJvZHk6IG9wdGlvbnMgfSk7XG4gIH0sXG4gIC8qKlxuICAgKiBBZGRzIGEgbWVtYmVyIHRvIGEgZ3VpbGQuXG4gICAqXG4gICAqIEBwYXJhbSBndWlsZElkIC0gVGhlIElEIG9mIHRoZSB0aHJlYWQgdG8gYWRkIHRoZSBtZW1iZXIgdG8uXG4gICAqIEBwYXJhbSB1c2VySWQgLSBUaGUgdXNlciBJRCBvZiB0aGUgbWVtYmVyIHRvIGFkZCB0byB0aGUgdGhyZWFkLlxuICAgKiBAcGFyYW0gb3B0aW9ucyAtIFRoZSBvcHRpb25zIGZvciB0aGUgYWRkIG9mIGEgZ3VpbGQgbWVtYmVyXG4gICAqXG4gICAqIEByZW1hcmtzXG4gICAqIFJlcXVpcmVzIHRoZSBib3QgdG8gYmUgaW4gdGhlIHNwZWNpZmllZCBzZXJ2ZXJcbiAgICogUmVxdWlyZXMgYW4gT0F1dGgyIGFjY2VzcyB0b2tlbiB3aXRoIHRoZSBgZ3VpbGRzLmpvaW5gIHNjb3BlXG4gICAqXG4gICAqIEZpcmVzIGEgX0d1aWxkIE1lbWJlciBBZGRfIGdhdGV3YXkgZXZlbnQuXG4gICAqXG4gICAqIEBzZWUge0BsaW5rIGh0dHBzOi8vZG9jcy5kaXNjb3JkLmNvbS9kZXZlbG9wZXJzL3Jlc291cmNlcy9ndWlsZCNhZGQtZ3VpbGQtbWVtYmVyfVxuICAgKi9cbiAgYXN5bmMgYWRkR3VpbGRNZW1iZXIocmVzdDogUmVzdE1hbmFnZXIsIGd1aWxkSWQ6IEJpZ1N0cmluZywgdXNlcklkOiBCaWdTdHJpbmcsIG9wdGlvbnM6IEFkZEd1aWxkTWVtYmVyT3B0aW9ucyk6IFByb21pc2U8dm9pZD4ge1xuICAgIHJldHVybiBhd2FpdCByZXN0LnB1dChyZXN0LnJvdXRlcy5ndWlsZHMubWVtYmVycy5tZW1iZXIoZ3VpbGRJZCwgdXNlcklkKSwge1xuICAgICAgYm9keTogb3B0aW9ucyxcbiAgICB9KTtcbiAgfSxcbiAgLyoqXG4gICAqIENyZWF0ZXMgYW4gYXV0b21vZCBydWxlIGluIGEgZ3VpbGQuXG4gICAqXG4gICAqIEBwYXJhbSBndWlsZElkIC0gVGhlIElEIG9mIHRoZSBndWlsZCB0byBjcmVhdGUgdGhlIHJ1bGUgaW4uXG4gICAqIEBwYXJhbSBvcHRpb25zIC0gVGhlIHBhcmFtZXRlcnMgZm9yIHRoZSBjcmVhdGlvbiBvZiB0aGUgcnVsZS5cbiAgICogQHBhcmFtIHtzdHJpbmd9IFtyZWFzb25dIC0gQW4gb3B0aW9uYWwgcmVhc29uIGZvciB0aGUgYWN0aW9uLCB0byBiZSBpbmNsdWRlZCBpbiB0aGUgYXVkaXQgbG9nLlxuICAgKiBAcmV0dXJucyBBbiBpbnN0YW5jZSBvZiB0aGUgY3JlYXRlZCB7QGxpbmsgRGlzY29yZEF1dG9Nb2RlcmF0aW9uUnVsZX0uXG4gICAqXG4gICAqIEByZW1hcmtzXG4gICAqIFJlcXVpcmVzIHRoZSBgTUFOQUdFX0dVSUxEYCBwZXJtaXNzaW9uLlxuICAgKlxuICAgKiBGaXJlcyBhbiBfQXV0byBNb2RlcmF0aW9uIFJ1bGUgQ3JlYXRlXyBnYXRld2F5IGV2ZW50LlxuICAgKlxuICAgKiBAc2VlIHtAbGluayBodHRwczovL2RvY3MuZGlzY29yZC5jb20vZGV2ZWxvcGVycy9yZXNvdXJjZXMvYXV0by1tb2RlcmF0aW9uI2NyZWF0ZS1hdXRvLW1vZGVyYXRpb24tcnVsZX1cbiAgICovXG4gIGFzeW5jIGNyZWF0ZUF1dG9tb2RSdWxlKFxuICAgIHJlc3Q6IFJlc3RNYW5hZ2VyLFxuICAgIGd1aWxkSWQ6IEJpZ1N0cmluZyxcbiAgICBvcHRpb25zOiBDcmVhdGVBdXRvTW9kZXJhdGlvblJ1bGVPcHRpb25zLFxuICAgIHJlYXNvbj86IHN0cmluZyxcbiAgKTogUHJvbWlzZTxEaXNjb3JkQXV0b01vZGVyYXRpb25SdWxlPiB7XG4gICAgcmV0dXJuIGF3YWl0IHJlc3QucG9zdDxEaXNjb3JkQXV0b01vZGVyYXRpb25SdWxlPihyZXN0LnJvdXRlcy5ndWlsZHMuYXV0b21vZC5ydWxlcyhndWlsZElkKSwgeyBib2R5OiBvcHRpb25zLCByZWFzb24gfSk7XG4gIH0sXG4gIC8qKlxuICAgKiBDcmVhdGVzIGEgY2hhbm5lbCB3aXRoaW4gYSBndWlsZC5cbiAgICpcbiAgICogQHBhcmFtIGd1aWxkSWQgLSBUaGUgSUQgb2YgdGhlIGd1aWxkIHRvIGNyZWF0ZSB0aGUgY2hhbm5lbCB3aXRoaW4uXG4gICAqIEBwYXJhbSBvcHRpb25zIC0gVGhlIHBhcmFtZXRlcnMgZm9yIHRoZSBjcmVhdGlvbiBvZiB0aGUgY2hhbm5lbC5cbiAgICogQHBhcmFtIHtzdHJpbmd9IFtyZWFzb25dIC0gQW4gb3B0aW9uYWwgcmVhc29uIGZvciB0aGUgYWN0aW9uLCB0byBiZSBpbmNsdWRlZCBpbiB0aGUgYXVkaXQgbG9nLlxuICAgKiBAcmV0dXJucyBBbiBpbnN0YW5jZSBvZiB0aGUgY3JlYXRlZCB7QGxpbmsgRGlzY29yZENoYW5uZWx9LlxuICAgKlxuICAgKiBAcmVtYXJrc1xuICAgKiBSZXF1aXJlcyB0aGUgYE1BTkFHRV9DSEFOTkVMU2AgcGVybWlzc2lvbi5cbiAgICpcbiAgICogSWYgc2V0dGluZyBwZXJtaXNzaW9uIG92ZXJ3cml0ZXMsIG9ubHkgdGhlIHBlcm1pc3Npb25zIHRoZSBib3QgdXNlciBoYXMgaW4gdGhlIGd1aWxkIGNhbiBiZSBhbGxvd2VkIG9yIGRlbmllZC5cbiAgICpcbiAgICogU2V0dGluZyB0aGUgYE1BTkFHRV9ST0xFU2AgcGVybWlzc2lvbiBpcyBvbmx5IHBvc3NpYmxlIGZvciBndWlsZCBhZG1pbmlzdHJhdG9ycy5cbiAgICpcbiAgICogRmlyZXMgYSBfQ2hhbm5lbCBDcmVhdGVfIGdhdGV3YXkgZXZlbnQuXG4gICAqXG4gICAqIEBzZWUge0BsaW5rIGh0dHBzOi8vZG9jcy5kaXNjb3JkLmNvbS9kZXZlbG9wZXJzL3Jlc291cmNlcy9ndWlsZCNjcmVhdGUtZ3VpbGQtY2hhbm5lbH1cbiAgICovXG4gIGFzeW5jIGNyZWF0ZUNoYW5uZWwocmVzdDogUmVzdE1hbmFnZXIsIGd1aWxkSWQ6IEJpZ1N0cmluZywgb3B0aW9uczogQ3JlYXRlR3VpbGRDaGFubmVsLCByZWFzb24/OiBzdHJpbmcpOiBQcm9taXNlPERpc2NvcmRDaGFubmVsPiB7XG4gICAgcmV0dXJuIGF3YWl0IHJlc3QucG9zdDxEaXNjb3JkQ2hhbm5lbD4ocmVzdC5yb3V0ZXMuZ3VpbGRzLmNoYW5uZWxzKGd1aWxkSWQpLCB7IGJvZHk6IG9wdGlvbnMsIHJlYXNvbiB9KTtcbiAgfSxcbiAgLyoqXG4gICAqIENyZWF0ZXMgYW4gZW1vamkgaW4gYSBndWlsZC5cbiAgICpcbiAgICogQHBhcmFtIGd1aWxkSWQgLSBUaGUgSUQgb2YgdGhlIGd1aWxkIGluIHdoaWNoIHRvIGNyZWF0ZSB0aGUgZW1vamkuXG4gICAqIEBwYXJhbSBvcHRpb25zIC0gVGhlIHBhcmFtZXRlcnMgZm9yIHRoZSBjcmVhdGlvbiBvZiB0aGUgZW1vamkuXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBbcmVhc29uXSAtIEFuIG9wdGlvbmFsIHJlYXNvbiBmb3IgdGhlIGFjdGlvbiwgdG8gYmUgaW5jbHVkZWQgaW4gdGhlIGF1ZGl0IGxvZy5cbiAgICogQHJldHVybnMgQW4gaW5zdGFuY2Ugb2YgdGhlIGNyZWF0ZWQge0BsaW5rIERpc2NvcmRFbW9qaX0uXG4gICAqXG4gICAqIEByZW1hcmtzXG4gICAqIFJlcXVpcmVzIHRoZSBgQ1JFQVRFX0dVSUxEX0VYUFJFU1NJT05TYCBwZXJtaXNzaW9uLlxuICAgKlxuICAgKiBFbW9qaXMgaGF2ZSBhIG1heGltdW0gZmlsZSBzaXplIG9mIDI1NiBraWxvYml0cy4gQXR0ZW1wdGluZyB0byB1cGxvYWQgYSBsYXJnZXIgZW1vamkgd2lsbCBjYXVzZSB0aGUgcm91dGUgdG8gcmV0dXJuIDQwMCBCYWQgUmVxdWVzdC5cbiAgICpcbiAgICogRmlyZXMgYSBfR3VpbGQgRW1vamlzIFVwZGF0ZV8gZ2F0ZXdheSBldmVudC5cbiAgICpcbiAgICogQHNlZSB7QGxpbmsgaHR0cHM6Ly9kb2NzLmRpc2NvcmQuY29tL2RldmVsb3BlcnMvcmVzb3VyY2VzL2Vtb2ppI2NyZWF0ZS1ndWlsZC1lbW9qaX1cbiAgICovXG4gIGFzeW5jIGNyZWF0ZUVtb2ppKHJlc3Q6IFJlc3RNYW5hZ2VyLCBndWlsZElkOiBCaWdTdHJpbmcsIG9wdGlvbnM6IENyZWF0ZUd1aWxkRW1vamksIHJlYXNvbj86IHN0cmluZyk6IFByb21pc2U8RGlzY29yZEVtb2ppPiB7XG4gICAgcmV0dXJuIGF3YWl0IHJlc3QucG9zdDxEaXNjb3JkRW1vamk+KHJlc3Qucm91dGVzLmd1aWxkcy5lbW9qaXMoZ3VpbGRJZCksIHsgYm9keTogb3B0aW9ucywgcmVhc29uIH0pO1xuICB9LFxuICAvKipcbiAgICogQ3JlYXRlcyBhbiBlbW9qaSBmb3IgdGhlIGFwcGxpY2F0aW9uLlxuICAgKlxuICAgKiBAcGFyYW0gb3B0aW9ucyAtIFRoZSBwYXJhbWV0ZXJzIGZvciB0aGUgY3JlYXRpb24gb2YgdGhlIGVtb2ppLlxuICAgKiBAcmV0dXJucyBBbiBpbnN0YW5jZSBvZiB0aGUgY3JlYXRlZCB7QGxpbmsgRGlzY29yZEVtb2ppfS5cbiAgICpcbiAgICogQHNlZSB7QGxpbmsgaHR0cHM6Ly9kb2NzLmRpc2NvcmQuY29tL2RldmVsb3BlcnMvcmVzb3VyY2VzL2Vtb2ppI2NyZWF0ZS1hcHBsaWNhdGlvbi1lbW9qaX1cbiAgICovXG4gIGFzeW5jIGNyZWF0ZUFwcGxpY2F0aW9uRW1vamkocmVzdDogUmVzdE1hbmFnZXIsIG9wdGlvbnM6IENyZWF0ZUFwcGxpY2F0aW9uRW1vamkpOiBQcm9taXNlPERpc2NvcmRFbW9qaT4ge1xuICAgIHJldHVybiBhd2FpdCByZXN0LnBvc3Q8RGlzY29yZEVtb2ppPihyZXN0LnJvdXRlcy5hcHBsaWNhdGlvbkVtb2ppcyhyZXN0LmFwcGxpY2F0aW9uSWQpLCB7IGJvZHk6IG9wdGlvbnMgfSk7XG4gIH0sXG4gIC8qKlxuICAgKiBDcmVhdGVzIGEgbmV3IHRocmVhZCBpbiBhIGZvcnVtIGNoYW5uZWwgb3IgbWVkaWEgY2hhbm5lbCwgYW5kIHNlbmRzIGEgbWVzc2FnZSB3aXRoaW4gdGhlIGNyZWF0ZWQgdGhyZWFkLlxuICAgKlxuICAgKiBAcGFyYW0gY2hhbm5lbElkIC0gVGhlIElEIG9mIHRoZSBmb3J1bSBjaGFubmVsIHRvIGNyZWF0ZSB0aGUgdGhyZWFkIHdpdGhpbi5cbiAgICogQHBhcmFtIG9wdGlvbnMgLSBUaGUgcGFyYW1ldGVycyBmb3IgdGhlIGNyZWF0aW9uIG9mIHRoZSB0aHJlYWQuXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBbcmVhc29uXSAtIEFuIG9wdGlvbmFsIHJlYXNvbiBmb3IgdGhlIGFjdGlvbiwgdG8gYmUgaW5jbHVkZWQgaW4gdGhlIGF1ZGl0IGxvZy5cbiAgICogQHJldHVybnMgQW4gaW5zdGFuY2Ugb2Yge0BsaW5rIERpc2NvcmRDaGFubmVsfSB3aXRoIGEgbmVzdGVkIHtAbGluayBEaXNjb3JkQ2hhbm5lbH0gb2JqZWN0LlxuICAgKlxuICAgKiBAcmVtYXJrc1xuICAgKiBSZXF1aXJlcyB0aGUgYENSRUFURV9NRVNTQUdFU2AgcGVybWlzc2lvbi5cbiAgICpcbiAgICogRmlyZXMgYSBfVGhyZWFkIENyZWF0ZV8gZ2F0ZXdheSBldmVudC5cbiAgICogRmlyZXMgYSBfTWVzc2FnZSBDcmVhdGVfIGdhdGV3YXkgZXZlbnQuXG4gICAqXG4gICAqIEBzZWUge0BsaW5rIGh0dHBzOi8vZG9jcy5kaXNjb3JkLmNvbS9kZXZlbG9wZXJzL3Jlc291cmNlcy9jaGFubmVsI3N0YXJ0LXRocmVhZC1pbi1mb3J1bS1vci1tZWRpYS1jaGFubmVsfVxuICAgKi9cbiAgYXN5bmMgY3JlYXRlRm9ydW1UaHJlYWQocmVzdDogUmVzdE1hbmFnZXIsIGNoYW5uZWxJZDogQmlnU3RyaW5nLCBvcHRpb25zOiBDcmVhdGVGb3J1bVBvc3RXaXRoTWVzc2FnZSwgcmVhc29uPzogc3RyaW5nKTogUHJvbWlzZTxEaXNjb3JkQ2hhbm5lbD4ge1xuICAgIHJldHVybiBhd2FpdCByZXN0LnBvc3Q8RGlzY29yZENoYW5uZWw+KHJlc3Qucm91dGVzLmNoYW5uZWxzLmZvcnVtKGNoYW5uZWxJZCksIHsgYm9keTogb3B0aW9ucywgZmlsZXM6IG9wdGlvbnMuZmlsZXMsIHJlYXNvbiB9KTtcbiAgfSxcbiAgLyoqXG4gICAqIENyZWF0ZXMgYW4gYXBwbGljYXRpb24gY29tbWFuZCBhY2Nlc3NpYmxlIGdsb2JhbGx5OyBhY3Jvc3MgZGlmZmVyZW50IGd1aWxkcyBhbmQgY2hhbm5lbHMuXG4gICAqXG4gICAqIEBwYXJhbSBjb21tYW5kIC0gVGhlIGNvbW1hbmQgdG8gY3JlYXRlLlxuICAgKiBAcGFyYW0gb3B0aW9ucyAtIEFkZGl0aW9uYWwgb3B0aW9ucyBmb3IgdGhlIGVuZHBvaW50XG4gICAqIEByZXR1cm5zIEFuIGluc3RhbmNlIG9mIHRoZSBjcmVhdGVkIHtAbGluayBEaXNjb3JkQXBwbGljYXRpb25Db21tYW5kfS5cbiAgICpcbiAgICogQHJlbWFya3NcbiAgICog4pqg77iPIENyZWF0aW5nIGEgY29tbWFuZCB3aXRoIHRoZSBzYW1lIG5hbWUgYXMgYW4gZXhpc3RpbmcgY29tbWFuZCBmb3IgeW91ciBhcHBsaWNhdGlvbiB3aWxsIG92ZXJ3cml0ZSB0aGUgb2xkIGNvbW1hbmQuXG4gICAqIOKaoO+4jyBHbG9iYWwgY29tbWFuZHMgb25jZSBjcmVhdGVkIGFyZSBjYWNoZWQgZm9yIHBlcmlvZHMgb2YgX19hbiBob3VyX18sIHNvIGNoYW5nZXMgbWFkZSB0byBleGlzdGluZyBjb21tYW5kcyB3aWxsIHRha2UgYW4gaG91ciB0byBzdXJmYWNlLlxuICAgKiDimqDvuI8gWW91IGNhbiBvbmx5IGNyZWF0ZSB1cCB0byAyMDAgX25ld18gY29tbWFuZHMgZGFpbHkuXG4gICAqXG4gICAqIFdoZW4gdXNpbmcgdGhlIGJlYXJlciB0b2tlbiB0aGUgdG9rZW4gbmVlZHMgdGhlIGBhcHBsaWNhdGlvbnMuY29tbWFuZHMudXBkYXRlYCBzY29wZSBhbmQgbXVzdCBiZSBhIGBDbGllbnQgZ3JhbnRgIHRva2VuLlxuICAgKiAgWW91IHdpbGwgYmUgYWJsZSB0byB1cGRhdGUgb25seSB5b3VyIG93biBhcHBsaWNhdGlvbiBjb21tYW5kc1xuICAgKlxuICAgKiBAc2VlIHtAbGluayBodHRwczovL2RvY3MuZGlzY29yZC5jb20vZGV2ZWxvcGVycy9pbnRlcmFjdGlvbnMvYXBwbGljYXRpb24tY29tbWFuZHMjY3JlYXRlLWdsb2JhbC1hcHBsaWNhdGlvbi1jb21tYW5kfVxuICAgKi9cbiAgYXN5bmMgY3JlYXRlR2xvYmFsQXBwbGljYXRpb25Db21tYW5kKFxuICAgIHJlc3Q6IFJlc3RNYW5hZ2VyLFxuICAgIGNvbW1hbmQ6IENyZWF0ZUFwcGxpY2F0aW9uQ29tbWFuZCxcbiAgICBvcHRpb25zPzogQ3JlYXRlR2xvYmFsQXBwbGljYXRpb25Db21tYW5kT3B0aW9ucyxcbiAgKTogUHJvbWlzZTxEaXNjb3JkQXBwbGljYXRpb25Db21tYW5kPiB7XG4gICAgY29uc3QgcmVzdE9wdGlvbnM6IE1ha2VSZXF1ZXN0T3B0aW9ucyA9IHsgYm9keTogY29tbWFuZCB9O1xuXG4gICAgaWYgKG9wdGlvbnM/LmJlYXJlclRva2VuKSB7XG4gICAgICByZXN0T3B0aW9ucy51bmF1dGhvcml6ZWQgPSB0cnVlO1xuICAgICAgcmVzdE9wdGlvbnMuaGVhZGVycyA9IHtcbiAgICAgICAgYXV0aG9yaXphdGlvbjogYEJlYXJlciAke29wdGlvbnMuYmVhcmVyVG9rZW59YCxcbiAgICAgIH07XG4gICAgfVxuXG4gICAgcmV0dXJuIGF3YWl0IHJlc3QucG9zdDxEaXNjb3JkQXBwbGljYXRpb25Db21tYW5kPihyZXN0LnJvdXRlcy5pbnRlcmFjdGlvbnMuY29tbWFuZHMuY29tbWFuZHMocmVzdC5hcHBsaWNhdGlvbklkKSwgcmVzdE9wdGlvbnMpO1xuICB9LFxuICAvKipcbiAgICogQ3JlYXRlcyBhbiBhcHBsaWNhdGlvbiBjb21tYW5kIG9ubHkgYWNjZXNzaWJsZSBpbiBhIHNwZWNpZmljIGd1aWxkLlxuICAgKlxuICAgKiBAcGFyYW0gY29tbWFuZCAtIFRoZSBjb21tYW5kIHRvIGNyZWF0ZS5cbiAgICogQHBhcmFtIGd1aWxkSWQgLSBUaGUgSUQgb2YgdGhlIGd1aWxkIHRvIGNyZWF0ZSB0aGUgY29tbWFuZCBmb3IuXG4gICAqIEBwYXJhbSBvcHRpb25zIC0gQWRkaXRpb25hbCBvcHRpb25zIGZvciB0aGUgZW5kcG9pbnRcbiAgICogQHJldHVybnMgQW4gaW5zdGFuY2Ugb2YgdGhlIGNyZWF0ZWQge0BsaW5rIERpc2NvcmRBcHBsaWNhdGlvbkNvbW1hbmR9LlxuICAgKlxuICAgKiBAcmVtYXJrc1xuICAgKiDimqDvuI8gQ3JlYXRpbmcgYSBjb21tYW5kIHdpdGggdGhlIHNhbWUgbmFtZSBhcyBhbiBleGlzdGluZyBjb21tYW5kIGZvciB5b3VyIGFwcGxpY2F0aW9uIHdpbGwgb3ZlcndyaXRlIHRoZSBvbGQgY29tbWFuZC5cbiAgICog4pqg77iPIFlvdSBjYW4gb25seSBjcmVhdGUgdXAgdG8gMjAwIF9uZXdfIGNvbW1hbmRzIGRhaWx5LlxuICAgKlxuICAgKiBXaGVuIHVzaW5nIHRoZSBiZWFyZXIgdG9rZW4gdGhlIHRva2VuIG5lZWRzIHRoZSBgYXBwbGljYXRpb25zLmNvbW1hbmRzLnVwZGF0ZWAgc2NvcGUgYW5kIG11c3QgYmUgYSBgQ2xpZW50IGdyYW50YCB0b2tlbi5cbiAgICogIFlvdSB3aWxsIGJlIGFibGUgdG8gdXBkYXRlIG9ubHkgeW91ciBvd24gYXBwbGljYXRpb24gY29tbWFuZHNcbiAgICpcbiAgICogQHNlZSB7QGxpbmsgaHR0cHM6Ly9kb2NzLmRpc2NvcmQuY29tL2RldmVsb3BlcnMvaW50ZXJhY3Rpb25zL2FwcGxpY2F0aW9uLWNvbW1hbmRzI2NyZWF0ZS1ndWlsZC1hcHBsaWNhdGlvbi1jb21tYW5kfVxuICAgKi9cbiAgYXN5bmMgY3JlYXRlR3VpbGRBcHBsaWNhdGlvbkNvbW1hbmQoXG4gICAgcmVzdDogUmVzdE1hbmFnZXIsXG4gICAgY29tbWFuZDogQ3JlYXRlQXBwbGljYXRpb25Db21tYW5kLFxuICAgIGd1aWxkSWQ6IEJpZ1N0cmluZyxcbiAgICBvcHRpb25zPzogQ3JlYXRlR3VpbGRBcHBsaWNhdGlvbkNvbW1hbmRPcHRpb25zLFxuICApOiBQcm9taXNlPERpc2NvcmRBcHBsaWNhdGlvbkNvbW1hbmQ+IHtcbiAgICBjb25zdCByZXN0T3B0aW9uczogTWFrZVJlcXVlc3RPcHRpb25zID0geyBib2R5OiBjb21tYW5kIH07XG5cbiAgICBpZiAob3B0aW9ucz8uYmVhcmVyVG9rZW4pIHtcbiAgICAgIHJlc3RPcHRpb25zLnVuYXV0aG9yaXplZCA9IHRydWU7XG4gICAgICByZXN0T3B0aW9ucy5oZWFkZXJzID0ge1xuICAgICAgICBhdXRob3JpemF0aW9uOiBgQmVhcmVyICR7b3B0aW9ucy5iZWFyZXJUb2tlbn1gLFxuICAgICAgfTtcbiAgICB9XG5cbiAgICByZXR1cm4gYXdhaXQgcmVzdC5wb3N0PERpc2NvcmRBcHBsaWNhdGlvbkNvbW1hbmQ+KHJlc3Qucm91dGVzLmludGVyYWN0aW9ucy5jb21tYW5kcy5ndWlsZHMuYWxsKHJlc3QuYXBwbGljYXRpb25JZCwgZ3VpbGRJZCksIHJlc3RPcHRpb25zKTtcbiAgfSxcbiAgLyoqXG4gICAqIENyZWF0ZSBhIG5ldyBzdGlja2VyIGZvciB0aGUgZ3VpbGQuXG4gICAqXG4gICAqIEBwYXJhbSBndWlsZElkIFRoZSBJRCBvZiB0aGUgZ3VpbGQgdG8gZ2V0XG4gICAqIEBwYXJhbSB7c3RyaW5nfSBbcmVhc29uXSAtIEFuIG9wdGlvbmFsIHJlYXNvbiBmb3IgdGhlIGFjdGlvbiwgdG8gYmUgaW5jbHVkZWQgaW4gdGhlIGF1ZGl0IGxvZy5cbiAgICogQHJldHVybiBBIHtAbGluayBEaXNjb3JkU3RpY2tlcn1cbiAgICpcbiAgICogQHJlbWFya3NcbiAgICogUmVxdWlyZXMgdGhlIGBDUkVBVEVfR1VJTERfRVhQUkVTU0lPTlNgIHBlcm1pc3Npb24uXG4gICAqIEZpcmVzIGEgR3VpbGQgU3RpY2tlcnMgVXBkYXRlIEdhdGV3YXkgZXZlbnQuXG4gICAqIEV2ZXJ5IGd1aWxkcyBoYXMgZml2ZSBmcmVlIHN0aWNrZXIgc2xvdHMgYnkgZGVmYXVsdCwgYW5kIGVhY2ggQm9vc3QgbGV2ZWwgd2lsbCBncmFudCBhY2Nlc3MgdG8gbW9yZSBzbG90cy5cbiAgICogTG90dGllIHN0aWNrZXJzIGNhbiBvbmx5IGJlIHVwbG9hZGVkIG9uIGd1aWxkcyB0aGF0IGhhdmUgZWl0aGVyIHRoZSBgVkVSSUZJRURgIGFuZC9vciB0aGUgYFBBUlRORVJFRGAgZ3VpbGQgZmVhdHVyZS5cbiAgICpcbiAgICogQHNlZSB7QGxpbmsgaHR0cHM6Ly9kb2NzLmRpc2NvcmQuY29tL2RldmVsb3BlcnMvcmVzb3VyY2VzL3N0aWNrZXIjY3JlYXRlLWd1aWxkLXN0aWNrZXJ9XG4gICAqL1xuICBhc3luYyBjcmVhdGVHdWlsZFN0aWNrZXIocmVzdDogUmVzdE1hbmFnZXIsIGd1aWxkSWQ6IEJpZ1N0cmluZywgb3B0aW9uczogQ3JlYXRlR3VpbGRTdGlja2VyT3B0aW9ucywgcmVhc29uPzogc3RyaW5nKTogUHJvbWlzZTxEaXNjb3JkU3RpY2tlcj4ge1xuICAgIGNvbnN0IGZvcm0gPSBuZXcgRm9ybURhdGEoKTtcbiAgICBmb3JtLmFwcGVuZCgnZmlsZScsIG9wdGlvbnMuZmlsZS5ibG9iLCBvcHRpb25zLmZpbGUubmFtZSk7XG4gICAgZm9ybS5hcHBlbmQoJ25hbWUnLCBvcHRpb25zLm5hbWUpO1xuICAgIGZvcm0uYXBwZW5kKCdkZXNjcmlwdGlvbicsIG9wdGlvbnMuZGVzY3JpcHRpb24pO1xuICAgIGZvcm0uYXBwZW5kKCd0YWdzJywgb3B0aW9ucy50YWdzKTtcblxuICAgIHJldHVybiBhd2FpdCByZXN0LnBvc3Q8RGlzY29yZFN0aWNrZXI+KHJlc3Qucm91dGVzLmd1aWxkcy5zdGlja2VycyhndWlsZElkKSwgeyBib2R5OiBmb3JtLCByZWFzb24gfSk7XG4gIH0sXG4gIC8qKlxuICAgKiBDcmVhdGVzIGEgdGVtcGxhdGUgZnJvbSBhIGd1aWxkLlxuICAgKlxuICAgKiBAcGFyYW0gZ3VpbGRJZCAtIFRoZSBJRCBvZiB0aGUgZ3VpbGQgdG8gY3JlYXRlIHRoZSB0ZW1wbGF0ZSBmcm9tLlxuICAgKiBAcGFyYW0gb3B0aW9ucyAtIFRoZSBwYXJhbWV0ZXJzIGZvciB0aGUgY3JlYXRpb24gb2YgdGhlIHRlbXBsYXRlLlxuICAgKiBAcmV0dXJucyBBbiBpbnN0YW5jZSBvZiB0aGUgY3JlYXRlZCB7QGxpbmsgRGlzY29yZFRlbXBsYXRlfS5cbiAgICpcbiAgICogQHJlbWFya3NcbiAgICogUmVxdWlyZXMgdGhlIGBNQU5BR0VfR1VJTERgIHBlcm1pc3Npb24uXG4gICAqXG4gICAqIEZpcmVzIGEgX0d1aWxkIFVwZGF0ZV8gZ2F0ZXdheSBldmVudC5cbiAgICpcbiAgICogQHNlZSB7QGxpbmsgaHR0cHM6Ly9kb2NzLmRpc2NvcmQuY29tL2RldmVsb3BlcnMvcmVzb3VyY2VzL2d1aWxkLXRlbXBsYXRlI2NyZWF0ZS1ndWlsZC10ZW1wbGF0ZX1cbiAgICovXG4gIGFzeW5jIGNyZWF0ZUd1aWxkVGVtcGxhdGUocmVzdDogUmVzdE1hbmFnZXIsIGd1aWxkSWQ6IEJpZ1N0cmluZywgb3B0aW9uczogQ3JlYXRlVGVtcGxhdGUpOiBQcm9taXNlPERpc2NvcmRUZW1wbGF0ZT4ge1xuICAgIHJldHVybiBhd2FpdCByZXN0LnBvc3Q8RGlzY29yZFRlbXBsYXRlPihyZXN0LnJvdXRlcy5ndWlsZHMudGVtcGxhdGVzLmFsbChndWlsZElkKSwgeyBib2R5OiBvcHRpb25zIH0pO1xuICB9LFxuICAvKipcbiAgICogQ3JlYXRlcyBhbiBpbnZpdGUgdG8gYSBjaGFubmVsIGluIGEgZ3VpbGQuXG4gICAqXG4gICAqIEBwYXJhbSBjaGFubmVsSWQgLSBUaGUgSUQgb2YgdGhlIGNoYW5uZWwgdG8gY3JlYXRlIHRoZSBpbnZpdGUgdG8uXG4gICAqIEBwYXJhbSBvcHRpb25zIC0gVGhlIHBhcmFtZXRlcnMgZm9yIHRoZSBjcmVhdGlvbiBvZiB0aGUgaW52aXRlLlxuICAgKiBAcGFyYW0ge3N0cmluZ30gW3JlYXNvbl0gLSBBbiBvcHRpb25hbCByZWFzb24gZm9yIHRoZSBhY3Rpb24sIHRvIGJlIGluY2x1ZGVkIGluIHRoZSBhdWRpdCBsb2cuXG4gICAqIEByZXR1cm5zIEFuIGluc3RhbmNlIG9mIHRoZSBjcmVhdGVkIHtAbGluayBEaXNjb3JkSW52aXRlfS5cbiAgICpcbiAgICogQHJlbWFya3NcbiAgICogUmVxdWlyZXMgdGhlIGBDUkVBVEVfSU5TVEFOVF9JTlZJVEVgIHBlcm1pc3Npb24uXG4gICAqXG4gICAqIEZpcmVzIGFuIF9JbnZpdGUgQ3JlYXRlXyBnYXRld2F5IGV2ZW50LlxuICAgKlxuICAgKiBAcHJpdmF0ZVJlbWFya3NcbiAgICogVGhlIHJlcXVlc3QgYm9keSBpcyBub3Qgb3B0aW9uYWwsIGFuZCBhbiBlbXB0eSBKU09OIG9iamVjdCBtdXN0IGJlIHNlbnQgcmVnYXJkbGVzcyBvZiB3aGV0aGVyIGFueSBmaWVsZHMgYXJlIGJlaW5nIHRyYW5zbWl0dGVkLlxuICAgKlxuICAgKiBAc2VlIHtAbGluayBodHRwczovL2RvY3MuZGlzY29yZC5jb20vZGV2ZWxvcGVycy9yZXNvdXJjZXMvY2hhbm5lbCNjcmVhdGUtY2hhbm5lbC1pbnZpdGV9XG4gICAqL1xuICBhc3luYyBjcmVhdGVJbnZpdGUocmVzdDogUmVzdE1hbmFnZXIsIGNoYW5uZWxJZDogQmlnU3RyaW5nLCBvcHRpb25zPzogQ3JlYXRlQ2hhbm5lbEludml0ZSwgcmVhc29uPzogc3RyaW5nKTogUHJvbWlzZTxEaXNjb3JkSW52aXRlPiB7XG4gICAgb3B0aW9ucyA/Pz0ge307XG5cbiAgICBpZiAoIW9wdGlvbnMudGFyZ2V0VXNlcnNGaWxlKSB7XG4gICAgICByZXR1cm4gYXdhaXQgcmVzdC5wb3N0PERpc2NvcmRJbnZpdGU+KHJlc3Qucm91dGVzLmNoYW5uZWxzLmludml0ZXMoY2hhbm5lbElkKSwgeyBib2R5OiBvcHRpb25zLCByZWFzb24gfSk7XG4gICAgfVxuXG4gICAgLy8gV2hlbiB3ZSBoYXZlIHRvIHVwbG9hZCBhIGZpbGUsIHdlIG5lZWQgdG8gdXNlIEZvcm1EYXRhLCBhbmQgYWxsIG90aGVyIGZpZWxkcyBuZWVkIHRvIGJlIHBhcnQgb2YgdGhlIHBheWxvYWRfanNvbiBmaWVsZC5cbiAgICBjb25zdCBmb3JtID0gbmV3IEZvcm1EYXRhKCk7XG5cbiAgICBmb3JtLmFwcGVuZCgncGF5bG9hZF9qc29uJywgSlNPTi5zdHJpbmdpZnkocmVzdC5jaGFuZ2VUb0Rpc2NvcmRGb3JtYXQoeyAuLi5vcHRpb25zLCB0YXJnZXRVc2Vyc0ZpbGU6IHVuZGVmaW5lZCB9KSkpO1xuICAgIGZvcm0uYXBwZW5kKCd0YXJnZXRfdXNlcnNfZmlsZScsIG9wdGlvbnMudGFyZ2V0VXNlcnNGaWxlKTtcblxuICAgIHJldHVybiBhd2FpdCByZXN0LnBvc3Q8RGlzY29yZEludml0ZT4ocmVzdC5yb3V0ZXMuY2hhbm5lbHMuaW52aXRlcyhjaGFubmVsSWQpLCB7IGJvZHk6IGZvcm0sIHJlYXNvbiB9KTtcbiAgfSxcbiAgLyoqXG4gICAqIEdldCBndWlsZCByb2xlIG1lbWJlciBjb3VudHNcbiAgICpcbiAgICogUmV0dXJucyBhIG1hcCBvZiByb2xlIElEcyB0byB0aGUgbnVtYmVyIG9mIG1lbWJlcnMgd2l0aCB0aGUgcm9sZS4gRG9lcyBub3QgaW5jbHVkZSB0aGUgXFxAZXZlcnlvbmUgcm9sZS5cbiAgICpcbiAgICogQHBhcmFtIGd1aWxkSWQgLSBUaGUgSUQgb2YgdGhlIGd1aWxkIHRvIGdldCByb2xlIG1lbWJlciBjb3VudHMgZm9yLlxuICAgKlxuICAgKiBAc2VlIHtAbGluayBodHRwczovL2RvY3MuZGlzY29yZC5jb20vZGV2ZWxvcGVycy9yZXNvdXJjZXMvZ3VpbGQjZ2V0LWd1aWxkLXJvbGUtbWVtYmVyLWNvdW50c31cbiAgICovXG4gIGFzeW5jIGdldEd1aWxkUm9sZU1lbWJlckNvdW50cyhyZXN0OiBSZXN0TWFuYWdlciwgZ3VpbGRJZDogQmlnU3RyaW5nKTogUHJvbWlzZTxSZWNvcmQ8c3RyaW5nLCBudW1iZXI+PiB7XG4gICAgcmV0dXJuIGF3YWl0IHJlc3QuZ2V0PFJlY29yZDxzdHJpbmcsIG51bWJlcj4+KHJlc3Qucm91dGVzLmd1aWxkcy5yb2xlcy5tZW1iZXJDb3VudHMoZ3VpbGRJZCkpO1xuICB9LFxuICAvKipcbiAgICogQ3JlYXRlcyBhIHJvbGUgaW4gYSBndWlsZC5cbiAgICpcbiAgICogQHBhcmFtIGd1aWxkSWQgLSBUaGUgSUQgb2YgdGhlIGd1aWxkIHRvIGNyZWF0ZSB0aGUgcm9sZSBpbi5cbiAgICogQHBhcmFtIG9wdGlvbnMgLSBUaGUgcGFyYW1ldGVycyBmb3IgdGhlIGNyZWF0aW9uIG9mIHRoZSByb2xlLlxuICAgKiBAcGFyYW0ge3N0cmluZ30gW3JlYXNvbl0gLSBBbiBvcHRpb25hbCByZWFzb24gZm9yIHRoZSBhY3Rpb24sIHRvIGJlIGluY2x1ZGVkIGluIHRoZSBhdWRpdCBsb2cuXG4gICAqIEByZXR1cm5zIEFuIGluc3RhbmNlIG9mIHRoZSBjcmVhdGVkIHtAbGluayBEaXNjb3JkUm9sZX0uXG4gICAqXG4gICAqIEByZW1hcmtzXG4gICAqIFJlcXVpcmVzIHRoZSBgTUFOQUdFX1JPTEVTYCBwZXJtaXNzaW9uLlxuICAgKlxuICAgKiBGaXJlcyBhIF9HdWlsZCBSb2xlIENyZWF0ZV8gZ2F0ZXdheSBldmVudC5cbiAgICpcbiAgICogQHNlZSB7QGxpbmsgaHR0cHM6Ly9kb2NzLmRpc2NvcmQuY29tL2RldmVsb3BlcnMvcmVzb3VyY2VzL2d1aWxkI2NyZWF0ZS1ndWlsZC1yb2xlfVxuICAgKi9cbiAgYXN5bmMgY3JlYXRlUm9sZShyZXN0OiBSZXN0TWFuYWdlciwgZ3VpbGRJZDogQmlnU3RyaW5nLCBvcHRpb25zOiBDcmVhdGVHdWlsZFJvbGUsIHJlYXNvbj86IHN0cmluZyk6IFByb21pc2U8RGlzY29yZFJvbGU+IHtcbiAgICByZXR1cm4gYXdhaXQgcmVzdC5wb3N0PERpc2NvcmRSb2xlPihyZXN0LnJvdXRlcy5ndWlsZHMucm9sZXMuYWxsKGd1aWxkSWQpLCB7IGJvZHk6IG9wdGlvbnMsIHJlYXNvbiB9KTtcbiAgfSxcbiAgLyoqXG4gICAqIENyZWF0ZXMgYSBzY2hlZHVsZWQgZXZlbnQgaW4gYSBndWlsZC5cbiAgICpcbiAgICogQHBhcmFtIGd1aWxkSWQgLSBUaGUgSUQgb2YgdGhlIGd1aWxkIHRvIGNyZWF0ZSB0aGUgc2NoZWR1bGVkIGV2ZW50IGluLlxuICAgKiBAcGFyYW0gb3B0aW9ucyAtIFRoZSBwYXJhbWV0ZXJzIGZvciB0aGUgY3JlYXRpb24gb2YgdGhlIHNjaGVkdWxlZCBldmVudC5cbiAgICogQHBhcmFtIHtzdHJpbmd9IFtyZWFzb25dIC0gQW4gb3B0aW9uYWwgcmVhc29uIGZvciB0aGUgYWN0aW9uLCB0byBiZSBpbmNsdWRlZCBpbiB0aGUgYXVkaXQgbG9nLlxuICAgKiBAcmV0dXJucyBBbiBpbnN0YW5jZSBvZiB0aGUgY3JlYXRlZCB7QGxpbmsgRGlzY29yZFNjaGVkdWxlZEV2ZW50fS5cbiAgICpcbiAgICogQHJlbWFya3NcbiAgICogUmVxdWlyZXMgdGhlIGBNQU5BR0VfRVZFTlRTYCBwZXJtaXNzaW9uLlxuICAgKlxuICAgKiBBIGd1aWxkIGNhbiBvbmx5IGhhdmUgYSBtYXhpbXVtIG9mIDEwMCBldmVudHMgd2l0aCBhIHN0YXR1cyBvZiB7QGxpbmsgU2NoZWR1bGVkRXZlbnRTdGF0dXN9LkFjdGl2ZSBvciB7QGxpbmsgU2NoZWR1bGVkRXZlbnRTdGF0dXN9LlNjaGVkdWxlZCAoaW5jbHVzaXZlKS5cbiAgICpcbiAgICogRmlyZXMgYSBfR3VpbGQgU2NoZWR1bGVkIEV2ZW50IENyZWF0ZV8gZ2F0ZXdheSBldmVudC5cbiAgICpcbiAgICogQHNlZSB7QGxpbmsgaHR0cHM6Ly9kb2NzLmRpc2NvcmQuY29tL2RldmVsb3BlcnMvcmVzb3VyY2VzL2d1aWxkLXNjaGVkdWxlZC1ldmVudCNjcmVhdGUtZ3VpbGQtc2NoZWR1bGVkLWV2ZW50fVxuICAgKi9cbiAgYXN5bmMgY3JlYXRlU2NoZWR1bGVkRXZlbnQocmVzdDogUmVzdE1hbmFnZXIsIGd1aWxkSWQ6IEJpZ1N0cmluZywgb3B0aW9uczogQ3JlYXRlU2NoZWR1bGVkRXZlbnQsIHJlYXNvbj86IHN0cmluZyk6IFByb21pc2U8RGlzY29yZFNjaGVkdWxlZEV2ZW50PiB7XG4gICAgcmV0dXJuIGF3YWl0IHJlc3QucG9zdDxEaXNjb3JkU2NoZWR1bGVkRXZlbnQ+KHJlc3Qucm91dGVzLmd1aWxkcy5ldmVudHMuZXZlbnRzKGd1aWxkSWQpLCB7IGJvZHk6IG9wdGlvbnMsIHJlYXNvbiB9KTtcbiAgfSxcbiAgLyoqXG4gICAqIENyZWF0ZXMgYSBzdGFnZSBpbnN0YW5jZSBhc3NvY2lhdGVkIHdpdGggYSBzdGFnZSBjaGFubmVsLlxuICAgKlxuICAgKiBAcGFyYW0gb3B0aW9ucyAtIFRoZSBwYXJhbWV0ZXJzIGZvciB0aGUgY3JlYXRpb24gb2YgdGhlIHN0YWdlIGluc3RhbmNlLlxuICAgKiBAcGFyYW0ge3N0cmluZ30gW3JlYXNvbl0gLSBBbiBvcHRpb25hbCByZWFzb24gZm9yIHRoZSBhY3Rpb24sIHRvIGJlIGluY2x1ZGVkIGluIHRoZSBhdWRpdCBsb2cuXG4gICAqIEByZXR1cm5zIEFuIGluc3RhbmNlIG9mIHRoZSBjcmVhdGVkIHtAbGluayBEaXNjb3JkU3RhZ2VJbnN0YW5jZX0uXG4gICAqXG4gICAqIEByZW1hcmtzXG4gICAqIFJlcXVpcmVzIHRoZSB1c2VyIHRvIGJlIGEgbW9kZXJhdG9yIG9mIHRoZSBzdGFnZSBjaGFubmVsLlxuICAgKlxuICAgKiBGaXJlcyBhIF9TdGFnZSBJbnN0YW5jZSBDcmVhdGVfIGdhdGV3YXkgZXZlbnQuXG4gICAqXG4gICAqIEBzZWUge0BsaW5rIGh0dHBzOi8vZG9jcy5kaXNjb3JkLmNvbS9kZXZlbG9wZXJzL3Jlc291cmNlcy9zdGFnZS1pbnN0YW5jZSNjcmVhdGUtc3RhZ2UtaW5zdGFuY2V9XG4gICAqL1xuICBhc3luYyBjcmVhdGVTdGFnZUluc3RhbmNlKHJlc3Q6IFJlc3RNYW5hZ2VyLCBvcHRpb25zOiBDcmVhdGVTdGFnZUluc3RhbmNlLCByZWFzb24/OiBzdHJpbmcpOiBQcm9taXNlPERpc2NvcmRTdGFnZUluc3RhbmNlPiB7XG4gICAgcmV0dXJuIGF3YWl0IHJlc3QucG9zdDxEaXNjb3JkU3RhZ2VJbnN0YW5jZT4ocmVzdC5yb3V0ZXMuY2hhbm5lbHMuc3RhZ2VzKCksIHsgYm9keTogb3B0aW9ucywgcmVhc29uIH0pO1xuICB9LFxuICAvKipcbiAgICogQ3JlYXRlcyBhIHdlYmhvb2suXG4gICAqXG4gICAqIEBwYXJhbSBjaGFubmVsSWQgLSBUaGUgSUQgb2YgdGhlIGNoYW5uZWwgdG8gY3JlYXRlIHRoZSB3ZWJob29rIGluLlxuICAgKiBAcGFyYW0gb3B0aW9ucyAtIFRoZSBwYXJhbWV0ZXJzIGZvciB0aGUgY3JlYXRpb24gb2YgdGhlIHdlYmhvb2suXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBbcmVhc29uXSAtIEFuIG9wdGlvbmFsIHJlYXNvbiBmb3IgdGhlIGFjdGlvbiwgdG8gYmUgaW5jbHVkZWQgaW4gdGhlIGF1ZGl0IGxvZy5cbiAgICogQHJldHVybnMgQW4gaW5zdGFuY2Ugb2YgdGhlIGNyZWF0ZWQge0BsaW5rIERpc2NvcmRXZWJob29rfS5cbiAgICpcbiAgICogQHJlbWFya3NcbiAgICogUmVxdWlyZXMgdGhlIGBNQU5BR0VfV0VCSE9PS1NgIHBlcm1pc3Npb24uXG4gICAqXG4gICAqIOKaoO+4jyBUaGUgd2ViaG9vayBuYW1lIG11c3Qgbm90IGNvbnRhaW4gdGhlIHN1YnN0cmluZ3MgJ2NseWRlJywgb3IgJ2Rpc2NvcmQnIChjYXNlLWluc2Vuc2l0aXZlKS5cbiAgICpcbiAgICogRmlyZXMgYSBfV2ViaG9va3MgVXBkYXRlXyBnYXRld2F5IGV2ZW50LlxuICAgKlxuICAgKiBAc2VlIHtAbGluayBodHRwczovL2RvY3MuZGlzY29yZC5jb20vZGV2ZWxvcGVycy9yZXNvdXJjZXMvd2ViaG9vayNjcmVhdGUtd2ViaG9va31cbiAgICovXG4gIGFzeW5jIGNyZWF0ZVdlYmhvb2socmVzdDogUmVzdE1hbmFnZXIsIGNoYW5uZWxJZDogQmlnU3RyaW5nLCBvcHRpb25zOiBDcmVhdGVXZWJob29rLCByZWFzb24/OiBzdHJpbmcpOiBQcm9taXNlPERpc2NvcmRXZWJob29rPiB7XG4gICAgcmV0dXJuIGF3YWl0IHJlc3QucG9zdDxEaXNjb3JkV2ViaG9vaz4ocmVzdC5yb3V0ZXMuY2hhbm5lbHMud2ViaG9va3MoY2hhbm5lbElkKSwge1xuICAgICAgYm9keTogb3B0aW9ucyxcbiAgICAgIHJlYXNvbixcbiAgICB9KTtcbiAgfSxcbiAgLyoqXG4gICAqIERlbGV0ZXMgYW4gYXV0b21vZCBydWxlLlxuICAgKlxuICAgKiBAcGFyYW0gZ3VpbGRJZCAtIFRoZSBJRCBvZiB0aGUgZ3VpbGQgdG8gZGVsZXRlIHRoZSBydWxlIGZyb20uXG4gICAqIEBwYXJhbSBydWxlSWQgLSBUaGUgSUQgb2YgdGhlIGF1dG9tb2QgcnVsZSB0byBkZWxldGUuXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBbcmVhc29uXSAtIEFuIG9wdGlvbmFsIHJlYXNvbiBmb3IgdGhlIGFjdGlvbiwgdG8gYmUgaW5jbHVkZWQgaW4gdGhlIGF1ZGl0IGxvZy5cbiAgICpcbiAgICogQHJlbWFya3NcbiAgICogUmVxdWlyZXMgdGhlIGBNQU5BR0VfR1VJTERgIHBlcm1pc3Npb24uXG4gICAqXG4gICAqIEZpcmVzIGFuIF9BdXRvIE1vZGVyYXRpb24gUnVsZSBEZWxldGVfIGdhdGV3YXkgZXZlbnQuXG4gICAqXG4gICAqIEBzZWUge0BsaW5rIGh0dHBzOi8vZG9jcy5kaXNjb3JkLmNvbS9kZXZlbG9wZXJzL3Jlc291cmNlcy9hdXRvLW1vZGVyYXRpb24jZGVsZXRlLWF1dG8tbW9kZXJhdGlvbi1ydWxlfVxuICAgKi9cbiAgYXN5bmMgZGVsZXRlQXV0b21vZFJ1bGUocmVzdDogUmVzdE1hbmFnZXIsIGd1aWxkSWQ6IEJpZ1N0cmluZywgcnVsZUlkOiBCaWdTdHJpbmcsIHJlYXNvbj86IHN0cmluZyk6IFByb21pc2U8dm9pZD4ge1xuICAgIGF3YWl0IHJlc3QuZGVsZXRlKHJlc3Qucm91dGVzLmd1aWxkcy5hdXRvbW9kLnJ1bGUoZ3VpbGRJZCwgcnVsZUlkKSwgeyByZWFzb24gfSk7XG4gIH0sXG4gIC8qKlxuICAgKiBTZXQgYSB2b2ljZSBjaGFubmVs4oCZcyBzdGF0dXNcbiAgICpcbiAgICogQHBhcmFtIGNoYW5uZWxJZCAtIFRoZSBJRCBvZiB0aGUgY2hhbm5lbCB0byBzZXQgdGhlIHN0YXR1cyBvZi5cbiAgICogQHBhcmFtIG9wdGlvbnMgLSBUaGUgcGFyYW1ldGVycyBmb3IgdGhlIHN0YXR1cyBvZiB0aGUgdm9pY2UgY2hhbm5lbC5cbiAgICogQHBhcmFtIHtzdHJpbmd9IFtyZWFzb25dIC0gQW4gb3B0aW9uYWwgcmVhc29uIGZvciB0aGUgYWN0aW9uLCB0byBiZSBpbmNsdWRlZCBpbiB0aGUgYXVkaXQgbG9nLlxuICAgKiBAcmV0dXJucyBOb3RoaW5nXG4gICAqXG4gICAqIEByZW1hcmtzXG4gICAqIFJlcXVpcmVzIHRoZSBgU0VUX1ZPSUNFX0NIQU5ORUxfU1RBVFVTYCBwZXJtaXNzaW9uLCBhbmQgYWRkaXRpb25hbGx5IHRoZSBgTUFOQUdFX0NIQU5ORUxTYCBwZXJtaXNzaW9uIGlmIHRoZSBjdXJyZW50IHVzZXIgaXMgbm90IGNvbm5lY3RlZCB0byB0aGUgdm9pY2UgY2hhbm5lbC5cbiAgICpcbiAgICogRmlyZXMgYSBfVm9pY2UgQ2hhbm5lbCBTdGF0dXMgVXBkYXRlXyBHYXRld2F5IGV2ZW50LlxuICAgKlxuICAgKiBAc2VlIHtAbGluayBodHRwczovL2RvY3MuZGlzY29yZC5jb20vZGV2ZWxvcGVycy9yZXNvdXJjZXMvY2hhbm5lbCNzZXQtdm9pY2UtY2hhbm5lbC1zdGF0dXN9XG4gICAqL1xuICBhc3luYyBzZXRWb2ljZUNoYW5uZWxTdGF0dXMocmVzdDogUmVzdE1hbmFnZXIsIGNoYW5uZWxJZDogQmlnU3RyaW5nLCBvcHRpb25zOiBTZXRWb2ljZUNoYW5uZWxTdGF0dXMsIHJlYXNvbj86IHN0cmluZyk6IFByb21pc2U8dm9pZD4ge1xuICAgIGF3YWl0IHJlc3QucHV0KHJlc3Qucm91dGVzLmNoYW5uZWxzLnZvaWNlU3RhdHVzKGNoYW5uZWxJZCksIHsgYm9keTogb3B0aW9ucywgcmVhc29uIH0pO1xuICB9LFxuICAvKipcbiAgICogRGVsZXRlcyBhIGNoYW5uZWwgZnJvbSB3aXRoaW4gYSBndWlsZC5cbiAgICpcbiAgICogQHBhcmFtIGNoYW5uZWxJZCAtIFRoZSBJRCBvZiB0aGUgY2hhbm5lbCB0byBkZWxldGUuXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBbcmVhc29uXSAtIEFuIG9wdGlvbmFsIHJlYXNvbiBmb3IgdGhlIGFjdGlvbiwgdG8gYmUgaW5jbHVkZWQgaW4gdGhlIGF1ZGl0IGxvZy5cbiAgICogQHJldHVybnMgbm90aGluZ1xuICAgKlxuICAgKiBAcmVtYXJrc1xuICAgKiBGb3IgY29tbXVuaXR5IGd1aWxkcywgdGhlIF9SdWxlc18sIF9HdWlkZWxpbmVzXyBhbmQgX0NvbW11bml0eSBVcGRhdGVfIGNoYW5uZWxzIGNhbm5vdCBiZSBkZWxldGVkLlxuICAgKlxuICAgKiBJZiB0aGUgY2hhbm5lbCBpcyBhIHRocmVhZDpcbiAgICogLSBSZXF1aXJlcyB0aGUgYE1BTkFHRV9USFJFQURTYCBwZXJtaXNzaW9uLlxuICAgKlxuICAgKiAtIEZpcmVzIGEgX1RocmVhZCBEZWxldGVfIGdhdGV3YXkgZXZlbnQuXG4gICAqXG4gICAqIE90aGVyd2lzZTpcbiAgICogLSBSZXF1aXJlcyB0aGUgYE1BTkFHRV9DSEFOTkVMU2AgcGVybWlzc2lvbi5cbiAgICpcbiAgICogLSDimqDvuI8gRGVsZXRpbmcgYSBjYXRlZ29yeSBjaGFubmVsIGRvZXMgbm90IGRlbGV0ZSBpdHMgY2hpbGQgY2hhbm5lbHMuXG4gICAqICAgSW5zdGVhZCwgdGhleSB3aWxsIGhhdmUgdGhlaXIgYHBhcmVudF9pZGAgcHJvcGVydHkgcmVtb3ZlZCwgYW5kIGEgYENoYW5uZWwgVXBkYXRlYCBnYXRld2F5IGV2ZW50IHdpbGwgZmlyZSBmb3IgZWFjaCBvZiB0aGVtLlxuICAgKlxuICAgKiAtIEZpcmVzIGEgX0NoYW5uZWwgRGVsZXRlXyBnYXRld2F5IGV2ZW50LlxuICAgKlxuICAgKiBAc2VlIHtAbGluayBodHRwczovL2RvY3MuZGlzY29yZC5jb20vZGV2ZWxvcGVycy9yZXNvdXJjZXMvY2hhbm5lbCNkZWxldGVjbG9zZS1jaGFubmVsfVxuICAgKi9cbiAgYXN5bmMgZGVsZXRlQ2hhbm5lbChyZXN0OiBSZXN0TWFuYWdlciwgY2hhbm5lbElkOiBCaWdTdHJpbmcsIHJlYXNvbj86IHN0cmluZyk6IFByb21pc2U8dm9pZD4ge1xuICAgIGF3YWl0IHJlc3QuZGVsZXRlKHJlc3Qucm91dGVzLmNoYW5uZWxzLmNoYW5uZWwoY2hhbm5lbElkKSwge1xuICAgICAgcmVhc29uLFxuICAgIH0pO1xuICB9LFxuICAvKipcbiAgICogRGVsZXRlcyBhIHBlcm1pc3Npb24gb3ZlcnJpZGUgZm9yIGEgdXNlciBvciByb2xlIGluIGEgY2hhbm5lbC5cbiAgICpcbiAgICogQHBhcmFtIGNoYW5uZWxJZCAtIFRoZSBJRCBvZiB0aGUgY2hhbm5lbCB0byBkZWxldGUgdGhlIHBlcm1pc3Npb24gb3ZlcnJpZGUgb2YuXG4gICAqIEBwYXJhbSBvdmVyd3JpdGVJZCAtIFRoZSBJRCBvZiB0aGUgcGVybWlzc2lvbiBvdmVycmlkZSB0byBkZWxldGUuXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBbcmVhc29uXSAtIEFuIG9wdGlvbmFsIHJlYXNvbiBmb3IgdGhlIGFjdGlvbiwgdG8gYmUgaW5jbHVkZWQgaW4gdGhlIGF1ZGl0IGxvZy5cbiAgICpcbiAgICogQHJlbWFya3NcbiAgICogUmVxdWlyZXMgdGhlIGBNQU5BR0VfUk9MRVNgIHBlcm1pc3Npb24uXG4gICAqXG4gICAqIEZpcmVzIGEgX0NoYW5uZWwgVXBkYXRlXyBnYXRld2F5IGV2ZW50LlxuICAgKlxuICAgKiBAc2VlIHtAbGluayBodHRwczovL2RvY3MuZGlzY29yZC5jb20vZGV2ZWxvcGVycy9yZXNvdXJjZXMvY2hhbm5lbCNkZWxldGUtY2hhbm5lbC1wZXJtaXNzaW9ufVxuICAgKi9cbiAgYXN5bmMgZGVsZXRlQ2hhbm5lbFBlcm1pc3Npb25PdmVycmlkZShyZXN0OiBSZXN0TWFuYWdlciwgY2hhbm5lbElkOiBCaWdTdHJpbmcsIG92ZXJ3cml0ZUlkOiBCaWdTdHJpbmcsIHJlYXNvbj86IHN0cmluZyk6IFByb21pc2U8dm9pZD4ge1xuICAgIGF3YWl0IHJlc3QuZGVsZXRlKHJlc3Qucm91dGVzLmNoYW5uZWxzLm92ZXJ3cml0ZShjaGFubmVsSWQsIG92ZXJ3cml0ZUlkKSwgeyByZWFzb24gfSk7XG4gIH0sXG4gIC8qKlxuICAgKiBEZWxldGVzIGFuIGVtb2ppIGZyb20gYSBndWlsZC5cbiAgICpcbiAgICogQHBhcmFtIGd1aWxkSWQgLSBUaGUgSUQgb2YgdGhlIGd1aWxkIGZyb20gd2hpY2ggdG8gZGVsZXRlIHRoZSBlbW9qaS5cbiAgICogQHBhcmFtIGlkIC0gVGhlIElEIG9mIHRoZSBlbW9qaSB0byBkZWxldGUuXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBbcmVhc29uXSAtIEFuIG9wdGlvbmFsIHJlYXNvbiBmb3IgdGhlIGFjdGlvbiwgdG8gYmUgaW5jbHVkZWQgaW4gdGhlIGF1ZGl0IGxvZy5cbiAgICpcbiAgICogQHJlbWFya3NcbiAgICogRm9yIGVtb2ppcyBjcmVhdGVkIGJ5IHRoZSBjdXJyZW50IHVzZXIsIHJlcXVpcmVzIGVpdGhlciB0aGUgYENSRUFURV9HVUlMRF9FWFBSRVNTSU9OU2Agb3IgYE1BTkFHRV9HVUlMRF9FWFBSRVNTSU9OU2AgcGVybWlzc2lvbi5cbiAgICogRm9yIG90aGVyIGVtb2ppcywgcmVxdWlyZXMgdGhlIGBNQU5BR0VfR1VJTERfRVhQUkVTU0lPTlNgIHBlcm1pc3Npb24uXG4gICAqXG4gICAqIEZpcmVzIGEgX0d1aWxkIEVtb2ppcyBVcGRhdGVfIGdhdGV3YXkgZXZlbnQuXG4gICAqXG4gICAqIEBzZWUge0BsaW5rIGh0dHBzOi8vZG9jcy5kaXNjb3JkLmNvbS9kZXZlbG9wZXJzL3Jlc291cmNlcy9lbW9qaSNkZWxldGUtZ3VpbGQtZW1vaml9XG4gICAqL1xuICBhc3luYyBkZWxldGVFbW9qaShyZXN0OiBSZXN0TWFuYWdlciwgZ3VpbGRJZDogQmlnU3RyaW5nLCBpZDogQmlnU3RyaW5nLCByZWFzb24/OiBzdHJpbmcpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBhd2FpdCByZXN0LmRlbGV0ZShyZXN0LnJvdXRlcy5ndWlsZHMuZW1vamkoZ3VpbGRJZCwgaWQpLCB7IHJlYXNvbiB9KTtcbiAgfSxcbiAgLyoqXG4gICAqIERlbGV0ZXMgYW4gZW1vamkgZnJvbSB0aGUgYXBwbGljYXRpb24uXG4gICAqXG4gICAqIEBwYXJhbSBpZCAtIFRoZSBJRCBvZiB0aGUgZW1vamkgdG8gZGVsZXRlLlxuICAgKlxuICAgKiBAc2VlIHtAbGluayBodHRwczovL2RvY3MuZGlzY29yZC5jb20vZGV2ZWxvcGVycy9yZXNvdXJjZXMvZW1vamkjZGVsZXRlLWFwcGxpY2F0aW9uLWVtb2ppfVxuICAgKi9cbiAgYXN5bmMgZGVsZXRlQXBwbGljYXRpb25FbW9qaShyZXN0OiBSZXN0TWFuYWdlciwgaWQ6IEJpZ1N0cmluZyk6IFByb21pc2U8dm9pZD4ge1xuICAgIGF3YWl0IHJlc3QuZGVsZXRlKHJlc3Qucm91dGVzLmFwcGxpY2F0aW9uRW1vamkocmVzdC5hcHBsaWNhdGlvbklkLCBpZCkpO1xuICB9LFxuICAvKipcbiAgICogRGVsZXRlcyBhIGZvbGxvdy11cCBtZXNzYWdlIHRvIGFuIGludGVyYWN0aW9uLlxuICAgKlxuICAgKiBAcGFyYW0gdG9rZW4gLSBUaGUgaW50ZXJhY3Rpb24gdG9rZW4gdG8gdXNlLCBwcm92aWRlZCBpbiB0aGUgb3JpZ2luYWwgaW50ZXJhY3Rpb24uXG4gICAqIEBwYXJhbSBtZXNzYWdlSWQgLSBUaGUgSUQgb2YgdGhlIG1lc3NhZ2UgdG8gZGVsZXRlLlxuICAgKlxuICAgKiBAcmVtYXJrc1xuICAgKiBVbmxpa2UgYGRlbGV0ZU1lc3NhZ2UoKWAsIHRoaXMgZW5kcG9pbnQgYWxsb3dzIHRoZSBib3QgdXNlciB0byBhY3Qgd2l0aG91dCBuZWVkaW5nIHRvIHNlZSB0aGUgY2hhbm5lbCB0aGUgbWVzc2FnZSBpcyBpbi5cbiAgICpcbiAgICogRmlyZXMgYSBfTWVzc2FnZSBEZWxldGVfIGV2ZW50LlxuICAgKlxuICAgKiBAc2VlIHtAbGluayBodHRwczovL2RvY3MuZGlzY29yZC5jb20vZGV2ZWxvcGVycy9pbnRlcmFjdGlvbnMvcmVjZWl2aW5nLWFuZC1yZXNwb25kaW5nI2RlbGV0ZS1mb2xsb3d1cC1tZXNzYWdlfVxuICAgKi9cbiAgYXN5bmMgZGVsZXRlRm9sbG93dXBNZXNzYWdlKHJlc3Q6IFJlc3RNYW5hZ2VyLCB0b2tlbjogc3RyaW5nLCBtZXNzYWdlSWQ6IEJpZ1N0cmluZyk6IFByb21pc2U8dm9pZD4ge1xuICAgIGF3YWl0IHJlc3QuZGVsZXRlKHJlc3Qucm91dGVzLmludGVyYWN0aW9ucy5yZXNwb25zZXMubWVzc2FnZShyZXN0LmFwcGxpY2F0aW9uSWQsIHRva2VuLCBtZXNzYWdlSWQpLCB7IHVuYXV0aG9yaXplZDogdHJ1ZSB9KTtcbiAgfSxcbiAgLyoqXG4gICAqIERlbGV0ZXMgYW4gYXBwbGljYXRpb24gY29tbWFuZCByZWdpc3RlcmVkIGdsb2JhbGx5LlxuICAgKlxuICAgKiBAcGFyYW0gY29tbWFuZElkIC0gVGhlIElEIG9mIHRoZSBjb21tYW5kIHRvIGRlbGV0ZS5cbiAgICpcbiAgICogQHNlZSB7QGxpbmsgaHR0cHM6Ly9kb2NzLmRpc2NvcmQuY29tL2RldmVsb3BlcnMvaW50ZXJhY3Rpb25zL2FwcGxpY2F0aW9uLWNvbW1hbmRzI2RlbGV0ZS1nbG9iYWwtYXBwbGljYXRpb24tY29tbWFuZH1cbiAgICovXG4gIGFzeW5jIGRlbGV0ZUdsb2JhbEFwcGxpY2F0aW9uQ29tbWFuZChyZXN0OiBSZXN0TWFuYWdlciwgY29tbWFuZElkOiBCaWdTdHJpbmcpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBhd2FpdCByZXN0LmRlbGV0ZShyZXN0LnJvdXRlcy5pbnRlcmFjdGlvbnMuY29tbWFuZHMuY29tbWFuZChyZXN0LmFwcGxpY2F0aW9uSWQsIGNvbW1hbmRJZCkpO1xuICB9LFxuICAvKipcbiAgICogRGVsZXRlcyBhbiBhcHBsaWNhdGlvbiBjb21tYW5kIHJlZ2lzdGVyZWQgaW4gYSBndWlsZC5cbiAgICpcbiAgICogQHBhcmFtIGd1aWxkSWQgLSBUaGUgSUQgb2YgdGhlIGd1aWxkIHRvIGRlbGV0ZSB0aGUgY29tbWFuZCBmcm9tLlxuICAgKiBAcGFyYW0gY29tbWFuZElkIC0gVGhlIElEIG9mIHRoZSBjb21tYW5kIHRvIGRlbGV0ZSBmcm9tIHRoZSBndWlsZC5cbiAgICpcbiAgICogQHNlZSB7QGxpbmsgaHR0cHM6Ly9kb2NzLmRpc2NvcmQuY29tL2RldmVsb3BlcnMvaW50ZXJhY3Rpb25zL2FwcGxpY2F0aW9uLWNvbW1hbmRzI2RlbGV0ZS1ndWlsZC1hcHBsaWNhdGlvbi1jb21tYW5kfVxuICAgKi9cbiAgYXN5bmMgZGVsZXRlR3VpbGRBcHBsaWNhdGlvbkNvbW1hbmQocmVzdDogUmVzdE1hbmFnZXIsIGNvbW1hbmRJZDogQmlnU3RyaW5nLCBndWlsZElkOiBCaWdTdHJpbmcpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBhd2FpdCByZXN0LmRlbGV0ZShyZXN0LnJvdXRlcy5pbnRlcmFjdGlvbnMuY29tbWFuZHMuZ3VpbGRzLm9uZShyZXN0LmFwcGxpY2F0aW9uSWQsIGd1aWxkSWQsIGNvbW1hbmRJZCkpO1xuICB9LFxuICAvKipcbiAgICogRGVsZXRlIGEgbmV3IHN0aWNrZXIgZm9yIHRoZSBndWlsZC5cbiAgICpcbiAgICogQHBhcmFtIGd1aWxkSWQgVGhlIElEIG9mIHRoZSBndWlsZCB0byBnZXRcbiAgICogQHBhcmFtIHtzdHJpbmd9IFtyZWFzb25dIC0gQW4gb3B0aW9uYWwgcmVhc29uIGZvciB0aGUgYWN0aW9uLCB0byBiZSBpbmNsdWRlZCBpbiB0aGUgYXVkaXQgbG9nLlxuICAgKiBAcmV0dXJuIEEge0BsaW5rIERpc2NvcmRTdGlja2VyfVxuICAgKlxuICAgKiBAcmVtYXJrc1xuICAgKiBGb3Igc3RpY2tlcnMgY3JlYXRlZCBieSB0aGUgY3VycmVudCB1c2VyLCByZXF1aXJlcyBlaXRoZXIgdGhlIGBDUkVBVEVfR1VJTERfRVhQUkVTU0lPTlNgIG9yIGBNQU5BR0VfR1VJTERfRVhQUkVTU0lPTlNgIHBlcm1pc3Npb24uXG4gICAqIEZvciBvdGhlciBzdGlja2VycywgcmVxdWlyZXMgdGhlIGBNQU5BR0VfR1VJTERfRVhQUkVTU0lPTlNgIHBlcm1pc3Npb24uXG4gICAqIEZpcmVzIGEgR3VpbGQgU3RpY2tlcnMgVXBkYXRlIEdhdGV3YXkgZXZlbnQuXG4gICAqIEV2ZXJ5IGd1aWxkcyBoYXMgZml2ZSBmcmVlIHN0aWNrZXIgc2xvdHMgYnkgZGVmYXVsdCwgYW5kIGVhY2ggQm9vc3QgbGV2ZWwgd2lsbCBncmFudCBhY2Nlc3MgdG8gbW9yZSBzbG90cy5cbiAgICogTG90dGllIHN0aWNrZXJzIGNhbiBvbmx5IGJlIHVwbG9hZGVkIG9uIGd1aWxkcyB0aGF0IGhhdmUgZWl0aGVyIHRoZSBgVkVSSUZJRURgIGFuZC9vciB0aGUgYFBBUlRORVJFRGAgZ3VpbGQgZmVhdHVyZS5cbiAgICpcbiAgICogQHNlZSB7QGxpbmsgaHR0cHM6Ly9kb2NzLmRpc2NvcmQuY29tL2RldmVsb3BlcnMvcmVzb3VyY2VzL3N0aWNrZXIjZGVsZXRlLWd1aWxkLXN0aWNrZXJ9XG4gICAqL1xuICBhc3luYyBkZWxldGVHdWlsZFN0aWNrZXIocmVzdDogUmVzdE1hbmFnZXIsIGd1aWxkSWQ6IEJpZ1N0cmluZywgc3RpY2tlcklkOiBCaWdTdHJpbmcsIHJlYXNvbj86IHN0cmluZyk6IFByb21pc2U8dm9pZD4ge1xuICAgIGF3YWl0IHJlc3QuZGVsZXRlKHJlc3Qucm91dGVzLmd1aWxkcy5zdGlja2VyKGd1aWxkSWQsIHN0aWNrZXJJZCksIHsgcmVhc29uIH0pO1xuICB9LFxuICAvKipcbiAgICogRGVsZXRlcyBhIHRlbXBsYXRlIGZyb20gYSBndWlsZC5cbiAgICpcbiAgICogQHBhcmFtIGd1aWxkSWQgLSBUaGUgSUQgb2YgdGhlIGd1aWxkIHRvIGRlbGV0ZSB0aGUgdGVtcGxhdGUgZnJvbS5cbiAgICogQHBhcmFtIHRlbXBsYXRlQ29kZSAtIFRoZSBjb2RlIG9mIHRoZSB0ZW1wbGF0ZSB0byBkZWxldGUuXG4gICAqXG4gICAqIEByZW1hcmtzXG4gICAqIFJlcXVpcmVzIHRoZSBgTUFOQUdFX0dVSUxEYCBwZXJtaXNzaW9uLlxuICAgKlxuICAgKiBGaXJlcyBhIF9HdWlsZCBVcGRhdGVfIGdhdGV3YXkgZXZlbnQuXG4gICAqXG4gICAqIEBzZWUge0BsaW5rIGh0dHBzOi8vZG9jcy5kaXNjb3JkLmNvbS9kZXZlbG9wZXJzL3Jlc291cmNlcy9ndWlsZC10ZW1wbGF0ZSNkZWxldGUtZ3VpbGQtdGVtcGxhdGV9XG4gICAqL1xuICBhc3luYyBkZWxldGVHdWlsZFRlbXBsYXRlKHJlc3Q6IFJlc3RNYW5hZ2VyLCBndWlsZElkOiBCaWdTdHJpbmcsIHRlbXBsYXRlQ29kZTogc3RyaW5nKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgYXdhaXQgcmVzdC5kZWxldGUocmVzdC5yb3V0ZXMuZ3VpbGRzLnRlbXBsYXRlcy5ndWlsZChndWlsZElkLCB0ZW1wbGF0ZUNvZGUpKTtcbiAgfSxcbiAgLyoqXG4gICAqIERlbGV0ZXMgYW4gaW50ZWdyYXRpb24gYXR0YWNoZWQgdG8gYSBndWlsZC5cbiAgICpcbiAgICogQHBhcmFtIGd1aWxkSWQgLSBUaGUgSUQgb2YgdGhlIGd1aWxkIGZyb20gd2hpY2ggdG8gZGVsZXRlIHRoZSBpbnRlZ3JhdGlvbi5cbiAgICogQHBhcmFtIGludGVncmF0aW9uSWQgLSBUaGUgSUQgb2YgdGhlIGludGVncmF0aW9uIHRvIGRlbGV0ZSBmcm9tIHRoZSBndWlsZC5cbiAgICogQHBhcmFtIHtzdHJpbmd9IFtyZWFzb25dIC0gQW4gb3B0aW9uYWwgcmVhc29uIGZvciB0aGUgYWN0aW9uLCB0byBiZSBpbmNsdWRlZCBpbiB0aGUgYXVkaXQgbG9nLlxuICAgKlxuICAgKiBAcmVtYXJrc1xuICAgKiBSZXF1aXJlcyB0aGUgYE1BTkFHRV9HVUlMRGAgcGVybWlzc2lvbi5cbiAgICpcbiAgICogRGVsZXRlcyBhbGwgd2ViaG9va3MgYXNzb2NpYXRlZCB3aXRoIHRoZSBpbnRlZ3JhdGlvbiwgYW5kIGtpY2tzIHRoZSBhc3NvY2lhdGVkIGJvdCBpZiB0aGVyZSBpcyBvbmUuXG4gICAqXG4gICAqIEZpcmVzIGEgX0d1aWxkIEludGVncmF0aW9ucyBVcGRhdGVfIGdhdGV3YXkgZXZlbnQuXG4gICAqIEZpcmVzIGEgX0ludGVncmF0aW9uIERlbGV0ZV8gZ2F0ZXdheSBldmVudC5cbiAgICpcbiAgICogQHNlZSB7QGxpbmsgaHR0cHM6Ly9kb2NzLmRpc2NvcmQuY29tL2RldmVsb3BlcnMvcmVzb3VyY2VzL2d1aWxkI2RlbGV0ZS1ndWlsZC1pbnRlZ3JhdGlvbn1cbiAgICovXG4gIGFzeW5jIGRlbGV0ZUludGVncmF0aW9uKHJlc3Q6IFJlc3RNYW5hZ2VyLCBndWlsZElkOiBCaWdTdHJpbmcsIGludGVncmF0aW9uSWQ6IEJpZ1N0cmluZywgcmVhc29uPzogc3RyaW5nKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgYXdhaXQgcmVzdC5kZWxldGUocmVzdC5yb3V0ZXMuZ3VpbGRzLmludGVncmF0aW9uKGd1aWxkSWQsIGludGVncmF0aW9uSWQpLCB7IHJlYXNvbiB9KTtcbiAgfSxcbiAgLyoqXG4gICAqIERlbGV0ZXMgYW4gaW52aXRlIHRvIGEgY2hhbm5lbC5cbiAgICpcbiAgICogQHBhcmFtIGludml0ZUNvZGUgLSBUaGUgaW52aXRlIGNvZGUgb2YgdGhlIGludml0ZSB0byBkZWxldGUuXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBbcmVhc29uXSAtIEFuIG9wdGlvbmFsIHJlYXNvbiBmb3IgdGhlIGFjdGlvbiwgdG8gYmUgaW5jbHVkZWQgaW4gdGhlIGF1ZGl0IGxvZy5cbiAgICpcbiAgICogQHJlbWFya3NcbiAgICogUmVxdWlyZXMgdGhlIGBNQU5BR0VfQ0hBTk5FTFNgIHBlcm1pc3Npb24uXG4gICAqXG4gICAqIEZpcmVzIGFuIF9JbnZpdGUgRGVsZXRlXyBnYXRld2F5IGV2ZW50LlxuICAgKlxuICAgKiBAc2VlIHtAbGluayBodHRwczovL2RvY3MuZGlzY29yZC5jb20vZGV2ZWxvcGVycy9yZXNvdXJjZXMvY2hhbm5lbCNkZWxldGUtY2hhbm5lbC1pbnZpdGV9XG4gICAqL1xuICBhc3luYyBkZWxldGVJbnZpdGUocmVzdDogUmVzdE1hbmFnZXIsIGludml0ZUNvZGU6IHN0cmluZywgcmVhc29uPzogc3RyaW5nKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgYXdhaXQgcmVzdC5kZWxldGUocmVzdC5yb3V0ZXMuZ3VpbGRzLmludml0ZShpbnZpdGVDb2RlKSwgeyByZWFzb24gfSk7XG4gIH0sXG4gIC8qKlxuICAgKiBHZXRzIHRoZSB1c2VycyBhbGxvd2VkIHRvIHNlZSBhbmQgYWNjZXB0IHRoaXMgaW52aXRlLlxuICAgKlxuICAgKiBAcGFyYW0gaW52aXRlQ29kZSAtIFRoZSBpbnZpdGUgY29kZSBvZiB0aGUgaW52aXRlIHRvIHVwZGF0ZS5cbiAgICogQHJldHVybnMgQ1NWIGZpbGUgY29udGFpbmluZyB0aGUgdXNlciBJRHMgd2l0aCB0aGUgaGVhZGVyIGB1c2VyX2lkYCBhbmQgZWFjaCB1c2VyIElEIGZyb20gdGhlIG9yaWdpbmFsIGZpbGVcbiAgICpcbiAgICogQHJlbWFya3NcbiAgICogUmVxdWlyZXMgY2FsbGVkIHRvIGJlIHRoZSBpbnZpdGVyLCBvciBoYXZlIGBNQU5BR0VfR1VJTERgIHBlcm1pc3Npb24sIG9yIGhhdmUgYFZJRVdfQVVESVRfTE9HYCBwZXJtaXNzaW9uLlxuICAgKlxuICAgKiBAc2VlIHtAbGluayBodHRwczovL2RvY3MuZGlzY29yZC5jb20vZGV2ZWxvcGVycy9yZXNvdXJjZXMvaW52aXRlI2dldC10YXJnZXQtdXNlcnN9XG4gICAqL1xuICBhc3luYyBnZXRUYXJnZXRVc2VycyhyZXN0OiBSZXN0TWFuYWdlciwgaW52aXRlQ29kZTogc3RyaW5nKTogUHJvbWlzZTxzdHJpbmc+IHtcbiAgICByZXR1cm4gYXdhaXQgcmVzdC5nZXQ8c3RyaW5nPihyZXN0LnJvdXRlcy5ndWlsZHMuaW52aXRlVGFyZ2V0VXNlcnMoaW52aXRlQ29kZSkpO1xuICB9LFxuICAvKipcbiAgICogVXBkYXRlcyB0aGUgdXNlcnMgYWxsb3dlZCB0byBzZWUgYW5kIGFjY2VwdCB0aGlzIGludml0ZS5cbiAgICpcbiAgICogQHBhcmFtIGludml0ZUNvZGUgLSBUaGUgaW52aXRlIGNvZGUgb2YgdGhlIGludml0ZSB0byB1cGRhdGUuXG4gICAqIEBwYXJhbSB0YXJnZXRVc2Vyc0ZpbGUgLSBBIENTViBmaWxlIHdpdGggYSBzaW5nbGUgY29sdW1uIG9mIHVzZXIgSURzIGZvciBhbGwgdGhlIHVzZXJzIGFibGUgdG8gYWNjZXB0IHRoaXMgaW52aXRlXG4gICAqXG4gICAqIEByZW1hcmtzXG4gICAqIFJlcXVpcmVzIHRoZSBjYWxsZXIgdG8gYmUgdGhlIGludml0ZXIgb3IgaGF2ZSB0aGUgYE1BTkFHRV9HVUlMRGAgcGVybWlzc2lvbi5cbiAgICpcbiAgICogVXBsb2FkaW5nIGEgZmlsZSB3aXRoIGludmFsaWQgdXNlciBJRHMgd2lsbCByZXN1bHQgaW4gYSA0MDAgd2l0aCB0aGUgaW52YWxpZCBJRHMgZGVzY3JpYmVkLlxuICAgKlxuICAgKiBAc2VlIHtAbGluayBodHRwczovL2RvY3MuZGlzY29yZC5jb20vZGV2ZWxvcGVycy9yZXNvdXJjZXMvaW52aXRlI3VwZGF0ZS10YXJnZXQtdXNlcnN9XG4gICAqL1xuICBhc3luYyB1cGRhdGVUYXJnZXRVc2VycyhyZXN0OiBSZXN0TWFuYWdlciwgaW52aXRlQ29kZTogc3RyaW5nLCB0YXJnZXRVc2Vyc0ZpbGU6IEJsb2IpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBjb25zdCBmb3JtID0gbmV3IEZvcm1EYXRhKCk7XG4gICAgZm9ybS5hcHBlbmQoJ3RhcmdldF91c2Vyc19maWxlJywgdGFyZ2V0VXNlcnNGaWxlKTtcblxuICAgIGF3YWl0IHJlc3QucHV0KHJlc3Qucm91dGVzLmd1aWxkcy5pbnZpdGVUYXJnZXRVc2VycyhpbnZpdGVDb2RlKSwgeyBib2R5OiBmb3JtIH0pO1xuICB9LFxuICAvKipcbiAgICogUHJvY2Vzc2luZyB0YXJnZXQgdXNlcnMgZnJvbSBhIENTViB3aGVuIGNyZWF0aW5nIG9yIHVwZGF0aW5nIGFuIGludml0ZSBpcyBkb25lIGFzeW5jaHJvbm91c2x5LiBUaGlzIGVuZHBvaW50IGFsbG93cyB5b3UgdG8gY2hlY2sgdGhlIHN0YXR1cyBvZiB0aGF0IGpvYi5cbiAgICpcbiAgICogQHBhcmFtIGludml0ZUNvZGUgLSBUaGUgaW52aXRlIGNvZGUgb2YgdGhlIGludml0ZSB0byBjaGVjayB0aGUgdGFyZ2V0IHVzZXJzIGpvYiBzdGF0dXMgZm9yLlxuICAgKiBAcmV0dXJucyBBbiBvYmplY3QgY29udGFpbmluZyB0aGUgc3RhdHVzIG9mIHRoZSB0YXJnZXQgdXNlcnMgam9iLlxuICAgKlxuICAgKiBAcmVtYXJrc1xuICAgKiBSZXF1aXJlcyB0aGUgY2FsbGVyIHRvIGJlIHRoZSBpbnZpdGVyLCBvciBoYXZlIGBNQU5BR0VfR1VJTERgIHBlcm1pc3Npb24sIG9yIGhhdmUgYFZJRVdfQVVESVRfTE9HYCBwZXJtaXNzaW9uLlxuICAgKlxuICAgKiBAc2VlIHtAbGluayBodHRwczovL2RvY3MuZGlzY29yZC5jb20vZGV2ZWxvcGVycy9yZXNvdXJjZXMvaW52aXRlI2dldC10YXJnZXQtdXNlcnMtam9iLXN0YXR1c31cbiAgICovXG4gIGFzeW5jIGdldFRhcmdldFVzZXJzSm9iU3RhdHVzKHJlc3Q6IFJlc3RNYW5hZ2VyLCBpbnZpdGVDb2RlOiBzdHJpbmcpOiBQcm9taXNlPERpc2NvcmRUYXJnZXRVc2Vyc0pvYlN0YXR1cz4ge1xuICAgIHJldHVybiBhd2FpdCByZXN0LmdldDxEaXNjb3JkVGFyZ2V0VXNlcnNKb2JTdGF0dXM+KHJlc3Qucm91dGVzLmd1aWxkcy5pbnZpdGVUYXJnZXRVc2Vyc0pvYlN0YXR1cyhpbnZpdGVDb2RlKSk7XG4gIH0sXG4gIC8qKlxuICAgKiBEZWxldGVzIGEgbWVzc2FnZSBmcm9tIGEgY2hhbm5lbC5cbiAgICpcbiAgICogQHBhcmFtIGNoYW5uZWxJZCAtIFRoZSBJRCBvZiB0aGUgY2hhbm5lbCB0byBkZWxldGUgdGhlIG1lc3NhZ2UgZnJvbS5cbiAgICogQHBhcmFtIG1lc3NhZ2VJZCAtIFRoZSBJRCBvZiB0aGUgbWVzc2FnZSB0byBkZWxldGUgZnJvbSB0aGUgY2hhbm5lbC5cbiAgICogQHBhcmFtIHtzdHJpbmd9IFtyZWFzb25dIC0gQW4gb3B0aW9uYWwgcmVhc29uIGZvciB0aGUgYWN0aW9uLCB0byBiZSBpbmNsdWRlZCBpbiB0aGUgYXVkaXQgbG9nLlxuICAgKlxuICAgKiBAcmVtYXJrc1xuICAgKiBJZiBub3QgZGVsZXRpbmcgb3duIG1lc3NhZ2U6XG4gICAqIC0gUmVxdWlyZXMgdGhlIGBNQU5BR0VfTUVTU0FHRVNgIHBlcm1pc3Npb24uXG4gICAqXG4gICAqIEZpcmVzIGEgX01lc3NhZ2UgRGVsZXRlXyBnYXRld2F5IGV2ZW50LlxuICAgKlxuICAgKiBAc2VlIHtAbGluayBodHRwczovL2RvY3MuZGlzY29yZC5jb20vZGV2ZWxvcGVycy9yZXNvdXJjZXMvY2hhbm5lbCNkZWxldGUtbWVzc2FnZX1cbiAgICovXG4gIGFzeW5jIGRlbGV0ZU1lc3NhZ2UocmVzdDogUmVzdE1hbmFnZXIsIGNoYW5uZWxJZDogQmlnU3RyaW5nLCBtZXNzYWdlSWQ6IEJpZ1N0cmluZywgcmVhc29uPzogc3RyaW5nKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgYXdhaXQgcmVzdC5kZWxldGUocmVzdC5yb3V0ZXMuY2hhbm5lbHMubWVzc2FnZShjaGFubmVsSWQsIG1lc3NhZ2VJZCksIHsgcmVhc29uIH0pO1xuICB9LFxuICAvKipcbiAgICogRGVsZXRlcyBtdWx0aXBsZSBtZXNzYWdlcyBmcm9tIGEgY2hhbm5lbC5cbiAgICpcbiAgICogQHBhcmFtIGNoYW5uZWxJZCAtIFRoZSBJRCBvZiB0aGUgY2hhbm5lbCB0byBkZWxldGUgdGhlIG1lc3NhZ2VzIGZyb20uXG4gICAqIEBwYXJhbSBtZXNzYWdlSWRzIC0gVGhlIElEcyBvZiB0aGUgbWVzc2FnZXMgdG8gZGVsZXRlIGZyb20gdGhlIGNoYW5uZWwuXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBbcmVhc29uXSAtIEFuIG9wdGlvbmFsIHJlYXNvbiBmb3IgdGhlIGFjdGlvbiwgdG8gYmUgaW5jbHVkZWQgaW4gdGhlIGF1ZGl0IGxvZy5cbiAgICpcbiAgICogQHJlbWFya3NcbiAgICogUmVxdWlyZXMgdGhlIGBNQU5BR0VfTUVTU0FHRVNgIHBlcm1pc3Npb24uXG4gICAqXG4gICAqIOKaoO+4jyBNZXNzYWdlcyBvbGRlciB0aGFuIDIgd2Vla3Mgb2xkIGNhbm5vdCBiZSBkZWxldGVkLlxuICAgKlxuICAgKiBGaXJlcyBhIF9NZXNzYWdlIERlbGV0ZSBCdWxrXyBnYXRld2F5IGV2ZW50LlxuICAgKlxuICAgKiBAc2VlIHtAbGluayBodHRwczovL2RvY3MuZGlzY29yZC5jb20vZGV2ZWxvcGVycy9yZXNvdXJjZXMvY2hhbm5lbCNidWxrLWRlbGV0ZS1tZXNzYWdlc31cbiAgICovXG4gIGFzeW5jIGRlbGV0ZU1lc3NhZ2VzKHJlc3Q6IFJlc3RNYW5hZ2VyLCBjaGFubmVsSWQ6IEJpZ1N0cmluZywgbWVzc2FnZUlkczogQmlnU3RyaW5nW10sIHJlYXNvbj86IHN0cmluZyk6IFByb21pc2U8dm9pZD4ge1xuICAgIGF3YWl0IHJlc3QucG9zdChyZXN0LnJvdXRlcy5jaGFubmVscy5idWxrKGNoYW5uZWxJZCksIHtcbiAgICAgIGJvZHk6IHtcbiAgICAgICAgbWVzc2FnZXM6IG1lc3NhZ2VJZHMuc2xpY2UoMCwgMTAwKS5tYXAoKGlkKSA9PiBpZC50b1N0cmluZygpKSxcbiAgICAgIH0sXG4gICAgICByZWFzb24sXG4gICAgfSk7XG4gIH0sXG4gIC8qKlxuICAgKiBEZWxldGVzIHRoZSBpbml0aWFsIG1lc3NhZ2UgcmVzcG9uc2UgdG8gYW4gaW50ZXJhY3Rpb24uXG4gICAqXG4gICAqIEBwYXJhbSB0b2tlbiAtIFRoZSBpbnRlcmFjdGlvbiB0b2tlbiB0byB1c2UsIHByb3ZpZGVkIGluIHRoZSBvcmlnaW5hbCBpbnRlcmFjdGlvbi5cbiAgICpcbiAgICogQHJlbWFya3NcbiAgICogVW5saWtlIGBkZWxldGVNZXNzYWdlKClgLCB0aGlzIGVuZHBvaW50IGFsbG93cyB0aGUgYm90IHVzZXIgdG8gYWN0IHdpdGhvdXQgbmVlZGluZyB0byBzZWUgdGhlIGNoYW5uZWwgdGhlIG1lc3NhZ2UgaXMgaW4uXG4gICAqXG4gICAqIEZpcmVzIGEgX01lc3NhZ2UgRGVsZXRlXyBldmVudC5cbiAgICpcbiAgICogQHNlZSB7QGxpbmsgaHR0cHM6Ly9kb2NzLmRpc2NvcmQuY29tL2RldmVsb3BlcnMvaW50ZXJhY3Rpb25zL3JlY2VpdmluZy1hbmQtcmVzcG9uZGluZyNkZWxldGUtb3JpZ2luYWwtaW50ZXJhY3Rpb24tcmVzcG9uc2V9XG4gICAqL1xuICBhc3luYyBkZWxldGVPcmlnaW5hbEludGVyYWN0aW9uUmVzcG9uc2UocmVzdDogUmVzdE1hbmFnZXIsIHRva2VuOiBzdHJpbmcpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBhd2FpdCByZXN0LmRlbGV0ZShyZXN0LnJvdXRlcy5pbnRlcmFjdGlvbnMucmVzcG9uc2VzLm9yaWdpbmFsKHJlc3QuYXBwbGljYXRpb25JZCwgdG9rZW4pLCB7IHVuYXV0aG9yaXplZDogdHJ1ZSB9KTtcbiAgfSxcbiAgLyoqXG4gICAqIERlbGV0ZXMgYSByZWFjdGlvbiBhZGRlZCBieSB0aGUgYm90IHVzZXIgZnJvbSBhIG1lc3NhZ2UuXG4gICAqXG4gICAqIEBwYXJhbSBjaGFubmVsSWQgLSBUaGUgSUQgb2YgdGhlIGNoYW5uZWwgdGhlIG1lc3NhZ2UgdG8gZGVsZXRlIHRoZSByZWFjdGlvbiBmcm9tIGlzIGluLlxuICAgKiBAcGFyYW0gbWVzc2FnZUlkIC0gVGhlIElEIG9mIHRoZSBtZXNzYWdlIHRvIGRlbGV0ZSB0aGUgcmVhY3Rpb24gZnJvbS5cbiAgICogQHBhcmFtIHJlYWN0aW9uIC0gVGhlIHJlYWN0aW9uIHRvIGRlbGV0ZSBmcm9tIHRoZSBtZXNzYWdlLlxuICAgKlxuICAgKiBAcmVtYXJrc1xuICAgKiBSZXF1aXJlcyB0aGUgYFJFQURfTUVTU0FHRV9ISVNUT1JZYCBwZXJtaXNzaW9uLlxuICAgKlxuICAgKiBGaXJlcyBhIF9NZXNzYWdlIFJlYWN0aW9uIFJlbW92ZV8gZ2F0ZXdheSBldmVudC5cbiAgICpcbiAgICogQHNlZSB7QGxpbmsgaHR0cHM6Ly9kb2NzLmRpc2NvcmQuY29tL2RldmVsb3BlcnMvcmVzb3VyY2VzL2NoYW5uZWwjZGVsZXRlLW93bi1yZWFjdGlvbn1cbiAgICovXG4gIGFzeW5jIGRlbGV0ZU93blJlYWN0aW9uKHJlc3Q6IFJlc3RNYW5hZ2VyLCBjaGFubmVsSWQ6IEJpZ1N0cmluZywgbWVzc2FnZUlkOiBCaWdTdHJpbmcsIHJlYWN0aW9uOiBzdHJpbmcpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICByZWFjdGlvbiA9IHByb2Nlc3NSZWFjdGlvblN0cmluZyhyZWFjdGlvbik7XG5cbiAgICBhd2FpdCByZXN0LmRlbGV0ZShyZXN0LnJvdXRlcy5jaGFubmVscy5yZWFjdGlvbnMuYm90KGNoYW5uZWxJZCwgbWVzc2FnZUlkLCByZWFjdGlvbikpO1xuICB9LFxuICAvKipcbiAgICogRGVsZXRlcyBhbGwgcmVhY3Rpb25zIGZvciBhbGwgZW1vamlzIGZyb20gYSBtZXNzYWdlLlxuICAgKlxuICAgKiBAcGFyYW0gY2hhbm5lbElkIC0gVGhlIElEIG9mIHRoZSBjaGFubmVsIHRoZSBtZXNzYWdlIHRvIGRlbGV0ZSB0aGUgcmVhY3Rpb25zIGZyb20gaXMgaW4uXG4gICAqIEBwYXJhbSBtZXNzYWdlSWQgLSBUaGUgSUQgb2YgdGhlIG1lc3NhZ2UgdG8gZGVsZXRlIHRoZSByZWFjdGlvbnMgZnJvbS5cbiAgICpcbiAgICogQHJlbWFya3NcbiAgICogUmVxdWlyZXMgdGhlIGBSRUFEX01FU1NBR0VfSElTVE9SWWAgcGVybWlzc2lvbi5cbiAgICpcbiAgICogUmVxdWlyZXMgdGhlIGBNQU5BR0VfTUVTU0FHRVNgIHBlcm1pc3Npb24uXG4gICAqXG4gICAqIEZpcmVzIGEgX01lc3NhZ2UgUmVhY3Rpb24gUmVtb3ZlIEFsbF8gZ2F0ZXdheSBldmVudC5cbiAgICpcbiAgICogQHNlZSB7QGxpbmsgaHR0cHM6Ly9kb2NzLmRpc2NvcmQuY29tL2RldmVsb3BlcnMvcmVzb3VyY2VzL2NoYW5uZWwjZGVsZXRlLWFsbC1yZWFjdGlvbnN9XG4gICAqL1xuICBhc3luYyBkZWxldGVSZWFjdGlvbnNBbGwocmVzdDogUmVzdE1hbmFnZXIsIGNoYW5uZWxJZDogQmlnU3RyaW5nLCBtZXNzYWdlSWQ6IEJpZ1N0cmluZyk6IFByb21pc2U8dm9pZD4ge1xuICAgIGF3YWl0IHJlc3QuZGVsZXRlKHJlc3Qucm91dGVzLmNoYW5uZWxzLnJlYWN0aW9ucy5hbGwoY2hhbm5lbElkLCBtZXNzYWdlSWQpKTtcbiAgfSxcbiAgLyoqXG4gICAqIERlbGV0ZXMgYWxsIHJlYWN0aW9ucyBmb3IgYW4gZW1vamkgZnJvbSBhIG1lc3NhZ2UuXG4gICAqXG4gICAqIEBwYXJhbSBjaGFubmVsSWQgLSBUaGUgSUQgb2YgdGhlIGNoYW5uZWwgdGhlIG1lc3NhZ2UgdG8gZGVsZXRlIHRoZSByZWFjdGlvbnMgZnJvbSBpcyBpbi5cbiAgICogQHBhcmFtIG1lc3NhZ2VJZCAtIFRoZSBJRCBvZiB0aGUgbWVzc2FnZSB0byBkZWxldGUgdGhlIHJlYWN0aW9ucyBmcm9tLlxuICAgKiBAcGFyYW0gcmVhY3Rpb24gLSBUaGUgcmVhY3Rpb24gdG8gcmVtb3ZlIGZyb20gdGhlIG1lc3NhZ2UuXG4gICAqXG4gICAqIEByZW1hcmtzXG4gICAqIFJlcXVpcmVzIHRoZSBgUkVBRF9NRVNTQUdFX0hJU1RPUllgIHBlcm1pc3Npb24uXG4gICAqXG4gICAqIFJlcXVpcmVzIHRoZSBgTUFOQUdFX01FU1NBR0VTYCBwZXJtaXNzaW9uLlxuICAgKlxuICAgKiBGaXJlcyBhIF9NZXNzYWdlIFJlYWN0aW9uIFJlbW92ZSBFbW9qaV8gZ2F0ZXdheSBldmVudC5cbiAgICpcbiAgICogQHNlZSB7QGxpbmsgaHR0cHM6Ly9kb2NzLmRpc2NvcmQuY29tL2RldmVsb3BlcnMvcmVzb3VyY2VzL2NoYW5uZWwjZGVsZXRlLWFsbC1yZWFjdGlvbnMtZm9yLWVtb2ppfVxuICAgKi9cbiAgYXN5bmMgZGVsZXRlUmVhY3Rpb25zRW1vamkocmVzdDogUmVzdE1hbmFnZXIsIGNoYW5uZWxJZDogQmlnU3RyaW5nLCBtZXNzYWdlSWQ6IEJpZ1N0cmluZywgcmVhY3Rpb246IHN0cmluZyk6IFByb21pc2U8dm9pZD4ge1xuICAgIHJlYWN0aW9uID0gcHJvY2Vzc1JlYWN0aW9uU3RyaW5nKHJlYWN0aW9uKTtcblxuICAgIGF3YWl0IHJlc3QuZGVsZXRlKHJlc3Qucm91dGVzLmNoYW5uZWxzLnJlYWN0aW9ucy5lbW9qaShjaGFubmVsSWQsIG1lc3NhZ2VJZCwgcmVhY3Rpb24pKTtcbiAgfSxcbiAgLyoqXG4gICAqIERlbGV0ZXMgYSByb2xlIGZyb20gYSBndWlsZC5cbiAgICpcbiAgICogQHBhcmFtIGd1aWxkSWQgLSBUaGUgSUQgb2YgdGhlIGd1aWxkIHRvIGRlbGV0ZSB0aGUgcm9sZSBmcm9tLlxuICAgKiBAcGFyYW0gcm9sZUlkIC0gVGhlIElEIG9mIHRoZSByb2xlIHRvIGRlbGV0ZS5cbiAgICogQHBhcmFtIHtzdHJpbmd9IFtyZWFzb25dIC0gQW4gb3B0aW9uYWwgcmVhc29uIGZvciB0aGUgYWN0aW9uLCB0byBiZSBpbmNsdWRlZCBpbiB0aGUgYXVkaXQgbG9nLlxuICAgKlxuICAgKiBAcmVtYXJrc1xuICAgKiBSZXF1aXJlcyB0aGUgYE1BTkFHRV9ST0xFU2AgcGVybWlzc2lvbi5cbiAgICpcbiAgICogRmlyZXMgYSBfR3VpbGQgUm9sZSBEZWxldGVfIGdhdGV3YXkgZXZlbnQuXG4gICAqXG4gICAqIEBzZWUge0BsaW5rIGh0dHBzOi8vZG9jcy5kaXNjb3JkLmNvbS9kZXZlbG9wZXJzL3Jlc291cmNlcy9ndWlsZCNkZWxldGUtZ3VpbGQtcm9sZX1cbiAgICovXG4gIGFzeW5jIGRlbGV0ZVJvbGUocmVzdDogUmVzdE1hbmFnZXIsIGd1aWxkSWQ6IEJpZ1N0cmluZywgcm9sZUlkOiBCaWdTdHJpbmcsIHJlYXNvbj86IHN0cmluZyk6IFByb21pc2U8dm9pZD4ge1xuICAgIGF3YWl0IHJlc3QuZGVsZXRlKHJlc3Qucm91dGVzLmd1aWxkcy5yb2xlcy5vbmUoZ3VpbGRJZCwgcm9sZUlkKSwgeyByZWFzb24gfSk7XG4gIH0sXG4gIC8qKlxuICAgKiBEZWxldGVzIGEgc2NoZWR1bGVkIGV2ZW50IGZyb20gYSBndWlsZC5cbiAgICpcbiAgICogQHBhcmFtIGd1aWxkSWQgLSBUaGUgSUQgb2YgdGhlIGd1aWxkIHRvIGRlbGV0ZSB0aGUgc2NoZWR1bGVkIGV2ZW50IGZyb20uXG4gICAqIEBwYXJhbSBldmVudElkIC0gVGhlIElEIG9mIHRoZSBzY2hlZHVsZWQgZXZlbnQgdG8gZGVsZXRlLlxuICAgKlxuICAgKiBAcmVtYXJrc1xuICAgKiBSZXF1aXJlcyB0aGUgYE1BTkFHRV9FVkVOVFNgIHBlcm1pc3Npb24uXG4gICAqXG4gICAqIEZpcmVzIGEgX0d1aWxkIFNjaGVkdWxlZCBFdmVudCBEZWxldGVfIGdhdGV3YXkgZXZlbnQuXG4gICAqXG4gICAqIEBzZWUge0BsaW5rIGh0dHBzOi8vZG9jcy5kaXNjb3JkLmNvbS9kZXZlbG9wZXJzL3Jlc291cmNlcy9ndWlsZC1zY2hlZHVsZWQtZXZlbnQjZGVsZXRlLWd1aWxkLXNjaGVkdWxlZC1ldmVudH1cbiAgICovXG4gIGFzeW5jIGRlbGV0ZVNjaGVkdWxlZEV2ZW50KHJlc3Q6IFJlc3RNYW5hZ2VyLCBndWlsZElkOiBCaWdTdHJpbmcsIGV2ZW50SWQ6IEJpZ1N0cmluZyk6IFByb21pc2U8dm9pZD4ge1xuICAgIGF3YWl0IHJlc3QuZGVsZXRlKHJlc3Qucm91dGVzLmd1aWxkcy5ldmVudHMuZXZlbnQoZ3VpbGRJZCwgZXZlbnRJZCkpO1xuICB9LFxuICAvKipcbiAgICogRGVsZXRlcyB0aGUgc3RhZ2UgaW5zdGFuY2UgYXNzb2NpYXRlZCB3aXRoIGEgc3RhZ2UgY2hhbm5lbCwgaWYgb25lIGV4aXN0cy5cbiAgICpcbiAgICogQHBhcmFtIGNoYW5uZWxJZCAtIFRoZSBJRCBvZiB0aGUgc3RhZ2UgY2hhbm5lbCB0aGUgc3RhZ2UgaW5zdGFuY2UgaXMgYXNzb2NpYXRlZCB3aXRoLlxuICAgKiBAcGFyYW0ge3N0cmluZ30gW3JlYXNvbl0gLSBBbiBvcHRpb25hbCByZWFzb24gZm9yIHRoZSBhY3Rpb24sIHRvIGJlIGluY2x1ZGVkIGluIHRoZSBhdWRpdCBsb2cuXG4gICAqXG4gICAqIEByZW1hcmtzXG4gICAqIFJlcXVpcmVzIHRoZSB1c2VyIHRvIGJlIGEgbW9kZXJhdG9yIG9mIHRoZSBzdGFnZSBjaGFubmVsLlxuICAgKlxuICAgKiBGaXJlcyBhIF9TdGFnZSBJbnN0YW5jZSBEZWxldGVfIGdhdGV3YXkgZXZlbnQuXG4gICAqXG4gICAqIEBzZWUge0BsaW5rIGh0dHBzOi8vZG9jcy5kaXNjb3JkLmNvbS9kZXZlbG9wZXJzL3Jlc291cmNlcy9zdGFnZS1pbnN0YW5jZSNkZWxldGUtc3RhZ2UtaW5zdGFuY2V9XG4gICAqL1xuICBhc3luYyBkZWxldGVTdGFnZUluc3RhbmNlKHJlc3Q6IFJlc3RNYW5hZ2VyLCBjaGFubmVsSWQ6IEJpZ1N0cmluZywgcmVhc29uPzogc3RyaW5nKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgYXdhaXQgcmVzdC5kZWxldGUocmVzdC5yb3V0ZXMuY2hhbm5lbHMuc3RhZ2UoY2hhbm5lbElkKSwgeyByZWFzb24gfSk7XG4gIH0sXG4gIC8qKlxuICAgKiBEZWxldGVzIGEgdXNlcidzIHJlYWN0aW9uIGZyb20gYSBtZXNzYWdlLlxuICAgKlxuICAgKiBAcGFyYW0gY2hhbm5lbElkIC0gVGhlIElEIG9mIHRoZSBjaGFubmVsIHRoZSBtZXNzYWdlIHRvIGRlbGV0ZSB0aGUgcmVhY3Rpb24gZnJvbSBpcyBpbi5cbiAgICogQHBhcmFtIG1lc3NhZ2VJZCAtIFRoZSBJRCBvZiB0aGUgbWVzc2FnZSB0byBkZWxldGUgdGhlIHJlYWN0aW9uIGZyb20uXG4gICAqIEBwYXJhbSB1c2VySWQgLSBUaGUgSUQgb2YgdGhlIHVzZXIgd2hvc2UgcmVhY3Rpb24gdG8gZGVsZXRlLlxuICAgKiBAcGFyYW0gcmVhY3Rpb24gLSBUaGUgcmVhY3Rpb24gdG8gZGVsZXRlIGZyb20gdGhlIG1lc3NhZ2UuXG4gICAqXG4gICAqIEByZW1hcmtzXG4gICAqIFJlcXVpcmVzIHRoZSBgUkVBRF9NRVNTQUdFX0hJU1RPUllgIHBlcm1pc3Npb24uXG4gICAqXG4gICAqIFJlcXVpcmVzIHRoZSBgTUFOQUdFX01FU1NBR0VTYCBwZXJtaXNzaW9uLlxuICAgKlxuICAgKiBGaXJlcyBhIF9NZXNzYWdlIFJlYWN0aW9uIFJlbW92ZV8gZ2F0ZXdheSBldmVudC5cbiAgICpcbiAgICogQHNlZSB7QGxpbmsgaHR0cHM6Ly9kb2NzLmRpc2NvcmQuY29tL2RldmVsb3BlcnMvcmVzb3VyY2VzL2NoYW5uZWwjZGVsZXRlLXVzZXItcmVhY3Rpb259XG4gICAqL1xuICBhc3luYyBkZWxldGVVc2VyUmVhY3Rpb24ocmVzdDogUmVzdE1hbmFnZXIsIGNoYW5uZWxJZDogQmlnU3RyaW5nLCBtZXNzYWdlSWQ6IEJpZ1N0cmluZywgdXNlcklkOiBCaWdTdHJpbmcsIHJlYWN0aW9uOiBzdHJpbmcpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICByZWFjdGlvbiA9IHByb2Nlc3NSZWFjdGlvblN0cmluZyhyZWFjdGlvbik7XG5cbiAgICBhd2FpdCByZXN0LmRlbGV0ZShyZXN0LnJvdXRlcy5jaGFubmVscy5yZWFjdGlvbnMudXNlcihjaGFubmVsSWQsIG1lc3NhZ2VJZCwgcmVhY3Rpb24sIHVzZXJJZCkpO1xuICB9LFxuICAvKipcbiAgICogRGVsZXRlcyBhIHdlYmhvb2suXG4gICAqXG4gICAqIEBwYXJhbSB3ZWJob29rSWQgLSBUaGUgSUQgb2YgdGhlIHdlYmhvb2sgdG8gZGVsZXRlLlxuICAgKlxuICAgKiBAcmVtYXJrc1xuICAgKiBSZXF1aXJlcyB0aGUgYE1BTkFHRV9XRUJIT09LU2AgcGVybWlzc2lvbi5cbiAgICpcbiAgICogRmlyZXMgYSBfV2ViaG9va3MgVXBkYXRlXyBnYXRld2F5IGV2ZW50LlxuICAgKlxuICAgKiBAc2VlIHtAbGluayBodHRwczovL2RvY3MuZGlzY29yZC5jb20vZGV2ZWxvcGVycy9yZXNvdXJjZXMvd2ViaG9vayNkZWxldGUtd2ViaG9va31cbiAgICovXG4gIGFzeW5jIGRlbGV0ZVdlYmhvb2socmVzdDogUmVzdE1hbmFnZXIsIHdlYmhvb2tJZDogQmlnU3RyaW5nLCByZWFzb24/OiBzdHJpbmcpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBhd2FpdCByZXN0LmRlbGV0ZShyZXN0LnJvdXRlcy53ZWJob29rcy5pZCh3ZWJob29rSWQpLCB7IHJlYXNvbiB9KTtcbiAgfSxcbiAgLyoqXG4gICAqIERlbGV0ZXMgYSB3ZWJob29rIG1lc3NhZ2UuXG4gICAqXG4gICAqIEBwYXJhbSB3ZWJob29rSWQgLSBUaGUgSUQgb2YgdGhlIHdlYmhvb2sgdG8gZGVsZXRlIHRoZSBtZXNzYWdlIGJlbG9uZ2luZyB0by5cbiAgICogQHBhcmFtIHRva2VuIC0gVGhlIHdlYmhvb2sgdG9rZW4sIHVzZWQgdG8gbWFuYWdlIHRoZSB3ZWJob29rLlxuICAgKiBAcGFyYW0gbWVzc2FnZUlkIC0gVGhlIElEIG9mIHRoZSBtZXNzYWdlIHRvIGRlbGV0ZS5cbiAgICogQHBhcmFtIG9wdGlvbnMgLSBUaGUgcGFyYW1ldGVycyBmb3IgdGhlIGRlbGV0aW9uIG9mIHRoZSBtZXNzYWdlLlxuICAgKlxuICAgKiBAcmVtYXJrc1xuICAgKiBGaXJlcyBhIF9NZXNzYWdlIERlbGV0ZV8gZ2F0ZXdheSBldmVudC5cbiAgICpcbiAgICogQHNlZSB7QGxpbmsgaHR0cHM6Ly9kb2NzLmRpc2NvcmQuY29tL2RldmVsb3BlcnMvcmVzb3VyY2VzL3dlYmhvb2sjZGVsZXRlLXdlYmhvb2t9XG4gICAqL1xuICBhc3luYyBkZWxldGVXZWJob29rTWVzc2FnZShcbiAgICByZXN0OiBSZXN0TWFuYWdlcixcbiAgICB3ZWJob29rSWQ6IEJpZ1N0cmluZyxcbiAgICB0b2tlbjogc3RyaW5nLFxuICAgIG1lc3NhZ2VJZDogQmlnU3RyaW5nLFxuICAgIG9wdGlvbnM/OiBEZWxldGVXZWJob29rTWVzc2FnZU9wdGlvbnMsXG4gICk6IFByb21pc2U8dm9pZD4ge1xuICAgIGF3YWl0IHJlc3QuZGVsZXRlKHJlc3Qucm91dGVzLndlYmhvb2tzLm1lc3NhZ2Uod2ViaG9va0lkLCB0b2tlbiwgbWVzc2FnZUlkLCBvcHRpb25zKSwgeyB1bmF1dGhvcml6ZWQ6IHRydWUgfSk7XG4gIH0sXG4gIC8qKlxuICAgKiBEZWxldGVzIGEgd2ViaG9vayBtZXNzYWdlIHVzaW5nIHRoZSB3ZWJob29rIHRva2VuLCB0aGVyZWJ5IGJ5cGFzc2luZyB0aGUgbmVlZCBmb3IgYXV0aGVudGljYXRpb24gKyBwZXJtaXNzaW9ucy5cbiAgICpcbiAgICogQHBhcmFtIHdlYmhvb2tJZCAtIFRoZSBJRCBvZiB0aGUgd2ViaG9vayB0byBkZWxldGUgdGhlIG1lc3NhZ2UgYmVsb25naW5nIHRvLlxuICAgKiBAcGFyYW0gdG9rZW4gLSBUaGUgd2ViaG9vayB0b2tlbiwgdXNlZCB0byBkZWxldGUgdGhlIHdlYmhvb2suXG4gICAqXG4gICAqIEByZW1hcmtzXG4gICAqIEZpcmVzIGEgX01lc3NhZ2UgRGVsZXRlXyBnYXRld2F5IGV2ZW50LlxuICAgKlxuICAgKiBAc2VlIHtAbGluayBodHRwczovL2RvY3MuZGlzY29yZC5jb20vZGV2ZWxvcGVycy9yZXNvdXJjZXMvd2ViaG9vayNkZWxldGUtd2ViaG9vay13aXRoLXRva2VufVxuICAgKi9cbiAgYXN5bmMgZGVsZXRlV2ViaG9va1dpdGhUb2tlbihyZXN0OiBSZXN0TWFuYWdlciwgd2ViaG9va0lkOiBCaWdTdHJpbmcsIHRva2VuOiBzdHJpbmcpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBhd2FpdCByZXN0LmRlbGV0ZShyZXN0LnJvdXRlcy53ZWJob29rcy53ZWJob29rKHdlYmhvb2tJZCwgdG9rZW4pLCB7XG4gICAgICB1bmF1dGhvcml6ZWQ6IHRydWUsXG4gICAgfSk7XG4gIH0sXG4gIC8qKlxuICAgKiBFZGl0cyB0aGUgcGVybWlzc2lvbnMgZm9yIGEgZ3VpbGQgYXBwbGljYXRpb24gY29tbWFuZC5cbiAgICpcbiAgICogQHBhcmFtIGd1aWxkSWQgLSBUaGUgSUQgb2YgdGhlIGd1aWxkIHRoZSBjb21tYW5kIGlzIHJlZ2lzdGVyZWQgaW4uXG4gICAqIEBwYXJhbSBjb21tYW5kSWQgLSBUaGUgSUQgb2YgdGhlIGNvbW1hbmQgdG8gZWRpdCB0aGUgcGVybWlzc2lvbnMgb2YuXG4gICAqIEBwYXJhbSBiZWFyZXJUb2tlbiAtIFRoZSBiZWFyZXIgdG9rZW4gdG8gdXNlIHRvIG1ha2UgdGhlIHJlcXVlc3QuXG4gICAqIEBwYXJhbSBvcHRpb25zIC0gVGhlIHBhcmFtZXRlcnMgZm9yIHRoZSBlZGl0IG9mIHRoZSBjb21tYW5kIHBlcm1pc3Npb25zLlxuICAgKiBAcmV0dXJucyBBbiBpbnN0YW5jZSBvZiB0aGUgZWRpdGVkIHtAbGluayBEaXNjb3JkR3VpbGRBcHBsaWNhdGlvbkNvbW1hbmRQZXJtaXNzaW9uc30uXG4gICAqXG4gICAqIEByZW1hcmtzXG4gICAqIFRoZSBiZWFyZXIgdG9rZW4gcmVxdWlyZXMgdGhlIGBhcHBsaWNhdGlvbnMuY29tbWFuZHMucGVybWlzc2lvbnMudXBkYXRlYCBzY29wZSB0byBiZSBlbmFibGVkLCBhbmQgdG8gaGF2ZSBhY2Nlc3MgdG8gdGhlIGd1aWxkIHdob3NlIElEIGhhcyBiZWVuIHByb3ZpZGVkIGluIHRoZSBwYXJhbWV0ZXJzLlxuICAgKlxuICAgKiBAc2VlIHtAbGluayBodHRwczovL2RvY3MuZGlzY29yZC5jb20vZGV2ZWxvcGVycy9pbnRlcmFjdGlvbnMvYXBwbGljYXRpb24tY29tbWFuZHMjZWRpdC1hcHBsaWNhdGlvbi1jb21tYW5kLXBlcm1pc3Npb25zfVxuICAgKi9cbiAgYXN5bmMgZWRpdEFwcGxpY2F0aW9uQ29tbWFuZFBlcm1pc3Npb25zKFxuICAgIHJlc3Q6IFJlc3RNYW5hZ2VyLFxuICAgIGd1aWxkSWQ6IEJpZ1N0cmluZyxcbiAgICBjb21tYW5kSWQ6IEJpZ1N0cmluZyxcbiAgICBiZWFyZXJUb2tlbjogc3RyaW5nLFxuICAgIG9wdGlvbnM6IENhbWVsaXplPERpc2NvcmRBcHBsaWNhdGlvbkNvbW1hbmRQZXJtaXNzaW9uc1tdPixcbiAgKTogUHJvbWlzZTxEaXNjb3JkR3VpbGRBcHBsaWNhdGlvbkNvbW1hbmRQZXJtaXNzaW9ucz4ge1xuICAgIHJldHVybiBhd2FpdCByZXN0LnB1dDxEaXNjb3JkR3VpbGRBcHBsaWNhdGlvbkNvbW1hbmRQZXJtaXNzaW9ucz4oXG4gICAgICByZXN0LnJvdXRlcy5pbnRlcmFjdGlvbnMuY29tbWFuZHMucGVybWlzc2lvbihyZXN0LmFwcGxpY2F0aW9uSWQsIGd1aWxkSWQsIGNvbW1hbmRJZCksXG4gICAgICB7XG4gICAgICAgIGJvZHk6IHtcbiAgICAgICAgICBwZXJtaXNzaW9uczogb3B0aW9ucyxcbiAgICAgICAgfSxcbiAgICAgICAgaGVhZGVyczogeyBhdXRob3JpemF0aW9uOiBgQmVhcmVyICR7YmVhcmVyVG9rZW59YCB9LFxuICAgICAgfSxcbiAgICApO1xuICB9LFxuICAvKipcbiAgICogRWRpdHMgYW4gYXV0b21vZCBydWxlLlxuICAgKlxuICAgKiBAcGFyYW0gZ3VpbGRJZCAtIFRoZSBJRCBvZiB0aGUgZ3VpbGQgdG8gZWRpdCB0aGUgcnVsZSBpbi5cbiAgICogQHBhcmFtIHJ1bGVJZCAtIFRoZSBJRCBvZiB0aGUgcnVsZSB0byBlZGl0LlxuICAgKiBAcGFyYW0gb3B0aW9ucyAtIFRoZSBwYXJhbWV0ZXJzIGZvciB0aGUgZWRpdCBvZiB0aGUgcnVsZS5cbiAgICogQHBhcmFtIHtzdHJpbmd9IFtyZWFzb25dIC0gQW4gb3B0aW9uYWwgcmVhc29uIGZvciB0aGUgYWN0aW9uLCB0byBiZSBpbmNsdWRlZCBpbiB0aGUgYXVkaXQgbG9nLlxuICAgKiBAcmV0dXJucyBBbiBpbnN0YW5jZSBvZiB0aGUgZWRpdGVkIHtAbGluayBEaXNjb3JkQXV0b01vZGVyYXRpb25SdWxlfS5cbiAgICpcbiAgICogQHJlbWFya3NcbiAgICogUmVxdWlyZXMgdGhlIGBNQU5BR0VfR1VJTERgIHBlcm1pc3Npb24uXG4gICAqXG4gICAqIEZpcmVzIGFuIF9BdXRvIE1vZGVyYXRpb24gUnVsZSBVcGRhdGVfIGdhdGV3YXkgZXZlbnQuXG4gICAqXG4gICAqIEBzZWUge0BsaW5rIGh0dHBzOi8vZG9jcy5kaXNjb3JkLmNvbS9kZXZlbG9wZXJzL3Jlc291cmNlcy9hdXRvLW1vZGVyYXRpb24jbW9kaWZ5LWF1dG8tbW9kZXJhdGlvbi1ydWxlfVxuICAgKi9cbiAgYXN5bmMgZWRpdEF1dG9tb2RSdWxlKFxuICAgIHJlc3Q6IFJlc3RNYW5hZ2VyLFxuICAgIGd1aWxkSWQ6IEJpZ1N0cmluZyxcbiAgICBydWxlSWQ6IEJpZ1N0cmluZyxcbiAgICBvcHRpb25zOiBQYXJ0aWFsPEVkaXRBdXRvTW9kZXJhdGlvblJ1bGVPcHRpb25zPixcbiAgICByZWFzb24/OiBzdHJpbmcsXG4gICk6IFByb21pc2U8RGlzY29yZEF1dG9Nb2RlcmF0aW9uUnVsZT4ge1xuICAgIHJldHVybiBhd2FpdCByZXN0LnBhdGNoPERpc2NvcmRBdXRvTW9kZXJhdGlvblJ1bGU+KHJlc3Qucm91dGVzLmd1aWxkcy5hdXRvbW9kLnJ1bGUoZ3VpbGRJZCwgcnVsZUlkKSwgeyBib2R5OiBvcHRpb25zLCByZWFzb24gfSk7XG4gIH0sXG4gIC8qKlxuICAgKiBNb2RpZmllcyB0aGUgYm90J3MgdXNlcm5hbWUsIGF2YXRhciBvciBiYW5uZXIuXG4gICAqXG4gICAqIEBwYXJhbSBvcHRpb25zIC0gVGhlIHBhcmFtZXRlcnMgZm9yIHRoZSBlZGl0IG9mIHRoZSBib3QncyBwcm9maWxlLlxuICAgKiBAcmV0dXJucyBBbiBpbnN0YW5jZSBvZiB0aGUgZWRpdGVkIHtAbGluayBEaXNjb3JkVXNlcn0uXG4gICAqXG4gICAqIEByZW1hcmtzXG4gICAqIEVkaXRpbmcgdGhlIGB1c2VybmFtZWAgbWF5IGNhdXNlIHRoZSBib3QncyBkaXNjcmltaW5hdG9yIHRvIGJlIHJhbmRvbWl6ZWQuXG4gICAqXG4gICAqIGBhdmF0YXJgIGFuZCBgYmFubmVyYCBtdXN0IHRvIGJlIGEgRGF0YSBVUkkgc2NoZW1lLiB7QGxpbmsgdXJsVG9CYXNlNjR9IGZyb20gYEBkaXNjb3JkZW5vL3V0aWxzYCBjYW4gYmUgdXNlZCB0byBjb252ZXJ0IGEgVVJMIHRvIGEgRGF0YSBVUkkgc2NoZW1lLlxuICAgKlxuICAgKiBAc2VlIHtAbGluayBodHRwczovL2RvY3MuZGlzY29yZC5jb20vZGV2ZWxvcGVycy9yZXNvdXJjZXMvdXNlciNtb2RpZnktY3VycmVudC11c2VyfVxuICAgKi9cbiAgYXN5bmMgZWRpdEJvdFByb2ZpbGUoXG4gICAgcmVzdDogUmVzdE1hbmFnZXIsXG4gICAgb3B0aW9uczogeyB1c2VybmFtZT86IHN0cmluZzsgYm90QXZhdGFyVVJMPzogc3RyaW5nIHwgbnVsbDsgYm90QmFubmVyVVJMPzogc3RyaW5nIHwgbnVsbCB9LFxuICApOiBQcm9taXNlPERpc2NvcmRVc2VyPiB7XG4gICAgcmV0dXJuIGF3YWl0IHJlc3QucGF0Y2g8RGlzY29yZFVzZXI+KHJlc3Qucm91dGVzLmN1cnJlbnRVc2VyKCksIHtcbiAgICAgIGJvZHk6IG9wdGlvbnMsXG4gICAgfSk7XG4gIH0sXG4gIC8qKlxuICAgKiBFZGl0cyBhIGNoYW5uZWwncyBzZXR0aW5ncy5cbiAgICpcbiAgICogQHBhcmFtIGNoYW5uZWxJZCAtIFRoZSBJRCBvZiB0aGUgY2hhbm5lbCB0byBlZGl0LlxuICAgKiBAcGFyYW0gb3B0aW9ucyAtIFRoZSBwYXJhbWV0ZXJzIGZvciB0aGUgZWRpdCBvZiB0aGUgY2hhbm5lbC5cbiAgICogQHBhcmFtIHtzdHJpbmd9IFtyZWFzb25dIC0gQW4gb3B0aW9uYWwgcmVhc29uIGZvciB0aGUgYWN0aW9uLCB0byBiZSBpbmNsdWRlZCBpbiB0aGUgYXVkaXQgbG9nLlxuICAgKiBAcmV0dXJucyBBbiBpbnN0YW5jZSBvZiB0aGUgZWRpdGVkIHtAbGluayBEaXNjb3JkQ2hhbm5lbH0uXG4gICAqXG4gICAqIEByZW1hcmtzXG4gICAqIElmIGVkaXRpbmcgYSBjaGFubmVsIG9mIHR5cGUge0BsaW5rIENoYW5uZWxUeXBlc30uR3JvdXBEbTpcbiAgICogLSBGaXJlcyBhIF9DaGFubmVsIFVwZGF0ZV8gZ2F0ZXdheSBldmVudC5cbiAgICpcbiAgICogSWYgZWRpdGluZyBhIHRocmVhZCBjaGFubmVsOlxuICAgKiAtIFJlcXVpcmVzIHRoZSBgTUFOQUdFX1RIUkVBRFNgIHBlcm1pc3Npb24gX191bmxlc3NfXyBpZiBzZXR0aW5nIHRoZSBgYXJjaGl2ZWRgIHByb3BlcnR5IHRvIGBmYWxzZWAgd2hlbiB0aGUgYGxvY2tlZGAgcHJvcGVydHkgaXMgYWxzbyBgZmFsc2VgLCBpbiB3aGljaCBjYXNlIG9ubHkgdGhlIGBTRU5EX01FU1NBR0VTYCBwZXJtaXNzaW9uIGlzIHJlcXVpcmVkLlxuICAgKlxuICAgKiAtIEZpcmVzIGEgX1RocmVhZCBVcGRhdGVfIGdhdGV3YXkgZXZlbnQuXG4gICAqXG4gICAqIElmIGVkaXRpbmcgYSBndWlsZCBjaGFubmVsOlxuICAgKiAtIFJlcXVpcmVzIHRoZSBgTUFOQUdFX0NIQU5ORUxTYCBwZXJtaXNzaW9uLlxuICAgKlxuICAgKiAtIElmIG1vZGlmeWluZyBwZXJtaXNzaW9uIG92ZXJyaWRlczpcbiAgICogICAtIFJlcXVpcmVzIHRoZSBgTUFOQUdFX1JPTEVTYCBwZXJtaXNzaW9uLlxuICAgKlxuICAgKiAgIC0gT25seSBwZXJtaXNzaW9ucyB0aGUgYm90IHVzZXIgaGFzIGluIHRoZSBndWlsZCBvciBwYXJlbnQgY2hhbm5lbCBjYW4gYmUgYWxsb3dlZC9kZW5pZWQgX191bmxlc3NfXyB0aGUgYm90IHVzZXIgaGFzIGEgYE1BTkFHRV9ST0xFU2AgcGVybWlzc2lvbiBvdmVycmlkZSBpbiB0aGUgY2hhbm5lbC5cbiAgICpcbiAgICogLSBJZiBtb2RpZnlpbmcgYSBjaGFubmVsIG9mIHR5cGUge0BsaW5rIENoYW5uZWxUeXBlc30uR3VpbGRDYXRlZ29yeTpcbiAgICogICAgIC0gRmlyZXMgYSBfQ2hhbm5lbCBVcGRhdGVfIGdhdGV3YXkgZXZlbnQgZm9yIGVhY2ggY2hpbGQgY2hhbm5lbCBpbXBhY3RlZCBpbiB0aGlzIGNoYW5nZS5cbiAgICogLSBPdGhlcndpc2U6XG4gICAqICAgICAtIEZpcmVzIGEgX0NoYW5uZWwgVXBkYXRlXyBnYXRld2F5IGV2ZW50LlxuICAgKi9cbiAgYXN5bmMgZWRpdENoYW5uZWwocmVzdDogUmVzdE1hbmFnZXIsIGNoYW5uZWxJZDogQmlnU3RyaW5nLCBvcHRpb25zOiBNb2RpZnlDaGFubmVsLCByZWFzb24/OiBzdHJpbmcpOiBQcm9taXNlPERpc2NvcmRDaGFubmVsPiB7XG4gICAgcmV0dXJuIGF3YWl0IHJlc3QucGF0Y2g8RGlzY29yZENoYW5uZWw+KHJlc3Qucm91dGVzLmNoYW5uZWxzLmNoYW5uZWwoY2hhbm5lbElkKSwgeyBib2R5OiBvcHRpb25zLCByZWFzb24gfSk7XG4gIH0sXG4gIC8qKlxuICAgKiBFZGl0cyB0aGUgcGVybWlzc2lvbiBvdmVycmlkZXMgZm9yIGEgdXNlciBvciByb2xlIGluIGEgY2hhbm5lbC5cbiAgICpcbiAgICogQHBhcmFtIGNoYW5uZWxJZCAtIFRoZSBJRCBvZiB0aGUgY2hhbm5lbCB0byBlZGl0IHRoZSBwZXJtaXNzaW9uIG92ZXJyaWRlcyBvZi5cbiAgICogQHBhcmFtIG9wdGlvbnMgLSBUaGUgcGVybWlzc2lvbiBvdmVycmlkZS5cbiAgICogQHBhcmFtIHtzdHJpbmd9IFtyZWFzb25dIC0gQW4gb3B0aW9uYWwgcmVhc29uIGZvciB0aGUgYWN0aW9uLCB0byBiZSBpbmNsdWRlZCBpbiB0aGUgYXVkaXQgbG9nLlxuICAgKlxuICAgKiBAcmVtYXJrc1xuICAgKiBSZXF1aXJlcyB0aGUgYE1BTkFHRV9ST0xFU2AgcGVybWlzc2lvbi5cbiAgICpcbiAgICogT25seSBwZXJtaXNzaW9ucyB0aGUgYm90IHVzZXIgaGFzIGluIHRoZSBndWlsZCBvciBwYXJlbnQgY2hhbm5lbCBjYW4gYmUgYWxsb3dlZC9kZW5pZWQgX191bmxlc3NfXyB0aGUgYm90IHVzZXIgaGFzIGEgYE1BTkFHRV9ST0xFU2AgcGVybWlzc2lvbiBvdmVycmlkZSBpbiB0aGUgY2hhbm5lbC5cbiAgICpcbiAgICogRmlyZXMgYSBfQ2hhbm5lbCBVcGRhdGVfIGdhdGV3YXkgZXZlbnQuXG4gICAqXG4gICAqIEBzZWUge0BsaW5rIGh0dHBzOi8vZG9jcy5kaXNjb3JkLmNvbS9kZXZlbG9wZXJzL3Jlc291cmNlcy9jaGFubmVsI2VkaXQtY2hhbm5lbC1wZXJtaXNzaW9uc31cbiAgICovXG4gIGFzeW5jIGVkaXRDaGFubmVsUGVybWlzc2lvbk92ZXJyaWRlcyhcbiAgICByZXN0OiBSZXN0TWFuYWdlcixcbiAgICBjaGFubmVsSWQ6IEJpZ1N0cmluZyxcbiAgICBvcHRpb25zOiBFZGl0Q2hhbm5lbFBlcm1pc3Npb25PdmVycmlkZXNPcHRpb25zLFxuICAgIHJlYXNvbj86IHN0cmluZyxcbiAgKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgYXdhaXQgcmVzdC5wdXQocmVzdC5yb3V0ZXMuY2hhbm5lbHMub3ZlcndyaXRlKGNoYW5uZWxJZCwgb3B0aW9ucy5pZCksIHsgYm9keTogb3B0aW9ucywgcmVhc29uIH0pO1xuICB9LFxuICAvKipcbiAgICogRWRpdHMgdGhlIHBvc2l0aW9ucyBvZiBhIHNldCBvZiBjaGFubmVscyBpbiBhIGd1aWxkLlxuICAgKlxuICAgKiBAcGFyYW0gZ3VpbGRJZCAtIFRoZSBJRCBvZiB0aGUgZ3VpbGQgaW4gd2hpY2ggdG8gZWRpdCB0aGUgcG9zaXRpb25zIG9mIHRoZSBjaGFubmVscy5cbiAgICogQHBhcmFtIGNoYW5uZWxQb3NpdGlvbnMgLSBBIHNldCBvZiBvYmplY3RzIGRlZmluaW5nIHRoZSB1cGRhdGVkIHBvc2l0aW9ucyBvZiB0aGUgY2hhbm5lbHMuXG4gICAqXG4gICAqIEByZW1hcmtzXG4gICAqIFJlcXVpcmVzIHRoZSBgTUFOQUdFX0NIQU5ORUxTYCBwZXJtaXNzaW9uLlxuICAgKlxuICAgKiBGaXJlcyBhIF9DaGFubmVsIFVwZGF0ZV8gZ2F0ZXdheSBldmVudCBmb3IgZXZlcnkgY2hhbm5lbCBpbXBhY3RlZCBpbiB0aGlzIGNoYW5nZS5cbiAgICpcbiAgICogQXQgbW9zdCBvbmUgZW50cnkgcGVyIHJlcXVlc3QgbWF5IGNoYW5nZSBgcGFyZW50X2lkYC4gQSByZXF1ZXN0IHRoYXQgY2hhbmdlcyBgcGFyZW50X2lkYCBmb3IgbW9yZSB0aGFuIG9uZSBjaGFubmVsIGZhaWxzIHdpdGggYSA0MDAgcmVzcG9uc2UgYW5kIGVycm9yIGNvZGUgNDAwMDkuXG4gICAqXG4gICAqIFBlcm1pc3Npb25zIGFyZSBjaGVja2VkIHBlciBlbnRyeSwgYmFzZWQgb24gd2hhdCB0aGUgZW50cnkgY2hhbmdlczpcbiAgICogLSBBbiBlbnRyeSB0aGF0IG9ubHkgY2hhbmdlcyBgcG9zaXRpb25gIHJlcXVpcmVzIHRoZSBgTUFOQUdFX0NIQU5ORUxTYCBwZXJtaXNzaW9uIGF0IHRoZSBndWlsZCBsZXZlbCAob3Igb24gdGhlIGNoYW5uZWwncyBjdXJyZW50IHBhcmVudCBjYXRlZ29yeSkuIEl0IGRvZXMgKipub3QqKiByZXF1aXJlIGFjY2VzcyB0byB0aGUgaW5kaXZpZHVhbCBjaGFubmVsLCBzbyBhIGZ1bGwgcmVvcmRlcmluZyBtYXkgaW5jbHVkZSBjaGFubmVscyB0aGUgY3VycmVudCB1c2VyIGNhbm5vdCB2aWV3LlxuICAgKiAtIEFuIGVudHJ5IHRoYXQgY2hhbmdlcyBgcGFyZW50X2lkYCByZXF1aXJlcyB0aGUgYE1BTkFHRV9DSEFOTkVMU2AgcGVybWlzc2lvbiBvbiB0aGF0IGNoYW5uZWwgYW5kIG9uIHRoZSBkZXN0aW5hdGlvbiAodGhlIG5ldyBwYXJlbnQgY2F0ZWdvcnksIG9yIHRoZSBndWlsZCB3aGVuIG1vdmluZyB0aGUgY2hhbm5lbCBvdXQgb2YgYSBjYXRlZ29yeSksIGFuZCB0aGUgY3VycmVudCB1c2VyIG11c3QgYmUgYWJsZSB0byB2aWV3IHRoZSBjaGFubmVsLiBPdGhlcndpc2UgdGhlIHJlcXVlc3QgZmFpbHMgd2l0aCBhIGA0MDNgIHJlc3BvbnNlIGFuZCBlcnJvciBjb2RlIDUwMDAxLiBTZXR0aW5nIGBsb2NrX3Blcm1pc3Npb25zYCBhZGRpdGlvbmFsbHkgcmVxdWlyZXMgYE1BTkFHRV9ST0xFU2AuXG4gICAqXG4gICAqIEBzZWUge0BsaW5rIGh0dHBzOi8vZG9jcy5kaXNjb3JkLmNvbS9kZXZlbG9wZXJzL3Jlc291cmNlcy9ndWlsZCNtb2RpZnktZ3VpbGQtY2hhbm5lbC1wb3NpdGlvbnN9XG4gICAqL1xuICBhc3luYyBlZGl0Q2hhbm5lbFBvc2l0aW9ucyhyZXN0OiBSZXN0TWFuYWdlciwgZ3VpbGRJZDogQmlnU3RyaW5nLCBjaGFubmVsUG9zaXRpb25zOiBNb2RpZnlHdWlsZENoYW5uZWxQb3NpdGlvbnNbXSk6IFByb21pc2U8dm9pZD4ge1xuICAgIGF3YWl0IHJlc3QucGF0Y2gocmVzdC5yb3V0ZXMuZ3VpbGRzLmNoYW5uZWxzKGd1aWxkSWQpLCB7IGJvZHk6IGNoYW5uZWxQb3NpdGlvbnMgfSk7XG4gIH0sXG4gIC8qKlxuICAgKiBFZGl0cyBhbiBlbW9qaS5cbiAgICpcbiAgICogQHBhcmFtIGd1aWxkSWQgLSBUaGUgSUQgb2YgdGhlIGd1aWxkIGluIHdoaWNoIHRvIGVkaXQgdGhlIGVtb2ppLlxuICAgKiBAcGFyYW0gaWQgLSBUaGUgSUQgb2YgdGhlIGVtb2ppIHRvIGVkaXQuXG4gICAqIEBwYXJhbSBvcHRpb25zIC0gVGhlIHBhcmFtZXRlcnMgZm9yIHRoZSBlZGl0IG9mIHRoZSBlbW9qaS5cbiAgICogQHBhcmFtIHtzdHJpbmd9IFtyZWFzb25dIC0gQW4gb3B0aW9uYWwgcmVhc29uIGZvciB0aGUgYWN0aW9uLCB0byBiZSBpbmNsdWRlZCBpbiB0aGUgYXVkaXQgbG9nLlxuICAgKiBAcmV0dXJucyBBbiBpbnN0YW5jZSBvZiB0aGUgdXBkYXRlZCB7QGxpbmsgRGlzY29yZEVtb2ppfS5cbiAgICpcbiAgICogQHJlbWFya3NcbiAgICogRm9yIGVtb2ppcyBjcmVhdGVkIGJ5IHRoZSBjdXJyZW50IHVzZXIsIHJlcXVpcmVzIGVpdGhlciB0aGUgYENSRUFURV9HVUlMRF9FWFBSRVNTSU9OU2Agb3IgYE1BTkFHRV9HVUlMRF9FWFBSRVNTSU9OU2AgcGVybWlzc2lvbi5cbiAgICogRm9yIG90aGVyIGVtb2ppcywgcmVxdWlyZXMgdGhlIGBNQU5BR0VfR1VJTERfRVhQUkVTU0lPTlNgIHBlcm1pc3Npb24uXG4gICAqXG4gICAqIEZpcmVzIGEgYEd1aWxkIEVtb2ppcyBVcGRhdGVgIGdhdGV3YXkgZXZlbnQuXG4gICAqXG4gICAqIEBzZWUge0BsaW5rIGh0dHBzOi8vZG9jcy5kaXNjb3JkLmNvbS9kZXZlbG9wZXJzL3Jlc291cmNlcy9lbW9qaSNtb2RpZnktZ3VpbGQtZW1vaml9XG4gICAqL1xuICBhc3luYyBlZGl0RW1vamkocmVzdDogUmVzdE1hbmFnZXIsIGd1aWxkSWQ6IEJpZ1N0cmluZywgaWQ6IEJpZ1N0cmluZywgb3B0aW9uczogTW9kaWZ5R3VpbGRFbW9qaSwgcmVhc29uPzogc3RyaW5nKTogUHJvbWlzZTxEaXNjb3JkRW1vamk+IHtcbiAgICByZXR1cm4gYXdhaXQgcmVzdC5wYXRjaDxEaXNjb3JkRW1vamk+KHJlc3Qucm91dGVzLmd1aWxkcy5lbW9qaShndWlsZElkLCBpZCksIHsgYm9keTogb3B0aW9ucywgcmVhc29uIH0pO1xuICB9LFxuICAvKipcbiAgICogRWRpdHMgYW4gYXBwbGljYXRpb24gZW1vamkuXG4gICAqXG4gICAqIEBwYXJhbSBpZCAtIFRoZSBJRCBvZiB0aGUgZW1vamkgdG8gZWRpdC5cbiAgICogQHBhcmFtIG9wdGlvbnMgLSBUaGUgcGFyYW1ldGVycyBmb3IgdGhlIGVkaXQgb2YgdGhlIGVtb2ppLlxuICAgKiBAcmV0dXJucyBBbiBpbnN0YW5jZSBvZiB0aGUgdXBkYXRlZCB7QGxpbmsgRGlzY29yZEVtb2ppfS5cbiAgICpcbiAgICogQHNlZSB7QGxpbmsgaHR0cHM6Ly9kb2NzLmRpc2NvcmQuY29tL2RldmVsb3BlcnMvcmVzb3VyY2VzL2Vtb2ppI21vZGlmeS1hcHBsaWNhdGlvbi1lbW9qaX1cbiAgICovXG4gIGFzeW5jIGVkaXRBcHBsaWNhdGlvbkVtb2ppKHJlc3Q6IFJlc3RNYW5hZ2VyLCBpZDogQmlnU3RyaW5nLCBvcHRpb25zOiBNb2RpZnlBcHBsaWNhdGlvbkVtb2ppKTogUHJvbWlzZTxEaXNjb3JkRW1vamk+IHtcbiAgICByZXR1cm4gYXdhaXQgcmVzdC5wYXRjaDxEaXNjb3JkRW1vamk+KHJlc3Qucm91dGVzLmFwcGxpY2F0aW9uRW1vamkocmVzdC5hcHBsaWNhdGlvbklkLCBpZCksIHsgYm9keTogb3B0aW9ucyB9KTtcbiAgfSxcbiAgLyoqXG4gICAqIEVkaXRzIGEgZm9sbG93LXVwIG1lc3NhZ2UgdG8gYW4gaW50ZXJhY3Rpb24uXG4gICAqXG4gICAqIEBwYXJhbSB0b2tlbiAtIFRoZSBpbnRlcmFjdGlvbiB0b2tlbiB0byB1c2UsIHByb3ZpZGVkIGluIHRoZSBvcmlnaW5hbCBpbnRlcmFjdGlvbi5cbiAgICogQHBhcmFtIG1lc3NhZ2VJZCAtIFRoZSBJRCBvZiB0aGUgbWVzc2FnZSB0byBlZGl0LlxuICAgKiBAcGFyYW0gb3B0aW9ucyAtIFRoZSBwYXJhbWV0ZXJzIGZvciB0aGUgZWRpdCBvZiB0aGUgbWVzc2FnZS5cbiAgICogQHJldHVybnMgQW4gaW5zdGFuY2Ugb2YgdGhlIGVkaXRlZCB7QGxpbmsgRGlzY29yZE1lc3NhZ2V9LlxuICAgKlxuICAgKiBAcmVtYXJrc1xuICAgKiBVbmxpa2UgYGVkaXRNZXNzYWdlKClgLCB0aGlzIGVuZHBvaW50IGFsbG93cyB0aGUgYm90IHVzZXIgdG8gYWN0IHdpdGhvdXQgbmVlZGluZyB0byBzZWUgdGhlIGNoYW5uZWwgdGhlIG1lc3NhZ2UgaXMgaW4uXG4gICAqXG4gICAqIERvZXMgbm90IHN1cHBvcnQgZXBoZW1lcmFsIGZvbGxvdy11cCBtZXNzYWdlcyBkdWUgdG8gdGhlc2UgYmVpbmcgc3RhdGVsZXNzLlxuICAgKlxuICAgKiBGaXJlcyBhIF9NZXNzYWdlIFVwZGF0ZV8gZXZlbnQuXG4gICAqXG4gICAqIEBzZWUge0BsaW5rIGh0dHBzOi8vZG9jcy5kaXNjb3JkLmNvbS9kZXZlbG9wZXJzL2ludGVyYWN0aW9ucy9yZWNlaXZpbmctYW5kLXJlc3BvbmRpbmcjZWRpdC1mb2xsb3d1cC1tZXNzYWdlfVxuICAgKi9cbiAgYXN5bmMgZWRpdEZvbGxvd3VwTWVzc2FnZShyZXN0OiBSZXN0TWFuYWdlciwgdG9rZW46IHN0cmluZywgbWVzc2FnZUlkOiBCaWdTdHJpbmcsIG9wdGlvbnM6IEludGVyYWN0aW9uQ2FsbGJhY2tEYXRhKTogUHJvbWlzZTxEaXNjb3JkTWVzc2FnZT4ge1xuICAgIHJldHVybiBhd2FpdCByZXN0LnBhdGNoPERpc2NvcmRNZXNzYWdlPihyZXN0LnJvdXRlcy5pbnRlcmFjdGlvbnMucmVzcG9uc2VzLm1lc3NhZ2UocmVzdC5hcHBsaWNhdGlvbklkLCB0b2tlbiwgbWVzc2FnZUlkKSwge1xuICAgICAgYm9keTogb3B0aW9ucyxcbiAgICAgIGZpbGVzOiBvcHRpb25zLmZpbGVzLFxuICAgICAgdW5hdXRob3JpemVkOiB0cnVlLFxuICAgIH0pO1xuICB9LFxuICAvKipcbiAgICogRWRpdHMgYSBnbG9iYWwgYXBwbGljYXRpb24gY29tbWFuZC5cbiAgICpcbiAgICogQHBhcmFtIGNvbW1hbmRJZCAtIFRoZSBJRCBvZiB0aGUgY29tbWFuZCB0byBlZGl0LlxuICAgKiBAcGFyYW0gb3B0aW9ucyAtIFRoZSBwYXJhbWV0ZXJzIGZvciB0aGUgZWRpdCBvZiB0aGUgY29tbWFuZC5cbiAgICogQHJldHVybnMgQW4gaW5zdGFuY2Ugb2YgdGhlIGVkaXRlZCB7QGxpbmsgRGlzY29yZEFwcGxpY2F0aW9uQ29tbWFuZH0uXG4gICAqXG4gICAqIEBzZWUge0BsaW5rIGh0dHBzOi8vZG9jcy5kaXNjb3JkLmNvbS9kZXZlbG9wZXJzL2ludGVyYWN0aW9ucy9hcHBsaWNhdGlvbi1jb21tYW5kcyNlZGl0LWdsb2JhbC1hcHBsaWNhdGlvbi1jb21tYW5kfVxuICAgKi9cbiAgYXN5bmMgZWRpdEdsb2JhbEFwcGxpY2F0aW9uQ29tbWFuZChyZXN0OiBSZXN0TWFuYWdlciwgY29tbWFuZElkOiBCaWdTdHJpbmcsIG9wdGlvbnM6IENyZWF0ZUFwcGxpY2F0aW9uQ29tbWFuZCk6IFByb21pc2U8RGlzY29yZEFwcGxpY2F0aW9uQ29tbWFuZD4ge1xuICAgIHJldHVybiBhd2FpdCByZXN0LnBhdGNoPERpc2NvcmRBcHBsaWNhdGlvbkNvbW1hbmQ+KHJlc3Qucm91dGVzLmludGVyYWN0aW9ucy5jb21tYW5kcy5jb21tYW5kKHJlc3QuYXBwbGljYXRpb25JZCwgY29tbWFuZElkKSwgeyBib2R5OiBvcHRpb25zIH0pO1xuICB9LFxuICAvKipcbiAgICogRWRpdHMgYSBndWlsZCdzIHNldHRpbmdzLlxuICAgKlxuICAgKiBAcGFyYW0gZ3VpbGRJZCAtIFRoZSBJRCBvZiB0aGUgZ3VpbGQgdG8gZWRpdC5cbiAgICogQHBhcmFtIG9wdGlvbnMgLSBUaGUgcGFyYW1ldGVycyBmb3IgdGhlIGVkaXQgb2YgdGhlIGd1aWxkLlxuICAgKiBAcGFyYW0ge3N0cmluZ30gW3JlYXNvbl0gLSBBbiBvcHRpb25hbCByZWFzb24gZm9yIHRoZSBhY3Rpb24sIHRvIGJlIGluY2x1ZGVkIGluIHRoZSBhdWRpdCBsb2cuXG4gICAqIEByZXR1cm5zIEFuIGluc3RhbmNlIG9mIHRoZSBlZGl0ZWQge0BsaW5rIERpc2NvcmRHdWlsZH0uXG4gICAqXG4gICAqIEByZW1hcmtzXG4gICAqIFJlcXVpcmVzIHRoZSBgTUFOQUdFX0dVSUxEYCBwZXJtaXNzaW9uLlxuICAgKlxuICAgKiBJZiBhdHRlbXB0aW5nIHRvIGFkZCBvciByZW1vdmUgdGhlIHtAbGluayBHdWlsZEZlYXR1cmVzfS5Db21tdW5pdHkgZmVhdHVyZTpcbiAgICogLSBSZXF1aXJlcyB0aGUgYEFETUlOSVNUUkFUT1JgIHBlcm1pc3Npb24uXG4gICAqXG4gICAqIEZpcmVzIGEgX0d1aWxkIFVwZGF0ZV8gZ2F0ZXdheSBldmVudC5cbiAgICpcbiAgICogQHNlZSB7QGxpbmsgaHR0cHM6Ly9kb2NzLmRpc2NvcmQuY29tL2RldmVsb3BlcnMvcmVzb3VyY2VzL2d1aWxkI21vZGlmeS1ndWlsZH1cbiAgICovXG4gIGFzeW5jIGVkaXRHdWlsZChyZXN0OiBSZXN0TWFuYWdlciwgZ3VpbGRJZDogQmlnU3RyaW5nLCBvcHRpb25zOiBNb2RpZnlHdWlsZCwgcmVhc29uPzogc3RyaW5nKTogUHJvbWlzZTxEaXNjb3JkR3VpbGQ+IHtcbiAgICByZXR1cm4gYXdhaXQgcmVzdC5wYXRjaDxEaXNjb3JkR3VpbGQ+KHJlc3Qucm91dGVzLmd1aWxkcy5ndWlsZChndWlsZElkKSwgeyBib2R5OiBvcHRpb25zLCByZWFzb24gfSk7XG4gIH0sXG4gIC8qKlxuICAgKiBFZGl0cyBhbiBhcHBsaWNhdGlvbiBjb21tYW5kIHJlZ2lzdGVyZWQgaW4gYSBndWlsZC5cbiAgICpcbiAgICogQHBhcmFtIGd1aWxkSWQgLSBUaGUgSUQgb2YgdGhlIGd1aWxkIHRoZSBjb21tYW5kIGlzIHJlZ2lzdGVyZWQgaW4uXG4gICAqIEBwYXJhbSBjb21tYW5kSWQgLSBUaGUgSUQgb2YgdGhlIGNvbW1hbmQgdG8gZWRpdC5cbiAgICogQHBhcmFtIG9wdGlvbnMgLSBUaGUgcGFyYW1ldGVycyBmb3IgdGhlIGVkaXQgb2YgdGhlIGNvbW1hbmQuXG4gICAqIEByZXR1cm5zIEFuIGluc3RhbmNlIG9mIHRoZSBlZGl0ZWQge0BsaW5rIERpc2NvcmRBcHBsaWNhdGlvbkNvbW1hbmR9LlxuICAgKlxuICAgKiBAc2VlIHtAbGluayBodHRwczovL2RvY3MuZGlzY29yZC5jb20vZGV2ZWxvcGVycy9pbnRlcmFjdGlvbnMvYXBwbGljYXRpb24tY29tbWFuZHMjZWRpdC1ndWlsZC1hcHBsaWNhdGlvbi1jb21tYW5kfVxuICAgKi9cbiAgYXN5bmMgZWRpdEd1aWxkQXBwbGljYXRpb25Db21tYW5kKFxuICAgIHJlc3Q6IFJlc3RNYW5hZ2VyLFxuICAgIGNvbW1hbmRJZDogQmlnU3RyaW5nLFxuICAgIGd1aWxkSWQ6IEJpZ1N0cmluZyxcbiAgICBvcHRpb25zOiBDcmVhdGVBcHBsaWNhdGlvbkNvbW1hbmQsXG4gICk6IFByb21pc2U8RGlzY29yZEFwcGxpY2F0aW9uQ29tbWFuZD4ge1xuICAgIHJldHVybiBhd2FpdCByZXN0LnBhdGNoPERpc2NvcmRBcHBsaWNhdGlvbkNvbW1hbmQ+KHJlc3Qucm91dGVzLmludGVyYWN0aW9ucy5jb21tYW5kcy5ndWlsZHMub25lKHJlc3QuYXBwbGljYXRpb25JZCwgZ3VpbGRJZCwgY29tbWFuZElkKSwge1xuICAgICAgYm9keTogb3B0aW9ucyxcbiAgICB9KTtcbiAgfSxcbiAgLyoqXG4gICAqIEVkaXQgdGhlIGdpdmVuIHN0aWNrZXIuXG4gICAqXG4gICAqIEBwYXJhbSBndWlsZElkIFRoZSBJRCBvZiB0aGUgZ3VpbGQgdG8gZ2V0XG4gICAqIEBwYXJhbSB7c3RyaW5nfSBbcmVhc29uXSAtIEFuIG9wdGlvbmFsIHJlYXNvbiBmb3IgdGhlIGFjdGlvbiwgdG8gYmUgaW5jbHVkZWQgaW4gdGhlIGF1ZGl0IGxvZy5cbiAgICogQHJldHVybiBBIHtAbGluayBEaXNjb3JkU3RpY2tlcn1cbiAgICpcbiAgICogQHJlbWFya3NcbiAgICogRm9yIHN0aWNrZXJzIGNyZWF0ZWQgYnkgdGhlIGN1cnJlbnQgdXNlciwgcmVxdWlyZXMgZWl0aGVyIHRoZSBgQ1JFQVRFX0dVSUxEX0VYUFJFU1NJT05TYCBvciBgTUFOQUdFX0dVSUxEX0VYUFJFU1NJT05TYCBwZXJtaXNzaW9uLlxuICAgKiBGb3Igb3RoZXIgc3RpY2tlcnMsIHJlcXVpcmVzIHRoZSBgTUFOQUdFX0dVSUxEX0VYUFJFU1NJT05TYCBwZXJtaXNzaW9uLlxuICAgKiBGaXJlcyBhIEd1aWxkIFN0aWNrZXJzIFVwZGF0ZSBHYXRld2F5IGV2ZW50LlxuICAgKlxuICAgKiBAc2VlIHtAbGluayBodHRwczovL2RvY3MuZGlzY29yZC5jb20vZGV2ZWxvcGVycy9yZXNvdXJjZXMvc3RpY2tlciNtb2RpZnktZ3VpbGQtc3RpY2tlcn1cbiAgICovXG4gIGFzeW5jIGVkaXRHdWlsZFN0aWNrZXIoXG4gICAgcmVzdDogUmVzdE1hbmFnZXIsXG4gICAgZ3VpbGRJZDogQmlnU3RyaW5nLFxuICAgIHN0aWNrZXJJZDogQmlnU3RyaW5nLFxuICAgIG9wdGlvbnM6IEF0TGVhc3RPbmU8RWRpdEd1aWxkU3RpY2tlck9wdGlvbnM+LFxuICAgIHJlYXNvbj86IHN0cmluZyxcbiAgKTogUHJvbWlzZTxEaXNjb3JkU3RpY2tlcj4ge1xuICAgIHJldHVybiBhd2FpdCByZXN0LnBhdGNoPERpc2NvcmRTdGlja2VyPihyZXN0LnJvdXRlcy5ndWlsZHMuc3RpY2tlcihndWlsZElkLCBzdGlja2VySWQpLCB7IGJvZHk6IG9wdGlvbnMsIHJlYXNvbiB9KTtcbiAgfSxcbiAgLyoqXG4gICAqIEVkaXRzIGEgdGVtcGxhdGUncyBzZXR0aW5ncy5cbiAgICpcbiAgICogQHBhcmFtIGd1aWxkSWQgLSBUaGUgSUQgb2YgdGhlIGd1aWxkIHRvIGVkaXQgYSB0ZW1wbGF0ZSBvZi5cbiAgICogQHBhcmFtIHRlbXBsYXRlQ29kZSAtIFRoZSBjb2RlIG9mIHRoZSB0ZW1wbGF0ZSB0byBlZGl0LlxuICAgKiBAcGFyYW0gb3B0aW9ucyAtIFRoZSBwYXJhbWV0ZXJzIGZvciB0aGUgZWRpdCBvZiB0aGUgdGVtcGxhdGUuXG4gICAqIEByZXR1cm5zIEFuIGluc3RhbmNlIG9mIHRoZSBlZGl0ZWQge0BsaW5rIERpc2NvcmRUZW1wbGF0ZX0uXG4gICAqXG4gICAqIEByZW1hcmtzXG4gICAqIFJlcXVpcmVzIHRoZSBgTUFOQUdFX0dVSUxEYCBwZXJtaXNzaW9uLlxuICAgKlxuICAgKiBGaXJlcyBhIF9HdWlsZCBVcGRhdGVfIGdhdGV3YXkgZXZlbnQuXG4gICAqXG4gICAqIEBzZWUge0BsaW5rIGh0dHBzOi8vZG9jcy5kaXNjb3JkLmNvbS9kZXZlbG9wZXJzL3Jlc291cmNlcy9ndWlsZC10ZW1wbGF0ZSNtb2RpZnktZ3VpbGQtdGVtcGxhdGV9XG4gICAqL1xuICBhc3luYyBlZGl0R3VpbGRUZW1wbGF0ZShyZXN0OiBSZXN0TWFuYWdlciwgZ3VpbGRJZDogQmlnU3RyaW5nLCB0ZW1wbGF0ZUNvZGU6IHN0cmluZywgb3B0aW9uczogTW9kaWZ5R3VpbGRUZW1wbGF0ZSk6IFByb21pc2U8RGlzY29yZFRlbXBsYXRlPiB7XG4gICAgcmV0dXJuIGF3YWl0IHJlc3QucGF0Y2g8RGlzY29yZFRlbXBsYXRlPihyZXN0LnJvdXRlcy5ndWlsZHMudGVtcGxhdGVzLmd1aWxkKGd1aWxkSWQsIHRlbXBsYXRlQ29kZSksIHsgYm9keTogb3B0aW9ucyB9KTtcbiAgfSxcbiAgLyoqXG4gICAqIEVkaXRzIGEgbWVzc2FnZS5cbiAgICpcbiAgICogQHBhcmFtIGNoYW5uZWxJZCAtIFRoZSBJRCBvZiB0aGUgY2hhbm5lbCB0byBlZGl0IHRoZSBtZXNzYWdlIGluLlxuICAgKiBAcGFyYW0gbWVzc2FnZUlkIC0gVGhlIElEcyBvZiB0aGUgbWVzc2FnZSB0byBlZGl0LlxuICAgKiBAcGFyYW0gb3B0aW9ucyAtIFRoZSBwYXJhbWV0ZXJzIGZvciB0aGUgZWRpdCBvZiB0aGUgbWVzc2FnZS5cbiAgICogQHJldHVybnMgQW4gaW5zdGFuY2Ugb2YgdGhlIGVkaXRlZCB7QGxpbmsgRGlzY29yZE1lc3NhZ2V9LlxuICAgKlxuICAgKiBAcmVtYXJrc1xuICAgKiBJZiBlZGl0aW5nIGFub3RoZXIgdXNlcidzIG1lc3NhZ2U6XG4gICAqIC0gUmVxdWlyZXMgdGhlIGBNQU5BR0VfTUVTU0FHRVNgIHBlcm1pc3Npb24uXG4gICAqIC0gT25seSB0aGUge0BsaW5rIEVkaXRNZXNzYWdlLmZsYWdzIHwgZmxhZ3N9IHByb3BlcnR5IG9mIHRoZSBvcHRpb25zIG9iamVjdCBwYXJhbWV0ZXIgY2FuIGJlIGVkaXRlZC5cbiAgICpcbiAgICogRmlyZXMgYSBfTWVzc2FnZSBVcGRhdGVfIGdhdGV3YXkgZXZlbnQuXG4gICAqXG4gICAqIEBzZWUge0BsaW5rIGh0dHBzOi8vZG9jcy5kaXNjb3JkLmNvbS9kZXZlbG9wZXJzL3Jlc291cmNlcy9jaGFubmVsI2VkaXQtbWVzc2FnZX1cbiAgICovXG4gIGFzeW5jIGVkaXRNZXNzYWdlKHJlc3Q6IFJlc3RNYW5hZ2VyLCBjaGFubmVsSWQ6IEJpZ1N0cmluZywgbWVzc2FnZUlkOiBCaWdTdHJpbmcsIG9wdGlvbnM6IEVkaXRNZXNzYWdlKTogUHJvbWlzZTxEaXNjb3JkTWVzc2FnZT4ge1xuICAgIHJldHVybiBhd2FpdCByZXN0LnBhdGNoPERpc2NvcmRNZXNzYWdlPihyZXN0LnJvdXRlcy5jaGFubmVscy5tZXNzYWdlKGNoYW5uZWxJZCwgbWVzc2FnZUlkKSwgeyBib2R5OiBvcHRpb25zLCBmaWxlczogb3B0aW9ucy5maWxlcyB9KTtcbiAgfSxcbiAgLyoqXG4gICAqIEVkaXRzIHRoZSBpbml0aWFsIG1lc3NhZ2UgcmVzcG9uc2UgdG8gYW4gaW50ZXJhY3Rpb24uXG4gICAqXG4gICAqIEBwYXJhbSB0b2tlbiAtIFRoZSBpbnRlcmFjdGlvbiB0b2tlbiB0byB1c2UsIHByb3ZpZGVkIGluIHRoZSBvcmlnaW5hbCBpbnRlcmFjdGlvbi5cbiAgICogQHBhcmFtIG9wdGlvbnMgLSBUaGUgcGFyYW1ldGVycyBmb3IgdGhlIGVkaXQgb2YgdGhlIHJlc3BvbnNlLlxuICAgKiBAcmV0dXJucyBBbiBpbnN0YW5jZSBvZiB0aGUgZWRpdGVkIHtAbGluayBEaXNjb3JkTWVzc2FnZX0uXG4gICAqXG4gICAqIEByZW1hcmtzXG4gICAqIFVubGlrZSBgZWRpdE1lc3NhZ2UoKWAsIHRoaXMgZW5kcG9pbnQgYWxsb3dzIHRoZSBib3QgdXNlciB0byBhY3Qgd2l0aG91dCBuZWVkaW5nIHRvIHNlZSB0aGUgY2hhbm5lbCB0aGUgbWVzc2FnZSBpcyBpbi5cbiAgICpcbiAgICogRG9lcyBub3Qgc3VwcG9ydCBlcGhlbWVyYWwgZm9sbG93LXVwIG1lc3NhZ2VzIGR1ZSB0byB0aGVzZSBiZWluZyBzdGF0ZWxlc3MuXG4gICAqXG4gICAqIEZpcmVzIGEgX01lc3NhZ2UgVXBkYXRlXyBldmVudC5cbiAgICpcbiAgICogQHNlZSB7QGxpbmsgaHR0cHM6Ly9kb2NzLmRpc2NvcmQuY29tL2RldmVsb3BlcnMvaW50ZXJhY3Rpb25zL3JlY2VpdmluZy1hbmQtcmVzcG9uZGluZyNlZGl0LW9yaWdpbmFsLWludGVyYWN0aW9uLXJlc3BvbnNlfVxuICAgKi9cbiAgYXN5bmMgZWRpdE9yaWdpbmFsSW50ZXJhY3Rpb25SZXNwb25zZShyZXN0OiBSZXN0TWFuYWdlciwgdG9rZW46IHN0cmluZywgb3B0aW9uczogSW50ZXJhY3Rpb25DYWxsYmFja0RhdGEpOiBQcm9taXNlPERpc2NvcmRNZXNzYWdlPiB7XG4gICAgcmV0dXJuIGF3YWl0IHJlc3QucGF0Y2g8RGlzY29yZE1lc3NhZ2U+KHJlc3Qucm91dGVzLmludGVyYWN0aW9ucy5yZXNwb25zZXMub3JpZ2luYWwocmVzdC5hcHBsaWNhdGlvbklkLCB0b2tlbiksIHtcbiAgICAgIGJvZHk6IG9wdGlvbnMsXG4gICAgICBmaWxlczogb3B0aW9ucy5maWxlcyxcbiAgICAgIHVuYXV0aG9yaXplZDogdHJ1ZSxcbiAgICB9KTtcbiAgfSxcbiAgLyoqXG4gICAqIEVkaXRzIHRoZSB2b2ljZSBzdGF0ZSBvZiB0aGUgYm90IHVzZXIuXG4gICAqXG4gICAqIEBwYXJhbSBndWlsZElkIC0gVGhlIElEIG9mIHRoZSBndWlsZCBpbiB3aGljaCB0byBlZGl0IHRoZSB2b2ljZSBzdGF0ZSBvZiB0aGUgYm90IHVzZXIuXG4gICAqIEBwYXJhbSBvcHRpb25zIC0gVGhlIHBhcmFtZXRlcnMgZm9yIHRoZSBlZGl0IG9mIHRoZSB2b2ljZSBzdGF0ZS5cbiAgICpcbiAgICogQHJlbWFya3NcbiAgICogVGhlIHtAbGluayBFZGl0T3duVm9pY2VTdGF0ZS5jaGFubmVsSWQgfCBjaGFubmVsSWR9IHByb3BlcnR5IG9mIHRoZSBvcHRpb25zIG9iamVjdCBwYXJhbWV0ZXIgbXVzdCBwb2ludCB0byBhIHN0YWdlIGNoYW5uZWwsIGFuZCB0aGUgYm90IHVzZXIgbXVzdCBhbHJlYWR5IGhhdmUgam9pbmVkIGl0LlxuICAgKlxuICAgKiBJZiBhdHRlbXB0aW5nIHRvIHVubXV0ZSBvbmVzZWxmOlxuICAgKiAtIFJlcXVpcmVzIHRoZSBgTVVURV9NRU1CRVJTYCBwZXJtaXNzaW9uLlxuICAgKlxuICAgKiBJZiBhdHRlbXB0aW5nIHRvIHJlcXVlc3QgdG8gc3BlYWs6XG4gICAqIC0gUmVxdWlyZXMgdGhlIGBSRVFVRVNUX1RPX1NQRUFLYCBwZXJtaXNzaW9uLlxuICAgKlxuICAgKiBAc2VlIHtAbGluayBodHRwczovL2RvY3MuZGlzY29yZC5jb20vZGV2ZWxvcGVycy9yZXNvdXJjZXMvdm9pY2UjbW9kaWZ5LWN1cnJlbnQtdXNlci12b2ljZS1zdGF0ZX1cbiAgICovXG4gIGFzeW5jIGVkaXRPd25Wb2ljZVN0YXRlKHJlc3Q6IFJlc3RNYW5hZ2VyLCBndWlsZElkOiBCaWdTdHJpbmcsIG9wdGlvbnM6IEVkaXRPd25Wb2ljZVN0YXRlKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgYXdhaXQgcmVzdC5wYXRjaChyZXN0LnJvdXRlcy5ndWlsZHMudm9pY2UoZ3VpbGRJZCksIHtcbiAgICAgIGJvZHk6IHtcbiAgICAgICAgLi4ub3B0aW9ucyxcbiAgICAgICAgcmVxdWVzdFRvU3BlYWtUaW1lc3RhbXA6IG9wdGlvbnMucmVxdWVzdFRvU3BlYWtUaW1lc3RhbXBcbiAgICAgICAgICA/IG5ldyBEYXRlKG9wdGlvbnMucmVxdWVzdFRvU3BlYWtUaW1lc3RhbXApLnRvSVNPU3RyaW5nKClcbiAgICAgICAgICA6IG9wdGlvbnMucmVxdWVzdFRvU3BlYWtUaW1lc3RhbXAsXG4gICAgICB9LFxuICAgIH0pO1xuICB9LFxuICAvKipcbiAgICogRWRpdHMgYSByb2xlIGluIGEgZ3VpbGQuXG4gICAqXG4gICAqIEBwYXJhbSBndWlsZElkIC0gVGhlIElEIG9mIHRoZSBndWlsZCB0byBlZGl0IHRoZSByb2xlIGluLlxuICAgKiBAcGFyYW0gcm9sZUlkIC0gVGhlIElEIG9mIHRoZSByb2xlIHRvIGVkaXQuXG4gICAqIEBwYXJhbSBvcHRpb25zIC0gVGhlIHBhcmFtZXRlcnMgZm9yIHRoZSBlZGl0IG9mIHRoZSByb2xlLlxuICAgKiBAcGFyYW0ge3N0cmluZ30gW3JlYXNvbl0gLSBBbiBvcHRpb25hbCByZWFzb24gZm9yIHRoZSBhY3Rpb24sIHRvIGJlIGluY2x1ZGVkIGluIHRoZSBhdWRpdCBsb2cuXG4gICAqIEByZXR1cm5zIEFuIGluc3RhbmNlIG9mIHRoZSBlZGl0ZWQge0BsaW5rIERpc2NvcmRSb2xlfS5cbiAgICpcbiAgICogQHJlbWFya3NcbiAgICogUmVxdWlyZXMgdGhlIGBNQU5BR0VfUk9MRVNgIHBlcm1pc3Npb24uXG4gICAqXG4gICAqIEZpcmVzIGEgX0d1aWxkIFJvbGUgVXBkYXRlXyBnYXRld2F5IGV2ZW50LlxuICAgKlxuICAgKiBAc2VlIHtAbGluayBodHRwczovL2RvY3MuZGlzY29yZC5jb20vZGV2ZWxvcGVycy9yZXNvdXJjZXMvZ3VpbGQjbW9kaWZ5LWd1aWxkLXJvbGV9XG4gICAqL1xuICBhc3luYyBlZGl0Um9sZShyZXN0OiBSZXN0TWFuYWdlciwgZ3VpbGRJZDogQmlnU3RyaW5nLCByb2xlSWQ6IEJpZ1N0cmluZywgb3B0aW9uczogRWRpdEd1aWxkUm9sZSwgcmVhc29uPzogc3RyaW5nKTogUHJvbWlzZTxEaXNjb3JkUm9sZT4ge1xuICAgIHJldHVybiBhd2FpdCByZXN0LnBhdGNoPERpc2NvcmRSb2xlPihyZXN0LnJvdXRlcy5ndWlsZHMucm9sZXMub25lKGd1aWxkSWQsIHJvbGVJZCksIHsgYm9keTogb3B0aW9ucywgcmVhc29uIH0pO1xuICB9LFxuICAvKipcbiAgICogRWRpdHMgdGhlIHBvc2l0aW9ucyBvZiBhIHNldCBvZiByb2xlcy5cbiAgICpcbiAgICogQHBhcmFtIGd1aWxkSWQgLSBUaGUgSUQgb2YgdGhlIGd1aWxkIHRvIGVkaXQgdGhlIHJvbGUgcG9zaXRpb25zIGluLlxuICAgKiBAcGFyYW0gb3B0aW9ucyAtIFRoZSBwYXJhbWV0ZXJzIGZvciB0aGUgZWRpdCBvZiB0aGUgcm9sZSBwb3NpdGlvbnMuXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBbcmVhc29uXSAtIEFuIG9wdGlvbmFsIHJlYXNvbiBmb3IgdGhlIGFjdGlvbiwgdG8gYmUgaW5jbHVkZWQgaW4gdGhlIGF1ZGl0IGxvZy5cbiAgICogQHJldHVybnMgQSBjb2xsZWN0aW9uIG9mIHtAbGluayBEaXNjb3JkUm9sZX0gb2JqZWN0cyBhc3NvcnRlZCBieSByb2xlIElELlxuICAgKlxuICAgKiBAcmVtYXJrc1xuICAgKiBSZXF1aXJlcyB0aGUgYE1BTkFHRV9ST0xFU2AgcGVybWlzc2lvbi5cbiAgICpcbiAgICogRmlyZXMgYSBfR3VpbGQgUm9sZSBVcGRhdGVfIGdhdGV3YXkgZXZlbnQgZm9yIGV2ZXJ5IHJvbGUgaW1wYWN0ZWQgaW4gdGhpcyBjaGFuZ2UuXG4gICAqXG4gICAqIEBzZWUge0BsaW5rIGh0dHBzOi8vZG9jcy5kaXNjb3JkLmNvbS9kZXZlbG9wZXJzL3Jlc291cmNlcy9ndWlsZCNtb2RpZnktZ3VpbGQtcm9sZS1wb3NpdGlvbnN9XG4gICAqL1xuICBhc3luYyBlZGl0Um9sZVBvc2l0aW9ucyhyZXN0OiBSZXN0TWFuYWdlciwgZ3VpbGRJZDogQmlnU3RyaW5nLCBvcHRpb25zOiBNb2RpZnlSb2xlUG9zaXRpb25zW10sIHJlYXNvbj86IHN0cmluZyk6IFByb21pc2U8RGlzY29yZFJvbGVbXT4ge1xuICAgIHJldHVybiBhd2FpdCByZXN0LnBhdGNoPERpc2NvcmRSb2xlW10+KHJlc3Qucm91dGVzLmd1aWxkcy5yb2xlcy5hbGwoZ3VpbGRJZCksIHsgYm9keTogb3B0aW9ucywgcmVhc29uIH0pO1xuICB9LFxuICAvKipcbiAgICogRWRpdHMgYSBzY2hlZHVsZWQgZXZlbnQuXG4gICAqXG4gICAqIEBwYXJhbSBndWlsZElkIC0gVGhlIElEIG9mIHRoZSBndWlsZCB0byBlZGl0IHRoZSBzY2hlZHVsZWQgZXZlbnQgaW4uXG4gICAqIEBwYXJhbSBldmVudElkIC0gVGhlIElEIG9mIHRoZSBzY2hlZHVsZWQgZXZlbnQgdG8gZWRpdC5cbiAgICogQHBhcmFtIHtzdHJpbmd9IFtyZWFzb25dIC0gQW4gb3B0aW9uYWwgcmVhc29uIGZvciB0aGUgYWN0aW9uLCB0byBiZSBpbmNsdWRlZCBpbiB0aGUgYXVkaXQgbG9nLlxuICAgKiBAcmV0dXJucyBBbiBpbnN0YW5jZSBvZiB0aGUgZWRpdGVkIHtAbGluayBEaXNjb3JkU2NoZWR1bGVkRXZlbnR9LlxuICAgKlxuICAgKiBAcmVtYXJrc1xuICAgKiBSZXF1aXJlcyB0aGUgYE1BTkFHRV9FVkVOVFNgIHBlcm1pc3Npb24uXG4gICAqXG4gICAqIFRvIHN0YXJ0IG9yIGVuZCBhbiBldmVudCwgbW9kaWZ5IHRoZSBldmVudCdzIGBzdGF0dXNgIHByb3BlcnR5LlxuICAgKlxuICAgKiBUaGUgYGVudGl0eV9tZXRhZGF0YWAgcHJvcGVydHkgaXMgZGlzY2FyZGVkIGZvciBldmVudHMgd2hvc2UgYGVudGl0eV90eXBlYCBpcyBub3Qge0BsaW5rIFNjaGVkdWxlZEV2ZW50RW50aXR5VHlwZX0uRXh0ZXJuYWwuXG4gICAqXG4gICAqIEZpcmVzIGEgX0d1aWxkIFNjaGVkdWxlZCBFdmVudCBVcGRhdGVfIGdhdGV3YXkgZXZlbnQuXG4gICAqXG4gICAqIEBzZWUge0BsaW5rIGh0dHBzOi8vZG9jcy5kaXNjb3JkLmNvbS9kZXZlbG9wZXJzL3Jlc291cmNlcy9ndWlsZC1zY2hlZHVsZWQtZXZlbnQjbW9kaWZ5LWd1aWxkLXNjaGVkdWxlZC1ldmVudH1cbiAgICovXG4gIGFzeW5jIGVkaXRTY2hlZHVsZWRFdmVudChcbiAgICByZXN0OiBSZXN0TWFuYWdlcixcbiAgICBndWlsZElkOiBCaWdTdHJpbmcsXG4gICAgZXZlbnRJZDogQmlnU3RyaW5nLFxuICAgIG9wdGlvbnM6IFBhcnRpYWw8RWRpdFNjaGVkdWxlZEV2ZW50PixcbiAgICByZWFzb24/OiBzdHJpbmcsXG4gICk6IFByb21pc2U8RGlzY29yZFNjaGVkdWxlZEV2ZW50PiB7XG4gICAgcmV0dXJuIGF3YWl0IHJlc3QucGF0Y2g8RGlzY29yZFNjaGVkdWxlZEV2ZW50PihyZXN0LnJvdXRlcy5ndWlsZHMuZXZlbnRzLmV2ZW50KGd1aWxkSWQsIGV2ZW50SWQpLCB7IGJvZHk6IG9wdGlvbnMsIHJlYXNvbiB9KTtcbiAgfSxcbiAgLyoqXG4gICAqIEVkaXRzIGEgc3RhZ2UgaW5zdGFuY2UuXG4gICAqXG4gICAqIEBwYXJhbSBjaGFubmVsSWQgLSBUaGUgSUQgb2YgdGhlIHN0YWdlIGNoYW5uZWwgdGhlIHN0YWdlIGluc3RhbmNlIGlzIGFzc29jaWF0ZWQgd2l0aC5cbiAgICogQHBhcmFtIHRvcGljIC0gVG9waWMgb2YgdGhlIFN0YWdlIGluc3RhbmNlICgxLTEyMCBjaGFyYWN0ZXJzKS5cbiAgICogQHBhcmFtIHtzdHJpbmd9IFtyZWFzb25dIC0gQW4gb3B0aW9uYWwgcmVhc29uIGZvciB0aGUgYWN0aW9uLCB0byBiZSBpbmNsdWRlZCBpbiB0aGUgYXVkaXQgbG9nLlxuICAgKiBAcmV0dXJucyBBbiBpbnN0YW5jZSBvZiB0aGUgdXBkYXRlZCB7QGxpbmsgRGlzY29yZFN0YWdlSW5zdGFuY2V9LlxuICAgKlxuICAgKiBAcmVtYXJrc1xuICAgKiBSZXF1aXJlcyB0aGUgdXNlciB0byBiZSBhIG1vZGVyYXRvciBvZiB0aGUgc3RhZ2UgY2hhbm5lbC5cbiAgICpcbiAgICogRmlyZXMgYSBfU3RhZ2UgSW5zdGFuY2UgVXBkYXRlXyBldmVudC5cbiAgICpcbiAgICogQHNlZSB7QGxpbmsgaHR0cHM6Ly9kb2NzLmRpc2NvcmQuY29tL2RldmVsb3BlcnMvcmVzb3VyY2VzL3N0YWdlLWluc3RhbmNlI21vZGlmeS1zdGFnZS1pbnN0YW5jZX1cbiAgICovXG4gIGFzeW5jIGVkaXRTdGFnZUluc3RhbmNlKHJlc3Q6IFJlc3RNYW5hZ2VyLCBjaGFubmVsSWQ6IEJpZ1N0cmluZywgdG9waWM6IHN0cmluZywgcmVhc29uPzogc3RyaW5nKTogUHJvbWlzZTxEaXNjb3JkU3RhZ2VJbnN0YW5jZT4ge1xuICAgIHJldHVybiBhd2FpdCByZXN0LnBhdGNoPERpc2NvcmRTdGFnZUluc3RhbmNlPihyZXN0LnJvdXRlcy5jaGFubmVscy5zdGFnZShjaGFubmVsSWQpLCB7IGJvZHk6IHsgdG9waWMgfSwgcmVhc29uIH0pO1xuICB9LFxuICAvKipcbiAgICogRWRpdHMgdGhlIHZvaWNlIHN0YXRlIG9mIGFub3RoZXIgdXNlci5cbiAgICpcbiAgICogQHBhcmFtIGd1aWxkSWQgLSBUaGUgSUQgb2YgdGhlIGd1aWxkIGluIHdoaWNoIHRvIGVkaXQgdGhlIHZvaWNlIHN0YXRlIG9mIHRoZSBib3QgdXNlci5cbiAgICogQHBhcmFtIG9wdGlvbnMgLSBUaGUgcGFyYW1ldGVycyBmb3IgdGhlIGVkaXQgb2YgdGhlIHZvaWNlIHN0YXRlLlxuICAgKlxuICAgKiBAcmVtYXJrc1xuICAgKiBUaGUge0BsaW5rIEVkaXRPd25Wb2ljZVN0YXRlLmNoYW5uZWxJZCB8IGNoYW5uZWxJZH0gcHJvcGVydHkgb2YgdGhlIG9wdGlvbnMgb2JqZWN0IHBhcmFtZXRlciBtdXN0IHBvaW50IHRvIGEgc3RhZ2UgY2hhbm5lbCwgYW5kIHRoZSB1c2VyIG11c3QgYWxyZWFkeSBoYXZlIGpvaW5lZCBpdC5cbiAgICpcbiAgICogUmVxdWlyZXMgdGhlIGBNVVRFX01FTUJFUlNgIHBlcm1pc3Npb24uXG4gICAqXG4gICAqIEBzZWUge0BsaW5rIGh0dHBzOi8vZG9jcy5kaXNjb3JkLmNvbS9kZXZlbG9wZXJzL3Jlc291cmNlcy92b2ljZSNtb2RpZnktdXNlci12b2ljZS1zdGF0ZX1cbiAgICovXG4gIGFzeW5jIGVkaXRVc2VyVm9pY2VTdGF0ZShyZXN0OiBSZXN0TWFuYWdlciwgZ3VpbGRJZDogQmlnU3RyaW5nLCBvcHRpb25zOiBFZGl0VXNlclZvaWNlU3RhdGUpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBhd2FpdCByZXN0LnBhdGNoKHJlc3Qucm91dGVzLmd1aWxkcy52b2ljZShndWlsZElkLCBvcHRpb25zLnVzZXJJZCksIHsgYm9keTogb3B0aW9ucyB9KTtcbiAgfSxcbiAgLyoqXG4gICAqIEVkaXQgdGhlIGN1cnJlbnQgdXNlciBhcHBsaWNhdGlvbiByb2xlIGNvbm5lY3Rpb24gZm9yIHRoZSBhcHBsaWNhdGlvbi5cbiAgICpcbiAgICogQHBhcmFtIGJlYXJlclRva2VuIC0gVGhlIGFjY2VzcyB0b2tlbiBvZiB0aGUgdXNlclxuICAgKiBAcGFyYW0gYXBwbGljYXRpb25JZCAtIFRoZSBpZCBvZiB0aGUgYXBwbGljYXRpb24gdG8gZWRpdCB0aGUgcm9sZSBjb25uZWN0aW9uXG4gICAqIEBwYXJhbSBvcHRpb25zIC0gVGhlIG9wdGlvbnMgdG8gZWRpdFxuICAgKiBAcmV0dXJucyB7RGlzY29yZEFwcGxpY2F0aW9uUm9sZUNvbm5lY3Rpb259XG4gICAqXG4gICAqIEByZW1hcmtzXG4gICAqIFRoaXMgcmVxdWlyZXMgdGhlIGByb2xlX2Nvbm5lY3Rpb25zLndyaXRlYCBzY29wZS5cbiAgICpcbiAgICogQHNlZSB7QGxpbmsgaHR0cHM6Ly9kb2NzLmRpc2NvcmQuY29tL2RldmVsb3BlcnMvcmVzb3VyY2VzL3VzZXIjdXBkYXRlLXVzZXItYXBwbGljYXRpb24tcm9sZS1jb25uZWN0aW9ufVxuICAgKi9cbiAgYXN5bmMgZWRpdFVzZXJBcHBsaWNhdGlvblJvbGVDb25uZWN0aW9uKFxuICAgIHJlc3Q6IFJlc3RNYW5hZ2VyLFxuICAgIGJlYXJlclRva2VuOiBzdHJpbmcsXG4gICAgYXBwbGljYXRpb25JZDogQmlnU3RyaW5nLFxuICAgIG9wdGlvbnM6IENhbWVsaXplPERpc2NvcmRBcHBsaWNhdGlvblJvbGVDb25uZWN0aW9uPixcbiAgKTogUHJvbWlzZTxEaXNjb3JkQXBwbGljYXRpb25Sb2xlQ29ubmVjdGlvbj4ge1xuICAgIHJldHVybiBhd2FpdCByZXN0LnB1dDxEaXNjb3JkQXBwbGljYXRpb25Sb2xlQ29ubmVjdGlvbj4ocmVzdC5yb3V0ZXMub2F1dGgyLnJvbGVDb25uZWN0aW9ucyhhcHBsaWNhdGlvbklkKSwge1xuICAgICAgYm9keTogb3B0aW9ucyxcbiAgICAgIGhlYWRlcnM6IHtcbiAgICAgICAgYXV0aG9yaXphdGlvbjogYEJlYXJlciAke2JlYXJlclRva2VufWAsXG4gICAgICB9LFxuICAgICAgdW5hdXRob3JpemVkOiB0cnVlLFxuICAgIH0pO1xuICB9LFxuICAvKipcbiAgICogRGVsZXRlcyB0aGUgYXBwbGljYXRpb24gcm9sZSBjb25uZWN0aW9uIGZvciB0aGUgdXNlci5cbiAgICpcbiAgICogQHBhcmFtIGJlYXJlclRva2VuIC0gVGhlIGFjY2VzcyB0b2tlbiBvZiB0aGUgdXNlclxuICAgKiBAcGFyYW0gYXBwbGljYXRpb25JZCAtIFRoZSBpZCBvZiB0aGUgYXBwbGljYXRpb24gdG8gZGVsZXRlIHRoZSByb2xlIGNvbm5lY3Rpb25cbiAgICpcbiAgICogQHJlbWFya3NcbiAgICogVGhpcyByZXF1aXJlcyB0aGUgYHJvbGVfY29ubmVjdGlvbnMud3JpdGVgIHNjb3BlLlxuICAgKlxuICAgKiBAc2VlIHtAbGluayBodHRwczovL2RvY3MuZGlzY29yZC5jb20vZGV2ZWxvcGVycy9yZXNvdXJjZXMvdXNlciNkZWxldGUtY3VycmVudC11c2VyLWFwcGxpY2F0aW9uLXJvbGUtY29ubmVjdGlvbn1cbiAgICovXG4gIGFzeW5jIGRlbGV0ZUN1cnJlbnRVc2VyQXBwbGljYXRpb25Sb2xlQ29ubmVjdGlvbihyZXN0OiBSZXN0TWFuYWdlciwgYmVhcmVyVG9rZW46IHN0cmluZywgYXBwbGljYXRpb25JZDogQmlnU3RyaW5nKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgcmV0dXJuIGF3YWl0IHJlc3QuZGVsZXRlKHJlc3Qucm91dGVzLm9hdXRoMi5yb2xlQ29ubmVjdGlvbnMoYXBwbGljYXRpb25JZCksIHtcbiAgICAgIGhlYWRlcnM6IHtcbiAgICAgICAgYXV0aG9yaXphdGlvbjogYEJlYXJlciAke2JlYXJlclRva2VufWAsXG4gICAgICB9LFxuICAgICAgdW5hdXRob3JpemVkOiB0cnVlLFxuICAgIH0pO1xuICB9LFxuICAvKipcbiAgICogRWRpdHMgYSB3ZWJob29rLlxuICAgKlxuICAgKiBAcGFyYW0gd2ViaG9va0lkIC0gVGhlIElEIG9mIHRoZSB3ZWJob29rIHRvIGVkaXQuXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBbcmVhc29uXSAtIEFuIG9wdGlvbmFsIHJlYXNvbiBmb3IgdGhlIGFjdGlvbiwgdG8gYmUgaW5jbHVkZWQgaW4gdGhlIGF1ZGl0IGxvZy5cbiAgICogQHJldHVybnMgQW4gaW5zdGFuY2Ugb2YgdGhlIGVkaXRlZCB7QGxpbmsgRGlzY29yZFdlYmhvb2t9LlxuICAgKlxuICAgKiBAcmVtYXJrc1xuICAgKiBSZXF1aXJlcyB0aGUgYE1BTkFHRV9XRUJIT09LU2AgcGVybWlzc2lvbi5cbiAgICpcbiAgICogRmlyZXMgYSBfV2ViaG9va3MgVXBkYXRlXyBnYXRld2F5IGV2ZW50LlxuICAgKlxuICAgKiBAc2VlIHtAbGluayBodHRwczovL2RvY3MuZGlzY29yZC5jb20vZGV2ZWxvcGVycy9yZXNvdXJjZXMvd2ViaG9vayNlZGl0LXdlYmhvb2t9XG4gICAqL1xuICBhc3luYyBlZGl0V2ViaG9vayhyZXN0OiBSZXN0TWFuYWdlciwgd2ViaG9va0lkOiBCaWdTdHJpbmcsIG9wdGlvbnM6IE1vZGlmeVdlYmhvb2ssIHJlYXNvbj86IHN0cmluZyk6IFByb21pc2U8RGlzY29yZFdlYmhvb2s+IHtcbiAgICByZXR1cm4gYXdhaXQgcmVzdC5wYXRjaDxEaXNjb3JkV2ViaG9vaz4ocmVzdC5yb3V0ZXMud2ViaG9va3MuaWQod2ViaG9va0lkKSwgeyBib2R5OiBvcHRpb25zLCByZWFzb24gfSk7XG4gIH0sXG4gIC8qKlxuICAgKiBFZGl0cyBhIHdlYmhvb2sgbWVzc2FnZS5cbiAgICpcbiAgICogQHBhcmFtIHdlYmhvb2tJZCAtIFRoZSBJRCBvZiB0aGUgd2ViaG9vayB0byBlZGl0IHRoZSBtZXNzYWdlIG9mLlxuICAgKiBAcGFyYW0gdG9rZW4gLSBUaGUgd2ViaG9vayB0b2tlbiwgdXNlZCB0byBlZGl0IHRoZSBtZXNzYWdlLlxuICAgKiBAcGFyYW0gbWVzc2FnZUlkIC0gVGhlIElEIG9mIHRoZSBtZXNzYWdlIHRvIGVkaXQuXG4gICAqIEBwYXJhbSBvcHRpb25zIC0gVGhlIHBhcmFtZXRlcnMgZm9yIHRoZSBlZGl0IG9mIHRoZSBtZXNzYWdlLlxuICAgKiBAcmV0dXJucyBBbiBpbnN0YW5jZSBvZiB0aGUgZWRpdGVkIHtAbGluayBEaXNjb3JkTWVzc2FnZX0uXG4gICAqXG4gICAqIEByZW1hcmtzXG4gICAqIEZpcmVzIGEgX01lc3NhZ2UgVXBkYXRlXyBnYXRld2F5IGV2ZW50LlxuICAgKlxuICAgKiBAc2VlIHtAbGluayBodHRwczovL2RvY3MuZGlzY29yZC5jb20vZGV2ZWxvcGVycy9yZXNvdXJjZXMvd2ViaG9vayNlZGl0LXdlYmhvb2stbWVzc2FnZX1cbiAgICovXG4gIGFzeW5jIGVkaXRXZWJob29rTWVzc2FnZShcbiAgICByZXN0OiBSZXN0TWFuYWdlcixcbiAgICB3ZWJob29rSWQ6IEJpZ1N0cmluZyxcbiAgICB0b2tlbjogc3RyaW5nLFxuICAgIG1lc3NhZ2VJZDogQmlnU3RyaW5nLFxuICAgIG9wdGlvbnM6IEVkaXRXZWJob29rTWVzc2FnZU9wdGlvbnMsXG4gICk6IFByb21pc2U8RGlzY29yZE1lc3NhZ2U+IHtcbiAgICByZXR1cm4gYXdhaXQgcmVzdC5wYXRjaDxEaXNjb3JkTWVzc2FnZT4ocmVzdC5yb3V0ZXMud2ViaG9va3MubWVzc2FnZSh3ZWJob29rSWQsIHRva2VuLCBtZXNzYWdlSWQsIG9wdGlvbnMpLCB7XG4gICAgICBib2R5OiBvcHRpb25zLFxuICAgICAgZmlsZXM6IG9wdGlvbnMuZmlsZXMsXG4gICAgICB1bmF1dGhvcml6ZWQ6IHRydWUsXG4gICAgfSk7XG4gIH0sXG4gIC8qKlxuICAgKiBFZGl0cyBhIHdlYmhvb2sgdXNpbmcgdGhlIHdlYmhvb2sgdG9rZW4sIHRoZXJlYnkgYnlwYXNzaW5nIHRoZSBuZWVkIGZvciBhdXRoZW50aWNhdGlvbiArIHBlcm1pc3Npb25zLlxuICAgKlxuICAgKiBAcGFyYW0gd2ViaG9va0lkIC0gVGhlIElEIG9mIHRoZSB3ZWJob29rIHRvIGVkaXQuXG4gICAqIEBwYXJhbSB0b2tlbiAtIFRoZSB3ZWJob29rIHRva2VuLCB1c2VkIHRvIGVkaXQgdGhlIHdlYmhvb2suXG4gICAqIEByZXR1cm5zIEFuIGluc3RhbmNlIG9mIHRoZSBlZGl0ZWQge0BsaW5rIERpc2NvcmRXZWJob29rfS5cbiAgICpcbiAgICogQHJlbWFya3NcbiAgICogUmVxdWlyZXMgdGhlIGBNQU5BR0VfV0VCSE9PS1NgIHBlcm1pc3Npb24uXG4gICAqXG4gICAqIEZpcmVzIGEgX1dlYmhvb2tzIFVwZGF0ZV8gZ2F0ZXdheSBldmVudC5cbiAgICpcbiAgICogQHNlZSB7QGxpbmsgaHR0cHM6Ly9kb2NzLmRpc2NvcmQuY29tL2RldmVsb3BlcnMvcmVzb3VyY2VzL3dlYmhvb2sjbW9kaWZ5LXdlYmhvb2std2l0aC10b2tlbn1cbiAgICovXG4gIGFzeW5jIGVkaXRXZWJob29rV2l0aFRva2VuKFxuICAgIHJlc3Q6IFJlc3RNYW5hZ2VyLFxuICAgIHdlYmhvb2tJZDogQmlnU3RyaW5nLFxuICAgIHRva2VuOiBzdHJpbmcsXG4gICAgb3B0aW9uczogT21pdDxNb2RpZnlXZWJob29rLCAnY2hhbm5lbElkJz4sXG4gICk6IFByb21pc2U8RGlzY29yZFdlYmhvb2s+IHtcbiAgICByZXR1cm4gYXdhaXQgcmVzdC5wYXRjaDxEaXNjb3JkV2ViaG9vaz4ocmVzdC5yb3V0ZXMud2ViaG9va3Mud2ViaG9vayh3ZWJob29rSWQsIHRva2VuKSwge1xuICAgICAgYm9keTogb3B0aW9ucyxcbiAgICAgIHVuYXV0aG9yaXplZDogdHJ1ZSxcbiAgICB9KTtcbiAgfSxcbiAgLyoqXG4gICAqIEVkaXRzIGEgZ3VpbGQncyB3ZWxjb21lIHNjcmVlbi5cbiAgICpcbiAgICogQHBhcmFtIGd1aWxkSWQgLSBUaGUgSUQgb2YgdGhlIGd1aWxkIHRvIGVkaXQgdGhlIHdlbGNvbWUgc2NyZWVuIG9mLlxuICAgKiBAcGFyYW0gb3B0aW9ucyAtIFRoZSBwYXJhbWV0ZXJzIGZvciB0aGUgZWRpdCBvZiB0aGUgd2VsY29tZSBzY3JlZW4uXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBbcmVhc29uXSAtIEFuIG9wdGlvbmFsIHJlYXNvbiBmb3IgdGhlIGFjdGlvbiwgdG8gYmUgaW5jbHVkZWQgaW4gdGhlIGF1ZGl0IGxvZy5cbiAgICogQHJldHVybnMgQW4gaW5zdGFuY2Ugb2YgdGhlIGVkaXRlZCB7QGxpbmsgRGlzY29yZFdlbGNvbWVTY3JlZW59LlxuICAgKlxuICAgKiBAcmVtYXJrc1xuICAgKiBSZXF1aXJlcyB0aGUgYE1BTkFHRV9HVUlMRGAgcGVybWlzc2lvbi5cbiAgICpcbiAgICogRmlyZXMgYSBfR3VpbGQgVXBkYXRlXyBnYXRld2F5IGV2ZW50LlxuICAgKlxuICAgKiBAc2VlIHtAbGluayBodHRwczovL2RvY3MuZGlzY29yZC5jb20vZGV2ZWxvcGVycy9yZXNvdXJjZXMvZ3VpbGQjbW9kaWZ5LWd1aWxkLXdlbGNvbWUtc2NyZWVufVxuICAgKi9cbiAgYXN5bmMgZWRpdFdlbGNvbWVTY3JlZW4ocmVzdDogUmVzdE1hbmFnZXIsIGd1aWxkSWQ6IEJpZ1N0cmluZywgb3B0aW9uczogTW9kaWZ5R3VpbGRXZWxjb21lU2NyZWVuLCByZWFzb24/OiBzdHJpbmcpOiBQcm9taXNlPERpc2NvcmRXZWxjb21lU2NyZWVuPiB7XG4gICAgcmV0dXJuIGF3YWl0IHJlc3QucGF0Y2g8RGlzY29yZFdlbGNvbWVTY3JlZW4+KHJlc3Qucm91dGVzLmd1aWxkcy53ZWxjb21lKGd1aWxkSWQpLCB7IGJvZHk6IG9wdGlvbnMsIHJlYXNvbiB9KTtcbiAgfSxcbiAgLyoqXG4gICAqIEVkaXRzIHRoZSBzZXR0aW5ncyBvZiBhIGd1aWxkJ3Mgd2lkZ2V0LlxuICAgKlxuICAgKiBAcGFyYW0gZ3VpbGRJZCAtIFRoZSBJRCBvZiB0aGUgZ3VpbGQgdG8gZWRpdCB0aGUgc2V0dGluZ3Mgb2YgdGhlIHdpZGdldCBvZi5cbiAgICogQHBhcmFtIHtzdHJpbmd9IFtyZWFzb25dIC0gQW4gb3B0aW9uYWwgcmVhc29uIGZvciB0aGUgYWN0aW9uLCB0byBiZSBpbmNsdWRlZCBpbiB0aGUgYXVkaXQgbG9nLlxuICAgKiBAcmV0dXJucyBBbiBpbnN0YW5jZSBvZiB0aGUgZWRpdGVkIHtAbGluayBEaXNjb3JkR3VpbGRXaWRnZXRTZXR0aW5nc30uXG4gICAqXG4gICAqIEByZW1hcmtzXG4gICAqIFJlcXVpcmVzIHRoZSBgTUFOQUdFX0dVSUxEYCBwZXJtaXNzaW9uLlxuICAgKlxuICAgKiBGaXJlcyBhIF9HdWlsZCBVcGRhdGVfIGdhdGV3YXkgZXZlbnQuXG4gICAqXG4gICAqIEBzZWUge0BsaW5rIGh0dHBzOi8vZG9jcy5kaXNjb3JkLmNvbS9kZXZlbG9wZXJzL3Jlc291cmNlcy9ndWlsZCNtb2RpZnktZ3VpbGQtd2lkZ2V0fVxuICAgKi9cbiAgYXN5bmMgZWRpdFdpZGdldFNldHRpbmdzKFxuICAgIHJlc3Q6IFJlc3RNYW5hZ2VyLFxuICAgIGd1aWxkSWQ6IEJpZ1N0cmluZyxcbiAgICBvcHRpb25zOiBDYW1lbGl6ZTxEaXNjb3JkR3VpbGRXaWRnZXRTZXR0aW5ncz4sXG4gICAgcmVhc29uPzogc3RyaW5nLFxuICApOiBQcm9taXNlPERpc2NvcmRHdWlsZFdpZGdldFNldHRpbmdzPiB7XG4gICAgcmV0dXJuIGF3YWl0IHJlc3QucGF0Y2g8RGlzY29yZEd1aWxkV2lkZ2V0U2V0dGluZ3M+KHJlc3Qucm91dGVzLmd1aWxkcy53aWRnZXQoZ3VpbGRJZCksIHsgYm9keTogb3B0aW9ucywgcmVhc29uIH0pO1xuICB9LFxuICAvKipcbiAgICogRXhlY3V0ZXMgYSB3ZWJob29rLCBjYXVzaW5nIGEgbWVzc2FnZSB0byBiZSBwb3N0ZWQgaW4gdGhlIGNoYW5uZWwgY29uZmlndXJlZCBmb3IgdGhlIHdlYmhvb2suXG4gICAqXG4gICAqIEBwYXJhbSB3ZWJob29rSWQgLSBUaGUgSUQgb2YgdGhlIHdlYmhvb2sgdG8gZXhlY3V0ZS5cbiAgICogQHBhcmFtIHRva2VuIC0gVGhlIHdlYmhvb2sgdG9rZW4sIHVzZWQgdG8gZXhlY3V0ZSB0aGUgd2ViaG9vay5cbiAgICogQHBhcmFtIG9wdGlvbnMgLSBUaGUgcGFyYW1ldGVycyBmb3IgdGhlIGV4ZWN1dGlvbiBvZiB0aGUgd2ViaG9vay5cbiAgICogQHJldHVybnMgQW4gaW5zdGFuY2Ugb2YgdGhlIGNyZWF0ZWQge0BsaW5rIERpc2NvcmRNZXNzYWdlfSwgb3IgYHVuZGVmaW5lZGAgaWYgdGhlIHtAbGluayBFeGVjdXRlV2ViaG9vay53YWl0IHwgd2FpdH0gcHJvcGVydHkgb2YgdGhlIG9wdGlvbnMgb2JqZWN0IHBhcmFtZXRlciBpcyBzZXQgdG8gYGZhbHNlYC5cbiAgICpcbiAgICogQHJlbWFya3NcbiAgICogSWYgdGhlIHdlYmhvb2sgY2hhbm5lbCBpcyBhIGZvcnVtIGNoYW5uZWwsIHlvdSBtdXN0IHByb3ZpZGUgYSB2YWx1ZSBmb3IgZWl0aGVyIGB0aHJlYWRJZGAgb3IgYHRocmVhZE5hbWVgLlxuICAgKlxuICAgKiBAc2VlIHtAbGluayBodHRwczovL2RvY3MuZGlzY29yZC5jb20vZGV2ZWxvcGVycy9yZXNvdXJjZXMvd2ViaG9vayNleGVjdXRlLXdlYmhvb2t9XG4gICAqL1xuICBhc3luYyBleGVjdXRlV2ViaG9vayhyZXN0OiBSZXN0TWFuYWdlciwgd2ViaG9va0lkOiBCaWdTdHJpbmcsIHRva2VuOiBzdHJpbmcsIG9wdGlvbnM6IEV4ZWN1dGVXZWJob29rKTogUHJvbWlzZTxEaXNjb3JkTWVzc2FnZSB8IHVuZGVmaW5lZD4ge1xuICAgIHJldHVybiBhd2FpdCByZXN0LnBvc3Q8RGlzY29yZE1lc3NhZ2U+KHJlc3Qucm91dGVzLndlYmhvb2tzLndlYmhvb2sod2ViaG9va0lkLCB0b2tlbiwgb3B0aW9ucyksIHtcbiAgICAgIGJvZHk6IG9wdGlvbnMsXG4gICAgICB1bmF1dGhvcml6ZWQ6IHRydWUsXG4gICAgfSk7XG4gIH0sXG4gIC8qKlxuICAgKiBGb2xsb3dzIGFuIGFubm91bmNlbWVudCBjaGFubmVsLCBhbGxvd2luZyBtZXNzYWdlcyBwb3N0ZWQgd2l0aGluIGl0IHRvIGJlIGNyb3NzLXBvc3RlZCBpbnRvIHRoZSB0YXJnZXQgY2hhbm5lbC5cbiAgICpcbiAgICogQHBhcmFtIHNvdXJjZUNoYW5uZWxJZCAtIFRoZSBJRCBvZiB0aGUgYW5ub3VuY2VtZW50IGNoYW5uZWwgdG8gZm9sbG93LlxuICAgKiBAcGFyYW0gdGFyZ2V0Q2hhbm5lbElkIC0gVGhlIElEIG9mIHRoZSB0YXJnZXQgY2hhbm5lbCAtIHRoZSBjaGFubmVsIHRvIGNyb3NzLXBvc3QgdG8uXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBbcmVhc29uXSAtIEFuIG9wdGlvbmFsIHJlYXNvbiBmb3IgdGhlIGFjdGlvbiwgdG8gYmUgaW5jbHVkZWQgaW4gdGhlIGF1ZGl0IGxvZy5cbiAgICogQHJldHVybnMgQW4gaW5zdGFuY2Ugb2Yge0BsaW5rIERpc2NvcmRGb2xsb3dlZENoYW5uZWx9LlxuICAgKlxuICAgKiBAcmVtYXJrc1xuICAgKiBSZXF1aXJlcyB0aGUgYE1BTkFHRV9XRUJIT09LU2AgcGVybWlzc2lvbiBpbiB0aGUgX190YXJnZXQgY2hhbm5lbF9fLlxuICAgKlxuICAgKiBGaXJlcyBhIF9XZWJob29rcyBVcGRhdGVfIGdhdGV3YXkgZXZlbnQuXG4gICAqXG4gICAqIEBzZWUge0BsaW5rIGh0dHBzOi8vZG9jcy5kaXNjb3JkLmNvbS9kZXZlbG9wZXJzL3Jlc291cmNlcy9jaGFubmVsI2ZvbGxvdy1hbm5vdW5jZW1lbnQtY2hhbm5lbH1cbiAgICovXG4gIGFzeW5jIGZvbGxvd0Fubm91bmNlbWVudChcbiAgICByZXN0OiBSZXN0TWFuYWdlcixcbiAgICBzb3VyY2VDaGFubmVsSWQ6IEJpZ1N0cmluZyxcbiAgICB0YXJnZXRDaGFubmVsSWQ6IEJpZ1N0cmluZyxcbiAgICByZWFzb24/OiBzdHJpbmcsXG4gICk6IFByb21pc2U8RGlzY29yZEZvbGxvd2VkQ2hhbm5lbD4ge1xuICAgIHJldHVybiBhd2FpdCByZXN0LnBvc3Q8RGlzY29yZEZvbGxvd2VkQ2hhbm5lbD4ocmVzdC5yb3V0ZXMuY2hhbm5lbHMuZm9sbG93KHNvdXJjZUNoYW5uZWxJZCksIHtcbiAgICAgIGJvZHk6IHtcbiAgICAgICAgd2ViaG9va0NoYW5uZWxJZDogdGFyZ2V0Q2hhbm5lbElkLFxuICAgICAgfSxcbiAgICAgIHJlYXNvbixcbiAgICB9KTtcbiAgfSxcbiAgLyoqXG4gICAqIEdldHMgdGhlIGxpc3Qgb2YgYWxsIGFjdGl2ZSB0aHJlYWRzIGZvciBhIGd1aWxkLlxuICAgKlxuICAgKiBAcGFyYW0gZ3VpbGRJZCAtIFRoZSBJRCBvZiB0aGUgZ3VpbGQgdG8gZ2V0IHRoZSB0aHJlYWRzIG9mLlxuICAgKiBAcmV0dXJucyBBbiBpbnN0YW5jZSBvZiB7QGxpbmsgRGlzY29yZExpc3RBY3RpdmVUaHJlYWRzfS5cbiAgICpcbiAgICogQHJlbWFya3NcbiAgICogUmV0dXJucyBib3RoIHB1YmxpYyBhbmQgcHJpdmF0ZSB0aHJlYWRzLlxuICAgKlxuICAgKiBUaHJlYWRzIGFyZSBvcmRlcmVkIGJ5IHRoZSBgaWRgIHByb3BlcnR5IGluIGRlc2NlbmRpbmcgb3JkZXIuXG4gICAqXG4gICAqIEBzZWUge0BsaW5rIGh0dHBzOi8vZG9jcy5kaXNjb3JkLmNvbS9kZXZlbG9wZXJzL3Jlc291cmNlcy9ndWlsZCNsaXN0LWFjdGl2ZS1ndWlsZC10aHJlYWRzfVxuICAgKi9cbiAgYXN5bmMgZ2V0QWN0aXZlVGhyZWFkcyhyZXN0OiBSZXN0TWFuYWdlciwgZ3VpbGRJZDogQmlnU3RyaW5nKTogUHJvbWlzZTxEaXNjb3JkTGlzdEFjdGl2ZVRocmVhZHM+IHtcbiAgICByZXR1cm4gYXdhaXQgcmVzdC5nZXQ8RGlzY29yZExpc3RBY3RpdmVUaHJlYWRzPihyZXN0LnJvdXRlcy5jaGFubmVscy50aHJlYWRzLmFjdGl2ZShndWlsZElkKSk7XG4gIH0sXG4gIC8qKiBHZXQgdGhlIGFwcGxpY2F0aW9ucyBpbmZvICovXG4gIGFzeW5jIGdldEFwcGxpY2F0aW9uSW5mbyhyZXN0OiBSZXN0TWFuYWdlcik6IFByb21pc2U8RGlzY29yZEFwcGxpY2F0aW9uPiB7XG4gICAgcmV0dXJuIGF3YWl0IHJlc3QuZ2V0PERpc2NvcmRBcHBsaWNhdGlvbj4ocmVzdC5yb3V0ZXMub2F1dGgyLmFwcGxpY2F0aW9uKCkpO1xuICB9LFxuICAvKipcbiAgICogRWRpdCBwcm9wZXJ0aWVzIG9mIHRoZSBhcHAgYXNzb2NpYXRlZCB3aXRoIHRoZSByZXF1ZXN0aW5nIGJvdCB1c2VyLlxuICAgKlxuICAgKiBAcmVtYXJrc1xuICAgKiBPbmx5IHByb3BlcnRpZXMgdGhhdCBhcmUgcGFzc2VkIHdpbGwgYmUgdXBkYXRlZC5cbiAgICovXG4gIGFzeW5jIGVkaXRBcHBsaWNhdGlvbkluZm8ocmVzdDogUmVzdE1hbmFnZXIsIGJvZHk6IEVkaXRBcHBsaWNhdGlvbik6IFByb21pc2U8RGlzY29yZEFwcGxpY2F0aW9uPiB7XG4gICAgcmV0dXJuIGF3YWl0IHJlc3QucGF0Y2g8RGlzY29yZEFwcGxpY2F0aW9uPihyZXN0LnJvdXRlcy5hcHBsaWNhdGlvbigpLCB7XG4gICAgICBib2R5LFxuICAgIH0pO1xuICB9LFxuICAvKipcbiAgICogR2V0IHRoZSBjdXJyZW50IGF1dGhlbnRpY2F0aW9uIGluZm8gZm9yIHRoZSBhdXRoZW50aWNhdGVkIHVzZXJcbiAgICpcbiAgICogQHBhcmFtIGJlYXJlclRva2VuIC0gQW55IE9BdXRoMiBkZXJpdmVkIGFjY2VzcyB0b2tlblxuICAgKiBAcmV0dXJucyBBbiBpbnN0YW5jZSBvZiB7QGxpbmsgRGlzY29yZEN1cnJlbnRBdXRob3JpemF0aW9ufVxuICAgKlxuICAgKiBAcmVtYXJrc1xuICAgKiBUaGUgdXNlciBvYmplY3QgaXMgbm90IGRlZmluZWQgaWYgdGhlIHNjb3BlcyBkbyBub3QgaW5jbHVkZSBgaWRlbnRpZnlgLlxuICAgKiBJbiB0aGUgdXNlciBvYmplY3QsIGlmIGRlZmluZWQsIHRoZSBlbWFpbCBpcyBub3QgaW5jbHVkZWQgaWYgdGhlIHNjb3BlcyBkbyBub3QgaW5jbHVkZSBgZW1haWxgXG4gICAqL1xuICBhc3luYyBnZXRDdXJyZW50QXV0aGVudGljYXRpb25JbmZvKHJlc3Q6IFJlc3RNYW5hZ2VyLCBiZWFyZXJUb2tlbjogc3RyaW5nKTogUHJvbWlzZTxEaXNjb3JkQ3VycmVudEF1dGhvcml6YXRpb24+IHtcbiAgICByZXR1cm4gYXdhaXQgcmVzdC5nZXQ8RGlzY29yZEN1cnJlbnRBdXRob3JpemF0aW9uPihyZXN0LnJvdXRlcy5vYXV0aDIuY3VycmVudEF1dGhvcml6YXRpb24oKSwge1xuICAgICAgaGVhZGVyczoge1xuICAgICAgICBhdXRob3JpemF0aW9uOiBgQmVhcmVyICR7YmVhcmVyVG9rZW59YCxcbiAgICAgIH0sXG4gICAgICB1bmF1dGhvcml6ZWQ6IHRydWUsXG4gICAgfSk7XG4gIH0sXG4gIC8qKlxuICAgKiBFeGNoYW5nZSB0aGUgaW5mb3JtYXRpb24gdG8gZ2V0IGEgT0F1dGgyIGFjY2Vzc1Rva2VuIHRva2VuXG4gICAqXG4gICAqIEBwYXJhbSBjbGllbnRJZCAtIEFwcGxpY2F0aW9uJ3MgY2xpZW50IGlkXG4gICAqIEBwYXJhbSBjbGllbnRTZWNyZXQgLSBhcHBsaWNhdGlvbidzIGNsaWVudCBzZWNyZXRcbiAgICogQHBhcmFtIG9wdGlvbnMgLSBUaGUgb3B0aW9ucyB0byBtYWtlIHRoZSBleGNoYW5nZSB3aXRoIGRpc2NvcmRcbiAgICovXG4gIGFzeW5jIGV4Y2hhbmdlVG9rZW4oXG4gICAgcmVzdDogUmVzdE1hbmFnZXIsXG4gICAgY2xpZW50SWQ6IEJpZ1N0cmluZyxcbiAgICBjbGllbnRTZWNyZXQ6IHN0cmluZyxcbiAgICBvcHRpb25zOiBDYW1lbGl6ZTxEaXNjb3JkVG9rZW5FeGNoYW5nZT4sXG4gICk6IFByb21pc2U8RGlzY29yZEFjY2Vzc1Rva2VuUmVzcG9uc2U+IHtcbiAgICBjb25zdCBiYXNpY0NyZWRlbnRpYWxzID0gQnVmZmVyLmZyb20oYCR7Y2xpZW50SWR9OiR7Y2xpZW50U2VjcmV0fWApO1xuXG4gICAgY29uc3QgcmVzdE9wdGlvbnM6IE1ha2VSZXF1ZXN0T3B0aW9ucyA9IHtcbiAgICAgIGJvZHk6IG9wdGlvbnMsXG4gICAgICBoZWFkZXJzOiB7XG4gICAgICAgICdjb250ZW50LXR5cGUnOiAnYXBwbGljYXRpb24veC13d3ctZm9ybS11cmxlbmNvZGVkJyxcbiAgICAgICAgYXV0aG9yaXphdGlvbjogYEJhc2ljICR7YmFzaWNDcmVkZW50aWFscy50b1N0cmluZygnYmFzZTY0Jyl9YCxcbiAgICAgIH0sXG4gICAgICBydW5UaHJvdWdoUXVldWU6IGZhbHNlLFxuICAgICAgdW5hdXRob3JpemVkOiB0cnVlLFxuICAgIH07XG5cbiAgICBpZiAob3B0aW9ucy5ncmFudFR5cGUgPT09ICdjbGllbnRfY3JlZGVudGlhbHMnKSB7XG4gICAgICByZXN0T3B0aW9ucy5ib2R5LnNjb3BlID0gb3B0aW9ucy5zY29wZS5qb2luKCcgJyk7XG4gICAgfVxuXG4gICAgcmV0dXJuIGF3YWl0IHJlc3QucG9zdDxEaXNjb3JkQWNjZXNzVG9rZW5SZXNwb25zZT4ocmVzdC5yb3V0ZXMub2F1dGgyLnRva2VuRXhjaGFuZ2UoKSwgcmVzdE9wdGlvbnMpO1xuICB9LFxuICAvKipcbiAgICogUmV2b2tlIGFuIGFjY2Vzc190b2tlblxuICAgKlxuICAgKiBAcGFyYW0gY2xpZW50SWQgLSBBcHBsaWNhdGlvbidzIGNsaWVudCBpZFxuICAgKiBAcGFyYW0gY2xpZW50U2VjcmV0IC0gYXBwbGljYXRpb24ncyBjbGllbnQgc2VjcmV0XG4gICAqIEBwYXJhbSBvcHRpb25zIC0gVGhlIG9wdGlvbnMgdG8gcmV2b2tlIHRoZSBhY2Nlc3NfdG9rZW5cbiAgICovXG4gIGFzeW5jIHJldm9rZVRva2VuKHJlc3Q6IFJlc3RNYW5hZ2VyLCBjbGllbnRJZDogQmlnU3RyaW5nLCBjbGllbnRTZWNyZXQ6IHN0cmluZywgb3B0aW9uczogQ2FtZWxpemU8RGlzY29yZFRva2VuUmV2b2NhdGlvbj4pOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBjb25zdCBiYXNpY0NyZWRlbnRpYWxzID0gQnVmZmVyLmZyb20oYCR7Y2xpZW50SWR9OiR7Y2xpZW50U2VjcmV0fWApO1xuXG4gICAgYXdhaXQgcmVzdC5wb3N0KHJlc3Qucm91dGVzLm9hdXRoMi50b2tlblJldm9rZSgpLCB7XG4gICAgICBib2R5OiBvcHRpb25zLFxuICAgICAgaGVhZGVyczoge1xuICAgICAgICAnY29udGVudC10eXBlJzogJ2FwcGxpY2F0aW9uL3gtd3d3LWZvcm0tdXJsZW5jb2RlZCcsXG4gICAgICAgIGF1dGhvcml6YXRpb246IGBCYXNpYyAke2Jhc2ljQ3JlZGVudGlhbHMudG9TdHJpbmcoJ2Jhc2U2NCcpfWAsXG4gICAgICB9LFxuICAgICAgdW5hdXRob3JpemVkOiB0cnVlLFxuICAgIH0pO1xuICB9LFxuICAvKipcbiAgICogR2V0cyB0aGUgcGVybWlzc2lvbnMgb2YgYSBndWlsZCBhcHBsaWNhdGlvbiBjb21tYW5kLlxuICAgKlxuICAgKiBAcGFyYW0gZ3VpbGRJZCAtIFRoZSBJRCBvZiB0aGUgZ3VpbGQgdGhlIGNvbW1hbmQgaXMgcmVnaXN0ZXJlZCBpbi5cbiAgICogQHBhcmFtIGNvbW1hbmRJZCAtIFRoZSBJRCBvZiB0aGUgY29tbWFuZCB0byBnZXQgdGhlIHBlcm1pc3Npb25zIG9mLlxuICAgKiBAcGFyYW0gb3B0aW9ucyAtIFRoZSBPQXV0aDIgcmVsYXRlZCBvcHRpb25hbCBwYXJhbWV0ZXJzIGZvciB0aGUgZW5kcG9pbnRcbiAgICogQHJldHVybnMgQW4gaW5zdGFuY2Ugb2Yge0BsaW5rIERpc2NvcmRHdWlsZEFwcGxpY2F0aW9uQ29tbWFuZFBlcm1pc3Npb25zfS5cbiAgICpcbiAgICogQHJlbWFya3NcbiAgICogVGhlbiBzcGVjaWZ5aW5nIHRoZSBvcHRpb25zIG9iamVjdCB0aGUgYWNjZXNzIHRva2VuIHBhc3NlZC1pbiByZXF1aXJlcyB0aGUgT0F1dGgyIHNjb3BlIGBhcHBsaWNhdGlvbnMuY29tbWFuZHMucGVybWlzc2lvbnMudXBkYXRlYFxuICAgKlxuICAgKiBAc2VlIHtAbGluayBodHRwczovL2RvY3MuZGlzY29yZC5jb20vZGV2ZWxvcGVycy9pbnRlcmFjdGlvbnMvYXBwbGljYXRpb24tY29tbWFuZHMjZ2V0LWFwcGxpY2F0aW9uLWNvbW1hbmQtcGVybWlzc2lvbnN9XG4gICAqL1xuICBhc3luYyBnZXRBcHBsaWNhdGlvbkNvbW1hbmRQZXJtaXNzaW9uKFxuICAgIHJlc3Q6IFJlc3RNYW5hZ2VyLFxuICAgIGd1aWxkSWQ6IEJpZ1N0cmluZyxcbiAgICBjb21tYW5kSWQ6IEJpZ1N0cmluZyxcbiAgICBvcHRpb25zPzogR2V0QXBwbGljYXRpb25Db21tYW5kUGVybWlzc2lvbk9wdGlvbnMsXG4gICk6IFByb21pc2U8RGlzY29yZEd1aWxkQXBwbGljYXRpb25Db21tYW5kUGVybWlzc2lvbnM+IHtcbiAgICBjb25zdCByZXN0T3B0aW9uczogT21pdDxNYWtlUmVxdWVzdE9wdGlvbnMsICdib2R5Jz4gPSB7fTtcblxuICAgIGlmIChvcHRpb25zPy5hY2Nlc3NUb2tlbikge1xuICAgICAgcmVzdE9wdGlvbnMudW5hdXRob3JpemVkID0gdHJ1ZTtcbiAgICAgIHJlc3RPcHRpb25zLmhlYWRlcnMgPSB7XG4gICAgICAgIGF1dGhvcml6YXRpb246IGBCZWFyZXIgJHtvcHRpb25zLmFjY2Vzc1Rva2VufWAsXG4gICAgICB9O1xuICAgIH1cblxuICAgIHJldHVybiBhd2FpdCByZXN0LmdldDxEaXNjb3JkR3VpbGRBcHBsaWNhdGlvbkNvbW1hbmRQZXJtaXNzaW9ucz4oXG4gICAgICByZXN0LnJvdXRlcy5pbnRlcmFjdGlvbnMuY29tbWFuZHMucGVybWlzc2lvbihvcHRpb25zPy5hcHBsaWNhdGlvbklkID8/IHJlc3QuYXBwbGljYXRpb25JZCwgZ3VpbGRJZCwgY29tbWFuZElkKSxcbiAgICAgIHJlc3RPcHRpb25zLFxuICAgICk7XG4gIH0sXG4gIC8qKlxuICAgKiBHZXRzIHRoZSBwZXJtaXNzaW9ucyBvZiBhbGwgYXBwbGljYXRpb24gY29tbWFuZHMgcmVnaXN0ZXJlZCBpbiBhIGd1aWxkIGJ5IHRoZSBJRCBvZiB0aGUgZ3VpbGQgYW5kIG9wdGlvbmFsbHkgYW4gZXh0ZXJuYWwgYXBwbGljYXRpb24uXG4gICAqXG4gICAqIEBwYXJhbSBndWlsZElkIC0gVGhlIElEIG9mIHRoZSBndWlsZCB0byBnZXQgdGhlIHBlcm1pc3Npb25zIG9iamVjdHMgb2YuXG4gICAqIEBwYXJhbSBvcHRpb25zIC0gVGhlIE9BdXRoMiByZWxhdGVkIG9wdGlvbmFsIHBhcmFtZXRlcnMgZm9yIHRoZSBlbmRwb2ludFxuICAgKiBAcmV0dXJucyBBIGNvbGxlY3Rpb24gb2Yge0BsaW5rIERpc2NvcmRHdWlsZEFwcGxpY2F0aW9uQ29tbWFuZFBlcm1pc3Npb25zfSBvYmplY3RzIGFzc29ydGVkIGJ5IGNvbW1hbmQgSUQuXG4gICAqXG4gICAqIEByZW1hcmtzXG4gICAqIFRoZW4gc3BlY2lmeWluZyB0aGUgb3B0aW9ucyBvYmplY3QgdGhlIGFjY2VzcyB0b2tlbiBwYXNzZWQtaW4gcmVxdWlyZXMgdGhlIE9BdXRoMiBzY29wZSBgYXBwbGljYXRpb25zLmNvbW1hbmRzLnBlcm1pc3Npb25zLnVwZGF0ZWBcbiAgICpcbiAgICogQHNlZSB7QGxpbmsgaHR0cHM6Ly9kb2NzLmRpc2NvcmQuY29tL2RldmVsb3BlcnMvaW50ZXJhY3Rpb25zL2FwcGxpY2F0aW9uLWNvbW1hbmRzI2dldC1ndWlsZC1hcHBsaWNhdGlvbi1jb21tYW5kLXBlcm1pc3Npb25zfVxuICAgKi9cbiAgYXN5bmMgZ2V0QXBwbGljYXRpb25Db21tYW5kUGVybWlzc2lvbnMoXG4gICAgcmVzdDogUmVzdE1hbmFnZXIsXG4gICAgZ3VpbGRJZDogQmlnU3RyaW5nLFxuICAgIG9wdGlvbnM/OiBHZXRBcHBsaWNhdGlvbkNvbW1hbmRQZXJtaXNzaW9uT3B0aW9ucyxcbiAgKTogUHJvbWlzZTxEaXNjb3JkR3VpbGRBcHBsaWNhdGlvbkNvbW1hbmRQZXJtaXNzaW9uc1tdPiB7XG4gICAgY29uc3QgcmVzdE9wdGlvbnM6IE9taXQ8TWFrZVJlcXVlc3RPcHRpb25zLCAnYm9keSc+ID0ge307XG5cbiAgICBpZiAob3B0aW9ucz8uYWNjZXNzVG9rZW4pIHtcbiAgICAgIHJlc3RPcHRpb25zLnVuYXV0aG9yaXplZCA9IHRydWU7XG4gICAgICByZXN0T3B0aW9ucy5oZWFkZXJzID0ge1xuICAgICAgICBhdXRob3JpemF0aW9uOiBgQmVhcmVyICR7b3B0aW9ucy5hY2Nlc3NUb2tlbn1gLFxuICAgICAgfTtcbiAgICB9XG5cbiAgICByZXR1cm4gYXdhaXQgcmVzdC5nZXQ8RGlzY29yZEd1aWxkQXBwbGljYXRpb25Db21tYW5kUGVybWlzc2lvbnNbXT4oXG4gICAgICByZXN0LnJvdXRlcy5pbnRlcmFjdGlvbnMuY29tbWFuZHMucGVybWlzc2lvbnMob3B0aW9ucz8uYXBwbGljYXRpb25JZCA/PyByZXN0LmFwcGxpY2F0aW9uSWQsIGd1aWxkSWQpLFxuICAgICAgcmVzdE9wdGlvbnMsXG4gICAgKTtcbiAgfSxcbiAgLyoqXG4gICAqIEdldHMgYSBndWlsZCdzIGF1ZGl0IGxvZy5cbiAgICpcbiAgICogQHBhcmFtIGd1aWxkSWQgLSBUaGUgSUQgb2YgdGhlIGd1aWxkIHRvIGdldCB0aGUgYXVkaXQgbG9nIG9mLlxuICAgKiBAcGFyYW0gb3B0aW9ucyAtIFRoZSBwYXJhbWV0ZXJzIGZvciB0aGUgZmV0Y2hpbmcgb2YgdGhlIGF1ZGl0IGxvZy5cbiAgICogQHJldHVybnMgQW4gaW5zdGFuY2Ugb2Yge0BsaW5rIERpc2NvcmRBdWRpdExvZ30uXG4gICAqXG4gICAqIEByZW1hcmtzXG4gICAqIFJlcXVpcmVzIHRoZSBgVklFV19BVURJVF9MT0dgIHBlcm1pc3Npb24uXG4gICAqXG4gICAqIEBzZWUge0BsaW5rIGh0dHBzOi8vZG9jcy5kaXNjb3JkLmNvbS9kZXZlbG9wZXJzL3Jlc291cmNlcy9hdWRpdC1sb2cjZ2V0LWd1aWxkLWF1ZGl0LWxvZ31cbiAgICovXG4gIGFzeW5jIGdldEF1ZGl0TG9nKHJlc3Q6IFJlc3RNYW5hZ2VyLCBndWlsZElkOiBCaWdTdHJpbmcsIG9wdGlvbnM/OiBHZXRHdWlsZEF1ZGl0TG9nKTogUHJvbWlzZTxEaXNjb3JkQXVkaXRMb2c+IHtcbiAgICByZXR1cm4gYXdhaXQgcmVzdC5nZXQ8RGlzY29yZEF1ZGl0TG9nPihyZXN0LnJvdXRlcy5ndWlsZHMuYXVkaXRsb2dzKGd1aWxkSWQsIG9wdGlvbnMpKTtcbiAgfSxcbiAgLyoqXG4gICAqIEdldHMgYW4gYXV0b21vZCBydWxlIGJ5IGl0cyBJRC5cbiAgICpcbiAgICogQHBhcmFtIGd1aWxkSWQgLSBUaGUgSUQgb2YgdGhlIGd1aWxkIHRvIGdldCB0aGUgcnVsZSBvZi5cbiAgICogQHBhcmFtIHJ1bGVJZCAtIFRoZSBJRCBvZiB0aGUgcnVsZSB0byBnZXQuXG4gICAqIEByZXR1cm5zIEFuIGluc3RhbmNlIG9mIHtAbGluayBEaXNjb3JkQXV0b01vZGVyYXRpb25SdWxlfS5cbiAgICpcbiAgICogQHJlbWFya3NcbiAgICogUmVxdWlyZXMgdGhlIGBNQU5BR0VfR1VJTERgIHBlcm1pc3Npb24uXG4gICAqXG4gICAqIEBzZWUge0BsaW5rIGh0dHBzOi8vZG9jcy5kaXNjb3JkLmNvbS9kZXZlbG9wZXJzL3Jlc291cmNlcy9hdXRvLW1vZGVyYXRpb24jZ2V0LWF1dG8tbW9kZXJhdGlvbi1ydWxlfVxuICAgKi9cbiAgYXN5bmMgZ2V0QXV0b21vZFJ1bGUocmVzdDogUmVzdE1hbmFnZXIsIGd1aWxkSWQ6IEJpZ1N0cmluZywgcnVsZUlkOiBCaWdTdHJpbmcpOiBQcm9taXNlPERpc2NvcmRBdXRvTW9kZXJhdGlvblJ1bGU+IHtcbiAgICByZXR1cm4gYXdhaXQgcmVzdC5nZXQ8RGlzY29yZEF1dG9Nb2RlcmF0aW9uUnVsZT4ocmVzdC5yb3V0ZXMuZ3VpbGRzLmF1dG9tb2QucnVsZShndWlsZElkLCBydWxlSWQpKTtcbiAgfSxcbiAgLyoqXG4gICAqIEdldHMgdGhlIGxpc3Qgb2YgYXV0b21vZCBydWxlcyBmb3IgYSBndWlsZC5cbiAgICpcbiAgICogQHBhcmFtIGd1aWxkSWQgLSBUaGUgSUQgb2YgdGhlIGd1aWxkIHRvIGdldCB0aGUgcnVsZXMgZnJvbS5cbiAgICogQHJldHVybnMgQSBjb2xsZWN0aW9uIG9mIHtAbGluayBEaXNjb3JkQXV0b01vZGVyYXRpb25SdWxlfSBvYmplY3RzIGFzc29ydGVkIGJ5IHJ1bGUgSUQuXG4gICAqXG4gICAqIEByZW1hcmtzXG4gICAqIFJlcXVpcmVzIHRoZSBgTUFOQUdFX0dVSUxEYCBwZXJtaXNzaW9uLlxuICAgKlxuICAgKiBAc2VlIHtAbGluayBodHRwczovL2RvY3MuZGlzY29yZC5jb20vZGV2ZWxvcGVycy9yZXNvdXJjZXMvYXV0by1tb2RlcmF0aW9uI2xpc3QtYXV0by1tb2RlcmF0aW9uLXJ1bGVzLWZvci1ndWlsZH1cbiAgICovXG4gIGFzeW5jIGdldEF1dG9tb2RSdWxlcyhyZXN0OiBSZXN0TWFuYWdlciwgZ3VpbGRJZDogQmlnU3RyaW5nKTogUHJvbWlzZTxEaXNjb3JkQXV0b01vZGVyYXRpb25SdWxlW10+IHtcbiAgICByZXR1cm4gYXdhaXQgcmVzdC5nZXQ8RGlzY29yZEF1dG9Nb2RlcmF0aW9uUnVsZVtdPihyZXN0LnJvdXRlcy5ndWlsZHMuYXV0b21vZC5ydWxlcyhndWlsZElkKSk7XG4gIH0sXG4gIC8qKlxuICAgKiBHZXRzIHRoZSBsaXN0IG9mIGF2YWlsYWJsZSB2b2ljZSByZWdpb25zLlxuICAgKlxuICAgKiBAcmV0dXJucyBBIGNvbGxlY3Rpb24gb2Yge0BsaW5rIERpc2NvcmRWb2ljZVJlZ2lvbn0gb2JqZWN0cyBhc3NvcnRlZCBieSB2b2ljZSByZWdpb24gSUQuXG4gICAqL1xuICBhc3luYyBnZXRBdmFpbGFibGVWb2ljZVJlZ2lvbnMocmVzdDogUmVzdE1hbmFnZXIpOiBQcm9taXNlPERpc2NvcmRWb2ljZVJlZ2lvbltdPiB7XG4gICAgcmV0dXJuIGF3YWl0IHJlc3QuZ2V0PERpc2NvcmRWb2ljZVJlZ2lvbltdPihyZXN0LnJvdXRlcy5yZWdpb25zKCkpO1xuICB9LFxuICAvKipcbiAgICogR2V0cyBhIGJhbiBieSB1c2VyIElELlxuICAgKlxuICAgKiBAcGFyYW0gZ3VpbGRJZCAtIFRoZSBJRCBvZiB0aGUgZ3VpbGQgdG8gZ2V0IHRoZSBiYW4gZnJvbS5cbiAgICogQHBhcmFtIHVzZXJJZCAtIFRoZSBJRCBvZiB0aGUgdXNlciB0byBnZXQgdGhlIGJhbiBmb3IuXG4gICAqIEByZXR1cm5zIEFuIGluc3RhbmNlIG9mIHtAbGluayBEaXNjb3JkQmFufS5cbiAgICpcbiAgICogQHJlbWFya3NcbiAgICogUmVxdWlyZXMgdGhlIGBCQU5fTUVNQkVSU2AgcGVybWlzc2lvbi5cbiAgICpcbiAgICogQHNlZSB7QGxpbmsgaHR0cHM6Ly9kb2NzLmRpc2NvcmQuY29tL2RldmVsb3BlcnMvcmVzb3VyY2VzL2d1aWxkI2dldC1ndWlsZC1iYW59XG4gICAqL1xuICBhc3luYyBnZXRCYW4ocmVzdDogUmVzdE1hbmFnZXIsIGd1aWxkSWQ6IEJpZ1N0cmluZywgdXNlcklkOiBCaWdTdHJpbmcpOiBQcm9taXNlPERpc2NvcmRCYW4+IHtcbiAgICByZXR1cm4gYXdhaXQgcmVzdC5nZXQ8RGlzY29yZEJhbj4ocmVzdC5yb3V0ZXMuZ3VpbGRzLm1lbWJlcnMuYmFuKGd1aWxkSWQsIHVzZXJJZCkpO1xuICB9LFxuICAvKipcbiAgICogR2V0cyB0aGUgbGlzdCBvZiBiYW5zIGZvciBhIGd1aWxkLlxuICAgKlxuICAgKiBAcGFyYW0gZ3VpbGRJZCAtIFRoZSBJRCBvZiB0aGUgZ3VpbGQgdG8gZ2V0IHRoZSBsaXN0IG9mIGJhbnMgZm9yLlxuICAgKiBAcGFyYW0gb3B0aW9ucyAtIFRoZSBwYXJhbWV0ZXJzIGZvciB0aGUgZmV0Y2hpbmcgb2YgdGhlIGxpc3Qgb2YgYmFucy5cbiAgICogQHJldHVybnMgQSBjb2xsZWN0aW9uIG9mIHtAbGluayBEaXNjb3JkQmFufSBvYmplY3RzIGFzc29ydGVkIGJ5IHVzZXIgSUQuXG4gICAqXG4gICAqIEByZW1hcmtzXG4gICAqIFJlcXVpcmVzIHRoZSBgQkFOX01FTUJFUlNgIHBlcm1pc3Npb24uXG4gICAqXG4gICAqIFVzZXJzIGFyZSBvcmRlcmVkIGJ5IHRoZWlyIElEcyBpbiBfYXNjZW5kaW5nXyBvcmRlci5cbiAgICpcbiAgICogQHNlZSB7QGxpbmsgaHR0cHM6Ly9kb2NzLmRpc2NvcmQuY29tL2RldmVsb3BlcnMvcmVzb3VyY2VzL2d1aWxkI2dldC1ndWlsZC1iYW5zfVxuICAgKi9cbiAgYXN5bmMgZ2V0QmFucyhyZXN0OiBSZXN0TWFuYWdlciwgZ3VpbGRJZDogQmlnU3RyaW5nLCBvcHRpb25zPzogR2V0QmFucyk6IFByb21pc2U8RGlzY29yZEJhbltdPiB7XG4gICAgcmV0dXJuIGF3YWl0IHJlc3QuZ2V0PERpc2NvcmRCYW5bXT4ocmVzdC5yb3V0ZXMuZ3VpbGRzLm1lbWJlcnMuYmFucyhndWlsZElkLCBvcHRpb25zKSk7XG4gIH0sXG4gIC8qKlxuICAgKiBHZXRzIGEgY2hhbm5lbCBieSBpdHMgSUQuXG4gICAqXG4gICAqIEBwYXJhbSBjaGFubmVsSWQgLSBUaGUgSUQgb2YgdGhlIGNoYW5uZWwgdG8gZ2V0LlxuICAgKiBAcmV0dXJucyBBbiBpbnN0YW5jZSBvZiB7QGxpbmsgRGlzY29yZENoYW5uZWx9LlxuICAgKlxuICAgKiBAcmVtYXJrc1xuICAgKiBJZiB0aGUgY2hhbm5lbCBpcyBhIHRocmVhZCwgYSB7QGxpbmsgRGlzY29yZFRocmVhZE1lbWJlcn0gb2JqZWN0IGlzIGluY2x1ZGVkIGluIHRoZSByZXN1bHQuXG4gICAqXG4gICAqIEBzZWUge0BsaW5rIGh0dHBzOi8vZG9jcy5kaXNjb3JkLmNvbS9kZXZlbG9wZXJzL3Jlc291cmNlcy9jaGFubmVsI2dldC1jaGFubmVsfVxuICAgKi9cbiAgYXN5bmMgZ2V0Q2hhbm5lbChyZXN0OiBSZXN0TWFuYWdlciwgY2hhbm5lbElkOiBCaWdTdHJpbmcpOiBQcm9taXNlPERpc2NvcmRDaGFubmVsPiB7XG4gICAgcmV0dXJuIGF3YWl0IHJlc3QuZ2V0PERpc2NvcmRDaGFubmVsPihyZXN0LnJvdXRlcy5jaGFubmVscy5jaGFubmVsKGNoYW5uZWxJZCkpO1xuICB9LFxuICAvKipcbiAgICogR2V0cyB0aGUgbGlzdCBvZiBpbnZpdGVzIGZvciBhIGNoYW5uZWwuXG4gICAqXG4gICAqIEBwYXJhbSBjaGFubmVsSWQgLSBUaGUgSUQgb2YgdGhlIGNoYW5uZWwgdG8gZ2V0IHRoZSBpbnZpdGVzIG9mLlxuICAgKiBAcmV0dXJucyBBIGNvbGxlY3Rpb24gb2Yge0BsaW5rIERpc2NvcmRJbnZpdGVNZXRhZGF0YX0gb2JqZWN0cyBhc3NvcnRlZCBieSBpbnZpdGUgY29kZS5cbiAgICpcbiAgICogQHJlbWFya3NcbiAgICogUmVxdWlyZXMgdGhlIGBNQU5BR0VfQ0hBTk5FTFNgIHBlcm1pc3Npb24uXG4gICAqXG4gICAqIE9ubHkgdXNhYmxlIGZvciBndWlsZCBjaGFubmVscy5cbiAgICpcbiAgICogQHNlZSB7QGxpbmsgaHR0cHM6Ly9kb2NzLmRpc2NvcmQuY29tL2RldmVsb3BlcnMvcmVzb3VyY2VzL2NoYW5uZWwjZ2V0LWNoYW5uZWwtaW52aXRlc31cbiAgICovXG4gIGFzeW5jIGdldENoYW5uZWxJbnZpdGVzKHJlc3Q6IFJlc3RNYW5hZ2VyLCBjaGFubmVsSWQ6IEJpZ1N0cmluZyk6IFByb21pc2U8RGlzY29yZEludml0ZU1ldGFkYXRhW10+IHtcbiAgICByZXR1cm4gYXdhaXQgcmVzdC5nZXQ8RGlzY29yZEludml0ZU1ldGFkYXRhW10+KHJlc3Qucm91dGVzLmNoYW5uZWxzLmludml0ZXMoY2hhbm5lbElkKSk7XG4gIH0sXG4gIC8qKlxuICAgKiBHZXRzIHRoZSBsaXN0IG9mIGNoYW5uZWxzIGZvciBhIGd1aWxkLlxuICAgKlxuICAgKiBAcGFyYW0gZ3VpbGRJZCAtIFRoZSBJRCBvZiB0aGUgZ3VpbGQgdG8gZ2V0IHRoZSBjaGFubmVscyBvZi5cbiAgICogQHJldHVybnMgQSBjb2xsZWN0aW9uIG9mIHtAbGluayBEaXNjb3JkQ2hhbm5lbH0gb2JqZWN0cyBhc3NvcnRlZCBieSBjaGFubmVsIElELlxuICAgKlxuICAgKiBAcmVtYXJrc1xuICAgKiBFeGNsdWRlcyB0aHJlYWRzLlxuICAgKlxuICAgKiBAc2VlIHtAbGluayBodHRwczovL2RvY3MuZGlzY29yZC5jb20vZGV2ZWxvcGVycy9yZXNvdXJjZXMvZ3VpbGQjZ2V0LWd1aWxkLWNoYW5uZWxzfVxuICAgKi9cbiAgYXN5bmMgZ2V0Q2hhbm5lbHMocmVzdDogUmVzdE1hbmFnZXIsIGd1aWxkSWQ6IEJpZ1N0cmluZyk6IFByb21pc2U8RGlzY29yZENoYW5uZWxbXT4ge1xuICAgIHJldHVybiBhd2FpdCByZXN0LmdldDxEaXNjb3JkQ2hhbm5lbFtdPihyZXN0LnJvdXRlcy5ndWlsZHMuY2hhbm5lbHMoZ3VpbGRJZCkpO1xuICB9LFxuICAvKipcbiAgICogR2V0cyBhIGxpc3Qgb2Ygd2ViaG9va3MgZm9yIGEgY2hhbm5lbC5cbiAgICpcbiAgICogQHBhcmFtIGNoYW5uZWxJZCAtIFRoZSBJRCBvZiB0aGUgY2hhbm5lbCB3aGljaCB0byBnZXQgdGhlIHdlYmhvb2tzIG9mLlxuICAgKiBAcmV0dXJucyBBIGNvbGxlY3Rpb24gb2Yge0BsaW5rIERpc2NvcmRXZWJob29rfSBvYmplY3RzIGFzc29ydGVkIGJ5IHdlYmhvb2sgSUQuXG4gICAqXG4gICAqIEByZW1hcmtzXG4gICAqIFJlcXVpcmVzIHRoZSBgTUFOQUdFX1dFQkhPT0tTYCBwZXJtaXNzaW9uLlxuICAgKlxuICAgKiBAc2VlIHtAbGluayBodHRwczovL2RvY3MuZGlzY29yZC5jb20vZGV2ZWxvcGVycy9yZXNvdXJjZXMvd2ViaG9vayNnZXQtY2hhbm5lbC13ZWJob29rc31cbiAgICovXG4gIGFzeW5jIGdldENoYW5uZWxXZWJob29rcyhyZXN0OiBSZXN0TWFuYWdlciwgY2hhbm5lbElkOiBCaWdTdHJpbmcpOiBQcm9taXNlPERpc2NvcmRXZWJob29rW10+IHtcbiAgICByZXR1cm4gYXdhaXQgcmVzdC5nZXQ8RGlzY29yZFdlYmhvb2tbXT4ocmVzdC5yb3V0ZXMuY2hhbm5lbHMud2ViaG9va3MoY2hhbm5lbElkKSk7XG4gIH0sXG4gIC8qKlxuICAgKiBHZXRzIG9yIGNyZWF0ZXMgYSBETSBjaGFubmVsIHdpdGggYSB1c2VyLlxuICAgKlxuICAgKiBAcGFyYW0gdXNlcklkIC0gVGhlIElEIG9mIHRoZSB1c2VyIHRvIGNyZWF0ZSB0aGUgRE0gY2hhbm5lbCB3aXRoLlxuICAgKiBAcmV0dXJucyBBbiBpbnN0YW5jZSBvZiB7QGxpbmsgRGlzY29yZENoYW5uZWx9LlxuICAgKlxuICAgKiBAc2VlIHtAbGluayBodHRwczovL2RvY3MuZGlzY29yZC5jb20vZGV2ZWxvcGVycy9yZXNvdXJjZXMvdXNlciNjcmVhdGUtZG19XG4gICAqL1xuICBhc3luYyBnZXREbUNoYW5uZWwocmVzdDogUmVzdE1hbmFnZXIsIHVzZXJJZDogQmlnU3RyaW5nKTogUHJvbWlzZTxEaXNjb3JkQ2hhbm5lbD4ge1xuICAgIHJldHVybiBhd2FpdCByZXN0LnBvc3Q8RGlzY29yZENoYW5uZWw+KHJlc3Qucm91dGVzLmNoYW5uZWxzLmRtKCksIHtcbiAgICAgIGJvZHk6IHsgcmVjaXBpZW50SWQ6IHVzZXJJZCB9LFxuICAgIH0pO1xuICB9LFxuICAvKipcbiAgICogQ3JlYXRlIGEgbmV3IGdyb3VwIERNIGNoYW5uZWwgd2l0aCBtdWx0aXBsZSB1c2Vycy5cbiAgICpcbiAgICogQHBhcmFtIG9wdGlvbnMgLSBUaGUgb3B0aW9ucyBmb3IgY3JlYXRlIGEgbmV3IGdyb3VwIGRtXG4gICAqIEByZXR1cm5zIEFuIGluc3RhbmNlIG9mIHtAbGluayBEaXNjb3JkQ2hhbm5lbH0uXG4gICAqXG4gICAqIEByZW1hcmtzXG4gICAqIFRoZSBhY2Nlc3MgdG9rZW5zIHJlcXVpcmUgdG8gaGF2ZSB0aGUgYGdkbS5qb2luYCBzY29wZVxuICAgKlxuICAgKiBUaGlzIGVuZHBvaW50IGlzIGxpbWl0ZWQgdG8gMTAgYWN0aXZlIGdyb3VwIERNcy5cbiAgICpcbiAgICogRmlyZXMgYSBfQ2hhbm5lbCBjcmVhdGVfIGdhdGV3YXkgZXZlbnQuXG4gICAqXG4gICAqIEBzZWUge0BsaW5rIGh0dHBzOi8vZG9jcy5kaXNjb3JkLmNvbS9kZXZlbG9wZXJzL3Jlc291cmNlcy91c2VyI2NyZWF0ZS1ncm91cC1kbX1cbiAgICovXG4gIGFzeW5jIGdldEdyb3VwRG1DaGFubmVsKHJlc3Q6IFJlc3RNYW5hZ2VyLCBvcHRpb25zOiBDcmVhdGVHcm91cERtT3B0aW9ucyk6IFByb21pc2U8RGlzY29yZENoYW5uZWw+IHtcbiAgICByZXR1cm4gYXdhaXQgcmVzdC5wb3N0PERpc2NvcmRDaGFubmVsPihyZXN0LnJvdXRlcy5jaGFubmVscy5kbSgpLCB7XG4gICAgICBib2R5OiBvcHRpb25zLFxuICAgIH0pO1xuICB9LFxuICAvKipcbiAgICogR2V0cyBhbiBlbW9qaSBieSBpdHMgSUQuXG4gICAqXG4gICAqIEBwYXJhbSBndWlsZElkIC0gVGhlIElEIG9mIHRoZSBndWlsZCBmcm9tIHdoaWNoIHRvIGdldCB0aGUgZW1vamkuXG4gICAqIEBwYXJhbSBlbW9qaUlkIC0gVGhlIElEIG9mIHRoZSBlbW9qaSB0byBnZXQuXG4gICAqIEByZXR1cm5zIEFuIGluc3RhbmNlIG9mIHtAbGluayBEaXNjb3JkRW1vaml9LlxuICAgKlxuICAgKiBAcmVtYXJrc1xuICAgKiBJbmNsdWRlcyB0aGUgYHVzZXJgIGZpZWxkIGlmIHRoZSBib3QgaGFzIHRoZSBgTUFOQUdFX0dVSUxEX0VYUFJFU1NJT05TYCBwZXJtaXNzaW9uLFxuICAgKiBvciBpZiB0aGUgYm90IGNyZWF0ZWQgdGhlIGVtb2ppIGFuZCBoYXMgdGhlIGBDUkVBVEVfR1VJTERfRVhQUkVTU0lPTlNgIHBlcm1pc3Npb24uXG4gICAqXG4gICAqIEBzZWUge0BsaW5rIGh0dHBzOi8vZG9jcy5kaXNjb3JkLmNvbS9kZXZlbG9wZXJzL3Jlc291cmNlcy9lbW9qaSNnZXQtZ3VpbGQtZW1vaml9XG4gICAqL1xuICBhc3luYyBnZXRFbW9qaShyZXN0OiBSZXN0TWFuYWdlciwgZ3VpbGRJZDogQmlnU3RyaW5nLCBlbW9qaUlkOiBCaWdTdHJpbmcpOiBQcm9taXNlPERpc2NvcmRFbW9qaT4ge1xuICAgIHJldHVybiBhd2FpdCByZXN0LmdldDxEaXNjb3JkRW1vamk+KHJlc3Qucm91dGVzLmd1aWxkcy5lbW9qaShndWlsZElkLCBlbW9qaUlkKSk7XG4gIH0sXG4gIC8qKlxuICAgKiBHZXRzIGFuIGFwcGxpY2F0aW9uIGVtb2ppIGJ5IGl0cyBJRC5cbiAgICpcbiAgICogQHBhcmFtIGVtb2ppSWQgLSBUaGUgSUQgb2YgdGhlIGVtb2ppIHRvIGdldC5cbiAgICogQHJldHVybnMgQW4gaW5zdGFuY2Ugb2Yge0BsaW5rIERpc2NvcmRFbW9qaX0uXG4gICAqXG4gICAqIEByZW1hcmtzXG4gICAqIEFsd2F5cyBpbmNsdWRlcyB0aGUgYHVzZXJgIG9iamVjdCBmb3IgdGhlIHRlYW0gbWVtYmVyIHRoYXQgdXBsb2FkZWQgdGhlIGVtb2ppIGZyb20gdGhlIGFwcCdzIHNldHRpbmdzLCBvciBmb3IgdGhlIGJvdCB1c2VyIGlmIHVwbG9hZGVkIHVzaW5nIHRoZSBBUEkuXG4gICAqXG4gICAqIEBzZWUge0BsaW5rIGh0dHBzOi8vZG9jcy5kaXNjb3JkLmNvbS9kZXZlbG9wZXJzL3Jlc291cmNlcy9lbW9qaSNnZXQtYXBwbGljYXRpb24tZW1vaml9XG4gICAqL1xuICBhc3luYyBnZXRBcHBsaWNhdGlvbkVtb2ppKHJlc3Q6IFJlc3RNYW5hZ2VyLCBlbW9qaUlkOiBCaWdTdHJpbmcpOiBQcm9taXNlPERpc2NvcmRFbW9qaT4ge1xuICAgIHJldHVybiBhd2FpdCByZXN0LmdldDxEaXNjb3JkRW1vamk+KHJlc3Qucm91dGVzLmFwcGxpY2F0aW9uRW1vamkocmVzdC5hcHBsaWNhdGlvbklkLCBlbW9qaUlkKSk7XG4gIH0sXG4gIC8qKlxuICAgKiBHZXRzIHRoZSBsaXN0IG9mIGVtb2ppcyBmb3IgYSBndWlsZC5cbiAgICpcbiAgICogQHBhcmFtIGd1aWxkSWQgLSBUaGUgSUQgb2YgdGhlIGd1aWxkIHdoaWNoIHRvIGdldCB0aGUgZW1vamlzIG9mLlxuICAgKiBAcmV0dXJucyBBIGNvbGxlY3Rpb24gb2Yge0BsaW5rIERpc2NvcmRFbW9qaX0gb2JqZWN0cyBhc3NvcnRlZCBieSBlbW9qaSBJRC5cbiAgICpcbiAgICogQHJlbWFya3NcbiAgICogSW5jbHVkZXMgYHVzZXJgIGZpZWxkcyBpZiB0aGUgYm90IGhhcyB0aGUgYENSRUFURV9HVUlMRF9FWFBSRVNTSU9OU2Agb3IgYE1BTkFHRV9HVUlMRF9FWFBSRVNTSU9OU2AgcGVybWlzc2lvbi5cbiAgICpcbiAgICogQHNlZSB7QGxpbmsgaHR0cHM6Ly9kb2NzLmRpc2NvcmQuY29tL2RldmVsb3BlcnMvcmVzb3VyY2VzL2Vtb2ppI2xpc3QtZ3VpbGQtZW1vamlzfVxuICAgKi9cbiAgYXN5bmMgZ2V0RW1vamlzKHJlc3Q6IFJlc3RNYW5hZ2VyLCBndWlsZElkOiBCaWdTdHJpbmcpOiBQcm9taXNlPERpc2NvcmRFbW9qaVtdPiB7XG4gICAgcmV0dXJuIGF3YWl0IHJlc3QuZ2V0PERpc2NvcmRFbW9qaVtdPihyZXN0LnJvdXRlcy5ndWlsZHMuZW1vamlzKGd1aWxkSWQpKTtcbiAgfSxcbiAgLyoqXG4gICAqIEdldHMgdGhlIGxpc3Qgb2YgZW1vamlzIGZvciBhbiBhcHBsaWNhdGlvbi5cbiAgICpcbiAgICogQHJldHVybnMgQW4gb2JqZWN0IHdpdGggdGhlIGFycmF5IG9mIHtAbGluayBEaXNjb3JkRW1vaml9IG9iamVjdHMuXG4gICAqXG4gICAqIEByZW1hcmtzXG4gICAqIEFsd2F5cyBpbmNsdWRlcyB0aGUgYHVzZXJgIG9iamVjdCBmb3IgdGhlIHRlYW0gbWVtYmVyIHRoYXQgdXBsb2FkZWQgdGhlIGVtb2ppIGZyb20gdGhlIGFwcCdzIHNldHRpbmdzLCBvciBmb3IgdGhlIGJvdCB1c2VyIGlmIHVwbG9hZGVkIHVzaW5nIHRoZSBBUEkuXG4gICAqXG4gICAqIEBzZWUge0BsaW5rIGh0dHBzOi8vZG9jcy5kaXNjb3JkLmNvbS9kZXZlbG9wZXJzL3Jlc291cmNlcy9lbW9qaSNsaXN0LWFwcGxpY2F0aW9uLWVtb2ppc31cbiAgICovXG4gIGFzeW5jIGdldEFwcGxpY2F0aW9uRW1vamlzKHJlc3Q6IFJlc3RNYW5hZ2VyKTogUHJvbWlzZTx7IGl0ZW1zOiBEaXNjb3JkRW1vamlbXSB9PiB7XG4gICAgcmV0dXJuIGF3YWl0IHJlc3QuZ2V0PHsgaXRlbXM6IERpc2NvcmRFbW9qaVtdIH0+KHJlc3Qucm91dGVzLmFwcGxpY2F0aW9uRW1vamlzKHJlc3QuYXBwbGljYXRpb25JZCkpO1xuICB9LFxuICAvKipcbiAgICogR2V0cyBhIGZvbGxvdy11cCBtZXNzYWdlIHRvIGFuIGludGVyYWN0aW9uIGJ5IHRoZSBJRCBvZiB0aGUgbWVzc2FnZS5cbiAgICpcbiAgICogQHBhcmFtIHRva2VuIC0gVGhlIGludGVyYWN0aW9uIHRva2VuIHRvIHVzZSwgcHJvdmlkZWQgaW4gdGhlIG9yaWdpbmFsIGludGVyYWN0aW9uLlxuICAgKiBAcGFyYW0gbWVzc2FnZUlkIC0gVGhlIElEIG9mIHRoZSBtZXNzYWdlIHRvIGdldC5cbiAgICogQHJldHVybnMgQW4gaW5zdGFuY2Ugb2Yge0BsaW5rIERpc2NvcmRNZXNzYWdlfS5cbiAgICpcbiAgICogQHJlbWFya3NcbiAgICogVW5saWtlIGBnZXRNZXNzYWdlKClgLCB0aGlzIGVuZHBvaW50IGFsbG93cyB0aGUgYm90IHVzZXIgdG8gYWN0IHdpdGhvdXQ6XG4gICAqIC0gTmVlZGluZyB0byBiZSBhYmxlIHRvIHNlZSB0aGUgY29udGVudHMgb2YgdGhlIGNoYW5uZWwgdGhhdCB0aGUgbWVzc2FnZSBpcyBpbi4gKGBSRUFEX01FU1NBR0VTYCBwZXJtaXNzaW9uLilcbiAgICogLSBSZXF1aXJpbmcgdGhlIGBNRVNTQUdFX0NPTlRFTlRgIGludGVudC5cbiAgICpcbiAgICogRG9lcyBub3Qgc3VwcG9ydCBlcGhlbWVyYWwgZm9sbG93LXVwIG1lc3NhZ2VzIGR1ZSB0byB0aGVzZSBiZWluZyBzdGF0ZWxlc3MuXG4gICAqXG4gICAqIEBzZWUge0BsaW5rIGh0dHBzOi8vZG9jcy5kaXNjb3JkLmNvbS9kZXZlbG9wZXJzL2ludGVyYWN0aW9ucy9yZWNlaXZpbmctYW5kLXJlc3BvbmRpbmcjZ2V0LWZvbGxvd3VwLW1lc3NhZ2V9XG4gICAqL1xuICBhc3luYyBnZXRGb2xsb3d1cE1lc3NhZ2UocmVzdDogUmVzdE1hbmFnZXIsIHRva2VuOiBzdHJpbmcsIG1lc3NhZ2VJZDogQmlnU3RyaW5nKTogUHJvbWlzZTxEaXNjb3JkTWVzc2FnZT4ge1xuICAgIHJldHVybiBhd2FpdCByZXN0LmdldDxEaXNjb3JkTWVzc2FnZT4ocmVzdC5yb3V0ZXMuaW50ZXJhY3Rpb25zLnJlc3BvbnNlcy5tZXNzYWdlKHJlc3QuYXBwbGljYXRpb25JZCwgdG9rZW4sIG1lc3NhZ2VJZCksIHsgdW5hdXRob3JpemVkOiB0cnVlIH0pO1xuICB9LFxuICAvKiogR2V0IHRoZSBib3RzIEdhdGV3YXkgbWV0YWRhdGEgdGhhdCBjYW4gaGVscCBkdXJpbmcgdGhlIG9wZXJhdGlvbiBvZiBsYXJnZSBvciBzaGFyZGVkIGJvdHMuICovXG4gIGFzeW5jIGdldEdhdGV3YXlCb3QocmVzdDogUmVzdE1hbmFnZXIpOiBQcm9taXNlPERpc2NvcmRHZXRHYXRld2F5Qm90PiB7XG4gICAgcmV0dXJuIGF3YWl0IHJlc3QuZ2V0PERpc2NvcmRHZXRHYXRld2F5Qm90PihyZXN0LnJvdXRlcy5nYXRld2F5Qm90KCkpO1xuICB9LFxuICAvKipcbiAgICogR2V0cyBhIGdsb2JhbCBhcHBsaWNhdGlvbiBjb21tYW5kIGJ5IGl0cyBJRC5cbiAgICpcbiAgICogQHBhcmFtIGNvbW1hbmRJZCAtIFRoZSBJRCBvZiB0aGUgY29tbWFuZCB0byBnZXQuXG4gICAqIEByZXR1cm5zIEFuIGluc3RhbmNlIG9mIHtAbGluayBEaXNjb3JkQXBwbGljYXRpb25Db21tYW5kfS5cbiAgICpcbiAgICogQHNlZSB7QGxpbmsgaHR0cHM6Ly9kb2NzLmRpc2NvcmQuY29tL2RldmVsb3BlcnMvaW50ZXJhY3Rpb25zL2FwcGxpY2F0aW9uLWNvbW1hbmRzI2dldC1nbG9iYWwtYXBwbGljYXRpb24tY29tbWFuZH1cbiAgICovXG4gIGFzeW5jIGdldEdsb2JhbEFwcGxpY2F0aW9uQ29tbWFuZChyZXN0OiBSZXN0TWFuYWdlciwgY29tbWFuZElkOiBCaWdTdHJpbmcpOiBQcm9taXNlPERpc2NvcmRBcHBsaWNhdGlvbkNvbW1hbmQ+IHtcbiAgICByZXR1cm4gYXdhaXQgcmVzdC5nZXQ8RGlzY29yZEFwcGxpY2F0aW9uQ29tbWFuZD4ocmVzdC5yb3V0ZXMuaW50ZXJhY3Rpb25zLmNvbW1hbmRzLmNvbW1hbmQocmVzdC5hcHBsaWNhdGlvbklkLCBjb21tYW5kSWQpKTtcbiAgfSxcbiAgLyoqXG4gICAqIEdldHMgdGhlIGxpc3Qgb2YgeW91ciBib3QncyBnbG9iYWwgYXBwbGljYXRpb24gY29tbWFuZHMuXG4gICAqXG4gICAqIEBwYXJhbSBvcHRpb25zIC0gVGhlIHBhcmFtZXRlcnMgZm9yIHRoZSBmZXRjaGluZyBvZiBnbG9iYWwgYXBwbGljYXRpb24gY29tbWFuZHNcbiAgICogQHJldHVybnMgQSBjb2xsZWN0aW9uIG9mIHtAbGluayBEaXNjb3JkQXBwbGljYXRpb25Db21tYW5kfSBvYmplY3RzIGFzc29ydGVkIGJ5IGNvbW1hbmQgSUQuXG4gICAqXG4gICAqIEBzZWUge0BsaW5rIGh0dHBzOi8vZG9jcy5kaXNjb3JkLmNvbS9kZXZlbG9wZXJzL2ludGVyYWN0aW9ucy9hcHBsaWNhdGlvbi1jb21tYW5kcyNnZXQtZ2xvYmFsLWFwcGxpY2F0aW9uLWNvbW1hbmRzfVxuICAgKi9cbiAgYXN5bmMgZ2V0R2xvYmFsQXBwbGljYXRpb25Db21tYW5kcyhyZXN0OiBSZXN0TWFuYWdlciwgb3B0aW9ucz86IEdldEdsb2JhbEFwcGxpY2F0aW9uQ29tbWFuZHNPcHRpb25zKTogUHJvbWlzZTxEaXNjb3JkQXBwbGljYXRpb25Db21tYW5kW10+IHtcbiAgICByZXR1cm4gYXdhaXQgcmVzdC5nZXQ8RGlzY29yZEFwcGxpY2F0aW9uQ29tbWFuZFtdPihyZXN0LnJvdXRlcy5pbnRlcmFjdGlvbnMuY29tbWFuZHMuY29tbWFuZHMocmVzdC5hcHBsaWNhdGlvbklkLCBvcHRpb25zPy53aXRoTG9jYWxpemF0aW9ucykpO1xuICB9LFxuICAvKipcbiAgICogR2V0cyBhIGd1aWxkIGJ5IGl0cyBJRC5cbiAgICpcbiAgICogQHBhcmFtIGd1aWxkSWQgLSBUaGUgSUQgb2YgdGhlIGd1aWxkIHRvIGdldC5cbiAgICogQHBhcmFtIG9wdGlvbnMgLSBUaGUgcGFyYW1ldGVycyBmb3IgdGhlIGZldGNoaW5nIG9mIHRoZSBndWlsZC5cbiAgICogQHJldHVybnMgQW4gaW5zdGFuY2Ugb2Yge0BsaW5rIERpc2NvcmRHdWlsZH0uXG4gICAqXG4gICAqIEBzZWUge0BsaW5rIGh0dHBzOi8vZG9jcy5kaXNjb3JkLmNvbS9kZXZlbG9wZXJzL3Jlc291cmNlcy9ndWlsZCNnZXQtZ3VpbGR9XG4gICAqL1xuICBhc3luYyBnZXRHdWlsZChyZXN0OiBSZXN0TWFuYWdlciwgZ3VpbGRJZDogQmlnU3RyaW5nLCBvcHRpb25zPzogeyBjb3VudHM/OiBib29sZWFuIH0pOiBQcm9taXNlPERpc2NvcmRHdWlsZD4ge1xuICAgIG9wdGlvbnMgPz89IHsgY291bnRzOiB0cnVlIH07XG5cbiAgICByZXR1cm4gYXdhaXQgcmVzdC5nZXQ8RGlzY29yZEd1aWxkPihyZXN0LnJvdXRlcy5ndWlsZHMuZ3VpbGQoZ3VpbGRJZCwgb3B0aW9ucy5jb3VudHMpKTtcbiAgfSxcbiAgLyoqXG4gICAqIEdldCB0aGUgdXNlciBndWlsZHMuXG4gICAqXG4gICAqIEBwYXJhbSBiZWFyZXJUb2tlbiAtIFRoZSBhY2Nlc3MgdG9rZW4gb2YgdGhlIHVzZXIsIGlmIHVuc3BlY2lmaWVkIHRoZSBib3QgdG9rZW4gaXMgdXNlZCBpbnN0ZWFkXG4gICAqIEBwYXJhbSBvcHRpb25zIC0gVGhlIHBhcmFtZXRlcnMgZm9yIHRoZSBmZXRjaGluZyBvZiB0aGUgZ3VpbGQuXG4gICAqIEByZXR1cm5zIEFuIGFycmF5IG9mIHBhcnRpYWwge0BsaW5rIERpc2NvcmRHdWlsZH0uXG4gICAqXG4gICAqIEByZW1hcmtzXG4gICAqIElmIHVzZWQgd2l0aCBhbiBhY2Nlc3MgdG9rZW4sIHRoZSB0b2tlbiBuZWVkcyB0byBoYXZlIHRoZSBgZ3VpbGRzYCBzY29wZVxuICAgKlxuICAgKiBAc2VlIHtAbGluayBodHRwczovL2RvY3MuZGlzY29yZC5jb20vZGV2ZWxvcGVycy9yZXNvdXJjZXMvdXNlciNnZXQtY3VycmVudC11c2VyLWd1aWxkc31cbiAgICovXG4gIGFzeW5jIGdldEd1aWxkcyhyZXN0OiBSZXN0TWFuYWdlciwgYmVhcmVyVG9rZW4/OiBzdHJpbmcsIG9wdGlvbnM/OiBHZXRVc2VyR3VpbGRzKTogUHJvbWlzZTxQYXJ0aWFsPERpc2NvcmRHdWlsZD5bXT4ge1xuICAgIGNvbnN0IG1ha2VSZXF1ZXN0T3B0aW9uczogTWFrZVJlcXVlc3RPcHRpb25zIHwgdW5kZWZpbmVkID0gYmVhcmVyVG9rZW5cbiAgICAgID8ge1xuICAgICAgICAgIGhlYWRlcnM6IHtcbiAgICAgICAgICAgIGF1dGhvcml6YXRpb246IGBCZWFyZXIgJHtiZWFyZXJUb2tlbn1gLFxuICAgICAgICAgIH0sXG4gICAgICAgICAgdW5hdXRob3JpemVkOiB0cnVlLFxuICAgICAgICB9XG4gICAgICA6IHVuZGVmaW5lZDtcblxuICAgIHJldHVybiBhd2FpdCByZXN0LmdldDxQYXJ0aWFsPERpc2NvcmRHdWlsZD5bXT4ocmVzdC5yb3V0ZXMuZ3VpbGRzLnVzZXJHdWlsZHMob3B0aW9ucyksIG1ha2VSZXF1ZXN0T3B0aW9ucyk7XG4gIH0sXG4gIC8qKlxuICAgKiBHZXRzIGEgZ3VpbGQgYXBwbGljYXRpb24gY29tbWFuZCBieSBpdHMgSUQuXG4gICAqXG4gICAqIEBwYXJhbSBndWlsZElkIC0gVGhlIElEIG9mIHRoZSBndWlsZCB0aGUgY29tbWFuZCBpcyByZWdpc3RlcmVkIGluLlxuICAgKiBAcGFyYW0gY29tbWFuZElkIC0gVGhlIElEIG9mIHRoZSBjb21tYW5kIHRvIGdldC5cbiAgICogQHJldHVybnMgQW4gaW5zdGFuY2Ugb2Yge0BsaW5rIERpc2NvcmRBcHBsaWNhdGlvbkNvbW1hbmR9LlxuICAgKlxuICAgKiBAc2VlIHtAbGluayBodHRwczovL2RvY3MuZGlzY29yZC5jb20vZGV2ZWxvcGVycy9pbnRlcmFjdGlvbnMvYXBwbGljYXRpb24tY29tbWFuZHMjZ2V0LWd1aWxkLWFwcGxpY2F0aW9uLWNvbW1hbmR9XG4gICAqL1xuICBhc3luYyBnZXRHdWlsZEFwcGxpY2F0aW9uQ29tbWFuZChyZXN0OiBSZXN0TWFuYWdlciwgY29tbWFuZElkOiBCaWdTdHJpbmcsIGd1aWxkSWQ6IEJpZ1N0cmluZyk6IFByb21pc2U8RGlzY29yZEFwcGxpY2F0aW9uQ29tbWFuZD4ge1xuICAgIHJldHVybiBhd2FpdCByZXN0LmdldDxEaXNjb3JkQXBwbGljYXRpb25Db21tYW5kPihyZXN0LnJvdXRlcy5pbnRlcmFjdGlvbnMuY29tbWFuZHMuZ3VpbGRzLm9uZShyZXN0LmFwcGxpY2F0aW9uSWQsIGd1aWxkSWQsIGNvbW1hbmRJZCkpO1xuICB9LFxuICAvKipcbiAgICogR2V0cyB0aGUgbGlzdCBvZiBhcHBsaWNhdGlvbiBjb21tYW5kcyByZWdpc3RlcmVkIGJ5IHlvdXIgYm90IGluIGEgZ3VpbGQuXG4gICAqXG4gICAqIEBwYXJhbSBndWlsZElkIC0gVGhlIElEIG9mIHRoZSBndWlsZCB0aGUgY29tbWFuZHMgYXJlIHJlZ2lzdGVyZWQgaW4uXG4gICAqIEBwYXJhbSBvcHRpb25zIC0gVGhlIHBhcmFtZXRlcnMgZm9yIHRoZSBmZXRjaGluZyBvZiBndWlsZCBhcHBsaWNhdGlvbiBjb21tYW5kc1xuICAgKiBAcmV0dXJucyBBIGNvbGxlY3Rpb24gb2Yge0BsaW5rIERpc2NvcmRBcHBsaWNhdGlvbkNvbW1hbmR9IG9iamVjdHMgYXNzb3J0ZWQgYnkgY29tbWFuZCBJRC5cbiAgICpcbiAgICogQHNlZSB7QGxpbmsgaHR0cHM6Ly9kb2NzLmRpc2NvcmQuY29tL2RldmVsb3BlcnMvaW50ZXJhY3Rpb25zL2FwcGxpY2F0aW9uLWNvbW1hbmRzI2dldC1nbG9iYWwtYXBwbGljYXRpb24tY29tbWFuZHNzfVxuICAgKi9cbiAgYXN5bmMgZ2V0R3VpbGRBcHBsaWNhdGlvbkNvbW1hbmRzKFxuICAgIHJlc3Q6IFJlc3RNYW5hZ2VyLFxuICAgIGd1aWxkSWQ6IEJpZ1N0cmluZyxcbiAgICBvcHRpb25zPzogR2V0R3VpbGRBcHBsaWNhdGlvbkNvbW1hbmRzT3B0aW9ucyxcbiAgKTogUHJvbWlzZTxEaXNjb3JkQXBwbGljYXRpb25Db21tYW5kW10+IHtcbiAgICByZXR1cm4gYXdhaXQgcmVzdC5nZXQ8RGlzY29yZEFwcGxpY2F0aW9uQ29tbWFuZFtdPihcbiAgICAgIHJlc3Qucm91dGVzLmludGVyYWN0aW9ucy5jb21tYW5kcy5ndWlsZHMuYWxsKHJlc3QuYXBwbGljYXRpb25JZCwgZ3VpbGRJZCwgb3B0aW9ucz8ud2l0aExvY2FsaXphdGlvbnMpLFxuICAgICk7XG4gIH0sXG4gIC8qKlxuICAgKiBHZXRzIHRoZSBwcmV2aWV3IG9mIGEgZ3VpbGQgYnkgYSBndWlsZCdzIElELlxuICAgKlxuICAgKiBAcGFyYW0gZ3VpbGRJZCAtIFRoZSBJRCBvZiB0aGUgZ3VpbGQgdG8gZ2V0IHRoZSBwcmV2aWV3IG9mLlxuICAgKiBAcmV0dXJucyBBbiBpbnN0YW5jZSBvZiB7QGxpbmsgRGlzY29yZEd1aWxkUHJldmlld30uXG4gICAqXG4gICAqIEByZW1hcmtzXG4gICAqIElmIHRoZSBib3QgdXNlciBpcyBub3QgaW4gdGhlIGd1aWxkLCB0aGUgZ3VpbGQgbXVzdCBiZSBkaXNjb3ZlcmFibGUuXG4gICAqXG4gICAqIEBzZWUge0BsaW5rIGh0dHBzOi8vZG9jcy5kaXNjb3JkLmNvbS9kZXZlbG9wZXJzL3Jlc291cmNlcy9ndWlsZCNnZXQtZ3VpbGQtcHJldmlld31cbiAgICovXG4gIGFzeW5jIGdldEd1aWxkUHJldmlldyhyZXN0OiBSZXN0TWFuYWdlciwgZ3VpbGRJZDogQmlnU3RyaW5nKTogUHJvbWlzZTxEaXNjb3JkR3VpbGRQcmV2aWV3PiB7XG4gICAgcmV0dXJuIGF3YWl0IHJlc3QuZ2V0PERpc2NvcmRHdWlsZFByZXZpZXc+KHJlc3Qucm91dGVzLmd1aWxkcy5wcmV2aWV3KGd1aWxkSWQpKTtcbiAgfSxcbiAgLyoqXG4gICAqIFJldHVybnMgYSBzdGlja2VyIG9iamVjdCBmb3IgdGhlIGdpdmVuIGd1aWxkIGFuZCBzdGlja2VyIElEcy5cbiAgICpcbiAgICogQHBhcmFtIGd1aWxkSWQgVGhlIElEIG9mIHRoZSBndWlsZCB0byBnZXRcbiAgICogQHBhcmFtIHN0aWNrZXJJZCBUaGUgSUQgb2YgdGhlIHN0aWNrZXIgdG8gZ2V0XG4gICAqIEByZXR1cm4gQSB7QGxpbmsgRGlzY29yZFN0aWNrZXJ9XG4gICAqXG4gICAqIEByZW1hcmtzIEluY2x1ZGVzIHRoZSB1c2VyIGZpZWxkIGlmIHRoZSBib3QgaGFzIHRoZSBgQ1JFQVRFX0dVSUxEX0VYUFJFU1NJT05TYCBvciBgTUFOQUdFX0dVSUxEX0VYUFJFU1NJT05TYCBwZXJtaXNzaW9uLlxuICAgKlxuICAgKiBAc2VlIHtAbGluayBodHRwczovL2RvY3MuZGlzY29yZC5jb20vZGV2ZWxvcGVycy9yZXNvdXJjZXMvc3RpY2tlciNnZXQtZ3VpbGQtc3RpY2tlcn1cbiAgICovXG4gIGFzeW5jIGdldEd1aWxkU3RpY2tlcihyZXN0OiBSZXN0TWFuYWdlciwgZ3VpbGRJZDogQmlnU3RyaW5nLCBzdGlja2VySWQ6IEJpZ1N0cmluZyk6IFByb21pc2U8RGlzY29yZFN0aWNrZXI+IHtcbiAgICByZXR1cm4gYXdhaXQgcmVzdC5nZXQ8RGlzY29yZFN0aWNrZXI+KHJlc3Qucm91dGVzLmd1aWxkcy5zdGlja2VyKGd1aWxkSWQsIHN0aWNrZXJJZCkpO1xuICB9LFxuICAvKipcbiAgICogUmV0dXJucyBhbiBhcnJheSBvZiBzdGlja2VyIG9iamVjdHMgZm9yIHRoZSBnaXZlbiBndWlsZC5cbiAgICpcbiAgICogQHBhcmFtIGd1aWxkSWQgVGhlIElEIG9mIHRoZSBndWlsZCB0byBnZXRcbiAgICogQHJldHVybnMgQSBjb2xsZWN0aW9uIG9mIHtAbGluayBEaXNjb3JkU3RpY2tlcn0gb2JqZWN0cyBhc3NvcnRlZCBieSBzdGlja2VyIElELlxuICAgKlxuICAgKiBAcmVtYXJrcyBJbmNsdWRlcyB1c2VyIGZpZWxkcyBpZiB0aGUgYm90IGhhcyB0aGUgYENSRUFURV9HVUlMRF9FWFBSRVNTSU9OU2Agb3IgYE1BTkFHRV9HVUlMRF9FWFBSRVNTSU9OU2AgcGVybWlzc2lvbi5cbiAgICpcbiAgICogQHNlZSB7QGxpbmsgaHR0cHM6Ly9kb2NzLmRpc2NvcmQuY29tL2RldmVsb3BlcnMvcmVzb3VyY2VzL3N0aWNrZXIjbGlzdC1ndWlsZC1zdGlja2Vyc31cbiAgICovXG4gIGFzeW5jIGdldEd1aWxkU3RpY2tlcnMocmVzdDogUmVzdE1hbmFnZXIsIGd1aWxkSWQ6IEJpZ1N0cmluZyk6IFByb21pc2U8RGlzY29yZFN0aWNrZXJbXT4ge1xuICAgIHJldHVybiBhd2FpdCByZXN0LmdldDxEaXNjb3JkU3RpY2tlcltdPihyZXN0LnJvdXRlcy5ndWlsZHMuc3RpY2tlcnMoZ3VpbGRJZCkpO1xuICB9LFxuICAvKipcbiAgICogR2V0cyBhIHRlbXBsYXRlIGJ5IGl0cyBjb2RlLlxuICAgKlxuICAgKiBAcGFyYW0gdGVtcGxhdGVDb2RlIC0gVGhlIGNvZGUgb2YgdGhlIHRlbXBsYXRlIHRvIGdldC5cbiAgICogQHJldHVybnMgQW4gaW5zdGFuY2Ugb2Yge0BsaW5rIERpc2NvcmRUZW1wbGF0ZX0uXG4gICAqXG4gICAqIEByZW1hcmtzXG4gICAqIFJlcXVpcmVzIHRoZSBgTUFOQUdFX0dVSUxEYCBwZXJtaXNzaW9uLlxuICAgKlxuICAgKiBAc2VlIHtAbGluayBodHRwczovL2RvY3MuZGlzY29yZC5jb20vZGV2ZWxvcGVycy9yZXNvdXJjZXMvZ3VpbGQtdGVtcGxhdGUjZ2V0LWd1aWxkLXRlbXBsYXRlfVxuICAgKi9cbiAgYXN5bmMgZ2V0R3VpbGRUZW1wbGF0ZShyZXN0OiBSZXN0TWFuYWdlciwgdGVtcGxhdGVDb2RlOiBzdHJpbmcpOiBQcm9taXNlPERpc2NvcmRUZW1wbGF0ZT4ge1xuICAgIHJldHVybiBhd2FpdCByZXN0LmdldDxEaXNjb3JkVGVtcGxhdGU+KHJlc3Qucm91dGVzLmd1aWxkcy50ZW1wbGF0ZXMuY29kZSh0ZW1wbGF0ZUNvZGUpKTtcbiAgfSxcbiAgLyoqXG4gICAqIEdldHMgdGhlIGxpc3Qgb2YgdGVtcGxhdGVzIGZvciBhIGd1aWxkLlxuICAgKlxuICAgKiBAcGFyYW0gZ3VpbGRJZCAtIFRoZSBJRCBvZiB0aGUgZ3VpbGQgdG8gZ2V0IHRoZSBsaXN0IG9mIHRlbXBsYXRlcyBmb3IuXG4gICAqIEByZXR1cm5zIEEgY29sbGVjdGlvbiBvZiB7QGxpbmsgRGlzY29yZFRlbXBsYXRlfSBvYmplY3RzIGFzc29ydGVkIGJ5IHRlbXBsYXRlIGNvZGUuXG4gICAqXG4gICAqIEByZW1hcmtzXG4gICAqIFJlcXVpcmVzIHRoZSBgTUFOQUdFX0dVSUxEYCBwZXJtaXNzaW9uLlxuICAgKlxuICAgKiBAc2VlIHtAbGluayBodHRwczovL2RvY3MuZGlzY29yZC5jb20vZGV2ZWxvcGVycy9yZXNvdXJjZXMvZ3VpbGQtdGVtcGxhdGUjZ2V0LWd1aWxkLXRlbXBsYXRlc31cbiAgICovXG4gIGFzeW5jIGdldEd1aWxkVGVtcGxhdGVzKHJlc3Q6IFJlc3RNYW5hZ2VyLCBndWlsZElkOiBCaWdTdHJpbmcpOiBQcm9taXNlPERpc2NvcmRUZW1wbGF0ZVtdPiB7XG4gICAgcmV0dXJuIGF3YWl0IHJlc3QuZ2V0PERpc2NvcmRUZW1wbGF0ZVtdPihyZXN0LnJvdXRlcy5ndWlsZHMudGVtcGxhdGVzLmFsbChndWlsZElkKSk7XG4gIH0sXG4gIC8qKlxuICAgKiBHZXRzIHRoZSBsaXN0IG9mIHdlYmhvb2tzIGZvciBhIGd1aWxkLlxuICAgKlxuICAgKiBAcGFyYW0gZ3VpbGRJZCAtIFRoZSBJRCBvZiB0aGUgZ3VpbGQgdG8gZ2V0IHRoZSBsaXN0IG9mIHdlYmhvb2tzIGZvci5cbiAgICogQHJldHVybnMgQSBjb2xsZWN0aW9uIG9mIHtAbGluayBEaXNjb3JkV2ViaG9va30gb2JqZWN0cyBhc3NvcnRlZCBieSB3ZWJob29rIElELlxuICAgKlxuICAgKiBAcmVtYXJrc1xuICAgKiBSZXF1aXJlcyB0aGUgYE1BTkFHRV9XRUJIT09LU2AgcGVybWlzc2lvbi5cbiAgICpcbiAgICogQHNlZSB7QGxpbmsgaHR0cHM6Ly9kb2NzLmRpc2NvcmQuY29tL2RldmVsb3BlcnMvcmVzb3VyY2VzL3dlYmhvb2sjZ2V0LWd1aWxkLXdlYmhvb2tzfVxuICAgKi9cbiAgYXN5bmMgZ2V0R3VpbGRXZWJob29rcyhyZXN0OiBSZXN0TWFuYWdlciwgZ3VpbGRJZDogQmlnU3RyaW5nKTogUHJvbWlzZTxEaXNjb3JkV2ViaG9va1tdPiB7XG4gICAgcmV0dXJuIGF3YWl0IHJlc3QuZ2V0PERpc2NvcmRXZWJob29rW10+KHJlc3Qucm91dGVzLmd1aWxkcy53ZWJob29rcyhndWlsZElkKSk7XG4gIH0sXG4gIC8qKlxuICAgKiBHZXRzIHRoZSBsaXN0IG9mIGludGVncmF0aW9ucyBhdHRhY2hlZCB0byBhIGd1aWxkLlxuICAgKlxuICAgKiBAcGFyYW0gZ3VpbGRJZCAtIFRoZSBJRCBvZiB0aGUgZ3VpbGQgdG8gZ2V0IHRoZSBsaXN0IG9mIGludGVncmF0aW9ucyBmcm9tLlxuICAgKiBAcmV0dXJucyBBIGNvbGxlY3Rpb24gb2Yge0BsaW5rIERpc2NvcmRJbnRlZ3JhdGlvbn0gb2JqZWN0cyBhc3NvcnRlZCBieSBpbnRlZ3JhdGlvbiBJRC5cbiAgICpcbiAgICogQHJlbWFya3NcbiAgICogUmVxdWlyZXMgdGhlIGBNQU5BR0VfR1VJTERgIHBlcm1pc3Npb24uXG4gICAqXG4gICAqIEBzZWUge0BsaW5rIGh0dHBzOi8vZG9jcy5kaXNjb3JkLmNvbS9kZXZlbG9wZXJzL3Jlc291cmNlcy9ndWlsZCNnZXQtZ3VpbGQtaW50ZWdyYXRpb25zfVxuICAgKi9cbiAgYXN5bmMgZ2V0SW50ZWdyYXRpb25zKHJlc3Q6IFJlc3RNYW5hZ2VyLCBndWlsZElkOiBCaWdTdHJpbmcpOiBQcm9taXNlPERpc2NvcmRJbnRlZ3JhdGlvbltdPiB7XG4gICAgcmV0dXJuIGF3YWl0IHJlc3QuZ2V0PERpc2NvcmRJbnRlZ3JhdGlvbltdPihyZXN0LnJvdXRlcy5ndWlsZHMuaW50ZWdyYXRpb25zKGd1aWxkSWQpKTtcbiAgfSxcbiAgLyoqXG4gICAqIEdldHMgYW4gaW52aXRlIHRvIGEgY2hhbm5lbCBieSBpdHMgaW52aXRlIGNvZGUuXG4gICAqXG4gICAqIEBwYXJhbSBpbnZpdGVDb2RlIC0gVGhlIGludml0ZSBjb2RlIG9mIHRoZSBpbnZpdGUgdG8gZ2V0LlxuICAgKiBAcGFyYW0gb3B0aW9ucyAtIFRoZSBwYXJhbWV0ZXJzIGZvciB0aGUgZmV0Y2hpbmcgb2YgdGhlIGludml0ZS5cbiAgICogQHJldHVybnMgQW4gaW5zdGFuY2Ugb2Yge0BsaW5rIERpc2NvcmRJbnZpdGVNZXRhZGF0YX0uXG4gICAqXG4gICAqIEBzZWUge0BsaW5rIGh0dHBzOi8vZG9jcy5kaXNjb3JkLmNvbS9kZXZlbG9wZXJzL3Jlc291cmNlcy9pbnZpdGUjZ2V0LWludml0ZX1cbiAgICovXG4gIGFzeW5jIGdldEludml0ZShyZXN0OiBSZXN0TWFuYWdlciwgaW52aXRlQ29kZTogc3RyaW5nLCBvcHRpb25zPzogR2V0SW52aXRlKTogUHJvbWlzZTxEaXNjb3JkSW52aXRlTWV0YWRhdGE+IHtcbiAgICByZXR1cm4gYXdhaXQgcmVzdC5nZXQ8RGlzY29yZEludml0ZU1ldGFkYXRhPihyZXN0LnJvdXRlcy5ndWlsZHMuaW52aXRlKGludml0ZUNvZGUsIG9wdGlvbnMpKTtcbiAgfSxcbiAgLyoqXG4gICAqIEdldHMgdGhlIGxpc3Qgb2YgaW52aXRlcyBmb3IgYSBndWlsZC5cbiAgICpcbiAgICogQHBhcmFtIGd1aWxkSWQgLSBUaGUgSUQgb2YgdGhlIGd1aWxkIHRvIGdldCB0aGUgaW52aXRlcyBmcm9tLlxuICAgKiBAcmV0dXJucyBBIGNvbGxlY3Rpb24gb2Yge0BsaW5rIERpc2NvcmRJbnZpdGVNZXRhZGF0YX0gb2JqZWN0cyBhc3NvcnRlZCBieSBpbnZpdGUgY29kZS5cbiAgICpcbiAgICogQHJlbWFya3NcbiAgICogUmVxdWlyZXMgdGhlIGBNQU5BR0VfR1VJTERgIG9yIGBWSUVXX0FVRElUX0xPR2AgcGVybWlzc2lvbi5cbiAgICpcbiAgICogQHNlZSB7QGxpbmsgaHR0cHM6Ly9kb2NzLmRpc2NvcmQuY29tL2RldmVsb3BlcnMvcmVzb3VyY2VzL2ludml0ZSNnZXQtaW52aXRlc31cbiAgICovXG4gIGFzeW5jIGdldEludml0ZXMocmVzdDogUmVzdE1hbmFnZXIsIGd1aWxkSWQ6IEJpZ1N0cmluZyk6IFByb21pc2U8RGlzY29yZEludml0ZU1ldGFkYXRhW10+IHtcbiAgICByZXR1cm4gYXdhaXQgcmVzdC5nZXQ8RGlzY29yZEludml0ZU1ldGFkYXRhW10+KHJlc3Qucm91dGVzLmd1aWxkcy5pbnZpdGVzKGd1aWxkSWQpKTtcbiAgfSxcbiAgLyoqXG4gICAqIEdldHMgYSBtZXNzYWdlIGZyb20gYSBjaGFubmVsIGJ5IHRoZSBJRCBvZiB0aGUgbWVzc2FnZS5cbiAgICpcbiAgICogQHBhcmFtIGNoYW5uZWxJZCAtIFRoZSBJRCBvZiB0aGUgY2hhbm5lbCBmcm9tIHdoaWNoIHRvIGdldCB0aGUgbWVzc2FnZS5cbiAgICogQHBhcmFtIG1lc3NhZ2VJZCAtIFRoZSBJRCBvZiB0aGUgbWVzc2FnZSB0byBnZXQuXG4gICAqIEByZXR1cm5zIEFuIGluc3RhbmNlIG9mIHtAbGluayBEaXNjb3JkTWVzc2FnZX0uXG4gICAqXG4gICAqIEByZW1hcmtzXG4gICAqIFJlcXVpcmVzIHRoYXQgdGhlIGJvdCB1c2VyIGJlIGFibGUgdG8gc2VlIHRoZSBjb250ZW50cyBvZiB0aGUgY2hhbm5lbCBpbiB3aGljaCB0aGUgbWVzc2FnZSB3YXMgcG9zdGVkLlxuICAgKlxuICAgKiBJZiBnZXR0aW5nIGEgbWVzc2FnZSBmcm9tIGEgZ3VpbGQgY2hhbm5lbDpcbiAgICogLSBSZXF1aXJlcyB0aGUgYFJFQURfTUVTU0FHRV9ISVNUT1JZYCBwZXJtaXNzaW9uLlxuICAgKlxuICAgKiBAc2VlIHtAbGluayBodHRwczovL2RvY3MuZGlzY29yZC5jb20vZGV2ZWxvcGVycy9yZXNvdXJjZXMvY2hhbm5lbCNnZXQtY2hhbm5lbC1tZXNzYWdlfVxuICAgKi9cbiAgYXN5bmMgZ2V0TWVzc2FnZShyZXN0OiBSZXN0TWFuYWdlciwgY2hhbm5lbElkOiBCaWdTdHJpbmcsIG1lc3NhZ2VJZDogQmlnU3RyaW5nKTogUHJvbWlzZTxEaXNjb3JkTWVzc2FnZT4ge1xuICAgIHJldHVybiBhd2FpdCByZXN0LmdldDxEaXNjb3JkTWVzc2FnZT4ocmVzdC5yb3V0ZXMuY2hhbm5lbHMubWVzc2FnZShjaGFubmVsSWQsIG1lc3NhZ2VJZCkpO1xuICB9LFxuICAvKipcbiAgICogR2V0cyBtdWx0aXBsZSBtZXNzYWdlcyBmcm9tIGEgY2hhbm5lbC5cbiAgICpcbiAgICogQHBhcmFtIGNoYW5uZWxJZCAtIFRoZSBJRCBvZiB0aGUgY2hhbm5lbCBmcm9tIHdoaWNoIHRvIGdldCB0aGUgbWVzc2FnZXMuXG4gICAqIEBwYXJhbSBvcHRpb25zIC0gVGhlIHBhcmFtZXRlcnMgZm9yIHRoZSBmZXRjaGluZyBvZiB0aGUgbWVzc2FnZXMuXG4gICAqIEByZXR1cm5zIFJldHVybnMgYW4gYXJyYXkgb2Yge0BsaW5rIERpc2NvcmRNZXNzYWdlfSBvYmplY3RzIGZyb20gbmV3ZXN0IHRvIG9sZGVzdCBvbiBzdWNjZXNzLlxuICAgKlxuICAgKiBAcmVtYXJrc1xuICAgKiBSZXF1aXJlcyB0aGF0IHRoZSBib3QgdXNlciBiZSBhYmxlIHRvIHNlZSB0aGUgY29udGVudHMgb2YgdGhlIGNoYW5uZWwgaW4gd2hpY2ggdGhlIG1lc3NhZ2VzIHdlcmUgcG9zdGVkLlxuICAgKlxuICAgKiBJZiBnZXR0aW5nIGEgbWVzc2FnZXMgZnJvbSBhIGd1aWxkIGNoYW5uZWw6XG4gICAqIC0gUmVxdWlyZXMgdGhlIGBSRUFEX01FU1NBR0VfSElTVE9SWWAgcGVybWlzc2lvbi5cbiAgICpcbiAgICogQHNlZSB7QGxpbmsgaHR0cHM6Ly9kb2NzLmRpc2NvcmQuY29tL2RldmVsb3BlcnMvcmVzb3VyY2VzL2NoYW5uZWwjZ2V0LWNoYW5uZWwtbWVzc2FnZXN9XG4gICAqL1xuICBhc3luYyBnZXRNZXNzYWdlcyhyZXN0OiBSZXN0TWFuYWdlciwgY2hhbm5lbElkOiBCaWdTdHJpbmcsIG9wdGlvbnM/OiBHZXRNZXNzYWdlc09wdGlvbnMpOiBQcm9taXNlPERpc2NvcmRNZXNzYWdlW10+IHtcbiAgICByZXR1cm4gYXdhaXQgcmVzdC5nZXQ8RGlzY29yZE1lc3NhZ2VbXT4ocmVzdC5yb3V0ZXMuY2hhbm5lbHMubWVzc2FnZXMoY2hhbm5lbElkLCBvcHRpb25zKSk7XG4gIH0sXG4gIC8qKlxuICAgKiBTZWFyY2ggbWVzc2FnZXMgaW4gYSBndWlsZC5cbiAgICpcbiAgICogQHJlbWFya3NcbiAgICogUmVxdWlyZXMgYFJFQURfTUVTU0FHRV9ISVNUT1JZYCBhbmQgaXMgcmVzdHJpY3RlZCBieSB0aGUgYE1FU1NBR0VfQ09OVEVOVGAgaW50ZW50LlxuICAgKlxuICAgKiBAc2VlIHtAbGluayBodHRwczovL2RvY3MuZGlzY29yZC5jb20vZGV2ZWxvcGVycy9yZXNvdXJjZXMvbWVzc2FnZSNzZWFyY2gtZ3VpbGQtbWVzc2FnZXN9XG4gICAqL1xuICBhc3luYyBzZWFyY2hHdWlsZE1lc3NhZ2VzKFxuICAgIHJlc3Q6IFJlc3RNYW5hZ2VyLFxuICAgIGd1aWxkSWQ6IEJpZ1N0cmluZyxcbiAgICBvcHRpb25zPzogU2VhcmNoR3VpbGRNZXNzYWdlc09wdGlvbnMsXG4gICk6IFByb21pc2U8RGlzY29yZFNlYXJjaEd1aWxkTWVzc2FnZXMgfCBEaXNjb3JkU2VhcmNoR3VpbGRNZXNzYWdlc0luZGV4aW5nPiB7XG4gICAgcmV0dXJuIGF3YWl0IHJlc3QuZ2V0PERpc2NvcmRTZWFyY2hHdWlsZE1lc3NhZ2VzIHwgRGlzY29yZFNlYXJjaEd1aWxkTWVzc2FnZXNJbmRleGluZz4ocmVzdC5yb3V0ZXMuZ3VpbGRzLm1lc3NhZ2VzU2VhcmNoKGd1aWxkSWQsIG9wdGlvbnMpKTtcbiAgfSxcbiAgLyoqXG4gICAqIFJldHVybnMgYSBzdGlja2VyIHBhY2sgZm9yIHRoZSBnaXZlbiBJRC5cbiAgICpcbiAgICogQHJldHVybnMgQSB7QGxpbmsgRGlzY29yZFN0aWNrZXJQYWNrfSBvYmplY3QuXG4gICAqXG4gICAqIEBzZWUge0BsaW5rIGh0dHBzOi8vZG9jcy5kaXNjb3JkLmNvbS9kZXZlbG9wZXJzL3Jlc291cmNlcy9zdGlja2VyI2dldC1zdGlja2VyLXBhY2t9XG4gICAqL1xuICBhc3luYyBnZXRTdGlja2VyUGFjayhyZXN0OiBSZXN0TWFuYWdlciwgc3RpY2tlclBhY2tJZDogQmlnU3RyaW5nKTogUHJvbWlzZTxEaXNjb3JkU3RpY2tlclBhY2s+IHtcbiAgICByZXR1cm4gYXdhaXQgcmVzdC5nZXQ8RGlzY29yZFN0aWNrZXJQYWNrPihyZXN0LnJvdXRlcy5zdGlja2VyUGFjayhzdGlja2VyUGFja0lkKSk7XG4gIH0sXG4gIC8qKlxuICAgKiBSZXR1cm5zIHRoZSBsaXN0IG9mIHN0aWNrZXIgcGFja3MgYXZhaWxhYmxlLlxuICAgKlxuICAgKiBAcmV0dXJucyBBIGNvbGxlY3Rpb24gb2Yge0BsaW5rIERpc2NvcmRTdGlja2VyUGFja30gb2JqZWN0cyBhc3NvcnRlZCBieSBzdGlja2VyIElELlxuICAgKlxuICAgKiBAc2VlIHtAbGluayBodHRwczovL2RvY3MuZGlzY29yZC5jb20vZGV2ZWxvcGVycy9yZXNvdXJjZXMvc3RpY2tlciNsaXN0LXN0aWNrZXItcGFja3N9XG4gICAqL1xuICBhc3luYyBnZXRTdGlja2VyUGFja3MocmVzdDogUmVzdE1hbmFnZXIpOiBQcm9taXNlPERpc2NvcmRTdGlja2VyUGFja1tdPiB7XG4gICAgcmV0dXJuIGF3YWl0IHJlc3QuZ2V0PERpc2NvcmRTdGlja2VyUGFja1tdPihyZXN0LnJvdXRlcy5zdGlja2VyUGFja3MoKSk7XG4gIH0sXG4gIC8qKlxuICAgKiBHZXRzIHRoZSBpbml0aWFsIG1lc3NhZ2UgcmVzcG9uc2UgdG8gYW4gaW50ZXJhY3Rpb24uXG4gICAqXG4gICAqIEBwYXJhbSB0b2tlbiAtIFRoZSBpbnRlcmFjdGlvbiB0b2tlbiB0byB1c2UsIHByb3ZpZGVkIGluIHRoZSBvcmlnaW5hbCBpbnRlcmFjdGlvbi5cbiAgICogQHJldHVybnMgQW4gaW5zdGFuY2Ugb2Yge0BsaW5rIERpc2NvcmRNZXNzYWdlfS5cbiAgICpcbiAgICogQHJlbWFya3NcbiAgICogVW5saWtlIGBnZXRNZXNzYWdlKClgLCB0aGlzIGVuZHBvaW50IGFsbG93cyB0aGUgYm90IHVzZXIgdG8gYWN0IHdpdGhvdXQ6XG4gICAqIC0gTmVlZGluZyB0byBiZSBhYmxlIHRvIHNlZSB0aGUgY29udGVudHMgb2YgdGhlIGNoYW5uZWwgdGhhdCB0aGUgbWVzc2FnZSBpcyBpbi4gKGBSRUFEX01FU1NBR0VTYCBwZXJtaXNzaW9uLilcbiAgICogLSBSZXF1aXJpbmcgdGhlIGBNRVNTQUdFX0NPTlRFTlRgIGludGVudC5cbiAgICpcbiAgICogRG9lcyBub3Qgc3VwcG9ydCBlcGhlbWVyYWwgZm9sbG93LXVwIG1lc3NhZ2VzIGR1ZSB0byB0aGVzZSBiZWluZyBzdGF0ZWxlc3MuXG4gICAqXG4gICAqIEBzZWUge0BsaW5rIGh0dHBzOi8vZG9jcy5kaXNjb3JkLmNvbS9kZXZlbG9wZXJzL2ludGVyYWN0aW9ucy9yZWNlaXZpbmctYW5kLXJlc3BvbmRpbmcjZ2V0LW9yaWdpbmFsLWludGVyYWN0aW9uLXJlc3BvbnNlfVxuICAgKi9cbiAgYXN5bmMgZ2V0T3JpZ2luYWxJbnRlcmFjdGlvblJlc3BvbnNlKHJlc3Q6IFJlc3RNYW5hZ2VyLCB0b2tlbjogc3RyaW5nKTogUHJvbWlzZTxEaXNjb3JkTWVzc2FnZT4ge1xuICAgIHJldHVybiBhd2FpdCByZXN0LmdldDxEaXNjb3JkTWVzc2FnZT4ocmVzdC5yb3V0ZXMuaW50ZXJhY3Rpb25zLnJlc3BvbnNlcy5vcmlnaW5hbChyZXN0LmFwcGxpY2F0aW9uSWQsIHRva2VuKSwgeyB1bmF1dGhvcml6ZWQ6IHRydWUgfSk7XG4gIH0sXG4gIC8qKlxuICAgKiBSZXRyaWV2ZXMgdGhlIGxpc3Qgb2YgcGlucyBpbiBhIGNoYW5uZWwuXG4gICAqXG4gICAqIEBwYXJhbSBjaGFubmVsSWQgLSBUaGUgSUQgb2YgdGhlIGNoYW5uZWwgdG8gZ2V0IHRoZSBwaW5zIGZvci5cbiAgICogQHBhcmFtIG9wdGlvbnMgLSBUaGUgb3B0aW9ucyBmb3IgdGhlIGZldGNoaW5nIG9mIHRoZSBwaW5zLlxuICAgKiBAcmV0dXJucyBBIHtAbGluayBEaXNjb3JkR2V0Q2hhbm5lbFBpbnN9IG9iamVjdHNcbiAgICpcbiAgICogQHJlbWFya3NcbiAgICogUmVxdWlyZXMgdGhlIGBWSUVXX0NIQU5ORUxgIHBlcm1pc3Npb24uXG4gICAqXG4gICAqIElmIHRoZSB1c2VyIGlzIG1pc3NpbmcgdGhlIGBSRUFEX01FU1NBR0VfSElTVE9SWWAgcGVybWlzc2lvbiBpbiB0aGUgY2hhbm5lbCwgdGhlbiBubyBwaW5zIHdpbGwgYmUgcmV0dXJuZWQuXG4gICAqXG4gICAqIEBzZWUge0BsaW5rIGh0dHBzOi8vZG9jcy5kaXNjb3JkLmNvbS9kZXZlbG9wZXJzL3Jlc291cmNlcy9tZXNzYWdlI2dldC1jaGFubmVsLXBpbnN9XG4gICAqL1xuICBhc3luYyBnZXRDaGFubmVsUGlucyhyZXN0OiBSZXN0TWFuYWdlciwgY2hhbm5lbElkOiBCaWdTdHJpbmcsIG9wdGlvbnM/OiBHZXRDaGFubmVsUGluc09wdGlvbnMpOiBQcm9taXNlPERpc2NvcmRHZXRDaGFubmVsUGlucz4ge1xuICAgIHJldHVybiBhd2FpdCByZXN0LmdldChyZXN0LnJvdXRlcy5jaGFubmVscy5tZXNzYWdlUGlucyhjaGFubmVsSWQsIG9wdGlvbnMpKTtcbiAgfSxcbiAgLyoqXG4gICAqIEdldHMgdGhlIHBpbm5lZCBtZXNzYWdlcyBmb3IgYSBjaGFubmVsLlxuICAgKlxuICAgKiBAcGFyYW0gY2hhbm5lbElkIC0gVGhlIElEIG9mIHRoZSBjaGFubmVsIHRvIGdldCB0aGUgcGlubmVkIG1lc3NhZ2VzIGZvci5cbiAgICogQHJldHVybnMgQSBjb2xsZWN0aW9uIG9mIHtAbGluayBEaXNjb3JkTWVzc2FnZX0gb2JqZWN0cyBhc3NvcnRlZCBieSBtZXNzYWdlIElELlxuICAgKlxuICAgKiBAcmVtYXJrc1xuICAgKiBSZXF1aXJlcyB0aGF0IHRoZSBib3QgdXNlciBiZSBhYmxlIHRvIHNlZSB0aGUgY29udGVudHMgb2YgdGhlIGNoYW5uZWwgaW4gd2hpY2ggdGhlIG1lc3NhZ2VzIHdlcmUgcG9zdGVkLlxuICAgKlxuICAgKiBJZiBnZXR0aW5nIGEgbWVzc2FnZSBmcm9tIGEgZ3VpbGQgY2hhbm5lbDpcbiAgICogLSBSZXF1aXJlcyB0aGUgYFJFQURfTUVTU0FHRV9ISVNUT1JZYCBwZXJtaXNzaW9uLlxuICAgKlxuICAgKiBAc2VlIHtAbGluayBodHRwczovL2RvY3MuZGlzY29yZC5jb20vZGV2ZWxvcGVycy9yZXNvdXJjZXMvbWVzc2FnZSNnZXQtcGlubmVkLW1lc3NhZ2VzLWRlcHJlY2F0ZWR9XG4gICAqIEBkZXByZWNhdGVkIFVzZSB7QGxpbmsgZ2V0Q2hhbm5lbFBpbnN9IGluc3RlYWQuXG4gICAqL1xuICBhc3luYyBnZXRQaW5uZWRNZXNzYWdlcyhyZXN0OiBSZXN0TWFuYWdlciwgY2hhbm5lbElkOiBCaWdTdHJpbmcpOiBQcm9taXNlPERpc2NvcmRNZXNzYWdlW10+IHtcbiAgICByZXR1cm4gYXdhaXQgcmVzdC5nZXQ8RGlzY29yZE1lc3NhZ2VbXT4ocmVzdC5yb3V0ZXMuY2hhbm5lbHMucGlucyhjaGFubmVsSWQpKTtcbiAgfSxcbiAgLyoqXG4gICAqIEdldHMgdGhlIGxpc3Qgb2YgcHJpdmF0ZSBhcmNoaXZlZCB0aHJlYWRzIGZvciBhIGNoYW5uZWwuXG4gICAqXG4gICAqIEBwYXJhbSBjaGFubmVsSWQgLSBUaGUgSUQgb2YgdGhlIGNoYW5uZWwgdG8gZ2V0IHRoZSBhcmNoaXZlZCB0aHJlYWRzIGZvci5cbiAgICogQHBhcmFtIG9wdGlvbnMgLSBUaGUgcGFyYW1ldGVycyBmb3IgdGhlIGZldGNoaW5nIG9mIHRocmVhZHMuXG4gICAqIEByZXR1cm5zIEFuIGluc3RhbmNlIG9mIHtAbGluayBEaXNjb3JkTGlzdEFyY2hpdmVkVGhyZWFkc30uXG4gICAqXG4gICAqIEByZW1hcmtzXG4gICAqIFJlcXVpcmVzIHRoZSBgUkVBRF9NRVNTQUdFX0hJU1RPUllgIHBlcm1pc3Npb24uXG4gICAqIFJlcXVpcmVzIHRoZSBgTUFOQUdFX1RIUkVBRFNgIHBlcm1pc3Npb24uXG4gICAqXG4gICAqIFJldHVybnMgdGhyZWFkcyBvZiB0eXBlIHtAbGluayBDaGFubmVsVHlwZXN9Lkd1aWxkUHJpdmF0ZVRocmVhZC5cbiAgICpcbiAgICogVGhyZWFkcyBhcmUgb3JkZXJlZCBieSB0aGUgYGFyY2hpdmVfdGltZXN0YW1wYCBwcm9wZXJ0eSBpbmNsdWRlZCBpbiB0aGUgbWV0YWRhdGEgb2YgdGhlIG9iamVjdCBpbiBkZXNjZW5kaW5nIG9yZGVyLlxuICAgKlxuICAgKiBAc2VlIHtAbGluayBodHRwczovL2RvY3MuZGlzY29yZC5jb20vZGV2ZWxvcGVycy9yZXNvdXJjZXMvY2hhbm5lbCNsaXN0LXByaXZhdGUtYXJjaGl2ZWQtdGhyZWFkc31cbiAgICovXG4gIGFzeW5jIGdldFByaXZhdGVBcmNoaXZlZFRocmVhZHMocmVzdDogUmVzdE1hbmFnZXIsIGNoYW5uZWxJZDogQmlnU3RyaW5nLCBvcHRpb25zPzogTGlzdEFyY2hpdmVkVGhyZWFkcyk6IFByb21pc2U8RGlzY29yZExpc3RBcmNoaXZlZFRocmVhZHM+IHtcbiAgICByZXR1cm4gYXdhaXQgcmVzdC5nZXQ8RGlzY29yZExpc3RBcmNoaXZlZFRocmVhZHM+KHJlc3Qucm91dGVzLmNoYW5uZWxzLnRocmVhZHMucHJpdmF0ZShjaGFubmVsSWQsIG9wdGlvbnMpKTtcbiAgfSxcbiAgLyoqXG4gICAqIEdldHMgdGhlIGxpc3Qgb2YgcHJpdmF0ZSBhcmNoaXZlZCB0aHJlYWRzIHRoZSBib3QgaXMgYSBtZW1iZXIgb2YgZm9yIGEgY2hhbm5lbC5cbiAgICpcbiAgICogQHBhcmFtIGNoYW5uZWxJZCAtIFRoZSBJRCBvZiB0aGUgY2hhbm5lbCB0byBnZXQgdGhlIGFyY2hpdmVkIHRocmVhZHMgZm9yLlxuICAgKiBAcGFyYW0gb3B0aW9ucyAtIFRoZSBwYXJhbWV0ZXJzIGZvciB0aGUgZmV0Y2hpbmcgb2YgdGhyZWFkcy5cbiAgICogQHJldHVybnMgQW4gaW5zdGFuY2Ugb2Yge0BsaW5rIERpc2NvcmRMaXN0QXJjaGl2ZWRUaHJlYWRzfS5cbiAgICpcbiAgICogQHJlbWFya3NcbiAgICogUmVxdWlyZXMgdGhlIGBSRUFEX01FU1NBR0VfSElTVE9SWWAgcGVybWlzc2lvbi5cbiAgICpcbiAgICogUmV0dXJucyB0aHJlYWRzIG9mIHR5cGUge0BsaW5rIENoYW5uZWxUeXBlc30uR3VpbGRQcml2YXRlVGhyZWFkLlxuICAgKlxuICAgKiBUaHJlYWRzIGFyZSBvcmRlcmVkIGJ5IHRoZSBgaWRgIHByb3BlcnR5IGluIGRlc2NlbmRpbmcgb3JkZXIuXG4gICAqXG4gICAqIEBzZWUge0BsaW5rIGh0dHBzOi8vZG9jcy5kaXNjb3JkLmNvbS9kZXZlbG9wZXJzL3Jlc291cmNlcy9jaGFubmVsI2xpc3Qtam9pbmVkLXByaXZhdGUtYXJjaGl2ZWQtdGhyZWFkc31cbiAgICovXG4gIGFzeW5jIGdldFByaXZhdGVKb2luZWRBcmNoaXZlZFRocmVhZHMocmVzdDogUmVzdE1hbmFnZXIsIGNoYW5uZWxJZDogQmlnU3RyaW5nLCBvcHRpb25zPzogTGlzdEFyY2hpdmVkVGhyZWFkcyk6IFByb21pc2U8RGlzY29yZExpc3RBcmNoaXZlZFRocmVhZHM+IHtcbiAgICByZXR1cm4gYXdhaXQgcmVzdC5nZXQ8RGlzY29yZExpc3RBcmNoaXZlZFRocmVhZHM+KHJlc3Qucm91dGVzLmNoYW5uZWxzLnRocmVhZHMuam9pbmVkKGNoYW5uZWxJZCwgb3B0aW9ucykpO1xuICB9LFxuICAvKipcbiAgICogR2V0cyB0aGUgbnVtYmVyIG9mIG1lbWJlcnMgdGhhdCB3b3VsZCBiZSBraWNrZWQgZnJvbSBhIGd1aWxkIGR1cmluZyBwcnVuaW5nLlxuICAgKlxuICAgKiBAcGFyYW0gZ3VpbGRJZCAtIFRoZSBJRCBvZiB0aGUgZ3VpbGQgdG8gZ2V0IHRoZSBwcnVuZSBjb3VudCBvZi5cbiAgICogQHBhcmFtIG9wdGlvbnMgLSBUaGUgcGFyYW1ldGVycyBmb3IgdGhlIGZldGNoaW5nIG9mIHRoZSBwcnVuZSBjb3VudC5cbiAgICogQHJldHVybnMgQSBudW1iZXIgaW5kaWNhdGluZyB0aGUgbnVtYmVyIG9mIG1lbWJlcnMgdGhhdCB3b3VsZCBiZSBraWNrZWQuXG4gICAqXG4gICAqIEByZW1hcmtzXG4gICAqIFJlcXVpcmVzIHRoZSBgTUFOQUdFX0dVSUxEYCBhbmQgYEtJQ0tfTUVNQkVSU2AgcGVybWlzc2lvbnMsIHVubGVzcyB0aGUgZ3VpbGQgaGFzIHRoZSBgUFJVTkVfUkVRVUlSRVNfQURNSU5gIGd1aWxkIGZlYXR1cmUsIGluIHdoaWNoIGNhc2UgaXQgcmVxdWlyZXMgdGhlIGBBRE1JTklTVFJBVE9SYCBwZXJtaXNzaW9uLlxuICAgKlxuICAgKiBAc2VlIHtAbGluayBodHRwczovL2RvY3MuZGlzY29yZC5jb20vZGV2ZWxvcGVycy9yZXNvdXJjZXMvZ3VpbGQjZ2V0LWd1aWxkLXBydW5lLWNvdW50fVxuICAgKi9cbiAgYXN5bmMgZ2V0UHJ1bmVDb3VudChyZXN0OiBSZXN0TWFuYWdlciwgZ3VpbGRJZDogQmlnU3RyaW5nLCBvcHRpb25zPzogR2V0R3VpbGRQcnVuZUNvdW50UXVlcnkpOiBQcm9taXNlPERpc2NvcmRQcnVuZWRDb3VudD4ge1xuICAgIHJldHVybiBhd2FpdCByZXN0LmdldDxEaXNjb3JkUHJ1bmVkQ291bnQ+KHJlc3Qucm91dGVzLmd1aWxkcy5wcnVuZShndWlsZElkLCBvcHRpb25zKSk7XG4gIH0sXG4gIC8qKlxuICAgKiBHZXRzIHRoZSBsaXN0IG9mIHB1YmxpYyBhcmNoaXZlZCB0aHJlYWRzIGZvciBhIGNoYW5uZWwuXG4gICAqXG4gICAqIEBwYXJhbSBjaGFubmVsSWQgLSBUaGUgSUQgb2YgdGhlIGNoYW5uZWwgdG8gZ2V0IHRoZSBhcmNoaXZlZCB0aHJlYWRzIGZvci5cbiAgICogQHBhcmFtIG9wdGlvbnMgLSBUaGUgcGFyYW1ldGVycyBmb3IgdGhlIGZldGNoaW5nIG9mIHRocmVhZHMuXG4gICAqIEByZXR1cm5zIEFuIGluc3RhbmNlIG9mIHtAbGluayBEaXNjb3JkTGlzdEFyY2hpdmVkVGhyZWFkc30uXG4gICAqXG4gICAqIEByZW1hcmtzXG4gICAqIFJlcXVpcmVzIHRoZSBgUkVBRF9NRVNTQUdFX0hJU1RPUllgIHBlcm1pc3Npb24uXG4gICAqXG4gICAqIElmIGNhbGxlZCBvbiBhIGNoYW5uZWwgb2YgdHlwZSB7QGxpbmsgQ2hhbm5lbFR5cGVzfS5HdWlsZFRleHQsIHJldHVybnMgdGhyZWFkcyBvZiB0eXBlIHtAbGluayBDaGFubmVsVHlwZXN9Lkd1aWxkUHVibGljVGhyZWFkLlxuICAgKiBJZiBjYWxsZWQgb24gYSBjaGFubmVsIG9mIHR5cGUge0BsaW5rIENoYW5uZWxUeXBlc30uR3VpbGROZXdzLCByZXR1cm5zIHRocmVhZHMgb2YgdHlwZSB7QGxpbmsgQ2hhbm5lbFR5cGVzfS5HdWlsZE5ld3NUaHJlYWQuXG4gICAqXG4gICAqIFRocmVhZHMgYXJlIG9yZGVyZWQgYnkgdGhlIGBhcmNoaXZlX3RpbWVzdGFtcGAgcHJvcGVydHkgaW5jbHVkZWQgaW4gdGhlIG1ldGFkYXRhIG9mIHRoZSBvYmplY3QgaW4gZGVzY2VuZGluZyBvcmRlci5cbiAgICpcbiAgICogQHNlZSB7QGxpbmsgaHR0cHM6Ly9kb2NzLmRpc2NvcmQuY29tL2RldmVsb3BlcnMvcmVzb3VyY2VzL2NoYW5uZWwjbGlzdC1wdWJsaWMtYXJjaGl2ZWQtdGhyZWFkc31cbiAgICovXG4gIGFzeW5jIGdldFB1YmxpY0FyY2hpdmVkVGhyZWFkcyhyZXN0OiBSZXN0TWFuYWdlciwgY2hhbm5lbElkOiBCaWdTdHJpbmcsIG9wdGlvbnM/OiBMaXN0QXJjaGl2ZWRUaHJlYWRzKTogUHJvbWlzZTxEaXNjb3JkTGlzdEFyY2hpdmVkVGhyZWFkcz4ge1xuICAgIHJldHVybiBhd2FpdCByZXN0LmdldDxEaXNjb3JkTGlzdEFyY2hpdmVkVGhyZWFkcz4ocmVzdC5yb3V0ZXMuY2hhbm5lbHMudGhyZWFkcy5wdWJsaWMoY2hhbm5lbElkLCBvcHRpb25zKSk7XG4gIH0sXG4gIC8qKlxuICAgKiBHZXRzIHRoZSBsaXN0IG9mIHJvbGVzIGZvciBhIGd1aWxkLlxuICAgKlxuICAgKiBAcGFyYW0gZ3VpbGRJZCAtIFRoZSBJRCBvZiB0aGUgZ3VpbGQgdG8gZ2V0IHRoZSBsaXN0IG9mIHJvbGVzIGZvci5cbiAgICogQHJldHVybnMgQSBjb2xsZWN0aW9uIG9mIHtAbGluayBEaXNjb3JkUm9sZX0gb2JqZWN0cyBhc3NvcnRlZCBieSByb2xlIElELlxuICAgKlxuICAgKiBAcmVtYXJrc1xuICAgKiDimqDvuI8gVGhpcyBlbmRwb2ludCBzaG91bGQgYmUgdXNlZCBzcGFyaW5nbHkgZHVlIHRvIHtAbGluayBEaXNjb3JkUm9sZX0gb2JqZWN0cyBhbHJlYWR5IGJlaW5nIGluY2x1ZGVkIGluIGd1aWxkIHBheWxvYWRzLlxuICAgKlxuICAgKiBAc2VlIHtAbGluayBodHRwczovL2RvY3MuZGlzY29yZC5jb20vZGV2ZWxvcGVycy9yZXNvdXJjZXMvZ3VpbGQjZ2V0LWd1aWxkLXJvbGVzfVxuICAgKi9cbiAgYXN5bmMgZ2V0Um9sZXMocmVzdDogUmVzdE1hbmFnZXIsIGd1aWxkSWQ6IEJpZ1N0cmluZyk6IFByb21pc2U8RGlzY29yZFJvbGVbXT4ge1xuICAgIHJldHVybiBhd2FpdCByZXN0LmdldDxEaXNjb3JkUm9sZVtdPihyZXN0LnJvdXRlcy5ndWlsZHMucm9sZXMuYWxsKGd1aWxkSWQpKTtcbiAgfSxcbiAgLyoqXG4gICAqIEdldHMgYSByb2xlIGJ5IGlkIGZvciBhIGd1aWxkLlxuICAgKlxuICAgKiBAcGFyYW0gZ3VpbGRJZCAtIFRoZSBJRCBvZiB0aGUgZ3VpbGQgdG8gZ2V0IHJvbGUgZm9yLlxuICAgKiBAcGFyYW0gcm9sZUlkIC0gVGhlIElEIG9mIHRoZSByb2xlLlxuICAgKiBAcmV0dXJucyBBIHtAbGluayBEaXNjb3JkUm9sZX0gb2JqZWN0LlxuICAgKlxuICAgKiBAc2VlIHtAbGluayBodHRwczovL2RvY3MuZGlzY29yZC5jb20vZGV2ZWxvcGVycy9yZXNvdXJjZXMvZ3VpbGQjZ2V0LWd1aWxkLXJvbGV9XG4gICAqL1xuICBhc3luYyBnZXRSb2xlKHJlc3Q6IFJlc3RNYW5hZ2VyLCBndWlsZElkOiBCaWdTdHJpbmcsIHJvbGVJZDogQmlnU3RyaW5nKTogUHJvbWlzZTxEaXNjb3JkUm9sZT4ge1xuICAgIHJldHVybiBhd2FpdCByZXN0LmdldDxEaXNjb3JkUm9sZT4ocmVzdC5yb3V0ZXMuZ3VpbGRzLnJvbGVzLm9uZShndWlsZElkLCByb2xlSWQpKTtcbiAgfSxcbiAgLyoqXG4gICAqIEdldHMgYSBzY2hlZHVsZWQgZXZlbnQgYnkgaXRzIElELlxuICAgKlxuICAgKiBAcGFyYW0gZ3VpbGRJZCAtIFRoZSBJRCBvZiB0aGUgZ3VpbGQgdG8gZ2V0IHRoZSBzY2hlZHVsZWQgZXZlbnQgZnJvbS5cbiAgICogQHBhcmFtIGV2ZW50SWQgLSBUaGUgSUQgb2YgdGhlIHNjaGVkdWxlZCBldmVudCB0byBnZXQuXG4gICAqIEBwYXJhbSBvcHRpb25zIC0gVGhlIHBhcmFtZXRlcnMgZm9yIHRoZSBmZXRjaGluZyBvZiB0aGUgc2NoZWR1bGVkIGV2ZW50LlxuICAgKiBAcmV0dXJucyBBbiBpbnN0YW5jZSBvZiB7QGxpbmsgRGlzY29yZFNjaGVkdWxlZEV2ZW50fS5cbiAgICpcbiAgICogQHNlZSB7QGxpbmsgaHR0cHM6Ly9kb2NzLmRpc2NvcmQuY29tL2RldmVsb3BlcnMvcmVzb3VyY2VzL2d1aWxkLXNjaGVkdWxlZC1ldmVudCNnZXQtZ3VpbGQtc2NoZWR1bGVkLWV2ZW50fVxuICAgKi9cbiAgYXN5bmMgZ2V0U2NoZWR1bGVkRXZlbnQoXG4gICAgcmVzdDogUmVzdE1hbmFnZXIsXG4gICAgZ3VpbGRJZDogQmlnU3RyaW5nLFxuICAgIGV2ZW50SWQ6IEJpZ1N0cmluZyxcbiAgICBvcHRpb25zPzogeyB3aXRoVXNlckNvdW50PzogYm9vbGVhbiB9LFxuICApOiBQcm9taXNlPERpc2NvcmRTY2hlZHVsZWRFdmVudD4ge1xuICAgIHJldHVybiBhd2FpdCByZXN0LmdldDxEaXNjb3JkU2NoZWR1bGVkRXZlbnQ+KHJlc3Qucm91dGVzLmd1aWxkcy5ldmVudHMuZXZlbnQoZ3VpbGRJZCwgZXZlbnRJZCwgb3B0aW9ucz8ud2l0aFVzZXJDb3VudCkpO1xuICB9LFxuICAvKipcbiAgICogR2V0cyB0aGUgbGlzdCBvZiBzY2hlZHVsZWQgZXZlbnRzIGZvciBhIGd1aWxkLlxuICAgKlxuICAgKiBAcGFyYW0gZ3VpbGRJZCAtIFRoZSBJRCBvZiB0aGUgZ3VpbGQgdG8gZ2V0IHRoZSBzY2hlZHVsZWQgZXZlbnRzIGZyb20uXG4gICAqIEBwYXJhbSBvcHRpb25zIC0gVGhlIHBhcmFtZXRlcnMgZm9yIHRoZSBmZXRjaGluZyBvZiB0aGUgc2NoZWR1bGVkIGV2ZW50cy5cbiAgICogQHJldHVybnMgQSBjb2xsZWN0aW9uIG9mIHtAbGluayBEaXNjb3JkU2NoZWR1bGVkRXZlbnR9IG9iamVjdHMgYXNzb3J0ZWQgYnkgZXZlbnQgSUQuXG4gICAqXG4gICAqIEBzZWUge0BsaW5rIGh0dHBzOi8vZG9jcy5kaXNjb3JkLmNvbS9kZXZlbG9wZXJzL3Jlc291cmNlcy9ndWlsZC1zY2hlZHVsZWQtZXZlbnQjbGlzdC1zY2hlZHVsZWQtZXZlbnRzLWZvci1ndWlsZH1cbiAgICovXG4gIGFzeW5jIGdldFNjaGVkdWxlZEV2ZW50cyhyZXN0OiBSZXN0TWFuYWdlciwgZ3VpbGRJZDogQmlnU3RyaW5nLCBvcHRpb25zPzogR2V0U2NoZWR1bGVkRXZlbnRzKTogUHJvbWlzZTxEaXNjb3JkU2NoZWR1bGVkRXZlbnRbXT4ge1xuICAgIHJldHVybiBhd2FpdCByZXN0LmdldDxEaXNjb3JkU2NoZWR1bGVkRXZlbnRbXT4ocmVzdC5yb3V0ZXMuZ3VpbGRzLmV2ZW50cy5ldmVudHMoZ3VpbGRJZCwgb3B0aW9ucz8ud2l0aFVzZXJDb3VudCkpO1xuICB9LFxuICAvKipcbiAgICogR2V0cyB0aGUgbGlzdCBvZiBzdWJzY3JpYmVycyB0byBhIHNjaGVkdWxlZCBldmVudCBmcm9tIGEgZ3VpbGQuXG4gICAqXG4gICAqIEBwYXJhbSBndWlsZElkIC0gVGhlIElEIG9mIHRoZSBndWlsZCB0byBnZXQgdGhlIHN1YnNjcmliZXJzIHRvIHRoZSBzY2hlZHVsZWQgZXZlbnQgZnJvbS5cbiAgICogQHBhcmFtIGV2ZW50SWQgLSBUaGUgSUQgb2YgdGhlIHNjaGVkdWxlZCBldmVudCB0byBnZXQgdGhlIHN1YnNjcmliZXJzIG9mLlxuICAgKiBAcGFyYW0gb3B0aW9ucyAtIFRoZSBwYXJhbWV0ZXJzIGZvciB0aGUgZmV0Y2hpbmcgb2YgdGhlIHN1YnNjcmliZXJzLlxuICAgKiBAcmV0dXJucyBBIGNvbGxlY3Rpb24gb2Yge0BsaW5rIERpc2NvcmRVc2VyfSBvYmplY3RzIGFzc29ydGVkIGJ5IHVzZXIgSUQuXG4gICAqXG4gICAqIEByZW1hcmtzXG4gICAqIFJlcXVpcmVzIHRoZSBgTUFOQUdFX0VWRU5UU2AgcGVybWlzc2lvbi5cbiAgICpcbiAgICogVXNlcnMgYXJlIG9yZGVyZWQgYnkgdGhlaXIgSURzIGluIF9hc2NlbmRpbmdfIG9yZGVyLlxuICAgKlxuICAgKiBAc2VlIHtAbGluayBodHRwczovL2RvY3MuZGlzY29yZC5jb20vZGV2ZWxvcGVycy9yZXNvdXJjZXMvZ3VpbGQtc2NoZWR1bGVkLWV2ZW50I2dldC1ndWlsZC1zY2hlZHVsZWQtZXZlbnQtdXNlcnN9XG4gICAqL1xuICBhc3luYyBnZXRTY2hlZHVsZWRFdmVudFVzZXJzKFxuICAgIHJlc3Q6IFJlc3RNYW5hZ2VyLFxuICAgIGd1aWxkSWQ6IEJpZ1N0cmluZyxcbiAgICBldmVudElkOiBCaWdTdHJpbmcsXG4gICAgb3B0aW9ucz86IEdldFNjaGVkdWxlZEV2ZW50VXNlcnMsXG4gICk6IFByb21pc2U8eyB1c2VyOiBEaXNjb3JkVXNlcjsgbWVtYmVyPzogRGlzY29yZE1lbWJlciB9W10+IHtcbiAgICByZXR1cm4gYXdhaXQgcmVzdC5nZXQ8QXJyYXk8eyB1c2VyOiBEaXNjb3JkVXNlcjsgbWVtYmVyPzogRGlzY29yZE1lbWJlciB9Pj4ocmVzdC5yb3V0ZXMuZ3VpbGRzLmV2ZW50cy51c2VycyhndWlsZElkLCBldmVudElkLCBvcHRpb25zKSk7XG4gIH0sXG4gIC8qKiBHZXQgdGhlIGJvdHMgR2F0ZXdheSBtZXRhZGF0YSB0aGF0IGNhbiBoZWxwIGR1cmluZyB0aGUgb3BlcmF0aW9uIG9mIGxhcmdlIG9yIHNoYXJkZWQgYm90cy4gKi9cbiAgYXN5bmMgZ2V0U2Vzc2lvbkluZm8ocmVzdDogUmVzdE1hbmFnZXIpOiBQcm9taXNlPERpc2NvcmRHZXRHYXRld2F5Qm90PiB7XG4gICAgcmV0dXJuIGF3YWl0IHJlc3Quc25ha2UuZ2V0R2F0ZXdheUJvdCgpO1xuICB9LFxuICAvKipcbiAgICogR2V0cyB0aGUgc3RhZ2UgaW5zdGFuY2UgYXNzb2NpYXRlZCB3aXRoIGEgc3RhZ2UgY2hhbm5lbCwgaWYgb25lIGV4aXN0cy5cbiAgICpcbiAgICogQHBhcmFtIGNoYW5uZWxJZCAtIFRoZSBJRCBvZiB0aGUgc3RhZ2UgY2hhbm5lbCB0aGUgc3RhZ2UgaW5zdGFuY2UgaXMgYXNzb2NpYXRlZCB3aXRoLlxuICAgKiBAcmV0dXJucyBBbiBpbnN0YW5jZSBvZiB7QGxpbmsgRGlzY29yZFN0YWdlSW5zdGFuY2V9LlxuICAgKlxuICAgKiBAc2VlIHtAbGluayBodHRwczovL2RvY3MuZGlzY29yZC5jb20vZGV2ZWxvcGVycy9yZXNvdXJjZXMvc3RhZ2UtaW5zdGFuY2UjZ2V0LXN0YWdlLWluc3RhbmNlfVxuICAgKi9cbiAgYXN5bmMgZ2V0U3RhZ2VJbnN0YW5jZShyZXN0OiBSZXN0TWFuYWdlciwgY2hhbm5lbElkOiBCaWdTdHJpbmcpOiBQcm9taXNlPERpc2NvcmRTdGFnZUluc3RhbmNlPiB7XG4gICAgcmV0dXJuIGF3YWl0IHJlc3QuZ2V0PERpc2NvcmRTdGFnZUluc3RhbmNlPihyZXN0LnJvdXRlcy5jaGFubmVscy5zdGFnZShjaGFubmVsSWQpKTtcbiAgfSxcbiAgLyoqXG4gICAqIFJldHVybnMgdGhlIGN1cnJlbnQgdXNlcidzIHZvaWNlIHN0YXRlIGluIHRoZSBndWlsZC5cbiAgICpcbiAgICogQHBhcmFtIGd1aWxkSWQgLSBUaGUgSUQgb2YgdGhlIGd1aWxkIHRvIGdldCB0aGUgdm9pY2Ugc3RhdGUgZnJvbS5cbiAgICogQHJldHVybnMgQW4gaW5zdGFuY2Ugb2Yge0BsaW5rIERpc2NvcmRWb2ljZVN0YXRlfS5cbiAgICpcbiAgICogQHNlZSB7QGxpbmsgaHR0cHM6Ly9kb2NzLmRpc2NvcmQuY29tL2RldmVsb3BlcnMvcmVzb3VyY2VzL3ZvaWNlI2dldC1jdXJyZW50LXVzZXItdm9pY2Utc3RhdGV9XG4gICAqL1xuICBhc3luYyBnZXRPd25Wb2ljZVN0YXRlKHJlc3Q6IFJlc3RNYW5hZ2VyLCBndWlsZElkOiBCaWdTdHJpbmcpOiBQcm9taXNlPERpc2NvcmRWb2ljZVN0YXRlPiB7XG4gICAgcmV0dXJuIGF3YWl0IHJlc3QuZ2V0PERpc2NvcmRWb2ljZVN0YXRlPihyZXN0LnJvdXRlcy5ndWlsZHMudm9pY2UoZ3VpbGRJZCkpO1xuICB9LFxuICAvKipcbiAgICogUmV0dXJucyB0aGUgc3BlY2lmaWVkIHVzZXIncyB2b2ljZSBzdGF0ZSBpbiB0aGUgZ3VpbGQuXG4gICAqXG4gICAqIEBwYXJhbSBndWlsZElkIC0gVGhlIElEIG9mIHRoZSBndWlsZCB0byBnZXQgdGhlIHZvaWNlIHN0YXRlIGZyb20uXG4gICAqIEBwYXJhbSB1c2VySWQgLSBUaGUgSUQgb2YgdGhlIHVzZXIgdG8gZ2V0IHRoZSB2b2ljZSBzdGF0ZSBmcm9tXG4gICAqIEByZXR1cm5zIEFuIGluc3RhbmNlIG9mIHtAbGluayBEaXNjb3JkVm9pY2VTdGF0ZX0uXG4gICAqXG4gICAqIEByZW1hcmtzXG4gICAqIElmIHRoZSBzcGVjaWZpZWQgdXNlciBpcyBjb25uZWN0ZWQgdG8gYSB2b2ljZSBjaGFubmVsLCB0aGUgY3VycmVudCB1c2VyIG11c3QgaGF2ZSBwZXJtaXNzaW9uIHRvIGNvbm5lY3QgdG8gdGhlIGNoYW5uZWwuXG4gICAqXG4gICAqIEBzZWUge0BsaW5rIGh0dHBzOi8vZG9jcy5kaXNjb3JkLmNvbS9kZXZlbG9wZXJzL3Jlc291cmNlcy92b2ljZSNnZXQtdXNlci12b2ljZS1zdGF0ZX1cbiAgICovXG4gIGFzeW5jIGdldFVzZXJWb2ljZVN0YXRlKHJlc3Q6IFJlc3RNYW5hZ2VyLCBndWlsZElkOiBCaWdTdHJpbmcsIHVzZXJJZDogQmlnU3RyaW5nKTogUHJvbWlzZTxEaXNjb3JkVm9pY2VTdGF0ZT4ge1xuICAgIHJldHVybiBhd2FpdCByZXN0LmdldDxEaXNjb3JkVm9pY2VTdGF0ZT4ocmVzdC5yb3V0ZXMuZ3VpbGRzLnZvaWNlKGd1aWxkSWQsIHVzZXJJZCkpO1xuICB9LFxuICAvKipcbiAgICogUmV0dXJucyBhIHN0aWNrZXIgb2JqZWN0IGZvciB0aGUgZ2l2ZW4gc3RpY2tlciBJRC5cbiAgICpcbiAgICogQHBhcmFtIHN0aWNrZXJJZCBUaGUgSUQgb2YgdGhlIHN0aWNrZXIgdG8gZ2V0XG4gICAqIEByZXR1cm5zIEEge0BsaW5rIERpc2NvcmRTdGlja2VyfVxuICAgKlxuICAgKiBAc2VlIHtAbGluayBodHRwczovL2RvY3MuZGlzY29yZC5jb20vZGV2ZWxvcGVycy9yZXNvdXJjZXMvc3RpY2tlciNnZXQtc3RpY2tlcn1cbiAgICovXG4gIGFzeW5jIGdldFN0aWNrZXIocmVzdDogUmVzdE1hbmFnZXIsIHN0aWNrZXJJZDogQmlnU3RyaW5nKTogUHJvbWlzZTxEaXNjb3JkU3RpY2tlcj4ge1xuICAgIHJldHVybiBhd2FpdCByZXN0LmdldDxEaXNjb3JkU3RpY2tlcj4ocmVzdC5yb3V0ZXMuc3RpY2tlcihzdGlja2VySWQpKTtcbiAgfSxcbiAgLyoqXG4gICAqIEdldHMgYSB0aHJlYWQgbWVtYmVyIGJ5IHRoZWlyIHVzZXIgSUQuXG4gICAqXG4gICAqIEBwYXJhbSBjaGFubmVsSWQgLSBUaGUgSUQgb2YgdGhlIHRocmVhZCB0byBnZXQgdGhlIHRocmVhZCBtZW1iZXIgb2YuXG4gICAqIEBwYXJhbSB1c2VySWQgLSBUaGUgdXNlciBJRCBvZiB0aGUgdGhyZWFkIG1lbWJlciB0byBnZXQuXG4gICAqIEBwYXJhbSBvcHRpb25zIC0gVGhlIHBhcmFtZXRlcnMgZm9yIHRoZSBmZXRjaGluZyBvZiB0aGUgdGhyZWFkIG1lbWJlci5cbiAgICogQHJldHVybnMgQW4gaW5zdGFuY2Ugb2Yge0BsaW5rIERpc2NvcmRUaHJlYWRNZW1iZXJ9LlxuICAgKlxuICAgKiBAc2VlIHtAbGluayBodHRwczovL2RvY3MuZGlzY29yZC5jb20vZGV2ZWxvcGVycy9yZXNvdXJjZXMvY2hhbm5lbCNnZXQtdGhyZWFkLW1lbWJlcn1cbiAgICovXG4gIGFzeW5jIGdldFRocmVhZE1lbWJlcihyZXN0OiBSZXN0TWFuYWdlciwgY2hhbm5lbElkOiBCaWdTdHJpbmcsIHVzZXJJZDogQmlnU3RyaW5nLCBvcHRpb25zPzogR2V0VGhyZWFkTWVtYmVyKTogUHJvbWlzZTxEaXNjb3JkVGhyZWFkTWVtYmVyPiB7XG4gICAgcmV0dXJuIGF3YWl0IHJlc3QuZ2V0PERpc2NvcmRUaHJlYWRNZW1iZXI+KHJlc3Qucm91dGVzLmNoYW5uZWxzLnRocmVhZHMuZ2V0VXNlcihjaGFubmVsSWQsIHVzZXJJZCwgb3B0aW9ucykpO1xuICB9LFxuICAvKipcbiAgICogR2V0cyB0aGUgbGlzdCBvZiB0aHJlYWQgbWVtYmVycyBmb3IgYSB0aHJlYWQuXG4gICAqXG4gICAqIEBwYXJhbSBjaGFubmVsSWQgLSBUaGUgSUQgb2YgdGhlIHRocmVhZCB0byBnZXQgdGhlIHRocmVhZCBtZW1iZXJzIG9mLlxuICAgKiBAcGFyYW0gb3B0aW9ucyAtIFRoZSBwYXJhbWV0ZXJzIGZvciB0aGUgZmV0Y2hpbmcgb2YgdGhlIHRocmVhZCBtZW1iZXJzLlxuICAgKiBAcmV0dXJucyBBIGNvbGxlY3Rpb24gb2Yge0BsaW5rIERpc2NvcmRUaHJlYWRNZW1iZXJ9IGFzc29ydGVkIGJ5IHVzZXIgSUQuXG4gICAqXG4gICAqIEByZW1hcmtzXG4gICAqIFJlcXVpcmVzIHRoZSBhcHBsaWNhdGlvbiB0byBoYXZlIHRoZSBgR1VJTERfTUVNQkVSU2AgcHJpdmlsZWdlZCBpbnRlbnQgZW5hYmxlZC5cbiAgICpcbiAgICogQHNlZSB7QGxpbmsgaHR0cHM6Ly9kb2NzLmRpc2NvcmQuY29tL2RldmVsb3BlcnMvcmVzb3VyY2VzL2NoYW5uZWwjbGlzdC10aHJlYWQtbWVtYmVyc31cbiAgICovXG4gIGFzeW5jIGdldFRocmVhZE1lbWJlcnMocmVzdDogUmVzdE1hbmFnZXIsIGNoYW5uZWxJZDogQmlnU3RyaW5nLCBvcHRpb25zPzogTGlzdFRocmVhZE1lbWJlcnMpOiBQcm9taXNlPERpc2NvcmRUaHJlYWRNZW1iZXJbXT4ge1xuICAgIHJldHVybiBhd2FpdCByZXN0LmdldDxEaXNjb3JkVGhyZWFkTWVtYmVyW10+KHJlc3Qucm91dGVzLmNoYW5uZWxzLnRocmVhZHMubWVtYmVycyhjaGFubmVsSWQsIG9wdGlvbnMpKTtcbiAgfSxcbiAgLyoqXG4gICAqIEdldHMgdGhlIGxpc3Qgb2YgdXNlcnMgdGhhdCByZWFjdGVkIHdpdGggYW4gZW1vamkgdG8gYSBtZXNzYWdlLlxuICAgKlxuICAgKiBAcGFyYW0gY2hhbm5lbElkIC0gVGhlIElEIG9mIHRoZSBjaGFubmVsIHRoZSBtZXNzYWdlIHRvIGdldCB0aGUgdXNlcnMgZm9yIGlzIGluLlxuICAgKiBAcGFyYW0gbWVzc2FnZUlkIC0gVGhlIElEIG9mIHRoZSBtZXNzYWdlIHRvIGdldCB0aGUgdXNlcnMgZm9yLlxuICAgKiBAcGFyYW0gcmVhY3Rpb24gLSBUaGUgcmVhY3Rpb24gZm9yIHdoaWNoIHRvIGdldCB0aGUgdXNlcnMuXG4gICAqIEBwYXJhbSBvcHRpb25zIC0gVGhlIHBhcmFtZXRlcnMgZm9yIHRoZSBmZXRjaGluZyBvZiB0aGUgdXNlcnMuXG4gICAqIEByZXR1cm5zIEEgY29sbGVjdGlvbiBvZiB7QGxpbmsgRGlzY29yZFVzZXJ9IG9iamVjdHMgYXNzb3J0ZWQgYnkgdXNlciBJRC5cbiAgICpcbiAgICogQHNlZSB7QGxpbmsgaHR0cHM6Ly9kb2NzLmRpc2NvcmQuY29tL2RldmVsb3BlcnMvcmVzb3VyY2VzL2NoYW5uZWwjZ2V0LXJlYWN0aW9uc31cbiAgICovXG4gIGFzeW5jIGdldFJlYWN0aW9ucyhcbiAgICByZXN0OiBSZXN0TWFuYWdlcixcbiAgICBjaGFubmVsSWQ6IEJpZ1N0cmluZyxcbiAgICBtZXNzYWdlSWQ6IEJpZ1N0cmluZyxcbiAgICByZWFjdGlvbjogc3RyaW5nLFxuICAgIG9wdGlvbnM/OiBHZXRSZWFjdGlvbnMsXG4gICk6IFByb21pc2U8RGlzY29yZFVzZXJbXT4ge1xuICAgIHJldHVybiBhd2FpdCByZXN0LmdldDxEaXNjb3JkVXNlcltdPihyZXN0LnJvdXRlcy5jaGFubmVscy5yZWFjdGlvbnMubWVzc2FnZShjaGFubmVsSWQsIG1lc3NhZ2VJZCwgcmVhY3Rpb24sIG9wdGlvbnMpKTtcbiAgfSxcbiAgLyoqXG4gICAqIEdldCBhIHVzZXIncyBkYXRhIGZyb20gdGhlIGFwaVxuICAgKlxuICAgKiBAcGFyYW0gaWQgVGhlIHVzZXIncyBpZFxuICAgKiBAcmV0dXJucyB7RGlzY29yZFVzZXJ9XG4gICAqL1xuICBhc3luYyBnZXRVc2VyKHJlc3Q6IFJlc3RNYW5hZ2VyLCBpZDogQmlnU3RyaW5nKTogUHJvbWlzZTxEaXNjb3JkVXNlcj4ge1xuICAgIHJldHVybiBhd2FpdCByZXN0LmdldDxEaXNjb3JkVXNlcj4ocmVzdC5yb3V0ZXMudXNlcihpZCkpO1xuICB9LFxuICAvKipcbiAgICogR2V0IHRoZSBjdXJyZW50IHVzZXIgZGF0YS5cbiAgICpcbiAgICogQHBhcmFtIGJlYXJlclRva2VuIC0gVGhlIGFjY2VzcyB0b2tlbiBvZiB0aGUgdXNlclxuICAgKiBAcmV0dXJucyB7RGlzY29yZFVzZXJ9XG4gICAqXG4gICAqIEByZW1hcmtzXG4gICAqIFRoaXMgcmVxdWlyZXMgdGhlIGBpZGVudGlmeWAgc2NvcGUuXG4gICAqXG4gICAqIFRvIGdldCB0aGUgbWFpbCB0aGlzIGFsc28gcmVxdWlyZXMgdGhlIGBlbWFpbGAgc2NvcGVcbiAgICovXG4gIGFzeW5jIGdldEN1cnJlbnRVc2VyKHJlc3Q6IFJlc3RNYW5hZ2VyLCBiZWFyZXJUb2tlbjogc3RyaW5nKTogUHJvbWlzZTxEaXNjb3JkVXNlcj4ge1xuICAgIHJldHVybiBhd2FpdCByZXN0LmdldDxEaXNjb3JkVXNlcj4ocmVzdC5yb3V0ZXMuY3VycmVudFVzZXIoKSwge1xuICAgICAgaGVhZGVyczoge1xuICAgICAgICBhdXRob3JpemF0aW9uOiBgQmVhcmVyICR7YmVhcmVyVG9rZW59YCxcbiAgICAgIH0sXG4gICAgICB1bmF1dGhvcml6ZWQ6IHRydWUsXG4gICAgfSk7XG4gIH0sXG4gIC8qKlxuICAgKiBHZXQgdGhlIGN1cnJlbnQgdXNlciBjb25uZWN0aW9ucy5cbiAgICpcbiAgICogQHBhcmFtIGJlYXJlclRva2VuIC0gVGhlIGFjY2VzcyB0b2tlbiBvZiB0aGUgdXNlclxuICAgKiBAcmV0dXJucyB7RGlzY29yZENvbm5lY3Rpb25bXX1cbiAgICpcbiAgICogQHJlbWFya3NcbiAgICogVGhpcyByZXF1aXJlcyB0aGUgYGNvbm5lY3Rpb25zYCBzY29wZS5cbiAgICovXG4gIGFzeW5jIGdldFVzZXJDb25uZWN0aW9ucyhyZXN0OiBSZXN0TWFuYWdlciwgYmVhcmVyVG9rZW46IHN0cmluZyk6IFByb21pc2U8RGlzY29yZENvbm5lY3Rpb25bXT4ge1xuICAgIHJldHVybiBhd2FpdCByZXN0LmdldDxEaXNjb3JkQ29ubmVjdGlvbltdPihyZXN0LnJvdXRlcy5vYXV0aDIuY29ubmVjdGlvbnMoKSwge1xuICAgICAgaGVhZGVyczoge1xuICAgICAgICBhdXRob3JpemF0aW9uOiBgQmVhcmVyICR7YmVhcmVyVG9rZW59YCxcbiAgICAgIH0sXG4gICAgICB1bmF1dGhvcml6ZWQ6IHRydWUsXG4gICAgfSk7XG4gIH0sXG4gIC8qKlxuICAgKiBHZXQgdGhlIGN1cnJlbnQgdXNlciBhcHBsaWNhdGlvbiByb2xlIGNvbm5lY3Rpb24gZm9yIHRoZSBhcHBsaWNhdGlvbi5cbiAgICpcbiAgICogQHBhcmFtIGJlYXJlclRva2VuIC0gVGhlIGFjY2VzcyB0b2tlbiBvZiB0aGUgdXNlclxuICAgKiBAcGFyYW0gYXBwbGljYXRpb25JZCAtIFRoZSBpZCBvZiB0aGUgYXBwbGljYXRpb24gdG8gZ2V0IHRoZSByb2xlIGNvbm5lY3Rpb25cbiAgICogQHJldHVybnMge0Rpc2NvcmRBcHBsaWNhdGlvblJvbGVDb25uZWN0aW9ufVxuICAgKlxuICAgKiBAcmVtYXJrc1xuICAgKiBUaGUgYWNjZXNzIHRva2VuIHJlcXVpcmVzIHRoZSBgcm9sZV9jb25uZWN0aW9ucy53cml0ZWAgc2NvcGUuXG4gICAqXG4gICAqIEBzZWUge0BsaW5rIGh0dHBzOi8vZG9jcy5kaXNjb3JkLmNvbS9kZXZlbG9wZXJzL3Jlc291cmNlcy91c2VyI2dldC11c2VyLWFwcGxpY2F0aW9uLXJvbGUtY29ubmVjdGlvbn1cbiAgICovXG4gIGFzeW5jIGdldFVzZXJBcHBsaWNhdGlvblJvbGVDb25uZWN0aW9uKFxuICAgIHJlc3Q6IFJlc3RNYW5hZ2VyLFxuICAgIGJlYXJlclRva2VuOiBzdHJpbmcsXG4gICAgYXBwbGljYXRpb25JZDogQmlnU3RyaW5nLFxuICApOiBQcm9taXNlPERpc2NvcmRBcHBsaWNhdGlvblJvbGVDb25uZWN0aW9uPiB7XG4gICAgcmV0dXJuIGF3YWl0IHJlc3QuZ2V0PERpc2NvcmRBcHBsaWNhdGlvblJvbGVDb25uZWN0aW9uPihyZXN0LnJvdXRlcy5vYXV0aDIucm9sZUNvbm5lY3Rpb25zKGFwcGxpY2F0aW9uSWQpLCB7XG4gICAgICBoZWFkZXJzOiB7XG4gICAgICAgIGF1dGhvcml6YXRpb246IGBCZWFyZXIgJHtiZWFyZXJUb2tlbn1gLFxuICAgICAgfSxcbiAgICAgIHVuYXV0aG9yaXplZDogdHJ1ZSxcbiAgICB9KTtcbiAgfSxcbiAgLyoqXG4gICAqIEdldHMgaW5mb3JtYXRpb24gYWJvdXQgdGhlIHZhbml0eSB1cmwgb2YgYSBndWlsZC5cbiAgICpcbiAgICogQHBhcmFtIGd1aWxkSWQgLSBUaGUgSUQgb2YgdGhlIGd1aWxkIHRvIGdldCB0aGUgdmFuaXR5IHVybCBpbmZvcm1hdGlvbiBmb3IuXG4gICAqIEByZXR1cm5zIEFuIGluc3RhbmNlIG9mIHtAbGluayBEaXNjb3JkVmFuaXR5VXJsfS5cbiAgICpcbiAgICogQHJlbWFya3NcbiAgICogUmVxdWlyZXMgdGhlIGBNQU5BR0VfR1VJTERgIHBlcm1pc3Npb24uXG4gICAqXG4gICAqIFRoZSBgY29kZWAgcHJvcGVydHkgd2lsbCBiZSBgbnVsbGAgaWYgdGhlIGd1aWxkIGRvZXMgbm90IGhhdmUgYSBzZXQgdmFuaXR5IHVybC5cbiAgICpcbiAgICogQHNlZSB7QGxpbmsgaHR0cHM6Ly9kb2NzLmRpc2NvcmQuY29tL2RldmVsb3BlcnMvcmVzb3VyY2VzL2d1aWxkI2dldC1ndWlsZC12YW5pdHktdXJsfVxuICAgKi9cbiAgYXN5bmMgZ2V0VmFuaXR5VXJsKHJlc3Q6IFJlc3RNYW5hZ2VyLCBndWlsZElkOiBCaWdTdHJpbmcpOiBQcm9taXNlPERpc2NvcmRWYW5pdHlVcmw+IHtcbiAgICByZXR1cm4gYXdhaXQgcmVzdC5nZXQ8RGlzY29yZFZhbml0eVVybD4ocmVzdC5yb3V0ZXMuZ3VpbGRzLnZhbml0eShndWlsZElkKSk7XG4gIH0sXG4gIC8qKlxuICAgKiBHZXRzIHRoZSBsaXN0IG9mIHZvaWNlIHJlZ2lvbnMgZm9yIGEgZ3VpbGQuXG4gICAqXG4gICAqIEBwYXJhbSBndWlsZElkIC0gVGhlIElEIG9mIHRoZSBndWlsZCB0byBnZXQgdGhlIHZvaWNlIHJlZ2lvbnMgZm9yLlxuICAgKiBAcmV0dXJucyBBIGNvbGxlY3Rpb24gb2Yge0BsaW5rIERpc2NvcmRWb2ljZVJlZ2lvbn0gb2JqZWN0cyBhc3NvcnRlZCBieSB2b2ljZSByZWdpb24gSUQuXG4gICAqXG4gICAqIEBzZWUge0BsaW5rIGh0dHBzOi8vZG9jcy5kaXNjb3JkLmNvbS9kZXZlbG9wZXJzL3Jlc291cmNlcy9ndWlsZCNnZXQtZ3VpbGQtdm9pY2UtcmVnaW9uc31cbiAgICovXG4gIGFzeW5jIGdldFZvaWNlUmVnaW9ucyhyZXN0OiBSZXN0TWFuYWdlciwgZ3VpbGRJZDogQmlnU3RyaW5nKTogUHJvbWlzZTxEaXNjb3JkVm9pY2VSZWdpb25bXT4ge1xuICAgIHJldHVybiBhd2FpdCByZXN0LmdldDxEaXNjb3JkVm9pY2VSZWdpb25bXT4ocmVzdC5yb3V0ZXMuZ3VpbGRzLnJlZ2lvbnMoZ3VpbGRJZCkpO1xuICB9LFxuICAvKipcbiAgICogR2V0cyBhIHdlYmhvb2sgYnkgaXRzIElELlxuICAgKlxuICAgKiBAcGFyYW0gd2ViaG9va0lkIC0gVGhlIElEIG9mIHRoZSB3ZWJob29rIHRvIGdldC5cbiAgICogQHJldHVybnMgQW4gaW5zdGFuY2Ugb2Yge0BsaW5rIERpc2NvcmRXZWJob29rfS5cbiAgICpcbiAgICogQHJlbWFya3NcbiAgICogUmVxdWlyZXMgdGhlIGBNQU5BR0VfV0VCSE9PS1NgIHBlcm1pc3Npb24gdW5sZXNzIHRoZSBhcHBsaWNhdGlvbiBtYWtpbmcgdGhlIHJlcXVlc3Qgb3ducyB0aGUgd2ViaG9vay5cbiAgICpcbiAgICogQHNlZSB7QGxpbmsgaHR0cHM6Ly9kb2NzLmRpc2NvcmQuY29tL2RldmVsb3BlcnMvcmVzb3VyY2VzL3dlYmhvb2sjZ2V0LXdlYmhvb2t9XG4gICAqL1xuICBhc3luYyBnZXRXZWJob29rKHJlc3Q6IFJlc3RNYW5hZ2VyLCB3ZWJob29rSWQ6IEJpZ1N0cmluZyk6IFByb21pc2U8RGlzY29yZFdlYmhvb2s+IHtcbiAgICByZXR1cm4gYXdhaXQgcmVzdC5nZXQ8RGlzY29yZFdlYmhvb2s+KHJlc3Qucm91dGVzLndlYmhvb2tzLmlkKHdlYmhvb2tJZCkpO1xuICB9LFxuICAvKipcbiAgICogR2V0cyBhIHdlYmhvb2sgbWVzc2FnZSBieSBpdHMgSUQuXG4gICAqXG4gICAqIEBwYXJhbSB3ZWJob29rSWQgLSBUaGUgSUQgb2YgdGhlIHdlYmhvb2sgdG8gZ2V0IGEgbWVzc2FnZSBvZi5cbiAgICogQHBhcmFtIHRva2VuIC0gVGhlIHdlYmhvb2sgdG9rZW4sIHVzZWQgdG8gZ2V0IHdlYmhvb2sgbWVzc2FnZXMuXG4gICAqIEBwYXJhbSBtZXNzYWdlSWQgLSB0aGUgSUQgb2YgdGhlIHdlYmhvb2sgbWVzc2FnZSB0byBnZXQuXG4gICAqIEBwYXJhbSBvcHRpb25zIC0gVGhlIHBhcmFtZXRlcnMgZm9yIHRoZSBmZXRjaGluZyBvZiB0aGUgbWVzc2FnZS5cbiAgICogQHJldHVybnMgQW4gaW5zdGFuY2Ugb2Yge0BsaW5rIERpc2NvcmRNZXNzYWdlfS5cbiAgICpcbiAgICogQHNlZSB7QGxpbmsgaHR0cHM6Ly9kb2NzLmRpc2NvcmQuY29tL2RldmVsb3BlcnMvcmVzb3VyY2VzL3dlYmhvb2sjZ2V0LXdlYmhvb2stbWVzc2FnZX1cbiAgICovXG4gIGFzeW5jIGdldFdlYmhvb2tNZXNzYWdlKFxuICAgIHJlc3Q6IFJlc3RNYW5hZ2VyLFxuICAgIHdlYmhvb2tJZDogQmlnU3RyaW5nLFxuICAgIHRva2VuOiBzdHJpbmcsXG4gICAgbWVzc2FnZUlkOiBCaWdTdHJpbmcsXG4gICAgb3B0aW9ucz86IEdldFdlYmhvb2tNZXNzYWdlT3B0aW9ucyxcbiAgKTogUHJvbWlzZTxEaXNjb3JkTWVzc2FnZT4ge1xuICAgIHJldHVybiBhd2FpdCByZXN0LmdldDxEaXNjb3JkTWVzc2FnZT4ocmVzdC5yb3V0ZXMud2ViaG9va3MubWVzc2FnZSh3ZWJob29rSWQsIHRva2VuLCBtZXNzYWdlSWQsIG9wdGlvbnMpLCB7XG4gICAgICB1bmF1dGhvcml6ZWQ6IHRydWUsXG4gICAgfSk7XG4gIH0sXG4gIC8qKlxuICAgKiBHZXRzIGEgd2ViaG9vayB1c2luZyB0aGUgd2ViaG9vayB0b2tlbiwgdGhlcmVieSBieXBhc3NpbmcgdGhlIG5lZWQgZm9yIGF1dGhlbnRpY2F0aW9uICsgcGVybWlzc2lvbnMuXG4gICAqXG4gICAqIEBwYXJhbSB3ZWJob29rSWQgLSBUaGUgSUQgb2YgdGhlIHdlYmhvb2sgdG8gZ2V0LlxuICAgKiBAcGFyYW0gdG9rZW4gLSBUaGUgd2ViaG9vayB0b2tlbiwgdXNlZCB0byBnZXQgdGhlIHdlYmhvb2suXG4gICAqIEByZXR1cm5zIEFuIGluc3RhbmNlIG9mIHtAbGluayBEaXNjb3JkV2ViaG9va30uXG4gICAqXG4gICAqIEBzZWUge0BsaW5rIGh0dHBzOi8vZG9jcy5kaXNjb3JkLmNvbS9kZXZlbG9wZXJzL3Jlc291cmNlcy93ZWJob29rI2dldC13ZWJob29rLXdpdGgtdG9rZW59XG4gICAqL1xuICBhc3luYyBnZXRXZWJob29rV2l0aFRva2VuKHJlc3Q6IFJlc3RNYW5hZ2VyLCB3ZWJob29rSWQ6IEJpZ1N0cmluZywgdG9rZW46IHN0cmluZyk6IFByb21pc2U8RGlzY29yZFdlYmhvb2s+IHtcbiAgICByZXR1cm4gYXdhaXQgcmVzdC5nZXQ8RGlzY29yZFdlYmhvb2s+KHJlc3Qucm91dGVzLndlYmhvb2tzLndlYmhvb2sod2ViaG9va0lkLCB0b2tlbiksIHtcbiAgICAgIHVuYXV0aG9yaXplZDogdHJ1ZSxcbiAgICB9KTtcbiAgfSxcbiAgLyoqXG4gICAqIEdldHMgdGhlIHdlbGNvbWUgc2NyZWVuIGZvciBhIGd1aWxkLlxuICAgKlxuICAgKiBAcGFyYW0gZ3VpbGRJZCAtIFRoZSBJRCBvZiB0aGUgZ3VpbGQgdG8gZ2V0IHRoZSB3ZWxjb21lIHNjcmVlbiBmb3IuXG4gICAqIEByZXR1cm5zIEFuIGluc3RhbmNlIG9mIHtAbGluayBEaXNjb3JkV2VsY29tZVNjcmVlbn0uXG4gICAqXG4gICAqIEByZW1hcmtzXG4gICAqIElmIHRoZSB3ZWxjb21lIHNjcmVlbiBpcyBub3QgZW5hYmxlZDpcbiAgICogLSBSZXF1aXJlcyB0aGUgYE1BTkFHRV9HVUlMRGAgcGVybWlzc2lvbi5cbiAgICpcbiAgICogQHNlZSB7QGxpbmsgaHR0cHM6Ly9kb2NzLmRpc2NvcmQuY29tL2RldmVsb3BlcnMvcmVzb3VyY2VzL2d1aWxkI2dldC1ndWlsZC13ZWxjb21lLXNjcmVlbn1cbiAgICovXG4gIGFzeW5jIGdldFdlbGNvbWVTY3JlZW4ocmVzdDogUmVzdE1hbmFnZXIsIGd1aWxkSWQ6IEJpZ1N0cmluZyk6IFByb21pc2U8RGlzY29yZFdlbGNvbWVTY3JlZW4+IHtcbiAgICByZXR1cm4gYXdhaXQgcmVzdC5nZXQ8RGlzY29yZFdlbGNvbWVTY3JlZW4+KHJlc3Qucm91dGVzLmd1aWxkcy53ZWxjb21lKGd1aWxkSWQpKTtcbiAgfSxcbiAgLyoqXG4gICAqIEdldHMgdGhlIGd1aWxkIHdpZGdldCBieSBndWlsZCBJRC5cbiAgICpcbiAgICogQHBhcmFtIGd1aWxkSWQgLSBUaGUgSUQgb2YgdGhlIGd1aWxkIHRvIGdldCB0aGUgd2lkZ2V0IG9mLlxuICAgKiBAcmV0dXJucyBBbiBpbnN0YW5jZSBvZiB7QGxpbmsgRGlzY29yZEd1aWxkV2lkZ2V0fS5cbiAgICpcbiAgICogQHJlbWFya3NcbiAgICogRmlyZXMgYW4gYElOVklURV9DUkVBVEVEYCBHYXRld2F5IGV2ZW50IHdoZW4gYW4gaW52aXRlIGNoYW5uZWwgaXMgZGVmaW5lZCBhbmQgYSBuZXcgYEludml0ZWAgaXMgZ2VuZXJhdGVkLlxuICAgKlxuICAgKiBAc2VlIHtAbGluayBodHRwczovL2RvY3MuZGlzY29yZC5jb20vZGV2ZWxvcGVycy9yZXNvdXJjZXMvZ3VpbGQjZ2V0LWd1aWxkLXdpZGdldH1cbiAgICovXG4gIGFzeW5jIGdldFdpZGdldChyZXN0OiBSZXN0TWFuYWdlciwgZ3VpbGRJZDogQmlnU3RyaW5nKTogUHJvbWlzZTxEaXNjb3JkR3VpbGRXaWRnZXQ+IHtcbiAgICByZXR1cm4gYXdhaXQgcmVzdC5nZXQ8RGlzY29yZEd1aWxkV2lkZ2V0PihyZXN0LnJvdXRlcy5ndWlsZHMud2lkZ2V0SnNvbihndWlsZElkKSk7XG4gIH0sXG4gIC8qKlxuICAgKiBHZXRzIHRoZSBzZXR0aW5ncyBvZiBhIGd1aWxkJ3Mgd2lkZ2V0LlxuICAgKlxuICAgKiBAcGFyYW0gZ3VpbGRJZCAtIFRoZSBJRCBvZiB0aGUgZ3VpbGQgdG8gZ2V0IHRoZSB3aWRnZXQgb2YuXG4gICAqIEByZXR1cm5zIEFuIGluc3RhbmNlIG9mIHtAbGluayBEaXNjb3JkR3VpbGRXaWRnZXRTZXR0aW5nc30uXG4gICAqXG4gICAqIEByZW1hcmtzXG4gICAqIFJlcXVpcmVzIHRoZSBgTUFOQUdFX0dVSUxEYCBwZXJtaXNzaW9uLlxuICAgKlxuICAgKiBAc2VlIHtAbGluayBodHRwczovL2RvY3MuZGlzY29yZC5jb20vZGV2ZWxvcGVycy9yZXNvdXJjZXMvZ3VpbGQjZ2V0LWd1aWxkLXdpZGdldC1zZXR0aW5nc31cbiAgICovXG4gIGFzeW5jIGdldFdpZGdldFNldHRpbmdzKHJlc3Q6IFJlc3RNYW5hZ2VyLCBndWlsZElkOiBCaWdTdHJpbmcpOiBQcm9taXNlPERpc2NvcmRHdWlsZFdpZGdldFNldHRpbmdzPiB7XG4gICAgcmV0dXJuIGF3YWl0IHJlc3QuZ2V0PERpc2NvcmRHdWlsZFdpZGdldFNldHRpbmdzPihyZXN0LnJvdXRlcy5ndWlsZHMud2lkZ2V0KGd1aWxkSWQpKTtcbiAgfSxcbiAgLyoqXG4gICAqIEFkZHMgdGhlIGJvdCB1c2VyIHRvIGEgdGhyZWFkLlxuICAgKlxuICAgKiBAcGFyYW0gY2hhbm5lbElkIC0gVGhlIElEIG9mIHRoZSB0aHJlYWQgdG8gYWRkIHRoZSBib3QgdXNlciB0by5cbiAgICpcbiAgICogQHJlbWFya3NcbiAgICogUmVxdWlyZXMgdGhlIHRocmVhZCBub3QgYmUgYXJjaGl2ZWQuXG4gICAqXG4gICAqIEZpcmVzIGEgX1RocmVhZCBNZW1iZXJzIFVwZGF0ZV8gZ2F0ZXdheSBldmVudC5cbiAgICpcbiAgICogQHNlZSB7QGxpbmsgaHR0cHM6Ly9kb2NzLmRpc2NvcmQuY29tL2RldmVsb3BlcnMvcmVzb3VyY2VzL2NoYW5uZWwjam9pbi10aHJlYWR9XG4gICAqL1xuICBhc3luYyBqb2luVGhyZWFkKHJlc3Q6IFJlc3RNYW5hZ2VyLCBjaGFubmVsSWQ6IEJpZ1N0cmluZyk6IFByb21pc2U8dm9pZD4ge1xuICAgIGF3YWl0IHJlc3QucHV0KHJlc3Qucm91dGVzLmNoYW5uZWxzLnRocmVhZHMubWUoY2hhbm5lbElkKSk7XG4gIH0sXG4gIC8qKlxuICAgKiBMZWF2ZXMgYSBndWlsZC5cbiAgICpcbiAgICogQHBhcmFtIGd1aWxkSWQgLSBUaGUgSUQgb2YgdGhlIGd1aWxkIHRvIGxlYXZlLlxuICAgKlxuICAgKiBAcmVtYXJrc1xuICAgKiBGaXJlcyBhIF9HdWlsZCBEZWxldGVfIGV2ZW50LlxuICAgKlxuICAgKiBAc2VlIHtAbGluayBodHRwczovL2RvY3MuZGlzY29yZC5jb20vZGV2ZWxvcGVycy9yZXNvdXJjZXMvdXNlciNsZWF2ZS1ndWlsZH1cbiAgICovXG4gIGFzeW5jIGxlYXZlR3VpbGQocmVzdDogUmVzdE1hbmFnZXIsIGd1aWxkSWQ6IEJpZ1N0cmluZyk6IFByb21pc2U8dm9pZD4ge1xuICAgIGF3YWl0IHJlc3QuZGVsZXRlKHJlc3Qucm91dGVzLmd1aWxkcy5sZWF2ZShndWlsZElkKSk7XG4gIH0sXG4gIC8qKlxuICAgKiBSZW1vdmVzIHRoZSBib3QgdXNlciBmcm9tIGEgdGhyZWFkLlxuICAgKlxuICAgKiBAcGFyYW0gY2hhbm5lbElkIC0gVGhlIElEIG9mIHRoZSB0aHJlYWQgdG8gcmVtb3ZlIHRoZSBib3QgdXNlciBmcm9tLlxuICAgKlxuICAgKiBAcmVtYXJrc1xuICAgKiBSZXF1aXJlcyB0aGUgdGhyZWFkIG5vdCBiZSBhcmNoaXZlZC5cbiAgICpcbiAgICogRmlyZXMgYSBfVGhyZWFkIE1lbWJlcnMgVXBkYXRlXyBnYXRld2F5IGV2ZW50LlxuICAgKlxuICAgKiBAc2VlIHtAbGluayBodHRwczovL2RvY3MuZGlzY29yZC5jb20vZGV2ZWxvcGVycy9yZXNvdXJjZXMvY2hhbm5lbCNsZWF2ZS10aHJlYWR9XG4gICAqL1xuICBhc3luYyBsZWF2ZVRocmVhZChyZXN0OiBSZXN0TWFuYWdlciwgY2hhbm5lbElkOiBCaWdTdHJpbmcpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBhd2FpdCByZXN0LmRlbGV0ZShyZXN0LnJvdXRlcy5jaGFubmVscy50aHJlYWRzLm1lKGNoYW5uZWxJZCkpO1xuICB9LFxuICAvKipcbiAgICogQ3Jvc3MtcG9zdHMgYSBtZXNzYWdlIHBvc3RlZCBpbiBhbiBhbm5vdW5jZW1lbnQgY2hhbm5lbCB0byBzdWJzY3JpYmVkIGNoYW5uZWxzLlxuICAgKlxuICAgKiBAcGFyYW0gY2hhbm5lbElkIC0gVGhlIElEIG9mIHRoZSBhbm5vdW5jZW1lbnQgY2hhbm5lbC5cbiAgICogQHBhcmFtIG1lc3NhZ2VJZCAtIFRoZSBJRCBvZiB0aGUgbWVzc2FnZSB0byBjcm9zcy1wb3N0LlxuICAgKiBAcmV0dXJucyBBbiBpbnN0YW5jZSBvZiB0aGUgY3Jvc3MtcG9zdGVkIHtAbGluayBEaXNjb3JkTWVzc2FnZX0uXG4gICAqXG4gICAqIEByZW1hcmtzXG4gICAqIFJlcXVpcmVzIHRoZSBgU0VORF9NRVNTQUdFU2AgcGVybWlzc2lvbi5cbiAgICpcbiAgICogSWYgbm90IGNyb3NzLXBvc3Rpbmcgb3duIG1lc3NhZ2U6XG4gICAqIC0gUmVxdWlyZXMgdGhlIGBNQU5BR0VfTUVTU0FHRVNgIHBlcm1pc3Npb24uXG4gICAqXG4gICAqIEZpcmVzIGEgX01lc3NhZ2UgQ3JlYXRlXyBldmVudCBpbiB0aGUgZ3VpbGRzIHRoZSBzdWJzY3JpYmVkIGNoYW5uZWxzIGFyZSBpbi5cbiAgICpcbiAgICogQHNlZSB7QGxpbmsgaHR0cHM6Ly9kb2NzLmRpc2NvcmQuY29tL2RldmVsb3BlcnMvcmVzb3VyY2VzL2NoYW5uZWwjY3Jvc3Nwb3N0LW1lc3NhZ2V9XG4gICAqL1xuICBhc3luYyBwdWJsaXNoTWVzc2FnZShyZXN0OiBSZXN0TWFuYWdlciwgY2hhbm5lbElkOiBCaWdTdHJpbmcsIG1lc3NhZ2VJZDogQmlnU3RyaW5nKTogUHJvbWlzZTxEaXNjb3JkTWVzc2FnZT4ge1xuICAgIHJldHVybiBhd2FpdCByZXN0LnBvc3Q8RGlzY29yZE1lc3NhZ2U+KHJlc3Qucm91dGVzLmNoYW5uZWxzLmNyb3NzcG9zdChjaGFubmVsSWQsIG1lc3NhZ2VJZCkpO1xuICB9LFxuICAvKipcbiAgICogUmVtb3ZlcyBhIHJvbGUgZnJvbSBhIG1lbWJlci5cbiAgICpcbiAgICogQHBhcmFtIGd1aWxkSWQgLSBUaGUgSUQgb2YgdGhlIGd1aWxkIHRoZSBtZW1iZXIgdG8gcmVtb3ZlIHRoZSByb2xlIGZyb20gaXMgaW4uXG4gICAqIEBwYXJhbSB1c2VySWQgLSBUaGUgdXNlciBJRCBvZiB0aGUgbWVtYmVyIHRvIHJlbW92ZSB0aGUgcm9sZSBmcm9tLlxuICAgKiBAcGFyYW0gcm9sZUlkIC0gVGhlIElEIG9mIHRoZSByb2xlIHRvIHJlbW92ZSBmcm9tIHRoZSBtZW1iZXIuXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBbcmVhc29uXSAtIEFuIG9wdGlvbmFsIHJlYXNvbiBmb3IgdGhlIGFjdGlvbiwgdG8gYmUgaW5jbHVkZWQgaW4gdGhlIGF1ZGl0IGxvZy5cbiAgICpcbiAgICogQHJlbWFya3NcbiAgICogUmVxdWlyZXMgdGhlIGBNQU5BR0VfUk9MRVNgIHBlcm1pc3Npb24uXG4gICAqXG4gICAqIEZpcmVzIGEgX0d1aWxkIE1lbWJlciBVcGRhdGVfIGdhdGV3YXkgZXZlbnQuXG4gICAqXG4gICAqIEBzZWUge0BsaW5rIGh0dHBzOi8vZG9jcy5kaXNjb3JkLmNvbS9kZXZlbG9wZXJzL3Jlc291cmNlcy9ndWlsZCNyZW1vdmUtZ3VpbGQtbWVtYmVyLXJvbGV9XG4gICAqL1xuICBhc3luYyByZW1vdmVSb2xlKHJlc3Q6IFJlc3RNYW5hZ2VyLCBndWlsZElkOiBCaWdTdHJpbmcsIHVzZXJJZDogQmlnU3RyaW5nLCByb2xlSWQ6IEJpZ1N0cmluZywgcmVhc29uPzogc3RyaW5nKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgYXdhaXQgcmVzdC5kZWxldGUocmVzdC5yb3V0ZXMuZ3VpbGRzLnJvbGVzLm1lbWJlcihndWlsZElkLCB1c2VySWQsIHJvbGVJZCksIHsgcmVhc29uIH0pO1xuICB9LFxuICAvKipcbiAgICogUmVtb3ZlcyBhIG1lbWJlciBmcm9tIGEgdGhyZWFkLlxuICAgKlxuICAgKiBAcGFyYW0gY2hhbm5lbElkIC0gVGhlIElEIG9mIHRoZSB0aHJlYWQgdG8gcmVtb3ZlIHRoZSB0aHJlYWQgbWVtYmVyIG9mLlxuICAgKiBAcGFyYW0gdXNlcklkIC0gVGhlIHVzZXIgSUQgb2YgdGhlIHRocmVhZCBtZW1iZXIgdG8gcmVtb3ZlLlxuICAgKlxuICAgKiBAcmVtYXJrc1xuICAgKiBJZiB0aGUgdGhyZWFkIGlzIG9mIHR5cGUge0BsaW5rIENoYW5uZWxUeXBlc30uR3VpbGRQcml2YXRlVGhyZWFkLCByZXF1aXJlcyB0byBiZSB0aGUgY3JlYXRvciBvZiB0aGUgdGhyZWFkLlxuICAgKiBPdGhlcndpc2UsIHJlcXVpcmVzIHRoZSBgTUFOQUdFX1RIUkVBRFNgIHBlcm1pc3Npb24uXG4gICAqXG4gICAqIFJlcXVpcmVzIHRoZSB0aHJlYWQgbm90IGJlIGFyY2hpdmVkLlxuICAgKlxuICAgKiBGaXJlcyBhIF9UaHJlYWQgTWVtYmVycyBVcGRhdGVfIGdhdGV3YXkgZXZlbnQuXG4gICAqXG4gICAqIEBzZWUge0BsaW5rIGh0dHBzOi8vZG9jcy5kaXNjb3JkLmNvbS9kZXZlbG9wZXJzL3Jlc291cmNlcy9jaGFubmVsI3JlbW92ZS10aHJlYWQtbWVtYmVyfVxuICAgKi9cbiAgYXN5bmMgcmVtb3ZlVGhyZWFkTWVtYmVyKHJlc3Q6IFJlc3RNYW5hZ2VyLCBjaGFubmVsSWQ6IEJpZ1N0cmluZywgdXNlcklkOiBCaWdTdHJpbmcpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBhd2FpdCByZXN0LmRlbGV0ZShyZXN0LnJvdXRlcy5jaGFubmVscy50aHJlYWRzLnVzZXIoY2hhbm5lbElkLCB1c2VySWQpKTtcbiAgfSxcbiAgLyoqXG4gICAqIFJlbW92ZXMgYSBtZW1iZXIgZnJvbSBhIEdyb3VwIERNLlxuICAgKlxuICAgKiBAcGFyYW0gY2hhbm5lbElkIC0gVGhlIElEIG9mIHRoZSBjaGFubmVsIHRvIHJlbW92ZSB0aGUgcmVjaXBpZW50IHVzZXIgb2YuXG4gICAqIEBwYXJhbSB1c2VySWQgLSBUaGUgdXNlciBJRCBvZiB0aGUgdXNlciB0byByZW1vdmUuXG4gICAqXG4gICAqIEBzZWUge0BsaW5rIGh0dHBzOi8vZG9jcy5kaXNjb3JkLmNvbS9kZXZlbG9wZXJzL3Jlc291cmNlcy9jaGFubmVsI2dyb3VwLWRtLXJlbW92ZS1yZWNpcGllbnR9XG4gICAqL1xuICBhc3luYyByZW1vdmVEbVJlY2lwaWVudChyZXN0OiBSZXN0TWFuYWdlciwgY2hhbm5lbElkOiBCaWdTdHJpbmcsIHVzZXJJZDogQmlnU3RyaW5nKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgYXdhaXQgcmVzdC5kZWxldGUocmVzdC5yb3V0ZXMuY2hhbm5lbHMuZG1SZWNpcGllbnQoY2hhbm5lbElkLCB1c2VySWQpKTtcbiAgfSxcbiAgLyoqXG4gICAqIFNlbmRzIGEgbWVzc2FnZSB0byBhIGNoYW5uZWwuXG4gICAqXG4gICAqIEBwYXJhbSBjaGFubmVsSWQgLSBUaGUgSUQgb2YgdGhlIGNoYW5uZWwgdG8gc2VuZCB0aGUgbWVzc2FnZSBpbi5cbiAgICogQHBhcmFtIG9wdGlvbnMgLSBUaGUgcGFyYW1ldGVycyBmb3IgdGhlIGNyZWF0aW9uIG9mIHRoZSBtZXNzYWdlLlxuICAgKiBAcmV0dXJucyBBbiBpbnN0YW5jZSBvZiB0aGUgY3JlYXRlZCB7QGxpbmsgRGlzY29yZE1lc3NhZ2V9LlxuICAgKlxuICAgKiBAcmVtYXJrc1xuICAgKiBSZXF1aXJlcyB0aGF0IHRoZSBib3QgdXNlciBiZSBhYmxlIHRvIHNlZSB0aGUgY29udGVudHMgb2YgdGhlIGNoYW5uZWwgdGhlIG1lc3NhZ2UgaXMgdG8gYmUgc2VudCBpbi5cbiAgICpcbiAgICogSWYgc2VuZGluZyBhIG1lc3NhZ2UgdG8gYSBndWlsZCBjaGFubmVsOlxuICAgKiAtIFJlcXVpcmVzIHRoZSBgU0VORF9NRVNTQUdFU2AgcGVybWlzc2lvbi5cbiAgICpcbiAgICogSWYgc2VuZGluZyBhIFRUUyBtZXNzYWdlOlxuICAgKiAtIFJlcXVpcmVzIHRoZSBgU0VORF9UVFNfTUVTU0FHRVNgIHBlcm1pc3Npb24uXG4gICAqXG4gICAqIElmIHNlbmRpbmcgYSBtZXNzYWdlIGFzIGEgcmVwbHkgdG8gYW5vdGhlciBtZXNzYWdlOlxuICAgKiAtIFJlcXVpcmVzIHRoZSBgUkVBRF9NRVNTQUdFX0hJU1RPUllgIHBlcm1pc3Npb24uXG4gICAqIC0gVGhlIG1lc3NhZ2UgYmVpbmcgcmVwbGllZCB0byBjYW5ub3QgYmUgYSBzeXN0ZW0gbWVzc2FnZS5cbiAgICpcbiAgICog4pqg77iPIFRoZSBtYXhpbXVtIHNpemUgb2YgYSByZXF1ZXN0IChhY2NvdW50aW5nIGZvciBhbnkgYXR0YWNobWVudHMgYW5kIG1lc3NhZ2UgY29udGVudCkgZm9yIGJvdCB1c2VycyBpcyBfOCBNaUJfLlxuICAgKlxuICAgKiBGaXJlcyBhIF9NZXNzYWdlIENyZWF0ZV8gZ2F0ZXdheSBldmVudC5cbiAgICpcbiAgICogQHNlZSB7QGxpbmsgaHR0cHM6Ly9kb2NzLmRpc2NvcmQuY29tL2RldmVsb3BlcnMvcmVzb3VyY2VzL2NoYW5uZWwjY3JlYXRlLW1lc3NhZ2V9XG4gICAqL1xuICBhc3luYyBzZW5kTWVzc2FnZShyZXN0OiBSZXN0TWFuYWdlciwgY2hhbm5lbElkOiBCaWdTdHJpbmcsIG9wdGlvbnM6IENyZWF0ZU1lc3NhZ2VPcHRpb25zKTogUHJvbWlzZTxEaXNjb3JkTWVzc2FnZT4ge1xuICAgIHJldHVybiBhd2FpdCByZXN0LnBvc3Q8RGlzY29yZE1lc3NhZ2U+KHJlc3Qucm91dGVzLmNoYW5uZWxzLm1lc3NhZ2VzKGNoYW5uZWxJZCksIHsgYm9keTogb3B0aW9ucywgZmlsZXM6IG9wdGlvbnMuZmlsZXMgfSk7XG4gIH0sXG4gIC8qKlxuICAgKiBTZW5kcyBhIGZvbGxvdy11cCBtZXNzYWdlIHRvIGFuIGludGVyYWN0aW9uLlxuICAgKlxuICAgKiBAcGFyYW0gdG9rZW4gLSBUaGUgaW50ZXJhY3Rpb24gdG9rZW4gdG8gdXNlLCBwcm92aWRlZCBpbiB0aGUgb3JpZ2luYWwgaW50ZXJhY3Rpb24uXG4gICAqIEBwYXJhbSBvcHRpb25zIC0gVGhlIHBhcmFtZXRlcnMgZm9yIHRoZSBjcmVhdGlvbiBvZiB0aGUgbWVzc2FnZS5cbiAgICogQHJldHVybnMgQW4gaW5zdGFuY2Ugb2YgdGhlIGNyZWF0ZWQge0BsaW5rIERpc2NvcmRNZXNzYWdlfS5cbiAgICpcbiAgICogQHJlbWFya3NcbiAgICog4pqg77iPIEludGVyYWN0aW9uIHRva2VucyBhcmUgb25seSB2YWxpZCBmb3IgXzE1IG1pbnV0ZXNfLlxuICAgKlxuICAgKiBCeSBkZWZhdWx0LCBtZW50aW9ucyBhcmUgc3VwcHJlc3NlZC4gVG8gZW5hYmxlIG1lbnRpb25zLCBwYXNzIGEgbWVudGlvbiBvYmplY3Qgd2l0aCB0aGUgY2FsbGJhY2sgZGF0YS5cbiAgICpcbiAgICogVW5saWtlIGBzZW5kTWVzc2FnZSgpYCwgdGhpcyBlbmRwb2ludCBhbGxvd3MgdGhlIGJvdCB1c2VyIHRvIGFjdCB3aXRob3V0OlxuICAgKiAtIE5lZWRpbmcgdG8gYmUgYWJsZSB0byBzZWUgdGhlIGNvbnRlbnRzIG9mIHRoZSBjaGFubmVsIHRoYXQgdGhlIG1lc3NhZ2UgaXMgaW4uIChgUkVBRF9NRVNTQUdFU2AgcGVybWlzc2lvbi4pXG4gICAqIC0gUmVxdWlyaW5nIHRoZSBgTUVTU0FHRV9DT05URU5UYCBpbnRlbnQuXG4gICAqXG4gICAqIEFwcHMgYXJlIGxpbWl0ZWQgdG8gNSBmb2xsb3d1cCBtZXNzYWdlcyBwZXIgaW50ZXJhY3Rpb24gaWYgaXQgd2FzIGluaXRpYXRlZCBmcm9tIGEgdXNlci1pbnN0YWxsZWQgYXBwIGFuZCBpc24ndCBpbnN0YWxsZWQgaW4gdGhlIHNlcnZlclxuICAgKiBZb3UgY2FuIGNoZWNrIGlmIGl0IHdhcyBpbml0aWF0ZWQgZnJvbSBhIHVzZXItaW5zdGFsbGVkIGFwcCB0aGF0IGlzbid0IGluc3RhbGxlZCBpbiB0aGUgc2VydmVyIGJ5IGNoZWNraW5nIGlmIHtAbGluayBEaXNjb3JkSW50ZXJhY3Rpb24uYXV0aG9yaXppbmdfaW50ZWdyYXRpb25fb3duZXJzIHwgYXV0aG9yaXppbmdJbnRlZ3JhdGlvbk93bmVyc30gb25seSBjb250YWlucyB7QGxpbmsgRGlzY29yZEFwcGxpY2F0aW9uSW50ZWdyYXRpb25UeXBlLlVzZXJJbnN0YWxsIHwgVXNlckluc3RhbGx9LlxuICAgKlxuICAgKiBGaXJlcyBhIF9NZXNzYWdlIENyZWF0ZV8gZXZlbnQuXG4gICAqXG4gICAqIEBzZWUge0BsaW5rIGh0dHBzOi8vZG9jcy5kaXNjb3JkLmNvbS9kZXZlbG9wZXJzL2ludGVyYWN0aW9ucy9yZWNlaXZpbmctYW5kLXJlc3BvbmRpbmcjY3JlYXRlLWZvbGxvd3VwLW1lc3NhZ2V9XG4gICAqL1xuICBhc3luYyBzZW5kRm9sbG93dXBNZXNzYWdlKHJlc3Q6IFJlc3RNYW5hZ2VyLCB0b2tlbjogc3RyaW5nLCBvcHRpb25zOiBJbnRlcmFjdGlvbkNhbGxiYWNrRGF0YSk6IFByb21pc2U8RGlzY29yZE1lc3NhZ2U+IHtcbiAgICByZXR1cm4gYXdhaXQgcmVzdC5wb3N0KHJlc3Qucm91dGVzLndlYmhvb2tzLndlYmhvb2socmVzdC5hcHBsaWNhdGlvbklkLCB0b2tlbiksIHtcbiAgICAgIGJvZHk6IG9wdGlvbnMsXG4gICAgICBmaWxlczogb3B0aW9ucy5maWxlcyxcbiAgICAgIHVuYXV0aG9yaXplZDogdHJ1ZSxcbiAgICB9KTtcbiAgfSxcbiAgLyoqXG4gICAqIFNlbmRzIGEgcmVzcG9uc2UgdG8gYW4gaW50ZXJhY3Rpb24uXG4gICAqXG4gICAqIEBwYXJhbSBpbnRlcmFjdGlvbklkIC0gVGhlIElEIG9mIHRoZSBpbnRlcmFjdGlvbiB0byByZXNwb25kIHRvLlxuICAgKiBAcGFyYW0gdG9rZW4gLSBUaGUgaW50ZXJhY3Rpb24gdG9rZW4gdG8gdXNlLCBwcm92aWRlZCBpbiB0aGUgb3JpZ2luYWwgaW50ZXJhY3Rpb24uXG4gICAqIEBwYXJhbSBvcHRpb25zIC0gVGhlIHBhcmFtZXRlcnMgZm9yIHRoZSBjcmVhdGlvbiBvZiB0aGUgbWVzc2FnZS5cbiAgICogQHBhcmFtIHBhcmFtcyAtIFRoZSBxdWVyeSBwYXJhbWV0ZXJzIGZvciB0aGUgcmVzcG9uc2Ugb2YgdGhlIGNhbGxiYWNrXG4gICAqIEByZXR1cm5zIE5vdGhpbmcgb3IgdGhlIHtAbGluayBEaXNjb3JkSW50ZXJhY3Rpb25DYWxsYmFja1Jlc3BvbnNlfSBpZiB3aXRoUmVzcG9uc2UgcGFyYW0gaXMgdHJ1ZVxuICAgKlxuICAgKiBAcmVtYXJrc1xuICAgKiDimqDvuI8gSW50ZXJhY3Rpb24gdG9rZW5zIGFyZSBvbmx5IHZhbGlkIGZvciBfMTUgbWludXRlc18uXG4gICAqXG4gICAqIEJ5IGRlZmF1bHQsIG1lbnRpb25zIGFyZSBzdXBwcmVzc2VkLiBUbyBlbmFibGUgbWVudGlvbnMsIHBhc3MgYSBtZW50aW9uIG9iamVjdCB3aXRoIHRoZSBjYWxsYmFjayBkYXRhLlxuICAgKlxuICAgKiBVbmxpa2UgYHNlbmRNZXNzYWdlKClgLCB0aGlzIGVuZHBvaW50IGFsbG93cyB0aGUgYm90IHVzZXIgdG8gYWN0IHdpdGhvdXQ6XG4gICAqIC0gTmVlZGluZyB0byBiZSBhYmxlIHRvIHNlZSB0aGUgY29udGVudHMgb2YgdGhlIGNoYW5uZWwgdGhhdCB0aGUgbWVzc2FnZSBpcyBpbi4gKGBSRUFEX01FU1NBR0VTYCBwZXJtaXNzaW9uLilcbiAgICogLSBSZXF1aXJpbmcgdGhlIGBNRVNTQUdFX0NPTlRFTlRgIGludGVudC5cbiAgICpcbiAgICogRmlyZXMgYSBfTWVzc2FnZSBDcmVhdGVfIGV2ZW50LlxuICAgKlxuICAgKiBAc2VlIHtAbGluayBodHRwczovL2RvY3MuZGlzY29yZC5jb20vZGV2ZWxvcGVycy9pbnRlcmFjdGlvbnMvcmVjZWl2aW5nLWFuZC1yZXNwb25kaW5nI2NyZWF0ZS1pbnRlcmFjdGlvbi1yZXNwb25zZX1cbiAgICovXG4gIGFzeW5jIHNlbmRJbnRlcmFjdGlvblJlc3BvbnNlKFxuICAgIHJlc3Q6IFJlc3RNYW5hZ2VyLFxuICAgIGludGVyYWN0aW9uSWQ6IEJpZ1N0cmluZyxcbiAgICB0b2tlbjogc3RyaW5nLFxuICAgIG9wdGlvbnM6IEludGVyYWN0aW9uUmVzcG9uc2UsXG4gICAgcGFyYW1zPzogSW50ZXJhY3Rpb25DYWxsYmFja09wdGlvbnMsXG4gICk6IFByb21pc2U8dm9pZCB8IERpc2NvcmRJbnRlcmFjdGlvbkNhbGxiYWNrUmVzcG9uc2U+IHtcbiAgICByZXR1cm4gYXdhaXQgcmVzdC5wb3N0PHZvaWQgfCBEaXNjb3JkSW50ZXJhY3Rpb25DYWxsYmFja1Jlc3BvbnNlPihyZXN0LnJvdXRlcy5pbnRlcmFjdGlvbnMucmVzcG9uc2VzLmNhbGxiYWNrKGludGVyYWN0aW9uSWQsIHRva2VuLCBwYXJhbXMpLCB7XG4gICAgICBib2R5OiBvcHRpb25zLFxuICAgICAgZmlsZXM6IG9wdGlvbnMuZGF0YT8uZmlsZXMsXG4gICAgICBydW5UaHJvdWdoUXVldWU6IGZhbHNlLFxuICAgICAgdW5hdXRob3JpemVkOiB0cnVlLFxuICAgIH0pO1xuICB9LFxuICAvKipcbiAgICogQ3JlYXRlcyBhIHRocmVhZCwgdXNpbmcgYW4gZXhpc3RpbmcgbWVzc2FnZSBhcyBpdHMgcG9pbnQgb2Ygb3JpZ2luLlxuICAgKlxuICAgKiBAcGFyYW0gY2hhbm5lbElkIC0gVGhlIElEIG9mIHRoZSBjaGFubmVsIGluIHdoaWNoIHRvIGNyZWF0ZSB0aGUgdGhyZWFkLlxuICAgKiBAcGFyYW0gbWVzc2FnZUlkIC0gVGhlIElEIG9mIHRoZSBtZXNzYWdlIHRvIHVzZSBhcyB0aGUgdGhyZWFkJ3MgcG9pbnQgb2Ygb3JpZ2luLlxuICAgKiBAcGFyYW0gb3B0aW9ucyAtIFRoZSBwYXJhbWV0ZXJzIHRvIHVzZSBmb3IgdGhlIGNyZWF0aW9uIG9mIHRoZSB0aHJlYWQuXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBbcmVhc29uXSAtIEFuIG9wdGlvbmFsIHJlYXNvbiBmb3IgdGhlIGFjdGlvbiwgdG8gYmUgaW5jbHVkZWQgaW4gdGhlIGF1ZGl0IGxvZy5cbiAgICogQHJldHVybnMgQW4gaW5zdGFuY2Ugb2YgdGhlIGNyZWF0ZWQge0BsaW5rIERpc2NvcmRDaGFubmVsfS5cbiAgICpcbiAgICogQHJlbWFya3NcbiAgICogSWYgY2FsbGVkIG9uIGEgY2hhbm5lbCBvZiB0eXBlIHtAbGluayBDaGFubmVsVHlwZXN9Lkd1aWxkVGV4dCwgY3JlYXRlcyBhIHtAbGluayBDaGFubmVsVHlwZXN9Lkd1aWxkUHVibGljVGhyZWFkLlxuICAgKiBJZiBjYWxsZWQgb24gYSBjaGFubmVsIG9mIHR5cGUge0BsaW5rIENoYW5uZWxUeXBlc30uR3VpbGROZXdzLCBjcmVhdGVzIGEge0BsaW5rIENoYW5uZWxUeXBlc30uR3VpbGROZXdzVGhyZWFkLlxuICAgKiBEb2VzIG5vdCB3b3JrIG9uIGNoYW5uZWxzIG9mIHR5cGUge0BsaW5rIENoYW5uZWxUeXBlc30uR3VpbGRGb3J1bS5cbiAgICpcbiAgICogVGhlIElEIG9mIHRoZSBjcmVhdGVkIHRocmVhZCB3aWxsIGJlIHRoZSBzYW1lIGFzIHRoZSBJRCBvZiB0aGUgc291cmNlIG1lc3NhZ2UuXG4gICAqXG4gICAqIEZpcmVzIGEgX1RocmVhZCBDcmVhdGVfIGdhdGV3YXkgZXZlbnQuXG4gICAqXG4gICAqIEBzZWUge0BsaW5rIGh0dHBzOi8vZG9jcy5kaXNjb3JkLmNvbS9kZXZlbG9wZXJzL3Jlc291cmNlcy9jaGFubmVsI3N0YXJ0LXRocmVhZC1mcm9tLW1lc3NhZ2V9XG4gICAqL1xuICBhc3luYyBzdGFydFRocmVhZFdpdGhNZXNzYWdlKFxuICAgIHJlc3Q6IFJlc3RNYW5hZ2VyLFxuICAgIGNoYW5uZWxJZDogQmlnU3RyaW5nLFxuICAgIG1lc3NhZ2VJZDogQmlnU3RyaW5nLFxuICAgIG9wdGlvbnM6IFN0YXJ0VGhyZWFkV2l0aE1lc3NhZ2UsXG4gICAgcmVhc29uPzogc3RyaW5nLFxuICApOiBQcm9taXNlPERpc2NvcmRDaGFubmVsPiB7XG4gICAgcmV0dXJuIGF3YWl0IHJlc3QucG9zdDxEaXNjb3JkQ2hhbm5lbD4ocmVzdC5yb3V0ZXMuY2hhbm5lbHMudGhyZWFkcy5tZXNzYWdlKGNoYW5uZWxJZCwgbWVzc2FnZUlkKSwgeyBib2R5OiBvcHRpb25zLCByZWFzb24gfSk7XG4gIH0sXG4gIC8qKlxuICAgKiBDcmVhdGVzIGEgdGhyZWFkIHdpdGhvdXQgdXNpbmcgYSBtZXNzYWdlIGFzIHRoZSB0aHJlYWQncyBwb2ludCBvZiBvcmlnaW4uXG4gICAqXG4gICAqIEBwYXJhbSBjaGFubmVsSWQgLSBUaGUgSUQgb2YgdGhlIGNoYW5uZWwgaW4gd2hpY2ggdG8gY3JlYXRlIHRoZSB0aHJlYWQuXG4gICAqIEBwYXJhbSBvcHRpb25zIC0gVGhlIHBhcmFtZXRlcnMgdG8gdXNlIGZvciB0aGUgY3JlYXRpb24gb2YgdGhlIHRocmVhZC5cbiAgICogQHBhcmFtIHtzdHJpbmd9IFtyZWFzb25dIC0gQW4gb3B0aW9uYWwgcmVhc29uIGZvciB0aGUgYWN0aW9uLCB0byBiZSBpbmNsdWRlZCBpbiB0aGUgYXVkaXQgbG9nLlxuICAgKiBAcmV0dXJucyBBbiBpbnN0YW5jZSBvZiB0aGUgY3JlYXRlZCB7QGxpbmsgRGlzY29yZENoYW5uZWwgfCBUaHJlYWR9LlxuICAgKlxuICAgKiBAcmVtYXJrc1xuICAgKiBDcmVhdGluZyBhIHByaXZhdGUgdGhyZWFkIHJlcXVpcmVzIHRoZSBzZXJ2ZXIgdG8gYmUgYm9vc3RlZC5cbiAgICpcbiAgICogRmlyZXMgYSBfVGhyZWFkIENyZWF0ZV8gZ2F0ZXdheSBldmVudC5cbiAgICpcbiAgICogQHNlZSB7QGxpbmsgaHR0cHM6Ly9kb2NzLmRpc2NvcmQuY29tL2RldmVsb3BlcnMvcmVzb3VyY2VzL2NoYW5uZWwjc3RhcnQtdGhyZWFkLXdpdGhvdXQtbWVzc2FnZX1cbiAgICovXG4gIGFzeW5jIHN0YXJ0VGhyZWFkV2l0aG91dE1lc3NhZ2UoXG4gICAgcmVzdDogUmVzdE1hbmFnZXIsXG4gICAgY2hhbm5lbElkOiBCaWdTdHJpbmcsXG4gICAgb3B0aW9uczogU3RhcnRUaHJlYWRXaXRob3V0TWVzc2FnZSxcbiAgICByZWFzb24/OiBzdHJpbmcsXG4gICk6IFByb21pc2U8RGlzY29yZENoYW5uZWw+IHtcbiAgICByZXR1cm4gYXdhaXQgcmVzdC5wb3N0PERpc2NvcmRDaGFubmVsPihyZXN0LnJvdXRlcy5jaGFubmVscy50aHJlYWRzLmFsbChjaGFubmVsSWQpLCB7IGJvZHk6IG9wdGlvbnMsIHJlYXNvbiB9KTtcbiAgfSxcbiAgLyoqXG4gICAqIEdldCBhIGxpc3Qgb2YgdXNlcnMgdGhhdCB2b3RlZCBmb3IgdGhpcyBzcGVjaWZpYyBhbnN3ZXIuXG4gICAqXG4gICAqIEBwYXJhbSBjaGFubmVsSWQgLSBUaGUgSUQgb2YgdGhlIGNoYW5uZWwgaW4gd2hpY2ggdGhlIG1lc3NhZ2Ugd2l0aCB0aGUgcG9sbCBsaXZlc1xuICAgKiBAcGFyYW0gbWVzc2FnZUlkIC0gVGhlIElEIG9mIHRoZSBtZXNzYWdlIGluIHdoaWNoIHRoZSBwb2xsIGxpdmVzXG4gICAqIEBwYXJhbSBhbnN3ZXJJZCAtIFRoZSBJRCBvZiB0aGUgYW5zd2VyIHRvIGdldCB0aGUgdXNlcnMgdGhhdCB2b3RlZCB0aGF0IGFuc3dlclxuICAgKiBAcGFyYW0gb3B0aW9ucyAtIFRoZSBvcHRpb25zIGZvciB0aGUgcmVxdWVzdFxuICAgKiBAcmV0dXJucyBUaGUgbGlzdCBvZiB1c2VycyB0aGF0IHZvdGVkIGZvciB0aGUgc3BlY2lmaWMgYW5zd2VyLlxuICAgKi9cbiAgYXN5bmMgZ2V0UG9sbEFuc3dlclZvdGVycyhcbiAgICByZXN0OiBSZXN0TWFuYWdlcixcbiAgICBjaGFubmVsSWQ6IEJpZ1N0cmluZyxcbiAgICBtZXNzYWdlSWQ6IEJpZ1N0cmluZyxcbiAgICBhbnN3ZXJJZDogbnVtYmVyLFxuICAgIG9wdGlvbnM/OiBHZXRQb2xsQW5zd2VyVm90ZXMsXG4gICk6IFByb21pc2U8RGlzY29yZEdldEFuc3dlclZvdGVzUmVzcG9uc2U+IHtcbiAgICByZXR1cm4gYXdhaXQgcmVzdC5nZXQ8RGlzY29yZEdldEFuc3dlclZvdGVzUmVzcG9uc2U+KHJlc3Qucm91dGVzLmNoYW5uZWxzLnBvbGxzLnZvdGVzKGNoYW5uZWxJZCwgbWVzc2FnZUlkLCBhbnN3ZXJJZCwgb3B0aW9ucykpO1xuICB9LFxuICAvKipcbiAgICogSW1tZWRpYXRlbHkgZW5kcyB0aGUgcG9sbC5cbiAgICpcbiAgICogQHBhcmFtIGNoYW5uZWxJZCAtIFRoZSBJRCBvZiB0aGUgY2hhbm5lbCBpbiB3aGljaCB0aGUgbWVzc2FnZSB3aXRoIHRoZSBwb2xsIGxpdmVzXG4gICAqIEBwYXJhbSBtZXNzYWdlSWQgLSBUaGUgSUQgb2YgdGhlIG1lc3NhZ2UgaW4gd2hpY2ggdGhlIHBvbGwgbGl2ZXNcbiAgICogQHJldHVybnMgVGhlIG1lc3NhZ2Ugd2l0aCB0aGUgZXhwaXJlZCBwb2xsXG4gICAqXG4gICAqIEByZW1hcmtzXG4gICAqIFlvdSBjYW5ub3QgZW5kIHBvbGxzIGZyb20gb3RoZXIgdXNlcnMuXG4gICAqXG4gICAqIEZpcmVzIGEgX01lc3NhZ2UgVXBkYXRlXyBnYXRld2F5IGV2ZW50XG4gICAqL1xuICBhc3luYyBlbmRQb2xsKHJlc3Q6IFJlc3RNYW5hZ2VyLCBjaGFubmVsSWQ6IEJpZ1N0cmluZywgbWVzc2FnZUlkOiBCaWdTdHJpbmcpOiBQcm9taXNlPERpc2NvcmRNZXNzYWdlPiB7XG4gICAgcmV0dXJuIGF3YWl0IHJlc3QucG9zdDxEaXNjb3JkTWVzc2FnZT4ocmVzdC5yb3V0ZXMuY2hhbm5lbHMucG9sbHMuZXhwaXJlKGNoYW5uZWxJZCwgbWVzc2FnZUlkKSk7XG4gIH0sXG4gIC8qKlxuICAgKiBTeW5jaHJvbmlzZXMgYSB0ZW1wbGF0ZSB3aXRoIHRoZSBjdXJyZW50IHN0YXRlIG9mIGEgZ3VpbGQuXG4gICAqXG4gICAqIEBwYXJhbSBndWlsZElkIC0gVGhlIElEIG9mIHRoZSBndWlsZCB0byBzeW5jaHJvbmlzZSBhIHRlbXBsYXRlIG9mLlxuICAgKiBAcmV0dXJucyBBbiBpbnN0YW5jZSBvZiB0aGUgZWRpdGVkIHtAbGluayBEaXNjb3JkVGVtcGxhdGV9LlxuICAgKlxuICAgKiBAcmVtYXJrc1xuICAgKiBSZXF1aXJlcyB0aGUgYE1BTkFHRV9HVUlMRGAgcGVybWlzc2lvbi5cbiAgICpcbiAgICogRmlyZXMgYSBfR3VpbGQgVXBkYXRlXyBnYXRld2F5IGV2ZW50LlxuICAgKlxuICAgKiBAc2VlIHtAbGluayBodHRwczovL2RvY3MuZGlzY29yZC5jb20vZGV2ZWxvcGVycy9yZXNvdXJjZXMvZ3VpbGQtdGVtcGxhdGUjZ2V0LWd1aWxkLXRlbXBsYXRlc31cbiAgICovXG4gIGFzeW5jIHN5bmNHdWlsZFRlbXBsYXRlKHJlc3Q6IFJlc3RNYW5hZ2VyLCBndWlsZElkOiBCaWdTdHJpbmcpOiBQcm9taXNlPERpc2NvcmRUZW1wbGF0ZT4ge1xuICAgIHJldHVybiBhd2FpdCByZXN0LnB1dDxEaXNjb3JkVGVtcGxhdGU+KHJlc3Qucm91dGVzLmd1aWxkcy50ZW1wbGF0ZXMuYWxsKGd1aWxkSWQpKTtcbiAgfSxcbiAgLyoqXG4gICAqIFRyaWdnZXJzIGEgdHlwaW5nIGluZGljYXRvciBmb3IgdGhlIHNwZWNpZmllZCBjaGFubmVsLCB3aGljaCBleHBpcmVzIGFmdGVyIDEwIHNlY29uZHMuXG4gICAqXG4gICAqIEBwYXJhbSBjaGFubmVsSWQgLSBUaGUgSUQgb2YgdGhlIGNoYW5uZWwgaW4gd2hpY2ggdG8gdHJpZ2dlciB0aGUgdHlwaW5nIGluZGljYXRvci5cbiAgICpcbiAgICogQHJlbWFya3NcbiAgICogR2VuZXJhbGx5IGJvdHMgc2hvdWxkICoqbm90KiogdXNlIHRoaXMgcm91dGUuXG4gICAqIEhvd2V2ZXIsIGlmIGEgYm90IGlzIHJlc3BvbmRpbmcgdG8gYSBjb21tYW5kIGFuZCBleHBlY3RzIHRoZSBjb21wdXRhdGlvbiB0byB0YWtlIGEgZmV3IHNlY29uZHMsXG4gICAqIHRoaXMgZW5kcG9pbnQgbWF5IGJlIGNhbGxlZCB0byBsZXQgdGhlIHVzZXIga25vdyB0aGF0IHRoZSBib3QgaXMgcHJvY2Vzc2luZyB0aGVpciBtZXNzYWdlLlxuICAgKlxuICAgKiBGaXJlcyBhIF9UeXBpbmcgU3RhcnRfIGdhdGV3YXkgZXZlbnQuXG4gICAqXG4gICAqIEBzZWUge0BsaW5rIGh0dHBzOi8vZG9jcy5kaXNjb3JkLmNvbS9kZXZlbG9wZXJzL3Jlc291cmNlcy9jaGFubmVsI3RyaWdnZXItdHlwaW5nLWluZGljYXRvcn1cbiAgICovXG4gIGFzeW5jIHRyaWdnZXJUeXBpbmdJbmRpY2F0b3IocmVzdDogUmVzdE1hbmFnZXIsIGNoYW5uZWxJZDogQmlnU3RyaW5nKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgYXdhaXQgcmVzdC5wb3N0KHJlc3Qucm91dGVzLmNoYW5uZWxzLnR5cGluZyhjaGFubmVsSWQpKTtcbiAgfSxcbiAgLyoqXG4gICAqIFJlLXJlZ2lzdGVycyB0aGUgbGlzdCBvZiBnbG9iYWwgYXBwbGljYXRpb24gY29tbWFuZHMsIG92ZXJ3cml0aW5nIHRoZSBwcmV2aW91cyBjb21tYW5kcyBjb21wbGV0ZWx5LlxuICAgKlxuICAgKiBAcGFyYW0gY29tbWFuZHMgLSBUaGUgbGlzdCBvZiBjb21tYW5kcyB0byB1c2UgdG8gb3ZlcndyaXRlIHRoZSBwcmV2aW91cyBsaXN0LlxuICAgKiBAcGFyYW0gb3B0aW9ucyAtIEFkZGl0aW9uYWwgb3B0aW9ucyBmb3IgdGhlIGVuZHBvaW50LlxuICAgKiBAcmV0dXJucyBBIGNvbGxlY3Rpb24gb2Yge0BsaW5rIERpc2NvcmRBcHBsaWNhdGlvbkNvbW1hbmR9IG9iamVjdHMgYXNzb3J0ZWQgYnkgY29tbWFuZCBJRC5cbiAgICpcbiAgICogQHJlbWFya3NcbiAgICog4p2XIENvbW1hbmRzIHRoYXQgYXJlIG5vdCBwcmVzZW50IGluIHRoZSBgY29tbWFuZHNgIGFycmF5IHdpbGwgYmUgX19kZWxldGVkX18uXG4gICAqXG4gICAqIOKaoO+4jyBDb21tYW5kcyB0aGF0IGRvIG5vdCBhbHJlYWR5IGV4aXN0IHdpbGwgY291bnQgdG93YXJkcyB0aGUgZGFpbHkgbGltaXQgb2YgXzIwMF8gbmV3IGNvbW1hbmRzLlxuICAgKlxuICAgKiBXaGVuIHVzaW5nIHRoZSBiZWFyZXIgdG9rZW4gdGhlIHRva2VuIG5lZWRzIHRoZSBgYXBwbGljYXRpb25zLmNvbW1hbmRzLnVwZGF0ZWAgc2NvcGUgYW5kIG11c3QgYmUgYSBgQ2xpZW50IGdyYW50YCB0b2tlbi5cbiAgICogIFlvdSB3aWxsIGJlIGFibGUgdG8gdXBkYXRlIG9ubHkgeW91ciBvd24gYXBwbGljYXRpb24gY29tbWFuZHNcbiAgICpcbiAgICogQHNlZSB7QGxpbmsgaHR0cHM6Ly9kb2NzLmRpc2NvcmQuY29tL2RldmVsb3BlcnMvaW50ZXJhY3Rpb25zL2FwcGxpY2F0aW9uLWNvbW1hbmRzI2J1bGstb3ZlcndyaXRlLWdsb2JhbC1hcHBsaWNhdGlvbi1jb21tYW5kc31cbiAgICovXG4gIGFzeW5jIHVwc2VydEdsb2JhbEFwcGxpY2F0aW9uQ29tbWFuZHMoXG4gICAgcmVzdDogUmVzdE1hbmFnZXIsXG4gICAgY29tbWFuZHM6IENyZWF0ZUFwcGxpY2F0aW9uQ29tbWFuZFtdLFxuICAgIG9wdGlvbnM/OiBVcHNlcnRHbG9iYWxBcHBsaWNhdGlvbkNvbW1hbmRPcHRpb25zLFxuICApOiBQcm9taXNlPERpc2NvcmRBcHBsaWNhdGlvbkNvbW1hbmRbXT4ge1xuICAgIGNvbnN0IHJlc3RPcHRpb25zOiBNYWtlUmVxdWVzdE9wdGlvbnMgPSB7IGJvZHk6IGNvbW1hbmRzIH07XG5cbiAgICBpZiAob3B0aW9ucz8uYmVhcmVyVG9rZW4pIHtcbiAgICAgIHJlc3RPcHRpb25zLnVuYXV0aG9yaXplZCA9IHRydWU7XG4gICAgICByZXN0T3B0aW9ucy5oZWFkZXJzID0ge1xuICAgICAgICBhdXRob3JpemF0aW9uOiBgQmVhcmVyICR7b3B0aW9ucy5iZWFyZXJUb2tlbn1gLFxuICAgICAgfTtcbiAgICB9XG5cbiAgICByZXR1cm4gYXdhaXQgcmVzdC5wdXQ8RGlzY29yZEFwcGxpY2F0aW9uQ29tbWFuZFtdPihyZXN0LnJvdXRlcy5pbnRlcmFjdGlvbnMuY29tbWFuZHMuY29tbWFuZHMocmVzdC5hcHBsaWNhdGlvbklkKSwgcmVzdE9wdGlvbnMpO1xuICB9LFxuICAvKipcbiAgICogUmUtcmVnaXN0ZXJzIHRoZSBsaXN0IG9mIGFwcGxpY2F0aW9uIGNvbW1hbmRzIHJlZ2lzdGVyZWQgaW4gYSBndWlsZCwgb3ZlcndyaXRpbmcgdGhlIHByZXZpb3VzIGNvbW1hbmRzIGNvbXBsZXRlbHkuXG4gICAqXG4gICAqIEBwYXJhbSBndWlsZElkIC0gVGhlIElEIG9mIHRoZSBndWlsZCB3aG9zZSBsaXN0IG9mIGNvbW1hbmRzIHRvIG92ZXJ3cml0ZS5cbiAgICogQHBhcmFtIGNvbW1hbmRzIC0gVGhlIGxpc3Qgb2YgY29tbWFuZHMgdG8gdXNlIHRvIG92ZXJ3cml0ZSB0aGUgcHJldmlvdXMgbGlzdC5cbiAgICogQHBhcmFtIG9wdGlvbnMgLSBBZGRpdGlvbmFsIG9wdGlvbnMgZm9yIHRoZSBlbmRwb2ludC5cbiAgICogQHJldHVybnMgQSBjb2xsZWN0aW9uIG9mIHtAbGluayBEaXNjb3JkQXBwbGljYXRpb25Db21tYW5kfSBvYmplY3RzIGFzc29ydGVkIGJ5IGNvbW1hbmQgSUQuXG4gICAqXG4gICAqIEByZW1hcmtzXG4gICAqIOKdlyBDb21tYW5kcyB0aGF0IGFyZSBub3QgcHJlc2VudCBpbiB0aGUgYGNvbW1hbmRzYCBhcnJheSB3aWxsIGJlIF9fZGVsZXRlZF9fLlxuICAgKlxuICAgKiDimqDvuI8gQ29tbWFuZHMgdGhhdCBkbyBub3QgYWxyZWFkeSBleGlzdCB3aWxsIGNvdW50IHRvd2FyZHMgdGhlIGRhaWx5IGxpbWl0IG9mIF8yMDBfIG5ldyBjb21tYW5kcy5cbiAgICpcbiAgICogV2hlbiB1c2luZyB0aGUgYmVhcmVyIHRva2VuIHRoZSB0b2tlbiBuZWVkcyB0aGUgYGFwcGxpY2F0aW9ucy5jb21tYW5kcy51cGRhdGVgIHNjb3BlIGFuZCBtdXN0IGJlIGEgYENsaWVudCBncmFudGAgdG9rZW4uXG4gICAqICBZb3Ugd2lsbCBiZSBhYmxlIHRvIHVwZGF0ZSBvbmx5IHlvdXIgb3duIGFwcGxpY2F0aW9uIGNvbW1hbmRzXG4gICAqXG4gICAqIEBzZWUge0BsaW5rIGh0dHBzOi8vZG9jcy5kaXNjb3JkLmNvbS9kZXZlbG9wZXJzL2ludGVyYWN0aW9ucy9hcHBsaWNhdGlvbi1jb21tYW5kcyNidWxrLW92ZXJ3cml0ZS1ndWlsZC1hcHBsaWNhdGlvbi1jb21tYW5kc31cbiAgICovXG4gIGFzeW5jIHVwc2VydEd1aWxkQXBwbGljYXRpb25Db21tYW5kcyhcbiAgICByZXN0OiBSZXN0TWFuYWdlcixcbiAgICBndWlsZElkOiBCaWdTdHJpbmcsXG4gICAgY29tbWFuZHM6IENyZWF0ZUFwcGxpY2F0aW9uQ29tbWFuZFtdLFxuICAgIG9wdGlvbnM/OiBVcHNlcnRHdWlsZEFwcGxpY2F0aW9uQ29tbWFuZE9wdGlvbnMsXG4gICk6IFByb21pc2U8RGlzY29yZEFwcGxpY2F0aW9uQ29tbWFuZFtdPiB7XG4gICAgY29uc3QgcmVzdE9wdGlvbnM6IE1ha2VSZXF1ZXN0T3B0aW9ucyA9IHsgYm9keTogY29tbWFuZHMgfTtcblxuICAgIGlmIChvcHRpb25zPy5iZWFyZXJUb2tlbikge1xuICAgICAgcmVzdE9wdGlvbnMudW5hdXRob3JpemVkID0gdHJ1ZTtcbiAgICAgIHJlc3RPcHRpb25zLmhlYWRlcnMgPSB7XG4gICAgICAgIGF1dGhvcml6YXRpb246IGBCZWFyZXIgJHtvcHRpb25zLmJlYXJlclRva2VufWAsXG4gICAgICB9O1xuICAgIH1cblxuICAgIHJldHVybiBhd2FpdCByZXN0LnB1dDxEaXNjb3JkQXBwbGljYXRpb25Db21tYW5kW10+KHJlc3Qucm91dGVzLmludGVyYWN0aW9ucy5jb21tYW5kcy5ndWlsZHMuYWxsKHJlc3QuYXBwbGljYXRpb25JZCwgZ3VpbGRJZCksIHJlc3RPcHRpb25zKTtcbiAgfSxcbiAgLyoqXG4gICAqIEJhbnMgYSB1c2VyIGZyb20gYSBndWlsZC5cbiAgICpcbiAgICogQHBhcmFtIGd1aWxkSWQgLSBUaGUgSUQgb2YgdGhlIGd1aWxkIHRvIGJhbiB0aGUgdXNlciBmcm9tLlxuICAgKiBAcGFyYW0gdXNlcklkIC0gVGhlIElEIG9mIHRoZSB1c2VyIHRvIGJhbiBmcm9tIHRoZSBndWlsZC5cbiAgICogQHBhcmFtIG9wdGlvbnMgLSBUaGUgcGFyYW1ldGVycyBmb3IgdGhlIGNyZWF0aW9uIG9mIHRoZSBiYW4uXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBbcmVhc29uXSAtIEFuIG9wdGlvbmFsIHJlYXNvbiBmb3IgdGhlIGFjdGlvbiwgdG8gYmUgaW5jbHVkZWQgaW4gdGhlIGF1ZGl0IGxvZy5cbiAgICpcbiAgICogQHJlbWFya3NcbiAgICogUmVxdWlyZXMgdGhlIGBCQU5fTUVNQkVSU2AgcGVybWlzc2lvbi5cbiAgICpcbiAgICogRmlyZXMgYSBfR3VpbGQgQmFuIEFkZF8gZ2F0ZXdheSBldmVudC5cbiAgICpcbiAgICogQHNlZSB7QGxpbmsgaHR0cHM6Ly9kb2NzLmRpc2NvcmQuY29tL2RldmVsb3BlcnMvcmVzb3VyY2VzL2d1aWxkI2NyZWF0ZS1ndWlsZC1iYW59XG4gICAqL1xuICBhc3luYyBiYW5NZW1iZXIocmVzdDogUmVzdE1hbmFnZXIsIGd1aWxkSWQ6IEJpZ1N0cmluZywgdXNlcklkOiBCaWdTdHJpbmcsIG9wdGlvbnM/OiBDcmVhdGVHdWlsZEJhbiwgcmVhc29uPzogc3RyaW5nKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgYXdhaXQgcmVzdC5wdXQ8dm9pZD4ocmVzdC5yb3V0ZXMuZ3VpbGRzLm1lbWJlcnMuYmFuKGd1aWxkSWQsIHVzZXJJZCksIHsgYm9keTogb3B0aW9ucywgcmVhc29uIH0pO1xuICB9LFxuICAvKipcbiAgICogQmFucyB1cCB0byAyMDAgdXNlcnMgZnJvbSBhIGd1aWxkLlxuICAgKlxuICAgKiBAcGFyYW0gZ3VpbGRJZCAtIFRoZSBJRCBvZiB0aGUgZ3VpbGQgdG8gYmFuIHRoZSB1c2VycyBmcm9tLlxuICAgKiBAcGFyYW0gb3B0aW9ucyAtIFRoZSB1c2VycyB0byBiYW4gYW5kIHRoZSBvdGhlciBvcHRpb25zIGZvciB0aGUgYmFuLlxuICAgKiBAcGFyYW0ge3N0cmluZ30gW3JlYXNvbl0gLSBBbiBvcHRpb25hbCByZWFzb24gZm9yIHRoZSBhY3Rpb24sIHRvIGJlIGluY2x1ZGVkIGluIHRoZSBhdWRpdCBsb2cuXG4gICAqXG4gICAqIEByZW1hcmtzXG4gICAqIFJlcXVpcmVzIHRoZSBgQkFOX01FTUJFUlNgIGFuZCBgTUFOQUdFX0dVSUxEYCBwZXJtaXNzaW9ucy5cbiAgICpcbiAgICogSWYgYWxsIHByb3ZpZGVkIHVzZXJzIGZhaWwgdG8gYmUgYmFubmVkLCBkaXNjb3JkIHdpbGwgcmVzcG9uZCB3aXRoIGFuIGVycm9yIChjb2RlOiBgNTAwMDAwOiBGYWlsZWQgdG8gYmFuIHVzZXJzYClcbiAgICpcbiAgICogRmlyZXMgYXMgbWFueSBfR3VpbGQgQmFuIEFkZF8gZ2F0ZXdheSBldmVudHMgYXMgbWFueSB1c2VyIHdoZXJlIGJhbm5lZC5cbiAgICpcbiAgICogQHNlZSB7QGxpbmsgaHR0cHM6Ly9kb2NzLmRpc2NvcmQuY29tL2RldmVsb3BlcnMvcmVzb3VyY2VzL2d1aWxkI2J1bGstZ3VpbGQtYmFufVxuICAgKi9cbiAgYXN5bmMgYnVsa0Jhbk1lbWJlcnMocmVzdDogUmVzdE1hbmFnZXIsIGd1aWxkSWQ6IEJpZ1N0cmluZywgb3B0aW9uczogQ3JlYXRlR3VpbGRCdWxrQmFuLCByZWFzb24/OiBzdHJpbmcpOiBQcm9taXNlPERpc2NvcmRCdWxrQmFuPiB7XG4gICAgcmV0dXJuIGF3YWl0IHJlc3QucG9zdDxEaXNjb3JkQnVsa0Jhbj4ocmVzdC5yb3V0ZXMuZ3VpbGRzLm1lbWJlcnMuYnVsa0JhbihndWlsZElkKSwgeyBib2R5OiBvcHRpb25zLCByZWFzb24gfSk7XG4gIH0sXG4gIC8qKlxuICAgKiBFZGl0cyB0aGUgbmlja25hbWUgb2YgdGhlIGJvdCB1c2VyLlxuICAgKlxuICAgKiBAcGFyYW0gZ3VpbGRJZCAtIFRoZSBJRCBvZiB0aGUgZ3VpbGQgdG8gZWRpdCB0aGUgbmlja25hbWUgb2YgdGhlIGJvdCB1c2VyIGluLlxuICAgKiBAcGFyYW0gb3B0aW9ucyAtIFRoZSBwYXJhbWV0ZXJzIGZvciB0aGUgZWRpdCBvZiB0aGUgbmlja25hbWUuXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBbcmVhc29uXSAtIEFuIG9wdGlvbmFsIHJlYXNvbiBmb3IgdGhlIGFjdGlvbiwgdG8gYmUgaW5jbHVkZWQgaW4gdGhlIGF1ZGl0IGxvZy5cbiAgICogQHJldHVybnMgQW4gaW5zdGFuY2Ugb2YgdGhlIGVkaXRlZCB7QGxpbmsgRGlzY29yZE1lbWJlcn1cbiAgICpcbiAgICogQHJlbWFya3NcbiAgICogRmlyZXMgYSBfR3VpbGQgTWVtYmVyIFVwZGF0ZV8gZ2F0ZXdheSBldmVudC5cbiAgICpcbiAgICogQHNlZSB7QGxpbmsgaHR0cHM6Ly9kb2NzLmRpc2NvcmQuY29tL2RldmVsb3BlcnMvcmVzb3VyY2VzL2d1aWxkI21vZGlmeS1jdXJyZW50LW1lbWJlcn1cbiAgICovXG4gIGFzeW5jIGVkaXRDdXJyZW50TWVtYmVyKHJlc3Q6IFJlc3RNYW5hZ2VyLCBndWlsZElkOiBCaWdTdHJpbmcsIG9wdGlvbnM6IE1vZGlmeUN1cnJlbnRNZW1iZXIsIHJlYXNvbj86IHN0cmluZyk6IFByb21pc2U8RGlzY29yZE1lbWJlcj4ge1xuICAgIHJldHVybiBhd2FpdCByZXN0LnBhdGNoPERpc2NvcmRNZW1iZXI+KHJlc3Qucm91dGVzLmd1aWxkcy5tZW1iZXJzLmJvdChndWlsZElkKSwgeyBib2R5OiBvcHRpb25zLCByZWFzb24gfSk7XG4gIH0sXG4gIC8qKlxuICAgKiBFZGl0cyBhIG1lbWJlcidzIHByb3BlcnRpZXMuXG4gICAqXG4gICAqIEBwYXJhbSBndWlsZElkIC0gVGhlIElEIG9mIHRoZSBndWlsZCB0byBlZGl0IHRoZSBtZW1iZXIgb2YuXG4gICAqIEBwYXJhbSB1c2VySWQgLSBUaGUgdXNlciBJRCBvZiB0aGUgbWVtYmVyIHRvIGVkaXQuXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBbcmVhc29uXSAtIEFuIG9wdGlvbmFsIHJlYXNvbiBmb3IgdGhlIGFjdGlvbiwgdG8gYmUgaW5jbHVkZWQgaW4gdGhlIGF1ZGl0IGxvZy5cbiAgICogQHBhcmFtIG9wdGlvbnMgLSBUaGUgcGFyYW1ldGVycyBmb3IgdGhlIGVkaXQgb2YgdGhlIHVzZXIuXG4gICAqXG4gICAqIEByZW1hcmtzXG4gICAqIFRoaXMgZW5kcG9pbnQgcmVxdWlyZXMgdmFyaW91cyBwZXJtaXNzaW9ucyBkZXBlbmRpbmcgb24gd2hhdCBpcyBlZGl0ZWQgYWJvdXQgdGhlIG1lbWJlci5cbiAgICogVG8gZmluZCBvdXQgdGhlIHJlcXVpcmVkIHBlcm1pc3Npb24gdG8gZW5hY3QgYSBjaGFuZ2UsIHJlYWQgdGhlIGRvY3VtZW50YXRpb24gb2YgdGhpcyBlbmRwb2ludCdzIHtAbGluayBNb2RpZnlHdWlsZE1lbWJlciB8IHBhcmFtZXRlcnN9LlxuICAgKlxuICAgKiBGaXJlcyBhIF9HdWlsZCBNZW1iZXIgVXBkYXRlXyBnYXRld2F5IGV2ZW50LlxuICAgKlxuICAgKiBAc2VlIHtAbGluayBodHRwczovL2RvY3MuZGlzY29yZC5jb20vZGV2ZWxvcGVycy9yZXNvdXJjZXMvZ3VpbGQjbW9kaWZ5LWd1aWxkLW1lbWJlcn1cbiAgICovXG4gIGFzeW5jIGVkaXRNZW1iZXIocmVzdDogUmVzdE1hbmFnZXIsIGd1aWxkSWQ6IEJpZ1N0cmluZywgdXNlcklkOiBCaWdTdHJpbmcsIG9wdGlvbnM6IE1vZGlmeUd1aWxkTWVtYmVyLCByZWFzb24/OiBzdHJpbmcpOiBQcm9taXNlPERpc2NvcmRNZW1iZXI+IHtcbiAgICByZXR1cm4gYXdhaXQgcmVzdC5wYXRjaDxEaXNjb3JkTWVtYmVyV2l0aFVzZXI+KHJlc3Qucm91dGVzLmd1aWxkcy5tZW1iZXJzLm1lbWJlcihndWlsZElkLCB1c2VySWQpLCB7IGJvZHk6IG9wdGlvbnMsIHJlYXNvbiB9KTtcbiAgfSxcbiAgLyoqXG4gICAqIEdldHMgdGhlIGN1cnJlbnQgbWVtYmVyIG9iamVjdC5cbiAgICpcbiAgICogQHBhcmFtIGJlYXJlclRva2VuIC0gVGhlIGFjY2VzcyB0b2tlbiBvZiB0aGUgdXNlclxuICAgKiBAcGFyYW0gZ3VpbGRJZCAtIFRoZSBJRCBvZiB0aGUgZ3VpbGQgdG8gZ2V0IHRoZSBtZW1iZXIgb2JqZWN0IGZvci5cbiAgICogQHJldHVybnMgQW4gaW5zdGFuY2Ugb2Yge0BsaW5rIERpc2NvcmRNZW1iZXJXaXRoVXNlcn0uXG4gICAqXG4gICAqIEByZW1hcmtzXG4gICAqIFRoZSBhY2Nlc3MgdG9rZW5zIG5lZWRzIHRoZSBgZ3VpbGRzLm1lbWJlcnMucmVhZGAgc2NvcGVcbiAgICpcbiAgICogQHNlZSB7QGxpbmsgaHR0cHM6Ly9kb2NzLmRpc2NvcmQuY29tL2RldmVsb3BlcnMvcmVzb3VyY2VzL3VzZXIjZ2V0LWN1cnJlbnQtdXNlci1ndWlsZC1tZW1iZXJ9XG4gICAqL1xuICBhc3luYyBnZXRDdXJyZW50TWVtYmVyKHJlc3Q6IFJlc3RNYW5hZ2VyLCBndWlsZElkOiBCaWdTdHJpbmcsIGJlYXJlclRva2VuOiBzdHJpbmcpOiBQcm9taXNlPERpc2NvcmRNZW1iZXJXaXRoVXNlcj4ge1xuICAgIHJldHVybiBhd2FpdCByZXN0LmdldDxEaXNjb3JkTWVtYmVyV2l0aFVzZXI+KHJlc3Qucm91dGVzLmd1aWxkcy5tZW1iZXJzLmN1cnJlbnRNZW1iZXIoZ3VpbGRJZCksIHtcbiAgICAgIGhlYWRlcnM6IHtcbiAgICAgICAgYXV0aG9yaXphdGlvbjogYEJlYXJlciAke2JlYXJlclRva2VufWAsXG4gICAgICB9LFxuICAgICAgdW5hdXRob3JpemVkOiB0cnVlLFxuICAgIH0pO1xuICB9LFxuICAvKipcbiAgICogR2V0cyB0aGUgbWVtYmVyIG9iamVjdCBieSB1c2VyIElELlxuICAgKlxuICBcbiAgICogQHBhcmFtIGd1aWxkSWQgLSBUaGUgSUQgb2YgdGhlIGd1aWxkIHRvIGdldCB0aGUgbWVtYmVyIG9iamVjdCBmb3IuXG4gICAqIEBwYXJhbSB1c2VySWQgLSBUaGUgSUQgb2YgdGhlIHVzZXIgdG8gZ2V0IHRoZSBtZW1iZXIgb2JqZWN0IGZvci5cbiAgICogQHJldHVybnMgQW4gaW5zdGFuY2Ugb2Yge0BsaW5rIERpc2NvcmRNZW1iZXJXaXRoVXNlcn0uXG4gICAqXG4gICAqIEBzZWUge0BsaW5rIGh0dHBzOi8vZG9jcy5kaXNjb3JkLmNvbS9kZXZlbG9wZXJzL3Jlc291cmNlcy9ndWlsZCNnZXQtZ3VpbGQtbWVtYmVyfVxuICAgKi9cbiAgYXN5bmMgZ2V0TWVtYmVyKHJlc3Q6IFJlc3RNYW5hZ2VyLCBndWlsZElkOiBCaWdTdHJpbmcsIHVzZXJJZDogQmlnU3RyaW5nKTogUHJvbWlzZTxEaXNjb3JkTWVtYmVyV2l0aFVzZXI+IHtcbiAgICByZXR1cm4gYXdhaXQgcmVzdC5nZXQ8RGlzY29yZE1lbWJlcldpdGhVc2VyPihyZXN0LnJvdXRlcy5ndWlsZHMubWVtYmVycy5tZW1iZXIoZ3VpbGRJZCwgdXNlcklkKSk7XG4gIH0sXG4gIC8qKlxuICAgKiBHZXRzIHRoZSBsaXN0IG9mIG1lbWJlcnMgZm9yIGEgZ3VpbGQuXG4gICAqXG4gICAqIEBwYXJhbSBndWlsZElkIC0gVGhlIElEIG9mIHRoZSBndWlsZCB0byBnZXQgdGhlIGxpc3Qgb2YgbWVtYmVycyBmb3IuXG4gICAqIEBwYXJhbSBvcHRpb25zIC0gVGhlIHBhcmFtZXRlcnMgZm9yIHRoZSBmZXRjaGluZyBvZiB0aGUgbWVtYmVycy5cbiAgICogQHJldHVybnMgQSBjb2xsZWN0aW9uIG9mIHtAbGluayBEaXNjb3JkTWVtYmVyV2l0aFVzZXJ9IG9iamVjdHMgYXNzb3J0ZWQgYnkgdXNlciBJRC5cbiAgICpcbiAgICogQHJlbWFya3NcbiAgICogUmVxdWlyZXMgdGhlIGBHVUlMRF9NRU1CRVJTYCBpbnRlbnQuXG4gICAqXG4gICAqIOKaoO+4jyBJdCBpcyBub3QgcmVjb21tZW5kZWQgdG8gdXNlIHRoaXMgZW5kcG9pbnQgd2l0aCB2ZXJ5IGxhcmdlIGJvdHMuIEluc3RlYWQsIG9wdCB0byB1c2UgYGZldGNoTWVtYmVycygpYDpcbiAgICogUkVTVCBjb21tdW5pY2F0aW9uIG9ubHkgcGVybWl0cyA1MCByZXF1ZXN0cyB0byBiZSBtYWRlIHBlciBzZWNvbmQsIHdoaWxlIGdhdGV3YXlzIGFsbG93IGZvciB1cCB0byAxMjAgcmVxdWVzdHNcbiAgICogcGVyIG1pbnV0ZSBwZXIgc2hhcmQuIEZvciBtb3JlIGluZm9ybWF0aW9uLCByZWFkIHtAbGluayBodHRwczovL2RvY3MuZGlzY29yZC5jb20vZGV2ZWxvcGVycy90b3BpY3MvcmF0ZS1saW1pdHMjcmF0ZS1saW1pdHN9LlxuICAgKlxuICAgKiBAc2VlIHtAbGluayBodHRwczovL2RvY3MuZGlzY29yZC5jb20vZGV2ZWxvcGVycy9yZXNvdXJjZXMvZ3VpbGQjbGlzdC1ndWlsZC1tZW1iZXJzfVxuICAgKiBAc2VlIHtAbGluayBodHRwczovL2RvY3MuZGlzY29yZC5jb20vZGV2ZWxvcGVycy9ldmVudHMvZ2F0ZXdheS1ldmVudHMjcmVxdWVzdC1ndWlsZC1tZW1iZXJzfVxuICAgKiBAc2VlIHtAbGluayBodHRwczovL2RvY3MuZGlzY29yZC5jb20vZGV2ZWxvcGVycy90b3BpY3MvcmF0ZS1saW1pdHMjcmF0ZS1saW1pdHN9XG4gICAqL1xuICBhc3luYyBnZXRNZW1iZXJzKHJlc3Q6IFJlc3RNYW5hZ2VyLCBndWlsZElkOiBCaWdTdHJpbmcsIG9wdGlvbnM6IExpc3RHdWlsZE1lbWJlcnMpOiBQcm9taXNlPERpc2NvcmRNZW1iZXJXaXRoVXNlcltdPiB7XG4gICAgcmV0dXJuIGF3YWl0IHJlc3QuZ2V0PERpc2NvcmRNZW1iZXJXaXRoVXNlcltdPihyZXN0LnJvdXRlcy5ndWlsZHMubWVtYmVycy5tZW1iZXJzKGd1aWxkSWQsIG9wdGlvbnMpKTtcbiAgfSxcbiAgLyoqXG4gICAqIFJldHVybnMgYSBzZXJpYWxpemVkIGFjdGl2aXR5IGluc3RhbmNlLCBpZiBpdCBleGlzdHMuIFVzZWZ1bCBmb3IgcHJldmVudGluZyB1bndhbnRlZCBhY3Rpdml0eSBzZXNzaW9ucy5cbiAgICpcbiAgICogQHBhcmFtIGFwcGxpY2F0aW9uSWQgLSBUaGUgSUQgb2YgdGhlIGFwcGxpY2F0aW9uXG4gICAqIEBwYXJhbSBpbnN0YW5jZUlkIC0gVGhlIElEIG9mIHRoZSBhY3Rpdml0eSBpbnN0YW5jZVxuICAgKi9cbiAgYXN5bmMgZ2V0QXBwbGljYXRpb25BY3Rpdml0eUluc3RhbmNlKHJlc3Q6IFJlc3RNYW5hZ2VyLCBhcHBsaWNhdGlvbklkOiBCaWdTdHJpbmcsIGluc3RhbmNlSWQ6IHN0cmluZyk6IFByb21pc2U8RGlzY29yZEFjdGl2aXR5SW5zdGFuY2U+IHtcbiAgICByZXR1cm4gYXdhaXQgcmVzdC5nZXQ8RGlzY29yZEFjdGl2aXR5SW5zdGFuY2U+KHJlc3Qucm91dGVzLmFwcGxpY2F0aW9uQWN0aXZpdHlJbnN0YW5jZShhcHBsaWNhdGlvbklkLCBpbnN0YW5jZUlkKSk7XG4gIH0sXG4gIC8qKlxuICAgKiBLaWNrcyBhIG1lbWJlciBmcm9tIGEgZ3VpbGQuXG4gICAqXG4gIFxuICAgKiBAcGFyYW0gZ3VpbGRJZCAtIFRoZSBJRCBvZiB0aGUgZ3VpbGQgdG8ga2ljayB0aGUgbWVtYmVyIGZyb20uXG4gICAqIEBwYXJhbSB1c2VySWQgLSBUaGUgdXNlciBJRCBvZiB0aGUgbWVtYmVyIHRvIGtpY2sgZnJvbSB0aGUgZ3VpbGQuXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBbcmVhc29uXSAtIEFuIG9wdGlvbmFsIHJlYXNvbiBmb3IgdGhlIGFjdGlvbiwgdG8gYmUgaW5jbHVkZWQgaW4gdGhlIGF1ZGl0IGxvZy5cbiAgICpcbiAgICogQHJlbWFya3NcbiAgICogUmVxdWlyZXMgdGhlIGBLSUNLX01FTUJFUlNgIHBlcm1pc3Npb24uXG4gICAqXG4gICAqIEZpcmVzIGEgX0d1aWxkIE1lbWJlciBSZW1vdmVfIGdhdGV3YXkgZXZlbnQuXG4gICAqXG4gICAqIEBzZWUge0BsaW5rIGh0dHBzOi8vZG9jcy5kaXNjb3JkLmNvbS9kZXZlbG9wZXJzL3Jlc291cmNlcy9ndWlsZCNyZW1vdmUtZ3VpbGQtbWVtYmVyfVxuICAgKi9cbiAgYXN5bmMga2lja01lbWJlcihyZXN0OiBSZXN0TWFuYWdlciwgZ3VpbGRJZDogQmlnU3RyaW5nLCB1c2VySWQ6IEJpZ1N0cmluZywgcmVhc29uPzogc3RyaW5nKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgYXdhaXQgcmVzdC5kZWxldGUocmVzdC5yb3V0ZXMuZ3VpbGRzLm1lbWJlcnMubWVtYmVyKGd1aWxkSWQsIHVzZXJJZCksIHtcbiAgICAgIHJlYXNvbixcbiAgICB9KTtcbiAgfSxcbiAgLyoqXG4gICAqIFBpbnMgYSBtZXNzYWdlIGluIGEgY2hhbm5lbC5cbiAgICpcbiAgICogQHBhcmFtIGNoYW5uZWxJZCAtIFRoZSBJRCBvZiB0aGUgY2hhbm5lbCB3aGVyZSB0aGUgbWVzc2FnZSBpcyB0byBiZSBwaW5uZWQuXG4gICAqIEBwYXJhbSBtZXNzYWdlSWQgLSBUaGUgSUQgb2YgdGhlIG1lc3NhZ2UgdG8gcGluLlxuICAgKiBAcGFyYW0ge3N0cmluZ30gW3JlYXNvbl0gLSBBbiBvcHRpb25hbCByZWFzb24gZm9yIHRoZSBhY3Rpb24sIHRvIGJlIGluY2x1ZGVkIGluIHRoZSBhdWRpdCBsb2cuXG4gICAqXG4gICAqIEByZW1hcmtzXG4gICAqIFJlcXVpcmVzIHRoZSBgUElOX01FU1NBR0VTYCBwZXJtaXNzaW9uLlxuICAgKlxuICAgKiBGaXJlcyBhIF9DaGFubmVsIFBpbnMgVXBkYXRlXyBldmVudC5cbiAgICpcbiAgICogQHNlZSB7QGxpbmsgaHR0cHM6Ly9kb2NzLmRpc2NvcmQuY29tL2RldmVsb3BlcnMvcmVzb3VyY2VzL21lc3NhZ2UjcGluLW1lc3NhZ2V9XG4gICAqL1xuICBhc3luYyBwaW5NZXNzYWdlKHJlc3Q6IFJlc3RNYW5hZ2VyLCBjaGFubmVsSWQ6IEJpZ1N0cmluZywgbWVzc2FnZUlkOiBCaWdTdHJpbmcsIHJlYXNvbj86IHN0cmluZyk6IFByb21pc2U8dm9pZD4ge1xuICAgIGF3YWl0IHJlc3QucHV0KHJlc3Qucm91dGVzLmNoYW5uZWxzLm1lc3NhZ2VQaW4oY2hhbm5lbElkLCBtZXNzYWdlSWQpLCB7IHJlYXNvbiB9KTtcbiAgfSxcbiAgLyoqXG4gICAqIEluaXRpYXRlcyB0aGUgcHJvY2VzcyBvZiBwcnVuaW5nIGluYWN0aXZlIG1lbWJlcnMuXG4gICAqXG4gIFxuICAgKiBAcGFyYW0gZ3VpbGRJZCAtIFRoZSBJRCBvZiB0aGUgZ3VpbGQgdG8gcHJ1bmUgdGhlIG1lbWJlcnMgb2YuXG4gICAqIEBwYXJhbSBvcHRpb25zIC0gVGhlIHBhcmFtZXRlcnMgZm9yIHRoZSBwcnVuaW5nIG9mIG1lbWJlcnMuXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBbcmVhc29uXSAtIEFuIG9wdGlvbmFsIHJlYXNvbiBmb3IgdGhlIGFjdGlvbiwgdG8gYmUgaW5jbHVkZWQgaW4gdGhlIGF1ZGl0IGxvZy5cbiAgICogQHJldHVybnMgQSBudW1iZXIgaW5kaWNhdGluZyBob3cgbWFueSBtZW1iZXJzIHdlcmUgcHJ1bmVkLlxuICAgKlxuICAgKiBAcmVtYXJrc1xuICAgKiBSZXF1aXJlcyB0aGUgYE1BTkFHRV9HVUlMRGAgYW5kIGBLSUNLX01FTUJFUlNgIHBlcm1pc3Npb25zLCB1bmxlc3MgdGhlIGd1aWxkIGhhcyB0aGUgYFBSVU5FX1JFUVVJUkVTX0FETUlOYCBndWlsZCBmZWF0dXJlLCBpbiB3aGljaCBjYXNlIGl0IHJlcXVpcmVzIHRoZSBgQURNSU5JU1RSQVRPUmAgcGVybWlzc2lvbi5cbiAgICpcbiAgICog4p2XIFJlcXVlc3RzIHRvIHRoaXMgZW5kcG9pbnQgd2lsbCB0aW1lIG91dCBmb3IgbGFyZ2UgZ3VpbGRzLiBUbyBwcmV2ZW50IHRoaXMgZnJvbSBoYXBwZW5pbmcsIHNldCB0aGUge0BsaW5rIEJlZ2luR3VpbGRQcnVuZS5jb21wdXRlUHJ1bmVDb3VudH0gcHJvcGVydHkgb2YgdGhlIG9wdGlvbnMgb2JqZWN0IHBhcmFtZXRlciB0byBgZmFsc2VgLiBUaGlzIHdpbGwgYmVnaW4gdGhlIHByb2Nlc3Mgb2YgcHJ1bmluZywgYW5kIGltbWVkaWF0ZWx5IHJldHVybiBgdW5kZWZpbmVkYCwgcmF0aGVyIHRoYW4gd2FpdCBmb3IgdGhlIHByb2Nlc3MgdG8gY29tcGxldGUgYmVmb3JlIHJldHVybmluZyB0aGUgYWN0dWFsIGNvdW50IG9mIG1lbWJlcnMgdGhhdCBoYXZlIGJlZW4ga2lja2VkLlxuICAgKlxuICAgKiDimqDvuI8gQnkgZGVmYXVsdCwgdGhpcyBwcm9jZXNzIHdpbGwgbm90IHJlbW92ZSBtZW1iZXJzIHdpdGggYSByb2xlLiBUbyBpbmNsdWRlIHRoZSBtZW1iZXJzIHdobyBoYXZlIGEgX3BhcnRpY3VsYXIgc3Vic2V0IG9mIHJvbGVzXywgc3BlY2lmeSB0aGUgcm9sZShzKSBpbiB0aGUge0BsaW5rIEJlZ2luR3VpbGRQcnVuZS5pbmNsdWRlUm9sZXMgfCBpbmNsdWRlUm9sZXN9IHByb3BlcnR5IG9mIHRoZSBvcHRpb25zIG9iamVjdCBwYXJhbWV0ZXIuXG4gICAqXG4gICAqIEZpcmVzIGEgX0d1aWxkIE1lbWJlciBSZW1vdmVfIGdhdGV3YXkgZXZlbnQgZm9yIGV2ZXJ5IG1lbWJlciBraWNrZWQuXG4gICAqXG4gICAqIEBzZWUge0BsaW5rIGh0dHBzOi8vZG9jcy5kaXNjb3JkLmNvbS9kZXZlbG9wZXJzL3Jlc291cmNlcy9ndWlsZCNiZWdpbi1ndWlsZC1wcnVuZX1cbiAgICovXG4gIGFzeW5jIHBydW5lTWVtYmVycyhyZXN0OiBSZXN0TWFuYWdlciwgZ3VpbGRJZDogQmlnU3RyaW5nLCBvcHRpb25zOiBCZWdpbkd1aWxkUHJ1bmUsIHJlYXNvbj86IHN0cmluZyk6IFByb21pc2U8eyBwcnVuZWQ6IG51bWJlciB8IG51bGwgfT4ge1xuICAgIHJldHVybiBhd2FpdCByZXN0LnBvc3Q8eyBwcnVuZWQ6IG51bWJlciB8IG51bGwgfT4ocmVzdC5yb3V0ZXMuZ3VpbGRzLm1lbWJlcnMucHJ1bmUoZ3VpbGRJZCksIHsgYm9keTogb3B0aW9ucywgcmVhc29uIH0pO1xuICB9LFxuICAvKipcbiAgICogR2V0cyB0aGUgbGlzdCBvZiBtZW1iZXJzIHdob3NlIHVzZXJuYW1lcyBvciBuaWNrbmFtZXMgc3RhcnQgd2l0aCBhIHByb3ZpZGVkIHN0cmluZy5cbiAgICpcbiAgXG4gICAqIEBwYXJhbSBndWlsZElkIC0gVGhlIElEIG9mIHRoZSBndWlsZCB0byBzZWFyY2ggaW4uXG4gICAqIEBwYXJhbSBxdWVyeSAtIFRoZSBzdHJpbmcgdG8gbWF0Y2ggdXNlcm5hbWVzIG9yIG5pY2tuYW1lcyBhZ2FpbnN0LlxuICAgKiBAcGFyYW0gb3B0aW9ucyAtIFRoZSBwYXJhbWV0ZXJzIGZvciBzZWFyY2hpbmcgdGhyb3VnaCB0aGUgbWVtYmVycy5cbiAgICogQHJldHVybnMgQSBjb2xsZWN0aW9uIG9mIHtAbGluayBEaXNjb3JkTWVtYmVyfSBvYmplY3RzIGFzc29ydGVkIGJ5IHVzZXIgSUQuXG4gICAqXG4gICAqIEBzZWUge0BsaW5rIGh0dHBzOi8vZG9jcy5kaXNjb3JkLmNvbS9kZXZlbG9wZXJzL3Jlc291cmNlcy9ndWlsZCNzZWFyY2gtZ3VpbGQtbWVtYmVyc31cbiAgICovXG4gIGFzeW5jIHNlYXJjaE1lbWJlcnMoXG4gICAgcmVzdDogUmVzdE1hbmFnZXIsXG4gICAgZ3VpbGRJZDogQmlnU3RyaW5nLFxuICAgIHF1ZXJ5OiBzdHJpbmcsXG4gICAgb3B0aW9ucz86IE9taXQ8U2VhcmNoTWVtYmVycywgJ3F1ZXJ5Jz4sXG4gICk6IFByb21pc2U8RGlzY29yZE1lbWJlcldpdGhVc2VyW10+IHtcbiAgICByZXR1cm4gYXdhaXQgcmVzdC5nZXQ8RGlzY29yZE1lbWJlcldpdGhVc2VyW10+KHJlc3Qucm91dGVzLmd1aWxkcy5tZW1iZXJzLnNlYXJjaChndWlsZElkLCBxdWVyeSwgb3B0aW9ucykpO1xuICB9LFxuICAvKipcbiAgICogVW5iYW5zIGEgdXNlciBmcm9tIGEgZ3VpbGQuXG4gICAqXG4gICAqIEBwYXJhbSBndWlsZElkIC0gVGhlIElEIG9mIHRoZSBndWlsZCB0byB1bmJhbiB0aGUgdXNlciBpbi5cbiAgICogQHBhcmFtIHVzZXJJZCAtIFRoZSBJRCBvZiB0aGUgdXNlciB0byB1bmJhbi5cbiAgICogQHBhcmFtIHtzdHJpbmd9IFtyZWFzb25dIC0gQW4gb3B0aW9uYWwgcmVhc29uIGZvciB0aGUgYWN0aW9uLCB0byBiZSBpbmNsdWRlZCBpbiB0aGUgYXVkaXQgbG9nLlxuICAgKlxuICAgKiBAcmVtYXJrc1xuICAgKiBSZXF1aXJlcyB0aGUgYEJBTl9NRU1CRVJTYCBwZXJtaXNzaW9uLlxuICAgKlxuICAgKiBGaXJlcyBhIF9HdWlsZCBCYW4gUmVtb3ZlXyBnYXRld2F5IGV2ZW50LlxuICAgKlxuICAgKiBAc2VlIHtAbGluayBodHRwczovL2RvY3MuZGlzY29yZC5jb20vZGV2ZWxvcGVycy9yZXNvdXJjZXMvZ3VpbGQjcmVtb3ZlLWd1aWxkLWJhbn1cbiAgICovXG4gIGFzeW5jIHVuYmFuTWVtYmVyKHJlc3Q6IFJlc3RNYW5hZ2VyLCBndWlsZElkOiBCaWdTdHJpbmcsIHVzZXJJZDogQmlnU3RyaW5nLCByZWFzb24/OiBzdHJpbmcpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBhd2FpdCByZXN0LmRlbGV0ZShyZXN0LnJvdXRlcy5ndWlsZHMubWVtYmVycy5iYW4oZ3VpbGRJZCwgdXNlcklkKSwgeyByZWFzb24gfSk7XG4gIH0sXG4gIC8qKlxuICAgKiBVbnBpbiBhIG1lc3NhZ2UgaW4gYSBjaGFubmVsLlxuICAgKlxuICAgKiBAcGFyYW0gY2hhbm5lbElkIC0gVGhlIElEIG9mIHRoZSBjaGFubmVsIHdoZXJlIHRoZSBtZXNzYWdlIGlzIHBpbm5lZC5cbiAgICogQHBhcmFtIG1lc3NhZ2VJZCAtIFRoZSBJRCBvZiB0aGUgbWVzc2FnZSB0byB1bnBpbi5cbiAgICogQHBhcmFtIHtzdHJpbmd9IFtyZWFzb25dIC0gQW4gb3B0aW9uYWwgcmVhc29uIGZvciB0aGUgYWN0aW9uLCB0byBiZSBpbmNsdWRlZCBpbiB0aGUgYXVkaXQgbG9nLlxuICAgKlxuICAgKiBAcmVtYXJrc1xuICAgKiBSZXF1aXJlcyB0aGUgYFBJTl9NRVNTQUdFU2AgcGVybWlzc2lvbi5cbiAgICpcbiAgICogRmlyZXMgYSBfQ2hhbm5lbCBQaW5zIFVwZGF0ZV8gZXZlbnQuXG4gICAqXG4gICAqIEBzZWUge0BsaW5rIGh0dHBzOi8vZG9jcy5kaXNjb3JkLmNvbS9kZXZlbG9wZXJzL3Jlc291cmNlcy9tZXNzYWdlI3VucGluLW1lc3NhZ2V9XG4gICAqL1xuICBhc3luYyB1bnBpbk1lc3NhZ2UocmVzdDogUmVzdE1hbmFnZXIsIGNoYW5uZWxJZDogQmlnU3RyaW5nLCBtZXNzYWdlSWQ6IEJpZ1N0cmluZywgcmVhc29uPzogc3RyaW5nKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgYXdhaXQgcmVzdC5kZWxldGUocmVzdC5yb3V0ZXMuY2hhbm5lbHMubWVzc2FnZVBpbihjaGFubmVsSWQsIG1lc3NhZ2VJZCksIHsgcmVhc29uIH0pO1xuICB9LFxuICAvKipcbiAgICogR2V0IHRoZSBndWlsZCBvbmJvYXJkaW5nXG4gICAqXG4gICAqIEBwYXJhbSBndWlsZElkIC0gVGhlIGd1aWxkIHRvIGdldCB0aGUgb25ib2FyZGluZyBmcm9tXG4gICAqL1xuICBhc3luYyBnZXRHdWlsZE9uYm9hcmRpbmcocmVzdDogUmVzdE1hbmFnZXIsIGd1aWxkSWQ6IEJpZ1N0cmluZyk6IFByb21pc2U8RGlzY29yZEd1aWxkT25ib2FyZGluZz4ge1xuICAgIHJldHVybiBhd2FpdCByZXN0LmdldDxEaXNjb3JkR3VpbGRPbmJvYXJkaW5nPihyZXN0LnJvdXRlcy5ndWlsZHMub25ib2FyZGluZyhndWlsZElkKSk7XG4gIH0sXG4gIC8qKlxuICAgKiBNb2RpZmllcyB0aGUgb25ib2FyZGluZyBjb25maWd1cmF0aW9uIG9mIHRoZSBndWlsZC5cbiAgICpcbiAgICogQHBhcmFtIGd1aWxkSWQgLSBUaGUgZ3VpbGQgdG8gZWRpdCB0aGUgb25ib2FyZGluZyBmcm9tXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBbcmVhc29uXSAtIEFuIG9wdGlvbmFsIHJlYXNvbiBmb3IgdGhlIGFjdGlvbiwgdG8gYmUgaW5jbHVkZWQgaW4gdGhlIGF1ZGl0IGxvZy5cbiAgICpcbiAgICogQHJlbWFya3NcbiAgICogUmVxdWlyZXMgdGhlIGBNQU5BR0VfR1VJTERgIGFuZCBgTUFOQUdFX1JPTEVTYCBwZXJtaXNzaW9ucy5cbiAgICpcbiAgICogT25ib2FyZGluZyBlbmZvcmNlcyBjb25zdHJhaW50cyB3aGVuIGVuYWJsZWQuIFRoZXNlIGNvbnN0cmFpbnRzIGFyZTpcbiAgICogIC0gYXQgbGVhc3QgNyBkZWZhdWx0IGNoYW5uZWxzXG4gICAqICAtIGF0IGxlYXN0IDUgb2YgdGhlIDcgY2hhbm5lbHMgbXVzdCBhbGxvdyBzZW5kaW5nIG1lc3NhZ2VzIHRvIHRoZSBcXEBldmVyeW9uZSByb2xlXG4gICAqXG4gICAqIFRoZSBgbW9kZWAgZmllbGQgbW9kaWZpZXMgd2hhdCBpcyBjb25zaWRlcmVkIHdoZW4gZW5mb3JjaW5nIHRoZXNlIGNvbnN0cmFpbnRzLlxuICAgKi9cbiAgYXN5bmMgZWRpdEd1aWxkT25ib2FyZGluZyhyZXN0OiBSZXN0TWFuYWdlciwgZ3VpbGRJZDogQmlnU3RyaW5nLCBvcHRpb25zOiBFZGl0R3VpbGRPbmJvYXJkaW5nLCByZWFzb24/OiBzdHJpbmcpOiBQcm9taXNlPERpc2NvcmRHdWlsZE9uYm9hcmRpbmc+IHtcbiAgICByZXR1cm4gYXdhaXQgcmVzdC5wdXQ8RGlzY29yZEd1aWxkT25ib2FyZGluZz4ocmVzdC5yb3V0ZXMuZ3VpbGRzLm9uYm9hcmRpbmcoZ3VpbGRJZCksIHtcbiAgICAgIGJvZHk6IG9wdGlvbnMsXG4gICAgICByZWFzb24sXG4gICAgfSk7XG4gIH0sXG4gIC8qKlxuICAgKiBNb2RpZmllcyB0aGUgaW5jaWRlbnQgYWN0aW9ucyBvZiB0aGUgZ3VpbGQuXG4gICAqXG4gICAqIEBwYXJhbSBndWlsZElkIC0gVGhlIGd1aWxkIHRvIGVkaXQgdGhlIGluY2lkZW50IGFjdGlvbnMgZnJvbVxuICAgKiBAcGFyYW0gb3B0aW9ucyAtIFRoZSBvcHRpb25zIGZvciB0aGUgaW5jaWRlbnQgYWN0aW9uc1xuICAgKlxuICAgKiBAcmVtYXJrc1xuICAgKiBSZXF1aXJlcyB0aGUgYE1BTkFHRV9HVUlMRGAgcGVybWlzc2lvbi5cbiAgICovXG4gIGFzeW5jIG1vZGlmeUd1aWxkSW5jaWRlbnRBY3Rpb25zKHJlc3Q6IFJlc3RNYW5hZ2VyLCBndWlsZElkOiBCaWdTdHJpbmcsIG9wdGlvbnM6IE1vZGlmeUd1aWxkSW5jaWRlbnRBY3Rpb25zKTogUHJvbWlzZTxEaXNjb3JkSW5jaWRlbnRzRGF0YT4ge1xuICAgIHJldHVybiBhd2FpdCByZXN0LnB1dDxEaXNjb3JkSW5jaWRlbnRzRGF0YT4ocmVzdC5yb3V0ZXMuZ3VpbGRzLmluY2lkZW50QWN0aW9ucyhndWlsZElkKSwgeyBib2R5OiBvcHRpb25zIH0pO1xuICB9LFxuICAvKipcbiAgICogUmV0dXJucyBhbGwgZW50aXRsZW1lbnRzIGZvciBhIGdpdmVuIGFwcCwgYWN0aXZlIGFuZCBleHBpcmVkLlxuICAgKlxuICAgKiBAcGFyYW0gYXBwbGljYXRpb25JZCAtIFRoZSBpZCBvZiB0aGUgYXBwbGljYXRpb24gdG8gZ2V0IHRoZSBlbnRpdGxlbWVudHNcbiAgICogQHBhcmFtIHtHZXRFbnRpdGxlbWVudHN9IFtvcHRpb25zXSAtIFRoZSBvcHRpb25hbCBxdWVyeSBwYXJhbXMgZm9yIHRoZSBlbmRwb2ludFxuICAgKi9cbiAgYXN5bmMgbGlzdEVudGl0bGVtZW50cyhyZXN0OiBSZXN0TWFuYWdlciwgYXBwbGljYXRpb25JZDogQmlnU3RyaW5nLCBvcHRpb25zPzogR2V0RW50aXRsZW1lbnRzKTogUHJvbWlzZTxEaXNjb3JkRW50aXRsZW1lbnRbXT4ge1xuICAgIHJldHVybiBhd2FpdCByZXN0LmdldDxEaXNjb3JkRW50aXRsZW1lbnRbXT4ocmVzdC5yb3V0ZXMubW9uZXRpemF0aW9uLmVudGl0bGVtZW50cyhhcHBsaWNhdGlvbklkLCBvcHRpb25zKSk7XG4gIH0sXG4gIC8qKlxuICAgKiBSZXR1cm5zIGFuIGVudGl0bGVtZW50LlxuICAgKlxuICAgKiBAcGFyYW0gYXBwbGljYXRpb25JZCAtIFRoZSBpZCBvZiB0aGUgYXBwbGljYXRpb24gdG8gZ2V0IHRoZSBlbnRpdGxlbWVudFxuICAgKiBAcGFyYW0gZW50aXRsZW1lbnRJZCAtIFRoZSBpZCBvZiB0aGUgZW50aXRsZW1lbnQgdG8gZ2V0XG4gICAqL1xuICBhc3luYyBnZXRFbnRpdGxlbWVudChyZXN0OiBSZXN0TWFuYWdlciwgYXBwbGljYXRpb25JZDogQmlnU3RyaW5nLCBlbnRpdGxlbWVudElkOiBCaWdTdHJpbmcpOiBQcm9taXNlPERpc2NvcmRFbnRpdGxlbWVudD4ge1xuICAgIHJldHVybiBhd2FpdCByZXN0LmdldDxEaXNjb3JkRW50aXRsZW1lbnQ+KHJlc3Qucm91dGVzLm1vbmV0aXphdGlvbi5lbnRpdGxlbWVudChhcHBsaWNhdGlvbklkLCBlbnRpdGxlbWVudElkKSk7XG4gIH0sXG4gIC8qKlxuICAgKiBDcmVhdGVzIGEgdGVzdCBlbnRpdGxlbWVudCB0byBhIGdpdmVuIFNLVSBmb3IgYSBnaXZlbiBndWlsZCBvciB1c2VyLiBEaXNjb3JkIHdpbGwgYWN0IGFzIHRob3VnaCB0aGF0IHVzZXIgb3IgZ3VpbGQgaGFzIGVudGl0bGVtZW50IHRvIHlvdXIgcHJlbWl1bSBvZmZlcmluZy5cbiAgICpcbiAgICogQHBhcmFtIGFwcGxpY2F0aW9uSWQgLSBUaGUgaWQgb2YgdGhlIGFwcGxpY2F0aW9uIHRvIGNyZWF0ZSB0aGUgZW50aXRsZW1lbnRcbiAgICogQHBhcmFtIGJvZHkgLSBUaGUgb3B0aW9ucyBmb3IgbmV3IGVudGl0bGVtZW50XG4gICAqXG4gICAqIEByZW1hcmtzXG4gICAqIFRoaXMgZW5kcG9pbnQgcmV0dXJucyBhIHBhcnRpYWwgZW50aXRsZW1lbnQgb2JqZWN0LlxuICAgKiBJdCB3aWxsIG5vdCBjb250YWluIHN1YnNjcmlwdGlvbl9pZCwgc3RhcnRzX2F0LCBvciBlbmRzX2F0LCBhcyBpdCdzIHZhbGlkIGluIHBlcnBldHVpdHkuXG4gICAqL1xuICBhc3luYyBjcmVhdGVUZXN0RW50aXRsZW1lbnQocmVzdDogUmVzdE1hbmFnZXIsIGFwcGxpY2F0aW9uSWQ6IEJpZ1N0cmluZywgYm9keTogQ3JlYXRlVGVzdEVudGl0bGVtZW50KTogUHJvbWlzZTxQYXJ0aWFsPERpc2NvcmRFbnRpdGxlbWVudD4+IHtcbiAgICByZXR1cm4gYXdhaXQgcmVzdC5wb3N0PERpc2NvcmRFbnRpdGxlbWVudD4ocmVzdC5yb3V0ZXMubW9uZXRpemF0aW9uLmVudGl0bGVtZW50cyhhcHBsaWNhdGlvbklkKSwge1xuICAgICAgYm9keSxcbiAgICB9KTtcbiAgfSxcbiAgLyoqXG4gICAqIERlbGV0ZXMgYSBjdXJyZW50bHktYWN0aXZlIHRlc3QgZW50aXRsZW1lbnQuIERpc2NvcmQgd2lsbCBhY3QgYXMgdGhvdWdoIHRoYXQgdXNlciBvciBndWlsZCBubyBsb25nZXIgaGFzIGVudGl0bGVtZW50IHRvIHlvdXIgcHJlbWl1bSBvZmZlcmluZy5cbiAgICpcbiAgICogQHBhcmFtIGFwcGxpY2F0aW9uSWQgLSBUaGUgaWQgb2YgdGhlIGFwcGxpY2F0aW9uIGZyb20gd2hlcmUgZGVsZXRlIHRoZSBlbnRpdGxlbWVudFxuICAgKiBAcGFyYW0gZW50aXRsZW1lbnRJZCAtIFRoZSBpZCBvZiB0aGUgZW50aXRsZW1lbnQgdG8gZGVsZXRlXG4gICAqL1xuICBhc3luYyBkZWxldGVUZXN0RW50aXRsZW1lbnQocmVzdDogUmVzdE1hbmFnZXIsIGFwcGxpY2F0aW9uSWQ6IEJpZ1N0cmluZywgZW50aXRsZW1lbnRJZDogQmlnU3RyaW5nKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgYXdhaXQgcmVzdC5kZWxldGUocmVzdC5yb3V0ZXMubW9uZXRpemF0aW9uLmVudGl0bGVtZW50KGFwcGxpY2F0aW9uSWQsIGVudGl0bGVtZW50SWQpKTtcbiAgfSxcbiAgLyoqXG4gICAqIEZvciBPbmUtVGltZSBQdXJjaGFzZSBjb25zdW1hYmxlIFNLVXMsIG1hcmtzIGEgZ2l2ZW4gZW50aXRsZW1lbnQgZm9yIHRoZSB1c2VyIGFzIGNvbnN1bWVkLiBUaGUgZW50aXRsZW1lbnQgd2lsbCBoYXZlIGBjb25zdW1lZDogdHJ1ZWAgd2hlbiB1c2luZyB7QGxpbmsgbGlzdEVudGl0bGVtZW50cyB8IExpc3QgRW50aXRsZW1lbnRzfVxuICAgKlxuICAgKiBAcGFyYW0gYXBwbGljYXRpb25JZCAtIFRoZSBpZCBvZiB0aGUgYXBwbGljYXRpb24gdG8gZ2V0IHRoZSBlbnRpdGxlbWVudFxuICAgKiBAcGFyYW0gZW50aXRsZW1lbnRJZCAtIFRoZSBpZCBvZiB0aGUgZW50aXRsZW1lbnQgdG8gZ2V0XG4gICAqL1xuICBhc3luYyBjb25zdW1lRW50aXRsZW1lbnQocmVzdDogUmVzdE1hbmFnZXIsIGFwcGxpY2F0aW9uSWQ6IEJpZ1N0cmluZywgZW50aXRsZW1lbnRJZDogQmlnU3RyaW5nKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgYXdhaXQgcmVzdC5wb3N0KHJlc3Qucm91dGVzLm1vbmV0aXphdGlvbi5jb25zdW1lRW50aXRsZW1lbnQoYXBwbGljYXRpb25JZCwgZW50aXRsZW1lbnRJZCkpO1xuICB9LFxuICAvKipcbiAgICogUmV0dXJucyBhbGwgU0tVcyBmb3IgYSBnaXZlbiBhcHBsaWNhdGlvblxuICAgKlxuICAgKiBAcGFyYW0gYXBwbGljYXRpb25JZCAtIFRoZSBpZCBvZiB0aGUgYXBwbGljYXRpb24gdG8gZ2V0IHRoZSBTS1VzXG4gICAqL1xuICBhc3luYyBsaXN0U2t1cyhyZXN0OiBSZXN0TWFuYWdlciwgYXBwbGljYXRpb25JZDogQmlnU3RyaW5nKTogUHJvbWlzZTxEaXNjb3JkU2t1W10+IHtcbiAgICByZXR1cm4gYXdhaXQgcmVzdC5nZXQ8RGlzY29yZFNrdVtdPihyZXN0LnJvdXRlcy5tb25ldGl6YXRpb24uc2t1cyhhcHBsaWNhdGlvbklkKSk7XG4gIH0sXG4gIC8qKlxuICAgKiBSZXR1cm5zIGFsbCBzdWJzY3JpcHRpb25zIGNvbnRhaW5pbmcgdGhlIFNLVSwgZmlsdGVyZWQgYnkgdXNlci5cbiAgICpcbiAgICogQHBhcmFtIHNrdUlkIC0gVGhlIGlkIG9mIHRoZSBza3Ugb2YgZ2V0IHRoZSBzdWJzY3JpcHRpb25zIGZvclxuICAgKi9cbiAgYXN5bmMgbGlzdFN1YnNjcmlwdGlvbnMocmVzdDogUmVzdE1hbmFnZXIsIHNrdUlkOiBCaWdTdHJpbmcsIG9wdGlvbnM/OiBMaXN0U2t1U3Vic2NyaXB0aW9uc09wdGlvbnMpOiBQcm9taXNlPERpc2NvcmRTdWJzY3JpcHRpb25bXT4ge1xuICAgIHJldHVybiBhd2FpdCByZXN0LmdldDxEaXNjb3JkU3Vic2NyaXB0aW9uW10+KHJlc3Qucm91dGVzLm1vbmV0aXphdGlvbi5zdWJzY3JpcHRpb25zKHNrdUlkLCBvcHRpb25zKSk7XG4gIH0sXG4gIC8qKlxuICAgKiBHZXQgYSBzdWJzY3JpcHRpb24gYnkgaXRzIElELlxuICAgKlxuICAgKiBAcGFyYW0gc2t1SWQgLSBUaGUgaWQgb2YgdGhlIHNrdSBvZiBnZXQgdGhlIHN1YnNjcmlwdGlvbnMgZm9yXG4gICAqL1xuICBhc3luYyBnZXRTdWJzY3JpcHRpb24ocmVzdDogUmVzdE1hbmFnZXIsIHNrdUlkOiBCaWdTdHJpbmcsIHN1YnNjcmlwdGlvbklkOiBCaWdTdHJpbmcpOiBQcm9taXNlPERpc2NvcmRTdWJzY3JpcHRpb24+IHtcbiAgICByZXR1cm4gYXdhaXQgcmVzdC5nZXQ8RGlzY29yZFN1YnNjcmlwdGlvbj4ocmVzdC5yb3V0ZXMubW9uZXRpemF0aW9uLnN1YnNjcmlwdGlvbihza3VJZCwgc3Vic2NyaXB0aW9uSWQpKTtcbiAgfSxcbiAgLyoqXG4gICAqIFNlbmQgYSBzb3VuZGJvYXJkIHNvdW5kIHRvIGEgdm9pY2UgY2hhbm5lbCB0aGUgdXNlciBpcyBjb25uZWN0ZWQgdG8uXG4gICAqXG4gICAqIEBwYXJhbSBjaGFubmVsSWQgLSBUaGUgaWQgb2YgdGhlIHZvaWNlIGNoYW5uZWxcbiAgICpcbiAgICogQHJlbWFya3NcbiAgICogRmlyZXMgYSBfVm9pY2UgQ2hhbm5lbCBFZmZlY3QgU2VuZF8gR2F0ZXdheSBldmVudC5cbiAgICpcbiAgICogUmVxdWlyZXMgdGhlIGBTUEVBS2AgYW5kIGBVU0VfU09VTkRCT0FSRGAgcGVybWlzc2lvbnMsIGFuZCBhbHNvIHRoZSBgVVNFX0VYVEVSTkFMX1NPVU5EU2AgcGVybWlzc2lvbiBpZiB0aGUgc291bmQgaXMgZnJvbSBhIGRpZmZlcmVudCBzZXJ2ZXIuXG4gICAqIEFkZGl0aW9uYWxseSwgcmVxdWlyZXMgdGhlIHVzZXIgdG8gYmUgY29ubmVjdGVkIHRvIHRoZSB2b2ljZSBjaGFubmVsLCBoYXZpbmcgYSB2b2ljZSBzdGF0ZSB3aXRob3V0IGBkZWFmYCwgYHNlbGZfZGVhZmAsIGBtdXRlYCwgb3IgYHN1cHByZXNzYCBlbmFibGVkLlxuICAgKi9cbiAgYXN5bmMgc2VuZFNvdW5kYm9hcmRTb3VuZChyZXN0OiBSZXN0TWFuYWdlciwgY2hhbm5lbElkOiBCaWdTdHJpbmcsIG9wdGlvbnM6IFNlbmRTb3VuZGJvYXJkU291bmQpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBhd2FpdCByZXN0LnBvc3QocmVzdC5yb3V0ZXMuc291bmRib2FyZC5zZW5kU291bmQoY2hhbm5lbElkKSwge1xuICAgICAgYm9keTogb3B0aW9ucyxcbiAgICB9KTtcbiAgfSxcbiAgLyoqIFJldHVybnMgYW4gYXJyYXkgb2Ygc291bmRib2FyZCBzb3VuZCBvYmplY3RzIHRoYXQgY2FuIGJlIHVzZWQgYnkgYWxsIHVzZXJzLiAqL1xuICBhc3luYyBsaXN0RGVmYXVsdFNvdW5kYm9hcmRTb3VuZHMocmVzdDogUmVzdE1hbmFnZXIpOiBQcm9taXNlPERpc2NvcmRTb3VuZGJvYXJkU291bmRbXT4ge1xuICAgIHJldHVybiBhd2FpdCByZXN0LmdldDxEaXNjb3JkU291bmRib2FyZFNvdW5kW10+KHJlc3Qucm91dGVzLnNvdW5kYm9hcmQubGlzdERlZmF1bHQoKSk7XG4gIH0sXG4gIC8qKlxuICAgKiBSZXR1cm5zIGEgbGlzdCBvZiB0aGUgZ3VpbGQncyBzb3VuZGJvYXJkIHNvdW5kcy5cbiAgICpcbiAgICogQHBhcmFtIGd1aWxkSWQgLSBUaGUgZ3VpbGQgdG8gZ2V0IHRoZSBzb3VuZHMgZnJvbVxuICAgKlxuICAgKiBAcmVtYXJrc1xuICAgKiBJbmNsdWRlcyBgdXNlcmAgZmllbGRzIGlmIHRoZSBib3QgaGFzIHRoZSBgQ1JFQVRFX0dVSUxEX0VYUFJFU1NJT05TYCBvciBgTUFOQUdFX0dVSUxEX0VYUFJFU1NJT05TYCBwZXJtaXNzaW9uLlxuICAgKi9cbiAgYXN5bmMgbGlzdEd1aWxkU291bmRib2FyZFNvdW5kcyhyZXN0OiBSZXN0TWFuYWdlciwgZ3VpbGRJZDogQmlnU3RyaW5nKTogUHJvbWlzZTx7IGl0ZW1zOiBEaXNjb3JkU291bmRib2FyZFNvdW5kW10gfT4ge1xuICAgIHJldHVybiBhd2FpdCByZXN0LmdldDx7IGl0ZW1zOiBEaXNjb3JkU291bmRib2FyZFNvdW5kW10gfT4ocmVzdC5yb3V0ZXMuc291bmRib2FyZC5ndWlsZFNvdW5kcyhndWlsZElkKSk7XG4gIH0sXG4gIC8qKlxuICAgKiBSZXR1cm5zIGEgc291bmRib2FyZCBzb3VuZCBvYmplY3QgZm9yIHRoZSBnaXZlbiBzb3VuZCBpZC5cbiAgICpcbiAgICogQHBhcmFtIGd1aWxkSWQgLSBUaGUgZ3VpbGQgdG8gZ2V0IHRoZSBzb3VuZHMgZnJvbVxuICAgKiBAcGFyYW0gc291bmRJZCAtIFRoZSBzb3VuZCBpZFxuICAgKlxuICAgKiBAcmVtYXJrc1xuICAgKiBJbmNsdWRlcyBgdXNlcmAgZmllbGRzIGlmIHRoZSBib3QgaGFzIHRoZSBgQ1JFQVRFX0dVSUxEX0VYUFJFU1NJT05TYCBvciBgTUFOQUdFX0dVSUxEX0VYUFJFU1NJT05TYCBwZXJtaXNzaW9uLlxuICAgKi9cbiAgYXN5bmMgZ2V0R3VpbGRTb3VuZGJvYXJkU291bmQocmVzdDogUmVzdE1hbmFnZXIsIGd1aWxkSWQ6IEJpZ1N0cmluZywgc291bmRJZDogQmlnU3RyaW5nKTogUHJvbWlzZTxEaXNjb3JkU291bmRib2FyZFNvdW5kPiB7XG4gICAgcmV0dXJuIGF3YWl0IHJlc3QuZ2V0PERpc2NvcmRTb3VuZGJvYXJkU291bmQ+KHJlc3Qucm91dGVzLnNvdW5kYm9hcmQuZ3VpbGRTb3VuZChndWlsZElkLCBzb3VuZElkKSk7XG4gIH0sXG4gIC8qKlxuICAgKiBDcmVhdGUgYSBuZXcgc291bmRib2FyZCBzb3VuZCBmb3IgdGhlIGd1aWxkLlxuICAgKlxuICAgKiBAcGFyYW0gZ3VpbGRJZCAtIFRoZSBndWlsZCB0byBjcmVhdGUgdGhlIHNvdW5kcyBpblxuICAgKiBAcGFyYW0gb3B0aW9ucyAtIFRoZSBvcHRpb25zIHRvIGNyZWF0ZSB0aGUgc291bmRcbiAgICogQHBhcmFtIHJlYXNvbiAtIFRoZSBhdWRpdCBsb2cgcmVhc29uXG4gICAqXG4gICAqIEByZW1hcmtzXG4gICAqIEZpcmVzIGEgX0d1aWxkIFNvdW5kYm9hcmQgU291bmQgQ3JlYXRlXyBHYXRld2F5IGV2ZW50LlxuICAgKlxuICAgKiBSZXF1aXJlcyB0aGUgYENSRUFURV9HVUlMRF9FWFBSRVNTSU9OU2AgcGVybWlzc2lvbi5cbiAgICovXG4gIGFzeW5jIGNyZWF0ZUd1aWxkU291bmRib2FyZFNvdW5kKFxuICAgIHJlc3Q6IFJlc3RNYW5hZ2VyLFxuICAgIGd1aWxkSWQ6IEJpZ1N0cmluZyxcbiAgICBvcHRpb25zOiBDcmVhdGVHdWlsZFNvdW5kYm9hcmRTb3VuZCxcbiAgICByZWFzb24/OiBzdHJpbmcsXG4gICk6IFByb21pc2U8RGlzY29yZFNvdW5kYm9hcmRTb3VuZD4ge1xuICAgIHJldHVybiBhd2FpdCByZXN0LnBvc3Q8RGlzY29yZFNvdW5kYm9hcmRTb3VuZD4ocmVzdC5yb3V0ZXMuc291bmRib2FyZC5ndWlsZFNvdW5kcyhndWlsZElkKSwge1xuICAgICAgYm9keTogb3B0aW9ucyxcbiAgICAgIHJlYXNvbixcbiAgICB9KTtcbiAgfSxcbiAgLyoqXG4gICAqIE1vZGlmeSB0aGUgZ2l2ZW4gc291bmRib2FyZCBzb3VuZC5cbiAgICpcbiAgICogQHBhcmFtIGd1aWxkSWQgLSBUaGUgZ3VpbGQgdG8gY3JlYXRlIHRoZSBzb3VuZHMgaW5cbiAgICogQHBhcmFtIHNvdW5kSWQgLSBUaGUgc291bmQgaWQgdG8gdXBkYXRlXG4gICAqIEBwYXJhbSBvcHRpb25zIC0gVGhlIG9wdGlvbnMgdG8gdXBkYXRlIHRoZSBzb3VuZFxuICAgKiBAcGFyYW0gcmVhc29uIC0gVGhlIGF1ZGl0IGxvZyByZWFzb25cbiAgICpcbiAgICogQHJlbWFya3NcbiAgICogRmlyZXMgYSBfR3VpbGQgU291bmRib2FyZCBTb3VuZCBVcGRhdGVfIEdhdGV3YXkgZXZlbnQuXG4gICAqXG4gICAqIEZvciBzb3VuZHMgY3JlYXRlZCBieSB0aGUgY3VycmVudCB1c2VyLCByZXF1aXJlcyBlaXRoZXIgdGhlIGBDUkVBVEVfR1VJTERfRVhQUkVTU0lPTlNgIG9yIGBNQU5BR0VfR1VJTERfRVhQUkVTU0lPTlNgIHBlcm1pc3Npb24uXG4gICAqIEZvciBvdGhlciBzb3VuZHMsIHJlcXVpcmVzIHRoZSBgTUFOQUdFX0dVSUxEX0VYUFJFU1NJT05TYCBwZXJtaXNzaW9uLlxuICAgKi9cbiAgYXN5bmMgbW9kaWZ5R3VpbGRTb3VuZGJvYXJkU291bmQoXG4gICAgcmVzdDogUmVzdE1hbmFnZXIsXG4gICAgZ3VpbGRJZDogQmlnU3RyaW5nLFxuICAgIHNvdW5kSWQ6IEJpZ1N0cmluZyxcbiAgICBvcHRpb25zOiBNb2RpZnlHdWlsZFNvdW5kYm9hcmRTb3VuZCxcbiAgICByZWFzb24/OiBzdHJpbmcsXG4gICk6IFByb21pc2U8RGlzY29yZFNvdW5kYm9hcmRTb3VuZD4ge1xuICAgIHJldHVybiBhd2FpdCByZXN0LnBvc3Q8RGlzY29yZFNvdW5kYm9hcmRTb3VuZD4ocmVzdC5yb3V0ZXMuc291bmRib2FyZC5ndWlsZFNvdW5kKGd1aWxkSWQsIHNvdW5kSWQpLCB7XG4gICAgICBib2R5OiBvcHRpb25zLFxuICAgICAgcmVhc29uLFxuICAgIH0pO1xuICB9LFxuICAvKipcbiAgICogRGVsZXRlIHRoZSBnaXZlbiBzb3VuZGJvYXJkIHNvdW5kLlxuICAgKlxuICAgKiBAcGFyYW0gZ3VpbGRJZCAtIFRoZSBndWlsZCB0byBjcmVhdGUgdGhlIHNvdW5kcyBpblxuICAgKiBAcGFyYW0gc291bmRJZCAtIFRoZSBzb3VuZCBpZCB0byBkZWxldGVcbiAgICogQHBhcmFtIHJlYXNvbiAtIFRoZSBhdWRpdCBsb2cgcmVhc29uXG4gICAqXG4gICAqIEByZW1hcmtzXG4gICAqIEZpcmVzIGEgX0d1aWxkIFNvdW5kYm9hcmQgU291bmQgRGVsZXRlXyBHYXRld2F5IGV2ZW50LlxuICAgKlxuICAgKiBGb3Igc291bmRzIGNyZWF0ZWQgYnkgdGhlIGN1cnJlbnQgdXNlciwgcmVxdWlyZXMgZWl0aGVyIHRoZSBgQ1JFQVRFX0dVSUxEX0VYUFJFU1NJT05TYCBvciBgTUFOQUdFX0dVSUxEX0VYUFJFU1NJT05TYCBwZXJtaXNzaW9uLlxuICAgKiBGb3Igb3RoZXIgc291bmRzLCByZXF1aXJlcyB0aGUgYE1BTkFHRV9HVUlMRF9FWFBSRVNTSU9OU2AgcGVybWlzc2lvbi5cbiAgICovXG4gIGFzeW5jIGRlbGV0ZUd1aWxkU291bmRib2FyZFNvdW5kKHJlc3Q6IFJlc3RNYW5hZ2VyLCBndWlsZElkOiBCaWdTdHJpbmcsIHNvdW5kSWQ6IEJpZ1N0cmluZywgcmVhc29uPzogc3RyaW5nKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgcmV0dXJuIGF3YWl0IHJlc3QuZGVsZXRlKHJlc3Qucm91dGVzLnNvdW5kYm9hcmQuZ3VpbGRTb3VuZChndWlsZElkLCBzb3VuZElkKSwge1xuICAgICAgcmVhc29uLFxuICAgIH0pO1xuICB9LFxuICAvKipcbiAgICogUmV0dXJucyBhIGxpc3Qgb2YgYXBwbGljYXRpb24gcm9sZSBjb25uZWN0aW9uIG1ldGFkYXRhIG9iamVjdHMgZm9yIHRoZSBnaXZlbiBhcHBsaWNhdGlvbi5cbiAgICpcbiAgICogQHBhcmFtIGFwcGxpY2F0aW9uSWQgLSBUaGUgYXBwbGljYXRpb24gdG8gZ2V0IHRoZSByb2xlIGNvbm5lY3Rpb25zIGZyb21cbiAgICogQHJldHVybnMgQSBsaXN0IG9mIGFwcGxpY2F0aW9uIHJvbGUgY29ubmVjdGlvbiBtZXRhZGF0YSBvYmplY3RzXG4gICAqL1xuICBhc3luYyBsaXN0QXBwbGljYXRpb25Sb2xlQ29ubmVjdGlvbnNNZXRhZGF0YVJlY29yZHMoXG4gICAgcmVzdDogUmVzdE1hbmFnZXIsXG4gICAgYXBwbGljYXRpb25JZDogQmlnU3RyaW5nLFxuICApOiBQcm9taXNlPERpc2NvcmRBcHBsaWNhdGlvblJvbGVDb25uZWN0aW9uTWV0YWRhdGFbXT4ge1xuICAgIHJldHVybiBhd2FpdCByZXN0LmdldDxEaXNjb3JkQXBwbGljYXRpb25Sb2xlQ29ubmVjdGlvbk1ldGFkYXRhW10+KHJlc3Qucm91dGVzLmFwcGxpY2F0aW9uUm9sZUNvbm5lY3Rpb25NZXRhZGF0YShhcHBsaWNhdGlvbklkKSk7XG4gIH0sXG4gIC8qKlxuICAgKiBVcGRhdGVzIGFuZCByZXR1cm5zIGEgbGlzdCBvZiBhcHBsaWNhdGlvbiByb2xlIGNvbm5lY3Rpb24gbWV0YWRhdGEgb2JqZWN0cyBmb3IgdGhlIGdpdmVuIGFwcGxpY2F0aW9uLlxuICAgKlxuICAgKiBAcGFyYW0gYXBwbGljYXRpb25JZCAtIFRoZSBhcHBsaWNhdGlvbiB0byBnZXQgdGhlIHJvbGUgY29ubmVjdGlvbnMgZnJvbVxuICAgKiBAcGFyYW0gb3B0aW9ucyAtIFRoZSBvcHRpb25zIHRvIHVwZGF0ZSB0aGUgcm9sZSBjb25uZWN0aW9uc1xuICAgKiBAcmV0dXJucyBBIGxpc3Qgb2YgYXBwbGljYXRpb24gcm9sZSBjb25uZWN0aW9uIG1ldGFkYXRhIG9iamVjdHNcbiAgICpcbiAgICogQHJlbWFya3NcbiAgICogQW4gYXBwbGljYXRpb24gY2FuIGhhdmUgYSBtYXhpbXVtIG9mIDUgbWV0YWRhdGEgcmVjb3Jkcy5cbiAgICovXG4gIGFzeW5jIHVwZGF0ZUFwcGxpY2F0aW9uUm9sZUNvbm5lY3Rpb25zTWV0YWRhdGFSZWNvcmRzKFxuICAgIHJlc3Q6IFJlc3RNYW5hZ2VyLFxuICAgIGFwcGxpY2F0aW9uSWQ6IEJpZ1N0cmluZyxcbiAgICBvcHRpb25zOiBDYW1lbGl6ZTxEaXNjb3JkQXBwbGljYXRpb25Sb2xlQ29ubmVjdGlvbk1ldGFkYXRhW10+LFxuICApOiBQcm9taXNlPERpc2NvcmRBcHBsaWNhdGlvblJvbGVDb25uZWN0aW9uTWV0YWRhdGFbXT4ge1xuICAgIHJldHVybiBhd2FpdCByZXN0LnB1dDxEaXNjb3JkQXBwbGljYXRpb25Sb2xlQ29ubmVjdGlvbk1ldGFkYXRhW10+KHJlc3Qucm91dGVzLmFwcGxpY2F0aW9uUm9sZUNvbm5lY3Rpb25NZXRhZGF0YShhcHBsaWNhdGlvbklkKSwge1xuICAgICAgYm9keTogb3B0aW9ucyxcbiAgICB9KTtcbiAgfSxcbiAgLyoqXG4gICAqIENyZWF0ZXMgYSBuZXcgbG9iYnksIGFkZGluZyBhbnkgb2YgdGhlIHNwZWNpZmllZCBtZW1iZXJzIHRvIGl0LCBpZiBwcm92aWRlZC5cbiAgICpcbiAgICogQHBhcmFtIG9wdGlvbnMgLSBUaGUgb3B0aW9ucyB0byBjcmVhdGUgdGhlIGxvYmJ5XG4gICAqIEByZXR1cm5zIFRoZSBjcmVhdGVkIGxvYmJ5XG4gICAqL1xuICBhc3luYyBjcmVhdGVMb2JieShyZXN0OiBSZXN0TWFuYWdlciwgb3B0aW9uczogQ3JlYXRlTG9iYnkpOiBQcm9taXNlPERpc2NvcmRMb2JieT4ge1xuICAgIHJldHVybiBhd2FpdCByZXN0LnBvc3Q8RGlzY29yZExvYmJ5PihyZXN0LnJvdXRlcy5sb2JieS5jcmVhdGUoKSwge1xuICAgICAgYm9keTogb3B0aW9ucyxcbiAgICB9KTtcbiAgfSxcbiAgLyoqXG4gICAqIENyZWF0ZXMgYSBuZXcgbG9iYnkgZm9yIHRoZSBhcHBsaWNhdGlvbiBpZGVudGlmaWVkIGJ5IGEgYHNlY3JldGAsIG9yIGpvaW5zIHRoZSBjYWxsaW5nIHVzZXIgdG8gdGhlIGV4aXN0aW5nIGxvYmJ5IHdpdGggdGhhdCBzZWNyZXQgaWYgb25lIGFscmVhZHkgZXhpc3RzLlxuICAgKlxuICAgKiBVcGRhdGVzIGxvYmJ5IG1ldGFkYXRhIGFuZCB0aGUgY2FsbGluZyBtZW1iZXIncyBtZXRhZGF0YSBvbiBqb2luLlxuICAgKlxuICAgKiBAcGFyYW0gb3B0aW9ucyAtIFRoZSBvcHRpb25zIHRvIGNyZWF0ZSBvciBqb2luIHRoZSBsb2JieVxuICAgKiBAcmV0dXJucyAtIFRoZSBjcmVhdGVkIG9yIGpvaW5lZCBsb2JieVxuICAgKlxuICAgKiBAcmVtYXJrc1xuICAgKiBVc2VzIGBCZWFyZXJgIHRva2VuIGZvciBhdXRob3JpemF0aW9uIHdpdGggdGhlIGBzZGsuc29jaWFsX2xheWVyYCBzY29wZS5cbiAgICovXG4gIGFzeW5jIGNyZWF0ZU9ySm9pbkxvYmJ5KHJlc3Q6IFJlc3RNYW5hZ2VyLCBvcHRpb25zOiBDcmVhdGVPckpvaW5Mb2JieSk6IFByb21pc2U8RGlzY29yZExvYmJ5PiB7XG4gICAgcmV0dXJuIGF3YWl0IHJlc3QucHV0PERpc2NvcmRMb2JieT4ocmVzdC5yb3V0ZXMubG9iYnkuY3JlYXRlKCksIHtcbiAgICAgIGJvZHk6IG9wdGlvbnMsXG4gICAgfSk7XG4gIH0sXG4gIC8qKlxuICAgKiBSZXR1cm5zIGEgbG9iYnkgb2JqZWN0IGZvciB0aGUgc3BlY2lmaWVkIGxvYmJ5IGlkLCBpZiBpdCBleGlzdHMuXG4gICAqXG4gICAqIEBwYXJhbSBsb2JieUlkIC0gVGhlIElEIG9mIHRoZSBsb2JieSB0byBnZXRcbiAgICogQHJldHVybnMgVGhlIGxvYmJ5IG9iamVjdFxuICAgKi9cbiAgYXN5bmMgZ2V0TG9iYnkocmVzdDogUmVzdE1hbmFnZXIsIGxvYmJ5SWQ6IEJpZ1N0cmluZyk6IFByb21pc2U8RGlzY29yZExvYmJ5PiB7XG4gICAgcmV0dXJuIGF3YWl0IHJlc3QuZ2V0PERpc2NvcmRMb2JieT4ocmVzdC5yb3V0ZXMubG9iYnkubG9iYnkobG9iYnlJZCkpO1xuICB9LFxuICAvKipcbiAgICogTW9kaWZpZXMgdGhlIHNwZWNpZmllZCBsb2JieSB3aXRoIG5ldyB2YWx1ZXMsIGlmIHByb3ZpZGVkLlxuICAgKlxuICAgKiBAcGFyYW0gbG9iYnlJZCAtIFRoZSBJRCBvZiB0aGUgbG9iYnkgdG8gbW9kaWZ5XG4gICAqIEBwYXJhbSBvcHRpb25zIC0gVGhlIG9wdGlvbnMgdG8gbW9kaWZ5IHRoZSBsb2JieVxuICAgKiBAcmV0dXJucyBUaGUgbW9kaWZpZWQgbG9iYnlcbiAgICovXG4gIGFzeW5jIG1vZGlmeUxvYmJ5KHJlc3Q6IFJlc3RNYW5hZ2VyLCBsb2JieUlkOiBCaWdTdHJpbmcsIG9wdGlvbnM6IE1vZGlmeUxvYmJ5KTogUHJvbWlzZTxEaXNjb3JkTG9iYnk+IHtcbiAgICByZXR1cm4gYXdhaXQgcmVzdC5wYXRjaDxEaXNjb3JkTG9iYnk+KHJlc3Qucm91dGVzLmxvYmJ5LmxvYmJ5KGxvYmJ5SWQpLCB7XG4gICAgICBib2R5OiBvcHRpb25zLFxuICAgIH0pO1xuICB9LFxuICAvKipcbiAgICogRGVsZXRlcyB0aGUgc3BlY2lmaWVkIGxvYmJ5IGlmIGl0IGV4aXN0cy5cbiAgICpcbiAgICogSXQgaXMgc2FmZSB0byBjYWxsIGV2ZW4gaWYgdGhlIGxvYmJ5IGlzIGFscmVhZHkgZGVsZXRlZCBhcyB3ZWxsLlxuICAgKlxuICAgKiBAcGFyYW0gbG9iYnlJZCAtIFRoZSBJRCBvZiB0aGUgbG9iYnkgdG8gZGVsZXRlXG4gICAqIEByZXR1cm5zIE5vdGhpbmdcbiAgICovXG4gIGFzeW5jIGRlbGV0ZUxvYmJ5KHJlc3Q6IFJlc3RNYW5hZ2VyLCBsb2JieUlkOiBCaWdTdHJpbmcpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICByZXR1cm4gYXdhaXQgcmVzdC5kZWxldGUocmVzdC5yb3V0ZXMubG9iYnkubG9iYnkobG9iYnlJZCkpO1xuICB9LFxuICAvKipcbiAgICogQWRkcyB0aGUgcHJvdmlkZWQgdXNlciB0byB0aGUgc3BlY2lmaWVkIGxvYmJ5LiBJZiBjYWxsZWQgd2hlbiB0aGUgdXNlciBpcyBhbHJlYWR5IGEgbWVtYmVyIG9mIHRoZSBsb2JieSB3aWxsIHVwZGF0ZSBmaWVsZHMgc3VjaCBhcyBtZXRhZGF0YSBvbiB0aGF0IHVzZXIgaW5zdGVhZC5cbiAgICpcbiAgICogQHBhcmFtIGxvYmJ5SWQgLSBUaGUgSUQgb2YgdGhlIGxvYmJ5IHRvIGFkZCB0aGUgdXNlciB0b1xuICAgKiBAcGFyYW0gdXNlcklkIC0gVGhlIElEIG9mIHRoZSB1c2VyIHRvIGFkZCB0byB0aGUgbG9iYnlcbiAgICogQHBhcmFtIG9wdGlvbnMgLSBUaGUgb3B0aW9ucyB0byBhZGQgdGhlIHVzZXIgdG8gdGhlIGxvYmJ5XG4gICAqIEByZXR1cm5zIFRoZSBsb2JieSBtZW1iZXIgb2JqZWN0XG4gICAqL1xuICBhc3luYyBhZGRNZW1iZXJUb0xvYmJ5KHJlc3Q6IFJlc3RNYW5hZ2VyLCBsb2JieUlkOiBCaWdTdHJpbmcsIHVzZXJJZDogQmlnU3RyaW5nLCBvcHRpb25zOiBBZGRMb2JieU1lbWJlcik6IFByb21pc2U8RGlzY29yZExvYmJ5TWVtYmVyPiB7XG4gICAgcmV0dXJuIGF3YWl0IHJlc3QucHV0PERpc2NvcmRMb2JieU1lbWJlcj4ocmVzdC5yb3V0ZXMubG9iYnkubWVtYmVyKGxvYmJ5SWQsIHVzZXJJZCksIHtcbiAgICAgIGJvZHk6IG9wdGlvbnMsXG4gICAgfSk7XG4gIH0sXG4gIC8qKlxuICAgKiBBZGRzLCB1cGRhdGVzLCBvciByZW1vdmVzIHVwIHRvIDI1IG1lbWJlcnMgZnJvbSB0aGUgc3BlY2lmaWVkIGxvYmJ5IGluIGEgc2luZ2xlIHJlcXVlc3QuXG4gICAqXG4gICAqIEBwYXJhbSBsb2JieUlkIC0gVGhlIElEIG9mIHRoZSBsb2JieSB0byBhZGQsIHVwZGF0ZSwgb3IgcmVtb3ZlIG1lbWJlcnMgZnJvbVxuICAgKiBAcGFyYW0gb3B0aW9ucyAtIFRoZSBvcHRpb25zIHRvIGFkZCwgdXBkYXRlLCBvciByZW1vdmUgbWVtYmVycyBmcm9tIHRoZSBsb2JieVxuICAgKiBAcmV0dXJucyBSZXR1cm5zIGFuIGFycmF5IG9mIGxvYmJ5IG1lbWJlciBvYmplY3RzIGZvciB0aGUgdXBzZXJ0ZWQgbWVtYmVycy4gUmVtb3ZlZCBtZW1iZXJzIGFyZSBub3QgaW5jbHVkZWQgaW4gdGhlIHJlc3BvbnNlLlxuICAgKlxuICAgKiBAcmVtYXJrc1xuICAgKiBNZW1iZXJzIHdpdGggYHJlbW92ZV9tZW1iZXI6IGZhbHNlYCAodGhlIGRlZmF1bHQpIGFyZSB1cHNlcnRlZCDigJQgYWRkZWQgaWYgbm90IHByZXNlbnQsIG9yIHVwZGF0ZWQgd2l0aCB0aGUgcHJvdmlkZWQgbWV0YWRhdGEgYW5kIGZsYWdzIGlmIGFscmVhZHkgYSBtZW1iZXIuIE1lbWJlcnMgd2l0aCBgcmVtb3ZlX21lbWJlcjogdHJ1ZWAgYXJlIHJlbW92ZWQuXG4gICAqXG4gICAqIFVzZXJzIHVua25vd24gdG8gRGlzY29yZCB3aWxsIHJldHVybiBhIDQwNCBVTktOT1dOX1VTRVIgZXJyb3IuXG4gICAqIFVzZXJzIHRoYXQgZmFpbCBwZXJtaXNzaW9uIGNoZWNrcyBvciB3aG8gaGF2ZSBhbHJlYWR5IHJlYWNoZWQgdGhlIG1heGltdW0gbnVtYmVyIG9mIGxvYmJpZXMgcGVyIGFwcGxpY2F0aW9uIChhbmQgYXJlIG5vdCBhbHJlYWR5IGEgbWVtYmVyIG9mIHRoaXMgbG9iYnkpIGFyZSBzaWxlbnRseSBkcm9wcGVkIGZyb20gdGhlIHVwc2VydCBzZXQuXG4gICAqXG4gICAqIEBzZWUge0BsaW5rIGh0dHBzOi8vZG9jcy5kaXNjb3JkLmNvbS9kZXZlbG9wZXJzL3Jlc291cmNlcy9sb2JieSNidWxrLXVwZGF0ZS1sb2JieS1tZW1iZXJzfVxuICAgKi9cbiAgYXN5bmMgYnVsa1VwZGF0ZUxvYmJ5TWVtYmVycyhyZXN0OiBSZXN0TWFuYWdlciwgbG9iYnlJZDogQmlnU3RyaW5nLCBvcHRpb25zOiBCdWxrVXBkYXRlTG9iYnlNZW1iZXJbXSk6IFByb21pc2U8RGlzY29yZExvYmJ5TWVtYmVyW10+IHtcbiAgICByZXR1cm4gYXdhaXQgcmVzdC5wb3N0PERpc2NvcmRMb2JieU1lbWJlcltdPihyZXN0LnJvdXRlcy5sb2JieS5tZW1iZXJzQnVsayhsb2JieUlkKSwge1xuICAgICAgYm9keTogb3B0aW9ucyxcbiAgICB9KTtcbiAgfSxcbiAgLyoqXG4gICAqIFJlbW92ZXMgdGhlIHByb3ZpZGVkIHVzZXIgZnJvbSB0aGUgc3BlY2lmaWVkIGxvYmJ5LiBJdCBpcyBzYWZlIHRvIGNhbGwgdGhpcyBldmVuIGlmIHRoZSB1c2VyIGlzIG5vIGxvbmdlciBhIG1lbWJlciBvZiB0aGUgbG9iYnksIGJ1dCB3aWxsIGZhaWwgaWYgdGhlIGxvYmJ5IGRvZXMgbm90IGV4aXN0LlxuICAgKlxuICAgKiBAcGFyYW0gbG9iYnlJZCAtIFRoZSBJRCBvZiB0aGUgbG9iYnkgdG8gcmVtb3ZlIHRoZSB1c2VyIGZyb21cbiAgICogQHBhcmFtIHVzZXJJZCAtIFRoZSBJRCBvZiB0aGUgdXNlciB0byByZW1vdmUgZnJvbSB0aGUgbG9iYnlcbiAgICogQHJldHVybnMgTm90aGluZ1xuICAgKi9cbiAgYXN5bmMgcmVtb3ZlTWVtYmVyRnJvbUxvYmJ5KHJlc3Q6IFJlc3RNYW5hZ2VyLCBsb2JieUlkOiBCaWdTdHJpbmcsIHVzZXJJZDogQmlnU3RyaW5nKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgcmV0dXJuIGF3YWl0IHJlc3QuZGVsZXRlKHJlc3Qucm91dGVzLmxvYmJ5Lm1lbWJlcihsb2JieUlkLCB1c2VySWQpKTtcbiAgfSxcbiAgLyoqXG4gICAqIFJlbW92ZXMgdGhlIGN1cnJlbnQgdXNlciBmcm9tIHRoZSBzcGVjaWZpZWQgbG9iYnkuIEl0IGlzIHNhZmUgdG8gY2FsbCB0aGlzIGV2ZW4gaWYgdGhlIHVzZXIgaXMgbm8gbG9uZ2VyIGEgbWVtYmVyIG9mIHRoZSBsb2JieSwgYnV0IHdpbGwgZmFpbCBpZiB0aGUgbG9iYnkgZG9lcyBub3QgZXhpc3QuXG4gICAqXG4gICAqIEBwYXJhbSBsb2JieUlkIC0gVGhlIElEIG9mIHRoZSBsb2JieSB0byByZW1vdmUgdGhlIHVzZXIgZnJvbVxuICAgKiBAcGFyYW0gYmVhcmVyVG9rZW4gLSBUaGUgYWNjZXNzIHRva2VuIG9mIHRoZSB1c2VyXG4gICAqIEByZXR1cm5zIE5vdGhpbmdcbiAgICpcbiAgICogQHJlbWFya3NcbiAgICogVGhpcyByZXF1aXJlcyBhIGJlYXJlciB0b2tlbiBmb3IgYXV0aG9yaXphdGlvblxuICAgKi9cbiAgYXN5bmMgbGVhdmVMb2JieShyZXN0OiBSZXN0TWFuYWdlciwgbG9iYnlJZDogQmlnU3RyaW5nLCBiZWFyZXJUb2tlbjogc3RyaW5nKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgcmV0dXJuIGF3YWl0IHJlc3QuZGVsZXRlKHJlc3Qucm91dGVzLmxvYmJ5LmxlYXZlKGxvYmJ5SWQpLCB7XG4gICAgICBoZWFkZXJzOiB7XG4gICAgICAgIGF1dGhvcml6YXRpb246IGBCZWFyZXIgJHtiZWFyZXJUb2tlbn1gLFxuICAgICAgfSxcbiAgICAgIHVuYXV0aG9yaXplZDogdHJ1ZSxcbiAgICB9KTtcbiAgfSxcbiAgLyoqXG4gICAqIExpbmtzIGFuIGV4aXN0aW5nIHRleHQgY2hhbm5lbCB0byBhIGxvYmJ5LlxuICAgKlxuICAgKiBAcGFyYW0gbG9iYnlJZCAtIFRoZSBJRCBvZiB0aGUgbG9iYnkgdG8gbGluayB0aGUgY2hhbm5lbCB0b1xuICAgKiBAcGFyYW0gYmVhcmVyVG9rZW4gLSBUaGUgYWNjZXNzIHRva2VuIG9mIHRoZSB1c2VyXG4gICAqIEBwYXJhbSBvcHRpb25zIC0gVGhlIG9wdGlvbnMgdG8gbGluayB0aGUgY2hhbm5lbCB0byB0aGUgbG9iYnlcbiAgICogQHJldHVybnMgVGhlIHVwZGF0ZWQgbG9iYnkgb2JqZWN0XG4gICAqXG4gICAqIEByZW1hcmtzXG4gICAqIFVzZXMgYmVhcmVyIHRva2VuIGZvciBhdXRob3JpemF0aW9uIGFuZCB0aGUgdXNlciBtdXN0IGJlIGEgbG9iYnkgbWVtYmVyIHdpdGggdGhlIENhbkxpbmtMb2JieSBsb2JieSBtZW1iZXIgZmxhZy5cbiAgICovXG4gIGFzeW5jIGxpbmtDaGFubmVsVG9Mb2JieShyZXN0OiBSZXN0TWFuYWdlciwgbG9iYnlJZDogQmlnU3RyaW5nLCBiZWFyZXJUb2tlbjogc3RyaW5nLCBvcHRpb25zOiBMaW5rQ2hhbm5lbFRvTG9iYnkpOiBQcm9taXNlPERpc2NvcmRMb2JieT4ge1xuICAgIHJldHVybiBhd2FpdCByZXN0LnBhdGNoPERpc2NvcmRMb2JieT4ocmVzdC5yb3V0ZXMubG9iYnkubGluayhsb2JieUlkKSwge1xuICAgICAgYm9keTogb3B0aW9ucyxcbiAgICAgIGhlYWRlcnM6IHtcbiAgICAgICAgYXV0aG9yaXphdGlvbjogYEJlYXJlciAke2JlYXJlclRva2VufWAsXG4gICAgICB9LFxuICAgICAgdW5hdXRob3JpemVkOiB0cnVlLFxuICAgIH0pO1xuICB9LFxuICAvKipcbiAgICogVW5saW5rcyBhbnkgY3VycmVudGx5IGxpbmtlZCBjaGFubmVscyBmcm9tIHRoZSBzcGVjaWZpZWQgbG9iYnkuXG4gICAqXG4gICAqIEBwYXJhbSBsb2JieUlkIC0gVGhlIElEIG9mIHRoZSBsb2JieSB0byB1bmxpbmsgdGhlIGNoYW5uZWwgZnJvbVxuICAgKiBAcGFyYW0gYmVhcmVyVG9rZW4gLSBUaGUgYWNjZXNzIHRva2VuIG9mIHRoZSB1c2VyXG4gICAqIEByZXR1cm5zIFRoZSB1cGRhdGVkIGxvYmJ5IG9iamVjdFxuICAgKlxuICAgKiBAcmVtYXJrc1xuICAgKiBVc2VzIGJlYXJlciB0b2tlbiBmb3IgYXV0aG9yaXphdGlvbiBhbmQgdGhlIHVzZXIgbXVzdCBiZSBhIGxvYmJ5IG1lbWJlciB3aXRoIHRoZSBDYW5MaW5rTG9iYnkgbG9iYnkgbWVtYmVyIGZsYWcuXG4gICAqL1xuICBhc3luYyB1bmxpbmtDaGFubmVsVG9Mb2JieShyZXN0OiBSZXN0TWFuYWdlciwgbG9iYnlJZDogQmlnU3RyaW5nLCBiZWFyZXJUb2tlbjogc3RyaW5nKTogUHJvbWlzZTxEaXNjb3JkTG9iYnk+IHtcbiAgICByZXR1cm4gYXdhaXQgcmVzdC5wYXRjaDxEaXNjb3JkTG9iYnk+KHJlc3Qucm91dGVzLmxvYmJ5LmxpbmsobG9iYnlJZCksIHtcbiAgICAgIGhlYWRlcnM6IHtcbiAgICAgICAgYXV0aG9yaXphdGlvbjogYEJlYXJlciAke2JlYXJlclRva2VufWAsXG4gICAgICB9LFxuICAgICAgdW5hdXRob3JpemVkOiB0cnVlLFxuICAgIH0pO1xuICB9LFxuICAvKipcbiAgICogU2V0cyB0aGUgbW9kZXJhdGlvbiBtZXRhZGF0YSBmb3IgYSBsb2JieSBtZXNzYWdlLiBUaGUgbWV0YWRhdGEgaXMgYXBwLXNjb3BlZCBhbmQgZGVsaXZlcmVkIHRvIGFjdGl2ZSBnYW1lIGNsaWVudHMgdmlhIHRoZSBTb2NpYWwgU0RLIGFzIGEgcmVhbHRpbWUgbWVzc2FnZSB1cGRhdGUuXG4gICAqXG4gICAqIEBwYXJhbSBsb2JieUlkIC0gVGhlIElEIG9mIHRoZSBsb2JieSB0byBzZXQgdGhlIG1vZGVyYXRpb24gbWV0YWRhdGFcbiAgICogQHBhcmFtIG1lc3NhZ2VJZCAtIFRoZSBJRCBvZiB0aGUgbWVzc2FnZSB0byBzZXQgdGhlIG1vZGVyYXRpb24gbWV0YWRhdGFcbiAgICogQHBhcmFtIG9wdGlvbnMgLSBUaGUgbW9kZXJhdGlvbiBtZXRhZGF0YSB0byBzZXRcbiAgICpcbiAgICogQHJlbWFya3NcbiAgICogVXNlcyBgQm90YCB0b2tlbiBmb3IgYXV0aG9yaXphdGlvbi5cbiAgICpcbiAgICogRm9yIHRoZSBvcHRpb25zOiBGcmVlLWZvcm0ga2V54oCTdmFsdWUgcGFpcnMgZGVzY3JpYmluZyB0aGUgbW9kZXJhdGlvbiBkZWNpc2lvbi4gVXAgdG8gNSBrZXlzOyBrZXkgbGVuZ3RoIDw9IDEwMjQgY2hhcmFjdGVyczsgdmFsdWUgbGVuZ3RoIDw9IDIwMDAgY2hhcmFjdGVyc1xuICAgKlxuICAgKiBAc2VlIHtAbGluayBodHRwczovL2Rpc2NvcmQuY29tL2RldmVsb3BlcnMvZG9jcy9nYW1lLXNkay9zb2NpYWwtc2RrL2NoYXQtbW9kZXJhdGlvbiNzZXJ2ZXItc2lkZS1jaGF0LW1vZGVyYXRpb259IGZvciB0aGUgZnVsbCBtb2RlcmF0aW9uIGZsb3cuXG4gICAqL1xuICBhc3luYyB1cGRhdGVMb2JieU1lc3NhZ2VNb2RlcmF0aW9uTWV0YWRhdGEoXG4gICAgcmVzdDogUmVzdE1hbmFnZXIsXG4gICAgbG9iYnlJZDogQmlnU3RyaW5nLFxuICAgIG1lc3NhZ2VJZDogQmlnU3RyaW5nLFxuICAgIG9wdGlvbnM6IFJlY29yZDxzdHJpbmcsIHN0cmluZz4sXG4gICk6IFByb21pc2U8dm9pZD4ge1xuICAgIGF3YWl0IHJlc3QucHV0KHJlc3Qucm91dGVzLmxvYmJ5Lm1vZGVyYXRpb25NZXRhZGF0YShsb2JieUlkLCBtZXNzYWdlSWQpLCB7XG4gICAgICBib2R5OiBvcHRpb25zLFxuICAgIH0pO1xuICB9LFxuICAvKipcbiAgICogU2VuZHMgYSBtZXNzYWdlIHRvIHRoZSBzcGVjaWZpZWQgbG9iYnkuIFRoZSBjYWxsaW5nIHVzZXIgbXVzdCBiZSBhIG1lbWJlciBvZiB0aGUgbG9iYnkuXG4gICAqXG4gICAqIEBwYXJhbSBiZWFyZXJUb2tlbiAtIFRoZSBhY2Nlc3MgdG9rZW4gb2YgdGhlIHVzZXJcbiAgICogQHBhcmFtIGxvYmJ5SWQgLSBUaGUgSUQgb2YgdGhlIGxvYmJ5IHRvIHNlbmQgdGhlIG1lc3NhZ2UgdG9cbiAgICogQHBhcmFtIG9wdGlvbnMgLSBUaGUgb3B0aW9ucyB0byBzZW5kIHRoZSBtZXNzYWdlXG4gICAqIEByZXR1cm5zIFJldHVybnMgdGhlIGNyZWF0ZWQgbG9iYnkgbWVzc2FnZSBvYmplY3QuXG4gICAqXG4gICAqIEByZW1hcmtzXG4gICAqIFVzZXMgYEJlYXJlcmAgdG9rZW4gZm9yIGF1dGhvcml6YXRpb24gd2l0aCB0aGUgYHNkay5zb2NpYWxfbGF5ZXJgIHNjb3BlLlxuICAgKlxuICAgKiBJZiB0aGUgbG9iYnkgaGFzIGEgbGlua2VkIGNoYW5uZWwsIHRoZSBtZXNzYWdlIGlzIGFsc28gZm9yd2FyZGVkIHRvIHRoYXQgY2hhbm5lbC5cbiAgICogSWYgZm9yd2FyZGluZyBmYWlscyAoZm9yIGV4YW1wbGUsIGR1ZSB0byBBdXRvTW9kKSwgdGhlIGxvYmJ5IG1lc3NhZ2UgaXMgc3RpbGwgZGVsaXZlcmVkIHRvIG90aGVyIGxvYmJ5IG1lbWJlcnMuXG4gICAqL1xuICBhc3luYyBzZW5kTG9iYnlNZXNzYWdlKHJlc3Q6IFJlc3RNYW5hZ2VyLCBiZWFyZXJUb2tlbjogc3RyaW5nLCBsb2JieUlkOiBCaWdTdHJpbmcsIG9wdGlvbnM6IFNlbmRMb2JieU1lc3NhZ2UpOiBQcm9taXNlPERpc2NvcmRMb2JieU1lc3NhZ2U+IHtcbiAgICByZXR1cm4gYXdhaXQgcmVzdC5wb3N0PERpc2NvcmRMb2JieU1lc3NhZ2U+KHJlc3Qucm91dGVzLmxvYmJ5Lm1lc3NhZ2VzKGxvYmJ5SWQpLCB7XG4gICAgICBib2R5OiBvcHRpb25zLFxuICAgICAgaGVhZGVyczoge1xuICAgICAgICBhdXRob3JpemF0aW9uOiBgQmVhcmVyICR7YmVhcmVyVG9rZW59YCxcbiAgICAgIH0sXG4gICAgICB1bmF1dGhvcml6ZWQ6IHRydWUsXG4gICAgfSk7XG4gIH0sXG4gIC8qKlxuICAgKiBSZXR1cm5zIHRoZSBtb3N0IHJlY2VudCBtZXNzYWdlcyBpbiB0aGUgc3BlY2lmaWVkIGxvYmJ5LiBUaGUgY2FsbGluZyB1c2VyIG11c3QgYmUgYSBtZW1iZXIgb2YgdGhlIGxvYmJ5LlxuICAgKlxuICAgKiBAcGFyYW0gYmVhcmVyVG9rZW4gLSBUaGUgYWNjZXNzIHRva2VuIG9mIHRoZSB1c2VyXG4gICAqIEBwYXJhbSBsb2JieUlkIC0gVGhlIElEIG9mIHRoZSBsb2JieSB0byBnZXQgdGhlIG1lc3NhZ2VzIGZyb21cbiAgICogQHBhcmFtIG9wdGlvbnMgLSBUaGUgb3B0aW9ucyB0byBnZXQgdGhlIG1lc3NhZ2VzXG4gICAqIEByZXR1cm5zIFJldHVybnMgYW4gYXJyYXkgb2YgbG9iYnkgbWVzc2FnZSBvYmplY3RzXG4gICAqXG4gICAqIEByZW1hcmtzXG4gICAqIFVzZXMgYEJlYXJlcmAgdG9rZW4gZm9yIGF1dGhvcml6YXRpb24gd2l0aCB0aGUgYHNkay5zb2NpYWxfbGF5ZXJgIHNjb3BlLlxuICAgKi9cbiAgYXN5bmMgZ2V0TG9iYnlNZXNzYWdlcyhyZXN0OiBSZXN0TWFuYWdlciwgYmVhcmVyVG9rZW46IHN0cmluZywgbG9iYnlJZDogQmlnU3RyaW5nLCBvcHRpb25zPzogR2V0TG9iYnlNZXNzYWdlcyk6IFByb21pc2U8RGlzY29yZExvYmJ5TWVzc2FnZVtdPiB7XG4gICAgcmV0dXJuIGF3YWl0IHJlc3QuZ2V0PERpc2NvcmRMb2JieU1lc3NhZ2VbXT4ocmVzdC5yb3V0ZXMubG9iYnkubWVzc2FnZXMobG9iYnlJZCwgb3B0aW9ucyksIHtcbiAgICAgIGhlYWRlcnM6IHtcbiAgICAgICAgYXV0aG9yaXphdGlvbjogYEJlYXJlciAke2JlYXJlclRva2VufWAsXG4gICAgICB9LFxuICAgICAgdW5hdXRob3JpemVkOiB0cnVlLFxuICAgIH0pO1xuICB9LFxuICAvKipcbiAgICogQ3JlYXRlcyBhIHNpbmdsZS11c2UgZ3VpbGQgaW52aXRlIHRvIHRoZSBsb2JieSdzIGxpbmtlZCBjaGFubmVsLCB0YXJnZXRlZCBhdCB0aGUgY2FsbGluZyB1c2VyLlxuICAgKlxuICAgKlxuICAgKiBAcGFyYW0gYmVhcmVyVG9rZW4gLSBUaGUgYWNjZXNzIHRva2VuIG9mIHRoZSB1c2VyXG4gICAqIEBwYXJhbSBsb2JieUlkIC0gVGhlIElEIG9mIHRoZSBsb2JieSB0byBjcmVhdGUgdGhlIGludml0ZSBmb3JcbiAgICogQHJldHVybnMgVGhlIGNyZWF0ZWQgaW52aXRlIG9iamVjdFxuICAgKlxuICAgKiBAcmVtYXJrc1xuICAgKiBVc2VzIGBCZWFyZXJgIHRva2VuIGZvciBhdXRob3JpemF0aW9uIHdpdGggdGhlIGBzZGsuc29jaWFsX2xheWVyYCBzY29wZS5cbiAgICpcbiAgICogVGhlIGxvYmJ5IG11c3QgaGF2ZSBhIGxpbmtlZCBjaGFubmVsIGFuZCB0aGUgY2FsbGVyIG11c3QgYmUgYSBtZW1iZXIgb2YgdGhlIGxvYmJ5LlxuICAgKiBUaGUgaW52aXRlIGV4cGlyZXMgYWZ0ZXIgb25lIGhvdXIuXG4gICAqL1xuICBhc3luYyBjcmVhdGVMb2JieUNoYW5uZWxJbnZpdGVGb3JTZWxmKHJlc3Q6IFJlc3RNYW5hZ2VyLCBiZWFyZXJUb2tlbjogc3RyaW5nLCBsb2JieUlkOiBCaWdTdHJpbmcpOiBQcm9taXNlPERpc2NvcmRMb2JieUludml0ZT4ge1xuICAgIHJldHVybiByZXN0LnBvc3Q8RGlzY29yZExvYmJ5SW52aXRlPihyZXN0LnJvdXRlcy5sb2JieS5pbnZpdGVTZWxmKGxvYmJ5SWQpLCB7XG4gICAgICBoZWFkZXJzOiB7XG4gICAgICAgIGF1dGhvcml6YXRpb246IGBCZWFyZXIgJHtiZWFyZXJUb2tlbn1gLFxuICAgICAgfSxcbiAgICAgIHVuYXV0aG9yaXplZDogdHJ1ZSxcbiAgICB9KTtcbiAgfSxcbiAgLyoqXG4gICAqIENyZWF0ZXMgYSBzaW5nbGUtdXNlIGd1aWxkIGludml0ZSB0byB0aGUgbG9iYnkncyBsaW5rZWQgY2hhbm5lbCBvbiBiZWhhbGYgb2YgYW4gYXBwbGljYXRpb24sIHRhcmdldGVkIGF0IHRoZSBzcGVjaWZpZWQgdXNlci5cbiAgICpcbiAgICogQHBhcmFtIGxvYmJ5SWQgLSBUaGUgSUQgb2YgdGhlIGxvYmJ5IHRvIGNyZWF0ZSB0aGUgaW52aXRlIGZvclxuICAgKiBAcGFyYW0gdXNlcklkIC0gVGhlIElEIG9mIHRoZSB1c2VyIHRvIGNyZWF0ZSB0aGUgaW52aXRlIGZvclxuICAgKiBAcmV0dXJucyBUaGUgY3JlYXRlZCBpbnZpdGUgb2JqZWN0XG4gICAqXG4gICAqIEByZW1hcmtzXG4gICAqIFVzZXMgYEJvdGAgdG9rZW4gZm9yIGF1dGhvcml6YXRpb25cbiAgICpcbiAgICogVGhlIGxvYmJ5IG11c3QgaGF2ZSBhIGxpbmtlZCBjaGFubmVsLlxuICAgKiBUaGUgaW52aXRlIGV4cGlyZXMgYWZ0ZXIgb25lIGhvdXIuXG4gICAqL1xuICBhc3luYyBjcmVhdGVMb2JieUNoYW5uZWxJbnZpdGVGb3JVc2VyKHJlc3Q6IFJlc3RNYW5hZ2VyLCBsb2JieUlkOiBCaWdTdHJpbmcsIHVzZXJJZDogQmlnU3RyaW5nKTogUHJvbWlzZTxEaXNjb3JkTG9iYnlJbnZpdGU+IHtcbiAgICByZXR1cm4gcmVzdC5wb3N0PERpc2NvcmRMb2JieUludml0ZT4ocmVzdC5yb3V0ZXMubG9iYnkuaW52aXRlVXNlcihsb2JieUlkLCB1c2VySWQpKTtcbiAgfSxcbn07XG5cbi8vIFdlIHJlbW92ZSB0aGUgcmVzdCBwYXJhbWV0ZXIgYXMgaXQgc2hvdWxkbid0IGJlIGluIHRoZSBmaW5hbCBmdW5jdGlvbiBzaWduYXR1cmUgYW5kIGlzIGluamVjdGVkIGJ5IHRoZSBSZXN0TWFuYWdlciB3aGVuIGNhbGxpbmcgdGhlIGVuZHBvaW50IGZ1bmN0aW9uLlxuZXhwb3J0IHR5cGUgUmVzdEVuZHBvaW50cyA9IHtcbiAgW0sgaW4ga2V5b2YgdHlwZW9mIHJlc3RFbmRwb2ludHNdOiAodHlwZW9mIHJlc3RFbmRwb2ludHMpW0tdIGV4dGVuZHMgKC4uLmFyZ3M6IFtSZXN0TWFuYWdlciwgLi4uaW5mZXIgQl0pID0+IGluZmVyIFIgPyAoLi4uYXJnczogQikgPT4gUiA6IG5ldmVyO1xufTtcblxuZXhwb3J0IHR5cGUgQ2FtZWxpemVkUmVzdEVuZHBvaW50cyA9IHtcbiAgW0sgaW4ga2V5b2YgUmVzdEVuZHBvaW50c106IFJlc3RFbmRwb2ludHNbS10gZXh0ZW5kcyAoLi4uYXJnczogaW5mZXIgQSkgPT4gUHJvbWlzZTxpbmZlciBSPiA/ICguLi5hcmdzOiBBKSA9PiBQcm9taXNlPENhbWVsaXplPFI+PiA6IG5ldmVyO1xufTtcbiJdLCJuYW1lcyI6WyJCdWZmZXIiLCJwcm9jZXNzUmVhY3Rpb25TdHJpbmciLCJyZXN0RW5kcG9pbnRzIiwiYWRkUmVhY3Rpb24iLCJyZXN0IiwiY2hhbm5lbElkIiwibWVzc2FnZUlkIiwicmVhY3Rpb24iLCJwdXQiLCJyb3V0ZXMiLCJjaGFubmVscyIsInJlYWN0aW9ucyIsImJvdCIsImFkZFJlYWN0aW9ucyIsIm9yZGVyZWQiLCJQcm9taXNlIiwiYWxsIiwibWFwIiwic25ha2UiLCJhZGRSb2xlIiwiZ3VpbGRJZCIsInVzZXJJZCIsInJvbGVJZCIsInJlYXNvbiIsImd1aWxkcyIsInJvbGVzIiwibWVtYmVyIiwiYWRkVGhyZWFkTWVtYmVyIiwidGhyZWFkcyIsInVzZXIiLCJhZGREbVJlY2lwaWVudCIsIm9wdGlvbnMiLCJkbVJlY2lwaWVudCIsImJvZHkiLCJhZGRHdWlsZE1lbWJlciIsIm1lbWJlcnMiLCJjcmVhdGVBdXRvbW9kUnVsZSIsInBvc3QiLCJhdXRvbW9kIiwicnVsZXMiLCJjcmVhdGVDaGFubmVsIiwiY3JlYXRlRW1vamkiLCJlbW9qaXMiLCJjcmVhdGVBcHBsaWNhdGlvbkVtb2ppIiwiYXBwbGljYXRpb25FbW9qaXMiLCJhcHBsaWNhdGlvbklkIiwiY3JlYXRlRm9ydW1UaHJlYWQiLCJmb3J1bSIsImZpbGVzIiwiY3JlYXRlR2xvYmFsQXBwbGljYXRpb25Db21tYW5kIiwiY29tbWFuZCIsInJlc3RPcHRpb25zIiwiYmVhcmVyVG9rZW4iLCJ1bmF1dGhvcml6ZWQiLCJoZWFkZXJzIiwiYXV0aG9yaXphdGlvbiIsImludGVyYWN0aW9ucyIsImNvbW1hbmRzIiwiY3JlYXRlR3VpbGRBcHBsaWNhdGlvbkNvbW1hbmQiLCJjcmVhdGVHdWlsZFN0aWNrZXIiLCJmb3JtIiwiRm9ybURhdGEiLCJhcHBlbmQiLCJmaWxlIiwiYmxvYiIsIm5hbWUiLCJkZXNjcmlwdGlvbiIsInRhZ3MiLCJzdGlja2VycyIsImNyZWF0ZUd1aWxkVGVtcGxhdGUiLCJ0ZW1wbGF0ZXMiLCJjcmVhdGVJbnZpdGUiLCJ0YXJnZXRVc2Vyc0ZpbGUiLCJpbnZpdGVzIiwiSlNPTiIsInN0cmluZ2lmeSIsImNoYW5nZVRvRGlzY29yZEZvcm1hdCIsInVuZGVmaW5lZCIsImdldEd1aWxkUm9sZU1lbWJlckNvdW50cyIsImdldCIsIm1lbWJlckNvdW50cyIsImNyZWF0ZVJvbGUiLCJjcmVhdGVTY2hlZHVsZWRFdmVudCIsImV2ZW50cyIsImNyZWF0ZVN0YWdlSW5zdGFuY2UiLCJzdGFnZXMiLCJjcmVhdGVXZWJob29rIiwid2ViaG9va3MiLCJkZWxldGVBdXRvbW9kUnVsZSIsInJ1bGVJZCIsImRlbGV0ZSIsInJ1bGUiLCJzZXRWb2ljZUNoYW5uZWxTdGF0dXMiLCJ2b2ljZVN0YXR1cyIsImRlbGV0ZUNoYW5uZWwiLCJjaGFubmVsIiwiZGVsZXRlQ2hhbm5lbFBlcm1pc3Npb25PdmVycmlkZSIsIm92ZXJ3cml0ZUlkIiwib3ZlcndyaXRlIiwiZGVsZXRlRW1vamkiLCJpZCIsImVtb2ppIiwiZGVsZXRlQXBwbGljYXRpb25FbW9qaSIsImFwcGxpY2F0aW9uRW1vamkiLCJkZWxldGVGb2xsb3d1cE1lc3NhZ2UiLCJ0b2tlbiIsInJlc3BvbnNlcyIsIm1lc3NhZ2UiLCJkZWxldGVHbG9iYWxBcHBsaWNhdGlvbkNvbW1hbmQiLCJjb21tYW5kSWQiLCJkZWxldGVHdWlsZEFwcGxpY2F0aW9uQ29tbWFuZCIsIm9uZSIsImRlbGV0ZUd1aWxkU3RpY2tlciIsInN0aWNrZXJJZCIsInN0aWNrZXIiLCJkZWxldGVHdWlsZFRlbXBsYXRlIiwidGVtcGxhdGVDb2RlIiwiZ3VpbGQiLCJkZWxldGVJbnRlZ3JhdGlvbiIsImludGVncmF0aW9uSWQiLCJpbnRlZ3JhdGlvbiIsImRlbGV0ZUludml0ZSIsImludml0ZUNvZGUiLCJpbnZpdGUiLCJnZXRUYXJnZXRVc2VycyIsImludml0ZVRhcmdldFVzZXJzIiwidXBkYXRlVGFyZ2V0VXNlcnMiLCJnZXRUYXJnZXRVc2Vyc0pvYlN0YXR1cyIsImludml0ZVRhcmdldFVzZXJzSm9iU3RhdHVzIiwiZGVsZXRlTWVzc2FnZSIsImRlbGV0ZU1lc3NhZ2VzIiwibWVzc2FnZUlkcyIsImJ1bGsiLCJtZXNzYWdlcyIsInNsaWNlIiwidG9TdHJpbmciLCJkZWxldGVPcmlnaW5hbEludGVyYWN0aW9uUmVzcG9uc2UiLCJvcmlnaW5hbCIsImRlbGV0ZU93blJlYWN0aW9uIiwiZGVsZXRlUmVhY3Rpb25zQWxsIiwiZGVsZXRlUmVhY3Rpb25zRW1vamkiLCJkZWxldGVSb2xlIiwiZGVsZXRlU2NoZWR1bGVkRXZlbnQiLCJldmVudElkIiwiZXZlbnQiLCJkZWxldGVTdGFnZUluc3RhbmNlIiwic3RhZ2UiLCJkZWxldGVVc2VyUmVhY3Rpb24iLCJkZWxldGVXZWJob29rIiwid2ViaG9va0lkIiwiZGVsZXRlV2ViaG9va01lc3NhZ2UiLCJkZWxldGVXZWJob29rV2l0aFRva2VuIiwid2ViaG9vayIsImVkaXRBcHBsaWNhdGlvbkNvbW1hbmRQZXJtaXNzaW9ucyIsInBlcm1pc3Npb24iLCJwZXJtaXNzaW9ucyIsImVkaXRBdXRvbW9kUnVsZSIsInBhdGNoIiwiZWRpdEJvdFByb2ZpbGUiLCJjdXJyZW50VXNlciIsImVkaXRDaGFubmVsIiwiZWRpdENoYW5uZWxQZXJtaXNzaW9uT3ZlcnJpZGVzIiwiZWRpdENoYW5uZWxQb3NpdGlvbnMiLCJjaGFubmVsUG9zaXRpb25zIiwiZWRpdEVtb2ppIiwiZWRpdEFwcGxpY2F0aW9uRW1vamkiLCJlZGl0Rm9sbG93dXBNZXNzYWdlIiwiZWRpdEdsb2JhbEFwcGxpY2F0aW9uQ29tbWFuZCIsImVkaXRHdWlsZCIsImVkaXRHdWlsZEFwcGxpY2F0aW9uQ29tbWFuZCIsImVkaXRHdWlsZFN0aWNrZXIiLCJlZGl0R3VpbGRUZW1wbGF0ZSIsImVkaXRNZXNzYWdlIiwiZWRpdE9yaWdpbmFsSW50ZXJhY3Rpb25SZXNwb25zZSIsImVkaXRPd25Wb2ljZVN0YXRlIiwidm9pY2UiLCJyZXF1ZXN0VG9TcGVha1RpbWVzdGFtcCIsIkRhdGUiLCJ0b0lTT1N0cmluZyIsImVkaXRSb2xlIiwiZWRpdFJvbGVQb3NpdGlvbnMiLCJlZGl0U2NoZWR1bGVkRXZlbnQiLCJlZGl0U3RhZ2VJbnN0YW5jZSIsInRvcGljIiwiZWRpdFVzZXJWb2ljZVN0YXRlIiwiZWRpdFVzZXJBcHBsaWNhdGlvblJvbGVDb25uZWN0aW9uIiwib2F1dGgyIiwicm9sZUNvbm5lY3Rpb25zIiwiZGVsZXRlQ3VycmVudFVzZXJBcHBsaWNhdGlvblJvbGVDb25uZWN0aW9uIiwiZWRpdFdlYmhvb2siLCJlZGl0V2ViaG9va01lc3NhZ2UiLCJlZGl0V2ViaG9va1dpdGhUb2tlbiIsImVkaXRXZWxjb21lU2NyZWVuIiwid2VsY29tZSIsImVkaXRXaWRnZXRTZXR0aW5ncyIsIndpZGdldCIsImV4ZWN1dGVXZWJob29rIiwiZm9sbG93QW5ub3VuY2VtZW50Iiwic291cmNlQ2hhbm5lbElkIiwidGFyZ2V0Q2hhbm5lbElkIiwiZm9sbG93Iiwid2ViaG9va0NoYW5uZWxJZCIsImdldEFjdGl2ZVRocmVhZHMiLCJhY3RpdmUiLCJnZXRBcHBsaWNhdGlvbkluZm8iLCJhcHBsaWNhdGlvbiIsImVkaXRBcHBsaWNhdGlvbkluZm8iLCJnZXRDdXJyZW50QXV0aGVudGljYXRpb25JbmZvIiwiY3VycmVudEF1dGhvcml6YXRpb24iLCJleGNoYW5nZVRva2VuIiwiY2xpZW50SWQiLCJjbGllbnRTZWNyZXQiLCJiYXNpY0NyZWRlbnRpYWxzIiwiZnJvbSIsInJ1blRocm91Z2hRdWV1ZSIsImdyYW50VHlwZSIsInNjb3BlIiwiam9pbiIsInRva2VuRXhjaGFuZ2UiLCJyZXZva2VUb2tlbiIsInRva2VuUmV2b2tlIiwiZ2V0QXBwbGljYXRpb25Db21tYW5kUGVybWlzc2lvbiIsImFjY2Vzc1Rva2VuIiwiZ2V0QXBwbGljYXRpb25Db21tYW5kUGVybWlzc2lvbnMiLCJnZXRBdWRpdExvZyIsImF1ZGl0bG9ncyIsImdldEF1dG9tb2RSdWxlIiwiZ2V0QXV0b21vZFJ1bGVzIiwiZ2V0QXZhaWxhYmxlVm9pY2VSZWdpb25zIiwicmVnaW9ucyIsImdldEJhbiIsImJhbiIsImdldEJhbnMiLCJiYW5zIiwiZ2V0Q2hhbm5lbCIsImdldENoYW5uZWxJbnZpdGVzIiwiZ2V0Q2hhbm5lbHMiLCJnZXRDaGFubmVsV2ViaG9va3MiLCJnZXREbUNoYW5uZWwiLCJkbSIsInJlY2lwaWVudElkIiwiZ2V0R3JvdXBEbUNoYW5uZWwiLCJnZXRFbW9qaSIsImVtb2ppSWQiLCJnZXRBcHBsaWNhdGlvbkVtb2ppIiwiZ2V0RW1vamlzIiwiZ2V0QXBwbGljYXRpb25FbW9qaXMiLCJnZXRGb2xsb3d1cE1lc3NhZ2UiLCJnZXRHYXRld2F5Qm90IiwiZ2F0ZXdheUJvdCIsImdldEdsb2JhbEFwcGxpY2F0aW9uQ29tbWFuZCIsImdldEdsb2JhbEFwcGxpY2F0aW9uQ29tbWFuZHMiLCJ3aXRoTG9jYWxpemF0aW9ucyIsImdldEd1aWxkIiwiY291bnRzIiwiZ2V0R3VpbGRzIiwibWFrZVJlcXVlc3RPcHRpb25zIiwidXNlckd1aWxkcyIsImdldEd1aWxkQXBwbGljYXRpb25Db21tYW5kIiwiZ2V0R3VpbGRBcHBsaWNhdGlvbkNvbW1hbmRzIiwiZ2V0R3VpbGRQcmV2aWV3IiwicHJldmlldyIsImdldEd1aWxkU3RpY2tlciIsImdldEd1aWxkU3RpY2tlcnMiLCJnZXRHdWlsZFRlbXBsYXRlIiwiY29kZSIsImdldEd1aWxkVGVtcGxhdGVzIiwiZ2V0R3VpbGRXZWJob29rcyIsImdldEludGVncmF0aW9ucyIsImludGVncmF0aW9ucyIsImdldEludml0ZSIsImdldEludml0ZXMiLCJnZXRNZXNzYWdlIiwiZ2V0TWVzc2FnZXMiLCJzZWFyY2hHdWlsZE1lc3NhZ2VzIiwibWVzc2FnZXNTZWFyY2giLCJnZXRTdGlja2VyUGFjayIsInN0aWNrZXJQYWNrSWQiLCJzdGlja2VyUGFjayIsImdldFN0aWNrZXJQYWNrcyIsInN0aWNrZXJQYWNrcyIsImdldE9yaWdpbmFsSW50ZXJhY3Rpb25SZXNwb25zZSIsImdldENoYW5uZWxQaW5zIiwibWVzc2FnZVBpbnMiLCJnZXRQaW5uZWRNZXNzYWdlcyIsInBpbnMiLCJnZXRQcml2YXRlQXJjaGl2ZWRUaHJlYWRzIiwicHJpdmF0ZSIsImdldFByaXZhdGVKb2luZWRBcmNoaXZlZFRocmVhZHMiLCJqb2luZWQiLCJnZXRQcnVuZUNvdW50IiwicHJ1bmUiLCJnZXRQdWJsaWNBcmNoaXZlZFRocmVhZHMiLCJwdWJsaWMiLCJnZXRSb2xlcyIsImdldFJvbGUiLCJnZXRTY2hlZHVsZWRFdmVudCIsIndpdGhVc2VyQ291bnQiLCJnZXRTY2hlZHVsZWRFdmVudHMiLCJnZXRTY2hlZHVsZWRFdmVudFVzZXJzIiwidXNlcnMiLCJnZXRTZXNzaW9uSW5mbyIsImdldFN0YWdlSW5zdGFuY2UiLCJnZXRPd25Wb2ljZVN0YXRlIiwiZ2V0VXNlclZvaWNlU3RhdGUiLCJnZXRTdGlja2VyIiwiZ2V0VGhyZWFkTWVtYmVyIiwiZ2V0VXNlciIsImdldFRocmVhZE1lbWJlcnMiLCJnZXRSZWFjdGlvbnMiLCJnZXRDdXJyZW50VXNlciIsImdldFVzZXJDb25uZWN0aW9ucyIsImNvbm5lY3Rpb25zIiwiZ2V0VXNlckFwcGxpY2F0aW9uUm9sZUNvbm5lY3Rpb24iLCJnZXRWYW5pdHlVcmwiLCJ2YW5pdHkiLCJnZXRWb2ljZVJlZ2lvbnMiLCJnZXRXZWJob29rIiwiZ2V0V2ViaG9va01lc3NhZ2UiLCJnZXRXZWJob29rV2l0aFRva2VuIiwiZ2V0V2VsY29tZVNjcmVlbiIsImdldFdpZGdldCIsIndpZGdldEpzb24iLCJnZXRXaWRnZXRTZXR0aW5ncyIsImpvaW5UaHJlYWQiLCJtZSIsImxlYXZlR3VpbGQiLCJsZWF2ZSIsImxlYXZlVGhyZWFkIiwicHVibGlzaE1lc3NhZ2UiLCJjcm9zc3Bvc3QiLCJyZW1vdmVSb2xlIiwicmVtb3ZlVGhyZWFkTWVtYmVyIiwicmVtb3ZlRG1SZWNpcGllbnQiLCJzZW5kTWVzc2FnZSIsInNlbmRGb2xsb3d1cE1lc3NhZ2UiLCJzZW5kSW50ZXJhY3Rpb25SZXNwb25zZSIsImludGVyYWN0aW9uSWQiLCJwYXJhbXMiLCJjYWxsYmFjayIsImRhdGEiLCJzdGFydFRocmVhZFdpdGhNZXNzYWdlIiwic3RhcnRUaHJlYWRXaXRob3V0TWVzc2FnZSIsImdldFBvbGxBbnN3ZXJWb3RlcnMiLCJhbnN3ZXJJZCIsInBvbGxzIiwidm90ZXMiLCJlbmRQb2xsIiwiZXhwaXJlIiwic3luY0d1aWxkVGVtcGxhdGUiLCJ0cmlnZ2VyVHlwaW5nSW5kaWNhdG9yIiwidHlwaW5nIiwidXBzZXJ0R2xvYmFsQXBwbGljYXRpb25Db21tYW5kcyIsInVwc2VydEd1aWxkQXBwbGljYXRpb25Db21tYW5kcyIsImJhbk1lbWJlciIsImJ1bGtCYW5NZW1iZXJzIiwiYnVsa0JhbiIsImVkaXRDdXJyZW50TWVtYmVyIiwiZWRpdE1lbWJlciIsImdldEN1cnJlbnRNZW1iZXIiLCJjdXJyZW50TWVtYmVyIiwiZ2V0TWVtYmVyIiwiZ2V0TWVtYmVycyIsImdldEFwcGxpY2F0aW9uQWN0aXZpdHlJbnN0YW5jZSIsImluc3RhbmNlSWQiLCJhcHBsaWNhdGlvbkFjdGl2aXR5SW5zdGFuY2UiLCJraWNrTWVtYmVyIiwicGluTWVzc2FnZSIsIm1lc3NhZ2VQaW4iLCJwcnVuZU1lbWJlcnMiLCJzZWFyY2hNZW1iZXJzIiwicXVlcnkiLCJzZWFyY2giLCJ1bmJhbk1lbWJlciIsInVucGluTWVzc2FnZSIsImdldEd1aWxkT25ib2FyZGluZyIsIm9uYm9hcmRpbmciLCJlZGl0R3VpbGRPbmJvYXJkaW5nIiwibW9kaWZ5R3VpbGRJbmNpZGVudEFjdGlvbnMiLCJpbmNpZGVudEFjdGlvbnMiLCJsaXN0RW50aXRsZW1lbnRzIiwibW9uZXRpemF0aW9uIiwiZW50aXRsZW1lbnRzIiwiZ2V0RW50aXRsZW1lbnQiLCJlbnRpdGxlbWVudElkIiwiZW50aXRsZW1lbnQiLCJjcmVhdGVUZXN0RW50aXRsZW1lbnQiLCJkZWxldGVUZXN0RW50aXRsZW1lbnQiLCJjb25zdW1lRW50aXRsZW1lbnQiLCJsaXN0U2t1cyIsInNrdXMiLCJsaXN0U3Vic2NyaXB0aW9ucyIsInNrdUlkIiwic3Vic2NyaXB0aW9ucyIsImdldFN1YnNjcmlwdGlvbiIsInN1YnNjcmlwdGlvbklkIiwic3Vic2NyaXB0aW9uIiwic2VuZFNvdW5kYm9hcmRTb3VuZCIsInNvdW5kYm9hcmQiLCJzZW5kU291bmQiLCJsaXN0RGVmYXVsdFNvdW5kYm9hcmRTb3VuZHMiLCJsaXN0RGVmYXVsdCIsImxpc3RHdWlsZFNvdW5kYm9hcmRTb3VuZHMiLCJndWlsZFNvdW5kcyIsImdldEd1aWxkU291bmRib2FyZFNvdW5kIiwic291bmRJZCIsImd1aWxkU291bmQiLCJjcmVhdGVHdWlsZFNvdW5kYm9hcmRTb3VuZCIsIm1vZGlmeUd1aWxkU291bmRib2FyZFNvdW5kIiwiZGVsZXRlR3VpbGRTb3VuZGJvYXJkU291bmQiLCJsaXN0QXBwbGljYXRpb25Sb2xlQ29ubmVjdGlvbnNNZXRhZGF0YVJlY29yZHMiLCJhcHBsaWNhdGlvblJvbGVDb25uZWN0aW9uTWV0YWRhdGEiLCJ1cGRhdGVBcHBsaWNhdGlvblJvbGVDb25uZWN0aW9uc01ldGFkYXRhUmVjb3JkcyIsImNyZWF0ZUxvYmJ5IiwibG9iYnkiLCJjcmVhdGUiLCJjcmVhdGVPckpvaW5Mb2JieSIsImdldExvYmJ5IiwibG9iYnlJZCIsIm1vZGlmeUxvYmJ5IiwiZGVsZXRlTG9iYnkiLCJhZGRNZW1iZXJUb0xvYmJ5IiwiYnVsa1VwZGF0ZUxvYmJ5TWVtYmVycyIsIm1lbWJlcnNCdWxrIiwicmVtb3ZlTWVtYmVyRnJvbUxvYmJ5IiwibGVhdmVMb2JieSIsImxpbmtDaGFubmVsVG9Mb2JieSIsImxpbmsiLCJ1bmxpbmtDaGFubmVsVG9Mb2JieSIsInVwZGF0ZUxvYmJ5TWVzc2FnZU1vZGVyYXRpb25NZXRhZGF0YSIsIm1vZGVyYXRpb25NZXRhZGF0YSIsInNlbmRMb2JieU1lc3NhZ2UiLCJnZXRMb2JieU1lc3NhZ2VzIiwiY3JlYXRlTG9iYnlDaGFubmVsSW52aXRlRm9yU2VsZiIsImludml0ZVNlbGYiLCJjcmVhdGVMb2JieUNoYW5uZWxJbnZpdGVGb3JVc2VyIiwiaW52aXRlVXNlciJdLCJtYXBwaW5ncyI6IkFBQUEsU0FBU0EsTUFBTSxRQUFRLGNBQWM7QUFvS3JDLFNBQVNDLHFCQUFxQixRQUFxQixvQkFBb0I7QUFHdkU7O0NBRUMsR0FDRCxPQUFPLE1BQU1DLGdCQUFnQjtJQUMzQjs7Ozs7Ozs7Ozs7Ozs7Ozs7R0FpQkMsR0FDRCxNQUFNQyxhQUFZQyxJQUFpQixFQUFFQyxTQUFvQixFQUFFQyxTQUFvQixFQUFFQyxRQUFnQjtRQUMvRkEsV0FBV04sc0JBQXNCTTtRQUVqQyxNQUFNSCxLQUFLSSxHQUFHLENBQUNKLEtBQUtLLE1BQU0sQ0FBQ0MsUUFBUSxDQUFDQyxTQUFTLENBQUNDLEdBQUcsQ0FBQ1AsV0FBV0MsV0FBV0M7SUFDMUU7SUFDQTs7Ozs7Ozs7Ozs7Ozs7Ozs7R0FpQkMsR0FDRCxNQUFNTSxjQUFhVCxJQUFpQixFQUFFQyxTQUFvQixFQUFFQyxTQUFvQixFQUFFSyxTQUFtQixFQUFFRyxPQUFpQjtRQUN0SCxJQUFJLENBQUNBLFNBQVM7WUFDWixNQUFNQyxRQUFRQyxHQUFHLENBQ2ZMLFVBQVVNLEdBQUcsQ0FBQyxPQUFPVjtnQkFDbkIsTUFBTUgsS0FBS2MsS0FBSyxDQUFDZixXQUFXLENBQUNFLFdBQVdDLFdBQVdDO1lBQ3JEO1lBRUY7UUFDRjtRQUVBLEtBQUssTUFBTUEsWUFBWUksVUFB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