mirror of
https://github.com/AsamK/signal-cli
synced 2025-08-29 10:30:38 +00:00
Update libsignal-service-java
This commit is contained in:
parent
fd25ef539f
commit
9eb97746c1
32 changed files with 242 additions and 288 deletions
|
@ -1573,12 +1573,17 @@
|
||||||
{"name":"signature_"}
|
{"name":"signature_"}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name":"org.signal.storageservice.protos.groups.BannedMember",
|
||||||
|
"fields":[{"name":"userId_"}]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name":"org.signal.storageservice.protos.groups.Group",
|
"name":"org.signal.storageservice.protos.groups.Group",
|
||||||
"fields":[
|
"fields":[
|
||||||
{"name":"accessControl_"},
|
{"name":"accessControl_"},
|
||||||
{"name":"announcementsOnly_"},
|
{"name":"announcementsOnly_"},
|
||||||
{"name":"avatar_"},
|
{"name":"avatar_"},
|
||||||
|
{"name":"bannedMembers_"},
|
||||||
{"name":"description_"},
|
{"name":"description_"},
|
||||||
{"name":"disappearingMessagesTimer_"},
|
{"name":"disappearingMessagesTimer_"},
|
||||||
{"name":"inviteLinkPassword_"},
|
{"name":"inviteLinkPassword_"},
|
||||||
|
@ -1608,9 +1613,11 @@
|
||||||
{
|
{
|
||||||
"name":"org.signal.storageservice.protos.groups.GroupChange$Actions",
|
"name":"org.signal.storageservice.protos.groups.GroupChange$Actions",
|
||||||
"fields":[
|
"fields":[
|
||||||
|
{"name":"addBannedMembers_"},
|
||||||
{"name":"addMembers_"},
|
{"name":"addMembers_"},
|
||||||
{"name":"addPendingMembers_"},
|
{"name":"addPendingMembers_"},
|
||||||
{"name":"addRequestingMembers_"},
|
{"name":"addRequestingMembers_"},
|
||||||
|
{"name":"deleteBannedMembers_"},
|
||||||
{"name":"deleteMembers_"},
|
{"name":"deleteMembers_"},
|
||||||
{"name":"deletePendingMembers_"},
|
{"name":"deletePendingMembers_"},
|
||||||
{"name":"deleteRequestingMembers_"},
|
{"name":"deleteRequestingMembers_"},
|
||||||
|
@ -1631,6 +1638,10 @@
|
||||||
{"name":"sourceUuid_"}
|
{"name":"sourceUuid_"}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name":"org.signal.storageservice.protos.groups.GroupChange$Actions$AddBannedMemberAction",
|
||||||
|
"fields":[{"name":"added_"}]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name":"org.signal.storageservice.protos.groups.GroupChange$Actions$AddMemberAction",
|
"name":"org.signal.storageservice.protos.groups.GroupChange$Actions$AddMemberAction",
|
||||||
"fields":[
|
"fields":[
|
||||||
|
@ -1646,6 +1657,10 @@
|
||||||
"name":"org.signal.storageservice.protos.groups.GroupChange$Actions$AddRequestingMemberAction",
|
"name":"org.signal.storageservice.protos.groups.GroupChange$Actions$AddRequestingMemberAction",
|
||||||
"fields":[{"name":"added_"}]
|
"fields":[{"name":"added_"}]
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name":"org.signal.storageservice.protos.groups.GroupChange$Actions$DeleteBannedMemberAction",
|
||||||
|
"fields":[{"name":"deletedUserId_"}]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name":"org.signal.storageservice.protos.groups.GroupChange$Actions$DeleteMemberAction",
|
"name":"org.signal.storageservice.protos.groups.GroupChange$Actions$DeleteMemberAction",
|
||||||
"fields":[{"name":"deletedUserId_"}]
|
"fields":[{"name":"deletedUserId_"}]
|
||||||
|
@ -1777,11 +1792,16 @@
|
||||||
{"name":"uuid_"}
|
{"name":"uuid_"}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name":"org.signal.storageservice.protos.groups.local.DecryptedBannedMember",
|
||||||
|
"fields":[{"name":"uuid_"}]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name":"org.signal.storageservice.protos.groups.local.DecryptedGroup",
|
"name":"org.signal.storageservice.protos.groups.local.DecryptedGroup",
|
||||||
"fields":[
|
"fields":[
|
||||||
{"name":"accessControl_"},
|
{"name":"accessControl_"},
|
||||||
{"name":"avatar_"},
|
{"name":"avatar_"},
|
||||||
|
{"name":"bannedMembers_"},
|
||||||
{"name":"description_"},
|
{"name":"description_"},
|
||||||
{"name":"disappearingMessagesTimer_"},
|
{"name":"disappearingMessagesTimer_"},
|
||||||
{"name":"inviteLinkPassword_"},
|
{"name":"inviteLinkPassword_"},
|
||||||
|
@ -1796,6 +1816,7 @@
|
||||||
{
|
{
|
||||||
"name":"org.signal.storageservice.protos.groups.local.DecryptedGroupChange",
|
"name":"org.signal.storageservice.protos.groups.local.DecryptedGroupChange",
|
||||||
"fields":[
|
"fields":[
|
||||||
|
{"name":"deleteBannedMembers_"},
|
||||||
{"name":"deleteMembers_"},
|
{"name":"deleteMembers_"},
|
||||||
{"name":"deletePendingMembers_"},
|
{"name":"deletePendingMembers_"},
|
||||||
{"name":"deleteRequestingMembers_"},
|
{"name":"deleteRequestingMembers_"},
|
||||||
|
@ -1804,6 +1825,7 @@
|
||||||
{"name":"modifyMemberRoles_"},
|
{"name":"modifyMemberRoles_"},
|
||||||
{"name":"newAttributeAccess_"},
|
{"name":"newAttributeAccess_"},
|
||||||
{"name":"newAvatar_"},
|
{"name":"newAvatar_"},
|
||||||
|
{"name":"newBannedMembers_"},
|
||||||
{"name":"newDescription_"},
|
{"name":"newDescription_"},
|
||||||
{"name":"newInviteLinkAccess_"},
|
{"name":"newInviteLinkAccess_"},
|
||||||
{"name":"newInviteLinkPassword_"},
|
{"name":"newInviteLinkPassword_"},
|
||||||
|
|
|
@ -14,7 +14,7 @@ repositories {
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation("com.github.turasa", "signal-service-java", "2.15.3_unofficial_44")
|
implementation("com.github.turasa", "signal-service-java", "2.15.3_unofficial_45")
|
||||||
implementation("com.fasterxml.jackson.core", "jackson-databind", "2.13.1")
|
implementation("com.fasterxml.jackson.core", "jackson-databind", "2.13.1")
|
||||||
implementation("com.google.protobuf", "protobuf-javalite", "3.11.4")
|
implementation("com.google.protobuf", "protobuf-javalite", "3.11.4")
|
||||||
implementation("org.bouncycastle", "bcprov-jdk15on", "1.70")
|
implementation("org.bouncycastle", "bcprov-jdk15on", "1.70")
|
||||||
|
|
|
@ -62,7 +62,6 @@ import org.asamk.signal.manager.util.KeyUtils;
|
||||||
import org.asamk.signal.manager.util.StickerUtils;
|
import org.asamk.signal.manager.util.StickerUtils;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
import org.whispersystems.libsignal.util.guava.Optional;
|
|
||||||
import org.whispersystems.signalservice.api.SignalSessionLock;
|
import org.whispersystems.signalservice.api.SignalSessionLock;
|
||||||
import org.whispersystems.signalservice.api.messages.SignalServiceDataMessage;
|
import org.whispersystems.signalservice.api.messages.SignalServiceDataMessage;
|
||||||
import org.whispersystems.signalservice.api.messages.SignalServiceReceiptMessage;
|
import org.whispersystems.signalservice.api.messages.SignalServiceReceiptMessage;
|
||||||
|
@ -82,6 +81,7 @@ import java.util.HashMap;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Optional;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
import java.util.concurrent.ExecutorService;
|
import java.util.concurrent.ExecutorService;
|
||||||
|
@ -246,14 +246,9 @@ class ManagerImpl implements Manager {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setProfile(
|
public void setProfile(
|
||||||
String givenName, final String familyName, String about, String aboutEmoji, java.util.Optional<File> avatar
|
String givenName, final String familyName, String about, String aboutEmoji, Optional<File> avatar
|
||||||
) throws IOException {
|
) throws IOException {
|
||||||
context.getProfileHelper()
|
context.getProfileHelper().setProfile(givenName, familyName, about, aboutEmoji, avatar);
|
||||||
.setProfile(givenName,
|
|
||||||
familyName,
|
|
||||||
about,
|
|
||||||
aboutEmoji,
|
|
||||||
avatar == null ? null : Optional.fromNullable(avatar.orElse(null)));
|
|
||||||
context.getSyncHelper().sendSyncFetchProfileMessage();
|
context.getSyncHelper().sendSyncFetchProfileMessage();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -308,7 +303,7 @@ class ManagerImpl implements Manager {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setRegistrationLockPin(java.util.Optional<String> pin) throws IOException, NotMasterDeviceException {
|
public void setRegistrationLockPin(Optional<String> pin) throws IOException, NotMasterDeviceException {
|
||||||
if (!account.isMasterDevice()) {
|
if (!account.isMasterDevice()) {
|
||||||
throw new NotMasterDeviceException();
|
throw new NotMasterDeviceException();
|
||||||
}
|
}
|
||||||
|
@ -442,7 +437,7 @@ class ManagerImpl implements Manager {
|
||||||
final var timestamp = System.currentTimeMillis();
|
final var timestamp = System.currentTimeMillis();
|
||||||
for (var recipient : recipients) {
|
for (var recipient : recipients) {
|
||||||
if (recipient instanceof RecipientIdentifier.Single single) {
|
if (recipient instanceof RecipientIdentifier.Single single) {
|
||||||
final var message = new SignalServiceTypingMessage(action, timestamp, Optional.absent());
|
final var message = new SignalServiceTypingMessage(action, timestamp, Optional.empty());
|
||||||
try {
|
try {
|
||||||
final var recipientId = context.getRecipientHelper().resolveRecipient(single);
|
final var recipientId = context.getRecipientHelper().resolveRecipient(single);
|
||||||
final var result = context.getSendHelper().sendTypingMessage(message, recipientId);
|
final var result = context.getSendHelper().sendTypingMessage(message, recipientId);
|
||||||
|
@ -558,7 +553,7 @@ class ManagerImpl implements Manager {
|
||||||
stickerPack.getPackKey(),
|
stickerPack.getPackKey(),
|
||||||
stickerId,
|
stickerId,
|
||||||
manifestSticker.emoji(),
|
manifestSticker.emoji(),
|
||||||
AttachmentUtils.createAttachment(streamDetails, Optional.absent())));
|
AttachmentUtils.createAttachment(streamDetails, Optional.empty())));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -719,7 +714,7 @@ class ManagerImpl implements Manager {
|
||||||
pack.isInstalled(),
|
pack.isInstalled(),
|
||||||
manifest.title(),
|
manifest.title(),
|
||||||
manifest.author(),
|
manifest.author(),
|
||||||
java.util.Optional.ofNullable(manifest.cover() == null ? null : manifest.cover().toApi()),
|
Optional.ofNullable(manifest.cover() == null ? null : manifest.cover().toApi()),
|
||||||
manifest.stickers().stream().map(JsonStickerPack.JsonSticker::toApi).toList());
|
manifest.stickers().stream().map(JsonStickerPack.JsonSticker::toApi).toList());
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
logger.warn("Failed to read local sticker pack manifest: {}", e.getMessage(), e);
|
logger.warn("Failed to read local sticker pack manifest: {}", e.getMessage(), e);
|
||||||
|
|
|
@ -4,7 +4,6 @@ import org.asamk.signal.manager.config.ServiceConfig;
|
||||||
import org.asamk.signal.manager.config.ServiceEnvironmentConfig;
|
import org.asamk.signal.manager.config.ServiceEnvironmentConfig;
|
||||||
import org.signal.libsignal.metadata.certificate.CertificateValidator;
|
import org.signal.libsignal.metadata.certificate.CertificateValidator;
|
||||||
import org.signal.zkgroup.profiles.ClientZkProfileOperations;
|
import org.signal.zkgroup.profiles.ClientZkProfileOperations;
|
||||||
import org.whispersystems.libsignal.util.guava.Optional;
|
|
||||||
import org.whispersystems.signalservice.api.KeyBackupService;
|
import org.whispersystems.signalservice.api.KeyBackupService;
|
||||||
import org.whispersystems.signalservice.api.SignalServiceAccountManager;
|
import org.whispersystems.signalservice.api.SignalServiceAccountManager;
|
||||||
import org.whispersystems.signalservice.api.SignalServiceDataStore;
|
import org.whispersystems.signalservice.api.SignalServiceDataStore;
|
||||||
|
@ -23,6 +22,7 @@ import org.whispersystems.signalservice.api.util.UptimeSleepTimer;
|
||||||
import org.whispersystems.signalservice.api.websocket.WebSocketFactory;
|
import org.whispersystems.signalservice.api.websocket.WebSocketFactory;
|
||||||
import org.whispersystems.signalservice.internal.websocket.WebSocketConnection;
|
import org.whispersystems.signalservice.internal.websocket.WebSocketConnection;
|
||||||
|
|
||||||
|
import java.util.Optional;
|
||||||
import java.util.concurrent.ExecutorService;
|
import java.util.concurrent.ExecutorService;
|
||||||
import java.util.function.Supplier;
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
|
@ -137,7 +137,7 @@ public class SignalDependencies {
|
||||||
public WebSocketConnection createUnidentifiedWebSocket() {
|
public WebSocketConnection createUnidentifiedWebSocket() {
|
||||||
return new WebSocketConnection("unidentified",
|
return new WebSocketConnection("unidentified",
|
||||||
serviceEnvironmentConfig.getSignalServiceConfiguration(),
|
serviceEnvironmentConfig.getSignalServiceConfiguration(),
|
||||||
Optional.absent(),
|
Optional.empty(),
|
||||||
userAgent,
|
userAgent,
|
||||||
healthMonitor);
|
healthMonitor);
|
||||||
}
|
}
|
||||||
|
@ -164,7 +164,7 @@ public class SignalDependencies {
|
||||||
sessionLock,
|
sessionLock,
|
||||||
userAgent,
|
userAgent,
|
||||||
getSignalWebSocket(),
|
getSignalWebSocket(),
|
||||||
Optional.absent(),
|
Optional.empty(),
|
||||||
getClientZkProfileOperations(),
|
getClientZkProfileOperations(),
|
||||||
executor,
|
executor,
|
||||||
ServiceConfig.MAX_ENVELOPE_SIZE,
|
ServiceConfig.MAX_ENVELOPE_SIZE,
|
||||||
|
|
|
@ -2,8 +2,8 @@ package org.asamk.signal.manager;
|
||||||
|
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
import org.whispersystems.libsignal.util.guava.Preconditions;
|
|
||||||
import org.whispersystems.signalservice.api.SignalWebSocket;
|
import org.whispersystems.signalservice.api.SignalWebSocket;
|
||||||
|
import org.whispersystems.signalservice.api.util.Preconditions;
|
||||||
import org.whispersystems.signalservice.api.util.SleepTimer;
|
import org.whispersystems.signalservice.api.util.SleepTimer;
|
||||||
import org.whispersystems.signalservice.api.websocket.HealthMonitor;
|
import org.whispersystems.signalservice.api.websocket.HealthMonitor;
|
||||||
import org.whispersystems.signalservice.api.websocket.WebSocketConnectionState;
|
import org.whispersystems.signalservice.api.websocket.WebSocketConnectionState;
|
||||||
|
|
|
@ -6,10 +6,11 @@ import org.asamk.signal.manager.storage.recipients.RecipientId;
|
||||||
import org.signal.libsignal.metadata.ProtocolException;
|
import org.signal.libsignal.metadata.ProtocolException;
|
||||||
import org.whispersystems.libsignal.protocol.CiphertextMessage;
|
import org.whispersystems.libsignal.protocol.CiphertextMessage;
|
||||||
import org.whispersystems.libsignal.protocol.DecryptionErrorMessage;
|
import org.whispersystems.libsignal.protocol.DecryptionErrorMessage;
|
||||||
import org.whispersystems.libsignal.util.guava.Optional;
|
|
||||||
import org.whispersystems.signalservice.api.messages.SignalServiceEnvelope;
|
import org.whispersystems.signalservice.api.messages.SignalServiceEnvelope;
|
||||||
import org.whispersystems.signalservice.internal.push.SignalServiceProtos;
|
import org.whispersystems.signalservice.internal.push.SignalServiceProtos;
|
||||||
|
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
public class SendRetryMessageRequestAction implements HandleAction {
|
public class SendRetryMessageRequestAction implements HandleAction {
|
||||||
|
|
||||||
private final RecipientId recipientId;
|
private final RecipientId recipientId;
|
||||||
|
@ -32,7 +33,7 @@ public class SendRetryMessageRequestAction implements HandleAction {
|
||||||
|
|
||||||
int senderDevice = protocolException.getSenderDevice();
|
int senderDevice = protocolException.getSenderDevice();
|
||||||
Optional<GroupId> groupId = protocolException.getGroupId().isPresent() ? Optional.of(GroupId.unknownVersion(
|
Optional<GroupId> groupId = protocolException.getGroupId().isPresent() ? Optional.of(GroupId.unknownVersion(
|
||||||
protocolException.getGroupId().get())) : Optional.absent();
|
protocolException.getGroupId().get())) : Optional.empty();
|
||||||
|
|
||||||
byte[] originalContent;
|
byte[] originalContent;
|
||||||
int envelopeType;
|
int envelopeType;
|
||||||
|
|
|
@ -82,7 +82,7 @@ public record MessageEnvelope(
|
||||||
public static Typing from(final SignalServiceTypingMessage typingMessage) {
|
public static Typing from(final SignalServiceTypingMessage typingMessage) {
|
||||||
return new Typing(typingMessage.getTimestamp(),
|
return new Typing(typingMessage.getTimestamp(),
|
||||||
typingMessage.isTypingStarted() ? Type.STARTED : Type.STOPPED,
|
typingMessage.isTypingStarted() ? Type.STARTED : Type.STOPPED,
|
||||||
Optional.ofNullable(typingMessage.getGroupId().transform(GroupId::unknownVersion).orNull()));
|
typingMessage.getGroupId().map(GroupId::unknownVersion));
|
||||||
}
|
}
|
||||||
|
|
||||||
public enum Type {
|
public enum Type {
|
||||||
|
@ -119,43 +119,33 @@ public record MessageEnvelope(
|
||||||
final AttachmentFileProvider fileProvider
|
final AttachmentFileProvider fileProvider
|
||||||
) {
|
) {
|
||||||
return new Data(dataMessage.getTimestamp(),
|
return new Data(dataMessage.getTimestamp(),
|
||||||
Optional.ofNullable(dataMessage.getGroupContext().transform(GroupContext::from).orNull()),
|
dataMessage.getGroupContext().map(GroupContext::from),
|
||||||
Optional.ofNullable(dataMessage.getGroupCallUpdate().transform(GroupCallUpdate::from).orNull()),
|
dataMessage.getGroupCallUpdate().map(GroupCallUpdate::from),
|
||||||
Optional.ofNullable(dataMessage.getBody().orNull()),
|
dataMessage.getBody(),
|
||||||
dataMessage.getExpiresInSeconds(),
|
dataMessage.getExpiresInSeconds(),
|
||||||
dataMessage.isExpirationUpdate(),
|
dataMessage.isExpirationUpdate(),
|
||||||
dataMessage.isViewOnce(),
|
dataMessage.isViewOnce(),
|
||||||
dataMessage.isEndSession(),
|
dataMessage.isEndSession(),
|
||||||
dataMessage.getProfileKey().isPresent(),
|
dataMessage.getProfileKey().isPresent(),
|
||||||
Optional.ofNullable(dataMessage.getReaction()
|
dataMessage.getReaction().map(r -> Reaction.from(r, recipientResolver, addressResolver)),
|
||||||
.transform(r -> Reaction.from(r, recipientResolver, addressResolver))
|
dataMessage.getQuote().map(q -> Quote.from(q, recipientResolver, addressResolver, fileProvider)),
|
||||||
.orNull()),
|
dataMessage.getPayment().map(p -> p.getPaymentNotification().isPresent() ? Payment.from(p) : null),
|
||||||
Optional.ofNullable(dataMessage.getQuote()
|
|
||||||
.transform(q -> Quote.from(q, recipientResolver, addressResolver, fileProvider))
|
|
||||||
.orNull()),
|
|
||||||
Optional.ofNullable(dataMessage.getPayment()
|
|
||||||
.transform(p -> p.getPaymentNotification().isPresent() ? Payment.from(p) : null)
|
|
||||||
.orNull()),
|
|
||||||
dataMessage.getAttachments()
|
dataMessage.getAttachments()
|
||||||
.transform(a -> a.stream().map(as -> Attachment.from(as, fileProvider)).toList())
|
.map(a -> a.stream().map(as -> Attachment.from(as, fileProvider)).toList())
|
||||||
.or(List.of()),
|
.orElse(List.of()),
|
||||||
Optional.ofNullable(dataMessage.getRemoteDelete()
|
dataMessage.getRemoteDelete().map(SignalServiceDataMessage.RemoteDelete::getTargetSentTimestamp),
|
||||||
.transform(SignalServiceDataMessage.RemoteDelete::getTargetSentTimestamp)
|
dataMessage.getSticker().map(Sticker::from),
|
||||||
.orNull()),
|
|
||||||
Optional.ofNullable(dataMessage.getSticker().transform(Sticker::from).orNull()),
|
|
||||||
dataMessage.getSharedContacts()
|
dataMessage.getSharedContacts()
|
||||||
.transform(a -> a.stream()
|
.map(a -> a.stream()
|
||||||
.map(sharedContact -> SharedContact.from(sharedContact, fileProvider))
|
.map(sharedContact -> SharedContact.from(sharedContact, fileProvider))
|
||||||
.toList())
|
.toList())
|
||||||
.or(List.of()),
|
.orElse(List.of()),
|
||||||
dataMessage.getMentions()
|
dataMessage.getMentions()
|
||||||
.transform(a -> a.stream()
|
.map(a -> a.stream().map(m -> Mention.from(m, recipientResolver, addressResolver)).toList())
|
||||||
.map(m -> Mention.from(m, recipientResolver, addressResolver))
|
.orElse(List.of()),
|
||||||
.toList())
|
|
||||||
.or(List.of()),
|
|
||||||
dataMessage.getPreviews()
|
dataMessage.getPreviews()
|
||||||
.transform(a -> a.stream().map(preview -> Preview.from(preview, fileProvider)).toList())
|
.map(a -> a.stream().map(preview -> Preview.from(preview, fileProvider)).toList())
|
||||||
.or(List.of()));
|
.orElse(List.of()));
|
||||||
}
|
}
|
||||||
|
|
||||||
public record GroupContext(GroupId groupId, boolean isGroupUpdate, int revision) {
|
public record GroupContext(GroupId groupId, boolean isGroupUpdate, int revision) {
|
||||||
|
@ -271,13 +261,13 @@ public record MessageEnvelope(
|
||||||
final var a = attachment.asPointer();
|
final var a = attachment.asPointer();
|
||||||
return new Attachment(Optional.of(a.getRemoteId().toString()),
|
return new Attachment(Optional.of(a.getRemoteId().toString()),
|
||||||
Optional.of(fileProvider.getFile(a.getRemoteId())),
|
Optional.of(fileProvider.getFile(a.getRemoteId())),
|
||||||
Optional.ofNullable(a.getFileName().orNull()),
|
a.getFileName(),
|
||||||
a.getContentType(),
|
a.getContentType(),
|
||||||
a.getUploadTimestamp() == 0 ? Optional.empty() : Optional.of(a.getUploadTimestamp()),
|
a.getUploadTimestamp() == 0 ? Optional.empty() : Optional.of(a.getUploadTimestamp()),
|
||||||
Optional.ofNullable(a.getSize().transform(Integer::longValue).orNull()),
|
a.getSize().map(Integer::longValue),
|
||||||
Optional.ofNullable(a.getPreview().orNull()),
|
a.getPreview(),
|
||||||
Optional.empty(),
|
Optional.empty(),
|
||||||
Optional.ofNullable(a.getCaption().orNull()),
|
a.getCaption(),
|
||||||
a.getWidth() == 0 ? Optional.empty() : Optional.of(a.getWidth()),
|
a.getWidth() == 0 ? Optional.empty() : Optional.of(a.getWidth()),
|
||||||
a.getHeight() == 0 ? Optional.empty() : Optional.of(a.getHeight()),
|
a.getHeight() == 0 ? Optional.empty() : Optional.of(a.getHeight()),
|
||||||
a.getVoiceNote(),
|
a.getVoiceNote(),
|
||||||
|
@ -287,13 +277,13 @@ public record MessageEnvelope(
|
||||||
final var a = attachment.asStream();
|
final var a = attachment.asStream();
|
||||||
return new Attachment(Optional.empty(),
|
return new Attachment(Optional.empty(),
|
||||||
Optional.empty(),
|
Optional.empty(),
|
||||||
Optional.ofNullable(a.getFileName().orNull()),
|
a.getFileName(),
|
||||||
a.getContentType(),
|
a.getContentType(),
|
||||||
a.getUploadTimestamp() == 0 ? Optional.empty() : Optional.of(a.getUploadTimestamp()),
|
a.getUploadTimestamp() == 0 ? Optional.empty() : Optional.of(a.getUploadTimestamp()),
|
||||||
Optional.of(a.getLength()),
|
Optional.of(a.getLength()),
|
||||||
Optional.ofNullable(a.getPreview().orNull()),
|
a.getPreview(),
|
||||||
Optional.empty(),
|
Optional.empty(),
|
||||||
Optional.ofNullable(a.getCaption().orNull()),
|
a.getCaption(),
|
||||||
a.getWidth() == 0 ? Optional.empty() : Optional.of(a.getWidth()),
|
a.getWidth() == 0 ? Optional.empty() : Optional.of(a.getWidth()),
|
||||||
a.getHeight() == 0 ? Optional.empty() : Optional.of(a.getHeight()),
|
a.getHeight() == 0 ? Optional.empty() : Optional.of(a.getHeight()),
|
||||||
a.getVoiceNote(),
|
a.getVoiceNote(),
|
||||||
|
@ -347,13 +337,11 @@ public record MessageEnvelope(
|
||||||
final AttachmentFileProvider fileProvider
|
final AttachmentFileProvider fileProvider
|
||||||
) {
|
) {
|
||||||
return new SharedContact(Name.from(sharedContact.getName()),
|
return new SharedContact(Name.from(sharedContact.getName()),
|
||||||
Optional.ofNullable(sharedContact.getAvatar()
|
sharedContact.getAvatar().map(avatar1 -> Avatar.from(avatar1, fileProvider)),
|
||||||
.transform(avatar1 -> Avatar.from(avatar1, fileProvider))
|
sharedContact.getPhone().map(p -> p.stream().map(Phone::from).toList()).orElse(List.of()),
|
||||||
.orNull()),
|
sharedContact.getEmail().map(p -> p.stream().map(Email::from).toList()).orElse(List.of()),
|
||||||
sharedContact.getPhone().transform(p -> p.stream().map(Phone::from).toList()).or(List.of()),
|
sharedContact.getAddress().map(p -> p.stream().map(Address::from).toList()).orElse(List.of()),
|
||||||
sharedContact.getEmail().transform(p -> p.stream().map(Email::from).toList()).or(List.of()),
|
sharedContact.getOrganization());
|
||||||
sharedContact.getAddress().transform(p -> p.stream().map(Address::from).toList()).or(List.of()),
|
|
||||||
Optional.ofNullable(sharedContact.getOrganization().orNull()));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public record Name(
|
public record Name(
|
||||||
|
@ -366,12 +354,12 @@ public record MessageEnvelope(
|
||||||
) {
|
) {
|
||||||
|
|
||||||
static Name from(org.whispersystems.signalservice.api.messages.shared.SharedContact.Name name) {
|
static Name from(org.whispersystems.signalservice.api.messages.shared.SharedContact.Name name) {
|
||||||
return new Name(Optional.ofNullable(name.getDisplay().orNull()),
|
return new Name(name.getDisplay(),
|
||||||
Optional.ofNullable(name.getGiven().orNull()),
|
name.getGiven(),
|
||||||
Optional.ofNullable(name.getFamily().orNull()),
|
name.getFamily(),
|
||||||
Optional.ofNullable(name.getPrefix().orNull()),
|
name.getPrefix(),
|
||||||
Optional.ofNullable(name.getSuffix().orNull()),
|
name.getSuffix(),
|
||||||
Optional.ofNullable(name.getMiddle().orNull()));
|
name.getMiddle());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -390,9 +378,7 @@ public record MessageEnvelope(
|
||||||
) {
|
) {
|
||||||
|
|
||||||
static Phone from(org.whispersystems.signalservice.api.messages.shared.SharedContact.Phone phone) {
|
static Phone from(org.whispersystems.signalservice.api.messages.shared.SharedContact.Phone phone) {
|
||||||
return new Phone(phone.getValue(),
|
return new Phone(phone.getValue(), Type.from(phone.getType()), phone.getLabel());
|
||||||
Type.from(phone.getType()),
|
|
||||||
Optional.ofNullable(phone.getLabel().orNull()));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public enum Type {
|
public enum Type {
|
||||||
|
@ -417,9 +403,7 @@ public record MessageEnvelope(
|
||||||
) {
|
) {
|
||||||
|
|
||||||
static Email from(org.whispersystems.signalservice.api.messages.shared.SharedContact.Email email) {
|
static Email from(org.whispersystems.signalservice.api.messages.shared.SharedContact.Email email) {
|
||||||
return new Email(email.getValue(),
|
return new Email(email.getValue(), Type.from(email.getType()), email.getLabel());
|
||||||
Type.from(email.getType()),
|
|
||||||
Optional.ofNullable(email.getLabel().orNull()));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public enum Type {
|
public enum Type {
|
||||||
|
@ -453,14 +437,14 @@ public record MessageEnvelope(
|
||||||
|
|
||||||
static Address from(org.whispersystems.signalservice.api.messages.shared.SharedContact.PostalAddress address) {
|
static Address from(org.whispersystems.signalservice.api.messages.shared.SharedContact.PostalAddress address) {
|
||||||
return new Address(Address.Type.from(address.getType()),
|
return new Address(Address.Type.from(address.getType()),
|
||||||
Optional.ofNullable(address.getLabel().orNull()),
|
address.getLabel(),
|
||||||
Optional.ofNullable(address.getLabel().orNull()),
|
address.getLabel(),
|
||||||
Optional.ofNullable(address.getLabel().orNull()),
|
address.getLabel(),
|
||||||
Optional.ofNullable(address.getLabel().orNull()),
|
address.getLabel(),
|
||||||
Optional.ofNullable(address.getLabel().orNull()),
|
address.getLabel(),
|
||||||
Optional.ofNullable(address.getLabel().orNull()),
|
address.getLabel(),
|
||||||
Optional.ofNullable(address.getLabel().orNull()),
|
address.getLabel(),
|
||||||
Optional.ofNullable(address.getLabel().orNull()));
|
address.getLabel());
|
||||||
}
|
}
|
||||||
|
|
||||||
public enum Type {
|
public enum Type {
|
||||||
|
@ -488,9 +472,7 @@ public record MessageEnvelope(
|
||||||
preview.getDescription(),
|
preview.getDescription(),
|
||||||
preview.getDate(),
|
preview.getDate(),
|
||||||
preview.getUrl(),
|
preview.getUrl(),
|
||||||
Optional.ofNullable(preview.getImage()
|
preview.getImage().map(as -> Attachment.from(as, fileProvider)));
|
||||||
.transform(as -> Attachment.from(as, fileProvider))
|
|
||||||
.orNull()));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -512,30 +494,22 @@ public record MessageEnvelope(
|
||||||
RecipientAddressResolver addressResolver,
|
RecipientAddressResolver addressResolver,
|
||||||
final AttachmentFileProvider fileProvider
|
final AttachmentFileProvider fileProvider
|
||||||
) {
|
) {
|
||||||
return new Sync(Optional.ofNullable(syncMessage.getSent()
|
return new Sync(syncMessage.getSent()
|
||||||
.transform(s -> Sent.from(s, recipientResolver, addressResolver, fileProvider))
|
.map(s -> Sent.from(s, recipientResolver, addressResolver, fileProvider)),
|
||||||
.orNull()),
|
syncMessage.getBlockedList().map(b -> Blocked.from(b, recipientResolver, addressResolver)),
|
||||||
Optional.ofNullable(syncMessage.getBlockedList()
|
|
||||||
.transform(b -> Blocked.from(b, recipientResolver, addressResolver))
|
|
||||||
.orNull()),
|
|
||||||
syncMessage.getRead()
|
syncMessage.getRead()
|
||||||
.transform(r -> r.stream()
|
.map(r -> r.stream().map(rm -> Read.from(rm, recipientResolver, addressResolver)).toList())
|
||||||
.map(rm -> Read.from(rm, recipientResolver, addressResolver))
|
.orElse(List.of()),
|
||||||
.toList())
|
|
||||||
.or(List.of()),
|
|
||||||
syncMessage.getViewed()
|
syncMessage.getViewed()
|
||||||
.transform(r -> r.stream()
|
.map(r -> r.stream()
|
||||||
.map(rm -> Viewed.from(rm, recipientResolver, addressResolver))
|
.map(rm -> Viewed.from(rm, recipientResolver, addressResolver))
|
||||||
.toList())
|
.toList())
|
||||||
.or(List.of()),
|
.orElse(List.of()),
|
||||||
Optional.ofNullable(syncMessage.getViewOnceOpen()
|
syncMessage.getViewOnceOpen().map(rm -> ViewOnceOpen.from(rm, recipientResolver, addressResolver)),
|
||||||
.transform(rm -> ViewOnceOpen.from(rm, recipientResolver, addressResolver))
|
syncMessage.getContacts().map(Contacts::from),
|
||||||
.orNull()),
|
syncMessage.getGroups().map(Groups::from),
|
||||||
Optional.ofNullable(syncMessage.getContacts().transform(Contacts::from).orNull()),
|
syncMessage.getMessageRequestResponse()
|
||||||
Optional.ofNullable(syncMessage.getGroups().transform(Groups::from).orNull()),
|
.map(m -> MessageRequestResponse.from(m, recipientResolver, addressResolver)));
|
||||||
Optional.ofNullable(syncMessage.getMessageRequestResponse()
|
|
||||||
.transform(m -> MessageRequestResponse.from(m, recipientResolver, addressResolver))
|
|
||||||
.orNull()));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public record Sent(
|
public record Sent(
|
||||||
|
@ -554,10 +528,8 @@ public record MessageEnvelope(
|
||||||
) {
|
) {
|
||||||
return new Sent(sentMessage.getTimestamp(),
|
return new Sent(sentMessage.getTimestamp(),
|
||||||
sentMessage.getExpirationStartTimestamp(),
|
sentMessage.getExpirationStartTimestamp(),
|
||||||
Optional.ofNullable(sentMessage.getDestination()
|
sentMessage.getDestination()
|
||||||
.transform(d -> addressResolver.resolveRecipientAddress(recipientResolver.resolveRecipient(
|
.map(d -> addressResolver.resolveRecipientAddress(recipientResolver.resolveRecipient(d))),
|
||||||
d)))
|
|
||||||
.orNull()),
|
|
||||||
sentMessage.getRecipients()
|
sentMessage.getRecipients()
|
||||||
.stream()
|
.stream()
|
||||||
.map(d -> addressResolver.resolveRecipientAddress(recipientResolver.resolveRecipient(d)))
|
.map(d -> addressResolver.resolveRecipientAddress(recipientResolver.resolveRecipient(d)))
|
||||||
|
@ -638,13 +610,9 @@ public record MessageEnvelope(
|
||||||
RecipientAddressResolver addressResolver
|
RecipientAddressResolver addressResolver
|
||||||
) {
|
) {
|
||||||
return new MessageRequestResponse(Type.from(messageRequestResponse.getType()),
|
return new MessageRequestResponse(Type.from(messageRequestResponse.getType()),
|
||||||
Optional.ofNullable(messageRequestResponse.getGroupId()
|
messageRequestResponse.getGroupId().map(GroupId::unknownVersion),
|
||||||
.transform(GroupId::unknownVersion)
|
messageRequestResponse.getPerson()
|
||||||
.orNull()),
|
.map(p -> addressResolver.resolveRecipientAddress(recipientResolver.resolveRecipient(p))));
|
||||||
Optional.ofNullable(messageRequestResponse.getPerson()
|
|
||||||
.transform(p -> addressResolver.resolveRecipientAddress(recipientResolver.resolveRecipient(
|
|
||||||
p)))
|
|
||||||
.orNull()));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public enum Type {
|
public enum Type {
|
||||||
|
@ -682,17 +650,17 @@ public record MessageEnvelope(
|
||||||
) {
|
) {
|
||||||
|
|
||||||
public static Call from(final SignalServiceCallMessage callMessage) {
|
public static Call from(final SignalServiceCallMessage callMessage) {
|
||||||
return new Call(Optional.ofNullable(callMessage.getDestinationDeviceId().orNull()),
|
return new Call(callMessage.getDestinationDeviceId(),
|
||||||
Optional.ofNullable(callMessage.getGroupId().transform(GroupId::unknownVersion).orNull()),
|
callMessage.getGroupId().map(GroupId::unknownVersion),
|
||||||
Optional.ofNullable(callMessage.getTimestamp().orNull()),
|
callMessage.getTimestamp(),
|
||||||
Optional.ofNullable(callMessage.getOfferMessage().transform(Offer::from).orNull()),
|
callMessage.getOfferMessage().map(Offer::from),
|
||||||
Optional.ofNullable(callMessage.getAnswerMessage().transform(Answer::from).orNull()),
|
callMessage.getAnswerMessage().map(Answer::from),
|
||||||
Optional.ofNullable(callMessage.getHangupMessage().transform(Hangup::from).orNull()),
|
callMessage.getHangupMessage().map(Hangup::from),
|
||||||
Optional.ofNullable(callMessage.getBusyMessage().transform(Busy::from).orNull()),
|
callMessage.getBusyMessage().map(Busy::from),
|
||||||
callMessage.getIceUpdateMessages()
|
callMessage.getIceUpdateMessages()
|
||||||
.transform(m -> m.stream().map(IceUpdate::from).toList())
|
.map(m -> m.stream().map(IceUpdate::from).toList())
|
||||||
.or(List.of()),
|
.orElse(List.of()),
|
||||||
Optional.ofNullable(callMessage.getOpaqueMessage().transform(Opaque::from).orNull()));
|
callMessage.getOpaqueMessage().map(Opaque::from));
|
||||||
}
|
}
|
||||||
|
|
||||||
public record Offer(long id, String sdp, Type type, byte[] opaque) {
|
public record Offer(long id, String sdp, Type type, byte[] opaque) {
|
||||||
|
@ -813,15 +781,12 @@ public record MessageEnvelope(
|
||||||
Optional<Sync> sync;
|
Optional<Sync> sync;
|
||||||
Optional<Call> call;
|
Optional<Call> call;
|
||||||
if (content != null) {
|
if (content != null) {
|
||||||
receipt = Optional.ofNullable(content.getReceiptMessage().transform(Receipt::from).orNull());
|
receipt = content.getReceiptMessage().map(Receipt::from);
|
||||||
typing = Optional.ofNullable(content.getTypingMessage().transform(Typing::from).orNull());
|
typing = content.getTypingMessage().map(Typing::from);
|
||||||
data = Optional.ofNullable(content.getDataMessage()
|
data = content.getDataMessage()
|
||||||
.transform(dataMessage -> Data.from(dataMessage, recipientResolver, addressResolver, fileProvider))
|
.map(dataMessage -> Data.from(dataMessage, recipientResolver, addressResolver, fileProvider));
|
||||||
.orNull());
|
sync = content.getSyncMessage().map(s -> Sync.from(s, recipientResolver, addressResolver, fileProvider));
|
||||||
sync = Optional.ofNullable(content.getSyncMessage()
|
call = content.getCallMessage().map(Call::from);
|
||||||
.transform(s -> Sync.from(s, recipientResolver, addressResolver, fileProvider))
|
|
||||||
.orNull());
|
|
||||||
call = Optional.ofNullable(content.getCallMessage().transform(Call::from).orNull());
|
|
||||||
} else {
|
} else {
|
||||||
receipt = envelope.isReceipt() ? Optional.of(new Receipt(envelope.getServerReceivedTimestamp(),
|
receipt = envelope.isReceipt() ? Optional.of(new Receipt(envelope.getServerReceivedTimestamp(),
|
||||||
Receipt.Type.DELIVERY,
|
Receipt.Type.DELIVERY,
|
||||||
|
|
|
@ -4,7 +4,6 @@ import org.bouncycastle.util.encoders.Hex;
|
||||||
import org.whispersystems.libsignal.InvalidKeyException;
|
import org.whispersystems.libsignal.InvalidKeyException;
|
||||||
import org.whispersystems.libsignal.ecc.Curve;
|
import org.whispersystems.libsignal.ecc.Curve;
|
||||||
import org.whispersystems.libsignal.ecc.ECPublicKey;
|
import org.whispersystems.libsignal.ecc.ECPublicKey;
|
||||||
import org.whispersystems.libsignal.util.guava.Optional;
|
|
||||||
import org.whispersystems.signalservice.api.push.TrustStore;
|
import org.whispersystems.signalservice.api.push.TrustStore;
|
||||||
import org.whispersystems.signalservice.internal.configuration.SignalCdnUrl;
|
import org.whispersystems.signalservice.internal.configuration.SignalCdnUrl;
|
||||||
import org.whispersystems.signalservice.internal.configuration.SignalCdshUrl;
|
import org.whispersystems.signalservice.internal.configuration.SignalCdshUrl;
|
||||||
|
@ -18,6 +17,7 @@ import org.whispersystems.signalservice.internal.configuration.SignalStorageUrl;
|
||||||
import java.util.Base64;
|
import java.util.Base64;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
import okhttp3.Dns;
|
import okhttp3.Dns;
|
||||||
import okhttp3.Interceptor;
|
import okhttp3.Interceptor;
|
||||||
|
@ -42,8 +42,8 @@ class LiveConfig {
|
||||||
private final static String SIGNAL_CDSH_URL = "";
|
private final static String SIGNAL_CDSH_URL = "";
|
||||||
private final static TrustStore TRUST_STORE = new WhisperTrustStore();
|
private final static TrustStore TRUST_STORE = new WhisperTrustStore();
|
||||||
|
|
||||||
private final static Optional<Dns> dns = Optional.absent();
|
private final static Optional<Dns> dns = Optional.empty();
|
||||||
private final static Optional<SignalProxy> proxy = Optional.absent();
|
private final static Optional<SignalProxy> proxy = Optional.empty();
|
||||||
|
|
||||||
private final static byte[] zkGroupServerPublicParams = Base64.getDecoder()
|
private final static byte[] zkGroupServerPublicParams = Base64.getDecoder()
|
||||||
.decode("AMhf5ywVwITZMsff/eCyudZx9JDmkkkbV6PInzG4p8x3VqVJSFiMvnvlEKWuRob/1eaIetR31IYeAbm0NdOuHH8Qi+Rexi1wLlpzIo1gstHWBfZzy1+qHRV5A4TqPp15YzBPm0WSggW6PbSn+F4lf57VCnHF7p8SvzAA2ZZJPYJURt8X7bbg+H3i+PEjH9DXItNEqs2sNcug37xZQDLm7X36nOoGPs54XsEGzPdEV+itQNGUFEjY6X9Uv+Acuks7NpyGvCoKxGwgKgE5XyJ+nNKlyHHOLb6N1NuHyBrZrgtY/JYJHRooo5CEqYKBqdFnmbTVGEkCvJKxLnjwKWf+fEPoWeQFj5ObDjcKMZf2Jm2Ae69x+ikU5gBXsRmoF94GXQ==");
|
.decode("AMhf5ywVwITZMsff/eCyudZx9JDmkkkbV6PInzG4p8x3VqVJSFiMvnvlEKWuRob/1eaIetR31IYeAbm0NdOuHH8Qi+Rexi1wLlpzIo1gstHWBfZzy1+qHRV5A4TqPp15YzBPm0WSggW6PbSn+F4lf57VCnHF7p8SvzAA2ZZJPYJURt8X7bbg+H3i+PEjH9DXItNEqs2sNcug37xZQDLm7X36nOoGPs54XsEGzPdEV+itQNGUFEjY6X9Uv+Acuks7NpyGvCoKxGwgKgE5XyJ+nNKlyHHOLb6N1NuHyBrZrgtY/JYJHRooo5CEqYKBqdFnmbTVGEkCvJKxLnjwKWf+fEPoWeQFj5ObDjcKMZf2Jm2Ae69x+ikU5gBXsRmoF94GXQ==");
|
||||||
|
|
|
@ -4,7 +4,6 @@ import org.bouncycastle.util.encoders.Hex;
|
||||||
import org.whispersystems.libsignal.InvalidKeyException;
|
import org.whispersystems.libsignal.InvalidKeyException;
|
||||||
import org.whispersystems.libsignal.ecc.Curve;
|
import org.whispersystems.libsignal.ecc.Curve;
|
||||||
import org.whispersystems.libsignal.ecc.ECPublicKey;
|
import org.whispersystems.libsignal.ecc.ECPublicKey;
|
||||||
import org.whispersystems.libsignal.util.guava.Optional;
|
|
||||||
import org.whispersystems.signalservice.api.push.TrustStore;
|
import org.whispersystems.signalservice.api.push.TrustStore;
|
||||||
import org.whispersystems.signalservice.internal.configuration.SignalCdnUrl;
|
import org.whispersystems.signalservice.internal.configuration.SignalCdnUrl;
|
||||||
import org.whispersystems.signalservice.internal.configuration.SignalCdshUrl;
|
import org.whispersystems.signalservice.internal.configuration.SignalCdshUrl;
|
||||||
|
@ -18,6 +17,7 @@ import org.whispersystems.signalservice.internal.configuration.SignalStorageUrl;
|
||||||
import java.util.Base64;
|
import java.util.Base64;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
import okhttp3.Dns;
|
import okhttp3.Dns;
|
||||||
import okhttp3.Interceptor;
|
import okhttp3.Interceptor;
|
||||||
|
@ -42,8 +42,8 @@ class StagingConfig {
|
||||||
private final static String SIGNAL_CDSH_URL = "https://cdsh.staging.signal.org";
|
private final static String SIGNAL_CDSH_URL = "https://cdsh.staging.signal.org";
|
||||||
private final static TrustStore TRUST_STORE = new WhisperTrustStore();
|
private final static TrustStore TRUST_STORE = new WhisperTrustStore();
|
||||||
|
|
||||||
private final static Optional<Dns> dns = Optional.absent();
|
private final static Optional<Dns> dns = Optional.empty();
|
||||||
private final static Optional<SignalProxy> proxy = Optional.absent();
|
private final static Optional<SignalProxy> proxy = Optional.empty();
|
||||||
|
|
||||||
private final static byte[] zkGroupServerPublicParams = Base64.getDecoder()
|
private final static byte[] zkGroupServerPublicParams = Base64.getDecoder()
|
||||||
.decode("ABSY21VckQcbSXVNCGRYJcfWHiAMZmpTtTELcDmxgdFbtp/bWsSxZdMKzfCp8rvIs8ocCU3B37fT3r4Mi5qAemeGeR2X+/YmOGR5ofui7tD5mDQfstAI9i+4WpMtIe8KC3wU5w3Inq3uNWVmoGtpKndsNfwJrCg0Hd9zmObhypUnSkfYn2ooMOOnBpfdanRtrvetZUayDMSC5iSRcXKpdlukrpzzsCIvEwjwQlJYVPOQPj4V0F4UXXBdHSLK05uoPBCQG8G9rYIGedYsClJXnbrgGYG3eMTG5hnx4X4ntARBgELuMWWUEEfSK0mjXg+/2lPmWcTZWR9nkqgQQP0tbzuiPm74H2wMO4u1Wafe+UwyIlIT9L7KLS19Aw8r4sPrXQ==");
|
.decode("ABSY21VckQcbSXVNCGRYJcfWHiAMZmpTtTELcDmxgdFbtp/bWsSxZdMKzfCp8rvIs8ocCU3B37fT3r4Mi5qAemeGeR2X+/YmOGR5ofui7tD5mDQfstAI9i+4WpMtIe8KC3wU5w3Inq3uNWVmoGtpKndsNfwJrCg0Hd9zmObhypUnSkfYn2ooMOOnBpfdanRtrvetZUayDMSC5iSRcXKpdlukrpzzsCIvEwjwQlJYVPOQPj4V0F4UXXBdHSLK05uoPBCQG8G9rYIGedYsClJXnbrgGYG3eMTG5hnx4X4ntARBgELuMWWUEEfSK0mjXg+/2lPmWcTZWR9nkqgQQP0tbzuiPm74H2wMO4u1Wafe+UwyIlIT9L7KLS19Aw8r4sPrXQ==");
|
||||||
|
|
|
@ -13,13 +13,13 @@ import org.asamk.signal.manager.util.NumberVerificationUtils;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
import org.whispersystems.libsignal.InvalidKeyException;
|
import org.whispersystems.libsignal.InvalidKeyException;
|
||||||
import org.whispersystems.libsignal.util.guava.Optional;
|
|
||||||
import org.whispersystems.signalservice.api.push.ACI;
|
import org.whispersystems.signalservice.api.push.ACI;
|
||||||
import org.whispersystems.signalservice.api.push.PNI;
|
import org.whispersystems.signalservice.api.push.PNI;
|
||||||
import org.whispersystems.signalservice.api.push.exceptions.AuthorizationFailedException;
|
import org.whispersystems.signalservice.api.push.exceptions.AuthorizationFailedException;
|
||||||
import org.whispersystems.signalservice.api.util.DeviceNameUtil;
|
import org.whispersystems.signalservice.api.util.DeviceNameUtil;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.util.Optional;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
public class AccountHelper {
|
public class AccountHelper {
|
||||||
|
@ -176,7 +176,7 @@ public class AccountHelper {
|
||||||
// When setting an empty GCM id, the Signal-Server also sets the fetchesMessages property to false.
|
// When setting an empty GCM id, the Signal-Server also sets the fetchesMessages property to false.
|
||||||
// If this is the master device, other users can't send messages to this number anymore.
|
// If this is the master device, other users can't send messages to this number anymore.
|
||||||
// If this is a linked device, other users can still send messages, but this device doesn't receive them anymore.
|
// If this is a linked device, other users can still send messages, but this device doesn't receive them anymore.
|
||||||
dependencies.getAccountManager().setGcmId(Optional.absent());
|
dependencies.getAccountManager().setGcmId(Optional.empty());
|
||||||
|
|
||||||
account.setRegistered(false);
|
account.setRegistered(false);
|
||||||
unregisteredListener.call();
|
unregisteredListener.call();
|
||||||
|
|
|
@ -34,7 +34,6 @@ import org.signal.zkgroup.groups.GroupSecretParams;
|
||||||
import org.signal.zkgroup.profiles.ProfileKey;
|
import org.signal.zkgroup.profiles.ProfileKey;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
import org.whispersystems.libsignal.util.guava.Optional;
|
|
||||||
import org.whispersystems.signalservice.api.groupsv2.GroupLinkNotActiveException;
|
import org.whispersystems.signalservice.api.groupsv2.GroupLinkNotActiveException;
|
||||||
import org.whispersystems.signalservice.api.messages.SignalServiceAttachment;
|
import org.whispersystems.signalservice.api.messages.SignalServiceAttachment;
|
||||||
import org.whispersystems.signalservice.api.messages.SignalServiceAttachmentStream;
|
import org.whispersystems.signalservice.api.messages.SignalServiceAttachmentStream;
|
||||||
|
@ -53,6 +52,7 @@ import java.nio.file.Files;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Optional;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
public class GroupHelper {
|
public class GroupHelper {
|
||||||
|
@ -91,10 +91,10 @@ public class GroupHelper {
|
||||||
public Optional<SignalServiceAttachmentStream> createGroupAvatarAttachment(GroupIdV1 groupId) throws IOException {
|
public Optional<SignalServiceAttachmentStream> createGroupAvatarAttachment(GroupIdV1 groupId) throws IOException {
|
||||||
final var streamDetails = context.getAvatarStore().retrieveGroupAvatar(groupId);
|
final var streamDetails = context.getAvatarStore().retrieveGroupAvatar(groupId);
|
||||||
if (streamDetails == null) {
|
if (streamDetails == null) {
|
||||||
return Optional.absent();
|
return Optional.empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
return Optional.of(AttachmentUtils.createAttachment(streamDetails, Optional.absent()));
|
return Optional.of(AttachmentUtils.createAttachment(streamDetails, Optional.empty()));
|
||||||
}
|
}
|
||||||
|
|
||||||
public GroupInfoV2 getOrMigrateGroup(
|
public GroupInfoV2 getOrMigrateGroup(
|
||||||
|
@ -625,9 +625,7 @@ public class GroupHelper {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
final var attachment = createGroupAvatarAttachment(g.getGroupId());
|
final var attachment = createGroupAvatarAttachment(g.getGroupId());
|
||||||
if (attachment.isPresent()) {
|
attachment.ifPresent(group::withAvatar);
|
||||||
group.withAvatar(attachment.get());
|
|
||||||
}
|
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
throw new AttachmentInvalidException(g.getGroupId().toBase64(), e);
|
throw new AttachmentInvalidException(g.getGroupId().toBase64(), e);
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,7 +10,6 @@ import org.asamk.signal.manager.groups.GroupPermission;
|
||||||
import org.asamk.signal.manager.groups.GroupUtils;
|
import org.asamk.signal.manager.groups.GroupUtils;
|
||||||
import org.asamk.signal.manager.groups.NotAGroupMemberException;
|
import org.asamk.signal.manager.groups.NotAGroupMemberException;
|
||||||
import org.asamk.signal.manager.storage.groups.GroupInfoV2;
|
import org.asamk.signal.manager.storage.groups.GroupInfoV2;
|
||||||
import org.asamk.signal.manager.storage.recipients.Profile;
|
|
||||||
import org.asamk.signal.manager.storage.recipients.RecipientId;
|
import org.asamk.signal.manager.storage.recipients.RecipientId;
|
||||||
import org.asamk.signal.manager.util.IOUtils;
|
import org.asamk.signal.manager.util.IOUtils;
|
||||||
import org.asamk.signal.manager.util.Utils;
|
import org.asamk.signal.manager.util.Utils;
|
||||||
|
@ -29,7 +28,6 @@ import org.signal.zkgroup.groups.GroupSecretParams;
|
||||||
import org.signal.zkgroup.groups.UuidCiphertext;
|
import org.signal.zkgroup.groups.UuidCiphertext;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
import org.whispersystems.libsignal.util.guava.Optional;
|
|
||||||
import org.whispersystems.signalservice.api.groupsv2.DecryptedGroupUtil;
|
import org.whispersystems.signalservice.api.groupsv2.DecryptedGroupUtil;
|
||||||
import org.whispersystems.signalservice.api.groupsv2.GroupCandidate;
|
import org.whispersystems.signalservice.api.groupsv2.GroupCandidate;
|
||||||
import org.whispersystems.signalservice.api.groupsv2.GroupLinkNotActiveException;
|
import org.whispersystems.signalservice.api.groupsv2.GroupLinkNotActiveException;
|
||||||
|
@ -48,6 +46,7 @@ import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
import java.util.Optional;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
@ -90,7 +89,7 @@ class GroupV2Helper {
|
||||||
|
|
||||||
return dependencies.getGroupsV2Api()
|
return dependencies.getGroupsV2Api()
|
||||||
.getGroupJoinInfo(groupSecretParams,
|
.getGroupJoinInfo(groupSecretParams,
|
||||||
Optional.fromNullable(password).transform(GroupLinkPassword::serialize),
|
Optional.ofNullable(password).map(GroupLinkPassword::serialize),
|
||||||
getGroupAuthForToday(groupSecretParams));
|
getGroupAuthForToday(groupSecretParams));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -145,44 +144,27 @@ class GroupV2Helper {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!areMembersValid(members)) return null;
|
final var self = new GroupCandidate(getSelfAci().uuid(), Optional.of(profileKeyCredential));
|
||||||
|
|
||||||
final var self = new GroupCandidate(getSelfAci().uuid(), Optional.fromNullable(profileKeyCredential));
|
|
||||||
final var memberList = new ArrayList<>(members);
|
final var memberList = new ArrayList<>(members);
|
||||||
final var credentials = context.getProfileHelper().getRecipientProfileKeyCredential(memberList).stream();
|
final var credentials = context.getProfileHelper().getRecipientProfileKeyCredential(memberList).stream();
|
||||||
final var uuids = memberList.stream()
|
final var uuids = memberList.stream()
|
||||||
.map(member -> context.getRecipientHelper().resolveSignalServiceAddress(member).getServiceId().uuid());
|
.map(member -> context.getRecipientHelper().resolveSignalServiceAddress(member).getServiceId().uuid());
|
||||||
var candidates = Utils.zip(uuids,
|
var candidates = Utils.zip(uuids,
|
||||||
credentials,
|
credentials,
|
||||||
(uuid, credential) -> new GroupCandidate(uuid, Optional.fromNullable(credential)))
|
(uuid, credential) -> new GroupCandidate(uuid, Optional.ofNullable(credential)))
|
||||||
.collect(Collectors.toSet());
|
.collect(Collectors.toSet());
|
||||||
|
|
||||||
final var groupSecretParams = GroupSecretParams.generate();
|
final var groupSecretParams = GroupSecretParams.generate();
|
||||||
return dependencies.getGroupsV2Operations()
|
return dependencies.getGroupsV2Operations()
|
||||||
.createNewGroup(groupSecretParams,
|
.createNewGroup(groupSecretParams,
|
||||||
name,
|
name,
|
||||||
Optional.fromNullable(avatar),
|
Optional.ofNullable(avatar),
|
||||||
self,
|
self,
|
||||||
candidates,
|
candidates,
|
||||||
Member.Role.DEFAULT,
|
Member.Role.DEFAULT,
|
||||||
0);
|
0);
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean areMembersValid(final Set<RecipientId> members) {
|
|
||||||
final var noGv2Capability = context.getProfileHelper()
|
|
||||||
.getRecipientProfile(new ArrayList<>(members))
|
|
||||||
.stream()
|
|
||||||
.filter(profile -> profile != null && !profile.getCapabilities().contains(Profile.Capability.gv2))
|
|
||||||
.collect(Collectors.toSet());
|
|
||||||
if (noGv2Capability.size() > 0) {
|
|
||||||
logger.warn("Cannot create a V2 group as some members don't support Groups V2: {}",
|
|
||||||
noGv2Capability.stream().map(Profile::getDisplayName).collect(Collectors.joining(", ")));
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
Pair<DecryptedGroup, GroupChange> updateGroup(
|
Pair<DecryptedGroup, GroupChange> updateGroup(
|
||||||
GroupInfoV2 groupInfoV2, String name, String description, File avatarFile
|
GroupInfoV2 groupInfoV2, String name, String description, File avatarFile
|
||||||
) throws IOException {
|
) throws IOException {
|
||||||
|
@ -212,21 +194,17 @@ class GroupV2Helper {
|
||||||
) throws IOException {
|
) throws IOException {
|
||||||
GroupsV2Operations.GroupOperations groupOperations = getGroupOperations(groupInfoV2);
|
GroupsV2Operations.GroupOperations groupOperations = getGroupOperations(groupInfoV2);
|
||||||
|
|
||||||
if (!areMembersValid(newMembers)) {
|
|
||||||
throw new IOException("Failed to update group");
|
|
||||||
}
|
|
||||||
|
|
||||||
final var memberList = new ArrayList<>(newMembers);
|
final var memberList = new ArrayList<>(newMembers);
|
||||||
final var credentials = context.getProfileHelper().getRecipientProfileKeyCredential(memberList).stream();
|
final var credentials = context.getProfileHelper().getRecipientProfileKeyCredential(memberList).stream();
|
||||||
final var uuids = memberList.stream()
|
final var uuids = memberList.stream()
|
||||||
.map(member -> context.getRecipientHelper().resolveSignalServiceAddress(member).getServiceId().uuid());
|
.map(member -> context.getRecipientHelper().resolveSignalServiceAddress(member).getServiceId().uuid());
|
||||||
var candidates = Utils.zip(uuids,
|
var candidates = Utils.zip(uuids,
|
||||||
credentials,
|
credentials,
|
||||||
(uuid, credential) -> new GroupCandidate(uuid, Optional.fromNullable(credential)))
|
(uuid, credential) -> new GroupCandidate(uuid, Optional.ofNullable(credential)))
|
||||||
.collect(Collectors.toSet());
|
.collect(Collectors.toSet());
|
||||||
|
|
||||||
final var aci = getSelfAci();
|
final var aci = getSelfAci();
|
||||||
final var change = groupOperations.createModifyGroupMembershipChange(candidates, aci.uuid());
|
final var change = groupOperations.createModifyGroupMembershipChange(candidates, Set.of(), aci.uuid());
|
||||||
|
|
||||||
change.setSourceUuid(getSelfAci().toByteString());
|
change.setSourceUuid(getSelfAci().toByteString());
|
||||||
|
|
||||||
|
@ -431,7 +409,7 @@ class GroupV2Helper {
|
||||||
GroupInfoV2 groupInfoV2, Set<UUID> uuids
|
GroupInfoV2 groupInfoV2, Set<UUID> uuids
|
||||||
) throws IOException {
|
) throws IOException {
|
||||||
final GroupsV2Operations.GroupOperations groupOperations = getGroupOperations(groupInfoV2);
|
final GroupsV2Operations.GroupOperations groupOperations = getGroupOperations(groupInfoV2);
|
||||||
return commitChange(groupInfoV2, groupOperations.createRemoveMembersChange(uuids));
|
return commitChange(groupInfoV2, groupOperations.createRemoveMembersChange(uuids, false));
|
||||||
}
|
}
|
||||||
|
|
||||||
private Pair<DecryptedGroup, GroupChange> commitChange(
|
private Pair<DecryptedGroup, GroupChange> commitChange(
|
||||||
|
@ -453,7 +431,7 @@ class GroupV2Helper {
|
||||||
}
|
}
|
||||||
|
|
||||||
var signedGroupChange = dependencies.getGroupsV2Api()
|
var signedGroupChange = dependencies.getGroupsV2Api()
|
||||||
.patchGroup(changeActions, getGroupAuthForToday(groupSecretParams), Optional.absent());
|
.patchGroup(changeActions, getGroupAuthForToday(groupSecretParams), Optional.empty());
|
||||||
|
|
||||||
return new Pair<>(decryptedGroupState, signedGroupChange);
|
return new Pair<>(decryptedGroupState, signedGroupChange);
|
||||||
}
|
}
|
||||||
|
@ -470,7 +448,7 @@ class GroupV2Helper {
|
||||||
return dependencies.getGroupsV2Api()
|
return dependencies.getGroupsV2Api()
|
||||||
.patchGroup(changeActions,
|
.patchGroup(changeActions,
|
||||||
getGroupAuthForToday(groupSecretParams),
|
getGroupAuthForToday(groupSecretParams),
|
||||||
Optional.fromNullable(password).transform(GroupLinkPassword::serialize));
|
Optional.ofNullable(password).map(GroupLinkPassword::serialize));
|
||||||
}
|
}
|
||||||
|
|
||||||
DecryptedGroup getUpdatedDecryptedGroup(
|
DecryptedGroup getUpdatedDecryptedGroup(
|
||||||
|
@ -493,7 +471,7 @@ class GroupV2Helper {
|
||||||
.forGroup(GroupSecretParams.deriveFromMasterKey(groupMasterKey));
|
.forGroup(GroupSecretParams.deriveFromMasterKey(groupMasterKey));
|
||||||
|
|
||||||
try {
|
try {
|
||||||
return groupOperations.decryptChange(GroupChange.parseFrom(signedGroupChange), true).orNull();
|
return groupOperations.decryptChange(GroupChange.parseFrom(signedGroupChange), true).orElse(null);
|
||||||
} catch (VerificationFailedException | InvalidGroupStateException | InvalidProtocolBufferException e) {
|
} catch (VerificationFailedException | InvalidGroupStateException | InvalidProtocolBufferException e) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
|
@ -270,7 +270,7 @@ public final class IncomingMessageHandler {
|
||||||
final DecryptionErrorMessage message
|
final DecryptionErrorMessage message
|
||||||
) {
|
) {
|
||||||
final var logEntries = account.getMessageSendLogStore()
|
final var logEntries = account.getMessageSendLogStore()
|
||||||
.findMessages(sender, senderDeviceId, message.getTimestamp(), !message.getRatchetKey().isPresent());
|
.findMessages(sender, senderDeviceId, message.getTimestamp(), message.getRatchetKey().isEmpty());
|
||||||
|
|
||||||
for (final var logEntry : logEntries) {
|
for (final var logEntry : logEntries) {
|
||||||
actions.add(new ResendMessageAction(sender, message.getTimestamp(), logEntry));
|
actions.add(new ResendMessageAction(sender, message.getTimestamp(), logEntry));
|
||||||
|
@ -318,7 +318,7 @@ public final class IncomingMessageHandler {
|
||||||
account.setMultiDevice(true);
|
account.setMultiDevice(true);
|
||||||
if (syncMessage.getSent().isPresent()) {
|
if (syncMessage.getSent().isPresent()) {
|
||||||
var message = syncMessage.getSent().get();
|
var message = syncMessage.getSent().get();
|
||||||
final var destination = message.getDestination().orNull();
|
final var destination = message.getDestination().orElse(null);
|
||||||
actions.addAll(handleSignalServiceDataMessage(message.getMessage(),
|
actions.addAll(handleSignalServiceDataMessage(message.getMessage(),
|
||||||
true,
|
true,
|
||||||
sender,
|
sender,
|
||||||
|
@ -388,11 +388,11 @@ public final class IncomingMessageHandler {
|
||||||
if (syncMessage.getStickerPackOperations().isPresent()) {
|
if (syncMessage.getStickerPackOperations().isPresent()) {
|
||||||
final var stickerPackOperationMessages = syncMessage.getStickerPackOperations().get();
|
final var stickerPackOperationMessages = syncMessage.getStickerPackOperations().get();
|
||||||
for (var m : stickerPackOperationMessages) {
|
for (var m : stickerPackOperationMessages) {
|
||||||
if (!m.getPackId().isPresent()) {
|
if (m.getPackId().isEmpty()) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
final var stickerPackId = StickerPackId.deserialize(m.getPackId().get());
|
final var stickerPackId = StickerPackId.deserialize(m.getPackId().get());
|
||||||
final var installed = !m.getType().isPresent()
|
final var installed = m.getType().isEmpty()
|
||||||
|| m.getType().get() == StickerPackOperationMessage.Type.INSTALL;
|
|| m.getType().get() == StickerPackOperationMessage.Type.INSTALL;
|
||||||
|
|
||||||
var sticker = account.getStickerStore().getStickerPack(stickerPackId);
|
var sticker = account.getStickerStore().getStickerPack(stickerPackId);
|
||||||
|
@ -488,12 +488,12 @@ public final class IncomingMessageHandler {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (content == null || !content.getDataMessage().isPresent()) {
|
if (content == null || content.getDataMessage().isEmpty()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
var message = content.getDataMessage().get();
|
var message = content.getDataMessage().get();
|
||||||
if (!message.getGroupContext().isPresent()) {
|
if (message.getGroupContext().isEmpty()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -15,8 +15,8 @@ import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
import org.whispersystems.libsignal.IdentityKey;
|
import org.whispersystems.libsignal.IdentityKey;
|
||||||
import org.whispersystems.libsignal.InvalidKeyException;
|
import org.whispersystems.libsignal.InvalidKeyException;
|
||||||
import org.whispersystems.libsignal.util.guava.Optional;
|
|
||||||
import org.whispersystems.signalservice.api.crypto.UnidentifiedAccess;
|
import org.whispersystems.signalservice.api.crypto.UnidentifiedAccess;
|
||||||
|
import org.whispersystems.signalservice.api.profiles.AvatarUploadParams;
|
||||||
import org.whispersystems.signalservice.api.profiles.ProfileAndCredential;
|
import org.whispersystems.signalservice.api.profiles.ProfileAndCredential;
|
||||||
import org.whispersystems.signalservice.api.profiles.SignalServiceProfile;
|
import org.whispersystems.signalservice.api.profiles.SignalServiceProfile;
|
||||||
import org.whispersystems.signalservice.api.push.SignalServiceAddress;
|
import org.whispersystems.signalservice.api.push.SignalServiceAddress;
|
||||||
|
@ -33,6 +33,7 @@ import java.util.Date;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
import java.util.Optional;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import io.reactivex.rxjava3.core.Flowable;
|
import io.reactivex.rxjava3.core.Flowable;
|
||||||
|
@ -130,20 +131,23 @@ public final class ProfileHelper {
|
||||||
var newProfile = builder.build();
|
var newProfile = builder.build();
|
||||||
|
|
||||||
if (uploadProfile) {
|
if (uploadProfile) {
|
||||||
try (final var streamDetails = avatar == null
|
try (final var streamDetails = avatar != null && avatar.isPresent() ? Utils.createStreamDetailsFromFile(
|
||||||
? context.getAvatarStore()
|
avatar.get()) : null) {
|
||||||
.retrieveProfileAvatar(account.getSelfRecipientAddress())
|
final var avatarUploadParams = avatar == null
|
||||||
: avatar.isPresent() ? Utils.createStreamDetailsFromFile(avatar.get()) : null) {
|
? AvatarUploadParams.unchanged(true)
|
||||||
|
: avatar.isPresent()
|
||||||
|
? AvatarUploadParams.forAvatar(streamDetails)
|
||||||
|
: AvatarUploadParams.unchanged(false);
|
||||||
final var avatarPath = dependencies.getAccountManager()
|
final var avatarPath = dependencies.getAccountManager()
|
||||||
.setVersionedProfile(account.getAci(),
|
.setVersionedProfile(account.getAci(),
|
||||||
account.getProfileKey(),
|
account.getProfileKey(),
|
||||||
newProfile.getInternalServiceName(),
|
newProfile.getInternalServiceName(),
|
||||||
newProfile.getAbout() == null ? "" : newProfile.getAbout(),
|
newProfile.getAbout() == null ? "" : newProfile.getAbout(),
|
||||||
newProfile.getAboutEmoji() == null ? "" : newProfile.getAboutEmoji(),
|
newProfile.getAboutEmoji() == null ? "" : newProfile.getAboutEmoji(),
|
||||||
Optional.absent(),
|
Optional.empty(),
|
||||||
streamDetails,
|
avatarUploadParams,
|
||||||
List.of(/* TODO */));
|
List.of(/* TODO */));
|
||||||
builder.withAvatarUrlPath(avatarPath.orNull());
|
builder.withAvatarUrlPath(avatarPath.orElse(null));
|
||||||
newProfile = builder.build();
|
newProfile = builder.build();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -202,7 +206,7 @@ public final class ProfileHelper {
|
||||||
|
|
||||||
private SignalServiceProfile retrieveProfileSync(String username) throws IOException {
|
private SignalServiceProfile retrieveProfileSync(String username) throws IOException {
|
||||||
final var locale = Utils.getDefaultLocale(Locale.US);
|
final var locale = Utils.getDefaultLocale(Locale.US);
|
||||||
return dependencies.getMessageReceiver().retrieveProfileByUsername(username, Optional.absent(), locale);
|
return dependencies.getMessageReceiver().retrieveProfileByUsername(username, Optional.empty(), locale);
|
||||||
}
|
}
|
||||||
|
|
||||||
private Profile decryptProfileAndDownloadAvatar(
|
private Profile decryptProfileAndDownloadAvatar(
|
||||||
|
@ -246,7 +250,7 @@ public final class ProfileHelper {
|
||||||
RecipientId recipientId, SignalServiceProfile.RequestType requestType
|
RecipientId recipientId, SignalServiceProfile.RequestType requestType
|
||||||
) {
|
) {
|
||||||
var unidentifiedAccess = getUnidentifiedAccess(recipientId);
|
var unidentifiedAccess = getUnidentifiedAccess(recipientId);
|
||||||
var profileKey = Optional.fromNullable(account.getProfileStore().getProfileKey(recipientId));
|
var profileKey = Optional.ofNullable(account.getProfileStore().getProfileKey(recipientId));
|
||||||
|
|
||||||
logger.trace("Retrieving profile for {} {}",
|
logger.trace("Retrieving profile for {} {}",
|
||||||
recipientId,
|
recipientId,
|
||||||
|
@ -259,7 +263,7 @@ public final class ProfileHelper {
|
||||||
if (requestType == SignalServiceProfile.RequestType.PROFILE_AND_CREDENTIAL
|
if (requestType == SignalServiceProfile.RequestType.PROFILE_AND_CREDENTIAL
|
||||||
|| account.getProfileStore().getProfileKeyCredential(recipientId) == null) {
|
|| account.getProfileStore().getProfileKeyCredential(recipientId) == null) {
|
||||||
logger.trace("Storing profile credential");
|
logger.trace("Storing profile credential");
|
||||||
final var profileKeyCredential = p.getProfileKeyCredential().orNull();
|
final var profileKeyCredential = p.getProfileKeyCredential().orElse(null);
|
||||||
account.getProfileStore().storeProfileKeyCredential(recipientId, profileKeyCredential);
|
account.getProfileStore().storeProfileKeyCredential(recipientId, profileKeyCredential);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -324,8 +328,8 @@ public final class ProfileHelper {
|
||||||
throw new NotFoundException("Profile not found");
|
throw new NotFoundException("Profile not found");
|
||||||
} else {
|
} else {
|
||||||
throw pair.getExecutionError()
|
throw pair.getExecutionError()
|
||||||
.or(pair.getApplicationError())
|
.or(pair::getApplicationError)
|
||||||
.or(new IOException("Unknown error while retrieving profile"));
|
.orElseThrow(() -> new IOException("Unknown error while retrieving profile"));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -380,6 +384,6 @@ public final class ProfileHelper {
|
||||||
return unidentifiedAccess.get().getTargetUnidentifiedAccess();
|
return unidentifiedAccess.get().getTargetUnidentifiedAccess();
|
||||||
}
|
}
|
||||||
|
|
||||||
return Optional.absent();
|
return Optional.empty();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -91,7 +91,7 @@ public class RecipientHelper {
|
||||||
|
|
||||||
public RecipientId refreshRegisteredUser(RecipientId recipientId) throws IOException, UnregisteredRecipientException {
|
public RecipientId refreshRegisteredUser(RecipientId recipientId) throws IOException, UnregisteredRecipientException {
|
||||||
final var address = resolveSignalServiceAddress(recipientId);
|
final var address = resolveSignalServiceAddress(recipientId);
|
||||||
if (!address.getNumber().isPresent()) {
|
if (address.getNumber().isEmpty()) {
|
||||||
return recipientId;
|
return recipientId;
|
||||||
}
|
}
|
||||||
final var number = address.getNumber().get();
|
final var number = address.getNumber().get();
|
||||||
|
|
|
@ -21,7 +21,6 @@ import org.whispersystems.libsignal.InvalidRegistrationIdException;
|
||||||
import org.whispersystems.libsignal.NoSessionException;
|
import org.whispersystems.libsignal.NoSessionException;
|
||||||
import org.whispersystems.libsignal.SignalProtocolAddress;
|
import org.whispersystems.libsignal.SignalProtocolAddress;
|
||||||
import org.whispersystems.libsignal.protocol.DecryptionErrorMessage;
|
import org.whispersystems.libsignal.protocol.DecryptionErrorMessage;
|
||||||
import org.whispersystems.libsignal.util.guava.Optional;
|
|
||||||
import org.whispersystems.signalservice.api.SignalServiceMessageSender;
|
import org.whispersystems.signalservice.api.SignalServiceMessageSender;
|
||||||
import org.whispersystems.signalservice.api.crypto.ContentHint;
|
import org.whispersystems.signalservice.api.crypto.ContentHint;
|
||||||
import org.whispersystems.signalservice.api.crypto.UnidentifiedAccess;
|
import org.whispersystems.signalservice.api.crypto.UnidentifiedAccess;
|
||||||
|
@ -47,6 +46,7 @@ import java.util.ArrayList;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Optional;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
import java.util.concurrent.atomic.AtomicLong;
|
import java.util.concurrent.atomic.AtomicLong;
|
||||||
|
@ -138,7 +138,7 @@ public class SendHelper {
|
||||||
final var result = handleSendMessage(recipientId,
|
final var result = handleSendMessage(recipientId,
|
||||||
(messageSender, address, unidentifiedAccess) -> messageSender.sendRetryReceipt(address,
|
(messageSender, address, unidentifiedAccess) -> messageSender.sendRetryReceipt(address,
|
||||||
unidentifiedAccess,
|
unidentifiedAccess,
|
||||||
groupId.transform(GroupId::serialize),
|
groupId.map(GroupId::serialize),
|
||||||
errorMessage));
|
errorMessage));
|
||||||
handleSendMessageResult(result);
|
handleSendMessageResult(result);
|
||||||
return result;
|
return result;
|
||||||
|
@ -222,7 +222,7 @@ public class SendHelper {
|
||||||
timestamp,
|
timestamp,
|
||||||
messageSendLogEntry.content(),
|
messageSendLogEntry.content(),
|
||||||
messageSendLogEntry.contentHint(),
|
messageSendLogEntry.contentHint(),
|
||||||
Optional.absent()));
|
Optional.empty()));
|
||||||
}
|
}
|
||||||
|
|
||||||
final var groupId = messageSendLogEntry.groupId().get();
|
final var groupId = messageSendLogEntry.groupId().get();
|
||||||
|
@ -457,7 +457,7 @@ public class SendHelper {
|
||||||
}
|
}
|
||||||
|
|
||||||
final var access = context.getUnidentifiedAccessHelper().getAccessFor(recipientId);
|
final var access = context.getUnidentifiedAccessHelper().getAccessFor(recipientId);
|
||||||
if (!access.isPresent() || !access.get().getTargetUnidentifiedAccess().isPresent()) {
|
if (access.isEmpty() || access.get().getTargetUnidentifiedAccess().isEmpty()) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -64,14 +64,14 @@ public class StickerHelper {
|
||||||
context.getStickerPackStore().storeSticker(packId, id, o -> IOUtils.copyStream(inputStream, o));
|
context.getStickerPackStore().storeSticker(packId, id, o -> IOUtils.copyStream(inputStream, o));
|
||||||
}
|
}
|
||||||
|
|
||||||
final var jsonManifest = new JsonStickerPack(manifest.getTitle().orNull(),
|
final var jsonManifest = new JsonStickerPack(manifest.getTitle().orElse(null),
|
||||||
manifest.getAuthor().orNull(),
|
manifest.getAuthor().orElse(null),
|
||||||
manifest.getCover()
|
manifest.getCover()
|
||||||
.transform(c -> new JsonStickerPack.JsonSticker(c.getId(),
|
.map(c -> new JsonStickerPack.JsonSticker(c.getId(),
|
||||||
c.getEmoji(),
|
c.getEmoji(),
|
||||||
String.valueOf(c.getId()),
|
String.valueOf(c.getId()),
|
||||||
c.getContentType()))
|
c.getContentType()))
|
||||||
.orNull(),
|
.orElse(null),
|
||||||
manifest.getStickers()
|
manifest.getStickers()
|
||||||
.stream()
|
.stream()
|
||||||
.map(c -> new JsonStickerPack.JsonSticker(c.getId(),
|
.map(c -> new JsonStickerPack.JsonSticker(c.getId(),
|
||||||
|
|
|
@ -13,7 +13,6 @@ import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
import org.whispersystems.libsignal.IdentityKey;
|
import org.whispersystems.libsignal.IdentityKey;
|
||||||
import org.whispersystems.libsignal.InvalidKeyException;
|
import org.whispersystems.libsignal.InvalidKeyException;
|
||||||
import org.whispersystems.libsignal.util.guava.Optional;
|
|
||||||
import org.whispersystems.signalservice.api.storage.SignalAccountRecord;
|
import org.whispersystems.signalservice.api.storage.SignalAccountRecord;
|
||||||
import org.whispersystems.signalservice.api.storage.SignalStorageManifest;
|
import org.whispersystems.signalservice.api.storage.SignalStorageManifest;
|
||||||
import org.whispersystems.signalservice.api.storage.SignalStorageRecord;
|
import org.whispersystems.signalservice.api.storage.SignalStorageRecord;
|
||||||
|
@ -25,6 +24,7 @@ import java.io.IOException;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
public class StorageHelper {
|
public class StorageHelper {
|
||||||
|
|
||||||
|
@ -51,7 +51,7 @@ public class StorageHelper {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!manifest.isPresent()) {
|
if (manifest.isEmpty()) {
|
||||||
logger.debug("Manifest is up to date, does not exist or couldn't be decrypted, ignoring.");
|
logger.debug("Manifest is up to date, does not exist or couldn't be decrypted, ignoring.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -79,7 +79,7 @@ public class StorageHelper {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void readContactRecord(final SignalStorageRecord record) {
|
private void readContactRecord(final SignalStorageRecord record) {
|
||||||
if (record == null || !record.getContact().isPresent()) {
|
if (record == null || record.getContact().isEmpty()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -92,9 +92,9 @@ public class StorageHelper {
|
||||||
(contact == null || !contact.isBlocked()) && contactRecord.isBlocked()
|
(contact == null || !contact.isBlocked()) && contactRecord.isBlocked()
|
||||||
)) {
|
)) {
|
||||||
final var newContact = (contact == null ? Contact.newBuilder() : Contact.newBuilder(contact)).withBlocked(
|
final var newContact = (contact == null ? Contact.newBuilder() : Contact.newBuilder(contact)).withBlocked(
|
||||||
contactRecord.isBlocked())
|
contactRecord.isBlocked()).withName((
|
||||||
.withName((contactRecord.getGivenName().or("") + " " + contactRecord.getFamilyName().or("")).trim())
|
contactRecord.getGivenName().orElse("") + " " + contactRecord.getFamilyName().orElse("")
|
||||||
.build();
|
).trim()).build();
|
||||||
account.getContactStore().storeContact(recipientId, newContact);
|
account.getContactStore().storeContact(recipientId, newContact);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -122,7 +122,7 @@ public class StorageHelper {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void readGroupV1Record(final SignalStorageRecord record) {
|
private void readGroupV1Record(final SignalStorageRecord record) {
|
||||||
if (record == null || !record.getGroupV1().isPresent()) {
|
if (record == null || record.getGroupV1().isEmpty()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -145,7 +145,7 @@ public class StorageHelper {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void readGroupV2Record(final SignalStorageRecord record) {
|
private void readGroupV2Record(final SignalStorageRecord record) {
|
||||||
if (record == null || !record.getGroupV2().isPresent()) {
|
if (record == null || record.getGroupV2().isEmpty()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -171,7 +171,7 @@ public class StorageHelper {
|
||||||
|
|
||||||
private void readAccountRecord(final SignalStorageManifest manifest) throws IOException {
|
private void readAccountRecord(final SignalStorageManifest manifest) throws IOException {
|
||||||
Optional<StorageId> accountId = manifest.getAccountStorageId();
|
Optional<StorageId> accountId = manifest.getAccountStorageId();
|
||||||
if (!accountId.isPresent()) {
|
if (accountId.isEmpty()) {
|
||||||
logger.warn("Manifest has no account record, ignoring.");
|
logger.warn("Manifest has no account record, ignoring.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -182,7 +182,7 @@ public class StorageHelper {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
SignalAccountRecord accountRecord = record.getAccount().orNull();
|
SignalAccountRecord accountRecord = record.getAccount().orElse(null);
|
||||||
if (accountRecord == null) {
|
if (accountRecord == null) {
|
||||||
logger.warn("The storage record didn't actually have an account, ignoring.");
|
logger.warn("The storage record didn't actually have an account, ignoring.");
|
||||||
return;
|
return;
|
||||||
|
@ -217,15 +217,15 @@ public class StorageHelper {
|
||||||
}
|
}
|
||||||
if (profileKey != null) {
|
if (profileKey != null) {
|
||||||
account.setProfileKey(profileKey);
|
account.setProfileKey(profileKey);
|
||||||
final var avatarPath = accountRecord.getAvatarUrlPath().orNull();
|
final var avatarPath = accountRecord.getAvatarUrlPath().orElse(null);
|
||||||
context.getProfileHelper().downloadProfileAvatar(account.getSelfRecipientId(), avatarPath, profileKey);
|
context.getProfileHelper().downloadProfileAvatar(account.getSelfRecipientId(), avatarPath, profileKey);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
context.getProfileHelper()
|
context.getProfileHelper()
|
||||||
.setProfile(false,
|
.setProfile(false,
|
||||||
accountRecord.getGivenName().orNull(),
|
accountRecord.getGivenName().orElse(null),
|
||||||
accountRecord.getFamilyName().orNull(),
|
accountRecord.getFamilyName().orElse(null),
|
||||||
null,
|
null,
|
||||||
null,
|
null,
|
||||||
null);
|
null);
|
||||||
|
|
|
@ -12,7 +12,6 @@ import org.asamk.signal.manager.util.IOUtils;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
import org.whispersystems.libsignal.IdentityKey;
|
import org.whispersystems.libsignal.IdentityKey;
|
||||||
import org.whispersystems.libsignal.util.guava.Optional;
|
|
||||||
import org.whispersystems.signalservice.api.messages.SignalServiceAttachment;
|
import org.whispersystems.signalservice.api.messages.SignalServiceAttachment;
|
||||||
import org.whispersystems.signalservice.api.messages.SignalServiceAttachmentStream;
|
import org.whispersystems.signalservice.api.messages.SignalServiceAttachmentStream;
|
||||||
import org.whispersystems.signalservice.api.messages.multidevice.BlockedListMessage;
|
import org.whispersystems.signalservice.api.messages.multidevice.BlockedListMessage;
|
||||||
|
@ -37,6 +36,7 @@ import java.io.InputStream;
|
||||||
import java.io.OutputStream;
|
import java.io.OutputStream;
|
||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
public class SyncHelper {
|
public class SyncHelper {
|
||||||
|
|
||||||
|
@ -81,7 +81,7 @@ public class SyncHelper {
|
||||||
for (var record : account.getGroupStore().getGroups()) {
|
for (var record : account.getGroupStore().getGroups()) {
|
||||||
if (record instanceof GroupInfoV1 groupInfo) {
|
if (record instanceof GroupInfoV1 groupInfo) {
|
||||||
out.write(new DeviceGroup(groupInfo.getGroupId().serialize(),
|
out.write(new DeviceGroup(groupInfo.getGroupId().serialize(),
|
||||||
Optional.fromNullable(groupInfo.name),
|
Optional.ofNullable(groupInfo.name),
|
||||||
groupInfo.getMembers()
|
groupInfo.getMembers()
|
||||||
.stream()
|
.stream()
|
||||||
.map(context.getRecipientHelper()::resolveSignalServiceAddress)
|
.map(context.getRecipientHelper()::resolveSignalServiceAddress)
|
||||||
|
@ -89,9 +89,9 @@ public class SyncHelper {
|
||||||
context.getGroupHelper().createGroupAvatarAttachment(groupInfo.getGroupId()),
|
context.getGroupHelper().createGroupAvatarAttachment(groupInfo.getGroupId()),
|
||||||
groupInfo.isMember(account.getSelfRecipientId()),
|
groupInfo.isMember(account.getSelfRecipientId()),
|
||||||
Optional.of(groupInfo.messageExpirationTime),
|
Optional.of(groupInfo.messageExpirationTime),
|
||||||
Optional.fromNullable(groupInfo.color),
|
Optional.ofNullable(groupInfo.color),
|
||||||
groupInfo.blocked,
|
groupInfo.blocked,
|
||||||
Optional.absent(),
|
Optional.empty(),
|
||||||
groupInfo.archived));
|
groupInfo.archived));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -139,28 +139,28 @@ public class SyncHelper {
|
||||||
|
|
||||||
var profileKey = account.getProfileStore().getProfileKey(recipientId);
|
var profileKey = account.getProfileStore().getProfileKey(recipientId);
|
||||||
out.write(new DeviceContact(address,
|
out.write(new DeviceContact(address,
|
||||||
Optional.fromNullable(contact.getName()),
|
Optional.ofNullable(contact.getName()),
|
||||||
createContactAvatarAttachment(new RecipientAddress(address)),
|
createContactAvatarAttachment(new RecipientAddress(address)),
|
||||||
Optional.fromNullable(contact.getColor()),
|
Optional.ofNullable(contact.getColor()),
|
||||||
Optional.fromNullable(verifiedMessage),
|
Optional.ofNullable(verifiedMessage),
|
||||||
Optional.fromNullable(profileKey),
|
Optional.ofNullable(profileKey),
|
||||||
contact.isBlocked(),
|
contact.isBlocked(),
|
||||||
Optional.of(contact.getMessageExpirationTime()),
|
Optional.of(contact.getMessageExpirationTime()),
|
||||||
Optional.absent(),
|
Optional.empty(),
|
||||||
contact.isArchived()));
|
contact.isArchived()));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (account.getProfileKey() != null) {
|
if (account.getProfileKey() != null) {
|
||||||
// Send our own profile key as well
|
// Send our own profile key as well
|
||||||
out.write(new DeviceContact(account.getSelfAddress(),
|
out.write(new DeviceContact(account.getSelfAddress(),
|
||||||
Optional.absent(),
|
Optional.empty(),
|
||||||
Optional.absent(),
|
Optional.empty(),
|
||||||
Optional.absent(),
|
Optional.empty(),
|
||||||
Optional.absent(),
|
Optional.empty(),
|
||||||
Optional.of(account.getProfileKey()),
|
Optional.of(account.getProfileKey()),
|
||||||
false,
|
false,
|
||||||
Optional.absent(),
|
Optional.empty(),
|
||||||
Optional.absent(),
|
Optional.empty(),
|
||||||
false));
|
false));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -215,16 +215,16 @@ public class SyncHelper {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void sendKeysMessage() {
|
public void sendKeysMessage() {
|
||||||
var keysMessage = new KeysMessage(Optional.fromNullable(account.getStorageKey()));
|
var keysMessage = new KeysMessage(Optional.ofNullable(account.getStorageKey()));
|
||||||
context.getSendHelper().sendSyncMessage(SignalServiceSyncMessage.forKeys(keysMessage));
|
context.getSendHelper().sendSyncMessage(SignalServiceSyncMessage.forKeys(keysMessage));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void sendConfigurationMessage() {
|
public void sendConfigurationMessage() {
|
||||||
final var config = account.getConfigurationStore();
|
final var config = account.getConfigurationStore();
|
||||||
var configurationMessage = new ConfigurationMessage(Optional.fromNullable(config.getReadReceipts()),
|
var configurationMessage = new ConfigurationMessage(Optional.ofNullable(config.getReadReceipts()),
|
||||||
Optional.fromNullable(config.getUnidentifiedDeliveryIndicators()),
|
Optional.ofNullable(config.getUnidentifiedDeliveryIndicators()),
|
||||||
Optional.fromNullable(config.getTypingIndicators()),
|
Optional.ofNullable(config.getTypingIndicators()),
|
||||||
Optional.fromNullable(config.getLinkPreviews()));
|
Optional.ofNullable(config.getLinkPreviews()));
|
||||||
context.getSendHelper().sendSyncMessage(SignalServiceSyncMessage.forConfiguration(configurationMessage));
|
context.getSendHelper().sendSyncMessage(SignalServiceSyncMessage.forConfiguration(configurationMessage));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -299,10 +299,10 @@ public class SyncHelper {
|
||||||
private Optional<SignalServiceAttachmentStream> createContactAvatarAttachment(RecipientAddress address) throws IOException {
|
private Optional<SignalServiceAttachmentStream> createContactAvatarAttachment(RecipientAddress address) throws IOException {
|
||||||
final var streamDetails = context.getAvatarStore().retrieveContactAvatar(address);
|
final var streamDetails = context.getAvatarStore().retrieveContactAvatar(address);
|
||||||
if (streamDetails == null) {
|
if (streamDetails == null) {
|
||||||
return Optional.absent();
|
return Optional.empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
return Optional.of(AttachmentUtils.createAttachment(streamDetails, Optional.absent()));
|
return Optional.of(AttachmentUtils.createAttachment(streamDetails, Optional.empty()));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void downloadContactAvatar(SignalServiceAttachment avatar, RecipientAddress address) {
|
private void downloadContactAvatar(SignalServiceAttachment avatar, RecipientAddress address) {
|
||||||
|
|
|
@ -10,12 +10,12 @@ import org.signal.libsignal.metadata.certificate.SenderCertificate;
|
||||||
import org.signal.zkgroup.profiles.ProfileKey;
|
import org.signal.zkgroup.profiles.ProfileKey;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
import org.whispersystems.libsignal.util.guava.Optional;
|
|
||||||
import org.whispersystems.signalservice.api.crypto.UnidentifiedAccess;
|
import org.whispersystems.signalservice.api.crypto.UnidentifiedAccess;
|
||||||
import org.whispersystems.signalservice.api.crypto.UnidentifiedAccessPair;
|
import org.whispersystems.signalservice.api.crypto.UnidentifiedAccessPair;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Optional;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
public class UnidentifiedAccessHelper {
|
public class UnidentifiedAccessHelper {
|
||||||
|
@ -54,26 +54,26 @@ public class UnidentifiedAccessHelper {
|
||||||
var recipientUnidentifiedAccessKey = getTargetUnidentifiedAccessKey(recipientId, noRefresh);
|
var recipientUnidentifiedAccessKey = getTargetUnidentifiedAccessKey(recipientId, noRefresh);
|
||||||
if (recipientUnidentifiedAccessKey == null) {
|
if (recipientUnidentifiedAccessKey == null) {
|
||||||
logger.trace("Unidentified access not available for {}", recipientId);
|
logger.trace("Unidentified access not available for {}", recipientId);
|
||||||
return Optional.absent();
|
return Optional.empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
var selfUnidentifiedAccessKey = getSelfUnidentifiedAccessKey(noRefresh);
|
var selfUnidentifiedAccessKey = getSelfUnidentifiedAccessKey(noRefresh);
|
||||||
if (selfUnidentifiedAccessKey == null) {
|
if (selfUnidentifiedAccessKey == null) {
|
||||||
logger.trace("Unidentified access not available for self");
|
logger.trace("Unidentified access not available for self");
|
||||||
return Optional.absent();
|
return Optional.empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
var senderCertificate = getSenderCertificateFor(recipientId);
|
var senderCertificate = getSenderCertificateFor(recipientId);
|
||||||
if (senderCertificate == null) {
|
if (senderCertificate == null) {
|
||||||
logger.trace("Unidentified access not available due to missing sender certificate");
|
logger.trace("Unidentified access not available due to missing sender certificate");
|
||||||
return Optional.absent();
|
return Optional.empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
return Optional.of(new UnidentifiedAccessPair(new UnidentifiedAccess(recipientUnidentifiedAccessKey,
|
return Optional.of(new UnidentifiedAccessPair(new UnidentifiedAccess(recipientUnidentifiedAccessKey,
|
||||||
senderCertificate), new UnidentifiedAccess(selfUnidentifiedAccessKey, senderCertificate)));
|
senderCertificate), new UnidentifiedAccess(selfUnidentifiedAccessKey, senderCertificate)));
|
||||||
} catch (InvalidCertificateException e) {
|
} catch (InvalidCertificateException e) {
|
||||||
return Optional.absent();
|
return Optional.empty();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -82,7 +82,7 @@ public class UnidentifiedAccessHelper {
|
||||||
var selfUnidentifiedAccessCertificate = getSenderCertificate();
|
var selfUnidentifiedAccessCertificate = getSenderCertificate();
|
||||||
|
|
||||||
if (selfUnidentifiedAccessKey == null || selfUnidentifiedAccessCertificate == null) {
|
if (selfUnidentifiedAccessKey == null || selfUnidentifiedAccessCertificate == null) {
|
||||||
return Optional.absent();
|
return Optional.empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
@ -90,7 +90,7 @@ public class UnidentifiedAccessHelper {
|
||||||
selfUnidentifiedAccessCertificate),
|
selfUnidentifiedAccessCertificate),
|
||||||
new UnidentifiedAccess(selfUnidentifiedAccessKey, selfUnidentifiedAccessCertificate)));
|
new UnidentifiedAccess(selfUnidentifiedAccessKey, selfUnidentifiedAccessCertificate)));
|
||||||
} catch (InvalidCertificateException e) {
|
} catch (InvalidCertificateException e) {
|
||||||
return Optional.absent();
|
return Optional.empty();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -705,9 +705,6 @@ public class SignalAccount implements Closeable {
|
||||||
if (profile.getCapabilities().gv1Migration) {
|
if (profile.getCapabilities().gv1Migration) {
|
||||||
capabilities.add(Profile.Capability.gv1Migration);
|
capabilities.add(Profile.Capability.gv1Migration);
|
||||||
}
|
}
|
||||||
if (profile.getCapabilities().gv2) {
|
|
||||||
capabilities.add(Profile.Capability.gv2);
|
|
||||||
}
|
|
||||||
if (profile.getCapabilities().storage) {
|
if (profile.getCapabilities().storage) {
|
||||||
capabilities.add(Profile.Capability.storage);
|
capabilities.add(Profile.Capability.storage);
|
||||||
}
|
}
|
||||||
|
|
|
@ -88,9 +88,6 @@ public class SignalProfile {
|
||||||
@JsonIgnore
|
@JsonIgnore
|
||||||
public boolean uuid;
|
public boolean uuid;
|
||||||
|
|
||||||
@JsonProperty
|
|
||||||
public boolean gv2;
|
|
||||||
|
|
||||||
@JsonProperty
|
@JsonProperty
|
||||||
public boolean storage;
|
public boolean storage;
|
||||||
|
|
||||||
|
|
|
@ -142,7 +142,6 @@ public class Profile {
|
||||||
}
|
}
|
||||||
|
|
||||||
public enum Capability {
|
public enum Capability {
|
||||||
gv2,
|
|
||||||
storage,
|
storage,
|
||||||
gv1Migration,
|
gv1Migration,
|
||||||
senderKey,
|
senderKey,
|
||||||
|
|
|
@ -28,7 +28,7 @@ public record RecipientAddress(Optional<UUID> uuid, Optional<String> number) {
|
||||||
}
|
}
|
||||||
|
|
||||||
public RecipientAddress(SignalServiceAddress address) {
|
public RecipientAddress(SignalServiceAddress address) {
|
||||||
this(Optional.of(address.getServiceId().uuid()), Optional.ofNullable(address.getNumber().orNull()));
|
this(Optional.of(address.getServiceId().uuid()), address.getNumber());
|
||||||
}
|
}
|
||||||
|
|
||||||
public RecipientAddress(UUID uuid) {
|
public RecipientAddress(UUID uuid) {
|
||||||
|
@ -62,7 +62,6 @@ public record RecipientAddress(Optional<UUID> uuid, Optional<String> number) {
|
||||||
}
|
}
|
||||||
|
|
||||||
public SignalServiceAddress toSignalServiceAddress() {
|
public SignalServiceAddress toSignalServiceAddress() {
|
||||||
return new SignalServiceAddress(ServiceId.from(uuid.orElse(UNKNOWN_UUID)),
|
return new SignalServiceAddress(ServiceId.from(uuid.orElse(UNKNOWN_UUID)), number);
|
||||||
org.whispersystems.libsignal.util.guava.Optional.fromNullable(number.orElse(null)));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
package org.asamk.signal.manager.util;
|
package org.asamk.signal.manager.util;
|
||||||
|
|
||||||
import org.asamk.signal.manager.api.AttachmentInvalidException;
|
import org.asamk.signal.manager.api.AttachmentInvalidException;
|
||||||
import org.whispersystems.libsignal.util.guava.Optional;
|
|
||||||
import org.whispersystems.signalservice.api.messages.SignalServiceAttachment;
|
import org.whispersystems.signalservice.api.messages.SignalServiceAttachment;
|
||||||
import org.whispersystems.signalservice.api.messages.SignalServiceAttachmentStream;
|
import org.whispersystems.signalservice.api.messages.SignalServiceAttachmentStream;
|
||||||
import org.whispersystems.signalservice.api.util.StreamDetails;
|
import org.whispersystems.signalservice.api.util.StreamDetails;
|
||||||
|
@ -11,6 +10,7 @@ import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
public class AttachmentUtils {
|
public class AttachmentUtils {
|
||||||
|
|
||||||
|
@ -39,10 +39,10 @@ public class AttachmentUtils {
|
||||||
) {
|
) {
|
||||||
// TODO mabybe add a parameter to set the voiceNote, borderless, preview, width, height and caption option
|
// TODO mabybe add a parameter to set the voiceNote, borderless, preview, width, height and caption option
|
||||||
final var uploadTimestamp = System.currentTimeMillis();
|
final var uploadTimestamp = System.currentTimeMillis();
|
||||||
Optional<byte[]> preview = Optional.absent();
|
Optional<byte[]> preview = Optional.empty();
|
||||||
Optional<String> caption = Optional.absent();
|
Optional<String> caption = Optional.empty();
|
||||||
Optional<String> blurHash = Optional.absent();
|
Optional<String> blurHash = Optional.empty();
|
||||||
final Optional<ResumableUploadSpec> resumableUploadSpec = Optional.absent();
|
final Optional<ResumableUploadSpec> resumableUploadSpec = Optional.empty();
|
||||||
return new SignalServiceAttachmentStream(streamDetails.getStream(),
|
return new SignalServiceAttachmentStream(streamDetails.getStream(),
|
||||||
streamDetails.getContentType(),
|
streamDetails.getContentType(),
|
||||||
streamDetails.getLength(),
|
streamDetails.getLength(),
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
package org.asamk.signal.manager.util;
|
package org.asamk.signal.manager.util;
|
||||||
|
|
||||||
import org.whispersystems.libsignal.util.guava.Optional;
|
|
||||||
import org.whispersystems.signalservice.api.messages.SignalServiceEnvelope;
|
import org.whispersystems.signalservice.api.messages.SignalServiceEnvelope;
|
||||||
import org.whispersystems.signalservice.api.push.ServiceId;
|
import org.whispersystems.signalservice.api.push.ServiceId;
|
||||||
import org.whispersystems.signalservice.api.push.SignalServiceAddress;
|
import org.whispersystems.signalservice.api.push.SignalServiceAddress;
|
||||||
|
@ -11,6 +10,7 @@ import java.io.File;
|
||||||
import java.io.FileInputStream;
|
import java.io.FileInputStream;
|
||||||
import java.io.FileOutputStream;
|
import java.io.FileOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
public class MessageCacheUtils {
|
public class MessageCacheUtils {
|
||||||
|
|
||||||
|
@ -59,7 +59,7 @@ public class MessageCacheUtils {
|
||||||
serverDeliveredTimestamp = in.readLong();
|
serverDeliveredTimestamp = in.readLong();
|
||||||
}
|
}
|
||||||
Optional<SignalServiceAddress> addressOptional = sourceServiceId == null
|
Optional<SignalServiceAddress> addressOptional = sourceServiceId == null
|
||||||
? Optional.absent()
|
? Optional.empty()
|
||||||
: Optional.of(new SignalServiceAddress(sourceServiceId, source));
|
: Optional.of(new SignalServiceAddress(sourceServiceId, source));
|
||||||
return new SignalServiceEnvelope(type,
|
return new SignalServiceEnvelope(type,
|
||||||
addressOptional,
|
addressOptional,
|
||||||
|
|
|
@ -5,7 +5,6 @@ import org.asamk.signal.manager.api.IncorrectPinException;
|
||||||
import org.asamk.signal.manager.api.Pair;
|
import org.asamk.signal.manager.api.Pair;
|
||||||
import org.asamk.signal.manager.api.PinLockedException;
|
import org.asamk.signal.manager.api.PinLockedException;
|
||||||
import org.asamk.signal.manager.helper.PinHelper;
|
import org.asamk.signal.manager.helper.PinHelper;
|
||||||
import org.whispersystems.libsignal.util.guava.Optional;
|
|
||||||
import org.whispersystems.signalservice.api.KbsPinData;
|
import org.whispersystems.signalservice.api.KbsPinData;
|
||||||
import org.whispersystems.signalservice.api.SignalServiceAccountManager;
|
import org.whispersystems.signalservice.api.SignalServiceAccountManager;
|
||||||
import org.whispersystems.signalservice.api.kbs.MasterKey;
|
import org.whispersystems.signalservice.api.kbs.MasterKey;
|
||||||
|
@ -15,6 +14,7 @@ import org.whispersystems.signalservice.internal.push.RequestVerificationCodeRes
|
||||||
import org.whispersystems.signalservice.internal.push.VerifyAccountResponse;
|
import org.whispersystems.signalservice.internal.push.VerifyAccountResponse;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
public class NumberVerificationUtils {
|
public class NumberVerificationUtils {
|
||||||
|
|
||||||
|
@ -26,14 +26,14 @@ public class NumberVerificationUtils {
|
||||||
final ServiceResponse<RequestVerificationCodeResponse> response;
|
final ServiceResponse<RequestVerificationCodeResponse> response;
|
||||||
if (voiceVerification) {
|
if (voiceVerification) {
|
||||||
response = accountManager.requestVoiceVerificationCode(Utils.getDefaultLocale(null),
|
response = accountManager.requestVoiceVerificationCode(Utils.getDefaultLocale(null),
|
||||||
Optional.fromNullable(captcha),
|
Optional.ofNullable(captcha),
|
||||||
Optional.absent(),
|
Optional.empty(),
|
||||||
Optional.absent());
|
Optional.empty());
|
||||||
} else {
|
} else {
|
||||||
response = accountManager.requestSmsVerificationCode(false,
|
response = accountManager.requestSmsVerificationCode(false,
|
||||||
Optional.fromNullable(captcha),
|
Optional.ofNullable(captcha),
|
||||||
Optional.absent(),
|
Optional.empty(),
|
||||||
Optional.absent());
|
Optional.empty());
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
handleResponseException(response);
|
handleResponseException(response);
|
||||||
|
@ -82,7 +82,7 @@ public class NumberVerificationUtils {
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void handleResponseException(final ServiceResponse<?> response) throws IOException {
|
private static void handleResponseException(final ServiceResponse<?> response) throws IOException {
|
||||||
final var throwableOptional = response.getExecutionError().or(response.getApplicationError());
|
final var throwableOptional = response.getExecutionError().or(response::getApplicationError);
|
||||||
if (throwableOptional.isPresent()) {
|
if (throwableOptional.isPresent()) {
|
||||||
if (throwableOptional.get() instanceof IOException) {
|
if (throwableOptional.get() instanceof IOException) {
|
||||||
throw (IOException) throwableOptional.get();
|
throw (IOException) throwableOptional.get();
|
||||||
|
|
|
@ -62,9 +62,6 @@ public class ProfileUtils {
|
||||||
if (encryptedProfile.getCapabilities().isGv1Migration()) {
|
if (encryptedProfile.getCapabilities().isGv1Migration()) {
|
||||||
capabilities.add(Profile.Capability.gv1Migration);
|
capabilities.add(Profile.Capability.gv1Migration);
|
||||||
}
|
}
|
||||||
if (encryptedProfile.getCapabilities().isGv2()) {
|
|
||||||
capabilities.add(Profile.Capability.gv2);
|
|
||||||
}
|
|
||||||
if (encryptedProfile.getCapabilities().isStorage()) {
|
if (encryptedProfile.getCapabilities().isStorage()) {
|
||||||
capabilities.add(Profile.Capability.storage);
|
capabilities.add(Profile.Capability.storage);
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,10 +2,9 @@ package org.asamk.signal.manager.util;
|
||||||
|
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
|
|
||||||
import org.asamk.signal.manager.api.StickerPackInvalidException;
|
|
||||||
import org.asamk.signal.manager.api.Pair;
|
import org.asamk.signal.manager.api.Pair;
|
||||||
|
import org.asamk.signal.manager.api.StickerPackInvalidException;
|
||||||
import org.asamk.signal.manager.storage.stickerPacks.JsonStickerPack;
|
import org.asamk.signal.manager.storage.stickerPacks.JsonStickerPack;
|
||||||
import org.whispersystems.libsignal.util.guava.Optional;
|
|
||||||
import org.whispersystems.signalservice.api.messages.SignalServiceStickerManifestUpload;
|
import org.whispersystems.signalservice.api.messages.SignalServiceStickerManifestUpload;
|
||||||
|
|
||||||
import java.io.BufferedInputStream;
|
import java.io.BufferedInputStream;
|
||||||
|
@ -15,6 +14,7 @@ import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.net.URLConnection;
|
import java.net.URLConnection;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Optional;
|
||||||
import java.util.zip.ZipFile;
|
import java.util.zip.ZipFile;
|
||||||
|
|
||||||
public class StickerUtils {
|
public class StickerUtils {
|
||||||
|
@ -61,7 +61,7 @@ public class StickerUtils {
|
||||||
: getContentType(rootPath, zip, sticker.file());
|
: getContentType(rootPath, zip, sticker.file());
|
||||||
var stickerInfo = new SignalServiceStickerManifestUpload.StickerInfo(data.first(),
|
var stickerInfo = new SignalServiceStickerManifestUpload.StickerInfo(data.first(),
|
||||||
data.second(),
|
data.second(),
|
||||||
Optional.fromNullable(sticker.emoji()).or(""),
|
Optional.ofNullable(sticker.emoji()).orElse(""),
|
||||||
contentType);
|
contentType);
|
||||||
stickers.add(stickerInfo);
|
stickers.add(stickerInfo);
|
||||||
}
|
}
|
||||||
|
@ -83,7 +83,7 @@ public class StickerUtils {
|
||||||
.contentType() : getContentType(rootPath, zip, pack.cover().file());
|
.contentType() : getContentType(rootPath, zip, pack.cover().file());
|
||||||
cover = new SignalServiceStickerManifestUpload.StickerInfo(data.first(),
|
cover = new SignalServiceStickerManifestUpload.StickerInfo(data.first(),
|
||||||
data.second(),
|
data.second(),
|
||||||
Optional.fromNullable(pack.cover().emoji()).or(""),
|
Optional.ofNullable(pack.cover().emoji()).orElse(""),
|
||||||
contentType);
|
contentType);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -70,7 +70,7 @@ public class Utils {
|
||||||
} else {
|
} else {
|
||||||
// Version 1: E164 user
|
// Version 1: E164 user
|
||||||
version = 1;
|
version = 1;
|
||||||
if (!ownAddress.getNumber().isPresent() || !theirAddress.getNumber().isPresent()) {
|
if (ownAddress.getNumber().isEmpty() || theirAddress.getNumber().isEmpty()) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
ownId = ownAddress.getNumber().get().getBytes();
|
ownId = ownAddress.getNumber().get().getBytes();
|
||||||
|
@ -102,7 +102,7 @@ public class Utils {
|
||||||
public static <L, R, T> Stream<T> zip(Stream<L> leftStream, Stream<R> rightStream, BiFunction<L, R, T> combiner) {
|
public static <L, R, T> Stream<T> zip(Stream<L> leftStream, Stream<R> rightStream, BiFunction<L, R, T> combiner) {
|
||||||
Spliterator<L> lefts = leftStream.spliterator();
|
Spliterator<L> lefts = leftStream.spliterator();
|
||||||
Spliterator<R> rights = rightStream.spliterator();
|
Spliterator<R> rights = rightStream.spliterator();
|
||||||
return StreamSupport.stream(new Spliterators.AbstractSpliterator<T>(Long.min(lefts.estimateSize(),
|
return StreamSupport.stream(new Spliterators.AbstractSpliterator<>(Long.min(lefts.estimateSize(),
|
||||||
rights.estimateSize()), lefts.characteristics() & rights.characteristics()) {
|
rights.estimateSize()), lefts.characteristics() & rights.characteristics()) {
|
||||||
@Override
|
@Override
|
||||||
public boolean tryAdvance(Consumer<? super T> action) {
|
public boolean tryAdvance(Consumer<? super T> action) {
|
||||||
|
|
|
@ -67,9 +67,10 @@ This can be piped to a QR encoder to create a display that can be captured by a
|
||||||
|
|
||||||
For example:
|
For example:
|
||||||
|
|
||||||
```
|
[source]
|
||||||
|
----
|
||||||
dbus-send --session --dest=org.asamk.Signal --type=method_call --print-reply /org/asamk/Signal org.asamk.Signal.link string:"My secondary client" | tr '\n' '\0' | sed 's/.*string //g' | sed 's/\"//g' | qrencode -s10 -tANSI256
|
dbus-send --session --dest=org.asamk.Signal --type=method_call --print-reply /org/asamk/Signal org.asamk.Signal.link string:"My secondary client" | tr '\n' '\0' | sed 's/.*string //g' | sed 's/\"//g' | qrencode -s10 -tANSI256
|
||||||
```
|
----
|
||||||
|
|
||||||
listAccounts() -> accountList<as>::
|
listAccounts() -> accountList<as>::
|
||||||
* accountList : Array of all attached accounts in DBus object path form
|
* accountList : Array of all attached accounts in DBus object path form
|
||||||
|
|
|
@ -7,6 +7,7 @@ import org.freedesktop.dbus.types.Variant;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Optional;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
public abstract class DbusProperties implements Properties {
|
public abstract class DbusProperties implements Properties {
|
||||||
|
@ -25,7 +26,7 @@ public abstract class DbusProperties implements Properties {
|
||||||
return handler.get();
|
return handler.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
private java.util.Optional<DbusInterfacePropertiesHandler> getHandlerOptional(final String interfaceName) {
|
private Optional<DbusInterfacePropertiesHandler> getHandlerOptional(final String interfaceName) {
|
||||||
return handlers.stream().filter(h -> h.getInterfaceName().equals(interfaceName)).findFirst();
|
return handlers.stream().filter(h -> h.getInterfaceName().equals(interfaceName)).findFirst();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue