···11use crate::mbz::{FindMbzData, try_find_mbz_data};
22use chrono::prelude::*;
33-use duckdb::{Connection, DuckdbConnectionManager, params};
33+use duckdb::{Connection, DuckdbConnectionManager, OptionalExt, params};
44use jacquard::types::datetime::Datetime;
55use jacquard_api::app_rocksky::scrobble::Scrobble as RockskyScrobble;
66use jacquard_api::fm_teal::alpha::feed::play::Play as TealAlphaPlay;
···1616 let created = scrobble.played_time.unwrap_or(Datetime::now());
1717 let created = created.as_ref().to_utc();
18181919- // TODO: check track name and time (and artist?) to see if there's already been a scrobble.
2020- // this is notably an issue with the dual rocksky-teal records.
1919+ if let Some(rkey) = check_duplicate_scrobble(&conn, did, &scrobble.track_name, created)? {
2020+ tracing::debug!("skipping duplicate scrobble of {rkey}");
2121+ return Ok(());
2222+ }
21232224 let artist = scrobble
2325 .artists
···4547 let conn = db.connect()?;
4648 let created = scrobble.created_at.as_ref().to_utc();
47494848- // TODO: check track name and time (and artist?) to see if there's already been a scrobble.
4949- // this is notably an issue with the dual rocksky-teal records.
5050+ if let Some(rkey) = check_duplicate_scrobble(&conn, did, &scrobble.title, created)? {
5151+ tracing::debug!("skipping duplicate scrobble of {rkey}");
5252+ return Ok(());
5353+ }
50545155 let find = FindMbzData {
5256 release_name: Some(&scrobble.album),
···104108105109 Ok(())
106110}
111111+112112+fn check_duplicate_scrobble(
113113+ conn: &Connection,
114114+ did: &str,
115115+ track: &str,
116116+ created: DateTime<Utc>,
117117+) -> eyre::Result<Option<String>> {
118118+ let mut stmt = conn.prepare_cached(
119119+ "SELECT rkey FROM scrobbles WHERE did = $1 AND track_name = $2 AND created_at = $3",
120120+ )?;
121121+122122+ let rkey = stmt
123123+ .query_one(params![did, track, created], |row| row.get(0))
124124+ .optional()?;
125125+126126+ Ok(rkey)
127127+}