eidolon/Helper.hs

179 lines
5.4 KiB
Haskell
Raw Normal View History

2014-08-13 22:52:57 +00:00
module Helper
( getUserIdFromText
2014-08-14 00:25:18 +00:00
, extractKey
2014-08-24 19:42:42 +00:00
, fromHex
, fromHex'
, toHex
, makeRandomToken
, generateSalt
2014-08-30 18:23:57 +00:00
, tagField
, userField
2014-09-03 23:15:27 +00:00
, sendMail
, generateString
, removeItem
2014-12-03 21:01:57 +00:00
, acceptedTypes
2014-12-14 19:21:23 +00:00
, iso8601
, localTimeToZonedTime
, rfc822
2014-12-19 20:59:55 +00:00
, mediumStaticImageRoute
, mediumStaticThumbRoute
2014-08-13 22:52:57 +00:00
)
where
import Prelude
2014-12-19 20:59:55 +00:00
import Yesod.Static
2014-08-15 11:24:14 +00:00
import Model
import Control.Applicative
import Control.Monad.Trans.Class
import Data.Maybe
2014-08-30 21:36:23 +00:00
import Data.Either
import Data.List
2014-08-24 19:42:42 +00:00
import qualified Data.ByteString as B
import qualified Data.ByteString.Lazy as BL
import qualified Data.ByteString.Char8 as BC
import qualified Data.Text as T
2014-12-14 19:21:23 +00:00
import Data.Time
import Data.Char
2014-08-15 11:24:14 +00:00
import Database.Persist
2014-08-13 22:52:57 +00:00
import Database.Persist.Types
2014-08-15 11:24:14 +00:00
import System.FilePath
2014-08-24 19:42:42 +00:00
import System.Random
2014-12-14 19:21:23 +00:00
import System.Locale
2014-08-15 11:24:14 +00:00
import Yesod.Persist.Core
import Yesod.Core.Types
2014-08-30 18:23:57 +00:00
import Yesod
2014-08-24 19:42:42 +00:00
import Numeric (readHex, showHex)
2014-09-03 23:15:27 +00:00
import Network.Mail.Mime
import Text.Blaze.Html.Renderer.Utf8
2014-08-13 22:52:57 +00:00
2014-08-24 19:42:42 +00:00
getUserIdFromText :: T.Text -> UserId
2014-08-13 22:52:57 +00:00
getUserIdFromText tempUserId =
2014-08-24 19:42:42 +00:00
Key $ PersistInt64 $ fromIntegral $ read $ T.unpack tempUserId
2014-08-14 00:25:18 +00:00
2014-08-24 19:42:42 +00:00
extractKey :: KeyBackend backend entity -> T.Text
2014-08-14 00:25:18 +00:00
extractKey = extractKey' . unKey
where
2014-08-24 19:42:42 +00:00
extractKey' (PersistInt64 k) = T.pack $ show k
2014-08-14 00:25:18 +00:00
extractKey' _ = ""
2014-08-15 11:24:14 +00:00
2014-08-24 19:42:42 +00:00
fromHex = BL.pack . hexToWords
where hexToWords (c:c':text) =
let hex = [c, c']
2014-08-26 02:37:56 +00:00
(word, _):_ = readHex hex
2014-08-24 19:42:42 +00:00
in word : hexToWords text
hexToWords _ = []
-- strict variant
fromHex' :: String -> B.ByteString
fromHex' = B.concat . BL.toChunks . fromHex
toHex :: B.ByteString -> T.Text
toHex = T.pack . concatMap mapByte . B.unpack
where mapByte = pad 2 '0' . flip showHex ""
pad len padding s
| length s < len = pad len padding $ padding:s
| otherwise = s
makeRandomToken :: IO T.Text
makeRandomToken = (T.pack . take 16 . randoms) `fmap` newStdGen
generateSalt :: IO B.ByteString
generateSalt = (B.pack . take 8 . randoms) <$> getStdGen
2014-08-30 18:23:57 +00:00
tagField :: Monad m => Field m [T.Text]
2014-08-30 18:23:57 +00:00
tagField = Field
{ fieldParse = \rawVals _ -> do
case rawVals of
[x] -> case null [x] of
2014-09-21 17:42:18 +00:00
False -> return $ Right $ Just $ removeItem "" $ T.splitOn " " x
True -> return $ Right $ Nothing
2014-08-30 18:23:57 +00:00
_ -> return $ Left $ error "unexpected tag list"
2014-08-30 21:36:23 +00:00
, fieldView = \idAttr nameAttr val eResult isReq ->
[whamlet|<input id=#{idAttr} type="text" name=#{nameAttr} value=#{either id (T.intercalate " ") eResult}>|]
2014-08-30 18:23:57 +00:00
, fieldEnctype = UrlEncoded
}
2014-09-03 23:15:27 +00:00
userField :: Monad m => [(T.Text, UserId)] -> Field m [UserId]
userField users = Field
{ fieldParse = \rawVals _ -> do
case rawVals of
[x] -> case x == "" of
False ->
-- clean = removeItem "" $ T.splitOn " " x
let ids = map (\u -> lookup u users) (removeItem "" $ T.splitOn " " x)
in case Nothing `elem` ids of
False -> return $ Right $ Just $ nub $ map fromJust ids
True -> return $ Left $ error "Invalid username list"
True -> return $ Right $ Just $ []
_ -> return $ Left $ error "unexpected username list"
, fieldView = \idAttr nameAttr val eResult isReq ->
[whamlet|<input id=#{idAttr} type="text" name=#{nameAttr} value=#{either id (getUsersFromResult users) eResult}>|]
, fieldEnctype = UrlEncoded
}
getUsersFromResult users res = T.intercalate " " $ map (\x -> fromMaybe "" $ reverseLookup x users) res
2014-09-03 23:15:27 +00:00
sendMail :: MonadIO m => T.Text -> T.Text -> Html -> m ()
sendMail toEmail subject body =
liftIO $ renderSendMail
Mail
{ mailFrom = Address Nothing "noreply" -- TODO: set sender Address
, mailTo = [Address Nothing toEmail]
, mailCc = []
, mailBcc = []
, mailHeaders = [("Subject", subject)]
, mailParts = [[Part
{ partType = "text/html; charset=utf-8"
, partEncoding = None
, partFilename = Nothing
, partHeaders = []
, partContent = renderHtml body
}]]
}
generateString :: IO T.Text
generateString = (toHex . B.pack . take 16 . randoms) <$> newStdGen
removeItem :: Eq a => a -> [a] -> [a]
removeItem _ [] = []
removeItem x (y:ys)
| x == y = removeItem x ys
| otherwise = y : removeItem x ys
2014-12-03 21:01:57 +00:00
reverseLookup :: Eq b => b -> [(a, b)] -> Maybe a
reverseLookup s ((x, y):zs)
| s == y = Just x
| s /= y = reverseLookup s zs
| otherwise = Nothing
2014-12-03 21:01:57 +00:00
acceptedTypes :: [T.Text]
2014-12-03 22:30:42 +00:00
acceptedTypes = ["image/jpeg", "image/jpg", "image/png", "image/x-ms-bmp", "image/x-bmp", "image/bmp", "image/tiff", "image/tiff-fx"]
2014-12-14 19:21:23 +00:00
iso8601 :: FormatTime t => t -> String
iso8601 time =
formatTime defaultTimeLocale (iso8601DateFormat $ Just "%H:%M:%S") time ++
zone
where zone = case formatTime defaultTimeLocale "%z" time of
(sig:digits@(h1:h2:m1:m2))
| sig `elem` "+-" &&
all isDigit digits ->
sig:h1:h2:':':m1:m2
_ ->
"Z"
localTimeToZonedTime :: TimeZone -> LocalTime -> ZonedTime
localTimeToZonedTime tz =
utcToZonedTime tz . localTimeToUTC tz
--rfc822 :: LocalTime -> String
rfc822 = formatTime defaultTimeLocale rfc822DateFormat
2014-12-19 20:59:55 +00:00
mediumStaticImageRoute :: Medium -> Route Static
mediumStaticImageRoute medium =
StaticRoute (drop 2 $ T.splitOn "/" $ T.pack $ mediumPath medium) []
mediumStaticThumbRoute :: Medium -> Route Static
mediumStaticThumbRoute medium =
StaticRoute (drop 2 $ T.splitOn "/" $ T.pack $ mediumThumb medium) []