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() == null
102 : recipient
.getContact().nickNameGivenName())
103 .setNicknameFamilyName(recipient
.getContact().nickNameFamilyName() == null
105 : recipient
.getContact().nickNameFamilyName())
106 .setNote(recipient
.getContact().note())
107 .setBlocked(recipient
.getContact().isBlocked())
108 .setProfileSharingEnabled(recipient
.getContact().isProfileSharingEnabled())
109 .setMuteUntil(recipient
.getContact().muteUntil())
110 .setHideStory(recipient
.getContact().hideStory())
111 .setUnregisteredTimestamp(recipient
.getContact().unregisteredTimestamp() == null
113 : recipient
.getContact().unregisteredTimestamp())
114 .setArchived(recipient
.getContact().isArchived())
115 .setHidden(recipient
.getContact().isHidden());
117 if (identity
!= null) {
118 builder
.setIdentityKey(identity
.getIdentityKey().serialize())
119 .setIdentityState(localToRemote(identity
.getTrustLevel()));
121 return SignalStorageRecord
.forContact(builder
.build());
124 public static SignalStorageRecord
localToRemoteRecord(
125 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(
137 GroupInfoV2 group
, byte[] rawStorageId
139 final var builder
= new SignalGroupV2Record
.Builder(rawStorageId
,
140 group
.getMasterKey(),
141 group
.getStorageRecord());
142 builder
.setBlocked(group
.isBlocked());
143 builder
.setProfileSharingEnabled(group
.isProfileSharingEnabled());
144 return SignalStorageRecord
.forGroupV2(builder
.build());
147 public static TrustLevel
remoteToLocal(IdentityState identityState
) {
148 return switch (identityState
) {
149 case DEFAULT
-> TrustLevel
.TRUSTED_UNVERIFIED
;
150 case UNVERIFIED
-> TrustLevel
.UNTRUSTED
;
151 case VERIFIED
-> TrustLevel
.TRUSTED_VERIFIED
;
155 private static IdentityState
localToRemote(TrustLevel local
) {
156 return switch (local
) {
157 case TRUSTED_VERIFIED
-> IdentityState
.VERIFIED
;
158 case UNTRUSTED
-> IdentityState
.UNVERIFIED
;
159 default -> IdentityState
.DEFAULT
;