Diff

plugins/muc/muc.lib.lua @ 1735:81406277279e

MUC: The MUC lib is now metatable based. Cleaned up code, etc.
author Waqas Hussain <waqas20@gmail.com>
date Mon, 07 Sep 2009 20:11:13 +0500
parent 1734:34ac9ba0aad6
child 1736:98f833669d7f
line wrap: on
line diff
--- a/plugins/muc/muc.lib.lua	Mon Sep 07 20:07:16 2009 +0500
+++ b/plugins/muc/muc.lib.lua	Mon Sep 07 20:11:13 2009 +0500
@@ -15,6 +15,7 @@
 local log = require "util.logger".init("mod_muc");
 local multitable_new = require "util.multitable".new;
 local t_insert, t_remove = table.insert, table.remove;
+local setmetatable = setmetatable;
 
 local muc_domain = nil; --module:get_host();
 local history_length = 20;
@@ -91,20 +92,22 @@
 
 --
 
-local function room_broadcast_presence(room, stanza, code, nick)
+local room_mt = {};
+
+local function room_mt:broadcast_presence(stanza, code, nick)
 	stanza = get_filtered_presence(stanza);
-	local data = room._participants[stanza.attr.from];
+	local data = self._participants[stanza.attr.from];
 	stanza:tag("x", {xmlns='http://jabber.org/protocol/muc#user'})
 		:tag("item", {affiliation=data.affiliation, role=data.role, nick=nick}):up();
 	if code then
 		stanza:tag("status", {code=code}):up();
 	end
 	local me;
-	for occupant, o_data in pairs(room._participants) do
+	for occupant, o_data in pairs(self._participants) do
 		if occupant ~= stanza.attr.from then
 			for jid in pairs(o_data.sessions) do
 				stanza.attr.to = jid;
-				room:route_stanza(stanza);
+				self:route_stanza(stanza);
 			end
 		else
 			me = o_data;
@@ -114,20 +117,20 @@
 		stanza:tag("status", {code='110'});
 		for jid in pairs(me.sessions) do
 			stanza.attr.to = jid;
-			room:route_stanza(stanza);
+			self:route_stanza(stanza);
 		end
 	end
 end
-local function room_broadcast_message(room, stanza, historic)
-	for occupant, o_data in pairs(room._participants) do
+local function room_mt:broadcast_message(stanza, historic)
+	for occupant, o_data in pairs(self._participants) do
 		for jid in pairs(o_data.sessions) do
 			stanza.attr.to = jid;
-			room:route_stanza(stanza);
+			self:route_stanza(stanza);
 		end
 	end
 	if historic then -- add to history
-		local history = room._data['history'];
-		if not history then history = {}; room._data['history'] = history; end
+		local history = self._data['history'];
+		if not history then history = {}; self._data['history'] = history; end
 		-- stanza = st.clone(stanza);
 		stanza:tag("delay", {xmlns = "urn:xmpp:delay", from = muc_domain, stamp = datetime.datetime()}):up(); -- XEP-0203
 		stanza:tag("x", {xmlns = "jabber:x:delay", from = muc_domain, stamp = datetime.legacy()}):up(); -- XEP-0091 (deprecated)
@@ -137,45 +140,45 @@
 end
 
 
-local function room_send_occupant_list(room, to)
-	local current_nick = room._jid_nick[to];
-	for occupant, o_data in pairs(room._participants) do
+function room_mt:send_occupant_list(to)
+	local current_nick = self._jid_nick[to];
+	for occupant, o_data in pairs(self._participants) do
 		if occupant ~= current_nick then
 			local pres = get_filtered_presence(o_data.sessions[o_data.jid]);
 			pres.attr.to, pres.attr.from = to, occupant;
 			pres:tag("x", {xmlns='http://jabber.org/protocol/muc#user'})
 				:tag("item", {affiliation=o_data.affiliation, role=o_data.role}):up();
-			room:route_stanza(pres);
+			self:route_stanza(pres);
 		end
 	end
 end
