]> nmode's Git Repositories - signal-cli/commitdiff
Refactor output writers
authorAsamK <asamk@gmx.de>
Sun, 8 Aug 2021 15:32:55 +0000 (17:32 +0200)
committerAsamK <asamk@gmx.de>
Sun, 8 Aug 2021 15:32:55 +0000 (17:32 +0200)
42 files changed:
src/main/java/org/asamk/signal/App.java
src/main/java/org/asamk/signal/DbusReceiveMessageHandler.java
src/main/java/org/asamk/signal/JsonDbusReceiveMessageHandler.java
src/main/java/org/asamk/signal/JsonReceiveMessageHandler.java
src/main/java/org/asamk/signal/JsonWriter.java
src/main/java/org/asamk/signal/OutputWriter.java [new file with mode: 0644]
src/main/java/org/asamk/signal/PlainTextWriter.java
src/main/java/org/asamk/signal/ReceiveMessageHandler.java
src/main/java/org/asamk/signal/commands/AddDeviceCommand.java
src/main/java/org/asamk/signal/commands/BlockCommand.java
src/main/java/org/asamk/signal/commands/Command.java
src/main/java/org/asamk/signal/commands/Commands.java
src/main/java/org/asamk/signal/commands/DaemonCommand.java
src/main/java/org/asamk/signal/commands/GetUserStatusCommand.java
src/main/java/org/asamk/signal/commands/JoinGroupCommand.java
src/main/java/org/asamk/signal/commands/LinkCommand.java
src/main/java/org/asamk/signal/commands/ListContactsCommand.java
src/main/java/org/asamk/signal/commands/ListDevicesCommand.java
src/main/java/org/asamk/signal/commands/ListGroupsCommand.java
src/main/java/org/asamk/signal/commands/ListIdentitiesCommand.java
src/main/java/org/asamk/signal/commands/QuitGroupCommand.java
src/main/java/org/asamk/signal/commands/ReceiveCommand.java
src/main/java/org/asamk/signal/commands/RegisterCommand.java
src/main/java/org/asamk/signal/commands/RemoteDeleteCommand.java
src/main/java/org/asamk/signal/commands/RemoveDeviceCommand.java
src/main/java/org/asamk/signal/commands/RemovePinCommand.java
src/main/java/org/asamk/signal/commands/SendCommand.java
src/main/java/org/asamk/signal/commands/SendContactsCommand.java
src/main/java/org/asamk/signal/commands/SendReactionCommand.java
src/main/java/org/asamk/signal/commands/SendSyncRequestCommand.java
src/main/java/org/asamk/signal/commands/SendTypingCommand.java
src/main/java/org/asamk/signal/commands/SetPinCommand.java
src/main/java/org/asamk/signal/commands/SubparserAttacher.java [new file with mode: 0644]
src/main/java/org/asamk/signal/commands/TrustCommand.java
src/main/java/org/asamk/signal/commands/UnblockCommand.java
src/main/java/org/asamk/signal/commands/UnregisterCommand.java
src/main/java/org/asamk/signal/commands/UpdateAccountCommand.java
src/main/java/org/asamk/signal/commands/UpdateContactCommand.java
src/main/java/org/asamk/signal/commands/UpdateGroupCommand.java
src/main/java/org/asamk/signal/commands/UpdateProfileCommand.java
src/main/java/org/asamk/signal/commands/UploadStickerPackCommand.java
src/main/java/org/asamk/signal/commands/VerifyCommand.java

index 9e410d2f10c96df4bbd79f024f2a5f319d56622a..33338a4c29db42b945f550fa117c328d19930746 100644 (file)
@@ -76,11 +76,10 @@ public class App {
 
         var subparsers = parser.addSubparsers().title("subcommands").dest("command");
 
-        final var commands = Commands.getCommands();
-        for (var entry : commands.entrySet()) {
-            var subparser = subparsers.addParser(entry.getKey());
-            entry.getValue().attachToSubparser(subparser);
-        }
+        Commands.getCommandSubparserAttachers().forEach((key, value) -> {
+            var subparser = subparsers.addParser(key);
+            value.attachToSubparser(subparser);
+        });
 
         return parser;
     }
@@ -90,13 +89,17 @@ public class App {
     }
 
     public void init() throws CommandException {
+        var outputType = ns.<OutputType>get("output");
+        var outputWriter = outputType == OutputType.JSON
+                ? new JsonWriter(System.out)
+                : new PlainTextWriterImpl(System.out);
+
         var commandKey = ns.getString("command");
-        var command = Commands.getCommand(commandKey);
+        var command = Commands.getCommand(commandKey, outputWriter);
         if (command == null) {
             throw new UserErrorException("Command not implemented!");
         }
 
-        var outputType = ns.<OutputType>get("output");
         if (!command.getSupportedOutputTypes().contains(outputType)) {
             throw new UserErrorException("Command doesn't support output type " + outputType.toString());
         }
index 8fb11a592ebeffbfe2b57adacd446e59154c00b6..ff7a56cf545186ca8ba7a098a2740ac35246990a 100644 (file)
@@ -10,8 +10,8 @@ public class DbusReceiveMessageHandler extends ReceiveMessageHandler {
     private final DBusConnection conn;
     private final String objectPath;
 
-    public DbusReceiveMessageHandler(Manager m, DBusConnection conn, final String objectPath) {
-        super(m);
+    public DbusReceiveMessageHandler(Manager m, PlainTextWriter writer, DBusConnection conn, final String objectPath) {
+        super(m, writer);
         this.conn = conn;
         this.objectPath = objectPath;
     }
index 4deeefd36c237d8561dbb90e56355949973350dd..5ed6af00f7e616ccb1026758e8f20bd8d07b4e50 100644 (file)
@@ -21,8 +21,10 @@ public class JsonDbusReceiveMessageHandler extends JsonReceiveMessageHandler {
 
     private final String objectPath;
 
-    public JsonDbusReceiveMessageHandler(Manager m, DBusConnection conn, final String objectPath) {
-        super(m);
+    public JsonDbusReceiveMessageHandler(
+            Manager m, JsonWriter jsonWriter, DBusConnection conn, final String objectPath
+    ) {
+        super(m, jsonWriter);
         this.conn = conn;
         this.objectPath = objectPath;
     }
index c8e1c24fe9bf5f5c38ecd660558590915efab45e..4cade79974c751ace9a818b9499ad9fb4a7a7931 100644 (file)
@@ -17,9 +17,9 @@ public class JsonReceiveMessageHandler implements Manager.ReceiveMessageHandler
     protected final Manager m;
     private final JsonWriter jsonWriter;
 
-    public JsonReceiveMessageHandler(Manager m) {
+    public JsonReceiveMessageHandler(Manager m, JsonWriter jsonWriter) {
         this.m = m;
-        jsonWriter = new JsonWriter(System.out);
+        this.jsonWriter = jsonWriter;
     }
 
     @Override
index 20cf7bc15b992fba15e01845e8b46eb4f93e4adf..c48fd095bdb9c1bef0758ba29f66edf0b0cf588e 100644 (file)
@@ -13,7 +13,7 @@ import java.io.OutputStreamWriter;
 import java.io.Writer;
 import java.nio.charset.StandardCharsets;
 
-public class JsonWriter {
+public class JsonWriter implements OutputWriter {
 
     private final Writer writer;
     private final ObjectMapper objectMapper;
diff --git a/src/main/java/org/asamk/signal/OutputWriter.java b/src/main/java/org/asamk/signal/OutputWriter.java
new file mode 100644 (file)
index 0000000..c282738
--- /dev/null
@@ -0,0 +1,5 @@
+package org.asamk.signal;
+
+public interface OutputWriter {
+
+}
index de738de966bbe1209d94d9b81216a0b32e36a241..92981e49a4a21407d7c674bccc613856a97b7726 100644 (file)
@@ -1,6 +1,8 @@
 package org.asamk.signal;
 
-public interface PlainTextWriter {
+import java.util.function.Consumer;
+
+public interface PlainTextWriter extends OutputWriter {
 
     void println(String format, Object... args);
 
@@ -10,12 +12,7 @@ public interface PlainTextWriter {
         println("");
     }
 
-    default void indent(final WriterConsumer subWriter) {
-        subWriter.consume(indentedWriter());
-    }
-
-    interface WriterConsumer {
-
-        void consume(PlainTextWriter writer);
+    default void indent(final Consumer<PlainTextWriter> subWriter) {
+        subWriter.accept(indentedWriter());
     }
 }
index 7228e005d70a8e1b5bf2dd47de51960306b247f7..323b6edfa2da295ca62d745cd7699a8c9591dde8 100644 (file)
@@ -29,15 +29,15 @@ import static org.asamk.signal.util.Util.getLegacyIdentifier;
 public class ReceiveMessageHandler implements Manager.ReceiveMessageHandler {
 
     final Manager m;
+    final PlainTextWriter writer;
 
-    public ReceiveMessageHandler(Manager m) {
+    public ReceiveMessageHandler(Manager m, final PlainTextWriter writer) {
         this.m = m;
+        this.writer = writer;
     }
 
     @Override
     public void handleMessage(SignalServiceEnvelope envelope, SignalServiceContent content, Throwable exception) {
-        PlainTextWriter writer = new PlainTextWriterImpl(System.out);
-
         if (envelope.hasSource()) {
             var source = envelope.getSourceAddress();
             writer.println("Envelope from: {} (device: {})", formatContact(source), envelope.getSourceDevice());
index df46f1a7a7dbcb7688312ac0cb6fe6d995dab756..67ba5b89d8518a111b49a9c2f9435a9dda487f37 100644 (file)
@@ -3,6 +3,7 @@ package org.asamk.signal.commands;
 import net.sourceforge.argparse4j.inf.Namespace;
 import net.sourceforge.argparse4j.inf.Subparser;
 
+import org.asamk.signal.OutputWriter;
 import org.asamk.signal.commands.exceptions.CommandException;
 import org.asamk.signal.commands.exceptions.IOErrorException;
 import org.asamk.signal.commands.exceptions.UnexpectedErrorException;
@@ -20,14 +21,16 @@ public class AddDeviceCommand implements LocalCommand {
 
     private final static Logger logger = LoggerFactory.getLogger(AddDeviceCommand.class);
 
-    @Override
-    public void attachToSubparser(final Subparser subparser) {
+    public static void attachToSubparser(final Subparser subparser) {
         subparser.help("Link another device to this device. Only works, if this is the master device.");
         subparser.addArgument("--uri")
                 .required(true)
                 .help("Specify the uri contained in the QR code shown by the new device.");
     }
 
+    public AddDeviceCommand(final OutputWriter outputWriter) {
+    }
+
     @Override
     public void handleCommand(final Namespace ns, final Manager m) throws CommandException {
         try {
index f94dfde44bd065e49dbb28b4bb4660e14783e46d..e62bb79a946b1221271dd5f6f3216c9d04595ee4 100644 (file)
@@ -3,6 +3,7 @@ package org.asamk.signal.commands;
 import net.sourceforge.argparse4j.inf.Namespace;
 import net.sourceforge.argparse4j.inf.Subparser;
 
+import org.asamk.signal.OutputWriter;
 import org.asamk.signal.commands.exceptions.CommandException;
 import org.asamk.signal.commands.exceptions.UserErrorException;
 import org.asamk.signal.manager.Manager;
@@ -18,20 +19,22 @@ public class BlockCommand implements LocalCommand {
 
     private final static Logger logger = LoggerFactory.getLogger(BlockCommand.class);
 
-    @Override
-    public void attachToSubparser(final Subparser subparser) {
+    public static void attachToSubparser(final Subparser subparser) {
         subparser.help("Block the given contacts or groups (no messages will be received)");
         subparser.addArgument("contact").help("Contact number").nargs("*");
         subparser.addArgument("-g", "--group").help("Group ID").nargs("*");
     }
 
+    public BlockCommand(final OutputWriter outputWriter) {
+    }
+
     @Override
     public void handleCommand(final Namespace ns, final Manager m) throws CommandException {
-        for (var contact_number : ns.<String>getList("contact")) {
+        for (var contactNumber : ns.<String>getList("contact")) {
             try {
-                m.setContactBlocked(contact_number, true);
+                m.setContactBlocked(contactNumber, true);
             } catch (InvalidNumberException e) {
-                logger.warn("Invalid number {}: {}", contact_number, e.getMessage());
+                logger.warn("Invalid number {}: {}", contactNumber, e.getMessage());
             } catch (NotMasterDeviceException e) {
                 throw new UserErrorException("This command doesn't work on linked devices.");
             }
index fc55cbe242963bdfdf3271a22cf4f8b13af2d8ff..9d054616f61727d9d4377479c3c4c6d148beed71 100644 (file)
@@ -1,15 +1,11 @@
 package org.asamk.signal.commands;
 
-import net.sourceforge.argparse4j.inf.Subparser;
-
 import org.asamk.signal.OutputType;
 
 import java.util.Set;
 
 public interface Command {
 
-    void attachToSubparser(Subparser subparser);
-
     default Set<OutputType> getSupportedOutputTypes() {
         return Set.of(OutputType.PLAIN_TEXT);
     }
index 06e1fa1e1cc534ca3f85013f09c4ba09563a6c4a..2e1d682181a3ae2c285791281cf23fa56153ed9e 100644 (file)
@@ -1,58 +1,70 @@
 package org.asamk.signal.commands;
 
+import org.asamk.signal.OutputWriter;
+
+import java.util.HashMap;
 import java.util.Map;
 import java.util.TreeMap;
 
 public class Commands {
 
-    private static final Map<String, Command> commands = new TreeMap<>();
+    private static final Map<String, CommandConstructor> commands = new HashMap<>();
+    private static final Map<String, SubparserAttacher> commandSubparserAttacher = new TreeMap<>();
 
     static {
-        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("listGroups", new ListGroupsCommand());
-        addCommand("listIdentities", new ListIdentitiesCommand());
-        addCommand("joinGroup", new JoinGroupCommand());
-        addCommand("quitGroup", new QuitGroupCommand());
-        addCommand("receive", new ReceiveCommand());
-        addCommand("register", new RegisterCommand());
-        addCommand("removeDevice", new RemoveDeviceCommand());
-        addCommand("remoteDelete", new RemoteDeleteCommand());
-        addCommand("removePin", new RemovePinCommand());
-        addCommand("send", new SendCommand());
-        addCommand("sendContacts", new SendContactsCommand());
-        addCommand("sendReaction", new SendReactionCommand());
-        addCommand("sendSyncRequest", new SendSyncRequestCommand());
-        addCommand("sendTyping", new SendTypingCommand());
-        addCommand("setPin", new SetPinCommand());
-        addCommand("trust", new TrustCommand());
-        addCommand("unblock", new UnblockCommand());
-        addCommand("unregister", new UnregisterCommand());
-        addCommand("updateAccount", new UpdateAccountCommand());
-        addCommand("updateContact", new UpdateContactCommand());
-        addCommand("updateGroup", new UpdateGroupCommand());
-        addCommand("updateProfile", new UpdateProfileCommand());
-        addCommand("uploadStickerPack", new UploadStickerPackCommand());
-        addCommand("verify", new VerifyCommand());
+        addCommand("addDevice", AddDeviceCommand::new, AddDeviceCommand::attachToSubparser);
+        addCommand("block", BlockCommand::new, BlockCommand::attachToSubparser);
+        addCommand("daemon", DaemonCommand::new, DaemonCommand::attachToSubparser);
+        addCommand("getUserStatus", GetUserStatusCommand::new, GetUserStatusCommand::attachToSubparser);
+        addCommand("link", LinkCommand::new, LinkCommand::attachToSubparser);
+        addCommand("listContacts", ListContactsCommand::new, ListContactsCommand::attachToSubparser);
+        addCommand("listDevices", ListDevicesCommand::new, ListDevicesCommand::attachToSubparser);
+        addCommand("listGroups", ListGroupsCommand::new, ListGroupsCommand::attachToSubparser);
+        addCommand("listIdentities", ListIdentitiesCommand::new, ListIdentitiesCommand::attachToSubparser);
+        addCommand("joinGroup", JoinGroupCommand::new, JoinGroupCommand::attachToSubparser);
+        addCommand("quitGroup", QuitGroupCommand::new, QuitGroupCommand::attachToSubparser);
+        addCommand("receive", ReceiveCommand::new, ReceiveCommand::attachToSubparser);
+        addCommand("register", RegisterCommand::new, RegisterCommand::attachToSubparser);
+        addCommand("removeDevice", RemoveDeviceCommand::new, RemoveDeviceCommand::attachToSubparser);
+        addCommand("remoteDelete", RemoteDeleteCommand::new, RemoteDeleteCommand::attachToSubparser);
+        addCommand("removePin", RemovePinCommand::new, RemovePinCommand::attachToSubparser);
+        addCommand("send", SendCommand::new, SendCommand::attachToSubparser);
+        addCommand("sendContacts", SendContactsCommand::new, SendContactsCommand::attachToSubparser);
+        addCommand("sendReaction", SendReactionCommand::new, SendReactionCommand::attachToSubparser);
+        addCommand("sendSyncRequest", SendSyncRequestCommand::new, SendSyncRequestCommand::attachToSubparser);
+        addCommand("sendTyping", SendTypingCommand::new, SendTypingCommand::attachToSubparser);
+        addCommand("setPin", SetPinCommand::new, SetPinCommand::attachToSubparser);
+        addCommand("trust", TrustCommand::new, TrustCommand::attachToSubparser);
+        addCommand("unblock", UnblockCommand::new, UnblockCommand::attachToSubparser);
+        addCommand("unregister", UnregisterCommand::new, UnregisterCommand::attachToSubparser);
+        addCommand("updateAccount", UpdateAccountCommand::new, UpdateAccountCommand::attachToSubparser);
+        addCommand("updateContact", UpdateContactCommand::new, UpdateContactCommand::attachToSubparser);
+        addCommand("updateGroup", UpdateGroupCommand::new, UpdateGroupCommand::attachToSubparser);
+        addCommand("updateProfile", UpdateProfileCommand::new, UpdateProfileCommand::attachToSubparser);
+        addCommand("uploadStickerPack", UploadStickerPackCommand::new, UploadStickerPackCommand::attachToSubparser);
+        addCommand("verify", VerifyCommand::new, VerifyCommand::attachToSubparser);
     }
 
-    public static Map<String, Command> getCommands() {
-        return commands;
+    public static Map<String, SubparserAttacher> getCommandSubparserAttachers() {
+        return commandSubparserAttacher;
     }
 
-    public static Command getCommand(String commandKey) {
+    public static Command getCommand(String commandKey, OutputWriter outputWriter) {
         if (!commands.containsKey(commandKey)) {
             return null;
         }
-        return commands.get(commandKey);
+        return commands.get(commandKey).constructCommand(outputWriter);
+    }
+
+    private static void addCommand(
+            String name, CommandConstructor commandConstructor, SubparserAttacher subparserAttacher
+    ) {
+        commands.put(name, commandConstructor);
+        commandSubparserAttacher.put(name, subparserAttacher);
     }
 
-    private static void addCommand(String name, Command command) {
-        commands.put(name, command);
+    private interface CommandConstructor {
+
+        Command constructCommand(OutputWriter outputWriter);
     }
 }
index 8cafea103e229107c8b919fd7ee7d94565e7b440..f7d8b12e2e088a4e476c1348fb45e5ea51e81c85 100644 (file)
@@ -7,7 +7,10 @@ import net.sourceforge.argparse4j.inf.Subparser;
 import org.asamk.signal.DbusConfig;
 import org.asamk.signal.DbusReceiveMessageHandler;
 import org.asamk.signal.JsonDbusReceiveMessageHandler;
+import org.asamk.signal.JsonWriter;
 import org.asamk.signal.OutputType;
+import org.asamk.signal.OutputWriter;
+import org.asamk.signal.PlainTextWriter;
 import org.asamk.signal.commands.exceptions.CommandException;
 import org.asamk.signal.commands.exceptions.UnexpectedErrorException;
 import org.asamk.signal.dbus.DbusSignalImpl;
@@ -26,9 +29,9 @@ import java.util.concurrent.TimeUnit;
 public class DaemonCommand implements MultiLocalCommand {
 
     private final static Logger logger = LoggerFactory.getLogger(DaemonCommand.class);
+    private final OutputWriter outputWriter;
 
-    @Override
-    public void attachToSubparser(final Subparser subparser) {
+    public static void attachToSubparser(final Subparser subparser) {
         subparser.help("Run in daemon mode and provide an experimental dbus interface.");
         subparser.addArgument("--system")
                 .action(Arguments.storeTrue())
@@ -38,6 +41,10 @@ public class DaemonCommand implements MultiLocalCommand {
                 .action(Arguments.storeTrue());
     }
 
+    public DaemonCommand(final OutputWriter outputWriter) {
+        this.outputWriter = outputWriter;
+    }
+
     @Override
     public Set<OutputType> getSupportedOutputTypes() {
         return Set.of(OutputType.PLAIN_TEXT, OutputType.JSON);
@@ -45,8 +52,6 @@ public class DaemonCommand implements MultiLocalCommand {
 
     @Override
     public void handleCommand(final Namespace ns, final Manager m) throws CommandException {
-        var inJson = ns.get("output") == OutputType.JSON;
-
         boolean ignoreAttachments = ns.getBoolean("ignore-attachments");
 
         DBusConnection.DBusBusType busType;
@@ -58,7 +63,7 @@ public class DaemonCommand implements MultiLocalCommand {
 
         try (var conn = DBusConnection.getConnection(busType)) {
             var objectPath = DbusConfig.getObjectPath();
-            var t = run(conn, objectPath, m, ignoreAttachments, inJson);
+            var t = run(conn, objectPath, m, ignoreAttachments);
 
             conn.requestBusName(DbusConfig.getBusname());
 
@@ -74,8 +79,6 @@ public class DaemonCommand implements MultiLocalCommand {
 
     @Override
     public void handleCommand(final Namespace ns, final List<Manager> managers) throws CommandException {
-        var inJson = ns.get("output") == OutputType.JSON;
-
         boolean ignoreAttachments = ns.getBoolean("ignore-attachments");
 
         DBusConnection.DBusBusType busType;
@@ -89,7 +92,7 @@ public class DaemonCommand implements MultiLocalCommand {
             var receiveThreads = new ArrayList<Thread>();
             for (var m : managers) {
                 var objectPath = DbusConfig.getObjectPath(m.getUsername());
-                var thread = run(conn, objectPath, m, ignoreAttachments, inJson);
+                var thread = run(conn, objectPath, m, ignoreAttachments);
                 receiveThreads.add(thread);
             }
 
@@ -108,20 +111,17 @@ public class DaemonCommand implements MultiLocalCommand {
     }
 
     private Thread run(
-            DBusConnection conn, String objectPath, Manager m, boolean ignoreAttachments, boolean inJson
+            DBusConnection conn, String objectPath, Manager m, boolean ignoreAttachments
     ) throws DBusException {
         conn.exportObject(objectPath, new DbusSignalImpl(m));
 
         final var thread = new Thread(() -> {
             while (true) {
                 try {
-                    m.receiveMessages(1,
-                            TimeUnit.HOURS,
-                            false,
-                            ignoreAttachments,
-                            inJson
-                                    ? new JsonDbusReceiveMessageHandler(m, conn, objectPath)
-                                    : new DbusReceiveMessageHandler(m, conn, objectPath));
+                    final var receiveMessageHandler = outputWriter instanceof JsonWriter
+                            ? new JsonDbusReceiveMessageHandler(m, (JsonWriter) outputWriter, conn, objectPath)
+                            : new DbusReceiveMessageHandler(m, (PlainTextWriter) outputWriter, conn, objectPath);
+                    m.receiveMessages(1, TimeUnit.HOURS, false, ignoreAttachments, receiveMessageHandler);
                 } catch (IOException e) {
                     logger.warn("Receiving messages failed, retrying", e);
                 }
index 36b9777a9539603faff3d2c72e8e667e0b512711..4a35fc11c07059a9fff5bc660af2dfe65a0d6aa5 100644 (file)
@@ -5,6 +5,7 @@ import net.sourceforge.argparse4j.inf.Subparser;
 
 import org.asamk.signal.JsonWriter;
 import org.asamk.signal.OutputType;
+import org.asamk.signal.OutputWriter;
 import org.asamk.signal.PlainTextWriterImpl;
 import org.asamk.signal.commands.exceptions.CommandException;
 import org.asamk.signal.commands.exceptions.IOErrorException;
@@ -21,13 +22,17 @@ import java.util.stream.Collectors;
 public class GetUserStatusCommand implements LocalCommand {
 
     private final static Logger logger = LoggerFactory.getLogger(GetUserStatusCommand.class);
+    private final OutputWriter outputWriter;
 
-    @Override
-    public void attachToSubparser(final Subparser subparser) {
+    public static void attachToSubparser(final Subparser subparser) {
         subparser.help("Check if the specified phone number/s have been registered");
         subparser.addArgument("number").help("Phone number").nargs("+");
     }
 
+    public GetUserStatusCommand(final OutputWriter outputWriter) {
+        this.outputWriter = outputWriter;
+    }
+
     @Override
     public Set<OutputType> getSupportedOutputTypes() {
         return Set.of(OutputType.PLAIN_TEXT, OutputType.JSON);
@@ -35,9 +40,6 @@ public class GetUserStatusCommand implements LocalCommand {
 
     @Override
     public void handleCommand(final Namespace ns, final Manager m) throws CommandException {
-        // Setup the json object mapper
-        var inJson = ns.get("output") == OutputType.JSON;
-
         // Get a map of registration statuses
         Map<String, Boolean> registered;
         try {
@@ -48,8 +50,8 @@ public class GetUserStatusCommand implements LocalCommand {
         }
 
         // Output
-        if (inJson) {
-            final var jsonWriter = new JsonWriter(System.out);
+        if (outputWriter instanceof JsonWriter) {
+            final var jsonWriter = (JsonWriter) outputWriter;
 
             var jsonUserStatuses = registered.entrySet()
                     .stream()
@@ -58,7 +60,7 @@ public class GetUserStatusCommand implements LocalCommand {
 
             jsonWriter.write(jsonUserStatuses);
         } else {
-            final var writer = new PlainTextWriterImpl(System.out);
+            final var writer = (PlainTextWriterImpl) outputWriter;
 
             for (var entry : registered.entrySet()) {
                 writer.println("{}: {}", entry.getKey(), entry.getValue());
index d501c398b775f7099f531baf911a534f39169f73..6cb81b7edefa707e61e4f9f3160bd096067fc1d7 100644 (file)
@@ -3,6 +3,7 @@ package org.asamk.signal.commands;
 import net.sourceforge.argparse4j.inf.Namespace;
 import net.sourceforge.argparse4j.inf.Subparser;
 
+import org.asamk.signal.OutputWriter;
 import org.asamk.signal.PlainTextWriterImpl;
 import org.asamk.signal.commands.exceptions.CommandException;
 import org.asamk.signal.commands.exceptions.IOErrorException;
@@ -20,8 +21,13 @@ import static org.asamk.signal.util.ErrorUtils.handleTimestampAndSendMessageResu
 
 public class JoinGroupCommand implements LocalCommand {
 
-    @Override
-    public void attachToSubparser(final Subparser subparser) {
+    private final OutputWriter outputWriter;
+
+    public JoinGroupCommand(final OutputWriter outputWriter) {
+        this.outputWriter = outputWriter;
+    }
+
+    public static void attachToSubparser(final Subparser subparser) {
         subparser.help("Join a group via an invitation link.");
         subparser.addArgument("--uri").required(true).help("Specify the uri with the group invitation link.");
     }
@@ -43,7 +49,7 @@ public class JoinGroupCommand implements LocalCommand {
         }
 
         try {
-            final var writer = new PlainTextWriterImpl(System.out);
+            final var writer = (PlainTextWriterImpl) outputWriter;
 
             final var results = m.joinGroup(linkUrl);
             var newGroupId = results.first();
index 88493d3f73a482eff7a0e47401499a4e36016a5c..ae496758aa308c0fe3ba0c5acb88a05984835dab 100644 (file)
@@ -3,6 +3,7 @@ package org.asamk.signal.commands;
 import net.sourceforge.argparse4j.inf.Namespace;
 import net.sourceforge.argparse4j.inf.Subparser;
 
+import org.asamk.signal.OutputWriter;
 import org.asamk.signal.PlainTextWriterImpl;
 import org.asamk.signal.commands.exceptions.CommandException;
 import org.asamk.signal.commands.exceptions.IOErrorException;
@@ -18,16 +19,20 @@ import java.util.concurrent.TimeoutException;
 public class LinkCommand implements ProvisioningCommand {
 
     private final static Logger logger = LoggerFactory.getLogger(LinkCommand.class);
+    private final OutputWriter outputWriter;
 
-    @Override
-    public void attachToSubparser(final Subparser subparser) {
+    public LinkCommand(final OutputWriter outputWriter) {
+        this.outputWriter = outputWriter;
+    }
+
+    public static void attachToSubparser(final Subparser subparser) {
         subparser.help("Link to an existing device, instead of registering a new number.");
         subparser.addArgument("-n", "--name").help("Specify a name to describe this new device.");
     }
 
     @Override
     public void handleCommand(final Namespace ns, final ProvisioningManager m) throws CommandException {
-        final var writer = new PlainTextWriterImpl(System.out);
+        final var writer = (PlainTextWriterImpl) outputWriter;
 
         var deviceName = ns.getString("name");
         if (deviceName == null) {
index a546fc6e900bf02066fee4fca1bf53f333e66f1f..d0e115281bfeb8df4ca9f8eeaf54274fee81c8ba 100644 (file)
@@ -3,6 +3,7 @@ package org.asamk.signal.commands;
 import net.sourceforge.argparse4j.inf.Namespace;
 import net.sourceforge.argparse4j.inf.Subparser;
 
+import org.asamk.signal.OutputWriter;
 import org.asamk.signal.PlainTextWriterImpl;
 import org.asamk.signal.manager.Manager;
 
@@ -10,14 +11,19 @@ import static org.asamk.signal.util.Util.getLegacyIdentifier;
 
 public class ListContactsCommand implements LocalCommand {
 
-    @Override
-    public void attachToSubparser(final Subparser subparser) {
+    private final OutputWriter outputWriter;
+
+    public ListContactsCommand(final OutputWriter outputWriter) {
+        this.outputWriter = outputWriter;
+    }
+
+    public static void attachToSubparser(final Subparser subparser) {
         subparser.help("Show a list of known contacts with names.");
     }
 
     @Override
     public void handleCommand(final Namespace ns, final Manager m) {
-        final var writer = new PlainTextWriterImpl(System.out);
+        final var writer = (PlainTextWriterImpl) outputWriter;
 
         var contacts = m.getContacts();
         for (var c : contacts) {
index 0f8b58198b783744b03f57297fefbdf84f66ed6f..c0873c15a1e90c7875abc05a78cd4f4373b5511f 100644 (file)
@@ -3,6 +3,7 @@ package org.asamk.signal.commands;
 import net.sourceforge.argparse4j.inf.Namespace;
 import net.sourceforge.argparse4j.inf.Subparser;
 
+import org.asamk.signal.OutputWriter;
 import org.asamk.signal.PlainTextWriterImpl;
 import org.asamk.signal.commands.exceptions.CommandException;
 import org.asamk.signal.commands.exceptions.IOErrorException;
@@ -18,15 +19,19 @@ import java.util.List;
 public class ListDevicesCommand implements LocalCommand {
 
     private final static Logger logger = LoggerFactory.getLogger(ListDevicesCommand.class);
+    private final OutputWriter outputWriter;
 
-    @Override
-    public void attachToSubparser(final Subparser subparser) {
+    public ListDevicesCommand(final OutputWriter outputWriter) {
+        this.outputWriter = outputWriter;
+    }
+
+    public static void attachToSubparser(final Subparser subparser) {
         subparser.help("Show a list of linked devices.");
     }
 
     @Override
     public void handleCommand(final Namespace ns, final Manager m) throws CommandException {
-        final var writer = new PlainTextWriterImpl(System.out);
+        final var writer = (PlainTextWriterImpl) outputWriter;
 
         List<Device> devices;
         try {
index 3735419065aa35b56be5e7b71b96590e2eeb869c..1708ade0458bd009af2d59c64d4e9fa3b2c6ee86 100644 (file)
@@ -6,8 +6,8 @@ import net.sourceforge.argparse4j.inf.Subparser;
 
 import org.asamk.signal.JsonWriter;
 import org.asamk.signal.OutputType;
+import org.asamk.signal.OutputWriter;
 import org.asamk.signal.PlainTextWriter;
-import org.asamk.signal.PlainTextWriterImpl;
 import org.asamk.signal.commands.exceptions.CommandException;
 import org.asamk.signal.manager.Manager;
 import org.asamk.signal.manager.storage.groups.GroupInfo;
@@ -16,7 +16,6 @@ import org.asamk.signal.util.Util;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import java.util.ArrayList;
 import java.util.Set;
 import java.util.stream.Collectors;
 
@@ -24,6 +23,13 @@ public class ListGroupsCommand implements LocalCommand {
 
     private final static Logger logger = LoggerFactory.getLogger(ListGroupsCommand.class);
 
+    public static void attachToSubparser(final Subparser subparser) {
+        subparser.help("List group information including names, ids, active status, blocked status and members");
+        subparser.addArgument("-d", "--detailed")
+                .action(Arguments.storeTrue())
+                .help("List the members and group invite links of each group. If output=json, then this is always set");
+    }
+
     private static Set<String> resolveMembers(Manager m, Set<RecipientId> addresses) {
         return addresses.stream()
                 .map(m::resolveSignalServiceAddress)
@@ -58,12 +64,10 @@ public class ListGroupsCommand implements LocalCommand {
         }
     }
 
-    @Override
-    public void attachToSubparser(final Subparser subparser) {
-        subparser.help("List group information including names, ids, active status, blocked status and members");
-        subparser.addArgument("-d", "--detailed")
-                .action(Arguments.storeTrue())
-                .help("List the members and group invite links of each group. If output=json, then this is always set");
+    private final OutputWriter outputWriter;
+
+    public ListGroupsCommand(final OutputWriter outputWriter) {
+        this.outputWriter = outputWriter;
     }
 
     @Override
@@ -73,14 +77,15 @@ public class ListGroupsCommand implements LocalCommand {
 
     @Override
     public void handleCommand(final Namespace ns, final Manager m) throws CommandException {
-        if (ns.get("output") == OutputType.JSON) {
-            final var jsonWriter = new JsonWriter(System.out);
+        final var groups = m.getGroups();
+
+        if (outputWriter instanceof JsonWriter) {
+            final var jsonWriter = (JsonWriter) outputWriter;
 
-            var jsonGroups = new ArrayList<JsonGroup>();
-            for (var group : m.getGroups()) {
+            var jsonGroups = groups.stream().map(group -> {
                 final var groupInviteLink = group.getGroupInviteLink();
 
-                jsonGroups.add(new JsonGroup(group.getGroupId().toBase64(),
+                return new JsonGroup(group.getGroupId().toBase64(),
                         group.getTitle(),
                         group.getDescription(),
                         group.isMember(m.getSelfRecipientId()),
@@ -89,14 +94,14 @@ public class ListGroupsCommand implements LocalCommand {
                         resolveMembers(m, group.getPendingMembers()),
                         resolveMembers(m, group.getRequestingMembers()),
                         resolveMembers(m, group.getAdminMembers()),
-                        groupInviteLink == null ? null : groupInviteLink.getUrl()));
-            }
+                        groupInviteLink == null ? null : groupInviteLink.getUrl());
+            }).collect(Collectors.toList());
 
             jsonWriter.write(jsonGroups);
         } else {
-            final var writer = new PlainTextWriterImpl(System.out);
+            final var writer = (PlainTextWriter) outputWriter;
             boolean detailed = ns.getBoolean("detailed");
-            for (var group : m.getGroups()) {
+            for (var group : groups) {
                 printGroupPlainText(writer, m, group, detailed);
             }
         }
index 2029d6b18f2aacbaeec3a4fa7ebdf5af46fca5e4..9f4765997622ae251781baac391e6bd948884dfa 100644 (file)
@@ -3,6 +3,7 @@ package org.asamk.signal.commands;
 import net.sourceforge.argparse4j.inf.Namespace;
 import net.sourceforge.argparse4j.inf.Subparser;
 
+import org.asamk.signal.OutputWriter;
 import org.asamk.signal.PlainTextWriter;
 import org.asamk.signal.PlainTextWriterImpl;
 import org.asamk.signal.commands.exceptions.CommandException;
@@ -21,6 +22,11 @@ import java.util.List;
 public class ListIdentitiesCommand implements LocalCommand {
 
     private final static Logger logger = LoggerFactory.getLogger(ListIdentitiesCommand.class);
+    private final OutputWriter outputWriter;
+
+    public ListIdentitiesCommand(final OutputWriter outputWriter) {
+        this.outputWriter = outputWriter;
+    }
 
     private static void printIdentityFingerprint(PlainTextWriter writer, Manager m, IdentityInfo theirId) {
         final SignalServiceAddress address = m.resolveSignalServiceAddress(theirId.getRecipientId());
@@ -33,15 +39,14 @@ public class ListIdentitiesCommand implements LocalCommand {
                 digits);
     }
 
-    @Override
-    public void attachToSubparser(final Subparser subparser) {
+    public static void attachToSubparser(final Subparser subparser) {
         subparser.help("List all known identity keys and their trust status, fingerprint and safety number.");
         subparser.addArgument("-n", "--number").help("Only show identity keys for the given phone number.");
     }
 
     @Override
     public void handleCommand(final Namespace ns, final Manager m) throws CommandException {
-        final var writer = new PlainTextWriterImpl(System.out);
+        final var writer = (PlainTextWriterImpl) outputWriter;
 
         var number = ns.getString("number");
 
index 0a53c638d297ebe352642eae683c4e67dcb4e1a0..3414d304c9683fe6b07ccf27511af65b965c89cc 100644 (file)
@@ -4,6 +4,7 @@ import net.sourceforge.argparse4j.impl.Arguments;
 import net.sourceforge.argparse4j.inf.Namespace;
 import net.sourceforge.argparse4j.inf.Subparser;
 
+import org.asamk.signal.OutputWriter;
 import org.asamk.signal.PlainTextWriterImpl;
 import org.asamk.signal.commands.exceptions.CommandException;
 import org.asamk.signal.commands.exceptions.IOErrorException;
@@ -28,9 +29,13 @@ import static org.asamk.signal.util.ErrorUtils.handleTimestampAndSendMessageResu
 public class QuitGroupCommand implements LocalCommand {
 
     private final static Logger logger = LoggerFactory.getLogger(QuitGroupCommand.class);
+    private final OutputWriter outputWriter;
 
-    @Override
-    public void attachToSubparser(final Subparser subparser) {
+    public QuitGroupCommand(final OutputWriter outputWriter) {
+        this.outputWriter = outputWriter;
+    }
+
+    public static void attachToSubparser(final Subparser subparser) {
         subparser.help("Send a quit group message to all group members and remove self from member list.");
         subparser.addArgument("-g", "--group").required(true).help("Specify the recipient group ID.");
         subparser.addArgument("--delete")
@@ -43,7 +48,7 @@ public class QuitGroupCommand implements LocalCommand {
 
     @Override
     public void handleCommand(final Namespace ns, final Manager m) throws CommandException {
-        final var writer = new PlainTextWriterImpl(System.out);
+        final var writer = (PlainTextWriterImpl) outputWriter;
 
         final GroupId groupId;
         try {
index 5cae9e2e899a8e723dfc2eec166beefc0ec47c9f..301694e986631e0b9b8ef07e04b4f23394a5330a 100644 (file)
@@ -8,6 +8,8 @@ import org.asamk.Signal;
 import org.asamk.signal.JsonReceiveMessageHandler;
 import org.asamk.signal.JsonWriter;
 import org.asamk.signal.OutputType;
+import org.asamk.signal.OutputWriter;
+import org.asamk.signal.PlainTextWriter;
 import org.asamk.signal.PlainTextWriterImpl;
 import org.asamk.signal.ReceiveMessageHandler;
 import org.asamk.signal.commands.exceptions.CommandException;
@@ -30,9 +32,9 @@ import java.util.concurrent.TimeUnit;
 public class ReceiveCommand implements ExtendedDbusCommand, LocalCommand {
 
     private final static Logger logger = LoggerFactory.getLogger(ReceiveCommand.class);
+    private final OutputWriter outputWriter;
 
-    @Override
-    public void attachToSubparser(final Subparser subparser) {
+    public static void attachToSubparser(final Subparser subparser) {
         subparser.help("Query the server for new messages.");
         subparser.addArgument("-t", "--timeout")
                 .type(double.class)
@@ -43,6 +45,10 @@ public class ReceiveCommand implements ExtendedDbusCommand, LocalCommand {
                 .action(Arguments.storeTrue());
     }
 
+    public ReceiveCommand(final OutputWriter outputWriter) {
+        this.outputWriter = outputWriter;
+    }
+
     @Override
     public Set<OutputType> getSupportedOutputTypes() {
         return Set.of(OutputType.PLAIN_TEXT, OutputType.JSON);
@@ -51,11 +57,9 @@ public class ReceiveCommand implements ExtendedDbusCommand, LocalCommand {
     public void handleCommand(
             final Namespace ns, final Signal signal, DBusConnection dbusconnection
     ) throws CommandException {
-        var inJson = ns.get("output") == OutputType.JSON;
-
         try {
-            if (inJson) {
-                final var jsonWriter = new JsonWriter(System.out);
+            if (outputWriter instanceof JsonWriter) {
+                final var jsonWriter = (JsonWriter) outputWriter;
 
                 dbusconnection.addSigHandler(Signal.MessageReceived.class, signal, messageReceived -> {
                     var envelope = new JsonMessageEnvelope(messageReceived);
@@ -75,7 +79,7 @@ public class ReceiveCommand implements ExtendedDbusCommand, LocalCommand {
                     jsonWriter.write(object);
                 });
             } else {
-                final var writer = new PlainTextWriterImpl(System.out);
+                final var writer = (PlainTextWriterImpl) outputWriter;
 
                 dbusconnection.addSigHandler(Signal.MessageReceived.class, signal, messageReceived -> {
                     writer.println("Envelope from: {}", messageReceived.getSender());
@@ -135,8 +139,6 @@ public class ReceiveCommand implements ExtendedDbusCommand, LocalCommand {
 
     @Override
     public void handleCommand(final Namespace ns, final Manager m) throws CommandException {
-        var inJson = ns.get("output") == OutputType.JSON;
-
         double timeout = ns.getDouble("timeout");
         var returnOnTimeout = true;
         if (timeout < 0) {
@@ -145,7 +147,8 @@ public class ReceiveCommand implements ExtendedDbusCommand, LocalCommand {
         }
         boolean ignoreAttachments = ns.getBoolean("ignore-attachments");
         try {
-            final var handler = inJson ? new JsonReceiveMessageHandler(m) : new ReceiveMessageHandler(m);
+            final var handler = outputWriter instanceof JsonWriter ? new JsonReceiveMessageHandler(m,
+                    (JsonWriter) outputWriter) : new ReceiveMessageHandler(m, (PlainTextWriter) outputWriter);
             m.receiveMessages((long) (timeout * 1000),
                     TimeUnit.MILLISECONDS,
                     returnOnTimeout,
index 1b7e5ef9ca0fe3d1151d3c78853c882246a7b614..cd23c8abf0eff0ee7ea222c635b488da62e2f099 100644 (file)
@@ -4,6 +4,7 @@ import net.sourceforge.argparse4j.impl.Arguments;
 import net.sourceforge.argparse4j.inf.Namespace;
 import net.sourceforge.argparse4j.inf.Subparser;
 
+import org.asamk.signal.OutputWriter;
 import org.asamk.signal.commands.exceptions.CommandException;
 import org.asamk.signal.commands.exceptions.IOErrorException;
 import org.asamk.signal.commands.exceptions.UserErrorException;
@@ -14,8 +15,10 @@ import java.io.IOException;
 
 public class RegisterCommand implements RegistrationCommand {
 
-    @Override
-    public void attachToSubparser(final Subparser subparser) {
+    public RegisterCommand(final OutputWriter outputWriter) {
+    }
+
+    public static void attachToSubparser(final Subparser subparser) {
         subparser.help("Register a phone number with SMS or voice verification.");
         subparser.addArgument("-v", "--voice")
                 .help("The verification should be done over voice, not SMS.")
index 8efd581bd6de287db202b4904fc9f86049dbc175..0ab68a902b5575fb783beed4ea3f23b4e800f667 100644 (file)
@@ -4,6 +4,7 @@ import net.sourceforge.argparse4j.inf.Namespace;
 import net.sourceforge.argparse4j.inf.Subparser;
 
 import org.asamk.Signal;
+import org.asamk.signal.OutputWriter;
 import org.asamk.signal.PlainTextWriterImpl;
 import org.asamk.signal.commands.exceptions.CommandException;
 import org.asamk.signal.commands.exceptions.UnexpectedErrorException;
@@ -17,8 +18,13 @@ import java.util.List;
 
 public class RemoteDeleteCommand implements DbusCommand {
 
-    @Override
-    public void attachToSubparser(final Subparser subparser) {
+    private final OutputWriter outputWriter;
+
+    public RemoteDeleteCommand(final OutputWriter outputWriter) {
+        this.outputWriter = outputWriter;
+    }
+
+    public static void attachToSubparser(final Subparser subparser) {
         subparser.help("Remotely delete a previously sent message.");
         subparser.addArgument("-t", "--target-timestamp")
                 .required(true)
@@ -43,7 +49,7 @@ public class RemoteDeleteCommand implements DbusCommand {
 
         final long targetTimestamp = ns.getLong("target-timestamp");
 
-        final var writer = new PlainTextWriterImpl(System.out);
+        final var writer = (PlainTextWriterImpl) outputWriter;
 
         byte[] groupId = null;
         if (groupIdString != null) {
index 4de93c4523ccd564d25e75c0bed0637b8ca25b61..a4d4ffeae60cb708335089155f943aa97e76eac5 100644 (file)
@@ -3,6 +3,7 @@ package org.asamk.signal.commands;
 import net.sourceforge.argparse4j.inf.Namespace;
 import net.sourceforge.argparse4j.inf.Subparser;
 
+import org.asamk.signal.OutputWriter;
 import org.asamk.signal.commands.exceptions.CommandException;
 import org.asamk.signal.commands.exceptions.IOErrorException;
 import org.asamk.signal.manager.Manager;
@@ -11,8 +12,10 @@ import java.io.IOException;
 
 public class RemoveDeviceCommand implements LocalCommand {
 
-    @Override
-    public void attachToSubparser(final Subparser subparser) {
+    public RemoveDeviceCommand(final OutputWriter outputWriter) {
+    }
+
+    public static void attachToSubparser(final Subparser subparser) {
         subparser.help("Remove a linked device.");
         subparser.addArgument("-d", "--device-id", "--deviceId")
                 .type(int.class)
index ebf3cf0729568cdc38c2449fa68bf3be7817e293..b729a9b99b9867e8165c275c3356d69dbc7484b0 100644 (file)
@@ -3,6 +3,7 @@ package org.asamk.signal.commands;
 import net.sourceforge.argparse4j.inf.Namespace;
 import net.sourceforge.argparse4j.inf.Subparser;
 
+import org.asamk.signal.OutputWriter;
 import org.asamk.signal.commands.exceptions.CommandException;
 import org.asamk.signal.commands.exceptions.IOErrorException;
 import org.asamk.signal.commands.exceptions.UnexpectedErrorException;
@@ -14,8 +15,10 @@ import java.io.IOException;
 
 public class RemovePinCommand implements LocalCommand {
 
-    @Override
-    public void attachToSubparser(final Subparser subparser) {
+    public RemovePinCommand(final OutputWriter outputWriter) {
+    }
+
+    public static void attachToSubparser(final Subparser subparser) {
         subparser.help("Remove the registration lock pin.");
     }
 
index 90aaa09a492dd7006ea8834113f27059e368eeaf..af512def59c6028d73c20edb7876fbad836c53a2 100644 (file)
@@ -5,6 +5,7 @@ import net.sourceforge.argparse4j.inf.Namespace;
 import net.sourceforge.argparse4j.inf.Subparser;
 
 import org.asamk.Signal;
+import org.asamk.signal.OutputWriter;
 import org.asamk.signal.PlainTextWriterImpl;
 import org.asamk.signal.commands.exceptions.CommandException;
 import org.asamk.signal.commands.exceptions.UnexpectedErrorException;
@@ -25,9 +26,13 @@ import java.util.List;
 public class SendCommand implements DbusCommand {
 
     private final static Logger logger = LoggerFactory.getLogger(SendCommand.class);
+    private final OutputWriter outputWriter;
 
-    @Override
-    public void attachToSubparser(final Subparser subparser) {
+    public SendCommand(final OutputWriter outputWriter) {
+        this.outputWriter = outputWriter;
+    }
+
+    public static void attachToSubparser(final Subparser subparser) {
         subparser.help("Send a message to another user or group.");
         subparser.addArgument("recipient").help("Specify the recipients' phone number.").nargs("*");
         final var mutuallyExclusiveGroup = subparser.addMutuallyExclusiveGroup();
@@ -87,7 +92,7 @@ public class SendCommand implements DbusCommand {
             attachments = List.of();
         }
 
-        final var writer = new PlainTextWriterImpl(System.out);
+        final var writer = (PlainTextWriterImpl) outputWriter;
 
         if (groupIdString != null) {
             byte[] groupId;
index 176f1bb9c21c0e2d3f04e522b4ce825d0447ea90..6abf9c6f3bcf38e5f445f2446fb32823a1239315 100644 (file)
@@ -3,6 +3,7 @@ package org.asamk.signal.commands;
 import net.sourceforge.argparse4j.inf.Namespace;
 import net.sourceforge.argparse4j.inf.Subparser;
 
+import org.asamk.signal.OutputWriter;
 import org.asamk.signal.commands.exceptions.CommandException;
 import org.asamk.signal.commands.exceptions.IOErrorException;
 import org.asamk.signal.commands.exceptions.UntrustedKeyErrorException;
@@ -13,8 +14,10 @@ import java.io.IOException;
 
 public class SendContactsCommand implements LocalCommand {
 
-    @Override
-    public void attachToSubparser(final Subparser subparser) {
+    public SendContactsCommand(final OutputWriter outputWriter) {
+    }
+
+    public static void attachToSubparser(final Subparser subparser) {
         subparser.help("Send a synchronization message with the local contacts list to all linked devices.");
     }
 
index 44286acb8d8bdc40f0275087a3b175b00beb0b10..8ed9ac6359f8247f650abae1e310d63f77fb834d 100644 (file)
@@ -5,6 +5,7 @@ import net.sourceforge.argparse4j.inf.Namespace;
 import net.sourceforge.argparse4j.inf.Subparser;
 
 import org.asamk.Signal;
+import org.asamk.signal.OutputWriter;
 import org.asamk.signal.PlainTextWriterImpl;
 import org.asamk.signal.commands.exceptions.CommandException;
 import org.asamk.signal.commands.exceptions.UnexpectedErrorException;
@@ -18,8 +19,13 @@ import java.util.List;
 
 public class SendReactionCommand implements DbusCommand {
 
-    @Override
-    public void attachToSubparser(final Subparser subparser) {
+    private final OutputWriter outputWriter;
+
+    public SendReactionCommand(final OutputWriter outputWriter) {
+        this.outputWriter = outputWriter;
+    }
+
+    public static void attachToSubparser(final Subparser subparser) {
         subparser.help("Send reaction to a previously received or sent message.");
         subparser.addArgument("-g", "--group").help("Specify the recipient group ID.");
         subparser.addArgument("recipient").help("Specify the recipients' phone number.").nargs("*");
@@ -54,7 +60,7 @@ public class SendReactionCommand implements DbusCommand {
         final var targetAuthor = ns.getString("target-author");
         final long targetTimestamp = ns.getLong("target-timestamp");
 
-        final var writer = new PlainTextWriterImpl(System.out);
+        final var writer = (PlainTextWriterImpl) outputWriter;
 
         byte[] groupId = null;
         if (groupIdString != null) {
index db021a4ca2fb7b798b4117365d5e5552b8706d64..9ced51890d03f94c8b0a187e7b6259508053f657 100644 (file)
@@ -3,6 +3,7 @@ package org.asamk.signal.commands;
 import net.sourceforge.argparse4j.inf.Namespace;
 import net.sourceforge.argparse4j.inf.Subparser;
 
+import org.asamk.signal.OutputWriter;
 import org.asamk.signal.commands.exceptions.CommandException;
 import org.asamk.signal.commands.exceptions.IOErrorException;
 import org.asamk.signal.manager.Manager;
@@ -11,8 +12,10 @@ import java.io.IOException;
 
 public class SendSyncRequestCommand implements LocalCommand {
 
-    @Override
-    public void attachToSubparser(final Subparser subparser) {
+    public SendSyncRequestCommand(final OutputWriter outputWriter) {
+    }
+
+    public static void attachToSubparser(final Subparser subparser) {
         subparser.help("Send a synchronization request message to master device (for group, contacts, ...).");
     }
 
index 80637dfbd78a20ac7748dda100cc8b7b939d43a2..cbf34a6d84f9aeed1e5de39cb71e30f5295571b8 100644 (file)
@@ -4,6 +4,7 @@ import net.sourceforge.argparse4j.impl.Arguments;
 import net.sourceforge.argparse4j.inf.Namespace;
 import net.sourceforge.argparse4j.inf.Subparser;
 
+import org.asamk.signal.OutputWriter;
 import org.asamk.signal.commands.exceptions.CommandException;
 import org.asamk.signal.commands.exceptions.UserErrorException;
 import org.asamk.signal.manager.Manager;
@@ -21,8 +22,10 @@ import java.util.HashSet;
 
 public class SendTypingCommand implements LocalCommand {
 
-    @Override
-    public void attachToSubparser(final Subparser subparser) {
+    public SendTypingCommand(final OutputWriter outputWriter) {
+    }
+
+    public static void attachToSubparser(final Subparser subparser) {
         subparser.help(
                 "Send typing message to trigger a typing indicator for the recipient. Indicator will be shown for 15seconds unless a typing STOP message is sent first.");
         subparser.addArgument("-g", "--group").help("Specify the recipient group ID.");
index e0af992b8771b45547e3ec33f5c2c917fd125ae0..6958b16ad2cd91c6e31223816ad77c0c43423256 100644 (file)
@@ -3,6 +3,7 @@ package org.asamk.signal.commands;
 import net.sourceforge.argparse4j.inf.Namespace;
 import net.sourceforge.argparse4j.inf.Subparser;
 
+import org.asamk.signal.OutputWriter;
 import org.asamk.signal.commands.exceptions.CommandException;
 import org.asamk.signal.commands.exceptions.IOErrorException;
 import org.asamk.signal.commands.exceptions.UnexpectedErrorException;
@@ -14,8 +15,10 @@ import java.io.IOException;
 
 public class SetPinCommand implements LocalCommand {
 
-    @Override
-    public void attachToSubparser(final Subparser subparser) {
+    public SetPinCommand(final OutputWriter outputWriter) {
+    }
+
+    public static void attachToSubparser(final Subparser subparser) {
         subparser.help("Set a registration lock pin, to prevent others from registering this number.");
         subparser.addArgument("registrationLockPin")
                 .help("The registration lock PIN, that will be required for new registrations (resets after 7 days of inactivity)");
diff --git a/src/main/java/org/asamk/signal/commands/SubparserAttacher.java b/src/main/java/org/asamk/signal/commands/SubparserAttacher.java
new file mode 100644 (file)
index 0000000..3540afb
--- /dev/null
@@ -0,0 +1,8 @@
+package org.asamk.signal.commands;
+
+import net.sourceforge.argparse4j.inf.Subparser;
+
+public interface SubparserAttacher {
+
+    void attachToSubparser(final Subparser subparser);
+}
index 7f303dbb3034a6df73ed9581b731a9c1126d79b1..eb99386b3d6ee48ea564244b3148652fa1ad4f1b 100644 (file)
@@ -4,6 +4,7 @@ import net.sourceforge.argparse4j.impl.Arguments;
 import net.sourceforge.argparse4j.inf.Namespace;
 import net.sourceforge.argparse4j.inf.Subparser;
 
+import org.asamk.signal.OutputWriter;
 import org.asamk.signal.commands.exceptions.CommandException;
 import org.asamk.signal.commands.exceptions.UserErrorException;
 import org.asamk.signal.manager.Manager;
@@ -14,8 +15,10 @@ import java.util.Locale;
 
 public class TrustCommand implements LocalCommand {
 
-    @Override
-    public void attachToSubparser(final Subparser subparser) {
+    public TrustCommand(final OutputWriter outputWriter) {
+    }
+
+    public static void attachToSubparser(final Subparser subparser) {
         subparser.help("Set the trust level of a given number.");
         subparser.addArgument("number").help("Specify the phone number, for which to set the trust.").required(true);
         var mutTrust = subparser.addMutuallyExclusiveGroup();
index 824f1fcf36e4cdfc975f1e02756a39d7ad737d40..412a904f934bb45d93265e45c935d97f9a77e4f8 100644 (file)
@@ -3,6 +3,7 @@ package org.asamk.signal.commands;
 import net.sourceforge.argparse4j.inf.Namespace;
 import net.sourceforge.argparse4j.inf.Subparser;
 
+import org.asamk.signal.OutputWriter;
 import org.asamk.signal.commands.exceptions.CommandException;
 import org.asamk.signal.commands.exceptions.UserErrorException;
 import org.asamk.signal.manager.Manager;
@@ -18,8 +19,10 @@ public class UnblockCommand implements LocalCommand {
 
     private final static Logger logger = LoggerFactory.getLogger(UnblockCommand.class);
 
-    @Override
-    public void attachToSubparser(final Subparser subparser) {
+    public UnblockCommand(final OutputWriter outputWriter) {
+    }
+
+    public static void attachToSubparser(final Subparser subparser) {
         subparser.help("Unblock the given contacts or groups (messages will be received again)");
         subparser.addArgument("contact").help("Contact number").nargs("*");
         subparser.addArgument("-g", "--group").help("Group ID").nargs("*");
index d6d27e2824c2d6290d602decbd057068bf17daef..c8c754acb17123311cb7ca816b08d3217e9a811e 100644 (file)
@@ -4,6 +4,7 @@ import net.sourceforge.argparse4j.impl.Arguments;
 import net.sourceforge.argparse4j.inf.Namespace;
 import net.sourceforge.argparse4j.inf.Subparser;
 
+import org.asamk.signal.OutputWriter;
 import org.asamk.signal.commands.exceptions.CommandException;
 import org.asamk.signal.commands.exceptions.IOErrorException;
 import org.asamk.signal.manager.Manager;
@@ -12,8 +13,10 @@ import java.io.IOException;
 
 public class UnregisterCommand implements LocalCommand {
 
-    @Override
-    public void attachToSubparser(final Subparser subparser) {
+    public UnregisterCommand(final OutputWriter outputWriter) {
+    }
+
+    public static void attachToSubparser(final Subparser subparser) {
         subparser.help("Unregister the current device from the signal server.");
         subparser.addArgument("--delete-account")
                 .help("Delete account completely from server. CAUTION: Only do this if you won't use this number again!")
index 13723f09b671c7414dabe9873340ccf707970ba5..ff5aa27eae0a079d1cb5539cabe6e7d485265ea9 100644 (file)
@@ -3,6 +3,7 @@ package org.asamk.signal.commands;
 import net.sourceforge.argparse4j.inf.Namespace;
 import net.sourceforge.argparse4j.inf.Subparser;
 
+import org.asamk.signal.OutputWriter;
 import org.asamk.signal.commands.exceptions.CommandException;
 import org.asamk.signal.commands.exceptions.IOErrorException;
 import org.asamk.signal.manager.Manager;
@@ -11,8 +12,10 @@ import java.io.IOException;
 
 public class UpdateAccountCommand implements LocalCommand {
 
-    @Override
-    public void attachToSubparser(final Subparser subparser) {
+    public UpdateAccountCommand(final OutputWriter outputWriter) {
+    }
+
+    public static void attachToSubparser(final Subparser subparser) {
         subparser.help("Update the account attributes on the signal server.");
     }
 
index c8f4addecf039f84ca593e4b42d89150224a1225..931b2a612a62f5b171dc316b2415d67466aba2a2 100644 (file)
@@ -3,6 +3,7 @@ package org.asamk.signal.commands;
 import net.sourceforge.argparse4j.inf.Namespace;
 import net.sourceforge.argparse4j.inf.Subparser;
 
+import org.asamk.signal.OutputWriter;
 import org.asamk.signal.commands.exceptions.CommandException;
 import org.asamk.signal.commands.exceptions.IOErrorException;
 import org.asamk.signal.commands.exceptions.UserErrorException;
@@ -14,8 +15,10 @@ import java.io.IOException;
 
 public class UpdateContactCommand implements LocalCommand {
 
-    @Override
-    public void attachToSubparser(final Subparser subparser) {
+    public UpdateContactCommand(final OutputWriter outputWriter) {
+    }
+
+    public static void attachToSubparser(final Subparser subparser) {
         subparser.help("Update the details of a given contact");
         subparser.addArgument("number").help("Contact number");
         subparser.addArgument("-n", "--name").help("New contact name");
index 931ad76371216170cf51ce7e64dd60c738ab8508..b392df052d68a02065997b69790d67c740110fa0 100644 (file)
@@ -7,6 +7,7 @@ import net.sourceforge.argparse4j.inf.Subparser;
 import org.asamk.Signal;
 import org.asamk.signal.GroupLinkState;
 import org.asamk.signal.GroupPermission;
+import org.asamk.signal.OutputWriter;
 import org.asamk.signal.PlainTextWriterImpl;
 import org.asamk.signal.commands.exceptions.CommandException;
 import org.asamk.signal.commands.exceptions.UnexpectedErrorException;
@@ -33,9 +34,13 @@ import java.util.List;
 public class UpdateGroupCommand implements DbusCommand, LocalCommand {
 
     private final static Logger logger = LoggerFactory.getLogger(UpdateGroupCommand.class);
+    private final OutputWriter outputWriter;
 
-    @Override
-    public void attachToSubparser(final Subparser subparser) {
+    public UpdateGroupCommand(final OutputWriter outputWriter) {
+        this.outputWriter = outputWriter;
+    }
+
+    public static void attachToSubparser(final Subparser subparser) {
         subparser.help("Create or update a group.");
         subparser.addArgument("-g", "--group").help("Specify the recipient group ID.");
         subparser.addArgument("-n", "--name").help("Specify the new group name.");
@@ -69,7 +74,7 @@ public class UpdateGroupCommand implements DbusCommand, LocalCommand {
 
     @Override
     public void handleCommand(final Namespace ns, final Manager m) throws CommandException {
-        final var writer = new PlainTextWriterImpl(System.out);
+        final var writer = (PlainTextWriterImpl) outputWriter;
         GroupId groupId = null;
         final var groupIdString = ns.getString("group");
         if (groupIdString != null) {
@@ -137,7 +142,7 @@ public class UpdateGroupCommand implements DbusCommand, LocalCommand {
 
     @Override
     public void handleCommand(final Namespace ns, final Signal signal) throws CommandException {
-        final var writer = new PlainTextWriterImpl(System.out);
+        final var writer = (PlainTextWriterImpl) outputWriter;
         byte[] groupId = null;
         if (ns.getString("group") != null) {
             try {
index d8b9c6c767fbb93c7d6a441bf07e8434a5a7ba5e..894b19dfc8ed56710720ec9852533de4bde5f0b4 100644 (file)
@@ -4,6 +4,7 @@ import net.sourceforge.argparse4j.impl.Arguments;
 import net.sourceforge.argparse4j.inf.Namespace;
 import net.sourceforge.argparse4j.inf.Subparser;
 
+import org.asamk.signal.OutputWriter;
 import org.asamk.signal.commands.exceptions.CommandException;
 import org.asamk.signal.commands.exceptions.IOErrorException;
 import org.asamk.signal.manager.Manager;
@@ -14,8 +15,10 @@ import java.io.IOException;
 
 public class UpdateProfileCommand implements LocalCommand {
 
-    @Override
-    public void attachToSubparser(final Subparser subparser) {
+    public UpdateProfileCommand(final OutputWriter outputWriter) {
+    }
+
+    public static void attachToSubparser(final Subparser subparser) {
         subparser.help("Set a name, about and avatar image for the user profile");
         subparser.addArgument("--given-name", "--name").help("New profile (given) name");
         subparser.addArgument("--family-name").help("New profile family name (optional)");
index 095c7d9697221174daf813cf026df43ded264710..e2ba2ff9edc27937d89a1ff215ebb4f61f96e266 100644 (file)
@@ -3,6 +3,7 @@ package org.asamk.signal.commands;
 import net.sourceforge.argparse4j.inf.Namespace;
 import net.sourceforge.argparse4j.inf.Subparser;
 
+import org.asamk.signal.OutputWriter;
 import org.asamk.signal.PlainTextWriterImpl;
 import org.asamk.signal.commands.exceptions.CommandException;
 import org.asamk.signal.commands.exceptions.IOErrorException;
@@ -18,9 +19,13 @@ import java.io.IOException;
 public class UploadStickerPackCommand implements LocalCommand {
 
     private final static Logger logger = LoggerFactory.getLogger(UploadStickerPackCommand.class);
+    private final OutputWriter outputWriter;
 
-    @Override
-    public void attachToSubparser(final Subparser subparser) {
+    public UploadStickerPackCommand(final OutputWriter outputWriter) {
+        this.outputWriter = outputWriter;
+    }
+
+    public static void attachToSubparser(final Subparser subparser) {
         subparser.help("Upload a new sticker pack, consisting of a manifest file and the stickers images.");
         subparser.addArgument("path")
                 .help("The path of the manifest.json or a zip file containing the sticker pack you wish to upload.");
@@ -28,7 +33,7 @@ public class UploadStickerPackCommand implements LocalCommand {
 
     @Override
     public void handleCommand(final Namespace ns, final Manager m) throws CommandException {
-        final var writer = new PlainTextWriterImpl(System.out);
+        final var writer = (PlainTextWriterImpl) outputWriter;
         var path = new File(ns.getString("path"));
 
         try {
index b580be2abb19c7bf2becf17f7187aa975af79dd4..f32139bdccde69b8695db0fa0559b90ea86efdd3 100644 (file)
@@ -3,6 +3,7 @@ package org.asamk.signal.commands;
 import net.sourceforge.argparse4j.inf.Namespace;
 import net.sourceforge.argparse4j.inf.Subparser;
 
+import org.asamk.signal.OutputWriter;
 import org.asamk.signal.commands.exceptions.CommandException;
 import org.asamk.signal.commands.exceptions.IOErrorException;
 import org.asamk.signal.commands.exceptions.UnexpectedErrorException;
@@ -16,8 +17,10 @@ import java.io.IOException;
 
 public class VerifyCommand implements RegistrationCommand {
 
-    @Override
-    public void attachToSubparser(final Subparser subparser) {
+    public VerifyCommand(final OutputWriter outputWriter) {
+    }
+
+    public static void attachToSubparser(final Subparser subparser) {
         subparser.help("Verify the number using the code received via SMS or voice.");
         subparser.addArgument("verificationCode").help("The verification code you received via sms or voice call.");
         subparser.addArgument("-p", "--pin").help("The registration lock PIN, that was set by the user (Optional)");