-
Notifications
You must be signed in to change notification settings - Fork 731
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Implement the current spec for event match conditions #6457
Changes from 8 commits
9df8009
48fc634
b24b1a1
e980f6b
365ec8e
144d6c9
f4f9851
bc20ad5
4a38352
e108666
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
Fix that replies to @roomba would be highlighted as a room ping. Contributed by Nico. |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -17,8 +17,6 @@ package org.matrix.android.sdk.api.session.pushrules | |
|
||
import org.matrix.android.sdk.api.session.events.model.Event | ||
import org.matrix.android.sdk.internal.di.MoshiProvider | ||
import org.matrix.android.sdk.internal.util.caseInsensitiveFind | ||
import org.matrix.android.sdk.internal.util.hasSpecialGlobChar | ||
import org.matrix.android.sdk.internal.util.simpleGlobToRegExp | ||
import timber.log.Timber | ||
|
||
|
@@ -31,40 +29,36 @@ class EventMatchCondition( | |
* The glob-style pattern to match against. Patterns with no special glob characters should | ||
* be treated as having asterisks prepended and appended when testing the condition. | ||
*/ | ||
val pattern: String, | ||
/** | ||
* true to match only words. In this case pattern will not be considered as a glob | ||
*/ | ||
val wordsOnly: Boolean | ||
val pattern: String | ||
) : Condition { | ||
|
||
override fun isSatisfied(event: Event, conditionResolver: ConditionResolver): Boolean { | ||
return conditionResolver.resolveEventMatchCondition(event, this) | ||
} | ||
|
||
override fun technicalDescription() = "'$key' matches '$pattern', words only '$wordsOnly'" | ||
override fun technicalDescription() = "'$key' matches '$pattern'" | ||
|
||
fun isSatisfied(event: Event): Boolean { | ||
// TODO encrypted events? | ||
val rawJson = MoshiProvider.providesMoshi().adapter(Event::class.java).toJsonValue(event) as? Map<*, *> | ||
?: return false | ||
val value = extractField(rawJson, key) ?: return false | ||
|
||
// Patterns with no special glob characters should be treated as having asterisks prepended | ||
// and appended when testing the condition. | ||
// The match is performed case-insensitively, and must match the entire value of | ||
// the event field given by `key` (though see below regarding `content.body`). The | ||
// exact meaning of "case insensitive" is defined by the implementation of the | ||
// homeserver. | ||
// | ||
// As a special case, if `key` is `content.body`, then `pattern` must instead | ||
// match any substring of the value of the property which starts and ends at a | ||
// word boundary. | ||
return try { | ||
if (wordsOnly) { | ||
value.caseInsensitiveFind(pattern) | ||
} else { | ||
val modPattern = if (pattern.hasSpecialGlobChar()) { | ||
// Regex.containsMatchIn() is way faster without leading and trailing | ||
// stars, that don't make any difference for the evaluation result | ||
pattern.removePrefix("*").removeSuffix("*").simpleGlobToRegExp() | ||
} else { | ||
pattern.simpleGlobToRegExp() | ||
} | ||
val regex = Regex(modPattern, RegexOption.DOT_MATCHES_ALL) | ||
if (key == "content.body") { | ||
val regex = Regex("(\\W|^)" + pattern.simpleGlobToRegExp() + "(\\W|$)", setOf(RegexOption.DOT_MATCHES_ALL, RegexOption.IGNORE_CASE)) | ||
regex.containsMatchIn(value) | ||
} else { | ||
val regex = Regex(pattern.simpleGlobToRegExp(), setOf(RegexOption.DOT_MATCHES_ALL, RegexOption.IGNORE_CASE)) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Shouldn't you keep the existing optimisation to remove * prefix/suffix? as per #5008 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. So in theory we could, but in this branch we are not matching the content.body field, but other fields of the event, which usually don't contain a long text. If someone explicitly writes a rule to match The important part here is in the following line, which does
The last 3 branches could probably be collapsed just into one, but considering that fields apart from Now on the other hand in the half that matches on There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Added the optimization back in the body branch, not in the other branch since I don't really see a need for it, but if you think I should, I can do that as well. |
||
regex.matches(value) | ||
} | ||
} catch (e: Throwable) { | ||
// e.g PatternSyntaxException | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How different from caseInsensitiveFind is this? can it reuse it too?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
caseInsesitiveFind doesn't evaluate globs (since it escapes the string, from what I can tell), otherwise it is the same.