commit 80475c62f2cc0435b906fca8bcf194c30b7931df Author: ChrisChrome Date: Wed Sep 4 07:41:25 2024 -0600 Move to separate repo diff --git a/Base64.lua b/Base64.lua new file mode 100644 index 0000000..bb6727a --- /dev/null +++ b/Base64.lua @@ -0,0 +1,34 @@ +function to_base64(data) + local b = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/' + return ((data:gsub('.', function(x) + local r,b='',x:byte() + for i=8,1,-1 do r=r..(b%2^i-b%2^(i-1)>0 and '1' or '0') end + return r; + end)..'0000'):gsub('%d%d%d?%d?%d?%d?', function(x) + if (#x < 6) then return '' end + local c=0 + for i=1,6 do c=c+(x:sub(i,i)=='1' and 2^(6-i) or 0) end + return b:sub(c+1,c+1) + end)..({ '', '==', '=' })[#data%3+1]) +end + +function from_base64(data) + local b = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/' + data = string.gsub(data, '[^'..b..'=]', '') + return (data:gsub('.', function(x) + if (x == '=') then return '' end + local r,f='',(b:find(x)-1) + for i=6,1,-1 do r=r..(f%2^i-f%2^(i-1)>0 and '1' or '0') end + return r; + end):gsub('%d%d%d?%d?%d?%d?%d?%d?', function(x) + if (#x ~= 8) then return '' end + local c=0 + for i=1,8 do c=c+(x:sub(i,i)=='1' and 2^(8-i) or 0) end + return string.char(c) + end)) +end + +return { + atob = from_base64, + btoa = to_base64 +} diff --git a/WebSocket.lua b/WebSocket.lua new file mode 100644 index 0000000..5195a66 --- /dev/null +++ b/WebSocket.lua @@ -0,0 +1,62 @@ +local Base64 = require(script.Base64) +local JobId = game:GetService('HttpService'):GenerateGUID(false) +local BaseUrl = "https://sock.kcadev.org/api/" +local atob = Base64.atob +local btoa = Base64.btoa +local messages = {} + +local function notExists(whichArray, itemName) + if (table.find(whichArray, itemName)) then + return false + else + return true + end +end + +local function notEmpty(s) + return s ~= nil or s ~= '' or s ~= " " +end + +local ws = function (dict) + local onMessage = dict.onMessage or function(msg) + print(msg) + end + local server = game:GetService('HttpService') + local id = server:RequestAsync({ + ["Url"] = BaseUrl .. "/connect/" .. JobId, + ["Method"] = "PUT", + ["Body"] = dict.url + }) + local function sendMessage(msg) + wait() + server:PostAsync(BaseUrl .. "api/send/" .. JobId .."/"..id, msg) + end + + local function close() + server:RequestAsync({ + ["Url"] = BaseUrl .. "api/close/" .. JobId .. "/" .. id, + ["Method"] = "DELETE" + }) + end + + local loop = coroutine.create(function() + while wait(50 / 1000) do + local msg = server:GetAsync(BaseUrl .. "poll/"..JobId.."/"..id) + if notExists(messages, msg) then + table.insert(messages, msg) + if notEmpty(msg) then + onMessage(msg) + end + end + end + end) + coroutine.resume(loop) + game:BindToClose(close) + return { + sendMessage = sendMessage, + onMessage = onMessage, + close = close + } +end + +return ws