Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- local config = {
- host = "http://lbc.my1337.xyz",
- saveFile = ".lpcsave",
- theme = {
- bg = colors.white,
- text = colors.black,
- bar = colors.cyan,
- bartext = colors.white,
- altbg = colors.lightGray,
- altbar = colors.blue,
- altbartext = colors.lightGray,
- alttext = colors.gray,
- txtboxbg = colors.gray,
- txtboxtxt = colors.white,
- sideBarBg = colors.lightGray,
- sideBarTxt = colors.white,
- },
- }
- local tx,ty = term.getSize()
- local txc,tyc = tx/2+1,ty/2+1
- local currentAddress = ""
- local currentPin = ""
- local json = {}
- function deepcopy(orig)
- local orig_type = type(orig)
- local copy
- if orig_type == 'table' then
- copy = {}
- for orig_key, orig_value in next, orig, nil do
- copy[deepcopy(orig_key)] = deepcopy(orig_value)
- end
- setmetatable(copy, deepcopy(getmetatable(orig)))
- else -- number, string, boolean, etc
- copy = orig
- end
- return copy
- end
- do
- ------------------------------------------------------------------ utils
- local controls = {["\n"]="\\n", ["\r"]="\\r", ["\t"]="\\t", ["\b"]="\\b", ["\f"]="\\f", ["\""]="\\\"", ["\\"]="\\\\"}
- local function isArray(t)
- local max = 0
- for k,v in pairs(t) do
- if type(k) ~= "number" then
- return false
- elseif k > max then
- max = k
- end
- end
- return max == #t
- end
- local whites = {['\n']=true; ['r']=true; ['\t']=true; [' ']=true; [',']=true; [':']=true}
- function removeWhite(str)
- while whites[str:sub(1, 1)] do
- str = str:sub(2)
- end
- return str
- end
- ------------------------------------------------------------------ encoding
- local function encodeCommon(val, pretty, tabLevel, tTracking)
- local str = ""
- -- Tabbing util
- local function tab(s)
- str = str .. ("\t"):rep(tabLevel) .. s
- end
- local function arrEncoding(val, bracket, closeBracket, iterator, loopFunc)
- str = str .. bracket
- if pretty then
- str = str .. "\n"
- tabLevel = tabLevel + 1
- end
- for k,v in iterator(val) do
- tab("")
- loopFunc(k,v)
- str = str .. ","
- if pretty then str = str .. "\n" end
- end
- if pretty then
- tabLevel = tabLevel - 1
- end
- if str:sub(-2) == ",\n" then
- str = str:sub(1, -3) .. "\n"
- elseif str:sub(-1) == "," then
- str = str:sub(1, -2)
- end
- tab(closeBracket)
- end
- -- Table encoding
- if type(val) == "table" then
- assert(not tTracking[val], "Cannot encode a table holding itself recursively")
- tTracking[val] = true
- if isArray(val) then
- arrEncoding(val, "[", "]", ipairs, function(k,v)
- str = str .. encodeCommon(v, pretty, tabLevel, tTracking)
- end)
- else
- arrEncoding(val, "{", "}", pairs, function(k,v)
- assert(type(k) == "string", "JSON object keys must be strings", 2)
- str = str .. encodeCommon(k, pretty, tabLevel, tTracking)
- str = str .. (pretty and ": " or ":") .. encodeCommon(v, pretty, tabLevel, tTracking)
- end)
- end
- -- String encoding
- elseif type(val) == "string" then
- str = '"' .. val:gsub("[%c\"\\]", controls) .. '"'
- -- Number encoding
- elseif type(val) == "number" or type(val) == "boolean" then
- str = tostring(val)
- else
- error("JSON only supports arrays, objects, numbers, booleans, and strings", 2)
- end
- return str
- end
- function encode(val)
- return encodeCommon(val, false, 0, {})
- end
- function encodePretty(val)
- return encodeCommon(val, true, 0, {})
- end
- ------------------------------------------------------------------ decoding
- function parseBoolean(str)
- if str:sub(1, 4) == "true" then
- return true, removeWhite(str:sub(5))
- else
- return false, removeWhite(str:sub(6))
- end
- end
- function parseNull(str)
- return nil, removeWhite(str:sub(5))
- end
- local numChars = {['e']=true; ['E']=true; ['+']=true; ['-']=true; ['.']=true}
- function parseNumber(str)
- local i = 1
- while numChars[str:sub(i, i)] or tonumber(str:sub(i, i)) do
- i = i + 1
- end
- local val = tonumber(str:sub(1, i - 1))
- str = removeWhite(str:sub(i))
- return val, str
- end
- function parseString(str)
- local i,j = str:find('[^\\]"')
- local s = str:sub(2, j - 1)
- for k,v in pairs(controls) do
- s = s:gsub(v, k)
- end
- str = removeWhite(str:sub(j + 1))
- return s, str
- end
- function parseArray(str)
- str = removeWhite(str:sub(2))
- local val = {}
- local i = 1
- while str:sub(1, 1) ~= "]" do
- local v = nil
- v, str = parseValue(str)
- val[i] = v
- i = i + 1
- str = removeWhite(str)
- end
- str = removeWhite(str:sub(2))
- return val, str
- end
- function parseObject(str)
- str = removeWhite(str:sub(2))
- local val = {}
- while str:sub(1, 1) ~= "}" do
- local k, v = nil, nil
- k, v, str = parseMember(str)
- val[k] = v
- str = removeWhite(str)
- end
- str = removeWhite(str:sub(2))
- return val, str
- end
- function parseMember(str)
- local k = nil
- k, str = parseValue(str)
- local val = nil
- val, str = parseValue(str)
- return k, val, str
- end
- function parseValue(str)
- local fchar = str:sub(1, 1)
- if fchar == "{" then
- return parseObject(str)
- elseif fchar == "[" then
- return parseArray(str)
- elseif tonumber(fchar) ~= nil or numChars[fchar] then
- return parseNumber(str)
- elseif str:sub(1, 4) == "true" or str:sub(1, 5) == "false" then
- return parseBoolean(str)
- elseif fchar == "\"" then
- return parseString(str)
- elseif str:sub(1, 4) == "null" then
- return parseNull(str)
- end
- return nil
- end
- function json.decode(str)
- str = removeWhite(str)
- t = parseValue(str)
- return t
- end
- function decodeFromFile(path)
- local file = assert(fs.open(path, "r"))
- return json.decode(file.readAll())
- end
- end
- local glib = {}
- function glib.center(t,y)
- term.setCursorPos(txc-(#t/2),y)
- term.write(t)
- end
- function glib.spinner(x,y)
- local invar = {"-","\\","|","/"}
- while true do
- for i=1,4 do
- term.setCursorPos(x,y)
- term.write(invar[i])
- sleep(0.25)
- end
- end
- end
- function glib.banner(y1,y2,col)
- term.setBackgroundColor(col)
- for i=y1,y2 do
- term.setCursorPos(1,i)
- term.write(string.rep(" ",tx))
- end
- end
- function glib.square(x1,x2,y1,y2,col)
- term.setBackgroundColor(col)
- for i=y1,y2 do
- term.setCursorPos(x1,i)
- term.write(string.rep(" ",x2-x1+1))
- end
- end
- local blib = {scene = {}}
- function blib.newScene()
- blib.scene = {}
- end
- function blib.addButton(tx,x,y,px,py,cob,cot,callback)
- if x=="c" then
- x = txc - (#tx+px*2)/2
- end
- table.insert(blib.scene,{x,y,px,py,tx,cob,cot,callback})
- end
- function blib.saveScene()
- return deepcopy(blib.scene)
- end
- function blib.loadScene(newScene)
- blib.scene = newScene
- end
- function blib.deployScene()
- local bcheck = {}
- for k,v in ipairs(blib.scene) do
- term.setBackgroundColor(v[6])
- term.setTextColor(v[7])
- for i=1,v[4]*2+1 do
- term.setCursorPos(v[1],v[2]+i-1)
- term.write(string.rep(" ",#v[5]+(v[3]*2)))
- end
- term.setCursorPos(v[1]+v[3],v[2]+v[4])
- term.write(v[5])
- table.insert(bcheck, {v[1],v[2],v[1]+#v[5]+v[3]*2-1,v[2]+v[4]*2,k})
- end
- while true do
- local e,p1,p2,p3 = os.pullEvent()
- local success = false
- if e=="mouse_click" then
- local b,x,y = p1,p2,p3
- --local bufferdebug = x..";"..y..": "
- for k,v in ipairs(bcheck) do
- --bufferdebug = bufferdebug.."("..math.floor(v[1])..","..math.floor(v[2]).."-"..math.floor(v[3])..","..math.floor(v[4])..") "
- if x >= math.floor(v[1]) and x <= math.floor(v[3]) then
- if y >= math.floor(v[2]) and y <= math.floor(v[4]) then
- blib.scene[v[5]][8]()
- success = true
- break
- end
- end
- end
- --term.setCursorPos(1,ty)
- --term.write(bufferdebug)
- end
- if success then break end
- end
- end
- function limitRead( nlim, cOverlay)
- cOverlay=cOverlay or nil
- local px,py = term.getCursorPos()
- local txt = ""
- local boxOffset = 0
- local strPos = 1
- term.setCursorBlink(true)
- while true do
- e,p1 = os.pullEvent()
- if e=="key" then
- local key = p1
- if key==keys.left then
- if strPos>1 then
- strPos=strPos-1
- if strPos-boxOffset==0 then
- boxOffset=boxOffset-1
- end
- end
- elseif key==keys.right then
- if strPos<=#txt then
- strPos=strPos+1
- if strPos-boxOffset>nlim then
- boxOffset=boxOffset+1
- end
- end
- elseif key==keys.enter then
- break
- elseif key==keys.backspace then
- if strPos~=1 then
- txt=txt:sub(1,strPos-2)..txt:sub(strPos,#txt)
- strPos=strPos-1
- if strPos-boxOffset==0 then
- boxOffset=boxOffset-1
- end
- end
- elseif key==keys.delete then
- if strPos-1~=#txt then
- txt=txt:sub(1,strPos-1)..txt:sub(strPos+1,#txt)
- end
- end
- elseif e=="char" then
- txt = txt:sub(1,strPos-1)..p1..txt:sub(strPos,#txt)
- strPos=strPos+1
- if strPos-1-boxOffset>=nlim then
- boxOffset=boxOffset+1
- end
- elseif e=="paste" then
- txt = txt:sub(1,strPos-1)..p1..txt:sub(strPos,#txt)
- end
- term.setCursorPos(px,py)
- write(string.rep(" ",nlim))
- term.setCursorPos(px,py)
- if cOverlay==nil then
- write(txt:sub(boxOffset+1,boxOffset+nlim))
- else
- write(string.rep(cOverlay,#txt):sub(boxOffset+1,nlim+boxOffset))
- end
- term.setCursorPos(px+strPos-1-boxOffset,py)
- end
- term.setCursorBlink(false)
- return txt
- end
- function httpCall(url,verify)
- http.request(url)
- while true do
- local x = {os.pullEvent()}
- local e = x[1]
- table.remove(x,1)
- if e=="http_success" then
- local get = x[2].readAll():match("[^%s]+")
- if verify(get) then
- return true,get
- end
- break
- elseif e=="http_failure" then
- break
- end
- end
- end
- function getInfo(x1,x2,y,label,colorsch,verify,over)
- label = label or ""
- local ubg = config.theme.bg
- local utx = config.theme.text
- if colorsch == "alt" then
- ubg = config.theme.altbg
- utx = config.theme.alttext
- end
- local stx = x1
- local enx = x2
- if verify then
- enx = enx-1
- end
- if label ~= "" then
- stx = x1+#label+1
- end
- term.setCursorPos(x1,y)
- term.setBackgroundColor(ubg)
- term.setTextColor(utx)
- term.write(label)
- local get = ""
- local function doIt()
- term.setCursorPos(stx,y)
- term.setBackgroundColor(config.theme.txtboxbg)
- term.setTextColor(config.theme.txtboxtxt)
- term.write(string.rep(" ",enx-stx+1))
- term.setCursorPos(stx,y)
- return limitRead(enx-stx+1,over)
- end
- if verify then
- --[[
- verify = {
- subdom = "/api/changePin"
- exq = {
- oldPin = "$INPUT$",
- newPin = "$INPUT$",
- address = "0000123412341234"
- }
- callback = function(inp)
- if inp=="SUCCESS_PIN_CHANGED" then
- return true
- end
- return false
- end
- }
- ]]
- local success = false
- local reinp
- term.setBackgroundColor(colors.orange)
- term.setCursorPos(x2,y)
- term.write(" ")
- while not success do
- reinp = doIt()
- if verify.preprocess then
- reinp = verify.preprocess(reinp)
- end
- local sbhost = config.host..verify.subdom.."?"
- for k,v in pairs(verify.exq) do
- if v=="$INPUT$" then
- v = tostring(reinp)
- end
- sbhost = sbhost..tostring(k).."="..v.."&"
- end
- sbhost = sbhost:sub(1,#sbhost-1)
- term.setBackgroundColor(ubg)
- term.setTextColor(utx)
- parallel.waitForAny(function() glib.spinner(x2,y) end, function()
- success = httpCall(sbhost,verify.callback)
- end)
- if not success then
- term.setCursorPos(x2,y)
- term.setBackgroundColor(colors.red)
- term.write(" ")
- end
- end
- term.setCursorPos(x2,y)
- term.setBackgroundColor(colors.green)
- term.write(" ")
- return reinp
- else
- return doIt()
- end
- end
- function getInfoPrerender(x1,x2,y,label,colorsch,verify)
- label = label or ""
- local ubg = config.theme.bg
- local utx = config.theme.text
- if colorsch == "alt" then
- ubg = config.theme.altbg
- utx = config.theme.alttext
- end
- local stx = x1
- local enx = x2
- if verify then
- enx = enx-1
- end
- if label ~= "" then
- stx = x1+#label+1
- end
- term.setCursorPos(x1,y)
- term.setBackgroundColor(ubg)
- term.setTextColor(utx)
- term.write(label)
- term.setCursorPos(stx,y)
- term.setBackgroundColor(config.theme.txtboxbg)
- term.setTextColor(config.theme.txtboxtxt)
- term.write(string.rep(" ",enx-stx+1))
- if verify then
- term.setBackgroundColor(colors.orange)
- term.setCursorPos(x2,y)
- term.write(" ")
- end
- end
- local pages = {}
- pages.nextAction = ""
- function pages.setup()
- term.setBackgroundColor(config.theme.bg)
- term.clear()
- term.setBackgroundColor(config.theme.altbg)
- term.setTextColor(config.theme.alttext)
- glib.banner(tyc-3,tyc+3,config.theme.altbg)
- glib.center("Please enter LBC account information:",tyc-2)
- getInfoPrerender(2, tx-1,tyc+2,"PIN:","alt",true)
- local inpAD, inpPIN
- inpAD = getInfo(2,tx-1,tyc,"LBC Address:","alt",{
- subdom = "/api/checkBalance",
- exq = {
- address = "$INPUT$",
- },
- preprocess = function(inp)
- return inp:gsub("%-","")
- end,
- callback = function(inp)
- if tonumber(inp) then
- return true
- end
- end
- })
- inpPIN = getInfo(2, tx-1, tyc+2,"PIN:","alt",{
- subdom = "/api/changePin",
- exq = {
- oldPin = "$INPUT$",
- newPin = "$INPUT$",
- address = inpAD
- },
- callback = function(inp)
- if inp=="SUCCESS_PIN_CHANGED" then
- return true
- end
- return false
- end
- },"*")
- local handle = fs.open(config.saveFile,"w")
- handle.write(inpAD..";"..inpPIN)
- handle.close()
- currentAddress = inpAD
- pages.main()
- end
- function pages.create()
- term.setBackgroundColor(config.theme.bg)
- term.clear()
- term.setBackgroundColor(config.theme.altbg)
- term.setTextColor(config.theme.alttext)
- glib.banner(tyc-3,tyc+3,config.theme.altbg)
- local succ,info = httpCall(config.host.."/api/newAddress",function()
- return true
- end)
- local split = info:find("%;")
- local addr = info:sub(1,split-1)
- local pin = info:sub(split+1)
- local addru = addr:sub(1,4).."-"..addr:sub(5,8).."-"..addr:sub(9,12).."-"..addr:sub(13,16)
- glib.center("Your Account Information: "..addru,tyc-2)
- glib.center("PIN: "..pin,tyc)
- local npin = getInfo(2,tx-1,tyc+2,"New PIN (Empty to Keep Old):","alt", {
- subdom = "/api/changePin",
- exq = {
- oldPin = pin,
- newPin = "$INPUT$",
- address = addr,
- },
- callback = function(inp)
- if inp=="SUCCESS_PIN_CHANGED" then
- return true
- end
- return false
- end,
- preprocess = function(inp)
- if inp=="" then
- return pin
- else
- return inp
- end
- end,
- })
- local handle = fs.open(config.saveFile,"w")
- handle.write(addr..";"..npin)
- handle.close()
- currentAddress = addr
- pages.nextAction = "main"
- end
- function pages.first()
- term.setBackgroundColor(config.theme.bg)
- term.clear()
- term.setBackgroundColor(config.theme.altbg)
- term.setTextColor(config.theme.alttext)
- glib.banner(tyc-3,tyc+3,config.theme.altbg)
- glib.center("Welcome to LPC",tyc-2)
- blib.newScene()
- --blib.addButton(tx,x,y,px,py,cob,cot)
- blib.addButton("Account Login","c",tyc,0,0,config.theme.txtboxbg,config.theme.txtboxtxt,function()
- pages.setup()
- end)
- blib.addButton("Create Account","c",tyc+2,0,0,config.theme.txtboxbg,config.theme.txtboxtxt,function()
- pages.create()
- end)
- blib.addButton("X",tx,1,0,0,colors.red,colors.white,function() pages.nextAction = "exitApp" end)
- blib.deployScene()
- end
- function pages.main()
- term.setBackgroundColor(config.theme.bg)
- term.clear()
- glib.banner(1,3,config.theme.bar)
- glib.center("Loading...",2)
- local succ,balance = httpCall(config.host.."/api/checkBalance?address="..currentAddress,function() return true end)
- term.setTextColor(config.theme.bartext)
- glib.center("Your current balance is "..balance.."LBC",2)
- blib.newScene()
- --blib.addButton(tx,x,y,px,py,cob,cot,callback)
- blib.addButton("Refresh",1,ty,txc-4,0,colors.gray,colors.white,function()
- glib.banner(1,3,config.theme.bar)
- parallel.waitForAny(function() glib.spinner(txc,2) end, function()
- term.setBackgroundColor(config.theme.bar)
- term.setTextColor(config.theme.bartext)
- local succ,balance = httpCall(config.host.."/api/checkBalance?address="..currentAddress,function() return true end)
- glib.center("Your current balance is "..balance.."LBC",2)
- end)
- end)
- --[[blib.addButton("Sign out",tx-8,1,0,0,config.theme.altbar,config.theme.altbartext,function()
- fs.delete(config.saveFile)
- currentAddress = ""
- currentPin = ""
- pages.nextAction = "first"
- end)]]
- blib.addButton("X",tx,1,0,0,colors.red,colors.white,function() pages.nextAction = "exitApp" end)
- blib.addButton(">",1,(ty-3)/2+2,0,1,config.theme.sideBarBg,config.theme.sideBarTxt,function()
- local oldScene = blib.saveScene()
- term.setBackgroundColor(config.theme.sideBarBg)
- for i=1,16,2.5 do
- for j=4,ty-1 do
- term.setCursorPos(1,j)
- term.write(string.rep(" ",i))
- end
- sleep(0)
- end
- local menuActions = {
- {"Sign Out",function()
- fs.delete(config.saveFile)
- currentAddress = ""
- currentPin = ""
- pages.nextAction = "first"
- end,ty-2}
- }
- blib.newScene()
- local regCount = 0
- for k,v in ipairs(menuActions) do
- blib.addButton(v[1],9-(#v[1]/2),v[3] or regCount*2+3,0,0,config.theme.sideBarBg,config.theme.sideBarTxt,v[2])
- if v[3] then regCount = regCount+1 end
- end
- blib.addButton("<",16,(ty-3)/2+2,0,1,config.theme.sideBarBg,config.theme.sideBarTxt,function() glib.banner(4,ty-1,config.theme.bg) end)
- blib.deployScene()
- blib.loadScene(oldScene)
- end)
- while pages.nextAction == "" do
- blib.deployScene()
- end
- end
- function pageMan()
- while pages.nextAction~="exitApp" do
- local tstore = pages.nextAction
- pages.nextAction=""
- pages[tstore]()
- end
- end
- local success = false
- if fs.exists(config.saveFile) then
- local handle = fs.open(config.saveFile,"r")
- local info = handle.readAll()
- handle.close()
- local semi = info:find(";")
- if semi then
- local addr = info:sub(1,semi-1)
- local pin = info:sub(semi+1)
- if #addr==16 then
- success = httpCall(config.host.."/api/changePin?address="..addr.."&oldPin="..pin.."&newPin="..pin,function(get)
- if get=="SUCCESS_PIN_CHANGED" then
- return true
- end
- end)
- if success then
- currentAddress = addr
- currentPin = pin
- pages.nextAction = "main"
- end
- end
- end
- end
- if not success then
- pages.nextAction = "first"
- end
- pageMan()
- term.setBackgroundColor(colors.black)
- term.setTextColor(colors.white)
- term.clear()
- glib.center("Thank you for using LPC!",2)
- term.setCursorPos(1,4)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement