<commit_before>//! User information-related models.

use serde_json;
use std::fmt;
use super::utils::deserialize_u16;
use super::prelude::*;
use crate::{internal::prelude::*, model::misc::Mentionable};

#[cfg(feature = "model")]
use crate::builder::{CreateMessage, EditProfile};
#[cfg(feature = "model")]
use crate::http::GuildPagination;
#[cfg(all(feature = "cache", feature = "model"))]
use parking_lot::RwLock;
#[cfg(feature = "model")]
use std::fmt::Write;
#[cfg(all(feature = "cache", feature = "model"))]
use crate::cache::CacheRwLock;
#[cfg(feature = "model")]
use serde_json::json;
#[cfg(all(feature = "cache", feature = "model"))]
use std::sync::Arc;
#[cfg(feature = "model")]
use crate::utils;
#[cfg(feature = "model")]
use crate::http::{Http, CacheHttp};

/// Information about the current user.
#[derive(Clone, Default, Debug, Deserialize, Serialize)]
pub struct CurrentUser {
    pub id: UserId,
    pub avatar: Option<String>,
    #[serde(default)] pub bot: bool,
    #[serde(deserialize_with = "deserialize_u16")] pub discriminator: u16,
    pub email: Option<String>,
    pub mfa_enabled: bool,
    #[serde(rename = "username")] pub name: String,
    pub verified: Option<bool>,
    #[serde(skip)]
    pub(crate) _nonexhaustive: (),
}

#[cfg(feature = "model")]
impl CurrentUser {
    /// Returns the formatted URL of the user's icon, if one exists.
    ///
    /// This will produce a WEBP image URL, or GIF if the user has a GIF avatar.
    ///
    /// # Examples
    ///
    /// Print out the current user's avatar url if one is set:
    ///
    /// ```rust,no_run
    /// # #[cfg(feature = "cache")]
    /// # fn main() {
    /// # use serenity::{cache::{Cache, CacheRwLock}, model::prelude::*, prelude::*};
    /// # use parking_lot::RwLock;
    /// # use std::sync::Arc;
    /// #
    /// # let cache: CacheRwLock = Arc::new(RwLock::new(Cache::default())).into();
    /// # let cache = cache.read();
    /// // assuming the cache has been unlocked
    /// let user = &cache.user;
    ///
    /// match user.avatar_url() {
    ///     Some(url) => println!("{}'s avatar can be found at {}", user.name, url),
    ///     None => println!("{} does not have an avatar set.", user.name)
    /// }
    /// # }
    /// #
    /// # #[cfg(not(feature = "cache"))]
    /// # fn main() {}
    /// ```
    #[inline]
    pub fn avatar_url(&self) -> Option<String> { avatar_url(self.id, self.avatar.as_ref()) }

    /// Returns the formatted URL to the user's default avatar URL.
    ///
    /// This will produce a PNG URL.
    #[inline]
    pub fn default_avatar_url(&self) -> String { default_avatar_url(self.discriminator) }

    /// Edits the current user's profile settings.
    ///
    /// This mutates the current user in-place.
    ///
    /// Refer to [`EditProfile`]'s documentation for its methods.
    ///
    /// # Examples
    ///
    /// Change the avatar:
    ///
    /// ```rust,ignore
    /// # #[cfg(feature = "cache")]
    /// # fn main() {
    /// let avatar = serenity::utils::read_image("./avatar.png").unwrap();
    ///
    /// context.cache.write().user.edit(|p| p.avatar(Some(&avatar)));
    /// # }
    /// #
    /// # #[cfg(not(feature = "cache"))]
    /// # fn main() {}
    /// ```
    ///
    /// [`EditProfile`]: ../../builder/struct.EditProfile.html
    pub fn edit<F>(&mut self, http: impl AsRef<Http>, f: F) -> Result<()>
        where F: FnOnce(&mut EditProfile) -> &mut EditProfile {
        let mut map = HashMap::new();
        map.insert("username", Value::String(self.name.clone()));

        if let Some(email) = self.email.as_ref() {
            map.insert("email", Value::String(email.clone()));
        }

        let mut edit_profile = EditProfile(map);
        f(&mut edit_profile);
        let map = utils::hashmap_to_json_map(edit_profile.0);

        *self = http.as_ref().edit_profile(&map)?;

        Ok(())
    }

