oglaf/Main.hs

96 lines
2.5 KiB
Haskell
Raw Normal View History

2015-10-09 15:36:53 +02:00
{-# LANGUAGE OverloadedStrings, RecordWildCards, ScopedTypeVariables #-}
import Control.Monad (when, forM_)
import Control.Exception (try)
import Data.Text (Text, unpack)
import qualified Data.Text.IO as T
import Data.Monoid
import Data.ByteString.Lazy (hPut)
import System.IO
import System.IO.Temp (withSystemTempFile)
import System.Environment (getEnv, lookupEnv)
import Network.HTTP.Conduit (HttpException, simpleHttp)
import Telegram
import Parser
url :: String
url = "http://oglaf.com"
commands :: String -> Comic -> [Command]
commands path Comic{..} =
[ if page == 1
then message user title
else nothing
, sendFile user path
, message user descr ]
cache :: IO String
cache = do
path <- lookupEnv "XDG_CACHE_HOME"
case path of
Just x -> return (x ++ "/oglaf")
Nothing -> (++ "/.cache/oglaf") <$> getEnv "HOME"
lastComic :: IO Text
lastComic = do
res <- try (T.readFile =<< cache)
case res of
Left (err :: IOError) -> do
putStrLn ("Can't read saved state " ++ show err)
putStrLn "Send anyway"
return ""
Right title -> return title
setLastComic :: Text -> IO ()
setLastComic title = cache >>= flip T.writeFile title
findPages :: Text -> IO [Comic]
findPages = findPages' 1 where
findPages' n link = do
res <- try $ simpleHttp (url <> page)
case res of
Left (_ :: HttpException) -> return []
Right cur -> (parseComic cur n :) <$> findPages' (succ n) link
where
page = unpack link <> show n
main :: IO ()
main = do
comics <- parseArchive <$> simpleHttp (url <> "/archive")
when (null comics) (fail "error parsing comics archive")
let latest = head comics
last <- lastComic
if latest == last
then T.putStrLn ("Already sent " <> last <> ", stopping")
else do
pages <- findPages latest
process <- telegramProcess
socket <- telegramSocket
send socket connect
forM_ pages $ \comic ->
withSystemTempFile "oglaf.png" $ \path temp -> do
simpleHttp (imgUrl comic) >>= hPut temp
hClose temp
result <- try $ mapM (send socket) (commands path comic)
case result of
Left (err :: IOError) -> do
putStrLn "failed" >> print err
fail "Could not send the comic :("
Right _ -> do
setLastComic latest
putStrLn ("Sent " <> show (page comic))
closeTelegram socket process