]> nmode's Git Repositories - signal-cli/commitdiff
Add MultiAccountManager
authorAsamK <asamk@gmx.de>
Thu, 11 Nov 2021 12:29:32 +0000 (13:29 +0100)
committerAsamK <asamk@gmx.de>
Thu, 11 Nov 2021 15:10:22 +0000 (16:10 +0100)
18 files changed:
lib/src/main/java/org/asamk/signal/manager/ManagerImpl.java
lib/src/main/java/org/asamk/signal/manager/MultiAccountManager.java [moved from src/main/java/org/asamk/signal/commands/SignalCreator.java with 60% similarity]
lib/src/main/java/org/asamk/signal/manager/MultiAccountManagerImpl.java [new file with mode: 0644]
lib/src/main/java/org/asamk/signal/manager/ProvisioningManager.java
lib/src/main/java/org/asamk/signal/manager/RegistrationManager.java
src/main/java/org/asamk/signal/App.java
src/main/java/org/asamk/signal/commands/DaemonCommand.java
src/main/java/org/asamk/signal/commands/JsonRpcMultiCommand.java
src/main/java/org/asamk/signal/commands/JsonRpcMultiLocalCommand.java
src/main/java/org/asamk/signal/commands/LinkCommand.java
src/main/java/org/asamk/signal/commands/ListAccountsCommand.java
src/main/java/org/asamk/signal/commands/MultiLocalCommand.java
src/main/java/org/asamk/signal/commands/SubmitRateLimitChallengeCommand.java
src/main/java/org/asamk/signal/commands/VerifyCommand.java
src/main/java/org/asamk/signal/commands/VersionCommand.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/jsonrpc/SignalJsonRpcDispatcherHandler.java

