svitak/app/EpubParser.hs

46 lines
1.5 KiB
Haskell

module EpubParser where
import Codec.Archive.Zip (toArchive, findEntryByPath, fromEntry, Archive)
import qualified Data.ByteString.Lazy as BL
import qualified Data.ByteString.Lazy.Char8 as C8
import Text.HTML.TagSoup (parseTags, fromAttrib, (~==), Tag, innerText, sections)
import System.FilePath (takeDirectory)
data BookInfo = BookInfo
{ title :: String
, author :: String
} deriving (Show)
openEpub :: FilePath -> IO (Either String Archive)
openEpub path = toArchive <$> BL.readFile path >>= \archive -> maybe (pure $ Left "Error reading file") (\entry -> if fromEntry entry == C8.pack "application/epub+zip" then pure (Right archive) else pure (Left "Wrong mimetype")) (findEntryByPath "mimetype" archive)
getOpfPath :: Archive -> Maybe FilePath
getOpfPath archive = do
entry <- findEntryByPath "META-INF/container.xml" archive
let content = C8.unpack (fromEntry entry)
let tags = parseTags content
let rootfileTags = filter (~== "<rootfile>") tags
-- If we found at least one, get the "full-path" attribute
case rootfileTags of
(t:_) -> Just (fromAttrib "full-path" t)
[] -> Nothing
getRootPrefix :: FilePath -> FilePath
getRootPrefix path =
let dir = takeDirectory path
in if dir == "."
then ""
else dir ++ "/"
tagify :: String -> String
tagify item = "<" ++ item ++ ">"
getTagText :: String -> [Tag String] -> String
getTagText tagName tags =
case sections (~== tagify tagName) tags of
(x:_) -> innerText x
[] -> ""