# HG changeset patch # User Kim Alvefur # Date 1294784391 -3600 # Node ID cb7656ee4dd8cb9dcc56454cb555fc48fbaa35e0 # Parent 3a321510707cb163e52de46fa5b3d46ada055fc7 plugins.groupchat: Update to use groupchat code in Verse diff -r 3a321510707c -r cb7656ee4dd8 plugins/groupchat.lua --- a/plugins/groupchat.lua Tue Jan 11 13:42:07 2011 +0100 +++ b/plugins/groupchat.lua Tue Jan 11 23:19:51 2011 +0100 @@ -1,14 +1,9 @@ -local events = require "events"; local st = require "util.stanza"; - -local room_mt = {}; -room_mt.__index = room_mt; - -local xmlns_delay = "urn:xmpp:delay"; local xmlns_muc = "http://jabber.org/protocol/muc"; function riddim.plugins.groupchat(bot) - bot.rooms = {}; + bot.stream:add_plugin("groupchat") + bot.rooms = bot.stream.rooms; bot:hook("started", function () for k, v in pairs(bot.config.autojoin or {}) do @@ -22,134 +17,49 @@ end end); - bot.stream:hook("stanza", function (stanza) - local room_jid = jid.bare(stanza.attr.from); - local room = bot.rooms[room_jid] - if room then - local nick = select(3, jid.split(stanza.attr.from)); - local body = stanza:get_child("body"); - local delay = stanza:get_child("delay", xmlns_delay); - local event = { - room_jid = room_jid; - room = room; - sender = room.occupants[nick]; - nick = nick; - body = (body and body:get_text()) or nil; - stanza = stanza; - delay = (delay and delay.attr.stamp); - }; - if stanza.name == "message" then - local replied; - local r = st.reply(stanza); - if stanza.attr.type == "groupchat" then - r.attr.type = stanza.attr.type; - r.attr.to = jid.bare(stanza.attr.to); - end - function event:reply(reply) - if not reply then reply = "Nothing to say to you"; end - if replied then return false; end - replied = true; - if r.attr.type == "groupchat" then - reply = event.sender.nick..": "..reply; - end - room:send(r:tag("body"):text(reply)); - end - end - local ret; - if stanza.name ~= "message" or nick ~= room.nick then - ret = room:event(stanza.name, event); - end - return ret or (stanza.name == "message") or nil; - end - end, 500); - - function bot:join_room(jid, nick) + -- Re-broadcast groupchat event on the bot + local reflect_events = { "groupchat/joining"; "groupchat/joined"; "groupchat/leaving"; "groupchat/left" }; + for i = 1,#reflect_events do + bot.stream:hook(reflect_events[i], function(room, ...) + room.bot = bot; + bot:event(reflect_events[i], room, ...) + end); + end + + function bot:join_room(room_jid, nick) nick = nick or bot.config.nick or ("bot"..math.random(10000,99999)); - local room = setmetatable({ - bot = bot, jid = jid, nick = nick, - occupants = {}, - events = events.new() - }, room_mt); - self.rooms[jid] = room; - local occupants = room.occupants; - room:hook("presence", function (presence) - local nick = presence.nick or nick; - if not occupants[nick] and presence.stanza.attr.type ~= "unavailable" then - occupants[nick] = { - nick = nick; - jid = presence.stanza.attr.from; - presence = presence.stanza; - }; - local x = presence.stanza:get_child("x", xmlns_muc .. "#user"); - if x then - local x_item = x:get_child("item"); - if x_item and x_item.attr then - occupants[nick].real_jid = x_item.attr.jid; - occupants[nick].affiliation = x_item.attr.affiliation; - occupants[nick].role = x_item.attr.role; - end + local room = bot.stream:join_room(room_jid, nick) + room.bot = bot; + room:hook("message", function(event) + if event.nick == room.nick then + return true; + end + end, 1000); + room:hook("message", function(event) + local stanza = event.stanza; + local replied; + local r = st.reply(stanza); + if stanza.attr.type == "groupchat" then + r.attr.type = stanza.attr.type; + r.attr.to = jid.bare(stanza.attr.to); + end + function event:reply(reply) + if not reply then reply = "Nothing to say to you"; end + if replied then return false; end + replied = true; + if r.attr.type == "groupchat" then + reply = event.sender.nick..": "..reply; end - if nick == room.nick then - room.bot:event("groupchat/joined", room); - else - room:event("occupant-joined", occupants[nick]); - end - elseif occupants[nick] and presence.stanza.attr.type == "unavailable" then - if nick == room.nick then - room.bot:event("groupchat/left", room); - self.rooms[room.jid] = nil; - else - occupants[nick].presence = presence.stanza; - room:event("occupant-left", occupants[nick]); - occupants[nick] = nil; - end + room:send(r:tag("body"):text(reply)); end - end); - self:send(st.presence({to = jid.."/"..nick}) - :tag("x",{xmlns = xmlns_muc}):tag("history",{maxstanzas = 0})); - self:event("groupchat/joining", room); + end, 500); return room; end -end -function room_mt:send(stanza) - if stanza.name == "message" and not stanza.attr.type then - stanza.attr.type = "groupchat"; - end - if stanza.attr.type == "groupchat" or not stanza.attr.to then - stanza.attr.to = self.jid; - end - self.bot:send(stanza); -end - -function room_mt:send_message(text) - self:send(st.message():tag("body"):text(text)); -end - -function room_mt:leave(message) - self.bot:event("groupchat/leaving", room); - self:send(st.presence({type="unavailable"})); + bot.stream:hook("pre-groupchat/joining", function(presence) + local muc_x = presence:get_child("x", xmlns_muc); + if muc_x then + muc_x:tag("history",{maxstanzas = 0}); + end + end); end - -function room_mt:set_role(nick, role, reason) - self:send(st.iq({type="set"}) - :query(xmlns_muc .. "#admin") - :tag("item", {nick = nick, role = role}) - :tag("reason"):text(reason or "")); -end - -function room_mt:set_affiliation(nick, affiliation, reason) - self:send(st.iq({type="set"}) - :query(xmlns_muc .. "#admin") - :tag("item", {nick = nick, affiliation = affiliation}) - :tag("reason"):text(reason or "")); -end - -function room_mt:event(name, arg) - self.bot.stream:debug("Firing room event: %s", name); - return self.events.fire_event(name, arg); -end - -function room_mt:hook(name, callback, priority) - return self.events.add_handler(name, callback, priority); -end