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