spotify_web_api/api/search/
search_for_item.rs

1use crate::{
2    api::{Endpoint, common::path_escaped, prelude::*},
3    model::{IncludeExternalType, SearchType},
4};
5
6/// Get Spotify catalog information about albums, artists, playlists, tracks, shows, episodes or audiobooks that match a keyword string.
7/// Audiobooks are only available within the US, UK, Canada, Ireland, New Zealand and Australia markets.
8#[derive(Debug, Clone)]
9pub struct SearchForItem {
10    /// Your search query.
11    pub query: String,
12
13    /// A list of item types to search across. Search results include hits from all the specified item types.
14    pub search_types: Vec<SearchType>,
15
16    /// An [ISO 3166-1 alpha-2 country code](https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2).
17    /// If a country code is specified, only content that is available in that market will be returned.
18    /// If a valid user access token is specified in the request header, the country associated with the user account will take priority over this parameter.
19    ///
20    /// # Notes
21    /// If neither market or user country are provided, the content is considered unavailable for the client.
22    /// Users can view the country that is associated with their account in the [account settings](https://www.spotify.com/account/overview/).
23    pub market: Option<Market>,
24
25    /// If `include_external=audio` is specified it signals that the client can play externally hosted audio content, and marks the content as playable in the response.
26    /// By default externally hosted audio content is marked as unplayable in the response.
27    pub include_external: Option<IncludeExternalType>,
28}
29
30impl SearchForItem {
31    pub fn new(
32        query: impl Into<String>,
33        search_types: impl IntoIterator<Item = SearchType>,
34    ) -> Self {
35        Self {
36            query: query.into(),
37            search_types: search_types.into_iter().collect(),
38            market: None,
39            include_external: None,
40        }
41    }
42
43    pub fn market(mut self, market: Market) -> Self {
44        self.market = Some(market);
45        self
46    }
47
48    pub fn include_external(mut self, include_external: IncludeExternalType) -> Self {
49        self.include_external = Some(include_external);
50        self
51    }
52}
53
54impl Endpoint for SearchForItem {
55    fn method(&self) -> Method {
56        Method::GET
57    }
58
59    fn endpoint(&self) -> Cow<'static, str> {
60        "search".into()
61    }
62
63    fn parameters(&self) -> QueryParams<'_> {
64        let mut params = QueryParams::default();
65        params.push("q", &format!("{}", path_escaped(&self.query)));
66
67        let type_str = self
68            .search_types
69            .iter()
70            .map(|x| x.to_string())
71            .collect::<Vec<_>>()
72            .join(",");
73
74        params.push("type", &type_str);
75        params.push_opt("market", self.market.as_ref());
76        params.push_opt("include_external", self.include_external.as_ref());
77
78        params
79    }
80}
81
82#[cfg(test)]
83mod tests {
84    use super::*;
85    use crate::{
86        api::{self, Query as _},
87        test::client::{ExpectedUrl, SingleTestClient},
88    };
89
90    #[test]
91    fn test_search_for_item_endpoint() {
92        let endpoint = ExpectedUrl::builder()
93            .endpoint("search")
94            .add_query_params(&[("q", "remaster%20track:Doxy%20artist:Miles%20Davis")])
95            .add_query_params(&[("type", "album")])
96            .build();
97
98        let client = SingleTestClient::new_raw(endpoint, "");
99
100        let endpoint = SearchForItem::new(
101            "remaster track:Doxy artist:Miles Davis",
102            [SearchType::Album],
103        );
104
105        api::ignore(endpoint).query(&client).unwrap();
106    }
107
108    #[test]
109    fn test_search_for_item_endpoint_with_include_external() {
110        let endpoint = ExpectedUrl::builder()
111            .endpoint("search")
112            .add_query_params(&[("q", "remaster%20track:Doxy%20artist:Miles%20Davis")])
113            .add_query_params(&[("type", "album")])
114            .add_query_params(&[("include_external", "audio")])
115            .build();
116        let client = SingleTestClient::new_raw(endpoint, "");
117
118        let endpoint = SearchForItem::new(
119            "remaster track:Doxy artist:Miles Davis",
120            [SearchType::Album],
121        )
122        .include_external(IncludeExternalType::Audio);
123
124        api::ignore(endpoint).query(&client).unwrap();
125    }
126}