UNPKG

@lifeintelligencegroup/ngx-lig-ari

Version:

Life Intelligence Group Artificial Intelligence

393 lines 51.2 kB
import { Injectable, Inject } from '@angular/core'; import { HttpHeaders } from '@angular/common/http'; import { Subject, BehaviorSubject, timer, } from 'rxjs'; import { map, takeUntil, catchError, startWith, switchMap, } from 'rxjs/operators'; import { AriConfigService } from '../model/ari-bot.mode'; import 'moment-timezone'; import * as i0 from "@angular/core"; import * as i1 from "@angular/common/http"; import * as i2 from "./pubsub.service"; import * as i3 from "./common.service"; const baseUrl = 'https://directline.botframework.com/v3/directline/conversations'; // const baseUrl = // 'http://localhost:62114/api/messages'; export class AriBotService { constructor(httpClient, pubsub, commonService, config) { this.httpClient = httpClient; this.pubsub = pubsub; this.commonService = commonService; this.config = config; this.unsubscribe$ = new Subject(); this.ariCreds$ = new Subject(); // tslint:disable-next-line: variable-name this._botResponse$ = new BehaviorSubject(null); this.hasInitializedConversation = false; this.hasConversations = false; this.reset$ = new Subject(); this.initMessage = {}; this.assistantName = 'Ari'; this.locationAccess$ = new Subject(); if (config.settings) { this.assistantName = config.settings.assistantName; this.auth = config.settings.auth; this.project = config.settings.project; this.baseUrlproject = config.settings.baseUrl; } this.ariCreds$.pipe(takeUntil(this.unsubscribe$)).subscribe((creds) => { if (creds) { this.subscribeToConversations(); } }); } get locationStatusChanged() { return this.locationAccess$.asObservable(); } botResponse$() { return this._botResponse$.asObservable(); } ariTimeout() { this.timer$ = this.reset$.pipe(startWith(0), switchMap(() => timer(0, 1000)) // 1000 = 1sec ); this.subscription = this.timer$.subscribe((i) => { /// 5 Minutes reset the timer and close ari and show "I have not heard from you for a while so I presume that you are busy. Call me again when you are ready. Goodbye." if (i == 600) { // 300 secs = 5 minutes this.subscription.unsubscribe(); this.pubsub.$pub('ARI-TIMEOUT', true); } }); } refreshTimer() { this.reset$.next(0); } stopTimer() { this.subscription.unsubscribe(); } subscribeToConversations() { let emptyConversationId; let hasEmptyConversation = false; this.hasConversations = true; return this.getConversations() .pipe(map((conversations) => { const { activities } = conversations; conversations.activities = activities.filter((activity) => { if (activity.from.Token && activity.from.RefreshToken) { this.commonService.updateUserObject(activity.from.Token, activity.from.RefreshToken); } if ((activity.text || activity.replyToId !== emptyConversationId) && hasEmptyConversation === false) { return activity; } if (!activity.text) { emptyConversationId = activity.id; hasEmptyConversation = true; activity.hasEmptyConversation = true; } else { hasEmptyConversation = false; activity.hasEmptyConversation = false; } }); return conversations; }), catchError((error) => { this.pubsub.$pub('ARI-ERROR', error); this.pubsub.$pub('ARI-LOADING-DONE'); return error.error; }), takeUntil(this.unsubscribe$)) .subscribe((response) => { if (response) { const getAllActivities = this.initMessage.activities ? this.initMessage.activities.concat(response.activities) : response.activities; const validActivities = getAllActivities.filter((item) => { if (item.id) { return item; } }); const dataResponse = { activities: validActivities, watermark: response.watermark, }; this._botResponse$.next(dataResponse); } }); } getConversations() { const { conversationId } = this.ariCreds; const url = `${baseUrl}/${conversationId}/activities`; const headers = this.conversationHeader; return this.httpClient.get(url, { headers, }); } paginateTasks(params) { const url = `${this.baseUrlproject}/api/ari/tasks`; const header = this.commonStateChangeHeaders(); return this.httpClient.get(url, { headers: header, params: params, }); } getInitialWelcomeMessage() { const auth = JSON.parse(localStorage.getItem(this.auth)); let params = {}; if (auth) { const timeZone = Intl.DateTimeFormat().resolvedOptions().timeZone; params = { RefreshToken: auth.RefreshToken, TimeZone: auth.timeZone ? auth.timeZone : timeZone, Project: this.project, Location: auth.location ? auth.location : timeZone.substring(timeZone.indexOf('/') + 1, timeZone.length), }; // if (auth.lat || auth.long) { // params.Lat = auth.lat; // params.Long = auth.long; // } } else { params = { ...JSON.parse(localStorage.getItem('temp_user')), }; } const url = `${this.baseUrlproject}/api/ari/welcome`; const header = this.commonStateChangeHeaders(); return this.httpClient.get(url, { headers: header, params: params, }); } commonStateChangeHeaders() { let headers; if (JSON.parse(localStorage.getItem(this.auth))) { headers = { 'Content-Type': 'application/json', Accept: 'application/json', Authorization: `Bearer ${JSON.parse(localStorage.getItem(this.auth)).Token}`, }; } else { headers = { 'Content-Type': 'application/json', Accept: 'application/json', }; } return new HttpHeaders(headers); } // ----------------------------------- // ----------------------------------- // ----------------------------------- // ----------------------------------- // ----------------------------------- // ----------------------------------- // INIT CONVERSATION // ----------------------------------- // ----------------------------------- // ----------------------------------- // ----------------------------------- // ----------------------------------- // ----------------------------------- get initHeaders() { return new HttpHeaders({ 'Content-Type': 'application/json', Accept: 'application/json', Authorization: `Bearer ${this.config.apiSecret}`, }); } getWelcomeMessage(locationPermission) { // ------------------------------------------- // To get user current location (long and lat) conditionally then call welcome message const oldAuthStorage = JSON.parse(localStorage.getItem(this.auth ? this.auth : 'temp_user')); const addToAuthStorage = { ...oldAuthStorage, }; const callWelcomeMessage = () => { this.getInitialWelcomeMessage().subscribe((res) => { if (res) { this.initMessage = res; this._botResponse$.next(res); } }); }; if (locationPermission) { // If Location access is allowed ( Completely remove for now ) const success = (pos) => { this.currentLocation = { long: pos.coords.longitude, lat: pos.coords.latitude, }; if (this.currentLocation) { addToAuthStorage.lat = this.currentLocation.lat; addToAuthStorage.long = this.currentLocation.long; } localStorage.setItem(this.auth ? this.auth : 'temp_user', JSON.stringify(addToAuthStorage)); callWelcomeMessage(); }; navigator.geolocation.getCurrentPosition(success); } else { // if Location access is not allowed delete addToAuthStorage.lat; delete addToAuthStorage.long; localStorage.setItem(this.auth ? this.auth : 'temp_user', JSON.stringify(addToAuthStorage)); callWelcomeMessage(); } } initConversation() { this.pubsub.$pub('ARI-LOADING'); // GET INITIAL MESSAGE FROM PROJECT API const headers = this.initHeaders; this.httpClient.post(baseUrl, {}, { headers }).subscribe((response) => { this.ariCreds = response; this.ariBotConversationId = this.ariCreds.conversationId; const oldAuthStorage = JSON.parse(localStorage.getItem(this.auth ? this.auth : 'temp_user')); const addToAuthStorage = { ...oldAuthStorage, conversationId: this.ariBotConversationId, conversionToken: this.ariCreds.token, }; localStorage.setItem(this.auth ? this.auth : 'temp_user', JSON.stringify(addToAuthStorage)); localStorage.setItem('AriCreds', JSON.stringify(response)); this.pubsub.$pub('ARI-LOADING-DONE'); this.hasInitializedConversation = true; this.getWelcomeMessage(false); }, (error) => { console.error('AriBot Error: ', error); this.pubsub.$pub('ARI-ERROR', error); this.pubsub.$pub('ARI-LOADING-DONE'); }); } // ----------------------------------- // ----------------------------------- // ----------------------------------- // ----------------------------------- // ----------------------------------- // ----------------------------------- // SEND MESSAGE // ----------------------------------- // ----------------------------------- // ----------------------------------- // ----------------------------------- // ----------------------------------- get conversationHeader() { if (!this.ariCreds) { this.ariCreds = localStorage.getItem('AriCreds'); this.ariCreds$.next(this.ariCreds); } const { token } = this.ariCreds; return new HttpHeaders({ 'Content-Type': 'application/json', Accept: 'application/json', Authorization: `Bearer ${token}`, }); } sendMessage(message) { const { type } = message; const { from, text } = message; const body = { type: type || 'message', from, text, }; this.pubsub.$pub('ARI-LOADING'); if (this.ariCreds) { const { conversationId } = this.ariCreds; const headers = this.conversationHeader; const url = `${baseUrl}/${conversationId}/activities`; this.httpClient.post(url, body, { headers }).subscribe((response) => { if (response) { this.subscribeToConversations(); this.pubsub.$pub('ARI-LOADING-DONE'); } }, (error) => { console.error('AriBot Error: ', error); this.pubsub.$pub('ARI-ERROR', error); this.pubsub.$pub('ARI-LOADING-DONE'); }); } else { this.pubsub.$pub('ARI-LOADING-DONE'); } } // ----------------------------------- // ----------------------------------- // ----------------------------------- // ----------------------------------- // ----------------------------------- // ----------------------------------- // TASK ACTIONS // ----------------------------------- // ----------------------------------- // ----------------------------------- // ----------------------------------- // ----------------------------------- taskActionMoveTo(payload) { const params = { ...payload, timeZone: Intl.DateTimeFormat().resolvedOptions().timeZone, }; const url = `${this.baseUrlproject}/api/tasks/move`; const header = this.commonStateChangeHeaders(); return this.httpClient.put(url, params, { headers: header, }); } taskMoveTo(payload) { return new Promise((resolve, reject) => { this.taskActionMoveTo(payload).subscribe((res) => { resolve(res ? res : null); }, (err) => { resolve(err.error); }); }); } taskActionTrash(id) { const url = `${this.baseUrlproject}/api/tasks/${id}`; const header = this.commonStateChangeHeaders(); return this.httpClient.delete(url, { headers: header, }); } taskTrash(id) { return new Promise((resolve, reject) => { this.taskActionTrash(id).subscribe((res) => { resolve(true); }, (err) => { resolve(false); }); }); } // ----------------------------------- // ----------------------------------- // ----------------------------------- // ----------------------------------- // ----------------------------------- // ----------------------------------- // RESET // ----------------------------------- // ----------------------------------- // ----------------------------------- // ----------------------------------- // ----------------------------------- resetConversation() { this._botResponse$.next(null); } ngOnDestroy() { this.resetConversation(); this.unsubscribe$.next(); this.unsubscribe$.complete(); } } AriBotService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.3.4", ngImport: i0, type: AriBotService, deps: [{ token: i1.HttpClient }, { token: i2.PubsubService }, { token: i3.CommonService }, { token: AriConfigService }], target: i0.ɵɵFactoryTarget.Injectable }); AriBotService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "13.3.4", ngImport: i0, type: AriBotService, providedIn: 'root' }); i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.4", ngImport: i0, type: AriBotService, decorators: [{ type: Injectable, args: [{ providedIn: 'root', }] }], ctorParameters: function () { return [{ type: i1.HttpClient }, { type: i2.PubsubService }, { type: i3.CommonService }, { type: undefined, decorators: [{ type: Inject, args: [AriConfigService] }] }]; } }); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYXJpLWJvdC5zZXJ2aWNlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vcHJvamVjdHMvbmd4LWxpZy1hcmkvc3JjL2xpYi9zZXJ2aWNlcy9hcmktYm90LnNlcnZpY2UudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLFVBQVUsRUFBYSxNQUFNLEVBQUUsTUFBTSxlQUFlLENBQUM7QUFDOUQsT0FBTyxFQUFjLFdBQVcsRUFBRSxNQUFNLHNCQUFzQixDQUFDO0FBQy9ELE9BQU8sRUFDTCxPQUFPLEVBRVAsZUFBZSxFQUNmLEtBQUssR0FFTixNQUFNLE1BQU0sQ0FBQztBQUtkLE9BQU8sRUFDTCxHQUFHLEVBQ0gsU0FBUyxFQUNULFVBQVUsRUFDVixTQUFTLEVBQ1QsU0FBUyxHQUNWLE1BQU0sZ0JBQWdCLENBQUM7QUFDeEIsT0FBTyxFQUFhLGdCQUFnQixFQUFFLE1BQU0sdUJBQXVCLENBQUM7QUFFcEUsT0FBTyxpQkFBaUIsQ0FBQzs7Ozs7QUFJekIsTUFBTSxPQUFPLEdBQ1gsaUVBQWlFLENBQUM7QUFDcEUsa0JBQWtCO0FBQ2xCLDJDQUEyQztBQUszQyxNQUFNLE9BQU8sYUFBYTtJQXVCeEIsWUFDVSxVQUFzQixFQUN0QixNQUFxQixFQUNyQixhQUE0QixFQUNGLE1BQWlCO1FBSDNDLGVBQVUsR0FBVixVQUFVLENBQVk7UUFDdEIsV0FBTSxHQUFOLE1BQU0sQ0FBZTtRQUNyQixrQkFBYSxHQUFiLGFBQWEsQ0FBZTtRQUNGLFdBQU0sR0FBTixNQUFNLENBQVc7UUExQjdDLGlCQUFZLEdBQUcsSUFBSSxPQUFPLEVBQU8sQ0FBQztRQUdsQyxjQUFTLEdBQUcsSUFBSSxPQUFPLEVBQUUsQ0FBQztRQUNsQywwQ0FBMEM7UUFDbEMsa0JBQWEsR0FBeUIsSUFBSSxlQUFlLENBQUMsSUFBSSxDQUFDLENBQUM7UUFDeEUsK0JBQTBCLEdBQUcsS0FBSyxDQUFDO1FBQ25DLHFCQUFnQixHQUFHLEtBQUssQ0FB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LElBQUksQ0FBQyxZQUFZLENBQUMsUUFBUSxFQUFFLENBQUM7SUFDL0IsQ0FBQzs7MEdBM2FVLGFBQWEsc0dBMkJkLGdCQUFnQjs4R0EzQmYsYUFBYSxjQUZaLE1BQU07MkZBRVAsYUFBYTtrQkFIekIsVUFBVTttQkFBQztvQkFDVixVQUFVLEVBQUUsTUFBTTtpQkFDbkI7OzBCQTRCSSxNQUFNOzJCQUFDLGdCQUFnQiIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IEluamVjdGFibGUsIE9uRGVzdHJveSwgSW5qZWN0IH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgeyBIdHRwQ2xpZW50LCBIdHRwSGVhZGVycyB9IGZyb20gJ0Bhbmd1bGFyL2NvbW1vbi9odHRwJztcbmltcG9ydCB7XG4gIFN1YmplY3QsXG4gIE9ic2VydmFibGUsXG4gIEJlaGF2aW9yU3ViamVjdCxcbiAgdGltZXIsXG4gIFN1YnNjcmlwdGlvbixcbn0gZnJvbSAncnhqcyc7XG5pbXBvcnQge1xuICBJQ29udmVyc2F0aW9uQWN0aXZpdGllcyxcbiAgSU1lc3NhZ2VBY3Rpdml0eSxcbn0gZnJvbSAnLi4vbW9kZWwvY29udmVyc2F0aW9uLm1vZGVsJztcbmltcG9ydCB7XG4gIG1hcCxcbiAgdGFrZVVudGlsLFxuICBjYXRjaEVycm9yLFxuICBzdGFydFdpdGgsXG4gIHN3aXRjaE1hcCxcbn0gZnJvbSAncnhqcy9vcGVyYXRvcnMnO1xuaW1wb3J0IHsgQXJpQ29uZmlnLCBBcmlDb25maWdTZXJ2aWNlIH0gZnJvbSAnLi4vbW9kZWwvYXJpLWJvdC5tb2RlJztcbmltcG9ydCB7IFB1YnN1YlNlcnZpY2UgfSBmcm9tICcuL3B1YnN1Yi5zZXJ2aWNlJztcbmltcG9ydCAnbW9tZW50LXRpbWV6b25lJztcbmltcG9ydCB7IENvbW1vblNlcnZpY2UgfSBmcm9tICcuL2NvbW1vbi5zZXJ2aWNlJztcbmltcG9ydCAqIGFzIG1vbWVudCBmcm9tICdtb21lbnQnO1xuXG5jb25zdCBiYXNlVXJsID1cbiAgJ2h0dHBzOi8vZGlyZWN0bGluZS5ib3RmcmFtZXdvcmsuY29tL3YzL2RpcmVjdGxpbmUvY29udmVyc2F0aW9ucyc7XG4vLyBjb25zdCBiYXNlVXJsID1cbi8vICAgJ2h0dHA6Ly9sb2NhbGhvc3Q6NjIxMTQvYXBpL21lc3NhZ2VzJztcblxuQEluamVjdGFibGUoe1xuICBwcm92aWRlZEluOiAncm9vdCcsXG59KVxuZXhwb3J0IGNsYXNzIEFyaUJvdFNlcnZpY2UgaW1wbGVtZW50cyBPbkRlc3Ryb3kge1xuICBwcml2YXRlIHVuc3Vic2NyaWJlJCA9IG5ldyBTdWJqZWN0PGFueT4oKTtcblxuICBwcml2YXRlIGFyaUNyZWRzOiBhbnk7XG4gIHByaXZhdGUgYXJpQ3JlZHMkID0gbmV3IFN1YmplY3QoKTtcbiAgLy8gdHNsaW50OmRpc2FibGUtbmV4dC1saW5lOiB2YXJpYWJsZS1uYW1lXG4gIHByaXZhdGUgX2JvdFJlc3BvbnNlJDogQmVoYXZpb3JTdWJqZWN0PGFueT4gPSBuZXcgQmVoYXZpb3JTdWJqZWN0KG51bGwpO1xuICBoYXNJbml0aWFsaXplZENvbnZlcnNhdGlvbiA9IGZhbHNlO1xuICBoYXNDb252ZXJzYXRpb25zID0gZmFsc2U7XG4gIHByaXZhdGUgcmVzZXQkID0gbmV3IFN1YmplY3QoKTtcbiAgdGltZXIkOiBPYnNlcnZhYmxlPGFueT47XG4gIHN1YnNjcmlwdGlvbjogU3Vic2NyaXB0aW9uO1xuICBhdXRoOiBhbnk7XG4gIGJhc2VVcmxwcm9qZWN0OiBhbnk7XG4gIHByb2plY3Q6IG51bWJlcjtcbiAgaW5pdE1lc3NhZ2U6IGFueSA9IHt9O1xuICBhc3Npc3RhbnROYW1lID0gJ0FyaSc7XG4gIGFyaUJvdENvbnZlcnNhdGlvbklkOiBzdHJpbmc7XG4gIGN1cnJlbnRMb2NhdGlvbjogYW55O1xuICBwdWJsaWMgbG9jYXRpb25BY2Nlc3MkID0gbmV3IFN1YmplY3Q8Ym9vbGVhbj4oKTtcbiAgZ2V0IGxvY2F0aW9uU3RhdHVzQ2hhbmdlZCgpOiBPYnNlcnZhYmxlPGJvb2xlYW4+IHtcbiAgICByZXR1cm4gdGhpcy5sb2NhdGlvbkFjY2VzcyQuYXNPYnNlcnZhYmxlKCk7XG4gIH1cbiAgY29uc3RydWN0b3IoXG4gICAgcHJpdmF0ZSBodHRwQ2xpZW50OiBIdHRwQ2xpZW50LFxuICAgIHByaXZhdGUgcHVic3ViOiBQdWJzdWJTZXJ2aWNlLFxuICAgIHByaXZhdGUgY29tbW9uU2VydmljZTogQ29tbW9uU2VydmljZSxcbiAgICBASW5qZWN0KEFyaUNvbmZpZ1NlcnZpY2UpIHByaXZhdGUgY29uZmlnOiBBcmlDb25maWdcbiAgKSB7XG4gICAgaWYgKGNvbmZpZy5zZXR0aW5ncykge1xuICAgICAgdGhpcy5hc3Npc3RhbnROYW1lID0gY29uZmlnLnNldHRpbmdzLmFzc2lzdGFudE5hbWU7XG4gICAgICB0aGlzLmF1dGggPSBjb25maWcuc2V0dGluZ3MuYXV0aDtcbiAgICAgIHRoaXMucHJvamVjdCA9IGNvbmZpZy5zZXR0aW5ncy5wcm9qZWN0O1xuICAgICAgdGhpcy5iYXNlVXJscHJvamVjdCA9IGNvbmZpZy5zZXR0aW5ncy5iYXNlVXJsO1xuICAgIH1cbiAgICB0aGlzLmFyaUNyZWRzJC5waXBlKHRha2VVbnRpbCh0aGlzLnVuc3Vic2NyaWJlJCkpLnN1YnNjcmliZSgoY3JlZHMpID0+IHtcbiAgICAgIGlmIChjcmVkcykge1xuICAgICAgICB0aGlzLnN1YnNjcmliZVRvQ29udmVyc2F0aW9ucygpO1xuICAgICAgfVxuICAgIH0pO1xuICB9XG5cbiAgYm90UmVzcG9uc2UkKCk6IE9ic2VydmFibGU8YW55PiB7XG4gICAgcmV0dXJuIHRoaXMuX2JvdFJlc3BvbnNlJC5hc09ic2VydmFibGUoKTtcbiAgfVxuICBhcmlUaW1lb3V0KCkge1xuICAgIHRoaXMudGltZXIkID0gdGhpcy5yZXNldCQucGlwZShcbiAgICAgIHN0YXJ0V2l0aCgwKSxcbiAgICAgIHN3aXRjaE1hcCgoKSA9PiB0aW1lcigwLCAxMDAwKSkgLy8gMTAwMCA9IDFzZWNcbiAgICApO1xuICAgIHRoaXMuc3Vic2NyaXB0aW9uID0gdGhpcy50aW1lciQuc3Vic2NyaWJlKChpKSA9PiB7XG4gICAgICAvLy8gNSBNaW51dGVzIHJlc2V0IHRoZSB0aW1lciBhbmQgY2xvc2UgYXJpIGFuZCBzaG93IFwiSSBoYXZlIG5vdCBoZWFyZCBmcm9tIHlvdSBmb3IgYSB3aGlsZSBzbyBJIHByZXN1bWUgdGhhdCB5b3UgYXJlIGJ1c3kuIENhbGwgbWUgYWdhaW4gd2hlbiB5b3UgYXJlIHJlYWR5LiBHb29kYnllLlwiXG4gICAgICBpZiAoaSA9PSA2MDApIHtcbiAgICAgICAgLy8gMzAwIHNlY3MgPSA1IG1pbnV0ZXNcbiAgICAgICAgdGhpcy5zdWJzY3JpcHRpb24udW5zdWJzY3JpYmUoKTtcbiAgICAgICAgdGhpcy5wdWJzdWIuJHB1YignQVJJLVRJTUVPVVQnLCB0cnVlKTtcbiAgICAgIH1cbiAgICB9KTtcbiAgfVxuICByZWZyZXNoVGltZXIoKTogdm9pZCB7XG4gICAgdGhpcy5yZXNldCQubmV4dCgwKTtcbiAgfVxuICBzdG9wVGltZXIoKSB7XG4gICAgdGhpcy5zdWJzY3JpcHRpb24udW5zdWJzY3JpYmUoKTtcbiAgfVxuICBzdWJzY3JpYmVUb0NvbnZlcnNhdGlvbnMoKSB7XG4gICAgbGV0IGVtcHR5Q29udmVyc2F0aW9uSWQ7XG4gICAgbGV0IGhhc0VtcHR5Q29udmVyc2F0aW9uID0gZmFsc2U7XG4gICAgdGhpcy5oYXNDb252ZXJzYXRpb25zID0gdHJ1ZTtcblxuICAgIHJldHVybiB0aGlzLmdldENvbnZlcnNhdGlvbnMoKVxuICAgICAgLnBpcGUoXG4gICAgICAgIG1hcCgoY29udmVyc2F0aW9ucykgPT4ge1xuICAgICAgICAgIGNvbnN0IHsgYWN0aXZpdGllcyB9ID0gY29udmVyc2F0aW9ucztcbiAgICAgICAgICBjb252ZXJzYXRpb25zLmFjdGl2aXRpZXMgPSBhY3Rpdml0aWVzLmZpbHRlcigoYWN0aXZpdHk6IGFueSkgPT4ge1xuXG4gICAgICAgICAgICBpZiAoYWN0aXZpdHkuZnJvbS5Ub2tlbiAmJiBhY3Rpdml0eS5mcm9tLlJlZnJlc2hUb2tlbikge1xuICAgICAgICAgICAgICB0aGlzLmNvbW1vblNlcnZpY2UudXBkYXRlVXNlck9iamVjdChcbiAgICAgICAgICAgICAgICBhY3Rpdml0eS5mcm9tLlRva2VuLFxuICAgICAgICAgICAgICAgIGFjdGl2aXR5LmZyb20uUmVmcmVzaFRva2VuXG4gICAgICAgICAgICAgICk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoXG4gICAgICAgICAgICAgIChhY3Rpdml0eS50ZXh0IHx8IGFjdGl2aXR5LnJlcGx5VG9JZCAhPT0gZW1wdHlDb252ZXJzYXRpb25JZCkgJiZcbiAgICAgICAgICAgICAgaGFzRW1wdHlDb252ZXJzYXRpb24gPT09IGZhbHNlXG4gICAgICAgICAgICApIHtcbiAgICAgICAgICAgICAgcmV0dXJuIGFjdGl2aXR5O1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAoIWFjdGl2aXR5LnRleHQpIHtcbiAgICAgICAgICAgICAgZW1wdHlDb252ZXJzYXRpb25JZCA9IGFjdGl2aXR5LmlkO1xuICAgICAgICAgICAgICBoYXNFbXB0eUNvbnZlcnNhdGlvbiA9IHRydWU7XG4gICAgICAgICAgICAgIGFjdGl2aXR5Lmhhc0VtcHR5Q29udmVyc2F0aW9uID0gdHJ1ZTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgIGhhc0VtcHR5Q29udmVyc2F0aW9uID0gZmFsc2U7XG4gICAgICAgICAgICAgIGFjdGl2aXR5Lmhhc0VtcHR5Q29udmVyc2F0aW9uID0gZmFsc2U7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfSk7XG4gICAgICAgICAgcmV0dXJuIGNvbnZlcnNhdGlvbnM7XG4gICAgICAgIH0pLFxuICAgICAgICBjYXRjaEVycm9yKChlcnJvcikgPT4ge1xuICAgICAgICAgIHRoaXMucHVic3ViLiRwdWIoJ0FSSS1FUlJPUicsIGVycm9yKTtcbiAgICAgICAgICB0aGlzLnB1YnN1Yi4kcHViKCdBUkktTE9BRElORy1ET05FJyk7XG4gICAgICAgICAgcmV0dXJuIGVycm9yLmVycm9yO1xuICAgICAgICB9KSxcbiAgICAgICAgdGFrZVVudGlsKHRoaXMudW5zdWJzY3JpYmUkKVxuICAgICAgKVxuICAgICAgLnN1YnNjcmliZSgocmVzcG9uc2U6IGFueSkgPT4ge1xuICAgICAgICBpZiAocmVzcG9uc2UpIHtcbiAgICAgICAgICBjb25zdCBnZXRBbGxBY3Rpdml0aWVzID0gdGhpcy5pbml0TWVzc2FnZS5hY3Rpdml0aWVzXG4gICAgICAgICAgICA/IHRoaXMuaW5pdE1lc3NhZ2UuYWN0aXZpdGllcy5jb25jYXQocmVzcG9uc2UuYWN0aXZpdGllcylcbiAgICAgICAgICAgIDogcmVzcG9uc2UuYWN0aXZpdGllcztcbiAgICAgICAgICBjb25zdCB2YWxpZEFjdGl2aXRpZXMgPSBnZXRBbGxBY3Rpdml0aWVzLmZpbHRlcigoaXRlbSkgPT4ge1xuICAgICAgICAgICAgaWYgKGl0ZW0uaWQpIHtcbiAgICAgICAgICAgICAgcmV0dXJuIGl0ZW07XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfSk7XG4gICAgICAgICAgY29uc3QgZGF0YVJlc3BvbnNlID0ge1xuICAgICAgICAgICAgYWN0aXZpdGllczogdmFsaWRBY3Rpdml0aWVzLFxuICAgICAgICAgICAgd2F0ZXJtYXJrOiByZXNwb25zZS53YXRlcm1hcmssXG4gICAgICAgICAgfTtcbiAgICAgICAgICB0aGlzLl9ib3RSZXNwb25zZSQubmV4dChkYXRhUmVzcG9uc2UpO1xuICAgICAgICB9XG4gICAgICB9KTtcbiAgfVxuXG4gIHByaXZhdGUgZ2V0Q29udmVyc2F0aW9ucygpOiBPYnNlcnZhYmxlPElDb252ZXJzYXRpb25BY3Rpdml0aWVzPiB7XG4gICAgY29uc3QgeyBjb252ZXJzYXRpb25JZCB9ID0gdGhpcy5hcmlDcmVkcztcbiAgICBjb25zdCB1cmwgPSBgJHtiYXNlVXJsfS8ke2NvbnZlcnNhdGlvbklkfS9hY3Rpdml0aWVzYDtcbiAgICBjb25zdCBoZWFkZXJzID0gdGhpcy5jb252ZXJzYXRpb25IZWFkZXI7XG5cbiAgICByZXR1cm4gdGhpcy5odHRwQ2xpZW50LmdldDxJQ29udmVyc2F0aW9uQWN0aXZpdGllcz4odXJsLCB7XG4gICAgICBoZWFkZXJzLFxuICAgIH0pO1xuICB9XG5cbiAgcHVibGljIHBhZ2luYXRlVGFza3MocGFyYW1zOiBhbnkpOiBPYnNlcnZhYmxlPGFueT4ge1xuICAgIGNvbnN0IHVybCA9IGAke3RoaXMuYmFzZVVybHByb2plY3R9L2FwaS9hcmkvdGFza3NgO1xuICAgIGNvbnN0IGhlYWRlciA9IHRoaXMuY29tbW9uU3RhdGVDaGFuZ2VIZWFkZXJzKCk7XG4gICAgcmV0dXJuIHRoaXMuaHR0cENsaWVudC5nZXQodXJsLCB7XG4gICAgICBoZWFkZXJzOiBoZWFkZXIsXG4gICAgICBwYXJhbXM6IHBhcmFtcyxcbiAgICB9KTtcbiAgfVxuICBwcml2YXRlIGdldEluaXRpYWxXZWxjb21lTWVzc2FnZSgpOiBPYnNlcnZhYmxlPGFueT4ge1xuICAgIGNvbnN0IGF1dGggPSBKU09OLnBhcnNlKGxvY2FsU3RvcmFnZS5nZXRJdGVtKHRoaXMuYXV0aCkpO1xuXG4gICAgbGV0IHBhcmFtczogYW55ID0ge307XG4gICAgaWYgKGF1dGgpIHtcbiAgICAgIGNvbnN0IHRpbWVab25lID0gSW50bC5EYXRlVGltZUZvcm1hdCgpLnJlc29sdmVkT3B0aW9ucygpLnRpbWVab25lO1xuICAgICAgcGFyYW1zID0ge1xuICAgICAgICBSZWZyZXNoVG9rZW46IGF1dGguUmVmcmVzaFRva2VuLFxuICAgICAgICBUaW1lWm9uZTogYXV0aC50aW1lWm9uZSA/IGF1dGgudGltZVpvbmUgOiB0aW1lWm9uZSxcbiAgICAgICAgUHJvamVjdDogdGhpcy5wcm9qZWN0LFxuICAgICAgICBMb2NhdGlvbjogYXV0aC5sb2NhdGlvblxuICAgICAgICAgID8gYXV0aC5sb2NhdGlvblxuICAgICAgICAgIDogdGltZVpvbmUuc3Vic3RyaW5nKHRpbWVab25lLmluZGV4T2YoJy8nKSArIDEsIHRpbWVab25lLmxlbmd0aCksXG4gICAgICB9O1xuICAgICAgLy8gaWYgKGF1dGgubGF0IHx8IGF1dGgubG9uZykge1xuICAgICAgLy8gICBwYXJhbXMuTGF0ID0gYXV0aC5sYXQ7XG4gICAgICAvLyAgIHBhcmFtcy5Mb25nID0gYXV0aC5sb25nO1xuICAgICAgLy8gfVxuICAgIH0gZWxzZSB7XG4gICAgICBwYXJhbXMgPSB7XG4gICAgICAgIC4uLkpTT04ucGFyc2UobG9jYWxTdG9yYWdlLmdldEl0ZW0oJ3RlbXBfdXNlcicpKSxcbiAgICAgIH07XG4gICAgfVxuICAgIGNvbnN0IHVybCA9IGAke3RoaXMuYmFzZVVybHByb2plY3R9L2FwaS9hcmkvd2VsY29tZWA7XG4gICAgY29uc3QgaGVhZGVyID0gdGhpcy5jb21tb25TdGF0ZUNoYW5nZUhlYWRlcnMoKTtcbiAgICByZXR1cm4gdGhpcy5odHRwQ2xpZW50LmdldCh1cmwsIHtcbiAgICAgIGhlYWRlcnM6IGhlYWRlcixcbiAgICAgIHBhcmFtczogcGFyYW1zLFxuICAgIH0pO1xuICB9XG5cbiAgcHJvdGVjdGVkIGNvbW1vblN0YXRlQ2hhbmdlSGVhZGVycygpOiBhbnkge1xuICAgIGxldCBoZWFkZXJzOiBhbnk7XG4gICAgaWYgKEpTT04ucGFyc2UobG9jYWxTdG9yYWdlLmdldEl0ZW0odGhpcy5hdXRoKSkpIHtcbiAgICAgIGhlYWRlcnMgPSB7XG4gICAgICAgICdDb250ZW50LVR5cGUnOiAnYXBwbGljYXRpb24vanNvbicsXG4gICAgICAgIEFjY2VwdDogJ2FwcGxpY2F0aW9uL2pzb24nLFxuICAgICAgICBBdXRob3JpemF0aW9uOiBgQmVhcmVyICR7SlNPTi5wYXJzZShsb2NhbFN0b3JhZ2UuZ2V0SXRlbSh0aGlzLmF1dGgpKS5Ub2tlblxuICAgICAgICAgIH1gLFxuICAgICAgfTtcbiAgICB9IGVsc2Uge1xuICAgICAgaGVhZGVycyA9IHtcbiAgICAgICAgJ0NvbnRlbnQtVHlwZSc6ICdhcHBsaWNhdGlvbi9qc29uJyxcbiAgICAgICAgQWNjZXB0OiAnYXBwbGljYXRpb24vanNvbicsXG4gICAgICB9O1xuICAgIH1cbiAgICByZXR1cm4gbmV3IEh0dHBIZWFkZXJzKGhlYWRlcnMpO1xuICB9XG5cbiAgLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgLy8gSU5JVCBDT05WRVJTQVRJT05cbiAgLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgZ2V0IGluaXRIZWFkZXJzKCk6IEh0dHBIZWFkZXJzIHtcbiAgICByZXR1cm4gbmV3IEh0dHBIZWFkZXJzKHtcbiAgICAgICdDb250ZW50LVR5cGUnOiAnYXBwbGljYXRpb24vanNvbicsXG4gICAgICBBY2NlcHQ6ICdhcHBsaWNhdGlvbi9qc29uJyxcbiAgICAgIEF1dGhvcml6YXRpb246IGBCZWFyZXIgJHt0aGlzLmNvbmZpZy5hcGlTZWNyZXR9YCxcbiAgICB9KTtcbiAgfVxuXG4gIGdldFdlbGNvbWVNZXNzYWdlKGxvY2F0aW9uUGVybWlzc2lvbj86IGJvb2xlYW4pIHtcbiAgICAvLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gICAgLy8gVG8gZ2V0IHVzZXIgY3VycmVudCBsb2NhdGlvbiAobG9uZyBhbmQgbGF0KSBjb25kaXRpb25hbGx5IHRoZW4gY2FsbCB3ZWxjb21lIG1lc3NhZ2VcbiAgICBjb25zdCBvbGRBdXRoU3RvcmFnZSA9IEpTT04ucGFyc2UoXG4gICAgICBsb2NhbFN0b3JhZ2UuZ2V0SXRlbSh0aGlzLmF1dGggPyB0aGlzLmF1dGggOiAndGVtcF91c2VyJylcbiAgICApO1xuICAgIGNvbnN0IGFkZFRvQXV0aFN0b3JhZ2UgPSB7XG4gICAgICAuLi5vbGRBdXRoU3RvcmFnZSxcbiAgICB9O1xuXG4gICAgY29uc3QgY2FsbFdlbGNvbWVNZXNzYWdlID0gKCkgPT4ge1xuICAgICAgdGhpcy5nZXRJbml0aWFsV2VsY29tZU1lc3NhZ2UoKS5zdWJzY3JpYmUoKHJlczogYW55KSA9PiB7XG4gICAgICAgIGlmIChyZXMpIHtcbiAgICAgICAgICB0aGlzLmluaXRNZXNzYWdlID0gcmVzO1xuICAgICAgICAgIHRoaXMuX2JvdFJlc3BvbnNlJC5uZXh0KHJlcyk7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuICAgIH07XG4gICAgaWYgKGxvY2F0aW9uUGVybWlzc2lvbikge1xuICAgICAgLy8gSWYgTG9jYXRpb24gYWNjZXNzIGlzIGFsbG93ZWQgKCBDb21wbGV0ZWx5IHJlbW92ZSBmb3Igbm93IClcbiAgICAgIGNvbnN0IHN1Y2Nlc3MgPSAocG9zKSA9PiB7XG4gICAgICAgIHRoaXMuY3VycmVudExvY2F0aW9uID0ge1xuICAgICAgICAgIGxvbmc6IHBvcy5jb29yZHMubG9uZ2l0dWRlLFxuICAgICAgICAgIGxhdDogcG9zLmNvb3Jkcy5sYXRpdHVkZSxcbiAgICAgICAgfTtcbiAgICAgICAgaWYgKHRoaXMuY3VycmVudExvY2F0aW9uKSB7XG4gICAgICAgICAgYWRkVG9BdXRoU3RvcmFnZS5sYXQgPSB0aGlzLmN1cnJlbnRMb2NhdGlvbi5sYXQ7XG4gICAgICAgICAgYWRkVG9BdXRoU3RvcmFnZS5sb25nID0gdGhpcy5jdXJyZW50TG9jYXRpb24ubG9uZztcbiAgICAgICAgfVxuICAgICAgICBsb2NhbFN0b3JhZ2Uuc2V0SXRlbShcbiAgICAgICAgICB0aGlzLmF1dGggPyB0aGlzLmF1dGggOiAndGVtcF91c2VyJyxcbiAgICAgICAgICBKU09OLnN0cmluZ2lmeShhZGRUb0F1dGhTdG9yYWdlKVxuICAgICAgICApO1xuICAgICAgICBjYWxsV2VsY29tZU1lc3NhZ2UoKTtcbiAgICAgIH07XG4gICAgICBuYXZpZ2F0b3IuZ2VvbG9jYXRpb24uZ2V0Q3VycmVudFBvc2l0aW9uKHN1Y2Nlc3MpO1xuICAgIH0gZWxzZSB7XG4gICAgICAvLyBpZiBMb2NhdGlvbiBhY2Nlc3MgaXMgbm90IGFsbG93ZWRcbiAgICAgIGRlbGV0ZSBhZGRUb0F1dGhTdG9yYWdlLmxhdDtcbiAgICAgIGRlbGV0ZSBhZGRUb0F1dGhTdG9yYWdlLmxvbmc7XG4gICAgICBsb2NhbFN0b3JhZ2Uuc2V0SXRlbShcbiAgICAgICAgdGhpcy5hdXRoID8gdGhpcy5hdXRoIDogJ3RlbXBfdXNlcicsXG4gICAgICAgIEpTT04uc3RyaW5naWZ5KGFkZFRvQXV0aFN0b3JhZ2UpXG4gICAgICApO1xuICAgICAgY2FsbFdlbGNvbWVNZXNzYWdlKCk7XG4gICAgfVxuICB9XG4gIGluaXRDb252ZXJzYXRpb24oKSB7XG4gICAgdGhpcy5wdWJzdWIuJHB1YignQVJJLUxPQURJTkcnKTtcbiAgICAvLyBHRVQgSU5JVElBTCBNRVNTQUdFIEZST00gUFJPSkVDVCBBUElcbiAgICBjb25zdCBoZWFkZXJzID0gdGhpcy5pbml0SGVhZGVycztcbiAgICB0aGlzLmh0dHBDbGllbnQucG9zdChiYXNlVXJsLCB7fSwgeyBoZWFkZXJzIH0pLnN1YnNjcmliZShcbiAgICAgIChyZXNwb25zZTogYW55KSA9PiB7XG4gICAgICAgIHRoaXMuYXJpQ3JlZHMgPSByZXNwb25zZTtcbiAgICAgICAgdGhpcy5hcmlCb3RDb252ZXJzYXRpb25JZCA9IHRoaXMuYXJpQ3JlZHMuY29udmVyc2F0aW9uSWQ7XG4gICAgICAgIGNvbnN0IG9sZEF1dGhTdG9yYWdlID0gSlNPTi5wYXJzZShcbiAgICAgICAgICBsb2NhbFN0b3JhZ2UuZ2V0SXRlbSh0aGlzLmF1dGggPyB0aGlzLmF1dGggOiAndGVtcF91c2VyJylcbiAgICAgICAgKTtcbiAgICAgICAgY29uc3QgYWRkVG9BdXRoU3RvcmFnZSA9IHtcbiAgICAgICAgICAuLi5vbGRBdXRoU3RvcmFnZSxcbiAgICAgICAgICBjb252ZXJzYXRpb25JZDogdGhpcy5hcmlCb3RDb252ZXJzYXRpb25JZCxcbiAgICAgICAgICBjb252ZXJzaW9uVG9rZW46IHRoaXMuYXJpQ3JlZHMudG9rZW4sXG4gICAgICAgIH07XG4gICAgICAgIGxvY2FsU3RvcmFnZS5zZXRJdGVtKFxuICAgICAgICAgIHRoaXMuYXV0aCA/IHRoaXMuYXV0aCA6ICd0ZW1wX3VzZXInLFxuICAgICAgICAgIEpTT04uc3RyaW5naWZ5KGFkZFRvQXV0aFN0b3JhZ2UpXG4gICAgICAgICk7XG4gICAgICAgIGxvY2FsU3RvcmFnZS5zZXRJdGVtKCdBcmlDcmVkcycsIEpTT04uc3RyaW5naWZ5KHJlc3BvbnNlKSk7XG4gICAgICAgIHRoaXMucHVic3ViLiRwdWIoJ0FSSS1MT0FESU5HLURPTkUnKTtcbiAgICAgICAgdGhpcy5oYXNJbml0aWFsaXplZENvbnZlcnNhdGlvbiA9IHRydWU7XG5cbiAgICAgICAgdGhpcy5nZXRXZWxjb21lTWVzc2FnZShmYWxzZSk7XG4gICAgICB9LFxuICAgICAgKGVycm9yKSA9PiB7XG4gICAgICAgIGNvbnNvbGUuZXJyb3IoJ0FyaUJvdCBFcnJvcjogJywgZXJyb3IpO1xuICAgICAgICB0aGlzLnB1YnN1Yi4kcHViKCdBUkktRVJST1InLCBlcnJvcik7XG4gICAgICAgIHRoaXMucHVic3ViLiRwdWIoJ0FSSS1MT0FESU5HLURPTkUnKTtcbiAgICAgIH1cbiAgICApO1xuICB9XG4gIC8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gIC8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gIC8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gIC8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gIC8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gIC8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gIC8vIFNFTkQgTUVTU0FHRVxuICAvLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAvLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAvLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAvLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAvLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuXG4gIGdldCBjb252ZXJzYXRpb25IZWFkZXIoKTogSHR0cEhlYWRlcnMge1xuICAgIGlmICghdGhpcy5hcmlDcmVkcykge1xuICAgICAgdGhpcy5hcmlDcmVkcyA9IGxvY2FsU3RvcmFnZS5nZXRJdGVtKCdBcmlDcmVkcycpO1xuICAgICAgdGhpcy5hcmlDcmVkcyQubmV4dCh0aGlzLmFyaUNyZWRzKTtcbiAgICB9XG4gICAgY29uc3QgeyB0b2tlbiB9ID0gdGhpcy5hcmlDcmVkcztcbiAgICByZXR1cm4gbmV3IEh0dHBIZWFkZXJzKHtcbiAgICAgICdDb250ZW50LVR5cGUnOiAnYXBwbGljYXRpb24vanNvbicsXG4gICAgICBBY2NlcHQ6ICdhcHBsaWNhdGlvbi9qc29uJyxcbiAgICAgIEF1dGhvcml6YXRpb246IGBCZWFyZXIgJHt0b2tlbn1gLFxuICAgIH0pO1xuICB9XG4gIHNlbmRNZXNzYWdlKG1lc3NhZ2U6IElNZXNzYWdlQWN0aXZpdHkpIHtcbiAgICBjb25zdCB7IHR5cGUgfSA9IG1lc3NhZ2U7XG4gICAgY29uc3QgeyBmcm9tLCB0ZXh0IH0gPSBtZXNzYWdlO1xuICAgIGNvbnN0IGJvZHkgPSB7XG4gICAgICB0eXBlOiB0eXBlIHx8ICdtZXNzYWdlJyxcbiAgICAgIGZyb20sXG4gICAgICB0ZXh0LFxuICAgIH07XG4gICAgdGhpcy5wdWJzdWIuJHB1YignQVJJLUxPQURJTkcnKTtcbiAgICBpZiAodGhpcy5hcmlDcmVkcykge1xuICAgICAgY29uc3QgeyBjb252ZXJzYXRpb25JZCB9ID0gdGhpcy5hcmlDcmVkcztcbiAgICAgIGNvbnN0IGhlYWRlcnMgPSB0aGlzLmNvbnZlcnNhdGlvbkhlYWRlcjtcbiAgICAgIGNvbnN0IHVybCA9IGAke2Jhc2VVcmx9LyR7Y29udmVyc2F0aW9uSWR9L2FjdGl2aXRpZXNgO1xuXG4gICAgICB0aGlzLmh0dHBDbGllbnQucG9zdCh1cmwsIGJvZHksIHsgaGVhZGVycyB9KS5zdWJzY3JpYmUoXG4gICAgICAgIChyZXNwb25zZSkgPT4ge1xuICAgICAgICAgIGlmIChyZXNwb25zZSkge1xuICAgICAgICAgICAgdGhpcy5zdWJzY3JpYmVUb0NvbnZlcnNhdGlvbnMoKTtcbiAgICAgICAgICAgIHRoaXMucHVic3ViLiRwdWIoJ0FSSS1MT0FESU5HLURPTkUnKTtcbiAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgICAgIChlcnJvcikgPT4ge1xuICAgICAgICAgIGNvbnNvbGUuZXJyb3IoJ0FyaUJvdCBFcnJvcjogJywgZXJyb3IpO1xuICAgICAgICAgIHRoaXMucHVic3ViLiRwdWIoJ0FSSS1FUlJPUicsIGVycm9yKTtcbiAgICAgICAgICB0aGlzLnB1YnN1Yi4kcHViKCdBUkktTE9BRElORy1ET05FJyk7XG4gICAgICAgIH1cbiAgICAgICk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRoaXMucHVic3ViLiRwdWIoJ0FSSS1MT0FESU5HLURPTkUnKTtcbiAgICB9XG4gIH1cblxuICAvLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAvLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAvLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAvLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAvLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAvLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAvLyBUQVNLIEFDVElPTlNcbiAgLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cblxuICBwcml2YXRlIHRhc2tBY3Rpb25Nb3ZlVG8ocGF5bG9hZDogYW55KTogT2JzZXJ2YWJsZTxhbnk+IHtcbiAgICBjb25zdCBwYXJhbXMgPSB7XG4gICAgICAuLi5wYXlsb2FkLFxuICAgICAgdGltZVpvbmU6IEludGwuRGF0ZVRpbWVGb3JtYXQoKS5yZXNvbHZlZE9wdGlvbnMoKS50aW1lWm9uZSxcbiAgICB9O1xuICAgIGNvbnN0IHVybCA9IGAke3RoaXMuYmFzZVVybHByb2plY3R9L2FwaS90YXNrcy9tb3ZlYDtcbiAgICBjb25zdCBoZWFkZXIgPSB0aGlzLmNvbW1vblN0YXRlQ2hhbmdlSGVhZGVycygpO1xuICAgIHJldHVybiB0aGlzLmh0dHBDbGllbnQucHV0KHVybCwgcGFyYW1zLCB7XG4gICAgICBoZWFkZXJzOiBoZWFkZXIsXG4gICAgfSk7XG4gIH1cbiAgdGFza01vdmVUbyhwYXlsb2FkOiBhbnkpOiBQcm9taXNlPGFueT4ge1xuICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICB0aGlzLnRhc2tBY3Rpb25Nb3ZlVG8ocGF5bG9hZCkuc3Vic2NyaWJlKFxuICAgICAgICAocmVzOiBhbnkpID0+IHtcbiAgICAgICAgICByZXNvbHZlKHJlcyA/IHJlcyA6IG51bGwpO1xuICAgICAgICB9LFxuICAgICAgICAoZXJyOiBhbnkpID0+IHtcbiAgICAgICAgICByZXNvbHZlKGVyci5lcnJvcik7XG4gICAgICAgIH1cbiAgICAgICk7XG4gICAgfSk7XG4gIH1cbiAgcHJpdmF0ZSB0YXNrQWN0aW9uVHJhc2goaWQ6IGFueSk6IE9ic2VydmFibGU8YW55PiB7XG4gICAgY29uc3QgdXJsID0gYCR7dGhpcy5iYXNlVXJscHJvamVjdH0vYXBpL3Rhc2tzLyR7aWR9YDtcbiAgICBjb25zdCBoZWFkZXIgPSB0aGlzLmNvbW1vblN0YXRlQ2hhbmdlSGVhZGVycygpO1xuICAgIHJldHVybiB0aGlzLmh0dHBDbGllbnQuZGVsZXRlKHVybCwge1xuICAgICAgaGVhZGVyczogaGVhZGVyLFxuICAgIH0pO1xuICB9XG4gIHRhc2tUcmFzaChpZDogYW55KTogUHJvbWlzZTxhbnk+IHtcbiAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT