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
|
MIT License
|
||||||
|
|
||||||
Copyright (c) 2019 Alessandro
|
Copyright (c) 2020 Alessandro
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
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 {
|
interface PollingClient extends Client {
|
||||||
lastPing: number,
|
lastPing: number,
|
||||||
queue: Array<any>,
|
queue: Array<any>,
|
||||||
|
token: string,
|
||||||
}
|
}
|
||||||
|
|
||||||
interface Channels {
|
interface Channels {
|
||||||
|
@ -428,6 +429,7 @@ pollingRouter.get("/connect", (req, res, next) => {
|
||||||
client.client = req;
|
client.client = req;
|
||||||
|
|
||||||
client.queue = [];
|
client.queue = [];
|
||||||
|
client.token = sessionToken;
|
||||||
|
|
||||||
client.send = function (data: string | object) {
|
client.send = function (data: string | object) {
|
||||||
if (typeof data === "string") data = JSON.parse(data);
|
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();
|
next();
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -547,6 +544,7 @@ pollingRouter.post("/update", (req, res, next) => {
|
||||||
queue: client.queue,
|
queue: client.queue,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
client.lastPing = Date.now();
|
||||||
client.queue = [];
|
client.queue = [];
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -577,7 +575,10 @@ app.listen(config.port, () => {
|
||||||
let v = clients[id] as PollingClient;
|
let v = clients[id] as PollingClient;
|
||||||
|
|
||||||
if ((Date.now() - v.lastPing) > 60000) {
|
if ((Date.now() - v.lastPing) > 60000) {
|
||||||
|
console.log("[POL]", `Client connected: ${id}`);
|
||||||
|
let clientToken = (clients[id] as PollingClient).token;
|
||||||
delete clients[id];
|
delete clients[id];
|
||||||
|
delete pollingTokens[clientToken]
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}, 60000)
|
}, 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>
|
<code>token</code> field.</p>
|
||||||
<p>Field <code>motd</code> is also supplied upon connection.</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>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -487,7 +487,7 @@
|
||||||
<tr>
|
<tr>
|
||||||
<td>motd</td>
|
<td>motd</td>
|
||||||
<td>string</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>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
|
|
437
soqet.lua
437
soqet.lua
|
@ -4,7 +4,7 @@ https://github.com/Ale32bit/Soqet/
|
||||||
|
|
||||||
MIT License
|
MIT License
|
||||||
|
|
||||||
Copyright (c) 2019 Alessandro
|
Copyright (c) 2020 Alessandro
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
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,
|
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
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
SOFTWARE.
|
SOFTWARE.
|
||||||
]]--
|
]] --
|
||||||
|
|
||||||
--[[
|
--[[
|
||||||
-- json.lua --
|
-- 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
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
SOFTWARE.
|
SOFTWARE.
|
||||||
|
|
||||||
]]--
|
]] --
|
||||||
|
|
||||||
local h = http.get("https://raw.githubusercontent.com/rxi/json.lua/master/json.lua")
|
local expect = dofile("rom/modules/main/cc/expect.lua").expect
|
||||||
local f = fs.open("json.lua", "w")
|
|
||||||
f.write(h.readAll())
|
|
||||||
f.close()
|
|
||||||
h.close()
|
|
||||||
|
|
||||||
local json = require("json")
|
|
||||||
|
|
||||||
local soqet = {
|
local soqet = {
|
||||||
ENDPOINT = "wss://soqet.alexdevs.pw",
|
ENDPOINT = "soqet.alexdevs.pw",
|
||||||
channels = {},
|
ssl = true,
|
||||||
socket = nil,
|
json = json,
|
||||||
running = false,
|
credits = "Soqet.lua v2 by AlexDevs"
|
||||||
uuid = nil,
|
|
||||||
sessionId = nil,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
local function send(data)
|
if not soqet.json then
|
||||||
if not soqet.socket then
|
if not fs.exists("json.lua") then
|
||||||
soqet.connect()
|
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
|
end
|
||||||
|
|
||||||
return soqet.socket.send(json.encode(data))
|
soqet.json = require("json")
|
||||||
end
|
end
|
||||||
|
|
||||||
local function receive()
|
function soqet.new()
|
||||||
if not soqet.socket then
|
if not http then
|
||||||
soqet.connect()
|
return false, "HTTP is not enabled!"
|
||||||
|
end
|
||||||
|
|
||||||
|
if not http.websocket then
|
||||||
|
return false, "HTTP WebSocket feature is not enabled!"
|
||||||
|
end
|
||||||
|
|
||||||
|
local client = {
|
||||||
|
channels = {},
|
||||||
|
uuid = nil,
|
||||||
|
socket = nil,
|
||||||
|
sessionId = math.random(0xffffff),
|
||||||
|
ssl = soqet.ssl
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
end
|
||||||
|
|
||||||
while true do
|
while true do
|
||||||
local data = soqet.socket.receive()
|
local data = client.socket.receive()
|
||||||
|
|
||||||
data = json.decode(data)
|
data = soqet.json.decode(data)
|
||||||
soqet.uuid = data.uuid
|
|
||||||
if data.type == "message" then
|
|
||||||
local message = data.message
|
|
||||||
local channel = data.channel
|
|
||||||
local meta = data.meta
|
|
||||||
|
|
||||||
return channel, message, meta
|
client.uuid = data.uuid
|
||||||
elseif data.type == "ping" then
|
|
||||||
send({
|
if data.type == "ping" then
|
||||||
|
rawsend(
|
||||||
|
{
|
||||||
type = "ping",
|
type = "ping",
|
||||||
id = 5,
|
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
|
end
|
||||||
end
|
|
||||||
|
|
||||||
function soqet.connect()
|
if ssl then
|
||||||
assert(http.websocket, "WebSocket not enabled or not compatible with this ComputerCraft version.")
|
client.ENDPOINT = "wss://" .. soqet.ENDPOINT .. "/" .. client.sessionId
|
||||||
soqet.sessionId = tostring(math.random(0xffffff))
|
else
|
||||||
local socket, err = http.websocket(soqet.ENDPOINT .. "/" .. soqet.sessionId)
|
client.ENDPOINT = "ws://" .. soqet.ENDPOINT .. "/" .. client.sessionId
|
||||||
|
end
|
||||||
|
|
||||||
|
function client.connect()
|
||||||
|
if client.socket then
|
||||||
|
pcall(client.socket.close)
|
||||||
|
end
|
||||||
|
|
||||||
|
local socket, err = http.websocket(client.ENDPOINT)
|
||||||
if not socket then
|
if not socket then
|
||||||
error(err, 1);
|
return false, err
|
||||||
end
|
end
|
||||||
soqet.socket = socket;
|
|
||||||
end
|
|
||||||
|
|
||||||
function soqet.open(channel)
|
client.socket = socket
|
||||||
send({
|
|
||||||
|
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
|
||||||
|
|
||||||
|
return rawsend(
|
||||||
|
{
|
||||||
type = "open",
|
type = "open",
|
||||||
channel = channel,
|
channel = channel
|
||||||
id = 2,
|
}
|
||||||
})
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
function soqet.close(channel)
|
function client.close(channel)
|
||||||
send({
|
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",
|
type = "close",
|
||||||
channel = channel,
|
channel = channel
|
||||||
id = 3,
|
}
|
||||||
})
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
function soqet.auth(token)
|
function client.send(channel, message, meta)
|
||||||
send({
|
expect(1, channel, "string", "number")
|
||||||
type = "auth",
|
expect(3, meta, "nil", "table")
|
||||||
token = token,
|
|
||||||
id = 4,
|
|
||||||
})
|
|
||||||
end
|
|
||||||
|
|
||||||
function soqet.send(channel, message, meta)
|
meta = meta or {}
|
||||||
send({
|
meta.library = meta.library or soqet.credits
|
||||||
|
|
||||||
|
return rawsend(
|
||||||
|
{
|
||||||
type = "send",
|
type = "send",
|
||||||
channel = channel,
|
channel = channel,
|
||||||
message = message,
|
message = message,
|
||||||
meta = meta or {},
|
meta = meta
|
||||||
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 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
|
end
|
||||||
|
|
||||||
function soqet.unlisten()
|
function soqet.poll(token)
|
||||||
soqet.running = false
|
local client = {
|
||||||
end
|
channels = {},
|
||||||
|
|
||||||
soqet.polling = {
|
|
||||||
host = "https://soqet.alexdevs.pw",
|
|
||||||
token = nil,
|
|
||||||
uuid = nil,
|
uuid = nil,
|
||||||
motd = "soqet",
|
sessionId = math.random(0xffffff),
|
||||||
|
sessionToken = nil,
|
||||||
|
ssl = soqet.ssl,
|
||||||
connected = false,
|
connected = false,
|
||||||
};
|
listening = true,
|
||||||
|
updateInterval = 1
|
||||||
|
}
|
||||||
|
|
||||||
function soqet.polling.connect(token)
|
if ssl then
|
||||||
local h, err = http.get(soqet.polling.host .. "/api/connect?token=" .. textutils.urlEncode(token));
|
client.ENDPOINT = "https://" .. soqet.ENDPOINT
|
||||||
if not h then
|
else
|
||||||
return false, err
|
client.ENDPOINT = "http://" .. soqet.ENDPOINT
|
||||||
end
|
end
|
||||||
|
|
||||||
local result = json.decode(h.readAll())
|
local function postJson(path, body)
|
||||||
|
return http.post(
|
||||||
if not result.ok then
|
client.ENDPOINT .. "/api/" .. path,
|
||||||
return false, result.error
|
soqet.json.encode(body),
|
||||||
|
{
|
||||||
|
["Content-Type"] = "application/json"
|
||||||
|
}
|
||||||
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
soqet.polling.token = result.token
|
local function rawreceive()
|
||||||
soqet.polling.motd = result.motd
|
if not client.connected then
|
||||||
soqet.polling.connected = true
|
client.connect()
|
||||||
|
end
|
||||||
return true
|
while true do
|
||||||
end
|
local h, err =
|
||||||
|
postJson(
|
||||||
function soqet.polling.update()
|
"update",
|
||||||
local h, err = http.post(soqet.polling.host .. "/api/update", textutils.serialiseJSON({
|
{
|
||||||
token = soqet.polling.token,
|
token = client.sessionToken
|
||||||
}))
|
}
|
||||||
|
)
|
||||||
|
|
||||||
if not h then
|
if not h then
|
||||||
return false, err
|
error(err)
|
||||||
end
|
end
|
||||||
|
|
||||||
local result = json.decode(h.readAll());
|
local data = soqet.json.decode(h.readAll())
|
||||||
|
h.close()
|
||||||
|
|
||||||
if not result.ok then
|
local queue = {}
|
||||||
return false, result.err
|
|
||||||
|
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
|
end
|
||||||
|
|
||||||
return result.queue
|
if #queue > 0 then
|
||||||
end
|
return queue
|
||||||
|
else
|
||||||
|
sleep(client.updateInterval)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
function soqet.polling.open(channel)
|
function client.connect(token)
|
||||||
local h, err = http.post(soqet.polling.host .. "/api/open", textutils.serialiseJSON({
|
expect(1, token, "nil", "string")
|
||||||
token = soqet.polling.token,
|
|
||||||
channel = channel,
|
local h, err, eh = http.get(client.ENDPOINT .. "/api/connect?token=" .. textutils.urlEncode(token or ""))
|
||||||
}))
|
|
||||||
|
|
||||||
if not h then
|
if not h then
|
||||||
return false, err
|
return false, err, eh
|
||||||
end
|
end
|
||||||
|
|
||||||
local result = json.decode(h.readAll());
|
local data = soqet.json.decode(h.readAll())
|
||||||
|
|
||||||
if not result.ok then
|
h.close()
|
||||||
return false, result.err
|
|
||||||
|
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
|
end
|
||||||
|
|
||||||
return true
|
return true
|
||||||
end
|
|
||||||
|
|
||||||
function soqet.polling.close(channel)
|
|
||||||
local h, err = http.post(soqet.polling.host .. "/api/close", textutils.serialiseJSON({
|
|
||||||
token = soqet.polling.token,
|
|
||||||
channel = channel,
|
|
||||||
}))
|
|
||||||
|
|
||||||
if not h then
|
|
||||||
return false, err
|
|
||||||
end
|
end
|
||||||
|
|
||||||
local result = json.decode(h.readAll());
|
function client.open(channel)
|
||||||
|
expect(1, channel, "string", "number")
|
||||||
|
|
||||||
if not result.ok then
|
client.channels[#client.channels + 1] = channel
|
||||||
return false, result.err
|
|
||||||
end
|
postJson(
|
||||||
|
"open",
|
||||||
|
{
|
||||||
|
token = client.sessionToken,
|
||||||
|
channel = channel
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
function soqet.polling.send(channel, message, meta)
|
function client.close(channel)
|
||||||
local h, err = http.post(soqet.polling.host .. "/api/send", textutils.serialiseJSON({
|
expect(1, channel, "string", "number")
|
||||||
token = soqet.polling.token,
|
|
||||||
|
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
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
postJson(
|
||||||
|
"send",
|
||||||
|
{
|
||||||
|
token = client.sessionToken,
|
||||||
channel = channel,
|
channel = channel,
|
||||||
message = message,
|
message = message,
|
||||||
meta = meta,
|
meta = meta
|
||||||
}))
|
}
|
||||||
|
)
|
||||||
if not h then
|
|
||||||
return false, err
|
|
||||||
end
|
end
|
||||||
|
|
||||||
local result = json.decode(h.readAll());
|
function client.receive()
|
||||||
|
return rawreceive()
|
||||||
if not result.ok then
|
|
||||||
return false, result.err
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
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
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
|
return client
|
||||||
end
|
end
|
||||||
|
|
||||||
return soqet
|
return soqet
|
||||||
|
|
Loading…
Reference in New Issue