]> nmode's Git Repositories - signal-cli/blobdiff - src/main/java/org/asamk/signal/Main.java
Update libsignal-service
[signal-cli] / src / main / java / org / asamk / signal / Main.java
index f9084516787b80314c52e66dabb6779029b5bd55..de076a87393e187970d9da64623814a3a9572386 100644 (file)
  */
 package org.asamk.signal;
 
+import com.fasterxml.jackson.annotation.JsonAutoDetect;
+import com.fasterxml.jackson.annotation.PropertyAccessor;
+import com.fasterxml.jackson.core.JsonGenerator;
+import com.fasterxml.jackson.databind.DeserializationFeature;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.SerializationFeature;
+import com.fasterxml.jackson.databind.node.ObjectNode;
 import net.sourceforge.argparse4j.ArgumentParsers;
 import net.sourceforge.argparse4j.impl.Arguments;
 import net.sourceforge.argparse4j.inf.*;
@@ -24,7 +31,6 @@ import org.asamk.Signal;
 import org.asamk.signal.storage.contacts.ContactInfo;
 import org.asamk.signal.storage.groups.GroupInfo;
 import org.asamk.signal.storage.protocol.JsonIdentityKeyStore;
-import org.asamk.signal.util.Base64;
 import org.asamk.signal.util.Hex;
 import org.freedesktop.dbus.DBusConnection;
 import org.freedesktop.dbus.DBusSigHandler;
@@ -39,6 +45,7 @@ import org.whispersystems.signalservice.api.push.exceptions.EncapsulatedExceptio
 import org.whispersystems.signalservice.api.push.exceptions.NetworkFailureException;
 import org.whispersystems.signalservice.api.push.exceptions.UnregisteredUserException;
 import org.whispersystems.signalservice.api.util.PhoneNumberFormatter;
+import org.whispersystems.signalservice.internal.util.Base64;
 
 import java.io.File;
 import java.io.IOException;
@@ -390,6 +397,13 @@ public class Main {
                                     System.out.println();
                                 }
                             });
