Update dependencies

updateProfile can now only update both name and avatar at the same time,
as the upstream API has changed.
This commit is contained in:
AsamK 2020-08-09 13:00:29 +02:00
parent 6b02b1076c
commit e6c1e03e21
6 changed files with 42 additions and 64 deletions

View file

@ -17,10 +17,10 @@ repositories {
}
dependencies {
implementation 'com.github.turasa:signal-service-java:2.15.3_unofficial_11'
implementation 'com.github.turasa:signal-service-java:2.15.3_unofficial_12'
implementation 'org.bouncycastle:bcprov-jdk15on:1.66'
implementation 'net.sourceforge.argparse4j:argparse4j:0.8.1'
implementation 'com.github.hypfvieh:dbus-java:3.2.2'
implementation 'com.github.hypfvieh:dbus-java:3.2.3'
implementation 'org.slf4j:slf4j-nop:1.7.30'
}

View file

@ -227,7 +227,7 @@ Specify the safety number of the key, only use this option if you have verified
=== updateProfile
Update the name and/or avatar image visible by message recipients for the current users.
Update the name and avatar image visible by message recipients for the current users.
The profile is stored encrypted on the Signal servers.
The decryption key is sent with every outgoing messages (excluding group messages).

View file

@ -200,7 +200,7 @@ public class ReceiveMessageHandler implements Manager.ReceiveMessageHandler {
SignalServiceCallMessage callMessage = content.getCallMessage().get();
if (callMessage.getAnswerMessage().isPresent()) {
AnswerMessage answerMessage = callMessage.getAnswerMessage().get();
System.out.println("Answer message: " + answerMessage.getId() + ": " + answerMessage.getDescription());
System.out.println("Answer message: " + answerMessage.getId() + ": " + answerMessage.getSdp());
}
if (callMessage.getBusyMessage().isPresent()) {
BusyMessage busyMessage = callMessage.getBusyMessage().get();
@ -218,7 +218,7 @@ public class ReceiveMessageHandler implements Manager.ReceiveMessageHandler {
}
if (callMessage.getOfferMessage().isPresent()) {
OfferMessage offerMessage = callMessage.getOfferMessage().get();
System.out.println("Offer message: " + offerMessage.getId() + ": " + offerMessage.getDescription());
System.out.println("Offer message: " + offerMessage.getId() + ": " + offerMessage.getSdp());
}
}
if (content.getReceiptMessage().isPresent()) {

View file

@ -14,16 +14,18 @@ public class UpdateProfileCommand implements LocalCommand {
@Override
public void attachToSubparser(final Subparser subparser) {
final MutuallyExclusiveGroup avatarOptions = subparser.addMutuallyExclusiveGroup();
final MutuallyExclusiveGroup avatarOptions = subparser.addMutuallyExclusiveGroup()
.required(true);
avatarOptions.addArgument("--avatar")
.help("Path to new profile avatar");
avatarOptions.addArgument("--remove-avatar")
.action(Arguments.storeTrue());
subparser.addArgument("--name")
.required(true)
.help("New profile name");
subparser.help("Set a name and/or avatar image for the user profile");
subparser.help("Set a name and avatar image for the user profile");
}
@Override
@ -34,38 +36,15 @@ public class UpdateProfileCommand implements LocalCommand {
}
String name = ns.getString("name");
if (name != null) {
try {
m.setProfileName(name);
} catch (IOException e) {
System.err.println("UpdateAccount error: " + e.getMessage());
return 3;
}
}
String avatarPath = ns.getString("avatar");
if (avatarPath != null) {
File avatarFile = new File(avatarPath);
try {
m.setProfileAvatar(avatarFile);
} catch (IOException e) {
System.err.println("UpdateAccount error: " + e.getMessage());
return 3;
}
}
boolean removeAvatar = ns.getBoolean("remove_avatar");
if (removeAvatar) {
try {
m.removeProfileAvatar();
} catch (IOException e) {
System.err.println("UpdateAccount error: " + e.getMessage());
return 3;
}
try {
File avatarFile = removeAvatar ? null : new File(avatarPath);
m.setProfile(name, avatarFile);
} catch (IOException e) {
System.err.println("UpdateAccount error: " + e.getMessage());
return 3;
}
return 0;

View file

@ -38,7 +38,6 @@ import org.signal.libsignal.metadata.ProtocolUntrustedIdentityException;
import org.signal.libsignal.metadata.SelfSendException;
import org.signal.libsignal.metadata.certificate.InvalidCertificateException;
import org.signal.zkgroup.InvalidInputException;
import org.signal.zkgroup.VerificationFailedException;
import org.signal.zkgroup.profiles.ClientZkProfileOperations;
import org.signal.zkgroup.profiles.ProfileKey;
import org.whispersystems.libsignal.IdentityKey;
@ -135,6 +134,8 @@ import java.util.Locale;
import java.util.Objects;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.stream.Collectors;
@ -288,18 +289,10 @@ public class Manager implements Closeable {
accountManager.setAccountAttributes(account.getSignalingKey(), account.getSignalProtocolStore().getLocalRegistrationId(), true, account.getRegistrationLockPin(), account.getRegistrationLock(), getSelfUnidentifiedAccessKey(), false, ServiceConfig.capabilities);
}
public void setProfileName(String name) throws IOException {
accountManager.setProfileName(account.getProfileKey(), name);
}
public void setProfileAvatar(File avatar) throws IOException {
final StreamDetails streamDetails = Utils.createStreamDetailsFromFile(avatar);
accountManager.setProfileAvatar(account.getProfileKey(), streamDetails);
streamDetails.getStream().close();
}
public void removeProfileAvatar() throws IOException {
accountManager.setProfileAvatar(account.getProfileKey(), null);
public void setProfile(String name, File avatar) throws IOException {
try (final StreamDetails streamDetails = avatar == null ? null : Utils.createStreamDetailsFromFile(avatar)) {
accountManager.setVersionedProfile(account.getUuid(), account.getProfileKey(), name, streamDetails);
}
}
public void unregister() throws IOException {
@ -421,8 +414,9 @@ public class Manager implements Closeable {
// TODO implement ZkGroup support
final ClientZkProfileOperations clientZkProfileOperations = null;
final boolean attachmentsV3 = false;
final ExecutorService executor = null;
return new SignalServiceMessageSender(serviceConfiguration, account.getUuid(), account.getUsername(), account.getPassword(),
account.getDeviceId(), account.getSignalProtocolStore(), userAgent, account.isMultiDevice(), attachmentsV3, Optional.fromNullable(messagePipe), Optional.fromNullable(unidentifiedMessagePipe), Optional.absent(), clientZkProfileOperations);
account.getDeviceId(), account.getSignalProtocolStore(), userAgent, account.isMultiDevice(), attachmentsV3, Optional.fromNullable(messagePipe), Optional.fromNullable(unidentifiedMessagePipe), Optional.absent(), clientZkProfileOperations, executor);
}
private SignalServiceProfile getEncryptedRecipientProfile(SignalServiceAddress address, Optional<UnidentifiedAccess> unidentifiedAccess) throws IOException {
@ -431,16 +425,16 @@ public class Manager implements Closeable {
if (pipe != null) {
try {
return pipe.getProfile(address, Optional.absent(), unidentifiedAccess, SignalServiceProfile.RequestType.PROFILE).getProfile();
} catch (IOException ignored) {
return pipe.getProfile(address, Optional.absent(), unidentifiedAccess, SignalServiceProfile.RequestType.PROFILE).get(10, TimeUnit.SECONDS).getProfile();
} catch (IOException | InterruptedException | ExecutionException | TimeoutException ignored) {
}
}
SignalServiceMessageReceiver receiver = getMessageReceiver();
try {
return receiver.retrieveProfile(address, Optional.absent(), unidentifiedAccess, SignalServiceProfile.RequestType.PROFILE).getProfile();
} catch (VerificationFailedException e) {
throw new AssertionError(e);
return receiver.retrieveProfile(address, Optional.absent(), unidentifiedAccess, SignalServiceProfile.RequestType.PROFILE).get(10, TimeUnit.SECONDS).getProfile();
} catch (InterruptedException | ExecutionException | TimeoutException e) {
throw new IOException("Failed to retrieve profile", e);
}
}

View file

@ -75,13 +75,13 @@ class Utils {
InputStream attachmentStream = new FileInputStream(attachmentFile);
final long attachmentSize = attachmentFile.length();
final String mime = getFileMimeType(attachmentFile);
// TODO mabybe add a parameter to set the voiceNote, preview, width, height and caption option
// TODO mabybe add a parameter to set the voiceNote, borderless, preview, width, height and caption option
final long uploadTimestamp = System.currentTimeMillis();
Optional<byte[]> preview = Optional.absent();
Optional<String> caption = Optional.absent();
Optional<String> blurHash = Optional.absent();
final Optional<ResumableUploadSpec> resumableUploadSpec = Optional.absent();
return new SignalServiceAttachmentStream(attachmentStream, mime, attachmentSize, Optional.of(attachmentFile.getName()), false, preview, 0, 0, uploadTimestamp, caption, blurHash, null, null, resumableUploadSpec);
return new SignalServiceAttachmentStream(attachmentStream, mime, attachmentSize, Optional.of(attachmentFile.getName()), false, false, preview, 0, 0, uploadTimestamp, caption, blurHash, null, null, resumableUploadSpec);
}
static StreamDetails createStreamDetailsFromFile(File file) throws IOException {
@ -152,7 +152,7 @@ class Utils {
try (FileInputStream f = new FileInputStream(file)) {
DataInputStream in = new DataInputStream(f);
int version = in.readInt();
if (version > 3) {
if (version > 4) {
return null;
}
int type = in.readInt();
@ -179,26 +179,30 @@ class Utils {
legacyMessage = new byte[legacyMessageLen];
in.readFully(legacyMessage);
}
long serverTimestamp = 0;
long serverReceivedTimestamp = 0;
String uuid = null;
if (version == 2) {
serverTimestamp = in.readLong();
if (version >= 2) {
serverReceivedTimestamp = in.readLong();
uuid = in.readUTF();
if ("".equals(uuid)) {
uuid = null;
}
}
long serverDeliveredTimestamp = 0;
if (version >= 4) {
serverDeliveredTimestamp = in.readLong();
}
Optional<SignalServiceAddress> addressOptional = sourceUuid == null && source.isEmpty()
? Optional.absent()
: Optional.of(new SignalServiceAddress(sourceUuid, source));
return new SignalServiceEnvelope(type, addressOptional, sourceDevice, timestamp, legacyMessage, content, serverTimestamp, uuid);
return new SignalServiceEnvelope(type, addressOptional, sourceDevice, timestamp, legacyMessage, content, serverReceivedTimestamp, serverDeliveredTimestamp, uuid);
}
}
static void storeEnvelope(SignalServiceEnvelope envelope, File file) throws IOException {
try (FileOutputStream f = new FileOutputStream(file)) {
try (DataOutputStream out = new DataOutputStream(f)) {
out.writeInt(3); // version
out.writeInt(4); // version
out.writeInt(envelope.getType());
out.writeUTF(envelope.getSourceE164().isPresent() ? envelope.getSourceE164().get() : "");
out.writeUTF(envelope.getSourceUuid().isPresent() ? envelope.getSourceUuid().get() : "");
@ -216,9 +220,10 @@ class Utils {
} else {
out.writeInt(0);
}
out.writeLong(envelope.getServerTimestamp());
out.writeLong(envelope.getServerReceivedTimestamp());
String uuid = envelope.getUuid();
out.writeUTF(uuid == null ? "" : uuid);
out.writeLong(envelope.getServerDeliveredTimestamp());
}
}
}