Expose MetaData directly so it can be bencoded from external packages
This commit is contained in:
parent
a44d2d88c3
commit
9d72fd024e
|
@ -344,7 +344,7 @@ func (b *Batch) Start(w io.Writer, nworkers int) (<-chan error, <-chan int64) {
|
|||
}
|
||||
|
||||
func (b *Batch) write_torrent(w io.Writer) error {
|
||||
var td torrent_data
|
||||
var td MetaInfo
|
||||
td.Announce = b.announce_list[0][0]
|
||||
if len(b.announce_list) != 1 || len(b.announce_list[0]) != 1 {
|
||||
td.AnnounceList = b.announce_list
|
||||
|
|
|
@ -2,75 +2,26 @@ package metainfo
|
|||
|
||||
import (
|
||||
"crypto/sha1"
|
||||
"errors"
|
||||
"github.com/nsf/libtorgo/bencode"
|
||||
"io"
|
||||
"os"
|
||||
"time"
|
||||
)
|
||||
|
||||
// Information specific to a single file inside the MetaInfo structure..
|
||||
// Information specific to a single file inside the MetaInfo structure.
|
||||
type FileInfo struct {
|
||||
Length int64 `bencode:"length"`
|
||||
Path []string `bencode:"path"`
|
||||
}
|
||||
|
||||
// MetaInfo is the type you should use when reading torrent files. See Load and
|
||||
// LoadFromFile functions. All the fields are intended to be read-only. If
|
||||
// 'len(Files) == 1', then the FileInfo.Path is nil in that entry.
|
||||
type MetaInfo struct {
|
||||
Info
|
||||
InfoHash []byte
|
||||
AnnounceList [][]string
|
||||
CreationDate time.Time
|
||||
Comment string
|
||||
CreatedBy string
|
||||
Encoding string
|
||||
WebSeedURLs []string
|
||||
InfoBytes []byte
|
||||
}
|
||||
|
||||
// Load a MetaInfo from an io.Reader. Returns a non-nil error in case of
|
||||
// failure.
|
||||
func Load(r io.Reader) (*MetaInfo, error) {
|
||||
var mi MetaInfo
|
||||
var data torrent_data
|
||||
d := bencode.NewDecoder(r)
|
||||
err := d.Decode(&data)
|
||||
err := d.Decode(&mi)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
mi.Info = data.Info.Info
|
||||
mi.InfoBytes = data.Info.Bytes
|
||||
mi.InfoHash = data.Info.Hash
|
||||
if len(data.AnnounceList) > 0 {
|
||||
mi.AnnounceList = data.AnnounceList
|
||||
} else {
|
||||
mi.AnnounceList = [][]string{[]string{data.Announce}}
|
||||
}
|
||||
mi.CreationDate = time.Unix(data.CreationDate, 0)
|
||||
mi.Comment = data.Comment
|
||||
mi.CreatedBy = data.CreatedBy
|
||||
mi.Encoding = data.Encoding
|
||||
if data.URLList != nil {
|
||||
switch v := data.URLList.(type) {
|
||||
case string:
|
||||
mi.WebSeedURLs = []string{v}
|
||||
case []interface{}:
|
||||
var ok bool
|
||||
ss := make([]string, len(v))
|
||||
for i, s := range v {
|
||||
ss[i], ok = s.(string)
|
||||
if !ok {
|
||||
return nil, errors.New("bad url-list data type")
|
||||
}
|
||||
}
|
||||
mi.WebSeedURLs = ss
|
||||
default:
|
||||
return nil, errors.New("bad url-list data type")
|
||||
}
|
||||
}
|
||||
return &mi, nil
|
||||
}
|
||||
|
||||
|
@ -84,6 +35,7 @@ func LoadFromFile(filename string) (*MetaInfo, error) {
|
|||
return Load(f)
|
||||
}
|
||||
|
||||
// The info dictionary.
|
||||
type Info struct {
|
||||
PieceLength int64 `bencode:"piece length"`
|
||||
Pieces []byte `bencode:"pieces"`
|
||||
|
@ -93,17 +45,15 @@ type Info struct {
|
|||
Files []FileInfo `bencode:"files,omitempty"`
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// unmarshal structures
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
type torrent_info_ex struct {
|
||||
// The info dictionary with its hash and raw bytes exposed, as these are
|
||||
// important to Bittorrent.
|
||||
type InfoEx struct {
|
||||
Info
|
||||
Hash []byte
|
||||
Bytes []byte
|
||||
}
|
||||
|
||||
func (this *torrent_info_ex) UnmarshalBencode(data []byte) error {
|
||||
func (this *InfoEx) UnmarshalBencode(data []byte) error {
|
||||
this.Bytes = make([]byte, 0, len(data))
|
||||
this.Bytes = append(this.Bytes, data...)
|
||||
h := sha1.New()
|
||||
|
@ -112,12 +62,12 @@ func (this *torrent_info_ex) UnmarshalBencode(data []byte) error {
|
|||
return bencode.Unmarshal(data, &this.Info)
|
||||
}
|
||||
|
||||
func (this *torrent_info_ex) MarshalBencode() ([]byte, error) {
|
||||
func (this *InfoEx) MarshalBencode() ([]byte, error) {
|
||||
return bencode.Marshal(&this.Info)
|
||||
}
|
||||
|
||||
type torrent_data struct {
|
||||
Info torrent_info_ex `bencode:"info"`
|
||||
type MetaInfo struct {
|
||||
Info InfoEx `bencode:"info"`
|
||||
Announce string `bencode:"announce"`
|
||||
AnnounceList [][]string `bencode:"announce-list,omitempty"`
|
||||
CreationDate int64 `bencode:"creation date,omitempty"`
|
||||
|
|
|
@ -9,11 +9,11 @@ func test_file(t *testing.T, filename string) {
|
|||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if len(mi.Files) == 1 {
|
||||
t.Logf("Single file: %s (length: %d)\n", mi.Name, mi.Files[0].Length)
|
||||
if len(mi.Info.Files) == 1 {
|
||||
t.Logf("Single file: %s (length: %d)\n", mi.Info.Name, mi.Info.Files[0].Length)
|
||||
} else {
|
||||
t.Logf("Multiple files: %s\n", mi.Name)
|
||||
for _, f := range mi.Files {
|
||||
t.Logf("Multiple files: %s\n", mi.Info.Name)
|
||||
for _, f := range mi.Info.Files {
|
||||
t.Logf(" - %s (length: %d)\n", path.Join(f.Path...), f.Length)
|
||||
}
|
||||
}
|
||||
|
@ -23,9 +23,9 @@ func test_file(t *testing.T, filename string) {
|
|||
t.Logf("Tracker: %s\n", tracker)
|
||||
}
|
||||
}
|
||||
for _, url := range mi.WebSeedURLs {
|
||||
t.Logf("URL: %s\n", url)
|
||||
}
|
||||
// for _, url := range mi.WebSeedURLs {
|
||||
// t.Logf("URL: %s\n", url)
|
||||
// }
|
||||
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue