Fix processing of outgoing attachment messages in public chats.

Before we were directly inserting messages into the database but that wasn't working because attachments never got downloaded. This fixes it so we forcefully go through signals pipeline via self sync messages.
This commit is contained in:
Mikunj 2019-11-15 11:37:36 +11:00
parent 848cab8677
commit 463aaf0fb8
2 changed files with 54 additions and 88 deletions

View File

@ -891,7 +891,7 @@ public class PushDecryptJob extends BaseJob implements InjectableType {
return threadId;
}
private long handleSynchronizeSentMediaMessage(@NonNull SentTranscriptMessage message)
public long handleSynchronizeSentMediaMessage(@NonNull SentTranscriptMessage message)
throws MmsException
{
MmsDatabase database = DatabaseFactory.getMmsDatabase(context);
@ -927,6 +927,7 @@ public class PushDecryptJob extends BaseJob implements InjectableType {
try {
long messageId = database.insertMessageOutbox(mediaMessage, threadId, false, null);
if (message.messageServerID >= 0) { DatabaseFactory.getLokiMessageDatabase(context).setServerID(messageId, message.messageServerID); }
if (recipients.getAddress().isGroup()) {
GroupReceiptDatabase receiptDatabase = DatabaseFactory.getGroupReceiptDatabase(context);
@ -1222,7 +1223,7 @@ public class PushDecryptJob extends BaseJob implements InjectableType {
}
}
private long handleSynchronizeSentTextMessage(@NonNull SentTranscriptMessage message)
public long handleSynchronizeSentTextMessage(@NonNull SentTranscriptMessage message)
throws MmsException
{
@ -1245,6 +1246,8 @@ public class PushDecryptJob extends BaseJob implements InjectableType {
outgoingMediaMessage = new OutgoingSecureMediaMessage(outgoingMediaMessage);
messageId = DatabaseFactory.getMmsDatabase(context).insertMessageOutbox(outgoingMediaMessage, threadId, false, null);
if (message.messageServerID >= 0) { DatabaseFactory.getLokiMessageDatabase(context).setServerID(messageId, message.messageServerID); }
database = DatabaseFactory.getMmsDatabase(context);
GroupReceiptDatabase receiptDatabase = DatabaseFactory.getGroupReceiptDatabase(context);

View File

@ -4,23 +4,15 @@ import android.content.Context
import android.os.Handler
import android.util.Log
import org.thoughtcrime.securesms.crypto.IdentityKeyUtil
import org.thoughtcrime.securesms.database.Address
import org.thoughtcrime.securesms.database.DatabaseFactory
import org.thoughtcrime.securesms.database.ThreadDatabase
import org.thoughtcrime.securesms.jobs.PushDecryptJob
import org.thoughtcrime.securesms.linkpreview.LinkPreviewRepository
import org.thoughtcrime.securesms.linkpreview.LinkPreviewUtil
import org.thoughtcrime.securesms.mms.OutgoingMediaMessage
import org.thoughtcrime.securesms.mms.QuoteModel
import org.thoughtcrime.securesms.recipients.Recipient
import org.thoughtcrime.securesms.util.GroupUtil
import org.thoughtcrime.securesms.util.TextSecurePreferences
import org.thoughtcrime.securesms.util.Util
import org.whispersystems.libsignal.util.guava.Optional
import org.whispersystems.signalservice.api.messages.SignalServiceAttachmentPointer
import org.whispersystems.signalservice.api.messages.SignalServiceContent
import org.whispersystems.signalservice.api.messages.SignalServiceDataMessage
import org.whispersystems.signalservice.api.messages.SignalServiceGroup
import org.whispersystems.signalservice.api.messages.multidevice.SentTranscriptMessage
import org.whispersystems.signalservice.api.push.SignalServiceAddress
import org.whispersystems.signalservice.loki.api.LokiPublicChat
import org.whispersystems.signalservice.loki.api.LokiPublicChatAPI
@ -28,6 +20,7 @@ import org.whispersystems.signalservice.loki.api.LokiPublicChatMessage
import org.whispersystems.signalservice.loki.api.LokiStorageAPI
import org.whispersystems.signalservice.loki.utilities.get
import org.whispersystems.signalservice.loki.utilities.successBackground
import java.util.*
class LokiPublicChatPoller(private val context: Context, private val group: LokiPublicChat) {
private val handler = Handler()
@ -97,18 +90,17 @@ class LokiPublicChatPoller(private val context: Context, private val group: Loki
// endregion
// region Polling
private fun pollForNewMessages() {
fun processIncomingMessage(message: LokiPublicChatMessage) {
val id = group.id.toByteArray()
val serviceGroup = SignalServiceGroup(SignalServiceGroup.Type.UPDATE, id, null, null, null)
val quote = if (message.quote != null) {
SignalServiceDataMessage.Quote(message.quote!!.quotedMessageTimestamp, SignalServiceAddress(message.quote!!.quoteeHexEncodedPublicKey), message.quote!!.quotedMessageBody, listOf())
} else {
null
}
val attachments = message.attachments.mapNotNull { attachment ->
if (attachment.kind != LokiPublicChatMessage.Attachment.Kind.Attachment) { return@mapNotNull null }
SignalServiceAttachmentPointer(
private fun getDataMessage(message: LokiPublicChatMessage): SignalServiceDataMessage {
val id = group.id.toByteArray()
val serviceGroup = SignalServiceGroup(SignalServiceGroup.Type.UPDATE, id, null, null, null)
val quote = if (message.quote != null) {
SignalServiceDataMessage.Quote(message.quote!!.quotedMessageTimestamp, SignalServiceAddress(message.quote!!.quoteeHexEncodedPublicKey), message.quote!!.quotedMessageBody, listOf())
} else {
null
}
val attachments = message.attachments.mapNotNull { attachment ->
if (attachment.kind != LokiPublicChatMessage.Attachment.Kind.Attachment) { return@mapNotNull null }
SignalServiceAttachmentPointer(
attachment.serverID,
attachment.contentType,
ByteArray(0),
@ -120,86 +112,57 @@ class LokiPublicChatPoller(private val context: Context, private val group: Loki
false,
Optional.fromNullable(attachment.caption),
attachment.url)
}
val linkPreview = message.attachments.firstOrNull { it.kind == LokiPublicChatMessage.Attachment.Kind.LinkPreview }
val signalLinkPreviews = mutableListOf<SignalServiceDataMessage.Preview>()
if (linkPreview != null) {
val attachment = SignalServiceAttachmentPointer(
linkPreview.serverID,
linkPreview.contentType,
ByteArray(0),
Optional.of(linkPreview.size),
Optional.absent(),
linkPreview.width, linkPreview.height,
Optional.absent(),
Optional.of(linkPreview.fileName),
false,
Optional.fromNullable(linkPreview.caption),
linkPreview.url)
signalLinkPreviews.add(SignalServiceDataMessage.Preview(linkPreview.linkPreviewURL!!, linkPreview.linkPreviewTitle!!, Optional.of(attachment)))
}
val body = if (message.body == message.timestamp.toString()) "" else message.body // Workaround for the fact that the back-end doesn't accept messages without a body
val serviceDataMessage = SignalServiceDataMessage(message.timestamp, serviceGroup, attachments, body, false, 0, false, null, false, quote, null, signalLinkPreviews, null)
}
val linkPreview = message.attachments.firstOrNull { it.kind == LokiPublicChatMessage.Attachment.Kind.LinkPreview }
val signalLinkPreviews = mutableListOf<SignalServiceDataMessage.Preview>()
if (linkPreview != null) {
val attachment = SignalServiceAttachmentPointer(
linkPreview.serverID,
linkPreview.contentType,
ByteArray(0),
Optional.of(linkPreview.size),
Optional.absent(),
linkPreview.width, linkPreview.height,
Optional.absent(),
Optional.of(linkPreview.fileName),
false,
Optional.fromNullable(linkPreview.caption),
linkPreview.url)
signalLinkPreviews.add(SignalServiceDataMessage.Preview(linkPreview.linkPreviewURL!!, linkPreview.linkPreviewTitle!!, Optional.of(attachment)))
}
val body = if (message.body == message.timestamp.toString()) "" else message.body // Workaround for the fact that the back-end doesn't accept messages without a body
return SignalServiceDataMessage(message.timestamp, serviceGroup, attachments, body, false, 0, false, null, false, quote, null, signalLinkPreviews, null)
}
private fun pollForNewMessages() {
fun processIncomingMessage(message: LokiPublicChatMessage) {
val serviceDataMessage = getDataMessage(message)
val serviceContent = SignalServiceContent(serviceDataMessage, message.hexEncodedPublicKey, SignalServiceAddress.DEFAULT_DEVICE_ID, message.timestamp, false)
val senderDisplayName = "${message.displayName} (...${message.hexEncodedPublicKey.takeLast(8)})"
DatabaseFactory.getLokiUserDatabase(context).setServerDisplayName(group.id, message.hexEncodedPublicKey, senderDisplayName)
if (quote != null || attachments.count() > 0 || linkPreview != null) {
if (serviceDataMessage.quote.isPresent || (serviceDataMessage.attachments.isPresent && serviceDataMessage.attachments.get().size > 0) || serviceDataMessage.previews.isPresent) {
PushDecryptJob(context).handleMediaMessage(serviceContent, serviceDataMessage, Optional.absent(), Optional.of(message.serverID))
} else {
PushDecryptJob(context).handleTextMessage(serviceContent, serviceDataMessage, Optional.absent(), Optional.of(message.serverID))
}
}
fun processOutgoingMessage(message: LokiPublicChatMessage) {
val messageServerID = message.serverID ?: return
val lokiMessageDatabase = DatabaseFactory.getLokiMessageDatabase(context)
val isDuplicate = lokiMessageDatabase.getMessageID(messageServerID) != null
val isDuplicate = DatabaseFactory.getLokiMessageDatabase(context).getMessageID(messageServerID) != null
if (isDuplicate) { return }
if (message.body.isEmpty() && message.attachments.isEmpty() && message.quote == null) { return }
val id = group.id.toByteArray()
val mmsDatabase = DatabaseFactory.getMmsDatabase(context)
val recipient = Recipient.from(context, Address.fromSerialized(GroupUtil.getEncodedId(id, false)), false)
val quote: QuoteModel?
if (message.quote != null) {
quote = QuoteModel(message.quote!!.quotedMessageTimestamp, Address.fromSerialized(message.quote!!.quoteeHexEncodedPublicKey), message.quote!!.quotedMessageBody, false, listOf())
val localNumber = TextSecurePreferences.getLocalNumber(context)
val dataMessage = getDataMessage(message)
val transcript = SentTranscriptMessage(localNumber, dataMessage.timestamp, dataMessage, dataMessage.expiresInSeconds.toLong(), Collections.singletonMap(localNumber, false))
transcript.messageServerID = messageServerID
if (dataMessage.quote.isPresent || (dataMessage.attachments.isPresent && dataMessage.attachments.get().size > 0) || dataMessage.previews.isPresent) {
PushDecryptJob(context).handleSynchronizeSentMediaMessage(transcript)
} else {
quote = null
}
// TODO: Handle attachments correctly for our previous messages
val body = if (message.body == message.timestamp.toString()) "" else message.body // Workaround for the fact that the back-end doesn't accept messages without a body
val signalMessage = OutgoingMediaMessage(recipient, body, listOf(), message.timestamp, 0, 0,
ThreadDatabase.DistributionTypes.DEFAULT, quote, listOf(), listOf(), listOf(), listOf())
val threadID = DatabaseFactory.getThreadDatabase(context).getThreadIdFor(recipient)
fun finalize() {
val messageID = mmsDatabase.insertMessageOutbox(signalMessage, threadID, false, null)
mmsDatabase.markAsSent(messageID, true)
mmsDatabase.markUnidentified(messageID, false)
lokiMessageDatabase.setServerID(messageID, messageServerID)
}
val urls = LinkPreviewUtil.findWhitelistedUrls(message.body)
val urlCount = urls.size
if (urlCount != 0) {
val lpr = LinkPreviewRepository(context)
var count = 0
urls.forEach { url ->
lpr.getLinkPreview(context, url.url) { lp ->
Util.runOnMain {
count += 1
if (lp.isPresent) { signalMessage.linkPreviews.add(lp.get()) }
if (count == urlCount) {
try {
finalize()
} catch (e: Exception) {
// TODO: Handle
}
}
}
}
}
} else {
finalize()
PushDecryptJob(context).handleSynchronizeSentTextMessage(transcript)
}
}
api.getMessages(group.channel, group.server).successBackground { messages ->
if (messages.isNotEmpty()) {
val ourDevices = LokiStorageAPI.shared.getAllDevicePublicKeys(userHexEncodedPublicKey).get(setOf())