plugins.groupchat: Update to use groupchat code in Verse

Tue, 11 Jan 2011 23:19:51 +0100

author
Kim Alvefur <zash@zash.se>
date
Tue, 11 Jan 2011 23:19:51 +0100
changeset 56
cb7656ee4dd8
parent 55
3a321510707c
child 57
766f4225110b

plugins.groupchat: Update to use groupchat code in Verse

plugins/groupchat.lua file | annotate | diff | comparison | revisions
--- 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

mercurial