annotate mod_vcard_muc/mod_vcard_muc.lua @ 3656:3e0f4d727825

mod_vcard_muc: Add an alternative method of signaling avatar change When the avatar has been changed, a signal is sent that the room configuration has changed. Clients then do a disco#info query to find the SHA-1 of the new avatar. They can then fetch it as before, or not if they have it cached already. This is meant to be less disruptive than signaling via presence, which caused problems for some clients. If clients transition to the new method, the old one can eventually be removed. The namespace is made up while waiting for standardization. Otherwise it is very close to what's described in https://xmpp.org/extensions/inbox/muc-avatars.html
author Kim Alvefur <zash@zash.se>
date Sun, 25 Aug 2019 20:46:43 +0200
parents d7b589dec591
children a533abe6ffd0
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
3043
6cc44e69443a mod_vcard_muc: Initial commit
Michel Le Bihan <michel@lebihan.pl>
parents:
diff changeset
1 -- Prosody IM
6cc44e69443a mod_vcard_muc: Initial commit
Michel Le Bihan <michel@lebihan.pl>
parents:
diff changeset
2 -- Copyright (C) 2008-2010 Matthew Wild
6cc44e69443a mod_vcard_muc: Initial commit
Michel Le Bihan <michel@lebihan.pl>
parents:
diff changeset
3 -- Copyright (C) 2008-2010 Waqas Hussain
6cc44e69443a mod_vcard_muc: Initial commit
Michel Le Bihan <michel@lebihan.pl>
parents:
diff changeset
4 -- Copyright (C) 2018 Michel Le Bihan
6cc44e69443a mod_vcard_muc: Initial commit
Michel Le Bihan <michel@lebihan.pl>
parents:
diff changeset
5 --
6cc44e69443a mod_vcard_muc: Initial commit
Michel Le Bihan <michel@lebihan.pl>
parents:
diff changeset
6 -- This project is MIT/X11 licensed. Please see the
6cc44e69443a mod_vcard_muc: Initial commit
Michel Le Bihan <michel@lebihan.pl>
parents:
diff changeset
7 -- COPYING file in the source package for more information.
6cc44e69443a mod_vcard_muc: Initial commit
Michel Le Bihan <michel@lebihan.pl>
parents:
diff changeset
8 --
6cc44e69443a mod_vcard_muc: Initial commit
Michel Le Bihan <michel@lebihan.pl>
parents:
diff changeset
9
6cc44e69443a mod_vcard_muc: Initial commit
Michel Le Bihan <michel@lebihan.pl>
parents:
diff changeset
10 local st = require "util.stanza"
6cc44e69443a mod_vcard_muc: Initial commit
Michel Le Bihan <michel@lebihan.pl>
parents:
diff changeset
11 local jid_split = require "util.jid".split;
6cc44e69443a mod_vcard_muc: Initial commit
Michel Le Bihan <michel@lebihan.pl>
parents:
diff changeset
12 local base64 = require"util.encodings".base64;
6cc44e69443a mod_vcard_muc: Initial commit
Michel Le Bihan <michel@lebihan.pl>
parents:
diff changeset
13 local sha1 = require"util.hashes".sha1;
6cc44e69443a mod_vcard_muc: Initial commit
Michel Le Bihan <michel@lebihan.pl>
parents:
diff changeset
14
6cc44e69443a mod_vcard_muc: Initial commit
Michel Le Bihan <michel@lebihan.pl>
parents:
diff changeset
15 local mod_muc = module:depends"muc";
6cc44e69443a mod_vcard_muc: Initial commit
Michel Le Bihan <michel@lebihan.pl>
parents:
diff changeset
16
6cc44e69443a mod_vcard_muc: Initial commit
Michel Le Bihan <michel@lebihan.pl>
parents:
diff changeset
17 local vcards = module:open_store();
6cc44e69443a mod_vcard_muc: Initial commit
Michel Le Bihan <michel@lebihan.pl>
parents:
diff changeset
18
6cc44e69443a mod_vcard_muc: Initial commit
Michel Le Bihan <michel@lebihan.pl>
parents:
diff changeset
19 module:add_feature("vcard-temp");
6cc44e69443a mod_vcard_muc: Initial commit
Michel Le Bihan <michel@lebihan.pl>
parents:
diff changeset
20
3077
f16b021e8a61 mod_vcard_muc: Get room from rooms table when get_room_from_jid API is not supported
Michel Le Bihan <michel@lebihan.pl>
parents: 3046
diff changeset
21 local get_room_from_jid = rawget(mod_muc, "get_room_from_jid") or
f16b021e8a61 mod_vcard_muc: Get room from rooms table when get_room_from_jid API is not supported
Michel Le Bihan <michel@lebihan.pl>
parents: 3046
diff changeset
22 function (jid)
f16b021e8a61 mod_vcard_muc: Get room from rooms table when get_room_from_jid API is not supported
Michel Le Bihan <michel@lebihan.pl>
parents: 3046
diff changeset
23 local rooms = rawget(mod_muc, "rooms");
f16b021e8a61 mod_vcard_muc: Get room from rooms table when get_room_from_jid API is not supported
Michel Le Bihan <michel@lebihan.pl>
parents: 3046
diff changeset
24 return rooms[jid];
f16b021e8a61 mod_vcard_muc: Get room from rooms table when get_room_from_jid API is not supported
Michel Le Bihan <michel@lebihan.pl>
parents: 3046
diff changeset
25 end
f16b021e8a61 mod_vcard_muc: Get room from rooms table when get_room_from_jid API is not supported
Michel Le Bihan <michel@lebihan.pl>
parents: 3046
diff changeset
26
3655
d7b589dec591 mod_vcard_muc: Factor out avatar hash retrieval into a function for easier reuse
Kim Alvefur <zash@zash.se>
parents: 3077
diff changeset
27 local function get_photo_hash(room)
d7b589dec591 mod_vcard_muc: Factor out avatar hash retrieval into a function for easier reuse
Kim Alvefur <zash@zash.se>
parents: 3077
diff changeset
28 local room_node = jid_split(room.jid);
3043
6cc44e69443a mod_vcard_muc: Initial commit
Michel Le Bihan <michel@lebihan.pl>
parents:
diff changeset
29 local vcard = st.deserialize(vcards:get(room_node));
6cc44e69443a mod_vcard_muc: Initial commit
Michel Le Bihan <michel@lebihan.pl>
parents:
diff changeset
30 if vcard then
6cc44e69443a mod_vcard_muc: Initial commit
Michel Le Bihan <michel@lebihan.pl>
parents:
diff changeset
31 local photo = vcard:get_child("PHOTO");
6cc44e69443a mod_vcard_muc: Initial commit
Michel Le Bihan <michel@lebihan.pl>
parents:
diff changeset
32
6cc44e69443a mod_vcard_muc: Initial commit
Michel Le Bihan <michel@lebihan.pl>
parents:
diff changeset
33 if photo then
6cc44e69443a mod_vcard_muc: Initial commit
Michel Le Bihan <michel@lebihan.pl>
parents:
diff changeset
34 local photo_b64 = photo:get_child_text("BINVAL");
6cc44e69443a mod_vcard_muc: Initial commit
Michel Le Bihan <michel@lebihan.pl>
parents:
diff changeset
35 local photo_raw = photo_b64 and base64.decode(photo_b64);
3655
d7b589dec591 mod_vcard_muc: Factor out avatar hash retrieval into a function for easier reuse
Kim Alvefur <zash@zash.se>
parents: 3077
diff changeset
36 return sha1(photo_raw, true);
3043
6cc44e69443a mod_vcard_muc: Initial commit
Michel Le Bihan <michel@lebihan.pl>
parents:
diff changeset
37 end
6cc44e69443a mod_vcard_muc: Initial commit
Michel Le Bihan <michel@lebihan.pl>
parents:
diff changeset
38 end
6cc44e69443a mod_vcard_muc: Initial commit
Michel Le Bihan <michel@lebihan.pl>
parents:
diff changeset
39
3655
d7b589dec591 mod_vcard_muc: Factor out avatar hash retrieval into a function for easier reuse
Kim Alvefur <zash@zash.se>
parents: 3077
diff changeset
40 end
d7b589dec591 mod_vcard_muc: Factor out avatar hash retrieval into a function for easier reuse
Kim Alvefur <zash@zash.se>
parents: 3077
diff changeset
41
d7b589dec591 mod_vcard_muc: Factor out avatar hash retrieval into a function for easier reuse
Kim Alvefur <zash@zash.se>
parents: 3077
diff changeset
42 local function broadcast_presence(room_jid, to)
d7b589dec591 mod_vcard_muc: Factor out avatar hash retrieval into a function for easier reuse
Kim Alvefur <zash@zash.se>
parents: 3077
diff changeset
43 local room = get_room_from_jid(room_jid);
d7b589dec591 mod_vcard_muc: Factor out avatar hash retrieval into a function for easier reuse
Kim Alvefur <zash@zash.se>
parents: 3077
diff changeset
44
3656
3e0f4d727825 mod_vcard_muc: Add an alternative method of signaling avatar change
Kim Alvefur <zash@zash.se>
parents: 3655
diff changeset
45 local photo_hash = get_photo_hash(room);
3043
6cc44e69443a mod_vcard_muc: Initial commit
Michel Le Bihan <michel@lebihan.pl>
parents:
diff changeset
46 local presence_vcard = st.presence({to = to, from = room_jid})
6cc44e69443a mod_vcard_muc: Initial commit
Michel Le Bihan <michel@lebihan.pl>
parents:
diff changeset
47 :tag("x", { xmlns = "vcard-temp:x:update" })
6cc44e69443a mod_vcard_muc: Initial commit
Michel Le Bihan <michel@lebihan.pl>
parents:
diff changeset
48 :tag("photo"):text(photo_hash):up();
6cc44e69443a mod_vcard_muc: Initial commit
Michel Le Bihan <michel@lebihan.pl>
parents:
diff changeset
49
6cc44e69443a mod_vcard_muc: Initial commit
Michel Le Bihan <michel@lebihan.pl>
parents:
diff changeset
50 if to == nil then
6cc44e69443a mod_vcard_muc: Initial commit
Michel Le Bihan <michel@lebihan.pl>
parents:
diff changeset
51 room:broadcast_message(presence_vcard);
6cc44e69443a mod_vcard_muc: Initial commit
Michel Le Bihan <michel@lebihan.pl>
parents:
diff changeset
52 else
6cc44e69443a mod_vcard_muc: Initial commit
Michel Le Bihan <michel@lebihan.pl>
parents:
diff changeset
53 module:send(presence_vcard);
6cc44e69443a mod_vcard_muc: Initial commit
Michel Le Bihan <michel@lebihan.pl>
parents:
diff changeset
54 end
6cc44e69443a mod_vcard_muc: Initial commit
Michel Le Bihan <michel@lebihan.pl>
parents:
diff changeset
55 end
6cc44e69443a mod_vcard_muc: Initial commit
Michel Le Bihan <michel@lebihan.pl>
parents:
diff changeset
56
6cc44e69443a mod_vcard_muc: Initial commit
Michel Le Bihan <michel@lebihan.pl>
parents:
diff changeset
57 local function handle_vcard(event)
6cc44e69443a mod_vcard_muc: Initial commit
Michel Le Bihan <michel@lebihan.pl>
parents:
diff changeset
58 local session, stanza = event.origin, event.stanza;
6cc44e69443a mod_vcard_muc: Initial commit
Michel Le Bihan <michel@lebihan.pl>
parents:
diff changeset
59
6cc44e69443a mod_vcard_muc: Initial commit
Michel Le Bihan <michel@lebihan.pl>
parents:
diff changeset
60 local room_jid = stanza.attr.to;
6cc44e69443a mod_vcard_muc: Initial commit
Michel Le Bihan <michel@lebihan.pl>
parents:
diff changeset
61 local room_node = jid_split(room_jid);
6cc44e69443a mod_vcard_muc: Initial commit
Michel Le Bihan <michel@lebihan.pl>
parents:
diff changeset
62 local room = get_room_from_jid(room_jid);
6cc44e69443a mod_vcard_muc: Initial commit
Michel Le Bihan <michel@lebihan.pl>
parents:
diff changeset
63
6cc44e69443a mod_vcard_muc: Initial commit
Michel Le Bihan <michel@lebihan.pl>
parents:
diff changeset
64 local from = stanza.attr.from;
6cc44e69443a mod_vcard_muc: Initial commit
Michel Le Bihan <michel@lebihan.pl>
parents:
diff changeset
65 local from_affiliation = room:get_affiliation(from);
6cc44e69443a mod_vcard_muc: Initial commit
Michel Le Bihan <michel@lebihan.pl>
parents:
diff changeset
66
6cc44e69443a mod_vcard_muc: Initial commit
Michel Le Bihan <michel@lebihan.pl>
parents:
diff changeset
67 if stanza.attr.type == "get" then
6cc44e69443a mod_vcard_muc: Initial commit
Michel Le Bihan <michel@lebihan.pl>
parents:
diff changeset
68 local vCard;
6cc44e69443a mod_vcard_muc: Initial commit
Michel Le Bihan <michel@lebihan.pl>
parents:
diff changeset
69 vCard = st.deserialize(vcards:get(room_node));
6cc44e69443a mod_vcard_muc: Initial commit
Michel Le Bihan <michel@lebihan.pl>
parents:
diff changeset
70
6cc44e69443a mod_vcard_muc: Initial commit
Michel Le Bihan <michel@lebihan.pl>
parents:
diff changeset
71 if vCard then
6cc44e69443a mod_vcard_muc: Initial commit
Michel Le Bihan <michel@lebihan.pl>
parents:
diff changeset
72 session.send(st.reply(stanza):add_child(vCard)); -- send vCard!
6cc44e69443a mod_vcard_muc: Initial commit
Michel Le Bihan <michel@lebihan.pl>
parents:
diff changeset
73 else
6cc44e69443a mod_vcard_muc: Initial commit
Michel Le Bihan <michel@lebihan.pl>
parents:
diff changeset
74 session.send(st.error_reply(stanza, "cancel", "item-not-found"));
6cc44e69443a mod_vcard_muc: Initial commit
Michel Le Bihan <michel@lebihan.pl>
parents:
diff changeset
75 end
6cc44e69443a mod_vcard_muc: Initial commit
Michel Le Bihan <michel@lebihan.pl>
parents:
diff changeset
76 else
6cc44e69443a mod_vcard_muc: Initial commit
Michel Le Bihan <michel@lebihan.pl>
parents:
diff changeset
77 if from_affiliation == "owner" then
6cc44e69443a mod_vcard_muc: Initial commit
Michel Le Bihan <michel@lebihan.pl>
parents:
diff changeset
78 if vcards:set(room_node, st.preserialize(stanza.tags[1])) then
6cc44e69443a mod_vcard_muc: Initial commit
Michel Le Bihan <michel@lebihan.pl>
parents:
diff changeset
79 session.send(st.reply(stanza):tag("vCard", { xmlns = "vcard-temp" }));
6cc44e69443a mod_vcard_muc: Initial commit
Michel Le Bihan <michel@lebihan.pl>
parents:
diff changeset
80 broadcast_presence(room_jid, nil)
3656
3e0f4d727825 mod_vcard_muc: Add an alternative method of signaling avatar change
Kim Alvefur <zash@zash.se>
parents: 3655
diff changeset
81
3e0f4d727825 mod_vcard_muc: Add an alternative method of signaling avatar change
Kim Alvefur <zash@zash.se>
parents: 3655
diff changeset
82 room:broadcast_message(st.message({ from = room.jid, type = "groupchat" })
3e0f4d727825 mod_vcard_muc: Add an alternative method of signaling avatar change
Kim Alvefur <zash@zash.se>
parents: 3655
diff changeset
83 :tag("x", { xmlns = "http://jabber.org/protocol/muc#user" })
3e0f4d727825 mod_vcard_muc: Add an alternative method of signaling avatar change
Kim Alvefur <zash@zash.se>
parents: 3655
diff changeset
84 :tag("status", { code = "104" }));
3043
6cc44e69443a mod_vcard_muc: Initial commit
Michel Le Bihan <michel@lebihan.pl>
parents:
diff changeset
85 else
6cc44e69443a mod_vcard_muc: Initial commit
Michel Le Bihan <michel@lebihan.pl>
parents:
diff changeset
86 -- TODO unable to write file, file may be locked, etc, what's the correct error?
6cc44e69443a mod_vcard_muc: Initial commit
Michel Le Bihan <michel@lebihan.pl>
parents:
diff changeset
87 session.send(st.error_reply(stanza, "wait", "internal-server-error"));
6cc44e69443a mod_vcard_muc: Initial commit
Michel Le Bihan <michel@lebihan.pl>
parents:
diff changeset
88 end
6cc44e69443a mod_vcard_muc: Initial commit
Michel Le Bihan <michel@lebihan.pl>
parents:
diff changeset
89 else
6cc44e69443a mod_vcard_muc: Initial commit
Michel Le Bihan <michel@lebihan.pl>
parents:
diff changeset
90 session.send(st.error_reply(stanza, "auth", "forbidden"));
6cc44e69443a mod_vcard_muc: Initial commit
Michel Le Bihan <michel@lebihan.pl>
parents:
diff changeset
91 end
6cc44e69443a mod_vcard_muc: Initial commit
Michel Le Bihan <michel@lebihan.pl>
parents:
diff changeset
92 end
6cc44e69443a mod_vcard_muc: Initial commit
Michel Le Bihan <michel@lebihan.pl>
parents:
diff changeset
93 return true;
6cc44e69443a mod_vcard_muc: Initial commit
Michel Le Bihan <michel@lebihan.pl>
parents:
diff changeset
94 end
6cc44e69443a mod_vcard_muc: Initial commit
Michel Le Bihan <michel@lebihan.pl>
parents:
diff changeset
95
6cc44e69443a mod_vcard_muc: Initial commit
Michel Le Bihan <michel@lebihan.pl>
parents:
diff changeset
96
6cc44e69443a mod_vcard_muc: Initial commit
Michel Le Bihan <michel@lebihan.pl>
parents:
diff changeset
97 module:hook("iq/bare/vcard-temp:vCard", handle_vcard);
6cc44e69443a mod_vcard_muc: Initial commit
Michel Le Bihan <michel@lebihan.pl>
parents:
diff changeset
98 module:hook("iq/host/vcard-temp:vCard", handle_vcard);
6cc44e69443a mod_vcard_muc: Initial commit
Michel Le Bihan <michel@lebihan.pl>
parents:
diff changeset
99
6cc44e69443a mod_vcard_muc: Initial commit
Michel Le Bihan <michel@lebihan.pl>
parents:
diff changeset
100 module:hook("muc-disco#info", function(event)
6cc44e69443a mod_vcard_muc: Initial commit
Michel Le Bihan <michel@lebihan.pl>
parents:
diff changeset
101 event.reply:tag("feature", { var = "vcard-temp" }):up();
3656
3e0f4d727825 mod_vcard_muc: Add an alternative method of signaling avatar change
Kim Alvefur <zash@zash.se>
parents: 3655
diff changeset
102
3e0f4d727825 mod_vcard_muc: Add an alternative method of signaling avatar change
Kim Alvefur <zash@zash.se>
parents: 3655
diff changeset
103 table.insert(event.form, {
3e0f4d727825 mod_vcard_muc: Add an alternative method of signaling avatar change
Kim Alvefur <zash@zash.se>
parents: 3655
diff changeset
104 name = "{http://modules.prosody.im/mod_vcard_muc}avatar#sha1",
3e0f4d727825 mod_vcard_muc: Add an alternative method of signaling avatar change
Kim Alvefur <zash@zash.se>
parents: 3655
diff changeset
105 type = "text-single",
3e0f4d727825 mod_vcard_muc: Add an alternative method of signaling avatar change
Kim Alvefur <zash@zash.se>
parents: 3655
diff changeset
106 });
3e0f4d727825 mod_vcard_muc: Add an alternative method of signaling avatar change
Kim Alvefur <zash@zash.se>
parents: 3655
diff changeset
107 event.formdata["{http://modules.prosody.im/mod_vcard_muc}avatar#sha1"] = get_photo_hash(event.room);
3043
6cc44e69443a mod_vcard_muc: Initial commit
Michel Le Bihan <michel@lebihan.pl>
parents:
diff changeset
108 end);
3046
d0db28768980 mod_vcard_muc: Send presence on muc-occupant-session-new event
Michel Le Bihan <michel@lebihan.pl>
parents: 3043
diff changeset
109
d0db28768980 mod_vcard_muc: Send presence on muc-occupant-session-new event
Michel Le Bihan <michel@lebihan.pl>
parents: 3043
diff changeset
110 module:hook("muc-occupant-session-new", function(event)
d0db28768980 mod_vcard_muc: Send presence on muc-occupant-session-new event
Michel Le Bihan <michel@lebihan.pl>
parents: 3043
diff changeset
111 broadcast_presence(event.room.jid, event.jid);
d0db28768980 mod_vcard_muc: Send presence on muc-occupant-session-new event
Michel Le Bihan <michel@lebihan.pl>
parents: 3043
diff changeset
112 end)