File

plugins/vcard_update.lua @ 498:50d0bd035bb7

util.sasl.oauthbearer: Don't send authzid It's not needed and not recommended in XMPP unless we want to act as someone other than who we authenticate as. We find out the JID during resource binding.
author Kim Alvefur <zash@zash.se>
date Fri, 23 Jun 2023 12:09:49 +0200
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