Invite by email (msisdn not working), command line (#548)
This commit is contained in:
parent
70e90d8542
commit
ab1d652f17
@ -18,6 +18,7 @@ package im.vector.matrix.android.api.session.room.members
|
|||||||
|
|
||||||
import androidx.lifecycle.LiveData
|
import androidx.lifecycle.LiveData
|
||||||
import im.vector.matrix.android.api.MatrixCallback
|
import im.vector.matrix.android.api.MatrixCallback
|
||||||
|
import im.vector.matrix.android.api.session.identity.ThreePid
|
||||||
import im.vector.matrix.android.api.session.room.model.RoomMemberSummary
|
import im.vector.matrix.android.api.session.room.model.RoomMemberSummary
|
||||||
import im.vector.matrix.android.api.util.Cancelable
|
import im.vector.matrix.android.api.util.Cancelable
|
||||||
|
|
||||||
@ -63,6 +64,12 @@ interface MembershipService {
|
|||||||
reason: String? = null,
|
reason: String? = null,
|
||||||
callback: MatrixCallback<Unit>): Cancelable
|
callback: MatrixCallback<Unit>): Cancelable
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Invite a user with email or phone number in the room
|
||||||
|
*/
|
||||||
|
fun invite3pid(threePid: ThreePid,
|
||||||
|
callback: MatrixCallback<Unit>): Cancelable
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Ban a user from the room
|
* Ban a user from the room
|
||||||
*/
|
*/
|
||||||
|
@ -62,6 +62,7 @@ import javax.net.ssl.HttpsURLConnection
|
|||||||
@SessionScope
|
@SessionScope
|
||||||
internal class DefaultIdentityService @Inject constructor(
|
internal class DefaultIdentityService @Inject constructor(
|
||||||
private val identityStore: IdentityStore,
|
private val identityStore: IdentityStore,
|
||||||
|
private val ensureIdentityTokenTask: EnsureIdentityTokenTask,
|
||||||
private val getOpenIdTokenTask: GetOpenIdTokenTask,
|
private val getOpenIdTokenTask: GetOpenIdTokenTask,
|
||||||
private val identityBulkLookupTask: IdentityBulkLookupTask,
|
private val identityBulkLookupTask: IdentityBulkLookupTask,
|
||||||
private val identityRegisterTask: IdentityRegisterTask,
|
private val identityRegisterTask: IdentityRegisterTask,
|
||||||
@ -278,7 +279,7 @@ internal class DefaultIdentityService @Inject constructor(
|
|||||||
}
|
}
|
||||||
|
|
||||||
private suspend fun lookUpInternal(canRetry: Boolean, threePids: List<ThreePid>): List<FoundThreePid> {
|
private suspend fun lookUpInternal(canRetry: Boolean, threePids: List<ThreePid>): List<FoundThreePid> {
|
||||||
ensureToken()
|
ensureIdentityTokenTask.execute(Unit)
|
||||||
|
|
||||||
return try {
|
return try {
|
||||||
identityBulkLookupTask.execute(IdentityBulkLookupTask.Params(threePids))
|
identityBulkLookupTask.execute(IdentityBulkLookupTask.Params(threePids))
|
||||||
@ -295,17 +296,6 @@ internal class DefaultIdentityService @Inject constructor(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private suspend fun ensureToken() {
|
|
||||||
val identityData = identityStore.getIdentityData() ?: throw IdentityServiceError.NoIdentityServerConfigured
|
|
||||||
val url = identityData.identityServerUrl ?: throw IdentityServiceError.NoIdentityServerConfigured
|
|
||||||
|
|
||||||
if (identityData.token == null) {
|
|
||||||
// Try to get a token
|
|
||||||
val token = getNewIdentityServerToken(url)
|
|
||||||
identityStore.setToken(token)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private suspend fun getNewIdentityServerToken(url: String): String {
|
private suspend fun getNewIdentityServerToken(url: String): String {
|
||||||
val api = retrofitFactory.create(unauthenticatedOkHttpClient, url).create(IdentityAuthAPI::class.java)
|
val api = retrofitFactory.create(unauthenticatedOkHttpClient, url).create(IdentityAuthAPI::class.java)
|
||||||
|
|
||||||
|
@ -0,0 +1,59 @@
|
|||||||
|
/*
|
||||||
|
* 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.identity
|
||||||
|
|
||||||
|
import dagger.Lazy
|
||||||
|
import im.vector.matrix.android.api.session.identity.IdentityServiceError
|
||||||
|
import im.vector.matrix.android.internal.di.UnauthenticatedWithCertificate
|
||||||
|
import im.vector.matrix.android.internal.network.RetrofitFactory
|
||||||
|
import im.vector.matrix.android.internal.session.identity.data.IdentityStore
|
||||||
|
import im.vector.matrix.android.internal.session.openid.GetOpenIdTokenTask
|
||||||
|
import im.vector.matrix.android.internal.task.Task
|
||||||
|
import okhttp3.OkHttpClient
|
||||||
|
import javax.inject.Inject
|
||||||
|
|
||||||
|
internal interface EnsureIdentityTokenTask : Task<Unit, Unit>
|
||||||
|
|
||||||
|
internal class DefaultEnsureIdentityTokenTask @Inject constructor(
|
||||||
|
private val identityStore: IdentityStore,
|
||||||
|
private val retrofitFactory: RetrofitFactory,
|
||||||
|
@UnauthenticatedWithCertificate
|
||||||
|
private val unauthenticatedOkHttpClient: Lazy<OkHttpClient>,
|
||||||
|
private val getOpenIdTokenTask: GetOpenIdTokenTask,
|
||||||
|
private val identityRegisterTask: IdentityRegisterTask
|
||||||
|
) : EnsureIdentityTokenTask {
|
||||||
|
|
||||||
|
override suspend fun execute(params: Unit) {
|
||||||
|
val identityData = identityStore.getIdentityData() ?: throw IdentityServiceError.NoIdentityServerConfigured
|
||||||
|
val url = identityData.identityServerUrl ?: throw IdentityServiceError.NoIdentityServerConfigured
|
||||||
|
|
||||||
|
if (identityData.token == null) {
|
||||||
|
// Try to get a token
|
||||||
|
val token = getNewIdentityServerToken(url)
|
||||||
|
identityStore.setToken(token)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private suspend fun getNewIdentityServerToken(url: String): String {
|
||||||
|
val api = retrofitFactory.create(unauthenticatedOkHttpClient, url).create(IdentityAuthAPI::class.java)
|
||||||
|
|
||||||
|
val openIdToken = getOpenIdTokenTask.execute(Unit)
|
||||||
|
val token = identityRegisterTask.execute(IdentityRegisterTask.Params(api, openIdToken))
|
||||||
|
|
||||||
|
return token.token
|
||||||
|
}
|
||||||
|
}
|
@ -78,6 +78,9 @@ internal abstract class IdentityModule {
|
|||||||
@Binds
|
@Binds
|
||||||
abstract fun bindIdentityStore(store: RealmIdentityStore): IdentityStore
|
abstract fun bindIdentityStore(store: RealmIdentityStore): IdentityStore
|
||||||
|
|
||||||
|
@Binds
|
||||||
|
abstract fun bindEnsureIdentityTokenTask(task: DefaultEnsureIdentityTokenTask): EnsureIdentityTokenTask
|
||||||
|
|
||||||
@Binds
|
@Binds
|
||||||
abstract fun bindIdentityPingTask(task: DefaultIdentityPingTask): IdentityPingTask
|
abstract fun bindIdentityPingTask(task: DefaultIdentityPingTask): IdentityPingTask
|
||||||
|
|
||||||
|
@ -31,6 +31,7 @@ import im.vector.matrix.android.internal.session.room.alias.RoomAliasDescription
|
|||||||
import im.vector.matrix.android.internal.session.room.membership.RoomMembersResponse
|
import im.vector.matrix.android.internal.session.room.membership.RoomMembersResponse
|
||||||
import im.vector.matrix.android.internal.session.room.membership.admin.UserIdAndReason
|
import im.vector.matrix.android.internal.session.room.membership.admin.UserIdAndReason
|
||||||
import im.vector.matrix.android.internal.session.room.membership.joining.InviteBody
|
import im.vector.matrix.android.internal.session.room.membership.joining.InviteBody
|
||||||
|
import im.vector.matrix.android.internal.session.room.membership.threepid.ThreePidInviteBody
|
||||||
import im.vector.matrix.android.internal.session.room.relation.RelationsResponse
|
import im.vector.matrix.android.internal.session.room.relation.RelationsResponse
|
||||||
import im.vector.matrix.android.internal.session.room.reporting.ReportContentBody
|
import im.vector.matrix.android.internal.session.room.reporting.ReportContentBody
|
||||||
import im.vector.matrix.android.internal.session.room.send.SendResponse
|
import im.vector.matrix.android.internal.session.room.send.SendResponse
|
||||||
@ -170,6 +171,14 @@ internal interface RoomAPI {
|
|||||||
@POST(NetworkConstants.URI_API_PREFIX_PATH_R0 + "rooms/{roomId}/invite")
|
@POST(NetworkConstants.URI_API_PREFIX_PATH_R0 + "rooms/{roomId}/invite")
|
||||||
fun invite(@Path("roomId") roomId: String, @Body body: InviteBody): Call<Unit>
|
fun invite(@Path("roomId") roomId: String, @Body body: InviteBody): Call<Unit>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Invite a user to a room, using a ThreePid
|
||||||
|
* Ref: https://matrix.org/docs/spec/client_server/r0.6.1#id101
|
||||||
|
* @param roomId Required. The room identifier (not alias) to which to invite the user.
|
||||||
|
*/
|
||||||
|
@POST(NetworkConstants.URI_API_PREFIX_PATH_R0 + "rooms/{roomId}/invite")
|
||||||
|
fun invite3pid(@Path("roomId") roomId: String, @Body body: ThreePidInviteBody): Call<Unit>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Send a generic state events
|
* Send a generic state events
|
||||||
*
|
*
|
||||||
|
@ -44,6 +44,8 @@ import im.vector.matrix.android.internal.session.room.membership.joining.InviteT
|
|||||||
import im.vector.matrix.android.internal.session.room.membership.joining.JoinRoomTask
|
import im.vector.matrix.android.internal.session.room.membership.joining.JoinRoomTask
|
||||||
import im.vector.matrix.android.internal.session.room.membership.leaving.DefaultLeaveRoomTask
|
import im.vector.matrix.android.internal.session.room.membership.leaving.DefaultLeaveRoomTask
|
||||||
import im.vector.matrix.android.internal.session.room.membership.leaving.LeaveRoomTask
|
import im.vector.matrix.android.internal.session.room.membership.leaving.LeaveRoomTask
|
||||||
|
import im.vector.matrix.android.internal.session.room.membership.threepid.DefaultInviteThreePidTask
|
||||||
|
import im.vector.matrix.android.internal.session.room.membership.threepid.InviteThreePidTask
|
||||||
import im.vector.matrix.android.internal.session.room.read.DefaultMarkAllRoomsReadTask
|
import im.vector.matrix.android.internal.session.room.read.DefaultMarkAllRoomsReadTask
|
||||||
import im.vector.matrix.android.internal.session.room.read.DefaultSetReadMarkersTask
|
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.MarkAllRoomsReadTask
|
||||||
@ -139,6 +141,9 @@ internal abstract class RoomModule {
|
|||||||
@Binds
|
@Binds
|
||||||
abstract fun bindInviteTask(task: DefaultInviteTask): InviteTask
|
abstract fun bindInviteTask(task: DefaultInviteTask): InviteTask
|
||||||
|
|
||||||
|
@Binds
|
||||||
|
abstract fun bindInviteThreePidTask(task: DefaultInviteThreePidTask): InviteThreePidTask
|
||||||
|
|
||||||
@Binds
|
@Binds
|
||||||
abstract fun bindJoinRoomTask(task: DefaultJoinRoomTask): JoinRoomTask
|
abstract fun bindJoinRoomTask(task: DefaultJoinRoomTask): JoinRoomTask
|
||||||
|
|
||||||
|
@ -21,6 +21,7 @@ import com.squareup.inject.assisted.Assisted
|
|||||||
import com.squareup.inject.assisted.AssistedInject
|
import com.squareup.inject.assisted.AssistedInject
|
||||||
import com.zhuinden.monarchy.Monarchy
|
import com.zhuinden.monarchy.Monarchy
|
||||||
import im.vector.matrix.android.api.MatrixCallback
|
import im.vector.matrix.android.api.MatrixCallback
|
||||||
|
import im.vector.matrix.android.api.session.identity.ThreePid
|
||||||
import im.vector.matrix.android.api.session.room.members.MembershipService
|
import im.vector.matrix.android.api.session.room.members.MembershipService
|
||||||
import im.vector.matrix.android.api.session.room.members.RoomMemberQueryParams
|
import im.vector.matrix.android.api.session.room.members.RoomMemberQueryParams
|
||||||
import im.vector.matrix.android.api.session.room.model.Membership
|
import im.vector.matrix.android.api.session.room.model.Membership
|
||||||
@ -36,6 +37,7 @@ import im.vector.matrix.android.internal.session.room.membership.admin.Membershi
|
|||||||
import im.vector.matrix.android.internal.session.room.membership.joining.InviteTask
|
import im.vector.matrix.android.internal.session.room.membership.joining.InviteTask
|
||||||
import im.vector.matrix.android.internal.session.room.membership.joining.JoinRoomTask
|
import im.vector.matrix.android.internal.session.room.membership.joining.JoinRoomTask
|
||||||
import im.vector.matrix.android.internal.session.room.membership.leaving.LeaveRoomTask
|
import im.vector.matrix.android.internal.session.room.membership.leaving.LeaveRoomTask
|
||||||
|
import im.vector.matrix.android.internal.session.room.membership.threepid.InviteThreePidTask
|
||||||
import im.vector.matrix.android.internal.task.TaskExecutor
|
import im.vector.matrix.android.internal.task.TaskExecutor
|
||||||
import im.vector.matrix.android.internal.task.configureWith
|
import im.vector.matrix.android.internal.task.configureWith
|
||||||
import im.vector.matrix.android.internal.util.fetchCopied
|
import im.vector.matrix.android.internal.util.fetchCopied
|
||||||
@ -48,6 +50,7 @@ internal class DefaultMembershipService @AssistedInject constructor(
|
|||||||
private val taskExecutor: TaskExecutor,
|
private val taskExecutor: TaskExecutor,
|
||||||
private val loadRoomMembersTask: LoadRoomMembersTask,
|
private val loadRoomMembersTask: LoadRoomMembersTask,
|
||||||
private val inviteTask: InviteTask,
|
private val inviteTask: InviteTask,
|
||||||
|
private val inviteThreePidTask: InviteThreePidTask,
|
||||||
private val joinTask: JoinRoomTask,
|
private val joinTask: JoinRoomTask,
|
||||||
private val leaveRoomTask: LeaveRoomTask,
|
private val leaveRoomTask: LeaveRoomTask,
|
||||||
private val membershipAdminTask: MembershipAdminTask,
|
private val membershipAdminTask: MembershipAdminTask,
|
||||||
@ -152,6 +155,15 @@ internal class DefaultMembershipService @AssistedInject constructor(
|
|||||||
.executeBy(taskExecutor)
|
.executeBy(taskExecutor)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun invite3pid(threePid: ThreePid, callback: MatrixCallback<Unit>): Cancelable {
|
||||||
|
val params = InviteThreePidTask.Params(roomId, threePid)
|
||||||
|
return inviteThreePidTask
|
||||||
|
.configureWith(params) {
|
||||||
|
this.callback = callback
|
||||||
|
}
|
||||||
|
.executeBy(taskExecutor)
|
||||||
|
}
|
||||||
|
|
||||||
override fun join(reason: String?, viaServers: List<String>, callback: MatrixCallback<Unit>): Cancelable {
|
override fun join(reason: String?, viaServers: List<String>, callback: MatrixCallback<Unit>): Cancelable {
|
||||||
val params = JoinRoomTask.Params(roomId, reason, viaServers)
|
val params = JoinRoomTask.Params(roomId, reason, viaServers)
|
||||||
return joinTask
|
return joinTask
|
||||||
|
@ -0,0 +1,65 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2019 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.membership.threepid
|
||||||
|
|
||||||
|
import im.vector.matrix.android.api.session.identity.IdentityServiceError
|
||||||
|
import im.vector.matrix.android.api.session.identity.ThreePid
|
||||||
|
import im.vector.matrix.android.api.session.identity.toMedium
|
||||||
|
import im.vector.matrix.android.internal.di.AuthenticatedIdentity
|
||||||
|
import im.vector.matrix.android.internal.network.executeRequest
|
||||||
|
import im.vector.matrix.android.internal.network.token.AccessTokenProvider
|
||||||
|
import im.vector.matrix.android.internal.session.identity.EnsureIdentityTokenTask
|
||||||
|
import im.vector.matrix.android.internal.session.identity.data.IdentityStore
|
||||||
|
import im.vector.matrix.android.internal.session.identity.data.getIdentityServerUrlWithoutProtocol
|
||||||
|
import im.vector.matrix.android.internal.session.room.RoomAPI
|
||||||
|
import im.vector.matrix.android.internal.task.Task
|
||||||
|
import org.greenrobot.eventbus.EventBus
|
||||||
|
import javax.inject.Inject
|
||||||
|
|
||||||
|
internal interface InviteThreePidTask : Task<InviteThreePidTask.Params, Unit> {
|
||||||
|
data class Params(
|
||||||
|
val roomId: String,
|
||||||
|
val threePid: ThreePid
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
internal class DefaultInviteThreePidTask @Inject constructor(
|
||||||
|
private val roomAPI: RoomAPI,
|
||||||
|
private val eventBus: EventBus,
|
||||||
|
private val identityStore: IdentityStore,
|
||||||
|
private val ensureIdentityTokenTask: EnsureIdentityTokenTask,
|
||||||
|
@AuthenticatedIdentity
|
||||||
|
private val accessTokenProvider: AccessTokenProvider
|
||||||
|
) : InviteThreePidTask {
|
||||||
|
|
||||||
|
override suspend fun execute(params: InviteThreePidTask.Params) {
|
||||||
|
ensureIdentityTokenTask.execute(Unit)
|
||||||
|
|
||||||
|
val identityServerUrlWithoutProtocol = identityStore.getIdentityServerUrlWithoutProtocol() ?: throw IdentityServiceError.NoIdentityServerConfigured
|
||||||
|
val identityServerAccessToken = accessTokenProvider.getToken() ?: throw IdentityServiceError.NoIdentityServerConfigured
|
||||||
|
|
||||||
|
return executeRequest(eventBus) {
|
||||||
|
val body = ThreePidInviteBody(
|
||||||
|
id_server = identityServerUrlWithoutProtocol,
|
||||||
|
id_access_token = identityServerAccessToken,
|
||||||
|
medium = params.threePid.toMedium(),
|
||||||
|
address = params.threePid.value
|
||||||
|
)
|
||||||
|
apiCall = roomAPI.invite3pid(params.roomId, body)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,41 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2019 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.membership.threepid
|
||||||
|
|
||||||
|
import com.squareup.moshi.Json
|
||||||
|
import com.squareup.moshi.JsonClass
|
||||||
|
|
||||||
|
@JsonClass(generateAdapter = true)
|
||||||
|
internal data class ThreePidInviteBody(
|
||||||
|
/**
|
||||||
|
* Required. The hostname+port of the identity server which should be used for third party identifier lookups.
|
||||||
|
*/
|
||||||
|
@Json(name = "id_server") val id_server: String,
|
||||||
|
/**
|
||||||
|
* Required. An access token previously registered with the identity server. Servers can treat this as optional
|
||||||
|
* to distinguish between r0.5-compatible clients and this specification version.
|
||||||
|
*/
|
||||||
|
@Json(name = "id_access_token") val id_access_token: String,
|
||||||
|
/**
|
||||||
|
* Required. The kind of address being passed in the address field, for example email.
|
||||||
|
*/
|
||||||
|
@Json(name = "medium") val medium: String,
|
||||||
|
/**
|
||||||
|
* Required. The invitee's third party identifier.
|
||||||
|
*/
|
||||||
|
@Json(name = "address") val address: String
|
||||||
|
)
|
@ -19,6 +19,8 @@ package im.vector.riotx.core.extensions
|
|||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.util.Patterns
|
import android.util.Patterns
|
||||||
import androidx.fragment.app.Fragment
|
import androidx.fragment.app.Fragment
|
||||||
|
import com.google.i18n.phonenumbers.NumberParseException
|
||||||
|
import com.google.i18n.phonenumbers.PhoneNumberUtil
|
||||||
|
|
||||||
fun Boolean.toOnOff() = if (this) "ON" else "OFF"
|
fun Boolean.toOnOff() = if (this) "ON" else "OFF"
|
||||||
|
|
||||||
@ -33,3 +35,16 @@ fun <T : Fragment> T.withArgs(block: Bundle.() -> Unit) = apply { arguments = Bu
|
|||||||
* Check if a CharSequence is an email
|
* Check if a CharSequence is an email
|
||||||
*/
|
*/
|
||||||
fun CharSequence.isEmail() = Patterns.EMAIL_ADDRESS.matcher(this).matches()
|
fun CharSequence.isEmail() = Patterns.EMAIL_ADDRESS.matcher(this).matches()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if a CharSequence is a phone number
|
||||||
|
* FIXME It does not work?
|
||||||
|
*/
|
||||||
|
fun CharSequence.isMsisdn(): Boolean {
|
||||||
|
return try {
|
||||||
|
PhoneNumberUtil.getInstance().parse(this, null)
|
||||||
|
true
|
||||||
|
} catch (e: NumberParseException) {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -17,6 +17,9 @@
|
|||||||
package im.vector.riotx.features.command
|
package im.vector.riotx.features.command
|
||||||
|
|
||||||
import im.vector.matrix.android.api.MatrixPatterns
|
import im.vector.matrix.android.api.MatrixPatterns
|
||||||
|
import im.vector.matrix.android.api.session.identity.ThreePid
|
||||||
|
import im.vector.riotx.core.extensions.isEmail
|
||||||
|
import im.vector.riotx.core.extensions.isMsisdn
|
||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
|
|
||||||
object CommandParser {
|
object CommandParser {
|
||||||
@ -139,15 +142,24 @@ object CommandParser {
|
|||||||
if (messageParts.size >= 2) {
|
if (messageParts.size >= 2) {
|
||||||
val userId = messageParts[1]
|
val userId = messageParts[1]
|
||||||
|
|
||||||
if (MatrixPatterns.isUserId(userId)) {
|
when {
|
||||||
ParsedCommand.Invite(
|
MatrixPatterns.isUserId(userId) -> {
|
||||||
userId,
|
ParsedCommand.Invite(
|
||||||
textMessage.substring(Command.INVITE.length + userId.length)
|
userId,
|
||||||
.trim()
|
textMessage.substring(Command.INVITE.length + userId.length)
|
||||||
.takeIf { it.isNotBlank() }
|
.trim()
|
||||||
)
|
.takeIf { it.isNotBlank() }
|
||||||
} else {
|
)
|
||||||
ParsedCommand.ErrorSyntax(Command.INVITE)
|
}
|
||||||
|
userId.isEmail() -> {
|
||||||
|
ParsedCommand.Invite3Pid(ThreePid.Email(userId))
|
||||||
|
}
|
||||||
|
userId.isMsisdn() -> {
|
||||||
|
ParsedCommand.Invite3Pid(ThreePid.Msisdn(userId))
|
||||||
|
}
|
||||||
|
else -> {
|
||||||
|
ParsedCommand.ErrorSyntax(Command.INVITE)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
ParsedCommand.ErrorSyntax(Command.INVITE)
|
ParsedCommand.ErrorSyntax(Command.INVITE)
|
||||||
|
@ -16,6 +16,8 @@
|
|||||||
|
|
||||||
package im.vector.riotx.features.command
|
package im.vector.riotx.features.command
|
||||||
|
|
||||||
|
import im.vector.matrix.android.api.session.identity.ThreePid
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represent a parsed command
|
* Represent a parsed command
|
||||||
*/
|
*/
|
||||||
@ -41,6 +43,7 @@ sealed class ParsedCommand {
|
|||||||
class UnbanUser(val userId: String, val reason: String?) : ParsedCommand()
|
class UnbanUser(val userId: String, val reason: String?) : ParsedCommand()
|
||||||
class SetUserPowerLevel(val userId: String, val powerLevel: Int?) : ParsedCommand()
|
class SetUserPowerLevel(val userId: String, val powerLevel: Int?) : ParsedCommand()
|
||||||
class Invite(val userId: String, val reason: String?) : ParsedCommand()
|
class Invite(val userId: String, val reason: String?) : ParsedCommand()
|
||||||
|
class Invite3Pid(val threePid: ThreePid) : ParsedCommand()
|
||||||
class JoinRoom(val roomAlias: String, val reason: String?) : ParsedCommand()
|
class JoinRoom(val roomAlias: String, val reason: String?) : ParsedCommand()
|
||||||
class PartRoom(val roomAlias: String, val reason: String?) : ParsedCommand()
|
class PartRoom(val roomAlias: String, val reason: String?) : ParsedCommand()
|
||||||
class ChangeTopic(val topic: String) : ParsedCommand()
|
class ChangeTopic(val topic: String) : ParsedCommand()
|
||||||
|
@ -960,7 +960,7 @@ class RoomDetailFragment @Inject constructor(
|
|||||||
updateComposerText("")
|
updateComposerText("")
|
||||||
}
|
}
|
||||||
is RoomDetailViewEvents.SlashCommandResultError -> {
|
is RoomDetailViewEvents.SlashCommandResultError -> {
|
||||||
displayCommandError(sendMessageResult.throwable.localizedMessage ?: getString(R.string.unexpected_error))
|
displayCommandError(errorFormatter.toHumanReadable(sendMessageResult.throwable))
|
||||||
}
|
}
|
||||||
is RoomDetailViewEvents.SlashCommandNotImplemented -> {
|
is RoomDetailViewEvents.SlashCommandNotImplemented -> {
|
||||||
displayCommandError(getString(R.string.not_implemented))
|
displayCommandError(getString(R.string.not_implemented))
|
||||||
|
@ -457,6 +457,10 @@ class RoomDetailViewModel @AssistedInject constructor(
|
|||||||
handleInviteSlashCommand(slashCommandResult)
|
handleInviteSlashCommand(slashCommandResult)
|
||||||
popDraft()
|
popDraft()
|
||||||
}
|
}
|
||||||
|
is ParsedCommand.Invite3Pid -> {
|
||||||
|
handleInvite3pidSlashCommand(slashCommandResult)
|
||||||
|
popDraft()
|
||||||
|
}
|
||||||
is ParsedCommand.SetUserPowerLevel -> {
|
is ParsedCommand.SetUserPowerLevel -> {
|
||||||
handleSetUserPowerLevel(slashCommandResult)
|
handleSetUserPowerLevel(slashCommandResult)
|
||||||
popDraft()
|
popDraft()
|
||||||
@ -678,6 +682,12 @@ class RoomDetailViewModel @AssistedInject constructor(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun handleInvite3pidSlashCommand(invite: ParsedCommand.Invite3Pid) {
|
||||||
|
launchSlashCommandFlow {
|
||||||
|
room.invite3pid(invite.threePid, it)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun handleSetUserPowerLevel(setUserPowerLevel: ParsedCommand.SetUserPowerLevel) {
|
private fun handleSetUserPowerLevel(setUserPowerLevel: ParsedCommand.SetUserPowerLevel) {
|
||||||
val currentPowerLevelsContent = room.getStateEvent(EventType.STATE_ROOM_POWER_LEVELS)
|
val currentPowerLevelsContent = room.getStateEvent(EventType.STATE_ROOM_POWER_LEVELS)
|
||||||
?.content
|
?.content
|
||||||
|
Loading…
x
Reference in New Issue
Block a user