From 359b94d98084b1e005d5add74f3739f6ef36aa8b Mon Sep 17 00:00:00 2001 From: olive Date: Sun, 13 Sep 2026 17:05:53 +0100 Subject: xmpp: multi-muc, sep out user resolution --- nanochat/pylon.lua | 4 +-- todo.txt | 4 +++ wilson.ini.example | 6 ++-- xmpp/pylon.lua | 100 +++++++++++++++++++++++++++++++++-------------------- 4 files changed, 71 insertions(+), 43 deletions(-) create mode 100644 todo.txt diff --git a/nanochat/pylon.lua b/nanochat/pylon.lua index 3e63b7a..096dcf0 100644 --- a/nanochat/pylon.lua +++ b/nanochat/pylon.lua @@ -31,9 +31,9 @@ function Nanochat:recving() if not deliverables[chan] then deliverables[chan] = {} end local sender, body = msg:match("^([^:]+): (.+)$", msgi) if sender then - deliverables[chan][#deliverables[chan]+1] = { i=i, sender=sender, body=body } + deliverables[chan][#deliverables[chan]+1] = { i=i, sender="[n]"..sender, body=body } else - deliverables[chan][#deliverables[chan]+1] = { i=i, sender=nil, body=msg:sub(msgi,-1) } + deliverables[chan][#deliverables[chan]+1] = { i=i, sender="[n]", body=msg:sub(msgi,-1) } end end end diff --git a/todo.txt b/todo.txt new file mode 100644 index 0000000..0ee8f75 --- /dev/null +++ b/todo.txt @@ -0,0 +1,4 @@ + +pylon.subclass should not have a pylon_type arg. is only used for logging. a pylon's _name_ should be used in log messages. + +pylons harcode prepend names with [x] [d] [n] etc. this is not robust and is weird it should be in some way dynamic? maybe pylons can have configured short names? but then what in the case of two channels with different users of the same nick? they should not be conflated.. diff --git a/wilson.ini.example b/wilson.ini.example index 86031a5..303d8a2 100644 --- a/wilson.ini.example +++ b/wilson.ini.example @@ -1,10 +1,10 @@ [top level] -loglevel=info +loglevel=info [pylon xmpp-barbaz] type=xmpp -; port 5222 -server=boingsrv.example.org +; port 5347 +server=localhost component=barbaz.boingsrv.example.org component_secret=seeeeeecret_password_here diff --git a/xmpp/pylon.lua b/xmpp/pylon.lua index 9568999..5056f18 100644 --- a/xmpp/pylon.lua +++ b/xmpp/pylon.lua @@ -12,11 +12,12 @@ local Xmpp = class.extend(BasePylon) function Xmpp.init(self) self:_check_fields"server component component_secret" - self.nicks_inuse = {} + + self.mucs = {} end -- only use on local connections! -function Xmpp._connect_component(self) +function Xmpp._connect(self) local sock = assert(socket.connect(self.server, 5347)) self.sock = sock sock:setmode('bn','bn') @@ -37,9 +38,51 @@ function Xmpp._connect_component(self) sock:write(xmlify(X.handshake{sha1.sha1(streamid..self.component_secret)})) check_and_send('',nil) + for busname, bus in pairs(self.wilson.busses) do + for _, channel in ipairs(bus) do + if channel.pylon == self then + self:add_channel(channel) + end + end + end + return sock end -Xmpp._connect = Xmpp._connect_component + +function Xmpp.add_channel(self, channel) + local muc = { nick_to_user={}, user_to_nick={} } + self.mucs[channel.descriptor] = muc + self.nick_bot = self:ensure_and_get_user(channel.descriptor, "wilson") +end + +function Xmpp.ensure_and_get_user(self, muc_jid, nick) + local muc = assert(self.mucs[muc_jid]) + local user = muc.nick_to_user[nick] + if user then + local user_jid = user..'@'..self.component + local nick_jid = muc_jid..'/'..nick + return user, nick, user_jid, nick_jid + end + + -- join up new user + + user = nick:gsub("[^a-zA-Z0-9%.]","."):match("^%.*(.-)%.*$") + while muc.user_to_nick[user] do user = user..'-' end + muc.nick_to_user[nick] = user + muc.user_to_nick[user] = nick + + local user_jid = user..'@'..self.component + local nick_jid = muc_jid..'/'..nick + + self.log("Joining up new user "..user_jid.." to "..nick_jid) + + self.sock:write(xmlify( + X.presence{from=user_jid, to=nick_jid, + X.x{xmlns='http://jabber.org/protocol/muc', + X.history{maxstanzas='0'}}})) + + return user, nick, user_jid, nick_jid +end function Xmpp.recving(self) local function getmore() @@ -53,50 +96,31 @@ function Xmpp.recving(self) self.log:debug(xmlify(x)) local body = x'body' and x'body'[1] if x.label == 'message' then - local from = x.xarg.from - local to = x.xarg.to - local from_addr, from_nick = from and from:match"(.*)/(.*)" - if - from_nick - and not self.nicks_inuse[from_nick] - and body - and to == 'wilson@'..self.component - then - self.log:proto('<',from_addr,from_nick,body) - self.wilson:deliver(Channel(self, from_addr), { - body = body, - sender = '[x]'..from_nick - }) + local from_bare_jid, from_nick + if x.xarg.from then from_bare_jid, from_nick = x.xarg.from:match"(.*)/(.*)" end + local muc = self.mucs[from_bare_jid] ; if muc then + if + x.xarg.to == 'wilson@'..self.component + and body + and from_nick and not muc.nick_to_user[from_nick] + then + self.log:proto('<',from_bare_jid,from_nick,body) + self.wilson:deliver(Channel(self, from_bare_jid), { + body = body, + sender = '[x]'..from_nick + }) + end end end end end function Xmpp.sending(self) - local users_inuse = {} - local function ensure_joined(muc,user,nick) - if self.nicks_inuse[nick] then return end - user = user:gsub("[^a-zA-Z0-9%.]","."):match("^%.*(.-)%.*$") - while users_inuse[user] do user = user..'-' end - local jid = user..'@'..self.component - local mucjid = muc..'/'..nick - self.nicks_inuse[nick] = true - users_inuse[user] = true - - self.sock:write(xmlify( - X.presence{from=jid, to=mucjid, - X.x{xmlns='http://jabber.org/protocol/muc', - X.history{maxstanzas='0'}}})) - end - ensure_joined('d@conference.ubq323.website', 'wilson', 'wilson') for dest_channel, message in self.inbox:iter() do self.log:proto('>',dest_channel,message.sender,message.body) - local muc = dest_channel.descriptor - ensure_joined(muc, message.sender, message.sender) - local user = message.sender:gsub("[^a-zA-Z0-9%.]","."):match("^%.*(.-)%.*$") - local jid = user..'@'..self.component + local user, nick, user_jid, nick_jid = self:ensure_and_get_user(dest_channel.descriptor, message.sender) self.sock:write(xmlify( - X.message{to=muc, type='groupchat', from=jid, + X.message{to=dest_channel.descriptor, type='groupchat', from=user_jid, X.body{message.body}})) end end -- cgit v1.2.3