]> nmode's Git Repositories - signal-cli/blobdiff - lib/src/main/java/org/asamk/signal/manager/SignalAccountFiles.java
Add SignalAccountFiles as a central entry point
[signal-cli] / lib / src / main / java / org / asamk / signal / manager / SignalAccountFiles.java
diff --git a/lib/src/main/java/org/asamk/signal/manager/SignalAccountFiles.java b/lib/src/main/java/org/asamk/signal/manager/SignalAccountFiles.java
new file mode 100644 (file)
index 0000000..f1d37e8
--- /dev/null
@@ -0,0 +1,152 @@
+package org.asamk.signal.manager;
+
+import org.asamk.signal.manager.api.AccountCheckException;
+import org.asamk.signal.manager.api.NotRegisteredException;
+import org.asamk.signal.manager.config.ServiceConfig;
+import org.asamk.signal.manager.config.ServiceEnvironment;
+import org.asamk.signal.manager.config.ServiceEnvironmentConfig;
+import org.asamk.signal.manager.storage.SignalAccount;
+import org.asamk.signal.manager.storage.accounts.AccountsStore;
+import org.asamk.signal.manager.storage.identities.TrustNewIdentity;
+import org.asamk.signal.manager.util.KeyUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.whispersystems.libsignal.util.KeyHelper;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.Objects;
+import java.util.Set;
+import java.util.function.Consumer;
+
+public class SignalAccountFiles {
+
+    private static final Logger logger = LoggerFactory.getLogger(MultiAccountManager.class);
+
+    private final PathConfig pathConfig;
+    private final ServiceEnvironmentConfig serviceEnvironmentConfig;
+    private final String userAgent;
+    private final TrustNewIdentity trustNewIdentity;
+    private final AccountsStore accountsStore;
+
+    public SignalAccountFiles(
+            final File settingsPath,
+            final ServiceEnvironment serviceEnvironment,
+            final String userAgent,
+            final TrustNewIdentity trustNewIdentity
+    ) {
+        this.pathConfig = PathConfig.createDefault(settingsPath);
+        this.serviceEnvironmentConfig = ServiceConfig.getServiceEnvironmentConfig(serviceEnvironment, userAgent);
+        this.userAgent = userAgent;
+        this.trustNewIdentity = trustNewIdentity;
+        this.accountsStore = new AccountsStore(pathConfig.dataPath());
+    }
+
+    public Set<String> getAllLocalAccountNumbers() {
+        return accountsStore.getAllNumbers();
+    }
+
+    public MultiAccountManager initMultiAccountManager() {
+        final var managers = getAllLocalAccountNumbers().stream().map(a -> {
+            try {
+                return initManager(a);
+            } catch (NotRegisteredException | IOException | AccountCheckException e) {
+                logger.warn("Ignoring {}: {} ({})", a, e.getMessage(), e.getClass().getSimpleName());
+                return null;
+            }
+        }).filter(Objects::nonNull).toList();
+
+        return new MultiAccountManagerImpl(managers, this);
+    }
+
+    public Manager initManager(String number) throws IOException, NotRegisteredException, AccountCheckException {
+        final var accountPath = accountsStore.getPathByNumber(number);
+        if (accountPath == null || !SignalAccount.accountFileExists(pathConfig.dataPath(), accountPath)) {
+            throw new NotRegisteredException();
+        }
+
+        var account = SignalAccount.load(pathConfig.dataPath(), accountPath, true, trustNewIdentity);
+        if (!number.equals(account.getNumber())) {
+            account.close();
+            throw new IOException("Number in account file doesn't match expected number: " + account.getNumber());
+        }
+
+        if (!account.isRegistered()) {
+            account.close();
+            throw new NotRegisteredException();
+        }
+
+        account.initDatabase();
+
+        final var manager = new ManagerImpl(account,
+                pathConfig,
+                (newNumber, newAci) -> accountsStore.updateAccount(accountPath, newNumber, newAci),
+                serviceEnvironmentConfig,
+                userAgent);
+
+        try {
+            manager.checkAccountState();
+        } catch (IOException e) {
+            manager.close();
+            throw new AccountCheckException("Error while checking account " + number + ": " + e.getMessage(), e);
+        }
+
+        return manager;
+    }
+
+    public ProvisioningManager initProvisioningManager() {
+        return initProvisioningManager(null);
+    }
+
+    public ProvisioningManager initProvisioningManager(Consumer<Manager> newManagerListener) {
+        return new ProvisioningManagerImpl(pathConfig,
+                serviceEnvironmentConfig,
+                userAgent,
+                newManagerListener,
+                accountsStore);
+    }
+
+    public RegistrationManager initRegistrationManager(String number) throws IOException {
+        return initRegistrationManager(number, null);
+    }
+
+    public RegistrationManager initRegistrationManager(
+            String number, Consumer<Manager> newManagerListener
+    ) throws IOException {
+        final var accountPath = accountsStore.getPathByNumber(number);
+        if (accountPath == null || !SignalAccount.accountFileExists(pathConfig.dataPath(), accountPath)) {
+            final var newAccountPath = accountPath == null ? accountsStore.addAccount(number, null) : accountPath;
+            var identityKey = KeyUtils.generateIdentityKeyPair();
+            var registrationId = KeyHelper.generateRegistrationId(false);
+
+            var profileKey = KeyUtils.createProfileKey();
+            var account = SignalAccount.create(pathConfig.dataPath(),
+                    newAccountPath,
+                    number,
+                    identityKey,
+                    registrationId,
+                    profileKey,
+                    trustNewIdentity);
+
+            return new RegistrationManagerImpl(account,
+                    pathConfig,
+                    serviceEnvironmentConfig,
+                    userAgent,
+                    newManagerListener,
+                    (newNumber, newAci) -> accountsStore.updateAccount(newAccountPath, newNumber, newAci));
+        }
+
+        var account = SignalAccount.load(pathConfig.dataPath(), accountPath, true, trustNewIdentity);
+        if (!number.equals(account.getNumber())) {
+            account.close();
+            throw new IOException("Number in account file doesn't match expected number: " + account.getNumber());
+        }
+
+        return new RegistrationManagerImpl(account,
+                pathConfig,
+                serviceEnvironmentConfig,
+                userAgent,
+                newManagerListener,
+                (newNumber, newAci) -> accountsStore.updateAccount(accountPath, newNumber, newAci));
+    }
+}