a55af9f667
Fixed logging lock (causes color issues in parallel env)
219 lines
6.8 KiB
Lua
219 lines
6.8 KiB
Lua
local secretToken = "$TOKEN"
|
|
local connectionUri = "$HOST"
|
|
local waitSeconds = 5
|
|
-- https://github.com/cc-tweaked/CC-Tweaked/blob/9cf70b10effeeed23e0e9c537bbbe0b2ff0d1a0f/src/main/java/dan200/computercraft/core/apis/http/options/AddressRule.java#L29
|
|
-- Chunk size must be less than packet size (type reply, success, chunkids, content: chunk) 16 kb for buffer
|
|
local maxMessageSize = (128 - 16) * 1024
|
|
|
|
local function chunkString(value, chunkSize)
|
|
if not chunkSize then chunkSize = maxMessageSize end
|
|
local length = value:len()
|
|
local total = math.ceil(length / chunkSize)
|
|
local chunks = {}
|
|
if length == 0 then
|
|
total = 1
|
|
chunks[1] = ""
|
|
else
|
|
local i = 1
|
|
for i=1,total do
|
|
local pos = 1 + ((i - 1) * chunkSize)
|
|
chunks[i] = value:sub(pos, pos + chunkSize - 1)
|
|
end
|
|
end
|
|
return total, chunks
|
|
end
|
|
|
|
local function sendJson(socket, message)
|
|
return socket.send(textutils.serializeJSON(message))
|
|
end
|
|
|
|
local function sendResponse(socket, id, result, success)
|
|
if success == nil then success = 0 end
|
|
|
|
local total, chunks = chunkString(result)
|
|
for i, chunk in pairs(chunks) do
|
|
sendJson(socket, { type = "reply", id = id, result = chunk, chunk = i, total = total, success = success })
|
|
end
|
|
end
|
|
|
|
-- error: no rs system
|
|
-- return rssystem rs
|
|
local function getPeripheral(name)
|
|
local dev = peripheral.find(name)
|
|
if not dev then error({message = "No peripheral '"..name.."' attached to the computer!"}) end
|
|
return dev
|
|
end
|
|
|
|
local function runRsCommand(params)
|
|
local script, reason = loadstring("local rs = peripheral.find(\"rsBridge\") if not rs then error({message = \"RS Bridge is not attached!\"}) end return rs."..params.command)
|
|
if not script then error({message = "Invalid command: "..reason.."!"}) end
|
|
local result = table.pack(pcall(script))
|
|
local success = result[1]
|
|
if not success then error({message = "Command execution failed: "..result[2].."!"}) end
|
|
|
|
local retvals = {}
|
|
retvals.n = result.n - 1
|
|
for i=1,retvals.n do retvals[tostring(i)] = result[i + 1] end
|
|
return textutils.serializeJSON(retvals)
|
|
end
|
|
|
|
-- error: any error during execution
|
|
-- return string result
|
|
local function getResponse(parsed)
|
|
if parsed.method == "energyusage" then
|
|
return tostring(getPeripheral("rsBridge").getEnergyUsage())
|
|
elseif parsed.method == "energystorage" then
|
|
return tostring(getPeripheral("rsBridge").getEnergyStorage())
|
|
elseif parsed.method == "listitems" then
|
|
return textutils.serializeJSON(getPeripheral("rsBridge").listItems())
|
|
elseif parsed.method == "listfluids" then
|
|
return textutils.serializeJSON(getPeripheral("rsBridge").listFluids())
|
|
elseif parsed.method == "craft" then
|
|
return tostring(getPeripheral("rsBridge").craftItem(parsed.params))
|
|
elseif parsed.method == "getitem" then
|
|
local item = getPeripheral("rsBridge").getItem(parsed.params)
|
|
if not item then error({message = "Requested item not found!"}) end
|
|
return textutils.serializeJSON(item)
|
|
elseif parsed.method == "command" then
|
|
return runRsCommand(parsed.params)
|
|
elseif parsed.method == "getonline" then
|
|
return textutils.serializeJSON(getPeripheral("playerDetector").getOnlinePlayers())
|
|
elseif parsed.method == "whereis" then
|
|
local pos = getPeripheral("playerDetector").getPlayerPos(parsed.params.username)
|
|
if not pos then return "null" end
|
|
return textutils.serializeJSON(pos)
|
|
elseif parsed.method == "send" then
|
|
if not parsed.params.username then
|
|
getPeripheral("chatBox").sendMessage(parsed.params.message, parsed.params.prefix)
|
|
else
|
|
getPeripheral("chatBox").sendMessageToPlayer(parsed.params.message, parsed.params.username, parsed.params.prefix)
|
|
end
|
|
return "true"
|
|
end
|
|
|
|
error({message = "No message handler for method: "..parsed.method.."!"})
|
|
end
|
|
|
|
local function logJSON(json, prefix)
|
|
if not prefix then prefix = "" end
|
|
for k,v in pairs(json) do
|
|
local key = prefix..k
|
|
if type(v) == "table" then
|
|
logJSON(v, key..".")
|
|
else
|
|
print(key, "=", textutils.serializeJSON(v))
|
|
end
|
|
end
|
|
end
|
|
|
|
-- return bool success
|
|
local function handleMessage(socket, message)
|
|
local parsed, reason = textutils.unserializeJSON(message)
|
|
if not parsed then
|
|
print("Received message:", message)
|
|
printError("Message could not be parsed:", reason)
|
|
return false
|
|
end
|
|
|
|
pcall(function() print("Received JSON:") logJSON(parsed) end)
|
|
|
|
if parsed.type == "request" then
|
|
local success, result = pcall(function() return getResponse(parsed) end)
|
|
if not success then
|
|
if not result.message then
|
|
sendResponse(socket, parsed.id, result, 2)
|
|
else
|
|
sendResponse(socket, parsed.id, result.message, 1)
|
|
end
|
|
else
|
|
sendResponse(socket, parsed.id, result, 0)
|
|
end
|
|
return true
|
|
end
|
|
|
|
printError("Invalid message type:", parsed.type)
|
|
return false
|
|
end
|
|
|
|
local function responder(socket)
|
|
while true do
|
|
local message, binary = socket.receive()
|
|
if not not message and not binary then
|
|
if message == "outdated" then
|
|
printError("Current script is outdated! Please update from the host!")
|
|
return
|
|
end
|
|
handleMessage(socket, message)
|
|
end
|
|
end
|
|
end
|
|
|
|
local function termWaiter()
|
|
os.pullEvent("terminate")
|
|
end
|
|
|
|
local function chatEventListener(socket)
|
|
while true do
|
|
event, username, message, uuid, hidden = os.pullEvent("chat")
|
|
sendJson(socket, {type = "chat", username = username, message = message, uuid = uuid, hidden = hidden})
|
|
print("Chat event relayed!")
|
|
end
|
|
end
|
|
|
|
local function getPeripheralInfo(side)
|
|
return {type = peripheral.getType(side), methods = peripheral.getMethods(side), side = side}
|
|
end
|
|
|
|
local function peripheralDetachEventListener(socket)
|
|
while true do
|
|
event, side = os.pullEvent("peripheral_detach")
|
|
sendJson(socket, {type = "peripheral_detach", side = side})
|
|
print("Peripheral was detached!")
|
|
end
|
|
end
|
|
|
|
local function peripheralAttachEventListener(socket)
|
|
while true do
|
|
event, side = os.pullEvent("peripheral")
|
|
sendJson(socket, {type = "peripheral", peripheral = getPeripheralInfo(side) })
|
|
print("Peripheral was attached!")
|
|
end
|
|
end
|
|
|
|
local function eventListeners(socket)
|
|
parallel.waitForAny(
|
|
termWaiter,
|
|
function() chatEventListener(socket) end,
|
|
function() peripheralDetachEventListener(socket) end,
|
|
function() peripheralAttachEventListener(socket) end
|
|
)
|
|
end
|
|
|
|
local function socketClient()
|
|
print("Connecting to the socket server at "..connectionUri.."...")
|
|
local socket, reason = http.websocket(connectionUri)
|
|
if not socket then error("Socket server could not be reached: "..reason) end
|
|
print("Connection successful!")
|
|
|
|
socket.send("login="..secretToken)
|
|
parallel.waitForAny(
|
|
function() responder(socket) end,
|
|
function() eventListeners(socket) end
|
|
)
|
|
socket.close()
|
|
end
|
|
|
|
local function main()
|
|
while true do
|
|
local status, error = pcall(socketClient)
|
|
if status then break end
|
|
printError("An uncaught exception was raised:", error)
|
|
printError("Restarting in", waitSeconds, "seconds...")
|
|
sleep(waitSeconds)
|
|
end
|
|
end
|
|
|
|
local oldPullEvent = os.pullEvent
|
|
os.pullEvent = os.pullEventRaw
|
|
pcall(main)
|
|
os.pullEvent = oldPullEvent |