local cqueues = require'cqueues' local socket = require'cqueues.socket' local condition = require'cqueues.condition' local pprint = require'pprint' local rirc = require'rirc' local Irc = {} function Irc.makepylon(pylonname, conf) local self = {pylonname=pylonname} local function conf_var(name) assert(conf[name] ~= nil, 'missing conf field '..name) self[name] = conf[name] end conf_var 'host' conf_var 'port' conf_var 'password' conf_var 'nodename' self.outqueue = {} self.outcv = condition.new() setmetatable(self, {__index=Irc}) return self end function Irc.send(self, args) args.source = args.source or self.nodename rirc.send(self.sock, args) 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.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 ch = msg.args[1] local body = msg.args[2] local source = msg.source local neighbors = self.network:neighbors_of(self.pylonname, ch) pprint('gt neighbors', neighbors) for _,other in ipairs(neighbors) do other.pylon:enqueue { channel = other.channel, body = body, source = source..'[i]' } end 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') while true do while #self.outqueue > 0 do local queue = self.outqueue self.outqueue = {} for _, outmsg in pairs(queue) do assert(say(outmsg.source, outmsg.channel, outmsg.body)) end end self.outcv:wait() end end function Irc.enqueue(self, message) table.insert(self.outqueue, message) self.outcv:signal() end function Irc.run(self, cq, network) self.network = network self:connect() cq:wrap(self.recving, self) cq:wrap(self.sending, self) end local cq = cqueues.new() local conf = { host = 'localhost', port = '6667', password = 'mypassword', nodename = 'wilson.ubq323', } local dummy_pylon = { enqueue = function(self, msg) print(string.format( "%s <%s> | %s", msg.channel, msg.source, msg.body)) end } local network = {neighbors_of = function(self, pylonname, channel) print('looking for neighbors of '..pylonname..', '..channel) return { {pylon = dummy_pylon, channel='#bridge'} } end} local pylon = Irc.makepylon('test', conf) pylon:run(cq, network) pprint(cq:loop())