1 | ;
|
2 |
|
3 | var _slicedToArray2 = require('babel-runtime/helpers/slicedToArray');
|
4 |
|
5 | var _slicedToArray3 = _interopRequireDefault(_slicedToArray2);
|
6 |
|
7 | var _regenerator = require('babel-runtime/regenerator');
|
8 |
|
9 | var _regenerator2 = _interopRequireDefault(_regenerator);
|
10 |
|
11 | var _classCallCheck2 = require('babel-runtime/helpers/classCallCheck');
|
12 |
|
13 | var _classCallCheck3 = _interopRequireDefault(_classCallCheck2);
|
14 |
|
15 | var _createClass2 = require('babel-runtime/helpers/createClass');
|
16 |
|
17 | var _createClass3 = _interopRequireDefault(_createClass2);
|
18 |
|
19 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
20 |
|
21 | var Promise = require('bluebird');
|
22 | var _ = require('lodash');
|
23 | var eventToPromise = require('event-to-promise');
|
24 |
|
25 | var _require = require('./utils');
|
26 |
|
27 | var asyncLimit = _require.asyncLimit;
|
28 |
|
29 |
|
30 | var co = Promise.coroutine;
|
31 |
|
32 | // Associations for user class.
|
33 |
|
34 | var UserAssociations = function () {
|
35 | function UserAssociations(props) {
|
36 | (0, _classCallCheck3.default)(this, UserAssociations);
|
37 |
|
38 | _.defaults(this, props);
|
39 | }
|
40 |
|
41 | (0, _createClass3.default)(UserAssociations, [{
|
42 | key: 'userJoinRoomReport',
|
43 | value: function userJoinRoomReport(userName, roomName) {
|
44 | this.transport.emitToChannel(roomName, 'roomUserJoined', roomName, userName);
|
45 | }
|
46 | }, {
|
47 | key: 'userLeftRoomReport',
|
48 | value: function userLeftRoomReport(userName, roomName, enableUserlistUpdates) {
|
49 | if (enableUserlistUpdates) {
|
50 | this.transport.emitToChannel(roomName, 'roomUserLeft', roomName, userName);
|
51 | }
|
52 | }
|
53 | }, {
|
54 | key: 'userRemovedReport',
|
55 | value: function userRemovedReport(userName, roomName, enableUserlistUpdates) {
|
56 | var cn = this.echoChannel;
|
57 | this.transport.emitToChannel(cn, 'roomAccessRemoved', roomName);
|
58 | this.userLeftRoomReport(userName, roomName, enableUserlistUpdates);
|
59 | }
|
60 | }, {
|
61 | key: 'socketJoinEcho',
|
62 | value: function socketJoinEcho(id, roomName, njoined, isLocalCall) {
|
63 | if (isLocalCall) {
|
64 | this.transport.emitToChannel(this.echoChannel, 'roomJoinedEcho', roomName, id, njoined);
|
65 | } else {
|
66 | this.transport.sendToChannel(id, this.echoChannel, 'roomJoinedEcho', roomName, id, njoined);
|
67 | }
|
68 | }
|
69 | }, {
|
70 | key: 'socketLeftEcho',
|
71 | value: function socketLeftEcho(id, roomName, njoined, isLocalCall) {
|
72 | if (isLocalCall) {
|
73 | this.transport.emitToChannel(this.echoChannel, 'roomLeftEcho', roomName, id, njoined);
|
74 | } else {
|
75 | this.transport.sendToChannel(id, this.echoChannel, 'roomLeftEcho', roomName, id, njoined);
|
76 | }
|
77 | }
|
78 | }, {
|
79 | key: 'socketConnectEcho',
|
80 | value: function socketConnectEcho(id, nconnected) {
|
81 | this.transport.sendToChannel(id, this.echoChannel, 'socketConnectEcho', id, nconnected);
|
82 | }
|
83 | }, {
|
84 | key: 'socketDisconnectEcho',
|
85 | value: function socketDisconnectEcho(id, nconnected) {
|
86 | this.transport.sendToChannel(id, this.echoChannel, 'socketDisconnectEcho', id, nconnected);
|
87 | }
|
88 | }, {
|
89 | key: 'leaveChannel',
|
90 | value: function leaveChannel(id, channel) {
|
91 | var _this = this;
|
92 |
|
93 | return this.transport.leaveChannel(id, channel).catch(function (e) {
|
94 | var info = { roomName: channel, id: id, opType: 'transportChannel' };
|
95 | return _this.consistencyFailure(e, info);
|
96 | });
|
97 | }
|
98 | }, {
|
99 | key: 'socketLeaveChannels',
|
100 | value: function socketLeaveChannels(id, channels) {
|
101 | var _this2 = this;
|
102 |
|
103 | return Promise.map(channels, function (channel) {
|
104 | return _this2.leaveChannel(id, channel);
|
105 | }, { concurrency: asyncLimit });
|
106 | }
|
107 | }, {
|
108 | key: 'leaveChannelMessage',
|
109 | value: function leaveChannelMessage(id, channel) {
|
110 | var bus = this.clusterBus;
|
111 | return Promise.try(function () {
|
112 | bus.emit('roomLeaveSocket', id, channel);
|
113 | return eventToPromise(bus, bus.makeSocketRoomLeftName(id, channel));
|
114 | }).timeout(this.busAckTimeout).catchReturn();
|
115 | }
|
116 | }, {
|
117 | key: 'channelLeaveSockets',
|
118 | value: function channelLeaveSockets(channel, ids) {
|
119 | var _this3 = this;
|
120 |
|
121 | return Promise.map(ids, function (id) {
|
122 | return _this3.leaveChannelMessage(id, channel);
|
123 | }, { concurrency: asyncLimit });
|
124 | }
|
125 | }, {
|
126 | key: 'rollbackRoomJoin',
|
127 | value: function rollbackRoomJoin(error, roomName, id) {
|
128 | var _this4 = this;
|
129 |
|
130 | return this.userState.removeSocketFromRoom(id, roomName).catch(function (e) {
|
131 | _this4.consistencyFailure(e, { roomName: roomName, opType: 'userRooms' });
|
132 | return [1];
|
133 | }).spread(function (njoined) {
|
134 | if (!njoined) {
|
135 | return _this4.leaveRoom(roomName);
|
136 | } else {
|
137 | return Promise.resolve();
|
138 | }
|
139 | }).thenThrow(error);
|
140 | }
|
141 | }, {
|
142 | key: 'leaveRoom',
|
143 | value: function leaveRoom(roomName) {
|
144 | var _this5 = this;
|
145 |
|
146 | return Promise.try(function () {
|
147 | return _this5.state.getRoom(roomName);
|
148 | }).then(function (room) {
|
149 | return room.leave(_this5.userName).catch(function (error) {
|
150 | return _this5.consistencyFailure(error, { roomName: roomName, opType: 'roomUserlist' });
|
151 | });
|
152 | }).catchReturn();
|
153 | }
|
154 | }, {
|
155 | key: 'getNotifySettings',
|
156 | value: function getNotifySettings(roomName) {
|
157 | var _this6 = this;
|
158 |
|
159 | return Promise.try(function () {
|
160 | return _this6.state.getRoom(roomName);
|
161 | }).then(function (room) {
|
162 | return room.getNotificationsInfo(null, true);
|
163 | }).catchReturn({});
|
164 | }
|
165 | }, {
|
166 | key: 'joinSocketToRoom',
|
167 | value: function joinSocketToRoom(id, roomName, isLocalCall) {
|
168 | var lock = this.userState.lockToRoom(roomName, this.lockTTL);
|
169 | return Promise.using(lock, co(_regenerator2.default.mark(function _callee() {
|
170 | var _this7 = this;
|
171 |
|
172 | var room, enableUserlistUpdates;
|
173 | return _regenerator2.default.wrap(function _callee$(_context) {
|
174 | while (1) {
|
175 | switch (_context.prev = _context.next) {
|
176 | case 0:
|
177 | _context.next = 2;
|
178 | return this.state.getRoom(roomName);
|
179 |
|
180 | case 2:
|
181 | room = _context.sent;
|
182 | _context.next = 5;
|
183 | return room.join(this.userName);
|
184 |
|
185 | case 5:
|
186 | _context.next = 7;
|
187 | return room.roomState.userlistUpdatesGet();
|
188 |
|
189 | case 7:
|
190 | enableUserlistUpdates = _context.sent;
|
191 | return _context.abrupt('return', this.userState.addSocketToRoom(id, roomName).then(function (njoined) {
|
192 | return _this7.transport.joinChannel(id, roomName).then(function () {
|
193 | if (njoined === 1 && enableUserlistUpdates) {
|
194 | _this7.userJoinRoomReport(_this7.userName, roomName);
|
195 | }
|
196 | return _this7.socketJoinEcho(id, roomName, njoined, isLocalCall);
|
197 | }).return(njoined);
|
198 | }).catch(function (e) {
|
199 | return _this7.rollbackRoomJoin(e, roomName, id);
|
200 | }));
|
201 |
|
202 | case 9:
|
203 | case 'end':
|
204 | return _context.stop();
|
205 | }
|
206 | }
|
207 | }, _callee, this);
|
208 | })).bind(this));
|
209 | }
|
210 | }, {
|
211 | key: 'leaveSocketFromRoom',
|
212 | value: function leaveSocketFromRoom(id, roomName, isLocalCall) {
|
213 | var lock = this.userState.lockToRoom(roomName, this.lockTTL);
|
214 | return Promise.using(lock, co(_regenerator2.default.mark(function _callee2() {
|
215 | var _ref, _ref2, njoined, hasChanged, _ref3, enableUserlistUpdates;
|
216 |
|
217 | return _regenerator2.default.wrap(function _callee2$(_context2) {
|
218 | while (1) {
|
219 | switch (_context2.prev = _context2.next) {
|
220 | case 0:
|
221 | _context2.next = 2;
|
222 | return this.userState.removeSocketFromRoom(id, roomName);
|
223 |
|
224 | case 2:
|
225 | _ref = _context2.sent;
|
226 | _ref2 = (0, _slicedToArray3.default)(_ref, 2);
|
227 | njoined = _ref2[0];
|
228 | hasChanged = _ref2[1];
|
229 | _context2.next = 8;
|
230 | return this.leaveChannel(id, roomName);
|
231 |
|
232 | case 8:
|
233 | if (!(njoined === 0)) {
|
234 | _context2.next = 11;
|
235 | break;
|
236 | }
|
237 |
|
238 | _context2.next = 11;
|
239 | return this.leaveRoom(roomName);
|
240 |
|
241 | case 11:
|
242 | if (!hasChanged) {
|
243 | _context2.next = 18;
|
244 | break;
|
245 | }
|
246 |
|
247 | _context2.next = 14;
|
248 | return this.getNotifySettings(roomName);
|
249 |
|
250 | case 14:
|
251 | _ref3 = _context2.sent;
|
252 | enableUserlistUpdates = _ref3.enableUserlistUpdates;
|
253 |
|
254 | this.socketLeftEcho(id, roomName, njoined, isLocalCall);
|
255 | this.userLeftRoomReport(this.userName, roomName, enableUserlistUpdates);
|
256 |
|
257 | case 18:
|
258 | return _context2.abrupt('return', Promise.resolve(njoined));
|
259 |
|
260 | case 19:
|
261 | case 'end':
|
262 | return _context2.stop();
|
263 | }
|
264 | }
|
265 | }, _callee2, this);
|
266 | })).bind(this));
|
267 | }
|
268 | }, {
|
269 | key: 'removeUserSocket',
|
270 | value: function removeUserSocket(id) {
|
271 | var _this8 = this;
|
272 |
|
273 | return this.userState.removeSocket(id).spread(function (roomsRemoved, joinedSockets, nconnected) {
|
274 | roomsRemoved = roomsRemoved || [];
|
275 | joinedSockets = joinedSockets || [];
|
276 | nconnected = nconnected || 0;
|
277 | return _this8.socketLeaveChannels(id, roomsRemoved).then(function () {
|
278 | return Promise.map(roomsRemoved, function (roomName, idx) {
|
279 | var njoined = joinedSockets[idx];
|
280 | _this8.socketLeftEcho(id, roomName, njoined);
|
281 | if (njoined) {
|
282 | return Promise.resolve();
|
283 | }
|
284 | return _this8.leaveRoom(roomName).then(function () {
|
285 | return _this8.getNotifySettings(roomName);
|
286 | }).then(function (_ref4) {
|
287 | var enableUserlistUpdates = _ref4.enableUserlistUpdates;
|
288 | return _this8.userLeftRoomReport(_this8.userName, roomName, enableUserlistUpdates);
|
289 | });
|
290 | }, { concurrency: asyncLimit }).then(function () {
|
291 | return _this8.socketDisconnectEcho(id, nconnected);
|
292 | });
|
293 | });
|
294 | }).then(function () {
|
295 | return _this8.state.removeSocket(id);
|
296 | });
|
297 | }
|
298 | }, {
|
299 | key: 'removeSocketFromServer',
|
300 | value: function removeSocketFromServer(id) {
|
301 | var _this9 = this;
|
302 |
|
303 | return this.removeUserSocket(id).catch(function (e) {
|
304 | var info = { id: id, opType: 'userSockets' };
|
305 | return _this9.consistencyFailure(e, info);
|
306 | });
|
307 | }
|
308 | }, {
|
309 | key: 'removeUserSocketsFromRoom',
|
310 | value: function removeUserSocketsFromRoom(roomName) {
|
311 | var _this10 = this;
|
312 |
|
313 | return this.userState.removeAllSocketsFromRoom(roomName).catch(function (e) {
|
314 | var info = { roomName: roomName, opType: 'roomUserlist' };
|
315 | return _this10.consistencyFailure(e, info);
|
316 | });
|
317 | }
|
318 | }, {
|
319 | key: 'removeFromRoom',
|
320 | value: function removeFromRoom(roomName) {
|
321 | var lock = this.userState.lockToRoom(roomName, this.lockTTL);
|
322 | return Promise.using(lock, co(_regenerator2.default.mark(function _callee3() {
|
323 | var removedSockets, _ref5, enableUserlistUpdates;
|
324 |
|
325 | return _regenerator2.default.wrap(function _callee3$(_context3) {
|
326 | while (1) {
|
327 | switch (_context3.prev = _context3.next) {
|
328 | case 0:
|
329 | _context3.next = 2;
|
330 | return this.removeUserSocketsFromRoom(roomName);
|
331 |
|
332 | case 2:
|
333 | removedSockets = _context3.sent;
|
334 |
|
335 | removedSockets = removedSockets || [];
|
336 | _context3.next = 6;
|
337 | return this.channelLeaveSockets(roomName, removedSockets);
|
338 |
|
339 | case 6:
|
340 | if (!removedSockets.length) {
|
341 | _context3.next = 12;
|
342 | break;
|
343 | }
|
344 |
|
345 | _context3.next = 9;
|
346 | return this.getNotifySettings(roomName);
|
347 |
|
348 | case 9:
|
349 | _ref5 = _context3.sent;
|
350 | enableUserlistUpdates = _ref5.enableUserlistUpdates;
|
351 |
|
352 | this.userRemovedReport(this.userName, roomName, enableUserlistUpdates);
|
353 |
|
354 | case 12:
|
355 | return _context3.abrupt('return', this.leaveRoom(roomName));
|
356 |
|
357 | case 13:
|
358 | case 'end':
|
359 | return _context3.stop();
|
360 | }
|
361 | }
|
362 | }, _callee3, this);
|
363 | })).bind(this));
|
364 | }
|
365 | }, {
|
366 | key: 'removeRoomUsers',
|
367 | value: function removeRoomUsers(roomName, userNames) {
|
368 | var _this11 = this;
|
369 |
|
370 | userNames = userNames || [];
|
371 | return Promise.map(userNames, function (userName) {
|
372 | return _this11.state.getUser(userName).then(function (user) {
|
373 | return user.removeFromRoom(roomName);
|
374 | }).catchReturn();
|
375 | }, { concurrency: asyncLimit });
|
376 | }
|
377 | }]);
|
378 | return UserAssociations;
|
379 | }();
|
380 |
|
381 | module.exports = UserAssociations;
|
382 | //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uL3NyYy9Vc2VyQXNzb2NpYXRpb25zLmpzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOzs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQUVBLElBQU0sVUFBVSxRQUFRLFVBQVIsQ0FBaEI7QUFDQSxJQUFNLElBQUksUUFBUSxRQUFSLENBQVY7QUFDQSxJQUFNLGlCQUFpQixRQUFRLGtCQUFSLENBQXZCOztlQUN1QixRQUFRLFNBQVIsQzs7SUFBZixVLFlBQUEsVTs7O0FBRVIsSUFBTSxLQUFLLFFBQVEsU0FBbkI7O0FBRUE7O0lBQ00sZ0I7QUFFSiw0QkFBYSxLQUFiLEVBQW9CO0FBQUE7O0FBQ2xCLE1BQUUsUUFBRixDQUFXLElBQVgsRUFBaUIsS0FBakI7QUFDRDs7Ozt1Q0FFbUIsUSxFQUFVLFEsRUFBVTtBQUN0QyxXQUFLLFNBQUwsQ0FBZSxhQUFmLENBQTZCLFFBQTdCLEVBQXVDLGdCQUF2QyxFQUF5RCxRQUF6RCxFQUFtRSxRQUFuRTtBQUNEOzs7dUNBRW1CLFEsRUFBVSxRLEVBQVUscUIsRUFBdUI7QUFDN0QsVUFBSSxxQkFBSixFQUEyQjtBQUN6QixhQUFLLFNBQUwsQ0FBZSxhQUFmLENBQTZCLFFBQTdCLEVBQXVDLGNBQXZDLEVBQXVELFFBQXZELEVBQWlFLFFBQWpFO0FBQ0Q7QUFDRjs7O3NDQUVrQixRLEVBQVUsUSxFQUFVLHFCLEVBQXVCO0FBQzVELFVBQUksS0FBSyxLQUFLLFdBQWQ7QUFDQSxXQUFLLFNBQUwsQ0FBZSxhQUFmLENBQTZCLEVBQTdCLEVBQWlDLG1CQUFqQyxFQUFzRCxRQUF0RDtBQUNBLFdBQUssa0JBQUwsQ0FBd0IsUUFBeEIsRUFBa0MsUUFBbEMsRUFBNEMscUJBQTVDO0FBQ0Q7OzttQ0FFZSxFLEVBQUksUSxFQUFVLE8sRUFBUyxXLEVBQWE7QUFDbEQsVUFBSSxXQUFKLEVBQWlCO0FBQ2YsYUFBSyxTQUFMLENBQWUsYUFBZixDQUNFLEtBQUssV0FEUCxFQUNvQixnQkFEcEIsRUFDc0MsUUFEdEMsRUFDZ0QsRUFEaEQs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Q29udGVudCI6WyIndXNlIHN0cmljdCdcblxuY29uc3QgUHJvbWlzZSA9IHJlcXVpcmUoJ2JsdWViaXJkJylcbmNvbnN0IF8gPSByZXF1aXJlKCdsb2Rhc2gnKVxuY29uc3QgZXZlbnRUb1Byb21pc2UgPSByZXF1aXJlKCdldmVudC10by1wcm9taXNlJylcbmNvbnN0IHsgYXN5bmNMaW1pdCB9ID0gcmVxdWlyZSgnLi91dGlscycpXG5cbmNvbnN0IGNvID0gUHJvbWlzZS5jb3JvdXRpbmVcblxuLy8gQXNzb2NpYXRpb25zIGZvciB1c2VyIGNsYXNzLlxuY2xhc3MgVXNlckFzc29jaWF0aW9ucyB7XG5cbiAgY29uc3RydWN0b3IgKHByb3BzKSB7XG4gICAgXy5kZWZhdWx0cyh0aGlzLCBwcm9wcylcbiAgfVxuXG4gIHVzZXJKb2luUm9vbVJlcG9ydCAodXNlck5hbWUsIHJvb21OYW1lKSB7XG4gICAgdGhpcy50cmFuc3BvcnQuZW1pdFRvQ2hhbm5lbChyb29tTmFtZSwgJ3Jvb21Vc2VySm9pbmVkJywgcm9vbU5hbWUsIHVzZXJOYW1lKVxuICB9XG5cbiAgdXNlckxlZnRSb29tUmVwb3J0ICh1c2VyTmFtZSwgcm9vbU5hbWUsIGVuYWJsZVVzZXJsaXN0VXBkYXRlcykge1xuICAgIGlmIChlbmFibGVVc2VybGlzdFVwZGF0ZXMpIHtcbiAgICAgIHRoaXMudHJhbnNwb3J0LmVtaXRUb0NoYW5uZWwocm9vbU5hbWUsICdyb29tVXNlckxlZnQnLCByb29tTmFtZSwgdXNlck5hbWUpXG4gICAgfVxuICB9XG5cbiAgdXNlclJlbW92ZWRSZXBvcnQgKHVzZXJOYW1lLCByb29tTmFtZSwgZW5hYmxlVXNlcmxpc3RVcGRhdGVzKSB7XG4gICAgbGV0IGNuID0gdGhpcy5lY2hvQ2hhbm5lbFxuICAgIHRoaXMudHJhbnNwb3J0LmVtaXRUb0NoYW5uZWwoY24sICdyb29tQWNjZXNzUmVtb3ZlZCcsIHJvb21OYW1lKVxuICAgIHRoaXMudXNlckxlZnRSb29tUmVwb3J0KHVzZXJOYW1lLCByb29tTmFtZSwgZW5hYmxlVXNlcmxpc3RVcGRhdGVzKVxuICB9XG5cbiAgc29ja2V0Sm9pbkVjaG8gKGlkLCByb29tTmFtZSwgbmpvaW5lZCwgaXNMb2NhbENhbGwpIHtcbiAgICBpZiAoaXNMb2NhbENhbGwpIHtcbiAgICAgIHRoaXMudHJhbnNwb3J0LmVtaXRUb0NoYW5uZWwoXG4gICAgICAgIHRoaXMuZWNob0NoYW5uZWwsICdyb29tSm9pbmVkRWNobycsIHJvb21OYW1lLCBpZCwgbmpvaW5lZClcbiAgICB9IGVsc2Uge1xuICAgICAgdGhpcy50cmFuc3BvcnQuc2VuZFRvQ2hhbm5lbChcbiAgICAgICAgaWQsIHRoaXMuZWNob0NoYW5uZWwsICdyb29tSm9pbmVkRWNobycsIHJvb21OYW1lLCBpZCwgbmpvaW5lZClcbiAgICB9XG4gIH1cblxuICBzb2NrZXRMZWZ0RWNobyAoaWQsIHJvb21OYW1lLCBuam9pbmVkLCBpc0xvY2FsQ2FsbCkge1xuICAgIGlmIChpc0xvY2FsQ2FsbCkge1xuICAgICAgdGhpcy50cmFuc3BvcnQuZW1pdFRvQ2hhbm5lbChcbiAgICAgICAgdGhpcy5lY2hvQ2hhbm5lbCwgJ3Jvb21MZWZ0RWNobycsIHJvb21OYW1lLCBpZCwgbmpvaW5lZClcbiAgICB9IGVsc2Uge1xuICAgICAgdGhpcy50cmFuc3BvcnQuc2VuZFRvQ2hhbm5lbChcbiAgICAgICAgaWQsIHRoaXMuZWNob0NoYW5uZWwsICdyb29tTGVmdEVjaG8nLCByb29tTmFtZSwgaWQsIG5qb2luZWQpXG4gICAgfVxuICB9XG5cbiAgc29ja2V0Q29ubmVjdEVjaG8gKGlkLCBuY29ubmVjdGVkKSB7XG4gICAgdGhpcy50cmFuc3BvcnQuc2VuZFRvQ2hhbm5lbChcbiAgICAgIGlkLCB0aGlzLmVjaG9DaGFubmVsLCAnc29ja2V0Q29ubmVjdEVjaG8nLCBpZCwgbmNvbm5lY3RlZClcbiAgfVxuXG4gIHNvY2tldERpc2Nvbm5lY3RFY2hvIChpZCwgbmNvbm5lY3RlZCkge1xuICAgIHRoaXMudHJhbnNwb3J0LnNlbmRUb0NoYW5uZWwoXG4gICAgICBpZCwgdGhpcy5lY2hvQ2hhbm5lbCwgJ3NvY2tldERpc2Nvbm5lY3RFY2hvJywgaWQsIG5jb25uZWN0ZWQpXG4gIH1cblxuICBsZWF2ZUNoYW5uZWwgKGlkLCBjaGFubmVsKSB7XG4gICAgcmV0dXJuIHRoaXMudHJhbnNwb3J0LmxlYXZlQ2hhbm5lbChpZCwgY2hhbm5lbCkuY2F0Y2goZSA9PiB7XG4gICAgICBsZXQgaW5mbyA9IHsgcm9vbU5hbWU6IGNoYW5uZWwsIGlkLCBvcFR5cGU6ICd0cmFuc3BvcnRDaGFubmVsJyB9XG4gICAgICByZXR1cm4gdGhpcy5jb25zaXN0ZW5jeUZhaWx1cmUoZSwgaW5mbylcbiAgICB9KVxuICB9XG5cbiAgc29ja2V0TGVhdmVDaGFubmVscyAoaWQsIGNoYW5uZWxzKSB7XG4gICAgcmV0dXJuIFByb21pc2UubWFwKFxuICAgICAgY2hhbm5lbHMsXG4gICAgICBjaGFubmVsID0+IHRoaXMubGVhdmVDaGFubmVsKGlkLCBjaGFubmVsKSxcbiAgICAgIHsgY29uY3VycmVuY3k6IGFzeW5jTGltaXQgfSlcbiAgfVxuXG4gIGxlYXZlQ2hhbm5lbE1lc3NhZ2UgKGlkLCBjaGFubmVsKSB7XG4gICAgbGV0IGJ1cyA9IHRoaXMuY2x1c3RlckJ1c1xuICAgIHJldHVybiBQcm9taXNlLnRyeSgoKSA9PiB7XG4gICAgICBidXMuZW1pdCgncm9vbUxlYXZlU29ja2V0JywgaWQsIGNoYW5uZWwpXG4gICAgICByZXR1cm4gZXZlbnRUb1Byb21pc2UoYnVzLCBidXMubWFrZVNvY2tldFJvb21MZWZ0TmFtZShpZCwgY2hhbm5lbCkpXG4gICAgfSkudGltZW91dCh0aGlzLmJ1c0Fja1RpbWVvdXQpLmNhdGNoUmV0dXJuKClcbiAgfVxuXG4gIGNoYW5uZWxMZWF2ZVNvY2tldHMgKGNoYW5uZWwsIGlkcykge1xuICAgIHJldHVybiBQcm9taXNlLm1hcChcbiAgICAgIGlkcyxcbiAgICAgIGlkID0+IHRoaXMubGVhdmVDaGFubmVsTWVzc2FnZShpZCwgY2hhbm5lbCksXG4gICAgICB7IGNvbmN1cnJlbmN5OiBhc3luY0xpbWl0IH0pXG4gIH1cblxuICByb2xsYmFja1Jvb21Kb2luIChlcnJvciwgcm9vbU5hbWUsIGlkKSB7XG4gICAgcmV0dXJuIHRoaXMudXNlclN0YXRlLnJlbW92ZVNvY2tldEZyb21Sb29tKGlkLCByb29tTmFtZSkuY2F0Y2goZSA9PiB7XG4gICAgICB0aGlzLmNvbnNpc3RlbmN5RmFpbHVyZShlLCB7IHJvb21OYW1lLCBvcFR5cGU6ICd1c2VyUm9vbXMnIH0pXG4gICAgICByZXR1cm4gWzFdXG4gICAgfSkuc3ByZWFkKG5qb2luZWQgPT4ge1xuICAgICAgaWYgKCFuam9pbmVkKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmxlYXZlUm9vbShyb29tTmFtZSlcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUoKVxuICAgICAgfVxuICAgIH0pLnRoZW5UaHJvdyhlcnJvcilcbiAgfVxuXG4gIGxlYXZlUm9vbSAocm9vbU5hbWUpIHtcbiAgICByZXR1cm4gUHJvbWlzZVxuICAgICAgLnRyeSgoKSA9PiB0aGlzLnN0YXRlLmdldFJvb20ocm9vbU5hbWUpKVxuICAgICAgLnRoZW4ocm9vbSA9PiByb29tLmxlYXZlKHRoaXMudXNlck5hbWUpXG4gICAgICAgICAgICAuY2F0Y2goZXJyb3IgPT4gdGhpcy5jb25zaXN0ZW5jeUZhaWx1cmUoXG4gICAgICAgICAgICAgIGVycm9yLCB7cm9vbU5hbWUsIG9wVHlwZTogJ3Jvb21Vc2VybGlzdCd9KSkpXG4gICAgICAuY2F0Y2hSZXR1cm4oKVxuICB9XG5cbiAgZ2V0Tm90aWZ5U2V0dGluZ3MgKHJvb21OYW1lKSB7XG4gICAgcmV0dXJuIFByb21pc2VcbiAgICAgIC50cnkoKCkgPT4gdGhpcy5zdGF0ZS5nZXRSb29tKHJvb21OYW1lKSlcbiAgICAgIC50aGVuKHJvb20gPT4gcm9vbS5nZXROb3RpZmljYXRpb25zSW5mbyhudWxsLCB0cnVlKSlcbiAgICAgIC5jYXRjaFJldHVybih7fSlcbiAgfVxuXG4gIGpvaW5Tb2NrZXRUb1Jvb20gKGlkLCByb29tTmFtZSwgaXNMb2NhbENhbGwpIHtcbiAgICBsZXQgbG9jayA9IHRoaXMudXNlclN0YXRlLmxvY2tUb1Jvb20ocm9vbU5hbWUsIHRoaXMubG9ja1RUTClcbiAgICByZXR1cm4gUHJvbWlzZS51c2luZyhsb2NrLCBjbyhmdW5jdGlvbiAqICgpIHtcbiAgICAgIGxldCByb29tID0geWllbGQgdGhpcy5zdGF0ZS5nZXRSb29tKHJvb21OYW1lKVxuICAgICAgeWllbGQgcm9vbS5qb2luKHRoaXMudXNlck5hbWUpXG4gICAgICBsZXQgZW5hYmxlVXNlcmxpc3RVcGRhdGVzID0geWllbGQgcm9vbS5yb29tU3RhdGUudXNlcmxpc3RVcGRhdGVzR2V0KClcbiAgICAgIHJldHVybiB0aGlzLnVzZXJTdGF0ZS5hZGRTb2NrZXRUb1Jvb20oaWQsIHJvb21OYW1lKS50aGVuKG5qb2luZWQgPT4ge1xuICAgICAgICByZXR1cm4gdGhpcy50cmFuc3BvcnQuam9pbkNoYW5uZWwoaWQsIHJvb21OYW1lKS50aGVuKCgpID0+IHtcbiAgICAgICAgICBpZiAobmpvaW5lZCA9PT0gMSAmJiBlbmFibGVVc2VybGlzdFVwZGF0ZXMpIHtcbiAgICAgICAgICAgIHRoaXMudXNlckpvaW5Sb29tUmVwb3J0KHRoaXMudXNlck5hbWUsIHJvb21OYW1lKVxuICAgICAgICAgIH1cbiAgICAgICAgICByZXR1cm4gdGhpcy5zb2NrZXRKb2luRWNobyhpZCwgcm9vbU5hbWUsIG5qb2luZWQsIGlzTG9jYWxDYWxsKVxuICAgICAgICB9KS5yZXR1cm4obmpvaW5lZClcbiAgICAgIH0pLmNhdGNoKGUgPT4gdGhpcy5yb2xsYmFja1Jvb21Kb2luKGUsIHJvb21OYW1lLCBpZCkpXG4gICAgfSkuYmluZCh0aGlzKSlcbiAgfVxuXG4gIGxlYXZlU29ja2V0RnJvbVJvb20gKGlkLCByb29tTmFtZSwgaXNMb2NhbENhbGwpIHtcbiAgICBsZXQgbG9jayA9IHRoaXMudXNlclN0YXRlLmxvY2tUb1Jvb20ocm9vbU5hbWUsIHRoaXMubG9ja1RUTClcbiAgICByZXR1cm4gUHJvbWlzZS51c2luZyhsb2NrLCBjbyhmdW5jdGlvbiAqICgpIHtcbiAgICAgIGxldCBbbmpvaW5lZCwgaGFzQ2hhbmdlZF0gPVxuICAgICAgICAgICAgeWllbGQgdGhpcy51c2VyU3RhdGUucmVtb3ZlU29ja2V0RnJvbVJvb20oaWQsIHJvb21OYW1lKVxuICAgICAgeWllbGQgdGhpcy5sZWF2ZUNoYW5uZWwoaWQsIHJvb21OYW1lKVxuICAgICAgaWYgKG5qb2luZWQgPT09IDApIHtcbiAgICAgICAgeWllbGQgdGhpcy5sZWF2ZVJvb20ocm9vbU5hbWUpXG4gICAgICB9XG4gICAgICBpZiAoaGFzQ2hhbmdlZCkge1xuICAgICAgICBsZXQgeyBlbmFibGVVc2VybGlzdFVwZGF0ZXMgfSA9IHlpZWxkIHRoaXMuZ2V0Tm90aWZ5U2V0dGluZ3Mocm9vbU5hbWUpXG4gICAgICAgIHRoaXMuc29ja2V0TGVmdEVjaG8oaWQsIHJvb21OYW1lLCBuam9pbmVkLCBpc0xvY2FsQ2FsbClcbiAgICAgICAgdGhpcy51c2VyTGVmdFJvb21SZXBvcnQodGhpcy51c2VyTmFtZSwgcm9vbU5hbWUsIGVuYWJsZVVzZXJsaXN0VXBkYXRlcylcbiAgICAgIH1cbiAgICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUobmpvaW5lZClcbiAgICB9KS5iaW5kKHRoaXMpKVxuICB9XG5cbiAgcmVtb3ZlVXNlclNvY2tldCAoaWQpIHtcbiAgICByZXR1cm4gdGhpcy51c2VyU3RhdGUucmVtb3ZlU29ja2V0KGlkKVxuICAgICAgLnNwcmVhZCgocm9vbXNSZW1vdmVkLCBqb2luZWRTb2NrZXRzLCBuY29ubmVjdGVkKSA9PiB7XG4gICAgICAgIHJvb21zUmVtb3ZlZCA9IHJvb21zUmVtb3ZlZCB8fCBbXVxuICAgICAgICBqb2luZWRTb2NrZXRzID0gam9pbmVkU29ja2V0cyB8fCBbXVxuICAgICAgICBuY29ubmVjdGVkID0gbmNvbm5lY3RlZCB8fCAwXG4gICAgICAgIHJldHVybiB0aGlzLnNvY2tldExlYXZlQ2hhbm5lbHMoaWQsIHJvb21zUmVtb3ZlZCkudGhlbigoKSA9PiB7XG4gICAgICAgICAgcmV0dXJuIFByb21pc2UubWFwKFxuICAgICAgICAgICAgcm9vbXNSZW1vdmVkLFxuICAgICAgICAgICAgKHJvb21OYW1lLCBpZHgpID0+IHtcbiAgICAgICAgICAgICAgbGV0IG5qb2luZWQgPSBqb2luZWRTb2NrZXRzW2lkeF1cbiAgICAgICAgICAgICAgdGhpcy5zb2NrZXRMZWZ0RWNobyhpZCwgcm9vbU5hbWUsIG5qb2luZWQpXG4gICAgICAgICAgICAgIGlmIChuam9pbmVkKSB7IHJldHVybiBQcm9taXNlLnJlc29sdmUoKSB9XG4gICAgICAgICAgICAgIHJldHVybiB0aGlzLmxlYXZlUm9vbShyb29tTmFtZSlcbiAgICAgICAgICAgICAgICAudGhlbigoKSA9PiB0aGlzLmdldE5vdGlmeVNldHRpbmdzKHJvb21OYW1lKSlcbiAgICAgICAgICAgICAgICAudGhlbigoe2VuYWJsZVVzZXJsaXN0VXBkYXRlc30pID0+IHRoaXMudXNlckxlZnRSb29tUmVwb3J0KFxuICAgICAgICAgICAgICAgICAgdGhpcy51c2VyTmFtZSwgcm9vbU5hbWUsIGVuYWJsZVVzZXJsaXN0VXBkYXRlcykpXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgeyBjb25jdXJyZW5jeTogYXN5bmNMaW1pdCB9KVxuICAgICAgICAgICAgLnRoZW4oKCkgPT4gdGhpcy5zb2NrZXREaXNjb25uZWN0RWNobyhpZCwgbmNvbm5lY3RlZCkpXG4gICAgICAgIH0pXG4gICAgICB9KS50aGVuKCgpID0+IHRoaXMuc3RhdGUucmVtb3ZlU29ja2V0KGlkKSlcbiAgfVxuXG4gIHJlbW92ZVNvY2tldEZyb21TZXJ2ZXIgKGlkKSB7XG4gICAgcmV0dXJuIHRoaXMucmVtb3ZlVXNlclNvY2tldChpZCkuY2F0Y2goZSA9PiB7XG4gICAgICBsZXQgaW5mbyA9IHsgaWQsIG9wVHlwZTogJ3VzZXJTb2NrZXRzJyB9XG4gICAgICByZXR1cm4gdGhpcy5jb25zaXN0ZW5jeUZhaWx1cmUoZSwgaW5mbylcbiAgICB9KVxuICB9XG5cbiAgcmVtb3ZlVXNlclNvY2tldHNGcm9tUm9vbSAocm9vbU5hbWUpIHtcbiAgICByZXR1cm4gdGhpcy51c2VyU3RhdGUucmVtb3ZlQWxsU29ja2V0c0Zyb21Sb29tKHJvb21OYW1lKS5jYXRjaChlID0+IHtcbiAgICAgIGxldCBpbmZvID0geyByb29tTmFtZSwgb3BUeXBlOiAncm9vbVVzZXJsaXN0JyB9XG4gICAgICByZXR1cm4gdGhpcy5jb25zaXN0ZW5jeUZhaWx1cmUoZSwgaW5mbylcbiAgICB9KVxuICB9XG5cbiAgcmVtb3ZlRnJvbVJvb20gKHJvb21OYW1lKSB7XG4gICAgbGV0IGxvY2sgPSB0aGlzLnVzZXJTdGF0ZS5sb2NrVG9Sb29tKHJvb21OYW1lLCB0aGlzLmxvY2tUVEwpXG4gICAgcmV0dXJuIFByb21pc2UudXNpbmcobG9jaywgY28oZnVuY3Rpb24gKiAoKSB7XG4gICAgICBsZXQgcmVtb3ZlZFNvY2tldHMgPSB5aWVsZCB0aGlzLnJlbW92ZVVzZXJTb2NrZXRzRnJvbVJvb20ocm9vbU5hbWUpXG4gICAgICByZW1vdmVkU29ja2V0cyA9IHJlbW92ZWRTb2NrZXRzIHx8IFtdXG4gICAgICB5aWVsZCB0aGlzLmNoYW5uZWxMZWF2ZVNvY2tldHMocm9vbU5hbWUsIHJlbW92ZWRTb2NrZXRzKVxuICAgICAgaWYgKHJlbW92ZWRTb2NrZXRzLmxlbmd0aCkge1xuICAgICAgICBsZXQgeyBlbmFibGVVc2VybGlzdFVwZGF0ZXMgfSA9IHlpZWxkIHRoaXMuZ2V0Tm90aWZ5U2V0dGluZ3Mocm9vbU5hbWUpXG4gICAgICAgIHRoaXMudXNlclJlbW92ZWRSZXBvcnQodGhpcy51c2VyTmFtZSwgcm9vbU5hbWUsIGVuYWJsZVVzZXJsaXN0VXBkYXRlcylcbiAgICAgIH1cbiAgICAgIHJldHVybiB0aGlzLmxlYXZlUm9vbShyb29tTmFtZSlcbiAgICB9KS5iaW5kKHRoaXMpKVxuICB9XG5cbiAgcmVtb3ZlUm9vbVVzZXJzIChyb29tTmFtZSwgdXNlck5hbWVzKSB7XG4gICAgdXNlck5hbWVzID0gdXNlck5hbWVzIHx8IFtdXG4gICAgcmV0dXJuIFByb21pc2UubWFwKFxuICAgICAgdXNlck5hbWVzLFxuICAgICAgdXNlck5hbWUgPT4ge1xuICAgICAgICByZXR1cm4gdGhpcy5zdGF0ZS5nZXRVc2VyKHVzZXJOYW1lKVxuICAgICAgICAgIC50aGVuKHVzZXIgPT4gdXNlci5yZW1vdmVGcm9tUm9vbShyb29tTmFtZSkpXG4gICAgICAgICAgLmNhdGNoUmV0dXJuKClcbiAgICAgIH0sXG4gICAgICB7IGNvbmN1cnJlbmN5OiBhc3luY0xpbWl0IH0pXG4gIH1cblxufVxuXG5tb2R1bGUuZXhwb3J0cyA9IFVzZXJBc3NvY2lhdGlvbnNcbiJdfQ== |
\ | No newline at end of file |