123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243 |
- // Converse.js
- // http://conversejs.org
- //
- // Copyright (c) 2013-2018, the Converse.js developers
- // Licensed under the Mozilla Public License (MPLv2)
- (function (root, factory) {
- define(["./converse-core", "./templates/vcard.html"], factory);
- }(this, function (converse, tpl_vcard) {
- "use strict";
- const { Backbone, Promise, Strophe, _, $iq, $build, b64_sha1, moment, sizzle } = converse.env;
- const u = converse.env.utils;
- converse.plugins.add('converse-vcard', {
- initialize () {
- /* The initialize function gets called as soon as the plugin is
- * loaded by converse.js's plugin machinery.
- */
- const { _converse } = this;
- _converse.VCard = Backbone.Model.extend({
- defaults: {
- 'image': _converse.DEFAULT_IMAGE,
- 'image_type': _converse.DEFAULT_IMAGE_TYPE
- },
- set (key, val, options) {
- // Override Backbone.Model.prototype.set to make sure that the
- // default `image` and `image_type` values are maintained.
- let attrs;
- if (typeof key === 'object') {
- attrs = key;
- options = val;
- } else {
- (attrs = {})[key] = val;
- }
- if (_.has(attrs, 'image') && !attrs['image']) {
- attrs['image'] = _converse.DEFAULT_IMAGE;
- attrs['image_type'] = _converse.DEFAULT_IMAGE_TYPE;
- return Backbone.Model.prototype.set.call(this, attrs, options);
- } else {
- return Backbone.Model.prototype.set.apply(this, arguments);
- }
- }
- });
- _converse.VCards = Backbone.Collection.extend({
- model: _converse.VCard,
- initialize () {
- this.on('add', (vcard) => _converse.api.vcard.update(vcard));
- }
- });
- function onVCardData (jid, iq, callback) {
- const vcard = iq.querySelector('vCard');
- let result = {};
- if (!_.isNull(vcard)) {
- result = {
- 'stanza': iq,
- 'fullname': _.get(vcard.querySelector('FN'), 'textContent'),
- 'nickname': _.get(vcard.querySelector('NICKNAME'), 'textContent'),
- 'image': _.get(vcard.querySelector('PHOTO BINVAL'), 'textContent'),
- 'image_type': _.get(vcard.querySelector('PHOTO TYPE'), 'textContent'),
- 'url': _.get(vcard.querySelector('URL'), 'textContent'),
- 'role': _.get(vcard.querySelector('ROLE'), 'textContent'),
- 'email': _.get(vcard.querySelector('EMAIL USERID'), 'textContent'),
- 'vcard_updated': moment().format(),
- 'vcard_error': undefined
- };
- }
- if (result.image) {
- const buffer = u.base64ToArrayBuffer(result['image']);
- crypto.subtle.digest('SHA-1', buffer)
- .then(ab => {
- result['image_hash'] = u.arrayBufferToHex(ab);
- if (callback) callback(result);
- });
- } else {
- if (callback) callback(result);
- }
- }
- function onVCardError (jid, iq, errback) {
- if (errback) {
- errback({
- 'stanza': iq,
- 'jid': jid,
- 'vcard_error': moment().format()
- });
- }
- }
- 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;
- }
- function setVCard (jid, data) {
- if (!jid) {
- throw Error("No jid provided for the VCard data");
- }
- const vcard_el = Strophe.xmlHtmlNode(tpl_vcard(data)).firstElementChild;
- return _converse.api.sendIQ(createStanza("set", jid, vcard_el));
- }
- function getVCard (_converse, jid) {
- /* Request the VCard of another user. Returns a promise.
- *
- * Parameters:
- * (String) jid - The Jabber ID of the user whose VCard
- * is being requested.
- */
- const to = Strophe.getBareJidFromJid(jid) === _converse.bare_jid ? null : jid;
- return new Promise((resolve, reject) => {
- _converse.connection.sendIQ(
- createStanza("get", to),
- _.partial(onVCardData, jid, _, resolve),
- _.partial(onVCardError, jid, _, resolve),
- _converse.IQ_TIMEOUT
- );
- });
- }
- /* Event handlers */
- _converse.initVCardCollection = function () {
- _converse.vcards = new _converse.VCards();
- const id = b64_sha1(`converse.vcards`);
- _converse.vcards.browserStorage = new Backbone.BrowserStorage[_converse.config.get('storage')](id);
- _converse.vcards.fetch();
- }
- _converse.api.listen.on('sessionInitialized', _converse.initVCardCollection);
- _converse.on('addClientFeatures', () => {
- _converse.api.disco.own.features.add(Strophe.NS.VCARD);
- });
- _.extend(_converse.api, {
- /**
- * The XEP-0054 VCard API
- *
- * This API lets you access and update user VCards
- *
- * @namespace _converse.api.vcard
- * @memberOf _converse.api
- */
- 'vcard': {
- /**
- * Enables setting new values for a VCard.
- *
- * @method _converse.api.vcard.set
- * @param {string} jid The JID for which the VCard should be set
- * @param {object} data A map of VCard keys and values
- * @example
- * _converse.api.vcard.set({
- * 'jid': _converse.bare_jid,
- * 'fn': 'John Doe',
- * 'nickname': 'jdoe'
- * }).then(() => {
- * // Succes
- * }).catch(() => {
- * // Failure
- * }).
- */
- 'set' (jid, data) {
- return setVCard(jid, data);
- },
- /**
- * @method _converse.api.vcard.get
- * @param {Backbone.Model|string} model Either a `Backbone.Model` instance, or a string JID.
- * If a `Backbone.Model` instance is passed in, then it must have either a `jid`
- * attribute or a `muc_jid` attribute.
- * @param {boolean} [force] A boolean indicating whether the vcard should be
- * fetched even if it's been fetched before.
- * @returns {promise} A Promise which resolves with the VCard data for a particular JID or for
- * a `Backbone.Model` instance which represents an entity with a JID (such as a roster contact,
- * chat or chatroom occupant).
- *
- * @example
- * _converse.api.waitUntil('rosterContactsFetched').then(() => {
- * _converse.api.vcard.get('someone@example.org').then(
- * (vcard) => {
- * // Do something with the vcard...
- * }
- * );
- * });
- */
- 'get' (model, force) {
- if (_.isString(model)) {
- return getVCard(_converse, model);
- } else if (force ||
- !model.get('vcard_updated') ||
- !moment(model.get('vcard_error')).isSame(new Date(), "day")) {
- const jid = model.get('jid');
- if (!jid) {
- throw new Error("No JID to get vcard for!");
- }
- return getVCard(_converse, jid);
- } else {
- return Promise.resolve({});
- }
- },
- /**
- * Fetches the VCard associated with a particular `Backbone.Model` instance
- * (by using its `jid` or `muc_jid` attribute) and then updates the model with the
- * returned VCard data.
- *
- * @method _converse.api.vcard.update
- * @param {Backbone.Model} model A `Backbone.Model` instance
- * @param {boolean} [force] A boolean indicating whether the vcard should be
- * fetched again even if it's been fetched before.
- * @returns {promise} A promise which resolves once the update has completed.
- * @example
- * _converse.api.waitUntil('rosterContactsFetched').then(() => {
- * const chatbox = _converse.chatboxes.getChatBox('someone@example.org');
- * _converse.api.vcard.update(chatbox);
- * });
- */
- 'update' (model, force) {
- return this.get(model, force)
- .then(vcard => {
- delete vcard['stanza']
- model.save(vcard);
- });
- }
- }
- });
- }
- });
- }));
|