diff options
| author | Austin Hellyer <[email protected]> | 2016-11-15 11:36:53 -0800 |
|---|---|---|
| committer | Austin Hellyer <[email protected]> | 2016-11-15 11:36:53 -0800 |
| commit | 5ccfaaa3b1a030b1fd0dcd364bdae001347d36e4 (patch) | |
| tree | 7cf531e4790109d6d7edd26bc5b483378d5ba5ac /src | |
| parent | Embed Author: everything but 'name' is optional (diff) | |
| download | serenity-5ccfaaa3b1a030b1fd0dcd364bdae001347d36e4.tar.xz serenity-5ccfaaa3b1a030b1fd0dcd364bdae001347d36e4.zip | |
Add state/framework/etc. conditional compile flags
This adds conditional compilation for the following features, in
addition to the voice conditional compilation flag:
- extras (message builder)
- framework
- methods
- state
These 4 are enabled _by default_, while the `voice` feature flag is
disabled.
Disabling the state will allow incredibly low-memory bots.
Diffstat (limited to 'src')
| -rw-r--r-- | src/client/connection.rs | 19 | ||||
| -rw-r--r-- | src/client/context.rs | 27 | ||||
| -rw-r--r-- | src/client/dispatch.rs | 430 | ||||
| -rw-r--r-- | src/client/event_store.rs | 27 | ||||
| -rw-r--r-- | src/client/mod.rs | 398 | ||||
| -rw-r--r-- | src/ext/mod.rs | 9 | ||||
| -rw-r--r-- | src/ext/state/mod.rs | 6 | ||||
| -rw-r--r-- | src/model/channel.rs | 68 | ||||
| -rw-r--r-- | src/model/gateway.rs | 4 | ||||
| -rw-r--r-- | src/model/guild.rs | 51 | ||||
| -rw-r--r-- | src/model/id.rs | 11 | ||||
| -rw-r--r-- | src/model/invite.rs | 4 | ||||
| -rw-r--r-- | src/model/misc.rs | 1 | ||||
| -rw-r--r-- | src/model/mod.rs | 10 | ||||
| -rw-r--r-- | src/model/permissions.rs | 3 | ||||
| -rw-r--r-- | src/model/user.rs | 25 | ||||
| -rw-r--r-- | src/model/utils.rs | 8 | ||||
| -rw-r--r-- | src/model/webhook.rs | 4 | ||||
| -rw-r--r-- | src/utils/builder/edit_role.rs | 14 | ||||
| -rw-r--r-- | src/utils/macros.rs | 300 | ||||
| -rw-r--r-- | src/utils/mod.rs | 90 |
21 files changed, 1096 insertions, 413 deletions
diff --git a/src/client/connection.rs b/src/client/connection.rs index d1e37e5..4862667 100644 --- a/src/client/connection.rs +++ b/src/client/connection.rs @@ -36,25 +36,6 @@ use ::model::{ #[cfg(feature="voice")] use ::ext::voice::Manager as VoiceManager; -#[cfg(feature="voice")] -macro_rules! connection { - ($($name1:ident: $val1:expr),*; $($name2:ident: $val2:expr,)*) => { - Connection { - $($name1: $val1,)* - $($name2: $val2,)* - } - } -} - -#[cfg(not(feature="voice"))] -macro_rules! connection { - ($($name1:ident: $val1:expr),*; $($name2:ident: $val2:expr,)*) => { - Connection { - $($name1: $val1,)* - } - } -} - #[doc(hidden)] pub enum Status { SendMessage(Value), diff --git a/src/client/context.rs b/src/client/context.rs index 0507bc3..6443efa 100644 --- a/src/client/context.rs +++ b/src/client/context.rs @@ -3,7 +3,7 @@ use std::collections::HashMap; use std::io::Read; use std::sync::{Arc, Mutex}; use super::connection::Connection; -use super::{STATE, http}; +use super::http; use super::login_type::LoginType; use ::utils::builder::{ CreateInvite, @@ -19,6 +19,9 @@ use ::internal::prelude::*; use ::model::*; use ::utils; +#[cfg(feature = "state")] +use super::STATE; + #[derive(Clone)] pub struct Context { channel_id: Option<ChannelId>, @@ -553,7 +556,7 @@ impl Context { let guild_id = guild_id.into(); let role_id = role_id.into(); - let map = { + let map = feature_state! {{ let state = STATE.lock().unwrap(); let role = if let Some(role) = { @@ -565,7 +568,9 @@ impl Context { }; f(EditRole::new(role)).0.build() - }; + } else { + f(EditRole::default()).0.build() + }}; http::edit_role(guild_id.0, role_id.0, map) } @@ -601,9 +606,11 @@ impl Context { where C: Into<ChannelId> { let channel_id = channel_id.into(); - if let Some(channel) = STATE.lock().unwrap().find_channel(channel_id) { - return Ok(channel.clone()) - } + feature_state_enabled! {{ + if let Some(channel) = STATE.lock().unwrap().find_channel(channel_id) { + return Ok(channel.clone()) + } + }} http::get_channel(channel_id.0) } @@ -612,13 +619,13 @@ impl Context { -> Result<HashMap<ChannelId, PublicChannel>> where G: Into<GuildId> { let guild_id = guild_id.into(); - { + feature_state_enabled! {{ let state = STATE.lock().unwrap(); if let Some(guild) = state.find_guild(guild_id) { return Ok(guild.channels.clone()); } - } + }} let mut channels = HashMap::new(); @@ -677,13 +684,13 @@ impl Context { let guild_id = guild_id.into(); let user_id = user_id.into(); - { + feature_state_enabled! {{ let state = STATE.lock().unwrap(); if let Some(member) = state.find_member(guild_id, user_id) { return Ok(member.clone()); } - } + }} http::get_member(guild_id.0, user_id.0) } diff --git a/src/client/dispatch.rs b/src/client/dispatch.rs index 6295bc9..fa41ddc 100644 --- a/src/client/dispatch.rs +++ b/src/client/dispatch.rs @@ -2,11 +2,16 @@ use std::sync::{Arc, Mutex}; use std::thread; use super::event_store::EventStore; use super::login_type::LoginType; -use super::{STATE, Connection, Context}; -use ::ext::framework::Framework; +use super::{Connection, Context}; use ::internal::prelude::*; use ::model::{ChannelId, Event, Message}; +#[cfg(feature="framework")] +use ::ext::framework::Framework; + +#[cfg(feature = "state")] +use super::STATE; + macro_rules! handler { ($field:ident, $event_store:ident) => { $event_store.lock() @@ -19,10 +24,14 @@ macro_rules! handler { macro_rules! update { ($method:ident, $event:expr) => { - STATE.lock().unwrap().$method(&$event); + feature_state_enabled! {{ + STATE.lock().unwrap().$method(&$event) + }} }; ($method:ident, $event:expr, $old:expr) => { - STATE.lock().unwrap().$method(&$event, $old); + feature_state_enabled! {{ + STATE.lock().unwrap().$method(&$event, $old) + }} }; } @@ -32,14 +41,72 @@ fn context(channel_id: Option<ChannelId>, Context::new(channel_id, conn, login_type) } -#[allow(cyclomatic_complexity)] +#[cfg(feature="framework")] pub fn dispatch(event: Result<Event>, conn: Arc<Mutex<Connection>>, framework: Arc<Mutex<Framework>>, login_type: LoginType, event_store: Arc<Mutex<EventStore>>) { match event { - Ok(Event::CallCreate(event)) => { + Ok(Event::MessageCreate(event)) => { + let context = context(Some(event.message.channel_id), + conn, + login_type); + let mut framework = framework.lock().expect("framework poisoned"); + + if framework.initialized { + dispatch_message(context.clone(), + event.message.clone(), + event_store); + + framework.dispatch(context, event.message); + } else { + dispatch_message(context, event.message, event_store); + } + }, + Ok(other) => handle_event(other, conn, login_type, event_store), + Err(_why) => {}, + } +} + +#[cfg(not(feature="framework"))] +pub fn dispatch(event: Result<Event>, + conn: Arc<Mutex<Connection>>, + login_type: LoginType, + event_store: Arc<Mutex<EventStore>>) { + match event { + Ok(Event::MessageCreate(event)) => { + let context = context(Some(event.message.channel_id), + conn, + login_type); + dispatch_message(context.clone(), + event.message.clone(), + event_store); + }, + Ok(other) => handle_event(other, conn, login_type, event_store), + Err(_why) => {}, + } +} + +fn dispatch_message(context: Context, + message: Message, + event_store: Arc<Mutex<EventStore>>) { + if let Some(ref handler) = handler!(on_message, event_store) { + let handler = handler.clone(); + + thread::spawn(move || { + (handler)(context, message); + }); + } +} + +#[allow(cyclomatic_complexity)] +fn handle_event(event: Event, + conn: Arc<Mutex<Connection>>, + login_type: LoginType, + event_store: Arc<Mutex<EventStore>>) { + match event { + Event::CallCreate(event) => { if let Some(ref handler) = handler!(on_call_create, event_store) { update!(update_with_call_create, event); @@ -53,7 +120,7 @@ pub fn dispatch(event: Result<Event>, update!(update_with_call_create, event); } }, - Ok(Event::CallDelete(event)) => { + Event::CallDelete(event) => { if let Some(ref handler) = handler!(on_call_delete, event_store) { let call = STATE .lock() @@ -72,27 +139,35 @@ pub fn dispatch(event: Result<Event>, update!(update_with_call_delete, event); } }, - Ok(Event::CallUpdate(event)) => { + Event::CallUpdate(event) => { if let Some(ref handler) = handler!(on_call_update, event_store) { - let before = update!(update_with_call_update, event, true); - let after = STATE - .lock() - .unwrap() - .calls - .get(&event.channel_id) - .cloned(); - let context = context(None, conn, login_type); let handler = handler.clone(); - thread::spawn(move || { - (handler)(context, before, after); - }); + feature_state! {{ + let before = update!(update_with_call_update, event, true); + let after = STATE + .lock() + .unwrap() + .calls + .get(&event.channel_id) + .cloned(); + + thread::spawn(move || { + (handler)(context, before, after); + }); + } else { + thread::spawn(move || { + (handler)(context, event); + }); + }} } else { - update!(update_with_call_update, event, false); + feature_state_enabled! {{ + update!(update_with_call_update, event, false); + }} } }, - Ok(Event::ChannelCreate(event)) => { + Event::ChannelCreate(event) => { if let Some(ref handler) = handler!(on_channel_create, event_store) { update!(update_with_channel_create, event); let context = context(Some(event.channel.id()), @@ -107,7 +182,7 @@ pub fn dispatch(event: Result<Event>, update!(update_with_channel_create, event); } }, - Ok(Event::ChannelDelete(event)) => { + Event::ChannelDelete(event) => { if let Some(ref handler) = handler!(on_channel_delete, event_store) { update!(update_with_channel_delete, event); let context = context(None, conn, login_type); @@ -120,7 +195,7 @@ pub fn dispatch(event: Result<Event>, update!(update_with_channel_delete, event); } }, - Ok(Event::ChannelPinsAck(event)) => { + Event::ChannelPinsAck(event) => { if let Some(ref handler) = handler!(on_channel_pins_ack, event_store) { let context = context(Some(event.channel_id), conn, @@ -132,7 +207,7 @@ pub fn dispatch(event: Result<Event>, }); } }, - Ok(Event::ChannelPinsUpdate(event)) => { + Event::ChannelPinsUpdate(event) => { if let Some(ref handler) = handler!(on_channel_pins_update, event_store) { let context = context(Some(event.channel_id), conn, @@ -144,7 +219,7 @@ pub fn dispatch(event: Result<Event>, }); } }, - Ok(Event::ChannelRecipientAdd(event)) => { + Event::ChannelRecipientAdd(event) => { update!(update_with_channel_recipient_add, event); if let Some(ref handler) = handler!(on_channel_recipient_addition, event_store) { @@ -158,7 +233,7 @@ pub fn dispatch(event: Result<Event>, }); } }, - Ok(Event::ChannelRecipientRemove(event)) => { + Event::ChannelRecipientRemove(event) => { update!(update_with_channel_recipient_remove, event); if let Some(ref handler) = handler!(on_channel_recipient_removal, event_store) { @@ -172,7 +247,7 @@ pub fn dispatch(event: Result<Event>, }); } }, - Ok(Event::ChannelUpdate(event)) => { + Event::ChannelUpdate(event) => { if let Some(ref handler) = handler!(on_channel_update, event_store) { let before = STATE.lock() .unwrap() @@ -190,7 +265,7 @@ pub fn dispatch(event: Result<Event>, update!(update_with_channel_update, event); } }, - Ok(Event::GuildBanAdd(event)) => { + Event::GuildBanAdd(event) => { if let Some(ref handler) = handler!(on_guild_ban_addition, event_store) { let context = context(None, conn, login_type); let handler = handler.clone(); @@ -200,7 +275,7 @@ pub fn dispatch(event: Result<Event>, }); } }, - Ok(Event::GuildBanRemove(event)) => { + Event::GuildBanRemove(event) => { if let Some(ref handler) = handler!(on_guild_ban_removal, event_store) { let context = context(None, conn, login_type); let handler = handler.clone(); @@ -210,7 +285,7 @@ pub fn dispatch(event: Result<Event>, }); } }, - Ok(Event::GuildCreate(event)) => { + Event::GuildCreate(event) => { update!(update_with_guild_create, event); if let Some(ref handler) = handler!(on_guild_create, event_store) { @@ -222,20 +297,29 @@ pub fn dispatch(event: Result<Event>, }); } }, - Ok(Event::GuildDelete(event)) => { + Event::GuildDelete(event) => { if let Some(ref handler) = handler!(on_guild_delete, event_store) { - let full = update!(update_with_guild_delete, event); let context = context(None, conn, login_type); let handler = handler.clone(); - thread::spawn(move || { - (handler)(context, event.guild, full); - }); + feature_state! {{ + let full = update!(update_with_guild_delete, event); + + thread::spawn(move || { + (handler)(context, event.guild, full); + }); + } else { + thread::spawn(move || { + (handler)(context, event.guild); + }); + }} } else { - let _full = update!(update_with_guild_delete, event); + feature_state_enabled! {{ + let _full = update!(update_with_guild_delete, event); + }} } }, - Ok(Event::GuildEmojisUpdate(event)) => { + Event::GuildEmojisUpdate(event) => { update!(update_with_guild_emojis_update, event); if let Some(ref handler) = handler!(on_guild_emojis_update, event_store) { @@ -247,7 +331,7 @@ pub fn dispatch(event: Result<Event>, }); } }, - Ok(Event::GuildIntegrationsUpdate(event)) => { + Event::GuildIntegrationsUpdate(event) => { if let Some(ref handler) = handler!(on_guild_integrations_update, event_store) { let context = context(None, conn, login_type); let handler = handler.clone(); @@ -257,7 +341,7 @@ pub fn dispatch(event: Result<Event>, }); } }, - Ok(Event::GuildMemberAdd(event)) => { + Event::GuildMemberAdd(event) => { update!(update_with_guild_member_add, event); if let Some(ref handler) = handler!(on_guild_member_addition, event_store) { @@ -269,42 +353,58 @@ pub fn dispatch(event: Result<Event>, }); } }, - Ok(Event::GuildMemberRemove(event)) => { + Event::GuildMemberRemove(event) => { if let Some(ref handler) = handler!(on_guild_member_removal, event_store) { - let member = update!(update_with_guild_member_remove, event); let context = context(None, conn, login_type); let handler = handler.clone(); - thread::spawn(move || { - (handler)(context, event.guild_id, event.user, member); - }); + feature_state! {{ + let member = update!(update_with_guild_member_remove, event); + + thread::spawn(move || { + (handler)(context, event.guild_id, event.user, member); + }); + } else { + thread::spawn(move || { + (handler)(context, event.guild_id, event.user); + }); + }} } else { - let _member = update!(update_with_guild_member_remove, event); + feature_state_enabled! {{ + let _member = update!(update_with_guild_member_remove, event); + }} } }, - Ok(Event::GuildMemberUpdate(event)) => { + Event::GuildMemberUpdate(event) => { if let Some(ref handler) = handler!(on_guild_member_update, event_store) { - let before = update!(update_with_guild_member_update, event, true); - - // This is safe, as the update would have created the member - // if it did not exist. Thus, there _should_ be no way that this - // could fail under any circumstance. - let after = STATE.lock() - .unwrap() - .find_member(event.guild_id, event.user.id) - .unwrap() - .clone(); let context = context(None, conn, login_type); let handler = handler.clone(); - thread::spawn(move || { - (handler)(context, before, after); - }); + feature_state! {{ + let before = update!(update_with_guild_member_update, event); + + // This is safe, as the update would have created the member + // if it did not exist. Thus, there _should_ be no way that this + // could fail under any circumstance. + let after = STATE.lock() + .unwrap() + .find_member(event.guild_id, event.user.id) + .unwrap() + .clone(); + + thread::spawn(move || { + (handler)(context, before, after); + }); + } else { + thread::spawn(move || { + (handler)(context, event); + }); + }} } else { - let _ = update!(update_with_guild_member_update, event, false); + let _ = update!(update_with_guild_member_update, event); } }, - Ok(Event::GuildMembersChunk(event)) => { + Event::GuildMembersChunk(event) => { update!(update_with_guild_members_chunk, event); if let Some(ref handler) = handler!(on_guild_members_chunk, event_store) { @@ -316,7 +416,7 @@ pub fn dispatch(event: Result<Event>, }); } }, - Ok(Event::GuildRoleCreate(event)) => { + Event::GuildRoleCreate(event) => { update!(update_with_guild_role_create, event); if let Some(ref handler) = handler!(on_guild_role_create, event_store) { @@ -328,30 +428,51 @@ pub fn dispatch(event: Result<Event>, }); } }, - Ok(Event::GuildRoleDelete(event)) => { + Event::GuildRoleDelete(event) => { if let Some(ref handler) = handler!(on_guild_role_delete, event_store) { - let role = update!(update_with_guild_role_delete, event); let context = context(None, conn, login_type); let handler = handler.clone(); - thread::spawn(move || { - (handler)(context, event.guild_id, event.role_id, role); - }); + feature_state! {{ + let role = update!(update_with_guild_role_delete, event); + + thread::spawn(move || { + (handler)(context, event.guild_id, event.role_id, role); + }); + } else { + thread::spawn(move || { + (handler)(context, event.guild_id, event.role_id); + }); + }} + } else { + feature_state_enabled! {{ + let _role = update!(update_with_guild_role_delete, event); + }} } }, - Ok(Event::GuildRoleUpdate(event)) => { - let before = update!(update_with_guild_role_update, event); - + Event::GuildRoleUpdate(event) => { if let Some(ref handler) = handler!(on_guild_role_update, event_store) { let context = context(None, conn, login_type); let handler = handler.clone(); - thread::spawn(move || { - (handler)(context, event.guild_id, before, event.role); - }); + feature_state! {{ + let before = update!(update_with_guild_role_update, event); + + thread::spawn(move || { + (handler)(context, event.guild_id, before, event.role); + }); + } else { + thread::spawn(move || { + (handler)(context, event.guild_id, event.role); + }); + }} + } else { + feature_state_enabled! {{ + let _before = update!(update_with_guild_role_update, event); + }} } }, - Ok(Event::GuildSync(event)) => { + Event::GuildSync(event) => { if let Some(ref handler) = handler!(on_guild_sync, event_store) { let context = context(None, conn, login_type); let handler = handler.clone(); @@ -361,7 +482,7 @@ pub fn dispatch(event: Result<Event>, }); } }, - Ok(Event::GuildUnavailable(event)) => { + Event::GuildUnavailable(event) => { update!(update_with_guild_unavailable, event); if let Some(ref handler) = handler!(on_guild_unavailable, event_store) { @@ -373,7 +494,7 @@ pub fn dispatch(event: Result<Event>, }); } }, - Ok(Event::GuildUpdate(event)) => { + Event::GuildUpdate(event) => { if let Some(ref handler) = handler!(on_guild_update, event_store) { let before = STATE.lock() .unwrap() @@ -391,7 +512,7 @@ pub fn dispatch(event: Result<Event>, update!(update_with_guild_update, event); } } - Ok(Event::MessageAck(event)) => { + Event::MessageAck(event) => { if let Some(ref handler) = handler!(on_message_ack, event_store) { let context = context(Some(event.channel_id), conn, @@ -403,23 +524,9 @@ pub fn dispatch(event: Result<Event>, }); } }, - Ok(Event::MessageCreate(event)) => { - let context = context(Some(event.message.channel_id), - conn, - login_type); - let mut framework = framework.lock().expect("framework poisoned"); - - if framework.initialized { - dispatch_message(context.clone(), - event.message.clone(), - event_store); - - framework.dispatch(context, event.message); - } else { - dispatch_message(context, event.message, event_store); - } - }, - Ok(Event::MessageDeleteBulk(event)) => { + // Already handled by the framework check macro + Event::MessageCreate(_event) => {}, + Event::MessageDeleteBulk(event) => { if let Some(ref handler) = handler!(on_message_delete_bulk, event_store) { let context = context(Some(event.channel_id), conn, @@ -431,7 +538,7 @@ pub fn dispatch(event: Result<Event>, }); } }, - Ok(Event::MessageDelete(event)) => { + Event::MessageDelete(event) => { if let Some(ref handler) = handler!(on_message_delete, event_store) { let context = context(Some(event.channel_id), conn, @@ -443,7 +550,7 @@ pub fn dispatch(event: Result<Event>, }); } }, - Ok(Event::MessageUpdate(event)) => { + Event::MessageUpdate(event) => { if let Some(ref handler) = handler!(on_message_update, event_store) { let context = context(Some(event.channel_id), conn, @@ -455,7 +562,7 @@ pub fn dispatch(event: Result<Event>, }); } }, - Ok(Event::PresencesReplace(event)) => { + Event::PresencesReplace(event) => { update!(update_with_presences_replace, event); if let Some(handler) = handler!(on_presence_replace, event_store) { @@ -467,7 +574,7 @@ pub fn dispatch(event: Result<Event>, }); } }, - Ok(Event::PresenceUpdate(event)) => { + Event::PresenceUpdate(event) => { update!(update_with_presence_update, event); if let Some(handler) = handler!(on_presence_update, event_store) { @@ -479,7 +586,7 @@ pub fn dispatch(event: Result<Event>, }); } }, - Ok(Event::ReactionAdd(event)) => { + Event::ReactionAdd(event) => { if let Some(ref handler) = handler!(on_reaction_add, event_store) { let context = context(Some(event.reaction.channel_id), conn, @@ -491,7 +598,7 @@ pub fn dispatch(event: Result<Event>, }); } }, - Ok(Event::ReactionRemove(event)) => { + Event::ReactionRemove(event) => { if let Some(ref handler) = handler!(on_reaction_remove, event_store) { let context = context(Some(event.reaction.channel_id), conn, @@ -503,7 +610,7 @@ pub fn dispatch(event: Result<Event>, }); } }, - Ok(Event::ReactionRemoveAll(event)) => { + Event::ReactionRemoveAll(event) => { if let Some(ref handler) = handler!(on_reaction_remove_all, event_store) { let context = context(Some(event.channel_id), conn, @@ -515,7 +622,7 @@ pub fn dispatch(event: Result<Event>, }); } }, - Ok(Event::Ready(event)) => { + Event::Ready(event) => { if let Some(ref handler) = handler!(on_ready, event_store) { update!(update_with_ready, event); @@ -529,7 +636,7 @@ pub fn dispatch(event: Result<Event>, update!(update_with_ready, event); } }, - Ok(Event::RelationshipAdd(event)) => { + Event::RelationshipAdd(event) => { update!(update_with_relationship_add, event); if let Some(ref handler) = handler!(on_relationship_addition, event_store) { @@ -541,7 +648,7 @@ pub fn dispatch(event: Result<Event>, }); } }, - Ok(Event::RelationshipRemove(event)) => { + Event::RelationshipRemove(event) => { update!(update_with_relationship_remove, event); if let Some(ref handler) = handler!(on_relationship_removal, event_store) { @@ -553,7 +660,7 @@ pub fn dispatch(event: Result<Event>, }); } }, - Ok(Event::Resumed(event)) => { + Event::Resumed(event) => { if let Some(ref handler) = handler!(on_resume, event_store) { let context = context(None, conn, login_type); let handler = handler.clone(); @@ -563,7 +670,7 @@ pub fn dispatch(event: Result<Event>, }); } }, - Ok(Event::TypingStart(event)) => { + Event::TypingStart(event) => { if let Some(ref handler) = handler!(on_typing_start, event_store) { let context = context(Some(event.channel_id), conn, @@ -575,7 +682,7 @@ pub fn dispatch(event: Result<Event>, }); } }, - Ok(Event::Unknown(event)) => { + Event::Unknown(event) => { if let Some(ref handler) = handler!(on_unknown, event_store) { let context = context(None, conn, login_type); let handler = handler.clone(); @@ -585,58 +692,96 @@ pub fn dispatch(event: Result<Event>, }); } }, - Ok(Event::UserGuildSettingsUpdate(event)) => { - let before = update!(update_with_user_guild_settings_update, event); - + Event::UserGuildSettingsUpdate(event) => { if let Some(ref handler) = handler!(on_user_guild_settings_update, event_store) { let context = context(None, conn, login_type); let handler = handler.clone(); - thread::spawn(move || { - (handler)(context, before, event.settings); - }); + feature_state! {{ + let before = update!(update_with_user_guild_settings_update, event); + + thread::spawn(move || { + (handler)(context, before, event.settings); + }); + } else { + thread::spawn(move || { + (handler)(context, event.settings); + }); + }} + } else { + feature_state_enabled! {{ + let _before = update!(update_with_user_guild_settings_update, event); + }} } }, - Ok(Event::UserNoteUpdate(event)) => { - let before = update!(update_with_user_note_update, event); - + Event::UserNoteUpdate(event) => { if let Some(ref handler) = handler!(on_note_update, event_store) { let context = context(None, conn, login_type); let handler = handler.clone(); - thread::spawn(move || { - (handler)(context, event.user_id, before, event.note); - }); + feature_state! {{ + let before = update!(update_with_user_note_update, event); + + thread::spawn(move || { + (handler)(context, event.user_id, before, event.note); + }); + } else { + thread::spawn(move || { + (handler)(context, event.user_id, event.note); + }); + }} + } else { + feature_state_enabled! {{ + let _before = update!(update_with_user_note_update, event); + }} } }, - Ok(Event::UserSettingsUpdate(event)) => { + Event::UserSettingsUpdate(event) => { if let Some(ref handler) = handler!(on_user_settings_update, event_store) { - let before = update!(update_with_user_settings_update, event, true); - let after = STATE.lock().unwrap().settings.clone(); - let context = context(None, conn, login_type); let handler = handler.clone(); - thread::spawn(move || { - (handler)(context, before.unwrap(), after.unwrap()); - }); + feature_state! {{ + let before = update!(update_with_user_settings_update, event, true); + let after = STATE.lock().unwrap().settings.clone(); + + thread::spawn(move || { + (handler)(context, before.unwrap(), after.unwrap()); + }); + } else { + thread::spawn(move || { + (handler)(context, event); + }); + }} } else { - update!(update_with_user_settings_update, event, false); + feature_state_enabled! {{ + update!(update_with_user_settings_update, event, false); + }} } }, - Ok(Event::UserUpdate(event)) => { - let before = update!(update_with_user_update, event); - + Event::UserUpdate(event) => { if let Some(ref handler) = handler!(on_user_update, event_store) { let context = context(None, conn, login_type); let handler = handler.clone(); - thread::spawn(move || { - (handler)(context, before, event.current_user); - }); + feature_state! {{ + let before = update!(update_with_user_update, event); + + thread::spawn(move || { + (handler)(context, before, event.current_user); + }); + } else { + thread::spawn(move || { + (handler)(context, event.current_user); + }); + }} + } else { + feature_state_enabled! {{ + let _before = update!(update_with_user_update, event); + }} } }, - Ok(Event::VoiceServerUpdate(event)) => { + Event::VoiceServerUpdate(event) => { if let Some(ref handler) = handler!(on_voice_server_update, event_store) { let context = context(None, conn, login_type); let handler = handler.clone(); @@ -646,7 +791,7 @@ pub fn dispatch(event: Result<Event>, }); } }, - Ok(Event::VoiceStateUpdate(event)) => { + Event::VoiceStateUpdate(event) => { update!(update_with_voice_state_update, event); if let Some(ref handler) = handler!(on_voice_state_update, event_store) { @@ -658,7 +803,7 @@ pub fn dispatch(event: Result<Event>, }); } }, - Ok(Event::WebhookUpdate(event)) => { + Event::WebhookUpdate(event) => { if let Some(ref handler) = handler!(on_webhook_update, event_store) { let context = context(None, conn, login_type); let handler = handler.clone(); @@ -668,18 +813,5 @@ pub fn dispatch(event: Result<Event>, }); } }, - Err(_why) => {}, - } -} - -fn dispatch_message(context: Context, - message: Message, - event_store: Arc<Mutex<EventStore>>) { - if let Some(ref handler) = handler!(on_message, event_store) { - let handler = handler.clone(); - - thread::spawn(move || { - (handler)(context, message); - }); } } diff --git a/src/client/event_store.rs b/src/client/event_store.rs index 387f9e7..98d874b 100644 --- a/src/client/event_store.rs +++ b/src/client/event_store.rs @@ -27,7 +27,10 @@ use ::model::*; pub struct EventStore { pub on_call_create: Option<Arc<Fn(Context, Call) + Send + Sync + 'static>>, pub on_call_delete: Option<Arc<Fn(Context, Option<Call>) + Send + Sync + 'static>>, + #[cfg(feature = "state")] pub on_call_update: Option<Arc<Fn(Context, Option<Call>, Option<Call>) + Send + Sync + 'static>>, + #[cfg(not(feature = "state"))] + pub on_call_update: Option<Arc<Fn(Context, CallUpdateEvent) + Send + Sync + 'static>>, pub on_channel_create: Option<Arc<Fn(Context, Channel) + Send + Sync + 'static>>, pub on_channel_delete: Option<Arc<Fn(Context, Channel) + Send + Sync + 'static>>, pub on_channel_pins_ack: Option<Arc<Fn(Context, ChannelPinsAckEvent) + Send + Sync + 'static>>, @@ -38,16 +41,31 @@ pub struct EventStore { pub on_guild_ban_addition: Option<Arc<Fn(Context, GuildId, User) + Send + Sync + 'static>>, pub on_guild_ban_removal: Option<Arc<Fn(Context, GuildId, User) + Send + Sync + 'static>>, pub on_guild_create: Option<Arc<Fn(Context, LiveGuild) + Send + Sync + 'static>>, + #[cfg(feature = "state")] pub on_guild_delete: Option<Arc<Fn(Context, Guild, Option<LiveGuild>) + Send + Sync + 'static>>, + #[cfg(not(feature = "state"))] + pub on_guild_delete: Option<Arc<Fn(Context, Guild) + Send + Sync + 'static>>, pub on_guild_emojis_update: Option<Arc<Fn(Context, GuildId, HashMap<EmojiId, Emoji>) + Send + Sync + 'static>>, pub on_guild_integrations_update: Option<Arc<Fn(Context, GuildId) + Send + Sync + 'static>>, pub on_guild_member_addition: Option<Arc<Fn(Context, GuildId, Member) + Send + Sync + 'static>>, + #[cfg(feature = "state")] pub on_guild_member_removal: Option<Arc<Fn(Context, GuildId, User, Option<Member>) + Send + Sync + 'static>>, + #[cfg(not(feature = "state"))] + pub on_guild_member_removal: Option<Arc<Fn(Context, GuildId, User) + Send + Sync + 'static>>, + #[cfg(feature = "state")] pub on_guild_member_update: Option<Arc<Fn(Context, Option<Member>, Member) + Send + Sync + 'static>>, + #[cfg(not(feature = "state"))] + pub on_guild_member_update: Option<Arc<Fn(Context, GuildMemberUpdateEvent) + Send + Sync + 'static>>, pub on_guild_members_chunk: Option<Arc<Fn(Context, GuildId, HashMap<UserId, Member>) + Send + Sync + 'static>>, pub on_guild_role_create: Option<Arc<Fn(Context, GuildId, Role) + Send + Sync + 'static>>, + #[cfg(feature = "state")] pub on_guild_role_delete: Option<Arc<Fn(Context, GuildId, RoleId, Option<Role>) + Send + Sync + 'static>>, + #[cfg(not(feature = "state"))] + pub on_guild_role_delete: Option<Arc<Fn(Context, GuildId, RoleId) + Send + Sync + 'static>>, + #[cfg(feature = "state")] pub on_guild_role_update: Option<Arc<Fn(Context, GuildId, Option<Role>, Role) + Send + Sync + 'static>>, + #[cfg(not(feature = "state"))] + pub on_guild_role_update: Option<Arc<Fn(Context, GuildId, Role) + Send + Sync + 'static>>, pub on_guild_sync: Option<Arc<Fn(Context, GuildSyncEvent) + Send + Sync + 'static>>, pub on_guild_unavailable: Option<Arc<Fn(Context, GuildId) + Send + Sync + 'static>>, pub on_guild_update: Option<Arc<Fn(Context, Option<LiveGuild>, Guild) + Send + Sync + 'static>>, @@ -59,7 +77,10 @@ pub struct EventStore { pub on_reaction_remove: Option<Arc<Fn(Context, Reaction) + Send + Sync + 'static>>, pub on_reaction_remove_all: Option<Arc<Fn(Context, ChannelId, MessageId) + Send + Sync + 'static>>, pub on_message_update: Option<Arc<Fn(Context, MessageUpdateEvent) + Send + Sync + 'static>>, + #[cfg(feature = "state")] pub on_note_update: Option<Arc<Fn(Context, UserId, Option<String>, String) + Send + Sync + 'static>>, + #[cfg(not(feature = "state"))] + pub on_note_update: Option<Arc<Fn(Context, UserId, String) + Send + Sync + 'static>>, pub on_presence_replace: Option<Arc<Fn(Context, Vec<Presence>) + Send + Sync + 'static>>, pub on_presence_update: Option<Arc<Fn(Context, PresenceUpdateEvent) + Send + Sync + 'static>>, pub on_ready: Option<Arc<Fn(Context, Ready) + Send + Sync + 'static>>, @@ -69,8 +90,14 @@ pub struct EventStore { pub on_typing_start: Option<Arc<Fn(Context, TypingStartEvent) + Send + Sync + 'static>>, pub on_unknown: Option<Arc<Fn(Context, String, BTreeMap<String, Value>) + Send + Sync + 'static>>, pub on_user_guild_settings_update: Option<Arc<Fn(Context, Option<UserGuildSettings>, UserGuildSettings) + Send + Sync + 'static>>, + #[cfg(feature = "state")] pub on_user_update: Option<Arc<Fn(Context, CurrentUser, CurrentUser) + Send + Sync + 'static>>, + #[cfg(not(feature = "state"))] + pub on_user_update: Option<Arc<Fn(Context, CurrentUser) + Send + Sync + 'static>>, + #[cfg(feature = "state")] pub on_user_settings_update: Option<Arc<Fn(Context, UserSettings, UserSettings) + Send + Sync + 'static>>, + #[cfg(not(feature = "state"))] + pub on_user_settings_update: Option<Arc<Fn(Context, UserSettingsUpdateEvent) + Send + Sync + 'static>>, pub on_voice_server_update: Option<Arc<Fn(Context, VoiceServerUpdateEvent) + Send + Sync + 'static>>, pub on_voice_state_update: Option<Arc<Fn(Context, Option<GuildId>, VoiceState) + Send + Sync + 'static>>, pub on_webhook_update: Option<Arc<Fn(Context, GuildId, ChannelId) + Send + Sync + 'static>>, diff --git a/src/client/mod.rs b/src/client/mod.rs index f270b31..77f1086 100644 --- a/src/client/mod.rs +++ b/src/client/mod.rs @@ -57,11 +57,16 @@ use std::collections::{BTreeMap, HashMap}; use std::sync::{Arc, Mutex}; use std::thread; use std::time::Duration; -use ::ext::framework::Framework; -use ::ext::state::State; use ::internal::prelude::*; use ::model::*; +#[cfg(feature = "framework")] +use ::ext::framework::Framework; + +#[cfg(feature = "state")] +use ::ext::state::State; + +#[cfg(feature = "state")] lazy_static! { /// The STATE is a mutable lazily-initialized static binding. It can be /// accessed across any function and in any context. @@ -220,6 +225,7 @@ pub enum ClientError { pub struct Client { pub connections: Vec<Arc<Mutex<Connection>>>, event_store: Arc<Mutex<EventStore>>, + #[cfg(feature="framework")] framework: Arc<Mutex<Framework>>, login_type: LoginType, token: String, @@ -271,6 +277,7 @@ impl Client { /// /// [`on_message`]: #method.on_message /// [framework docs]: ../ext/framework/index.html + #[cfg(feature="framework")] pub fn with_framework<F>(&mut self, f: F) where F: FnOnce(Framework) -> Framework + Send + Sync + 'static { self.framework = Arc::new(Mutex::new(f(Framework::default()))); @@ -403,16 +410,6 @@ impl Client { .on_call_delete = Some(Arc::new(handler)); } - /// Attaches a handler for when a [`CallUpdate`] is received. - /// - /// [`CallUpdate`]: ../model/enum.Event.html#variant.CallUpdate - pub fn on_call_update<F>(&mut self, handler: F) - where F: Fn(Context, Option<Call>, Option<Call>) + Send + Sync + 'static { - self.event_store.lock() - .unwrap() - .on_call_update = Some(Arc::new(handler)); - } - /// Attaches a handler for when a [`ChannelCreate`] is received. /// /// [`ChannelCreate`]: ../model/enum.Event.html#variant.ChannelCreate @@ -473,26 +470,6 @@ impl Client { .on_guild_create = Some(Arc::new(handler)); } - /// Attaches a handler for when a [`GuilDelete`] is received. - /// - /// Returns a partial guild as well as - optionally - the full guild, with - /// data like [`Role`]s. This can be `None` in the event that it was not in - /// the [`State`]. - /// - /// **Note**: The relevant guild is _removed_ from the State when this event - /// is received. If you need to keep it, you can either re-insert it - /// yourself back into the State or manage it in another way. - /// - /// [`GuildDelete`]: ../model/enum.Event.html#variant.GuildDelete - /// [`Role`]: ../model/struct.Role.html - /// [`State`]: ../ext/state/struct.State.html - pub fn on_guild_delete<F>(&mut self, handler: F) - where F: Fn(Context, Guild, Option<LiveGuild>) + Send + Sync + 'static { - self.event_store.lock() - .unwrap() - .on_guild_delete = Some(Arc::new(handler)); - } - /// Attaches a handler for when a [`GuildEmojisUpdate`] is received. /// /// The `HashMap` of emojis is the new full list of emojis. @@ -525,29 +502,6 @@ impl Client { .on_guild_member_addition = Some(Arc::new(handler)); } - /// Attaches a handler for when a [`GuildMemberRemove`] is received. - /// - /// Returns the user's associated `Member` object, _if_ it existed in the - /// state. - /// - /// [`GuildMemberRemove`]: ../model/enum.Event.html#variant.GuildMemberRemove - pub fn on_guild_member_remove<F>(&mut self, handler: F) - where F: Fn(Context, GuildId, User, Option<Member>) + Send + Sync + 'static { - self.event_store.lock() - .unwrap() - .on_guild_member_removal = Some(Arc::new(handler)); - } - - /// Attaches a handler for when a [`GuildMemberUpdate`] is received. - /// - /// [`GuildMemberUpdate`]: ../model/enum.Event.html#variant.GuildMemberUpdate - pub fn on_guild_member_update<F>(&mut self, handler: F) - where F: Fn(Context, Option<Member>, Member) + Send + Sync + 'static { - self.event_store.lock() - .unwrap() - .on_guild_member_update = Some(Arc::new(handler)); - } - /// Attaches a handler for when a [`GuildMembersChunk`] is received. /// /// [`GuildMembersChunk`]: ../model/enum.Event.html#variant.GuildMembersChunk @@ -568,16 +522,6 @@ impl Client { .on_guild_role_create = Some(Arc::new(handler)); } - /// Attaches a handler for when a [`GuildRoleDelete`] is received. - /// - /// [`GuildRoleDelete`]: ../model/enum.Event.html#variant.GuildRoleDelete - pub fn on_guild_role_delete<F>(&mut self, handler: F) - where F: Fn(Context, GuildId, RoleId, Option<Role>) + Send + Sync + 'static { - self.event_store.lock() - .unwrap() - .on_guild_role_delete = Some(Arc::new(handler)); - } - /// Attaches a handler for when a [`GuildRoleUpdate`] is received. /// /// The optional `Role` is the role prior to updating. This can be `None` if @@ -693,19 +637,6 @@ impl Client { .on_message_update = Some(Arc::new(handler)); } - /// Attaches a handler for when a [`UserNoteUpdate`] is received. - /// - /// Optionally returns the old note for the [`User`], if one existed. - /// - /// [`User`]: ../model/struct.User.html - /// [`UserNoteUpdate`]: ../model/enum.Event.html#variant.UserNoteUpdate - pub fn on_note_update<F>(&mut self, handler: F) - where F: Fn(Context, UserId, Option<String>, String) + Send + Sync + 'static { - self.event_store.lock() - .unwrap() - .on_note_update = Some(Arc::new(handler)); - } - /// Attaches a handler for when a [`PresencesReplace`] is received. /// /// [`PresencesReplace`]: ../model/enum.Event.html#variant.PresencesReplace @@ -733,7 +664,7 @@ impl Client { where F: Fn(Context, Reaction) + Send + Sync + 'static { self.event_store.lock() .unwrap() - .on_reaction_add = Some(Arc::new(handler)) + .on_reaction_add = Some(Arc::new(handler)); } /// Attached a handler for when a [`ReactionRemove`] is received. @@ -743,7 +674,7 @@ impl Client { where F: Fn(Context, Reaction) + Send + Sync + 'static { self.event_store.lock() .unwrap() - .on_reaction_remove = Some(Arc::new(handler)) + .on_reaction_remove = Some(Arc::new(handler)); } /// Attached a handler for when a [`ReactionRemoveAll`] is received. @@ -753,7 +684,7 @@ impl Client { where F: Fn(Context, ChannelId, MessageId) + Send + Sync + 'static { self.event_store.lock() .unwrap() - .on_reaction_remove_all = Some(Arc::new(handler)) + .on_reaction_remove_all = Some(Arc::new(handler)); } /// Register an event to be called whenever a Ready event is received. @@ -868,26 +799,6 @@ impl Client { .on_user_guild_settings_update = Some(Arc::new(handler)); } - /// Attaches a handler for when a [`UserUpdate`] is received. - /// - /// [`UserUpdate`]: ../model/enum.Event.html#variant.UserUpdate - pub fn on_user_update<F>(&mut self, handler: F) - where F: Fn(Context, CurrentUser, CurrentUser) + Send + Sync + 'static { - self.event_store.lock() - .unwrap() - .on_user_update = Some(Arc::new(handler)); - } - - /// Attaches a handler for when a [`UserSettingsUpdate`] is received. - /// - /// [`UserSettingsUpdate`]: ../model/enum.Event.html#variant.UserSettingsUpdate - pub fn on_user_settings_update<F>(&mut self, handler: F) - where F: Fn(Context, UserSettings, UserSettings) + Send + Sync + 'static { - self.event_store.lock() - .unwrap() - .on_user_settings_update = Some(Arc::new(handler)); - } - /// Attaches a handler for when a [`VoiceServerUpdate`] is received. /// /// [`VoiceServerUpdate`]: ../model/enum.Event.html#variant.VoiceServerUpdate @@ -936,28 +847,47 @@ impl Client { Ok((connection, ready)) => { self.connections.push(Arc::new(Mutex::new(connection))); - STATE.lock() - .unwrap() - .update_with_ready(&ready); + feature_state_enabled! {{ + STATE.lock() + .unwrap() + .update_with_ready(&ready); + }} match self.connections.last() { Some(connection) => { - dispatch(Ok(Event::Ready(ready)), - connection.clone(), - self.framework.clone(), - self.login_type, - self.event_store.clone()); + feature_framework! {{ + dispatch(Ok(Event::Ready(ready)), + connection.clone(), + self.framework.clone(), + self.login_type, + self.event_store.clone()); + } { + dispatch(Ok(Event::Ready(ready)), + connection.clone(), + self.login_type, + self.event_store.clone()); + }} let connection_clone = connection.clone(); let event_store = self.event_store.clone(); - let framework = self.framework.clone(); let login_type = self.login_type; - thread::spawn(move || { - handle_connection(connection_clone, - framework, - login_type, - event_store); - }); + + feature_framework! {{ + let framework = self.framework.clone(); + + thread::spawn(move || { + handle_connection(connection_clone, + framework, + login_type, + event_store) + }); + } { + thread::spawn(move || { + handle_connection(connection_clone, + login_type, + event_store) + }); + }} }, None => return Err(Error::Client(ClientError::ConnectionUnknown)), } @@ -986,6 +916,201 @@ impl Client { } } +#[cfg(feature = "state")] +impl Client { + /// Attaches a handler for when a [`CallUpdate`] is received. + /// + /// [`CallUpdate`]: ../model/enum.Event.html#variant.CallUpdate + pub fn on_call_update<F>(&mut self, handler: F) + where F: Fn(Context, Option<Call>, Option<Call>) + Send + Sync + 'static { + self.event_store.lock() + .unwrap() + .on_call_update = Some(Arc::new(handler)); + } + + /// Attaches a handler for when a [`GuildDelete`] is received. + /// + /// Returns a partial guild as well as - optionally - the full guild, with + /// data like [`Role`]s. This can be `None` in the event that it was not in + /// the [`State`]. + /// + /// **Note**: The relevant guild is _removed_ from the State when this event + /// is received. If you need to keep it, you can either re-insert it + /// yourself back into the State or manage it in another way. + /// + /// [`GuildDelete`]: ../model/enum.Event.html#variant.GuildDelete + /// [`Role`]: ../model/struct.Role.html + /// [`State`]: ../ext/state/struct.State.html + pub fn on_guild_delete<F>(&mut self, handler: F) + where F: Fn(Context, Guild, Option<LiveGuild>) + Send + Sync + 'static { + self.event_store.lock() + .unwrap() + .on_guild_delete = Some(Arc::new(handler)); + } + + /// Attaches a handler for when a [`GuildMemberRemove`] is received. + /// + /// Returns the user's associated `Member` object, _if_ it existed in the + /// state. + /// + /// [`GuildMemberRemove`]: ../model/enum.Event.html#variant.GuildMemberRemove + pub fn on_guild_member_remove<F>(&mut self, handler: F) + where F: Fn(Context, GuildId, User, Option<Member>) + Send + Sync + 'static { + self.event_store.lock() + .unwrap() + .on_guild_member_removal = Some(Arc::new(handler)); + } + + /// Attaches a handler for when a [`GuildMemberUpdate`] is received. + /// + /// [`GuildMemberUpdate`]: ../model/enum.Event.html#variant.GuildMemberUpdate + pub fn on_guild_member_update<F>(&mut self, handler: F) + where F: Fn(Context, Option<Member>, Member) + Send + Sync + 'static { + self.event_store.lock() + .unwrap() + .on_guild_member_update = Some(Arc::new(handler)); + } + + /// Attaches a handler for when a [`GuildRoleDelete`] is received. + /// + /// [`GuildRoleDelete`]: ../model/enum.Event.html#variant.GuildRoleDelete + pub fn on_guild_role_delete<F>(&mut self, handler: F) + where F: Fn(Context, GuildId, RoleId, Option<Role>) + Send + Sync + 'static { + self.event_store.lock() + .unwrap() + .on_guild_role_delete = Some(Arc::new(handler)); + } + + /// Attaches a handler for when a [`UserNoteUpdate`] is received. + /// + /// Optionally returns the old note for the [`User`], if one existed. + /// + /// [`User`]: ../model/struct.User.html + /// [`UserNoteUpdate`]: ../model/enum.Event.html#variant.UserNoteUpdate + pub fn on_note_update<F>(&mut self, handler: F) + where F: Fn(Context, UserId, Option<String>, String) + Send + Sync + 'static { + self.event_store.lock() + .unwrap() + .on_note_update = Some(Arc::new(handler)); + } + + /// Attaches a handler for when a [`UserSettingsUpdate`] is received. + /// + /// The old user settings will be provided as well. + /// + /// [`UserSettingsUpdate`]: ../model/enum.Event.html#variant.UserSettingsUpdate + pub fn on_user_settings_update<F>(&mut self, handler: F) + where F: Fn(Context, UserSettings, UserSettings) + Send + Sync + 'static { + self.event_store.lock() + .unwrap() + .on_user_settings_update = Some(Arc::new(handler)); + } + + /// Attaches a handler for when a [`UserUpdate`] is received. + /// + /// The old current user will be provided as well. + /// + /// [`UserUpdate`]: ../model/enum.Event.html#variant.UserUpdate + pub fn on_user_update<F>(&mut self, handler: F) + where F: Fn(Context, CurrentUser, CurrentUser) + Send + Sync + 'static { + self.event_store.lock() + .unwrap() + .on_user_update = Some(Arc::new(handler)); + } +} + +#[cfg(not(feature = "state"))] +impl Client { + /// Attaches a handler for when a [`CallUpdate`] is received. + /// + /// [`CallUpdate`]: ../model/enum.Event.html#variant.CallUpdate + pub fn on_call_update<F>(&mut self, handler: F) + where F: Fn(Context, CallUpdateEvent) + Send + Sync + 'static { + self.event_store.lock() + .unwrap() + .on_call_update = Some(Arc::new(handler)); + } + + /// Attaches a handler for when a [`GuildDelete`] is received. + /// + /// [`GuildDelete`]: ../model/enum.Event.html#variant.GuildDelete + /// [`Role`]: ../model/struct.Role.html + /// [`State`]: ../ext/state/struct.State.html + pub fn on_guild_delete<F>(&mut self, handler: F) + where F: Fn(Context, Guild, Option<LiveGuild>) + Send + Sync + 'static { + self.event_store.lock() + .unwrap() + .on_guild_delete = Some(Arc::new(handler)); + } + + /// Attaches a handler for when a [`GuildMemberRemove`] is received. + /// + /// Returns the user's associated `Member` object, _if_ it existed in the + /// state. + /// + /// [`GuildMemberRemove`]: ../model/enum.Event.html#variant.GuildMemberRemove + pub fn on_guild_member_remove<F>(&mut self, handler: F) + where F: Fn(Context, GuildId, User) + Send + Sync + 'static { + self.event_store.lock() + .unwrap() + .on_guild_member_removal = Some(Arc::new(handler)); + } + + /// Attaches a handler for when a [`GuildMemberUpdate`] is received. + /// + /// [`GuildMemberUpdate`]: ../model/enum.Event.html#variant.GuildMemberUpdate + pub fn on_guild_member_update<F>(&mut self, handler: F) + where F: Fn(Context, GuildMemberUpdateEvent) + Send + Sync + 'static { + self.event_store.lock() + .unwrap() + .on_guild_member_update = Some(Arc::new(handler)); + } + + /// Attaches a handler for when a [`GuildRoleDelete`] is received. + /// + /// [`GuildRoleDelete`]: ../model/enum.Event.html#variant.GuildRoleDelete + pub fn on_guild_role_delete<F>(&mut self, handler: F) + where F: Fn(Context, GuildId, RoleId) + Send + Sync + 'static { + self.event_store.lock() + .unwrap() + .on_guild_role_delete = Some(Arc::new(handler)); + } + + /// Attaches a handler for when a [`UserNoteUpdate`] is received. + /// + /// Optionally returns the old note for the [`User`], if one existed. + /// + /// [`User`]: ../model/struct.User.html + /// [`UserNoteUpdate`]: ../model/enum.Event.html#variant.UserNoteUpdate + pub fn on_note_update<F>(&mut self, handler: F) + where F: Fn(Context, UserId, String) + Send + Sync + 'static { + self.event_store.lock() + .unwrap() + .on_note_update = Some(Arc::new(handler)); + } + + /// Attaches a handler for when a [`UserSettingsUpdate`] is received. + /// + /// [`UserSettingsUpdate`]: ../model/enum.Event.html#variant.UserSettingsUpdate + pub fn on_user_settings_update<F>(&mut self, handler: F) + where F: Fn(Context, UserSettingsEvent) + Send + Sync + 'static { + self.event_store.lock() + .unwrap() + .on_user_settings_update = Some(Arc::new(handler)); + } + + /// Attaches a handler for when a [`UserUpdate`] is received. + /// + /// [`UserUpdate`]: ../model/enum.Event.html#variant.UserUpdate + pub fn on_user_update<F>(&mut self, handler: F) + where F: Fn(Context, CurrentUser) + Send + Sync + 'static { + self.event_store.lock() + .unwrap() + .on_user_update = Some(Arc::new(handler)); + } +} + +#[cfg(feature="framework")] fn handle_connection(connection: Arc<Mutex<Connection>>, framework: Arc<Mutex<Framework>>, login_type: LoginType, @@ -1005,18 +1130,45 @@ fn handle_connection(connection: Arc<Mutex<Connection>>, } } +#[cfg(not(feature="framework"))] +fn handle_connection(connection: Arc<Mutex<Connection>>, + login_type: LoginType, + event_store: Arc<Mutex<EventStore>>) { + loop { + let event = { + let mut connection = connection.lock().unwrap(); + + connection.receive() + }; + + dispatch(event, + connection.clone(), + login_type, + event_store.clone()); + } +} + fn login(token: &str, login_type: LoginType) -> Client { let token = token.to_owned(); http::set_token(&token); - Client { - connections: Vec::default(), - event_store: Arc::new(Mutex::new(EventStore::default())), - framework: Arc::new(Mutex::new(Framework::default())), - login_type: login_type, - token: token.to_owned(), - } + feature_framework! {{ + Client { + connections: Vec::default(), + event_store: Arc::new(Mutex::new(EventStore::default())), + framework: Arc::new(Mutex::new(Framework::default())), + login_type: login_type, + token: token.to_owned(), + } + } { + Client { + connections: Vec::default(), + event_store: Arc::new(Mutex::new(EventStore::default())), + login_type: login_type, + token: token.to_owned(), + } + }} } /// Validates that a token is likely in a valid format. diff --git a/src/ext/mod.rs b/src/ext/mod.rs index bb87911..312074b 100644 --- a/src/ext/mod.rs +++ b/src/ext/mod.rs @@ -5,10 +5,17 @@ //! //! See each extension's module-level documentation for more information. //! +//! Note that the framework module requires the `framework` feature to be +//! enabled (enabled by default), the state requires the `state` feature to be +//! enabled (enabled by default), and voice support requires the `voice` feature +//! to be enabled (disabled by default). +//! //! [`Client`]: ../client/struct.Client.html //! [`Connection`]: ../client/struct.Connection.html +#[cfg(feature = "framework")] pub mod framework; +#[cfg(feature = "state")] pub mod state; -#[cfg(feature="voice")] +#[cfg(feature = "voice")] pub mod voice; diff --git a/src/ext/state/mod.rs b/src/ext/state/mod.rs index fa38b6f..5c56a54 100644 --- a/src/ext/state/mod.rs +++ b/src/ext/state/mod.rs @@ -166,7 +166,7 @@ impl State { self.update_with_guild_member_remove(event); }, Event::GuildMemberUpdate(ref event) => { - self.update_with_guild_member_update(event, false); + self.update_with_guild_member_update(event); }, Event::GuildMembersChunk(ref event) => { self.update_with_guild_members_chunk(event); @@ -448,10 +448,8 @@ impl State { } pub fn update_with_guild_member_update(&mut self, - event: &GuildMemberUpdateEvent, - old: bool) + event: &GuildMemberUpdateEvent) -> Option<Member> { - if let Some(guild) = self.guilds.get_mut(&event.guild_id) { let mut found = false; diff --git a/src/model/channel.rs b/src/model/channel.rs index 429fa01..72a1f09 100644 --- a/src/model/channel.rs +++ b/src/model/channel.rs @@ -1,11 +1,5 @@ -use hyper::Client as HyperClient; -use serde_json::builder::ObjectBuilder; use std::borrow::Cow; use std::fmt::{self, Write}; -use std::fs::File; -use std::io::{Read, Write as IoWrite}; -use std::mem; -use std::path::{Path, PathBuf}; use super::utils::{ decode_id, into_map, @@ -15,16 +9,34 @@ use super::utils::{ warn_field, }; use super::*; -use super::utils; -use ::utils::builder::{CreateEmbed, CreateInvite, EditChannel}; -use ::client::{STATE, http}; use ::constants; use ::internal::prelude::*; use ::utils::decode_array; +#[cfg(feature = "methods")] +use hyper::Client as HyperClient; +#[cfg(feature = "methods")] +use serde_json::builder::ObjectBuilder; +#[cfg(feature = "methods")] +use std::fs::File; +#[cfg(feature = "methods")] +use std::io::{Read, Write as IoWrite}; +#[cfg(feature = "methods")] +use std::mem; +#[cfg(feature = "methods")] +use std::path::{Path, PathBuf}; +#[cfg(feature = "methods")] +use super::utils; + +#[cfg(feature = "methods")] +use ::utils::builder::{CreateEmbed, CreateInvite, EditChannel}; +#[cfg(feature = "methods")] +use ::client::{STATE, http}; + impl Attachment { /// If this attachment is an image, then a tuple of the width and height /// in pixels is returned. + #[cfg(feature = "methods")] pub fn dimensions(&self) -> Option<(u64, u64)> { if let (Some(width), Some(height)) = (self.width, self.height) { Some((width, height)) @@ -99,6 +111,7 @@ impl Attachment { /// [`Error::Hyper`]: ../enum.Error.html#variant.Hyper /// [`Error::Io`]: ../enum.Error.html#variant.Io /// [`Message`]: struct.Message.html + #[cfg(feature = "methods")] pub fn download(&self) -> Result<Vec<u8>> { let hyper = HyperClient::new(); let mut response = try!(hyper.get(&self.url).send()); @@ -163,6 +176,7 @@ impl Attachment { /// [`Error::Hyper`]: ../enum.Error.html#variant.Hyper /// [`Error::Io`]: ../enum.Error.html#variant.Io /// [`Message`]: struct.Message.html + #[cfg(feature = "methods")] pub fn download_to_directory<P: AsRef<Path>>(&self, path: P) -> Result<PathBuf> { let bytes = try!(self.download()); @@ -196,6 +210,7 @@ impl Channel { /// closest functionality is leaving it. /// /// [`Group`]: struct.Group.html + #[cfg(feature = "methods")] pub fn delete(&self) -> Result<()> { match *self { Channel::Group(ref group) => { @@ -258,6 +273,7 @@ impl Embed { /// This should only be useful in conjunction with [`Webhook::execute`]. /// /// [`Webhook::execute`]: struct.Webhook.html + #[cfg(feature = "methods")] #[inline(always)] pub fn fake<F>(f: F) -> Value where F: FnOnce(CreateEmbed) -> CreateEmbed { f(CreateEmbed::default()).0.build() @@ -270,6 +286,7 @@ impl Group { /// /// **Note**: Groups have a limit of 10 recipients, including the current /// user. + #[cfg(feature = "methods")] pub fn add_recipient<U: Into<UserId>>(&self, user: U) -> Result<()> { let user = user.into(); @@ -282,6 +299,7 @@ impl Group { } /// Broadcasts that the current user is typing in the group. + #[cfg(feature = "methods")] pub fn broadcast_typing(&self) -> Result<()> { http::broadcast_typing(self.channel_id.0) } @@ -301,6 +319,7 @@ impl Group { /// /// [`ClientError::DeleteMessageDaysAmount`]: ../client/enum.ClientError.html#variant.DeleteMessageDaysAmount /// [`Context::delete_messages`]: ../client/struct.Context.html#delete_messages + #[cfg(feature = "methods")] pub fn delete_messages(&self, message_ids: &[MessageId]) -> Result<()> { if message_ids.len() < 2 || message_ids.len() > 100 { return Err(Error::Client(ClientError::BulkDeleteAmount)); @@ -324,6 +343,7 @@ impl Group { } /// Leaves the group. + #[cfg(feature = "methods")] pub fn leave(&self) -> Result<Group> { http::leave_group(self.channel_id.0) } @@ -352,6 +372,7 @@ impl Group { } /// Retrieves the list of messages that have been pinned in the group. + #[cfg(feature = "methods")] pub fn pins(&self) -> Result<Vec<Message>> { http::get_pins(self.channel_id.0) } @@ -360,6 +381,7 @@ impl Group { /// the group, then nothing is done. /// /// **Note**: This is only available to the group owner. + #[cfg(feature = "methods")] pub fn remove_recipient<U: Into<UserId>>(&self, user: U) -> Result<()> { let user = user.into(); @@ -378,6 +400,7 @@ impl Group { /// **Note**: Requires the [Send Messages] permission. /// /// [Send Messages]: permissions/constant.SEND_MESSAGES.html + #[cfg(feature = "methods")] pub fn send_message(&self, content: &str) -> Result<Message> { let map = ObjectBuilder::new() .insert("content", content) @@ -408,6 +431,7 @@ impl Message { /// [`ClientError::InvalidPermissions`]: ../client/enum.ClientError.html#variant.InvalidPermissions /// [`ClientError::InvalidUser`]: ../client/enum.ClientError.html#variant.InvalidUser /// [Manage Messages]: permissions/constant.MANAGE_MESSAGES.html + #[cfg(feature = "methods")] pub fn delete(&self) -> Result<()> { let req = permissions::MANAGE_MESSAGES; let is_author = self.author.id != STATE.lock().unwrap().user.id; @@ -435,6 +459,7 @@ impl Message { /// [`ClientError::InvalidPermissions`]: ../client/enum.ClientError.html#variant.InvalidPermissions /// [`Reaction`]: struct.Reaction.html /// [Manage Messages]: permissions/constant.MANAGE_MESSAGES.html + #[cfg(feature = "methods")] pub fn delete_reactions(&self) -> Result<()> { let req = permissions::MANAGE_MESSAGES; @@ -462,6 +487,7 @@ impl Message { /// /// [`ClientError::InvalidUser`]: ../client/enum.ClientError.html#variant.InvalidUser /// [`ClientError::MessageTooLong`]: enum.ClientError.html#variant.MessageTooLong + #[cfg(feature = "methods")] pub fn edit(&mut self, new_content: &str) -> Result<()> { if let Some(length_over) = Message::overflow_length(new_content) { return Err(Error::Client(ClientError::MessageTooLong(length_over))); @@ -516,6 +542,7 @@ impl Message { /// /// [`ClientError::InvalidPermissions`]: ../client/enum.ClientError.html#variant.InvalidPermissions /// [Manage Messages]: permissions/constant.MANAGE_MESSAGES.html + #[cfg(feature = "methods")] pub fn pin(&self) -> Result<()> { let req = permissions::MANAGE_MESSAGES; @@ -539,6 +566,7 @@ impl Message { /// [`Emoji`]: struct.Emoji.html /// [Add Reactions]: permissions/constant.ADD_REACTIONS.html /// [permissions]: permissions + #[cfg(feature = "methods")] pub fn react<R: Into<ReactionType>>(&self, reaction_type: R) -> Result<()> { let req = permissions::ADD_REACTIONS; @@ -572,6 +600,7 @@ impl Message { /// [`ClientError::InvalidPermissions`]: ../client/enum.ClientError.html#variant.InvalidPermissions /// [`ClientError::MessageTooLong`]: enum.ClientError.html#variant.MessageTooLong /// [Send Messages]: permissions/constant.SEND_MESSAGES.html + #[cfg(feature = "methods")] pub fn reply(&self, content: &str) -> Result<Message> { if let Some(length_over) = Message::overflow_length(content) { return Err(Error::Client(ClientError::MessageTooLong(length_over))); @@ -609,6 +638,7 @@ impl Message { /// /// [`ClientError::InvalidPermissions`]: ../client/enum.ClientError.html#variant.InvalidPermissions /// [Manage Messages]: permissions/constant.MANAGE_MESSAGES.html + #[cfg(feature = "methods")] pub fn unpin(&self) -> Result<()> { let req = permissions::MANAGE_MESSAGES; @@ -621,6 +651,7 @@ impl Message { } impl PermissionOverwrite { + #[doc(hidden)] pub fn decode(value: Value) -> Result<PermissionOverwrite> { let mut map = try!(into_map(value)); let id = try!(remove(&mut map, "id").and_then(decode_id)); @@ -641,6 +672,7 @@ impl PermissionOverwrite { impl PrivateChannel { /// Broadcasts that the current user is typing to the recipient. + #[cfg(feature = "methods")] pub fn broadcast_typing(&self) -> Result<()> { http::broadcast_typing(self.id.0) } @@ -672,6 +704,7 @@ impl PrivateChannel { /// [`ClientError::InvalidUser`] if the current user is not a bot user. /// /// [`ClientError::InvalidUser`]: ../client/enum.ClientError.html#variant.InvalidOperationAsUser + #[cfg(feature = "methods")] pub fn delete_messages(&self, message_ids: &[MessageId]) -> Result<()> { if !STATE.lock().unwrap().user.bot { return Err(Error::Client(ClientError::InvalidOperationAsUser)); @@ -691,12 +724,14 @@ impl PrivateChannel { /// Deletes the channel. This does not delete the contents of the channel, /// and is equivilant to closing a private channel on the client, which can /// be re-opened. + #[cfg(feature = "methods")] pub fn delete(&self) -> Result<Channel> { http::delete_channel(self.id.0) } /// Retrieves the list of messages that have been pinned in the private /// channel. + #[cfg(feature = "methods")] pub fn pins(&self) -> Result<Vec<Message>> { http::get_pins(self.id.0) } @@ -712,6 +747,7 @@ impl PrivateChannel { /// over the limit. /// /// [`ClientError::MessageTooLong`]: ../client/enum.ClientError.html#variant.MessageTooLong + #[cfg(feature = "methods")] pub fn send_message(&self, content: &str) -> Result<Message> { if let Some(length_over) = Message::overflow_length(content) { return Err(Error::Client(ClientError::MessageTooLong(length_over))); @@ -749,10 +785,12 @@ impl PublicChannel { /// /// [`ClientError::InvalidPermissions`]: ../client/enum.ClientError.html#variant.InvalidPermissions /// [Send Messages]: permissions/constants.SEND_MESSAGES.html + #[cfg(feature = "methods")] pub fn broadcast_typing(&self) -> Result<()> { http::broadcast_typing(self.id.0) } + #[cfg(feature = "methods")] pub fn create_invite<F>(&self, f: F) -> Result<RichInvite> where F: FnOnce(CreateInvite) -> CreateInvite { let req = permissions::CREATE_INVITE; @@ -766,6 +804,7 @@ impl PublicChannel { http::create_invite(self.id.0, map) } + #[doc(hidden)] pub fn decode(value: Value) -> Result<PublicChannel> { let mut map = try!(into_map(value)); @@ -774,6 +813,7 @@ impl PublicChannel { PublicChannel::decode_guild(Value::Object(map), id) } + #[doc(hidden)] pub fn decode_guild(value: Value, guild_id: GuildId) -> Result<PublicChannel> { let mut map = try!(into_map(value)); missing!(map, PublicChannel { @@ -792,6 +832,7 @@ impl PublicChannel { } /// Deletes this channel, returning the channel on a successful deletion. + #[cfg(feature = "methods")] pub fn delete(&self) -> Result<Channel> { let req = permissions::MANAGE_CHANNELS; @@ -801,8 +842,9 @@ impl PublicChannel { http::delete_channel(self.id.0) } - pub fn edit<F>(&mut self, f: F) -> Result<()> + #[cfg(feature = "methods")] + pub fn edit<F>(&mut self, f: F) -> Result<()> where F: FnOnce(EditChannel) -> EditChannel { let req = permissions::MANAGE_CHANNELS; @@ -834,6 +876,7 @@ impl PublicChannel { self.id.mention() } + #[cfg(feature = "methods")] pub fn pins(&self) -> Result<Vec<Message>> { http::get_pins(self.id.0) } @@ -856,6 +899,7 @@ impl PublicChannel { /// [`ClientError::InvalidPermissions`]: ../client/enum.ClientError.html#variant.InvalidPermissions /// [`ClientError::MessageTooLong`]: ../client/enum.ClientError.html#variant.MessageTooLong /// [Send Messages]: permissions/constant.SEND_MESSAGES.html + #[cfg(feature = "methods")] pub fn send_message(&self, content: &str) -> Result<Message> { if let Some(length_over) = Message::overflow_length(content) { return Err(Error::Client(ClientError::MessageTooLong(length_over))); @@ -881,6 +925,7 @@ impl PublicChannel { /// **Note**: Requires the [Manage Webhooks] permission. /// /// [Manage Webhooks]: permissions/constant.MANAGE_WEBHOOKS.html + #[cfg(feature = "methods")] pub fn webhooks(&self) -> Result<Vec<Webhook>> { http::get_channel_webhooks(self.id.0) } @@ -908,6 +953,7 @@ impl Reaction { /// [`ClientError::InvalidPermissions`]: ../client/enum.ClientError.html#variant.InvalidPermissions /// [Manage Messages]: permissions/constant.MANAGE_MESSAGES.html /// [permissions]: permissions + #[cfg(feature = "methods")] pub fn delete(&self) -> Result<()> { let user = if self.user_id == STATE.lock().unwrap().user.id { None @@ -958,6 +1004,7 @@ impl Reaction { /// [`User`]: struct.User.html /// [Read Message History]: permissions/constant.READ_MESSAGE_HISTORY.html /// [permissions]: permissions + #[cfg(feature = "methods")] pub fn users<R, U>(&self, reaction_type: R, limit: Option<u8>, @@ -1013,6 +1060,7 @@ impl ReactionType { } } + #[doc(hidden)] pub fn decode(value: Value) -> Result<Self> { let mut map = try!(into_map(value)); let name = try!(remove(&mut map, "name").and_then(into_string)); diff --git a/src/model/gateway.rs b/src/model/gateway.rs index aa3d995..1a286af 100644 --- a/src/model/gateway.rs +++ b/src/model/gateway.rs @@ -734,6 +734,7 @@ impl Event { } impl Game { + #[cfg(feature="methods")] pub fn playing(name: String) -> Game { Game { kind: GameType::Playing, @@ -742,6 +743,7 @@ impl Game { } } + #[cfg(feature="methods")] pub fn streaming(name: String, url: String) -> Game { Game { kind: GameType::Streaming, @@ -750,6 +752,7 @@ impl Game { } } + #[doc(hidden)] pub fn decode(value: Value) -> Result<Option<Game>> { let mut map = try!(into_map(value)); @@ -771,6 +774,7 @@ impl Game { } impl Presence { + #[doc(hidden)] pub fn decode(value: Value) -> Result<Presence> { let mut value = try!(into_map(value)); let mut user_map = try!(remove(&mut value, "user").and_then(into_map)); diff --git a/src/model/guild.rs b/src/model/guild.rs index 1ab9bb3..a350cae 100644 --- a/src/model/guild.rs +++ b/src/model/guild.rs @@ -1,6 +1,5 @@ -use serde_json::builder::ObjectBuilder; use std::collections::HashMap; -use std::{fmt, mem}; +use std::fmt; use super::utils::{ decode_emojis, decode_members, @@ -14,11 +13,21 @@ use super::utils::{ warn_field }; use super::*; -use ::utils::builder::{EditGuild, EditMember, EditRole}; -use ::client::{STATE, http}; use ::internal::prelude::*; use ::utils::decode_array; +#[cfg(feature = "methods")] +use serde_json::builder::ObjectBuilder; +#[cfg(feature = "methods")] +use std::mem; +#[cfg(feature = "methods")] +use ::utils::builder::{EditGuild, EditMember, EditRole}; +#[cfg(feature = "methods")] +use ::client::http; + +#[cfg(feature = "state")] +use ::client::STATE; + impl From<Guild> for GuildContainer { fn from(guild: Guild) -> GuildContainer { GuildContainer::Guild(guild) @@ -41,6 +50,7 @@ impl Emoji { /// Finds the [`Guild`] that owns the emoji by looking through the state. /// /// [`Guild`]: struct.Guild.html + #[cfg(feature = "methods")] pub fn find_guild_id(&self) -> Option<GuildId> { STATE.lock() .unwrap() @@ -57,6 +67,7 @@ impl Emoji { /// **Note**: Only user accounts may use this method. /// /// [Manage Emojis]: permissions/constant.MANAGE_EMOJIS.html + #[cfg(feature = "methods")] pub fn delete(&self) -> Result<()> { match self.find_guild_id() { Some(guild_id) => http::delete_emoji(guild_id.0, self.id.0), @@ -71,6 +82,7 @@ impl Emoji { /// **Note**: Only user accounts may use this method. /// /// [Manage Emojis]: permissions/constant.MANAGE_EMOJIS.html + #[cfg(feature = "methods")] pub fn edit(&mut self, name: &str) -> Result<()> { match self.find_guild_id() { Some(guild_id) => { @@ -116,6 +128,7 @@ impl GuildInfo { impl Guild { /// Finds a role by Id within the guild. + #[cfg(feature = "methods")] pub fn find_role<R: Into<RoleId>>(&self, role_id: R) -> Option<&Role> { self.roles.get(&role_id.into()) } @@ -127,6 +140,7 @@ impl Guild { /// **Note**: Requires the [Change Nickname] permission. /// /// [Change Nickname]: permissions/constant.CHANGE_NICKNAME.html + #[cfg(feature = "methods")] #[inline] pub fn edit_nickname(&self, new_nickname: Option<&str>) -> Result<()> { http::edit_nickname(self.id.0, new_nickname) @@ -143,6 +157,7 @@ impl Guild { /// **Note**: Requires the [Manage Webhooks] permission. /// /// [Manage Webhooks]: permissions/constant.MANAGE_WEBHOOKS.html + #[cfg(feature = "methods")] #[inline] pub fn webhooks(&self) -> Result<Vec<Webhook>> { http::get_guild_webhooks(self.id.0) @@ -150,6 +165,7 @@ impl Guild { } impl LiveGuild { + #[cfg(feature = "state")] fn has_perms(&self, mut permissions: Permissions) -> Result<bool> { let member = match self.get_member(STATE.lock().unwrap().user.id) { Some(member) => member, @@ -163,6 +179,11 @@ impl LiveGuild { Ok(permissions.is_empty()) } + #[cfg(not(feature = "state"))] + fn has_perms(&self, mut permissions: Permissions) -> Result<bool> { + Ok(true) + } + /// Ban a [`User`] from the guild. All messages by the /// user within the last given number of days given will be deleted. This /// may be a range between `0` and `7`. @@ -190,6 +211,7 @@ impl LiveGuild { /// [`ClientError::InvalidPermissions`]: ../client/enum.ClientError.html#variant.InvalidPermissions /// [`User`]: struct.User.html /// [Ban Members]: permissions/constant.BAN_MEMBERS.html + #[cfg(feature = "methods")] pub fn ban<U: Into<UserId>>(&self, user: U, delete_message_days: u8) -> Result<()> { if delete_message_days > 7 { @@ -217,6 +239,7 @@ impl LiveGuild { /// [`Ban`]: struct.Ban.html /// [`ClientError::InvalidPermissions`]: ../client/enum.ClientError.html#variant.InvalidPermissions /// [Ban Members]: permissions/constant.BAN_MEMBERS.html + #[cfg(feature = "methods")] pub fn bans(&self) -> Result<Vec<Ban>> { let req = permissions::BAN_MEMBERS; @@ -249,6 +272,7 @@ impl LiveGuild { /// [`Channel`]: struct.Channel.html /// [`ClientError::InvalidPermissions`]: ../client/enum.ClientError.html#variant.InvalidPermissions /// [Manage Channels]: permissions/constants.MANAGE_CHANNELS.html + #[cfg(feature = "methods")] pub fn create_channel(&mut self, name: &str, kind: ChannelType) -> Result<Channel> { let req = permissions::MANAGE_CHANNELS; @@ -280,6 +304,7 @@ impl LiveGuild { /// [`Context::create_role`]: ../client/struct.Context.html#method.create_role /// [`Role`]: struct.Role.html /// [Manage Roles]: permissions/constants.MANAGE_ROLES.html + #[cfg(feature = "methods")] pub fn create_role<F>(&self, f: F) -> Result<Role> where F: FnOnce(EditRole) -> EditRole { let req = permissions::MANAGE_ROLES; @@ -352,6 +377,7 @@ impl LiveGuild { /// guild owner. /// /// [`ClientError::InvalidUser`]: ../client/enum.ClientError.html#variant.InvalidUser + #[cfg(feature = "methods")] pub fn delete(&self) -> Result<Guild> { if self.owner_id != STATE.lock().unwrap().user.id { let req = permissions::MANAGE_GUILD; @@ -376,6 +402,7 @@ impl LiveGuild { /// [`ClientError::InvalidPermissions`]: ../client/enum.ClientError.html#variant.InvalidPermissions /// [`Context::edit_guild`]: ../client/struct.Context.html#method.edit_guild /// [Manage Guild]: permissions/constants.MANAGE_GUILD.html + #[cfg(feature = "methods")] pub fn edit<F>(&mut self, f: F) -> Result<()> where F: FnOnce(EditGuild) -> EditGuild { let req = permissions::MANAGE_GUILD; @@ -421,6 +448,7 @@ impl LiveGuild { /// /// [`ClientError::InvalidPermissions`]: ../client/enum.ClientError.html#variant.InvalidPermissions /// [Change Nickname]: permissions/constant.CHANGE_NICKNAME.html + #[cfg(feature = "methods")] pub fn edit_nickname(&self, new_nickname: Option<&str>) -> Result<()> { let req = permissions::CHANGE_NICKNAME; @@ -450,6 +478,7 @@ impl LiveGuild { /// /// [`ClientError::InvalidPermissions`]: ../client/enum.ClientError.html#variant.InvalidPermissions /// [Manage Guild]: permissions/constant.MANAGE_GUILD.html + #[cfg(feature = "methods")] pub fn get_invites(&self) -> Result<Vec<RichInvite>> { let req = permissions::MANAGE_GUILD; @@ -526,6 +555,7 @@ impl LiveGuild { } /// Leaves the guild. + #[cfg(feature = "methods")] pub fn leave(&self) -> Result<Guild> { http::leave_guild(self.id.0) } @@ -655,6 +685,7 @@ impl LiveGuild { /// [`GuildPrune`]: struct.GuildPrune.html /// [`Member`]: struct.Member.html /// [Kick Members]: permissions/constant.KICK_MEMBERS.html + #[cfg(feature = "methods")] pub fn prune_count(&self, days: u16) -> Result<GuildPrune> { let req = permissions::KICK_MEMBERS; @@ -684,6 +715,7 @@ impl LiveGuild { /// [`GuildPrune`]: struct.GuildPrune.html /// [`Member`]: struct.Member.html /// [Kick Members]: permissions/constant.KICK_MEMBERS.html + #[cfg(feature = "methods")] pub fn start_prune(&self, days: u16) -> Result<GuildPrune> { let req = permissions::KICK_MEMBERS; @@ -710,6 +742,7 @@ impl LiveGuild { /// [`ClientError::InvalidPermissions`]: ../client/enum.ClientError.html#variant.InvalidPermissions /// [`User`]: struct.User.html /// [Ban Members]: permissions/constant.BAN_MEMBERS.html + #[cfg(feature = "methods")] pub fn unban<U: Into<UserId>>(&self, user: U) -> Result<()> { let req = permissions::BAN_MEMBERS; @@ -725,6 +758,7 @@ impl LiveGuild { /// **Note**: Requires the [Manage Webhooks] permission. /// /// [Manage Webhooks]: permissions/constant.MANAGE_WEBHOOKS.html + #[cfg(feature = "methods")] #[inline] pub fn webhooks(&self) -> Result<Vec<Webhook>> { http::get_guild_webhooks(self.id.0) @@ -739,6 +773,7 @@ impl Member { /// /// [`Role`]: struct.Role.html /// [Manage Roles]: permissions/constant.MANAGE_ROLES.html + #[cfg(feature = "methods")] pub fn add_role<R: Into<RoleId>>(&mut self, role_id: R) -> Result<()> { self.add_roles(&[role_id.into()]) } @@ -750,6 +785,7 @@ impl Member { /// /// [`Role`]: struct.Role.html /// [Manage Roles]: permissions/constant.MANAGE_ROLES.html + #[cfg(feature = "methods")] pub fn add_roles(&mut self, role_ids: &[RoleId]) -> Result<()> { let guild_id = try!(self.find_guild()); self.roles.extend_from_slice(role_ids); @@ -772,6 +808,7 @@ impl Member { /// **Note**: Requires the [Ban Members] role. /// /// [Ban Members]: permissions/constant.BAN_MEMBERS.html + #[cfg(feature = "methods")] pub fn ban(&self, delete_message_days: u8) -> Result<()> { let guild_id = try!(self.find_guild()); @@ -795,6 +832,7 @@ impl Member { /// /// [`Context::edit_member`]: ../client/struct.Context.html#method.edit_member /// [`EditMember`]: ../builder/struct.EditMember.html + #[cfg(feature = "methods")] pub fn edit<F>(&self, f: F) -> Result<()> where F: FnOnce(EditMember) -> EditMember { let guild_id = try!(self.find_guild()); @@ -806,6 +844,7 @@ impl Member { /// Finds the Id of the [`Guild`] that the member is in. /// /// [`Guild`]: struct.Guild.html + #[cfg(feature = "methods")] pub fn find_guild(&self) -> Result<GuildId> { STATE.lock() .unwrap() @@ -831,6 +870,7 @@ impl Member { /// /// [`Role`]: struct.Role.html /// [Manage Roles]: permissions/constant.MANAGE_ROLES.html + #[cfg(feature = "methods")] pub fn remove_role<R: Into<RoleId>>(&mut self, role_id: R) -> Result<()> { self.remove_roles(&[role_id.into()]) } @@ -841,6 +881,7 @@ impl Member { /// /// [`Role`]: struct.Role.html /// [Manage Roles]: permissions/constant.MANAGE_ROLES.html + #[cfg(feature = "methods")] pub fn remove_roles(&mut self, role_ids: &[RoleId]) -> Result<()> { let guild_id = try!(self.find_guild()); self.roles.retain(|r| !role_ids.contains(r)); @@ -924,6 +965,7 @@ impl Role { /// **Note** Requires the [Manage Roles] permission. /// /// [Manage Roles]: permissions/constant.MANAGE_ROLES.html + #[cfg(feature = "methods")] pub fn delete(&self) -> Result<()> { let guild_id = try!(self.find_guild()); @@ -938,6 +980,7 @@ impl Role { /// that contains the role. /// /// [`ClientError::GuildNotFound`]: ../client/enum.ClientError.html#variant.GuildNotFound + #[cfg(feature = "methods")] pub fn find_guild(&self) -> Result<GuildId> { STATE.lock() .unwrap() diff --git a/src/model/id.rs b/src/model/id.rs index 0d9fb32..ff236e1 100644 --- a/src/model/id.rs +++ b/src/model/id.rs @@ -1,15 +1,20 @@ use super::*; + +#[cfg(feature = "methods")] use ::client::{STATE, http}; +#[cfg(feature = "methods")] use ::internal::prelude::*; impl ChannelId { /// Search the state for the channel with the Id. + #[cfg(feature="methods")] pub fn find(&self) -> Option<Channel> { STATE.lock().unwrap().find_channel(*self) } /// Search the state for the channel. If it can't be found, the channel is /// requested over REST. + #[cfg(feature="methods")] pub fn get(&self) -> Result<Channel> { if let Some(channel) = STATE.lock().unwrap().find_channel(*self) { return Ok(channel); @@ -34,6 +39,7 @@ impl ChannelId { /// **Note**: Requires the [Manage Webhooks] permission. /// /// [Manage Webhooks]: permissions/constant.MANAGE_WEBHOOKS.html + #[cfg(feature="methods")] pub fn webhooks(&self) -> Result<Vec<Webhook>> { http::get_channel_webhooks(self.0) } @@ -69,6 +75,7 @@ impl From<Emoji> for EmojiId { impl GuildId { /// Search the state for the guild. + #[cfg(feature="methods")] pub fn find(&self) -> Option<LiveGuild> { STATE.lock().unwrap().find_guild(*self).cloned() } @@ -77,6 +84,7 @@ impl GuildId { /// /// Note that this will not be a complete guild, as REST does not send /// all data with a guild retrieval. + #[cfg(feature="methods")] pub fn get(&self) -> Result<Guild> { http::get_guild(self.0) } @@ -96,6 +104,7 @@ impl GuildId { /// **Note**: Requires the [Manage Webhooks] permission. /// /// [Manage Webhooks]: permissions/constant.MANAGE_WEBHOOKS.html + #[cfg(feature="methods")] pub fn webhooks(&self) -> Result<Vec<Webhook>> { http::get_guild_webhooks(self.0) } @@ -145,6 +154,7 @@ impl From<Role> for RoleId { impl RoleId { /// Search the state for the role. + #[cfg(feature="methods")] pub fn find(&self) -> Option<Role> { STATE.lock() .unwrap() @@ -206,6 +216,7 @@ impl WebhookId { /// **Note**: Requires the [Manage Webhooks] permission. /// /// [Manage Webhooks]: permissions/constant.MANAGE_WEBHOOKS.html + #[cfg(feature="methods")] pub fn webhooks(&self) -> Result<Webhook> { http::get_webhook(self.0) } diff --git a/src/model/invite.rs b/src/model/invite.rs index 8fd55e7..c33647e 100644 --- a/src/model/invite.rs +++ b/src/model/invite.rs @@ -10,6 +10,7 @@ impl Invite { /// banned. A ban is equivilant to an IP ban. /// /// [`Guild`]: struct.Guild.html + #[cfg(feature="methods")] pub fn accept(&self) -> Result<Invite> { http::accept_invite(&self.code) } @@ -25,6 +26,7 @@ impl Invite { /// /// [`ClientError::InvalidPermissions`]: ../client/enum.ClientError.html#variant.InvalidPermissions /// [Manage Guild]: permissions/constant.MANAGE_GUILD.html + #[cfg(feature="methods")] pub fn delete(&self) -> Result<Invite> { let req = permissions::MANAGE_GUILD; @@ -43,6 +45,7 @@ impl RichInvite { /// accepting an invite. /// /// [`Invite::accept`]: struct.Invite.html#method.accept + #[cfg(feature="methods")] pub fn accept(&self) -> Result<Invite> { http::accept_invite(&self.code) } @@ -60,6 +63,7 @@ impl RichInvite { /// [`ClientError::InvalidPermissions`]: ../client/enum.ClientError.html#variant.InvalidPermissions /// [`Invite::delete`]: struct.Invite.html#method.delete /// [Manage Guild]: permissions/constant.MANAGE_GUILD.html + #[cfg(feature="methods")] pub fn delete(&self) -> Result<Invite> { let req = permissions::MANAGE_GUILD; diff --git a/src/model/misc.rs b/src/model/misc.rs index 16cc7fe..3a17d96 100644 --- a/src/model/misc.rs +++ b/src/model/misc.rs @@ -89,6 +89,7 @@ impl fmt::Display for Mention { } impl IncidentStatus { + #[doc(hidden)] pub fn decode(value: Value) -> Result<Self> { Self::decode_str(value) } diff --git a/src/model/mod.rs b/src/model/mod.rs index f21da09..f00dffb 100644 --- a/src/model/mod.rs +++ b/src/model/mod.rs @@ -7,21 +7,27 @@ mod channel; mod gateway; mod guild; mod id; -mod invite; mod misc; mod user; mod voice; + +#[cfg(feature = "methods")] +mod invite; +#[cfg(feature = "methods")] mod webhook; pub use self::channel::*; pub use self::gateway::*; pub use self::guild::*; pub use self::id::*; -pub use self::invite::*; pub use self::misc::*; pub use self::permissions::Permissions; pub use self::user::*; pub use self::voice::*; + +#[cfg(feature = "methods")] +pub use self::invite::*; +#[cfg(feature = "methods")] pub use self::webhook::*; use self::utils::*; diff --git a/src/model/permissions.rs b/src/model/permissions.rs index 49a5069..c21e441 100644 --- a/src/model/permissions.rs +++ b/src/model/permissions.rs @@ -82,6 +82,7 @@ use ::internal::prelude::*; /// [Speak]: constant.SPEAK.html /// [Use External Emojis]: constant.USE_EXTERNAL_EMOJIS.html /// [Use VAD]: constant.USE_VAD.html +#[cfg(feature="extras")] pub fn general() -> Permissions { use self::*; @@ -119,6 +120,7 @@ pub fn general() -> Permissions { /// [Send Messages]: constant.SEND_MESSAGES.html /// [Send TTS Messages]: constant.SEND_TTS_MESSAGES.html /// [Use External Emojis]: constant.USE_EXTERNAL_EMOJIS.html +#[cfg(feature="extras")] pub fn text() -> Permissions { use self::*; @@ -140,6 +142,7 @@ pub fn text() -> Permissions { /// [Connect]: constant.CONNECT.html /// [Speak]: constant.SPEAK.html /// [Use VAD]: constant.USE_VAD.html +#[cfg(feature="extras")] pub fn voice() -> Permissions { use self::*; diff --git a/src/model/user.rs b/src/model/user.rs index f748d67..ce3d3a5 100644 --- a/src/model/user.rs +++ b/src/model/user.rs @@ -1,4 +1,3 @@ -use serde_json::builder::ObjectBuilder; use std::fmt; use super::utils::{into_map, into_string, remove, warn_field}; use super::{ @@ -6,15 +5,23 @@ use super::{ GuildContainer, GuildId, Mention, - Message, RoleId, UserSettings, User }; -use ::client::{STATE, http}; use ::internal::prelude::*; use ::utils::decode_array; +#[cfg(feature = "methods")] +use serde_json::builder::ObjectBuilder; +#[cfg(feature = "methods")] +use super::Message; +#[cfg(feature = "methods")] +use ::client::http; + +#[cfg(feature = "state")] +use ::client::STATE; + impl User { /// Returns the formatted URL of the user's icon, if one exists. pub fn avatar_url(&self) -> Option<String> { @@ -25,6 +32,7 @@ impl User { /// This is an alias of [direct_message]. /// /// [direct_message]: #method.direct_message + #[cfg(feature="methods")] pub fn dm(&self, content: &str) -> Result<Message> { self.direct_message(content) } @@ -32,6 +40,7 @@ impl User { /// Send a direct message to a user. This will create or retrieve the /// PrivateChannel over REST if one is not already in the State, and then /// send a message to it. + #[cfg(feature="methods")] pub fn direct_message(&self, content: &str) -> Result<Message> { let private_channel_id = { @@ -94,12 +103,16 @@ impl User { match guild.into() { GuildContainer::Guild(guild) => { - guild.find_role(role_id).is_some() + guild.roles.get(&role_id).is_some() }, GuildContainer::Id(guild_id) => { - let state = STATE.lock().unwrap(); + feature_state! {{ + let state = STATE.lock().unwrap(); - state.find_role(guild_id, role_id).is_some() + state.find_role(guild_id, role_id).is_some() + } else { + true + }} }, } } diff --git a/src/model/utils.rs b/src/model/utils.rs index f85a30f..92dfbd9 100644 --- a/src/model/utils.rs +++ b/src/model/utils.rs @@ -1,5 +1,4 @@ use std::collections::{BTreeMap, HashMap}; -use super::permissions::{self, Permissions}; use super::{ Channel, ChannelId, @@ -15,10 +14,14 @@ use super::{ UserId, VoiceState, }; -use ::client::STATE; use ::internal::prelude::*; use ::utils::{decode_array, into_array}; +#[cfg(feature = "methods")] +use super::permissions::{self, Permissions}; +#[cfg(feature = "methods")] +use ::client::STATE; + #[macro_escape] macro_rules! missing { (@ $name:expr, $json:ident, $value:expr) => { @@ -268,6 +271,7 @@ pub fn remove(map: &mut BTreeMap<String, Value>, key: &str) -> Result<Value> { } #[doc(hidden)] +#[cfg(feature="methods")] pub fn user_has_perms(channel_id: ChannelId, mut permissions: Permissions) -> Result<bool> { diff --git a/src/model/webhook.rs b/src/model/webhook.rs index 04f6d5d..f0d7b16 100644 --- a/src/model/webhook.rs +++ b/src/model/webhook.rs @@ -12,6 +12,7 @@ impl Webhook { /// authentication is not required. /// /// [`http::delete_webhook_with_token`]: ../client/http/fn.delete_webhook_with_token.html + #[cfg(feature="methods")] pub fn delete(&self) -> Result<()> { http::delete_webhook_with_token(self.id.0, &self.token) } @@ -62,6 +63,7 @@ impl Webhook { /// /// [`http::edit_webhook`]: ../client/http/fn.edit_webhook.html /// [`http::edit_webhook_with_token`]: ../client/http/fn.edit_webhook_with_token.html + #[cfg(feature="methods")] pub fn edit(&mut self, name: Option<&str>, avatar: Option<&str>) -> Result<()> { if name.is_none() && avatar.is_none() { @@ -141,6 +143,7 @@ impl Webhook { /// .embeds(vec![embed])) /// .expect("err executing"); /// ``` + #[cfg(feature="methods")] pub fn execute<F>(&self, f: F) -> Result<Message> where F: FnOnce(ExecuteWebhook) -> ExecuteWebhook { let map = f(ExecuteWebhook::default()).0.build(); @@ -155,6 +158,7 @@ impl Webhook { /// authentication is not required. /// /// [`http::get_webhook_with_token`]: ../client/http/fn.get_webhook_with_token.html + #[cfg(feature="methods")] pub fn refresh(&mut self) -> Result<()> { match http::get_webhook_with_token(self.id.0, &self.token) { Ok(replacement) => { diff --git a/src/utils/builder/edit_role.rs b/src/utils/builder/edit_role.rs index d1e2c0e..f87d22e 100644 --- a/src/utils/builder/edit_role.rs +++ b/src/utils/builder/edit_role.rs @@ -93,12 +93,18 @@ impl Default for EditRole { /// /// [general permissions set]: ../model/permissions/fn.general.html fn default() -> EditRole { - EditRole(ObjectBuilder::new() + let mut map = ObjectBuilder::new() .insert("color", 10070709) .insert("hoist", false) .insert("mentionable", false) - .insert("name", String::from("new role")) - .insert("permissions", permissions::general().bits()) - .insert("position", 1)) + .insert("name", "new role".to_owned()); + + feature_extras_enabled! {{ + map = map.insert("permissions", permissions::general().bits()); + }} + + map = map.insert("position", 1); + + EditRole(map) } } diff --git a/src/utils/macros.rs b/src/utils/macros.rs new file mode 100644 index 0000000..34cfaa4 --- /dev/null +++ b/src/utils/macros.rs @@ -0,0 +1,300 @@ +macro_rules! request { + ($route:expr, $method:ident($body:expr), $url:expr, $($rest:tt)*) => {{ + let client = HyperClient::new(); + try!(request($route, || client + .$method(&format!(api!($url), $($rest)*)) + .body(&$body))) + }}; + ($route:expr, $method:ident($body:expr), $url:expr) => {{ + let client = HyperClient::new(); + try!(request($route, || client + .$method(api!($url)) + .body(&$body))) + }}; + ($route:expr, $method:ident, $url:expr, $($rest:tt)*) => {{ + let client = HyperClient::new(); + try!(request($route, || client + .$method(&format!(api!($url), $($rest)*)))) + }}; + ($route:expr, $method:ident, $url:expr) => {{ + let client = HyperClient::new(); + try!(request($route, || client + .$method(api_concat!($url)))) + }}; +} + +macro_rules! cdn_concat { + ($e:expr) => { + concat!("https://cdn.discordapp.com", $e) + } +} +macro_rules! api { + ($e:expr) => { + concat!("https://discordapp.com/api/v6", $e) + }; + ($e:expr, $($rest:tt)*) => { + format!(api!($e), $($rest)*) + }; +} + +macro_rules! api_concat { + ($e:expr) => { + concat!("https://discordapp.com/api/v6", $e) + } +} +macro_rules! status_concat { + ($e:expr) => { + concat!("https://status.discordapp.com/api/v2", $e) + } +} + +// Enable/disable check for extras +macro_rules! feature_extras { + ($enabled:block) => { + { + feature_extras_enabled! {{ + $enabled + }} + } + }; + ($enabled:block $disabled:block) => { + { + feature_extras_enabled! {{ + $enabled + }} + + feature_extras_disabled! {{ + $disabled + }} + } + }; +} + +#[cfg(feature = "extras")] +macro_rules! feature_extras_enabled { + ($enabled:block) => {{ + { + $enabled + } + }} +} + +#[cfg(not(feature = "extras"))] +macro_rules! feature_extras_enabled { + ($enabled:block) => {} +} + +#[cfg(feature = "extras")] +macro_rules! feature_extras_disabled { + ($disabled:block) => {} +} + +#[cfg(not(feature = "extras"))] +macro_rules! feature_extras_disabled { + ($disabled:block) => { + { + $disabled + } + } +} + +// Enable/disable check for framework +macro_rules! feature_framework { + ($enabled:block) => { + { + feature_framework_enabled! {{ + $enabled + }} + } + }; + ($enabled:block $disabled:block) => { + { + feature_framework_enabled! {{ + $enabled + }} + + feature_framework_disabled! {{ + $disabled + }} + } + }; +} + +#[cfg(feature = "framework")] +macro_rules! feature_framework_enabled { + ($enabled:block) => { + { + $enabled + } + } +} + +#[cfg(not(feature = "framework"))] +macro_rules! feature_framework_enabled { + ($enabled:block) => {} +} + +#[cfg(feature = "framework")] +macro_rules! feature_framework_disabled { + ($disabled:block) => {} +} + +#[cfg(not(feature = "framework"))] +macro_rules! feature_framework_disabled { + ($disabled:block) => { + { + $disabled + } + } +} + +// Enable/disable check for methods +macro_rules! feature_methods { + ($enabled:block) => { + { + feature_methods_enabled! {{ + $enabled + }} + } + }; + ($enabled:block $disabled:block) => { + { + feature_methods_enabled! {{ + $enabled + }} + + feature_methods_disabled! {{ + $disabled + }} + } + }; +} + +#[cfg(feature = "methods")] +macro_rules! feature_methods_enabled { + ($enabled:block) => { + { + $enabled + } + } +} + +#[cfg(not(feature = "methods"))] +macro_rules! feature_methods_enabled { + ($enabled:block) => {} +} + +#[cfg(feature = "methods")] +macro_rules! feature_methods_disabled { + ($disabled:block) => {} +} + +#[cfg(not(feature = "methods"))] +macro_rules! feature_methods_disabled { + ($disabled:block) => { + { + $disabled + } + } +} + +// Enable/disable check for state +#[cfg(feature = "state")] +macro_rules! feature_state { + ($enabled:block) => { + { + feature_state_enabled! {{ + $enabled + }} + } + }; + ($enabled:block else $disabled:block) => { + { + feature_state_enabled! {{ + $enabled + }} + + feature_state_disabled! {{ + $disabled + }} + } + }; +} + +#[cfg(feature = "state")] +macro_rules! feature_state_enabled { + ($enabled:block) => { + { + $enabled + } + } +} + +#[cfg(not(feature = "state"))] +macro_rules! feature_state_enabled { + ($enabled:block) => {} +} + +#[cfg(feature = "state")] +macro_rules! feature_state_disabled { + ($disabled:block) => {} +} + +#[cfg(not(feature = "state"))] +macro_rules! feature_state_disabled { + ($disabled:block) => { + { + $disabled + } + } +} + +// Enable/disable check for voice +macro_rules! feature_voice { + ($enabled:block) => { + { + feature_voice_enabled! {{ + $enabled + }} + } + }; + ($enabled:block $disabled:block) => { + { + feature_voice_enabled! {{ + $enabled + }} + + feature_voice_disabled! {{ + $disabled + }} + } + }; +} + +#[cfg(feature = "voice")] +macro_rules! feature_voice_enabled { + ($enabled:block) => { + { + $enabled + } + } +} + +#[cfg(not(feature = "voice"))] +macro_rules! feature_voice_enabled { + ($enabled:block) => {} +} + +#[cfg(feature = "voice")] +macro_rules! feature_voice_disabled { + ($disabled:block) => {} +} + +#[cfg(not(feature = "voice"))] +macro_rules! feature_voice_disabled { + ($disabled:block) => { + { + $disabled + } + } +} diff --git a/src/utils/mod.rs b/src/utils/mod.rs index 28d18f1..ccf7787 100644 --- a/src/utils/mod.rs +++ b/src/utils/mod.rs @@ -1,8 +1,18 @@ //! A set of utilities to help with common use cases that are not required to //! fully use the library. +#[macro_use] +pub mod macros; + pub mod builder; +mod colour; + +#[cfg(feature = "extras")] +mod message_builder; + +pub use self::colour::Colour; + use base64; use std::ffi::OsStr; use std::fs::File; @@ -10,10 +20,7 @@ use std::io::Read; use std::path::Path; use ::internal::prelude::*; -mod colour; -mod message_builder; - -pub use self::colour::Colour; +#[cfg(feature = "extras")] pub use self::message_builder::MessageBuilder; macro_rules! cdn_concat { @@ -83,81 +90,6 @@ pub fn into_array(value: Value) -> Result<Vec<Value>> { } } -macro_rules! request { - ($route:expr, $method:ident($body:expr), $url:expr, $($rest:tt)*) => {{ - let client = HyperClient::new(); - try!(request($route, || client - .$method(&format!(api!($url), $($rest)*)) - .body(&$body))) - }}; - ($route:expr, $method:ident($body:expr), $url:expr) => {{ - let client = HyperClient::new(); - try!(request($route, || client - .$method(api!($url)) - .body(&$body))) - }}; - ($route:expr, $method:ident, $url:expr, $($rest:tt)*) => {{ - let client = HyperClient::new(); - try!(request($route, || client - .$method(&format!(api!($url), $($rest)*)))) - }}; - ($route:expr, $method:ident, $url:expr) => {{ - let client = HyperClient::new(); - try!(request($route, || client - .$method(api_concat!($url)))) - }}; -} - -// Enable/disable check for voice -macro_rules! feature_voice { - ($enabled:block) => { - { - feature_voice_enabled! {{ - $enabled - }} - } - }; - ($enabled:block $disabled:block) => { - { - feature_voice_enabled! {{ - $enabled - }} - - feature_voice_disabled! {{ - $disabled - }} - } - }; -} - -#[cfg(feature="voice")] -macro_rules! feature_voice_enabled { - ($enabled:block) => { - { - $enabled - } - } -} - -#[cfg(not(feature="voice"))] -macro_rules! feature_voice_enabled { - ($enabled:block) => {} -} - -#[cfg(feature="voice")] -macro_rules! feature_voice_disabled { - ($disabled:block) => {} -} - -#[cfg(not(feature="voice"))] -macro_rules! feature_voice_disabled { - ($disabled:block) => { - { - $disabled - } - } -} - /// Retrieves the "code" part of an [invite][`RichInvite`] out of a URL. /// /// # Examples |