local cqueues = require'cqueues' local socket = require'cqueues.socket' local pprint = require'pprint' local rirc = require'rirc' local Queue = require'queue' local Irc = {} function Irc._send(self, args) args.source = args.source or self.nodename local sent = rirc.send(self.sock, args) print('>', sent) end function Irc.check_config(self, vars) for x in vars:gmatch("%S+") do assert(self[x], "missing conf field "..x) end end function Irc.make(wilson, conf) local self = setmetatable(conf, {__index=Irc}) for k,v in pairs { wilson = wilson, inbox = Queue.make(), } do self[k] = v end self:check_config "host port password nodename" return self end function Irc._connect(self) self.sock = assert(socket.connect(self.host, self.port)) self:_send{'PASS', self.password, '0210-IRC', 'wilson|'} self:_send{'SERVER', self.nodename, '1', 'i am wilson'} end function Irc.run(self) local cq = cqueues.new() self:_connect() cq:wrap(self.recving, self) cq:wrap(self.sending, self) print('irc',cq:loop()) end function Irc.recving(self) for line in self.sock:lines "*l" do print('<', line) local msg = rirc.parse(line) if msg.op == 'PING' then self:_send{'PONG', msg.args[1]} elseif msg.op == 'PRIVMSG' then local channel_name = msg.args[1] local body = msg.args[2] local sender = msg.source self.wilson:deliver(Channel(self, channel_name), { body = body, sender = sender..'[i]' }) elseif msg.op == 'ERROR' then error(msg.args[1]) end end end function Irc.sending(self) local nicks_channels = {} local function ensure_joined(nick, channel) if not nicks_channels[nick] then self:_send{'NICK', nick, 1, 'username', 'host', 1, '+', 'realname'} nicks_channels[nick] = {} end if not nicks_channels[nick][channel] then self:_send{source=nick, 'JOIN', channel} nicks_channels[nick][channel] = true end end local function say(nick, channel, body) ensure_joined(nick, channel) self:_send{source=nick, 'PRIVMSG', channel, body} end say('WILSON', '#test', 'i am wilson') for dest_channel, message in self.inbox:iter() do local channel_name = dest_channel.descriptor say(message.sender, channel_name, message.body) end end function Irc.post(self, dest_channel, message) self.inbox.enqueue(dest_channel, message) end return Irc