1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218
//! `rust-gravatar` is a small Rust library that generates Gravatar image URLs based on the
//! [official Gravatar specification](https://en.gravatar.com/site/implement/images/).
//!
//! Example
//! --------
//! ```
//! extern crate gravatar;
//! use gravatar::{Gravatar, Rating};
//!
//! let url = Gravatar::new("email@example.com")
//! .set_size(Some(150))
//! .set_rating(Some(Rating::Pg))
//! .image_url();
//! assert_eq!(
//! url.as_str(),
//! "https://secure.gravatar.com/avatar/5658ffccee7f0ebfda2b226238b1eb6e?s=150&r=pg"
//! );
//! ```
extern crate md5;
extern crate url;
use md5::{Digest, Md5};
use url::percent_encoding::{utf8_percent_encode, DEFAULT_ENCODE_SET};
use url::Url;
/// The default image to display if the user's email does not have a Gravatar.
///
/// See <https://en.gravatar.com/site/implement/images/#default-image>.
#[derive(Clone, Debug)]
pub enum Default {
/// The URL of an image file to display as the default.
ImageUrl(Url),
/// Instead of loading an image, the Gravatar URL will return an HTTP 404 (File Not Found)
/// response if the email is not found.
Http404,
/// A transparent PNG image.
Blank,
/// A simple, cartoon-style silhouetted outline of a person that does not vary by email hash.
MysteryMan,
/// A geometric pattern based on the email hash.
Identicon,
/// A "monster" with different colors, faces, etc. that are generated by the email hash.
MonsterId,
/// A face with different features and backgrounds, generated by the email hash.
Wavatar,
/// An 8-bit arcade-style pixelated face that is generated by the email hash.
Retro,
}
/// The maximum rating level for which Gravatar will show the user's image instead of the specified
/// default.
///
/// See <https://en.gravatar.com/site/implement/images/#rating>.
#[derive(Clone, Debug)]
pub enum Rating {
/// Show "G"-rated images only.
G,
/// Show "PG"-rated images or lower only.
Pg,
/// Show "R"-rated images or lower only.
R,
/// Show all images, up to and including "X"-rated ones.
X,
}
/// Representation of a single Gravatar image URL.
#[derive(Clone, Debug)]
pub struct Gravatar {
email: String,
size: Option<u16>,
default: Option<Default>,
force_default: bool,
rating: Option<Rating>,
ssl: bool,
}
impl Gravatar {
/// Creates a new Gravatar with the given email and default values for the other parameters.
pub fn new(email: &str) -> Gravatar {
Gravatar {
email: email.to_string(),
size: None,
default: None,
force_default: false,
rating: None,
ssl: true,
}
}
/// Sets the desired image size. If `None` is provided, then no size is passed to Gravatar,
/// which will then use a default of 80px by 80px. Gravatar will only provide images between
/// 1px and 2048px by size, so this function will use 1px if the desired size is less than that
/// and 2048px if the desired size is greater than that.
///
/// For more information, see <https://en.gravatar.com/site/implement/images/#size>.
///
/// **Default value:** `None`
pub fn set_size(&mut self, size: Option<u16>) -> &mut Self {
self.size = match size {
Some(s) => Some(s.max(1).min(2048)),
None => None,
};
self
}
/// Sets the default image to use if the user does not have a Gravatar. If `None` is provided,
/// then Gravatar returns a blue Gravatar logo. The default image can be either a URL or one of
/// Gravatar's premade defaults.
///
/// For more information, see <https://en.gravatar.com/site/implement/images/#default-image>.
///
/// **Default value:** `None`
pub fn set_default(&mut self, default: Option<Default>) -> &mut Self {
self.default = default;
self
}
/// If `force_default` is set to `true`, then Gravatar will always return the specified default
/// image, whether or not the user's email exists.
///
/// For more information, see <https://en.gravatar.com/site/implement/images/#force-default>.
///
/// **Default value:** `false`
pub fn set_force_default(&mut self, force_default: bool) -> &mut Self {
self.force_default = force_default;
self
}
/// Sets the maximum rating level for which Gravatar will show the user's image. If `None` is
/// provided, then Gravatar will only deliver "G"-rated images by default. If an image is at a
/// higher rating level than the requested one, the default image is returned instead.
///
/// For more information, see <https://en.gravatar.com/site/implement/images/#rating>.
///
/// **Default value:** `None`
pub fn set_rating(&mut self, rating: Option<Rating>) -> &mut Self {
self.rating = rating;
self
}
/// If `ssl` is set to `true`, Gravatar's secure URL (https://secure.gravatar.com/avatar/...)
/// is used. Otherwise, the non-SSL website is used instead
/// (http://www.gravatar.com/avatar/...).
///
/// **Default value:** `true`
pub fn set_ssl(&mut self, ssl: bool) -> &mut Self {
self.ssl = ssl;
self
}
/// Returns the image URL of the user's Gravatar with all specified parameters.
pub fn image_url(self: &Self) -> Url {
// Generate MD5 hash of email
let digest = Md5::new()
.chain(&self.email.trim().to_ascii_lowercase())
.result();
let hash = format!("{:x}", digest);
// Create base URL using the hash
let mut url = Url::parse(&format!(
"{}.gravatar.com/avatar/{}",
if self.ssl {
"https://secure"
} else {
"http://www"
},
hash
))
.unwrap();
if let Some(s) = self.size {
url.query_pairs_mut().append_pair("s", &s.to_string());
}
if let Some(ref d) = self.default {
let val = match d {
Default::ImageUrl(ref u) => {
utf8_percent_encode(u.as_str(), DEFAULT_ENCODE_SET).to_string()
}
Default::Http404 => "404".to_string(),
Default::MysteryMan => "mm".to_string(),
Default::Identicon => "identicon".to_string(),
Default::MonsterId => "monsterid".to_string(),
Default::Wavatar => "wavatar".to_string(),
Default::Retro => "retro".to_string(),
Default::Blank => "blank".to_string(),
};
url.query_pairs_mut().append_pair("d", &val);
}
if self.force_default {
url.query_pairs_mut().append_pair("f", "y");
}
if let Some(ref r) = self.rating {
let val = match r {
Rating::G => "g",
Rating::Pg => "pg",
Rating::R => "r",
Rating::X => "x",
};
url.query_pairs_mut().append_pair("r", val);
}
url
}
}