stream-chat-angular 4.66.1 → 5.0.0-v5.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/assets/version.d.ts +1 -1
- package/{esm2015/assets/version.js → esm2020/assets/version.mjs} +2 -2
- package/esm2020/lib/attachment-configuration.service.mjs +185 -0
- package/esm2020/lib/attachment-list/attachment-list.component.mjs +205 -0
- package/esm2020/lib/attachment-preview-list/attachment-preview-list.component.mjs +45 -0
- package/esm2020/lib/attachment.service.mjs +262 -0
- package/esm2020/lib/avatar/avatar.component.mjs +163 -0
- package/esm2020/lib/avatar-placeholder/avatar-placeholder.component.mjs +74 -0
- package/esm2020/lib/channel/channel.component.mjs +46 -0
- package/esm2020/lib/channel-header/channel-header.component.mjs +79 -0
- package/esm2020/lib/channel-list/channel-list-toggle.service.mjs +72 -0
- package/esm2020/lib/channel-list/channel-list.component.mjs +60 -0
- package/esm2020/lib/channel-preview/channel-preview.component.mjs +155 -0
- package/esm2020/lib/channel.service.mjs +1460 -0
- package/esm2020/lib/chat-client.service.mjs +206 -0
- package/{esm2015/lib/custom-templates.service.js → esm2020/lib/custom-templates.service.mjs} +3 -3
- package/{esm2015/lib/date-parser.service.js → esm2020/lib/date-parser.service.mjs} +3 -3
- package/esm2020/lib/edit-message-form/edit-message-form.component.mjs +83 -0
- package/esm2020/lib/get-channel-display-text.mjs +14 -0
- package/esm2020/lib/get-message-translation.mjs +12 -0
- package/esm2020/lib/icon/icon.component.mjs +21 -0
- package/esm2020/lib/icon-placeholder/icon-placeholder.component.mjs +31 -0
- package/esm2020/lib/loading-indicator/loading-indicator.component.mjs +31 -0
- package/esm2020/lib/loading-indicator-placeholder/loading-indicator-placeholder.component.mjs +38 -0
- package/esm2020/lib/message/message.component.mjs +418 -0
- package/esm2020/lib/message-actions-box/message-actions-box.component.mjs +130 -0
- package/esm2020/lib/message-actions.service.mjs +119 -0
- package/esm2020/lib/message-bounce-prompt/message-bounce-prompt.component.mjs +71 -0
- package/esm2020/lib/message-input/autocomplete-textarea/autocomplete-textarea.component.mjs +262 -0
- package/{esm2015/lib/message-input/emoji-input.service.js → esm2020/lib/message-input/emoji-input.service.mjs} +3 -3
- package/{esm2015/lib/message-input/message-input-config.service.js → esm2020/lib/message-input/message-input-config.service.mjs} +3 -3
- package/esm2020/lib/message-input/message-input.component.mjs +443 -0
- package/{esm2015/lib/message-input/textarea/textarea.component.js → esm2020/lib/message-input/textarea/textarea.component.mjs} +5 -9
- package/esm2020/lib/message-input/textarea.directive.mjs +89 -0
- package/esm2020/lib/message-list/group-styles.mjs +52 -0
- package/{esm2015/lib/message-list/image-load.service.js → esm2020/lib/message-list/image-load.service.mjs} +3 -3
- package/esm2020/lib/message-list/message-list.component.mjs +699 -0
- package/esm2020/lib/message-preview.mjs +21 -0
- package/esm2020/lib/message-reactions/message-reactions.component.mjs +252 -0
- package/{esm2015/lib/message-reactions.service.js → esm2020/lib/message-reactions.service.mjs} +3 -3
- package/{esm2015/lib/message.service.js → esm2020/lib/message.service.mjs} +4 -4
- package/esm2020/lib/modal/modal.component.mjs +69 -0
- package/esm2020/lib/notification/notification.component.mjs +20 -0
- package/esm2020/lib/notification-list/notification-list.component.mjs +37 -0
- package/esm2020/lib/notification.service.mjs +79 -0
- package/esm2020/lib/read-by.mjs +12 -0
- package/{esm2015/lib/stream-autocomplete-textarea.module.js → esm2020/lib/stream-autocomplete-textarea.module.mjs} +6 -6
- package/{esm2015/lib/stream-avatar.module.js → esm2020/lib/stream-avatar.module.mjs} +5 -5
- package/{esm2015/lib/stream-chat.module.js → esm2020/lib/stream-chat.module.mjs} +14 -16
- package/{esm2015/lib/stream-i18n.service.js → esm2020/lib/stream-i18n.service.mjs} +5 -5
- package/{esm2015/lib/stream-textarea.module.js → esm2020/lib/stream-textarea.module.mjs} +6 -6
- package/esm2020/lib/theme.service.mjs +123 -0
- package/esm2020/lib/thread/thread.component.mjs +51 -0
- package/{esm2015/lib/transliteration.service.js → esm2020/lib/transliteration.service.mjs} +3 -3
- package/esm2020/lib/types.mjs +2 -0
- package/esm2020/lib/voice-recording/voice-recording-wavebar/voice-recording-wavebar.component.mjs +183 -0
- package/esm2020/lib/voice-recording/voice-recording.component.mjs +102 -0
- package/fesm2015/{stream-chat-angular.js → stream-chat-angular.mjs} +313 -426
- package/fesm2015/stream-chat-angular.mjs.map +1 -0
- package/fesm2020/stream-chat-angular.mjs +7123 -0
- package/fesm2020/stream-chat-angular.mjs.map +1 -0
- package/lib/attachment-list/attachment-list.component.d.ts +3 -3
- package/lib/attachment-preview-list/attachment-preview-list.component.d.ts +1 -1
- package/lib/attachment.service.d.ts +0 -1
- package/lib/avatar/avatar.component.d.ts +1 -1
- package/lib/avatar-placeholder/avatar-placeholder.component.d.ts +1 -1
- package/lib/channel/channel.component.d.ts +1 -1
- package/lib/channel-header/channel-header.component.d.ts +1 -1
- package/lib/channel-list/channel-list-toggle.service.d.ts +0 -1
- package/lib/channel-list/channel-list.component.d.ts +1 -1
- package/lib/channel-preview/channel-preview.component.d.ts +1 -1
- package/lib/channel.service.d.ts +7 -7
- package/lib/chat-client.service.d.ts +1 -1
- package/lib/edit-message-form/edit-message-form.component.d.ts +1 -1
- package/lib/get-message-translation.d.ts +1 -1
- package/lib/icon/icon.component.d.ts +1 -1
- package/lib/icon-placeholder/icon-placeholder.component.d.ts +1 -1
- package/lib/loading-indicator/loading-indicator.component.d.ts +1 -1
- package/lib/loading-indicator-placeholder/loading-indicator-placeholder.component.d.ts +1 -1
- package/lib/message/message.component.d.ts +3 -7
- package/lib/message-actions-box/message-actions-box.component.d.ts +2 -4
- package/lib/message-actions.service.d.ts +0 -1
- package/lib/message-bounce-prompt/message-bounce-prompt.component.d.ts +1 -1
- package/lib/message-input/autocomplete-textarea/autocomplete-textarea.component.d.ts +1 -1
- package/lib/message-input/message-input.component.d.ts +2 -2
- package/lib/message-input/textarea/textarea.component.d.ts +1 -1
- package/lib/message-input/textarea.directive.d.ts +1 -1
- package/lib/message-list/group-styles.d.ts +1 -1
- package/lib/message-list/message-list.component.d.ts +4 -5
- package/lib/message-reactions/message-reactions.component.d.ts +1 -4
- package/lib/message.service.d.ts +0 -1
- package/lib/modal/modal.component.d.ts +1 -1
- package/lib/notification/notification.component.d.ts +1 -1
- package/lib/notification-list/notification-list.component.d.ts +2 -2
- package/lib/notification.service.d.ts +2 -5
- package/lib/stream-chat.module.d.ts +3 -3
- package/lib/theme.service.d.ts +1 -2
- package/lib/thread/thread.component.d.ts +1 -1
- package/lib/types.d.ts +18 -18
- package/lib/voice-recording/voice-recording-wavebar/voice-recording-wavebar.component.d.ts +2 -2
- package/lib/voice-recording/voice-recording.component.d.ts +1 -1
- package/package.json +31 -17
- package/src/assets/styles/v2/css/index.css +1 -1
- package/src/assets/styles/v2/css/index.layout.css +1 -1
- package/src/assets/styles/v2/scss/_base.scss +2 -2
- package/src/assets/version.ts +1 -1
- package/bundles/stream-chat-angular.umd.js +0 -8445
- package/bundles/stream-chat-angular.umd.js.map +0 -1
- package/esm2015/lib/attachment-configuration.service.js +0 -186
- package/esm2015/lib/attachment-list/attachment-list.component.js +0 -209
- package/esm2015/lib/attachment-preview-list/attachment-preview-list.component.js +0 -49
- package/esm2015/lib/attachment.service.js +0 -276
- package/esm2015/lib/avatar/avatar.component.js +0 -172
- package/esm2015/lib/avatar-placeholder/avatar-placeholder.component.js +0 -78
- package/esm2015/lib/channel/channel.component.js +0 -50
- package/esm2015/lib/channel-header/channel-header.component.js +0 -86
- package/esm2015/lib/channel-list/channel-list-toggle.service.js +0 -73
- package/esm2015/lib/channel-list/channel-list.component.js +0 -67
- package/esm2015/lib/channel-preview/channel-preview.component.js +0 -167
- package/esm2015/lib/channel.service.js +0 -1487
- package/esm2015/lib/chat-client.service.js +0 -211
- package/esm2015/lib/edit-message-form/edit-message-form.component.js +0 -87
- package/esm2015/lib/get-channel-display-text.js +0 -15
- package/esm2015/lib/get-message-translation.js +0 -13
- package/esm2015/lib/icon/icon.component.js +0 -25
- package/esm2015/lib/icon-placeholder/icon-placeholder.component.js +0 -35
- package/esm2015/lib/loading-indicator/loading-indicator.component.js +0 -35
- package/esm2015/lib/loading-indicator-placeholder/loading-indicator-placeholder.component.js +0 -42
- package/esm2015/lib/message/message.component.js +0 -436
- package/esm2015/lib/message-actions-box/message-actions-box.component.js +0 -137
- package/esm2015/lib/message-actions.service.js +0 -114
- package/esm2015/lib/message-bounce-prompt/message-bounce-prompt.component.js +0 -80
- package/esm2015/lib/message-input/autocomplete-textarea/autocomplete-textarea.component.js +0 -262
- package/esm2015/lib/message-input/message-input.component.js +0 -455
- package/esm2015/lib/message-input/textarea.directive.js +0 -90
- package/esm2015/lib/message-list/group-styles.js +0 -53
- package/esm2015/lib/message-list/message-list.component.js +0 -726
- package/esm2015/lib/message-preview.js +0 -7
- package/esm2015/lib/message-reactions/message-reactions.component.js +0 -266
- package/esm2015/lib/modal/modal.component.js +0 -74
- package/esm2015/lib/notification/notification.component.js +0 -24
- package/esm2015/lib/notification-list/notification-list.component.js +0 -38
- package/esm2015/lib/notification.service.js +0 -79
- package/esm2015/lib/read-by.js +0 -13
- package/esm2015/lib/theme.service.js +0 -122
- package/esm2015/lib/thread/thread.component.js +0 -55
- package/esm2015/lib/types.js +0 -2
- package/esm2015/lib/voice-recording/voice-recording-wavebar/voice-recording-wavebar.component.js +0 -192
- package/esm2015/lib/voice-recording/voice-recording.component.js +0 -115
- package/fesm2015/stream-chat-angular.js.map +0 -1
- /package/{esm2015/assets/i18n/en.js → esm2020/assets/i18n/en.mjs} +0 -0
- /package/{esm2015/lib/injection-tokens.js → esm2020/lib/injection-tokens.mjs} +0 -0
- /package/{esm2015/lib/is-image-attachment.js → esm2020/lib/is-image-attachment.mjs} +0 -0
- /package/{esm2015/lib/is-image-file.js → esm2020/lib/is-image-file.mjs} +0 -0
- /package/{esm2015/lib/is-on-separate-date.js → esm2020/lib/is-on-separate-date.mjs} +0 -0
- /package/{esm2015/lib/list-users.js → esm2020/lib/list-users.mjs} +0 -0
- /package/{esm2015/lib/message-input/textarea.interface.js → esm2020/lib/message-input/textarea.interface.mjs} +0 -0
- /package/{esm2015/lib/parse-date.js → esm2020/lib/parse-date.mjs} +0 -0
- /package/{esm2015/public-api.js → esm2020/public-api.mjs} +0 -0
- /package/{esm2015/stream-chat-angular.js → esm2020/stream-chat-angular.mjs} +0 -0
- /package/{stream-chat-angular.d.ts → index.d.ts} +0 -0
|
@@ -1,1487 +0,0 @@
|
|
|
1
|
-
import { __awaiter } from "tslib";
|
|
2
|
-
import { Injectable } from '@angular/core';
|
|
3
|
-
import { BehaviorSubject, combineLatest, ReplaySubject, } from 'rxjs';
|
|
4
|
-
import { filter, first, map, shareReplay, take } from 'rxjs/operators';
|
|
5
|
-
import { getMessageTranslation } from './get-message-translation';
|
|
6
|
-
import { createMessagePreview } from './message-preview';
|
|
7
|
-
import { getReadBy } from './read-by';
|
|
8
|
-
import * as i0 from "@angular/core";
|
|
9
|
-
import * as i1 from "./chat-client.service";
|
|
10
|
-
import * as i2 from "./notification.service";
|
|
11
|
-
/**
|
|
12
|
-
* The `ChannelService` provides data and interaction for the channel list and message list.
|
|
13
|
-
*/
|
|
14
|
-
export class ChannelService {
|
|
15
|
-
constructor(chatClientService, ngZone, notificationService) {
|
|
16
|
-
this.chatClientService = chatClientService;
|
|
17
|
-
this.ngZone = ngZone;
|
|
18
|
-
this.notificationService = notificationService;
|
|
19
|
-
this.channelsSubject = new BehaviorSubject(undefined);
|
|
20
|
-
this.activeChannelSubject = new BehaviorSubject(undefined);
|
|
21
|
-
this.activeChannelMessagesSubject = new BehaviorSubject([]);
|
|
22
|
-
this.activeChannelPinnedMessagesSubject = new BehaviorSubject([]);
|
|
23
|
-
this.hasMoreChannelsSubject = new ReplaySubject(1);
|
|
24
|
-
this.activeChannelSubscriptions = [];
|
|
25
|
-
this.channelSubscriptions = {};
|
|
26
|
-
this.activeParentMessageIdSubject = new BehaviorSubject(undefined);
|
|
27
|
-
this.activeThreadMessagesSubject = new BehaviorSubject([]);
|
|
28
|
-
this.jumpToMessageSubject = new BehaviorSubject({ id: undefined, parentId: undefined });
|
|
29
|
-
this.latestMessageDateByUserByChannelsSubject = new BehaviorSubject({});
|
|
30
|
-
this.messagePageSize = 25;
|
|
31
|
-
this.messageToQuoteSubject = new BehaviorSubject(undefined);
|
|
32
|
-
this.usersTypingInChannelSubject = new BehaviorSubject([]);
|
|
33
|
-
this.usersTypingInThreadSubject = new BehaviorSubject([]);
|
|
34
|
-
this._shouldMarkActiveChannelAsRead = true;
|
|
35
|
-
this.isStateRecoveryInProgress = false;
|
|
36
|
-
this.channelQueryStateSubject = new BehaviorSubject(undefined);
|
|
37
|
-
this.channelListSetter = (channels, shouldStopWatchingRemovedChannels = true) => {
|
|
38
|
-
const currentChannels = this.channelsSubject.getValue() || [];
|
|
39
|
-
const newChannels = channels.filter((c) => !currentChannels.find((channel) => channel.cid === c.cid));
|
|
40
|
-
const deletedChannels = currentChannels.filter((c) => !(channels === null || channels === void 0 ? void 0 : channels.find((channel) => channel.cid === c.cid)));
|
|
41
|
-
void this.addChannelsFromNotification(newChannels);
|
|
42
|
-
this.removeChannelsFromChannelList(deletedChannels.map((c) => c.cid), shouldStopWatchingRemovedChannels);
|
|
43
|
-
};
|
|
44
|
-
this.messageListSetter = (messages) => {
|
|
45
|
-
this.activeChannelMessagesSubject.next(messages);
|
|
46
|
-
};
|
|
47
|
-
this.threadListSetter = (messages) => {
|
|
48
|
-
this.activeThreadMessagesSubject.next(messages);
|
|
49
|
-
};
|
|
50
|
-
this.parentMessageSetter = (message) => {
|
|
51
|
-
this.activeParentMessageIdSubject.next(message === null || message === void 0 ? void 0 : message.id);
|
|
52
|
-
};
|
|
53
|
-
this.areReadEventsPaused = false;
|
|
54
|
-
this.channels$ = this.channelsSubject.asObservable().pipe(shareReplay(1));
|
|
55
|
-
this.activeChannel$ = this.activeChannelSubject
|
|
56
|
-
.asObservable()
|
|
57
|
-
.pipe(shareReplay(1));
|
|
58
|
-
this.activeChannelMessages$ = this.activeChannelMessagesSubject.pipe(map((messages) => {
|
|
59
|
-
const channel = this.activeChannelSubject.getValue();
|
|
60
|
-
return messages.map((message) => this.transformToStreamMessage(message, channel));
|
|
61
|
-
}), shareReplay(1));
|
|
62
|
-
this.bouncedMessage$ = new BehaviorSubject(undefined);
|
|
63
|
-
this.hasMoreChannels$ = this.hasMoreChannelsSubject
|
|
64
|
-
.asObservable()
|
|
65
|
-
.pipe(shareReplay(1));
|
|
66
|
-
this.activeParentMessageId$ = this.activeParentMessageIdSubject
|
|
67
|
-
.asObservable()
|
|
68
|
-
.pipe(shareReplay(1));
|
|
69
|
-
this.activeThreadMessages$ = this.activeThreadMessagesSubject.pipe(map((messages) => {
|
|
70
|
-
const channel = this.activeChannelSubject.getValue();
|
|
71
|
-
return messages.map((message) => this.transformToStreamMessage(message, channel));
|
|
72
|
-
}), shareReplay(1));
|
|
73
|
-
this.activeParentMessage$ = combineLatest([
|
|
74
|
-
this.activeChannelMessages$,
|
|
75
|
-
this.activeParentMessageId$,
|
|
76
|
-
]).pipe(map(([messages, parentMessageId]) => {
|
|
77
|
-
if (!parentMessageId) {
|
|
78
|
-
return undefined;
|
|
79
|
-
}
|
|
80
|
-
else {
|
|
81
|
-
const message = messages.find((m) => m.id === parentMessageId);
|
|
82
|
-
if (!message) {
|
|
83
|
-
void this.setAsActiveParentMessage(undefined);
|
|
84
|
-
return undefined;
|
|
85
|
-
}
|
|
86
|
-
else {
|
|
87
|
-
return message;
|
|
88
|
-
}
|
|
89
|
-
}
|
|
90
|
-
}), shareReplay(1));
|
|
91
|
-
this.messageToQuote$ = this.messageToQuoteSubject
|
|
92
|
-
.asObservable()
|
|
93
|
-
.pipe(shareReplay(1));
|
|
94
|
-
this.jumpToMessage$ = this.jumpToMessageSubject
|
|
95
|
-
.asObservable()
|
|
96
|
-
.pipe(shareReplay(1));
|
|
97
|
-
this.usersTypingInChannel$ = this.usersTypingInChannelSubject
|
|
98
|
-
.asObservable()
|
|
99
|
-
.pipe(shareReplay(1));
|
|
100
|
-
this.usersTypingInThread$ = this.usersTypingInThreadSubject
|
|
101
|
-
.asObservable()
|
|
102
|
-
.pipe(shareReplay(1));
|
|
103
|
-
this.latestMessageDateByUserByChannels$ =
|
|
104
|
-
this.latestMessageDateByUserByChannelsSubject
|
|
105
|
-
.asObservable()
|
|
106
|
-
.pipe(shareReplay(1));
|
|
107
|
-
this.activeChannelPinnedMessages$ = this.activeChannelPinnedMessagesSubject
|
|
108
|
-
.asObservable()
|
|
109
|
-
.pipe(shareReplay(1));
|
|
110
|
-
this.channelQueryState$ = this.channelQueryStateSubject
|
|
111
|
-
.asObservable()
|
|
112
|
-
.pipe(shareReplay(1));
|
|
113
|
-
}
|
|
114
|
-
/**
|
|
115
|
-
* If set to false, read events won't be sent as new messages are received. If set to true active channel (if any) will immediately be marked as read.
|
|
116
|
-
*/
|
|
117
|
-
get shouldMarkActiveChannelAsRead() {
|
|
118
|
-
return this._shouldMarkActiveChannelAsRead;
|
|
119
|
-
}
|
|
120
|
-
/**
|
|
121
|
-
* If set to false, read events won't be sent as new messages are received. If set to true active channel (if any) will immediately be marked as read.
|
|
122
|
-
*/
|
|
123
|
-
set shouldMarkActiveChannelAsRead(shouldMarkActiveChannelAsRead) {
|
|
124
|
-
if (!this._shouldMarkActiveChannelAsRead && shouldMarkActiveChannelAsRead) {
|
|
125
|
-
const activeChannel = this.activeChannelSubject.getValue();
|
|
126
|
-
if (activeChannel && this.canSendReadEvents) {
|
|
127
|
-
void activeChannel.markRead();
|
|
128
|
-
}
|
|
129
|
-
}
|
|
130
|
-
this._shouldMarkActiveChannelAsRead = shouldMarkActiveChannelAsRead;
|
|
131
|
-
}
|
|
132
|
-
/**
|
|
133
|
-
* Sets the given `channel` as active and marks it as read.
|
|
134
|
-
* If the channel wasn't previously part of the channel, it will be added to the beginning of the list.
|
|
135
|
-
*
|
|
136
|
-
* @param channel
|
|
137
|
-
*/
|
|
138
|
-
setAsActiveChannel(channel) {
|
|
139
|
-
var _a, _b;
|
|
140
|
-
const prevActiveChannel = this.activeChannelSubject.getValue();
|
|
141
|
-
if ((prevActiveChannel === null || prevActiveChannel === void 0 ? void 0 : prevActiveChannel.cid) === channel.cid) {
|
|
142
|
-
return;
|
|
143
|
-
}
|
|
144
|
-
this.stopWatchForActiveChannelEvents(prevActiveChannel);
|
|
145
|
-
this.areReadEventsPaused = false;
|
|
146
|
-
const readState = channel.state.read[((_a = this.chatClientService.chatClient.user) === null || _a === void 0 ? void 0 : _a.id) || ''];
|
|
147
|
-
this.activeChannelLastReadMessageId = readState === null || readState === void 0 ? void 0 : readState.last_read_message_id;
|
|
148
|
-
if (((_b = channel.state.latestMessages[channel.state.latestMessages.length - 1]) === null || _b === void 0 ? void 0 : _b.id) === this.activeChannelLastReadMessageId) {
|
|
149
|
-
this.activeChannelLastReadMessageId = undefined;
|
|
150
|
-
}
|
|
151
|
-
this.activeChannelUnreadCount = (readState === null || readState === void 0 ? void 0 : readState.unread_messages) || 0;
|
|
152
|
-
this.watchForActiveChannelEvents(channel);
|
|
153
|
-
this.addChannel(channel);
|
|
154
|
-
this.activeChannelSubject.next(channel);
|
|
155
|
-
const channelStateLength = channel.state.latestMessages.length;
|
|
156
|
-
if (channelStateLength > 2 * this.messagePageSize) {
|
|
157
|
-
channel.state.latestMessages = channel.state.latestMessages.slice(channelStateLength - 2 * this.messagePageSize);
|
|
158
|
-
}
|
|
159
|
-
this.setChannelState(channel);
|
|
160
|
-
}
|
|
161
|
-
/**
|
|
162
|
-
* Deselects the currently active (if any) channel
|
|
163
|
-
*/
|
|
164
|
-
deselectActiveChannel() {
|
|
165
|
-
const activeChannel = this.activeChannelSubject.getValue();
|
|
166
|
-
if (!activeChannel) {
|
|
167
|
-
return;
|
|
168
|
-
}
|
|
169
|
-
this.stopWatchForActiveChannelEvents(activeChannel);
|
|
170
|
-
this.activeChannelMessagesSubject.next([]);
|
|
171
|
-
this.activeChannelSubject.next(undefined);
|
|
172
|
-
this.activeParentMessageIdSubject.next(undefined);
|
|
173
|
-
this.activeThreadMessagesSubject.next([]);
|
|
174
|
-
this.latestMessageDateByUserByChannelsSubject.next({});
|
|
175
|
-
this.selectMessageToQuote(undefined);
|
|
176
|
-
this.jumpToMessageSubject.next({ id: undefined, parentId: undefined });
|
|
177
|
-
this.activeChannelPinnedMessagesSubject.next([]);
|
|
178
|
-
this.usersTypingInChannelSubject.next([]);
|
|
179
|
-
this.usersTypingInThreadSubject.next([]);
|
|
180
|
-
this.activeChannelLastReadMessageId = undefined;
|
|
181
|
-
this.activeChannelUnreadCount = undefined;
|
|
182
|
-
this.areReadEventsPaused = false;
|
|
183
|
-
}
|
|
184
|
-
/**
|
|
185
|
-
* Sets the given `message` as an active parent message. If `undefined` is provided, it will deleselect the current parent message.
|
|
186
|
-
* @param message
|
|
187
|
-
* @param loadMessagesForm
|
|
188
|
-
*/
|
|
189
|
-
setAsActiveParentMessage(message, loadMessagesForm = 'request') {
|
|
190
|
-
var _a;
|
|
191
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
192
|
-
const messageToQuote = this.messageToQuoteSubject.getValue();
|
|
193
|
-
if (messageToQuote && !!messageToQuote.parent_id) {
|
|
194
|
-
this.messageToQuoteSubject.next(undefined);
|
|
195
|
-
}
|
|
196
|
-
if (!message) {
|
|
197
|
-
this.activeParentMessageIdSubject.next(undefined);
|
|
198
|
-
this.activeThreadMessagesSubject.next([]);
|
|
199
|
-
const messageToJumpTo = this.jumpToMessageSubject.getValue();
|
|
200
|
-
if (messageToJumpTo && !!messageToJumpTo.parentId) {
|
|
201
|
-
this.jumpToMessageSubject.next({ id: undefined, parentId: undefined });
|
|
202
|
-
}
|
|
203
|
-
}
|
|
204
|
-
else {
|
|
205
|
-
this.activeParentMessageIdSubject.next(message.id);
|
|
206
|
-
const activeChannel = this.activeChannelSubject.getValue();
|
|
207
|
-
if (loadMessagesForm === 'request') {
|
|
208
|
-
const result = yield (activeChannel === null || activeChannel === void 0 ? void 0 : activeChannel.getReplies(message.id, {
|
|
209
|
-
limit: (_a = this.options) === null || _a === void 0 ? void 0 : _a.message_limit,
|
|
210
|
-
}));
|
|
211
|
-
this.activeThreadMessagesSubject.next((result === null || result === void 0 ? void 0 : result.messages) || []);
|
|
212
|
-
}
|
|
213
|
-
else {
|
|
214
|
-
this.activeThreadMessagesSubject.next((activeChannel === null || activeChannel === void 0 ? void 0 : activeChannel.state.threads[message.id]) || []);
|
|
215
|
-
}
|
|
216
|
-
}
|
|
217
|
-
});
|
|
218
|
-
}
|
|
219
|
-
/**
|
|
220
|
-
* Loads the next page of messages of the active channel. The page size can be set in the [query option](https://getstream.io/chat/docs/javascript/query_channels/?language=javascript#query-options) object.
|
|
221
|
-
* @param direction
|
|
222
|
-
*/
|
|
223
|
-
loadMoreMessages(direction = 'older') {
|
|
224
|
-
var _a, _b, _c, _d;
|
|
225
|
-
const activeChnannel = this.activeChannelSubject.getValue();
|
|
226
|
-
const messages = this.activeChannelMessagesSubject.getValue();
|
|
227
|
-
const lastMessageId = (_a = messages[direction === 'older' ? 0 : messages.length - 1]) === null || _a === void 0 ? void 0 : _a.id;
|
|
228
|
-
if (direction === 'newer' &&
|
|
229
|
-
((_b = activeChnannel === null || activeChnannel === void 0 ? void 0 : activeChnannel.state) === null || _b === void 0 ? void 0 : _b.latestMessages) === ((_c = activeChnannel === null || activeChnannel === void 0 ? void 0 : activeChnannel.state) === null || _c === void 0 ? void 0 : _c.messages)) {
|
|
230
|
-
// If we are on latest message set, activeChannelMessages$ will be refreshed by WS events, no need for a request
|
|
231
|
-
return false;
|
|
232
|
-
}
|
|
233
|
-
return activeChnannel === null || activeChnannel === void 0 ? void 0 : activeChnannel.query({
|
|
234
|
-
messages: {
|
|
235
|
-
limit: (_d = this.options) === null || _d === void 0 ? void 0 : _d.message_limit,
|
|
236
|
-
[direction === 'older' ? 'id_lt' : 'id_gt']: lastMessageId,
|
|
237
|
-
},
|
|
238
|
-
members: { limit: 0 },
|
|
239
|
-
watchers: { limit: 0 },
|
|
240
|
-
}).then((res) => {
|
|
241
|
-
var _a, _b, _c;
|
|
242
|
-
if (((_a = activeChnannel === null || activeChnannel === void 0 ? void 0 : activeChnannel.data) === null || _a === void 0 ? void 0 : _a.id) ===
|
|
243
|
-
((_c = (_b = this.activeChannelSubject.getValue()) === null || _b === void 0 ? void 0 : _b.data) === null || _c === void 0 ? void 0 : _c.id)) {
|
|
244
|
-
this.activeChannelMessagesSubject.next([
|
|
245
|
-
...activeChnannel.state.messages,
|
|
246
|
-
]);
|
|
247
|
-
}
|
|
248
|
-
return res;
|
|
249
|
-
});
|
|
250
|
-
}
|
|
251
|
-
/**
|
|
252
|
-
* Loads the next page of messages of the active thread. The page size can be set in the [query option](https://getstream.io/chat/docs/javascript/query_channels/?language=javascript#query-options) object.
|
|
253
|
-
* @param direction
|
|
254
|
-
*/
|
|
255
|
-
loadMoreThreadReplies(direction = 'older') {
|
|
256
|
-
var _a, _b;
|
|
257
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
258
|
-
if (direction === 'newer') {
|
|
259
|
-
// Thread replies aren't broke into different message sets, activeThreadMessages$ will be refreshed by WS events, no need for a request
|
|
260
|
-
return;
|
|
261
|
-
}
|
|
262
|
-
const activeChnannel = this.activeChannelSubject.getValue();
|
|
263
|
-
const parentMessageId = this.activeParentMessageIdSubject.getValue();
|
|
264
|
-
if (!parentMessageId) {
|
|
265
|
-
return;
|
|
266
|
-
}
|
|
267
|
-
const threadMessages = this.activeThreadMessagesSubject.getValue();
|
|
268
|
-
const lastMessageId = (_a = threadMessages[direction === 'older' ? 0 : threadMessages.length - 1]) === null || _a === void 0 ? void 0 : _a.id;
|
|
269
|
-
yield (activeChnannel === null || activeChnannel === void 0 ? void 0 : activeChnannel.getReplies(parentMessageId, {
|
|
270
|
-
limit: (_b = this.options) === null || _b === void 0 ? void 0 : _b.message_limit,
|
|
271
|
-
[direction === 'older' ? 'id_lt' : 'id_gt']: lastMessageId,
|
|
272
|
-
}));
|
|
273
|
-
this.activeThreadMessagesSubject.next((activeChnannel === null || activeChnannel === void 0 ? void 0 : activeChnannel.state.threads[parentMessageId]) || []);
|
|
274
|
-
});
|
|
275
|
-
}
|
|
276
|
-
/**
|
|
277
|
-
* Queries the channels with the given filters, sorts and options. More info about [channel querying](https://getstream.io/chat/docs/javascript/query_channels/?language=javascript) can be found in the platform documentation. By default the first channel in the list will be set as active channel and will be marked as read.
|
|
278
|
-
* @param filters
|
|
279
|
-
* @param sort
|
|
280
|
-
* @param options
|
|
281
|
-
* @param shouldSetActiveChannel Decides if the first channel in the result should be made as an active channel, or no channel should be marked as active
|
|
282
|
-
* @returns the list of channels found by the query
|
|
283
|
-
*/
|
|
284
|
-
init(filters, sort, options, shouldSetActiveChannel = true) {
|
|
285
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
286
|
-
this.filters = filters;
|
|
287
|
-
this.options = Object.assign({ limit: 25, state: true, presence: true, watch: true, message_limit: this.messagePageSize }, options);
|
|
288
|
-
this.sort = sort || { last_message_at: -1 };
|
|
289
|
-
this.shouldSetActiveChannel = shouldSetActiveChannel;
|
|
290
|
-
this.clientEventsSubscription = this.chatClientService.events$.subscribe((notification) => void this.handleNotification(notification));
|
|
291
|
-
try {
|
|
292
|
-
const result = yield this.queryChannels(this.shouldSetActiveChannel);
|
|
293
|
-
return result;
|
|
294
|
-
}
|
|
295
|
-
catch (error) {
|
|
296
|
-
this.dismissErrorNotification =
|
|
297
|
-
this.notificationService.addPermanentNotification('streamChat.Error loading channels', 'error');
|
|
298
|
-
throw error;
|
|
299
|
-
}
|
|
300
|
-
});
|
|
301
|
-
}
|
|
302
|
-
/**
|
|
303
|
-
* Resets the `activeChannel$`, `channels$` and `activeChannelMessages$` Observables. Useful when disconnecting a chat user, use in combination with [`disconnectUser`](./ChatClientService.mdx/#disconnectuser).
|
|
304
|
-
*/
|
|
305
|
-
reset() {
|
|
306
|
-
var _a, _b;
|
|
307
|
-
this.deselectActiveChannel();
|
|
308
|
-
this.channelsSubject.next(undefined);
|
|
309
|
-
this.channelQueryStateSubject.next(undefined);
|
|
310
|
-
(_a = this.clientEventsSubscription) === null || _a === void 0 ? void 0 : _a.unsubscribe();
|
|
311
|
-
(_b = this.dismissErrorNotification) === null || _b === void 0 ? void 0 : _b.call(this);
|
|
312
|
-
this.dismissErrorNotification = undefined;
|
|
313
|
-
Object.keys(this.channelSubscriptions).forEach((cid) => {
|
|
314
|
-
this.channelSubscriptions[cid]();
|
|
315
|
-
});
|
|
316
|
-
this.channelSubscriptions = {};
|
|
317
|
-
this.nextPageConfiguration = undefined;
|
|
318
|
-
}
|
|
319
|
-
/**
|
|
320
|
-
* Loads the next page of channels. The page size can be set in the [query option](https://getstream.io/chat/docs/javascript/query_channels/?language=javascript#query-options) object.
|
|
321
|
-
*/
|
|
322
|
-
loadMoreChannels() {
|
|
323
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
324
|
-
yield this.queryChannels(false);
|
|
325
|
-
});
|
|
326
|
-
}
|
|
327
|
-
/**
|
|
328
|
-
* Adds a reaction to a message.
|
|
329
|
-
* @param messageId The id of the message to add the reaction to
|
|
330
|
-
* @param reactionType The type of the reaction
|
|
331
|
-
* @param customData
|
|
332
|
-
*/
|
|
333
|
-
addReaction(messageId, reactionType, customData) {
|
|
334
|
-
var _a;
|
|
335
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
336
|
-
yield ((_a = this.activeChannelSubject.getValue()) === null || _a === void 0 ? void 0 : _a.sendReaction(messageId, Object.assign({ type: reactionType }, customData)));
|
|
337
|
-
});
|
|
338
|
-
}
|
|
339
|
-
/**
|
|
340
|
-
* Removes a reaction from a message.
|
|
341
|
-
* @param messageId The id of the message to remove the reaction from
|
|
342
|
-
* @param reactionType Thr type of reaction to remove
|
|
343
|
-
*/
|
|
344
|
-
removeReaction(messageId, reactionType) {
|
|
345
|
-
var _a;
|
|
346
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
347
|
-
yield ((_a = this.activeChannelSubject
|
|
348
|
-
.getValue()) === null || _a === void 0 ? void 0 : _a.deleteReaction(messageId, reactionType));
|
|
349
|
-
});
|
|
350
|
-
}
|
|
351
|
-
/**
|
|
352
|
-
* Sends a message to the active channel. The message is immediately added to the message list, if an error occurs and the message can't be sent, the error is indicated in `state` of the message.
|
|
353
|
-
* @param text The text of the message
|
|
354
|
-
* @param attachments The attachments
|
|
355
|
-
* @param mentionedUsers Mentioned users
|
|
356
|
-
* @param parentId Id of the parent message (if sending a thread reply)
|
|
357
|
-
* @param quotedMessageId Id of the message to quote (if sending a quote reply)
|
|
358
|
-
* @param customData
|
|
359
|
-
*/
|
|
360
|
-
sendMessage(text, attachments = [], mentionedUsers = [], parentId = undefined, quotedMessageId = undefined, customData = undefined) {
|
|
361
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
362
|
-
let input = {
|
|
363
|
-
text,
|
|
364
|
-
attachments,
|
|
365
|
-
mentionedUsers,
|
|
366
|
-
parentId,
|
|
367
|
-
quotedMessageId,
|
|
368
|
-
customData,
|
|
369
|
-
};
|
|
370
|
-
if (this.beforeSendMessage) {
|
|
371
|
-
input = yield this.beforeSendMessage(input);
|
|
372
|
-
}
|
|
373
|
-
const preview = createMessagePreview(this.chatClientService.chatClient.user, input.text, input.attachments, input.mentionedUsers, input.parentId, input.quotedMessageId, input.customData);
|
|
374
|
-
const channel = this.activeChannelSubject.getValue();
|
|
375
|
-
preview.readBy = [];
|
|
376
|
-
channel.state.addMessageSorted(preview, true);
|
|
377
|
-
const response = yield this.sendMessageRequest(preview, input.customData);
|
|
378
|
-
return response;
|
|
379
|
-
});
|
|
380
|
-
}
|
|
381
|
-
/**
|
|
382
|
-
* Resends the given message to the active channel
|
|
383
|
-
* @param message The message to resend
|
|
384
|
-
*/
|
|
385
|
-
resendMessage(message) {
|
|
386
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
387
|
-
const channel = this.activeChannelSubject.getValue();
|
|
388
|
-
channel.state.addMessageSorted(Object.assign(Object.assign({}, message), { errorStatusCode: undefined, status: 'sending' }), true);
|
|
389
|
-
return this.sendMessageRequest(message, undefined, true);
|
|
390
|
-
});
|
|
391
|
-
}
|
|
392
|
-
/**
|
|
393
|
-
* Updates the message in the active channel
|
|
394
|
-
* @param message Mesage to be updated
|
|
395
|
-
*/
|
|
396
|
-
updateMessage(message) {
|
|
397
|
-
var _a;
|
|
398
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
399
|
-
let messageToUpdate = Object.assign({}, message);
|
|
400
|
-
delete messageToUpdate.i18n;
|
|
401
|
-
if (this.beforeUpdateMessage) {
|
|
402
|
-
messageToUpdate = yield this.beforeUpdateMessage(messageToUpdate);
|
|
403
|
-
}
|
|
404
|
-
if (message.moderation_details) {
|
|
405
|
-
return this.resendMessage(message);
|
|
406
|
-
}
|
|
407
|
-
const response = yield this.chatClientService.chatClient.updateMessage(messageToUpdate);
|
|
408
|
-
const channel = (_a = this.channelsSubject
|
|
409
|
-
.getValue()) === null || _a === void 0 ? void 0 : _a.find((c) => c.cid === message.cid);
|
|
410
|
-
if (response.message.type === 'error' &&
|
|
411
|
-
response.message.moderation_details) {
|
|
412
|
-
this.notificationService.addTemporaryNotification('streamChat.This message did not meet our content guidelines');
|
|
413
|
-
return message;
|
|
414
|
-
}
|
|
415
|
-
return this.transformToStreamMessage(response.message, channel);
|
|
416
|
-
});
|
|
417
|
-
}
|
|
418
|
-
/**
|
|
419
|
-
* Deletes the message from the active channel
|
|
420
|
-
* @param message Message to be deleted
|
|
421
|
-
* @param isLocalDelete set this `true` if you want to delete a message that's only part of the local state, not yet saved on the backend
|
|
422
|
-
*/
|
|
423
|
-
deleteMessage(message, isLocalDelete = false) {
|
|
424
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
425
|
-
if (isLocalDelete && this.activeChannel) {
|
|
426
|
-
const result = this.activeChannel.state.removeMessage({
|
|
427
|
-
id: message.id,
|
|
428
|
-
parent_id: message.parent_id,
|
|
429
|
-
});
|
|
430
|
-
if (result) {
|
|
431
|
-
message.parent_id
|
|
432
|
-
? this.activeThreadMessagesSubject.next(this.activeChannel.state.threads[message.parent_id])
|
|
433
|
-
: this.activeChannelMessagesSubject.next(this.activeChannel.state.messages);
|
|
434
|
-
}
|
|
435
|
-
return;
|
|
436
|
-
}
|
|
437
|
-
if (this.messageDeleteConfirmationHandler) {
|
|
438
|
-
const result = yield this.messageDeleteConfirmationHandler(message);
|
|
439
|
-
if (result) {
|
|
440
|
-
yield this.chatClientService.chatClient.deleteMessage(message.id);
|
|
441
|
-
}
|
|
442
|
-
}
|
|
443
|
-
else {
|
|
444
|
-
yield this.chatClientService.chatClient.deleteMessage(message.id);
|
|
445
|
-
}
|
|
446
|
-
});
|
|
447
|
-
}
|
|
448
|
-
/**
|
|
449
|
-
* Uploads files to the channel. If you want to know more about [file uploads](https://getstream.io/chat/docs/javascript/file_uploads/?language=javascript) check out the platform documentation.
|
|
450
|
-
* @param uploads the attachments to upload (output of the [`AttachmentService`](./AttachmentService.mdx))
|
|
451
|
-
* @returns the result of file upload requests
|
|
452
|
-
*/
|
|
453
|
-
uploadAttachments(uploads) {
|
|
454
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
455
|
-
const result = [];
|
|
456
|
-
const channel = this.activeChannelSubject.getValue();
|
|
457
|
-
const uploadResults = yield Promise.allSettled(uploads.map((upload) => upload.type === 'image'
|
|
458
|
-
? this.customImageUploadRequest
|
|
459
|
-
? this.customImageUploadRequest(upload.file, channel)
|
|
460
|
-
: channel.sendImage(upload.file, upload.file.name, upload.file.type)
|
|
461
|
-
: this.customFileUploadRequest
|
|
462
|
-
? this.customFileUploadRequest(upload.file, channel)
|
|
463
|
-
: channel.sendFile(upload.file, upload.file.name, upload.file.type)));
|
|
464
|
-
uploadResults.forEach((uploadResult, i) => {
|
|
465
|
-
var _a, _b, _c, _d, _e, _f, _g;
|
|
466
|
-
const file = uploads[i].file;
|
|
467
|
-
const type = uploads[i].type;
|
|
468
|
-
if (uploadResult.status === 'fulfilled') {
|
|
469
|
-
result.push({
|
|
470
|
-
file,
|
|
471
|
-
type,
|
|
472
|
-
state: 'success',
|
|
473
|
-
url: uploadResult.value.file,
|
|
474
|
-
/* eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access */
|
|
475
|
-
thumb_url: uploadResult.value.thumb_url,
|
|
476
|
-
});
|
|
477
|
-
}
|
|
478
|
-
else {
|
|
479
|
-
let reason = 'unknown';
|
|
480
|
-
let extraData;
|
|
481
|
-
/* eslint-disable-next-line @typescript-eslint/no-unsafe-assignment */
|
|
482
|
-
const message =
|
|
483
|
-
/* eslint-disable-next-line @typescript-eslint/no-unsafe-member-access */
|
|
484
|
-
(_b = (_a = uploadResult.reason.response) === null || _a === void 0 ? void 0 : _a.data) === null || _b === void 0 ? void 0 : _b.message;
|
|
485
|
-
/* eslint-disable-next-line @typescript-eslint/no-unsafe-assignment */
|
|
486
|
-
const code =
|
|
487
|
-
/* eslint-disable-next-line @typescript-eslint/no-unsafe-member-access */
|
|
488
|
-
(_d = (_c = uploadResult.reason.response) === null || _c === void 0 ? void 0 : _c.data) === null || _d === void 0 ? void 0 : _d.code;
|
|
489
|
-
if (code === 22) {
|
|
490
|
-
reason = 'file-size';
|
|
491
|
-
extraData = { param: ((_e = /\d+MB/.exec(message || '')) === null || _e === void 0 ? void 0 : _e[0]) || '100MB' };
|
|
492
|
-
}
|
|
493
|
-
else if (code === 4 &&
|
|
494
|
-
((_f = message === null || message === void 0 ? void 0 : message.toLowerCase()) === null || _f === void 0 ? void 0 : _f.includes('file extension'))) {
|
|
495
|
-
reason = 'file-extension';
|
|
496
|
-
extraData = { param: ((_g = /\.\w+/.exec(message)) === null || _g === void 0 ? void 0 : _g[0]) || '' };
|
|
497
|
-
}
|
|
498
|
-
result.push({
|
|
499
|
-
file,
|
|
500
|
-
type,
|
|
501
|
-
state: 'error',
|
|
502
|
-
errorReason: reason,
|
|
503
|
-
errorExtraInfo: extraData ? [extraData] : undefined,
|
|
504
|
-
});
|
|
505
|
-
}
|
|
506
|
-
});
|
|
507
|
-
return result;
|
|
508
|
-
});
|
|
509
|
-
}
|
|
510
|
-
/**
|
|
511
|
-
* Deletes an uploaded file by URL. If you want to know more about [file uploads](https://getstream.io/chat/docs/javascript/file_uploads/?language=javascript) check out the platform documentation
|
|
512
|
-
* @param attachmentUpload Attachment to be deleted (output of the [`AttachmentService`](./AttachmentService.mdx))
|
|
513
|
-
*/
|
|
514
|
-
deleteAttachment(attachmentUpload) {
|
|
515
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
516
|
-
const channel = this.activeChannelSubject.getValue();
|
|
517
|
-
yield (attachmentUpload.type === 'image'
|
|
518
|
-
? this.customImageDeleteRequest
|
|
519
|
-
? this.customImageDeleteRequest(attachmentUpload.url, channel)
|
|
520
|
-
: channel.deleteImage(attachmentUpload.url)
|
|
521
|
-
: this.customFileDeleteRequest
|
|
522
|
-
? this.customFileDeleteRequest(attachmentUpload.url, channel)
|
|
523
|
-
: channel.deleteFile(attachmentUpload.url));
|
|
524
|
-
});
|
|
525
|
-
}
|
|
526
|
-
/**
|
|
527
|
-
* Returns the autocomplete options for current channel members. If the channel has less than 100 members, it returns the channel members, otherwise sends a [search request](https://getstream.io/chat/docs/javascript/query_members/?language=javascript#pagination-and-ordering) with the given search term.
|
|
528
|
-
* @param searchTerm Text to search for in the names of members
|
|
529
|
-
* @returns The list of members matching the search filter
|
|
530
|
-
*/
|
|
531
|
-
autocompleteMembers(searchTerm) {
|
|
532
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
533
|
-
const activeChannel = this.activeChannelSubject.getValue();
|
|
534
|
-
if (!activeChannel) {
|
|
535
|
-
return [];
|
|
536
|
-
}
|
|
537
|
-
if (Object.keys(activeChannel.state.members).length < 100) {
|
|
538
|
-
return Object.values(activeChannel.state.members).filter((m) => { var _a; return ((_a = m.user) === null || _a === void 0 ? void 0 : _a.id) !== this.chatClientService.chatClient.userID; });
|
|
539
|
-
}
|
|
540
|
-
else {
|
|
541
|
-
if (!searchTerm) {
|
|
542
|
-
return [];
|
|
543
|
-
}
|
|
544
|
-
const result = yield activeChannel.queryMembers({
|
|
545
|
-
name: { $autocomplete: searchTerm },
|
|
546
|
-
id: { $ne: this.chatClientService.chatClient.userID },
|
|
547
|
-
}); // TODO: find out why we need typecast here
|
|
548
|
-
return Object.values(result.members);
|
|
549
|
-
}
|
|
550
|
-
});
|
|
551
|
-
}
|
|
552
|
-
/**
|
|
553
|
-
* [Runs a message action](https://getstream.io/chat/docs/rest/#messages-runmessageaction) in the current channel. Updates the message list based on the action result (if no message is returned, the message will be removed from the message list).
|
|
554
|
-
* @param messageId
|
|
555
|
-
* @param formData
|
|
556
|
-
* @param parentMessageId
|
|
557
|
-
*/
|
|
558
|
-
sendAction(messageId, formData, parentMessageId) {
|
|
559
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
560
|
-
const channel = this.activeChannelSubject.getValue();
|
|
561
|
-
const response = yield channel.sendAction(messageId, formData);
|
|
562
|
-
if (response === null || response === void 0 ? void 0 : response.message) {
|
|
563
|
-
channel.state.addMessageSorted(Object.assign(Object.assign({}, response.message), { status: 'received' }));
|
|
564
|
-
const isThreadReply = !!response.message.parent_id;
|
|
565
|
-
isThreadReply
|
|
566
|
-
? this.activeThreadMessagesSubject.next([
|
|
567
|
-
...channel.state.threads[response.message.parent_id],
|
|
568
|
-
])
|
|
569
|
-
: this.activeChannelMessagesSubject.next([...channel.state.messages]);
|
|
570
|
-
}
|
|
571
|
-
else {
|
|
572
|
-
channel.state.removeMessage({
|
|
573
|
-
id: messageId,
|
|
574
|
-
parent_id: parentMessageId,
|
|
575
|
-
});
|
|
576
|
-
if (parentMessageId) {
|
|
577
|
-
this.activeThreadMessagesSubject.next(channel.state.threads[this.activeParentMessageIdSubject.getValue()]);
|
|
578
|
-
}
|
|
579
|
-
else {
|
|
580
|
-
this.activeChannelMessagesSubject.next([...channel.state.messages]);
|
|
581
|
-
}
|
|
582
|
-
}
|
|
583
|
-
});
|
|
584
|
-
}
|
|
585
|
-
/**
|
|
586
|
-
* Selects or deselects the current message to quote reply to
|
|
587
|
-
* @param message The message to select, if called with `undefined`, it deselects the message
|
|
588
|
-
*/
|
|
589
|
-
selectMessageToQuote(message) {
|
|
590
|
-
this.messageToQuoteSubject.next(message);
|
|
591
|
-
}
|
|
592
|
-
/**
|
|
593
|
-
* Add a new channel to the channel list
|
|
594
|
-
* The channel will be added to the beginning of the channel list
|
|
595
|
-
* @param channel
|
|
596
|
-
*/
|
|
597
|
-
addChannel(channel) {
|
|
598
|
-
if (!this.channels.find((c) => c.cid === channel.cid)) {
|
|
599
|
-
this.channelsSubject.next([channel, ...this.channels]);
|
|
600
|
-
this.watchForChannelEvents(channel);
|
|
601
|
-
}
|
|
602
|
-
}
|
|
603
|
-
sendMessageRequest(preview, customData, isResend = false) {
|
|
604
|
-
var _a, _b, _c, _d;
|
|
605
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
606
|
-
const channel = this.activeChannelSubject.getValue();
|
|
607
|
-
const isThreadReply = !!preview.parent_id;
|
|
608
|
-
isThreadReply
|
|
609
|
-
? this.activeThreadMessagesSubject.next([
|
|
610
|
-
...channel.state.threads[preview.parent_id],
|
|
611
|
-
])
|
|
612
|
-
: this.activeChannelMessagesSubject.next([...channel.state.messages]);
|
|
613
|
-
try {
|
|
614
|
-
const response = yield channel.sendMessage(Object.assign({ id: preview.id, text: preview.text, attachments: preview.attachments, mentioned_users: (_a = preview.mentioned_users) === null || _a === void 0 ? void 0 : _a.map((u) => u.id), parent_id: preview.parent_id, quoted_message_id: preview.quoted_message_id }, customData)); // TODO: find out why we need typecast here
|
|
615
|
-
channel.state.addMessageSorted(Object.assign(Object.assign({}, response.message), { status: 'received' }), true);
|
|
616
|
-
isThreadReply
|
|
617
|
-
? this.activeThreadMessagesSubject.next([
|
|
618
|
-
...channel.state.threads[preview.parent_id],
|
|
619
|
-
])
|
|
620
|
-
: this.activeChannelMessagesSubject.next([...channel.state.messages]);
|
|
621
|
-
let messages;
|
|
622
|
-
(isThreadReply ? this.activeThreadMessages$ : this.activeChannelMessages$)
|
|
623
|
-
.pipe(take(1))
|
|
624
|
-
.subscribe((m) => (messages = m));
|
|
625
|
-
const newMessage = messages[messages.length - 1];
|
|
626
|
-
return newMessage;
|
|
627
|
-
}
|
|
628
|
-
catch (error) {
|
|
629
|
-
const stringError = JSON.stringify(error);
|
|
630
|
-
const parsedError = stringError ? JSON.parse(stringError) : {};
|
|
631
|
-
let isAlreadyExists = false;
|
|
632
|
-
if (isResend) {
|
|
633
|
-
if (parsedError.status === 400 &&
|
|
634
|
-
parsedError.code === 4 &&
|
|
635
|
-
((_d = (_c = (_b = parsedError === null || parsedError === void 0 ? void 0 : parsedError.response) === null || _b === void 0 ? void 0 : _b.data) === null || _c === void 0 ? void 0 : _c.message) === null || _d === void 0 ? void 0 : _d.includes('already exists'))) {
|
|
636
|
-
isAlreadyExists = true;
|
|
637
|
-
}
|
|
638
|
-
}
|
|
639
|
-
channel.state.addMessageSorted(Object.assign(Object.assign({}, preview), { errorStatusCode: isAlreadyExists
|
|
640
|
-
? undefined
|
|
641
|
-
: parsedError.status || undefined, status: isAlreadyExists ? 'received' : 'failed' }), true);
|
|
642
|
-
isThreadReply
|
|
643
|
-
? this.activeThreadMessagesSubject.next([
|
|
644
|
-
...channel.state.threads[preview.parent_id],
|
|
645
|
-
])
|
|
646
|
-
: this.activeChannelMessagesSubject.next([...channel.state.messages]);
|
|
647
|
-
let messages;
|
|
648
|
-
(isThreadReply ? this.activeThreadMessages$ : this.activeChannelMessages$)
|
|
649
|
-
.pipe(take(1))
|
|
650
|
-
.subscribe((m) => (messages = m));
|
|
651
|
-
const newMessage = messages[messages.length - 1];
|
|
652
|
-
return newMessage;
|
|
653
|
-
}
|
|
654
|
-
});
|
|
655
|
-
}
|
|
656
|
-
/**
|
|
657
|
-
* Jumps to the selected message inside the message list, if the message is not yet loaded, it'll load the message (and it's surroundings) from the API.
|
|
658
|
-
* @param messageId The ID of the message to be loaded, 'latest' means jump to the latest messages
|
|
659
|
-
* @param parentMessageId The ID of the parent message if we want to load a thread message
|
|
660
|
-
*/
|
|
661
|
-
jumpToMessage(messageId, parentMessageId) {
|
|
662
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
663
|
-
const activeChannel = this.activeChannelSubject.getValue();
|
|
664
|
-
try {
|
|
665
|
-
yield (activeChannel === null || activeChannel === void 0 ? void 0 : activeChannel.state.loadMessageIntoState(messageId, parentMessageId));
|
|
666
|
-
const messages = (activeChannel === null || activeChannel === void 0 ? void 0 : activeChannel.state.messages) || [];
|
|
667
|
-
this.activeChannelMessagesSubject.next([...messages]);
|
|
668
|
-
if (parentMessageId) {
|
|
669
|
-
const parentMessage = messages.find((m) => m.id === parentMessageId);
|
|
670
|
-
void this.setAsActiveParentMessage(parentMessage, 'state');
|
|
671
|
-
}
|
|
672
|
-
this.jumpToMessageSubject.next({
|
|
673
|
-
id: messageId,
|
|
674
|
-
parentId: parentMessageId,
|
|
675
|
-
});
|
|
676
|
-
}
|
|
677
|
-
catch (error) {
|
|
678
|
-
this.notificationService.addTemporaryNotification('streamChat.Message not found');
|
|
679
|
-
throw error;
|
|
680
|
-
}
|
|
681
|
-
});
|
|
682
|
-
}
|
|
683
|
-
/**
|
|
684
|
-
* Pins the given message in the channel
|
|
685
|
-
* @param message
|
|
686
|
-
*/
|
|
687
|
-
pinMessage(message) {
|
|
688
|
-
var _a;
|
|
689
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
690
|
-
try {
|
|
691
|
-
yield ((_a = this.chatClientService.chatClient) === null || _a === void 0 ? void 0 : _a.pinMessage(message));
|
|
692
|
-
this.notificationService.addTemporaryNotification('streamChat.Message pinned', 'success');
|
|
693
|
-
}
|
|
694
|
-
catch (error) {
|
|
695
|
-
this.notificationService.addTemporaryNotification('streamChat.Error pinning message');
|
|
696
|
-
throw error;
|
|
697
|
-
}
|
|
698
|
-
});
|
|
699
|
-
}
|
|
700
|
-
/**
|
|
701
|
-
* Removes the given message from pinned messages
|
|
702
|
-
* @param message
|
|
703
|
-
*/
|
|
704
|
-
unpinMessage(message) {
|
|
705
|
-
var _a;
|
|
706
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
707
|
-
try {
|
|
708
|
-
yield ((_a = this.chatClientService.chatClient) === null || _a === void 0 ? void 0 : _a.unpinMessage(message));
|
|
709
|
-
this.notificationService.addTemporaryNotification('streamChat.Message unpinned', 'success');
|
|
710
|
-
}
|
|
711
|
-
catch (error) {
|
|
712
|
-
this.notificationService.addTemporaryNotification('streamChat.Error removing message pin');
|
|
713
|
-
throw error;
|
|
714
|
-
}
|
|
715
|
-
});
|
|
716
|
-
}
|
|
717
|
-
handleNotification(clientEvent) {
|
|
718
|
-
switch (clientEvent.eventType) {
|
|
719
|
-
case 'connection.recovered': {
|
|
720
|
-
void this.ngZone.run(() => __awaiter(this, void 0, void 0, function* () {
|
|
721
|
-
if (this.isStateRecoveryInProgress) {
|
|
722
|
-
return;
|
|
723
|
-
}
|
|
724
|
-
this.isStateRecoveryInProgress = true;
|
|
725
|
-
try {
|
|
726
|
-
this.nextPageConfiguration = undefined;
|
|
727
|
-
// If channel list is not inited, we set the active channel
|
|
728
|
-
const shoulSetActiveChannel = this.shouldSetActiveChannel &&
|
|
729
|
-
!this.activeChannelSubject.getValue();
|
|
730
|
-
yield this.queryChannels(shoulSetActiveChannel || false, true);
|
|
731
|
-
if (this.activeChannelSubject.getValue()) {
|
|
732
|
-
// Thread messages are not refetched so active thread gets deselected to avoid displaying stale messages
|
|
733
|
-
void this.setAsActiveParentMessage(undefined);
|
|
734
|
-
// Update and reselect message to quote
|
|
735
|
-
const messageToQuote = this.messageToQuoteSubject.getValue();
|
|
736
|
-
this.setChannelState(this.activeChannelSubject.getValue());
|
|
737
|
-
let messages;
|
|
738
|
-
this.activeChannelMessages$
|
|
739
|
-
.pipe(take(1))
|
|
740
|
-
.subscribe((m) => (messages = m));
|
|
741
|
-
const updatedMessageToQuote = messages.find((m) => m.id === (messageToQuote === null || messageToQuote === void 0 ? void 0 : messageToQuote.id));
|
|
742
|
-
if (updatedMessageToQuote) {
|
|
743
|
-
this.selectMessageToQuote(updatedMessageToQuote);
|
|
744
|
-
}
|
|
745
|
-
}
|
|
746
|
-
this.isStateRecoveryInProgress = false;
|
|
747
|
-
}
|
|
748
|
-
catch (_a) {
|
|
749
|
-
this.isStateRecoveryInProgress = false;
|
|
750
|
-
}
|
|
751
|
-
}));
|
|
752
|
-
break;
|
|
753
|
-
}
|
|
754
|
-
case 'notification.message_new': {
|
|
755
|
-
this.ngZone.run(() => {
|
|
756
|
-
if (this.customNewMessageNotificationHandler) {
|
|
757
|
-
this.customNewMessageNotificationHandler(clientEvent, this.channelListSetter);
|
|
758
|
-
}
|
|
759
|
-
else {
|
|
760
|
-
this.handleNewMessageNotification(clientEvent);
|
|
761
|
-
}
|
|
762
|
-
});
|
|
763
|
-
break;
|
|
764
|
-
}
|
|
765
|
-
case 'notification.added_to_channel': {
|
|
766
|
-
this.ngZone.run(() => {
|
|
767
|
-
if (this.customAddedToChannelNotificationHandler) {
|
|
768
|
-
this.customAddedToChannelNotificationHandler(clientEvent, this.channelListSetter);
|
|
769
|
-
}
|
|
770
|
-
else {
|
|
771
|
-
this.handleAddedToChannelNotification(clientEvent);
|
|
772
|
-
}
|
|
773
|
-
});
|
|
774
|
-
break;
|
|
775
|
-
}
|
|
776
|
-
case 'notification.removed_from_channel': {
|
|
777
|
-
this.ngZone.run(() => {
|
|
778
|
-
if (this.customRemovedFromChannelNotificationHandler) {
|
|
779
|
-
this.customRemovedFromChannelNotificationHandler(clientEvent, this.channelListSetter);
|
|
780
|
-
}
|
|
781
|
-
else {
|
|
782
|
-
this.handleRemovedFromChannelNotification(clientEvent);
|
|
783
|
-
}
|
|
784
|
-
});
|
|
785
|
-
break;
|
|
786
|
-
}
|
|
787
|
-
case 'user.updated': {
|
|
788
|
-
this.ngZone.run(() => {
|
|
789
|
-
var _a;
|
|
790
|
-
const updatedChannels = (_a = this.channelsSubject.getValue()) === null || _a === void 0 ? void 0 : _a.map((c) => {
|
|
791
|
-
if (this.chatClientService.chatClient.activeChannels[c.cid]) {
|
|
792
|
-
return this.chatClientService.chatClient.activeChannels[c.cid];
|
|
793
|
-
}
|
|
794
|
-
else {
|
|
795
|
-
return c;
|
|
796
|
-
}
|
|
797
|
-
});
|
|
798
|
-
this.channelsSubject.next(updatedChannels);
|
|
799
|
-
const activeChannel = this.activeChannelSubject.getValue();
|
|
800
|
-
if (activeChannel) {
|
|
801
|
-
this.activeChannelSubject.next(this.chatClientService.chatClient.activeChannels[activeChannel.cid] || activeChannel);
|
|
802
|
-
this.activeChannelMessagesSubject.next(activeChannel.state.messages.map((m) => {
|
|
803
|
-
m.readBy = getReadBy(m, activeChannel);
|
|
804
|
-
return Object.assign({}, m);
|
|
805
|
-
}));
|
|
806
|
-
const activeParentMessage = this.activeParentMessageIdSubject.getValue();
|
|
807
|
-
if (activeParentMessage) {
|
|
808
|
-
const messages = activeChannel.state.threads[activeParentMessage];
|
|
809
|
-
this.activeThreadMessagesSubject.next([...messages]);
|
|
810
|
-
}
|
|
811
|
-
this.activeChannelPinnedMessagesSubject.next([
|
|
812
|
-
...activeChannel.state.pinnedMessages,
|
|
813
|
-
]);
|
|
814
|
-
}
|
|
815
|
-
});
|
|
816
|
-
break;
|
|
817
|
-
}
|
|
818
|
-
}
|
|
819
|
-
}
|
|
820
|
-
handleRemovedFromChannelNotification(clientEvent) {
|
|
821
|
-
const channelIdToBeRemoved = clientEvent.event.channel.cid;
|
|
822
|
-
this.removeChannelsFromChannelList([channelIdToBeRemoved], true);
|
|
823
|
-
}
|
|
824
|
-
handleNewMessageNotification(clientEvent) {
|
|
825
|
-
if (clientEvent.event.channel) {
|
|
826
|
-
void this.addChannelsFromNotification([clientEvent.event.channel]);
|
|
827
|
-
}
|
|
828
|
-
}
|
|
829
|
-
handleAddedToChannelNotification(clientEvent) {
|
|
830
|
-
if (clientEvent.event.channel) {
|
|
831
|
-
void this.addChannelsFromNotification([clientEvent.event.channel]);
|
|
832
|
-
}
|
|
833
|
-
}
|
|
834
|
-
addChannelsFromNotification(channelResponses) {
|
|
835
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
836
|
-
let newChannels = [];
|
|
837
|
-
const watchRequests = [];
|
|
838
|
-
channelResponses.forEach((channelResponse) => {
|
|
839
|
-
const channel = this.chatClientService.chatClient.channel(channelResponse.type, channelResponse.id);
|
|
840
|
-
watchRequests.push(channel.watch());
|
|
841
|
-
newChannels.push(channel);
|
|
842
|
-
});
|
|
843
|
-
yield Promise.all(watchRequests);
|
|
844
|
-
const currentChannels = this.channelsSubject.getValue() || [];
|
|
845
|
-
newChannels = newChannels.filter((newChannel) => !currentChannels.find((c) => c.cid === newChannel.cid));
|
|
846
|
-
if (newChannels.length > 0) {
|
|
847
|
-
newChannels.forEach((c) => this.watchForChannelEvents(c));
|
|
848
|
-
this.channelsSubject.next([...newChannels, ...currentChannels]);
|
|
849
|
-
}
|
|
850
|
-
});
|
|
851
|
-
}
|
|
852
|
-
removeChannelsFromChannelList(cids, shouldStopWatching) {
|
|
853
|
-
var _a;
|
|
854
|
-
const channels = this.channels.filter((c) => !cids.includes(c.cid || ''));
|
|
855
|
-
if (shouldStopWatching) {
|
|
856
|
-
cids.forEach((cid) => {
|
|
857
|
-
var _a;
|
|
858
|
-
if (this.channelSubscriptions[cid]) {
|
|
859
|
-
this.channelSubscriptions[cid]();
|
|
860
|
-
delete this.channelSubscriptions.cid;
|
|
861
|
-
}
|
|
862
|
-
void ((_a = this.chatClientService.chatClient.activeChannels[cid]) === null || _a === void 0 ? void 0 : _a.stopWatching());
|
|
863
|
-
});
|
|
864
|
-
}
|
|
865
|
-
if (channels.length < this.channels.length) {
|
|
866
|
-
this.channelsSubject.next(channels);
|
|
867
|
-
if (cids.includes(((_a = this.activeChannelSubject.getValue()) === null || _a === void 0 ? void 0 : _a.cid) || '')) {
|
|
868
|
-
if (channels.length > 0) {
|
|
869
|
-
this.setAsActiveChannel(channels[0]);
|
|
870
|
-
}
|
|
871
|
-
else {
|
|
872
|
-
this.activeChannelSubject.next(undefined);
|
|
873
|
-
}
|
|
874
|
-
}
|
|
875
|
-
}
|
|
876
|
-
}
|
|
877
|
-
watchForActiveChannelEvents(channel) {
|
|
878
|
-
this.activeChannelSubscriptions.push(channel.on('message.new', (event) => {
|
|
879
|
-
this.ngZone.run(() => {
|
|
880
|
-
event.message && event.message.parent_id
|
|
881
|
-
? event.message.parent_id ===
|
|
882
|
-
this.activeParentMessageIdSubject.getValue()
|
|
883
|
-
? this.activeThreadMessagesSubject.next([
|
|
884
|
-
...channel.state.threads[event.message.parent_id],
|
|
885
|
-
])
|
|
886
|
-
: null
|
|
887
|
-
: this.activeChannelMessagesSubject.next([
|
|
888
|
-
...channel.state.messages,
|
|
889
|
-
]);
|
|
890
|
-
this.activeChannel$.pipe(first()).subscribe((c) => {
|
|
891
|
-
if (c) {
|
|
892
|
-
this.markRead(c);
|
|
893
|
-
}
|
|
894
|
-
});
|
|
895
|
-
this.updateLatestMessages(event);
|
|
896
|
-
});
|
|
897
|
-
}));
|
|
898
|
-
this.activeChannelSubscriptions.push(channel.on('message.updated', (event) => this.messageUpdated(event)));
|
|
899
|
-
this.activeChannelSubscriptions.push(channel.on('message.deleted', (event) => this.messageUpdated(event)));
|
|
900
|
-
this.activeChannelSubscriptions.push(channel.on('reaction.new', (e) => this.messageReactionEventReceived(e)));
|
|
901
|
-
this.activeChannelSubscriptions.push(channel.on('reaction.deleted', (e) => this.messageReactionEventReceived(e)));
|
|
902
|
-
this.activeChannelSubscriptions.push(channel.on('reaction.updated', (e) => this.messageReactionEventReceived(e)));
|
|
903
|
-
this.activeChannelSubscriptions.push(channel.on('message.read', (e) => {
|
|
904
|
-
this.ngZone.run(() => {
|
|
905
|
-
let latestMessage;
|
|
906
|
-
let messages;
|
|
907
|
-
this.activeChannelMessages$.pipe(first()).subscribe((m) => {
|
|
908
|
-
messages = m;
|
|
909
|
-
latestMessage = messages[messages.length - 1];
|
|
910
|
-
});
|
|
911
|
-
if (!latestMessage || !e.user) {
|
|
912
|
-
return;
|
|
913
|
-
}
|
|
914
|
-
if (latestMessage.readBy) {
|
|
915
|
-
latestMessage.readBy.splice(0, latestMessage.readBy.length);
|
|
916
|
-
}
|
|
917
|
-
else {
|
|
918
|
-
latestMessage.readBy = [];
|
|
919
|
-
}
|
|
920
|
-
latestMessage.readBy.push(...getReadBy(latestMessage, channel));
|
|
921
|
-
messages[messages.length - 1] = Object.assign({}, latestMessage);
|
|
922
|
-
this.activeChannelMessagesSubject.next([...messages]);
|
|
923
|
-
});
|
|
924
|
-
}));
|
|
925
|
-
this.activeChannelSubscriptions.push(this.chatClientService.events$
|
|
926
|
-
.pipe(filter((e) => e.eventType === 'notification.mark_unread' &&
|
|
927
|
-
e.event.channel_id === channel.id), map((e) => e.event))
|
|
928
|
-
.subscribe((e) => {
|
|
929
|
-
this.ngZone.run(() => {
|
|
930
|
-
this.activeChannelLastReadMessageId = e.last_read_message_id;
|
|
931
|
-
this.activeChannelUnreadCount = e.unread_messages;
|
|
932
|
-
this.activeChannelSubject.next(this.activeChannel);
|
|
933
|
-
});
|
|
934
|
-
}));
|
|
935
|
-
this.activeChannelSubscriptions.push(channel.on('typing.start', (e) => this.ngZone.run(() => this.handleTypingStartEvent(e))));
|
|
936
|
-
this.activeChannelSubscriptions.push(channel.on('typing.stop', (e) => this.ngZone.run(() => this.handleTypingStopEvent(e))));
|
|
937
|
-
}
|
|
938
|
-
/**
|
|
939
|
-
* Call this method if user started typing in the active channel
|
|
940
|
-
* @param parentId The id of the parent message, if user is typing in a thread
|
|
941
|
-
*/
|
|
942
|
-
typingStarted(parentId) {
|
|
943
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
944
|
-
const activeChannel = this.activeChannelSubject.getValue();
|
|
945
|
-
yield (activeChannel === null || activeChannel === void 0 ? void 0 : activeChannel.keystroke(parentId));
|
|
946
|
-
});
|
|
947
|
-
}
|
|
948
|
-
/**
|
|
949
|
-
* Call this method if user stopped typing in the active channel
|
|
950
|
-
* @param parentId The id of the parent message, if user were typing in a thread
|
|
951
|
-
*/
|
|
952
|
-
typingStopped(parentId) {
|
|
953
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
954
|
-
const activeChannel = this.activeChannelSubject.getValue();
|
|
955
|
-
yield (activeChannel === null || activeChannel === void 0 ? void 0 : activeChannel.stopTyping(parentId));
|
|
956
|
-
});
|
|
957
|
-
}
|
|
958
|
-
/**
|
|
959
|
-
* The current list of channels
|
|
960
|
-
*/
|
|
961
|
-
get channels() {
|
|
962
|
-
return this.channelsSubject.getValue() || [];
|
|
963
|
-
}
|
|
964
|
-
/**
|
|
965
|
-
* The current active channel
|
|
966
|
-
*/
|
|
967
|
-
get activeChannel() {
|
|
968
|
-
return this.activeChannelSubject.getValue() || undefined;
|
|
969
|
-
}
|
|
970
|
-
/**
|
|
971
|
-
* The current active channel messages
|
|
972
|
-
*/
|
|
973
|
-
get activeChannelMessages() {
|
|
974
|
-
return this.activeChannelMessagesSubject.getValue() || [];
|
|
975
|
-
}
|
|
976
|
-
/**
|
|
977
|
-
* Get the last 1200 reactions of a message in the current active channel. If you need to fetch more reactions please use the [following endpoint](https://getstream.io/chat/docs/javascript/send_reaction/?language=javascript#paginating-reactions).
|
|
978
|
-
* @param messageId
|
|
979
|
-
* @returns all reactions of a message
|
|
980
|
-
*/
|
|
981
|
-
getMessageReactions(messageId) {
|
|
982
|
-
var _a, _b;
|
|
983
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
984
|
-
const reactions = [];
|
|
985
|
-
const limit = 300;
|
|
986
|
-
let offset = 0;
|
|
987
|
-
const reactionsLimit = ChannelService.MAX_MESSAGE_REACTIONS_TO_FETCH;
|
|
988
|
-
let lastPageSize = limit;
|
|
989
|
-
while (lastPageSize === limit && reactions.length < reactionsLimit) {
|
|
990
|
-
try {
|
|
991
|
-
const response = yield ((_a = this.activeChannel) === null || _a === void 0 ? void 0 : _a.getReactions(messageId, {
|
|
992
|
-
offset,
|
|
993
|
-
limit,
|
|
994
|
-
}));
|
|
995
|
-
lastPageSize = ((_b = response === null || response === void 0 ? void 0 : response.reactions) === null || _b === void 0 ? void 0 : _b.length) || 0;
|
|
996
|
-
if (lastPageSize > 0) {
|
|
997
|
-
reactions.push(...response.reactions);
|
|
998
|
-
}
|
|
999
|
-
offset += lastPageSize;
|
|
1000
|
-
}
|
|
1001
|
-
catch (e) {
|
|
1002
|
-
this.notificationService.addTemporaryNotification('streamChat.Error loading reactions');
|
|
1003
|
-
throw e;
|
|
1004
|
-
}
|
|
1005
|
-
}
|
|
1006
|
-
return reactions;
|
|
1007
|
-
});
|
|
1008
|
-
}
|
|
1009
|
-
/**
|
|
1010
|
-
* Marks the channel from the given message as unread
|
|
1011
|
-
* @param messageId
|
|
1012
|
-
* @returns the result of the request
|
|
1013
|
-
*/
|
|
1014
|
-
markMessageUnread(messageId) {
|
|
1015
|
-
var _a, _b, _c, _d;
|
|
1016
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
1017
|
-
if (!this.activeChannel) {
|
|
1018
|
-
return;
|
|
1019
|
-
}
|
|
1020
|
-
try {
|
|
1021
|
-
const response = yield this.activeChannel.markUnread({
|
|
1022
|
-
message_id: messageId,
|
|
1023
|
-
});
|
|
1024
|
-
this.areReadEventsPaused = true;
|
|
1025
|
-
return response;
|
|
1026
|
-
}
|
|
1027
|
-
catch (e) {
|
|
1028
|
-
const error = JSON.parse(JSON.stringify(e));
|
|
1029
|
-
const data = (_a = error === null || error === void 0 ? void 0 : error.response) === null || _a === void 0 ? void 0 : _a.data;
|
|
1030
|
-
if (data &&
|
|
1031
|
-
data.code === 4 &&
|
|
1032
|
-
data.StatusCode === 400 &&
|
|
1033
|
-
((_b = data.message) === null || _b === void 0 ? void 0 : _b.includes('it is older than last'))) {
|
|
1034
|
-
const count = (_d = (_c = /\d+ channel messages/
|
|
1035
|
-
.exec(data.message)) === null || _c === void 0 ? void 0 : _c[0].match(/\d+/)) === null || _d === void 0 ? void 0 : _d[0];
|
|
1036
|
-
if (count) {
|
|
1037
|
-
this.notificationService.addTemporaryNotification('streamChat.Error, only the first {{count}} message can be marked as unread', undefined, undefined, { count });
|
|
1038
|
-
throw e;
|
|
1039
|
-
}
|
|
1040
|
-
}
|
|
1041
|
-
this.notificationService.addTemporaryNotification('streamChat.Error marking message as unread');
|
|
1042
|
-
throw e;
|
|
1043
|
-
}
|
|
1044
|
-
});
|
|
1045
|
-
}
|
|
1046
|
-
messageUpdated(event) {
|
|
1047
|
-
this.ngZone.run(() => {
|
|
1048
|
-
var _a;
|
|
1049
|
-
const isThreadReply = event.message && event.message.parent_id;
|
|
1050
|
-
const channel = this.activeChannelSubject.getValue();
|
|
1051
|
-
if (!channel) {
|
|
1052
|
-
return;
|
|
1053
|
-
}
|
|
1054
|
-
// Get messages from state as message order could change, and message could've been deleted
|
|
1055
|
-
const messages = isThreadReply
|
|
1056
|
-
? channel.state.threads[((_a = event === null || event === void 0 ? void 0 : event.message) === null || _a === void 0 ? void 0 : _a.parent_id) || '']
|
|
1057
|
-
: channel.state.messages;
|
|
1058
|
-
if (!messages) {
|
|
1059
|
-
return;
|
|
1060
|
-
}
|
|
1061
|
-
const messageIndex = messages.findIndex((m) => { var _a; return m.id === ((_a = event === null || event === void 0 ? void 0 : event.message) === null || _a === void 0 ? void 0 : _a.id); });
|
|
1062
|
-
if (messageIndex !== -1) {
|
|
1063
|
-
isThreadReply
|
|
1064
|
-
? this.activeThreadMessagesSubject.next([...messages])
|
|
1065
|
-
: this.activeChannelMessagesSubject.next([...messages]);
|
|
1066
|
-
this.activeChannelPinnedMessagesSubject.next([
|
|
1067
|
-
...channel.state.pinnedMessages,
|
|
1068
|
-
]);
|
|
1069
|
-
}
|
|
1070
|
-
});
|
|
1071
|
-
}
|
|
1072
|
-
messageReactionEventReceived(e) {
|
|
1073
|
-
this.ngZone.run(() => {
|
|
1074
|
-
var _a, _b, _c, _d;
|
|
1075
|
-
const isThreadMessage = e.message && e.message.parent_id;
|
|
1076
|
-
let messages;
|
|
1077
|
-
(isThreadMessage
|
|
1078
|
-
? this.activeThreadMessages$
|
|
1079
|
-
: this.activeChannelMessages$)
|
|
1080
|
-
.pipe(first())
|
|
1081
|
-
.subscribe((m) => (messages = m));
|
|
1082
|
-
const messageIndex = messages.findIndex((m) => { var _a; return m.id === ((_a = e === null || e === void 0 ? void 0 : e.message) === null || _a === void 0 ? void 0 : _a.id); });
|
|
1083
|
-
if (messageIndex === -1) {
|
|
1084
|
-
return;
|
|
1085
|
-
}
|
|
1086
|
-
const message = messages[messageIndex];
|
|
1087
|
-
message.reaction_counts = Object.assign({}, (_a = e.message) === null || _a === void 0 ? void 0 : _a.reaction_counts);
|
|
1088
|
-
message.reaction_scores = Object.assign({}, (_b = e.message) === null || _b === void 0 ? void 0 : _b.reaction_scores);
|
|
1089
|
-
message.latest_reactions = [...(((_c = e.message) === null || _c === void 0 ? void 0 : _c.latest_reactions) || [])];
|
|
1090
|
-
message.own_reactions = [...(((_d = e.message) === null || _d === void 0 ? void 0 : _d.own_reactions) || [])];
|
|
1091
|
-
messages[messageIndex] = Object.assign({}, message);
|
|
1092
|
-
isThreadMessage
|
|
1093
|
-
? this.activeThreadMessagesSubject.next([...messages])
|
|
1094
|
-
: this.activeChannelMessagesSubject.next([...messages]);
|
|
1095
|
-
});
|
|
1096
|
-
}
|
|
1097
|
-
formatMessage(message) {
|
|
1098
|
-
const m = message;
|
|
1099
|
-
m.pinned_at = message.pinned_at ? new Date(message.pinned_at) : null;
|
|
1100
|
-
m.created_at = message.created_at
|
|
1101
|
-
? new Date(message.created_at)
|
|
1102
|
-
: new Date();
|
|
1103
|
-
m.updated_at = message.updated_at
|
|
1104
|
-
? new Date(message.updated_at)
|
|
1105
|
-
: new Date();
|
|
1106
|
-
message.status = message.status || 'received';
|
|
1107
|
-
return m;
|
|
1108
|
-
}
|
|
1109
|
-
isStreamMessage(message) {
|
|
1110
|
-
return !!message.readBy;
|
|
1111
|
-
}
|
|
1112
|
-
isFormatMessageResponse(message) {
|
|
1113
|
-
return message.created_at instanceof Date;
|
|
1114
|
-
}
|
|
1115
|
-
stopWatchForActiveChannelEvents(channel) {
|
|
1116
|
-
if (!channel) {
|
|
1117
|
-
return;
|
|
1118
|
-
}
|
|
1119
|
-
this.activeChannelSubscriptions.forEach((s) => s.unsubscribe());
|
|
1120
|
-
this.activeChannelSubscriptions = [];
|
|
1121
|
-
}
|
|
1122
|
-
queryChannels(shouldSetActiveChannel, recoverState = false) {
|
|
1123
|
-
var _a, _b;
|
|
1124
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
1125
|
-
try {
|
|
1126
|
-
this.channelQueryStateSubject.next({ state: 'in-progress' });
|
|
1127
|
-
let filters;
|
|
1128
|
-
let options;
|
|
1129
|
-
if (this.nextPageConfiguration) {
|
|
1130
|
-
if (this.nextPageConfiguration.type === 'filter') {
|
|
1131
|
-
filters = Object.assign(Object.assign({}, this.filters), this.nextPageConfiguration.paginationFilter);
|
|
1132
|
-
options = this.options;
|
|
1133
|
-
}
|
|
1134
|
-
else {
|
|
1135
|
-
options = Object.assign(Object.assign({}, this.options), { offset: this.nextPageConfiguration.offset });
|
|
1136
|
-
filters = this.filters;
|
|
1137
|
-
}
|
|
1138
|
-
}
|
|
1139
|
-
else {
|
|
1140
|
-
filters = this.filters;
|
|
1141
|
-
options = this.options;
|
|
1142
|
-
}
|
|
1143
|
-
const channels = yield this.chatClientService.chatClient.queryChannels(filters, this.sort || {}, options);
|
|
1144
|
-
this.setNextPageConfiguration(channels);
|
|
1145
|
-
channels.forEach((c) => this.watchForChannelEvents(c));
|
|
1146
|
-
const prevChannels = recoverState
|
|
1147
|
-
? []
|
|
1148
|
-
: this.channelsSubject.getValue() || [];
|
|
1149
|
-
const filteredChannels = channels.filter((channel) => !prevChannels.find((existingChannel) => existingChannel.cid === channel.cid));
|
|
1150
|
-
let currentActiveChannel = this.activeChannelSubject.getValue();
|
|
1151
|
-
let isCurrentActiveChannelDeselected = false;
|
|
1152
|
-
const nextChannels = [...prevChannels, ...filteredChannels];
|
|
1153
|
-
if (recoverState &&
|
|
1154
|
-
currentActiveChannel &&
|
|
1155
|
-
!filteredChannels.find((c) => c.cid === (currentActiveChannel === null || currentActiveChannel === void 0 ? void 0 : currentActiveChannel.cid))) {
|
|
1156
|
-
try {
|
|
1157
|
-
yield currentActiveChannel.watch();
|
|
1158
|
-
nextChannels.unshift(currentActiveChannel);
|
|
1159
|
-
}
|
|
1160
|
-
catch (e) {
|
|
1161
|
-
isCurrentActiveChannelDeselected = true;
|
|
1162
|
-
}
|
|
1163
|
-
}
|
|
1164
|
-
this.channelsSubject.next(nextChannels);
|
|
1165
|
-
if (isCurrentActiveChannelDeselected) {
|
|
1166
|
-
this.deselectActiveChannel();
|
|
1167
|
-
}
|
|
1168
|
-
if (filteredChannels.length > 0 &&
|
|
1169
|
-
!currentActiveChannel &&
|
|
1170
|
-
shouldSetActiveChannel) {
|
|
1171
|
-
this.setAsActiveChannel(filteredChannels[0]);
|
|
1172
|
-
currentActiveChannel = this.activeChannelSubject.getValue();
|
|
1173
|
-
}
|
|
1174
|
-
this.hasMoreChannelsSubject.next(channels.length >= this.options.limit);
|
|
1175
|
-
this.channelQueryStateSubject.next({ state: 'success' });
|
|
1176
|
-
if (((_a = this.options) === null || _a === void 0 ? void 0 : _a.keepAliveChannels$OnError) &&
|
|
1177
|
-
this.dismissErrorNotification) {
|
|
1178
|
-
this.dismissErrorNotification();
|
|
1179
|
-
}
|
|
1180
|
-
return channels;
|
|
1181
|
-
}
|
|
1182
|
-
catch (error) {
|
|
1183
|
-
if (!((_b = this.options) === null || _b === void 0 ? void 0 : _b.keepAliveChannels$OnError)) {
|
|
1184
|
-
this.channelsSubject.error(error);
|
|
1185
|
-
}
|
|
1186
|
-
this.channelQueryStateSubject.next({
|
|
1187
|
-
state: 'error',
|
|
1188
|
-
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
|
1189
|
-
error,
|
|
1190
|
-
});
|
|
1191
|
-
throw error;
|
|
1192
|
-
}
|
|
1193
|
-
});
|
|
1194
|
-
}
|
|
1195
|
-
watchForChannelEvents(channel) {
|
|
1196
|
-
const unsubscribe = channel.on((event) => {
|
|
1197
|
-
// eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion
|
|
1198
|
-
const type = event.type;
|
|
1199
|
-
switch (type) {
|
|
1200
|
-
case 'message.new': {
|
|
1201
|
-
this.ngZone.run(() => {
|
|
1202
|
-
if (this.customNewMessageHandler) {
|
|
1203
|
-
this.customNewMessageHandler(event, channel, this.channelListSetter, this.messageListSetter, this.threadListSetter, this.parentMessageSetter);
|
|
1204
|
-
}
|
|
1205
|
-
else {
|
|
1206
|
-
this.handleNewMessage(event, channel);
|
|
1207
|
-
}
|
|
1208
|
-
});
|
|
1209
|
-
break;
|
|
1210
|
-
}
|
|
1211
|
-
case 'channel.hidden': {
|
|
1212
|
-
this.ngZone.run(() => {
|
|
1213
|
-
if (this.customChannelHiddenHandler) {
|
|
1214
|
-
this.customChannelHiddenHandler(event, channel, this.channelListSetter, this.messageListSetter, this.threadListSetter, this.parentMessageSetter);
|
|
1215
|
-
}
|
|
1216
|
-
else {
|
|
1217
|
-
this.handleChannelHidden(event);
|
|
1218
|
-
}
|
|
1219
|
-
});
|
|
1220
|
-
break;
|
|
1221
|
-
}
|
|
1222
|
-
case 'channel.deleted': {
|
|
1223
|
-
this.ngZone.run(() => {
|
|
1224
|
-
if (this.customChannelDeletedHandler) {
|
|
1225
|
-
this.customChannelDeletedHandler(event, channel, this.channelListSetter, this.messageListSetter, this.threadListSetter, this.parentMessageSetter);
|
|
1226
|
-
}
|
|
1227
|
-
else {
|
|
1228
|
-
this.handleChannelDeleted(event);
|
|
1229
|
-
}
|
|
1230
|
-
});
|
|
1231
|
-
break;
|
|
1232
|
-
}
|
|
1233
|
-
case 'channel.visible': {
|
|
1234
|
-
this.ngZone.run(() => {
|
|
1235
|
-
if (this.customChannelVisibleHandler) {
|
|
1236
|
-
this.customChannelVisibleHandler(event, channel, this.channelListSetter, this.messageListSetter, this.threadListSetter, this.parentMessageSetter);
|
|
1237
|
-
}
|
|
1238
|
-
else {
|
|
1239
|
-
this.handleChannelVisible(event, channel);
|
|
1240
|
-
}
|
|
1241
|
-
});
|
|
1242
|
-
break;
|
|
1243
|
-
}
|
|
1244
|
-
case 'channel.updated': {
|
|
1245
|
-
this.ngZone.run(() => {
|
|
1246
|
-
if (this.customChannelUpdatedHandler) {
|
|
1247
|
-
this.customChannelUpdatedHandler(event, channel, this.channelListSetter, this.messageListSetter, this.threadListSetter, this.parentMessageSetter);
|
|
1248
|
-
}
|
|
1249
|
-
else {
|
|
1250
|
-
this.handleChannelUpdate(event);
|
|
1251
|
-
}
|
|
1252
|
-
});
|
|
1253
|
-
break;
|
|
1254
|
-
}
|
|
1255
|
-
case 'channel.truncated': {
|
|
1256
|
-
this.ngZone.run(() => {
|
|
1257
|
-
if (this.customChannelTruncatedHandler) {
|
|
1258
|
-
this.customChannelTruncatedHandler(event, channel, this.channelListSetter, this.messageListSetter, this.threadListSetter, this.parentMessageSetter);
|
|
1259
|
-
}
|
|
1260
|
-
else {
|
|
1261
|
-
this.handleChannelTruncate(event);
|
|
1262
|
-
}
|
|
1263
|
-
});
|
|
1264
|
-
break;
|
|
1265
|
-
}
|
|
1266
|
-
case 'capabilities.changed': {
|
|
1267
|
-
this.ngZone.run(() => {
|
|
1268
|
-
var _a;
|
|
1269
|
-
const cid = event.cid;
|
|
1270
|
-
if (cid) {
|
|
1271
|
-
const currentChannels = this.channelsSubject.getValue();
|
|
1272
|
-
const index = currentChannels === null || currentChannels === void 0 ? void 0 : currentChannels.findIndex((c) => c.cid === cid);
|
|
1273
|
-
if (index !== -1 && index !== undefined) {
|
|
1274
|
-
this.channelsSubject.next([...currentChannels]);
|
|
1275
|
-
if (cid === ((_a = this.activeChannelSubject.getValue()) === null || _a === void 0 ? void 0 : _a.cid)) {
|
|
1276
|
-
this.activeChannelSubject.next(this.activeChannelSubject.getValue());
|
|
1277
|
-
}
|
|
1278
|
-
}
|
|
1279
|
-
}
|
|
1280
|
-
});
|
|
1281
|
-
break;
|
|
1282
|
-
}
|
|
1283
|
-
}
|
|
1284
|
-
});
|
|
1285
|
-
this.channelSubscriptions[channel.cid] = unsubscribe.unsubscribe;
|
|
1286
|
-
}
|
|
1287
|
-
handleNewMessage(_, channel) {
|
|
1288
|
-
const channelIndex = this.channels.findIndex((c) => c.cid === channel.cid);
|
|
1289
|
-
this.channels.splice(channelIndex, 1);
|
|
1290
|
-
this.channelsSubject.next([channel, ...this.channels]);
|
|
1291
|
-
}
|
|
1292
|
-
handleChannelHidden(event) {
|
|
1293
|
-
this.removeChannelsFromChannelList([event.channel.cid], false);
|
|
1294
|
-
}
|
|
1295
|
-
handleChannelDeleted(event) {
|
|
1296
|
-
this.removeChannelsFromChannelList([event.channel.cid], false);
|
|
1297
|
-
}
|
|
1298
|
-
handleChannelVisible(event, channel) {
|
|
1299
|
-
if (!this.channels.find((c) => c.cid === event.cid)) {
|
|
1300
|
-
this.ngZone.run(() => this.channelsSubject.next([...this.channels, channel]));
|
|
1301
|
-
}
|
|
1302
|
-
}
|
|
1303
|
-
handleChannelUpdate(event) {
|
|
1304
|
-
var _a, _b, _c, _d;
|
|
1305
|
-
const channelIndex = this.channels.findIndex((c) => c.cid === event.channel.cid);
|
|
1306
|
-
if (channelIndex !== -1) {
|
|
1307
|
-
const channel = this.channels[channelIndex];
|
|
1308
|
-
const notIncludedProperies = {
|
|
1309
|
-
hidden: ((_a = channel.data) === null || _a === void 0 ? void 0 : _a.hidden) || false,
|
|
1310
|
-
own_capabilities: ((_b = channel.data) === null || _b === void 0 ? void 0 : _b.own_capabilities) || [],
|
|
1311
|
-
};
|
|
1312
|
-
channel.data = Object.assign(Object.assign({}, event.channel), notIncludedProperies);
|
|
1313
|
-
this.channelsSubject.next([...this.channels]);
|
|
1314
|
-
if (((_c = event.channel) === null || _c === void 0 ? void 0 : _c.cid) === ((_d = this.activeChannelSubject.getValue()) === null || _d === void 0 ? void 0 : _d.cid)) {
|
|
1315
|
-
this.activeChannelSubject.next(channel);
|
|
1316
|
-
}
|
|
1317
|
-
}
|
|
1318
|
-
}
|
|
1319
|
-
handleChannelTruncate(event) {
|
|
1320
|
-
var _a, _b;
|
|
1321
|
-
const channelIndex = this.channels.findIndex((c) => c.cid === event.channel.cid);
|
|
1322
|
-
if (channelIndex !== -1) {
|
|
1323
|
-
this.channels[channelIndex].state.messages = [];
|
|
1324
|
-
this.channelsSubject.next([...this.channels]);
|
|
1325
|
-
if (((_a = event.channel) === null || _a === void 0 ? void 0 : _a.cid) === ((_b = this.activeChannelSubject.getValue()) === null || _b === void 0 ? void 0 : _b.cid)) {
|
|
1326
|
-
const channel = this.activeChannelSubject.getValue();
|
|
1327
|
-
channel.state.messages = [];
|
|
1328
|
-
this.activeChannelSubject.next(channel);
|
|
1329
|
-
this.activeChannelMessagesSubject.next([]);
|
|
1330
|
-
this.activeParentMessageIdSubject.next(undefined);
|
|
1331
|
-
this.activeThreadMessagesSubject.next([]);
|
|
1332
|
-
}
|
|
1333
|
-
}
|
|
1334
|
-
}
|
|
1335
|
-
get canSendReadEvents() {
|
|
1336
|
-
var _a;
|
|
1337
|
-
const channel = this.activeChannelSubject.getValue();
|
|
1338
|
-
if (!channel) {
|
|
1339
|
-
return false;
|
|
1340
|
-
}
|
|
1341
|
-
const capabilites = (_a = channel.data) === null || _a === void 0 ? void 0 : _a.own_capabilities;
|
|
1342
|
-
return capabilites.indexOf('read-events') !== -1;
|
|
1343
|
-
}
|
|
1344
|
-
transformToStreamMessage(message, channel) {
|
|
1345
|
-
const isThreadMessage = !!message.parent_id;
|
|
1346
|
-
if (this.isStreamMessage(message) &&
|
|
1347
|
-
this.isFormatMessageResponse(message)) {
|
|
1348
|
-
if (message.quoted_message) {
|
|
1349
|
-
message.quoted_message.translation = getMessageTranslation(message.quoted_message, channel, this.chatClientService.chatClient.user);
|
|
1350
|
-
}
|
|
1351
|
-
message.translation = getMessageTranslation(message, channel, this.chatClientService.chatClient.user);
|
|
1352
|
-
return message;
|
|
1353
|
-
}
|
|
1354
|
-
else {
|
|
1355
|
-
if (message.quoted_message) {
|
|
1356
|
-
message.quoted_message.translation = getMessageTranslation(message.quoted_message, channel, this.chatClientService.chatClient.user);
|
|
1357
|
-
}
|
|
1358
|
-
if (this.isFormatMessageResponse(message)) {
|
|
1359
|
-
message.readBy = isThreadMessage
|
|
1360
|
-
? []
|
|
1361
|
-
: channel
|
|
1362
|
-
? getReadBy(message, channel)
|
|
1363
|
-
: [];
|
|
1364
|
-
message.translation = getMessageTranslation(message, channel, this.chatClientService.chatClient.user);
|
|
1365
|
-
return message;
|
|
1366
|
-
}
|
|
1367
|
-
else {
|
|
1368
|
-
message = this.formatMessage(message);
|
|
1369
|
-
message.readBy = isThreadMessage
|
|
1370
|
-
? []
|
|
1371
|
-
: channel
|
|
1372
|
-
? getReadBy(message, channel)
|
|
1373
|
-
: [];
|
|
1374
|
-
message.translation = getMessageTranslation(message, channel, this.chatClientService.chatClient.user);
|
|
1375
|
-
return message;
|
|
1376
|
-
}
|
|
1377
|
-
}
|
|
1378
|
-
}
|
|
1379
|
-
handleTypingStartEvent(event) {
|
|
1380
|
-
var _a, _b;
|
|
1381
|
-
if (((_a = event.user) === null || _a === void 0 ? void 0 : _a.id) === ((_b = this.chatClientService.chatClient.user) === null || _b === void 0 ? void 0 : _b.id)) {
|
|
1382
|
-
return;
|
|
1383
|
-
}
|
|
1384
|
-
const isTypingInThread = !!event.parent_id;
|
|
1385
|
-
if (isTypingInThread &&
|
|
1386
|
-
event.parent_id !== this.activeParentMessageIdSubject.getValue()) {
|
|
1387
|
-
return;
|
|
1388
|
-
}
|
|
1389
|
-
const subject = isTypingInThread
|
|
1390
|
-
? this.usersTypingInThreadSubject
|
|
1391
|
-
: this.usersTypingInChannelSubject;
|
|
1392
|
-
const users = subject.getValue();
|
|
1393
|
-
const user = event.user;
|
|
1394
|
-
if (user && !users.find((u) => u.id === user.id)) {
|
|
1395
|
-
users.push(user);
|
|
1396
|
-
subject.next([...users]);
|
|
1397
|
-
}
|
|
1398
|
-
}
|
|
1399
|
-
handleTypingStopEvent(event) {
|
|
1400
|
-
const usersTypingInChannel = this.usersTypingInChannelSubject.getValue();
|
|
1401
|
-
const usersTypingInThread = this.usersTypingInThreadSubject.getValue();
|
|
1402
|
-
const user = event.user;
|
|
1403
|
-
if (user && usersTypingInChannel.find((u) => u.id === user.id)) {
|
|
1404
|
-
usersTypingInChannel.splice(usersTypingInChannel.findIndex((u) => u.id === user.id), 1);
|
|
1405
|
-
this.usersTypingInChannelSubject.next([...usersTypingInChannel]);
|
|
1406
|
-
return;
|
|
1407
|
-
}
|
|
1408
|
-
if (user && usersTypingInThread.find((u) => u.id === user.id)) {
|
|
1409
|
-
usersTypingInThread.splice(usersTypingInThread.findIndex((u) => u.id === user.id), 1);
|
|
1410
|
-
this.usersTypingInThreadSubject.next([...usersTypingInThread]);
|
|
1411
|
-
return;
|
|
1412
|
-
}
|
|
1413
|
-
}
|
|
1414
|
-
updateLatestMessages(event) {
|
|
1415
|
-
var _a, _b, _c, _d, _e, _f, _g;
|
|
1416
|
-
if (((_b = (_a = event.message) === null || _a === void 0 ? void 0 : _a.user) === null || _b === void 0 ? void 0 : _b.id) !== ((_d = (_c = this.chatClientService) === null || _c === void 0 ? void 0 : _c.chatClient.user) === null || _d === void 0 ? void 0 : _d.id)) {
|
|
1417
|
-
return;
|
|
1418
|
-
}
|
|
1419
|
-
const latestMessages = this.latestMessageDateByUserByChannelsSubject.getValue();
|
|
1420
|
-
if (!((_e = event.message) === null || _e === void 0 ? void 0 : _e.created_at)) {
|
|
1421
|
-
return;
|
|
1422
|
-
}
|
|
1423
|
-
const channelId = (_f = event === null || event === void 0 ? void 0 : event.message) === null || _f === void 0 ? void 0 : _f.cid;
|
|
1424
|
-
if (!channelId) {
|
|
1425
|
-
return;
|
|
1426
|
-
}
|
|
1427
|
-
const messageDate = new Date(event.message.created_at);
|
|
1428
|
-
if (!latestMessages[channelId] ||
|
|
1429
|
-
((_g = latestMessages[channelId]) === null || _g === void 0 ? void 0 : _g.getTime()) < messageDate.getTime()) {
|
|
1430
|
-
latestMessages[channelId] = messageDate;
|
|
1431
|
-
this.latestMessageDateByUserByChannelsSubject.next(Object.assign({}, latestMessages));
|
|
1432
|
-
}
|
|
1433
|
-
}
|
|
1434
|
-
setChannelState(channel) {
|
|
1435
|
-
channel.state.messages.forEach((m) => {
|
|
1436
|
-
m.readBy = getReadBy(m, channel);
|
|
1437
|
-
m.translation = getMessageTranslation(m, channel, this.chatClientService.chatClient.user);
|
|
1438
|
-
if (m.quoted_message) {
|
|
1439
|
-
m.quoted_message.translation = getMessageTranslation(m.quoted_message, channel, this.chatClientService.chatClient.user);
|
|
1440
|
-
}
|
|
1441
|
-
});
|
|
1442
|
-
this.markRead(channel);
|
|
1443
|
-
this.activeChannelMessagesSubject.next([...channel.state.messages]);
|
|
1444
|
-
this.activeChannelPinnedMessagesSubject.next([
|
|
1445
|
-
...channel.state.pinnedMessages,
|
|
1446
|
-
]);
|
|
1447
|
-
this.activeParentMessageIdSubject.next(undefined);
|
|
1448
|
-
this.activeThreadMessagesSubject.next([]);
|
|
1449
|
-
this.messageToQuoteSubject.next(undefined);
|
|
1450
|
-
this.usersTypingInChannelSubject.next([]);
|
|
1451
|
-
this.usersTypingInThreadSubject.next([]);
|
|
1452
|
-
}
|
|
1453
|
-
markRead(channel) {
|
|
1454
|
-
if (this.canSendReadEvents &&
|
|
1455
|
-
this.shouldMarkActiveChannelAsRead &&
|
|
1456
|
-
!this.areReadEventsPaused) {
|
|
1457
|
-
void channel.markRead();
|
|
1458
|
-
}
|
|
1459
|
-
}
|
|
1460
|
-
setNextPageConfiguration(channelQueryResult) {
|
|
1461
|
-
var _a;
|
|
1462
|
-
if (this.customPaginator) {
|
|
1463
|
-
this.nextPageConfiguration = this.customPaginator(channelQueryResult);
|
|
1464
|
-
}
|
|
1465
|
-
else {
|
|
1466
|
-
this.nextPageConfiguration = {
|
|
1467
|
-
type: 'offset',
|
|
1468
|
-
offset: (((_a = this.nextPageConfiguration) === null || _a === void 0 ? void 0 : _a.type) === 'offset'
|
|
1469
|
-
? this.nextPageConfiguration.offset
|
|
1470
|
-
: 0) + channelQueryResult.length,
|
|
1471
|
-
};
|
|
1472
|
-
}
|
|
1473
|
-
}
|
|
1474
|
-
}
|
|
1475
|
-
/**
|
|
1476
|
-
* internal
|
|
1477
|
-
*/
|
|
1478
|
-
ChannelService.MAX_MESSAGE_REACTIONS_TO_FETCH = 1200;
|
|
1479
|
-
ChannelService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: ChannelService, deps: [{ token: i1.ChatClientService }, { token: i0.NgZone }, { token: i2.NotificationService }], target: i0.ɵɵFactoryTarget.Injectable });
|
|
1480
|
-
ChannelService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: ChannelService, providedIn: 'root' });
|
|
1481
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: ChannelService, decorators: [{
|
|
1482
|
-
type: Injectable,
|
|
1483
|
-
args: [{
|
|
1484
|
-
providedIn: 'root',
|
|
1485
|
-
}]
|
|
1486
|
-
}], ctorParameters: function () { return [{ type: i1.ChatClientService }, { type: i0.NgZone }, { type: i2.NotificationService }]; } });
|
|
1487
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2hhbm5lbC5zZXJ2aWNlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vcHJvamVjdHMvc3RyZWFtLWNoYXQtYW5ndWxhci9zcmMvbGliL2NoYW5uZWwuc2VydmljZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiO0FBQUEsT0FBTyxFQUFFLFVBQVUsRUFBVSxNQUFNLGVBQWUsQ0FBQztBQUNuRCxPQUFPLEVBQ0wsZUFBZSxFQUNmLGFBQWEsRUFFYixhQUFhLEdBRWQsTUFBTSxNQUFNLENBQUM7QUFDZCxPQUFPLEVBQUUsTUFBTSxFQUFFLEtBQUssRUFBRSxHQUFHLEVBQUUsV0FBVyxFQUFFLElBQUksRUFBRSxNQUFNLGdCQUFnQixDQUFDO0FBbUJ2RSxPQUFPLEVBQUUscUJBQXFCLEVBQUUsTUFBTSwyQkFBMkIsQ0FBQztBQUNsRSxPQUFPLEVBQUUsb0JBQW9CLEVBQUUsTUFBTSxtQkFBbUIsQ0FBQztBQUV6RCxPQUFPLEVBQUUsU0FBUyxFQUFFLE1BQU0sV0FBVyxDQUFDOzs7O0FBWXRDOztHQUVHO0FBSUgsTUFBTSxPQUFPLGNBQWM7SUF3V3pCLFlBQ1UsaUJBQXVDLEVBQ3ZDLE1BQWMsRUFDZCxtQkFBd0M7UUFGeEMsc0JBQWlCLEdBQWpCLGlCQUFpQixDQUFzQjtRQUN2QyxXQUFNLEdBQU4sTUFBTSxDQUFRO1FBQ2Qsd0JBQW1CLEdBQW5CLG1CQUFtQixDQUFxQjtRQXZGMUMsb0JBQWUsR0FBRyxJQUFJLGVBQWUsQ0FDM0MsU0FBUyxDQUNWLENBQUM7UUFDTSx5QkFBb0IsR0FBRyxJQUFJLGVBQWUsQ0FDaEQsU0FBUyxDQUNWLENBQUM7UUFDTSxpQ0FBNEIsR0FBRyxJQUFJLGVBQWUsQ0FFeEQsRUFBRSxDQUFDLENBQUM7UUFDRSx1Q0FBa0MsR0FBRyxJQUFJLGVBQWUsQ0FFOUQsRUFBRSxDQUFDLENBQUM7UUFDRSwyQkFBc0IsR0FBRyxJQUFJLGFBQWEsQ0FBVSxDQUFDLENBQUMsQ0FBQztRQUN2RCwrQkFBMEIsR0FB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QUFkLGNBQWMsY0FGYixNQUFNOzJGQUVQLGNBQWM7a0JBSDFCLFVBQVU7bUJBQUM7b0JBQ1YsVUFBVSxFQUFFLE1BQU07aUJBQ25CIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgSW5qZWN0YWJsZSwgTmdab25lIH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQge1xuICBCZWhhdmlvclN1YmplY3QsXG4gIGNvbWJpbmVMYXRlc3QsXG4gIE9ic2VydmFibGUsXG4gIFJlcGxheVN1YmplY3QsXG4gIFN1YnNjcmlwdGlvbixcbn0gZnJvbSAncnhqcyc7XG5pbXBvcnQgeyBmaWx0ZXIsIGZpcnN0LCBtYXAsIHNoYXJlUmVwbGF5LCB0YWtlIH0gZnJvbSAncnhqcy9vcGVyYXRvcnMnO1xuaW1wb3J0IHtcbiAgQXR0YWNobWVudCxcbiAgQ2hhbm5lbCxcbiAgQ2hhbm5lbEZpbHRlcnMsXG4gIENoYW5uZWxPcHRpb25zLFxuICBDaGFubmVsUmVzcG9uc2UsXG4gIENoYW5uZWxTb3J0LFxuICBFdmVudCxcbiAgRXZlbnRUeXBlcyxcbiAgRm9ybWF0TWVzc2FnZVJlc3BvbnNlLFxuICBNZXNzYWdlLFxuICBNZXNzYWdlUmVzcG9uc2UsXG4gIFJlYWN0aW9uUmVzcG9uc2UsXG4gIFVwZGF0ZWRNZXNzYWdlLFxuICBVc2VyRmlsdGVycyxcbiAgVXNlclJlc3BvbnNlLFxufSBmcm9tICdzdHJlYW0tY2hhdCc7XG5pbXBvcnQgeyBDaGF0Q2xpZW50U2VydmljZSwgQ2xpZW50RXZlbnQgfSBmcm9tICcuL2NoYXQtY2xpZW50LnNlcnZpY2UnO1xuaW1wb3J0IHsgZ2V0TWVzc2FnZVRyYW5zbGF0aW9uIH0gZnJvbSAnLi9nZXQtbWVzc2FnZS10cmFuc2xhdGlvbic7XG5pbXBvcnQgeyBjcmVhdGVNZXNzYWdlUHJldmlldyB9IGZyb20gJy4vbWVzc2FnZS1wcmV2aWV3JztcbmltcG9ydCB7IE5vdGlmaWNhdGlvblNlcnZpY2UgfSBmcm9tICcuL25vdGlmaWNhdGlvbi5zZXJ2aWNlJztcbmltcG9ydCB7IGdldFJlYWRCeSB9IGZyb20gJy4vcmVhZC1ieSc7XG5pbXBvcnQge1xuICBBdHRhY2htZW50VXBsb2FkLFxuICBBdHRhY2htZW50VXBsb2FkRXJyb3JSZWFzb24sXG4gIENoYW5uZWxRdWVyeVN0YXRlLFxuICBEZWZhdWx0U3RyZWFtQ2hhdEdlbmVyaWNzLFxuICBNZXNzYWdlSW5wdXQsXG4gIE1lc3NhZ2VSZWFjdGlvblR5cGUsXG4gIE5leHRQYWdlQ29uZmlndXJhdGlvbixcbiAgU3RyZWFtTWVzc2FnZSxcbn0gZnJvbSAnLi90eXBlcyc7XG5cbi8qKlxuICogVGhlIGBDaGFubmVsU2VydmljZWAgcHJvdmlkZXMgZGF0YSBhbmQgaW50ZXJhY3Rpb24gZm9yIHRoZSBjaGFubmVsIGxpc3QgYW5kIG1lc3NhZ2UgbGlzdC5cbiAqL1xuQEluamVjdGFibGUoe1xuICBwcm92aWRlZEluOiAncm9vdCcsXG59KVxuZXhwb3J0IGNsYXNzIENoYW5uZWxTZXJ2aWNlPFxuICBUIGV4dGVuZHMgRGVmYXVsdFN0cmVhbUNoYXRHZW5lcmljcyA9IERlZmF1bHRTdHJlYW1DaGF0R2VuZXJpY3Ncbj4ge1xuICAvKipcbiAgICogRW1pdHMgYGZhbHNlYCBpZiB0aGVyZSBhcmUgbm8gbW9yZSBwYWdlcyBvZiBjaGFubmVscyB0aGF0IGNhbiBiZSBsb2FkZWQuXG4gICAqL1xuICBoYXNNb3JlQ2hhbm5lbHMkOiBPYnNlcnZhYmxlPGJvb2xlYW4+O1xuICAvKipcbiAgICogRW1pdHMgdGhlIGN1cnJlbnRseSBsb2FkZWQgYW5kIFt3YXRjaGVkXShodHRwczovL2dldHN0cmVhbS5pby9jaGF0L2RvY3MvamF2YXNjcmlwdC93YXRjaF9jaGFubmVsLz9sYW5ndWFnZT1qYXZhc2NyaXB0KSBjaGFubmVsIGxpc3QuXG4gICAqXG4gICAqIDo6OmltcG9ydGFudFxuICAgKiBJZiB5b3Ugd2FudCB0byBzdWJzY3JpYmUgdG8gY2hhbm5lbCBldmVudHMsIHlvdSBuZWVkIHRvIG1hbnVhbGx5IHJlZW50ZXIgQW5ndWxhcidzIGNoYW5nZSBkZXRlY3Rpb24gem9uZSwgb3VyIFtDaGFuZ2UgZGV0ZWN0aW9uIGd1aWRlXSguLi9jb25jZXB0cy9jaGFuZ2UtZGV0ZWN0aW9uLm1keCkgZXhwbGFpbnMgdGhpcyBpbiBkZXRhaWwuXG4gICAqIDo6OlxuICAgKlxuICAgKiAgQXBhcnQgZnJvbSBwYWdpbmF0aW9uLCB0aGUgY2hhbm5lbCBsaXN0IGlzIGFsc28gdXBkYXRlZCBvbiB0aGUgZm9sbG93aW5nIGV2ZW50czpcbiAgICpcbiAgICogIHwgRXZlbnQgdHlwZSAgICAgICAgICAgICAgICAgICAgICAgICAgfCBEZWZhdWx0IGJlaGF2aW9yICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfCBDdXN0b20gaGFuZGxlciB0byBvdmVycmlkZSAgICAgICAgICAgICAgICAgICAgfFxuICAgKiAgfCAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSB8IC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSB8IC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSB8XG4gICAqICB8IGBjaGFubmVsLmRlbGV0ZWRgICAgICAgICAgICAgICAgICAgIHwgUmVtb3ZlIGNoYW5uZWwgZnJvbSB0aGUgbGlzdCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgYGN1c3RvbUNoYW5uZWxEZWxldGVkSGFuZGxlcmAgICAgICAgICAgICAgICAgIHxcbiAgICogIHwgYGNoYW5uZWwuaGlkZGVuYCAgICAgICAgICAgICAgICAgICAgfCBSZW1vdmUgY2hhbm5lbCBmcm9tIHRoZSBsaXN0ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfCBgY3VzdG9tQ2hhbm5lbEhpZGRlbkhhbmRsZXJgICAgICAgICAgICAgICAgICAgfFxuICAgKiAgfCBgY2hhbm5lbC50cnVuY2F0ZWRgICAgICAgICAgICAgICAgICB8IFVwZGF0ZXMgdGhlIGNoYW5uZWwgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8IGBjdXN0b21DaGFubmVsVHJ1bmNhdGVkSGFuZGxlcmAgICAgICAgICAgICAgICB8XG4gICAqICB8IGBjaGFubmVsLnVwZGF0ZWRgICAgICAgICAgICAgICAgICAgIHwgVXBkYXRlcyB0aGUgY2hhbm5lbCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgYGN1c3RvbUNoYW5uZWxVcGRhdGVkSGFuZGxlcmAgICAgICAgICAgICAgICAgIHxcbiAgICogIHwgYGNoYW5uZWwudmlzaWJsZWAgICAgICAgICAgICAgICAgICAgfCBBZGRzIHRoZSBjaGFubmVsIHRvIHRoZSBsaXN0ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfCBgY3VzdG9tQ2hhbm5lbFZpc2libGVIYW5kbGVyYCAgICAgICAgICAgICAgICAgfFxuICAgKiAgfCBgbWVzc2FnZS5uZXdgICAgICAgICAgICAgICAgICAgICAgICB8IE1vdmVzIHRoZSBjaGFubmVsIHRvIHRvcCBvZiB0aGUgbGlzdCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8IGBjdXN0b21OZXdNZXNzYWdlSGFuZGxlcmAgICAgICAgICAgICAgICAgICAgICB8XG4gICAqICB8IGBub3RpZmljYXRpb24uYWRkZWRfdG9fY2hhbm5lbGAgICAgIHwgQWRkcyB0aGUgbmV3IGNoYW5uZWwgdG8gdGhlIHRvcCBvZiB0aGUgbGlzdCBhbmQgc3RhcnRzIHdhdGNoaW5nIGl0IHwgYGN1c3RvbUFkZGVkVG9DaGFubmVsTm90aWZpY2F0aW9uSGFuZGxlcmAgICAgIHxcbiAgICogIHwgYG5vdGlmaWNhdGlvbi5tZXNzYWdlX25ld2AgICAgICAgICAgfCBBZGRzIHRoZSBuZXcgY2hhbm5lbCB0byB0aGUgdG9wIG9mIHRoZSBsaXN0IGFuZCBzdGFydHMgd2F0Y2hpbmcgaXQgfCBgY3VzdG9tTmV3TWVzc2FnZU5vdGlmaWNhdGlvbkhhbmRsZXJgICAgICAgICAgfFxuICAgKiAgfCBgbm90aWZpY2F0aW9uLnJlbW92ZWRfZnJvbV9jaGFubmVsYCB8IFJlbW92ZXMgdGhlIGNoYW5uZWwgZnJvbSB0aGUgbGlzdCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8IGBjdXN0b21SZW1vdmVkRnJvbUNoYW5uZWxOb3RpZmljYXRpb25IYW5kbGVyYCB8XG4gICAqXG4gICAqICBJdCdzIGltcG9ydGFudCB0byBub3RlIHRoYXQgZmlsdGVycyBkb24ndCBhcHBseSB0byB1cGRhdGVzIHRvIHRoZSBsaXN0IGZyb20gZXZlbnRzLlxuICAgKlxuICAgKiAgT3VyIHBsYXRmb3JtIGRvY3VtZW50YXRpb24gY292ZXJzIHRoZSB0b3BpYyBvZiBbY2hhbm5lbCBldmVudHNdKGh0dHBzOi8vZ2V0c3RyZWFtLmlvL2NoYXQvZG9jcy9qYXZhc2NyaXB0L2V2ZW50X29iamVjdC8/bGFuZ3VhZ2U9amF2YXNjcmlwdCNldmVudHMpIGluIGRlcHRoLlxuICAgKlxuICAgKiAgQnkgZGVmYXVsdCBpZiBhbiBlcnJvciBvY2N1cnMgZHVyaW5nIGNoYW5uZWwgbG9hZCwgdGhlIE9ic2VydmFibGUgd2lsbCBlbWl0IGFuIGVycm9yLCB3aGljaCB3aWxsIGNsb3NlIHRoZSBzdHJlYW0uIFVzZXJzIHdpbGwgaGF2ZSB0byByZWxvYWQgdGhlIHBhZ2UgdG8gYmUgYWJsZSB0byByZWluaXRpYWxpemUgdGhlIGBDaGFubmVsU2VydmljZWAuIElmIHlvdSBkb24ndCB3YW50IHRoZSBzdHJlYW1zIHRvIGJlIGNsb3NlZCwgeW91IGNhbiBwYXNzIGBvcHRpb25zLmtlZXBBbGl2ZUNoYW5uZWxzJE9uRXJyb3IgPSB0cnVlYCB0byB0aGUgYGluaXRgIG1ldGhvZC4gSW4gdGhhdCBjYXNlIHRoZSBgY2hhbm5lbFF1ZXJ5U3RhdGUkYCBzdHJlYW0gd2lsbCBlbWl0IHRoZSBzdGF0dXMgb2YgdGhlIGxhdGVzdCBjaGFubmVsIGxvYWQgcmVxdWVzdC5cbiAgICovXG4gIGNoYW5uZWxzJDogT2JzZXJ2YWJsZTxDaGFubmVsPFQ+W10gfCB1bmRlZmluZWQ+O1xuICAvKipcbiAgICogVGhlIHJlc3VsdCBvZiB0aGUgbGF0ZXN0IGNoYW5uZWwgcXVlcnkgcmVxdWVzdC5cbiAgICovXG4gIGNoYW5uZWxRdWVyeVN0YXRlJDogT2JzZXJ2YWJsZTxDaGFubmVsUXVlcnlTdGF0ZSB8IHVuZGVmaW5lZD47XG4gIC8qKlxuICAgKiBFbWl0cyB0aGUgY3VycmVudGx5IGFjdGl2ZSBjaGFubmVsLlxuICAgKlxuICAgKiA6OjppbXBvcnRhbnRcbiAgICogSWYgeW91IHdhbnQgdG8gc3Vic2NyaWJlIHRvIGNoYW5uZWwgZXZlbnRzLCB5b3UgbmVlZCB0byBtYW51YWxseSByZWVudGVyIEFuZ3VsYXIncyBjaGFuZ2UgZGV0ZWN0aW9uIHpvbmUsIG91ciBbQ2hhbmdlIGRldGVjdGlvbiBndWlkZV0oLi4vY29uY2VwdHMvY2hhbmdlLWRldGVjdGlvbi5tZHgpIGV4cGxhaW5zIHRoaXMgaW4gZGV0YWlsLlxuICAgKiA6OjpcbiAgICpcbiAgICogVGhlIGFjdGl2ZSBjaGFubmVsIHdpbGwgYWx3YXlzIGJlIG1hcmtlZCBhcyByZWFkIHdoZW4gYSBuZXcgbWVzc2FnZSBpcyByZWNlaXZlZFxuICAgKi9cbiAgYWN0aXZlQ2hhbm5lbCQ6IE9ic2VydmFibGU8Q2hhbm5lbDxUPiB8IHVuZGVmaW5lZD47XG4gIC8qKlxuICAgKiBFbWl0cyB0aGUgbGlzdCBvZiBjdXJyZW50bHkgbG9hZGVkIG1lc3NhZ2VzIG9mIHRoZSBhY3RpdmUgY2hhbm5lbC5cbiAgICovXG4gIGFjdGl2ZUNoYW5uZWxNZXNzYWdlcyQ6IE9ic2VydmFibGU8U3RyZWFtTWVzc2FnZTxUPltdPjtcbiAgLyoqXG4gICAqIEVtaXRzIHRoZSBsaXN0IG9mIHBpbm5lZCBtZXNzYWdlcyBvZiB0aGUgYWN0aXZlIGNoYW5uZWwuXG4gICAqL1xuICBhY3RpdmVDaGFubmVsUGlubmVkTWVzc2FnZXMkOiBPYnNlcnZhYmxlPFN0cmVhbU1lc3NhZ2U8VD5bXT47XG4gIC8qKlxuICAgKiBFbWl0cyB0aGUgaWQgb2YgdGhlIGN1cnJlbnRseSBzZWxlY3RlZCBwYXJlbnQgbWVzc2FnZS4gSWYgbm8gbWVzc2FnZSBpcyBzZWxlY3RlZCwgaXQgZW1pdHMgdW5kZWZpbmVkLlxuICAgKi9cbiAgYWN0aXZlUGFyZW50TWVzc2FnZUlkJDogT2JzZXJ2YWJsZTxzdHJpbmcgfCB1bmRlZmluZWQ+O1xuICAvKipcbiAgICogRW1pdHMgdGhlIGxpc3Qgb2YgY3VycmVudGx5IGxvYWRlZCB0aHJlYWQgcmVwbGllcyBiZWxvbmdpbmcgdG8gdGhlIHNlbGVjdGVkIHBhcmVudCBtZXNzYWdlLiBJZiB0aGVyZSBpcyBubyBjdXJyZW50bHkgYWN0aXZlIHRocmVhZCBpdCBlbWl0cyBhbiBlbXB0eSBhcnJheS5cbiAgICovXG4gIGFjdGl2ZVRocmVhZE1lc3NhZ2VzJDogT2JzZXJ2YWJsZTxTdHJlYW1NZXNzYWdlPFQ+W10+O1xuICAvKipcbiAgICogRW1pdHMgdGhlIGN1cnJlbnRseSBzZWxlY3RlZCBwYXJlbnQgbWVzc2FnZS4gSWYgbm8gbWVzc2FnZSBpcyBzZWxlY3RlZCwgaXQgZW1pdHMgdW5kZWZpbmVkLlxuICAgKi9cbiAgYWN0aXZlUGFyZW50TWVzc2FnZSQ6IE9ic2VydmFibGU8U3RyZWFtTWVzc2FnZTxUPiB8IHVuZGVmaW5lZD47XG4gIC8qKlxuICAgKiBFbWl0cyB0aGUgY3VycmVudGx5IHNlbGVjdGVkIG1lc3NhZ2UgdG8gcXVvdGVcbiAgICovXG4gIG1lc3NhZ2VUb1F1b3RlJDogT2JzZXJ2YWJsZTxTdHJlYW1NZXNzYWdlPFQ+IHwgdW5kZWZpbmVkPjtcbiAgLyoqXG4gICAqIEVtaXRzIHRoZSBJRCBvZiB0aGUgbWVzc2FnZSB0aGUgbWVzc2FnZSBsaXN0IHNob3VsZCBqdW1wIHRvIChjYW4gYmUgYSBjaGFubmVsIG1lc3NhZ2Ugb3IgdGhyZWFkIG1lc3NhZ2UpXG4gICAqL1xuICBqdW1wVG9NZXNzYWdlJDogT2JzZXJ2YWJsZTx7IGlkPzogc3RyaW5nOyBwYXJlbnRJZD86IHN0cmluZyB9PjtcbiAgLyoqXG4gICAqIEVtaXRzIHRoZSBsaXN0IG9mIHVzZXJzIHRoYXQgYXJlIGN1cnJlbnRseSB0eXBpbmcgaW4gdGhlIGNoYW5uZWwgKGN1cnJlbnQgdXNlciBpcyBub3QgaW5jbHVkZWQpXG4gICAqL1xuICB1c2Vyc1R5cGluZ0luQ2hhbm5lbCQ6IE9ic2VydmFibGU8VXNlclJlc3BvbnNlPFQ+W10+O1xuICAvKipcbiAgICogRW1pdHMgdGhlIGxpc3Qgb2YgdXNlcnMgdGhhdCBhcmUgY3VycmVudGx5IHR5cGluZyBpbiB0aGUgYWN0aXZlIHRocmVhZCAoY3VycmVudCB1c2VyIGlzIG5vdCBpbmNsdWRlZClcbiAgICovXG4gIHVzZXJzVHlwaW5nSW5UaHJlYWQkOiBPYnNlcnZhYmxlPFVzZXJSZXNwb25zZTxUPltdPjtcbiAgLyoqXG4gICAqIEVtaXRzIGEgbWFwIHRoYXQgY29udGFpbnMgdGhlIGRhdGUgb2YgdGhlIGxhdGVzdCBtZXNzYWdlIHNlbnQgYnkgdGhlIGN1cnJlbnQgdXNlciBieSBjaGFubmVscyAodGhpcyBpcyB1c2VkIHRvIGRldGVjdCBpZiBzbG93IG1vZGUgY291bnRkb3duIHNob3VsZCBiZSBzdGFydGVkKVxuICAgKi9cbiAgbGF0ZXN0TWVzc2FnZURhdGVCeVVzZXJCeUNoYW5uZWxzJDogT2JzZXJ2YWJsZTx7IFtrZXk6IHN0cmluZ106IERhdGUgfT47XG4gIC8qKlxuICAgKiBJZiB5b3UncmUgdXNpbmcgW3NlbWFudGljIGZpbHRlcnMgZm9yIG1vZGVyYXRpb25dKGh0dHBzOi8vZ2V0c3RyZWFtLmlvL2F1dG9tYXRlZC1tb2RlcmF0aW9uL2RvY3MvYXV0b21vZF9jb25maWd1cmF0aW9uLz9xPXNlbWFudGljJTIwZmlsdGVycykgeW91IGNhbiBzZXQgdXAgcnVsZXMgZm9yIGJvdW5jaW5nIG1lc3NhZ2VzLlxuICAgKlxuICAgKiBJZiBhIG1lc3NhZ2UgaXMgYm91bmNlZCwgaXQgd2lsbCBiZSBlbWl0dGVkIHZpYSB0aGlzIGBPYnNlcnZhYmxlYC4gVGhlIGJ1aWx0LWluIFtgTWVzc2FnZUJvdW5jZVByb21wdGAgY29tcG9uZW50XSguLi8uLi9jb21wb25lbnRzL01lc3NhZ2VCb3VuY2VQcm9tcHRDb21wb25lbnQpIHdpbGwgZGlzcGxheSB0aGUgYm91bmNlIG9wdGlvbiB0byB0aGUgdXNlciBpZiBhIGJvdW5jZWQgbWVzc2FnZSBpcyBjbGlja2VkLlxuICAgKi9cbiAgYm91bmNlZE1lc3NhZ2UkOiBCZWhhdmlvclN1YmplY3Q8U3RyZWFtTWVzc2FnZTxUPiB8IHVuZGVmaW5lZD47XG4gIC8qKlxuICAgKiBUaGUgbGFzdCByZWFkIG1lc3NhZ2UgaWQgb2YgdGhlIGFjdGl2ZSBjaGFubmVsLCBpdCdzIHVzZWQgYnkgdGhlIG1lc3NhZ2UgbGlzdCBjb21wb25lbnQgdG8gZGlzcGxheSB1bnJlYWQgVUksIGFuZCBqdW1wIHRvIGxhdGVzdCByZWFkIG1lc3NhZ2VcbiAgICpcbiAgICogVGhpcyBwcm9wZXJ0eSBpc24ndCBhbHdheXMgdXBkYXRlZCwgcGxlYXNlIHVzZSBgY2hhbm5lbC5yZWFkYCB0byBkaXNwbGF5IHVwLXRvLWRhdGUgcmVhZCBpbmZvcm1hdGlvblxuICAgKi9cbiAgYWN0aXZlQ2hhbm5lbExhc3RSZWFkTWVzc2FnZUlkPzogc3RyaW5nO1xuICAvKipcbiAgICogVGhlIHVucmVhZCBjb3VudCBvZiB0aGUgYWN0aXZlIGNoYW5uZWwsIGl0J3MgdXNlZCBieSB0aGUgbWVzc2FnZSBsaXN0IGNvbXBvbmVudCB0byBkaXNwbGF5IHVucmVhZCBVSVxuICAgKlxuICAgKiBUaGlzIHByb3BlcnR5IGlzbid0IGFsd2F5cyB1cGRhdGVkLCBwbGVhc2UgdXNlIGBjaGFubmVsLnJlYWRgIHRvIGRpc3BsYXkgdXAtdG8tZGF0ZSByZWFkIGluZm9ybWF0aW9uXG4gICAqL1xuICBhY3RpdmVDaGFubmVsVW5yZWFkQ291bnQ/OiBudW1iZXI7XG4gIC8qKlxuICAgKiBDdXN0b20gZXZlbnQgaGFuZGxlciB0byBjYWxsIGlmIGEgbmV3IG1lc3NhZ2UgcmVjZWl2ZWQgZnJvbSBhIGNoYW5uZWwgdGhhdCBpcyBub3QgYmVpbmcgd2F0Y2hlZCwgcHJvdmlkZSBhbiBldmVudCBoYW5kbGVyIGlmIHlvdSB3YW50IHRvIG92ZXJyaWRlIHRoZSBbZGVmYXVsdCBjaGFubmVsIGxpc3Qgb3JkZXJpbmddKC4vQ2hhbm5lbFNlcnZpY2UubWR4LyNjaGFubmVscylcbiAgICovXG4gIGN1c3RvbU5ld01lc3NhZ2VOb3RpZmljYXRpb25IYW5kbGVyPzogKFxuICAgIGNsaWVudEV2ZW50OiBDbGllbnRFdmVudCxcbiAgICBjaGFubmVsTGlzdFNldHRlcjogKFxuICAgICAgY2hhbm5lbHM6IChDaGFubmVsPFQ+IHwgQ2hhbm5lbFJlc3BvbnNlPFQ+KVtdLFxuICAgICAgc2hvdWxkU3RvcFdhdGNoaW5nUmVtb3ZlZENoYW5uZWxzPzogYm9vbGVhblxuICAgICkgPT4gdm9pZFxuICApID0+IHZvaWQ7XG4gIC8qKlxuICAgKiBDdXN0b20gZXZlbnQgaGFuZGxlciB0byBjYWxsIHdoZW4gdGhlIHVzZXIgaXMgYWRkZWQgdG8gYSBjaGFubmVsLCBwcm92aWRlIGFuIGV2ZW50IGhhbmRsZXIgaWYgeW91IHdhbnQgdG8gb3ZlcnJpZGUgdGhlIFtkZWZhdWx0IGNoYW5uZWwgbGlzdCBvcmRlcmluZ10oLi9DaGFubmVsU2VydmljZS5tZHgvI2NoYW5uZWxzKVxuICAgKi9cbiAgY3VzdG9tQWRkZWRUb0NoYW5uZWxOb3RpZmljYXRpb25IYW5kbGVyPzogKFxuICAgIGNsaWVudEV2ZW50OiBDbGllbnRFdmVudCxcbiAgICBjaGFubmVsTGlzdFNldHRlcjogKFxuICAgICAgY2hhbm5lbHM6IChDaGFubmVsPFQ+IHwgQ2hhbm5lbFJlc3BvbnNlPFQ+KVtdLFxuICAgICAgc2hvdWxkU3RvcFdhdGNoaW5nUmVtb3ZlZENoYW5uZWxzPzogYm9vbGVhblxuICAgICkgPT4gdm9pZFxuICApID0+IHZvaWQ7XG4gIC8qKlxuICAgKiBDdXN0b20gZXZlbnQgaGFuZGxlciB0byBjYWxsIHdoZW4gdGhlIHVzZXIgaXMgcmVtb3ZlZCBmcm9tIGEgY2hhbm5lbCwgcHJvdmlkZSBhbiBldmVudCBoYW5kbGVyIGlmIHlvdSB3YW50IHRvIG92ZXJyaWRlIHRoZSBbZGVmYXVsdCBjaGFubmVsIGxpc3Qgb3JkZXJpbmddKC4vQ2hhbm5lbFNlcnZpY2UubWR4LyNjaGFubmVscylcbiAgICovXG4gIGN1c3RvbVJlbW92ZWRGcm9tQ2hhbm5lbE5vdGlmaWNhdGlvbkhhbmRsZXI/OiAoXG4gICAgY2xpZW50RXZlbnQ6IENsaWVudEV2ZW50LFxuICAgIGNoYW5uZWxMaXN0U2V0dGVyOiAoXG4gICAgICBjaGFubmVsczogKENoYW5uZWw8VD4gfCBDaGFubmVsUmVzcG9uc2U8VD4pW10sXG4gICAgICBzaG91bGRTdG9wV2F0Y2hpbmdSZW1vdmVkQ2hhbm5lbHM/OiBib29sZWFuXG4gICAgKSA9PiB2b2lkXG4gICkgPT4gdm9pZDtcbiAgLyoqXG4gICAqIEN1c3RvbSBldmVudCBoYW5kbGVyIHRvIGNhbGwgd2hlbiBhIGNoYW5uZWwgaXMgZGVsZXRlZCwgcHJvdmlkZSBhbiBldmVudCBoYW5kbGVyIGlmIHlvdSB3YW50IHRvIG92ZXJyaWRlIHRoZSBbZGVmYXVsdCBjaGFubmVsIGxpc3Qgb3JkZXJpbmddKC4vQ2hhbm5lbFNlcnZpY2UubWR4LyNjaGFubmVscylcbiAgICovXG4gIGN1c3RvbUNoYW5uZWxEZWxldGVkSGFuZGxlcj86IChcbiAgICBldmVudDogRXZlbnQsXG4gICAgY2hhbm5lbDogQ2hhbm5lbDxUPixcbiAgICBjaGFubmVsTGlzdFNldHRlcjogKFxuICAgICAgY2hhbm5lbHM6IChDaGFubmVsPFQ+IHwgQ2hhbm5lbFJlc3BvbnNlPFQ+KVtdLFxuICAgICAgc2hvdWxkU3RvcFdhdGNoaW5nUmVtb3ZlZENoYW5uZWxzPzogYm9vbGVhblxuICAgICkgPT4gdm9pZCxcbiAgICBtZXNzYWdlTGlzdFNldHRlcjogKG1lc3NhZ2VzOiBTdHJlYW1NZXNzYWdlPFQ+W10pID0+IHZvaWQsXG4gICAgdGhyZWFkTGlzdFNldHRlcjogKG1lc3NhZ2VzOiBTdHJlYW1NZXNzYWdlPFQ+W10pID0+IHZvaWQsXG4gICAgcGFyZW50TWVzc2FnZVNldHRlcjogKG1lc3NhZ2U6IFN0cmVhbU1lc3NhZ2U8VD4gfCB1bmRlZmluZWQpID0+IHZvaWRcbiAgKSA9PiB2b2lkO1xuICAvKipcbiAgICogQ3VzdG9tIGV2ZW50IGhhbmRsZXIgdG8gY2FsbCB3aGVuIGEgY2hhbm5lbCBpcyB1cGRhdGVkLCBwcm92aWRlIGFuIGV2ZW50IGhhbmRsZXIgaWYgeW91IHdhbnQgdG8gb3ZlcnJpZGUgdGhlIFtkZWZhdWx0IGNoYW5uZWwgbGlzdCBvcmRlcmluZ10oLi9DaGFubmVsU2VydmljZS5tZHgvI2NoYW5uZWxzKVxuICAgKi9cbiAgY3VzdG9tQ2hhbm5lbFVwZGF0ZWRIYW5kbGVyPzogKFxuICAgIGV2ZW50OiBFdmVudCxcbiAgICBjaGFubmVsOiBDaGFubmVsPFQ+LFxuICAgIGNoYW5uZWxMaXN0U2V0dGVyOiAoXG4gICAgICBjaGFubmVsczogKENoYW5uZWw8VD4gfCBDaGFubmVsUmVzcG9uc2U8VD4pW10sXG4gICAgICBzaG91bGRTdG9wV2F0Y2hpbmdSZW1vdmVkQ2hhbm5lbHM/OiBib29sZWFuXG4gICAgKSA9PiB2b2lkLFxuICAgIG1lc3NhZ2VMaXN0U2V0dGVyOiAobWVzc2FnZXM6IFN0cmVhbU1lc3NhZ2VbXSkgPT4gdm9pZCxcbiAgICB0aHJlYWRMaXN0U2V0dGVyOiAobWVzc2FnZXM6IFN0cmVhbU1lc3NhZ2VbXSkgPT4gdm9pZCxcbiAgICBwYXJlbnRNZXNzYWdlU2V0dGVyOiAobWVzc2FnZTogU3RyZWFtTWVzc2FnZSB8IHVuZGVmaW5lZCkgPT4gdm9pZFxuICApID0+IHZvaWQ7XG4gIC8qKlxuICAgKiBDdXN0b20gZXZlbnQgaGFuZGxlciB0byBjYWxsIHdoZW4gYSBjaGFubmVsIGlzIHRydW5jYXRlZCwgcHJvdmlkZSBhbiBldmVudCBoYW5kbGVyIGlmIHlvdSB3YW50IHRvIG92ZXJyaWRlIHRoZSBbZGVmYXVsdCBjaGFubmVsIGxpc3Qgb3JkZXJpbmddKC4vQ2hhbm5lbFNlcnZpY2UubWR4LyNjaGFubmVscylcbiAgICovXG4gIGN1c3RvbUNoYW5uZWxUcnVuY2F0ZWRIYW5kbGVyPzogKFxuICAgIGV2ZW50OiBFdmVudCxcbiAgICBjaGFubmVsOiBDaGFubmVsPFQ+LFxuICAgIGNoYW5uZWxMaXN0U2V0dGVyOiAoXG4gICAgICBjaGFubmVsczogKENoYW5uZWw8VD4gfCBDaGFubmVsUmVzcG9uc2U8VD4pW10sXG4gICAgICBzaG91bGRTdG9wV2F0Y2hpbmdSZW1vdmVkQ2hhbm5lbHM/OiBib29sZWFuXG4gICAgKSA9PiB2b2lkLFxuICAgIG1lc3NhZ2VMaXN0U2V0dGVyOiAobWVzc2FnZXM6IFN0cmVhbU1lc3NhZ2U8VD5bXSkgPT4gdm9pZCxcbiAgICB0aHJlYWRMaXN0U2V0dGVyOiAobWVzc2FnZXM6IFN0cmVhbU1lc3NhZ2U8VD5bXSkgPT4gdm9pZCxcbiAgICBwYXJlbnRNZXNzYWdlU2V0dGVyOiAobWVzc2FnZTogU3RyZWFtTWVzc2FnZTxUPiB8IHVuZGVmaW5lZCkgPT4gdm9pZFxuICApID0+IHZvaWQ7XG4gIC8qKlxuICAgKiBDdXN0b20gZXZlbnQgaGFuZGxlciB0byBjYWxsIHdoZW4gYSBjaGFubmVsIGJlY29tZXMgaGlkZGVuLCBwcm92aWRlIGFuIGV2ZW50IGhhbmRsZXIgaWYgeW91IHdhbnQgdG8gb3ZlcnJpZGUgdGhlIFtkZWZhdWx0IGNoYW5uZWwgbGlzdCBvcmRlcmluZ10oLi9DaGFubmVsU2VydmljZS5tZHgvI2NoYW5uZWxzKVxuICAgKi9cbiAgY3VzdG9tQ2hhbm5lbEhpZGRlbkhhbmRsZXI/OiAoXG4gICAgZXZlbnQ6IEV2ZW50LFxuICAgIGNoYW5uZWw6IENoYW5uZWw8VD4sXG4gICAgY2hhbm5lbExpc3RTZXR0ZXI6IChcbiAgICAgIGNoYW5uZWxzOiAoQ2hhbm5lbDxUPiB8IENoYW5uZWxSZXNwb25zZTxUPilbXSxcbiAgICAgIHNob3VsZFN0b3BXYXRjaGluZ1JlbW92ZWRDaGFubmVscz86IGJvb2xlYW5cbiAgICApID0+IHZvaWQsXG4gICAgbWVzc2FnZUxpc3RTZXR0ZXI6IChtZXNzYWdlczogU3RyZWFtTWVzc2FnZTxUPltdKSA9PiB2b2lkLFxuICAgIHRocmVhZExpc3RTZXR0ZXI6IChtZXNzYWdlczogU3RyZWFtTWVzc2FnZTxUPltdKSA9PiB2b2lkLFxuICAgIHBhcmVudE1lc3NhZ2VTZXR0ZXI6IChtZXNzYWdlOiBTdHJlYW1NZXNzYWdlPFQ+IHwgdW5kZWZpbmVkKSA9PiB2b2lkXG4gICkgPT4gdm9pZDtcbiAgLyoqXG4gICAqIEN1c3RvbSBldmVudCBoYW5kbGVyIHRvIGNhbGwgd2hlbiBhIGNoYW5uZWwgYmVjb21lcyB2aXNpYmxlLCBwcm92aWRlIGFuIGV2ZW50IGhhbmRsZXIgaWYgeW91IHdhbnQgdG8gb3ZlcnJpZGUgdGhlIFtkZWZhdWx0IGNoYW5uZWwgbGlzdCBvcmRlcmluZ10oLi9DaGFubmVsU2VydmljZS5tZHgvI2NoYW5uZWxzKVxuICAgKi9cbiAgY3VzdG9tQ2hhbm5lbFZpc2libGVIYW5kbGVyPzogKFxuICAgIGV2ZW50OiBFdmVudCxcbiAgICBjaGFubmVsOiBDaGFubmVsPFQ+LFxuICAgIGNoYW5uZWxMaXN0U2V0dGVyOiAoXG4gICAgICBjaGFubmVsczogKENoYW5uZWw8VD4gfCBDaGFubmVsUmVzcG9uc2U8VD4pW10sXG4gICAgICBzaG91bGRTdG9wV2F0Y2hpbmdSZW1vdmVkQ2hhbm5lbHM/OiBib29sZWFuXG4gICAgKSA9PiB2b2lkLFxuICAgIG1lc3NhZ2VMaXN0U2V0dGVyOiAobWVzc2FnZXM6IFN0cmVhbU1lc3NhZ2U8VD5bXSkgPT4gdm9pZCxcbiAgICB0aHJlYWRMaXN0U2V0dGVyOiAobWVzc2FnZXM6IFN0cmVhbU1lc3NhZ2U8VD5bXSkgPT4gdm9pZCxcbiAgICBwYXJlbnRNZXNzYWdlU2V0dGVyOiAobWVzc2FnZTogU3RyZWFtTWVzc2FnZTxUPiB8IHVuZGVmaW5lZCkgPT4gdm9pZFxuICApID0+IHZvaWQ7XG4gIC8qKlxuICAgKiBDdXN0b20gZXZlbnQgaGFuZGxlciB0byBjYWxsIGlmIGEgbmV3IG1lc3NhZ2UgcmVjZWl2ZWQgZnJvbSBhIGNoYW5uZWwgdGhhdCBpcyBiZWluZyB3YXRjaGVkLCBwcm92aWRlIGFuIGV2ZW50IGhhbmRsZXIgaWYgeW91IHdhbnQgdG8gb3ZlcnJpZGUgdGhlIFtkZWZhdWx0IGNoYW5uZWwgbGlzdCBvcmRlcmluZ10oLi9DaGFubmVsU2VydmljZS5tZHgvI2NoYW5uZWxzKVxuICAgKi9cbiAgY3VzdG9tTmV3TWVzc2FnZUhhbmRsZXI/OiAoXG4gICAgZXZlbnQ6IEV2ZW50LFxuICAgIGNoYW5uZWw6IENoYW5uZWw8VD4sXG4gICAgY2hhbm5lbExpc3RTZXR0ZXI6IChcbiAgICAgIGNoYW5uZWxzOiAoQ2hhbm5lbDxUPiB8IENoYW5uZWxSZXNwb25zZTxUPilbXSxcbiAgICAgIHNob3VsZFN0b3BXYXRjaGluZ1JlbW92ZWRDaGFubmVscz86IGJvb2xlYW5cbiAgICApID0+IHZvaWQsXG4gICAgbWVzc2FnZUxpc3RTZXR0ZXI6IChtZXNzYWdlczogU3RyZWFtTWVzc2FnZTxUPltdKSA9PiB2b2lkLFxuICAgIHRocmVhZExpc3RTZXR0ZXI6IChtZXNzYWdlczogU3RyZWFtTWVzc2FnZTxUPltdKSA9PiB2b2lkLFxuICAgIHBhcmVudE1lc3NhZ2VTZXR0ZXI6IChtZXNzYWdlOiBTdHJlYW1NZXNzYWdlPFQ+IHwgdW5kZWZpbmVkKSA9PiB2b2lkXG4gICkgPT4gdm9pZDtcbiAgLyoqXG4gICAqIFlvdSBjYW4gb3ZlcnJpZGUgdGhlIGRlZmF1bHQgZmlsZSB1cGxvYWQgcmVxdWVzdCAtIHlvdSBjYW4gdXNlIHRoaXMgdG8gdXBsb2FkIGZpbGVzIHRvIHlvdXIgb3duIENETlxuICAgKi9cbiAgY3VzdG9tRmlsZVVwbG9hZFJlcXVlc3Q/OiAoXG4gICAgZmlsZTogRmlsZSxcbiAgICBjaGFubmVsOiBDaGFubmVsPFQ+XG4gICkgPT4gUHJvbWlzZTx7IGZpbGU6IHN0cmluZyB9PjtcbiAgLyoqXG4gICAqIFlvdSBjYW4gb3ZlcnJpZGUgdGhlIGRlZmF1bHQgaW1hZ2UgdXBsb2FkIHJlcXVlc3QgLSB5b3UgY2FuIHVzZSB0aGlzIHRvIHVwbG9hZCBpbWFnZXMgdG8geW91ciBvd24gQ0ROXG4gICAqL1xuICBjdXN0b21JbWFnZVVwbG9hZFJlcXVlc3Q/OiAoXG4gICAgZmlsZTogRmlsZSxcbiAgICBjaGFubmVsOiBDaGFubmVsPFQ+XG4gICkgPT4gUHJvbWlzZTx7IGZpbGU6IHN0cmluZyB9PjtcbiAgLyoqXG4gICAqIFlvdSBjYW4gb3ZlcnJpZGUgdGhlIGRlZmF1bHQgZmlsZSBkZWxldGUgcmVxdWVzdCAtIG92ZXJyaWRlIHRoaXMgaWYgeW91IHVzZSB5b3VyIG93biBDRE5cbiAgICovXG4gIGN1c3RvbUZpbGVEZWxldGVSZXF1ZXN0PzogKHVybDogc3RyaW5nLCBjaGFubmVsOiBDaGFubmVsPFQ+KSA9PiBQcm9taXNlPHZvaWQ+O1xuICAvKipcbiAgICogWW91IGNhbiBvdmVycmlkZSB0aGUgZGVmYXVsdCBpbWFnZSBkZWxldGUgcmVxdWVzdCAtIG92ZXJyaWRlIHRoaXMgaWYgeW91IHVzZSB5b3VyIG93biBDRE5cbiAgICovXG4gIGN1c3RvbUltYWdlRGVsZXRlUmVxdWVzdD86IChcbiAgICB1cmw6IHN0cmluZyxcbiAgICBjaGFubmVsOiBDaGFubmVsPFQ+XG4gICkgPT4gUHJvbWlzZTx2b2lkPjtcbiAgLyoqXG4gICAqIFRoZSBwcm92aWRlZCBtZXRob2Qgd2lsbCBiZSBjYWxsZWQgYmVmb3JlIGRlbGV0aW5nIGEgbWVzc2FnZS4gSWYgdGhlIHJldHVybmVkIFByb21pc2UgcmVzb2x2ZXMgdG8gYHRydWVgIHRvIGRlbGV0aW9uIHdpbGwgZ28gYWhlYWQuIElmIGBmYWxzZWAgaXMgcmV0dXJuZWQsIHRoZSBtZXNzYWdlIHdvbid0IGJlIGRlbGV0ZWQuXG4gICAqL1xuICBtZXNzYWdlRGVsZXRlQ29uZmlybWF0aW9uSGFuZGxlcj86IChcbiAgICBtZXNzYWdlOiBTdHJlYW1NZXNzYWdlPFQ+XG4gICkgPT4gUHJvbWlzZTxib29sZWFuPjtcbiAgLyoqXG4gICAqIFRoZSBwcm92aWRlZCBtZXRob2Qgd2lsbCBiZSBjYWxsZWQgYmVmb3JlIGEgbmV3IG1lc3NhZ2UgaXMgc2VudCB0byBTdHJlYW0ncyBBUEkuIFlvdSBjYW4gdXNlIHRoaXMgaG9vayB0byB0cmFuZnJvbSBvciBlbnJpY2ggdGhlIG1lc3NhZ2UgYmVpbmcgc2VudC5cbiAgICovXG4gIGJlZm9yZVNlbmRNZXNzYWdlPzogKFxuICAgIGlucHV0OiBNZXNzYWdlSW5wdXQ8VD5cbiAgKSA9PiBNZXNzYWdlSW5wdXQ8VD4gfCBQcm9taXNlPE1lc3NhZ2VJbnB1dDxUPj47XG4gIC8qKlxuICAgKiBUaGUgcHJvdmlkZWQgbWV0aG9kIHdpbGwgYmUgY2FsbGVkIGJlZm9yZSBhIG1lc3NhZ2UgaXMgc2VudCB0byBTdHJlYW0ncyBBUEkgZm9yIHVwZGF0ZS4gWW91IGNhbiB1c2UgdGhpcyBob29rIHRvIHRyYW5mcm9tIG9yIGVucmljaCB0aGUgbWVzc2FnZSBiZWluZyB1cGRhdGVkLlxuICAgKi9cbiAgYmVmb3JlVXBkYXRlTWVzc2FnZT86IChcbiAgICBtZXNzYWdlOiBTdHJlYW1NZXNzYWdlPFQ+XG4gICkgPT4gU3RyZWFtTWVzc2FnZTxUPiB8IFByb21pc2U8U3RyZWFtTWVzc2FnZTxUPj47XG4gIC8qKlxuICAgKiBCeSBkZWZhdWx0IHRoZSBTREsgdXNlcyBhbiBvZmZzZXQgYmFzZWQgcGFnaW5hdGlvbiwgeW91IGNhbiBjaGFuZ2UvZXh0ZW5kIHRoaXMgYnkgcHJvdmlkaW5nIHlvdXIgb3duIGN1c3RvbSBwYWdpbmF0b3IgbWV0aG9kLlxuICAgKlxuICAgKiBUaGUgbWV0aG9kIHdpbGwgYmUgY2FsbGVkIHdpdGggdGhlIHJlc3VsdCBvZiB0aGUgbGF0ZXN0IGNoYW5uZWwgcXVlcnkuXG4gICAqXG4gICAqIFlvdSBjYW4gcmV0dXJuIGVpdGhlciBhbiBvZmZzZXQsIG9yIGEgZmlsdGVyIHVzaW5nIHRoZSBbYCRsdGVgL2AkZ3RlYCBvcGVyYXRvcl0oaHR0cHM6Ly9nZXRzdHJlYW0uaW8vY2hhdC9kb2NzL2phdmFzY3JpcHQvcXVlcnlfc3ludGF4X29wZXJhdG9ycy8pLiBJZiB5b3UgcmV0dXJuIGEgZmlsdGVyLCBpdCB3aWxsIGJlIG1lcmdlZCB3aXRoIHRoZSBmaWx0ZXIgcHJvdmlkZWQgZm9yIHRoZSBgaW5pdGAgbWV0aG9kLlxuICAgKi9cbiAgY3VzdG9tUGFnaW5hdG9yPzogKGNoYW5uZWxRdWVyeVJlc3VsdDogQ2hhbm5lbDxUPltdKSA9PiBOZXh0UGFnZUNvbmZpZ3VyYXRpb247XG4gIC8qKlxuICAgKiBpbnRlcm5hbFxuICAgKi9cbiAgc3RhdGljIHJlYWRvbmx5IE1BWF9NRVNTQUdFX1JFQUNUSU9OU19UT19GRVRDSCA9IDEyMDA7XG4gIHByaXZhdGUgY2hhbm5lbHNTdWJqZWN0ID0gbmV3IEJlaGF2aW9yU3ViamVjdDxDaGFubmVsPFQ+W10gfCB1bmRlZmluZWQ+KFxuICAgIHVuZGVmaW5lZFxuICApO1xuICBwcml2YXRlIGFjdGl2ZUNoYW5uZWxTdWJqZWN0ID0gbmV3IEJlaGF2aW9yU3ViamVjdDxDaGFubmVsPFQ+IHwgdW5kZWZpbmVkPihcbiAgICB1bmRlZmluZWRcbiAgKTtcbiAgcHJpdmF0ZSBhY3RpdmVDaGFubmVsTWVzc2FnZXNTdWJqZWN0ID0gbmV3IEJlaGF2aW9yU3ViamVjdDxcbiAgICAoU3RyZWFtTWVzc2FnZTxUPiB8IE1lc3NhZ2VSZXNwb25zZTxUPiB8IEZvcm1hdE1lc3NhZ2VSZXNwb25zZTxUPilbXVxuICA+KFtdKTtcbiAgcHJpdmF0ZSBhY3RpdmVDaGFubmVsUGlubmVkTWVzc2FnZXNTdWJqZWN0ID0gbmV3IEJlaGF2aW9yU3ViamVjdDxcbiAgICBTdHJlYW1NZXNzYWdlW11cbiAgPihbXSk7XG4gIHByaXZhdGUgaGFzTW9yZUNoYW5uZWxzU3ViamVjdCA9IG5ldyBSZXBsYXlTdWJqZWN0PGJvb2xlYW4+KDEpO1xuICBwcml2YXRlIGFjdGl2ZUNoYW5uZWxTdWJzY3JpcHRpb25zOiB7IHVuc3Vic2NyaWJlOiAoKSA9PiB2b2lkIH1bXSA9IFtdO1xuICBwcml2YXRlIGNoYW5uZWxTdWJzY3JpcHRpb25zOiB7IFtrZXk6IHN0cmluZ106ICgpID0+IHZvaWQgfSA9IHt9O1xuICBwcml2YXRlIGFjdGl2ZVBhcmVudE1lc3NhZ2VJZFN1YmplY3QgPSBuZXcgQmVoYXZpb3JTdWJqZWN0PFxuICAgIHN0cmluZyB8IHVuZGVmaW5lZFxuICA+KHVuZGVmaW5lZCk7XG4gIHByaXZhdGUgYWN0aXZlVGhyZWFkTWVzc2FnZXNTdWJqZWN0ID0gbmV3IEJlaGF2aW9yU3ViamVjdDxcbiAgICAoU3RyZWFtTWVzc2FnZTxUPiB8IE1lc3NhZ2VSZXNwb25zZTxUPiB8IEZvcm1hdE1lc3NhZ2VSZXNwb25zZTxUPilbXVxuICA+KFtdKTtcbiAgcHJpdmF0ZSBqdW1wVG9NZXNzYWdlU3ViamVjdCA9IG5ldyBCZWhhdmlvclN1YmplY3Q8e1xuICAgIGlkPzogc3RyaW5nO1xuICAgIHBhcmVudElkPzogc3RyaW5nO1xuICB9Pih7IGlkOiB1bmRlZmluZWQsIHBhcmVudElkOiB1bmRlZmluZWQgfSk7XG4gIHByaXZhdGUgbGF0ZXN0TWVzc2FnZURhdGVCeVVzZXJCeUNoYW5uZWxzU3ViamVjdCA9IG5ldyBCZWhhdmlvclN1YmplY3Q8e1xuICAgIFtrZXk6IHN0cmluZ106IERhdGU7XG4gIH0+KHt9KTtcbiAgcHJpdmF0ZSBmaWx0ZXJzOiBDaGFubmVsRmlsdGVyczxUPiB8IHVuZGVmaW5lZDtcbiAgcHJpdmF0ZSBzb3J0OiBDaGFubmVsU29ydDxUPiB8IHVuZGVmaW5lZDtcbiAgcHJpdmF0ZSBvcHRpb25zOlxuICAgIHwgKENoYW5uZWxPcHRpb25zICYgeyBrZWVwQWxpdmVDaGFubmVscyRPbkVycm9yPzogYm9vbGVhbiB9KVxuICAgIHwgdW5kZWZpbmVkO1xuICBwcml2YXRlIHJlYWRvbmx5IG1lc3NhZ2VQYWdlU2l6ZSA9IDI1O1xuICBwcml2YXRlIG1lc3NhZ2VUb1F1b3RlU3ViamVjdCA9IG5ldyBCZWhhdmlvclN1YmplY3Q8XG4gICAgU3RyZWFtTWVzc2FnZTxUPiB8IHVuZGVmaW5lZFxuICA+KHVuZGVmaW5lZCk7XG4gIHByaXZhdGUgdXNlcnNUeXBpbmdJbkNoYW5uZWxTdWJqZWN0ID0gbmV3IEJlaGF2aW9yU3ViamVjdDxVc2VyUmVzcG9uc2U8VD5bXT4oXG4gICAgW11cbiAgKTtcbiAgcHJpdmF0ZSB1c2Vyc1R5cGluZ0luVGhyZWFkU3ViamVjdCA9IG5ldyBCZWhhdmlvclN1YmplY3Q8VXNlclJlc3BvbnNlPFQ+W10+KFxuICAgIFtdXG4gICk7XG4gIHByaXZhdGUgX3Nob3VsZE1hcmtBY3RpdmVDaGFubmVsQXNSZWFkID0gdHJ1ZTtcbiAgcHJpdmF0ZSBzaG91bGRTZXRBY3RpdmVDaGFubmVsOiBib29sZWFuIHwgdW5kZWZpbmVkO1xuICBwcml2YXRlIGNsaWVudEV2ZW50c1N1YnNjcmlwdGlvbjogU3Vic2NyaXB0aW9uIHwgdW5kZWZpbmVkO1xuICBwcml2YXRlIGlzU3RhdGVSZWNvdmVyeUluUHJvZ3Jlc3MgPSBmYWxzZTtcbiAgcHJpdmF0ZSBjaGFubmVsUXVlcnlTdGF0ZVN1YmplY3QgPSBuZXcgQmVoYXZpb3JTdWJqZWN0PFxuICAgIENoYW5uZWxRdWVyeVN0YXRlIHwgdW5kZWZpbmVkXG4gID4odW5kZWZpbmVkKTtcblxuICBwcml2YXRlIGNoYW5uZWxMaXN0U2V0dGVyID0gKFxuICAgIGNoYW5uZWxzOiAoQ2hhbm5lbDxUPiB8IENoYW5uZWxSZXNwb25zZTxUPilbXSxcbiAgICBzaG91bGRTdG9wV2F0Y2hpbmdSZW1vdmVkQ2hhbm5lbHMgPSB0cnVlXG4gICkgPT4ge1xuICAgIGNvbnN0IGN1cnJlbnRDaGFubmVscyA9IHRoaXMuY2hhbm5lbHNTdWJqZWN0LmdldFZhbHVlKCkgfHwgW107XG4gICAgY29uc3QgbmV3Q2hhbm5lbHMgPSBjaGFubmVscy5maWx0ZXIoXG4gICAgICAoYykgPT4gIWN1cnJlbnRDaGFubmVscy5maW5kKChjaGFubmVsKSA9PiBjaGFubmVsLmNpZCA9PT0gYy5jaWQpXG4gICAgKTtcbiAgICBjb25zdCBkZWxldGVkQ2hhbm5lbHMgPSBjdXJyZW50Q2hhbm5lbHMuZmlsdGVyKFxuICAgICAgKGMpID0+ICFjaGFubmVscz8uZmluZCgoY2hhbm5lbCkgPT4gY2hhbm5lbC5jaWQgPT09IGMuY2lkKVxuICAgICk7XG4gICAgdm9pZCB0aGlzLmFkZENoYW5uZWxzRnJvbU5vdGlmaWNhdGlvbihuZXdDaGFubmVscyBhcyBDaGFubmVsUmVzcG9uc2U8VD5bXSk7XG4gICAgdGhpcy5yZW1vdmVDaGFubmVsc0Zyb21DaGFubmVsTGlzdChcbiAgICAgIGRlbGV0ZWRDaGFubmVscy5tYXAoKGMpID0+IGMuY2lkKSxcbiAgICAgIHNob3VsZFN0b3BXYXRjaGluZ1JlbW92ZWRDaGFubmVsc1xuICAgICk7XG4gIH07XG5cbiAgcHJpdmF0ZSBtZXNzYWdlTGlzdFNldHRlciA9IChtZXNzYWdlczogU3RyZWFtTWVzc2FnZTxUPltdKSA9PiB7XG4gICAgdGhpcy5hY3RpdmVDaGFubmVsTWVzc2FnZXNTdWJqZWN0Lm5leHQobWVzc2FnZXMpO1xuICB9O1xuXG4gIHByaXZhdGUgdGhyZWFkTGlzdFNldHRlciA9IChtZXNzYWdlczogU3RyZWFtTWVzc2FnZTxUPltdKSA9PiB7XG4gICAgdGhpcy5hY3RpdmVUaHJlYWRNZXNzYWdlc1N1YmplY3QubmV4dChtZXNzYWdlcyk7XG4gIH07XG5cbiAgcHJpdmF0ZSBwYXJlbnRNZXNzYWdlU2V0dGVyID0gKG1lc3NhZ2U6IFN0cmVhbU1lc3NhZ2U8VD4gfCB1bmRlZmluZWQpID0+IHtcbiAgICB0aGlzLmFjdGl2ZVBhcmVudE1lc3NhZ2VJZFN1YmplY3QubmV4dChtZXNzYWdlPy5pZCk7XG4gIH07XG4gIHByaXZhdGUgZGlzbWlzc0Vycm9yTm90aWZpY2F0aW9uPzogRnVuY3Rpb247XG4gIHByaXZhdGUgbmV4dFBhZ2VDb25maWd1cmF0aW9uPzogTmV4dFBhZ2VDb25maWd1cmF0aW9uO1xuICBwcml2YXRlIGFyZVJlYWRFdmVudHNQYXVzZWQgPSBmYWxzZTtcblxuICBjb25zdHJ1Y3RvcihcbiAgICBwcml2YXRlIGNoYXRDbGllbnRTZXJ2aWNlOiBDaGF0Q2xpZW50U2VydmljZTxUPixcbiAgICBwcml2YXRlIG5nWm9uZTogTmdab25lLFxuICAgIHByaXZhdGUgbm90aWZpY2F0aW9uU2VydmljZTogTm90aWZpY2F0aW9uU2VydmljZVxuICApIHtcbiAgICB0aGlzLmNoYW5uZWxzJCA9IHRoaXMuY2hhbm5lbHNTdWJqZWN0LmFzT2JzZXJ2YWJsZSgpLnBpcGUoc2hhcmVSZXBsYXkoMSkpO1xuICAgIHRoaXMuYWN0aXZlQ2hhbm5lbCQgPSB0aGlzLmFjdGl2ZUNoYW5uZWxTdWJqZWN0XG4gICAgICAuYXNPYnNlcnZhYmxlKClcbiAgICAgIC5waXBlKHNoYXJlUmVwbGF5KDEpKTtcbiAgICB0aGlzLmFjdGl2ZUNoYW5uZWxNZXNzYWdlcyQgPSB0aGlzLmFjdGl2ZUNoYW5uZWxNZXNzYWdlc1N1YmplY3QucGlwZShcbiAgICAgIG1hcCgobWVzc2FnZXMpID0+IHtcbiAgICAgICAgY29uc3QgY2hhbm5lbCA9IHRoaXMuYWN0aXZlQ2hhbm5lbFN1YmplY3QuZ2V0VmFsdWUoKSE7XG4gICAgICAgIHJldHVybiBtZXNzYWdlcy5tYXAoKG1lc3NhZ2UpID0+XG4gICAgICAgICAgdGhpcy50cmFuc2Zvcm1Ub1N0cmVhbU1lc3NhZ2UobWVzc2FnZSwgY2hhbm5lbClcbiAgICAgICAgKTtcbiAgICAgIH0pLFxuICAgICAgc2hhcmVSZXBsYXkoMSlcbiAgICApO1xuICAgIHRoaXMuYm91bmNlZE1lc3NhZ2UkID0gbmV3IEJlaGF2aW9yU3ViamVjdDxTdHJlYW1NZXNzYWdlPFQ+IHwgdW5kZWZpbmVkPihcbiAgICAgIHVuZGVmaW5lZFxuICAgICk7XG4gICAgdGhpcy5oYXNNb3JlQ2hhbm5lbHMkID0gdGhpcy5oYXNNb3JlQ2hhbm5lbHNTdWJqZWN0XG4gICAgICAuYXNPYnNlcnZhYmxlKClcbiAgICAgIC5waXBlKHNoYXJlUmVwbGF5KDEpKTtcbiAgICB0aGlzLmFjdGl2ZVBhcmVudE1lc3NhZ2VJZCQgPSB0aGlzLmFjdGl2ZVBhcmVudE1lc3NhZ2VJZFN1YmplY3RcbiAgICAgIC5hc09ic2VydmFibGUoKVxuICAgICAgLnBpcGUoc2hhcmVSZXBsYXkoMSkpO1xuICAgIHRoaXMuYWN0aXZlVGhyZWFkTWVzc2FnZXMkID0gdGhpcy5hY3RpdmVUaHJlYWRNZXNzYWdlc1N1YmplY3QucGlwZShcbiAgICAgIG1hcCgobWVzc2FnZXMpID0+IHtcbiAgICAgICAgY29uc3QgY2hhbm5lbCA9IHRoaXMuYWN0aXZlQ2hhbm5lbFN1YmplY3QuZ2V0VmFsdWUoKSE7XG4gICAgICAgIHJldHVybiBtZXNzYWdlcy5tYXAoKG1lc3NhZ2UpID0+XG4gICAgICAgICAgdGhpcy50cmFuc2Zvcm1Ub1N0cmVhbU1lc3NhZ2UobWVzc2FnZSwgY2hhbm5lbClcbiAgICAgICAgKTtcbiAgICAgIH0pLFxuICAgICAgc2hhcmVSZXBsYXkoMSlcbiAgICApO1xuICAgIHRoaXMuYWN0aXZlUGFyZW50TWVzc2FnZSQgPSBjb21iaW5lTGF0ZXN0KFtcbiAgICAgIHRoaXMuYWN0aXZlQ2hhbm5lbE1lc3NhZ2VzJCxcbiAgICAgIHRoaXMuYWN0aXZlUGFyZW50TWVzc2FnZUlkJCxcbiAgICBdKS5waXBlKFxuICAgICAgbWFwKFxuICAgICAgICAoW21lc3NhZ2VzLCBwYXJlbnRNZXNzYWdlSWRdOiBbXG4gICAgICAgICAgU3RyZWFtTWVzc2FnZVtdLFxuICAgICAgICAgIHN0cmluZyB8IHVuZGVmaW5lZFxuICAgICAgICBdKSA9PiB7XG4gICAgICAgICAgaWYgKCFwYXJlbnRNZXNzYWdlSWQpIHtcbiAgICAgICAgICAgIHJldHVybiB1bmRlZmluZWQ7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGNvbnN0IG1lc3NhZ2UgPSBtZXNzYWdlcy5maW5kKChtKSA9PiBtLmlkID09PSBwYXJlbnRNZXNzYWdlSWQpO1xuICAgICAgICAgICAgaWYgKCFtZXNzYWdlKSB7XG4gICAgICAgICAgICAgIHZvaWQgdGhpcy5zZXRBc0FjdGl2ZVBhcmVudE1lc3NhZ2UodW5kZWZpbmVkKTtcbiAgICAgICAgICAgICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgIHJldHVybiBtZXNzYWdlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgKSxcbiAgICAgIHNoYXJlUmVwbGF5KDEpXG4gICAgKTtcbiAgICB0aGlzLm1lc3NhZ2VUb1F1b3RlJCA9IHRoaXMubWVzc2FnZVRvUXVvdGVTdWJqZWN0XG4gICAgICAuYXNPYnNlcnZhYmxlKClcbiAgICAgIC5waXBlKHNoYXJlUmVwbGF5KDEpKTtcbiAgICB0aGlzLmp1bXBUb01lc3NhZ2UkID0gdGhpcy5qdW1wVG9NZXNzYWdlU3ViamVjdFxuICAgICAgLmFzT2JzZXJ2YWJsZSgpXG4gICAgICAucGlwZShzaGFyZVJlcGxheSgxKSk7XG5cbiAgICB0aGlzLnVzZXJzVHlwaW5nSW5DaGFubmVsJCA9IHRoaXMudXNlcnNUeXBpbmdJbkNoYW5uZWxTdWJqZWN0XG4gICAgICAuYXNPYnNlcnZhYmxlKClcbiAgICAgIC5waXBlKHNoYXJlUmVwbGF5KDEpKTtcbiAgICB0aGlzLnVzZXJzVHlwaW5nSW5UaHJlYWQkID0gdGhpcy51c2Vyc1R5cGluZ0luVGhyZWFkU3ViamVjdFxuICAgICAgLmFzT2JzZXJ2YWJsZSgpXG4gICAgICAucGlwZShzaGFyZVJlcGxheSgxKSk7XG4gICAgdGhpcy5sYXRlc3RNZXNzYWdlRGF0ZUJ5VXNlckJ5Q2hhbm5lbHMkID1cbiAgICAgIHRoaXMubGF0ZXN0TWVzc2FnZURhdGVCeVVzZXJCeUNoYW5uZWxzU3ViamVjdFxuICAgICAgICAuYXNPYnNlcnZhYmxlKClcbiAgICAgICAgLnBpcGUoc2hhcmVSZXBsYXkoMSkpO1xuICAgIHRoaXMuYWN0aXZlQ2hhbm5lbFBpbm5lZE1lc3NhZ2VzJCA9IHRoaXMuYWN0aXZlQ2hhbm5lbFBpbm5lZE1lc3NhZ2VzU3ViamVjdFxuICAgICAgLmFzT2JzZXJ2YWJsZSgpXG4gICAgICAucGlwZShzaGFyZVJlcGxheSgxKSk7XG4gICAgdGhpcy5jaGFubmVsUXVlcnlTdGF0ZSQgPSB0aGlzLmNoYW5uZWxRdWVyeVN0YXRlU3ViamVjdFxuICAgICAgLmFzT2JzZXJ2YWJsZSgpXG4gICAgICAucGlwZShzaGFyZVJlcGxheSgxKSk7XG4gIH1cblxuICAvKipcbiAgICogSWYgc2V0IHRvIGZhbHNlLCByZWFkIGV2ZW50cyB3b24ndCBiZSBzZW50IGFzIG5ldyBtZXNzYWdlcyBhcmUgcmVjZWl2ZWQuIElmIHNldCB0byB0cnVlIGFjdGl2ZSBjaGFubmVsIChpZiBhbnkpIHdpbGwgaW1tZWRpYXRlbHkgYmUgbWFya2VkIGFzIHJlYWQuXG4gICAqL1xuICBnZXQgc2hvdWxkTWFya0FjdGl2ZUNoYW5uZWxBc1JlYWQoKSB7XG4gICAgcmV0dXJuIHRoaXMuX3Nob3VsZE1hcmtBY3RpdmVDaGFubmVsQXNSZWFkO1xuICB9XG5cbiAgLyoqXG4gICAqIElmIHNldCB0byBmYWxzZSwgcmVhZCBldmVudHMgd29uJ3QgYmUgc2VudCBhcyBuZXcgbWVzc2FnZXMgYXJlIHJlY2VpdmVkLiBJZiBzZXQgdG8gdHJ1ZSBhY3RpdmUgY2hhbm5lbCAoaWYgYW55KSB3aWxsIGltbWVkaWF0ZWx5IGJlIG1hcmtlZCBhcyByZWFkLlxuICAgKi9cbiAgc2V0IHNob3VsZE1hcmtBY3RpdmVDaGFubmVsQXNSZWFkKHNob3VsZE1hcmtBY3RpdmVDaGFubmVsQXNSZWFkOiBib29sZWFuKSB7XG4gICAgaWYgKCF0aGlzLl9zaG91bGRNYXJrQWN0aXZlQ2hhbm5lbEFzUmVhZCAmJiBzaG91bGRNYXJrQWN0aXZlQ2hhbm5lbEFzUmVhZCkge1xuICAgICAgY29uc3QgYWN0aXZlQ2hhbm5lbCA9IHRoaXMuYWN0aXZlQ2hhbm5lbFN1YmplY3QuZ2V0VmFsdWUoKTtcbiAgICAgIGlmIChhY3RpdmVDaGFubmVsICYmIHRoaXMuY2FuU2VuZFJlYWRFdmVudHMpIHtcbiAgICAgICAgdm9pZCBhY3RpdmVDaGFubmVsLm1hcmtSZWFkKCk7XG4gICAgICB9XG4gICAgfVxuICAgIHRoaXMuX3Nob3VsZE1hcmtBY3RpdmVDaGFubmVsQXNSZWFkID0gc2hvdWxkTWFya0FjdGl2ZUNoYW5uZWxBc1JlYWQ7XG4gIH1cblxuICAvKipcbiAgICogU2V0cyB0aGUgZ2l2ZW4gYGNoYW5uZWxgIGFzIGFjdGl2ZSBhbmQgbWFya3MgaXQgYXMgcmVhZC5cbiAgICogSWYgdGhlIGNoYW5uZWwgd2Fzbid0IHByZXZpb3VzbHkgcGFydCBvZiB0aGUgY2hhbm5lbCwgaXQgd2lsbCBiZSBhZGRlZCB0byB0aGUgYmVnaW5uaW5nIG9mIHRoZSBsaXN0LlxuICAgKlxuICAgKiBAcGFyYW0gY2hhbm5lbFxuICAgKi9cbiAgc2V0QXNBY3RpdmVDaGFubmVsKGNoYW5uZWw6IENoYW5uZWw8VD4pIHtcbiAgICBjb25zdCBwcmV2QWN0aXZlQ2hhbm5lbCA9IHRoaXMuYWN0aXZlQ2hhbm5lbFN1YmplY3QuZ2V0VmFsdWUoKTtcbiAgICBpZiAocHJldkFjdGl2ZUNoYW5uZWw/LmNpZCA9PT0gY2hhbm5lbC5jaWQpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgdGhpcy5zdG9wV2F0Y2hGb3JBY3RpdmVDaGFubmVsRXZlbnRzKHByZXZBY3RpdmVDaGFubmVsKTtcbiAgICB0aGlzLmFyZVJlYWRFdmVudHNQYXVzZWQgPSBmYWxzZTtcbiAgICBjb25zdCByZWFkU3RhdGUgPVxuICAgICAgY2hhbm5lbC5zdGF0ZS5yZWFkW3RoaXMuY2hhdENsaWVudFNlcnZpY2UuY2hhdENsaWVudC51c2VyPy5pZCB8fCAnJ107XG4gICAgdGhpcy5hY3RpdmVDaGFubmVsTGFzdFJlYWRNZXNzYWdlSWQgPSByZWFkU3RhdGU/Lmxhc3RfcmVhZF9tZXNzYWdlX2lkO1xuICAgIGlmIChcbiAgICAgIGNoYW5uZWwuc3RhdGUubGF0ZXN0TWVzc2FnZXNbY2hhbm5lbC5zdGF0ZS5sYXRlc3RNZXNzYWdlcy5sZW5ndGggLSAxXVxuICAgICAgICA/LmlkID09PSB0aGlzLmFjdGl2ZUNoYW5uZWxMYXN0UmVhZE1lc3NhZ2VJZFxuICAgICkge1xuICAgICAgdGhpcy5hY3RpdmVDaGFubmVsTGFzdFJlYWRNZXNzYWdlSWQgPSB1bmRlZmluZWQ7XG4gICAgfVxuICAgIHRoaXMuYWN0aXZlQ2hhbm5lbFVucmVhZENvdW50ID0gcmVhZFN0YXRlPy51bnJlYWRfbWVzc2FnZXMgfHwgMDtcbiAgICB0aGlzLndhdGNoRm9yQWN0aXZlQ2hhbm5lbEV2ZW50cyhjaGFubmVsKTtcbiAgICB0aGlzLmFkZENoYW5uZWwoY2hhbm5lbCk7XG4gICAgdGhpcy5hY3RpdmVDaGFubmVsU3ViamVjdC5uZXh0KGNoYW5uZWwpO1xuICAgIGNvbnN0IGNoYW5uZWxTdGF0ZUxlbmd0aCA9IGNoYW5uZWwuc3RhdGUubGF0ZXN0TWVzc2FnZXMubGVuZ3RoO1xuICAgIGlmIChjaGFubmVsU3RhdGVMZW5ndGggPiAyICogdGhpcy5tZXNzYWdlUGFnZVNpemUpIHtcbiAgICAgIGNoYW5uZWwuc3RhdGUubGF0ZXN0TWVzc2FnZXMgPSBjaGFubmVsLnN0YXRlLmxhdGVzdE1lc3NhZ2VzLnNsaWNlKFxuICAgICAgICBjaGFubmVsU3RhdGVMZW5ndGggLSAyICogdGhpcy5tZXNzYWdlUGFnZVNpemVcbiAgICAgICk7XG4gICAgfVxuICAgIHRoaXMuc2V0Q2hhbm5lbFN0YXRlKGNoYW5uZWwpO1xuICB9XG5cbiAgLyoqXG4gICAqIERlc2VsZWN0cyB0aGUgY3VycmVudGx5IGFjdGl2ZSAoaWYgYW55KSBjaGFubmVsXG4gICAqL1xuICBkZXNlbGVjdEFjdGl2ZUNoYW5uZWwoKSB7XG4gICAgY29uc3QgYWN0aXZlQ2hhbm5lbCA9IHRoaXMuYWN0aXZlQ2hhbm5lbFN1YmplY3QuZ2V0VmFsdWUoKTtcbiAgICBpZiAoIWFjdGl2ZUNoYW5uZWwpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgdGhpcy5zdG9wV2F0Y2hGb3JBY3RpdmVDaGFubmVsRXZlbnRzKGFjdGl2ZUNoYW5uZWwpO1xuICAgIHRoaXMuYWN0aXZlQ2hhbm5lbE1lc3NhZ2VzU3ViamVjdC5uZXh0KFtdKTtcbiAgICB0aGlzLmFjdGl2ZUNoYW5uZWxTdWJqZWN0Lm5leHQodW5kZWZpbmVkKTtcbiAgICB0aGlzLmFjdGl2ZVBhcmVudE1lc3NhZ2VJZFN1YmplY3QubmV4dCh1bmRlZmluZWQpO1xuICAgIHRoaXMuYWN0aXZlVGhyZWFkTWVzc2FnZXNTdWJqZWN0Lm5leHQoW10pO1xuICAgIHRoaXMubGF0ZXN0TWVzc2FnZURhdGVCeVVzZXJCeUNoYW5uZWxzU3ViamVjdC5uZXh0KHt9KTtcbiAgICB0aGlzLnNlbGVjdE1lc3NhZ2VUb1F1b3RlKHVuZGVmaW5lZCk7XG4gICAgdGhpcy5qdW1wVG9NZXNzYWdlU3ViamVjdC5uZXh0KHsgaWQ6IHVuZGVmaW5lZCwgcGFyZW50SWQ6IHVuZGVmaW5lZCB9KTtcbiAgICB0aGlzLmFjdGl2ZUNoYW5uZWxQaW5uZWRNZXNzYWdlc1N1YmplY3QubmV4dChbXSk7XG4gICAgdGhpcy51c2Vyc1R5cGluZ0luQ2hhbm5lbFN1YmplY3QubmV4dChbXSk7XG4gICAgdGhpcy51c2Vyc1R5cGluZ0luVGhyZWFkU3ViamVjdC5uZXh0KFtdKTtcbiAgICB0aGlzLmFjdGl2ZUNoYW5uZWxMYXN0UmVhZE1lc3NhZ2VJZCA9IHVuZGVmaW5lZDtcbiAgICB0aGlzLmFjdGl2ZUNoYW5uZWxVbnJlYWRDb3VudCA9IHVuZGVmaW5lZDtcbiAgICB0aGlzLmFyZVJlYWRFdmVudHNQYXVzZWQgPSBmYWxzZTtcbiAgfVxuXG4gIC8qKlxuICAgKiBTZXRzIHRoZSBnaXZlbiBgbWVzc2FnZWAgYXMgYW4gYWN0aXZlIHBhcmVudCBtZXNzYWdlLiBJZiBgdW5kZWZpbmVkYCBpcyBwcm92aWRlZCwgaXQgd2lsbCBkZWxlc2VsZWN0IHRoZSBjdXJyZW50IHBhcmVudCBtZXNzYWdlLlxuICAgKiBAcGFyYW0gbWVzc2FnZVxuICAgKiBAcGFyYW0gbG9hZE1lc3NhZ2VzRm9ybVxuICAgKi9cbiAgYXN5bmMgc2V0QXNBY3RpdmVQYXJlbnRNZXNzYWdlKFxuICAgIG1lc3NhZ2U6IFN0cmVhbU1lc3NhZ2U8VD4gfCB1bmRlZmluZWQsXG4gICAgbG9hZE1lc3NhZ2VzRm9ybTogJ3JlcXVlc3QnIHwgJ3N0YXRlJyA9ICdyZXF1ZXN0J1xuICApIHtcbiAgICBjb25zdCBtZXNzYWdlVG9RdW90ZSA9IHRoaXMubWVzc2FnZVRvUXVvdGVTdWJqZWN0LmdldFZhbHVlKCk7XG4gICAgaWYgKG1lc3NhZ2VUb1F1b3RlICYmICEhbWVzc2FnZVRvUXVvdGUucGFyZW50X2lkKSB7XG4gICAgICB0aGlzLm1lc3NhZ2VUb1F1b3RlU3ViamVjdC5uZXh0KHVuZGVmaW5lZCk7XG4gICAgfVxuICAgIGlmICghbWVzc2FnZSkge1xuICAgICAgdGhpcy5hY3RpdmVQYXJlbnRNZXNzYWdlSWRTdWJqZWN0Lm5leHQodW5kZWZpbmVkKTtcbiAgICAgIHRoaXMuYWN0aXZlVGhyZWFkTWVzc2FnZXNTdWJqZWN0Lm5leHQoW10pO1xuICAgICAgY29uc3QgbWVzc2FnZVRvSnVtcFRvID0gdGhpcy5qdW1wVG9NZXNzYWdlU3ViamVjdC5nZXRWYWx1ZSgpO1xuICAgICAgaWYgKG1lc3NhZ2VUb0p1bXBUbyAmJiAhIW1lc3NhZ2VUb0p1bXBUby5wYXJlbnRJZCkge1xuICAgICAgICB0aGlzLmp1bXBUb01lc3NhZ2VTdWJqZWN0Lm5leHQoeyBpZDogdW5kZWZpbmVkLCBwYXJlbnRJZDogdW5kZWZpbmVkIH0pO1xuICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICB0aGlzLmFjdGl2ZVBhcmVudE1lc3NhZ2VJZFN1YmplY3QubmV4dChtZXNzYWdlLmlkKTtcbiAgICAgIGNvbnN0IGFjdGl2ZUNoYW5uZWwgPSB0aGlzLmFjdGl2ZUNoYW5uZWxTdWJqZWN0LmdldFZhbHVlKCk7XG4gICAgICBpZiAobG9hZE1lc3NhZ2VzRm9ybSA9PT0gJ3JlcXVlc3QnKSB7XG4gICAgICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IGFjdGl2ZUNoYW5uZWw/LmdldFJlcGxpZXMobWVzc2FnZS5pZCwge1xuICAgICAgICAgIGxpbWl0OiB0aGlzLm9wdGlvbnM/Lm1lc3NhZ2VfbGltaXQsXG4gICAgICAgIH0pO1xuICAgICAgICB0aGlzLmFjdGl2ZVRocmVhZE1lc3NhZ2VzU3ViamVjdC5uZXh0KHJlc3VsdD8ubWVzc2FnZXMgfHwgW10pO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdGhpcy5hY3RpdmVUaHJlYWRNZXNzYWdlc1N1YmplY3QubmV4dChcbiAgICAgICAgICBhY3RpdmVDaGFubmVsPy5zdGF0ZS50aHJlYWRzW21lc3NhZ2UuaWRdIHx8IFtdXG4gICAgICAgICk7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIExvYWRzIHRoZSBuZXh0IHBhZ2Ugb2YgbWVzc2FnZXMgb2YgdGhlIGFjdGl2ZSBjaGFubmVsLiBUaGUgcGFnZSBzaXplIGNhbiBiZSBzZXQgaW4gdGhlIFtxdWVyeSBvcHRpb25dKGh0dHBzOi8vZ2V0c3RyZWFtLmlvL2NoYXQvZG9jcy9qYXZhc2NyaXB0L3F1ZXJ5X2NoYW5uZWxzLz9sYW5ndWFnZT1qYXZhc2NyaXB0I3F1ZXJ5LW9wdGlvbnMpIG9iamVjdC5cbiAgICogQHBhcmFtIGRpcmVjdGlvblxuICAgKi9cbiAgbG9hZE1vcmVNZXNzYWdlcyhkaXJlY3Rpb246ICdvbGRlcicgfCAnbmV3ZXInID0gJ29sZGVyJykge1xuICAgIGNvbnN0IGFjdGl2ZUNobmFubmVsID0gdGhpcy5hY3RpdmVDaGFubmVsU3ViamVjdC5nZXRWYWx1ZSgpO1xuICAgIGNvbnN0IG1lc3NhZ2VzID0gdGhpcy5hY3RpdmVDaGFubmVsTWVzc2FnZXNTdWJqZWN0LmdldFZhbHVlKCk7XG4gICAgY29uc3QgbGFzdE1lc3NhZ2VJZCA9XG4gICAgICBtZXNzYWdlc1tkaXJlY3Rpb24gPT09ICdvbGRlcicgPyAwIDogbWVzc2FnZXMubGVuZ3RoIC0gMV0/LmlkO1xuICAgIGlmIChcbiAgICAgIGRpcmVjdGlvbiA9PT0gJ25ld2VyJyAmJlxuICAgICAgYWN0aXZlQ2huYW5uZWw/LnN0YXRlPy5sYXRlc3RNZXNzYWdlcyA9PT0gYWN0aXZlQ2huYW5uZWw/LnN0YXRlPy5tZXNzYWdlc1xuICAgICkge1xuICAgICAgLy8gSWYgd2UgYXJlIG9uIGxhdGVzdCBtZXNzYWdlIHNldCwgYWN0aXZlQ2hhbm5lbE1lc3NhZ2VzJCB3aWxsIGJlIHJlZnJlc2hlZCBieSBXUyBldmVudHMsIG5vIG5lZWQgZm9yIGEgcmVxdWVzdFxuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgICByZXR1cm4gYWN0aXZlQ2huYW5uZWxcbiAgICAgID8ucXVlcnkoe1xuICAgICAgICBtZXNzYWdlczoge1xuICAgICAgICAgIGxpbWl0OiB0aGlzLm9wdGlvbnM/Lm1lc3NhZ2VfbGltaXQsXG4gICAgICAgICAgW2RpcmVjdGlvbiA9PT0gJ29sZGVyJyA/ICdpZF9sdCcgOiAnaWRfZ3QnXTogbGFzdE1lc3NhZ2VJZCxcbiAgICAgICAgfSxcbiAgICAgICAgbWVtYmVyczogeyBsaW1pdDogMCB9LFxuICAgICAgICB3YXRjaGVyczogeyBsaW1pdDogMCB9LFxuICAgICAgfSlcbiAgICAgIC50aGVuKChyZXMpID0+IHtcbiAgICAgICAgaWYgKFxuICAgICAgICAgIGFjdGl2ZUNobmFubmVsPy5kYXRhPy5pZCA9PT1cbiAgICAgICAgICB0aGlzLmFjdGl2ZUNoYW5uZWxTdWJqZWN0LmdldFZhbHVlKCk/LmRhdGE/LmlkXG4gICAgICAgICkge1xuICAgICAgICAgIHRoaXMuYWN0aXZlQ2hhbm5lbE1lc3NhZ2VzU3ViamVjdC5uZXh0KFtcbiAgICAgICAgICAgIC4uLmFjdGl2ZUNobmFubmVsLnN0YXRlLm1lc3NhZ2VzLFxuICAgICAgICAgIF0pO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHJlcztcbiAgICAgIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIExvYWRzIHRoZSBuZXh0IHBhZ2Ugb2YgbWVzc2FnZXMgb2YgdGhlIGFjdGl2ZSB0aHJlYWQuIFRoZSBwYWdlIHNpemUgY2FuIGJlIHNldCBpbiB0aGUgW3F1ZXJ5IG9wdGlvbl0oaHR0cHM6Ly9nZXRzdHJlYW0uaW8vY2hhdC9kb2NzL2phdmFzY3JpcHQvcXVlcnlfY2hhbm5lbHMvP2xhbmd1YWdlPWphdmFzY3JpcHQjcXVlcnktb3B0aW9ucykgb2JqZWN0LlxuICAgKiBAcGFyYW0gZGlyZWN0aW9uXG4gICAqL1xuICBhc3luYyBsb2FkTW9yZVRocmVhZFJlcGxpZXMoZGlyZWN0aW9uOiAnb2xkZXInIHwgJ25ld2VyJyA9ICdvbGRlcicpIHtcbiAgICBpZiAoZGlyZWN0aW9uID09PSAnbmV3ZXInKSB7XG4gICAgICAvLyBUaHJlYWQgcmVwbGllcyBhcmVuJ3QgYnJva2UgaW50byBkaWZmZXJlbnQgbWVzc2FnZSBzZXRzLCBhY3RpdmVUaHJlYWRNZXNzYWdlcyQgd2lsbCBiZSByZWZyZXNoZWQgYnkgV1MgZXZlbnRzLCBubyBuZWVkIGZvciBhIHJlcXVlc3RcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgY29uc3QgYWN0aXZlQ2huYW5uZWwgPSB0aGlzLmFjdGl2ZUNoYW5uZWxTdWJqZWN0LmdldFZhbHVlKCk7XG4gICAgY29uc3QgcGFyZW50TWVzc2FnZUlkID0gdGhpcy5hY3RpdmVQYXJlbnRNZXNzYWdlSWRTdWJqZWN0LmdldFZhbHVlKCk7XG4gICAgaWYgKCFwYXJlbnRNZXNzYWdlSWQpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgY29uc3QgdGhyZWFkTWVzc2FnZXMgPSB0aGlzLmFjdGl2ZVRocmVhZE1lc3NhZ2VzU3ViamVjdC5nZXRWYWx1ZSgpO1xuICAgIGNvbnN0IGxhc3RNZXNzYWdlSWQgPVxuICAgICAgdGhyZWFkTWVzc2FnZXNbZGlyZWN0aW9uID09PSAnb2xkZXInID8gMCA6IHRocmVhZE1lc3NhZ2VzLmxlbmd0aCAtIDFdPy5pZDtcbiAgICBhd2FpdCBhY3RpdmVDaG5hbm5lbD8uZ2V0UmVwbGllcyhwYXJlbnRNZXNzYWdlSWQsIHtcbiAgICAgIGxpbWl0OiB0aGlzLm9wdGlvbnM/Lm1lc3NhZ2VfbGltaXQsXG4gICAgICBbZGlyZWN0aW9uID09PSAnb2xkZXInID8gJ2lkX2x0JyA6ICdpZF9ndCddOiBsYXN0TWVzc2FnZUlkLFxuICAgIH0pO1xuICAgIHRoaXMuYWN0aXZlVGhyZWFkTWVzc2FnZXNTdWJqZWN0Lm5leHQoXG4gICAgICBhY3RpdmVDaG5hbm5lbD8uc3RhdGUudGhyZWFkc1twYXJlbnRNZXNzYWdlSWRdIHx8IFtdXG4gICAgKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBRdWVyaWVzIHRoZSBjaGFubmVscyB3aXRoIHRoZSBnaXZlbiBmaWx0ZXJzLCBzb3J0cyBhbmQgb3B0aW9ucy4gTW9yZSBpbmZvIGFib3V0IFtjaGFubmVsIHF1ZXJ5aW5nXShodHRwczovL2dldHN0cmVhbS5pby9jaGF0L2RvY3MvamF2YXNjcmlwdC9xdWVyeV9jaGFubmVscy8/bGFuZ3VhZ2U9amF2YXNjcmlwdCkgY2FuIGJlIGZvdW5kIGluIHRoZSBwbGF0Zm9ybSBkb2N1bWVudGF0aW9uLiBCeSBkZWZhdWx0IHRoZSBmaXJzdCBjaGFubmVsIGluIHRoZSBsaXN0IHdpbGwgYmUgc2V0IGFzIGFjdGl2ZSBjaGFubmVsIGFuZCB3aWxsIGJlIG1hcmtlZCBhcyByZWFkLlxuICAgKiBAcGFyYW0gZmlsdGVyc1xuICAgKiBAcGFyYW0gc29ydFxuICAgKiBAcGFyYW0gb3B0aW9uc1xuICAgKiBAcGFyYW0gc2hvdWxkU2V0QWN0aXZlQ2hhbm5lbCBEZWNpZGVzIGlmIHRoZSBmaXJzdCBjaGFubmVsIGluIHRoZSByZXN1bHQgc2hvdWxkIGJlIG1hZGUgYXMgYW4gYWN0aXZlIGNoYW5uZWwsIG9yIG5vIGNoYW5uZWwgc2hvdWxkIGJlIG1hcmtlZCBhcyBhY3RpdmVcbiAgICogQHJldHVybnMgdGhlIGxpc3Qgb2YgY2hhbm5lbHMgZm91bmQgYnkgdGhlIHF1ZXJ5XG4gICAqL1xuICBhc3luYyBpbml0KFxuICAgIGZpbHRlcnM6IENoYW5uZWxGaWx0ZXJzPFQ+LFxuICAgIHNvcnQ/OiBDaGFubmVsU29ydDxUPixcbiAgICBvcHRpb25zPzogQ2hhbm5lbE9wdGlvbnMgJiB7IGtlZXBBbGl2ZUNoYW5uZWxzJE9uRXJyb3I/OiBib29sZWFuIH0sXG4gICAgc2hvdWxkU2V0QWN0aXZlQ2hhbm5lbDogYm9vbGVhbiA9IHRydWVcbiAgKSB7XG4gICAgdGhpcy5maWx0ZXJzID0gZmlsdGVycztcbiAgICB0aGlzLm9wdGlvbnMgPSB7XG4gICAgICBsaW1pdDogMjUsXG4gICAgICBzdGF0ZTogdHJ1ZSxcbiAgICAgIHByZXNlbmNlOiB0cnVlLFxuICAgICAgd2F0Y2g6IHRydWUsXG4gICAgICBtZXNzYWdlX2xpbWl0OiB0aGlzLm1lc3NhZ2VQYWdlU2l6ZSxcbiAgICAgIC4uLm9wdGlvbnMsXG4gICAgfTtcbiAgICB0aGlzLnNvcnQgPSBzb3J0IHx8IHsgbGFzdF9tZXNzYWdlX2F0OiAtMSB9O1xuICAgIHRoaXMuc2hvdWxkU2V0QWN0aXZlQ2hhbm5lbCA9IHNob3VsZFNldEFjdGl2ZUNoYW5uZWw7XG4gICAgdGhpcy5jbGllbnRFdmVudHNTdWJzY3JpcHRpb24gPSB0aGlzLmNoYXRDbGllbnRTZXJ2aWNlLmV2ZW50cyQuc3Vic2NyaWJlKFxuICAgICAgKG5vdGlmaWNhdGlvbikgPT4gdm9pZCB0aGlzLmhhbmRsZU5vdGlmaWNhdGlvbihub3RpZmljYXRpb24pXG4gICAgKTtcbiAgICB0cnkge1xuICAgICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgdGhpcy5xdWVyeUNoYW5uZWxzKHRoaXMuc2hvdWxkU2V0QWN0aXZlQ2hhbm5lbCk7XG4gICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICB0aGlzLmRpc21pc3NFcnJvck5vdGlmaWNhdGlvbiA9XG4gICAgICAgIHRoaXMubm90aWZpY2F0aW9uU2VydmljZS5hZGRQZXJtYW5lbnROb3RpZmljYXRpb24oXG4gICAgICAgICAgJ3N0cmVhbUNoYXQuRXJyb3IgbG9hZGluZyBjaGFubmVscycsXG4gICAgICAgICAgJ2Vycm9yJ1xuICAgICAgICApO1xuICAgICAgdGhyb3cgZXJyb3I7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFJlc2V0cyB0aGUgYGFjdGl2ZUNoYW5uZWwkYCwgYGNoYW5uZWxzJGAgYW5kIGBhY3RpdmVDaGFubmVsTWVzc2FnZXMkYCBPYnNlcnZhYmxlcy4gVXNlZnVsIHdoZW4gZGlzY29ubmVjdGluZyBhIGNoYXQgdXNlciwgdXNlIGluIGNvbWJpbmF0aW9uIHdpdGggW2BkaXNjb25uZWN0VXNlcmBdKC4vQ2hhdENsaWVudFNlcnZpY2UubWR4LyNkaXNjb25uZWN0dXNlcikuXG4gICAqL1xuICByZXNldCgpIHtcbiAgICB0aGlzLmRlc2VsZWN0QWN0aXZlQ2hhbm5lbCgpO1xuICAgIHRoaXMuY2hhbm5lbHNTdWJqZWN0Lm5leHQodW5kZWZpbmVkKTtcbiAgICB0aGlzLmNoYW5uZWxRdWVyeVN0YXRlU3ViamVjdC5uZXh0KHVuZGVmaW5lZCk7XG4gICAgdGhpcy5jbGllbnRFdmVudHNTdWJzY3JpcHRpb24/LnVuc3Vic2NyaWJlKCk7XG4gICAgdGhpcy5kaXNtaXNzRXJyb3JOb3RpZmljYXRpb24/LigpO1xuICAgIHRoaXMuZGlzbWlzc0Vycm9yTm90aWZpY2F0aW9uID0gdW5kZWZpbmVkO1xuICAgIE9iamVjdC5rZXlzKHRoaXMuY2hhbm5lbFN1YnNjcmlwdGlvbnMpLmZvckVhY2goKGNpZCkgPT4ge1xuICAgICAgdGhpcy5jaGFubmVsU3Vic2NyaXB0aW9uc1tjaWRdKCk7XG4gICAgfSk7XG4gICAgdGhpcy5jaGFubmVsU3Vic2NyaXB0aW9ucyA9IHt9O1xuICAgIHRoaXMubmV4dFBhZ2VDb25maWd1cmF0aW9uID0gdW5kZWZpbmVkO1xuICB9XG5cbiAgLyoqXG4gICAqIExvYWRzIHRoZSBuZXh0IHBhZ2Ugb2YgY2hhbm5lbHMuIFRoZSBwYWdlIHNpemUgY2FuIGJlIHNldCBpbiB0aGUgW3F1ZXJ5IG9wdGlvbl0oaHR0cHM6Ly9nZXRzdHJlYW0uaW8vY2hhdC9kb2NzL2phdmFzY3JpcHQvcXVlcnlfY2hhbm5lbHMvP2xhbmd1YWdlPWphdmFzY3JpcHQjcXVlcnktb3B0aW9ucykgb2JqZWN0LlxuICAgKi9cbiAgYXN5bmMgbG9hZE1vcmVDaGFubmVscygpIHtcbiAgICBhd2FpdCB0aGlzLnF1ZXJ5Q2hhbm5lbHMoZmFsc2UpO1xuICB9XG5cbiAgLyoqXG4gICAqIEFkZHMgYSByZWFjdGlvbiB0byBhIG1lc3NhZ2UuXG4gICAqIEBwYXJhbSBtZXNzYWdlSWQgVGhlIGlkIG9mIHRoZSBtZXNzYWdlIHRvIGFkZCB0aGUgcmVhY3Rpb24gdG9cbiAgICogQHBhcmFtIHJlYWN0aW9uVHlwZSBUaGUgdHlwZSBvZiB0aGUgcmVhY3Rpb25cbiAgICogQHBhcmFtIGN1c3RvbURhdGFcbiAgICovXG4gIGFzeW5jIGFkZFJlYWN0aW9uKFxuICAgIG1lc3NhZ2VJZDogc3RyaW5nLFxuICAgIHJlYWN0aW9uVHlwZTogTWVzc2FnZVJlYWN0aW9uVHlwZSxcbiAgICBjdXN0b21EYXRhPzogVFsncmVhY3Rpb25UeXBlJ11cbiAgKSB7XG4gICAgYXdhaXQgdGhpcy5hY3RpdmVDaGFubmVsU3ViamVjdC5nZXRWYWx1ZSgpPy5zZW5kUmVhY3Rpb24obWVzc2FnZUlkLCB7XG4gICAgICB0eXBlOiByZWFjdGlvblR5cGUsXG4gICAgICAuLi5jdXN0b21EYXRhLFxuICAgIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIFJlbW92ZXMgYSByZWFjdGlvbiBmcm9tIGEgbWVzc2FnZS5cbiAgICogQHBhcmFtIG1lc3NhZ2VJZCBUaGUgaWQgb2YgdGhlIG1lc3NhZ2UgdG8gcmVtb3ZlIHRoZSByZWFjdGlvbiBmcm9tXG4gICAqIEBwYXJhbSByZWFjdGlvblR5cGUgVGhyIHR5cGUgb2YgcmVhY3Rpb24gdG8gcmVtb3ZlXG4gICAqL1xuICBhc3luYyByZW1vdmVSZWFjdGlvbihtZXNzYWdlSWQ6IHN0cmluZywgcmVhY3Rpb25UeXBlOiBNZXNzYWdlUmVhY3Rpb25UeXBlKSB7XG4gICAgYXdhaXQgdGhpcy5hY3RpdmVDaGFubmVsU3ViamVjdFxuICAgICAgLmdldFZhbHVlKClcbiAgICAgID8uZGVsZXRlUmVhY3Rpb24obWVzc2FnZUlkLCByZWFjdGlvblR5cGUpO1xuICB9XG5cbiAgLyoqXG4gICAqIFNlbmRzIGEgbWVzc2FnZSB0byB0aGUgYWN0aXZlIGNoYW5uZWwuIFRoZSBtZXNzYWdlIGlzIGltbWVkaWF0ZWx5IGFkZGVkIHRvIHRoZSBtZXNzYWdlIGxpc3QsIGlmIGFuIGVycm9yIG9jY3VycyBhbmQgdGhlIG1lc3NhZ2UgY2FuJ3QgYmUgc2VudCwgdGhlIGVycm9yIGlzIGluZGljYXRlZCBpbiBgc3RhdGVgIG9mIHRoZSBtZXNzYWdlLlxuICAgKiBAcGFyYW0gdGV4dCBUaGUgdGV4dCBvZiB0aGUgbWVzc2FnZVxuICAgKiBAcGFyYW0gYXR0YWNobWVudHMgVGhlIGF0dGFjaG1lbnRzXG4gICAqIEBwYXJhbSBtZW50aW9uZWRVc2VycyBNZW50aW9uZWQgdXNlcnNcbiAgICogQHBhcmFtIHBhcmVudElkIElkIG9mIHRoZSBwYXJlbnQgbWVzc2FnZSAoaWYgc2VuZGluZyBhIHRocmVhZCByZXBseSlcbiAgICogQHBhcmFtIHF1b3RlZE1lc3NhZ2VJZCBJZCBvZiB0aGUgbWVzc2FnZSB0byBxdW90ZSAoaWYgc2VuZGluZyBhIHF1b3RlIHJlcGx5KVxuICAgKiBAcGFyYW0gY3VzdG9tRGF0YVxuICAgKi9cbiAgYXN5bmMgc2VuZE1lc3NhZ2UoXG4gICAgdGV4dDogc3RyaW5nLFxuICAgIGF0dGFjaG1lbnRzOiBBdHRhY2htZW50PFQ+W10gPSBbXSxcbiAgICBtZW50aW9uZWRVc2VyczogVXNlclJlc3BvbnNlPFQ+W10gPSBbXSxcbiAgICBwYXJlbnRJZDogc3RyaW5nIHwgdW5kZWZpbmVkID0gdW5kZWZpbmVkLFxuICAgIHF1b3RlZE1lc3NhZ2VJZDogc3RyaW5nIHwgdW5kZWZpbmVkID0gdW5kZWZpbmVkLFxuICAgIGN1c3RvbURhdGE6IHVuZGVmaW5lZCB8IFBhcnRpYWw8VFsnbWVzc2FnZVR5cGUnXT4gPSB1bmRlZmluZWRcbiAgKSB7XG4gICAgbGV0IGlucHV0OiBNZXNzYWdlSW5wdXQ8VD4gPSB7XG4gICAgICB0ZXh0LFxuICAgICAgYXR0YWNobWVudHMsXG4gICAgICBtZW50aW9uZWRVc2VycyxcbiAgICAgIHBhcmVudElkLFxuICAgICAgcXVvdGVkTWVzc2FnZUlkLFxuICAgICAgY3VzdG9tRGF0YSxcbiAgICB9O1xuICAgIGlmICh0aGlzLmJlZm9yZVNlbmRNZXNzYWdlKSB7XG4gICAgICBpbnB1dCA9IGF3YWl0IHRoaXMuYmVmb3JlU2VuZE1lc3NhZ2UoaW5wdXQpO1xuICAgIH1cbiAgICBjb25zdCBwcmV2aWV3ID0gY3JlYXRlTWVzc2FnZVByZXZpZXcoXG4gICAgICB0aGlzLmNoYXRDbGllbnRTZXJ2aWNlLmNoYXRDbGllbnQudXNlciEsXG4gICAgICBpbnB1dC50ZXh0LFxuICAgICAgaW5wdXQuYXR0YWNobWVudHMsXG4gICAgICBpbnB1dC5tZW50aW9uZWRVc2VycyxcbiAgICAgIGlucHV0LnBhcmVudElkLFxuICAgICAgaW5wdXQucXVvdGVkTWVzc2FnZUlkLFxuICAgICAgaW5wdXQuY3VzdG9tRGF0YVxuICAgICk7XG4gICAgY29uc3QgY2hhbm5lbCA9IHRoaXMuYWN0aXZlQ2hhbm5lbFN1YmplY3QuZ2V0VmFsdWUoKSE7XG4gICAgcHJldmlldy5yZWFkQnkgPSBbXTtcbiAgICBjaGFubmVsLnN0YXRlLmFkZE1lc3NhZ2VTb3J0ZWQocHJldmlldywgdHJ1ZSk7XG4gICAgY29uc3QgcmVzcG9uc2UgPSBhd2FpdCB0aGlzLnNlbmRNZXNzYWdlUmVxdWVzdChwcmV2aWV3LCBpbnB1dC5jdXN0b21EYXRhKTtcbiAgICByZXR1cm4gcmVzcG9uc2U7XG4gIH1cblxuICAvKipcbiAgICogUmVzZW5kcyB0aGUgZ2l2ZW4gbWVzc2FnZSB0byB0aGUgYWN0aXZlIGNoYW5uZWxcbiAgICogQHBhcmFtIG1lc3NhZ2UgVGhlIG1lc3NhZ2UgdG8gcmVzZW5kXG4gICAqL1xuICBhc3luYyByZXNlbmRNZXNzYWdlKG1lc3NhZ2U6IFN0cmVhbU1lc3NhZ2UpIHtcbiAgICBjb25zdCBjaGFubmVsID0gdGhpcy5hY3RpdmVDaGFubmVsU3ViamVjdC5nZXRWYWx1ZSgpITtcbiAgICBjaGFubmVsLnN0YXRlLmFkZE1lc3NhZ2VTb3J0ZWQoXG4gICAgICB7XG4gICAgICAgIC4uLihtZXNzYWdlIGFzIGFueSBhcyBNZXNzYWdlUmVzcG9uc2U8VD4pLFxuICAgICAgICBlcnJvclN0YXR1c0NvZGU6IHVuZGVmaW5lZCxcbiAgICAgICAgc3RhdHVzOiAnc2VuZGluZycsXG4gICAgICB9LFxuICAgICAgdHJ1ZVxuICAgICk7XG4gICAgcmV0dXJuIHRoaXMuc2VuZE1lc3NhZ2VSZXF1ZXN0KG1lc3NhZ2UsIHVuZGVmaW5lZCwgdHJ1ZSk7XG4gIH1cblxuICAvKipcbiAgICogVXBkYXRlcyB0aGUgbWVzc2FnZSBpbiB0aGUgYWN0aXZlIGNoYW5uZWxcbiAgICogQHBhcmFtIG1lc3NhZ2UgTWVzYWdlIHRvIGJlIHVwZGF0ZWRcbiAgICovXG4gIGFzeW5jIHVwZGF0ZU1lc3NhZ2UobWVzc2FnZTogU3RyZWFtTWVzc2FnZTxUPikge1xuICAgIGxldCBtZXNzYWdlVG9VcGRhdGUgPSB7IC4uLm1lc3NhZ2UgfTtcbiAgICBkZWxldGUgbWVzc2FnZVRvVXBkYXRlLmkxOG47XG4gICAgaWYgKHRoaXMuYmVmb3JlVXBkYXRlTWVzc2FnZSkge1xuICAgICAgbWVzc2FnZVRvVXBkYXRlID0gYXdhaXQgdGhpcy5iZWZvcmVVcGRhdGVNZXNzYWdlKG1lc3NhZ2VUb1VwZGF0ZSk7XG4gICAgfVxuICAgIGlmIChtZXNzYWdlLm1vZGVyYXRpb25fZGV0YWlscykge1xuICAgICAgcmV0dXJuIHRoaXMucmVzZW5kTWVzc2FnZShtZXNzYWdlKTtcbiAgICB9XG4gICAgY29uc3QgcmVzcG9uc2UgPSBhd2FpdCB0aGlzLmNoYXRDbGllbnRTZXJ2aWNlLmNoYXRDbGllbnQudXBkYXRlTWVzc2FnZShcbiAgICAgIG1lc3NhZ2VUb1VwZGF0ZSBhcyBhbnkgYXMgVXBkYXRlZE1lc3NhZ2U8VD5cbiAgICApO1xuXG4gICAgY29uc3QgY2hhbm5lbCA9IHRoaXMuY2hhbm5lbHNTdWJqZWN0XG4gICAgICAuZ2V0VmFsdWUoKVxuICAgICAgPy5maW5kKChjKSA9PiBjLmNpZCA9PT0gbWVzc2FnZS5jaWQpO1xuXG4gICAgaWYgKFxuICAgICAgcmVzcG9uc2UubWVzc2FnZS50eXBlID09PSAnZXJyb3InICYmXG4gICAgICByZXNwb25zZS5tZXNzYWdlLm1vZGVyYXRpb25fZGV0YWlsc1xuICAgICkge1xuICAgICAgdGhpcy5ub3RpZmljYXRpb25TZXJ2aWNlLmFkZFRlbXBvcmFyeU5vdGlmaWNhdGlvbihcbiAgICAgICAgJ3N0cmVhbUNoYXQuVGhpcyBtZXNzYWdlIGRpZCBub3QgbWVldCBvdXIgY29udGVudCBndWlkZWxpbmVzJ1xuICAgICAgKTtcbiAgICAgIHJldHVybiBtZXNzYWdlO1xuICAgIH1cblxuICAgIHJldHVybiB0aGlzLnRyYW5zZm9ybVRvU3RyZWFtTWVzc2FnZShyZXNwb25zZS5tZXNzYWdlLCBjaGFubmVsKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBEZWxldGVzIHRoZSBtZXNzYWdlIGZyb20gdGhlIGFjdGl2ZSBjaGFubmVsXG4gICAqIEBwYXJhbSBtZXNzYWdlIE1lc3NhZ2UgdG8gYmUgZGVsZXRlZFxuICAgKiBAcGFyYW0gaXNMb2NhbERlbGV0ZSBzZXQgdGhpcyBgdHJ1ZWAgaWYgeW91IHdhbnQgdG8gZGVsZXRlIGEgbWVzc2FnZSB0aGF0J3Mgb25seSBwYXJ0IG9mIHRoZSBsb2NhbCBzdGF0ZSwgbm90IHlldCBzYXZlZCBvbiB0aGUgYmFja2VuZFxuICAgKi9cbiAgYXN5bmMgZGVsZXRlTWVzc2FnZShtZXNzYWdlOiBTdHJlYW1NZXNzYWdlLCBpc0xvY2FsRGVsZXRlID0gZmFsc2UpIHtcbiAgICBpZiAoaXNMb2NhbERlbGV0ZSAmJiB0aGlzLmFjdGl2ZUNoYW5uZWwpIHtcbiAgICAgIGNvbnN0IHJlc3VsdCA9IHRoaXMuYWN0aXZlQ2hhbm5lbC5zdGF0ZS5yZW1vdmVNZXNzYWdlKHtcbiAgICAgICAgaWQ6IG1lc3NhZ2UuaWQsXG4gICAgICAgIHBhcmVudF9pZDogbWVzc2FnZS5wYXJlbnRfaWQsXG4gICAgICB9KTtcbiAgICAgIGlmIChyZXN1bHQpIHtcbiAgICAgICAgbWVzc2FnZS5wYXJlbnRfaWRcbiAgICAgICAgICA/IHRoaXMuYWN0aXZlVGhyZWFkTWVzc2FnZXNTdWJqZWN0Lm5leHQoXG4gICAgICAgICAgICAgIHRoaXMuYWN0aXZlQ2hhbm5lbC5zdGF0ZS50aHJlYWRzW21lc3NhZ2UucGFyZW50X2lkXVxuICAgICAgICAgICAgKVxuICAgICAgICAgIDogdGhpcy5hY3RpdmVDaGFubmVsTWVzc2FnZXNTdWJqZWN0Lm5leHQoXG4gICAgICAgICAgICAgIHRoaXMuYWN0aXZlQ2hhbm5lbC5zdGF0ZS5tZXNzYWdlc1xuICAgICAgICAgICAgKTtcbiAgICAgIH1cbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgaWYgKHRoaXMubWVzc2FnZURlbGV0ZUNvbmZpcm1hdGlvbkhhbmRsZXIpIHtcbiAgICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IHRoaXMubWVzc2FnZURlbGV0ZUNvbmZpcm1hdGlvbkhhbmRsZXIobWVzc2FnZSk7XG4gICAgICBpZiAocmVzdWx0KSB7XG4gICAgICAgIGF3YWl0IHRoaXMuY2hhdENsaWVudFNlcnZpY2UuY2hhdENsaWVudC5kZWxldGVNZXNzYWdlKG1lc3NhZ2UuaWQpO1xuICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICBhd2FpdCB0aGlzLmNoYXRDbGllbnRTZXJ2aWNlLmNoYXRDbGllbnQuZGVsZXRlTWVzc2FnZShtZXNzYWdlLmlkKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogVXBsb2FkcyBmaWxlcyB0byB0aGUgY2hhbm5lbC4gSWYgeW91IHdhbnQgdG8ga25vdyBtb3JlIGFib3V0IFtmaWxlIHVwbG9hZHNdKGh0dHBzOi8vZ2V0c3RyZWFtLmlvL2NoYXQvZG9jcy9qYXZhc2NyaXB0L2ZpbGVfdXBsb2Fkcy8/bGFuZ3VhZ2U9amF2YXNjcmlwdCkgY2hlY2sgb3V0IHRoZSBwbGF0Zm9ybSBkb2N1bWVudGF0aW9uLlxuICAgKiBAcGFyYW0gdXBsb2FkcyB0aGUgYXR0YWNobWVudHMgdG8gdXBsb2FkIChvdXRwdXQgb2YgdGhlIFtgQXR0YWNobWVudFNlcnZpY2VgXSguL0F0dGFjaG1lbnRTZXJ2aWNlLm1keCkpXG4gICAqIEByZXR1cm5zIHRoZSByZXN1bHQgb2YgZmlsZSB1cGxvYWQgcmVxdWVzdHNcbiAgICovXG4gIGFzeW5jIHVwbG9hZEF0dGFjaG1lbnRzKFxuICAgIHVwbG9hZHM6IEF0dGFjaG1lbnRVcGxvYWRbXVxuICApOiBQcm9taXNlPEF0dGFjaG1lbnRVcGxvYWRbXT4ge1xuICAgIGNvbnN0IHJlc3VsdDogQXR0YWNobWVudFVwbG9hZFtdID0gW107XG4gICAgY29uc3QgY2hhbm5lbCA9IHRoaXMuYWN0aXZlQ2hhbm5lbFN1YmplY3QuZ2V0VmFsdWUoKSE7XG4gICAgY29uc3QgdXBsb2FkUmVzdWx0cyA9IGF3YWl0IFByb21pc2UuYWxsU2V0dGxlZChcbiAgICAgIHVwbG9hZHMubWFwKCh1cGxvYWQpID0+XG4gICAgICAgIHVwbG9hZC50eXBlID09PSAnaW1hZ2UnXG4gICAgICAgICAgPyB0aGlzLmN1c3RvbUltYWdlVXBsb2FkUmVxdWVzdFxuICAgICAgICAgICAgPyB0aGlzLmN1c3RvbUltYWdlVXBsb2FkUmVxdWVzdCh1cGxvYWQuZmlsZSwgY2hhbm5lbClcbiAgICAgICAgICAgIDogY2hhbm5lbC5zZW5kSW1hZ2UodXBsb2FkLmZpbGUsIHVwbG9hZC5maWxlLm5hbWUsIHVwbG9hZC5maWxlLnR5cGUpXG4gICAgICAgICAgOiB0aGlzLmN1c3RvbUZpbGVVcGxvYWRSZXF1ZXN0XG4gICAgICAgICAgPyB0aGlzLmN1c3RvbUZpbGVVcGxvYWRSZXF1ZXN0KHVwbG9hZC5maWxlLCBjaGFubmVsKVxuICAgICAgICAgIDogY2hhbm5lbC5zZW5kRmlsZSh1cGxvYWQuZmlsZSwgdXBsb2FkLmZpbGUubmFtZSwgdXBsb2FkLmZpbGUudHlwZSlcbiAgICAgIClcbiAgICApO1xuICAgIHVwbG9hZFJlc3VsdHMuZm9yRWFjaCgodXBsb2FkUmVzdWx0LCBpKSA9PiB7XG4gICAgICBjb25zdCBmaWxlID0gdXBsb2Fkc1tpXS5maWxlO1xuICAgICAgY29uc3QgdHlwZSA9IHVwbG9hZHNbaV0udHlwZTtcbiAgICAgIGlmICh1cGxvYWRSZXN1bHQuc3RhdHVzID09PSAnZnVsZmlsbGVkJykge1xuICAgICAgICByZXN1bHQucHVzaCh7XG4gICAgICAgICAgZmlsZSxcbiAgICAgICAgICB0eXBlLFxuICAgICAgICAgIHN0YXRlOiAnc3VjY2VzcycsXG4gICAgICAgICAgdXJsOiB1cGxvYWRSZXN1bHQudmFsdWUuZmlsZSxcbiAgICAgICAgICAvKiBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25vLXVuc2FmZS1hc3NpZ25tZW50LCBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tdW5zYWZlLW1lbWJlci1hY2Nlc3MgKi9cbiAgICAgICAgICB0aHVtYl91cmw6ICh1cGxvYWRSZXN1bHQudmFsdWUgYXMgYW55KS50aHVtYl91cmwsXG4gICAgICAgIH0pO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgbGV0IHJlYXNvbjogQXR0YWNobWVudFVwbG9hZEVycm9yUmVhc29uID0gJ3Vua25vd24nO1xuICAgICAgICBsZXQgZXh0cmFEYXRhOiB7IHBhcmFtOiBzdHJpbmcgfSB8IHVuZGVmaW5lZDtcbiAgICAgICAgLyogZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uby11bnNhZmUtYXNzaWdubWVudCAqL1xuICAgICAgICBjb25zdCBtZXNzYWdlOiBzdHJpbmcgfCB1bmRlZmluZWQgPVxuICAgICAgICAgIC8qIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tdW5zYWZlLW1lbWJlci1hY2Nlc3MgKi9cbiAgICAgICAgICB1cGxvYWRSZXN1bHQucmVhc29uLnJlc3BvbnNlPy5kYXRhPy5tZXNzYWdlO1xuICAgICAgICAvKiBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25vLXVuc2FmZS1hc3NpZ25tZW50ICovXG4gICAgICAgIGNvbnN0IGNvZGU6IG51bWJlciB8IHVuZGVmaW5lZCA9XG4gICAgICAgICAgLyogZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uby11bnNhZmUtbWVtYmVyLWFjY2VzcyAqL1xuICAgICAgICAgIHVwbG9hZFJlc3VsdC5yZWFzb24ucmVzcG9uc2U/LmRhdGE/LmNvZGU7XG4gICAgICAgIGlmIChjb2RlID09PSAyMikge1xuICAgICAgICAgIHJlYXNvbiA9ICdmaWxlLXNpemUnO1xuICAgICAgICAgIGV4dHJhRGF0YSA9IHsgcGFyYW06IC9cXGQrTUIvLmV4ZWMobWVzc2FnZSB8fCAnJyk/LlswXSB8fCAnMTAwTUInIH07XG4gICAgICAgIH0gZWxzZSBpZiAoXG4gICAgICAgICAgY29kZSA9PT0gNCAmJlxuICAgICAgICAgIG1lc3NhZ2U/LnRvTG93ZXJDYXNlKCk/LmluY2x1ZGVzKCdmaWxlIGV4dGVuc2lvbicpXG4gICAgICAgICkge1xuICAgICAgICAgIHJlYXNvbiA9ICdmaWxlLWV4dGVuc2lvbic7XG4gICAgICAgICAgZXh0cmFEYXRhID0geyBwYXJhbTogL1xcLlxcdysvLmV4ZWMobWVzc2FnZSk/LlswXSB8fCAnJyB9O1xuICAgICAgICB9XG4gICAgICAgIHJlc3VsdC5wdXNoKHtcbiAgICAgICAgICBmaWxlLFxuICAgICAgICAgIHR5cGUsXG4gICAgICAgICAgc3RhdGU6ICdlcnJvcicsXG4gICAgICAgICAgZXJyb3JSZWFzb246IHJlYXNvbixcbiAgICAgICAgICBlcnJvckV4dHJhSW5mbzogZXh0cmFEYXRhID8gW2V4dHJhRGF0YV0gOiB1bmRlZmluZWQsXG4gICAgICAgIH0pO1xuICAgICAgfVxuICAgIH0pO1xuXG4gICAgcmV0dXJuIHJlc3VsdDtcbiAgfVxuXG4gIC8qKlxuICAgKiBEZWxldGVzIGFuIHVwbG9hZGVkIGZpbGUgYnkgVVJMLiBJZiB5b3Ugd2FudCB0byBrbm93IG1vcmUgYWJvdXQgW2ZpbGUgdXBsb2Fkc10oaHR0cHM6Ly9nZXRzdHJlYW0uaW8vY2hhdC9kb2NzL2phdmFzY3JpcHQvZmlsZV91cGxvYWRzLz9sYW5ndWFnZT1qYXZhc2NyaXB0KSBjaGVjayBvdXQgdGhlIHBsYXRmb3JtIGRvY3VtZW50YXRpb25cbiAgICogQHBhcmFtIGF0dGFjaG1lbnRVcGxvYWQgQXR0YWNobWVudCB0byBiZSBkZWxldGVkIChvdXRwdXQgb2YgdGhlIFtgQXR0YWNobWVudFNlcnZpY2VgXSguL0F0dGFjaG1lbnRTZXJ2aWNlLm1keCkpXG4gICAqL1xuICBhc3luYyBkZWxldGVBdHRhY2htZW50KGF0dGFjaG1lbnRVcGxvYWQ6IEF0dGFjaG1lbnRVcGxvYWQpIHtcbiAgICBjb25zdCBjaGFubmVsID0gdGhpcy5hY3RpdmVDaGFubmVsU3ViamVjdC5nZXRWYWx1ZSgpITtcbiAgICBhd2FpdCAoYXR0YWNobWVudFVwbG9hZC50eXBlID09PSAnaW1hZ2UnXG4gICAgICA/IHRoaXMuY3VzdG9tSW1hZ2VEZWxldGVSZXF1ZXN0XG4gICAgICAgID8gdGhpcy5jdXN0b21JbWFnZURlbGV0ZVJlcXVlc3QoYXR0YWNobWVudFVwbG9hZC51cmwhLCBjaGFubmVsKVxuICAgICAgICA6IGNoYW5uZWwuZGVsZXRlSW1hZ2UoYXR0YWNobWVudFVwbG9hZC51cmwhKVxuICAgICAgOiB0aGlzLmN1c3RvbUZpbGVEZWxldGVSZXF1ZXN0XG4gICAgICA/IHRoaXMuY3VzdG9tRmlsZURlbGV0ZVJlcXVlc3QoYXR0YWNobWVudFVwbG9hZC51cmwhLCBjaGFubmVsKVxuICAgICAgOiBjaGFubmVsLmRlbGV0ZUZpbGUoYXR0YWNobWVudFVwbG9hZC51cmwhKSk7XG4gIH1cblxuICAvKipcbiAgICogUmV0dXJucyB0aGUgYXV0b2NvbXBsZXRlIG9wdGlvbnMgZm9yIGN1cnJlbnQgY2hhbm5lbCBtZW1iZXJzLiBJZiB0aGUgY2hhbm5lbCBoYXMgbGVzcyB0aGFuIDEwMCBtZW1iZXJzLCBpdCByZXR1cm5zIHRoZSBjaGFubmVsIG1lbWJlcnMsIG90aGVyd2lzZSBzZW5kcyBhIFtzZWFyY2ggcmVxdWVzdF0oaHR0cHM6Ly9nZXRzdHJlYW0uaW8vY2hhdC9kb2NzL2phdmFzY3JpcHQvcXVlcnlfbWVtYmVycy8/bGFuZ3VhZ2U9amF2YXNjcmlwdCNwYWdpbmF0aW9uLWFuZC1vcmRlcmluZykgd2l0aCB0aGUgZ2l2ZW4gc2VhcmNoIHRlcm0uXG4gICAqIEBwYXJhbSBzZWFyY2hUZXJtIFRleHQgdG8gc2VhcmNoIGZvciBpbiB0aGUgbmFtZXMgb2YgbWVtYmVyc1xuICAgKiBAcmV0dXJucyBUaGUgbGlzdCBvZiBtZW1iZXJzIG1hdGNoaW5nIHRoZSBzZWFyY2ggZmlsdGVyXG4gICAqL1xuICBhc3luYyBhdXRvY29tcGxldGVNZW1iZXJzKHNlYXJjaFRlcm06IHN0cmluZykge1xuICAgIGNvbnN0IGFjdGl2ZUNoYW5uZWwgPSB0aGlzLmFjdGl2ZUNoYW5uZWxTdWJqZWN0LmdldFZhbHVlKCk7XG4gICAgaWYgKCFhY3RpdmVDaGFubmVsKSB7XG4gICAgICByZXR1cm4gW107XG4gICAgfVxuICAgIGlmIChPYmplY3Qua2V5cyhhY3RpdmVDaGFubmVsLnN0YXRlLm1lbWJlcnMpLmxlbmd0aCA8IDEwMCkge1xuICAgICAgcmV0dXJuIE9iamVjdC52YWx1ZXMoYWN0aXZlQ2hhbm5lbC5zdGF0ZS5tZW1iZXJzKS5maWx0ZXIoXG4gICAgICAgIChtKSA9PiBtLnVzZXI/LmlkICE9PSB0aGlzLmNoYXRDbGllbnRTZXJ2aWNlLmNoYXRDbGllbnQudXNlcklEIVxuICAgICAgKTtcbiAgICB9IGVsc2Uge1xuICAgICAgaWYgKCFzZWFyY2hUZXJtKSB7XG4gICAgICAgIHJldHVybiBbXTtcbiAgICAgIH1cbiAgICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IGFjdGl2ZUNoYW5uZWwucXVlcnlNZW1iZXJzKHtcbiAgICAgICAgbmFtZTogeyAkYXV0b2NvbXBsZXRlOiBzZWFyY2hUZXJtIH0sXG4gICAgICAgIGlkOiB7ICRuZTogdGhpcy5jaGF0Q2xpZW50U2VydmljZS5jaGF0Q2xpZW50LnVzZXJJRCEgfSxcbiAgICAgIH0gYXMgVXNlckZpbHRlcnM8VD4pOyAvLyBUT0RPOiBmaW5kIG91dCB3aHkgd2UgbmVlZCB0eXBlY2FzdCBoZXJlXG4gICAgICByZXR1cm4gT2JqZWN0LnZhbHVlcyhyZXN1bHQubWVtYmVycyk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFtSdW5zIGEgbWVzc2FnZSBhY3Rpb25dKGh0dHBzOi8vZ2V0c3RyZWFtLmlvL2NoYXQvZG9jcy9yZXN0LyNtZXNzYWdlcy1ydW5tZXNzYWdlYWN0aW9uKSBpbiB0aGUgY3VycmVudCBjaGFubmVsLiBVcGRhdGVzIHRoZSBtZXNzYWdlIGxpc3QgYmFzZWQgb24gdGhlIGFjdGlvbiByZXN1bHQgKGlmIG5vIG1lc3NhZ2UgaXMgcmV0dXJuZWQsIHRoZSBtZXNzYWdlIHdpbGwgYmUgcmVtb3ZlZCBmcm9tIHRoZSBtZXNzYWdlIGxpc3QpLlxuICAgKiBAcGFyYW0gbWVzc2FnZUlkXG4gICAqIEBwYXJhbSBmb3JtRGF0YVxuICAgKiBAcGFyYW0gcGFyZW50TWVzc2FnZUlkXG4gICAqL1xuICBhc3luYyBzZW5kQWN0aW9uKFxuICAgIG1lc3NhZ2VJZDogc3RyaW5nLFxuICAgIGZvcm1EYXRhOiBSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+LFxuICAgIHBhcmVudE1lc3NhZ2VJZD86IHN0cmluZ1xuICApIHtcbiAgICBjb25zdCBjaGFubmVsID0gdGhpcy5hY3RpdmVDaGFubmVsU3ViamVjdC5nZXRWYWx1ZSgpITtcbiAgICBjb25zdCByZXNwb25zZSA9IGF3YWl0IGNoYW5uZWwuc2VuZEFjdGlvbihtZXNzYWdlSWQsIGZvcm1EYXRhKTtcbiAgICBpZiAocmVzcG9uc2U/Lm1lc3NhZ2UpIHtcbiAgICAgIGNoYW5uZWwuc3RhdGUuYWRkTWVzc2FnZVNvcnRlZCh7XG4gICAgICAgIC4uLnJlc3BvbnNlLm1lc3NhZ2UsXG4gICAgICAgIHN0YXR1czogJ3JlY2VpdmVkJyxcbiAgICAgIH0pO1xuICAgICAgY29uc3QgaXNUaHJlYWRSZXBseSA9ICEhcmVzcG9uc2UubWVzc2FnZS5wYXJlbnRfaWQ7XG4gICAgICBpc1RocmVhZFJlcGx5XG4gICAgICAgID8gdGhpcy5hY3RpdmVUaHJlYWRNZXNzYWdlc1N1YmplY3QubmV4dChbXG4gICAgICAgICAgICAuLi5jaGFubmVsLnN0YXRlLnRocmVhZHNbcmVzcG9uc2UubWVzc2FnZS5wYXJlbnRfaWQhXSxcbiAgICAgICAgICBdKVxuICAgICAgICA6IHRoaXMuYWN0aXZlQ2hhbm5lbE1lc3NhZ2VzU3ViamVjdC5uZXh0KFsuLi5jaGFubmVsLnN0YXRlLm1lc3NhZ2VzXSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIGNoYW5uZWwuc3RhdGUucmVtb3ZlTWVzc2FnZSh7XG4gICAgICAgIGlkOiBtZXNzYWdlSWQsXG4gICAgICAgIHBhcmVudF9pZDogcGFyZW50TWVzc2FnZUlkLFxuICAgICAgfSk7XG4gICAgICBpZiAocGFyZW50TWVzc2FnZUlkKSB7XG4gICAgICAgIHRoaXMuYWN0aXZlVGhyZWFkTWVzc2FnZXNTdWJqZWN0Lm5leHQoXG4gICAgICAgICAgY2hhbm5lbC5zdGF0ZS50aHJlYWRzW3RoaXMuYWN0aXZlUGFyZW50TWVzc2FnZUlkU3ViamVjdC5nZXRWYWx1ZSgpIV1cbiAgICAgICAgKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHRoaXMuYWN0aXZlQ2hhbm5lbE1lc3NhZ2VzU3ViamVjdC5uZXh0KFsuLi5jaGFubmVsLnN0YXRlLm1lc3NhZ2VzXSk7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFNlbGVjdHMgb3IgZGVzZWxlY3RzIHRoZSBjdXJyZW50IG1lc3NhZ2UgdG8gcXVvdGUgcmVwbHkgdG9cbiAgICogQHBhcmFtIG1lc3NhZ2UgVGhlIG1lc3NhZ2UgdG8gc2VsZWN0LCBpZiBjYWxsZWQgd2l0aCBgdW5kZWZpbmVkYCwgaXQgZGVzZWxlY3RzIHRoZSBtZXNzYWdlXG4gICAqL1xuICBzZWxlY3RNZXNzYWdlVG9RdW90ZShtZXNzYWdlOiBTdHJlYW1NZXNzYWdlIHwgdW5kZWZpbmVkKSB7XG4gICAgdGhpcy5tZXNzYWdlVG9RdW90ZVN1YmplY3QubmV4dChtZXNzYWdlKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBBZGQgYSBuZXcgY2hhbm5lbCB0byB0aGUgY2hhbm5lbCBsaXN0XG4gICAqIFRoZSBjaGFubmVsIHdpbGwgYmUgYWRkZWQgdG8gdGhlIGJlZ2lubmluZyBvZiB0aGUgY2hhbm5lbCBsaXN0XG4gICAqIEBwYXJhbSBjaGFubmVsXG4gICAqL1xuICBhZGRDaGFubmVsKGNoYW5uZWw6IENoYW5uZWw8VD4pIHtcbiAgICBpZiAoIXRoaXMuY2hhbm5lbHMuZmluZCgoYykgPT4gYy5jaWQgPT09IGNoYW5uZWwuY2lkKSkge1xuICAgICAgdGhpcy5jaGFubmVsc1N1YmplY3QubmV4dChbY2hhbm5lbCwgLi4udGhpcy5jaGFubmVsc10pO1xuICAgICAgdGhpcy53YXRjaEZvckNoYW5uZWxFdmVudHMoY2hhbm5lbCk7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBhc3luYyBzZW5kTWVzc2FnZVJlcXVlc3QoXG4gICAgcHJldmlldzogTWVzc2FnZVJlc3BvbnNlPFQ+IHwgU3RyZWFtTWVzc2FnZTxUPixcbiAgICBjdXN0b21EYXRhPzogUGFydGlhbDxUWydtZXNzYWdlVHlwZSddPixcbiAgICBpc1Jlc2VuZCA9IGZhbHNlXG4gICkge1xuICAgIGNvbnN0IGNoYW5uZWwgPSB0aGlzLmFjdGl2ZUNoYW5uZWxTdWJqZWN0LmdldFZhbHVlKCkhO1xuICAgIGNvbnN0IGlzVGhyZWFkUmVwbHkgPSAhIXByZXZpZXcucGFyZW50X2lkO1xuICAgIGlzVGhyZWFkUmVwbHlcbiAgICAgID8gdGhpcy5hY3RpdmVUaHJlYWRNZXNzYWdlc1N1YmplY3QubmV4dChbXG4gICAgICAgICAgLi4uY2hhbm5lbC5zdGF0ZS50aHJlYWRzW3ByZXZpZXcucGFyZW50X2lkIV0sXG4gICAgICAgIF0pXG4gICAgICA6IHRoaXMuYWN0aXZlQ2hhbm5lbE1lc3NhZ2VzU3ViamVjdC5uZXh0KFsuLi5jaGFubmVsLnN0YXRlLm1lc3NhZ2VzXSk7XG4gICAgdHJ5IHtcbiAgICAgIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgY2hhbm5lbC5zZW5kTWVzc2FnZSh7XG4gICAgICAgIGlkOiBwcmV2aWV3LmlkLFxuICAgICAgICB0ZXh0OiBwcmV2aWV3LnRleHQsXG4gICAgICAgIGF0dGFjaG1lbnRzOiBwcmV2aWV3LmF0dGFjaG1lbnRzLFxuICAgICAgICBtZW50aW9uZWRfdXNlcnM6IHByZXZpZXcubWVudGlvbmVkX3VzZXJzPy5tYXAoKHUpID0+IHUuaWQpLFxuICAgICAgICBwYXJlbnRfaWQ6IHByZXZpZXcucGFyZW50X2lkLFxuICAgICAgICBxdW90ZWRfbWVzc2FnZV9pZDogcHJldmlldy5xdW90ZWRfbWVzc2FnZV9pZCxcbiAgICAgICAgLi4uY3VzdG9tRGF0YSxcbiAgICAgIH0gYXMgTWVzc2FnZTxUPik7IC8vIFRPRE86IGZpbmQgb3V0IHdoeSB3ZSBuZWVkIHR5cGVjYXN0IGhlcmVcbiAgICAgIGNoYW5uZWwuc3RhdGUuYWRkTWVzc2FnZVNvcnRlZChcbiAgICAgICAge1xuICAgICAgICAgIC4uLnJlc3BvbnNlLm1lc3NhZ2UsXG4gICAgICAgICAgc3RhdHVzOiAncmVjZWl2ZWQnLFxuICAgICAgICB9LFxuICAgICAgICB0cnVlXG4gICAgICApO1xuICAgICAgaXNUaHJlYWRSZXBseVxuICAgICAgICA/IHRoaXMuYWN0aXZlVGhyZWFkTWVzc2FnZXNTdWJqZWN0Lm5leHQoW1xuICAgICAgICAgICAgLi4uY2hhbm5lbC5zdGF0ZS50aHJlYWRzW3ByZXZpZXcucGFyZW50X2lkIV0sXG4gICAgICAgICAgXSlcbiAgICAgICAgOiB0aGlzLmFjdGl2ZUNoYW5uZWxNZXNzYWdlc1N1YmplY3QubmV4dChbLi4uY2hhbm5lbC5zdGF0ZS5tZXNzYWdlc10pO1xuICAgICAgbGV0IG1lc3NhZ2VzITogU3RyZWFtTWVzc2FnZTxUPltdO1xuICAgICAgKGlzVGhyZWFkUmVwbHkgPyB0aGlzLmFjdGl2ZVRocmVhZE1lc3NhZ2VzJCA6IHRoaXMuYWN0aXZlQ2hhbm5lbE1lc3NhZ2VzJClcbiAgICAgICAgLnBpcGUodGFrZSgxKSlcbiAgICAgICAgLnN1YnNjcmliZSgobSkgPT4gKG1lc3NhZ2VzID0gbSkpO1xuICAgICAgY29uc3QgbmV3TWVzc2FnZSA9IG1lc3NhZ2VzW21lc3NhZ2VzLmxlbmd0aCAtIDFdITtcbiAgICAgIHJldHVybiBuZXdNZXNzYWdlO1xuICAgIH0gY2F0Y2ggKGVycm9yOiBhbnkpIHtcbiAgICAgIGNvbnN0IHN0cmluZ0Vycm9yID0gSlNPTi5zdHJpbmdpZnkoZXJyb3IpO1xuICAgICAgY29uc3QgcGFyc2VkRXJyb3I6IHtcbiAgICAgICAgc3RhdHVzPzogbnVtYmVyO1xuICAgICAgICBjb2RlPzogbnVtYmVyO1xuICAgICAgICByZXNwb25zZT86IHsgZGF0YT86IHsgbWVzc2FnZT86IHN0cmluZyB9IH07XG4gICAgICB9ID0gc3RyaW5nRXJyb3IgPyAoSlNPTi5wYXJzZShzdHJpbmdFcnJvcikgYXMgeyBzdGF0dXM/OiBudW1iZXIgfSkgOiB7fTtcblxuICAgICAgbGV0IGlzQWxyZWFkeUV4aXN0cyA9IGZhbHNlO1xuICAgICAgaWYgKGlzUmVzZW5kKSB7XG4gICAgICAgIGlmIChcbiAgICAgICAgICBwYXJzZWRFcnJvci5zdGF0dXMgPT09IDQwMCAmJlxuICAgICAgICAgIHBhcnNlZEVycm9yLmNvZGUgPT09IDQgJiZcbiAgICAgICAgICBwYXJzZWRFcnJvcj8ucmVzcG9uc2U/LmRhdGE/Lm1lc3NhZ2U/LmluY2x1ZGVzKCdhbHJlYWR5IGV4aXN0cycpXG4gICAgICAgICkge1xuICAgICAgICAgIGlzQWxyZWFkeUV4aXN0cyA9IHRydWU7XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgY2hhbm5lbC5zdGF0ZS5hZGRNZXNzYWdlU29ydGVkKFxuICAgICAgICB7XG4gICAgICAgICAgLi4uKHByZXZpZXcgYXMgTWVzc2FnZVJlc3BvbnNlPFQ+KSxcbiAgICAgICAgICBlcnJvclN0YXR1c0NvZGU6IGlzQWxyZWFkeUV4aXN0c1xuICAgICAgICAgICAgPyB1bmRlZmluZWRcbiAgICAgICAgICAgIDogcGFyc2VkRXJyb3Iuc3RhdHVzIHx8IHVuZGVmaW5lZCxcbiAgICAgICAgICBzdGF0dXM6IGlzQWxyZWFkeUV4aXN0cyA/ICdyZWNlaXZlZCcgOiAnZmFpbGVkJyxcbiAgICAgICAgfSxcbiAgICAgICAgdHJ1ZVxuICAgICAgKTtcbiAgICAgIGlzVGhyZWFkUmVwbHlcbiAgICAgICAgPyB0aGlzLmFjdGl2ZVRocmVhZE1lc3NhZ2VzU3ViamVjdC5uZXh0KFtcbiAgICAgICAgICAgIC4uLmNoYW5uZWwuc3RhdGUudGhyZWFkc1twcmV2aWV3LnBhcmVudF9pZCFdLFxuICAgICAgICAgIF0pXG4gICAgICAgIDogdGhpcy5hY3RpdmVDaGFubmVsTWVzc2FnZXNTdWJqZWN0Lm5leHQoWy4uLmNoYW5uZWwuc3RhdGUubWVzc2FnZXNdKTtcbiAgICAgIGxldCBtZXNzYWdlcyE6IFN0cmVhbU1lc3NhZ2U8VD5bXTtcbiAgICAgIChpc1RocmVhZFJlcGx5ID8gdGhpcy5hY3RpdmVUaHJlYWRNZXNzYWdlcyQgOiB0aGlzLmFjdGl2ZUNoYW5uZWxNZXNzYWdlcyQpXG4gICAgICAgIC5waXBlKHRha2UoMSkpXG4gICAgICAgIC5zdWJzY3JpYmUoKG0pID0+IChtZXNzYWdlcyA9IG0pKTtcbiAgICAgIGNvbnN0IG5ld01lc3NhZ2UgPSBtZXNzYWdlc1ttZXNzYWdlcy5sZW5ndGggLSAxXSE7XG4gICAgICByZXR1cm4gbmV3TWVzc2FnZTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogSnVtcHMgdG8gdGhlIHNlbGVjdGVkIG1lc3NhZ2UgaW5zaWRlIHRoZSBtZXNzYWdlIGxpc3QsIGlmIHRoZSBtZXNzYWdlIGlzIG5vdCB5ZXQgbG9hZGVkLCBpdCdsbCBsb2FkIHRoZSBtZXNzYWdlIChhbmQgaXQncyBzdXJyb3VuZGluZ3MpIGZyb20gdGhlIEFQSS5cbiAgICogQHBhcmFtIG1lc3NhZ2VJZCBUaGUgSUQgb2YgdGhlIG1lc3NhZ2UgdG8gYmUgbG9hZGVkLCAnbGF0ZXN0JyBtZWFucyBqdW1wIHRvIHRoZSBsYXRlc3QgbWVzc2FnZXNcbiAgICogQHBhcmFtIHBhcmVudE1lc3NhZ2VJZCBUaGUgSUQgb2YgdGhlIHBhcmVudCBtZXNzYWdlIGlmIHdlIHdhbnQgdG8gbG9hZCBhIHRocmVhZCBtZXNzYWdlXG4gICAqL1xuICBhc3luYyBqdW1wVG9NZXNzYWdlKG1lc3NhZ2VJZDogc3RyaW5nLCBwYXJlbnRNZXNzYWdlSWQ/OiBzdHJpbmcpIHtcbiAgICBjb25zdCBhY3RpdmVDaGFubmVsID0gdGhpcy5hY3RpdmVDaGFubmVsU3ViamVjdC5nZXRWYWx1ZSgpO1xuICAgIHRyeSB7XG4gICAgICBhd2FpdCBhY3RpdmVDaGFubmVsPy5zdGF0ZS5sb2FkTWVzc2FnZUludG9TdGF0ZShcbiAgICAgICAgbWVzc2FnZUlkLFxuICAgICAgICBwYXJlbnRNZXNzYWdlSWRcbiAgICAgICk7XG4gICAgICBjb25zdCBtZXNzYWdlcyA9IGFjdGl2ZUNoYW5uZWw/LnN0YXRlLm1lc3NhZ2VzIHx8IFtdO1xuICAgICAgdGhpcy5hY3RpdmVDaGFubmVsTWVzc2FnZXNTdWJqZWN0Lm5leHQoWy4uLm1lc3NhZ2VzXSk7XG4gICAgICBpZiAocGFyZW50TWVzc2FnZUlkKSB7XG4gICAgICAgIGNvbnN0IHBhcmVudE1lc3NhZ2UgPSBtZXNzYWdlcy5maW5kKChtKSA9PiBtLmlkID09PSBwYXJlbnRNZXNzYWdlSWQpO1xuICAgICAgICB2b2lkIHRoaXMuc2V0QXNBY3RpdmVQYXJlbnRNZXNzYWdlKHBhcmVudE1lc3NhZ2UsICdzdGF0ZScpO1xuICAgICAgfVxuICAgICAgdGhpcy5qdW1wVG9NZXNzYWdlU3ViamVjdC5uZXh0KHtcbiAgICAgICAgaWQ6IG1lc3NhZ2VJZCxcbiAgICAgICAgcGFyZW50SWQ6IHBhcmVudE1lc3NhZ2VJZCxcbiAgICAgIH0pO1xuICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICB0aGlzLm5vdGlmaWNhdGlvblNlcnZpY2UuYWRkVGVtcG9yYXJ5Tm90aWZpY2F0aW9uKFxuICAgICAgICAnc3RyZWFtQ2hhdC5NZXNzYWdlIG5vdCBmb3VuZCdcbiAgICAgICk7XG4gICAgICB0aHJvdyBlcnJvcjtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogUGlucyB0aGUgZ2l2ZW4gbWVzc2FnZSBpbiB0aGUgY2hhbm5lbFxuICAgKiBAcGFyYW0gbWVzc2FnZVxuICAgKi9cbiAgYXN5bmMgcGluTWVzc2FnZShtZXNzYWdlOiBTdHJlYW1NZXNzYWdlPERlZmF1bHRTdHJlYW1DaGF0R2VuZXJpY3M+KSB7XG4gICAgdHJ5IHtcbiAgICAgIGF3YWl0IHRoaXMuY2hhdENsaWVudFNlcnZpY2UuY2hhdENsaWVudD8ucGluTWVzc2FnZShtZXNzYWdlKTtcbiAgICAgIHRoaXMubm90aWZpY2F0aW9uU2VydmljZS5hZGRUZW1wb3JhcnlOb3RpZmljYXRpb24oXG4gICAgICAgICdzdHJlYW1DaGF0Lk1lc3NhZ2UgcGlubmVkJyxcbiAgICAgICAgJ3N1Y2Nlc3MnXG4gICAgICApO1xuICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICB0aGlzLm5vdGlmaWNhdGlvblNlcnZpY2UuYWRkVGVtcG9yYXJ5Tm90aWZpY2F0aW9uKFxuICAgICAgICAnc3RyZWFtQ2hhdC5FcnJvciBwaW5uaW5nIG1lc3NhZ2UnXG4gICAgICApO1xuICAgICAgdGhyb3cgZXJyb3I7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFJlbW92ZXMgdGhlIGdpdmVuIG1lc3NhZ2UgZnJvbSBwaW5uZWQgbWVzc2FnZXNcbiAgICogQHBhcmFtIG1lc3NhZ2VcbiAgICovXG4gIGFzeW5jIHVucGluTWVzc2FnZShtZXNzYWdlOiBTdHJlYW1NZXNzYWdlPERlZmF1bHRTdHJlYW1DaGF0R2VuZXJpY3M+KSB7XG4gICAgdHJ5IHtcbiAgICAgIGF3YWl0IHRoaXMuY2hhdENsaWVudFNlcnZpY2UuY2hhdENsaWVudD8udW5waW5NZXNzYWdlKG1lc3NhZ2UpO1xuICAgICAgdGhpcy5ub3RpZmljYXRpb25TZXJ2aWNlLmFkZFRlbXBvcmFyeU5vdGlmaWNhdGlvbihcbiAgICAgICAgJ3N0cmVhbUNoYXQuTWVzc2FnZSB1bnBpbm5lZCcsXG4gICAgICAgICdzdWNjZXNzJ1xuICAgICAgKTtcbiAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgdGhpcy5ub3RpZmljYXRpb25TZXJ2aWNlLmFkZFRlbXBvcmFyeU5vdGlmaWNhdGlvbihcbiAgICAgICAgJ3N0cmVhbUNoYXQuRXJyb3IgcmVtb3ZpbmcgbWVzc2FnZSBwaW4nXG4gICAgICApO1xuICAgICAgdGhyb3cgZXJyb3I7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBoYW5kbGVOb3RpZmljYXRpb24oY2xpZW50RXZlbnQ6IENsaWVudEV2ZW50PFQ+KSB7XG4gICAgc3dpdGNoIChjbGllbnRFdmVudC5ldmVudFR5cGUpIHtcbiAgICAgIGNhc2UgJ2Nvbm5lY3Rpb24ucmVjb3ZlcmVkJzoge1xuICAgICAgICB2b2lkIHRoaXMubmdab25lLnJ1bihhc3luYyAoKSA9PiB7XG4gICAgICAgICAgaWYgKHRoaXMuaXNTdGF0ZVJlY292ZXJ5SW5Qcm9ncmVzcykge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgIH1cbiAgICAgICAgICB0aGlzLmlzU3RhdGVSZWNvdmVyeUluUHJvZ3Jlc3MgPSB0cnVlO1xuICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICB0aGlzLm5leHRQYWdlQ29uZmlndXJhdGlvbiA9IHVuZGVmaW5lZDtcbiAgICAgICAgICAgIC8vIElmIGNoYW5uZWwgbGlzdCBpcyBub3QgaW5pdGVkLCB3ZSBzZXQgdGhlIGFjdGl2ZSBjaGFubmVsXG4gICAgICAgICAgICBjb25zdCBzaG91bFNldEFjdGl2ZUNoYW5uZWwgPVxuICAgICAgICAgICAgICB0aGlzLnNob3VsZFNldEFjdGl2ZUNoYW5uZWwgJiZcbiAgICAgICAgICAgICAgIXRoaXMuYWN0aXZlQ2hhbm5lbFN1YmplY3QuZ2V0VmFsdWUoKTtcbiAgICAgICAgICAgIGF3YWl0IHRoaXMucXVlcnlDaGFubmVscyhzaG91bFNldEFjdGl2ZUNoYW5uZWwgfHwgZmFsc2UsIHRydWUpO1xuICAgICAgICAgICAgaWYgKHRoaXMuYWN0aXZlQ2hhbm5lbFN1YmplY3QuZ2V0VmFsdWUoKSkge1xuICAgICAgICAgICAgICAvLyBUaHJlYWQgbWVzc2FnZXMgYXJlIG5vdCByZWZldGNoZWQgc28gYWN0aXZlIHRocmVhZCBnZXRzIGRlc2VsZWN0ZWQgdG8gYXZvaWQgZGlzcGxheWluZyBzdGFsZSBtZXNzYWdlc1xuICAgICAgICAgICAgICB2b2lkIHRoaXMuc2V0QXNBY3RpdmVQYXJlbnRNZXNzYWdlKHVuZGVmaW5lZCk7XG4gICAgICAgICAgICAgIC8vIFVwZGF0ZSBhbmQgcmVzZWxlY3QgbWVzc2FnZSB0byBxdW90ZVxuICAgICAgICAgICAgICBjb25zdCBtZXNzYWdlVG9RdW90ZSA9IHRoaXMubWVzc2FnZVRvUXVvdGVTdWJqZWN0LmdldFZhbHVlKCk7XG4gICAgICAgICAgICAgIHRoaXMuc2V0Q2hhbm5lbFN0YXRlKHRoaXMuYWN0aXZlQ2hhbm5lbFN1YmplY3QuZ2V0VmFsdWUoKSEpO1xuICAgICAgICAgICAgICBsZXQgbWVzc2FnZXMhOiBTdHJlYW1NZXNzYWdlPFQ+W107XG4gICAgICAgICAgICAgIHRoaXMuYWN0aXZlQ2hhbm5lbE1lc3NhZ2VzJFxuICAgICAgICAgICAgICAgIC5waXBlKHRha2UoMSkpXG4gICAgICAgICAgICAgICAgLnN1YnNjcmliZSgobSkgPT4gKG1lc3NhZ2VzID0gbSkpO1xuICAgICAgICAgICAgICBjb25zdCB1cGRhdGVkTWVzc2FnZVRvUXVvdGUgPSBtZXNzYWdlcy5maW5kKFxuICAgICAgICAgICAgICAgIChtKSA9PiBtLmlkID09PSBtZXNzYWdlVG9RdW90ZT8uaWRcbiAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgaWYgKHVwZGF0ZWRNZXNzYWdlVG9RdW90ZSkge1xuICAgICAgICAgICAgICAgIHRoaXMuc2VsZWN0TWVzc2FnZVRvUXVvdGUodXBkYXRlZE1lc3NhZ2VUb1F1b3RlKTtcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhpcy5pc1N0YXRlUmVjb3ZlcnlJblByb2dyZXNzID0gZmFsc2U7XG4gICAgICAgICAgfSBjYXRjaCB7XG4gICAgICAgICAgICB0aGlzLmlzU3RhdGVSZWNvdmVyeUluUHJvZ3Jlc3MgPSBmYWxzZTtcbiAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgICAgICBicmVhaztcbiAgICAgIH1cbiAgICAgIGNhc2UgJ25vdGlmaWNhdGlvbi5tZXNzYWdlX25ldyc6IHtcbiAgICAgICAgdGhpcy5uZ1pvbmUucnVuKCgpID0+IHtcbiAgICAgICAgICBpZiAodGhpcy5jdXN0b21OZXdNZXNzYWdlTm90aWZpY2F0aW9uSGFuZGxlcikge1xuICAgICAgICAgICAgdGhpcy5jdXN0b21OZXdNZXNzYWdlTm90aWZpY2F0aW9uSGFuZGxlcihcbiAgICAgICAgICAgICAgY2xpZW50RXZlbnQsXG4gICAgICAgICAgICAgIHRoaXMuY2hhbm5lbExpc3RTZXR0ZXJcbiAgICAgICAgICAgICk7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHRoaXMuaGFuZGxlTmV3TWVzc2FnZU5vdGlmaWNhdGlvbihjbGllbnRFdmVudCk7XG4gICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICAgICAgYnJlYWs7XG4gICAgICB9XG4gICAgICBjYXNlICdub3RpZmljYXRpb24uYWRkZWRfdG9fY2hhbm5lbCc6IHtcbiAgICAgICAgdGhpcy5uZ1pvbmUucnVuKCgpID0+IHtcbiAgICAgICAgICBpZiAodGhpcy5jdXN0b21BZGRlZFRvQ2hhbm5lbE5vdGlmaWNhdGlvbkhhbmRsZXIpIHtcbiAgICAgICAgICAgIHRoaXMuY3VzdG9tQWRkZWRUb0NoYW5uZWxOb3RpZmljYXRpb25IYW5kbGVyKFxuICAgICAgICAgICAgICBjbGllbnRFdmVudCxcbiAgICAgICAgICAgICAgdGhpcy5jaGFubmVsTGlzdFNldHRlclxuICAgICAgICAgICAgKTtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgdGhpcy5oYW5kbGVBZGRlZFRvQ2hhbm5lbE5vdGlmaWNhdGlvbihjbGllbnRFdmVudCk7XG4gICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICAgICAgYnJlYWs7XG4gICAgICB9XG4gICAgICBjYXNlICdub3RpZmljYXRpb24ucmVtb3ZlZF9mcm9tX2NoYW5uZWwnOiB7XG4gICAgICAgIHRoaXMubmdab25lLnJ1bigoKSA9PiB7XG4gICAgICAgICAgaWYgKHRoaXMuY3VzdG9tUmVtb3ZlZEZyb21DaGFubmVsTm90aWZpY2F0aW9uSGFuZGxlcikge1xuICAgICAgICAgICAgdGhpcy5jdXN0b21SZW1vdmVkRnJvbUNoYW5uZWxOb3RpZmljYXRpb25IYW5kbGVyKFxuICAgICAgICAgICAgICBjbGllbnRFdmVudCxcbiAgICAgICAgICAgICAgdGhpcy5jaGFubmVsTGlzdFNldHRlclxuICAgICAgICAgICAgKTtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgdGhpcy5oYW5kbGVSZW1vdmVkRnJvbUNoYW5uZWxOb3RpZmljYXRpb24oY2xpZW50RXZlbnQpO1xuICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgICAgIGJyZWFrO1xuICAgICAgfVxuICAgICAgY2FzZSAndXNlci51cGRhdGVkJzoge1xuICAgICAgICB0aGlzLm5nWm9uZS5ydW4oKCkgPT4ge1xuICAgICAgICAgIGNvbnN0IHVwZGF0ZWRDaGFubmVscyA9IHRoaXMuY2hhbm5lbHNTdWJqZWN0LmdldFZhbHVlKCk/Lm1hcCgoYykgPT4ge1xuICAgICAgICAgICAgaWYgKHRoaXMuY2hhdENsaWVudFNlcnZpY2UuY2hhdENsaWVudC5hY3RpdmVDaGFubmVsc1tjLmNpZF0pIHtcbiAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuY2hhdENsaWVudFNlcnZpY2UuY2hhdENsaWVudC5hY3RpdmVDaGFubmVsc1tjLmNpZF07XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICByZXR1cm4gYztcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9KTtcbiAgICAgICAgICB0aGlzLmNoYW5uZWxzU3ViamVjdC5uZXh0KHVwZGF0ZWRDaGFubmVscyk7XG4gICAgICAgICAgY29uc3QgYWN0aXZlQ2hhbm5lbCA9IHRoaXMuYWN0aXZlQ2hhbm5lbFN1YmplY3QuZ2V0VmFsdWUoKTtcbiAgICAgICAgICBpZiAoYWN0aXZlQ2hhbm5lbCkge1xuICAgICAgICAgICAgdGhpcy5hY3RpdmVDaGFubmVsU3ViamVjdC5uZXh0KFxuICAgICAgICAgICAgICB0aGlzLmNoYXRDbGllbnRTZXJ2aWNlLmNoYXRDbGllbnQuYWN0aXZlQ2hhbm5lbHNbXG4gICAgICAgICAgICAgICAgYWN0aXZlQ2hhbm5lbC5jaWRcbiAgICAgICAgICAgICAgXSB8fCBhY3RpdmVDaGFubmVsXG4gICAgICAgICAgICApO1xuICAgICAgICAgICAgdGhpcy5hY3RpdmVDaGFubmVsTWVzc2FnZXNTdWJqZWN0Lm5leHQoXG4gICAgICAgICAgICAgIGFjdGl2ZUNoYW5uZWwuc3RhdGUubWVzc2FnZXMubWFwKChtKSA9PiB7XG4gICAgICAgICAgICAgICAgbS5yZWFkQnkgPSBnZXRSZWFkQnkobSwgYWN0aXZlQ2hhbm5lbCk7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHsgLi4ubSB9O1xuICAgICAgICAgICAgICB9KVxuICAgICAgICAgICAgKTtcbiAgICAgICAgICAgIGNvbnN0IGFjdGl2ZVBhcmVudE1lc3NhZ2UgPVxuICAgICAgICAgICAgICB0aGlzLmFjdGl2ZVBhcmVudE1lc3NhZ2VJZFN1YmplY3QuZ2V0VmFsdWUoKTtcbiAgICAgICAgICAgIGlmIChhY3RpdmVQYXJlbnRNZXNzYWdlKSB7XG4gICAgICAgICAgICAgIGNvbnN0IG1lc3NhZ2VzID0gYWN0aXZlQ2hhbm5lbC5zdGF0ZS50aHJlYWRzW2FjdGl2ZVBhcmVudE1lc3NhZ2VdO1xuICAgICAgICAgICAgICB0aGlzLmFjdGl2ZVRocmVhZE1lc3NhZ2VzU3ViamVjdC5uZXh0KFsuLi5tZXNzYWdlc10pO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhpcy5hY3RpdmVDaGFubmVsUGlubmVkTWVzc2FnZXNTdWJqZWN0Lm5leHQoW1xuICAgICAgICAgICAgICAuLi5hY3RpdmVDaGFubmVsLnN0YXRlLnBpbm5lZE1lc3NhZ2VzLFxuICAgICAgICAgICAgXSk7XG4gICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICAgICAgYnJlYWs7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBoYW5kbGVSZW1vdmVkRnJvbUNoYW5uZWxOb3RpZmljYXRpb24oY2xpZW50RXZlbnQ6IENsaWVudEV2ZW50PFQ+KSB7XG4gICAgY29uc3QgY2hhbm5lbElkVG9CZVJlbW92ZWQgPSBjbGllbnRFdmVudC5ldmVudC5jaGFubmVsIS5jaWQ7XG4gICAgdGhpcy5yZW1vdmVDaGFubmVsc0Zyb21DaGFubmVsTGlzdChbY2hhbm5lbElkVG9CZVJlbW92ZWRdLCB0cnVlKTtcbiAgfVxuXG4gIHByaXZhdGUgaGFuZGxlTmV3TWVzc2FnZU5vdGlmaWNhdGlvbihjbGllbnRFdmVudDogQ2xpZW50RXZlbnQ8VD4pIHtcbiAgICBpZiAoY2xpZW50RXZlbnQuZXZlbnQuY2hhbm5lbCkge1xuICAgICAgdm9pZCB0aGlzLmFkZENoYW5uZWxzRnJvbU5vdGlmaWNhdGlvbihbY2xpZW50RXZlbnQuZXZlbnQuY2hhbm5lbF0pO1xuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgaGFuZGxlQWRkZWRUb0NoYW5uZWxOb3RpZmljYXRpb24oY2xpZW50RXZlbnQ6IENsaWVudEV2ZW50PFQ+KSB7XG4gICAgaWYgKGNsaWVudEV2ZW50LmV2ZW50LmNoYW5uZWwpIHtcbiAgICAgIHZvaWQgdGhpcy5hZGRDaGFubmVsc0Zyb21Ob3RpZmljYXRpb24oW2NsaWVudEV2ZW50LmV2ZW50LmNoYW5uZWxdKTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIGFzeW5jIGFkZENoYW5uZWxzRnJvbU5vdGlmaWNhdGlvbihcbiAgICBjaGFubmVsUmVzcG9uc2VzOiBDaGFubmVsUmVzcG9uc2U8VD5bXVxuICApIHtcbiAgICBsZXQgbmV3Q2hhbm5lbHM6IENoYW5uZWw8VD5bXSA9IFtdO1xuICAgIGNvbnN0IHdhdGNoUmVxdWVzdHM6IFByb21pc2U8YW55PltdID0gW107XG4gICAgY2hhbm5lbFJlc3BvbnNlcy5mb3JFYWNoKChjaGFubmVsUmVzcG9uc2UpID0+IHtcbiAgICAgIGNvbnN0IGNoYW5uZWwgPSB0aGlzLmNoYXRDbGllbnRTZXJ2aWNlLmNoYXRDbGllbnQuY2hhbm5lbChcbiAgICAgICAgY2hhbm5lbFJlc3BvbnNlLnR5cGUsXG4gICAgICAgIGNoYW5uZWxSZXNwb25zZS5pZFxuICAgICAgKTtcbiAgICAgIHdhdGNoUmVxdWVzdHMucHVzaChjaGFubmVsLndhdGNoKCkpO1xuICAgICAgbmV3Q2hhbm5lbHMucHVzaChjaGFubmVsKTtcbiAgICB9KTtcbiAgICBhd2FpdCBQcm9taXNlLmFsbCh3YXRjaFJlcXVlc3RzKTtcbiAgICBjb25zdCBjdXJyZW50Q2hhbm5lbHMgPSB0aGlzLmNoYW5uZWxzU3ViamVjdC5nZXRWYWx1ZSgpIHx8IFtdO1xuICAgIG5ld0NoYW5uZWxzID0gbmV3Q2hhbm5lbHMuZmlsdGVyKFxuICAgICAgKG5ld0NoYW5uZWwpID0+ICFjdXJyZW50Q2hhbm5lbHMuZmluZCgoYykgPT4gYy5jaWQgPT09IG5ld0NoYW5uZWwuY2lkKVxuICAgICk7XG4gICAgaWYgKG5ld0NoYW5uZWxzLmxlbmd0aCA+IDApIHtcbiAgICAgIG5ld0NoYW5uZWxzLmZvckVhY2goKGMpID0+IHRoaXMud2F0Y2hGb3JDaGFubmVsRXZlbnRzKGMpKTtcbiAgICAgIHRoaXMuY2hhbm5lbHNTdWJqZWN0Lm5leHQoWy4uLm5ld0NoYW5uZWxzLCAuLi5jdXJyZW50Q2hhbm5lbHNdKTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIHJlbW92ZUNoYW5uZWxzRnJvbUNoYW5uZWxMaXN0KFxuICAgIGNpZHM6IHN0cmluZ1tdLFxuICAgIHNob3VsZFN0b3BXYXRjaGluZzogYm9vbGVhblxuICApIHtcbiAgICBjb25zdCBjaGFubmVscyA9IHRoaXMuY2hhbm5lbHMuZmlsdGVyKChjKSA9PiAhY2lkcy5pbmNsdWRlcyhjLmNpZCB8fCAnJykpO1xuICAgIGlmIChzaG91bGRTdG9wV2F0Y2hpbmcpIHtcbiAgICAgIGNpZHMuZm9yRWFjaCgoY2lkKSA9PiB7XG4gICAgICAgIGlmICh0aGlzLmNoYW5uZWxTdWJzY3JpcHRpb25zW2NpZF0pIHtcbiAgICAgICAgICB0aGlzLmNoYW5uZWxTdWJzY3JpcHRpb25zW2NpZF0oKTtcbiAgICAgICAgICBkZWxldGUgdGhpcy5jaGFubmVsU3Vic2NyaXB0aW9ucy5jaWQ7XG4gICAgICAgIH1cbiAgICAgICAgdm9pZCB0aGlzLmNoYXRDbGllbnRTZXJ2aWNlLmNoYXRDbGllbnQuYWN0aXZlQ2hhbm5lbHNbXG4gICAgICAgICAgY2lkXG4gICAgICAgIF0/LnN0b3BXYXRjaGluZygpO1xuICAgICAgfSk7XG4gICAgfVxuICAgIGlmIChjaGFubmVscy5sZW5ndGggPCB0aGlzLmNoYW5uZWxzLmxlbmd0aCkge1xuICAgICAgdGhpcy5jaGFubmVsc1N1YmplY3QubmV4dChjaGFubmVscyk7XG4gICAgICBpZiAoY2lkcy5pbmNsdWRlcyh0aGlzLmFjdGl2ZUNoYW5uZWxTdWJqZWN0LmdldFZhbHVlKCk/LmNpZCB8fCAnJykpIHtcbiAgICAgICAgaWYgKGNoYW5uZWxzLmxlbmd0aCA+IDApIHtcbiAgICAgICAgICB0aGlzLnNldEFzQWN0aXZlQ2hhbm5lbChjaGFubmVsc1swXSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgdGhpcy5hY3RpdmVDaGFubmVsU3ViamVjdC5uZXh0KHVuZGVmaW5lZCk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICBwcml2YXRlIHdhdGNoRm9yQWN0aXZlQ2hhbm5lbEV2ZW50cyhjaGFubmVsOiBDaGFubmVsPFQ+KSB7XG4gICAgdGhpcy5hY3RpdmVDaGFubmVsU3Vic2NyaXB0aW9ucy5wdXNoKFxuICAgICAgY2hhbm5lbC5vbignbWVzc2FnZS5uZXcnLCAoZXZlbnQpID0+IHtcbiAgICAgICAgdGhpcy5uZ1pvbmUucnVuKCgpID0+IHtcbiAgICAgICAgICBldmVudC5tZXNzYWdlICYmIGV2ZW50Lm1lc3NhZ2UucGFyZW50X2lkXG4gICAgICAgICAgICA/IGV2ZW50Lm1lc3NhZ2UucGFyZW50X2lkID09PVxuICAgICAgICAgICAgICB0aGlzLmFjdGl2ZVBhcmVudE1lc3NhZ2VJZFN1YmplY3QuZ2V0VmFsdWUoKVxuICAgICAgICAgICAgICA/IHRoaXMuYWN0aXZlVGhyZWFkTWVzc2FnZXNTdWJqZWN0Lm5leHQoW1xuICAgICAgICAgICAgICAgICAgLi4uY2hhbm5lbC5zdGF0ZS50aHJlYWRzW2V2ZW50Lm1lc3NhZ2UucGFyZW50X2lkXSxcbiAgICAgICAgICAgICAgICBdKVxuICAgICAgICAgICAgICA6IG51bGxcbiAgICAgICAgICAgIDogdGhpcy5hY3RpdmVDaGFubmVsTWVzc2FnZXNTdWJqZWN0Lm5leHQoW1xuICAgICAgICAgICAgICAgIC4uLmNoYW5uZWwuc3RhdGUubWVzc2FnZXMsXG4gICAgICAgICAgICAgIF0pO1xuICAgICAgICAgIHRoaXMuYWN0aXZlQ2hhbm5lbCQucGlwZShmaXJzdCgpKS5zdWJzY3JpYmUoKGMpID0+IHtcbiAgICAgICAgICAgIGlmIChjKSB7XG4gICAgICAgICAgICAgIHRoaXMubWFya1JlYWQoYyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfSk7XG4gICAgICAgICAgdGhpcy51cGRhdGVMYXRlc3RNZXNzYWdlcyhldmVudCk7XG4gICAgICAgIH0pO1xuICAgICAgfSlcbiAgICApO1xuICAgIHRoaXMuYWN0aXZlQ2hhbm5lbFN1YnNjcmlwdGlvbnMucHVzaChcbiAgICAgIGNoYW5uZWwub24oJ21lc3NhZ2UudXBkYXRlZCcsIChldmVudCkgPT4gdGhpcy5tZXNzYWdlVXBkYXRlZChldmVudCkpXG4gICAgKTtcbiAgICB0aGlzLmFjdGl2ZUNoYW5uZWxTdWJzY3JpcHRpb25zLnB1c2goXG4gICAgICBjaGFubmVsLm9uKCdtZXNzYWdlLmRlbGV0ZWQnLCAoZXZlbnQpID0+IHRoaXMubWVzc2FnZVVwZGF0ZWQoZXZlbnQpKVxuICAgICk7XG4gICAgdGhpcy5hY3RpdmVDaGFubmVsU3Vic2NyaXB0aW9ucy5wdXNoKFxuICAgICAgY2hhbm5lbC5vbigncmVhY3Rpb24ubmV3JywgKGUpID0+IHRoaXMubWVzc2FnZVJlYWN0aW9uRXZlbnRSZWNlaXZlZChlKSlcbiAgICApO1xuICAgIHRoaXMuYWN0aXZlQ2hhbm5lbFN1YnNjcmlwdGlvbnMucHVzaChcbiAgICAgIGNoYW5uZWwub24oJ3JlYWN0aW9uLmRlbGV0ZWQnLCAoZSkgPT5cbiAgICAgICAgdGhpcy5tZXNzYWdlUmVhY3Rpb25FdmVudFJlY2VpdmVkKGUpXG4gICAgICApXG4gICAgKTtcbiAgICB0aGlzLmFjdGl2ZUNoYW5uZWxTdWJzY3JpcHRpb25zLnB1c2goXG4gICAgICBjaGFubmVsLm9uKCdyZWFjdGlvbi51cGRhdGVkJywgKGUpID0+XG4gICAgICAgIHRoaXMubWVzc2FnZVJlYWN0aW9uRXZlbnRSZWNlaXZlZChlKVxuICAgICAgKVxuICAgICk7XG4gICAgdGhpcy5hY3RpdmVDaGFubmVsU3Vic2NyaXB0aW9ucy5wdXNoKFxuICAgICAgY2hhbm5lbC5vbignbWVzc2FnZS5yZWFkJywgKGUpID0+IHtcbiAgICAgICAgdGhpcy5uZ1pvbmUucnVuKCgpID0+IHtcbiAgICAgICAgICBsZXQgbGF0ZXN0TWVzc2FnZSE6IFN0cmVhbU1lc3NhZ2U7XG4gICAgICAgICAgbGV0IG1lc3NhZ2VzITogU3RyZWFtTWVzc2FnZVtdO1xuICAgICAgICAgIHRoaXMuYWN0aXZlQ2hhbm5lbE1lc3NhZ2VzJC5waXBlKGZpcnN0KCkpLnN1YnNjcmliZSgobSkgPT4ge1xuICAgICAgICAgICAgbWVzc2FnZXMgPSBtO1xuICAgICAgICAgICAgbGF0ZXN0TWVzc2FnZSA9IG1lc3NhZ2VzW21lc3NhZ2VzLmxlbmd0aCAtIDFdO1xuICAgICAgICAgIH0pO1xuICAgICAgICAgIGlmICghbGF0ZXN0TWVzc2FnZSB8fCAhZS51c2VyKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgfVxuICAgICAgICAgIGlmIChsYXRlc3RNZXNzYWdlLnJlYWRCeSkge1xuICAgICAgICAgICAgbGF0ZXN0TWVzc2FnZS5yZWFkQnkuc3BsaWNlKDAsIGxhdGVzdE1lc3NhZ2UucmVhZEJ5Lmxlbmd0aCk7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGxhdGVzdE1lc3NhZ2UucmVhZEJ5ID0gW107XG4gICAgICAgICAgfVxuICAgICAgICAgIGxhdGVzdE1lc3NhZ2UucmVhZEJ5LnB1c2goLi4uZ2V0UmVhZEJ5KGxhdGVzdE1lc3NhZ2UsIGNoYW5uZWwpKTtcbiAgICAgICAgICBtZXNzYWdlc1ttZXNzYWdlcy5sZW5ndGggLSAxXSA9IHsgLi4ubGF0ZXN0TWVzc2FnZSB9O1xuXG4gICAgICAgICAgdGhpcy5hY3RpdmVDaGFubmVsTWVzc2FnZXNTdWJqZWN0Lm5leHQoWy4uLm1lc3NhZ2VzXSk7XG4gICAgICAgIH0pO1xuICAgICAgfSlcbiAgICApO1xuICAgIHRoaXMuYWN0aXZlQ2hhbm5lbFN1YnNjcmlwdGlvbnMucHVzaChcbiAgICAgIHRoaXMuY2hhdENsaWVudFNlcnZpY2UuZXZlbnRzJFxuICAgICAgICAucGlwZShcbiAgICAgICAgICBmaWx0ZXIoXG4gICAgICAgICAgICAoZSkgPT5cbiAgICAgICAgICAgICAgZS5ldmVudFR5cGUgPT09ICdub3RpZmljYXRpb24ubWFya191bnJlYWQnICYmXG4gICAgICAgICAgICAgIGUuZXZlbnQuY2hhbm5lbF9pZCA9PT0gY2hhbm5lbC5pZFxuICAgICAgICAgICksXG4gICAgICAgICAgbWFwKChlKSA9PiBlLmV2ZW50KVxuICAgICAgICApXG4gICAgICAgIC5zdWJzY3JpYmUoKGUpID0+IHtcbiAgICAgICAgICB0aGlzLm5nWm9uZS5ydW4oKCkgPT4ge1xuICAgICAgICAgICAgdGhpcy5hY3RpdmVDaGFubmVsTGFzdFJlYWRNZXNzYWdlSWQgPSBlLmxhc3RfcmVhZF9tZXNzYWdlX2lkO1xuICAgICAgICAgICAgdGhpcy5hY3RpdmVDaGFubmVsVW5yZWFkQ291bnQgPSBlLnVucmVhZF9tZXNzYWdlcztcbiAgICAgICAgICAgIHRoaXMuYWN0aXZlQ2hhbm5lbFN1YmplY3QubmV4dCh0aGlzLmFjdGl2ZUNoYW5uZWwpO1xuICAgICAgICAgIH0pO1xuICAgICAgICB9KVxuICAgICk7XG4gICAgdGhpcy5hY3RpdmVDaGFubmVsU3Vic2NyaXB0aW9ucy5wdXNoKFxuICAgICAgY2hhbm5lbC5vbigndHlwaW5nLnN0YXJ0JywgKGUpID0+XG4gICAgICAgIHRoaXMubmdab25lLnJ1bigoKSA9PiB0aGlzLmhhbmRsZVR5cGluZ1N0YXJ0RXZlbnQoZSkpXG4gICAgICApXG4gICAgKTtcbiAgICB0aGlzLmFjdGl2ZUNoYW5uZWxTdWJzY3JpcHRpb25zLnB1c2goXG4gICAgICBjaGFubmVsLm9uKCd0eXBpbmcuc3RvcCcsIChlKSA9PlxuICAgICAgICB0aGlzLm5nWm9uZS5ydW4oKCkgPT4gdGhpcy5oYW5kbGVUeXBpbmdTdG9wRXZlbnQoZSkpXG4gICAgICApXG4gICAgKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBDYWxsIHRoaXMgbWV0aG9kIGlmIHVzZXIgc3RhcnRlZCB0eXBpbmcgaW4gdGhlIGFjdGl2ZSBjaGFubmVsXG4gICAqIEBwYXJhbSBwYXJlbnRJZCBUaGUgaWQgb2YgdGhlIHBhcmVudCBtZXNzYWdlLCBpZiB1c2VyIGlzIHR5cGluZyBpbiBhIHRocmVhZFxuICAgKi9cbiAgYXN5bmMgdHlwaW5nU3RhcnRlZChwYXJlbnRJZD86IHN0cmluZykge1xuICAgIGNvbnN0IGFjdGl2ZUNoYW5uZWwgPSB0aGlzLmFjdGl2ZUNoYW5uZWxTdWJqZWN0LmdldFZhbHVlKCk7XG4gICAgYXdhaXQgYWN0aXZlQ2hhbm5lbD8ua2V5c3Ryb2tlKHBhcmVudElkKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBDYWxsIHRoaXMgbWV0aG9kIGlmIHVzZXIgc3RvcHBlZCB0eXBpbmcgaW4gdGhlIGFjdGl2ZSBjaGFubmVsXG4gICAqIEBwYXJhbSBwYXJlbnRJZCBUaGUgaWQgb2YgdGhlIHBhcmVudCBtZXNzYWdlLCBpZiB1c2VyIHdlcmUgdHlwaW5nIGluIGEgdGhyZWFkXG4gICAqL1xuICBhc3luYyB0eXBpbmdTdG9wcGVkKHBhcmVudElkPzogc3RyaW5nKSB7XG4gICAgY29uc3QgYWN0aXZlQ2hhbm5lbCA9IHRoaXMuYWN0aXZlQ2hhbm5lbFN1YmplY3QuZ2V0VmFsdWUoKTtcbiAgICBhd2FpdCBhY3RpdmVDaGFubmVsPy5zdG9wVHlwaW5nKHBhcmVudElkKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBUaGUgY3VycmVudCBsaXN0IG9mIGNoYW5uZWxzXG4gICAqL1xuICBnZXQgY2hhbm5lbHMoKSB7XG4gICAgcmV0dXJuIHRoaXMuY2hhbm5lbHNTdWJqZWN0LmdldFZhbHVlKCkgfHwgW107XG4gIH1cblxuICAvKipcbiAgICogVGhlIGN1cnJlbnQgYWN0aXZlIGNoYW5uZWxcbiAgICovXG4gIGdldCBhY3RpdmVDaGFubmVsKCkge1xuICAgIHJldHVybiB0aGlzLmFjdGl2ZUNoYW5uZWxTdWJqZWN0LmdldFZhbHVlKCkgfHwgdW5kZWZpbmVkO1xuICB9XG5cbiAgLyoqXG4gICAqIFRoZSBjdXJyZW50IGFjdGl2ZSBjaGFubmVsIG1lc3NhZ2VzXG4gICAqL1xuICBnZXQgYWN0aXZlQ2hhbm5lbE1lc3NhZ2VzKCkge1xuICAgIHJldHVybiB0aGlzLmFjdGl2ZUNoYW5uZWxNZXNzYWdlc1N1YmplY3QuZ2V0VmFsdWUoKSB8fCBbXTtcbiAgfVxuXG4gIC8qKlxuICAgKiBHZXQgdGhlIGxhc3QgMTIwMCByZWFjdGlvbnMgb2YgYSBtZXNzYWdlIGluIHRoZSBjdXJyZW50IGFjdGl2ZSBjaGFubmVsLiBJZiB5b3UgbmVlZCB0byBmZXRjaCBtb3JlIHJlYWN0aW9ucyBwbGVhc2UgdXNlIHRoZSBbZm9sbG93aW5nIGVuZHBvaW50XShodHRwczovL2dldHN0cmVhbS5pby9jaGF0L2RvY3MvamF2YXNjcmlwdC9zZW5kX3JlYWN0aW9uLz9sYW5ndWFnZT1qYXZhc2NyaXB0I3BhZ2luYXRpbmctcmVhY3Rpb25zKS5cbiAgICogQHBhcmFtIG1lc3NhZ2VJZFxuICAgKiBAcmV0dXJucyBhbGwgcmVhY3Rpb25zIG9mIGEgbWVzc2FnZVxuICAgKi9cbiAgYXN5bmMgZ2V0TWVzc2FnZVJlYWN0aW9ucyhtZXNzYWdlSWQ6IHN0cmluZykge1xuICAgIGNvbnN0IHJlYWN0aW9uczogUmVhY3Rpb25SZXNwb25zZTxUPltdID0gW107XG4gICAgY29uc3QgbGltaXQgPSAzMDA7XG4gICAgbGV0IG9mZnNldCA9IDA7XG4gICAgY29uc3QgcmVhY3Rpb25zTGltaXQgPSBDaGFubmVsU2VydmljZS5NQVhfTUVTU0FHRV9SRUFDVElPTlNfVE9fRkVUQ0g7XG4gICAgbGV0IGxhc3RQYWdlU2l6ZSA9IGxpbWl0O1xuXG4gICAgd2hpbGUgKGxhc3RQYWdlU2l6ZSA9PT0gbGltaXQgJiYgcmVhY3Rpb25zLmxlbmd0aCA8IHJlYWN0aW9uc0xpbWl0KSB7XG4gICAgICB0cnkge1xuICAgICAgICBjb25zdCByZXNwb25zZSA9IGF3YWl0IHRoaXMuYWN0aXZlQ2hhbm5lbD8uZ2V0UmVhY3Rpb25zKG1lc3NhZ2VJZCwge1xuICAgICAgICAgIG9mZnNldCxcbiAgICAgICAgICBsaW1pdCxcbiAgICAgICAgfSk7XG4gICAgICAgIGxhc3RQYWdlU2l6ZSA9IHJlc3BvbnNlPy5yZWFjdGlvbnM/Lmxlbmd0aCB8fCAwO1xuICAgICAgICBpZiAobGFzdFBhZ2VTaXplID4gMCkge1xuICAgICAgICAgIHJlYWN0aW9ucy5wdXNoKC4uLnJlc3BvbnNlIS5yZWFjdGlvbnMpO1xuICAgICAgICB9XG4gICAgICAgIG9mZnNldCArPSBsYXN0UGFnZVNpemU7XG4gICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgIHRoaXMubm90aWZpY2F0aW9uU2VydmljZS5hZGRUZW1wb3JhcnlOb3RpZmljYXRpb24oXG4gICAgICAgICAgJ3N0cmVhbUNoYXQuRXJyb3IgbG9hZGluZyByZWFjdGlvbnMnXG4gICAgICAgICk7XG4gICAgICAgIHRocm93IGU7XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiByZWFjdGlvbnM7XG4gIH1cblxuICAvKipcbiAgICogTWFya3MgdGhlIGNoYW5uZWwgZnJvbSB0aGUgZ2l2ZW4gbWVzc2FnZSBhcyB1bnJlYWRcbiAgICogQHBhcmFtIG1lc3NhZ2VJZFxuICAgKiBAcmV0dXJucyB0aGUgcmVzdWx0IG9mIHRoZSByZXF1ZXN0XG4gICAqL1xuICBhc3luYyBtYXJrTWVzc2FnZVVucmVhZChtZXNzYWdlSWQ6IHN0cmluZykge1xuICAgIGlmICghdGhpcy5hY3RpdmVDaGFubmVsKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgdHJ5IHtcbiAgICAgIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgdGhpcy5hY3RpdmVDaGFubmVsLm1hcmtVbnJlYWQoe1xuICAgICAgICBtZXNzYWdlX2lkOiBtZXNzYWdlSWQsXG4gICAgICB9KTtcbiAgICAgIHRoaXMuYXJlUmVhZEV2ZW50c1BhdXNlZCA9IHRydWU7XG4gICAgICByZXR1cm4gcmVzcG9uc2U7XG4gICAgfSBjYXRjaCAoZTogYW55KSB7XG4gICAgICBjb25zdCBlcnJvcjoge1xuICAgICAgICByZXNwb25zZT86IHtcbiAgICAgICAgICBkYXRhPzogeyBjb2RlPzogbnVtYmVyOyBtZXNzYWdlPzogc3RyaW5nOyBTdGF0dXNDb2RlPzogbnVtYmVyIH07XG4gICAgICAgIH07XG4gICAgICB9ID0gSlNPTi5wYXJzZShKU09OLnN0cmluZ2lmeShlKSkgYXMge1xuICAgICAgICByZXNwb25zZT86IHtcbiAgICAgICAgICBkYXRhPzogeyBjb2RlPzogbnVtYmVyOyBtZXNzYWdlPzogc3RyaW5nOyBTdGF0dXNDb2RlPzogbnVtYmVyIH07XG4gICAgICAgIH07XG4gICAgICB9O1xuICAgICAgY29uc3QgZGF0YSA9IGVycm9yPy5yZXNwb25zZT8uZGF0YTtcbiAgICAgIGlmIChcbiAgICAgICAgZGF0YSAmJlxuICAgICAgICBkYXRhLmNvZGUgPT09IDQgJiZcbiAgICAgICAgZGF0YS5TdGF0dXNDb2RlID09PSA0MDAgJiZcbiAgICAgICAgZGF0YS5tZXNzYWdlPy5pbmNsdWRlcygnaXQgaXMgb2xkZXIgdGhhbiBsYXN0JylcbiAgICAgICkge1xuICAgICAgICBjb25zdCBjb3VudCA9IC9cXGQrIGNoYW5uZWwgbWVzc2FnZXMvXG4gICAgICAgICAgLmV4ZWMoZGF0YS5tZXNzYWdlKT8uWzBdXG4gICAgICAgICAgLm1hdGNoKC9cXGQrLyk/LlswXTtcbiAgICAgICAgaWYgKGNvdW50KSB7XG4gICAgICAgICAgdGhpcy5ub3RpZmljYXRpb25TZXJ2aWNlLmFkZFRlbXBvcmFyeU5vdGlmaWNhdGlvbihcbiAgICAgICAgICAgICdzdHJlYW1DaGF0LkVycm9yLCBvbmx5IHRoZSBmaXJzdCB7e2NvdW50fX0gbWVzc2FnZSBjYW4gYmUgbWFya2VkIGFzIHVucmVhZCcsXG4gICAgICAgICAgICB1bmRlZmluZWQsXG4gICAgICAgICAgICB1bmRlZmluZWQsXG4gICAgICAgICAgICB7IGNvdW50IH1cbiAgICAgICAgICApO1xuICAgICAgICAgIHRocm93IGU7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIHRoaXMubm90aWZpY2F0aW9uU2VydmljZS5hZGRUZW1wb3JhcnlOb3RpZmljYXRpb24oXG4gICAgICAgICdzdHJlYW1DaGF0LkVycm9yIG1hcmtpbmcgbWVzc2FnZSBhcyB1bnJlYWQnXG4gICAgICApO1xuICAgICAgdGhyb3cgZTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIG1lc3NhZ2VVcGRhdGVkKGV2ZW50OiBFdmVudDxUPikge1xuICAgIHRoaXMubmdab25lLnJ1bigoKSA9PiB7XG4gICAgICBjb25zdCBpc1RocmVhZFJlcGx5ID0gZXZlbnQubWVzc2FnZSAmJiBldmVudC5tZXNzYWdlLnBhcmVudF9pZDtcbiAgICAgIGNvbnN0IGNoYW5uZWwgPSB0aGlzLmFjdGl2ZUNoYW5uZWxTdWJqZWN0LmdldFZhbHVlKCk7XG4gICAgICBpZiAoIWNoYW5uZWwpIHtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuICAgICAgLy8gR2V0IG1lc3NhZ2VzIGZyb20gc3RhdGUgYXMgbWVzc2FnZSBvcmRlciBjb3VsZCBjaGFuZ2UsIGFuZCBtZXNzYWdlIGNvdWxkJ3ZlIGJlZW4gZGVsZXRlZFxuICAgICAgY29uc3QgbWVzc2FnZXM6IEZvcm1hdE1lc3NhZ2VSZXNwb25zZTxUPltdID0gaXNUaHJlYWRSZXBseVxuICAgICAgICA/IGNoYW5uZWwuc3RhdGUudGhyZWFkc1tldmVudD8ubWVzc2FnZT8ucGFyZW50X2lkIHx8ICcnXVxuICAgICAgICA6IGNoYW5uZWwuc3RhdGUubWVzc2FnZXM7XG4gICAgICBpZiAoIW1lc3NhZ2VzKSB7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cbiAgICAgIGNvbnN0IG1lc3NhZ2VJbmRleCA9IG1lc3NhZ2VzLmZpbmRJbmRleChcbiAgICAgICAgKG0pID0+IG0uaWQgPT09IGV2ZW50Py5tZXNzYWdlPy5pZFxuICAgICAgKTtcbiAgICAgIGlmIChtZXNzYWdlSW5kZXggIT09IC0xKSB7XG4gICAgICAgIGlzVGhyZWFkUmVwbHlcbiAgICAgICAgICA/IHRoaXMuYWN0aXZlVGhyZWFkTWVzc2FnZXNTdWJqZWN0Lm5leHQoWy4uLm1lc3NhZ2VzXSlcbiAgICAgICAgICA6IHRoaXMuYWN0aXZlQ2hhbm5lbE1lc3NhZ2VzU3ViamVjdC5uZXh0KFsuLi5tZXNzYWdlc10pO1xuICAgICAgICB0aGlzLmFjdGl2ZUNoYW5uZWxQaW5uZWRNZXNzYWdlc1N1YmplY3QubmV4dChbXG4gICAgICAgICAgLi4uY2hhbm5lbC5zdGF0ZS5waW5uZWRNZXNzYWdlcyxcbiAgICAgICAgXSk7XG4gICAgICB9XG4gICAgfSk7XG4gIH1cblxuICBwcml2YXRlIG1lc3NhZ2VSZWFjdGlvbkV2ZW50UmVjZWl2ZWQoZTogRXZlbnQ8VD4pIHtcbiAgICB0aGlzLm5nWm9uZS5ydW4oKCkgPT4ge1xuICAgICAgY29uc3QgaXNUaHJlYWRNZXNzYWdlID0gZS5tZXNzYWdlICYmIGUubWVzc2FnZS5wYXJlbnRfaWQ7XG4gICAgICBsZXQgbWVzc2FnZXMhOiBTdHJlYW1NZXNzYWdlW107XG4gICAgICAoaXNUaHJlYWRNZXNzYWdlXG4gICAgICAgID8gdGhpcy5hY3RpdmVUaHJlYWRNZXNzYWdlcyRcbiAgICAgICAgOiB0aGlzLmFjdGl2ZUNoYW5uZWxNZXNzYWdlcyRcbiAgICAgIClcbiAgICAgICAgLnBpcGUoZmlyc3QoKSlcbiAgICAgICAgLnN1YnNjcmliZSgobSkgPT4gKG1lc3NhZ2VzID0gbSkpO1xuICAgICAgY29uc3QgbWVzc2FnZUluZGV4ID0gbWVzc2FnZXMuZmluZEluZGV4KChtKSA9PiBtLmlkID09PSBlPy5tZXNzYWdlPy5pZCk7XG4gICAgICBpZiAobWVzc2FnZUluZGV4ID09PSAtMSkge1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG4gICAgICBjb25zdCBtZXNzYWdlID0gbWVzc2FnZXNbbWVzc2FnZUluZGV4XTtcbiAgICAgIG1lc3NhZ2UucmVhY3Rpb25fY291bnRzID0geyAuLi5lLm1lc3NhZ2U/LnJlYWN0aW9uX2NvdW50cyB9O1xuICAgICAgbWVzc2FnZS5yZWFjdGlvbl9zY29yZXMgPSB7IC4uLmUubWVzc2FnZT8ucmVhY3Rpb25fc2NvcmVzIH07XG4gICAgICBtZXNzYWdlLmxhdGVzdF9yZWFjdGlvbnMgPSBbLi4uKGUubWVzc2FnZT8ubGF0ZXN0X3JlYWN0aW9ucyB8fCBbXSldO1xuICAgICAgbWVzc2FnZS5vd25fcmVhY3Rpb25zID0gWy4uLihlLm1lc3NhZ2U/Lm93bl9yZWFjdGlvbnMgfHwgW10pXTtcblxuICAgICAgbWVzc2FnZXNbbWVzc2FnZUluZGV4XSA9IHsgLi4ubWVzc2FnZSB9O1xuICAgICAgaXNUaHJlYWRNZXNzYWdlXG4gICAgICAgID8gdGhpcy5hY3RpdmVUaHJlYWRNZXNzYWdlc1N1YmplY3QubmV4dChbLi4ubWVzc2FnZXNdKVxuICAgICAgICA6IHRoaXMuYWN0aXZlQ2hhbm5lbE1lc3NhZ2VzU3ViamVjdC5uZXh0KFsuLi5tZXNzYWdlc10pO1xuICAgIH0pO1xuICB9XG5cbiAgcHJpdmF0ZSBmb3JtYXRNZXNzYWdlKG1lc3NhZ2U6IE1lc3NhZ2VSZXNwb25zZTxUPikge1xuICAgIGNvbnN0IG0gPSBtZXNzYWdlIGFzIGFueSBhcyBGb3JtYXRNZXNzYWdlUmVzcG9uc2U8VD47XG4gICAgbS5waW5uZWRfYXQgPSBtZXNzYWdlLnBpbm5lZF9hdCA/IG5ldyBEYXRlKG1lc3NhZ2UucGlubmVkX2F0KSA6IG51bGw7XG4gICAgbS5jcmVhdGVkX2F0ID0gbWVzc2FnZS5jcmVhdGVkX2F0XG4gICAgICA/IG5ldyBEYXRlKG1lc3NhZ2UuY3JlYXRlZF9hdClcbiAgICAgIDogbmV3IERhdGUoKTtcbiAgICBtLnVwZGF0ZWRfYXQgPSBtZXNzYWdlLnVwZGF0ZWRfYXRcbiAgICAgID8gbmV3IERhdGUobWVzc2FnZS51cGRhdGVkX2F0KVxuICAgICAgOiBuZXcgRGF0ZSgpO1xuICAgIG1lc3NhZ2Uuc3RhdHVzID0gbWVzc2FnZS5zdGF0dXMgfHwgJ3JlY2VpdmVkJztcblxuICAgIHJldHVybiBtO1xuICB9XG5cbiAgcHJpdmF0ZSBpc1N0cmVhbU1lc3NhZ2UoXG4gICAgbWVzc2FnZTogU3RyZWFtTWVzc2FnZSB8IEZvcm1hdE1lc3NhZ2VSZXNwb25zZSB8IE1lc3NhZ2VSZXNwb25zZVxuICApOiBtZXNzYWdlIGlzIFN0cmVhbU1lc3NhZ2Uge1xuICAgIHJldHVybiAhIW1lc3NhZ2UucmVhZEJ5O1xuICB9XG5cbiAgcHJpdmF0ZSBpc0Zvcm1hdE1lc3NhZ2VSZXNwb25zZShcbiAgICBtZXNzYWdlOiBTdHJlYW1NZXNzYWdlIHwgRm9ybWF0TWVzc2FnZVJlc3BvbnNlIHwgTWVzc2FnZVJlc3BvbnNlXG4gICk6IG1lc3NhZ2UgaXMgRm9ybWF0TWVzc2FnZVJlc3BvbnNlIHtcbiAgICByZXR1cm4gbWVzc2FnZS5jcmVhdGVkX2F0IGluc3RhbmNlb2YgRGF0ZTtcbiAgfVxuXG4gIHByaXZhdGUgc3RvcFdhdGNoRm9yQWN0aXZlQ2hhbm5lbEV2ZW50cyhjaGFubmVsOiBDaGFubmVsPFQ+IHwgdW5kZWZpbmVkKSB7XG4gICAgaWYgKCFjaGFubmVsKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIHRoaXMuYWN0aXZlQ2hhbm5lbFN1YnNjcmlwdGlvbnMuZm9yRWFjaCgocykgPT4gcy51bnN1YnNjcmliZSgpKTtcbiAgICB0aGlzLmFjdGl2ZUNoYW5uZWxTdWJzY3JpcHRpb25zID0gW107XG4gIH1cblxuICBwcml2YXRlIGFzeW5jIHF1ZXJ5Q2hhbm5lbHMoXG4gICAgc2hvdWxkU2V0QWN0aXZlQ2hhbm5lbDogYm9vbGVhbixcbiAgICByZWNvdmVyU3RhdGUgPSBmYWxzZVxuICApIHtcbiAgICB0cnkge1xuICAgICAgdGhpcy5jaGFubmVsUXVlcnlTdGF0ZVN1YmplY3QubmV4dCh7IHN0YXRlOiAnaW4tcHJvZ3Jlc3MnIH0pO1xuICAgICAgbGV0IGZpbHRlcnM6IENoYW5uZWxGaWx0ZXJzPFQ+O1xuICAgICAgbGV0IG9wdGlvbnM6IENoYW5uZWxPcHRpb25zO1xuICAgICAgaWYgKHRoaXMubmV4dFBhZ2VDb25maWd1cmF0aW9uKSB7XG4gICAgICAgIGlmICh0aGlzLm5leHRQYWdlQ29uZmlndXJhdGlvbi50eXBlID09PSAnZmlsdGVyJykge1xuICAgICAgICAgIGZpbHRlcnMgPSB7XG4gICAgICAgICAgICAuLi50aGlzLmZpbHRlcnMhLFxuICAgICAgICAgICAgLi4udGhpcy5uZXh0UGFnZUNvbmZpZ3VyYXRpb24ucGFnaW5hdGlvbkZpbHRlcixcbiAgICAgICAgICB9O1xuICAgICAgICAgIG9wdGlvbnMgPSB0aGlzLm9wdGlvbnMgYXMgQ2hhbm5lbE9wdGlvbnM7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgb3B0aW9ucyA9IHtcbiAgICAgICAgICAgIC4uLnRoaXMub3B0aW9ucyxcbiAgICAgICAgICAgIG9mZnNldDogdGhpcy5uZXh0UGFnZUNvbmZpZ3VyYXRpb24ub2Zmc2V0LFxuICAgICAgICAgIH07XG4gICAgICAgICAgZmlsdGVycyA9IHRoaXMuZmlsdGVycyE7XG4gICAgICAgIH1cbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGZpbHRlcnMgPSB0aGlzLmZpbHRlcnMhO1xuICAgICAgICBvcHRpb25zID0gdGhpcy5vcHRpb25zIGFzIENoYW5uZWxPcHRpb25zO1xuICAgICAgfVxuICAgICAgY29uc3QgY2hhbm5lbHMgPSBhd2FpdCB0aGlzLmNoYXRDbGllbnRTZXJ2aWNlLmNoYXRDbGllbnQucXVlcnlDaGFubmVscyhcbiAgICAgICAgZmlsdGVycyxcbiAgICAgICAgdGhpcy5zb3J0IHx8IHt9LFxuICAgICAgICBvcHRpb25zXG4gICAgICApO1xuICAgICAgdGhpcy5zZXROZXh0UGFnZUNvbmZpZ3VyYXRpb24oY2hhbm5lbHMpO1xuICAgICAgY2hhbm5lbHMuZm9yRWFjaCgoYykgPT4gdGhpcy53YXRjaEZvckNoYW5uZWxFdmVudHMoYykpO1xuICAgICAgY29uc3QgcHJldkNoYW5uZWxzID0gcmVjb3ZlclN0YXRlXG4gICAgICAgID8gW11cbiAgICAgICAgOiB0aGlzLmNoYW5uZWxzU3ViamVjdC5nZXRWYWx1ZSgpIHx8IFtdO1xuICAgICAgY29uc3QgZmlsdGVyZWRDaGFubmVscyA9IGNoYW5uZWxzLmZpbHRlcihcbiAgICAgICAgKGNoYW5uZWwpID0+XG4gICAgICAgICAgIXByZXZDaGFubmVscy5maW5kKFxuICAgICAgICAgICAgKGV4aXN0aW5nQ2hhbm5lbCkgPT4gZXhpc3RpbmdDaGFubmVsLmNpZCA9PT0gY2hhbm5lbC5jaWRcbiAgICAgICAgICApXG4gICAgICApO1xuICAgICAgbGV0IGN1cnJlbnRBY3RpdmVDaGFubmVsID0gdGhpcy5hY3RpdmVDaGFubmVsU3ViamVjdC5nZXRWYWx1ZSgpO1xuICAgICAgbGV0IGlzQ3VycmVudEFjdGl2ZUNoYW5uZWxEZXNlbGVjdGVkID0gZmFsc2U7XG4gICAgICBjb25zdCBuZXh0Q2hhbm5lbHMgPSBbLi4ucHJldkNoYW5uZWxzLCAuLi5maWx0ZXJlZENoYW5uZWxzXTtcbiAgICAgIGlmIChcbiAgICAgICAgcmVjb3ZlclN0YXRlICYmXG4gICAgICAgIGN1cnJlbnRBY3RpdmVDaGFubmVsICYmXG4gICAgICAgICFmaWx0ZXJlZENoYW5uZWxzLmZpbmQoKGMpID0+IGMuY2lkID09PSBjdXJyZW50QWN0aXZlQ2hhbm5lbD8uY2lkKVxuICAgICAgKSB7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgYXdhaXQgY3VycmVudEFjdGl2ZUNoYW5uZWwud2F0Y2goKTtcbiAgICAgICAgICBuZXh0Q2hhbm5lbHMudW5zaGlmdChjdXJyZW50QWN0aXZlQ2hhbm5lbCk7XG4gICAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgICBpc0N1cnJlbnRBY3RpdmVDaGFubmVsRGVzZWxlY3RlZCA9IHRydWU7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIHRoaXMuY2hhbm5lbHNTdWJqZWN0Lm5leHQobmV4dENoYW5uZWxzKTtcbiAgICAgIGlmIChpc0N1cnJlbnRBY3RpdmVDaGFubmVsRGVzZWxlY3RlZCkge1xuICAgICAgICB0aGlzLmRlc2VsZWN0QWN0aXZlQ2hhbm5lbCgpO1xuICAgICAgfVxuICAgICAgaWYgKFxuICAgICAgICBmaWx0ZXJlZENoYW5uZWxzLmxlbmd0aCA+IDAgJiZcbiAgICAgICAgIWN1cnJlbnRBY3RpdmVDaGFubmVsICYmXG4gICAgICAgIHNob3VsZFNldEFjdGl2ZUNoYW5uZWxcbiAgICAgICkge1xuICAgICAgICB0aGlzLnNldEFzQWN0aXZlQ2hhbm5lbChmaWx0ZXJlZENoYW5uZWxzWzBdKTtcbiAgICAgICAgY3VycmVudEFjdGl2ZUNoYW5uZWwgPSB0aGlzLmFjdGl2ZUNoYW5uZWxTdWJqZWN0LmdldFZhbHVlKCk7XG4gICAgICB9XG4gICAgICB0aGlzLmhhc01vcmVDaGFubmVsc1N1YmplY3QubmV4dChjaGFubmVscy5sZW5ndGggPj0gdGhpcy5vcHRpb25zIS5saW1pdCEpO1xuICAgICAgdGhpcy5jaGFubmVsUXVlcnlTdGF0ZVN1YmplY3QubmV4dCh7IHN0YXRlOiAnc3VjY2VzcycgfSk7XG4gICAgICBpZiAoXG4gICAgICAgIHRoaXMub3B0aW9ucz8ua2VlcEFsaXZlQ2hhbm5lbHMkT25FcnJvciAmJlxuICAgICAgICB0aGlzLmRpc21pc3NFcnJvck5vdGlmaWNhdGlvblxuICAgICAgKSB7XG4gICAgICAgIHRoaXMuZGlzbWlzc0Vycm9yTm90aWZpY2F0aW9uKCk7XG4gICAgICB9XG4gICAgICByZXR1cm4gY2hhbm5lbHM7XG4gICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgIGlmICghdGhpcy5vcHRpb25zPy5rZWVwQWxpdmVDaGFubmVscyRPbkVycm9yKSB7XG4gICAgICAgIHRoaXMuY2hhbm5lbHNTdWJqZWN0LmVycm9yKGVycm9yKTtcbiAgICAgIH1cbiAgICAgIHRoaXMuY2hhbm5lbFF1ZXJ5U3RhdGVTdWJqZWN0Lm5leHQoe1xuICAgICAgICBzdGF0ZTogJ2Vycm9yJyxcbiAgICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uby11bnNhZmUtYXNzaWdubWVudFxuICAgICAgICBlcnJvcixcbiAgICAgIH0pO1xuICAgICAgdGhyb3cgZXJyb3I7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSB3YXRjaEZvckNoYW5uZWxFdmVudHMoY2hhbm5lbDogQ2hhbm5lbDxUPikge1xuICAgIGNvbnN0IHVuc3Vic2NyaWJlID0gY2hhbm5lbC5vbigoZXZlbnQ6IEV2ZW50PFQ+KSA9PiB7XG4gICAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25vLXVubmVjZXNzYXJ5LXR5cGUtYXNzZXJ0aW9uXG4gICAgICBjb25zdCB0eXBlID0gZXZlbnQudHlwZSBhcyBFdmVudFR5cGVzIHwgJ2NhcGFiaWxpdGllcy5jaGFuZ2VkJztcbiAgICAgIHN3aXRjaCAodHlwZSkge1xuICAgICAgICBjYXNlICdtZXNzYWdlLm5ldyc6IHtcbiAgICAgICAgICB0aGlzLm5nWm9uZS5ydW4oKCkgPT4ge1xuICAgICAgICAgICAgaWYgKHRoaXMuY3VzdG9tTmV3TWVzc2FnZUhhbmRsZXIpIHtcbiAgICAgICAgICAgICAgdGhpcy5jdXN0b21OZXdNZXNzYWdlSGFuZGxlcihcbiAgICAgICAgICAgICAgICBldmVudCxcbiAgICAgICAgICAgICAgICBjaGFubmVsLFxuICAgICAgICAgICAgICAgIHRoaXMuY2hhbm5lbExpc3RTZXR0ZXIsXG4gICAgICAgICAgICAgICAgdGhpcy5tZXNzYWdlTGlzdFNldHRlcixcbiAgICAgICAgICAgICAgICB0aGlzLnRocmVhZExpc3RTZXR0ZXIsXG4gICAgICAgICAgICAgICAgdGhpcy5wYXJlbnRNZXNzYWdlU2V0dGVyXG4gICAgICAgICAgICAgICk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICB0aGlzLmhhbmRsZU5ld01lc3NhZ2UoZXZlbnQsIGNoYW5uZWwpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH0pO1xuICAgICAgICAgIGJyZWFrO1xuICAgICAgICB9XG4gICAgICAgIGNhc2UgJ2NoYW5uZWwuaGlkZGVuJzoge1xuICAgICAgICAgIHRoaXMubmdab25lLnJ1bigoKSA9PiB7XG4gICAgICAgICAgICBpZiAodGhpcy5jdXN0b21DaGFubmVsSGlkZGVuSGFuZGxlcikge1xuICAgICAgICAgICAgICB0aGlzLmN1c3RvbUNoYW5uZWxIaWRkZW5IYW5kbGVyKFxuICAgICAgICAgICAgICAgIGV2ZW50LFxuICAgICAgICAgICAgICAgIGNoYW5uZWwsXG4gICAgICAgICAgICAgICAgdGhpcy5jaGFubmVsTGlzdFNldHRlcixcbiAgICAgICAgICAgICAgICB0aGlzLm1lc3NhZ2VMaXN0U2V0dGVyLFxuICAgICAgICAgICAgICAgIHRoaXMudGhyZWFkTGlzdFNldHRlcixcbiAgICAgICAgICAgICAgICB0aGlzLnBhcmVudE1lc3NhZ2VTZXR0ZXJcbiAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgIHRoaXMuaGFuZGxlQ2hhbm5lbEhpZGRlbihldmVudCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfSk7XG4gICAgICAgICAgYnJlYWs7XG4gICAgICAgIH1cbiAgICAgICAgY2FzZSAnY2hhbm5lbC5kZWxldGVkJzoge1xuICAgICAgICAgIHRoaXMubmdab25lLnJ1bigoKSA9PiB7XG4gICAgICAgICAgICBpZiAodGhpcy5jdXN0b21DaGFubmVsRGVsZXRlZEhhbmRsZXIpIHtcbiAgICAgICAgICAgICAgdGhpcy5jdXN0b21DaGFubmVsRGVsZXRlZEhhbmRsZXIoXG4gICAgICAgICAgICAgICAgZXZlbnQsXG4gICAgICAgICAgICAgICAgY2hhbm5lbCxcbiAgICAgICAgICAgICAgICB0aGlzLmNoYW5uZWxMaXN0U2V0dGVyLFxuICAgICAgICAgICAgICAgIHRoaXMubWVzc2FnZUxpc3RTZXR0ZXIsXG4gICAgICAgICAgICAgICAgdGhpcy50aHJlYWRMaXN0U2V0dGVyLFxuICAgICAgICAgICAgICAgIHRoaXMucGFyZW50TWVzc2FnZVNldHRlclxuICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgdGhpcy5oYW5kbGVDaGFubmVsRGVsZXRlZChldmVudCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfSk7XG4gICAgICAgICAgYnJlYWs7XG4gICAgICAgIH1cbiAgICAgICAgY2FzZSAnY2hhbm5lbC52aXNpYmxlJzoge1xuICAgICAgICAgIHRoaXMubmdab25lLnJ1bigoKSA9PiB7XG4gICAgICAgICAgICBpZiAodGhpcy5jdXN0b21DaGFubmVsVmlzaWJsZUhhbmRsZXIpIHtcbiAgICAgICAgICAgICAgdGhpcy5jdXN0b21DaGFubmVsVmlzaWJsZUhhbmRsZXIoXG4gICAgICAgICAgICAgICAgZXZlbnQsXG4gICAgICAgICAgICAgICAgY2hhbm5lbCxcbiAgICAgICAgICAgICAgICB0aGlzLmNoYW5uZWxMaXN0U2V0dGVyLFxuICAgICAgICAgICAgICAgIHRoaXMubWVzc2FnZUxpc3RTZXR0ZXIsXG4gICAgICAgICAgICAgICAgdGhpcy50aHJlYWRMaXN0U2V0dGVyLFxuICAgICAgICAgICAgICAgIHRoaXMucGFyZW50TWVzc2FnZVNldHRlclxuICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgdGhpcy5oYW5kbGVDaGFubmVsVmlzaWJsZShldmVudCwgY2hhbm5lbCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfSk7XG4gICAgICAgICAgYnJlYWs7XG4gICAgICAgIH1cbiAgICAgICAgY2FzZSAnY2hhbm5lbC51cGRhdGVkJzoge1xuICAgICAgICAgIHRoaXMubmdab25lLnJ1bigoKSA9PiB7XG4gICAgICAgICAgICBpZiAodGhpcy5jdXN0b21DaGFubmVsVXBkYXRlZEhhbmRsZXIpIHtcbiAgICAgICAgICAgICAgdGhpcy5jdXN0b21DaGFubmVsVXBkYXRlZEhhbmRsZXIoXG4gICAgICAgICAgICAgICAgZXZlbnQsXG4gICAgICAgICAgICAgICAgY2hhbm5lbCxcbiAgICAgICAgICAgICAgICB0aGlzLmNoYW5uZWxMaXN0U2V0dGVyLFxuICAgICAgICAgICAgICAgIHRoaXMubWVzc2FnZUxpc3RTZXR0ZXIsXG4gICAgICAgICAgICAgICAgdGhpcy50aHJlYWRMaXN0U2V0dGVyLFxuICAgICAgICAgICAgICAgIHRoaXMucGFyZW50TWVzc2FnZVNldHRlclxuICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgdGhpcy5oYW5kbGVDaGFubmVsVXBkYXRlKGV2ZW50KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9KTtcbiAgICAgICAgICBicmVhaztcbiAgICAgICAgfVxuICAgICAgICBjYXNlICdjaGFubmVsLnRydW5jYXRlZCc6IHtcbiAgICAgICAgICB0aGlzLm5nWm9uZS5ydW4oKCkgPT4ge1xuICAgICAgICAgICAgaWYgKHRoaXMuY3VzdG9tQ2hhbm5lbFRydW5jYXRlZEhhbmRsZXIpIHtcbiAgICAgICAgICAgICAgdGhpcy5jdXN0b21DaGFubmVsVHJ1bmNhdGVkSGFuZGxlcihcbiAgICAgICAgICAgICAgICBldmVudCxcbiAgICAgICAgICAgICAgICBjaGFubmVsLFxuICAgICAgICAgICAgICAgIHRoaXMuY2hhbm5lbExpc3RTZXR0ZXIsXG4gICAgICAgICAgICAgICAgdGhpcy5tZXNzYWdlTGlzdFNldHRlcixcbiAgICAgICAgICAgICAgICB0aGlzLnRocmVhZExpc3RTZXR0ZXIsXG4gICAgICAgICAgICAgICAgdGhpcy5wYXJlbnRNZXNzYWdlU2V0dGVyXG4gICAgICAgICAgICAgICk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICB0aGlzLmhhbmRsZUNoYW5uZWxUcnVuY2F0ZShldmVudCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfSk7XG4gICAgICAgICAgYnJlYWs7XG4gICAgICAgIH1cbiAgICAgICAgY2FzZSAnY2FwYWJpbGl0aWVzLmNoYW5nZWQnOiB7XG4gICAgICAgICAgdGhpcy5uZ1pvbmUucnVuKCgpID0+IHtcbiAgICAgICAgICAgIGNvbnN0IGNpZCA9IGV2ZW50LmNpZDtcbiAgICAgICAgICAgIGlmIChjaWQpIHtcbiAgICAgICAgICAgICAgY29uc3QgY3VycmVudENoYW5uZWxzID0gdGhpcy5jaGFubmVsc1N1YmplY3QuZ2V0VmFsdWUoKTtcbiAgICAgICAgICAgICAgY29uc3QgaW5kZXggPSBjdXJyZW50Q2hhbm5lbHM/LmZpbmRJbmRleCgoYykgPT4gYy5jaWQgPT09IGNpZCk7XG4gICAgICAgICAgICAgIGlmIChpbmRleCAhPT0gLTEgJiYgaW5kZXggIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICAgIHRoaXMuY2hhbm5lbHNTdWJqZWN0Lm5leHQoWy4uLmN1cnJlbnRDaGFubmVscyFdKTtcbiAgICAgICAgICAgICAgICBpZiAoY2lkID09PSB0aGlzLmFjdGl2ZUNoYW5uZWxTdWJqZWN0LmdldFZhbHVlKCk/LmNpZCkge1xuICAgICAgICAgICAgICAgICAgdGhpcy5hY3RpdmVDaGFubmVsU3ViamVjdC5uZXh0KFxuICAgICAgICAgICAgICAgICAgICB0aGlzLmFjdGl2ZUNoYW5uZWxTdWJqZWN0LmdldFZhbHVlKClcbiAgICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfSk7XG4gICAgICAgICAgYnJlYWs7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9KTtcbiAgICB0aGlzLmNoYW5uZWxTdWJzY3JpcHRpb25zW2NoYW5uZWwuY2lkXSA9IHVuc3Vic2NyaWJlLnVuc3Vic2NyaWJlO1xuICB9XG5cbiAgcHJpdmF0ZSBoYW5kbGVOZXdNZXNzYWdlKF86IEV2ZW50LCBjaGFubmVsOiBDaGFubmVsPFQ+KSB7XG4gICAgY29uc3QgY2hhbm5lbEluZGV4ID0gdGhpcy5jaGFubmVscy5maW5kSW5kZXgoKGMpID0+IGMuY2lkID09PSBjaGFubmVsLmNpZCk7XG4gICAgdGhpcy5jaGFubmVscy5zcGxpY2UoY2hhbm5lbEluZGV4LCAxKTtcbiAgICB0aGlzLmNoYW5uZWxzU3ViamVjdC5uZXh0KFtjaGFubmVsLCAuLi50aGlzLmNoYW5uZWxzXSk7XG4gIH1cblxuICBwcml2YXRlIGhhbmRsZUNoYW5uZWxIaWRkZW4oZXZlbnQ6IEV2ZW50KSB7XG4gICAgdGhpcy5yZW1vdmVDaGFubmVsc0Zyb21DaGFubmVsTGlzdChbZXZlbnQuY2hhbm5lbCEuY2lkXSwgZmFsc2UpO1xuICB9XG5cbiAgcHJpdmF0ZSBoYW5kbGVDaGFubmVsRGVsZXRlZChldmVudDogRXZlbnQpIHtcbiAgICB0aGlzLnJlbW92ZUNoYW5uZWxzRnJvbUNoYW5uZWxMaXN0KFtldmVudC5jaGFubmVsIS5jaWRdLCBmYWxzZSk7XG4gIH1cblxuICBwcml2YXRlIGhhbmRsZUNoYW5uZWxWaXNpYmxlKGV2ZW50OiBFdmVudCwgY2hhbm5lbDogQ2hhbm5lbDxUPikge1xuICAgIGlmICghdGhpcy5jaGFubmVscy5maW5kKChjKSA9PiBjLmNpZCA9PT0gZXZlbnQuY2lkKSkge1xuICAgICAgdGhpcy5uZ1pvbmUucnVuKCgpID0+XG4gICAgICAgIHRoaXMuY2hhbm5lbHNTdWJqZWN0Lm5leHQoWy4uLnRoaXMuY2hhbm5lbHMsIGNoYW5uZWxdKVxuICAgICAgKTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIGhhbmRsZUNoYW5uZWxVcGRhdGUoZXZlbnQ6IEV2ZW50PFQ+KSB7XG4gICAgY29uc3QgY2hhbm5lbEluZGV4ID0gdGhpcy5jaGFubmVscy5maW5kSW5kZXgoXG4gICAgICAoYykgPT4gYy5jaWQgPT09IGV2ZW50LmNoYW5uZWwhLmNpZFxuICAgICk7XG4gICAgaWYgKGNoYW5uZWxJbmRleCAhPT0gLTEpIHtcbiAgICAgIGNvbnN0IGNoYW5uZWwgPSB0aGlzLmNoYW5uZWxzW2NoYW5uZWxJbmRleF07XG4gICAgICBjb25zdCBub3RJbmNsdWRlZFByb3BlcmllcyA9IHtcbiAgICAgICAgaGlkZGVuOiBjaGFubmVsLmRhdGE/LmhpZGRlbiB8fCBmYWxzZSxcbiAgICAgICAgb3duX2NhcGFiaWxpdGllczogY2hhbm5lbC5kYXRhPy5vd25fY2FwYWJpbGl0aWVzIHx8IFtdLFxuICAgICAgfTtcbiAgICAgIGNoYW5uZWwuZGF0YSA9IHtcbiAgICAgICAgLi4uZXZlbnQuY2hhbm5lbCEsXG4gICAgICAgIC4uLm5vdEluY2x1ZGVkUHJvcGVyaWVzLFxuICAgICAgfTtcbiAgICAgIHRoaXMuY2hhbm5lbHNTdWJqZWN0Lm5leHQoWy4uLnRoaXMuY2hhbm5lbHNdKTtcbiAgICAgIGlmIChldmVudC5jaGFubmVsPy5jaWQgPT09IHRoaXMuYWN0aXZlQ2hhbm5lbFN1YmplY3QuZ2V0VmFsdWUoKT8uY2lkKSB7XG4gICAgICAgIHRoaXMuYWN0aXZlQ2hhbm5lbFN1YmplY3QubmV4dChjaGFubmVsKTtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICBwcml2YXRlIGhhbmRsZUNoYW5uZWxUcnVuY2F0ZShldmVudDogRXZlbnQpIHtcbiAgICBjb25zdCBjaGFubmVsSW5kZXggPSB0aGlzLmNoYW5uZWxzLmZpbmRJbmRleChcbiAgICAgIChjKSA9PiBjLmNpZCA9PT0gZXZlbnQuY2hhbm5lbCEuY2lkXG4gICAgKTtcbiAgICBpZiAoY2hhbm5lbEluZGV4ICE9PSAtMSkge1xuICAgICAgdGhpcy5jaGFubmVsc1tjaGFubmVsSW5kZXhdLnN0YXRlLm1lc3NhZ2VzID0gW107XG4gICAgICB0aGlzLmNoYW5uZWxzU3ViamVjdC5uZXh0KFsuLi50aGlzLmNoYW5uZWxzXSk7XG4gICAgICBpZiAoZXZlbnQuY2hhbm5lbD8uY2lkID09PSB0aGlzLmFjdGl2ZUNoYW5uZWxTdWJqZWN0LmdldFZhbHVlKCk/LmNpZCkge1xuICAgICAgICBjb25zdCBjaGFubmVsID0gdGhpcy5hY3RpdmVDaGFubmVsU3ViamVjdC5nZXRWYWx1ZSgpITtcbiAgICAgICAgY2hhbm5lbC5zdGF0ZS5tZXNzYWdlcyA9IFtdO1xuICAgICAgICB0aGlzLmFjdGl2ZUNoYW5uZWxTdWJqZWN0Lm5leHQoY2hhbm5lbCk7XG4gICAgICAgIHRoaXMuYWN0aXZlQ2hhbm5lbE1lc3NhZ2VzU3ViamVjdC5uZXh0KFtdKTtcbiAgICAgICAgdGhpcy5hY3RpdmVQYXJlbnRNZXNzYWdlSWRTdWJqZWN0Lm5leHQodW5kZWZpbmVkKTtcbiAgICAgICAgdGhpcy5hY3RpdmVUaHJlYWRNZXNzYWdlc1N1YmplY3QubmV4dChbXSk7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBnZXQgY2FuU2VuZFJlYWRFdmVudHMoKSB7XG4gICAgY29uc3QgY2hhbm5lbCA9IHRoaXMuYWN0aXZlQ2hhbm5lbFN1YmplY3QuZ2V0VmFsdWUoKTtcbiAgICBpZiAoIWNoYW5uZWwpIHtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG4gICAgY29uc3QgY2FwYWJpbGl0ZXMgPSBjaGFubmVsLmRhdGE/Lm93bl9jYXBhYmlsaXRpZXMgYXMgc3RyaW5nW107XG4gICAgcmV0dXJuIGNhcGFiaWxpdGVzLmluZGV4T2YoJ3JlYWQtZXZlbnRzJykgIT09IC0xO1xuICB9XG5cbiAgcHJpdmF0ZSB0cmFuc2Zvcm1Ub1N0cmVhbU1lc3NhZ2UoXG4gICAgbWVzc2FnZTogU3RyZWFtTWVzc2FnZTxUPiB8IE1lc3NhZ2VSZXNwb25zZTxUPiB8IEZvcm1hdE1lc3NhZ2VSZXNwb25zZTxUPixcbiAgICBjaGFubmVsPzogQ2hhbm5lbDxUPlxuICApIHtcbiAgICBjb25zdCBpc1RocmVhZE1lc3NhZ2UgPSAhIW1lc3NhZ2UucGFyZW50X2lkO1xuICAgIGlmIChcbiAgICAgIHRoaXMuaXNTdHJlYW1NZXNzYWdlKG1lc3NhZ2UpICYmXG4gICAgICB0aGlzLmlzRm9ybWF0TWVzc2FnZVJlc3BvbnNlKG1lc3NhZ2UpXG4gICAgKSB7XG4gICAgICBpZiAobWVzc2FnZS5xdW90ZWRfbWVzc2FnZSkge1xuICAgICAgICBtZXNzYWdlLnF1b3RlZF9tZXNzYWdlLnRyYW5zbGF0aW9uID0gZ2V0TWVzc2FnZVRyYW5zbGF0aW9uKFxuICAgICAgICAgIG1lc3NhZ2UucXVvdGVkX21lc3NhZ2UsXG4gICAgICAgICAgY2hhbm5lbCxcbiAgICAgICAgICB0aGlzLmNoYXRDbGllbnRTZXJ2aWNlLmNoYXRDbGllbnQudXNlclxuICAgICAgICApO1xuICAgICAgfVxuICAgICAgbWVzc2FnZS50cmFuc2xhdGlvbiA9IGdldE1lc3NhZ2VUcmFuc2xhdGlvbihcbiAgICAgICAgbWVzc2FnZSxcbiAgICAgICAgY2hhbm5lbCxcbiAgICAgICAgdGhpcy5jaGF0Q2xpZW50U2VydmljZS5jaGF0Q2xpZW50LnVzZXJcbiAgICAgICk7XG4gICAgICByZXR1cm4gbWVzc2FnZTtcbiAgICB9IGVsc2Uge1xuICAgICAgaWYgKG1lc3NhZ2UucXVvdGVkX21lc3NhZ2UpIHtcbiAgICAgICAgbWVzc2FnZS5xdW90ZWRfbWVzc2FnZS50cmFuc2xhdGlvbiA9IGdldE1lc3NhZ2VUcmFuc2xhdGlvbihcbiAgICAgICAgICBtZXNzYWdlLnF1b3RlZF9tZXNzYWdlLFxuICAgICAgICAgIGNoYW5uZWwsXG4gICAgICAgICAgdGhpcy5jaGF0Q2xpZW50U2VydmljZS5jaGF0Q2xpZW50LnVzZXJcbiAgICAgICAgKTtcbiAgICAgIH1cbiAgICAgIGlmICh0aGlzLmlzRm9ybWF0TWVzc2FnZVJlc3BvbnNlKG1lc3NhZ2UpKSB7XG4gICAgICAgIG1lc3NhZ2UucmVhZEJ5ID0gaXNUaHJlYWRNZXNzYWdlXG4gICAgICAgICAgPyBbXVxuICAgICAgICAgIDogY2hhbm5lbFxuICAgICAgICAgID8gZ2V0UmVhZEJ5KG1lc3NhZ2UsIGNoYW5uZWwpXG4gICAgICAgICAgOiBbXTtcbiAgICAgICAgbWVzc2FnZS50cmFuc2xhdGlvbiA9IGdldE1lc3NhZ2VUcmFuc2xhdGlvbihcbiAgICAgICAgICBtZXNzYWdlLFxuICAgICAgICAgIGNoYW5uZWwsXG4gICAgICAgICAgdGhpcy5jaGF0Q2xpZW50U2VydmljZS5jaGF0Q2xpZW50LnVzZXJcbiAgICAgICAgKTtcblxuICAgICAgICByZXR1cm4gbWVzc2FnZTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIG1lc3NhZ2UgPSB0aGlzLmZvcm1hdE1lc3NhZ2UobWVzc2FnZSk7XG4gICAgICAgIG1lc3NhZ2UucmVhZEJ5ID0gaXNUaHJlYWRNZXNzYWdlXG4gICAgICAgICAgPyBbXVxuICAgICAgICAgIDogY2hhbm5lbFxuICAgICAgICAgID8gZ2V0UmVhZEJ5KG1lc3NhZ2UsIGNoYW5uZWwpXG4gICAgICAgICAgOiBbXTtcbiAgICAgICAgbWVzc2FnZS50cmFuc2xhdGlvbiA9IGdldE1lc3NhZ2VUcmFuc2xhdGlvbihcbiAgICAgICAgICBtZXNzYWdlLFxuICAgICAgICAgIGNoYW5uZWwsXG4gICAgICAgICAgdGhpcy5jaGF0Q2xpZW50U2VydmljZS5jaGF0Q2xpZW50LnVzZXJcbiAgICAgICAgKTtcbiAgICAgICAgcmV0dXJuIG1lc3NhZ2U7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBoYW5kbGVUeXBpbmdTdGFydEV2ZW50KGV2ZW50OiBFdmVudCkge1xuICAgIGlmIChldmVudC51c2VyPy5pZCA9PT0gdGhpcy5jaGF0Q2xpZW50U2VydmljZS5jaGF0Q2xpZW50LnVzZXI/LmlkKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIGNvbnN0IGlzVHlwaW5nSW5UaHJlYWQgPSAhIWV2ZW50LnBhcmVudF9pZDtcbiAgICBpZiAoXG4gICAgICBpc1R5cGluZ0luVGhyZWFkICYmXG4gICAgICBldmVudC5wYXJlbnRfaWQgIT09IHRoaXMuYWN0aXZlUGFyZW50TWVzc2FnZUlkU3ViamVjdC5nZXRWYWx1ZSgpXG4gICAgKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIGNvbnN0IHN1YmplY3QgPSBpc1R5cGluZ0luVGhyZWFkXG4gICAgICA/IHRoaXMudXNlcnNUeXBpbmdJblRocmVhZFN1YmplY3RcbiAgICAgIDogdGhpcy51c2Vyc1R5cGluZ0luQ2hhbm5lbFN1YmplY3Q7XG4gICAgY29uc3QgdXNlcnM6IFVzZXJSZXNwb25zZVtdID0gc3ViamVjdC5nZXRWYWx1ZSgpO1xuICAgIGNvbnN0IHVzZXIgPSBldmVudC51c2VyO1xuICAgIGlmICh1c2VyICYmICF1c2Vycy5maW5kKCh1KSA9PiB1LmlkID09PSB1c2VyLmlkKSkge1xuICAgICAgdXNlcnMucHVzaCh1c2VyKTtcbiAgICAgIHN1YmplY3QubmV4dChbLi4udXNlcnNdKTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIGhhbmRsZVR5cGluZ1N0b3BFdmVudChldmVudDogRXZlbnQpIHtcbiAgICBjb25zdCB1c2Vyc1R5cGluZ0luQ2hhbm5lbCA9IHRoaXMudXNlcnNUeXBpbmdJbkNoYW5uZWxTdWJqZWN0LmdldFZhbHVlKCk7XG4gICAgY29uc3QgdXNlcnNUeXBpbmdJblRocmVhZCA9IHRoaXMudXNlcnNUeXBpbmdJblRocmVhZFN1YmplY3QuZ2V0VmFsdWUoKTtcbiAgICBjb25zdCB1c2VyID0gZXZlbnQudXNlcjtcbiAgICBpZiAodXNlciAmJiB1c2Vyc1R5cGluZ0luQ2hhbm5lbC5maW5kKCh1KSA9PiB1LmlkID09PSB1c2VyLmlkKSkge1xuICAgICAgdXNlcnNUeXBpbmdJbkNoYW5uZWwuc3BsaWNlKFxuICAgICAgICB1c2Vyc1R5cGluZ0luQ2hhbm5lbC5maW5kSW5kZXgoKHUpID0+IHUuaWQgPT09IHVzZXIuaWQpLFxuICAgICAgICAxXG4gICAgICApO1xuICAgICAgdGhpcy51c2Vyc1R5cGluZ0luQ2hhbm5lbFN1YmplY3QubmV4dChbLi4udXNlcnNUeXBpbmdJbkNoYW5uZWxdKTtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgaWYgKHVzZXIgJiYgdXNlcnNUeXBpbmdJblRocmVhZC5maW5kKCh1KSA9PiB1LmlkID09PSB1c2VyLmlkKSkge1xuICAgICAgdXNlcnNUeXBpbmdJblRocmVhZC5zcGxpY2UoXG4gICAgICAgIHVzZXJzVHlwaW5nSW5UaHJlYWQuZmluZEluZGV4KCh1KSA9PiB1LmlkID09PSB1c2VyLmlkKSxcbiAgICAgICAgMVxuICAgICAgKTtcbiAgICAgIHRoaXMudXNlcnNUeXBpbmdJblRocmVhZFN1YmplY3QubmV4dChbLi4udXNlcnNUeXBpbmdJblRocmVhZF0pO1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgdXBkYXRlTGF0ZXN0TWVzc2FnZXMoZXZlbnQ6IEV2ZW50KSB7XG4gICAgaWYgKFxuICAgICAgZXZlbnQubWVzc2FnZT8udXNlcj8uaWQgIT09IHRoaXMuY2hhdENsaWVudFNlcnZpY2U/LmNoYXRDbGllbnQudXNlcj8uaWRcbiAgICApIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgY29uc3QgbGF0ZXN0TWVzc2FnZXMgPVxuICAgICAgdGhpcy5sYXRlc3RNZXNzYWdlRGF0ZUJ5VXNlckJ5Q2hhbm5lbHNTdWJqZWN0LmdldFZhbHVlKCk7XG4gICAgaWYgKCFldmVudC5tZXNzYWdlPy5jcmVhdGVkX2F0KSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIGNvbnN0IGNoYW5uZWxJZCA9IGV2ZW50Py5tZXNzYWdlPy5jaWQ7XG4gICAgaWYgKCFjaGFubmVsSWQpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgY29uc3QgbWVzc2FnZURhdGUgPSBuZXcgRGF0ZShldmVudC5tZXNzYWdlLmNyZWF0ZWRfYXQpO1xuICAgIGlmIChcbiAgICAgICFsYXRlc3RNZXNzYWdlc1tjaGFubmVsSWRdIHx8XG4gICAgICBsYXRlc3RNZXNzYWdlc1tjaGFubmVsSWRdPy5nZXRUaW1lKCkgPCBtZXNzYWdlRGF0ZS5nZXRUaW1lKClcbiAgICApIHtcbiAgICAgIGxhdGVzdE1lc3NhZ2VzW2NoYW5uZWxJZF0gPSBtZXNzYWdlRGF0ZTtcbiAgICAgIHRoaXMubGF0ZXN0TWVzc2FnZURhdGVCeVVzZXJCeUNoYW5uZWxzU3ViamVjdC5uZXh0KHtcbiAgICAgICAgLi4ubGF0ZXN0TWVzc2FnZXMsXG4gICAgICB9KTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIHNldENoYW5uZWxTdGF0ZShjaGFubmVsOiBDaGFubmVsPFQ+KSB7XG4gICAgY2hhbm5lbC5zdGF0ZS5tZXNzYWdlcy5mb3JFYWNoKChtKSA9PiB7XG4gICAgICBtLnJlYWRCeSA9IGdldFJlYWRCeShtLCBjaGFubmVsKTtcbiAgICAgIG0udHJhbnNsYXRpb24gPSBnZXRNZXNzYWdlVHJhbnNsYXRpb24oXG4gICAgICAgIG0sXG4gICAgICAgIGNoYW5uZWwsXG4gICAgICAgIHRoaXMuY2hhdENsaWVudFNlcnZpY2UuY2hhdENsaWVudC51c2VyXG4gICAgICApO1xuICAgICAgaWYgKG0ucXVvdGVkX21lc3NhZ2UpIHtcbiAgICAgICAgbS5xdW90ZWRfbWVzc2FnZS50cmFuc2xhdGlvbiA9IGdldE1lc3NhZ2VUcmFuc2xhdGlvbihcbiAgICAgICAgICBtLnF1b3RlZF9tZXNzYWdlLFxuICAgICAgICAgIGNoYW5uZWwsXG4gICAgICAgICAgdGhpcy5jaGF0Q2xpZW50U2VydmljZS5jaGF0Q2xpZW50LnVzZXJcbiAgICAgICAgKTtcbiAgICAgIH1cbiAgICB9KTtcbiAgICB0aGlzLm1hcmtSZWFkKGNoYW5uZWwpO1xuICAgIHRoaXMuYWN0aXZlQ2hhbm5lbE1lc3NhZ2VzU3ViamVjdC5uZXh0KFsuLi5jaGFubmVsLnN0YXRlLm1lc3NhZ2VzXSk7XG4gICAgdGhpcy5hY3RpdmVDaGFubmVsUGlubmVkTWVzc2FnZXNTdWJqZWN0Lm5leHQoW1xuICAgICAgLi4uY2hhbm5lbC5zdGF0ZS5waW5uZWRNZXNzYWdlcyxcbiAgICBdKTtcbiAgICB0aGlzLmFjdGl2ZVBhcmVudE1lc3NhZ2VJZFN1YmplY3QubmV4dCh1bmRlZmluZWQpO1xuICAgIHRoaXMuYWN0aXZlVGhyZWFkTWVzc2FnZXNTdWJqZWN0Lm5leHQoW10pO1xuICAgIHRoaXMubWVzc2FnZVRvUXVvdGVTdWJqZWN0Lm5leHQodW5kZWZpbmVkKTtcbiAgICB0aGlzLnVzZXJzVHlwaW5nSW5DaGFubmVsU3ViamVjdC5uZXh0KFtdKTtcbiAgICB0aGlzLnVzZXJzVHlwaW5nSW5UaHJlYWRTdWJqZWN0Lm5leHQoW10pO1xuICB9XG5cbiAgcHJpdmF0ZSBtYXJrUmVhZChjaGFubmVsOiBDaGFubmVsPFQ+KSB7XG4gICAgaWYgKFxuICAgICAgdGhpcy5jYW5TZW5kUmVhZEV2ZW50cyAmJlxuICAgICAgdGhpcy5zaG91bGRNYXJrQWN0aXZlQ2hhbm5lbEFzUmVhZCAmJlxuICAgICAgIXRoaXMuYXJlUmVhZEV2ZW50c1BhdXNlZFxuICAgICkge1xuICAgICAgdm9pZCBjaGFubmVsLm1hcmtSZWFkKCk7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBzZXROZXh0UGFnZUNvbmZpZ3VyYXRpb24oY2hhbm5lbFF1ZXJ5UmVzdWx0OiBDaGFubmVsPFQ+W10pIHtcbiAgICBpZiAodGhpcy5jdXN0b21QYWdpbmF0b3IpIHtcbiAgICAgIHRoaXMubmV4dFBhZ2VDb25maWd1cmF0aW9uID0gdGhpcy5jdXN0b21QYWdpbmF0b3IoY2hhbm5lbFF1ZXJ5UmVzdWx0KTtcbiAgICB9IGVsc2Uge1xuICAgICAgdGhpcy5uZXh0UGFnZUNvbmZpZ3VyYXRpb24gPSB7XG4gICAgICAgIHR5cGU6ICdvZmZzZXQnLFxuICAgICAgICBvZmZzZXQ6XG4gICAgICAgICAgKHRoaXMubmV4dFBhZ2VDb25maWd1cmF0aW9uPy50eXBlID09PSAnb2Zmc2V0J1xuICAgICAgICAgICAgPyB0aGlzLm5leHRQYWdlQ29uZmlndXJhdGlvbi5vZmZzZXRcbiAgICAgICAgICAgIDogMCkgKyBjaGFubmVsUXVlcnlSZXN1bHQubGVuZ3RoLFxuICAgICAgfTtcbiAgICB9XG4gIH1cbn1cbiJdfQ==
|