1 // Downloads torrents from the command-line.
13 "github.com/anacrolix/args"
14 "github.com/anacrolix/envpprof"
15 "github.com/anacrolix/log"
16 xprometheus "github.com/anacrolix/missinggo/v2/prometheus"
17 "github.com/anacrolix/torrent/bencode"
18 "github.com/anacrolix/torrent/version"
19 "github.com/davecgh/go-spew/spew"
20 "github.com/prometheus/client_golang/prometheus"
21 "github.com/prometheus/client_golang/prometheus/promhttp"
25 if err := mainErr(); err != nil {
26 log.Printf("error in main: %v", err)
32 prometheus.MustRegister(xprometheus.NewExpvarCollector())
33 http.Handle("/metrics", promhttp.Handler())
36 func mainErr() error {
38 stdLog.SetFlags(stdLog.Flags() | stdLog.Lshortfile)
39 debug := args.Flag(args.FlagOpt{Long: "debug"})
40 return args.ParseMain(
42 args.Subcommand("metainfo", metainfoCmd),
43 args.Subcommand("announce", func(p args.SubCmdCtx) error {
45 err := p.NewParser().AddParams(
46 args.Pos("tracker", &cmd.Tracker),
47 args.Pos("infohash", &cmd.InfoHash)).Parse()
51 return announceErr(cmd)
53 args.Subcommand("scrape", func(p args.SubCmdCtx) error {
55 err := p.NewParser().AddParams(
56 args.Pos("tracker", &cmd.Tracker),
57 args.Pos("infohash", &cmd.InfoHashes, args.Arity('+'))).Parse()
63 args.Subcommand("download", func(p args.SubCmdCtx) error {
65 err := p.NewParser().AddParams(
66 append(args.FromStruct(&dlc), debug)...,
75 p.Defer(func() error {
76 return downloadErr(dlf)
82 func(p args.SubCmdCtx) error {
83 var print func(interface{}) error
85 args.Subcommand("json", func(ctx args.SubCmdCtx) (err error) {
87 je := json.NewEncoder(os.Stdout)
92 args.Subcommand("spew", func(ctx args.SubCmdCtx) (err error) {
94 config := spew.NewDefaultConfig()
95 config.DisableCapacities = true
97 print = func(v interface{}) error {
104 return errors.New("an output type is required")
106 d := bencode.NewDecoder(os.Stdin)
107 p.Defer(func() error {
115 return fmt.Errorf("decoding message index %d: %w", i, err)
123 args.Help("reads bencoding from stdin into Go native types and spews the result"),
125 args.Subcommand("version", func(p args.SubCmdCtx) error {
126 fmt.Printf("HTTP User-Agent: %q\n", version.DefaultHttpUserAgent)
127 fmt.Printf("Torrent client version: %q\n", version.DefaultExtendedHandshakeClientVersion)
128 fmt.Printf("Torrent version prefix: %q\n", version.DefaultBep20Prefix)
131 args.Subcommand("serve", serve, args.Help("creates and seeds a torrent from a filepath")),