]> nmode's Git Repositories - signal-cli/blob - lib/src/main/java/org/asamk/signal/manager/storage/recipients/RecipientAddress.java
6f796b4a61031e3a11a2328242fcddf903f79111
[signal-cli] / lib / src / main / java / org / asamk / signal / manager / storage / recipients / RecipientAddress.java
1 package org.asamk.signal.manager.storage.recipients;
2
3 import org.whispersystems.signalservice.api.push.PNI;
4 import org.whispersystems.signalservice.api.push.ServiceId;
5 import org.whispersystems.signalservice.api.push.SignalServiceAddress;
6
7 import java.util.Optional;
8
9 public record RecipientAddress(Optional<ServiceId> serviceId, Optional<PNI> pni, Optional<String> number) {
10
11 /**
12 * Construct a RecipientAddress.
13 *
14 * @param serviceId The ACI or PNI of the user, if available.
15 * @param number The phone number of the user, if available.
16 */
17 public RecipientAddress {
18 if (serviceId.isPresent() && serviceId.get().equals(ServiceId.UNKNOWN)) {
19 serviceId = Optional.empty();
20 }
21 if (pni.isPresent() && pni.get().equals(ServiceId.UNKNOWN)) {
22 pni = Optional.empty();
23 }
24 if (serviceId.isEmpty() && pni.isPresent()) {
25 serviceId = Optional.of(pni.get());
26 }
27 if (serviceId.isPresent() && serviceId.get() instanceof PNI sPNI) {
28 if (pni.isPresent() && !sPNI.equals(pni.get())) {
29 throw new AssertionError("Must not have two different PNIs!");
30 }
31 if (pni.isEmpty()) {
32 pni = Optional.of(sPNI);
33 }
34 }
35 if (serviceId.isEmpty() && number.isEmpty()) {
36 throw new AssertionError("Must have either a ServiceId or E164 number!");
37 }
38 }
39
40 public RecipientAddress(Optional<ServiceId> serviceId, Optional<String> number) {
41 this(serviceId, Optional.empty(), number);
42 }
43
44 public RecipientAddress(ServiceId serviceId, String e164) {
45 this(Optional.ofNullable(serviceId), Optional.empty(), Optional.ofNullable(e164));
46 }
47
48 public RecipientAddress(ServiceId serviceId, PNI pni, String e164) {
49 this(Optional.ofNullable(serviceId), Optional.ofNullable(pni), Optional.ofNullable(e164));
50 }
51
52 public RecipientAddress(SignalServiceAddress address) {
53 this(Optional.of(address.getServiceId()), Optional.empty(), address.getNumber());
54 }
55
56 public RecipientAddress(org.asamk.signal.manager.api.RecipientAddress address) {
57 this(address.uuid().map(ServiceId::from), Optional.empty(), address.number());
58 }
59
60 public RecipientAddress(ServiceId serviceId) {
61 this(Optional.of(serviceId), Optional.empty());
62 }
63
64 public RecipientAddress withIdentifiersFrom(RecipientAddress address) {
65 return new RecipientAddress((
66 this.serviceId.isEmpty() || this.isServiceIdPNI() || this.serviceId.equals(address.pni)
67 ) && !address.isServiceIdPNI() ? address.serviceId : this.serviceId,
68 address.pni.or(this::pni),
69 address.number.or(this::number));
70 }
71
72 public RecipientAddress removeIdentifiersFrom(RecipientAddress address) {
73 return new RecipientAddress(address.serviceId.equals(this.serviceId) || address.pni.equals(this.serviceId)
74 ? Optional.empty()
75 : this.serviceId,
76 address.pni.equals(this.pni) || address.serviceId.equals(this.pni) ? Optional.empty() : this.pni,
77 address.number.equals(this.number) ? Optional.empty() : this.number);
78 }
79
80 public ServiceId getServiceId() {
81 return serviceId.orElse(ServiceId.UNKNOWN);
82 }
83
84 public String getIdentifier() {
85 if (serviceId.isPresent()) {
86 return serviceId.get().toString();
87 } else if (number.isPresent()) {
88 return number.get();
89 } else {
90 throw new AssertionError("Given the checks in the constructor, this should not be possible.");
91 }
92 }
93
94 public String getLegacyIdentifier() {
95 if (number.isPresent()) {
96 return number.get();
97 } else if (serviceId.isPresent()) {
98 return serviceId.get().toString();
99 } else {
100 throw new AssertionError("Given the checks in the constructor, this should not be possible.");
101 }
102 }
103
104 public boolean matches(RecipientAddress other) {
105 return (serviceId.isPresent() && other.serviceId.isPresent() && serviceId.get().equals(other.serviceId.get()))
106 || (
107 pni.isPresent() && other.serviceId.isPresent() && pni.get().equals(other.serviceId.get())
108 )
109 || (
110 serviceId.isPresent() && other.pni.isPresent() && serviceId.get().equals(other.pni.get())
111 )
112 || (
113 pni.isPresent() && other.pni.isPresent() && pni.get().equals(other.pni.get())
114 )
115 || (
116 number.isPresent() && other.number.isPresent() && number.get().equals(other.number.get())
117 );
118 }
119
120 public boolean hasSingleIdentifier() {
121 return serviceId().isEmpty() || number.isEmpty();
122 }
123
124 public boolean hasIdentifiersOf(RecipientAddress address) {
125 return (address.serviceId.isEmpty() || address.serviceId.equals(serviceId) || address.serviceId.equals(pni))
126 && (address.pni.isEmpty() || address.pni.equals(pni))
127 && (address.number.isEmpty() || address.number.equals(number));
128 }
129
130 public boolean hasAdditionalIdentifiersThan(RecipientAddress address) {
131 return (
132 serviceId.isPresent() && (
133 address.serviceId.isEmpty() || (
134 !address.serviceId.equals(serviceId) && !address.pni.equals(serviceId)
135 )
136 )
137 ) || (
138 pni.isPresent() && !address.serviceId.equals(pni) && (
139 address.pni.isEmpty() || !address.pni.equals(pni)
140 )
141 ) || (
142 number.isPresent() && (
143 address.number.isEmpty() || !address.number.equals(number)
144 )
145 );
146 }
147
148 public boolean hasOnlyPniAndNumber() {
149 return pni.isPresent() && serviceId.equals(pni) && number.isPresent();
150 }
151
152 public boolean isServiceIdPNI() {
153 return serviceId.isPresent() && (pni.isPresent() && serviceId.equals(pni));
154 }
155
156 public SignalServiceAddress toSignalServiceAddress() {
157 return new SignalServiceAddress(getServiceId(), number);
158 }
159
160 public org.asamk.signal.manager.api.RecipientAddress toApiRecipientAddress() {
161 return new org.asamk.signal.manager.api.RecipientAddress(serviceId().map(ServiceId::uuid), number());
162 }
163 }