1use serde::{Serialize, Deserialize};
2
3use crate::album::Album;
4use crate::annotation::Referent;
5use crate::user::{User, UserMetadata};
6use crate::{Body, Date};
7
8#[derive(Serialize, Deserialize, Debug)]
9pub struct Song {
10 pub annotation_count: u32,
12 pub api_path: String,
14 #[serde(skip_serializing_if = "Option::is_none")]
17 pub apple_music_id: Option<String>,
18 #[serde(skip_serializing_if = "Option::is_none")]
21 pub apple_music_player_url: Option<String>,
22 #[serde(skip_serializing_if = "Option::is_none")]
25 pub comment_count: Option<u32>,
26 #[serde(skip_serializing_if = "Option::is_none")]
29 pub custom_header_image_url: Option<String>,
30 #[serde(skip_serializing_if = "Option::is_none")]
33 pub custom_song_art_image_url: Option<String>,
34 #[serde(skip_serializing_if = "Option::is_none")]
37 pub description: Option<Body>,
38 #[serde(skip_serializing_if = "Option::is_none")]
41 pub description_preview: Option<String>,
42 #[serde(skip_serializing_if = "Option::is_none")]
45 pub embed_content: Option<String>,
46 #[serde(skip_serializing_if = "Option::is_none")]
49 pub facebook_share_message_without_url: Option<String>,
50 #[serde(skip_serializing_if = "Option::is_none")]
53 pub featured_video: Option<bool>,
54 pub full_title: String,
56 #[serde(skip_serializing_if = "Option::is_none")]
59 pub has_instagram_reel_annotations: Option<bool>,
60 pub header_image_thumbnail_url: String,
62 pub header_image_url: String,
64 #[serde(skip_serializing_if = "Option::is_none")]
67 pub hidden: Option<bool>,
68 pub id: u32,
70 #[serde(skip_serializing_if = "Option::is_none")]
73 pub instrumental: Option<bool>,
74 #[serde(skip_serializing_if = "Option::is_none")]
77 pub is_music: Option<bool>,
78 #[serde(skip_serializing_if = "Option::is_none")]
81 pub lyrics: Option<Body>,
82 pub lyrics_owner_id: u32,
84 pub lyrics_state: String,
86 #[serde(skip_serializing_if = "Option::is_none")]
89 pub lyrics_updated_at: Option<u64>,
90 pub path: String,
92 #[serde(skip_serializing_if = "Option::is_none")]
95 pub pending_lyrics_edits_count: Option<u32>,
96 #[serde(skip_serializing_if = "Option::is_none")]
99 pub published: Option<bool>,
100 #[serde(skip_serializing_if = "Option::is_none")]
102 pub pusher_channel: Option<String>,
103 #[serde(skip_serializing_if = "Option::is_none")]
106 pub release_date_components: Option<Date>,
107 #[serde(skip_serializing_if = "Option::is_none")]
109 pub pyongs_count: Option<u32>,
110 #[serde(skip_serializing_if = "Option::is_none")]
113 pub recording_location: Option<String>,
114 #[serde(skip_serializing_if = "Option::is_none")]
117 pub release_date: Option<String>,
118 #[serde(skip_serializing_if = "Option::is_none")]
121 pub release_date_for_display: Option<String>,
122 #[serde(skip_serializing_if = "Option::is_none")]
125 pub share_url: Option<String>,
126 pub song_art_image_thumbnail_url: String,
128 pub song_art_image_url: String,
130 #[serde(skip_serializing_if = "Option::is_none")]
133 pub soundcloud_url: Option<String>,
134 #[serde(skip_serializing_if = "Option::is_none")]
137 pub spotify_uuid: Option<String>,
138 pub stats: SongStatus,
140 pub title: String,
142 pub title_with_featured: String,
144 #[serde(skip_serializing_if = "Option::is_none")]
146 pub tracking_paths: Option<TrackingPaths>,
147 #[serde(skip_serializing_if = "Option::is_none")]
150 pub twitter_share_message: Option<String>,
151 #[serde(skip_serializing_if = "Option::is_none")]
154 pub twitter_share_message_without_url: Option<String>,
155 #[serde(skip_serializing_if = "Option::is_none")]
158 pub updated_by_human_at: Option<u64>,
159 pub url: String,
161 #[serde(skip_serializing_if = "Option::is_none")]
163 pub viewable_by_roles: Option<Vec<String>>,
164 #[serde(skip_serializing_if = "Option::is_none")]
167 pub youtube_start: Option<String>,
168 #[serde(skip_serializing_if = "Option::is_none")]
171 pub youtube_url: Option<String>,
172 #[serde(skip_serializing_if = "Option::is_none")]
175 pub current_user_metadata: Option<UserMetadata>,
176 pub primary_artist: Artist,
178 #[serde(skip_serializing_if = "Option::is_none")]
181 pub album: Option<Album>,
182 #[serde(skip_serializing_if = "Option::is_none")]
185 pub albums: Option<Vec<Album>>,
186 #[serde(skip_serializing_if = "Option::is_none")]
189 pub custom_performances: Option<Vec<SongPerformance>>,
190 #[serde(skip_serializing_if = "Option::is_none")]
193 pub description_annotation: Option<Referent>,
194 #[serde(skip_serializing_if = "Option::is_none")]
197 pub featured_artists: Option<Vec<Artist>>,
198 #[serde(skip_serializing_if = "Option::is_none")]
201 pub media: Option<Vec<SongMedia>>,
202 #[serde(skip_serializing_if = "Option::is_none")]
205 pub producer_artists: Option<Vec<Artist>>,
206 #[serde(skip_serializing_if = "Option::is_none")]
209 pub song_relationships: Option<Vec<SongRelationship>>,
210 #[serde(skip_serializing_if = "Option::is_none")]
213 pub verified_annotations_by: Option<Vec<User>>,
214 #[serde(skip_serializing_if = "Option::is_none")]
217 pub verified_contributors: Option<Vec<SongContributor>>,
218 #[serde(skip_serializing_if = "Option::is_none")]
221 pub verified_lyrics_by: Option<Vec<User>>,
222 #[serde(skip_serializing_if = "Option::is_none")]
225 pub writer_artists: Option<Vec<Artist>>,
226}
227
228#[derive(Serialize, Deserialize, Debug)]
229pub struct TrackingPaths {
230 pub aggregate: String,
231 pub concurrent: String,
232}
233
234#[derive(Serialize, Deserialize, Debug)]
235pub struct SongContributor {
236 pub contributions: Vec<String>,
237 pub artist: Artist,
238 #[serde(skip_serializing_if = "Option::is_none")]
239 pub user: Option<User>,
240}
241
242#[derive(Serialize, Deserialize, Debug)]
243pub struct SongRelationship {
244 pub relationship_type: String,
246 pub songs: Vec<Option<Song>>,
248}
249
250#[derive(Serialize, Deserialize, Debug)]
251pub struct SongPerformance {
252 pub label: String,
253 pub artists: Vec<Artist>,
254}
255
256#[derive(Serialize, Deserialize, Debug)]
257pub struct SongMedia {
258 #[serde(skip_serializing_if = "Option::is_none")]
260 pub native_uri: Option<String>,
261 #[serde(skip_serializing_if = "Option::is_none")]
263 pub attribution: Option<String>,
264 pub provider: String,
266 #[serde(skip_serializing_if = "Option::is_none")]
268 pub start: Option<u32>,
269 #[serde(rename = "type")]
271 pub media_type: String,
272 pub url: String,
274}
275
276#[derive(Serialize, Deserialize, Debug)]
277pub struct SongStatus {
278 #[serde(skip_serializing_if = "Option::is_none")]
280 pub accepted_annotations: Option<u32>,
281 #[serde(skip_serializing_if = "Option::is_none")]
283 pub contributors: Option<u32>,
284 #[serde(skip_serializing_if = "Option::is_none")]
286 pub iq_earners: Option<u32>,
287 #[serde(skip_serializing_if = "Option::is_none")]
289 pub transcribers: Option<u32>,
290 #[serde(skip_serializing_if = "Option::is_none")]
292 pub verified_annotations: Option<u32>,
293 pub unreviewed_annotations: u32,
295 pub hot: bool,
297 #[serde(skip_serializing_if = "Option::is_none")]
299 pub pageviews: Option<u32>,
300}
301
302#[derive(Serialize, Deserialize, Debug)]
303pub struct Artist {
304 pub api_path: String,
306 pub header_image_url: String,
308 pub id: u32,
310 pub image_url: String,
312 #[serde(skip_serializing_if = "Option::is_none")]
315 pub index_character: Option<char>,
316 pub is_meme_verified: bool,
318 pub is_verified: bool,
320 pub name: String,
322 #[serde(skip_serializing_if = "Option::is_none")]
324 pub slug: Option<String>,
325 pub url: String,
327 #[serde(skip_serializing_if = "Option::is_none")]
329 pub iq: Option<u32>,
330}