UNPKG

angular-chat-widget-rasa

Version:

A chatbot widget that is able to connect to a rasa chatbot using SocketIO

244 lines 20.4 kB
/** * @fileoverview added by tsickle * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc */ import { Component, ElementRef, HostListener, Input, ViewChild } from '@angular/core'; import { Subject } from 'rxjs'; import { fadeIn, fadeInOut } from '../animations'; import { ChatService } from '../chatbot-rasa.service'; /** @type {?} */ var rand = (/** * @param {?} max * @return {?} */ function (max) { return Math.floor(Math.random() * max); }); var ɵ0 = rand; var ChatWidgetComponent = /** @class */ (function () { function ChatWidgetComponent(chatService) { this.theme = 'blue'; this.botName = 'Bot'; this.botAvatar = "https://cdn.dribbble.com/users/275794/screenshots/3128598/gbot_800.png"; this.userAvatar = "https://storage.proboards.com/6172192/images/gKhXFw_5W0SD4nwuMev1.png"; this.url = 'http://localhost:5002'; this.startingMessage = 'Hi, how can we help you?'; this.opened = true; this._visible = false; this.focus = new Subject(); this.messages = []; this.chatService = chatService; this.chatService.connect(this.url); } Object.defineProperty(ChatWidgetComponent.prototype, "visible", { get: /** * @return {?} */ function () { return this._visible; }, set: /** * @param {?} visible * @return {?} */ function (visible) { var _this = this; this._visible = visible; if (this._visible) { setTimeout((/** * @return {?} */ function () { _this.scrollToBottom(); _this.focusMessage(); }), 0); } }, enumerable: true, configurable: true }); /** * @param {?} from * @param {?} text * @param {?} type * @return {?} */ ChatWidgetComponent.prototype.addMessage = /** * @param {?} from * @param {?} text * @param {?} type * @return {?} */ function (from, text, type) { this.messages.unshift({ from: from, text: text, type: type, date: new Date().getTime(), }); this.scrollToBottom(); }; /** * @return {?} */ ChatWidgetComponent.prototype.scrollToBottom = /** * @return {?} */ function () { if (this.bottom !== undefined) { this.bottom.nativeElement.scrollIntoView(); } }; /** * @return {?} */ ChatWidgetComponent.prototype.focusMessage = /** * @return {?} */ function () { this.focus.next(true); }; /** * @return {?} */ ChatWidgetComponent.prototype.ngOnInit = /** * @return {?} */ function () { var _this = this; this.client = { name: 'Guest User', status: 'online', avatar: this.userAvatar, }; this.operator = { name: this.botName, status: 'online', avatar: this.botAvatar, }; if (this.opened) { setTimeout((/** * @return {?} */ function () { return _this.visible = true; }), 1000); } setTimeout((/** * @return {?} */ function () { _this.addMessage(_this.operator, _this.startingMessage, 'received'); }), 1500); this.chatService .getMessages() .subscribe((/** * @param {?} message * @return {?} */ function (message) { setTimeout((/** * @return {?} */ function () { _this.addMessage(_this.operator, message.text, 'received'); }), 1000); })); }; /** * @return {?} */ ChatWidgetComponent.prototype.toggleChat = /** * @return {?} */ function () { this.visible = !this.visible; }; /** * @param {?} __0 * @return {?} */ ChatWidgetComponent.prototype.sendMessage = /** * @param {?} __0 * @return {?} */ function (_a) { var message = _a.message; if (message.trim() === '') { return; } this.addMessage(this.client, message, 'sent'); this.chatService.sendMessage(message); }; /** * @param {?} event * @return {?} */ ChatWidgetComponent.prototype.handleKeyboardEvent = /** * @param {?} event * @return {?} */ function (event) { if (event.key === '/') { this.focusMessage(); } if (event.key === '?' && !this._visible) { this.toggleChat(); } }; ChatWidgetComponent.decorators = [ { type: Component, args: [{ selector: 'chat-widget', template: "<div class=\"wrapper {{theme}}\">\n <div class=\"chat-box\" *ngIf=\"visible\" [@fadeInOut]=\"visible\">\n <div class=\"chat-box-header\">\n <div class=\"\">\n <div class=\"operator-status\">\n {{operator.status}}\n <span class=\"operator-status-online\">\u25CF</span>\n <button class=\"chat-button-header\" (click)=\"toggleChat()\">\u2715</button>\n </div>\n <chat-avatar [image]=\"operator.avatar\"></chat-avatar>\n <h3 class=\"operator-name\">\n {{operator.name}}\n </h3>\n </div>\n </div>\n <div class=\"chat-box-main\">\n <div class=\"chat-message-bottom\" #bottom></div>\n <ng-container *ngFor=\"let message of messages\">\n <div class=\"chat-message\" [class.chat-message-received]=\"message.type === 'received'\"\n [@fadeIn]\n [class.chat-message-sent]=\"message.type === 'sent'\">\n <div >\n <chat-avatar [image]=\"message.from.avatar\" class=\"chat-message-from-avatar\"></chat-avatar>\n <div class=\"chat-message-text\">\n {{message.text}}\n </div>\n </div>\n <div class=\"chat-message-date\">\n {{message.date | date: 'short'}}\n </div>\n </div>\n </ng-container>\n </div>\n <div class=\"chat-box-footer\">\n <chat-input (send)=\"sendMessage($event)\" (dismiss)=\"toggleChat()\" [focus]=\"focus\"></chat-input>\n </div>\n </div>\n <button class=\"chat-button\" (click)=\"toggleChat()\">\n <span [@fadeIn] *ngIf=\"visible\">\u2715</span>\n <span [@fadeIn] *ngIf=\"!visible\">?</span>\n </button>\n</div>\n", animations: [fadeInOut, fadeIn], styles: ["*{box-sizing:border-box;position:relative;font-family:\"Open Sans\",\"Helvetica Neue\",sans-serif}.wrapper{position:absolute;top:0;bottom:0;height:100vh;width:100vw}.chat-button{z-index:1;width:60px;height:60px;position:absolute;bottom:20px;right:40px;box-shadow:0 5px 40px rgba(0,0,0,.16);background:#1976d2;border-radius:50%;border:none;outline:0;color:#fff;font-size:32px}.chat-button-header{z-index:1;font-weight:700;color:#fff;border:1px solid #fff;background-color:inherit;padding:5px 9px;margin-left:5px}.chat-button:focus{border:2px solid #fff}.chat-box{z-index:2;position:absolute;left:0;height:100vh;width:100vw;margin:0;display:flex;flex-direction:column;box-shadow:0 5px 40px rgba(0,0,0,.16);background:#1976d2}.chat-box-hidden{display:none}.chat-box-header{padding:10px;color:#fff}.chat-box-main{flex:1;width:100%;background:#f5f5f5;display:flex;flex-direction:column-reverse;overflow:auto}.chat-box-footer{color:#fff;height:50px}.operator-name{margin:0;padding:1px}.operator-status{float:right;padding:4px}.operator-status span{margin-left:4px}.operator-status-online{color:#7cfc00}.operator-status-offline{color:red}.operator-avatar{height:30px;width:30px;border-radius:50%;float:left;margin-right:10px}.chat-message{display:block;width:auto;margin:5px;align-self:flex-start;flex-direction:row;max-width:80%;word-wrap:break-word}.chat-message-date{font-size:11px;color:#8d898d;padding:5px}.chat-message-from-avatar{height:35px;width:35px;border-radius:50%}.chat-message-text{margin-left:10px;padding:10px;border-radius:3px}.chat-message-received{margin-right:50px}.chat-message-received .chat-message-text{background:#b9d6f2;margin-left:50px;border-bottom-left-radius:0}.chat-message-received .chat-message-text:before{position:absolute;content:\" \";left:-10px;bottom:0;border-right:10px solid #b9d6f2;border-top:10px solid transparent;z-index:0}.chat-message-received .chat-message-date{margin-left:50px}.chat-message-received .chat-message-from-avatar{position:absolute;left:0;bottom:-15px}.chat-message-sent{align-self:flex-end}.chat-message-sent .chat-message-from{float:right}.chat-message-sent .chat-message-text{background:#84dccf;margin-right:50px;border-bottom-right-radius:0}.chat-message-sent .chat-message-text:after{position:absolute;content:\" \";right:-10px;bottom:0;border-left:10px solid #84dccf;border-top:10px solid transparent;z-index:0}.chat-message-sent .chat-message-date{text-align:right;padding-right:50px}.chat-message-sent .chat-message-from-avatar{position:absolute;right:0;bottom:-15px}.blue .chat-box,.blue .chat-button{background:#1976d2}.grey .chat-box,.grey .chat-button{background:#454549}.red .chat-box,.red .chat-button{background:#dd0031}@media (min-width:576px){.wrapper{top:auto;right:0;width:300px}.chat-button{display:block}.chat-button-header{display:none}.chat-box{top:auto;left:auto;bottom:100px;right:40px;height:60vh;width:300px;border-radius:10px}}@media (min-width:768px){.chat-box{height:70vh}}@media (min-width:992px){.chat-box{height:80vh}}"] }] } ]; /** @nocollapse */ ChatWidgetComponent.ctorParameters = function () { return [ { type: ChatService } ]; }; ChatWidgetComponent.propDecorators = { bottom: [{ type: ViewChild, args: ['bottom',] }], theme: [{ type: Input }], botName: [{ type: Input }], botAvatar: [{ type: Input }], userAvatar: [{ type: Input }], url: [{ type: Input }], startingMessage: [{ type: Input }], opened: [{ type: Input }], visible: [{ type: Input }], handleKeyboardEvent: [{ type: HostListener, args: ['document:keypress', ['$event'],] }] }; return ChatWidgetComponent; }()); export { ChatWidgetComponent }; if (false) { /** @type {?} */ ChatWidgetComponent.prototype.bottom; /** @type {?} */ ChatWidgetComponent.prototype.theme; /** @type {?} */ ChatWidgetComponent.prototype.botName; /** @type {?} */ ChatWidgetComponent.prototype.botAvatar; /** @type {?} */ ChatWidgetComponent.prototype.userAvatar; /** @type {?} */ ChatWidgetComponent.prototype.url; /** @type {?} */ ChatWidgetComponent.prototype.startingMessage; /** @type {?} */ ChatWidgetComponent.prototype.opened; /** @type {?} */ ChatWidgetComponent.prototype._visible; /** * @type {?} * @private */ ChatWidgetComponent.prototype.chatService; /** @type {?} */ ChatWidgetComponent.prototype.focus; /** @type {?} */ ChatWidgetComponent.prototype.operator; /** @type {?} */ ChatWidgetComponent.prototype.client; /** @type {?} */ ChatWidgetComponent.prototype.messages; } export { ɵ0 }; //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2hhdC13aWRnZXQuY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6Im5nOi8vYW5ndWxhci1jaGF0LXdpZGdldC1yYXNhLyIsInNvdXJjZXMiOlsibGliL2NoYXQtd2lkZ2V0L2NoYXQtd2lkZ2V0LmNvbXBvbmVudC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7O0FBQUEsT0FBTyxFQUFFLFNBQVMsRUFBRSxVQUFVLEVBQUUsWUFBWSxFQUFFLEtBQUssRUFBVSxTQUFTLEVBQUUsTUFBTSxlQUFlLENBQUE7QUFDN0YsT0FBTyxFQUFFLE9BQU8sRUFBRSxNQUFNLE1BQU0sQ0FBQTtBQUM5QixPQUFPLEVBQUUsTUFBTSxFQUFFLFNBQVMsRUFBRSxNQUFNLGVBQWUsQ0FBQTtBQUNqRCxPQUFPLEVBQUUsV0FBVyxFQUFFLE1BQU0seUJBQXlCLENBQUM7O0lBRWhELElBQUk7Ozs7QUFBRyxVQUFBLEdBQUcsSUFBSSxPQUFBLElBQUksQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLE1BQU0sRUFBRSxHQUFHLEdBQUcsQ0FBQyxFQUEvQixDQUErQixDQUFBOztBQUVuRDtJQW9CRSw2QkFBWSxXQUF3QjtRQVpwQixVQUFLLEdBQTRCLE1BQU0sQ0FBQTtRQUN2QyxZQUFPLEdBQVcsS0FBSyxDQUFDO1FBQ3hCLGNBQVMsR0FBVyx3RUFBd0UsQ0FBQTtRQUM1RixlQUFVLEdBQVcsdUVBQXVFLENBQUE7UUFDNUYsUUFBRyxHQUFXLHVCQUF1QixDQUFBO1FBQ3JDLG9CQUFlLEdBQVcsMEJBQTBCLENBQUE7UUFDcEQsV0FBTSxHQUFZLElBQUksQ0FBQTtRQUUvQixhQUFRLEdBQUcsS0FBSyxDQUFBO1FBdUJoQixVQUFLLEdBQUcsSUFBSSxPQUFPLEVBQUUsQ0FBQTtRQU1yQixhQUFRLEdBQUcsRUFBRSxDQUFBO1FBeEJsQixJQUFJLENBQUMsV0FBVyxHQUFHLFdBQVcsQ0FBQztRQUMvQixJQUFJLENBQUMsV0FBVyxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDLENBQUM7SUFDckMsQ0FBQztJQUVELHNCQUFXLHdDQUFPOzs7O1FBQWxCO1lBQ0UsT0FBTyxJQUFJLENBQUMsUUFBUSxDQUFBO1FBQ3RCLENBQUM7Ozs7O1FBRUQsVUFBNEIsT0FBTztZQUFuQyxpQkFRQztZQVBDLElBQUksQ0FBQyxRQUFRLEdBQUcsT0FBTyxDQUFBO1lBQ3ZCLElBQUksSUFBSSxDQUFDLFFBQVEsRUFBRTtnQkFDakIsVUFBVTs7O2dCQUFDO29CQUNULEtBQUksQ0FBQyxjQUFjLEVBQUUsQ0FBQTtvQkFDckIsS0FBSSxDQUFDLFlBQVksRUFBRSxDQUFBO2dCQUNyQixDQUFDLEdBQUUsQ0FBQyxDQUFDLENBQUE7YUFDTjtRQUNILENBQUM7OztPQVZBOzs7Ozs7O0lBb0JNLHdDQUFVOzs7Ozs7SUFBakIsVUFBa0IsSUFBSSxFQUFFLElBQUksRUFBRSxJQUF5QjtRQUNyRCxJQUFJLENBQUMsUUFBUSxDQUFDLE9BQU8sQ0FBQztZQUNwQixJQUFJLE1BQUE7WUFDSixJQUFJLE1BQUE7WUFDSixJQUFJLE1BQUE7WUFDSixJQUFJLEVBQUUsSUFBSSxJQUFJLEVBQUUsQ0FBQyxPQUFPLEVBQUU7U0FDM0IsQ0FBQyxDQUFBO1FBQ0YsSUFBSSxDQUFDLGNBQWMsRUFBRSxDQUFBO0lBQ3ZCLENBQUM7Ozs7SUFFTSw0Q0FBYzs7O0lBQXJCO1FBQ0UsSUFBSSxJQUFJLENBQUMsTUFBTSxLQUFLLFNBQVMsRUFBRTtZQUM3QixJQUFJLENBQUMsTUFBTSxDQUFDLGFBQWEsQ0FBQyxjQUFjLEVBQUUsQ0FBQTtTQUMzQztJQUNILENBQUM7Ozs7SUFFTSwwQ0FBWTs7O0lBQW5CO1FBQ0UsSUFBSSxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUE7SUFDdkIsQ0FBQzs7OztJQUVELHNDQUFROzs7SUFBUjtRQUFBLGlCQXVCQztRQXRCQyxJQUFJLENBQUMsTUFBTSxHQUFHO1lBQ1osSUFBSSxFQUFFLFlBQVk7WUFDbEIsTUFBTSxFQUFFLFFBQVE7WUFDaEIsTUFBTSxFQUFFLElBQUksQ0FBQyxVQUFVO1NBQ3hCLENBQUM7UUFFRixJQUFJLENBQUMsUUFBUSxHQUFJO1lBQ2YsSUFBSSxFQUFFLElBQUksQ0FBQyxPQUFPO1lBQ2xCLE1BQU0sRUFBRSxRQUFRO1lBQ2hCLE1BQU0sRUFBRSxJQUFJLENBQUMsU0FBUztTQUN2QixDQUFDO1FBQ0YsSUFBRyxJQUFJLENBQUMsTUFBTSxFQUFDO1lBQ2IsVUFBVTs7O1lBQUMsY0FBTSxPQUFBLEtBQUksQ0FBQyxPQUFPLEdBQUcsSUFBSSxFQUFuQixDQUFtQixHQUFFLElBQUksQ0FBQyxDQUFBO1NBQzVDO1FBQ0QsVUFBVTs7O1FBQUM7WUFDVCxLQUFJLENBQUMsVUFBVSxDQUFDLEtBQUksQ0FBQyxRQUFRLEVBQUUsS0FBSSxDQUFDLGVBQWUsRUFBRSxVQUFVLENBQUMsQ0FBQTtRQUNsRSxDQUFDLEdBQUUsSUFBSSxDQUFDLENBQUE7UUFDUixJQUFJLENBQUMsV0FBVzthQUNiLFdBQVcsRUFBRTthQUNiLFNBQVM7Ozs7UUFBQyxVQUFDLE9BQU87WUFDakIsVUFBVTs7O1lBQUMsY0FBTSxLQUFJLENBQUMsVUFBVSxDQUFDLEtBQUksQ0FBQyxRQUFRLEVBQUUsT0FBTyxDQUFDLElBQUksRUFBRSxVQUFVLENBQUMsQ0FBQSxDQUFBLENBQUMsR0FBQyxJQUFJLENBQUMsQ0FBQztRQUNuRixDQUFDLEVBQUMsQ0FBQztJQUNQLENBQUM7Ozs7SUFFTSx3Q0FBVTs7O0lBQWpCO1FBQ0UsSUFBSSxDQUFDLE9BQU8sR0FBRyxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUE7SUFDOUIsQ0FBQzs7Ozs7SUFFTSx5Q0FBVzs7OztJQUFsQixVQUFtQixFQUFXO1lBQVQsb0JBQU87UUFDMUIsSUFBSSxPQUFPLENBQUMsSUFBSSxFQUFFLEtBQUssRUFBRSxFQUFFO1lBQ3pCLE9BQU07U0FDUDtRQUNELElBQUksQ0FBQyxVQUFVLENBQUMsSUFBSSxDQUFDLE1BQU0sRUFBRSxPQUFPLEVBQUUsTUFBTSxDQUFDLENBQUE7UUFDN0MsSUFBSSxDQUFDLFdBQVcsQ0FBQyxXQUFXLENBQUMsT0FBTyxDQUFDLENBQUE7SUFDdkMsQ0FBQzs7Ozs7SUFHRCxpREFBbUI7Ozs7SUFEbkIsVUFDb0IsS0FBb0I7UUFDdEMsSUFBSSxLQUFLLENBQUMsR0FBRyxLQUFLLEdBQUcsRUFBRTtZQUNyQixJQUFJLENBQUMsWUFBWSxFQUFFLENBQUE7U0FDcEI7UUFDRCxJQUFJLEtBQUssQ0FBQyxHQUFHLEtBQUssR0FBRyxJQUFJLENBQUMsSUFBSSxDQUFDLFFBQVEsRUFBRTtZQUN2QyxJQUFJLENBQUMsVUFBVSxFQUFFLENBQUE7U0FDbEI7SUFDSCxDQUFDOztnQkFoSEYsU0FBUyxTQUFDO29CQUNULFFBQVEsRUFBRSxhQUFhO29CQUN2Qix1cERBQTJDO29CQUUzQyxVQUFVLEVBQUUsQ0FBQyxTQUFTLEVBQUUsTUFBTSxDQUFDOztpQkFDaEM7Ozs7Z0JBVFEsV0FBVzs7O3lCQVdqQixTQUFTLFNBQUMsUUFBUTt3QkFDbEIsS0FBSzswQkFDTCxLQUFLOzRCQUNMLEtBQUs7NkJBQ0wsS0FBSztzQkFDTCxLQUFLO2tDQUNMLEtBQUs7eUJBQ0wsS0FBSzswQkFlTCxLQUFLO3NDQTJFTCxZQUFZLFNBQUMsbUJBQW1CLEVBQUUsQ0FBQyxRQUFRLENBQUM7O0lBVS9DLDBCQUFDO0NBQUEsQUFsSEQsSUFrSEM7U0E1R1ksbUJBQW1COzs7SUFDOUIscUNBQXVDOztJQUN2QyxvQ0FBdUQ7O0lBQ3ZELHNDQUF3Qzs7SUFDeEMsd0NBQTRHOztJQUM1Ryx5Q0FBNEc7O0lBQzVHLGtDQUFxRDs7SUFDckQsOENBQW9FOztJQUNwRSxxQ0FBc0M7O0lBRXRDLHVDQUF1Qjs7Ozs7SUFFdkIsMENBQWlDOztJQXFCakMsb0NBQTRCOztJQUU1Qix1Q0FBZ0I7O0lBRWhCLHFDQUFjOztJQUVkLHVDQUFvQiIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IENvbXBvbmVudCwgRWxlbWVudFJlZiwgSG9zdExpc3RlbmVyLCBJbnB1dCwgT25Jbml0LCBWaWV3Q2hpbGQgfSBmcm9tICdAYW5ndWxhci9jb3JlJ1xuaW1wb3J0IHsgU3ViamVjdCB9IGZyb20gJ3J4anMnXG5pbXBvcnQgeyBmYWRlSW4sIGZhZGVJbk91dCB9IGZyb20gJy4uL2FuaW1hdGlvbnMnXG5pbXBvcnQgeyBDaGF0U2VydmljZSB9IGZyb20gJy4uL2NoYXRib3QtcmFzYS5zZXJ2aWNlJztcblxuY29uc3QgcmFuZCA9IG1heCA9PiBNYXRoLmZsb29yKE1hdGgucmFuZG9tKCkgKiBtYXgpXG5cbkBDb21wb25lbnQoe1xuICBzZWxlY3RvcjogJ2NoYXQtd2lkZ2V0JyxcbiAgdGVtcGxhdGVVcmw6ICcuL2NoYXQtd2lkZ2V0LmNvbXBvbmVudC5odG1sJyxcbiAgc3R5bGVVcmxzOiBbJy4vY2hhdC13aWRnZXQuY29tcG9uZW50LmNzcyddLFxuICBhbmltYXRpb25zOiBbZmFkZUluT3V0LCBmYWRlSW5dLFxufSlcbmV4cG9ydCBjbGFzcyBDaGF0V2lkZ2V0Q29tcG9uZW50IGltcGxlbWVudHMgT25Jbml0IHtcbiAgQFZpZXdDaGlsZCgnYm90dG9tJykgYm90dG9tOiBFbGVtZW50UmVmXG4gIEBJbnB1dCgpIHB1YmxpYyB0aGVtZTogJ2JsdWUnIHwgJ2dyZXknIHwgJ3JlZCcgPSAnYmx1ZSdcbiAgQElucHV0KCkgcHVibGljIGJvdE5hbWU6IHN0cmluZyA9ICdCb3QnO1xuICBASW5wdXQoKSBwdWJsaWMgYm90QXZhdGFyOiBzdHJpbmcgPSBgaHR0cHM6Ly9jZG4uZHJpYmJibGUuY29tL3VzZXJzLzI3NTc5NC9zY3JlZW5zaG90cy8zMTI4NTk4L2dib3RfODAwLnBuZ2BcbiAgQElucHV0KCkgcHVibGljIHVzZXJBdmF0YXI6IHN0cmluZyA9IGBodHRwczovL3N0b3JhZ2UucHJvYm9hcmRzLmNvbS82MTcyMTkyL2ltYWdlcy9nS2hYRndfNVcwU0Q0bnd1TWV2MS5wbmdgXG4gIEBJbnB1dCgpIHB1YmxpYyB1cmw6IHN0cmluZyA9ICdodHRwOi8vbG9jYWxob3N0OjUwMDInXG4gIEBJbnB1dCgpIHB1YmxpYyBzdGFydGluZ01lc3NhZ2U6IHN0cmluZyA9ICdIaSwgaG93IGNhbiB3ZSBoZWxwIHlvdT8nXG4gIEBJbnB1dCgpIHB1YmxpYyBvcGVuZWQ6IGJvb2xlYW4gPSB0cnVlXG5cbiAgcHVibGljIF92aXNpYmxlID0gZmFsc2VcblxuICBwcml2YXRlIGNoYXRTZXJ2aWNlOiBDaGF0U2VydmljZTtcblxuICBjb25zdHJ1Y3RvcihjaGF0U2VydmljZTogQ2hhdFNlcnZpY2UpIHtcbiAgICB0aGlzLmNoYXRTZXJ2aWNlID0gY2hhdFNlcnZpY2U7XG4gICAgdGhpcy5jaGF0U2VydmljZS5jb25uZWN0KHRoaXMudXJsKTtcbiAgfVxuXG4gIHB1YmxpYyBnZXQgdmlzaWJsZSgpIHtcbiAgICByZXR1cm4gdGhpcy5fdmlzaWJsZVxuICB9XG5cbiAgQElucHV0KCkgcHVibGljIHNldCB2aXNpYmxlKHZpc2libGUpIHtcbiAgICB0aGlzLl92aXNpYmxlID0gdmlzaWJsZVxuICAgIGlmICh0aGlzLl92aXNpYmxlKSB7XG4gICAgICBzZXRUaW1lb3V0KCgpID0+IHtcbiAgICAgICAgdGhpcy5zY3JvbGxUb0JvdHRvbSgpXG4gICAgICAgIHRoaXMuZm9jdXNNZXNzYWdlKClcbiAgICAgIH0sIDApXG4gICAgfVxuICB9XG5cbiAgcHVibGljIGZvY3VzID0gbmV3IFN1YmplY3QoKVxuXG4gIHB1YmxpYyBvcGVyYXRvcjtcblxuICBwdWJsaWMgY2xpZW50O1xuXG4gIHB1YmxpYyBtZXNzYWdlcyA9IFtdXG5cbiAgcHVibGljIGFkZE1lc3NhZ2UoZnJvbSwgdGV4dCwgdHlwZTogJ3JlY2VpdmVkJyB8ICdzZW50Jykge1xuICAgIHRoaXMubWVzc2FnZXMudW5zaGlmdCh7XG4gICAgICBmcm9tLFxuICAgICAgdGV4dCxcbiAgICAgIHR5cGUsXG4gICAgICBkYXRlOiBuZXcgRGF0ZSgpLmdldFRpbWUoKSxcbiAgICB9KVxuICAgIHRoaXMuc2Nyb2xsVG9Cb3R0b20oKVxuICB9XG5cbiAgcHVibGljIHNjcm9sbFRvQm90dG9tKCkge1xuICAgIGlmICh0aGlzLmJvdHRvbSAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICB0aGlzLmJvdHRvbS5uYXRpdmVFbGVtZW50LnNjcm9sbEludG9WaWV3KClcbiAgICB9XG4gIH1cblxuICBwdWJsaWMgZm9jdXNNZXNzYWdlKCkge1xuICAgIHRoaXMuZm9jdXMubmV4dCh0cnVlKVxuICB9XG5cbiAgbmdPbkluaXQoKSB7XG4gICAgdGhpcy5jbGllbnQgPSB7XG4gICAgICBuYW1lOiAnR3Vlc3QgVXNlcicsXG4gICAgICBzdGF0dXM6ICdvbmxpbmUnLFxuICAgICAgYXZhdGFyOiB0aGlzLnVzZXJBdmF0YXIsXG4gICAgfTtcblxuICAgIHRoaXMub3BlcmF0b3IgID0ge1xuICAgICAgbmFtZTogdGhpcy5ib3ROYW1lLFxuICAgICAgc3RhdHVzOiAnb25saW5lJyxcbiAgICAgIGF2YXRhcjogdGhpcy5ib3RBdmF0YXIsXG4gICAgfTtcbiAgICBpZih0aGlzLm9wZW5lZCl7XG4gICAgICBzZXRUaW1lb3V0KCgpID0+IHRoaXMudmlzaWJsZSA9IHRydWUsIDEwMDApXG4gICAgfVxuICAgIHNldFRpbWVvdXQoKCkgPT4ge1xuICAgICAgdGhpcy5hZGRNZXNzYWdlKHRoaXMub3BlcmF0b3IsIHRoaXMuc3RhcnRpbmdNZXNzYWdlLCAncmVjZWl2ZWQnKVxuICAgIH0sIDE1MDApXG4gICAgdGhpcy5jaGF0U2VydmljZVxuICAgICAgLmdldE1lc3NhZ2VzKClcbiAgICAgIC5zdWJzY3JpYmUoKG1lc3NhZ2UpID0+IHtcbiAgICAgICAgc2V0VGltZW91dCgoKT0+IHt0aGlzLmFkZE1lc3NhZ2UodGhpcy5vcGVyYXRvciwgbWVzc2FnZS50ZXh0LCAncmVjZWl2ZWQnKX0sMTAwMCk7XG4gICAgICB9KTtcbiAgfVxuXG4gIHB1YmxpYyB0b2dnbGVDaGF0KCkge1xuICAgIHRoaXMudmlzaWJsZSA9ICF0aGlzLnZpc2libGVcbiAgfVxuXG4gIHB1YmxpYyBzZW5kTWVzc2FnZSh7IG1lc3NhZ2UgfSkge1xuICAgIGlmIChtZXNzYWdlLnRyaW0oKSA9PT0gJycpIHtcbiAgICAgIHJldHVyblxuICAgIH1cbiAgICB0aGlzLmFkZE1lc3NhZ2UodGhpcy5jbGllbnQsIG1lc3NhZ2UsICdzZW50JylcbiAgICB0aGlzLmNoYXRTZXJ2aWNlLnNlbmRNZXNzYWdlKG1lc3NhZ2UpXG4gIH1cblxuICBASG9zdExpc3RlbmVyKCdkb2N1bWVudDprZXlwcmVzcycsIFsnJGV2ZW50J10pXG4gIGhhbmRsZUtleWJvYXJkRXZlbnQoZXZlbnQ6IEtleWJvYXJkRXZlbnQpIHtcbiAgICBpZiAoZXZlbnQua2V5ID09PSAnLycpIHtcbiAgICAgIHRoaXMuZm9jdXNNZXNzYWdlKClcbiAgICB9XG4gICAgaWYgKGV2ZW50LmtleSA9PT0gJz8nICYmICF0aGlzLl92aXNpYmxlKSB7XG4gICAgICB0aGlzLnRvZ2dsZUNoYXQoKVxuICAgIH1cbiAgfVxuXG59XG4iXX0=