diff mod_vcard_muc/mod_vcard_muc.lua @ 3043:6cc44e69443a

mod_vcard_muc: Initial commit
author Michel Le Bihan <michel@lebihan.pl>
date Thu, 24 May 2018 20:27:48 +0200
parents
children d0db28768980
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mod_vcard_muc/mod_vcard_muc.lua	Thu May 24 20:27:48 2018 +0200
@@ -0,0 +1,91 @@
+-- Prosody IM
+-- Copyright (C) 2008-2010 Matthew Wild
+-- Copyright (C) 2008-2010 Waqas Hussain
+-- Copyright (C) 2018 Michel Le Bihan
+--
+-- This project is MIT/X11 licensed. Please see the
+-- COPYING file in the source package for more information.
+--
+
+local st = require "util.stanza"
+local jid_split = require "util.jid".split;
+local base64 = require"util.encodings".base64;
+local sha1 = require"util.hashes".sha1;
+
+local mod_muc = module:depends"muc";
+local get_room_from_jid = mod_muc.get_room_from_jid;
+
+local vcards = module:open_store();
+
+module:add_feature("vcard-temp");
+
+local function broadcast_presence(room_jid, to)
+	local room = get_room_from_jid(room_jid);
+	local room_node = jid_split(room_jid);
+	local vcard = st.deserialize(vcards:get(room_node));
+	local photo_hash;
+
+	if vcard then
+		local photo = vcard:get_child("PHOTO");
+
+		if photo then
+			local photo_b64 = photo:get_child_text("BINVAL");
+			local photo_raw = photo_b64 and base64.decode(photo_b64);
+			photo_hash = sha1(photo_raw, true);
+		end
+	end
+
+	local presence_vcard = st.presence({to = to, from = room_jid})
+		:tag("x", { xmlns = "vcard-temp:x:update" })
+			:tag("photo"):text(photo_hash):up();
+
+	if to == nil then
+		room:broadcast_message(presence_vcard);
+	else
+		module:send(presence_vcard);
+	end
+end
+
+local function handle_vcard(event)
+	local session, stanza = event.origin, event.stanza;
+
+	local room_jid = stanza.attr.to;
+	local room_node = jid_split(room_jid);
+	local room = get_room_from_jid(room_jid);
+
+	local from = stanza.attr.from;
+	local from_affiliation = room:get_affiliation(from);
+
+	if stanza.attr.type == "get" then
+		local vCard;
+		vCard = st.deserialize(vcards:get(room_node));
+
+		if vCard then
+			session.send(st.reply(stanza):add_child(vCard)); -- send vCard!
+		else
+			session.send(st.error_reply(stanza, "cancel", "item-not-found"));
+		end
+	else
+		if from_affiliation == "owner" then
+			if vcards:set(room_node, st.preserialize(stanza.tags[1])) then
+				session.send(st.reply(stanza):tag("vCard", { xmlns = "vcard-temp" }));
+				broadcast_presence(room_jid, nil)
+			else
+				-- TODO unable to write file, file may be locked, etc, what's the correct error?
+				session.send(st.error_reply(stanza, "wait", "internal-server-error"));
+			end
+		else
+			session.send(st.error_reply(stanza, "auth", "forbidden"));
+		end
+	end
+	return true;
+end
+
+
+module:hook("iq/bare/vcard-temp:vCard", handle_vcard);
+module:hook("iq/host/vcard-temp:vCard", handle_vcard);
+
+module:hook("muc-disco#info", function(event)
+	event.reply:tag("feature", { var = "vcard-temp" }):up();
+	broadcast_presence(event.room.jid, event.reply.attr.to);
+end);