From 96c4c2a22f90a261476682b170c9a1d87c3ed80c Mon Sep 17 00:00:00 2001 From: Janne Mareike Koschinski Date: Thu, 10 Jul 2025 15:25:07 +0200 Subject: [PATCH 1/2] Improved APIs for parsing matrix links & mentions --- CHANGELOG.md | 1 + .../net/folivo/trixnity/core/MatrixRegex.kt | 44 ++++++++++++++++++- 2 files changed, 44 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a06f06061..a1932afe2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -31,6 +31,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Use event filter when filling timeline gaps - Retry operations are not stopped when sync is not running +- Improved APIs for parsing matrix links & mentions ### Deprecated diff --git a/trixnity-core/src/commonMain/kotlin/net/folivo/trixnity/core/MatrixRegex.kt b/trixnity-core/src/commonMain/kotlin/net/folivo/trixnity/core/MatrixRegex.kt index 3234cbd97..22fc4f3c0 100644 --- a/trixnity-core/src/commonMain/kotlin/net/folivo/trixnity/core/MatrixRegex.kt +++ b/trixnity-core/src/commonMain/kotlin/net/folivo/trixnity/core/MatrixRegex.kt @@ -61,7 +61,7 @@ object MatrixRegex { """matrix:(roomid\/$opaqueIdRegex:$servernameRegex)\/e\/($opaqueIdRegex)$queryParameterRegex?""" // https://spec.matrix.org/v1.11/appendices/#matrixto-navigation - private val viaArgumentRegex = """(?:\?(via=$servernameRegex))""" + private val viaArgumentRegex = """(\?via=([^\s&]+)(?:\&via=([^\s&]+))*)""" private val matrixToRegex = """https?:\/\/matrix\.to\/$hash\/""" private val userPermalinkRegex = """$matrixToRegex$at($userLocalpartRegex)$colon($servernameRegex)$viaArgumentRegex?""" @@ -289,6 +289,48 @@ object MatrixRegex { } } } + + fun parseUserLink(input: String, label: String?): Mention.User? { + val match = userIdUri.matchEntire(input) + ?: userIdPermalink.matchEntire(input) + return match?.groupValues?.filter(String::isNotBlank)?.let { result -> + val (match, localpart, domain) = result + val (params, _) = parseOptions(result.drop(3), false) + return Mention.User(UserId(localpart, domain), match, params, label) + } + } + + fun parseRoomIdLink(input: String, label: String?): Mention.Room? { + val match = roomIdUri.matchEntire(input) + ?: roomIdPermalink.matchEntire(input) + return match?.groupValues?.filter(String::isNotBlank)?.let { result -> + val (match, localpart, domain) = result + val (params, _) = parseOptions(result.drop(3), false) + return Mention.Room(RoomId(localpart, domain), match, params, label) + } + } + + fun parseRoomAliasLink(input: String, label: String?): Mention.RoomAlias? { + val match = roomAliasUri.matchEntire(input) + ?: roomAliasPermalink.matchEntire(input) + return match?.groupValues?.filter(String::isNotBlank)?.let { result -> + val (match, localpart, domain) = result + val (params, _) = parseOptions(result.drop(3), false) + return Mention.RoomAlias(RoomAliasId(localpart, domain), match, params, label) + } + } + + fun parseEventLink(input: String, label: String?): Mention.Event? { + val match = eventIdUri.matchEntire(input) + ?: eventIdPermalink.matchEntire(input) + return match?.groupValues?.filter(String::isNotBlank)?.let { result -> + val match = result[0] + val roomId = result[1].replaceFirst("roomid/", "!") + val eventId = result[2] + val (params, _) = parseOptions(result.drop(3), false) + return Mention.Event(RoomId(roomId), EventId("$$eventId"), match, label, params) + } + } } private fun String.toRegex(maxLength: Int) = "(?!.{${maxLength + 1},})$this".toRegex() -- GitLab From eb8a9f30fc01738b8cdfab99a70aceea4ea9256e Mon Sep 17 00:00:00 2001 From: Janne Mareike Koschinski Date: Tue, 15 Jul 2025 13:35:10 +0200 Subject: [PATCH 2/2] Make matrix.to regex public --- .../kotlin/net/folivo/trixnity/core/MatrixRegex.kt | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/trixnity-core/src/commonMain/kotlin/net/folivo/trixnity/core/MatrixRegex.kt b/trixnity-core/src/commonMain/kotlin/net/folivo/trixnity/core/MatrixRegex.kt index 22fc4f3c0..48600c73a 100644 --- a/trixnity-core/src/commonMain/kotlin/net/folivo/trixnity/core/MatrixRegex.kt +++ b/trixnity-core/src/commonMain/kotlin/net/folivo/trixnity/core/MatrixRegex.kt @@ -3,6 +3,7 @@ package net.folivo.trixnity.core import io.ktor.http.* import net.folivo.trixnity.core.model.* +@Suppress("DEPRECATION") object MatrixRegex { // Decode/Encode Grammar private fun makeSymboleRegex(symbole: String, code: String) = "(?:(?:$symbole)|(?:$code))" @@ -93,10 +94,14 @@ object MatrixRegex { val roomAliasUri by lazy { roomAliasUriRegex.toRegex(255) } val eventIdUri by lazy { eventUriRegex.toRegex(255) } - private val userIdPermalink by lazy { userPermalinkRegex.toRegex(255) } - private val roomIdPermalink by lazy { roomIdPermalinkRegex.toRegex(255) } - private val roomAliasPermalink by lazy { roomAliasPermalinkRegex.toRegex(255) } - private val eventIdPermalink by lazy { eventPermalinkRegex.toRegex(255) } + @Deprecated("matrix.to links should be replaced with matrix: links if possible") + val userIdPermalink by lazy { userPermalinkRegex.toRegex(255) } + @Deprecated("matrix.to links should be replaced with matrix: links if possible") + val roomIdPermalink by lazy { roomIdPermalinkRegex.toRegex(255) } + @Deprecated("matrix.to links should be replaced with matrix: links if possible") + val roomAliasPermalink by lazy { roomAliasPermalinkRegex.toRegex(255) } + @Deprecated("matrix.to links should be replaced with matrix: links if possible") + val eventIdPermalink by lazy { eventPermalinkRegex.toRegex(255) } internal val userIdPermalinkAnchor by lazy { getAnchor(userPermalinkRegex, 255).toRegex() } internal val roomIdPermalinkAnchor by lazy { getAnchor(roomIdPermalinkRegex, 255).toRegex() } -- GitLab