Skip to content

Instantly share code, notes, and snippets.

@Fingercomp
Created Jun 8, 2020
Embed
What would you like to do?
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
while true do
local chunk, err = handle.read()
if not chunk then --
local _, _, responseHeaders = handle.response() --
local length
for k, v in pairs(responseHeaders) do --
if k:lower() == "content-length" then
length = tonumber(v)
end
end
if not length or read >= length then --
break
end
return nil, ("error occured while reading response: %s"):format(err or "unknown error") --
end
read = read + #chunk --
table.insert(url, chunk)
end
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
while true do
local chunk, err = handle.read()
if not chunk then
f:close() --
local _, _, responseHeaders = handle.response()
local length
for k, v in pairs(responseHeaders) do
if k:lower() == "content-length" then
length = tonumber(v)
end
end
if not length or read >= length then
break
end
return nil, ("error occured while reading response: %s"):format(err or "unknown error")
end
read = read + #chunk
f:write(chunk)
end
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