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.
Unlike on_retry, this fires only when a previously initialized connection drops, which means that you should prefer
on_retry instead if you want more accurate responses to the initial connect or handshake failures, and on_disconnect
for reacting to post-connection failures.
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}