diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index da2122f1..cbbbbd7a 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -16,7 +16,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - java: [ '25' ] + java: [ '25', '26' ] steps: - uses: actions/checkout@v6 diff --git a/CHANGELOG.md b/CHANGELOG.md index 7567a29d..74377ed7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,15 @@ # 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 diff --git a/build.gradle.kts b/build.gradle.kts index 631be293..2f4e25bb 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -10,7 +10,7 @@ plugins { allprojects { group = "org.asamk" - version = "0.14.2-SNAPSHOT" + version = "0.14.2" } java { @@ -160,6 +160,20 @@ tasks.register("fatJar", type = Jar::class) { 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("jsonSchemas") { dependsOn(tasks.compileJava) val schemaBaseUri = "http://localhost:8080/schemas/" diff --git a/data/org.asamk.SignalCli.metainfo.xml b/data/org.asamk.SignalCli.metainfo.xml index 15df456a..c1730192 100644 --- a/data/org.asamk.SignalCli.metainfo.xml +++ b/data/org.asamk.SignalCli.metainfo.xml @@ -45,6 +45,9 @@ intense + + https://github.com/AsamK/signal-cli/releases/tag/v0.14.2 + https://github.com/AsamK/signal-cli/releases/tag/v0.14.1 diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index dbc3ce4a..c61a118f 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME 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 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME diff --git a/lib/src/main/java/org/asamk/signal/manager/helper/AccountHelper.java b/lib/src/main/java/org/asamk/signal/manager/helper/AccountHelper.java index 82fb7d5a..2396b36e 100644 --- a/lib/src/main/java/org/asamk/signal/manager/helper/AccountHelper.java +++ b/lib/src/main/java/org/asamk/signal/manager/helper/AccountHelper.java @@ -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.AuthorizationFailedException; import org.whispersystems.signalservice.api.push.exceptions.DeprecatedVersionException; -import org.whispersystems.signalservice.api.push.exceptions.UsernameIsNotReservedException; -import org.whispersystems.signalservice.api.push.exceptions.UsernameMalformedException; -import org.whispersystems.signalservice.api.push.exceptions.UsernameTakenException; +import org.whispersystems.signalservice.api.push.exceptions.NonSuccessfulResponseCodeException; import org.whispersystems.signalservice.api.util.DeviceNameUtil; import org.whispersystems.signalservice.internal.push.DeviceLimitExceededException; import org.whispersystems.signalservice.internal.push.KyberPreKeyEntity; @@ -465,7 +463,7 @@ public class AccountHelper { logger.debug("Attempting to resynchronize username."); try { tryReserveConfirmUsername(username); - } catch (UsernameMalformedException | UsernameTakenException | UsernameIsNotReservedException e) { + } catch (NonSuccessfulResponseCodeException e) { logger.debug("[confirmUsername] Failed to reserve confirm username: {} ({})", e.getMessage(), e.getClass().getSimpleName()); diff --git a/lib/src/main/java/org/asamk/signal/manager/internal/ManagerImpl.java b/lib/src/main/java/org/asamk/signal/manager/internal/ManagerImpl.java index 3a3da757..e0174e7f 100644 --- a/lib/src/main/java/org/asamk/signal/manager/internal/ManagerImpl.java +++ b/lib/src/main/java/org/asamk/signal/manager/internal/ManagerImpl.java @@ -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.push.ServiceIdType; import org.whispersystems.signalservice.api.push.exceptions.CdsiResourceExhaustedException; -import org.whispersystems.signalservice.api.push.exceptions.UsernameMalformedException; -import org.whispersystems.signalservice.api.push.exceptions.UsernameTakenException; +import org.whispersystems.signalservice.api.push.exceptions.NonSuccessfulResponseCodeException; import org.whispersystems.signalservice.api.util.DeviceNameUtil; import org.whispersystems.signalservice.api.util.StreamDetails; import org.whispersystems.signalservice.internal.util.Util; @@ -411,10 +410,8 @@ public class ManagerImpl implements Manager { } else { context.getAccountHelper().reserveUsernameFromNickname(username); } - } catch (UsernameMalformedException e) { - throw new InvalidUsernameException("Username is malformed", e); - } catch (UsernameTakenException e) { - throw new InvalidUsernameException("Username is already registered", e); + } catch (NonSuccessfulResponseCodeException e) { + throw new InvalidUsernameException("Username is malformed or already taken", e); } catch (BaseUsernameException e) { throw new InvalidUsernameException(e.getMessage() + " (" + e.getClass().getSimpleName() + ")", e); } diff --git a/lib/src/main/java/org/asamk/signal/manager/internal/RegistrationManagerImpl.java b/lib/src/main/java/org/asamk/signal/manager/internal/RegistrationManagerImpl.java index ee1cd096..e90bb154 100644 --- a/lib/src/main/java/org/asamk/signal/manager/internal/RegistrationManagerImpl.java +++ b/lib/src/main/java/org/asamk/signal/manager/internal/RegistrationManagerImpl.java @@ -45,6 +45,7 @@ import org.whispersystems.signalservice.api.push.ServiceIdType; import org.whispersystems.signalservice.api.push.SignalServiceAddress; import org.whispersystems.signalservice.api.push.exceptions.AlreadyVerifiedException; 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.internal.push.VerifyAccountResponse; @@ -262,6 +263,8 @@ public class RegistrationManagerImpl implements RegistrationManager { final var registrationApi = unauthenticatedAccountManager.getRegistrationApi(); try { 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) { // Already verified so can continue registering } diff --git a/libsignal-version b/libsignal-version new file mode 100644 index 00000000..ae02209b --- /dev/null +++ b/libsignal-version @@ -0,0 +1 @@ +0.90.0 diff --git a/src/main/java/org/asamk/signal/BaseConfig.java b/src/main/java/org/asamk/signal/BaseConfig.java index dc19b461..022a22f1 100644 --- a/src/main/java/org/asamk/signal/BaseConfig.java +++ b/src/main/java/org/asamk/signal/BaseConfig.java @@ -8,7 +8,7 @@ public class BaseConfig { 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")) - .orElse("Signal-Android/8.1.2"); + .orElse("Signal-Android/8.6.1"); static final String USER_AGENT_SIGNAL_CLI = PROJECT_NAME == null ? "signal-cli" : PROJECT_NAME + "/" + PROJECT_VERSION; diff --git a/src/main/java/org/asamk/signal/commands/GetAttachmentCommand.java b/src/main/java/org/asamk/signal/commands/GetAttachmentCommand.java index cf716194..c640ee83 100644 --- a/src/main/java/org/asamk/signal/commands/GetAttachmentCommand.java +++ b/src/main/java/org/asamk/signal/commands/GetAttachmentCommand.java @@ -41,6 +41,9 @@ public class GetAttachmentCommand implements JsonRpcLocalCommand { ) throws CommandException { final var id = ns.getString("id"); + if (id == null) { + throw new UserErrorException("Missing attachment id parameter"); + } try (InputStream attachment = m.retrieveAttachment(id)) { final var bytes = attachment.readAllBytes();