Skip to main content

ytmapi_rs/query/
artist.rs

1use super::{PostMethod, PostQuery, Query};
2use crate::auth::{AuthToken, LoggedIn};
3use crate::common::{ArtistChannelID, BrowseParams, YoutubeID};
4use crate::parse::{GetArtist, GetArtistAlbumsAlbum};
5use serde_json::json;
6
7#[derive(Debug, Clone)]
8pub struct GetArtistQuery<'a> {
9    channel_id: ArtistChannelID<'a>,
10}
11#[derive(Debug, Clone)]
12pub struct GetArtistAlbumsQuery<'a> {
13    channel_id: ArtistChannelID<'a>,
14    params: BrowseParams<'a>,
15}
16#[derive(Debug, Clone)]
17pub struct SubscribeArtistQuery<'a> {
18    channel_id: ArtistChannelID<'a>,
19}
20#[derive(Debug, Clone)]
21pub struct UnsubscribeArtistsQuery<'a> {
22    channel_ids: Vec<ArtistChannelID<'a>>,
23}
24impl<'a> GetArtistQuery<'a> {
25    pub fn new(channel_id: impl Into<ArtistChannelID<'a>>) -> GetArtistQuery<'a> {
26        GetArtistQuery {
27            channel_id: channel_id.into(),
28        }
29    }
30}
31impl<'a> GetArtistAlbumsQuery<'a> {
32    pub fn new(
33        channel_id: ArtistChannelID<'a>,
34        params: BrowseParams<'a>,
35    ) -> GetArtistAlbumsQuery<'a> {
36        GetArtistAlbumsQuery { channel_id, params }
37    }
38}
39impl<'a> SubscribeArtistQuery<'a> {
40    pub fn new(channel_id: ArtistChannelID<'a>) -> SubscribeArtistQuery<'a> {
41        SubscribeArtistQuery { channel_id }
42    }
43}
44impl<'a> UnsubscribeArtistsQuery<'a> {
45    pub fn new(
46        channel_ids: impl IntoIterator<Item = ArtistChannelID<'a>>,
47    ) -> UnsubscribeArtistsQuery<'a> {
48        UnsubscribeArtistsQuery {
49            channel_ids: channel_ids.into_iter().collect(),
50        }
51    }
52}
53
54impl<'a, T: Into<ArtistChannelID<'a>>> From<T> for GetArtistQuery<'a> {
55    fn from(channel_id: T) -> Self {
56        GetArtistQuery::new(channel_id.into())
57    }
58}
59
60impl<A: AuthToken> Query<A> for GetArtistQuery<'_> {
61    type Output = GetArtist;
62    type Method = PostMethod;
63}
64impl PostQuery for GetArtistQuery<'_> {
65    fn header(&self) -> serde_json::Map<String, serde_json::Value> {
66        // XXX: could do in new to avoid process every time called
67        // or even better, could do this first time called, and store state so not
68        // required after that.
69        let value = self.channel_id.get_raw().replacen("MPLA", "", 1);
70        let serde_json::Value::Object(map) = json!({
71            "browseId" : value,
72        }) else {
73            unreachable!()
74        };
75        map
76    }
77    fn path(&self) -> &str {
78        "browse"
79    }
80    fn params(&self) -> std::vec::Vec<(&str, std::borrow::Cow<'_, str>)> {
81        vec![]
82    }
83}
84// TODO: Check if the MPLA strip is correct for both of these.
85impl<A: AuthToken> Query<A> for GetArtistAlbumsQuery<'_> {
86    type Output = Vec<GetArtistAlbumsAlbum>;
87    type Method = PostMethod;
88}
89impl PostQuery for GetArtistAlbumsQuery<'_> {
90    fn header(&self) -> serde_json::Map<String, serde_json::Value> {
91        // XXX: should do in new
92        // XXX: Think I could remove allocation here
93        let value = self.channel_id.get_raw().replacen("MPLA", "", 1);
94        FromIterator::from_iter([
95            ("browseId".to_string(), json!(value)),
96            ("params".to_string(), json!(self.params)),
97        ])
98    }
99    fn path(&self) -> &str {
100        "browse"
101    }
102    fn params(&self) -> std::vec::Vec<(&str, std::borrow::Cow<'_, str>)> {
103        vec![]
104    }
105}
106impl<A: LoggedIn> Query<A> for SubscribeArtistQuery<'_> {
107    type Output = ();
108    type Method = PostMethod;
109}
110impl PostQuery for SubscribeArtistQuery<'_> {
111    fn header(&self) -> serde_json::Map<String, serde_json::Value> {
112        FromIterator::from_iter([("channelIds".into(), json!([self.channel_id]))])
113    }
114    fn path(&self) -> &str {
115        "subscription/subscribe"
116    }
117    fn params(&self) -> std::vec::Vec<(&str, std::borrow::Cow<'_, str>)> {
118        vec![]
119    }
120}
121impl<A: LoggedIn> Query<A> for UnsubscribeArtistsQuery<'_> {
122    type Output = ();
123    type Method = PostMethod;
124}
125impl PostQuery for UnsubscribeArtistsQuery<'_> {
126    fn header(&self) -> serde_json::Map<String, serde_json::Value> {
127        FromIterator::from_iter([("channelIds".into(), json!(self.channel_ids))])
128    }
129    fn path(&self) -> &str {
130        "subscription/unsubscribe"
131    }
132    fn params(&self) -> std::vec::Vec<(&str, std::borrow::Cow<'_, str>)> {
133        vec![]
134    }
135}