From 138e94edb51eb1091fd67bd9a84a3808498d775f Mon Sep 17 00:00:00 2001 From: technillogue Date: Tue, 29 Dec 2020 19:12:58 -0500 Subject: [PATCH] moved code to a new stdio command file --- README.md | 2 +- signal-cli-script | 1 - .../org/asamk/signal/commands/Commands.java | 1 + .../asamk/signal/commands/DaemonCommand.java | 101 ++----------- .../asamk/signal/commands/StdioCommand.java | 134 ++++++++++++++++++ 5 files changed, 147 insertions(+), 92 deletions(-) delete mode 120000 signal-cli-script create mode 100644 src/main/java/org/asamk/signal/commands/StdioCommand.java diff --git a/README.md b/README.md index 60fa2f44..b0e1b8a3 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -This fork changes the daemon command to read commands as JSON from stdin instead of exporting a DBus interface. It also includes reactions in JSON output. +This fork adds a stdio command, which is similar to the daemon --dbus command but read commands as JSON from stdin instead of exporting a DBus interface. It also includes reactions in JSON output. Currently, only sendMessage is available. The JSON interface is {"command": "sendMessage", "recipient": number, "content": message, "details": {"attachments": []}}. The details field is optional. As far as I can tell, attachments must be full absolute file paths. diff --git a/signal-cli-script b/signal-cli-script deleted file mode 120000 index 4ce3c4d7..00000000 --- a/signal-cli-script +++ /dev/null @@ -1 +0,0 @@ -build/install/signal-cli/bin/signal-cli \ No newline at end of file diff --git a/src/main/java/org/asamk/signal/commands/Commands.java b/src/main/java/org/asamk/signal/commands/Commands.java index 183b40a0..6e5a003a 100644 --- a/src/main/java/org/asamk/signal/commands/Commands.java +++ b/src/main/java/org/asamk/signal/commands/Commands.java @@ -11,6 +11,7 @@ public class Commands { addCommand("addDevice", new AddDeviceCommand()); addCommand("block", new BlockCommand()); addCommand("daemon", new DaemonCommand()); + addCommand("stdio", new StdioCommand()); addCommand("link", new LinkCommand()); addCommand("listContacts", new ListContactsCommand()); addCommand("listDevices", new ListDevicesCommand()); diff --git a/src/main/java/org/asamk/signal/commands/DaemonCommand.java b/src/main/java/org/asamk/signal/commands/DaemonCommand.java index 0f65f5ae..2b983851 100644 --- a/src/main/java/org/asamk/signal/commands/DaemonCommand.java +++ b/src/main/java/org/asamk/signal/commands/DaemonCommand.java @@ -6,90 +6,17 @@ import net.sourceforge.argparse4j.inf.Subparser; import org.asamk.signal.DbusReceiveMessageHandler; import org.asamk.signal.JsonDbusReceiveMessageHandler; -import org.asamk.signal.ReceiveMessageHandler; -import org.asamk.signal.JsonReceiveMessageHandler; import org.asamk.signal.dbus.DbusSignalImpl; import org.asamk.signal.manager.Manager; -import org.asamk.signal.manager.AttachmentInvalidException; import org.freedesktop.dbus.connections.impl.DBusConnection; import org.freedesktop.dbus.exceptions.DBusException; -import java.io.BufferedReader; -import java.io.InputStream; -import java.io.InputStreamReader; import java.io.IOException; import java.util.concurrent.TimeUnit; -import java.util.Arrays; -import java.util.ArrayList; -import java.util.List; + import static org.asamk.signal.DbusConfig.SIGNAL_BUSNAME; import static org.asamk.signal.DbusConfig.SIGNAL_OBJECTPATH; import static org.asamk.signal.util.ErrorUtils.handleAssertionError; -import org.whispersystems.signalservice.api.push.exceptions.EncapsulatedExceptions; -import org.whispersystems.signalservice.api.util.InvalidNumberException; -import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.ObjectMapper; - -class JsonInterface { - public String commandName; - public String recipient; - public String content; - public JsonNode details; -} - - -class InputReader implements Runnable { - private volatile boolean alive = true; - private Manager m; - - public void terminate() { - this.alive = false; - } - InputReader (final Manager m) { - this.m = m; - } - - @Override - public void run() { - BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); - ObjectMapper jsonProcessor = new ObjectMapper(); - while (alive) { - try { - String in = br.readLine(); - if (in != null) { - JsonInterface command = jsonProcessor.readValue(in, JsonInterface.class); - if (command.commandName.equals("sendMessage")){ - List recipients = new ArrayList(); - recipients.add(command.recipient); - List attachments = new ArrayList<>(); - if (command.details != null && command.details.has("attachments") ) { - command.details.get("attachments").forEach(attachment -> { - if (attachment.isTextual()){ - attachments.add(attachment.asText()); - } - }); - } - try { - // verbosity flag? better yet, json acknowledgement with timestamp or message id? - System.out.println("sentMessage '" + command.content + "' to " + command.recipient); - this.m.sendMessage(command.content, attachments, recipients); - } catch (AssertionError | EncapsulatedExceptions| AttachmentInvalidException | InvalidNumberException e) { - System.err.println("error in sending message"); - e.printStackTrace(System.out); - } - } /* elif (command.commandName == "sendTyping") { - getMessageSender().sendTyping(signalServiceAddress?, ....) - }*/ - } - - } catch (IOException e) { - System.err.println(e); - alive = false; - } - - } - } -} public class DaemonCommand implements LocalCommand { @@ -112,7 +39,7 @@ public class DaemonCommand implements LocalCommand { System.err.println("User is not registered."); return 1; } -/* DBusConnection conn = null; + DBusConnection conn = null; try { try { DBusConnection.DBusBusType busType; @@ -121,9 +48,9 @@ public class DaemonCommand implements LocalCommand { } else { busType = DBusConnection.DBusBusType.SESSION; } -// conn = DBusConnection.getConnection(busType); -// conn.exportObject(SIGNAL_OBJECTPATH, new DbusSignalImpl(m)); -// conn.requestBusName(SIGNAL_BUSNAME); + conn = DBusConnection.getConnection(busType); + conn.exportObject(SIGNAL_OBJECTPATH, new DbusSignalImpl(m)); + conn.requestBusName(SIGNAL_BUSNAME); } catch (UnsatisfiedLinkError e) { System.err.println("Missing native library dependency for dbus service: " + e.getMessage()); return 1; @@ -131,17 +58,9 @@ public class DaemonCommand implements LocalCommand { e.printStackTrace(); return 2; } - */ boolean ignoreAttachments = ns.getBoolean("ignore_attachments"); - InputReader reader = new InputReader(m); - Thread readerThread = new Thread(reader); - readerThread.start(); try { - m.receiveMessagesAndReadStdin(1, TimeUnit.HOURS, false, ignoreAttachments, - ns.getBoolean("json") - ? new JsonReceiveMessageHandler(m) - : new ReceiveMessageHandler(m) - /*true*/); + m.receiveMessages(1, TimeUnit.HOURS, false, ignoreAttachments, ns.getBoolean("json") ? new JsonDbusReceiveMessageHandler(m, conn, SIGNAL_OBJECTPATH) : new DbusReceiveMessageHandler(m, conn, SIGNAL_OBJECTPATH)); return 0; } catch (IOException e) { System.err.println("Error while receiving messages: " + e.getMessage()); @@ -149,9 +68,11 @@ public class DaemonCommand implements LocalCommand { } catch (AssertionError e) { handleAssertionError(e); return 1; - } finally { - reader.terminate(); } - + } finally { + if (conn != null) { + conn.disconnect(); + } + } } } diff --git a/src/main/java/org/asamk/signal/commands/StdioCommand.java b/src/main/java/org/asamk/signal/commands/StdioCommand.java new file mode 100644 index 00000000..3e441fcd --- /dev/null +++ b/src/main/java/org/asamk/signal/commands/StdioCommand.java @@ -0,0 +1,134 @@ +package org.asamk.signal.commands; + +import net.sourceforge.argparse4j.impl.Arguments; +import net.sourceforge.argparse4j.inf.Namespace; +import net.sourceforge.argparse4j.inf.Subparser; + +import org.asamk.signal.DbusReceiveMessageHandler; +import org.asamk.signal.JsonDbusReceiveMessageHandler; +import org.asamk.signal.ReceiveMessageHandler; +import org.asamk.signal.JsonReceiveMessageHandler; +import org.asamk.signal.dbus.DbusSignalImpl; +import org.asamk.signal.manager.Manager; +import org.asamk.signal.manager.AttachmentInvalidException; +import org.freedesktop.dbus.connections.impl.DBusConnection; +import org.freedesktop.dbus.exceptions.DBusException; + +import java.io.BufferedReader; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.IOException; +import java.util.concurrent.TimeUnit; +import java.util.Arrays; +import java.util.ArrayList; +import java.util.List; +import static org.asamk.signal.DbusConfig.SIGNAL_BUSNAME; +import static org.asamk.signal.DbusConfig.SIGNAL_OBJECTPATH; +import static org.asamk.signal.util.ErrorUtils.handleAssertionError; +import org.whispersystems.signalservice.api.push.exceptions.EncapsulatedExceptions; +import org.whispersystems.signalservice.api.util.InvalidNumberException; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; + +class JsonInterface { + public String commandName; + public String recipient; + public String content; + public JsonNode details; +} + + +class InputReader implements Runnable { + private volatile boolean alive = true; + private Manager m; + + public void terminate() { + this.alive = false; + } + InputReader (final Manager m) { + this.m = m; + } + + @Override + public void run() { + BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); + ObjectMapper jsonProcessor = new ObjectMapper(); + while (alive) { + try { + String in = br.readLine(); + if (in != null) { + JsonInterface command = jsonProcessor.readValue(in, JsonInterface.class); + if (command.commandName.equals("sendMessage")){ + List recipients = new ArrayList(); + recipients.add(command.recipient); + List attachments = new ArrayList<>(); + if (command.details != null && command.details.has("attachments") ) { + command.details.get("attachments").forEach(attachment -> { + if (attachment.isTextual()){ + attachments.add(attachment.asText()); + } + }); + } + try { + // verbosity flag? better yet, json acknowledgement with timestamp or message id? + System.out.println("sentMessage '" + command.content + "' to " + command.recipient); + this.m.sendMessage(command.content, attachments, recipients); + } catch (AssertionError | EncapsulatedExceptions| AttachmentInvalidException | InvalidNumberException e) { + System.err.println("error in sending message"); + e.printStackTrace(System.out); + } + } /* elif (command.commandName == "sendTyping") { + getMessageSender().sendTyping(signalServiceAddress?, ....) + }*/ + } + + } catch (IOException e) { + System.err.println(e); + alive = false; + } + + } + } +} + +public class StdioCommand implements LocalCommand { + + @Override + public void attachToSubparser(final Subparser subparser) { + subparser.addArgument("--ignore-attachments") + .help("Don’t download attachments of received messages.") + .action(Arguments.storeTrue()); + subparser.addArgument("--json") // should maybe remove this + .help("Output received messages in json format, one json object per line.") + .action(Arguments.storeTrue()); + } + + @Override + public int handleCommand(final Namespace ns, final Manager m) { + if (!m.isRegistered()) { + System.err.println("User is not registered."); + return 1; + } + boolean ignoreAttachments = ns.getBoolean("ignore_attachments"); + InputReader reader = new InputReader(m); + Thread readerThread = new Thread(reader); + readerThread.start(); + try { + m.receiveMessagesAndReadStdin(1, TimeUnit.HOURS, false, ignoreAttachments, + ns.getBoolean("json") + ? new JsonReceiveMessageHandler(m) + : new ReceiveMessageHandler(m) + /*true*/); + return 0; + } catch (IOException e) { + System.err.println("Error while receiving messages: " + e.getMessage()); + return 3; + } catch (AssertionError e) { + handleAssertionError(e); + return 1; + } finally { + reader.terminate(); + } + + } +}