aboutsummaryrefslogtreecommitdiff
path: root/src/model/gateway.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/model/gateway.rs')
-rw-r--r--src/model/gateway.rs188
1 files changed, 152 insertions, 36 deletions
diff --git a/src/model/gateway.rs b/src/model/gateway.rs
index dc25d0d..826f723 100644
--- a/src/model/gateway.rs
+++ b/src/model/gateway.rs
@@ -1,29 +1,40 @@
+use serde::de::Error as DeError;
+use serde_json;
use std::sync::{Arc, RwLock};
use super::utils::*;
use super::*;
-use ::internal::prelude::*;
-impl Game {
- #[doc(hidden)]
- pub fn decode(value: Value) -> Result<Option<Game>> {
- let mut map = into_map(value)?;
-
- let name = match map.remove("name") {
- Some(Value::Null) | None => return Ok(None),
- Some(v) => into_string(v)?,
- };
-
- if name.trim().is_empty() {
- return Ok(None);
- }
+/// A representation of the data retrieved from the bot gateway endpoint.
+///
+/// This is different from the [`Gateway`], as this includes the number of
+/// shards that Discord recommends to use for a bot user.
+///
+/// This is only applicable to bot users.
+#[derive(Clone, Debug, Deserialize)]
+pub struct BotGateway {
+ /// The number of shards that is recommended to be used by the current bot
+ /// user.
+ pub shards: u64,
+ /// The gateway to connect to.
+ pub url: String,
+}
- Ok(Some(Game {
- name: name,
- kind: opt(&mut map, "type", GameType::decode)?.unwrap_or(GameType::Playing),
- url: opt(&mut map, "url", into_string)?,
- }))
- }
+/// Representation of a game that a [`User`] is playing -- or streaming in the
+/// case that a stream URL is provided.
+#[derive(Clone, Debug)]
+pub struct Game {
+ /// The type of game status.
+ pub kind: GameType,
+ /// The name of the game being played.
+ pub name: String,
+ /// The Stream URL if [`kind`] is [`GameType::Streaming`].
+ ///
+ /// [`GameType::Streaming`]: enum.GameType.html#variant.Streaming
+ /// [`kind`]: #structfield.kind
+ pub url: Option<String>,
+}
+impl Game {
/// Creates a `Game` struct that appears as a `Playing <name>` status.
///
/// **Note**: Maximum `name` length is 128.
@@ -47,31 +58,136 @@ impl Game {
}
}
-impl Presence {
- #[doc(hidden)]
- pub fn decode(value: Value) -> Result<Presence> {
- let mut value = into_map(value)?;
- let mut user_map = remove(&mut value, "user").and_then(into_map)?;
+impl Deserialize for Game {
+ fn deserialize<D: Deserializer>(deserializer: D) -> StdResult<Self, D::Error> {
+ let mut map = JsonMap::deserialize(deserializer)?;
+ let kind = map.remove("type")
+ .and_then(|v| GameType::deserialize(v).ok())
+ .unwrap_or(GameType::Playing);
+ let name = map.remove("name")
+ .and_then(|v| String::deserialize(v).ok())
+ .unwrap_or_else(String::new);
+ let url = map.remove("url").and_then(|v| serde_json::from_value::<String>(v).ok());
+
+ Ok(Game {
+ kind: kind,
+ name: name,
+ url: url
+ })
+ }
+}
+
+enum_number!(
+ /// The type of activity that is being performed when playing a game.
+ GameType {
+ /// An indicator that the user is playing a game.
+ Playing = 0,
+ /// An indicator that the user is streaming to a service.
+ Streaming = 1,
+ }
+);
+
+impl Default for GameType {
+ fn default() -> Self {
+ GameType::Playing
+ }
+}
+
+/// A representation of the data retrieved from the gateway endpoint.
+///
+/// For the bot-specific gateway, refer to [`BotGateway`].
+///
+/// [`BotGateway`]: struct.BotGateway.html
+#[derive(Clone, Debug, Deserialize)]
+pub struct Gateway {
+ /// The gateway to connect to.
+ pub url: String,
+}
+
+/// Information detailing the current online status of a [`User`].
+///
+/// [`User`]: struct.User.html
+#[derive(Clone, Debug)]
+pub struct Presence {
+ /// The game that a [`User`] is current playing.
+ ///
+ /// [`User`]: struct.User.html
+ pub game: Option<Game>,
+ /// The date of the last presence update.
+ pub last_modified: Option<u64>,
+ /// The nickname of the member, if applicable.
+ pub nick: Option<String>,
+ /// The user's online status.
+ pub status: OnlineStatus,
+ /// The Id of the [`User`]. Can be used to calculate the user's creation
+ /// date.
+ pub user_id: UserId,
+ /// The associated user instance.
+ pub user: Option<Arc<RwLock<User>>>,
+}
+
+impl Deserialize for Presence {
+ fn deserialize<D: Deserializer>(deserializer: D) -> StdResult<Presence, D::Error> {
+ let mut map = JsonMap::deserialize(deserializer)?;
+ let mut user_map = map.remove("user")
+ .ok_or_else(|| DeError::custom("expected presence user"))
+ .and_then(JsonMap::deserialize)
+ .map_err(DeError::custom)?;
let (user_id, user) = if user_map.len() > 1 {
- let user = User::decode(Value::Object(user_map))?;
- (user.id, Some(user))
+ let user = User::deserialize(Value::Object(user_map)).map_err(DeError::custom)?;
+
+ (user.id, Some(Arc::new(RwLock::new(user))))
} else {
- (remove(&mut user_map, "id").and_then(UserId::decode)?, None)
+ let user_id = user_map.remove("id")
+ .ok_or_else(|| DeError::custom("Missing presence user id"))
+ .and_then(|x| UserId::deserialize(x.clone()))
+ .map_err(DeError::custom)?;
+
+ (user_id, None)
};
- let game = match value.remove("game") {
- None | Some(Value::Null) => None,
- Some(v) => Game::decode(v)?,
+ let game = match map.remove("game") {
+ Some(v) => serde_json::from_value::<Option<Game>>(v).map_err(DeError::custom)?,
+ None => None,
+ };
+ let last_modified = match map.remove("last_modified") {
+ Some(v) => Some(u64::deserialize(v).map_err(DeError::custom)?),
+ None => None,
+ };
+ let nick = match map.remove("nick") {
+ Some(v) => serde_json::from_value::<Option<String>>(v).map_err(DeError::custom)?,
+ None => None,
};
+ let status = map.remove("status")
+ .ok_or_else(|| DeError::custom("expected presence status"))
+ .and_then(OnlineStatus::deserialize)
+ .map_err(DeError::custom)?;
Ok(Presence {
- user_id: user_id,
- status: remove(&mut value, "status").and_then(OnlineStatus::decode_str)?,
- last_modified: opt(&mut value, "last_modified", |v| Ok(req!(v.as_u64())))?,
game: game,
- user: user.map(RwLock::new).map(Arc::new),
- nick: opt(&mut value, "nick", into_string)?,
+ last_modified: last_modified,
+ nick: nick,
+ status: status,
+ user: user,
+ user_id: user_id,
})
}
}
+
+/// An initial set of information given after IDENTIFYing to the gateway.
+#[derive(Clone, Debug, Deserialize)]
+pub struct Ready {
+ pub guilds: Vec<GuildStatus>,
+ #[serde(deserialize_with="deserialize_presences")]
+ pub presences: HashMap<UserId, Presence>,
+ #[serde(deserialize_with="deserialize_private_channels")]
+ pub private_channels: HashMap<ChannelId, Channel>,
+ pub session_id: String,
+ pub shard: Option<[u64; 2]>,
+ #[serde(default, rename="_trace")]
+ pub trace: Vec<String>,
+ pub user: CurrentUser,
+ #[serde(rename="v")]
+ pub version: u64,
+}