use super::{
search_query_header, AuthToken, PostMethod, PostQuery, Query, SearchQuery, SearchType,
SpellingMode, SEARCH_QUERY_PATH, SPECIALIZED_PLAYLIST_EXACT_MATCH_PARAMS,
SPECIALIZED_PLAYLIST_PREFIX_PARAMS, SPECIALIZED_PLAYLIST_WITH_SUGGESTIONS_PARAMS,
};
use crate::parse::{
SearchResultAlbum, SearchResultArtist, SearchResultEpisode, SearchResultFeaturedPlaylist,
SearchResultPlaylist, SearchResultPodcast, SearchResultProfile, SearchResultSong,
SearchResultVideo,
};
use std::borrow::Cow;
pub trait FilteredSearchType: Default {
fn filtered_param_bits(&self) -> Cow<str>;
fn filtered_spelling_param(&self, spelling_mode: &SpellingMode) -> Cow<str> {
match spelling_mode {
SpellingMode::ExactMatch => "AWoMEA4QChADEAQQCRAF".into(),
SpellingMode::WithSuggestions => "AUICCAFqDBAOEAoQAxAEEAkQBQ%3D%3D".into(),
}
}
fn filtered_prefix_param(&self) -> Cow<str> {
"EgWKAQ".into()
}
}
#[derive(Default, Debug, Clone, PartialEq)]
pub struct FilteredSearch<F: FilteredSearchType> {
pub(crate) filter: F,
}
#[derive(Default, PartialEq, Debug, Clone)]
pub struct SongsFilter;
#[derive(Default, PartialEq, Debug, Clone)]
pub struct VideosFilter;
#[derive(Default, PartialEq, Debug, Clone)]
pub struct AlbumsFilter;
#[derive(Default, PartialEq, Debug, Clone)]
pub struct ArtistsFilter;
#[derive(Default, PartialEq, Debug, Clone)]
pub struct PlaylistsFilter;
#[derive(Default, PartialEq, Debug, Clone)]
pub struct CommunityPlaylistsFilter;
#[derive(Default, PartialEq, Debug, Clone)]
pub struct FeaturedPlaylistsFilter;
#[derive(Default, PartialEq, Debug, Clone)]
pub struct EpisodesFilter;
#[derive(Default, PartialEq, Debug, Clone)]
pub struct PodcastsFilter;
#[derive(Default, PartialEq, Debug, Clone)]
pub struct ProfilesFilter;
impl<F: FilteredSearchType> SearchType for FilteredSearch<F> {
fn specialised_params(&self, spelling_mode: &SpellingMode) -> Option<Cow<str>> {
Some(
format!(
"{}{}{}",
self.filter.filtered_prefix_param(),
self.filter.filtered_param_bits(),
self.filter.filtered_spelling_param(spelling_mode),
)
.into(),
)
}
}
impl FilteredSearchType for SongsFilter {
fn filtered_param_bits(&self) -> Cow<str> {
"II".into()
}
}
impl FilteredSearchType for VideosFilter {
fn filtered_param_bits(&self) -> Cow<str> {
"IQ".into()
}
}
impl FilteredSearchType for AlbumsFilter {
fn filtered_param_bits(&self) -> Cow<str> {
"IY".into()
}
}
impl FilteredSearchType for ArtistsFilter {
fn filtered_param_bits(&self) -> Cow<str> {
"Ig".into()
}
}
impl FilteredSearchType for PlaylistsFilter {
fn filtered_param_bits(&self) -> Cow<str> {
"".into()
}
fn filtered_spelling_param(&self, spelling_mode: &SpellingMode) -> Cow<str> {
match spelling_mode {
SpellingMode::ExactMatch => "MABCAggBagoQBBADEAkQBRAK",
SpellingMode::WithSuggestions => "MABqChAEEAMQCRAFEAo%3D",
}
.into()
}
fn filtered_prefix_param(&self) -> Cow<str> {
"Eg-KAQwIABAAGAAgACgB".into()
}
}
impl FilteredSearchType for CommunityPlaylistsFilter {
fn filtered_param_bits(&self) -> Cow<str> {
"EA".into()
}
fn filtered_spelling_param(&self, spelling_mode: &SpellingMode) -> Cow<str> {
match spelling_mode {
SpellingMode::ExactMatch => SPECIALIZED_PLAYLIST_EXACT_MATCH_PARAMS,
SpellingMode::WithSuggestions => SPECIALIZED_PLAYLIST_WITH_SUGGESTIONS_PARAMS,
}
.into()
}
fn filtered_prefix_param(&self) -> Cow<str> {
SPECIALIZED_PLAYLIST_PREFIX_PARAMS.into()
}
}
impl FilteredSearchType for FeaturedPlaylistsFilter {
fn filtered_param_bits(&self) -> Cow<str> {
"Dg".into()
}
fn filtered_spelling_param(&self, spelling_mode: &SpellingMode) -> Cow<str> {
match spelling_mode {
SpellingMode::ExactMatch => SPECIALIZED_PLAYLIST_EXACT_MATCH_PARAMS,
SpellingMode::WithSuggestions => SPECIALIZED_PLAYLIST_WITH_SUGGESTIONS_PARAMS,
}
.into()
}
fn filtered_prefix_param(&self) -> Cow<str> {
SPECIALIZED_PLAYLIST_PREFIX_PARAMS.into()
}
}
impl FilteredSearchType for EpisodesFilter {
fn filtered_param_bits(&self) -> Cow<str> {
"JI".into()
}
}
impl FilteredSearchType for PodcastsFilter {
fn filtered_param_bits(&self) -> Cow<str> {
"JQ".into()
}
}
impl FilteredSearchType for ProfilesFilter {
fn filtered_param_bits(&self) -> Cow<str> {
"JY".into()
}
}
impl<A: AuthToken> Query<A> for SearchQuery<'_, FilteredSearch<SongsFilter>> {
type Output = Vec<SearchResultSong>;
type Method = PostMethod;
}
impl PostQuery for SearchQuery<'_, FilteredSearch<SongsFilter>> {
fn header(&self) -> serde_json::Map<String, serde_json::Value> {
search_query_header(self)
}
fn path(&self) -> &str {
SEARCH_QUERY_PATH
}
fn params(&self) -> Vec<(&str, Cow<str>)> {
vec![]
}
}
impl<A: AuthToken> Query<A> for SearchQuery<'_, FilteredSearch<PlaylistsFilter>> {
type Output = Vec<SearchResultPlaylist>;
type Method = PostMethod;
}
impl PostQuery for SearchQuery<'_, FilteredSearch<PlaylistsFilter>> {
fn header(&self) -> serde_json::Map<String, serde_json::Value> {
search_query_header(self)
}
fn path(&self) -> &str {
SEARCH_QUERY_PATH
}
fn params(&self) -> Vec<(&str, Cow<str>)> {
vec![]
}
}
impl<A: AuthToken> Query<A> for SearchQuery<'_, FilteredSearch<CommunityPlaylistsFilter>> {
type Output = Vec<SearchResultPlaylist>;
type Method = PostMethod;
}
impl PostQuery for SearchQuery<'_, FilteredSearch<CommunityPlaylistsFilter>> {
fn header(&self) -> serde_json::Map<String, serde_json::Value> {
search_query_header(self)
}
fn path(&self) -> &str {
SEARCH_QUERY_PATH
}
fn params(&self) -> Vec<(&str, Cow<str>)> {
vec![]
}
}
impl<A: AuthToken> Query<A> for SearchQuery<'_, FilteredSearch<AlbumsFilter>> {
type Output = Vec<SearchResultAlbum>;
type Method = PostMethod;
}
impl PostQuery for SearchQuery<'_, FilteredSearch<AlbumsFilter>> {
fn header(&self) -> serde_json::Map<String, serde_json::Value> {
search_query_header(self)
}
fn path(&self) -> &str {
SEARCH_QUERY_PATH
}
fn params(&self) -> Vec<(&str, Cow<str>)> {
vec![]
}
}
impl<A: AuthToken> Query<A> for SearchQuery<'_, FilteredSearch<ArtistsFilter>> {
type Output = Vec<SearchResultArtist>;
type Method = PostMethod;
}
impl PostQuery for SearchQuery<'_, FilteredSearch<ArtistsFilter>> {
fn header(&self) -> serde_json::Map<String, serde_json::Value> {
search_query_header(self)
}
fn path(&self) -> &str {
SEARCH_QUERY_PATH
}
fn params(&self) -> Vec<(&str, Cow<str>)> {
vec![]
}
}
impl<A: AuthToken> Query<A> for SearchQuery<'_, FilteredSearch<FeaturedPlaylistsFilter>> {
type Output = Vec<SearchResultFeaturedPlaylist>;
type Method = PostMethod;
}
impl PostQuery for SearchQuery<'_, FilteredSearch<FeaturedPlaylistsFilter>> {
fn header(&self) -> serde_json::Map<String, serde_json::Value> {
search_query_header(self)
}
fn path(&self) -> &str {
SEARCH_QUERY_PATH
}
fn params(&self) -> Vec<(&str, Cow<str>)> {
vec![]
}
}
impl<A: AuthToken> Query<A> for SearchQuery<'_, FilteredSearch<EpisodesFilter>> {
type Output = Vec<SearchResultEpisode>;
type Method = PostMethod;
}
impl PostQuery for SearchQuery<'_, FilteredSearch<EpisodesFilter>> {
fn header(&self) -> serde_json::Map<String, serde_json::Value> {
search_query_header(self)
}
fn path(&self) -> &str {
SEARCH_QUERY_PATH
}
fn params(&self) -> Vec<(&str, Cow<str>)> {
vec![]
}
}
impl<A: AuthToken> Query<A> for SearchQuery<'_, FilteredSearch<PodcastsFilter>> {
type Output = Vec<SearchResultPodcast>;
type Method = PostMethod;
}
impl PostQuery for SearchQuery<'_, FilteredSearch<PodcastsFilter>> {
fn header(&self) -> serde_json::Map<String, serde_json::Value> {
search_query_header(self)
}
fn path(&self) -> &str {
SEARCH_QUERY_PATH
}
fn params(&self) -> Vec<(&str, Cow<str>)> {
vec![]
}
}
impl<A: AuthToken> Query<A> for SearchQuery<'_, FilteredSearch<VideosFilter>> {
type Output = Vec<SearchResultVideo>;
type Method = PostMethod;
}
impl PostQuery for SearchQuery<'_, FilteredSearch<VideosFilter>> {
fn header(&self) -> serde_json::Map<String, serde_json::Value> {
search_query_header(self)
}
fn path(&self) -> &str {
SEARCH_QUERY_PATH
}
fn params(&self) -> Vec<(&str, Cow<str>)> {
vec![]
}
}
impl<A: AuthToken> Query<A> for SearchQuery<'_, FilteredSearch<ProfilesFilter>> {
type Output = Vec<SearchResultProfile>;
type Method = PostMethod;
}
impl PostQuery for SearchQuery<'_, FilteredSearch<ProfilesFilter>> {
fn header(&self) -> serde_json::Map<String, serde_json::Value> {
search_query_header(self)
}
fn path(&self) -> &str {
SEARCH_QUERY_PATH
}
fn params(&self) -> Vec<(&str, Cow<str>)> {
vec![]
}
}