README.md
1# TransmissionRPC
2
3[![GoDoc](https://godoc.org/github.com/hekmon/transmissionrpc?status.svg)](https://godoc.org/github.com/hekmon/transmissionrpc) [![Go Report Card](https://goreportcard.com/badge/github.com/hekmon/transmissionrpc)](https://goreportcard.com/report/github.com/hekmon/transmissionrpc)
4
5Golang bindings to Transmission (bittorent) RPC interface (Work in Progress).
6
7Even if there is some high level wrappers/helpers, the goal of this lib is to stay close to the original API in terms of methods and payloads while enhancing certain types to be more "golangish": timestamps are converted from/to time.Time, numeric durations in time.Duration, booleans in numeric form are converted to real bool, etc...
8
9Also payload generation aims to be precise: when several values can be added to a payload, only instanciated values will be forwarded (and kept !) to the final payload. This means that the default JSON marshalling (with omitempty) can't always be used and therefor a manual, reflect based, approach is used to build the final payload and accurately send what the user have instanciated, even if a value is at its default type value.
10
11This lib follow the [transmission v15 RPC specification](https://github.com/transmission/transmission/blob/2.9x/extras/rpc-spec.txt#L639).
12
13## Getting started
14
15First the main client object must be instantiated with [New()](https://godoc.org/github.com/hekmon/transmissionrpc#New). In its basic form only host/ip, username and password must be provided. Default will apply for port (`9091`) rpc URI (`/transmission/rpc`) and others values.
16
17```golang
18transmissionbt := transmissionrpc.New("127.0.0.1", "rpcuser", "rpcpass", nil)
19```
20
21But advanced values can also be configured to your liking using [AdvancedConfig](https://godoc.org/github.com/hekmon/transmissionrpc#AdvancedConfig).
22Each value of `AdvancedConfig` with a type default value will be replaced by the lib default value, so you can set only the ones you want:
23
24```golang
25transmissionbt := transmissionrpc.New("bt.mydomain.net", "rpcuser", "rpcpass",
26 &transmissionrpc.AdvancedConfig{
27 HTTPS: true,
28 Port: 443,
29 })
30```
31
32The remote RPC version can be checked against this library before starting to operate:
33
34```golang
35ok, serverVersion, serverMinimumVersion, err := transmission.RPCVersion()
36if err != nil {
37 panic(err)
38}
39if !ok {
40 panic(fmt.Sprintf("Remote transmission RPC version (v%d) is incompatible with the transmission library (v%d): remote needs at least v%d",
41 serverVersion, transmissionrpc.RPCVersion, serverMinimumVersion))
42}
43fmt.Printf("Remote transmission RPC version (v%d) is compatible with our transmissionrpc library (v%d)\n",
44 serverVersion, transmissionrpc.RPCVersion)
45```
46
47## Features
48
49* [Torrent Requests](#torrent-requests)
50 * [Torrent Action Requests](#torrent-action-requests)
51 * [x] torrent-start
52 * [x] torrent-start-now
53 * [x] torrent-stop
54 * [x] torrent-verify
55 * [x] torrent-reannounce
56 * [Torrent Mutators](#torrent-mutators)
57 * [x] torrent-set
58 * [Torrent Accessors](#torrent-accessors)
59 * [x] torrent-get
60 * [Adding a Torrent](#adding-a-torrent)
61 * [x] torrent-add
62 * [Removing a Torrent](#removing-a-torrent)
63 * [x] torrent-remove
64 * [Moving a Torrent](#moving-a-torrent)
65 * [x] torrent-set-location
66 * [Renaming a Torrent path](#renaming-a-torrent-path)
67 * [x] torrent-rename-path
68* [Session Requests](#session-requests)
69 * [Session Arguments](#session-arguments)
70 * [x] session-set
71 * [x] session-get
72 * [Session Statistics](#session-statistics)
73 * [x] session-stats
74 * [Blocklist](#blocklist)
75 * [ ] blocklist-update
76 * [Port Checking](#port-checking)
77 * [x] port-test
78 * [Session Shutdown](#session-shutdown)
79 * [ ] session-close
80 * [Queue Movement Requests](#queue-movement-requests)
81 * [ ] queue-move-top
82 * [ ] queue-move-up
83 * [ ] queue-move-down
84 * [ ] queue-move-bottom
85 * [Free Space](#free-space)
86 * [x] free-space
87
88### Torrent Requests
89
90#### Torrent Action Requests
91
92Each rpc methods here can work with ID list, hash list or `recently-active` magic word. Therefor, there is 3 golang method variants for each of them.
93
94```golang
95transmissionbt.TorrentXXXXIDs(...)
96transmissionbt.TorrentXXXXHashes(...)
97transmissionbt.TorrentXXXXRecentlyActive()
98```
99
100* torrent-start
101
102Check [TorrentStartIDs()](https://godoc.org/github.com/hekmon/transmissionrpc#Client.TorrentStartIDs), [TorrentStartHashes()](https://godoc.org/github.com/hekmon/transmissionrpc#Client.TorrentStartHashes) and [TorrentStartRecentlyActive()](https://godoc.org/github.com/hekmon/transmissionrpc#Client.TorrentStartRecentlyActive).
103
104Ex:
105
106```golang
107err := transmissionbt.TorrentStartIDs([]int64{55})
108if err != nil {
109 fmt.Fprintln(os.Stderr, err)
110} else {
111 fmt.Println("yay")
112}
113```
114
115* torrent-start-now
116
117Check [TorrentStartNowIDs()](https://godoc.org/github.com/hekmon/transmissionrpc#Client.TorrentStartNowIDs), [TorrentStartNowHashes()](https://godoc.org/github.com/hekmon/transmissionrpc#Client.TorrentStartNowHashes) and [TorrentStartNowRecentlyActive()](https://godoc.org/github.com/hekmon/transmissionrpc#Client.TorrentStartNowRecentlyActive).
118
119Ex:
120
121```golang
122err := transmissionbt.TorrentStartNowHashes([]string{"f07e0b0584745b7bcb35e98097488d34e68623d0"})
123if err != nil {
124 fmt.Fprintln(os.Stderr, err)
125} else {
126 fmt.Println("yay")
127}
128```
129
130* torrent-stop
131
132Check [TorrentStopIDs()](https://godoc.org/github.com/hekmon/transmissionrpc#Client.TorrentStopIDs), [TorrentStopHashes()](https://godoc.org/github.com/hekmon/transmissionrpc#Client.TorrentStopHashes) and [TorrentStopRecentlyActive()](https://godoc.org/github.com/hekmon/transmissionrpc#Client.TorrentStopRecentlyActive).
133
134Ex:
135
136```golang
137err := transmissionbt.TorrentStopIDs([]int64{55})
138if err != nil {
139 fmt.Fprintln(os.Stderr, err)
140} else {
141 fmt.Println("yay")
142}
143```
144
145* torrent-verify
146
147Check [TorrentVerifyIDs()](https://godoc.org/github.com/hekmon/transmissionrpc#Client.TorrentVerifyIDs), [TorrentVerifyHashes()](https://godoc.org/github.com/hekmon/transmissionrpc#Client.TorrentVerifyHashes) and [TorrentVerifyRecentlyActive()](https://godoc.org/github.com/hekmon/transmissionrpc#Client.TorrentVerifyRecentlyActive).
148
149Ex:
150
151```golang
152err := transmissionbt.TorrentVerifyHashes([]string{"f07e0b0584745b7bcb35e98097488d34e68623d0"})
153if err != nil {
154 fmt.Fprintln(os.Stderr, err)
155} else {
156 fmt.Println("yay")
157}
158```
159
160* torrent-reannounce
161
162Check [TorrentReannounceIDs()](https://godoc.org/github.com/hekmon/transmissionrpc#Client.TorrentReannounceIDs), [TorrentReannounceHashes()](https://godoc.org/github.com/hekmon/transmissionrpc#Client.TorrentReannounceHashes) and [TorrentReannounceRecentlyActive()](https://godoc.org/github.com/hekmon/transmissionrpc#Client.TorrentReannounceRecentlyActive).
163
164Ex:
165
166```golang
167err := transmissionbt.TorrentReannounceRecentlyActive()
168if err != nil {
169 fmt.Fprintln(os.Stderr, err)
170} else {
171 fmt.Println("yay")
172}
173```
174
175#### Torrent Mutators
176
177* torrent-set
178
179Mapped as [TorrentSet()](https://godoc.org/github.com/hekmon/transmissionrpc#Client.TorrentSet).
180
181Ex: apply a 1 MB/s limit to a torrent.
182
183```golang
184uploadLimited := true
185uploadLimitKBps := int64(1000)
186err := transmissionbt.TorrentSet(&transmissionrpc.TorrentSetPayload{
187 IDs: []int64{55},
188 UploadLimited: &uploadLimited,
189 UploadLimit: &uploadLimitKBps,
190})
191if err != nil {
192 fmt.Fprintln(os.Stderr, err)
193} else {
194 fmt.Println("yay")
195}
196```
197
198There is a lot more [mutators](https://godoc.org/github.com/hekmon/transmissionrpc#TorrentSetPayload) available.
199
200#### Torrent Accessors
201
202* torrent-get
203
204All fields for all torrents with [TorrentGetAll()](https://godoc.org/github.com/hekmon/transmissionrpc#Client.TorrentGetAll):
205
206```golang
207torrents, err := transmissionbt.TorrentGetAll()
208if err != nil {
209 fmt.Fprintln(os.Stderr, err)
210} else {
211 fmt.Println(torrents) // meh it's full of pointers
212}
213```
214
215All fields for a restricted list of ids with [TorrentGetAllFor()](https://godoc.org/github.com/hekmon/transmissionrpc#Client.TorrentGetAll):
216
217```golang
218torrents, err := transmissionbt.TorrentGetAllFor([]int64{31})
219if err != nil {
220 fmt.Fprintln(os.Stderr, err)
221} else {
222 fmt.Println(torrents) // meh it's still full of pointers
223}
224```
225
226Some fields for some torrents with the low level accessor [TorrentGet()](https://godoc.org/github.com/hekmon/transmissionrpc#Client.TorrentGet):
227
228```golang
229torrents, err := transmissionbt.TorrentGet([]string{"status"}, []int64{54, 55})
230if err != nil {
231 fmt.Fprintln(os.Stderr, err)
232} else {
233 for _, torrent := range torrents {
234 fmt.Println(torrent.Status) // the only instanciated field, as requested
235 }
236}
237```
238
239Some fields for all torrents, still with the low level accessor [TorrentGet()](https://godoc.org/github.com/hekmon/transmissionrpc#Client.TorrentGet):
240
241```golang
242torrents, err := transmissionbt.TorrentGet([]string{"id", "name", "hashString"}, nil)
243if err != nil {
244 fmt.Fprintln(os.Stderr, err)
245} else {
246 for _, torrent := range torrents {
247 fmt.Println(torrent.ID)
248 fmt.Println(torrent.Name)
249 fmt.Println(torrent.HashString)
250 }
251}
252```
253
254Valid fields name can be found as JSON tag on the [Torrent](https://godoc.org/github.com/hekmon/transmissionrpc#Torrent) struct.
255
256#### Adding a Torrent
257
258* torrent-add
259
260Adding a torrent from a file (using [TorrentAddFile](https://godoc.org/github.com/hekmon/transmissionrpc#Client.TorrentAddFile) wrapper):
261
262```golang
263filepath := "/home/hekmon/Downloads/ubuntu-17.10.1-desktop-amd64.iso.torrent"
264torrent, err := transmissionbt.TorrentAddFile(filepath)
265if err != nil {
266 fmt.Fprintln(os.Stderr, err)
267} else {
268 // Only 3 fields will be returned/set in the Torrent struct
269 fmt.Println(*torrent.ID)
270 fmt.Println(*torrent.Name)
271 fmt.Println(*torrent.HashString)
272}
273```
274
275Adding a torrent from an URL (ex: a magnet) with the real [TorrentAdd](https://godoc.org/github.com/hekmon/transmissionrpc#Client.TorrentAdd) method:
276
277```golang
278magnet := "magnet:?xt=urn:btih:f07e0b0584745b7bcb35e98097488d34e68623d0&dn=ubuntu-17.10.1-desktop-amd64.iso&tr=http%3A%2F%2Ftorrent.ubuntu.com%3A6969%2Fannounce&tr=http%3A%2F%2Fipv6.torrent.ubuntu.com%3A6969%2Fannounce"
279torrent, err := btserv.TorrentAdd(&transmissionrpc.TorrentAddPayload{
280 Filename: &magnet,
281})
282if err != nil {
283 fmt.Fprintln(os.Stderr, err)
284} else {
285 // Only 3 fields will be returned/set in the Torrent struct
286 fmt.Println(*torrent.ID)
287 fmt.Println(*torrent.Name)
288 fmt.Println(*torrent.HashString)
289}
290```
291
292Which would output:
293
294```raw
29555
296ubuntu-17.10.1-desktop-amd64.iso
297f07e0b0584745b7bcb35e98097488d34e68623d0
298```
299
300#### Removing a Torrent
301
302* torrent-remove
303
304Mapped as [TorrentRemove()](https://godoc.org/github.com/hekmon/transmissionrpc#Client.TorrentRemove).
305
306#### Moving a Torrent
307
308* torrent-set-location
309
310Mapped as [TorrentSetLocation()](https://godoc.org/github.com/hekmon/transmissionrpc#Client.TorrentSetLocation).
311
312#### Renaming a Torrent path
313
314* torrent-rename-path
315
316Mapped as [TorrentRenamePath()](https://godoc.org/github.com/hekmon/transmissionrpc#Client.TorrentRenamePath).
317
318### Session Requests
319
320#### Session Arguments
321
322* session-set
323
324Mapped as [SessionArgumentsSet()](https://godoc.org/github.com/hekmon/transmissionrpc#Client.SessionArgumentsSet).
325
326* session-get
327
328Mapped as [SessionArgumentsGet()](https://godoc.org/github.com/hekmon/transmissionrpc#Client.SessionArgumentsGet).
329
330#### Session Statistics
331
332* session-stats
333
334Mapped as [SessionStats()](https://godoc.org/github.com/hekmon/transmissionrpc#Client.SessionStats).
335
336#### Blocklist
337
338* blocklist-update _(to do)_
339
340#### Port Checking
341
342* port-test
343
344Mapped as [PortTest()](https://godoc.org/github.com/hekmon/transmissionrpc#Client.PortTest).
345
346Ex:
347
348```golang
349 st, err := transmissionbt.PortTest()
350 if err != nil {
351 fmt.Fprintln(os.Stderr, err)
352 }
353 if st {
354 fmt.Println("Open!")
355 }
356```
357
358#### Session Shutdown
359
360* session-close _(to do)_
361
362#### Queue Movement Requests
363
364* queue-move-top _(to do)_
365* queue-move-up _(to do)_
366* queue-move-down _(to do)_
367* queue-move-bottom _(to do)_
368
369#### Free Space
370
371* free-space
372
373Mappped as [FreeSpace()](https://godoc.org/github.com/hekmon/transmissionrpc#Client.FreeSpace).
374
375Ex: Get the space available for /data.
376
377```golang
378 freeSpace, err := transmissionbt.FreeSpace("/data")
379 if err != nil {
380 fmt.Fprintln(os.Stderr, err)
381 } else {
382 fmt.Printd("%s | %d | %v", freeSpace, freeSpace, freeSpace)
383 }
384}
385```
386
387For more information about the freeSpace type, check the [ComputerUnits](https://github.com/hekmon/cunits) library.
388