Skip to content

Instantly share code, notes, and snippets.

@Fingercomp
Last active August 25, 2022 13:49
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Fingercomp/457c53915d7a09944385f0b78676253e to your computer and use it in GitHub Desktop.
Save Fingercomp/457c53915d7a09944385f0b78676253e to your computer and use it in GitHub Desktop.
clbin client for OpenComputers
local com = require("component")
local comp = require("computer")
local fs = require("filesystem")
local shell = require("shell")
local inet = com.internet
local function generateBorder(str)
local longestOccurence = nil
for match in str:gmatch("%-*cldata") do
if not longestOccurence or #match > #longestOccurence then
longestOccurence = match
end
end
return longestOccurence and ("-" .. longestOccurence) or "cldata"
end
local function asFormData(str, fieldName)
local border = generateBorder(str)
local contentType = "multipart/form-data; boundary=" .. border
return ([[
--%s
Content-Disposition: form-data; name="%s"
%s
--%s--]]):format(
border,
fieldName,
str,
border
), contentType
end
local function request(url, body, headers, timeout)
local handle, err = inet.request(url, body, headers) -- ①
if not handle then
return nil, ("request failed: %s"):format(err or "unknown error")
end
local start = comp.uptime() -- ②
while true do
local status, err = handle.finishConnect() -- ③
if status then -- ④
break
end
if status == nil then -- ⑤
return nil, ("request failed: %s"):format(err or "unknown error")
end
if comp.uptime() >= start + timeout then -- ⑥
handle.close()
return nil, "request failed: connection timed out"
end
os.sleep(0.05) -- ⑦
end
return handle -- ⑧
end
local function sendFile(path)
local f, err = io.open(path, "r") -- ①
if not f then
return nil, ("could not open file for reading: %s"):format(err or "unknown error")
end
local contents = f:read("*a") -- ②
f:close()
local data, contentType = asFormData(contents, "clbin") -- ③
local headers = {["Content-Type"] = contentType}
local handle, err = request("https://clbin.com", data, headers, 10) -- ④
if not handle then
return nil, err
end
local url = {} -- ⑤
local read = 0
local _, _, responseHeaders = handle.response() -- ⑥
local length
for k, v in pairs(responseHeaders) do -- ⑦
if k:lower() == "content-length" then
length = tonumber(v)
end
end
while not length or read < length do -- ⑧
local chunk, err = handle.read()
if not chunk then
if length then -- ⑨
return nil, ("error occured while reading response: %s"):format(err or "unknown error") -- ⑩
end
break -- ⑩
end
read = read + #chunk -- ⑪
if length and read > length then
chunk = chunk:sub(1, length - read - 1) -- ⑫
end
table.insert(url, chunk)
end
handle.close() -- ⑬
return table.concat(url) -- ⑭
end
local function getFile(url, path)
local f, err = io.open(path, "w") -- ①
if not f then
return nil, ("could not open file for writing: %s"):format(err or "unknown error")
end
local handle, err = request(url, nil, nil, 10) -- ②
if not handle then
return nil, err
end
local read = 0
local _, _, responseHeaders = handle.response()
local length
for k, v in pairs(responseHeaders) do
if k:lower() == "content-length" then
length = tonumber(v)
end
end
while not length or read < length do
local chunk, err = handle.read()
if not chunk then
if length then
f:close() -- ③
return nil, ("error occured while reading response: %s"):format(err or "unknown error")
end
break
end
read = read + #chunk
if length and read > length then
chunk = chunk:sub(1, length - read - 1)
end
f:write(chunk)
end
f:close() -- ④
handle.close()
return true
end
local args, opts = shell.parse(...)
local function printHelp()
io.stderr:write([[
Usage: clbin { get [-f] <code> <path> | put <path> }
clbin get [-f] <code> <path>
Download a file from clbin to <path>.
If the target file exists, -f overwrites it.
clbin put <path>
Upload a file to clbin.
]])
os.exit(1)
end
if args[1] == "get" then
if #args < 3 then
printHelp()
end
local code = args[2]
local path = args[3]
local url = ("https://clbin.com/%s"):format(code)
path = fs.concat(shell.getWorkingDirectory(), path)
if not (opts.f or opts.force) and fs.exists(path) then
io.stderr:write("file already exists, pass -f to overwrite\n")
os.exit(2)
end
local status, err = getFile(url, path)
if status then
print("Success! The file is written to " .. path)
os.exit(0)
else
io.stderr:write(err .. "\n")
os.exit(3)
end
elseif args[1] == "put" then
if #args < 2 then
printHelp()
end
local path = args[2]
local url, err = sendFile(path)
if url then
url = url:gsub("[\r\n]", "")
print("Success! The file is posted to " .. url)
os.exit(0)
else
io.stderr:write(err .. "\n")
os.exit(4)
end
else
printHelp()
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment