mirror of
https://github.com/oxen-io/session-android.git
synced 2025-02-26 07:47:21 +00:00
Add a job for sending a background message.
Send a friend request background message to other linked devices upon accepting a friend request.
This commit is contained in:
parent
9541588383
commit
55ecd3cae4
@ -13,6 +13,7 @@ import org.thoughtcrime.securesms.jobmanager.impl.NetworkConstraintObserver;
|
|||||||
import org.thoughtcrime.securesms.jobmanager.impl.NetworkOrCellServiceConstraint;
|
import org.thoughtcrime.securesms.jobmanager.impl.NetworkOrCellServiceConstraint;
|
||||||
import org.thoughtcrime.securesms.jobmanager.impl.SqlCipherMigrationConstraint;
|
import org.thoughtcrime.securesms.jobmanager.impl.SqlCipherMigrationConstraint;
|
||||||
import org.thoughtcrime.securesms.jobmanager.impl.SqlCipherMigrationConstraintObserver;
|
import org.thoughtcrime.securesms.jobmanager.impl.SqlCipherMigrationConstraintObserver;
|
||||||
|
import org.thoughtcrime.securesms.loki.PushBackgroundMessageSendJob;
|
||||||
import org.thoughtcrime.securesms.loki.PushMessageSyncSendJob;
|
import org.thoughtcrime.securesms.loki.PushMessageSyncSendJob;
|
||||||
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
@ -72,6 +73,7 @@ public final class JobManagerFactories {
|
|||||||
put(TypingSendJob.KEY, new TypingSendJob.Factory());
|
put(TypingSendJob.KEY, new TypingSendJob.Factory());
|
||||||
put(UpdateApkJob.KEY, new UpdateApkJob.Factory());
|
put(UpdateApkJob.KEY, new UpdateApkJob.Factory());
|
||||||
put(PushMessageSyncSendJob.KEY, new PushMessageSyncSendJob.Factory());
|
put(PushMessageSyncSendJob.KEY, new PushMessageSyncSendJob.Factory());
|
||||||
|
put(PushBackgroundMessageSendJob.KEY, new PushBackgroundMessageSendJob.Factory());
|
||||||
}};
|
}};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -652,9 +652,9 @@ public class PushDecryptJob extends BaseJob implements InjectableType {
|
|||||||
DeviceContactsInputStream contactsInputStream = new DeviceContactsInputStream(contactsMessage.getContactsStream().asStream().getInputStream());
|
DeviceContactsInputStream contactsInputStream = new DeviceContactsInputStream(contactsMessage.getContactsStream().asStream().getInputStream());
|
||||||
DeviceContact deviceContact = contactsInputStream.read();
|
DeviceContact deviceContact = contactsInputStream.read();
|
||||||
while (deviceContact != null) {
|
while (deviceContact != null) {
|
||||||
// Check if we have the contact as a friend
|
// Check if we have the contact as a friend and that we're not trying to sync our own device
|
||||||
Address address = Address.fromSerialized(deviceContact.getNumber());
|
Address address = Address.fromSerialized(deviceContact.getNumber());
|
||||||
if (!address.isPhone()) { continue; }
|
if (!address.isPhone() || address.toPhoneString().equalsIgnoreCase(TextSecurePreferences.getLocalNumber(context))) { continue; }
|
||||||
|
|
||||||
/*
|
/*
|
||||||
If we're not friends with the contact we received or our friend request expired then we should send them a friend request
|
If we're not friends with the contact we received or our friend request expired then we should send them a friend request
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
package org.thoughtcrime.securesms.loki
|
package org.thoughtcrime.securesms.loki
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
|
import android.os.Handler
|
||||||
import nl.komponents.kovenant.*
|
import nl.komponents.kovenant.*
|
||||||
import nl.komponents.kovenant.functional.bind
|
import nl.komponents.kovenant.functional.bind
|
||||||
import nl.komponents.kovenant.functional.map
|
import nl.komponents.kovenant.functional.map
|
||||||
@ -22,6 +23,8 @@ import org.whispersystems.signalservice.loki.api.PairingAuthorisation
|
|||||||
import org.whispersystems.signalservice.loki.messaging.LokiThreadFriendRequestStatus
|
import org.whispersystems.signalservice.loki.messaging.LokiThreadFriendRequestStatus
|
||||||
import org.whispersystems.signalservice.loki.utilities.recover
|
import org.whispersystems.signalservice.loki.utilities.recover
|
||||||
import org.whispersystems.signalservice.loki.utilities.retryIfNeeded
|
import org.whispersystems.signalservice.loki.utilities.retryIfNeeded
|
||||||
|
import java.util.*
|
||||||
|
import kotlin.concurrent.schedule
|
||||||
|
|
||||||
fun getAllDeviceFriendRequestStatuses(context: Context, hexEncodedPublicKey: String): Promise<Map<String, LokiThreadFriendRequestStatus>, Exception> {
|
fun getAllDeviceFriendRequestStatuses(context: Context, hexEncodedPublicKey: String): Promise<Map<String, LokiThreadFriendRequestStatus>, Exception> {
|
||||||
val lokiThreadDatabase = DatabaseFactory.getLokiThreadDatabase(context)
|
val lokiThreadDatabase = DatabaseFactory.getLokiThreadDatabase(context)
|
||||||
@ -128,8 +131,11 @@ fun signAndSendPairingAuthorisationMessage(context: Context, pairingAuthorisatio
|
|||||||
// If both promises complete successfully then we should sync our contacts
|
// If both promises complete successfully then we should sync our contacts
|
||||||
all(listOf(sendPromise, updatePromise), cancelOthersOnError = false).success {
|
all(listOf(sendPromise, updatePromise), cancelOthersOnError = false).success {
|
||||||
Log.d("Loki", "Successfully pairing with a secondary device! Syncing contacts.")
|
Log.d("Loki", "Successfully pairing with a secondary device! Syncing contacts.")
|
||||||
|
// Send out sync contact after a delay
|
||||||
|
Timer().schedule(3000) {
|
||||||
MessageSender.syncAllContacts(context)
|
MessageSender.syncAllContacts(context)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun isOneOfOurDevices(context: Context, address: Address): Promise<Boolean, Exception> {
|
fun isOneOfOurDevices(context: Context, address: Address): Promise<Boolean, Exception> {
|
||||||
|
@ -0,0 +1,98 @@
|
|||||||
|
package org.thoughtcrime.securesms.loki
|
||||||
|
|
||||||
|
import org.thoughtcrime.securesms.ApplicationContext
|
||||||
|
import org.thoughtcrime.securesms.database.DatabaseFactory
|
||||||
|
import org.thoughtcrime.securesms.dependencies.InjectableType
|
||||||
|
import org.thoughtcrime.securesms.jobmanager.Data
|
||||||
|
import org.thoughtcrime.securesms.jobmanager.Job
|
||||||
|
import org.thoughtcrime.securesms.jobmanager.impl.NetworkConstraint
|
||||||
|
import org.thoughtcrime.securesms.jobs.BaseJob
|
||||||
|
import org.thoughtcrime.securesms.logging.Log
|
||||||
|
import org.whispersystems.libsignal.util.guava.Optional
|
||||||
|
import org.whispersystems.signalservice.api.SignalServiceMessageSender
|
||||||
|
import org.whispersystems.signalservice.api.crypto.UnidentifiedAccessPair
|
||||||
|
import org.whispersystems.signalservice.api.crypto.UntrustedIdentityException
|
||||||
|
import org.whispersystems.signalservice.api.messages.SignalServiceDataMessage
|
||||||
|
import org.whispersystems.signalservice.api.push.SignalServiceAddress
|
||||||
|
import java.io.IOException
|
||||||
|
import java.util.concurrent.TimeUnit
|
||||||
|
import javax.inject.Inject
|
||||||
|
|
||||||
|
class PushBackgroundMessageSendJob private constructor(
|
||||||
|
parameters: Parameters,
|
||||||
|
private val recipient: String,
|
||||||
|
private val messageBody: String?,
|
||||||
|
private val friendRequest: Boolean
|
||||||
|
) : BaseJob(parameters) {
|
||||||
|
companion object {
|
||||||
|
const val KEY = "PushBackgroundMessageSendJob"
|
||||||
|
|
||||||
|
private val TAG = PushBackgroundMessageSendJob::class.java.simpleName
|
||||||
|
|
||||||
|
private val KEY_RECIPIENT = "recipient"
|
||||||
|
private val KEY_MESSAGE_BODY = "message_body"
|
||||||
|
private val KEY_FRIEND_REQUEST = "asFriendRequest"
|
||||||
|
}
|
||||||
|
|
||||||
|
constructor(recipient: String): this(recipient, null, false)
|
||||||
|
constructor(recipient: String, messageBody: String?, friendRequest: Boolean) : this(Parameters.Builder()
|
||||||
|
.addConstraint(NetworkConstraint.KEY)
|
||||||
|
.setQueue(KEY)
|
||||||
|
.setLifespan(TimeUnit.DAYS.toMillis(1))
|
||||||
|
.setMaxAttempts(1)
|
||||||
|
.build(),
|
||||||
|
recipient, messageBody, friendRequest)
|
||||||
|
|
||||||
|
override fun serialize(): Data {
|
||||||
|
return Data.Builder()
|
||||||
|
.putString(KEY_RECIPIENT, recipient)
|
||||||
|
.putString(KEY_MESSAGE_BODY, messageBody)
|
||||||
|
.putBoolean(KEY_FRIEND_REQUEST, friendRequest)
|
||||||
|
.build()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getFactoryKey(): String {
|
||||||
|
return KEY
|
||||||
|
}
|
||||||
|
|
||||||
|
public override fun onRun() {
|
||||||
|
val message = SignalServiceDataMessage.newBuilder()
|
||||||
|
.withTimestamp(System.currentTimeMillis())
|
||||||
|
.withBody(messageBody)
|
||||||
|
|
||||||
|
if (friendRequest) {
|
||||||
|
val bundle = DatabaseFactory.getLokiPreKeyBundleDatabase(context).generatePreKeyBundle(recipient)
|
||||||
|
message.withPreKeyBundle(bundle)
|
||||||
|
.asFriendRequest(true)
|
||||||
|
}
|
||||||
|
|
||||||
|
val messageSender = ApplicationContext.getInstance(context).communicationModule.provideSignalMessageSender()
|
||||||
|
val address = SignalServiceAddress(recipient)
|
||||||
|
try {
|
||||||
|
messageSender.sendMessage(-1, address, Optional.absent<UnidentifiedAccessPair>(), message.build()) // The message ID doesn't matter
|
||||||
|
} catch (e: Exception) {
|
||||||
|
Log.d("Loki", "Failed to send background message to: $recipient.")
|
||||||
|
throw e
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override fun onShouldRetry(e: Exception): Boolean {
|
||||||
|
// Loki - Disable since we have our own retrying when sending messages
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onCanceled() {}
|
||||||
|
|
||||||
|
class Factory : Job.Factory<PushBackgroundMessageSendJob> {
|
||||||
|
override fun create(parameters: Parameters, data: Data): PushBackgroundMessageSendJob {
|
||||||
|
try {
|
||||||
|
val recipient = data.getString(KEY_RECIPIENT)
|
||||||
|
val messageBody = if (data.hasString(KEY_MESSAGE_BODY)) data.getString(KEY_MESSAGE_BODY) else null
|
||||||
|
val friendRequest = data.getBooleanOrDefault(KEY_FRIEND_REQUEST, false)
|
||||||
|
return PushBackgroundMessageSendJob(parameters, recipient, messageBody, friendRequest)
|
||||||
|
} catch (e: IOException) {
|
||||||
|
throw AssertionError(e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -41,7 +41,7 @@ class PushMessageSyncSendJob private constructor(
|
|||||||
.addConstraint(NetworkConstraint.KEY)
|
.addConstraint(NetworkConstraint.KEY)
|
||||||
.setQueue(KEY)
|
.setQueue(KEY)
|
||||||
.setLifespan(TimeUnit.DAYS.toMillis(1))
|
.setLifespan(TimeUnit.DAYS.toMillis(1))
|
||||||
.setMaxAttempts(3)
|
.setMaxAttempts(1)
|
||||||
.build(),
|
.build(),
|
||||||
messageID, recipient, timestamp, message, ttl)
|
messageID, recipient, timestamp, message, ttl)
|
||||||
|
|
||||||
|
@ -17,6 +17,7 @@
|
|||||||
package org.thoughtcrime.securesms.sms;
|
package org.thoughtcrime.securesms.sms;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
import android.os.AsyncTask;
|
||||||
import android.support.annotation.NonNull;
|
import android.support.annotation.NonNull;
|
||||||
import android.support.annotation.Nullable;
|
import android.support.annotation.Nullable;
|
||||||
|
|
||||||
@ -47,6 +48,7 @@ import org.thoughtcrime.securesms.logging.Log;
|
|||||||
import org.thoughtcrime.securesms.loki.FriendRequestHandler;
|
import org.thoughtcrime.securesms.loki.FriendRequestHandler;
|
||||||
import org.thoughtcrime.securesms.loki.GeneralUtilitiesKt;
|
import org.thoughtcrime.securesms.loki.GeneralUtilitiesKt;
|
||||||
import org.thoughtcrime.securesms.loki.MultiDeviceUtilities;
|
import org.thoughtcrime.securesms.loki.MultiDeviceUtilities;
|
||||||
|
import org.thoughtcrime.securesms.loki.PushBackgroundMessageSendJob;
|
||||||
import org.thoughtcrime.securesms.loki.PushMessageSyncSendJob;
|
import org.thoughtcrime.securesms.loki.PushMessageSyncSendJob;
|
||||||
import org.thoughtcrime.securesms.mms.MmsException;
|
import org.thoughtcrime.securesms.mms.MmsException;
|
||||||
import org.thoughtcrime.securesms.mms.OutgoingMediaMessage;
|
import org.thoughtcrime.securesms.mms.OutgoingMediaMessage;
|
||||||
@ -110,9 +112,10 @@ public class MessageSender {
|
|||||||
long threadID = DatabaseFactory.getThreadDatabase(context).getThreadIdIfExistsFor(recipient);
|
long threadID = DatabaseFactory.getThreadDatabase(context).getThreadIdIfExistsFor(recipient);
|
||||||
if (threadID < 0) { continue; }
|
if (threadID < 0) { continue; }
|
||||||
LokiThreadFriendRequestStatus friendRequestStatus = DatabaseFactory.getLokiThreadDatabase(context).getFriendRequestStatus(threadID);
|
LokiThreadFriendRequestStatus friendRequestStatus = DatabaseFactory.getLokiThreadDatabase(context).getFriendRequestStatus(threadID);
|
||||||
// TODO: Do we want to send a bg message regardless of FR status? OR do we want to send a custom FR to those we are not friends with
|
|
||||||
if (friendRequestStatus == LokiThreadFriendRequestStatus.FRIENDS || friendRequestStatus == LokiThreadFriendRequestStatus.REQUEST_RECEIVED) {
|
if (friendRequestStatus == LokiThreadFriendRequestStatus.FRIENDS || friendRequestStatus == LokiThreadFriendRequestStatus.REQUEST_RECEIVED) {
|
||||||
sendBackgroundMessage(context, device);
|
sendBackgroundMessage(context, device);
|
||||||
|
} else if (friendRequestStatus == LokiThreadFriendRequestStatus.NONE || friendRequestStatus == LokiThreadFriendRequestStatus.REQUEST_EXPIRED) {
|
||||||
|
sendBackgroundFriendRequest(context, device, "This is a friend request from android! please replace this message in the future");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -120,34 +123,18 @@ public class MessageSender {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// region Background message
|
||||||
|
|
||||||
|
// We don't call the message sender here directly and instead we just opt to create a specific job for the send
|
||||||
|
// This is because calling message sender directly would cause the application to freeze in some cases as it was blocking the thread when waiting for a response from the send
|
||||||
public static void sendBackgroundMessage(Context context, String contactHexEncodedPublicKey) {
|
public static void sendBackgroundMessage(Context context, String contactHexEncodedPublicKey) {
|
||||||
SignalServiceDataMessage message = new SignalServiceDataMessage(System.currentTimeMillis(), null);
|
ApplicationContext.getInstance(context).getJobManager().add(new PushBackgroundMessageSendJob(contactHexEncodedPublicKey));
|
||||||
sendMessage(context, contactHexEncodedPublicKey, message);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void sendBackgroundFriendRequest(Context context, String contactHexEncodedPublicKey, String messageBody) {
|
public static void sendBackgroundFriendRequest(Context context, String contactHexEncodedPublicKey, String messageBody) {
|
||||||
PreKeyBundle bundle = DatabaseFactory.getLokiPreKeyBundleDatabase(context).generatePreKeyBundle(contactHexEncodedPublicKey);
|
ApplicationContext.getInstance(context).getJobManager().add(new PushBackgroundMessageSendJob(contactHexEncodedPublicKey, messageBody, true));
|
||||||
SignalServiceDataMessage message = SignalServiceDataMessage.newBuilder()
|
|
||||||
.withTimestamp(System.currentTimeMillis())
|
|
||||||
.withBody(messageBody)
|
|
||||||
.asFriendRequest(true)
|
|
||||||
.withPreKeyBundle(bundle)
|
|
||||||
.build();
|
|
||||||
sendMessage(context, contactHexEncodedPublicKey, message);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void sendMessage(Context context, String contactHexEncodedPublicKey, SignalServiceDataMessage message) {
|
|
||||||
Util.runOnMain(() -> {
|
|
||||||
SignalServiceMessageSender messageSender = ApplicationContext.getInstance(context).communicationModule.provideSignalMessageSender();
|
|
||||||
SignalServiceAddress address = new SignalServiceAddress(contactHexEncodedPublicKey);
|
|
||||||
try {
|
|
||||||
// Try send to the original person
|
|
||||||
messageSender.sendMessage(-1, address, Optional.absent(), message); // The message ID doesn't matter
|
|
||||||
} catch (Exception e) {
|
|
||||||
Log.d("Loki", "Failed to send background message to: " + contactHexEncodedPublicKey + ".");
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
// endregion
|
||||||
|
|
||||||
public static long send(final Context context,
|
public static long send(final Context context,
|
||||||
final OutgoingTextMessage message,
|
final OutgoingTextMessage message,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user