summaryrefslogtreecommitdiff
path: root/irc.lua
blob: fe357537c5d8f31ceb5ed2da6c93ffbff8889d9a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
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