From 76849c4374ce464e09d296312f69c7e4ac5a4bc7 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Fri, 8 Aug 2025 13:35:44 +0200 Subject: [PATCH] Introduce SessionWellknownRetriever and implementation that uses a MatrixClient. --- .../api/SessionWellknownRetriever.kt | 13 +++++ libraries/wellknown/impl/build.gradle.kts | 1 + .../impl/DefaultSessionWellknownRetriever.kt | 49 +++++++++++++++++++ .../impl/DefaultWellknownRetriever.kt | 14 ------ .../libraries/wellknown/impl/Mapper.kt | 26 ++++++++++ 5 files changed, 89 insertions(+), 14 deletions(-) create mode 100644 libraries/wellknown/api/src/main/kotlin/io/element/android/libraries/wellknown/api/SessionWellknownRetriever.kt create mode 100644 libraries/wellknown/impl/src/main/kotlin/io/element/android/libraries/wellknown/impl/DefaultSessionWellknownRetriever.kt create mode 100644 libraries/wellknown/impl/src/main/kotlin/io/element/android/libraries/wellknown/impl/Mapper.kt diff --git a/libraries/wellknown/api/src/main/kotlin/io/element/android/libraries/wellknown/api/SessionWellknownRetriever.kt b/libraries/wellknown/api/src/main/kotlin/io/element/android/libraries/wellknown/api/SessionWellknownRetriever.kt new file mode 100644 index 0000000000..7f7b9b983f --- /dev/null +++ b/libraries/wellknown/api/src/main/kotlin/io/element/android/libraries/wellknown/api/SessionWellknownRetriever.kt @@ -0,0 +1,13 @@ +/* + * Copyright 2025 New Vector Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.libraries.wellknown.api + +interface SessionWellknownRetriever { + suspend fun getWellKnown(): WellKnown? + suspend fun getElementWellKnown(): ElementWellKnown? +} diff --git a/libraries/wellknown/impl/build.gradle.kts b/libraries/wellknown/impl/build.gradle.kts index a9c1a1e9bf..0754ce6184 100644 --- a/libraries/wellknown/impl/build.gradle.kts +++ b/libraries/wellknown/impl/build.gradle.kts @@ -27,6 +27,7 @@ dependencies { implementation(libs.serialization.json) implementation(projects.libraries.architecture) implementation(projects.libraries.core) + implementation(projects.libraries.matrix.api) implementation(projects.libraries.network) implementation(projects.libraries.wellknown.api) } diff --git a/libraries/wellknown/impl/src/main/kotlin/io/element/android/libraries/wellknown/impl/DefaultSessionWellknownRetriever.kt b/libraries/wellknown/impl/src/main/kotlin/io/element/android/libraries/wellknown/impl/DefaultSessionWellknownRetriever.kt new file mode 100644 index 0000000000..259f7848b3 --- /dev/null +++ b/libraries/wellknown/impl/src/main/kotlin/io/element/android/libraries/wellknown/impl/DefaultSessionWellknownRetriever.kt @@ -0,0 +1,49 @@ +/* + * Copyright 2025 New Vector Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.libraries.wellknown.impl + +import com.squareup.anvil.annotations.ContributesBinding +import io.element.android.libraries.core.extensions.mapCatchingExceptions +import io.element.android.libraries.di.SessionScope +import io.element.android.libraries.matrix.api.MatrixClient +import io.element.android.libraries.wellknown.api.ElementWellKnown +import io.element.android.libraries.wellknown.api.SessionWellknownRetriever +import io.element.android.libraries.wellknown.api.WellKnown +import kotlinx.serialization.json.Json +import timber.log.Timber +import javax.inject.Inject + +@ContributesBinding(SessionScope::class) +class DefaultSessionWellknownRetriever @Inject constructor( + private val matrixClient: MatrixClient, +) : SessionWellknownRetriever { + private val parser by lazy { Json { ignoreUnknownKeys = true } } + private val domain by lazy { matrixClient.userIdServerName() } + + override suspend fun getWellKnown(): WellKnown? { + val url = "https://$domain/.well-known/matrix/client" + return matrixClient + .getUrl(url) + .mapCatchingExceptions { String(it) } + .mapCatchingExceptions { parser.decodeFromString(InternalWellKnown.serializer(), it) } + .onFailure { Timber.e(it, "Failed to retrieve .well-known from $domain") } + .map { it.map() } + .getOrNull() + } + + override suspend fun getElementWellKnown(): ElementWellKnown? { + val url = "https://$domain/.well-known/element/element.json" + return matrixClient + .getUrl(url) + .mapCatchingExceptions { String(it) } + .mapCatchingExceptions { parser.decodeFromString(InternalElementWellKnown.serializer(), it) } + .onFailure { Timber.e(it, "Failed to retrieve Element .well-known from $domain") } + .map { it.map() } + .getOrNull() + } +} diff --git a/libraries/wellknown/impl/src/main/kotlin/io/element/android/libraries/wellknown/impl/DefaultWellknownRetriever.kt b/libraries/wellknown/impl/src/main/kotlin/io/element/android/libraries/wellknown/impl/DefaultWellknownRetriever.kt index 4149d24df6..0d45f60be5 100644 --- a/libraries/wellknown/impl/src/main/kotlin/io/element/android/libraries/wellknown/impl/DefaultWellknownRetriever.kt +++ b/libraries/wellknown/impl/src/main/kotlin/io/element/android/libraries/wellknown/impl/DefaultWellknownRetriever.kt @@ -53,17 +53,3 @@ class DefaultWellknownRetriever @Inject constructor( } } } - -private fun InternalElementWellKnown.map() = ElementWellKnown( - registrationHelperUrl = registrationHelperUrl, - enforceElementPro = enforceElementPro, -) - -private fun InternalWellKnown.map() = WellKnown( - homeServer = homeServer?.map(), - identityServer = identityServer?.map(), -) - -private fun InternalWellKnownBaseConfig.map() = WellKnownBaseConfig( - baseURL = baseURL, -) diff --git a/libraries/wellknown/impl/src/main/kotlin/io/element/android/libraries/wellknown/impl/Mapper.kt b/libraries/wellknown/impl/src/main/kotlin/io/element/android/libraries/wellknown/impl/Mapper.kt new file mode 100644 index 0000000000..8625571c62 --- /dev/null +++ b/libraries/wellknown/impl/src/main/kotlin/io/element/android/libraries/wellknown/impl/Mapper.kt @@ -0,0 +1,26 @@ +/* + * Copyright 2025 New Vector Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.libraries.wellknown.impl + +import io.element.android.libraries.wellknown.api.ElementWellKnown +import io.element.android.libraries.wellknown.api.WellKnown +import io.element.android.libraries.wellknown.api.WellKnownBaseConfig + +internal fun InternalElementWellKnown.map() = ElementWellKnown( + registrationHelperUrl = registrationHelperUrl, + enforceElementPro = enforceElementPro, +) + +internal fun InternalWellKnown.map() = WellKnown( + homeServer = homeServer?.map(), + identityServer = identityServer?.map(), +) + +internal fun InternalWellKnownBaseConfig.map() = WellKnownBaseConfig( + baseURL = baseURL, +)