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(
84 IdentityInfo identity
,
87 final var address
= recipient
.getAddress();
88 final var builder
= new SignalContactRecord
.Builder(rawStorageId
,
89 address
.aci().orElse(null),
90 recipient
.getStorageRecord()).setE164(address
.number().orElse(null))
91 .setPni(address
.pni().orElse(null))
92 .setUsername(address
.username().orElse(null))
93 .setProfileKey(recipient
.getProfileKey() == null ?
null : recipient
.getProfileKey().serialize());
94 if (recipient
.getProfile() != null) {
95 builder
.setProfileGivenName(recipient
.getProfile().getGivenName())
96 .setProfileFamilyName(recipient
.getProfile().getFamilyName());
98 if (recipient
.getContact() != null) {
99 builder
.setSystemGivenName(recipient
.getContact().givenName())
100 .setSystemFamilyName(recipient
.getContact().familyName())
101 .setSystemNickname(recipient
.getContact().nickName())
102 .setNicknameGivenName(recipient
.getContact().nickNameGivenName() == null
104 : recipient
.getContact().nickNameGivenName())
105 .setNicknameFamilyName(recipient
.getContact().nickNameFamilyName() == null
107 : recipient
.getContact().nickNameFamilyName())
108 .setNote(recipient
.getContact().note())
109 .setBlocked(recipient
.getContact().isBlocked())
110 .setProfileSharingEnabled(recipient
.getContact().isProfileSharingEnabled())
111 .setMuteUntil(recipient
.getContact().muteUntil())
112 .setHideStory(recipient
.getContact().hideStory())
113 .setUnregisteredTimestamp(recipient
.getContact().unregisteredTimestamp() == null
115 : recipient
.getContact().unregisteredTimestamp())
116 .setArchived(recipient
.getContact().isArchived())
117 .setHidden(recipient
.getContact().isHidden());
119 if (identity
!= null) {
120 builder
.setIdentityKey(identity
.getIdentityKey().serialize())
121 .setIdentityState(localToRemote(identity
.getTrustLevel()));
123 return SignalStorageRecord
.forContact(builder
.build());
126 public static SignalStorageRecord
localToRemoteRecord(GroupInfoV1 group
, byte[] rawStorageId
) {
127 final var builder
= new SignalGroupV1Record
.Builder(rawStorageId
,
128 group
.getGroupId().serialize(),
129 group
.getStorageRecord());
130 builder
.setBlocked(group
.isBlocked());
131 builder
.setArchived(group
.archived
);
132 builder
.setProfileSharingEnabled(true);
133 return SignalStorageRecord
.forGroupV1(builder
.build());
136 public static SignalStorageRecord
localToRemoteRecord(GroupInfoV2 group
, byte[] rawStorageId
) {
137 final var builder
= new SignalGroupV2Record
.Builder(rawStorageId
,
138 group
.getMasterKey(),
139 group
.getStorageRecord());
140 builder
.setBlocked(group
.isBlocked());
141 builder
.setProfileSharingEnabled(group
.isProfileSharingEnabled());
142 return SignalStorageRecord
.forGroupV2(builder
.build());
145 public static TrustLevel
remoteToLocal(IdentityState identityState
) {
146 return switch (identityState
) {
147 case DEFAULT
-> TrustLevel
.TRUSTED_UNVERIFIED
;
148 case UNVERIFIED
-> TrustLevel
.UNTRUSTED
;
149 case VERIFIED
-> TrustLevel
.TRUSTED_VERIFIED
;
153 private static IdentityState
localToRemote(TrustLevel local
) {
154 return switch (local
) {
155 case TRUSTED_VERIFIED
-> IdentityState
.VERIFIED
;
156 case UNTRUSTED
-> IdentityState
.UNVERIFIED
;
157 default -> IdentityState
.DEFAULT
;