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
;
11 import org
.whispersystems
.signalservice
.api
.storage
.StorageId
;
12 import org
.whispersystems
.signalservice
.internal
.storage
.protos
.GroupV1Record
;
14 import java
.sql
.Connection
;
15 import java
.sql
.SQLException
;
16 import java
.util
.Arrays
;
17 import java
.util
.Optional
;
20 * Handles merging remote storage updates into local group v1 state.
22 public final class GroupV1RecordProcessor
extends DefaultStorageRecordProcessor
<SignalGroupV1Record
> {
24 private static final Logger logger
= LoggerFactory
.getLogger(GroupV1RecordProcessor
.class);
25 private final SignalAccount account
;
26 private final Connection connection
;
28 public GroupV1RecordProcessor(SignalAccount account
, Connection connection
) {
29 this.account
= account
;
30 this.connection
= connection
;
36 * - GV1 IDs that map to GV2 IDs, meaning we've already migrated them.
39 protected boolean isInvalid(SignalGroupV1Record remote
) throws SQLException
{
41 final var id
= GroupId
.unknownVersion(remote
.getProto().id
.toByteArray());
42 if (!(id
instanceof GroupIdV1
)) {
45 final var group
= account
.getGroupStore().getGroup(connection
, id
);
47 if (group
instanceof GroupInfoV2
) {
48 logger
.debug("We already have an upgraded V2 group for this V1 group -- marking as invalid.");
53 } catch (AssertionError e
) {
54 logger
.debug("Bad Group ID -- marking as invalid.");
60 protected Optional
<SignalGroupV1Record
> getMatching(SignalGroupV1Record remote
) throws SQLException
{
61 final var id
= GroupId
.v1(remote
.getProto().id
.toByteArray());
62 final var group
= account
.getGroupStore().getGroup(connection
, id
);
65 return Optional
.empty();
68 final var storageId
= account
.getGroupStore().getGroupStorageId(connection
, id
);
69 return Optional
.of(new SignalGroupV1Record(storageId
, StorageSyncModels
.localToRemoteRecord(group
)));
73 protected SignalGroupV1Record
merge(SignalGroupV1Record remoteRecord
, SignalGroupV1Record localRecord
) {
74 final var remote
= remoteRecord
.getProto();
75 final var local
= localRecord
.getProto();
77 final var mergedBuilder
= SignalGroupV1Record
.Companion
.newBuilder(remote
.unknownFields().toByteArray())
79 .blocked(remote
.blocked
)
80 .whitelisted(remote
.whitelisted
)
81 .markedUnread(remote
.markedUnread
)
82 .mutedUntilTimestamp(remote
.mutedUntilTimestamp
)
83 .archived(remote
.archived
);
85 final var merged
= mergedBuilder
.build();
87 final var matchesRemote
= doProtosMatch(merged
, remote
);
92 final var matchesLocal
= doProtosMatch(merged
, local
);
97 return new SignalGroupV1Record(StorageId
.forGroupV1(KeyUtils
.createRawStorageId()), mergedBuilder
.build());
101 protected void insertLocal(SignalGroupV1Record
record) throws SQLException
{
102 // TODO send group info request (after server message queue is empty)
103 // context.getGroupHelper().sendGroupInfoRequest(groupIdV1, account.getSelfRecipientId());
104 StorageRecordUpdate
<SignalGroupV1Record
> update
= new StorageRecordUpdate
<>(null, record);
109 protected void updateLocal(StorageRecordUpdate
<SignalGroupV1Record
> update
) throws SQLException
{
110 final var groupV1Record
= update
.newRecord();
111 final var groupV1Proto
= groupV1Record
.getProto();
112 final var groupIdV1
= GroupId
.v1(groupV1Proto
.id
.toByteArray());
114 final var group
= account
.getGroupStore().getOrCreateGroupV1(connection
, groupIdV1
);
116 group
.setBlocked(groupV1Proto
.blocked
);
117 account
.getGroupStore().updateGroup(connection
, group
);
118 account
.getGroupStore()
119 .storeStorageRecord(connection
, group
.getGroupId(), groupV1Record
.getId(), groupV1Proto
.encode());
124 public int compare(SignalGroupV1Record lhs
, SignalGroupV1Record rhs
) {
125 if (lhs
.getProto().id
.equals(rhs
.getProto().id
)) {
132 private static boolean doProtosMatch(GroupV1Record merged
, GroupV1Record other
) {
133 return Arrays
.equals(merged
.encode(), other
.encode());