jmap_chat_client/methods/
chat.rs1use jmap_types::{Id, PatchObject, State};
12
13use super::{
14 AddMemberInput, ChangesResponse, ChatCreateInput, ChatPatch, ChatQueryInput, GetResponse,
15 QueryChangesResponse, QueryResponse, SetResponse, TypingResponse, UpdateMemberRoleInput,
16};
17
18impl super::SessionClient {
19 pub async fn chat_get(
24 &self,
25 ids: Option<&[Id]>,
26 properties: Option<&[&str]>,
27 ) -> Result<GetResponse<jmap_chat_types::Chat>, jmap_base_client::ClientError> {
28 let (api_url, account_id) = self.session_parts()?;
29 let mut args = serde_json::json!({ "accountId": account_id });
36 if let Some(id_slice) = ids {
37 args["ids"] = serde_json::to_value(id_slice).expect("Id slice Serialize is infallible");
38 }
39 if let Some(props) = properties {
40 args["properties"] = serde_json::Value::Array(
41 props.iter().copied().map(serde_json::Value::from).collect(),
42 );
43 }
44 let req = super::build_request("Chat/get", args, super::USING_CHAT);
45 let resp = self.call_internal(api_url, &req).await?;
46 jmap_base_client::extract_response(&resp, super::CALL_ID)
47 }
48
49 pub async fn chat_query(
54 &self,
55 input: &ChatQueryInput,
56 ) -> Result<QueryResponse, jmap_base_client::ClientError> {
57 let (api_url, account_id) = self.session_parts()?;
58 let mut filter = serde_json::Map::new();
59 if let Some(ref k) = input.filter_kind {
60 let kind_str = serde_json::to_value(k).map_err(jmap_base_client::ClientError::Parse)?;
61 filter.insert("kind".into(), kind_str);
62 }
63 if let Some(m) = input.filter_muted {
64 filter.insert("muted".into(), m.into());
65 }
66 let filter_val = if filter.is_empty() {
67 serde_json::Value::Null
68 } else {
69 serde_json::Value::Object(filter)
70 };
71 let mut args = serde_json::json!({
72 "accountId": account_id,
73 "filter": filter_val,
74 });
75 if let Some(p) = input.position {
76 args["position"] = p.into();
77 }
78 if let Some(l) = input.limit {
79 args["limit"] = l.into();
80 }
81 let req = super::build_request("Chat/query", args, super::USING_CHAT);
82 let resp = self.call_internal(api_url, &req).await?;
83 jmap_base_client::extract_response(&resp, super::CALL_ID)
84 }
85
86 pub async fn chat_changes(
91 &self,
92 since_state: &State,
93 max_changes: Option<u64>,
94 ) -> Result<ChangesResponse, jmap_base_client::ClientError> {
95 if since_state.as_ref().is_empty() {
100 return Err(jmap_base_client::ClientError::InvalidArgument(
101 "chat_changes: since_state may not be empty".into(),
102 ));
103 }
104 let (api_url, account_id) = self.session_parts()?;
105 let mut args = serde_json::json!({
106 "accountId": account_id,
107 "sinceState": since_state,
108 });
109 if let Some(mc) = max_changes {
110 args["maxChanges"] = mc.into();
111 }
112 let req = super::build_request("Chat/changes", args, super::USING_CHAT);
113 let resp = self.call_internal(api_url, &req).await?;
114 jmap_base_client::extract_response(&resp, super::CALL_ID)
115 }
116
117 pub async fn chat_typing(
127 &self,
128 chat_id: &Id,
129 typing: bool,
130 ) -> Result<TypingResponse, jmap_base_client::ClientError> {
131 let (api_url, account_id) = self.session_parts()?;
132 let args = serde_json::json!({
133 "accountId": account_id,
134 "chatId": chat_id,
135 "typing": typing,
136 });
137 let req = super::build_request("Chat/typing", args, super::USING_CHAT);
138 let resp = self.call_internal(api_url, &req).await?;
139 jmap_base_client::extract_response(&resp, super::CALL_ID)
140 }
141
142 pub async fn chat_query_changes(
148 &self,
149 since_query_state: &State,
150 max_changes: Option<u64>,
151 ) -> Result<QueryChangesResponse, jmap_base_client::ClientError> {
152 if since_query_state.as_ref().is_empty() {
154 return Err(jmap_base_client::ClientError::InvalidArgument(
155 "chat_query_changes: since_query_state may not be empty".into(),
156 ));
157 }
158 let (api_url, account_id) = self.session_parts()?;
159 let mut args = serde_json::json!({
160 "accountId": account_id,
161 "sinceQueryState": since_query_state,
162 });
163 if let Some(mc) = max_changes {
164 args["maxChanges"] = mc.into();
165 }
166 let req = super::build_request("Chat/queryChanges", args, super::USING_CHAT);
167 let resp = self.call_internal(api_url, &req).await?;
168 jmap_base_client::extract_response(&resp, super::CALL_ID)
169 }
170
171 pub async fn chat_create(
181 &self,
182 input: &ChatCreateInput<'_>,
183 ) -> Result<SetResponse, jmap_base_client::ClientError> {
184 let (api_url, account_id) = self.session_parts()?;
185 let create_obj;
186 let client_id_opt = match input {
187 ChatCreateInput::Direct {
188 client_id,
189 contact_id,
190 } => {
191 create_obj = serde_json::json!({
192 "kind": "direct",
193 "contactId": contact_id,
194 });
195 *client_id
196 }
197 ChatCreateInput::Group {
198 client_id,
199 name,
200 member_ids,
201 description,
202 avatar_blob_id,
203 message_expiry_seconds,
204 } => {
205 if name.is_empty() {
206 return Err(jmap_base_client::ClientError::InvalidArgument(
207 "chat_create: name may not be empty".into(),
208 ));
209 }
210 let mut obj = serde_json::json!({
211 "kind": "group",
212 "name": name,
213 "memberIds": member_ids,
214 });
215 if let Some(d) = description {
216 obj["description"] = (*d).into();
217 }
218 if let Some(b) = avatar_blob_id {
219 obj["avatarBlobId"] = b.as_ref().into();
220 }
221 if let Some(s) = message_expiry_seconds {
222 obj["messageExpirySeconds"] = (*s).into();
223 }
224 create_obj = obj;
225 *client_id
226 }
227 ChatCreateInput::Channel {
228 client_id,
229 space_id,
230 name,
231 description,
232 } => {
233 if name.is_empty() {
234 return Err(jmap_base_client::ClientError::InvalidArgument(
235 "chat_create: name may not be empty".into(),
236 ));
237 }
238 let mut obj = serde_json::json!({
239 "kind": "channel",
240 "spaceId": space_id,
241 "name": name,
242 });
243 if let Some(d) = description {
244 obj["description"] = (*d).into();
245 }
246 create_obj = obj;
247 *client_id
248 }
249 };
250 let client_id = super::resolve_client_id(client_id_opt);
251 let args = serde_json::json!({
252 "accountId": account_id,
253 "create": { client_id: create_obj },
254 });
255 let req = super::build_request("Chat/set", args, super::USING_CHAT);
256 let resp = self.call_internal(api_url, &req).await?;
257 jmap_base_client::extract_response(&resp, super::CALL_ID)
258 }
259
260 pub async fn chat_update(
271 &self,
272 id: &Id,
273 patch: &ChatPatch<'_>,
274 ) -> Result<SetResponse, jmap_base_client::ClientError> {
275 let (api_url, account_id) = self.session_parts()?;
276 let mut patch_map = serde_json::Map::new();
277
278 if let Some(m) = patch.muted {
279 patch_map.insert("muted".into(), m.into());
280 }
281 if let Some(entry) = patch
282 .mute_until
283 .map_entry()
284 .map_err(jmap_base_client::ClientError::Parse)?
285 {
286 patch_map.insert("muteUntil".into(), entry);
287 }
288 if let Some(rti) = patch.receive_typing_indicators {
289 patch_map.insert("receiveTypingIndicators".into(), rti.into());
290 }
291 if let Some(ids) = patch.pinned_message_ids {
292 patch_map.insert(
293 "pinnedMessageIds".into(),
294 serde_json::to_value(ids).expect("Id slice Serialize is infallible"),
295 );
296 }
297 if let Some(s) = patch.message_expiry_seconds {
298 patch_map.insert("messageExpirySeconds".into(), s.into());
299 }
300 if let Some(rs) = patch.receipt_sharing {
301 patch_map.insert("receiptSharing".into(), rs.into());
302 }
303 if let Some(n) = patch.name {
304 patch_map.insert("name".into(), n.into());
305 }
306 if let Some(entry) = patch
307 .description
308 .map_entry()
309 .map_err(jmap_base_client::ClientError::Parse)?
310 {
311 patch_map.insert("description".into(), entry);
312 }
313 if let Some(entry) = patch
314 .avatar_blob_id
315 .map_entry()
316 .map_err(jmap_base_client::ClientError::Parse)?
317 {
318 patch_map.insert("avatarBlobId".into(), entry);
319 }
320 if let Some(members) = patch.add_members {
321 if !members.is_empty() {
322 let arr = members
323 .iter()
324 .map(|m: &AddMemberInput<'_>| {
325 let mut obj = serde_json::json!({ "id": m.id });
326 if let Some(ref role) = m.role {
327 obj["role"] = serde_json::to_value(role)
328 .map_err(jmap_base_client::ClientError::Parse)?;
329 }
330 Ok(obj)
331 })
332 .collect::<Result<Vec<_>, jmap_base_client::ClientError>>()?;
333 patch_map.insert("addMembers".into(), serde_json::Value::Array(arr));
334 }
335 }
336 if let Some(rm) = patch.remove_members {
337 if !rm.is_empty() {
338 patch_map.insert(
339 "removeMembers".into(),
340 serde_json::to_value(rm).expect("Id slice Serialize is infallible"),
341 );
342 }
343 }
344 if let Some(umr) = patch.update_member_roles {
345 if !umr.is_empty() {
346 let arr = umr
347 .iter()
348 .map(|u: &UpdateMemberRoleInput<'_>| {
349 Ok(serde_json::json!({
350 "id": u.id,
351 "role": serde_json::to_value(&u.role)
352 .map_err(jmap_base_client::ClientError::Parse)?,
353 }))
354 })
355 .collect::<Result<Vec<_>, jmap_base_client::ClientError>>()?;
356 patch_map.insert("updateMemberRoles".into(), serde_json::Value::Array(arr));
357 }
358 }
359
360 let patch_value = serde_json::Value::Object(PatchObject::from_map(patch_map).into_inner());
365 let args = serde_json::json!({
366 "accountId": account_id,
367 "update": { id.as_ref(): patch_value },
368 });
369 let req = super::build_request("Chat/set", args, super::USING_CHAT);
370 let resp = self.call_internal(api_url, &req).await?;
371 jmap_base_client::extract_response(&resp, super::CALL_ID)
372 }
373
374 pub async fn chat_destroy(
379 &self,
380 ids: &[Id],
381 ) -> Result<SetResponse, jmap_base_client::ClientError> {
382 if ids.is_empty() {
383 return Err(jmap_base_client::ClientError::InvalidArgument(
384 "chat_destroy: ids may not be empty".into(),
385 ));
386 }
387 let (api_url, account_id) = self.session_parts()?;
388 let args = serde_json::json!({
389 "accountId": account_id,
390 "destroy": ids,
391 });
392 let req = super::build_request("Chat/set", args, super::USING_CHAT);
393 let resp = self.call_internal(api_url, &req).await?;
394 jmap_base_client::extract_response(&resp, super::CALL_ID)
395 }
396}