]> nmode's Git Repositories - signal-cli/commitdiff
Command to check if number is registered (#391)
authorAtomic-Bean <75401809+Atomic-Bean@users.noreply.github.com>
Sun, 3 Jan 2021 20:02:34 +0000 (06:32 +1030)
committerGitHub <noreply@github.com>
Sun, 3 Jan 2021 20:02:34 +0000 (21:02 +0100)
* Added the isRegistered command

* Minor fixes

* Corrected description

* Added AsamK's suggestions

Fixes #178

man/signal-cli.1.adoc
src/main/java/org/asamk/signal/commands/Commands.java
src/main/java/org/asamk/signal/commands/GetUserStatusCommand.java [new file with mode: 0644]
src/main/java/org/asamk/signal/manager/Manager.java

index b5c221679cc63dd19810fc6ad6ee5d021338bee9..fa2db7c3f89d6f10a07f86309cf363252bc45c18 100644 (file)
@@ -124,6 +124,15 @@ Only works, if this is the master device.
 Specify the device you want to remove.
 Use listDevices to see the deviceIds.
 
 Specify the device you want to remove.
 Use listDevices to see the deviceIds.
 
+=== getUserStatus
+
+Uses a list of phone numbers to determine the statuses of those users. Shows if they are registered on the Signal Servers or not.
+
+[NUMBER [NUMBER ...]]::
+One or more numbers to check.
+*--json*::
+Output the statuses as an array of json objects.
+
 === send
 
 Send a message to another user or group.
 === send
 
 Send a message to another user or group.
index 85e7af32665095f5cd2d6fdab7b91eb052ee8777..1e081dffcf2499b1a7328e0c36e3810e2607c2a3 100644 (file)
@@ -11,6 +11,7 @@ public class Commands {
         addCommand("addDevice", new AddDeviceCommand());
         addCommand("block", new BlockCommand());
         addCommand("daemon", new DaemonCommand());
         addCommand("addDevice", new AddDeviceCommand());
         addCommand("block", new BlockCommand());
         addCommand("daemon", new DaemonCommand());
+        addCommand("getUserStatus", new GetUserStatusCommand());
         addCommand("link", new LinkCommand());
         addCommand("listContacts", new ListContactsCommand());
         addCommand("listDevices", new ListDevicesCommand());
         addCommand("link", new LinkCommand());
         addCommand("listContacts", new ListContactsCommand());
         addCommand("listDevices", new ListDevicesCommand());
diff --git a/src/main/java/org/asamk/signal/commands/GetUserStatusCommand.java b/src/main/java/org/asamk/signal/commands/GetUserStatusCommand.java
new file mode 100644 (file)
index 0000000..c4bdf3d
--- /dev/null
@@ -0,0 +1,87 @@
+package org.asamk.signal.commands;
+
+import com.fasterxml.jackson.annotation.JsonAutoDetect;
+import com.fasterxml.jackson.annotation.PropertyAccessor;
+import com.fasterxml.jackson.core.JsonGenerator;
+import com.fasterxml.jackson.databind.DeserializationFeature;
+import com.fasterxml.jackson.databind.ObjectMapper;
+
+import net.sourceforge.argparse4j.impl.Arguments;
+import net.sourceforge.argparse4j.inf.Namespace;
+import net.sourceforge.argparse4j.inf.Subparser;
+
+import org.asamk.signal.manager.Manager;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.Set;
+import java.util.Map;
+import java.util.List;
+
+public class GetUserStatusCommand implements LocalCommand {
+
+    @Override
+    public void attachToSubparser(final Subparser subparser) {
+        subparser.addArgument("number").help("Phone number").nargs("+");
+        subparser.help("Check if the specified phone number/s have been registered");
+        subparser.addArgument("--json")
+                .help("Output received messages in json format, one json object per line.")
+                .action(Arguments.storeTrue());
+    }
+
+    @Override
+    public int handleCommand(final Namespace ns, final Manager m) {
+        if (!m.isRegistered()) {
+            System.err.println("User is not registered.");
+            return 1;
+        }
+
+        // Setup the json object mapper
+        ObjectMapper jsonProcessor = new ObjectMapper();
+        jsonProcessor.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY); // disable autodetect
+        jsonProcessor.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
+        jsonProcessor.disable(JsonGenerator.Feature.AUTO_CLOSE_TARGET);
+
+        // Get a map of registration statuses
+        Map<String, Boolean> registered;
+        try {
+            registered = m.areUsersRegistered(new HashSet<>(ns.<String>getList("number")));
+        } catch (IOException e) {
+            System.err.println("Unable to check if users are registered");
+            return 1;
+        }
+
+        // Output
+        if (ns.getBoolean("json")) {
+            List<JsonIsRegistered> objects = new ArrayList<>();
+            for (Map.Entry<String, Boolean> entry : registered.entrySet()) {
+                objects.add(new JsonIsRegistered(entry.getKey(), entry.getValue()));
+            }
+
+            try {
+                System.out.println(jsonProcessor.writeValueAsString(objects));
+            } catch (IOException e) {
+                System.err.println(e.getMessage());
+            }
+
+        } else {
+            for (Map.Entry<String, Boolean> entry : registered.entrySet()) {
+                System.out.println(entry.getKey() + ": " + entry.getValue());
+            }
+        }
+
+        return 0;
+    }
+
+    private class JsonIsRegistered {
+        String name;
+        boolean isRegistered;
+
+        public JsonIsRegistered(String name, boolean isRegistered) {
+            this.name = name;
+            this.isRegistered = isRegistered;
+        }
+    }
+
+}
index 7ad7b88803ffe3a2fc55f7f6105beac8b2e57833..e964d21830694efb7a8ee07d6a5db140bd6a5ad8 100644 (file)
@@ -383,6 +383,28 @@ public class Manager implements Closeable {
         return account.isRegistered();
     }
 
         return account.isRegistered();
     }
 
+    /**
+     * This is used for checking a set of phone numbers for registration on Signal
+     *
+     * @param numbers The set of phone number in question
+     * @return A map of numbers to booleans. True if registered, false otherwise. Should never be null
+     * @throws IOException if its unable to check if the users are registered
+     */
+    public Map<String, Boolean> areUsersRegistered(Set<String> numbers) throws IOException {
+        // Note "contactDetails" has no optionals. It only gives us info on users who are registered
+        List<ContactTokenDetails> contactDetails = this.accountManager.getContacts(numbers);
+
+        // Make the initial map with all numbers set to false for now
+        Map<String, Boolean> usersRegistered = numbers.stream().collect(Collectors.toMap(x -> x, x -> false));
+
+        // Override the contacts we did obtain
+        for (ContactTokenDetails contactDetail : contactDetails) {
+            usersRegistered.put(contactDetail.getNumber(), true);
+        }
+
+        return usersRegistered;
+    }
+
     public void register(boolean voiceVerification, String captcha) throws IOException {
         account.setPassword(KeyUtils.createPassword());
 
     public void register(boolean voiceVerification, String captcha) throws IOException {
         account.setPassword(KeyUtils.createPassword());