1 package org
.asamk
.signal
.manager
.syncStorage
;
3 import org
.asamk
.signal
.manager
.api
.PhoneNumberSharingMode
;
4 import org
.asamk
.signal
.manager
.api
.TrustLevel
;
5 import org
.asamk
.signal
.manager
.storage
.configuration
.ConfigurationStore
;
6 import org
.asamk
.signal
.manager
.storage
.groups
.GroupInfoV1
;
7 import org
.asamk
.signal
.manager
.storage
.groups
.GroupInfoV2
;
8 import org
.asamk
.signal
.manager
.storage
.identities
.IdentityInfo
;
9 import org
.asamk
.signal
.manager
.storage
.recipients
.Recipient
;
10 import org
.whispersystems
.signalservice
.api
.push
.UsernameLinkComponents
;
11 import org
.whispersystems
.signalservice
.api
.storage
.SignalAccountRecord
;
12 import org
.whispersystems
.signalservice
.api
.storage
.SignalContactRecord
;
13 import org
.whispersystems
.signalservice
.api
.storage
.SignalGroupV1Record
;
14 import org
.whispersystems
.signalservice
.api
.storage
.SignalGroupV2Record
;
15 import org
.whispersystems
.signalservice
.api
.storage
.SignalStorageRecord
;
16 import org
.whispersystems
.signalservice
.api
.util
.UuidUtil
;
17 import org
.whispersystems
.signalservice
.internal
.storage
.protos
.AccountRecord
;
18 import org
.whispersystems
.signalservice
.internal
.storage
.protos
.AccountRecord
.UsernameLink
;
19 import org
.whispersystems
.signalservice
.internal
.storage
.protos
.ContactRecord
.IdentityState
;
21 import java
.util
.Optional
;
23 import okio
.ByteString
;
25 public final class StorageSyncModels
{
27 private StorageSyncModels() {
30 public static AccountRecord
.PhoneNumberSharingMode
localToRemote(PhoneNumberSharingMode phoneNumberPhoneNumberSharingMode
) {
31 return switch (phoneNumberPhoneNumberSharingMode
) {
32 case EVERYBODY
-> AccountRecord
.PhoneNumberSharingMode
.EVERYBODY
;
33 case CONTACTS
, NOBODY
-> AccountRecord
.PhoneNumberSharingMode
.NOBODY
;
37 public static PhoneNumberSharingMode
remoteToLocal(AccountRecord
.PhoneNumberSharingMode phoneNumberPhoneNumberSharingMode
) {
38 return switch (phoneNumberPhoneNumberSharingMode
) {
39 case EVERYBODY
-> PhoneNumberSharingMode
.EVERYBODY
;
40 case NOBODY
-> PhoneNumberSharingMode
.NOBODY
;
45 public static SignalStorageRecord
localToRemoteRecord(
46 ConfigurationStore configStore
,
48 UsernameLinkComponents usernameLinkComponents
,
51 final var builder
= new SignalAccountRecord
.Builder(rawStorageId
, self
.getStorageRecord());
52 if (self
.getProfileKey() != null) {
53 builder
.setProfileKey(self
.getProfileKey().serialize());
55 if (self
.getProfile() != null) {
56 builder
.setGivenName(self
.getProfile().getGivenName())
57 .setFamilyName(self
.getProfile().getFamilyName())
58 .setAvatarUrlPath(self
.getProfile().getAvatarUrlPath());
60 builder
.setTypingIndicatorsEnabled(Optional
.ofNullable(configStore
.getTypingIndicators()).orElse(true))
61 .setReadReceiptsEnabled(Optional
.ofNullable(configStore
.getReadReceipts()).orElse(true))
62 .setSealedSenderIndicatorsEnabled(Optional
.ofNullable(configStore
.getUnidentifiedDeliveryIndicators())
64 .setLinkPreviewsEnabled(Optional
.ofNullable(configStore
.getLinkPreviews()).orElse(true))
65 .setUnlistedPhoneNumber(Optional
.ofNullable(configStore
.getPhoneNumberUnlisted()).orElse(false))
66 .setPhoneNumberSharingMode(Optional
.ofNullable(configStore
.getPhoneNumberSharingMode())
67 .map(StorageSyncModels
::localToRemote
)
68 .orElse(AccountRecord
.PhoneNumberSharingMode
.UNKNOWN
))
69 .setE164(self
.getAddress().number().orElse(""))
70 .setUsername(self
.getAddress().username().orElse(null));
71 if (usernameLinkComponents
!= null) {
72 final var linkColor
= configStore
.getUsernameLinkColor();
73 builder
.setUsernameLink(new UsernameLink
.Builder().entropy(ByteString
.of(usernameLinkComponents
.getEntropy()))
74 .serverId(UuidUtil
.toByteString(usernameLinkComponents
.getServerId()))
75 .color(linkColor
== null ? UsernameLink
.Color
.UNKNOWN
: UsernameLink
.Color
.valueOf(linkColor
))
79 return SignalStorageRecord
.forAccount(builder
.build());
82 public static SignalStorageRecord
localToRemoteRecord(
83 Recipient recipient
, IdentityInfo identity
, byte[] rawStorageId
85 final var address
= recipient
.getAddress();
86 final var builder
= new SignalContactRecord
.Builder(rawStorageId
,
87 address
.aci().orElse(null),
88 recipient
.getStorageRecord()).setE164(address
.number().orElse(null))
89 .setPni(address
.pni().orElse(null))
90 .setUsername(address
.username().orElse(null))
91 .setProfileKey(recipient
.getProfileKey() == null ?
null : recipient
.getProfileKey().serialize());
92 if (recipient
.getProfile() != null) {
93 builder
.setProfileGivenName(recipient
.getProfile().getGivenName())
94 .setProfileFamilyName(recipient
.getProfile().getFamilyName());
96 if (recipient
.getContact() != null) {
97 builder
.setSystemGivenName(recipient
.getContact().givenName())
98 .setSystemFamilyName(recipient
.getContact().familyName())
99 .setSystemNickname(recipient
.getContact().nickName())
100 .setNicknameGivenName(recipient
.getContact().nickNameGivenName())
101 .setNicknameFamilyName(recipient
.getContact().nickNameFamilyName())
102 .setNote(recipient
.getContact().note())
103 .setBlocked(recipient
.getContact().isBlocked())
104 .setProfileSharingEnabled(recipient
.getContact().isProfileSharingEnabled())
105 .setMuteUntil(recipient
.getContact().muteUntil())
106 .setHideStory(recipient
.getContact().hideStory())
107 .setUnregisteredTimestamp(recipient
.getContact().unregisteredTimestamp() == null
109 : recipient
.getContact().unregisteredTimestamp())
110 .setArchived(recipient
.getContact().isArchived())
111 .setHidden(recipient
.getContact().isHidden());
113 if (identity
!= null) {
114 builder
.setIdentityKey(identity
.getIdentityKey().serialize())
115 .setIdentityState(localToRemote(identity
.getTrustLevel()));
117 return SignalStorageRecord
.forContact(builder
.build());
120 public static SignalStorageRecord
localToRemoteRecord(
121 GroupInfoV1 group
, byte[] rawStorageId
123 final var builder
= new SignalGroupV1Record
.Builder(rawStorageId
,
124 group
.getGroupId().serialize(),
125 group
.getStorageRecord());
126 builder
.setBlocked(group
.isBlocked());
127 builder
.setArchived(group
.archived
);
128 builder
.setProfileSharingEnabled(true);
129 return SignalStorageRecord
.forGroupV1(builder
.build());
132 public static SignalStorageRecord
localToRemoteRecord(
133 GroupInfoV2 group
, byte[] rawStorageId
135 final var builder
= new SignalGroupV2Record
.Builder(rawStorageId
,
136 group
.getMasterKey(),
137 group
.getStorageRecord());
138 builder
.setBlocked(group
.isBlocked());
139 builder
.setProfileSharingEnabled(group
.isProfileSharingEnabled());
140 return SignalStorageRecord
.forGroupV2(builder
.build());
143 public static TrustLevel
remoteToLocal(IdentityState identityState
) {
144 return switch (identityState
) {
145 case DEFAULT
-> TrustLevel
.TRUSTED_UNVERIFIED
;
146 case UNVERIFIED
-> TrustLevel
.UNTRUSTED
;
147 case VERIFIED
-> TrustLevel
.TRUSTED_VERIFIED
;
151 private static IdentityState
localToRemote(TrustLevel local
) {
152 return switch (local
) {
153 case TRUSTED_VERIFIED
-> IdentityState
.VERIFIED
;
154 case UNTRUSTED
-> IdentityState
.UNVERIFIED
;
155 default -> IdentityState
.DEFAULT
;