94 lines
2.1 KiB
Go
94 lines
2.1 KiB
Go
package main
|
|
|
|
import (
|
|
"context"
|
|
"flag"
|
|
"fmt"
|
|
"log"
|
|
"os"
|
|
"path/filepath"
|
|
"regexp"
|
|
"time"
|
|
|
|
"github.com/anacrolix/torrent"
|
|
)
|
|
|
|
var invalidFilenameChars = regexp.MustCompile(`[<>:"/\\|?*\x00-\x1F]`)
|
|
|
|
// sanitizeFilename replaces invalid filesystem characters with underscores.
|
|
func sanitizeFilename(name string) string {
|
|
return invalidFilenameChars.ReplaceAllString(name, "_")
|
|
}
|
|
|
|
func main() {
|
|
// Command-line flags
|
|
output := flag.String("o", "", "Output .torrent filename (optional)")
|
|
timeout := flag.Duration("timeout", 5*time.Minute, "Timeout for metadata retrieval")
|
|
upload := flag.Bool("upload", false, "Allow uploading (seeding) after metadata retrieval")
|
|
|
|
flag.Usage = func() {
|
|
fmt.Fprintf(flag.CommandLine.Output(), "Usage: %s [options] magnet_link\nOptions:\n", os.Args[0])
|
|
flag.PrintDefaults()
|
|
}
|
|
flag.Parse()
|
|
|
|
if flag.NArg() < 1 {
|
|
flag.Usage()
|
|
os.Exit(1)
|
|
}
|
|
magnetLink := flag.Arg(0)
|
|
|
|
// Configure torrent client
|
|
clientConfig := torrent.NewDefaultClientConfig()
|
|
clientConfig.DataDir = os.TempDir()
|
|
clientConfig.NoUpload = !*upload
|
|
|
|
client, err := torrent.NewClient(clientConfig)
|
|
if err != nil {
|
|
log.Fatalf("Error creating torrent client: %v", err)
|
|
}
|
|
defer client.Close()
|
|
|
|
// Add magnet link
|
|
t, err := client.AddMagnet(magnetLink)
|
|
if err != nil {
|
|
log.Fatalf("Error adding magnet link: %v", err)
|
|
}
|
|
|
|
// Wait for metadata with timeout
|
|
ctx, cancel := context.WithTimeout(context.Background(), *timeout)
|
|
defer cancel()
|
|
|
|
select {
|
|
case <-t.GotInfo():
|
|
// Metadata received
|
|
case <-ctx.Done():
|
|
log.Fatalf("Timeout waiting for metadata after %v", *timeout)
|
|
}
|
|
|
|
info := t.Metainfo()
|
|
|
|
// Determine output filename
|
|
outFile := *output
|
|
if outFile == "" {
|
|
base := sanitizeFilename(t.Name())
|
|
outFile = base + ".torrent"
|
|
}
|
|
outFile = filepath.Clean(outFile)
|
|
|
|
// Write .torrent file
|
|
f, err := os.Create(outFile)
|
|
if err != nil {
|
|
log.Fatalf("Error creating file %s: %v", outFile, err)
|
|
}
|
|
defer f.Close()
|
|
|
|
if err := info.Write(f); err != nil {
|
|
log.Fatalf("Error writing torrent file: %v", err)
|
|
}
|
|
|
|
fmt.Printf("Torrent metadata saved to %s\n", outFile)
|
|
|
|
// Drop the torrent handle; client will close via defer
|
|
t.Drop()
|
|
}
|