Merge pull request #975 from vector-im/feature/cleanup

Cleanup push rule code
This commit is contained in:
Benoit Marty 2020-02-10 16:32:24 +01:00 committed by GitHub
commit 588a644e02
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
19 changed files with 291 additions and 142 deletions

View File

@ -15,30 +15,32 @@
*/
package im.vector.matrix.android.api.pushrules
import im.vector.matrix.android.api.session.events.model.Event
abstract class Condition(val kind: Kind) {
enum class Kind(val value: String) {
event_match("event_match"),
contains_display_name("contains_display_name"),
room_member_count("room_member_count"),
sender_notification_permission("sender_notification_permission"),
UNRECOGNIZE("");
EventMatch("event_match"),
ContainsDisplayName("contains_display_name"),
RoomMemberCount("room_member_count"),
SenderNotificationPermission("sender_notification_permission"),
Unrecognised("");
companion object {
fun fromString(value: String): Kind {
return when (value) {
"event_match" -> event_match
"contains_display_name" -> contains_display_name
"room_member_count" -> room_member_count
"sender_notification_permission" -> sender_notification_permission
else -> UNRECOGNIZE
"event_match" -> EventMatch
"contains_display_name" -> ContainsDisplayName
"room_member_count" -> RoomMemberCount
"sender_notification_permission" -> SenderNotificationPermission
else -> Unrecognised
}
}
}
}
abstract fun isSatisfied(conditionResolver: ConditionResolver): Boolean
abstract fun isSatisfied(event: Event, conditionResolver: ConditionResolver): Boolean
open fun technicalDescription(): String {
return "Kind: $kind"

View File

@ -15,14 +15,22 @@
*/
package im.vector.matrix.android.api.pushrules
import im.vector.matrix.android.api.session.events.model.Event
/**
* Acts like a visitor on Conditions.
* This class as all required context needed to evaluate rules
*/
interface ConditionResolver {
fun resolveEventMatchCondition(event: Event,
condition: EventMatchCondition): Boolean
fun resolveEventMatchCondition(eventMatchCondition: EventMatchCondition): Boolean
fun resolveRoomMemberCountCondition(roomMemberCountCondition: RoomMemberCountCondition): Boolean
fun resolveSenderNotificationPermissionCondition(senderNotificationPermissionCondition: SenderNotificationPermissionCondition): Boolean
fun resolveContainsDisplayNameCondition(containsDisplayNameCondition: ContainsDisplayNameCondition) : Boolean
fun resolveRoomMemberCountCondition(event: Event,
condition: RoomMemberCountCondition): Boolean
fun resolveSenderNotificationPermissionCondition(event: Event,
condition: SenderNotificationPermissionCondition): Boolean
fun resolveContainsDisplayNameCondition(event: Event,
condition: ContainsDisplayNameCondition): Boolean
}

View File

@ -21,10 +21,10 @@ import im.vector.matrix.android.api.session.events.model.toModel
import im.vector.matrix.android.api.session.room.model.message.MessageContent
import timber.log.Timber
class ContainsDisplayNameCondition : Condition(Kind.contains_display_name) {
class ContainsDisplayNameCondition : Condition(Kind.ContainsDisplayName) {
override fun isSatisfied(conditionResolver: ConditionResolver): Boolean {
return conditionResolver.resolveContainsDisplayNameCondition(this)
override fun isSatisfied(event: Event, conditionResolver: ConditionResolver): Boolean {
return conditionResolver.resolveContainsDisplayNameCondition(event, this)
}
override fun technicalDescription(): String {

View File

@ -19,10 +19,20 @@ import im.vector.matrix.android.api.session.events.model.Event
import im.vector.matrix.android.internal.di.MoshiProvider
import timber.log.Timber
class EventMatchCondition(val key: String, val pattern: String) : Condition(Kind.event_match) {
class EventMatchCondition(
/**
* The dot-separated field of the event to match, e.g. content.body
*/
val key: String,
/**
* 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
) : Condition(Kind.EventMatch) {
override fun isSatisfied(conditionResolver: ConditionResolver) : Boolean {
return conditionResolver.resolveEventMatchCondition(this)
override fun isSatisfied(event: Event, conditionResolver: ConditionResolver): Boolean {
return conditionResolver.resolveEventMatchCondition(event, this)
}
override fun technicalDescription(): String {

View File

@ -16,25 +16,32 @@
package im.vector.matrix.android.api.pushrules
import im.vector.matrix.android.api.session.events.model.Event
import im.vector.matrix.android.api.session.room.RoomService
import im.vector.matrix.android.internal.session.room.RoomGetter
import timber.log.Timber
private val regex = Regex("^(==|<=|>=|<|>)?(\\d*)$")
class RoomMemberCountCondition(val iz: String) : Condition(Kind.room_member_count) {
class RoomMemberCountCondition(
/**
* A decimal integer optionally prefixed by one of ==, <, >, >= or <=.
* A prefix of < matches rooms where the member count is strictly less than the given number and so forth.
* If no prefix is present, this parameter defaults to ==.
*/
val iz: String
) : Condition(Kind.RoomMemberCount) {
override fun isSatisfied(conditionResolver: ConditionResolver): Boolean {
return conditionResolver.resolveRoomMemberCountCondition(this)
override fun isSatisfied(event: Event, conditionResolver: ConditionResolver): Boolean {
return conditionResolver.resolveRoomMemberCountCondition(event, this)
}
override fun technicalDescription(): String {
return "Room member count is $iz"
}
fun isSatisfied(event: Event, session: RoomService?): Boolean {
// sanity check^
internal fun isSatisfied(event: Event, roomGetter: RoomGetter): Boolean {
// sanity checks
val roomId = event.roomId ?: return false
val room = session?.getRoom(roomId) ?: return false
val room = roomGetter.getRoom(roomId) ?: return false
// Parse the is field into prefix and number the first time
val (prefix, count) = parseIsField() ?: return false

View File

@ -19,10 +19,18 @@ import im.vector.matrix.android.api.session.events.model.Event
import im.vector.matrix.android.api.session.room.model.PowerLevelsContent
import im.vector.matrix.android.api.session.room.powerlevels.PowerLevelsHelper
class SenderNotificationPermissionCondition(val key: String) : Condition(Kind.sender_notification_permission) {
class SenderNotificationPermissionCondition(
/**
* A string that determines the power level the sender must have to trigger notifications of a given type,
* such as room. Refer to the m.room.power_levels event schema for information about what the defaults are
* and how to interpret the event. The key is used to look up the power level required to send a notification
* type from the notifications object in the power level event content.
*/
val key: String
) : Condition(Kind.SenderNotificationPermission) {
override fun isSatisfied(conditionResolver: ConditionResolver): Boolean {
return conditionResolver.resolveSenderNotificationPermissionCondition(this)
override fun isSatisfied(event: Event, conditionResolver: ConditionResolver): Boolean {
return conditionResolver.resolveSenderNotificationPermissionCondition(event, this)
}
override fun technicalDescription(): String {

View File

@ -22,7 +22,7 @@ import com.squareup.moshi.JsonClass
* All push rulesets for a user.
*/
@JsonClass(generateAdapter = true)
data class GetPushRulesResponse(
internal data class GetPushRulesResponse(
/**
* Global rules, account level applying to all devices
*/

View File

@ -17,7 +17,11 @@ package im.vector.matrix.android.api.pushrules.rest
import com.squareup.moshi.Json
import com.squareup.moshi.JsonClass
import im.vector.matrix.android.api.pushrules.*
import im.vector.matrix.android.api.pushrules.Condition
import im.vector.matrix.android.api.pushrules.ContainsDisplayNameCondition
import im.vector.matrix.android.api.pushrules.EventMatchCondition
import im.vector.matrix.android.api.pushrules.RoomMemberCountCondition
import im.vector.matrix.android.api.pushrules.SenderNotificationPermissionCondition
import timber.log.Timber
@JsonClass(generateAdapter = true)
@ -30,13 +34,13 @@ data class PushCondition(
/**
* Required for event_match conditions. The dot- separated field of the event to match.
*/
val key: String? = null,
/**
*Required for event_match conditions.
*/
/**
* Required for event_match conditions.
*/
val pattern: String? = null,
/**
* Required for room_member_count conditions.
* A decimal integer optionally prefixed by one of, ==, <, >, >= or <=.
@ -47,30 +51,35 @@ data class PushCondition(
) {
fun asExecutableCondition(): Condition? {
return when (Condition.Kind.fromString(this.kind)) {
Condition.Kind.event_match -> {
if (this.key != null && this.pattern != null) {
return when (Condition.Kind.fromString(kind)) {
Condition.Kind.EventMatch -> {
if (key != null && pattern != null) {
EventMatchCondition(key, pattern)
} else {
Timber.e("Malformed Event match condition")
null
}
}
Condition.Kind.contains_display_name -> {
Condition.Kind.ContainsDisplayName -> {
ContainsDisplayNameCondition()
}
Condition.Kind.room_member_count -> {
if (this.iz.isNullOrBlank()) {
Condition.Kind.RoomMemberCount -> {
if (iz.isNullOrEmpty()) {
Timber.e("Malformed ROOM_MEMBER_COUNT condition")
null
} else {
RoomMemberCountCondition(this.iz)
RoomMemberCountCondition(iz)
}
}
Condition.Kind.sender_notification_permission -> {
this.key?.let { SenderNotificationPermissionCondition(it) }
Condition.Kind.SenderNotificationPermission -> {
if (key == null) {
Timber.e("Malformed Sender Notification Permission condition")
null
} else {
SenderNotificationPermissionCondition(key)
}
}
Condition.Kind.UNRECOGNIZE -> {
Condition.Kind.Unrecognised -> {
Timber.e("Unknown kind $kind")
null
}

View File

@ -18,7 +18,7 @@ package im.vector.matrix.android.api.pushrules.rest
import com.squareup.moshi.JsonClass
@JsonClass(generateAdapter = true)
data class Ruleset(
internal data class Ruleset(
val content: List<PushRule>? = null,
val override: List<PushRule>? = null,
val room: List<PushRule>? = null,

View File

@ -110,9 +110,11 @@ internal class ShieldTrustUpdater @Inject constructor(
val map = HashMap<String, List<String>>()
impactedRoomsId.forEach { roomId ->
RoomMemberSummaryEntity.where(backgroundSessionRealm.get(), roomId).findAll()?.let { results ->
map[roomId] = results.map { it.userId }
}
RoomMemberSummaryEntity.where(backgroundSessionRealm.get(), roomId)
.findAll()
.let { results ->
map[roomId] = results.map { it.userId }
}
}
map.forEach { entry ->

View File

@ -38,7 +38,7 @@ internal object PushRulesMapper {
enabled = pushrule.enabled,
ruleId = pushrule.ruleId,
conditions = listOf(
PushCondition(Condition.Kind.event_match.name, "content.body", pushrule.pattern)
PushCondition(Condition.Kind.EventMatch.name, "content.body", pushrule.pattern)
)
)
}
@ -59,7 +59,7 @@ internal object PushRulesMapper {
enabled = pushrule.enabled,
ruleId = pushrule.ruleId,
conditions = listOf(
PushCondition(Condition.Kind.event_match.name, "room_id", pushrule.ruleId)
PushCondition(Condition.Kind.EventMatch.name, "room_id", pushrule.ruleId)
)
)
}
@ -71,7 +71,7 @@ internal object PushRulesMapper {
enabled = pushrule.enabled,
ruleId = pushrule.ruleId,
conditions = listOf(
PushCondition(Condition.Kind.event_match.name, "user_id", pushrule.ruleId)
PushCondition(Condition.Kind.EventMatch.name, "user_id", pushrule.ruleId)
)
)
}

View File

@ -38,12 +38,13 @@ import timber.log.Timber
import javax.inject.Inject
@SessionScope
internal class DefaultPushRuleService @Inject constructor(private val getPushRulesTask: GetPushRulesTask,
private val updatePushRuleEnableStatusTask: UpdatePushRuleEnableStatusTask,
private val addPushRuleTask: AddPushRuleTask,
private val removePushRuleTask: RemovePushRuleTask,
private val taskExecutor: TaskExecutor,
private val monarchy: Monarchy
internal class DefaultPushRuleService @Inject constructor(
private val getPushRulesTask: GetPushRulesTask,
private val updatePushRuleEnableStatusTask: UpdatePushRuleEnableStatusTask,
private val addPushRuleTask: AddPushRuleTask,
private val removePushRuleTask: RemovePushRuleTask,
private val taskExecutor: TaskExecutor,
private val monarchy: Monarchy
) : PushRuleService {
private var listeners = mutableSetOf<PushRuleService.PushRuleListener>()

View File

@ -16,12 +16,11 @@
package im.vector.matrix.android.internal.session.notification
import im.vector.matrix.android.api.pushrules.ConditionResolver
import im.vector.matrix.android.api.pushrules.rest.PushRule
import im.vector.matrix.android.api.session.events.model.Event
import im.vector.matrix.android.api.session.events.model.EventType
import im.vector.matrix.android.api.session.room.RoomService
import im.vector.matrix.android.internal.di.UserId
import im.vector.matrix.android.internal.session.pushers.DefaultConditionResolver
import im.vector.matrix.android.internal.session.sync.model.RoomsSyncResponse
import im.vector.matrix.android.internal.task.Task
import timber.log.Timber
@ -36,7 +35,7 @@ internal interface ProcessEventForPushTask : Task<ProcessEventForPushTask.Params
internal class DefaultProcessEventForPushTask @Inject constructor(
private val defaultPushRuleService: DefaultPushRuleService,
private val roomService: RoomService,
private val conditionResolver: ConditionResolver,
@UserId private val userId: String
) : ProcessEventForPushTask {
@ -97,12 +96,10 @@ internal class DefaultProcessEventForPushTask @Inject constructor(
}
private fun fulfilledBingRule(event: Event, rules: List<PushRule>): PushRule? {
// TODO This should be injected
val conditionResolver = DefaultConditionResolver(event, roomService, userId)
return rules.firstOrNull { rule ->
// All conditions must hold true for an event in order to apply the action for the event.
rule.enabled && rule.conditions?.all {
it.asExecutableCondition()?.isSatisfied(conditionResolver) ?: false
it.asExecutableCondition()?.isSatisfied(event, conditionResolver) ?: false
} ?: false
}
}

View File

@ -15,37 +15,52 @@
*/
package im.vector.matrix.android.internal.session.pushers
import im.vector.matrix.android.api.pushrules.*
import im.vector.matrix.android.api.pushrules.ConditionResolver
import im.vector.matrix.android.api.pushrules.ContainsDisplayNameCondition
import im.vector.matrix.android.api.pushrules.EventMatchCondition
import im.vector.matrix.android.api.pushrules.RoomMemberCountCondition
import im.vector.matrix.android.api.pushrules.SenderNotificationPermissionCondition
import im.vector.matrix.android.api.session.events.model.Event
import im.vector.matrix.android.api.session.room.RoomService
import im.vector.matrix.android.api.session.events.model.EventType
import im.vector.matrix.android.api.session.events.model.toModel
import im.vector.matrix.android.api.session.room.model.PowerLevelsContent
import im.vector.matrix.android.internal.di.UserId
import timber.log.Timber
import im.vector.matrix.android.internal.session.room.RoomGetter
import javax.inject.Inject
// TODO Inject constructor
internal class DefaultConditionResolver(private val event: Event,
private val roomService: RoomService,
@UserId private val userId: String) : ConditionResolver {
internal class DefaultConditionResolver @Inject constructor(
private val roomGetter: RoomGetter,
@UserId private val userId: String
) : ConditionResolver {
override fun resolveEventMatchCondition(eventMatchCondition: EventMatchCondition): Boolean {
return eventMatchCondition.isSatisfied(event)
override fun resolveEventMatchCondition(event: Event,
condition: EventMatchCondition): Boolean {
return condition.isSatisfied(event)
}
override fun resolveRoomMemberCountCondition(roomMemberCountCondition: RoomMemberCountCondition): Boolean {
return roomMemberCountCondition.isSatisfied(event, roomService)
override fun resolveRoomMemberCountCondition(event: Event,
condition: RoomMemberCountCondition): Boolean {
return condition.isSatisfied(event, roomGetter)
}
override fun resolveSenderNotificationPermissionCondition(senderNotificationPermissionCondition: SenderNotificationPermissionCondition): Boolean {
// val roomId = event.roomId ?: return false
// val room = roomService.getRoom(roomId) ?: return false
// TODO RoomState not yet managed
Timber.e("POWER LEVELS STATE NOT YET MANAGED BY RIOTX")
return false // senderNotificationPermissionCondition.isSatisfied(event, )
}
override fun resolveContainsDisplayNameCondition(containsDisplayNameCondition: ContainsDisplayNameCondition): Boolean {
override fun resolveSenderNotificationPermissionCondition(event: Event,
condition: SenderNotificationPermissionCondition): Boolean {
val roomId = event.roomId ?: return false
val room = roomService.getRoom(roomId) ?: return false
val room = roomGetter.getRoom(roomId) ?: return false
val powerLevelsContent = room.getStateEvent(EventType.STATE_ROOM_POWER_LEVELS, "")
?.content
?.toModel<PowerLevelsContent>()
?: PowerLevelsContent()
return condition.isSatisfied(event, powerLevelsContent)
}
override fun resolveContainsDisplayNameCondition(event: Event,
condition: ContainsDisplayNameCondition): Boolean {
val roomId = event.roomId ?: return false
val room = roomGetter.getRoom(roomId) ?: return false
val myDisplayName = room.getRoomMember(userId)?.displayName ?: return false
return containsDisplayNameCondition.isSatisfied(event, myDisplayName)
return condition.isSatisfied(event, myDisplayName)
}
}

View File

@ -22,14 +22,12 @@ import im.vector.matrix.android.api.MatrixCallback
import im.vector.matrix.android.api.session.room.Room
import im.vector.matrix.android.api.session.room.RoomService
import im.vector.matrix.android.api.session.room.RoomSummaryQueryParams
import im.vector.matrix.android.api.session.room.model.Membership
import im.vector.matrix.android.api.session.room.model.RoomSummary
import im.vector.matrix.android.api.session.room.model.VersioningState
import im.vector.matrix.android.api.session.room.model.create.CreateRoomParams
import im.vector.matrix.android.api.util.Cancelable
import im.vector.matrix.android.api.util.Optional
import im.vector.matrix.android.internal.database.mapper.RoomSummaryMapper
import im.vector.matrix.android.internal.database.model.RoomEntity
import im.vector.matrix.android.internal.database.model.RoomSummaryEntity
import im.vector.matrix.android.internal.database.model.RoomSummaryEntityFields
import im.vector.matrix.android.internal.database.query.findByAlias
@ -37,7 +35,6 @@ import im.vector.matrix.android.internal.database.query.where
import im.vector.matrix.android.internal.query.process
import im.vector.matrix.android.internal.session.room.alias.GetRoomIdByAliasTask
import im.vector.matrix.android.internal.session.room.create.CreateRoomTask
import im.vector.matrix.android.internal.session.room.membership.RoomMemberHelper
import im.vector.matrix.android.internal.session.room.membership.joining.JoinRoomTask
import im.vector.matrix.android.internal.session.room.read.MarkAllRoomsReadTask
import im.vector.matrix.android.internal.session.user.accountdata.UpdateBreadcrumbsTask
@ -48,15 +45,17 @@ import io.realm.Realm
import io.realm.RealmQuery
import javax.inject.Inject
internal class DefaultRoomService @Inject constructor(private val monarchy: Monarchy,
private val roomSummaryMapper: RoomSummaryMapper,
private val createRoomTask: CreateRoomTask,
private val joinRoomTask: JoinRoomTask,
private val markAllRoomsReadTask: MarkAllRoomsReadTask,
private val updateBreadcrumbsTask: UpdateBreadcrumbsTask,
private val roomIdByAliasTask: GetRoomIdByAliasTask,
private val roomFactory: RoomFactory,
private val taskExecutor: TaskExecutor) : RoomService {
internal class DefaultRoomService @Inject constructor(
private val monarchy: Monarchy,
private val roomSummaryMapper: RoomSummaryMapper,
private val createRoomTask: CreateRoomTask,
private val joinRoomTask: JoinRoomTask,
private val markAllRoomsReadTask: MarkAllRoomsReadTask,
private val updateBreadcrumbsTask: UpdateBreadcrumbsTask,
private val roomIdByAliasTask: GetRoomIdByAliasTask,
private val roomGetter: RoomGetter,
private val taskExecutor: TaskExecutor
) : RoomService {
override fun createRoom(createRoomParams: CreateRoomParams, callback: MatrixCallback<String>): Cancelable {
return createRoomTask
@ -67,33 +66,11 @@ internal class DefaultRoomService @Inject constructor(private val monarchy: Mona
}
override fun getRoom(roomId: String): Room? {
return Realm.getInstance(monarchy.realmConfiguration).use {
if (RoomEntity.where(it, roomId).findFirst() != null) {
roomFactory.create(roomId)
} else {
null
}
}
return roomGetter.getRoom(roomId)
}
override fun getExistingDirectRoomWithUser(otherUserId: String): Room? {
Realm.getInstance(monarchy.realmConfiguration).use { realm ->
val candidates = RoomSummaryEntity.where(realm)
.equalTo(RoomSummaryEntityFields.IS_DIRECT, true)
.findAll()?.filter { dm ->
dm.otherMemberIds.contains(otherUserId)
&& dm.membership == Membership.JOIN
}?.map {
it.roomId
}
?: return null
candidates.forEach { roomId ->
if (RoomMemberHelper(realm, roomId).getActiveRoomMemberIds().any { it == otherUserId }) {
return RoomEntity.where(realm, roomId).findFirst()?.let { roomFactory.create(roomId) }
}
}
return null
}
return roomGetter.getDirectRoomWith(otherUserId)
}
override fun getRoomSummary(roomIdOrAlias: String): RoomSummary? {

View File

@ -0,0 +1,66 @@
/*
* Copyright (c) 2020 New Vector 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.
*/
package im.vector.matrix.android.internal.session.room
import com.zhuinden.monarchy.Monarchy
import im.vector.matrix.android.api.session.room.Room
import im.vector.matrix.android.api.session.room.model.Membership
import im.vector.matrix.android.internal.database.model.RoomEntity
import im.vector.matrix.android.internal.database.model.RoomSummaryEntity
import im.vector.matrix.android.internal.database.model.RoomSummaryEntityFields
import im.vector.matrix.android.internal.database.query.where
import im.vector.matrix.android.internal.session.SessionScope
import im.vector.matrix.android.internal.session.room.membership.RoomMemberHelper
import io.realm.Realm
import javax.inject.Inject
internal interface RoomGetter {
fun getRoom(roomId: String): Room?
fun getDirectRoomWith(otherUserId: String): Room?
}
@SessionScope
internal class DefaultRoomGetter @Inject constructor(
private val monarchy: Monarchy,
private val roomFactory: RoomFactory
) : RoomGetter {
override fun getRoom(roomId: String): Room? {
return Realm.getInstance(monarchy.realmConfiguration).use { realm ->
createRoom(realm, roomId)
}
}
override fun getDirectRoomWith(otherUserId: String): Room? {
return Realm.getInstance(monarchy.realmConfiguration).use { realm ->
RoomSummaryEntity.where(realm)
.equalTo(RoomSummaryEntityFields.IS_DIRECT, true)
.equalTo(RoomSummaryEntityFields.MEMBERSHIP_STR, Membership.JOIN.name)
.findAll()
.filter { dm -> dm.otherMemberIds.contains(otherUserId) }
.map { it.roomId }
.firstOrNull { roomId -> otherUserId in RoomMemberHelper(realm, roomId).getActiveRoomMemberIds() }
?.let { roomId -> createRoom(realm, roomId) }
}
}
private fun createRoom(realm: Realm, roomId: String): Room? {
return RoomEntity.where(realm, roomId).findFirst()
?.let { roomFactory.create(roomId) }
}
}

View File

@ -46,12 +46,20 @@ import im.vector.matrix.android.internal.session.room.read.DefaultMarkAllRoomsRe
import im.vector.matrix.android.internal.session.room.read.DefaultSetReadMarkersTask
import im.vector.matrix.android.internal.session.room.read.MarkAllRoomsReadTask
import im.vector.matrix.android.internal.session.room.read.SetReadMarkersTask
import im.vector.matrix.android.internal.session.room.relation.*
import im.vector.matrix.android.internal.session.room.relation.DefaultFetchEditHistoryTask
import im.vector.matrix.android.internal.session.room.relation.DefaultFindReactionEventForUndoTask
import im.vector.matrix.android.internal.session.room.relation.DefaultUpdateQuickReactionTask
import im.vector.matrix.android.internal.session.room.relation.FetchEditHistoryTask
import im.vector.matrix.android.internal.session.room.relation.FindReactionEventForUndoTask
import im.vector.matrix.android.internal.session.room.relation.UpdateQuickReactionTask
import im.vector.matrix.android.internal.session.room.reporting.DefaultReportContentTask
import im.vector.matrix.android.internal.session.room.reporting.ReportContentTask
import im.vector.matrix.android.internal.session.room.state.DefaultSendStateTask
import im.vector.matrix.android.internal.session.room.state.SendStateTask
import im.vector.matrix.android.internal.session.room.timeline.*
import im.vector.matrix.android.internal.session.room.timeline.DefaultGetContextOfEventTask
import im.vector.matrix.android.internal.session.room.timeline.DefaultPaginationTask
import im.vector.matrix.android.internal.session.room.timeline.GetContextOfEventTask
import im.vector.matrix.android.internal.session.room.timeline.PaginationTask
import im.vector.matrix.android.internal.session.room.typing.DefaultSendTypingTask
import im.vector.matrix.android.internal.session.room.typing.SendTypingTask
import retrofit2.Retrofit
@ -72,6 +80,9 @@ internal abstract class RoomModule {
@Binds
abstract fun bindRoomFactory(factory: DefaultRoomFactory): RoomFactory
@Binds
abstract fun bindRoomGetter(getter: DefaultRoomGetter): RoomGetter
@Binds
abstract fun bindRoomService(service: DefaultRoomService): RoomService

View File

@ -54,7 +54,7 @@ internal fun RoomNotificationState.toRoomPushRule(roomId: String): RoomPushRule?
}
else -> {
val condition = PushCondition(
kind = Condition.Kind.event_match.value,
kind = Condition.Kind.EventMatch.value,
key = "room_id",
pattern = roomId
)

View File

@ -19,18 +19,23 @@ package im.vector.matrix.android.api.pushrules
import im.vector.matrix.android.api.session.events.model.Event
import im.vector.matrix.android.api.session.events.model.toContent
import im.vector.matrix.android.api.session.room.Room
import im.vector.matrix.android.api.session.room.RoomService
import im.vector.matrix.android.api.session.room.model.Membership
import im.vector.matrix.android.api.session.room.model.RoomMemberContent
import im.vector.matrix.android.api.session.room.model.message.MessageTextContent
import im.vector.matrix.android.internal.session.room.RoomGetter
import io.mockk.every
import io.mockk.mockk
import org.amshove.kluent.shouldBe
import org.junit.Assert.assertFalse
import org.junit.Assert.assertTrue
import org.junit.Test
class PushrulesConditionTest {
/* ==========================================================================================
* Test EventMatchCondition
* ========================================================================================== */
@Test
fun test_eventmatch_type_condition() {
val condition = EventMatchCondition("type", "m.room.message")
@ -120,6 +125,24 @@ class PushrulesConditionTest {
assert(condition.isSatisfied(simpleTextEvent))
}
@Test
fun test_notice_condition() {
val conditionEqual = EventMatchCondition("content.msgtype", "m.notice")
Event(
type = "m.room.message",
eventId = "mx0",
content = MessageTextContent("m.notice", "A").toContent(),
originServerTs = 0,
roomId = "2joined").also {
assertTrue("Notice", conditionEqual.isSatisfied(it))
}
}
/* ==========================================================================================
* Test RoomMemberCountCondition
* ========================================================================================== */
@Test
fun test_roommember_condition() {
val conditionEqual3 = RoomMemberCountCondition("3")
@ -137,7 +160,7 @@ class PushrulesConditionTest {
every { getNumberOfJoinedMembers() } returns 3
}
val sessionStub = mockk<RoomService> {
val roomGetterStub = mockk<RoomGetter> {
every { getRoom(room2JoinedId) } returns roomStub2Joined
every { getRoom(room3JoinedId) } returns roomStub3Joined
}
@ -148,9 +171,9 @@ class PushrulesConditionTest {
content = MessageTextContent("m.text", "A").toContent(),
originServerTs = 0,
roomId = room2JoinedId).also {
assertFalse("This room does not have 3 members", conditionEqual3.isSatisfied(it, sessionStub))
assertFalse("This room does not have 3 members", conditionEqual3Bis.isSatisfied(it, sessionStub))
assertTrue("This room has less than 3 members", conditionLessThan3.isSatisfied(it, sessionStub))
assertFalse("This room does not have 3 members", conditionEqual3.isSatisfied(it, roomGetterStub))
assertFalse("This room does not have 3 members", conditionEqual3Bis.isSatisfied(it, roomGetterStub))
assertTrue("This room has less than 3 members", conditionLessThan3.isSatisfied(it, roomGetterStub))
}
Event(
@ -159,23 +182,36 @@ class PushrulesConditionTest {
content = MessageTextContent("m.text", "A").toContent(),
originServerTs = 0,
roomId = room3JoinedId).also {
assertTrue("This room has 3 members", conditionEqual3.isSatisfied(it, sessionStub))
assertTrue("This room has 3 members", conditionEqual3Bis.isSatisfied(it, sessionStub))
assertFalse("This room has more than 3 members", conditionLessThan3.isSatisfied(it, sessionStub))
assertTrue("This room has 3 members", conditionEqual3.isSatisfied(it, roomGetterStub))
assertTrue("This room has 3 members", conditionEqual3Bis.isSatisfied(it, roomGetterStub))
assertFalse("This room has more than 3 members", conditionLessThan3.isSatisfied(it, roomGetterStub))
}
}
/* ==========================================================================================
* Test ContainsDisplayNameCondition
* ========================================================================================== */
@Test
fun test_notice_condition() {
val conditionEqual = EventMatchCondition("content.msgtype", "m.notice")
fun test_displayName_condition() {
val condition = ContainsDisplayNameCondition()
Event(
val event = Event(
type = "m.room.message",
eventId = "mx0",
content = MessageTextContent("m.notice", "A").toContent(),
content = MessageTextContent("m.text", "How was the cake benoit?").toContent(),
originServerTs = 0,
roomId = "2joined").also {
assertTrue("Notice", conditionEqual.isSatisfied(it))
}
roomId = "2joined")
condition.isSatisfied(event, "how") shouldBe true
condition.isSatisfied(event, "How") shouldBe true
condition.isSatisfied(event, "benoit") shouldBe true
condition.isSatisfied(event, "Benoit") shouldBe true
condition.isSatisfied(event, "cake") shouldBe true
condition.isSatisfied(event, "ben") shouldBe false
condition.isSatisfied(event, "oit") shouldBe false
condition.isSatisfied(event, "enoi") shouldBe false
condition.isSatisfied(event, "H") shouldBe false
}
}