Skip to main content

filthy_rich/
client.rs

1use anyhow::anyhow;
2use tokio::sync::{mpsc::Sender, oneshot};
3
4use crate::types::{Activity, IPCCommand};
5
6/// A client handle for communicating with [`super::PresenceRunner`] and its inner loop.
7#[derive(Debug, Clone)]
8pub struct PresenceClient {
9    pub(crate) tx: Sender<IPCCommand>,
10    pub(crate) client_id: String,
11}
12
13impl PresenceClient {
14    /// Returns the client ID.
15    #[must_use]
16    pub fn client_id(&self) -> String {
17        self.client_id.clone()
18    }
19
20    /// Sets/updates the Discord Rich presence activity.
21    /// The runner must be started before calling this.
22    pub async fn set_activity(&self, activity: Activity) -> Result<(), anyhow::Error> {
23        self.tx
24            .send(IPCCommand::SetActivity {
25                activity: Box::new(activity),
26            })
27            .await
28            .map_err(|_| anyhow!("Connection has already been closed."))?;
29
30        Ok(())
31    }
32
33    /// Clears a previously set Discord Rich Presence activity.
34    pub async fn clear_activity(&self) -> Result<(), anyhow::Error> {
35        self.tx
36            .send(IPCCommand::ClearActivity)
37            .await
38            .map_err(|_| anyhow!("Connection has already been closed."))?;
39
40        Ok(())
41    }
42
43    /// Closes the current connection if any.
44    pub async fn close(&self) -> Result<(), anyhow::Error> {
45        let (done_tx, done_rx) = oneshot::channel::<()>();
46
47        if self
48            .tx
49            .send(IPCCommand::Close { done: done_tx })
50            .await
51            .is_err()
52        {
53            return Ok(());
54        }
55
56        done_rx.await?;
57
58        Ok(())
59    }
60}