package main import ( "bufio" "bytes" "crypto/sha1" "encoding/gob" "encoding/hex" "encoding/xml" "flag" "fmt" "io" "os" "strconv" "time" "go.stargrave.org/rutrackerer" ) func main() { doCSV := flag.Bool("csv", false, "Output CSV instead of gob") flag.Parse() br := bufio.NewReader(os.Stdin) d := xml.NewDecoder(br) var t xml.Token var err error var e xml.StartElement var ok bool for { t, err = d.Token() if err != nil { panic(err) } e, ok = t.(xml.StartElement) if ok && e.Name.Local == "torrents" { break } } var gobEnc *gob.Encoder bufStdout := bufio.NewWriter(os.Stdout) if !*doCSV { gobEnc = gob.NewEncoder(bufStdout) } emptyHash := make([]byte, sha1.Size) var torrent *rutrackerer.Torrent var c xml.CharData var attr xml.Attr for { t, err = d.Token() if err != nil { if err == io.EOF { break } panic(err) } e, ok = t.(xml.StartElement) if !ok { continue } switch e.Name.Local { case "title": t, err = d.Token() if err != nil { panic(err) } c, ok = t.(xml.CharData) if !ok { panic("non-character data after title") } torrent.Title = string(c) case "torrent": if len(e.Attr) < 3 { for _, attr = range e.Attr { if attr.Name.Local != "hash" { continue } if len(attr.Value) != sha1.Size*2 { panic("bad hash size") } _, err = hex.Decode(torrent.Hash[:], []byte(attr.Value)) if err != nil { panic(err) } } continue } if torrent != nil { if torrent.Title == "" { panic("empty title") } if torrent.Id == 0 { panic("empty id") } if torrent.Size == 0 { panic("empty size") } if bytes.Compare(torrent.Hash[:], emptyHash) == 0 { panic("empty hash") } if *doCSV { fmt.Println(torrent.CSV()) } else { if err = gobEnc.Encode(torrent); err != nil { panic(err) } } } torrent = new(rutrackerer.Torrent) for _, attr = range e.Attr { switch attr.Name.Local { case "id": torrent.Id, err = strconv.ParseInt(attr.Value, 10, 64) if err != nil { panic(err) } torrent.Offset = d.InputOffset() case "registred_at": torrent.Registered, err = time.Parse( "2006.01.02 15:04:05", attr.Value, ) if err != nil { panic(err) } case "size": torrent.Size, err = strconv.ParseInt(attr.Value, 10, 64) if err != nil { panic(err) } } } } } if !*doCSV { if err = bufStdout.Flush(); err != nil { panic(err) } } }