import org.asamk.signal.commands.MultiLocalCommand;
import org.asamk.signal.commands.ProvisioningCommand;
import org.asamk.signal.commands.RegistrationCommand;
+import org.asamk.signal.commands.exceptions.CommandException;
+import org.asamk.signal.commands.exceptions.UnexpectedErrorException;
+import org.asamk.signal.commands.exceptions.UserErrorException;
import org.asamk.signal.manager.Manager;
import org.asamk.signal.manager.NotRegisteredException;
import org.asamk.signal.manager.ProvisioningManager;
import java.io.File;
import java.io.IOException;
+import java.util.ArrayList;
import java.util.List;
-import java.util.Objects;
-import java.util.stream.Collectors;
public class App {
this.ns = ns;
}
- public int init() {
+ public void init() throws CommandException {
var commandKey = ns.getString("command");
var command = Commands.getCommand(commandKey);
if (command == null) {
- logger.error("Command not implemented!");
- return 1;
+ throw new UserErrorException("Command not implemented!");
}
OutputType outputType = ns.get("output");
if (!command.getSupportedOutputTypes().contains(outputType)) {
- logger.error("Command doesn't support output type {}", outputType.toString());
- return 1;
+ throw new UserErrorException("Command doesn't support output type " + outputType.toString());
}
var username = ns.getString("username");
final boolean useDbusSystem = ns.getBoolean("dbus_system");
if (useDbus || useDbusSystem) {
// If username is null, it will connect to the default object path
- return initDbusClient(command, username, useDbusSystem);
+ initDbusClient(command, username, useDbusSystem);
+ return;
}
final File dataPath;
}
if (!ServiceConfig.isSignalClientAvailable()) {
- logger.error("Missing required native library dependency: libsignal-client");
- return 1;
+ throw new UserErrorException("Missing required native library dependency: libsignal-client");
}
if (command instanceof ProvisioningCommand) {
if (username != null) {
- System.err.println("You cannot specify a username (phone number) when linking");
- return 1;
+ throw new UserErrorException("You cannot specify a username (phone number) when linking");
}
- return handleProvisioningCommand((ProvisioningCommand) command, dataPath, serviceEnvironment);
+ handleProvisioningCommand((ProvisioningCommand) command, dataPath, serviceEnvironment);
+ return;
}
if (username == null) {
var usernames = Manager.getAllLocalUsernames(dataPath);
if (usernames.size() == 0) {
- System.err.println("No local users found, you first need to register or link an account");
- return 1;
+ throw new UserErrorException("No local users found, you first need to register or link an account");
}
if (command instanceof MultiLocalCommand) {
- return handleMultiLocalCommand((MultiLocalCommand) command, dataPath, serviceEnvironment, usernames);
+ handleMultiLocalCommand((MultiLocalCommand) command, dataPath, serviceEnvironment, usernames);
+ return;
}
if (usernames.size() > 1) {
- System.err.println("Multiple users found, you need to specify a username (phone number) with -u");
- return 1;
+ throw new UserErrorException(
+ "Multiple users found, you need to specify a username (phone number) with -u");
}
username = usernames.get(0);
} else if (!PhoneNumberFormatter.isValidNumber(username, null)) {
- System.err.println("Invalid username (phone number), make sure you include the country code.");
- return 1;
+ throw new UserErrorException("Invalid username (phone number), make sure you include the country code.");
}
if (command instanceof RegistrationCommand) {
- return handleRegistrationCommand((RegistrationCommand) command, username, dataPath, serviceEnvironment);
+ handleRegistrationCommand((RegistrationCommand) command, username, dataPath, serviceEnvironment);
+ return;
}
if (!(command instanceof LocalCommand)) {
- System.err.println("Command only works via dbus");
- return 1;
+ throw new UserErrorException("Command only works via dbus");
}
- return handleLocalCommand((LocalCommand) command, username, dataPath, serviceEnvironment);
+ handleLocalCommand((LocalCommand) command, username, dataPath, serviceEnvironment);
}
- private int handleProvisioningCommand(
+ private void handleProvisioningCommand(
final ProvisioningCommand command, final File dataPath, final ServiceEnvironment serviceEnvironment
- ) {
+ ) throws CommandException {
var pm = ProvisioningManager.init(dataPath, serviceEnvironment, BaseConfig.USER_AGENT);
- return command.handleCommand(ns, pm);
+ command.handleCommand(ns, pm);
}
- private int handleRegistrationCommand(
+ private void handleRegistrationCommand(
final RegistrationCommand command,
final String username,
final File dataPath,
final ServiceEnvironment serviceEnvironment
- ) {
+ ) throws CommandException {
final RegistrationManager manager;
try {
manager = RegistrationManager.init(username, dataPath, serviceEnvironment, BaseConfig.USER_AGENT);
} catch (Throwable e) {
- logger.error("Error loading or creating state file: {}", e.getMessage());
- return 2;
+ throw new UnexpectedErrorException("Error loading or creating state file: " + e.getMessage());
}
try (var m = manager) {
- return command.handleCommand(ns, m);
+ command.handleCommand(ns, m);
} catch (IOException e) {
- logger.error("Cleanup failed", e);
- return 2;
+ logger.warn("Cleanup failed", e);
}
}
- private int handleLocalCommand(
+ private void handleLocalCommand(
final LocalCommand command,
final String username,
final File dataPath,
final ServiceEnvironment serviceEnvironment
- ) {
+ ) throws CommandException {
try (var m = loadManager(username, dataPath, serviceEnvironment)) {
- if (m == null) {
- return 2;
- }
-
- return command.handleCommand(ns, m);
+ command.handleCommand(ns, m);
} catch (IOException e) {
- logger.error("Cleanup failed", e);
- return 2;
+ logger.warn("Cleanup failed", e);
}
}
- private int handleMultiLocalCommand(
+ private void handleMultiLocalCommand(
final MultiLocalCommand command,
final File dataPath,
final ServiceEnvironment serviceEnvironment,
final List<String> usernames
- ) {
- final var managers = usernames.stream()
- .map(u -> loadManager(u, dataPath, serviceEnvironment))
- .filter(Objects::nonNull)
- .collect(Collectors.toList());
+ ) throws CommandException {
+ final var managers = new ArrayList<Manager>();
+ for (String u : usernames) {
+ managers.add(loadManager(u, dataPath, serviceEnvironment));
+ }
- var result = command.handleCommand(ns, managers);
+ command.handleCommand(ns, managers);
for (var m : managers) {
try {
logger.warn("Cleanup failed", e);
}
}
- return result;
}
private Manager loadManager(
final String username, final File dataPath, final ServiceEnvironment serviceEnvironment
- ) {
+ ) throws CommandException {
Manager manager;
try {
manager = Manager.init(username, dataPath, serviceEnvironment, BaseConfig.USER_AGENT);
} catch (NotRegisteredException e) {
- logger.error("User " + username + " is not registered.");
- return null;
+ throw new UserErrorException("User " + username + " is not registered.");
} catch (Throwable e) {
- logger.error("Error loading state file for user " + username + ": {}", e.getMessage());
- return null;
+ throw new UnexpectedErrorException("Error loading state file for user " + username + ": " + e.getMessage());
}
try {
manager.checkAccountState();
} catch (IOException e) {
- logger.error("Error while checking account " + username + ": {}", e.getMessage());
- return null;
+ throw new UnexpectedErrorException("Error while checking account " + username + ": " + e.getMessage());
}
return manager;
}
- private int initDbusClient(final Command command, final String username, final boolean systemBus) {
+ private void initDbusClient(
+ final Command command, final String username, final boolean systemBus
+ ) throws CommandException {
try {
DBusConnection.DBusBusType busType;
if (systemBus) {
DbusConfig.getObjectPath(username),
Signal.class);
- return handleCommand(command, ts, dBusConn);
+ handleCommand(command, ts, dBusConn);
}
} catch (DBusException | IOException e) {
logger.error("Dbus client failed", e);
- return 2;
+ throw new UnexpectedErrorException("Dbus client failed");
}
}
- private int handleCommand(Command command, Signal ts, DBusConnection dBusConn) {
+ private void handleCommand(Command command, Signal ts, DBusConnection dBusConn) throws CommandException {
if (command instanceof ExtendedDbusCommand) {
- return ((ExtendedDbusCommand) command).handleCommand(ns, ts, dBusConn);
+ ((ExtendedDbusCommand) command).handleCommand(ns, ts, dBusConn);
} else if (command instanceof DbusCommand) {
- return ((DbusCommand) command).handleCommand(ns, ts);
+ ((DbusCommand) command).handleCommand(ns, ts);
} else {
- System.err.println("Command is not yet implemented via dbus");
- return 1;
+ throw new UserErrorException("Command is not yet implemented via dbus");
}
}
import org.whispersystems.signalservice.api.messages.SignalServiceContent;
import org.whispersystems.signalservice.api.messages.SignalServiceEnvelope;
-import java.io.IOException;
import java.util.HashMap;
public class JsonReceiveMessageHandler implements Manager.ReceiveMessageHandler {
if (envelope != null) {
object.put("envelope", new JsonMessageEnvelope(envelope, content, m));
}
- try {
- jsonWriter.write(object);
- } catch (IOException e) {
- logger.error("Failed to write json object: {}", e.getMessage());
- }
+
+ jsonWriter.write(object);
}
}
objectMapper.disable(JsonGenerator.Feature.AUTO_CLOSE_TARGET);
}
- public void write(final Object object) throws IOException {
+ public void write(final Object object) {
try {
- objectMapper.writeValue(writer, object);
- } catch (JsonProcessingException e) {
- // Some issue with json serialization, probably caused by a bug
+ try {
+ objectMapper.writeValue(writer, object);
+ } catch (JsonProcessingException e) {
+ // Some issue with json serialization, probably caused by a bug
+ throw new AssertionError(e);
+ }
+ writer.write(System.lineSeparator());
+ writer.flush();
+ } catch (IOException e) {
throw new AssertionError(e);
}
- writer.write(System.lineSeparator());
- writer.flush();
}
}
import net.sourceforge.argparse4j.inf.ArgumentParserException;
import net.sourceforge.argparse4j.inf.Namespace;
+import org.asamk.signal.commands.exceptions.CommandException;
+import org.asamk.signal.commands.exceptions.IOErrorException;
+import org.asamk.signal.commands.exceptions.UnexpectedErrorException;
+import org.asamk.signal.commands.exceptions.UntrustedKeyErrorException;
+import org.asamk.signal.commands.exceptions.UserErrorException;
import org.asamk.signal.manager.LibSignalLogger;
import org.asamk.signal.util.SecurityProvider;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
var ns = parser.parseArgsOrFail(args);
- var res = new App(ns).init();
- System.exit(res);
+ int status = 0;
+ try {
+ new App(ns).init();
+ } catch (CommandException e) {
+ System.err.println(e.getMessage());
+ status = getStatusForError(e);
+ }
+ System.exit(status);
}
private static void installSecurityProviderWorkaround() {
System.setProperty("org.slf4j.simpleLogger.showDateTime", "false");
}
}
+
+ private static int getStatusForError(final CommandException e) {
+ if (e instanceof UserErrorException) {
+ return 1;
+ } else if (e instanceof UnexpectedErrorException) {
+ return 2;
+ } else if (e instanceof IOErrorException) {
+ return 3;
+ } else if (e instanceof UntrustedKeyErrorException) {
+ return 4;
+ } else {
+ return 2;
+ }
+ }
}
package org.asamk.signal;
-import java.io.IOException;
-
public interface PlainTextWriter {
- void println(String format, Object... args) throws IOException;
+ void println(String format, Object... args);
PlainTextWriter indentedWriter();
- default void println() throws IOException {
+ default void println() {
println("");
}
- default void indent(final WriterConsumer subWriter) throws IOException {
+ default void indent(final WriterConsumer subWriter) {
subWriter.consume(indentedWriter());
}
interface WriterConsumer {
- void consume(PlainTextWriter writer) throws IOException;
+ void consume(PlainTextWriter writer);
}
}
}
@Override
- public void println(String format, Object... args) throws IOException {
+ public void println(String format, Object... args) {
final var message = MessageFormatter.arrayFormat(format, args).getMessage();
- writer.write(message);
- writer.write(System.lineSeparator());
- writer.flush();
+ try {
+ writer.write(message);
+ writer.write(System.lineSeparator());
+ writer.flush();
+ } catch (IOException e) {
+ throw new AssertionError(e);
+ }
}
@Override
}
@Override
- public void println(final String format, final Object... args) throws IOException {
- writer.write(spaces);
+ public void println(final String format, final Object... args) {
+ try {
+ writer.write(spaces);
+ } catch (IOException e) {
+ throw new AssertionError(e);
+ }
plainTextWriter.println(format, args);
}
writer.println("- {}: {} (length: {})", formatContact(address), mention.getStart(), mention.getLength());
}
- private void printAttachment(PlainTextWriter writer, SignalServiceAttachment attachment) throws IOException {
+ private void printAttachment(PlainTextWriter writer, SignalServiceAttachment attachment) {
writer.println("Content-Type: {}", attachment.getContentType());
writer.println("Type: {}", attachment.isPointer() ? "Pointer" : attachment.isStream() ? "Stream" : "<unknown>");
if (attachment.isPointer()) {
import net.sourceforge.argparse4j.inf.Namespace;
import net.sourceforge.argparse4j.inf.Subparser;
+import org.asamk.signal.commands.exceptions.CommandException;
+import org.asamk.signal.commands.exceptions.IOErrorException;
+import org.asamk.signal.commands.exceptions.UnexpectedErrorException;
+import org.asamk.signal.commands.exceptions.UserErrorException;
import org.asamk.signal.manager.Manager;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
import org.whispersystems.libsignal.InvalidKeyException;
import java.io.IOException;
public class AddDeviceCommand implements LocalCommand {
+ private final static Logger logger = LoggerFactory.getLogger(AddDeviceCommand.class);
+
@Override
public void attachToSubparser(final Subparser subparser) {
subparser.addArgument("--uri")
}
@Override
- public int handleCommand(final Namespace ns, final Manager m) {
+ public void handleCommand(final Namespace ns, final Manager m) throws CommandException {
try {
m.addDeviceLink(new URI(ns.getString("uri")));
- return 0;
} catch (IOException e) {
- e.printStackTrace();
- return 3;
- } catch (InvalidKeyException | URISyntaxException e) {
- e.printStackTrace();
- return 2;
+ logger.error("Add device link failed", e);
+ throw new IOErrorException("Add device link failed");
+ } catch (URISyntaxException e) {
+ throw new UserErrorException("Device link uri has invalid format: {}" + e.getMessage());
+ } catch (InvalidKeyException e) {
+ logger.error("Add device link failed", e);
+ throw new UnexpectedErrorException("Add device link failed.");
} catch (AssertionError e) {
handleAssertionError(e);
- return 1;
+ throw e;
}
}
}
import org.asamk.signal.manager.groups.GroupIdFormatException;
import org.asamk.signal.manager.groups.GroupNotFoundException;
import org.asamk.signal.util.Util;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
import org.whispersystems.signalservice.api.util.InvalidNumberException;
public class BlockCommand implements LocalCommand {
+ private final static Logger logger = LoggerFactory.getLogger(BlockCommand.class);
+
@Override
public void attachToSubparser(final Subparser subparser) {
subparser.addArgument("contact").help("Contact number").nargs("*");
}
@Override
- public int handleCommand(final Namespace ns, final Manager m) {
+ public void handleCommand(final Namespace ns, final Manager m) {
for (var contact_number : ns.<String>getList("contact")) {
try {
m.setContactBlocked(contact_number, true);
} catch (InvalidNumberException e) {
- System.err.println(e.getMessage());
+ logger.warn("Invalid number {}: {}", contact_number, e.getMessage());
}
}
var groupId = Util.decodeGroupId(groupIdString);
m.setGroupBlocked(groupId, true);
} catch (GroupIdFormatException | GroupNotFoundException e) {
- System.err.println(e.getMessage());
+ logger.warn("Invalid group id {}: {}", groupIdString, e.getMessage());
}
}
}
-
- return 0;
}
}
import org.asamk.signal.DbusReceiveMessageHandler;
import org.asamk.signal.JsonDbusReceiveMessageHandler;
import org.asamk.signal.OutputType;
+import org.asamk.signal.commands.exceptions.CommandException;
+import org.asamk.signal.commands.exceptions.UnexpectedErrorException;
import org.asamk.signal.dbus.DbusSignalImpl;
import org.asamk.signal.manager.Manager;
import org.freedesktop.dbus.connections.impl.DBusConnection;
}
@Override
- public int handleCommand(final Namespace ns, final Manager m) {
+ public void handleCommand(final Namespace ns, final Manager m) throws CommandException {
var inJson = ns.get("output") == OutputType.JSON || ns.getBoolean("json");
// TODO delete later when "json" variable is removed
t.join();
} catch (InterruptedException ignored) {
}
- return 0;
} catch (DBusException | IOException e) {
logger.error("Dbus command failed", e);
- return 2;
+ throw new UnexpectedErrorException("Dbus command failed");
}
}
@Override
- public int handleCommand(final Namespace ns, final List<Manager> managers) {
+ public void handleCommand(final Namespace ns, final List<Manager> managers) throws CommandException {
var inJson = ns.get("output") == OutputType.JSON || ns.getBoolean("json");
// TODO delete later when "json" variable is removed
} catch (InterruptedException ignored) {
}
}
- return 0;
} catch (DBusException | IOException e) {
logger.error("Dbus command failed", e);
- return 2;
+ throw new UnexpectedErrorException("Dbus command failed");
}
}
import net.sourceforge.argparse4j.inf.Namespace;
import org.asamk.Signal;
+import org.asamk.signal.commands.exceptions.CommandException;
import org.asamk.signal.dbus.DbusSignalImpl;
import org.asamk.signal.manager.Manager;
public interface DbusCommand extends LocalCommand {
- int handleCommand(Namespace ns, Signal signal);
+ void handleCommand(Namespace ns, Signal signal) throws CommandException;
- default int handleCommand(final Namespace ns, final Manager m) {
- return handleCommand(ns, new DbusSignalImpl(m));
+ default void handleCommand(final Namespace ns, final Manager m) throws CommandException {
+ handleCommand(ns, new DbusSignalImpl(m));
}
}
import net.sourceforge.argparse4j.inf.Namespace;
import org.asamk.Signal;
+import org.asamk.signal.commands.exceptions.CommandException;
import org.freedesktop.dbus.connections.impl.DBusConnection;
public interface ExtendedDbusCommand extends Command {
- int handleCommand(Namespace ns, Signal signal, DBusConnection dbusconnection);
+ void handleCommand(Namespace ns, Signal signal, DBusConnection dbusconnection) throws CommandException;
}
import org.asamk.signal.JsonWriter;
import org.asamk.signal.OutputType;
import org.asamk.signal.PlainTextWriterImpl;
+import org.asamk.signal.commands.exceptions.CommandException;
+import org.asamk.signal.commands.exceptions.IOErrorException;
import org.asamk.signal.manager.Manager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
}
@Override
- public int handleCommand(final Namespace ns, final Manager m) {
+ public void handleCommand(final Namespace ns, final Manager m) throws CommandException {
// Setup the json object mapper
var inJson = ns.get("output") == OutputType.JSON || ns.getBoolean("json");
try {
registered = m.areUsersRegistered(new HashSet<>(ns.getList("number")));
} catch (IOException e) {
- System.err.println("Unable to check if users are registered");
- return 3;
+ logger.debug("Failed to check registered users", e);
+ throw new IOErrorException("Unable to check if users are registered");
}
// Output
.map(entry -> new JsonUserStatus(entry.getKey(), entry.getValue()))
.collect(Collectors.toList());
- try {
- jsonWriter.write(jsonUserStatuses);
- } catch (IOException e) {
- logger.error("Failed to write json object: {}", e.getMessage());
- return 3;
- }
+ jsonWriter.write(jsonUserStatuses);
} else {
final var writer = new PlainTextWriterImpl(System.out);
- try {
- for (var entry : registered.entrySet()) {
- writer.println("{}: {}", entry.getKey(), entry.getValue());
- }
- } catch (IOException e) {
- e.printStackTrace();
- return 3;
+ for (var entry : registered.entrySet()) {
+ writer.println("{}: {}", entry.getKey(), entry.getValue());
}
}
-
- return 0;
}
private static final class JsonUserStatus {
import net.sourceforge.argparse4j.inf.Subparser;
import org.asamk.signal.PlainTextWriterImpl;
+import org.asamk.signal.commands.exceptions.CommandException;
+import org.asamk.signal.commands.exceptions.IOErrorException;
+import org.asamk.signal.commands.exceptions.UnexpectedErrorException;
+import org.asamk.signal.commands.exceptions.UserErrorException;
import org.asamk.signal.manager.Manager;
import org.asamk.signal.manager.groups.GroupInviteLinkUrl;
import org.freedesktop.dbus.exceptions.DBusExecutionException;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
import org.whispersystems.signalservice.api.groupsv2.GroupLinkNotActiveException;
import org.whispersystems.signalservice.internal.push.exceptions.GroupPatchNotAcceptedException;
import java.io.IOException;
import static org.asamk.signal.util.ErrorUtils.handleAssertionError;
-import static org.asamk.signal.util.ErrorUtils.handleIOException;
import static org.asamk.signal.util.ErrorUtils.handleTimestampAndSendMessageResults;
public class JoinGroupCommand implements LocalCommand {
- private final static Logger logger = LoggerFactory.getLogger(JoinGroupCommand.class);
-
@Override
public void attachToSubparser(final Subparser subparser) {
subparser.addArgument("--uri").required(true).help("Specify the uri with the group invitation link.");
}
@Override
- public int handleCommand(final Namespace ns, final Manager m) {
+ public void handleCommand(final Namespace ns, final Manager m) throws CommandException {
final GroupInviteLinkUrl linkUrl;
var uri = ns.getString("uri");
try {
linkUrl = GroupInviteLinkUrl.fromUri(uri);
} catch (GroupInviteLinkUrl.InvalidGroupLinkException e) {
- System.err.println("Group link is invalid: " + e.getMessage());
- return 1;
+ throw new UserErrorException("Group link is invalid: " + e.getMessage());
} catch (GroupInviteLinkUrl.UnknownGroupLinkVersionException e) {
- System.err.println("Group link was created with an incompatible version: " + e.getMessage());
- return 1;
+ throw new UserErrorException("Group link was created with an incompatible version: " + e.getMessage());
}
if (linkUrl == null) {
- System.err.println("Link is not a signal group invitation link");
- return 1;
+ throw new UserErrorException("Link is not a signal group invitation link");
}
try {
} else {
writer.println("Joined group \"{}\"", newGroupId.toBase64());
}
- return handleTimestampAndSendMessageResults(writer, 0, results.second());
+ handleTimestampAndSendMessageResults(writer, 0, results.second());
} catch (AssertionError e) {
handleAssertionError(e);
- return 1;
+ throw e;
} catch (GroupPatchNotAcceptedException e) {
- System.err.println("Failed to join group, maybe already a member");
- return 1;
+ throw new UserErrorException("Failed to join group, maybe already a member");
} catch (IOException e) {
- e.printStackTrace();
- handleIOException(e);
- return 3;
+ throw new IOErrorException("Failed to send message: " + e.getMessage());
} catch (DBusExecutionException e) {
- System.err.println("Failed to send message: " + e.getMessage());
- return 2;
+ throw new UnexpectedErrorException("Failed to send message: " + e.getMessage());
} catch (GroupLinkNotActiveException e) {
- System.err.println("Group link is not valid: " + e.getMessage());
- return 1;
+ throw new UserErrorException("Group link is not valid: " + e.getMessage());
}
}
}
import net.sourceforge.argparse4j.inf.Subparser;
import org.asamk.signal.PlainTextWriterImpl;
+import org.asamk.signal.commands.exceptions.CommandException;
+import org.asamk.signal.commands.exceptions.IOErrorException;
+import org.asamk.signal.commands.exceptions.UnexpectedErrorException;
+import org.asamk.signal.commands.exceptions.UserErrorException;
import org.asamk.signal.manager.ProvisioningManager;
import org.asamk.signal.manager.UserAlreadyExists;
import org.slf4j.Logger;
}
@Override
- public int handleCommand(final Namespace ns, final ProvisioningManager m) {
+ public void handleCommand(final Namespace ns, final ProvisioningManager m) throws CommandException {
final var writer = new PlainTextWriterImpl(System.out);
var deviceName = ns.getString("name");
var username = m.finishDeviceLink(deviceName);
writer.println("Associated with: {}", username);
} catch (TimeoutException e) {
- System.err.println("Link request timed out, please try again.");
- return 3;
+ throw new UserErrorException("Link request timed out, please try again.");
} catch (IOException e) {
- System.err.println("Link request error: " + e.getMessage());
- return 3;
+ throw new IOErrorException("Link request error: " + e.getMessage());
} catch (AssertionError e) {
handleAssertionError(e);
- return 1;
+ throw e;
} catch (InvalidKeyException e) {
- e.printStackTrace();
- return 2;
+ logger.debug("Finish device link failed", e);
+ throw new UnexpectedErrorException("Invalid key: " + e.getMessage());
} catch (UserAlreadyExists e) {
- System.err.println("The user "
+ throw new UserErrorException("The user "
+ e.getUsername()
+ " already exists\nDelete \""
+ e.getFileName()
+ "\" before trying again.");
- return 1;
}
- return 0;
}
}
import org.asamk.signal.PlainTextWriterImpl;
import org.asamk.signal.manager.Manager;
-import java.io.IOException;
-
public class ListContactsCommand implements LocalCommand {
@Override
}
@Override
- public int handleCommand(final Namespace ns, final Manager m) {
+ public void handleCommand(final Namespace ns, final Manager m) {
final var writer = new PlainTextWriterImpl(System.out);
var contacts = m.getContacts();
- try {
- for (var c : contacts) {
- writer.println("Number: {} Name: {} Blocked: {}", c.number, c.name, c.blocked);
- }
- } catch (IOException e) {
- e.printStackTrace();
- return 3;
+ for (var c : contacts) {
+ writer.println("Number: {} Name: {} Blocked: {}", c.number, c.name, c.blocked);
}
- return 0;
}
}
import net.sourceforge.argparse4j.inf.Subparser;
import org.asamk.signal.PlainTextWriterImpl;
+import org.asamk.signal.commands.exceptions.CommandException;
+import org.asamk.signal.commands.exceptions.IOErrorException;
import org.asamk.signal.manager.Manager;
import org.asamk.signal.util.DateUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.whispersystems.signalservice.api.messages.multidevice.DeviceInfo;
import java.io.IOException;
+import java.util.List;
public class ListDevicesCommand implements LocalCommand {
+ private final static Logger logger = LoggerFactory.getLogger(ListDevicesCommand.class);
+
@Override
public void attachToSubparser(final Subparser subparser) {
}
@Override
- public int handleCommand(final Namespace ns, final Manager m) {
+ public void handleCommand(final Namespace ns, final Manager m) throws CommandException {
final var writer = new PlainTextWriterImpl(System.out);
+
+ List<DeviceInfo> devices;
try {
- var devices = m.getLinkedDevices();
- for (var d : devices) {
- writer.println("- Device {}{}:", d.getId(), (d.getId() == m.getDeviceId() ? " (this device)" : ""));
- writer.indent(w -> {
- w.println("Name: {}", d.getName());
- w.println("Created: {}", DateUtils.formatTimestamp(d.getCreated()));
- w.println("Last seen: {}", DateUtils.formatTimestamp(d.getLastSeen()));
- });
- }
- return 0;
+ devices = m.getLinkedDevices();
} catch (IOException e) {
- e.printStackTrace();
- return 3;
+ logger.debug("Failed to get linked devices", e);
+ throw new IOErrorException("Failed to get linked devices: " + e.getMessage());
+ }
+
+ for (var d : devices) {
+ writer.println("- Device {}{}:", d.getId(), (d.getId() == m.getDeviceId() ? " (this device)" : ""));
+ writer.indent(w -> {
+ w.println("Name: {}", d.getName());
+ w.println("Created: {}", DateUtils.formatTimestamp(d.getCreated()));
+ w.println("Last seen: {}", DateUtils.formatTimestamp(d.getLastSeen()));
+ });
}
}
}
import org.asamk.signal.OutputType;
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;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.whispersystems.signalservice.api.push.SignalServiceAddress;
-import java.io.IOException;
import java.util.ArrayList;
import java.util.Set;
import java.util.stream.Collectors;
private static void printGroupPlainText(
PlainTextWriter writer, Manager m, GroupInfo group, boolean detailed
- ) throws IOException {
+ ) {
if (detailed) {
final var groupInviteLink = group.getGroupInviteLink();
}
@Override
- public int handleCommand(final Namespace ns, final Manager m) {
+ public void handleCommand(final Namespace ns, final Manager m) throws CommandException {
if (ns.get("output") == OutputType.JSON) {
final var jsonWriter = new JsonWriter(System.out);
groupInviteLink == null ? null : groupInviteLink.getUrl()));
}
- try {
- jsonWriter.write(jsonGroups);
- } catch (IOException e) {
- logger.error("Failed to write json object: {}", e.getMessage());
- return 3;
- }
-
- return 0;
+ jsonWriter.write(jsonGroups);
} else {
final var writer = new PlainTextWriterImpl(System.out);
boolean detailed = ns.getBoolean("detailed");
- try {
- for (var group : m.getGroups()) {
- printGroupPlainText(writer, m, group, detailed);
- }
- } catch (IOException e) {
- e.printStackTrace();
- return 3;
+ for (var group : m.getGroups()) {
+ printGroupPlainText(writer, m, group, detailed);
}
}
-
- return 0;
}
private static final class JsonGroup {
import org.asamk.signal.PlainTextWriter;
import org.asamk.signal.PlainTextWriterImpl;
+import org.asamk.signal.commands.exceptions.CommandException;
+import org.asamk.signal.commands.exceptions.UserErrorException;
import org.asamk.signal.manager.Manager;
import org.asamk.signal.manager.storage.protocol.IdentityInfo;
import org.asamk.signal.util.Hex;
import org.slf4j.LoggerFactory;
import org.whispersystems.signalservice.api.util.InvalidNumberException;
-import java.io.IOException;
+import java.util.List;
public class ListIdentitiesCommand implements LocalCommand {
private static void printIdentityFingerprint(PlainTextWriter writer, Manager m, IdentityInfo theirId) {
var digits = Util.formatSafetyNumber(m.computeSafetyNumber(theirId.getAddress(), theirId.getIdentityKey()));
- try {
- writer.println("{}: {} Added: {} Fingerprint: {} Safety Number: {}",
- theirId.getAddress().getNumber().orNull(),
- theirId.getTrustLevel(),
- theirId.getDateAdded(),
- Hex.toString(theirId.getFingerprint()),
- digits);
- } catch (IOException e) {
- e.printStackTrace();
- }
+ writer.println("{}: {} Added: {} Fingerprint: {} Safety Number: {}",
+ theirId.getAddress().getNumber().orNull(),
+ theirId.getTrustLevel(),
+ theirId.getDateAdded(),
+ Hex.toString(theirId.getFingerprint()),
+ digits);
}
@Override
}
@Override
- public int handleCommand(final Namespace ns, final Manager m) {
+ public void handleCommand(final Namespace ns, final Manager m) throws CommandException {
final var writer = new PlainTextWriterImpl(System.out);
- if (ns.get("number") == null) {
+ var number = ns.getString("number");
+
+ if (number == null) {
for (var identity : m.getIdentities()) {
printIdentityFingerprint(writer, m, identity);
}
- } else {
- var number = ns.getString("number");
- try {
- var identities = m.getIdentities(number);
- for (var id : identities) {
- printIdentityFingerprint(writer, m, id);
- }
- } catch (InvalidNumberException e) {
- System.err.println("Invalid number: " + e.getMessage());
- }
+ return;
+ }
+
+ List<IdentityInfo> identities;
+ try {
+ identities = m.getIdentities(number);
+ } catch (InvalidNumberException e) {
+ throw new UserErrorException("Invalid number: " + e.getMessage());
+ }
+
+ for (var id : identities) {
+ printIdentityFingerprint(writer, m, id);
}
- return 0;
}
}
import net.sourceforge.argparse4j.inf.Namespace;
+import org.asamk.signal.commands.exceptions.CommandException;
import org.asamk.signal.manager.Manager;
public interface LocalCommand extends Command {
- int handleCommand(Namespace ns, Manager m);
+ void handleCommand(Namespace ns, Manager m) throws CommandException;
}
import net.sourceforge.argparse4j.inf.Namespace;
+import org.asamk.signal.commands.exceptions.CommandException;
import org.asamk.signal.manager.Manager;
import java.util.List;
public interface MultiLocalCommand extends LocalCommand {
- int handleCommand(Namespace ns, List<Manager> m);
+ void handleCommand(Namespace ns, List<Manager> m) throws CommandException;
@Override
- default int handleCommand(final Namespace ns, final Manager m) {
- return handleCommand(ns, List.of(m));
+ default void handleCommand(final Namespace ns, final Manager m) throws CommandException {
+ handleCommand(ns, List.of(m));
}
}
import net.sourceforge.argparse4j.inf.Namespace;
+import org.asamk.signal.commands.exceptions.CommandException;
import org.asamk.signal.manager.ProvisioningManager;
public interface ProvisioningCommand extends Command {
- int handleCommand(Namespace ns, ProvisioningManager m);
+ void handleCommand(Namespace ns, ProvisioningManager m) throws CommandException;
}
import net.sourceforge.argparse4j.inf.Subparser;
import org.asamk.signal.PlainTextWriterImpl;
+import org.asamk.signal.commands.exceptions.CommandException;
+import org.asamk.signal.commands.exceptions.IOErrorException;
+import org.asamk.signal.commands.exceptions.UserErrorException;
import org.asamk.signal.manager.Manager;
+import org.asamk.signal.manager.groups.GroupId;
import org.asamk.signal.manager.groups.GroupIdFormatException;
import org.asamk.signal.manager.groups.GroupNotFoundException;
import org.asamk.signal.manager.groups.NotAGroupMemberException;
import java.io.IOException;
import static org.asamk.signal.util.ErrorUtils.handleAssertionError;
-import static org.asamk.signal.util.ErrorUtils.handleGroupIdFormatException;
-import static org.asamk.signal.util.ErrorUtils.handleGroupNotFoundException;
-import static org.asamk.signal.util.ErrorUtils.handleIOException;
-import static org.asamk.signal.util.ErrorUtils.handleNotAGroupMemberException;
import static org.asamk.signal.util.ErrorUtils.handleTimestampAndSendMessageResults;
public class QuitGroupCommand implements LocalCommand {
}
@Override
- public int handleCommand(final Namespace ns, final Manager m) {
+ public void handleCommand(final Namespace ns, final Manager m) throws CommandException {
+ final var writer = new PlainTextWriterImpl(System.out);
+
+ final GroupId groupId;
try {
- final var writer = new PlainTextWriterImpl(System.out);
+ groupId = Util.decodeGroupId(ns.getString("group"));
+ } catch (GroupIdFormatException e) {
+ throw new UserErrorException("Invalid group id:" + e.getMessage());
+ }
- final var groupId = Util.decodeGroupId(ns.getString("group"));
+ try {
final var results = m.sendQuitGroupMessage(groupId);
- return handleTimestampAndSendMessageResults(writer, results.first(), results.second());
+ handleTimestampAndSendMessageResults(writer, results.first(), results.second());
} catch (IOException e) {
- handleIOException(e);
- return 3;
+ throw new IOErrorException("Failed to send message: " + e.getMessage());
} catch (AssertionError e) {
handleAssertionError(e);
- return 1;
+ throw e;
} catch (GroupNotFoundException e) {
- handleGroupNotFoundException(e);
- return 1;
+ throw new UserErrorException("Failed to send to group: " + e.getMessage());
} catch (NotAGroupMemberException e) {
- handleNotAGroupMemberException(e);
- return 1;
- } catch (GroupIdFormatException e) {
- handleGroupIdFormatException(e);
- return 1;
+ throw new UserErrorException("Failed to send to group: " + e.getMessage());
}
}
}
import org.asamk.signal.OutputType;
import org.asamk.signal.PlainTextWriterImpl;
import org.asamk.signal.ReceiveMessageHandler;
+import org.asamk.signal.commands.exceptions.CommandException;
+import org.asamk.signal.commands.exceptions.IOErrorException;
+import org.asamk.signal.commands.exceptions.UnexpectedErrorException;
import org.asamk.signal.json.JsonMessageEnvelope;
import org.asamk.signal.manager.Manager;
import org.asamk.signal.util.DateUtils;
return Set.of(OutputType.PLAIN_TEXT, OutputType.JSON);
}
- public int handleCommand(final Namespace ns, final Signal signal, DBusConnection dbusconnection) {
+ public void handleCommand(
+ final Namespace ns, final Signal signal, DBusConnection dbusconnection
+ ) throws CommandException {
var inJson = ns.get("output") == OutputType.JSON || ns.getBoolean("json");
// TODO delete later when "json" variable is removed
dbusconnection.addSigHandler(Signal.MessageReceived.class, messageReceived -> {
var envelope = new JsonMessageEnvelope(messageReceived);
final var object = Map.of("envelope", envelope);
- try {
- jsonWriter.write(object);
- } catch (IOException e) {
- logger.error("Failed to write json object: {}", e.getMessage());
- }
+ jsonWriter.write(object);
});
dbusconnection.addSigHandler(Signal.ReceiptReceived.class, receiptReceived -> {
var envelope = new JsonMessageEnvelope(receiptReceived);
final var object = Map.of("envelope", envelope);
- try {
- jsonWriter.write(object);
- } catch (IOException e) {
- logger.error("Failed to write json object: {}", e.getMessage());
- }
+ jsonWriter.write(object);
});
dbusconnection.addSigHandler(Signal.SyncMessageReceived.class, syncReceived -> {
var envelope = new JsonMessageEnvelope(syncReceived);
final var object = Map.of("envelope", envelope);
- try {
- jsonWriter.write(object);
- } catch (IOException e) {
- logger.error("Failed to write json object: {}", e.getMessage());
- }
+ jsonWriter.write(object);
});
} else {
final var writer = new PlainTextWriterImpl(System.out);
dbusconnection.addSigHandler(Signal.MessageReceived.class, messageReceived -> {
- try {
- writer.println("Envelope from: {}", messageReceived.getSender());
- writer.println("Timestamp: {}", DateUtils.formatTimestamp(messageReceived.getTimestamp()));
- writer.println("Body: {}", messageReceived.getMessage());
- if (messageReceived.getGroupId().length > 0) {
- writer.println("Group info:");
- writer.indentedWriter()
- .println("Id: {}",
- Base64.getEncoder().encodeToString(messageReceived.getGroupId()));
- }
- if (messageReceived.getAttachments().size() > 0) {
- writer.println("Attachments:");
- for (var attachment : messageReceived.getAttachments()) {
- writer.println("- Stored plaintext in: {}", attachment);
- }
+ writer.println("Envelope from: {}", messageReceived.getSender());
+ writer.println("Timestamp: {}", DateUtils.formatTimestamp(messageReceived.getTimestamp()));
+ writer.println("Body: {}", messageReceived.getMessage());
+ if (messageReceived.getGroupId().length > 0) {
+ writer.println("Group info:");
+ writer.indentedWriter()
+ .println("Id: {}", Base64.getEncoder().encodeToString(messageReceived.getGroupId()));
+ }
+ if (messageReceived.getAttachments().size() > 0) {
+ writer.println("Attachments:");
+ for (var attachment : messageReceived.getAttachments()) {
+ writer.println("- Stored plaintext in: {}", attachment);
}
- writer.println();
- } catch (IOException e) {
- e.printStackTrace();
}
+ writer.println();
});
dbusconnection.addSigHandler(Signal.ReceiptReceived.class, receiptReceived -> {
- try {
- writer.println("Receipt from: {}", receiptReceived.getSender());
- writer.println("Timestamp: {}", DateUtils.formatTimestamp(receiptReceived.getTimestamp()));
- } catch (IOException e) {
- e.printStackTrace();
- }
+ writer.println("Receipt from: {}", receiptReceived.getSender());
+ writer.println("Timestamp: {}", DateUtils.formatTimestamp(receiptReceived.getTimestamp()));
});
dbusconnection.addSigHandler(Signal.SyncMessageReceived.class, syncReceived -> {
- try {
- writer.println("Sync Envelope from: {} to: {}",
- syncReceived.getSource(),
- syncReceived.getDestination());
- writer.println("Timestamp: {}", DateUtils.formatTimestamp(syncReceived.getTimestamp()));
- writer.println("Body: {}", syncReceived.getMessage());
- if (syncReceived.getGroupId().length > 0) {
- writer.println("Group info:");
- writer.indentedWriter()
- .println("Id: {}", Base64.getEncoder().encodeToString(syncReceived.getGroupId()));
- }
- if (syncReceived.getAttachments().size() > 0) {
- writer.println("Attachments:");
- for (var attachment : syncReceived.getAttachments()) {
- writer.println("- Stored plaintext in: {}", attachment);
- }
+ writer.println("Sync Envelope from: {} to: {}",
+ syncReceived.getSource(),
+ syncReceived.getDestination());
+ writer.println("Timestamp: {}", DateUtils.formatTimestamp(syncReceived.getTimestamp()));
+ writer.println("Body: {}", syncReceived.getMessage());
+ if (syncReceived.getGroupId().length > 0) {
+ writer.println("Group info:");
+ writer.indentedWriter()
+ .println("Id: {}", Base64.getEncoder().encodeToString(syncReceived.getGroupId()));
+ }
+ if (syncReceived.getAttachments().size() > 0) {
+ writer.println("Attachments:");
+ for (var attachment : syncReceived.getAttachments()) {
+ writer.println("- Stored plaintext in: {}", attachment);
}
- writer.println();
- } catch (IOException e) {
- e.printStackTrace();
}
+ writer.println();
});
}
} catch (DBusException e) {
- e.printStackTrace();
- return 2;
+ logger.error("Dbus client failed", e);
+ throw new UnexpectedErrorException("Dbus client failed");
}
while (true) {
try {
Thread.sleep(10000);
- } catch (InterruptedException e) {
- return 0;
+ } catch (InterruptedException ignored) {
+ return;
}
}
}
@Override
- public int handleCommand(final Namespace ns, final Manager m) {
+ public void handleCommand(final Namespace ns, final Manager m) throws CommandException {
var inJson = ns.get("output") == OutputType.JSON || ns.getBoolean("json");
// TODO delete later when "json" variable is removed
returnOnTimeout,
ignoreAttachments,
handler);
- return 0;
} catch (IOException e) {
- System.err.println("Error while receiving messages: " + e.getMessage());
- return 3;
+ throw new IOErrorException("Error while receiving messages: " + e.getMessage());
} catch (AssertionError e) {
handleAssertionError(e);
- return 1;
+ throw e;
}
}
}
import net.sourceforge.argparse4j.inf.Namespace;
import net.sourceforge.argparse4j.inf.Subparser;
+import org.asamk.signal.commands.exceptions.CommandException;
+import org.asamk.signal.commands.exceptions.IOErrorException;
+import org.asamk.signal.commands.exceptions.UserErrorException;
import org.asamk.signal.manager.RegistrationManager;
import org.whispersystems.signalservice.api.push.exceptions.CaptchaRequiredException;
}
@Override
- public int handleCommand(final Namespace ns, final RegistrationManager m) {
+ public void handleCommand(final Namespace ns, final RegistrationManager m) throws CommandException {
final boolean voiceVerification = ns.getBoolean("voice");
final var captcha = ns.getString("captcha");
try {
m.register(voiceVerification, captcha);
- return 0;
} catch (CaptchaRequiredException e) {
+ String message;
if (captcha == null) {
- System.err.println("Captcha required for verification, use --captcha CAPTCHA");
- System.err.println("To get the token, go to https://signalcaptchas.org/registration/generate.html");
- System.err.println("Check the developer tools (F12) console for a failed redirect to signalcaptcha://");
- System.err.println("Everything after signalcaptcha:// is the captcha token.");
+ message = "Captcha required for verification, use --captcha CAPTCHA\n"
+ + "To get the token, go to https://signalcaptchas.org/registration/generate.html\n"
+ + "Check the developer tools (F12) console for a failed redirect to signalcaptcha://\n"
+ + "Everything after signalcaptcha:// is the captcha token.";
} else {
- System.err.println("Invalid captcha given.");
+ message = "Invalid captcha given.";
}
- return 1;
+ throw new UserErrorException(message);
} catch (IOException e) {
- System.err.println("Request verify error: " + e.getMessage());
- return 3;
+ throw new IOErrorException("Request verify error: " + e.getMessage());
}
}
}
import net.sourceforge.argparse4j.inf.Namespace;
+import org.asamk.signal.commands.exceptions.CommandException;
import org.asamk.signal.manager.RegistrationManager;
public interface RegistrationCommand extends Command {
- int handleCommand(Namespace ns, RegistrationManager m);
+ void handleCommand(Namespace ns, RegistrationManager m) throws CommandException;
}
import net.sourceforge.argparse4j.inf.Namespace;
import net.sourceforge.argparse4j.inf.Subparser;
+import org.asamk.signal.commands.exceptions.CommandException;
+import org.asamk.signal.commands.exceptions.IOErrorException;
import org.asamk.signal.manager.Manager;
import java.io.IOException;
}
@Override
- public int handleCommand(final Namespace ns, final Manager m) {
+ public void handleCommand(final Namespace ns, final Manager m) throws CommandException {
try {
int deviceId = ns.getInt("deviceId");
m.removeLinkedDevices(deviceId);
- return 0;
} catch (IOException e) {
- e.printStackTrace();
- return 3;
+ throw new IOErrorException("Error while removing device: " + e.getMessage());
}
}
}
import net.sourceforge.argparse4j.inf.Namespace;
import net.sourceforge.argparse4j.inf.Subparser;
+import org.asamk.signal.commands.exceptions.CommandException;
+import org.asamk.signal.commands.exceptions.IOErrorException;
+import org.asamk.signal.commands.exceptions.UnexpectedErrorException;
import org.asamk.signal.manager.Manager;
import org.whispersystems.libsignal.util.guava.Optional;
import org.whispersystems.signalservice.internal.contacts.crypto.UnauthenticatedResponseException;
}
@Override
- public int handleCommand(final Namespace ns, final Manager m) {
+ public void handleCommand(final Namespace ns, final Manager m) throws CommandException {
try {
m.setRegistrationLockPin(Optional.absent());
- return 0;
} catch (UnauthenticatedResponseException e) {
- System.err.println("Remove pin error: " + e.getMessage());
- return 2;
+ throw new UnexpectedErrorException("Remove pin failed with unauthenticated response: " + e.getMessage());
} catch (IOException e) {
- System.err.println("Remove pin error: " + e.getMessage());
- return 3;
+ throw new IOErrorException("Remove pin error: " + e.getMessage());
}
}
}
import org.asamk.Signal;
import org.asamk.signal.PlainTextWriterImpl;
+import org.asamk.signal.commands.exceptions.CommandException;
+import org.asamk.signal.commands.exceptions.UnexpectedErrorException;
+import org.asamk.signal.commands.exceptions.UntrustedKeyErrorException;
+import org.asamk.signal.commands.exceptions.UserErrorException;
import org.asamk.signal.manager.groups.GroupIdFormatException;
import org.asamk.signal.util.IOUtils;
import org.asamk.signal.util.Util;
import java.util.List;
import static org.asamk.signal.util.ErrorUtils.handleAssertionError;
-import static org.asamk.signal.util.ErrorUtils.handleGroupIdFormatException;
public class SendCommand implements DbusCommand {
}
@Override
- public int handleCommand(final Namespace ns, final Signal signal) {
+ public void handleCommand(final Namespace ns, final Signal signal) throws CommandException {
final List<String> recipients = ns.getList("recipient");
final var isEndSession = ns.getBoolean("endsession");
final var groupIdString = ns.getString("group");
final var noRecipients = recipients == null || recipients.isEmpty();
if ((noRecipients && isEndSession) || (noRecipients && groupIdString == null && !isNoteToSelf)) {
- System.err.println("No recipients given");
- System.err.println("Aborting sending.");
- return 1;
+ throw new UserErrorException("No recipients given");
}
if (!noRecipients && groupIdString != null) {
- System.err.println("You cannot specify recipients by phone number and groups at the same time");
- return 1;
+ throw new UserErrorException("You cannot specify recipients by phone number and groups at the same time");
}
if (!noRecipients && isNoteToSelf) {
- System.err.println("You cannot specify recipients by phone number and not to self at the same time");
- return 1;
+ throw new UserErrorException(
+ "You cannot specify recipients by phone number and not to self at the same time");
}
if (isEndSession) {
try {
signal.sendEndSessionMessage(recipients);
- return 0;
+ return;
} catch (AssertionError e) {
handleAssertionError(e);
- return 1;
+ throw e;
} catch (Signal.Error.UntrustedIdentity e) {
- System.err.println("Failed to send message: " + e.getMessage());
- return 4;
+ throw new UntrustedKeyErrorException("Failed to send message: " + e.getMessage());
} catch (DBusExecutionException e) {
- System.err.println("Failed to send message: " + e.getMessage());
- return 2;
+ throw new UnexpectedErrorException("Failed to send message: " + e.getMessage());
}
}
try {
messageText = IOUtils.readAll(System.in, Charset.defaultCharset());
} catch (IOException e) {
- System.err.println("Failed to read message from stdin: " + e.getMessage());
- System.err.println("Aborting sending.");
- return 1;
+ throw new UserErrorException("Failed to read message from stdin: " + e.getMessage());
}
}
try {
groupId = Util.decodeGroupId(groupIdString).serialize();
} catch (GroupIdFormatException e) {
- handleGroupIdFormatException(e);
- return 1;
+ throw new UserErrorException("Invalid group id:" + e.getMessage());
}
try {
var timestamp = signal.sendGroupMessage(messageText, attachments, groupId);
writer.println("{}", timestamp);
- return 0;
+ return;
} catch (AssertionError e) {
handleAssertionError(e);
- return 1;
+ throw e;
} catch (DBusExecutionException e) {
- System.err.println("Failed to send group message: " + e.getMessage());
- return 2;
- } catch (IOException e) {
- e.printStackTrace();
- return 3;
+ throw new UnexpectedErrorException("Failed to send group message: " + e.getMessage());
}
}
try {
var timestamp = signal.sendNoteToSelfMessage(messageText, attachments);
writer.println("{}", timestamp);
- return 0;
+ return;
} catch (AssertionError e) {
handleAssertionError(e);
- return 1;
+ throw e;
} catch (Signal.Error.UntrustedIdentity e) {
- System.err.println("Failed to send message: " + e.getMessage());
- return 4;
+ throw new UntrustedKeyErrorException("Failed to send message: " + e.getMessage());
} catch (DBusExecutionException e) {
- System.err.println("Failed to send note to self message: " + e.getMessage());
- return 2;
- } catch (IOException e) {
- e.printStackTrace();
- return 3;
+ throw new UnexpectedErrorException("Failed to send note to self message: " + e.getMessage());
}
}
try {
var timestamp = signal.sendMessage(messageText, attachments, recipients);
writer.println("{}", timestamp);
- return 0;
} catch (AssertionError e) {
handleAssertionError(e);
- return 1;
+ throw e;
} catch (UnknownObject e) {
- System.err.println("Failed to find dbus object, maybe missing the -u flag: " + e.getMessage());
- return 1;
+ throw new UserErrorException("Failed to find dbus object, maybe missing the -u flag: " + e.getMessage());
} catch (Signal.Error.UntrustedIdentity e) {
- System.err.println("Failed to send message: " + e.getMessage());
- return 4;
+ throw new UntrustedKeyErrorException("Failed to send message: " + e.getMessage());
} catch (DBusExecutionException e) {
- System.err.println("Failed to send message: " + e.getMessage());
- return 2;
- } catch (IOException e) {
- e.printStackTrace();
- return 3;
+ throw new UnexpectedErrorException("Failed to send message: " + e.getMessage());
}
}
}
import net.sourceforge.argparse4j.inf.Namespace;
import net.sourceforge.argparse4j.inf.Subparser;
+import org.asamk.signal.commands.exceptions.CommandException;
+import org.asamk.signal.commands.exceptions.IOErrorException;
+import org.asamk.signal.commands.exceptions.UntrustedKeyErrorException;
import org.asamk.signal.manager.Manager;
import org.whispersystems.signalservice.api.crypto.UntrustedIdentityException;
}
@Override
- public int handleCommand(final Namespace ns, final Manager m) {
+ public void handleCommand(final Namespace ns, final Manager m) throws CommandException {
try {
m.sendContacts();
- return 0;
} catch (UntrustedIdentityException e) {
- System.err.println("SendContacts error: " + e.getMessage());
- return 2;
+ throw new UntrustedKeyErrorException("SendContacts error: " + e.getMessage());
} catch (IOException e) {
- System.err.println("SendContacts error: " + e.getMessage());
- return 3;
+ throw new IOErrorException("SendContacts error: " + e.getMessage());
}
}
}
import net.sourceforge.argparse4j.inf.Subparser;
import org.asamk.signal.PlainTextWriterImpl;
+import org.asamk.signal.commands.exceptions.CommandException;
+import org.asamk.signal.commands.exceptions.IOErrorException;
+import org.asamk.signal.commands.exceptions.UserErrorException;
import org.asamk.signal.manager.Manager;
+import org.asamk.signal.manager.groups.GroupId;
import org.asamk.signal.manager.groups.GroupIdFormatException;
import org.asamk.signal.manager.groups.GroupNotFoundException;
import org.asamk.signal.manager.groups.NotAGroupMemberException;
import java.util.List;
import static org.asamk.signal.util.ErrorUtils.handleAssertionError;
-import static org.asamk.signal.util.ErrorUtils.handleGroupIdFormatException;
-import static org.asamk.signal.util.ErrorUtils.handleGroupNotFoundException;
-import static org.asamk.signal.util.ErrorUtils.handleIOException;
-import static org.asamk.signal.util.ErrorUtils.handleInvalidNumberException;
-import static org.asamk.signal.util.ErrorUtils.handleNotAGroupMemberException;
import static org.asamk.signal.util.ErrorUtils.handleTimestampAndSendMessageResults;
public class SendReactionCommand implements LocalCommand {
}
@Override
- public int handleCommand(final Namespace ns, final Manager m) {
+ public void handleCommand(final Namespace ns, final Manager m) throws CommandException {
final List<String> recipients = ns.getList("recipient");
final var groupIdString = ns.getString("group");
final var noRecipients = recipients == null || recipients.isEmpty();
if (noRecipients && groupIdString == null) {
- System.err.println("No recipients given");
- System.err.println("Aborting sending.");
- return 1;
+ throw new UserErrorException("No recipients given");
}
if (!noRecipients && groupIdString != null) {
- System.err.println("You cannot specify recipients by phone number and groups at the same time");
- return 1;
+ throw new UserErrorException("You cannot specify recipients by phone number and groups at the same time");
}
final var emoji = ns.getString("emoji");
final var targetAuthor = ns.getString("target_author");
final long targetTimestamp = ns.getLong("target_timestamp");
- try {
- final var writer = new PlainTextWriterImpl(System.out);
+ final var writer = new PlainTextWriterImpl(System.out);
+
+ final Pair<Long, List<SendMessageResult>> results;
+
+ GroupId groupId = null;
+ if (groupId != null) {
+ try {
+ groupId = Util.decodeGroupId(groupIdString);
+ } catch (GroupIdFormatException e) {
+ throw new UserErrorException("Invalid group id:" + e.getMessage());
+ }
+ }
- final Pair<Long, List<SendMessageResult>> results;
- if (groupIdString != null) {
- var groupId = Util.decodeGroupId(groupIdString);
+ try {
+ if (groupId != null) {
results = m.sendGroupMessageReaction(emoji, isRemove, targetAuthor, targetTimestamp, groupId);
} else {
results = m.sendMessageReaction(emoji, isRemove, targetAuthor, targetTimestamp, recipients);
}
- return handleTimestampAndSendMessageResults(writer, results.first(), results.second());
+ handleTimestampAndSendMessageResults(writer, results.first(), results.second());
} catch (IOException e) {
- handleIOException(e);
- return 3;
+ throw new IOErrorException("Failed to send message: " + e.getMessage());
} catch (AssertionError e) {
handleAssertionError(e);
- return 1;
+ throw e;
} catch (GroupNotFoundException e) {
- handleGroupNotFoundException(e);
- return 1;
+ throw new UserErrorException("Failed to send to group: " + e.getMessage());
} catch (NotAGroupMemberException e) {
- handleNotAGroupMemberException(e);
- return 1;
- } catch (GroupIdFormatException e) {
- handleGroupIdFormatException(e);
- return 1;
+ throw new UserErrorException("Failed to send to group: " + e.getMessage());
} catch (InvalidNumberException e) {
- handleInvalidNumberException(e);
- return 1;
+ throw new UserErrorException("Invalid number: " + e.getMessage());
}
}
}
import net.sourceforge.argparse4j.inf.Namespace;
import net.sourceforge.argparse4j.inf.Subparser;
+import org.asamk.signal.commands.exceptions.CommandException;
+import org.asamk.signal.commands.exceptions.IOErrorException;
+import org.asamk.signal.commands.exceptions.UnexpectedErrorException;
import org.asamk.signal.manager.Manager;
import org.whispersystems.libsignal.util.guava.Optional;
import org.whispersystems.signalservice.internal.contacts.crypto.UnauthenticatedResponseException;
}
@Override
- public int handleCommand(final Namespace ns, final Manager m) {
+ public void handleCommand(final Namespace ns, final Manager m) throws CommandException {
try {
var registrationLockPin = ns.getString("registrationLockPin");
m.setRegistrationLockPin(Optional.of(registrationLockPin));
- return 0;
} catch (UnauthenticatedResponseException e) {
- System.err.println("Set pin error: " + e.getMessage());
- return 2;
+ throw new UnexpectedErrorException("Set pin error failed with unauthenticated response: " + e.getMessage());
} catch (IOException e) {
- System.err.println("Set pin error: " + e.getMessage());
- return 3;
+ throw new IOErrorException("Set pin error: " + e.getMessage());
}
}
}
import net.sourceforge.argparse4j.inf.Namespace;
import net.sourceforge.argparse4j.inf.Subparser;
+import org.asamk.signal.commands.exceptions.CommandException;
+import org.asamk.signal.commands.exceptions.UserErrorException;
import org.asamk.signal.manager.Manager;
-import org.asamk.signal.util.ErrorUtils;
import org.asamk.signal.util.Hex;
import org.whispersystems.signalservice.api.util.InvalidNumberException;
}
@Override
- public int handleCommand(final Namespace ns, final Manager m) {
+ public void handleCommand(final Namespace ns, final Manager m) throws CommandException {
var number = ns.getString("number");
if (ns.getBoolean("trust_all_known_keys")) {
var res = m.trustIdentityAllKeys(number);
if (!res) {
- System.err.println("Failed to set the trust for this number, make sure the number is correct.");
- return 1;
+ throw new UserErrorException("Failed to set the trust for this number, make sure the number is correct.");
}
} else {
var safetyNumber = ns.getString("verified_safety_number");
try {
fingerprintBytes = Hex.toByteArray(safetyNumber.toLowerCase(Locale.ROOT));
} catch (Exception e) {
- System.err.println(
+ throw new UserErrorException(
"Failed to parse the fingerprint, make sure the fingerprint is a correctly encoded hex string without additional characters.");
- return 1;
}
boolean res;
try {
res = m.trustIdentityVerified(number, fingerprintBytes);
} catch (InvalidNumberException e) {
- ErrorUtils.handleInvalidNumberException(e);
- return 1;
+ throw new UserErrorException("Failed to parse recipient: " + e.getMessage());
}
if (!res) {
- System.err.println(
+ throw new UserErrorException(
"Failed to set the trust for the fingerprint of this number, make sure the number and the fingerprint are correct.");
- return 1;
}
} else if (safetyNumber.length() == 60) {
boolean res;
try {
res = m.trustIdentityVerifiedSafetyNumber(number, safetyNumber);
} catch (InvalidNumberException e) {
- ErrorUtils.handleInvalidNumberException(e);
- return 1;
+ throw new UserErrorException("Failed to parse recipient: " + e.getMessage());
}
if (!res) {
- System.err.println(
+ throw new UserErrorException(
"Failed to set the trust for the safety number of this phone number, make sure the phone number and the safety number are correct.");
- return 1;
}
} else {
- System.err.println(
+ throw new UserErrorException(
"Safety number has invalid format, either specify the old hex fingerprint or the new safety number");
- return 1;
}
} else {
- System.err.println(
+ throw new UserErrorException(
"You need to specify the fingerprint/safety number you have verified with -v SAFETY_NUMBER");
- return 1;
}
}
- return 0;
}
}
import net.sourceforge.argparse4j.inf.Namespace;
import net.sourceforge.argparse4j.inf.Subparser;
+import org.asamk.signal.commands.exceptions.CommandException;
import org.asamk.signal.manager.Manager;
import org.asamk.signal.manager.groups.GroupIdFormatException;
import org.asamk.signal.manager.groups.GroupNotFoundException;
import org.asamk.signal.util.Util;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
import org.whispersystems.signalservice.api.util.InvalidNumberException;
public class UnblockCommand implements LocalCommand {
+ private final static Logger logger = LoggerFactory.getLogger(UnblockCommand.class);
+
@Override
public void attachToSubparser(final Subparser subparser) {
subparser.addArgument("contact").help("Contact number").nargs("*");
}
@Override
- public int handleCommand(final Namespace ns, final Manager m) {
- for (var contact_number : ns.<String>getList("contact")) {
+ public void handleCommand(final Namespace ns, final Manager m) throws CommandException {
+ for (var contactNumber : ns.<String>getList("contact")) {
try {
- m.setContactBlocked(contact_number, false);
+ m.setContactBlocked(contactNumber, false);
} catch (InvalidNumberException e) {
- System.err.println(e.getMessage());
+ logger.warn("Invalid number: {}", contactNumber);
}
}
try {
var groupId = Util.decodeGroupId(groupIdString);
m.setGroupBlocked(groupId, false);
- } catch (GroupIdFormatException | GroupNotFoundException e) {
- System.err.println(e.getMessage());
+ } catch (GroupIdFormatException e) {
+ logger.warn("Invalid group id: {}", groupIdString);
+ } catch (GroupNotFoundException e) {
+ logger.warn("Unknown group id: {}", groupIdString);
}
}
}
-
- return 0;
}
}
import net.sourceforge.argparse4j.inf.Namespace;
import net.sourceforge.argparse4j.inf.Subparser;
+import org.asamk.signal.commands.exceptions.CommandException;
+import org.asamk.signal.commands.exceptions.IOErrorException;
import org.asamk.signal.manager.Manager;
import java.io.IOException;
}
@Override
- public int handleCommand(final Namespace ns, final Manager m) {
+ public void handleCommand(final Namespace ns, final Manager m) throws CommandException {
try {
m.unregister();
- return 0;
} catch (IOException e) {
- System.err.println("Unregister error: " + e.getMessage());
- return 3;
+ throw new IOErrorException("Unregister error: " + e.getMessage());
}
}
}
import net.sourceforge.argparse4j.inf.Namespace;
import net.sourceforge.argparse4j.inf.Subparser;
+import org.asamk.signal.commands.exceptions.CommandException;
+import org.asamk.signal.commands.exceptions.IOErrorException;
import org.asamk.signal.manager.Manager;
import java.io.IOException;
}
@Override
- public int handleCommand(final Namespace ns, final Manager m) {
+ public void handleCommand(final Namespace ns, final Manager m) throws CommandException {
try {
m.updateAccountAttributes();
- return 0;
} catch (IOException e) {
- System.err.println("UpdateAccount error: " + e.getMessage());
- return 3;
+ throw new IOErrorException("UpdateAccount error: " + e.getMessage());
}
}
}
import net.sourceforge.argparse4j.inf.Namespace;
import net.sourceforge.argparse4j.inf.Subparser;
+import org.asamk.signal.commands.exceptions.CommandException;
+import org.asamk.signal.commands.exceptions.IOErrorException;
+import org.asamk.signal.commands.exceptions.UserErrorException;
import org.asamk.signal.manager.Manager;
import org.whispersystems.signalservice.api.util.InvalidNumberException;
}
@Override
- public int handleCommand(final Namespace ns, final Manager m) {
+ public void handleCommand(final Namespace ns, final Manager m) throws CommandException {
var number = ns.getString("number");
var name = ns.getString("name");
m.setExpirationTimer(number, expiration);
}
} catch (InvalidNumberException e) {
- System.err.println("Invalid contact number: " + e.getMessage());
- return 1;
+ throw new UserErrorException("Invalid contact number: " + e.getMessage());
} catch (IOException e) {
- System.err.println("Update contact error: " + e.getMessage());
- return 3;
+ throw new IOErrorException("Update contact error: " + e.getMessage());
}
-
- return 0;
}
}
import org.asamk.Signal;
import org.asamk.signal.PlainTextWriterImpl;
+import org.asamk.signal.commands.exceptions.CommandException;
+import org.asamk.signal.commands.exceptions.UnexpectedErrorException;
+import org.asamk.signal.commands.exceptions.UserErrorException;
import org.asamk.signal.manager.groups.GroupIdFormatException;
import org.asamk.signal.util.Util;
import org.freedesktop.dbus.exceptions.DBusExecutionException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import java.io.IOException;
import java.util.ArrayList;
import java.util.Base64;
import java.util.List;
import static org.asamk.signal.util.ErrorUtils.handleAssertionError;
-import static org.asamk.signal.util.ErrorUtils.handleGroupIdFormatException;
public class UpdateGroupCommand implements DbusCommand {
}
@Override
- public int handleCommand(final Namespace ns, final Signal signal) {
+ public void handleCommand(final Namespace ns, final Signal signal) throws CommandException {
final var writer = new PlainTextWriterImpl(System.out);
byte[] groupId = null;
if (ns.getString("group") != null) {
try {
groupId = Util.decodeGroupId(ns.getString("group")).serialize();
} catch (GroupIdFormatException e) {
- handleGroupIdFormatException(e);
- return 1;
+ throw new UserErrorException("Invalid group id:" + e.getMessage());
}
}
if (groupId == null) {
try {
var newGroupId = signal.updateGroup(groupId, groupName, groupMembers, groupAvatar);
if (groupId.length != newGroupId.length) {
- try {
- writer.println("Creating new group \"{}\" …", Base64.getEncoder().encodeToString(newGroupId));
- } catch (IOException e) {
- e.printStackTrace();
- return 3;
- }
+ writer.println("Created new group: \"{}\"", Base64.getEncoder().encodeToString(newGroupId));
}
- return 0;
} catch (AssertionError e) {
handleAssertionError(e);
- return 1;
+ throw e;
} catch (Signal.Error.AttachmentInvalid e) {
- System.err.println("Failed to add avatar attachment for group\": " + e.getMessage());
- return 1;
+ throw new UserErrorException("Failed to add avatar attachment for group\": " + e.getMessage());
} catch (DBusExecutionException e) {
- System.err.println("Failed to send message: " + e.getMessage());
- return 2;
+ throw new UnexpectedErrorException("Failed to send message: " + e.getMessage());
}
}
}
import net.sourceforge.argparse4j.inf.Namespace;
import net.sourceforge.argparse4j.inf.Subparser;
+import org.asamk.signal.commands.exceptions.CommandException;
+import org.asamk.signal.commands.exceptions.IOErrorException;
import org.asamk.signal.manager.Manager;
import org.whispersystems.libsignal.util.guava.Optional;
}
@Override
- public int handleCommand(final Namespace ns, final Manager m) {
+ public void handleCommand(final Namespace ns, final Manager m) throws CommandException {
var name = ns.getString("name");
var about = ns.getString("about");
var aboutEmoji = ns.getString("about_emoji");
var avatarPath = ns.getString("avatar");
boolean removeAvatar = ns.getBoolean("remove_avatar");
+ Optional<File> avatarFile = removeAvatar
+ ? Optional.absent()
+ : avatarPath == null ? null : Optional.of(new File(avatarPath));
+
try {
- Optional<File> avatarFile = removeAvatar
- ? Optional.absent()
- : avatarPath == null ? null : Optional.of(new File(avatarPath));
m.setProfile(name, about, aboutEmoji, avatarFile);
} catch (IOException e) {
- System.err.println("Update profile error: " + e.getMessage());
- return 3;
+ throw new IOErrorException("Update profile error: " + e.getMessage());
}
-
- return 0;
}
}
import net.sourceforge.argparse4j.inf.Subparser;
import org.asamk.signal.PlainTextWriterImpl;
+import org.asamk.signal.commands.exceptions.CommandException;
+import org.asamk.signal.commands.exceptions.IOErrorException;
+import org.asamk.signal.commands.exceptions.UserErrorException;
import org.asamk.signal.manager.Manager;
import org.asamk.signal.manager.StickerPackInvalidException;
import org.slf4j.Logger;
}
@Override
- public int handleCommand(final Namespace ns, final Manager m) {
+ public void handleCommand(final Namespace ns, final Manager m) throws CommandException {
final var writer = new PlainTextWriterImpl(System.out);
+ var path = new File(ns.getString("path"));
+
try {
- var path = new File(ns.getString("path"));
var url = m.uploadStickerPack(path);
writer.println("{}", url);
- return 0;
} catch (IOException e) {
- System.err.println("Upload error: " + e.getMessage());
- return 3;
+ throw new IOErrorException("Upload error: " + e.getMessage());
} catch (StickerPackInvalidException e) {
- System.err.println("Invalid sticker pack: " + e.getMessage());
- return 1;
+ throw new UserErrorException("Invalid sticker pack: " + e.getMessage());
}
}
}
import net.sourceforge.argparse4j.inf.Namespace;
import net.sourceforge.argparse4j.inf.Subparser;
+import org.asamk.signal.commands.exceptions.CommandException;
+import org.asamk.signal.commands.exceptions.IOErrorException;
+import org.asamk.signal.commands.exceptions.UnexpectedErrorException;
+import org.asamk.signal.commands.exceptions.UserErrorException;
import org.asamk.signal.manager.RegistrationManager;
import org.whispersystems.signalservice.api.KeyBackupServicePinException;
import org.whispersystems.signalservice.api.KeyBackupSystemNoDataException;
}
@Override
- public int handleCommand(final Namespace ns, final RegistrationManager m) {
+ public void handleCommand(final Namespace ns, final RegistrationManager m) throws CommandException {
+ var verificationCode = ns.getString("verificationCode");
+ var pin = ns.getString("pin");
+
try {
- var verificationCode = ns.getString("verificationCode");
- var pin = ns.getString("pin");
m.verifyAccount(verificationCode, pin);
- return 0;
} catch (LockedException e) {
- System.err.println("Verification failed! This number is locked with a pin. Hours remaining until reset: "
- + (e.getTimeRemaining() / 1000 / 60 / 60));
- System.err.println("Use '--pin PIN_CODE' to specify the registration lock PIN");
- return 1;
+ throw new UserErrorException(
+ "Verification failed! This number is locked with a pin. Hours remaining until reset: "
+ + (e.getTimeRemaining() / 1000 / 60 / 60)
+ + "\nUse '--pin PIN_CODE' to specify the registration lock PIN");
} catch (KeyBackupServicePinException e) {
- System.err.println("Verification failed! Invalid pin, tries remaining: " + e.getTriesRemaining());
- return 1;
+ throw new UserErrorException("Verification failed! Invalid pin, tries remaining: " + e.getTriesRemaining());
} catch (KeyBackupSystemNoDataException e) {
- System.err.println("Verification failed! No KBS data.");
- return 3;
+ throw new UnexpectedErrorException("Verification failed! No KBS data.");
} catch (IOException e) {
- System.err.println("Verify error: " + e.getMessage());
- return 3;
+ throw new IOErrorException("Verify error: " + e.getMessage());
}
}
}
--- /dev/null
+package org.asamk.signal.commands.exceptions;
+
+public class CommandException extends Exception {
+
+ public CommandException(final String message) {
+ super(message);
+ }
+}
--- /dev/null
+package org.asamk.signal.commands.exceptions;
+
+public final class IOErrorException extends CommandException {
+
+ public IOErrorException(final String message) {
+ super(message);
+ }
+}
--- /dev/null
+package org.asamk.signal.commands.exceptions;
+
+public final class UnexpectedErrorException extends CommandException {
+
+ public UnexpectedErrorException(final String message) {
+ super(message);
+ }
+}
--- /dev/null
+package org.asamk.signal.commands.exceptions;
+
+public final class UntrustedKeyErrorException extends CommandException {
+
+ public UntrustedKeyErrorException(final String message) {
+ super(message);
+ }
+}
--- /dev/null
+package org.asamk.signal.commands.exceptions;
+
+public final class UserErrorException extends CommandException {
+
+ public UserErrorException(final String message) {
+ super(message);
+ }
+}
package org.asamk.signal.util;
import org.asamk.signal.PlainTextWriter;
-import org.asamk.signal.manager.groups.GroupIdFormatException;
-import org.asamk.signal.manager.groups.GroupNotFoundException;
-import org.asamk.signal.manager.groups.NotAGroupMemberException;
+import org.asamk.signal.commands.exceptions.CommandException;
+import org.asamk.signal.commands.exceptions.IOErrorException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
import org.whispersystems.signalservice.api.messages.SendMessageResult;
-import org.whispersystems.signalservice.api.util.InvalidNumberException;
-import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
public class ErrorUtils {
+ private final static Logger logger = LoggerFactory.getLogger(ErrorUtils.class);
+
private ErrorUtils() {
}
public static void handleAssertionError(AssertionError e) {
- System.err.println("Failed to send/receive message (Assertion): " + e.getMessage());
- e.printStackTrace();
- System.err.println(
- "If you use an Oracle JRE please check if you have unlimited strength crypto enabled, see README");
+ logger.warn("If you use an Oracle JRE please check if you have unlimited strength crypto enabled, see README");
}
- public static int handleTimestampAndSendMessageResults(
- PlainTextWriter writer,
- long timestamp,
- List<SendMessageResult> results
- ) throws IOException {
+ public static void handleTimestampAndSendMessageResults(
+ PlainTextWriter writer, long timestamp, List<SendMessageResult> results
+ ) throws CommandException {
if (timestamp != 0) {
writer.println("{}", timestamp);
}
var errors = getErrorMessagesFromSendMessageResults(results);
- return handleSendMessageResultErrors(errors);
+ handleSendMessageResultErrors(errors);
}
public static List<String> getErrorMessagesFromSendMessageResults(List<SendMessageResult> results) {
return null;
}
- private static int handleSendMessageResultErrors(List<String> errors) {
+ private static void handleSendMessageResultErrors(List<String> errors) throws CommandException {
if (errors.size() == 0) {
- return 0;
+ return;
}
- System.err.println("Failed to send (some) messages:");
+ var message = new StringBuilder();
+ message.append("Failed to send (some) messages:\n");
for (var error : errors) {
- System.err.println(error);
+ message.append(error).append("\n");
}
- return 3;
- }
-
- public static void handleIOException(IOException e) {
- System.err.println("Failed to send message: " + e.getMessage());
- }
-
- public static void handleGroupNotFoundException(GroupNotFoundException e) {
- System.err.println("Failed to send to group: " + e.getMessage());
- System.err.println("Aborting sending.");
- }
-
- public static void handleNotAGroupMemberException(NotAGroupMemberException e) {
- System.err.println("Failed to send to group: " + e.getMessage());
- System.err.println("Update the group on another device to readd the user to this group.");
- System.err.println("Aborting sending.");
- }
-
- public static void handleGroupIdFormatException(GroupIdFormatException e) {
- System.err.println(e.getMessage());
- System.err.println("Aborting sending.");
- }
-
- public static void handleInvalidNumberException(InvalidNumberException e) {
- System.err.println("Failed to parse recipient: " + e.getMessage());
- System.err.println("Aborting sending.");
+ throw new IOErrorException(message.toString());
}
}