am_api/resource/library/
mod.rs1use crate::error::Error;
4use crate::request::context::ContextContainer;
5use crate::request::try_resource_response;
6use crate::resource::{Resource, ResourceInfo, ResourceType};
7use crate::ApiClient;
8
9use crate::request::builder::MusicRequestBuilder;
10use reqwest::header;
11use std::collections::{HashMap, HashSet};
12use std::sync::Arc;
13
14pub mod album;
15pub mod artist;
16pub mod music_video;
17pub mod playlist;
18pub mod song;
19
20pub struct LibraryBuilder;
22
23pub type LibraryAddResourceBuilder<'a> =
25 MusicRequestBuilder<'a, LibraryBuilder, HashMap<&'static str, HashSet<String>>>;
26
27impl<'a> LibraryAddResourceBuilder<'a> {
28 pub fn new() -> LibraryAddResourceBuilder<'a> {
30 LibraryAddResourceBuilder::default()
31 }
32
33 pub fn add_resource(mut self, resource: &Resource) -> Result<Self, Error> {
35 let supported = matches!(
36 resource,
37 Resource::Album { .. }
38 | Resource::Artist { .. }
39 | Resource::MusicVideo { .. }
40 | Resource::Playlist { .. }
41 | Resource::Song { .. }
42 );
43
44 if !supported {
45 return Err(Error::InvalidResourceType);
46 }
47 self.data
48 .entry(resource.get_type())
49 .or_default()
50 .insert(resource.get_header().id.clone());
51
52 Ok(self)
53 }
54
55 pub fn add_resources(mut self, resources: &[Resource]) -> Result<Self, Error> {
57 for resource in resources {
58 let supported = matches!(
59 resource,
60 Resource::Album { .. }
61 | Resource::Artist { .. }
62 | Resource::MusicVideo { .. }
63 | Resource::Playlist { .. }
64 | Resource::Song { .. }
65 );
66
67 if !supported {
68 return Err(Error::InvalidResourceType);
69 }
70 self.data
71 .entry(resource.get_type())
72 .or_default()
73 .insert(resource.get_header().id.clone());
74 }
75 Ok(self)
76 }
77
78 pub async fn send(mut self, client: &ApiClient) -> Result<Vec<Resource>, Error> {
80 let mut request_context = self.get_request_context_drain(client);
81 request_context
82 .query
83 .push((String::from("representation"), String::from("ids")));
84
85 for (resource_type, ids) in self.data {
86 request_context.query.push((
87 format!("ids[{}]", resource_type),
88 ids.into_iter().collect::<Vec<_>>().join(","),
89 ));
90 }
91
92 let request_context = Arc::new(request_context);
93
94 let response = client
95 .post("/v1/me/library")
96 .header(header::CONTENT_LENGTH, 0)
97 .query(&request_context.query)
98 .send()
99 .await?;
100
101 let mut response = try_resource_response(response).await?;
102 response.data.set_context(request_context);
103 Ok(response.data)
104 }
105}