ytmapi_rs/query/
recommendations.rs1use std::borrow::Cow;
2
3use serde_json::{json, Value};
4
5use super::{PostMethod, PostQuery, Query};
6use crate::{
7 auth::AuthToken,
8 common::{MoodCategoryParams, TasteToken},
9 parse::{MoodCategorySection, MoodPlaylistCategory, TasteProfileArtist},
10};
11
12#[derive(Clone)]
13pub struct GetTasteProfileQuery;
14
15#[derive(Clone)]
16pub struct SetTasteProfileQuery<'a, I>
17where
18 I: Iterator<Item = TasteToken<'a>> + Clone,
19{
20 taste_tokens: I,
21}
22
23#[derive(Clone)]
24pub struct GetMoodCategoriesQuery;
25
26#[derive(Clone)]
27pub struct GetMoodPlaylistsQuery<'a> {
28 params: MoodCategoryParams<'a>,
29}
30
31impl<'a, I> SetTasteProfileQuery<'a, I>
32where
33 I: Iterator<Item = TasteToken<'a>> + Clone,
34{
35 pub fn new<II: IntoIterator<IntoIter = I>>(taste_tokens: II) -> Self {
36 let taste_tokens = taste_tokens.into_iter();
37 Self { taste_tokens }
38 }
39}
40
41impl<'a> GetMoodPlaylistsQuery<'a> {
42 pub fn new(params: MoodCategoryParams<'a>) -> Self {
43 Self { params }
44 }
45}
46
47impl<A: AuthToken> Query<A> for GetTasteProfileQuery {
48 type Output = Vec<TasteProfileArtist>;
49 type Method = PostMethod;
50}
51impl PostQuery for GetTasteProfileQuery {
52 fn header(&self) -> serde_json::Map<String, serde_json::Value> {
53 serde_json::Map::from_iter([("browseId".to_string(), json!("FEmusic_tastebuilder"))])
54 }
55 fn params(&self) -> Vec<(&str, Cow<str>)> {
56 vec![]
57 }
58 fn path(&self) -> &str {
59 "browse"
60 }
61}
62
63impl<'a, A, I> Query<A> for SetTasteProfileQuery<'a, I>
64where
65 A: AuthToken,
66 I: Iterator<Item = TasteToken<'a>> + Clone,
67{
68 type Output = ();
69 type Method = PostMethod;
70}
71impl<'a, I> PostQuery for SetTasteProfileQuery<'a, I>
72where
73 I: Iterator<Item = TasteToken<'a>> + Clone,
74{
75 fn header(&self) -> serde_json::Map<String, serde_json::Value> {
76 let (impression_tokens, selection_tokens): (Vec<Value>, Vec<Value>) = self
77 .taste_tokens
78 .clone()
79 .map(|t| (json!(t.impression_value), json!(t.selection_value)))
80 .unzip();
81 serde_json::Map::from_iter([
82 ("browseId".to_string(), json!("FEmusic_home")),
83 (
84 "formData".to_string(),
85 json!({
86 "impressionValues": impression_tokens,
87 "selectedValues": selection_tokens
88 }),
89 ),
90 ])
91 }
92 fn params(&self) -> Vec<(&str, Cow<str>)> {
93 vec![]
94 }
95 fn path(&self) -> &str {
96 "browse"
97 }
98}
99
100impl<A: AuthToken> Query<A> for GetMoodCategoriesQuery {
101 type Output = Vec<MoodCategorySection>;
102 type Method = PostMethod;
103}
104impl PostQuery for GetMoodCategoriesQuery {
105 fn header(&self) -> serde_json::Map<String, serde_json::Value> {
106 serde_json::Map::from_iter([("browseId".to_string(), json!("FEmusic_moods_and_genres"))])
107 }
108 fn params(&self) -> Vec<(&str, Cow<str>)> {
109 vec![]
110 }
111 fn path(&self) -> &str {
112 "browse"
113 }
114}
115
116impl<A: AuthToken> Query<A> for GetMoodPlaylistsQuery<'_> {
117 type Output = Vec<MoodPlaylistCategory>;
118 type Method = PostMethod;
119}
120impl PostQuery for GetMoodPlaylistsQuery<'_> {
121 fn header(&self) -> serde_json::Map<String, serde_json::Value> {
122 serde_json::Map::from_iter([
123 (
124 "browseId".to_string(),
125 json!("FEmusic_moods_and_genres_category"),
126 ),
127 ("params".to_string(), json!(self.params)),
128 ])
129 }
130 fn params(&self) -> Vec<(&str, Cow<str>)> {
131 vec![]
132 }
133 fn path(&self) -> &str {
134 "browse"
135 }
136}