ytmapi_rs/
common.rs

1//! Re-usable core structures.
2// Intended to be for structures that are also suitable to be reused by other
3// libraries. As opposed to simply part of the interface.
4use serde::{Deserialize, Serialize};
5use std::borrow::Cow;
6
7/// A search suggestion containing a list of TextRuns.
8/// May be a history suggestion.
9#[derive(PartialEq, Debug, Clone, Deserialize)]
10#[non_exhaustive]
11pub struct SearchSuggestion {
12    pub runs: Vec<TextRun>,
13    pub suggestion_type: SuggestionType,
14}
15
16#[derive(PartialEq, Debug, Clone, Deserialize, Copy)]
17pub enum SuggestionType {
18    History,
19    Prediction,
20}
21
22/// A block of text that may be boldened.
23#[derive(PartialEq, Debug, Clone, Deserialize)]
24pub enum TextRun {
25    Bold(String),
26    Normal(String),
27}
28
29impl TextRun {
30    /// Take the text from the run, ignoring format.
31    pub fn take_text(self) -> String {
32        match self {
33            TextRun::Bold(s) => s,
34            TextRun::Normal(s) => s,
35        }
36    }
37    /// Get a reference to the text from the run, ignoring format.
38    pub fn get_text(&self) -> &str {
39        match self {
40            TextRun::Bold(s) => s,
41            TextRun::Normal(s) => s,
42        }
43    }
44}
45
46impl SearchSuggestion {
47    /// Gets the text of the runs concaternated into a String.
48    /// Note - allocates a new String.
49    pub fn get_text(&self) -> String {
50        self.runs
51            .iter()
52            .fold(String::new(), |acc, r| acc + r.get_text())
53    }
54    pub(crate) fn new(suggestion_type: SuggestionType, runs: Vec<TextRun>) -> Self {
55        Self {
56            runs,
57            suggestion_type,
58        }
59    }
60}
61
62#[derive(PartialEq, Debug, Clone, Deserialize, Serialize)]
63#[must_use]
64/// Indicates a result from an API action such as a 'delete playlist'
65pub enum ApiOutcome {
66    #[serde(alias = "STATUS_SUCCEEDED")]
67    Success,
68    #[serde(alias = "STATUS_FAILED")]
69    Failure,
70}
71
72#[derive(Debug, PartialEq, Clone, Deserialize, Serialize)]
73// Intentionally not marked non_exhaustive - not expecting this to change.
74pub struct Thumbnail {
75    pub height: u64,
76    pub width: u64,
77    pub url: String,
78}
79
80#[derive(PartialEq, Debug, Clone, Serialize, Deserialize)]
81/// Set of both taste tokens.
82// Intentionally not marked non_exhaustive - not expecting this to change.
83// TODO: constructor
84pub struct TasteToken<'a> {
85    pub impression_value: TasteTokenImpression<'a>,
86    pub selection_value: TasteTokenSelection<'a>,
87}
88
89/// Collection of required fields to identify and change library status.
90// Intentionally not marked non_exhaustive - not expecting this to change.
91#[derive(PartialEq, Clone, Debug, Deserialize, Serialize)]
92pub struct LibraryManager {
93    pub status: LibraryStatus,
94    pub add_to_library_token: FeedbackTokenAddToLibrary<'static>,
95    pub remove_from_library_token: FeedbackTokenRemoveFromLibrary<'static>,
96}
97
98#[derive(PartialEq, Clone, Debug, Deserialize, Serialize)]
99pub enum LibraryStatus {
100    #[serde(rename = "LIBRARY_SAVED")]
101    InLibrary,
102    #[serde(rename = "LIBRARY_ADD")]
103    NotInLibrary,
104}
105
106#[derive(Deserialize, Serialize, Clone, Debug, PartialEq)]
107pub enum LikeStatus {
108    #[serde(rename = "LIKE")]
109    Liked,
110    #[serde(rename = "DISLIKE")]
111    Disliked,
112    #[serde(rename = "INDIFFERENT")]
113    /// Indifferent means that the song has not been liked or disliked.
114    Indifferent,
115}
116
117#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
118pub enum Explicit {
119    IsExplicit,
120    NotExplicit,
121}
122
123#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
124pub enum AlbumType {
125    Single,
126    Album,
127    EP,
128}
129
130/// Type safe version of API ID used as part of YTM's interface.
131pub trait YoutubeID<'a> {
132    fn get_raw(&self) -> &str;
133    // TODO: Create fallible version for when parsing is required. This could
134    // possiby be a seperate trait YoutubeIDFallible
135    fn from_raw<S: Into<Cow<'a, str>>>(raw_str: S) -> Self;
136}
137
138#[derive(PartialEq, Debug, Clone, Serialize, Deserialize)]
139pub struct FeedbackTokenRemoveFromHistory<'a>(Cow<'a, str>);
140#[derive(PartialEq, Debug, Clone, Serialize, Deserialize)]
141pub struct FeedbackTokenAddToLibrary<'a>(Cow<'a, str>);
142#[derive(PartialEq, Debug, Clone, Serialize, Deserialize)]
143pub struct FeedbackTokenRemoveFromLibrary<'a>(Cow<'a, str>);
144#[derive(PartialEq, Debug, Clone, Serialize, Deserialize)]
145pub struct BrowseParams<'a>(Cow<'a, str>);
146#[derive(PartialEq, Debug, Clone, Serialize, Deserialize)]
147pub struct PodcastChannelParams<'a>(Cow<'a, str>);
148// TODO: Add parsing - PlaylistID begining with VL should fail.
149#[derive(PartialEq, Debug, Clone, Serialize, Deserialize)]
150pub struct PlaylistID<'a>(Cow<'a, str>);
151#[derive(PartialEq, Debug, Clone, Serialize, Deserialize)]
152pub struct AlbumID<'a>(Cow<'a, str>);
153#[derive(PartialEq, Debug, Clone, Serialize, Deserialize)]
154pub struct ArtistChannelID<'a>(Cow<'a, str>);
155#[derive(PartialEq, Debug, Clone, Serialize, Deserialize)]
156pub struct PodcastChannelID<'a>(Cow<'a, str>);
157#[derive(PartialEq, Debug, Clone, Serialize, Deserialize)]
158pub struct ContinuationParams<'a>(Cow<'a, str>);
159#[derive(PartialEq, Debug, Clone, Serialize, Deserialize)]
160pub struct ProfileID<'a>(Cow<'a, str>);
161#[derive(PartialEq, Debug, Clone, Serialize, Deserialize)]
162pub struct PodcastID<'a>(Cow<'a, str>);
163#[derive(PartialEq, Debug, Clone, Serialize, Deserialize)]
164pub struct EpisodeID<'a>(Cow<'a, str>);
165#[derive(PartialEq, Debug, Clone, Serialize, Deserialize)]
166pub struct VideoID<'a>(Cow<'a, str>);
167#[derive(PartialEq, Debug, Clone, Serialize, Deserialize)]
168pub struct UploadEntityID<'a>(Cow<'a, str>);
169#[derive(PartialEq, Debug, Clone, Serialize, Deserialize)]
170pub struct LyricsID<'a>(Cow<'a, str>);
171#[derive(PartialEq, Debug, Clone, Serialize, Deserialize)]
172pub struct SetVideoID<'a>(Cow<'a, str>);
173#[derive(PartialEq, Debug, Clone, Serialize, Deserialize)]
174pub struct UploadAlbumID<'a>(Cow<'a, str>);
175#[derive(PartialEq, Debug, Clone, Serialize, Deserialize)]
176pub struct UploadArtistID<'a>(Cow<'a, str>);
177#[derive(PartialEq, Debug, Clone, Serialize, Deserialize)]
178pub struct TasteTokenSelection<'a>(Cow<'a, str>);
179#[derive(PartialEq, Debug, Clone, Serialize, Deserialize)]
180pub struct TasteTokenImpression<'a>(Cow<'a, str>);
181#[derive(PartialEq, Debug, Clone, Serialize, Deserialize)]
182pub struct MoodCategoryParams<'a>(Cow<'a, str>);
183#[derive(PartialEq, Debug, Clone, Serialize, Deserialize)]
184pub struct SongTrackingUrl<'a>(Cow<'a, str>);
185
186impl_youtube_id!(UploadEntityID<'a>);
187impl_youtube_id!(SetVideoID<'a>);
188impl_youtube_id!(AlbumID<'a>);
189impl_youtube_id!(UploadAlbumID<'a>);
190impl_youtube_id!(UploadArtistID<'a>);
191impl_youtube_id!(ProfileID<'a>);
192impl_youtube_id!(PodcastID<'a>);
193impl_youtube_id!(EpisodeID<'a>);
194impl_youtube_id!(VideoID<'a>);
195impl_youtube_id!(PlaylistID<'a>);
196impl_youtube_id!(ArtistChannelID<'a>);
197impl_youtube_id!(PodcastChannelID<'a>);
198impl_youtube_id!(LyricsID<'a>);
199impl_youtube_id!(BrowseParams<'a>);
200impl_youtube_id!(PodcastChannelParams<'a>);
201impl_youtube_id!(ContinuationParams<'a>);
202impl_youtube_id!(FeedbackTokenRemoveFromHistory<'a>);
203impl_youtube_id!(FeedbackTokenRemoveFromLibrary<'a>);
204impl_youtube_id!(FeedbackTokenAddToLibrary<'a>);
205impl_youtube_id!(TasteTokenImpression<'a>);
206impl_youtube_id!(TasteTokenSelection<'a>);
207impl_youtube_id!(MoodCategoryParams<'a>);
208impl_youtube_id!(SongTrackingUrl<'a>);