diff --git a/CHANGELOG.md b/CHANGELOG.md index 51dd50560e60f78bafba019070a5236f26b8fc89..c4b1a2935a87687dc529220eb1732c840dc0d83c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Changed +- Move remaining link matching and filtering functions from trixnity-messenger + ### Deprecated ### Removed 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 cace0e37e0a44715b20d8b1f566c2411b5a8722c..8778567649a4f1c532f777b2d101299f158a2b7d 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 @@ -16,7 +16,6 @@ object MatrixRegex { fun findMentions(message: String): Map { val links = findLinkMentions(message) - println(links) val users = findIdMentions(message) val linksRange = links.keys.sortedBy { it.first } val uniqueUsers = users.filter { (user, _) -> @@ -27,17 +26,39 @@ object MatrixRegex { return links.plus(uniqueUsers).toMap() } - fun findIdMentions(content: String): Map { - return idRegex.findAll(content) + fun findIdMentions(content: String, from: Int = 0, to: Int = content.length): Map { + return idRegex + .findAll(content, startIndex = from) + .filter { it.range.last < to } .filter { it.range.last - it.range.first <= 255 } .mapNotNull { Pair(it.range, parseMatrixId(it.value) ?: return@mapNotNull null) } .toMap() } - fun findLinkMentions(content: String): Map { - return Patterns.AUTOLINK_MATRIX_URI.findAll(content).mapNotNull { - Pair(it.range, MatrixLinks.parse(it.value) ?: return@mapNotNull null) - }.toMap() + fun findLinkMentions(content: String, from: Int = 0, to: Int = content.length): Map { + return Patterns.AUTOLINK_MATRIX_URI + .findAll(content, startIndex = from) + .filter { it.range.last < to } + .mapNotNull { + val trimmedContent = it.value.trimLink() + Pair( + it.range.first.until(it.range.first + trimmedContent.length), + MatrixLinks.parse(trimmedContent) ?: return@mapNotNull null + ) + }.toMap() + } + + fun findLinks(content: String, from: Int = 0, to: Int = content.length): Map { + return Patterns.AUTOLINK_MATRIX_URI + .findAll(content, startIndex = from) + .filter { it.range.last < to } + .map { + val trimmedContent = it.value.trimLink() + Pair( + it.range.first.until(it.range.first + trimmedContent.length), + trimmedContent, + ) + }.toMap() } fun isValidUserId(id: String): Boolean = @@ -73,4 +94,19 @@ object MatrixRegex { } return index >= 0 } + + private fun String.trimParens(): String = + if (endsWith(')')) { + val trimmed = trimEnd(')') + val openingParens = trimmed.count { it == '(' } + val closingParens = trimmed.count { it == ')' } + val endingParens = length - trimmed.length + val openParens = openingParens - closingParens + + val desiredParens = minOf(endingParens, openParens) + take(trimmed.length + desiredParens) + } else this + + private fun String.trimLink(): String = + trimEnd(',', '.', '!', '?', ':').trimParens() } \ No newline at end of file diff --git a/trixnity-core/src/commonTest/kotlin/net/folivo/trixnity/core/MatrixRegexTest.kt b/trixnity-core/src/commonTest/kotlin/net/folivo/trixnity/core/MatrixRegexTest.kt index 64d848d1cb723dc374dc884ea040dd277ad8aa7c..e801c8f405758566a402f6eb8a0da48a33adf457 100644 --- a/trixnity-core/src/commonTest/kotlin/net/folivo/trixnity/core/MatrixRegexTest.kt +++ b/trixnity-core/src/commonTest/kotlin/net/folivo/trixnity/core/MatrixRegexTest.kt @@ -658,4 +658,16 @@ class MatrixRegexTest : TrixnityBaseTest() { ) ) } + + @Test + fun `finds regular links`() { + assertEquals( + expected = mapOf( + 19..65 to "https://en.wikipedia.org/wiki/Matrix_(protocol)", + ), + actual = MatrixRegex.findLinks( + "I saw that online (https://en.wikipedia.org/wiki/Matrix_(protocol)), neat eh?" + ) + ) + } }