diff --git a/client.go b/client.go index 39dc0a1e..56df4285 100644 --- a/client.go +++ b/client.go @@ -1083,6 +1083,21 @@ func (cl *Client) setMetaData(t *torrent, md metainfo.Info, bytes []byte) (err e } cl.downloadStrategy.TorrentStarted(t) + select { + case t.gotMetainfo <- &metainfo.MetaInfo{ + Info: metainfo.InfoEx{ + Info: md, + }, + CreationDate: time.Now().Unix(), + Comment: "metadata set in client", + CreatedBy: "go.torrent", + // TODO(anacrolix): Expose trackers given when torrent added. + }: + default: + panic("shouldn't block") + } + close(t.gotMetainfo) + t.gotMetainfo = nil return } @@ -1096,7 +1111,10 @@ func newTorrent(ih InfoHash, announceList [][]string) (t *torrent, err error) { closing: make(chan struct{}), ceasingNetworking: make(chan struct{}), + + gotMetainfo: make(chan *metainfo.MetaInfo, 1), } + t.GotMetainfo = t.gotMetainfo t.Trackers = make([][]tracker.Client, len(announceList)) for tierIndex := range announceList { tier := t.Trackers[tierIndex] @@ -1120,12 +1138,12 @@ func newTorrent(ih InfoHash, announceList [][]string) (t *torrent, err error) { return } -func (cl *Client) AddMagnet(uri string) (err error) { +func (cl *Client) AddMagnet(uri string) (t *torrent, err error) { m, err := ParseMagnetURI(uri) if err != nil { return } - t, err := newTorrent(m.InfoHash, [][]string{m.Trackers}) + t, err = newTorrent(m.InfoHash, [][]string{m.Trackers}) if err != nil { return } diff --git a/cmd/magnet-metainfo/main.go b/cmd/magnet-metainfo/main.go new file mode 100644 index 00000000..9e73c919 --- /dev/null +++ b/cmd/magnet-metainfo/main.go @@ -0,0 +1,48 @@ +// Converts magnet URIs and info hashes into torrent metainfo files. +package main + +import ( + "flag" + "log" + "os" + "sync" + + "github.com/anacrolix/libtorgo/bencode" + + "bitbucket.org/anacrolix/go.torrent" +) + +func main() { + flag.Parse() + cl, err := torrent.NewClient(nil) + if err != nil { + log.Fatalf("error creating client: %s", err) + } + wg := sync.WaitGroup{} + for _, arg := range flag.Args() { + t, err := cl.AddMagnet(arg) + if err != nil { + log.Fatalf("error adding magnet to client: %s", err) + } + wg.Add(1) + go func() { + defer wg.Done() + mi, ok := <-t.GotMetainfo + t.Close() + if !ok { + log.Printf("no metainfo for %q", t.Name()) + return + } + f, err := os.Create(mi.Info.Name + ".torrent") + if err != nil { + log.Fatalf("error creating torrent metainfo file: %s", err) + } + defer f.Close() + err = bencode.NewEncoder(f).Encode(mi) + if err != nil { + log.Fatalf("error writing torrent metainfo file: %s", err) + } + }() + } + wg.Wait() +} diff --git a/cmd/torrent/main.go b/cmd/torrent/main.go index ed989324..20a7f6e3 100644 --- a/cmd/torrent/main.go +++ b/cmd/torrent/main.go @@ -56,7 +56,7 @@ func main() { log.Fatalf("error parsing magnet uri: %s", err) } ih = m.InfoHash - err = client.AddMagnet(arg) + _, err = client.AddMagnet(arg) if err != nil { log.Fatalf("error adding magnet: %s", err) } diff --git a/cmd/torrentfs/main.go b/cmd/torrentfs/main.go index 4a5b7599..fa9389e4 100644 --- a/cmd/torrentfs/main.go +++ b/cmd/torrentfs/main.go @@ -130,7 +130,7 @@ func main() { log.Printf("error adding torrent to client: %s", err) } } else if ev.MagnetURI != "" { - err := client.AddMagnet(ev.MagnetURI) + _, err := client.AddMagnet(ev.MagnetURI) if err != nil { log.Printf("error adding magnet: %s", err) } diff --git a/fs/torrentfs_test.go b/fs/torrentfs_test.go index fb214bdf..8cd8ebe5 100644 --- a/fs/torrentfs_test.go +++ b/fs/torrentfs_test.go @@ -142,7 +142,7 @@ func TestDownloadOnDemand(t *testing.T) { seeder.WriteStatus(w) }) defer seeder.Stop() - err = seeder.AddMagnet(fmt.Sprintf("magnet:?xt=urn:btih:%x", layout.Metainfo.Info.Hash)) + _, err = seeder.AddMagnet(fmt.Sprintf("magnet:?xt=urn:btih:%x", layout.Metainfo.Info.Hash)) if err != nil { t.Fatal(err) } diff --git a/torrent.go b/torrent.go index ce9d9273..c4686eda 100644 --- a/torrent.go +++ b/torrent.go @@ -67,6 +67,9 @@ type torrent struct { DisplayName string MetaData []byte metadataHave []bool + + gotMetainfo chan *metainfo.MetaInfo + GotMetainfo <-chan *metainfo.MetaInfo } func (t *torrent) worstConnsHeap() (wcs *worstConns) {