1 | ;
|
2 |
|
3 | var _getIterator2 = require('babel-runtime/core-js/get-iterator');
|
4 |
|
5 | var _getIterator3 = _interopRequireDefault(_getIterator2);
|
6 |
|
7 | var _getPrototypeOf = require('babel-runtime/core-js/object/get-prototype-of');
|
8 |
|
9 | var _getPrototypeOf2 = _interopRequireDefault(_getPrototypeOf);
|
10 |
|
11 | var _possibleConstructorReturn2 = require('babel-runtime/helpers/possibleConstructorReturn');
|
12 |
|
13 | var _possibleConstructorReturn3 = _interopRequireDefault(_possibleConstructorReturn2);
|
14 |
|
15 | var _inherits2 = require('babel-runtime/helpers/inherits');
|
16 |
|
17 | var _inherits3 = _interopRequireDefault(_inherits2);
|
18 |
|
19 | var _classCallCheck2 = require('babel-runtime/helpers/classCallCheck');
|
20 |
|
21 | var _classCallCheck3 = _interopRequireDefault(_classCallCheck2);
|
22 |
|
23 | var _createClass2 = require('babel-runtime/helpers/createClass');
|
24 |
|
25 | var _createClass3 = _interopRequireDefault(_createClass2);
|
26 |
|
27 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
28 |
|
29 | var ChatServiceError = require('./ChatServiceError');
|
30 | var FastMap = require('collections/fast-map');
|
31 | var FastSet = require('collections/fast-set');
|
32 | var List = require('collections/list');
|
33 | var Promise = require('bluebird');
|
34 | var Room = require('./Room');
|
35 | var User = require('./User');
|
36 | var _ = require('lodash');
|
37 | var promiseRetry = require('promise-retry');
|
38 | var uid = require('uid-safe');
|
39 |
|
40 | var _require = require('es6-mixin');
|
41 |
|
42 | var mixin = _require.mixin;
|
43 |
|
44 |
|
45 | function _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 |
|
57 | var 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 |
|
95 | var 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 |
|
177 | var 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 |
|
401 | var 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 |
|
446 | var 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 |
|
633 | var 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 |
|
777 | module.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 |