summaryrefslogtreecommitdiff
path: root/irc.lua
blob: d6f8dae1ae0bf5724c3e42c9bba7ac607f67dc15 (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
120
121
122
123
124
125
126
127
128
129
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())