Advertisement
Guest User

Chat

a guest
Oct 10th, 2015
103
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 12.00 KB | None | 0 0
  1. -- [ --------------------------------------------------------------------- ] --
  2. -- [ Chatting Software            ---------------------------------------- ]
  3.  
  4. local VERSION = " Pocket 1.1.6"
  5. local MODEM = nil
  6. local NICKNAME = nil
  7. local ACTIVE = false
  8. local BUFFER = {}
  9. local POINTER = 0
  10. local ONLINE = {}
  11. local ISONLINE = false
  12. local ID = os.computerID()
  13. local LAST_MSG_TARGET = nil
  14. local CHANNEL = 1
  15. local SCROLL_POINTER = POINTER
  16. local WIDTH, HEIGHT = term.getSize()
  17. local LINES = HEIGHT - 6
  18. local START_LINE = 5
  19. local OPERATOR = "OP"
  20. local IRC_CHANNEL = "#matecraft"
  21. -- [ --------------------------------------------------------------------- ] --
  22.  
  23. -- Split a string
  24. function split(str, pat)
  25.     local t = {}  -- NOTE: use {n = 0} in Lua-5.0
  26.     if str ~= nil then
  27.        local fpat = "(.-)" .. pat
  28.        local last_end = 1
  29.        local s, e, cap = str:find(fpat, 1)
  30.        while s do
  31.           if s ~= 1 or cap ~= "" then
  32.             table.insert(t,cap)
  33.           end
  34.           last_end = e+1
  35.           s, e, cap = str:find(fpat, last_end)
  36.        end
  37.        if last_end <= #str then
  38.           cap = str:sub(last_end)
  39.           table.insert(t, cap)
  40.        end
  41.     else
  42.         print("##ERROR failed to split ["..str.."] by:"..pat)
  43.     end
  44.     return t
  45. end
  46.  
  47. -- Log a message to file
  48. function log(message)
  49.   local file = io.open("chathistory.log", "a")
  50.   file:write("\n" .. message)
  51.   file:close()
  52. end
  53.  
  54. -- Application entry
  55. function main()
  56.   term.clear()
  57.   term.setCursorPos(1, 1)
  58.  
  59.   if not setPeripherals() then
  60.     print("[FATAL ERROR] Not able to setup peripherals. Check modem")
  61.     return false
  62.   end
  63.  
  64.   welcome()
  65. end
  66.  
  67. -- Set the attached peripherals. Opens rednet modem and warps monitor
  68. function setPeripherals()
  69.   local i, side
  70.  
  71.   for i, side in pairs(rs.getSides()) do
  72.     if peripheral.isPresent(side) then
  73.       if peripheral.getType(side) == "modem" then
  74.         MODEM = side
  75.         if not rednet.isOpen(side) then
  76.           rednet.open(MODEM)
  77.         end
  78.       end
  79.     end
  80.   end
  81.  
  82.   -- Exit with a fatal error when modem not found
  83.   if MODEM == nil then
  84.     print("[FATAL ERROR] No modem was detected. Plase attach a modem on any side.")
  85.     return false
  86.   end
  87.  
  88.   return true
  89. end
  90.  
  91. -- Start the welcome screen
  92. function welcome()
  93.   local x, y
  94.  
  95.   term.clear()
  96.   writeHeader()
  97.  
  98.   print("")
  99.   print("")
  100.   print("Welcome to Chat Software by: Cowboy433")
  101.   print("")
  102.   print("To start, enter your nickname and press [Enter]")
  103.   print("")
  104.   print("Note*: Graphics are much better on advanced")
  105.   print("computers")
  106.   print("")
  107.   term.write("Nickname: ")
  108.  
  109.   x, y = term.getCursorPos()
  110.  
  111.   while NICKNAME == nil or NICKNAME == "" do
  112.     term.setCursorPos(x, y)
  113.     NICKNAME = read()
  114.     execute("/online")
  115.     appendBuffer("[" .. OPERATOR .. "]: Type /help for a list of commands")
  116.   end
  117.  
  118.   start()
  119. end
  120.  
  121. -- Writes the screen header
  122. function writeHeader()
  123.   local col
  124.  
  125.   term.setCursorPos(1, 1)
  126.   term.write("Public Chat " .. VERSION .. "")
  127.   term.setCursorPos(1, 2)
  128.  
  129.   for col = 1, WIDTH do
  130.     term.write("-")
  131.   end
  132. end
  133.  
  134. -- Writes the list of online users
  135. function writeOnlineList()
  136.   local i, v, count, x, y, col
  137.  
  138.   count = 0
  139.  
  140.   x, y = term.getCursorPos()
  141.  
  142.   term.setCursorPos(1, HEIGHT - 1)
  143.  
  144.   for col = 1, WIDTH do
  145.     term.write("-")
  146.   end
  147.  
  148.   term.setCursorPos(1, HEIGHT)
  149.   term.clearLine()
  150.   term.write("Online> ")
  151.  
  152.   for i, v in pairs(ONLINE) do
  153.     if count == 0 then
  154.       term.write(i)
  155.     else
  156.       term.write(", " .. i)
  157.     end
  158.  
  159.     count = count + 1
  160.   end
  161.  
  162.   if count == 0 then
  163.     term.write("Nobody online in channel " .. CHANNEL)
  164.   end
  165.  
  166.   term.setCursorPos(x, y)
  167. end
  168.  
  169. -- Start the chat
  170. function start()
  171.   term.clear()
  172.   writeHeader()
  173.   writeOnlineList()
  174.  
  175.   ACTIVE = true
  176.  
  177.   showBuffer()
  178.  
  179.   parallel.waitForAll(input, watchEvents)
  180. end
  181.  
  182. -- Stop the application
  183. function stop()
  184.   ACTIVE = false
  185. end
  186.  
  187. -- Reset the application
  188. function reset()
  189.   execute("/offline")
  190.  
  191.   if rednet.isOpen(MODEM) then
  192.     rednet.close(MODEM)
  193.   end
  194.  
  195.   sleep(1.5)
  196.   os.reboot()
  197. end
  198.  
  199. -- Watch all input to provide possible shortcuts (for example usernames)
  200. function watchEvents()
  201.   local type, param, param2, param3, i, v
  202.  
  203.   while ACTIVE do
  204.     type, param, param2, param3 = os.pullEvent()
  205.  
  206.     if type == "key" then
  207.       if param == 200 then -- up
  208.         scroll(-1)
  209.       elseif param == 208 then -- down
  210.         scroll(1)
  211.       elseif param == 201 then -- pageup
  212.         scroll(-12)
  213.       elseif param == 209 then -- pagedown
  214.         scroll(12)
  215.       --else
  216.       --  appendBuffer(tostring(param))
  217.       end
  218.     elseif type == "mouse_scroll" then
  219.       if param == -1 then
  220.         scroll(-1)
  221.       else
  222.         scroll(1)
  223.       end
  224.     elseif type == "rednet_message" then
  225.       receive(param2)
  226.     end
  227.   end
  228. end
  229.  
  230. -- Scroll through the chat
  231. function scroll(amount)
  232.   SCROLL_POINTER = SCROLL_POINTER + amount
  233.   showBuffer()
  234. end
  235.  
  236. -- Handle input from the prompt
  237. function input()
  238.   local message, col
  239.  
  240.   term.setCursorPos(1, 4)
  241.  
  242.   for col = 1, WIDTH do
  243.     term.write("-")
  244.   end
  245.  
  246.   while ACTIVE do
  247.     term.setCursorPos(1, 3)
  248.     term.clearLine()
  249.     term.write("[" .. CHANNEL .. "] > ")
  250.  
  251.     message = read()
  252.  
  253.     if message ~= nil and message ~= "" then
  254.       execute(message, "local")
  255.     end
  256.   end
  257. end
  258.  
  259. -- Send a message
  260. function send(message, target)
  261.   local request, serialized, x, encrypted
  262.  
  263.   request = {protocol = "rnc", nickname = NICKNAME, sender = ID, target = target, channel = CHANNEL, message = message}
  264.   serialized = textutils.serialize(request)
  265.  
  266.   encrypted = ""
  267.   for x = 1, #serialized do
  268.     encrypted = encrypted .. string.char(serialized:byte(x) + 1)
  269.   end
  270.  
  271.   if request.target ~= nil then      
  272.     rednet.send(request.target, encrypted)
  273.   else
  274.     rednet.broadcast(encrypted)
  275.   end
  276. end
  277.  
  278. -- Recieve a message
  279. function receive(message)
  280.   local request, decrypted, x
  281.  
  282.   if message ~= nil and message ~= "" then
  283.  
  284.     decrypted = ""
  285.     for x = 1, #message do
  286.       decrypted = decrypted .. string.char(message:byte(x) - 1)
  287.     end
  288.  
  289.     request = textutils.unserialize(decrypted)
  290.  
  291.     if request.protocol == "rnc" and request.channel == CHANNEL then
  292.       if request.nickname ~= nil and request.nickname ~= "" then
  293.         execute(request, "remote")
  294.       end
  295.     end
  296.   end
  297. end
  298.  
  299. -- Execute a command or add a chat message
  300. function execute(message, source)
  301.   local command, splitCommand, nickname, id, body, onlineUser
  302.  
  303.   if message.nickname ~= nil then
  304.     executeRemote(message)
  305.     return
  306.   end
  307.  
  308.   if message:sub(0, 1) == "/" then
  309.       command = message:sub(2)
  310.  
  311.       if command == "quit"
  312.           or command == "reset"
  313.           or command == "restart"
  314.           or command == "reboot"
  315.           or command == "stop"
  316.         then
  317.           appendBuffer("[" .. OPERATOR .. "]: Stopping application")
  318.           reset()
  319.       elseif command == "online" then
  320.         if not ISONLINE then
  321.           send("/online")
  322.           putOnline()
  323.           appendBuffer("[" .. OPERATOR .. "]: You are now online")
  324.           ISONLINE = true
  325.         else
  326.           appendBuffer("[" .. OPERATOR .. "]: You are already online")
  327.         end
  328.       elseif command == "offline" then
  329.         if ISONLINE then
  330.           send("/offline")
  331.           takeOffline()
  332.           appendBuffer("[" .. OPERATOR .. "]: You are now offline")
  333.           ISONLINE = false
  334.         else
  335.           appendBuffer("[" .. OPERATOR .. "]: You are already offline")
  336.         end
  337.       elseif command:sub(0, 5) == "nick " then
  338.         takeOffline()
  339.         NICKNAME = command:sub(6)
  340.         putOnline()
  341.         appendBuffer("[" .. OPERATOR .. "]: Your nickname has been changed")
  342.       elseif command:sub(0, 5) == "slap " then
  343.         appendBuffer(command:sub(6) .. " was slapped by " .. NICKNAME)
  344.       elseif command:sub(0, 4) == "msg " then
  345.         splitCommand = split(command:sub(5), "%s")
  346.  
  347.         onlineUser = false
  348.  
  349.         for nickname, id in pairs(ONLINE) do
  350.           if nickname == splitCommand[1] then
  351.             body = command:sub(5 + splitCommand[1]:len() + 1)
  352.             send(body, id)
  353.             appendBuffer(NICKNAME .. " > " .. nickname .. ": " .. body)
  354.             onlineUser = true
  355.             LAST_MSG_TARGET = nickname
  356.           end
  357.         end
  358.  
  359.         if not onlineUser then
  360.             appendBuffer("[" .. OPERATOR .. "]: User " .. splitCommand[1] .. " is not online")
  361.         end
  362.       elseif command:sub(0, 2) == "r " then
  363.         if LAST_MSG_TARGET ~= nil then
  364.           execute("/msg " .. LAST_MSG_TARGET .. " " .. command:sub(3), "local")
  365.         else
  366.           appendBuffer("[" .. OPERATOR .. "]: No valid user for message")
  367.         end
  368.       elseif command:sub(0, 5) == "join " then
  369.         if CHANNEL ~= tonumber(command:sub(6)) then
  370.           execute("/offline")
  371.           CHANNEL = tonumber(command:sub(6))
  372.           execute("/online")
  373.           appendBuffer("[" .. OPERATOR .. "]: Joined channel " .. CHANNEL)
  374.         else
  375.           appendBuffer("[" .. OPERATOR .. "]: Already in channel " .. CHANNEL)
  376.         end
  377.       elseif command == "help" then
  378.         appendBuffer("[" .. OPERATOR .. "] Commands:")
  379.         appendBuffer("/quit : Exit the chat")
  380.         appendBuffer("/msg <nickname> <message> : Send a private message")
  381.         appendBuffer("/r <message> : Reply to a private message")
  382.         appendBuffer("/join <channel> : Switch channel")
  383.       else
  384.         appendBuffer("[" .. OPERATOR .. "]: Unknown command")
  385.       end
  386.      
  387.       return
  388.   end
  389.  
  390.   appendBuffer(NICKNAME .. ": " .. message)
  391.   send(message)
  392. end
  393.  
  394. --
  395. function putOnline(nickname, id)
  396.   if nickname == nil or id == nil then
  397.     nickname = NICKNAME
  398.     id = ID
  399.   end
  400.  
  401.   ONLINE[nickname] = id
  402.  
  403.   writeOnlineList()
  404. end
  405.  
  406. --
  407. function takeOffline(nickname, id)
  408.   if nickname == nil or id == nil then
  409.     nickname = NICKNAME
  410.     id = ID
  411.   end
  412.  
  413.   ONLINE[nickname] = nil
  414.  
  415.   writeOnlineList()
  416. end
  417.  
  418. --
  419. function executeRemote(request)
  420.   local command
  421.  
  422.   if request.message:sub(0, 1) == "/" then
  423.     command = request.message:sub(2)
  424.  
  425.     if command == "online" then
  426.       putOnline(request.nickname, request.sender)
  427.       appendBuffer("[" .. OPERATOR .. "]: " .. request.nickname .. " is now online")
  428.       send("/metoo")
  429.     elseif command == "offline" then
  430.       takeOffline(request.nickname, request.sender)
  431.       appendBuffer("[" .. OPERATOR .. "]: " .. request.nickname .. " is now offline")
  432.     elseif command == "metoo" then
  433.       putOnline(request.nickname, request.sender)
  434.     end
  435.     return
  436.   end
  437.  
  438.   if request.target ~= nil then
  439.     appendBuffer(request.nickname .. " > " .. NICKNAME .. ": " .. request.message)
  440.     LAST_MSG_TARGET = request.nickname
  441.   else
  442.     appendBuffer(request.nickname .. ": " .. request.message)
  443.   end
  444. end
  445.  
  446. --
  447. function appendBuffer(message)
  448.   local length
  449.  
  450.   length = message:len()
  451.  
  452.   if length > WIDTH then
  453.     table.insert(BUFFER, message:sub(1, WIDTH))
  454.     POINTER = POINTER + 1
  455.     appendBuffer(message:sub(WIDTH + 1))
  456.   else
  457.     table.insert(BUFFER, message)
  458.     POINTER = POINTER + 1
  459.   end
  460.  
  461.   SCROLL_POINTER = POINTER
  462.  
  463.   showBuffer()
  464. end
  465.  
  466. --
  467. function showBuffer()
  468.   local i, line, bufferPointer, x, y, pointer
  469.  
  470.   pointer = SCROLL_POINTER
  471.  
  472.   if pointer == 0 then
  473.     return
  474.   elseif SCROLL_POINTER > POINTER then
  475.     SCROLL_POINTER = POINTER
  476.     pointer = POINTER
  477.   elseif POINTER < LINES + 1 then
  478.     SCROLL_POINTER = POINTER
  479.     pointer = POINTER
  480.   elseif POINTER > LINES and SCROLL_POINTER < LINES then
  481.     SCROLL_POINTER = LINES
  482.     pointer = SCROLL_POINTER
  483.   end
  484.  
  485.   x, y = term.getCursorPos()
  486.  
  487.   line = START_LINE
  488.  
  489.   bufferPointer = -(LINES - 1 - pointer)
  490.  
  491.   for i = bufferPointer, bufferPointer + (LINES - 1) do
  492.     term.setCursorPos(1, line)
  493.     term.clearLine()
  494.    
  495.     if BUFFER[i] ~= nil then
  496.       term.write(tostring(BUFFER[i]))
  497.     end
  498.    
  499.     line = line + 1
  500.   end
  501.  
  502.   term.setCursorPos(x, y)
  503. end
  504.  
  505. -- Fire up the application
  506. main()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement