diff --git a/app/sql.js b/app/sql.js index f1f6ad229..64fa1848a 100644 --- a/app/sql.js +++ b/app/sql.js @@ -118,6 +118,7 @@ module.exports = { removeMessage, getUnreadByConversation, getMessageBySender, + getMessageByServerId, getMessageById, getAllMessages, getAllMessageIds, @@ -801,6 +802,11 @@ async function updateToLokiSchemaVersion1(currentVersion, instance) { const { id, type, name, friendRequestStatus } = publicChatData; + await instance.run( + `ALTER TABLE messages + ADD COLUMN serverId STRING;` + ); + await instance.run( `INSERT INTO conversations ( id, @@ -1718,6 +1724,7 @@ async function saveMessage(data, { forceSave } = {}) { hasFileAttachments, hasVisualMediaAttachments, id, + serverId, // eslint-disable-next-line camelcase received_at, schemaVersion, @@ -1736,6 +1743,7 @@ async function saveMessage(data, { forceSave } = {}) { $id: id, $json: objectToJSON(data), + $serverId: serverId, $body: body, $conversationId: conversationId, $expirationStartTimestamp: expirationStartTimestamp, @@ -1758,6 +1766,7 @@ async function saveMessage(data, { forceSave } = {}) { await db.run( `UPDATE messages SET json = $json, + serverId = $serverId, body = $body, conversationId = $conversationId, expirationStartTimestamp = $expirationStartTimestamp, @@ -1792,6 +1801,7 @@ async function saveMessage(data, { forceSave } = {}) { id, json, + serverId, body, conversationId, expirationStartTimestamp, @@ -1812,6 +1822,7 @@ async function saveMessage(data, { forceSave } = {}) { $id, $json, + $serverId, $body, $conversationId, $expirationStartTimestamp, @@ -1934,6 +1945,21 @@ async function removeMessage(id) { ); } +async function getMessageByServerId(serverId) { + const row = await db.get( + 'SELECT * FROM messages WHERE serverId = $serverId;', + { + $serverId: serverId, + } + ); + + if (!row) { + return null; + } + + return jsonToObject(row.json); +} + async function getMessageById(id) { const row = await db.get('SELECT * FROM messages WHERE id = $id;', { $id: id, diff --git a/js/background.js b/js/background.js index b7e5fd804..1b2317c80 100644 --- a/js/background.js +++ b/js/background.js @@ -750,14 +750,17 @@ } }); - Whisper.events.on('publicMessageSent', ({ pubKey, timestamp }) => { - try { - const conversation = ConversationController.get(pubKey); - conversation.onPublicMessageSent(pubKey, timestamp); - } catch (e) { - window.log.error('Error setting public on message'); + Whisper.events.on( + 'publicMessageSent', + ({ pubKey, timestamp, serverId }) => { + try { + const conversation = ConversationController.get(pubKey); + conversation.onPublicMessageSent(pubKey, timestamp, serverId); + } catch (e) { + window.log.error('Error setting public on message'); + } } - }); + ); Whisper.events.on('password-updated', () => { if (appView && appView.inboxView) { @@ -1411,7 +1414,6 @@ const { isError } = options; let messageData = { - id: data.id, source: data.source, sourceDevice: data.sourceDevice, sent_at: data.timestamp, diff --git a/js/models/conversations.js b/js/models/conversations.js index 3715a3aba..26a27e8a8 100644 --- a/js/models/conversations.js +++ b/js/models/conversations.js @@ -368,9 +368,14 @@ await Promise.all(messages.map(m => m.setIsP2p(true))); }, - async onPublicMessageSent(pubKey, timestamp) { + async onPublicMessageSent(pubKey, timestamp, serverId) { const messages = this._getMessagesWithTimestamp(pubKey, timestamp); - await Promise.all(messages.map(m => m.setIsPublic(true))); + await Promise.all( + messages.map(message => [ + message.setIsPublic(true), + message.setServerId(serverId), + ]) + ); }, async onNewMessage(message) { @@ -1357,7 +1362,6 @@ options.messageType = message.get('type'); if (this.isPublic()) { options.publicEndpoint = this.getEndpoint(); - options.messageId = id; } const groupNumbers = this.getRecipients(); diff --git a/js/models/messages.js b/js/models/messages.js index cc6c885ef..6aee70a89 100644 --- a/js/models/messages.js +++ b/js/models/messages.js @@ -1242,6 +1242,17 @@ Message: Whisper.Message, }); }, + async setServerId(serverId) { + if (_.isEqual(this.get('serverId'), serverId)) return; + + this.set({ + serverId, + }); + + await window.Signal.Data.saveMessage(this.attributes, { + Message: Whisper.Message, + }); + }, async setIsPublic(isPublic) { if (_.isEqual(this.get('isPublic'), isPublic)) return; @@ -2014,9 +2025,7 @@ } else { await conversation.onFriendRequestAccepted(); } - // Force save if the message already has an id, used for public channels const id = await window.Signal.Data.saveMessage(message.attributes, { - forceSave: !!message.id, Message: Whisper.Message, }); message.set({ id }); diff --git a/js/modules/data.js b/js/modules/data.js index 347fc36fc..cebc102cb 100644 --- a/js/modules/data.js +++ b/js/modules/data.js @@ -141,6 +141,7 @@ module.exports = { removeAllMessagesInConversation, getMessageBySender, + getMessageByServerId, getMessageById, getAllMessages, getAllUnsentMessages, @@ -875,6 +876,15 @@ async function _removeMessages(ids) { await channels.removeMessage(ids); } +async function getMessageByServerId(id, { Message }) { + const message = await channels.getMessageByServerId(id); + if (!message) { + return null; + } + + return new Message(message); +} + async function getMessageById(id, { Message }) { const message = await channels.getMessageById(id); if (!message) { diff --git a/js/modules/loki_message_api.js b/js/modules/loki_message_api.js index 8216ca084..672e6c4f6 100644 --- a/js/modules/loki_message_api.js +++ b/js/modules/loki_message_api.js @@ -80,7 +80,6 @@ class LokiMessageAPI { isPing = false, numConnections = DEFAULT_CONNECTIONS, publicEndpoint = null, - messageId = null, } = options; // Data required to identify a message in a conversation const messageEventData = { @@ -106,13 +105,12 @@ class LokiMessageAPI { timestamp: messageTimeStamp, from: displayName, source: this.ourKey, - id: messageId, }, }, ], }; try { - await nodeFetch(publicEndpoint, { + const result = await nodeFetch(publicEndpoint, { method: 'post', headers: { 'Content-Type': 'application/json', @@ -120,6 +118,8 @@ class LokiMessageAPI { }, body: JSON.stringify(payload), }); + const body = await result.json(); + messageEventData.serverId = body.data.id; window.Whisper.events.trigger('publicMessageSent', messageEventData); return; } catch (e) { diff --git a/js/modules/loki_public_chat_api.js b/js/modules/loki_public_chat_api.js index 17d8e004d..1acc1e884 100644 --- a/js/modules/loki_public_chat_api.js +++ b/js/modules/loki_public_chat_api.js @@ -161,14 +161,13 @@ class LokiPublicChannelAPI { let timestamp = new Date(adnMessage.created_at).getTime(); let from = adnMessage.user.username; let source; - let id; if (adnMessage.annotations.length) { const noteValue = adnMessage.annotations[0].value; - ({ from, timestamp, source, id } = noteValue); + ({ from, timestamp, source } = noteValue); } const messageData = { - id, + serverId: adnMessage.id, friendRequest: false, source, sourceDevice: 1, diff --git a/libtextsecure/outgoing_message.js b/libtextsecure/outgoing_message.js index 02d8fc77d..a0ab663a4 100644 --- a/libtextsecure/outgoing_message.js +++ b/libtextsecure/outgoing_message.js @@ -50,12 +50,10 @@ function OutgoingMessage( messageType, isPing, publicEndpoint, - messageId, } = options || {}; this.numberInfo = numberInfo; this.publicEndpoint = publicEndpoint; - this.messageId = messageId; this.senderCertificate = senderCertificate; this.online = online; this.messageType = messageType || 'outgoing'; @@ -205,7 +203,6 @@ OutgoingMessage.prototype = { }; if (this.publicEndpoint) { options.publicEndpoint = this.publicEndpoint; - options.messageId = this.messageId; } await lokiMessageAPI.sendMessage(pubKey, data, timestamp, ttl, options); } catch (e) {