1 module FuncTorrent.Metainfo
8 import Prelude hiding (lookup)
9 import Data.ByteString.Char8 (ByteString, unpack)
10 import Data.Map as M ((!), lookup)
11 import Crypto.Hash.SHA1 (hash)
12 import Data.Maybe (maybeToList)
14 import FuncTorrent.Bencode (BVal(..), encode, decode, bstrToString, bValToInteger)
16 -- only single file mode supported for the time being.
17 data Info = Info { pieceLength :: !Integer
18 , pieces :: !ByteString
19 , private :: !(Maybe Integer)
21 , lengthInBytes :: !Integer
22 , md5sum :: !(Maybe String)
25 data Metainfo = Metainfo { info :: !Info
26 , announceList :: ![String]
27 , creationDate :: !(Maybe Integer)
28 , comment :: !(Maybe String)
29 , createdBy :: !(Maybe String)
30 , encoding :: !(Maybe String)
31 , infoHash :: !ByteString
34 mkInfo :: BVal -> Maybe Info
35 mkInfo (Bdict m) = let (Bint pieceLength') = m ! "piece length"
36 (Bstr pieces') = m ! "pieces"
38 (Bstr name') = m ! "name"
39 (Bint length') = m ! "length"
41 in Just Info { pieceLength = pieceLength'
45 , lengthInBytes = length'
49 mkMetaInfo :: BVal -> Either String Metainfo
50 mkMetaInfo (Bdict m) =
51 let (Just info') = mkInfo $ m ! "info"
52 announce' = lookup "announce" m
53 announceList' = lookup "announce-list" m
54 creationDate' = lookup "creation date" m
55 comment' = lookup "comment" m
56 createdBy' = lookup "created by" m
57 encoding' = lookup "encoding" m
60 , announceList = maybeToList (announce' >>= bstrToString)
61 ++ getAnnounceList announceList'
62 , creationDate = bValToInteger =<< creationDate'
63 , comment = bstrToString =<< comment'
64 , createdBy = bstrToString =<< createdBy'
65 , encoding = bstrToString =<< encoding'
66 , infoHash = hash . encode $ (m ! "info")
69 mkMetaInfo _ = Left "mkMetaInfo: expect an input dict"
71 getAnnounceList :: Maybe BVal -> [String]
72 getAnnounceList Nothing = []
73 getAnnounceList (Just (Bint _)) = []
74 getAnnounceList (Just (Bstr _)) = []
75 getAnnounceList (Just (Blist l)) = map (\s -> case s of
76 (Bstr s') -> unpack s'
77 (Blist s') -> case s' of
78 [Bstr s''] -> unpack s''
82 getAnnounceList (Just (Bdict _)) = []
84 torrentToMetainfo :: ByteString -> Either String Metainfo