]> Sergey Matveev's repositories - btrtrc.git/blob - metainfo/metainfo.go
Buffer metainfo loads from files
[btrtrc.git] / metainfo / metainfo.go
1 package metainfo
2
3 import (
4         "bufio"
5         "io"
6         "net/url"
7         "os"
8         "time"
9
10         "github.com/anacrolix/torrent/bencode"
11 )
12
13 type MetaInfo struct {
14         InfoBytes    bencode.Bytes `bencode:"info,omitempty"`                              // BEP 3
15         Announce     string        `bencode:"announce,omitempty"`                          // BEP 3
16         AnnounceList AnnounceList  `bencode:"announce-list,omitempty"`                     // BEP 12
17         Nodes        []Node        `bencode:"nodes,omitempty,ignore_unmarshal_type_error"` // BEP 5
18         // Where's this specified? Mentioned at
19         // https://wiki.theory.org/index.php/BitTorrentSpecification: (optional) the creation time of
20         // the torrent, in standard UNIX epoch format (integer, seconds since 1-Jan-1970 00:00:00 UTC)
21         CreationDate int64   `bencode:"creation date,omitempty,ignore_unmarshal_type_error"`
22         Comment      string  `bencode:"comment,omitempty"`
23         CreatedBy    string  `bencode:"created by,omitempty"`
24         Encoding     string  `bencode:"encoding,omitempty"`
25         UrlList      UrlList `bencode:"url-list,omitempty"` // BEP 19 WebSeeds
26 }
27
28 // Load a MetaInfo from an io.Reader. Returns a non-nil error in case of
29 // failure.
30 func Load(r io.Reader) (*MetaInfo, error) {
31         var mi MetaInfo
32         d := bencode.NewDecoder(r)
33         err := d.Decode(&mi)
34         if err != nil {
35                 return nil, err
36         }
37         return &mi, nil
38 }
39
40 // Convenience function for loading a MetaInfo from a file.
41 func LoadFromFile(filename string) (*MetaInfo, error) {
42         f, err := os.Open(filename)
43         if err != nil {
44                 return nil, err
45         }
46         defer f.Close()
47         var buf bufio.Reader
48         buf.Reset(f)
49         return Load(&buf)
50 }
51
52 func (mi MetaInfo) UnmarshalInfo() (info Info, err error) {
53         err = bencode.Unmarshal(mi.InfoBytes, &info)
54         return
55 }
56
57 func (mi MetaInfo) HashInfoBytes() (infoHash Hash) {
58         return HashBytes(mi.InfoBytes)
59 }
60
61 // Encode to bencoded form.
62 func (mi MetaInfo) Write(w io.Writer) error {
63         return bencode.NewEncoder(w).Encode(mi)
64 }
65
66 // Set good default values in preparation for creating a new MetaInfo file.
67 func (mi *MetaInfo) SetDefaults() {
68         mi.CreatedBy = "github.com/anacrolix/torrent"
69         mi.CreationDate = time.Now().Unix()
70 }
71
72 // Creates a Magnet from a MetaInfo. Optional infohash and parsed info can be provided.
73 func (mi MetaInfo) Magnet(infoHash *Hash, info *Info) (m Magnet) {
74         m.Trackers = append(m.Trackers, mi.UpvertedAnnounceList().DistinctValues()...)
75         if info != nil {
76                 m.DisplayName = info.BestName()
77         }
78         if infoHash != nil {
79                 m.InfoHash = *infoHash
80         } else {
81                 m.InfoHash = mi.HashInfoBytes()
82         }
83         m.Params = make(url.Values)
84         m.Params["ws"] = mi.UrlList
85         return
86 }
87
88 // Returns the announce list converted from the old single announce field if
89 // necessary.
90 func (mi *MetaInfo) UpvertedAnnounceList() AnnounceList {
91         if mi.AnnounceList.OverridesAnnounce(mi.Announce) {
92                 return mi.AnnounceList
93         }
94         if mi.Announce != "" {
95                 return [][]string{{mi.Announce}}
96         }
97         return nil
98 }