Merge branch 'master' into openapi-docs

This commit is contained in:
Era Dorta 2026-04-06 18:22:07 +02:00
commit 7773a3fd83
11 changed files with 43 additions and 15 deletions

View File

@ -16,7 +16,7 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
strategy: strategy:
matrix: matrix:
java: [ '25' ] java: [ '25', '26' ]
steps: steps:
- uses: actions/checkout@v6 - uses: actions/checkout@v6

View File

@ -1,6 +1,15 @@
# Changelog # Changelog
## [Unreleased] ## [0.14.2] - 2026-04-04
### Added
- Add `--voice-note` parameter to `send` command (Thanks @Kevin)
- Add experimental support for voice calling (Thanks @visigoth)
### Fixed
- Fix `updateGroup` command for adding admins and removing members (Thanks @joeykrim)
## [0.14.1] - 2026-03-08 ## [0.14.1] - 2026-03-08

View File

@ -10,7 +10,7 @@ plugins {
allprojects { allprojects {
group = "org.asamk" group = "org.asamk"
version = "0.14.2-SNAPSHOT" version = "0.14.2"
} }
java { java {
@ -160,6 +160,20 @@ tasks.register("fatJar", type = Jar::class) {
with(tasks.jar.get()) with(tasks.jar.get())
} }
tasks.register("writeLibsignalVersion") {
doLast {
val resolutionResult = configurations.runtimeClasspath.get().incoming.resolutionResult
val libsignalDep =
resolutionResult.allDependencies.find { dep -> dep.requested is ModuleComponentSelector && (dep.requested as ModuleComponentSelector).group == "org.signal" && (dep.requested as ModuleComponentSelector).moduleIdentifier.name == "libsignal-client" }
if (libsignalDep != null) {
val version = (libsignalDep.requested as ModuleComponentSelector).version
file("libsignal-version").writeText(version + "\n")
} else {
throw GradleException("Could not find libsignal-client dependency")
}
}
}
tasks.register<JavaCompile>("jsonSchemas") { tasks.register<JavaCompile>("jsonSchemas") {
dependsOn(tasks.compileJava) dependsOn(tasks.compileJava)
val schemaBaseUri = "http://localhost:8080/schemas/" val schemaBaseUri = "http://localhost:8080/schemas/"

View File

@ -45,6 +45,9 @@
<content_attribute id="social-chat">intense</content_attribute> <content_attribute id="social-chat">intense</content_attribute>
</content_rating> </content_rating>
<releases> <releases>
<release version="0.14.2" date="2026-04-04">
<url type="details">https://github.com/AsamK/signal-cli/releases/tag/v0.14.2</url>
</release>
<release version="0.14.1" date="2026-03-08"> <release version="0.14.1" date="2026-03-08">
<url type="details">https://github.com/AsamK/signal-cli/releases/tag/v0.14.1</url> <url type="details">https://github.com/AsamK/signal-cli/releases/tag/v0.14.1</url>
</release> </release>

View File

@ -1,6 +1,6 @@
distributionBase=GRADLE_USER_HOME distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-9.4.0-bin.zip distributionUrl=https\://services.gradle.org/distributions/gradle-9.4.1-bin.zip
networkTimeout=10000 networkTimeout=10000
validateDistributionUrl=true validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME zipStoreBase=GRADLE_USER_HOME

View File

@ -37,9 +37,7 @@ import org.whispersystems.signalservice.api.push.UsernameLinkComponents;
import org.whispersystems.signalservice.api.push.exceptions.AlreadyVerifiedException; import org.whispersystems.signalservice.api.push.exceptions.AlreadyVerifiedException;
import org.whispersystems.signalservice.api.push.exceptions.AuthorizationFailedException; import org.whispersystems.signalservice.api.push.exceptions.AuthorizationFailedException;
import org.whispersystems.signalservice.api.push.exceptions.DeprecatedVersionException; import org.whispersystems.signalservice.api.push.exceptions.DeprecatedVersionException;
import org.whispersystems.signalservice.api.push.exceptions.UsernameIsNotReservedException; import org.whispersystems.signalservice.api.push.exceptions.NonSuccessfulResponseCodeException;
import org.whispersystems.signalservice.api.push.exceptions.UsernameMalformedException;
import org.whispersystems.signalservice.api.push.exceptions.UsernameTakenException;
import org.whispersystems.signalservice.api.util.DeviceNameUtil; import org.whispersystems.signalservice.api.util.DeviceNameUtil;
import org.whispersystems.signalservice.internal.push.DeviceLimitExceededException; import org.whispersystems.signalservice.internal.push.DeviceLimitExceededException;
import org.whispersystems.signalservice.internal.push.KyberPreKeyEntity; import org.whispersystems.signalservice.internal.push.KyberPreKeyEntity;
@ -465,7 +463,7 @@ public class AccountHelper {
logger.debug("Attempting to resynchronize username."); logger.debug("Attempting to resynchronize username.");
try { try {
tryReserveConfirmUsername(username); tryReserveConfirmUsername(username);
} catch (UsernameMalformedException | UsernameTakenException | UsernameIsNotReservedException e) { } catch (NonSuccessfulResponseCodeException e) {
logger.debug("[confirmUsername] Failed to reserve confirm username: {} ({})", logger.debug("[confirmUsername] Failed to reserve confirm username: {} ({})",
e.getMessage(), e.getMessage(),
e.getClass().getSimpleName()); e.getClass().getSimpleName());

View File

@ -117,8 +117,7 @@ import org.whispersystems.signalservice.api.messages.calls.SignalServiceCallMess
import org.whispersystems.signalservice.api.messages.multidevice.DeviceInfo; import org.whispersystems.signalservice.api.messages.multidevice.DeviceInfo;
import org.whispersystems.signalservice.api.push.ServiceIdType; import org.whispersystems.signalservice.api.push.ServiceIdType;
import org.whispersystems.signalservice.api.push.exceptions.CdsiResourceExhaustedException; import org.whispersystems.signalservice.api.push.exceptions.CdsiResourceExhaustedException;
import org.whispersystems.signalservice.api.push.exceptions.UsernameMalformedException; import org.whispersystems.signalservice.api.push.exceptions.NonSuccessfulResponseCodeException;
import org.whispersystems.signalservice.api.push.exceptions.UsernameTakenException;
import org.whispersystems.signalservice.api.util.DeviceNameUtil; import org.whispersystems.signalservice.api.util.DeviceNameUtil;
import org.whispersystems.signalservice.api.util.StreamDetails; import org.whispersystems.signalservice.api.util.StreamDetails;
import org.whispersystems.signalservice.internal.util.Util; import org.whispersystems.signalservice.internal.util.Util;
@ -411,10 +410,8 @@ public class ManagerImpl implements Manager {
} else { } else {
context.getAccountHelper().reserveUsernameFromNickname(username); context.getAccountHelper().reserveUsernameFromNickname(username);
} }
} catch (UsernameMalformedException e) { } catch (NonSuccessfulResponseCodeException e) {
throw new InvalidUsernameException("Username is malformed", e); throw new InvalidUsernameException("Username is malformed or already taken", e);
} catch (UsernameTakenException e) {
throw new InvalidUsernameException("Username is already registered", e);
} catch (BaseUsernameException e) { } catch (BaseUsernameException e) {
throw new InvalidUsernameException(e.getMessage() + " (" + e.getClass().getSimpleName() + ")", e); throw new InvalidUsernameException(e.getMessage() + " (" + e.getClass().getSimpleName() + ")", e);
} }

View File

@ -45,6 +45,7 @@ import org.whispersystems.signalservice.api.push.ServiceIdType;
import org.whispersystems.signalservice.api.push.SignalServiceAddress; import org.whispersystems.signalservice.api.push.SignalServiceAddress;
import org.whispersystems.signalservice.api.push.exceptions.AlreadyVerifiedException; import org.whispersystems.signalservice.api.push.exceptions.AlreadyVerifiedException;
import org.whispersystems.signalservice.api.push.exceptions.DeprecatedVersionException; import org.whispersystems.signalservice.api.push.exceptions.DeprecatedVersionException;
import org.whispersystems.signalservice.api.push.exceptions.MustRequestNewCodeException;
import org.whispersystems.signalservice.api.svr.SecureValueRecovery; import org.whispersystems.signalservice.api.svr.SecureValueRecovery;
import org.whispersystems.signalservice.internal.push.VerifyAccountResponse; import org.whispersystems.signalservice.internal.push.VerifyAccountResponse;
@ -262,6 +263,8 @@ public class RegistrationManagerImpl implements RegistrationManager {
final var registrationApi = unauthenticatedAccountManager.getRegistrationApi(); final var registrationApi = unauthenticatedAccountManager.getRegistrationApi();
try { try {
handleResponseException(registrationApi.verifyAccount(sessionId, verificationCode)); handleResponseException(registrationApi.verifyAccount(sessionId, verificationCode));
} catch (MustRequestNewCodeException e) {
throw new IOException("Verification code expired, please request a new one by registering again.", e);
} catch (AlreadyVerifiedException e) { } catch (AlreadyVerifiedException e) {
// Already verified so can continue registering // Already verified so can continue registering
} }

1
libsignal-version Normal file
View File

@ -0,0 +1 @@
0.90.0

View File

@ -8,7 +8,7 @@ public class BaseConfig {
public static final String PROJECT_VERSION = BaseConfig.class.getPackage().getImplementationVersion(); public static final String PROJECT_VERSION = BaseConfig.class.getPackage().getImplementationVersion();
static final String USER_AGENT_SIGNAL_ANDROID = Optional.ofNullable(System.getenv("SIGNAL_CLI_USER_AGENT")) static final String USER_AGENT_SIGNAL_ANDROID = Optional.ofNullable(System.getenv("SIGNAL_CLI_USER_AGENT"))
.orElse("Signal-Android/8.1.2"); .orElse("Signal-Android/8.6.1");
static final String USER_AGENT_SIGNAL_CLI = PROJECT_NAME == null static final String USER_AGENT_SIGNAL_CLI = PROJECT_NAME == null
? "signal-cli" ? "signal-cli"
: PROJECT_NAME + "/" + PROJECT_VERSION; : PROJECT_NAME + "/" + PROJECT_VERSION;

View File

@ -41,6 +41,9 @@ public class GetAttachmentCommand implements JsonRpcLocalCommand {
) throws CommandException { ) throws CommandException {
final var id = ns.getString("id"); final var id = ns.getString("id");
if (id == null) {
throw new UserErrorException("Missing attachment id parameter");
}
try (InputStream attachment = m.retrieveAttachment(id)) { try (InputStream attachment = m.retrieveAttachment(id)) {
final var bytes = attachment.readAllBytes(); final var bytes = attachment.readAllBytes();