1 | 'use strict';
|
2 |
|
3 | var _typeof2 = require('babel-runtime/helpers/typeof');
|
4 |
|
5 | var _typeof3 = _interopRequireDefault(_typeof2);
|
6 |
|
7 | var _getIterator2 = require('babel-runtime/core-js/get-iterator');
|
8 |
|
9 | var _getIterator3 = _interopRequireDefault(_getIterator2);
|
10 |
|
11 | var _keys = require('babel-runtime/core-js/object/keys');
|
12 |
|
13 | var _keys2 = _interopRequireDefault(_keys);
|
14 |
|
15 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
16 |
|
17 |
|
18 |
|
19 |
|
20 |
|
21 |
|
22 |
|
23 |
|
24 |
|
25 |
|
26 |
|
27 |
|
28 |
|
29 |
|
30 |
|
31 |
|
32 |
|
33 |
|
34 |
|
35 |
|
36 |
|
37 | var RULEKINDS_IN_ORDER = ['override', 'content', 'room', 'sender', 'underride'];
|
38 |
|
39 |
|
40 |
|
41 |
|
42 |
|
43 |
|
44 | function PushProcessor(client) {
|
45 | var _this = this;
|
46 |
|
47 | var escapeRegExp = function escapeRegExp(string) {
|
48 | return string.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
49 | };
|
50 |
|
51 | var cachedGlobToRegex = {
|
52 |
|
53 | };
|
54 |
|
55 | var matchingRuleFromKindSet = function matchingRuleFromKindSet(ev, kindset, device) {
|
56 | for (var ruleKindIndex = 0; ruleKindIndex < RULEKINDS_IN_ORDER.length; ++ruleKindIndex) {
|
57 | var kind = RULEKINDS_IN_ORDER[ruleKindIndex];
|
58 | var ruleset = kindset[kind];
|
59 |
|
60 | for (var ruleIndex = 0; ruleIndex < ruleset.length; ++ruleIndex) {
|
61 | var rule = ruleset[ruleIndex];
|
62 | if (!rule.enabled) {
|
63 | continue;
|
64 | }
|
65 |
|
66 | var rawrule = templateRuleToRaw(kind, rule, device);
|
67 | if (!rawrule) {
|
68 | continue;
|
69 | }
|
70 |
|
71 | if (_this.ruleMatchesEvent(rawrule, ev)) {
|
72 | rule.kind = kind;
|
73 | return rule;
|
74 | }
|
75 | }
|
76 | }
|
77 | return null;
|
78 | };
|
79 |
|
80 | var templateRuleToRaw = function templateRuleToRaw(kind, tprule, device) {
|
81 | var rawrule = {
|
82 | 'rule_id': tprule.rule_id,
|
83 | 'actions': tprule.actions,
|
84 | 'conditions': []
|
85 | };
|
86 | switch (kind) {
|
87 | case 'underride':
|
88 | case 'override':
|
89 | rawrule.conditions = tprule.conditions;
|
90 | break;
|
91 | case 'room':
|
92 | if (!tprule.rule_id) {
|
93 | return null;
|
94 | }
|
95 | rawrule.conditions.push({
|
96 | 'kind': 'event_match',
|
97 | 'key': 'room_id',
|
98 | 'value': tprule.rule_id
|
99 | });
|
100 | break;
|
101 | case 'sender':
|
102 | if (!tprule.rule_id) {
|
103 | return null;
|
104 | }
|
105 | rawrule.conditions.push({
|
106 | 'kind': 'event_match',
|
107 | 'key': 'user_id',
|
108 | 'value': tprule.rule_id
|
109 | });
|
110 | break;
|
111 | case 'content':
|
112 | if (!tprule.pattern) {
|
113 | return null;
|
114 | }
|
115 | rawrule.conditions.push({
|
116 | 'kind': 'event_match',
|
117 | 'key': 'content.body',
|
118 | 'pattern': tprule.pattern
|
119 | });
|
120 | break;
|
121 | }
|
122 | if (device) {
|
123 | rawrule.conditions.push({
|
124 | 'kind': 'device',
|
125 | 'profile_tag': device
|
126 | });
|
127 | }
|
128 | return rawrule;
|
129 | };
|
130 |
|
131 | var eventFulfillsCondition = function eventFulfillsCondition(cond, ev) {
|
132 | var condition_functions = {
|
133 | "event_match": eventFulfillsEventMatchCondition,
|
134 | "device": eventFulfillsDeviceCondition,
|
135 | "contains_display_name": eventFulfillsDisplayNameCondition,
|
136 | "room_member_count": eventFulfillsRoomMemberCountCondition,
|
137 | "sender_notification_permission": eventFulfillsSenderNotifPermCondition
|
138 | };
|
139 | if (condition_functions[cond.kind]) {
|
140 | return condition_functions[cond.kind](cond, ev);
|
141 | }
|
142 |
|
143 |
|
144 |
|
145 | return false;
|
146 | };
|
147 |
|
148 | var eventFulfillsSenderNotifPermCondition = function eventFulfillsSenderNotifPermCondition(cond, ev) {
|
149 | var notifLevelKey = cond['key'];
|
150 | if (!notifLevelKey) {
|
151 | return false;
|
152 | }
|
153 |
|
154 | var room = client.getRoom(ev.getRoomId());
|
155 | if (!room || !room.currentState) {
|
156 | return false;
|
157 | }
|
158 |
|
159 |
|
160 |
|
161 |
|
162 | return room.currentState.mayTriggerNotifOfType(notifLevelKey, ev.getSender());
|
163 | };
|
164 |
|
165 | var eventFulfillsRoomMemberCountCondition = function eventFulfillsRoomMemberCountCondition(cond, ev) {
|
166 | if (!cond.is) {
|
167 | return false;
|
168 | }
|
169 |
|
170 | var room = client.getRoom(ev.getRoomId());
|
171 | if (!room || !room.currentState || !room.currentState.members) {
|
172 | return false;
|
173 | }
|
174 |
|
175 | var memberCount = room.currentState.getJoinedMemberCount();
|
176 |
|
177 | var m = cond.is.match(/^([=<>]*)([0-9]*)$/);
|
178 | if (!m) {
|
179 | return false;
|
180 | }
|
181 | var ineq = m[1];
|
182 | var rhs = parseInt(m[2]);
|
183 | if (isNaN(rhs)) {
|
184 | return false;
|
185 | }
|
186 | switch (ineq) {
|
187 | case '':
|
188 | case '==':
|
189 | return memberCount == rhs;
|
190 | case '<':
|
191 | return memberCount < rhs;
|
192 | case '>':
|
193 | return memberCount > rhs;
|
194 | case '<=':
|
195 | return memberCount <= rhs;
|
196 | case '>=':
|
197 | return memberCount >= rhs;
|
198 | default:
|
199 | return false;
|
200 | }
|
201 | };
|
202 |
|
203 | var eventFulfillsDisplayNameCondition = function eventFulfillsDisplayNameCondition(cond, ev) {
|
204 | var content = ev.getContent();
|
205 | if (!content || !content.body || typeof content.body != 'string') {
|
206 | return false;
|
207 | }
|
208 |
|
209 | var room = client.getRoom(ev.getRoomId());
|
210 | if (!room || !room.currentState || !room.currentState.members || !room.currentState.getMember(client.credentials.userId)) {
|
211 | return false;
|
212 | }
|
213 |
|
214 | var displayName = room.currentState.getMember(client.credentials.userId).name;
|
215 |
|
216 |
|
217 |
|
218 | var pat = new RegExp("(^|\\W)" + escapeRegExp(displayName) + "(\\W|$)", 'i');
|
219 | return content.body.search(pat) > -1;
|
220 | };
|
221 |
|
222 | var eventFulfillsDeviceCondition = function eventFulfillsDeviceCondition(cond, ev) {
|
223 | return false;
|
224 | };
|
225 |
|
226 | var eventFulfillsEventMatchCondition = function eventFulfillsEventMatchCondition(cond, ev) {
|
227 | if (!cond.key) {
|
228 | return false;
|
229 | }
|
230 |
|
231 | var val = valueForDottedKey(cond.key, ev);
|
232 | if (!val || typeof val != 'string') {
|
233 | return false;
|
234 | }
|
235 |
|
236 | if (cond.value) {
|
237 | return cond.value === val;
|
238 | }
|
239 |
|
240 | var regex = void 0;
|
241 |
|
242 | if (cond.key == 'content.body') {
|
243 | regex = createCachedRegex('(^|\\W)', cond.pattern, '(\\W|$)');
|
244 | } else {
|
245 | regex = createCachedRegex('^', cond.pattern, '$');
|
246 | }
|
247 |
|
248 | return !!val.match(regex);
|
249 | };
|
250 |
|
251 | var createCachedRegex = function createCachedRegex(prefix, glob, suffix) {
|
252 | if (cachedGlobToRegex[glob]) {
|
253 | return cachedGlobToRegex[glob];
|
254 | }
|
255 | cachedGlobToRegex[glob] = new RegExp(prefix + globToRegexp(glob) + suffix, 'i');
|
256 | return cachedGlobToRegex[glob];
|
257 | };
|
258 |
|
259 | var globToRegexp = function globToRegexp(glob) {
|
260 |
|
261 |
|
262 |
|
263 |
|
264 | var pat = escapeRegExp(glob);
|
265 | pat = pat.replace(/\\\*/g, '.*');
|
266 | pat = pat.replace(/\?/g, '.');
|
267 | pat = pat.replace(/\\\[(!|)(.*)\\]/g, function (match, p1, p2, offset, string) {
|
268 | var first = p1 && '^' || '';
|
269 | var second = p2.replace(/\\\-/, '-');
|
270 | return '[' + first + second + ']';
|
271 | });
|
272 | return pat;
|
273 | };
|
274 |
|
275 | var valueForDottedKey = function valueForDottedKey(key, ev) {
|
276 | var parts = key.split('.');
|
277 | var val = void 0;
|
278 |
|
279 |
|
280 | var firstPart = parts[0];
|
281 | if (firstPart == 'content') {
|
282 | val = ev.getContent();
|
283 | parts.shift();
|
284 | } else if (firstPart == 'type') {
|
285 | val = ev.getType();
|
286 | parts.shift();
|
287 | } else {
|
288 |
|
289 | val = ev.event;
|
290 | }
|
291 |
|
292 | while (parts.length > 0) {
|
293 | var thispart = parts.shift();
|
294 | if (!val[thispart]) {
|
295 | return null;
|
296 | }
|
297 | val = val[thispart];
|
298 | }
|
299 | return val;
|
300 | };
|
301 |
|
302 | var matchingRuleForEventWithRulesets = function matchingRuleForEventWithRulesets(ev, rulesets) {
|
303 | if (!rulesets || !rulesets.device) {
|
304 | return null;
|
305 | }
|
306 | if (ev.getSender() == client.credentials.userId) {
|
307 | return null;
|
308 | }
|
309 |
|
310 | var allDevNames = (0, _keys2.default)(rulesets.device);
|
311 | for (var i = 0; i < allDevNames.length; ++i) {
|
312 | var devname = allDevNames[i];
|
313 | var devrules = rulesets.device[devname];
|
314 |
|
315 | var matchingRule = matchingRuleFromKindSet(devrules, devname);
|
316 | if (matchingRule) {
|
317 | return matchingRule;
|
318 | }
|
319 | }
|
320 | return matchingRuleFromKindSet(ev, rulesets.global);
|
321 | };
|
322 |
|
323 | var pushActionsForEventAndRulesets = function pushActionsForEventAndRulesets(ev, rulesets) {
|
324 | var rule = matchingRuleForEventWithRulesets(ev, rulesets);
|
325 | if (!rule) {
|
326 | return {};
|
327 | }
|
328 |
|
329 | var actionObj = PushProcessor.actionListToActionsObject(rule.actions);
|
330 |
|
331 |
|
332 | if (actionObj.tweaks.highlight === undefined) {
|
333 |
|
334 |
|
335 | actionObj.tweaks.highlight = rule.kind == 'content';
|
336 | }
|
337 |
|
338 | return actionObj;
|
339 | };
|
340 |
|
341 | this.ruleMatchesEvent = function (rule, ev) {
|
342 | var ret = true;
|
343 | for (var i = 0; i < rule.conditions.length; ++i) {
|
344 | var cond = rule.conditions[i];
|
345 | ret &= eventFulfillsCondition(cond, ev);
|
346 | }
|
347 |
|
348 | return ret;
|
349 | };
|
350 |
|
351 | |
352 |
|
353 |
|
354 |
|
355 |
|
356 |
|
357 |
|
358 | this.actionsForEvent = function (ev) {
|
359 | return pushActionsForEventAndRulesets(ev, client.pushRules);
|
360 | };
|
361 |
|
362 | |
363 |
|
364 |
|
365 |
|
366 |
|
367 |
|
368 | this.getPushRuleById = function (ruleId) {
|
369 | var _arr = ['device', 'global'];
|
370 |
|
371 | for (var _i = 0; _i < _arr.length; _i++) {
|
372 | var scope = _arr[_i];
|
373 | if (client.pushRules[scope] === undefined) continue;
|
374 |
|
375 | var _iteratorNormalCompletion = true;
|
376 | var _didIteratorError = false;
|
377 | var _iteratorError = undefined;
|
378 |
|
379 | try {
|
380 | for (var _iterator = (0, _getIterator3.default)(RULEKINDS_IN_ORDER), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
|
381 | var kind = _step.value;
|
382 |
|
383 | if (client.pushRules[scope][kind] === undefined) continue;
|
384 |
|
385 | var _iteratorNormalCompletion2 = true;
|
386 | var _didIteratorError2 = false;
|
387 | var _iteratorError2 = undefined;
|
388 |
|
389 | try {
|
390 | for (var _iterator2 = (0, _getIterator3.default)(client.pushRules[scope][kind]), _step2; !(_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done); _iteratorNormalCompletion2 = true) {
|
391 | var rule = _step2.value;
|
392 |
|
393 | if (rule.rule_id === ruleId) return rule;
|
394 | }
|
395 | } catch (err) {
|
396 | _didIteratorError2 = true;
|
397 | _iteratorError2 = err;
|
398 | } finally {
|
399 | try {
|
400 | if (!_iteratorNormalCompletion2 && _iterator2.return) {
|
401 | _iterator2.return();
|
402 | }
|
403 | } finally {
|
404 | if (_didIteratorError2) {
|
405 | throw _iteratorError2;
|
406 | }
|
407 | }
|
408 | }
|
409 | }
|
410 | } catch (err) {
|
411 | _didIteratorError = true;
|
412 | _iteratorError = err;
|
413 | } finally {
|
414 | try {
|
415 | if (!_iteratorNormalCompletion && _iterator.return) {
|
416 | _iterator.return();
|
417 | }
|
418 | } finally {
|
419 | if (_didIteratorError) {
|
420 | throw _iteratorError;
|
421 | }
|
422 | }
|
423 | }
|
424 | }
|
425 | return null;
|
426 | };
|
427 | }
|
428 |
|
429 |
|
430 |
|
431 |
|
432 |
|
433 |
|
434 |
|
435 |
|
436 |
|
437 | PushProcessor.actionListToActionsObject = function (actionlist) {
|
438 | var actionobj = { 'notify': false, 'tweaks': {} };
|
439 | for (var i = 0; i < actionlist.length; ++i) {
|
440 | var action = actionlist[i];
|
441 | if (action === 'notify') {
|
442 | actionobj.notify = true;
|
443 | } else if ((typeof action === 'undefined' ? 'undefined' : (0, _typeof3.default)(action)) === 'object') {
|
444 | if (action.value === undefined) {
|
445 | action.value = true;
|
446 | }
|
447 | actionobj.tweaks[action.set_tweak] = action.value;
|
448 | }
|
449 | }
|
450 | return actionobj;
|
451 | };
|
452 |
|
453 |
|
454 |
|
455 |
|
456 |
|
457 |
|
458 |
|
459 |
|
460 |
|
461 |
|
462 |
|
463 |
|
464 |
|
465 | module.exports = PushProcessor;
|
466 |
|
\ | No newline at end of file |