Advertisement
gpgautier

RedNet Chat Remote 0.5

Nov 7th, 2012
186
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 8.49 KB | None | 0 0
  1. -- [ --------------------------------------------------------------------- ] --
  2. -- [ RedNetChat                                                            ] --
  3. -- [ A public chat client for ComputerCraft                                ] --
  4. -- [ Created by GPG Incorporated.                                          ] --
  5. -- [ --------------------------------------------------------------------- ] --
  6.  
  7. -- Indicates if the application is running
  8. local RUNNING = false
  9.  
  10. -- Url of the api
  11. local API_URL = "http://rednetchat.gpgautier.nl/api.php"
  12.  
  13. -- Queue with all the messages
  14. local MESSAGE_QUEUE = {}
  15.  
  16. -- Indicates if there is a message loading
  17. local MESSAGE_LOADING = false
  18.  
  19. -- Protocol to use for sending and recieving messages
  20. local PROTOCOL = "rednet"
  21.  
  22. -- ID of this client
  23. local ID = os.computerID()
  24.  
  25. -- Nickname for the user in chat
  26. local NICKNAME = ""
  27.  
  28. -- ID for the chat session
  29. local SESSION = nil
  30.  
  31. -- Indicates if requests and responses should be logged
  32. local LOGGING = true
  33.  
  34. -- Display buffer
  35. local DISPLAY_BUFFER = {}
  36.  
  37. -- Pointer for the display buffer
  38. local DISPLAY_BUFFER_POINTER = 0
  39.  
  40. -- Indicates if the client is joined
  41. local JOINED = false
  42.  
  43. -- The last nicknamed that you messaged with
  44. local LAST_MSG = nil
  45.  
  46. -- Target for private messaging
  47. local TARGET = nil
  48.  
  49. -- Channel for group messaging
  50. local CHANNEL = 1
  51.  
  52. -- Process the message queue and send a message when queued
  53. function processQueue()
  54.   -- only process when there is no message loading
  55.   if not MESSAGE_LOADING then
  56.     if MESSAGE_QUEUE[1] ~= nil then
  57.       MESSAGE_LOADING = true
  58.       http.request(API_URL, MESSAGE_QUEUE[1])
  59.       table.remove(MESSAGE_QUEUE, 1)
  60.     end
  61.   end
  62. end
  63.  
  64. -- Add a message to the queue
  65. function addMessage(header, body)
  66.   local key, value, message, session
  67.  
  68.   if SESSION ~= nil then
  69.     session = SESSION
  70.   else
  71.     session = ""
  72.   end
  73.  
  74.   -- assemble the post data
  75.   message = "?protocol=" .. PROTOCOL
  76.   message = message .. "&session=" .. session
  77.   message = message .. "&channel=" .. CHANNEL
  78.   message = message .. "&origin=" .. ID
  79.   message = message .. "&nickname=" .. NICKNAME
  80.   message = message .. "&header=" .. header
  81.   message = message .. "&body="
  82.  
  83.   if body ~= nil then
  84.     message = message .. body  
  85.   end
  86.  
  87.   if LOGGING then log(message) end
  88.  
  89.   -- add the message to the queue
  90.   table.insert(MESSAGE_QUEUE, message)
  91.  
  92.   -- start processing the message queue
  93.   processQueue()
  94. end
  95.  
  96. -- Handles all OS events
  97. function handleEvents()
  98.   local type, param1, param2, param3, param4
  99.  
  100.   while JOINED == false or RUNNING do
  101.     type, param1, param2, param3, param4 = os.pullEvent()
  102.  
  103.     -- Handles incoming http events
  104.     if type == "http_failure" or type == "http_success" then
  105.       if param2 ~= nil then
  106.         param2 = param2.readAll()
  107.       end
  108.  
  109.       if LOGGING then log(param2) end
  110.  
  111.       if type == "http_success" then
  112.         handleResponse(textutils.unserialize(param2))
  113.       end
  114.  
  115.       -- indicate that the message is finished loading and start sending the next message
  116.       MESSAGE_LOADING = false
  117.       processQueue()
  118.     end
  119.   end
  120. end
  121.  
  122. -- Handles http responses
  123. function handleResponse(response)  
  124.   -- check if the protocol matches
  125.   if response.protocol ~= PROTOCOL then
  126.     return
  127.   end
  128.  
  129.   -- check for correct origin
  130.   if tonumber(response.origin) ~= ID then
  131.     return
  132.   end
  133.  
  134.   if response.header == "join" then
  135.     if response.status == "ok" then
  136.       SESSION = response.session
  137.       JOINED = true
  138.       CHANNEL = response.channel
  139.     else
  140.       writeHeader()
  141.       term.setCursorPos(2, 9)
  142.       term.clearLine()
  143.       term.write("Error: " .. response.body)
  144.       NICKNAME = ""
  145.       inputNickname()
  146.     end
  147.   elseif response.header == "leave" then
  148.     addMessage("update")
  149.     SESSION = nil
  150.   elseif response.header == "msg" then
  151.     if response.status == "error" then
  152.       appendDisplayBuffer(response.body)
  153.     else
  154.       LAST_MSG = response.body
  155.     end
  156.   elseif response.header == "update" then
  157.     local messages = response.body
  158.     showOnlineUsers(response.online)
  159.     if messages ~= nil and messages ~= "" then
  160.       local i, message
  161.       for i, message in pairs(messages) do
  162.           message = messages[i]
  163.         if message.sender ~= nil and message.header == "msg" then
  164.           LAST_MSG = message.sender
  165.         end
  166.         appendDisplayBuffer(message.body)
  167.       end
  168.     end
  169.   end
  170. end
  171.  
  172. -- General logging function
  173. function log(message)
  174.   local file = io.open(ID .. "_rednetchat.log", "a")
  175.   file:write("\n" .. message)
  176.   file:close()
  177. end
  178.  
  179. -- Receive buffer updates for the service
  180. function updateBuffer()
  181.   while RUNNING do
  182.     if SESSION ~= nil then
  183.       addMessage("update")
  184.     end
  185.     sleep(1)
  186.   end
  187. end
  188.  
  189. -- Enable and process the input buffer
  190. function inputBuffer()
  191.   local buffer
  192.  
  193.   term.setCursorPos(1, 4)
  194.   term.write("--------------------------------------------------")
  195.  
  196.   while RUNNING do
  197.     buffer = ""
  198.  
  199.     while buffer == nil or buffer == "" do
  200.       term.setCursorPos(1, 3)
  201.       term.clearLine()
  202.       term.write("Send > ")
  203.  
  204.       buffer = read()
  205.     end
  206.  
  207.     if buffer:sub(1, 5) == "/join" then
  208.       join(buffer:sub(7))
  209.     elseif buffer == "/leave" then
  210.       leave()
  211.     elseif buffer:sub(1, 4) == "/msg" then
  212.       msg(buffer:sub(6))
  213.     elseif buffer:sub(1, 7) == "/public" then
  214.       if TARGET ~= nil then
  215.         TARGET = nil
  216.         appendDisplayBuffer("Public messaging")
  217.       end
  218.     elseif buffer:sub(1, 8) == "/private" then
  219.       local target = buffer:sub(10)
  220.       if target ~= "" and target ~= nil then
  221.         TARGET = target
  222.         appendDisplayBuffer("Private messaging to " .. TARGET)
  223.       else
  224.         TARGET = nil
  225.         appendDisplayBuffer("Public messaging")
  226.       end
  227.     elseif buffer:sub(1, 2) == "/r" then
  228.       r(buffer:sub(4))
  229.     else
  230.       if TARGET ~= nil then
  231.         msg(TARGET .. " " .. buffer)
  232.       else
  233.         say(buffer)
  234.       end
  235.     end
  236.   end
  237. end
  238.  
  239. -- Writes the application header
  240. function writeHeader()
  241.   term.clear()
  242.   term.setCursorPos(1, 1)
  243.   term.write("RedNet Chat 0.5 beta           by GPG Incorporated")
  244.   term.setCursorPos(1, 2)
  245.   term.write("--------------------------------------------------")
  246. end
  247.  
  248. -- COMMAND - /join
  249. function join(channel)
  250.   channel = tonumber(channel)
  251.   if channel == nil then
  252.     channel = 1
  253.   end
  254.   addMessage("join", channel)
  255. end
  256.  
  257. -- COMMAND - /leave
  258. function leave()
  259.   addMessage("leave")
  260. end
  261.  
  262. -- COMMAND - /say
  263. function say(message)
  264.   addMessage("say", message)
  265. end
  266.  
  267. --
  268. function msg(message)
  269.   addMessage("msg", message)
  270. end
  271.  
  272. --
  273. function r(message)
  274.   addMessage("msg", LAST_MSG .. " " .. message)
  275. end
  276.  
  277. --
  278. function appendDisplayBuffer(message)
  279.   local length
  280.  
  281.   length = message:len()
  282.  
  283.   if length > 50 then
  284.     table.insert(DISPLAY_BUFFER, message:sub(1, 50))
  285.     DISPLAY_BUFFER_POINTER = DISPLAY_BUFFER_POINTER + 1
  286.     appendDisplayBuffer(message:sub(51))
  287.   else
  288.     table.insert(DISPLAY_BUFFER, message)
  289.     DISPLAY_BUFFER_POINTER = DISPLAY_BUFFER_POINTER + 1
  290.   end
  291.  
  292.   showDisplayBuffer()
  293. end
  294.  
  295. --
  296. function showDisplayBuffer()
  297.   local i, line, pointer, x, y
  298.  
  299.   if DISPLAY_BUFFER_POINTER == 0 then
  300.     return
  301.   end
  302.  
  303.   x, y = term.getCursorPos()
  304.  
  305.   line = 5
  306.  
  307.   pointer = -(11 - DISPLAY_BUFFER_POINTER)
  308.  
  309.   for i = pointer, pointer + 11 do
  310.     term.setCursorPos(1, line)
  311.     term.clearLine()
  312.    
  313.     if DISPLAY_BUFFER[i] ~= nil then
  314.       term.write(tostring(DISPLAY_BUFFER[i]))
  315.     end
  316.    
  317.     line = line + 1
  318.   end
  319.  
  320.   term.setCursorPos(x, y)
  321. end
  322.  
  323. --
  324. function showOnlineUsers(online)
  325.   local x, y = term.getCursorPos()
  326.  
  327.   if online == nil then
  328.     online = "-"
  329.   end
  330.  
  331.   term.setCursorPos(1, 17)
  332.   term.write("--------------------------------------------------")
  333.   term.setCursorPos(1, 18)
  334.   term.clearLine()
  335.   term.write("Online: " .. online)
  336.  
  337.   term.setCursorPos(x, y)
  338. end
  339.  
  340. --
  341. function inputNickname()
  342.   term.setCursorPos(1, 4)
  343.   term.write(" Enter a username and press enter.")
  344.  
  345.   while NICKNAME == "" do
  346.     term.setCursorPos(2, 6)
  347.     term.clearLine()
  348.     term.write("Username: ")
  349.  
  350.     NICKNAME = read()
  351.   end
  352.  
  353.   join()
  354. end
  355.  
  356. -- Application entry
  357. function main()
  358.   local file = io.open(ID .. "_rednetchat.log", "w")
  359.   file:write("RedNet Log")
  360.   file:close()
  361.  
  362.   writeHeader()
  363.  
  364.   parallel.waitForAll(handleEvents, inputNickname)
  365.  
  366.   RUNNING = true
  367.  
  368.   writeHeader()
  369.  
  370.   showDisplayBuffer()
  371.   parallel.waitForAll(handleEvents, updateBuffer, inputBuffer)
  372. end
  373.  
  374. main()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement