1pub use discord_presence;
4
5pub mod config;
6
7pub mod plugin {
9 use std::ops::DerefMut;
10
11 use bevy::{app::{Plugin, Startup, Update}, log::{debug, error, warn}, prelude::{Deref, Event, EventReader, ResMut, Resource}};
12 use discord_presence::{models::Activity, Client as DiscordClient, DiscordError};
13
14 use crate::config::RPCPlugin;
15
16 #[derive(Resource, Deref)]
17 struct Client(DiscordClient);
18
19 #[derive(Event, Deref)]
21 pub struct ActivityUpdate(pub Activity);
22
23 impl Default for ActivityUpdate {
25 fn default() -> Self {
26 Self(Activity::default())
27 }
28 }
29
30 impl DerefMut for Client {
31 fn deref_mut(&mut self) -> &mut Self::Target {
32 &mut self.0
33 }
34 }
35
36 impl Client {
37 pub fn new(client_id: u64) -> Self {
38 let rpc = DiscordClient::new(client_id);
39 rpc.on_error(|e| error!("DiscordClient got an error: {e:#?}")).persist();
40
41 Client(rpc)
42 }
43 }
44
45 impl Plugin for RPCPlugin {
46 fn build(&self, app: &mut bevy::prelude::App) {
47 let cc = &self.config;
48
49 app.add_systems(Startup, startup_client);
50 app.add_systems(Update, update_activity);
51
52 app.insert_resource(Client::new(cc.app_id));
53 app.add_event::<ActivityUpdate>();
54 }
55
56 fn name(&self) -> &str {
57 "Discord Presence"
58 }
59 }
60
61 fn startup_client(mut client: ResMut<Client>) {
62 client.0.start();
63 }
64
65 fn update_activity(mut client: ResMut<Client>, mut activity_update: EventReader<ActivityUpdate>) {
66 let event = match activity_update.read().next() {
67 Some(v) => v,
68 None => return,
69 };
70
71 let activity = &event.0; __update_activity(&mut client, activity)
74 }
75
76 fn __update_activity(client: &mut DiscordClient, activity: &Activity) {
77 let update_err = match client.set_activity(|_| { activity.clone() }) {
78 Ok(v) => {
79 debug!("Activity updated: {v:#?}");
80 return;
81 },
82 Err(e) => e
83 };
84
85 match update_err {
86 DiscordError::IoError(error) => error!("Discord RPC error occurred: {error}"),
87 DiscordError::SendMessage(error) => error!("An MPSC send error occurred: {error}"),
88 DiscordError::CloseError(error) => error!("An MPSC send error occurred: {error}"),
89 DiscordError::ReceiveError(error) => error!("An MPSC receive error occurred: {error}"),
90 DiscordError::MPSCReceiveError(error) => error!("An MPSC receive error occurred: {error}"),
91 DiscordError::MPSCTimeout(error) => error!("The MPSC channel timed out: {error}"),
92 DiscordError::TimeoutError(error) => error!("The MPSC channel timed out: {error}"),
93 DiscordError::JsonError(error) => error!("A JSON serialization error occurred: {error}"),
94 DiscordError::ThreadError => error!("A discord_presence thread ran into an unexpected error."),
95 DiscordError::NoneError(_) => error!("The library discord_presence unwrapped an Option<T> on a None value"),
96 DiscordError::Conversion => error!("An unspecified conversion error occurred"),
97 DiscordError::SubscriptionFailed => error!("An event subscription error occurred"),
98 DiscordError::ConnectionClosed => error!("The connection was unexpectedly closed"),
99 DiscordError::NotStarted => error!("The client has not started yet!"),
100 DiscordError::EventLoopError => error!("The MPSC send & receive loop ran into an error"),
101 DiscordError::NoChangesMade => warn!("No changes were made to the event handle"),
102 DiscordError::ThreadInUse => error!("The RPC thread is in use"),
103 }
104 }
105}