UNPKG

@cause-911/social-network

Version:

Run `npm install @cause-911/social-network --save` to add this library to your project

418 lines 30.5 kB
/** * @fileoverview added by tsickle * @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc */ import { Injectable } from '@angular/core'; import { LoadScriptService } from './load-script.service'; import { HttpClient, HttpBackend } from '@angular/common/http'; import { Observable, forkJoin, of } from 'rxjs'; import { catchError, delay, map, retryWhen, take } from 'rxjs/operators'; import * as i0 from "@angular/core"; import * as i1 from "@angular/common/http"; import * as i2 from "./load-script.service"; /** * @record */ function Facebook() { } if (false) { /** @type {?} */ Facebook.prototype.Event; /** * @param {?} url * @param {?} callback * @return {?} */ Facebook.prototype.api = function (url, callback) { }; /** * @param {?} config * @return {?} */ Facebook.prototype.init = function (config) { }; /** * @param {?} callback * @param {?} permissions * @return {?} */ Facebook.prototype.login = function (callback, permissions) { }; /** * @param {?} config * @return {?} */ Facebook.prototype.getAuthResponse = function (config) { }; /** * @param {?} config * @return {?} */ Facebook.prototype.getLoginStatus = function (config) { }; } export class FacebookService { /** * @param {?} httpBackend * @param {?} loadScript */ constructor(httpBackend, loadScript) { this.isLoaded = false; this.isInitialize = false; this.httpClient = new HttpClient(httpBackend); loadScript.get('https://connect.facebook.net/en_US/sdk.js').subscribe((/** * @param {?} response * @return {?} */ response => { this.isLoaded = true; }), (/** * @param {?} error * @return {?} */ error => { this.error = error; })); } /** * @param {?} appId * @param {?=} version * @return {?} */ initialize(appId, version = 'v6.0') { this.appId = appId; this.version = version; return Observable.create((/** * @param {?} observer * @return {?} */ observer => { if (this.error) { observer.error(this.error); } else if (!this.isLoaded) { observer.error(new Error('Facebook SDK is not loaded')); } else { observer.next(true); } observer.complete(); })).pipe(map((/** * @return {?} */ () => this.initializeSDK())), retryWhen((/** * @param {?} error * @return {?} */ error => error.pipe(delay(200), take(25)))), catchError((/** * @param {?} error * @return {?} */ error => of(error)))); } /** * @return {?} */ findManageablePage() { return Observable.create((/** * @param {?} observer * @return {?} */ observer => { /** @type {?} */ const loadError = this.validateSDK(); if (loadError) { observer.error(loadError); } this.getAuthentification().subscribe((/** * @param {?} response * @return {?} */ response => { if (response && response.userID) { this.listAccessiblePage(response.userID).subscribe((/** * @param {?} pages * @return {?} */ pages => { observer.next(pages); observer.complete(); }), (/** * @param {?} error * @return {?} */ error => { observer.error(error); })); } else { observer.error(new Error('No user are connected to Facebook')); } }), (/** * @param {?} error * @return {?} */ error => { observer.error(error); })); })); } /** * @return {?} */ askToManagePage() { return Observable.create((/** * @param {?} observer * @return {?} */ observer => { /** @type {?} */ const loadError = this.validateSDK(); if (loadError) { observer.error(loadError); } this.askTokenWithScope('manage_pages, publish_pages').subscribe((/** * @param {?} response * @return {?} */ response => { if (!response.userID) { observer.error(response); } else { this.listAccessiblePage(response.userID).subscribe((/** * @param {?} pages * @return {?} */ pages => { observer.next(pages); observer.complete(); }), (/** * @param {?} error * @return {?} */ error => { observer.error(error); })); } }), (/** * @param {?} error * @return {?} */ error => { observer.error(error); })); })); } /** * @param {?} pageId * @param {?} accessToken * @param {?} message * @param {?=} photos * @return {?} */ publishToPage(pageId, accessToken, message, photos = null) { /** @type {?} */ const body = { message: message, access_token: accessToken, }; if (photos) { return this.postUnpublishedPhotos(pageId, accessToken, photos).pipe(catchError((/** * @param {?} error * @return {?} */ error => { return this.httpClient.post(`https://graph.facebook.com/${pageId}/feed`, body); })), map((/** * @param {?} response * @return {?} */ response => { response.forEach((/** * @param {?} id * @param {?} index * @return {?} */ (id, index) => { body[`attached_media[${index}]`] = { media_fbid: id }; })); return this.httpClient.post(`https://graph.facebook.com/${pageId}/feed`, body); }))); } else { return this.httpClient.post(`https://graph.facebook.com/${pageId}/feed`, body); } } /** * @private * @param {?} pageId * @param {?} accessToken * @param {?} photos * @return {?} */ postUnpublishedPhotos(pageId, accessToken, photos) { /** @type {?} */ const posts = []; photos.forEach((/** * @param {?} photoUrl * @return {?} */ photoUrl => { /** @type {?} */ const task = this.httpClient.post(`https://graph.facebook.com/${pageId}/photos`, { url: photoUrl, caption: '', published: false, access_token: accessToken, }).pipe(map((/** * @param {?} response * @return {?} */ response => response['id']))); posts.push(task); })); return forkJoin(posts); } /** * @private * @param {?} userId * @return {?} */ listAccessiblePage(userId) { return Observable.create((/** * @param {?} observer * @return {?} */ observer => { FB.api(`/${userId}/accounts`, (/** * @param {?} response * @return {?} */ (response) => { if (response && !response.error) { if (response.data instanceof Error) { observer.error(response.data); } else { observer.next(response.data); observer.complete(); } } else { observer.error(response); } })); })); } /** * @private * @param {?} scope * @return {?} */ askTokenWithScope(scope) { return Observable.create((/** * @param {?} observer * @return {?} */ observer => { FB.login((/** * @param {?} response * @return {?} */ (response) => { if (response.authResponse) { observer.next(response.authResponse); observer.complete(); } else { observer.error(new Error('User cancelled login or did not fully authorize')); } }), { scope: scope, }); })); } /** * @private * @return {?} */ getAuthentification() { return Observable.create((/** * @param {?} observer * @return {?} */ observer => { /** @type {?} */ const timer = setTimeout((/** * @return {?} */ () => { observer.error(`Facebook SDK can't be used`); }), 2000); FB.getLoginStatus((/** * @param {?} response * @return {?} */ (response) => { clearTimeout(timer); if (response.status === 'connected') { observer.next(response.authResponse); } else { observer.next({}); } observer.complete(); })); })); } /** * @private * @return {?} */ initializeSDK() { FB.init({ appId: this.appId, cookie: true, xfbml: true, version: this.version, }); this.isInitialize = true; } /** * @private * @return {?} */ validateSDK() { if (location.protocol !== 'https:') { return new Error(`You can only use the Facebook SDK on HTTPS`); } if (!this.isInitialize) { return new Error('You need to initialize the service'); } return false; } } FacebookService.decorators = [ { type: Injectable, args: [{ providedIn: 'root' },] } ]; /** @nocollapse */ FacebookService.ctorParameters = () => [ { type: HttpBackend }, { type: LoadScriptService } ]; /** @nocollapse */ FacebookService.ngInjectableDef = i0.ɵɵdefineInjectable({ factory: function FacebookService_Factory() { return new FacebookService(i0.ɵɵinject(i1.HttpBackend), i0.ɵɵinject(i2.LoadScriptService)); }, token: FacebookService, providedIn: "root" }); if (false) { /** * @type {?} * @private */ FacebookService.prototype.httpClient; /** @type {?} */ FacebookService.prototype.error; /** @type {?} */ FacebookService.prototype.appId; /** @type {?} */ FacebookService.prototype.version; /** @type {?} */ FacebookService.prototype.isLoaded; /** @type {?} */ FacebookService.prototype.isInitialize; } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZmFjZWJvb2suc2VydmljZS5qcyIsInNvdXJjZVJvb3QiOiJuZzovL0BjYXVzZS05MTEvc29jaWFsLW5ldHdvcmsvIiwic291cmNlcyI6WyJsaWIvc2hhcmVkL3NlcnZpY2VzL2ZhY2Vib29rLnNlcnZpY2UudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7OztBQUFBLE9BQU8sRUFBQyxVQUFVLEVBQUMsTUFBTSxlQUFlLENBQUM7QUFDekMsT0FBTyxFQUFDLGlCQUFpQixFQUFDLE1BQU0sdUJBQXVCLENBQUM7QUFDeEQsT0FBTyxFQUFDLFVBQVUsRUFBRSxXQUFXLEVBQUMsTUFBTSxzQkFBc0IsQ0FBQztBQUM3RCxPQUFPLEVBQUMsVUFBVSxFQUFFLFFBQVEsRUFBRSxFQUFFLEVBQUMsTUFBTSxNQUFNLENBQUM7QUFDOUMsT0FBTyxFQUFDLFVBQVUsRUFBRSxLQUFLLEVBQUUsR0FBRyxFQUFFLFNBQVMsRUFBRSxJQUFJLEVBQUMsTUFBTSxnQkFBZ0IsQ0FBQzs7Ozs7OztBQUl2RSx1QkFZQzs7O0lBWEcseUJBQVc7Ozs7OztJQUVYLHNEQUFzQzs7Ozs7SUFFdEMsZ0RBQXdCOzs7Ozs7SUFFeEIsZ0VBQTZDOzs7OztJQUU3QywyREFBbUM7Ozs7O0lBRW5DLDBEQUFrQzs7QUFNdEMsTUFBTSxPQUFPLGVBQWU7Ozs7O0lBUXhCLFlBQ0ksV0FBd0IsRUFDeEIsVUFBNkI7UUFMMUIsYUFBUSxHQUFHLEtBQUssQ0FBQztRQUNqQixpQkFBWSxHQUFHLEtBQUssQ0FBQztRQU14QixJQUFJLENBQUMsVUFBVSxHQUFHLElBQUksVUFBVSxDQUFDLFdBQVcsQ0FBQyxDQUFDO1FBRTlDLFVBQVUsQ0FBQyxHQUFHLENBQUMsMkNBQTJDLENBQUMsQ0FBQyxTQUFTOzs7O1FBQUMsUUFBUSxDQUFDLEVBQUU7WUFDN0UsSUFBSSxDQUFDLFFBQVEsR0FBRyxJQUFJLENBQUM7UUFDekIsQ0FBQzs7OztRQUFFLEtBQUssQ0FBQyxFQUFFO1lBQ1AsSUFBSSxDQUFDLEtBQUssR0FBRyxL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eEIsdUNBQTRCIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHtJbmplY3RhYmxlfSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7TG9hZFNjcmlwdFNlcnZpY2V9IGZyb20gJy4vbG9hZC1zY3JpcHQuc2VydmljZSc7XG5pbXBvcnQge0h0dHBDbGllbnQsIEh0dHBCYWNrZW5kfSBmcm9tICdAYW5ndWxhci9jb21tb24vaHR0cCc7XG5pbXBvcnQge09ic2VydmFibGUsIGZvcmtKb2luLCBvZn0gZnJvbSAncnhqcyc7XG5pbXBvcnQge2NhdGNoRXJyb3IsIGRlbGF5LCBtYXAsIHJldHJ5V2hlbiwgdGFrZX0gZnJvbSAncnhqcy9vcGVyYXRvcnMnO1xuXG5kZWNsYXJlIHZhciBGQjogRmFjZWJvb2s7XG5cbmludGVyZmFjZSBGYWNlYm9vayB7XG4gICAgRXZlbnQ6IGFueTtcblxuICAgIGFwaSh1cmw6IHN0cmluZywgY2FsbGJhY2s6IGFueSk6IHZvaWQ7XG5cbiAgICBpbml0KGNvbmZpZzogYW55KTogdm9pZDtcblxuICAgIGxvZ2luKGNhbGxiYWNrOiBhbnksIHBlcm1pc3Npb25zOiBhbnkpOiB2b2lkO1xuXG4gICAgZ2V0QXV0aFJlc3BvbnNlKGNvbmZpZzogYW55KTogdm9pZDtcblxuICAgIGdldExvZ2luU3RhdHVzKGNvbmZpZzogYW55KTogdm9pZDtcbn1cblxuQEluamVjdGFibGUoe1xuICAgIHByb3ZpZGVkSW46ICdyb290J1xufSlcbmV4cG9ydCBjbGFzcyBGYWNlYm9va1NlcnZpY2Uge1xuICAgIHByaXZhdGUgaHR0cENsaWVudDogSHR0cENsaWVudDtcbiAgICBwdWJsaWMgZXJyb3I6IGFueTtcbiAgICBwdWJsaWMgYXBwSWQ6IHN0cmluZztcbiAgICBwdWJsaWMgdmVyc2lvbjogc3RyaW5nO1xuICAgIHB1YmxpYyBpc0xvYWRlZCA9IGZhbHNlO1xuICAgIHB1YmxpYyBpc0luaXRpYWxpemUgPSBmYWxzZTtcblxuICAgIGNvbnN0cnVjdG9yKFxuICAgICAgICBodHRwQmFja2VuZDogSHR0cEJhY2tlbmQsXG4gICAgICAgIGxvYWRTY3JpcHQ6IExvYWRTY3JpcHRTZXJ2aWNlLFxuICAgICkge1xuICAgICAgICB0aGlzLmh0dHBDbGllbnQgPSBuZXcgSHR0cENsaWVudChodHRwQmFja2VuZCk7XG5cbiAgICAgICAgbG9hZFNjcmlwdC5nZXQoJ2h0dHBzOi8vY29ubmVjdC5mYWNlYm9vay5uZXQvZW5fVVMvc2RrLmpzJykuc3Vic2NyaWJlKHJlc3BvbnNlID0+IHtcbiAgICAgICAgICAgIHRoaXMuaXNMb2FkZWQgPSB0cnVlO1xuICAgICAgICB9LCBlcnJvciA9PiB7XG4gICAgICAgICAgICB0aGlzLmVycm9yID0gZXJyb3I7XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIHB1YmxpYyBpbml0aWFsaXplKGFwcElkOiBzdHJpbmcsIHZlcnNpb246IHN0cmluZyA9ICd2Ni4wJyk6IE9ic2VydmFibGU8Ym9vbGVhbj4ge1xuICAgICAgICB0aGlzLmFwcElkID0gYXBwSWQ7XG4gICAgICAgIHRoaXMudmVyc2lvbiA9IHZlcnNpb247XG5cbiAgICAgICAgcmV0dXJuIE9ic2VydmFibGUuY3JlYXRlKG9ic2VydmVyID0+IHtcbiAgICAgICAgICAgIGlmICh0aGlzLmVycm9yKSB7XG4gICAgICAgICAgICAgICAgb2JzZXJ2ZXIuZXJyb3IodGhpcy5lcnJvcik7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKCF0aGlzLmlzTG9hZGVkKSB7XG4gICAgICAgICAgICAgICAgb2JzZXJ2ZXIuZXJyb3IobmV3IEVycm9yKCdGYWNlYm9vayBTREsgaXMgbm90IGxvYWRlZCcpKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgb2JzZXJ2ZXIubmV4dCh0cnVlKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgb2JzZXJ2ZXIuY29tcGxldGUoKTtcbiAgICAgICAgfSkucGlwZShcbiAgICAgICAgICAgIG1hcCgoKSA9PiB0aGlzLmluaXRpYWxpemVTREsoKSksXG4gICAgICAgICAgICByZXRyeVdoZW4oZXJyb3IgPT4gZXJyb3IucGlwZShcbiAgICAgICAgICAgICAgICBkZWxheSgyMDApLFxuICAgICAgICAgICAgICAgIHRha2UoMjUpLFxuICAgICAgICAgICAgKSksXG4gICAgICAgICAgICBjYXRjaEVycm9yKGVycm9yID0+IG9mKGVycm9yKSlcbiAgICAgICAgKTtcbiAgICB9XG5cbiAgICBwdWJsaWMgZmluZE1hbmFnZWFibGVQYWdlKCk6IE9ic2VydmFibGU8YW55PiB7XG4gICAgICAgIHJldHVybiBPYnNlcnZhYmxlLmNyZWF0ZShvYnNlcnZlciA9PiB7XG4gICAgICAgICAgICBjb25zdCBsb2FkRXJyb3IgPSB0aGlzLnZhbGlkYXRlU0RLKCk7XG4gICAgICAgICAgICBpZiAobG9hZEVycm9yKSB7XG4gICAgICAgICAgICAgICAgb2JzZXJ2ZXIuZXJyb3IobG9hZEVycm9yKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgdGhpcy5nZXRBdXRoZW50aWZpY2F0aW9uKCkuc3Vic2NyaWJlKHJlc3BvbnNlID0+IHtcbiAgICAgICAgICAgICAgICBpZiAocmVzcG9uc2UgJiYgcmVzcG9uc2UudXNlcklEKSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMubGlzdEFjY2Vzc2libGVQYWdlKHJlc3BvbnNlLnVzZXJJRCkuc3Vic2NyaWJlKHBhZ2VzID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIG9ic2VydmVyLm5leHQocGFnZXMpO1xuICAgICAgICAgICAgICAgICAgICAgICAgb2JzZXJ2ZXIuY29tcGxldGUoKTtcbiAgICAgICAgICAgICAgICAgICAgfSwgZXJyb3IgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgb2JzZXJ2ZXIuZXJyb3IoZXJyb3IpO1xuICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBvYnNlcnZlci5lcnJvcihuZXcgRXJyb3IoJ05vIHVzZXIgYXJlIGNvbm5lY3RlZCB0byBGYWNlYm9vaycpKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9LCBlcnJvciA9PiB7XG4gICAgICAgICAgICAgICAgb2JzZXJ2ZXIuZXJyb3IoZXJyb3IpO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIHB1YmxpYyBhc2tUb01hbmFnZVBhZ2UoKTogT2JzZXJ2YWJsZTxhbnk+IHtcbiAgICAgICAgcmV0dXJuIE9ic2VydmFibGUuY3JlYXRlKG9ic2VydmVyID0+IHtcbiAgICAgICAgICAgIGNvbnN0IGxvYWRFcnJvciA9IHRoaXMudmFsaWRhdGVTREsoKTtcbiAgICAgICAgICAgIGlmIChsb2FkRXJyb3IpIHtcbiAgICAgICAgICAgICAgICBvYnNlcnZlci5lcnJvcihsb2FkRXJyb3IpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICB0aGlzLmFza1Rva2VuV2l0aFNjb3BlKCdtYW5hZ2VfcGFnZXMsIHB1Ymxpc2hfcGFnZXMnKS5zdWJzY3JpYmUocmVzcG9uc2UgPT4ge1xuICAgICAgICAgICAgICAgIGlmICghcmVzcG9uc2UudXNlcklEKSB7XG4gICAgICAgICAgICAgICAgICAgIG9ic2VydmVyLmVycm9yKHJlc3BvbnNlKTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmxpc3RBY2Nlc3NpYmxlUGFnZShyZXNwb25zZS51c2VySUQpLnN1YnNjcmliZShwYWdlcyA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICBvYnNlcnZlci5uZXh0KHBhZ2VzKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIG9ic2VydmVyLmNvbXBsZXRlKCk7XG4gICAgICAgICAgICAgICAgICAgIH0sIGVycm9yID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIG9ic2VydmVyLmVycm9yKGVycm9yKTtcbiAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSwgZXJyb3IgPT4ge1xuICAgICAgICAgICAgICAgIG9ic2VydmVyLmVycm9yKGVycm9yKTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICBwdWJsaWMgcHVibGlzaFRvUGFnZShwYWdlSWQ6IHN0cmluZywgYWNjZXNzVG9rZW46IHN0cmluZywgbWVzc2FnZTogc3RyaW5nLCBwaG90b3M6IHN0cmluZ1tdID0gbnVsbCk6IE9ic2VydmFibGU8YW55PiB7XG4gICAgICAgIGNvbnN0IGJvZHkgPSB7XG4gICAgICAgICAgICBtZXNzYWdlOiBtZXNzYWdlLFxuICAgICAgICAgICAgYWNjZXNzX3Rva2VuOiBhY2Nlc3NUb2tlbixcbiAgICAgICAgfTtcblxuICAgICAgICBpZiAocGhvdG9zKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5wb3N0VW5wdWJsaXNoZWRQaG90b3MocGFnZUlkLCBhY2Nlc3NUb2tlbiwgcGhvdG9zKS5waXBlKFxuICAgICAgICAgICAgICAgIGNhdGNoRXJyb3IoZXJyb3IgPT4ge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5odHRwQ2xpZW50LnBvc3QoYGh0dHBzOi8vZ3JhcGguZmFjZWJvb2suY29tLyR7cGFnZUlkfS9mZWVkYCwgYm9keSk7XG4gICAgICAgICAgICAgICAgfSksXG4gICAgICAgICAgICAgICAgbWFwKHJlc3BvbnNlID0+IHtcbiAgICAgICAgICAgICAgICAgICAgcmVzcG9uc2UuZm9yRWFjaCgoaWQsIGluZGV4KSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICBib2R5W2BhdHRhY2hlZF9tZWRpYVske2luZGV4fV1gXSA9IHsgbWVkaWFfZmJpZDogaWQgfTtcbiAgICAgICAgICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuaHR0cENsaWVudC5wb3N0KGBodHRwczovL2dyYXBoLmZhY2Vib29rLmNvbS8ke3BhZ2VJZH0vZmVlZGAsIGJvZHkpO1xuICAgICAgICAgICAgICAgIH0pXG4gICAgICAgICAgICApO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuaHR0cENsaWVudC5wb3N0KGBodHRwczovL2dyYXBoLmZhY2Vib29rLmNvbS8ke3BhZ2VJZH0vZmVlZGAsIGJvZHkpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBwb3N0VW5wdWJsaXNoZWRQaG90b3MocGFnZUlkOiBzdHJpbmcsIGFjY2Vzc1Rva2VuOiBzdHJpbmcsIHBob3Rvczogc3RyaW5nW10pOiBPYnNlcnZhYmxlPGFueT4ge1xuICAgICAgICBjb25zdCBwb3N0cyA9IFtdO1xuXG4gICAgICAgIHBob3Rvcy5mb3JFYWNoKHBob3RvVXJsID0+IHtcbiAgICAgICAgICAgIGNvbnN0IHRhc2sgPSB0aGlzLmh0dHBDbGllbnQucG9zdChgaHR0cHM6Ly9ncmFwaC5mYWNlYm9vay5jb20vJHtwYWdlSWR9L3Bob3Rvc2AsIHtcbiAgICAgICAgICAgICAgICB1cmw6IHBob3RvVXJsLFxuICAgICAgICAgICAgICAgIGNhcHRpb246ICcnLFxuICAgICAgICAgICAgICAgIHB1Ymxpc2hlZDogZmFsc2UsXG4gICAgICAgICAgICAgICAgYWNjZXNzX3Rva2VuOiBhY2Nlc3NUb2tlbixcbiAgICAgICAgICAgIH0pLnBpcGUoXG4gICAgICAgICAgICAgICAgbWFwKHJlc3BvbnNlID0+IHJlc3BvbnNlWydpZCddKVxuICAgICAgICAgICAgKTtcblxuICAgICAgICAgICAgcG9zdHMucHVzaCh0YXNrKTtcbiAgICAgICAgfSk7XG5cbiAgICAgICAgcmV0dXJuIGZvcmtKb2luKHBvc3RzKTtcbiAgICB9XG5cbiAgICBwcml2YXRlIGxpc3RBY2Nlc3NpYmxlUGFnZSh1c2VySWQ6IHN0cmluZyk6IE9ic2VydmFibGU8YW55PiB7XG4gICAgICAgIHJldHVybiBPYnNlcnZhYmxlLmNyZWF0ZShvYnNlcnZlciA9PiB7XG4gICAgICAgICAgICBGQi5hcGkoYC8ke3VzZXJJZH0vYWNjb3VudHNgLCAocmVzcG9uc2U6IGFueSkgPT4ge1xuICAgICAgICAgICAgICAgIGlmIChyZXNwb25zZSAmJiAhcmVzcG9uc2UuZXJyb3IpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHJlc3BvbnNlLmRhdGEgaW5zdGFuY2VvZiBFcnJvcikge1xuICAgICAgICAgICAgICAgICAgICAgICAgb2JzZXJ2ZXIuZXJyb3IocmVzcG9uc2UuZGF0YSk7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBvYnNlcnZlci5uZXh0KHJlc3BvbnNlLmRhdGEpO1xuICAgICAgICAgICAgICAgICAgICAgICAgb2JzZXJ2ZXIuY29tcGxldGUoKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIG9ic2VydmVyLmVycm9yKHJlc3BvbnNlKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBhc2tUb2tlbldpdGhTY29wZShzY29wZTogc3RyaW5nKTogT2JzZXJ2YWJsZTxhbnk+IHtcbiAgICAgICAgcmV0dXJuIE9ic2VydmFibGUuY3JlYXRlKG9ic2VydmVyID0+IHtcbiAgICAgICAgICAgIEZCLmxvZ2luKChyZXNwb25zZTogYW55KSA9PiB7XG4gICAgICAgICAgICAgICAgaWYgKHJlc3BvbnNlLmF1dGhSZXNwb25zZSkge1xuICAgICAgICAgICAgICAgICAgICBvYnNlcnZlci5uZXh0KHJlc3BvbnNlLmF1dGhSZXNwb25zZSk7XG4gICAgICAgICAgICAgICAgICAgIG9ic2VydmVyLmNvbXBsZXRlKCk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgb2JzZXJ2ZXIuZXJyb3IobmV3IEVycm9yKCdVc2VyIGNhbmNlbGxlZCBsb2dpbiBvciBkaWQgbm90IGZ1bGx5IGF1dGhvcml6ZScpKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9LCB7XG4gICAgICAgICAgICAgICAgc2NvcGU6IHNjb3BlLFxuICAgICAgICAgICAgfSk7XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIHByaXZhdGUgZ2V0QXV0aGVudGlmaWNhdGlvbigpOiBPYnNlcnZhYmxlPGFueT4ge1xuICAgICAgICByZXR1cm4gT2JzZXJ2YWJsZS5jcmVhdGUob2JzZXJ2ZXIgPT4ge1xuICAgICAgICAgICAgY29uc3QgdGltZXIgPSBzZXRUaW1lb3V0KCgpID0+IHtcbiAgICAgICAgICAgICAgICBvYnNlcnZlci5lcnJvcihgRmFjZWJvb2sgU0RLIGNhbid0IGJlIHVzZWRgKTtcbiAgICAgICAgICAgIH0sIDIwMDApO1xuXG4gICAgICAgICAgICBGQi5nZXRMb2dpblN0YXR1cygocmVzcG9uc2U6IGFueSkgPT4ge1xuICAgICAgICAgICAgICAgIGNsZWFyVGltZW91dCh0aW1lcik7XG5cbiAgICAgICAgICAgICAgICBpZiAocmVzcG9uc2Uuc3RhdHVzID09PSAnY29ubmVjdGVkJykge1xuICAgICAgICAgICAgICAgICAgICBvYnNlcnZlci5uZXh0KHJlc3BvbnNlLmF1dGhSZXNwb25zZSk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgb2JzZXJ2ZXIubmV4dCh7fSk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgb2JzZXJ2ZXIuY29tcGxldGUoKTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICBwcml2YXRlIGluaXRpYWxpemVTREsoKSB7XG4gICAgICAgIEZCLmluaXQoe1xuICAgICAgICAgICAgYXBwSWQ6IHRoaXMuYXBwSWQsXG4gICAgICAgICAgICBjb29raWU6IHRydWUsXG4gICAgICAgICAgICB4ZmJtbDogdHJ1ZSxcbiAgICAgICAgICAgIHZlcnNpb246IHRoaXMudmVyc2lvbixcbiAgICAgICAgfSk7XG5cbiAgICAgICAgdGhpcy5pc0luaXRpYWxpemUgPSB0cnVlO1xuICAgIH1cblxuICAgIHByaXZhdGUgdmFsaWRhdGVTREsoKSB7XG4gICAgICAgIGlmIChsb2NhdGlvbi5wcm90b2NvbCAhPT0gJ2h0dHBzOicpIHtcbiAgICAgICAgICAgIHJldHVybiBuZXcgRXJyb3IoYFlvdSBjYW4gb25seSB1c2UgdGhlIEZhY2Vib29rIFNESyBvbiBIVFRQU2ApO1xuICAgICAgICB9XG4gICAgICAgIGlmICghdGhpcy5pc0luaXRpYWxpemUpIHtcbiAgICAgICAgICAgIHJldHVybiBuZXcgRXJyb3IoJ1lvdSBuZWVkIHRvIGluaXRpYWxpemUgdGhlIHNlcnZpY2UnKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG59XG4iXX0=