"allDeclaredFields":true,
"queryAllDeclaredMethods":true,
"queryAllDeclaredConstructors":true,
- "methods":[{"name":"<init>","parameterTypes":["java.lang.String"] }, {"name":"getUsernameLinkEncryptedValue","parameterTypes":[] }]
+ "methods":[{"name":"<init>","parameterTypes":["java.lang.String"] }, {"name":"<init>","parameterTypes":["java.lang.String","boolean"] }, {"name":"getKeepLinkHandle","parameterTypes":[] }, {"name":"getUsernameLinkEncryptedValue","parameterTypes":[] }]
},
{
"name":"org.whispersystems.signalservice.internal.push.SetUsernameLinkResponseBody",
"queryAllDeclaredConstructors":true,
"methods":[{"name":"<init>","parameterTypes":["java.lang.String","java.lang.String","java.lang.String","java.lang.String","java.lang.String"] }, {"name":"getCaptcha","parameterTypes":[] }, {"name":"getMcc","parameterTypes":[] }, {"name":"getMnc","parameterTypes":[] }, {"name":"getPushChallenge","parameterTypes":[] }, {"name":"getPushToken","parameterTypes":[] }, {"name":"getPushTokenType","parameterTypes":[] }]
},
+{
+ "name":"org.whispersystems.signalservice.internal.push.VerificationCodeFailureResponseBody",
+ "allDeclaredFields":true,
+ "queryAllDeclaredMethods":true,
+ "queryAllDeclaredConstructors":true,
+ "methods":[{"name":"<init>","parameterTypes":["boolean","java.lang.String"] }, {"name":"<init>","parameterTypes":["boolean","java.lang.String","int","kotlin.jvm.internal.DefaultConstructorMarker"] }]
+},
{
"name":"org.whispersystems.signalservice.internal.push.VerificationSessionMetadataRequestBody",
"allDeclaredFields":true,
}]},
"bundles":[{
"name":"net.sourceforge.argparse4j.internal.ArgumentParserImpl",
- "locales":["", "en", "und"]
+ "locales":["", "de", "en", "und"]
}]
}
public record Contact(
String givenName,
String familyName,
+ String nickName,
String color,
int messageExpirationTime,
+ long muteUntil,
+ boolean hideStory,
boolean isBlocked,
boolean isArchived,
boolean isProfileSharingEnabled,
- boolean isHidden
+ boolean isHidden,
+ Long unregisteredTimestamp
) {
private Contact(final Builder builder) {
this(builder.givenName,
builder.familyName,
+ builder.nickName,
builder.color,
builder.messageExpirationTime,
+ builder.muteUntil,
+ builder.hideStory,
builder.isBlocked,
builder.isArchived,
builder.isProfileSharingEnabled,
- builder.isHidden);
+ builder.isHidden,
+ builder.unregisteredTimestamp);
}
public static Builder newBuilder() {
Builder builder = new Builder();
builder.givenName = copy.givenName();
builder.familyName = copy.familyName();
+ builder.nickName = copy.nickName();
builder.color = copy.color();
builder.messageExpirationTime = copy.messageExpirationTime();
+ builder.muteUntil = copy.muteUntil();
+ builder.hideStory = copy.hideStory();
builder.isBlocked = copy.isBlocked();
builder.isArchived = copy.isArchived();
builder.isProfileSharingEnabled = copy.isProfileSharingEnabled();
builder.isHidden = copy.isHidden();
+ builder.unregisteredTimestamp = copy.unregisteredTimestamp();
return builder;
}
private String givenName;
private String familyName;
+ private String nickName;
private String color;
private int messageExpirationTime;
+ private long muteUntil;
+ private boolean hideStory;
private boolean isBlocked;
private boolean isArchived;
private boolean isProfileSharingEnabled;
private boolean isHidden;
+ private Long unregisteredTimestamp;
private Builder() {
}
return this;
}
+ public Builder withNickName(final String val) {
+ nickName = val;
+ return this;
+ }
+
public Builder withColor(final String val) {
color = val;
return this;
return this;
}
+ public Builder withMuteUntil(final long val) {
+ muteUntil = val;
+ return this;
+ }
+
+ public Builder withHideStory(final boolean val) {
+ hideStory = val;
+ return this;
+ }
+
public Builder withIsBlocked(final boolean val) {
isBlocked = val;
return this;
return this;
}
+ public Builder withUnregisteredTimestamp(final Long val) {
+ unregisteredTimestamp = val;
+ return this;
+ }
+
public Contact build() {
return new Contact(this);
}
import java.io.File;
import java.sql.Connection;
import java.sql.SQLException;
+import java.sql.Statement;
import java.util.HashMap;
import java.util.Optional;
import java.util.UUID;
public class AccountDatabase extends Database {
private static final Logger logger = LoggerFactory.getLogger(AccountDatabase.class);
- private static final long DATABASE_VERSION = 21;
+ private static final long DATABASE_VERSION = 22;
private AccountDatabase(final HikariDataSource dataSource) {
super(logger, DATABASE_VERSION, dataSource);
if (oldVersion < 15) {
logger.debug("Updating database: Store serviceId as TEXT");
try (final var statement = connection.createStatement()) {
- statement.executeUpdate("""
- CREATE TABLE tmp_mapping_table (
- uuid BLOB NOT NULL,
- address TEXT NOT NULL
- ) STRICT;
- """);
-
- final var sql = (
- """
- SELECT r.uuid, r.pni
- FROM recipient r
- """
- );
- final var uuidAddressMapping = new HashMap<UUID, ServiceId>();
- try (final var preparedStatement = connection.prepareStatement(sql)) {
- try (var result = Utils.executeQueryForStream(preparedStatement, (resultSet) -> {
- final var pni = Optional.ofNullable(resultSet.getBytes("pni"))
- .map(UuidUtil::parseOrNull)
- .map(ServiceId.PNI::from);
- final var serviceIdUuid = Optional.ofNullable(resultSet.getBytes("uuid"))
- .map(UuidUtil::parseOrNull);
- final var serviceId = serviceIdUuid.isPresent() && pni.isPresent() && serviceIdUuid.get()
- .equals(pni.get().getRawUuid())
- ? pni.<ServiceId>map(p -> p)
- : serviceIdUuid.<ServiceId>map(ACI::from);
-
- return new Pair<>(serviceId, pni);
- })) {
- result.forEach(p -> {
- final var serviceId = p.first();
- final var pni = p.second();
- if (serviceId.isPresent()) {
- uuidAddressMapping.put(serviceId.get().getRawUuid(), serviceId.get());
- }
- if (pni.isPresent()) {
- uuidAddressMapping.put(pni.get().getRawUuid(), pni.get());
- }
- });
- }
- }
-
- final var insertSql = """
- INSERT INTO tmp_mapping_table (uuid, address)
- VALUES (?,?)
- """;
- try (final var insertStatement = connection.prepareStatement(insertSql)) {
- for (final var entry : uuidAddressMapping.entrySet()) {
- final var uuid = entry.getKey();
- final var serviceId = entry.getValue();
- insertStatement.setBytes(1, UuidUtil.toByteArray(uuid));
- insertStatement.setString(2, serviceId.toString());
- insertStatement.execute();
- }
- }
+ createUuidMappingTable(connection, statement);
statement.executeUpdate("""
CREATE TABLE identity2 (
try (final var statement = connection.createStatement()) {
statement.executeUpdate("""
ALTER TABLE recipient ADD unregistered_timestamp INTEGER;
- UPDATE recipient SET pni = NULL WHERE uuid IS NOT NULL;
""");
}
}
+ if (oldVersion < 22) {
+ logger.debug("Updating database: Store recipient aci/pni as TEXT");
+ try (final var statement = connection.createStatement()) {
+ createUuidMappingTable(connection, statement);
+
+ statement.executeUpdate("""
+ CREATE TABLE recipient2 (
+ _id INTEGER PRIMARY KEY AUTOINCREMENT,
+ storage_id BLOB UNIQUE,
+ storage_record BLOB,
+ number TEXT UNIQUE,
+ username TEXT UNIQUE,
+ aci TEXT UNIQUE,
+ pni TEXT UNIQUE,
+ unregistered_timestamp INTEGER,
+ profile_key BLOB,
+ profile_key_credential BLOB,
+
+ given_name TEXT,
+ family_name TEXT,
+ nick_name TEXT,
+ color TEXT,
+
+ expiration_time INTEGER NOT NULL DEFAULT 0,
+ mute_until INTEGER NOT NULL DEFAULT 0,
+ blocked INTEGER NOT NULL DEFAULT FALSE,
+ archived INTEGER NOT NULL DEFAULT FALSE,
+ profile_sharing INTEGER NOT NULL DEFAULT FALSE,
+ hide_story INTEGER NOT NULL DEFAULT FALSE,
+ hidden INTEGER NOT NULL DEFAULT FALSE,
+
+ profile_last_update_timestamp INTEGER NOT NULL DEFAULT 0,
+ profile_given_name TEXT,
+ profile_family_name TEXT,
+ profile_about TEXT,
+ profile_about_emoji TEXT,
+ profile_avatar_url_path TEXT,
+ profile_mobile_coin_address BLOB,
+ profile_unidentified_access_mode TEXT,
+ profile_capabilities TEXT
+ ) STRICT;
+ INSERT INTO recipient2 (_id, aci, pni, storage_id, storage_record, number, username, unregistered_timestamp, profile_key, profile_key_credential, given_name, family_name, color, expiration_time, blocked, archived, profile_sharing, hidden, profile_last_update_timestamp, profile_given_name, profile_family_name, profile_about, profile_about_emoji, profile_avatar_url_path, profile_mobile_coin_address, profile_unidentified_access_mode, profile_capabilities)
+ SELECT r._id, (SELECT t.address FROM tmp_mapping_table t WHERE t.uuid = r.uuid AND t.address not like 'PNI:%') aci, (SELECT t.address FROM tmp_mapping_table t WHERE t.uuid = r.pni AND t.address like 'PNI:%') pni, storage_id, storage_record, number, username, unregistered_timestamp, profile_key, profile_key_credential, given_name, family_name, color, expiration_time, blocked, archived, profile_sharing, hidden, profile_last_update_timestamp, profile_given_name, profile_family_name, profile_about, profile_about_emoji, profile_avatar_url_path, profile_mobile_coin_address, profile_unidentified_access_mode, profile_capabilities
+ FROM recipient r;
+ DROP TABLE recipient;
+ ALTER TABLE recipient2 RENAME TO recipient;
+
+ DROP TABLE tmp_mapping_table;
+ """);
+ }
+ }
+ }
+
+ private static void createUuidMappingTable(
+ final Connection connection, final Statement statement
+ ) throws SQLException {
+ statement.executeUpdate("""
+ CREATE TABLE tmp_mapping_table (
+ uuid BLOB NOT NULL,
+ address TEXT NOT NULL
+ ) STRICT;
+ """);
+
+ final var sql = (
+ """
+ SELECT r.uuid, r.pni
+ FROM recipient r
+ """
+ );
+ final var uuidAddressMapping = new HashMap<UUID, ServiceId>();
+ try (final var preparedStatement = connection.prepareStatement(sql)) {
+ try (var result = Utils.executeQueryForStream(preparedStatement, (resultSet) -> {
+ final var pni = Optional.ofNullable(resultSet.getBytes("pni"))
+ .map(UuidUtil::parseOrNull)
+ .map(ServiceId.PNI::from);
+ final var serviceIdUuid = Optional.ofNullable(resultSet.getBytes("uuid")).map(UuidUtil::parseOrNull);
+ final var serviceId = serviceIdUuid.isPresent() && pni.isPresent() && serviceIdUuid.get()
+ .equals(pni.get().getRawUuid())
+ ? pni.<ServiceId>map(p -> p)
+ : serviceIdUuid.<ServiceId>map(ACI::from);
+
+ return new Pair<>(serviceId, pni);
+ })) {
+ result.forEach(p -> {
+ final var serviceId = p.first();
+ final var pni = p.second();
+ if (serviceId.isPresent()) {
+ final var rawUuid = serviceId.get().getRawUuid();
+ if (!uuidAddressMapping.containsKey(rawUuid)) {
+ uuidAddressMapping.put(rawUuid, serviceId.get());
+ }
+ }
+ if (pni.isPresent()) {
+ uuidAddressMapping.put(pni.get().getRawUuid(), pni.get());
+ }
+ });
+ }
+ }
+
+ final var insertSql = """
+ INSERT INTO tmp_mapping_table (uuid, address)
+ VALUES (?,?)
+ """;
+ try (final var insertStatement = connection.prepareStatement(insertSql)) {
+ for (final var entry : uuidAddressMapping.entrySet()) {
+ final var uuid = entry.getKey();
+ final var serviceId = entry.getValue();
+ insertStatement.setBytes(1, UuidUtil.toByteArray(uuid));
+ insertStatement.setString(2, serviceId.toString());
+ insertStatement.execute();
+ }
+ }
}
}
}
getRecipientStore().deleteRecipientData(recipientId);
getMessageCache().deleteMessages(recipientId);
- if (recipientAddress.serviceId().isPresent()) {
- final var serviceId = recipientAddress.serviceId().get();
+ if (recipientAddress.aci().isPresent()) {
+ final var serviceId = recipientAddress.aci().get();
+ aciAccountData.getSessionStore().deleteAllSessions(serviceId);
+ pniAccountData.getSessionStore().deleteAllSessions(serviceId);
+ getIdentityKeyStore().deleteIdentity(serviceId);
+ getSenderKeyStore().deleteAll(serviceId);
+ }
+ if (recipientAddress.pni().isPresent()) {
+ final var serviceId = recipientAddress.pni().get();
aciAccountData.getSessionStore().deleteAllSessions(serviceId);
pniAccountData.getSessionStore().deleteAllSessions(serviceId);
getIdentityKeyStore().deleteIdentity(serviceId);
final var recipientId = getRecipientStore().resolveRecipientTrusted(contact.getAddress());
getContactStore().storeContact(recipientId,
new Contact(contact.name,
+ null,
null,
contact.color,
contact.messageExpirationTime,
+ 0,
+ false,
contact.blocked,
contact.archived,
false,
- false));
+ false,
+ null));
// Store profile keys only in profile store
var profileKeyString = contact.profileKey;
if (g instanceof Storage.GroupV1 g1) {
final var members = g1.members.stream().map(m -> {
if (m.recipientId == null) {
- return recipientResolver.resolveRecipient(new RecipientAddress(ServiceId.parseOrNull(m.uuid),
+ return recipientResolver.resolveRecipient(new RecipientAddress(ServiceId.ACI.parseOrNull(m.uuid),
m.number));
}
if (node.isArray()) {
for (var entry : node) {
var name = entry.hasNonNull("name") ? entry.get("name").asText() : null;
- var serviceId = entry.hasNonNull("uuid") ? ServiceId.parseOrNull(entry.get("uuid").asText()) : null;
+ var serviceId = entry.hasNonNull("uuid")
+ ? ServiceId.ACI.parseOrNull(entry.get("uuid").asText())
+ : null;
final var address = new RecipientAddress(serviceId, name);
ProfileKey profileKey = null;
try {
if (node.isArray()) {
for (var recipient : node) {
var recipientName = recipient.get("name").asText();
- var serviceId = ServiceId.parseOrThrow(recipient.get("uuid").asText());
+ var serviceId = ServiceId.ACI.parseOrThrow(recipient.get("uuid").asText());
addresses.add(new RecipientAddress(serviceId, recipientName));
}
}
Contact contact = null;
if (r.contact != null) {
contact = new Contact(r.contact.name,
+ null,
null,
r.contact.color,
r.contact.messageExpirationTime,
+ 0,
+ false,
r.contact.blocked,
r.contact.archived,
r.contact.profileSharingEnabled,
- false);
+ false,
+ null);
}
ProfileKey profileKey = null;
return new Pair<>(recipient.id(), List.of());
}
- if (recipient.address().serviceId().isEmpty() || (
- recipient.address().serviceId().equals(address.serviceId())
- ) || (
- recipient.address().pni().isPresent() && recipient.address().pni().equals(address.serviceId())
- ) || (
- recipient.address().serviceId().equals(address.pni())
- ) || (
- address.pni().isPresent() && address.pni().equals(recipient.address().pni())
- )) {
+ if (recipient.address().aci().isEmpty() || (
+ address.aci().isEmpty() && (
+ address.pni().isEmpty()
+ || recipient.address().pni().equals(address.pni())
+ )
+ ) || recipient.address().aci().equals(address.aci())) {
logger.debug("Got existing recipient {}, updating with high trust address", recipient.id());
store.updateRecipientAddress(recipient.id(), recipient.address().withIdentifiersFrom(address));
return new Pair<>(recipient.id(), List.of());
}
logger.debug(
- "Got recipient {} existing with number/pni/username, but different serviceId, so stripping its number and adding new recipient",
+ "Got recipient {} existing with number/pni/username, but different aci, so stripping its number and adding new recipient",
recipient.id());
store.updateRecipientAddress(recipient.id(), recipient.address().removeIdentifiersFrom(address));
}
var resultingRecipient = recipients.stream()
- .filter(r -> r.address().serviceId().equals(address.serviceId()) || r.address()
- .pni()
- .equals(address.serviceId()))
+ .filter(r -> r.address().aci().isPresent() && r.address().aci().equals(address.aci()))
.findFirst();
if (resultingRecipient.isEmpty() && address.pni().isPresent()) {
- resultingRecipient = recipients.stream().filter(r -> r.address().serviceId().equals(address.pni()) || (
- address.serviceId().equals(address.pni()) && r.address().pni().equals(address.pni())
- )).findFirst();
+ resultingRecipient = recipients.stream().filter(r -> r.address().pni().equals(address.pni())).findFirst();
}
final Set<RecipientWithAddress> remainingRecipients;
import java.util.Optional;
public record RecipientAddress(
- Optional<ServiceId> serviceId, Optional<PNI> pni, Optional<String> number, Optional<String> username
+ Optional<ACI> aci, Optional<PNI> pni, Optional<String> number, Optional<String> username
) {
/**
* Construct a RecipientAddress.
*
- * @param serviceId The ACI or PNI of the user, if available.
- * @param number The phone number of the user, if available.
+ * @param aci The ACI of the user, if available.
+ * @param pni The PNI of the user, if available.
+ * @param number The phone number of the user, if available.
+ * @param username The username of the user, if available.
*/
public RecipientAddress {
- if (serviceId.isPresent() && serviceId.get().isUnknown()) {
- serviceId = Optional.empty();
+ if (aci.isPresent() && aci.get().isUnknown()) {
+ aci = Optional.empty();
}
if (pni.isPresent() && pni.get().isUnknown()) {
pni = Optional.empty();
}
- if (serviceId.isEmpty() && pni.isPresent()) {
- serviceId = Optional.of(pni.get());
- }
- if (serviceId.isPresent() && serviceId.get() instanceof PNI sPNI) {
- if (pni.isPresent() && !sPNI.equals(pni.get())) {
- throw new AssertionError("Must not have two different PNIs!");
- }
- if (pni.isEmpty()) {
- pni = Optional.of(sPNI);
- }
- }
- if (serviceId.isEmpty() && number.isEmpty()) {
+ if (aci.isEmpty() && pni.isEmpty() && number.isEmpty()) {
throw new AssertionError("Must have either a ServiceId or E164 number!");
}
}
public RecipientAddress(Optional<ServiceId> serviceId, Optional<String> number) {
- this(serviceId, Optional.empty(), number, Optional.empty());
+ this(serviceId.filter(s -> s instanceof ACI).map(s -> (ACI) s),
+ serviceId.filter(s -> s instanceof PNI).map(s -> (PNI) s),
+ number,
+ Optional.empty());
+ }
+
+ public RecipientAddress(ACI aci, String e164) {
+ this(Optional.ofNullable(aci), Optional.empty(), Optional.ofNullable(e164), Optional.empty());
}
- public RecipientAddress(ServiceId serviceId, String e164) {
- this(Optional.ofNullable(serviceId), Optional.empty(), Optional.ofNullable(e164), Optional.empty());
+ public RecipientAddress(String e164) {
+ this(Optional.empty(), Optional.empty(), Optional.ofNullable(e164), Optional.empty());
}
- public RecipientAddress(ServiceId serviceId, PNI pni, String e164) {
- this(Optional.ofNullable(serviceId), Optional.ofNullable(pni), Optional.ofNullable(e164), Optional.empty());
+ public RecipientAddress(ACI aci, PNI pni, String e164) {
+ this(Optional.ofNullable(aci), Optional.ofNullable(pni), Optional.ofNullable(e164), Optional.empty());
}
- public RecipientAddress(ServiceId serviceId, PNI pni, String e164, String username) {
- this(Optional.ofNullable(serviceId),
+ public RecipientAddress(ACI aci, PNI pni, String e164, String username) {
+ this(Optional.ofNullable(aci),
Optional.ofNullable(pni),
Optional.ofNullable(e164),
Optional.ofNullable(username));
}
public RecipientAddress(SignalServiceAddress address) {
- this(Optional.of(address.getServiceId()), Optional.empty(), address.getNumber(), Optional.empty());
+ this(address.getServiceId() instanceof ACI ? Optional.of((ACI) address.getServiceId()) : Optional.empty(),
+ address.getServiceId() instanceof PNI ? Optional.of((PNI) address.getServiceId()) : Optional.empty(),
+ address.getNumber(),
+ Optional.empty());
}
public RecipientAddress(org.asamk.signal.manager.api.RecipientAddress address) {
}
public RecipientAddress withIdentifiersFrom(RecipientAddress address) {
- return new RecipientAddress((
- this.serviceId.isEmpty() || this.isServiceIdPNI() || this.serviceId.equals(address.pni)
- ) && !address.isServiceIdPNI() ? address.serviceId : this.serviceId,
+ return new RecipientAddress(address.aci.or(this::aci),
address.pni.or(this::pni),
address.number.or(this::number),
address.username.or(this::username));
}
public RecipientAddress removeIdentifiersFrom(RecipientAddress address) {
- return new RecipientAddress(address.serviceId.equals(this.serviceId) || address.pni.equals(this.serviceId)
- ? Optional.empty()
- : this.serviceId,
- address.pni.equals(this.pni) || address.serviceId.equals(this.pni) ? Optional.empty() : this.pni,
+ return new RecipientAddress(address.aci.equals(this.aci) ? Optional.empty() : this.aci,
+ address.pni.equals(this.pni) ? Optional.empty() : this.pni,
address.number.equals(this.number) ? Optional.empty() : this.number,
address.username.equals(this.username) ? Optional.empty() : this.username);
}
- public Optional<ACI> aci() {
- return serviceId.map(s -> s instanceof ServiceId.ACI aci ? aci : null);
+ public Optional<ServiceId> serviceId() {
+ return aci.map(aci -> (ServiceId) aci).or(this::pni);
}
public String getIdentifier() {
- if (serviceId.isPresent()) {
- return serviceId.get().toString();
+ if (aci.isPresent()) {
+ return aci.get().toString();
+ } else if (pni.isPresent()) {
+ return pni.get().toString();
} else if (number.isPresent()) {
return number.get();
} else {
public String getLegacyIdentifier() {
if (number.isPresent()) {
return number.get();
- } else if (serviceId.isPresent()) {
- return serviceId.get().toString();
+ } else if (aci.isPresent()) {
+ return aci.get().toString();
+ } else if (pni.isPresent()) {
+ return pni.get().toString();
} else {
throw new AssertionError("Given the checks in the constructor, this should not be possible.");
}
}
public boolean matches(RecipientAddress other) {
- return (serviceId.isPresent() && other.serviceId.isPresent() && serviceId.get().equals(other.serviceId.get()))
- || (
- pni.isPresent() && other.serviceId.isPresent() && pni.get().equals(other.serviceId.get())
- )
- || (
- serviceId.isPresent() && other.pni.isPresent() && serviceId.get().equals(other.pni.get())
- )
- || (
+ return (aci.isPresent() && other.aci.isPresent() && aci.get().equals(other.aci.get())) || (
pni.isPresent() && other.pni.isPresent() && pni.get().equals(other.pni.get())
- )
- || (
+ ) || (
number.isPresent() && other.number.isPresent() && number.get().equals(other.number.get())
);
}
public boolean hasSingleIdentifier() {
- final var identifiersCount = serviceId().map(s -> 1).orElse(0)
- + number().map(s -> 1).orElse(0)
- + username().map(s -> 1).orElse(0);
+ final var identifiersCount = aci().map(s -> 1).orElse(0) + pni().map(s -> 1).orElse(0) + number().map(s -> 1)
+ .orElse(0) + username().map(s -> 1).orElse(0);
return identifiersCount == 1;
}
public boolean hasIdentifiersOf(RecipientAddress address) {
- return (address.serviceId.isEmpty() || address.serviceId.equals(serviceId) || address.serviceId.equals(pni))
+ return (address.aci.isEmpty() || address.aci.equals(aci))
&& (address.pni.isEmpty() || address.pni.equals(pni))
&& (address.number.isEmpty() || address.number.equals(number))
&& (address.username.isEmpty() || address.username.equals(username));
public boolean hasAdditionalIdentifiersThan(RecipientAddress address) {
return (
- serviceId.isPresent() && (
- address.serviceId.isEmpty() || (
- !address.serviceId.equals(serviceId) && !address.pni.equals(serviceId)
- )
+ aci.isPresent() && (
+ address.aci.isEmpty() || !address.aci.equals(aci)
+
)
) || (
- pni.isPresent() && !address.serviceId.equals(pni) && (
+ pni.isPresent() && (
address.pni.isEmpty() || !address.pni.equals(pni)
)
) || (
}
public boolean hasOnlyPniAndNumber() {
- return pni.isPresent() && serviceId.equals(pni) && number.isPresent();
- }
-
- public boolean isServiceIdPNI() {
- return serviceId.isPresent() && (pni.isPresent() && serviceId.equals(pni));
+ return pni.isPresent() && aci.isEmpty() && number.isPresent();
}
public SignalServiceAddress toSignalServiceAddress() {
- return new SignalServiceAddress(serviceId.orElse(ACI.UNKNOWN), number);
+ return new SignalServiceAddress(aci.orElse(ACI.UNKNOWN), number);
}
public org.asamk.signal.manager.api.RecipientAddress toApiRecipientAddress() {
- return new org.asamk.signal.manager.api.RecipientAddress(serviceId().map(ServiceId::getRawUuid),
+ return new org.asamk.signal.manager.api.RecipientAddress(aci().map(ServiceId::getRawUuid),
number(),
username());
}
import org.whispersystems.signalservice.api.push.ServiceId.PNI;
import org.whispersystems.signalservice.api.push.SignalServiceAddress;
import org.whispersystems.signalservice.api.storage.StorageId;
-import org.whispersystems.signalservice.api.util.UuidUtil;
import java.sql.Connection;
import java.sql.ResultSet;
private static final Logger logger = LoggerFactory.getLogger(RecipientStore.class);
private static final String TABLE_RECIPIENT = "recipient";
- private static final String SQL_IS_CONTACT = "r.given_name IS NOT NULL OR r.family_name IS NOT NULL OR r.expiration_time > 0 OR r.profile_sharing = TRUE OR r.color IS NOT NULL OR r.blocked = TRUE OR r.archived = TRUE";
+ private static final String SQL_IS_CONTACT = "r.given_name IS NOT NULL OR r.family_name IS NOT NULL OR r.nick_name IS NOT NULL OR r.expiration_time > 0 OR r.profile_sharing = TRUE OR r.color IS NOT NULL OR r.blocked = TRUE OR r.archived = TRUE";
private final RecipientMergeHandler recipientMergeHandler;
private final SelfAddressProvider selfAddressProvider;
storage_record BLOB,
number TEXT UNIQUE,
username TEXT UNIQUE,
- uuid BLOB UNIQUE,
- pni BLOB UNIQUE,
+ aci TEXT UNIQUE,
+ pni TEXT UNIQUE,
unregistered_timestamp INTEGER,
profile_key BLOB,
profile_key_credential BLOB,
given_name TEXT,
family_name TEXT,
+ nick_name TEXT,
color TEXT,
expiration_time INTEGER NOT NULL DEFAULT 0,
+ mute_until INTEGER NOT NULL DEFAULT 0,
blocked INTEGER NOT NULL DEFAULT FALSE,
archived INTEGER NOT NULL DEFAULT FALSE,
profile_sharing INTEGER NOT NULL DEFAULT FALSE,
+ hide_story INTEGER NOT NULL DEFAULT FALSE,
hidden INTEGER NOT NULL DEFAULT FALSE,
profile_last_update_timestamp INTEGER NOT NULL DEFAULT 0,
public RecipientAddress resolveRecipientAddress(RecipientId recipientId) {
final var sql = (
"""
- SELECT r.number, r.uuid, r.pni, r.username
+ SELECT r.number, r.aci, r.pni, r.username
FROM %s r
WHERE r._id = ?
"""
public RecipientId resolveRecipientTrusted(
final Optional<ACI> aci, final Optional<PNI> pni, final Optional<String> number
) {
- final var serviceId = aci.map(a -> (ServiceId) a).or(() -> pni);
- return resolveRecipientTrusted(new RecipientAddress(serviceId, pni, number, Optional.empty()));
+ return resolveRecipientTrusted(new RecipientAddress(aci, pni, number, Optional.empty()));
}
@Override
public List<Pair<RecipientId, Contact>> getContacts() {
final var sql = (
"""
- SELECT r._id, r.given_name, r.family_name, r.expiration_time, r.profile_sharing, r.color, r.blocked, r.archived, r.hidden
+ SELECT r._id, r.given_name, r.family_name, r.nick_name, r.expiration_time, r.mute_until, r.hide_story, r.profile_sharing, r.color, r.blocked, r.archived, r.hidden, r.unregistered_timestamp
FROM %s r
- WHERE (r.number IS NOT NULL OR r.uuid IS NOT NULL) AND %s AND r.hidden = FALSE
+ WHERE (r.number IS NOT NULL OR r.aci IS NOT NULL) AND %s AND r.hidden = FALSE
"""
).formatted(TABLE_RECIPIENT, SQL_IS_CONTACT);
try (final var connection = database.getConnection()) {
final var sql = (
"""
SELECT r._id,
- r.number, r.uuid, r.pni, r.username,
+ r.number, r.aci, r.pni, r.username,
r.profile_key, r.profile_key_credential,
- r.given_name, r.family_name, r.expiration_time, r.profile_sharing, r.color, r.blocked, r.archived, r.hidden,
+ r.given_name, r.family_name, r.nick_name, r.expiration_time, r.mute_until, r.hide_story, r.profile_sharing, r.color, r.blocked, r.archived, r.hidden, r.unregistered_timestamp,
r.profile_last_update_timestamp, r.profile_given_name, r.profile_family_name, r.profile_about, r.profile_about_emoji, r.profile_avatar_url_path, r.profile_mobile_coin_address, r.profile_unidentified_access_mode, r.profile_capabilities,
r.storage_record
FROM %s r
final var sql = (
"""
SELECT r._id,
- r.number, r.uuid, r.pni, r.username,
+ r.number, r.aci, r.pni, r.username,
r.profile_key, r.profile_key_credential,
- r.given_name, r.family_name, r.expiration_time, r.profile_sharing, r.color, r.blocked, r.archived, r.hidden,
+ r.given_name, r.family_name, r.nick_name, r.expiration_time, r.mute_until, r.hide_story, r.profile_sharing, r.color, r.blocked, r.archived, r.hidden, r.unregistered_timestamp,
r.profile_last_update_timestamp, r.profile_given_name, r.profile_family_name, r.profile_about, r.profile_about_emoji, r.profile_avatar_url_path, r.profile_mobile_coin_address, r.profile_unidentified_access_mode, r.profile_capabilities,
r.storage_record
FROM %s r
final var sql = (
"""
SELECT r._id,
- r.number, r.uuid, r.pni, r.username,
+ r.number, r.aci, r.pni, r.username,
r.profile_key, r.profile_key_credential,
- r.given_name, r.family_name, r.expiration_time, r.profile_sharing, r.color, r.blocked, r.archived, r.hidden,
+ r.given_name, r.family_name, r.nick_name, r.expiration_time, r.mute_until, r.hide_story, r.profile_sharing, r.color, r.blocked, r.archived, r.hidden, r.unregistered_timestamp,
r.profile_last_update_timestamp, r.profile_given_name, r.profile_family_name, r.profile_about, r.profile_about_emoji, r.profile_avatar_url_path, r.profile_mobile_coin_address, r.profile_unidentified_access_mode, r.profile_capabilities,
r.storage_record
FROM %s r
- WHERE (r.number IS NOT NULL OR r.uuid IS NOT NULL) AND %s
+ WHERE (r.number IS NOT NULL OR r.aci IS NOT NULL) AND %s
"""
).formatted(TABLE_RECIPIENT, sqlWhere.isEmpty() ? "TRUE" : String.join(" AND ", sqlWhere));
- final var selfServiceId = selfAddressProvider.getSelfAddress().serviceId();
+ final var selfAddress = selfAddressProvider.getSelfAddress();
try (final var connection = database.getConnection()) {
try (final var statement = connection.prepareStatement(sql)) {
if (blocked.isPresent()) {
return result.filter(r -> name.isEmpty() || (
r.getContact() != null && name.get().equals(r.getContact().getName())
) || (r.getProfile() != null && name.get().equals(r.getProfile().getDisplayName()))).map(r -> {
- if (r.getAddress().serviceId().equals(selfServiceId)) {
+ if (r.getAddress().matches(selfAddress)) {
return Recipient.newBuilder(r)
.withProfileKey(selfProfileKeyProvider.getSelfProfileKey())
.build();
public Map<ServiceId, ProfileKey> getServiceIdToProfileKeyMap() {
final var sql = (
"""
- SELECT r.uuid, r.profile_key
+ SELECT r.aci, r.profile_key
FROM %s r
- WHERE r.uuid IS NOT NULL AND r.profile_key IS NOT NULL
+ WHERE r.aci IS NOT NULL AND r.profile_key IS NOT NULL
"""
).formatted(TABLE_RECIPIENT);
- final var selfServiceId = selfAddressProvider.getSelfAddress().serviceId().orElse(null);
+ final var selfAci = selfAddressProvider.getSelfAddress().aci().orElse(null);
try (final var connection = database.getConnection()) {
try (final var statement = connection.prepareStatement(sql)) {
return Utils.executeQueryForStream(statement, resultSet -> {
- final var serviceId = ServiceId.parseOrThrow(resultSet.getBytes("uuid"));
- if (serviceId.equals(selfServiceId)) {
- return new Pair<>(serviceId, selfProfileKeyProvider.getSelfProfileKey());
+ final var aci = ACI.parseOrThrow(resultSet.getString("aci"));
+ if (aci.equals(selfAci)) {
+ return new Pair<>(aci, selfProfileKeyProvider.getSelfProfileKey());
}
final var profileKey = getProfileKeyFromResultSet(resultSet);
- return new Pair<>(serviceId, profileKey);
+ return new Pair<>(aci, profileKey);
}).filter(Objects::nonNull).collect(Collectors.toMap(Pair::first, Pair::second));
}
} catch (SQLException e) {
"""
SELECT r._id
FROM %s r
- WHERE (r.number IS NOT NULL OR r.uuid IS NOT NULL)
+ WHERE (r.number IS NOT NULL OR r.aci IS NOT NULL)
"""
).formatted(TABLE_RECIPIENT);
try (final var statement = connection.prepareStatement(sql)) {
public List<StorageId> getStorageIds(Connection connection) throws SQLException {
final var sql = """
SELECT r.storage_id
- FROM %s r WHERE r.storage_id IS NOT NULL AND r._id != ? AND (r.uuid IS NOT NULL OR r.pni IS NOT NULL)
+ FROM %s r WHERE r.storage_id IS NOT NULL AND r._id != ? AND (r.aci IS NOT NULL OR r.pni IS NOT NULL)
""".formatted(TABLE_RECIPIENT);
final var selfRecipientId = resolveRecipient(connection, selfAddressProvider.getSelfAddress());
try (final var statement = connection.prepareStatement(sql)) {
long start = System.nanoTime();
final var sql = (
"""
- INSERT INTO %s (_id, number, uuid)
+ INSERT INTO %s (_id, number, aci)
VALUES (?, ?, ?)
"""
).formatted(TABLE_RECIPIENT);
for (final var recipient : recipients.values()) {
statement.setLong(1, recipient.getRecipientId().id());
statement.setString(2, recipient.getAddress().number().orElse(null));
- statement.setBytes(3,
- recipient.getAddress()
- .serviceId()
- .map(ServiceId::getRawUuid)
- .map(UuidUtil::toByteArray)
- .orElse(null));
+ statement.setString(3, recipient.getAddress().aci().map(ACI::toString).orElse(null));
statement.executeUpdate();
}
}
final var sql = (
"""
UPDATE %s
- SET given_name = ?, family_name = ?, expiration_time = ?, profile_sharing = ?, color = ?, blocked = ?, archived = ?
+ SET given_name = ?, family_name = ?, nick_name = ?, expiration_time = ?, mute_until = ?, hide_story = ?, profile_sharing = ?, color = ?, blocked = ?, archived = ?, unregistered_timestamp = ?
WHERE _id = ?
"""
).formatted(TABLE_RECIPIENT);
try (final var statement = connection.prepareStatement(sql)) {
statement.setString(1, contact == null ? null : contact.givenName());
statement.setString(2, contact == null ? null : contact.familyName());
- statement.setInt(3, contact == null ? 0 : contact.messageExpirationTime());
- statement.setBoolean(4, contact != null && contact.isProfileSharingEnabled());
- statement.setString(5, contact == null ? null : contact.color());
- statement.setBoolean(6, contact != null && contact.isBlocked());
- statement.setBoolean(7, contact != null && contact.isArchived());
- statement.setLong(8, recipientId.id());
+ statement.setString(3, contact == null ? null : contact.nickName());
+ statement.setInt(4, contact == null ? 0 : contact.messageExpirationTime());
+ statement.setLong(5, contact == null ? 0 : contact.muteUntil());
+ statement.setBoolean(6, contact != null && contact.hideStory());
+ statement.setBoolean(7, contact != null && contact.isProfileSharingEnabled());
+ statement.setString(8, contact == null ? null : contact.color());
+ statement.setBoolean(9, contact != null && contact.isBlocked());
+ statement.setBoolean(10, contact != null && contact.isArchived());
+ if (contact == null || contact.unregisteredTimestamp() == null) {
+ statement.setNull(11, Types.INTEGER);
+ } else {
+ statement.setLong(11, contact.unregisteredTimestamp());
+ }
+ statement.setLong(12, recipientId.id());
statement.executeUpdate();
}
rotateStorageId(connection, recipientId);
private RecipientId resolveRecipientLocked(
Connection connection, RecipientAddress address
) throws SQLException {
- final var aci = address.aci().isEmpty()
+ final var byAci = address.aci().isEmpty()
? Optional.<RecipientWithAddress>empty()
: findByServiceId(connection, address.aci().get());
- if (aci.isPresent()) {
- return aci.get().id();
+ if (byAci.isPresent()) {
+ return byAci.get().id();
}
final var byPni = address.pni().isEmpty()
if (recipient.isEmpty()) {
logger.debug("Got new recipient, number is unknown");
- return addNewRecipient(connection, new RecipientAddress(null, number));
+ return addNewRecipient(connection, new RecipientAddress(number));
}
return recipient.get().id();
) throws SQLException {
final var sql = (
"""
- INSERT INTO %s (number, uuid, pni, username)
+ INSERT INTO %s (number, aci, pni, username)
VALUES (?, ?, ?, ?)
RETURNING _id
"""
).formatted(TABLE_RECIPIENT);
try (final var statement = connection.prepareStatement(sql)) {
statement.setString(1, address.number().orElse(null));
- statement.setBytes(2, address.aci().map(ServiceId::getRawUuid).map(UuidUtil::toByteArray).orElse(null));
- statement.setBytes(3, address.pni().map(PNI::getRawUuid).map(UuidUtil::toByteArray).orElse(null));
+ statement.setString(2, address.aci().map(ACI::toString).orElse(null));
+ statement.setString(3, address.pni().map(PNI::toString).orElse(null));
statement.setString(4, address.username().orElse(null));
final var generatedKey = Utils.executeQueryForOptional(statement, Utils::getIdMapper);
if (generatedKey.isPresent()) {
final var sql = (
"""
UPDATE %s
- SET number = NULL, uuid = NULL, pni = NULL, username = NULL, storage_id = NULL
+ SET number = NULL, aci = NULL, pni = NULL, username = NULL, storage_id = NULL
WHERE _id = ?
"""
).formatted(TABLE_RECIPIENT);
final var sql = (
"""
UPDATE %s
- SET number = ?, uuid = ?, pni = ?, username = ?
+ SET number = ?, aci = ?, pni = ?, username = ?
WHERE _id = ?
"""
).formatted(TABLE_RECIPIENT);
try (final var statement = connection.prepareStatement(sql)) {
statement.setString(1, address.number().orElse(null));
- statement.setBytes(2, address.aci().map(ServiceId::getRawUuid).map(UuidUtil::toByteArray).orElse(null));
- statement.setBytes(3, address.pni().map(PNI::getRawUuid).map(UuidUtil::toByteArray).orElse(null));
+ statement.setString(2, address.aci().map(ACI::toString).orElse(null));
+ statement.setString(3, address.pni().map(PNI::toString).orElse(null));
statement.setString(4, address.username().orElse(null));
statement.setLong(5, recipientId.id());
statement.executeUpdate();
final Connection connection, final String number
) throws SQLException {
final var sql = """
- SELECT r._id, r.number, r.uuid, r.pni, r.username
+ SELECT r._id, r.number, r.aci, r.pni, r.username
FROM %s r
WHERE r.number = ?
LIMIT 1
final Connection connection, final String username
) throws SQLException {
final var sql = """
- SELECT r._id, r.number, r.uuid, r.pni, r.username
+ SELECT r._id, r.number, r.aci, r.pni, r.username
FROM %s r
WHERE r.username = ?
LIMIT 1
return recipientWithAddress;
}
final var sql = """
- SELECT r._id, r.number, r.uuid, r.pni, r.username
+ SELECT r._id, r.number, r.aci, r.pni, r.username
FROM %s r
WHERE %s = ?1
LIMIT 1
- """.formatted(TABLE_RECIPIENT, serviceId instanceof ACI ? "r.uuid" : "r.pni");
+ """.formatted(TABLE_RECIPIENT, serviceId instanceof ACI ? "r.aci" : "r.pni");
try (final var statement = connection.prepareStatement(sql)) {
- statement.setBytes(1, UuidUtil.toByteArray(serviceId.getRawUuid()));
+ statement.setString(1, serviceId.toString());
recipientWithAddress = Utils.executeQueryForOptional(statement, this::getRecipientWithAddressFromResultSet);
recipientWithAddress.ifPresent(r -> recipientAddressCache.put(serviceId, r));
return recipientWithAddress;
final Connection connection, final RecipientAddress address
) throws SQLException {
final var sql = """
- SELECT r._id, r.number, r.uuid, r.pni, r.username
+ SELECT r._id, r.number, r.aci, r.pni, r.username
FROM %s r
- WHERE r.uuid = ?1 OR
+ WHERE r.aci = ?1 OR
r.pni = ?2 OR
r.number = ?3 OR
r.username = ?4
""".formatted(TABLE_RECIPIENT);
try (final var statement = connection.prepareStatement(sql)) {
- statement.setBytes(1, address.aci().map(ServiceId::getRawUuid).map(UuidUtil::toByteArray).orElse(null));
- statement.setBytes(2, address.pni().map(ServiceId::getRawUuid).map(UuidUtil::toByteArray).orElse(null));
+ statement.setString(1, address.aci().map(ServiceId::toString).orElse(null));
+ statement.setString(2, address.pni().map(ServiceId::toString).orElse(null));
statement.setString(3, address.number().orElse(null));
statement.setString(4, address.username().orElse(null));
return Utils.executeQueryForStream(statement, this::getRecipientWithAddressFromResultSet)
private Contact getContact(final Connection connection, final RecipientId recipientId) throws SQLException {
final var sql = (
"""
- SELECT r.given_name, r.family_name, r.expiration_time, r.profile_sharing, r.color, r.blocked, r.archived, r.hidden
+ SELECT r.given_name, r.family_name, r.nick_name, r.expiration_time, r.mute_until, r.hide_story, r.profile_sharing, r.color, r.blocked, r.archived, r.hidden, r.unregistered_timestamp
FROM %s r
WHERE r._id = ? AND (%s)
"""
}
private RecipientAddress getRecipientAddressFromResultSet(ResultSet resultSet) throws SQLException {
- final var pni = Optional.ofNullable(resultSet.getBytes("pni")).map(UuidUtil::parseOrNull).map(PNI::from);
- final var serviceIdUuid = Optional.ofNullable(resultSet.getBytes("uuid")).map(UuidUtil::parseOrNull);
- final var serviceId = serviceIdUuid.isPresent() && pni.isPresent() && serviceIdUuid.get()
- .equals(pni.get().getRawUuid()) ? pni.<ServiceId>map(p -> p) : serviceIdUuid.<ServiceId>map(ACI::from);
+ final var aci = Optional.ofNullable(resultSet.getString("aci")).map(ACI::parseOrThrow);
+ final var pni = Optional.ofNullable(resultSet.getString("pni")).map(PNI::parseOrThrow);
final var number = Optional.ofNullable(resultSet.getString("number"));
final var username = Optional.ofNullable(resultSet.getString("username"));
- return new RecipientAddress(serviceId, pni, number, username);
+ return new RecipientAddress(aci, pni, number, username);
}
private RecipientId getRecipientIdFromResultSet(ResultSet resultSet) throws SQLException {
}
private Contact getContactFromResultSet(ResultSet resultSet) throws SQLException {
+ final var unregisteredTimestamp = resultSet.getLong("unregistered_timestamp");
return new Contact(resultSet.getString("given_name"),
resultSet.getString("family_name"),
+ resultSet.getString("nick_name"),
resultSet.getString("color"),
resultSet.getInt("expiration_time"),
+ resultSet.getLong("mute_until"),
+ resultSet.getBoolean("hide_story"),
resultSet.getBoolean("blocked"),
resultSet.getBoolean("archived"),
resultSet.getBoolean("profile_sharing"),
- resultSet.getBoolean("hidden"));
+ resultSet.getBoolean("hidden"),
+ unregisteredTimestamp == 0 ? null : unregisteredTimestamp);
}
private Profile getProfileFromResultSet(ResultSet resultSet) throws SQLException {
final var profileShared = contact != null && contact.isProfileSharingEnabled();
final var archived = contact != null && contact.isArchived();
final var hidden = contact != null && contact.isHidden();
+ final var hideStory = contact != null && contact.hideStory();
+ final var muteUntil = contact == null ? 0 : contact.muteUntil();
+ final var unregisteredTimestamp = contact == null || contact.unregisteredTimestamp() == null
+ ? 0
+ : contact.unregisteredTimestamp();
final var contactGivenName = contact == null ? null : contact.givenName();
final var contactFamilyName = contact == null ? null : contact.familyName();
+ final var contactNickName = contact == null ? null : contact.nickName();
if (blocked != contactRecord.isBlocked()
|| profileShared != contactRecord.isProfileSharingEnabled()
|| archived != contactRecord.isArchived()
|| hidden != contactRecord.isHidden()
+ || hideStory != contactRecord.shouldHideStory()
+ || muteUntil != contactRecord.getMuteUntil()
+ || unregisteredTimestamp != contactRecord.getUnregisteredTimestamp()
|| !Objects.equals(contactRecord.getSystemGivenName().orElse(null), contactGivenName)
- || !Objects.equals(contactRecord.getSystemFamilyName().orElse(null), contactFamilyName)) {
+ || !Objects.equals(contactRecord.getSystemFamilyName().orElse(null), contactFamilyName)
+ || !Objects.equals(contactRecord.getSystemNickname().orElse(null), contactNickName)) {
logger.debug("Storing new or updated contact {}", recipientId);
final var contactBuilder = contact == null ? Contact.newBuilder() : Contact.newBuilder(contact);
final var newContact = contactBuilder.withIsBlocked(contactRecord.isBlocked())
.withIsProfileSharingEnabled(contactRecord.isProfileSharingEnabled())
.withIsArchived(contactRecord.isArchived())
.withIsHidden(contactRecord.isHidden())
+ .withMuteUntil(contactRecord.getMuteUntil())
+ .withHideStory(contactRecord.shouldHideStory())
.withGivenName(contactRecord.getSystemGivenName().orElse(null))
- .withFamilyName(contactRecord.getSystemFamilyName().orElse(null));
+ .withFamilyName(contactRecord.getSystemFamilyName().orElse(null))
+ .withNickName(contactRecord.getSystemNickname().orElse(null))
+ .withUnregisteredTimestamp(contactRecord.getUnregisteredTimestamp() == 0
+ ? null
+ : contactRecord.getUnregisteredTimestamp());
account.getRecipientStore().storeContact(connection, recipientId, newContact.build());
}
}
if (recipient.getContact() != null) {
builder.setSystemGivenName(recipient.getContact().givenName())
- .setSystemFamilyName((recipient.getContact().familyName()))
+ .setSystemFamilyName(recipient.getContact().familyName())
+ .setSystemNickname(recipient.getContact().nickName())
.setBlocked(recipient.getContact().isBlocked())
.setProfileSharingEnabled(recipient.getContact().isProfileSharingEnabled())
+ .setMuteUntil(recipient.getContact().muteUntil())
+ .setHideStory(recipient.getContact().hideStory())
+ .setUnregisteredTimestamp(recipient.getContact().unregisteredTimestamp() == null
+ ? 0
+ : recipient.getContact().unregisteredTimestamp())
.setArchived(recipient.getContact().isArchived())
.setHidden(recipient.getContact().isHidden());
}
import org.signal.core.util.SetUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import org.whispersystems.signalservice.api.push.ServiceId;
import org.whispersystems.signalservice.api.storage.SignalStorageManifest;
import org.whispersystems.signalservice.api.storage.SignalStorageRecord;
import org.whispersystems.signalservice.api.storage.StorageId;
if (insert.getContact().isPresent()) {
final var contact = insert.getContact().get();
- final var serviceId = contact.getServiceId().map(ServiceId.class::cast);
+ final var aci = contact.getAci();
final var pni = contact.getPni();
final var number = contact.getNumber();
final var username = contact.getUsername();
- final var address = new RecipientAddress(serviceId, pni, number, username);
+ final var address = new RecipientAddress(aci, pni, number, username);
if (self.matches(address)) {
throw new SelfAddedAsContactError();
}
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource;
-import org.whispersystems.signalservice.api.push.ServiceId;
+import org.whispersystems.signalservice.api.push.ServiceId.ACI;
import org.whispersystems.signalservice.api.push.ServiceId.PNI;
import java.util.Arrays;
class MergeRecipientHelperTest {
- static final ServiceId SERVICE_ID_A = ServiceId.ACI.from(UUID.randomUUID());
- static final ServiceId SERVICE_ID_B = ServiceId.ACI.from(UUID.randomUUID());
+ static final ACI ACI_A = ACI.from(UUID.randomUUID());
+ static final ACI ACI_B = ACI.from(UUID.randomUUID());
static final PNI PNI_A = PNI.from(UUID.randomUUID());
static final PNI PNI_B = PNI.from(UUID.randomUUID());
static final String NUMBER_A = "+AAA";
static final String USERNAME_A = "USER.1";
static final String USERNAME_B = "USER.2";
- static final PartialAddresses ADDR_A = new PartialAddresses(SERVICE_ID_A, PNI_A, NUMBER_A, USERNAME_A);
- static final PartialAddresses ADDR_B = new PartialAddresses(SERVICE_ID_B, PNI_B, NUMBER_B, USERNAME_B);
+ static final PartialAddresses ADDR_A = new PartialAddresses(ACI_A, PNI_A, NUMBER_A, USERNAME_A);
+ static final PartialAddresses ADDR_B = new PartialAddresses(ACI_B, PNI_B, NUMBER_B, USERNAME_B);
static final T[] testInstancesNone = new T[]{
new T(Set.of(), ADDR_A.FULL, Set.of(rec(1000000, ADDR_A.FULL))),
new T(Set.of(rec(1, ADDR_A.PNI)), ADDR_A.ACI_NUM, Set.of(rec(1, ADDR_A.PNI), rec(1000000, ADDR_A.ACI_NUM))),
new T(Set.of(rec(1, ADDR_A.NUM)), ADDR_A.ACI_NUM, Set.of(rec(1, ADDR_A.ACI_NUM))),
new T(Set.of(rec(1, ADDR_A.ACI_NUM)), ADDR_A.ACI_NUM, Set.of(rec(1, ADDR_A.ACI_NUM))),
- new T(Set.of(rec(1, ADDR_A.PNI_NUM)),
- ADDR_A.ACI_NUM,
- Set.of(rec(1, ADDR_A.PNI), rec(1000000, ADDR_A.ACI_NUM))),
+ new T(Set.of(rec(1, ADDR_A.PNI_NUM)), ADDR_A.ACI_NUM, Set.of(rec(1, ADDR_A.FULL))),
new T(Set.of(rec(1, ADDR_A.ACI_PNI)), ADDR_A.ACI_NUM, Set.of(rec(1, ADDR_A.FULL))),
new T(Set.of(rec(1, ADDR_A.FULL)), ADDR_A.PNI_NUM, Set.of(rec(1, ADDR_A.FULL))),
@Override
public String toString() {
return "T{#input=%s, request=%s_%s_%s, #output=%s}".formatted(input.size(),
- request.serviceId().isPresent() ? "SVI" : "",
+ request.aci().isPresent() ? "ACI" : "",
request.pni().isPresent() ? "PNI" : "",
request.number().isPresent() ? "NUM" : "",
output.size());
RecipientAddress ACI_USERNAME
) {
- PartialAddresses(ServiceId serviceId, PNI pni, String number, String username) {
- this(new RecipientAddress(serviceId, pni, number),
- new RecipientAddress(serviceId, pni, number, username),
- new RecipientAddress(serviceId, null, null),
+ PartialAddresses(ACI aci, PNI pni, String number, String username) {
+ this(new RecipientAddress(aci, pni, number),
+ new RecipientAddress(aci, pni, number, username),
+ new RecipientAddress(aci, null, null),
new RecipientAddress(null, pni, null),
new RecipientAddress(null, null, number),
- new RecipientAddress(serviceId, null, number),
- new RecipientAddress(serviceId, null, number, username),
+ new RecipientAddress(aci, null, number),
+ new RecipientAddress(aci, null, number, username),
new RecipientAddress(null, pni, number),
- new RecipientAddress(serviceId, pni, null),
- new RecipientAddress(serviceId, null, null, username));
+ new RecipientAddress(aci, pni, null),
+ new RecipientAddress(aci, null, null, username));
}
}
}
}
return Recipient.newBuilder()
.withAddress(new RecipientAddress(null, n))
- .withContact(new Contact(contactName, null, null, 0, contactBlocked, false, false, false))
+ .withContact(new Contact(contactName,
+ null,
+ null,
+ null,
+ 0,
+ 0,
+ false,
+ contactBlocked,
+ false,
+ false,
+ false,
+ null))
.build();
}).filter(Objects::nonNull).toList();
}