Convert StorageSyncModels to kotlin.
This commit is contained in:
parent
89767cc260
commit
a79b4c3ba0
2 changed files with 311 additions and 347 deletions
|
@ -1,347 +0,0 @@
|
|||
package org.thoughtcrime.securesms.storage;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import com.annimon.stream.Stream;
|
||||
|
||||
import org.signal.libsignal.zkgroup.groups.GroupMasterKey;
|
||||
import org.thoughtcrime.securesms.components.settings.app.usernamelinks.UsernameQrCodeColorScheme;
|
||||
import org.thoughtcrime.securesms.database.CallLinkTable;
|
||||
import org.thoughtcrime.securesms.database.GroupTable;
|
||||
import org.thoughtcrime.securesms.database.IdentityTable;
|
||||
import org.thoughtcrime.securesms.database.RecipientTable;
|
||||
import org.thoughtcrime.securesms.database.SignalDatabase;
|
||||
import org.thoughtcrime.securesms.database.model.DistributionListId;
|
||||
import org.thoughtcrime.securesms.database.model.DistributionListRecord;
|
||||
import org.thoughtcrime.securesms.database.model.InAppPaymentSubscriberRecord;
|
||||
import org.thoughtcrime.securesms.database.model.RecipientRecord;
|
||||
import org.thoughtcrime.securesms.database.model.databaseprotos.InAppPaymentData;
|
||||
import org.thoughtcrime.securesms.groups.GroupId;
|
||||
import org.thoughtcrime.securesms.keyvalue.PhoneNumberPrivacyValues;
|
||||
import org.thoughtcrime.securesms.keyvalue.SignalStore;
|
||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||
import org.thoughtcrime.securesms.service.webrtc.links.CallLinkRoomId;
|
||||
import org.whispersystems.signalservice.api.push.SignalServiceAddress;
|
||||
import org.whispersystems.signalservice.api.storage.SignalAccountRecord;
|
||||
import org.whispersystems.signalservice.api.storage.SignalCallLinkRecord;
|
||||
import org.whispersystems.signalservice.api.storage.SignalContactRecord;
|
||||
import org.whispersystems.signalservice.api.storage.SignalGroupV1Record;
|
||||
import org.whispersystems.signalservice.api.storage.SignalGroupV2Record;
|
||||
import org.whispersystems.signalservice.api.storage.SignalStorageRecord;
|
||||
import org.whispersystems.signalservice.api.storage.SignalStoryDistributionListRecord;
|
||||
import org.whispersystems.signalservice.api.subscriptions.SubscriberId;
|
||||
import org.whispersystems.signalservice.api.util.UuidUtil;
|
||||
import org.whispersystems.signalservice.internal.storage.protos.AccountRecord;
|
||||
import org.whispersystems.signalservice.internal.storage.protos.ContactRecord.IdentityState;
|
||||
import org.whispersystems.signalservice.internal.storage.protos.GroupV2Record;
|
||||
|
||||
import java.util.Currency;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public final class StorageSyncModels {
|
||||
|
||||
private StorageSyncModels() {}
|
||||
|
||||
public static @NonNull SignalStorageRecord localToRemoteRecord(@NonNull RecipientRecord settings) {
|
||||
if (settings.getStorageId() == null) {
|
||||
throw new AssertionError("Must have a storage key!");
|
||||
}
|
||||
|
||||
return localToRemoteRecord(settings, settings.getStorageId());
|
||||
}
|
||||
|
||||
public static @NonNull SignalStorageRecord localToRemoteRecord(@NonNull RecipientRecord settings, @NonNull GroupMasterKey groupMasterKey) {
|
||||
if (settings.getStorageId() == null) {
|
||||
throw new AssertionError("Must have a storage key!");
|
||||
}
|
||||
|
||||
return SignalStorageRecord.forGroupV2(localToRemoteGroupV2(settings, settings.getStorageId(), groupMasterKey));
|
||||
}
|
||||
|
||||
public static @NonNull SignalStorageRecord localToRemoteRecord(@NonNull RecipientRecord settings, @NonNull byte[] rawStorageId) {
|
||||
switch (settings.getRecipientType()) {
|
||||
case INDIVIDUAL: return SignalStorageRecord.forContact(localToRemoteContact(settings, rawStorageId));
|
||||
case GV1: return SignalStorageRecord.forGroupV1(localToRemoteGroupV1(settings, rawStorageId));
|
||||
case GV2: return SignalStorageRecord.forGroupV2(localToRemoteGroupV2(settings, rawStorageId, settings.getSyncExtras().getGroupMasterKey()));
|
||||
case DISTRIBUTION_LIST: return SignalStorageRecord.forStoryDistributionList(localToRemoteStoryDistributionList(settings, rawStorageId));
|
||||
case CALL_LINK: return SignalStorageRecord.forCallLink(localToRemoteCallLink(settings, rawStorageId));
|
||||
default: throw new AssertionError("Unsupported type!");
|
||||
}
|
||||
}
|
||||
|
||||
public static AccountRecord.PhoneNumberSharingMode localToRemotePhoneNumberSharingMode(PhoneNumberPrivacyValues.PhoneNumberSharingMode phoneNumberPhoneNumberSharingMode) {
|
||||
switch (phoneNumberPhoneNumberSharingMode) {
|
||||
case DEFAULT : return AccountRecord.PhoneNumberSharingMode.NOBODY;
|
||||
case EVERYBODY: return AccountRecord.PhoneNumberSharingMode.EVERYBODY;
|
||||
case NOBODY : return AccountRecord.PhoneNumberSharingMode.NOBODY;
|
||||
default : throw new AssertionError();
|
||||
}
|
||||
}
|
||||
|
||||
public static PhoneNumberPrivacyValues.PhoneNumberSharingMode remoteToLocalPhoneNumberSharingMode(AccountRecord.PhoneNumberSharingMode phoneNumberPhoneNumberSharingMode) {
|
||||
switch (phoneNumberPhoneNumberSharingMode) {
|
||||
case EVERYBODY : return PhoneNumberPrivacyValues.PhoneNumberSharingMode.EVERYBODY;
|
||||
case NOBODY : return PhoneNumberPrivacyValues.PhoneNumberSharingMode.NOBODY;
|
||||
default : return PhoneNumberPrivacyValues.PhoneNumberSharingMode.DEFAULT;
|
||||
}
|
||||
}
|
||||
|
||||
public static List<SignalAccountRecord.PinnedConversation> localToRemotePinnedConversations(@NonNull List<RecipientRecord> settings) {
|
||||
return Stream.of(settings)
|
||||
.filter(s -> s.getRecipientType() == RecipientTable.RecipientType.GV1 ||
|
||||
s.getRecipientType() == RecipientTable.RecipientType.GV2 ||
|
||||
s.getRegistered() == RecipientTable.RegisteredState.REGISTERED)
|
||||
.map(StorageSyncModels::localToRemotePinnedConversation)
|
||||
.toList();
|
||||
}
|
||||
|
||||
private static @NonNull SignalAccountRecord.PinnedConversation localToRemotePinnedConversation(@NonNull RecipientRecord settings) {
|
||||
switch (settings.getRecipientType()) {
|
||||
case INDIVIDUAL: return SignalAccountRecord.PinnedConversation.forContact(new SignalServiceAddress(settings.getServiceId(), settings.getE164()));
|
||||
case GV1: return SignalAccountRecord.PinnedConversation.forGroupV1(settings.getGroupId().requireV1().getDecodedId());
|
||||
case GV2: return SignalAccountRecord.PinnedConversation.forGroupV2(settings.getSyncExtras().getGroupMasterKey().serialize());
|
||||
default : throw new AssertionError("Unexpected group type!");
|
||||
}
|
||||
}
|
||||
|
||||
public static @NonNull AccountRecord.UsernameLink.Color localToRemoteUsernameColor(UsernameQrCodeColorScheme local) {
|
||||
switch (local) {
|
||||
case Blue: return AccountRecord.UsernameLink.Color.BLUE;
|
||||
case White: return AccountRecord.UsernameLink.Color.WHITE;
|
||||
case Grey: return AccountRecord.UsernameLink.Color.GREY;
|
||||
case Tan: return AccountRecord.UsernameLink.Color.OLIVE;
|
||||
case Green: return AccountRecord.UsernameLink.Color.GREEN;
|
||||
case Orange: return AccountRecord.UsernameLink.Color.ORANGE;
|
||||
case Pink: return AccountRecord.UsernameLink.Color.PINK;
|
||||
case Purple: return AccountRecord.UsernameLink.Color.PURPLE;
|
||||
default: return AccountRecord.UsernameLink.Color.BLUE;
|
||||
}
|
||||
}
|
||||
|
||||
public static @NonNull UsernameQrCodeColorScheme remoteToLocalUsernameColor(AccountRecord.UsernameLink.Color remote) {
|
||||
switch (remote) {
|
||||
case BLUE: return UsernameQrCodeColorScheme.Blue;
|
||||
case WHITE: return UsernameQrCodeColorScheme.White;
|
||||
case GREY: return UsernameQrCodeColorScheme.Grey;
|
||||
case OLIVE: return UsernameQrCodeColorScheme.Tan;
|
||||
case GREEN: return UsernameQrCodeColorScheme.Green;
|
||||
case ORANGE: return UsernameQrCodeColorScheme.Orange;
|
||||
case PINK: return UsernameQrCodeColorScheme.Pink;
|
||||
case PURPLE: return UsernameQrCodeColorScheme.Purple;
|
||||
default: return UsernameQrCodeColorScheme.Blue;
|
||||
}
|
||||
}
|
||||
|
||||
private static @NonNull SignalContactRecord localToRemoteContact(@NonNull RecipientRecord recipient, byte[] rawStorageId) {
|
||||
if (recipient.getAci() == null && recipient.getPni() == null && recipient.getE164() == null) {
|
||||
throw new AssertionError("Must have either a UUID or a phone number!");
|
||||
}
|
||||
|
||||
boolean hideStory = recipient.getExtras() != null && recipient.getExtras().hideStory();
|
||||
|
||||
return new SignalContactRecord.Builder(rawStorageId, recipient.getAci(), recipient.getSyncExtras().getStorageProto())
|
||||
.setE164(recipient.getE164())
|
||||
.setPni(recipient.getPni())
|
||||
.setProfileKey(recipient.getProfileKey())
|
||||
.setProfileGivenName(recipient.getProfileName().getGivenName())
|
||||
.setProfileFamilyName(recipient.getProfileName().getFamilyName())
|
||||
.setSystemGivenName(recipient.getSystemProfileName().getGivenName())
|
||||
.setSystemFamilyName(recipient.getSystemProfileName().getFamilyName())
|
||||
.setSystemNickname(recipient.getSyncExtras().getSystemNickname())
|
||||
.setBlocked(recipient.isBlocked())
|
||||
.setProfileSharingEnabled(recipient.isProfileSharing() || recipient.getSystemContactUri() != null)
|
||||
.setIdentityKey(recipient.getSyncExtras().getIdentityKey())
|
||||
.setIdentityState(localToRemoteIdentityState(recipient.getSyncExtras().getIdentityStatus()))
|
||||
.setArchived(recipient.getSyncExtras().isArchived())
|
||||
.setForcedUnread(recipient.getSyncExtras().isForcedUnread())
|
||||
.setMuteUntil(recipient.getMuteUntil())
|
||||
.setHideStory(hideStory)
|
||||
.setUnregisteredTimestamp(recipient.getSyncExtras().getUnregisteredTimestamp())
|
||||
.setHidden(recipient.getHiddenState() != Recipient.HiddenState.NOT_HIDDEN)
|
||||
.setUsername(recipient.getUsername())
|
||||
.setPniSignatureVerified(recipient.getSyncExtras().getPniSignatureVerified())
|
||||
.setNicknameGivenName(recipient.getNickname().getGivenName())
|
||||
.setNicknameFamilyName(recipient.getNickname().getFamilyName())
|
||||
.setNote(recipient.getNote())
|
||||
.build();
|
||||
}
|
||||
|
||||
private static @NonNull SignalGroupV1Record localToRemoteGroupV1(@NonNull RecipientRecord recipient, byte[] rawStorageId) {
|
||||
GroupId groupId = recipient.getGroupId();
|
||||
|
||||
if (groupId == null) {
|
||||
throw new AssertionError("Must have a groupId!");
|
||||
}
|
||||
|
||||
if (!groupId.isV1()) {
|
||||
throw new AssertionError("Group is not V1");
|
||||
}
|
||||
|
||||
return new SignalGroupV1Record.Builder(rawStorageId, groupId.getDecodedId(), recipient.getSyncExtras().getStorageProto())
|
||||
.setBlocked(recipient.isBlocked())
|
||||
.setProfileSharingEnabled(recipient.isProfileSharing())
|
||||
.setArchived(recipient.getSyncExtras().isArchived())
|
||||
.setForcedUnread(recipient.getSyncExtras().isForcedUnread())
|
||||
.setMuteUntil(recipient.getMuteUntil())
|
||||
.build();
|
||||
}
|
||||
|
||||
private static @NonNull SignalGroupV2Record localToRemoteGroupV2(@NonNull RecipientRecord recipient, byte[] rawStorageId, @NonNull GroupMasterKey groupMasterKey) {
|
||||
GroupId groupId = recipient.getGroupId();
|
||||
|
||||
if (groupId == null) {
|
||||
throw new AssertionError("Must have a groupId!");
|
||||
}
|
||||
|
||||
if (!groupId.isV2()) {
|
||||
throw new AssertionError("Group is not V2");
|
||||
}
|
||||
|
||||
if (groupMasterKey == null) {
|
||||
throw new AssertionError("Group master key not on recipient record");
|
||||
}
|
||||
|
||||
boolean hideStory = recipient.getExtras() != null && recipient.getExtras().hideStory();
|
||||
GroupTable.ShowAsStoryState showAsStoryState = SignalDatabase.groups().getShowAsStoryState(groupId);
|
||||
GroupV2Record.StorySendMode storySendMode;
|
||||
|
||||
switch (showAsStoryState) {
|
||||
case ALWAYS:
|
||||
storySendMode = GroupV2Record.StorySendMode.ENABLED;
|
||||
break;
|
||||
case NEVER:
|
||||
storySendMode = GroupV2Record.StorySendMode.DISABLED;
|
||||
break;
|
||||
default:
|
||||
storySendMode = GroupV2Record.StorySendMode.DEFAULT;
|
||||
}
|
||||
|
||||
return new SignalGroupV2Record.Builder(rawStorageId, groupMasterKey, recipient.getSyncExtras().getStorageProto())
|
||||
.setBlocked(recipient.isBlocked())
|
||||
.setProfileSharingEnabled(recipient.isProfileSharing())
|
||||
.setArchived(recipient.getSyncExtras().isArchived())
|
||||
.setForcedUnread(recipient.getSyncExtras().isForcedUnread())
|
||||
.setMuteUntil(recipient.getMuteUntil())
|
||||
.setNotifyForMentionsWhenMuted(recipient.getMentionSetting() == RecipientTable.MentionSetting.ALWAYS_NOTIFY)
|
||||
.setHideStory(hideStory)
|
||||
.setStorySendMode(storySendMode)
|
||||
.build();
|
||||
}
|
||||
|
||||
private static @NonNull SignalCallLinkRecord localToRemoteCallLink(@NonNull RecipientRecord recipient, @NonNull byte[] rawStorageId) {
|
||||
CallLinkRoomId callLinkRoomId = recipient.getCallLinkRoomId();
|
||||
|
||||
if (callLinkRoomId == null) {
|
||||
throw new AssertionError("Must have a callLinkRoomId!");
|
||||
}
|
||||
|
||||
CallLinkTable.CallLink callLink = SignalDatabase.callLinks().getCallLinkByRoomId(callLinkRoomId);
|
||||
if (callLink == null) {
|
||||
throw new AssertionError("Must have a call link record!");
|
||||
}
|
||||
|
||||
if (callLink.getCredentials() == null) {
|
||||
throw new AssertionError("Must have call link credentials!");
|
||||
}
|
||||
|
||||
long deletedTimestamp = Math.max(0, SignalDatabase.callLinks().getDeletedTimestampByRoomId(callLinkRoomId));
|
||||
byte[] adminPassword = deletedTimestamp > 0 ? new byte[]{} : Objects.requireNonNull(callLink.getCredentials().getAdminPassBytes(), "Non-deleted call link requires admin pass!");
|
||||
|
||||
return new SignalCallLinkRecord.Builder(rawStorageId, null)
|
||||
.setRootKey(callLink.getCredentials().getLinkKeyBytes())
|
||||
.setAdminPassKey(adminPassword)
|
||||
.setDeletedTimestamp(deletedTimestamp)
|
||||
.build();
|
||||
}
|
||||
|
||||
private static @NonNull SignalStoryDistributionListRecord localToRemoteStoryDistributionList(@NonNull RecipientRecord recipient, @NonNull byte[] rawStorageId) {
|
||||
DistributionListId distributionListId = recipient.getDistributionListId();
|
||||
|
||||
if (distributionListId == null) {
|
||||
throw new AssertionError("Must have a distributionListId!");
|
||||
}
|
||||
|
||||
DistributionListRecord record = SignalDatabase.distributionLists().getListForStorageSync(distributionListId);
|
||||
if (record == null) {
|
||||
throw new AssertionError("Must have a distribution list record!");
|
||||
}
|
||||
|
||||
if (record.getDeletedAtTimestamp() > 0L) {
|
||||
return new SignalStoryDistributionListRecord.Builder(rawStorageId, recipient.getSyncExtras().getStorageProto())
|
||||
.setIdentifier(UuidUtil.toByteArray(record.getDistributionId().asUuid()))
|
||||
.setDeletedAtTimestamp(record.getDeletedAtTimestamp())
|
||||
.build();
|
||||
}
|
||||
|
||||
return new SignalStoryDistributionListRecord.Builder(rawStorageId, recipient.getSyncExtras().getStorageProto())
|
||||
.setIdentifier(UuidUtil.toByteArray(record.getDistributionId().asUuid()))
|
||||
.setName(record.getName())
|
||||
.setRecipients(record.getMembersToSync()
|
||||
.stream()
|
||||
.map(Recipient::resolved)
|
||||
.filter(Recipient::getHasServiceId)
|
||||
.map(Recipient::requireServiceId)
|
||||
.map(SignalServiceAddress::new)
|
||||
.collect(Collectors.toList()))
|
||||
.setAllowsReplies(record.getAllowsReplies())
|
||||
.setIsBlockList(record.getPrivacyMode().isBlockList())
|
||||
.build();
|
||||
}
|
||||
|
||||
public static @NonNull IdentityTable.VerifiedStatus remoteToLocalIdentityStatus(@NonNull IdentityState identityState) {
|
||||
switch (identityState) {
|
||||
case VERIFIED: return IdentityTable.VerifiedStatus.VERIFIED;
|
||||
case UNVERIFIED: return IdentityTable.VerifiedStatus.UNVERIFIED;
|
||||
default: return IdentityTable.VerifiedStatus.DEFAULT;
|
||||
}
|
||||
}
|
||||
|
||||
private static IdentityState localToRemoteIdentityState(@NonNull IdentityTable.VerifiedStatus local) {
|
||||
switch (local) {
|
||||
case VERIFIED: return IdentityState.VERIFIED;
|
||||
case UNVERIFIED: return IdentityState.UNVERIFIED;
|
||||
default: return IdentityState.DEFAULT;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* TODO - need to store the subscriber type
|
||||
*/
|
||||
public static @NonNull SignalAccountRecord.Subscriber localToRemoteSubscriber(@Nullable InAppPaymentSubscriberRecord subscriber) {
|
||||
if (subscriber == null) {
|
||||
return new SignalAccountRecord.Subscriber(null, null);
|
||||
} else {
|
||||
return new SignalAccountRecord.Subscriber(subscriber.getCurrency().getCurrencyCode(), subscriber.getSubscriberId().getBytes());
|
||||
}
|
||||
}
|
||||
|
||||
public static @Nullable InAppPaymentSubscriberRecord remoteToLocalSubscriber(
|
||||
@NonNull SignalAccountRecord.Subscriber subscriber,
|
||||
@NonNull InAppPaymentSubscriberRecord.Type type
|
||||
) {
|
||||
if (subscriber.getId().isPresent()) {
|
||||
SubscriberId subscriberId = SubscriberId.fromBytes(subscriber.getId().get());
|
||||
InAppPaymentSubscriberRecord localSubscriberRecord = SignalDatabase.inAppPaymentSubscribers().getBySubscriberId(subscriberId);
|
||||
boolean requiresCancel = localSubscriberRecord != null && localSubscriberRecord.getRequiresCancel();
|
||||
InAppPaymentData.PaymentMethodType paymentMethodType = localSubscriberRecord != null ? localSubscriberRecord.getPaymentMethodType() : InAppPaymentData.PaymentMethodType.UNKNOWN;
|
||||
|
||||
Currency currency;
|
||||
if (subscriber.getCurrencyCode().isEmpty()) {
|
||||
return null;
|
||||
} else {
|
||||
try {
|
||||
currency = Currency.getInstance(subscriber.getCurrencyCode().get());
|
||||
} catch (IllegalArgumentException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
return new InAppPaymentSubscriberRecord(subscriberId, currency, type, requiresCancel, paymentMethodType);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,311 @@
|
|||
package org.thoughtcrime.securesms.storage
|
||||
|
||||
import org.signal.libsignal.zkgroup.groups.GroupMasterKey
|
||||
import org.thoughtcrime.securesms.components.settings.app.usernamelinks.UsernameQrCodeColorScheme
|
||||
import org.thoughtcrime.securesms.database.GroupTable.ShowAsStoryState
|
||||
import org.thoughtcrime.securesms.database.IdentityTable.VerifiedStatus
|
||||
import org.thoughtcrime.securesms.database.RecipientTable
|
||||
import org.thoughtcrime.securesms.database.RecipientTable.RecipientType
|
||||
import org.thoughtcrime.securesms.database.SignalDatabase.Companion.callLinks
|
||||
import org.thoughtcrime.securesms.database.SignalDatabase.Companion.distributionLists
|
||||
import org.thoughtcrime.securesms.database.SignalDatabase.Companion.groups
|
||||
import org.thoughtcrime.securesms.database.SignalDatabase.Companion.inAppPaymentSubscribers
|
||||
import org.thoughtcrime.securesms.database.model.InAppPaymentSubscriberRecord
|
||||
import org.thoughtcrime.securesms.database.model.RecipientRecord
|
||||
import org.thoughtcrime.securesms.database.model.databaseprotos.InAppPaymentData
|
||||
import org.thoughtcrime.securesms.keyvalue.PhoneNumberPrivacyValues
|
||||
import org.thoughtcrime.securesms.recipients.Recipient
|
||||
import org.whispersystems.signalservice.api.push.SignalServiceAddress
|
||||
import org.whispersystems.signalservice.api.storage.SignalAccountRecord
|
||||
import org.whispersystems.signalservice.api.storage.SignalCallLinkRecord
|
||||
import org.whispersystems.signalservice.api.storage.SignalContactRecord
|
||||
import org.whispersystems.signalservice.api.storage.SignalGroupV1Record
|
||||
import org.whispersystems.signalservice.api.storage.SignalGroupV2Record
|
||||
import org.whispersystems.signalservice.api.storage.SignalStorageRecord
|
||||
import org.whispersystems.signalservice.api.storage.SignalStoryDistributionListRecord
|
||||
import org.whispersystems.signalservice.api.subscriptions.SubscriberId
|
||||
import org.whispersystems.signalservice.api.util.UuidUtil
|
||||
import org.whispersystems.signalservice.internal.storage.protos.AccountRecord
|
||||
import org.whispersystems.signalservice.internal.storage.protos.ContactRecord.IdentityState
|
||||
import org.whispersystems.signalservice.internal.storage.protos.GroupV2Record
|
||||
import java.util.Currency
|
||||
import kotlin.math.max
|
||||
|
||||
object StorageSyncModels {
|
||||
|
||||
@JvmStatic
|
||||
fun localToRemoteRecord(settings: RecipientRecord): SignalStorageRecord {
|
||||
if (settings.storageId == null) {
|
||||
throw AssertionError("Must have a storage key!")
|
||||
}
|
||||
|
||||
return localToRemoteRecord(settings, settings.storageId)
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun localToRemoteRecord(settings: RecipientRecord, groupMasterKey: GroupMasterKey): SignalStorageRecord {
|
||||
if (settings.storageId == null) {
|
||||
throw AssertionError("Must have a storage key!")
|
||||
}
|
||||
|
||||
return SignalStorageRecord.forGroupV2(localToRemoteGroupV2(settings, settings.storageId, groupMasterKey))
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun localToRemoteRecord(settings: RecipientRecord, rawStorageId: ByteArray): SignalStorageRecord {
|
||||
return when (settings.recipientType) {
|
||||
RecipientType.INDIVIDUAL -> SignalStorageRecord.forContact(localToRemoteContact(settings, rawStorageId))
|
||||
RecipientType.GV1 -> SignalStorageRecord.forGroupV1(localToRemoteGroupV1(settings, rawStorageId))
|
||||
RecipientType.GV2 -> SignalStorageRecord.forGroupV2(localToRemoteGroupV2(settings, rawStorageId, settings.syncExtras.groupMasterKey!!))
|
||||
RecipientType.DISTRIBUTION_LIST -> SignalStorageRecord.forStoryDistributionList(localToRemoteStoryDistributionList(settings, rawStorageId))
|
||||
RecipientType.CALL_LINK -> SignalStorageRecord.forCallLink(localToRemoteCallLink(settings, rawStorageId))
|
||||
else -> throw AssertionError("Unsupported type!")
|
||||
}
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun localToRemotePhoneNumberSharingMode(phoneNumberPhoneNumberSharingMode: PhoneNumberPrivacyValues.PhoneNumberSharingMode): AccountRecord.PhoneNumberSharingMode {
|
||||
return when (phoneNumberPhoneNumberSharingMode) {
|
||||
PhoneNumberPrivacyValues.PhoneNumberSharingMode.DEFAULT -> AccountRecord.PhoneNumberSharingMode.NOBODY
|
||||
PhoneNumberPrivacyValues.PhoneNumberSharingMode.EVERYBODY -> AccountRecord.PhoneNumberSharingMode.EVERYBODY
|
||||
PhoneNumberPrivacyValues.PhoneNumberSharingMode.NOBODY -> AccountRecord.PhoneNumberSharingMode.NOBODY
|
||||
}
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun remoteToLocalPhoneNumberSharingMode(phoneNumberPhoneNumberSharingMode: AccountRecord.PhoneNumberSharingMode): PhoneNumberPrivacyValues.PhoneNumberSharingMode {
|
||||
return when (phoneNumberPhoneNumberSharingMode) {
|
||||
AccountRecord.PhoneNumberSharingMode.EVERYBODY -> PhoneNumberPrivacyValues.PhoneNumberSharingMode.EVERYBODY
|
||||
AccountRecord.PhoneNumberSharingMode.NOBODY -> PhoneNumberPrivacyValues.PhoneNumberSharingMode.NOBODY
|
||||
else -> PhoneNumberPrivacyValues.PhoneNumberSharingMode.DEFAULT
|
||||
}
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun localToRemotePinnedConversations(records: List<RecipientRecord>): List<SignalAccountRecord.PinnedConversation> {
|
||||
return records
|
||||
.filter { it.recipientType == RecipientType.GV1 || it.recipientType == RecipientType.GV2 || it.registered == RecipientTable.RegisteredState.REGISTERED }
|
||||
.map { localToRemotePinnedConversation(it) }
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
private fun localToRemotePinnedConversation(settings: RecipientRecord): SignalAccountRecord.PinnedConversation {
|
||||
return when (settings.recipientType) {
|
||||
RecipientType.INDIVIDUAL -> SignalAccountRecord.PinnedConversation.forContact(SignalServiceAddress(settings.serviceId, settings.e164))
|
||||
RecipientType.GV1 -> SignalAccountRecord.PinnedConversation.forGroupV1(settings.groupId!!.requireV1().decodedId)
|
||||
RecipientType.GV2 -> SignalAccountRecord.PinnedConversation.forGroupV2(settings.syncExtras.groupMasterKey!!.serialize())
|
||||
else -> throw AssertionError("Unexpected group type!")
|
||||
}
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun localToRemoteUsernameColor(local: UsernameQrCodeColorScheme): AccountRecord.UsernameLink.Color {
|
||||
return when (local) {
|
||||
UsernameQrCodeColorScheme.Blue -> AccountRecord.UsernameLink.Color.BLUE
|
||||
UsernameQrCodeColorScheme.White -> AccountRecord.UsernameLink.Color.WHITE
|
||||
UsernameQrCodeColorScheme.Grey -> AccountRecord.UsernameLink.Color.GREY
|
||||
UsernameQrCodeColorScheme.Tan -> AccountRecord.UsernameLink.Color.OLIVE
|
||||
UsernameQrCodeColorScheme.Green -> AccountRecord.UsernameLink.Color.GREEN
|
||||
UsernameQrCodeColorScheme.Orange -> AccountRecord.UsernameLink.Color.ORANGE
|
||||
UsernameQrCodeColorScheme.Pink -> AccountRecord.UsernameLink.Color.PINK
|
||||
UsernameQrCodeColorScheme.Purple -> AccountRecord.UsernameLink.Color.PURPLE
|
||||
}
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun remoteToLocalUsernameColor(remote: AccountRecord.UsernameLink.Color): UsernameQrCodeColorScheme {
|
||||
return when (remote) {
|
||||
AccountRecord.UsernameLink.Color.BLUE -> UsernameQrCodeColorScheme.Blue
|
||||
AccountRecord.UsernameLink.Color.WHITE -> UsernameQrCodeColorScheme.White
|
||||
AccountRecord.UsernameLink.Color.GREY -> UsernameQrCodeColorScheme.Grey
|
||||
AccountRecord.UsernameLink.Color.OLIVE -> UsernameQrCodeColorScheme.Tan
|
||||
AccountRecord.UsernameLink.Color.GREEN -> UsernameQrCodeColorScheme.Green
|
||||
AccountRecord.UsernameLink.Color.ORANGE -> UsernameQrCodeColorScheme.Orange
|
||||
AccountRecord.UsernameLink.Color.PINK -> UsernameQrCodeColorScheme.Pink
|
||||
AccountRecord.UsernameLink.Color.PURPLE -> UsernameQrCodeColorScheme.Purple
|
||||
else -> UsernameQrCodeColorScheme.Blue
|
||||
}
|
||||
}
|
||||
|
||||
private fun localToRemoteContact(recipient: RecipientRecord, rawStorageId: ByteArray): SignalContactRecord {
|
||||
if (recipient.aci == null && recipient.pni == null && recipient.e164 == null) {
|
||||
throw AssertionError("Must have either a UUID or a phone number!")
|
||||
}
|
||||
|
||||
val hideStory = recipient.extras != null && recipient.extras.hideStory()
|
||||
|
||||
return SignalContactRecord.Builder(rawStorageId, recipient.aci, recipient.syncExtras.storageProto)
|
||||
.setE164(recipient.e164)
|
||||
.setPni(recipient.pni)
|
||||
.setProfileKey(recipient.profileKey)
|
||||
.setProfileGivenName(recipient.signalProfileName.givenName)
|
||||
.setProfileFamilyName(recipient.signalProfileName.familyName)
|
||||
.setSystemGivenName(recipient.systemProfileName.givenName)
|
||||
.setSystemFamilyName(recipient.systemProfileName.familyName)
|
||||
.setSystemNickname(recipient.syncExtras.systemNickname)
|
||||
.setBlocked(recipient.isBlocked)
|
||||
.setProfileSharingEnabled(recipient.profileSharing || recipient.systemContactUri != null)
|
||||
.setIdentityKey(recipient.syncExtras.identityKey)
|
||||
.setIdentityState(localToRemoteIdentityState(recipient.syncExtras.identityStatus))
|
||||
.setArchived(recipient.syncExtras.isArchived)
|
||||
.setForcedUnread(recipient.syncExtras.isForcedUnread)
|
||||
.setMuteUntil(recipient.muteUntil)
|
||||
.setHideStory(hideStory)
|
||||
.setUnregisteredTimestamp(recipient.syncExtras.unregisteredTimestamp)
|
||||
.setHidden(recipient.hiddenState != Recipient.HiddenState.NOT_HIDDEN)
|
||||
.setUsername(recipient.username)
|
||||
.setPniSignatureVerified(recipient.syncExtras.pniSignatureVerified)
|
||||
.setNicknameGivenName(recipient.nickname.givenName)
|
||||
.setNicknameFamilyName(recipient.nickname.familyName)
|
||||
.setNote(recipient.note)
|
||||
.build()
|
||||
}
|
||||
|
||||
private fun localToRemoteGroupV1(recipient: RecipientRecord, rawStorageId: ByteArray): SignalGroupV1Record {
|
||||
val groupId = recipient.groupId ?: throw AssertionError("Must have a groupId!")
|
||||
|
||||
if (!groupId.isV1) {
|
||||
throw AssertionError("Group is not V1")
|
||||
}
|
||||
|
||||
return SignalGroupV1Record.Builder(rawStorageId, groupId.decodedId, recipient.syncExtras.storageProto)
|
||||
.setBlocked(recipient.isBlocked)
|
||||
.setProfileSharingEnabled(recipient.profileSharing)
|
||||
.setArchived(recipient.syncExtras.isArchived)
|
||||
.setForcedUnread(recipient.syncExtras.isForcedUnread)
|
||||
.setMuteUntil(recipient.muteUntil)
|
||||
.build()
|
||||
}
|
||||
|
||||
private fun localToRemoteGroupV2(recipient: RecipientRecord, rawStorageId: ByteArray?, groupMasterKey: GroupMasterKey): SignalGroupV2Record {
|
||||
val groupId = recipient.groupId ?: throw AssertionError("Must have a groupId!")
|
||||
|
||||
if (!groupId.isV2) {
|
||||
throw AssertionError("Group is not V2")
|
||||
}
|
||||
|
||||
if (groupMasterKey == null) {
|
||||
throw AssertionError("Group master key not on recipient record")
|
||||
}
|
||||
|
||||
val hideStory = recipient.extras != null && recipient.extras.hideStory()
|
||||
val showAsStoryState = groups.getShowAsStoryState(groupId)
|
||||
|
||||
val storySendMode = when (showAsStoryState) {
|
||||
ShowAsStoryState.ALWAYS -> GroupV2Record.StorySendMode.ENABLED
|
||||
ShowAsStoryState.NEVER -> GroupV2Record.StorySendMode.DISABLED
|
||||
else -> GroupV2Record.StorySendMode.DEFAULT
|
||||
}
|
||||
|
||||
return SignalGroupV2Record.Builder(rawStorageId, groupMasterKey, recipient.syncExtras.storageProto)
|
||||
.setBlocked(recipient.isBlocked)
|
||||
.setProfileSharingEnabled(recipient.profileSharing)
|
||||
.setArchived(recipient.syncExtras.isArchived)
|
||||
.setForcedUnread(recipient.syncExtras.isForcedUnread)
|
||||
.setMuteUntil(recipient.muteUntil)
|
||||
.setNotifyForMentionsWhenMuted(recipient.mentionSetting == RecipientTable.MentionSetting.ALWAYS_NOTIFY)
|
||||
.setHideStory(hideStory)
|
||||
.setStorySendMode(storySendMode)
|
||||
.build()
|
||||
}
|
||||
|
||||
private fun localToRemoteCallLink(recipient: RecipientRecord, rawStorageId: ByteArray): SignalCallLinkRecord {
|
||||
val callLinkRoomId = recipient.callLinkRoomId ?: throw AssertionError("Must have a callLinkRoomId!")
|
||||
|
||||
val callLink = callLinks.getCallLinkByRoomId(callLinkRoomId) ?: throw AssertionError("Must have a call link record!")
|
||||
|
||||
if (callLink.credentials == null) {
|
||||
throw AssertionError("Must have call link credentials!")
|
||||
}
|
||||
|
||||
val deletedTimestamp = max(0.0, callLinks.getDeletedTimestampByRoomId(callLinkRoomId).toDouble()).toLong()
|
||||
val adminPassword = if (deletedTimestamp > 0) byteArrayOf() else callLink.credentials.adminPassBytes!!
|
||||
|
||||
return SignalCallLinkRecord.Builder(rawStorageId, null)
|
||||
.setRootKey(callLink.credentials.linkKeyBytes)
|
||||
.setAdminPassKey(adminPassword)
|
||||
.setDeletedTimestamp(deletedTimestamp)
|
||||
.build()
|
||||
}
|
||||
|
||||
private fun localToRemoteStoryDistributionList(recipient: RecipientRecord, rawStorageId: ByteArray): SignalStoryDistributionListRecord {
|
||||
val distributionListId = recipient.distributionListId ?: throw AssertionError("Must have a distributionListId!")
|
||||
|
||||
val record = distributionLists.getListForStorageSync(distributionListId) ?: throw AssertionError("Must have a distribution list record!")
|
||||
|
||||
if (record.deletedAtTimestamp > 0L) {
|
||||
return SignalStoryDistributionListRecord.Builder(rawStorageId, recipient.syncExtras.storageProto)
|
||||
.setIdentifier(UuidUtil.toByteArray(record.distributionId.asUuid()))
|
||||
.setDeletedAtTimestamp(record.deletedAtTimestamp)
|
||||
.build()
|
||||
}
|
||||
|
||||
return SignalStoryDistributionListRecord.Builder(rawStorageId, recipient.syncExtras.storageProto)
|
||||
.setIdentifier(UuidUtil.toByteArray(record.distributionId.asUuid()))
|
||||
.setName(record.name)
|
||||
.setRecipients(
|
||||
record.getMembersToSync()
|
||||
.map { Recipient.resolved(it) }
|
||||
.filter { it.hasServiceId }
|
||||
.map { it.requireServiceId() }
|
||||
.map { SignalServiceAddress(it) }
|
||||
)
|
||||
.setAllowsReplies(record.allowsReplies)
|
||||
.setIsBlockList(record.privacyMode.isBlockList)
|
||||
.build()
|
||||
}
|
||||
|
||||
fun remoteToLocalIdentityStatus(identityState: IdentityState): VerifiedStatus {
|
||||
return when (identityState) {
|
||||
IdentityState.VERIFIED -> VerifiedStatus.VERIFIED
|
||||
IdentityState.UNVERIFIED -> VerifiedStatus.UNVERIFIED
|
||||
else -> VerifiedStatus.DEFAULT
|
||||
}
|
||||
}
|
||||
|
||||
private fun localToRemoteIdentityState(local: VerifiedStatus): IdentityState {
|
||||
return when (local) {
|
||||
VerifiedStatus.VERIFIED -> IdentityState.VERIFIED
|
||||
VerifiedStatus.UNVERIFIED -> IdentityState.UNVERIFIED
|
||||
else -> IdentityState.DEFAULT
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* TODO - need to store the subscriber type
|
||||
*/
|
||||
fun localToRemoteSubscriber(subscriber: InAppPaymentSubscriberRecord?): SignalAccountRecord.Subscriber {
|
||||
return if (subscriber == null) {
|
||||
SignalAccountRecord.Subscriber(null, null)
|
||||
} else {
|
||||
SignalAccountRecord.Subscriber(subscriber.currency.currencyCode, subscriber.subscriberId.bytes)
|
||||
}
|
||||
}
|
||||
|
||||
fun remoteToLocalSubscriber(
|
||||
subscriber: SignalAccountRecord.Subscriber,
|
||||
type: InAppPaymentSubscriberRecord.Type
|
||||
): InAppPaymentSubscriberRecord? {
|
||||
if (subscriber.id.isPresent) {
|
||||
val subscriberId = SubscriberId.fromBytes(subscriber.id.get())
|
||||
val localSubscriberRecord = inAppPaymentSubscribers.getBySubscriberId(subscriberId)
|
||||
val requiresCancel = localSubscriberRecord != null && localSubscriberRecord.requiresCancel
|
||||
val paymentMethodType = localSubscriberRecord?.paymentMethodType ?: InAppPaymentData.PaymentMethodType.UNKNOWN
|
||||
|
||||
val currency: Currency
|
||||
if (subscriber.currencyCode.isEmpty) {
|
||||
return null
|
||||
} else {
|
||||
try {
|
||||
currency = Currency.getInstance(subscriber.currencyCode.get())
|
||||
} catch (e: IllegalArgumentException) {
|
||||
return null
|
||||
}
|
||||
}
|
||||
|
||||
return InAppPaymentSubscriberRecord(subscriberId, currency, type, requiresCancel, paymentMethodType)
|
||||
} else {
|
||||
return null
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Add table
Reference in a new issue