mirror of
https://github.com/ap-pauloafonso/ratio-spoof.git
synced 2026-01-11 20:10:22 +00:00
initial clean up
This commit is contained in:
parent
fe5c6bde7a
commit
bcd8f91ebb
4 changed files with 159 additions and 161 deletions
|
|
@ -1,17 +1,110 @@
|
|||
package beencode
|
||||
|
||||
import (
|
||||
"crypto/sha1"
|
||||
"net/url"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
const (
|
||||
dictToken = byte('d')
|
||||
numberToken = byte('i')
|
||||
listToken = byte('l')
|
||||
endOfCollectionToken = byte('e')
|
||||
lengthValueStringSeparator = byte(':')
|
||||
dictToken = byte('d')
|
||||
numberToken = byte('i')
|
||||
listToken = byte('l')
|
||||
endOfCollectionToken = byte('e')
|
||||
lengthValueStringSeparatorToken = byte(':')
|
||||
|
||||
torrentInfoKey = "info"
|
||||
torrentNameKey = "name"
|
||||
torrentPieceLengthKey = "piece length"
|
||||
torrentLengthKey = "length"
|
||||
torrentFilesKey = "files"
|
||||
mainAnnounceKey = "announce"
|
||||
announceListKey = "announce-list"
|
||||
torrentDictOffsetsKey = "byte_offsets"
|
||||
)
|
||||
|
||||
// TorrentInfo contains all relevant information extracted from a beencode file
|
||||
type TorrentInfo struct {
|
||||
Name string
|
||||
PieceSize int
|
||||
TotalSize int
|
||||
TrackerInfo *TrackerInfo
|
||||
InfoHashURLEncoded string
|
||||
}
|
||||
|
||||
//TrackerInfo contains http urls from the tracker
|
||||
type TrackerInfo struct {
|
||||
Main string
|
||||
Urls []string
|
||||
}
|
||||
|
||||
type torrentDict struct {
|
||||
resultMap map[string]interface{}
|
||||
}
|
||||
|
||||
//TorrentDictParse decodes the beencoded bytes and builds the torrentInfo file
|
||||
func TorrentDictParse(dat []byte) (*TorrentInfo, error) {
|
||||
dict, _ := mapParse(0, &dat)
|
||||
torrentMap := torrentDict{resultMap: dict}
|
||||
return &TorrentInfo{
|
||||
Name: torrentMap.resultMap[torrentInfoKey].(map[string]interface{})[torrentNameKey].(string),
|
||||
PieceSize: torrentMap.resultMap[torrentInfoKey].(map[string]interface{})[torrentPieceLengthKey].(int),
|
||||
TotalSize: torrentMap.extractTotalSize(),
|
||||
TrackerInfo: torrentMap.extractTrackerInfo(),
|
||||
InfoHashURLEncoded: torrentMap.extractInfoHashURLEncoded(dat),
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (T *torrentDict) extractInfoHashURLEncoded(rawData []byte) string {
|
||||
byteOffsets := T.resultMap[torrentInfoKey].(map[string]interface{})[torrentDictOffsetsKey].([]int)
|
||||
h := sha1.New()
|
||||
h.Write([]byte(rawData[byteOffsets[0]:byteOffsets[1]]))
|
||||
ret := h.Sum(nil)
|
||||
return url.QueryEscape(string(ret))
|
||||
|
||||
}
|
||||
|
||||
func (T *torrentDict) extractTotalSize() int {
|
||||
if value, ok := T.resultMap[torrentInfoKey].(map[string]interface{})[torrentLengthKey]; ok {
|
||||
return value.(int)
|
||||
}
|
||||
var total int
|
||||
|
||||
for _, file := range T.resultMap[torrentInfoKey].(map[string]interface{})[torrentFilesKey].([]interface{}) {
|
||||
total += file.(map[string]interface{})[torrentLengthKey].(int)
|
||||
}
|
||||
return total
|
||||
}
|
||||
|
||||
func (T *torrentDict) extractTrackerInfo() *TrackerInfo {
|
||||
uniqueUrls := make(map[string]int)
|
||||
currentCount := 0
|
||||
if main, ok := T.resultMap[mainAnnounceKey]; ok {
|
||||
if _, found := uniqueUrls[main.(string)]; !found {
|
||||
uniqueUrls[main.(string)] = currentCount
|
||||
currentCount++
|
||||
}
|
||||
}
|
||||
if list, ok := T.resultMap[announceListKey]; ok {
|
||||
for _, innerList := range list.([]interface{}) {
|
||||
for _, item := range innerList.([]interface{}) {
|
||||
if _, found := uniqueUrls[item.(string)]; !found {
|
||||
uniqueUrls[item.(string)] = currentCount
|
||||
currentCount++
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
trackerInfo := TrackerInfo{Urls: make([]string, len(uniqueUrls))}
|
||||
for key, value := range uniqueUrls {
|
||||
trackerInfo.Urls[value] = key
|
||||
}
|
||||
|
||||
trackerInfo.Main = trackerInfo.Urls[0]
|
||||
return &trackerInfo
|
||||
}
|
||||
|
||||
//Decode accepts a byte slice and returns a map with information parsed.(panic if it fails)
|
||||
func Decode(data []byte) map[string]interface{} {
|
||||
result, _ := findParse(0, &data)
|
||||
|
|
@ -76,7 +169,7 @@ func numberParse(startIdx int, data *[]byte) (result int, nextIdx int) {
|
|||
|
||||
func stringParse(startIdx int, data *[]byte) (result string, nextIdx int) {
|
||||
current := startIdx
|
||||
for (*data)[current : current+1][0] != lengthValueStringSeparator {
|
||||
for (*data)[current : current+1][0] != lengthValueStringSeparatorToken {
|
||||
current++
|
||||
}
|
||||
sizeStr, _ := strconv.Atoi(string(((*data)[startIdx:current])))
|
||||
|
|
|
|||
|
|
@ -5,38 +5,7 @@ import (
|
|||
"testing"
|
||||
)
|
||||
|
||||
func TestGenerateRandomPeerId(T *testing.T) {
|
||||
T.Run("PeerIds are different", func(t *testing.T) {
|
||||
keys := make(map[string]bool)
|
||||
for i := 0; i < 10; i++ {
|
||||
obj := NewQbitTorrent()
|
||||
key := obj.PeerID()
|
||||
t.Log(key)
|
||||
if _, ok := keys[key]; ok {
|
||||
t.Error("peerId must be random")
|
||||
break
|
||||
}
|
||||
keys[key] = true
|
||||
}
|
||||
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
func TestGenerateRandomKey(T *testing.T) {
|
||||
T.Run("Keys are different", func(t *testing.T) {
|
||||
keys := make(map[string]bool)
|
||||
for i := 0; i < 10; i++ {
|
||||
obj := NewQbitTorrent()
|
||||
key := obj.Key()
|
||||
t.Log(key)
|
||||
if _, ok := keys[key]; ok {
|
||||
t.Error("Keys must be random")
|
||||
break
|
||||
}
|
||||
keys[key] = true
|
||||
}
|
||||
})
|
||||
T.Run("Key has 8 length", func(t *testing.T) {
|
||||
obj := NewQbitTorrent()
|
||||
key := obj.Key()
|
||||
|
|
|
|||
|
|
@ -38,7 +38,7 @@ func (R *ratioSpoofState) PrintState(exitedCH <-chan string) {
|
|||
if R.retryAttempt > 0 {
|
||||
retryStr = fmt.Sprintf("(*Retry %v - check your connection)", R.retryAttempt)
|
||||
}
|
||||
fmt.Println(center(" RATIO-SPOOF ", width-len(" RATIO-SPOOF "), "#"))
|
||||
fmt.Printf("%s\n", center(" RATIO-SPOOF ", width-len(" RATIO-SPOOF "), "#"))
|
||||
fmt.Printf(`
|
||||
Torrent: %v
|
||||
Tracker: %v
|
||||
|
|
@ -47,20 +47,15 @@ func (R *ratioSpoofState) PrintState(exitedCH <-chan string) {
|
|||
Download Speed: %v/s
|
||||
Upload Speed: %v/s
|
||||
Size: %v
|
||||
Emulation: %v | Port: %v`, R.torrentInfo.name, R.torrentInfo.trackerInfo.main, seedersStr, leechersStr, humanReadableSize(float64(R.input.downloadSpeed)),
|
||||
humanReadableSize(float64(R.input.uploadSpeed)), humanReadableSize(float64(R.torrentInfo.totalSize)), R.bitTorrentClient.Name(), R.input.port)
|
||||
fmt.Println()
|
||||
fmt.Println()
|
||||
fmt.Println(center(" GITHUB.COM/AP-PAULOAFONSO/RATIO-SPOOF ", width-len(" GITHUB.COM/AP-PAULOAFONSO/RATIO-SPOOF "), "#"))
|
||||
fmt.Println()
|
||||
Emulation: %v | Port: %v`, R.torrentInfo.Name, R.torrentInfo.TrackerInfo.Main, seedersStr, leechersStr, humanReadableSize(float64(R.input.downloadSpeed)),
|
||||
humanReadableSize(float64(R.input.uploadSpeed)), humanReadableSize(float64(R.torrentInfo.TotalSize)), R.bitTorrentClient.Name(), R.input.port)
|
||||
fmt.Printf("\n\n%s\n\n", center(" GITHUB.COM/AP-PAULOAFONSO/RATIO-SPOOF ", width-len(" GITHUB.COM/AP-PAULOAFONSO/RATIO-SPOOF "), "#"))
|
||||
for i := 0; i <= R.announceHistory.Len()-2; i++ {
|
||||
dequeItem := R.announceHistory.At(i).(announceEntry)
|
||||
fmt.Printf("#%v downloaded: %v(%.2f%%) | left: %v | uploaded: %v | announced", dequeItem.count, humanReadableSize(float64(dequeItem.downloaded)), dequeItem.percentDownloaded, humanReadableSize(float64(dequeItem.left)), humanReadableSize(float64(dequeItem.uploaded)))
|
||||
fmt.Println()
|
||||
|
||||
fmt.Printf("#%v downloaded: %v(%.2f%%) | left: %v | uploaded: %v | announced\n", dequeItem.count, humanReadableSize(float64(dequeItem.downloaded)), dequeItem.percentDownloaded, humanReadableSize(float64(dequeItem.left)), humanReadableSize(float64(dequeItem.uploaded)))
|
||||
}
|
||||
lastDequeItem := R.announceHistory.At(R.announceHistory.Len() - 1).(announceEntry)
|
||||
fmt.Printf("#%v downloaded: %v(%.2f%%) | left: %v | uploaded: %v | next announce in: %v %v", lastDequeItem.count,
|
||||
fmt.Printf("#%v downloaded: %v(%.2f%%) | left: %v | uploaded: %v | next announce in: %v %v\n", lastDequeItem.count,
|
||||
humanReadableSize(float64(lastDequeItem.downloaded)),
|
||||
lastDequeItem.percentDownloaded,
|
||||
humanReadableSize(float64(lastDequeItem.left)),
|
||||
|
|
@ -69,14 +64,8 @@ func (R *ratioSpoofState) PrintState(exitedCH <-chan string) {
|
|||
retryStr)
|
||||
|
||||
if R.input.debug {
|
||||
fmt.Println()
|
||||
fmt.Println()
|
||||
fmt.Println(center(" DEBUG ", width-len(" DEBUG "), "#"))
|
||||
fmt.Println()
|
||||
fmt.Print(R.lastAnounceRequest)
|
||||
fmt.Println()
|
||||
fmt.Println()
|
||||
fmt.Print(R.lastTackerResponse)
|
||||
fmt.Printf("\n%s\n", center(" DEBUG ", width-len(" DEBUG "), "#"))
|
||||
fmt.Printf("\n%s\n\n%s", R.lastAnounceRequest, R.lastTackerResponse)
|
||||
}
|
||||
time.Sleep(1 * time.Second)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,14 +3,12 @@ package ratiospoof
|
|||
import (
|
||||
"bytes"
|
||||
"compress/gzip"
|
||||
"crypto/sha1"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"math"
|
||||
"math/rand"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"os"
|
||||
"os/signal"
|
||||
"strconv"
|
||||
|
|
@ -33,8 +31,9 @@ var validSpeedSufixes = [...]string{"kbps", "mbps"}
|
|||
type ratioSpoofState struct {
|
||||
mutex *sync.Mutex
|
||||
httpClient HttpClient
|
||||
torrentInfo *torrentInfo
|
||||
torrentInfo *beencode.TorrentInfo
|
||||
input *inputParsed
|
||||
trackerState *httpTracker
|
||||
bitTorrentClient TorrentClientEmulation
|
||||
currentAnnounceTimer int
|
||||
announceInterval int
|
||||
|
|
@ -48,6 +47,30 @@ type ratioSpoofState struct {
|
|||
lastTackerResponse string
|
||||
retryAttempt int
|
||||
}
|
||||
type httpTracker struct {
|
||||
urls []string
|
||||
}
|
||||
|
||||
func newHttpTracker(torrentInfo *beencode.TorrentInfo) (*httpTracker, error) {
|
||||
|
||||
var result []string
|
||||
for _, url := range torrentInfo.TrackerInfo.Urls {
|
||||
if strings.HasPrefix(url, "http") {
|
||||
result = append(result, url)
|
||||
}
|
||||
}
|
||||
if len(result) == 0 {
|
||||
return nil, errors.New("No tcp/http tracker url announce found")
|
||||
}
|
||||
return &httpTracker{urls: torrentInfo.TrackerInfo.Urls}, nil
|
||||
}
|
||||
|
||||
func (T *httpTracker) SwapFirst(currentIdx int) {
|
||||
aux := T.urls[0]
|
||||
T.urls[0] = T.urls[currentIdx]
|
||||
T.urls[currentIdx] = aux
|
||||
}
|
||||
|
||||
type InputArgs struct {
|
||||
TorrentPath string
|
||||
InitialDownloaded string
|
||||
|
|
@ -68,34 +91,12 @@ type inputParsed struct {
|
|||
debug bool
|
||||
}
|
||||
|
||||
type torrentInfo struct {
|
||||
name string
|
||||
pieceSize int
|
||||
totalSize int
|
||||
trackerInfo trackerInfo
|
||||
infoHashURLEncoded string
|
||||
}
|
||||
|
||||
func extractTorrentInfo(torrentPath string) (*torrentInfo, error) {
|
||||
dat, err := ioutil.ReadFile(torrentPath)
|
||||
func (I *InputArgs) parseInput(torrentInfo *beencode.TorrentInfo) (*inputParsed, error) {
|
||||
downloaded, err := extractInputInitialByteCount(I.InitialDownloaded, torrentInfo.TotalSize, true)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
torrentMap := beencode.Decode(dat)
|
||||
return &torrentInfo{
|
||||
name: torrentMap["info"].(map[string]interface{})["name"].(string),
|
||||
pieceSize: torrentMap["info"].(map[string]interface{})["piece length"].(int),
|
||||
totalSize: extractTotalSize(torrentMap),
|
||||
trackerInfo: extractTrackerInfo(torrentMap),
|
||||
infoHashURLEncoded: extractInfoHashURLEncoded(dat, torrentMap),
|
||||
}, nil
|
||||
}
|
||||
func (I *InputArgs) parseInput(torrentInfo *torrentInfo) (*inputParsed, error) {
|
||||
downloaded, err := extractInputInitialByteCount(I.InitialDownloaded, torrentInfo.totalSize, true)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
uploaded, err := extractInputInitialByteCount(I.InitialUploaded, torrentInfo.totalSize, false)
|
||||
uploaded, err := extractInputInitialByteCount(I.InitialUploaded, torrentInfo.TotalSize, false)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
@ -123,7 +124,17 @@ func (I *InputArgs) parseInput(torrentInfo *torrentInfo) (*inputParsed, error) {
|
|||
|
||||
func NewRatioSPoofState(input InputArgs, torrentClient TorrentClientEmulation, httpclient HttpClient) (*ratioSpoofState, error) {
|
||||
|
||||
torrentInfo, err := extractTorrentInfo(input.TorrentPath)
|
||||
dat, err := ioutil.ReadFile(input.TorrentPath)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
torrentInfo, err := beencode.TorrentDictParse(dat)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
httpTracker, err := newHttpTracker(torrentInfo)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
|
@ -137,6 +148,7 @@ func NewRatioSPoofState(input InputArgs, torrentClient TorrentClientEmulation, h
|
|||
bitTorrentClient: torrentClient,
|
||||
httpClient: httpclient,
|
||||
torrentInfo: torrentInfo,
|
||||
trackerState: httpTracker,
|
||||
input: inputParsed,
|
||||
numWant: 200,
|
||||
status: "started",
|
||||
|
|
@ -183,17 +195,6 @@ func extractInputByteSpeed(initialSpeedInput string) (int, error) {
|
|||
return ret, nil
|
||||
}
|
||||
|
||||
type trackerInfo struct {
|
||||
main string
|
||||
urls []string
|
||||
}
|
||||
|
||||
func (T *trackerInfo) SwapFirst(currentIdx int) {
|
||||
aux := T.urls[0]
|
||||
T.urls[0] = T.urls[currentIdx]
|
||||
T.urls[currentIdx] = aux
|
||||
}
|
||||
|
||||
type trackerResponse struct {
|
||||
minInterval int
|
||||
interval int
|
||||
|
|
@ -261,7 +262,7 @@ func (R *ratioSpoofState) Run() {
|
|||
}
|
||||
func (R *ratioSpoofState) firstAnnounce() {
|
||||
println("Trying to connect to the tracker...")
|
||||
R.addAnnounce(R.input.initialDownloaded, R.input.initialUploaded, calculateBytesLeft(R.input.initialDownloaded, R.torrentInfo.totalSize), (float32(R.input.initialDownloaded)/float32(R.torrentInfo.totalSize))*100)
|
||||
R.addAnnounce(R.input.initialDownloaded, R.input.initialUploaded, calculateBytesLeft(R.input.initialDownloaded, R.torrentInfo.TotalSize), (float32(R.input.initialDownloaded)/float32(R.torrentInfo.TotalSize))*100)
|
||||
R.fireAnnounce(false)
|
||||
}
|
||||
|
||||
|
|
@ -283,7 +284,7 @@ func (R *ratioSpoofState) addAnnounce(currentDownloaded, currentUploaded, curren
|
|||
}
|
||||
func (R *ratioSpoofState) fireAnnounce(retry bool) {
|
||||
lastAnnounce := R.announceHistory.Back().(announceEntry)
|
||||
replacer := strings.NewReplacer("{infohash}", R.torrentInfo.infoHashURLEncoded,
|
||||
replacer := strings.NewReplacer("{infohash}", R.torrentInfo.InfoHashURLEncoded,
|
||||
"{port}", fmt.Sprint(R.input.port),
|
||||
"{peerid}", R.bitTorrentClient.PeerID(),
|
||||
"{uploaded}", fmt.Sprint(lastAnnounce.uploaded),
|
||||
|
|
@ -334,20 +335,20 @@ func (R *ratioSpoofState) generateNextAnnounce() {
|
|||
currentDownloaded := lastAnnounce.downloaded
|
||||
var downloadCandidate int
|
||||
|
||||
if currentDownloaded < R.torrentInfo.totalSize {
|
||||
downloadCandidate = calculateNextTotalSizeByte(R.input.downloadSpeed, currentDownloaded, R.torrentInfo.pieceSize, R.currentAnnounceTimer, R.torrentInfo.totalSize)
|
||||
if currentDownloaded < R.torrentInfo.TotalSize {
|
||||
downloadCandidate = calculateNextTotalSizeByte(R.input.downloadSpeed, currentDownloaded, R.torrentInfo.PieceSize, R.currentAnnounceTimer, R.torrentInfo.TotalSize)
|
||||
} else {
|
||||
downloadCandidate = R.torrentInfo.totalSize
|
||||
downloadCandidate = R.torrentInfo.TotalSize
|
||||
}
|
||||
|
||||
currentUploaded := lastAnnounce.uploaded
|
||||
uploadCandidate := calculateNextTotalSizeByte(R.input.uploadSpeed, currentUploaded, R.torrentInfo.pieceSize, R.currentAnnounceTimer, 0)
|
||||
uploadCandidate := calculateNextTotalSizeByte(R.input.uploadSpeed, currentUploaded, R.torrentInfo.PieceSize, R.currentAnnounceTimer, 0)
|
||||
|
||||
leftCandidate := calculateBytesLeft(downloadCandidate, R.torrentInfo.totalSize)
|
||||
leftCandidate := calculateBytesLeft(downloadCandidate, R.torrentInfo.TotalSize)
|
||||
|
||||
d, u, l := R.bitTorrentClient.NextAmountReport(downloadCandidate, uploadCandidate, leftCandidate, R.torrentInfo.pieceSize)
|
||||
d, u, l := R.bitTorrentClient.NextAmountReport(downloadCandidate, uploadCandidate, leftCandidate, R.torrentInfo.PieceSize)
|
||||
|
||||
R.addAnnounce(d, u, l, (float32(d)/float32(R.torrentInfo.totalSize))*100)
|
||||
R.addAnnounce(d, u, l, (float32(d)/float32(R.torrentInfo.TotalSize))*100)
|
||||
}
|
||||
func (R *ratioSpoofState) decreaseTimer() {
|
||||
for {
|
||||
|
|
@ -367,7 +368,7 @@ func (R *ratioSpoofState) changeCurrentTimer(newAnnounceRate int) {
|
|||
}
|
||||
|
||||
func (R *ratioSpoofState) tryMakeRequest(query string) *trackerResponse {
|
||||
for idx, url := range R.torrentInfo.trackerInfo.urls {
|
||||
for idx, url := range R.torrentInfo.TrackerInfo.Urls {
|
||||
completeURL := url + "?" + strings.TrimLeft(query, "?")
|
||||
R.lastAnounceRequest = completeURL
|
||||
req, _ := http.NewRequest("GET", completeURL, nil)
|
||||
|
|
@ -390,7 +391,7 @@ func (R *ratioSpoofState) tryMakeRequest(query string) *trackerResponse {
|
|||
R.lastTackerResponse = string(bytesR)
|
||||
decodedResp := beencode.Decode(bytesR)
|
||||
if idx != 0 {
|
||||
R.torrentInfo.trackerInfo.SwapFirst(idx)
|
||||
R.trackerState.SwapFirst(idx)
|
||||
}
|
||||
ret := extractTrackerResponse(decodedResp)
|
||||
return &ret
|
||||
|
|
@ -416,60 +417,6 @@ func calculateNextTotalSizeByte(speedBytePerSecond, currentByte, pieceSizeByte,
|
|||
return totalCandidate
|
||||
}
|
||||
|
||||
func extractInfoHashURLEncoded(rawData []byte, torrentData map[string]interface{}) string {
|
||||
byteOffsets := torrentData["info"].(map[string]interface{})["byte_offsets"].([]int)
|
||||
h := sha1.New()
|
||||
h.Write([]byte(rawData[byteOffsets[0]:byteOffsets[1]]))
|
||||
ret := h.Sum(nil)
|
||||
return url.QueryEscape(string(ret))
|
||||
|
||||
}
|
||||
func extractTotalSize(torrentData map[string]interface{}) int {
|
||||
if value, ok := torrentData["info"].(map[string]interface{})["length"]; ok {
|
||||
return value.(int)
|
||||
}
|
||||
|
||||
var total int
|
||||
|
||||
for _, file := range torrentData["info"].(map[string]interface{})["files"].([]interface{}) {
|
||||
total += file.(map[string]interface{})["length"].(int)
|
||||
}
|
||||
return total
|
||||
}
|
||||
|
||||
func extractTrackerInfo(torrentData map[string]interface{}) trackerInfo {
|
||||
uniqueUrls := make(map[string]int)
|
||||
currentCount := 0
|
||||
if main, ok := torrentData["announce"]; ok && strings.HasPrefix(main.(string), "http") {
|
||||
if _, found := uniqueUrls[main.(string)]; !found {
|
||||
uniqueUrls[main.(string)] = currentCount
|
||||
currentCount++
|
||||
}
|
||||
}
|
||||
if list, ok := torrentData["announce-list"]; ok {
|
||||
for _, innerList := range list.([]interface{}) {
|
||||
for _, item := range innerList.([]interface{}) {
|
||||
if _, found := uniqueUrls[item.(string)]; !found && strings.HasPrefix(item.(string), "http") {
|
||||
uniqueUrls[item.(string)] = currentCount
|
||||
currentCount++
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
trackerInfo := trackerInfo{urls: make([]string, len(uniqueUrls))}
|
||||
for key, value := range uniqueUrls {
|
||||
trackerInfo.urls[value] = key
|
||||
}
|
||||
|
||||
trackerInfo.main = trackerInfo.urls[0]
|
||||
|
||||
if len(trackerInfo.urls) == 0 {
|
||||
panic("No tcp/http tracker url announce found'")
|
||||
}
|
||||
return trackerInfo
|
||||
}
|
||||
|
||||
func extractTrackerResponse(datatrackerResponse map[string]interface{}) trackerResponse {
|
||||
var result trackerResponse
|
||||
if v, ok := datatrackerResponse["failure reason"].(string); ok && len(v) > 0 {
|
||||
|
|
|
|||
Loading…
Reference in a new issue