minetest-matrix_bridge/init.lua

206 lines
6.5 KiB
Lua
Raw Normal View History

print("Matrix bridge loaded.")
2022-01-21 15:16:11 +01:00
local modpath = minetest.get_modpath(minetest.get_current_modname())
2022-01-21 16:02:39 +01:00
dofile(modpath.."/config.lua")
2022-01-21 15:16:11 +01:00
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()
2022-01-26 03:01:04 +01:00
local since = nil
local eventid = nil
local function mchat(data)
if data == nil then
return
end
if since == data.next_batch 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
2022-01-23 05:24:06 +01:00
minetest.log("action", "matrix_bridge - found timeline but no events")
return
end
2022-01-23 05:24:06 +01:00
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.log("action", message)
minetest.chat_send_all(message)
end
end
end
end
2022-01-23 06:19:10 +01:00
local function msync(s)
-- optimization note: request more recent instead of unfiltered req
-- local param1 = '&filter={\"room\":{\"timeline\":{\"limit\":1}}}'
2022-01-26 03:01:04 +01:00
-- local param1 = "?access_token=" .. token
local param2 = "?full_state=false"
2022-01-23 06:19:10 +01:00
local param3 = "&timeout=5000"
2022-01-26 03:01:04 +01:00
local u = MATRIX_SERVER.."/_matrix/client/r0/sync" .. param2 .. param3
2022-01-23 06:19:10 +01:00
if s == nil then -- first time sync
-- do nothing for now
else -- second time sync -> append since parameter
2022-01-23 06:19:10 +01:00
u = u .. "&since="..s
end
2022-01-26 03:01:04 +01:00
local h = {"Authorization: Bearer " .. token}
http.fetch({url=u, method="GET", extra_headers=h},
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
else
local response = minetest.parse_json(res.data)
if response ~= nil then
mchat(response)
2022-01-26 03:01:04 +01:00
since = response.next_batch
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()
2022-01-23 06:19:10 +01:00
minetest.log("action", "Matrix authenticated")
else
minetest.log("error", to_string(res))
end
end
)
end
mlogin()
2022-01-21 15:16:11 +01:00
2022-01-26 03:01:04 +01:00
local function send_message(msg)
txid = txid + 1
local u = MATRIX_SERVER.."/_matrix/client/r0/rooms/"..MATRIX_ROOM.."/send/m.room.message/" .. txid -- ?access_token=..token
local h = {"Content-Type: application/json", "Authorization: Bearer " .. token}
local d = minetest.write_json({msgtype="m.text", body=msg})
http.fetch({url=u, method="PUT", extra_headers=h, data=d},
function (res)
if res.code == 200 then
local data = minetest.parse_json(res.data)
minetest.log("action", "got " .. data["event_id"])
eventid = data["event_id"]
elseif res.code == 401 then
minetest.log("error", "matrix_bridge - not authorized to send messages")
elseif res.code == 404 then
minetest.log("error", "matrix_bridge - could not find endpoint for send")
end
end)
2022-01-21 15:16:11 +01:00
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)
2022-01-26 03:01:04 +01:00
local GLOBAL_THRESHHOLD = 50
if GLOBAL_STEPS == GLOBAL_THRESHHOLD then
msync(since)
2022-01-26 03:01:04 +01:00
end
GLOBAL_STEPS = (GLOBAL_STEPS + 1) % (GLOBAL_THRESHHOLD+1)
end)
2022-01-23 06:19:10 +01:00
minetest.register_chatcommand("msync", {
privs = {
interact = true
},
func = function(name, param)
2022-01-23 13:19:59 +01:00
if param == "nil" then -- test sync as called from login
2022-01-23 06:19:10 +01:00
msync()
2022-01-23 22:36:05 +01:00
elseif param == "relogin" then
mlogin()
2022-01-23 13:19:59 +01:00
elseif #param > 1 then -- test sync with specific 'since' parameter
msync(param)
else -- test sync with current since parameter
2022-01-23 06:19:10 +01:00
msync(since)
end
return true, "[matrix_bridge] Fetching from matrix..."
end})
2022-01-21 15:16:11 +01:00
2022-01-23 22:36:05 +01:00
minetest.register_on_shutdown(function()
minetest.log("action", "matrix_bridge - signing out.")
local u = MATRIX_SERVER.."/logout/all"
http.fetch({url=u, method="POST", function (res) end})
end)
2022-01-21 15:16:11 +01:00
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)