Skip to content

Commit

Permalink
Merge pull request #9 from mrobinsn/add-progress
Browse files Browse the repository at this point in the history
Add way to get updated status for a specific Torrent
  • Loading branch information
Michael Robinson authored Apr 1, 2019
2 parents 9202379 + 053bb43 commit 12696af
Show file tree
Hide file tree
Showing 2 changed files with 114 additions and 1 deletion.
77 changes: 76 additions & 1 deletion rtorrent/rtorrent.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,15 @@ type Torrent struct {
Ratio float64
}

// Status represents the status of a torrent
type Status struct {
Completed bool
CompletedBytes int
DownRate int
UpRate int
Ratio float64
}

// File represents a file in rTorrent
type File struct {
Path string
Expand Down Expand Up @@ -135,6 +144,21 @@ func (r *RTorrent) DownTotal() (int, error) {
return 0, errors.Errorf("result isn't int: %v", result)
}

// DownRate returns the current download rate reported by this RTorrent instance (bytes/s)
func (r *RTorrent) DownRate() (int, error) {
result, err := r.xmlrpcClient.Call("throttle.global_down.rate")
if err != nil {
return 0, errors.Wrap(err, "throttle.global_down.rate XMLRPC call failed")
}
if totals, ok := result.([]interface{}); ok {
result = totals[0]
}
if total, ok := result.(int); ok {
return total, nil
}
return 0, errors.Errorf("result isn't int: %v", result)
}

// UpTotal returns the total uploaded metric reported by this RTorrent instance (bytes)
func (r *RTorrent) UpTotal() (int, error) {
result, err := r.xmlrpcClient.Call("throttle.global_up.total")
Expand All @@ -150,6 +174,21 @@ func (r *RTorrent) UpTotal() (int, error) {
return 0, errors.Errorf("result isn't int: %v", result)
}

// UpRate returns the current upload rate reported by this RTorrent instance (bytes/s)
func (r *RTorrent) UpRate() (int, error) {
result, err := r.xmlrpcClient.Call("throttle.global_up.rate")
if err != nil {
return 0, errors.Wrap(err, "throttle.global_up.rate XMLRPC call failed")
}
if totals, ok := result.([]interface{}); ok {
result = totals[0]
}
if total, ok := result.(int); ok {
return total, nil
}
return 0, errors.Errorf("result isn't int: %v", result)
}

// GetTorrents returns all of the torrents reported by this RTorrent instance
func (r *RTorrent) GetTorrents(view View) ([]Torrent, error) {
args := []interface{}{"", string(view), "d.name=", "d.size_bytes=", "d.hash=", "d.custom1=", "d.base_path=", "d.is_active=", "d.complete=", "d.ratio="}
Expand All @@ -175,7 +214,7 @@ func (r *RTorrent) GetTorrents(view View) ([]Torrent, error) {
return torrents, nil
}

// Delete removes the torent
// Delete removes the torrent
func (r *RTorrent) Delete(t Torrent) error {
_, err := r.xmlrpcClient.Call("d.erase", t.Hash)
if err != nil {
Expand Down Expand Up @@ -213,3 +252,39 @@ func (r *RTorrent) SetLabel(t Torrent, newLabel string) error {
}
return nil
}

// GetStatus returns the Status for a given Torrent
func (r *RTorrent) GetStatus(t Torrent) (Status, error) {
var s Status
// Completed
results, err := r.xmlrpcClient.Call("d.complete", t.Hash)
if err != nil {
return s, errors.Wrap(err, "d.complete XMLRPC call failed")
}
s.Completed = results.([]interface{})[0].(int) > 0
// CompletedBytes
results, err = r.xmlrpcClient.Call("d.completed_bytes", t.Hash)
if err != nil {
return s, errors.Wrap(err, "d.completed_bytes XMLRPC call failed")
}
s.CompletedBytes = results.([]interface{})[0].(int)
// DownRate
results, err = r.xmlrpcClient.Call("d.down.rate", t.Hash)
if err != nil {
return s, errors.Wrap(err, "d.down.rate XMLRPC call failed")
}
s.DownRate = results.([]interface{})[0].(int)
// UpRate
results, err = r.xmlrpcClient.Call("d.up.rate", t.Hash)
if err != nil {
return s, errors.Wrap(err, "d.up.rate XMLRPC call failed")
}
s.UpRate = results.([]interface{})[0].(int)
// Ratio
results, err = r.xmlrpcClient.Call("d.ratio", t.Hash)
if err != nil {
return s, errors.Wrap(err, "d.ratio XMLRPC call failed")
}
s.Ratio = float64(results.([]interface{})[0].(int)) / float64(1000)
return s, nil
}
38 changes: 38 additions & 0 deletions rtorrent/rtorrent_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,18 @@ func TestRTorrent(t *testing.T) {
require.Zero(t, total, "expected no data to be transferred yet")
})

t.Run("down rate", func(t *testing.T) {
rate, err := client.DownRate()
require.NoError(t, err)
require.Zero(t, rate, "expected no download yet")
})

t.Run("up rate", func(t *testing.T) {
rate, err := client.UpRate()
require.NoError(t, err)
require.Zero(t, rate, "expected no upload yet")
})

t.Run("get no torrents", func(t *testing.T) {
torrents, err := client.GetTorrents(ViewMain)
require.NoError(t, err)
Expand Down Expand Up @@ -111,6 +123,32 @@ func TestRTorrent(t *testing.T) {
require.Equal(t, "TestLabel", torrents[0].Label)
})

t.Run("get status", func(t *testing.T) {
var status Status
var err error
// It may take some time for the download to start
tries := 0
for {
<-time.After(time.Second)
status, err = client.GetStatus(torrents[0])
require.NoError(t, err)
t.Logf("Status = %+v", status)
if status.CompletedBytes > 0 {
break
}
if tries > 10 {
require.NoError(t, errors.Errorf("torrent did not start in time"))
}
tries++
}

require.False(t, status.Completed)
require.NotZero(t, status.CompletedBytes)
require.NotZero(t, status.DownRate)
// require.NotZero(t, status.UpRate)
//require.NotZero(t, status.Ratio)
})

t.Run("delete torrent", func(t *testing.T) {
err := client.Delete(torrents[0])
require.NoError(t, err)
Expand Down

0 comments on commit 12696af

Please sign in to comment.