diff options
author | ubq323 <ubq323@ubq323.website> | 2025-02-25 23:43:41 +0000 |
---|---|---|
committer | ubq323 <ubq323@ubq323.website> | 2025-02-25 23:43:41 +0000 |
commit | 4dec20e4ff11b61be57a6cfbdb289327d9e1eb7d (patch) | |
tree | cc2ffe0357c1110236270ad46dc2006cdb01bf89 /irc | |
parent | e03937bbe51f3dd8e0d8ecc732999f5c4578fa94 (diff) |
the Restructuring
Diffstat (limited to 'irc')
-rw-r--r-- | irc/pylon.lua | 96 | ||||
-rw-r--r-- | irc/rirc.lua | 61 |
2 files changed, 157 insertions, 0 deletions
diff --git a/irc/pylon.lua b/irc/pylon.lua new file mode 100644 index 0000000..4259f5e --- /dev/null +++ b/irc/pylon.lua @@ -0,0 +1,96 @@ +local cqueues = require'cqueues' +local socket = require'cqueues.socket' +local pprint = require'pprint' +local rirc = require'irc.rirc' +local Queue = require'util.queue' +local Channel = require'util.channel' + +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 diff --git a/irc/rirc.lua b/irc/rirc.lua new file mode 100644 index 0000000..0508351 --- /dev/null +++ b/irc/rirc.lua @@ -0,0 +1,61 @@ +local irc = {} + +function irc.sendmsg(conn, ch, msg) + local m = msg:gsub("[\r\n]+"," ") + local l = 512-12-#ch + m = m:sub(1,l) + conn:send("PRIVMSG "..ch.." :"..m.."\r\n") +end + +function irc.send(sock, args) + local out = '' + if args.source then + out = ':' .. args.source .. ' ' + end + for i = 1, #args-1 do + local arg = tostring(args[i]) + out = out .. arg:gsub("[\r\n ]+","") .. ' ' + end + local last = tostring(args[#args]):gsub("[\r\n]+"," ") + out = out .. ':' .. last + sock:write(out..'\r\n') + return out +end + +function irc.parse(line) + local words = {} + local idx = 1 + while true do + local word,nidx = line:match("(%g+)%s*()",idx) + if not word then + break + elseif word:sub(1,1) == ":" and idx ~= 1 then + -- first word can start with : + local rest = line:sub(idx+1) + table.insert(words,rest) + break + else + table.insert(words,word) + idx = nidx + end + end + + local from = nil + if words[1] and words[1]:sub(1,1) == ":" then + -- we have a source + from = table.remove(words,1):sub(2) + end + + local op = words[1] + local args = {} + for i=2,#words do + args[i-1] = words[i] + end + return {source=from,op=op:upper(),args=args} +end + +function irc.parse_src(src) + return src:match"^(.*)!(.*)@(.*)$" +end + +return irc |