]> nmode's Git Repositories - signal-cli/commitdiff
Remove libsignal-service from manager lib API
authorAsamK <asamk@gmx.de>
Sat, 6 Nov 2021 12:29:26 +0000 (13:29 +0100)
committerAsamK <asamk@gmx.de>
Sat, 6 Nov 2021 12:38:10 +0000 (13:38 +0100)
31 files changed:
lib/build.gradle.kts
lib/src/main/java/org/asamk/signal/manager/Manager.java
lib/src/main/java/org/asamk/signal/manager/ManagerImpl.java
lib/src/main/java/org/asamk/signal/manager/RegistrationManager.java
lib/src/main/java/org/asamk/signal/manager/api/CaptchaRequiredException.java [new file with mode: 0644]
lib/src/main/java/org/asamk/signal/manager/api/IncorrectPinException.java [new file with mode: 0644]
lib/src/main/java/org/asamk/signal/manager/api/InvalidNumberException.java [new file with mode: 0644]
lib/src/main/java/org/asamk/signal/manager/api/MessageEnvelope.java
lib/src/main/java/org/asamk/signal/manager/api/PinLockedException.java [new file with mode: 0644]
lib/src/main/java/org/asamk/signal/manager/api/ProofRequiredException.java [new file with mode: 0644]
lib/src/main/java/org/asamk/signal/manager/api/RecipientIdentifier.java
lib/src/main/java/org/asamk/signal/manager/api/SendGroupMessageResults.java
lib/src/main/java/org/asamk/signal/manager/api/SendMessageResult.java [new file with mode: 0644]
lib/src/main/java/org/asamk/signal/manager/api/SendMessageResults.java
lib/src/main/java/org/asamk/signal/manager/config/ServiceConfig.java
lib/src/main/java/org/asamk/signal/manager/helper/GroupHelper.java
lib/src/main/java/org/asamk/signal/manager/storage/recipients/RecipientAddress.java
src/main/java/org/asamk/signal/App.java
src/main/java/org/asamk/signal/Main.java
src/main/java/org/asamk/signal/ReceiveMessageHandler.java
src/main/java/org/asamk/signal/commands/JoinGroupCommand.java
src/main/java/org/asamk/signal/commands/ListIdentitiesCommand.java
src/main/java/org/asamk/signal/commands/RegisterCommand.java
src/main/java/org/asamk/signal/commands/VerifyCommand.java
src/main/java/org/asamk/signal/dbus/DbusManagerImpl.java
src/main/java/org/asamk/signal/dbus/DbusSignalControlImpl.java
src/main/java/org/asamk/signal/dbus/DbusSignalImpl.java
src/main/java/org/asamk/signal/json/JsonMessageEnvelope.java
src/main/java/org/asamk/signal/util/CommandUtil.java
src/main/java/org/asamk/signal/util/ErrorUtils.java
src/main/java/org/asamk/signal/util/Util.java

