use of org.whispersystems.signalservice.api.messages.shared.SharedContact in project Signal-Android by WhisperSystems.
the class SignalServiceMessageSender method createSharedContactContent.
private List<DataMessage.Contact> createSharedContactContent(List<SharedContact> contacts) throws IOException {
List<DataMessage.Contact> results = new LinkedList<>();
for (SharedContact contact : contacts) {
DataMessage.Contact.Name.Builder nameBuilder = DataMessage.Contact.Name.newBuilder();
if (contact.getName().getFamily().isPresent())
nameBuilder.setFamilyName(contact.getName().getFamily().get());
if (contact.getName().getGiven().isPresent())
nameBuilder.setGivenName(contact.getName().getGiven().get());
if (contact.getName().getMiddle().isPresent())
nameBuilder.setMiddleName(contact.getName().getMiddle().get());
if (contact.getName().getPrefix().isPresent())
nameBuilder.setPrefix(contact.getName().getPrefix().get());
if (contact.getName().getSuffix().isPresent())
nameBuilder.setSuffix(contact.getName().getSuffix().get());
if (contact.getName().getDisplay().isPresent())
nameBuilder.setDisplayName(contact.getName().getDisplay().get());
DataMessage.Contact.Builder contactBuilder = DataMessage.Contact.newBuilder().setName(nameBuilder);
if (contact.getAddress().isPresent()) {
for (SharedContact.PostalAddress address : contact.getAddress().get()) {
DataMessage.Contact.PostalAddress.Builder addressBuilder = DataMessage.Contact.PostalAddress.newBuilder();
switch(address.getType()) {
case HOME:
addressBuilder.setType(DataMessage.Contact.PostalAddress.Type.HOME);
break;
case WORK:
addressBuilder.setType(DataMessage.Contact.PostalAddress.Type.WORK);
break;
case CUSTOM:
addressBuilder.setType(DataMessage.Contact.PostalAddress.Type.CUSTOM);
break;
default:
throw new AssertionError("Unknown type: " + address.getType());
}
if (address.getCity().isPresent())
addressBuilder.setCity(address.getCity().get());
if (address.getCountry().isPresent())
addressBuilder.setCountry(address.getCountry().get());
if (address.getLabel().isPresent())
addressBuilder.setLabel(address.getLabel().get());
if (address.getNeighborhood().isPresent())
addressBuilder.setNeighborhood(address.getNeighborhood().get());
if (address.getPobox().isPresent())
addressBuilder.setPobox(address.getPobox().get());
if (address.getPostcode().isPresent())
addressBuilder.setPostcode(address.getPostcode().get());
if (address.getRegion().isPresent())
addressBuilder.setRegion(address.getRegion().get());
if (address.getStreet().isPresent())
addressBuilder.setStreet(address.getStreet().get());
contactBuilder.addAddress(addressBuilder);
}
}
if (contact.getEmail().isPresent()) {
for (SharedContact.Email email : contact.getEmail().get()) {
DataMessage.Contact.Email.Builder emailBuilder = DataMessage.Contact.Email.newBuilder().setValue(email.getValue());
switch(email.getType()) {
case HOME:
emailBuilder.setType(DataMessage.Contact.Email.Type.HOME);
break;
case WORK:
emailBuilder.setType(DataMessage.Contact.Email.Type.WORK);
break;
case MOBILE:
emailBuilder.setType(DataMessage.Contact.Email.Type.MOBILE);
break;
case CUSTOM:
emailBuilder.setType(DataMessage.Contact.Email.Type.CUSTOM);
break;
default:
throw new AssertionError("Unknown type: " + email.getType());
}
if (email.getLabel().isPresent())
emailBuilder.setLabel(email.getLabel().get());
contactBuilder.addEmail(emailBuilder);
}
}
if (contact.getPhone().isPresent()) {
for (SharedContact.Phone phone : contact.getPhone().get()) {
DataMessage.Contact.Phone.Builder phoneBuilder = DataMessage.Contact.Phone.newBuilder().setValue(phone.getValue());
switch(phone.getType()) {
case HOME:
phoneBuilder.setType(DataMessage.Contact.Phone.Type.HOME);
break;
case WORK:
phoneBuilder.setType(DataMessage.Contact.Phone.Type.WORK);
break;
case MOBILE:
phoneBuilder.setType(DataMessage.Contact.Phone.Type.MOBILE);
break;
case CUSTOM:
phoneBuilder.setType(DataMessage.Contact.Phone.Type.CUSTOM);
break;
default:
throw new AssertionError("Unknown type: " + phone.getType());
}
if (phone.getLabel().isPresent())
phoneBuilder.setLabel(phone.getLabel().get());
contactBuilder.addNumber(phoneBuilder);
}
}
if (contact.getAvatar().isPresent()) {
AttachmentPointer pointer = contact.getAvatar().get().getAttachment().isStream() ? createAttachmentPointer(contact.getAvatar().get().getAttachment().asStream()) : createAttachmentPointer(contact.getAvatar().get().getAttachment().asPointer());
contactBuilder.setAvatar(DataMessage.Contact.Avatar.newBuilder().setAvatar(pointer).setIsProfile(contact.getAvatar().get().isProfile()));
}
if (contact.getOrganization().isPresent()) {
contactBuilder.setOrganization(contact.getOrganization().get());
}
results.add(contactBuilder.build());
}
return results;
}
use of org.whispersystems.signalservice.api.messages.shared.SharedContact in project Signal-Android by WhisperSystems.
the class SignalServiceContent method createSignalServiceMessage.
private static SignalServiceDataMessage createSignalServiceMessage(SignalServiceMetadata metadata, SignalServiceProtos.DataMessage content) throws UnsupportedDataMessageException, InvalidMessageStructureException {
SignalServiceGroupV2 groupInfoV2 = createGroupV2Info(content);
Optional<SignalServiceGroupContext> groupContext;
try {
groupContext = SignalServiceGroupContext.createOptional(null, groupInfoV2);
} catch (InvalidMessageException e) {
throw new InvalidMessageStructureException(e);
}
List<SignalServiceAttachment> attachments = new LinkedList<>();
boolean endSession = ((content.getFlags() & SignalServiceProtos.DataMessage.Flags.END_SESSION_VALUE) != 0);
boolean expirationUpdate = ((content.getFlags() & SignalServiceProtos.DataMessage.Flags.EXPIRATION_TIMER_UPDATE_VALUE) != 0);
boolean profileKeyUpdate = ((content.getFlags() & SignalServiceProtos.DataMessage.Flags.PROFILE_KEY_UPDATE_VALUE) != 0);
boolean isGroupV2 = groupInfoV2 != null;
SignalServiceDataMessage.Quote quote = createQuote(content, isGroupV2);
List<SharedContact> sharedContacts = createSharedContacts(content);
List<SignalServiceDataMessage.Preview> previews = createPreviews(content);
List<SignalServiceDataMessage.Mention> mentions = createMentions(content.getBodyRangesList(), content.getBody(), isGroupV2);
SignalServiceDataMessage.Sticker sticker = createSticker(content);
SignalServiceDataMessage.Reaction reaction = createReaction(content);
SignalServiceDataMessage.RemoteDelete remoteDelete = createRemoteDelete(content);
SignalServiceDataMessage.GroupCallUpdate groupCallUpdate = createGroupCallUpdate(content);
SignalServiceDataMessage.StoryContext storyContext = createStoryContext(content);
if (content.getRequiredProtocolVersion() > SignalServiceProtos.DataMessage.ProtocolVersion.CURRENT_VALUE) {
throw new UnsupportedDataMessageProtocolVersionException(SignalServiceProtos.DataMessage.ProtocolVersion.CURRENT_VALUE, content.getRequiredProtocolVersion(), metadata.getSender().getIdentifier(), metadata.getSenderDevice(), groupContext);
}
SignalServiceDataMessage.Payment payment = createPayment(content);
if (content.getRequiredProtocolVersion() > SignalServiceProtos.DataMessage.ProtocolVersion.CURRENT.getNumber()) {
throw new UnsupportedDataMessageProtocolVersionException(SignalServiceProtos.DataMessage.ProtocolVersion.CURRENT.getNumber(), content.getRequiredProtocolVersion(), metadata.getSender().getIdentifier(), metadata.getSenderDevice(), groupContext);
}
for (SignalServiceProtos.AttachmentPointer pointer : content.getAttachmentsList()) {
attachments.add(createAttachmentPointer(pointer));
}
if (content.hasTimestamp() && content.getTimestamp() != metadata.getTimestamp()) {
throw new InvalidMessageStructureException("Timestamps don't match: " + content.getTimestamp() + " vs " + metadata.getTimestamp(), metadata.getSender().getIdentifier(), metadata.getSenderDevice());
}
return new SignalServiceDataMessage(metadata.getTimestamp(), null, groupInfoV2, attachments, content.hasBody() ? content.getBody() : null, endSession, content.getExpireTimer(), expirationUpdate, content.hasProfileKey() ? content.getProfileKey().toByteArray() : null, profileKeyUpdate, quote, sharedContacts, previews, mentions, sticker, content.getIsViewOnce(), reaction, remoteDelete, groupCallUpdate, payment, storyContext);
}
use of org.whispersystems.signalservice.api.messages.shared.SharedContact in project Signal-Android by WhisperSystems.
the class ContactModelMapper method remoteToLocal.
public static Contact remoteToLocal(@NonNull SharedContact sharedContact) {
Name name = new Name(sharedContact.getName().getDisplay().orNull(), sharedContact.getName().getGiven().orNull(), sharedContact.getName().getFamily().orNull(), sharedContact.getName().getPrefix().orNull(), sharedContact.getName().getSuffix().orNull(), sharedContact.getName().getMiddle().orNull());
List<Phone> phoneNumbers = new LinkedList<>();
if (sharedContact.getPhone().isPresent()) {
for (SharedContact.Phone phone : sharedContact.getPhone().get()) {
phoneNumbers.add(new Phone(phone.getValue(), remoteToLocalType(phone.getType()), phone.getLabel().orNull()));
}
}
List<Email> emails = new LinkedList<>();
if (sharedContact.getEmail().isPresent()) {
for (SharedContact.Email email : sharedContact.getEmail().get()) {
emails.add(new Email(email.getValue(), remoteToLocalType(email.getType()), email.getLabel().orNull()));
}
}
List<PostalAddress> postalAddresses = new LinkedList<>();
if (sharedContact.getAddress().isPresent()) {
for (SharedContact.PostalAddress postalAddress : sharedContact.getAddress().get()) {
postalAddresses.add(new PostalAddress(remoteToLocalType(postalAddress.getType()), postalAddress.getLabel().orNull(), postalAddress.getStreet().orNull(), postalAddress.getPobox().orNull(), postalAddress.getNeighborhood().orNull(), postalAddress.getCity().orNull(), postalAddress.getRegion().orNull(), postalAddress.getPostcode().orNull(), postalAddress.getCountry().orNull()));
}
}
Avatar avatar = null;
if (sharedContact.getAvatar().isPresent()) {
Attachment attachment = PointerAttachment.forPointer(Optional.of(sharedContact.getAvatar().get().getAttachment().asPointer())).get();
boolean isProfile = sharedContact.getAvatar().get().isProfile();
avatar = new Avatar(null, attachment, isProfile);
}
return new Contact(name, sharedContact.getOrganization().orNull(), phoneNumbers, emails, postalAddresses, avatar);
}
use of org.whispersystems.signalservice.api.messages.shared.SharedContact in project Signal-Android by WhisperSystems.
the class PushSendJob method getSharedContactsFor.
List<SharedContact> getSharedContactsFor(OutgoingMediaMessage mediaMessage) {
List<SharedContact> sharedContacts = new LinkedList<>();
for (Contact contact : mediaMessage.getSharedContacts()) {
SharedContact.Builder builder = ContactModelMapper.localToRemoteBuilder(contact);
SharedContact.Avatar avatar = null;
if (contact.getAvatar() != null && contact.getAvatar().getAttachment() != null) {
avatar = SharedContact.Avatar.newBuilder().withAttachment(getAttachmentFor(contact.getAvatarAttachment())).withProfileFlag(contact.getAvatar().isProfile()).build();
}
builder.setAvatar(avatar);
sharedContacts.add(builder.build());
}
return sharedContacts;
}
use of org.whispersystems.signalservice.api.messages.shared.SharedContact in project Signal-Android by WhisperSystems.
the class PushGroupSendJob method deliver.
private List<SendMessageResult> deliver(OutgoingMediaMessage message, @NonNull Recipient groupRecipient, @NonNull List<Recipient> destinations) throws IOException, UntrustedIdentityException, UndeliverableMessageException {
try {
rotateSenderCertificateIfNecessary();
GroupId.Push groupId = groupRecipient.requireGroupId().requirePush();
Optional<byte[]> profileKey = getProfileKey(groupRecipient);
Optional<Quote> quote = getQuoteFor(message);
Optional<SignalServiceDataMessage.Sticker> sticker = getStickerFor(message);
List<SharedContact> sharedContacts = getSharedContactsFor(message);
List<Preview> previews = getPreviewsFor(message);
List<SignalServiceDataMessage.Mention> mentions = getMentionsFor(message.getMentions());
List<Attachment> attachments = Stream.of(message.getAttachments()).filterNot(Attachment::isSticker).toList();
List<SignalServiceAttachment> attachmentPointers = getAttachmentPointersFor(attachments);
boolean isRecipientUpdate = Stream.of(SignalDatabase.groupReceipts().getGroupReceiptInfo(messageId)).anyMatch(info -> info.getStatus() > GroupReceiptDatabase.STATUS_UNDELIVERED);
if (message.isGroup()) {
OutgoingGroupUpdateMessage groupMessage = (OutgoingGroupUpdateMessage) message;
if (groupMessage.isV2Group()) {
MessageGroupContext.GroupV2Properties properties = groupMessage.requireGroupV2Properties();
GroupContextV2 groupContext = properties.getGroupContext();
SignalServiceGroupV2.Builder builder = SignalServiceGroupV2.newBuilder(properties.getGroupMasterKey()).withRevision(groupContext.getRevision());
ByteString groupChange = groupContext.getGroupChange();
if (groupChange != null) {
builder.withSignedGroupChange(groupChange.toByteArray());
}
SignalServiceGroupV2 group = builder.build();
SignalServiceDataMessage groupDataMessage = SignalServiceDataMessage.newBuilder().withTimestamp(message.getSentTimeMillis()).withExpiration(groupRecipient.getExpiresInSeconds()).asGroupMessage(group).build();
return GroupSendUtil.sendResendableDataMessage(context, groupRecipient.requireGroupId().requireV2(), destinations, isRecipientUpdate, ContentHint.IMPLICIT, new MessageId(messageId, true), groupDataMessage);
} else {
throw new UndeliverableMessageException("Messages can no longer be sent to V1 groups!");
}
} else {
Optional<GroupDatabase.GroupRecord> groupRecord = SignalDatabase.groups().getGroup(groupRecipient.requireGroupId());
if (groupRecord.isPresent() && groupRecord.get().isAnnouncementGroup() && !groupRecord.get().isAdmin(Recipient.self())) {
throw new UndeliverableMessageException("Non-admins cannot send messages in announcement groups!");
}
SignalServiceDataMessage.Builder builder = SignalServiceDataMessage.newBuilder().withTimestamp(message.getSentTimeMillis());
GroupUtil.setDataMessageGroupContext(context, builder, groupId);
SignalServiceDataMessage groupMessage = builder.withAttachments(attachmentPointers).withBody(message.getBody()).withExpiration((int) (message.getExpiresIn() / 1000)).withViewOnce(message.isViewOnce()).asExpirationUpdate(message.isExpirationUpdate()).withProfileKey(profileKey.orNull()).withQuote(quote.orNull()).withSticker(sticker.orNull()).withSharedContacts(sharedContacts).withPreviews(previews).withMentions(mentions).build();
Log.i(TAG, JobLogger.format(this, "Beginning message send."));
return GroupSendUtil.sendResendableDataMessage(context, groupRecipient.getGroupId().transform(GroupId::requireV2).orNull(), destinations, isRecipientUpdate, ContentHint.RESENDABLE, new MessageId(messageId, true), groupMessage);
}
} catch (ServerRejectedException e) {
throw new UndeliverableMessageException(e);
}
}
Aggregations