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