Added open group syncing.

Refactor open group adding code.
This commit is contained in:
Mikunj 2020-02-25 11:28:56 +11:00
parent ef2ceff0c1
commit 55523b3baf
9 changed files with 166 additions and 20 deletions

View File

@ -48,6 +48,7 @@ import org.thoughtcrime.securesms.jobs.TypingSendJob;
import org.thoughtcrime.securesms.linkpreview.LinkPreviewRepository;
import org.thoughtcrime.securesms.logging.Log;
import org.thoughtcrime.securesms.loki.LokiSessionResetImplementation;
import org.thoughtcrime.securesms.loki.MultiDeviceOpenGroupUpdateJob;
import org.thoughtcrime.securesms.loki.PushMessageSyncSendJob;
import org.thoughtcrime.securesms.preferences.AppProtectionPreferenceFragment;
import org.thoughtcrime.securesms.push.MessageSenderEventListener;
@ -115,7 +116,8 @@ import network.loki.messenger.BuildConfig;
MultiDeviceStickerPackOperationJob.class,
MultiDeviceStickerPackSyncJob.class,
LinkPreviewRepository.class,
PushMessageSyncSendJob.class})
PushMessageSyncSendJob.class,
MultiDeviceOpenGroupUpdateJob.class})
public class SignalCommunicationModule {

View File

@ -13,6 +13,7 @@ import org.thoughtcrime.securesms.jobmanager.impl.NetworkConstraintObserver;
import org.thoughtcrime.securesms.jobmanager.impl.NetworkOrCellServiceConstraint;
import org.thoughtcrime.securesms.jobmanager.impl.SqlCipherMigrationConstraint;
import org.thoughtcrime.securesms.jobmanager.impl.SqlCipherMigrationConstraintObserver;
import org.thoughtcrime.securesms.loki.MultiDeviceOpenGroupUpdateJob;
import org.thoughtcrime.securesms.loki.PushBackgroundMessageSendJob;
import org.thoughtcrime.securesms.loki.PushMessageSyncSendJob;
@ -74,6 +75,7 @@ public final class JobManagerFactories {
put(UpdateApkJob.KEY, new UpdateApkJob.Factory());
put(PushMessageSyncSendJob.KEY, new PushMessageSyncSendJob.Factory());
put(PushBackgroundMessageSendJob.KEY, new PushBackgroundMessageSendJob.Factory());
put(MultiDeviceOpenGroupUpdateJob.KEY, new MultiDeviceOpenGroupUpdateJob.Factory());
}};
}

View File

