Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- --#filename:tmart
- --#version:0.5
- --#author:Advert
- -- tmart (formerly pget) 0.5 'TrollMart'
- -- (C) 2012 User 'Advert' at http://www.computercraft.info/forums2/
- -- X11/mit licence (use/modify at your will, but please, leave credit where due)
- if not http then
- error("plib requires http! Enable it in your config file!")
- end
- local plib = {}
- -- Configuration:
- local dConf = {}
- do -- dConf settings.
- dConf["sMasterLink"] = "rb7LSHsJ" -- This is where we get all the other "paste repositories"
- -- if sMasterLink starts with "http:", then that should indicate it's a full url; e.g "http://computercraft.info/pget_master.txt" or something.
- dConf["sBaseURL"] = "http://pastebin.com/raw.php?i=%s"
- dConf["sPoweredBy"] = "Powered by pastebin.com (http://pastebin.com)"
- dConf["sPoweredBySplash"] = { -- Comment this out to prevent splash.
- [[ _____ _ _ _ ]],
- [[ /__ \_ __ ___ | | | /\/\ ____ _ __| |_ ]],
- [[ / /\/ '__/ _ \| | |/ \ / _, | '__| __|]],
- [[ / / | | | (_) | | / /\/\ \ (_| | | | |_ ]],
- [[ \/ |_| \___/|_|_\/ \/\__,_|_| \__|]],
- [[ ]],
- [[ Powered By:]],
- [[ ___ _ _ _ ]],
- [[ / _ \____ ___| |_ ___| |__ (_)_ __ ]],
- [[ / /_)/ _, / __| __/ _ \ '_ \| | '_ \ ]],
- [[ / ___/ (_| \__ \ || __/ |_) | | | | |]],
- [[ \/ \__,_|___/\__\___|_.__/|_|_| |_|]],
- [[ ]],
- "",
- " http://pastebin.com"}
- end
- local config = dConf -- TODO: copy table
- local pasteTree, pasteCats, rawSave = {}, {}, {};
- -- String split helper function
- local function strSplitFirst(sData, sSplit)
- -- Only supports one character splits!
- local nPos;
- for i = 1, sData:len() do
- local sCur = sData:sub(i, i)
- if sCur == sSplit then
- nPos = i
- break
- end
- end
- if nPos == nil then return sData, nil end
- return string.sub(sData, 1, nPos -1), string.sub(sData, nPos +1)
- end
- -- Will get a paste, and seperate metadata etc.
- function plib.rawGet(sCode)
- local sURL;
- if sCode:sub(1, 7) == "http://" then
- sURL = sCode
- else
- sURL = string.format(config["sBaseURL"], sCode) -- To allow support for other paste services. (as long as they have a RAW function)
- -- ^ Redunant if this function changes to pure http get. (url determination would occur elsewhere)
- end
- local sData = "" -- The code/file contents (seperated from metadata)
- local meta = {} -- Some metadata is great.
- local hHandle = http.get(sURL) -- TODO: Change to non-blocking
- if not hHandle then
- return nil, {error = true}
- end
- while true do
- sleep(0)
- local sLine = hHandle:readLine()
- if sLine:sub(1, 3) == "--#" then -- Metadata!
- local sFirst, sSecond = strSplitFirst(sLine:sub(4), ":")
- meta[sFirst or tostring(i)] = sSecond -- Metadata only supports strings, at the moment. Metadata could be parsed as lua, but meh.
- else
- -- For some reason, we dont seem to need this:
- sData = sLine .. "\n" -- We've hit some data, let's add it, then just dump the rest, all in one go.
- break
- end
- end
- sData = sData .. hHandle:readAll() -- Dump the rest of the data into sData.
- hHandle:close()
- return sData, meta
- end
- local function stringIter(sData, sBreak) -- string iterator help function
- return function()
- if not sData then return nil end
- local ret
- ret, sData = strSplitFirst(sData, sBreak)
- if not ret and sData then
- ret = ""
- end
- --print(ret, "..", sData)
- return ret
- end
- end -- Wow, that was simple!
- local function strSplitSupreme(sData, sSplit) -- All hail.
- if sData == nil then return end
- local a, b = strSplitFirst(sData, sSplit)
- return a, strSplitSupreme(b, sSplit)
- end
- function plib.getNode(sCode, targetTable, bTrusted)
- -- if bTrusted is true, load other nodes listed inside, otherwise, no.
- if rawSave[sCode] then return {"Recursive table"} end -- todo: add appropriate table here.
- local sData, meta = plib.rawGet(sCode)
- rawSave[sCode] = {sData = sData, meta = meta} -- prevent recursion
- targetTable.nodes = targetTable.nodes or {}
- for sDataF in stringIter(sData, "\n") do
- sleep(0)
- --print("DataF: ", sDataF)
- if sDataF:sub(1, 1) ~= "-" and sDataF:len() > 0 then -- Check for comments
- --print("Is not a comment.")
- --TODO: better helper function for this.
- local sType, sLocation, sName, sCategory, sAuthor = strSplitSupreme(sDataF, ",")
- --print(string.format("sType: %s; sLocation: %s; sName: %s; sCategory: %s; sAuthor: %s.", sType, sLocation, sName, sCategory, sAuthor))
- local infoT = {sLocation = sLocation, sName = sName, sCategory = sCategory, sAuthor = sAuthor}
- if sType == "program" then
- table.insert(targetTable, infoT)
- if not pasteCats[sCategory] then
- pasteCats[sCategory] = {}
- end
- table.insert(pasteCats[sCategory], infoT)
- elseif sType == "node-trusted" then
- local node = infoT
- if bTrusted then
- plib.getNode(sLocation, node, true)
- end
- table.insert(targetTable.nodes, node)
- elseif sType == "node" then
- local node = {}
- if bTrusted then
- plib.getNode(sLocation, node, false)
- end
- table.insert(targetTable.nodes, node)
- end
- end
- end
- end
- function plib.downloadAndSave(sCode, sFile)
- --[[term.clear()
- term.setCursorPos(1, 1)
- if not sFile then
- print("Enter desired filename: ")
- sFile = read()
- end
- while fs.exists(sFile) do
- print("File already exists, overwrite? Y/newname")
- local inp = read()
- if inp == "y" or inp == "Y" then
- break
- end
- sFile = inp
- end
- --]]
- showSplash("Downloading!")
- local sData, meta = plib.rawGet(sCode)
- local hHandle = io.open(sFile, "w")
- if not hHandle then
- error("Unable to open file")
- end
- hHandle:write(sData)
- hHandle:close()
- end
- -- Graphical functions
- -- I felt obligated to make this function, to support pastebin.
- function showSplash(sBottomNotice)
- if config["sPoweredBySplash"] then
- term.clear()
- term.setCursorPos(1, 1)
- for i = 1, #config["sPoweredBySplash"] do
- term.setCursorPos(1, i)
- term.write(config["sPoweredBySplash"][i])
- end
- term.setCursorPos(1, 18)
- local sSpacer = ""
- if sBottomNotice:len() < 32 then
- sSpacer = (" "):rep(32 - sBottomNotice:len())
- end
- term.write(sSpacer .. sBottomNotice)
- term.setCursorPos(1, 1)
- sleep(1)
- else
- end
- end
- -- I REALLY need to clean up varaibles. TODO TODO TODO TODO
- -- TODO.
- local orderedCats = {}; -- Who ordered the cats? No, seirously, who ordered....
- local nCurCat, nCurItem = 1, 1
- local sState, sOldState = "help", "main"
- local render_mart;
- local function w(l, str) term.setCursorPos(1, l) term.write(str) end -- sick of two long commands to write text t_t
- local function render()
- -- I might make an API for this, since it would certainly be handy.
- term.clear()
- -- Core stuff:
- term.setCursorPos(1,1)
- w(1,"------ tmart v0.50 Powered by Pastebin.com -------")
- w(18, "x:exit; h:help/creds. You are here: " .. sState)
- if sState == "main" then
- render_mart() -- Render the current category, a few items, etc.
- elseif sState == "help" then
- w(2, "==================== credits =====================")
- w(3, " Advert: Programming")
- w(4, " Espen: Feedback, Testing, ")
- w(5, " A nice http.request example")
- w(6, " tomass1996: Original pastebin downloader ")
- w(7, " Everyone else that have helped, but that I can't")
- w(8, " remember: You know who you are (And aren't)!")
- w(9, "==================== Help ====================")
- w(10," m: main screen; download stuff here")
- w(11," g: download selected item")
- w(12," w/s: navigate categories")
- w(13," a/d: navigate items")
- end
- term.setCursorPos(1,1)
- return true
- end
- local function orderCats()
- --Haha, I lied. This simply dumps the table.
- for k, v in pairs(pasteCats) do
- table.insert(orderedCats, k)
- end
- end
- local function getCatT(nID)
- nID = nID or nCurCat
- return pasteCats[orderedCats[nID]]
- end
- local function getPasteT(nID)
- return getCatT()[nID]
- end
- local function fixedString(sStr, nSize)
- sStr = tostring(sStr or "")
- nSize = nSize or 12
- if sStr:len() > nSize then
- sStr = sStr:sub(1, nSize)
- elseif sStr:len() < nSize then
- sStr = sStr .. (" "):rep(nSize - sStr:len())
- end
- return sStr
- end
- local dataValues = {}
- local function getVar(sWhole, sVar)
- local sText = dataValues[sVar]
- return fixedString(sText, sWhole:len())
- end
- local function modText(sText)
- -- Our format: %name%
- -- e.g %text1%
- return string.gsub(sText, "(%%%s*(%w+)%s*%%)", getVar)
- end
- function render_mart()
- assimilate_dataValues()
- local screen = {
- [[================== Troll-Mart ==================]],
- [[ % recentlydownloaded % ]],
- [[ Select an item, using wasd, refridgerator. ]],
- [[--------------------------------------------------]],
- [[ Category | File | Details ]],
- [[------------+------------+------------------------]],
- [[ % cat1 % | % item1 % | - Name - ]],
- [[ % cat2 % | % item2 % | % detail1 % ]],
- [[ % cat3 % | % item3 % | -Category- ]],
- [[ % cat4 % | % item4 % | % detail2 % ]],
- [[>% cat5 %<|>% item5 %<| - Author - ]],
- [[ % cat6 % | % item6 % | % detail3 % ]],
- [[ % cat7 % | % item7 % | - Code - ]],
- [[ % cat8 % | % item8 % | % detail4 % ]],
- [[ % cat9 % | % item9 % | ]],
- [[==================================================]]}
- for i, v in ipairs(screen) do
- w(i + 1, modText(v))
- end
- end
- local function m_clamp(n, n2, n3)
- if n < n2 then
- n = n2
- end
- if n > n3 then
- n = n3
- end
- return n
- end
- function assimilate_dataValues()
- local numCats = #orderedCats
- local numItems = #getCatT()
- dataValues["nc"] = numCats
- dataValues["ni"] = numItems
- term.setCursorPos(1,1)
- local startCat, startItem = nCurCat - 5, nCurItem - 5
- for i = 1, 9 do --TODO: move depending on selection
- dataValues["cat" .. tostring(i)] = orderedCats[i + startCat]
- end
- for i = 1, 9 do --TODO: move depending on selection
- local pt = getPasteT(i + startItem)
- dataValues["item" .. tostring(i)]= pt and pt.sName
- end
- local ct = getPasteT(nCurItem)
- dataValues["detail1"] = ct.sName
- dataValues["detail2"] = ct.sCategory
- dataValues["detail3"] = ct.sAuthor
- dataValues["detail4"] = ct.sLocation
- end
- -- Main function*
- local bExit = false; -- TODO: move this up
- local events = {}
- local timerEvents = {}
- local activeTimers = {}
- local function registerTimer(fFunct, nDelay)
- local timerT = os.startTimer(nDelay)
- timerEvents[fFunct] = nDelay
- activeTimers[timerT] = fFunct
- return timerT
- end
- local function killTimer(fFunct)
- timerEvents[fFunct] = nil
- end
- function events.timer(timerT)
- if activeTimers[timerT] then
- --print("We has!")
- if timerEvents[activeTimers[timerT]] and activeTimers[timerT]() then
- --print("It wants MOAR!")
- activeTimers[os.startTimer(timerEvents[activeTimers[timerT]])] = activeTimers[timerT] -- Problem?
- activeTimers[timerT] = nil
- else
- activeTimers[timerT] = nil
- --print("STOP! HAMM0R TIEM!")
- end
- end
- end
- local sOldState
- function events.char(sChar)
- if sChar == "x" then
- bExit = true
- term.clear()
- term.setCursorPos(1, 1)
- print("Goodbye, and thank you for choosing Troll-Mart!")
- end
- local sCState = sState
- if sChar == "h" then
- sState = sState == "help" and sOldState or "help"
- elseif sChar == "m" then
- sState = "main"
- end
- if sState == "main" then
- if sChar == "g" then
- if not fs.exists("trollmart/") then
- fs.makeDir("trollmart")
- end
- local ct = getPasteT(nCurItem)
- if ct and ct.sName and ct.sLocation then
- local sFile, sCode = ct.sName, ct.sLocation -- Can tweak this later, and promt for filename/save dir.
- killTimer(render)
- plib.downloadAndSave(sCode, "trollmart/" .. sFile)
- dataValues["recentlydownloaded"] = "File saved as: " .. "trollmart/" .. sFile
- registerTimer(render, 0.1)
- end
- elseif sChar == "a" then -- Prev Category TODO: fix this bug
- -- nCurCat: Current category
- nCurCat = nCurCat - 1
- nCurItem = 1 -- Reset this. <-- bug
- elseif sChar == "d" then -- Next Category
- nCurCat = nCurCat + 1
- nCurItem = 1 -- Reset this (if we changed category <-- bug
- elseif sChar == "w" then -- Prev Item
- nCurItem = nCurItem - 1
- elseif sChar == "s" then -- Next Item "down is +"
- nCurItem = nCurItem + 1
- end
- nCurCat = m_clamp(nCurCat, 1, #orderedCats)
- nCurItem = m_clamp(nCurItem, 1, #getCatT())
- end
- if sCState ~= sState then
- sOldState = sCState
- end
- end
- --setmetatable(events, {__index = function(_, k) return function(...) print("Event: " .. k .. "; Args: ", unpack(arg)) end end})
- local function main(cmdArg)
- --local opt = unnamed_function(cmdArg) -- TODO: find function name for this.
- showSplash("Retrieving Nodes...")
- --loadConfig() --TODO: Impliment this
- -- Start render timer -- NEED TO DO BELOW getNode; until getNode uses not http.get
- -- Get pluginz.
- plib.getNode(config["sMasterLink"], pasteTree, true)
- orderCats()
- registerTimer(render, 0.1)
- -- Could cache this, too.
- term.setCursorPos(1,1)
- while not bExit do
- local sEvent, param1, param2 = os.pullEvent()
- local eRes = events[sEvent] and events[sEvent](param1, param2)
- end
- end
- -- Commandline helpers
- local function displayCmdArgs()
- print([[
- "tmart [--gui]" -> GUI
- GUI saves into 'trollmart/file'
- "tmart --help" -> This message
- "tmart --get [code] [--saveas 'file']" -> Gets [code]. Will prompt for savename if no metadata specifying filename or no --saveas.
- Will save into current directory.
- ]])
- end
- -- REAL main function*
- local function parse_args(...)
- --TODO: do this.
- end
- --
- -- commandline stuff. TODO: use parse_args() or something.
- local arg = {...}
- local cArg = {}
- for i = 1, #arg do
- cArg[i] = string.lower(arg[i])
- end
- if #arg == 0 or cArg[1] == "--gui" then
- main(arg)
- elseif cArg[1] == "--get" then
- local sFile = ""
- if not arg[2] then
- displayCmdArgs()
- error("Invalid paramters.")
- end
- if cArg[3] == "--saveas" and not arg[4] then
- displayCmdArgs()
- error("Invalid parameters.")
- end
- if cArg[3] == "--saveas" and arg[4] then
- sFile = arg[4]
- end
- showSplash("Downloading...")
- term.clear()
- local sData, meta = plib.rawGet(arg[2])
- if meta["error"] then
- print("An error occured; your file probably does not exist.")
- error("tmart: unable to find file.", 2)
- end
- if sFile == "" then
- if meta["filename"] then
- sFile = meta["filename"]
- else
- print("Input filename: ")
- sFile = read()
- end
- end
- while fs.exists(sFile) do
- print("File '" .. sFile .. "' already exists. Overwrite? (y/newfilename)")
- local inp = read()
- if inp ~= "y" then
- sFile = inp
- else
- break
- end
- end
- local hHandle = io.open(sFile, "w")
- if not hHandle then
- error("Unable to open file")
- end
- hHandle:write(sData)
- hHandle:close()
- print("Done.")
- local sInfo = ""
- if meta["version"] and meta["author"] and meta["filename"] then
- sInfo = " (" .. meta["filename"] .. " version " .. meta["version"] .. ", by " .. meta["author"] .. ")"
- end
- print("Your file is: " .. sFile .. sInfo)
- elseif arg[1] == "--help" then
- displayCmdArgs()
- elseif arg[1] == "--test" then
- print("tmart: --test No longer supported.")
- end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement