mirror of https://github.com/Ale32bit/Soqet.git
Compare commits
No commits in common. "8528b39f3a15e07d579a7979fc8495bfdf6e1a74" and "b3ba105f0cf0d8d5d098f2e332fa0be719710d5c" have entirely different histories.
8528b39f3a
...
b3ba105f0c
2
LICENSE
2
LICENSE
|
@ -1,6 +1,6 @@
|
||||||
MIT License
|
MIT License
|
||||||
|
|
||||||
Copyright (c) 2020 Alessandro
|
Copyright (c) 2019 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,7 +30,6 @@ 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 {
|
||||||
|
@ -429,7 +428,6 @@ 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);
|
||||||
|
@ -459,6 +457,11 @@ 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();
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -544,7 +547,6 @@ pollingRouter.post("/update", (req, res, next) => {
|
||||||
queue: client.queue,
|
queue: client.queue,
|
||||||
});
|
});
|
||||||
|
|
||||||
client.lastPing = Date.now();
|
|
||||||
client.queue = [];
|
client.queue = [];
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -575,10 +577,7 @@ 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)
|
||||||
|
|
|
@ -0,0 +1,95 @@
|
||||||
|
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
|
|
@ -0,0 +1,46 @@
|
||||||
|
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)
|
290
oc_soqet.lua
290
oc_soqet.lua
|
@ -1,290 +0,0 @@
|
||||||
--[[
|
|
||||||
-- 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 <code>/api/update</code> at least once every 60 seconds to keep the session token alive!</b>
|
<p><b>Once connected you need to request 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>Inspiring quotes to help the developer and the user get over problems and easily achieve life goals.</i></td>
|
<td><i>Any message the </i></td>
|
||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
|
|
439
soqet.lua
439
soqet.lua
|
@ -4,7 +4,7 @@ https://github.com/Ale32bit/Soqet/
|
||||||
|
|
||||||
MIT License
|
MIT License
|
||||||
|
|
||||||
Copyright (c) 2020 Alessandro
|
Copyright (c) 2019 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,361 +50,220 @@ 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 expect = dofile("rom/modules/main/cc/expect.lua").expect
|
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 soqet = {
|
local soqet = {
|
||||||
ENDPOINT = "soqet.alexdevs.pw",
|
ENDPOINT = "wss://soqet.alexdevs.pw",
|
||||||
ssl = true,
|
channels = {},
|
||||||
json = json,
|
socket = nil,
|
||||||
credits = "Soqet.lua v2 by AlexDevs"
|
running = false,
|
||||||
|
uuid = nil,
|
||||||
|
sessionId = nil,
|
||||||
}
|
}
|
||||||
|
|
||||||
if not soqet.json then
|
local function send(data)
|
||||||
if not fs.exists("json.lua") then
|
if not soqet.socket then
|
||||||
local h = http.get("https://raw.githubusercontent.com/rxi/json.lua/master/json.lua")
|
soqet.connect()
|
||||||
local f = fs.open("json.lua", "w")
|
|
||||||
f.write(h.readAll())
|
|
||||||
f.close()
|
|
||||||
h.close()
|
|
||||||
end
|
end
|
||||||
|
|
||||||
soqet.json = require("json")
|
return soqet.socket.send(json.encode(data))
|
||||||
end
|
end
|
||||||
|
|
||||||
function soqet.new()
|
local function receive()
|
||||||
if not http then
|
if not soqet.socket then
|
||||||
return false, "HTTP is not enabled!"
|
soqet.connect()
|
||||||
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 = client.socket.receive()
|
local data = soqet.socket.receive()
|
||||||
|
|
||||||
data = soqet.json.decode(data)
|
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
|
||||||
|
|
||||||
client.uuid = data.uuid
|
return channel, message, meta
|
||||||
|
elseif data.type == "ping" then
|
||||||
if data.type == "ping" then
|
send({
|
||||||
rawsend(
|
|
||||||
{
|
|
||||||
type = "ping",
|
type = "ping",
|
||||||
id = 99
|
id = 5,
|
||||||
}
|
})
|
||||||
)
|
|
||||||
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
|
||||||
|
|
||||||
if ssl then
|
function soqet.connect()
|
||||||
client.ENDPOINT = "wss://" .. soqet.ENDPOINT .. "/" .. client.sessionId
|
assert(http.websocket, "WebSocket not enabled or not compatible with this ComputerCraft version.")
|
||||||
else
|
soqet.sessionId = tostring(math.random(0xffffff))
|
||||||
client.ENDPOINT = "ws://" .. soqet.ENDPOINT .. "/" .. client.sessionId
|
local socket, err = http.websocket(soqet.ENDPOINT .. "/" .. soqet.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
|
||||||
return false, err
|
error(err, 1);
|
||||||
end
|
end
|
||||||
|
soqet.socket = socket;
|
||||||
|
end
|
||||||
|
|
||||||
client.socket = socket
|
function soqet.open(channel)
|
||||||
|
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 client.close(channel)
|
function soqet.close(channel)
|
||||||
expect(1, channel, "string", "number")
|
send({
|
||||||
|
|
||||||
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 client.send(channel, message, meta)
|
function soqet.auth(token)
|
||||||
expect(1, channel, "string", "number")
|
send({
|
||||||
expect(3, meta, "nil", "table")
|
type = "auth",
|
||||||
|
token = token,
|
||||||
|
id = 4,
|
||||||
|
})
|
||||||
|
end
|
||||||
|
|
||||||
meta = meta or {}
|
function soqet.send(channel, message, meta)
|
||||||
meta.library = meta.library or soqet.credits
|
send({
|
||||||
|
|
||||||
return rawsend(
|
|
||||||
{
|
|
||||||
type = "send",
|
type = "send",
|
||||||
channel = channel,
|
channel = channel,
|
||||||
message = message,
|
message = message,
|
||||||
meta = meta
|
meta = meta or {},
|
||||||
}
|
id = 1,
|
||||||
)
|
})
|
||||||
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.poll(token)
|
function soqet.receive()
|
||||||
local client = {
|
return receive()
|
||||||
channels = {},
|
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,
|
uuid = nil,
|
||||||
sessionId = math.random(0xffffff),
|
motd = "soqet",
|
||||||
sessionToken = nil,
|
|
||||||
ssl = soqet.ssl,
|
|
||||||
connected = false,
|
connected = false,
|
||||||
listening = true,
|
};
|
||||||
updateInterval = 1
|
|
||||||
}
|
|
||||||
|
|
||||||
if ssl then
|
function soqet.polling.connect(token)
|
||||||
client.ENDPOINT = "https://" .. soqet.ENDPOINT
|
local h, err = http.get(soqet.polling.host .. "/api/connect?token=" .. textutils.urlEncode(token));
|
||||||
else
|
if not h then
|
||||||
client.ENDPOINT = "http://" .. soqet.ENDPOINT
|
return false, err
|
||||||
end
|
end
|
||||||
|
|
||||||
local function postJson(path, body)
|
local result = json.decode(h.readAll())
|
||||||
return http.post(
|
|
||||||
client.ENDPOINT .. "/api/" .. path,
|
if not result.ok then
|
||||||
soqet.json.encode(body),
|
return false, result.error
|
||||||
{
|
|
||||||
["Content-Type"] = "application/json"
|
|
||||||
}
|
|
||||||
)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
local function rawreceive()
|
soqet.polling.token = result.token
|
||||||
if not client.connected then
|
soqet.polling.motd = result.motd
|
||||||
client.connect()
|
soqet.polling.connected = true
|
||||||
end
|
|
||||||
while true do
|
return true
|
||||||
local h, err =
|
end
|
||||||
postJson(
|
|
||||||
"update",
|
function soqet.polling.update()
|
||||||
{
|
local h, err = http.post(soqet.polling.host .. "/api/update", textutils.serialiseJSON({
|
||||||
token = client.sessionToken
|
token = soqet.polling.token,
|
||||||
}
|
}))
|
||||||
)
|
|
||||||
|
|
||||||
if not h then
|
if not h then
|
||||||
error(err)
|
return false, err
|
||||||
end
|
end
|
||||||
|
|
||||||
local data = soqet.json.decode(h.readAll())
|
local result = json.decode(h.readAll());
|
||||||
h.close()
|
|
||||||
|
|
||||||
local queue = {}
|
if not result.ok then
|
||||||
|
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
|
||||||
|
|
||||||
if #queue > 0 then
|
return result.queue
|
||||||
return queue
|
end
|
||||||
else
|
|
||||||
sleep(client.updateInterval)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function client.connect(token)
|
function soqet.polling.open(channel)
|
||||||
expect(1, token, "nil", "string")
|
local h, err = http.post(soqet.polling.host .. "/api/open", textutils.serialiseJSON({
|
||||||
|
token = soqet.polling.token,
|
||||||
local h, err, eh = http.get(client.ENDPOINT .. "/api/connect?token=" .. textutils.urlEncode(token or ""))
|
channel = channel,
|
||||||
|
}))
|
||||||
|
|
||||||
if not h then
|
if not h then
|
||||||
return false, err, eh
|
return false, err
|
||||||
end
|
end
|
||||||
|
|
||||||
local data = soqet.json.decode(h.readAll())
|
local result = json.decode(h.readAll());
|
||||||
|
|
||||||
h.close()
|
if not result.ok then
|
||||||
|
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
|
||||||
|
|
||||||
function client.open(channel)
|
local result = json.decode(h.readAll());
|
||||||
expect(1, channel, "string", "number")
|
|
||||||
|
|
||||||
client.channels[#client.channels + 1] = channel
|
if not result.ok then
|
||||||
|
return false, result.err
|
||||||
postJson(
|
end
|
||||||
"open",
|
|
||||||
{
|
|
||||||
token = client.sessionToken,
|
|
||||||
channel = channel
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
function client.close(channel)
|
function soqet.polling.send(channel, message, meta)
|
||||||
expect(1, channel, "string", "number")
|
local h, err = http.post(soqet.polling.host .. "/api/send", textutils.serialiseJSON({
|
||||||
|
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
|
||||||
|
|
||||||
function client.receive()
|
local result = json.decode(h.readAll());
|
||||||
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