From 8e36efe0c22dadc956af2ca88feb40c3ad88c9d4 Mon Sep 17 00:00:00 2001 From: Adam Brown Date: Fri, 28 Oct 2022 22:19:16 +0100 Subject: [PATCH] message parsing refactor --- .../app/dapk/st/matrix/sync/SyncService.kt | 2 +- .../sync/internal/DefaultSyncService.kt | 1 + .../sync/internal/room/RoomEventsDecrypter.kt | 2 +- .../sync/internal/sync/RichMessageParser.kt | 197 ------------------ .../sync/internal/sync/RoomEventCreator.kt | 1 + .../sync/internal/sync/RoomEventFactory.kt | 1 + .../sync/internal/sync/message/HtmlParser.kt | 118 +++++++++++ .../sync/internal/sync/message/ParserScope.kt | 13 ++ .../sync/internal/sync/message/PartBuilder.kt | 56 +++++ .../sync/message/RichMessageParser.kt | 50 +++++ .../sync/internal/sync/message/UrlParser.kt | 47 +++++ .../internal/room/RoomEventsDecrypterTest.kt | 2 +- .../internal/sync/RichMessageParserTest.kt | 3 +- .../internal/sync/RoomEventCreatorTest.kt | 1 + 14 files changed, 293 insertions(+), 201 deletions(-) delete mode 100644 matrix/services/sync/src/main/kotlin/app/dapk/st/matrix/sync/internal/sync/RichMessageParser.kt create mode 100644 matrix/services/sync/src/main/kotlin/app/dapk/st/matrix/sync/internal/sync/message/HtmlParser.kt create mode 100644 matrix/services/sync/src/main/kotlin/app/dapk/st/matrix/sync/internal/sync/message/ParserScope.kt create mode 100644 matrix/services/sync/src/main/kotlin/app/dapk/st/matrix/sync/internal/sync/message/PartBuilder.kt create mode 100644 matrix/services/sync/src/main/kotlin/app/dapk/st/matrix/sync/internal/sync/message/RichMessageParser.kt create mode 100644 matrix/services/sync/src/main/kotlin/app/dapk/st/matrix/sync/internal/sync/message/UrlParser.kt diff --git a/matrix/services/sync/src/main/kotlin/app/dapk/st/matrix/sync/SyncService.kt b/matrix/services/sync/src/main/kotlin/app/dapk/st/matrix/sync/SyncService.kt index c6923a0..a5726df 100644 --- a/matrix/services/sync/src/main/kotlin/app/dapk/st/matrix/sync/SyncService.kt +++ b/matrix/services/sync/src/main/kotlin/app/dapk/st/matrix/sync/SyncService.kt @@ -8,7 +8,7 @@ import app.dapk.st.matrix.sync.internal.DefaultSyncService import app.dapk.st.matrix.sync.internal.request.* import app.dapk.st.matrix.sync.internal.room.MessageDecrypter import app.dapk.st.matrix.sync.internal.room.MissingMessageDecrypter -import app.dapk.st.matrix.sync.internal.sync.RichMessageParser +import app.dapk.st.matrix.sync.internal.sync.message.RichMessageParser import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.flow.Flow diff --git a/matrix/services/sync/src/main/kotlin/app/dapk/st/matrix/sync/internal/DefaultSyncService.kt b/matrix/services/sync/src/main/kotlin/app/dapk/st/matrix/sync/internal/DefaultSyncService.kt index 907388c..3eb9136 100644 --- a/matrix/services/sync/src/main/kotlin/app/dapk/st/matrix/sync/internal/DefaultSyncService.kt +++ b/matrix/services/sync/src/main/kotlin/app/dapk/st/matrix/sync/internal/DefaultSyncService.kt @@ -13,6 +13,7 @@ import app.dapk.st.matrix.sync.internal.room.RoomEventsDecrypter import app.dapk.st.matrix.sync.internal.room.SyncEventDecrypter import app.dapk.st.matrix.sync.internal.room.SyncSideEffects import app.dapk.st.matrix.sync.internal.sync.* +import app.dapk.st.matrix.sync.internal.sync.message.RichMessageParser import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.async import kotlinx.coroutines.awaitAll diff --git a/matrix/services/sync/src/main/kotlin/app/dapk/st/matrix/sync/internal/room/RoomEventsDecrypter.kt b/matrix/services/sync/src/main/kotlin/app/dapk/st/matrix/sync/internal/room/RoomEventsDecrypter.kt index 0f88ba5..3e2c540 100644 --- a/matrix/services/sync/src/main/kotlin/app/dapk/st/matrix/sync/internal/room/RoomEventsDecrypter.kt +++ b/matrix/services/sync/src/main/kotlin/app/dapk/st/matrix/sync/internal/room/RoomEventsDecrypter.kt @@ -6,7 +6,7 @@ import app.dapk.st.matrix.sync.internal.request.ApiTimelineEvent import app.dapk.st.matrix.sync.internal.request.ApiTimelineEvent.TimelineMessage.Content.Image import app.dapk.st.matrix.sync.internal.request.ApiTimelineEvent.TimelineMessage.Content.Text import app.dapk.st.matrix.sync.internal.request.DecryptedContent -import app.dapk.st.matrix.sync.internal.sync.RichMessageParser +import app.dapk.st.matrix.sync.internal.sync.message.RichMessageParser import kotlinx.serialization.json.Json internal class RoomEventsDecrypter( diff --git a/matrix/services/sync/src/main/kotlin/app/dapk/st/matrix/sync/internal/sync/RichMessageParser.kt b/matrix/services/sync/src/main/kotlin/app/dapk/st/matrix/sync/internal/sync/RichMessageParser.kt deleted file mode 100644 index 692d280..0000000 --- a/matrix/services/sync/src/main/kotlin/app/dapk/st/matrix/sync/internal/sync/RichMessageParser.kt +++ /dev/null @@ -1,197 +0,0 @@ -package app.dapk.st.matrix.sync.internal.sync - -import app.dapk.st.matrix.common.RichText -import app.dapk.st.matrix.common.RichText.Part.* -import app.dapk.st.matrix.common.UserId - -private const val INVALID_TRAILING_CHARS = ",.:;?" -private const val TAG_OPEN = '<' -private const val TAG_CLOSE = '>' - -class RichMessageParser { - - fun parse(source: String): RichText { - val input = source - .removeHtmlEntities() - .dropTextFallback() - val builder = PartBuilder() - var openIndex = 0 - var closeIndex = 0 - var lastStartIndex = 0 - while (openIndex != -1) { - val foundIndex = input.indexOf(TAG_OPEN, startIndex = openIndex) - if (foundIndex != -1) { - closeIndex = input.indexOf(TAG_CLOSE, startIndex = foundIndex) - if (closeIndex == -1) { - openIndex++ - } else { - val wholeTag = input.substring(foundIndex, closeIndex + 1) - val tagName = wholeTag.substring(1, wholeTag.indexOfFirst { it == '>' || it == ' ' }) - - if (tagName.startsWith('@')) { - if (openIndex != foundIndex) { - builder.appendText(input.substring(openIndex, foundIndex)) - } - builder.appendPerson(UserId(tagName), tagName) - openIndex = foundIndex + wholeTag.length - lastStartIndex = openIndex - continue - } - - if (tagName == "br") { - if (openIndex != foundIndex) { - builder.appendText(input.substring(openIndex, foundIndex)) - } - builder.appendText("\n") - openIndex = foundIndex + wholeTag.length - lastStartIndex = openIndex - continue - } - - val exitTag = "" - val exitIndex = input.indexOf(exitTag, startIndex = closeIndex) - if (exitIndex == -1) { - openIndex++ - } else { - when (tagName) { - "mx-reply" -> { - openIndex = exitIndex + exitTag.length - lastStartIndex = openIndex - continue - } - } - - if (openIndex != foundIndex) { - builder.appendText(input.substring(openIndex, foundIndex)) - } - val tagContent = input.substring(closeIndex + 1, exitIndex) - openIndex = exitIndex + exitTag.length - lastStartIndex = openIndex - - when (tagName) { - "a" -> { - val findHrefUrl = wholeTag.substringAfter("href=").replace("\"", "").removeSuffix(">") - if (findHrefUrl.startsWith("https://matrix.to/#/@")) { - val userId = UserId(findHrefUrl.substringAfter("https://matrix.to/#/").substringBeforeLast("\"")) - builder.appendPerson(userId, "@${tagContent.removePrefix("@")}") - if (input.getOrNull(openIndex) == ':') { - openIndex++ - lastStartIndex = openIndex - } - } else { - builder.appendLink(findHrefUrl, label = tagContent) - } - } - - "b" -> builder.appendBold(tagContent) - "strong" -> builder.appendBold(tagContent) - "i" -> builder.appendItalic(tagContent) - "em" -> builder.appendItalic(tagContent) - - else -> builder.appendText(tagContent) - } - } - } - } else { - // check for urls - val urlIndex = input.indexOf("http", startIndex = openIndex) - if (urlIndex != -1) { - if (lastStartIndex != urlIndex) { - builder.appendText(input.substring(lastStartIndex, urlIndex)) - } - - val originalUrl = input.substring(urlIndex) - val urlEndIndex = originalUrl.indexOfFirst { it == '\n' || it == ' ' } - val urlContinuesUntilEnd = urlEndIndex == -1 - when { - urlContinuesUntilEnd -> { - val cleanedUrl = originalUrl.bestGuessStripTrailingUrlChar() - builder.appendLink(url = cleanedUrl, label = null) - if (cleanedUrl != originalUrl) { - builder.appendText(originalUrl.last().toString()) - } - break - } - - else -> { - val originalUrl = input.substring(urlIndex, urlEndIndex) - val cleanedUrl = originalUrl.bestGuessStripTrailingUrlChar() - builder.appendLink(url = cleanedUrl, label = null) - openIndex = if (originalUrl == cleanedUrl) urlEndIndex else urlEndIndex - 1 - lastStartIndex = openIndex - continue - } - } - } - - // exit - if (lastStartIndex < input.length) { - builder.appendText(input.substring(lastStartIndex)) - } - break - } - } - return RichText(builder.build()) - } -} - -private fun String.removeHtmlEntities() = this.replace(""", "\"").replace("'", "'") - -private fun String.dropTextFallback() = this.lines() - .dropWhile { it.startsWith("> ") || it.isEmpty() } - .joinToString(separator = "\n") - -private fun String.bestGuessStripTrailingUrlChar(): String { - val last = this.last() - return if (INVALID_TRAILING_CHARS.contains(last)) { - this.dropLast(1) - } else { - this - } -} - -private class PartBuilder { - - private var normalBuffer = StringBuilder() - - private val parts = mutableSetOf() - - fun appendText(value: String) { - normalBuffer.append(value.cleanFirstTextLine()) - } - - fun appendItalic(value: String) { - flushNormalBuffer() - parts.add(Italic(value.cleanFirstTextLine())) - } - - fun appendBold(value: String) { - flushNormalBuffer() - parts.add(Bold(value.cleanFirstTextLine())) - } - - private fun String.cleanFirstTextLine() = if (parts.isEmpty() && normalBuffer.isEmpty()) this.trimStart() else this - - fun appendPerson(userId: UserId, displayName: String) { - flushNormalBuffer() - parts.add(Person(userId, displayName)) - } - - fun appendLink(url: String, label: String?) { - flushNormalBuffer() - parts.add(Link(url, label ?: url)) - } - - fun build(): Set { - flushNormalBuffer() - return parts - } - - private fun flushNormalBuffer() { - if (normalBuffer.isNotEmpty()) { - parts.add(Normal(normalBuffer.toString())) - normalBuffer.clear() - } - } - -} \ No newline at end of file diff --git a/matrix/services/sync/src/main/kotlin/app/dapk/st/matrix/sync/internal/sync/RoomEventCreator.kt b/matrix/services/sync/src/main/kotlin/app/dapk/st/matrix/sync/internal/sync/RoomEventCreator.kt index 72d9a46..d291f6f 100644 --- a/matrix/services/sync/src/main/kotlin/app/dapk/st/matrix/sync/internal/sync/RoomEventCreator.kt +++ b/matrix/services/sync/src/main/kotlin/app/dapk/st/matrix/sync/internal/sync/RoomEventCreator.kt @@ -12,6 +12,7 @@ import app.dapk.st.matrix.sync.RoomMembersService import app.dapk.st.matrix.sync.find import app.dapk.st.matrix.sync.internal.request.ApiEncryptedContent import app.dapk.st.matrix.sync.internal.request.ApiTimelineEvent +import app.dapk.st.matrix.sync.internal.sync.message.RichMessageParser private typealias Lookup = suspend (EventId) -> LookupResult diff --git a/matrix/services/sync/src/main/kotlin/app/dapk/st/matrix/sync/internal/sync/RoomEventFactory.kt b/matrix/services/sync/src/main/kotlin/app/dapk/st/matrix/sync/internal/sync/RoomEventFactory.kt index c8b1f10..dbfc70c 100644 --- a/matrix/services/sync/src/main/kotlin/app/dapk/st/matrix/sync/internal/sync/RoomEventFactory.kt +++ b/matrix/services/sync/src/main/kotlin/app/dapk/st/matrix/sync/internal/sync/RoomEventFactory.kt @@ -6,6 +6,7 @@ import app.dapk.st.matrix.sync.RoomEvent import app.dapk.st.matrix.sync.RoomMembersService import app.dapk.st.matrix.sync.find import app.dapk.st.matrix.sync.internal.request.ApiTimelineEvent +import app.dapk.st.matrix.sync.internal.sync.message.RichMessageParser private val UNKNOWN_AUTHOR = RoomMember(id = UserId("unknown"), displayName = null, avatarUrl = null) diff --git a/matrix/services/sync/src/main/kotlin/app/dapk/st/matrix/sync/internal/sync/message/HtmlParser.kt b/matrix/services/sync/src/main/kotlin/app/dapk/st/matrix/sync/internal/sync/message/HtmlParser.kt new file mode 100644 index 0000000..d855bb2 --- /dev/null +++ b/matrix/services/sync/src/main/kotlin/app/dapk/st/matrix/sync/internal/sync/message/HtmlParser.kt @@ -0,0 +1,118 @@ +package app.dapk.st.matrix.sync.internal.sync.message + +import app.dapk.st.matrix.common.UserId + +private const val TAG_OPEN = '<' +private const val TAG_CLOSE = '>' +private const val NO_RESULT_FOUND = -1 + +internal class HtmlParser { + + fun parseHtmlTags(input: String, searchIndex: Int, builder: PartBuilder) = input.findTag( + fromIndex = searchIndex, + onInvalidTag = { builder.appendText(input[it].toString()) }, + onTag = { tagOpen, tagClose -> + val wholeTag = input.substring(tagOpen, tagClose + 1) + val tagName = wholeTag.substring(1, wholeTag.indexOfFirst { it == '>' || it == ' ' }) + + when { + tagName.startsWith('@') -> { + appendTextBeforeTag(searchIndex, tagOpen, builder, input) + builder.appendPerson(UserId(tagName), tagName) + tagClose.next() + } + + tagName == "br" -> { + appendTextBeforeTag(searchIndex, tagOpen, builder, input) + builder.appendText("\n") + tagClose.next() + } + + else -> { + val exitTag = "" + val exitIndex = input.indexOf(exitTag, startIndex = tagClose) + val exitTagClose = exitIndex + exitTag.length + if (exitIndex == END_SEARCH) { + builder.appendText(input[searchIndex].toString()) + searchIndex.next() + } else { + when (tagName) { + "mx-reply" -> { + exitTagClose + } + + else -> { + appendTextBeforeTag(searchIndex, tagOpen, builder, input) + val tagContent = input.substring(tagClose + 1, exitIndex) + when (tagName) { + "a" -> { + val findHrefUrl = wholeTag.substringAfter("href=").replace("\"", "").removeSuffix(">") + if (findHrefUrl.startsWith("https://matrix.to/#/@")) { + val userId = UserId(findHrefUrl.substringAfter("https://matrix.to/#/").substringBeforeLast("\"")) + builder.appendPerson(userId, "@${tagContent.removePrefix("@")}") + if (input.getOrNull(exitTagClose) == ':') { + exitTagClose.next() + } else { + exitTagClose + } + } else { + builder.appendLink(findHrefUrl, label = tagContent) + exitTagClose + } + } + + "b" -> { + builder.appendBold(tagContent) + exitTagClose + } + + "strong" -> { + builder.appendBold(tagContent) + exitTagClose + } + + "i" -> { + builder.appendItalic(tagContent) + exitTagClose + } + + "em" -> { + builder.appendItalic(tagContent) + exitTagClose + } + + else -> { + builder.appendText(tagContent) + exitTagClose + } + } + } + } + } + } + } + } + ) + + private fun appendTextBeforeTag(searchIndex: Int, tagOpen: Int, builder: PartBuilder, input: String) { + if (searchIndex != tagOpen) { + builder.appendText(input.substring(searchIndex, tagOpen)) + } + } + + private fun String.findTag(fromIndex: Int, onInvalidTag: (Int) -> Unit, onTag: (Int, Int) -> Int): Int { + return when (val foundIndex = this.indexOf(TAG_OPEN, startIndex = fromIndex)) { + NO_RESULT_FOUND -> END_SEARCH + + else -> when (val closeIndex = indexOf(TAG_CLOSE, startIndex = foundIndex)) { + NO_RESULT_FOUND -> { + onInvalidTag(fromIndex) + fromIndex + 1 + } + + else -> onTag(foundIndex, closeIndex) + } + } + } + +} \ No newline at end of file diff --git a/matrix/services/sync/src/main/kotlin/app/dapk/st/matrix/sync/internal/sync/message/ParserScope.kt b/matrix/services/sync/src/main/kotlin/app/dapk/st/matrix/sync/internal/sync/message/ParserScope.kt new file mode 100644 index 0000000..8674f47 --- /dev/null +++ b/matrix/services/sync/src/main/kotlin/app/dapk/st/matrix/sync/internal/sync/message/ParserScope.kt @@ -0,0 +1,13 @@ +package app.dapk.st.matrix.sync.internal.sync.message + +internal typealias SearchIndex = Int + +internal fun Int.next() = this + 1 + + +internal interface ParserScope { + fun appendTextBeforeTag(searchIndex: Int, tagOpen: Int, builder: PartBuilder, input: String) + + fun SearchIndex.next(): SearchIndex + +} \ No newline at end of file diff --git a/matrix/services/sync/src/main/kotlin/app/dapk/st/matrix/sync/internal/sync/message/PartBuilder.kt b/matrix/services/sync/src/main/kotlin/app/dapk/st/matrix/sync/internal/sync/message/PartBuilder.kt new file mode 100644 index 0000000..db3c93b --- /dev/null +++ b/matrix/services/sync/src/main/kotlin/app/dapk/st/matrix/sync/internal/sync/message/PartBuilder.kt @@ -0,0 +1,56 @@ +package app.dapk.st.matrix.sync.internal.sync.message + +import app.dapk.st.matrix.common.RichText +import app.dapk.st.matrix.common.UserId + +internal class PartBuilder { + + private var normalBuffer = StringBuilder() + + private val parts = mutableSetOf() + + fun appendText(value: String) { + normalBuffer.append(value.cleanFirstTextLine()) + } + + fun appendItalic(value: String) { + flushNormalBuffer() + parts.add(RichText.Part.Italic(value.cleanFirstTextLine())) + } + + fun appendBold(value: String) { + flushNormalBuffer() + parts.add(RichText.Part.Bold(value.cleanFirstTextLine())) + } + + private fun String.cleanFirstTextLine() = if (parts.isEmpty() && normalBuffer.isEmpty()) this.trimStart() else this + + fun appendPerson(userId: UserId, displayName: String) { + flushNormalBuffer() + parts.add(RichText.Part.Person(userId, displayName)) + } + + fun appendLink(url: String, label: String?) { + flushNormalBuffer() + parts.add(RichText.Part.Link(url, label ?: url)) + } + + fun build(): Set { + flushNormalBuffer() + return parts + } + + private fun flushNormalBuffer() { + if (normalBuffer.isNotEmpty()) { + parts.add(RichText.Part.Normal(normalBuffer.toString())) + normalBuffer.clear() + } + } + +} + +internal fun PartBuilder.appendTextBeforeTag(previousIndex: Int, tagOpenIndex: Int, input: String) { + if (previousIndex != tagOpenIndex) { + this.appendText(input.substring(previousIndex, tagOpenIndex)) + } +} diff --git a/matrix/services/sync/src/main/kotlin/app/dapk/st/matrix/sync/internal/sync/message/RichMessageParser.kt b/matrix/services/sync/src/main/kotlin/app/dapk/st/matrix/sync/internal/sync/message/RichMessageParser.kt new file mode 100644 index 0000000..2d68b78 --- /dev/null +++ b/matrix/services/sync/src/main/kotlin/app/dapk/st/matrix/sync/internal/sync/message/RichMessageParser.kt @@ -0,0 +1,50 @@ +package app.dapk.st.matrix.sync.internal.sync.message + +import app.dapk.st.matrix.common.RichText +import kotlin.math.max + +internal const val END_SEARCH = -1 + +class RichMessageParser { + + private val htmlParser = HtmlParser() + private val urlParser = UrlParser() + + fun parse(source: String): RichText { + val input = source + .removeHtmlEntities() + .dropTextFallback() + val builder = PartBuilder() + var nextIndex = 0 + while (nextIndex != END_SEARCH) { + val htmlResult = htmlParser.parseHtmlTags(input, nextIndex, builder) + val linkStartIndex = findUrlStartIndex(htmlResult, nextIndex) + val urlResult = urlParser.parseUrl(input, linkStartIndex, builder) + + val hasReachedEnd = hasReachedEnd(htmlResult, urlResult, input) + if (hasReachedEnd && hasUnprocessedText(htmlResult, urlResult, input)) { + builder.appendText(input.substring(nextIndex)) + } + nextIndex = if (hasReachedEnd) END_SEARCH else max(htmlResult, urlResult) + } + return RichText(builder.build()) + } + + private fun hasUnprocessedText(htmlResult: Int, urlResult: Int, input: String) = htmlResult < input.length && urlResult < input.length + + private fun findUrlStartIndex(htmlResult: Int, searchIndex: Int) = when { + htmlResult == END_SEARCH && searchIndex == 0 -> 0 + htmlResult == END_SEARCH -> searchIndex + else -> htmlResult + } + + private fun hasReachedEnd(htmlResult: SearchIndex, urlResult: Int, input: String) = + (htmlResult == END_SEARCH && urlResult == END_SEARCH) || (htmlResult >= input.length || urlResult >= input.length) + +} + +private fun String.removeHtmlEntities() = this.replace(""", "\"").replace("'", "'") + +private fun String.dropTextFallback() = this.lines() + .dropWhile { it.startsWith("> ") || it.isEmpty() } + .joinToString(separator = "\n") diff --git a/matrix/services/sync/src/main/kotlin/app/dapk/st/matrix/sync/internal/sync/message/UrlParser.kt b/matrix/services/sync/src/main/kotlin/app/dapk/st/matrix/sync/internal/sync/message/UrlParser.kt new file mode 100644 index 0000000..a37869e --- /dev/null +++ b/matrix/services/sync/src/main/kotlin/app/dapk/st/matrix/sync/internal/sync/message/UrlParser.kt @@ -0,0 +1,47 @@ +package app.dapk.st.matrix.sync.internal.sync.message + +private const val INVALID_TRAILING_CHARS = ",.:;?" + +internal class UrlParser { + + fun parseUrl(input: String, linkStartIndex: Int, builder: PartBuilder): Int { + val urlIndex = input.indexOf("http", startIndex = linkStartIndex) + val urlResult = if (urlIndex == END_SEARCH) END_SEARCH else { + builder.appendTextBeforeTag(linkStartIndex, urlIndex, input) + + val originalUrl = input.substring(urlIndex) + val urlEndIndex = originalUrl.indexOfFirst { it == '\n' || it == ' ' } + val urlContinuesUntilEnd = urlEndIndex == -1 + + when { + urlContinuesUntilEnd -> { + val cleanedUrl = originalUrl.bestGuessStripTrailingUrlChar() + builder.appendLink(url = cleanedUrl, label = null) + if (cleanedUrl != originalUrl) { + builder.appendText(originalUrl.last().toString()) + } + input.length.next() + } + + else -> { + val originalUrl = input.substring(urlIndex, urlEndIndex) + val cleanedUrl = originalUrl.bestGuessStripTrailingUrlChar() + builder.appendLink(url = cleanedUrl, label = null) + if (originalUrl == cleanedUrl) urlEndIndex else urlEndIndex - 1 + } + } + } + return urlResult + } + +} + + +private fun String.bestGuessStripTrailingUrlChar(): String { + val last = this.last() + return if (INVALID_TRAILING_CHARS.contains(last)) { + this.dropLast(1) + } else { + this + } +} diff --git a/matrix/services/sync/src/test/kotlin/app/dapk/st/matrix/sync/internal/room/RoomEventsDecrypterTest.kt b/matrix/services/sync/src/test/kotlin/app/dapk/st/matrix/sync/internal/room/RoomEventsDecrypterTest.kt index 3aca409..dea7f06 100644 --- a/matrix/services/sync/src/test/kotlin/app/dapk/st/matrix/sync/internal/room/RoomEventsDecrypterTest.kt +++ b/matrix/services/sync/src/test/kotlin/app/dapk/st/matrix/sync/internal/room/RoomEventsDecrypterTest.kt @@ -5,7 +5,7 @@ import app.dapk.st.matrix.common.JsonString import app.dapk.st.matrix.common.RichText import app.dapk.st.matrix.sync.RoomEvent import app.dapk.st.matrix.sync.internal.request.DecryptedContent -import app.dapk.st.matrix.sync.internal.sync.RichMessageParser +import app.dapk.st.matrix.sync.internal.sync.message.RichMessageParser import fake.FakeMatrixLogger import fake.FakeMessageDecrypter import fixture.* diff --git a/matrix/services/sync/src/test/kotlin/app/dapk/st/matrix/sync/internal/sync/RichMessageParserTest.kt b/matrix/services/sync/src/test/kotlin/app/dapk/st/matrix/sync/internal/sync/RichMessageParserTest.kt index ac80b1f..3cf80f8 100644 --- a/matrix/services/sync/src/test/kotlin/app/dapk/st/matrix/sync/internal/sync/RichMessageParserTest.kt +++ b/matrix/services/sync/src/test/kotlin/app/dapk/st/matrix/sync/internal/sync/RichMessageParserTest.kt @@ -2,6 +2,7 @@ package app.dapk.st.matrix.sync.internal.sync import app.dapk.st.matrix.common.RichText import app.dapk.st.matrix.common.RichText.Part.* +import app.dapk.st.matrix.sync.internal.sync.message.RichMessageParser import fixture.aUserId import org.amshove.kluent.shouldBeEqualTo import org.junit.Ignore @@ -157,7 +158,7 @@ class RichMessageParserTest { expected = RichText( setOf( Normal("hello "), - RichText.Part.BoldItalic("wor"), + BoldItalic("wor"), Normal("ld"), ) ) diff --git a/matrix/services/sync/src/test/kotlin/app/dapk/st/matrix/sync/internal/sync/RoomEventCreatorTest.kt b/matrix/services/sync/src/test/kotlin/app/dapk/st/matrix/sync/internal/sync/RoomEventCreatorTest.kt index a2d5cc7..6f11704 100644 --- a/matrix/services/sync/src/test/kotlin/app/dapk/st/matrix/sync/internal/sync/RoomEventCreatorTest.kt +++ b/matrix/services/sync/src/test/kotlin/app/dapk/st/matrix/sync/internal/sync/RoomEventCreatorTest.kt @@ -6,6 +6,7 @@ import app.dapk.st.matrix.common.asString import app.dapk.st.matrix.sync.RoomEvent import app.dapk.st.matrix.sync.internal.request.ApiEncryptedContent import app.dapk.st.matrix.sync.internal.request.ApiTimelineEvent +import app.dapk.st.matrix.sync.internal.sync.message.RichMessageParser import fake.FakeErrorTracker import fake.FakeRoomMembersService import fixture.*