@ -59,6 +59,7 @@ import org.thoughtcrime.securesms.database.model.MmsMessageRecord;
import org.thoughtcrime.securesms.database.model.SmsMessageRecord;
import org.thoughtcrime.securesms.database.model.StickerRecord;
import org.thoughtcrime.securesms.dependencies.InjectableType;
import org.thoughtcrime.securesms.groups.GroupManager;
import org.thoughtcrime.securesms.groups.GroupMessageProcessor;
import org.thoughtcrime.securesms.jobmanager.Data;
import org.thoughtcrime.securesms.jobmanager.Job;
@ -72,6 +73,7 @@ import org.thoughtcrime.securesms.loki.LokiMessageDatabase;
import org.thoughtcrime.securesms.loki.LokiSessionResetImplementation;
import org.thoughtcrime.securesms.loki.LokiThreadDatabase;
import org.thoughtcrime.securesms.loki.MultiDeviceUtilities;
import org.thoughtcrime.securesms.loki.OpenGroupUtilities;
import org.thoughtcrime.securesms.loki.redesign.activities.HomeActivity;
import org.thoughtcrime.securesms.loki.redesign.messaging.LokiAPIUtilities;
import org.thoughtcrime.securesms.loki.redesign.messaging.LokiPreKeyBundleDatabase;
@ -138,6 +140,7 @@ import org.whispersystems.signalservice.loki.api.DeviceLink;
import org.whispersystems.signalservice.loki.api.DeviceLinkingSession;
import org.whispersystems.signalservice.loki.api.LokiAPI;
import org.whispersystems.signalservice.loki.api.LokiDeviceLinkUtilities;
import org.whispersystems.signalservice.loki.api.LokiPublicChat;
import org.whispersystems.signalservice.loki.crypto.LokiServiceCipher;
import org.whispersystems.signalservice.loki.messaging.LokiMessageFriendRequestStatus;
import org.whispersystems.signalservice.loki.messaging.LokiServiceMessage;
@ -393,6 +396,7 @@ public class PushDecryptJob extends BaseJob implements InjectableType {
else if (syncMessage.getStickerPackOperations().isPresent()) handleSynchronizeStickerPackOperation(syncMessage.getStickerPackOperations().get());
else if (syncMessage.getContacts().isPresent()) handleContactSyncMessage(syncMessage.getContacts().get());
else if (syncMessage.getGroups().isPresent()) handleGroupSyncMessage(content, syncMessage.getGroups().get());
else if (syncMessage.getOpenGroups().isPresent()) handleOpenGroupSyncMessage(syncMessage.getOpenGroups().get());
else Log.w(TAG, "Contains no known sync types...");
} else if (content.getCallMessage().isPresent()) {
Log.i(TAG, "Got call message...");
@ -749,6 +753,24 @@ public class PushDecryptJob extends BaseJob implements InjectableType {
}
}
private void handleOpenGroupSyncMessage(@NonNull List<LokiPublicChat> openGroups) {
try {
for (LokiPublicChat openGroup : openGroups) {
long threadID = GroupManager.getPublicChatThreadId(openGroup.getId(), context);
if (threadID > -1) continue;
String url = openGroup.getServer();
long channel = openGroup.getChannel();
OpenGroupUtilities.addGroup(context, url, channel).fail(e -> {
Log.d("Loki", "Failed to sync open group " + url + " due to error: " + e + ".");
return Unit.INSTANCE;
});
}
} catch (Exception e) {
Log.d("Loki", "Failed to sync open groups due to error: " + e + ".");
}
}
private void handleSynchronizeSentMessage(@NonNull SignalServiceContent content,
@NonNull SentTranscriptMessage message)
throws StorageFailedException

View File

@ -0,0 +1,83 @@
package org.thoughtcrime.securesms.loki
import org.thoughtcrime.securesms.crypto.UnidentifiedAccessUtil
import org.thoughtcrime.securesms.database.DatabaseFactory
import org.thoughtcrime.securesms.dependencies.InjectableType
import org.thoughtcrime.securesms.groups.GroupManager
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.thoughtcrime.securesms.util.TextSecurePreferences
import org.whispersystems.signalservice.api.SignalServiceMessageSender
import org.whispersystems.signalservice.api.messages.multidevice.SignalServiceSyncMessage
import org.whispersystems.signalservice.loki.api.LokiPublicChat
import java.util.concurrent.TimeUnit
import javax.inject.Inject
class MultiDeviceOpenGroupUpdateJob private constructor(parameters: Parameters) : BaseJob(parameters), InjectableType {
companion object {
const val KEY = "MultiDeviceGroupUpdateJob"
private val TAG = MultiDeviceOpenGroupUpdateJob::class.java.simpleName
}
@Inject
lateinit var messageSender: SignalServiceMessageSender
constructor() : this(Parameters.Builder()
.addConstraint(NetworkConstraint.KEY)
.setQueue("MultiDeviceGroupUpdateJob")
.setLifespan(TimeUnit.DAYS.toMillis(1))
.setMaxAttempts(Parameters.UNLIMITED)
.build())
override fun getFactoryKey(): String {
return KEY
}
override fun serialize(): Data {
return Data.EMPTY
}
@Throws(Exception::class)
public override fun onRun() {
if (!TextSecurePreferences.isMultiDevice(context)) {
Log.i(TAG, "Not multi device, aborting...")
return
}
val openGroups = mutableListOf<LokiPublicChat>()
DatabaseFactory.getGroupDatabase(context).groups.use { reader ->
while (true) {
val record = reader.next ?: return@use
if (!record.isPublicChat) { continue; }
val threadID = GroupManager.getThreadIdFromGroupId(record.encodedId, context)
val openGroup = DatabaseFactory.getLokiThreadDatabase(context).getPublicChat(threadID)
if (openGroup != null) {
openGroups.add(openGroup)
}
}
}
if (openGroups.size > 0) {
messageSender.sendMessage(0, SignalServiceSyncMessage.forOpenGroups(openGroups),
UnidentifiedAccessUtil.getAccessForSync(context))
} else {
Log.d(TAG, "No open groups to sync.")
}
}
public override fun onShouldRetry(exception: Exception): Boolean {
return false
}
override fun onCanceled() { }
class Factory : Job.Factory<MultiDeviceOpenGroupUpdateJob> {
override fun create(parameters: Parameters, data: Data): MultiDeviceOpenGroupUpdateJob {
return MultiDeviceOpenGroupUpdateJob(parameters)
}
}
}

