Advertisement
1lann

global chat

Jan 31st, 2015
130
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 13.23 KB | None | 0 0
  1. --
  2. --  JSON API by Elvis Jerricco: http://pastebin.com/4nRg9CHU
  3. --
  4.  
  5. local encode, encodePretty, parseBoolean, parseNull, parseString, parseArray
  6. local parseObject, parseMember, parseValue, decode, decodeFromFile
  7.  
  8. local controls = {["\n"]="\\n", ["\r"]="\\r", ["\t"]="\\t", ["\b"]="\\b", ["\f"]="\\f", ["\""]="\\\"", ["\\"]="\\\\"}
  9.  
  10. local function isArray(t)
  11.     local max = 0
  12.     for k,v in pairs(t) do
  13.         if type(k) ~= "number" then
  14.             return false
  15.         elseif k > max then
  16.             max = k
  17.         end
  18.     end
  19.     return max == #t
  20. end
  21.  
  22. local whites = {['\n']=true; ['r']=true; ['\t']=true; [' ']=true; [',']=true; [':']=true}
  23. function removeWhite(str)
  24.     while whites[str:sub(1, 1)] do
  25.         str = str:sub(2)
  26.     end
  27.     return str
  28. end
  29.  
  30.  
  31. local function encodeCommon(val, pretty, tabLevel, tTracking)
  32.     local str = ""
  33.  
  34.     -- Tabbing util
  35.     local function tab(s)
  36.         str = str .. ("\t"):rep(tabLevel) .. s
  37.     end
  38.  
  39.     local function arrEncoding(val, bracket, closeBracket, iterator, loopFunc)
  40.         str = str .. bracket
  41.         if pretty then
  42.             str = str .. "\n"
  43.             tabLevel = tabLevel + 1
  44.         end
  45.         for k,v in iterator(val) do
  46.             tab("")
  47.             loopFunc(k,v)
  48.             str = str .. ","
  49.             if pretty then str = str .. "\n" end
  50.         end
  51.         if pretty then
  52.             tabLevel = tabLevel - 1
  53.         end
  54.         if str:sub(-2) == ",\n" then
  55.             str = str:sub(1, -3) .. "\n"
  56.         elseif str:sub(-1) == "," then
  57.             str = str:sub(1, -2)
  58.         end
  59.         tab(closeBracket)
  60.     end
  61.  
  62.     -- Table encoding
  63.     if type(val) == "table" then
  64.         assert(not tTracking[val], "Cannot encode a table holding itself recursively")
  65.         tTracking[val] = true
  66.         if isArray(val) then
  67.             arrEncoding(val, "[", "]", ipairs, function(k,v)
  68.                 str = str .. encodeCommon(v, pretty, tabLevel, tTracking)
  69.             end)
  70.         else
  71.             arrEncoding(val, "{", "}", pairs, function(k,v)
  72.                 assert(type(k) == "string", "JSON object keys must be strings", 2)
  73.                 str = str .. encodeCommon(k, pretty, tabLevel, tTracking)
  74.                 str = str .. (pretty and ": " or ":") .. encodeCommon(v, pretty, tabLevel, tTracking)
  75.             end)
  76.         end
  77.     -- String encoding
  78.     elseif type(val) == "string" then
  79.         str = '"' .. val:gsub("[%c\"\\]", controls) .. '"'
  80.     -- Number encoding
  81.     elseif type(val) == "number" or type(val) == "boolean" then
  82.         str = tostring(val)
  83.     else
  84.         error("JSON only supports arrays, objects, numbers, booleans, and strings", 2)
  85.     end
  86.     return str
  87. end
  88.  
  89. function encode(val)
  90.     return encodeCommon(val, false, 0, {})
  91. end
  92.  
  93. function encodePretty(val)
  94.     return encodeCommon(val, true, 0, {})
  95. end
  96.  
  97.  
  98. function parseBoolean(str)
  99.     if str:sub(1, 4) == "true" then
  100.         return true, removeWhite(str:sub(5))
  101.     else
  102.         return false, removeWhite(str:sub(6))
  103.     end
  104. end
  105.  
  106. function parseNull(str)
  107.     return nil, removeWhite(str:sub(5))
  108. end
  109.  
  110. local numChars = {['e']=true; ['E']=true; ['+']=true; ['-']=true; ['.']=true}
  111. function parseNumber(str)
  112.     local i = 1
  113.     while numChars[str:sub(i, i)] or tonumber(str:sub(i, i)) do
  114.         i = i + 1
  115.     end
  116.     local val = tonumber(str:sub(1, i - 1))
  117.     str = removeWhite(str:sub(i))
  118.     return val, str
  119. end
  120.  
  121. function parseString(str)
  122.     local i,j = str:find('[^\\]"')
  123.     local s = str:sub(2, j - 1)
  124.  
  125.     for k,v in pairs(controls) do
  126.         s = s:gsub(v, k)
  127.     end
  128.     str = removeWhite(str:sub(j + 1))
  129.     return s, str
  130. end
  131.  
  132. function parseArray(str)
  133.     str = removeWhite(str:sub(2))
  134.  
  135.     local val = {}
  136.     local i = 1
  137.     while str:sub(1, 1) ~= "]" do
  138.         local v = nil
  139.         v, str = parseValue(str)
  140.         val[i] = v
  141.         i = i + 1
  142.         str = removeWhite(str)
  143.     end
  144.     str = removeWhite(str:sub(2))
  145.     return val, str
  146. end
  147.  
  148. function parseObject(str)
  149.     str = removeWhite(str:sub(2))
  150.  
  151.     local val = {}
  152.     while str:sub(1, 1) ~= "}" do
  153.         local k, v = nil, nil
  154.         k, v, str = parseMember(str)
  155.         val[k] = v
  156.         str = removeWhite(str)
  157.     end
  158.     str = removeWhite(str:sub(2))
  159.     return val, str
  160. end
  161.  
  162. function parseMember(str)
  163.     local k = nil
  164.     k, str = parseValue(str)
  165.     local val = nil
  166.     val, str = parseValue(str)
  167.     return k, val, str
  168. end
  169.  
  170. function parseValue(str)
  171.     local fchar = str:sub(1, 1)
  172.     if fchar == "{" then
  173.         return parseObject(str)
  174.     elseif fchar == "[" then
  175.         return parseArray(str)
  176.     elseif tonumber(fchar) ~= nil or numChars[fchar] then
  177.         return parseNumber(str)
  178.     elseif str:sub(1, 4) == "true" or str:sub(1, 5) == "false" then
  179.         return parseBoolean(str)
  180.     elseif fchar == "\"" then
  181.         return parseString(str)
  182.     elseif str:sub(1, 4) == "null" then
  183.         return parseNull(str)
  184.     end
  185.     return nil
  186. end
  187.  
  188. function decode(str)
  189.     str = removeWhite(str)
  190.     t = parseValue(str)
  191.     return t
  192. end
  193.  
  194. function decodeFromFile(path)
  195.     local file = assert(fs.open(path, "r"))
  196.     return decode(file.readAll())
  197. end
  198.  
  199. --
  200. --  Socket Library. Fast and asynchronous.
  201. --
  202.  
  203. local Socket = {}
  204. Socket.__index = Socket
  205.  
  206. Socket.timeout = 30 -- Should be server timeout + 10. DO NOT CHANGE UNLESS
  207.                     -- YOU OWN THE SERVER FOR THE SOCKET CONNECTION, AND
  208.                     -- HAVE CONFIGURED THE SERVER CORRECTLY.
  209.  
  210. Socket.connections = {}
  211. Socket.messages = {}
  212. Socket.timers = {}
  213.  
  214. Socket.emptyResponse = "empty response"
  215. Socket.unexpectedError = "unexpected error"
  216. Socket.httpFailure = "http failure"
  217. Socket.parseError = "parse error"
  218. Socket.verifyFailure = "verify failure"
  219. Socket.serverError = "server error"
  220. Socket.identityTaken = "identifier already in use"
  221. Socket.timeoutError = "timeout"
  222.  
  223. function Socket.randomId()
  224.     return tostring({}):sub(8, -1)
  225. end
  226.  
  227. function Socket.encodePost(data)
  228.     local ret = ""
  229.     for k, v in pairs(data) do
  230.         ret = ret .. textutils.urlEncode(k) .. "=" .. textutils.urlEncode(v) .. "&"
  231.     end
  232.  
  233.     return ret:sub(1, -2)
  234. end
  235.  
  236. function Socket.new(address, identifier)
  237.     local self = setmetatable({}, Socket)
  238.     self:setup(address, identifier)
  239.     table.insert(Socket.connections, self)
  240.     return self
  241. end
  242.  
  243. local function queueSocketFailure(fullAddress, message)
  244.     local requestObject = Socket.messages[fullAddress]
  245.  
  246.     if requestObject then
  247.         if requestObject.listen == "true" then
  248.             os.queueEvent("socket_failure", requestObject.address, "listen",
  249.                 "", requestObject.identifier, message)
  250.         else
  251.             os.queueEvent("socket_failure", requestObject.address, "send",
  252.                 requestObject.channel, requestObject.identifier, message)
  253.         end
  254.     end
  255.  
  256.     Socket.messages[fullAddress] = nil
  257. end
  258.  
  259. local function refreshConnection(fullAddress)
  260.     local requestObject = Socket.messages[fullAddress]
  261.  
  262.     local request = {
  263.         ["identifier"] = requestObject.identifier,
  264.         ["listen"] = "true",
  265.         ["messageId"] = requestObject.messageId
  266.     }
  267.  
  268.     if not http.request(fullAddress, Socket.encodePost(request)) then
  269.         error("Socket: HTTP request failed")
  270.     end
  271.  
  272.     local timer = os.startTimer(Socket.timeout)
  273.     Socket.timers[fullAddress] = timer
  274. end
  275.  
  276. local function handleReceivedMessage(fullAddress, message)
  277.     local requestObject = Socket.messages[fullAddress]
  278.  
  279.     resp, result = pcall(function() return decode(message) end)
  280.     if resp then
  281.         if type(result.MessageId) == "string" and
  282.                 result.MessageId == requestObject.messageId then
  283.             if result.Error then
  284.                 if type(result.Message) == "string" then
  285.                     if result.Message == Socket.identityTaken then
  286.                         queueSocketFailure(fullAddress, Socket.identityTaken)
  287.                     else
  288.                         queueSocketFailure(fullAddress, Socket.serverError)
  289.                     end
  290.                 else
  291.                     queueSocketFailure(fullAddress, Socket.serverError)
  292.                 end
  293.             elseif result.SendSuccess then
  294.                 os.queueEvent("socket_write_success", requestObject.address,
  295.                     requestObject.channel, requestObject.identifier,
  296.                     requestObject.message)
  297.                 Socket.messages[fullAddress] = nil
  298.             elseif result.RefreshConnection then
  299.                 refreshConnection(fullAddress)
  300.             elseif type(result.Queue) == "table" then
  301.                 local queue = result.Queue
  302.                 for k, v in pairs(queue) do
  303.                     if type(v.Channel) == "string" and
  304.                             type(v.Message) == "string" then
  305.                         os.queueEvent("socket_message", requestObject.address,
  306.                             v.Channel, requestObject.identifier, v.Message)
  307.                     end
  308.                 end
  309.                 refreshConnection(fullAddress)
  310.             elseif type(result.Message) == "string" and
  311.                     type(result.Channel) == "string" and
  312.                     result.Message:len() > 0 and result.Channel:len() > 0 then
  313.                 os.queueEvent("socket_message", requestObject.address,
  314.                     result.Channel, requestObject.identifier, result.Message)
  315.                 refreshConnection(fullAddress)
  316.             else
  317.                 queueSocketFailure(fullAddress, Socket.verifyFailure)
  318.             end
  319.         else
  320.             queueSocketFailure(fullAddress, Socket.verifyFailure)
  321.         end
  322.     else
  323.         queueSocketFailure(fullAddress, Socket.parseError)
  324.     end
  325. end
  326.  
  327. local function getSocketFromTimer(id)
  328.     for k, v in pairs(Socket.timers) do
  329.         if v == id then
  330.             return k
  331.         end
  332.     end
  333. end
  334.  
  335. local function getSocketFromDetails(address, identifier)
  336.     for k, v in pairs(Socket.connections) do
  337.         if v.address == address and v.identifier == identifier then
  338.             return v
  339.         end
  340.     end
  341. end
  342.  
  343. function Socket.run()
  344.     while true do
  345.         local event, url, handle, identifier, message = os.pullEvent()
  346.         if event == "timer" then
  347.             local timerAddress = getSocketFromTimer(url)
  348.             if timerAddress then
  349.                 queueSocketFailure(timerAddress, Socket.timeoutError)
  350.             end
  351.         elseif event == "socket_message" then
  352.             local channel = handle
  353.             local socket = getSocketFromDetails(url, identifier)
  354.             if socket then
  355.                 if type(socket.listeners[channel]) == "function" then
  356.                     socket.listeners[channel](message)
  357.                 end
  358.             end
  359.         elseif event == "http_success" then
  360.             if type(url) == "string" and
  361.                     type(handle) == "table" and
  362.                     type(handle.readAll) == "function" then
  363.                 if Socket.messages[url] then
  364.                     if not handle then
  365.                         queueSocketFailure(url, Socket.emptyResponse)
  366.                     else
  367.                         local resp, contents = pcall(handle.readAll)
  368.                         if resp then
  369.                             handleReceivedMessage(url, contents)
  370.                         else
  371.                             queueSocketFailure(url, Socket.unexpectedError)
  372.                         end
  373.                     end
  374.                 end
  375.             end
  376.         elseif event == "http_failure" then
  377.             queueSocketFailure(url, Socket.httpFailure)
  378.         end
  379.     end
  380. end
  381.  
  382. function Socket:setup(address, identifier)
  383.     if self.closed then
  384.         error("u wot m8, use :reconnect plz")
  385.     end
  386.  
  387.     if not identifier then
  388.         identifier = Socket.randomId()
  389.     end
  390.  
  391.     if address:sub(1, 4) ~= "http" then
  392.         error("http prefix required for socket address")
  393.     end
  394.  
  395.     self.address = address
  396.     self.identifier = identifier
  397.     self.listeners = {}
  398.  
  399.     local messageId = Socket.randomId()
  400.     local request = {
  401.         ["identifier"] = identifier,
  402.         ["listen"] = "true",
  403.         ["messageId"] = messageId
  404.     }
  405.  
  406.     fullAddress = address .. "#" .. messageId
  407.     self.fullAddress = fullAddress
  408.     self.listenId = messageId
  409.  
  410.     if not http.request(fullAddress, Socket.encodePost(request)) then
  411.         error("Socket: HTTP request failed")
  412.     end
  413.  
  414.     request["address"] = address
  415.     Socket.messages[fullAddress] = request
  416.  
  417.     local timer = os.startTimer(Socket.timeout)
  418.     Socket.timers[fullAddress] = timer
  419. end
  420.  
  421. function Socket:write(channel, contents)
  422.     if self.closed then
  423.         error("Cannot write to closed socket")
  424.     end
  425.  
  426.     local messageId = Socket.randomId()
  427.  
  428.     local request = {
  429.         ["channel"] = channel,
  430.         ["identifier"] = self.identifier,
  431.         ["listen"] = "false",
  432.         ["messageId"] = messageId,
  433.         ["message"] = contents
  434.     }
  435.  
  436.     fullAddress = self.address .. "#" .. messageId
  437.  
  438.     if not http.request(fullAddress, Socket.encodePost(request)) then
  439.         error("Socket: HTTP request failed")
  440.     end
  441.  
  442.     request["address"] = self.address
  443.     Socket.messages[fullAddress] = request
  444. end
  445.  
  446. function Socket:on(channel, func)
  447.     if self.closed then
  448.         error("Really? You want to attach a listener on a closed socket?")
  449.     end
  450.  
  451.     self.listeners[channel] = func
  452. end
  453.  
  454. function Socket:reconnect()
  455.     self.closed = false
  456.     table.insert(Socket.connections, self)
  457.  
  458.     Socket.messages[self.fullAddress] = {
  459.         ["identifier"] = self.identifier,
  460.         ["messageId"] = self.listenId,
  461.         ["listen"] = "true",
  462.         ["address"] = self.address
  463.     }
  464.  
  465.     refreshConnection(self.fullAddress)
  466. end
  467.  
  468. function Socket:close()
  469.     self.closed = true
  470.     for k, v in pairs(Socket.connections) do
  471.         if v == self then
  472.             table.remove(Socket.connections, k)
  473.             break
  474.         end
  475.     end
  476. end
  477.  
  478.  
  479.  
  480. local messages = {}
  481.  
  482. local function clearArea()
  483.     local oldX, oldY = term.getCursorPos()
  484.     for i = 1, 18 do
  485.         term.setCursorPos(1, i)
  486.         term.clearLine()
  487.     end
  488.     term.setCursorPos(oldX, oldY)
  489. end
  490.  
  491. local function renderMessages()
  492.     local oldX, oldY = term.getCursorPos()
  493.     local position = 18
  494.     for i = #messages, math.max(1, #messages - 28), -1 do
  495.         term.setCursorPos(1, position)
  496.         term.write(messages[i])
  497.         position = position - 1
  498.     end
  499.     term.setCursorPos(oldX, oldY)
  500. end
  501.  
  502. local function receivedMessage(msg)
  503.     msg = msg:gsub("\\u003c", "<"):gsub("\\u003e", ">"):gsub("\\u0026", "&")
  504.     table.insert(messages, msg)
  505.     clearArea()
  506.     renderMessages()
  507. end
  508.  
  509. local function main()
  510.     write("Enter a username: ")
  511.     username = read()
  512.  
  513.     clearArea()
  514.  
  515.     s = Socket.new("http://onelann.tk:9000/", Socket.randomId())
  516.     s:on("message", receivedMessage)
  517.  
  518.     while true do
  519.         term.setCursorPos(1, 19)
  520.         term.clearLine()
  521.         term.setCursorPos(1, 19)
  522.         term.write("> ")
  523.         message = read()
  524.         clearArea()
  525.         renderMessages()
  526.         s:write("broadcast", "<" .. username .. "> " .. message)
  527.     end
  528. end
  529.  
  530. local function  monitor()
  531.     while true do
  532.         local event, p1, p2, p3 = os.pullEvent()
  533.         if false and event:find("socket") then
  534.             table.insert(messages, "[EVENT] " .. event .. " | " .. p1 .. "|" .. p2 .. "|" .. p3)
  535.             clearArea()
  536.             renderMessages()
  537.         end
  538.     end
  539. end
  540.  
  541. parallel.waitForAny(Socket.run, main, monitor)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement