Skip to content

Instantly share code, notes, and snippets.

@IS2511
Last active January 16, 2021 19:21
Show Gist options
  • Save IS2511/e4c6a6f638609fcfa733ceeb432cfced to your computer and use it in GitHub Desktop.
Save IS2511/e4c6a6f638609fcfa733ceeb432cfced to your computer and use it in GitHub Desktop.
catbox.lua - catbox.moe api in lua for OpenComputers (https://pastebin.com/kuGkdm53)
--[[
Catbox https://gist.github.com/IS2511/e4c6a6f638609fcfa733ceeb432cfced
An implementation of CatBox.moe API in Lua
Pastebin: https://pastebin.com/kuGkdm53
Author: IS2511
parg library
https://gist.github.com/IS2511/96847fe185278b457505218b1c141f9d
Special thanks to fingercomp
]]--
-- Libs, components
local shell = require("shell")
local fs = require("filesystem")
local io = require("io")
local print = print -- Bring print() to local so redef not global
local os = require("os")
local comp = require("computer")
if not require("component").isAvailable("internet") then error("No internet card found!") end
local compRequest = require("component").internet.request
local CONFIG_FILE = fs.concat(os.getenv("HOME"), ".catbox")
local HOST = "https://catbox.moe/user/api.php"
local ok, parg = pcall(require, "parg")
if not ok then
print("Library \"parg\" not found!")
print("Installing...")
if not fs.isDirectory("/usr/lib") then fs.makeDirectory("/usr/lib") end
shell.execute("pastebin get nSgXWHtp /usr/lib/parg.lua")
print("Done installing!")
end
local parg = require("parg")
-- Command-line arguments
local anon, requestTimeout, yesToAll
parg.register({"help", "h"}, "flag")
parg.register({"anonymous", "a"}, "flag",
function (count) anon = (count > 0) or (not fs.exists(CONFIG_FILE)) end)
parg.register({"timeout", "t"}, "value",
function (value) requestTimeout = tonumber(value) or 10 end)
parg.register({"yes", "y"}, "flag",
function (count) yesToAll = (count > 0) end)
parg.register({"quite", "q"}, "flag",
function (count)
if count > 0 then
print = function (...) end
end
end)
local args = parg( {...} )
if args.quite > 0 then yesToAll = true end
-- Helper functions
local Multipart = {}
function Multipart.generateBorder(str)
local border = tostring({}):sub(14) -- 10?
local longestOccurence = nil
for match in str:gmatch("%-*"..border) do
if (not longestOccurence) or (#match > #longestOccurence) then
longestOccurence = match
end
end
return longestOccurence and ("-" .. longestOccurence) or border
end
function Multipart:formData()
local border = ""
for i, v in ipairs(self.data) do
border = border..Multipart.generateBorder(v.value)
end
local data = ""
for i, v in ipairs(self.data) do
local params = ""
if v.params then
for k, vv in pairs(v.params) do
params = params.."; "..k.."=\""..vv.."\""
end
end
data = data..([[--%s
Content-Disposition: form-data; name="%s"%s
%s
]]):format(border, v.name, params, v.value)
end
data = data.."--"..border.."--"
-- data:gsub("\n", "\r\n") -- Nope
return data, ("multipart/form-data; boundary="..border) -- data, Content-Type
end
function Multipart.new()
return {
formData = Multipart.formData,
data = {}
}
end
local function urlEncode(str)
if str then
str = str:gsub("\n", "\r\n")
str = str:gsub("([^%w %-%_%.%~])", function(c)
return ("%%%02X"):format(string.byte(c))
end)
str = str:gsub(" ", "+")
end
return str
end
local function dataUrlEncode(t)
local data = ""
for k, v in pairs(t) do
data = data..k.."="..urlEncode(v).."&"
end
data = data:sub(1, #data-1)
return data
end
local function request(url, body, headers, method, timeout)
local handle, err = compRequest(url, body, headers, method)
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
-- Main functions
local function catboxRequest (reqtype, arg, data)
local handle, err
if reqtype == "fileupload" then
handle, err = request(HOST, data.data, {["Content-Type"] = data.contentType}, "POST", requestTimeout)
else
handle, err = request(HOST, dataUrlEncode(data), {["Content-Type"] = "application/x-www-form-urlencoded; charset=UTF-8"}, "POST", requestTimeout)
end
data = nil form = nil contentType = nil -- Clearing memory
for i=1, 10 do os.sleep(0) end -- Collect garbadge
if handle == nil then
print("Request error \""..arg.."\": "..tostring(err))
else
local result = ""
while true do
local chunk, err = handle.read()
if not chunk then break end
result = result..chunk
end
if handle.response() == 200 then -- Response code == 200 OK
if (result:sub(1, 25) == "https://files.catbox.moe/") or (result:sub(1, 19) == "https://catbox.moe/") then
if result:sub(1, 21) == "https://catbox.moe/c/" then -- "createalbum" ?
print("Album short: "..result:sub(22))
end
print("Link: "..result)
else
print("Success! "..result)
end
else
print("Catbox error \""..arg.."\": "..result)
end
end
end
local function usage (album)
if album then
print([[
Usage: catbox album <command> [arguments]
Every command here needs userhash so be sure you have set it up!
Every title or discription must be written in "" if you want to write more than one word!
Commands:
create <title> <description> <file(s)> - Create album
edit <short> <title> <description> [file(s)] - Edit album
add <short> <file(s)> - Add files to album
remove <short> <file(s)> - Remove files from album
delete <short> - Delete album]])
else
print([[
Usage: catbox <command> [arguments]
Commands:
user [userhash] - Get or set current userhash.
Pass 'off' to forget set userhash
file <filename(s)> - Upload files to catbox.moe
url <url(s)> - Upload files from URLs to catbox.moe
delete <filenames(s)> - Delete files from catbox.moe. Requires userhash
album - Album Managment ('catbox album' for help)
-a, --anonymous - Ignore userhash, upload anonymously
-h, --help - Print this message
-y, --yes - Yes to everything, skip all checks
-q, --quite - Suppress all output (except sys err) and --yes]])
end
end
local function Hash (hash)
if hash then
local file, err = io.open(CONFIG_FILE, "w")
if not file then error(err) end
file:write(hash)
file:close()
hash = true
else
if anon or (not fs.exists(CONFIG_FILE)) then
return nil
end
local file, err = io.open(CONFIG_FILE, "r")
if not file then error(err) end
hash = file:read("*l")
end
return hash
end
-- Program start
if #args == 0 or (args.help > 0) then
usage(args[1] == "album")
return
elseif args[1] == "user" then -- NOTE: user
if not args[2] then
if fs.exists(CONFIG_FILE) then
print("Your current userhash is: "..Hash())
else
print("No userhash is currently set, so you are anonymous")
end
else
if args[2] ~= "off" then
Hash(args[2])
print("Userhash "..args[2].." set in "..CONFIG_FILE)
else
fs.remove(CONFIG_FILE)
print("You are now Anonymous!")
end
end
elseif args[1] == "file" then -- NOTE: file
if #args == 1 then
print("Usage: catbox file <filename> [<filename>...] - Uploads files to CatBox.moe")
return
end
if anon then
print("Uploading anonymously...")
else
print("Uploading with userhash...")
end
for i=2, #args do
local path = fs.concat(fs.path(args[0]), args[i])
if fs.exists(path) and (not fs.isDirectory(path)) then
local form = Multipart.new()
table.insert(form.data, {name = "reqtype", value = "fileupload"})
if not anon then table.insert(form.data, {name = "userhash", value = Hash()}) end
table.insert(form.data, {
name = "fileToUpload",
params = { filename = fs.name(path) },
value = io.open(path):read("*a") })
local data, contentType = form:formData()
-- print("DEBUG:") print(data) print(contentType)
catboxRequest("fileupload", path, {data = data, contentType = contentType})
else
print("File "..path.." does not exist or is a directory!")
end
end
print("Done!")
elseif args[1] == "url" then -- NOTE: url
if #args == 1 then
print("Usage: catbox url <url> [<url>...] - Uploads files from urls to CatBox.moe")
return
end
if anon then
print("Uploading anonymously...")
else
print("Uploading with userhash...")
end
for i=2, #args do
local data = {
reqtype = "urlupload",
userhash = Hash(), -- If anon Hash():nil
url = args[i]
}
catboxRequest("urlupload", args[i], data)
end
print("Done!")
elseif args[1] == "delete" then -- NOTE: delete
if #args == 1 then
print("Usage: catbox delete <filename> [<filename>...] - Deletes files from your CatBox.moe account")
return
end
if anon then
print("Can't delete files! No userhash!")
return
end
print("Deleting files...")
for i=2, #args do
local data = {
reqtype = "deletefiles",
userhash = Hash(),
files = args[i] -- Deleting 1 file at a time
}
catboxRequest("deletefiles", args[i], data)
end
print("Done!")
elseif args[1] == "album" then -- NOTE: album
if #args == 1 then
usage(true)
return
end
if args[2] == "create" then
if #args < 5 then
print("Usage: catbox album create <title> <description> <filename> [<filename> ...] - Careates an album with given title, discription and files")
return
end
if anon then
print("Anonymous albums are permanently disabled in this program.")
print("I don't think they are needed anyway. Use userhash for albums.")
return
end
local title, desc, files = args[3], args[4], ""
for i=5, #args do
files = files..args[i]..((i ~= #args) and " " or "")
end
print("Creating Album...")
print("Title: "..title)
print("Description: "..desc)
print("Files: "..files)
print()
if not yesToAll then
io.write("Are you sure? [y/N] ")
local answer = io.read() -- "*line" (default)
if (string.lower(answer) == "no") or (string.lower(answer) == "n") or (answer == "") then
print("Aborting.")
return
end
end
local data = {
reqtype = "createalbum",
userhash = Hash(),
title = title,
desc = desc,
files = files
}
catboxRequest("createalbum", title, data)
print("Done!")
elseif args[2] == "edit" then
if #args < 5 then
print("Usage: catbox album edit <short> <title> <description> [<filename> ...] - Edites album")
print("Filenames are optional, BUT if none are specified the album WILL BE EMPTY!")
return
end
if anon then
print("Can't edit albums! No userhash!")
return
end
local short, title, desc, files = args[3], args[4], args[5], ""
for i=6, #args do
files = files..args[i]..((i ~= #args) and " " or "")
end
print("Editing Album...")
print("Short: "..short)
print("Title: "..title)
print("Description: "..desc)
print("Files: "..files)
print("Filenames are optional, BUT if none are specified the album WILL BE EMPTY!")
print()
if not yesToAll then
io.write("Are you sure? [y/N] ")
local answer = io.read() -- "*line" (default)
if (string.lower(answer) == "no") or (string.lower(answer) == "n") or (answer == "") then
print("Aborting.")
return
end
end
local data = {
reqtype = "editalbum",
userhash = Hash(),
short = short,
title = title,
desc = desc,
files = files
}
catboxRequest("editalbum", short, data)
print("Done!")
elseif args[2] == "add" then
if #args < 4 then
print("Usage: catbox album add <short> <filename> [<filename> ...] - Adds files to the specific album")
return
end
if anon then
print("Can't add files to albums! No userhash!")
return
end
local short, files = args[3], ""
for i=4, #args do
files = files..args[i]..((i ~= #args) and " " or "")
end
print("Adding files to Album...")
print("Short: "..short)
print("Files: "..files)
print()
local data = {
reqtype = "addtoalbum",
userhash = Hash(),
short = short,
files = files
}
catboxRequest("addtoalbum", short, data)
print("Done!")
elseif args[2] == "remove" then
if #args < 4 then
print("Usage: catbox album remove <short> <filename> [<filename> ...] - Removes files from the specific album")
return
end
if anon then
print("Can't remove files from albums! No userhash!")
return
end
local short, files = args[3], ""
for i=4, #args do
files = files..args[i]..((i ~= #args) and " " or "")
end
print("Removing files from Album...")
print("Short: "..short)
print("Files: "..files)
print()
local data = {
reqtype = "removefromalbum",
userhash = Hash(),
short = short,
files = files
}
catboxRequest("removefromalbum", short, data)
print("Done!")
elseif args[2] == "delete" then
if #args < 3 then
print("Usage: catbox album delete <short> [<short> ...] - Deletes album")
return
end
if anon then
print("Can't delete albums! No userhash!")
return
end
local short = args[3]
print("Deleting Album...")
print("Short: "..short)
print()
if not yesToAll then
io.write("Are you sure? [y/N] ")
local answer = io.read() -- "*line" (default)
if (string.lower(answer) == "no") or (string.lower(answer) == "n") or (answer == "") then
print("Aborting.")
return
end
end
local data = {
reqtype = "deletealbum",
userhash = Hash(),
short = short
}
catboxRequest("deletealbum", short, data)
print("Done!")
else
usage(true)
end
else
usage()
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment