diff --git a/src/connection.rs b/src/connection.rs index a53a9610..05729927 100644 --- a/src/connection.rs +++ b/src/connection.rs @@ -226,8 +226,8 @@ impl Connection { if let Event::VoiceStateUpdate(server_id, ref voice_state) = event { self.voice(server_id).__update_state(voice_state); } - if let Event::VoiceServerUpdate { server_id, channel_id: _, ref endpoint, ref token } = event { - self.voice(server_id).__update_server(endpoint, token); + if let Event::VoiceServerUpdate(ref update) = event { + self.voice(update.server_id).__update_server(&update.endpoint, &update.token); } } return Ok(event); diff --git a/src/model.rs b/src/model.rs index b2883fea..2c0614c2 100644 --- a/src/model.rs +++ b/src/model.rs @@ -1775,6 +1775,138 @@ pub struct ReadyEvent { pub shard: Option<[u8; 2]>, } +// Contains information about a successful reconnection +#[derive(Debug, Clone)] +pub struct Resumed { + pub trace: Vec>, +} + +/// Struct containing information about the logged-in user's preferences or +/// client settings +#[derive(Debug, Clone)] +pub struct UserSettingsUpdate { + pub detect_platform_accounts: Option, + pub developer_mode: Option, + pub enable_tts_command: Option, + pub inline_attachment_media: Option, + pub inline_embed_media: Option, + pub locale: Option, + pub message_display_compact: Option, + pub render_embeds: Option, + pub server_positions: Option>, + pub show_current_game: Option, + pub status: Option, + pub theme: Option, + pub convert_emoticons: Option, + pub friend_source_flags: Option, +} + +/// Voice server information +#[derive(Debug, Clone)] +pub struct VoiceServerUpdate { + pub server_id: Option, + pub channel_id: Option, + pub endpoint: Option, + pub token: String, +} + +/// Group call update information +#[derive(Debug, Clone)] +pub struct CallUpdate { + pub channel_id: ChannelId, + pub message_id: MessageId, + pub region: String, + pub ringing: Vec, +} + +/// Received when a user started typing, the typing is considered to last 10 +/// seconds. +#[derive(Debug, Clone)] +pub struct TypingStart { + pub channel_id: ChannelId, + pub user_id: UserId, + pub timestamp: u64, +} + +/// Contains information about the changed presence of a user +#[derive(Debug, Clone)] +pub struct PresenceUpdate { + pub presence: Presence, + pub server_id: Option, + pub roles: Option>, +} + +/// Received when a message has been updated. +#[derive(Debug, Clone)] +pub struct MessageUpdate { + pub id: MessageId, + pub channel_id: ChannelId, + pub kind: Option, + pub content: Option, + pub nonce: Option, + pub tts: Option, + pub pinned: Option, + pub timestamp: Option, + pub edited_timestamp: Option, + pub author: Option, + pub mention_everyone: Option, + pub mentions: Option>, + pub mention_roles: Option>, + pub attachments: Option>, + pub embeds: Option>, +} + +/// Holds information when a message was acknowledged by another logged-in +/// device +#[derive(Debug, Clone)] +pub struct MessageAck { + pub channel_id: ChannelId, + /// May be `None` if a private channel with no messages has closed. + pub message_id: Option, +} + +/// Received when a message was deleted +#[derive(Debug, Clone)] +pub struct MessageDelete { + pub channel_id: ChannelId, + pub message_id: MessageId, +} + +#[derive(Debug, Clone)] +pub struct MessageDeleteBulk { + pub channel_id: ChannelId, + pub ids: Vec, +} + +/// Received when a member's roles have changed +#[derive(Debug, Clone)] +pub struct ServerMemberUpdate { + pub server_id: ServerId, + pub roles: Vec, + pub user: User, + pub nick: Option, +} + +#[derive(Debug, Clone)] +pub struct ServerSync { + pub server_id: ServerId, + pub large: bool, + pub members: Vec, + pub presences: Vec, +} + +#[derive(Debug, Clone)] +pub struct ChannelPinsAck { + pub channel_id: ChannelId, + pub timestamp: String, +} + +#[derive(Debug, Clone)] +pub struct ChannelPinsUpdate { + pub channel_id: ChannelId, + pub last_pin_timestamp: Option, +} + /// Event received over a websocket connection #[derive(Debug, Clone)] pub enum Event { @@ -1783,129 +1915,64 @@ pub enum Event { /// May also be received at a later time in the event of a reconnect. Ready(ReadyEvent), /// The connection has successfully resumed after a disconnect. - Resumed { - trace: Vec>, - }, - + Resumed(Resumed), /// Update to the logged-in user's information UserUpdate(CurrentUser), /// Update to a note that the logged-in user has set for another user. UserNoteUpdate(UserId, String), /// Update to the logged-in user's preferences or client settings - UserSettingsUpdate { - detect_platform_accounts: Option, - developer_mode: Option, - enable_tts_command: Option, - inline_attachment_media: Option, - inline_embed_media: Option, - locale: Option, - message_display_compact: Option, - render_embeds: Option, - server_positions: Option>, - show_current_game: Option, - status: Option, - theme: Option, - convert_emoticons: Option, - friend_source_flags: Option, - }, + UserSettingsUpdate(UserSettingsUpdate), /// Update to the logged-in user's server-specific notification settings UserServerSettingsUpdate(UserServerSettings), /// A member's voice state has changed VoiceStateUpdate(Option, VoiceState), /// Voice server information is available - VoiceServerUpdate { - server_id: Option, - channel_id: Option, - endpoint: Option, - token: String, - }, + VoiceServerUpdate(VoiceServerUpdate), /// A new group call has been created CallCreate(Call), /// A group call has been updated - CallUpdate { - channel_id: ChannelId, - message_id: MessageId, - region: String, - ringing: Vec, - }, + CallUpdate(CallUpdate), /// A group call has been deleted (the call ended) CallDelete(ChannelId), /// A user has been added to a group ChannelRecipientAdd(ChannelId, User), /// A user has been removed from a group ChannelRecipientRemove(ChannelId, User), - - /// A user is typing; considered to last 5 seconds - TypingStart { - channel_id: ChannelId, - user_id: UserId, - timestamp: u64, - }, + /// A user is typing; considered to last 10 seconds + TypingStart(TypingStart), /// A member's presence state (or username or avatar) has changed - PresenceUpdate { - presence: Presence, - server_id: Option, - roles: Option>, - }, + PresenceUpdate(PresenceUpdate), /// The precense list of the user's friends should be replaced entirely PresencesReplace(Vec), RelationshipAdd(Relationship), RelationshipRemove(UserId, RelationshipType), + /// A new message has been created (received). + /// This event is also received when `Discord::send_message` was used. MessageCreate(Message), - /// A message has been edited, either by the user or the system - MessageUpdate { - id: MessageId, - channel_id: ChannelId, - kind: Option, - content: Option, - nonce: Option, - tts: Option, - pinned: Option, - timestamp: Option, - edited_timestamp: Option, - author: Option, - mention_everyone: Option, - mentions: Option>, - mention_roles: Option>, - attachments: Option>, - embeds: Option>, - }, + /// A message has been edited, either by the user or the system. + /// If an embedded message is sent or a message with a link was transformed + /// into an embedded message, this event will be returned. + MessageUpdate(MessageUpdate), /// Another logged-in device acknowledged this message - MessageAck { - channel_id: ChannelId, - /// May be `None` if a private channel with no messages has closed. - message_id: Option, - }, - MessageDelete { - channel_id: ChannelId, - message_id: MessageId, - }, - MessageDeleteBulk { - channel_id: ChannelId, - ids: Vec, - }, + MessageAck(MessageAck), + MessageDelete(MessageDelete), + MessageDeleteBulk(MessageDeleteBulk), + /// A new server was created or this account has been added to a new server + /// or this account connected to a server. ServerCreate(PossibleServer), ServerUpdate(Server), + /// A server was deleted or this account has been removed from the server. ServerDelete(PossibleServer), + /// A new member joined the server ServerMemberAdd(ServerId, Member), /// A member's roles have changed - ServerMemberUpdate { - server_id: ServerId, - roles: Vec, - user: User, - nick: Option, - }, + ServerMemberUpdate(ServerMemberUpdate), ServerMemberRemove(ServerId, User), ServerMembersChunk(ServerId, Vec), - ServerSync { - server_id: ServerId, - large: bool, - members: Vec, - presences: Vec, - }, + ServerSync(ServerSync), ServerRoleCreate(ServerId, Role), ServerRoleUpdate(ServerId, Role), @@ -1920,14 +1987,8 @@ pub enum Event { ChannelCreate(Channel), ChannelUpdate(Channel), ChannelDelete(Channel), - ChannelPinsAck { - channel_id: ChannelId, - timestamp: String, - }, - ChannelPinsUpdate { - channel_id: ChannelId, - last_pin_timestamp: Option, - }, + ChannelPinsAck(ChannelPinsAck), + ChannelPinsUpdate(ChannelPinsUpdate), ReactionAdd(Reaction), ReactionRemove(Reaction), @@ -1963,9 +2024,9 @@ impl Event { shard: try!(opt(&mut value, "shard", decode_shards)), })) } else if kind == "RESUMED" { - warn_json!(value, Event::Resumed { + warn_json!(value, Event::Resumed(Resumed { trace: try!(remove(&mut value, "_trace").and_then(|v| decode_array(v, |v| Ok(into_string(v).ok())))), - }) + })) } else if kind == "USER_UPDATE" { CurrentUser::decode(Value::Object(value)).map(Event::UserUpdate) } else if kind == "USER_NOTE_UPDATE" { @@ -1974,7 +2035,7 @@ impl Event { try!(remove(&mut value, "note").and_then(into_string)), )) } else if kind == "USER_SETTINGS_UPDATE" { - warn_json!(value, Event::UserSettingsUpdate { + warn_json!(value, Event::UserSettingsUpdate(UserSettingsUpdate { detect_platform_accounts: remove(&mut value, "detect_platform_accounts").ok().and_then(|v| v.as_bool()), developer_mode: remove(&mut value, "developer_mode").ok().and_then(|v| v.as_bool()), enable_tts_command: remove(&mut value, "enable_tts_command").ok().and_then(|v| v.as_bool()), @@ -1989,30 +2050,30 @@ impl Event { theme: try!(opt(&mut value, "theme", into_string)), convert_emoticons: remove(&mut value, "convert_emoticons").ok().and_then(|v| v.as_bool()), friend_source_flags: try!(opt(&mut value, "friend_source_flags", FriendSourceFlags::decode)), - }) + })) } else if kind == "USER_GUILD_SETTINGS_UPDATE" { UserServerSettings::decode(Value::Object(value)).map(Event::UserServerSettingsUpdate) } else if kind == "VOICE_STATE_UPDATE" { let server_id = try!(opt(&mut value, "guild_id", ServerId::decode)); Ok(Event::VoiceStateUpdate(server_id, try!(VoiceState::decode(Value::Object(value))))) } else if kind == "VOICE_SERVER_UPDATE" { - warn_json!(value, Event::VoiceServerUpdate { + warn_json!(value, Event::VoiceServerUpdate(VoiceServerUpdate { server_id: try!(opt(&mut value, "guild_id", ServerId::decode)), channel_id: try!(opt(&mut value, "channel_id", ChannelId::decode)), endpoint: try!(opt(&mut value, "endpoint", into_string)), token: try!(remove(&mut value, "token").and_then(into_string)), - }) + })) } else if kind == "CALL_CREATE" { Ok(Event::CallCreate(try!(Call::decode(Value::Object(value))))) } else if kind == "CALL_DELETE" { Ok(Event::CallDelete(try!(remove(&mut value, "channel_id").and_then(ChannelId::decode)))) } else if kind == "CALL_UPDATE" { - warn_json!(value, Event::CallUpdate { + warn_json!(value, Event::CallUpdate(CallUpdate { channel_id: try!(remove(&mut value, "channel_id").and_then(ChannelId::decode)), message_id: try!(remove(&mut value, "message_id").and_then(MessageId::decode)), region: try!(remove(&mut value, "region").and_then(into_string)), ringing: try!(decode_array(try!(remove(&mut value, "ringing")), UserId::decode)), - }) + })) } else if kind == "CHANNEL_RECIPIENT_ADD" { let channel_id = try!(remove(&mut value, "channel_id").and_then(ChannelId::decode)); let user = try!(remove(&mut value, "user").and_then(User::decode)); @@ -2022,20 +2083,20 @@ impl Event { let user = try!(remove(&mut value, "user").and_then(User::decode)); Ok(Event::ChannelRecipientRemove(channel_id, user)) } else if kind == "TYPING_START" { - warn_json!(value, Event::TypingStart { + warn_json!(value, Event::TypingStart(TypingStart { channel_id: try!(remove(&mut value, "channel_id").and_then(ChannelId::decode)), user_id: try!(remove(&mut value, "user_id").and_then(UserId::decode)), timestamp: req!(try!(remove(&mut value, "timestamp")).as_u64()), - }) + })) } else if kind == "PRESENCE_UPDATE" { let server_id = try!(opt(&mut value, "guild_id", ServerId::decode)); let roles = try!(opt(&mut value, "roles", |v| decode_array(v, RoleId::decode))); let presence = try!(Presence::decode(Value::Object(value))); - Ok(Event::PresenceUpdate { + Ok(Event::PresenceUpdate(PresenceUpdate { server_id: server_id, roles: roles, presence: presence, - }) + })) } else if kind == "RELATIONSHIP_ADD" { Relationship::decode(Value::Object(value)).map(Event::RelationshipAdd) } else if kind == "RELATIONSHIP_REMOVE" { @@ -2050,7 +2111,7 @@ impl Event { } else if kind == "MESSAGE_CREATE" { Message::decode(Value::Object(value)).map(Event::MessageCreate) } else if kind == "MESSAGE_UPDATE" { - warn_json!(value, Event::MessageUpdate { + warn_json!(value, Event::MessageUpdate(MessageUpdate { id: try!(remove(&mut value, "id").and_then(MessageId::decode)), channel_id: try!(remove(&mut value, "channel_id").and_then(ChannelId::decode)), kind: try!(opt(&mut value, "type", MessageType::decode)), @@ -2066,22 +2127,22 @@ impl Event { mention_roles: try!(opt(&mut value, "mention_roles", |v| decode_array(v, RoleId::decode))), attachments: try!(opt(&mut value, "attachments", |v| decode_array(v, Attachment::decode))), embeds: try!(opt(&mut value, "embeds", |v| decode_array(v, Ok))), - }) + })) } else if kind == "MESSAGE_ACK" { - warn_json!(value, Event::MessageAck { + warn_json!(value, Event::MessageAck(MessageAck { channel_id: try!(remove(&mut value, "channel_id").and_then(ChannelId::decode)), message_id: try!(opt(&mut value, "message_id", MessageId::decode)), - }) + })) } else if kind == "MESSAGE_DELETE" { - warn_json!(value, Event::MessageDelete { + warn_json!(value, Event::MessageDelete(MessageDelete { channel_id: try!(remove(&mut value, "channel_id").and_then(ChannelId::decode)), message_id: try!(remove(&mut value, "id").and_then(MessageId::decode)), - }) + })) } else if kind == "MESSAGE_DELETE_BULK" { - warn_json!(value, Event::MessageDeleteBulk { + warn_json!(value, Event::MessageDeleteBulk(MessageDeleteBulk { channel_id: try!(remove(&mut value, "channel_id").and_then(ChannelId::decode)), ids: try!(decode_array(try!(remove(&mut value, "ids")), MessageId::decode)), - }) + })) } else if kind == "GUILD_CREATE" { PossibleServer::::decode(Value::Object(value)).map(Event::ServerCreate) } else if kind == "GUILD_UPDATE" { @@ -2094,12 +2155,12 @@ impl Event { try!(Member::decode(Value::Object(value))), )) } else if kind == "GUILD_MEMBER_UPDATE" { - warn_json!(value, Event::ServerMemberUpdate { + warn_json!(value, Event::ServerMemberUpdate(ServerMemberUpdate { server_id: try!(remove(&mut value, "guild_id").and_then(ServerId::decode)), roles: try!(decode_array(try!(remove(&mut value, "roles")), RoleId::decode)), user: try!(remove(&mut value, "user").and_then(User::decode)), nick: try!(opt(&mut value, "nick", into_string)), - }) + })) } else if kind == "GUILD_MEMBER_REMOVE" { warn_json!(value, Event::ServerMemberRemove( try!(remove(&mut value, "guild_id").and_then(ServerId::decode)), @@ -2111,12 +2172,12 @@ impl Event { try!(remove(&mut value, "members").and_then(|v| decode_array(v, Member::decode))), )) } else if kind == "GUILD_SYNC" { - warn_json!(value, Event::ServerSync { + warn_json!(value, Event::ServerSync(ServerSync { server_id: try!(remove(&mut value, "id").and_then(ServerId::decode)), large: req!(try!(remove(&mut value, "large")).as_bool()), members: try!(remove(&mut value, "members").and_then(|v| decode_array(v, Member::decode))), presences: try!(decode_array(try!(remove(&mut value, "presences")), Presence::decode)), - }) + })) } else if kind == "GUILD_ROLE_CREATE" { warn_json!(value, Event::ServerRoleCreate( try!(remove(&mut value, "guild_id").and_then(ServerId::decode)), @@ -2158,15 +2219,15 @@ impl Event { } else if kind == "CHANNEL_DELETE" { Channel::decode(Value::Object(value)).map(Event::ChannelDelete) } else if kind == "CHANNEL_PINS_ACK" { - warn_json!(value, Event::ChannelPinsAck { + warn_json!(value, Event::ChannelPinsAck(ChannelPinsAck { channel_id: try!(remove(&mut value, "channel_id").and_then(ChannelId::decode)), timestamp: try!(remove(&mut value, "timestamp").and_then(into_string)), - }) + })) } else if kind == "CHANNEL_PINS_UPDATE" { - warn_json!(value, Event::ChannelPinsUpdate { + warn_json!(value, Event::ChannelPinsUpdate(ChannelPinsUpdate { channel_id: try!(remove(&mut value, "channel_id").and_then(ChannelId::decode)), last_pin_timestamp: try!(opt(&mut value, "last_pin_timestamp", into_string)), - }) + })) } else { Ok(Event::Unknown(kind, value)) } diff --git a/src/state.rs b/src/state.rs index a4eeea96..0ef9b826 100644 --- a/src/state.rs +++ b/src/state.rs @@ -99,31 +99,22 @@ impl State { } } }, - Event::UserSettingsUpdate { - ref detect_platform_accounts, ref developer_mode, - ref enable_tts_command, ref inline_attachment_media, - ref inline_embed_media, ref locale, - ref message_display_compact, - ref render_embeds, ref server_positions, - ref show_current_game, ref status, - ref theme, ref convert_emoticons, - ref friend_source_flags, - } => { + Event::UserSettingsUpdate(ref update) => { if let Some(settings) = self.settings.as_mut() { - opt_modify(&mut settings.detect_platform_accounts, detect_platform_accounts); - opt_modify(&mut settings.developer_mode, developer_mode); - opt_modify(&mut settings.enable_tts_command, enable_tts_command); - opt_modify(&mut settings.inline_attachment_media, inline_attachment_media); - opt_modify(&mut settings.inline_embed_media, inline_embed_media); - opt_modify(&mut settings.locale, locale); - opt_modify(&mut settings.message_display_compact, message_display_compact); - opt_modify(&mut settings.render_embeds, render_embeds); - opt_modify(&mut settings.server_positions, server_positions); - opt_modify(&mut settings.show_current_game, show_current_game); - opt_modify(&mut settings.status, status); - opt_modify(&mut settings.theme, theme); - opt_modify(&mut settings.convert_emoticons, convert_emoticons); - opt_modify(&mut settings.friend_source_flags, friend_source_flags); + opt_modify(&mut settings.detect_platform_accounts, &update.detect_platform_accounts); + opt_modify(&mut settings.developer_mode, &update.developer_mode); + opt_modify(&mut settings.enable_tts_command, &update.enable_tts_command); + opt_modify(&mut settings.inline_attachment_media, &update.inline_attachment_media); + opt_modify(&mut settings.inline_embed_media, &update.inline_embed_media); + opt_modify(&mut settings.locale, &update.locale); + opt_modify(&mut settings.message_display_compact, &update.message_display_compact); + opt_modify(&mut settings.render_embeds, &update.render_embeds); + opt_modify(&mut settings.server_positions, &update.server_positions); + opt_modify(&mut settings.show_current_game, &update.show_current_game); + opt_modify(&mut settings.status, &update.status); + opt_modify(&mut settings.theme, &update.theme); + opt_modify(&mut settings.convert_emoticons, &update.convert_emoticons); + opt_modify(&mut settings.friend_source_flags, &update.friend_source_flags); } } Event::UserServerSettingsUpdate(ref settings) => { @@ -172,10 +163,10 @@ impl State { Entry::Occupied(mut e) => { e.get_mut().clone_from(call); } } } - Event::CallUpdate { channel_id, message_id: _, ref region, ref ringing } => { - if let Some(call) = self.calls.get_mut(&channel_id) { - call.region.clone_from(region); - call.ringing.clone_from(ringing); + Event::CallUpdate(ref update) => { + if let Some(call) = self.calls.get_mut(&update.channel_id) { + call.region.clone_from(&update.region); + call.ringing.clone_from(&update.ringing); } } Event::CallDelete(channel_id) => { @@ -191,19 +182,19 @@ impl State { group.recipients.retain(|u| u.id != user.id); } } - Event::PresenceUpdate { server_id, ref presence, roles: _ } => { - if let Some(server_id) = server_id { + Event::PresenceUpdate(ref update) => { + if let Some(server_id) = update.server_id { self.servers.iter_mut().find(|s| s.id == server_id).map(|srv| { // If the user was modified, update the member list - if let Some(user) = presence.user.as_ref() { + if let Some(user) = update.presence.user.as_ref() { srv.members.iter_mut().find(|u| u.user.id == user.id).map(|member| { member.user.clone_from(user); }); } - update_presence(&mut srv.presences, presence); + update_presence(&mut srv.presences, &update.presence); }); } else { - update_presence(&mut self.presences, presence); + update_presence(&mut self.presences, &update.presence); } } Event::PresencesReplace(ref presences) => { @@ -251,12 +242,12 @@ impl State { srv.members.push(member.clone()); }); } - Event::ServerMemberUpdate { ref server_id, ref roles, ref user, ref nick } => { - self.servers.iter_mut().find(|s| s.id == *server_id).map(|srv| { - srv.members.iter_mut().find(|m| m.user.id == user.id).map(|member| { - member.user.clone_from(user); - member.roles.clone_from(roles); - member.nick.clone_from(nick); + Event::ServerMemberUpdate(ref update) => { + self.servers.iter_mut().find(|s| s.id == update.server_id).map(|srv| { + srv.members.iter_mut().find(|m| m.user.id == update.user.id).map(|member| { + member.user.clone_from(&update.user); + member.roles.clone_from(&update.roles); + member.nick.clone_from(&update.nick); }) }); } @@ -271,11 +262,11 @@ impl State { srv.members.extend_from_slice(members); }); } - Event::ServerSync { server_id, large, ref members, ref presences } => { - self.servers.iter_mut().find(|s| s.id == server_id).map(|srv| { - srv.large = large; - srv.members.clone_from(members); - srv.presences.clone_from(presences); + Event::ServerSync(ref sync) => { + self.servers.iter_mut().find(|s| s.id == sync.server_id).map(|srv| { + srv.large = sync.large; + srv.members.clone_from(&sync.members); + srv.presences.clone_from(&sync.presences); }); } Event::ServerRoleCreate(ref server_id, ref role) => { @@ -352,25 +343,25 @@ impl State { }); } }, - Event::ChannelPinsUpdate { ref channel_id, ref last_pin_timestamp } => { + Event::ChannelPinsUpdate(ref update) => { for server in &mut self.servers { for channel in &mut server.channels { - if channel.id == *channel_id { - channel.last_pin_timestamp = last_pin_timestamp.clone(); + if channel.id == update.channel_id { + channel.last_pin_timestamp = update.last_pin_timestamp.clone(); return } } } for channel in &mut self.private_channels { - if channel.id == *channel_id { - channel.last_pin_timestamp = last_pin_timestamp.clone(); + if channel.id == update.channel_id { + channel.last_pin_timestamp = update.last_pin_timestamp.clone(); return } } - if let Some(group) = self.groups.get_mut(channel_id) { - group.last_pin_timestamp = last_pin_timestamp.clone(); + if let Some(group) = self.groups.get_mut(&update.channel_id) { + group.last_pin_timestamp = update.last_pin_timestamp.clone(); return } }