@hsaadawy/ngx-chat
Version:
411 lines • 73.5 kB
JavaScript
import { __awaiter } from "tslib";
import { jid as parseJid, xml } from '@xmpp/client';
import { BehaviorSubject, Subject } from 'rxjs';
import { dummyAvatarRoom } from '../../../../core/contact-avatar';
import { Direction } from '../../../../core/message';
import { MessageStore } from '../../../../core/message-store';
import { isJid } from '../../../../core/recipient';
import { AbstractStanzaBuilder } from '../abstract-stanza-builder';
import { StanzaBuilder } from '../stanza-builder';
import { AbstractXmppPlugin } from './abstract-xmpp-plugin';
import { MessageReceivedEvent } from './message.plugin';
import { ServiceDiscoveryPlugin } from './service-discovery.plugin';
export class Room {
constructor(occupantJid, logService, name) {
this.recipientType = 'room';
this.avatar = dummyAvatarRoom;
this.metadata = {};
this.roomJid = occupantJid.bare();
this.name = name !== null && name !== void 0 ? name : occupantJid.bare().toString();
this.nick = name !== null && name !== void 0 ? name : occupantJid.bare().toString();
this.occupantJid = occupantJid;
this.messageStore = new MessageStore(logService);
}
get jidBare() {
return this.roomJid;
}
get messages$() {
return this.messageStore.messages$;
}
get messages() {
return this.messageStore.messages;
}
get dateMessagesGroups() {
return this.messageStore.dateMessageGroups;
}
get oldestMessage() {
return this.messageStore.oldestMessage;
}
get mostRecentMessage() {
return this.messageStore.mostRecentMessage;
}
get mostRecentMessageReceived() {
return this.messageStore.mostRecentMessageReceived;
}
get mostRecentMessageSent() {
return this.messageStore.mostRecentMessageSent;
}
addMessage(message) {
this.messageStore.addMessage(message);
}
equalsBareJid(other) {
if (other instanceof Room || isJid(other)) {
const otherJid = other instanceof Room ? other.roomJid : other.bare();
return this.roomJid.bare().equals(otherJid);
}
return false;
}
}
export var Affiliation;
(function (Affiliation) {
Affiliation[Affiliation["none"] = 0] = "none";
Affiliation[Affiliation["member"] = 1] = "member";
Affiliation[Affiliation["admin"] = 2] = "admin";
Affiliation[Affiliation["owner"] = 3] = "owner";
Affiliation[Affiliation["outcast"] = 4] = "outcast";
})(Affiliation || (Affiliation = {}));
class QueryMemberListStanzaBuilder extends AbstractStanzaBuilder {
constructor(roomJid, affiliation) {
super();
this.roomJid = roomJid;
this.affiliation = affiliation;
}
static build(roomJid, affiliation) {
return new QueryMemberListStanzaBuilder(roomJid, affiliation).toStanza();
}
toStanza() {
return xml('iq', { type: 'get', to: this.roomJid }, xml('query', { xmlns: 'http://jabber.org/protocol/muc#admin' }, xml('item', { affiliation: this.affiliation })));
}
}
class ModifyMemberListStanzaBuilder extends AbstractStanzaBuilder {
constructor(roomJid, modifications) {
super();
this.roomJid = roomJid;
this.modifications = modifications;
}
static build(roomJid, modifications) {
return new ModifyMemberListStanzaBuilder(roomJid, modifications).toStanza();
}
toStanza() {
return xml('iq', { to: this.roomJid, type: 'set' }, xml('query', { xmlns: 'http://jabber.org/protocol/muc#admin' }, ...this.modifications.map(modification => this.buildItem(modification))));
}
buildItem({ nick, jid, affiliation }) {
const item = xml('item', { jid, affiliation: Affiliation[affiliation] });
if (nick) {
item.attrs.nick = nick;
}
return item;
}
}
/**
* The MultiUserChatPlugin tries to provide the necessary functionality for a multi-user text chat,
* whereby multiple XMPP users can exchange messages in the context of a room or channel, similar to Internet Relay Chat (IRC).
* For more details see:
* @see https://xmpp.org/extensions/xep-0045.html
*/
export class MultiUserChatPlugin extends AbstractXmppPlugin {
constructor(xmppChatAdapter, logService, serviceDiscoveryPlugin) {
super();
this.xmppChatAdapter = xmppChatAdapter;
this.logService = logService;
this.serviceDiscoveryPlugin = serviceDiscoveryPlugin;
this.rooms$ = new BehaviorSubject([]);
this.message$ = new Subject();
this.roomJoinResponseHandlers = new Map();
}
onOffline() {
this.roomJoinResponseHandlers.clear();
this.rooms$.next([]);
}
handleStanza(stanza, archiveDelayElement) {
if (this.isRoomPresenceStanza(stanza)) {
return this.handleRoomPresenceStanza(stanza);
}
else if (this.isRoomMessageStanza(stanza)) {
return this.handleRoomMessageStanza(stanza, archiveDelayElement);
}
return false;
}
isRoomPresenceStanza(stanza) {
return stanza.name === 'presence' && (stanza.getChild('x', 'http://jabber.org/protocol/muc')
|| stanza.getChild('x', 'http://jabber.org/protocol/muc#user')) != null;
}
handleRoomPresenceStanza(stanza) {
const handleStanza = this.roomJoinResponseHandlers.get(stanza.attrs.from);
if (handleStanza) {
this.roomJoinResponseHandlers.delete(stanza.attrs.from);
handleStanza(stanza);
return true;
}
return false;
}
/**
* Resolves if room could be configured as requested, rejects if room did exist or server did not accept configuration.
*/
createRoom(request) {
return __awaiter(this, void 0, void 0, function* () {
const { roomId, nick, name } = request;
const service = yield this.serviceDiscoveryPlugin.findService('conference', 'text');
const occupantJid = parseJid(roomId, service.jid, nick);
const { presenceResponse, room } = yield this.joinRoomInternal(occupantJid, name);
const itemElement = presenceResponse.getChild('x').getChild('item');
if (itemElement.attrs.affiliation !== 'owner') {
throw new Error('error creating room, user is not owner: ' + presenceResponse.toString());
}
/**
* requests a configuration form for a room which returns with the default values
* for an example see:
* https://xmpp.org/extensions/xep-0045.html#registrar-formtype-owner
*/
const configurationForm = yield this.xmppChatAdapter.chatConnectionService.sendIq(xml('iq', { type: 'get', to: room.roomJid.toString() }, xml('query', { xmlns: 'http://jabber.org/protocol/muc#owner' })));
const configurationListElement = configurationForm.getChild('query').getChild('x');
if (!configurationListElement) {
throw new Error('room not configurable');
}
const roomConfigurationOptions = this.applyRoomCreationRequestOptions(this.extractDefaultConfiguration(configurationListElement.getChildren('field')), request);
try {
yield this.xmppChatAdapter.chatConnectionService.sendIq(xml('iq', { type: 'set', to: room.roomJid.toString() }, xml('query', { xmlns: 'http://jabber.org/protocol/muc#owner' }, xml('x', { xmlns: 'jabber:x:data', type: 'submit' }, xml('field', { var: 'FORM_TYPE' }, xml('value', {}, 'http://jabber.org/protocol/muc#roomconfig')), ...this.configurationToElements(roomConfigurationOptions)))));
return room;
}
catch (e) {
this.logService.error('room configuration rejected', e);
throw e;
}
});
}
destroyRoom(roomJid) {
return __awaiter(this, void 0, void 0, function* () {
let roomDestroyedResponse;
try {
roomDestroyedResponse = yield this.xmppChatAdapter.chatConnectionService.sendIq(xml('iq', { type: 'set', to: roomJid.toString() }, xml('query', { xmlns: 'http://jabber.org/protocol/muc#owner' }, xml('destroy'))));
}
catch (e) {
this.logService.error('error destroying room');
throw e;
}
// TODO: refactor so that we instead listen to the presence destroy stanza
const allRoomsWithoutDestroyedRoom = this.rooms$.getValue().filter(room => !room.roomJid.equals(roomJid));
this.rooms$.next(allRoomsWithoutDestroyedRoom);
return roomDestroyedResponse;
});
}
joinRoomInternal(roomJid, name) {
return __awaiter(this, void 0, void 0, function* () {
if (this.getRoomByJid(roomJid.bare())) {
throw new Error('can not join room more than once: ' + roomJid.bare().toString());
}
const userJid = this.xmppChatAdapter.chatConnectionService.userJid;
const occupantJid = parseJid(roomJid.local, roomJid.domain, roomJid.resource || userJid.local);
const roomJoinedPromise = new Promise(resolve => this.roomJoinResponseHandlers.set(occupantJid.toString(), resolve));
try {
yield this.xmppChatAdapter.chatConnectionService.send(xml('presence', { from: userJid.toString(), to: occupantJid.toString() }, xml('x', { xmlns: 'http://jabber.org/protocol/muc' })));
}
catch (e) {
this.logService.error('error sending presence stanza to join a room', e);
this.roomJoinResponseHandlers.delete(occupantJid.toString());
throw e;
}
const presenceResponse = yield roomJoinedPromise;
if (presenceResponse.getChild('error')) {
throw new Error('error joining room: ' + presenceResponse.toString());
}
let room = this.getRoomByJid(roomJid);
if (!room) {
room = new Room(occupantJid, this.logService, name);
this.rooms$.next([room].concat(this.rooms$.getValue()));
}
return { presenceResponse, room };
});
}
joinRoom(occupantJid) {
return __awaiter(this, void 0, void 0, function* () {
return (yield this.joinRoomInternal(occupantJid)).room;
});
}
queryAllRooms() {
return __awaiter(this, void 0, void 0, function* () {
const conferenceServer = yield this.serviceDiscoveryPlugin.findService('conference', 'text');
const to = conferenceServer.jid.toString();
const result = [];
let roomQueryResponse = yield this.xmppChatAdapter.chatConnectionService.sendIq(xml('iq', { type: 'get', to: conferenceServer.jid.toString() }, xml('query', { xmlns: ServiceDiscoveryPlugin.DISCO_ITEMS })));
result.push(...this.extractRoomSummariesFromResponse(roomQueryResponse));
let resultSet = this.extractResultSetFromResponse(roomQueryResponse);
while (resultSet && resultSet.getChild('last')) {
const lastReceivedRoom = resultSet.getChildText('last');
roomQueryResponse = yield this.xmppChatAdapter.chatConnectionService.sendIq(xml('iq', { type: 'get', to: conferenceServer.jid.toString() }, xml('query', { xmlns: ServiceDiscoveryPlugin.DISCO_ITEMS }, xml('set', { xmlns: 'http://jabber.org/protocol/rsm' }, xml('max', {}, 250), xml('after', {}, lastReceivedRoom)))));
result.push(...this.extractRoomSummariesFromResponse(roomQueryResponse));
resultSet = this.extractResultSetFromResponse(roomQueryResponse);
}
return result;
});
}
extractRoomSummariesFromResponse(iq) {
var _a, _b;
return ((_b = (_a = iq
.getChild('query', ServiceDiscoveryPlugin.DISCO_ITEMS)) === null || _a === void 0 ? void 0 : _a.getChildren('item')) === null || _b === void 0 ? void 0 : _b.map(room => room.attrs)) || [];
}
extractResultSetFromResponse(iq) {
var _a;
return (_a = iq
.getChild('query', ServiceDiscoveryPlugin.DISCO_ITEMS)) === null || _a === void 0 ? void 0 : _a.getChild('set', 'http://jabber.org/protocol/rsm');
}
/**
* Get all members of a MUC-Room with their affiliation to the room using the rooms fullJid
* @param fullRoomJid fullJid of the room as string
*/
queryMemberList(fullRoomJid) {
return __awaiter(this, void 0, void 0, function* () {
const memberQueryResponses = yield Promise.all([
this.xmppChatAdapter.chatConnectionService.sendIq(QueryMemberListStanzaBuilder.build(fullRoomJid, 'admin')),
this.xmppChatAdapter.chatConnectionService.sendIq(QueryMemberListStanzaBuilder.build(fullRoomJid, 'member')),
this.xmppChatAdapter.chatConnectionService.sendIq(QueryMemberListStanzaBuilder.build(fullRoomJid, 'owner')),
this.xmppChatAdapter.chatConnectionService.sendIq(QueryMemberListStanzaBuilder.build(fullRoomJid, 'outcast')),
]);
let members = [];
for (const memberQueryResponse of memberQueryResponses) {
const membersFromQueryResponse = memberQueryResponse.getChild('query').getChildren('item')
.map((memberItem) => ({
jid: memberItem.attrs.jid,
nick: memberItem.attrs.nick,
affiliation: this.reverseMapAffiliation(memberItem.attrs.affiliation),
}));
members = members.concat(membersFromQueryResponse);
}
return members;
});
}
reverseMapAffiliation(value) {
if (!value || value === 'none') {
return Affiliation.none;
}
else if (value === 'member') {
return Affiliation.member;
}
else if (value === 'admin') {
return Affiliation.admin;
}
else if (value === 'owner') {
return Affiliation.owner;
}
else if (value === 'outcast') {
return Affiliation.outcast;
}
else {
const message = 'unexpected affilation: ' + value;
this.logService.error(message);
throw new Error(message);
}
}
modifyMemberList(roomJid, jid, affiliation, nick) {
return __awaiter(this, void 0, void 0, function* () {
return yield this.xmppChatAdapter.chatConnectionService.sendIq(ModifyMemberListStanzaBuilder.build(roomJid, [{ jid, affiliation, nick }]));
});
}
sendMessage(room, body, thread) {
return __awaiter(this, void 0, void 0, function* () {
const from = this.xmppChatAdapter.chatConnectionService.userJid.toString();
const roomJid = room.roomJid.toString();
const roomMessageStanza = thread ? StanzaBuilder.buildRoomMessageWithThread(from, roomJid, body, thread)
: StanzaBuilder.buildRoomMessageWithBody(from, roomJid, body);
for (const plugin of this.xmppChatAdapter.plugins) {
plugin.beforeSendMessage(roomMessageStanza);
}
return yield this.xmppChatAdapter.chatConnectionService.send(roomMessageStanza);
});
}
configurationToElements(configurationOptions) {
return [...configurationOptions.entries()]
.map(([configurationKey, configurationValues]) => xml('field', { var: configurationKey }, ...configurationValues.map(value => xml('value', {}, value))));
}
extractDefaultConfiguration(fields) {
const entries = fields
.filter(field => field.attrs.type !== 'hidden')
.map((field) => [
field.attrs.var,
field.getChildren('value').map(value => value.getText())
]);
return new Map(entries);
}
applyRoomCreationRequestOptions(defaultOptions, request) {
const options = new Map(defaultOptions);
options
.set('muc#roomconfig_whois', [request.nonAnonymous ? 'anyone' : 'moderators'])
.set('muc#roomconfig_publicroom', [request.public ? '1' : '0'])
.set('muc#roomconfig_membersonly', [request.membersOnly ? '1' : '0'])
.set('muc#roomconfig_persistentroom', [request.persistentRoom ? '1' : '0']);
if (request.allowSubscription !== undefined) {
options.set('allow_subscription', [request.allowSubscription === true ? '1' : '0']);
}
return options;
}
isRoomMessageStanza(stanza) {
var _a;
return stanza.name === 'message' && stanza.attrs.type === 'groupchat' && !!((_a = stanza.getChildText('body')) === null || _a === void 0 ? void 0 : _a.trim());
}
handleRoomMessageStanza(messageStanza, archiveDelayElement) {
const delayElement = archiveDelayElement !== null && archiveDelayElement !== void 0 ? archiveDelayElement : messageStanza.getChild('delay');
const datetime = (delayElement === null || delayElement === void 0 ? void 0 : delayElement.attrs.stamp)
? new Date(delayElement.attrs.stamp)
: new Date() /* TODO: replace with entity time plugin */;
const from = parseJid(messageStanza.attrs.from);
const room = this.getRoomByJid(from.bare());
if (!room) {
// there are several reasons why we can receive a message for an unknown room:
// - this is a message delivered via MAM/MUCSub but the room it was stored for
// - is gone (was destroyed)
// - user was banned from room
// - room wasn't joined yet
// - this is some kind of error on developer's side
this.logService.warn(`received stanza for unknown room: ${from.bare().toString()}`);
return false;
}
const message = {
body: messageStanza.getChildText('body').trim(),
datetime,
id: messageStanza.attrs.id,
from,
direction: from.equals(room.occupantJid) ? Direction.out : Direction.in,
delayed: !!delayElement,
fromArchive: archiveDelayElement != null
};
const messageReceivedEvent = new MessageReceivedEvent();
for (const plugin of this.xmppChatAdapter.plugins) {
plugin.afterReceiveMessage(message, messageStanza, messageReceivedEvent);
}
if (!messageReceivedEvent.discard) {
room.addMessage(message);
}
if (!message.delayed) {
this.message$.next(room);
}
return true;
}
getRoomByJid(jid) {
return this.rooms$.getValue().find(room => room.roomJid.equals(jid));
}
ban() {
throw new Error('moderation not implemented');
}
invite() {
throw new Error('moderation not implemented');
}
join() {
throw new Error('moderation not implemented');
}
kick() {
throw new Error('moderation not implemented');
}
nick() {
throw new Error('moderation not implemented');
}
part() {
this.leave();
}
leave() {
throw new Error('moderation not implemented');
}
topic() {
throw new Error('moderation not implemented');
}
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibXVsdGktdXNlci1jaGF0LnBsdWdpbi5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uLy4uLy4uLy4uLy4uL3Byb2plY3RzL3BhenpuZXR3b3JrL25neC1jaGF0L3NyYy9saWIvc2VydmljZXMvYWRhcHRlcnMveG1wcC9wbHVnaW5zL211bHRpLXVzZXItY2hhdC5wbHVnaW4udHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBLE9BQU8sRUFBRSxHQUFHLElBQUksUUFBUSxFQUFFLEdBQUcsRUFBRSxNQUFNLGNBQWMsQ0FBQztBQUdwRCxPQUFPLEVBQUUsZUFBZSxFQUFFLE9BQU8sRUFBRSxNQUFNLE1BQU0sQ0FBQztBQUVoRCxPQUFPLEVBQUUsZUFBZSxFQUFFLE1BQU0saUNBQWlDLENBQUM7QUFDbEUsT0FBTyxFQUFFLFNBQVMsRUFBVyxNQUFNLDBCQUEwQixDQUFDO0FBQzlELE9BQU8sRUFBcUIsWUFBWSxFQUFFLE1BQU0sZ0NBQWdDLENBQUM7QUFDakYsT0FBTyxFQUFFLEtBQUssRUFBYSxNQUFNLDRCQUE0QixDQUFDO0FBRzlELE9BQU8sRUFBRSxxQkFBcUIsRUFBRSxNQUFNLDRCQUE0QixDQUFDO0FBQ25FLE9BQU8sRUFBRSxhQUFhLEVBQUUsTUFBTSxtQkFBbUIsQ0FBQztBQUVsRCxPQUFPLEVBQUUsa0JBQWtCLEVBQUUsTUFBTSx3QkFBd0IsQ0FBQztBQUM1RCxPQUFPLEVBQUUsb0JBQW9CLEVBQUUsTUFBTSxrQkFBa0IsQ0FBQztBQUN4RCxPQUFPLEVBQUUsc0JBQXNCLEVBQUUsTUFBTSw0QkFBNEIsQ0FBQztBQTREcEUsTUFBTSxPQUFPLElBQUk7SUFlYixZQUFZLFdBQWdCLEVBQUUsVUFBc0IsRUFBRSxJQUF5QjtRQWJ0RSxrQkFBYSxHQUFHLE1BQU0sQ0FBQztRQUtoQyxXQUFNLEdBQUcsZUFBZSxDQUFDO1FBQ3pCLGFBQVEsR0FBaUIsRUFBRSxDQUFDO1FBUXhCLElBQUksQ0FBQyxPQUFPLEdBQUcsV0FB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JztcclxuaW1wb3J0IHsgSklEIH0gZnJvbSAnQHhtcHAvamlkJztcclxuaW1wb3J0IHsgRWxlbWVudCB9IGZyb20gJ2x0eCc7XHJcbmltcG9ydCB7IEJlaGF2aW9yU3ViamVjdCwgU3ViamVjdCB9IGZyb20gJ3J4anMnO1xyXG5pbXBvcnQgeyBDb250YWN0TWV0YWRhdGEgfSBmcm9tICcuLi8uLi8uLi8uLi9jb3JlL2NvbnRhY3QnO1xyXG5pbXBvcnQgeyBkdW1teUF2YXRhclJvb20gfSBmcm9tICcuLi8uLi8uLi8uLi9jb3JlL2NvbnRhY3QtYXZhdGFyJztcclxuaW1wb3J0IHsgRGlyZWN0aW9uLCBNZXNzYWdlIH0gZnJvbSAnLi4vLi4vLi4vLi4vY29yZS9tZXNzYWdlJztcclxuaW1wb3J0IHsgRGF0ZU1lc3NhZ2VzR3JvdXAsIE1lc3NhZ2VTdG9yZSB9IGZyb20gJy4uLy4uLy4uLy4uL2NvcmUvbWVzc2FnZS1zdG9yZSc7XHJcbmltcG9ydCB7IGlzSmlkLCBSZWNpcGllbnQgfSBmcm9tICcuLi8uLi8uLi8uLi9jb3JlL3JlY2lwaWVudCc7XHJcbmltcG9ydCB7IElxUmVzcG9uc2VTdGFuemEsIFN0YW56YSB9IGZyb20gJy4uLy4uLy4uLy4uL2NvcmUvc3RhbnphJztcclxuaW1wb3J0IHsgTG9nU2VydmljZSB9IGZyb20gJy4uLy4uLy4uL2xvZy5zZXJ2aWNlJztcclxuaW1wb3J0IHsgQWJzdHJhY3RTdGFuemFCdWlsZGVyIH0gZnJvbSAnLi4vYWJzdHJhY3Qtc3RhbnphLWJ1aWxkZXInO1xyXG5pbXBvcnQgeyBTdGFuemFCdWlsZGVyIH0gZnJvbSAnLi4vc3RhbnphLWJ1aWxkZXInO1xyXG5pbXBvcnQgeyBYbXBwQ2hhdEFkYXB0ZXIgfSBmcm9tICcuLi94bXBwLWNoYXQtYWRhcHRlci5zZXJ2aWNlJztcclxuaW1wb3J0IHsgQWJzdHJhY3RYbXBwUGx1Z2luIH0gZnJvbSAnLi9hYnN0cmFjdC14bXBwLXBsdWdpbic7XHJcbmltcG9ydCB7IE1lc3NhZ2VSZWNlaXZlZEV2ZW50IH0gZnJvbSAnLi9tZXNzYWdlLnBsdWdpbic7XHJcbmltcG9ydCB7IFNlcnZpY2VEaXNjb3ZlcnlQbHVnaW4gfSBmcm9tICcuL3NlcnZpY2UtZGlzY292ZXJ5LnBsdWdpbic7XHJcblxyXG4vKipcclxuICogc2VlOlxyXG4gKiBodHRwczovL3htcHAub3JnL2V4dGVuc2lvbnMveGVwLTAwNDUuaHRtbCN0ZXJtcy1yb29tc1xyXG4gKi9cclxuZXhwb3J0IGludGVyZmFjZSBSb29tQ3JlYXRpb25PcHRpb25zIHtcclxuICAgIG5hbWU/OiBzdHJpbmc7XHJcbiAgICByb29tSWQ6IHN0cmluZztcclxuICAgIC8qKlxyXG4gICAgICogQSByb29tIHRoYXQgY2FuIGJlIGZvdW5kIGJ5IGFueSB1c2VyIHRocm91Z2ggbm9ybWFsIG1lYW5zIHN1Y2ggYXMgc2VhcmNoaW5nIGFuZCBzZXJ2aWNlIGRpc2NvdmVyeVxyXG4gICAgICovXHJcbiAgICBwdWJsaWM6IGJvb2xlYW47XHJcbiAgICAvKipcclxuICAgICAqIGZvciB0cnVlOlxyXG4gICAgICogQSByb29tIHRoYXQgYSB1c2VyIGNhbm5vdCBlbnRlciB3aXRob3V0IGJlaW5nIG9uIHRoZSBtZW1iZXIgbGlzdC5cclxuICAgICAqIGZvciBmYWxzZTpcclxuICAgICAqIEEgcm9vbSB0aGF0IG5vbi1iYW5uZWQgZW50aXRpZXMgYXJlIGFsbG93ZWQgdG8gZW50ZXIgd2l0aG91dCBiZWluZyBvbiB0aGUgbWVtYmVyIGxpc3QuXHJcbiAgICAgKi9cclxuICAgIG1lbWJlcnNPbmx5OiBib29sZWFuO1xyXG4gICAgLyoqXHJcbiAgICAgKiBmb3IgdHJ1ZTpcclxuICAgICAqIEEgcm9vbSBpbiB3aGljaCBhbiBvY2N1cGFudCdzIGZ1bGwgSklEIGlzIGV4cG9zZWQgdG8gYWxsIG90aGVyIG9jY3VwYW50cyxcclxuICAgICAqIGFsdGhvdWdoIHRoZSBvY2N1cGFudCBjYW4gcmVxdWVzdCBhbnkgZGVzaXJlZCByb29tIG5pY2tuYW1lLlxyXG4gICAgICogZm9yIGZhbHNlOlxyXG4gICAgICogQSByb29tIGluIHdoaWNoIGFuIG9jY3VwYW50J3MgZnVsbCBKSUQgY2FuIGJlIGRpc2NvdmVyZWQgYnkgcm9vbSBhZG1pbnMgb25seS5cclxuICAgICAqL1xyXG4gICAgbm9uQW5vbnltb3VzOiBib29sZWFuO1xyXG4gICAgLyoqXHJcbiAgICAgKiBmb3IgdHJ1ZTpcclxuICAgICAqIEEgcm9vbSB0aGF0IGlzIG5vdCBkZXN0cm95ZWQgaWYgdGhlIGxhc3Qgb2NjdXBhbnQgZXhpdHMuXHJcbiAgICAgKiBmb3IgZmFsc2U6XHJcbiAgICAgKiBBIHJvb20gdGhhdCBpcyBkZXN0cm95ZWQgaWYgdGhlIGxhc3Qgb2NjdXBhbnQgZXhpdHMuXHJcbiAgICAgKi9cclxuICAgIHBlcnNpc3RlbnRSb29tOiBib29sZWFuO1xyXG4gICAgLyoqXHJcbiAgICAgKiBPcHRpb25hbCBuYW1lIGZvciB0aGUgcm9vbSwgaWYgbm8gcHJvdmlkZWQgcm9vbSB3aWxsIGJlIG9ubHkgaWRlbnRpZmllZCBieSBpdHMgamlkXHJcbiAgICAgKi9cclxuICAgIG5pY2s/OiBzdHJpbmc7XHJcbiAgICAvKipcclxuICAgICAqIGFsbG93IGVqYWJiZXJkIE11Y1N1YiBzdWJzY3JpcHRpb25zLlxyXG4gICAgICogUm9vbSBvY2N1cGFudHMgYXJlIGFsbG93ZWQgdG8gc3Vic2NyaWJlIHRvIG1lc3NhZ2Ugbm90aWZpY2F0aW9ucyBiZWluZyBhcmNoaXZlZCB3aGlsZSB0aGV5IHdlcmUgb2ZmbGluZVxyXG4gICAgICovXHJcbiAgICBhbGxvd1N1YnNjcmlwdGlvbj86IGJvb2xlYW47XHJcbn1cclxuXHJcbmV4cG9ydCBpbnRlcmZhY2UgUm9vbU1lc3NhZ2UgZXh0ZW5kcyBNZXNzYWdlIHtcclxuICAgIGZyb206IEpJRDtcclxufVxyXG5cclxuZXhwb3J0IGludGVyZmFjZSBPY2N1cGFudCB7XHJcbiAgICByb29tSmlkOiBKSUQ7XHJcbiAgICByZWFsSmlkPzogSklEO1xyXG4gICAgbWV0YWRhdGE6IENvbnRhY3RNZXRhZGF0YTtcclxufVxyXG5cclxuZXhwb3J0IGludGVyZmFjZSBSb29tTWV0YWRhdGEge1xyXG4gICAgW2tleTogc3RyaW5nXTogYW55O1xyXG59XHJcblxyXG5leHBvcnQgY2xhc3MgUm9vbSB7XHJcblxyXG4gICAgcmVhZG9ubHkgcmVjaXBpZW50VHlwZSA9ICdyb29tJztcclxuICAgIHJlYWRvbmx5IHJvb21KaWQ6IEpJRDtcclxuICAgIG9jY3VwYW50SmlkOiBKSUQ7XHJcbiAgICBuYW1lOiBzdHJpbmc7XHJcbiAgICBuaWNrOnN0cmluZztcclxuICAgIGF2YXRhciA9IGR1bW15QXZhdGFyUm9vbTtcclxuICAgIG1ldGFkYXRhOiBSb29tTWV0YWRhdGEgPSB7fTtcclxuICAgIHByaXZhdGUgbWVzc2FnZVN0b3JlOiBNZXNzYWdlU3RvcmU8Um9vbU1lc3NhZ2U+O1xyXG5cclxuICAgIGdldCBqaWRCYXJlKCk6IEpJRCB7XHJcbiAgICAgICAgcmV0dXJuIHRoaXMucm9vbUppZDtcclxuICAgIH1cclxuXHJcbiAgICBjb25zdHJ1Y3RvcihvY2N1cGFudEppZDogSklELCBsb2dTZXJ2aWNlOiBMb2dTZXJ2aWNlLCBuYW1lPzogc3RyaW5nIHwgdW5kZWZpbmVkKSB7XHJcbiAgICAgICAgdGhpcy5yb29tSmlkID0gb2NjdXBhbnRKaWQuYmFyZSgpO1xyXG4gICAgICAgIHRoaXMubmFtZSA9IG5hbWUgPz8gb2NjdXBhbnRKaWQuYmFyZSgpLnRvU3RyaW5nKCk7XHJcbiAgICAgICAgdGhpcy5uaWNrID0gbmFtZSA/PyBvY2N1cGFudEppZC5iYXJlKCkudG9TdHJpbmcoKTtcclxuICAgICAgICB0aGlzLm9jY3VwYW50SmlkID0gb2NjdXBhbnRKaWQ7XHJcbiAgICAgICAgdGhpcy5tZXNzYWdlU3RvcmUgPSBuZXcgTWVzc2FnZVN0b3JlPFJvb21NZXNzYWdlPihsb2dTZXJ2aWNlKTtcclxuICAgIH1cclxuXHJcbiAgICBnZXQgbWVzc2FnZXMkKCk6IFN1YmplY3Q8Um9vbU1lc3NhZ2U+IHtcclxuICAgICAgICByZXR1cm4gdGhpcy5tZXNzYWdlU3RvcmUubWVzc2FnZXMkO1xyXG4gICAgfVxyXG5cclxuICAgIGdldCBtZXNzYWdlcygpOiBSb29tTWVzc2FnZVtdIHtcclxuICAgICAgICByZXR1cm4gdGhpcy5tZXNzYWdlU3RvcmUubWVzc2FnZXM7XHJcbiAgICB9XHJcblxyXG4gICAgZ2V0IGRhdGVNZXNzYWdlc0dyb3VwcygpOiBEYXRlTWVzc2FnZXNHcm91cDxSb29tTWVzc2FnZT5bXSB7XHJcbiAgICAgICAgcmV0dXJuIHRoaXMubWVzc2FnZVN0b3JlLmRhdGVNZXNzYWdlR3JvdXBzO1xyXG4gICAgfVxyXG5cclxuICAgIGdldCBvbGRlc3RNZXNzYWdlKCk6IFJvb21NZXNzYWdlIHtcclxuICAgICAgICByZXR1cm4gdGhpcy5tZXNzYWdlU3RvcmUub2xkZXN0TWVzc2FnZTtcclxuICAgIH1cclxuXHJcbiAgICBnZXQgbW9zdFJlY2VudE1lc3NhZ2UoKTogUm9vbU1lc3NhZ2Uge1xyXG4gICAgICAgIHJldHVybiB0aGlzLm1lc3NhZ2VTdG9yZS5tb3N0UmVjZW50TWVzc2FnZTtcclxuICAgIH1cclxuXHJcbiAgICBnZXQgbW9zdFJlY2VudE1lc3NhZ2VSZWNlaXZlZCgpOiBSb29tTWVzc2FnZSB7XHJcbiAgICAgICAgcmV0dXJuIHRoaXMubWVzc2FnZVN0b3JlLm1vc3RSZWNlbnRNZXNzYWdlUmVjZWl2ZWQ7XHJcbiAgICB9XHJcblxyXG4gICAgZ2V0IG1vc3RSZWNlbnRNZXNzYWdlU2VudCgpOiBSb29tTWVzc2FnZSB7XHJcbiAgICAgICAgcmV0dXJuIHRoaXMubWVzc2FnZVN0b3JlLm1vc3RSZWNlbnRNZXNzYWdlU2VudDtcclxuICAgIH1cclxuXHJcbiAgICBhZGRNZXNzYWdlKG1lc3NhZ2U6IFJvb21NZXNzYWdlKTogdm9pZCB7XHJcbiAgICAgICAgdGhpcy5tZXNzYWdlU3RvcmUuYWRkTWVzc2FnZShtZXNzYWdlKTtcclxuICAgIH1cclxuXHJcbiAgICBlcXVhbHNCYXJlSmlkKG90aGVyOiBSZWNpcGllbnQgfCBKSUQpOiBib29sZWFuIHtcclxuICAgICAgICBpZiAob3RoZXIgaW5zdGFuY2VvZiBSb29tIHx8IGlzSmlkKG90aGVyKSkge1xyXG4gICAgICAgICAgICBjb25zdCBvdGhlckppZCA9IG90aGVyIGluc3RhbmNlb2YgUm9vbSA/IG90aGVyLnJvb21KaWQgOiBvdGhlci5iYXJlKCk7XHJcbiAgICAgICAgICAgIHJldHVybiB0aGlzLnJvb21KaWQuYmFyZSgpLmVxdWFscyhvdGhlckppZCk7XHJcbiAgICAgICAgfVxyXG4gICAgICAgIHJldHVybiBmYWxzZTtcclxuICAgIH1cclxuXHJcbn1cclxuXHJcbmV4cG9ydCBlbnVtIEFmZmlsaWF0aW9uIHtcclxuICAgIG5vbmUsXHJcbiAgICBtZW1iZXIsXHJcbiAgICBhZG1pbixcclxuICAgIG93bmVyLFxyXG4gICAgb3V0Y2FzdFxyXG59XHJcblxyXG5jbGFzcyBRdWVyeU1lbWJlckxpc3RTdGFuemFCdWlsZGVyIGV4dGVuZHMgQWJzdHJhY3RTdGFuemFCdWlsZGVyIHtcclxuXHJcbiAgICBjb25zdHJ1Y3Rvcihwcml2YXRlIHJlYWRvbmx5IHJvb21KaWQ6IHN0cmluZywgcHJpdmF0ZSByZWFkb25seSBhZmZpbGlhdGlvbjogc3RyaW5nKSB7XHJcbiAgICAgICAgc3VwZXIoKTtcclxuICAgIH1cclxuXHJcbiAgICBzdGF0aWMgYnVpbGQocm9vbUppZDogc3RyaW5nLCBhZmZpbGlhdGlvbjogc3RyaW5nKTogU3RhbnphIHtcclxuICAgICAgICByZXR1cm4gbmV3IFF1ZXJ5TWVtYmVyTGlzdFN0YW56YUJ1aWxkZXIocm9vbUppZCwgYWZmaWxpYXRpb24pLnRvU3RhbnphKCk7XHJcbiAgICB9XHJcblxyXG4gICAgdG9TdGFuemEoKTogU3RhbnphIHtcclxuICAgICAgICByZXR1cm4geG1sKCdpcScsIHt0eXBlOiAnZ2V0JywgdG86IHRoaXMucm9vbUppZH0sXHJcbiAgICAgICAgICAgIHhtbCgncXVlcnknLCB7eG1sbnM6ICdodHRwOi8vamFiYmVyLm9yZy9wcm90b2NvbC9tdWMjYWRtaW4nfSxcclxuICAgICAgICAgICAgICAgIHhtbCgnaXRlbScsIHthZmZpbGlhdGlvbjogdGhpcy5hZmZpbGlhdGlvbn0pLFxyXG4gICAgICAgICAgICApLFxyXG4gICAgICAgICk7XHJcbiAgICB9XHJcblxyXG59XHJcblxyXG5leHBvcnQgaW50ZXJmYWNlIE1lbWJlckxpc3RJdGVtIHtcclxuICAgIGppZDogc3RyaW5nO1xyXG4gICAgYWZmaWxpYXRpb246IEFmZmlsaWF0aW9uO1xyXG4gICAgbmljaz86IHN0cmluZztcclxufVxyXG5cclxuZXhwb3J0IGludGVyZmFjZSBSb29tU3VtbWFyeSB7XHJcbiAgICBqaWQ6IHN0cmluZztcclxuICAgIG5hbWU6IHN0cmluZztcclxufVxyXG5cclxuY2xhc3MgTW9kaWZ5TWVtYmVyTGlzdFN0YW56YUJ1aWxkZXIgZXh0ZW5kcyBBYnN0cmFjdFN0YW56YUJ1aWxkZXIge1xyXG5cclxuICAgIGNvbnN0cnVjdG9yKHByaXZhdGUgcmVhZG9ubHkgcm9vbUppZDogc3RyaW5nLCBwcml2YXRlIHJlYWRvbmx5IG1vZGlmaWNhdGlvbnM6IHJlYWRvbmx5IE1lbWJlckxpc3RJdGVtW10pIHtcclxuICAgICAgICBzdXBlcigpO1xyXG4gICAgfVxyXG5cclxuICAgIHN0YXRpYyBidWlsZChyb29tSmlkOiBzdHJpbmcsIG1vZGlmaWNhdGlvbnM6IHJlYWRvbmx5IE1lbWJlckxpc3RJdGVtW10pOiBTdGFuemEge1xyXG4gICAgICAgIHJldHVybiBuZXcgTW9kaWZ5TWVtYmVyTGlzdFN0YW56YUJ1aWxkZXIocm9vbUppZCwgbW9kaWZpY2F0aW9ucykudG9TdGFuemEoKTtcclxuICAgIH1cclxuXHJcbiAgICB0b1N0YW56YSgpOiBTdGFuemEge1xyXG4gICAgICAgIHJldHVybiB4bWwoJ2lxJywge3RvOiB0aGlzLnJvb21KaWQsIHR5cGU6ICdzZXQnfSxcclxuICAgICAgICAgICAgeG1sKCdxdWVyeScsIHt4bWxuczogJ2h0dHA6Ly9qYWJiZXIub3JnL3Byb3RvY29sL211YyNhZG1pbid9LFxyXG4gICAgICAgICAgICAgICAgLi4udGhpcy5tb2RpZmljYXRpb25zLm1hcChtb2RpZmljYXRpb24gPT4gdGhpcy5idWlsZEl0ZW0obW9kaWZpY2F0aW9uK