plugins/groupchat.lua

Thu, 18 Mar 2010 14:16:05 +0100

author
Thilo Cestonaro <thilo@cestona.ro>
date
Thu, 18 Mar 2010 14:16:05 +0100
changeset 9
8c3bec93087b
parent 0
7d84f4403d67
child 14
3df63aaba9e3
permissions
-rw-r--r--

groupchat.lua: make the occupant-left event work
tell.lua: double check the room and clear told tellings.

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] and presence.stanza.attr.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
			elseif occupants[nick] and presence.stanza.attr.type == "unavailable" then
				occupants[nick].presence = presence.stanza;
				room:event("occupant-left", occupants[nick]);
				occupants[nick] = nil;
			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

mercurial