<commit_before>use crate::builder::EditProfile;
use crate::client::bridge::gateway::ShardMessenger;
use crate::error::Result;
use crate::gateway::InterMessage;
use crate::model::prelude::*;
use parking_lot::RwLock;
use serde_json::Value;
use std::sync::{
    Arc,
    mpsc::Sender
};
use typemap::ShareMap;
use crate::utils::VecMap;
use crate::utils::vecmap_to_json_map;
#[cfg(feature = "cache")]
pub use crate::cache::Cache;
#[cfg(feature = "http")]
use crate::http::Http;

/// The context is a general utility struct provided on event dispatches, which
/// helps with dealing with the current "context" of the event dispatch.
/// The context also acts as a general high-level interface over the associated
/// [`Shard`] which received the event, or the low-level [`http`] module.
///
/// The context contains "shortcuts", like for interacting with the shard.
/// Methods like [`set_activity`] will unlock the shard and perform an update for
/// you to save a bit of work.
///
/// A context will only live for the event it was dispatched for. After the
/// event handler finished, it is destroyed and will not be re-used.
///
/// [`Shard`]: ../gateway/struct.Shard.html
/// [`http`]: ../http/index.html
/// [`set_activity`]: #method.set_activity
#[derive(Clone)]
pub struct Context {
    /// A clone of [`Client::data`]. Refer to its documentation for more
    /// information.
    ///
    /// [`Client::data`]: struct.Client.html#structfield.data
    pub data: Arc<RwLock<ShareMap>>,
    /// The messenger to communicate with the shard runner.
    pub shard: ShardMessenger,
    /// The ID of the shard this context is related to.
    pub shard_id: u64,
    #[cfg(feature = "cache")]
    pub cache: Arc<RwLock<Cache>>,
    #[cfg(feature = "http")]
    pub http: Arc<Http>,
}

impl Context {
    /// Create a new Context to be passed to an event handler.
    pub(crate) fn new(
        data: Arc<RwLock<ShareMap>>,
        runner_tx: Sender<InterMessage>,
        shard_id: u64,
        cache: Arc<RwLock<Cache>>,
        http: Arc<Http>,
    ) -> Context {
        Context {
            shard: ShardMessenger::new(runner_tx),
            shard_id,
            data,
            #[cfg(feature = "cache")]
            cache,
            #[cfg(feature = "http")]
            http,
        }
    }

