]> nmode's Git Repositories - signal-cli/blob - lib/src/main/java/org/asamk/signal/manager/Manager.java
Make send behavior more deterministic if there are unregistered recipients
[signal-cli] / lib / src / main / java / org / asamk / signal / manager / Manager.java
1 package org.asamk.signal.manager;
2
3 import org.asamk.signal.manager.api.Configuration;
4 import org.asamk.signal.manager.api.Device;
5 import org.asamk.signal.manager.api.Group;
6 import org.asamk.signal.manager.api.Identity;
7 import org.asamk.signal.manager.api.InactiveGroupLinkException;
8 import org.asamk.signal.manager.api.InvalidDeviceLinkException;
9 import org.asamk.signal.manager.api.Message;
10 import org.asamk.signal.manager.api.MessageEnvelope;
11 import org.asamk.signal.manager.api.Pair;
12 import org.asamk.signal.manager.api.RecipientIdentifier;
13 import org.asamk.signal.manager.api.SendGroupMessageResults;
14 import org.asamk.signal.manager.api.SendMessageResults;
15 import org.asamk.signal.manager.api.TypingAction;
16 import org.asamk.signal.manager.api.UpdateGroup;
17 import org.asamk.signal.manager.config.ServiceConfig;
18 import org.asamk.signal.manager.config.ServiceEnvironment;
19 import org.asamk.signal.manager.groups.GroupId;
20 import org.asamk.signal.manager.groups.GroupInviteLinkUrl;
21 import org.asamk.signal.manager.groups.GroupNotFoundException;
22 import org.asamk.signal.manager.groups.GroupSendingNotAllowedException;
23 import org.asamk.signal.manager.groups.LastGroupAdminException;
24 import org.asamk.signal.manager.groups.NotAGroupMemberException;
25 import org.asamk.signal.manager.storage.SignalAccount;
26 import org.asamk.signal.manager.storage.identities.TrustNewIdentity;
27 import org.asamk.signal.manager.storage.recipients.Contact;
28 import org.asamk.signal.manager.storage.recipients.Profile;
29 import org.asamk.signal.manager.storage.recipients.RecipientAddress;
30 import org.whispersystems.signalservice.api.util.PhoneNumberFormatter;
31
32 import java.io.Closeable;
33 import java.io.File;
34 import java.io.IOException;
35 import java.net.URI;
36 import java.util.Arrays;
37 import java.util.List;
38 import java.util.Map;
39 import java.util.Optional;
40 import java.util.Set;
41 import java.util.UUID;
42 import java.util.concurrent.TimeUnit;
43 import java.util.stream.Collectors;
44
45 public interface Manager extends Closeable {
46
47 static Manager init(
48 String number,
49 File settingsPath,
50 ServiceEnvironment serviceEnvironment,
51 String userAgent,
52 TrustNewIdentity trustNewIdentity
53 ) throws IOException, NotRegisteredException {
54 var pathConfig = PathConfig.createDefault(settingsPath);
55
56 if (!SignalAccount.userExists(pathConfig.dataPath(), number)) {
57 throw new NotRegisteredException();
58 }
59
60 var account = SignalAccount.load(pathConfig.dataPath(), number, true, trustNewIdentity);
61
62 if (!account.isRegistered()) {
63 throw new NotRegisteredException();
64 }
65
66 final var serviceEnvironmentConfig = ServiceConfig.getServiceEnvironmentConfig(serviceEnvironment, userAgent);
67
68 return new ManagerImpl(account, pathConfig, serviceEnvironmentConfig, userAgent);
69 }
70
71 static void initLogger() {
72 LibSignalLogger.initLogger();
73 }
74
75 static boolean isValidNumber(final String e164Number, final String countryCode) {
76 return PhoneNumberFormatter.isValidNumber(e164Number, countryCode);
77 }
78
79 static List<String> getAllLocalAccountNumbers(File settingsPath) {
80 var pathConfig = PathConfig.createDefault(settingsPath);
81 final var dataPath = pathConfig.dataPath();
82 final var files = dataPath.listFiles();
83
84 if (files == null) {
85 return List.of();
86 }
87
88 return Arrays.stream(files)
89 .filter(File::isFile)
90 .map(File::getName)
91 .filter(file -> PhoneNumberFormatter.isValidNumber(file, null))
92 .collect(Collectors.toList());
93 }
94
95 String getSelfNumber();
96
97 void checkAccountState() throws IOException;
98
99 Map<String, Pair<String, UUID>> areUsersRegistered(Set<String> numbers) throws IOException;
100
101 void updateAccountAttributes(String deviceName) throws IOException;
102
103 Configuration getConfiguration();
104
105 void updateConfiguration(Configuration configuration) throws IOException, NotMasterDeviceException;
106
107 void setProfile(
108 String givenName, String familyName, String about, String aboutEmoji, Optional<File> avatar
109 ) throws IOException;
110
111 void unregister() throws IOException;
112
113 void deleteAccount() throws IOException;
114
115 void submitRateLimitRecaptchaChallenge(String challenge, String captcha) throws IOException;
116
117 List<Device> getLinkedDevices() throws IOException;
118
119 void removeLinkedDevices(long deviceId) throws IOException;
120
121 void addDeviceLink(URI linkUri) throws IOException, InvalidDeviceLinkException;
122
123 void setRegistrationLockPin(Optional<String> pin) throws IOException;
124
125 Profile getRecipientProfile(RecipientIdentifier.Single recipient) throws IOException;
126
127 List<Group> getGroups();
128
129 SendGroupMessageResults quitGroup(
130 GroupId groupId, Set<RecipientIdentifier.Single> groupAdmins
131 ) throws GroupNotFoundException, IOException, NotAGroupMemberException, LastGroupAdminException;
132
133 void deleteGroup(GroupId groupId) throws IOException;
134
135 Pair<GroupId, SendGroupMessageResults> createGroup(
136 String name, Set<RecipientIdentifier.Single> members, File avatarFile
137 ) throws IOException, AttachmentInvalidException;
138
139 SendGroupMessageResults updateGroup(
140 final GroupId groupId, final UpdateGroup updateGroup
141 ) throws IOException, GroupNotFoundException, AttachmentInvalidException, NotAGroupMemberException, GroupSendingNotAllowedException;
142
143 Pair<GroupId, SendGroupMessageResults> joinGroup(
144 GroupInviteLinkUrl inviteLinkUrl
145 ) throws IOException, InactiveGroupLinkException;
146
147 SendMessageResults sendTypingMessage(
148 TypingAction action, Set<RecipientIdentifier> recipients
149 ) throws IOException, NotAGroupMemberException, GroupNotFoundException, GroupSendingNotAllowedException;
150
151 SendMessageResults sendReadReceipt(
152 RecipientIdentifier.Single sender, List<Long> messageIds
153 ) throws IOException;
154
155 SendMessageResults sendViewedReceipt(
156 RecipientIdentifier.Single sender, List<Long> messageIds
157 ) throws IOException;
158
159 SendMessageResults sendMessage(
160 Message message, Set<RecipientIdentifier> recipients
161 ) throws IOException, AttachmentInvalidException, NotAGroupMemberException, GroupNotFoundException, GroupSendingNotAllowedException;
162
163 SendMessageResults sendRemoteDeleteMessage(
164 long targetSentTimestamp, Set<RecipientIdentifier> recipients
165 ) throws IOException, NotAGroupMemberException, GroupNotFoundException, GroupSendingNotAllowedException;
166
167 SendMessageResults sendMessageReaction(
168 String emoji,
169 boolean remove,
170 RecipientIdentifier.Single targetAuthor,
171 long targetSentTimestamp,
172 Set<RecipientIdentifier> recipients
173 ) throws IOException, NotAGroupMemberException, GroupNotFoundException, GroupSendingNotAllowedException;
174
175 SendMessageResults sendEndSessionMessage(Set<RecipientIdentifier.Single> recipients) throws IOException;
176
177 void setContactName(
178 RecipientIdentifier.Single recipient, String name
179 ) throws NotMasterDeviceException, IOException;
180
181 void setContactBlocked(
182 RecipientIdentifier.Single recipient, boolean blocked
183 ) throws NotMasterDeviceException, IOException;
184
185 void setGroupBlocked(
186 GroupId groupId, boolean blocked
187 ) throws GroupNotFoundException, IOException, NotMasterDeviceException;
188
189 void setExpirationTimer(
190 RecipientIdentifier.Single recipient, int messageExpirationTimer
191 ) throws IOException;
192
193 URI uploadStickerPack(File path) throws IOException, StickerPackInvalidException;
194
195 void requestAllSyncData() throws IOException;
196
197 /**
198 * Add a handler to receive new messages.
199 * Will start receiving messages from server, if not already started.
200 */
201 default void addReceiveHandler(ReceiveMessageHandler handler) {
202 addReceiveHandler(handler, false);
203 }
204
205 void addReceiveHandler(ReceiveMessageHandler handler, final boolean isWeakListener);
206
207 /**
208 * Remove a handler to receive new messages.
209 * Will stop receiving messages from server, if this was the last registered receiver.
210 */
211 void removeReceiveHandler(ReceiveMessageHandler handler);
212
213 boolean isReceiving();
214
215 /**
216 * Receive new messages from server, returns if no new message arrive in a timespan of timeout.
217 */
218 void receiveMessages(long timeout, TimeUnit unit, ReceiveMessageHandler handler) throws IOException;
219
220 /**
221 * Receive new messages from server, returns only if the thread is interrupted.
222 */
223 void receiveMessages(ReceiveMessageHandler handler) throws IOException;
224
225 void setIgnoreAttachments(boolean ignoreAttachments);
226
227 boolean hasCaughtUpWithOldMessages();
228
229 boolean isContactBlocked(RecipientIdentifier.Single recipient);
230
231 void sendContacts() throws IOException;
232
233 List<Pair<RecipientAddress, Contact>> getContacts();
234
235 String getContactOrProfileName(RecipientIdentifier.Single recipient);
236
237 Group getGroup(GroupId groupId);
238
239 List<Identity> getIdentities();
240
241 List<Identity> getIdentities(RecipientIdentifier.Single recipient);
242
243 boolean trustIdentityVerified(RecipientIdentifier.Single recipient, byte[] fingerprint);
244
245 boolean trustIdentityVerifiedSafetyNumber(RecipientIdentifier.Single recipient, String safetyNumber);
246
247 boolean trustIdentityVerifiedSafetyNumber(RecipientIdentifier.Single recipient, byte[] safetyNumber);
248
249 boolean trustIdentityAllKeys(RecipientIdentifier.Single recipient);
250
251 void addClosedListener(Runnable listener);
252
253 @Override
254 void close() throws IOException;
255
256 interface ReceiveMessageHandler {
257
258 ReceiveMessageHandler EMPTY = (envelope, e) -> {
259 };
260
261 void handleMessage(MessageEnvelope envelope, Throwable e);
262 }
263 }