1use anyhow::{Error, Result, bail};
8
9use crate::contact::ContactId;
10use crate::key::Fingerprint;
11use crate::qr::Qr;
12
13#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
17pub enum QrInvite {
18 Contact {
19 contact_id: ContactId,
20 fingerprint: Fingerprint,
21 invitenumber: String,
22 authcode: String,
23 #[serde(default)]
24 is_v3: bool,
25 },
26 Group {
27 contact_id: ContactId,
28 fingerprint: Fingerprint,
29 name: String,
30 grpid: String,
31 invitenumber: String,
32 authcode: String,
33 #[serde(default)]
34 is_v3: bool,
35 },
36 Broadcast {
37 contact_id: ContactId,
38 fingerprint: Fingerprint,
39 name: String,
40 grpid: String,
41 invitenumber: String,
42 authcode: String,
43 #[serde(default)]
44 is_v3: bool,
45 },
46}
47
48impl QrInvite {
49 pub fn contact_id(&self) -> ContactId {
54 match self {
55 Self::Contact { contact_id, .. }
56 | Self::Group { contact_id, .. }
57 | Self::Broadcast { contact_id, .. } => *contact_id,
58 }
59 }
60
61 pub fn fingerprint(&self) -> &Fingerprint {
63 match self {
64 Self::Contact { fingerprint, .. }
65 | Self::Group { fingerprint, .. }
66 | Self::Broadcast { fingerprint, .. } => fingerprint,
67 }
68 }
69
70 pub fn invitenumber(&self) -> &str {
72 match self {
73 Self::Contact { invitenumber, .. }
74 | Self::Group { invitenumber, .. }
75 | Self::Broadcast { invitenumber, .. } => invitenumber,
76 }
77 }
78
79 pub fn authcode(&self) -> &str {
81 match self {
82 Self::Contact { authcode, .. }
83 | Self::Group { authcode, .. }
84 | Self::Broadcast { authcode, .. } => authcode,
85 }
86 }
87
88 pub fn is_v3(&self) -> bool {
89 match *self {
90 QrInvite::Contact { is_v3, .. } => is_v3,
91 QrInvite::Group { is_v3, .. } => is_v3,
92 QrInvite::Broadcast { is_v3, .. } => is_v3,
93 }
94 }
95}
96
97impl TryFrom<Qr> for QrInvite {
98 type Error = Error;
99
100 fn try_from(qr: Qr) -> Result<Self> {
101 match qr {
102 Qr::AskVerifyContact {
103 contact_id,
104 fingerprint,
105 invitenumber,
106 authcode,
107 is_v3,
108 } => Ok(QrInvite::Contact {
109 contact_id,
110 fingerprint,
111 invitenumber,
112 authcode,
113 is_v3,
114 }),
115 Qr::AskVerifyGroup {
116 grpname,
117 grpid,
118 contact_id,
119 fingerprint,
120 invitenumber,
121 authcode,
122 is_v3,
123 } => Ok(QrInvite::Group {
124 contact_id,
125 fingerprint,
126 name: grpname,
127 grpid,
128 invitenumber,
129 authcode,
130 is_v3,
131 }),
132 Qr::AskJoinBroadcast {
133 name,
134 grpid,
135 contact_id,
136 fingerprint,
137 authcode,
138 invitenumber,
139 is_v3,
140 } => Ok(QrInvite::Broadcast {
141 name,
142 grpid,
143 contact_id,
144 fingerprint,
145 authcode,
146 invitenumber,
147 is_v3,
148 }),
149 _ => bail!("Unsupported QR type"),
150 }
151 }
152}
153
154impl rusqlite::types::ToSql for QrInvite {
155 fn to_sql(&self) -> rusqlite::Result<rusqlite::types::ToSqlOutput<'_>> {
156 let json = serde_json::to_string(self)
157 .map_err(|err| rusqlite::Error::ToSqlConversionFailure(Box::new(err)))?;
158 let val = rusqlite::types::Value::Text(json);
159 let out = rusqlite::types::ToSqlOutput::Owned(val);
160 Ok(out)
161 }
162}
163
164impl rusqlite::types::FromSql for QrInvite {
165 fn column_result(value: rusqlite::types::ValueRef<'_>) -> rusqlite::types::FromSqlResult<Self> {
166 String::column_result(value).and_then(|val| {
167 serde_json::from_str(&val)
168 .map_err(|err| rusqlite::types::FromSqlError::Other(Box::new(err)))
169 })
170 }
171}