libravatar 0.1.0.2 → 0.2.0.0
raw patch · 3 files changed
+150/−33 lines, 3 filesPVP ok
version bump matches the API change (PVP)
API changes (from Hackage documentation)
+ Network.Libravatar: AvatarOptions :: Bool -> DefaultImage -> Size -> AvatarOptions
+ Network.Libravatar: DefaultSize :: Size
+ Network.Libravatar: Email :: String -> UserAddress
+ Network.Libravatar: ImgCustom :: String -> DefaultImage
+ Network.Libravatar: ImgLibravatarLogo :: DefaultImage
+ Network.Libravatar: ImgNotFound :: DefaultImage
+ Network.Libravatar: ImgSpecial :: SpecialImage -> DefaultImage
+ Network.Libravatar: OpenID :: String -> UserAddress
+ Network.Libravatar: Size :: Int -> Size
+ Network.Libravatar: SpecialIdenticon :: SpecialImage
+ Network.Libravatar: SpecialMonsterID :: SpecialImage
+ Network.Libravatar: SpecialMysteryPerson :: SpecialImage
+ Network.Libravatar: SpecialRetro :: SpecialImage
+ Network.Libravatar: SpecialWavatar :: SpecialImage
+ Network.Libravatar: [optDefault] :: AvatarOptions -> DefaultImage
+ Network.Libravatar: [optSecure] :: AvatarOptions -> Bool
+ Network.Libravatar: [optSize] :: AvatarOptions -> Size
+ Network.Libravatar: data AvatarOptions
+ Network.Libravatar: data DefaultImage
+ Network.Libravatar: data Size
+ Network.Libravatar: data SpecialImage
+ Network.Libravatar: data UserAddress
- Network.Libravatar: avatarUrl :: Either String String -> Bool -> Maybe String -> Maybe Int -> IO (Maybe String)
+ Network.Libravatar: avatarUrl :: UserAddress -> AvatarOptions -> IO (Maybe String)
Files
- NEWS +23/−0
- libravatar.cabal +2/−2
- src/Network/Libravatar.hs +125/−31
NEWS view
@@ -3,6 +3,29 @@ +libravatar 0.2.0.0 -- 2015-12-08+================================++General, build and documentation changes:++* Add some background details to the docs++New APIs, features and enhancements:++* Provide dedicated datatypes and more type safety++Bug fixes:++* (none)++Dependency changes:++* (none)+++++ libravatar 0.1.0.2 -- 2015-12-03 ================================
libravatar.cabal view
@@ -1,5 +1,5 @@ name: libravatar-version: 0.1.0.2+version: 0.2.0.0 synopsis: Use Libravatar, the decentralized avatar delivery service description: This package is a Haskell library for <http://libravatar.org Libravatar>.@@ -17,7 +17,7 @@ source-repository head type: darcs- location: http://darcs.rel4tion.org/repos/libravatar/+ location: http://hub.darcs.net/fr33domlover/libravatar library exposed-modules: Network.Libravatar
src/Network/Libravatar.hs view
@@ -14,7 +14,12 @@ -} module Network.Libravatar- ( avatarUrl+ ( UserAddress (..)+ , SpecialImage (..)+ , DefaultImage (..)+ , Size (..)+ , AvatarOptions (..)+ , avatarUrl ) where @@ -42,6 +47,76 @@ minAvatarSize = 1 maxAvatarSize = 512 +-- | User address for which to generate an avatar URL. Email or OpenID.+data UserAddress+ = Email String -- ^ For example @john\@doe.org@+ | OpenID String -- ^ For example @https://example.org/accounts/john/id@++-- | Special values available for the default image. The comments briefly+-- explain the origin of the image/technique.+data SpecialImage+ -- | A very simple outline of a person (constant image, does not vary by+ -- user address). Sometimes referred to as “mystery man”.+ = SpecialMysteryPerson+ -- | Geometric pattern based on a user address hash.+ --+ -- Origin: A visual representation of a hash value, usually of an+ -- IP address, that serves to identify a user of a computer system as a+ -- form of avatar while protecting the users' privacy.+ | SpecialIdenticon+ -- | A generated monster image with different colors, faces, etc.+ --+ -- Origin: A method to generate a unique monster image based upon a+ -- certain identifier (IP address, email address, etc.). It can be used to+ -- automatically provide personal avatar images in blog comments or other+ -- community services.+ | SpecialMonsterID+ -- | A generated face with differing features and backgrounds.+ --+ -- Origin: Wavatars is a Wordpress plugin that will generate and assign+ -- icons to the visitors leaving comments at your site. The icons are based+ -- on email, so a given visitor will get the same icon each time they+ -- comment. It livens up comment threads and gives people memorable “faces”+ -- to aid in following conversation threads. It’s also fun.+ | SpecialWavatar+ -- | A generated, 8-bit arcade-style pixelated face.+ --+ -- Origin: I don't know :P+ | SpecialRetro++-- | What to do if the user's address isn't found in the Libravatar server's+-- database.+data DefaultImage+ -- | Don't specify a default image, let the server send its default image,+ -- which is the Libravatar logo (the orange butterfly).+ = ImgLibravatarLogo+ -- | Return HTTP 404 error (i.e. file not found) instead of an image.+ | ImgNotFound+ -- | Use one of the available special images or image generators.+ | ImgSpecial SpecialImage+ -- | Use the given image URL as the default.+ | ImgCustom String++-- | Image size in pixels.+data Size+ -- | Use the given size. Acceptable values are between 1 and 512. Note that+ -- this library doesn't check the size you pass here, so make sure you+ -- pass a size within that range.+ = Size Int+ -- | Use the default size, which is 80 pixels.+ | DefaultSize++-- | Avatar details in addition to the user address itself.+data AvatarOptions = AvatarOptions+ { -- | Whether the avatar URL should be secure (use HTTPS).+ optSecure :: Bool+ -- | What to do if the user address isn't found in the Libravatar+ -- database.+ , optDefault :: DefaultImage+ -- | Image size in pixels.+ , optSize :: Size+ }+ -- Hash emails with MD5, I think it's faster than SHA256 hashMail :: String -> String hashMail =@@ -54,14 +129,14 @@ hashOpenid = show . sha256 . BLU.fromString -- From email or openid, generate avatar hash and get the relevant domain-parseUserAddress :: Either String String -> Maybe (String, String)-parseUserAddress (Left email) =+parseUserAddress :: UserAddress -> Maybe (String, String)+parseUserAddress (Email email) = let lowEmail = map toLower email d = dropWhile (/= '@') lowEmail domain = if null d then d else tail d hash = hashMail lowEmail in Just (hash, domain)-parseUserAddress (Right openid) = do+parseUserAddress (OpenID openid) = do uri <- parseAbsoluteURI openid auth <- uriAuthority uri let lower = map toLower@@ -72,12 +147,32 @@ } return (hashOpenid $ uriToString id openidl "", uriRegName authl) +-- Convert 'Size' to 'Maybe' for use with 'Maybe' functor+sizeToMaybe :: Size -> Maybe Int+sizeToMaybe (Size n) = Just n+sizeToMaybe DefaultSize = Nothing++-- Get name string for special image+showSpecial :: SpecialImage -> String+showSpecial SpecialMysteryPerson = "mm"+showSpecial SpecialIdenticon = "identicon"+showSpecial SpecialMonsterID = "monsterid"+showSpecial SpecialWavatar = "wavatar"+showSpecial SpecialRetro = "retro"++-- Get name string for default image+showDefault :: DefaultImage -> Maybe String+showDefault ImgLibravatarLogo = Nothing+showDefault ImgNotFound = Just "404"+showDefault (ImgSpecial img) = Just $ showSpecial img+showDefault (ImgCustom url) = Just url+ -- Determine URL query parameters-buildParams :: Maybe String -> Maybe Int -> [(String, String)]+buildParams :: DefaultImage -> Size -> [(String, String)] buildParams def size =- let defParam = liftM ((,) "d") def- size' = liftM (max minAvatarSize . min maxAvatarSize) size- sizeParam = liftM ((,) "s" . show) size'+ let defParam = fmap ((,) "d") $ showDefault def+ size' = fmap (max minAvatarSize . min maxAvatarSize) $ sizeToMaybe size+ sizeParam = fmap ((,) "s" . show) size' in catMaybes [defParam, sizeParam] -- Get the DNS service to query for a given domain and scheme@@ -170,49 +265,48 @@ -- | Return a URL to the avatar image. -- -- If an error occurs, return 'Nothing'. Currently, this happens only if the--- user address (first parameter) fails to be parsed.+-- user address fails to be parsed. -- -- Examples: -- -- Email, HTTP, default fallback image (the libravatar logo), -- default size (80): ----- >>> avatarUrl (Left "john@doe.org") False Nothing Nothing+-- >>> avatarUrl (Email "john@doe.org") AvatarOptions+-- >>> { optSecure = False+-- >>> , optDefault = ImgLibravatarLogo+-- >>> , optSize = DefaultSize+-- >>> } -- Just "http://cdn.libravatar.org/avatar/bc6a715808d9aae0ddeefb1e47e482a6" -- -- Email, HTTPS, default fallback image, size 100. But now use an email with a -- domain which has SRV records for avatars: ----- >>> avatarUrl (Left "fr33domlover@rel4tion.org") True Nothing (Just 100)+-- >>> avatarUrl (Email "fr33domlover@rel4tion.org") AvatarOptions+-- >>> { optSecure = True+-- >>> , optDefault = ImgLibravatarLogo+-- >>> , optSize = Size 100+-- >>> } -- Just "https://avatars.rel4tion.org:5679/avatar/e9e9ccabc2a166b1783bd7f4f9ceb376?s=100" -- -- OpenID, HTTPS, specified fallback (special value \"retro\"), default -- size (80): ----- >>> avatarUrl (Right "https://examplibre.org/accounts/xyz/id") True (Just "retro") Nothing+-- >>> avatarUrl (OpenID "https://examplibre.org/accounts/xyz/id") AvatarOptions+-- >>> { optSecure = True+-- >>> , optDefault = ImgSpecial SpecialRetro+-- >>> , optSize = DefaultSize+-- >>> } -- Just "https://seccdn.libravatar.org/avatar/c2cbc5f5a1784fa7105380e550360d73f15c4c1f9c7ca1ac436c45a33027fcd7?d=retro" -- -- (Note that the 2nd example uses dummy SRV records created by the author,--- and he doesn't really run (at the time of writing) a Libravatar provider.--- This is just an example, the specific URL here will probably result with--- 404.)-avatarUrl- :: Either String String- -- ^ User address. Email or OpenID.- -> Bool- -- ^ Whether the generated URL should be secure (use HTTPS).- -> Maybe String- -- ^ Default image URL if the user address isn't found in the Libravatar- -- server's database. If you pass 'Nothing', the default image will be the- -- Libravatar logo. A few special values are available, such as @404@- -- (return HTTP 404 error instead of an image) and @retro@ (one of the- -- several available simple default images).- -> Maybe Int- -- ^ Image size in pixels, default is 80.- -> IO (Maybe String)-avatarUrl address https def size =+-- and he isn't really running a Libravatar provider. This is just an example,+-- the specific URL here will probably result with 404.)+avatarUrl :: UserAddress -> AvatarOptions -> IO (Maybe String)+avatarUrl address options = let (hash, domain) = fromMaybe ("", "") $ parseUserAddress address- params = buildParams def size+ params = buildParams (optDefault options) (optSize options)+ https = optSecure options in if null domain then return Nothing else do