-local function room_send_history(room, to)
-	local history = room._data['history']; -- send discussion history
+function room_mt:send_history(to)
+	local history = self._data['history']; -- send discussion history
 	if history then
 		for _, msg in ipairs(history) do
 			msg = st.deserialize(msg);
 			msg.attr.to=to;
-			room:route_stanza(msg);
+			self:route_stanza(msg);
 		end
 	end
-	if room._data['subject'] then
-		room:route_stanza(st.message({type='groupchat', from=room.jid, to=to}):tag("subject"):text(room._data['subject']));
+	if self._data['subject'] then
+		self:route_stanza(st.message({type='groupchat', from=self.jid, to=to}):tag("subject"):text(self._data['subject']));
 	end
 end
 
 local function room_get_disco_info(self, stanza) end
 local function room_get_disco_items(self, stanza) end
-local function room_set_subject(room, current_nick, subject)
+function room_mt:set_subject(current_nick, subject)
 	-- TODO check nick's authority
 	if subject == "" then subject = nil; end
-	room._data['subject'] = subject;
+	self._data['subject'] = subject;
 	local msg = st.message({type='groupchat', from=current_nick})
 		:tag('subject'):text(subject):up();
-	room_broadcast_message(room, msg, false);
+	self:broadcast_message(msg, false);
 	return true;
 end
 
-local function room_handle_to_occupant(self, origin, stanza) -- PM, vCards, etc
+function room_mt:handle_to_occupant(origin, stanza) -- PM, vCards, etc
 	local from, to = stanza.attr.from, stanza.attr.to;
 	local room = jid_bare(to);
 	local current_nick = self._jid_nick[from];
@@ -188,14 +191,15 @@
 		if type == "error" then -- error, kick em out!
 			if current_nick then
 				log("debug", "kicking %s from %s", current_nick, room);
-				room_handle_to_occupant(self, origin, st.presence({type='unavailable', from=from, to=to}):tag('status'):text('This participant is kicked from the room because he sent an error presence')); -- send unavailable
+				self:handle_to_occupant(origin, st.presence({type='unavailable', from=from, to=to})
+					:tag('status'):text('This participant is kicked from the room because he sent an error presence')); -- send unavailable
 			end
 		elseif type == "unavailable" then -- unavailable
 			if current_nick then
 				log("debug", "%s leaving %s", current_nick, room);
 				local data = self._participants[current_nick];
 				data.role = 'none';
-				room_broadcast_presence(self, pr);
+				self:broadcast_presence(pr);
 				self._participants[current_nick] = nil;
 				self._jid_nick[from] = nil;
 			end
@@ -205,7 +209,7 @@
 					if current_nick == to then -- simple presence
 						log("debug", "%s broadcasted presence", current_nick);
 						self._participants[current_nick].sessions[from] = pr;
-						room_broadcast_presence(self, pr);
+						self:broadcast_presence(pr);
 					else -- change nick
 						if self._participants[to] then
 							log("debug", "%s couldn't change nick", current_nick);
@@ -216,13 +220,13 @@
 							if to_nick then
 								log("debug", "%s (%s) changing nick to %s", current_nick, data.jid, to);
 								local p = st.presence({type='unavailable', from=current_nick});
-								room_broadcast_presence(self, p, '303', to_nick);
+								self:broadcast_presence(p, '303', to_nick);
 								self._participants[current_nick] = nil;
 								self._participants[to] = data;
 								self._jid_nick[from] = to;
 								pr.attr.from = to;
 								self._participants[to].sessions[from] = pr;
-								room_broadcast_presence(self, pr);
+								self:broadcast_presence(pr);
 							else
 								--TODO malformed-jid
 							end
@@ -230,8 +234,9 @@
 					end
 				--else -- possible rejoin
 				--	log("debug", "%s had connection replaced", current_nick);
