From: AsamK Date: Sun, 8 Aug 2021 15:32:55 +0000 (+0200) Subject: Refactor output writers X-Git-Tag: v0.9.0~90 X-Git-Url: https://git.nmode.ca/signal-cli/commitdiff_plain/48b2c7ff8ad7b653c3a0cb42775a5850f593d0a0?ds=sidebyside Refactor output writers --- diff --git a/src/main/java/org/asamk/signal/App.java b/src/main/java/org/asamk/signal/App.java index 9e410d2f..33338a4c 100644 --- a/src/main/java/org/asamk/signal/App.java +++ b/src/main/java/org/asamk/signal/App.java @@ -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.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.get("output"); if (!command.getSupportedOutputTypes().contains(outputType)) { throw new UserErrorException("Command doesn't support output type " + outputType.toString()); } diff --git a/src/main/java/org/asamk/signal/DbusReceiveMessageHandler.java b/src/main/java/org/asamk/signal/DbusReceiveMessageHandler.java index 8fb11a59..ff7a56cf 100644 --- a/src/main/java/org/asamk/signal/DbusReceiveMessageHandler.java +++ b/src/main/java/org/asamk/signal/DbusReceiveMessageHandler.java @@ -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; } diff --git a/src/main/java/org/asamk/signal/JsonDbusReceiveMessageHandler.java b/src/main/java/org/asamk/signal/JsonDbusReceiveMessageHandler.java index 4deeefd3..5ed6af00 100644 --- a/src/main/java/org/asamk/signal/JsonDbusReceiveMessageHandler.java +++ b/src/main/java/org/asamk/signal/JsonDbusReceiveMessageHandler.java @@ -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; } diff --git a/src/main/java/org/asamk/signal/JsonReceiveMessageHandler.java b/src/main/java/org/asamk/signal/JsonReceiveMessageHandler.java index c8e1c24f..4cade799 100644 --- a/src/main/java/org/asamk/signal/JsonReceiveMessageHandler.java +++ b/src/main/java/org/asamk/signal/JsonReceiveMessageHandler.java @@ -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 diff --git a/src/main/java/org/asamk/signal/JsonWriter.java b/src/main/java/org/asamk/signal/JsonWriter.java index 20cf7bc1..c48fd095 100644 --- a/src/main/java/org/asamk/signal/JsonWriter.java +++ b/src/main/java/org/asamk/signal/JsonWriter.java @@ -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 index 00000000..c282738c --- /dev/null +++ b/src/main/java/org/asamk/signal/OutputWriter.java @@ -0,0 +1,5 @@ +package org.asamk.signal; + +public interface OutputWriter { + +} diff --git a/src/main/java/org/asamk/signal/PlainTextWriter.java b/src/main/java/org/asamk/signal/PlainTextWriter.java index de738de9..92981e49 100644 --- a/src/main/java/org/asamk/signal/PlainTextWriter.java +++ b/src/main/java/org/asamk/signal/PlainTextWriter.java @@ -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 subWriter) { + subWriter.accept(indentedWriter()); } } diff --git a/src/main/java/org/asamk/signal/ReceiveMessageHandler.java b/src/main/java/org/asamk/signal/ReceiveMessageHandler.java index 7228e005..323b6edf 100644 --- a/src/main/java/org/asamk/signal/ReceiveMessageHandler.java +++ b/src/main/java/org/asamk/signal/ReceiveMessageHandler.java @@ -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()); diff --git a/src/main/java/org/asamk/signal/commands/AddDeviceCommand.java b/src/main/java/org/asamk/signal/commands/AddDeviceCommand.java index df46f1a7..67ba5b89 100644 --- a/src/main/java/org/asamk/signal/commands/AddDeviceCommand.java +++ b/src/main/java/org/asamk/signal/commands/AddDeviceCommand.java @@ -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 { diff --git a/src/main/java/org/asamk/signal/commands/BlockCommand.java b/src/main/java/org/asamk/signal/commands/BlockCommand.java index f94dfde4..e62bb79a 100644 --- a/src/main/java/org/asamk/signal/commands/BlockCommand.java +++ b/src/main/java/org/asamk/signal/commands/BlockCommand.java @@ -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.getList("contact")) { + for (var contactNumber : ns.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."); } diff --git a/src/main/java/org/asamk/signal/commands/Command.java b/src/main/java/org/asamk/signal/commands/Command.java index fc55cbe2..9d054616 100644 --- a/src/main/java/org/asamk/signal/commands/Command.java +++ b/src/main/java/org/asamk/signal/commands/Command.java @@ -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 getSupportedOutputTypes() { return Set.of(OutputType.PLAIN_TEXT); } diff --git a/src/main/java/org/asamk/signal/commands/Commands.java b/src/main/java/org/asamk/signal/commands/Commands.java index 06e1fa1e..2e1d6821 100644 --- a/src/main/java/org/asamk/signal/commands/Commands.java +++ b/src/main/java/org/asamk/signal/commands/Commands.java @@ -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 commands = new TreeMap<>(); + private static final Map commands = new HashMap<>(); + private static final Map 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 getCommands() { - return commands; + public static Map 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); } } diff --git a/src/main/java/org/asamk/signal/commands/DaemonCommand.java b/src/main/java/org/asamk/signal/commands/DaemonCommand.java index 8cafea10..f7d8b12e 100644 --- a/src/main/java/org/asamk/signal/commands/DaemonCommand.java +++ b/src/main/java/org/asamk/signal/commands/DaemonCommand.java @@ -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 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 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(); 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); } diff --git a/src/main/java/org/asamk/signal/commands/GetUserStatusCommand.java b/src/main/java/org/asamk/signal/commands/GetUserStatusCommand.java index 36b9777a..4a35fc11 100644 --- a/src/main/java/org/asamk/signal/commands/GetUserStatusCommand.java +++ b/src/main/java/org/asamk/signal/commands/GetUserStatusCommand.java @@ -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 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 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()); diff --git a/src/main/java/org/asamk/signal/commands/JoinGroupCommand.java b/src/main/java/org/asamk/signal/commands/JoinGroupCommand.java index d501c398..6cb81b7e 100644 --- a/src/main/java/org/asamk/signal/commands/JoinGroupCommand.java +++ b/src/main/java/org/asamk/signal/commands/JoinGroupCommand.java @@ -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(); diff --git a/src/main/java/org/asamk/signal/commands/LinkCommand.java b/src/main/java/org/asamk/signal/commands/LinkCommand.java index 88493d3f..ae496758 100644 --- a/src/main/java/org/asamk/signal/commands/LinkCommand.java +++ b/src/main/java/org/asamk/signal/commands/LinkCommand.java @@ -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) { diff --git a/src/main/java/org/asamk/signal/commands/ListContactsCommand.java b/src/main/java/org/asamk/signal/commands/ListContactsCommand.java index a546fc6e..d0e11528 100644 --- a/src/main/java/org/asamk/signal/commands/ListContactsCommand.java +++ b/src/main/java/org/asamk/signal/commands/ListContactsCommand.java @@ -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) { diff --git a/src/main/java/org/asamk/signal/commands/ListDevicesCommand.java b/src/main/java/org/asamk/signal/commands/ListDevicesCommand.java index 0f8b5819..c0873c15 100644 --- a/src/main/java/org/asamk/signal/commands/ListDevicesCommand.java +++ b/src/main/java/org/asamk/signal/commands/ListDevicesCommand.java @@ -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 devices; try { diff --git a/src/main/java/org/asamk/signal/commands/ListGroupsCommand.java b/src/main/java/org/asamk/signal/commands/ListGroupsCommand.java index 37354190..1708ade0 100644 --- a/src/main/java/org/asamk/signal/commands/ListGroupsCommand.java +++ b/src/main/java/org/asamk/signal/commands/ListGroupsCommand.java @@ -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 resolveMembers(Manager m, Set 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(); - 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); } } diff --git a/src/main/java/org/asamk/signal/commands/ListIdentitiesCommand.java b/src/main/java/org/asamk/signal/commands/ListIdentitiesCommand.java index 2029d6b1..9f476599 100644 --- a/src/main/java/org/asamk/signal/commands/ListIdentitiesCommand.java +++ b/src/main/java/org/asamk/signal/commands/ListIdentitiesCommand.java @@ -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"); diff --git a/src/main/java/org/asamk/signal/commands/QuitGroupCommand.java b/src/main/java/org/asamk/signal/commands/QuitGroupCommand.java index 0a53c638..3414d304 100644 --- a/src/main/java/org/asamk/signal/commands/QuitGroupCommand.java +++ b/src/main/java/org/asamk/signal/commands/QuitGroupCommand.java @@ -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 { diff --git a/src/main/java/org/asamk/signal/commands/ReceiveCommand.java b/src/main/java/org/asamk/signal/commands/ReceiveCommand.java index 5cae9e2e..301694e9 100644 --- a/src/main/java/org/asamk/signal/commands/ReceiveCommand.java +++ b/src/main/java/org/asamk/signal/commands/ReceiveCommand.java @@ -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 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, diff --git a/src/main/java/org/asamk/signal/commands/RegisterCommand.java b/src/main/java/org/asamk/signal/commands/RegisterCommand.java index 1b7e5ef9..cd23c8ab 100644 --- a/src/main/java/org/asamk/signal/commands/RegisterCommand.java +++ b/src/main/java/org/asamk/signal/commands/RegisterCommand.java @@ -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.") diff --git a/src/main/java/org/asamk/signal/commands/RemoteDeleteCommand.java b/src/main/java/org/asamk/signal/commands/RemoteDeleteCommand.java index 8efd581b..0ab68a90 100644 --- a/src/main/java/org/asamk/signal/commands/RemoteDeleteCommand.java +++ b/src/main/java/org/asamk/signal/commands/RemoteDeleteCommand.java @@ -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) { diff --git a/src/main/java/org/asamk/signal/commands/RemoveDeviceCommand.java b/src/main/java/org/asamk/signal/commands/RemoveDeviceCommand.java index 4de93c45..a4d4ffea 100644 --- a/src/main/java/org/asamk/signal/commands/RemoveDeviceCommand.java +++ b/src/main/java/org/asamk/signal/commands/RemoveDeviceCommand.java @@ -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) diff --git a/src/main/java/org/asamk/signal/commands/RemovePinCommand.java b/src/main/java/org/asamk/signal/commands/RemovePinCommand.java index ebf3cf07..b729a9b9 100644 --- a/src/main/java/org/asamk/signal/commands/RemovePinCommand.java +++ b/src/main/java/org/asamk/signal/commands/RemovePinCommand.java @@ -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."); } diff --git a/src/main/java/org/asamk/signal/commands/SendCommand.java b/src/main/java/org/asamk/signal/commands/SendCommand.java index 90aaa09a..af512def 100644 --- a/src/main/java/org/asamk/signal/commands/SendCommand.java +++ b/src/main/java/org/asamk/signal/commands/SendCommand.java @@ -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; diff --git a/src/main/java/org/asamk/signal/commands/SendContactsCommand.java b/src/main/java/org/asamk/signal/commands/SendContactsCommand.java index 176f1bb9..6abf9c6f 100644 --- a/src/main/java/org/asamk/signal/commands/SendContactsCommand.java +++ b/src/main/java/org/asamk/signal/commands/SendContactsCommand.java @@ -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."); } diff --git a/src/main/java/org/asamk/signal/commands/SendReactionCommand.java b/src/main/java/org/asamk/signal/commands/SendReactionCommand.java index 44286acb..8ed9ac63 100644 --- a/src/main/java/org/asamk/signal/commands/SendReactionCommand.java +++ b/src/main/java/org/asamk/signal/commands/SendReactionCommand.java @@ -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) { diff --git a/src/main/java/org/asamk/signal/commands/SendSyncRequestCommand.java b/src/main/java/org/asamk/signal/commands/SendSyncRequestCommand.java index db021a4c..9ced5189 100644 --- a/src/main/java/org/asamk/signal/commands/SendSyncRequestCommand.java +++ b/src/main/java/org/asamk/signal/commands/SendSyncRequestCommand.java @@ -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, ...)."); } diff --git a/src/main/java/org/asamk/signal/commands/SendTypingCommand.java b/src/main/java/org/asamk/signal/commands/SendTypingCommand.java index 80637dfb..cbf34a6d 100644 --- a/src/main/java/org/asamk/signal/commands/SendTypingCommand.java +++ b/src/main/java/org/asamk/signal/commands/SendTypingCommand.java @@ -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."); diff --git a/src/main/java/org/asamk/signal/commands/SetPinCommand.java b/src/main/java/org/asamk/signal/commands/SetPinCommand.java index e0af992b..6958b16a 100644 --- a/src/main/java/org/asamk/signal/commands/SetPinCommand.java +++ b/src/main/java/org/asamk/signal/commands/SetPinCommand.java @@ -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 index 00000000..3540afb7 --- /dev/null +++ b/src/main/java/org/asamk/signal/commands/SubparserAttacher.java @@ -0,0 +1,8 @@ +package org.asamk.signal.commands; + +import net.sourceforge.argparse4j.inf.Subparser; + +public interface SubparserAttacher { + + void attachToSubparser(final Subparser subparser); +} diff --git a/src/main/java/org/asamk/signal/commands/TrustCommand.java b/src/main/java/org/asamk/signal/commands/TrustCommand.java index 7f303dbb..eb99386b 100644 --- a/src/main/java/org/asamk/signal/commands/TrustCommand.java +++ b/src/main/java/org/asamk/signal/commands/TrustCommand.java @@ -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(); diff --git a/src/main/java/org/asamk/signal/commands/UnblockCommand.java b/src/main/java/org/asamk/signal/commands/UnblockCommand.java index 824f1fcf..412a904f 100644 --- a/src/main/java/org/asamk/signal/commands/UnblockCommand.java +++ b/src/main/java/org/asamk/signal/commands/UnblockCommand.java @@ -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("*"); diff --git a/src/main/java/org/asamk/signal/commands/UnregisterCommand.java b/src/main/java/org/asamk/signal/commands/UnregisterCommand.java index d6d27e28..c8c754ac 100644 --- a/src/main/java/org/asamk/signal/commands/UnregisterCommand.java +++ b/src/main/java/org/asamk/signal/commands/UnregisterCommand.java @@ -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!") diff --git a/src/main/java/org/asamk/signal/commands/UpdateAccountCommand.java b/src/main/java/org/asamk/signal/commands/UpdateAccountCommand.java index 13723f09..ff5aa27e 100644 --- a/src/main/java/org/asamk/signal/commands/UpdateAccountCommand.java +++ b/src/main/java/org/asamk/signal/commands/UpdateAccountCommand.java @@ -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."); } diff --git a/src/main/java/org/asamk/signal/commands/UpdateContactCommand.java b/src/main/java/org/asamk/signal/commands/UpdateContactCommand.java index c8f4adde..931b2a61 100644 --- a/src/main/java/org/asamk/signal/commands/UpdateContactCommand.java +++ b/src/main/java/org/asamk/signal/commands/UpdateContactCommand.java @@ -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"); diff --git a/src/main/java/org/asamk/signal/commands/UpdateGroupCommand.java b/src/main/java/org/asamk/signal/commands/UpdateGroupCommand.java index 931ad763..b392df05 100644 --- a/src/main/java/org/asamk/signal/commands/UpdateGroupCommand.java +++ b/src/main/java/org/asamk/signal/commands/UpdateGroupCommand.java @@ -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 { diff --git a/src/main/java/org/asamk/signal/commands/UpdateProfileCommand.java b/src/main/java/org/asamk/signal/commands/UpdateProfileCommand.java index d8b9c6c7..894b19df 100644 --- a/src/main/java/org/asamk/signal/commands/UpdateProfileCommand.java +++ b/src/main/java/org/asamk/signal/commands/UpdateProfileCommand.java @@ -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)"); diff --git a/src/main/java/org/asamk/signal/commands/UploadStickerPackCommand.java b/src/main/java/org/asamk/signal/commands/UploadStickerPackCommand.java index 095c7d96..e2ba2ff9 100644 --- a/src/main/java/org/asamk/signal/commands/UploadStickerPackCommand.java +++ b/src/main/java/org/asamk/signal/commands/UploadStickerPackCommand.java @@ -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 { diff --git a/src/main/java/org/asamk/signal/commands/VerifyCommand.java b/src/main/java/org/asamk/signal/commands/VerifyCommand.java index b580be2a..f32139bd 100644 --- a/src/main/java/org/asamk/signal/commands/VerifyCommand.java +++ b/src/main/java/org/asamk/signal/commands/VerifyCommand.java @@ -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)");