mirror of https://github.com/Ale32bit/Soqet.git
Compare commits
3 Commits
b3ba105f0c
...
8528b39f3a
Author | SHA1 | Date |
---|---|---|
Alessandro | 8528b39f3a | |
Alessandro | d53478bdcd | |
Alessandro | 0b39a16fc8 |
2
LICENSE
2
LICENSE
|
@ -1,6 +1,6 @@
|
|||
MIT License
|
||||
|
||||
Copyright (c) 2019 Alessandro
|
||||
Copyright (c) 2020 Alessandro
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
|
|
11
index.ts
11
index.ts
|
@ -30,6 +30,7 @@ interface Client {
|
|||
interface PollingClient extends Client {
|
||||
lastPing: number,
|
||||
queue: Array<any>,
|
||||
token: string,
|
||||
}
|
||||
|
||||
interface Channels {
|
||||
|
@ -428,6 +429,7 @@ pollingRouter.get("/connect", (req, res, next) => {
|
|||
client.client = req;
|
||||
|
||||
client.queue = [];
|
||||
client.token = sessionToken;
|
||||
|
||||
client.send = function (data: string | object) {
|
||||
if (typeof data === "string") data = JSON.parse(data);
|
||||
|
@ -457,11 +459,6 @@ pollingRouter.use("*", function (req, res, next) {
|
|||
})
|
||||
}
|
||||
|
||||
let client = clients[pollingTokens[sessionToken]] as PollingClient;
|
||||
|
||||
client.lastPing = Date.now();
|
||||
|
||||
clients[pollingTokens[sessionToken]] = client; // you're never 100% sure
|
||||
next();
|
||||
})
|
||||
|
||||
|
@ -547,6 +544,7 @@ pollingRouter.post("/update", (req, res, next) => {
|
|||
queue: client.queue,
|
||||
});
|
||||
|
||||
client.lastPing = Date.now();
|
||||
client.queue = [];
|
||||
})
|
||||
|
||||
|
@ -577,7 +575,10 @@ app.listen(config.port, () => {
|
|||
let v = clients[id] as PollingClient;
|
||||
|
||||
if ((Date.now() - v.lastPing) > 60000) {
|
||||
console.log("[POL]", `Client connected: ${id}`);
|
||||
let clientToken = (clients[id] as PollingClient).token;
|
||||
delete clients[id];
|
||||
delete pollingTokens[clientToken]
|
||||
}
|
||||
})
|
||||
}, 60000)
|
||||
|
|
|
@ -1,95 +0,0 @@
|
|||
local component = require("component")
|
||||
local modem = component.modem
|
||||
if not modem then
|
||||
error("Missing network card", 2)
|
||||
end
|
||||
|
||||
local serial = require("serialization")
|
||||
local event = require("event")
|
||||
|
||||
local soqet = {
|
||||
uuid = nil,
|
||||
running = false,
|
||||
|
||||
}
|
||||
local lastid
|
||||
|
||||
local function open()
|
||||
modem.open(1010)
|
||||
end
|
||||
|
||||
local function receive()
|
||||
if not modem.isOpen(1010) then
|
||||
open()
|
||||
end
|
||||
|
||||
while true do
|
||||
local ev = {event.pull(nil, "modem_message")}
|
||||
local ch = ev[4]
|
||||
local message = serial.unserialize(ev[6])
|
||||
--print(serial.serialize(message))
|
||||
soqet.uuid = message.uuid
|
||||
if lastid ~= message.mid then
|
||||
if message.message and message.channel and message.meta then
|
||||
lastid = message.mid
|
||||
return message.channel, message.message, message.meta
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function send(data)
|
||||
if not modem.isOpen(1010) then
|
||||
open()
|
||||
end
|
||||
modem.broadcast(1010, serial.serialize(data))
|
||||
end
|
||||
|
||||
function soqet.open(channel)
|
||||
send({
|
||||
type = "open",
|
||||
channel = channel,
|
||||
})
|
||||
end
|
||||
|
||||
function soqet.close(channel)
|
||||
send({
|
||||
type = "close",
|
||||
channel = channel,
|
||||
})
|
||||
end
|
||||
|
||||
function soqet.auth(token)
|
||||
send({
|
||||
type = "auth",
|
||||
token = token,
|
||||
})
|
||||
end
|
||||
|
||||
function soqet.send(channel, message, meta)
|
||||
send({
|
||||
type = "send",
|
||||
channel = channel,
|
||||
message = message,
|
||||
meta = meta,
|
||||
})
|
||||
end
|
||||
|
||||
function soqet.listen()
|
||||
open()
|
||||
soqet.running = true
|
||||
while soqet.running do
|
||||
event.push("soqet_message", receive())
|
||||
end
|
||||
end
|
||||
|
||||
function soqet.receive()
|
||||
open()
|
||||
return receive()
|
||||
end
|
||||
|
||||
function soqet.unlisten()
|
||||
soqet.running = false
|
||||
end
|
||||
|
||||
return soqet
|
46
oc/proxy.lua
46
oc/proxy.lua
|
@ -1,46 +0,0 @@
|
|||
local modem = peripheral.find("modem")
|
||||
modem.open(1010)
|
||||
|
||||
local soqet = require("soqet")
|
||||
|
||||
local function action(data)
|
||||
if data.type == "open" and data.channel then
|
||||
print("Opening " .. data.channel)
|
||||
soqet.open(data.channel)
|
||||
elseif data.type == "close" and data.channel then
|
||||
print("Closing " .. data.channel)
|
||||
soqet.close(data.channel)
|
||||
elseif data.type == "send" then
|
||||
print("Sending message...")
|
||||
soqet.send(data.channel, data.message, data.meta)
|
||||
elseif data.type == "auth" then
|
||||
print("Authenticating...")
|
||||
soqet.auth(data.token)
|
||||
end
|
||||
end
|
||||
|
||||
local function main()
|
||||
while true do
|
||||
local ev = {os.pullEvent()}
|
||||
|
||||
--for k,v in pairs(ev) do
|
||||
--print(k, v)
|
||||
--end
|
||||
|
||||
if ev[1] == "soqet_message" then
|
||||
modem.transmit(1010, 0, textutils.serialise({
|
||||
channel = ev[2],
|
||||
message = ev[3],
|
||||
meta = ev[4],
|
||||
uuid = soqet.uuid,
|
||||
mid = math.random(0,99999)
|
||||
}))
|
||||
|
||||
elseif ev[1] == "modem_message" and ev[3] == 1010 then
|
||||
local data = textutils.unserialize(ev[5])
|
||||
action(data)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
parallel.waitForAny(soqet.listen, main)
|
|
@ -0,0 +1,290 @@
|
|||
--[[
|
||||
-- OC_Soqet.lua --
|
||||
https://github.com/Ale32bit/Soqet/
|
||||
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2020 Alessandro
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
]] --
|
||||
|
||||
--[[
|
||||
-- json.lua --
|
||||
https://github.com/rxi/json.lua
|
||||
|
||||
Copyright (c) 2019 rxi
|
||||
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
this software and associated documentation files (the "Software"), to deal in
|
||||
the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do
|
||||
so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
]] --
|
||||
|
||||
local http = require("internet")
|
||||
local fs = require("filesystem")
|
||||
|
||||
if not http then
|
||||
error("Missing internet card", 2)
|
||||
end
|
||||
|
||||
local function _request(...)
|
||||
local handle = http.request(...)
|
||||
|
||||
handle.finishConnect()
|
||||
|
||||
local content = ""
|
||||
for chunk in handle do
|
||||
content = content .. chunk
|
||||
end
|
||||
return content
|
||||
end
|
||||
|
||||
local function get(url)
|
||||
return _request(url)
|
||||
end
|
||||
|
||||
local function post(url, data, headers)
|
||||
return _request(url, data, headers, "POST")
|
||||
end
|
||||
|
||||
if not fs.exists("/lib/json.lua") then
|
||||
local con = get("https://raw.githubusercontent.com/rxi/json.lua/master/json.lua")
|
||||
local f = io.open("/lib/json.lua", "w")
|
||||
f:write(con)
|
||||
f:close()
|
||||
end
|
||||
|
||||
local function expect(index, value, ...)
|
||||
local types = {...}
|
||||
|
||||
local valueType = type(value)
|
||||
|
||||
local valid = false
|
||||
for _, v in ipairs(types) do
|
||||
if valueType == v then
|
||||
valid = true
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
if not valid then
|
||||
error(("bad argument #%d (expected %s, got %s)"):format(index, table.concat(types, ", "), valueType), 3)
|
||||
end
|
||||
|
||||
return value
|
||||
end
|
||||
|
||||
local soqet = {
|
||||
ENDPOINT = "soqet.alexdevs.pw",
|
||||
ssl = false,
|
||||
json = require("json"),
|
||||
credits = "OC_Soqet.lua by AlexDevs"
|
||||
}
|
||||
|
||||
local function postJson(url, data)
|
||||
return _request(
|
||||
url,
|
||||
soqet.json.encode(data),
|
||||
{
|
||||
["Content-Type"] = "application/json"
|
||||
}
|
||||
)
|
||||
end
|
||||
|
||||
function soqet.new()
|
||||
error("WebSocket client is not supported. Use long polling instead.", 2)
|
||||
end
|
||||
|
||||
function soqet.poll()
|
||||
local client = {
|
||||
channels = {},
|
||||
uuid = nil,
|
||||
sessionId = math.random(0xffffff),
|
||||
sessionToken = nil,
|
||||
ssl = soqet.ssl,
|
||||
connected = false,
|
||||
listening = true,
|
||||
updateInterval = 1
|
||||
}
|
||||
|
||||
if ssl then
|
||||
client.ENDPOINT = "https://" .. soqet.ENDPOINT
|
||||
else
|
||||
client.ENDPOINT = "http://" .. soqet.ENDPOINT
|
||||
end
|
||||
|
||||
local function send(path, body)
|
||||
return postJson(client.ENDPOINT .. "/api/" .. path, body)
|
||||
end
|
||||
|
||||
local function rawreceive()
|
||||
if not client.connected then
|
||||
client.connect()
|
||||
end
|
||||
while true do
|
||||
local h =
|
||||
send(
|
||||
"update",
|
||||
{
|
||||
token = client.sessionToken
|
||||
}
|
||||
)
|
||||
|
||||
local data = soqet.json.decode(h)
|
||||
|
||||
local queue = {}
|
||||
|
||||
for i, v in ipairs(data.queue) do
|
||||
if v.type == "message" then
|
||||
table.insert(
|
||||
queue,
|
||||
{
|
||||
channel = v.channel,
|
||||
message = v.message,
|
||||
meta = v.meta
|
||||
}
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
if #queue > 0 then
|
||||
return queue
|
||||
else
|
||||
os.sleep(client.updateInterval)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function client.connect(token)
|
||||
if nil and type(token) ~= "string" then
|
||||
error("bad argument #1", 2)
|
||||
end
|
||||
local h = get(client.ENDPOINT .. "/api/connect?token=" .. (token or ""))
|
||||
|
||||
local data = soqet.json.decode(h)
|
||||
|
||||
client.uuid = data.uuid
|
||||
client.sessionToken = data.token
|
||||
client.motd = data.motd
|
||||
|
||||
client.connected = true
|
||||
|
||||
for i, v in pairs(client.channels) do
|
||||
client.open(v)
|
||||
end
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
function client.open(channel)
|
||||
expect(1, channel, "string", "number")
|
||||
|
||||
client.channels[#client.channels + 1] = channel
|
||||
|
||||
send(
|
||||
"open",
|
||||
{
|
||||
token = client.sessionToken,
|
||||
channel = channel
|
||||
}
|
||||
)
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
function client.close(channel)
|
||||
expect(1, channel, "string", "number")
|
||||
|
||||
for i, v in pairs(client.channels) do
|
||||
if v == channel then
|
||||
client.channels[i] = nil
|
||||
end
|
||||
end
|
||||
|
||||
send(
|
||||
"close",
|
||||
{
|
||||
token = client.sessionToken,
|
||||
channel = channel
|
||||
}
|
||||
)
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
function client.send(channel, message, meta)
|
||||
expect(1, channel, "string", "number")
|
||||
expect(3, meta, "nil", "table")
|
||||
|
||||
meta = meta or {}
|
||||
meta.library = meta.library or soqet.credits
|
||||
|
||||
send(
|
||||
"send",
|
||||
{
|
||||
token = client.sessionToken,
|
||||
channel = channel,
|
||||
message = message,
|
||||
meta = meta
|
||||
}
|
||||
)
|
||||
end
|
||||
|
||||
function client.receive()
|
||||
return rawreceive()
|
||||
end
|
||||
|
||||
function client.listen()
|
||||
client.listening = true
|
||||
while client.listening do
|
||||
local queue = rawreceive()
|
||||
|
||||
for i, v in ipairs(queue) do
|
||||
computer.pushSignal("soqet_message", v.channel, v.message, v.meta, client.sessionId)
|
||||
end
|
||||
|
||||
sleep(client.updateInterval)
|
||||
end
|
||||
end
|
||||
|
||||
function client.unlisten()
|
||||
client.listening = false
|
||||
return true
|
||||
end
|
||||
|
||||
return client
|
||||
end
|
||||
|
||||
return soqet
|
|
@ -297,7 +297,7 @@
|
|||
<code>token</code> field.</p>
|
||||
<p>Field <code>motd</code> is also supplied upon connection.</p>
|
||||
|
||||
<p><b>Once connected you need to request at least once every 60 seconds to keep the session token alive!</b>
|
||||
<p><b>Once connected you need to request <code>/api/update</code> at least once every 60 seconds to keep the session token alive!</b>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
|
@ -487,7 +487,7 @@
|
|||
<tr>
|
||||
<td>motd</td>
|
||||
<td>string</td>
|
||||
<td><i>Any message the </i></td>
|
||||
<td><i>Inspiring quotes to help the developer and the user get over problems and easily achieve life goals.</i></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
|
|
475
soqet.lua
475
soqet.lua
|
@ -4,7 +4,7 @@ https://github.com/Ale32bit/Soqet/
|
|||
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2019 Alessandro
|
||||
Copyright (c) 2020 Alessandro
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
|
@ -23,7 +23,7 @@ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
]]--
|
||||
]] --
|
||||
|
||||
--[[
|
||||
-- json.lua --
|
||||
|
@ -50,220 +50,361 @@ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
]]--
|
||||
]] --
|
||||
|
||||
local h = http.get("https://raw.githubusercontent.com/rxi/json.lua/master/json.lua")
|
||||
local f = fs.open("json.lua", "w")
|
||||
f.write(h.readAll())
|
||||
f.close()
|
||||
h.close()
|
||||
|
||||
local json = require("json")
|
||||
local expect = dofile("rom/modules/main/cc/expect.lua").expect
|
||||
|
||||
local soqet = {
|
||||
ENDPOINT = "wss://soqet.alexdevs.pw",
|
||||
channels = {},
|
||||
socket = nil,
|
||||
running = false,
|
||||
uuid = nil,
|
||||
sessionId = nil,
|
||||
ENDPOINT = "soqet.alexdevs.pw",
|
||||
ssl = true,
|
||||
json = json,
|
||||
credits = "Soqet.lua v2 by AlexDevs"
|
||||
}
|
||||
|
||||
local function send(data)
|
||||
if not soqet.socket then
|
||||
soqet.connect()
|
||||
if not soqet.json then
|
||||
if not fs.exists("json.lua") then
|
||||
local h = http.get("https://raw.githubusercontent.com/rxi/json.lua/master/json.lua")
|
||||
local f = fs.open("json.lua", "w")
|
||||
f.write(h.readAll())
|
||||
f.close()
|
||||
h.close()
|
||||
end
|
||||
|
||||
return soqet.socket.send(json.encode(data))
|
||||
soqet.json = require("json")
|
||||
end
|
||||
|
||||
local function receive()
|
||||
if not soqet.socket then
|
||||
soqet.connect()
|
||||
function soqet.new()
|
||||
if not http then
|
||||
return false, "HTTP is not enabled!"
|
||||
end
|
||||
|
||||
while true do
|
||||
local data = soqet.socket.receive()
|
||||
if not http.websocket then
|
||||
return false, "HTTP WebSocket feature is not enabled!"
|
||||
end
|
||||
|
||||
data = json.decode(data)
|
||||
soqet.uuid = data.uuid
|
||||
if data.type == "message" then
|
||||
local message = data.message
|
||||
local channel = data.channel
|
||||
local meta = data.meta
|
||||
local client = {
|
||||
channels = {},
|
||||
uuid = nil,
|
||||
socket = nil,
|
||||
sessionId = math.random(0xffffff),
|
||||
ssl = soqet.ssl
|
||||
}
|
||||
|
||||
return channel, message, meta
|
||||
elseif data.type == "ping" then
|
||||
send({
|
||||
type = "ping",
|
||||
id = 5,
|
||||
})
|
||||
local function rawsend(data)
|
||||
if not client.socket then
|
||||
return false
|
||||
end
|
||||
|
||||
client.socket.send(soqet.json.encode(data))
|
||||
return true
|
||||
end
|
||||
|
||||
local function rawreceive()
|
||||
if not client.socket then
|
||||
client.connect()
|
||||
end
|
||||
|
||||
while true do
|
||||
local data = client.socket.receive()
|
||||
|
||||
data = soqet.json.decode(data)
|
||||
|
||||
client.uuid = data.uuid
|
||||
|
||||
if data.type == "ping" then
|
||||
rawsend(
|
||||
{
|
||||
type = "ping",
|
||||
id = 99
|
||||
}
|
||||
)
|
||||
elseif data.type == "motd" then
|
||||
client.motd = data.motd
|
||||
elseif data.type == "message" then
|
||||
return data.channel, data.message, data.meta
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function soqet.connect()
|
||||
assert(http.websocket, "WebSocket not enabled or not compatible with this ComputerCraft version.")
|
||||
soqet.sessionId = tostring(math.random(0xffffff))
|
||||
local socket, err = http.websocket(soqet.ENDPOINT .. "/" .. soqet.sessionId)
|
||||
if not socket then
|
||||
error(err, 1);
|
||||
end
|
||||
soqet.socket = socket;
|
||||
end
|
||||
|
||||
function soqet.open(channel)
|
||||
send({
|
||||
type = "open",
|
||||
channel = channel,
|
||||
id = 2,
|
||||
})
|
||||
end
|
||||
|
||||
function soqet.close(channel)
|
||||
send({
|
||||
type = "close",
|
||||
channel = channel,
|
||||
id = 3,
|
||||
})
|
||||
end
|
||||
|
||||
function soqet.auth(token)
|
||||
send({
|
||||
type = "auth",
|
||||
token = token,
|
||||
id = 4,
|
||||
})
|
||||
end
|
||||
|
||||
function soqet.send(channel, message, meta)
|
||||
send({
|
||||
type = "send",
|
||||
channel = channel,
|
||||
message = message,
|
||||
meta = meta or {},
|
||||
id = 1,
|
||||
})
|
||||
end
|
||||
|
||||
function soqet.receive()
|
||||
return receive()
|
||||
end
|
||||
|
||||
function soqet.listen()
|
||||
soqet.running = true
|
||||
while soqet.running do
|
||||
local channel, message, meta = receive()
|
||||
os.queueEvent("soqet_message", channel, message, meta)
|
||||
end
|
||||
end
|
||||
|
||||
function soqet.unlisten()
|
||||
soqet.running = false
|
||||
end
|
||||
|
||||
soqet.polling = {
|
||||
host = "https://soqet.alexdevs.pw",
|
||||
token = nil,
|
||||
uuid = nil,
|
||||
motd = "soqet",
|
||||
connected = false,
|
||||
};
|
||||
|
||||
function soqet.polling.connect(token)
|
||||
local h, err = http.get(soqet.polling.host .. "/api/connect?token=" .. textutils.urlEncode(token));
|
||||
if not h then
|
||||
return false, err
|
||||
if ssl then
|
||||
client.ENDPOINT = "wss://" .. soqet.ENDPOINT .. "/" .. client.sessionId
|
||||
else
|
||||
client.ENDPOINT = "ws://" .. soqet.ENDPOINT .. "/" .. client.sessionId
|
||||
end
|
||||
|
||||
local result = json.decode(h.readAll())
|
||||
function client.connect()
|
||||
if client.socket then
|
||||
pcall(client.socket.close)
|
||||
end
|
||||
|
||||
if not result.ok then
|
||||
return false, result.error
|
||||
local socket, err = http.websocket(client.ENDPOINT)
|
||||
if not socket then
|
||||
return false, err
|
||||
end
|
||||
|
||||
client.socket = socket
|
||||
|
||||
for i, v in pairs(client.channels) do
|
||||
client.open(v)
|
||||
end
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
soqet.polling.token = result.token
|
||||
soqet.polling.motd = result.motd
|
||||
soqet.polling.connected = true
|
||||
function client.open(channel)
|
||||
expect(1, channel, "string", "number")
|
||||
|
||||
return true
|
||||
client.channels[#client.channels + 1] = channel
|
||||
|
||||
return rawsend(
|
||||
{
|
||||
type = "open",
|
||||
channel = channel
|
||||
}
|
||||
)
|
||||
end
|
||||
|
||||
function client.close(channel)
|
||||
expect(1, channel, "string", "number")
|
||||
|
||||
for i, v in pairs(client.channels) do
|
||||
if v == channel then
|
||||
client.channels[i] = nil
|
||||
end
|
||||
end
|
||||
|
||||
return rawsend(
|
||||
{
|
||||
type = "close",
|
||||
channel = channel
|
||||
}
|
||||
)
|
||||
end
|
||||
|
||||
function client.send(channel, message, meta)
|
||||
expect(1, channel, "string", "number")
|
||||
expect(3, meta, "nil", "table")
|
||||
|
||||
meta = meta or {}
|
||||
meta.library = meta.library or soqet.credits
|
||||
|
||||
return rawsend(
|
||||
{
|
||||
type = "send",
|
||||
channel = channel,
|
||||
message = message,
|
||||
meta = meta
|
||||
}
|
||||
)
|
||||
end
|
||||
|
||||
function client.auth(token)
|
||||
expect(1, token, "string")
|
||||
|
||||
return rawsend(
|
||||
{
|
||||
type = "auth",
|
||||
token = token
|
||||
}
|
||||
)
|
||||
end
|
||||
|
||||
function client.receive()
|
||||
return rawreceive()
|
||||
end
|
||||
|
||||
function client.listen()
|
||||
client.listening = true
|
||||
while client.listening do
|
||||
local channel, message, meta = rawreceive()
|
||||
os.queueEvent("soqet_message", channel, message, meta, client.sessionId)
|
||||
end
|
||||
return true
|
||||
end
|
||||
|
||||
function client.unlisten()
|
||||
client.listening = false
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
return client, client.sessionId
|
||||
end
|
||||
|
||||
function soqet.polling.update()
|
||||
local h, err = http.post(soqet.polling.host .. "/api/update", textutils.serialiseJSON({
|
||||
token = soqet.polling.token,
|
||||
}))
|
||||
function soqet.poll(token)
|
||||
local client = {
|
||||
channels = {},
|
||||
uuid = nil,
|
||||
sessionId = math.random(0xffffff),
|
||||
sessionToken = nil,
|
||||
ssl = soqet.ssl,
|
||||
connected = false,
|
||||
listening = true,
|
||||
updateInterval = 1
|
||||
}
|
||||
|
||||
if not h then
|
||||
return false, err
|
||||
if ssl then
|
||||
client.ENDPOINT = "https://" .. soqet.ENDPOINT
|
||||
else
|
||||
client.ENDPOINT = "http://" .. soqet.ENDPOINT
|
||||
end
|
||||
|
||||
local result = json.decode(h.readAll());
|
||||
|
||||
if not result.ok then
|
||||
return false, result.err
|
||||
local function postJson(path, body)
|
||||
return http.post(
|
||||
client.ENDPOINT .. "/api/" .. path,
|
||||
soqet.json.encode(body),
|
||||
{
|
||||
["Content-Type"] = "application/json"
|
||||
}
|
||||
)
|
||||
end
|
||||
|
||||
return result.queue
|
||||
end
|
||||
local function rawreceive()
|
||||
if not client.connected then
|
||||
client.connect()
|
||||
end
|
||||
while true do
|
||||
local h, err =
|
||||
postJson(
|
||||
"update",
|
||||
{
|
||||
token = client.sessionToken
|
||||
}
|
||||
)
|
||||
|
||||
function soqet.polling.open(channel)
|
||||
local h, err = http.post(soqet.polling.host .. "/api/open", textutils.serialiseJSON({
|
||||
token = soqet.polling.token,
|
||||
channel = channel,
|
||||
}))
|
||||
if not h then
|
||||
error(err)
|
||||
end
|
||||
|
||||
if not h then
|
||||
return false, err
|
||||
local data = soqet.json.decode(h.readAll())
|
||||
h.close()
|
||||
|
||||
local queue = {}
|
||||
|
||||
for i, v in ipairs(data.queue) do
|
||||
if v.type == "message" then
|
||||
table.insert(
|
||||
queue,
|
||||
{
|
||||
channel = v.channel,
|
||||
message = v.message,
|
||||
meta = v.meta
|
||||
}
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
if #queue > 0 then
|
||||
return queue
|
||||
else
|
||||
sleep(client.updateInterval)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local result = json.decode(h.readAll());
|
||||
function client.connect(token)
|
||||
expect(1, token, "nil", "string")
|
||||
|
||||
if not result.ok then
|
||||
return false, result.err
|
||||
local h, err, eh = http.get(client.ENDPOINT .. "/api/connect?token=" .. textutils.urlEncode(token or ""))
|
||||
|
||||
if not h then
|
||||
return false, err, eh
|
||||
end
|
||||
|
||||
local data = soqet.json.decode(h.readAll())
|
||||
|
||||
h.close()
|
||||
|
||||
client.uuid = data.uuid
|
||||
client.sessionToken = data.token
|
||||
client.motd = data.motd
|
||||
|
||||
client.connected = true
|
||||
|
||||
for i, v in pairs(client.channels) do
|
||||
client.open(v)
|
||||
end
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
return true
|
||||
end
|
||||
function client.open(channel)
|
||||
expect(1, channel, "string", "number")
|
||||
|
||||
function soqet.polling.close(channel)
|
||||
local h, err = http.post(soqet.polling.host .. "/api/close", textutils.serialiseJSON({
|
||||
token = soqet.polling.token,
|
||||
channel = channel,
|
||||
}))
|
||||
client.channels[#client.channels + 1] = channel
|
||||
|
||||
if not h then
|
||||
return false, err
|
||||
postJson(
|
||||
"open",
|
||||
{
|
||||
token = client.sessionToken,
|
||||
channel = channel
|
||||
}
|
||||
)
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
local result = json.decode(h.readAll());
|
||||
function client.close(channel)
|
||||
expect(1, channel, "string", "number")
|
||||
|
||||
if not result.ok then
|
||||
return false, result.err
|
||||
for i, v in pairs(client.channels) do
|
||||
if v == channel then
|
||||
client.channels[i] = nil
|
||||
end
|
||||
end
|
||||
|
||||
postJson(
|
||||
"close",
|
||||
{
|
||||
token = client.sessionToken,
|
||||
channel = channel
|
||||
}
|
||||
)
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
return true
|
||||
end
|
||||
function client.send(channel, message, meta)
|
||||
expect(1, channel, "string", "number")
|
||||
expect(3, meta, "nil", "table")
|
||||
|
||||
function soqet.polling.send(channel, message, meta)
|
||||
local h, err = http.post(soqet.polling.host .. "/api/send", textutils.serialiseJSON({
|
||||
token = soqet.polling.token,
|
||||
channel = channel,
|
||||
message = message,
|
||||
meta = meta,
|
||||
}))
|
||||
meta = meta or {}
|
||||
meta.library = meta.library or soqet.credits
|
||||
|
||||
if not h then
|
||||
return false, err
|
||||
postJson(
|
||||
"send",
|
||||
{
|
||||
token = client.sessionToken,
|
||||
channel = channel,
|
||||
message = message,
|
||||
meta = meta
|
||||
}
|
||||
)
|
||||
end
|
||||
|
||||
local result = json.decode(h.readAll());
|
||||
|
||||
if not result.ok then
|
||||
return false, result.err
|
||||
function client.receive()
|
||||
return rawreceive()
|
||||
end
|
||||
|
||||
return true
|
||||
function client.listen()
|
||||
client.listening = true
|
||||
while client.listening do
|
||||
local queue = rawreceive()
|
||||
|
||||
for i, v in ipairs(queue) do
|
||||
os.queueEvent("soqet_message", v.channel, v.message, v.meta, client.sessionId)
|
||||
end
|
||||
|
||||
sleep(client.updateInterval)
|
||||
end
|
||||
end
|
||||
|
||||
function client.unlisten()
|
||||
client.listening = false
|
||||
return true
|
||||
end
|
||||
|
||||
return client
|
||||
end
|
||||
|
||||
return soqet
|
||||
|
|
Loading…
Reference in New Issue