View File

@ -0,0 +1,39 @@
package org.thoughtcrime.securesms.loki
import android.content.Context
import nl.komponents.kovenant.Promise
import nl.komponents.kovenant.then
import org.thoughtcrime.securesms.ApplicationContext
import org.thoughtcrime.securesms.crypto.ProfileKeyUtil
import org.thoughtcrime.securesms.database.DatabaseFactory
import org.thoughtcrime.securesms.groups.GroupManager
import org.thoughtcrime.securesms.util.TextSecurePreferences
import org.whispersystems.signalservice.loki.api.LokiPublicChat
object OpenGroupUtilities {
@JvmStatic fun addGroup(context: Context, url: String, channel: Long): Promise<LokiPublicChat, Exception> {
// Check if we have an existing group
val groupId = LokiPublicChat.getId(channel, url)
val threadID = GroupManager.getPublicChatThreadId(groupId, context)
val openGroup = DatabaseFactory.getLokiThreadDatabase(context).getPublicChat(threadID)
if (openGroup != null) {
return Promise.of(openGroup)
}
// Add the new group
val application = ApplicationContext.getInstance(context)
val displayName = TextSecurePreferences.getProfileName(context)
val lokiPublicChatAPI = application.lokiPublicChatAPI ?: throw Error("LokiPublicChatAPI is not initialized")
return application.lokiPublicChatManager.addChat(url, channel).then { group ->
DatabaseFactory.getLokiAPIDatabase(context).removeLastMessageServerID(channel, url)
DatabaseFactory.getLokiAPIDatabase(context).removeLastDeletionServerID(channel, url)
lokiPublicChatAPI.getMessages(channel, url)
lokiPublicChatAPI.setDisplayName(displayName, url)
lokiPublicChatAPI.join(channel, url)
val profileKey: ByteArray = ProfileKeyUtil.getProfileKey(context)
val profileUrl: String? = TextSecurePreferences.getProfileAvatarUrl(context)
lokiPublicChatAPI.setProfilePicture(url, profileKey, profileUrl)
group
}
}
}

View File

