Add spudnet library

This commit is contained in:
v 2021-02-13 19:28:22 +00:00
parent 4d2a17e9a7
commit 287c7a0709
2 changed files with 163 additions and 0 deletions

151
spudnet/lib/spudnet.lua Normal file
View File

@ -0,0 +1,151 @@
local mt = dofile "/lib/multitask.lua"
local p = mt.newPool({crash_on_error = true})
local spudnet = {}
spudnet.init = function(o)
o = o or {}
o.on_init = o.on_init or function() end
if not o.channel then
error("no channel specified")
end
if not o.mode then
error("no mode specified")
end
o.subchannels = o.subchannels or {}
local url = "wss://spudnet.osmarks.net/v4?enc=json&force_binary=true"
local ws = nil
local api = {}
local since_last_ping = os.epoch"utc"
local init
for i,v in ipairs(o.subchannels) do
o.subchannels[i]=o.mode..":"..o.channel.."/"..v
end
local get_spudmsg = function(filter)
while true do
local e, url_, data = coroutine.yield("websocket_message")
data = textutils.unserializeJSON(data)
if url_ == url then
if not filter or filter == data.type then
return data
end
end
end
end
api.send_raw = function(data)
return p.add(function(this)
local x = pcall(ws.send,textutils.serializeJSON(data),true)
if not x then
p.clear()
p.add(init,{name="spudnet_init"})
end
end)
end
api.send_raw_sync = function(data)
local id = math.random(1,0xFFFFFF)
data.cid = id
p.await(api.send_raw(data))
while true do
local m = get_spudmsg("ok")
if m.cid == id then
return true
end
end
end
api.receive = function(filter)
while true do
local m = get_spudmsg("message").data
if filter then
if m.type == filter then
return m
end
else
return m
end
end
end
api.send = function(data,subchannel)
api.send_raw({
type="send",
data=data,
channel=o.mode..":"..o.channel.."/"..subchannel
})
end
api.send_sync = function(data,subchannel)
api.send_raw_sync({
type="send",
data=data,
channel=o.mode..":"..o.channel.."/"..subchannel
})
end
local error_handler = function()
while true do
local a = get_spudmsg("error")
if a.error == "timeout" then
p.clear()
p.add(init,{name="spudnet_init"})
else
error("Error from SPUDNET ('"..(a["error"] or a["for"]).."'): "..a.detail)
end
end
end
local ping_handler = function()
while true do
local a = get_spudmsg("ping").seq
since_last_ping = os.epoch"utc"
api.send_raw({
type="pong",
seq = a,
})
os.queueEvent("spudnet_ping",seq)
end
end
local terminate_handler = function()
local x = os.pullEventRaw("terminate")
if ws then ws.close() end
p.clear()
end
local timeout_handler = function()
while true do
sleep(1)
if os.epoch"utc" - since_last_ping >= 15000 then
p.clear()
p.add(init,{name="spudnet_init"})
os.queueEvent("spudnet_timeout")
end
end
end
init = function()
p.add(terminate_handler,{name="spudnet_termination_handler"})
if ws then ws.close() end
ws = nil
while true do
ws = http.websocket(url)
if ws then
break
end
sleep(0.3)
end
p.add(error_handler,{name="spudnet_error_handler"})
p.add(ping_handler,{name="spudnet_ping_handler"})
p.add(timeout_handler,{name="spudnet_timeout_handler"})
api.send_raw_sync({
type="identify",
key=o.key,
channels=o.subchannels,
})
p.add(o.on_init)
os.queueEvent("spudnet_ready")
end
p.add(init,{name="spudnet_init"})
return api,p.run
end
spudnet.pool = p
return spudnet

12
spudnet/pkgmeta.ltn Normal file
View File

@ -0,0 +1,12 @@
{
["version"] = "0.1.0",
["dependencies"] = {
"multitask",
},
["description"] = "Basic multitask-based spudnet interaction.",
["files"] = {
["lib"] = {
"spudnet.lua"
}
}
}