-				--	handle_to_occupant(origin, st.presence({type='unavailable', from=from, to=to}):tag('status'):text('Replaced by new connection'):up()); -- send unavailable
-				--	handle_to_occupant(origin, stanza); -- resend available
+				--	self:handle_to_occupant(origin, st.presence({type='unavailable', from=from, to=to})
+				--		:tag('status'):text('Replaced by new connection'):up()); -- send unavailable
+				--	self:handle_to_occupant(origin, stanza); -- resend available
 				--end
 			else -- enter room
 				local new_nick = to;
@@ -253,10 +258,10 @@
 					end
 					self._participants[to] = data;
 					self._jid_nick[from] = to;
-					room_send_occupant_list(self, from);
+					self:send_occupant_list(from);
 					pr.attr.from = to;
-					room_broadcast_presence(self, pr);
-					room_send_history(self, from);
+					self:broadcast_presence(pr);
+					self:send_history(from);
 				end
 			end
 		elseif type ~= 'result' then -- bad type
@@ -268,7 +273,7 @@
 		origin.send(st.error_reply(stanza, "modify", "bad-request"));
 	elseif stanza.name == "message" and type == "error" and get_kickable_error(stanza) then
 		log("debug", "%s kicked from %s for sending an error message", current_nick, room);
-		room_handle_to_occupant(self, origin, st.presence({type='unavailable', from=from, to=to}):tag('status'):text('This participant is kicked from the room because he sent an error message to another occupant')); -- send unavailable
+		self:handle_to_occupant(origin, st.presence({type='unavailable', from=from, to=to}):tag('status'):text('This participant is kicked from the room because he sent an error message to another occupant')); -- send unavailable
 	else -- private stanza
 		local o_data = self._participants[to];
 		if o_data then
@@ -283,7 +288,7 @@
 	end
 end
 
-local function room_handle_to_room(self, origin, stanza) -- presence changes and groupchat messages, along with disco/etc
+function room_mt:handle_to_room(origin, stanza) -- presence changes and groupchat messages, along with disco/etc
 	local type = stanza.attr.type;
 	if stanza.name == "iq" and type == "get" then -- disco requests
 		local xmlns = stanza.tags[1].attr.xmlns;
@@ -307,7 +312,7 @@
 			if subject then
 				self:set_subject(current_nick, subject); -- TODO use broadcast_message_stanza
 			else
-				room_broadcast_message(self, stanza, true);
+				self:broadcast_message(stanza, true);
 			end
 		end
 	elseif stanza.name == "presence" then -- hack - some buggy clients send presence updates to the room rather than their nick
@@ -315,7 +320,7 @@
 		local current_nick = self._jid_nick[stanza.attr.from];
 		if current_nick then
 			stanza.attr.to = current_nick;
-			room_handle_to_occupant(self, origin, stanza);
+			self:handle_to_occupant(origin, stanza);
 			stanza.attr.to = to;
 		elseif type ~= "error" and type ~= "result" then
 			origin.send(st.error_reply(stanza, "cancel", "service-unavailable"));
@@ -336,27 +341,26 @@
 	end
 end
 
-local function room_handle_stanza(self, origin, stanza)
+function room_mt:handle_stanza(origin, stanza)
 	local to_node, to_host, to_resource = jid_split(stanza.attr.to);
 	if to_resource then
-		room_handle_to_occupant(self, origin, stanza);
+		self:handle_to_occupant(origin, stanza);
 	else
-		room_handle_to_room(self, origin, stanza);
+		self:handle_to_room(origin, stanza);
 	end
 end
 
+function room_mt:route_stanza(stanza) end -- Replace with a routing function, e.g., function(room, stanza) core_route_stanza(origin, stanza); end
+
 module "muc"
 
 function new_room(jid)
-	return {
+	return setmetatable({
 		jid = jid;
-		handle_stanza = room_handle_stanza;
-		set_subject = room_set_subject;
-		route_stanza = function(room, stanza) end; -- Replace with a routing function, e.g., function(room, stanza) core_route_stanza(origin, stanza); end
 		_jid_nick = {};
 		_participants = {};
 		_data = {};
-	}
+	}, room_mt);
 end
 
 return _M;