feat: process manual channel mentions and emoji shortcodes
Signed-off-by: Infi <infi@infi.sh>
This commit is contained in:
parent
8a935862b0
commit
ac31be2a49
|
|
@ -1,14 +1,26 @@
|
||||||
package chat.revolt.api.internals
|
package chat.revolt.api.internals
|
||||||
|
|
||||||
import chat.revolt.api.RevoltAPI
|
import chat.revolt.api.RevoltAPI
|
||||||
|
import chat.revolt.api.schemas.ChannelType
|
||||||
|
import chat.revolt.internals.EmojiImpl
|
||||||
|
|
||||||
object MessageProcessor {
|
object MessageProcessor {
|
||||||
private val MentionRegex = Regex("@((?:\\p{L}|[\\d_.-])+)#([0-9]{4})", RegexOption.IGNORE_CASE)
|
private val MentionRegex = Regex("@((?:\\p{L}|[\\d_.-])+)#([0-9]{4})", RegexOption.IGNORE_CASE)
|
||||||
|
private val ChannelRegex = Regex("(?:\\s|^)#(.+?)(?:\\s|\$)", RegexOption.IGNORE_CASE)
|
||||||
|
private val EmojiRegex = Regex(":(.+?):", RegexOption.IGNORE_CASE)
|
||||||
|
|
||||||
fun processOutgoing(content: String): String {
|
private val emojiMetadata = EmojiImpl()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Processes an outgoing message for sending.
|
||||||
|
* 1. Replaces @mentions#0000 with <@userId>
|
||||||
|
* 2. Replaces #channel with <#channelId> if the current server has a channel with that name
|
||||||
|
* 2. Replaces :emoji-shortcode: with the emoji's unicode character, if it exists
|
||||||
|
*/
|
||||||
|
fun processOutgoing(content: String, serverId: String?): String {
|
||||||
val mentions = MentionRegex.findAll(content).map { it.value }.toList()
|
val mentions = MentionRegex.findAll(content).map { it.value }.toList()
|
||||||
|
|
||||||
return mentions.fold(content) { acc, mention ->
|
var returnable = mentions.fold(content) { acc, mention ->
|
||||||
val (username, discriminator) = MentionRegex.matchEntire(mention)?.destructured
|
val (username, discriminator) = MentionRegex.matchEntire(mention)?.destructured
|
||||||
?: return@fold acc
|
?: return@fold acc
|
||||||
|
|
||||||
|
|
@ -18,5 +30,34 @@ object MessageProcessor {
|
||||||
val userId = user?.id ?: return@fold acc
|
val userId = user?.id ?: return@fold acc
|
||||||
acc.replace(mention, "<@$userId>")
|
acc.replace(mention, "<@$userId>")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val channels = ChannelRegex.findAll(returnable).map { it.value }.toList()
|
||||||
|
|
||||||
|
returnable = channels.fold(returnable) { acc, channel ->
|
||||||
|
val channelName = ChannelRegex.matchEntire(channel)?.destructured?.component1()
|
||||||
|
?: return@fold acc
|
||||||
|
|
||||||
|
val fetchedChannel =
|
||||||
|
RevoltAPI.channelCache.values.find {
|
||||||
|
it.name == channelName && it.server == serverId && it.channelType == ChannelType.TextChannel
|
||||||
|
}
|
||||||
|
?: return@fold acc
|
||||||
|
|
||||||
|
fetchedChannel.name?.let { acc.replace("#${it}", "<#${fetchedChannel.id}>") } ?: acc
|
||||||
|
}
|
||||||
|
|
||||||
|
val emojis = EmojiRegex.findAll(returnable).map { it.value }.toList()
|
||||||
|
|
||||||
|
returnable = emojis.fold(returnable) { acc, emoji ->
|
||||||
|
val emojiName = EmojiRegex.matchEntire(emoji)?.destructured?.component1()
|
||||||
|
?: return@fold acc
|
||||||
|
|
||||||
|
val byShortcode = emojiMetadata.unicodeByShortcode(emojiName)
|
||||||
|
?: return@fold acc
|
||||||
|
|
||||||
|
acc.replace(":$emojiName:", byShortcode)
|
||||||
|
}
|
||||||
|
|
||||||
|
return returnable
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -247,6 +247,18 @@ class EmojiImpl {
|
||||||
return list
|
return list
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun unicodeByShortcode(shortcode: String): String? {
|
||||||
|
return metadata.asSequence().mapNotNull { group ->
|
||||||
|
group.emoji.find { emoji ->
|
||||||
|
emoji.shortcodes.any { code ->
|
||||||
|
code == ":${shortcode}:"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}.firstOrNull().let { emoji ->
|
||||||
|
emoji?.base?.joinToString("") { String(Character.toChars(it.toInt())) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
init {
|
init {
|
||||||
metadata = initMetadata(RevoltApplication.instance.applicationContext)
|
metadata = initMetadata(RevoltApplication.instance.applicationContext)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -212,7 +212,10 @@ class ChannelScreenViewModel : ViewModel() {
|
||||||
|
|
||||||
sendMessage(
|
sendMessage(
|
||||||
activeChannel!!.id!!,
|
activeChannel!!.id!!,
|
||||||
MessageProcessor.processOutgoing(pendingMessageContent.trimIndent()),
|
MessageProcessor.processOutgoing(
|
||||||
|
pendingMessageContent.trimIndent(),
|
||||||
|
activeChannel?.server
|
||||||
|
),
|
||||||
attachments = if (attachmentIds.isEmpty()) null else attachmentIds,
|
attachments = if (attachmentIds.isEmpty()) null else attachmentIds,
|
||||||
replies = pendingReplies
|
replies = pendingReplies
|
||||||
)
|
)
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue