jmap_chat_client/methods/
space.rs1use jmap_types::{Id, PatchObject, State};
12
13use super::{
14 ChangesResponse, GetResponse, QueryChangesResponse, QueryResponse, SetResponse,
15 SpaceAddCategoryInput, SpaceAddChannelInput, SpaceAddMemberInput, SpaceAddRoleInput,
16 SpaceCreateInput, SpaceJoinInput, SpaceJoinResponse, SpacePatch, SpaceQueryInput,
17 SpaceUpdateCategoryInput, SpaceUpdateChannelInput, SpaceUpdateMemberInput,
18 SpaceUpdateRoleInput,
19};
20
21impl super::SessionClient {
22 pub async fn space_get(
27 &self,
28 ids: Option<&[Id]>,
29 properties: Option<&[&str]>,
30 ) -> Result<GetResponse<jmap_chat_types::Space>, jmap_base_client::ClientError> {
31 let (api_url, account_id) = self.session_parts()?;
32 let mut args = serde_json::json!({ "accountId": account_id });
35 if let Some(id_slice) = ids {
36 args["ids"] = serde_json::to_value(id_slice).expect("Id slice Serialize is infallible");
37 }
38 if let Some(props) = properties {
39 args["properties"] = serde_json::Value::Array(
40 props.iter().copied().map(serde_json::Value::from).collect(),
41 );
42 }
43 let req = super::build_request("Space/get", args, super::USING_CHAT);
44 let resp = self.call_internal(api_url, &req).await?;
45 jmap_base_client::extract_response(&resp, super::CALL_ID)
46 }
47
48 pub async fn space_changes(
53 &self,
54 since_state: &State,
55 max_changes: Option<u64>,
56 ) -> Result<ChangesResponse, jmap_base_client::ClientError> {
57 if since_state.as_ref().is_empty() {
59 return Err(jmap_base_client::ClientError::InvalidArgument(
60 "space_changes: since_state may not be empty".into(),
61 ));
62 }
63 let (api_url, account_id) = self.session_parts()?;
64 let mut args = serde_json::json!({
65 "accountId": account_id,
66 "sinceState": since_state,
67 });
68 if let Some(mc) = max_changes {
69 args["maxChanges"] = mc.into();
70 }
71 let req = super::build_request("Space/changes", args, super::USING_CHAT);
72 let resp = self.call_internal(api_url, &req).await?;
73 jmap_base_client::extract_response(&resp, super::CALL_ID)
74 }
75
76 pub async fn space_destroy(
81 &self,
82 ids: &[Id],
83 ) -> Result<SetResponse, jmap_base_client::ClientError> {
84 if ids.is_empty() {
85 return Err(jmap_base_client::ClientError::InvalidArgument(
86 "space_destroy: ids may not be empty".into(),
87 ));
88 }
89 let (api_url, account_id) = self.session_parts()?;
90 let args = serde_json::json!({
91 "accountId": account_id,
92 "destroy": ids,
93 });
94 let req = super::build_request("Space/set", args, super::USING_CHAT);
95 let resp = self.call_internal(api_url, &req).await?;
96 jmap_base_client::extract_response(&resp, super::CALL_ID)
97 }
98
99 pub async fn space_query(
104 &self,
105 input: &SpaceQueryInput<'_>,
106 ) -> Result<QueryResponse, jmap_base_client::ClientError> {
107 let (api_url, account_id) = self.session_parts()?;
108 let mut filter = serde_json::Map::new();
109 if let Some(n) = input.filter_name {
110 filter.insert("name".into(), n.into());
111 }
112 if let Some(p) = input.filter_is_public {
113 filter.insert("isPublic".into(), p.into());
114 }
115 let filter_val = if filter.is_empty() {
116 serde_json::Value::Null
117 } else {
118 serde_json::Value::Object(filter)
119 };
120 let mut args = serde_json::json!({
121 "accountId": account_id,
122 "filter": filter_val,
123 });
124 if let Some(p) = input.position {
125 args["position"] = p.into();
126 }
127 if let Some(l) = input.limit {
128 args["limit"] = l.into();
129 }
130 let req = super::build_request("Space/query", args, super::USING_CHAT);
131 let resp = self.call_internal(api_url, &req).await?;
132 jmap_base_client::extract_response(&resp, super::CALL_ID)
133 }
134
135 pub async fn space_query_changes(
141 &self,
142 since_query_state: &State,
143 max_changes: Option<u64>,
144 ) -> Result<QueryChangesResponse, jmap_base_client::ClientError> {
145 if since_query_state.as_ref().is_empty() {
147 return Err(jmap_base_client::ClientError::InvalidArgument(
148 "space_query_changes: since_query_state may not be empty".into(),
149 ));
150 }
151 let (api_url, account_id) = self.session_parts()?;
152 let mut args = serde_json::json!({
153 "accountId": account_id,
154 "sinceQueryState": since_query_state,
155 });
156 if let Some(mc) = max_changes {
157 args["maxChanges"] = mc.into();
158 }
159 let req = super::build_request("Space/queryChanges", args, super::USING_CHAT);
160 let resp = self.call_internal(api_url, &req).await?;
161 jmap_base_client::extract_response(&resp, super::CALL_ID)
162 }
163
164 pub async fn space_create(
170 &self,
171 input: &SpaceCreateInput<'_>,
172 ) -> Result<SetResponse, jmap_base_client::ClientError> {
173 if input.name.is_empty() {
174 return Err(jmap_base_client::ClientError::InvalidArgument(
175 "space_create: name may not be empty".into(),
176 ));
177 }
178 let (api_url, account_id) = self.session_parts()?;
179 let client_id = super::resolve_client_id(input.client_id);
180 let mut create_obj = serde_json::json!({ "name": input.name });
181 if let Some(d) = input.description {
182 create_obj["description"] = d.into();
183 }
184 if let Some(b) = input.icon_blob_id {
185 create_obj["iconBlobId"] = b.as_ref().into();
186 }
187 let args = serde_json::json!({
188 "accountId": account_id,
189 "create": { client_id: create_obj },
190 });
191 let req = super::build_request("Space/set", args, super::USING_CHAT);
192 let resp = self.call_internal(api_url, &req).await?;
193 jmap_base_client::extract_response(&resp, super::CALL_ID)
194 }
195
196 pub async fn space_join(
201 &self,
202 input: &SpaceJoinInput<'_>,
203 ) -> Result<SpaceJoinResponse, jmap_base_client::ClientError> {
204 let (api_url, account_id) = self.session_parts()?;
205 let mut args = serde_json::json!({ "accountId": account_id });
206 match input {
207 SpaceJoinInput::InviteCode(ic) => {
208 if ic.is_empty() {
209 return Err(jmap_base_client::ClientError::InvalidArgument(
210 "space_join: invite_code may not be empty".into(),
211 ));
212 }
213 args["inviteCode"] = (*ic).into();
214 }
215 SpaceJoinInput::SpaceId(sid) => {
216 args["spaceId"] = sid.as_ref().into();
217 }
218 }
219 let req = super::build_request("Space/join", args, super::USING_CHAT);
220 let resp = self.call_internal(api_url, &req).await?;
221 jmap_base_client::extract_response(&resp, super::CALL_ID)
222 }
223
224 pub async fn space_update(
240 &self,
241 id: &Id,
242 patch: &SpacePatch<'_>,
243 ) -> Result<SetResponse, jmap_base_client::ClientError> {
244 let (api_url, account_id) = self.session_parts()?;
245 let mut patch_map = serde_json::Map::new();
246
247 if let Some(n) = patch.name {
248 patch_map.insert("name".into(), n.into());
249 }
250 if let Some(entry) = patch
251 .description
252 .map_entry()
253 .map_err(jmap_base_client::ClientError::Parse)?
254 {
255 patch_map.insert("description".into(), entry);
256 }
257 if let Some(entry) = patch
258 .icon_blob_id
259 .map_entry()
260 .map_err(jmap_base_client::ClientError::Parse)?
261 {
262 patch_map.insert("iconBlobId".into(), entry);
263 }
264 if let Some(ip) = patch.is_public {
265 patch_map.insert("isPublic".into(), ip.into());
266 }
267 if let Some(ipp) = patch.is_publicly_previewable {
268 patch_map.insert("isPubliclyPreviewable".into(), ipp.into());
269 }
270 if let Some(members) = patch.add_members {
271 if !members.is_empty() {
272 let arr: Vec<serde_json::Value> = members
273 .iter()
274 .map(
275 |m: &SpaceAddMemberInput<'_>| -> Result<
276 serde_json::Value,
277 jmap_base_client::ClientError,
278 > {
279 let mut obj = serde_json::json!({ "id": m.id });
280 if let Some(role_ids) = m.role_ids {
281 obj["roleIds"] = serde_json::to_value(role_ids)
282 .expect("Id slice Serialize is infallible");
283 }
284 Ok(obj)
285 },
286 )
287 .collect::<Result<Vec<_>, _>>()?;
288 patch_map.insert("addMembers".into(), serde_json::Value::Array(arr));
289 }
290 }
291 if let Some(rm) = patch.remove_members {
292 if !rm.is_empty() {
293 patch_map.insert(
294 "removeMembers".into(),
295 serde_json::to_value(rm).expect("Id slice Serialize is infallible"),
296 );
297 }
298 }
299 if let Some(um) = patch.update_members {
300 if !um.is_empty() {
301 let arr: Vec<serde_json::Value> = um
302 .iter()
303 .map(
304 |u: &SpaceUpdateMemberInput<'_>| -> Result<
305 serde_json::Value,
306 jmap_base_client::ClientError,
307 > {
308 let mut obj = serde_json::json!({ "id": u.id });
309 if let Some(role_ids) = u.role_ids {
310 obj["roleIds"] = serde_json::to_value(role_ids)
311 .expect("Id slice Serialize is infallible");
312 }
313 if let Some(entry) = u
314 .nick
315 .map_entry()
316 .map_err(jmap_base_client::ClientError::Parse)?
317 {
318 obj["nick"] = entry;
319 }
320 Ok(obj)
321 },
322 )
323 .collect::<Result<Vec<_>, _>>()?;
324 patch_map.insert("updateMembers".into(), serde_json::Value::Array(arr));
325 }
326 }
327 if let Some(ac) = patch.add_channels {
328 if !ac.is_empty() {
329 let arr = ac
330 .iter()
331 .map(|c: &SpaceAddChannelInput<'_>| {
332 if c.name.is_empty() {
333 return Err(jmap_base_client::ClientError::InvalidArgument(
334 "space_update: channel name may not be empty".into(),
335 ));
336 }
337 let mut obj = serde_json::json!({ "name": c.name });
338 if let Some(cat) = c.category_id {
339 obj["categoryId"] = cat.as_ref().into();
340 }
341 if let Some(pos) = c.position {
342 obj["position"] = pos.into();
343 }
344 if let Some(t) = c.topic {
345 obj["topic"] = t.into();
346 }
347 Ok(obj)
348 })
349 .collect::<Result<Vec<serde_json::Value>, jmap_base_client::ClientError>>()?;
350 patch_map.insert("addChannels".into(), serde_json::Value::Array(arr));
351 }
352 }
353 if let Some(rc) = patch.remove_channels {
354 if !rc.is_empty() {
355 patch_map.insert(
356 "removeChannels".into(),
357 serde_json::to_value(rc).expect("Id slice Serialize is infallible"),
358 );
359 }
360 }
361 if let Some(uc) = patch.update_channels {
362 if !uc.is_empty() {
363 let arr = uc
364 .iter()
365 .map(|c: &SpaceUpdateChannelInput<'_>| {
366 let mut obj = serde_json::json!({ "id": c.id });
367 if let Some(n) = c.name {
368 obj["name"] = n.into();
369 }
370 if let Some(entry) = c
371 .topic
372 .map_entry()
373 .map_err(jmap_base_client::ClientError::Parse)?
374 {
375 obj["topic"] = entry;
376 }
377 if let Some(entry) = c
378 .category_id
379 .map_entry()
380 .map_err(jmap_base_client::ClientError::Parse)?
381 {
382 obj["categoryId"] = entry;
383 }
384 if let Some(p) = c.position {
385 obj["position"] = p.into();
386 }
387 if let Some(s) = c.slow_mode_seconds {
388 obj["slowModeSeconds"] = s.into();
389 }
390 if let Some(po) = c.permission_overrides {
391 obj["permissionOverrides"] = serde_json::to_value(po)
392 .map_err(jmap_base_client::ClientError::Parse)?;
393 }
394 Ok(obj)
395 })
396 .collect::<Result<Vec<serde_json::Value>, jmap_base_client::ClientError>>()?;
397 patch_map.insert("updateChannels".into(), serde_json::Value::Array(arr));
398 }
399 }
400 if let Some(ar) = patch.add_roles {
401 if !ar.is_empty() {
402 let arr = ar
403 .iter()
404 .map(|r: &SpaceAddRoleInput<'_>| {
405 if r.name.is_empty() {
406 return Err(jmap_base_client::ClientError::InvalidArgument(
407 "space_update: role name may not be empty".into(),
408 ));
409 }
410 let mut obj = serde_json::json!({
411 "name": r.name,
412 "permissions": r.permissions,
413 "position": r.position,
414 });
415 if let Some(c) = r.color {
416 obj["color"] = c.into();
417 }
418 Ok(obj)
419 })
420 .collect::<Result<Vec<serde_json::Value>, jmap_base_client::ClientError>>()?;
421 patch_map.insert("addRoles".into(), serde_json::Value::Array(arr));
422 }
423 }
424 if let Some(rr) = patch.remove_roles {
425 if !rr.is_empty() {
426 patch_map.insert(
427 "removeRoles".into(),
428 serde_json::to_value(rr).expect("Id slice Serialize is infallible"),
429 );
430 }
431 }
432 if let Some(ur) = patch.update_roles {
433 if !ur.is_empty() {
434 let arr = ur
435 .iter()
436 .map(|r: &SpaceUpdateRoleInput<'_>| {
437 let mut obj = serde_json::json!({ "id": r.id });
438 if let Some(n) = r.name {
439 obj["name"] = n.into();
440 }
441 if let Some(entry) = r
442 .color
443 .map_entry()
444 .map_err(jmap_base_client::ClientError::Parse)?
445 {
446 obj["color"] = entry;
447 }
448 if let Some(perms) = r.permissions {
449 obj["permissions"] = serde_json::Value::Array(
450 perms.iter().copied().map(serde_json::Value::from).collect(),
451 );
452 }
453 if let Some(p) = r.position {
454 obj["position"] = p.into();
455 }
456 Ok(obj)
457 })
458 .collect::<Result<Vec<serde_json::Value>, jmap_base_client::ClientError>>()?;
459 patch_map.insert("updateRoles".into(), serde_json::Value::Array(arr));
460 }
461 }
462 if let Some(ac) = patch.add_categories {
463 if !ac.is_empty() {
464 let arr = ac
465 .iter()
466 .map(|c: &SpaceAddCategoryInput<'_>| {
467 if c.name.is_empty() {
468 return Err(jmap_base_client::ClientError::InvalidArgument(
469 "space_update: category name may not be empty".into(),
470 ));
471 }
472 let mut obj = serde_json::json!({ "name": c.name });
473 if let Some(p) = c.position {
474 obj["position"] = p.into();
475 }
476 if let Some(cids) = c.channel_ids {
477 obj["channelIds"] = serde_json::to_value(cids)
478 .expect("Id slice Serialize is infallible");
479 }
480 Ok(obj)
481 })
482 .collect::<Result<Vec<serde_json::Value>, jmap_base_client::ClientError>>()?;
483 patch_map.insert("addCategories".into(), serde_json::Value::Array(arr));
484 }
485 }
486 if let Some(rc) = patch.remove_categories {
487 if !rc.is_empty() {
488 patch_map.insert(
489 "removeCategories".into(),
490 serde_json::to_value(rc).expect("Id slice Serialize is infallible"),
491 );
492 }
493 }
494 if let Some(uc) = patch.update_categories {
495 if !uc.is_empty() {
496 let arr = uc
497 .iter()
498 .map(|c: &SpaceUpdateCategoryInput<'_>| {
499 let mut obj = serde_json::json!({ "id": c.id });
500 if let Some(n) = c.name {
501 obj["name"] = n.into();
502 }
503 if let Some(p) = c.position {
504 obj["position"] = p.into();
505 }
506 if let Some(cids) = c.channel_ids {
507 obj["channelIds"] = serde_json::to_value(cids)
508 .expect("Id slice Serialize is infallible");
509 }
510 obj
511 })
512 .collect::<Vec<serde_json::Value>>();
513 patch_map.insert("updateCategories".into(), serde_json::Value::Array(arr));
514 }
515 }
516
517 let patch_value = serde_json::Value::Object(PatchObject::from_map(patch_map).into_inner());
521 let args = serde_json::json!({
522 "accountId": account_id,
523 "update": { id.as_ref(): patch_value },
524 });
525 let req = super::build_request("Space/set", args, super::USING_CHAT);
526 let resp = self.call_internal(api_url, &req).await?;
527 jmap_base_client::extract_response(&resp, super::CALL_ID)
528 }
529}