From dfe5a4464b7ae129d355d0f09333266ccc308520 Mon Sep 17 00:00:00 2001 From: Evgeny Date: Fri, 14 Feb 2025 23:37:06 +0000 Subject: [PATCH] desktop, android: fix parser for reactions (#5629) * desktop, android: fix parser for reactions * core: restrict API to known reactions --- apps/ios/SimpleXChat/ChatTypes.swift | 8 ++++++-- .../kotlin/chat/simplex/common/model/ChatModel.kt | 11 ++++++++--- src/Simplex/Chat.hs | 4 ++-- src/Simplex/Chat/Protocol.hs | 7 +++++++ 4 files changed, 23 insertions(+), 7 deletions(-) diff --git a/apps/ios/SimpleXChat/ChatTypes.swift b/apps/ios/SimpleXChat/ChatTypes.swift index f64a1076a5..01ea2f48af 100644 --- a/apps/ios/SimpleXChat/ChatTypes.swift +++ b/apps/ios/SimpleXChat/ChatTypes.swift @@ -3391,8 +3391,12 @@ extension MsgReaction: Decodable { let type = try container.decode(String.self, forKey: CodingKeys.type) switch type { case "emoji": - let emoji = try container.decode(MREmojiChar.self, forKey: CodingKeys.emoji) - self = .emoji(emoji: emoji) + do { + let emoji = try container.decode(MREmojiChar.self, forKey: CodingKeys.emoji) + self = .emoji(emoji: emoji) + } catch { + self = .unknown(type: "emoji") + } default: self = .unknown(type: type) } diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/model/ChatModel.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/model/ChatModel.kt index d051fc3a53..fcd2c83d60 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/model/ChatModel.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/model/ChatModel.kt @@ -2981,7 +2981,7 @@ sealed class MsgReaction { MREmojiChar.Heart -> "❤️" else -> emoji.value } - is Unknown -> "" + is Unknown -> "?" } companion object { @@ -3003,8 +3003,13 @@ object MsgReactionSerializer : KSerializer { return if (json is JsonObject && "type" in json) { when(val t = json["type"]?.jsonPrimitive?.content ?: "") { "emoji" -> { - val emoji = Json.decodeFromString(json["emoji"].toString()) - if (emoji == null) MsgReaction.Unknown(t, json) else MsgReaction.Emoji(emoji) + val msgReaction = try { + val emoji = Json.decodeFromString(json["emoji"].toString()) + MsgReaction.Emoji(emoji) + } catch (e: Throwable) { + MsgReaction.Unknown(t, json) + } + msgReaction } else -> MsgReaction.Unknown(t, json) } diff --git a/src/Simplex/Chat.hs b/src/Simplex/Chat.hs index e09ed71e57..4b217e57f8 100644 --- a/src/Simplex/Chat.hs +++ b/src/Simplex/Chat.hs @@ -8463,8 +8463,8 @@ chatCommandP = "/_update item " *> (APIUpdateChatItem <$> chatRefP <* A.space <*> A.decimal <*> liveMessageP <* A.space <*> msgContentP), "/_delete item " *> (APIDeleteChatItem <$> chatRefP <*> _strP <*> _strP), "/_delete member item #" *> (APIDeleteMemberChatItem <$> A.decimal <*> _strP), - "/_reaction " *> (APIChatItemReaction <$> chatRefP <* A.space <*> A.decimal <* A.space <*> onOffP <* A.space <*> jsonP), - "/_reaction members " *> (APIGetReactionMembers <$> A.decimal <* " #" <*> A.decimal <* A.space <*> A.decimal <* A.space <*> jsonP), + "/_reaction " *> (APIChatItemReaction <$> chatRefP <* A.space <*> A.decimal <* A.space <*> onOffP <* A.space <*> (knownReaction <$?> jsonP)), + "/_reaction members " *> (APIGetReactionMembers <$> A.decimal <* " #" <*> A.decimal <* A.space <*> A.decimal <* A.space <*> (knownReaction <$?> jsonP)), "/_forward plan " *> (APIPlanForwardChatItems <$> chatRefP <*> _strP), "/_forward " *> (APIForwardChatItems <$> chatRefP <* A.space <*> chatRefP <*> _strP <*> sendMessageTTLP), "/_read user " *> (APIUserRead <$> A.decimal), diff --git a/src/Simplex/Chat/Protocol.hs b/src/Simplex/Chat/Protocol.hs index bc6b083964..bfe1c8f02c 100644 --- a/src/Simplex/Chat/Protocol.hs +++ b/src/Simplex/Chat/Protocol.hs @@ -407,6 +407,13 @@ data MsgReaction = MREmoji {emoji :: MREmojiChar} | MRUnknown {tag :: Text, json emojiTag :: IsString a => a emojiTag = "emoji" +knownReaction :: MsgReaction -> Either String MsgReaction +knownReaction = \case + r@MREmoji {} -> Right r + MRUnknown {} -> Left "unknown MsgReaction" + +-- parseJSON for MsgReaction parses unknown emoji reactions as MRUnknown with type "emoji", +-- allowing to add new emojis in a backwards compatible way - UI shows them as ? instance FromJSON MsgReaction where parseJSON (J.Object v) = do tag <- v .: "type"