index c12ad0a46f0c7e6f0794a5f1aedc9071ff024792..91726ae15e257027e0650b6493c905dd4d1041cf 100644 (file)
@@ -14,7 +14,7 @@ repositories {
 }
 
 dependencies {
-    api("com.github.turasa:signal-service-java:2.15.3_unofficial_31")
+    implementation("com.github.turasa:signal-service-java:2.15.3_unofficial_31")
     api("com.fasterxml.jackson.core", "jackson-databind", "2.13.0")
     implementation("com.google.protobuf:protobuf-javalite:3.10.0")
     implementation("org.bouncycastle:bcprov-jdk15on:1.69")
index 77be3074bacb8f441151f80e8fd746fec390668e..b4579274b738c4372a8d0f9ace7213bbf08eb718 100644 (file)
@@ -67,6 +67,14 @@ public interface Manager extends Closeable {
         return new ManagerImpl(account, pathConfig, serviceEnvironmentConfig, userAgent);
     }
 
+    static void initLogger() {
+        LibSignalLogger.initLogger();
+    }
+
+    static boolean isValidNumber(final String e164Number, final String countryCode) {
+        return PhoneNumberFormatter.isValidNumber(e164Number, countryCode);
+    }
+
     static List<String> getAllLocalNumbers(File settingsPath) {
         var pathConfig = PathConfig.createDefault(settingsPath);
         final var dataPath = pathConfig.dataPath();
index 9994ad6540578e0bf2bf7e7d77b0efb0aa647cd4..59cfbbaa11c7911cb1af674cd99c174c973a0d6a 100644 (file)
@@ -26,6 +26,7 @@ import org.asamk.signal.manager.api.Message;
 import org.asamk.signal.manager.api.Pair;
 import org.asamk.signal.manager.api.RecipientIdentifier;
 import org.asamk.signal.manager.api.SendGroupMessageResults;
+import org.asamk.signal.manager.api.SendMessageResult;
 import org.asamk.signal.manager.api.SendMessageResults;
 import org.asamk.signal.manager.api.TypingAction;
 import org.asamk.signal.manager.api.UpdateGroup;
@@ -69,7 +70,6 @@ import org.whispersystems.libsignal.InvalidKeyException;
 import org.whispersystems.libsignal.ecc.ECPublicKey;
 import org.whispersystems.libsignal.util.guava.Optional;
 import org.whispersystems.signalservice.api.SignalSessionLock;
-import org.whispersystems.signalservice.api.messages.SendMessageResult;
 import org.whispersystems.signalservice.api.messages.SignalServiceDataMessage;
 import org.whispersystems.signalservice.api.messages.SignalServiceEnvelope;
 import org.whispersystems.signalservice.api.messages.SignalServiceReceiptMessage;
@@ -581,13 +581,24 @@ public class ManagerImpl implements Manager {
             if (recipient instanceof RecipientIdentifier.Single single) {
                 final var recipientId = resolveRecipient(single);
                 final var result = sendHelper.sendMessage(messageBuilder, recipientId);
-                results.put(recipient, List.of(result));
+                results.put(recipient,
+                        List.of(SendMessageResult.from(result,
+                                account.getRecipientStore(),
+                                account.getRecipientStore()::resolveRecipientAddress)));
             } else if (recipient instanceof RecipientIdentifier.NoteToSelf) {
                 final var result = sendHelper.sendSelfMessage(messageBuilder);
-                results.put(recipient, List.of(result));
+                results.put(recipient,
+                        List.of(SendMessageResult.from(result,
+                                account.getRecipientStore(),
+                                account.getRecipientStore()::resolveRecipientAddress)));
             } else if (recipient instanceof RecipientIdentifier.Group group) {
                 final var result = sendHelper.sendAsGroupMessage(messageBuilder, group.groupId());
-                results.put(recipient, result);
+                results.put(recipient,
+                        result.stream()
+                                .map(sendMessageResult -> SendMessageResult.from(sendMessageResult,
+                                        account.getRecipientStore(),
+                                        account.getRecipientStore()::resolveRecipientAddress))
+                                .collect(Collectors.toList()));
             }
         }
         return new SendMessageResults(timestamp, results);
@@ -1292,7 +1303,8 @@ public class ManagerImpl implements Manager {
     }
 
     private void handleIdentityFailure(
-            final RecipientId recipientId, final SendMessageResult.IdentityFailure identityFailure
+            final RecipientId recipientId,
+            final org.whispersystems.signalservice.api.messages.SendMessageResult.IdentityFailure identityFailure
     ) {
         this.identityHelper.handleIdentityFailure(recipientId, identityFailure);
     }
index 8a96dad0c6f28d160dae265e59c8382e1ca9c94a..97361ec5b20b5a948cada789b89719f572705092 100644 (file)
@@ -16,6 +16,9 @@
  */
 package org.asamk.signal.manager;
 
+import org.asamk.signal.manager.api.CaptchaRequiredException;
+import org.asamk.signal.manager.api.IncorrectPinException;
+import org.asamk.signal.manager.api.PinLockedException;
 import org.asamk.signal.manager.config.ServiceConfig;
 import org.asamk.signal.manager.config.ServiceEnvironment;
 import org.asamk.signal.manager.config.ServiceEnvironmentConfig;
@@ -27,6 +30,7 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.whispersystems.libsignal.util.KeyHelper;
 import org.whispersystems.libsignal.util.guava.Optional;
+import org.whispersystems.signalservice.api.KbsPinData;
 import org.whispersystems.signalservice.api.KeyBackupServicePinException;
 import org.whispersystems.signalservice.api.KeyBackupSystemNoDataException;
 import org.whispersystems.signalservice.api.SignalServiceAccountManager;
@@ -116,7 +120,7 @@ public class RegistrationManager implements Closeable {
         return new RegistrationManager(account, pathConfig, serviceConfiguration, userAgent);
     }
 
-    public void register(boolean voiceVerification, String captcha) throws IOException {
+    public void register(boolean voiceVerification, String captcha) throws IOException, CaptchaRequiredException {
         final ServiceResponse<RequestVerificationCodeResponse> response;
         if (voiceVerification) {
             response = accountManager.requestVoiceVerificationCode(getDefaultLocale(),
@@ -129,7 +133,11 @@ public class RegistrationManager implements Closeable {
                     Optional.absent(),
                     Optional.absent());
         }
-        handleResponseException(response);
+        try {
+            handleResponseException(response);
+        } catch (org.whispersystems.signalservice.api.push.exceptions.CaptchaRequiredException e) {
+            throw new CaptchaRequiredException(e.getMessage(), e);
+        }
     }
 
     private Locale getDefaultLocale() {
@@ -146,7 +154,7 @@ public class RegistrationManager implements Closeable {
 
     public Manager verifyAccount(
             String verificationCode, String pin
-    ) throws IOException, LockedException, KeyBackupSystemNoDataException, KeyBackupServicePinException {
+    ) throws IOException, PinLockedException, IncorrectPinException {
         verificationCode = verificationCode.replace("-", "");
         VerifyAccountResponse response;
         MasterKey masterKey;
@@ -157,10 +165,17 @@ public class RegistrationManager implements Closeable {
             pin = null;
         } catch (LockedException e) {
             if (pin == null) {
-                throw e;
+                throw new PinLockedException(e.getTimeRemaining());
             }
 
-            var registrationLockData = pinHelper.getRegistrationLockData(pin, e);
+            KbsPinData registrationLockData;
+            try {
+                registrationLockData = pinHelper.getRegistrationLockData(pin, e);
+            } catch (KeyBackupSystemNoDataException ex) {
+                throw new IOException(e);
+            } catch (KeyBackupServicePinException ex) {
+                throw new IncorrectPinException(ex.getTriesRemaining());
+            }
             if (registrationLockData == null) {
                 throw e;
             }
diff --git a/lib/src/main/java/org/asamk/signal/manager/api/CaptchaRequiredException.java b/lib/src/main/java/org/asamk/signal/manager/api/CaptchaRequiredException.java
new file mode 100644 (file)
index 0000000..9504d24
--- /dev/null
@@ -0,0 +1,12 @@
+package org.asamk.signal.manager.api;
+
+public class CaptchaRequiredException extends Exception {
+
+    public CaptchaRequiredException(final String message) {
+        super(message);
+    }
+
+    public CaptchaRequiredException(final String message, final Throwable cause) {
+        super(message, cause);
+    }
+}
diff --git a/lib/src/main/java/org/asamk/signal/manager/api/IncorrectPinException.java b/lib/src/main/java/org/asamk/signal/manager/api/IncorrectPinException.java
new file mode 100644 (file)
index 0000000..6de58f5
--- /dev/null
@@ -0,0 +1,14 @@
+package org.asamk.signal.manager.api;
+
+public class IncorrectPinException extends Exception {
+
+    private final int triesRemaining;
+
+    public IncorrectPinException(int triesRemaining) {
+        this.triesRemaining = triesRemaining;
+    }
+
+    public int getTriesRemaining() {
+        return triesRemaining;
+    }
+}
diff --git a/lib/src/main/java/org/asamk/signal/manager/api/InvalidNumberException.java b/lib/src/main/java/org/asamk/signal/manager/api/InvalidNumberException.java
new file mode 100644 (file)
index 0000000..ba71ef2
--- /dev/null
@@ -0,0 +1,8 @@
+package org.asamk.signal.manager.api;
+
+public class InvalidNumberException extends Exception {
+
+    InvalidNumberException(String message, Throwable e) {
+        super(message, e);
+    }
+}
index 98b754e2ce13a1c6b4a95d1322abb12213868034..dd40c81bf7842bdea764574ed8bc93e8a98c7a49 100644 (file)
@@ -48,7 +48,7 @@ public record MessageEnvelope(
         Optional<Call> call
 ) {
 
-    public static final record Receipt(long when, Type type, List<Long> timestamps) {
+    public record Receipt(long when, Type type, List<Long> timestamps) {
 
         static Receipt from(final SignalServiceReceiptMessage receiptMessage) {
             return new Receipt(receiptMessage.getWhen(),
@@ -73,7 +73,7 @@ public record MessageEnvelope(
         }
     }
 
-    public static final record Typing(long timestamp, Type type, Optional<GroupId> groupId) {
+    public record Typing(long timestamp, Type type, Optional<GroupId> groupId) {
 
         public static Typing from(final SignalServiceTypingMessage typingMessage) {
             return new Typing(typingMessage.getTimestamp(),
@@ -87,7 +87,7 @@ public record MessageEnvelope(
         }
     }
 
-    public static final record Data(
+    public record Data(
             long timestamp,
             Optional<GroupContext> groupContext,
             Optional<GroupCallUpdate> groupCallUpdate,
@@ -204,11 +204,15 @@ public record MessageEnvelope(
                 return new Quote(quote.getId(),
                         addressResolver.resolveRecipientAddress(recipientResolver.resolveRecipient(quote.getAuthor())),
                         Optional.ofNullable(quote.getText()),
-                        quote.getMentions()
-                                .stream()
-                                .map(m -> Mention.from(m, recipientResolver, addressResolver))
-                                .collect(Collectors.toList()),
-                        quote.getAttachments().stream().map(Attachment::from).collect(Collectors.toList()));
+                        quote.getMentions() == null
+                                ? List.of()
+                                : quote.getMentions()
+                                        .stream()
+                                        .map(m -> Mention.from(m, recipientResolver, addressResolver))
+                                        .collect(Collectors.toList()),
+                        quote.getAttachments() == null
+                                ? List.of()
+                                : quote.getAttachments().stream().map(Attachment::from).collect(Collectors.toList()));
             }
         }
 
@@ -455,7 +459,7 @@ public record MessageEnvelope(
         }
     }
 
-    public static final record Sync(
+    public record Sync(
             Optional<Sent> sent,
             Optional<Blocked> blocked,
             List<Read> read,
@@ -631,7 +635,7 @@ public record MessageEnvelope(
         }
     }
 
-    public static final record Call(
+    public record Call(
             Optional<Integer> destinationDeviceId,
             Optional<GroupId> groupId,
             Optional<Long> timestamp,
diff --git a/lib/src/main/java/org/asamk/signal/manager/api/PinLockedException.java b/lib/src/main/java/org/asamk/signal/manager/api/PinLockedException.java
new file mode 100644 (file)
index 0000000..161a1b6
--- /dev/null
@@ -0,0 +1,14 @@
+package org.asamk.signal.manager.api;
+
+public class PinLockedException extends Exception {
+
+    private final long timeRemaining;
+
+    public PinLockedException(long timeRemaining) {
+        this.timeRemaining = timeRemaining;
+    }
+
+    public long getTimeRemaining() {
+        return timeRemaining;
+    }
+}
diff --git a/lib/src/main/java/org/asamk/signal/manager/api/ProofRequiredException.java b/lib/src/main/java/org/asamk/signal/manager/api/ProofRequiredException.java
new file mode 100644 (file)
index 0000000..949dc4e
--- /dev/null
@@ -0,0 +1,44 @@
+package org.asamk.signal.manager.api;
+
+import java.util.Set;
+import java.util.stream.Collectors;
+
+/**
+ * Thrown when rate-limited by the server and proof of humanity is required to continue messaging.
+ */
+public class ProofRequiredException extends Exception {
+
+    private final String token;
+    private final Set<Option> options;
+    private final long retryAfterSeconds;
+
+    public ProofRequiredException(org.whispersystems.signalservice.api.push.exceptions.ProofRequiredException e) {
+        this.token = e.getToken();
+        this.options = e.getOptions().stream().map(Option::from).collect(Collectors.toSet());
+        this.retryAfterSeconds = e.getRetryAfterSeconds();
+    }
+
+    public String getToken() {
+        return token;
+    }
+
+    public Set<Option> getOptions() {
+        return options;
+    }
+
+    public long getRetryAfterSeconds() {
+        return retryAfterSeconds;
+    }
+
+    public enum Option {
+        RECAPTCHA,
+        PUSH_CHALLENGE;
+
+        static Option from(org.whispersystems.signalservice.api.push.exceptions.ProofRequiredException.Option option) {
+            return switch (option) {
+                case RECAPTCHA -> RECAPTCHA;
+                case PUSH_CHALLENGE -> PUSH_CHALLENGE;
+            };
+        }
+    }
+}
index a4b79ba0b9584db81c26ee90f1bdeecb29a54757..671cafcd20e8a602b03c31ef6bc87819ac86101c 100644 (file)
@@ -2,8 +2,6 @@ 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.whispersystems.signalservice.api.util.PhoneNumberFormatter;
 import org.whispersystems.signalservice.api.util.UuidUtil;
 
@@ -19,13 +17,13 @@ public sealed interface RecipientIdentifier {
     sealed interface Single extends RecipientIdentifier {
 
         static Single fromString(String identifier, String localNumber) throws InvalidNumberException {
-            return UuidUtil.isUuid(identifier)
-                    ? new Uuid(UUID.fromString(identifier))
-                    : new Number(PhoneNumberFormatter.formatNumber(identifier, localNumber));
-        }
-
-        static Single fromAddress(SignalServiceAddress address) {
-            return new Uuid(address.getUuid());
+            try {
+                return UuidUtil.isUuid(identifier)
+                        ? new Uuid(UUID.fromString(identifier))
+                        : new Number(PhoneNumberFormatter.formatNumber(identifier, localNumber));
+            } catch (org.whispersystems.signalservice.api.util.InvalidNumberException e) {
+                throw new InvalidNumberException(e.getMessage(), e);
+            }
         }
 
         static Single fromAddress(RecipientAddress address) {
index 54f55b920810e5c7211521f7efdc69a873c8f281..c40005030b59716739596898bac11c89718ccb80 100644 (file)
@@ -1,7 +1,5 @@
 package org.asamk.signal.manager.api;
 
-import org.whispersystems.signalservice.api.messages.SendMessageResult;
-
 import java.util.List;
 
 public record SendGroupMessageResults(long timestamp, List<SendMessageResult> results) {}
diff --git a/lib/src/main/java/org/asamk/signal/manager/api/SendMessageResult.java b/lib/src/main/java/org/asamk/signal/manager/api/SendMessageResult.java
new file mode 100644 (file)
index 0000000..c54e9f2
--- /dev/null
@@ -0,0 +1,56 @@
+package org.asamk.signal.manager.api;
+
+import org.asamk.signal.manager.helper.RecipientAddressResolver;
+import org.asamk.signal.manager.storage.recipients.RecipientAddress;
+import org.asamk.signal.manager.storage.recipients.RecipientResolver;
+import org.whispersystems.libsignal.IdentityKey;
+
+public record SendMessageResult(
+        RecipientAddress address,
+        boolean isSuccess,
+        boolean isNetworkFailure,
+        boolean isUnregisteredFailure,
+        boolean isIdentityFailure,
+        ProofRequiredException proofRequiredFailure
+) {
+
+    public static SendMessageResult success(RecipientAddress address) {
+        return new SendMessageResult(address, true, false, false, false, null);
+    }
+
+    public static SendMessageResult networkFailure(RecipientAddress address) {
+        return new SendMessageResult(address, false, true, false, false, null);
+    }
+
+    public static SendMessageResult unregisteredFailure(RecipientAddress address) {
+        return new SendMessageResult(address, false, false, true, false, null);
+    }
+
+    public static SendMessageResult identityFailure(RecipientAddress address, IdentityKey identityKey) {
+        return new SendMessageResult(address, false, false, false, true, null);
+    }
+
+    public static SendMessageResult proofRequiredFailure(
+            RecipientAddress address, ProofRequiredException proofRequiredException
+    ) {
+        return new SendMessageResult(address, false, true, false, false, proofRequiredException);
+    }
+
+    public static SendMessageResult from(
+            final org.whispersystems.signalservice.api.messages.SendMessageResult sendMessageResult,
+            RecipientResolver recipientResolver,
+            RecipientAddressResolver addressResolver
+    ) {
+        return new SendMessageResult(addressResolver.resolveRecipientAddress(recipientResolver.resolveRecipient(
+                sendMessageResult.getAddress())),
+                sendMessageResult.isSuccess(),
+                sendMessageResult.isNetworkFailure(),
+                sendMessageResult.isUnregisteredFailure(),
+                sendMessageResult.getIdentityFailure() != null,
+                sendMessageResult.getProofRequiredFailure() == null
+                        ? null
+                        : new ProofRequiredException(sendMessageResult.getProofRequiredFailure()));
+    }
+
+    public record IdentityFailure(IdentityKey identityKey) {}
+}
index 064532c04fabb5bbea375303486a6663207fd109..f0d609e9526a37b564e82e1091eda13214e63fb7 100644 (file)
@@ -1,7 +1,5 @@
 package org.asamk.signal.manager.api;
 
-import org.whispersystems.signalservice.api.messages.SendMessageResult;
-
 import java.util.List;
 import java.util.Map;
 
index 2634a59342e9976d46d2e78d1e5c25339dafaf81..6ff29c55575d3bdc776810b6cffc66328046dffc 100644 (file)
@@ -60,6 +60,10 @@ public class ServiceConfig {
         }
     }
 
+    public static boolean isZkgroupAvailable() {
+        return ServiceConfig.getCapabilities().isGv2();
+    }
+
     public static boolean isSignalClientAvailable() {
         try {
             org.signal.client.internal.Native.DeviceTransfer_GeneratePrivateKey();
index 3d91ea4294977c0a18938684f7e5449be7502696..d7d605c34b0f871f2ca130e9bbe225a5ee471f72 100644 (file)
@@ -6,6 +6,7 @@ import org.asamk.signal.manager.SignalDependencies;
 import org.asamk.signal.manager.api.InactiveGroupLinkException;
 import org.asamk.signal.manager.api.Pair;
 import org.asamk.signal.manager.api.SendGroupMessageResults;
+import org.asamk.signal.manager.api.SendMessageResult;
 import org.asamk.signal.manager.config.ServiceConfig;
 import org.asamk.signal.manager.groups.GroupId;
 import org.asamk.signal.manager.groups.GroupIdV1;
@@ -676,6 +677,11 @@ public class GroupHelper {
         final var timestamp = System.currentTimeMillis();
         messageBuilder.withTimestamp(timestamp);
         final var results = sendHelper.sendGroupMessage(messageBuilder.build(), members);
-        return new SendGroupMessageResults(timestamp, results);
+        return new SendGroupMessageResults(timestamp,
+                results.stream()
+                        .map(sendMessageResult -> SendMessageResult.from(sendMessageResult,
+                                recipientResolver,
+                                account.getRecipientStore()::resolveRecipientAddress))
+                        .collect(Collectors.toList()));
     }
 }
index bd8710dd1dad0e44465fae7c6f331890d7fc5e68..b74631b9300a5e5558e01271365a6afc5f026e50 100644 (file)
@@ -1,13 +1,14 @@
 package org.asamk.signal.manager.storage.recipients;
 
 import org.whispersystems.signalservice.api.push.SignalServiceAddress;
-import org.whispersystems.signalservice.api.util.UuidUtil;
 
 import java.util.Optional;
 import java.util.UUID;
 
 public class RecipientAddress {
 
+    public static final UUID UNKNOWN_UUID = new UUID(0, 0);
+
     private final Optional<UUID> uuid;
     private final Optional<String> e164;
 
@@ -18,7 +19,7 @@ public class RecipientAddress {
      * @param e164 The phone number of the user, if available.
      */
     public RecipientAddress(Optional<UUID> uuid, Optional<String> e164) {
-        uuid = uuid.isPresent() && uuid.get().equals(UuidUtil.UNKNOWN_UUID) ? Optional.empty() : uuid;
+        uuid = uuid.isPresent() && uuid.get().equals(UNKNOWN_UUID) ? Optional.empty() : uuid;
         if (uuid.isEmpty() && e164.isEmpty()) {
             throw new AssertionError("Must have either a UUID or E164 number!");
         }
@@ -74,7 +75,7 @@ public class RecipientAddress {
     }
 
     public SignalServiceAddress toSignalServiceAddress() {
-        return new SignalServiceAddress(uuid.orElse(UuidUtil.UNKNOWN_UUID),
+        return new SignalServiceAddress(uuid.orElse(UNKNOWN_UUID),
                 org.whispersystems.libsignal.util.guava.Optional.fromNullable(e164.orElse(null)));
     }
 
index 3d35ff8f120f73228900119b5672254a9e60ef11..7c86f09ed8f389e45921435854bb55d7e2492bb8 100644 (file)
@@ -32,7 +32,6 @@ import org.freedesktop.dbus.exceptions.DBusException;
 import org.freedesktop.dbus.exceptions.DBusExecutionException;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
-import org.whispersystems.signalservice.api.util.PhoneNumberFormatter;
 
 import java.io.File;
 import java.io.IOException;
@@ -133,7 +132,7 @@ public class App {
             dataPath = getDefaultDataPath();
         }
 
-        if (!ServiceConfig.getCapabilities().isGv2()) {
+        if (!ServiceConfig.isZkgroupAvailable()) {
             logger.warn("WARNING: Support for new group V2 is disabled,"
                     + " because the required native library dependency is missing: libzkgroup");
         }
@@ -182,7 +181,7 @@ public class App {
             }
 
             username = usernames.get(0);
-        } else if (!PhoneNumberFormatter.isValidNumber(username, null)) {
+        } else if (!Manager.isValidNumber(username, null)) {
             throw new UserErrorException("Invalid username (phone number), make sure you include the country code.");
         }
 
index 2a95e6de1b4bc287e574a6fc94f794dafa279cf3..863f838824fe1bf4822ce85e9f69c84fdc96f4e4 100644 (file)
@@ -26,7 +26,7 @@ import org.asamk.signal.commands.exceptions.IOErrorException;
 import org.asamk.signal.commands.exceptions.UnexpectedErrorException;
 import org.asamk.signal.commands.exceptions.UntrustedKeyErrorException;
 import org.asamk.signal.commands.exceptions.UserErrorException;
-import org.asamk.signal.manager.LibSignalLogger;
+import org.asamk.signal.manager.Manager;
 import org.asamk.signal.util.SecurityProvider;
 import org.bouncycastle.jce.provider.BouncyCastleProvider;
 
@@ -90,7 +90,7 @@ public class Main {
             System.setProperty("org.slf4j.simpleLogger.showShortLogName", "false");
             System.setProperty("org.slf4j.simpleLogger.showDateTime", "true");
             System.setProperty("org.slf4j.simpleLogger.dateTimeFormat", "yyyy-MM-dd'T'HH:mm:ss.SSSXX");
-            LibSignalLogger.initLogger();
+            Manager.initLogger();
         } else {
             System.setProperty("org.slf4j.simpleLogger.defaultLogLevel", "info");
             System.setProperty("org.slf4j.simpleLogger.showThreadName", "false");
index 0b1ea5bede168d5a41fdf4a3fba66e8fa902f595..b794f8602b8eeabf612abb7e71cf6a66979ff0a8 100644 (file)
@@ -361,7 +361,9 @@ public class ReceiveMessageHandler implements Manager.ReceiveMessageHandler {
     ) {
         writer.println("Id: {}", quote.id());
         writer.println("Author: {}", formatContact(quote.author()));
-        writer.println("Text: {}", quote.text());
+        if (quote.text().isPresent()) {
+            writer.println("Text: {}", quote.text().get());
+        }
         if (quote.mentions() != null && quote.mentions().size() > 0) {
             writer.println("Mentions:");
             for (var mention : quote.mentions()) {
@@ -371,14 +373,8 @@ public class ReceiveMessageHandler implements Manager.ReceiveMessageHandler {
         if (quote.attachments().size() > 0) {
             writer.println("Attachments:");
             for (var attachment : quote.attachments()) {
-                writer.println("- Filename: {}", attachment.fileName());
-                writer.indent(w -> {
-                    w.println("Type: {}", attachment.contentType());
-                    w.println("Thumbnail:");
-                    if (attachment.thumbnail().isPresent()) {
-                        printAttachment(w, attachment.thumbnail().get());
-                    }
-                });
+                writer.println("- Attachment:");
+                printAttachment(writer.indentedWriter(), attachment);
             }
         }
     }
@@ -527,6 +523,10 @@ public class ReceiveMessageHandler implements Manager.ReceiveMessageHandler {
                             + attachment.preview().get().length
                             + " bytes)" : "");
         }
+        if (attachment.thumbnail().isPresent()) {
+            writer.println("Thumbnail:");
+            printAttachment(writer.indentedWriter(), attachment.thumbnail().get());
+        }
         final var flags = new ArrayList<String>();
         if (attachment.isVoiceNote()) {
             flags.add("voice note");
index c7b8b0403ee91443408e0b7d488fb7ac365f7a2f..5feb7c1bc0e777ebfb4164d97c8b5b1ce0b84566 100644 (file)
@@ -14,7 +14,6 @@ import org.asamk.signal.manager.Manager;
 import org.asamk.signal.manager.api.InactiveGroupLinkException;
 import org.asamk.signal.manager.groups.GroupInviteLinkUrl;
 import org.freedesktop.dbus.exceptions.DBusExecutionException;
-import org.whispersystems.signalservice.internal.push.exceptions.GroupPatchNotAcceptedException;
 
 import java.io.IOException;
 import java.util.Map;
@@ -70,8 +69,6 @@ public class JoinGroupCommand implements JsonRpcLocalCommand {
                 }
             }
             handleSendMessageResults(results.second().results());
-        } catch (GroupPatchNotAcceptedException e) {
-            throw new UserErrorException("Failed to join group, maybe already a member");
         } catch (IOException e) {
             throw new IOErrorException("Failed to send message: "
                     + e.getMessage()
index 8c9e6b4c07b4abde121d031ba88cdc84ea246ec2..04a2f2bd5568f80ca39cb29e8d8ffc895912768f 100644 (file)
@@ -63,10 +63,10 @@ public class ListIdentitiesCommand implements JsonRpcLocalCommand {
         } else {
             final var writer = (JsonWriter) outputWriter;
             final var jsonIdentities = identities.stream().map(id -> {
-                final var address = id.recipient().toSignalServiceAddress();
+                final var address = id.recipient();
                 var safetyNumber = Util.formatSafetyNumber(id.safetyNumber());
                 var scannableSafetyNumber = id.scannableSafetyNumber();
-                return new JsonIdentity(address.getNumber().orNull(),
+                return new JsonIdentity(address.getNumber().orElse(null),
                         address.getUuid().toString(),
                         Hex.toString(id.getFingerprint()),
                         safetyNumber,
index 7e4fe505978ef78017070b7ca866687c5e32e662..da72e1a42cc7f269e3f5e59be2e059d13ea68908 100644 (file)
@@ -8,7 +8,7 @@ import org.asamk.signal.commands.exceptions.CommandException;
 import org.asamk.signal.commands.exceptions.IOErrorException;
 import org.asamk.signal.commands.exceptions.UserErrorException;
 import org.asamk.signal.manager.RegistrationManager;
-import org.whispersystems.signalservice.api.push.exceptions.CaptchaRequiredException;
+import org.asamk.signal.manager.api.CaptchaRequiredException;
 
 import java.io.IOException;
 
index b7fffcd23ca5c663c2abb2247c2652121483ad78..9179988729f37d3adcbc19f83da3c82e04a00b25 100644 (file)
@@ -5,12 +5,10 @@ import net.sourceforge.argparse4j.inf.Subparser;
 
 import org.asamk.signal.commands.exceptions.CommandException;
 import org.asamk.signal.commands.exceptions.IOErrorException;
-import org.asamk.signal.commands.exceptions.UnexpectedErrorException;
 import org.asamk.signal.commands.exceptions.UserErrorException;
 import org.asamk.signal.manager.RegistrationManager;
-import org.whispersystems.signalservice.api.KeyBackupServicePinException;
-import org.whispersystems.signalservice.api.KeyBackupSystemNoDataException;
-import org.whispersystems.signalservice.internal.push.LockedException;
+import org.asamk.signal.manager.api.IncorrectPinException;
+import org.asamk.signal.manager.api.PinLockedException;
 
 import java.io.IOException;
 
@@ -36,15 +34,13 @@ public class VerifyCommand implements RegistrationCommand {
         try {
             final var manager = m.verifyAccount(verificationCode, pin);
             manager.close();
-        } catch (LockedException e) {
+        } catch (PinLockedException e) {
             throw new UserErrorException(
                     "Verification failed! This number is locked with a pin. Hours remaining until reset: "
                             + (e.getTimeRemaining() / 1000 / 60 / 60)
                             + "\nUse '--pin PIN_CODE' to specify the registration lock PIN");
-        } catch (KeyBackupServicePinException e) {
+        } catch (IncorrectPinException e) {
             throw new UserErrorException("Verification failed! Invalid pin, tries remaining: " + e.getTriesRemaining());
-        } catch (KeyBackupSystemNoDataException e) {
-            throw new UnexpectedErrorException("Verification failed! No KBS data.", e);
         } catch (IOException e) {
             throw new IOErrorException("Verify error: " + e.getMessage(), e);
         }
index 0d87cdb5a05188ef03d4f4389648685f604a6f4d..4656975ec7bada54794cedad8ed7b1bba3a40079 100644 (file)
@@ -33,8 +33,6 @@ import org.freedesktop.dbus.DBusPath;
 import org.freedesktop.dbus.connections.impl.DBusConnection;
 import org.freedesktop.dbus.exceptions.DBusException;
 import org.freedesktop.dbus.interfaces.DBusInterface;
-import org.whispersystems.signalservice.api.push.exceptions.UnregisteredUserException;
-import org.whispersystems.signalservice.api.util.UuidUtil;
 
 import java.io.File;
 import java.io.IOException;
@@ -84,7 +82,7 @@ public class DbusManagerImpl implements Manager {
         final var result = new HashMap<String, Pair<String, UUID>>();
         for (var i = 0; i < numbersList.size(); i++) {
             result.put(numbersList.get(i),
-                    new Pair<>(numbersList.get(i), registered.get(i) ? UuidUtil.UNKNOWN_UUID : null));
+                    new Pair<>(numbersList.get(i), registered.get(i) ? RecipientAddress.UNKNOWN_UUID : null));
         }
         return result;
     }
@@ -173,7 +171,7 @@ public class DbusManagerImpl implements Manager {
     }
 
     @Override
-    public Profile getRecipientProfile(final RecipientIdentifier.Single recipient) throws UnregisteredUserException {
+    public Profile getRecipientProfile(final RecipientIdentifier.Single recipient) {
         throw new UnsupportedOperationException();
     }
 
@@ -370,7 +368,7 @@ public class DbusManagerImpl implements Manager {
     @Override
     public void setContactName(
             final RecipientIdentifier.Single recipient, final String name
-    ) throws NotMasterDeviceException, UnregisteredUserException {
+    ) throws NotMasterDeviceException {
         signal.setContactName(recipient.getIdentifier(), name);
     }
 
index a70da5636a6d91c2df1f0d8ba51f6495a05b8961..e69bf059c4d75f4328dfe41ee570bfc360dc4583 100644 (file)
@@ -8,12 +8,11 @@ import org.asamk.signal.manager.Manager;
 import org.asamk.signal.manager.ProvisioningManager;
 import org.asamk.signal.manager.RegistrationManager;
 import org.asamk.signal.manager.UserAlreadyExists;
+import org.asamk.signal.manager.api.CaptchaRequiredException;
+import org.asamk.signal.manager.api.IncorrectPinException;
 import org.asamk.signal.manager.api.Pair;
+import org.asamk.signal.manager.api.PinLockedException;
 import org.freedesktop.dbus.DBusPath;
-import org.whispersystems.signalservice.api.KeyBackupServicePinException;
-import org.whispersystems.signalservice.api.KeyBackupSystemNoDataException;
-import org.whispersystems.signalservice.api.push.exceptions.CaptchaRequiredException;
-import org.whispersystems.signalservice.api.util.PhoneNumberFormatter;
 
 import java.io.IOException;
 import java.net.URI;
@@ -100,7 +99,7 @@ public class DbusSignalControlImpl implements org.asamk.SignalControl {
     public void registerWithCaptcha(
             final String number, final boolean voiceVerification, final String captcha
     ) throws Error.Failure, Error.InvalidNumber {
-        if (!PhoneNumberFormatter.isValidNumber(number, null)) {
+        if (!Manager.isValidNumber(number, null)) {
             throw new SignalControl.Error.InvalidNumber(
                     "Invalid username (phone number), make sure you include the country code.");
         }
@@ -126,7 +125,7 @@ public class DbusSignalControlImpl implements org.asamk.SignalControl {
         try (final RegistrationManager registrationManager = c.getNewRegistrationManager(number)) {
             final Manager manager = registrationManager.verifyAccount(verificationCode, pin);
             addManager(manager);
-        } catch (IOException | KeyBackupSystemNoDataException | KeyBackupServicePinException e) {
+        } catch (IOException | PinLockedException | IncorrectPinException e) {
             throw new SignalControl.Error.Failure(e.getClass().getSimpleName() + " " + e.getMessage());
         }
     }
index 0a36376ccd1984006814ecde24f09ec5c976afbd..58bd1a97c797cbeb8a48ec8448ca1aa6f94e2ca3 100644 (file)
@@ -11,9 +11,11 @@ import org.asamk.signal.manager.UntrustedIdentityException;
 import org.asamk.signal.manager.api.Identity;
 import org.asamk.signal.manager.api.InactiveGroupLinkException;
 import org.asamk.signal.manager.api.InvalidDeviceLinkException;
+import org.asamk.signal.manager.api.InvalidNumberException;
 import org.asamk.signal.manager.api.Message;
 import org.asamk.signal.manager.api.Pair;
 import org.asamk.signal.manager.api.RecipientIdentifier;
+import org.asamk.signal.manager.api.SendMessageResult;
 import org.asamk.signal.manager.api.TypingAction;
 import org.asamk.signal.manager.api.UpdateGroup;
 import org.asamk.signal.manager.groups.GroupId;
@@ -32,8 +34,6 @@ import org.freedesktop.dbus.connections.impl.DBusConnection;
 import org.freedesktop.dbus.exceptions.DBusException;
 import org.freedesktop.dbus.exceptions.DBusExecutionException;
 import org.freedesktop.dbus.types.Variant;
-import org.whispersystems.signalservice.api.messages.SendMessageResult;
-import org.whispersystems.signalservice.api.util.InvalidNumberException;
 
 import java.io.File;
 import java.io.IOException;
@@ -719,7 +719,7 @@ public class DbusSignalImpl implements Signal {
 
         final var message = timestamp + "\nFailed to send message:\n" + error + '\n';
 
-        if (result.getIdentityFailure() != null) {
+        if (result.isIdentityFailure()) {
             throw new Error.UntrustedIdentity(message);
         } else {
             throw new Error.Failure(message);
index 04340d0f5862295705a84dcd435b86da0e885362..80c367c395a3841292d83d1919657aeb514cded9 100644 (file)
@@ -5,9 +5,9 @@ import com.fasterxml.jackson.annotation.JsonInclude;
 import org.asamk.Signal;
 import org.asamk.signal.manager.Manager;
 import org.asamk.signal.manager.UntrustedIdentityException;
+import org.asamk.signal.manager.api.InvalidNumberException;
 import org.asamk.signal.manager.api.MessageEnvelope;
 import org.asamk.signal.manager.api.RecipientIdentifier;
-import org.whispersystems.signalservice.api.util.InvalidNumberException;
 
 import java.util.List;
 import java.util.UUID;
index 0a624e6b214ac7596b8552fa34749528a5079f6f..b9574d0e628f1dcceeaada0a8b348e1ceea1eb9e 100644 (file)
@@ -2,10 +2,10 @@ package org.asamk.signal.util;
 
 import org.asamk.signal.commands.exceptions.UserErrorException;
 import org.asamk.signal.manager.Manager;
+import org.asamk.signal.manager.api.InvalidNumberException;
 import org.asamk.signal.manager.api.RecipientIdentifier;
 import org.asamk.signal.manager.groups.GroupId;
 import org.asamk.signal.manager.groups.GroupIdFormatException;
-import org.whispersystems.signalservice.api.util.InvalidNumberException;
 
 import java.util.Collection;
 import java.util.HashSet;
index 1c8a8f38fb2942286428dbc31675b4e12e1b3223..c3ecf34097bc28903cea6bed6961354684e47127 100644 (file)
@@ -2,11 +2,11 @@ package org.asamk.signal.util;
 
 import org.asamk.signal.commands.exceptions.CommandException;
 import org.asamk.signal.commands.exceptions.IOErrorException;
+import org.asamk.signal.manager.api.ProofRequiredException;
 import org.asamk.signal.manager.api.RecipientIdentifier;
+import org.asamk.signal.manager.api.SendMessageResult;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
-import org.whispersystems.signalservice.api.messages.SendMessageResult;
-import org.whispersystems.signalservice.api.push.exceptions.ProofRequiredException;
 
 import java.util.ArrayList;
 import java.util.Collection;
@@ -14,8 +14,6 @@ import java.util.List;
 import java.util.Map;
 import java.util.stream.Collectors;
 
-import static org.asamk.signal.util.Util.getLegacyIdentifier;
-
 public class ErrorUtils {
 
     private final static Logger logger = LoggerFactory.getLogger(ErrorUtils.class);
@@ -57,9 +55,9 @@ public class ErrorUtils {
     }
 
     public static String getErrorMessageFromSendMessageResult(SendMessageResult result) {
-        var identifier = getLegacyIdentifier(result.getAddress());
-        if (result.getProofRequiredFailure() != null) {
-            final var failure = result.getProofRequiredFailure();
+        var identifier = result.address().getLegacyIdentifier();
+        if (result.proofRequiredFailure() != null) {
+            final var failure = result.proofRequiredFailure();
             return String.format(
                     "CAPTCHA proof required for sending to \"%s\", available options \"%s\" with challenge token \"%s\", or wait \"%d\" seconds.\n"
                             + (
@@ -83,7 +81,7 @@ public class ErrorUtils {
             return String.format("Network failure for \"%s\"", identifier);
         } else if (result.isUnregisteredFailure()) {
             return String.format("Unregistered user \"%s\"", identifier);
-        } else if (result.getIdentityFailure() != null) {
+        } else if (result.isIdentityFailure()) {
             return String.format("Untrusted Identity for \"%s\"", identifier);
         }
         return null;
index 48e6f35de06a17ebaf5f667a5afacd3d091c1538..c844e2ea910787f5cccdf1e7c18ff1d464cd7153 100644 (file)
@@ -5,8 +5,6 @@ import com.fasterxml.jackson.annotation.PropertyAccessor;
 import com.fasterxml.jackson.core.JsonGenerator;
 import com.fasterxml.jackson.databind.ObjectMapper;
 
-import org.whispersystems.signalservice.api.push.SignalServiceAddress;
-
 import java.util.Arrays;
 import java.util.List;
 import java.util.Locale;
@@ -59,10 +57,6 @@ public class Util {
         return f.toString();
     }
 
-    public static String getLegacyIdentifier(final SignalServiceAddress address) {
-        return address.getNumber().or(() -> address.getUuid().toString());
-    }
-
     public static ObjectMapper createJsonObjectMapper() {
         var objectMapper = new ObjectMapper();
         objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.PUBLIC_ONLY);