* Add support for MSC3931: Room Version Supports push rule condition * Create experimental flag for future work, and use it to gate MSC3931 * Changelog entrytags/v1.73.0rc1
@@ -0,0 +1 @@ | |||
Add unstable support for an Extensible Events room version (`org.matrix.msc1767.10`) via [MSC1767](https://github.com/matrix-org/matrix-spec-proposals/pull/1767), [MSC3931](https://github.com/matrix-org/matrix-spec-proposals/pull/3931), [MSC3932](https://github.com/matrix-org/matrix-spec-proposals/pull/3932), and [MSC3933](https://github.com/matrix-org/matrix-spec-proposals/pull/3933). |
@@ -29,6 +29,10 @@ use super::{ | |||
lazy_static! { | |||
/// Used to parse the `is` clause in the room member count condition. | |||
static ref INEQUALITY_EXPR: Regex = Regex::new(r"^([=<>]*)([0-9]+)$").expect("valid regex"); | |||
/// Used to determine which MSC3931 room version feature flags are actually known to | |||
/// the push evaluator. | |||
static ref KNOWN_RVER_FLAGS: Vec<String> = vec![]; | |||
} | |||
/// Allows running a set of push rules against a particular event. | |||
@@ -57,6 +61,13 @@ pub struct PushRuleEvaluator { | |||
/// If msc3664, push rules for related events, is enabled. | |||
related_event_match_enabled: bool, | |||
/// If MSC3931 is applicable, the feature flags for the room version. | |||
room_version_feature_flags: Vec<String>, | |||
/// If MSC3931 (room version feature flags) is enabled. Usually controlled by the same | |||
/// flag as MSC1767 (extensible events core). | |||
msc3931_enabled: bool, | |||
} | |||
#[pymethods] | |||
@@ -70,6 +81,8 @@ impl PushRuleEvaluator { | |||
notification_power_levels: BTreeMap<String, i64>, | |||
related_events_flattened: BTreeMap<String, BTreeMap<String, String>>, | |||
related_event_match_enabled: bool, | |||
room_version_feature_flags: Vec<String>, | |||
msc3931_enabled: bool, | |||
) -> Result<Self, Error> { | |||
let body = flattened_keys | |||
.get("content.body") | |||
@@ -84,6 +97,8 @@ impl PushRuleEvaluator { | |||
sender_power_level, | |||
related_events_flattened, | |||
related_event_match_enabled, | |||
room_version_feature_flags, | |||
msc3931_enabled, | |||
}) | |||
} | |||
@@ -204,6 +219,15 @@ impl PushRuleEvaluator { | |||
false | |||
} | |||
} | |||
KnownCondition::RoomVersionSupports { feature } => { | |||
if !self.msc3931_enabled { | |||
false | |||
} else { | |||
let flag = feature.to_string(); | |||
KNOWN_RVER_FLAGS.contains(&flag) | |||
&& self.room_version_feature_flags.contains(&flag) | |||
} | |||
} | |||
}; | |||
Ok(result) | |||
@@ -362,6 +386,8 @@ fn push_rule_evaluator() { | |||
BTreeMap::new(), | |||
BTreeMap::new(), | |||
true, | |||
vec![], | |||
true, | |||
) | |||
.unwrap(); | |||
@@ -277,6 +277,10 @@ pub enum KnownCondition { | |||
SenderNotificationPermission { | |||
key: Cow<'static, str>, | |||
}, | |||
#[serde(rename = "org.matrix.msc3931.room_version_supports")] | |||
RoomVersionSupports { | |||
feature: Cow<'static, str>, | |||
}, | |||
} | |||
impl IntoPy<PyObject> for Condition { | |||
@@ -491,6 +495,18 @@ fn test_deserialize_unstable_msc3664_condition() { | |||
)); | |||
} | |||
#[test] | |||
fn test_deserialize_unstable_msc3931_condition() { | |||
let json = | |||
r#"{"kind":"org.matrix.msc3931.room_version_supports","feature":"org.example.feature"}"#; | |||
let condition: Condition = serde_json::from_str(json).unwrap(); | |||
assert!(matches!( | |||
condition, | |||
Condition::Known(KnownCondition::RoomVersionSupports { feature: _ }) | |||
)); | |||
} | |||
#[test] | |||
fn test_deserialize_custom_condition() { | |||
let json = r#"{"kind":"custom_tag"}"#; | |||
@@ -41,6 +41,8 @@ class PushRuleEvaluator: | |||
notification_power_levels: Mapping[str, int], | |||
related_events_flattened: Mapping[str, Mapping[str, str]], | |||
related_event_match_enabled: bool, | |||
room_version_feature_flags: list[str], | |||
msc3931_enabled: bool, | |||
): ... | |||
def run( | |||
self, | |||
@@ -12,7 +12,7 @@ | |||
# See the License for the specific language governing permissions and | |||
# limitations under the License. | |||
from typing import Callable, Dict, Optional | |||
from typing import Callable, Dict, List, Optional | |||
import attr | |||
@@ -91,6 +91,12 @@ class RoomVersion: | |||
msc3787_knock_restricted_join_rule: bool | |||
# MSC3667: Enforce integer power levels | |||
msc3667_int_only_power_levels: bool | |||
# MSC3931: Adds a push rule condition for "room version feature flags", making | |||
# some push rules room version dependent. Note that adding a flag to this list | |||
# is not enough to mark it "supported": the push rule evaluator also needs to | |||
# support the flag. Unknown flags are ignored by the evaluator, making conditions | |||
# fail if used. | |||
msc3931_push_features: List[str] | |||
class RoomVersions: | |||
@@ -111,6 +117,7 @@ class RoomVersions: | |||
msc2716_redactions=False, | |||
msc3787_knock_restricted_join_rule=False, | |||
msc3667_int_only_power_levels=False, | |||
msc3931_push_features=[], | |||
) | |||
V2 = RoomVersion( | |||
"2", | |||
@@ -129,6 +136,7 @@ class RoomVersions: | |||
msc2716_redactions=False, | |||
msc3787_knock_restricted_join_rule=False, | |||
msc3667_int_only_power_levels=False, | |||
msc3931_push_features=[], | |||
) | |||
V3 = RoomVersion( | |||
"3", | |||
@@ -147,6 +155,7 @@ class RoomVersions: | |||
msc2716_redactions=False, | |||
msc3787_knock_restricted_join_rule=False, | |||
msc3667_int_only_power_levels=False, | |||
msc3931_push_features=[], | |||
) | |||
V4 = RoomVersion( | |||
"4", | |||
@@ -165,6 +174,7 @@ class RoomVersions: | |||
msc2716_redactions=False, | |||
msc3787_knock_restricted_join_rule=False, | |||
msc3667_int_only_power_levels=False, | |||
msc3931_push_features=[], | |||
) | |||
V5 = RoomVersion( | |||
"5", | |||
@@ -183,6 +193,7 @@ class RoomVersions: | |||
msc2716_redactions=False, | |||
msc3787_knock_restricted_join_rule=False, | |||
msc3667_int_only_power_levels=False, | |||
msc3931_push_features=[], | |||
) | |||
V6 = RoomVersion( | |||
"6", | |||
@@ -201,6 +212,7 @@ class RoomVersions: | |||
msc2716_redactions=False, | |||
msc3787_knock_restricted_join_rule=False, | |||
msc3667_int_only_power_levels=False, | |||
msc3931_push_features=[], | |||
) | |||
MSC2176 = RoomVersion( | |||
"org.matrix.msc2176", | |||
@@ -219,6 +231,7 @@ class RoomVersions: | |||
msc2716_redactions=False, | |||
msc3787_knock_restricted_join_rule=False, | |||
msc3667_int_only_power_levels=False, | |||
msc3931_push_features=[], | |||
) | |||
V7 = RoomVersion( | |||
"7", | |||
@@ -237,6 +250,7 @@ class RoomVersions: | |||
msc2716_redactions=False, | |||
msc3787_knock_restricted_join_rule=False, | |||
msc3667_int_only_power_levels=False, | |||
msc3931_push_features=[], | |||
) | |||
V8 = RoomVersion( | |||
"8", | |||
@@ -255,6 +269,7 @@ class RoomVersions: | |||
msc2716_redactions=False, | |||
msc3787_knock_restricted_join_rule=False, | |||
msc3667_int_only_power_levels=False, | |||
msc3931_push_features=[], | |||
) | |||
V9 = RoomVersion( | |||
"9", | |||
@@ -273,6 +288,7 @@ class RoomVersions: | |||
msc2716_redactions=False, | |||
msc3787_knock_restricted_join_rule=False, | |||
msc3667_int_only_power_levels=False, | |||
msc3931_push_features=[], | |||
) | |||
MSC3787 = RoomVersion( | |||
"org.matrix.msc3787", | |||
@@ -291,6 +307,7 @@ class RoomVersions: | |||
msc2716_redactions=False, | |||
msc3787_knock_restricted_join_rule=True, | |||
msc3667_int_only_power_levels=False, | |||
msc3931_push_features=[], | |||
) | |||
V10 = RoomVersion( | |||
"10", | |||
@@ -309,6 +326,7 @@ class RoomVersions: | |||
msc2716_redactions=False, | |||
msc3787_knock_restricted_join_rule=True, | |||
msc3667_int_only_power_levels=True, | |||
msc3931_push_features=[], | |||
) | |||
MSC2716v4 = RoomVersion( | |||
"org.matrix.msc2716v4", | |||
@@ -327,6 +345,7 @@ class RoomVersions: | |||
msc2716_redactions=True, | |||
msc3787_knock_restricted_join_rule=False, | |||
msc3667_int_only_power_levels=False, | |||
msc3931_push_features=[], | |||
) | |||
@@ -128,3 +128,6 @@ class ExperimentalConfig(Config): | |||
# MSC3912: Relation-based redactions. | |||
self.msc3912_enabled: bool = experimental.get("msc3912_enabled", False) | |||
# MSC1767 and friends: Extensible Events | |||
self.msc1767_enabled: bool = experimental.get("msc1767_enabled", False) |
@@ -338,6 +338,10 @@ class BulkPushRuleEvaluator: | |||
for user_id, level in notification_levels.items(): | |||
notification_levels[user_id] = int(level) | |||
room_version_features = event.room_version.msc3931_push_features | |||
if not room_version_features: | |||
room_version_features = [] | |||
evaluator = PushRuleEvaluator( | |||
_flatten_dict(event), | |||
room_member_count, | |||
@@ -345,6 +349,8 @@ class BulkPushRuleEvaluator: | |||
notification_levels, | |||
related_events, | |||
self._related_event_match_enabled, | |||
room_version_features, | |||
self.hs.config.experimental.msc1767_enabled, # MSC3931 flag | |||
) | |||
users = rules_by_user.keys() | |||
@@ -62,6 +62,8 @@ class PushRuleEvaluatorTestCase(unittest.TestCase): | |||
power_levels.get("notifications", {}), | |||
{} if related_events is None else related_events, | |||
True, | |||
event.room_version.msc3931_push_features, | |||
True, | |||
) | |||
def test_display_name(self) -> None: | |||