plugins/vcard_update.lua

1
local verse = require "verse";
2
 
3
-- local xmlns_vcard = "vcard-temp";
4
local xmlns_vcard_update = "vcard-temp:x:update";
5
 
6
local sha1 = require("prosody.util.hashes").sha1;
7
 
8
local ok, fun = pcall(function()
9
	local unb64 = require("prosody.util.encodings").base64.decode;
10
	assert(unb64("SGVsbG8=") == "Hello")
11
	return unb64;
12
end);
13
if not ok then
14
	ok, fun = pcall(function() return require("mime").unb64; end);
15
	if not ok then
16
		error("Could not find a base64 decoder")
17
	end
18
end
19
local unb64 = fun;
20
 
21
function verse.plugins.vcard_update(stream)
22
	stream:add_plugin("vcard");
23
	stream:add_plugin("presence");
24
 
25
 
26
	local x_vcard_update;
27
 
28
	local function update_vcard_photo(vCard)
29
		local data;
30
		for i=1,#vCard do
31
			if vCard[i].name == "PHOTO" then
32
				data = vCard[i][1];
33
				break
34
			end
35
		end
36
		if data then
37
			local hash = sha1(unb64(data), true);
38
			x_vcard_update = verse.stanza("x", { xmlns = xmlns_vcard_update })
39
			:tag("photo"):text(hash);
40
 
41
			stream:resend_presence()
42
		else
43
			x_vcard_update = nil;
44
		end
45
	end
46
 
47
 
48
	--[[ TODO Complete this, it's probably broken.
49
	-- Maybe better to hook outgoing stanza?
50
	local _set_vcard = stream.set_vcard;
51
	function stream:set_vcard(vCard, callback)
52
		_set_vcard(vCard, function(event, ...)
53
			if event.attr.type == "result" then
54
				local vCard_ = response:get_child("vCard", xmlns_vcard);
55
				if vCard_ then
56
					update_vcard_photo(vCard_);
57
				end -- Or fetch it again? Seems wasteful, but if the server overrides stuff? :/
58
			end
59
			if callback then
60
				return callback(event, ...);
61
			end
62
		end);
63
	end
64
	--]]
65
 
66
	local initial_vcard_fetch_started;
67
	stream:hook("ready", function()
68
		if initial_vcard_fetch_started then return; end
69
		initial_vcard_fetch_started = true;
70
		-- if stream:jid_supports(nil, xmlns_vcard) then TODO this, correctly
71
		stream:get_vcard(nil, function(response)
72
			if response then
73
				update_vcard_photo(response)
74
			end
75
			stream:event("ready");
76
		end);
77
		return true;
78
	end, 3);
79
 
80
	stream:hook("presence-out", function(presence)
81
		if x_vcard_update and not presence:get_child("x", xmlns_vcard_update) then
82
			presence:add_child(x_vcard_update);
83
		end
84
	end, 10);
85
 
86
	--[[
87
	stream:hook("presence", function(presence)
88
			local x_vcard_update = presence:get_child("x", xmlns_vcard_update);
89
			local photo_hash = x_vcard_update and x_vcard_update:get_child("photo");
90
				:get_child_text("photo");
91
			if x_vcard_update then
92
				-- TODO Cache peoples avatars here
93
			end
94
	end);
95
	--]]
96
end