rakshasa / rtorrent

rTorrent BitTorrent client
https://github.com/rakshasa/rtorrent/wiki
GNU General Public License v2.0
4.05k stars 412 forks source link

Add optional Lua scripting capabilties #1260

Open kannibalox opened 5 months ago

kannibalox commented 5 months ago

This was tested on Lua 5.4, since while there shouldn't be any version-specific features in use, the lack of native 64-bit integer support in versions before 5.3 seems like a deal breaker.

There are three RPC commands added: lua.execute, which allows executing Lua code, with a rtorrent package that has basic support for making direct RPC calls from a file:

local ofile = io.open("/tmp/out.lua.txt", "w")
-- Purposefully inefficient as a demonstration of `rtorrent.call`
for _, result in ipairs(rtorrent.call("d.multicall2", "", "main", "d.hash=")) do
   ofile:write(rtorrent.call("d.name", result[1]).."\n")
end
-- Alternative syntactical sugar
r = rtorrent.autocall
ofile:write(r.system.hostname())
ofile:close()

That's a little verbose to be a replacement for rtorrent.rc, so there's also lua.import, which uses the same "autocall" Lua magic for a simpler syntax:

local base = "/tmp/rtorrent/"
scgi_port("0.0.0.0:9998")
session(base.."session")
directory(base.."data")
network.http.max_open.set(256)

lua.execute.str is mainly to allow events, but could it definitely use a more convenient syntax:

local function insert_method(name, func_name, arg0, arg1, arg2, arg3)
   args = {
      arg0 or "$argument.0=",
      arg1 or "$argument.1=",
      arg2 or "$argument.2=",
      arg3 or "$argument.3=",
   }
   arg_str = table.concat(args, ",")
   rtorrent.call("method.insert", "", name, "simple", "lua.execute.str=\"return "..func_name.."(...)\","..arg_str)
end
function event_handler(target, name)
   rtorrent.call("print", "", "Lua event: Inserted \""..target..": "..name.."\"")
end
insert_method("d.event_handler", "event_handler", "(d.name)")

rtorrent.call("method.set_key", "", "event.download.inserted", "print_name", "d.event_handler=")

Implements https://github.com/rakshasa/rtorrent/issues/490

kartikynwa commented 2 weeks ago

This looks interesting. What do you use this for personally?

kannibalox commented 2 weeks ago

I converted my config to Lua, but that was more to test any edge cases. More regularly I find myself using it to do complicated client-side filtering.

My main goal was to start out with making methods/events more structured, since that proves to be a major source of confusion when new people are learning the rTorrent scripting language. Currently I think it needs a better syntax than the one I provided above, so I'm still playing around with that a little. If you're looking for ideas, luarocks has a lot of neat packages that could extend rtorrent to do pretty much anything.