add option to send a message to a single device, or to all device except one

pull/1137/head
Audric Ackermann 5 years ago
parent afbc1a345d
commit 12b396ce7e
No known key found for this signature in database
GPG Key ID: 999F434D76324AD4

@ -1124,11 +1124,6 @@
"message": " Type your message", "message": " Type your message",
"description": "Placeholder text in the message entry field" "description": "Placeholder text in the message entry field"
}, },
"secondaryDeviceDefaultFR": {
"message": "Please accept to enable messages to be synced across devices",
"description":
"Placeholder text in the message entry field when it is disabled because a secondary device conversation is visible"
},
"sendMessageDisabledSecondary": { "sendMessageDisabledSecondary": {
"message": "message":
"This pubkey belongs to a secondary device. You should never see this message", "This pubkey belongs to a secondary device. You should never see this message",

@ -14,7 +14,8 @@
clipboard, clipboard,
BlockedNumberController, BlockedNumberController,
lokiPublicChatAPI, lokiPublicChatAPI,
JobQueue JobQueue,
libloki
*/ */
/* eslint-disable more/no-then */ /* eslint-disable more/no-then */
@ -1074,6 +1075,14 @@
window.textsecure.OutgoingMessage.DebugMessageType window.textsecure.OutgoingMessage.DebugMessageType
.INCOMING_FR_ACCEPTED .INCOMING_FR_ACCEPTED
); );
// send an AFR to other device of that user (or none)
const primaryPubKey = await libloki.api.getPrimaryDevicePubkey(this.id);
const autoFrMessage = textsecure.OutgoingMessage.buildAutoFriendRequestMessage(
primaryPubKey
);
await autoFrMessage.sendToNumber(primaryPubKey, true, this.id);
} }
}, },
// Our outgoing friend request has been accepted // Our outgoing friend request has been accepted

@ -2152,7 +2152,7 @@
// still go through one of the previous two codepaths // still go through one of the previous two codepaths
const ourNumber = textsecure.storage.user.getNumber(); const ourNumber = textsecure.storage.user.getNumber();
const message = this; const message = this;
let source = message.get('source'); const source = message.get('source');
let conversationId = message.get('conversationId'); let conversationId = message.get('conversationId');
const authorisation = await libloki.storage.getGrantAuthorisationForSecondaryPubKey( const authorisation = await libloki.storage.getGrantAuthorisationForSecondaryPubKey(
source source
@ -2234,7 +2234,7 @@
} }
} }
const conversation = conversationPrimary; const conversation = conversationPrimary;
source = primarySource; // source = primarySource;
return conversation.queueJob(async () => { return conversation.queueJob(async () => {
window.log.info( window.log.info(
@ -2569,7 +2569,8 @@
} }
} }
if (source !== ourNumber) { // We need to map the original message source to the primary device
if (source !== ourNumber && !message.isFriendRequest()) {
message.set({ source: primarySource }); message.set({ source: primarySource });
} }

@ -90,38 +90,22 @@
const message = textsecure.OutgoingMessage.buildSessionEstablishedMessage( const message = textsecure.OutgoingMessage.buildSessionEstablishedMessage(
pubKey pubKey
); );
await message.sendToNumber(pubKey); await message.sendToNumber(pubKey, false);
} }
async function sendBackgroundMessage(pubKey, debugMessageType) { async function sendBackgroundMessage(pubKey, debugMessageType) {
const primaryPubKey = await getPrimaryDevicePubkey(pubKey);
if (primaryPubKey !== pubKey) {
// if we got the secondary device pubkey first,
// call ourself again with the primary device pubkey
await sendBackgroundMessage(primaryPubKey, debugMessageType);
return;
}
const backgroundMessage = textsecure.OutgoingMessage.buildBackgroundMessage( const backgroundMessage = textsecure.OutgoingMessage.buildBackgroundMessage(
pubKey, pubKey,
debugMessageType debugMessageType
); );
await backgroundMessage.sendToNumber(pubKey); await backgroundMessage.sendToNumber(pubKey, false);
} }
async function sendAutoFriendRequestMessage(pubKey) { async function sendAutoFriendRequestMessage(pubKey) {
const primaryPubKey = await getPrimaryDevicePubkey(pubKey);
if (primaryPubKey !== pubKey) {
// if we got the secondary device pubkey first,
// call ourself again with the primary device pubkey
await sendAutoFriendRequestMessage(primaryPubKey);
return;
}
const autoFrMessage = textsecure.OutgoingMessage.buildAutoFriendRequestMessage( const autoFrMessage = textsecure.OutgoingMessage.buildAutoFriendRequestMessage(
pubKey pubKey
); );
await autoFrMessage.sendToNumber(pubKey); await autoFrMessage.sendToNumber(pubKey, false);
} }
function createPairingAuthorisationProtoMessage({ function createPairingAuthorisationProtoMessage({
@ -157,7 +141,7 @@
const unpairingMessage = textsecure.OutgoingMessage.buildUnpairingMessage( const unpairingMessage = textsecure.OutgoingMessage.buildUnpairingMessage(
pubKey pubKey
); );
return unpairingMessage.sendToNumber(pubKey); return unpairingMessage.sendToNumber(pubKey, false);
} }
// Serialise as <Element0.length><Element0><Element1.length><Element1>... // Serialise as <Element0.length><Element0><Element1.length><Element1>...
// This is an implementation of the reciprocal of contacts_parser.js // This is an implementation of the reciprocal of contacts_parser.js
@ -296,7 +280,7 @@
callback callback
); );
pairingRequestMessage.sendToNumber(recipientPubKey); pairingRequestMessage.sendToNumber(recipientPubKey, false);
}); });
return p; return p;
} }
@ -346,6 +330,7 @@
createContactSyncProtoMessage, createContactSyncProtoMessage,
createGroupSyncProtoMessage, createGroupSyncProtoMessage,
createOpenGroupsSyncProtoMessage, createOpenGroupsSyncProtoMessage,
getPrimaryDevicePubkey,
debug, debug,
}; };
})(); })();

