Advertisement
Pinkishu

ircChatbox

Jul 24th, 2016
190
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 20.07 KB | None | 0 0
  1. -- A (very (very!)) simple IRC client. Reference:
  2. -- http://tools.ietf.org/html/rfc2812
  3.  
  4. local os = require("os")
  5. local component = require("component")
  6. local computer = require("computer")
  7.  
  8. if not component.isAvailable("internet") then
  9.   io.stderr:write("OpenIRC requires an Internet Card to run!\n")
  10.   return
  11. end
  12.  
  13. if not component.isAvailable("chat_box") then
  14.   io.stderr:write("This Version of OpenIRC needs a Chat Box to broadcast messages to chat")
  15.   return
  16. end
  17.  
  18. local event = require("event")
  19. local internet = require("internet")
  20. local shell = require("shell")
  21. local term = require("term")
  22. local text = require("text")
  23.  
  24. local args, options = shell.parse(...)
  25. local nick = args[1] or "BTMRelay"
  26. local host = args[2] or "irc.esper.net:6667"
  27.  
  28. if not host:find(":") then
  29.   host = host .. ":6667"
  30. end
  31.  
  32. -- try to connect to server.
  33. local sock, reason = internet.open(host)
  34. if not sock then
  35.   io.stderr:write(reason .. "\n")
  36.   return
  37. end
  38.  
  39. -- extract nickname from identity.
  40. local function name(identity)
  41.   return identity and identity:match("^[^!]+") or identity or "Anonymous"
  42. end
  43.  
  44. local function antiHighlightNick(nick)
  45.   local symbol = "​"
  46.   local p1 = 1
  47.   local p2 = nil
  48.   if #nick > 2 then
  49.     p2 = math.random(2, #nick - 1)
  50.   end
  51.   local newNick = nick:sub(1, p1) .. symbol
  52.   if p2 then
  53.     newNick = newNick .. nick:sub(p1 + 1, p2) .. symbol .. nick:sub(p2 + 1)
  54.   else
  55.     newNick = newNick .. nick:sub(p1 + 1)
  56.   end
  57.   return newNick
  58. end
  59.  
  60. local users = {}
  61.  
  62. local function antiHighlight(source, msg)
  63.   local pat = "[%a%d%_%-%\\%[%]%{%}%^%`%|]+"
  64.   local matches = string.gmatch(msg, pat)
  65.   local players = component.debug.getPlayers()
  66.   if users[source] then
  67.     for w in matches do
  68.       for _, v2 in ipairs(players) do
  69.         if v2 == w then
  70.           for _, v in ipairs(users[source]) do
  71.             if v == w then
  72.               msg = msg:gsub(w, antiHighlightNick(w))
  73.               break
  74.             end
  75.           end
  76.         end
  77.       end
  78.     end
  79.   end
  80.   return msg
  81. end
  82.  
  83. local nativeprint = print
  84. -- custom print that uses all except the last line for printing.
  85. local function print(message, overwrite)
  86.   local w, h = component.gpu.getResolution()
  87.   local line
  88.   repeat
  89.     line, message = text.wrap(text.trim(message), w, w)
  90.     if not overwrite then
  91.       component.gpu.copy(1, 1, w, h - 1, 0, -1)
  92.     end
  93.     overwrite = false
  94.     component.gpu.fill(1, h - 1, w, 1, " ")
  95.     component.gpu.set(1, h - 1, line)
  96.   until not message or message == ""
  97. end
  98.  
  99. component.chat_box.setDistance(math.huge)
  100. local lastPrefix = "ChatBox"
  101. local function chatSay(prefix, source, nick, message)
  102.   if lastPrefix ~= prefix then
  103.     component.chat_box.setName(prefix)
  104.     lastPrefix = prefix
  105.   end
  106.   component.chat_box.say(nick .. message)
  107. end
  108.  
  109. -- utility method for reply tracking tables.
  110. function autocreate(table, key)
  111.   table[key] = {}
  112.   return table[key]
  113. end
  114.  
  115.  
  116.  
  117. -- user defined callback for messages (via `lua function(msg) ... end`)
  118. local callback = nil
  119.  
  120. -- list of whois info per user (used to accumulate whois replies).
  121. local whois = setmetatable({}, {__index=autocreate})
  122.  
  123. function remUser(channel, name)
  124.   for i, v in ipairs(users[channel]) do
  125.     if v == name then
  126.       table.remove(users[channel], i)
  127.       break
  128.     end
  129.   end
  130. end
  131.  
  132. -- list of users per channel (used to accumulate names replies).
  133. local names = setmetatable({}, {__index=autocreate})
  134.  
  135. -- timer used to drive socket reading.
  136. local timer, timer2
  137.  
  138. -- ignored commands, reserved according to RFC.
  139. -- http://tools.ietf.org/html/rfc2812#section-5.3
  140. local ignore = {
  141.   [213]=true, [214]=true, [215]=true, [216]=true, [217]=true,
  142.   [218]=true, [231]=true, [232]=true, [233]=true, [240]=true,
  143.   [241]=true, [244]=true, [244]=true, [246]=true, [247]=true,
  144.   [250]=true, [300]=true, [316]=true, [361]=true, [362]=true,
  145.   [363]=true, [373]=true, [384]=true, [492]=true,
  146.   -- custom ignored responses.
  147.   [265]=true, [266]=true, [330]=true
  148. }
  149.  
  150. -- command numbers to names.
  151. local commands = {
  152. --Replys
  153.   RPL_WELCOME = "001",
  154.   RPL_YOURHOST = "002",
  155.   RPL_CREATED = "003",
  156.   RPL_MYINFO = "004",
  157.   RPL_BOUNCE = "005",
  158.   RPL_LUSERCLIENT = "251",
  159.   RPL_LUSEROP = "252",
  160.   RPL_LUSERUNKNOWN = "253",
  161.   RPL_LUSERCHANNELS = "254",
  162.   RPL_LUSERME = "255",
  163.   RPL_AWAY = "301",
  164.   RPL_UNAWAY = "305",
  165.   RPL_NOWAWAY = "306",
  166.   RPL_WHOISUSER = "311",
  167.   RPL_WHOISSERVER = "312",
  168.   RPL_WHOISOPERATOR = "313",
  169.   RPL_WHOISIDLE = "317",
  170.   RPL_ENDOFWHOIS = "318",
  171.   RPL_WHOISCHANNELS = "319",
  172.   RPL_CHANNELMODEIS = "324",
  173.   RPL_NOTOPIC = "331",
  174.   RPL_TOPIC = "332",
  175.   RPL_NAMREPLY = "353",
  176.   RPL_ENDOFNAMES = "366",
  177.   RPL_MOTDSTART = "375",
  178.   RPL_MOTD = "372",
  179.   RPL_ENDOFMOTD = "376",
  180.   RPL_WHOISSECURE = "671",
  181.   RPL_HELPSTART = "704",
  182.   RPL_HELPTXT = "705",
  183.   RPL_ENDOFHELP = "706",
  184.   RPL_UMODEGMSG = "718",
  185.  
  186. --Errors
  187.   ERR_BANLISTFULL = "478",
  188.   ERR_CHANNELISFULL = "471",
  189.   ERR_UNKNOWNMODE = "472",
  190.   ERR_INVITEONLYCHAN = "473",
  191.   ERR_BANNEDFROMCHAN = "474",
  192.   ERR_CHANOPRIVSNEEDED = "482",
  193.   ERR_UNIQOPRIVSNEEDED = "485",
  194.   ERR_USERNOTINCHANNEL = "441",
  195.   ERR_NOTONCHANNEL = "442",
  196.   ERR_NICKCOLLISION = "436",
  197.   ERR_NICKNAMEINUSE = "433",
  198.   ERR_ERRONEUSNICKNAME = "432",
  199.   ERR_WASNOSUCHNICK = "406",
  200.   ERR_TOOMANYCHANNELS = "405",
  201.   ERR_CANNOTSENDTOCHAN = "404",
  202.   ERR_NOSUCHCHANNEL = "403",
  203.   ERR_NOSUCHNICK = "401",
  204.   ERR_MODELOCK = "742"
  205. }
  206.  
  207. -- main command handling callback.
  208. local function handleCommand(prefix, command, args, message)
  209.   ---------------------------------------------------
  210.   -- Keepalive
  211.  
  212.   if command == "PING" then
  213.     sock:write(string.format("PONG :%s\r\n", message))
  214.     sock:flush()
  215.  
  216.   ---------------------------------------------------
  217.   -- General commands
  218.   elseif command == "NICK" then
  219.     local oldNick, newNick = name(prefix), tostring(args[1] or message)
  220.     if oldNick == nick then
  221.       nick = newNick
  222.     end
  223.     print(oldNick .. " is now known as " .. newNick .. ".")
  224.   elseif command == "MODE" then
  225.     if #args == 2 then
  226.       print("[" .. args[1] .. "] " .. name(prefix) .. " set mode".. ( #args[2] > 2 and "s" or "" ) .. " " .. tostring(args[2] or message) .. ".")
  227.     else
  228.       local setmode = {}
  229.       local cumode = "+"
  230.       args[2]:gsub(".", function(char)
  231.         if char == "-" or char == "+" then
  232.           cumode = char
  233.         else
  234.           table.insert(setmode, {cumode, char})
  235.         end
  236.       end)
  237.       local d = {}
  238.       local users = {}
  239.       for i = 3, #args do
  240.         users[i-2] = args[i]
  241.       end
  242.       users[#users+1] = message
  243.       local last
  244.       local ctxt = ""
  245.       for c = 1, #users do
  246.         if not setmode[c] then
  247.           break
  248.         end
  249.         local mode = setmode[c][2]
  250.         local pfx = setmode[c][1]=="+"
  251.         local key = mode == "o" and (pfx and "opped" or "deoped") or
  252.           mode == "v" and (pfx and "voiced" or "devoiced") or
  253.           mode == "q" and (pfx and "quieted" or "unquieted") or
  254.           mode == "b" and (pfx and "banned" or "unbanned") or
  255.           "set " .. setmode[c][1] .. mode .. " on"
  256.         if last ~= key then
  257.           if last then
  258.             print(ctxt)
  259.           end
  260.           ctxt = "[" .. args[1] .. "] " .. name(prefix) .. " " .. key
  261.           last = key
  262.         end
  263.         ctxt = ctxt .. " " .. users[c]
  264.       end
  265.       if #ctxt > 0 then
  266.         print(ctxt)
  267.       end
  268.     end
  269.   elseif command == "QUIT" then
  270.     --remUser(args[1], name(prefix))
  271.     print(name(prefix) .. " quit (" .. (message or "Quit") .. ").")
  272.   elseif command == "JOIN" then
  273.     --table.insert(users[args[1]], name(prefix))
  274.     print("[" .. args[1] .. "] " .. name(prefix) .. " entered the room.")
  275.   elseif command == "PART" then
  276.     --remUser(args[1], name(prefix))
  277.     print("[" .. args[1] .. "] " .. name(prefix) .. " has left the room (quit: " .. (message or "Quit") .. ").")
  278.   elseif command == "TOPIC" then
  279.     print("[" .. args[1] .. "] " .. name(prefix) .. " has changed the topic to: " .. message)
  280.   elseif command == "KICK" then
  281.     print("[" .. args[1] .. "] " .. name(prefix) .. " kicked " .. args[2])
  282.   elseif command == "PRIVMSG" then
  283.     local ctcp = message:match("^\1(.-)\1$")
  284.     if ctcp then
  285.       --print("[" .. name(prefix) .. "] CTCP " .. ctcp)
  286.       local ctcp, param = ctcp:match("^(%S+) ?(.-)$")
  287.       ctcp = ctcp:upper()
  288.  
  289.       print("[" .. name(prefix) .. "] CTCP " .. ctcp)
  290.      
  291.       if ctcp == "TIME" then
  292.         sock:write("NOTICE " .. name(prefix) .. " :\001TIME " .. os.date() .. "\001\r\n")
  293.         sock:flush()
  294.       elseif ctcp == "VERSION" then
  295.         sock:write("NOTICE " .. name(prefix) .. " :\001VERSION Minecraft/OpenComputers Lua 5.2\001\r\n")
  296.         sock:flush()
  297.       elseif ctcp == "PING" then
  298.         sock:write("NOTICE " .. name(prefix) .. " :\001PING " .. param .. "\001\r\n")
  299.         sock:flush()
  300.       end
  301.     else
  302.       if string.find(message, "\001ACTION") then
  303.         chatSay(args[1], args[1], name(prefix), " " .. string.gsub(string.gsub(message, "\001ACTION", ""), "\001", ""))
  304.       else
  305.         chatSay(args[1], args[1], name(prefix), ": " .. message)
  306.       end
  307.     end
  308.   elseif command == "NOTICE" then
  309.     print("[NOTICE] " .. message)
  310.   elseif command == "ERROR" then
  311.     print("[ERROR] " .. message)
  312.  
  313.   ---------------------------------------------------
  314.   -- Ignored reserved numbers
  315.   -- -- http://tools.ietf.org/html/rfc2812#section-5.3
  316.  
  317.   elseif tonumber(command) and ignore[tonumber(command)] then
  318.     -- ignore
  319.  
  320.   ---------------------------------------------------
  321.   -- Command replies
  322.   -- http://tools.ietf.org/html/rfc2812#section-5.1
  323.  
  324.   elseif command == commands.RPL_WELCOME then
  325.     print(message)
  326.   elseif command == commands.RPL_YOURHOST then -- ignore
  327.   elseif command == commands.RPL_CREATED then -- ignore
  328.   elseif command == commands.RPL_MYINFO then -- ignore
  329.   elseif command == commands.RPL_BOUNCE then -- ignore
  330.   elseif command == commands.RPL_LUSERCLIENT then
  331.     print(message)
  332.   elseif command == commands.RPL_LUSEROP then -- ignore
  333.   elseif command == commands.RPL_LUSERUNKNOWN then -- ignore
  334.   elseif command == commands.RPL_LUSERCHANNELS then -- ignore
  335.   elseif command == commands.RPL_LUSERME then
  336.     print(message)
  337.   elseif command == commands.RPL_AWAY then
  338.     print(string.format("%s is away: %s", name(args[1]), message))
  339.   elseif command == commands.RPL_UNAWAY or command == commands.RPL_NOWAWAY then
  340.     print(message)
  341.   elseif command == commands.RPL_WHOISUSER then
  342.     local nick = args[2]:lower()
  343.     whois[nick].nick = args[2]
  344.     whois[nick].user = args[3]
  345.     whois[nick].host = args[4]
  346.     whois[nick].realName = message
  347.   elseif command == commands.RPL_WHOISSERVER then
  348.     local nick = args[2]:lower()
  349.     whois[nick].server = args[3]
  350.     whois[nick].serverInfo = message
  351.   elseif command == commands.RPL_WHOISOPERATOR then
  352.     local nick = args[2]:lower()
  353.     whois[nick].isOperator = true
  354.   elseif command == commands.RPL_WHOISIDLE then
  355.     local nick = args[2]:lower()
  356.     whois[nick].idle = tonumber(args[3])
  357.   elseif command == commands.RPL_WHOISSECURE then
  358.     local nick = args[2]:lower()
  359.     whois[nick].secureconn = "Is using a secure connection"
  360.   elseif command == commands.RPL_ENDOFWHOIS then
  361.     local nick = args[2]:lower()
  362.     local info = whois[nick]
  363.     if info.nick then print("Nick: " .. info.nick) end
  364.     if info.user then print("User name: " .. info.user) end
  365.     if info.realName then print("Real name: " .. info.realName) end
  366.     if info.host then print("Host: " .. info.host) end
  367.     if info.server then print("Server: " .. info.server .. (info.serverInfo and (" (" .. info.serverInfo .. ")") or "")) end
  368.     if info.secureconn then print(info.secureconn) end
  369.     if info.channels then print("Channels: " .. info.channels) end
  370.     if info.idle then print("Idle for: " .. info.idle) end
  371.     whois[nick] = nil
  372.   elseif command == commands.RPL_WHOISCHANNELS then
  373.     local nick = args[2]:lower()
  374.     whois[nick].channels = message
  375.   elseif command == commands.RPL_CHANNELMODEIS then
  376.     print("Channel mode for " .. args[1] .. ": " .. args[2] .. " (" .. args[3] .. ")")
  377.   elseif command == commands.RPL_NOTOPIC then
  378.     print("No topic is set for " .. args[1] .. ".")
  379.   elseif command == commands.RPL_TOPIC then
  380.     print("Topic for " .. args[1] .. ": " .. message)
  381.   elseif command == commands.RPL_NAMREPLY then
  382.     local channel = args[3]
  383.     table.insert(names[channel], message)
  384.   elseif command == commands.RPL_ENDOFNAMES then
  385.     local channel = args[2]
  386.     print("Users on " .. channel .. ": " .. (#names[channel] > 0 and table.concat(names[channel], " ") or "none"))
  387.     users[channel] = names[channel]
  388.     names[channel] = nil
  389.     component.chat_box.say("Connected to IRC.")
  390.   elseif command == commands.RPL_MOTDSTART then
  391.     if options.motd then
  392.       print(message .. args[1])
  393.     end
  394.   elseif command == commands.RPL_MOTD then
  395.     if options.motd then
  396.       print(message)
  397.     end
  398.   elseif command == commands.RPL_ENDOFMOTD then -- ignore
  399.   elseif command == commands.RPL_HELPSTART or
  400.   command == commands.RPL_HELPTXT or
  401.   command == commands.RPL_ENDOFHELP then
  402.     print(message)
  403.   elseif command == commands.ERR_BANLISTFULL or
  404.   command == commands.ERR_BANNEDFROMCHAN or
  405.   command == commands.ERR_CANNOTSENDTOCHAN or
  406.   command == commands.ERR_CHANNELISFULL or
  407.   command == commands.ERR_CHANOPRIVSNEEDED or
  408.   command == commands.ERR_ERRONEUSNICKNAME or
  409.   command == commands.ERR_INVITEONLYCHAN or
  410.   command == commands.ERR_NICKCOLLISION or
  411.   command == commands.ERR_NOSUCHNICK or
  412.   command == commands.ERR_NOTONCHANNEL or
  413.   command == commands.ERR_UNIQOPRIVSNEEDED or
  414.   command == commands.ERR_UNKNOWNMODE or
  415.   command == commands.ERR_USERNOTINCHANNEL or
  416.   command == commands.ERR_WASNOSUCHNICK or
  417.   command == commands.ERR_MODELOCK then
  418.     print("[ERROR]: " .. message)
  419.   elseif tonumber(command) and (tonumber(command) >= 200 and tonumber(command) < 400) then
  420.     if message ~= nil then
  421.       print("[Response " .. command .. "] " .. table.concat(args, ", ") .. ": " .. message)
  422.     end
  423.  
  424.   ---------------------------------------------------
  425.   -- Error messages. No real point in handling those manually.
  426.   -- http://tools.ietf.org/html/rfc2812#section-5.2
  427.  
  428.   elseif tonumber(command) and (tonumber(command) >= 400 and tonumber(command) < 600) then
  429.     print("[Error] " .. table.concat(args, ", ") .. ": " .. message)
  430.  
  431.   ---------------------------------------------------
  432.   -- Unhandled message.
  433.  
  434.   else
  435.     print("Unhandled command: " .. command .. ": " .. message)
  436.   end
  437. end
  438.  
  439. local errReport = nil
  440.  
  441. -- catch errors to allow manual closing of socket and removal of timer.
  442. local result, reason = pcall(function()
  443.   -- say hello.
  444.   term.clear()
  445.   print("Welcome to OpenIRC!")
  446.  
  447.   -- avoid sock:read locking up the computer.
  448.   sock:setTimeout(0.05)
  449.  
  450.   -- http://tools.ietf.org/html/rfc2812#section-3.1
  451.   sock:write(string.format("NICK %s\r\n", nick))
  452.   sock:write(string.format("USER %s 0 * :%s [OpenComputers]\r\n", nick:lower(), nick))
  453.   sock:flush()
  454.  
  455.   -- socket reading logic (receive messages) driven by a timer.
  456.   timer = event.timer(0.5, function()
  457.     if not sock then
  458.       return false
  459.     end
  460.     repeat
  461.       local ok, line = pcall(sock.read, sock)
  462.       if ok then
  463.         if not line then
  464.           print("Connection lost.")
  465.           sock:close()
  466.           sock = nil
  467.           return false
  468.         end
  469.         line = text.trim(line) -- get rid of trailing \r
  470.         local match, prefix = line:match("^(:(%S+) )")
  471.         if match then line = line:sub(#match + 1) end
  472.         local match, command = line:match("^(([^:]%S*))")
  473.         if match then line = line:sub(#match + 1) end
  474.         local args = {}
  475.         repeat
  476.           local match, arg = line:match("^( ([^:]%S*))")
  477.           if match then
  478.             line = line:sub(#match + 1)
  479.             table.insert(args, arg)
  480.           end
  481.         until not match
  482.         local message = line:match("^ :(.*)$")
  483.  
  484.         if callback then
  485.           local result, reason = pcall(callback, prefix, command, args, message)
  486.           if not result then
  487.             print("Error in callback: " .. tostring(reason))
  488.           end
  489.         end
  490.         handleCommand(prefix, command, args, message)
  491.       end
  492.     until not ok
  493.  
  494.   end, math.huge)
  495.  
  496.  
  497.   os.sleep(12)
  498.   -- default target for messages, so we don't have to type /msg all the time.
  499.   local target = "#BTM"
  500.   sock:write("JOIN #BTM\r\n")
  501.   sock:flush()
  502.  
  503.   event.onError = function(msg)
  504.     nativeprint(msg)
  505.     computer.pushSignal("killself")
  506.   end
  507.  
  508.   local function chatBoxRead(causedEvent, chatBoxID, username,message)
  509.     print("[" .. (target or "?") .. "] " .. nick .. ": " .. "<"..username.."> "..message, true,true)
  510.     if not sock or sock:write("PRIVMSG " .. target .. " :<" .. username .. "> " .. message .. "\r\n") == nil then sock = nil
  511.       error("Socket died")
  512.       computer.pushSignal("killself")
  513.     else sock:flush() end
  514.   end
  515.  
  516.   local chatReader = event.listen("chat_message",chatBoxRead)
  517.  
  518.   -- command history.
  519.   local history = {}
  520.  
  521.   timer2 = event.timer(30, function()
  522.       if sock == nil then computer.pushSignal("killself") end
  523.     end, math.huge)
  524.  
  525.   repeat
  526.    
  527.     local ev = event.pull("killself")
  528.     sock = nil
  529.     line = nil
  530.     --[[term.write((target or "?") .. "> ")
  531.     local line = term.read(history)
  532.     if sock and line and line ~= "" then
  533.       line = text.trim(line)
  534.       if line:lower():sub(1,4) == "/me " then
  535.         print("[" .. (target or "?") .. "] " .. nick .. " " .. line:sub(5), true)
  536.       elseif line~="" then
  537.         print("[" .. (target or "?") .. "] " .. nick .. ": " .. line, true)
  538.       end
  539.       if line:lower():sub(1, 5) == "/msg " then
  540.         local user, message = line:sub(6):match("^(%S+) (.+)$")
  541.         if message then
  542.           message = text.trim(message)
  543.         end
  544.         if not user or not message or message == "" then
  545.           print("Invalid use of /msg. Usage: /msg nick|channel message.")
  546.           line = ""
  547.         else
  548.           target = user
  549.           line = "PRIVMSG " .. target .. " :" .. message
  550.         end
  551.       elseif line:lower():sub(1, 6) == "/join " then
  552.         local channel = text.trim(line:sub(7))
  553.         if not channel or channel == "" then
  554.           print("Invalid use of /join. Usage: /join channel.")
  555.           line = ""
  556.         else
  557.           target = channel
  558.           line = "JOIN " .. channel
  559.         end
  560.       elseif line:lower():sub(1, 5) == "/lua " then
  561.         local script = text.trim(line:sub(6))
  562.         local result, reason = load(script, "=stdin", nil, setmetatable({print=print, socket=sock, nick=nick}, {__index=_G}))
  563.         if not result then
  564.           result, reason = load("return " .. script, "=stdin", nil, setmetatable({print=print, socket=sock, nick=nick}, {__index=_G}))
  565.         end
  566.         line = ""
  567.         if not result then
  568.           print("Error: " .. tostring(reason))
  569.         else
  570.           result, reason = pcall(result)
  571.           if not result then
  572.             print("Error: " .. tostring(reason))
  573.           elseif type(reason) == "function" then
  574.             callback = reason
  575.           elseif reason then
  576.             line = tostring(reason)
  577.           end
  578.         end
  579.       elseif line:lower():sub(1,4) == "/me " then
  580.         if not target then
  581.           print("No default target set. Use /msg or /join to set one.")
  582.           line = ""
  583.         else
  584.           line = "PRIVMSG " .. target .. " :\001ACTION " .. line:sub(5) .. "\001"
  585.         end
  586.       elseif line:sub(1, 1) == "/" then
  587.         line = line:sub(2)
  588.       elseif line ~= "" then
  589.         if not target then
  590.           print("No default target set. Use /msg or /join to set one.")
  591.           line = ""
  592.         else
  593.           line = "PRIVMSG " .. target .. " :" .. line
  594.         end
  595.       end
  596.       if line and line ~= "" then
  597.         sock:write(line .. "\r\n")
  598.         sock:flush()
  599.       end
  600.     end--]]
  601.   until not sock or not line
  602. end)
  603.  
  604. if sock then
  605.   sock:write("QUIT\r\n")
  606.   sock:close()
  607. end
  608. if timer then
  609.   event.cancel(timer)
  610. end
  611. if timer2 then
  612.   event.cancel(timer2)
  613. end
  614.  
  615. if not result then
  616.   error(reason)
  617. end
  618. return reason
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement