Skip to main content

xmtp_db/encrypted_store/group_message/
convert.rs

1use super::*;
2use xmtp_proto::ConversionError;
3use xmtp_proto::xmtp::device_sync::message_backup::{
4    ContentTypeSave, DeliveryStatusSave, GroupMessageKindSave, GroupMessageSave,
5};
6
7impl TryFrom<GroupMessageSave> for StoredGroupMessage {
8    type Error = ConversionError;
9    fn try_from(value: GroupMessageSave) -> Result<Self, Self::Error> {
10        let kind = value.kind().try_into()?;
11        let delivery_status = value.delivery_status().try_into()?;
12
13        let mut content_type: ContentType = value.content_type_save().into();
14        if matches!(content_type, ContentType::Unknown) {
15            content_type = value.content_type.into();
16        }
17
18        Ok(Self {
19            id: value.id,
20            group_id: value.group_id.try_into()?,
21            decrypted_message_bytes: value.decrypted_message_bytes,
22            sent_at_ns: value.sent_at_ns,
23            kind,
24            sender_installation_id: value.sender_installation_id,
25            sender_inbox_id: value.sender_inbox_id,
26            delivery_status,
27            content_type,
28            version_major: value.version_major,
29            version_minor: value.version_minor,
30            authority_id: value.authority_id,
31            reference_id: value.reference_id,
32            sequence_id: value.sequence_id.unwrap_or(0),
33            envelope_hash: None,
34            expiry_ns: None,
35            expire_at_ns: None,
36            inserted_at_ns: 0,  // Will be set by database
37            should_push: false, // Default to false for synced messages
38            // GroupMessageSave does not carry the idempotency key; fall back to
39            // the historical default (the send timestamp). Restored messages are
40            // already published, so this value is only informational.
41            idempotency_key: value.sent_at_ns.to_string(),
42        })
43    }
44}
45
46impl TryFrom<GroupMessageKindSave> for GroupMessageKind {
47    type Error = ConversionError;
48    fn try_from(value: GroupMessageKindSave) -> Result<Self, Self::Error> {
49        let message_kind = match value {
50            GroupMessageKindSave::Application => Self::Application,
51            GroupMessageKindSave::MembershipChange => Self::MembershipChange,
52            GroupMessageKindSave::Unspecified => {
53                return Err(ConversionError::Unspecified("message_kind"));
54            }
55        };
56        Ok(message_kind)
57    }
58}
59
60impl TryFrom<DeliveryStatusSave> for DeliveryStatus {
61    type Error = ConversionError;
62    fn try_from(value: DeliveryStatusSave) -> Result<Self, Self::Error> {
63        let delivery_status = match value {
64            DeliveryStatusSave::Failed => Self::Failed,
65            DeliveryStatusSave::Published => Self::Published,
66            DeliveryStatusSave::Unpublished => Self::Unpublished,
67            DeliveryStatusSave::Unspecified => {
68                return Err(ConversionError::Unspecified("delivery_status"));
69            }
70        };
71        Ok(delivery_status)
72    }
73}
74
75impl From<ContentTypeSave> for ContentType {
76    fn from(value: ContentTypeSave) -> Self {
77        match value {
78            ContentTypeSave::Attachment => Self::Attachment,
79            ContentTypeSave::GroupMembershipChange => Self::GroupMembershipChange,
80            ContentTypeSave::GroupUpdated => Self::GroupUpdated,
81            ContentTypeSave::Reaction => Self::Reaction,
82            ContentTypeSave::ReadReceipt => Self::ReadReceipt,
83            ContentTypeSave::RemoteAttachment => Self::RemoteAttachment,
84            ContentTypeSave::Reply => Self::Reply,
85            ContentTypeSave::Text => Self::Text,
86            ContentTypeSave::TransactionReference => Self::TransactionReference,
87            _ => Self::Unknown,
88        }
89    }
90}
91
92impl From<StoredGroupMessage> for GroupMessageSave {
93    fn from(value: StoredGroupMessage) -> Self {
94        let kind: GroupMessageKindSave = value.kind.into();
95        let delivery_status: DeliveryStatusSave = value.delivery_status.into();
96
97        Self {
98            id: value.id,
99            group_id: value.group_id.into(),
100            decrypted_message_bytes: value.decrypted_message_bytes,
101            sent_at_ns: value.sent_at_ns,
102            kind: kind as i32,
103            sender_installation_id: value.sender_installation_id,
104            sender_inbox_id: value.sender_inbox_id,
105            delivery_status: delivery_status as i32,
106            content_type: value.content_type.to_string(),
107            version_major: value.version_major,
108            version_minor: value.version_minor,
109            authority_id: value.authority_id,
110            reference_id: value.reference_id,
111            sequence_id: Some(value.sequence_id),
112
113            // Deprecated
114            #[allow(deprecated)]
115            content_type_save: 0,
116            ..Default::default()
117        }
118    }
119}
120impl From<GroupMessageKind> for GroupMessageKindSave {
121    fn from(value: GroupMessageKind) -> Self {
122        match value {
123            GroupMessageKind::Application => Self::Application,
124            GroupMessageKind::MembershipChange => Self::MembershipChange,
125        }
126    }
127}
128impl From<DeliveryStatus> for DeliveryStatusSave {
129    fn from(value: DeliveryStatus) -> Self {
130        match value {
131            DeliveryStatus::Failed => Self::Failed,
132            DeliveryStatus::Published => Self::Published,
133            DeliveryStatus::Unpublished => Self::Unpublished,
134        }
135    }
136}