mirror of
https://github.com/AsamK/signal-cli
synced 2025-08-29 10:30:38 +00:00
Remove libsignal-service from manager lib API
This commit is contained in:
parent
9075cc1a30
commit
2ab42ca547
31 changed files with 269 additions and 96 deletions
|
@ -14,7 +14,7 @@ repositories {
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
api("com.github.turasa:signal-service-java:2.15.3_unofficial_31")
|
implementation("com.github.turasa:signal-service-java:2.15.3_unofficial_31")
|
||||||
api("com.fasterxml.jackson.core", "jackson-databind", "2.13.0")
|
api("com.fasterxml.jackson.core", "jackson-databind", "2.13.0")
|
||||||
implementation("com.google.protobuf:protobuf-javalite:3.10.0")
|
implementation("com.google.protobuf:protobuf-javalite:3.10.0")
|
||||||
implementation("org.bouncycastle:bcprov-jdk15on:1.69")
|
implementation("org.bouncycastle:bcprov-jdk15on:1.69")
|
||||||
|
|
|
@ -67,6 +67,14 @@ public interface Manager extends Closeable {
|
||||||
return new ManagerImpl(account, pathConfig, serviceEnvironmentConfig, userAgent);
|
return new ManagerImpl(account, pathConfig, serviceEnvironmentConfig, userAgent);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void initLogger() {
|
||||||
|
LibSignalLogger.initLogger();
|
||||||
|
}
|
||||||
|
|
||||||
|
static boolean isValidNumber(final String e164Number, final String countryCode) {
|
||||||
|
return PhoneNumberFormatter.isValidNumber(e164Number, countryCode);
|
||||||
|
}
|
||||||
|
|
||||||
static List<String> getAllLocalNumbers(File settingsPath) {
|
static List<String> getAllLocalNumbers(File settingsPath) {
|
||||||
var pathConfig = PathConfig.createDefault(settingsPath);
|
var pathConfig = PathConfig.createDefault(settingsPath);
|
||||||
final var dataPath = pathConfig.dataPath();
|
final var dataPath = pathConfig.dataPath();
|
||||||
|
|
|
@ -26,6 +26,7 @@ import org.asamk.signal.manager.api.Message;
|
||||||
import org.asamk.signal.manager.api.Pair;
|
import org.asamk.signal.manager.api.Pair;
|
||||||
import org.asamk.signal.manager.api.RecipientIdentifier;
|
import org.asamk.signal.manager.api.RecipientIdentifier;
|
||||||
import org.asamk.signal.manager.api.SendGroupMessageResults;
|
import org.asamk.signal.manager.api.SendGroupMessageResults;
|
||||||
|
import org.asamk.signal.manager.api.SendMessageResult;
|
||||||
import org.asamk.signal.manager.api.SendMessageResults;
|
import org.asamk.signal.manager.api.SendMessageResults;
|
||||||
import org.asamk.signal.manager.api.TypingAction;
|
import org.asamk.signal.manager.api.TypingAction;
|
||||||
import org.asamk.signal.manager.api.UpdateGroup;
|
import org.asamk.signal.manager.api.UpdateGroup;
|
||||||
|
@ -69,7 +70,6 @@ import org.whispersystems.libsignal.InvalidKeyException;
|
||||||
import org.whispersystems.libsignal.ecc.ECPublicKey;
|
import org.whispersystems.libsignal.ecc.ECPublicKey;
|
||||||
import org.whispersystems.libsignal.util.guava.Optional;
|
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.SendMessageResult;
|
|
||||||
import org.whispersystems.signalservice.api.messages.SignalServiceDataMessage;
|
import org.whispersystems.signalservice.api.messages.SignalServiceDataMessage;
|
||||||
import org.whispersystems.signalservice.api.messages.SignalServiceEnvelope;
|
import org.whispersystems.signalservice.api.messages.SignalServiceEnvelope;
|
||||||
import org.whispersystems.signalservice.api.messages.SignalServiceReceiptMessage;
|
import org.whispersystems.signalservice.api.messages.SignalServiceReceiptMessage;
|
||||||
|
@ -581,13 +581,24 @@ public class ManagerImpl implements Manager {
|
||||||
if (recipient instanceof RecipientIdentifier.Single single) {
|
if (recipient instanceof RecipientIdentifier.Single single) {
|
||||||
final var recipientId = resolveRecipient(single);
|
final var recipientId = resolveRecipient(single);
|
||||||
final var result = sendHelper.sendMessage(messageBuilder, recipientId);
|
final var result = sendHelper.sendMessage(messageBuilder, recipientId);
|
||||||
results.put(recipient, List.of(result));
|
results.put(recipient,
|
||||||
|
List.of(SendMessageResult.from(result,
|
||||||
|
account.getRecipientStore(),
|
||||||
|
account.getRecipientStore()::resolveRecipientAddress)));
|
||||||
} else if (recipient instanceof RecipientIdentifier.NoteToSelf) {
|
} else if (recipient instanceof RecipientIdentifier.NoteToSelf) {
|
||||||
final var result = sendHelper.sendSelfMessage(messageBuilder);
|
final var result = sendHelper.sendSelfMessage(messageBuilder);
|
||||||
results.put(recipient, List.of(result));
|
results.put(recipient,
|
||||||
|
List.of(SendMessageResult.from(result,
|
||||||
|
account.getRecipientStore(),
|
||||||
|
account.getRecipientStore()::resolveRecipientAddress)));
|
||||||
} else if (recipient instanceof RecipientIdentifier.Group group) {
|
} else if (recipient instanceof RecipientIdentifier.Group group) {
|
||||||
final var result = sendHelper.sendAsGroupMessage(messageBuilder, group.groupId());
|
final var result = sendHelper.sendAsGroupMessage(messageBuilder, group.groupId());
|
||||||
results.put(recipient, result);
|
results.put(recipient,
|
||||||
|
result.stream()
|
||||||
|
.map(sendMessageResult -> SendMessageResult.from(sendMessageResult,
|
||||||
|
account.getRecipientStore(),
|
||||||
|
account.getRecipientStore()::resolveRecipientAddress))
|
||||||
|
.collect(Collectors.toList()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return new SendMessageResults(timestamp, results);
|
return new SendMessageResults(timestamp, results);
|
||||||
|
@ -1292,7 +1303,8 @@ public class ManagerImpl implements Manager {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void handleIdentityFailure(
|
private void handleIdentityFailure(
|
||||||
final RecipientId recipientId, final SendMessageResult.IdentityFailure identityFailure
|
final RecipientId recipientId,
|
||||||
|
final org.whispersystems.signalservice.api.messages.SendMessageResult.IdentityFailure identityFailure
|
||||||
) {
|
) {
|
||||||
this.identityHelper.handleIdentityFailure(recipientId, identityFailure);
|
this.identityHelper.handleIdentityFailure(recipientId, identityFailure);
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,6 +16,9 @@
|
||||||
*/
|
*/
|
||||||
package org.asamk.signal.manager;
|
package org.asamk.signal.manager;
|
||||||
|
|
||||||
|
import org.asamk.signal.manager.api.CaptchaRequiredException;
|
||||||
|
import org.asamk.signal.manager.api.IncorrectPinException;
|
||||||
|
import org.asamk.signal.manager.api.PinLockedException;
|
||||||
import org.asamk.signal.manager.config.ServiceConfig;
|
import org.asamk.signal.manager.config.ServiceConfig;
|
||||||
import org.asamk.signal.manager.config.ServiceEnvironment;
|
import org.asamk.signal.manager.config.ServiceEnvironment;
|
||||||
import org.asamk.signal.manager.config.ServiceEnvironmentConfig;
|
import org.asamk.signal.manager.config.ServiceEnvironmentConfig;
|
||||||
|
@ -27,6 +30,7 @@ import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
import org.whispersystems.libsignal.util.KeyHelper;
|
import org.whispersystems.libsignal.util.KeyHelper;
|
||||||
import org.whispersystems.libsignal.util.guava.Optional;
|
import org.whispersystems.libsignal.util.guava.Optional;
|
||||||
|
import org.whispersystems.signalservice.api.KbsPinData;
|
||||||
import org.whispersystems.signalservice.api.KeyBackupServicePinException;
|
import org.whispersystems.signalservice.api.KeyBackupServicePinException;
|
||||||
import org.whispersystems.signalservice.api.KeyBackupSystemNoDataException;
|
import org.whispersystems.signalservice.api.KeyBackupSystemNoDataException;
|
||||||
import org.whispersystems.signalservice.api.SignalServiceAccountManager;
|
import org.whispersystems.signalservice.api.SignalServiceAccountManager;
|
||||||
|
@ -116,7 +120,7 @@ public class RegistrationManager implements Closeable {
|
||||||
return new RegistrationManager(account, pathConfig, serviceConfiguration, userAgent);
|
return new RegistrationManager(account, pathConfig, serviceConfiguration, userAgent);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void register(boolean voiceVerification, String captcha) throws IOException {
|
public void register(boolean voiceVerification, String captcha) throws IOException, CaptchaRequiredException {
|
||||||
final ServiceResponse<RequestVerificationCodeResponse> response;
|
final ServiceResponse<RequestVerificationCodeResponse> response;
|
||||||
if (voiceVerification) {
|
if (voiceVerification) {
|
||||||
response = accountManager.requestVoiceVerificationCode(getDefaultLocale(),
|
response = accountManager.requestVoiceVerificationCode(getDefaultLocale(),
|
||||||
|
@ -129,7 +133,11 @@ public class RegistrationManager implements Closeable {
|
||||||
Optional.absent(),
|
Optional.absent(),
|
||||||
Optional.absent());
|
Optional.absent());
|
||||||
}
|
}
|
||||||
handleResponseException(response);
|
try {
|
||||||
|
handleResponseException(response);
|
||||||
|
} catch (org.whispersystems.signalservice.api.push.exceptions.CaptchaRequiredException e) {
|
||||||
|
throw new CaptchaRequiredException(e.getMessage(), e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private Locale getDefaultLocale() {
|
private Locale getDefaultLocale() {
|
||||||
|
@ -146,7 +154,7 @@ public class RegistrationManager implements Closeable {
|
||||||
|
|
||||||
public Manager verifyAccount(
|
public Manager verifyAccount(
|
||||||
String verificationCode, String pin
|
String verificationCode, String pin
|
||||||
) throws IOException, LockedException, KeyBackupSystemNoDataException, KeyBackupServicePinException {
|
) throws IOException, PinLockedException, IncorrectPinException {
|
||||||
verificationCode = verificationCode.replace("-", "");
|
verificationCode = verificationCode.replace("-", "");
|
||||||
VerifyAccountResponse response;
|
VerifyAccountResponse response;
|
||||||
MasterKey masterKey;
|
MasterKey masterKey;
|
||||||
|
@ -157,10 +165,17 @@ public class RegistrationManager implements Closeable {
|
||||||
pin = null;
|
pin = null;
|
||||||
} catch (LockedException e) {
|
} catch (LockedException e) {
|
||||||
if (pin == null) {
|
if (pin == null) {
|
||||||
throw e;
|
throw new PinLockedException(e.getTimeRemaining());
|
||||||
}
|
}
|
||||||
|
|
||||||
var registrationLockData = pinHelper.getRegistrationLockData(pin, e);
|
KbsPinData registrationLockData;
|
||||||
|
try {
|
||||||
|
registrationLockData = pinHelper.getRegistrationLockData(pin, e);
|
||||||
|
} catch (KeyBackupSystemNoDataException ex) {
|
||||||
|
throw new IOException(e);
|
||||||
|
} catch (KeyBackupServicePinException ex) {
|
||||||
|
throw new IncorrectPinException(ex.getTriesRemaining());
|
||||||
|
}
|
||||||
if (registrationLockData == null) {
|
if (registrationLockData == null) {
|
||||||
throw e;
|
throw e;
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,12 @@
|
||||||
|
package org.asamk.signal.manager.api;
|
||||||
|
|
||||||
|
public class CaptchaRequiredException extends Exception {
|
||||||
|
|
||||||
|
public CaptchaRequiredException(final String message) {
|
||||||
|
super(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
public CaptchaRequiredException(final String message, final Throwable cause) {
|
||||||
|
super(message, cause);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,14 @@
|
||||||
|
package org.asamk.signal.manager.api;
|
||||||
|
|
||||||
|
public class IncorrectPinException extends Exception {
|
||||||
|
|
||||||
|
private final int triesRemaining;
|
||||||
|
|
||||||
|
public IncorrectPinException(int triesRemaining) {
|
||||||
|
this.triesRemaining = triesRemaining;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getTriesRemaining() {
|
||||||
|
return triesRemaining;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,8 @@
|
||||||
|
package org.asamk.signal.manager.api;
|
||||||
|
|
||||||
|
public class InvalidNumberException extends Exception {
|
||||||
|
|
||||||
|
InvalidNumberException(String message, Throwable e) {
|
||||||
|
super(message, e);
|
||||||
|
}
|
||||||
|
}
|
|
@ -48,7 +48,7 @@ public record MessageEnvelope(
|
||||||
Optional<Call> call
|
Optional<Call> call
|
||||||
) {
|
) {
|
||||||
|
|
||||||
public static final record Receipt(long when, Type type, List<Long> timestamps) {
|
public record Receipt(long when, Type type, List<Long> timestamps) {
|
||||||
|
|
||||||
static Receipt from(final SignalServiceReceiptMessage receiptMessage) {
|
static Receipt from(final SignalServiceReceiptMessage receiptMessage) {
|
||||||
return new Receipt(receiptMessage.getWhen(),
|
return new Receipt(receiptMessage.getWhen(),
|
||||||
|
@ -73,7 +73,7 @@ public record MessageEnvelope(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static final record Typing(long timestamp, Type type, Optional<GroupId> groupId) {
|
public record Typing(long timestamp, Type type, Optional<GroupId> groupId) {
|
||||||
|
|
||||||
public static Typing from(final SignalServiceTypingMessage typingMessage) {
|
public static Typing from(final SignalServiceTypingMessage typingMessage) {
|
||||||
return new Typing(typingMessage.getTimestamp(),
|
return new Typing(typingMessage.getTimestamp(),
|
||||||
|
@ -87,7 +87,7 @@ public record MessageEnvelope(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static final record Data(
|
public record Data(
|
||||||
long timestamp,
|
long timestamp,
|
||||||
Optional<GroupContext> groupContext,
|
Optional<GroupContext> groupContext,
|
||||||
Optional<GroupCallUpdate> groupCallUpdate,
|
Optional<GroupCallUpdate> groupCallUpdate,
|
||||||
|
@ -204,11 +204,15 @@ public record MessageEnvelope(
|
||||||
return new Quote(quote.getId(),
|
return new Quote(quote.getId(),
|
||||||
addressResolver.resolveRecipientAddress(recipientResolver.resolveRecipient(quote.getAuthor())),
|
addressResolver.resolveRecipientAddress(recipientResolver.resolveRecipient(quote.getAuthor())),
|
||||||
Optional.ofNullable(quote.getText()),
|
Optional.ofNullable(quote.getText()),
|
||||||
quote.getMentions()
|
quote.getMentions() == null
|
||||||
.stream()
|
? List.of()
|
||||||
.map(m -> Mention.from(m, recipientResolver, addressResolver))
|
: quote.getMentions()
|
||||||
.collect(Collectors.toList()),
|
.stream()
|
||||||
quote.getAttachments().stream().map(Attachment::from).collect(Collectors.toList()));
|
.map(m -> Mention.from(m, recipientResolver, addressResolver))
|
||||||
|
.collect(Collectors.toList()),
|
||||||
|
quote.getAttachments() == null
|
||||||
|
? List.of()
|
||||||
|
: quote.getAttachments().stream().map(Attachment::from).collect(Collectors.toList()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -455,7 +459,7 @@ public record MessageEnvelope(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static final record Sync(
|
public record Sync(
|
||||||
Optional<Sent> sent,
|
Optional<Sent> sent,
|
||||||
Optional<Blocked> blocked,
|
Optional<Blocked> blocked,
|
||||||
List<Read> read,
|
List<Read> read,
|
||||||
|
@ -631,7 +635,7 @@ public record MessageEnvelope(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static final record Call(
|
public record Call(
|
||||||
Optional<Integer> destinationDeviceId,
|
Optional<Integer> destinationDeviceId,
|
||||||
Optional<GroupId> groupId,
|
Optional<GroupId> groupId,
|
||||||
Optional<Long> timestamp,
|
Optional<Long> timestamp,
|
||||||
|
|
|
@ -0,0 +1,14 @@
|
||||||
|
package org.asamk.signal.manager.api;
|
||||||
|
|
||||||
|
public class PinLockedException extends Exception {
|
||||||
|
|
||||||
|
private final long timeRemaining;
|
||||||
|
|
||||||
|
public PinLockedException(long timeRemaining) {
|
||||||
|
this.timeRemaining = timeRemaining;
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getTimeRemaining() {
|
||||||
|
return timeRemaining;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,44 @@
|
||||||
|
package org.asamk.signal.manager.api;
|
||||||
|
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Thrown when rate-limited by the server and proof of humanity is required to continue messaging.
|
||||||
|
*/
|
||||||
|
public class ProofRequiredException extends Exception {
|
||||||
|
|
||||||
|
private final String token;
|
||||||
|
private final Set<Option> options;
|
||||||
|
private final long retryAfterSeconds;
|
||||||
|
|
||||||
|
public ProofRequiredException(org.whispersystems.signalservice.api.push.exceptions.ProofRequiredException e) {
|
||||||
|
this.token = e.getToken();
|
||||||
|
this.options = e.getOptions().stream().map(Option::from).collect(Collectors.toSet());
|
||||||
|
this.retryAfterSeconds = e.getRetryAfterSeconds();
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getToken() {
|
||||||
|
return token;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Set<Option> getOptions() {
|
||||||
|
return options;
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getRetryAfterSeconds() {
|
||||||
|
return retryAfterSeconds;
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum Option {
|
||||||
|
RECAPTCHA,
|
||||||
|
PUSH_CHALLENGE;
|
||||||
|
|
||||||
|
static Option from(org.whispersystems.signalservice.api.push.exceptions.ProofRequiredException.Option option) {
|
||||||
|
return switch (option) {
|
||||||
|
case RECAPTCHA -> RECAPTCHA;
|
||||||
|
case PUSH_CHALLENGE -> PUSH_CHALLENGE;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -2,8 +2,6 @@ package org.asamk.signal.manager.api;
|
||||||
|
|
||||||
import org.asamk.signal.manager.groups.GroupId;
|
import org.asamk.signal.manager.groups.GroupId;
|
||||||
import org.asamk.signal.manager.storage.recipients.RecipientAddress;
|
import org.asamk.signal.manager.storage.recipients.RecipientAddress;
|
||||||
import org.whispersystems.signalservice.api.push.SignalServiceAddress;
|
|
||||||
import org.whispersystems.signalservice.api.util.InvalidNumberException;
|
|
||||||
import org.whispersystems.signalservice.api.util.PhoneNumberFormatter;
|
import org.whispersystems.signalservice.api.util.PhoneNumberFormatter;
|
||||||
import org.whispersystems.signalservice.api.util.UuidUtil;
|
import org.whispersystems.signalservice.api.util.UuidUtil;
|
||||||
|
|
||||||
|
@ -19,13 +17,13 @@ public sealed interface RecipientIdentifier {
|
||||||
sealed interface Single extends RecipientIdentifier {
|
sealed interface Single extends RecipientIdentifier {
|
||||||
|
|
||||||
static Single fromString(String identifier, String localNumber) throws InvalidNumberException {
|
static Single fromString(String identifier, String localNumber) throws InvalidNumberException {
|
||||||
return UuidUtil.isUuid(identifier)
|
try {
|
||||||
? new Uuid(UUID.fromString(identifier))
|
return UuidUtil.isUuid(identifier)
|
||||||
: new Number(PhoneNumberFormatter.formatNumber(identifier, localNumber));
|
? new Uuid(UUID.fromString(identifier))
|
||||||
}
|
: new Number(PhoneNumberFormatter.formatNumber(identifier, localNumber));
|
||||||
|
} catch (org.whispersystems.signalservice.api.util.InvalidNumberException e) {
|
||||||
static Single fromAddress(SignalServiceAddress address) {
|
throw new InvalidNumberException(e.getMessage(), e);
|
||||||
return new Uuid(address.getUuid());
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static Single fromAddress(RecipientAddress address) {
|
static Single fromAddress(RecipientAddress address) {
|
||||||
|
|
|
@ -1,7 +1,5 @@
|
||||||
package org.asamk.signal.manager.api;
|
package org.asamk.signal.manager.api;
|
||||||
|
|
||||||
import org.whispersystems.signalservice.api.messages.SendMessageResult;
|
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public record SendGroupMessageResults(long timestamp, List<SendMessageResult> results) {}
|
public record SendGroupMessageResults(long timestamp, List<SendMessageResult> results) {}
|
||||||
|
|
|
@ -0,0 +1,56 @@
|
||||||
|
package org.asamk.signal.manager.api;
|
||||||
|
|
||||||
|
import org.asamk.signal.manager.helper.RecipientAddressResolver;
|
||||||
|
import org.asamk.signal.manager.storage.recipients.RecipientAddress;
|
||||||
|
import org.asamk.signal.manager.storage.recipients.RecipientResolver;
|
||||||
|
import org.whispersystems.libsignal.IdentityKey;
|
||||||
|
|
||||||
|
public record SendMessageResult(
|
||||||
|
RecipientAddress address,
|
||||||
|
boolean isSuccess,
|
||||||
|
boolean isNetworkFailure,
|
||||||
|
boolean isUnregisteredFailure,
|
||||||
|
boolean isIdentityFailure,
|
||||||
|
ProofRequiredException proofRequiredFailure
|
||||||
|
) {
|
||||||
|
|
||||||
|
public static SendMessageResult success(RecipientAddress address) {
|
||||||
|
return new SendMessageResult(address, true, false, false, false, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static SendMessageResult networkFailure(RecipientAddress address) {
|
||||||
|
return new SendMessageResult(address, false, true, false, false, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static SendMessageResult unregisteredFailure(RecipientAddress address) {
|
||||||
|
return new SendMessageResult(address, false, false, true, false, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static SendMessageResult identityFailure(RecipientAddress address, IdentityKey identityKey) {
|
||||||
|
return new SendMessageResult(address, false, false, false, true, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static SendMessageResult proofRequiredFailure(
|
||||||
|
RecipientAddress address, ProofRequiredException proofRequiredException
|
||||||
|
) {
|
||||||
|
return new SendMessageResult(address, false, true, false, false, proofRequiredException);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static SendMessageResult from(
|
||||||
|
final org.whispersystems.signalservice.api.messages.SendMessageResult sendMessageResult,
|
||||||
|
RecipientResolver recipientResolver,
|
||||||
|
RecipientAddressResolver addressResolver
|
||||||
|
) {
|
||||||
|
return new SendMessageResult(addressResolver.resolveRecipientAddress(recipientResolver.resolveRecipient(
|
||||||
|
sendMessageResult.getAddress())),
|
||||||
|
sendMessageResult.isSuccess(),
|
||||||
|
sendMessageResult.isNetworkFailure(),
|
||||||
|
sendMessageResult.isUnregisteredFailure(),
|
||||||
|
sendMessageResult.getIdentityFailure() != null,
|
||||||
|
sendMessageResult.getProofRequiredFailure() == null
|
||||||
|
? null
|
||||||
|
: new ProofRequiredException(sendMessageResult.getProofRequiredFailure()));
|
||||||
|
}
|
||||||
|
|
||||||
|
public record IdentityFailure(IdentityKey identityKey) {}
|
||||||
|
}
|
|
@ -1,7 +1,5 @@
|
||||||
package org.asamk.signal.manager.api;
|
package org.asamk.signal.manager.api;
|
||||||
|
|
||||||
import org.whispersystems.signalservice.api.messages.SendMessageResult;
|
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
|
|
|
@ -60,6 +60,10 @@ public class ServiceConfig {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static boolean isZkgroupAvailable() {
|
||||||
|
return ServiceConfig.getCapabilities().isGv2();
|
||||||
|
}
|
||||||
|
|
||||||
public static boolean isSignalClientAvailable() {
|
public static boolean isSignalClientAvailable() {
|
||||||
try {
|
try {
|
||||||
org.signal.client.internal.Native.DeviceTransfer_GeneratePrivateKey();
|
org.signal.client.internal.Native.DeviceTransfer_GeneratePrivateKey();
|
||||||
|
|
|
@ -6,6 +6,7 @@ import org.asamk.signal.manager.SignalDependencies;
|
||||||
import org.asamk.signal.manager.api.InactiveGroupLinkException;
|
import org.asamk.signal.manager.api.InactiveGroupLinkException;
|
||||||
import org.asamk.signal.manager.api.Pair;
|
import org.asamk.signal.manager.api.Pair;
|
||||||
import org.asamk.signal.manager.api.SendGroupMessageResults;
|
import org.asamk.signal.manager.api.SendGroupMessageResults;
|
||||||
|
import org.asamk.signal.manager.api.SendMessageResult;
|
||||||
import org.asamk.signal.manager.config.ServiceConfig;
|
import org.asamk.signal.manager.config.ServiceConfig;
|
||||||
import org.asamk.signal.manager.groups.GroupId;
|
import org.asamk.signal.manager.groups.GroupId;
|
||||||
import org.asamk.signal.manager.groups.GroupIdV1;
|
import org.asamk.signal.manager.groups.GroupIdV1;
|
||||||
|
@ -676,6 +677,11 @@ public class GroupHelper {
|
||||||
final var timestamp = System.currentTimeMillis();
|
final var timestamp = System.currentTimeMillis();
|
||||||
messageBuilder.withTimestamp(timestamp);
|
messageBuilder.withTimestamp(timestamp);
|
||||||
final var results = sendHelper.sendGroupMessage(messageBuilder.build(), members);
|
final var results = sendHelper.sendGroupMessage(messageBuilder.build(), members);
|
||||||
return new SendGroupMessageResults(timestamp, results);
|
return new SendGroupMessageResults(timestamp,
|
||||||
|
results.stream()
|
||||||
|
.map(sendMessageResult -> SendMessageResult.from(sendMessageResult,
|
||||||
|
recipientResolver,
|
||||||
|
account.getRecipientStore()::resolveRecipientAddress))
|
||||||
|
.collect(Collectors.toList()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,13 +1,14 @@
|
||||||
package org.asamk.signal.manager.storage.recipients;
|
package org.asamk.signal.manager.storage.recipients;
|
||||||
|
|
||||||
import org.whispersystems.signalservice.api.push.SignalServiceAddress;
|
import org.whispersystems.signalservice.api.push.SignalServiceAddress;
|
||||||
import org.whispersystems.signalservice.api.util.UuidUtil;
|
|
||||||
|
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
public class RecipientAddress {
|
public class RecipientAddress {
|
||||||
|
|
||||||
|
public static final UUID UNKNOWN_UUID = new UUID(0, 0);
|
||||||
|
|
||||||
private final Optional<UUID> uuid;
|
private final Optional<UUID> uuid;
|
||||||
private final Optional<String> e164;
|
private final Optional<String> e164;
|
||||||
|
|
||||||
|
@ -18,7 +19,7 @@ public class RecipientAddress {
|
||||||
* @param e164 The phone number of the user, if available.
|
* @param e164 The phone number of the user, if available.
|
||||||
*/
|
*/
|
||||||
public RecipientAddress(Optional<UUID> uuid, Optional<String> e164) {
|
public RecipientAddress(Optional<UUID> uuid, Optional<String> e164) {
|
||||||
uuid = uuid.isPresent() && uuid.get().equals(UuidUtil.UNKNOWN_UUID) ? Optional.empty() : uuid;
|
uuid = uuid.isPresent() && uuid.get().equals(UNKNOWN_UUID) ? Optional.empty() : uuid;
|
||||||
if (uuid.isEmpty() && e164.isEmpty()) {
|
if (uuid.isEmpty() && e164.isEmpty()) {
|
||||||
throw new AssertionError("Must have either a UUID or E164 number!");
|
throw new AssertionError("Must have either a UUID or E164 number!");
|
||||||
}
|
}
|
||||||
|
@ -74,7 +75,7 @@ public class RecipientAddress {
|
||||||
}
|
}
|
||||||
|
|
||||||
public SignalServiceAddress toSignalServiceAddress() {
|
public SignalServiceAddress toSignalServiceAddress() {
|
||||||
return new SignalServiceAddress(uuid.orElse(UuidUtil.UNKNOWN_UUID),
|
return new SignalServiceAddress(uuid.orElse(UNKNOWN_UUID),
|
||||||
org.whispersystems.libsignal.util.guava.Optional.fromNullable(e164.orElse(null)));
|
org.whispersystems.libsignal.util.guava.Optional.fromNullable(e164.orElse(null)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -32,7 +32,6 @@ import org.freedesktop.dbus.exceptions.DBusException;
|
||||||
import org.freedesktop.dbus.exceptions.DBusExecutionException;
|
import org.freedesktop.dbus.exceptions.DBusExecutionException;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
import org.whispersystems.signalservice.api.util.PhoneNumberFormatter;
|
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
@ -133,7 +132,7 @@ public class App {
|
||||||
dataPath = getDefaultDataPath();
|
dataPath = getDefaultDataPath();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!ServiceConfig.getCapabilities().isGv2()) {
|
if (!ServiceConfig.isZkgroupAvailable()) {
|
||||||
logger.warn("WARNING: Support for new group V2 is disabled,"
|
logger.warn("WARNING: Support for new group V2 is disabled,"
|
||||||
+ " because the required native library dependency is missing: libzkgroup");
|
+ " because the required native library dependency is missing: libzkgroup");
|
||||||
}
|
}
|
||||||
|
@ -182,7 +181,7 @@ public class App {
|
||||||
}
|
}
|
||||||
|
|
||||||
username = usernames.get(0);
|
username = usernames.get(0);
|
||||||
} else if (!PhoneNumberFormatter.isValidNumber(username, null)) {
|
} else if (!Manager.isValidNumber(username, null)) {
|
||||||
throw new UserErrorException("Invalid username (phone number), make sure you include the country code.");
|
throw new UserErrorException("Invalid username (phone number), make sure you include the country code.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -26,7 +26,7 @@ import org.asamk.signal.commands.exceptions.IOErrorException;
|
||||||
import org.asamk.signal.commands.exceptions.UnexpectedErrorException;
|
import org.asamk.signal.commands.exceptions.UnexpectedErrorException;
|
||||||
import org.asamk.signal.commands.exceptions.UntrustedKeyErrorException;
|
import org.asamk.signal.commands.exceptions.UntrustedKeyErrorException;
|
||||||
import org.asamk.signal.commands.exceptions.UserErrorException;
|
import org.asamk.signal.commands.exceptions.UserErrorException;
|
||||||
import org.asamk.signal.manager.LibSignalLogger;
|
import org.asamk.signal.manager.Manager;
|
||||||
import org.asamk.signal.util.SecurityProvider;
|
import org.asamk.signal.util.SecurityProvider;
|
||||||
import org.bouncycastle.jce.provider.BouncyCastleProvider;
|
import org.bouncycastle.jce.provider.BouncyCastleProvider;
|
||||||
|
|
||||||
|
@ -90,7 +90,7 @@ public class Main {
|
||||||
System.setProperty("org.slf4j.simpleLogger.showShortLogName", "false");
|
System.setProperty("org.slf4j.simpleLogger.showShortLogName", "false");
|
||||||
System.setProperty("org.slf4j.simpleLogger.showDateTime", "true");
|
System.setProperty("org.slf4j.simpleLogger.showDateTime", "true");
|
||||||
System.setProperty("org.slf4j.simpleLogger.dateTimeFormat", "yyyy-MM-dd'T'HH:mm:ss.SSSXX");
|
System.setProperty("org.slf4j.simpleLogger.dateTimeFormat", "yyyy-MM-dd'T'HH:mm:ss.SSSXX");
|
||||||
LibSignalLogger.initLogger();
|
Manager.initLogger();
|
||||||
} else {
|
} else {
|
||||||
System.setProperty("org.slf4j.simpleLogger.defaultLogLevel", "info");
|
System.setProperty("org.slf4j.simpleLogger.defaultLogLevel", "info");
|
||||||
System.setProperty("org.slf4j.simpleLogger.showThreadName", "false");
|
System.setProperty("org.slf4j.simpleLogger.showThreadName", "false");
|
||||||
|
|
|
@ -361,7 +361,9 @@ public class ReceiveMessageHandler implements Manager.ReceiveMessageHandler {
|
||||||
) {
|
) {
|
||||||
writer.println("Id: {}", quote.id());
|
writer.println("Id: {}", quote.id());
|
||||||
writer.println("Author: {}", formatContact(quote.author()));
|
writer.println("Author: {}", formatContact(quote.author()));
|
||||||
writer.println("Text: {}", quote.text());
|
if (quote.text().isPresent()) {
|
||||||
|
writer.println("Text: {}", quote.text().get());
|
||||||
|
}
|
||||||
if (quote.mentions() != null && quote.mentions().size() > 0) {
|
if (quote.mentions() != null && quote.mentions().size() > 0) {
|
||||||
writer.println("Mentions:");
|
writer.println("Mentions:");
|
||||||
for (var mention : quote.mentions()) {
|
for (var mention : quote.mentions()) {
|
||||||
|
@ -371,14 +373,8 @@ public class ReceiveMessageHandler implements Manager.ReceiveMessageHandler {
|
||||||
if (quote.attachments().size() > 0) {
|
if (quote.attachments().size() > 0) {
|
||||||
writer.println("Attachments:");
|
writer.println("Attachments:");
|
||||||
for (var attachment : quote.attachments()) {
|
for (var attachment : quote.attachments()) {
|
||||||
writer.println("- Filename: {}", attachment.fileName());
|
writer.println("- Attachment:");
|
||||||
writer.indent(w -> {
|
printAttachment(writer.indentedWriter(), attachment);
|
||||||
w.println("Type: {}", attachment.contentType());
|
|
||||||
w.println("Thumbnail:");
|
|
||||||
if (attachment.thumbnail().isPresent()) {
|
|
||||||
printAttachment(w, attachment.thumbnail().get());
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -527,6 +523,10 @@ public class ReceiveMessageHandler implements Manager.ReceiveMessageHandler {
|
||||||
+ attachment.preview().get().length
|
+ attachment.preview().get().length
|
||||||
+ " bytes)" : "");
|
+ " bytes)" : "");
|
||||||
}
|
}
|
||||||
|
if (attachment.thumbnail().isPresent()) {
|
||||||
|
writer.println("Thumbnail:");
|
||||||
|
printAttachment(writer.indentedWriter(), attachment.thumbnail().get());
|
||||||
|
}
|
||||||
final var flags = new ArrayList<String>();
|
final var flags = new ArrayList<String>();
|
||||||
if (attachment.isVoiceNote()) {
|
if (attachment.isVoiceNote()) {
|
||||||
flags.add("voice note");
|
flags.add("voice note");
|
||||||
|
|
|
@ -14,7 +14,6 @@ import org.asamk.signal.manager.Manager;
|
||||||
import org.asamk.signal.manager.api.InactiveGroupLinkException;
|
import org.asamk.signal.manager.api.InactiveGroupLinkException;
|
||||||
import org.asamk.signal.manager.groups.GroupInviteLinkUrl;
|
import org.asamk.signal.manager.groups.GroupInviteLinkUrl;
|
||||||
import org.freedesktop.dbus.exceptions.DBusExecutionException;
|
import org.freedesktop.dbus.exceptions.DBusExecutionException;
|
||||||
import org.whispersystems.signalservice.internal.push.exceptions.GroupPatchNotAcceptedException;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
@ -70,8 +69,6 @@ public class JoinGroupCommand implements JsonRpcLocalCommand {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
handleSendMessageResults(results.second().results());
|
handleSendMessageResults(results.second().results());
|
||||||
} catch (GroupPatchNotAcceptedException e) {
|
|
||||||
throw new UserErrorException("Failed to join group, maybe already a member");
|
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
throw new IOErrorException("Failed to send message: "
|
throw new IOErrorException("Failed to send message: "
|
||||||
+ e.getMessage()
|
+ e.getMessage()
|
||||||
|
|
|
@ -63,10 +63,10 @@ public class ListIdentitiesCommand implements JsonRpcLocalCommand {
|
||||||
} else {
|
} else {
|
||||||
final var writer = (JsonWriter) outputWriter;
|
final var writer = (JsonWriter) outputWriter;
|
||||||
final var jsonIdentities = identities.stream().map(id -> {
|
final var jsonIdentities = identities.stream().map(id -> {
|
||||||
final var address = id.recipient().toSignalServiceAddress();
|
final var address = id.recipient();
|
||||||
var safetyNumber = Util.formatSafetyNumber(id.safetyNumber());
|
var safetyNumber = Util.formatSafetyNumber(id.safetyNumber());
|
||||||
var scannableSafetyNumber = id.scannableSafetyNumber();
|
var scannableSafetyNumber = id.scannableSafetyNumber();
|
||||||
return new JsonIdentity(address.getNumber().orNull(),
|
return new JsonIdentity(address.getNumber().orElse(null),
|
||||||
address.getUuid().toString(),
|
address.getUuid().toString(),
|
||||||
Hex.toString(id.getFingerprint()),
|
Hex.toString(id.getFingerprint()),
|
||||||
safetyNumber,
|
safetyNumber,
|
||||||
|
|
|
@ -8,7 +8,7 @@ import org.asamk.signal.commands.exceptions.CommandException;
|
||||||
import org.asamk.signal.commands.exceptions.IOErrorException;
|
import org.asamk.signal.commands.exceptions.IOErrorException;
|
||||||
import org.asamk.signal.commands.exceptions.UserErrorException;
|
import org.asamk.signal.commands.exceptions.UserErrorException;
|
||||||
import org.asamk.signal.manager.RegistrationManager;
|
import org.asamk.signal.manager.RegistrationManager;
|
||||||
import org.whispersystems.signalservice.api.push.exceptions.CaptchaRequiredException;
|
import org.asamk.signal.manager.api.CaptchaRequiredException;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
|
|
|
@ -5,12 +5,10 @@ import net.sourceforge.argparse4j.inf.Subparser;
|
||||||
|
|
||||||
import org.asamk.signal.commands.exceptions.CommandException;
|
import org.asamk.signal.commands.exceptions.CommandException;
|
||||||
import org.asamk.signal.commands.exceptions.IOErrorException;
|
import org.asamk.signal.commands.exceptions.IOErrorException;
|
||||||
import org.asamk.signal.commands.exceptions.UnexpectedErrorException;
|
|
||||||
import org.asamk.signal.commands.exceptions.UserErrorException;
|
import org.asamk.signal.commands.exceptions.UserErrorException;
|
||||||
import org.asamk.signal.manager.RegistrationManager;
|
import org.asamk.signal.manager.RegistrationManager;
|
||||||
import org.whispersystems.signalservice.api.KeyBackupServicePinException;
|
import org.asamk.signal.manager.api.IncorrectPinException;
|
||||||
import org.whispersystems.signalservice.api.KeyBackupSystemNoDataException;
|
import org.asamk.signal.manager.api.PinLockedException;
|
||||||
import org.whispersystems.signalservice.internal.push.LockedException;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
|
@ -36,15 +34,13 @@ public class VerifyCommand implements RegistrationCommand {
|
||||||
try {
|
try {
|
||||||
final var manager = m.verifyAccount(verificationCode, pin);
|
final var manager = m.verifyAccount(verificationCode, pin);
|
||||||
manager.close();
|
manager.close();
|
||||||
} catch (LockedException e) {
|
} catch (PinLockedException e) {
|
||||||
throw new UserErrorException(
|
throw new UserErrorException(
|
||||||
"Verification failed! This number is locked with a pin. Hours remaining until reset: "
|
"Verification failed! This number is locked with a pin. Hours remaining until reset: "
|
||||||
+ (e.getTimeRemaining() / 1000 / 60 / 60)
|
+ (e.getTimeRemaining() / 1000 / 60 / 60)
|
||||||
+ "\nUse '--pin PIN_CODE' to specify the registration lock PIN");
|
+ "\nUse '--pin PIN_CODE' to specify the registration lock PIN");
|
||||||
} catch (KeyBackupServicePinException e) {
|
} catch (IncorrectPinException e) {
|
||||||
throw new UserErrorException("Verification failed! Invalid pin, tries remaining: " + e.getTriesRemaining());
|
throw new UserErrorException("Verification failed! Invalid pin, tries remaining: " + e.getTriesRemaining());
|
||||||
} catch (KeyBackupSystemNoDataException e) {
|
|
||||||
throw new UnexpectedErrorException("Verification failed! No KBS data.", e);
|
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
throw new IOErrorException("Verify error: " + e.getMessage(), e);
|
throw new IOErrorException("Verify error: " + e.getMessage(), e);
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,8 +33,6 @@ import org.freedesktop.dbus.DBusPath;
|
||||||
import org.freedesktop.dbus.connections.impl.DBusConnection;
|
import org.freedesktop.dbus.connections.impl.DBusConnection;
|
||||||
import org.freedesktop.dbus.exceptions.DBusException;
|
import org.freedesktop.dbus.exceptions.DBusException;
|
||||||
import org.freedesktop.dbus.interfaces.DBusInterface;
|
import org.freedesktop.dbus.interfaces.DBusInterface;
|
||||||
import org.whispersystems.signalservice.api.push.exceptions.UnregisteredUserException;
|
|
||||||
import org.whispersystems.signalservice.api.util.UuidUtil;
|
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
@ -84,7 +82,7 @@ public class DbusManagerImpl implements Manager {
|
||||||
final var result = new HashMap<String, Pair<String, UUID>>();
|
final var result = new HashMap<String, Pair<String, UUID>>();
|
||||||
for (var i = 0; i < numbersList.size(); i++) {
|
for (var i = 0; i < numbersList.size(); i++) {
|
||||||
result.put(numbersList.get(i),
|
result.put(numbersList.get(i),
|
||||||
new Pair<>(numbersList.get(i), registered.get(i) ? UuidUtil.UNKNOWN_UUID : null));
|
new Pair<>(numbersList.get(i), registered.get(i) ? RecipientAddress.UNKNOWN_UUID : null));
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -173,7 +171,7 @@ public class DbusManagerImpl implements Manager {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Profile getRecipientProfile(final RecipientIdentifier.Single recipient) throws UnregisteredUserException {
|
public Profile getRecipientProfile(final RecipientIdentifier.Single recipient) {
|
||||||
throw new UnsupportedOperationException();
|
throw new UnsupportedOperationException();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -370,7 +368,7 @@ public class DbusManagerImpl implements Manager {
|
||||||
@Override
|
@Override
|
||||||
public void setContactName(
|
public void setContactName(
|
||||||
final RecipientIdentifier.Single recipient, final String name
|
final RecipientIdentifier.Single recipient, final String name
|
||||||
) throws NotMasterDeviceException, UnregisteredUserException {
|
) throws NotMasterDeviceException {
|
||||||
signal.setContactName(recipient.getIdentifier(), name);
|
signal.setContactName(recipient.getIdentifier(), name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -8,12 +8,11 @@ import org.asamk.signal.manager.Manager;
|
||||||
import org.asamk.signal.manager.ProvisioningManager;
|
import org.asamk.signal.manager.ProvisioningManager;
|
||||||
import org.asamk.signal.manager.RegistrationManager;
|
import org.asamk.signal.manager.RegistrationManager;
|
||||||
import org.asamk.signal.manager.UserAlreadyExists;
|
import org.asamk.signal.manager.UserAlreadyExists;
|
||||||
|
import org.asamk.signal.manager.api.CaptchaRequiredException;
|
||||||
|
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.freedesktop.dbus.DBusPath;
|
import org.freedesktop.dbus.DBusPath;
|
||||||
import org.whispersystems.signalservice.api.KeyBackupServicePinException;
|
|
||||||
import org.whispersystems.signalservice.api.KeyBackupSystemNoDataException;
|
|
||||||
import org.whispersystems.signalservice.api.push.exceptions.CaptchaRequiredException;
|
|
||||||
import org.whispersystems.signalservice.api.util.PhoneNumberFormatter;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
|
@ -100,7 +99,7 @@ public class DbusSignalControlImpl implements org.asamk.SignalControl {
|
||||||
public void registerWithCaptcha(
|
public void registerWithCaptcha(
|
||||||
final String number, final boolean voiceVerification, final String captcha
|
final String number, final boolean voiceVerification, final String captcha
|
||||||
) throws Error.Failure, Error.InvalidNumber {
|
) throws Error.Failure, Error.InvalidNumber {
|
||||||
if (!PhoneNumberFormatter.isValidNumber(number, null)) {
|
if (!Manager.isValidNumber(number, null)) {
|
||||||
throw new SignalControl.Error.InvalidNumber(
|
throw new SignalControl.Error.InvalidNumber(
|
||||||
"Invalid username (phone number), make sure you include the country code.");
|
"Invalid username (phone number), make sure you include the country code.");
|
||||||
}
|
}
|
||||||
|
@ -126,7 +125,7 @@ public class DbusSignalControlImpl implements org.asamk.SignalControl {
|
||||||
try (final RegistrationManager registrationManager = c.getNewRegistrationManager(number)) {
|
try (final RegistrationManager registrationManager = c.getNewRegistrationManager(number)) {
|
||||||
final Manager manager = registrationManager.verifyAccount(verificationCode, pin);
|
final Manager manager = registrationManager.verifyAccount(verificationCode, pin);
|
||||||
addManager(manager);
|
addManager(manager);
|
||||||
} catch (IOException | KeyBackupSystemNoDataException | KeyBackupServicePinException e) {
|
} catch (IOException | PinLockedException | IncorrectPinException e) {
|
||||||
throw new SignalControl.Error.Failure(e.getClass().getSimpleName() + " " + e.getMessage());
|
throw new SignalControl.Error.Failure(e.getClass().getSimpleName() + " " + e.getMessage());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,9 +11,11 @@ import org.asamk.signal.manager.UntrustedIdentityException;
|
||||||
import org.asamk.signal.manager.api.Identity;
|
import org.asamk.signal.manager.api.Identity;
|
||||||
import org.asamk.signal.manager.api.InactiveGroupLinkException;
|
import org.asamk.signal.manager.api.InactiveGroupLinkException;
|
||||||
import org.asamk.signal.manager.api.InvalidDeviceLinkException;
|
import org.asamk.signal.manager.api.InvalidDeviceLinkException;
|
||||||
|
import org.asamk.signal.manager.api.InvalidNumberException;
|
||||||
import org.asamk.signal.manager.api.Message;
|
import org.asamk.signal.manager.api.Message;
|
||||||
import org.asamk.signal.manager.api.Pair;
|
import org.asamk.signal.manager.api.Pair;
|
||||||
import org.asamk.signal.manager.api.RecipientIdentifier;
|
import org.asamk.signal.manager.api.RecipientIdentifier;
|
||||||
|
import org.asamk.signal.manager.api.SendMessageResult;
|
||||||
import org.asamk.signal.manager.api.TypingAction;
|
import org.asamk.signal.manager.api.TypingAction;
|
||||||
import org.asamk.signal.manager.api.UpdateGroup;
|
import org.asamk.signal.manager.api.UpdateGroup;
|
||||||
import org.asamk.signal.manager.groups.GroupId;
|
import org.asamk.signal.manager.groups.GroupId;
|
||||||
|
@ -32,8 +34,6 @@ import org.freedesktop.dbus.connections.impl.DBusConnection;
|
||||||
import org.freedesktop.dbus.exceptions.DBusException;
|
import org.freedesktop.dbus.exceptions.DBusException;
|
||||||
import org.freedesktop.dbus.exceptions.DBusExecutionException;
|
import org.freedesktop.dbus.exceptions.DBusExecutionException;
|
||||||
import org.freedesktop.dbus.types.Variant;
|
import org.freedesktop.dbus.types.Variant;
|
||||||
import org.whispersystems.signalservice.api.messages.SendMessageResult;
|
|
||||||
import org.whispersystems.signalservice.api.util.InvalidNumberException;
|
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
@ -719,7 +719,7 @@ public class DbusSignalImpl implements Signal {
|
||||||
|
|
||||||
final var message = timestamp + "\nFailed to send message:\n" + error + '\n';
|
final var message = timestamp + "\nFailed to send message:\n" + error + '\n';
|
||||||
|
|
||||||
if (result.getIdentityFailure() != null) {
|
if (result.isIdentityFailure()) {
|
||||||
throw new Error.UntrustedIdentity(message);
|
throw new Error.UntrustedIdentity(message);
|
||||||
} else {
|
} else {
|
||||||
throw new Error.Failure(message);
|
throw new Error.Failure(message);
|
||||||
|
|
|
@ -5,9 +5,9 @@ import com.fasterxml.jackson.annotation.JsonInclude;
|
||||||
import org.asamk.Signal;
|
import org.asamk.Signal;
|
||||||
import org.asamk.signal.manager.Manager;
|
import org.asamk.signal.manager.Manager;
|
||||||
import org.asamk.signal.manager.UntrustedIdentityException;
|
import org.asamk.signal.manager.UntrustedIdentityException;
|
||||||
|
import org.asamk.signal.manager.api.InvalidNumberException;
|
||||||
import org.asamk.signal.manager.api.MessageEnvelope;
|
import org.asamk.signal.manager.api.MessageEnvelope;
|
||||||
import org.asamk.signal.manager.api.RecipientIdentifier;
|
import org.asamk.signal.manager.api.RecipientIdentifier;
|
||||||
import org.whispersystems.signalservice.api.util.InvalidNumberException;
|
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
|
@ -2,10 +2,10 @@ package org.asamk.signal.util;
|
||||||
|
|
||||||
import org.asamk.signal.commands.exceptions.UserErrorException;
|
import org.asamk.signal.commands.exceptions.UserErrorException;
|
||||||
import org.asamk.signal.manager.Manager;
|
import org.asamk.signal.manager.Manager;
|
||||||
|
import org.asamk.signal.manager.api.InvalidNumberException;
|
||||||
import org.asamk.signal.manager.api.RecipientIdentifier;
|
import org.asamk.signal.manager.api.RecipientIdentifier;
|
||||||
import org.asamk.signal.manager.groups.GroupId;
|
import org.asamk.signal.manager.groups.GroupId;
|
||||||
import org.asamk.signal.manager.groups.GroupIdFormatException;
|
import org.asamk.signal.manager.groups.GroupIdFormatException;
|
||||||
import org.whispersystems.signalservice.api.util.InvalidNumberException;
|
|
||||||
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
|
|
|
@ -2,11 +2,11 @@ package org.asamk.signal.util;
|
||||||
|
|
||||||
import org.asamk.signal.commands.exceptions.CommandException;
|
import org.asamk.signal.commands.exceptions.CommandException;
|
||||||
import org.asamk.signal.commands.exceptions.IOErrorException;
|
import org.asamk.signal.commands.exceptions.IOErrorException;
|
||||||
|
import org.asamk.signal.manager.api.ProofRequiredException;
|
||||||
import org.asamk.signal.manager.api.RecipientIdentifier;
|
import org.asamk.signal.manager.api.RecipientIdentifier;
|
||||||
|
import org.asamk.signal.manager.api.SendMessageResult;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
import org.whispersystems.signalservice.api.messages.SendMessageResult;
|
|
||||||
import org.whispersystems.signalservice.api.push.exceptions.ProofRequiredException;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
@ -14,8 +14,6 @@ import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
import static org.asamk.signal.util.Util.getLegacyIdentifier;
|
|
||||||
|
|
||||||
public class ErrorUtils {
|
public class ErrorUtils {
|
||||||
|
|
||||||
private final static Logger logger = LoggerFactory.getLogger(ErrorUtils.class);
|
private final static Logger logger = LoggerFactory.getLogger(ErrorUtils.class);
|
||||||
|
@ -57,9 +55,9 @@ public class ErrorUtils {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String getErrorMessageFromSendMessageResult(SendMessageResult result) {
|
public static String getErrorMessageFromSendMessageResult(SendMessageResult result) {
|
||||||
var identifier = getLegacyIdentifier(result.getAddress());
|
var identifier = result.address().getLegacyIdentifier();
|
||||||
if (result.getProofRequiredFailure() != null) {
|
if (result.proofRequiredFailure() != null) {
|
||||||
final var failure = result.getProofRequiredFailure();
|
final var failure = result.proofRequiredFailure();
|
||||||
return String.format(
|
return String.format(
|
||||||
"CAPTCHA proof required for sending to \"%s\", available options \"%s\" with challenge token \"%s\", or wait \"%d\" seconds.\n"
|
"CAPTCHA proof required for sending to \"%s\", available options \"%s\" with challenge token \"%s\", or wait \"%d\" seconds.\n"
|
||||||
+ (
|
+ (
|
||||||
|
@ -83,7 +81,7 @@ public class ErrorUtils {
|
||||||
return String.format("Network failure for \"%s\"", identifier);
|
return String.format("Network failure for \"%s\"", identifier);
|
||||||
} else if (result.isUnregisteredFailure()) {
|
} else if (result.isUnregisteredFailure()) {
|
||||||
return String.format("Unregistered user \"%s\"", identifier);
|
return String.format("Unregistered user \"%s\"", identifier);
|
||||||
} else if (result.getIdentityFailure() != null) {
|
} else if (result.isIdentityFailure()) {
|
||||||
return String.format("Untrusted Identity for \"%s\"", identifier);
|
return String.format("Untrusted Identity for \"%s\"", identifier);
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
|
|
|
@ -5,8 +5,6 @@ import com.fasterxml.jackson.annotation.PropertyAccessor;
|
||||||
import com.fasterxml.jackson.core.JsonGenerator;
|
import com.fasterxml.jackson.core.JsonGenerator;
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
|
|
||||||
import org.whispersystems.signalservice.api.push.SignalServiceAddress;
|
|
||||||
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
|
@ -59,10 +57,6 @@ public class Util {
|
||||||
return f.toString();
|
return f.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String getLegacyIdentifier(final SignalServiceAddress address) {
|
|
||||||
return address.getNumber().or(() -> address.getUuid().toString());
|
|
||||||
}
|
|
||||||
|
|
||||||
public static ObjectMapper createJsonObjectMapper() {
|
public static ObjectMapper createJsonObjectMapper() {
|
||||||
var objectMapper = new ObjectMapper();
|
var objectMapper = new ObjectMapper();
|
||||||
objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.PUBLIC_ONLY);
|
objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.PUBLIC_ONLY);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue