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
|