kaixuan1115 / notes

笔记收录
6 stars 0 forks source link

Golang爬取magnet保存torrent #4

Closed xiaokaixuan closed 5 years ago

xiaokaixuan commented 5 years ago
package main

import (
    "encoding/hex"
    "encoding/json"
    "fmt"
    "net/http"
    _ "net/http/pprof"
    "os"

    "github.com/shiyanhui/dht"
    md "github.com/bttown/metadata"
)

type file struct {
    Path   []interface{} `json:"path"`
    Length int           `json:"length"`
}

type bitTorrent struct {
    InfoHash string `json:"infohash"`
    Name     string `json:"name"`
    Files    []file `json:"files,omitempty"`
    Length   int    `json:"length,omitempty"`
}

func IsExist(path string) bool {
    _, err := os.Stat(path)
    return err == nil || os.IsExist(err)
}

func main() {
    go func() {
        http.ListenAndServe(":6060", nil)
    }()

    w := dht.NewWire(65536, 1024, 256)
    go func() {
        for resp := range w.Response() {
            metadata, err := dht.Decode(resp.MetadataInfo)
            if err != nil {
                continue
            }
            torrent := &md.Torrent{}
            md.NewTorrentFromMetadata(resp.MetadataInfo, torrent)
            fileName := hex.EncodeToString(resp.InfoHash)
            if IsExist(fileName + ".torrent") {
                continue
            }
            f, _ := os.Create(fileName + ".torrent")
            defer f.Close()
            f.Write(torrent.Bytes())

            info := metadata.(map[string]interface{})

            if _, ok := info["name"]; !ok {
                continue
            }

            bt := bitTorrent{
                InfoHash: hex.EncodeToString(resp.InfoHash),
                Name:     info["name"].(string),
            }

            if v, ok := info["files"]; ok {
                files := v.([]interface{})
                bt.Files = make([]file, len(files))

                for i, item := range files {
                    f := item.(map[string]interface{})
                    bt.Files[i] = file{
                        Path:   f["path"].([]interface{}),
                        Length: f["length"].(int),
                    }
                }
            } else if _, ok := info["length"]; ok {
                bt.Length = info["length"].(int)
            }

            data, err := json.Marshal(bt)
            if err == nil {
                fmt.Printf("%s\n\n", data)
            }
        }
    }()
    go w.Run()

    config := dht.NewCrawlConfig()
    config.OnAnnouncePeer = func(infoHash, ip string, port int) {
        w.Request([]byte(infoHash), ip, port)
    }
    d := dht.New(config)

    d.Run()
}