Refactor command creation

This commit is contained in:
AsamK 2021-08-20 18:42:38 +02:00
parent 47143a90e1
commit af292d8f0e
45 changed files with 436 additions and 282 deletions

View file

@ -96,7 +96,7 @@ public class App {
: new PlainTextWriterImpl(System.out);
var commandKey = ns.getString("command");
var command = Commands.getCommand(commandKey, outputWriter);
var command = Commands.getCommand(commandKey);
if (command == null) {
throw new UserErrorException("Command not implemented!");
}
@ -111,7 +111,7 @@ public class App {
final var useDbusSystem = ns.getBoolean("dbus-system");
if (useDbus || useDbusSystem) {
// If username is null, it will connect to the default object path
initDbusClient(command, username, useDbusSystem);
initDbusClient(command, username, useDbusSystem, outputWriter);
return;
}
@ -142,7 +142,7 @@ public class App {
throw new UserErrorException("You cannot specify a username (phone number) when linking");
}
handleProvisioningCommand((ProvisioningCommand) command, dataPath, serviceEnvironment);
handleProvisioningCommand((ProvisioningCommand) command, dataPath, serviceEnvironment, outputWriter);
return;
}
@ -150,7 +150,11 @@ public class App {
var usernames = Manager.getAllLocalUsernames(dataPath);
if (command instanceof MultiLocalCommand) {
handleMultiLocalCommand((MultiLocalCommand) command, dataPath, serviceEnvironment, usernames);
handleMultiLocalCommand((MultiLocalCommand) command,
dataPath,
serviceEnvironment,
usernames,
outputWriter);
return;
}
@ -175,14 +179,17 @@ public class App {
throw new UserErrorException("Command only works via dbus");
}
handleLocalCommand((LocalCommand) command, username, dataPath, serviceEnvironment);
handleLocalCommand((LocalCommand) command, username, dataPath, serviceEnvironment, outputWriter);
}
private void handleProvisioningCommand(
final ProvisioningCommand command, final File dataPath, final ServiceEnvironment serviceEnvironment
final ProvisioningCommand command,
final File dataPath,
final ServiceEnvironment serviceEnvironment,
final OutputWriter outputWriter
) throws CommandException {
var pm = ProvisioningManager.init(dataPath, serviceEnvironment, BaseConfig.USER_AGENT);
command.handleCommand(ns, pm);
command.handleCommand(ns, pm, outputWriter);
}
private void handleRegistrationCommand(
@ -212,10 +219,11 @@ public class App {
final LocalCommand command,
final String username,
final File dataPath,
final ServiceEnvironment serviceEnvironment
final ServiceEnvironment serviceEnvironment,
final OutputWriter outputWriter
) throws CommandException {
try (var m = loadManager(username, dataPath, serviceEnvironment)) {
command.handleCommand(ns, m);
command.handleCommand(ns, m, outputWriter);
} catch (IOException e) {
logger.warn("Cleanup failed", e);
}
@ -225,7 +233,8 @@ public class App {
final MultiLocalCommand command,
final File dataPath,
final ServiceEnvironment serviceEnvironment,
final List<String> usernames
final List<String> usernames,
final OutputWriter outputWriter
) throws CommandException {
final var managers = new ArrayList<Manager>();
for (String u : usernames) {
@ -246,7 +255,7 @@ public class App {
public RegistrationManager getNewRegistrationManager(String username) throws IOException {
return RegistrationManager.init(username, dataPath, serviceEnvironment, BaseConfig.USER_AGENT);
}
});
}, outputWriter);
for (var m : managers) {
try {
@ -286,7 +295,7 @@ public class App {
}
private void initDbusClient(
final Command command, final String username, final boolean systemBus
final Command command, final String username, final boolean systemBus, final OutputWriter outputWriter
) throws CommandException {
try {
DBusConnection.DBusBusType busType;
@ -300,7 +309,7 @@ public class App {
DbusConfig.getObjectPath(username),
Signal.class);
handleCommand(command, ts, dBusConn);
handleCommand(command, ts, dBusConn, outputWriter);
}
} catch (DBusException | IOException e) {
logger.error("Dbus client failed", e);
@ -308,11 +317,13 @@ public class App {
}
}
private void handleCommand(Command command, Signal ts, DBusConnection dBusConn) throws CommandException {
private void handleCommand(
Command command, Signal ts, DBusConnection dBusConn, OutputWriter outputWriter
) throws CommandException {
if (command instanceof ExtendedDbusCommand) {
((ExtendedDbusCommand) command).handleCommand(ns, ts, dBusConn);
((ExtendedDbusCommand) command).handleCommand(ns, ts, dBusConn, outputWriter);
} else if (command instanceof DbusCommand) {
((DbusCommand) command).handleCommand(ns, ts);
((DbusCommand) command).handleCommand(ns, ts, outputWriter);
} else {
throw new UserErrorException("Command is not yet implemented via dbus");
}

View file

@ -21,18 +21,23 @@ public class AddDeviceCommand implements JsonRpcLocalCommand {
private final static Logger logger = LoggerFactory.getLogger(AddDeviceCommand.class);
public static void attachToSubparser(final Subparser subparser) {
@Override
public String getName() {
return "addDevice";
}
@Override
public 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 {
public void handleCommand(
final Namespace ns, final Manager m, final OutputWriter outputWriter
) throws CommandException {
try {
m.addDeviceLink(new URI(ns.getString("uri")));
} catch (IOException e) {

View file

@ -19,17 +19,22 @@ public class BlockCommand implements JsonRpcLocalCommand {
private final static Logger logger = LoggerFactory.getLogger(BlockCommand.class);
public static void attachToSubparser(final Subparser subparser) {
@Override
public String getName() {
return "block";
}
@Override
public 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-id", "--group").help("Group ID").nargs("*");
}
public BlockCommand(final OutputWriter outputWriter) {
}
@Override
public void handleCommand(final Namespace ns, final Manager m) throws CommandException {
public void handleCommand(
final Namespace ns, final Manager m, final OutputWriter outputWriter
) throws CommandException {
for (var contactNumber : ns.<String>getList("contact")) {
try {
m.setContactBlocked(contactNumber, true);

View file

@ -0,0 +1,8 @@
package org.asamk.signal.commands;
import net.sourceforge.argparse4j.inf.Subparser;
public interface CliCommand extends Command {
void attachToSubparser(Subparser subparser);
}

View file

@ -2,11 +2,13 @@ package org.asamk.signal.commands;
import org.asamk.signal.OutputType;
import java.util.Set;
import java.util.List;
public interface Command {
default Set<OutputType> getSupportedOutputTypes() {
return Set.of(OutputType.PLAIN_TEXT);
String getName();
default List<OutputType> getSupportedOutputTypes() {
return List.of(OutputType.PLAIN_TEXT);
}
}

View file

@ -1,74 +1,65 @@
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, CommandConstructor> commands = new HashMap<>();
private static final Map<String, Command> commands = new HashMap<>();
private static final Map<String, SubparserAttacher> commandSubparserAttacher = new TreeMap<>();
static {
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("jsonRpc", JsonRpcDispatcherCommand::new, JsonRpcDispatcherCommand::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);
addCommand("version", VersionCommand::new, null);
addCommand(new AddDeviceCommand());
addCommand(new BlockCommand());
addCommand(new DaemonCommand());
addCommand(new GetUserStatusCommand());
addCommand(new JoinGroupCommand());
addCommand(new JsonRpcDispatcherCommand());
addCommand(new LinkCommand());
addCommand(new ListContactsCommand());
addCommand(new ListDevicesCommand());
addCommand(new ListGroupsCommand());
addCommand(new ListIdentitiesCommand());
addCommand(new QuitGroupCommand());
addCommand(new ReceiveCommand());
addCommand(new RegisterCommand());
addCommand(new RemoveDeviceCommand());
addCommand(new RemoteDeleteCommand());
addCommand(new RemovePinCommand());
addCommand(new SendCommand());
addCommand(new SendContactsCommand());
addCommand(new SendReactionCommand());
addCommand(new SendSyncRequestCommand());
addCommand(new SendTypingCommand());
addCommand(new SetPinCommand());
addCommand(new TrustCommand());
addCommand(new UnblockCommand());
addCommand(new UnregisterCommand());
addCommand(new UpdateAccountCommand());
addCommand(new UpdateContactCommand());
addCommand(new UpdateGroupCommand());
addCommand(new UpdateProfileCommand());
addCommand(new UploadStickerPackCommand());
addCommand(new VerifyCommand());
addCommand(new VersionCommand());
}
public static Map<String, SubparserAttacher> getCommandSubparserAttachers() {
return commandSubparserAttacher;
}
public static Command getCommand(String commandKey, OutputWriter outputWriter) {
public static Command getCommand(String commandKey) {
if (!commands.containsKey(commandKey)) {
return null;
}
return commands.get(commandKey).constructCommand(outputWriter);
return commands.get(commandKey);
}
private static void addCommand(
String name, CommandConstructor commandConstructor, SubparserAttacher subparserAttacher
) {
commands.put(name, commandConstructor);
if (subparserAttacher != null) {
commandSubparserAttacher.put(name, subparserAttacher);
private static void addCommand(Command command) {
commands.put(command.getName(), command);
if (command instanceof CliCommand) {
commandSubparserAttacher.put(command.getName(), ((CliCommand) command)::attachToSubparser);
}
}
private interface CommandConstructor {
Command constructCommand(OutputWriter outputWriter);
}
}

View file

@ -23,15 +23,19 @@ import org.slf4j.LoggerFactory;
import java.io.IOException;
import java.util.List;
import java.util.Set;
import java.util.concurrent.TimeUnit;
public class DaemonCommand implements MultiLocalCommand {
private final static Logger logger = LoggerFactory.getLogger(DaemonCommand.class);
private final OutputWriter outputWriter;
public static void attachToSubparser(final Subparser subparser) {
@Override
public String getName() {
return "daemon";
}
@Override
public void attachToSubparser(final Subparser subparser) {
subparser.help("Run in daemon mode and provide an experimental dbus interface.");
subparser.addArgument("--system")
.action(Arguments.storeTrue())
@ -41,17 +45,15 @@ public class DaemonCommand implements MultiLocalCommand {
.action(Arguments.storeTrue());
}
public DaemonCommand(final OutputWriter outputWriter) {
this.outputWriter = outputWriter;
@Override
public List<OutputType> getSupportedOutputTypes() {
return List.of(OutputType.PLAIN_TEXT, OutputType.JSON);
}
@Override
public Set<OutputType> getSupportedOutputTypes() {
return Set.of(OutputType.PLAIN_TEXT, OutputType.JSON);
}
@Override
public void handleCommand(final Namespace ns, final Manager m) throws CommandException {
public void handleCommand(
final Namespace ns, final Manager m, final OutputWriter outputWriter
) throws CommandException {
boolean ignoreAttachments = ns.getBoolean("ignore-attachments");
DBusConnection.DBusBusType busType;
@ -63,7 +65,7 @@ public class DaemonCommand implements MultiLocalCommand {
try (var conn = DBusConnection.getConnection(busType)) {
var objectPath = DbusConfig.getObjectPath();
var t = run(conn, objectPath, m, ignoreAttachments);
var t = run(conn, objectPath, m, outputWriter, ignoreAttachments);
conn.requestBusName(DbusConfig.getBusname());
@ -79,7 +81,7 @@ public class DaemonCommand implements MultiLocalCommand {
@Override
public void handleCommand(
final Namespace ns, final List<Manager> managers, SignalCreator c
final Namespace ns, final List<Manager> managers, final SignalCreator c, final OutputWriter outputWriter
) throws CommandException {
boolean ignoreAttachments = ns.getBoolean("ignore-attachments");
@ -94,7 +96,7 @@ public class DaemonCommand implements MultiLocalCommand {
final var signalControl = new DbusSignalControlImpl(c, m -> {
try {
final var objectPath = DbusConfig.getObjectPath(m.getUsername());
return run(conn, objectPath, m, ignoreAttachments);
return run(conn, objectPath, m, outputWriter, ignoreAttachments);
} catch (DBusException e) {
logger.error("Failed to export object", e);
return null;
@ -116,7 +118,7 @@ public class DaemonCommand implements MultiLocalCommand {
}
private Thread run(
DBusConnection conn, String objectPath, Manager m, boolean ignoreAttachments
DBusConnection conn, String objectPath, Manager m, OutputWriter outputWriter, boolean ignoreAttachments
) throws DBusException {
conn.exportObject(new DbusSignalImpl(m, objectPath));

View file

@ -3,15 +3,18 @@ package org.asamk.signal.commands;
import net.sourceforge.argparse4j.inf.Namespace;
import org.asamk.Signal;
import org.asamk.signal.OutputWriter;
import org.asamk.signal.commands.exceptions.CommandException;
import org.asamk.signal.dbus.DbusSignalImpl;
import org.asamk.signal.manager.Manager;
public interface DbusCommand extends LocalCommand {
void handleCommand(Namespace ns, Signal signal) throws CommandException;
void handleCommand(Namespace ns, Signal signal, OutputWriter outputWriter) throws CommandException;
default void handleCommand(final Namespace ns, final Manager m) throws CommandException {
handleCommand(ns, new DbusSignalImpl(m, null));
default void handleCommand(
final Namespace ns, final Manager m, final OutputWriter outputWriter
) throws CommandException {
handleCommand(ns, new DbusSignalImpl(m, null), outputWriter);
}
}

View file

@ -3,10 +3,13 @@ package org.asamk.signal.commands;
import net.sourceforge.argparse4j.inf.Namespace;
import org.asamk.Signal;
import org.asamk.signal.OutputWriter;
import org.asamk.signal.commands.exceptions.CommandException;
import org.freedesktop.dbus.connections.impl.DBusConnection;
public interface ExtendedDbusCommand extends Command {
public interface ExtendedDbusCommand extends CliCommand {
void handleCommand(Namespace ns, Signal signal, DBusConnection dbusconnection) throws CommandException;
void handleCommand(
Namespace ns, Signal signal, DBusConnection dbusconnection, final OutputWriter outputWriter
) throws CommandException;
}

View file

@ -20,19 +20,22 @@ import java.util.stream.Collectors;
public class GetUserStatusCommand implements JsonRpcLocalCommand {
private final static Logger logger = LoggerFactory.getLogger(GetUserStatusCommand.class);
private final OutputWriter outputWriter;
public static void attachToSubparser(final Subparser subparser) {
@Override
public String getName() {
return "getUserStatus";
}
@Override
public 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 void handleCommand(final Namespace ns, final Manager m) throws CommandException {
public void handleCommand(
final Namespace ns, final Manager m, final OutputWriter outputWriter
) throws CommandException {
// Get a map of registration statuses
Map<String, Boolean> registered;
try {

View file

@ -23,19 +23,21 @@ import static org.asamk.signal.util.ErrorUtils.handleSendMessageResults;
public class JoinGroupCommand implements JsonRpcLocalCommand {
private final OutputWriter outputWriter;
public JoinGroupCommand(final OutputWriter outputWriter) {
this.outputWriter = outputWriter;
@Override
public String getName() {
return "joinGroup";
}
public static void attachToSubparser(final Subparser subparser) {
@Override
public 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.");
}
@Override
public void handleCommand(final Namespace ns, final Manager m) throws CommandException {
public void handleCommand(
final Namespace ns, final Manager m, final OutputWriter outputWriter
) throws CommandException {
final GroupInviteLinkUrl linkUrl;
var uri = ns.getString("uri");
try {

View file

@ -3,10 +3,11 @@ package org.asamk.signal.commands;
import com.fasterxml.jackson.core.type.TypeReference;
import org.asamk.signal.OutputType;
import org.asamk.signal.OutputWriter;
import org.asamk.signal.commands.exceptions.CommandException;
import org.asamk.signal.manager.Manager;
import java.util.Set;
import java.util.List;
public interface JsonRpcCommand<T> extends Command {
@ -14,9 +15,9 @@ public interface JsonRpcCommand<T> extends Command {
return null;
}
void handleCommand(T request, Manager m) throws CommandException;
void handleCommand(T request, Manager m, OutputWriter outputWriter) throws CommandException;
default Set<OutputType> getSupportedOutputTypes() {
return Set.of(OutputType.JSON);
default List<OutputType> getSupportedOutputTypes() {
return List.of(OutputType.JSON);
}
}

View file

@ -31,8 +31,8 @@ import org.slf4j.LoggerFactory;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;
public class JsonRpcDispatcherCommand implements LocalCommand {
@ -43,26 +43,28 @@ public class JsonRpcDispatcherCommand implements LocalCommand {
private static final int IO_ERROR = -3;
private static final int UNTRUSTED_KEY_ERROR = -4;
private final OutputWriter outputWriter;
@Override
public String getName() {
return "jsonRpc";
}
public static void attachToSubparser(final Subparser subparser) {
@Override
public void attachToSubparser(final Subparser subparser) {
subparser.help("Take commands from standard input as line-delimited JSON RPC while receiving messages.");
subparser.addArgument("--ignore-attachments")
.help("Dont download attachments of received messages.")
.action(Arguments.storeTrue());
}
public JsonRpcDispatcherCommand(final OutputWriter outputWriter) {
this.outputWriter = outputWriter;
@Override
public List<OutputType> getSupportedOutputTypes() {
return List.of(OutputType.JSON);
}
@Override
public Set<OutputType> getSupportedOutputTypes() {
return Set.of(OutputType.JSON);
}
@Override
public void handleCommand(final Namespace ns, final Manager m) throws CommandException {
public void handleCommand(
final Namespace ns, final Manager m, final OutputWriter outputWriter
) throws CommandException {
final boolean ignoreAttachments = ns.getBoolean("ignore-attachments");
final var objectMapper = Util.createJsonObjectMapper();
@ -104,7 +106,7 @@ public class JsonRpcDispatcherCommand implements LocalCommand {
result[0] = s;
};
var command = Commands.getCommand(method, commandOutputWriter);
var command = Commands.getCommand(method);
if (!(command instanceof JsonRpcCommand)) {
throw new JsonRpcException(new JsonRpcResponse.Error(JsonRpcResponse.Error.METHOD_NOT_FOUND,
"Method not implemented",
@ -112,7 +114,7 @@ public class JsonRpcDispatcherCommand implements LocalCommand {
}
try {
parseParamsAndRunCommand(m, objectMapper, params, (JsonRpcCommand<?>) command);
parseParamsAndRunCommand(m, objectMapper, params, commandOutputWriter, (JsonRpcCommand<?>) command);
} catch (JsonMappingException e) {
throw new JsonRpcException(new JsonRpcResponse.Error(JsonRpcResponse.Error.INVALID_REQUEST,
e.getMessage(),
@ -135,7 +137,11 @@ public class JsonRpcDispatcherCommand implements LocalCommand {
}
private <T> void parseParamsAndRunCommand(
final Manager m, final ObjectMapper objectMapper, final TreeNode params, final JsonRpcCommand<T> command
final Manager m,
final ObjectMapper objectMapper,
final TreeNode params,
final OutputWriter outputWriter,
final JsonRpcCommand<T> command
) throws CommandException, JsonMappingException {
T requestParams = null;
final var requestType = command.getRequestType();
@ -148,7 +154,7 @@ public class JsonRpcDispatcherCommand implements LocalCommand {
throw new AssertionError(e);
}
}
command.handleCommand(requestParams, m);
command.handleCommand(requestParams, m, outputWriter);
}
private Thread receiveMessages(

View file

@ -5,13 +5,13 @@ import com.fasterxml.jackson.core.type.TypeReference;
import net.sourceforge.argparse4j.inf.Namespace;
import org.asamk.signal.OutputType;
import org.asamk.signal.OutputWriter;
import org.asamk.signal.commands.exceptions.CommandException;
import org.asamk.signal.manager.Manager;
import org.asamk.signal.util.Util;
import java.util.List;
import java.util.Map;
import java.util.Set;
public interface JsonRpcLocalCommand extends JsonRpcCommand<Map<String, Object>>, LocalCommand {
@ -20,13 +20,15 @@ public interface JsonRpcLocalCommand extends JsonRpcCommand<Map<String, Object>>
};
}
default void handleCommand(Map<String, Object> request, Manager m) throws CommandException {
default void handleCommand(
Map<String, Object> request, Manager m, OutputWriter outputWriter
) throws CommandException {
Namespace commandNamespace = new JsonRpcNamespace(request == null ? Map.of() : request);
handleCommand(commandNamespace, m);
handleCommand(commandNamespace, m, outputWriter);
}
default Set<OutputType> getSupportedOutputTypes() {
return Set.of(OutputType.PLAIN_TEXT, OutputType.JSON);
default List<OutputType> getSupportedOutputTypes() {
return List.of(OutputType.PLAIN_TEXT, OutputType.JSON);
}
/**

View file

@ -19,19 +19,22 @@ import java.util.concurrent.TimeoutException;
public class LinkCommand implements ProvisioningCommand {
private final static Logger logger = LoggerFactory.getLogger(LinkCommand.class);
private final OutputWriter outputWriter;
public LinkCommand(final OutputWriter outputWriter) {
this.outputWriter = outputWriter;
@Override
public String getName() {
return "link";
}
public static void attachToSubparser(final Subparser subparser) {
@Override
public 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 {
public void handleCommand(
final Namespace ns, final ProvisioningManager m, final OutputWriter outputWriter
) throws CommandException {
final var writer = (PlainTextWriter) outputWriter;
var deviceName = ns.getString("name");

View file

@ -11,18 +11,18 @@ import static org.asamk.signal.util.Util.getLegacyIdentifier;
public class ListContactsCommand implements LocalCommand {
private final OutputWriter outputWriter;
public ListContactsCommand(final OutputWriter outputWriter) {
this.outputWriter = outputWriter;
@Override
public String getName() {
return "listContacts";
}
public static void attachToSubparser(final Subparser subparser) {
@Override
public 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) {
public void handleCommand(final Namespace ns, final Manager m, final OutputWriter outputWriter) {
final var writer = (PlainTextWriter) outputWriter;
var contacts = m.getContacts();

View file

@ -19,18 +19,21 @@ import java.util.List;
public class ListDevicesCommand implements LocalCommand {
private final static Logger logger = LoggerFactory.getLogger(ListDevicesCommand.class);
private final OutputWriter outputWriter;
public ListDevicesCommand(final OutputWriter outputWriter) {
this.outputWriter = outputWriter;
@Override
public String getName() {
return "listDevices";
}
public static void attachToSubparser(final Subparser subparser) {
@Override
public 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 {
public void handleCommand(
final Namespace ns, final Manager m, final OutputWriter outputWriter
) throws CommandException {
final var writer = (PlainTextWriter) outputWriter;
List<Device> devices;

View file

@ -22,7 +22,13 @@ public class ListGroupsCommand implements JsonRpcLocalCommand {
private final static Logger logger = LoggerFactory.getLogger(ListGroupsCommand.class);
public static void attachToSubparser(final Subparser subparser) {
@Override
public String getName() {
return "listGroups";
}
@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())
@ -63,14 +69,10 @@ public class ListGroupsCommand implements JsonRpcLocalCommand {
}
}
private final OutputWriter outputWriter;
public ListGroupsCommand(final OutputWriter outputWriter) {
this.outputWriter = outputWriter;
}
@Override
public void handleCommand(final Namespace ns, final Manager m) throws CommandException {
public void handleCommand(
final Namespace ns, final Manager m, final OutputWriter outputWriter
) throws CommandException {
final var groups = m.getGroups();
if (outputWriter instanceof JsonWriter) {

View file

@ -21,10 +21,10 @@ 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;
@Override
public String getName() {
return "listIdentities";
}
private static void printIdentityFingerprint(PlainTextWriter writer, Manager m, IdentityInfo theirId) {
@ -38,13 +38,16 @@ public class ListIdentitiesCommand implements LocalCommand {
digits);
}
public static void attachToSubparser(final Subparser subparser) {
@Override
public 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 {
public void handleCommand(
final Namespace ns, final Manager m, final OutputWriter outputWriter
) throws CommandException {
final var writer = (PlainTextWriter) outputWriter;
var number = ns.getString("number");

View file

@ -2,10 +2,11 @@ package org.asamk.signal.commands;
import net.sourceforge.argparse4j.inf.Namespace;
import org.asamk.signal.OutputWriter;
import org.asamk.signal.commands.exceptions.CommandException;
import org.asamk.signal.manager.Manager;
public interface LocalCommand extends Command {
public interface LocalCommand extends CliCommand {
void handleCommand(Namespace ns, Manager m) throws CommandException;
void handleCommand(Namespace ns, Manager m, OutputWriter outputWriter) throws CommandException;
}

View file

@ -2,6 +2,7 @@ package org.asamk.signal.commands;
import net.sourceforge.argparse4j.inf.Namespace;
import org.asamk.signal.OutputWriter;
import org.asamk.signal.commands.exceptions.CommandException;
import org.asamk.signal.manager.Manager;
@ -9,10 +10,14 @@ import java.util.List;
public interface MultiLocalCommand extends LocalCommand {
void handleCommand(Namespace ns, List<Manager> m, final SignalCreator c) throws CommandException;
void handleCommand(
Namespace ns, List<Manager> m, SignalCreator c, OutputWriter outputWriter
) throws CommandException;
@Override
default void handleCommand(final Namespace ns, final Manager m) throws CommandException {
handleCommand(ns, List.of(m), null);
default void handleCommand(
final Namespace ns, final Manager m, final OutputWriter outputWriter
) throws CommandException {
handleCommand(ns, List.of(m), null, outputWriter);
}
}

View file

@ -2,10 +2,11 @@ package org.asamk.signal.commands;
import net.sourceforge.argparse4j.inf.Namespace;
import org.asamk.signal.OutputWriter;
import org.asamk.signal.commands.exceptions.CommandException;
import org.asamk.signal.manager.ProvisioningManager;
public interface ProvisioningCommand extends Command {
public interface ProvisioningCommand extends CliCommand {
void handleCommand(Namespace ns, ProvisioningManager m) throws CommandException;
void handleCommand(Namespace ns, ProvisioningManager m, final OutputWriter outputWriter) throws CommandException;
}

View file

@ -31,13 +31,14 @@ import static org.asamk.signal.util.ErrorUtils.handleSendMessageResults;
public class QuitGroupCommand implements JsonRpcLocalCommand {
private final static Logger logger = LoggerFactory.getLogger(QuitGroupCommand.class);
private final OutputWriter outputWriter;
public QuitGroupCommand(final OutputWriter outputWriter) {
this.outputWriter = outputWriter;
@Override
public String getName() {
return "quitGroup";
}
public static void attachToSubparser(final Subparser subparser) {
@Override
public 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-id", "--group").required(true).help("Specify the recipient group ID.");
subparser.addArgument("--delete")
@ -49,7 +50,9 @@ public class QuitGroupCommand implements JsonRpcLocalCommand {
}
@Override
public void handleCommand(final Namespace ns, final Manager m) throws CommandException {
public void handleCommand(
final Namespace ns, final Manager m, final OutputWriter outputWriter
) throws CommandException {
final GroupId groupId;
try {
groupId = Util.decodeGroupId(ns.getString("group-id"));
@ -64,7 +67,7 @@ public class QuitGroupCommand implements JsonRpcLocalCommand {
final var results = m.sendQuitGroupMessage(groupId,
groupAdmins == null ? Set.of() : new HashSet<>(groupAdmins));
final var timestamp = results.first();
outputResult(timestamp);
outputResult(outputWriter, timestamp);
handleSendMessageResults(results.second());
} catch (NotAGroupMemberException e) {
logger.info("User is not a group member");
@ -84,7 +87,7 @@ public class QuitGroupCommand implements JsonRpcLocalCommand {
}
}
private void outputResult(final long timestamp) {
private void outputResult(final OutputWriter outputWriter, final long timestamp) {
if (outputWriter instanceof PlainTextWriter) {
final var writer = (PlainTextWriter) outputWriter;
writer.println("{}", timestamp);

View file

@ -24,16 +24,21 @@ import org.slf4j.LoggerFactory;
import java.io.IOException;
import java.util.Base64;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;
public class ReceiveCommand implements ExtendedDbusCommand, LocalCommand {
private final static Logger logger = LoggerFactory.getLogger(ReceiveCommand.class);
private final OutputWriter outputWriter;
public static void attachToSubparser(final Subparser subparser) {
@Override
public String getName() {
return "receive";
}
@Override
public void attachToSubparser(final Subparser subparser) {
subparser.help("Query the server for new messages.");
subparser.addArgument("-t", "--timeout")
.type(double.class)
@ -44,17 +49,13 @@ 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);
public List<OutputType> getSupportedOutputTypes() {
return List.of(OutputType.PLAIN_TEXT, OutputType.JSON);
}
public void handleCommand(
final Namespace ns, final Signal signal, DBusConnection dbusconnection
final Namespace ns, final Signal signal, DBusConnection dbusconnection, final OutputWriter outputWriter
) throws CommandException {
try {
if (outputWriter instanceof JsonWriter) {
@ -137,7 +138,9 @@ public class ReceiveCommand implements ExtendedDbusCommand, LocalCommand {
}
@Override
public void handleCommand(final Namespace ns, final Manager m) throws CommandException {
public void handleCommand(
final Namespace ns, final Manager m, final OutputWriter outputWriter
) throws CommandException {
double timeout = ns.getDouble("timeout");
var returnOnTimeout = true;
if (timeout < 0) {

View file

@ -4,7 +4,6 @@ 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;
@ -15,10 +14,13 @@ import java.io.IOException;
public class RegisterCommand implements RegistrationCommand {
public RegisterCommand(final OutputWriter outputWriter) {
@Override
public String getName() {
return "register";
}
public static void attachToSubparser(final Subparser subparser) {
@Override
public 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.")

View file

@ -5,7 +5,7 @@ import net.sourceforge.argparse4j.inf.Namespace;
import org.asamk.signal.commands.exceptions.CommandException;
import org.asamk.signal.manager.RegistrationManager;
public interface RegistrationCommand extends Command {
public interface RegistrationCommand extends CliCommand {
void handleCommand(Namespace ns, RegistrationManager m) throws CommandException;
}

View file

@ -22,13 +22,13 @@ import java.util.Map;
public class RemoteDeleteCommand implements DbusCommand, JsonRpcLocalCommand {
private final OutputWriter outputWriter;
public RemoteDeleteCommand(final OutputWriter outputWriter) {
this.outputWriter = outputWriter;
@Override
public String getName() {
return "remoteDelete";
}
public static void attachToSubparser(final Subparser subparser) {
@Override
public void attachToSubparser(final Subparser subparser) {
subparser.help("Remotely delete a previously sent message.");
subparser.addArgument("-t", "--target-timestamp")
.required(true)
@ -39,7 +39,9 @@ public class RemoteDeleteCommand implements DbusCommand, JsonRpcLocalCommand {
}
@Override
public void handleCommand(final Namespace ns, final Signal signal) throws CommandException {
public void handleCommand(
final Namespace ns, final Signal signal, final OutputWriter outputWriter
) throws CommandException {
final List<String> recipients = ns.getList("recipient");
final var groupIdString = ns.getString("group-id");
@ -69,7 +71,7 @@ public class RemoteDeleteCommand implements DbusCommand, JsonRpcLocalCommand {
} else {
timestamp = signal.sendRemoteDeleteMessage(targetTimestamp, recipients);
}
outputResult(timestamp);
outputResult(outputWriter, timestamp);
} catch (UnknownObject e) {
throw new UserErrorException("Failed to find dbus object, maybe missing the -u flag: " + e.getMessage());
} catch (Signal.Error.InvalidNumber e) {
@ -82,11 +84,13 @@ public class RemoteDeleteCommand implements DbusCommand, JsonRpcLocalCommand {
}
@Override
public void handleCommand(final Namespace ns, final Manager m) throws CommandException {
handleCommand(ns, new DbusSignalImpl(m, null));
public void handleCommand(
final Namespace ns, final Manager m, final OutputWriter outputWriter
) throws CommandException {
handleCommand(ns, new DbusSignalImpl(m, null), outputWriter);
}
private void outputResult(final long timestamp) {
private void outputResult(final OutputWriter outputWriter, final long timestamp) {
if (outputWriter instanceof PlainTextWriter) {
final var writer = (PlainTextWriter) outputWriter;
writer.println("{}", timestamp);

View file

@ -12,10 +12,13 @@ import java.io.IOException;
public class RemoveDeviceCommand implements JsonRpcLocalCommand {
public RemoveDeviceCommand(final OutputWriter outputWriter) {
@Override
public String getName() {
return "removeDevice";
}
public static void attachToSubparser(final Subparser subparser) {
@Override
public void attachToSubparser(final Subparser subparser) {
subparser.help("Remove a linked device.");
subparser.addArgument("-d", "--device-id", "--deviceId")
.type(int.class)
@ -24,7 +27,9 @@ public class RemoveDeviceCommand implements JsonRpcLocalCommand {
}
@Override
public void handleCommand(final Namespace ns, final Manager m) throws CommandException {
public void handleCommand(
final Namespace ns, final Manager m, final OutputWriter outputWriter
) throws CommandException {
try {
int deviceId = ns.getInt("device-id");
m.removeLinkedDevices(deviceId);

View file

@ -15,15 +15,20 @@ import java.io.IOException;
public class RemovePinCommand implements JsonRpcLocalCommand {
public RemovePinCommand(final OutputWriter outputWriter) {
@Override
public String getName() {
return "removePin";
}
public static void attachToSubparser(final Subparser subparser) {
@Override
public void attachToSubparser(final Subparser subparser) {
subparser.help("Remove the registration lock pin.");
}
@Override
public void handleCommand(final Namespace ns, final Manager m) throws CommandException {
public void handleCommand(
final Namespace ns, final Manager m, final OutputWriter outputWriter
) throws CommandException {
try {
m.setRegistrationLockPin(Optional.absent());
} catch (UnauthenticatedResponseException e) {

View file

@ -30,13 +30,14 @@ import java.util.Map;
public class SendCommand implements DbusCommand, JsonRpcLocalCommand {
private final static Logger logger = LoggerFactory.getLogger(SendCommand.class);
private final OutputWriter outputWriter;
public SendCommand(final OutputWriter outputWriter) {
this.outputWriter = outputWriter;
@Override
public String getName() {
return "send";
}
public static void attachToSubparser(final Subparser subparser) {
@Override
public 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();
@ -53,7 +54,9 @@ public class SendCommand implements DbusCommand, JsonRpcLocalCommand {
}
@Override
public void handleCommand(final Namespace ns, final Signal signal) throws CommandException {
public void handleCommand(
final Namespace ns, final Signal signal, final OutputWriter outputWriter
) throws CommandException {
final List<String> recipients = ns.getList("recipient");
final var isEndSession = ns.getBoolean("end-session");
final var groupIdString = ns.getString("group-id");
@ -106,7 +109,7 @@ public class SendCommand implements DbusCommand, JsonRpcLocalCommand {
try {
var timestamp = signal.sendGroupMessage(messageText, attachments, groupId);
outputResult(timestamp);
outputResult(outputWriter, timestamp);
return;
} catch (DBusExecutionException e) {
throw new UnexpectedErrorException("Failed to send group message: " + e.getMessage());
@ -116,7 +119,7 @@ public class SendCommand implements DbusCommand, JsonRpcLocalCommand {
if (isNoteToSelf) {
try {
var timestamp = signal.sendNoteToSelfMessage(messageText, attachments);
outputResult(timestamp);
outputResult(outputWriter, timestamp);
return;
} catch (Signal.Error.UntrustedIdentity e) {
throw new UntrustedKeyErrorException("Failed to send message: " + e.getMessage());
@ -127,7 +130,7 @@ public class SendCommand implements DbusCommand, JsonRpcLocalCommand {
try {
var timestamp = signal.sendMessage(messageText, attachments, recipients);
outputResult(timestamp);
outputResult(outputWriter, timestamp);
} catch (UnknownObject e) {
throw new UserErrorException("Failed to find dbus object, maybe missing the -u flag: " + e.getMessage());
} catch (Signal.Error.UntrustedIdentity e) {
@ -137,7 +140,7 @@ public class SendCommand implements DbusCommand, JsonRpcLocalCommand {
}
}
private void outputResult(final long timestamp) {
private void outputResult(final OutputWriter outputWriter, final long timestamp) {
if (outputWriter instanceof PlainTextWriter) {
final var writer = (PlainTextWriter) outputWriter;
writer.println("{}", timestamp);
@ -148,7 +151,9 @@ public class SendCommand implements DbusCommand, JsonRpcLocalCommand {
}
@Override
public void handleCommand(final Namespace ns, final Manager m) throws CommandException {
handleCommand(ns, new DbusSignalImpl(m, null));
public void handleCommand(
final Namespace ns, final Manager m, final OutputWriter outputWriter
) throws CommandException {
handleCommand(ns, new DbusSignalImpl(m, null), outputWriter);
}
}

View file

@ -14,15 +14,20 @@ import java.io.IOException;
public class SendContactsCommand implements JsonRpcLocalCommand {
public SendContactsCommand(final OutputWriter outputWriter) {
@Override
public String getName() {
return "sendContacts";
}
public static void attachToSubparser(final Subparser subparser) {
@Override
public void attachToSubparser(final Subparser subparser) {
subparser.help("Send a synchronization message with the local contacts list to all linked devices.");
}
@Override
public void handleCommand(final Namespace ns, final Manager m) throws CommandException {
public void handleCommand(
final Namespace ns, final Manager m, final OutputWriter outputWriter
) throws CommandException {
try {
m.sendContacts();
} catch (UntrustedIdentityException e) {

View file

@ -23,13 +23,13 @@ import java.util.Map;
public class SendReactionCommand implements DbusCommand, JsonRpcLocalCommand {
private final OutputWriter outputWriter;
public SendReactionCommand(final OutputWriter outputWriter) {
this.outputWriter = outputWriter;
@Override
public String getName() {
return "sendReaction";
}
public static void attachToSubparser(final Subparser subparser) {
@Override
public void attachToSubparser(final Subparser subparser) {
subparser.help("Send reaction to a previously received or sent message.");
subparser.addArgument("-g", "--group-id", "--group").help("Specify the recipient group ID.");
subparser.addArgument("recipient").help("Specify the recipients' phone number.").nargs("*");
@ -47,7 +47,9 @@ public class SendReactionCommand implements DbusCommand, JsonRpcLocalCommand {
}
@Override
public void handleCommand(final Namespace ns, final Signal signal) throws CommandException {
public void handleCommand(
final Namespace ns, final Signal signal, final OutputWriter outputWriter
) throws CommandException {
final List<String> recipients = ns.getList("recipient");
final var groupIdString = ns.getString("group-id");
@ -80,7 +82,7 @@ public class SendReactionCommand implements DbusCommand, JsonRpcLocalCommand {
} else {
timestamp = signal.sendMessageReaction(emoji, isRemove, targetAuthor, targetTimestamp, recipients);
}
outputResult(timestamp);
outputResult(outputWriter, timestamp);
} catch (UnknownObject e) {
throw new UserErrorException("Failed to find dbus object, maybe missing the -u flag: " + e.getMessage());
} catch (Signal.Error.InvalidNumber e) {
@ -93,11 +95,13 @@ public class SendReactionCommand implements DbusCommand, JsonRpcLocalCommand {
}
@Override
public void handleCommand(final Namespace ns, final Manager m) throws CommandException {
handleCommand(ns, new DbusSignalImpl(m, null));
public void handleCommand(
final Namespace ns, final Manager m, final OutputWriter outputWriter
) throws CommandException {
handleCommand(ns, new DbusSignalImpl(m, null), outputWriter);
}
private void outputResult(final long timestamp) {
private void outputResult(final OutputWriter outputWriter, final long timestamp) {
if (outputWriter instanceof PlainTextWriter) {
final var writer = (PlainTextWriter) outputWriter;
writer.println("{}", timestamp);

View file

@ -12,15 +12,20 @@ import java.io.IOException;
public class SendSyncRequestCommand implements JsonRpcLocalCommand {
public SendSyncRequestCommand(final OutputWriter outputWriter) {
@Override
public String getName() {
return "sendSyncRequest";
}
public static void attachToSubparser(final Subparser subparser) {
@Override
public void attachToSubparser(final Subparser subparser) {
subparser.help("Send a synchronization request message to master device (for group, contacts, ...).");
}
@Override
public void handleCommand(final Namespace ns, final Manager m) throws CommandException {
public void handleCommand(
final Namespace ns, final Manager m, final OutputWriter outputWriter
) throws CommandException {
try {
m.requestAllSyncData();
} catch (IOException e) {

View file

@ -22,10 +22,13 @@ import java.util.HashSet;
public class SendTypingCommand implements JsonRpcLocalCommand {
public SendTypingCommand(final OutputWriter outputWriter) {
@Override
public String getName() {
return "sendTyping";
}
public static void attachToSubparser(final Subparser subparser) {
@Override
public 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-id", "--group").help("Specify the recipient group ID.");
@ -34,7 +37,9 @@ public class SendTypingCommand implements JsonRpcLocalCommand {
}
@Override
public void handleCommand(final Namespace ns, final Manager m) throws CommandException {
public void handleCommand(
final Namespace ns, final Manager m, final OutputWriter outputWriter
) throws CommandException {
final var recipients = ns.<String>getList("recipient");
final var groupIdString = ns.getString("group-id");

View file

@ -15,17 +15,22 @@ import java.io.IOException;
public class SetPinCommand implements JsonRpcLocalCommand {
public SetPinCommand(final OutputWriter outputWriter) {
@Override
public String getName() {
return "setPin";
}
public static void attachToSubparser(final Subparser subparser) {
@Override
public void attachToSubparser(final Subparser subparser) {
subparser.help("Set a registration lock pin, to prevent others from registering this number.");
subparser.addArgument("pin")
.help("The registration lock PIN, that will be required for new registrations (resets after 7 days of inactivity)");
}
@Override
public void handleCommand(final Namespace ns, final Manager m) throws CommandException {
public void handleCommand(
final Namespace ns, final Manager m, final OutputWriter outputWriter
) throws CommandException {
try {
var registrationLockPin = ns.getString("pin");
m.setRegistrationLockPin(Optional.of(registrationLockPin));

View file

@ -15,10 +15,13 @@ import java.util.Locale;
public class TrustCommand implements JsonRpcLocalCommand {
public TrustCommand(final OutputWriter outputWriter) {
@Override
public String getName() {
return "trust";
}
public static void attachToSubparser(final Subparser subparser) {
@Override
public 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();
@ -30,7 +33,9 @@ public class TrustCommand implements JsonRpcLocalCommand {
}
@Override
public void handleCommand(final Namespace ns, final Manager m) throws CommandException {
public void handleCommand(
final Namespace ns, final Manager m, final OutputWriter outputWriter
) throws CommandException {
var number = ns.getString("number");
if (ns.getBoolean("trust-all-known-keys")) {
boolean res;

View file

@ -19,17 +19,22 @@ public class UnblockCommand implements JsonRpcLocalCommand {
private final static Logger logger = LoggerFactory.getLogger(UnblockCommand.class);
public UnblockCommand(final OutputWriter outputWriter) {
@Override
public String getName() {
return "unblock";
}
public static void attachToSubparser(final Subparser subparser) {
@Override
public 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-id", "--group").help("Group ID").nargs("*");
}
@Override
public void handleCommand(final Namespace ns, final Manager m) throws CommandException {
public void handleCommand(
final Namespace ns, final Manager m, final OutputWriter outputWriter
) throws CommandException {
for (var contactNumber : ns.<String>getList("contact")) {
try {
m.setContactBlocked(contactNumber, false);

View file

@ -13,10 +13,13 @@ import java.io.IOException;
public class UnregisterCommand implements LocalCommand {
public UnregisterCommand(final OutputWriter outputWriter) {
@Override
public String getName() {
return "unregister";
}
public static void attachToSubparser(final Subparser subparser) {
@Override
public 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!")
@ -24,7 +27,9 @@ public class UnregisterCommand implements LocalCommand {
}
@Override
public void handleCommand(final Namespace ns, final Manager m) throws CommandException {
public void handleCommand(
final Namespace ns, final Manager m, final OutputWriter outputWriter
) throws CommandException {
try {
if (ns.getBoolean("delete-account")) {
m.deleteAccount();

View file

@ -12,15 +12,20 @@ import java.io.IOException;
public class UpdateAccountCommand implements JsonRpcLocalCommand {
public UpdateAccountCommand(final OutputWriter outputWriter) {
@Override
public String getName() {
return "updateAccount";
}
public static void attachToSubparser(final Subparser subparser) {
@Override
public void attachToSubparser(final Subparser subparser) {
subparser.help("Update the account attributes on the signal server.");
}
@Override
public void handleCommand(final Namespace ns, final Manager m) throws CommandException {
public void handleCommand(
final Namespace ns, final Manager m, final OutputWriter outputWriter
) throws CommandException {
try {
m.updateAccountAttributes();
} catch (IOException e) {

View file

@ -15,10 +15,13 @@ import java.io.IOException;
public class UpdateContactCommand implements JsonRpcLocalCommand {
public UpdateContactCommand(final OutputWriter outputWriter) {
@Override
public String getName() {
return "updateContact";
}
public static void attachToSubparser(final Subparser subparser) {
@Override
public 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");
@ -26,7 +29,9 @@ public class UpdateContactCommand implements JsonRpcLocalCommand {
}
@Override
public void handleCommand(final Namespace ns, final Manager m) throws CommandException {
public void handleCommand(
final Namespace ns, final Manager m, final OutputWriter outputWriter
) throws CommandException {
var number = ns.getString("number");
try {

View file

@ -35,13 +35,14 @@ import java.util.List;
public class UpdateGroupCommand implements DbusCommand, JsonRpcLocalCommand {
private final static Logger logger = LoggerFactory.getLogger(UpdateGroupCommand.class);
private final OutputWriter outputWriter;
public UpdateGroupCommand(final OutputWriter outputWriter) {
this.outputWriter = outputWriter;
@Override
public String getName() {
return "updateGroup";
}
public static void attachToSubparser(final Subparser subparser) {
@Override
public void attachToSubparser(final Subparser subparser) {
subparser.help("Create or update a group.");
subparser.addArgument("-g", "--group-id", "--group").help("Specify the group ID.");
subparser.addArgument("-n", "--name").help("Specify the new group name.");
@ -107,7 +108,9 @@ public class UpdateGroupCommand implements DbusCommand, JsonRpcLocalCommand {
}
@Override
public void handleCommand(final Namespace ns, final Manager m) throws CommandException {
public void handleCommand(
final Namespace ns, final Manager m, final OutputWriter outputWriter
) throws CommandException {
GroupId groupId = null;
final var groupIdString = ns.getString("group-id");
if (groupIdString != null) {
@ -163,7 +166,7 @@ public class UpdateGroupCommand implements DbusCommand, JsonRpcLocalCommand {
timestamp = results.first();
ErrorUtils.handleSendMessageResults(results.second());
}
outputResult(timestamp, isNewGroup ? groupId : null);
outputResult(outputWriter, timestamp, isNewGroup ? groupId : null);
} catch (AttachmentInvalidException e) {
throw new UserErrorException("Failed to add avatar attachment for group\": " + e.getMessage());
} catch (GroupNotFoundException e) {
@ -178,7 +181,9 @@ public class UpdateGroupCommand implements DbusCommand, JsonRpcLocalCommand {
}
@Override
public void handleCommand(final Namespace ns, final Signal signal) throws CommandException {
public void handleCommand(
final Namespace ns, final Signal signal, final OutputWriter outputWriter
) throws CommandException {
byte[] groupId = null;
if (ns.getString("group-id") != null) {
try {
@ -209,7 +214,7 @@ public class UpdateGroupCommand implements DbusCommand, JsonRpcLocalCommand {
try {
var newGroupId = signal.updateGroup(groupId, groupName, groupMembers, groupAvatar);
if (groupId.length != newGroupId.length) {
outputResult(null, GroupId.unknownVersion(newGroupId));
outputResult(outputWriter, null, GroupId.unknownVersion(newGroupId));
}
} catch (Signal.Error.AttachmentInvalid e) {
throw new UserErrorException("Failed to add avatar attachment for group\": " + e.getMessage());
@ -218,7 +223,7 @@ public class UpdateGroupCommand implements DbusCommand, JsonRpcLocalCommand {
}
}
private void outputResult(final Long timestamp, final GroupId groupId) {
private void outputResult(final OutputWriter outputWriter, final Long timestamp, final GroupId groupId) {
if (outputWriter instanceof PlainTextWriter) {
final var writer = (PlainTextWriter) outputWriter;
if (groupId != null) {

View file

@ -15,10 +15,13 @@ import java.io.IOException;
public class UpdateProfileCommand implements JsonRpcLocalCommand {
public UpdateProfileCommand(final OutputWriter outputWriter) {
@Override
public String getName() {
return "updateProfile";
}
public static void attachToSubparser(final Subparser subparser) {
@Override
public 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)");
@ -31,7 +34,9 @@ public class UpdateProfileCommand implements JsonRpcLocalCommand {
}
@Override
public void handleCommand(final Namespace ns, final Manager m) throws CommandException {
public void handleCommand(
final Namespace ns, final Manager m, final OutputWriter outputWriter
) throws CommandException {
var givenName = ns.getString("given-name");
var familyName = ns.getString("family-name");
var about = ns.getString("about");

View file

@ -19,20 +19,23 @@ import java.io.IOException;
public class UploadStickerPackCommand implements LocalCommand {
private final static Logger logger = LoggerFactory.getLogger(UploadStickerPackCommand.class);
private final OutputWriter outputWriter;
public UploadStickerPackCommand(final OutputWriter outputWriter) {
this.outputWriter = outputWriter;
@Override
public String getName() {
return "uploadStickerPack";
}
public static void attachToSubparser(final Subparser subparser) {
@Override
public 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.");
}
@Override
public void handleCommand(final Namespace ns, final Manager m) throws CommandException {
public void handleCommand(
final Namespace ns, final Manager m, final OutputWriter outputWriter
) throws CommandException {
final var writer = (PlainTextWriter) outputWriter;
var path = new File(ns.getString("path"));

View file

@ -3,7 +3,6 @@ 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;
@ -17,10 +16,13 @@ import java.io.IOException;
public class VerifyCommand implements RegistrationCommand {
public VerifyCommand(final OutputWriter outputWriter) {
@Override
public String getName() {
return "verify";
}
public static void attachToSubparser(final Subparser subparser) {
@Override
public 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)");

View file

@ -10,14 +10,15 @@ import java.util.Map;
public class VersionCommand implements JsonRpcCommand<Void> {
private final OutputWriter outputWriter;
public VersionCommand(final OutputWriter outputWriter) {
this.outputWriter = outputWriter;
@Override
public String getName() {
return "version";
}
@Override
public void handleCommand(final Void request, final Manager m) throws CommandException {
public void handleCommand(
final Void request, final Manager m, final OutputWriter outputWriter
) throws CommandException {
final var jsonWriter = (JsonWriter) outputWriter;
jsonWriter.write(Map.of("version", BaseConfig.PROJECT_VERSION));
}