+                            dBusConn.addSigHandler(Signal.ReceiptReceived.class, new DBusSigHandler<Signal.ReceiptReceived>() {
+                                @Override
+                                public void handle(Signal.ReceiptReceived s) {
+                                    System.out.print(String.format("Receipt from: %s\nTimestamp: %s\n",
+                                            s.getSender(), formatTimestamp(s.getTimestamp())));
+                                }
+                            });
                         } catch (UnsatisfiedLinkError e) {
                             System.err.println("Missing native library dependency for dbus service: " + e.getMessage());
                             return 1;
@@ -420,7 +434,8 @@ public class Main {
                     }
                     boolean ignoreAttachments = ns.getBoolean("ignore_attachments");
                     try {
-                        m.receiveMessages((long) (timeout * 1000), TimeUnit.MILLISECONDS, returnOnTimeout, ignoreAttachments, new ReceiveMessageHandler(m));
+                        final Manager.ReceiveMessageHandler handler = ns.getBoolean("json") ? new JsonReceiveMessageHandler(m) : new ReceiveMessageHandler(m);
+                        m.receiveMessages((long) (timeout * 1000), TimeUnit.MILLISECONDS, returnOnTimeout, ignoreAttachments, handler);
                     } catch (IOException e) {
                         System.err.println("Error while receiving messages: " + e.getMessage());
                         return 3;
@@ -460,11 +475,7 @@ public class Main {
 
                     break;
                 case "updateGroup":
-                    if (dBusConn != null) {
-                        System.err.println("updateGroup is not yet implemented via dbus");
-                        return 1;
-                    }
-                    if (!m.isRegistered()) {
+                    if (dBusConn == null && !m.isRegistered()) {
                         System.err.println("User is not registered.");
                         return 1;
                     }
@@ -474,8 +485,23 @@ public class Main {
                         if (ns.getString("group") != null) {
                             groupId = decodeGroupId(ns.getString("group"));
                         }
-                        byte[] newGroupId = m.sendUpdateGroupMessage(groupId, ns.getString("name"), ns.<String>getList("member"), ns.getString("avatar"));
                         if (groupId == null) {
+                            groupId = new byte[0];
+                        }
+                        String groupName = ns.getString("name");
+                        if (groupName == null) {
+                            groupName = "";
+                        }
+                        List<String> groupMembers = ns.<String>getList("member");
+                        if (groupMembers == null) {
+                            groupMembers = new ArrayList<String>();
+                        }
+                        String groupAvatar = ns.getString("avatar");
+                        if (groupAvatar == null) {
+                            groupAvatar = "";
+                        }
+                        byte[] newGroupId = ts.updateGroup(groupId, groupName, groupMembers, groupAvatar);
+                        if (groupId.length != newGroupId.length) {
                             System.out.println("Creating new group \"" + Base64.encodeBytes(newGroupId) + "\" …");
                         }
                     } catch (IOException e) {
@@ -811,6 +837,9 @@ public class Main {
         parserReceive.addArgument("--ignore-attachments")
                 .help("Don’t download attachments of received messages.")
                 .action(Arguments.storeTrue());
+        parserReceive.addArgument("--json")
+                .help("Output received messages in json format, one json object per line.")
+                .action(Arguments.storeTrue());
 
         Subparser parserDaemon = subparsers.addParser("daemon");
         parserDaemon.addArgument("--system")
@@ -927,8 +956,13 @@ public class Main {
                         SignalServiceSyncMessage syncMessage = content.getSyncMessage().get();
 
                         if (syncMessage.getContacts().isPresent()) {
-                            System.out.println("Received sync contacts");
-                            printAttachment(syncMessage.getContacts().get());
+                            final ContactsMessage contactsMessage = syncMessage.getContacts().get();
+                            if (contactsMessage.isComplete()) {
+                                System.out.println("Received complete sync contacts");
+                            } else {
+                                System.out.println("Received sync contacts");
+                            }
+                            printAttachment(contactsMessage.getContactsStream());
                         }
                         if (syncMessage.getGroups().isPresent()) {
                             System.out.println("Received sync groups");
@@ -976,6 +1010,13 @@ public class Main {
                                 System.out.println(" - " + number);
                             }
                         }
+                        if (syncMessage.getVerified().isPresent()) {
+                            System.out.println("Received sync message with verified identities:");
+                            final VerifiedMessage verifiedMessage = syncMessage.getVerified().get();
+                            System.out.println(" - " + verifiedMessage.getDestination() + ": " + verifiedMessage.getVerified());
+                            String safetyNumber = formatSafetyNumber(m.computeSafetyNumber(verifiedMessage.getDestination(), verifiedMessage.getIdentityKey()));
+                            System.out.println("   " + safetyNumber);
+                        }
                     }
                 }
             } else {
@@ -1038,7 +1079,9 @@ public class Main {
             if (attachment.isPointer()) {
                 final SignalServiceAttachmentPointer pointer = attachment.asPointer();
                 System.out.println("  Id: " + pointer.getId() + " Key length: " + pointer.getKey().length + (pointer.getRelay().isPresent() ? " Relay: " + pointer.getRelay().get() : ""));
+                System.out.println("  Filename: " + (pointer.getFileName().isPresent() ? pointer.getFileName().get() : "-"));
                 System.out.println("  Size: " + (pointer.getSize().isPresent() ? pointer.getSize().get() + " bytes" : "<unavailable>") + (pointer.getPreview().isPresent() ? " (Preview is available: " + pointer.getPreview().get().length + " bytes)" : ""));
+                System.out.println("  Voice note: " + (pointer.getVoiceNote() ? "yes" : "no"));
                 File file = m.getAttachmentFile(pointer.getId());
                 if (file.exists()) {
                     System.out.println("  Stored plaintext in: " + file);
@@ -1059,7 +1102,17 @@ public class Main {
         public void handleMessage(SignalServiceEnvelope envelope, SignalServiceContent content, Throwable exception) {
             super.handleMessage(envelope, content, exception);
 
-            if (!envelope.isReceipt() && content != null && content.getDataMessage().isPresent()) {
+            if (envelope.isReceipt()) {
+                try {
+                    conn.sendSignal(new Signal.ReceiptReceived(
+                            SIGNAL_OBJECTPATH,
+                            envelope.getTimestamp(),
+                            envelope.getSource()
+                    ));
+                } catch (DBusException e) {
+                    e.printStackTrace();
+                }
+            } else if (content != null && content.getDataMessage().isPresent()) {
                 SignalServiceDataMessage message = content.getDataMessage().get();
 
                 if (!message.isEndSession() &&
@@ -1088,7 +1141,37 @@ public class Main {
                 }
             }
         }
+    }
+
+    private static class JsonReceiveMessageHandler implements Manager.ReceiveMessageHandler {
+        final Manager m;
+        final ObjectMapper jsonProcessor;
+
+        public JsonReceiveMessageHandler(Manager m) {
+            this.m = m;
+            this.jsonProcessor = new ObjectMapper();
+            jsonProcessor.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY); // disable autodetect
+            jsonProcessor.enable(SerializationFeature.WRITE_NULL_MAP_VALUES);
+            jsonProcessor.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
+            jsonProcessor.disable(JsonGenerator.Feature.AUTO_CLOSE_TARGET);
+        }
 
+        @Override
+        public void handleMessage(SignalServiceEnvelope envelope, SignalServiceContent content, Throwable exception) {
+            ObjectNode result = jsonProcessor.createObjectNode();
+            if (exception != null) {
+                result.putPOJO("error", new JsonError(exception));
+            }
+            if (envelope != null) {
+                result.putPOJO("envelope", new JsonMessageEnvelope(envelope, content));
+            }
+            try {
+                jsonProcessor.writeValue(System.out, result);
+                System.out.println();
+            } catch (IOException e) {
+                e.printStackTrace();
+            }
+        }
     }
 
     private static String formatTimestamp(long timestamp) {