From d992dcc9ae8835d20f99a072f252df55de1515a8 Mon Sep 17 00:00:00 2001 From: Jakob Ovrum Date: Wed, 10 Mar 2010 20:03:36 +0900 Subject: [PATCH] Refactored structure --- init.lua | 249 +++++++++---------------------------------------------- 1 file changed, 37 insertions(+), 212 deletions(-) diff --git a/init.lua b/init.lua index 4be79cb..75a2a94 100644 --- a/init.lua +++ b/init.lua @@ -1,97 +1,44 @@ ---[[ - Lua IRC library - - Copyright (c) 2010 Jakob Ovrum - - Permission is hereby granted, free of charge, to any person - obtaining a copy of this software and associated documentation - files (the "Software"), to deal in the Software without - restriction, including without limitation the rights to use, - copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following - conditions: - - The above copyright notice and this permission notice shall be - included in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - OTHER DEALINGS IN THE SOFTWARE.]] - local socket = require "socket" local error = error local setmetatable = setmetatable local rawget = rawget -local ipairs = ipairs -local print = print local unpack = unpack local pairs = pairs -local string = string -local tostring = tostring -local table = table -local type = type +local assert = assert +local require = require -module("irc") +local print = print -local function assert(b, err, errlevel) - if not b then - error(err, errlevel or 3) - end - return b -end - -debug = false - -local clients = {} +module "irc" local meta = {} meta.__index = meta +_META = meta + +require "irc.util" +require "irc.asyncoperations" local meta_preconnect = {} - -local function postAuth_join(o, channel, key) - if key then - o:send("JOIN %s :%s", channel, key) - else - o:send("JOIN %s", channel) - end -end - function meta_preconnect.__index(o, k) - local v = rawget(meta_preconnect, k) - if not v and meta[k] then - error("field '"..k.."' is not accessible before connecting", 2) - end - return v + local v = rawget(meta_preconnect, k) + + if not v and meta[k] then + error("field '"..k.."' is not accessible before connecting", 2) + end + return v end - + function new(user) - local o = {} - o.nick = assert(user.nick, "Field 'nick' is required") - o.username = user.username or "lua" - o.realname = user.realname or "Lua owns" - o.socket = socket.tcp() - o.hooks = {} - o.rooms = {} - o.connected = false - + local o = { + nick = assert(user.nick, "Field 'nick' is required"); + username = user.username or "lua"; + realname = user.realname or "Lua owns"; + hooks = {}; + } return setmetatable(o, meta_preconnect) end -function think() - local think = meta.think - for _,o in ipairs(clients) do - think(o) - end -end - function meta:hook(name, id, f) f = f or id self.hooks[name] = self.hooks[name] or {} @@ -116,26 +63,24 @@ function meta:invoke(name, ...) end end -function meta:connect(server, port) +function meta_preconnect:connect(server, port, timeout) port = port or 6667 - self.socket:settimeout(30) - local succ, err = self.socket:connect(server, port) - if not succ then return nil, err end - + local s = socket.tcp() + self.socket = s + s:settimeout(timeout or 30) + assert(s:connect(server, port)) + setmetatable(self, meta) self:send("USER %s 0 * :%s", self.username, self.realname) self:send("NICK %s", self.nick) - - self._i = #clients + 1 - clients[self._i] = self - - self.socket:settimeout(0) - self.connected = true - return true + + s:settimeout(0) + repeat + self:think() + until self.authed end -meta_preconnect.connect = meta.connect function meta:disconnect(message) local message = message or "Bye!" @@ -147,13 +92,8 @@ function meta:disconnect(message) end function meta:shutdown() - self.connected = false - self.socket:shutdown() self.socket:close() - - clients[self._i] = nil - setmetatable(self, nil) end @@ -165,13 +105,13 @@ local function getline(self, errlevel) self:shutdown() error(err, errlevel) end - + return line end function meta:think() while true do - local line = getline(self, 4) + local line = getline(self, 3) if line then self:handle(parse(line)) else @@ -180,42 +120,6 @@ function meta:think() end end -function parsePrefix(prefix) - local user = {} - if prefix then - user.nick, user.username, user.host = prefix:match("(.*)!(.*)@(.*)") - end - return user -end - -function parse(line) - local colonsplit = line:find(":", 2) - local last - if colonsplit then - last = line:sub(colonsplit+1) - line = line:sub(1, colonsplit-2) - end - - local prefix - if line:sub(1,1) == ":" then - local space = line:find(" ") - prefix = line:sub(2, space-1) - line = line:sub(space) - end - - local params = {} - local it, state, init = line:gmatch("(%S+)") - local cmd = it(state, init) - - for sub in it, state, init do - params[#params + 1] = sub - end - - if last then params[#params + 1] = last end - - return prefix, cmd, params -end - local handlers = {} handlers["PING"] = function(o, prefix, query) @@ -223,17 +127,7 @@ handlers["PING"] = function(o, prefix, query) end handlers["001"] = function(o) - if type(o.config.startup) == "function" then - o.config.startup(o) - end - - o.join = postAuth_join - for k,room in ipairs(o.rooms) do - o:join(room.name, room.key) - end - o.rooms = nil - - o:invoke("OnConnect") + o.authed = true end handlers["PRIVMSG"] = function(o, prefix, channel, message) @@ -255,72 +149,16 @@ end handlers["ERROR"] = function(o, prefix, message) o:invoke("OnDisconnect", message, true) o:shutdown() - error(message) + error(message, 3) end function meta:handle(prefix, cmd, params) local handler = handlers[cmd] if handler then - return handler(self, prefix, unpack(params)) + handler(self, prefix, unpack(params)) end end -function meta:send(fmt, ...) - self.socket:send(fmt:format(...) .. "\r\n") -end - -function meta:sendChat(channel, msg) - toChannel = table.concat{"PRIVMSG ", channel, " :"} - for line in msg:gmatch("[^\r\n]+") do - self.socket:send(table.concat{toChannel, line, "\r\n"}) - end -end - ---preAuth_join -function meta:join(channel, key) - table.insert(self.rooms, {name = channel, key = key}) -end -meta_preconnect.join = meta.join - -function meta:part(channel) - self:send("PART %s", channel) -end - -color = { - black = 1, - blue = 2, - green = 3, - red = 4, - lightred = 5, - purple = 6, - brown = 7, - yellow = 8, - lightgreen = 9, - navy = 10, - cyan = 11, - lightblue = 12, - violet = 13, - gray = 14, - lightgray = 15, - white = 16 -} - -local colByte = string.char(3) -setmetatable(color, {__call = function(_, text, colornum) - colornum = type(colornum) == "string" and assert(color[colornum], "Invalid color '"..colornum.."'") or colornum - return table.concat{colByte, tostring(colornum), text, colByte} -end}) - -local boldByte = string.char(2) -function bold(text) - return boldByte..text..boldByte -end - -local underlineByte = string.char(31) -function underline(text) - return underlineByte..text..underlineByte -end - local whoisHandlers = { ["311"] = "userinfo"; ["312"] = "node"; @@ -354,16 +192,3 @@ function meta:whois(nick) end return result end - -function meta:setmode(t) - local target = t.target or self.nick - local mode = "" - local add, rem = t.add, t.remove - if add then - mode = table.concat{mode, "+", add} - elseif rem then - mode = table.concat{mode, "-", rem} - end - - self:send("MODE %s %s", target, mode) -end