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 #[serde(default)]
22 addrs: Vec<String>,
23 invitenumber: String,
24 authcode: String,
25 #[serde(default)]
26 is_v3: bool,
27 },
28 Group {
29 contact_id: ContactId,
30 fingerprint: Fingerprint,
31 #[serde(default)]
32 addrs: Vec<String>,
33 name: String,
34 grpid: String,
35 invitenumber: String,
36 authcode: String,
37 #[serde(default)]
38 is_v3: bool,
39 },
40 Broadcast {
41 contact_id: ContactId,
42 fingerprint: Fingerprint,
43 #[serde(default)]
44 addrs: Vec<String>,
45 name: String,
46 grpid: String,
47 invitenumber: String,
48 authcode: String,
49 #[serde(default)]
50 is_v3: bool,
51 },
52}
53
54impl QrInvite {
55 pub fn contact_id(&self) -> ContactId {
60 match self {
61 Self::Contact { contact_id, .. }
62 | Self::Group { contact_id, .. }
63 | Self::Broadcast { contact_id, .. } => *contact_id,
64 }
65 }
66
67 pub fn fingerprint(&self) -> &Fingerprint {
69 match self {
70 Self::Contact { fingerprint, .. }
71 | Self::Group { fingerprint, .. }
72 | Self::Broadcast { fingerprint, .. } => fingerprint,
73 }
74 }
75
76 pub fn invitenumber(&self) -> &str {
78 match self {
79 Self::Contact { invitenumber, .. }
80 | Self::Group { invitenumber, .. }
81 | Self::Broadcast { invitenumber, .. } => invitenumber,
82 }
83 }
84
85 pub fn authcode(&self) -> &str {
87 match self {
88 Self::Contact { authcode, .. }
89 | Self::Group { authcode, .. }
90 | Self::Broadcast { authcode, .. } => authcode,
91 }
92 }
93
94 pub fn is_v3(&self) -> bool {
95 match *self {
96 QrInvite::Contact { is_v3, .. } => is_v3,
97 QrInvite::Group { is_v3, .. } => is_v3,
98 QrInvite::Broadcast { is_v3, .. } => is_v3,
99 }
100 }
101
102 pub(crate) fn addrs(&self) -> &Vec<String> {
103 match self {
104 QrInvite::Contact { addrs, .. } => addrs,
105 QrInvite::Group { addrs, .. } => addrs,
106 QrInvite::Broadcast { addrs, .. } => addrs,
107 }
108 }
109}
110
111impl TryFrom<Qr> for QrInvite {
112 type Error = Error;
113
114 fn try_from(qr: Qr) -> Result<Self> {
115 match qr {
116 Qr::AskVerifyContact {
117 contact_id,
118 fingerprint,
119 addrs,
120 invitenumber,
121 authcode,
122 is_v3,
123 } => Ok(QrInvite::Contact {
124 contact_id,
125 fingerprint,
126 addrs,
127 invitenumber,
128 authcode,
129 is_v3,
130 }),
131 Qr::AskVerifyGroup {
132 grpname,
133 grpid,
134 contact_id,
135 fingerprint,
136 addrs,
137 invitenumber,
138 authcode,
139 is_v3,
140 } => Ok(QrInvite::Group {
141 contact_id,
142 fingerprint,
143 addrs,
144 name: grpname,
145 grpid,
146 invitenumber,
147 authcode,
148 is_v3,
149 }),
150 Qr::AskJoinBroadcast {
151 name,
152 grpid,
153 contact_id,
154 fingerprint,
155 addrs,
156 authcode,
157 invitenumber,
158 is_v3,
159 } => Ok(QrInvite::Broadcast {
160 name,
161 grpid,
162 contact_id,
163 fingerprint,
164 addrs,
165 authcode,
166 invitenumber,
167 is_v3,
168 }),
169 _ => bail!("Unsupported QR type"),
170 }
171 }
172}
173
174impl rusqlite::types::ToSql for QrInvite {
175 fn to_sql(&self) -> rusqlite::Result<rusqlite::types::ToSqlOutput<'_>> {
176 let json = serde_json::to_string(self)
177 .map_err(|err| rusqlite::Error::ToSqlConversionFailure(Box::new(err)))?;
178 let val = rusqlite::types::Value::Text(json);
179 let out = rusqlite::types::ToSqlOutput::Owned(val);
180 Ok(out)
181 }
182}
183
184impl rusqlite::types::FromSql for QrInvite {
185 fn column_result(value: rusqlite::types::ValueRef<'_>) -> rusqlite::types::FromSqlResult<Self> {
186 String::column_result(value).and_then(|val| {
187 serde_json::from_str(&val)
188 .map_err(|err| rusqlite::types::FromSqlError::Other(Box::new(err)))
189 })
190 }
191}