Initial WIP commit, functionnal

This commit is contained in:
Benoît Rouits 2020-05-23 15:17:53 +02:00
parent eac69d3fd4
commit d0a8e78d33
5 changed files with 250 additions and 0 deletions

1
depends.txt Normal file
View File

@ -0,0 +1 @@
default

54
init.lua Normal file
View File

@ -0,0 +1,54 @@
local json = require("json")
ssb = dofile(minetest.get_modpath("scuttlebutt") .. "/ssb.lua")
function ssb_receive(key, json)
relation = "FROM JSON"
message = key .. "said: " .. "FROM JSON"
name = "FROM RELATION"
minetest.chat_send_player(name, message)
end
function ssb_send(player, key, message)
if key == "" or message == "" then
return "error: empty key or message!"
end
local pname = player:get_player_name()
message = string.format("Minetest bot here. %s says: %s", pname, message)
local content = {
type = "post",
text = message,
recps = {key},
}
local ret, err = ssb:publish(content)
if (not err) then
return "ok: message sent."
-- return (string.format("ret: %s", json.encode(ret)))
else
return (string.format("error happened: %s", err))
end
end
minetest.register_chatcommand("ssb", {
params = "<@key> [message]",
description = "Scuttlebutt Chat",
privs = {
ssb = true,
},
func = function(name, param)
local player = minetest.get_player_by_name(name)
local key, message = string.match(param, "^(@[^ ]+) *(.*)$")
if not key or key == "" then
return true, "error: could not parse key"
elseif not message or message == "" then
local settings = minetest.settings:to_table()
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
})

3
mod.conf Normal file
View File

@ -0,0 +1,3 @@
name = scuttlebutt
description = Add Scuttlebutt chat.
depends = default

192
ssb.lua Normal file
View File

@ -0,0 +1,192 @@
local json = require("json")
local socket = require("socket")
local unix = require("socket.unix")
local bit32 = require("bit32")
local ssb = { VERSION = '0.1' }
local function get_ssb_dir()
local home = os.getenv("HOME")
return string.format("%s/.ssb", home)
end
local function read_manifest()
local manifest = get_ssb_dir() .. "/manifest.json"
local f = io.open(manifest, "rb")
if not f then
return nil, "cannot find manifest: " .. manifest
end
local buf = f:read("*all")
f:close()
local js = json.decode(buf)
return js, nil
end
function do_read(conn, id, final)
local buf, err = conn:receive(9)
if string.len(buf) < 9 then
minetest.log("do_read: header len should be 9 but is: " .. string.len(buf))
return nil, string.len(buf)
end
local first = string.byte(buf, 1)
local len = bit32.bor(bit32.lshift(string.byte(buf, 2), 24),
bit32.lshift(string.byte(buf, 3), 16),
bit32.lshift(string.byte(buf, 4), 8),
string.byte(buf, 5))
-- remove minus sign
local id = bit32.bxor(bit32.bor(bit32.lshift(string.byte(buf, 6), 24),
bit32.lshift(string.byte(buf, 7), 16),
bit32.lshift(string.byte(buf, 8), 8),
string.byte(buf, 9)), 0xFFFFFFFF) + 1
-- minetest.log("do_read: len: " .. len)
-- 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
function do_write(conn, req, mtype, ptype, id, final)
-- first byte construction
local pkt = {
buffer = 0,
string = 1,
json = 2,
}
local pktype = pkt[ptype]
local stream
if mtype == "async" then stream = 0 else stream = 1 end
local fin
if final then fin = 1 else fin = 0 end
local first = string.char(bit32.bor(bit32.lshift(stream, 3), bit32.lshift(fin, 2), bit32.band(pktype, 3)))
-- big-endian header construction
local b0 = bit32.rshift(bit32.band(string.len(req), 0xFF000000), 24)
local b1 = bit32.rshift(bit32.band(string.len(req), 0x00FF0000), 16)
local b2 = bit32.rshift(bit32.band(string.len(req), 0x0000FF00), 8)
local b3 = bit32.band(string.len(req), 0x000000FF)
-- limitation to 255 ids
local head = string.char(b0, b1, b2, b3, 0, 0, 0, id)
-- concat
local buf = first .. head .. req
return conn:send(buf)
end
function do_goodbye(conn)
return do_write(conn, "", "async", "buffer", 0, true)
end
function rpc_async(conn, meth, mtype, param)
-- wrap
local req = json.encode({
name = meth,
args = {param},
})
local ret, err = do_write(conn, req, mtype, "json", 1, false)
-- minetest.log("do_write: len: " .. ret)
if err then
minetest.log("do_write: " .. err)
return ret, err
end
ret, err = do_read(conn, 1, false)
-- minetest.log("do_read: len: " .. string.len(ret))
if err then
minetest.log("do_read: " .. err)
return ret, err
end
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,
-- TODO implement all types
}
local rpc = switch[mtype]
if not rpc then
return nil, "method type unimplemented yet."
end
return rpc(conn, meth, mtype, param)
end
local function parse_msgs(arr)
local r = {}
for i, msg in ipairs(arr) do
r[i] = json.decode(msg)
end
return r
end
local mt = {
__index = function(self, k)
local manifest, err = read_manifest()
if err then
return function(s, ...)
return nil, "cannot initialize: " .. err
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 params = {...}
local js
-- for key, val in ipairs(params) do
-- minetest.log(key .. "=" .. json.encode(val))
-- end
-- take only first param
js = params[1]
local c = unix()
local ret, err = c:connect(get_ssb_dir() .. "/socket")
if err then
return c, err
end
local ret, err = muxrpc(c, k, mtype, js)
if err then
c:close()
return ret, err
end
-- minetest.log(ret)
if not err then
if (type(ret) ~= "table") then
res = json.decode(ret)
else
res = parse_msgs(ret)
end
else
res = nil
err = ret
end
return res, err
end
end
}
setmetatable(ssb, mt)
return ssb

BIN
textures/ssbmod_shell.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB