diff options
| -rw-r--r-- | src/client/connection.rs | 77 | ||||
| -rw-r--r-- | src/client/context.rs | 32 |
2 files changed, 103 insertions, 6 deletions
diff --git a/src/client/connection.rs b/src/client/connection.rs index 8937710..02075d6 100644 --- a/src/client/connection.rs +++ b/src/client/connection.rs @@ -70,6 +70,8 @@ impl Display for ConnectionError { } } +type CurrentPresence = (Option<Game>, OnlineStatus, bool); + /// A connection is a handler for a websocket connection to Discord's gateway. /// The connection allows for sending and receiving messages over the websocket, /// such as setting the active game, reconnecting, syncing guilds, and more. @@ -134,6 +136,7 @@ impl Display for ConnectionError { /// [`receive`]: #method.receive /// [docs]: https://discordapp.com/developers/docs/topics/gateway#sharding pub struct Connection { + current_presence: CurrentPresence, keepalive_channel: MpscSender<Status>, last_sequence: u64, login_type: LoginType, @@ -212,6 +215,7 @@ impl Connection { Ok((feature_voice! {{ Connection { + current_presence: (None, OnlineStatus::Online, false), keepalive_channel: tx.clone(), last_sequence: sequence, login_type: login_type, @@ -223,6 +227,7 @@ impl Connection { } } else { Connection { + current_presence: (None, OnlineStatus::Online, false), keepalive_channel: tx.clone(), last_sequence: sequence, login_type: login_type, @@ -238,11 +243,62 @@ impl Connection { self.shard_info } - pub fn set_game(&self, game: Option<Game>) { - self.set_presence(game, OnlineStatus::Online, false) + /// Sets whether the current user is afk. This helps Discord determine where + /// to send notifications. + /// + /// Other presence settings are maintained. + pub fn set_afk(&mut self, afk: bool) { + self.current_presence.2 = afk; + + self.update_presence(); + } + + /// Sets the user's current game, if any. + /// + /// Other presence settings are maintained. + pub fn set_game(&mut self, game: Option<Game>) { + self.current_presence.0 = game; + + self.update_presence(); + } + + /// Sets the user's current online status. + /// + /// Note that [`Offline`] is not a valid presence, so it is automatically + /// converted to [`Invisible`]. + /// + /// Other presence settings are maintained. + pub fn set_status(&mut self, online_status: OnlineStatus) { + self.current_presence.1 = match online_status { + OnlineStatus::Offline => OnlineStatus::Invisible, + other => other, + }; + + self.update_presence(); } - pub fn set_presence(&self, + /// Sets the user's full presence information. + /// + /// Consider using the individual setters if you only need to modify one of + /// these. + /// + /// # Examples + /// + /// Set the current user as playing `"Heroes of the Storm"`, being online, + /// and not being afk: + /// + /// ```rust,no_run + /// use serenity::model::{Game, OnlineStatus}; + /// + /// // assuming you are in a context + /// + /// context.connection.lock() + /// .unwrap() + /// .set_presence(Game::playing("Heroes of the Storm"), + /// OnlineStatus::Online, + /// false); + /// ``` + pub fn set_presence(&mut self, game: Option<Game>, status: OnlineStatus, afk: bool) { @@ -250,6 +306,15 @@ impl Connection { OnlineStatus::Offline => OnlineStatus::Invisible, other => other, }; + + self.current_presence = (game, status, afk); + + self.update_presence(); + } + + fn update_presence(&self) { + let (ref game, status, afk) = self.current_presence; + let msg = ObjectBuilder::new() .insert("op", OpCode::StatusUpdate.num()) .insert_object("d", move |mut object| { @@ -257,10 +322,10 @@ impl Connection { .insert("afk", afk) .insert("status", status.name()); - match game { - Some(game) => { + match game.as_ref() { + Some(ref game) => { object.insert_object("game", move |o| o - .insert("name", game.name)) + .insert("name", &game.name)) }, None => object.insert("game", Value::Null), } diff --git a/src/client/context.rs b/src/client/context.rs index d262096..e2d9fe2 100644 --- a/src/client/context.rs +++ b/src/client/context.rs @@ -1218,6 +1218,38 @@ impl Context { http::send_message(channel_id.into().0, Value::Object(map)) } + /// Sets the current user as being [`Online`]. This maintains the current + /// game and `afk` setting. + /// + /// [`Online`]: ../model/enum.OnlineStatus.html#variant.Online + pub fn online(&self) { + self.connection.lock().unwrap().set_status(OnlineStatus::Online); + } + + /// Sets the current user as being [`Idle`]. This maintains the current + /// game and `afk` setting. + /// + /// [`Idle`]: ../model/enum.OnlineStatus.html#variant.Idle + pub fn idle(&self) { + self.connection.lock().unwrap().set_status(OnlineStatus::Idle); + } + + /// Sets the current user as being [`DoNotDisturb`]. This maintains the + /// current game and `afk` setting. + /// + /// [`DoNotDisturb`]: ../model/enum.OnlineStatus.html#variant.DoNotDisturb + pub fn dnd(&self) { + self.connection.lock().unwrap().set_status(OnlineStatus::DoNotDisturb); + } + + /// Sets the current user as being [`Invisible`]. This maintains the current + /// game and `afk` setting. + /// + /// [`Invisible`]: ../model/enum.OnlineStatus.html#variant.Invisible + pub fn invisible(&self) { + self.connection.lock().unwrap().set_status(OnlineStatus::Invisible); + } + /// "Resets" the current user's presence, by setting the game to `None`, /// the online status to [`Online`], and `afk` to `false`. /// |