    /// Edits the current user's profile settings.
    ///
    /// Refer to `EditProfile`'s documentation for its methods.
    ///
    /// # Examples
    ///
    /// Change the current user's username:
    ///
    /// ```rust,no_run
    /// # use serenity::prelude::*;
    /// # use serenity::model::channel::Message;
    /// #
    /// struct Handler;
    ///
    /// impl EventHandler for Handler {
    ///     fn message(&self, ctx: Context, msg: Message) {
    ///         if msg.content == "!changename" {
    ///             ctx.edit_profile(|mut e| {
    ///                 e.username("<NAME>");
    ///
    ///                 e
    ///             });
    ///         }
    ///     }
    /// }
    /// let mut client = Client::new("token", Handler).unwrap();
    ///
    /// client.start().unwrap();
    /// ```
    #[cfg(feature = "builder")]
    #[deprecated(since = "0.5.6", note = "Use the http module instead.")]
    pub fn edit_profile<F>(&self, f: F) -> Result<CurrentUser>
    where F: FnOnce(&mut EditProfile) -> &mut EditProfile {
        let mut map = VecMap::with_capacity(2);

        feature_cache! {
            {
                let cache = self.cache.read();

                map.insert("username", Value::String(cache.user.name.clone()));

                if let Some(email) = cache.user.email.clone() {
                    map.insert("email", Value::String(email));
                }
            } else {
                let user = http.get_current_user()?;

                map.insert("username", Value::String(user.name));

                if let Some(email) = user.email {
                    map.insert("email", Value::String(email));
                }
            }
        }<commit_msg>Add different `Context::new`s based on feature-set. (#492)<commit_after>use crate::builder::EditProfile;
use crate::client::bridge::gateway::ShardMessenger;
use crate::error::Result;
use crate::gateway::InterMessage;
use crate::model::prelude::*;
use parking_lot::RwLock;
use serde_json::Value;
use std::sync::{
    Arc,
    mpsc::Sender
};
use typemap::ShareMap;
use crate::utils::VecMap;
use crate::utils::vecmap_to_json_map;
#[cfg(feature = "cache")]
pub use crate::cache::Cache;
#[cfg(feature = "http")]
use crate::http::Http;

/// The context is a general utility struct provided on event dispatches, which
/// helps with dealing with the current "context" of the event dispatch.
/// The context also acts as a general high-level interface over the associated
/// [`Shard`] which received the event, or the low-level [`http`] module.
///
/// The context contains "shortcuts", like for interacting with the shard.
/// Methods like [`set_activity`] will unlock the shard and perform an update for
/// you to save a bit of work.
///
/// A context will only live for the event it was dispatched for. After the
/// event handler finished, it is destroyed and will not be re-used.
///
/// [`Shard`]: ../gateway/struct.Shard.html
/// [`http`]: ../http/index.html
/// [`set_activity`]: #method.set_activity
#[derive(Clone)]
pub struct Context {
    /// A clone of [`Client::data`]. Refer to its documentation for more
    /// information.
    ///
    /// [`Client::data`]: struct.Client.html#structfield.data
    pub data: Arc<RwLock<ShareMap>>,
    /// The messenger to communicate with the shard runner.
    pub shard: ShardMessenger,
    /// The ID of the shard this context is related to.
    pub shard_id: u64,
    #[cfg(feature = "cache")]
    pub cache: Arc<RwLock<Cache>>,
    #[cfg(feature = "http")]
    pub http: Arc<Http>,
}

impl Context {
    /// Create a new Context to be passed to an event handler.
    #[cfg(all(feature = "cache", feature = "http"))]
    pub(crate) fn new(
        data: Arc<RwLock<ShareMap>>,
        runner_tx: Sender<InterMessage>,
        shard_id: u64,
        cache: Arc<RwLock<Cache>>,
        http: Arc<Http>,
    ) -> Context {
        Context {
            shard: ShardMessenger::new(runner_tx),
            shard_id,
            data,
            cache,
            http,
        }
    }

    /// Create a new Context to be passed to an event handler.
    #[cfg(all(not(feature = "cache"), feature = "http"))]
    pub(crate) fn new(
        data: Arc<RwLock<ShareMap>>,
        runner_tx: Sender<InterMessage>,
        shard_id: u64,
        http: Arc<Http>,
    ) -> Context {
        Context {
            shard: ShardMessenger::new(runner_tx),
            shard_id,
            data,
            http,
        }
    }

    /// Create a new Context to be passed to an event handler.
    #[cfg(all(feature = "cache", not(feature = "http")))]
    pub(crate) fn new(
        data: Arc<RwLock<ShareMap>>,
        runner_tx: Sender<InterMessage>,
        shard_id: u64,
        cache: Arc<RwLock<Cache>>,
    ) -> Context {
        Context {
            shard: ShardMessenger::new(runner_tx),
            shard_id,
            data,
            cache,
        }
    }

    /// Create a new Context to be passed to an event handler.
    #[cfg(all(not(feature = "cache"), not(feature = "http")))]
    pub(crate) fn new(
        data: Arc<RwLock<ShareMap>>,
        runner_tx: Sender<InterMessage>,
        shard_id: u64,
    ) -> Context {
        Context {
            shard: ShardMessenger::new(runner_tx),
            shard_id,
            data,
        }
    }

    /// Edits the current user's profile settings.
    ///
    /// Refer to `EditProfile`'s documentation for its methods.
    ///
    /// # Examples
    ///
    /// Change the current user's username:
    ///
    /// ```rust,no_run
    /// # use serenity::prelude::*;
    /// # use serenity::model::channel::Message;
    /// #
    /// struct Handler;
    ///
    /// impl EventHandler for Handler {
    ///     fn message(&self, ctx: Context, msg: Message) {
    ///         if msg.content == "!changename" {
    ///             ctx.edit_profile(|mut e| {
    ///                 e.username("<NAME>");
    ///
    ///                 e
    ///             });
    ///         }
    ///     }
    /// }
    /// let mut client = Client::new("token", Handler).unwrap();
    ///
    /// client.start().unwrap();
    /// ```
    #[cfg(feature = "builder")]
    #[deprecated(since = "0.5.6", note = "Use the http module instead.")]
    pub fn edit_profile<F>(&self, f: F) -> Result<CurrentUser>
    where F: FnOnce(&mut EditProfile) -> &mut EditProfile {
        let mut map = VecMap::with_capacity(2);

        feature_cache! {
            {
                let cache = self.cache.read();

                map.insert("username", Value::String(cache.user.name.clone()));

                if let Some(email) = cache.user.email.clone() {
                    map.insert("email", Value::String(email));
                }
            } else {
                let user = self.http.get_current_user()?;

                map.insert("username", Value::String(user.name));

                if let Some(email) = user.email {
                    map.insert("email", Value::String(email));
                }
            }
        }
{'fraction_non_alphanumeric': 0.15641739875723162, 'fraction_numerical': 0.002678380115706021, 'mean_word_length': 2.039726473461413, 'pattern_counts': {'":': 0, '<': 43, '<?xml version=': 0, '>': 52, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6573965', 'n_tokens_mistral': 2827, 'n_tokens_neox': 2791, 'n_words': 760}