local socket = require('cqueues.socket') local colors = { [0] = 15, [1] = 0, [2] = 4, [3] = 2, [4] = 1, [5] = 3, [6] = 5, [7] = 3, [8] = 11, [9] = 10, [10] = 6, [11] = 14, [12] = 12, [13] = 13, [14] = 8, [15] = 7 } local Logger do local _class_0 local _base_0 = { helpers = { error = '\00304', reset = '\003', warn = '\00308', okay = '\00303' }, print_bare = function(line) return print(line:gsub('\003(%d%d?),(%d%d?)', function(fg, bg) fg, bg = tonumber(fg), tonumber(bg) if colors[fg] and colors[bg] then return '\27[38;5;' .. colors[fg] .. ';48;5;' .. colors[bg] .. 'm' end end):gsub('\003(%d%d?)', function(fg) fg = tonumber(fg) if colors[fg] then return '\27[38;5;' .. colors[fg] .. 'm' end end):gsub('\003', function() return '\27[0m' end) .. '\27[0m') end, log = function(line) return Logger.print_bare(os.date('[%X]'):gsub('.', function(ch) if ch:match('[%[%]:]') then return '\00311' .. ch .. '\003' else return '\00315' .. ch .. '\003' end end) .. ' ' .. line) end } _base_0.__index = _base_0 _class_0 = setmetatable({ __init = function() end, __base = _base_0, __name = "Logger" }, { __index = _base_0, __call = function(cls, ...) local _self_0 = setmetatable({}, _base_0) cls.__init(_self_0, ...) return _self_0 end }) _base_0.__class = _class_0 Logger = _class_0 end local IRCConnection do local _class_0 local _base_0 = { add_handler = function(self, id, handler) if not self.handlers[id] then self.handlers[id] = { handler } else return table.insert(self.handlers[id], handler) end end, add_sender = function(self, id, sender) assert(not self.senders[id], "Sender already exists: " .. id) self.senders[id] = sender end, load_modules = function(self, modules) if modules.senders then for id, sender in pairs(modules.senders) do self:add_sender(id, sender) end end if modules.handlers then for id, handler in pairs(modules.handlers) do self:add_handler(id, handler) end end end, connect = function(self) if self.socket then self.socket:shutdown() end local host = self.config.server local port = self.config.port Logger.log(Logger.helpers.warn .. '--- Connecting...') self.socket = assert(socket.connect({ host = host, port = port })) Logger.log(Logger.helpers.okay .. '--- Connected') if self.config.ssl then self.socket:starttls() end local nick = self.config.nick or 'Moonmoon' local user = self.config.username or 'moon' local real = self.config.realname or 'Moon Moon: MoonScript IRC Bot' self:send_raw(('NICK %s'):format(nick)) self:send_raw(('USER %s * * :%s'):format(user, real)) return Logger.log(Logger.helpers.okay .. '--- Sent authentication data') end, send_raw = function(self, ...) return self.socket:write(table.concat({ ... }, ' ') .. '\n') end, send = function(self, name, pattern, ...) return self.senders[name](pattern:format(...)) end, parse = function(self, message) local prefix_end = 0 local prefix = nil if message:sub(1, 1) == ":" then prefix_end = message:find(" ") prefix = message:sub(2, message:find(" ") - 1) end local trailing = nil local tstart = message:find(" :") if tstart then trailing = message:sub(tstart + 1) else tstart = #message end local rest = (function(segment) local t = { } for word in segment:gmatch("%S+") do table.insert(t, word) end return t end)(message:sub(prefix_end + 1, tstart)) local command = rest[1] table.remove(rest, 1) return prefix, command, rest, trailing end, process = function(self, line) local prefix, command, args, rest = self:parse(line) if not self.handlers[command] then return end for _, handler in pairs(self.handlers[command]) do local ok, err = pcall(handler, self, prefix, args, rest) if not ok then Logger.log(Logger.helpers.warn .. ' *** ' .. err) end end end, loop = function(self) local line local print_error print_error = function(err) return Logger.log("Error: " .. err .. " (" .. line .. ")") end for received_line in self.socket:lines() do line = received_line xpcall(self.process, print_error, self, received_line) end end } _base_0.__index = _base_0 _class_0 = setmetatable({ __init = function(self, server, port, config) if port == nil then port = 6667 end if config == nil then config = { } end assert(server) self.config = { server = server, port = port, config = config } for k, v in pairs(config) do self.config[k] = v end self.handlers = { } self.senders = { } self.server = { } end, __base = _base_0, __name = "IRCConnection" }, { __index = _base_0, __call = function(cls, ...) local _self_0 = setmetatable({}, _base_0) cls.__init(_self_0, ...) return _self_0 end }) _base_0.__class = _class_0 IRCConnection = _class_0 end return { IRCConnection = IRCConnection, Logger = Logger }