rustfm_scraper/models/
recent_tracks.rs1use chrono::prelude::*;
2use serde::Deserialize;
3
4#[derive(Debug, Deserialize)]
5pub struct RecentTracksResponse {
6 #[serde(rename = "recenttracks")]
7 pub recent_tracks: RecentTracks,
8}
9
10#[derive(Debug, Deserialize)]
11pub struct RecentTracks {
12 #[serde(rename = "@attr")]
13 pub attr: Attr,
14 #[serde(rename = "track")]
15 pub tracks: Vec<Track>,
16}
17
18#[derive(Debug, Deserialize)]
19pub struct Attr {
20 page: String,
21 #[serde(rename = "perPage")]
22 per_page: String,
23 user: String,
24 total: String,
25 #[serde(rename = "totalPages")]
26 total_pages: String,
27}
28
29impl Attr {
30 pub fn page(&self) -> i32 {
31 self.page.parse().unwrap_or(0)
32 }
33
34 pub fn per_page(&self) -> i32 {
35 self.per_page.parse().unwrap_or(0)
36 }
37
38 pub fn total_tracks(&self) -> i32 {
39 self.total.parse().unwrap_or(0)
40 }
41
42 pub fn total_pages(&self) -> i32 {
43 self.total_pages.parse().unwrap_or(0)
44 }
45
46 pub fn last_page(&self) -> bool {
47 self.page() == self.total_pages()
48 }
49
50 pub fn single_page(&self) -> bool {
51 self.total_pages() == 1
52 }
53
54 pub fn single_track(&self) -> bool {
55 self.total_tracks() == 1
56 }
57}
58
59#[derive(Clone, Debug, Deserialize)]
60pub struct Track {
61 #[serde(rename = "@attr")]
62 pub attr: Option<TrackAttr>,
63 pub artist: Artist,
64 pub album: Album,
65 pub streamable: String,
67 pub date: Option<Date>,
68 pub name: String,
69 pub mbid: String,
70 loved: String,
71}
72
73impl PartialEq for Track {
74 fn eq(&self, other: &Self) -> bool {
75 self.combined_title().eq(&other.combined_title())
76 }
77}
78
79impl Track {
80 pub fn combined_title(&self) -> String {
81 format!("{} - {} - {}", self.name, self.artist.name, self.album.text)
82 }
83
84 pub fn loved(&self) -> bool {
85 self.loved == "1"
86 }
87
88 pub fn now_playing(&self) -> bool {
89 match &self.attr {
90 Some(attr) => attr.now_playing == "true",
91 None => false,
92 }
93 }
94
95 pub fn date(&self) -> Date {
96 self.date.clone().unwrap()
97 }
98}
99
100#[derive(Clone, Debug, Deserialize)]
101pub struct TrackAttr {
102 #[serde(rename = "nowplaying")]
103 now_playing: String,
104}
105
106#[derive(Clone, Debug, Deserialize)]
107pub struct Artist {
108 pub url: String,
109 pub mbid: String,
110 pub name: String,
111}
112
113#[derive(Clone, Debug, Deserialize)]
114pub struct Album {
115 pub mbid: String,
116 #[serde(rename = "#text")]
117 pub text: String,
118}
119
120#[derive(Clone, Debug, Deserialize)]
121pub struct Date {
122 uts: String,
123 #[serde(rename = "#text")]
124 text: String,
125}
126
127impl Date {
128 pub fn time_stamp(&self) -> i64 {
129 let timestamp: i64 = self.uts.parse().unwrap();
130 let dt = NaiveDateTime::from_timestamp(timestamp, 0);
131
132 dt.timestamp()
133 }
134
135 pub fn datetime_utc(&self) -> DateTime<Utc> {
136 DateTime::<Utc>::from_utc(NaiveDateTime::from_timestamp(self.time_stamp(), 0), Utc)
137 }
138
139 pub fn datetime_local(&self) -> DateTime<Local> {
140 let dt = self.datetime_utc().naive_utc();
141
142 Local::from_utc_datetime(&Local, &dt)
143 }
144}