Advertisement
TheRockettek

Untitled

Apr 9th, 2017
147
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. local baseUrl = "http://86.11.11.101:9090/"
  2. local dynamicUrl = ""
  3.  
  4. --------------------------------------------------------------------------------
  5. --------------------------------------------------------------------------------
  6. -- JSON4Lua: JSON encoding / decoding support for the Lua language.
  7. -- json Module.
  8. -- Author: Craig Mason-Jones
  9. -- Homepage: http://json.luaforge.net/
  10. -- Version: 0.9.40
  11. -- This module is released under the MIT License (MIT).
  12.  
  13. -- edited for brevity
  14.  
  15. local errormsg = printError
  16. local base = _G
  17. local decode_scanArray
  18. local decode_scanComment
  19. local decode_scanConstant
  20. local decode_scanNumber
  21. local decode_scanObject
  22. local decode_scanString
  23. local decode_scanWhitespace
  24. local encodeString
  25. local isArray
  26. local isEncodable
  27.  
  28. local function encode (v)
  29.   -- Handle nil values
  30.   if v==nil then
  31.     return "null"
  32.   end
  33.  
  34.   local vtype = base.type(v)  
  35.  
  36.   -- Handle strings
  37.   if vtype=='string' then    
  38.     return '"' .. encodeString(v) .. '"'            -- Need to handle encoding in string
  39.   end
  40.  
  41.   -- Handle booleans
  42.   if vtype=='number' or vtype=='boolean' then
  43.     return base.tostring(v)
  44.   end
  45.  
  46.   -- Handle tables
  47.   if vtype=='table' then
  48.     local rval = {}
  49.     -- Consider arrays separately
  50.     local bArray, maxCount = isArray(v)
  51.     if bArray then
  52.       for i = 1,maxCount do
  53.         table.insert(rval, encode(v[i]))
  54.       end
  55.     else        -- An object, not an array
  56.       for i,j in base.pairs(v) do
  57.         if isEncodable(i) and isEncodable(j) then
  58.           table.insert(rval, '"' .. encodeString(i) .. '":' .. encode(j))
  59.         end
  60.       end
  61.     end
  62.     if bArray then
  63.       return '[' .. table.concat(rval,',') ..']'
  64.     else
  65.       return '{' .. table.concat(rval,',') .. '}'
  66.     end
  67.   end
  68.  
  69.   -- Handle null values
  70.   if vtype=='function' and v==null then
  71.     return 'null'
  72.   end
  73.  
  74.   base.assert(false,'encode attempt to encode unsupported type ' .. vtype .. ':' .. base.tostring(v))
  75. end
  76.  
  77. local function decode(s, startPos)
  78.   startPos = startPos and startPos or 1
  79.   startPos = decode_scanWhitespace(s,startPos)
  80.   base.assert(startPos<=string.len(s), 'Unterminated JSON encoded object found at position in [' .. s .. ']')
  81.   local curChar = string.sub(s,startPos,startPos)
  82.   -- Object
  83.   if curChar=='{' then
  84.     return decode_scanObject(s,startPos)
  85.   end
  86.   -- Array
  87.   if curChar=='[' then
  88.     return decode_scanArray(s,startPos)
  89.   end
  90.   -- Number
  91.   if string.find("+-0123456789.e", curChar, 1, true) then
  92.     return decode_scanNumber(s,startPos)
  93.   end
  94.   -- String
  95.   if curChar==[["]] or curChar==[[']] then
  96.    return decode_scanString(s,startPos)
  97.  end
  98.  if string.sub(s,startPos,startPos+1)=='/*' then
  99.    return decode(s, decode_scanComment(s,startPos))
  100.  end
  101.  -- Otherwise, it must be a constant
  102.  return decode_scanConstant(s,startPos)
  103. end
  104.  
  105. local function null()
  106.  return null -- so json.null() will also return null ;-)
  107. end
  108.  
  109.  
  110. function decode_scanArray(s,startPos)
  111.  local array = {}      -- The return value
  112.  local stringLen = string.len(s)
  113.  base.assert(string.sub(s,startPos,startPos)=='[','decode_scanArray called but array does not start at position ' .. startPos .. ' in string:\n'..s )
  114.  startPos = startPos + 1
  115.  -- Infinite loop for array elements
  116.  repeat
  117.    startPos = decode_scanWhitespace(s,startPos)
  118.    base.assert(startPos<=stringLen,'JSON String ended unexpectedly scanning array.')
  119.    local curChar = string.sub(s,startPos,startPos)
  120.    if (curChar==']') then
  121.      return array, startPos+1
  122.    end
  123.    if (curChar==',') then
  124.      startPos = decode_scanWhitespace(s,startPos+1)
  125.    end
  126.    base.assert(startPos<=stringLen, 'JSON String ended unexpectedly scanning array.')
  127.    object, startPos = decode(s,startPos)
  128.    table.insert(array,object)
  129.  until false
  130. end
  131.  
  132. function decode_scanComment(s, startPos)
  133.  base.assert( string.sub(s,startPos,startPos+1)=='/*', "decode_scanComment called but comment does not start at position " .. startPos)
  134.  local endPos = string.find(s,'*/',startPos+2)
  135.  base.assert(endPos~=nil, "Unterminated comment in string at " .. startPos)
  136.  return endPos+2  
  137. end
  138.  
  139. function decode_scanConstant(s, startPos)
  140.  local consts = { ["true"] = true, ["false"] = false, ["null"] = nil }
  141.  local constNames = {"true","false","null"}
  142.  
  143.  for i,k in base.pairs(constNames) do
  144.    --print ("[" .. string.sub(s,startPos, startPos + string.len(k) -1) .."]", k)
  145.    if string.sub(s,startPos, startPos + string.len(k) -1 )==k then
  146.      return consts[k], startPos + string.len(k)
  147.    end
  148.  end
  149.  base.assert(nil, 'Failed to scan constant from string ' .. s .. ' at starting position ' .. startPos)
  150. end
  151.  
  152. function decode_scanNumber(s,startPos)
  153.  local endPos = startPos+1
  154.  local stringLen = string.len(s)
  155.  local acceptableChars = "+-0123456789.e"
  156.  while (string.find(acceptableChars, string.sub(s,endPos,endPos), 1, true)
  157.        and endPos<=stringLen
  158.        ) do
  159.    endPos = endPos + 1
  160.  end
  161.  local stringValue = 'return ' .. string.sub(s,startPos, endPos-1)
  162.  local stringEval = base.loadstring(stringValue)
  163.  base.assert(stringEval, 'Failed to scan number [ ' .. stringValue .. '] in JSON string at position ' .. startPos .. ' : ' .. endPos)
  164.  return stringEval(), endPos
  165. end
  166.  
  167. function decode_scanObject(s,startPos)
  168.  local object = {}
  169.  local stringLen = string.len(s)
  170.  local key, value
  171.  base.assert(string.sub(s,startPos,startPos)=='{','decode_scanObject called but object does not start at position ' .. startPos .. ' in string:\n' .. s)
  172.  startPos = startPos + 1
  173.  repeat
  174.    startPos = decode_scanWhitespace(s,startPos)
  175.    base.assert(startPos<=stringLen, 'JSON string ended unexpectedly while scanning object.')
  176.    local curChar = string.sub(s,startPos,startPos)
  177.    if (curChar=='}') then
  178.      return object,startPos+1
  179.    end
  180.    if (curChar==',') then
  181.      startPos = decode_scanWhitespace(s,startPos+1)
  182.    end
  183.    base.assert(startPos<=stringLen, 'JSON string ended unexpectedly scanning object.')
  184.    -- Scan the key
  185.    key, startPos = decode(s,startPos)
  186.    base.assert(startPos<=stringLen, 'JSON string ended unexpectedly searching for value of key ' .. key)
  187.    startPos = decode_scanWhitespace(s,startPos)
  188.    base.assert(startPos<=stringLen, 'JSON string ended unexpectedly searching for value of key ' .. key)
  189.    base.assert(string.sub(s,startPos,startPos)==':','JSON object key-value assignment mal-formed at ' .. startPos)
  190.    startPos = decode_scanWhitespace(s,startPos+1)
  191.    base.assert(startPos<=stringLen, 'JSON string ended unexpectedly searching for value of key ' .. key)
  192.    value, startPos = decode(s,startPos)
  193.    object[key]=value
  194.  until false   -- infinite loop while key-value pairs are found
  195. end
  196.  
  197. function decode_scanString(s,startPos)
  198.  base.assert(startPos, 'decode_scanString(..) called without start position')
  199.  local startChar = string.sub(s,startPos,startPos)
  200.  base.assert(startChar==[[']] or startChar==[["]],'decode_scanString called for a non-string')
  201.   local escaped = false
  202.   local endPos = startPos + 1
  203.   local bEnded = false
  204.   local stringLen = string.len(s)
  205.   repeat
  206.     local curChar = string.sub(s,endPos,endPos)
  207.     -- Character escaping is only used to escape the string delimiters
  208.     if not escaped then
  209.       if curChar==[[\]] then
  210.         escaped = true
  211.       else
  212.         bEnded = curChar==startChar
  213.       end
  214.     else
  215.       -- If we're escaped, we accept the current character come what may
  216.       escaped = false
  217.     end
  218.     endPos = endPos + 1
  219.     base.assert(endPos <= stringLen+1, "String decoding failed: unterminated string at position " .. endPos)
  220.   until bEnded
  221.   local stringValue = 'return ' .. string.sub(s, startPos, endPos-1)
  222.   local stringEval = base.loadstring(stringValue)
  223.   base.assert(stringEval, 'Failed to load string [ ' .. stringValue .. '] in JSON4Lua.decode_scanString at position ' .. startPos .. ' : ' .. endPos)
  224.   return stringEval(), endPos  
  225. end
  226.  
  227. function decode_scanWhitespace(s,startPos)
  228.   local whitespace=" \n\r\t"
  229.   local stringLen = string.len(s)
  230.   while ( string.find(whitespace, string.sub(s,startPos,startPos), 1, true)  and startPos <= stringLen) do
  231.     startPos = startPos + 1
  232.   end
  233.   return startPos
  234. end
  235.  
  236. function encodeString(s)
  237.   s = string.gsub(s,'\\','\\\\')
  238.   s = string.gsub(s,'"','\\"')
  239.   s = string.gsub(s,'\n','\\n')
  240.   s = string.gsub(s,'\t','\\t')
  241.   return s
  242. end
  243.  
  244. function isArray(t)
  245.   -- Next we count all the elements, ensuring that any non-indexed elements are not-encodable
  246.   -- (with the possible exception of 'n')
  247.   local maxIndex = 0
  248.   for k,v in base.pairs(t) do
  249.     if (base.type(k)=='number' and math.floor(k)==k and 1<=k) then      -- k,v is an indexed pair
  250.       if (not isEncodable(v)) then return false end     -- All array elements must be encodable
  251.       maxIndex = math.max(maxIndex,k)
  252.     else
  253.       if (k=='n') then
  254.         if v ~= table.getn(t) then return false end  -- False if n does not hold the number of elements
  255.       else -- Else of (k=='n')
  256.         if isEncodable(v) then return false end
  257.       end  -- End of (k~='n')
  258.     end -- End of k,v not an indexed pair
  259.   end  -- End of loop across all pairs
  260.   return true, maxIndex
  261. end
  262.  
  263. function isEncodable(o)
  264.   local t = base.type(o)
  265.   return (t=='string' or t=='boolean' or t=='number' or t=='nil' or t=='table') or (t=='function' and o==null)
  266. end
  267.  
  268. --------------------------------------------------------------------------------
  269. --------------------------------------------------------------------------------
  270.  
  271. -- ComputerCraft IRC client code begins here
  272.  
  273. --------------------------------------------------------------------------------
  274. --------------------------------------------------------------------------------
  275.  
  276. local defaultNick = "cc-irc-client"..tostring(math.random(1,1000))
  277. local nick = defaultNick
  278. local password = nil
  279. local newNick = ""
  280.  
  281. local counter = 0 -- used by the qwebirc protocol for something
  282. local sessionID = "" -- as is this, although a bit more self evident
  283.  
  284. local currentChannel = "status"
  285. local quitReason = ""
  286.  
  287. local BUFFERSIZE = 100 -- keep this many lines in each windows history
  288. local offset = 0 -- for scrolling, not implemented
  289.  
  290. local w,h = term.getSize()
  291. local legacy = true --(window == nil) CC v < 1.6 doesn't have the window API which would be useful, but maybe later
  292. local windows = {}
  293. local winnumbers = {}
  294. local seen = {}
  295. if not legacy then
  296.     local origTerm = term.current()
  297.     windows["input"] = window.create(origTerm,1,h-1,w,2)
  298.     windows["status"] = window.create(origTerm,1,1,w,h-2)
  299.     windows["current"] = windows["status"]
  300. else
  301.     windows["status"] = {}
  302.     windows["current"] = windows["status"]
  303. end
  304. table.insert(winnumbers,"status")
  305. seen[windows["status"]] = true
  306. local lock = "off"
  307.  
  308. local win2num = function(win)
  309.     for k,v in pairs(winnumbers) do
  310.         if v == win then return k end
  311.     end
  312.     return nil
  313. end
  314.  
  315. --os.loadAPI("json")
  316.  
  317. local post = function(url,data)
  318.     local cacheAvoidance = "abc"..tostring(math.random(0,10000)) -- not sure if this is needed...
  319.     local resp = http.post(baseUrl..dynamicUrl.."e/"..url,"r="..cacheAvoidance.."&t="..tostring(counter)..data)
  320.     counter = counter + 1
  321.     return resp
  322. end
  323.  
  324. -- better responsiveness with asynchronous methods as we usually let the recv couroutine handle the responses
  325. local request = function(url,data)
  326.     local cacheAvoidance = "abc"..tostring(math.random(0,10000)) -- not sure if this is needed...
  327.     http.request(baseUrl..dynamicUrl.."e/"..url,"r="..cacheAvoidance.."&t="..tostring(counter)..data)
  328.     counter = counter + 1
  329. end
  330.  
  331. -- these special URLs are used by the webchat server for different methods
  332. local send = function(data)
  333.     return request("p","&s="..sessionID.."&c="..textutils.urlEncode(data))
  334. end
  335.  
  336. local recv = function()
  337.     return post("s","&s="..sessionID)
  338. end
  339.  
  340. local connect = function(password)
  341.   if password ~= nil then
  342.     return post("n","&nick="..nick.."&password="..password)
  343.   else
  344.     return post("n","&nick="..nick)
  345.   end
  346. end
  347.  
  348. -- some helper functions
  349. local pong = function(data)
  350.     return send("PONG :"..data)
  351. end
  352.  
  353. local quit = function(_reason)
  354.     local reason = _reason or ""
  355.     return send("QUIT :"..reason)
  356. end
  357.  
  358. -- lua default string methods suck :/
  359. local split = function(str,sep)
  360.         local sep, fields = sep or ":", {}
  361.         local pattern = string.format("([^%s]+)", sep)
  362.         str:gsub(pattern, function(c) fields[#fields+1] = c end)
  363.         return fields
  364. end
  365.  
  366. local exit = function(reason)
  367.     local r = reason or ""
  368.     term.clear()
  369.     term.setCursorPos(1,1)
  370.     print(r)
  371. end
  372.  
  373. -- for debug
  374. local writeLine
  375. writeLine = function(data,line)
  376.     if not (type(data) == "table") then
  377.         return tostring(data)
  378.     end
  379.     for i=1,#data do
  380.         if type(data[i]) == "table" then
  381.             line = writeLine(data[i],line)
  382.         elseif data[i] ~= nick then
  383.             line = line..data[i].." "
  384.         end
  385.     end
  386.     return line
  387. end
  388.  
  389. -- some IRC protocol codes we handle "properly"
  390. local codes = {}
  391. codes["371"] = "RPL_INFO"
  392. codes["374"] = "RPL_ENDINFO"
  393. codes["375"] = "RPL_MOTDSTART"
  394. codes["372"] = "RPL_MOTD"
  395. codes["376"] = "RPL_ENDOFMOTD"
  396. codes["352"] = "RPL_WHOREPLY"
  397.  
  398. commands = {}
  399. commands["join"] = function(input)
  400.   if not input[2] then
  401.     errormsg("No channel specified!")
  402.     return true
  403.   end
  404.     local channel = input[2]:lower()
  405.     if channel:sub(1,1) ~= "#" then
  406.         errormsg("Invalid channel name!")
  407.         return true
  408.     end
  409.     currentChannel = channel
  410.     if legacy then
  411.         windows[channel] = {}
  412.     end
  413.     windows["current"] = windows[currentChannel]
  414.     table.insert(winnumbers,channel)
  415.     seen[windows[channel]] = true
  416.     send("JOIN "..channel)
  417.     return true
  418. end
  419.  
  420. commands["who"] = function(input)
  421.     local channel = input[2]
  422.     send("WHO "..channel)
  423.     return true
  424. end
  425.  
  426. commands["whois"] = function(input)
  427.     local user = input[2]
  428.     send("WHOIS "..user)
  429.     return true
  430. end
  431.  
  432. commands["part"] = function(input)
  433.     local channel = currentChannel
  434.     if channel == "status" then
  435.         errormsg("Can't part status window!")
  436.     else
  437.         local nwin
  438.         for i,v in pairs(winnumbers) do
  439.             if v == channel then
  440.                 nwin = i
  441.                 break
  442.             end
  443.         end
  444.         table.remove(winnumbers,nwin)
  445.         seen[windows[channel]] = nil
  446.         windows[channel] = nil
  447.         currentChannel = winnumbers[#winnumbers]
  448.         print(currentChannel)
  449.         windows["current"] = windows[currentChannel]
  450.         seen[windows["current"]] = true
  451.         if channel:sub(1,1) == "#" then
  452.             send("PART "..channel)
  453.         end
  454.     end
  455.     return true
  456. end
  457.  
  458. commands["quit"] = function(input)
  459.     quit(input[2])
  460.     return false
  461. end
  462.  
  463. commands["window"] = function(input)
  464.     local nwin = tonumber(input[2])
  465.     if not nwin then
  466.         errormsg("Invalid window number!")
  467.     elseif nwin > #winnumbers or nwin < 1 then
  468.         errormsg("Invalid window number!")
  469.     else
  470.         windows["current"] = windows[winnumbers[nwin]]
  471.         seen[windows["current"]] = true
  472.         currentChannel = winnumbers[nwin]
  473.     end
  474.     return true
  475. end
  476.  
  477. commands["nick"] = function(input)
  478.     local nickname = input[2]
  479.     if nickname then
  480.         send("NICK "..nickname)
  481.         newNick = nickname
  482.         writeToWin(windows["status"],"Changed nick to: "..newNick)
  483.     else
  484.         errormsg("No nickname given.")
  485.     end
  486.     return true
  487. end
  488.  
  489. commands["query"] = function(input)
  490.     local user = input[2]
  491.     if user then
  492.         currentChannel = user
  493.         if legacy then
  494.             windows[user] = {}
  495.         end
  496.         windows["current"] = windows[currentChannel]
  497.         table.insert(winnumbers,user)
  498.         seen[windows[user]] = true
  499.         --send("JOIN "..channel)
  500.     else
  501.         errormsg("No username given.")
  502.     end
  503.     return true
  504. end
  505.  
  506. commands["help"] = function(input)
  507.     writeToWin(windows["status"],"Available commands:")
  508.     for k,v in pairs(commands) do
  509.         writeToWin(windows["status"],"- "..k)
  510.     end
  511.     return true
  512. end
  513.  
  514. local alias = {}
  515. alias["w"] = "window"
  516. alias["j"] = "join"
  517. alias["p"] = "part"
  518. alias["q"] = "quit"
  519. alias["exit"] = "quit"
  520. alias["e"] = "quit"
  521. alias["n"] = "nick"
  522. alias["qr"] = "query"
  523. alias["h"] = "help"
  524.  
  525. -- helper
  526. local errormsg = function(msg)
  527.     print(msg)
  528. end
  529.  
  530. local handleResponse = function(data)
  531.     dat = data
  532.     for i = 1, #data do
  533.         local id = data[i][2]
  534.         if id == "PING" then
  535.             pong(data[i][4][1])
  536.         elseif id == "PRIVMSG" then
  537.             local senderDetails = data[i][3]
  538.             local sender = senderDetails:sub(1,senderDetails:find("!")-1)
  539.             local channel = data[i][4][1]:lower()
  540.             if channel == nick then
  541.                 channel = sender
  542.             end
  543.             local msg = data[i][4][2]
  544.             print("<"..sender.."> "..msg)
  545.         elseif id == "376" then
  546.             print("Joining channel")
  547.             send("JOIN #" .. channel)
  548.         elseif id == "NICK" then
  549.             if newNick ~= "" then
  550.                 local name = data[i][3]:sub(1,data[i][3]:find("!")-1)
  551.                 if name == nick then
  552.                     nick = newNick
  553.                     newNick = ""
  554.                 end
  555.             end
  556.         elseif id == "433" then
  557.             print("Nickname already in use!")
  558.             newNick = ""
  559.         elseif codes[id] then
  560.             print(data[i][4][2])
  561.         end
  562.     end
  563. end
  564.  
  565.  
  566. local receive = function()
  567.     resp = recv()
  568.     while resp do
  569.         _data = resp.readAll()
  570.         if #_data > 0 then
  571.             data = decode(_data)
  572.             handleResponse(data)
  573.         end
  574.         resp = recv()
  575.     end
  576.     quitReason = "Disconnected!"
  577. end
  578.  
  579. local nick = "twitchplayzcomputercraft"
  580. local password = "oauth:pq386z6ttls22h7bmsqbiuil1i2ns3"
  581. local channel = "rockettek"
  582.  
  583. local resp = connect(password)
  584. if not resp then printError("Unable to connect!") return end
  585. local _data = resp.readAll()
  586. local data = decode(_data)
  587. local sessionID = data[2]
  588. errormsg("Got sessionID: "..sessionID)
  589.  
  590. receive()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement