mirror of
https://github.com/ap-pauloafonso/ratio-spoof.git
synced 2026-04-21 16:41:57 +00:00
quick refactor
This commit is contained in:
parent
8c3dc91ce5
commit
144c8adf3c
8 changed files with 231 additions and 275 deletions
|
|
@ -6,7 +6,7 @@ import (
|
||||||
"net/http"
|
"net/http"
|
||||||
"runtime"
|
"runtime"
|
||||||
|
|
||||||
"github.com/ap-pauloafonso/ratio-spoof/qbittorrent"
|
"github.com/ap-pauloafonso/ratio-spoof/emulation"
|
||||||
"github.com/ap-pauloafonso/ratio-spoof/ratiospoof"
|
"github.com/ap-pauloafonso/ratio-spoof/ratiospoof"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -57,7 +57,7 @@ required arguments:
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
qbit := qbittorrent.NewQbitTorrent()
|
qbit := emulation.NewQbitTorrent()
|
||||||
r, err := ratiospoof.NewRatioSPoofState(
|
r, err := ratiospoof.NewRatioSPoofState(
|
||||||
ratiospoof.InputArgs{
|
ratiospoof.InputArgs{
|
||||||
TorrentPath: *torrentPath,
|
TorrentPath: *torrentPath,
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
package qbittorrent
|
package emulation
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
package qbittorrent
|
package emulation
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"strings"
|
"strings"
|
||||||
124
ratiospoof/printstate.go
Normal file
124
ratiospoof/printstate.go
Normal file
|
|
@ -0,0 +1,124 @@
|
||||||
|
package ratiospoof
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
"os/exec"
|
||||||
|
"runtime"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/olekukonko/ts"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (R *ratioSpoofState) PrintState(exitedCH <-chan string) {
|
||||||
|
exit := false
|
||||||
|
go func() {
|
||||||
|
_ = <-exitedCH
|
||||||
|
exit = true
|
||||||
|
}()
|
||||||
|
|
||||||
|
for {
|
||||||
|
if exit {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
width := terminalSize()
|
||||||
|
clear()
|
||||||
|
if R.announceHistory.Len() > 0 {
|
||||||
|
seedersStr := fmt.Sprint(R.seeders)
|
||||||
|
leechersStr := fmt.Sprint(R.leechers)
|
||||||
|
if R.seeders == 0 {
|
||||||
|
seedersStr = "not informed"
|
||||||
|
}
|
||||||
|
|
||||||
|
if R.leechers == 0 {
|
||||||
|
leechersStr = "not informed"
|
||||||
|
}
|
||||||
|
var retryStr 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(`
|
||||||
|
Torrent: %v
|
||||||
|
Tracker: %v
|
||||||
|
Seeders: %v
|
||||||
|
Leechers:%v
|
||||||
|
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()
|
||||||
|
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()
|
||||||
|
|
||||||
|
}
|
||||||
|
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,
|
||||||
|
humanReadableSize(float64(lastDequeItem.downloaded)),
|
||||||
|
lastDequeItem.percentDownloaded,
|
||||||
|
humanReadableSize(float64(lastDequeItem.left)),
|
||||||
|
humanReadableSize(float64(lastDequeItem.uploaded)),
|
||||||
|
fmtDuration(R.currentAnnounceTimer),
|
||||||
|
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)
|
||||||
|
}
|
||||||
|
time.Sleep(1 * time.Second)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func terminalSize() int {
|
||||||
|
size, _ := ts.GetSize()
|
||||||
|
width := size.Col()
|
||||||
|
if width < 40 {
|
||||||
|
width = 40
|
||||||
|
}
|
||||||
|
return width
|
||||||
|
}
|
||||||
|
func clear() {
|
||||||
|
if runtime.GOOS == "windows" {
|
||||||
|
cmd := exec.Command("cmd", "/c", "cls")
|
||||||
|
cmd.Stdout = os.Stdout
|
||||||
|
cmd.Run()
|
||||||
|
} else {
|
||||||
|
fmt.Print("\033c")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func center(s string, n int, fill string) string {
|
||||||
|
div := n / 2
|
||||||
|
return strings.Repeat(fill, div) + s + strings.Repeat(fill, div)
|
||||||
|
}
|
||||||
|
|
||||||
|
func humanReadableSize(byteSize float64) string {
|
||||||
|
var unitFound string
|
||||||
|
for _, unit := range []string{"B", "KiB", "MiB", "GiB", "TiB"} {
|
||||||
|
if byteSize < 1024.0 {
|
||||||
|
unitFound = unit
|
||||||
|
break
|
||||||
|
}
|
||||||
|
byteSize /= 1024.0
|
||||||
|
}
|
||||||
|
return fmt.Sprintf("%.2f%v", byteSize, unitFound)
|
||||||
|
}
|
||||||
|
|
||||||
|
func fmtDuration(seconds int) string {
|
||||||
|
d := time.Duration(seconds) * time.Second
|
||||||
|
return fmt.Sprintf("%s", d)
|
||||||
|
}
|
||||||
31
ratiospoof/printstate_test.go
Normal file
31
ratiospoof/printstate_test.go
Normal file
|
|
@ -0,0 +1,31 @@
|
||||||
|
package ratiospoof
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestHumanReadableSize(T *testing.T) {
|
||||||
|
data := []struct {
|
||||||
|
in float64
|
||||||
|
out string
|
||||||
|
}{
|
||||||
|
{1536, "1.50KiB"},
|
||||||
|
{379040563, "361.48MiB"},
|
||||||
|
{6291456, "6.00MiB"},
|
||||||
|
{372749107, "355.48MiB"},
|
||||||
|
{10485760, "10.00MiB"},
|
||||||
|
{15728640, "15.00MiB"},
|
||||||
|
{363311923, "346.48MiB"},
|
||||||
|
{16777216, "16.00MiB"},
|
||||||
|
{379040563, "361.48MiB"},
|
||||||
|
}
|
||||||
|
for idx, td := range data {
|
||||||
|
T.Run(fmt.Sprint(idx), func(t *testing.T) {
|
||||||
|
got := humanReadableSize(td.in)
|
||||||
|
if got != td.out {
|
||||||
|
t.Errorf("got %q, want %q", got, td.out)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,141 +0,0 @@
|
||||||
package ratiospoof
|
|
||||||
|
|
||||||
import (
|
|
||||||
"io/ioutil"
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
"github.com/ap-pauloafonso/ratio-spoof/beencode"
|
|
||||||
)
|
|
||||||
|
|
||||||
func assertAreEqual(t *testing.T, got, want interface{}) {
|
|
||||||
t.Helper()
|
|
||||||
if got != want {
|
|
||||||
t.Errorf("\ngot: %v\n want: %v", got, want)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// func TestStrSize2ByteSize(T *testing.T) {
|
|
||||||
// T.Run("100kb", func(t *testing.T) {
|
|
||||||
// got := strSize2ByteSize("100kb", 100)
|
|
||||||
// want := 102400
|
|
||||||
// assertAreEqual(t, got, want)
|
|
||||||
// })
|
|
||||||
// T.Run("1kb", func(t *testing.T) {
|
|
||||||
// got := strSize2ByteSize("1kb", 0)
|
|
||||||
// want := 1024
|
|
||||||
// assertAreEqual(t, got, want)
|
|
||||||
// })
|
|
||||||
|
|
||||||
// T.Run("1mb", func(t *testing.T) {
|
|
||||||
// got := strSize2ByteSize("1mb", 0)
|
|
||||||
// want := 1048576
|
|
||||||
// assertAreEqual(t, got, want)
|
|
||||||
// })
|
|
||||||
// T.Run("1gb", func(t *testing.T) {
|
|
||||||
// got := strSize2ByteSize("1gb", 0)
|
|
||||||
// want := 1073741824
|
|
||||||
// assertAreEqual(t, got, want)
|
|
||||||
// })
|
|
||||||
// T.Run("1.5gb", func(t *testing.T) {
|
|
||||||
// got := strSize2ByteSize("1.5gb", 0)
|
|
||||||
// want := 1610612736
|
|
||||||
// assertAreEqual(t, got, want)
|
|
||||||
// })
|
|
||||||
// T.Run("1tb", func(t *testing.T) {
|
|
||||||
// got := strSize2ByteSize("1tb", 0)
|
|
||||||
// want := 1099511627776
|
|
||||||
// assertAreEqual(t, got, want)
|
|
||||||
// })
|
|
||||||
// T.Run("1b", func(t *testing.T) {
|
|
||||||
// got := strSize2ByteSize("1b", 0)
|
|
||||||
// want := 1
|
|
||||||
// assertAreEqual(t, got, want)
|
|
||||||
// })
|
|
||||||
// T.Run("100%% of 10gb ", func(t *testing.T) {
|
|
||||||
// got := strSize2ByteSize("100%", 10737418240)
|
|
||||||
// want := 10737418240
|
|
||||||
// assertAreEqual(t, got, want)
|
|
||||||
// })
|
|
||||||
// T.Run("55%% of 900mb ", func(t *testing.T) {
|
|
||||||
// got := strSize2ByteSize("55%", 943718400)
|
|
||||||
// want := 519045120
|
|
||||||
// assertAreEqual(t, got, want)
|
|
||||||
// })
|
|
||||||
// T.Run("55%% of 900mb ", func(t *testing.T) {
|
|
||||||
// got := strSize2ByteSize("55%", 943718400)
|
|
||||||
// want := 519045120
|
|
||||||
// assertAreEqual(t, got, want)
|
|
||||||
// })
|
|
||||||
// }
|
|
||||||
|
|
||||||
// func TestHumanReadableSize(T *testing.T) {
|
|
||||||
|
|
||||||
// T.Run("#1", func(t *testing.T) {
|
|
||||||
// got := humanReadableSize(1536, true)
|
|
||||||
// want := "1.50KiB"
|
|
||||||
|
|
||||||
// assertAreEqual(t, got, want)
|
|
||||||
// })
|
|
||||||
// T.Run("#2", func(t *testing.T) {
|
|
||||||
// got := humanReadableSize(379040563, true)
|
|
||||||
// want := "1.50KiB"
|
|
||||||
|
|
||||||
// assertAreEqual(t, got, want)
|
|
||||||
// })
|
|
||||||
// T.Run("#3", func(t *testing.T) {
|
|
||||||
// got := humanReadableSize(6291456, true)
|
|
||||||
// want := "1.50KiB"
|
|
||||||
|
|
||||||
// assertAreEqual(t, got, want)
|
|
||||||
// })
|
|
||||||
// T.Run("#4", func(t *testing.T) {
|
|
||||||
// got := humanReadableSize(372749107, true)
|
|
||||||
// want := "1.50KiB"
|
|
||||||
|
|
||||||
// assertAreEqual(t, got, want)
|
|
||||||
// })
|
|
||||||
// T.Run("#5", func(t *testing.T) {
|
|
||||||
// got := humanReadableSize(10485760, true)
|
|
||||||
// want := "1.50KiB"
|
|
||||||
|
|
||||||
// assertAreEqual(t, got, want)
|
|
||||||
// })
|
|
||||||
// T.Run("#6", func(t *testing.T) {
|
|
||||||
// got := humanReadableSize(15728640, true)
|
|
||||||
// want := "1.50KiB"
|
|
||||||
// assertAreEqual(t, got, want)
|
|
||||||
// })
|
|
||||||
// T.Run("#7", func(t *testing.T) {
|
|
||||||
// got := humanReadableSize(363311923, true)
|
|
||||||
// want := "1.50KiB"
|
|
||||||
// assertAreEqual(t, got, want)
|
|
||||||
// })
|
|
||||||
// T.Run("#8", func(t *testing.T) {
|
|
||||||
// got := humanReadableSize(16777216, true)
|
|
||||||
// want := "1.50KiB"
|
|
||||||
|
|
||||||
// assertAreEqual(t, got, want)
|
|
||||||
// })
|
|
||||||
// T.Run("#9", func(t *testing.T) {
|
|
||||||
// got := humanReadableSize(379040563, true)
|
|
||||||
// want := "1.50KiB"
|
|
||||||
|
|
||||||
// assertAreEqual(t, got, want)
|
|
||||||
// })
|
|
||||||
// }
|
|
||||||
|
|
||||||
func TestClculateNextTotalSizeByte(T *testing.T) {
|
|
||||||
|
|
||||||
got := calculateNextTotalSizeByte(100, 0, 512, 30, 87979879)
|
|
||||||
want := 3074560
|
|
||||||
|
|
||||||
assertAreEqual(T, got, want)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestUrlEncodeInfoHash(T *testing.T) {
|
|
||||||
|
|
||||||
b, _ := ioutil.ReadFile("")
|
|
||||||
got := extractInfoHashURLEncoded(b, beencode.Decode(b))
|
|
||||||
want := "%60N%7d%1f%8b%3a%9bT%d5%fc%ad%d1%27%ab5%02%1c%fb%03%b0"
|
|
||||||
assertAreEqual(T, got, want)
|
|
||||||
}
|
|
||||||
|
|
@ -12,9 +12,7 @@ import (
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/url"
|
"net/url"
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
|
||||||
"os/signal"
|
"os/signal"
|
||||||
"runtime"
|
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
@ -23,7 +21,6 @@ import (
|
||||||
|
|
||||||
"github.com/ap-pauloafonso/ratio-spoof/beencode"
|
"github.com/ap-pauloafonso/ratio-spoof/beencode"
|
||||||
"github.com/gammazero/deque"
|
"github.com/gammazero/deque"
|
||||||
"github.com/olekukonko/ts"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
|
@ -33,7 +30,7 @@ const (
|
||||||
var validInitialSufixes = [...]string{"%", "b", "kb", "mb", "gb", "tb"}
|
var validInitialSufixes = [...]string{"%", "b", "kb", "mb", "gb", "tb"}
|
||||||
var validSpeedSufixes = [...]string{"kbps", "mbps"}
|
var validSpeedSufixes = [...]string{"kbps", "mbps"}
|
||||||
|
|
||||||
type ratioSPoofState struct {
|
type ratioSpoofState struct {
|
||||||
mutex *sync.Mutex
|
mutex *sync.Mutex
|
||||||
httpClient HttpClient
|
httpClient HttpClient
|
||||||
torrentInfo *torrentInfo
|
torrentInfo *torrentInfo
|
||||||
|
|
@ -124,7 +121,7 @@ func (I *InputArgs) parseInput(torrentInfo *torrentInfo) (*inputParsed, error) {
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewRatioSPoofState(input InputArgs, torrentClient TorrentClient, httpclient HttpClient) (*ratioSPoofState, error) {
|
func NewRatioSPoofState(input InputArgs, torrentClient TorrentClient, httpclient HttpClient) (*ratioSpoofState, error) {
|
||||||
|
|
||||||
torrentInfo, err := extractTorrentInfo(input.TorrentPath)
|
torrentInfo, err := extractTorrentInfo(input.TorrentPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
@ -136,7 +133,7 @@ func NewRatioSPoofState(input InputArgs, torrentClient TorrentClient, httpclient
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return &ratioSPoofState{
|
return &ratioSpoofState{
|
||||||
bitTorrentClient: torrentClient,
|
bitTorrentClient: torrentClient,
|
||||||
httpClient: httpclient,
|
httpClient: httpclient,
|
||||||
torrentInfo: torrentInfo,
|
torrentInfo: torrentInfo,
|
||||||
|
|
@ -235,14 +232,14 @@ func (A *announceHistory) pushValueHistory(value announceEntry) {
|
||||||
A.PushBack(value)
|
A.PushBack(value)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (R *ratioSPoofState) gracefullyExit() {
|
func (R *ratioSpoofState) gracefullyExit() {
|
||||||
fmt.Printf("\nGracefully exiting...\n")
|
fmt.Printf("\nGracefully exiting...\n")
|
||||||
R.status = "stopped"
|
R.status = "stopped"
|
||||||
R.numWant = 0
|
R.numWant = 0
|
||||||
R.fireAnnounce(false)
|
R.fireAnnounce(false)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (R *ratioSPoofState) Run() {
|
func (R *ratioSpoofState) Run() {
|
||||||
rand.Seed(time.Now().UnixNano())
|
rand.Seed(time.Now().UnixNano())
|
||||||
sigCh := make(chan os.Signal)
|
sigCh := make(chan os.Signal)
|
||||||
stopPrintCh := make(chan string)
|
stopPrintCh := make(chan string)
|
||||||
|
|
@ -250,7 +247,7 @@ func (R *ratioSPoofState) Run() {
|
||||||
signal.Notify(sigCh, os.Interrupt, syscall.SIGINT, syscall.SIGTERM)
|
signal.Notify(sigCh, os.Interrupt, syscall.SIGINT, syscall.SIGTERM)
|
||||||
R.firstAnnounce()
|
R.firstAnnounce()
|
||||||
go R.decreaseTimer()
|
go R.decreaseTimer()
|
||||||
go R.printState(stopPrintCh)
|
go R.PrintState(stopPrintCh)
|
||||||
go func() {
|
go func() {
|
||||||
for {
|
for {
|
||||||
R.generateNextAnnounce()
|
R.generateNextAnnounce()
|
||||||
|
|
@ -262,13 +259,13 @@ func (R *ratioSPoofState) Run() {
|
||||||
stopPrintCh <- "exit print"
|
stopPrintCh <- "exit print"
|
||||||
R.gracefullyExit()
|
R.gracefullyExit()
|
||||||
}
|
}
|
||||||
func (R *ratioSPoofState) firstAnnounce() {
|
func (R *ratioSpoofState) firstAnnounce() {
|
||||||
println("Trying to connect to the tracker...")
|
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)
|
R.fireAnnounce(false)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (R *ratioSPoofState) updateInterval(resp trackerResponse) {
|
func (R *ratioSpoofState) updateInterval(resp trackerResponse) {
|
||||||
if resp.minInterval > 0 {
|
if resp.minInterval > 0 {
|
||||||
R.announceInterval = resp.minInterval
|
R.announceInterval = resp.minInterval
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -276,15 +273,15 @@ func (R *ratioSPoofState) updateInterval(resp trackerResponse) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (R *ratioSPoofState) updateSeedersAndLeechers(resp trackerResponse) {
|
func (R *ratioSpoofState) updateSeedersAndLeechers(resp trackerResponse) {
|
||||||
R.seeders = resp.seeders
|
R.seeders = resp.seeders
|
||||||
R.leechers = resp.leechers
|
R.leechers = resp.leechers
|
||||||
}
|
}
|
||||||
func (R *ratioSPoofState) addAnnounce(currentDownloaded, currentUploaded, currentLeft int, percentDownloaded float32) {
|
func (R *ratioSpoofState) addAnnounce(currentDownloaded, currentUploaded, currentLeft int, percentDownloaded float32) {
|
||||||
R.announceCount++
|
R.announceCount++
|
||||||
R.announceHistory.pushValueHistory(announceEntry{count: R.announceCount, downloaded: currentDownloaded, uploaded: currentUploaded, left: currentLeft, percentDownloaded: percentDownloaded})
|
R.announceHistory.pushValueHistory(announceEntry{count: R.announceCount, downloaded: currentDownloaded, uploaded: currentUploaded, left: currentLeft, percentDownloaded: percentDownloaded})
|
||||||
}
|
}
|
||||||
func (R *ratioSPoofState) fireAnnounce(retry bool) {
|
func (R *ratioSpoofState) fireAnnounce(retry bool) {
|
||||||
lastAnnounce := R.announceHistory.Back().(announceEntry)
|
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),
|
"{port}", fmt.Sprint(R.input.port),
|
||||||
|
|
@ -331,7 +328,7 @@ func (R *ratioSPoofState) fireAnnounce(retry bool) {
|
||||||
R.updateInterval(*trackerResp)
|
R.updateInterval(*trackerResp)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
func (R *ratioSPoofState) generateNextAnnounce() {
|
func (R *ratioSpoofState) generateNextAnnounce() {
|
||||||
R.changeCurrentTimer(R.announceInterval)
|
R.changeCurrentTimer(R.announceInterval)
|
||||||
lastAnnounce := R.announceHistory.Back().(announceEntry)
|
lastAnnounce := R.announceHistory.Back().(announceEntry)
|
||||||
currentDownloaded := lastAnnounce.downloaded
|
currentDownloaded := lastAnnounce.downloaded
|
||||||
|
|
@ -352,7 +349,7 @@ func (R *ratioSPoofState) generateNextAnnounce() {
|
||||||
|
|
||||||
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() {
|
func (R *ratioSpoofState) decreaseTimer() {
|
||||||
for {
|
for {
|
||||||
time.Sleep(1 * time.Second)
|
time.Sleep(1 * time.Second)
|
||||||
R.mutex.Lock()
|
R.mutex.Lock()
|
||||||
|
|
@ -362,126 +359,14 @@ func (R *ratioSPoofState) decreaseTimer() {
|
||||||
R.mutex.Unlock()
|
R.mutex.Unlock()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
func (R *ratioSPoofState) printState(exitedCH <-chan string) {
|
|
||||||
terminalSize := func() int {
|
|
||||||
size, _ := ts.GetSize()
|
|
||||||
width := size.Col()
|
|
||||||
if width < 40 {
|
|
||||||
width = 40
|
|
||||||
}
|
|
||||||
return width
|
|
||||||
}
|
|
||||||
clear := func() {
|
|
||||||
if runtime.GOOS == "windows" {
|
|
||||||
cmd := exec.Command("cmd", "/c", "cls")
|
|
||||||
cmd.Stdout = os.Stdout
|
|
||||||
cmd.Run()
|
|
||||||
} else {
|
|
||||||
fmt.Print("\033c")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
center := func(s string, n int, fill string) string {
|
func (R *ratioSpoofState) changeCurrentTimer(newAnnounceRate int) {
|
||||||
div := n / 2
|
|
||||||
return strings.Repeat(fill, div) + s + strings.Repeat(fill, div)
|
|
||||||
}
|
|
||||||
|
|
||||||
humanReadableSize := func(byteSize float64) string {
|
|
||||||
var unitFound string
|
|
||||||
for _, unit := range []string{"B", "KiB", "MiB", "GiB", "TiB"} {
|
|
||||||
if byteSize < 1024.0 {
|
|
||||||
unitFound = unit
|
|
||||||
break
|
|
||||||
}
|
|
||||||
byteSize /= 1024.0
|
|
||||||
}
|
|
||||||
return fmt.Sprintf("%.2f%v", byteSize, unitFound)
|
|
||||||
}
|
|
||||||
|
|
||||||
fmtDuration := func(seconds int) string {
|
|
||||||
d := time.Duration(seconds) * time.Second
|
|
||||||
return fmt.Sprintf("%s", d)
|
|
||||||
}
|
|
||||||
|
|
||||||
exit := false
|
|
||||||
|
|
||||||
go func() {
|
|
||||||
_ = <-exitedCH
|
|
||||||
exit = true
|
|
||||||
}()
|
|
||||||
|
|
||||||
for {
|
|
||||||
if exit {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
width := terminalSize()
|
|
||||||
clear()
|
|
||||||
if R.announceHistory.Len() > 0 {
|
|
||||||
seedersStr := fmt.Sprint(R.seeders)
|
|
||||||
leechersStr := fmt.Sprint(R.leechers)
|
|
||||||
if R.seeders == 0 {
|
|
||||||
seedersStr = "not informed"
|
|
||||||
}
|
|
||||||
|
|
||||||
if R.leechers == 0 {
|
|
||||||
leechersStr = "not informed"
|
|
||||||
}
|
|
||||||
var retryStr 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(`
|
|
||||||
Torrent: %v
|
|
||||||
Tracker: %v
|
|
||||||
Seeders: %v
|
|
||||||
Leechers:%v
|
|
||||||
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()
|
|
||||||
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()
|
|
||||||
|
|
||||||
}
|
|
||||||
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,
|
|
||||||
humanReadableSize(float64(lastDequeItem.downloaded)),
|
|
||||||
lastDequeItem.percentDownloaded,
|
|
||||||
humanReadableSize(float64(lastDequeItem.left)),
|
|
||||||
humanReadableSize(float64(lastDequeItem.uploaded)),
|
|
||||||
fmtDuration(R.currentAnnounceTimer),
|
|
||||||
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)
|
|
||||||
}
|
|
||||||
time.Sleep(1 * time.Second)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (R *ratioSPoofState) changeCurrentTimer(newAnnounceRate int) {
|
|
||||||
R.mutex.Lock()
|
R.mutex.Lock()
|
||||||
R.currentAnnounceTimer = newAnnounceRate
|
R.currentAnnounceTimer = newAnnounceRate
|
||||||
R.mutex.Unlock()
|
R.mutex.Unlock()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (R *ratioSPoofState) tryMakeRequest(query string) *trackerResponse {
|
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, "?")
|
completeURL := url + "?" + strings.TrimLeft(query, "?")
|
||||||
R.lastAnounceRequest = completeURL
|
R.lastAnounceRequest = completeURL
|
||||||
57
ratiospoof/ratiospoof_test.go
Normal file
57
ratiospoof/ratiospoof_test.go
Normal file
|
|
@ -0,0 +1,57 @@
|
||||||
|
package ratiospoof
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func assertAreEqual(t *testing.T, got, want interface{}) {
|
||||||
|
t.Helper()
|
||||||
|
if got != want {
|
||||||
|
t.Errorf("\ngot: %v\n want: %v", got, want)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestStrSize2ByteSize(T *testing.T) {
|
||||||
|
|
||||||
|
data := []struct {
|
||||||
|
in string
|
||||||
|
inTotalSize int
|
||||||
|
out int
|
||||||
|
}{
|
||||||
|
{"100kb", 100, 102400},
|
||||||
|
{"1kb", 0, 1024},
|
||||||
|
{"1mb", 0, 1048576},
|
||||||
|
{"1gb", 0, 1073741824},
|
||||||
|
{"1.5gb", 0, 1610612736},
|
||||||
|
{"1tb", 0, 1099511627776},
|
||||||
|
{"1b", 0, 1},
|
||||||
|
{"100%", 10737418240, 10737418240},
|
||||||
|
{"55%", 943718400, 519045120},
|
||||||
|
}
|
||||||
|
|
||||||
|
for idx, td := range data {
|
||||||
|
T.Run(fmt.Sprint(idx), func(t *testing.T) {
|
||||||
|
got := strSize2ByteSize(td.in, td.inTotalSize)
|
||||||
|
if got != td.out {
|
||||||
|
t.Errorf("got %v, want %v", got, td.out)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestClculateNextTotalSizeByte(T *testing.T) {
|
||||||
|
|
||||||
|
got := calculateNextTotalSizeByte(100*1024, 0, 512, 30, 87979879)
|
||||||
|
want := 3075072
|
||||||
|
|
||||||
|
assertAreEqual(T, got, want)
|
||||||
|
}
|
||||||
|
|
||||||
|
// func TestUrlEncodeInfoHash(T *testing.T) {
|
||||||
|
|
||||||
|
// b, _ := ioutil.ReadFile("")
|
||||||
|
// got := extractInfoHashURLEncoded(b, beencode.Decode(b))
|
||||||
|
// want := "%60N%7d%1f%8b%3a%9bT%d5%fc%ad%d1%27%ab5%02%1c%fb%03%b0"
|
||||||
|
// assertAreEqual(T, got, want)
|
||||||
|
// }
|
||||||
Loading…
Reference in a new issue