index d7245d56eb5487620cd98b27ccd53a8de6402e19..69ae926992fe0764b55fb461935ceb3acf9a6b49 100644 (file)
@@ -403,6 +403,8 @@ public class ManagerImpl implements Manager {
 
     @Override
     public void submitRateLimitRecaptchaChallenge(String challenge, String captcha) throws IOException {
+        captcha = captcha == null ? null : captcha.replace("signalcaptcha://", "");
+
         dependencies.getAccountManager().submitRateLimitRecaptchaChallenge(challenge, captcha);
     }
 
similarity index 60%
rename from src/main/java/org/asamk/signal/commands/SignalCreator.java
rename to lib/src/main/java/org/asamk/signal/manager/MultiAccountManager.java
index 46bbbfc0672ca45d075ba4b41e4aa67fd7b1caf5..e7205276e32f7e68476411b5be58dfddec68c523 100644 (file)
@@ -1,24 +1,23 @@
-package org.asamk.signal.commands;
-
-import org.asamk.signal.manager.Manager;
-import org.asamk.signal.manager.ProvisioningManager;
-import org.asamk.signal.manager.RegistrationManager;
+package org.asamk.signal.manager;
 
 import java.io.IOException;
 import java.util.List;
 import java.util.function.Consumer;
 
-public interface SignalCreator {
+public interface MultiAccountManager extends AutoCloseable {
 
     List<String> getAccountNumbers();
 
-    void addManager(Manager m);
-
     void addOnManagerAddedHandler(Consumer<Manager> handler);
 
+    void addOnManagerRemovedHandler(Consumer<Manager> handler);
+
     Manager getManager(String phoneNumber);
 
     ProvisioningManager getNewProvisioningManager();
 
     RegistrationManager getNewRegistrationManager(String username) throws IOException;
+
+    @Override
+    void close();
 }
diff --git a/lib/src/main/java/org/asamk/signal/manager/MultiAccountManagerImpl.java b/lib/src/main/java/org/asamk/signal/manager/MultiAccountManagerImpl.java
new file mode 100644 (file)
index 0000000..df74cf4
--- /dev/null
@@ -0,0 +1,104 @@
+package org.asamk.signal.manager;
+
+import org.asamk.signal.manager.config.ServiceEnvironment;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import java.util.function.Consumer;
+import java.util.stream.Collectors;
+
+public class MultiAccountManagerImpl implements MultiAccountManager {
+
+    private final static Logger logger = LoggerFactory.getLogger(MultiAccountManagerImpl.class);
+
+    private final Set<Consumer<Manager>> onManagerAddedHandlers = new HashSet<>();
+    private final Set<Consumer<Manager>> onManagerRemovedHandlers = new HashSet<>();
+    private final Set<Manager> managers = new HashSet<>();
+    private final File dataPath;
+    private final ServiceEnvironment serviceEnvironment;
+    private final String userAgent;
+
+    public MultiAccountManagerImpl(
+            final Collection<Manager> managers,
+            final File dataPath,
+            final ServiceEnvironment serviceEnvironment,
+            final String userAgent
+    ) {
+        this.managers.addAll(managers);
+        this.dataPath = dataPath;
+        this.serviceEnvironment = serviceEnvironment;
+        this.userAgent = userAgent;
+    }
+
+    @Override
+    public List<String> getAccountNumbers() {
+        synchronized (managers) {
+            return managers.stream().map(Manager::getSelfNumber).collect(Collectors.toList());
+        }
+    }
+
+    void addManager(final Manager m) {
+        synchronized (managers) {
+            if (managers.contains(m)) {
+                return;
+            }
+            managers.add(m);
+        }
+        synchronized (onManagerAddedHandlers) {
+            for (final var handler : onManagerAddedHandlers) {
+                handler.accept(m);
+            }
+        }
+    }
+
+    @Override
+    public void addOnManagerAddedHandler(final Consumer<Manager> handler) {
+        synchronized (onManagerAddedHandlers) {
+            onManagerAddedHandlers.add(handler);
+        }
+    }
+
+    @Override
+    public void addOnManagerRemovedHandler(final Consumer<Manager> handler) {
+        synchronized (onManagerRemovedHandlers) {
+            onManagerRemovedHandlers.add(handler);
+        }
+    }
+
+    @Override
+    public Manager getManager(final String account) {
+        synchronized (managers) {
+            return managers.stream().filter(m -> m.getSelfNumber().equals(account)).findFirst().orElse(null);
+        }
+    }
+
+    @Override
+    public ProvisioningManager getNewProvisioningManager() {
+        return ProvisioningManager.init(dataPath, serviceEnvironment, userAgent, this::addManager);
+    }
+
+    @Override
+    public RegistrationManager getNewRegistrationManager(String account) throws IOException {
+        return RegistrationManager.init(account, dataPath, serviceEnvironment, userAgent, this::addManager);
+    }
+
+    @Override
+    public void close() {
+        synchronized (managers) {
+            for (var m : managers) {
+                try {
+                    m.close();
+                } catch (IOException e) {
+                    logger.warn("Cleanup failed", e);
+                }
+            }
+            managers.clear();
+        }
+    }
+}
index bd9385a9251125801b71cec5e4f22809f7ca7716..6445e5111fc8f68e6fd3150971123cf22d0deeb3 100644 (file)
@@ -38,6 +38,7 @@ import java.io.File;
 import java.io.IOException;
 import java.net.URI;
 import java.util.concurrent.TimeoutException;
+import java.util.function.Consumer;
 
 public class ProvisioningManager {
 
@@ -46,16 +47,23 @@ public class ProvisioningManager {
     private final PathConfig pathConfig;
     private final ServiceEnvironmentConfig serviceEnvironmentConfig;
     private final String userAgent;
+    private final Consumer<Manager> newManagerListener;
 
     private final SignalServiceAccountManager accountManager;
     private final IdentityKeyPair tempIdentityKey;
     private final int registrationId;
     private final String password;
 
-    ProvisioningManager(PathConfig pathConfig, ServiceEnvironmentConfig serviceEnvironmentConfig, String userAgent) {
+    ProvisioningManager(
+            PathConfig pathConfig,
+            ServiceEnvironmentConfig serviceEnvironmentConfig,
+            String userAgent,
+            final Consumer<Manager> newManagerListener
+    ) {
         this.pathConfig = pathConfig;
         this.serviceEnvironmentConfig = serviceEnvironmentConfig;
         this.userAgent = userAgent;
+        this.newManagerListener = newManagerListener;
 
         tempIdentityKey = KeyUtils.generateIdentityKeyPair();
         registrationId = KeyHelper.generateRegistrationId(false);
@@ -75,12 +83,21 @@ public class ProvisioningManager {
 
     public static ProvisioningManager init(
             File settingsPath, ServiceEnvironment serviceEnvironment, String userAgent
+    ) {
+        return init(settingsPath, serviceEnvironment, userAgent, null);
+    }
+
+    public static ProvisioningManager init(
+            File settingsPath,
+            ServiceEnvironment serviceEnvironment,
+            String userAgent,
+            Consumer<Manager> newManagerListener
     ) {
         var pathConfig = PathConfig.createDefault(settingsPath);
 
         final var serviceConfiguration = ServiceConfig.getServiceEnvironmentConfig(serviceEnvironment, userAgent);
 
-        return new ProvisioningManager(pathConfig, serviceConfiguration, userAgent);
+        return new ProvisioningManager(pathConfig, serviceConfiguration, userAgent, newManagerListener);
     }
 
     public URI getDeviceLinkUri() throws TimeoutException, IOException {
@@ -89,7 +106,7 @@ public class ProvisioningManager {
         return new DeviceLinkInfo(deviceUuid, tempIdentityKey.getPublicKey().getPublicKey()).createDeviceLinkUri();
     }
 
-    public Manager finishDeviceLink(String deviceName) throws IOException, TimeoutException, UserAlreadyExists {
+    public String finishDeviceLink(String deviceName) throws IOException, TimeoutException, UserAlreadyExists {
         var ret = accountManager.getNewDeviceRegistration(tempIdentityKey);
         var number = ret.getNumber();
 
@@ -145,11 +162,11 @@ public class ProvisioningManager {
                             "Failed to request sync messages from linked device, data can be requested again with `sendSyncRequest`.");
                 }
 
-                final var result = m;
-                account = null;
-                m = null;
-
-                return result;
+                if (newManagerListener != null) {
+                    newManagerListener.accept(m);
+                    m = null;
+                }
+                return number;
             } finally {
                 if (m != null) {
                     m.close();
index 789173af6d495073464584c5a9865aea4e913cc9..669034d12dfebcc2f5d5ad2326e945f881c6a3a3 100644 (file)
@@ -49,6 +49,7 @@ import org.whispersystems.signalservice.internal.util.DynamicCredentialsProvider
 import java.io.Closeable;
 import java.io.File;
 import java.io.IOException;
+import java.util.function.Consumer;
 
 public class RegistrationManager implements Closeable {
 
@@ -58,6 +59,7 @@ public class RegistrationManager implements Closeable {
     private final PathConfig pathConfig;
     private final ServiceEnvironmentConfig serviceEnvironmentConfig;
     private final String userAgent;
+    private final Consumer<Manager> newManagerListener;
 
     private final SignalServiceAccountManager accountManager;
     private final PinHelper pinHelper;
@@ -66,12 +68,14 @@ public class RegistrationManager implements Closeable {
             SignalAccount account,
             PathConfig pathConfig,
             ServiceEnvironmentConfig serviceEnvironmentConfig,
-            String userAgent
+            String userAgent,
+            Consumer<Manager> newManagerListener
     ) {
         this.account = account;
         this.pathConfig = pathConfig;
         this.serviceEnvironmentConfig = serviceEnvironmentConfig;
         this.userAgent = userAgent;
+        this.newManagerListener = newManagerListener;
 
         GroupsV2Operations groupsV2Operations;
         try {
@@ -96,6 +100,16 @@ public class RegistrationManager implements Closeable {
 
     public static RegistrationManager init(
             String number, File settingsPath, ServiceEnvironment serviceEnvironment, String userAgent
+    ) throws IOException {
+        return init(number, settingsPath, serviceEnvironment, userAgent, null);
+    }
+
+    public static RegistrationManager init(
+            String number,
+            File settingsPath,
+            ServiceEnvironment serviceEnvironment,
+            String userAgent,
+            Consumer<Manager> newManagerListener
     ) throws IOException {
         var pathConfig = PathConfig.createDefault(settingsPath);
 
@@ -112,15 +126,16 @@ public class RegistrationManager implements Closeable {
                     profileKey,
                     TrustNewIdentity.ON_FIRST_USE);
 
-            return new RegistrationManager(account, pathConfig, serviceConfiguration, userAgent);
+            return new RegistrationManager(account, pathConfig, serviceConfiguration, userAgent, newManagerListener);
         }
 
         var account = SignalAccount.load(pathConfig.dataPath(), number, true, TrustNewIdentity.ON_FIRST_USE);
 
-        return new RegistrationManager(account, pathConfig, serviceConfiguration, userAgent);
+        return new RegistrationManager(account, pathConfig, serviceConfiguration, userAgent, newManagerListener);
     }
 
     public void register(boolean voiceVerification, String captcha) throws IOException, CaptchaRequiredException {
+        captcha = captcha == null ? null : captcha.replace("signalcaptcha://", "");
         final ServiceResponse<RequestVerificationCodeResponse> response;
         if (voiceVerification) {
             response = accountManager.requestVoiceVerificationCode(Utils.getDefaultLocale(),
@@ -140,7 +155,7 @@ public class RegistrationManager implements Closeable {
         }
     }
 
-    public Manager verifyAccount(
+    public void verifyAccount(
             String verificationCode, String pin
     ) throws IOException, PinLockedException, IncorrectPinException {
         verificationCode = verificationCode.replace("-", "");
@@ -196,10 +211,10 @@ public class RegistrationManager implements Closeable {
                 logger.warn("Failed to set default profile: {}", e.getMessage());
             }
 
-            final var result = m;
-            m = null;
-
-            return result;
+            if (newManagerListener != null) {
+                newManagerListener.accept(m);
+                m = null;
+            }
         } finally {
             if (m != null) {
                 m.close();
index 060572aabcc28e35d5d0f86c99920027c360fb25..0a8c7b4151356f9252e00a865d7d0b3b9c035a08 100644 (file)
@@ -12,13 +12,13 @@ import org.asamk.signal.commands.LocalCommand;
 import org.asamk.signal.commands.MultiLocalCommand;
 import org.asamk.signal.commands.ProvisioningCommand;
 import org.asamk.signal.commands.RegistrationCommand;
-import org.asamk.signal.commands.SignalCreator;
 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.dbus.DbusManagerImpl;
 import org.asamk.signal.manager.Manager;
+import org.asamk.signal.manager.MultiAccountManagerImpl;
 import org.asamk.signal.manager.NotRegisteredException;
 import org.asamk.signal.manager.ProvisioningManager;
 import org.asamk.signal.manager.RegistrationManager;
@@ -39,8 +39,6 @@ import java.io.OutputStreamWriter;
 import java.nio.charset.Charset;
 import java.util.ArrayList;
 import java.util.List;
-import java.util.function.Consumer;
-import java.util.stream.Collectors;
 
 import static net.sourceforge.argparse4j.DefaultSettings.VERSION_0_9_0_DEFAULT_SETTINGS;
 
@@ -186,7 +184,7 @@ public class App {
                 throw new UserErrorException("No local users found, you first need to register or link an account");
             } else if (accounts.size() > 1) {
                 throw new UserErrorException(
-                        "Multiple users found, you need to specify a account (phone number) with -u");
+                        "Multiple users found, you need to specify an account (phone number) with -a");
             }
 
             account = accounts.get(0);
@@ -237,8 +235,8 @@ public class App {
                     + e.getClass().getSimpleName()
                     + ")", e);
         }
-        try (var m = manager) {
-            command.handleCommand(ns, m);
+        try (manager) {
+            command.handleCommand(ns, manager);
         } catch (IOException e) {
             logger.warn("Cleanup failed", e);
         }
@@ -268,73 +266,19 @@ public class App {
             final TrustNewIdentity trustNewIdentity
     ) throws CommandException {
         final var managers = new ArrayList<Manager>();
-        try {
-            for (String u : accounts) {
-                try {
-                    managers.add(loadManager(u, dataPath, serviceEnvironment, trustNewIdentity));
-                } catch (CommandException e) {
-                    logger.warn("Ignoring {}: {}", u, e.getMessage());
-                }
+        for (String a : accounts) {
+            try {
+                managers.add(loadManager(a, dataPath, serviceEnvironment, trustNewIdentity));
+            } catch (CommandException e) {
+                logger.warn("Ignoring {}: {}", a, e.getMessage());
             }
+        }
 
-            command.handleCommand(ns, new SignalCreator() {
-                private final List<Consumer<Manager>> onManagerAddedHandlers = new ArrayList<>();
-
-                @Override
-                public List<String> getAccountNumbers() {
-                    synchronized (managers) {
-                        return managers.stream().map(Manager::getSelfNumber).collect(Collectors.toList());
-                    }
-                }
-
-                @Override
-                public void addManager(final Manager m) {
-                    synchronized (managers) {
-                        if (!managers.contains(m)) {
-                            managers.add(m);
-                            for (final var handler : onManagerAddedHandlers) {
-                                handler.accept(m);
-                            }
-                        }
-                    }
-                }
-
-                @Override
-                public void addOnManagerAddedHandler(final Consumer<Manager> handler) {
-                    onManagerAddedHandlers.add(handler);
-                }
-
-                @Override
-                public Manager getManager(final String phoneNumber) {
-                    synchronized (managers) {
-                        return managers.stream()
-                                .filter(m -> m.getSelfNumber().equals(phoneNumber))
-                                .findFirst()
-                                .orElse(null);
-                    }
-                }
-
-                @Override
-                public ProvisioningManager getNewProvisioningManager() {
-                    return ProvisioningManager.init(dataPath, serviceEnvironment, BaseConfig.USER_AGENT);
-                }
-
-                @Override
-                public RegistrationManager getNewRegistrationManager(String account) throws IOException {
-                    return RegistrationManager.init(account, dataPath, serviceEnvironment, BaseConfig.USER_AGENT);
-                }
-            }, outputWriter);
-        } finally {
-            synchronized (managers) {
-                for (var m : managers) {
-                    try {
-                        m.close();
-                    } catch (IOException e) {
-                        logger.warn("Cleanup failed", e);
-                    }
-                }
-                managers.clear();
-            }
+        try (var multiAccountManager = new MultiAccountManagerImpl(managers,
+                dataPath,
+                serviceEnvironment,
+                BaseConfig.USER_AGENT)) {
+            command.handleCommand(ns, multiAccountManager, outputWriter);
         }
     }
 
index 5e7156474d74f27c8703b412e700891b2e14c6fc..605182ae04a999bd52f453d243a2bcb87d306202 100644 (file)
@@ -19,6 +19,7 @@ import org.asamk.signal.dbus.DbusSignalControlImpl;
 import org.asamk.signal.dbus.DbusSignalImpl;
 import org.asamk.signal.jsonrpc.SignalJsonRpcDispatcherHandler;
 import org.asamk.signal.manager.Manager;
+import org.asamk.signal.manager.MultiAccountManager;
 import org.asamk.signal.util.IOUtils;
 import org.freedesktop.dbus.connections.impl.DBusConnection;
 import org.freedesktop.dbus.exceptions.DBusException;
@@ -141,7 +142,7 @@ public class DaemonCommand implements MultiLocalCommand, LocalCommand {
 
     @Override
     public void handleCommand(
-            final Namespace ns, final SignalCreator c, final OutputWriter outputWriter
+            final Namespace ns, final MultiAccountManager c, final OutputWriter outputWriter
     ) throws CommandException {
         logger.info("Starting daemon in multi-account mode");
         final var noReceiveStdOut = Boolean.TRUE.equals(ns.getBoolean("no-receive-stdout"));
@@ -220,7 +221,7 @@ public class DaemonCommand implements MultiLocalCommand, LocalCommand {
     }
 
     private void runSocketMultiAccount(
-            final SignalCreator c, final ServerSocketChannel serverChannel, final boolean noReceiveOnStart
+            final MultiAccountManager c, final ServerSocketChannel serverChannel, final boolean noReceiveOnStart
     ) {
         runSocket(serverChannel, channel -> {
             final var handler = getSignalJsonRpcDispatcherHandler(channel, noReceiveOnStart);
@@ -276,7 +277,7 @@ public class DaemonCommand implements MultiLocalCommand, LocalCommand {
     }
 
     private void runDbusMultiAccount(
-            final SignalCreator c, final boolean noReceiveOnStart, final boolean isDbusSystem
+            final MultiAccountManager c, final boolean noReceiveOnStart, final boolean isDbusSystem
     ) throws UnexpectedErrorException {
         runDbus(isDbusSystem, (connection, objectPath) -> {
             final var signalControl = new DbusSignalControlImpl(c, objectPath);
index 3f5b04a0867c221d3ae4761efc818c2a2669d9e0..5ac5e4df878c18c7c578e9c152a851c4b846e9ca 100644 (file)
@@ -2,8 +2,9 @@ package org.asamk.signal.commands;
 
 import org.asamk.signal.JsonWriter;
 import org.asamk.signal.commands.exceptions.CommandException;
+import org.asamk.signal.manager.MultiAccountManager;
 
 public interface JsonRpcMultiCommand<T> extends JsonRpcCommand<T> {
 
-    void handleCommand(T request, SignalCreator c, JsonWriter jsonWriter) throws CommandException;
+    void handleCommand(T request, MultiAccountManager c, JsonWriter jsonWriter) throws CommandException;
 }
index 1701ac8c02cd542081bffee36dcc598253566df5..57bbe801f194caf6a899401a67b77d3ee55f2d97 100644 (file)
@@ -7,6 +7,7 @@ import net.sourceforge.argparse4j.inf.Namespace;
 import org.asamk.signal.JsonWriter;
 import org.asamk.signal.OutputType;
 import org.asamk.signal.commands.exceptions.CommandException;
+import org.asamk.signal.manager.MultiAccountManager;
 
 import java.util.List;
 import java.util.Map;
@@ -18,7 +19,7 @@ public interface JsonRpcMultiLocalCommand extends JsonRpcMultiCommand<Map<String
     }
 
     default void handleCommand(
-            Map<String, Object> request, SignalCreator c, JsonWriter jsonWriter
+            Map<String, Object> request, MultiAccountManager c, JsonWriter jsonWriter
     ) throws CommandException {
         Namespace commandNamespace = new JsonRpcNamespace(request == null ? Map.of() : request);
         handleCommand(commandNamespace, c, jsonWriter);
index 1d697299dc950657a350f198c1b43b08de02b940..c8830db2270073cded10b14844c18feb5ddc80a1 100644 (file)
@@ -43,9 +43,8 @@ public class LinkCommand implements ProvisioningCommand {
         }
         try {
             writer.println("{}", m.getDeviceLinkUri());
-            try (var manager = m.finishDeviceLink(deviceName)) {
-                writer.println("Associated with: {}", manager.getSelfNumber());
-            }
+            var number = m.finishDeviceLink(deviceName);
+            writer.println("Associated with: {}", number);
         } catch (TimeoutException e) {
             throw new UserErrorException("Link request timed out, please try again.");
         } catch (IOException e) {
index 3a04fb358faedfd7b9837966bbdcabd819e49926..4ad8fc2d2533687d4809d4d1bc8403c9bf28f309 100644 (file)
@@ -7,6 +7,7 @@ import org.asamk.signal.JsonWriter;
 import org.asamk.signal.OutputWriter;
 import org.asamk.signal.PlainTextWriter;
 import org.asamk.signal.commands.exceptions.CommandException;
+import org.asamk.signal.manager.MultiAccountManager;
 
 import java.util.stream.Collectors;
 
@@ -24,7 +25,7 @@ public class ListAccountsCommand implements JsonRpcMultiLocalCommand {
 
     @Override
     public void handleCommand(
-            final Namespace ns, final SignalCreator c, final OutputWriter outputWriter
+            final Namespace ns, final MultiAccountManager c, final OutputWriter outputWriter
     ) throws CommandException {
         final var accountNumbers = c.getAccountNumbers();
         if (outputWriter instanceof JsonWriter jsonWriter) {
index 9cc6846cb095e991678a3f8abe3b7bb491343f6f..da37c7a71f6b488f8310f1afabf890c1176e94e4 100644 (file)
@@ -4,8 +4,9 @@ import net.sourceforge.argparse4j.inf.Namespace;
 
 import org.asamk.signal.OutputWriter;
 import org.asamk.signal.commands.exceptions.CommandException;
+import org.asamk.signal.manager.MultiAccountManager;
 
 public interface MultiLocalCommand extends CliCommand {
 
-    void handleCommand(Namespace ns, SignalCreator c, OutputWriter outputWriter) throws CommandException;
+    void handleCommand(Namespace ns, MultiAccountManager c, OutputWriter outputWriter) throws CommandException;
 }
index 46f69896d825172683a5eb05095a66dc76762b7a..075833921eb394560f2d5da57f574c365b9c771f 100644 (file)
@@ -32,8 +32,7 @@ public class SubmitRateLimitChallengeCommand implements JsonRpcLocalCommand {
     @Override
     public void handleCommand(final Namespace ns, final Manager m, OutputWriter outputWriter) throws CommandException {
         final var challenge = ns.getString("challenge");
-        final var captchaString = ns.getString("captcha");
-        final var captcha = captchaString == null ? null : captchaString.replace("signalcaptcha://", "");
+        final var captcha = ns.getString("captcha");
 
         try {
             m.submitRateLimitRecaptchaChallenge(challenge, captcha);
index 9179988729f37d3adcbc19f83da3c82e04a00b25..155cdb09229f730206c0a40e83c27162374bac4b 100644 (file)
@@ -32,8 +32,7 @@ public class VerifyCommand implements RegistrationCommand {
         var pin = ns.getString("pin");
 
         try {
-            final var manager = m.verifyAccount(verificationCode, pin);
-            manager.close();
+            m.verifyAccount(verificationCode, pin);
         } catch (PinLockedException e) {
             throw new UserErrorException(
                     "Verification failed! This number is locked with a pin. Hours remaining until reset: "
index 7263efac160ae34b2f4705f5a207207f3cb05724..b8fb1fe96b6813b32d4855af129a30056ac96486 100644 (file)
@@ -4,6 +4,7 @@ import org.asamk.signal.BaseConfig;
 import org.asamk.signal.JsonWriter;
 import org.asamk.signal.commands.exceptions.CommandException;
 import org.asamk.signal.manager.Manager;
+import org.asamk.signal.manager.MultiAccountManager;
 
 import java.util.Map;
 
@@ -23,7 +24,7 @@ public class VersionCommand implements JsonRpcSingleCommand<Void>, JsonRpcMultiC
 
     @Override
     public void handleCommand(
-            final Void request, final SignalCreator c, final JsonWriter jsonWriter
+            final Void request, final MultiAccountManager c, final JsonWriter jsonWriter
     ) throws CommandException {
         outputVersion(jsonWriter);
     }
index e178ca1520fd5c468618efda6d37179ef72be74e..18d966ae959265c79aa43bed45da826ac6c4f64a 100644 (file)
@@ -3,8 +3,8 @@ package org.asamk.signal.dbus;
 import org.asamk.SignalControl;
 import org.asamk.signal.BaseConfig;
 import org.asamk.signal.DbusConfig;
-import org.asamk.signal.commands.SignalCreator;
 import org.asamk.signal.manager.Manager;
+import org.asamk.signal.manager.MultiAccountManager;
 import org.asamk.signal.manager.ProvisioningManager;
 import org.asamk.signal.manager.RegistrationManager;
 import org.asamk.signal.manager.UserAlreadyExists;
@@ -21,11 +21,11 @@ import java.util.stream.Collectors;
 
 public class DbusSignalControlImpl implements org.asamk.SignalControl {
 
-    private final SignalCreator c;
+    private final MultiAccountManager c;
 
     private final String objectPath;
 
-    public DbusSignalControlImpl(final SignalCreator c, final String objectPath) {
+    public DbusSignalControlImpl(final MultiAccountManager c, final String objectPath) {
         this.c = c;
         this.objectPath = objectPath;
     }
@@ -75,8 +75,7 @@ public class DbusSignalControlImpl implements org.asamk.SignalControl {
             final String number, final String verificationCode, final String pin
     ) throws Error.Failure, Error.InvalidNumber {
         try (final RegistrationManager registrationManager = c.getNewRegistrationManager(number)) {
-            final Manager manager = registrationManager.verifyAccount(verificationCode, pin);
-            c.addManager(manager);
+            registrationManager.verifyAccount(verificationCode, pin);
         } catch (IOException | PinLockedException | IncorrectPinException e) {
             throw new SignalControl.Error.Failure(e.getClass().getSimpleName() + " " + e.getMessage());
         }
@@ -89,8 +88,7 @@ public class DbusSignalControlImpl implements org.asamk.SignalControl {
             final URI deviceLinkUri = provisioningManager.getDeviceLinkUri();
             new Thread(() -> {
                 try {
-                    final Manager manager = provisioningManager.finishDeviceLink(newDeviceName);
-                    c.addManager(manager);
+                    provisioningManager.finishDeviceLink(newDeviceName);
                 } catch (IOException | TimeoutException | UserAlreadyExists e) {
                     e.printStackTrace();
                 }
index c9099c0b1d66406c01c5ee08ee571040a4268bda..2983b2931f292eb7502e4529e683359c0021c029 100644 (file)
@@ -129,9 +129,7 @@ public class DbusSignalImpl implements Signal {
     }
 
     @Override
-    public void submitRateLimitChallenge(String challenge, String captchaString) {
-        final var captcha = captchaString == null ? null : captchaString.replace("signalcaptcha://", "");
-
+    public void submitRateLimitChallenge(String challenge, String captcha) {
         try {
             m.submitRateLimitRecaptchaChallenge(challenge, captcha);
         } catch (IOException e) {
index d2debfe0e1871c87b9b267f235fba1a06e010943..112bc5a9f8ae766dfcb8404a59fcde521bbd64a5 100644 (file)
@@ -6,6 +6,7 @@ import com.fasterxml.jackson.databind.JsonMappingException;
 import com.fasterxml.jackson.databind.JsonNode;
 import com.fasterxml.jackson.databind.ObjectMapper;
 import com.fasterxml.jackson.databind.node.ContainerNode;
+import com.fasterxml.jackson.databind.node.ObjectNode;
 
 import org.asamk.signal.JsonReceiveMessageHandler;
 import org.asamk.signal.JsonWriter;
@@ -13,12 +14,12 @@ import org.asamk.signal.commands.Command;
 import org.asamk.signal.commands.Commands;
 import org.asamk.signal.commands.JsonRpcMultiCommand;
 import org.asamk.signal.commands.JsonRpcSingleCommand;
-import org.asamk.signal.commands.SignalCreator;
 import org.asamk.signal.commands.exceptions.CommandException;
 import org.asamk.signal.commands.exceptions.IOErrorException;
 import org.asamk.signal.commands.exceptions.UntrustedKeyErrorException;
 import org.asamk.signal.commands.exceptions.UserErrorException;
 import org.asamk.signal.manager.Manager;
+import org.asamk.signal.manager.MultiAccountManager;
 import org.asamk.signal.util.Util;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -42,7 +43,7 @@ public class SignalJsonRpcDispatcherHandler {
     private final JsonRpcReader jsonRpcReader;
     private final boolean noReceiveOnStart;
 
-    private SignalCreator c;
+    private MultiAccountManager c;
     private final Map<Manager, Manager.ReceiveMessageHandler> receiveHandlers = new HashMap<>();
 
     private Manager m;
@@ -56,7 +57,7 @@ public class SignalJsonRpcDispatcherHandler {
         this.jsonRpcReader = new JsonRpcReader(jsonRpcSender, lineSupplier);
     }
 
-    public void handleConnection(final SignalCreator c) {
+    public void handleConnection(final MultiAccountManager c) {
         this.c = c;
 
         if (!noReceiveOnStart) {
@@ -120,19 +121,19 @@ public class SignalJsonRpcDispatcherHandler {
     ) throws JsonRpcException {
         var command = getCommand(method);
         // TODO implement register, verify, link
-        if (c != null && command instanceof JsonRpcMultiCommand<?> jsonRpcCommand) {
-            return runCommand(objectMapper, params, new MultiCommandRunnerImpl<>(c, jsonRpcCommand));
+        if (c != null) {
+            if (command instanceof JsonRpcMultiCommand<?> jsonRpcCommand) {
+                return runCommand(objectMapper, params, new MultiCommandRunnerImpl<>(c, jsonRpcCommand));
+            }
         }
         if (command instanceof JsonRpcSingleCommand<?> jsonRpcCommand) {
             if (m != null) {
                 return runCommand(objectMapper, params, new CommandRunnerImpl<>(m, jsonRpcCommand));
             }
 
-            if (params.has("account")) {
-                Manager manager = c.getManager(params.get("account").asText());
-                if (manager != null) {
-                    return runCommand(objectMapper, params, new CommandRunnerImpl<>(manager, jsonRpcCommand));
-                }
+            final var manager = getManagerFromParams(params);
+            if (manager != null) {
+                return runCommand(objectMapper, params, new CommandRunnerImpl<>(manager, jsonRpcCommand));
             } else {
                 throw new JsonRpcException(new JsonRpcResponse.Error(JsonRpcResponse.Error.INVALID_PARAMS,
                         "Method requires valid account parameter",
@@ -145,6 +146,15 @@ public class SignalJsonRpcDispatcherHandler {
                 null));
     }
 
+    private Manager getManagerFromParams(final ContainerNode<?> params) {
+        if (params.has("account")) {
+            final var manager = c.getManager(params.get("account").asText());
+            ((ObjectNode) params).remove("account");
+            return manager;
+        }
+        return null;
+    }
+
     private Command getCommand(final String method) {
         if ("subscribeReceive".equals(method)) {
             return new SubscribeReceiveCommand();
@@ -169,7 +179,7 @@ public class SignalJsonRpcDispatcherHandler {
     }
 
     private record MultiCommandRunnerImpl<T>(
-            SignalCreator c, JsonRpcMultiCommand<T> command
+            MultiAccountManager c, JsonRpcMultiCommand<T> command
     ) implements CommandRunner<T> {
 
         @Override