You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
cryptpad/www/common/outer/mailbox-handlers.js

203 lines
7.4 KiB
JavaScript

This file contains invisible Unicode characters!

This file contains invisible Unicode characters that may be processed differently from what appears below. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to reveal hidden characters.

define([
'/common/common-messaging.js',
], function (Messaging) {
var getRandomTimeout = function (ctx) {
var lag = ctx.store.realtime.getLag().lag || 0;
return (Math.max(0, lag) + 300) * 20 * (0.5 + Math.random());
};
var handlers = {};
var removeHandlers = {};
// Store the friend request displayed to avoid duplicates
var friendRequest = {};
handlers['FRIEND_REQUEST'] = function (ctx, box, data, cb) {
// Check if the request is valid (send by the correct user)
if (data.msg.author !== data.msg.content.curvePublic) {
return void cb(true);
}
// Don't show duplicate friend request: if we already have a friend request
// in memory from the same user, dismiss the new one
if (friendRequest[data.msg.author]) { return void cb(true); }
friendRequest[data.msg.author] = true;
// If the user is already in our friend list, automatically accept the request
if (Messaging.getFriend(ctx.store.proxy, data.msg.author) ||
ctx.store.proxy.friends_pending[data.msg.author]) {
Messaging.acceptFriendRequest(ctx.store, data.msg.content, function (obj) {
if (obj && obj.error) {
return void cb();
}
cb(true);
});
return;
}
cb();
};
removeHandlers['FRIEND_REQUEST'] = function (ctx, box, data) {
if (friendRequest[data.content.curvePublic]) {
delete friendRequest[data.content.curvePublic];
}
};
var friendRequestDeclined = {};
handlers['DECLINE_FRIEND_REQUEST'] = function (ctx, box, data, cb) {
setTimeout(function () {
// Our friend request was declined.
if (!ctx.store.proxy.friends_pending[data.msg.author]) { return; }
// Remove the pending message and display the "declined" state in the UI
delete ctx.store.proxy.friends_pending[data.msg.author];
ctx.updateMetadata();
if (friendRequestDeclined[data.msg.author]) { return; }
box.sendMessage({
type: 'FRIEND_REQUEST_DECLINED',
content: {
user: data.msg.author,
name: data.msg.content.displayName
}
}, function () {
if (friendRequestDeclined[data.msg.author]) {
// TODO remove our message because another one was sent first?
}
friendRequestDeclined[data.msg.author] = true;
});
}, getRandomTimeout(ctx));
cb(true);
};
handlers['FRIEND_REQUEST_DECLINED'] = function (ctx, box, data, cb) {
ctx.updateMetadata();
if (friendRequestDeclined[data.msg.content.user]) { return void cb(true); }
friendRequestDeclined[data.msg.content.user] = true;
cb();
};
removeHandlers['FRIEND_REQUEST_DECLINED'] = function (ctx, box, data) {
if (friendRequestDeclined[data.content.user]) {
delete friendRequestDeclined[data.content.user];
}
};
var friendRequestAccepted = {};
handlers['ACCEPT_FRIEND_REQUEST'] = function (ctx, box, data, cb) {
// Our friend request was accepted.
setTimeout(function () {
// Make sure we really sent it
if (!ctx.store.proxy.friends_pending[data.msg.author]) { return; }
// And add the friend
Messaging.addToFriendList({
proxy: ctx.store.proxy,
realtime: ctx.store.realtime,
pinPads: ctx.pinPads
}, data.msg.content, function (err) {
if (err) { console.error(err); }
delete ctx.store.proxy.friends_pending[data.msg.author];
if (ctx.store.messenger) {
ctx.store.messenger.onFriendAdded(data.msg.content);
}
ctx.updateMetadata();
// If you have a profile page open, update it
if (ctx.store.modules['profile']) { ctx.store.modules['profile'].update(); }
if (friendRequestAccepted[data.msg.author]) { return; }
// Display the "accepted" state in the UI
box.sendMessage({
type: 'FRIEND_REQUEST_ACCEPTED',
content: {
user: data.msg.author,
name: data.msg.content.displayName
}
}, function () {
if (friendRequestAccepted[data.msg.author]) {
// TODO remove our message because another one was sent first?
}
friendRequestAccepted[data.msg.author] = true;
});
});
}, getRandomTimeout(ctx));
cb(true);
};
handlers['FRIEND_REQUEST_ACCEPTED'] = function (ctx, box, data, cb) {
ctx.updateMetadata();
if (friendRequestAccepted[data.msg.content.user]) { return void cb(true); }
friendRequestAccepted[data.msg.content.user] = true;
cb();
};
removeHandlers['FRIEND_REQUEST_ACCEPTED'] = function (ctx, box, data) {
if (friendRequestAccepted[data.content.user]) {
delete friendRequestAccepted[data.content.user];
}
};
handlers['UNFRIEND'] = function (ctx, box, data, cb) {
var curve = data.msg.content.curvePublic;
var friend = Messaging.getFriend(ctx.store.proxy, curve);
if (!friend) { return void cb(true); }
delete ctx.store.proxy.friends[curve];
if (ctx.store.messenger) {
ctx.store.messenger.onFriendRemoved(curve, friend.channel);
}
ctx.updateMetadata();
cb(true);
};
handlers['UPDATE_DATA'] = function (ctx, box, data, cb) {
var msg = data.msg;
var curve = msg.author;
var friend = ctx.store.proxy.friends && ctx.store.proxy.friends[curve];
if (!friend || typeof msg.content !== "object") { return void cb(true); }
Object.keys(msg.content).forEach(function (key) {
friend[key] = msg.content[key];
});
ctx.updateMetadata();
cb(true);
};
return {
add: function (ctx, box, data, cb) {
/**
* data = {
msg: {
type: 'STRING',
author: 'curvePublicString',
content: {} (depend on the "type")
},
hash: 'string'
}
*/
if (!data.msg) { return void cb(true); }
var type = data.msg.type;
if (handlers[type]) {
try {
handlers[type](ctx, box, data, cb);
} catch (e) {
console.error(e);
cb();
}
} else {
cb();
}
},
remove: function (ctx, box, data, h) {
// We sometimes try to delete non-existant data (with "delete box.content[h]")
// In this case, we don't have the data in memory so we don't need to call
// any "remove" handler
if (!data) { return; }
var type = data.type;
if (removeHandlers[type]) {
try {
removeHandlers[type](ctx, box, data, h);
} catch (e) {
console.error(e);
}
}
}
};
});