@pazznetwork/ngx-chat
Version:
[](https://travis-ci.com/pazznetwork/ngx-chat) [](https://coveralls.io/github/pazzn
185 lines • 31 kB
JavaScript
import { Injectable } from '@angular/core';
import { jid as parseJid } from '@xmpp/client';
import { BehaviorSubject, combineLatest, merge, Subject } from 'rxjs';
import { filter, map } from 'rxjs/operators';
import { dummyAvatarContact } from '../../../core/contact-avatar';
import { defaultTranslations } from '../../../core/translations-default';
import { MessageArchivePlugin } from './plugins/message-archive.plugin';
import { MessagePlugin } from './plugins/message.plugin';
import { MultiUserChatPlugin } from './plugins/multi-user-chat/multi-user-chat.plugin';
import { RosterPlugin } from './plugins/roster.plugin';
import * as i0 from "@angular/core";
import * as i1 from "./xmpp-chat-connection.service";
import * as i2 from "../../log.service";
import * as i3 from "../../contact-factory.service";
export class XmppChatAdapter {
constructor(chatConnectionService, logService, contactFactory) {
this.chatConnectionService = chatConnectionService;
this.logService = logService;
this.contactFactory = contactFactory;
this.message$ = new Subject();
this.messageSent$ = new Subject();
this.contacts$ = new BehaviorSubject([]);
this.contactCreated$ = new Subject();
this.blockedContactIds$ = new BehaviorSubject(new Set());
this.blockedContacts$ = combineLatest([this.contacts$, this.blockedContactIds$])
.pipe(map(([contacts, blockedJids]) => contacts.filter(contact => blockedJids.has(contact.jidBare.toString()))));
this.notBlockedContacts$ = combineLatest([this.contacts$, this.blockedContactIds$])
.pipe(map(([contacts, blockedJids]) => contacts.filter(contact => !blockedJids.has(contact.jidBare.toString()))));
this.contactsSubscribed$ = this.notBlockedContacts$.pipe(map(contacts => contacts.filter(contact => contact.isSubscribed())));
this.contactRequestsReceived$ = this.notBlockedContacts$.pipe(map(contacts => contacts.filter(contact => contact.pendingIn$.getValue())));
this.contactRequestsSent$ = this.notBlockedContacts$.pipe(map(contacts => contacts.filter(contact => contact.pendingOut$.getValue())));
this.contactsUnaffiliated$ = this.notBlockedContacts$.pipe(map(contacts => contacts.filter(contact => contact.isUnaffiliated() && contact.messages.length > 0)));
this.state$ = new BehaviorSubject('disconnected');
this.plugins = [];
this.enableDebugging = false;
this.userAvatar$ = new BehaviorSubject(dummyAvatarContact);
this.translations = defaultTranslations();
this.chatActions = [{
id: 'sendMessage',
cssClass: 'chat-window-send',
html: '»',
onClick: (chatActionContext) => {
chatActionContext.chatWindow.sendMessage();
},
}];
this.state$.subscribe((state) => this.logService.info('state changed to:', state));
chatConnectionService.state$
.pipe(filter(nextState => nextState !== this.state$.getValue()))
.subscribe((nextState) => {
this.handleInternalStateChange(nextState);
});
this.chatConnectionService.stanzaUnknown$.subscribe((stanza) => this.onUnknownStanza(stanza));
merge(this.messageSent$, this.message$).subscribe(() => {
// re-emit contacts when sending or receiving a message to refresh contact groups
// if the sending contact was in 'other', he still is in other now, but passes the 'messages.length > 0' predicate, so that
// he should be seen now.
this.contacts$.next(this.contacts$.getValue());
});
}
handleInternalStateChange(newState) {
if (newState === 'online') {
this.state$.next('connecting');
Promise
.all(this.plugins.map(plugin => plugin.onBeforeOnline()))
.catch((e) => this.logService.error('error while connecting', e))
.finally(() => this.announceAvailability());
}
else {
if (this.state$.getValue() === 'online') {
// clear data the first time we transition to a not-online state
this.onOffline();
}
this.state$.next('disconnected');
}
}
onOffline() {
this.contacts$.next([]);
this.plugins.forEach(plugin => {
try {
plugin.onOffline();
}
catch (e) {
this.logService.error('error while handling offline in ', plugin);
}
});
}
announceAvailability() {
this.logService.info('announcing availability');
this.chatConnectionService.sendPresence();
this.state$.next('online');
}
addPlugins(plugins) {
plugins.forEach(plugin => {
this.plugins.push(plugin);
});
}
reloadContacts() {
this.getPlugin(RosterPlugin).refreshRosterContacts();
}
getContactById(jidPlain) {
const bareJidToFind = parseJid(jidPlain).bare();
return this.contacts$.getValue().find(contact => contact.jidBare.equals(bareJidToFind));
}
getOrCreateContactById(jidPlain, name) {
let contact = this.getContactById(jidPlain);
if (!contact) {
contact = this.contactFactory.createContact(parseJid(jidPlain).bare().toString(), name);
this.contacts$.next([contact, ...this.contacts$.getValue()]);
this.contactCreated$.next(contact);
}
return contact;
}
addContact(identifier) {
this.getPlugin(RosterPlugin).addRosterContact(identifier);
}
removeContact(identifier) {
this.getPlugin(RosterPlugin).removeRosterContact(identifier);
}
async logIn(logInRequest) {
this.lastLogInRequest = logInRequest;
if (this.state$.getValue() === 'disconnected') {
await this.chatConnectionService.logIn(logInRequest);
}
}
logOut() {
return this.chatConnectionService.logOut();
}
async sendMessage(recipient, body) {
const trimmedBody = body.trim();
if (trimmedBody.length === 0) {
return;
}
switch (recipient.recipientType) {
case 'room':
await this.getPlugin(MultiUserChatPlugin).sendMessage(recipient, trimmedBody);
break;
case 'contact':
this.getPlugin(MessagePlugin).sendMessage(recipient, trimmedBody);
this.messageSent$.next(recipient);
break;
default:
throw new Error('invalid recipient type: ' + recipient?.recipientType);
}
}
loadCompleteHistory() {
return this.getPlugin(MessageArchivePlugin).loadAllMessages();
}
getPlugin(constructor) {
for (const plugin of this.plugins) {
if (plugin.constructor === constructor) {
return plugin;
}
}
throw new Error('plugin not found: ' + constructor);
}
onUnknownStanza(stanza) {
let handled = false;
for (const plugin of this.plugins) {
try {
if (plugin.handleStanza(stanza)) {
this.logService.debug(plugin.constructor.name, 'handled', stanza.toString());
handled = true;
}
}
catch (e) {
this.logService.error('error handling stanza in ', plugin.constructor.name, e);
}
}
if (!handled) {
this.logService.warn('unknown stanza <=', stanza.toString());
}
}
reconnectSilently() {
this.chatConnectionService.reconnectSilently();
}
reconnect() {
return this.logIn(this.lastLogInRequest);
}
}
XmppChatAdapter.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: XmppChatAdapter, deps: [{ token: i1.XmppChatConnectionService }, { token: i2.LogService }, { token: i3.ContactFactoryService }], target: i0.ɵɵFactoryTarget.Injectable });
XmppChatAdapter.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: XmppChatAdapter });
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: XmppChatAdapter, decorators: [{
type: Injectable
}], ctorParameters: function () { return [{ type: i1.XmppChatConnectionService }, { type: i2.LogService }, { type: i3.ContactFactoryService }]; } });
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoieG1wcC1jaGF0LWFkYXB0ZXIuc2VydmljZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uLy4uLy4uL3NyYy9saWIvc2VydmljZXMvYWRhcHRlcnMveG1wcC94bXBwLWNoYXQtYWRhcHRlci5zZXJ2aWNlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxVQUFVLEVBQUUsTUFBTSxlQUFlLENBQUM7QUFDM0MsT0FBTyxFQUFFLEdBQUcsSUFBSSxRQUFRLEVBQUUsTUFBTSxjQUFjLENBQUM7QUFDL0MsT0FBTyxFQUFFLGVBQWUsRUFBRSxhQUFhLEVBQUUsS0FBSyxFQUFjLE9BQU8sRUFBRSxNQUFNLE1BQU0sQ0FBQztBQUNsRixPQUFPLEVBQUUsTUFBTSxFQUFFLEdBQUcsRUFBRSxNQUFNLGdCQUFnQixDQUFDO0FBRTdDLE9BQU8sRUFBRSxrQkFBa0IsRUFBRSxNQUFNLDhCQUE4QixDQUFDO0FBTWxFLE9BQU8sRUFBRSxtQkFBbUIsRUFBRSxNQUFNLG9DQUFvQyxDQUFDO0FBSXpFLE9BQU8sRUFBRSxvQkFBb0IsRUFBRSxNQUFNLGtDQUFrQyxDQUFDO0FBQ3hFLE9BQU8sRUFBRSxhQUFhLEVBQUUsTUFBTSwwQkFBMEIsQ0FBQztBQUN6RCxPQUFPLEVBQUUsbUJBQW1CLEVBQUUsTUFBTSxrREFBa0QsQ0FBQztBQUN2RixPQUFPLEVBQUUsWUFBWSxFQUFFLE1BQU0seUJBQXlCLENBQUM7Ozs7O0FBc0J2RCxNQUFNLE9BQU8sZUFBZTtJQWdEeEIsWUFDVyxxQkFBZ0QsRUFDL0MsVUFBc0IsRUFDdEIsY0FBcUM7UUFGdEMsMEJBQXFCLEdBQXJCLHFCQUFxQixDQUEyQjtRQUMvQyxlQUFVLEdBQVYsVUFBVSxDQUFZO1FBQ3RCLG1CQUFjLEdBQWQsY0FBYyxDQUF1QjtRQWpEeEMsYUFBUSxHQUFHLElBQUksT0FBTyxFQUFXLENBQUM7UUFDbEMsaUJBQVksR0FBcUIsSUFBSSxPQUFPLEVBQUUsQ0FBQztRQUUv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LGVBQWU7MkZBQWYsZUFBZTtrQkFEM0IsVUFBVSIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IEluamVjdGFibGUgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IGppZCBhcyBwYXJzZUppZCB9IGZyb20gJ0B4bXBwL2NsaWVudCc7XG5pbXBvcnQgeyBCZWhhdmlvclN1YmplY3QsIGNvbWJpbmVMYXRlc3QsIG1lcmdlLCBPYnNlcnZhYmxlLCBTdWJqZWN0IH0gZnJvbSAncnhqcyc7XG5pbXBvcnQgeyBmaWx0ZXIsIG1hcCB9IGZyb20gJ3J4anMvb3BlcmF0b3JzJztcbmltcG9ydCB7IENvbnRhY3QgfSBmcm9tICcuLi8uLi8uLi9jb3JlL2NvbnRhY3QnO1xuaW1wb3J0IHsgZHVtbXlBdmF0YXJDb250YWN0IH0gZnJvbSAnLi4vLi4vLi4vY29yZS9jb250YWN0LWF2YXRhcic7XG5pbXBvcnQgeyBMb2dJblJlcXVlc3QgfSBmcm9tICcuLi8uLi8uLi9jb3JlL2xvZy1pbi1yZXF1ZXN0JztcbmltcG9ydCB7IENoYXRQbHVnaW4gfSBmcm9tICcuLi8uLi8uLi9jb3JlL3BsdWdpbic7XG5pbXBvcnQgeyBSZWNpcGllbnQgfSBmcm9tICcuLi8uLi8uLi9jb3JlL3JlY2lwaWVudCc7XG5pbXBvcnQgeyBTdGFuemEgfSBmcm9tICcuLi8uLi8uLi9jb3JlL3N0YW56YSc7XG5pbXBvcnQgeyBUcmFuc2xhdGlvbnMgfSBmcm9tICcuLi8uLi8uLi9jb3JlL3RyYW5zbGF0aW9ucyc7XG5pbXBvcnQgeyBkZWZhdWx0VHJhbnNsYXRpb25zIH0gZnJvbSAnLi4vLi4vLi4vY29yZS90cmFuc2xhdGlvbnMtZGVmYXVsdCc7XG5pbXBvcnQgeyBDaGF0U2VydmljZSwgQ29ubmVjdGlvblN0YXRlcyB9IGZyb20gJy4uLy4uL2NoYXQtc2VydmljZSc7XG5pbXBvcnQgeyBDb250YWN0RmFjdG9yeVNlcnZpY2UgfSBmcm9tICcuLi8uLi9jb250YWN0LWZhY3Rvcnkuc2VydmljZSc7XG5pbXBvcnQgeyBMb2dTZXJ2aWNlIH0gZnJvbSAnLi4vLi4vbG9nLnNlcnZpY2UnO1xuaW1wb3J0IHsgTWVzc2FnZUFyY2hpdmVQbHVnaW4gfSBmcm9tICcuL3BsdWdpbnMvbWVzc2FnZS1hcmNoaXZlLnBsdWdpbic7XG5pbXBvcnQgeyBNZXNzYWdlUGx1Z2luIH0gZnJvbSAnLi9wbHVnaW5zL21lc3NhZ2UucGx1Z2luJztcbmltcG9ydCB7IE11bHRpVXNlckNoYXRQbHVnaW4gfSBmcm9tICcuL3BsdWdpbnMvbXVsdGktdXNlci1jaGF0L211bHRpLXVzZXItY2hhdC5wbHVnaW4nO1xuaW1wb3J0IHsgUm9zdGVyUGx1Z2luIH0gZnJvbSAnLi9wbHVnaW5zL3Jvc3Rlci5wbHVnaW4nO1xuaW1wb3J0IHsgWG1wcENoYXRDb25uZWN0aW9uU2VydmljZSwgWG1wcENoYXRTdGF0ZXMgfSBmcm9tICcuL3htcHAtY2hhdC1jb25uZWN0aW9uLnNlcnZpY2UnO1xuXG5cbmV4cG9ydCBpbnRlcmZhY2UgQ2hhdEFjdGlvbjxUQ2hhdFdpbmRvdz4ge1xuICAgIGNzc0NsYXNzOiB7IFtjbGFzc05hbWU6IHN0cmluZ106IGJvb2xlYW4gfSB8IHN0cmluZyB8IHN0cmluZ1tdO1xuICAgIC8qKlxuICAgICAqIHRvIGlkZW50aWZ5IGFjdGlvbnNcbiAgICAgKi9cbiAgICBpZDogc3RyaW5nO1xuICAgIGh0bWw6IHN0cmluZztcblxuICAgIG9uQ2xpY2soY2hhdEFjdGlvbkNvbnRleHQ6IENoYXRBY3Rpb25Db250ZXh0PFRDaGF0V2luZG93Pik6IHZvaWQ7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgQ2hhdEFjdGlvbkNvbnRleHQ8VENoYXRXaW5kb3c+IHtcbiAgICBjb250YWN0OiBzdHJpbmc7XG4gICAgY2hhdFdpbmRvdzogVENoYXRXaW5kb3c7XG59XG5cblxuQEluamVjdGFibGUoKVxuZXhwb3J0IGNsYXNzIFhtcHBDaGF0QWRhcHRlciBpbXBsZW1lbnRzIENoYXRTZXJ2aWNlIHtcblxuICAgIHJlYWRvbmx5IG1lc3NhZ2UkID0gbmV3IFN1YmplY3Q8Q29udGFjdD4oKTtcbiAgICByZWFkb25seSBtZXNzYWdlU2VudCQ6IFN1YmplY3Q8Q29udGFjdD4gPSBuZXcgU3ViamVjdCgpO1xuXG4gICAgcmVhZG9ubHkgY29udGFjdHMkID0gbmV3IEJlaGF2aW9yU3ViamVjdDxDb250YWN0W10+KFtdKTtcbiAgICByZWFkb25seSBjb250YWN0Q3JlYXRlZCQgPSBuZXcgU3ViamVjdDxDb250YWN0PigpO1xuXG4gICAgcmVhZG9ubHkgYmxvY2tlZENvbnRhY3RJZHMkID0gbmV3IEJlaGF2aW9yU3ViamVjdDxTZXQ8c3RyaW5nPj4obmV3IFNldDxzdHJpbmc+KCkpO1xuICAgIHJlYWRvbmx5IGJsb2NrZWRDb250YWN0cyQgPSBjb21iaW5lTGF0ZXN0KFt0aGlzLmNvbnRhY3RzJCwgdGhpcy5ibG9ja2VkQ29udGFjdElkcyRdKVxuICAgICAgICAucGlwZShcbiAgICAgICAgICAgIG1hcChcbiAgICAgICAgICAgICAgICAoW2NvbnRhY3RzLCBibG9ja2VkSmlkc10pID0+XG4gICAgICAgICAgICAgICAgICAgIGNvbnRhY3RzLmZpbHRlcihjb250YWN0ID0+IGJsb2NrZWRKaWRzLmhhcyhjb250YWN0LmppZEJhcmUudG9TdHJpbmcoKSkpLFxuICAgICAgICAgICAgKSxcbiAgICAgICAgKTtcbiAgICByZWFkb25seSBub3RCbG9ja2VkQ29udGFjdHMkID0gY29tYmluZUxhdGVzdChbdGhpcy5jb250YWN0cyQsIHRoaXMuYmxvY2tlZENvbnRhY3RJZHMkXSlcbiAgICAgICAgLnBpcGUoXG4gICAgICAgICAgICBtYXAoXG4gICAgICAgICAgICAgICAgKFtjb250YWN0cywgYmxvY2tlZEppZHNdKSA9PlxuICAgICAgICAgICAgICAgICAgICBjb250YWN0cy5maWx0ZXIoY29udGFjdCA9PiAhYmxvY2tlZEppZHMuaGFzKGNvbnRhY3QuamlkQmFyZS50b1N0cmluZygpKSksXG4gICAgICAgICAgICApLFxuICAgICAgICApO1xuICAgIHJlYWRvbmx5IGNvbnRhY3RzU3Vic2NyaWJlZCQ6IE9ic2VydmFibGU8Q29udGFjdFtdPiA9IHRoaXMubm90QmxvY2tlZENvbnRhY3RzJC5waXBlKFxuICAgICAgICBtYXAoY29udGFjdHMgPT4gY29udGFjdHMuZmlsdGVyKGNvbnRhY3QgPT4gY29udGFjdC5pc1N1YnNjcmliZWQoKSkpKTtcbiAgICByZWFkb25seSBjb250YWN0UmVxdWVzdHNSZWNlaXZlZCQ6IE9ic2VydmFibGU8Q29udGFjdFtdPiA9IHRoaXMubm90QmxvY2tlZENvbnRhY3RzJC5waXBlKFxuICAgICAgICBtYXAoY29udGFjdHMgPT4gY29udGFjdHMuZmlsdGVyKGNvbnRhY3QgPT4gY29udGFjdC5wZW5kaW5nSW4kLmdldFZhbHVlKCkpKSk7XG4gICAgcmVhZG9ubHkgY29udGFjdFJlcXVlc3RzU2VudCQ6IE9ic2VydmFibGU8Q29udGFjdFtdPiA9IHRoaXMubm90QmxvY2tlZENvbnRhY3RzJC5waXBlKFxuICAgICAgICBtYXAoY29udGFjdHMgPT4gY29udGFjdHMuZmlsdGVyKGNvbnRhY3QgPT4gY29udGFjdC5wZW5kaW5nT3V0JC5nZXRWYWx1ZSgpKSkpO1xuICAgIHJlYWRvbmx5IGNvbnRhY3RzVW5hZmZpbGlhdGVkJDogT2JzZXJ2YWJsZTxDb250YWN0W10+ID0gdGhpcy5ub3RCbG9ja2VkQ29udGFjdHMkLnBpcGUoXG4gICAgICAgIG1hcChjb250YWN0cyA9PiBjb250YWN0cy5maWx0ZXIoY29udGFjdCA9PiBjb250YWN0LmlzVW5hZmZpbGlhdGVkKCkgJiYgY29udGFjdC5tZXNzYWdlcy5sZW5ndGggPiAwKSkpO1xuICAgIHJlYWRvbmx5IHN0YXRlJCA9IG5ldyBCZWhhdmlvclN1YmplY3Q8Q29ubmVjdGlvblN0YXRlcz4oJ2Rpc2Nvbm5lY3RlZCcpO1xuICAgIHJlYWRvbmx5IHBsdWdpbnM6IENoYXRQbHVnaW5bXSA9IFtdO1xuICAgIGVuYWJsZURlYnVnZ2luZyA9IGZhbHNlO1xuICAgIHJlYWRvbmx5IHVzZXJBdmF0YXIkID0gbmV3IEJlaGF2aW9yU3ViamVjdChkdW1teUF2YXRhckNvbnRhY3QpO1xuICAgIHRyYW5zbGF0aW9uczogVHJhbnNsYXRpb25zID0gZGVmYXVsdFRyYW5zbGF0aW9ucygpO1xuXG4gICAgY2hhdEFjdGlvbnMgPSBbe1xuICAgICAgICBpZDogJ3NlbmRNZXNzYWdlJyxcbiAgICAgICAgY3NzQ2xhc3M6ICdjaGF0LXdpbmRvdy1zZW5kJyxcbiAgICAgICAgaHRtbDogJyZyYXF1bzsnLFxuICAgICAgICBvbkNsaWNrOiAoY2hhdEFjdGlvbkNvbnRleHQ6IENoYXRBY3Rpb25Db250ZXh0PHsgc2VuZE1lc3NhZ2U6ICgpID0+IHZvaWQgfT4pID0+IHtcbiAgICAgICAgICAgIGNoYXRBY3Rpb25Db250ZXh0LmNoYXRXaW5kb3cuc2VuZE1lc3NhZ2UoKTtcbiAgICAgICAgfSxcbiAgICB9XTtcblxuICAgIHByaXZhdGUgbGFzdExvZ0luUmVxdWVzdDogTG9nSW5SZXF1ZXN0O1xuXG4gICAgY29uc3RydWN0b3IoXG4gICAgICAgIHB1YmxpYyBjaGF0Q29ubmVjdGlvblNlcnZpY2U6IFhtcHBDaGF0Q29ubmVjdGlvblNlcnZpY2UsXG4gICAgICAgIHByaXZhdGUgbG9nU2VydmljZTogTG9nU2VydmljZSxcbiAgICAgICAgcHJpdmF0ZSBjb250YWN0RmFjdG9yeTogQ29udGFjdEZhY3RvcnlTZXJ2aWNlLFxuICAgICkge1xuICAgICAgICB0aGlzLnN0YXRlJC5zdWJzY3JpYmUoKHN0YXRlKSA9PiB0aGlzLmxvZ1NlcnZpY2UuaW5mbygnc3RhdGUgY2hhbmdlZCB0bzonLCBzdGF0ZSkpO1xuICAgICAgICBjaGF0Q29ubmVjdGlvblNlcnZpY2Uuc3RhdGUkXG4gICAgICAgICAgICAucGlwZShmaWx0ZXIobmV4dFN0YXRlID0+IG5leHRTdGF0ZSAhPT0gdGhpcy5zdGF0ZSQuZ2V0VmFsdWUoKSkpXG4gICAgICAgICAgICAuc3Vic2NyaWJlKChuZXh0U3RhdGUpID0+IHtcbiAgICAgICAgICAgICAgICB0aGlzLmhhbmRsZUludGVybmFsU3RhdGVDaGFuZ2UobmV4dFN0YXRlKTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB0aGlzLmNoYXRDb25uZWN0aW9uU2VydmljZS5zdGFuemFVbmtub3duJC5zdWJzY3JpYmUoKHN0YW56YSkgPT4gdGhpcy5vblVua25vd25TdGFuemEoc3RhbnphKSk7XG5cbiAgICAgICAgbWVyZ2UodGhpcy5tZXNzYWdlU2VudCQsIHRoaXMubWVzc2FnZSQpLnN1YnNjcmliZSgoKSA9PiB7XG4gICAgICAgICAgICAvLyByZS1lbWl0IGNvbnRhY3RzIHdoZW4gc2VuZGluZyBvciByZWNlaXZpbmcgYSBtZXNzYWdlIHRvIHJlZnJlc2ggY29udGFjdCBncm91cHNcbiAgICAgICAgICAgIC8vIGlmIHRoZSBzZW5kaW5nIGNvbnRhY3Qgd2FzIGluICdvdGhlcicsIGhlIHN0aWxsIGlzIGluIG90aGVyIG5vdywgYnV0IHBhc3NlcyB0aGUgJ21lc3NhZ2VzLmxlbmd0aCA+IDAnIHByZWRpY2F0ZSwgc28gdGhhdFxuICAgICAgICAgICAgLy8gaGUgc2hvdWxkIGJlIHNlZW4gbm93LlxuICAgICAgICAgICAgdGhpcy5jb250YWN0cyQubmV4dCh0aGlzLmNvbnRhY3RzJC5nZXRWYWx1ZSgpKTtcbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBoYW5kbGVJbnRlcm5hbFN0YXRlQ2hhbmdlKG5ld1N0YXRlOiBYbXBwQ2hhdFN0YXRlcykge1xuICAgICAgICBpZiAobmV3U3RhdGUgPT09ICdvbmxpbmUnKSB7XG4gICAgICAgICAgICB0aGlzLnN0YXRlJC5uZXh0KCdjb25uZWN0aW5nJyk7XG4gICAgICAgICAgICBQcm9taXNlXG4gICAgICAgICAgICAgICAgLmFsbCh0aGlzLnBsdWdpbnMubWFwKHBsdWdpbiA9PiBwbHVnaW4ub25CZWZvcmVPbmxpbmUoKSkpXG4gICAgICAgICAgICAgICAgLmNhdGNoKChlKSA9PiB0aGlzLmxvZ1NlcnZpY2UuZXJyb3IoJ2Vycm9yIHdoaWxlIGNvbm5lY3RpbmcnLCBlKSlcbiAgICAgICAgICAgICAgICAuZmluYWxseSgoKSA9PiB0aGlzLmFubm91bmNlQXZhaWxhYmlsaXR5KCkpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgaWYgKHRoaXMuc3RhdGUkLmdldFZhbHVlKCkgPT09ICdvbmxpbmUnKSB7XG4gICAgICAgICAgICAgICAgLy8gY2xlYXIgZGF0YSB0aGUgZmlyc3QgdGltZSB3ZSB0cmFuc2l0aW9uIHRvIGEgbm90LW9ubGluZSBzdGF0ZVxuICAgICAgICAgICAgICAgIHRoaXMub25PZmZsaW5lKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aGlzLnN0YXRlJC5uZXh0KCdkaXNjb25uZWN0ZWQnKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHByaXZhdGUgb25PZmZsaW5lKCkge1xuICAgICAgICB0aGlzLmNvbnRhY3RzJC5uZXh0KFtdKTtcbiAgICAgICAgdGhpcy5wbHVnaW5zLmZvckVhY2gocGx1Z2luID0+IHtcbiAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgcGx1Z2luLm9uT2ZmbGluZSgpO1xuICAgICAgICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICAgICAgICAgIHRoaXMubG9nU2VydmljZS5lcnJvcignZXJyb3Igd2hpbGUgaGFuZGxpbmcgb2ZmbGluZSBpbiAnLCBwbHVnaW4pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICBwcml2YXRlIGFubm91bmNlQXZhaWxhYmlsaXR5KCkge1xuICAgICAgICB0aGlzLmxvZ1NlcnZpY2UuaW5mbygnYW5ub3VuY2luZyBhdmFpbGFiaWxpdHknKTtcbiAgICAgICAgdGhpcy5jaGF0Q29ubmVjdGlvblNlcnZpY2Uuc2VuZFByZXNlbmNlKCk7XG4gICAgICAgIHRoaXMuc3RhdGUkLm5leHQoJ29ubGluZScpO1xuICAgIH1cblxuICAgIGFkZFBsdWdpbnMocGx1Z2luczogQ2hhdFBsdWdpbltdKSB7XG4gICAgICAgIHBsdWdpbnMuZm9yRWFjaChwbHVnaW4gPT4ge1xuICAgICAgICAgICAgdGhpcy5wbHVnaW5zLnB1c2gocGx1Z2luKTtcbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgcmVsb2FkQ29udGFjdHMoKTogdm9pZCB7XG4gICAgICAgIHRoaXMuZ2V0UGx1Z2luKFJvc3RlclBsdWdpbikucmVmcmVzaFJvc3RlckNvbnRhY3RzKCk7XG4gICAgfVxuXG4gICAgZ2V0Q29udGFjdEJ5SWQoamlkUGxhaW46IHN0cmluZykge1xuICAgICAgICBjb25zdCBiYXJlSmlkVG9GaW5kID0gcGFyc2VKaWQoamlkUGxhaW4pLmJhcmUoKTtcbiAgICAgICAgcmV0dXJuIHRoaXMuY29udGFjdHMkLmdldFZhbHVlKCkuZmluZChjb250YWN0ID0+IGNvbnRhY3QuamlkQmFyZS5lcXVhbHMoYmFyZUppZFRvRmluZCkpO1xuICAgIH1cblxuICAgIGdldE9yQ3JlYXRlQ29udGFjdEJ5SWQoamlkUGxhaW46IHN0cmluZywgbmFtZT86IHN0cmluZykge1xuICAgICAgICBsZXQgY29udGFjdCA9IHRoaXMuZ2V0Q29udGFjdEJ5SWQoamlkUGxhaW4pO1xuICAgICAgICBpZiAoIWNvbnRhY3QpIHtcbiAgICAgICAgICAgIGNvbnRhY3QgPSB0aGlzLmNvbnRhY3RGYWN0b3J5LmNyZWF0ZUNvbnRhY3QocGFyc2VKaWQoamlkUGxhaW4pLmJhcmUoKS50b1N0cmluZygpLCBuYW1lKTtcbiAgICAgICAgICAgIHRoaXMuY29udGFjdHMkLm5leHQoW2NvbnRhY3QsIC4uLnRoaXMuY29udGFjdHMkLmdldFZhbHVlKCldKTtcbiAgICAgICAgICAgIHRoaXMuY29udGFjdENyZWF0ZWQkLm5leHQoY29udGFjdCk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGNvbnRhY3Q7XG4gICAgfVxuXG4gICAgYWRkQ29udGFjdChpZGVudGlmaWVyOiBzdHJpbmcpIHtcbiAgICAgICAgdGhpcy5nZXRQbHVnaW4oUm9zdGVyUGx1Z2luKS5hZGRSb3N0ZXJDb250YWN0KGlkZW50aWZpZXIpO1xuICAgIH1cblxuICAgIHJlbW92ZUNvbnRhY3QoaWRlbnRpZmllcjogc3RyaW5nKSB7XG4gICAgICAgIHRoaXMuZ2V0UGx1Z2luKFJvc3RlclBsdWdpbikucmVtb3ZlUm9zdGVyQ29udGFjdChpZGVudGlmaWVyKTtcbiAgICB9XG5cbiAgICBhc3luYyBsb2dJbihsb2dJblJlcXVlc3Q6IExvZ0luUmVxdWVzdCkge1xuICAgICAgICB0aGlzLmxhc3RMb2dJblJlcXVlc3QgPSBsb2dJblJlcXVlc3Q7XG4gICAgICAgIGlmICh0aGlzLnN0YXRlJC5nZXRWYWx1ZSgpID09PSAnZGlzY29ubmVjdGVkJykge1xuICAgICAgICAgICAgYXdhaXQgdGhpcy5jaGF0Q29ubmVjdGlvblNlcnZpY2UubG9nSW4obG9nSW5SZXF1ZXN0KTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIGxvZ091dCgpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICAgICAgcmV0dXJuIHRoaXMuY2hhdENvbm5lY3Rpb25TZXJ2aWNlLmxvZ091dCgpO1xuICAgIH1cblxuICAgIGFzeW5jIHNlbmRNZXNzYWdlKHJlY2lwaWVudDogUmVjaXBpZW50LCBib2R5OiBzdHJpbmcpIHtcbiAgICAgICAgY29uc3QgdHJpbW1lZEJvZHkgPSBib2R5LnRyaW0oKTtcbiAgICAgICAgaWYgKHRyaW1tZWRCb2R5Lmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIHN3aXRjaCAocmVjaXBpZW50LnJlY2lwaWVudFR5cGUpIHtcbiAgICAgICAgICAgIGNhc2UgJ3Jvb20nOlxuICAgICAgICAgICAgICAgIGF3YWl0IHRoaXMuZ2V0UGx1Z2luKE11bHRpVXNlckNoYXRQbHVnaW4pLnNlbmRNZXNzYWdlKHJlY2lwaWVudCwgdHJpbW1lZEJvZHkpO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgY2FzZSAnY29udGFjdCc6XG4gICAgICAgICAgICAgICAgdGhpcy5nZXRQbHVnaW4oTWVzc2FnZVBsdWdpbikuc2VuZE1lc3NhZ2UocmVjaXBpZW50LCB0cmltbWVkQm9keSk7XG4gICAgICAgICAgICAgICAgdGhpcy5tZXNzYWdlU2VudCQubmV4dChyZWNpcGllbnQpO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ2ludmFsaWQgcmVjaXBpZW50IHR5cGU6ICcgKyAocmVjaXBpZW50IGFzIGFueSk/LnJlY2lwaWVudFR5cGUpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgbG9hZENvbXBsZXRlSGlzdG9yeSgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuZ2V0UGx1Z2luKE1lc3NhZ2VBcmNoaXZlUGx1Z2luKS5sb2FkQWxsTWVzc2FnZXMoKTtcbiAgICB9XG5cbiAgICBnZXRQbHVnaW48VCBleHRlbmRzIENoYXRQbHVnaW4+KGNvbnN0cnVjdG9yOiBuZXcoLi4uYXJnczogYW55W10pID0+IFQpOiBUIHtcbiAgICAgICAgZm9yIChjb25zdCBwbHVnaW4gb2YgdGhpcy5wbHVnaW5zKSB7XG4gICAgICAgICAgICBpZiAocGx1Z2luLmNvbnN0cnVjdG9yID09PSBjb25zdHJ1Y3Rvcikge1xuICAgICAgICAgICAgICAgIHJldHVybiBwbHVnaW4gYXMgVDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ3BsdWdpbiBub3QgZm91bmQ6ICcgKyBjb25zdHJ1Y3Rvcik7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBvblVua25vd25TdGFuemEoc3RhbnphOiBTdGFuemEpIHtcblxuICAgICAgICBsZXQgaGFuZGxlZCA9IGZhbHNlO1xuXG4gICAgICAgIGZvciAoY29uc3QgcGx1Z2luIG9mIHRoaXMucGx1Z2lucykge1xuICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICBpZiAocGx1Z2luLmhhbmRsZVN0YW56YShzdGFuemEpKSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMubG9nU2VydmljZS5kZWJ1ZyhwbHVnaW4uY29uc3RydWN0b3IubmFtZSwgJ2hhbmRsZWQnLCBzdGFuemEudG9TdHJpbmcoKSk7XG4gICAgICAgICAgICAgICAgICAgIGhhbmRsZWQgPSB0cnVlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmxvZ1NlcnZpY2UuZXJyb3IoJ2Vycm9yIGhhbmRsaW5nIHN0YW56YSBpbiAnLCBwbHVnaW4uY29uc3RydWN0b3IubmFtZSwgZSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoIWhhbmRsZWQpIHtcbiAgICAgICAgICAgIHRoaXMubG9nU2VydmljZS53YXJuKCd1bmtub3duIHN0YW56YSA8PScsIHN0YW56YS50b1N0cmluZygpKTtcbiAgICAgICAgfVxuXG4gICAgfVxuXG4gICAgcmVjb25uZWN0U2lsZW50bHkoKTogdm9pZCB7XG4gICAgICAgIHRoaXMuY2hhdENvbm5lY3Rpb25TZXJ2aWNlLnJlY29ubmVjdFNpbGVudGx5KCk7XG4gICAgfVxuXG4gICAgcmVjb25uZWN0KCkge1xuICAgICAgICByZXR1cm4gdGhpcy5sb2dJbih0aGlzLmxhc3RMb2dJblJlcXVlc3QpO1xuICAgIH1cblxufVxuIl19