Inspired by Don Stewart's article on Scripting with Haskell I tried a rewrite of a shell-script I did the other day. I was really astonished how easily it worked but as a whole it is about double the size of my shell script and some things feel a bit "clumsy".
IO-return type, which seems a bit "unhaskellish"
extractFromFileseem a bit unelegant especially the maybe parts and the trivial case "" to prevent last from throwing an error.
To run my code the packages
network-info had to be installed - the rest was already there (Debian haskell-platform 2012.2.0.0, ghc-7.4.1)
What my code does:
I want to log the IP-address my provider gives me - and when it changes; as I have a dynamic IP. With this information I can ssh from other devices to my home PC, and I know how long the periods are in which my IP doesn't change.
import System.IO (readFile, appendFile) import System.Exit (exitSuccess) import System.Directory (doesFileExist, getHomeDirectory) import Data.Maybe (listToMaybe, fromMaybe) import Data.Time (getZonedTime) import Network.BSD (getHostName) import Network.Curl (curlGetString, URLString, CurlOption(CurlTimeout)) import Network.Curl.Code (CurlCode(CurlOK)) import Network.Info (getNetworkInterfaces, NetworkInterface, name, ipv4) localFilePath :: FilePath localFilePath = "/Dropbox/iplog.log" dyndns :: URLString dyndns = "http://checkip.dyndns.org" main :: IO () main = do home <- getHomeDirectory let iplogFilePath = home ++ localFilePath iplogS <- myReadFile iplogFilePath curlS <- getCurlIP dyndns let oldIP = extractFromFile iplogS currentIP = extractIp curlS if oldIP /= currentIP then do date <- fmap show getZonedTime host <- getHostName localIP <- fmap getLocalIP getNetworkInterfaces let content = unwords [currentIP, date, host, localIP, "\n"] appendFile iplogFilePath content else exitSuccess extractFromFile :: String -> String extractFromFile "" = "" extractFromFile s = (fromMaybe  . listToMaybe . words . last . lines) s extractIp :: String -> String extractIp "" = "" extractIp s = (takeWhile (/='<') . last . words) s myReadFile :: FilePath -> IO String myReadFile fp = do iplogExists <- doesFileExist fp if iplogExists then readFile fp else do print "File does not exist - and will be created" print ("at: ~" ++ localFilePath) return "" getCurlIP :: URLString -> IO String getCurlIP url = do (curlState, curlString) <- curlGetString url [CurlTimeout 60] if curlState == CurlOK then return curlString else do print "No external IP found" return "0.0.0.0" getLocalIP :: [NetworkInterface] -> String getLocalIP = show . ipv4 . head . filter (\x -> name x == "eth0")