package org.asamk.signal.manager.api;
-import org.asamk.signal.manager.groups.GroupId;
-import org.asamk.signal.manager.storage.recipients.RecipientAddress;
-import org.whispersystems.signalservice.api.push.SignalServiceAddress;
-import org.whispersystems.signalservice.api.util.InvalidNumberException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
import org.whispersystems.signalservice.api.util.PhoneNumberFormatter;
import org.whispersystems.signalservice.api.util.UuidUtil;
import java.util.UUID;
-public sealed abstract class RecipientIdentifier {
+public sealed interface RecipientIdentifier {
- public static final class NoteToSelf extends RecipientIdentifier {
+ String getIdentifier();
- public static NoteToSelf INSTANCE = new NoteToSelf();
+ record NoteToSelf() implements RecipientIdentifier {
- private NoteToSelf() {
- }
- }
-
- public sealed static abstract class Single extends RecipientIdentifier {
+ public static final NoteToSelf INSTANCE = new NoteToSelf();
- public static Single fromString(String identifier, String localNumber) throws InvalidNumberException {
- return UuidUtil.isUuid(identifier)
- ? new Uuid(UUID.fromString(identifier))
- : new Number(PhoneNumberFormatter.formatNumber(identifier, localNumber));
+ @Override
+ public String getIdentifier() {
+ return "Note-To-Self";
}
+ }
- public static Single fromAddress(SignalServiceAddress address) {
- return new Uuid(address.getUuid());
+ sealed interface Single extends RecipientIdentifier {
+
+ static Single fromString(String identifier, String localNumber) throws InvalidNumberException {
+ try {
+ if (UuidUtil.isUuid(identifier)) {
+ return new Uuid(UUID.fromString(identifier));
+ }
+
+ if (identifier.startsWith("PNI:")) {
+ final var pni = identifier.substring(4);
+ if (!UuidUtil.isUuid(pni)) {
+ throw new InvalidNumberException("Invalid PNI");
+ }
+ return new Pni(UUID.fromString(pni));
+ }
+
+ if (identifier.startsWith("u:")) {
+ return new Username(identifier.substring(2));
+ }
+
+ final var normalizedNumber = PhoneNumberFormatter.formatNumber(identifier, localNumber);
+ if (!normalizedNumber.equals(identifier)) {
+ final Logger logger = LoggerFactory.getLogger(RecipientIdentifier.class);
+ logger.debug("Normalized number {} to {}.", identifier, normalizedNumber);
+ }
+ return new Number(normalizedNumber);
+ } catch (org.whispersystems.signalservice.api.util.InvalidNumberException e) {
+ throw new InvalidNumberException(e.getMessage(), e);
+ }
}
- public static Single fromAddress(RecipientAddress address) {
- if (address.getNumber().isPresent()) {
- return new Number(address.getNumber().get());
- } else if (address.getUuid().isPresent()) {
- return new Uuid(address.getUuid().get());
+ static Single fromAddress(RecipientAddress address) {
+ if (address.number().isPresent()) {
+ return new Number(address.number().get());
+ } else if (address.aci().isPresent()) {
+ return new Uuid(UUID.fromString(address.aci().get()));
+ } else if (address.pni().isPresent()) {
+ return new Pni(UUID.fromString(address.pni().get().substring(4)));
+ } else if (address.username().isPresent()) {
+ return new Username(address.username().get());
}
throw new AssertionError("RecipientAddress without identifier");
}
- public abstract String getIdentifier();
+ RecipientAddress toPartialRecipientAddress();
}
- public static final class Uuid extends Single {
-
- public final UUID uuid;
-
- public Uuid(final UUID uuid) {
- this.uuid = uuid;
- }
+ record Uuid(UUID uuid) implements Single {
@Override
- public boolean equals(final Object o) {
- if (this == o) return true;
- if (o == null || getClass() != o.getClass()) return false;
-
- final Uuid uuid1 = (Uuid) o;
-
- return uuid.equals(uuid1.uuid);
- }
-
- @Override
- public int hashCode() {
- return uuid.hashCode();
+ public String getIdentifier() {
+ return uuid.toString();
}
@Override
- public String getIdentifier() {
- return uuid.toString();
+ public RecipientAddress toPartialRecipientAddress() {
+ return new RecipientAddress(uuid);
}
}
- public static final class Number extends Single {
-
- public final String number;
-
- public Number(final String number) {
- this.number = number;
- }
+ record Pni(UUID pni) implements Single {
@Override
- public boolean equals(final Object o) {
- if (this == o) return true;
- if (o == null || getClass() != o.getClass()) return false;
-
- final Number number1 = (Number) o;
-
- return number.equals(number1.number);
+ public String getIdentifier() {
+ return "PNI:" + pni.toString();
}
@Override
- public int hashCode() {
- return number.hashCode();
+ public RecipientAddress toPartialRecipientAddress() {
+ return new RecipientAddress(null, getIdentifier(), null, null);
}
+ }
+
+ record Number(String number) implements Single {
@Override
public String getIdentifier() {
return number;
}
- }
- public static final class Group extends RecipientIdentifier {
+ @Override
+ public RecipientAddress toPartialRecipientAddress() {
+ return new RecipientAddress(number);
+ }
+ }
- public final GroupId groupId;
+ record Username(String username) implements Single {
- public Group(final GroupId groupId) {
- this.groupId = groupId;
+ @Override
+ public String getIdentifier() {
+ return "u:" + username;
}
@Override
- public boolean equals(final Object o) {
- if (this == o) return true;
- if (o == null || getClass() != o.getClass()) return false;
-
- final Group group = (Group) o;
-
- return groupId.equals(group.groupId);
+ public RecipientAddress toPartialRecipientAddress() {
+ return new RecipientAddress(null, null, null, username);
}
+ }
+
+ record Group(GroupId groupId) implements RecipientIdentifier {
@Override
- public int hashCode() {
- return groupId.hashCode();
+ public String getIdentifier() {
+ return groupId.toBase64();
}
}
}