A decentralized music tracking and discovery platform built on AT Protocol 🎵 rocksky.app
spotify atproto lastfm musicbrainz scrobbling listenbrainz
98
fork

Configure Feed

Select the types of activity you want to include in your feed.

feat: add normalize_date function for date formatting and validation

+80 -4
+32
crates/scrobbler/src/musicbrainz/mod.rs
··· 1 + use anyhow::Error; 2 + 1 3 use crate::musicbrainz::{recording::Recordings, release::Release}; 2 4 use std::cmp::Ordering; 3 5 ··· 179 181 9_999_01_01 180 182 } 181 183 184 + pub fn normalize_date(d: Option<&str>) -> Result<Option<String>, Error> { 185 + if let Some(d) = d { 186 + let mut parts = d.split('-'); 187 + let y = parts.next().unwrap_or("9999"); 188 + let m = parts.next().unwrap_or("01"); 189 + let day = parts.next().unwrap_or("01"); 190 + 191 + let y: i32 = y.parse().unwrap_or(9999); 192 + let m: i32 = m.parse().unwrap_or(1); 193 + let day: i32 = day.parse().unwrap_or(1); 194 + 195 + if y == 9999 { 196 + return Err(Error::msg("Invalid date")); 197 + } 198 + 199 + return Ok(Some(format!("{:04}-{:02}-{:02}", y, m, day))); 200 + } 201 + Ok(None) 202 + } 203 + 182 204 fn is_live_release(rel: &Release) -> bool { 183 205 let t_live = rel.title.to_ascii_lowercase().contains("live"); 184 206 let d_live = rel ··· 209 231 assert_eq!(date_key(Some("2020")), 20200101); 210 232 assert_eq!(date_key(None), 99990101); 211 233 assert_eq!(date_key(Some("invalid-date")), 99990101); 234 + } 235 + 236 + #[test] 237 + fn test_normalize_date() -> Result<(), Error> { 238 + assert_eq!(normalize_date(Some("2020-5-3"))?, Some("2020-05-03".into())); 239 + assert_eq!(normalize_date(Some("2020-05"))?, Some("2020-05-01".into())); 240 + assert_eq!(normalize_date(Some("2020"))?, Some("2020-01-01".into())); 241 + assert_eq!(normalize_date(None)?, None); 242 + assert!(normalize_date(Some("invalid-date")).is_err()); 243 + Ok(()) 212 244 } 213 245 214 246 #[test]
+8 -2
crates/scrobbler/src/types.rs
··· 1 1 use serde::{Deserialize, Serialize}; 2 2 3 - use crate::{musicbrainz, spotify, xata}; 3 + use crate::{ 4 + musicbrainz::{self, normalize_date}, 5 + spotify, xata, 6 + }; 4 7 5 8 #[derive(Debug, Deserialize, Clone)] 6 9 pub struct Scrobble { ··· 77 80 .first() 78 81 .map(|release| release.title.clone()) 79 82 .unwrap_or_default(); 80 - let release_date = releases.first().and_then(|release| release.date.clone()); 83 + let release_date = releases 84 + .first() 85 + .and_then(|release| release.date.clone()) 86 + .and_then(|date| normalize_date(Some(&date)).unwrap_or(None)); 81 87 Track { 82 88 title: recording.title.clone(), 83 89 album,
+32
crates/webscrobbler/src/musicbrainz/mod.rs
··· 1 + use anyhow::Error; 2 + 1 3 use crate::musicbrainz::{recording::Recordings, release::Release}; 2 4 use std::cmp::Ordering; 3 5 ··· 179 181 9_999_01_01 180 182 } 181 183 184 + pub fn normalize_date(d: Option<&str>) -> Result<Option<String>, Error> { 185 + if let Some(d) = d { 186 + let mut parts = d.split('-'); 187 + let y = parts.next().unwrap_or("9999"); 188 + let m = parts.next().unwrap_or("01"); 189 + let day = parts.next().unwrap_or("01"); 190 + 191 + let y: i32 = y.parse().unwrap_or(9999); 192 + let m: i32 = m.parse().unwrap_or(1); 193 + let day: i32 = day.parse().unwrap_or(1); 194 + 195 + if y == 9999 { 196 + return Err(Error::msg("Invalid date")); 197 + } 198 + 199 + return Ok(Some(format!("{:04}-{:02}-{:02}", y, m, day))); 200 + } 201 + Ok(None) 202 + } 203 + 182 204 fn is_live_release(rel: &Release) -> bool { 183 205 let t_live = rel.title.to_ascii_lowercase().contains("live"); 184 206 let d_live = rel ··· 209 231 assert_eq!(date_key(Some("2020")), 20200101); 210 232 assert_eq!(date_key(None), 99990101); 211 233 assert_eq!(date_key(Some("invalid-date")), 99990101); 234 + } 235 + 236 + #[test] 237 + fn test_normalize_date() -> Result<(), Error> { 238 + assert_eq!(normalize_date(Some("2020-5-3"))?, Some("2020-05-03".into())); 239 + assert_eq!(normalize_date(Some("2020-05"))?, Some("2020-05-01".into())); 240 + assert_eq!(normalize_date(Some("2020"))?, Some("2020-01-01".into())); 241 + assert_eq!(normalize_date(None)?, None); 242 + assert!(normalize_date(Some("invalid-date")).is_err()); 243 + Ok(()) 212 244 } 213 245 214 246 #[test]
+8 -2
crates/webscrobbler/src/types.rs
··· 1 1 use serde::{Deserialize, Serialize}; 2 2 3 - use crate::{musicbrainz, spotify, xata}; 3 + use crate::{ 4 + musicbrainz::{self, normalize_date}, 5 + spotify, xata, 6 + }; 4 7 5 8 #[derive(Deserialize, Debug, Clone)] 6 9 pub struct Connector { ··· 161 164 .map(|credit| credit.name.clone()) 162 165 .unwrap_or_default(); 163 166 let releases = recording.releases.unwrap_or_default(); 164 - let release_date = releases.first().and_then(|release| release.date.clone()); 167 + let release_date = releases 168 + .first() 169 + .and_then(|release| release.date.clone()) 170 + .and_then(|date| normalize_date(Some(&date)).unwrap_or(None)); 165 171 let album_artist = releases 166 172 .first() 167 173 .and_then(|release| {