print("Matrix bridge loaded.") local modpath = minetest.get_modpath(minetest.get_current_modname()) dofile(modpath.."/config.lua") dofile(modpath.."/debug.lua") local http = minetest.request_http_api() if http == nil then error("Please add matrix_bridge to secure.http_mods") end local token = nil local txid = 0 -- used for msync() local since = nil local last_batch = nil local function mchat(data) if data == nil then return end -- lets just get this working if data["rooms"] == nil then return end if data["rooms"]["join"] == nil then return end if data["rooms"]["join"][MATRIX_ROOM] == nil then return end if data["rooms"]["join"][MATRIX_ROOM]["timeline"] == nil then return else local events = data["rooms"]["join"][MATRIX_ROOM]["timeline"]["events"] if events == nil then minetest.log("action", "matrix_bridge - found timeline but no events") return end minetest.log("action", "matrix_bridge - sync'd and found new messages") for i, event in ipairs(events) do if event.type == "m.room.message" and event.sender ~= MATRIX_USERNAME_LONG then local message = event.sender .. ": " .. event.content.body minetest.chat_send_all(message) end end end end local function msync(s) -- optimization note: request more recent instead of unfiltered req -- local param1 = '&filter={\"room\":{\"timeline\":{\"limit\":1}}}' local param1 = "?access_token=" .. token local param2 = "&full_state=false" local param3 = "&timeout=5000" local u = MATRIX_SERVER.."/_matrix/client/r0/sync" .. param1 .. param2 .. param3 if s == nil then -- first time sync -- do nothing for now else -- second time sync -> append since parameter u = u .. "&since="..s end http.fetch({url=u}, function (res) if res == nil then -- received nothing from server minetest.log("error", "matrix_bridge - sync response is nil") elseif res.code == 0 then minetest.log("info", "matrix_bridge - not found / timeout") elseif res.code == 404 then minetest.log("error", "matrix_bridge - 404") else local response = minetest.parse_json(res.data) if response ~= nil then since = response.next_batch last_batch = response.prev_batch mchat(response) end end end ) end local function mlogin() local u = MATRIX_SERVER.."/_matrix/client/r0/login" local d = '{"type":"m.login.password","password":"'..MATRIX_PASSWORD..'","identifier":{"type":"m.id.user","user":"'..MATRIX_USERNAME..'"}}' local h = {"Content-Type: application/json"} http.fetch({url=u, method="POST", extra_headers=h, data=d}, function(res) if res.code == 200 then minetest.log("action", res.data) local data = minetest.parse_json(res.data) token = data.access_token msync() minetest.log("action", "Matrix authenticated") else minetest.log("error", to_string(res)) end end ) end mlogin() function send_message(msg) txid = txid + 1 http.fetch({ url = MATRIX_SERVER.."/_matrix/client/r0/rooms/"..MATRIX_ROOM.."/send/m.room.message/"..txid.."?access_token="..token, method = "PUT", extra_headers = {"Content-Type: application/json"}, data = minetest.write_json({msgtype="m.text", body=msg}) }, function(res) end) end -- http.fetch({ -- url = MATRIX_SERVER.."/_matrix/client/r0/login", -- method = "POST", -- extra_headers = {"Content-Type: application/json"}, -- data = '{"type":"m.login.password","password":"'..MATRIX_PASSWORD..'","identifier":{"type":"m.id.user","user":"'..MATRIX_USERNAME..'"}}' -- }, function(res) -- if res.code == 200 then -- minetest.log("action", res.data) -- local data = minetest.parse_json(res.data) -- token = data.access_token -- minetest.log("action", "Matrix authenticated") -- else -- minetest.log("error", to_string(res)) -- end -- end) -- local GLOBAL_STEPS = 0 -- minetest.register_globalstep(function(dtine) -- -- print(GLOBAL_STEPS) -- if GLOBAL_STEPS == 4 then -- msync() -- end -- GLOBAL_STEPS = (GLOBAL_STEPS + 1) % 5 -- end) minetest.register_chatcommand("msync", { privs = { interact = true }, func = function(name, param) if param == "nil" then msync() else msync(since) end return true, "[matrix_bridge] Fetching from matrix..." end}) minetest.register_on_joinplayer(function(player) local name = player:get_player_name() if token then send_message("*** "..name.." joined the game") end end) minetest.register_on_leaveplayer(function(player, timed_out) local name = player:get_player_name() if token then send_message("*** "..name.." left the game".. (timed_out and " (Timed out)" or "")) end end) minetest.register_on_chat_message(function(name, message) if token == nil or message:sub(1, 1) == "/" or message:sub(1, 5) == "[off]" or (not minetest.check_player_privs(name, {shout=true})) then return end local nl = message:find("\n", 1, true) if nl then message = message:sub(1, nl - 1) end send_message("<"..name.."> "..message) end)