summaryrefslogtreecommitdiff
path: root/irc.lua
blob: 541c725f35c6f6dba075f40f5e9938c5366344dc (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
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
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.makepylon(pylonname, conf, cq, network)
	local self = {
		pylonname=pylonname,
		cq = cq,
		network = network,
		inbox = Queue.make(),
	}
	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'

	setmetatable(self, {__index=Irc})
	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)
	self:_connect()
	self.cq:wrap(self.recving, self)
	self.cq:wrap(self.sending, self)
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 = msg.args[1]
			local body = msg.args[2]
			local source = msg.source
			self.network:post(self.pylonname, channel, {
				body = body,
				source = source..'[i]'
			})
		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 ch, msg in self.inbox:iter() do
		say(msg.source, ch, msg.body)
	end
end

return Irc

-- local cq = cqueues.new()
-- local conf = {
-- 	host = 'localhost',
-- 	port = '6667',
-- 	password = 'mypassword',
-- 	nodename = 'wilson.ubq323',
-- }

-- local dummy_network = {
-- 	post = function(self, pylonname, channel, message)
-- 		pprint(pylonname, channel, message)
-- 	end
-- }

-- local pylon = Irc.makepylon('test', conf, cq, dummy_network)
-- pylon:run()
-- cq:wrap(function()
-- 	local i = 0
-- 	while true do
-- 		cqueues.sleep(1)
-- 		pylon.inbox:enqueue{
-- 			source = 'helen',
-- 			channel = '#test',
-- 			body = 'i am helen '..i,
-- 		}
-- 		i = i + 1
-- 	end
-- end)
-- pprint('cheese', cq:loop())