    /// Retrieves the URL to the current user's avatar, falling back to the
    /// default avatar if needed.
    ///
    /// This will call [`avatar_url`] first, and if that returns `None`, it
    /// then falls back to [`default_avatar_url`].
    ///
    /// [`avatar_url`]: #method.avatar_url
    /// [`default_avatar_url`]: #method.default_avatar_url
    #[inline]
    pub fn face(&self) -> String {
        self.avatar_url()
            .unwrap_or_else(|| self.default_avatar_url())
    }

    /// Gets a list of guilds that the current user is in.
    ///
    /// # Examples
    ///
    /// Print out the names of all guilds the current user is in:
    ///
    /// ```rust,no_run
    /// # #[cfg(feature = "cache")]
    /// # fn main() {
    /// # use serenity::{cache::{Cache, CacheRwLock}, http::Http, model::prelude::*, prelude::*};
    /// # use parking_lot::RwLock;
    /// # use std::sync::Arc;
    /// #
    /// # let cache: CacheRwLock = Arc::new(RwLock::new(Cache::default())).into();
    /// # let cache = cache.read();
    /// # let http = Arc::new(Http::default());
    /// // assuming the cache has been unlocked
    /// let user = &cache.user;
    ///
    /// if let Ok(guilds) = user.guilds(&http) {
    ///     for (index, guild) in guilds.into_iter().enumerate() {
    ///         println!("{}: {}", index, guild.name);
    ///     }
    /// }
    /// # }
    /// #
    /// # #[cfg(not(feature = "cache"))]
    /// # fn main() {}
    /// ```
    #[inline]
    pub fn guilds(&self, http: impl AsRef<Http>) -> Result<Vec<GuildInfo>> {
        http.as_ref().get_guilds(&GuildPagination::After(GuildId(1)), 100)
    }
<commit_msg>Add pagination for CurrentUser::guilds (#877)<commit_after>//! User information-related models.

use serde_json;
use std::fmt;
use super::utils::deserialize_u16;
use super::prelude::*;
use crate::{internal::prelude::*, model::misc::Mentionable};

#[cfg(feature = "model")]
use crate::builder::{CreateMessage, EditProfile};
#[cfg(feature = "model")]
use crate::http::GuildPagination;
#[cfg(all(feature = "cache", feature = "model"))]
use parking_lot::RwLock;
#[cfg(feature = "model")]
use std::fmt::Write;
#[cfg(all(feature = "cache", feature = "model"))]
use crate::cache::CacheRwLock;
#[cfg(feature = "model")]
use serde_json::json;
#[cfg(all(feature = "cache", feature = "model"))]
use std::sync::Arc;
#[cfg(feature = "model")]
use crate::utils;
#[cfg(feature = "model")]
use crate::http::{Http, CacheHttp};

/// Information about the current user.
#[derive(Clone, Default, Debug, Deserialize, Serialize)]
pub struct CurrentUser {
    pub id: UserId,
    pub avatar: Option<String>,
    #[serde(default)] pub bot: bool,
    #[serde(deserialize_with = "deserialize_u16")] pub discriminator: u16,
    pub email: Option<String>,
    pub mfa_enabled: bool,
    #[serde(rename = "username")] pub name: String,
    pub verified: Option<bool>,
    #[serde(skip)]
    pub(crate) _nonexhaustive: (),
}

#[cfg(feature = "model")]
impl CurrentUser {
    /// Returns the formatted URL of the user's icon, if one exists.
    ///
    /// This will produce a WEBP image URL, or GIF if the user has a GIF avatar.
    ///
    /// # Examples
    ///
    /// Print out the current user's avatar url if one is set:
    ///
    /// ```rust,no_run
    /// # #[cfg(feature = "cache")]
    /// # fn main() {
    /// # use serenity::{cache::{Cache, CacheRwLock}, model::prelude::*, prelude::*};
    /// # use parking_lot::RwLock;
    /// # use std::sync::Arc;
    /// #
    /// # let cache: CacheRwLock = Arc::new(RwLock::new(Cache::default())).into();
    /// # let cache = cache.read();
    /// // assuming the cache has been unlocked
    /// let user = &cache.user;
    ///
    /// match user.avatar_url() {
    ///     Some(url) => println!("{}'s avatar can be found at {}", user.name, url),
    ///     None => println!("{} does not have an avatar set.", user.name)
    /// }
    /// # }
    /// #
    /// # #[cfg(not(feature = "cache"))]
    /// # fn main() {}
    /// ```
    #[inline]
    pub fn avatar_url(&self) -> Option<String> { avatar_url(self.id, self.avatar.as_ref()) }

    /// Returns the formatted URL to the user's default avatar URL.
    ///
    /// This will produce a PNG URL.
    #[inline]
    pub fn default_avatar_url(&self) -> String { default_avatar_url(self.discriminator) }

    /// Edits the current user's profile settings.
    ///
    /// This mutates the current user in-place.
    ///
    /// Refer to [`EditProfile`]'s documentation for its methods.
    ///
    /// # Examples
    ///
    /// Change the avatar:
    ///
    /// ```rust,ignore
    /// # #[cfg(feature = "cache")]
    /// # fn main() {
    /// let avatar = serenity::utils::read_image("./avatar.png").unwrap();
    ///
    /// context.cache.write().user.edit(|p| p.avatar(Some(&avatar)));
    /// # }
    /// #
    /// # #[cfg(not(feature = "cache"))]
    /// # fn main() {}
    /// ```
    ///
    /// [`EditProfile`]: ../../builder/struct.EditProfile.html
    pub fn edit<F>(&mut self, http: impl AsRef<Http>, f: F) -> Result<()>
        where F: FnOnce(&mut EditProfile) -> &mut EditProfile {
        let mut map = HashMap::new();
        map.insert("username", Value::String(self.name.clone()));

        if let Some(email) = self.email.as_ref() {
            map.insert("email", Value::String(email.clone()));
        }

        let mut edit_profile = EditProfile(map);
        f(&mut edit_profile);
        let map = utils::hashmap_to_json_map(edit_profile.0);

        *self = http.as_ref().edit_profile(&map)?;

        Ok(())
    }

    /// Retrieves the URL to the current user's avatar, falling back to the
    /// default avatar if needed.
    ///
    /// This will call [`avatar_url`] first, and if that returns `None`, it
    /// then falls back to [`default_avatar_url`].
    ///
    /// [`avatar_url`]: #method.avatar_url
    /// [`default_avatar_url`]: #method.default_avatar_url
    #[inline]
    pub fn face(&self) -> String {
        self.avatar_url()
            .unwrap_or_else(|| self.default_avatar_url())
    }

    /// Gets a list of guilds that the current user is in.
    ///
    /// # Examples
    ///
    /// Print out the names of all guilds the current user is in:
    ///
    /// ```rust,no_run
    /// # #[cfg(feature = "cache")]
    /// # fn main() {
    /// # use serenity::{cache::{Cache, CacheRwLock}, http::Http, model::prelude::*, prelude::*};
    /// # use parking_lot::RwLock;
    /// # use std::sync::Arc;
    /// #
    /// # let cache: CacheRwLock = Arc::new(RwLock::new(Cache::default())).into();
    /// # let cache = cache.read();
    /// # let http = Arc::new(Http::default());
    /// // assuming the cache has been unlocked
    /// let user = &cache.user;
    ///
    /// if let Ok(guilds) = user.guilds(&http) {
    ///     for (index, guild) in guilds.into_iter().enumerate() {
    ///         println!("{}: {}", index, guild.name);
    ///     }
    /// }
    /// # }
    /// #
    /// # #[cfg(not(feature = "cache"))]
    /// # fn main() {}
    /// ```
    pub fn guilds(&self, http: impl AsRef<Http>) -> Result<Vec<GuildInfo>> {
        let mut guilds = Vec::new();
        loop {
            let mut pagination = http.as_ref().get_guilds(
                &GuildPagination::After(guilds.last().map_or(GuildId(1), |g: &GuildInfo| g.id)),
                100,
            )?;
            let len = pagination.len();
            guilds.append(&mut pagination);
            if len != 100 {
                break;
            }
        }
        Ok(guilds)
    }

{'fraction_non_alphanumeric': 0.20383672039243167, 'fraction_numerical': 0.002452697967764541, 'mean_word_length': 2.348093841642229, 'pattern_counts': {'":': 0, '<': 23, '<?xml version=': 0, '>': 39, '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': '3577875', 'n_tokens_mistral': 3764, 'n_tokens_neox': 3781, 'n_words': 899}