Skip to content

Commit 3aa1708

Browse files
Ch 22 - Last Exercise - Not clear what's asked of me
1 parent 47ef2d0 commit 3aa1708

File tree

2 files changed

+113
-0
lines changed

2 files changed

+113
-0
lines changed

chapter22/package.yaml

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,15 @@ description: Please see the README on Github at <https://github.com/Arul
2121

2222
dependencies:
2323
- base >= 4.7 && < 5
24+
- bytestring
25+
- hedis
26+
- mtl
27+
- network-uri
28+
- random
29+
- scotty
30+
- semigroups
31+
- text
32+
- transformers
2433

2534
library:
2635
source-dirs: src

chapter22/src/ShawtyWithReader.hs

Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
{-# LANGUAGE OverloadedStrings #-}
2+
3+
module ShawtyWithReader where
4+
5+
import Control.Monad (replicateM)
6+
import Control.Monad.IO.Class (liftIO)
7+
import qualified Data.ByteString.Char8 as BC
8+
import Data.Text.Encoding (decodeUtf8, encodeUtf8)
9+
import qualified Data.Text.Lazy as TL
10+
import qualified Database.Redis as R
11+
import Network.URI (URI, parseURI)
12+
import qualified System.Random as SR
13+
import Web.Scotty
14+
15+
16+
newtype Reader r a =
17+
Reader {runReader :: r -> a}
18+
19+
alphaNum :: String
20+
alphaNum = ['A'..'Z'] ++ ['0'..'9']
21+
22+
randomElement :: String -> IO Char
23+
randomElement xs = do
24+
let maxIndex :: Int
25+
maxIndex = length xs - 1
26+
-- Right of arrow is IO Int, so randomDigit is Int
27+
randomDigit <- SR.randomRIO (0, maxIndex) :: IO Int
28+
return (xs !! randomDigit)
29+
30+
shortyGen :: IO String
31+
shortyGen =
32+
replicateM 7 (randomElement alphaNum)
33+
34+
saveURI :: R.Connection
35+
-> BC.ByteString
36+
-> BC.ByteString
37+
-> IO (Either R.Reply R.Status)
38+
saveURI conn shortURI uri =
39+
R.runRedis conn $ R.set shortURI uri
40+
41+
getURI :: R.Connection
42+
-> BC.ByteString
43+
-> IO (Either R.Reply (Maybe BC.ByteString))
44+
getURI conn shortURI = R.runRedis conn $ R.get shortURI
45+
46+
linkShorty :: String -> String
47+
linkShorty shorty =
48+
concat [ "<a href=\""
49+
, shorty
50+
, "\">Copy and paste your short URL</a>"
51+
]
52+
53+
shortyCreated :: Show a => a -> String -> TL.Text
54+
shortyCreated resp shawty =
55+
TL.concat [ TL.pack (show resp)
56+
, " shorty is: ", TL.pack (linkShorty shawty)
57+
]
58+
59+
shortyAintUri :: TL.Text -> TL.Text
60+
shortyAintUri uri =
61+
TL.concat [ uri
62+
, " wasn't a url, did you forget http://?"
63+
]
64+
65+
shortyFound :: TL.Text -> TL.Text
66+
shortyFound tbs =
67+
TL.concat ["<a href=\"", tbs, "\">", tbs, "</a>"]
68+
69+
data Conn =
70+
Conn {getConn :: R.Connection}
71+
72+
app :: Conn
73+
-> ScottyM ()
74+
app = do
75+
rConn <- getConn
76+
return $ get "/" $ do
77+
uri <- param "uri"
78+
let parsedUri :: Maybe URI
79+
parsedUri = parseURI $ TL.unpack uri
80+
case parsedUri of
81+
Just _ -> do
82+
shawty <- liftIO shortyGen
83+
let shorty :: BC.ByteString
84+
shorty = BC.pack shawty
85+
uri' :: BC.ByteString
86+
uri' = encodeUtf8 (TL.toStrict uri)
87+
resp <- liftIO (saveURI rConn shorty uri')
88+
html (shortyCreated resp shawty)
89+
Nothing -> text (shortyAintUri uri)
90+
return $ get "/:short" $ do
91+
short <- param "short"
92+
uri <- liftIO (getURI rConn short)
93+
case uri of
94+
Left reply -> text (TL.pack (show reply))
95+
Right mbBS -> case mbBS of
96+
Nothing -> text "uri not found"
97+
Just bs -> html (shortyFound tbs)
98+
where tbs :: TL.Text
99+
tbs = TL.fromStrict (decodeUtf8 bs)
100+
101+
main :: IO ()
102+
main = do
103+
rConn <- R.connect R.defaultConnectInfo
104+
scotty 3000 (app (Conn rConn))

0 commit comments

Comments
 (0)