wcrb-now-playing

CLI to get the current playing track on WCRB

git clone https://code.pdelong.com/wcrb-now-playing.git

 1use std::fmt::Display;
 2
 3mod json;
 4
 5const NOW_PLAYING_URL: &str = "https://api.composer.nprstations.org/v1/widget/53877c98e1c80a130decb6c8/now?format=json&style=v2&show_song=true";
 6
 7struct Track {
 8    name: String,
 9    composer: String,
10}
11
12impl Display for Track {
13    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
14        write!(f, "{}: {}", self.composer, self.name)
15    }
16}
17
18#[derive(Default)]
19struct Current {
20    // The current program or show.  This may be unset during transitions.
21    program: Option<String>,
22    // The current song.  This is expected to be unset for some programs (e.g. BSO livestreams) and
23    // also during transitions.
24    track: Option<Track>,
25}
26
27impl Current {
28    fn fetch(url: &str) -> Result<Current, anyhow::Error> {
29        let body: json::Root = ureq::get(url).call()?.into_json()?;
30
31        Ok(Current {
32            program: body.on_now.program.map(|p| p.name),
33            track: body.on_now.song.map(|s| Track {
34                name: s.track_name,
35                composer: s.composer_name,
36            }),
37        })
38    }
39}
40
41impl Display for Current {
42    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
43        match (&self.track, &self.program) {
44            (Some(track), _) => write!(f, "{track}"),
45            (None, Some(program)) => write!(f, "{program}"),
46            (None, None) => write!(f, "UNKNOWN"),
47        }
48    }
49}
50
51fn main() {
52    match Current::fetch(NOW_PLAYING_URL) {
53        Ok(c) => println!("{c}"),
54        Err(err) => {
55            eprintln!("failed to fetch: {err}");
56            std::process::exit(1)
57        }
58    }
59}