e492885ac0
This reduces lookup time for vcards greatly, since we don't can access a map of ids instead of using `findWhere` through an array of models.
189 lines
5.8 KiB
JavaScript
189 lines
5.8 KiB
JavaScript
import log from "@converse/headless/log";
|
|
import { _converse, api, converse } from "../../core.js";
|
|
import { initStorage } from '@converse/headless/utils/storage.js';
|
|
|
|
const { Strophe, $iq, u } = converse.env;
|
|
|
|
|
|
async function onVCardData (jid, iq) {
|
|
const vcard = iq.querySelector('vCard');
|
|
let result = {};
|
|
if (vcard !== null) {
|
|
result = {
|
|
'stanza': iq,
|
|
'fullname': vcard.querySelector('FN')?.textContent,
|
|
'nickname': vcard.querySelector('NICKNAME')?.textContent,
|
|
'image': vcard.querySelector('PHOTO BINVAL')?.textContent,
|
|
'image_type': vcard.querySelector('PHOTO TYPE')?.textContent,
|
|
'url': vcard.querySelector('URL')?.textContent,
|
|
'role': vcard.querySelector('ROLE')?.textContent,
|
|
'email': vcard.querySelector('EMAIL USERID')?.textContent,
|
|
'vcard_updated': (new Date()).toISOString(),
|
|
'vcard_error': undefined
|
|
};
|
|
}
|
|
if (result.image) {
|
|
const buffer = u.base64ToArrayBuffer(result['image']);
|
|
const ab = await crypto.subtle.digest('SHA-1', buffer);
|
|
result['image_hash'] = u.arrayBufferToHex(ab);
|
|
}
|
|
return result;
|
|
}
|
|
|
|
|
|
export function createStanza (type, jid, vcard_el) {
|
|
const iq = $iq(jid ? {'type': type, 'to': jid} : {'type': type});
|
|
if (!vcard_el) {
|
|
iq.c("vCard", {'xmlns': Strophe.NS.VCARD});
|
|
} else {
|
|
iq.cnode(vcard_el);
|
|
}
|
|
return iq;
|
|
}
|
|
|
|
|
|
export function onOccupantAvatarChanged (occupant) {
|
|
const hash = occupant.get('image_hash');
|
|
const vcards = [];
|
|
if (occupant.get('jid')) {
|
|
vcards.push(_converse.vcards.get(occupant.get('jid')));
|
|
}
|
|
vcards.push(_converse.vcards.get(occupant.get('from')));
|
|
vcards.forEach(v => (hash && v?.get('image_hash') !== hash) && api.vcard.update(v, true));
|
|
}
|
|
|
|
|
|
export async function setVCardOnModel (model) {
|
|
let jid;
|
|
if (model instanceof _converse.Message) {
|
|
if (['error', 'info'].includes(model.get('type'))) {
|
|
return;
|
|
}
|
|
jid = model.get('from');
|
|
} else {
|
|
jid = model.get('jid');
|
|
}
|
|
|
|
if (!jid) {
|
|
log.warn(`Could not set VCard on model because no JID found!`);
|
|
return;
|
|
}
|
|
|
|
await api.waitUntil('VCardsInitialized');
|
|
model.vcard = _converse.vcards.get(jid) || _converse.vcards.create({ jid });
|
|
model.vcard.on('change', () => model.trigger('vcard:change'));
|
|
model.trigger('vcard:add');
|
|
}
|
|
|
|
|
|
function getVCardForOccupant (occupant) {
|
|
const muc = occupant?.collection?.chatroom;
|
|
const nick = occupant.get('nick');
|
|
|
|
if (nick && muc?.get('nick') === nick) {
|
|
return _converse.xmppstatus.vcard;
|
|
} else {
|
|
const jid = occupant.get('jid') || occupant.get('from');
|
|
if (jid) {
|
|
return _converse.vcards.get(jid) || _converse.vcards.create({ jid });
|
|
} else {
|
|
log.warn(`Could not get VCard for occupant because no JID found!`);
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
export async function setVCardOnOccupant (occupant) {
|
|
await api.waitUntil('VCardsInitialized');
|
|
occupant.vcard = getVCardForOccupant(occupant);
|
|
if (occupant.vcard) {
|
|
occupant.vcard.on('change', () => occupant.trigger('vcard:change'));
|
|
occupant.trigger('vcard:add');
|
|
}
|
|
}
|
|
|
|
|
|
function getVCardForMUCMessage (message) {
|
|
const muc = message?.collection?.chatbox;
|
|
const nick = Strophe.getResourceFromJid(message.get('from'));
|
|
|
|
if (nick && muc?.get('nick') === nick) {
|
|
return _converse.xmppstatus.vcard;
|
|
} else {
|
|
const jid = message.occupant?.get('jid') || message.get('from');
|
|
if (jid) {
|
|
return _converse.vcards.get(jid) || _converse.vcards.create({ jid });
|
|
} else {
|
|
log.warn(`Could not get VCard for message because no JID found! msgid: ${message.get('msgid')}`);
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
export async function setVCardOnMUCMessage (message) {
|
|
if (['error', 'info'].includes(message.get('type'))) {
|
|
return;
|
|
} else {
|
|
await api.waitUntil('VCardsInitialized');
|
|
message.vcard = getVCardForMUCMessage(message);
|
|
if (message.vcard) {
|
|
message.vcard.on('change', () => message.trigger('vcard:change'));
|
|
message.trigger('vcard:add');
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
export async function initVCardCollection () {
|
|
_converse.vcards = new _converse.VCards();
|
|
const id = `${_converse.bare_jid}-converse.vcards`;
|
|
initStorage(_converse.vcards, id);
|
|
await new Promise(resolve => {
|
|
_converse.vcards.fetch({
|
|
'success': resolve,
|
|
'error': resolve
|
|
}, {'silent': true});
|
|
});
|
|
const vcards = _converse.vcards;
|
|
if (_converse.session) {
|
|
const jid = _converse.session.get('bare_jid');
|
|
const status = _converse.xmppstatus;
|
|
status.vcard = vcards.get(jid) || vcards.create({'jid': jid});
|
|
if (status.vcard) {
|
|
status.vcard.on('change', () => status.trigger('vcard:change'));
|
|
status.trigger('vcard:add');
|
|
}
|
|
}
|
|
/**
|
|
* Triggered as soon as the `_converse.vcards` collection has been initialized and populated from cache.
|
|
* @event _converse#VCardsInitialized
|
|
*/
|
|
api.trigger('VCardsInitialized');
|
|
}
|
|
|
|
|
|
export function clearVCardsSession () {
|
|
if (_converse.shouldClearCache()) {
|
|
api.promises.add('VCardsInitialized');
|
|
if (_converse.vcards) {
|
|
_converse.vcards.clearStore();
|
|
delete _converse.vcards;
|
|
}
|
|
}
|
|
}
|
|
|
|
export async function getVCard (jid) {
|
|
const to = Strophe.getBareJidFromJid(jid) === _converse.bare_jid ? null : jid;
|
|
let iq;
|
|
try {
|
|
iq = await api.sendIQ(createStanza("get", to))
|
|
} catch (iq) {
|
|
return {
|
|
jid,
|
|
'stanza': iq,
|
|
'vcard_error': (new Date()).toISOString()
|
|
}
|
|
}
|
|
return onVCardData(jid, iq);
|
|
}
|