1 package org
.asamk
.signal
.manager
.syncStorage
;
3 import org
.asamk
.signal
.manager
.api
.GroupId
;
4 import org
.asamk
.signal
.manager
.api
.GroupIdV1
;
5 import org
.asamk
.signal
.manager
.storage
.SignalAccount
;
6 import org
.asamk
.signal
.manager
.storage
.groups
.GroupInfoV2
;
7 import org
.asamk
.signal
.manager
.util
.KeyUtils
;
8 import org
.slf4j
.Logger
;
9 import org
.slf4j
.LoggerFactory
;
10 import org
.whispersystems
.signalservice
.api
.storage
.SignalGroupV1Record
;
12 import java
.sql
.Connection
;
13 import java
.sql
.SQLException
;
14 import java
.util
.Arrays
;
15 import java
.util
.Optional
;
18 * Handles merging remote storage updates into local group v1 state.
20 public final class GroupV1RecordProcessor
extends DefaultStorageRecordProcessor
<SignalGroupV1Record
> {
22 private static final Logger logger
= LoggerFactory
.getLogger(GroupV1RecordProcessor
.class);
23 private final SignalAccount account
;
24 private final Connection connection
;
26 public GroupV1RecordProcessor(SignalAccount account
, Connection connection
) {
27 this.account
= account
;
28 this.connection
= connection
;
34 * - GV1 IDs that map to GV2 IDs, meaning we've already migrated them.
37 protected boolean isInvalid(SignalGroupV1Record remote
) throws SQLException
{
39 final var id
= GroupId
.unknownVersion(remote
.getGroupId());
40 if (!(id
instanceof GroupIdV1
)) {
43 final var group
= account
.getGroupStore().getGroup(connection
, id
);
45 if (group
instanceof GroupInfoV2
) {
46 logger
.debug("We already have an upgraded V2 group for this V1 group -- marking as invalid.");
51 } catch (AssertionError e
) {
52 logger
.debug("Bad Group ID -- marking as invalid.");
58 protected Optional
<SignalGroupV1Record
> getMatching(SignalGroupV1Record remote
) throws SQLException
{
59 final var id
= GroupId
.v1(remote
.getGroupId());
60 final var group
= account
.getGroupStore().getGroup(connection
, id
);
63 return Optional
.empty();
66 final var storageId
= account
.getGroupStore().getGroupStorageId(connection
, id
);
67 return Optional
.of(StorageSyncModels
.localToRemoteRecord(group
, storageId
.getRaw()).getGroupV1().get());
71 protected SignalGroupV1Record
merge(SignalGroupV1Record remote
, SignalGroupV1Record local
) {
72 final var unknownFields
= remote
.serializeUnknownFields();
73 final var blocked
= remote
.isBlocked();
74 final var profileSharing
= remote
.isProfileSharingEnabled();
75 final var archived
= remote
.isArchived();
76 final var forcedUnread
= remote
.isForcedUnread();
77 final var muteUntil
= remote
.getMuteUntil();
79 final var mergedBuilder
= new SignalGroupV1Record
.Builder(remote
.getId().getRaw(),
81 unknownFields
).setBlocked(blocked
)
82 .setProfileSharingEnabled(profileSharing
)
83 .setForcedUnread(forcedUnread
)
84 .setMuteUntil(muteUntil
)
85 .setArchived(archived
);
87 final var merged
= mergedBuilder
.build();
89 final var matchesRemote
= doProtosMatch(merged
, remote
);
94 final var matchesLocal
= doProtosMatch(merged
, local
);
99 return mergedBuilder
.setId(KeyUtils
.createRawStorageId()).build();
103 protected void insertLocal(SignalGroupV1Record
record) throws SQLException
{
104 // TODO send group info request (after server message queue is empty)
105 // context.getGroupHelper().sendGroupInfoRequest(groupIdV1, account.getSelfRecipientId());
106 StorageRecordUpdate
<SignalGroupV1Record
> update
= new StorageRecordUpdate
<>(null, record);
111 protected void updateLocal(StorageRecordUpdate
<SignalGroupV1Record
> update
) throws SQLException
{
112 final var groupV1Record
= update
.newRecord();
113 final var groupIdV1
= GroupId
.v1(groupV1Record
.getGroupId());
115 final var group
= account
.getGroupStore().getOrCreateGroupV1(connection
, groupIdV1
);
117 group
.setBlocked(groupV1Record
.isBlocked());
118 account
.getGroupStore().updateGroup(connection
, group
);
119 account
.getGroupStore()
120 .storeStorageRecord(connection
,
122 groupV1Record
.getId(),
123 groupV1Record
.toProto().encode());
128 public int compare(SignalGroupV1Record lhs
, SignalGroupV1Record rhs
) {
129 if (Arrays
.equals(lhs
.getGroupId(), rhs
.getGroupId())) {
136 private static boolean doProtosMatch(SignalGroupV1Record merged
, SignalGroupV1Record other
) {
137 return Arrays
.equals(merged
.toProto().encode(), other
.toProto().encode());