Create local room state events in dedicated task
This commit is contained in:
parent
7216f6bd64
commit
dee8484618
@ -43,9 +43,11 @@ import org.matrix.android.sdk.internal.session.room.alias.DefaultGetRoomLocalAli
|
||||
import org.matrix.android.sdk.internal.session.room.alias.DeleteRoomAliasTask
|
||||
import org.matrix.android.sdk.internal.session.room.alias.GetRoomIdByAliasTask
|
||||
import org.matrix.android.sdk.internal.session.room.alias.GetRoomLocalAliasesTask
|
||||
import org.matrix.android.sdk.internal.session.room.create.CreateLocalRoomStateEventsTask
|
||||
import org.matrix.android.sdk.internal.session.room.create.CreateLocalRoomTask
|
||||
import org.matrix.android.sdk.internal.session.room.create.CreateRoomFromLocalRoomTask
|
||||
import org.matrix.android.sdk.internal.session.room.create.CreateRoomTask
|
||||
import org.matrix.android.sdk.internal.session.room.create.DefaultCreateLocalRoomStateEventsTask
|
||||
import org.matrix.android.sdk.internal.session.room.create.DefaultCreateLocalRoomTask
|
||||
import org.matrix.android.sdk.internal.session.room.create.DefaultCreateRoomFromLocalRoomTask
|
||||
import org.matrix.android.sdk.internal.session.room.create.DefaultCreateRoomTask
|
||||
@ -215,6 +217,9 @@ internal abstract class RoomModule {
|
||||
@Binds
|
||||
abstract fun bindCreateLocalRoomTask(task: DefaultCreateLocalRoomTask): CreateLocalRoomTask
|
||||
|
||||
@Binds
|
||||
abstract fun bindCreateLocalRoomStateEventsTask(task: DefaultCreateLocalRoomStateEventsTask): CreateLocalRoomStateEventsTask
|
||||
|
||||
@Binds
|
||||
abstract fun bindCreateRoomFromLocalRoomTask(task: DefaultCreateRoomFromLocalRoomTask): CreateRoomFromLocalRoomTask
|
||||
|
||||
|
@ -0,0 +1,296 @@
|
||||
/*
|
||||
* Copyright 2022 The Matrix.org Foundation C.I.C.
|
||||
*
|
||||
* 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 org.matrix.android.sdk.internal.session.room.create
|
||||
|
||||
import org.matrix.android.sdk.api.MatrixPatterns.getServerName
|
||||
import org.matrix.android.sdk.api.extensions.orFalse
|
||||
import org.matrix.android.sdk.api.extensions.tryOrNull
|
||||
import org.matrix.android.sdk.api.session.events.model.Content
|
||||
import org.matrix.android.sdk.api.session.events.model.Event
|
||||
import org.matrix.android.sdk.api.session.events.model.EventType
|
||||
import org.matrix.android.sdk.api.session.events.model.LocalEcho
|
||||
import org.matrix.android.sdk.api.session.events.model.toContent
|
||||
import org.matrix.android.sdk.api.session.room.model.GuestAccess
|
||||
import org.matrix.android.sdk.api.session.room.model.Membership
|
||||
import org.matrix.android.sdk.api.session.room.model.PowerLevelsContent
|
||||
import org.matrix.android.sdk.api.session.room.model.RoomCanonicalAliasContent
|
||||
import org.matrix.android.sdk.api.session.room.model.RoomGuestAccessContent
|
||||
import org.matrix.android.sdk.api.session.room.model.RoomHistoryVisibility
|
||||
import org.matrix.android.sdk.api.session.room.model.RoomHistoryVisibilityContent
|
||||
import org.matrix.android.sdk.api.session.room.model.RoomJoinRules
|
||||
import org.matrix.android.sdk.api.session.room.model.RoomJoinRulesContent
|
||||
import org.matrix.android.sdk.api.session.room.model.RoomMemberContent
|
||||
import org.matrix.android.sdk.api.session.room.model.RoomNameContent
|
||||
import org.matrix.android.sdk.api.session.room.model.RoomThirdPartyInviteContent
|
||||
import org.matrix.android.sdk.api.session.room.model.RoomTopicContent
|
||||
import org.matrix.android.sdk.api.session.room.model.banOrDefault
|
||||
import org.matrix.android.sdk.api.session.room.model.create.CreateRoomParams
|
||||
import org.matrix.android.sdk.api.session.room.model.create.CreateRoomPreset
|
||||
import org.matrix.android.sdk.api.session.room.model.create.RoomCreateContent
|
||||
import org.matrix.android.sdk.api.session.room.model.eventsDefaultOrDefault
|
||||
import org.matrix.android.sdk.api.session.room.model.inviteOrDefault
|
||||
import org.matrix.android.sdk.api.session.room.model.kickOrDefault
|
||||
import org.matrix.android.sdk.api.session.room.model.localecho.LocalRoomThirdPartyInviteContent
|
||||
import org.matrix.android.sdk.api.session.room.model.redactOrDefault
|
||||
import org.matrix.android.sdk.api.session.room.model.stateDefaultOrDefault
|
||||
import org.matrix.android.sdk.api.session.room.model.usersDefaultOrDefault
|
||||
import org.matrix.android.sdk.api.session.user.UserService
|
||||
import org.matrix.android.sdk.internal.session.room.create.CreateLocalRoomStateEventsTask.Params
|
||||
import org.matrix.android.sdk.internal.session.room.membership.threepid.toThreePid
|
||||
import org.matrix.android.sdk.internal.task.Task
|
||||
import org.matrix.android.sdk.internal.util.time.Clock
|
||||
import javax.inject.Inject
|
||||
|
||||
internal interface CreateLocalRoomStateEventsTask : Task<Params, List<Event>> {
|
||||
data class Params(
|
||||
val roomCreatorUserId: String,
|
||||
val createRoomBody: CreateRoomBody
|
||||
)
|
||||
}
|
||||
|
||||
internal class DefaultCreateLocalRoomStateEventsTask @Inject constructor(
|
||||
private val userService: UserService,
|
||||
private val clock: Clock,
|
||||
) : CreateLocalRoomStateEventsTask {
|
||||
|
||||
private lateinit var createRoomBody: CreateRoomBody
|
||||
private lateinit var roomCreatorUserId: String
|
||||
|
||||
override suspend fun execute(params: Params): List<Event> {
|
||||
createRoomBody = params.createRoomBody
|
||||
roomCreatorUserId = params.roomCreatorUserId
|
||||
|
||||
return buildList {
|
||||
createRoomCreateEvent()
|
||||
createRoomMemberEvents(listOf(roomCreatorUserId))
|
||||
createRoomPowerLevelsEvent()
|
||||
createRoomAliasEvent()
|
||||
createRoomPresetEvents()
|
||||
createRoomInitialStateEvents()
|
||||
createRoomNameAndTopicStateEvents()
|
||||
createRoomMemberEvents(createRoomBody.invitedUserIds.orEmpty())
|
||||
createRoomThreePidEvents()
|
||||
createRoomDefaultEvents()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate the create state event related to this room.
|
||||
*/
|
||||
private fun MutableList<Event>.createRoomCreateEvent() = apply {
|
||||
val roomCreateEvent = createLocalEvent(
|
||||
type = EventType.STATE_ROOM_CREATE,
|
||||
content = RoomCreateContent(
|
||||
creator = roomCreatorUserId,
|
||||
roomVersion = createRoomBody.roomVersion,
|
||||
type = (createRoomBody.creationContent as? Map<*, *>)?.get(CreateRoomParams.CREATION_CONTENT_KEY_ROOM_TYPE) as? String
|
||||
|
||||
).toContent(),
|
||||
stateKey = ""
|
||||
)
|
||||
add(roomCreateEvent)
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate the create state event related to the power levels using the given overridden values or the default values according to the specification.
|
||||
* Ref: https://spec.matrix.org/latest/client-server-api/#mroompower_levels
|
||||
*/
|
||||
private fun MutableList<Event>.createRoomPowerLevelsEvent() = apply {
|
||||
val powerLevelsContent = createLocalEvent(
|
||||
type = EventType.STATE_ROOM_POWER_LEVELS,
|
||||
content = (createRoomBody.powerLevelContentOverride ?: PowerLevelsContent()).let {
|
||||
it.copy(
|
||||
ban = it.banOrDefault(),
|
||||
eventsDefault = it.eventsDefaultOrDefault(),
|
||||
invite = it.inviteOrDefault(),
|
||||
kick = it.kickOrDefault(),
|
||||
redact = it.redactOrDefault(),
|
||||
stateDefault = it.stateDefaultOrDefault(),
|
||||
usersDefault = it.usersDefaultOrDefault(),
|
||||
)
|
||||
}.toContent(),
|
||||
stateKey = ""
|
||||
)
|
||||
add(powerLevelsContent)
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate the local room member state events related to the given user ids, if any.
|
||||
*/
|
||||
private suspend fun MutableList<Event>.createRoomMemberEvents(userIds: List<String>) = apply {
|
||||
val memberEvents = userIds
|
||||
.mapNotNull { tryOrNull { userService.resolveUser(it) } }
|
||||
.map { user ->
|
||||
createLocalEvent(
|
||||
type = EventType.STATE_ROOM_MEMBER,
|
||||
content = RoomMemberContent(
|
||||
isDirect = createRoomBody.isDirect.takeUnless { user.userId == roomCreatorUserId }.orFalse(),
|
||||
membership = if (user.userId == roomCreatorUserId) Membership.JOIN else Membership.INVITE,
|
||||
displayName = user.displayName,
|
||||
avatarUrl = user.avatarUrl
|
||||
).toContent(),
|
||||
stateKey = user.userId
|
||||
)
|
||||
}
|
||||
addAll(memberEvents)
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate the local state events related to the given third party invites, if any.
|
||||
*/
|
||||
private fun MutableList<Event>.createRoomThreePidEvents() = apply {
|
||||
val threePidEvents = createRoomBody.invite3pids.orEmpty().map { body ->
|
||||
val localThirdPartyInviteEvent = createLocalEvent(
|
||||
type = EventType.LOCAL_STATE_ROOM_THIRD_PARTY_INVITE,
|
||||
content = LocalRoomThirdPartyInviteContent(
|
||||
isDirect = createRoomBody.isDirect.orFalse(),
|
||||
membership = Membership.INVITE,
|
||||
displayName = body.address,
|
||||
thirdPartyInvite = body.toThreePid()
|
||||
).toContent(),
|
||||
stateKey = ""
|
||||
)
|
||||
val thirdPartyInviteEvent = createLocalEvent(
|
||||
type = EventType.STATE_ROOM_THIRD_PARTY_INVITE,
|
||||
content = RoomThirdPartyInviteContent(body.address, null, null, null).toContent(),
|
||||
stateKey = ""
|
||||
)
|
||||
listOf(localThirdPartyInviteEvent, thirdPartyInviteEvent)
|
||||
}.flatten()
|
||||
addAll(threePidEvents)
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate the local state event related to the given alias, if any.
|
||||
*/
|
||||
fun MutableList<Event>.createRoomAliasEvent() = apply {
|
||||
if (createRoomBody.roomAliasName != null) {
|
||||
val canonicalAliasContent = createLocalEvent(
|
||||
type = EventType.STATE_ROOM_CANONICAL_ALIAS,
|
||||
content = RoomCanonicalAliasContent(
|
||||
canonicalAlias = "${createRoomBody.roomAliasName}:${roomCreatorUserId.getServerName()}"
|
||||
).toContent(),
|
||||
stateKey = ""
|
||||
)
|
||||
add(canonicalAliasContent)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate the local state events related to the given [CreateRoomPreset].
|
||||
* Ref: https://spec.matrix.org/latest/client-server-api/#post_matrixclientv3createroom
|
||||
*/
|
||||
private fun MutableList<Event>.createRoomPresetEvents() = apply {
|
||||
val preset = createRoomBody.preset ?: return@apply
|
||||
|
||||
var joinRules: RoomJoinRules? = null
|
||||
var historyVisibility: RoomHistoryVisibility? = null
|
||||
var guestAccess: GuestAccess? = null
|
||||
when (preset) {
|
||||
CreateRoomPreset.PRESET_PRIVATE_CHAT,
|
||||
CreateRoomPreset.PRESET_TRUSTED_PRIVATE_CHAT -> {
|
||||
joinRules = RoomJoinRules.INVITE
|
||||
historyVisibility = RoomHistoryVisibility.SHARED
|
||||
guestAccess = GuestAccess.CanJoin
|
||||
}
|
||||
CreateRoomPreset.PRESET_PUBLIC_CHAT -> {
|
||||
joinRules = RoomJoinRules.PUBLIC
|
||||
historyVisibility = RoomHistoryVisibility.SHARED
|
||||
guestAccess = GuestAccess.Forbidden
|
||||
}
|
||||
}
|
||||
|
||||
add(createLocalEvent(EventType.STATE_ROOM_JOIN_RULES, RoomJoinRulesContent(joinRules.value).toContent(), ""))
|
||||
add(createLocalEvent(EventType.STATE_ROOM_HISTORY_VISIBILITY, RoomHistoryVisibilityContent(historyVisibility.value).toContent(), ""))
|
||||
add(createLocalEvent(EventType.STATE_ROOM_GUEST_ACCESS, RoomGuestAccessContent(guestAccess.value).toContent(), ""))
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate the local state events related to the given initial states, if any.
|
||||
* The given initial state events override the potential existing ones of the same type.
|
||||
*/
|
||||
private fun MutableList<Event>.createRoomInitialStateEvents() = apply {
|
||||
val initialStates = createRoomBody.initialStates ?: return@apply
|
||||
|
||||
val initialStateEvents = initialStates.map { createLocalEvent(it.type, it.content, it.stateKey) }
|
||||
// Erase existing events of the same type
|
||||
removeAll { event -> event.type in initialStateEvents.map { it.type } }
|
||||
// Add the initial state events to the list
|
||||
addAll(initialStateEvents)
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate the local events related to the given room name and topic, if any.
|
||||
*/
|
||||
private fun MutableList<Event>.createRoomNameAndTopicStateEvents() = apply {
|
||||
if (createRoomBody.name != null) {
|
||||
add(createLocalEvent(EventType.STATE_ROOM_NAME, RoomNameContent(createRoomBody.name).toContent(), ""))
|
||||
}
|
||||
if (createRoomBody.topic != null) {
|
||||
add(createLocalEvent(EventType.STATE_ROOM_TOPIC, RoomTopicContent(createRoomBody.topic).toContent(), ""))
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate the local events which have not been set and are in that case provided by the server with default values.
|
||||
* Default events:
|
||||
* - m.room.history_visibility (https://spec.matrix.org/latest/client-server-api/#server-behaviour-5)
|
||||
* - m.room.guest_access (https://spec.matrix.org/latest/client-server-api/#mroomguest_access)
|
||||
*/
|
||||
private fun MutableList<Event>.createRoomDefaultEvents() = apply {
|
||||
// HistoryVisibility
|
||||
if (none { it.type == EventType.STATE_ROOM_HISTORY_VISIBILITY }) {
|
||||
add(
|
||||
createLocalEvent(
|
||||
type = EventType.STATE_ROOM_HISTORY_VISIBILITY,
|
||||
content = RoomHistoryVisibilityContent(RoomHistoryVisibility.SHARED.value).toContent(),
|
||||
stateKey = ""
|
||||
)
|
||||
)
|
||||
}
|
||||
// GuestAccess
|
||||
if (none { it.type == EventType.STATE_ROOM_GUEST_ACCESS }) {
|
||||
add(
|
||||
createLocalEvent(
|
||||
type = EventType.STATE_ROOM_GUEST_ACCESS,
|
||||
content = RoomGuestAccessContent(GuestAccess.Forbidden.value).toContent(),
|
||||
stateKey = ""
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate a local event from the given parameters.
|
||||
*
|
||||
* @param type the event type, see [EventType]
|
||||
* @param content the content of the Event
|
||||
* @param stateKey the stateKey, if any
|
||||
*
|
||||
* @return a local event
|
||||
*/
|
||||
private fun createLocalEvent(type: String?, content: Content?, stateKey: String?): Event {
|
||||
return Event(
|
||||
type = type,
|
||||
senderId = roomCreatorUserId,
|
||||
stateKey = stateKey,
|
||||
content = content,
|
||||
originServerTs = clock.epochMillis(),
|
||||
eventId = LocalEcho.createLocalEchoId()
|
||||
)
|
||||
}
|
||||
}
|
@ -21,43 +21,14 @@ import io.realm.Realm
|
||||
import io.realm.RealmConfiguration
|
||||
import io.realm.kotlin.createObject
|
||||
import kotlinx.coroutines.TimeoutCancellationException
|
||||
import org.matrix.android.sdk.api.MatrixPatterns.getServerName
|
||||
import org.matrix.android.sdk.api.extensions.orFalse
|
||||
import org.matrix.android.sdk.api.extensions.tryOrNull
|
||||
import org.matrix.android.sdk.api.session.events.model.Content
|
||||
import org.matrix.android.sdk.api.session.events.model.Event
|
||||
import org.matrix.android.sdk.api.session.events.model.EventType
|
||||
import org.matrix.android.sdk.api.session.events.model.LocalEcho
|
||||
import org.matrix.android.sdk.api.session.events.model.toContent
|
||||
import org.matrix.android.sdk.api.session.room.failure.CreateRoomFailure
|
||||
import org.matrix.android.sdk.api.session.room.model.GuestAccess
|
||||
import org.matrix.android.sdk.api.session.room.model.Membership
|
||||
import org.matrix.android.sdk.api.session.room.model.PowerLevelsContent
|
||||
import org.matrix.android.sdk.api.session.room.model.RoomCanonicalAliasContent
|
||||
import org.matrix.android.sdk.api.session.room.model.RoomGuestAccessContent
|
||||
import org.matrix.android.sdk.api.session.room.model.RoomHistoryVisibility
|
||||
import org.matrix.android.sdk.api.session.room.model.RoomHistoryVisibilityContent
|
||||
import org.matrix.android.sdk.api.session.room.model.RoomJoinRules
|
||||
import org.matrix.android.sdk.api.session.room.model.RoomJoinRulesContent
|
||||
import org.matrix.android.sdk.api.session.room.model.RoomMemberContent
|
||||
import org.matrix.android.sdk.api.session.room.model.RoomNameContent
|
||||
import org.matrix.android.sdk.api.session.room.model.RoomThirdPartyInviteContent
|
||||
import org.matrix.android.sdk.api.session.room.model.RoomTopicContent
|
||||
import org.matrix.android.sdk.api.session.room.model.banOrDefault
|
||||
import org.matrix.android.sdk.api.session.room.model.create.CreateRoomParams
|
||||
import org.matrix.android.sdk.api.session.room.model.create.CreateRoomPreset
|
||||
import org.matrix.android.sdk.api.session.room.model.create.RoomCreateContent
|
||||
import org.matrix.android.sdk.api.session.room.model.eventsDefaultOrDefault
|
||||
import org.matrix.android.sdk.api.session.room.model.inviteOrDefault
|
||||
import org.matrix.android.sdk.api.session.room.model.kickOrDefault
|
||||
import org.matrix.android.sdk.api.session.room.model.localecho.LocalRoomThirdPartyInviteContent
|
||||
import org.matrix.android.sdk.api.session.room.model.localecho.RoomLocalEcho
|
||||
import org.matrix.android.sdk.api.session.room.model.redactOrDefault
|
||||
import org.matrix.android.sdk.api.session.room.model.stateDefaultOrDefault
|
||||
import org.matrix.android.sdk.api.session.room.model.usersDefaultOrDefault
|
||||
import org.matrix.android.sdk.api.session.room.send.SendState
|
||||
import org.matrix.android.sdk.api.session.sync.model.RoomSyncSummary
|
||||
import org.matrix.android.sdk.api.session.user.UserService
|
||||
import org.matrix.android.sdk.internal.crypto.DefaultCryptoService
|
||||
import org.matrix.android.sdk.internal.database.awaitNotEmptyResult
|
||||
import org.matrix.android.sdk.internal.database.helper.addTimelineEvent
|
||||
@ -78,7 +49,6 @@ import org.matrix.android.sdk.internal.di.SessionDatabase
|
||||
import org.matrix.android.sdk.internal.di.UserId
|
||||
import org.matrix.android.sdk.internal.session.events.getFixedRoomMemberContent
|
||||
import org.matrix.android.sdk.internal.session.room.membership.RoomMemberEventHandler
|
||||
import org.matrix.android.sdk.internal.session.room.membership.threepid.toThreePid
|
||||
import org.matrix.android.sdk.internal.session.room.summary.RoomSummaryUpdater
|
||||
import org.matrix.android.sdk.internal.session.room.timeline.PaginationDirection
|
||||
import org.matrix.android.sdk.internal.task.Task
|
||||
@ -96,9 +66,9 @@ internal class DefaultCreateLocalRoomTask @Inject constructor(
|
||||
private val roomSummaryUpdater: RoomSummaryUpdater,
|
||||
@SessionDatabase private val realmConfiguration: RealmConfiguration,
|
||||
private val createRoomBodyBuilder: CreateRoomBodyBuilder,
|
||||
private val userService: UserService,
|
||||
private val cryptoService: DefaultCryptoService,
|
||||
private val clock: Clock,
|
||||
private val createLocalRoomStateEventsTask: CreateLocalRoomStateEventsTask,
|
||||
) : CreateLocalRoomTask {
|
||||
|
||||
override suspend fun execute(params: CreateRoomParams): String {
|
||||
@ -186,7 +156,7 @@ internal class DefaultCreateLocalRoomTask @Inject constructor(
|
||||
isLastForward = true
|
||||
}
|
||||
|
||||
val eventList = createLocalRoomEvents(createRoomBody)
|
||||
val eventList = createLocalRoomStateEventsTask.execute(CreateLocalRoomStateEventsTask.Params(myUserId, createRoomBody))
|
||||
val roomMemberContentsByUser = HashMap<String, RoomMemberContent?>()
|
||||
|
||||
for (event in eventList) {
|
||||
@ -226,232 +196,4 @@ internal class DefaultCreateLocalRoomTask @Inject constructor(
|
||||
|
||||
return chunkEntity
|
||||
}
|
||||
|
||||
/**
|
||||
* Build the list of state events related to the room creation body.
|
||||
* The events list is ordered following the specification: https://spec.matrix.org/latest/client-server-api/#post_matrixclientv3createroom
|
||||
*
|
||||
* @param createRoomBody the room creation body
|
||||
*
|
||||
* @return the list of events
|
||||
*/
|
||||
private suspend fun createLocalRoomEvents(createRoomBody: CreateRoomBody): List<Event> {
|
||||
return buildList {
|
||||
createRoomCreateEvent(createRoomBody)
|
||||
createRoomMemberEvents(listOf(myUserId))
|
||||
createRoomPowerLevelsEvent(createRoomBody)
|
||||
createRoomAliasEvent(createRoomBody)
|
||||
createRoomPresetEvents(createRoomBody)
|
||||
createRoomInitialStateEvents(createRoomBody)
|
||||
createRoomNameAndTopicStateEvents(createRoomBody)
|
||||
createRoomMemberEvents(createRoomBody.invitedUserIds.orEmpty())
|
||||
createRoomThreePidEvents(createRoomBody)
|
||||
createRoomDefaultEvents()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate the create state event related to this room.
|
||||
*/
|
||||
private fun MutableList<Event>.createRoomCreateEvent(createRoomBody: CreateRoomBody) = apply {
|
||||
val roomCreateEvent = createLocalEvent(
|
||||
type = EventType.STATE_ROOM_CREATE,
|
||||
content = RoomCreateContent(
|
||||
creator = myUserId,
|
||||
roomVersion = createRoomBody.roomVersion,
|
||||
type = (createRoomBody.creationContent as? Map<*, *>)?.get(CreateRoomParams.CREATION_CONTENT_KEY_ROOM_TYPE) as? String
|
||||
|
||||
).toContent(),
|
||||
stateKey = ""
|
||||
)
|
||||
add(roomCreateEvent)
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate the create state event related to the power levels using the given overridden values or the default values according to the specification.
|
||||
* Ref: https://spec.matrix.org/latest/client-server-api/#mroompower_levels
|
||||
*/
|
||||
private fun MutableList<Event>.createRoomPowerLevelsEvent(createRoomBody: CreateRoomBody) = apply {
|
||||
val powerLevelsContent = createLocalEvent(
|
||||
type = EventType.STATE_ROOM_POWER_LEVELS,
|
||||
content = (createRoomBody.powerLevelContentOverride ?: PowerLevelsContent()).let {
|
||||
it.copy(
|
||||
ban = it.banOrDefault(),
|
||||
eventsDefault = it.eventsDefaultOrDefault(),
|
||||
invite = it.inviteOrDefault(),
|
||||
kick = it.kickOrDefault(),
|
||||
redact = it.redactOrDefault(),
|
||||
stateDefault = it.stateDefaultOrDefault(),
|
||||
usersDefault = it.usersDefaultOrDefault(),
|
||||
)
|
||||
}.toContent(),
|
||||
stateKey = ""
|
||||
)
|
||||
add(powerLevelsContent)
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate the local room member state events related to the given user ids, if any.
|
||||
*/
|
||||
private suspend fun MutableList<Event>.createRoomMemberEvents(userIds: List<String>, isDirect: Boolean? = null) = apply {
|
||||
val memberEvents = userIds
|
||||
.mapNotNull { tryOrNull { userService.resolveUser(it) } }
|
||||
.map { user ->
|
||||
createLocalEvent(
|
||||
type = EventType.STATE_ROOM_MEMBER,
|
||||
content = RoomMemberContent(
|
||||
isDirect = isDirect.orFalse(),
|
||||
membership = if (user.userId == myUserId) Membership.JOIN else Membership.INVITE,
|
||||
displayName = user.displayName,
|
||||
avatarUrl = user.avatarUrl
|
||||
).toContent(),
|
||||
stateKey = user.userId
|
||||
)
|
||||
}
|
||||
addAll(memberEvents)
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate the local state events related to the given third party invites, if any.
|
||||
*/
|
||||
private fun MutableList<Event>.createRoomThreePidEvents(createRoomBody: CreateRoomBody) = apply {
|
||||
val threePidEvents = createRoomBody.invite3pids.orEmpty().map { body ->
|
||||
val localThirdPartyInviteEvent = createLocalEvent(
|
||||
type = EventType.LOCAL_STATE_ROOM_THIRD_PARTY_INVITE,
|
||||
content = LocalRoomThirdPartyInviteContent(
|
||||
isDirect = createRoomBody.isDirect.orFalse(),
|
||||
membership = Membership.INVITE,
|
||||
displayName = body.address,
|
||||
thirdPartyInvite = body.toThreePid()
|
||||
).toContent(),
|
||||
stateKey = ""
|
||||
)
|
||||
val thirdPartyInviteEvent = createLocalEvent(
|
||||
type = EventType.STATE_ROOM_THIRD_PARTY_INVITE,
|
||||
content = RoomThirdPartyInviteContent(body.address, null, null, null).toContent(),
|
||||
stateKey = ""
|
||||
)
|
||||
listOf(localThirdPartyInviteEvent, thirdPartyInviteEvent)
|
||||
}.flatten()
|
||||
addAll(threePidEvents)
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate the local state event related to the given alias, if any.
|
||||
*/
|
||||
fun MutableList<Event>.createRoomAliasEvent(createRoomBody: CreateRoomBody) = apply {
|
||||
if (createRoomBody.roomAliasName != null) {
|
||||
val canonicalAliasContent = createLocalEvent(
|
||||
type = EventType.STATE_ROOM_CANONICAL_ALIAS,
|
||||
content = RoomCanonicalAliasContent(
|
||||
canonicalAlias = "${createRoomBody.roomAliasName}:${myUserId.getServerName()}"
|
||||
).toContent(),
|
||||
stateKey = ""
|
||||
)
|
||||
add(canonicalAliasContent)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate the local state events related to the given [CreateRoomPreset].
|
||||
* Ref: https://spec.matrix.org/latest/client-server-api/#post_matrixclientv3createroom
|
||||
*/
|
||||
private fun MutableList<Event>.createRoomPresetEvents(createRoomBody: CreateRoomBody) = apply {
|
||||
createRoomBody.preset ?: return@apply
|
||||
|
||||
var joinRules: RoomJoinRules? = null
|
||||
var historyVisibility: RoomHistoryVisibility? = null
|
||||
var guestAccess: GuestAccess? = null
|
||||
when (createRoomBody.preset) {
|
||||
CreateRoomPreset.PRESET_PRIVATE_CHAT,
|
||||
CreateRoomPreset.PRESET_TRUSTED_PRIVATE_CHAT -> {
|
||||
joinRules = RoomJoinRules.INVITE
|
||||
historyVisibility = RoomHistoryVisibility.SHARED
|
||||
guestAccess = GuestAccess.CanJoin
|
||||
}
|
||||
CreateRoomPreset.PRESET_PUBLIC_CHAT -> {
|
||||
joinRules = RoomJoinRules.PUBLIC
|
||||
historyVisibility = RoomHistoryVisibility.SHARED
|
||||
guestAccess = GuestAccess.Forbidden
|
||||
}
|
||||
}
|
||||
|
||||
add(createLocalEvent(EventType.STATE_ROOM_JOIN_RULES, RoomJoinRulesContent(joinRules.value).toContent(), ""))
|
||||
add(createLocalEvent(EventType.STATE_ROOM_HISTORY_VISIBILITY, RoomHistoryVisibilityContent(historyVisibility.value).toContent(), ""))
|
||||
add(createLocalEvent(EventType.STATE_ROOM_GUEST_ACCESS, RoomGuestAccessContent(guestAccess.value).toContent(), ""))
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate the local state events related to the given initial states, if any.
|
||||
* The given initial state events override the potential existing ones of the same type.
|
||||
*/
|
||||
private fun MutableList<Event>.createRoomInitialStateEvents(createRoomBody: CreateRoomBody) = apply {
|
||||
createRoomBody.initialStates ?: return@apply
|
||||
|
||||
val initialStateEvents = createRoomBody.initialStates.map { createLocalEvent(it.type, it.content, it.stateKey) }
|
||||
// Erase existing events of the same type
|
||||
removeAll { event -> event.type in initialStateEvents.map { it.type } }
|
||||
// Add the initial state events to the list
|
||||
addAll(initialStateEvents)
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate the local events related to the given room name and topic, if any.
|
||||
*/
|
||||
private fun MutableList<Event>.createRoomNameAndTopicStateEvents(createRoomBody: CreateRoomBody) = apply {
|
||||
if (createRoomBody.name != null) {
|
||||
add(createLocalEvent(EventType.STATE_ROOM_NAME, RoomNameContent(createRoomBody.name).toContent(), ""))
|
||||
}
|
||||
if (createRoomBody.topic != null) {
|
||||
add(createLocalEvent(EventType.STATE_ROOM_TOPIC, RoomTopicContent(createRoomBody.topic).toContent(), ""))
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate the local events which have not been set and are in that case provided by the server with default values:
|
||||
* - m.room.history_visibility (https://spec.matrix.org/latest/client-server-api/#server-behaviour-5)
|
||||
* - m.room.guest_access (https://spec.matrix.org/latest/client-server-api/#mroomguest_access)
|
||||
*/
|
||||
private fun MutableList<Event>.createRoomDefaultEvents() = apply {
|
||||
// HistoryVisibility
|
||||
if (none { it.type == EventType.STATE_ROOM_HISTORY_VISIBILITY }) {
|
||||
add(
|
||||
createLocalEvent(
|
||||
type = EventType.STATE_ROOM_HISTORY_VISIBILITY,
|
||||
content = RoomHistoryVisibilityContent(RoomHistoryVisibility.SHARED.value).toContent(),
|
||||
stateKey = ""
|
||||
)
|
||||
)
|
||||
}
|
||||
// GuestAccess
|
||||
if (none { it.type == EventType.STATE_ROOM_GUEST_ACCESS }) {
|
||||
add(
|
||||
createLocalEvent(
|
||||
type = EventType.STATE_ROOM_GUEST_ACCESS,
|
||||
content = RoomGuestAccessContent(GuestAccess.Forbidden.value).toContent(),
|
||||
stateKey = ""
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate a local event from the given parameters.
|
||||
*
|
||||
* @param type the event type, see [EventType]
|
||||
* @param content the content of the Event
|
||||
* @param stateKey the stateKey, if any
|
||||
*
|
||||
* @return a local event
|
||||
*/
|
||||
private fun createLocalEvent(type: String?, content: Content?, stateKey: String?): Event {
|
||||
return Event(
|
||||
type = type,
|
||||
senderId = myUserId,
|
||||
stateKey = stateKey,
|
||||
content = content,
|
||||
originServerTs = clock.epochMillis(),
|
||||
eventId = LocalEcho.createLocalEchoId()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user