resourcespace_client/api/collection.rs
1use serde::Serialize;
2use serde_with::json::JsonString;
3use serde_with::{serde_as, skip_serializing_none};
4use validator::Validate;
5
6use crate::client::Client;
7use crate::error::RsError;
8
9use super::{List, SortOrder};
10
11/// Sub-API for collection endpoints.
12#[derive(Debug)]
13pub struct CollectionApi<'a> {
14 client: &'a Client,
15}
16
17impl<'a> CollectionApi<'a> {
18 pub(crate) fn new(client: &'a Client) -> Self {
19 Self { client }
20 }
21
22 /// Returns a list of the user's collections.
23 ///
24 /// ## Arguments
25 /// `None`
26 ///
27 /// ## Examples
28 /// ```no_run
29 /// # use resourcespace_client::Client;
30 /// # async fn example(client: Client) -> Result<(), Box<dyn std::error::Error>> {
31 /// let status = client.collection().get_user_collections().await?;
32 /// # Ok(())
33 /// # }
34 /// ```
35 pub async fn get_user_collections(&self) -> Result<serde_json::Value, RsError> {
36 self.client
37 .send_request("get_user_collections", reqwest::Method::GET, ())
38 .await
39 }
40
41 /// Add a resource to a collection.
42 ///
43 /// ## Arguments
44 /// * `request` - Parameters built via [`AddResourceToCollectionRequest`]
45 ///
46 /// ## Returns
47 /// True or false depending on operation success.
48 ///
49 /// ## TODO: Errors
50 ///
51 /// ## TODO: Examples
52 pub async fn add_resource_to_collection(
53 &self,
54 request: AddResourceToCollectionRequest,
55 ) -> Result<serde_json::Value, RsError> {
56 self.client
57 .send_request("add_resource_to_collection", reqwest::Method::POST, request)
58 .await
59 }
60
61 /// Remove a resource from a collection.
62 ///
63 /// ## Arguments
64 /// * `request` - Parameters built via [`RemoveResourceFromCollectionRequest`]
65 ///
66 /// ## Returns
67 /// True or false depending on operation success.
68 ///
69 /// ## TODO: Errors
70 ///
71 /// ## TODO: Examples
72 pub async fn remove_resource_from_collection(
73 &self,
74 request: RemoveResourceFromCollectionRequest,
75 ) -> Result<serde_json::Value, RsError> {
76 self.client
77 .send_request(
78 "remove_resource_from_collection",
79 reqwest::Method::POST,
80 request,
81 )
82 .await
83 }
84
85 /// Create a new collection for the user.
86 ///
87 /// ## Arguments
88 /// * `request` - Parameters built via [`CreateCollectionRequest`]
89 ///
90 /// ## Returns
91 /// Integer|bool - ID of the collection created, false if collection creation is not permitted
92 ///
93 /// ## TODO: Errors
94 ///
95 /// ## TODO: Examples
96 pub async fn create_collection(
97 &self,
98 request: CreateCollectionRequest,
99 ) -> Result<serde_json::Value, RsError> {
100 self.client
101 .send_request("create_collection", reqwest::Method::POST, request)
102 .await
103 }
104
105 /// Deletes a collection. The user must have write access to this collection.
106 ///
107 /// ## Arguments
108 /// * `request` - Parameters built via [`DeleteCollectionRequest`]
109 ///
110 /// ## Returns
111 /// True or false depending on operation success.
112 ///
113 /// ## TODO: Errors
114 ///
115 /// ## TODO: Examples
116 pub async fn delete_collection(
117 &self,
118 request: DeleteCollectionRequest,
119 ) -> Result<serde_json::Value, RsError> {
120 self.client
121 .send_request("delete_collection", reqwest::Method::POST, request)
122 .await
123 }
124
125 /// Search public and featured collections.
126 ///
127 /// ## Arguments
128 /// * `request` - Parameters built via [`SearchPublicCollectionsRequest`]
129 ///
130 /// ## Returns
131 /// A list of matching public or featured collections.
132 ///
133 /// ## TODO: Errors
134 ///
135 /// ## TODO: Examples
136 pub async fn search_public_collections(
137 &self,
138 request: SearchPublicCollectionsRequest,
139 ) -> Result<serde_json::Value, RsError> {
140 self.client
141 .send_request("search_public_collections", reqwest::Method::GET, request)
142 .await
143 }
144
145 /// Get collection details.
146 ///
147 /// This requires administrator access ("a" permission).
148 ///
149 /// ## Arguments
150 /// * `request` - Parameters built via [`GetCollectionRequest`]
151 ///
152 /// ## Returns
153 /// The collection details including owner name, description, public/private status, thumbnail image reference. All available columns are returned.
154 ///
155 /// ## TODO: Errors
156 ///
157 /// ## TODO: Examples
158 pub async fn get_collection(
159 &self,
160 request: GetCollectionRequest,
161 ) -> Result<serde_json::Value, RsError> {
162 self.client
163 .send_request("get_collection", reqwest::Method::GET, request)
164 .await
165 }
166
167 /// Save collection data.
168 ///
169 /// ## Arguments
170 /// * `request` - Parameters built via [`SaveCollectionRequest`]
171 ///
172 /// ## Returns
173 /// Returns false if access control fails or invalid arguments have been received (e.g ref not a number), true otherwise.
174 ///
175 /// ## TODO: Errors
176 ///
177 /// ## TODO: Examples
178 pub async fn save_collection(
179 &self,
180 request: SaveCollectionRequest,
181 ) -> Result<serde_json::Value, RsError> {
182 self.client
183 .send_request("save_collection", reqwest::Method::POST, request)
184 .await
185 }
186
187 /// Shows or hides a collection from the user's drop-down list.
188 ///
189 /// ## Arguments
190 /// * `request` - Parameters built via [`ShowHideCollectionRequest`]
191 ///
192 /// ## Returns
193 /// True or false depending on operation success.
194 ///
195 /// ## TODO: Errors
196 ///
197 /// ## TODO: Examples
198 pub async fn show_hide_collection(
199 &self,
200 request: ShowHideCollectionRequest,
201 ) -> Result<serde_json::Value, RsError> {
202 self.client
203 .send_request("show_hide_collection", reqwest::Method::POST, request)
204 .await
205 }
206
207 /// Sends a copy of the collection for admin review.
208 ///
209 /// ## Arguments
210 /// * `request` - Parameters built via [`SendCollectionToAdminRequest`]
211 ///
212 /// ## Returns
213 /// True or false depending on operation success.
214 ///
215 /// ## TODO: Errors
216 ///
217 /// ## TODO: Examples
218 pub async fn send_collection_to_admin(
219 &self,
220 request: SendCollectionToAdminRequest,
221 ) -> Result<serde_json::Value, RsError> {
222 self.client
223 .send_request("send_collection_to_admin", reqwest::Method::POST, request)
224 .await
225 }
226
227 /// Get ResourceSpace featured collections (category).
228 ///
229 /// ## Arguments
230 /// * `request` - Parameters built via [`GetFeaturedCollectionsRequest`]
231 ///
232 /// ## Returns
233 /// If successful, a 200 HTTP status will be returned with the body containing an array. If the parent is invalid an empty array will be returned instead.
234 ///
235 /// ## TODO: Errors
236 ///
237 /// ## TODO: Examples
238 pub async fn get_featured_collections(
239 &self,
240 request: GetFeaturedCollectionsRequest,
241 ) -> Result<serde_json::Value, RsError> {
242 self.client
243 .send_request("get_featured_collections", reqwest::Method::GET, request)
244 .await
245 }
246
247 /// Deletes all resources in a collection.
248 ///
249 /// The user must have edit access to the resources, permission to delete resources and the collection must be writable.
250 ///
251 /// ## Arguments
252 /// * `request` - Parameters built via [`DeleteResourcesInCollectionRequest`]
253 ///
254 /// ## Returns
255 /// True or false depending on operation success.
256 ///
257 /// ## TODO: Errors
258 ///
259 /// ## TODO: Examples
260 pub async fn delete_resources_in_collection(
261 &self,
262 request: DeleteResourcesInCollectionRequest,
263 ) -> Result<serde_json::Value, RsError> {
264 self.client
265 .send_request(
266 "delete_resources_in_collection",
267 reqwest::Method::POST,
268 request,
269 )
270 .await
271 }
272
273 /// Get the total resource count for a list of collections.
274 ///
275 /// Requires permission `b` and the collections must be readable by the user.
276 ///
277 /// ## Arguments
278 /// * `request` - Parameters built via [`GetCollectionsResourceCountRequest`]
279 ///
280 /// ## Returns
281 /// Array of collections and their total resource count. Note the returned array may
282 /// not contain keys for all input IDs if validation fails for some.
283 ///
284 /// ## TODO: Errors
285 ///
286 /// ## TODO: Examples
287 pub async fn get_collections_resource_count(
288 &self,
289 request: GetCollectionsResourceCountRequest,
290 ) -> Result<serde_json::Value, RsError> {
291 self.client
292 .send_request(
293 "get_collections_resource_count",
294 reqwest::Method::GET,
295 request,
296 )
297 .await
298 }
299}
300
301#[derive(Clone, Debug, PartialEq, Serialize)]
302pub struct AddResourceToCollectionRequest {
303 /// The ID of the resource to add.
304 pub resource: u32,
305 /// The ID of the collection to add the resource to.
306 pub collection: u32,
307}
308
309impl AddResourceToCollectionRequest {
310 pub fn new(resource: u32, collection: u32) -> Self {
311 Self {
312 resource,
313 collection,
314 }
315 }
316}
317
318#[derive(Clone, Debug, PartialEq, Serialize)]
319pub struct RemoveResourceFromCollectionRequest {
320 /// The ID of the resource to remove.
321 pub resource: u32,
322 /// The ID of the collection to remove the resource from.
323 pub collection: u32,
324}
325
326impl RemoveResourceFromCollectionRequest {
327 pub fn new(resource: u32, collection: u32) -> Self {
328 Self {
329 resource,
330 collection,
331 }
332 }
333}
334
335#[skip_serializing_none]
336#[derive(Clone, Debug, PartialEq, Serialize)]
337pub struct CreateCollectionRequest {
338 /// The name of the new collection.
339 pub name: String,
340 /// If set, marks this collection as an upload collection.
341 pub forupload: Option<u8>,
342}
343
344impl CreateCollectionRequest {
345 pub fn new(name: impl Into<String>) -> Self {
346 Self {
347 name: name.into(),
348 forupload: None,
349 }
350 }
351
352 pub fn forupload(mut self, forupload: bool) -> Self {
353 self.forupload = Some(forupload as u8);
354 self
355 }
356}
357
358#[derive(Clone, Debug, PartialEq, Serialize)]
359pub struct DeleteCollectionRequest {
360 /// The ID of the collection to delete.
361 pub collection: u32,
362}
363
364impl DeleteCollectionRequest {
365 pub fn new(collection: u32) -> Self {
366 Self { collection }
367 }
368}
369
370#[skip_serializing_none]
371#[derive(Clone, Debug, Default, PartialEq, Serialize)]
372pub struct SearchPublicCollectionsRequest {
373 /// Optional search string to filter collections by name.
374 pub search: Option<String>,
375 /// Field name to order results by.
376 pub order_by: Option<String>,
377 /// Sort direction for the results.
378 pub sort: Option<SortOrder>,
379 /// If set, excludes theme/featured collections from results.
380 pub exclude_themes: Option<u8>,
381}
382
383impl SearchPublicCollectionsRequest {
384 pub fn new() -> Self {
385 Self::default()
386 }
387
388 pub fn search(mut self, search: impl Into<String>) -> Self {
389 self.search = Some(search.into());
390 self
391 }
392
393 pub fn order_by(mut self, order_by: impl Into<String>) -> Self {
394 self.order_by = Some(order_by.into());
395 self
396 }
397
398 pub fn sort(mut self, sort: SortOrder) -> Self {
399 self.sort = Some(sort);
400 self
401 }
402
403 pub fn exclude_themes(mut self, exclude_themes: bool) -> Self {
404 self.exclude_themes = Some(exclude_themes as u8);
405 self
406 }
407}
408
409#[derive(Clone, Debug, PartialEq, Serialize)]
410pub struct GetCollectionRequest {
411 /// The ID of the collection to retrieve.
412 #[serde(rename = "ref")]
413 pub r#ref: u32,
414}
415
416impl GetCollectionRequest {
417 pub fn new(r#ref: u32) -> Self {
418 Self { r#ref }
419 }
420}
421
422#[serde_as]
423#[derive(Clone, Debug, PartialEq, Serialize)]
424pub struct SaveCollectionRequest {
425 /// The ID of the collection to save.
426 #[serde(rename = "ref")]
427 pub r#ref: u32,
428 /// JSON object containing the collection fields to update (e.g. name, description, public).
429 #[serde_as(as = "JsonString")]
430 pub coldata: SaveCollectionColdata,
431}
432
433impl SaveCollectionRequest {
434 pub fn new(r#ref: u32, coldata: SaveCollectionColdata) -> Self {
435 Self { r#ref, coldata }
436 }
437}
438
439#[derive(Clone, Debug, PartialEq, Serialize, Validate)]
440pub struct SaveCollectionColdata {
441 /// Comma-separated value of keywords to be associated with this collection.
442 pub keywords: Option<List<String>>,
443 /// To set whether other users are allowed to add/remove resources when collection is shared or is public. The allowed value is 0 or 1.
444 #[validate(range(min = 0, max = 1))]
445 pub allow_changes: Option<u8>,
446 /// Comma-separated value of users to attach to the collection.
447 pub users: Option<List<String>>,
448 /// Collection name.
449 pub name: Option<String>,
450 /// 0 for private, 1 for public (legacy).
451 #[validate(range(min = 0, max = 1))]
452 pub public: Option<u8>,
453 /// 0 = standard, 3 = Featured collection, 4 = public. If 3 or 4 then public should be set to 1.
454 #[serde(rename = "type")]
455 pub r#type: Option<u8>,
456 /// ID of parent featured collection. Set to 0 to create a new root level collection (see below). Applies to Featured collections only.
457 pub parent: Option<u32>,
458 /// Required to be set to 1 if creating a root level featured collection (parent=0). Applies to Featured collections only.
459 #[validate(range(min = 0, max = 1))]
460 pub force_featured_collection_type: Option<u8>,
461 /// 0 = no image, 1 = most popular image, 10 - most popular images, 100 - manually select image. Applies to Featured collections only.
462 pub thumbnail_selection_method: Option<u32>,
463 /// Resource ID to use as thumbnail. Only if thumbnail_selection_method =100. Applies to Featured collections only.
464 pub bg_img_resource_ref: Option<u32>,
465}
466
467#[derive(Clone, Debug, PartialEq, Serialize)]
468pub struct ShowHideCollectionRequest {
469 /// The ID of the collection to show or hide.
470 pub collection: u32,
471 /// If set, shows the collection in the drop-down list.
472 pub show: u8,
473 /// The ID of the user whose drop-down list is being updated.
474 pub user: u32,
475}
476
477impl ShowHideCollectionRequest {
478 pub fn new(collection: u32, show: bool, user: u32) -> Self {
479 Self {
480 collection,
481 show: show as u8,
482 user,
483 }
484 }
485}
486
487#[derive(Clone, Debug, PartialEq, Serialize)]
488pub struct SendCollectionToAdminRequest {
489 /// The ID of the collection to send to the administrator for review.
490 pub collection: u32,
491}
492
493impl SendCollectionToAdminRequest {
494 pub fn new(collection: u32) -> Self {
495 Self { collection }
496 }
497}
498
499#[derive(Clone, Debug, PartialEq, Serialize)]
500pub struct GetFeaturedCollectionsRequest {
501 /// The ID of the parent featured collection (category) to retrieve children for. Use 0 for top-level.
502 pub parent: u32,
503}
504
505impl GetFeaturedCollectionsRequest {
506 pub fn new(parent: u32) -> Self {
507 Self { parent }
508 }
509}
510
511#[derive(Clone, Debug, PartialEq, Serialize)]
512pub struct DeleteResourcesInCollectionRequest {
513 /// The ID of the collection whose resources should all be deleted.
514 pub collection: u32,
515}
516
517impl DeleteResourcesInCollectionRequest {
518 pub fn new(collection: u32) -> Self {
519 Self { collection }
520 }
521}
522
523#[derive(Clone, Debug, PartialEq, Serialize)]
524pub struct GetCollectionsResourceCountRequest {
525 /// Comma-separated list of collection IDs to retrieve resource counts for.
526 pub refs: List<u32>,
527}
528
529impl GetCollectionsResourceCountRequest {
530 pub fn new(refs: impl Into<List<u32>>) -> Self {
531 Self { refs: refs.into() }
532 }
533}