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.
session-android/src/org/thoughtcrime/securesms/loki/protocol/MultiDeviceProtocol.kt

95 lines
5.1 KiB
Kotlin

package org.thoughtcrime.securesms.loki.protocol
import android.content.Context
import org.thoughtcrime.securesms.ApplicationContext
import org.thoughtcrime.securesms.database.Address
import org.thoughtcrime.securesms.database.DatabaseFactory
import org.thoughtcrime.securesms.jobs.PushMediaSendJob
import org.thoughtcrime.securesms.jobs.PushSendJob
import org.thoughtcrime.securesms.jobs.PushTextSendJob
import org.thoughtcrime.securesms.recipients.Recipient
import org.whispersystems.signalservice.loki.api.fileserver.LokiFileServerAPI
import org.whispersystems.signalservice.loki.protocol.meta.SessionMetaProtocol
import org.whispersystems.signalservice.loki.protocol.multidevice.MultiDeviceProtocol
import org.whispersystems.signalservice.loki.protocol.todo.LokiMessageFriendRequestStatus
import org.whispersystems.signalservice.loki.protocol.todo.LokiThreadFriendRequestStatus
object MultiDeviceProtocol {
@JvmStatic
fun sendUnlinkingRequest(context: Context, publicKey: String) {
val unlinkingRequest = EphemeralMessage.createUnlinkingRequest(publicKey)
ApplicationContext.getInstance(context).jobManager.add(PushEphemeralMessageSendJob(unlinkingRequest))
}
enum class MessageType { Text, Media }
@JvmStatic
fun sendTextPush(context: Context, recipient: Recipient, messageID: Long) {
}
@JvmStatic
fun sendMediaPush(context: Context, recipient: Recipient, messageID: Long) {
}
private fun sendMessagePushToDevice(context: Context, recipient: Recipient, messageID: Long, messageType: MessageType): PushSendJob {
val threadID = DatabaseFactory.getThreadDatabase(context).getThreadIdFor(recipient)
val threadFRStatus = DatabaseFactory.getLokiThreadDatabase(context).getFriendRequestStatus(threadID)
val isContactFriend = (threadFRStatus == LokiThreadFriendRequestStatus.FRIENDS)
val messageFRStatus = DatabaseFactory.getLokiMessageDatabase(context).getFriendRequestStatus(messageID)
val isFRMessage = (messageFRStatus != LokiMessageFriendRequestStatus.NONE)
val hasVisibleContent = when (messageType) {
MessageType.Text -> DatabaseFactory.getSmsDatabase(context).getMessage(messageID).body.isNotBlank()
MessageType.Media -> {
val outgoingMediaMessage = DatabaseFactory.getMmsDatabase(context).getOutgoingMessage(messageID)
outgoingMediaMessage.body.isNotBlank() || outgoingMediaMessage.attachments.isNotEmpty()
}
}
val shouldSendAutoGeneratedFR = !isContactFriend && !isFRMessage
&& !SessionMetaProtocol.shared.isNoteToSelf(recipient.address.serialize()) && !recipient.address.isGroup // Group threads work through session requests
&& hasVisibleContent
if (!shouldSendAutoGeneratedFR) {
when (messageType) {
MessageType.Text -> return PushTextSendJob(messageID, recipient.address)
MessageType.Media -> return PushMediaSendJob(messageID, recipient.address)
}
} else {
val autoGeneratedFRMessage = "Please accept to enable messages to be synced across devices"
when (messageType) {
MessageType.Text -> return PushTextSendJob(messageID, messageID, recipient.address, true, autoGeneratedFRMessage)
MessageType.Media -> return PushMediaSendJob(messageID, messageID, recipient.address, true, autoGeneratedFRMessage)
}
}
}
private fun sendMessagePush(context: Context, recipient: Recipient, messageID: Long, messageType: MessageType) {
val jobManager = ApplicationContext.getInstance(context).jobManager
val isMultiDeviceRequired = !recipient.address.isOpenGroup
if (!isMultiDeviceRequired) {
when (messageType) {
MessageType.Text -> jobManager.add(PushTextSendJob(messageID, recipient.address))
MessageType.Media -> PushMediaSendJob.enqueue(context, jobManager, messageID, recipient.address)
}
}
val publicKey = recipient.address.serialize()
LokiFileServerAPI.shared.getDeviceLinks(publicKey).success {
val devices = MultiDeviceProtocol.shared.getAllLinkedDevices(publicKey)
val jobs = devices.map { sendMessagePushToDevice(context, Recipient.from(context, Address.fromSerialized(it), false), messageID, messageType) }
@Suppress("UNCHECKED_CAST")
when (messageType) {
MessageType.Text -> jobManager.startChain(jobs).enqueue()
MessageType.Media -> PushMediaSendJob.enqueue(context, jobManager, jobs as List<PushMediaSendJob>)
}
}.fail { exception ->
// Proceed even if updating the recipient's device links failed, so that message sending
// is independent of whether the file server is online
when (messageType) {
MessageType.Text -> jobManager.add(PushTextSendJob(messageID, recipient.address))
MessageType.Media -> PushMediaSendJob.enqueue(context, jobManager, messageID, recipient.address)
}
}
}
}