diff --git a/lib/src/main/java/org/asamk/signal/manager/Manager.java b/lib/src/main/java/org/asamk/signal/manager/Manager.java index 9661b12c..885f683c 100644 --- a/lib/src/main/java/org/asamk/signal/manager/Manager.java +++ b/lib/src/main/java/org/asamk/signal/manager/Manager.java @@ -122,6 +122,7 @@ import org.whispersystems.signalservice.api.messages.multidevice.SentTranscriptM import org.whispersystems.signalservice.api.messages.multidevice.SignalServiceSyncMessage; import org.whispersystems.signalservice.api.messages.multidevice.StickerPackOperationMessage; import org.whispersystems.signalservice.api.messages.multidevice.VerifiedMessage; +import org.whispersystems.signalservice.api.messages.shared.SharedContact; import org.whispersystems.signalservice.api.profiles.ProfileAndCredential; import org.whispersystems.signalservice.api.profiles.SignalServiceProfile; import org.whispersystems.signalservice.api.push.SignalServiceAddress; @@ -1558,6 +1559,14 @@ public class Manager implements Closeable { downloadAttachment(attachment); } } + if (message.getSharedContacts().isPresent() && !ignoreAttachments) { + for (SharedContact contact : message.getSharedContacts().get()) { + if (contact.getAvatar().isPresent()) { + // TODO probably should save to contacts instead + downloadAttachment(contact.getAvatar().get().getAttachment()); + } + } + } if (message.getProfileKey().isPresent() && message.getProfileKey().get().length == 32) { final ProfileKey profileKey; try { diff --git a/src/main/java/org/asamk/signal/ReceiveMessageHandler.java b/src/main/java/org/asamk/signal/ReceiveMessageHandler.java index 07dbfd1d..7b69df52 100644 --- a/src/main/java/org/asamk/signal/ReceiveMessageHandler.java +++ b/src/main/java/org/asamk/signal/ReceiveMessageHandler.java @@ -429,8 +429,37 @@ public class ReceiveMessageHandler implements Manager.ReceiveMessageHandler { final List sharedContacts = message.getSharedContacts().get(); System.out.println("Contacts:"); for (SharedContact contact : sharedContacts) { - System.out.println(" - Name: " + contact.getName()); + System.out.println(" - Name: " + contact.getName()); // This just displays " - Name: org.whispersystems.signalservice.api.messages.shared.SharedContact$Name@7bde1f3a" + System.out.println(" - Avatar: " + (contact.getAvatar().isPresent() ? contact.getAvatar() : "-")); + System.out.println(" - Phone details:"); + if (contact.getPhone().isPresent()) { + for (SharedContact.Phone phone : contact.getPhone().get()) { + System.out.println(" " + phone); + } + } else { + System.out.println(" -"); + } + System.out.println(" - Email details:"); + + if (contact.getEmail().isPresent()) { + for (SharedContact.Email email : contact.getEmail().get()) { + System.out.println(" " + email); + } + } else { + System.out.println(" -"); + } + System.out.println(" - Address details:"); + if (contact.getAddress().isPresent()) { + for (SharedContact.PostalAddress address : contact.getAddress().get()) { + System.out.println(" " + address); + } + } else { + System.out.println(" -"); + } + System.out.println(" - Organisation: " + + (contact.getOrganization().isPresent() ? contact.getOrganization().get() : "-")); // TODO show or store rest of the contact info + // TODO: TEST THIS } } if (message.getSticker().isPresent()) { diff --git a/src/main/java/org/asamk/signal/json/JsonContactAddress.java b/src/main/java/org/asamk/signal/json/JsonContactAddress.java new file mode 100644 index 00000000..5d2cdd5f --- /dev/null +++ b/src/main/java/org/asamk/signal/json/JsonContactAddress.java @@ -0,0 +1,47 @@ +package org.asamk.signal.json; + +import com.fasterxml.jackson.annotation.JsonProperty; + +import org.whispersystems.signalservice.api.messages.shared.SharedContact; + +public class JsonContactAddress { + + @JsonProperty + private final SharedContact.PostalAddress.Type type; + + @JsonProperty + private final String label; + + @JsonProperty + private final String street; + + @JsonProperty + private final String pobox; + + @JsonProperty + private final String neighborhood; + + @JsonProperty + private final String city; + + @JsonProperty + private final String region; + + @JsonProperty + private final String postcode; + + @JsonProperty + private final String country; + + public JsonContactAddress(SharedContact.PostalAddress address) { + type = address.getType(); + label = address.getLabel().orNull(); + street = address.getStreet().orNull(); + pobox = address.getPobox().orNull(); + neighborhood = address.getNeighborhood().orNull(); + city = address.getCity().orNull(); + region = address.getRegion().orNull(); + postcode = address.getPostcode().orNull(); + country = address.getCountry().orNull(); + } +} diff --git a/src/main/java/org/asamk/signal/json/JsonContactAvatar.java b/src/main/java/org/asamk/signal/json/JsonContactAvatar.java new file mode 100644 index 00000000..3ed55f6f --- /dev/null +++ b/src/main/java/org/asamk/signal/json/JsonContactAvatar.java @@ -0,0 +1,19 @@ +package org.asamk.signal.json; + +import com.fasterxml.jackson.annotation.JsonProperty; + +import org.whispersystems.signalservice.api.messages.shared.SharedContact; + +public class JsonContactAvatar { + + @JsonProperty + private final JsonAttachment attachment; + + @JsonProperty + private final boolean isProfile; + + public JsonContactAvatar(SharedContact.Avatar avatar) { + attachment = new JsonAttachment(avatar.getAttachment()); + isProfile = avatar.isProfile(); + } +} diff --git a/src/main/java/org/asamk/signal/json/JsonContactEmail.java b/src/main/java/org/asamk/signal/json/JsonContactEmail.java new file mode 100644 index 00000000..600432af --- /dev/null +++ b/src/main/java/org/asamk/signal/json/JsonContactEmail.java @@ -0,0 +1,23 @@ +package org.asamk.signal.json; + +import com.fasterxml.jackson.annotation.JsonProperty; + +import org.whispersystems.signalservice.api.messages.shared.SharedContact; + +public class JsonContactEmail { + + @JsonProperty + private final String value; + + @JsonProperty + private final SharedContact.Email.Type type; + + @JsonProperty + private final String label; + + public JsonContactEmail(SharedContact.Email email) { + value = email.getValue(); + type = email.getType(); + label = email.getLabel().orNull(); + } +} diff --git a/src/main/java/org/asamk/signal/json/JsonContactPhone.java b/src/main/java/org/asamk/signal/json/JsonContactPhone.java new file mode 100644 index 00000000..5d27cd42 --- /dev/null +++ b/src/main/java/org/asamk/signal/json/JsonContactPhone.java @@ -0,0 +1,23 @@ +package org.asamk.signal.json; + +import com.fasterxml.jackson.annotation.JsonProperty; + +import org.whispersystems.signalservice.api.messages.shared.SharedContact; + +public class JsonContactPhone { + + @JsonProperty + private final String value; + + @JsonProperty + private final SharedContact.Phone.Type type; + + @JsonProperty + private final String label; + + public JsonContactPhone(SharedContact.Phone phone) { + value = phone.getValue(); + type = phone.getType(); + label = phone.getLabel().orNull(); + } +} diff --git a/src/main/java/org/asamk/signal/json/JsonDataMessage.java b/src/main/java/org/asamk/signal/json/JsonDataMessage.java index 1c927b40..57facc99 100644 --- a/src/main/java/org/asamk/signal/json/JsonDataMessage.java +++ b/src/main/java/org/asamk/signal/json/JsonDataMessage.java @@ -52,6 +52,10 @@ class JsonDataMessage { @JsonInclude(JsonInclude.Include.NON_NULL) final JsonRemoteDelete remoteDelete; + @JsonProperty + @JsonInclude(JsonInclude.Include.NON_NULL) + final List contacts; + @JsonProperty @JsonInclude(JsonInclude.Include.NON_NULL) final JsonGroupInfo groupInfo; @@ -100,6 +104,16 @@ class JsonDataMessage { this.attachments = List.of(); } this.sticker = dataMessage.getSticker().isPresent() ? new JsonSticker(dataMessage.getSticker().get()) : null; + + if (dataMessage.getSharedContacts().isPresent()) { + this.contacts = dataMessage.getSharedContacts() + .get() + .stream() + .map(JsonSharedContact::new) + .collect(Collectors.toList()); + } else { + this.contacts = List.of(); + } } public JsonDataMessage(Signal.MessageReceived messageReceived) { @@ -109,10 +123,11 @@ class JsonDataMessage { expiresInSeconds = null; viewOnce = null; remoteDelete = null; - reaction = null; // TODO Replace these 4 with the proper commands + reaction = null; // TODO Replace these 5 with the proper commands quote = null; mentions = null; sticker = null; + contacts = null; attachments = messageReceived.getAttachments().stream().map(JsonAttachment::new).collect(Collectors.toList()); } @@ -123,10 +138,11 @@ class JsonDataMessage { expiresInSeconds = null; viewOnce = null; remoteDelete = null; - reaction = null; // TODO Replace these 4 with the proper commands + reaction = null; // TODO Replace these 5 with the proper commands quote = null; mentions = null; sticker = null; + contacts = null; attachments = messageReceived.getAttachments().stream().map(JsonAttachment::new).collect(Collectors.toList()); } } diff --git a/src/main/java/org/asamk/signal/json/JsonName.java b/src/main/java/org/asamk/signal/json/JsonName.java new file mode 100644 index 00000000..eb6b96d1 --- /dev/null +++ b/src/main/java/org/asamk/signal/json/JsonName.java @@ -0,0 +1,35 @@ +package org.asamk.signal.json; + +import com.fasterxml.jackson.annotation.JsonProperty; + +import org.whispersystems.signalservice.api.messages.shared.SharedContact; + +public class JsonName { + + @JsonProperty + private final String display; + + @JsonProperty + private final String given; + + @JsonProperty + private final String family; + + @JsonProperty + private final String prefix; + + @JsonProperty + private final String suffix; + + @JsonProperty + private final String middle; + + public JsonName(SharedContact.Name name) { + display = name.getDisplay().orNull(); + given = name.getGiven().orNull(); + family = name.getFamily().orNull(); + prefix = name.getPrefix().orNull(); + suffix = name.getSuffix().orNull(); + middle = name.getMiddle().orNull(); + } +} diff --git a/src/main/java/org/asamk/signal/json/JsonSharedContact.java b/src/main/java/org/asamk/signal/json/JsonSharedContact.java new file mode 100644 index 00000000..669b7997 --- /dev/null +++ b/src/main/java/org/asamk/signal/json/JsonSharedContact.java @@ -0,0 +1,75 @@ +package org.asamk.signal.json; + +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; + +import org.whispersystems.signalservice.api.messages.shared.SharedContact; + +import java.util.List; +import java.util.stream.Collectors; + +public class JsonSharedContact { + + @JsonProperty + final JsonName name; + + @JsonProperty + final JsonContactAvatar avatar; + + @JsonProperty + @JsonInclude(JsonInclude.Include.NON_NULL) + final List phone; + + @JsonProperty + @JsonInclude(JsonInclude.Include.NON_NULL) + final List email; + + @JsonProperty + @JsonInclude(JsonInclude.Include.NON_NULL) + final List address; + + @JsonProperty + final String organization; + + + public JsonSharedContact(SharedContact contact) { + name = new JsonName(contact.getName()); + if (contact.getAvatar().isPresent()) { + avatar = new JsonContactAvatar(contact.getAvatar().get()); + } else { + avatar = null; + } + + if (contact.getPhone().isPresent()) { + phone = contact.getPhone() + .get() + .stream() + .map(JsonContactPhone::new) + .collect(Collectors.toList()); + } else { + phone = null; + } + + if (contact.getEmail().isPresent()) { + email = contact.getEmail() + .get() + .stream() + .map(JsonContactEmail::new) + .collect(Collectors.toList()); + } else { + email = null; + } + + if (contact.getAddress().isPresent()) { + address = contact.getAddress() + .get() + .stream() + .map(JsonContactAddress::new) + .collect(Collectors.toList()); + } else { + address = null; + } + + organization = contact.getOrganization().orNull(); + } +}