ComputerCraft Archive

progdor

computer utility LDDestroier github

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 progdor
Archive: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

none

Source

View Original Source

Code 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