Scripting Guide

Building on the Configuration Quick Start, this chapter explains more complex commands and constructs of the scripting language. It also helps with controlling rTorrent from the outside, via the XMLRPC protocol.

It is to become the comprehensive reference to rTorrent’s command language that was always missing, and will only be a success when enough people join forces and thus spread the workload to many shoulders. If you’re a developer or power user, this will be an invaluable tool, so please take the time and contribute what you know.

See the Commands Reference chapter for a list of all relevant XMLRPC and ‘private’ commands of rTorrent with a short explanation. The generated index also lists all the command names.

Another helpful tool is the quite powerful GitHub search. Use it to find information on commands, e.g. their old vs. new syntax variants, what they actually do (i.e. “read the source”), and internal uses in predefined methods, handlers, and schedules. Consider the view.add example.

Introduction

rTorrent scripting uses a strictly line-oriented syntax, with no control structures that span several logical lines. Read Basic Syntax Elements (again) regarding the most fundamental syntax rules. If you skipped Config Template Deconstructed, now is the time to go through it, since it exposes you to common idioms while explaining the core config commands.

Here’s also a short command syntax summary:

  • Comments start with a #.
  • Line continuations work by escaping the line end with \.
  • Commands take the form cmd = arg, (‘old’ syntax) or (cmd, arg, …) (‘new’ syntax).
  • Arguments are a comma-separated list: arg1, arg2, .
  • $cmd=… evaluates cmd and inserts its result value in place of the call. A command in single parentheses is also immediately evaluated.
  • Use double quotes for preserving whitespace, or to pass statements as arguments to other commands (like method.insert and schedule2). Use \" to escape quotes within quoted strings.
  • Within double quotes, a semicolon ; can be used as a delimiter to pass command sequences, e.g. in event handler bodies and scheduled commands.
  • Use double parentheses to pass a command unevaluated to another command.
  • Braces {…, …} pass a list as an argument, used for setting list values, or with boolean operators.
  • All commands are defined in the C++ source files rtorrent/src/command_*.cc of the client’s source code, which is the ultimate reference when it comes to intricate details.

Commands

A command is basically a function call or method, used to either query or change a configuration setting, or cause some side-effect at runtime. They’re called by the configuration file parser, timed schedules, event handlers, and via XMLRPC.

See Object Types for the difference between simple and ‘multi’ commands, and what return types commands can have. You can use method.redirect to define alias names for commands, which is mostly used internally to keep deprecated command names alive for a while.

A deep-dive into defining your own commands can be found in the reference of related method.* commands.

Use the Commands Reference for details on specific commands, and the generated index to find them by name.

Escaping

The most basic form of escaping is when you have to supply a command with multiple arguments to another command as part of an argument list. You have to tell rTorrent which comma belongs to the inner argument list, and which to the outer one, by quoting the inner command using double quotation marks:

outer = arg1, "inner=arg21,arg22", arg3

It’s also good style to avoid deep nesting by defining your own custom commands (see method.insert, and also Config Template Deconstructed and Common Configuration Use-Cases for many examples). You can then use these building blocks in another command, instead of a literal nested group. The additional benefit is you can name things for documentation purposes, and also avoid overly long lines.

In practice, anything but a single nested quote should be avoided, because the next level already gives you the \\\" awkwardness.

Make plenty use of line continuations, i.e. escaping of line ends to break up long physical lines into several short ones. Put the breaks into places where you can use any amount of whitespace, and then indent the parts according to the structure of the logical line.

method.insert = indent_sequence_of_cmds_and_their_args, private|simple,\
    "load.verbose =\
        (cat, (cfg.watch), (argument.0), /*.torrent),\
        (cat, d.category.set=, (argument.0)) ;\
     category.view.update = (argument.0)"

schedule2 = polling, 10, 120,\
    ((d.multicall2, main,\
        "branch=\"or={d.up.rate=,d.down.rate=,}\",\
            poll=$interval.active=,\
            poll=$interval.idle="))

Also note how using combinations of ‘new’ and ‘old’ syntax keeps the needed amount of escaping at bay (double parentheses are also a form of escaping).

Object Types

This is a summary about the possible object types in command_dynamic.cc (applies to 0.9.6).

Subtypes determine certain traits of a command, like immutability (const, enabled directly in a definition, or via method.const.enable). If a command is private, it can only be called from within rTorrent, but not directly via XMLRPC – it will thus also be excluded from system.listMethods.

TODO static?!

