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
|
||||
|
||||
import chat.revolt.api.RevoltAPI
|
||||
import chat.revolt.api.schemas.ChannelType
|
||||
import chat.revolt.internals.EmojiImpl
|
||||
|
||||
object MessageProcessor {
|
||||
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()
|
||||
|
||||
return mentions.fold(content) { acc, mention ->
|
||||
var returnable = mentions.fold(content) { acc, mention ->
|
||||
val (username, discriminator) = MentionRegex.matchEntire(mention)?.destructured
|
||||
?: return@fold acc
|
||||
|
||||
|
|
@ -18,5 +30,34 @@ object MessageProcessor {
|
|||
val userId = user?.id ?: return@fold acc
|
||||
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
|
||||
}
|
||||
|
||||
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 {
|
||||
metadata = initMetadata(RevoltApplication.instance.applicationContext)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -212,7 +212,10 @@ class ChannelScreenViewModel : ViewModel() {
|
|||
|
||||
sendMessage(
|
||||
activeChannel!!.id!!,
|
||||
MessageProcessor.processOutgoing(pendingMessageContent.trimIndent()),
|
||||
MessageProcessor.processOutgoing(
|
||||
pendingMessageContent.trimIndent(),
|
||||
activeChannel?.server
|
||||
),
|
||||
attachments = if (attachmentIds.isEmpty()) null else attachmentIds,
|
||||
replies = pendingReplies
|
||||
)
|
||||
|
|
|
|||
Loading…
Reference in New Issue