Implement MSC3952: Intentional mentions (#14823)

MSC3952 defines push rules which searches for mentions in a list of
Matrix IDs in the event body, instead of searching the entire event
body for display name / local part.

This is implemented behind an experimental configuration flag and
does not yet implement the backwards compatibility pieces of the MSC.
This commit is contained in:
Patrick Cloke 2023-01-27 10:16:21 -05:00 committed by GitHub
parent faecc6c083
commit 2a51f3ec36
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
11 changed files with 263 additions and 11 deletions

View file

@ -12,7 +12,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.
from typing import Dict, List, Optional, Union, cast
from typing import Dict, List, Optional, Set, Union, cast
import frozendict
@ -39,7 +39,12 @@ from tests.test_utils.event_injection import create_event, inject_member_event
class PushRuleEvaluatorTestCase(unittest.TestCase):
def _get_evaluator(
self, content: JsonMapping, related_events: Optional[JsonDict] = None
self,
content: JsonMapping,
*,
user_mentions: Optional[Set[str]] = None,
room_mention: bool = False,
related_events: Optional[JsonDict] = None,
) -> PushRuleEvaluator:
event = FrozenEvent(
{
@ -57,13 +62,15 @@ class PushRuleEvaluatorTestCase(unittest.TestCase):
power_levels: Dict[str, Union[int, Dict[str, int]]] = {}
return PushRuleEvaluator(
_flatten_dict(event),
user_mentions or set(),
room_mention,
room_member_count,
sender_power_level,
cast(Dict[str, int], power_levels.get("notifications", {})),
{} if related_events is None else related_events,
True,
event.room_version.msc3931_push_features,
True,
related_event_match_enabled=True,
room_version_feature_flags=event.room_version.msc3931_push_features,
msc3931_enabled=True,
)
def test_display_name(self) -> None:
@ -90,6 +97,51 @@ class PushRuleEvaluatorTestCase(unittest.TestCase):
# A display name with spaces should work fine.
self.assertTrue(evaluator.matches(condition, "@user:test", "foo bar"))
def test_user_mentions(self) -> None:
"""Check for user mentions."""
condition = {"kind": "org.matrix.msc3952.is_user_mention"}
# No mentions shouldn't match.
evaluator = self._get_evaluator({})
self.assertFalse(evaluator.matches(condition, "@user:test", None))
# An empty set shouldn't match
evaluator = self._get_evaluator({}, user_mentions=set())
self.assertFalse(evaluator.matches(condition, "@user:test", None))
# The Matrix ID appearing anywhere in the mentions list should match
evaluator = self._get_evaluator({}, user_mentions={"@user:test"})
self.assertTrue(evaluator.matches(condition, "@user:test", None))
evaluator = self._get_evaluator(
{}, user_mentions={"@another:test", "@user:test"}
)
self.assertTrue(evaluator.matches(condition, "@user:test", None))
# Note that invalid data is tested at tests.push.test_bulk_push_rule_evaluator.TestBulkPushRuleEvaluator.test_mentions
# since the BulkPushRuleEvaluator is what handles data sanitisation.
def test_room_mentions(self) -> None:
"""Check for room mentions."""
condition = {"kind": "org.matrix.msc3952.is_room_mention"}
# No room mention shouldn't match.
evaluator = self._get_evaluator({})
self.assertFalse(evaluator.matches(condition, None, None))
# Room mention should match.
evaluator = self._get_evaluator({}, room_mention=True)
self.assertTrue(evaluator.matches(condition, None, None))
# A room mention and user mention is valid.
evaluator = self._get_evaluator(
{}, user_mentions={"@another:test"}, room_mention=True
)
self.assertTrue(evaluator.matches(condition, None, None))
# Note that invalid data is tested at tests.push.test_bulk_push_rule_evaluator.TestBulkPushRuleEvaluator.test_mentions
# since the BulkPushRuleEvaluator is what handles data sanitisation.
def _assert_matches(
self, condition: JsonDict, content: JsonMapping, msg: Optional[str] = None
) -> None:
@ -308,7 +360,7 @@ class PushRuleEvaluatorTestCase(unittest.TestCase):
},
}
},
{
related_events={
"m.in_reply_to": {
"event_id": "$parent_event_id",
"type": "m.room.message",
@ -408,7 +460,7 @@ class PushRuleEvaluatorTestCase(unittest.TestCase):
},
}
},
{
related_events={
"m.in_reply_to": {
"event_id": "$parent_event_id",
"type": "m.room.message",