99 lines
		
	
	
		
			3.2 KiB
		
	
	
	
		
			Python
		
	
	
			
		
		
	
	
			99 lines
		
	
	
		
			3.2 KiB
		
	
	
	
		
			Python
		
	
	
| # -*- coding: utf-8 -*-
 | |
| # Copyright 2015 OpenMarket Ltd
 | |
| #
 | |
| # Licensed under the Apache License, Version 2.0 (the "License");
 | |
| # you may not use this file except in compliance with the License.
 | |
| # You may obtain a copy of the License at
 | |
| #
 | |
| #     http://www.apache.org/licenses/LICENSE-2.0
 | |
| #
 | |
| # Unless required by applicable law or agreed to in writing, software
 | |
| # distributed under the License is distributed on an "AS IS" BASIS,
 | |
| # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | |
| # See the License for the specific language governing permissions and
 | |
| # limitations under the License.
 | |
| 
 | |
| import logging
 | |
| import simplejson as json
 | |
| 
 | |
| from twisted.internet import defer
 | |
| 
 | |
| from synapse.types import UserID
 | |
| 
 | |
| import baserules
 | |
| from push_rule_evaluator import PushRuleEvaluator
 | |
| 
 | |
| logger = logging.getLogger(__name__)
 | |
| 
 | |
| 
 | |
| def decode_rule_json(rule):
 | |
|     rule['conditions'] = json.loads(rule['conditions'])
 | |
|     rule['actions'] = json.loads(rule['actions'])
 | |
|     return rule
 | |
| 
 | |
| 
 | |
| @defer.inlineCallbacks
 | |
| def evaluator_for_room_id(room_id, hs, store):
 | |
|     users = yield store.get_users_in_room(room_id)
 | |
|     rules_by_user = yield store.bulk_get_push_rules(users)
 | |
|     rules_by_user = {
 | |
|         uid: baserules.list_with_base_rules(
 | |
|             [decode_rule_json(rule_list) for rule_list in rules_by_user[uid]]
 | |
|             if uid in rules_by_user else [],
 | |
|             UserID.from_string(uid)
 | |
|         )
 | |
|         for uid in users
 | |
|     }
 | |
|     member_events = yield store.get_current_state(
 | |
|         room_id=room_id,
 | |
|         event_type='m.room.member',
 | |
|     )
 | |
|     display_names = {}
 | |
|     for ev in member_events:
 | |
|         if ev.content.get("displayname"):
 | |
|             display_names[ev.state_key] = ev.content.get("displayname")
 | |
| 
 | |
|     defer.returnValue(BulkPushRuleEvaluator(
 | |
|             room_id, rules_by_user, display_names, users
 | |
|     ))
 | |
| 
 | |
| 
 | |
| class BulkPushRuleEvaluator:
 | |
|     def __init__(self, room_id, rules_by_user, display_names, users_in_room):
 | |
|         self.room_id = room_id
 | |
|         self.rules_by_user = rules_by_user
 | |
|         self.display_names = display_names
 | |
|         self.users_in_room = users_in_room
 | |
| 
 | |
|     def action_for_event_by_user(self, event):
 | |
|         actions_by_user = {}
 | |
| 
 | |
|         for uid, rules in self.rules_by_user.items():
 | |
|             display_name = None
 | |
|             if uid in self.display_names:
 | |
|                 display_name = self.display_names[uid]
 | |
| 
 | |
|             for rule in rules:
 | |
|                 if 'enabled' in rule and not rule['enabled']:
 | |
|                     continue
 | |
| 
 | |
|                 # XXX: profile tags
 | |
|                 if BulkPushRuleEvaluator.event_matches_rule(
 | |
|                     event, rule,
 | |
|                     display_name, len(self.users_in_room), None
 | |
|                 ):
 | |
|                     actions = [x for x in rule['actions'] if x != 'dont_notify']
 | |
|                     if len(actions) > 0:
 | |
|                         actions_by_user[uid] = actions
 | |
|                     break
 | |
|         return actions_by_user
 | |
| 
 | |
|     @staticmethod
 | |
|     def event_matches_rule(event, rule,
 | |
|                            display_name, room_member_count, profile_tag):
 | |
|         matches = True
 | |
|         for cond in rule['conditions']:
 | |
|             matches &= PushRuleEvaluator._event_fulfills_condition(
 | |
|                 event, cond, display_name, room_member_count, profile_tag
 | |
|             )
 | |
|         return matches |