Browse Source

Parse Android message links with matching punctuation rules

master
evgeny 1 week ago
parent
commit
0a060d04ca
  1. 34
      tools/chatgui-android/app/src/main/java/com/utun/chat/data/MessageLinks.kt

34
tools/chatgui-android/app/src/main/java/com/utun/chat/data/MessageLinks.kt

@ -0,0 +1,34 @@
package com.utun.chat.data
import java.net.URI
/** Границы UTF-16 и полный адрес; разбор не меняет текст и не открывает ссылки. */
data class MessageLink(val start: Int, val end: Int, val url: String)
object MessageLinks {
private val pattern = Regex("utun://[A-Za-z0-9+/]+={0,2}|(?i:https?://)[^\\s\\p{Z}\\p{Cc}<>\"'`«»“”‘’]+")
/** Некорректные URL в пользовательском тексте остаются обычным текстом. */
fun isWebUrl(url: String): Boolean = try {
val uri = URI(url)
(uri.scheme.equals("http", true) || uri.scheme.equals("https", true)) &&
uri.toURL().let { it.host.isNotEmpty() && it.port in -1..65535 }
} catch (_: IllegalArgumentException) { false }
catch (_: java.net.URISyntaxException) { false }
catch (_: java.net.MalformedURLException) { false }
fun parse(text: String): List<MessageLink> = pattern.findAll(text).mapNotNull { match ->
var url = match.value
if (!url.startsWith("utun://")) {
while (url.isNotEmpty()) {
val last = url.last()
val closing = ")]}".indexOf(last)
val unmatched = closing >= 0 && url.count { it == last } > url.count { it == "([{"[closing] }
if (last !in ".,;:!?" && !unmatched) break
url = url.dropLast(1)
}
if (!isWebUrl(url)) return@mapNotNull null
}
MessageLink(match.range.first, match.range.first + url.length, url)
}.toList()
}
Loading…
Cancel
Save