[ MIRROR ] Command line tool for interacting with Teal.fm git.ngill.net/onyx.git
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132use std::{io::BufRead, path::PathBuf};
use jacquard::client::{Agent, AgentSessionExt};use jacquard_api::fm_teal::alpha::feed as fm_teal_feed;use owo_colors::OwoColorize;
use crate::{ LogFormat, auth::GenericSession, error::OnyxError, parser::{LogParser, audio_scrobbler::AudioScrobblerParser, json::JsonParser}, record::Play,};
pub struct Scrobbler { pub service: String, pub version: String,
agent: Agent<GenericSession>,}
impl Scrobbler { pub fn new(service: &str, version: &str, session: GenericSession) -> Self { Self { service: service.to_owned(), version: version.to_owned(), agent: Agent::from(session), } }
fn generate_client_agent(&self, id: Option<String>) -> String { if let Some(id) = id { format!("{}/{} ({})", self.service, self.version, id) } else { format!("{}/{}", self.service, self.version) } }
pub async fn scrobble_track(&self, mut track: Play) -> Result<(), OnyxError> { let name = track.track_name.clone();
let res = async { track.submission_client_agent = Some(self.generate_client_agent(track.submission_client_agent)); let play: fm_teal_feed::play::Play = track.into(); self.agent.create_record(play, None).await } .await;
if let Err(e) = res { println!("{} {}", "[✗]".red().bold(), name); return Err(OnyxError::Other(format!("{}, for '{}'", e, name).into())); } else { println!("{} {}", "[✓]".green().bold(), name); }
Ok(()) }
pub async fn scrobble_logfile( &self, path: PathBuf, format: LogFormat, ) -> Result<(), OnyxError> { println!( "{} {}", "scrobbling log:".dimmed(), path.to_str().unwrap().dimmed() );
let tracks = match format { LogFormat::AudioScrobbler => <AudioScrobblerParser as LogParser>::parse(path.clone()), LogFormat::Json => <JsonParser as LogParser>::parse(path.clone()), }?;
let count = tracks.len(); let mut errors = Vec::new();
for track in tracks { if let Err(e) = self.scrobble_track(track).await { errors.push(e); } }
if !errors.is_empty() { println!("\n{}:", "errors".red().bold());
for error in &errors { println!(" - {}", error); }
println!( "\n{}: {} tracks submitted, {} failed", "summary".yellow().bold(), count - errors.len(), errors.len() );
return Err(OnyxError::Other( format!( "failed to scrobble log file {}, see errors above", path.to_str().unwrap() ) .into(), )); } else { println!("\n{}: {} tracks submitted", "success".green().bold(), count); }
Ok(()) }
pub async fn scrobble_lines<R>(&self, reader: R) -> Result<(), OnyxError> where R: BufRead, { for msg in reader.lines() { let msg = msg?;
if msg.trim().is_empty() { // skip empty messages continue; }
let msg: Play = serde_json::from_str(&msg)?; self.scrobble_track(msg).await?; }
Ok(()) }}