@ -16,14 +16,12 @@ import kotlinx.android.synthetic.main.fragment_enter_chat_url.*
import network.loki.messenger.R
import nl.komponents.kovenant.ui.failUi
import nl.komponents.kovenant.ui.successUi
import org.thoughtcrime.securesms.ApplicationContext
import org.thoughtcrime.securesms.BaseActionBarActivity
import org.thoughtcrime.securesms.PassphraseRequiredActionBarActivity
import org.thoughtcrime.securesms.crypto.ProfileKeyUtil
import org.thoughtcrime.securesms.database.DatabaseFactory
import org.thoughtcrime.securesms.loki.OpenGroupUtilities
import org.thoughtcrime.securesms.loki.redesign.fragments.ScanQRCodeWrapperFragment
import org.thoughtcrime.securesms.loki.redesign.fragments.ScanQRCodeWrapperFragmentDelegate
import org.thoughtcrime.securesms.util.TextSecurePreferences
import org.thoughtcrime.securesms.sms.MessageSender
class JoinPublicChatActivity : PassphraseRequiredActionBarActivity(), ScanQRCodeWrapperFragmentDelegate {
private val adapter = JoinPublicChatActivityAdapter(this)
@ -68,19 +66,11 @@ class JoinPublicChatActivity : PassphraseRequiredActionBarActivity(), ScanQRCode
return Toast.makeText(this, "Invalid URL", Toast.LENGTH_SHORT).show()
}
showLoader()
val application = ApplicationContext.getInstance(this)
val channel: Long = 1
val displayName = TextSecurePreferences.getProfileName(this)
val lokiPublicChatAPI = application.lokiPublicChatAPI!!
application.lokiPublicChatManager.addChat(url, channel).successUi {
DatabaseFactory.getLokiAPIDatabase(this).removeLastMessageServerID(channel, url)
DatabaseFactory.getLokiAPIDatabase(this).removeLastDeletionServerID(channel, url)
lokiPublicChatAPI.getMessages(channel, url)
lokiPublicChatAPI.setDisplayName(displayName, url)
lokiPublicChatAPI.join(channel, url)
val profileKey: ByteArray = ProfileKeyUtil.getProfileKey(this)
val profileUrl: String? = TextSecurePreferences.getProfileAvatarUrl(this)
lokiPublicChatAPI.setProfilePicture(url, profileKey, profileUrl)
OpenGroupUtilities.addGroup(this, url, channel).success {
MessageSender.syncAllOpenGroups(this)
}.successUi {
finish()
}.failUi {
hideLoader()

View File

@ -151,6 +151,7 @@ class LinkedDevicesActivity : PassphraseRequiredActionBarActivity, LoaderManager
Timer().schedule(4000) {
MessageSender.syncAllGroups(this@LinkedDevicesActivity)
MessageSender.syncAllContacts(this@LinkedDevicesActivity, Address.fromSerialized(deviceLink.slaveHexEncodedPublicKey))
MessageSender.syncAllOpenGroups(this@LinkedDevicesActivity)
}
}.failUi {
Toast.makeText(this, "Couldn't link device", Toast.LENGTH_LONG).show()

View File

@ -48,6 +48,7 @@ import org.thoughtcrime.securesms.logging.Log;
import org.thoughtcrime.securesms.loki.BackgroundMessage;
import org.thoughtcrime.securesms.loki.FriendRequestHandler;
import org.thoughtcrime.securesms.loki.GeneralUtilitiesKt;
import org.thoughtcrime.securesms.loki.MultiDeviceOpenGroupUpdateJob;
import org.thoughtcrime.securesms.loki.MultiDeviceUtilities;
import org.thoughtcrime.securesms.loki.PushBackgroundMessageSendJob;
import org.thoughtcrime.securesms.loki.PushMessageSyncSendJob;
@ -86,6 +87,10 @@ public class MessageSender {
ApplicationContext.getInstance(context).getJobManager().add(new MultiDeviceGroupUpdateJob());
}
public static void syncAllOpenGroups(Context context) {
ApplicationContext.getInstance(context).getJobManager().add(new MultiDeviceOpenGroupUpdateJob());
}
/**
* Send a contact sync message to all our devices telling them that we want to sync `contact`
*/

View File

@ -4,15 +4,13 @@ import android.content.Context;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.annotation.WorkerThread;
import android.widget.Toast;
import com.google.protobuf.ByteString;
import network.loki.messenger.R;
import org.thoughtcrime.securesms.database.Address;
import org.thoughtcrime.securesms.database.DatabaseFactory;
import org.thoughtcrime.securesms.database.GroupDatabase;
import org.thoughtcrime.securesms.database.GroupDatabase.*;
import org.thoughtcrime.securesms.database.GroupDatabase.GroupRecord;
import org.thoughtcrime.securesms.logging.Log;
import org.thoughtcrime.securesms.mms.OutgoingGroupMediaMessage;
import org.thoughtcrime.securesms.recipients.Recipient;
@ -26,6 +24,8 @@ import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import network.loki.messenger.R;
import static org.whispersystems.signalservice.internal.push.SignalServiceProtos.GroupContext;
public class GroupUtil {
@ -114,6 +114,8 @@ public class GroupUtil {
}
public static boolean leaveGroup(@NonNull Context context, Recipient groupRecipient) {
if (!groupRecipient.getAddress().isSignalGroup()) { return true; }
long threadId = DatabaseFactory.getThreadDatabase(context).getThreadIdFor(groupRecipient);
Optional<OutgoingGroupMediaMessage> leaveMessage = GroupUtil.createGroupLeaveMessage(context, groupRecipient);