pub struct PresenceRunner { /* private fields */ }Expand description
A runner that manages the Discord RPC background task. Create a runner, configure it, run it to get a client handle, then clone the handle for sharing.
Implementations§
Source§impl PresenceRunner
impl PresenceRunner
Sourcepub fn new(client_id: impl Into<String>) -> Self
pub fn new(client_id: impl Into<String>) -> Self
Create a new PresenceRunner instance. Requires the client ID of your chosen app from the
Discord Developer Portal.
Examples found in repository?
4async fn main() -> Result<(), PresenceError> {
5 let mut runner = PresenceRunner::new("1463450870480900160")
6 .show_errors()
7 .on_disconnect(|reason| {
8 eprintln!("discord rpc disconnected: {reason:?}");
9 });
10
11 runner.run(false).await?;
12 runner.wait().await?;
13
14 Ok(())
15}More examples
4async fn main() -> Result<(), PresenceError> {
5 let mut runner = PresenceRunner::new("1463450870480900160");
6
7 let activity = Activity::new()
8 .name("cool app name")
9 .details("Something?")
10 .state("Probably~")
11 .build()?;
12
13 let client = runner.run(true).await?;
14 client.set_activity(activity).await?;
15
16 // indefinitely block here
17 runner.wait().await?;
18
19 Ok(())
20}13async fn main() -> Result<(), PresenceError> {
14 // simple atomic counter
15 let count = Arc::new(AtomicUsize::new(0));
16
17 let mut runner = PresenceRunner::new("1463450870480900160")
18 .on_ready(|data| println!("Connected to user: {}", data.user.username()))
19 .on_activity_send(move |_| {
20
21 // increments the counter with every send_activity()
22 let val = count.fetch_add(1, Ordering::Relaxed) + 1;
23
24 println!("Activity {val} sent successfully.")
25
26 })
27 .show_errors() // enables verbose error logging
28 ;
29
30 // create activities for later use
31 let activity_1 = Activity::new()
32 .details("this runs")
33 .state("for ten seconds")
34 .build()?;
35
36 let activity_2 = Activity::new()
37 .details("believe it")
38 .state("or not")
39 .build()?;
40
41 let closing_activity = Activity::new()
42 .details("closing presence in...")
43 .duration(Duration::from_secs(5))
44 .small_image("status")
45 .build()?;
46
47 // first run
48 let client = runner.run(true).await?;
49
50 client.set_activity(activity_1).await?;
51 sleep(Duration::from_secs(5)).await;
52 client.set_activity(activity_2).await?;
53 sleep(Duration::from_secs(5)).await;
54 client.set_activity(closing_activity).await?;
55 sleep(Duration::from_secs(5)).await;
56
57 client.close().await?;
58
59 println!("Stopped.");
60
61 Ok(())
62}8async fn main() -> Result<(), PresenceError> {
9 let mut runner = PresenceRunner::new("1463450870480900160")
10 .on_ready(|data| {
11 println!(
12 "RPC version: v{}; Connected to user: {}",
13 data.version(),
14 data.user.global_name().unwrap_or_default(),
15 )
16 })
17 .on_activity_send(|data| {
18 println!(
19 "Activity sent to app! (running on {})\nCreated at: {}",
20 data.platform().unwrap_or_default(),
21 data.activity.created_at()
22 );
23 })
24 .on_disconnect(|f| println!("Disconnected: {f:?}"))
25 .show_errors() // enables verbose error logging
26 .on_retry(move |c| {
27 if c % 10 == 0 {
28 println!("Retry count {c}; is Discord open?");
29 }
30 });
31
32 let client = runner.run(true).await?;
33
34 // the activity can include any combination of builder function calls
35 let activity = Activity::new()
36 .activity_type(ActivityType::Playing)
37 .details("epic game")
38 .details_url("https://github.com/hitblast")
39 .status_display_type(StatusDisplayType::Details)
40 .large_image("game_icon")
41 .large_text("Playing a game")
42 .large_url("https://hitblast.github.io/")
43 .small_image("status")
44 .small_text("Online")
45 .build()?;
46
47 client.set_activity(activity).await?;
48
49 // indefinitely block here
50 runner.wait().await?;
51
52 Ok(())
53}Sourcepub fn on_ready<F: Fn(ReadyData) + Send + Sync + 'static>(self, f: F) -> Self
pub fn on_ready<F: Fn(ReadyData) + Send + Sync + 'static>(self, f: F) -> Self
Runs a particular closure after receiving a READY event.
This can fire multiple times depending on how many times the client needs to disconnect and reconnect.
Examples found in repository?
13async fn main() -> Result<(), PresenceError> {
14 // simple atomic counter
15 let count = Arc::new(AtomicUsize::new(0));
16
17 let mut runner = PresenceRunner::new("1463450870480900160")
18 .on_ready(|data| println!("Connected to user: {}", data.user.username()))
19 .on_activity_send(move |_| {
20
21 // increments the counter with every send_activity()
22 let val = count.fetch_add(1, Ordering::Relaxed) + 1;
23
24 println!("Activity {val} sent successfully.")
25
26 })
27 .show_errors() // enables verbose error logging
28 ;
29
30 // create activities for later use
31 let activity_1 = Activity::new()
32 .details("this runs")
33 .state("for ten seconds")
34 .build()?;
35
36 let activity_2 = Activity::new()
37 .details("believe it")
38 .state("or not")
39 .build()?;
40
41 let closing_activity = Activity::new()
42 .details("closing presence in...")
43 .duration(Duration::from_secs(5))
44 .small_image("status")
45 .build()?;
46
47 // first run
48 let client = runner.run(true).await?;
49
50 client.set_activity(activity_1).await?;
51 sleep(Duration::from_secs(5)).await;
52 client.set_activity(activity_2).await?;
53 sleep(Duration::from_secs(5)).await;
54 client.set_activity(closing_activity).await?;
55 sleep(Duration::from_secs(5)).await;
56
57 client.close().await?;
58
59 println!("Stopped.");
60
61 Ok(())
62}More examples
8async fn main() -> Result<(), PresenceError> {
9 let mut runner = PresenceRunner::new("1463450870480900160")
10 .on_ready(|data| {
11 println!(
12 "RPC version: v{}; Connected to user: {}",
13 data.version(),
14 data.user.global_name().unwrap_or_default(),
15 )
16 })
17 .on_activity_send(|data| {
18 println!(
19 "Activity sent to app! (running on {})\nCreated at: {}",
20 data.platform().unwrap_or_default(),
21 data.activity.created_at()
22 );
23 })
24 .on_disconnect(|f| println!("Disconnected: {f:?}"))
25 .show_errors() // enables verbose error logging
26 .on_retry(move |c| {
27 if c % 10 == 0 {
28 println!("Retry count {c}; is Discord open?");
29 }
30 });
31
32 let client = runner.run(true).await?;
33
34 // the activity can include any combination of builder function calls
35 let activity = Activity::new()
36 .activity_type(ActivityType::Playing)
37 .details("epic game")
38 .details_url("https://github.com/hitblast")
39 .status_display_type(StatusDisplayType::Details)
40 .large_image("game_icon")
41 .large_text("Playing a game")
42 .large_url("https://hitblast.github.io/")
43 .small_image("status")
44 .small_text("Online")
45 .build()?;
46
47 client.set_activity(activity).await?;
48
49 // indefinitely block here
50 runner.wait().await?;
51
52 Ok(())
53}Sourcepub fn on_activity_send<F: Fn(ActivityResponseData) + Send + Sync + 'static>(
self,
f: F,
) -> Self
pub fn on_activity_send<F: Fn(ActivityResponseData) + Send + Sync + 'static>( self, f: F, ) -> Self
Run a particular closure after ensuring that a PresenceClient::set_activity has successfully managed to pass its data through the IPC channel.
This can fire multiple times.
Examples found in repository?
13async fn main() -> Result<(), PresenceError> {
14 // simple atomic counter
15 let count = Arc::new(AtomicUsize::new(0));
16
17 let mut runner = PresenceRunner::new("1463450870480900160")
18 .on_ready(|data| println!("Connected to user: {}", data.user.username()))
19 .on_activity_send(move |_| {
20
21 // increments the counter with every send_activity()
22 let val = count.fetch_add(1, Ordering::Relaxed) + 1;
23
24 println!("Activity {val} sent successfully.")
25
26 })
27 .show_errors() // enables verbose error logging
28 ;
29
30 // create activities for later use
31 let activity_1 = Activity::new()
32 .details("this runs")
33 .state("for ten seconds")
34 .build()?;
35
36 let activity_2 = Activity::new()
37 .details("believe it")
38 .state("or not")
39 .build()?;
40
41 let closing_activity = Activity::new()
42 .details("closing presence in...")
43 .duration(Duration::from_secs(5))
44 .small_image("status")
45 .build()?;
46
47 // first run
48 let client = runner.run(true).await?;
49
50 client.set_activity(activity_1).await?;
51 sleep(Duration::from_secs(5)).await;
52 client.set_activity(activity_2).await?;
53 sleep(Duration::from_secs(5)).await;
54 client.set_activity(closing_activity).await?;
55 sleep(Duration::from_secs(5)).await;
56
57 client.close().await?;
58
59 println!("Stopped.");
60
61 Ok(())
62}More examples
8async fn main() -> Result<(), PresenceError> {
9 let mut runner = PresenceRunner::new("1463450870480900160")
10 .on_ready(|data| {
11 println!(
12 "RPC version: v{}; Connected to user: {}",
13 data.version(),
14 data.user.global_name().unwrap_or_default(),
15 )
16 })
17 .on_activity_send(|data| {
18 println!(
19 "Activity sent to app! (running on {})\nCreated at: {}",
20 data.platform().unwrap_or_default(),
21 data.activity.created_at()
22 );
23 })
24 .on_disconnect(|f| println!("Disconnected: {f:?}"))
25 .show_errors() // enables verbose error logging
26 .on_retry(move |c| {
27 if c % 10 == 0 {
28 println!("Retry count {c}; is Discord open?");
29 }
30 });
31
32 let client = runner.run(true).await?;
33
34 // the activity can include any combination of builder function calls
35 let activity = Activity::new()
36 .activity_type(ActivityType::Playing)
37 .details("epic game")
38 .details_url("https://github.com/hitblast")
39 .status_display_type(StatusDisplayType::Details)
40 .large_image("game_icon")
41 .large_text("Playing a game")
42 .large_url("https://hitblast.github.io/")
43 .small_image("status")
44 .small_text("Online")
45 .build()?;
46
47 client.set_activity(activity).await?;
48
49 // indefinitely block here
50 runner.wait().await?;
51
52 Ok(())
53}Sourcepub fn on_disconnect<F: Fn(DisconnectReason) + Send + Sync + 'static>(
self,
f: F,
) -> Self
pub fn on_disconnect<F: Fn(DisconnectReason) + Send + Sync + 'static>( self, f: F, ) -> Self
Runs a particular closure after the RPC connection is lost.
This can fire multiple times depending on how many times the client disconnects and reconnects again.
Examples found in repository?
4async fn main() -> Result<(), PresenceError> {
5 let mut runner = PresenceRunner::new("1463450870480900160")
6 .show_errors()
7 .on_disconnect(|reason| {
8 eprintln!("discord rpc disconnected: {reason:?}");
9 });
10
11 runner.run(false).await?;
12 runner.wait().await?;
13
14 Ok(())
15}More examples
8async fn main() -> Result<(), PresenceError> {
9 let mut runner = PresenceRunner::new("1463450870480900160")
10 .on_ready(|data| {
11 println!(
12 "RPC version: v{}; Connected to user: {}",
13 data.version(),
14 data.user.global_name().unwrap_or_default(),
15 )
16 })
17 .on_activity_send(|data| {
18 println!(
19 "Activity sent to app! (running on {})\nCreated at: {}",
20 data.platform().unwrap_or_default(),
21 data.activity.created_at()
22 );
23 })
24 .on_disconnect(|f| println!("Disconnected: {f:?}"))
25 .show_errors() // enables verbose error logging
26 .on_retry(move |c| {
27 if c % 10 == 0 {
28 println!("Retry count {c}; is Discord open?");
29 }
30 });
31
32 let client = runner.run(true).await?;
33
34 // the activity can include any combination of builder function calls
35 let activity = Activity::new()
36 .activity_type(ActivityType::Playing)
37 .details("epic game")
38 .details_url("https://github.com/hitblast")
39 .status_display_type(StatusDisplayType::Details)
40 .large_image("game_icon")
41 .large_text("Playing a game")
42 .large_url("https://hitblast.github.io/")
43 .small_image("status")
44 .small_text("Online")
45 .build()?;
46
47 client.set_activity(activity).await?;
48
49 // indefinitely block here
50 runner.wait().await?;
51
52 Ok(())
53}Sourcepub fn on_retry<F: Fn(usize) + Send + Sync + 'static>(self, f: F) -> Self
pub fn on_retry<F: Fn(usize) + Send + Sync + 'static>(self, f: F) -> Self
Runs a particular closure when retrying for socket creation or handshake.
This can fire multiple times, or for a limited amount depending on the amount of maximum
retries that has been set (through PresenceRunner::set_max_retries).
The closure parameter is the count of retries done at the time of its execution.
Examples found in repository?
8async fn main() -> Result<(), PresenceError> {
9 let mut runner = PresenceRunner::new("1463450870480900160")
10 .on_ready(|data| {
11 println!(
12 "RPC version: v{}; Connected to user: {}",
13 data.version(),
14 data.user.global_name().unwrap_or_default(),
15 )
16 })
17 .on_activity_send(|data| {
18 println!(
19 "Activity sent to app! (running on {})\nCreated at: {}",
20 data.platform().unwrap_or_default(),
21 data.activity.created_at()
22 );
23 })
24 .on_disconnect(|f| println!("Disconnected: {f:?}"))
25 .show_errors() // enables verbose error logging
26 .on_retry(move |c| {
27 if c % 10 == 0 {
28 println!("Retry count {c}; is Discord open?");
29 }
30 });
31
32 let client = runner.run(true).await?;
33
34 // the activity can include any combination of builder function calls
35 let activity = Activity::new()
36 .activity_type(ActivityType::Playing)
37 .details("epic game")
38 .details_url("https://github.com/hitblast")
39 .status_display_type(StatusDisplayType::Details)
40 .large_image("game_icon")
41 .large_text("Playing a game")
42 .large_url("https://hitblast.github.io/")
43 .small_image("status")
44 .small_text("Online")
45 .build()?;
46
47 client.set_activity(activity).await?;
48
49 // indefinitely block here
50 runner.wait().await?;
51
52 Ok(())
53}Sourcepub fn show_errors(self) -> Self
pub fn show_errors(self) -> Self
Enable verbose error logging over std::io::stderr writes for RPC and code events.
Examples found in repository?
4async fn main() -> Result<(), PresenceError> {
5 let mut runner = PresenceRunner::new("1463450870480900160")
6 .show_errors()
7 .on_disconnect(|reason| {
8 eprintln!("discord rpc disconnected: {reason:?}");
9 });
10
11 runner.run(false).await?;
12 runner.wait().await?;
13
14 Ok(())
15}More examples
13async fn main() -> Result<(), PresenceError> {
14 // simple atomic counter
15 let count = Arc::new(AtomicUsize::new(0));
16
17 let mut runner = PresenceRunner::new("1463450870480900160")
18 .on_ready(|data| println!("Connected to user: {}", data.user.username()))
19 .on_activity_send(move |_| {
20
21 // increments the counter with every send_activity()
22 let val = count.fetch_add(1, Ordering::Relaxed) + 1;
23
24 println!("Activity {val} sent successfully.")
25
26 })
27 .show_errors() // enables verbose error logging
28 ;
29
30 // create activities for later use
31 let activity_1 = Activity::new()
32 .details("this runs")
33 .state("for ten seconds")
34 .build()?;
35
36 let activity_2 = Activity::new()
37 .details("believe it")
38 .state("or not")
39 .build()?;
40
41 let closing_activity = Activity::new()
42 .details("closing presence in...")
43 .duration(Duration::from_secs(5))
44 .small_image("status")
45 .build()?;
46
47 // first run
48 let client = runner.run(true).await?;
49
50 client.set_activity(activity_1).await?;
51 sleep(Duration::from_secs(5)).await;
52 client.set_activity(activity_2).await?;
53 sleep(Duration::from_secs(5)).await;
54 client.set_activity(closing_activity).await?;
55 sleep(Duration::from_secs(5)).await;
56
57 client.close().await?;
58
59 println!("Stopped.");
60
61 Ok(())
62}8async fn main() -> Result<(), PresenceError> {
9 let mut runner = PresenceRunner::new("1463450870480900160")
10 .on_ready(|data| {
11 println!(
12 "RPC version: v{}; Connected to user: {}",
13 data.version(),
14 data.user.global_name().unwrap_or_default(),
15 )
16 })
17 .on_activity_send(|data| {
18 println!(
19 "Activity sent to app! (running on {})\nCreated at: {}",
20 data.platform().unwrap_or_default(),
21 data.activity.created_at()
22 );
23 })
24 .on_disconnect(|f| println!("Disconnected: {f:?}"))
25 .show_errors() // enables verbose error logging
26 .on_retry(move |c| {
27 if c % 10 == 0 {
28 println!("Retry count {c}; is Discord open?");
29 }
30 });
31
32 let client = runner.run(true).await?;
33
34 // the activity can include any combination of builder function calls
35 let activity = Activity::new()
36 .activity_type(ActivityType::Playing)
37 .details("epic game")
38 .details_url("https://github.com/hitblast")
39 .status_display_type(StatusDisplayType::Details)
40 .large_image("game_icon")
41 .large_text("Playing a game")
42 .large_url("https://hitblast.github.io/")
43 .small_image("status")
44 .small_text("Online")
45 .build()?;
46
47 client.set_activity(activity).await?;
48
49 // indefinitely block here
50 runner.wait().await?;
51
52 Ok(())
53}Sourcepub fn set_max_retries(self, count: usize) -> Self
pub fn set_max_retries(self, count: usize) -> Self
Sets the amount of maximum retries to do on socket creation and handshakes before the runner should give up.
By default this is set to 0 internally, which means the inner loop would retry indefinitely.
Sourcepub async fn run(
&mut self,
wait_for_ready: bool,
) -> Result<&PresenceClient, PresenceRunnerError>
pub async fn run( &mut self, wait_for_ready: bool, ) -> Result<&PresenceClient, PresenceRunnerError>
Run the runner. Must be called before any client handle operations.
Examples found in repository?
4async fn main() -> Result<(), PresenceError> {
5 let mut runner = PresenceRunner::new("1463450870480900160")
6 .show_errors()
7 .on_disconnect(|reason| {
8 eprintln!("discord rpc disconnected: {reason:?}");
9 });
10
11 runner.run(false).await?;
12 runner.wait().await?;
13
14 Ok(())
15}More examples
4async fn main() -> Result<(), PresenceError> {
5 let mut runner = PresenceRunner::new("1463450870480900160");
6
7 let activity = Activity::new()
8 .name("cool app name")
9 .details("Something?")
10 .state("Probably~")
11 .build()?;
12
13 let client = runner.run(true).await?;
14 client.set_activity(activity).await?;
15
16 // indefinitely block here
17 runner.wait().await?;
18
19 Ok(())
20}13async fn main() -> Result<(), PresenceError> {
14 // simple atomic counter
15 let count = Arc::new(AtomicUsize::new(0));
16
17 let mut runner = PresenceRunner::new("1463450870480900160")
18 .on_ready(|data| println!("Connected to user: {}", data.user.username()))
19 .on_activity_send(move |_| {
20
21 // increments the counter with every send_activity()
22 let val = count.fetch_add(1, Ordering::Relaxed) + 1;
23
24 println!("Activity {val} sent successfully.")
25
26 })
27 .show_errors() // enables verbose error logging
28 ;
29
30 // create activities for later use
31 let activity_1 = Activity::new()
32 .details("this runs")
33 .state("for ten seconds")
34 .build()?;
35
36 let activity_2 = Activity::new()
37 .details("believe it")
38 .state("or not")
39 .build()?;
40
41 let closing_activity = Activity::new()
42 .details("closing presence in...")
43 .duration(Duration::from_secs(5))
44 .small_image("status")
45 .build()?;
46
47 // first run
48 let client = runner.run(true).await?;
49
50 client.set_activity(activity_1).await?;
51 sleep(Duration::from_secs(5)).await;
52 client.set_activity(activity_2).await?;
53 sleep(Duration::from_secs(5)).await;
54 client.set_activity(closing_activity).await?;
55 sleep(Duration::from_secs(5)).await;
56
57 client.close().await?;
58
59 println!("Stopped.");
60
61 Ok(())
62}8async fn main() -> Result<(), PresenceError> {
9 let mut runner = PresenceRunner::new("1463450870480900160")
10 .on_ready(|data| {
11 println!(
12 "RPC version: v{}; Connected to user: {}",
13 data.version(),
14 data.user.global_name().unwrap_or_default(),
15 )
16 })
17 .on_activity_send(|data| {
18 println!(
19 "Activity sent to app! (running on {})\nCreated at: {}",
20 data.platform().unwrap_or_default(),
21 data.activity.created_at()
22 );
23 })
24 .on_disconnect(|f| println!("Disconnected: {f:?}"))
25 .show_errors() // enables verbose error logging
26 .on_retry(move |c| {
27 if c % 10 == 0 {
28 println!("Retry count {c}; is Discord open?");
29 }
30 });
31
32 let client = runner.run(true).await?;
33
34 // the activity can include any combination of builder function calls
35 let activity = Activity::new()
36 .activity_type(ActivityType::Playing)
37 .details("epic game")
38 .details_url("https://github.com/hitblast")
39 .status_display_type(StatusDisplayType::Details)
40 .large_image("game_icon")
41 .large_text("Playing a game")
42 .large_url("https://hitblast.github.io/")
43 .small_image("status")
44 .small_text("Online")
45 .build()?;
46
47 client.set_activity(activity).await?;
48
49 // indefinitely block here
50 runner.wait().await?;
51
52 Ok(())
53}Sourcepub fn clone_handle(&self) -> PresenceClient
pub fn clone_handle(&self) -> PresenceClient
Returns a clone of the client handle for sharing.
Sourcepub async fn wait(&mut self) -> Result<(), PresenceRunnerError>
pub async fn wait(&mut self) -> Result<(), PresenceRunnerError>
Waits for the IPC task to finish.
NOTE: If there’s no join_handle present, the function will do nothing and
just return blank.
Examples found in repository?
4async fn main() -> Result<(), PresenceError> {
5 let mut runner = PresenceRunner::new("1463450870480900160")
6 .show_errors()
7 .on_disconnect(|reason| {
8 eprintln!("discord rpc disconnected: {reason:?}");
9 });
10
11 runner.run(false).await?;
12 runner.wait().await?;
13
14 Ok(())
15}More examples
4async fn main() -> Result<(), PresenceError> {
5 let mut runner = PresenceRunner::new("1463450870480900160");
6
7 let activity = Activity::new()
8 .name("cool app name")
9 .details("Something?")
10 .state("Probably~")
11 .build()?;
12
13 let client = runner.run(true).await?;
14 client.set_activity(activity).await?;
15
16 // indefinitely block here
17 runner.wait().await?;
18
19 Ok(())
20}8async fn main() -> Result<(), PresenceError> {
9 let mut runner = PresenceRunner::new("1463450870480900160")
10 .on_ready(|data| {
11 println!(
12 "RPC version: v{}; Connected to user: {}",
13 data.version(),
14 data.user.global_name().unwrap_or_default(),
15 )
16 })
17 .on_activity_send(|data| {
18 println!(
19 "Activity sent to app! (running on {})\nCreated at: {}",
20 data.platform().unwrap_or_default(),
21 data.activity.created_at()
22 );
23 })
24 .on_disconnect(|f| println!("Disconnected: {f:?}"))
25 .show_errors() // enables verbose error logging
26 .on_retry(move |c| {
27 if c % 10 == 0 {
28 println!("Retry count {c}; is Discord open?");
29 }
30 });
31
32 let client = runner.run(true).await?;
33
34 // the activity can include any combination of builder function calls
35 let activity = Activity::new()
36 .activity_type(ActivityType::Playing)
37 .details("epic game")
38 .details_url("https://github.com/hitblast")
39 .status_display_type(StatusDisplayType::Details)
40 .large_image("game_icon")
41 .large_text("Playing a game")
42 .large_url("https://hitblast.github.io/")
43 .small_image("status")
44 .small_text("Online")
45 .build()?;
46
47 client.set_activity(activity).await?;
48
49 // indefinitely block here
50 runner.wait().await?;
51
52 Ok(())
53}