diff --git a/init.lua b/init.lua index 203b1a1..697ab73 100644 --- a/init.lua +++ b/init.lua @@ -1,11 +1,27 @@ minetest.request_insecure_environment() ssb = dofile(minetest.get_modpath("scuttlebutt") .. "/ssb.lua") +chat = {} -function ssb_receive(key, json) - relation = "FROM JSON" - message = key .. "said: " .. "FROM JSON" - name = "FROM RELATION" - minetest.chat_send_player(name, message) +function ssb_poll(pname, value) + local content = { + id = value.me, + sequence = value.sequence, + limit = 1, + live = false, + old = true, + keys = true, + } + + local ret, err = ssb:createHistoryStream(content) + if err then + return (string.format("error happened: %s", err)) + else + if ret == true then + -- early end of stream + ret = nil + end + return ret + end end function ssb_send(player, key, message) @@ -23,14 +39,48 @@ function ssb_send(player, key, message) } local ret, err = ssb:publish(content) - if (not err) then - return "ok: message sent." - -- return (string.format("ret: %s", json.encode(ret))) - else + if err then return (string.format("error happened: %s", err)) + else + minetest.log(json.encode(ret)) + local v = { + id = ret.key, + sequence = ret.value.sequence + 1, + me = ret.value.author, + rcpt = key, + } + if chat[pname] == nil then + chat[pname] = {} + end + table.insert(chat[pname], v) + return "ok: message sent." end end +function reap() + for p, v in pairs(chat) do + minetest.log("polling responses for player: " .. p) + for i, c in ipairs(v) do -- crawl conversations + local ret, err = ssb_poll(p, c) + if err then + minetest.log(err) + return + end + if ret ~= nil then + if c.id == ret.value.previous and c.rcpt == ret.value.author then + table.remove(v, i) -- end conversation + local text = ssb:private():unbox(ret.value.content) + local author = "ssb: " .. string.sub(ret.value.author, 1, 7) .. "..." + minetest.chat_send_player(p, author .. " replied: " .. text) + end + end + end + end + minetest.after(60, reap) +end + +minetest.after(60, reap) + minetest.register_privilege("ssb", "Ability to chat through Scuttlebutt") minetest.register_chatcommand("ssb", { @@ -49,7 +99,6 @@ minetest.register_chatcommand("ssb", { local ip = settings.server_address or "127.0.0.1" local port = settings.port or 30000 message = "Please join me on minetest: " .. ip .. ":" .. port - -- return true, "error: could not parse message" end return true, ssb_send(player, key, message) end diff --git a/ssb.lua b/ssb.lua index ecccf97..d0fbc98 100644 --- a/ssb.lua +++ b/ssb.lua @@ -21,6 +21,14 @@ local function read_manifest() return js, nil end +function method_to_json(meth) + local res = {} + for tok in string.gmatch(meth, "[^.]+") do + table.insert(res, tok) + end + return res +end + function do_read(conn, id, final) local buf, err = conn:receive(9) if string.len(buf) < 9 then @@ -42,7 +50,6 @@ function do_read(conn, id, final) -- minetest.log("do_read: id : " .. id) if id ~= 1 then minetest.log("do_read: id should be 1 but is: " .. id) - -- minetest.log("do_read: " .. string.byte(buf, 6) .. string.byte(buf, 7) .. string.byte(buf, 8) .. string.byte(buf, 9)) end return conn:receive(len) end @@ -79,10 +86,39 @@ function do_goodbye(conn) return do_write(conn, "", "async", "buffer", 0, true) end +function rpc_source(conn, meth, mtype, param) + local req = json.encode({ + name = method_to_json(meth), + args = {param}, + type = mtype, + }) + + local ret, err = do_write(conn, req, mtype, "json", 1, false) + if err then + minetest.log("do_write: " .. err) + return ret, err + end + + ret, err = do_read(conn, 1, false) + if err then + minetest.log("do_read :" .. err) + return ret, err + end + + minetest.log(ret) + do_goodbye(conn) + + return ret, err +end + +function rpc_sync(conn, meth, mtype, param) + return rpc_source(conn, meth, mtype, param) +end + function rpc_async(conn, meth, mtype, param) -- wrap local req = json.encode({ - name = meth, + name = method_to_json(meth), args = {param}, }) @@ -102,18 +138,14 @@ function rpc_async(conn, meth, mtype, param) do_goodbye(conn) --- local ret = json.encode({ --- name = meth, --- type = mtype, --- arg = param, --- }) --- local err = nil return ret, err end function muxrpc(conn, meth, mtype, param) local switch = { async = rpc_async, + source = rpc_source, + sync = rpc_sync, -- TODO implement all types } @@ -142,15 +174,7 @@ local mt = { end end - return function(s, ...) - local res, err = nil - - if not manifest[k] then - return err, "method not found: " .. k - end - - local mtype = manifest[k] - + local mux = function (k, mtype, ...) local params = {...} local js -- for key, val in ipairs(params) do @@ -174,17 +198,45 @@ local mt = { -- minetest.log(ret) if not err then if (type(ret) ~= "table") then - res = json.decode(ret) + ret = json.decode(ret) else - res = parse_msgs(ret) + ret = parse_msgs(ret) end else - res = nil err = ret + ret = nil end - return res, err - end + return ret, err + end + + return function(s, ...) + if not manifest[k] then + return nil, "method not found: " .. k + end + + local mtype = manifest[k] + + if type(mtype) ~= "table" then + return mux(k, mtype, ...) + end + + local submt = { + __index = function (self, subk) + return function (s, ...) + if mtype[subk] == nil then + return nil, "method not found: " .. k .. "." .. subk + end + + return mux(k .. "." .. subk, mtype[subk], ...) + end + end + } + + local sub = {} + setmetatable(sub, submt) + return sub + end end }