module Book ( Book(..), readBookInfo, unknownBook , bookFileName, titleFromFileName ) where import Data.ByteString.Lazy.Internal (smallChunkSize) import Data.List (intercalate) import System.FilePath (makeValid, takeBaseName) import Text.Regex.TDFA ((=~)) import FB2 import Utils -- TODO: consider structured author data Book = Book { authors :: [String] , title :: String , genres :: [String] , date :: String , lang :: String , archive :: String , path :: String , size :: Int } deriving (Eq) instance Show Book where show b = unlines $ [ (intercalate ", " $ authors b) ++ " /" , " " ++ title b , " " ++ date b , " " ++ (intercalate " " $ genres b) , " lang : " ++ lang b , " in : " ++ (archive b) ++ " : " ++ (path b) ] unknownBook :: Book unknownBook = Book { authors = [] , title = "" , genres = [] , date = "" , lang = "" , archive = "" , path = "" , size = 0 } readBookInfo :: String -> Book readBookInfo bytes = let -- in FB2 all meta data is usually in the beginning, -- we don't need to parse everything, smallChunkSize is just a guess (4k) -- which seems to work on most of the real-world files doc = convParseXml $ take smallChunkSize bytes t = getTitle doc as = getAuthors doc g = getGenres doc l = getLang doc d = getDate doc sz = length bytes in unknownBook { authors = as, title = t, genres = g , lang = l, date = d, size = sz } -- | Standard template for book files. bookFileName :: Book -> String bookFileName book = let t = title book as = intercalate ", " . filter (not . null) $ authors book bookname = takeBaseName $ path book year = wrap (" (") (")") (date book) wrap b a what | null what = "" | otherwise = b ++ what ++ a filename = intercalate " ~ " . filter (not . null) $ [ t, (as ++ year), (bookname ++ ".fb2") ] in makeValid . fixname $ filename -- | Extract title template from filename titleFromFileName :: String -> String titleFromFileName n = let (t,_,_) = n =~ " ~ " :: (String,String,String) in unfixname t