]> nmode's Git Repositories - signal-cli/blob - lib/src/main/java/org/asamk/signal/manager/syncStorage/GroupV2RecordProcessor.java
4d41901aaf9bccb2a8d8d9a9b168d96648a27f54
[signal-cli] / lib / src / main / java / org / asamk / signal / manager / syncStorage / GroupV2RecordProcessor.java
1 package org.asamk.signal.manager.syncStorage;
2
3 import org.asamk.signal.manager.groups.GroupUtils;
4 import org.asamk.signal.manager.storage.SignalAccount;
5 import org.asamk.signal.manager.util.KeyUtils;
6 import org.signal.libsignal.zkgroup.groups.GroupMasterKey;
7 import org.slf4j.Logger;
8 import org.slf4j.LoggerFactory;
9 import org.whispersystems.signalservice.api.storage.SignalGroupV2Record;
10
11 import java.sql.Connection;
12 import java.sql.SQLException;
13 import java.util.Arrays;
14 import java.util.Optional;
15
16 public final class GroupV2RecordProcessor extends DefaultStorageRecordProcessor<SignalGroupV2Record> {
17
18 private static final Logger logger = LoggerFactory.getLogger(GroupV2RecordProcessor.class);
19 private final SignalAccount account;
20 private final Connection connection;
21
22 public GroupV2RecordProcessor(SignalAccount account, Connection connection) {
23 this.account = account;
24 this.connection = connection;
25 }
26
27 @Override
28 protected boolean isInvalid(SignalGroupV2Record remote) {
29 return remote.getMasterKeyBytes().length != GroupMasterKey.SIZE;
30 }
31
32 @Override
33 protected Optional<SignalGroupV2Record> getMatching(SignalGroupV2Record remote) throws SQLException {
34 final var id = GroupUtils.getGroupIdV2(remote.getMasterKeyOrThrow());
35 final var group = account.getGroupStore().getGroup(connection, id);
36
37 if (group == null) {
38 return Optional.empty();
39 }
40
41 final var storageId = account.getGroupStore().getGroupStorageId(connection, id);
42 return Optional.of(StorageSyncModels.localToRemoteRecord(group, storageId.getRaw()).getGroupV2().get());
43 }
44
45 @Override
46 protected SignalGroupV2Record merge(SignalGroupV2Record remote, SignalGroupV2Record local) {
47 final var unknownFields = remote.serializeUnknownFields();
48 final var blocked = remote.isBlocked();
49 final var profileSharing = remote.isProfileSharingEnabled();
50 final var archived = remote.isArchived();
51 final var forcedUnread = remote.isForcedUnread();
52 final var muteUntil = remote.getMuteUntil();
53 final var notifyForMentionsWhenMuted = remote.notifyForMentionsWhenMuted();
54 final var hideStory = remote.shouldHideStory();
55 final var storySendMode = remote.getStorySendMode();
56
57 final var mergedBuilder = new SignalGroupV2Record.Builder(remote.getId().getRaw(),
58 remote.getMasterKeyBytes(),
59 unknownFields).setBlocked(blocked)
60 .setProfileSharingEnabled(profileSharing)
61 .setArchived(archived)
62 .setForcedUnread(forcedUnread)
63 .setMuteUntil(muteUntil)
64 .setNotifyForMentionsWhenMuted(notifyForMentionsWhenMuted)
65 .setHideStory(hideStory)
66 .setStorySendMode(storySendMode);
67 final var merged = mergedBuilder.build();
68
69 final var matchesRemote = doProtosMatch(merged, remote);
70 if (matchesRemote) {
71 return remote;
72 }
73
74 final var matchesLocal = doProtosMatch(merged, local);
75 if (matchesLocal) {
76 return local;
77 }
78
79 return mergedBuilder.setId(KeyUtils.createRawStorageId()).build();
80 }
81
82 @Override
83 protected void insertLocal(SignalGroupV2Record record) throws SQLException {
84 StorageRecordUpdate<SignalGroupV2Record> update = new StorageRecordUpdate<>(null, record);
85 updateLocal(update);
86 }
87
88 @Override
89 protected void updateLocal(StorageRecordUpdate<SignalGroupV2Record> update) throws SQLException {
90 final var groupV2Record = update.newRecord();
91 final var groupMasterKey = groupV2Record.getMasterKeyOrThrow();
92
93 final var group = account.getGroupStore().getGroupOrPartialMigrate(connection, groupMasterKey);
94 group.setBlocked(groupV2Record.isBlocked());
95 account.getGroupStore().updateGroup(connection, group);
96 account.getGroupStore()
97 .storeStorageRecord(connection,
98 group.getGroupId(),
99 groupV2Record.getId(),
100 groupV2Record.toProto().encode());
101 }
102
103 @Override
104 public int compare(SignalGroupV2Record lhs, SignalGroupV2Record rhs) {
105 if (Arrays.equals(lhs.getMasterKeyBytes(), rhs.getMasterKeyBytes())) {
106 return 0;
107 } else {
108 return 1;
109 }
110 }
111
112 private static boolean doProtosMatch(SignalGroupV2Record merged, SignalGroupV2Record other) {
113 return Arrays.equals(merged.toProto().encode(), other.toProto().encode());
114 }
115 }