rtapi is a small Go client for rTorrent's XML-RPC interface over SCGI. It is
the library used by rtelegram.
- Go 1.26 or newer.
- rTorrent built with XML-RPC support.
- A local SCGI endpoint such as a protected Unix socket or
scgi_port = 127.0.0.1:5000.
The rTorrent RPC endpoint has no authentication and exposes powerful methods. Prefer a permission-protected Unix socket. Never expose SCGI directly to an untrusted network; see rTorrent's official XML-RPC security guidance.
go get github.com/pyed/rtapi@latestpackage main
import (
"fmt"
"log"
"github.com/pyed/rtapi"
)
func main() {
rt, err := rtapi.NewRtorrent("/run/user/1000/rtorrent.sock")
if err != nil {
log.Fatal(err)
}
torrents, err := rt.Torrents()
if err != nil {
log.Fatal(err)
}
for _, torrent := range torrents {
fmt.Printf("%s: %d/%d bytes\n", torrent.Name, torrent.Completed, torrent.Size)
}
}TCP addresses such as 127.0.0.1:5000 are also accepted, as are http:// and
https:// XML-RPC URLs for rTorrent behind a web server, such as
https://user:password@seedbox.example/RPC2. Credentials in the URL are sent
with HTTP basic authentication and kept out of error messages; requests use
Rtorrent.HTTPClient when it is set, as for a proxy or a certificate
authority of one's own, and http.DefaultClient, which honors HTTPS_PROXY,
otherwise. Basic authentication over plain http:// sends the password
readably; use https:// beyond the local machine.
NewRtorrent asks rTorrent for its version, so it fails while rTorrent is
down. NewClient asks nothing, for programs that may start before rTorrent;
GetVersion asks for the version later. An address that is neither a URL nor
host:port is a socket path, whether or not the socket exists yet.
Every method has a ...Context variant, such as TorrentsContext, and
NewRtorrentContext. Cancelling the context interrupts the request.
Cancellations and timeouts match context.Canceled and
context.DeadlineExceeded with errors.Is. Every SCGI request is
bounded by rtapi.DefaultTimeout (30 seconds) unless Rtorrent.Timeout is set.
Responses default to a 16 MiB safety bound; set Rtorrent.MaxResponseSize when
a legitimately large library needs more. Transport errors, malformed responses,
and XML-RPC faults are returned to the caller; errors.As can inspect an
*rtapi.XMLRPCFault.
- Transfer fields (
Size,Completed, andUpTotal) contain exact byte counts. Path(d.base_path) is empty until rTorrent opens a torrent.DirectoryandMultiFileare always reported:Directoryis the data directory of a multi-file torrent, or the directory containing a single-file torrent's file.SpeedsWithErrorreturns the current transfer rates.DownloadRawloads torrent bytes directly, avoiding credential-bearing intermediary URLs.DownloadWithOptionsremains available for URL loading. SetDotTorrentWithOptions.Stoppedto load a torrent without starting it. An emptyDirorLabelleaves rTorrent's default. rTorrent parses them as command arguments and runs one that starts with$as a command, so loads refuse such values, and those with control characters or invalid UTF-8, withErrCommandArgument. URL loads use rTorrent's verbose load commands, so rTorrent logs why a link failed to load.Torrentsmakes two requests: one for every torrent's details and one, with a call per torrent, for their trackers. For large libraries,ListwithListOptions{}skips the trackers, andTrackersfills them in later for the torrents that need them.Hasheslists only info-hashes, the cheapest way to see which torrents are loaded, andTransferslists how much of each torrent's data has been uploaded and downloaded. Those counts leave out the protocol messages exchanged with peers, which rTorrent's global totals (Stats) include; a seeding library alone receives hundreds of megabytes of those a day.GetTorrentrequests only the one torrent rather than listing them all.- Errors of calls on a torrent rTorrent does not have, such as one removed
since it was listed, match
ErrNotFoundwitherrors.Is; timeouts and other faults do not. Torrent.Finishedis when a torrent completed andTorrent.Startedwhen it first started, in Unix seconds, or 0 until then; rTorrent keeps both across restarts.Torrent.Ageis when rTorrent loaded the torrent, which it does again for every torrent each time it starts, soStartedis the better guide to when a torrent was added.Torrent.AddedisStarted, orAgefor a torrent that never started, andByAddedsorts by it;ByAgeorders torrents by the time they were loaded.Torrent.TrackerCountis how many trackers a torrent lists.Messageis what the last tracker to answer said, which need not be the first.Torrent.Labelisd.custom1, where ruTorrent keeps its label, andSetLabelsets it. ruTorrent stores labels percent-encoded, as JavaScript'sencodeURIComponentwrites them, and decodes them to show them; rtapi passes labels through as they are.Fileslists a torrent's files, andSetFilePrioritiesskips or prioritizes them by index (FileSkip,FileNormal,FileHigh).GlobalLimitsandSetGlobalLimitsread and set the global download and upload rate limits, in bytes per second; zero means unlimited.FreeDiskSpacereports the free space on the filesystem holding a torrent, andFreeDiskSpacesthat of several torrents in one request. rTorrent knows where that is only for torrents it has opened, such as active ones, and reports 0 for the rest.Connectionscounts peer connections in one request: those peers opened to rTorrent, which they can only do when its port is reachable, and those rTorrent opened.Torrents.Sorttakes an explicitrtapi.Sortingvalue. Sorting is stable and compares names case-insensitively.DeleteMetadataerases torrents from rTorrent and checks that rTorrent acknowledged every one. rtapi never deletes data: the data belongs to the rTorrent host, so an application that offers it must enforce its own containment policy there.
From v1.0.0, rtapi follows semantic versioning: v1 releases add to the API but do not break it.
v1.1.0 adds List, Trackers, and Hashes, and decodes responses several
times faster with a fraction of the memory, which matters for libraries of
thousands of torrents. If rTorrent drops d.multicall2, as it plans to,
listing switches to d.multicall.
v1.2.0 adds Torrent.Started, and v1.3.0 adds Transfers, Stats.PID
(rTorrent's process ID, which tells when rTorrent has restarted),
Torrent.Private, SetLabel, FreeDiskSpaces, and Connections.
v1.4.0 refuses a load's Dir or Label that rTorrent would run as a command
(ErrCommandArgument), and adds ErrNotFound, NewClient and GetVersion,
Rtorrent.HTTPClient, Torrent.Added with ByAdded sorting, and
Torrent.TrackerCount. Socket paths count as sockets before the socket
exists.
Upgrading from v0:
Speedsis gone; useSpeedsWithErrororSpeedsContext, which report failures instead of returning zero.DeleteandErrUnsafeDataDeleteare gone; useDeleteMetadata.- The process-global
CurrentSortingvariable is gone; pass anrtapi.SortingtoTorrents.Sort.
go test ./...
go vet ./...
go build ./...