UNPKG

64.7 kBJavaScriptView Raw
1'use strict';
2
3var _getIterator2 = require('babel-runtime/core-js/get-iterator');
4
5var _getIterator3 = _interopRequireDefault(_getIterator2);
6
7var _getPrototypeOf = require('babel-runtime/core-js/object/get-prototype-of');
8
9var _getPrototypeOf2 = _interopRequireDefault(_getPrototypeOf);
10
11var _possibleConstructorReturn2 = require('babel-runtime/helpers/possibleConstructorReturn');
12
13var _possibleConstructorReturn3 = _interopRequireDefault(_possibleConstructorReturn2);
14
15var _inherits2 = require('babel-runtime/helpers/inherits');
16
17var _inherits3 = _interopRequireDefault(_inherits2);
18
19var _classCallCheck2 = require('babel-runtime/helpers/classCallCheck');
20
21var _classCallCheck3 = _interopRequireDefault(_classCallCheck2);
22
23var _createClass2 = require('babel-runtime/helpers/createClass');
24
25var _createClass3 = _interopRequireDefault(_createClass2);
26
27function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
28
29var ChatServiceError = require('./ChatServiceError');
30var FastMap = require('collections/fast-map');
31var FastSet = require('collections/fast-set');
32var List = require('collections/list');
33var Promise = require('bluebird');
34var Room = require('./Room');
35var User = require('./User');
36var _ = require('lodash');
37var promiseRetry = require('promise-retry');
38var uid = require('uid-safe');
39
40var _require = require('es6-mixin');
41
42var mixin = _require.mixin;
43
44
45function _initState(state, values) {
46 state.clear();
47 if (!values) {
48 return Promise.resolve();
49 } else {
50 return state.addEach(values);
51 }
52}
53
54// Memory lock operations.
55// @mixin
56
57var LockOperations = function () {
58 function LockOperations(locks) {
59 (0, _classCallCheck3.default)(this, LockOperations);
60
61 this.locks = locks;
62 }
63
64 (0, _createClass3.default)(LockOperations, [{
65 key: 'lock',
66 value: function lock(key, val, ttl) {
67 var _this = this;
68
69 return promiseRetry({ minTimeout: 100, retries: 10, factor: 1.5, randomize: true }, function (retry, n) {
70 if (_this.locks.has(key)) {
71 var err = new ChatServiceError('timeout');
72 return retry(err);
73 } else {
74 _this.locks.set(key, val);
75 return Promise.resolve();
76 }
77 });
78 }
79 }, {
80 key: 'unlock',
81 value: function unlock(key, val) {
82 var currentVal = this.locks.get(key);
83 if (currentVal === val) {
84 this.locks.delete(key);
85 }
86 return Promise.resolve();
87 }
88 }]);
89 return LockOperations;
90}();
91
92// Implements state API lists management.
93
94
95var ListsStateMemory = function () {
96 function ListsStateMemory() {
97 (0, _classCallCheck3.default)(this, ListsStateMemory);
98 }
99
100 (0, _createClass3.default)(ListsStateMemory, [{
101 key: 'checkList',
102 value: function checkList(listName, num, limit) {
103 if (!this.hasList(listName)) {
104 var error = new ChatServiceError('noList', listName);
105 return Promise.reject(error);
106 }
107 if (listName === 'userlist') {
108 return Promise.resolve();
109 }
110 if (this[listName].length + num > limit) {
111 var _error = new ChatServiceError('listLimitExceeded', listName);
112 return Promise.reject(_error);
113 } else {
114 return Promise.resolve();
115 }
116 }
117 }, {
118 key: 'addToList',
119 value: function addToList(listName, elems, limit) {
120 var _this2 = this;
121
122 var num = elems.length;
123 return this.checkList(listName, num, limit).then(function () {
124 _this2[listName].addEach(elems);
125 return Promise.resolve();
126 });
127 }
128 }, {
129 key: 'removeFromList',
130 value: function removeFromList(listName, elems) {
131 var _this3 = this;
132
133 return this.checkList(listName).then(function () {
134 _this3[listName].deleteEach(elems);
135 return Promise.resolve();
136 });
137 }
138 }, {
139 key: 'getList',
140 value: function getList(listName) {
141 var _this4 = this;
142
143 return this.checkList(listName).then(function () {
144 var data = _this4[listName].toArray();
145 return Promise.resolve(data);
146 });
147 }
148 }, {
149 key: 'hasInList',
150 value: function hasInList(listName, elem) {
151 var _this5 = this;
152
153 return this.checkList(listName).then(function () {
154 var data = _this5[listName].has(elem);
155 data = Boolean(data);
156 return Promise.resolve(data);
157 });
158 }
159 }, {
160 key: 'whitelistOnlySet',
161 value: function whitelistOnlySet(mode) {
162 this.whitelistOnly = Boolean(mode);
163 return Promise.resolve();
164 }
165 }, {
166 key: 'whitelistOnlyGet',
167 value: function whitelistOnlyGet() {
168 return Promise.resolve(this.whitelistOnly);
169 }
170 }]);
171 return ListsStateMemory;
172}();
173
174// Implements room state API.
175
176
177var RoomStateMemory = function (_ListsStateMemory) {
178 (0, _inherits3.default)(RoomStateMemory, _ListsStateMemory);
179
180 function RoomStateMemory(server, name) {
181 (0, _classCallCheck3.default)(this, RoomStateMemory);
182
183 var _this6 = (0, _possibleConstructorReturn3.default)(this, (0, _getPrototypeOf2.default)(RoomStateMemory).call(this));
184
185 _this6.server = server;
186 _this6.name = name;
187 _this6.historyMaxGetMessages = _this6.server.historyMaxGetMessages;
188 _this6.historyMaxSize = _this6.server.historyMaxSize;
189 _this6.whitelist = new FastSet();
190 _this6.blacklist = new FastSet();
191 _this6.adminlist = new FastSet();
192 _this6.userlist = new FastSet();
193 _this6.messagesHistory = new List();
194 _this6.messagesTimestamps = new List();
195 _this6.messagesIds = new List();
196 _this6.usersseen = new FastMap();
197 _this6.lastMessageId = 0;
198 _this6.whitelistOnly = false;
199 _this6.owner = null;
200 return _this6;
201 }
202
203 (0, _createClass3.default)(RoomStateMemory, [{
204 key: 'initState',
205 value: function initState(state) {
206 state = state || {};
207 var _state = state;
208 var whitelist = _state.whitelist;
209 var blacklist = _state.blacklist;
210 var adminlist = _state.adminlist;
211 var whitelistOnly = _state.whitelistOnly;
212 var owner = _state.owner;
213 var historyMaxSize = _state.historyMaxSize;
214 var _state$enableAccessLi = _state.enableAccessListsUpdates;
215 var enableAccessListsUpdates = _state$enableAccessLi === undefined ? this.server.enableAccessListsUpdates : _state$enableAccessLi;
216 var _state$enableUserlist = _state.enableUserlistUpdates;
217 var enableUserlistUpdates = _state$enableUserlist === undefined ? this.server.enableUserlistUpdates : _state$enableUserlist;
218
219 _initState(this.whitelist, whitelist);
220 _initState(this.blacklist, blacklist);
221 _initState(this.adminlist, adminlist);
222 _initState(this.messagesHistory);
223 _initState(this.messagesTimestamps);
224 _initState(this.messagesIds);
225 _initState(this.usersseen);
226 this.whitelistOnly = Boolean(whitelistOnly);
227 this.enableAccessListsUpdates = Boolean(enableAccessListsUpdates);
228 this.enableUserlistUpdates = Boolean(enableUserlistUpdates);
229 this.owner = owner || null;
230 return this.historyMaxSizeSet(historyMaxSize);
231 }
232 }, {
233 key: 'removeState',
234 value: function removeState() {
235 return Promise.resolve();
236 }
237 }, {
238 key: 'startRemoving',
239 value: function startRemoving() {
240 return Promise.resolve();
241 }
242 }, {
243 key: 'hasList',
244 value: function hasList(listName) {
245 return listName === 'adminlist' || listName === 'whitelist' || listName === 'blacklist' || listName === 'userlist';
246 }
247 }, {
248 key: 'ownerGet',
249 value: function ownerGet() {
250 return Promise.resolve(this.owner);
251 }
252 }, {
253 key: 'ownerSet',
254 value: function ownerSet(owner) {
255 this.owner = owner;
256 return Promise.resolve();
257 }
258 }, {
259 key: 'accessListsUpdatesSet',
260 value: function accessListsUpdatesSet(enableAccessListsUpdates) {
261 this.enableAccessListsUpdates = Boolean(enableAccessListsUpdates);
262 return Promise.resolve();
263 }
264 }, {
265 key: 'accessListsUpdatesGet',
266 value: function accessListsUpdatesGet() {
267 return Promise.resolve(this.enableAccessListsUpdates);
268 }
269 }, {
270 key: 'userlistUpdatesSet',
271 value: function userlistUpdatesSet(enableUserlistUpdates) {
272 this.enableUserlistUpdates = Boolean(enableUserlistUpdates);
273 return Promise.resolve();
274 }
275 }, {
276 key: 'userlistUpdatesGet',
277 value: function userlistUpdatesGet() {
278 return Promise.resolve(this.enableUserlistUpdates);
279 }
280 }, {
281 key: 'historyMaxSizeSet',
282 value: function historyMaxSizeSet(historyMaxSize) {
283 if (_.isNumber(historyMaxSize) && historyMaxSize >= 0) {
284 this.historyMaxSize = historyMaxSize;
285 }
286 var limit = this.historyMaxSize;
287 this.messagesHistory = new List(this.messagesHistory.slice(0, limit));
288 this.messagesTimestamps = new List(this.messagesTimestamps.slice(0, limit));
289 this.messagesIds = new List(this.messagesIds.slice(0, limit));
290 return Promise.resolve();
291 }
292 }, {
293 key: 'historyInfo',
294 value: function historyInfo() {
295 var historySize = this.messagesHistory.length;
296 var info = {
297 historySize: historySize,
298 historyMaxSize: this.historyMaxSize,
299 historyMaxGetMessages: this.historyMaxGetMessages,
300 lastMessageId: this.lastMessageId
301 };
302 return Promise.resolve(info);
303 }
304 }, {
305 key: 'getCommonUsers',
306 value: function getCommonUsers() {
307 var nonWL = this.userlist.difference(this.whitelist);
308 var nonAdmin = nonWL.difference(this.adminlist);
309 var data = nonAdmin.toArray();
310 return Promise.resolve(data);
311 }
312 }, {
313 key: 'messageAdd',
314 value: function messageAdd(msg) {
315 var _this7 = this;
316
317 var timestamp = _.now();
318 this.lastMessageId++;
319 var makeResult = function makeResult() {
320 msg.timestamp = timestamp;
321 msg.id = _this7.lastMessageId;
322 return Promise.resolve(msg);
323 };
324 if (this.historyMaxSize <= 0) {
325 return makeResult();
326 }
327 this.messagesHistory.unshift(msg);
328 this.messagesTimestamps.unshift(timestamp);
329 this.messagesIds.unshift(this.lastMessageId);
330 if (this.messagesHistory.length > this.historyMaxSize) {
331 this.messagesHistory.pop();
332 this.messagesTimestamps.pop();
333 this.messagesIds.pop();
334 }
335 return makeResult();
336 }
337 }, {
338 key: 'messagesGetRecent',
339 value: function messagesGetRecent() {
340 var msgs = this.messagesHistory.slice(0, this.historyMaxGetMessages);
341 var tss = this.messagesTimestamps.slice(0, this.historyMaxGetMessages);
342 var ids = this.messagesIds.slice(0, this.historyMaxGetMessages);
343 var data = [];
344 for (var idx = 0; idx < msgs.length; idx++) {
345 var msg = msgs[idx];
346 var obj = _.cloneDeep(msg);
347 obj.timestamp = tss[idx];
348 obj.id = ids[idx];
349 data[idx] = obj;
350 }
351 return Promise.resolve(data);
352 }
353 }, {
354 key: 'messagesGet',
355 value: function messagesGet(id) {
356 var maxMessages = arguments.length <= 1 || arguments[1] === undefined ? this.historyMaxGetMessages : arguments[1];
357
358 if (maxMessages <= 0) {
359 return Promise.resolve([]);
360 }
361 id = _.max([0, id]);
362 var lastid = this.lastMessageId;
363 id = _.min([id, lastid]);
364 var end = lastid - id;
365 var len = _.min([maxMessages, end]);
366 var start = _.max([0, end - len]);
367 var msgs = this.messagesHistory.slice(start, end);
368 var tss = this.messagesTimestamps.slice(start, end);
369 var ids = this.messagesIds.slice(start, end);
370 var data = [];
371 for (var idx = 0; idx < msgs.length; idx++) {
372 var msg = msgs[idx];
373 var obj = _.cloneDeep(msg);
374 msg.timestamp = tss[idx];
375 msg.id = ids[idx];
376 data[idx] = obj;
377 }
378 return Promise.resolve(msgs);
379 }
380 }, {
381 key: 'userSeenGet',
382 value: function userSeenGet(userName) {
383 var joined = Boolean(this.userlist.get(userName));
384 var timestamp = this.usersseen.get(userName) || null;
385 return Promise.resolve({ joined: joined, timestamp: timestamp });
386 }
387 }, {
388 key: 'userSeenUpdate',
389 value: function userSeenUpdate(userName) {
390 var timestamp = _.now();
391 this.usersseen.set(userName, timestamp);
392 return Promise.resolve();
393 }
394 }]);
395 return RoomStateMemory;
396}(ListsStateMemory);
397
398// Implements direct messaging state API.
399
400
401var DirectMessagingStateMemory = function (_ListsStateMemory2) {
402 (0, _inherits3.default)(DirectMessagingStateMemory, _ListsStateMemory2);
403
404 function DirectMessagingStateMemory(server, userName) {
405 (0, _classCallCheck3.default)(this, DirectMessagingStateMemory);
406
407 var _this8 = (0, _possibleConstructorReturn3.default)(this, (0, _getPrototypeOf2.default)(DirectMessagingStateMemory).call(this));
408
409 _this8.server = server;
410 _this8.userName = userName;
411 _this8.whitelistOnly = false;
412 _this8.whitelist = new FastSet();
413 _this8.blacklist = new FastSet();
414 return _this8;
415 }
416
417 (0, _createClass3.default)(DirectMessagingStateMemory, [{
418 key: 'initState',
419 value: function initState(_ref) {
420 var whitelist = _ref.whitelist;
421 var blacklist = _ref.blacklist;
422 var whitelistOnly = _ref.whitelistOnly;
423
424 _initState(this.whitelist, whitelist);
425 _initState(this.blacklist, blacklist);
426 this.whitelistOnly = Boolean(whitelistOnly);
427 return Promise.resolve();
428 }
429 }, {
430 key: 'removeState',
431 value: function removeState() {
432 return Promise.resolve();
433 }
434 }, {
435 key: 'hasList',
436 value: function hasList(listName) {
437 return listName === 'whitelist' || listName === 'blacklist';
438 }
439 }]);
440 return DirectMessagingStateMemory;
441}(ListsStateMemory);
442
443// Implements user state API.
444
445
446var UserStateMemory = function () {
447 function UserStateMemory(server, userName) {
448 (0, _classCallCheck3.default)(this, UserStateMemory);
449
450 this.server = server;
451 this.userName = userName;
452 this.socketsToRooms = new FastMap();
453 this.socketsToInstances = new FastMap();
454 this.roomsToSockets = new FastMap();
455 this.locks = new FastMap();
456 mixin(this, LockOperations, this.locks);
457 }
458
459 (0, _createClass3.default)(UserStateMemory, [{
460 key: 'addSocket',
461 value: function addSocket(id, uid) {
462 var roomsset = new FastSet();
463 this.socketsToRooms.set(id, roomsset);
464 this.socketsToInstances.set(id, uid);
465 var nconnected = this.socketsToRooms.length;
466 return Promise.resolve(nconnected);
467 }
468 }, {
469 key: 'getAllSockets',
470 value: function getAllSockets() {
471 var sockets = this.socketsToRooms.keysArray();
472 return Promise.resolve(sockets);
473 }
474 }, {
475 key: 'getSocketsToInstance',
476 value: function getSocketsToInstance() {
477 var data = this.socketsToInstances.toObject();
478 return Promise.resolve(data);
479 }
480 }, {
481 key: 'getRoomToSockets',
482 value: function getRoomToSockets(roomName) {
483 var socketsset = this.roomsToSockets.get(roomName);
484 var data = socketsset && socketsset.toObject() || {};
485 return Promise.resolve(data);
486 }
487 }, {
488 key: 'getSocketsToRooms',
489 value: function getSocketsToRooms() {
490 var result = {};
491 var sockets = this.socketsToRooms.keysArray();
492 var _iteratorNormalCompletion = true;
493 var _didIteratorError = false;
494 var _iteratorError = undefined;
495
496 try {
497 for (var _iterator = (0, _getIterator3.default)(sockets), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
498 var id = _step.value;
499
500 var socketsset = this.socketsToRooms.get(id);
501 result[id] = socketsset && socketsset.toArray() || [];
502 }
503 } catch (err) {
504 _didIteratorError = true;
505 _iteratorError = err;
506 } finally {
507 try {
508 if (!_iteratorNormalCompletion && _iterator.return) {
509 _iterator.return();
510 }
511 } finally {
512 if (_didIteratorError) {
513 throw _iteratorError;
514 }
515 }
516 }
517
518 return Promise.resolve(result);
519 }
520 }, {
521 key: 'addSocketToRoom',
522 value: function addSocketToRoom(id, roomName) {
523 var roomsset = this.socketsToRooms.get(id);
524 var socketsset = this.roomsToSockets.get(roomName);
525 if (!socketsset) {
526 socketsset = new FastSet();
527 this.roomsToSockets.set(roomName, socketsset);
528 }
529 roomsset.add(roomName);
530 socketsset.add(id);
531 var njoined = socketsset.length;
532 return Promise.resolve(njoined);
533 }
534 }, {
535 key: 'removeSocketFromRoom',
536 value: function removeSocketFromRoom(id, roomName) {
537 var roomsset = this.socketsToRooms.get(id);
538 var socketsset = this.roomsToSockets.get(roomName);
539 var wasjoined = socketsset && socketsset.length || 0;
540 if (roomsset) {
541 roomsset.delete(roomName);
542 }
543 if (socketsset) {
544 socketsset.delete(id);
545 }
546 var njoined = 0;
547 if (wasjoined > 0) {
548 njoined = socketsset.length;
549 }
550 var hasChanged = njoined !== wasjoined;
551 return Promise.resolve([njoined, hasChanged]);
552 }
553 }, {
554 key: 'removeAllSocketsFromRoom',
555 value: function removeAllSocketsFromRoom(roomName) {
556 var sockets = this.socketsToRooms.keysArray();
557 var socketsset = this.roomsToSockets.get(roomName);
558 var removedSockets = socketsset && socketsset.toArray() || [];
559 var _iteratorNormalCompletion2 = true;
560 var _didIteratorError2 = false;
561 var _iteratorError2 = undefined;
562
563 try {
564 for (var _iterator2 = (0, _getIterator3.default)(removedSockets), _step2; !(_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done); _iteratorNormalCompletion2 = true) {
565 var id = _step2.value;
566
567 var roomsset = this.socketsToRooms.get(id);
568 roomsset.delete(roomName);
569 }
570 } catch (err) {
571 _didIteratorError2 = true;
572 _iteratorError2 = err;
573 } finally {
574 try {
575 if (!_iteratorNormalCompletion2 && _iterator2.return) {
576 _iterator2.return();
577 }
578 } finally {
579 if (_didIteratorError2) {
580 throw _iteratorError2;
581 }
582 }
583 }
584
585 if (socketsset) {
586 socketsset = socketsset.difference(sockets);
587 this.roomsToSockets.set(roomName, socketsset);
588 }
589 return Promise.resolve(removedSockets);
590 }
591 }, {
592 key: 'removeSocket',
593 value: function removeSocket(id) {
594 var roomsset = this.socketsToRooms.get(id);
595 var removedRooms = roomsset && roomsset.toArray() || [];
596 var joinedSockets = [];
597 for (var idx = 0; idx < removedRooms.length; idx++) {
598 var roomName = removedRooms[idx];
599 var socketsset = this.roomsToSockets.get(roomName);
600 socketsset.delete(id);
601 var njoined = socketsset.length;
602 joinedSockets[idx] = njoined;
603 }
604 this.socketsToRooms.delete(id);
605 this.socketsToInstances.delete(id);
606 var nconnected = this.socketsToRooms.length;
607 return Promise.resolve([removedRooms, joinedSockets, nconnected]);
608 }
609 }, {
610 key: 'lockToRoom',
611 value: function lockToRoom(roomName, ttl) {
612 var _this9 = this;
613
614 return uid(18).then(function (val) {
615 var start = _.now();
616 return _this9.lock(roomName, val, ttl).then(function () {
617 return Promise.resolve().disposer(function () {
618 if (start + ttl < _.now()) {
619 _this9.server.emit('lockTimeExceeded', val, { userName: _this9.userName, roomName: roomName });
620 }
621 return _this9.unlock(roomName, val);
622 });
623 });
624 });
625 }
626 }]);
627 return UserStateMemory;
628}();
629
630// Implements global state API.
631
632
633var MemoryState = function () {
634 function MemoryState(server, options) {
635 (0, _classCallCheck3.default)(this, MemoryState);
636
637 this.server = server;
638 this.options = options;
639 this.closed = false;
640 this.users = new FastMap();
641 this.rooms = new FastMap();
642 this.sockets = new FastMap();
643 this.RoomState = RoomStateMemory;
644 this.UserState = UserStateMemory;
645 this.DirectMessagingState = DirectMessagingStateMemory;
646 this.instanceUID = this.server.instanceUID;
647 this.heartbeatStamp = null;
648 this.lockTTL = this.options.lockTTL || 5000;
649 }
650
651 (0, _createClass3.default)(MemoryState, [{
652 key: 'close',
653 value: function close() {
654 this.closed = true;
655 return Promise.resolve();
656 }
657 }, {
658 key: 'getRoom',
659 value: function getRoom(name) {
660 var isPredicate = arguments.length <= 1 || arguments[1] === undefined ? false : arguments[1];
661
662 var room = this.rooms.get(name);
663 if (room) {
664 return Promise.resolve(room);
665 }
666 if (isPredicate) {
667 return Promise.resolve(null);
668 } else {
669 var error = new ChatServiceError('noRoom', name);
670 return Promise.reject(error);
671 }
672 }
673 }, {
674 key: 'addRoom',
675 value: function addRoom(name, state) {
676 var room = new Room(this.server, name);
677 if (!this.rooms.get(name)) {
678 this.rooms.set(name, room);
679 } else {
680 var error = new ChatServiceError('roomExists', name);
681 return Promise.reject(error);
682 }
683 return room.initState(state).return(room);
684 }
685 }, {
686 key: 'removeRoom',
687 value: function removeRoom(name) {
688 this.rooms.delete(name);
689 return Promise.resolve();
690 }
691 }, {
692 key: 'addSocket',
693 value: function addSocket(id, userName) {
694 this.sockets.set(id, userName);
695 return Promise.resolve();
696 }
697 }, {
698 key: 'removeSocket',
699 value: function removeSocket(id) {
700 this.sockets.delete(id);
701 return Promise.resolve();
702 }
703 }, {
704 key: 'getInstanceSockets',
705 value: function getInstanceSockets() {
706 var uid = arguments.length <= 0 || arguments[0] === undefined ? this.instanceUID : arguments[0];
707
708 return Promise.resolve(this.sockets.toObject());
709 }
710 }, {
711 key: 'updateHeartbeat',
712 value: function updateHeartbeat() {
713 this.heartbeatStamp = _.now();
714 return Promise.resolve();
715 }
716 }, {
717 key: 'getInstanceHeartbeat',
718 value: function getInstanceHeartbeat() {
719 var uid = arguments.length <= 0 || arguments[0] === undefined ? this.instanceUID : arguments[0];
720
721 if (uid !== this.instanceUID) {
722 return Promise.resolve(null);
723 }
724 return Promise.resolve(this.heartbeatStamp);
725 }
726 }, {
727 key: 'getOrAddUser',
728 value: function getOrAddUser(name, state) {
729 var user = this.users.get(name);
730 if (user) {
731 return Promise.resolve(user);
732 }
733 return this.addUser(name, state);
734 }
735 }, {
736 key: 'getUser',
737 value: function getUser(name) {
738 var isPredicate = arguments.length <= 1 || arguments[1] === undefined ? false : arguments[1];
739
740 var user = this.users.get(name);
741 if (user) {
742 return Promise.resolve(user);
743 }
744 if (isPredicate) {
745 return Promise.resolve(null);
746 } else {
747 var error = new ChatServiceError('noUser', name);
748 return Promise.reject(error);
749 }
750 }
751 }, {
752 key: 'addUser',
753 value: function addUser(name, state) {
754 var user = this.users.get(name);
755 if (user) {
756 var error = new ChatServiceError('userExists', name);
757 return Promise.reject(error);
758 }
759 user = new User(this.server, name);
760 this.users.set(name, user);
761 if (state) {
762 return user.initState(state).return(user);
763 } else {
764 return Promise.resolve(user);
765 }
766 }
767 }, {
768 key: 'removeUser',
769 value: function removeUser(name) {
770 this.users.delete(name);
771 return Promise.resolve();
772 }
773 }]);
774 return MemoryState;
775}();
776
777module.exports = MemoryState;
778//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uL3NyYy9NZW1vcnlTdGF0ZS5qcyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQUVBLElBQU0sbUJBQW1CLFFBQVEsb0JBQVIsQ0FBekI7QUFDQSxJQUFNLFVBQVUsUUFBUSxzQkFBUixDQUFoQjtBQUNBLElBQU0sVUFBVSxRQUFRLHNCQUFSLENBQWhCO0FBQ0EsSUFBTSxPQUFPLFFBQVEsa0JBQVIsQ0FBYjtBQUNBLElBQU0sVUFBVSxRQUFRLFVBQVIsQ0FBaEI7QUFDQSxJQUFNLE9BQU8sUUFBUSxRQUFSLENBQWI7QUFDQSxJQUFNLE9BQU8sUUFBUSxRQUFSLENBQWI7QUFDQSxJQUFNLElBQUksUUFBUSxRQUFSLENBQVY7QUFDQSxJQUFNLGVBQWUsUUFBUSxlQUFSLENBQXJCO0FBQ0EsSUFBTSxNQUFNLFFBQVEsVUFBUixDQUFaOztlQUNrQixRQUFRLFdBQVIsQzs7SUFBVixLLFlBQUEsSzs7O0FBRVIsU0FBUyxVQUFULENBQW9CLEtBQXBCLEVBQTJCLE1BQTNCLEVBQW1DO0FBQ2pDLFFBQU0sS0FBTjtBQUNBLE1BQUksQ0FBQyxNQUFMLEVBQWE7QUFDWCxXQUFPLFFBQVEsT0FBUixFQUFQO0FBQ0QsR0FGRCxNQUVPO0FBQ0wsV0FBTyxNQUFNLE9BQU4sQ0FBYyxNQUFkLENBQVA7QUFDRDtBQUNGOztBQUVEO0FBQ0E7O0lBQ00sYztBQUVKLDBCQUFhLEtBQWIsRUFBb0I7QUFBQTs7QUFDbEIsU0FBSyxLQUFMLEdBQWEsS0FBYjtBQUNEOzs7O3lCQUVLLEcsRUFBSyxHLEVBQUssRyxFQUFLO0FBQUE7O0FBQ25CLGFBQU8sYUFDTCxFQUFDLFlBQVksR0FBYixFQUFrQixTQUFTLEVBQTNCLEVBQStCLFFBQVEsR0FBdkMsRUFBNEMsV0FBVyxJQUF2RCxFQURLLEVBRUwsVUFBQyxLQUFELEVBQVEsQ0FBUixFQUFjO0FBQ1osWUFBSSxNQUFLLEtBQUwsQ0FBVyxHQUFYLENBQWUsR0FBZixDQUFKLEVB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O0FBQ0QsYUFBTyxJQUFJLElBQUosQ0FBUyxLQUFLLE1BQWQsRUFBc0IsSUFBdEIsQ0FBUDtBQUNBLFdBQUssS0FBTCxDQUFXLEdBQVgsQ0FBZSxJQUFmLEVBQXFCLElBQXJCO0FBQ0EsVUFBSSxLQUFKLEVBQVc7QUFDVCxlQUFPLEtBQUssU0FBTCxDQUFlLEtBQWYsRUFBc0IsTUFBdEIsQ0FBNkIsSUFBN0IsQ0FBUDtBQUNELE9BRkQsTUFFTztBQUNMLGVBQU8sUUFBUSxPQUFSLENBQWdCLElBQWhCLENBQVA7QUFDRDtBQUNGOzs7K0JBRVcsSSxFQUFNO0FBQ2hCLFdBQUssS0FBTCxDQUFXLE1BQVgsQ0FBa0IsSUFBbEI7QUFDQSxhQUFPLFFBQVEsT0FBUixFQUFQO0FBQ0Q7Ozs7O0FBR0gsT0FBTyxPQUFQLEdBQWlCLFdBQWpCIiwiZmlsZSI6Ik1lbW9yeVN0YXRlLmpzIiwic291cmNlc0NvbnRlbnQiOlsiJ3VzZSBzdHJpY3QnXG5cbmNvbnN0IENoYXRTZXJ2aWNlRXJyb3IgPSByZXF1aXJlKCcuL0NoYXRTZXJ2aWNlRXJyb3InKVxuY29uc3QgRmFzdE1hcCA9IHJlcXVpcmUoJ2NvbGxlY3Rpb25zL2Zhc3QtbWFwJylcbmNvbnN0IEZhc3RTZXQgPSByZXF1aXJlKCdjb2xsZWN0aW9ucy9mYXN0LXNldCcpXG5jb25zdCBMaXN0ID0gcmVxdWlyZSgnY29sbGVjdGlvbnMvbGlzdCcpXG5jb25zdCBQcm9taXNlID0gcmVxdWlyZSgnYmx1ZWJpcmQnKVxuY29uc3QgUm9vbSA9IHJlcXVpcmUoJy4vUm9vbScpXG5jb25zdCBVc2VyID0gcmVxdWlyZSgnLi9Vc2VyJylcbmNvbnN0IF8gPSByZXF1aXJlKCdsb2Rhc2gnKVxuY29uc3QgcHJvbWlzZVJldHJ5ID0gcmVxdWlyZSgncHJvbWlzZS1yZXRyeScpXG5jb25zdCB1aWQgPSByZXF1aXJlKCd1aWQtc2FmZScpXG5jb25zdCB7IG1peGluIH0gPSByZXF1aXJlKCdlczYtbWl4aW4nKVxuXG5mdW5jdGlvbiBpbml0U3RhdGUgKHN0YXRlLCB2YWx1ZXMpIHtcbiAgc3RhdGUuY2xlYXIoKVxuICBpZiAoIXZhbHVlcykge1xuICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUoKVxuICB9IGVsc2Uge1xuICAgIHJldHVybiBzdGF0ZS5hZGRFYWNoKHZhbHVlcylcbiAgfVxufVxuXG4vLyBNZW1vcnkgbG9jayBvcGVyYXRpb25zLlxuLy8gQG1peGluXG5jbGFzcyBMb2NrT3BlcmF0aW9ucyB7XG5cbiAgY29uc3RydWN0b3IgKGxvY2tzKSB7XG4gICAgdGhpcy5sb2NrcyA9IGxvY2tzXG4gIH1cblxuICBsb2NrIChrZXksIHZhbCwgdHRsKSB7XG4gICAgcmV0dXJuIHByb21pc2VSZXRyeShcbiAgICAgIHttaW5UaW1lb3V0OiAxMDAsIHJldHJpZXM6IDEwLCBmYWN0b3I6IDEuNSwgcmFuZG9taXplOiB0cnVlfSxcbiAgICAgIChyZXRyeSwgbikgPT4ge1xuICAgICAgICBpZiAodGhpcy5sb2Nrcy5oYXMoa2V5KSkge1xuICAgICAgICAgIGxldCBlcnIgPSBuZXcgQ2hhdFNlcnZpY2VFcnJvcigndGltZW91dCcpXG4gICAgICAgICAgcmV0dXJuIHJldHJ5KGVycilcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICB0aGlzLmxvY2tzLnNldChrZXksIHZhbClcbiAgICAgICAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKClcbiAgICAgICAgfVxuICAgICAgfVxuICAgIClcbiAgfVxuXG4gIHVubG9jayAoa2V5LCB2YWwpIHtcbiAgICBsZXQgY3VycmVudFZhbCA9IHRoaXMubG9ja3MuZ2V0KGtleSlcbiAgICBpZiAoY3VycmVudFZhbCA9PT0gdmFsKSB7XG4gICAgICB0aGlzLmxvY2tzLmRlbGV0ZShrZXkpXG4gICAgfVxuICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUoKVxuICB9XG5cbn1cblxuLy8gSW1wbGVtZW50cyBzdGF0ZSBBUEkgbGlzdHMgbWFuYWdlbWVudC5cbmNsYXNzIExpc3RzU3RhdGVNZW1vcnkge1xuXG4gIGNoZWNrTGlzdCAobGlzdE5hbWUsIG51bSwgbGltaXQpIHtcbiAgICBpZiAoIXRoaXMuaGFzTGlzdChsaXN0TmFtZSkpIHtcbiAgICAgIGxldCBlcnJvciA9IG5ldyBDaGF0U2VydmljZUVycm9yKCdub0xpc3QnLCBsaXN0TmFtZSlcbiAgICAgIHJldHVybiBQcm9taXNlLnJlamVjdChlcnJvcilcbiAgICB9XG4gICAgaWYgKGxpc3ROYW1lID09PSAndXNlcmxpc3QnKSB7XG4gICAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKClcbiAgICB9XG4gICAgaWYgKHRoaXNbbGlzdE5hbWVdLmxlbmd0aCArIG51bSA+IGxpbWl0KSB7XG4gICAgICBsZXQgZXJyb3IgPSBuZXcgQ2hhdFNlcnZpY2VFcnJvcignbGlzdExpbWl0RXhjZWVkZWQnLCBsaXN0TmFtZSlcbiAgICAgIHJldHVybiBQcm9taXNlLnJlamVjdChlcnJvcilcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZSgpXG4gICAgfVxuICB9XG5cbiAgYWRkVG9MaXN0IChsaXN0TmFtZSwgZWxlbXMsIGxpbWl0KSB7XG4gICAgbGV0IG51bSA9IGVsZW1zLmxlbmd0aFxuICAgIHJldHVybiB0aGlzLmNoZWNrTGlzdChsaXN0TmFtZSwgbnVtLCBsaW1pdCkudGhlbigoKSA9PiB7XG4gICAgICB0aGlzW2xpc3ROYW1lXS5hZGRFYWNoKGVsZW1zKVxuICAgICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZSgpXG4gICAgfSlcbiAgfVxuXG4gIHJlbW92ZUZyb21MaXN0IChsaXN0TmFtZSwgZWxlbXMpIHtcbiAgICByZXR1cm4gdGhpcy5jaGVja0xpc3QobGlzdE5hbWUpLnRoZW4oKCkgPT4ge1xuICAgICAgdGhpc1tsaXN0TmFtZV0uZGVsZXRlRWFjaChlbGVtcylcbiAgICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUoKVxuICAgIH0pXG4gIH1cblxuICBnZXRMaXN0IChsaXN0TmFtZSkge1xuICAgIHJldHVybiB0aGlzLmNoZWNrTGlzdChsaXN0TmFtZSkudGhlbigoKSA9PiB7XG4gICAgICBsZXQgZGF0YSA9IHRoaXNbbGlzdE5hbWVdLnRvQXJyYXkoKVxuICAgICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZShkYXRhKVxuICAgIH0pXG4gIH1cblxuICBoYXNJbkxpc3QgKGxpc3ROYW1lLCBlbGVtKSB7XG4gICAgcmV0dXJuIHRoaXMuY2hlY2tMaXN0KGxpc3ROYW1lKS50aGVuKCgpID0+IHtcbiAgICAgIGxldCBkYXRhID0gdGhpc1tsaXN0TmFtZV0uaGFzKGVsZW0pXG4gICAgICBkYXRhID0gQm9vbGVhbihkYXRhKVxuICAgICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZShkYXRhKVxuICAgIH0pXG4gIH1cblxuICB3aGl0ZWxpc3RPbmx5U2V0IChtb2RlKSB7XG4gICAgdGhpcy53aGl0ZWxpc3RPbmx5ID0gQm9vbGVhbihtb2RlKVxuICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUoKVxuICB9XG5cbiAgd2hpdGVsaXN0T25seUdldCAoKSB7XG4gICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZSh0aGlzLndoaXRlbGlzdE9ubHkpXG4gIH1cblxufVxuXG4vLyBJbXBsZW1lbnRzIHJvb20gc3RhdGUgQVBJLlxuY2xhc3MgUm9vbVN0YXRlTWVtb3J5IGV4dGVuZHMgTGlzdHNTdGF0ZU1lbW9yeSB7XG5cbiAgY29uc3RydWN0b3IgKHNlcnZlciwgbmFtZSkge1xuICAgIHN1cGVyKClcbiAgICB0aGlzLnNlcnZlciA9IHNlcnZlclxuICAgIHRoaXMubmFtZSA9IG5hbWVcbiAgICB0aGlzLmhpc3RvcnlNYXhHZXRNZXNzYWdlcyA9IHRoaXMuc2VydmVyLmhpc3RvcnlNYXhHZXRNZXNzYWdlc1xuICAgIHRoaXMuaGlzdG9yeU1heFNpemUgPSB0aGlzLnNlcnZlci5oaXN0b3J5TWF4U2l6ZVxuICAgIHRoaXMud2hpdGVsaXN0ID0gbmV3IEZhc3RTZXQoKVxuICAgIHRoaXMuYmxhY2tsaXN0ID0gbmV3IEZhc3RTZXQoKVxuICAgIHRoaXMuYWRtaW5saXN0ID0gbmV3IEZhc3RTZXQoKVxuICAgIHRoaXMudXNlcmxpc3QgPSBuZXcgRmFzdFNldCgpXG4gICAgdGhpcy5tZXNzYWdlc0hpc3RvcnkgPSBuZXcgTGlzdCgpXG4gICAgdGhpcy5tZXNzYWdlc1RpbWVzdGFtcHMgPSBuZXcgTGlzdCgpXG4gICAgdGhpcy5tZXNzYWdlc0lkcyA9IG5ldyBMaXN0KClcbiAgICB0aGlzLnVzZXJzc2VlbiA9IG5ldyBGYXN0TWFwKClcbiAgICB0aGlzLmxhc3RNZXNzYWdlSWQgPSAwXG4gICAgdGhpcy53aGl0ZWxpc3RPbmx5ID0gZmFsc2VcbiAgICB0aGlzLm93bmVyID0gbnVsbFxuICB9XG5cbiAgaW5pdFN0YXRlIChzdGF0ZSkge1xuICAgIHN0YXRlID0gc3RhdGUgfHwge31cbiAgICBsZXQgeyB3aGl0ZWxpc3QsIGJsYWNrbGlzdCwgYWRtaW5saXN0LFxuICAgICAgICAgIHdoaXRlbGlzdE9ubHksIG93bmVyLCBoaXN0b3J5TWF4U2l6ZSxcbiAgICAgICAgICBlbmFibGVBY2Nlc3NMaXN0c1VwZGF0ZXMgPSB0aGlzLnNlcnZlci5lbmFibGVBY2Nlc3NMaXN0c1VwZGF0ZXMsXG4gICAgICAgICAgZW5hYmxlVXNlcmxpc3RVcGRhdGVzID0gdGhpcy5zZXJ2ZXIuZW5hYmxlVXNlcmxpc3RVcGRhdGVzXG4gICAgICAgIH0gPSBzdGF0ZVxuICAgIGluaXRTdGF0ZSh0aGlzLndoaXRlbGlzdCwgd2hpdGVsaXN0KVxuICAgIGluaXRTdGF0ZSh0aGlzLmJsYWNrbGlzdCwgYmxhY2tsaXN0KVxuICAgIGluaXRTdGF0ZSh0aGlzLmFkbWlubGlzdCwgYWRtaW5saXN0KVxuICAgIGluaXRTdGF0ZSh0aGlzLm1lc3NhZ2VzSGlzdG9yeSlcbiAgICBpbml0U3RhdGUodGhpcy5tZXNzYWdlc1RpbWVzdGFtcHMpXG4gICAgaW5pdFN0YXRlKHRoaXMubWVzc2FnZXNJZHMpXG4gICAgaW5pdFN0YXRlKHRoaXMudXNlcnNzZWVuKVxuICAgIHRoaXMud2hpdGVsaXN0T25seSA9IEJvb2xlYW4od2hpdGVsaXN0T25seSlcbiAgICB0aGlzLmVuYWJsZUFjY2Vzc0xpc3RzVXBkYXRlcyA9IEJvb2xlYW4oZW5hYmxlQWNjZXNzTGlzdHNVcGRhdGVzKVxuICAgIHRoaXMuZW5hYmxlVXNlcmxpc3RVcGRhdGVzID0gQm9vbGVhbihlbmFibGVVc2VybGlzdFVwZGF0ZXMpXG4gICAgdGhpcy5vd25lciA9IG93bmVyIHx8IG51bGxcbiAgICByZXR1cm4gdGhpcy5oaXN0b3J5TWF4U2l6ZVNldChoaXN0b3J5TWF4U2l6ZSlcbiAgfVxuXG4gIHJlbW92ZVN0YXRlICgpIHtcbiAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKClcbiAgfVxuXG4gIHN0YXJ0UmVtb3ZpbmcgKCkge1xuICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUoKVxuICB9XG5cbiAgaGFzTGlzdCAobGlzdE5hbWUpIHtcbiAgICByZXR1cm4gbGlzdE5hbWUgPT09ICdhZG1pbmxpc3QnIHx8IGxpc3ROYW1lID09PSAnd2hpdGVsaXN0JyB8fFxuICAgICAgbGlzdE5hbWUgPT09ICdibGFja2xpc3QnIHx8IGxpc3ROYW1lID09PSAndXNlcmxpc3QnXG4gIH1cblxuICBvd25lckdldCAoKSB7XG4gICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZSh0aGlzLm93bmVyKVxuICB9XG5cbiAgb3duZXJTZXQgKG93bmVyKSB7XG4gICAgdGhpcy5vd25lciA9IG93bmVyXG4gICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZSgpXG4gIH1cblxuICBhY2Nlc3NMaXN0c1VwZGF0ZXNTZXQgKGVuYWJsZUFjY2Vzc0xpc3RzVXBkYXRlcykge1xuICAgIHRoaXMuZW5hYmxlQWNjZXNzTGlzdHNVcGRhdGVzID0gQm9vbGVhbihlbmFibGVBY2Nlc3NMaXN0c1VwZGF0ZXMpXG4gICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZSgpXG4gIH1cblxuICBhY2Nlc3NMaXN0c1VwZGF0ZXNHZXQgKCkge1xuICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUodGhpcy5lbmFibGVBY2Nlc3NMaXN0c1VwZGF0ZXMpXG4gIH1cblxuICB1c2VybGlzdFVwZGF0ZXNTZXQgKGVuYWJsZVVzZXJsaXN0VXBkYXRlcykge1xuICAgIHRoaXMuZW5hYmxlVXNlcmxpc3RVcGRhdGVzID0gQm9vbGVhbihlbmFibGVVc2VybGlzdFVwZGF0ZXMpXG4gICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZSgpXG4gIH1cblxuICB1c2VybGlzdFVwZGF0ZXNHZXQgKCkge1xuICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUodGhpcy5lbmFibGVVc2VybGlzdFVwZGF0ZXMpXG4gIH1cblxuICBoaXN0b3J5TWF4U2l6ZVNldCAoaGlzdG9yeU1heFNpemUpIHtcbiAgICBpZiAoXy5pc051bWJlcihoaXN0b3J5TWF4U2l6ZSkgJiYgaGlzdG9yeU1heFNpemUgPj0gMCkge1xuICAgICAgdGhpcy5oaXN0b3J5TWF4U2l6ZSA9IGhpc3RvcnlNYXhTaXplXG4gICAgfVxuICAgIGxldCBsaW1pdCA9IHRoaXMuaGlzdG9yeU1heFNpemVcbiAgICB0aGlzLm1lc3NhZ2VzSGlzdG9yeSA9IG5ldyBMaXN0KHRoaXMubWVzc2FnZXNIaXN0b3J5LnNsaWNlKDAsIGxpbWl0KSlcbiAgICB0aGlzLm1lc3NhZ2VzVGltZXN0YW1wcyA9IG5ldyBMaXN0KHRoaXMubWVzc2FnZXNUaW1lc3RhbXBzLnNsaWNlKDAsIGxpbWl0KSlcbiAgICB0aGlzLm1lc3NhZ2VzSWRzID0gbmV3IExpc3QodGhpcy5tZXNzYWdlc0lkcy5zbGljZSgwLCBsaW1pdCkpXG4gICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZSgpXG4gIH1cblxuICBoaXN0b3J5SW5mbyAoKSB7XG4gICAgbGV0IGhpc3RvcnlTaXplID0gdGhpcy5tZXNzYWdlc0hpc3RvcnkubGVuZ3RoXG4gICAgbGV0IGluZm8gPSB7XG4gICAgICBoaXN0b3J5U2l6ZSxcbiAgICAgIGhpc3RvcnlNYXhTaXplOiB0aGlzLmhpc3RvcnlNYXhTaXplLFxuICAgICAgaGlzdG9yeU1heEdldE1lc3NhZ2VzOiB0aGlzLmhpc3RvcnlNYXhHZXRNZXNzYWdlcyxcbiAgICAgIGxhc3RNZXNzYWdlSWQ6IHRoaXMubGFzdE1lc3NhZ2VJZFxuICAgIH1cbiAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKGluZm8pXG4gIH1cblxuICBnZXRDb21tb25Vc2VycyAoKSB7XG4gICAgbGV0IG5vbldMID0gdGhpcy51c2VybGlzdC5kaWZmZXJlbmNlKHRoaXMud2hpdGVsaXN0KVxuICAgIGxldCBub25BZG1pbiA9IG5vbldMLmRpZmZlcmVuY2UodGhpcy5hZG1pbmxpc3QpXG4gICAgbGV0IGRhdGEgPSBub25BZG1pbi50b0FycmF5KClcbiAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKGRhdGEpXG4gIH1cblxuICBtZXNzYWdlQWRkIChtc2cpIHtcbiAgICBsZXQgdGltZXN0YW1wID0gXy5ub3coKVxuICAgIHRoaXMubGFzdE1lc3NhZ2VJZCsrXG4gICAgbGV0IG1ha2VSZXN1bHQgPSAoKSA9PiB7XG4gICAgICBtc2cudGltZXN0YW1wID0gdGltZXN0YW1wXG4gICAgICBtc2cuaWQgPSB0aGlzLmxhc3RNZXNzYWdlSWRcbiAgICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUobXNnKVxuICAgIH1cbiAgICBpZiAodGhpcy5oaXN0b3J5TWF4U2l6ZSA8PSAwKSB7XG4gICAgICByZXR1cm4gbWFrZVJlc3VsdCgpXG4gICAgfVxuICAgIHRoaXMubWVzc2FnZXNIaXN0b3J5LnVuc2hpZnQobXNnKVxuICAgIHRoaXMubWVzc2FnZXNUaW1lc3RhbXBzLnVuc2hpZnQodGltZXN0YW1wKVxuICAgIHRoaXMubWVzc2FnZXNJZHMudW5zaGlmdCh0aGlzLmxhc3RNZXNzYWdlSWQpXG4gICAgaWYgKHRoaXMubWVzc2FnZXNIaXN0b3J5Lmxlbmd0aCA+IHRoaXMuaGlzdG9yeU1heFNpemUpIHtcbiAgICAgIHRoaXMubWVzc2FnZXNIaXN0b3J5LnBvcCgpXG4gICAgICB0aGlzLm1lc3NhZ2VzVGltZXN0YW1wcy5wb3AoKVxuICAgICAgdGhpcy5tZXNzYWdlc0lkcy5wb3AoKVxuICAgIH1cbiAgICByZXR1cm4gbWFrZVJlc3VsdCgpXG4gIH1cblxuICBtZXNzYWdlc0dldFJlY2VudCAoKSB7XG4gICAgbGV0IG1zZ3MgPSB0aGlzLm1lc3NhZ2VzSGlzdG9yeS5zbGljZSgwLCB0aGlzLmhpc3RvcnlNYXhHZXRNZXNzYWdlcylcbiAgICBsZXQgdHNzID0gdGhpcy5tZXNzYWdlc1RpbWVzdGFtcHMuc2xpY2UoMCwgdGhpcy5oaXN0b3J5TWF4R2V0TWVzc2FnZXMpXG4gICAgbGV0IGlkcyA9IHRoaXMubWVzc2FnZXNJZHMuc2xpY2UoMCwgdGhpcy5oaXN0b3J5TWF4R2V0TWVzc2FnZXMpXG4gICAgbGV0IGRhdGEgPSBbXVxuICAgIGZvciAobGV0IGlkeCA9IDA7IGlkeCA8IG1zZ3MubGVuZ3RoOyBpZHgrKykge1xuICAgICAgbGV0IG1zZyA9IG1zZ3NbaWR4XVxuICAgICAgbGV0IG9iaiA9IF8uY2xvbmVEZWVwKG1zZylcbiAgICAgIG9iai50aW1lc3RhbXAgPSB0c3NbaWR4XVxuICAgICAgb2JqLmlkID0gaWRzW2lkeF1cbiAgICAgIGRhdGFbaWR4XSA9IG9ialxuICAgIH1cbiAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKGRhdGEpXG4gIH1cblxuICBtZXNzYWdlc0dldCAoaWQsIG1heE1lc3NhZ2VzID0gdGhpcy5oaXN0b3J5TWF4R2V0TWVzc2FnZXMpIHtcbiAgICBpZiAobWF4TWVzc2FnZXMgPD0gMCkgeyByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKFtdKSB9XG4gICAgaWQgPSBfLm1heChbMCwgaWRdKVxuICAgIGxldCBsYXN0aWQgPSB0aGlzLmxhc3RNZXNzYWdlSWRcbiAgICBpZCA9IF8ubWluKFsgaWQsIGxhc3RpZCBdKVxuICAgIGxldCBlbmQgPSBsYXN0aWQgLSBpZFxuICAgIGxldCBsZW4gPSBfLm1pbihbIG1heE1lc3NhZ2VzLCBlbmQgXSlcbiAgICBsZXQgc3RhcnQgPSBfLm1heChbIDAsIGVuZCAtIGxlbiBdKVxuICAgIGxldCBtc2dzID0gdGhpcy5tZXNzYWdlc0hpc3Rvcnkuc2xpY2Uoc3RhcnQsIGVuZClcbiAgICBsZXQgdHNzID0gdGhpcy5tZXNzYWdlc1RpbWVzdGFtcHMuc2xpY2Uoc3RhcnQsIGVuZClcbiAgICBsZXQgaWRzID0gdGhpcy5tZXNzYWdlc0lkcy5zbGljZShzdGFydCwgZW5kKVxuICAgIGxldCBkYXRhID0gW11cbiAgICBmb3IgKGxldCBpZHggPSAwOyBpZHggPCBtc2dzLmxlbmd0aDsgaWR4KyspIHtcbiAgICAgIGxldCBtc2cgPSBtc2dzW2lkeF1cbiAgICAgIGxldCBvYmogPSBfLmNsb25lRGVlcChtc2cpXG4gICAgICBtc2cudGltZXN0YW1wID0gdHNzW2lkeF1cbiAgICAgIG1zZy5pZCA9IGlkc1tpZHhdXG4gICAgICBkYXRhW2lkeF0gPSBvYmpcbiAgICB9XG4gICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZShtc2dzKVxuICB9XG5cbiAgdXNlclNlZW5HZXQgKHVzZXJOYW1lKSB7XG4gICAgbGV0IGpvaW5lZCA9IEJvb2xlYW4odGhpcy51c2VybGlzdC5nZXQodXNlck5hbWUpKVxuICAgIGxldCB0aW1lc3RhbXAgPSB0aGlzLnVzZXJzc2Vlbi5nZXQodXNlck5hbWUpIHx8IG51bGxcbiAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKHtqb2luZWQsIHRpbWVzdGFtcH0pXG4gIH1cblxuICB1c2VyU2VlblVwZGF0ZSAodXNlck5hbWUpIHtcbiAgICBsZXQgdGltZXN0YW1wID0gXy5ub3coKVxuICAgIHRoaXMudXNlcnNzZWVuLnNldCh1c2VyTmFtZSwgdGltZXN0YW1wKVxuICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUoKVxuICB9XG5cbn1cblxuLy8gSW1wbGVtZW50cyBkaXJlY3QgbWVzc2FnaW5nIHN0YXRlIEFQSS5cbmNsYXNzIERpcmVjdE1lc3NhZ2luZ1N0YXRlTWVtb3J5IGV4dGVuZHMgTGlzdHNTdGF0ZU1lbW9yeSB7XG5cbiAgY29uc3RydWN0b3IgKHNlcnZlciwgdXNlck5hbWUpIHtcbiAgICBzdXBlcigpXG4gICAgdGhpcy5zZXJ2ZXIgPSBzZXJ2ZXJcbiAgICB0aGlzLnVzZXJOYW1lID0gdXNlck5hbWVcbiAgICB0aGlzLndoaXRlbGlzdE9ubHkgPSBmYWxzZVxuICAgIHRoaXMud2hpdGVsaXN0ID0gbmV3IEZhc3RTZXQoKVxuICAgIHRoaXMuYmxhY2tsaXN0ID0gbmV3IEZhc3RTZXQoKVxuICB9XG5cbiAgaW5pdFN0YXRlICh7IHdoaXRlbGlzdCwgYmxhY2tsaXN0LCB3aGl0ZWxpc3RPbmx5IH0pIHtcbiAgICBpbml0U3RhdGUodGhpcy53aGl0ZWxpc3QsIHdoaXRlbGlzdClcbiAgICBpbml0U3RhdGUodGhpcy5ibGFja2xpc3QsIGJsYWNrbGlzdClcbiAgICB0aGlzLndoaXRlbGlzdE9ubHkgPSBCb29sZWFuKHdoaXRlbGlzdE9ubHkpXG4gICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZSgpXG4gIH1cblxuICByZW1vdmVTdGF0ZSAoKSB7XG4gICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZSgpXG4gIH1cblxuICBoYXNMaXN0IChsaXN0TmFtZSkge1xuICAgIHJldHVybiBsaXN0TmFtZSA9PT0gJ3doaXRlbGlzdCcgfHwgbGlzdE5hbWUgPT09ICdibGFja2xpc3QnXG4gIH1cblxufVxuXG4vLyBJbXBsZW1lbnRzIHVzZXIgc3RhdGUgQVBJLlxuY2xhc3MgVXNlclN0YXRlTWVtb3J5IHtcblxuICBjb25zdHJ1Y3RvciAoc2VydmVyLCB1c2VyTmFtZSkge1xuICAgIHRoaXMuc2VydmVyID0gc2VydmVyXG4gICAgdGhpcy51c2VyTmFtZSA9IHVzZXJOYW1lXG4gICAgdGhpcy5zb2NrZXRzVG9Sb29tcyA9IG5ldyBGYXN0TWFwKClcbiAgICB0aGlzLnNvY2tldHNUb0luc3RhbmNlcyA9IG5ldyBGYXN0TWFwKClcbiAgICB0aGlzLnJvb21zVG9Tb2NrZXRzID0gbmV3IEZhc3RNYXAoKVxuICAgIHRoaXMubG9ja3MgPSBuZXcgRmFzdE1hcCgpXG4gICAgbWl4aW4odGhpcywgTG9ja09wZXJhdGlvbnMsIHRoaXMubG9ja3MpXG4gIH1cblxuICBhZGRTb2NrZXQgKGlkLCB1aWQpIHtcbiAgICBsZXQgcm9vbXNzZXQgPSBuZXcgRmFzdFNldCgpXG4gICAgdGhpcy5zb2NrZXRzVG9Sb29tcy5zZXQoaWQsIHJvb21zc2V0KVxuICAgIHRoaXMuc29ja2V0c1RvSW5zdGFuY2VzLnNldChpZCwgdWlkKVxuICAgIGxldCBuY29ubmVjdGVkID0gdGhpcy5zb2NrZXRzVG9Sb29tcy5sZW5ndGhcbiAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKG5jb25uZWN0ZWQpXG4gIH1cblxuICBnZXRBbGxTb2NrZXRzICgpIHtcbiAgICBsZXQgc29ja2V0cyA9IHRoaXMuc29ja2V0c1RvUm9vbXMua2V5c0FycmF5KClcbiAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKHNvY2tldHMpXG4gIH1cblxuICBnZXRTb2NrZXRzVG9JbnN0YW5jZSAoKSB7XG4gICAgbGV0IGRhdGEgPSB0aGlzLnNvY2tldHNUb0luc3RhbmNlcy50b09iamVjdCgpXG4gICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZShkYXRhKVxuICB9XG5cbiAgZ2V0Um9vbVRvU29ja2V0cyAocm9vbU5hbWUpIHtcbiAgICBsZXQgc29ja2V0c3NldCA9IHRoaXMucm9vbXNUb1NvY2tldHMuZ2V0KHJvb21OYW1lKVxuICAgIGxldCBkYXRhID0gKHNvY2tldHNzZXQgJiYgc29ja2V0c3NldC50b09iamVjdCgpKSB8fCB7fVxuICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUoZGF0YSlcbiAgfVxuXG4gIGdldFNvY2tldHNUb1Jvb21zICgpIHtcbiAgICBsZXQgcmVzdWx0ID0ge31cbiAgICBsZXQgc29ja2V0cyA9IHRoaXMuc29ja2V0c1RvUm9vbXMua2V5c0FycmF5KClcbiAgICBmb3IgKGxldCBpZCBvZiBzb2NrZXRzKSB7XG4gICAgICBsZXQgc29ja2V0c3NldCA9IHRoaXMuc29ja2V0c1RvUm9vbXMuZ2V0KGlkKVxuICAgICAgcmVzdWx0W2lkXSA9IChzb2NrZXRzc2V0ICYmIHNvY2tldHNzZXQudG9BcnJheSgpKSB8fCBbXVxuICAgIH1cbiAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKHJlc3VsdClcbiAgfVxuXG4gIGFkZFNvY2tldFRvUm9vbSAoaWQsIHJvb21OYW1lKSB7XG4gICAgbGV0IHJvb21zc2V0ID0gdGhpcy5zb2NrZXRzVG9Sb29tcy5nZXQoaWQpXG4gICAgbGV0IHNvY2tldHNzZXQgPSB0aGlzLnJvb21zVG9Tb2NrZXRzLmdldChyb29tTmFtZSlcbiAgICBpZiAoIXNvY2tldHNzZXQpIHtcbiAgICAgIHNvY2tldHNzZXQgPSBuZXcgRmFzdFNldCgpXG4gICAgICB0aGlzLnJvb21zVG9Tb2NrZXRzLnNldChyb29tTmFtZSwgc29ja2V0c3NldClcbiAgICB9XG4gICAgcm9vbXNzZXQuYWRkKHJvb21OYW1lKVxuICAgIHNvY2tldHNzZXQuYWRkKGlkKVxuICAgIGxldCBuam9pbmVkID0gc29ja2V0c3NldC5sZW5ndGhcbiAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKG5qb2luZWQpXG4gIH1cblxuICByZW1vdmVTb2NrZXRGcm9tUm9vbSAoaWQsIHJvb21OYW1lKSB7XG4gICAgbGV0IHJvb21zc2V0ID0gdGhpcy5zb2NrZXRzVG9Sb29tcy5nZXQoaWQpXG4gICAgbGV0IHNvY2tldHNzZXQgPSB0aGlzLnJvb21zVG9Tb2NrZXRzLmdldChyb29tTmFtZSlcbiAgICBsZXQgd2Fzam9pbmVkID0gKHNvY2tldHNzZXQgJiYgc29ja2V0c3NldC5sZW5ndGgpIHx8IDBcbiAgICBpZiAocm9vbXNzZXQpIHtcbiAgICAgIHJvb21zc2V0LmRlbGV0ZShyb29tTmFtZSlcbiAgICB9XG4gICAgaWYgKHNvY2tldHNzZXQpIHtcbiAgICAgIHNvY2tldHNzZXQuZGVsZXRlKGlkKVxuICAgIH1cbiAgICBsZXQgbmpvaW5lZCA9IDBcbiAgICBpZiAod2Fzam9pbmVkID4gMCkge1xuICAgICAgbmpvaW5lZCA9IHNvY2tldHNzZXQubGVuZ3RoXG4gICAgfVxuICAgIGxldCBoYXNDaGFuZ2VkID0gbmpvaW5lZCAhPT0gd2Fzam9pbmVkXG4gICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZShbbmpvaW5lZCwgaGFzQ2hhbmdlZF0pXG4gIH1cblxuICByZW1vdmVBbGxTb2NrZXRzRnJvbVJvb20gKHJvb21OYW1lKSB7XG4gICAgbGV0IHNvY2tldHMgPSB0aGlzLnNvY2tldHNUb1Jvb21zLmtleXNBcnJheSgpXG4gICAgbGV0IHNvY2tldHNzZXQgPSB0aGlzLnJvb21zVG9Tb2NrZXRzLmdldChyb29tTmFtZSlcbiAgICBsZXQgcmVtb3ZlZFNvY2tldHMgPSAoc29ja2V0c3NldCAmJiBzb2NrZXRzc2V0LnRvQXJyYXkoKSkgfHwgW11cbiAgICBmb3IgKGxldCBpZCBvZiByZW1vdmVkU29ja2V0cykge1xuICAgICAgbGV0IHJvb21zc2V0ID0gdGhpcy5zb2NrZXRzVG9Sb29tcy5nZXQoaWQpXG4gICAgICByb29tc3NldC5kZWxldGUocm9vbU5hbWUpXG4gICAgfVxuICAgIGlmIChzb2NrZXRzc2V0KSB7XG4gICAgICBzb2NrZXRzc2V0ID0gc29ja2V0c3NldC5kaWZmZXJlbmNlKHNvY2tldHMpXG4gICAgICB0aGlzLnJvb21zVG9Tb2NrZXRzLnNldChyb29tTmFtZSwgc29ja2V0c3NldClcbiAgICB9XG4gICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZShyZW1vdmVkU29ja2V0cylcbiAgfVxuXG4gIHJlbW92ZVNvY2tldCAoaWQpIHtcbiAgICBsZXQgcm9vbXNzZXQgPSB0aGlzLnNvY2tldHNUb1Jvb21zLmdldChpZClcbiAgICBsZXQgcmVtb3ZlZFJvb21zID0gKHJvb21zc2V0ICYmIHJvb21zc2V0LnRvQXJyYXkoKSkgfHwgW11cbiAgICBsZXQgam9pbmVkU29ja2V0cyA9IFtdXG4gICAgZm9yIChsZXQgaWR4ID0gMDsgaWR4IDwgcmVtb3ZlZFJvb21zLmxlbmd0aDsgaWR4KyspIHtcbiAgICAgIGxldCByb29tTmFtZSA9IHJlbW92ZWRSb29tc1tpZHhdXG4gICAgICBsZXQgc29ja2V0c3NldCA9IHRoaXMucm9vbXNUb1NvY2tldHMuZ2V0KHJvb21OYW1lKVxuICAgICAgc29ja2V0c3NldC5kZWxldGUoaWQpXG4gICAgICBsZXQgbmpvaW5lZCA9IHNvY2tldHNzZXQubGVuZ3RoXG4gICAgICBqb2luZWRTb2NrZXRzW2lkeF0gPSBuam9pbmVkXG4gICAgfVxuICAgIHRoaXMuc29ja2V0c1RvUm9vbXMuZGVsZXRlKGlkKVxuICAgIHRoaXMuc29ja2V0c1RvSW5zdGFuY2VzLmRlbGV0ZShpZClcbiAgICBsZXQgbmNvbm5lY3RlZCA9IHRoaXMuc29ja2V0c1RvUm9vbXMubGVuZ3RoXG4gICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZShbIHJlbW92ZWRSb29tcywgam9pbmVkU29ja2V0cywgbmNvbm5lY3RlZCBdKVxuICB9XG5cbiAgbG9ja1RvUm9vbSAocm9vbU5hbWUsIHR0bCkge1xuICAgIHJldHVybiB1aWQoMTgpLnRoZW4odmFsID0+IHtcbiAgICAgIGxldCBzdGFydCA9IF8ubm93KClcbiAgICAgIHJldHVybiB0aGlzLmxvY2socm9vbU5hbWUsIHZhbCwgdHRsKS50aGVuKCgpID0+IHtcbiAgICAgICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZSgpLmRpc3Bvc2VyKCgpID0+IHtcbiAgICAgICAgICBpZiAoc3RhcnQgKyB0dGwgPCBfLm5vdygpKSB7XG4gICAgICAgICAgICB0aGlzLnNlcnZlci5lbWl0KFxuICAgICAgICAgICAgICAnbG9ja1RpbWVFeGNlZWRlZCcsIHZhbCwge3VzZXJOYW1lOiB0aGlzLnVzZXJOYW1lLCByb29tTmFtZX0pXG4gICAgICAgICAgfVxuICAgICAgICAgIHJldHVybiB0aGlzLnVubG9jayhyb29tTmFtZSwgdmFsKVxuICAgICAgICB9KVxuICAgICAgfSlcbiAgICB9KVxuICB9XG5cbn1cblxuLy8gSW1wbGVtZW50cyBnbG9iYWwgc3RhdGUgQVBJLlxuY2xhc3MgTWVtb3J5U3RhdGUge1xuXG4gIGNvbnN0cnVjdG9yIChzZXJ2ZXIsIG9wdGlvbnMpIHtcbiAgICB0aGlzLnNlcnZlciA9IHNlcnZlclxuICAgIHRoaXMub3B0aW9ucyA9IG9wdGlvbnNcbiAgICB0aGlzLmNsb3NlZCA9IGZhbHNlXG4gICAgdGhpcy51c2VycyA9IG5ldyBGYXN0TWFwKClcbiAgICB0aGlzLnJvb21zID0gbmV3IEZhc3RNYXAoKVxuICAgIHRoaXMuc29ja2V0cyA9IG5ldyBGYXN0TWFwKClcbiAgICB0aGlzLlJvb21TdGF0ZSA9IFJvb21TdGF0ZU1lbW9yeVxuICAgIHRoaXMuVXNlclN0YXRlID0gVXNlclN0YXRlTWVtb3J5XG4gICAgdGhpcy5EaXJlY3RNZXNzYWdpbmdTdGF0ZSA9IERpcmVjdE1lc3NhZ2luZ1N0YXRlTWVtb3J5XG4gICAgdGhpcy5pbnN0YW5jZVVJRCA9IHRoaXMuc2VydmVyLmluc3RhbmNlVUlEXG4gICAgdGhpcy5oZWFydGJlYXRTdGFtcCA9IG51bGxcbiAgICB0aGlzLmxvY2tUVEwgPSB0aGlzLm9wdGlvbnMubG9ja1RUTCB8fCA1MDAwXG4gIH1cblxuICBjbG9zZSAoKSB7XG4gICAgdGhpcy5jbG9zZWQgPSB0cnVlXG4gICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZSgpXG4gIH1cblxuICBnZXRSb29tIChuYW1lLCBpc1ByZWRpY2F0ZSA9IGZhbHNlKSB7XG4gICAgbGV0IHJvb20gPSB0aGlzLnJvb21zLmdldChuYW1lKVxuICAgIGlmIChyb29tKSB7IHJldHVybiBQcm9taXNlLnJlc29sdmUocm9vbSkgfVxuICAgIGlmIChpc1ByZWRpY2F0ZSkge1xuICAgICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZShudWxsKVxuICAgIH0gZWxzZSB7XG4gICAgICBsZXQgZXJyb3IgPSBuZXcgQ2hhdFNlcnZpY2VFcnJvcignbm9Sb29tJywgbmFtZSlcbiAgICAgIHJldHVybiBQcm9taXNlLnJlamVjdChlcnJvcilcbiAgICB9XG4gIH1cblxuICBhZGRSb29tIChuYW1lLCBzdGF0ZSkge1xuICAgIGxldCByb29tID0gbmV3IFJvb20odGhpcy5zZXJ2ZXIsIG5hbWUpXG4gICAgaWYgKCF0aGlzLnJvb21zLmdldChuYW1lKSkge1xuICAgICAgdGhpcy5yb29tcy5zZXQobmFtZSwgcm9vbSlcbiAgICB9IGVsc2Uge1xuICAgICAgbGV0IGVycm9yID0gbmV3IENoYXRTZXJ2aWNlRXJyb3IoJ3Jvb21FeGlzdHMnLCBuYW1lKVxuICAgICAgcmV0dXJuIFByb21pc2UucmVqZWN0KGVycm9yKVxuICAgIH1cbiAgICByZXR1cm4gcm9vbS5pbml0U3RhdGUoc3RhdGUpLnJldHVybihyb29tKVxuICB9XG5cbiAgcmVtb3ZlUm9vbSAobmFtZSkge1xuICAgIHRoaXMucm9vbXMuZGVsZXRlKG5hbWUpXG4gICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZSgpXG4gIH1cblxuICBhZGRTb2NrZXQgKGlkLCB1c2VyTmFtZSkge1xuICAgIHRoaXMuc29ja2V0cy5zZXQoaWQsIHVzZXJOYW1lKVxuICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUoKVxuICB9XG5cbiAgcmVtb3ZlU29ja2V0IChpZCkge1xuICAgIHRoaXMuc29ja2V0cy5kZWxldGUoaWQpXG4gICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZSgpXG4gIH1cblxuICBnZXRJbnN0YW5jZVNvY2tldHMgKHVpZCA9IHRoaXMuaW5zdGFuY2VVSUQpIHtcbiAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKHRoaXMuc29ja2V0cy50b09iamVjdCgpKVxuICB9XG5cbiAgdXBkYXRlSGVhcnRiZWF0ICgpIHtcbiAgICB0aGlzLmhlYXJ0YmVhdFN0YW1wID0gXy5ub3coKVxuICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUoKVxuICB9XG5cbiAgZ2V0SW5zdGFuY2VIZWFydGJlYXQgKHVpZCA9IHRoaXMuaW5zdGFuY2VVSUQpIHtcbiAgICBpZiAodWlkICE9PSB0aGlzLmluc3RhbmNlVUlEKSB7IHJldHVybiBQcm9taXNlLnJlc29sdmUobnVsbCkgfVxuICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUodGhpcy5oZWFydGJlYXRTdGFtcClcbiAgfVxuXG4gIGdldE9yQWRkVXNlciAobmFtZSwgc3RhdGUpIHtcbiAgICBsZXQgdXNlciA9IHRoaXMudXNlcnMuZ2V0KG5hbWUpXG4gICAgaWYgKHVzZXIpIHsgcmV0dXJuIFByb21pc2UucmVzb2x2ZSh1c2VyKSB9XG4gICAgcmV0dXJuIHRoaXMuYWRkVXNlcihuYW1lLCBzdGF0ZSlcbiAgfVxuXG4gIGdldFVzZXIgKG5hbWUsIGlzUHJlZGljYXRlID0gZmFsc2UpIHtcbiAgICBsZXQgdXNlciA9IHRoaXMudXNlcnMuZ2V0KG5hbWUpXG4gICAgaWYgKHVzZXIpIHsgcmV0dXJuIFByb21pc2UucmVzb2x2ZSh1c2VyKSB9XG4gICAgaWYgKGlzUHJlZGljYXRlKSB7XG4gICAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKG51bGwpXG4gICAgfSBlbHNlIHtcbiAgICAgIGxldCBlcnJvciA9IG5ldyBDaGF0U2VydmljZUVycm9yKCdub1VzZXInLCBuYW1lKVxuICAgICAgcmV0dXJuIFByb21pc2UucmVqZWN0KGVycm9yKVxuICAgIH1cbiAgfVxuXG4gIGFkZFVzZXIgKG5hbWUsIHN0YXRlKSB7XG4gICAgbGV0IHVzZXIgPSB0aGlzLnVzZXJzLmdldChuYW1lKVxuICAgIGlmICh1c2VyKSB7XG4gICAgICBsZXQgZXJyb3IgPSBuZXcgQ2hhdFNlcnZpY2VFcnJvcigndXNlckV4aXN0cycsIG5hbWUpXG4gICAgICByZXR1cm4gUHJvbWlzZS5yZWplY3QoZXJyb3IpXG4gICAgfVxuICAgIHVzZXIgPSBuZXcgVXNlcih0aGlzLnNlcnZlciwgbmFtZSlcbiAgICB0aGlzLnVzZXJzLnNldChuYW1lLCB1c2VyKVxuICAgIGlmIChzdGF0ZSkge1xuICAgICAgcmV0dXJuIHVzZXIuaW5pdFN0YXRlKHN0YXRlKS5yZXR1cm4odXNlcilcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZSh1c2VyKVxuICAgIH1cbiAgfVxuXG4gIHJlbW92ZVVzZXIgKG5hbWUpIHtcbiAgICB0aGlzLnVzZXJzLmRlbGV0ZShuYW1lKVxuICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUoKVxuICB9XG59XG5cbm1vZHVsZS5leHBvcnRzID0gTWVtb3J5U3RhdGVcbiJdfQ==
\No newline at end of file