From 9244d60abe0c6ea509735936da71af3df73959d5 Mon Sep 17 00:00:00 2001 From: Chris Cummer Date: Tue, 25 Jun 2019 23:04:12 -0700 Subject: [PATCH] Add a rudimentary Transmission module (https://transmissionbt.com) --- go.mod | 3 + go.sum | 6 ++ maker/widget_maker.go | 4 + modules/hibp/widget.go | 6 +- modules/transmission/keyboard.go | 10 +++ modules/transmission/widget.go | 123 +++++++++++++++++++++++++++++++ 6 files changed, 149 insertions(+), 3 deletions(-) create mode 100644 modules/transmission/keyboard.go diff --git a/go.mod b/go.mod index 9ae21c1f..7fb0caf2 100644 --- a/go.mod +++ b/go.mod @@ -39,7 +39,10 @@ require ( github.com/google/pprof v0.0.0-20190515194954-54271f7e092f // indirect github.com/gorilla/mux v1.7.1 // indirect github.com/grpc-ecosystem/grpc-gateway v1.9.0 // indirect + github.com/hashicorp/go-cleanhttp v0.5.1 // indirect github.com/hashicorp/golang-lru v0.5.1 // indirect + github.com/hekmon/cunits v2.0.1+incompatible // indirect + github.com/hekmon/transmissionrpc v0.0.0-20190525133028-1d589625bacd github.com/jessevdk/go-flags v1.4.0 github.com/kisielk/errcheck v1.2.0 // indirect github.com/kisielk/gotool v1.0.0 // indirect diff --git a/go.sum b/go.sum index 35f0a27a..6d2cd83e 100644 --- a/go.sum +++ b/go.sum @@ -122,9 +122,15 @@ github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2z github.com/gorilla/mux v1.7.1/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= github.com/grpc-ecosystem/grpc-gateway v1.5.0/go.mod h1:RSKVYQBd5MCa4OVpNdGskqpgL2+G+NZTnrVHpWWfpdw= github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= +github.com/hashicorp/go-cleanhttp v0.5.1 h1:dH3aiDG9Jvb5r5+bYHsikaOUIpcM0xvgMXVoDkXMzJM= +github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.1 h1:0hERBMJE1eitiLkihrMvRVBYAkpHzc/J3QdDN+dAcgU= github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= +github.com/hekmon/cunits v2.0.1+incompatible h1:yy/Wq5YvNtrweqfeRjvrvMdBMH6axBrlL8t7arLlm5A= +github.com/hekmon/cunits v2.0.1+incompatible/go.mod h1:0QdfIGGkucx1VgStMNiHOYn84t/Ru65b+D3z1QszVPc= +github.com/hekmon/transmissionrpc v0.0.0-20190525133028-1d589625bacd h1:bZZYKxyrUV8EsKB5AjsPsJiWE7n0FDURijlSzYZVqAM= +github.com/hekmon/transmissionrpc v0.0.0-20190525133028-1d589625bacd/go.mod h1:b1R6hlzo+gEUNWGh53mw9mPWyYyODdZu/qlVqT+W+PU= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/jessevdk/go-flags v1.4.0 h1:4IU2WS7AumrZ/40jfhf4QVDMsQwqA7VEHozFRrGARJA= github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= diff --git a/maker/widget_maker.go b/maker/widget_maker.go index d02a970a..4d3a2791 100644 --- a/maker/widget_maker.go +++ b/maker/widget_maker.go @@ -41,6 +41,7 @@ import ( "github.com/wtfutil/wtf/modules/textfile" "github.com/wtfutil/wtf/modules/todo" "github.com/wtfutil/wtf/modules/todoist" + "github.com/wtfutil/wtf/modules/transmission" "github.com/wtfutil/wtf/modules/travisci" "github.com/wtfutil/wtf/modules/trello" "github.com/wtfutil/wtf/modules/twitter" @@ -181,6 +182,9 @@ func MakeWidget( case "todoist": settings := todoist.NewSettingsFromYAML(widgetName, moduleConfig, globalConfig) widget = todoist.NewWidget(app, pages, settings) + case "transmission": + settings := transmission.NewSettingsFromYAML(widgetName, moduleConfig, globalConfig) + widget = transmission.NewWidget(app, pages, settings) case "travisci": settings := travisci.NewSettingsFromYAML(widgetName, moduleConfig, globalConfig) widget = travisci.NewWidget(app, pages, settings) diff --git a/modules/hibp/widget.go b/modules/hibp/widget.go index c623ace0..c33a390c 100644 --- a/modules/hibp/widget.go +++ b/modules/hibp/widget.go @@ -17,18 +17,18 @@ type Widget struct { // NewWidget creates a new instance of a widget func NewWidget(app *tview.Application, settings *Settings) *Widget { - widget := Widget{ + widget := &Widget{ TextWidget: wtf.NewTextWidget(app, settings.common, false), settings: settings, } - return &widget + return widget } /* -------------------- Exported Functions -------------------- */ -// Fetch rettrieves HIBP data from the HIBP API +// Fetch retrieves HIBP data from the HIBP API func (widget *Widget) Fetch(accounts []string) ([]*Status, error) { data := []*Status{} diff --git a/modules/transmission/keyboard.go b/modules/transmission/keyboard.go new file mode 100644 index 00000000..d6009aab --- /dev/null +++ b/modules/transmission/keyboard.go @@ -0,0 +1,10 @@ +package transmission + +// import "github.com/gdamore/tcell" + +func (widget *Widget) initializeKeyboardControls() { + widget.SetKeyboardChar("/", widget.ShowHelp, "Show/hide this help prompt") + widget.SetKeyboardChar("m", nil, "Add new magnet torrent") + widget.SetKeyboardChar("p", nil, "Pause torrent") + widget.SetKeyboardChar("r", nil, "Remove torrent from list") +} diff --git a/modules/transmission/widget.go b/modules/transmission/widget.go index dc9c0ba8..16e2732b 100644 --- a/modules/transmission/widget.go +++ b/modules/transmission/widget.go @@ -1 +1,124 @@ package transmission + +import ( + "fmt" + "strings" + + "github.com/hekmon/transmissionrpc" + "github.com/rivo/tview" + "github.com/wtfutil/wtf/wtf" +) + +// Widget is the container for transmission data +type Widget struct { + wtf.KeyboardWidget + wtf.TextWidget + + settings *Settings +} + +// NewWidget creates a new instance of a widget +func NewWidget(app *tview.Application, pages *tview.Pages, settings *Settings) *Widget { + widget := &Widget{ + KeyboardWidget: wtf.NewKeyboardWidget(app, pages, settings.common), + TextWidget: wtf.NewTextWidget(app, settings.common, true), + + settings: settings, + } + + widget.initializeKeyboardControls() + widget.View.SetInputCapture(widget.InputCapture) + widget.KeyboardWidget.SetView(widget.View) + + return widget +} + +/* -------------------- Exported Functions -------------------- */ + +// Fetch retrieves torrent data from the Transmission daemon +func (widget *Widget) Fetch() ([]*transmissionrpc.Torrent, error) { + transmissionbt, err := transmissionrpc.New(widget.settings.host, widget.settings.username, widget.settings.password, nil) + if err != nil { + return nil, err + } + + torrents, err := transmissionbt.TorrentGetAll() + if err != nil { + return nil, err + } + + return torrents, nil +} + +// Refresh updates the data for this widget and displays it onscreen +func (widget *Widget) Refresh() { + torrents, err := widget.Fetch() + + var content string + if err != nil { + content = err.Error() + } else { + content = widget.contentFrom(torrents) + } + + widget.Redraw(widget.CommonSettings.Title, content, false) +} + +// HelpText returns the help text for this widget +func (widget *Widget) HelpText() string { + return widget.KeyboardWidget.HelpText() +} + +/* -------------------- Unexported Functions -------------------- */ + +func (widget *Widget) contentFrom(data []*transmissionrpc.Torrent) string { + str := "" + + for _, torrent := range data { + str += fmt.Sprintf( + " %s %s%s[white]\n", + widget.torrentPercentDone(torrent), + widget.torrentState(torrent), + widget.prettyTorrentName(*torrent.Name), + ) + } + + return str +} + +func (widget *Widget) prettyTorrentName(name string) string { + str := strings.Replace(name, "[", "(", -1) + str = strings.Replace(str, "]", ")", -1) + + return str +} + +func (widget *Widget) torrentPercentDone(torrent *transmissionrpc.Torrent) string { + pctDone := *torrent.PercentDone + str := fmt.Sprintf("%3d", int(pctDone*100)) + + if pctDone == 0.0 { + str = "[gray::b]" + str + } else if pctDone == 1.0 { + str = "[green::b]" + str + } else { + str = "[lightblue::b]" + str + } + + return str + "[white]" +} + +func (widget *Widget) torrentState(torrent *transmissionrpc.Torrent) string { + str := "" + + switch *torrent.Status { + case transmissionrpc.TorrentStatusStopped: + str += "[gray]" + case transmissionrpc.TorrentStatusDownload: + str += "[lightblue]" + case transmissionrpc.TorrentStatusSeed: + str += "[green]" + } + + return str +}