progdor
Description
A collection of all my ComputerCraft programs and the APIs they use. This is mostly just to get them the fuck off of pastebin, and also to ensure that API owners don't change things to break my precious programs...!
Installation
Copy one of these commands into your ComputerCraft terminal:
wget:
wget https://raw.githubusercontent.com/LDDestroier/CC/master/progdor.lua progdorArchive:
wget https://cc.shobie.xyz/cc/get/gh-LDDestroier-CC-progdor progdor
Quick Install:
wget https://cc.shobie.xyz/cc/get/gh-LDDestroier-CC-progdor progdor
Usage
Run: progdor
Tags
Source
View Original SourceCode Preview
--[[
PROGDOR file bundling program
Download with:
pastebin get YXx5jjMV progdor
std ld progdor progdor
This is a stable release. You fool!
--]]
local doCompress = false --even if this is false, it will decompress compressed files. nifty, huh?
local doPastebin = false
local tArg = {...}
local input, outpath
if tArg[1] == "-p" then --the p is for pastebin
doPastebin = true
input = tArg[2]
outpath = tArg[3]
else
input = tArg[1]
outpath = tArg[2]
end
local progdor = fs.getName(shell.getRunningProgram())
local dir = shell.dir()
local displayHelp = function()
local txt = progdor.." <input> [output]\nCompression is "..tostring(doCompress):upper().."."
return print(txt)
end
local yield = function()
os.queueEvent("yield")
os.pullEvent("yield")
end
-- CCA API START --
local bit = bit32
local function pack(bn1, bn2)
return bit.band(bn1, 0xFF), bit.rshift(bn1, 8) + bit.lshift(bit.band(bn2, 0xF), 4), bit.rshift(bn2, 4)
end
local function upack(b1, b2, b3)
return (b1 + bit.lshift(bit.band(b2, 0xF), 8)), (bit.lshift(b3,4) + bit.band(bit.rshift(b2, 4), 0xF))
end
local function createDict(bool)
local ret = {}
for i = 1, 255 do
if bool then
ret[string.char(i)] = i
else
ret[i] = string.char(i)
end
end
if not bool then ret[256] = 256 end
return ret
end
local function cp(sInput)
local dic = createDict(true)
local s = ""
local ch
local dlen = 256
local result = {}
local temp
for i = 1, #sInput do
if dlen == 4095 then
result[#result + 1] = dic[s]
result[#result + 1] = 256
dic = createDict(true)
dlen = 256
s = ""
end
ch = sInput:sub(i, i)
temp = s..ch
if dic[temp] then
s = temp
else
result[#result + 1] = dic[s]
dlen = dlen +1
dic[temp] = dlen
s = ch
end
end
result[#result + 1] = dic[s]
return result
end
local function dc(data)
local dic = createDict(false)
local entry
local ch
local currCode
local result = {}
result[#result + 1] = dic[data[1]]
prefix = dic[data[1]]
for i = 2, #data do
currCode = data[i]
if currCode == 256 then
dic = createDict(false)
prefix = ""
else
entry = dic[currCode]
if entry then--exists in dictionary
ch = entry:sub(1, 1)
result[#result + 1] = entry
if prefix ~= "" then
dic[#dic+1] = prefix .. ch
end
else
ch = prefix:sub(1, 1)
result[#result + 1] = prefix..ch
dic[#dic + 1] = prefix..ch
end
prefix = dic[currCode]
end
end
return table.concat(result)
end
local function trim(inp)
for i = 0,2 do
if inp[#inp] == 0 then
inp[#inp] = nil
end
end
end
local function decompress(input)
local rec = {}
for i = 1, #input, 3 do
if i % 66 == 0 then
yield()
end
rec[#rec+1], rec[#rec+2] = upack(input[i], input[i+1] or 0, input[i+2] or 0)
end
trim(rec)
return dc(rec)
end
local function compress(input)
local rec = {}
local data = cp(input)
for i=1, #data, 2 do
yield()
rec[#rec+1], rec[#rec+2], rec[#rec+3] = pack(data[i], data[i+1] or 0)
end
trim(rec)
return rec
end
-- CCA API END --
local fixstr = function(str)
return str:gsub("\\(%d%d%d)",string.char)
end
local explode = function(div,str)
if (div=='') then return false end
local pos,arr = 0,{}
for st,sp in function() return string.find(str,div,pos,true) end do
table.insert(arr,str:sub(pos,st-1))
pos = sp + 1
end
table.insert(arr,str:sub(pos))
return arr
end
local sanitize = function(sani,tize)
local _,x = string.find(sani,tize)
if x then
return sani:sub(x+1)
else
return sani
end
end
local tablize = function(input)
if type(input) == "string" then
return explode("\n",input)
elseif type(input) == "table" then
return table.concat(input,"\n")
end
end
local compyress = function(input)
return string.char(unpack(compress(input)))
end
local decompyress = function(input)
local out = {}
for a = 1, #input do
table.insert(out,string.byte(input:sub(a,a)))
end
return decompress(out)
end
local listAll
listAll = function(_path, _files, noredundant)
local path = _path or ""
local files = _files or {}
if #path > 1 then table.insert(files, path) end
for _, file in ipairs(fs.list(path)) do
local path = fs.combine(path, file)
if (file ~= thisProgram) then
local guud = true
if guud then
if fs.isDir(path) then
listAll(path, files, noredundant)
else
table.insert(files, path)
end
end
end
end
if noredundant then
for a = 1, #files do
if fs.isDir(tostring(files[a])) then
if #fs.list(tostring(files[a])) ~= 0 then
table.remove(files,a)
end
end
end
end
return files
end
if not (input) then
return displayHelp()
end
if not outpath then
outpath = input
end
local choice = function(input,verbose)
if not input then
input = "yn"
end
if verbose then
write("[")
for a = 1, #input do
write(input:sub(a,a):upper())
if a < #input then
write(",")
end
end
write("]?")
end
local evt,char
repeat
evt,char = os.pullEvent("char")
until string.find(input:lower(),char:lower())
if verbose then
print(char:upper())
end
local pos = string.find(input:lower(),char:lower())
return pos, char:lower()
end
local postToPastebin = function(name, contents)
local key = "0ec2eb25b6166c0c27a394ae118ad829"
local response = http.post(
"http://pastebin.com/api/api_post.php",
"api_option=paste&"..
"api_dev_key="..key.."&"..
"api_paste_format=lua&"..
"api_paste_name="..textutils.urlEncode(name).."&"..
"api_paste_code="..textutils.urlEncode(contents)
)
if response then
local sResponse = response.readAll()
response.close()
local sCode = string.match( sResponse, "[^/]+{{code}}quot; )
return sCode
else
return false
end
return
end
function doPack(input,output,doCompress,verbose) --make sure that shell exists before using verbose mode
local tx = term.getTextColor()
if not doPastebin then
if not fs.exists(input) then return 3 end
if fs.isReadOnly(output) then return 5 end
end
local packageSelf = true
local packageReadOnly = true
local ro_asked = false
local ps_asked = false
if fs.isDir(input) then --if not a package
local out = {}
local list = listAll(input,nil,true)
if verbose then
for a = 1, #list do --this checks for self and read-only files
if fs.isReadOnly(list[a]) and (not ro_asked) then
write("Include read-only files? ")
if choice("yn",true) == 2 then
packageReadOnly = false
end
ro_asked = true
end
if fs.combine("",list[a]) == shell.getRunningProgram() and (not ps_asked) then
write("Include self? ")
if choice("yn",true) == 2 then
packageSelf = false
end
ps_asked = true
end
end
end
for a = 1, #list do --this loop kills fascists
local is_self = fs.combine("",list[a]) == fs.combine("",shell.getRunningProgram())
if not ((is_self and not packageSelf) or (fs.isReadOnly(list[a]) and not packageReadOnly)) then
if verbose then
write("[")
if term.isColor() then term.setTextColor(colors.lightGray) end
write(sanitize(list[a],fs.combine(dir,input)))
term.setTextColor(tx)
write("]")
end
if fs.isDir(list[a]) then
out[sanitize(list[a],fs.combine(dir,input))] = true
else
local file = fs.open(list[a],"r")
local cont = file.readAll()
file.close()
if doCompress then
out[sanitize(list[a],fs.combine(dir,input))] = tablize(compyress(cont))
else
out[sanitize(list[a],fs.combine(dir,input))] = tablize(cont)
end
end
local tx = term.getTextColor()
if fs.getName(list[a]):lower() == "peasant" then
if term.isColor() then
term.setTextColor(colors.orange)
end
print(" BURNINATED")
else
if term.isColor() then
term.setTextColor(colors.green)
end
print(" GOOD")
end
term.setTextColor(tx)
else
if fs.getName(list[a]):lower() == "peasant" then
print("Spared "..list[a])
else
print("Skipped "..list[a])
end
end
end
local fullOutput = tostring(doCompress).."\n"..fixstr(textutils.serialize(out))
local sCode
if doPastebin then
print("Uploading...")
sCode = postToPastebin(input,fullOutput)
return 7, "Code = '"..sCode.."'"
else
if fs.isDir(output) then fs.delete(output) end
local file = fs.open(output,"w")
file.write(fullOutput)
file.close()
return 1
end
else --if a package
local list, isCompy
if not doPastebin then
local file = fs.open(input,"r")
isCompy = file.readLine()
list = file.readAll()
file.close()
else
local file = http.get("http://pastebin.com/raw/"..tostring(input))
if file then
isCompy = file.readLine()
list = file.readAll()
else
return 6
end
end
local list = textutils.unserialize(list)
if type(list) ~= "table" then
return 4
end
if fs.exists(output) then
fs.delete(output)
end
local amnt = 0
for k,v in pairs(list) do
amnt = amnt + 1
end
local num = 0
for k,v in pairs(list) do
num = num + 1
if v == true then
fs.makeDir(fs.combine(output,fs.combine(k,dir)))
else
local file = fs.open(fs.combine(output,fs.combine(k,dir)),"w")
if verbose then
write("[")
if term.isColor() then term.setTextColor(colors.lightGray) end
write(k)
term.setTextColor(tx)
write("]")
end
if isCompy:gsub(" ","") == "true" then
file.write(decompyress(tablize(v)))
else
file.write(tablize(v))
end
file.close()
local tx = term.getTextColor()
if fs.getName(k):lower() == "peasant" then
if term.isColor() then
term.setTextColor(colors.orange)
end
print(" UNBURNINATED")
else
if term.isColor() then
term.setTextColor(colors.green)
end
print(" GOOD")
end
term.setTextColor(tx)
end
end
return 2
end
end
local success, res, otherRes = pcall( function() return doPack(input,outpath,doCompress,true) end ) --functionized it!
if not success then
term.setTextColor(colors.white)
print("\n***Something went wrong!***")
return printError(res)
end
if res then
local msgs = {
[1] = "Successfully packed '"..input.."/' as '"..outpath.."'",
[2] = "Successfully unpacked '"..input.."' to '"..outpath.."/'",
[3] = "That file/folder does not exist.",
[4] = "That file isn't a packed folder.",
[5] = "You don't have permission.",
[6] = "Failed to connect.",
[7] = "Uploaded successfully.",
}
print(msgs[res])
if otherRes then
print(otherRes)
end
end