Skip to main content

ytmapi_rs/query/
recommendations.rs

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