]> nmode's Git Repositories - signal-cli/blob - lib/src/main/java/org/asamk/signal/manager/syncStorage/StorageSyncModels.java
9eeaf53a244768e4fdb61ebc0559e76305d69d23
[signal-cli] / lib / src / main / java / org / asamk / signal / manager / syncStorage / StorageSyncModels.java
1 package org.asamk.signal.manager.syncStorage;
2
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.ServiceId.ACI;
11 import org.whispersystems.signalservice.api.push.ServiceId.PNI;
12 import org.whispersystems.signalservice.api.push.UsernameLinkComponents;
13 import org.whispersystems.signalservice.api.storage.SignalAccountRecord;
14 import org.whispersystems.signalservice.api.storage.SignalContactRecord;
15 import org.whispersystems.signalservice.api.storage.SignalGroupV1Record;
16 import org.whispersystems.signalservice.api.storage.SignalGroupV2Record;
17 import org.whispersystems.signalservice.api.util.UuidUtil;
18 import org.whispersystems.signalservice.internal.storage.protos.AccountRecord;
19 import org.whispersystems.signalservice.internal.storage.protos.AccountRecord.UsernameLink;
20 import org.whispersystems.signalservice.internal.storage.protos.ContactRecord;
21 import org.whispersystems.signalservice.internal.storage.protos.ContactRecord.IdentityState;
22 import org.whispersystems.signalservice.internal.storage.protos.GroupV1Record;
23 import org.whispersystems.signalservice.internal.storage.protos.GroupV2Record;
24
25 import java.util.Optional;
26
27 import okio.ByteString;
28
29 import static org.signal.core.util.StringExtensionsKt.emptyIfNull;
30
31 public final class StorageSyncModels {
32
33 private StorageSyncModels() {
34 }
35
36 public static AccountRecord.PhoneNumberSharingMode localToRemote(PhoneNumberSharingMode phoneNumberPhoneNumberSharingMode) {
37 return switch (phoneNumberPhoneNumberSharingMode) {
38 case EVERYBODY -> AccountRecord.PhoneNumberSharingMode.EVERYBODY;
39 case CONTACTS, NOBODY -> AccountRecord.PhoneNumberSharingMode.NOBODY;
40 };
41 }
42
43 public static PhoneNumberSharingMode remoteToLocal(AccountRecord.PhoneNumberSharingMode phoneNumberPhoneNumberSharingMode) {
44 return switch (phoneNumberPhoneNumberSharingMode) {
45 case EVERYBODY -> PhoneNumberSharingMode.EVERYBODY;
46 case NOBODY -> PhoneNumberSharingMode.NOBODY;
47 case UNKNOWN -> null;
48 };
49 }
50
51 public static AccountRecord localToRemoteRecord(
52 ConfigurationStore configStore,
53 Recipient self,
54 UsernameLinkComponents usernameLinkComponents
55 ) {
56 final var builder = SignalAccountRecord.Companion.newBuilder(self.getStorageRecord());
57 if (self.getProfileKey() != null) {
58 builder.profileKey(ByteString.of(self.getProfileKey().serialize()));
59 }
60 if (self.getProfile() != null) {
61 builder.givenName(emptyIfNull(self.getProfile().getGivenName()))
62 .familyName(emptyIfNull(self.getProfile().getFamilyName()))
63 .avatarUrlPath(emptyIfNull(self.getProfile().getAvatarUrlPath()));
64 }
65 builder.typingIndicators(Optional.ofNullable(configStore.getTypingIndicators()).orElse(true))
66 .readReceipts(Optional.ofNullable(configStore.getReadReceipts()).orElse(true))
67 .sealedSenderIndicators(Optional.ofNullable(configStore.getUnidentifiedDeliveryIndicators())
68 .orElse(true))
69 .linkPreviews(Optional.ofNullable(configStore.getLinkPreviews()).orElse(true))
70 .unlistedPhoneNumber(Optional.ofNullable(configStore.getPhoneNumberUnlisted()).orElse(false))
71 .phoneNumberSharingMode(Optional.ofNullable(configStore.getPhoneNumberSharingMode())
72 .map(StorageSyncModels::localToRemote)
73 .orElse(AccountRecord.PhoneNumberSharingMode.UNKNOWN))
74 .e164(self.getAddress().number().orElse(""))
75 .username(self.getAddress().username().orElse(""));
76 if (usernameLinkComponents != null) {
77 final var linkColor = configStore.getUsernameLinkColor();
78 builder.usernameLink(new UsernameLink.Builder().entropy(ByteString.of(usernameLinkComponents.getEntropy()))
79 .serverId(UuidUtil.toByteString(usernameLinkComponents.getServerId()))
80 .color(linkColor == null ? UsernameLink.Color.UNKNOWN : UsernameLink.Color.valueOf(linkColor))
81 .build());
82 }
83
84 return builder.build();
85 }
86
87 public static ContactRecord localToRemoteRecord(Recipient recipient, IdentityInfo identity) {
88 final var address = recipient.getAddress();
89 final var builder = SignalContactRecord.Companion.newBuilder(recipient.getStorageRecord())
90 .aci(address.aci().map(ACI::toString).orElse(""))
91 .e164(address.number().orElse(""))
92 .pni(address.pni().map(PNI::toStringWithoutPrefix).orElse(""))
93 .username(address.username().orElse(""))
94 .profileKey(recipient.getProfileKey() == null
95 ? ByteString.EMPTY
96 : ByteString.of(recipient.getProfileKey().serialize()));
97 if (recipient.getProfile() != null) {
98 builder.givenName(emptyIfNull(recipient.getProfile().getGivenName()))
99 .familyName(emptyIfNull(recipient.getProfile().getFamilyName()));
100 }
101 if (recipient.getContact() != null) {
102 builder.systemGivenName(emptyIfNull(recipient.getContact().givenName()))
103 .systemFamilyName(emptyIfNull(recipient.getContact().familyName()))
104 .systemNickname(emptyIfNull(recipient.getContact().nickName()))
105 .nickname(new ContactRecord.Name.Builder().given(emptyIfNull(recipient.getContact()
106 .nickNameGivenName()))
107 .family(emptyIfNull(recipient.getContact().nickNameFamilyName()))
108 .build())
109 .note(emptyIfNull(recipient.getContact().note()))
110 .blocked(recipient.getContact().isBlocked())
111 .whitelisted(recipient.getContact().isProfileSharingEnabled())
112 .mutedUntilTimestamp(recipient.getContact().muteUntil())
113 .hideStory(recipient.getContact().hideStory())
114 .unregisteredAtTimestamp(recipient.getContact().unregisteredTimestamp() == null
115 ? 0
116 : recipient.getContact().unregisteredTimestamp())
117 .archived(recipient.getContact().isArchived())
118 .hidden(recipient.getContact().isHidden());
119 }
120 if (identity != null) {
121 builder.identityKey(ByteString.of(identity.getIdentityKey().serialize()))
122 .identityState(localToRemote(identity.getTrustLevel()));
123 }
124 return builder.build();
125 }
126
127 public static GroupV1Record localToRemoteRecord(GroupInfoV1 group) {
128 final var builder = SignalGroupV1Record.Companion.newBuilder(group.getStorageRecord());
129 builder.id(ByteString.of(group.getGroupId().serialize()));
130 builder.blocked(group.isBlocked());
131 builder.archived(group.archived);
132 builder.whitelisted(true);
133 return builder.build();
134 }
135
136 public static GroupV2Record localToRemoteRecord(GroupInfoV2 group) {
137 final var builder = SignalGroupV2Record.Companion.newBuilder(group.getStorageRecord());
138 builder.masterKey(ByteString.of(group.getMasterKey().serialize()));
139 builder.blocked(group.isBlocked());
140 builder.whitelisted(group.isProfileSharingEnabled());
141 return builder.build();
142 }
143
144 public static TrustLevel remoteToLocal(IdentityState identityState) {
145 return switch (identityState) {
146 case DEFAULT -> TrustLevel.TRUSTED_UNVERIFIED;
147 case UNVERIFIED -> TrustLevel.UNTRUSTED;
148 case VERIFIED -> TrustLevel.TRUSTED_VERIFIED;
149 };
150 }
151
152 private static IdentityState localToRemote(TrustLevel local) {
153 return switch (local) {
154 case TRUSTED_VERIFIED -> IdentityState.VERIFIED;
155 case UNTRUSTED -> IdentityState.UNVERIFIED;
156 default -> IdentityState.DEFAULT;
157 };
158 }
159 }