5 g "github.com/anacrolix/generics"
6 infohash_v2 "github.com/anacrolix/torrent/types/infohash-v2"
8 "github.com/anacrolix/torrent/metainfo"
9 pp "github.com/anacrolix/torrent/peer_protocol"
10 "github.com/anacrolix/torrent/storage"
13 // Specifies a new torrent for adding to a client, or additions to an existing Torrent. There are
14 // constructor functions for magnet URIs and torrent metainfo files. TODO: This type should be
15 // dismantled into a new Torrent option type, and separate Torrent mutate method(s).
16 type TorrentSpec struct {
17 // The tiered tracker URIs.
19 // TODO: Move into a "new" Torrent opt type.
20 InfoHash metainfo.Hash
21 InfoHashV2 g.Option[infohash_v2.T]
23 // The name to use if the Name field from the Info isn't available.
25 // WebSeed URLs. For additional options add the URLs separately with Torrent.AddWebSeeds
30 // The combination of the "xs" and "as" fields in magnet links, for now.
32 // BEP 52 "piece layers" from metainfo
33 PieceLayers map[string]string
35 // The chunk size to use for outbound requests. Defaults to 16KiB if not set. Can only be set
36 // for new Torrents. TODO: Move into a "new" Torrent opt type.
38 // TODO: Move into a "new" Torrent opt type.
39 Storage storage.ClientImpl
41 DisableInitialPieceCheck bool
43 // Whether to allow data download or upload
44 DisallowDataUpload bool
45 DisallowDataDownload bool
48 func TorrentSpecFromMagnetUri(uri string) (spec *TorrentSpec, err error) {
49 m, err := metainfo.ParseMagnetUri(uri)
54 Trackers: [][]string{m.Trackers},
55 DisplayName: m.DisplayName,
57 Webseeds: m.Params["ws"],
58 Sources: append(m.Params["xs"], m.Params["as"]...),
59 PeerAddrs: m.Params["x.pe"], // BEP 9
60 // TODO: What's the parameter for DHT nodes?
65 // The error will be from unmarshalling the info bytes. The TorrentSpec is still filled out as much
66 // as possible in this case.
67 func TorrentSpecFromMetaInfoErr(mi *metainfo.MetaInfo) (*TorrentSpec, error) {
68 info, err := mi.UnmarshalInfo()
70 err = fmt.Errorf("unmarshalling info: %w", err)
72 var v2Infohash g.Option[infohash_v2.T]
74 v2Infohash.Set(infohash_v2.HashBytes(mi.InfoBytes))
77 Trackers: mi.UpvertedAnnounceList(),
78 InfoHash: mi.HashInfoBytes(),
79 InfoHashV2: v2Infohash,
80 PieceLayers: mi.PieceLayers,
81 InfoBytes: mi.InfoBytes,
82 DisplayName: info.Name,
84 DhtNodes: func() (ret []string) {
85 ret = make([]string, 0, len(mi.Nodes))
86 for _, node := range mi.Nodes {
87 ret = append(ret, string(node))
94 // Panics if there was anything missing from the metainfo.
95 func TorrentSpecFromMetaInfo(mi *metainfo.MetaInfo) *TorrentSpec {
96 ts, err := TorrentSpecFromMetaInfoErr(mi)