46 lines
1.5 KiB
Haskell
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
|
|
[] -> ""
|