ytmapi_rs/query/
library.rs1use super::{PostMethod, PostQuery, Query};
2use crate::{
3 auth::AuthToken,
4 common::{ApiOutcome, FeedbackTokenAddToLibrary, FeedbackTokenRemoveFromLibrary, YoutubeID},
5 parse::{
6 GetLibraryAlbums, GetLibraryArtistSubscriptions, GetLibraryArtists, GetLibraryPlaylists,
7 GetLibrarySongs,
8 },
9};
10use serde_json::json;
11use std::borrow::Cow;
12
13#[derive(Default, Clone)]
18pub enum GetLibrarySortOrder {
19 NameAsc,
20 NameDesc,
21 MostSongs,
22 RecentlySaved,
23 #[default]
24 Default,
25}
26
27pub struct GetLibraryPlaylistsQuery;
28#[derive(Default)]
29pub struct GetLibrarySongsQuery {
31 sort_order: GetLibrarySortOrder,
32}
33#[derive(Default)]
34pub struct GetLibraryAlbumsQuery {
36 sort_order: GetLibrarySortOrder,
37}
38#[derive(Default)]
39pub struct GetLibraryArtistSubscriptionsQuery {
41 sort_order: GetLibrarySortOrder,
42}
43#[derive(Default)]
44pub struct GetLibraryArtistsQuery {
46 sort_order: GetLibrarySortOrder,
47}
48pub struct EditSongLibraryStatusQuery<'a> {
49 add_to_library_feedback_tokens: Vec<FeedbackTokenAddToLibrary<'a>>,
50 remove_from_library_feedback_tokens: Vec<FeedbackTokenRemoveFromLibrary<'a>>,
51}
52
53impl GetLibrarySongsQuery {
54 pub fn new(sort_order: GetLibrarySortOrder) -> Self {
55 Self { sort_order }
56 }
57}
58impl GetLibraryAlbumsQuery {
59 pub fn new(sort_order: GetLibrarySortOrder) -> Self {
60 Self { sort_order }
61 }
62}
63impl GetLibraryArtistSubscriptionsQuery {
64 pub fn new(sort_order: GetLibrarySortOrder) -> Self {
65 Self { sort_order }
66 }
67}
68impl GetLibraryArtistsQuery {
69 pub fn new(sort_order: GetLibrarySortOrder) -> Self {
70 Self { sort_order }
71 }
72}
73impl<'a> EditSongLibraryStatusQuery<'a> {
74 pub fn new_from_add_to_library_feedback_tokens(
75 add_to_library_feedback_tokens: Vec<FeedbackTokenAddToLibrary<'a>>,
76 ) -> Self {
77 Self {
78 add_to_library_feedback_tokens,
79 remove_from_library_feedback_tokens: vec![],
80 }
81 }
82 pub fn new_from_remove_from_library_feedback_tokens(
83 remove_from_library_feedback_tokens: Vec<FeedbackTokenRemoveFromLibrary<'a>>,
84 ) -> Self {
85 Self {
86 add_to_library_feedback_tokens: vec![],
87 remove_from_library_feedback_tokens,
88 }
89 }
90 pub fn with_add_to_library_feedback_tokens(
91 mut self,
92 add_to_library_feedback_tokens: Vec<FeedbackTokenAddToLibrary<'a>>,
93 ) -> Self {
94 self.add_to_library_feedback_tokens = add_to_library_feedback_tokens;
95 self
96 }
97 pub fn with_remove_from_library_feedback_tokens(
98 mut self,
99 remove_from_library_feedback_tokens: Vec<FeedbackTokenRemoveFromLibrary<'a>>,
100 ) -> Self {
101 self.remove_from_library_feedback_tokens = remove_from_library_feedback_tokens;
102 self
103 }
104}
105
106impl<A: AuthToken> Query<A> for GetLibraryPlaylistsQuery {
107 type Output = GetLibraryPlaylists;
108 type Method = PostMethod;
109}
110impl PostQuery for GetLibraryPlaylistsQuery {
111 fn header(&self) -> serde_json::Map<String, serde_json::Value> {
112 FromIterator::from_iter([("browseId".to_string(), json!("FEmusic_liked_playlists"))])
113 }
114 fn path(&self) -> &str {
115 "browse"
116 }
117 fn params(&self) -> Vec<(&str, Cow<str>)> {
118 vec![]
119 }
120}
121impl<A: AuthToken> Query<A> for GetLibraryArtistsQuery {
122 type Output = GetLibraryArtists;
123 type Method = PostMethod;
124}
125impl PostQuery for GetLibraryArtistsQuery {
126 fn header(&self) -> serde_json::Map<String, serde_json::Value> {
127 if let Some(params) = get_sort_order_params(&self.sort_order) {
128 FromIterator::from_iter([
129 (
130 "browseId".to_string(),
131 json!("FEmusic_library_corpus_track_artists"),
132 ),
133 ("params".to_string(), json!(params)),
134 ])
135 } else {
136 FromIterator::from_iter([(
137 "browseId".to_string(),
138 json!("FEmusic_library_corpus_track_artists"),
139 )])
140 }
141 }
142 fn path(&self) -> &str {
143 "browse"
144 }
145 fn params(&self) -> Vec<(&str, Cow<str>)> {
146 vec![]
147 }
148}
149
150impl<A: AuthToken> Query<A> for GetLibrarySongsQuery {
151 type Output = GetLibrarySongs;
152 type Method = PostMethod;
153}
154impl PostQuery for GetLibrarySongsQuery {
155 fn header(&self) -> serde_json::Map<String, serde_json::Value> {
156 if let Some(params) = get_sort_order_params(&self.sort_order) {
157 serde_json::Map::from_iter([
158 ("browseId".to_string(), json!("FEmusic_liked_videos")),
159 ("params".to_string(), json!(params)),
160 ])
161 } else {
162 serde_json::Map::from_iter([("browseId".to_string(), json!("FEmusic_liked_videos"))])
163 }
164 }
165 fn params(&self) -> Vec<(&str, Cow<str>)> {
166 vec![]
167 }
168 fn path(&self) -> &str {
169 "browse"
170 }
171}
172impl<A: AuthToken> Query<A> for GetLibraryAlbumsQuery {
173 type Output = GetLibraryAlbums;
174 type Method = PostMethod;
175}
176impl PostQuery for GetLibraryAlbumsQuery {
177 fn header(&self) -> serde_json::Map<String, serde_json::Value> {
178 if let Some(params) = get_sort_order_params(&self.sort_order) {
179 serde_json::Map::from_iter([
180 ("browseId".to_string(), json!("FEmusic_liked_albums")),
181 ("params".to_string(), json!(params)),
182 ])
183 } else {
184 serde_json::Map::from_iter([("browseId".to_string(), json!("FEmusic_liked_albums"))])
185 }
186 }
187 fn params(&self) -> Vec<(&str, Cow<str>)> {
188 vec![]
189 }
190 fn path(&self) -> &str {
191 "browse"
192 }
193}
194impl<A: AuthToken> Query<A> for GetLibraryArtistSubscriptionsQuery {
195 type Output = GetLibraryArtistSubscriptions;
196 type Method = PostMethod;
197}
198impl PostQuery for GetLibraryArtistSubscriptionsQuery {
199 fn header(&self) -> serde_json::Map<String, serde_json::Value> {
200 if let Some(params) = get_sort_order_params(&self.sort_order) {
201 serde_json::Map::from_iter([
202 (
203 "browseId".to_string(),
204 json!("FEmusic_library_corpus_artists"),
205 ),
206 ("params".to_string(), json!(params)),
207 ])
208 } else {
209 serde_json::Map::from_iter([(
210 "browseId".to_string(),
211 json!("FEmusic_library_corpus_artists"),
212 )])
213 }
214 }
215 fn params(&self) -> Vec<(&str, Cow<str>)> {
216 vec![]
217 }
218 fn path(&self) -> &str {
219 "browse"
220 }
221}
222impl<A: AuthToken> Query<A> for EditSongLibraryStatusQuery<'_> {
225 type Output = Vec<ApiOutcome>;
226 type Method = PostMethod;
227}
228impl PostQuery for EditSongLibraryStatusQuery<'_> {
229 fn header(&self) -> serde_json::Map<String, serde_json::Value> {
230 let add_feedback_tokens_raw = self
231 .add_to_library_feedback_tokens
232 .iter()
233 .map(|t| t.get_raw());
234 let feedback_tokens = self
235 .remove_from_library_feedback_tokens
236 .iter()
237 .map(|t| t.get_raw())
238 .chain(add_feedback_tokens_raw)
239 .collect::<Vec<_>>();
240 serde_json::Map::from_iter([("feedbackTokens".to_string(), json!(feedback_tokens))])
241 }
242 fn params(&self) -> Vec<(&str, Cow<str>)> {
243 vec![]
244 }
245 fn path(&self) -> &str {
246 "feedback"
247 }
248}
249
250pub(crate) fn get_sort_order_params(o: &GetLibrarySortOrder) -> Option<&'static str> {
251 match o {
252 GetLibrarySortOrder::NameAsc => Some("ggMGKgQIARAA"),
253 GetLibrarySortOrder::NameDesc => Some("ggMGKgQIARAB"),
254 GetLibrarySortOrder::MostSongs => todo!(),
256 GetLibrarySortOrder::RecentlySaved => Some("ggMGKgQIABAB"),
257 GetLibrarySortOrder::Default => None,
258 }
259}