Skip to main content

filthy_rich/
client.rs

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