Skip to main content

koan_core/remote/
scrobbling.rs

1//! The signed-in account's scrobbling, set up through its koan server
2//! (`koanScrobbling`). The server holds the ListenBrainz token and sends the
3//! plays, so the apps only ask, connect and disconnect. The sending is
4//! `crate::scrobbling`'s, on the server.
5
6use crate::config::Config;
7use crate::db::queries::scrobbling::LISTENBRAINZ;
8use crate::remote::client::{KoanScrobbleService, SubsonicClient, SubsonicError};
9
10#[derive(Debug, thiserror::Error)]
11pub enum ScrobblingError {
12    #[error("no server is signed in")]
13    NotSignedIn,
14    #[error(transparent)]
15    Remote(#[from] SubsonicError),
16}
17
18fn client() -> Result<std::sync::Arc<SubsonicClient>, ScrobblingError> {
19    crate::helpers::subsonic_client(&Config::load().unwrap_or_default())
20        .ok_or(ScrobblingError::NotSignedIn)
21}
22
23fn listenbrainz(services: Vec<KoanScrobbleService>) -> Option<KoanScrobbleService> {
24    services.into_iter().find(|s| s.name == LISTENBRAINZ)
25}
26
27/// The account's ListenBrainz connection, if it has one.
28pub fn status() -> Result<Option<KoanScrobbleService>, ScrobblingError> {
29    Ok(listenbrainz(client()?.koan_scrobbling()?.service))
30}
31
32/// Connect the account's ListenBrainz with a user token. A token
33/// ListenBrainz refuses comes back as the server's message.
34pub fn connect(token: &str) -> Result<Option<KoanScrobbleService>, ScrobblingError> {
35    Ok(listenbrainz(
36        client()?.koan_scrobbling_connect(token)?.service,
37    ))
38}
39
40pub fn disconnect() -> Result<(), ScrobblingError> {
41    client()?.koan_scrobbling_disconnect()?;
42    Ok(())
43}