feat: support push rule conditions event_property_is & event_property_contains
This commit is contained in:
parent
735190cd78
commit
239a39e2cb
|
|
@ -2188,7 +2188,11 @@ class Room {
|
|||
id,
|
||||
[],
|
||||
conditions: [
|
||||
PushCondition(kind: 'event_match', key: 'room_id', pattern: id),
|
||||
PushCondition(
|
||||
kind: PushRuleConditions.eventMatch.name,
|
||||
key: 'room_id',
|
||||
pattern: id,
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,8 +18,26 @@
|
|||
|
||||
// Helper for fast evaluation of push conditions on a bunch of events
|
||||
|
||||
import 'package:collection/collection.dart';
|
||||
|
||||
import 'package:matrix/matrix.dart';
|
||||
|
||||
enum PushRuleConditions {
|
||||
eventMatch('event_match'),
|
||||
eventPropertyIs('event_property_is'),
|
||||
eventPropertyContains('event_property_contains'),
|
||||
containsDisplayName('contains_display_name'),
|
||||
roomMemberCount('room_member_count'),
|
||||
senderNotificationPermission('sender_notification_permission');
|
||||
|
||||
final String name;
|
||||
const PushRuleConditions(this.name);
|
||||
|
||||
static PushRuleConditions? fromString(String name) {
|
||||
return values.firstWhereOrNull((e) => e.name == name);
|
||||
}
|
||||
}
|
||||
|
||||
class EvaluatedPushRuleAction {
|
||||
// if this message should be highlighted.
|
||||
bool highlight = false;
|
||||
|
|
@ -56,24 +74,20 @@ class _PatternCondition {
|
|||
String field = '';
|
||||
|
||||
_PatternCondition.fromEventMatch(PushCondition condition) {
|
||||
if (condition.kind != 'event_match') {
|
||||
if (condition.kind != PushRuleConditions.eventMatch.name) {
|
||||
throw 'Logic error: invalid push rule passed to constructor ${condition.kind}';
|
||||
}
|
||||
|
||||
final tempField = condition.key;
|
||||
if (tempField == null) {
|
||||
{
|
||||
throw 'No field to match pattern on!';
|
||||
}
|
||||
}
|
||||
field = tempField;
|
||||
|
||||
var tempPat = condition.pattern;
|
||||
if (tempPat == null) {
|
||||
{
|
||||
throw 'PushCondition is missing pattern';
|
||||
}
|
||||
}
|
||||
tempPat =
|
||||
RegExp.escape(tempPat).replaceAll('\\*', '.*').replaceAll('\\?', '.');
|
||||
|
||||
|
|
@ -84,15 +98,60 @@ class _PatternCondition {
|
|||
}
|
||||
}
|
||||
|
||||
bool match(Map<String, String> content) {
|
||||
final fieldContent = content[field];
|
||||
if (fieldContent == null) {
|
||||
bool match(Map<String, Object?> flattenedEventJson) {
|
||||
final fieldContent = flattenedEventJson[field];
|
||||
if (fieldContent == null || fieldContent is! String) {
|
||||
return false;
|
||||
}
|
||||
return pattern.hasMatch(fieldContent);
|
||||
}
|
||||
}
|
||||
|
||||
class _EventPropertyCondition {
|
||||
PushRuleConditions? kind;
|
||||
// what field to match on, i.e. content.body
|
||||
String field = '';
|
||||
Object? value;
|
||||
|
||||
_EventPropertyCondition.fromEventMatch(PushCondition condition) {
|
||||
if (![
|
||||
PushRuleConditions.eventPropertyIs.name,
|
||||
PushRuleConditions.eventPropertyContains.name,
|
||||
].contains(condition.kind)) {
|
||||
throw 'Logic error: invalid push rule passed to constructor ${condition.kind}';
|
||||
}
|
||||
kind = PushRuleConditions.fromString(condition.kind);
|
||||
|
||||
final tempField = condition.key;
|
||||
if (tempField == null) {
|
||||
throw 'No field to check event property on!';
|
||||
}
|
||||
field = tempField;
|
||||
|
||||
final tempValue = condition.value;
|
||||
if (![String, int, bool, Null].contains(tempValue.runtimeType)) {
|
||||
throw 'PushCondition value is not a string, int, bool or null';
|
||||
}
|
||||
value = tempValue;
|
||||
}
|
||||
|
||||
bool match(Map<String, Object?> flattenedEventJson) {
|
||||
final fieldContent = flattenedEventJson[field];
|
||||
switch (kind) {
|
||||
case PushRuleConditions.eventPropertyIs:
|
||||
// We check if the property exists because null is a valid property value.
|
||||
if (!flattenedEventJson.keys.contains(field)) return false;
|
||||
return fieldContent == value;
|
||||
case PushRuleConditions.eventPropertyContains:
|
||||
if (fieldContent is! Iterable) return false;
|
||||
return fieldContent.contains(value);
|
||||
default:
|
||||
// This should never happen
|
||||
throw 'Logic error: invalid push rule passed in _EventPropertyCondition ${kind?.name}';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
enum _CountComparisonOp {
|
||||
eq,
|
||||
lt,
|
||||
|
|
@ -106,7 +165,7 @@ class _MemberCountCondition {
|
|||
int count = 0;
|
||||
|
||||
_MemberCountCondition.fromEventMatch(PushCondition condition) {
|
||||
if (condition.kind != 'room_member_count') {
|
||||
if (condition.kind != PushRuleConditions.roomMemberCount.name) {
|
||||
throw 'Logic error: invalid push rule passed to constructor ${condition.kind}';
|
||||
}
|
||||
|
||||
|
|
@ -160,6 +219,7 @@ class _MemberCountCondition {
|
|||
|
||||
class _OptimizedRules {
|
||||
List<_PatternCondition> patterns = [];
|
||||
List<_EventPropertyCondition> eventProperties = [];
|
||||
List<_MemberCountCondition> memberCounts = [];
|
||||
List<String> notificationPermissions = [];
|
||||
bool matchDisplayname = false;
|
||||
|
|
@ -168,18 +228,24 @@ class _OptimizedRules {
|
|||
_OptimizedRules.fromRule(PushRule rule) {
|
||||
if (!rule.enabled) return;
|
||||
|
||||
for (final condition in rule.conditions ?? []) {
|
||||
switch (condition.kind) {
|
||||
case 'event_match':
|
||||
for (final condition in rule.conditions ?? <PushCondition>[]) {
|
||||
final kind = PushRuleConditions.fromString(condition.kind);
|
||||
switch (kind) {
|
||||
case PushRuleConditions.eventMatch:
|
||||
patterns.add(_PatternCondition.fromEventMatch(condition));
|
||||
break;
|
||||
case 'contains_display_name':
|
||||
case PushRuleConditions.eventPropertyIs:
|
||||
case PushRuleConditions.eventPropertyContains:
|
||||
eventProperties
|
||||
.add(_EventPropertyCondition.fromEventMatch(condition));
|
||||
break;
|
||||
case PushRuleConditions.containsDisplayName:
|
||||
matchDisplayname = true;
|
||||
break;
|
||||
case 'room_member_count':
|
||||
case PushRuleConditions.roomMemberCount:
|
||||
memberCounts.add(_MemberCountCondition.fromEventMatch(condition));
|
||||
break;
|
||||
case 'sender_notification_permission':
|
||||
case PushRuleConditions.senderNotificationPermission:
|
||||
final key = condition.key;
|
||||
if (key != null) {
|
||||
notificationPermissions.add(key);
|
||||
|
|
@ -193,19 +259,22 @@ class _OptimizedRules {
|
|||
}
|
||||
|
||||
EvaluatedPushRuleAction? match(
|
||||
Map<String, String> event,
|
||||
Map<String, Object?> flattenedEventJson,
|
||||
String? displayName,
|
||||
int memberCount,
|
||||
Room room,
|
||||
) {
|
||||
if (patterns.any((pat) => !pat.match(event))) {
|
||||
if (patterns.any((pat) => !pat.match(flattenedEventJson))) {
|
||||
return null;
|
||||
}
|
||||
if (eventProperties.any((pat) => !pat.match(flattenedEventJson))) {
|
||||
return null;
|
||||
}
|
||||
if (memberCounts.any((pat) => !pat.match(memberCount))) {
|
||||
return null;
|
||||
}
|
||||
if (matchDisplayname) {
|
||||
final body = event.tryGet<String>('content.body');
|
||||
final body = flattenedEventJson.tryGet<String>('content.body');
|
||||
if (displayName == null || body == null) {
|
||||
return null;
|
||||
}
|
||||
|
|
@ -220,7 +289,7 @@ class _OptimizedRules {
|
|||
}
|
||||
|
||||
if (notificationPermissions.isNotEmpty) {
|
||||
final sender = event.tryGet<String>('sender');
|
||||
final sender = flattenedEventJson.tryGet<String>('sender');
|
||||
if (sender == null ||
|
||||
notificationPermissions.any(
|
||||
(notificationType) => !room.canSendNotification(
|
||||
|
|
@ -244,7 +313,7 @@ class PushruleEvaluator {
|
|||
final List<_OptimizedRules> _underride = [];
|
||||
|
||||
PushruleEvaluator.fromRuleset(PushRuleSet ruleset) {
|
||||
for (final o in ruleset.override ?? []) {
|
||||
for (final o in ruleset.override ?? <PushRule>[]) {
|
||||
if (!o.enabled) continue;
|
||||
try {
|
||||
_override.add(_OptimizedRules.fromRule(o));
|
||||
|
|
@ -252,7 +321,7 @@ class PushruleEvaluator {
|
|||
Logs().d('Error parsing push rule $o', e);
|
||||
}
|
||||
}
|
||||
for (final u in ruleset.underride ?? []) {
|
||||
for (final u in ruleset.underride ?? <PushRule>[]) {
|
||||
if (!u.enabled) continue;
|
||||
try {
|
||||
_underride.add(_OptimizedRules.fromRule(u));
|
||||
|
|
@ -260,13 +329,13 @@ class PushruleEvaluator {
|
|||
Logs().d('Error parsing push rule $u', e);
|
||||
}
|
||||
}
|
||||
for (final c in ruleset.content ?? []) {
|
||||
for (final c in ruleset.content ?? <PushRule>[]) {
|
||||
if (!c.enabled) continue;
|
||||
final rule = PushRule(
|
||||
actions: c.actions,
|
||||
conditions: [
|
||||
PushCondition(
|
||||
kind: 'event_match',
|
||||
kind: PushRuleConditions.eventMatch.name,
|
||||
key: 'content.body',
|
||||
pattern: c.pattern,
|
||||
),
|
||||
|
|
@ -281,12 +350,12 @@ class PushruleEvaluator {
|
|||
Logs().d('Error parsing push rule $rule', e);
|
||||
}
|
||||
}
|
||||
for (final r in ruleset.room ?? []) {
|
||||
for (final r in ruleset.room ?? <PushRule>[]) {
|
||||
if (r.enabled) {
|
||||
_room_rules[r.ruleId] = EvaluatedPushRuleAction.fromActions(r.actions);
|
||||
}
|
||||
}
|
||||
for (final r in ruleset.sender ?? []) {
|
||||
for (final r in ruleset.sender ?? <PushRule>[]) {
|
||||
if (r.enabled) {
|
||||
_sender_rules[r.ruleId] =
|
||||
EvaluatedPushRuleAction.fromActions(r.actions);
|
||||
|
|
@ -294,18 +363,18 @@ class PushruleEvaluator {
|
|||
}
|
||||
}
|
||||
|
||||
Map<String, String> _flattenJson(
|
||||
Map<String, Object?> _flattenJson(
|
||||
Map<String, dynamic> obj,
|
||||
Map<String, String> flattened,
|
||||
Map<String, Object?> flattened,
|
||||
String prefix,
|
||||
) {
|
||||
for (final entry in obj.entries) {
|
||||
final key = prefix == '' ? entry.key : '$prefix.${entry.key}';
|
||||
final value = entry.value;
|
||||
if (value is String) {
|
||||
flattened[key] = value;
|
||||
} else if (value is Map<String, dynamic>) {
|
||||
if (value is Map<String, dynamic>) {
|
||||
flattened = _flattenJson(value, flattened, key);
|
||||
} else {
|
||||
flattened[key] = value;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -317,12 +386,13 @@ class PushruleEvaluator {
|
|||
final displayName = event.room
|
||||
.unsafeGetUserFromMemoryOrFallback(event.room.client.userID!)
|
||||
.displayName;
|
||||
final content = _flattenJson(event.toJson(), {}, '');
|
||||
final flattenedEventJson = _flattenJson(event.toJson(), {}, '');
|
||||
// ensure roomid is present
|
||||
content['room_id'] = event.room.id;
|
||||
flattenedEventJson['room_id'] = event.room.id;
|
||||
|
||||
for (final o in _override) {
|
||||
final actions = o.match(content, displayName, memberCount, event.room);
|
||||
final actions =
|
||||
o.match(flattenedEventJson, displayName, memberCount, event.room);
|
||||
if (actions != null) {
|
||||
return actions;
|
||||
}
|
||||
|
|
@ -339,14 +409,16 @@ class PushruleEvaluator {
|
|||
}
|
||||
|
||||
for (final o in _content_rules) {
|
||||
final actions = o.match(content, displayName, memberCount, event.room);
|
||||
final actions =
|
||||
o.match(flattenedEventJson, displayName, memberCount, event.room);
|
||||
if (actions != null) {
|
||||
return actions;
|
||||
}
|
||||
}
|
||||
|
||||
for (final o in _underride) {
|
||||
final actions = o.match(content, displayName, memberCount, event.room);
|
||||
final actions =
|
||||
o.match(flattenedEventJson, displayName, memberCount, event.room);
|
||||
if (actions != null) {
|
||||
return actions;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -23,6 +23,22 @@ import 'package:test/test.dart';
|
|||
import 'package:matrix/matrix.dart';
|
||||
import 'fake_client.dart';
|
||||
|
||||
void _testMatch(PushRuleSet ruleset, Event event) {
|
||||
final evaluator = PushruleEvaluator.fromRuleset(ruleset);
|
||||
final actions = evaluator.match(event);
|
||||
expect(actions.notify, true);
|
||||
expect(actions.highlight, true);
|
||||
expect(actions.sound, 'goose.wav');
|
||||
}
|
||||
|
||||
void _testNotMatch(PushRuleSet ruleset, Event event) {
|
||||
final evaluator = PushruleEvaluator.fromRuleset(ruleset);
|
||||
final actions = evaluator.match(event);
|
||||
expect(actions.notify, false);
|
||||
expect(actions.highlight, false);
|
||||
expect(actions.sound, null);
|
||||
}
|
||||
|
||||
void main() {
|
||||
/// All Tests related to the Event
|
||||
group('Event', () {
|
||||
|
|
@ -145,62 +161,46 @@ void main() {
|
|||
],
|
||||
);
|
||||
|
||||
void testMatch(PushRuleSet ruleset, Event event) {
|
||||
final evaluator = PushruleEvaluator.fromRuleset(ruleset);
|
||||
final actions = evaluator.match(event);
|
||||
expect(actions.notify, true);
|
||||
expect(actions.highlight, true);
|
||||
expect(actions.sound, 'goose.wav');
|
||||
}
|
||||
|
||||
void testNotMatch(PushRuleSet ruleset, Event event) {
|
||||
final evaluator = PushruleEvaluator.fromRuleset(ruleset);
|
||||
final actions = evaluator.match(event);
|
||||
expect(actions.notify, false);
|
||||
expect(actions.highlight, false);
|
||||
expect(actions.sound, null);
|
||||
}
|
||||
|
||||
testMatch(override_ruleset, event);
|
||||
testMatch(underride_ruleset, event);
|
||||
testMatch(content_ruleset, event);
|
||||
testMatch(room_ruleset, event);
|
||||
testMatch(sender_ruleset, event);
|
||||
_testMatch(override_ruleset, event);
|
||||
_testMatch(underride_ruleset, event);
|
||||
_testMatch(content_ruleset, event);
|
||||
_testMatch(room_ruleset, event);
|
||||
_testMatch(sender_ruleset, event);
|
||||
|
||||
event.content['body'] = 'FoX';
|
||||
testMatch(override_ruleset, event);
|
||||
testMatch(underride_ruleset, event);
|
||||
testMatch(content_ruleset, event);
|
||||
testMatch(room_ruleset, event);
|
||||
testMatch(sender_ruleset, event);
|
||||
_testMatch(override_ruleset, event);
|
||||
_testMatch(underride_ruleset, event);
|
||||
_testMatch(content_ruleset, event);
|
||||
_testMatch(room_ruleset, event);
|
||||
_testMatch(sender_ruleset, event);
|
||||
|
||||
event.content['body'] = '@FoX:';
|
||||
testMatch(override_ruleset, event);
|
||||
testMatch(underride_ruleset, event);
|
||||
testMatch(content_ruleset, event);
|
||||
testMatch(room_ruleset, event);
|
||||
testMatch(sender_ruleset, event);
|
||||
_testMatch(override_ruleset, event);
|
||||
_testMatch(underride_ruleset, event);
|
||||
_testMatch(content_ruleset, event);
|
||||
_testMatch(room_ruleset, event);
|
||||
_testMatch(sender_ruleset, event);
|
||||
|
||||
event.content['body'] = 'äFoXü';
|
||||
testMatch(override_ruleset, event);
|
||||
testMatch(underride_ruleset, event);
|
||||
testMatch(content_ruleset, event);
|
||||
testMatch(room_ruleset, event);
|
||||
testMatch(sender_ruleset, event);
|
||||
_testMatch(override_ruleset, event);
|
||||
_testMatch(underride_ruleset, event);
|
||||
_testMatch(content_ruleset, event);
|
||||
_testMatch(room_ruleset, event);
|
||||
_testMatch(sender_ruleset, event);
|
||||
|
||||
event.content['body'] = 'äFoXu';
|
||||
testNotMatch(override_ruleset, event);
|
||||
testNotMatch(underride_ruleset, event);
|
||||
testNotMatch(content_ruleset, event);
|
||||
testMatch(room_ruleset, event);
|
||||
testMatch(sender_ruleset, event);
|
||||
_testNotMatch(override_ruleset, event);
|
||||
_testNotMatch(underride_ruleset, event);
|
||||
_testNotMatch(content_ruleset, event);
|
||||
_testMatch(room_ruleset, event);
|
||||
_testMatch(sender_ruleset, event);
|
||||
|
||||
event.content['body'] = 'aFoXü';
|
||||
testNotMatch(override_ruleset, event);
|
||||
testNotMatch(underride_ruleset, event);
|
||||
testNotMatch(content_ruleset, event);
|
||||
testMatch(room_ruleset, event);
|
||||
testMatch(sender_ruleset, event);
|
||||
_testNotMatch(override_ruleset, event);
|
||||
_testNotMatch(underride_ruleset, event);
|
||||
_testNotMatch(content_ruleset, event);
|
||||
_testMatch(room_ruleset, event);
|
||||
_testMatch(sender_ruleset, event);
|
||||
|
||||
final override_ruleset2 = PushRuleSet(
|
||||
override: [
|
||||
|
|
@ -224,22 +224,25 @@ void main() {
|
|||
],
|
||||
);
|
||||
|
||||
testMatch(override_ruleset2, event);
|
||||
_testMatch(override_ruleset2, event);
|
||||
event.senderId = '@nope:server.tld';
|
||||
testNotMatch(override_ruleset2, event);
|
||||
_testNotMatch(override_ruleset2, event);
|
||||
event.senderId = '${senderID}a';
|
||||
testNotMatch(override_ruleset2, event);
|
||||
_testNotMatch(override_ruleset2, event);
|
||||
event.senderId = 'a$senderID';
|
||||
testNotMatch(override_ruleset2, event);
|
||||
_testNotMatch(override_ruleset2, event);
|
||||
|
||||
event.senderId = senderID;
|
||||
testMatch(override_ruleset2, event);
|
||||
_testMatch(override_ruleset2, event);
|
||||
override_ruleset2.override?[0].enabled = false;
|
||||
testNotMatch(override_ruleset2, event);
|
||||
_testNotMatch(override_ruleset2, event);
|
||||
});
|
||||
|
||||
test('invalid push condition', () async {
|
||||
final invalid_ruleset = PushRuleSet(
|
||||
test('event_property_is rule', () async {
|
||||
final event = Event.fromJson(jsonObj, room);
|
||||
event.content['body'] = 'Hello fox';
|
||||
|
||||
final ruleset = PushRuleSet(
|
||||
override: [
|
||||
PushRule(
|
||||
ruleId: 'my.rule',
|
||||
|
|
@ -252,26 +255,81 @@ void main() {
|
|||
],
|
||||
conditions: [
|
||||
PushCondition(
|
||||
kind: 'invalidcondition',
|
||||
pattern: 'fox',
|
||||
kind: 'event_property_is',
|
||||
key: 'content.body',
|
||||
value: 'Hello fox',
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
);
|
||||
|
||||
expect(
|
||||
() => PushruleEvaluator.fromRuleset(invalid_ruleset),
|
||||
returnsNormally,
|
||||
);
|
||||
_testMatch(ruleset, event);
|
||||
|
||||
final evaluator = PushruleEvaluator.fromRuleset(invalid_ruleset);
|
||||
event.content['body'] = 'Hello Fox';
|
||||
_testNotMatch(ruleset, event);
|
||||
|
||||
event.content['body'] = null;
|
||||
ruleset.override?[0].conditions?[0].value = null;
|
||||
_testMatch(ruleset, event);
|
||||
|
||||
event.content['body'] = true;
|
||||
_testNotMatch(ruleset, event);
|
||||
|
||||
ruleset.override?[0].conditions?[0].value = true;
|
||||
_testMatch(ruleset, event);
|
||||
|
||||
event.content['body'] = 12345;
|
||||
_testNotMatch(ruleset, event);
|
||||
|
||||
ruleset.override?[0].conditions?[0].value = 12345;
|
||||
_testMatch(ruleset, event);
|
||||
});
|
||||
|
||||
test('event_property_contains rule', () async {
|
||||
final event = Event.fromJson(jsonObj, room);
|
||||
final actions = evaluator.match(event);
|
||||
expect(actions.highlight, false);
|
||||
expect(actions.sound, null);
|
||||
expect(actions.notify, false);
|
||||
|
||||
final ruleset = PushRuleSet(
|
||||
override: [
|
||||
PushRule(
|
||||
ruleId: 'my.rule',
|
||||
default$: false,
|
||||
enabled: true,
|
||||
actions: [
|
||||
'notify',
|
||||
{'set_tweak': 'highlight', 'value': true},
|
||||
{'set_tweak': 'sound', 'value': 'goose.wav'},
|
||||
],
|
||||
conditions: [
|
||||
PushCondition(
|
||||
kind: 'event_property_contains',
|
||||
key: 'content.body',
|
||||
value: 'Fox',
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
);
|
||||
|
||||
_testNotMatch(ruleset, event);
|
||||
|
||||
event.content['body'] = [];
|
||||
_testNotMatch(ruleset, event);
|
||||
|
||||
event.content['body'] = null;
|
||||
_testNotMatch(ruleset, event);
|
||||
|
||||
event.content['body'] = ['Fox'];
|
||||
_testMatch(ruleset, event);
|
||||
|
||||
ruleset.override?[0].conditions?[0].value = true;
|
||||
_testNotMatch(ruleset, event);
|
||||
|
||||
event.content['body'] = [12345, true];
|
||||
_testMatch(ruleset, event);
|
||||
|
||||
ruleset.override?[0].conditions?[0].value = 12345;
|
||||
_testMatch(ruleset, event);
|
||||
});
|
||||
|
||||
test('match_display_name rule', () async {
|
||||
|
|
@ -306,17 +364,12 @@ void main() {
|
|||
),
|
||||
],
|
||||
);
|
||||
event.content['body'] = 'äNicoü';
|
||||
|
||||
final evaluator = PushruleEvaluator.fromRuleset(ruleset);
|
||||
var actions = evaluator.match(event);
|
||||
expect(actions.notify, true);
|
||||
expect(actions.highlight, true);
|
||||
expect(actions.sound, 'goose.wav');
|
||||
event.content['body'] = 'äNicoü';
|
||||
_testMatch(ruleset, event);
|
||||
|
||||
event.content['body'] = 'äNicou';
|
||||
actions = evaluator.match(event);
|
||||
expect(actions.notify, false);
|
||||
_testNotMatch(ruleset, event);
|
||||
});
|
||||
|
||||
test('member_count rule', () async {
|
||||
|
|
@ -352,33 +405,25 @@ void main() {
|
|||
],
|
||||
);
|
||||
event.content['body'] = 'äNicoü';
|
||||
|
||||
var evaluator = PushruleEvaluator.fromRuleset(ruleset);
|
||||
expect(evaluator.match(event).notify, true);
|
||||
_testMatch(ruleset, event);
|
||||
|
||||
ruleset.override?[0].conditions?[0].is$ = '<=0';
|
||||
evaluator = PushruleEvaluator.fromRuleset(ruleset);
|
||||
expect(evaluator.match(event).notify, false);
|
||||
_testNotMatch(ruleset, event);
|
||||
|
||||
ruleset.override?[0].conditions?[0].is$ = '<=1';
|
||||
evaluator = PushruleEvaluator.fromRuleset(ruleset);
|
||||
expect(evaluator.match(event).notify, true);
|
||||
_testMatch(ruleset, event);
|
||||
|
||||
ruleset.override?[0].conditions?[0].is$ = '>=1';
|
||||
evaluator = PushruleEvaluator.fromRuleset(ruleset);
|
||||
expect(evaluator.match(event).notify, true);
|
||||
_testMatch(ruleset, event);
|
||||
|
||||
ruleset.override?[0].conditions?[0].is$ = '>1';
|
||||
evaluator = PushruleEvaluator.fromRuleset(ruleset);
|
||||
expect(evaluator.match(event).notify, false);
|
||||
_testNotMatch(ruleset, event);
|
||||
|
||||
ruleset.override?[0].conditions?[0].is$ = '==1';
|
||||
evaluator = PushruleEvaluator.fromRuleset(ruleset);
|
||||
expect(evaluator.match(event).notify, true);
|
||||
_testMatch(ruleset, event);
|
||||
|
||||
ruleset.override?[0].conditions?[0].is$ = '1';
|
||||
evaluator = PushruleEvaluator.fromRuleset(ruleset);
|
||||
expect(evaluator.match(event).notify, true);
|
||||
_testMatch(ruleset, event);
|
||||
});
|
||||
|
||||
test('notification permissions rule', () async {
|
||||
|
|
@ -420,11 +465,42 @@ void main() {
|
|||
],
|
||||
);
|
||||
|
||||
final evaluator = PushruleEvaluator.fromRuleset(ruleset);
|
||||
expect(evaluator.match(event).notify, true);
|
||||
_testMatch(ruleset, event);
|
||||
|
||||
event.senderId = '@a:b.c';
|
||||
expect(evaluator.match(event).notify, false);
|
||||
_testNotMatch(ruleset, event);
|
||||
});
|
||||
|
||||
test('invalid push condition', () async {
|
||||
final invalid_ruleset = PushRuleSet(
|
||||
override: [
|
||||
PushRule(
|
||||
ruleId: 'my.rule',
|
||||
default$: false,
|
||||
enabled: true,
|
||||
actions: [
|
||||
'notify',
|
||||
{'set_tweak': 'highlight', 'value': true},
|
||||
{'set_tweak': 'sound', 'value': 'goose.wav'},
|
||||
],
|
||||
conditions: [
|
||||
PushCondition(
|
||||
kind: 'invalidcondition',
|
||||
pattern: 'fox',
|
||||
key: 'content.body',
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
);
|
||||
|
||||
expect(
|
||||
() => PushruleEvaluator.fromRuleset(invalid_ruleset),
|
||||
returnsNormally,
|
||||
);
|
||||
|
||||
final event = Event.fromJson(jsonObj, room);
|
||||
_testNotMatch(invalid_ruleset, event);
|
||||
});
|
||||
|
||||
test('invalid content rule', () async {
|
||||
|
|
|
|||
Loading…
Reference in New Issue