--- /dev/null
+package org.asamk.signal;
+
+import org.whispersystems.signalservice.api.messages.SignalServiceAttachment;
+import org.whispersystems.signalservice.api.messages.SignalServiceAttachmentPointer;
+
+class JsonAttachment {
+ String contentType;
+ long id;
+ int size;
+
+ JsonAttachment(SignalServiceAttachment attachment) {
+ this.contentType = attachment.getContentType();
+ final SignalServiceAttachmentPointer pointer = attachment.asPointer();
+ if (attachment.isPointer()) {
+ this.id = pointer.getId();
+ if (pointer.getSize().isPresent()) {
+ this.size = pointer.getSize().get();
+ }
+ }
+ }
+}
--- /dev/null
+package org.asamk.signal;
+
+import org.whispersystems.signalservice.api.messages.calls.*;
+
+import java.util.List;
+
+class JsonCallMessage {
+ OfferMessage offerMessage;
+ AnswerMessage answerMessage;
+ BusyMessage busyMessage;
+ HangupMessage hangupMessage;
+ List<IceUpdateMessage> iceUpdateMessages;
+
+ JsonCallMessage(SignalServiceCallMessage callMessage) {
+ if (callMessage.getOfferMessage().isPresent()) {
+ this.offerMessage = callMessage.getOfferMessage().get();
+ }
+ if (callMessage.getAnswerMessage().isPresent()) {
+ this.answerMessage = callMessage.getAnswerMessage().get();
+ }
+ if (callMessage.getBusyMessage().isPresent()) {
+ this.busyMessage = callMessage.getBusyMessage().get();
+ }
+ if (callMessage.getHangupMessage().isPresent()) {
+ this.hangupMessage = callMessage.getHangupMessage().get();
+ }
+ if (callMessage.getIceUpdateMessages().isPresent()) {
+ this.iceUpdateMessages = callMessage.getIceUpdateMessages().get();
+ }
+ }
+}
--- /dev/null
+package org.asamk.signal;
+
+import org.whispersystems.signalservice.api.messages.SignalServiceAttachment;
+import org.whispersystems.signalservice.api.messages.SignalServiceDataMessage;
+
+import java.util.ArrayList;
+import java.util.List;
+
+class JsonDataMessage {
+ long timestamp;
+ String message;
+ int expiresInSeconds;
+ List<JsonAttachment> attachments;
+ JsonGroupInfo groupInfo;
+
+ JsonDataMessage(SignalServiceDataMessage dataMessage) {
+ this.timestamp = dataMessage.getTimestamp();
+ if (dataMessage.getGroupInfo().isPresent()) {
+ this.groupInfo = new JsonGroupInfo(dataMessage.getGroupInfo().get());
+ }
+ if (dataMessage.getBody().isPresent()) {
+ this.message = dataMessage.getBody().get();
+ }
+ this.expiresInSeconds = dataMessage.getExpiresInSeconds();
+ if (dataMessage.getAttachments().isPresent()) {
+ this.attachments = new ArrayList<>(dataMessage.getAttachments().get().size());
+ for (SignalServiceAttachment attachment : dataMessage.getAttachments().get()) {
+ this.attachments.add(new JsonAttachment(attachment));
+ }
+ } else {
+ this.attachments = new ArrayList<>();
+ }
+ }
+}
--- /dev/null
+package org.asamk.signal;
+
+class JsonError {
+ String message;
+
+ JsonError(Throwable exception) {
+ this.message = exception.getMessage();
+ }
+}
--- /dev/null
+package org.asamk.signal;
+
+import org.whispersystems.signalservice.api.messages.SignalServiceGroup;
+import org.whispersystems.signalservice.internal.util.Base64;
+
+import java.util.List;
+
+class JsonGroupInfo {
+ String groupId;
+ List<String> members;
+ String name;
+ String type;
+
+ JsonGroupInfo(SignalServiceGroup groupInfo) {
+ this.groupId = Base64.encodeBytes(groupInfo.getGroupId());
+ if (groupInfo.getMembers().isPresent()) {
+ this.members = groupInfo.getMembers().get();
+ }
+ if (groupInfo.getName().isPresent()) {
+ this.name = groupInfo.getName().get();
+ }
+ this.type = groupInfo.getType().toString();
+ }
+}
--- /dev/null
+package org.asamk.signal;
+
+import org.whispersystems.signalservice.api.messages.SignalServiceContent;
+import org.whispersystems.signalservice.api.messages.SignalServiceEnvelope;
+import org.whispersystems.signalservice.api.push.SignalServiceAddress;
+
+class JsonMessageEnvelope {
+ String source;
+ int sourceDevice;
+ String relay;
+ long timestamp;
+ boolean isReceipt;
+ JsonDataMessage dataMessage;
+ JsonSyncMessage syncMessage;
+ JsonCallMessage callMessage;
+
+ public JsonMessageEnvelope(SignalServiceEnvelope envelope, SignalServiceContent content) {
+ SignalServiceAddress source = envelope.getSourceAddress();
+ this.source = source.getNumber();
+ this.sourceDevice = envelope.getSourceDevice();
+ this.relay = source.getRelay().isPresent() ? source.getRelay().get() : null;
+ this.timestamp = envelope.getTimestamp();
+ this.isReceipt = envelope.isReceipt();
+ if (content != null) {
+ if (content.getDataMessage().isPresent()) {
+ this.dataMessage = new JsonDataMessage(content.getDataMessage().get());
+ }
+ if (content.getSyncMessage().isPresent()) {
+ this.syncMessage = new JsonSyncMessage(content.getSyncMessage().get());
+ }
+ if (content.getCallMessage().isPresent()) {
+ this.callMessage = new JsonCallMessage(content.getCallMessage().get());
+ }
+ }
+ }
+}
--- /dev/null
+package org.asamk.signal;
+
+import org.whispersystems.signalservice.api.messages.multidevice.ReadMessage;
+import org.whispersystems.signalservice.api.messages.multidevice.SignalServiceSyncMessage;
+
+import java.util.List;
+
+class JsonSyncMessage {
+ JsonDataMessage sentMessage;
+ List<String> blockedNumbers;
+ List<ReadMessage> readMessages;
+
+ JsonSyncMessage(SignalServiceSyncMessage syncMessage) {
+ if (syncMessage.getSent().isPresent()) {
+ this.sentMessage = new JsonDataMessage(syncMessage.getSent().get().getMessage());
+ }
+ if (syncMessage.getBlockedList().isPresent()) {
+ this.blockedNumbers = syncMessage.getBlockedList().get().getNumbers();
+ }
+ if (syncMessage.getRead().isPresent()) {
+ this.readMessages = syncMessage.getRead().get();
+ }
+ }
+}
*/
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.*;
}
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;
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")
}
}
}
+ }
+
+ 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) {
import org.whispersystems.libsignal.IdentityKeyPair;
import org.whispersystems.libsignal.InvalidKeyIdException;
import org.whispersystems.libsignal.SignalProtocolAddress;
-import org.whispersystems.libsignal.state.*;
+import org.whispersystems.libsignal.state.PreKeyRecord;
+import org.whispersystems.libsignal.state.SessionRecord;
+import org.whispersystems.libsignal.state.SignalProtocolStore;
+import org.whispersystems.libsignal.state.SignedPreKeyRecord;
import java.util.List;
import java.util.Map;