value, bool, string, list (subtypes: static, private, const)

These are the standard object types, value is an integer, and bool just a convention of using the integer values 0 for false and 1 for true.

Lists are either generated by commands that return multiple values, like download_list, or defined literally using the {val[, …]} syntax to pass them into commands.

simple (subtypes: static, private, const)

Simple commands are defined once and cannot be changed dynamically like multi ones. They can still contain a sequence of several commands in a given order, using "cmd1=… ; cmd2=…" or (( (cmd1,…), (cmd2,…) )).

Important

Be aware of the time of evaluation of commands in method definitions.

Quoted command sequences are parsed on each execution and thus only evaluated then, while using parentheses means instant evaluation for a single pair, and delayed evaluation for commands in double parentheses.

That delay is not inherited by nested commands. So ((cat, (manifest.constant) )) works as intended, while ((if, (dynamic.value), )) does not (the inner call also needs double parentheses)!

Which means you always have to keep the surrounding context in mind when writing nested command sequences.

multi (subtypes: static, private, const, rlookup)

A multi command is an array of simple commands, indexed by a name. When you call a multi command, the sequence is executed in order of the keys used when defining a single command of the sequence.

Multi commands are used at many places in rTorrent, especially where dynamic user-defined behaviour is needed. All the event handlers are of type multi.

Note that many internal entries in multi commands used by the system are prefixed with either ! or ~, to push them to the front or end of the processing order.

TODO rlookup?!

Formatting & Type Conversions

TODO

Custom Attributes

TODO

Advanced Concepts

‘✴.multicall’ Demystified

TODO

Scripting Best Practices

TODO

Using XMLRPC for Remote Control

XMLRPC is the remote interface rTorrent offers to execute commands after startup in a running process. Commands are sent via either a UNIX domain socket or a TCP socket using a protocol called SCGI, typically used between a web server and a long-running CGI process.

The /RPC2 mount some software needs just bridges that internal connection to a full HTTP end point. Any XMLRPC library can be used against such a HTTP gateway, while using the ‘raw’ SCGI end point requires special client libraries that speak that protocol (see below).

Commands usable via XMLRPC are almost the same you can use in configuration files. Differences are:

  • There is the concept of internal commands that are not exposed to XMLRPC, and only available in configuration and via the Ctrl-X prompt. You can circumvent that restriction by putting commands into a file, and then importing that.
  • You (almost) always have to pass the so-called target which is the object the command should act on, like a download item or a peer or file entry. See below for details.

See the Commands Reference for descriptions of existing commands, the generated index can help you to quickly find them by their name.

Command Targets

All XMLPPC commands (with a few exceptions like system.listMethods) take an info hash as the first argument when called over the API, to uniquely identify the target object. ‘Target’ is also the term used for that first parameter in error messages like Unsupported target type found, and that message is the one you’ll most likely get if you forgot to provide one.

Commands that do not target a specific item still need to have one (in newer versions of rTorrent), so provide an empty string as a placeholder in those cases.

$ rtxmlrpc view.size default
ERROR    While calling view.size('default'): <Fault -501: 'Unsupported target type found.'>
$ rtxmlrpc view.size '' default
133

Note that f.* commands, p.* commands, and t.* commands, when not called via their associated multicall command, have special target forms with additional information appended: ‹infohash›:f‹file-index›, ‹infohash›:p‹peer-id›, and ‹infohash›:t‹tracker-index›.

Configuration Considerations

Be aware of the security implications of opening a XMLRPC socket, as described in the network.scgi.open_port reference – you must safe-guard it via file level permissions or HTTP authorization. A TCP socket generally is open to all local users on a machine, unless you use network namespaces. That is why it is deprecated and a secured UNIX domain socket is better in all regards.

If you activate the daemon mode introduced with rTorrent 0.9.7, using XMLRPC is the only way to control a running rTorrent process

Regarding available commands, the -D, -I, and -K command line options switch the deprecated and intermediate command groups off during startup. The related method.use_deprecated and method.use_intermediate commands reflect those options. If you run badly maintained or abandoned client software, you still need to keep the deprecated commands active. See ‘Intermediate’ Commands for more details.

XMLRPC payloads can get quite large, especially when you get a large list of attributes for all loaded items. The network.xmlrpc.size_limit.set command determines the size of the buffer used to hold those payloads. Use 16M or more for larger instances, for example getting 20 attributes for 10,000 items generates a 1.4 KiB request, resulting in a roughly 10 MiB response.

Client Libraries

TODO