File

plugins/vcard_update.lua @ 494:04c216ac429a

configure: fix --lua-lib-dir
author Trần H. Trung <xmpp:trần.h.trung@trung.fun>
date Fri, 07 Jul 2023 17:23:09 +0700
parent 490:6b2f31da9610
line wrap: on
line source

local verse = require "verse";

-- local xmlns_vcard = "vcard-temp";
local xmlns_vcard_update = "vcard-temp:x:update";

local sha1 = require("prosody.util.hashes").sha1;

local ok, fun = pcall(function()
	local unb64 = require("prosody.util.encodings").base64.decode;
	assert(unb64("SGVsbG8=") == "Hello")
	return unb64;
end);
if not ok then
	ok, fun = pcall(function() return require("mime").unb64; end);
	if not ok then
		error("Could not find a base64 decoder")
	end
end
local unb64 = fun;

function verse.plugins.vcard_update(stream)
	stream:add_plugin("vcard");
	stream:add_plugin("presence");


	local x_vcard_update;

	local function update_vcard_photo(vCard)
		local data;
		for i=1,#vCard do
			if vCard[i].name == "PHOTO" then
				data = vCard[i][1];
				break
			end
		end
		if data then
			local hash = sha1(unb64(data), true);
			x_vcard_update = verse.stanza("x", { xmlns = xmlns_vcard_update })
			:tag("photo"):text(hash);

			stream:resend_presence()
		else
			x_vcard_update = nil;
		end
	end


	--[[ TODO Complete this, it's probably broken.
	-- Maybe better to hook outgoing stanza?
	local _set_vcard = stream.set_vcard;
	function stream:set_vcard(vCard, callback)
		_set_vcard(vCard, function(event, ...)
			if event.attr.type == "result" then
				local vCard_ = response:get_child("vCard", xmlns_vcard);
				if vCard_ then
					update_vcard_photo(vCard_);
				end -- Or fetch it again? Seems wasteful, but if the server overrides stuff? :/
			end
			if callback then
				return callback(event, ...);
			end
		end);
	end
	--]]

	local initial_vcard_fetch_started;
	stream:hook("ready", function()
		if initial_vcard_fetch_started then return; end
		initial_vcard_fetch_started = true;
		-- if stream:jid_supports(nil, xmlns_vcard) then TODO this, correctly
		stream:get_vcard(nil, function(response)
			if response then
				update_vcard_photo(response)
			end
			stream:event("ready");
		end);
		return true;
	end, 3);

	stream:hook("presence-out", function(presence)
		if x_vcard_update and not presence:get_child("x", xmlns_vcard_update) then
			presence:add_child(x_vcard_update);
		end
	end, 10);

	--[[
	stream:hook("presence", function(presence)
			local x_vcard_update = presence:get_child("x", xmlns_vcard_update);
			local photo_hash = x_vcard_update and x_vcard_update:get_child("photo");
				:get_child_text("photo");
			if x_vcard_update then
				-- TODO Cache peoples avatars here
			end
	end);
	--]]
end