@ -216,17 +216,26 @@ OutgoingMessage.prototype = {
this.errors[this.errors.length] = error; this.errors[this.errors.length] = error;
this.numberCompleted(); this.numberCompleted();
}, },
reloadDevicesAndSend(primaryPubKey) { reloadDevicesAndSend(primaryPubKey, multiDevice = true, excludedDevices = []) {
const ourNumber = textsecure.storage.user.getNumber(); const ourNumber = textsecure.storage.user.getNumber();
if (!multiDevice) {
if (primaryPubKey === ourNumber) {
return Promise.resolve();
}
return this.doSendMessage(primaryPubKey, [primaryPubKey]);
}
return ( return (
libloki.storage libloki.storage
.getAllDevicePubKeysForPrimaryPubKey(primaryPubKey) .getAllDevicePubKeysForPrimaryPubKey(primaryPubKey)
// Don't send to ourselves // Don't send to ourselves
.then(devicesPubKeys => .then(devicesPubKeys =>
devicesPubKeys.filter(pubKey => pubKey !== ourNumber) devicesPubKeys.filter(pubKey => pubKey !== ourNumber && !excludedDevices.includes(pubKey))
) )
.then(devicesPubKeys => { .then(devicesPubKeys => {
if (devicesPubKeys.length === 0) { if (devicesPubKeys.length === 0) {
// No need to start the sending of message without a recipient // No need to start the sending of message without a recipient
return Promise.resolve(); return Promise.resolve();
@ -349,7 +358,7 @@ OutgoingMessage.prototype = {
const updatedDevices = await getStaleDeviceIdsForNumber(devicePubKey); const updatedDevices = await getStaleDeviceIdsForNumber(devicePubKey);
const keysFound = await this.getKeysForNumber(devicePubKey, updatedDevices); const keysFound = await this.getKeysForNumber(devicePubKey, updatedDevices);
let isMultiDeviceRequest = false; // let isMultiDeviceRequest = false;
let thisDeviceMessageType = this.messageType; let thisDeviceMessageType = this.messageType;
if ( if (
thisDeviceMessageType !== 'pairing-request' && thisDeviceMessageType !== 'pairing-request' &&
@ -370,7 +379,7 @@ OutgoingMessage.prototype = {
// - We haven't received a friend request from this device // - We haven't received a friend request from this device
// - We haven't sent a friend request recently // - We haven't sent a friend request recently
if (conversation.friendRequestTimerIsExpired()) { if (conversation.friendRequestTimerIsExpired()) {
isMultiDeviceRequest = true; // isMultiDeviceRequest = true;
thisDeviceMessageType = 'friend-request'; thisDeviceMessageType = 'friend-request';
} else { } else {
// Throttle automated friend requests // Throttle automated friend requests
@ -412,27 +421,11 @@ OutgoingMessage.prototype = {
window.log.info('attaching prekeys to outgoing message'); window.log.info('attaching prekeys to outgoing message');
} }
let messageBuffer; const messageBuffer = this.message.toArrayBuffer();
let logDetails; const logDetails = {
if (isMultiDeviceRequest) {
const tempMessage = new textsecure.protobuf.Content();
const tempDataMessage = new textsecure.protobuf.DataMessage();
tempDataMessage.body = i18n('secondaryDeviceDefaultFR');
if (this.message.dataMessage && this.message.dataMessage.profile) {
tempDataMessage.profile = this.message.dataMessage.profile;
}
tempMessage.preKeyBundleMessage = this.message.preKeyBundleMessage;
tempMessage.dataMessage = tempDataMessage;
messageBuffer = tempMessage.toArrayBuffer();
logDetails = {
tempMessage,
};
} else {
messageBuffer = this.message.toArrayBuffer();
logDetails = {
message: this.message, message: this.message,
}; };
}
const messageTypeStr = this.debugMessageType; const messageTypeStr = this.debugMessageType;
const ourPubKey = textsecure.storage.user.getNumber(); const ourPubKey = textsecure.storage.user.getNumber();
@ -489,6 +482,7 @@ OutgoingMessage.prototype = {
plaintext, plaintext,
pubKey, pubKey,
isSessionRequest, isSessionRequest,
isFriendRequest,
enableFallBackEncryption, enableFallBackEncryption,
} = clearMessage; } = clearMessage;
// Session doesn't use the deviceId scheme, it's always 1. // Session doesn't use the deviceId scheme, it's always 1.
@ -534,7 +528,7 @@ OutgoingMessage.prototype = {
sourceDevice, sourceDevice,
content, content,
pubKey, pubKey,
isFriendRequest: enableFallBackEncryption, isFriendRequest,
isSessionRequest, isSessionRequest,
}; };
}, },
@ -708,14 +702,14 @@ OutgoingMessage.prototype = {
return promise; return promise;
}, },
sendToNumber(number) { sendToNumber(number, multiDevice = true, excludedDevices = []) {
let conversation; let conversation;
try { try {
conversation = ConversationController.get(number); conversation = ConversationController.get(number);
} catch (e) { } catch (e) {
// do nothing // do nothing
} }
return this.reloadDevicesAndSend(number).catch(error => { return this.reloadDevicesAndSend(number, multiDevice, excludedDevices).catch(error => {
conversation.resetPendingSend(); conversation.resetPendingSend();
if (error.message === 'Identity key changed') { if (error.message === 'Identity key changed') {
// eslint-disable-next-line no-param-reassign // eslint-disable-next-line no-param-reassign
@ -740,9 +734,7 @@ OutgoingMessage.prototype = {
OutgoingMessage.buildAutoFriendRequestMessage = function buildAutoFriendRequestMessage( OutgoingMessage.buildAutoFriendRequestMessage = function buildAutoFriendRequestMessage(
pubKey pubKey
) { ) {
const body = const body = 'Please accept to enable messages to be synced across devices';
'(If you see this message, you must be using an out-of-date client)';
const dataMessage = new textsecure.protobuf.DataMessage({ body }); const dataMessage = new textsecure.protobuf.DataMessage({ body });
const content = new textsecure.protobuf.Content({ const content = new textsecure.protobuf.Content({
@ -750,7 +742,7 @@ OutgoingMessage.buildAutoFriendRequestMessage = function buildAutoFriendRequestM
}); });
const options = { const options = {
messageType: 'onlineBroadcast', messageType: 'friend-request',
debugMessageType: DebugMessageType.AUTO_FR_REQUEST, debugMessageType: DebugMessageType.AUTO_FR_REQUEST,
}; };
// Send a empty message with information about how to contact us directly // Send a empty message with information about how to contact us directly
@ -768,9 +760,12 @@ OutgoingMessage.buildAutoFriendRequestMessage = function buildAutoFriendRequestM
OutgoingMessage.buildSessionRequestMessage = function buildSessionRequestMessage( OutgoingMessage.buildSessionRequestMessage = function buildSessionRequestMessage(
pubKey pubKey
) { ) {
const body =
'(If you see this message, you must be using an out-of-date client)';
const flags = textsecure.protobuf.DataMessage.Flags.SESSION_REQUEST; const flags = textsecure.protobuf.DataMessage.Flags.SESSION_REQUEST;
const dataMessage = new textsecure.protobuf.DataMessage({ flags }); const dataMessage = new textsecure.protobuf.DataMessage({ flags, body });
const content = new textsecure.protobuf.Content({ const content = new textsecure.protobuf.Content({
dataMessage, dataMessage,

Loading…
Cancel
Save