diff -r 000000000000 -r 7d84f4403d67 plugins/groupchat.lua --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/plugins/groupchat.lua Mon Dec 21 19:27:08 2009 +0000 @@ -0,0 +1,115 @@ +local events = require "events"; +local st = require "util.stanza"; + +local room_mt = {}; +room_mt.__index = room_mt; + +local xmlns_delay = "urn:xmpp:delay"; + +function riddim.plugins.groupchat(bot) + bot.rooms = {}; + + 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) + 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; + if not occupants[nick] then + if presence.type ~= "unavailable" then + occupants[nick] = { + nick = nick; + jid = presence.stanza.attr.from; + presence = presence.stanza; + }; + if nick == room.nick then + room.bot:event("groupchat/joined", room); + else + room:event("occupant-joined", occupants[nick]); + end + else + occupants[nick].presence = presence.stanza; + room:event("occupant-left", occupants[nick]); + occupants[nick] = nil; + end + end + end); + self:send(st.presence({to = jid.."/"..nick})); + self:event("groupchat/joining", room); + 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" 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"})); + self.bot:event("groupchat/left", room); +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