You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

104 lines
3.1 KiB
Lua

-- Copyright 2014-2018 Sandor Balazsi <sandor.balazsi@gmail.com>
-- Licensed to the public under the GNU General Public License.
local ipairs, string, tostring, tonumber, table = ipairs, string, tostring, tonumber, table
local assert, type, unpack = assert, type, unpack
local nixio = require "nixio"
local socket = require "socket"
local xmlrpc = require "xmlrpc"
local scgi = require "xmlrpc.scgi"
local SCGI_ADDRESS = "localhost"
local SCGI_PORT = 5000
local HTTP_AUTH_USER = "rtorrent"
local HTTP_AUTH_PASSWORD = "czNz9JwdcLYcGDcVnZbQ"
module "rtorrent"
function map(array, func)
local new_array = {}
for i, v in ipairs(array) do
new_array[i] = func(v)
end
return new_array
end
function alter(prefix, methods, postfix)
methods = map(methods, function(method)
if method == 0 then return method end
if prefix then method = prefix .. method end
if postfix then method = method .. postfix end
return method
end)
return methods
end
function format(method_type, res, methods)
local formatted = {}
for _, r in ipairs(res) do
local item = {}
for i, v in ipairs(r) do
item[methods[method_type == "d." and i or i + 1]:gsub("%.", "_")] = v
end
table.insert(formatted, item)
end
return formatted
end
function call(method, ...)
local ok, res = scgi.call(SCGI_ADDRESS, SCGI_PORT, method, ...)
if not ok and res == "socket connect failed" then
assert(ok, "\n\nFailed to connect to rtorrent: rpc port not reachable!\n"
.. "Possible reasons:\n"
.. "- not the rpc version of rtorrent is installed\n"
.. "- scgi port is not defined in .rtorrent.rc (scgi_port = 127.0.0.1:5000)\n"
.. "- rtorrent is not running (ps | grep rtorrent)\n")
end
assert(ok, string.format("XML-RPC call failed on client: %s", tostring(res)))
return res
end
function rpc(xml)
local auth = "Basic " .. nixio.bin.b64encode(HTTP_AUTH_USER .. ":" .. HTTP_AUTH_PASSWORD)
if auth ~= nixio.getenv("HTTP_AUTHORIZATION") then
return 'Status: 401 Unauthorized\r\n'
.. 'WWW-Authenticate: Basic realm="rTorrent"\r\n\r\n'
end
local sock = socket.connect(SCGI_ADDRESS, SCGI_PORT)
if sock ~= nil then
sock:send(scgi.netstring(xml))
local err, code, headers, body = scgi.receive(sock)
if tonumber(code) == 200 then
return 'Status: 200 OK\r\n'
.. 'Content-Type: application/xml\r\n\r\n' .. body
end
end
return 'Status: 500 Internal Server Error\r\n\r\n'
end
function multicall(method_type, filter, ...)
local res = (method_type == "d.")
and call(method_type .. "multicall2", "", filter, unpack(alter(method_type, {...}, "=")))
or call(method_type .. "multicall", filter, unpack(alter(method_type, {...}, "=")))
return format(method_type, res, {...})
end
function batchcall(methods, params, prefix, postfix)
local p = type(params) == "table" and params or { params }
local methods_array = {}
for _, m in ipairs(alter(prefix, methods, postfix)) do
table.insert(methods_array, {
["methodName"] = m,
["params"] = xmlrpc.newTypedValue(p, "array")
})
end
local res = {}
for i, r in ipairs(call("system.multicall", xmlrpc.newTypedValue(methods_array, "array"))) do
res[methods[i]] = r[1]
end
return res
end