summaryrefslogtreecommitdiff
path: root/nanochat/pylon.lua
blob: c92897d5bbb4f2b978611be81fddc9d92a48a10c (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
local cqueues = require 'cqueues'
local socket = require 'cqueues.socket'
local class = require 'r.class'

local BasePylon = require 'pylon'
local Thing = require 'thing'

local Nanochat = class.extend(BasePylon)

function Nanochat:init()
	self:_check_fields "server port poll"
end

function Nanochat:_connect()
	self.sock = socket.connect(self.server, tonumber(self.port))
	self.sock:write("LAST 0\n")
	self.sock:read("*l") -- discard count
	self.lastid = tonumber(assert(self.sock:read("*l")))
	self.usids = {}
end

function Nanochat:recving()
	while true do
		self.sock:write("SKIP "..self.lastid.."\n")
		local deliverables = {} -- holey
		local n = tonumber(assert(self.sock:read("*l")))
		for i=1,n do
			local msg = assert(self.sock:read("*l"))
			local chan, msgi = msg:match("^([^ ]+) ()")
			if chan then
				local sender, body = msg:match("^([^:]+): (.+)$", msgi)
				if sender then
					deliverables[i] = {
						pylon=self,
						channel=Thing(self, chan),
						author=Thing(self,sender),
						body=body
					}
				else
					deliverables[i] = {
						pylon=self,
						channel=Thing(self, chan),
						author=Thing(self,""),
						body=msg:sub(msgi,-1)
					}
				end
			end
			-- else ignore messages without a channel, they stay nanochat-local
		end
		local s = self.sock:read("*l")
		self.lastid = tonumber(assert(s))

		for i=1,n do
			local msg = deliverables[i] ; if msg then
				local id = i - n + self.lastid
				if self.usids[id] then
					self.usids[id] = nil
				else
					self.log:proto('<', msg.channel.id, msg.author, msg.body)
					msg.pylon_ids = { [self]=id }
					self.wilson:deliver(msg)
				end
			end
		end

		cqueues.sleep(tonumber(self.poll))
	end
end

function Nanochat:sending()
	for dest_channel, message in self.inbox:iter() do
		self.log:proto('>',dest_channel,message.author,message.body)
		assert(self.sock:write(
			"SEND "
			..dest_channel.id
			..message.author:name_with_shortname()
			..": "..message.body
			.."\n"))
		local id = assert(tonumber(self.sock:read("*l")))
		message.pylon_ids[self] = id
		self.usids[id] = true
	end
end


return Nanochat