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