mirror of
https://github.com/AsamK/signal-cli.git
synced 2026-01-28 19:13:33 +00:00
Compare commits
28 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
14297986f2 | ||
|
|
0bd4d554d8 | ||
|
|
32c8d4f801 | ||
|
|
82abc20871 | ||
|
|
e8ab01f665 | ||
|
|
dee557a9ad | ||
|
|
f1fa2eba1d | ||
|
|
ccd58bbf23 | ||
|
|
54700d9cd0 | ||
|
|
984ea47f9d | ||
|
|
9458972d15 | ||
|
|
8eb9662694 | ||
|
|
a9be1aa608 | ||
|
|
3af9dff0ed | ||
|
|
c5e4b250b8 | ||
|
|
5fafa24974 | ||
|
|
b26c521930 | ||
|
|
eb52380ecf | ||
|
|
f1de69d7ff | ||
|
|
ba2214d8c7 | ||
|
|
fca4d7459c | ||
|
|
ad2338b898 | ||
|
|
c237f98044 | ||
|
|
87945ac506 | ||
|
|
11d96c894d | ||
|
|
8dcc16d640 | ||
|
|
9a1ddd0d41 | ||
|
|
b8bb58b083 |
6
.github/workflows/ci.yml
vendored
6
.github/workflows/ci.yml
vendored
@ -16,7 +16,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
matrix:
|
||||
java: [ '21', '25' ]
|
||||
java: [ '25' ]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
@ -58,8 +58,8 @@ jobs:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: graalvm/setup-graalvm@v1
|
||||
with:
|
||||
version: 'latest'
|
||||
java-version: '21'
|
||||
distribution: 'graalvm'
|
||||
java-version: '25'
|
||||
cache: 'gradle'
|
||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
- name: Build with Gradle
|
||||
|
||||
2
.github/workflows/codeql-analysis.yml
vendored
2
.github/workflows/codeql-analysis.yml
vendored
@ -24,7 +24,7 @@ jobs:
|
||||
uses: actions/setup-java@v3
|
||||
with:
|
||||
distribution: 'zulu'
|
||||
java-version: 21
|
||||
java-version: 25
|
||||
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
|
||||
27
CHANGELOG.md
27
CHANGELOG.md
@ -1,5 +1,32 @@
|
||||
# Changelog
|
||||
|
||||
## [Unreleased]
|
||||
|
||||
**Attention**: Now requires Java 25
|
||||
|
||||
### Breaking changes
|
||||
|
||||
- Remove isRegistered method without parameters from Signal dbus interface, which always returned `true`
|
||||
- Remove `sandbox` value for --service-environment parameter, use `staging` instead
|
||||
- The `daemon` command now requires at least one channel parameter (`--socket`, `--dbus`, ...) and no longer defaults to dbus
|
||||
|
||||
## [0.13.23] - 2026-01-24
|
||||
|
||||
Requires libsignal-client version 0.86.12.
|
||||
|
||||
### Added
|
||||
|
||||
- Add sendPollCreate, sendPollVote, sendPollTerminate commands for polls
|
||||
- Add updateDevice command to set device name of linked devices
|
||||
|
||||
### Changed
|
||||
|
||||
- Allow updating contact names from linked devices
|
||||
|
||||
### Fixed
|
||||
|
||||
- Start multi account mode even if some accounts have authorization failures
|
||||
|
||||
## [0.13.22] - 2025-11-14
|
||||
|
||||
Requires libsignal-client version 0.86.1.
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
FROM docker.io/azul/zulu-openjdk:21-jre-headless
|
||||
FROM docker.io/azul/zulu-openjdk:25-jre-headless
|
||||
|
||||
LABEL org.opencontainers.image.source=https://github.com/AsamK/signal-cli
|
||||
LABEL org.opencontainers.image.description="signal-cli provides an unofficial commandline, dbus and JSON-RPC interface for the Signal messenger."
|
||||
|
||||
19
README.md
19
README.md
@ -8,7 +8,7 @@ For registering you need a phone number where you can receive SMS or incoming ca
|
||||
|
||||
signal-cli is primarily intended to be used on servers to notify admins of important events.
|
||||
For this use-case, it has a daemon mode with JSON-RPC interface ([man page](https://github.com/AsamK/signal-cli/blob/master/man/signal-cli-jsonrpc.5.adoc))
|
||||
and D-BUS interface ([man page](https://github.com/AsamK/signal-cli/blob/master/man/signal-cli-dbus.5.adoc)) .
|
||||
and D-BUS interface ([man page](https://github.com/AsamK/signal-cli/blob/master/man/signal-cli-dbus.5.adoc)).
|
||||
For the JSON-RPC interface there's also a simple [example client](https://github.com/AsamK/signal-cli/tree/master/client), written in Rust.
|
||||
|
||||
signal-cli needs to be kept up-to-date to keep up with Signal-Server changes.
|
||||
@ -23,24 +23,33 @@ Windows. There's also a [docker image and some Linux packages](https://github.co
|
||||
|
||||
System requirements:
|
||||
|
||||
- at least Java Runtime Environment (JRE) 21
|
||||
- at least Java Runtime Environment (JRE) 25
|
||||
- native library: libsignal-client
|
||||
|
||||
The native libs are bundled for x86_64 Linux (with recent enough glibc), Windows and MacOS. For other
|
||||
systems/architectures
|
||||
see: [Provide native lib for libsignal](https://github.com/AsamK/signal-cli/wiki/Provide-native-lib-for-libsignal)
|
||||
|
||||
### Install system-wide on Linux
|
||||
### Install system-wide on Linux [ JVM build ]
|
||||
|
||||
See [latest version](https://github.com/AsamK/signal-cli/releases).
|
||||
|
||||
```sh
|
||||
export VERSION=<latest version, format "x.y.z">
|
||||
wget https://github.com/AsamK/signal-cli/releases/download/v"${VERSION}"/signal-cli-"${VERSION}".tar.gz
|
||||
VERSION=$(curl -Ls -o /dev/null -w %{url_effective} https://github.com/AsamK/signal-cli/releases/latest | sed -e 's/^.*\/v//')
|
||||
curl -L -O https://github.com/AsamK/signal-cli/releases/download/v"${VERSION}"/signal-cli-"${VERSION}".tar.gz
|
||||
sudo tar xf signal-cli-"${VERSION}".tar.gz -C /opt
|
||||
sudo ln -sf /opt/signal-cli-"${VERSION}"/bin/signal-cli /usr/local/bin/
|
||||
```
|
||||
|
||||
### Install system-wide on Linux [ GraalVM native build ]
|
||||
|
||||
```sh
|
||||
VERSION=$(curl -Ls -o /dev/null -w %{url_effective} https://github.com/AsamK/signal-cli/releases/latest | sed -e 's/^.*\/v//')
|
||||
curl -L -O https://github.com/AsamK/signal-cli/releases/download/v"${VERSION}"/signal-cli-"${VERSION}"-Linux-native.tar.gz
|
||||
sudo tar xf signal-cli-"${VERSION}"-Linux-native.tar.gz -C /opt
|
||||
sudo ln -sf /opt/signal-cli /usr/local/bin/
|
||||
```
|
||||
|
||||
You can find further instructions on the Wiki:
|
||||
|
||||
- [Quickstart](https://github.com/AsamK/signal-cli/wiki/Quickstart)
|
||||
|
||||
@ -3,17 +3,17 @@ plugins {
|
||||
application
|
||||
eclipse
|
||||
`check-lib-versions`
|
||||
id("org.graalvm.buildtools.native") version "0.11.3"
|
||||
id("org.graalvm.buildtools.native") version "0.11.4"
|
||||
}
|
||||
|
||||
allprojects {
|
||||
group = "org.asamk"
|
||||
version = "0.13.22"
|
||||
version = "0.14.0-SNAPSHOT"
|
||||
}
|
||||
|
||||
java {
|
||||
sourceCompatibility = JavaVersion.VERSION_21
|
||||
targetCompatibility = JavaVersion.VERSION_21
|
||||
sourceCompatibility = JavaVersion.VERSION_25
|
||||
targetCompatibility = JavaVersion.VERSION_25
|
||||
|
||||
if (!JavaVersion.current().isCompatibleWith(targetCompatibility)) {
|
||||
toolchain {
|
||||
@ -39,7 +39,7 @@ graalvmNative {
|
||||
if (System.getenv("GRAALVM_HOME") == null) {
|
||||
toolchainDetection.set(true)
|
||||
javaLauncher.set(javaToolchains.launcherFor {
|
||||
languageVersion.set(JavaLanguageVersion.of(21))
|
||||
languageVersion.set(JavaLanguageVersion.of(25))
|
||||
})
|
||||
} else {
|
||||
toolchainDetection.set(false)
|
||||
|
||||
@ -7,11 +7,11 @@ plugins {
|
||||
}
|
||||
|
||||
tasks.named<KotlinCompilationTask<KotlinJvmCompilerOptions>>("compileKotlin").configure {
|
||||
compilerOptions.jvmTarget.set(JvmTarget.JVM_17)
|
||||
compilerOptions.jvmTarget.set(JvmTarget.JVM_24)
|
||||
}
|
||||
|
||||
java {
|
||||
targetCompatibility = JavaVersion.VERSION_17
|
||||
targetCompatibility = JavaVersion.VERSION_24
|
||||
}
|
||||
|
||||
repositories {
|
||||
|
||||
@ -1,5 +1,3 @@
|
||||
@file:Suppress("DEPRECATION")
|
||||
|
||||
import org.gradle.api.Plugin
|
||||
import org.gradle.api.Project
|
||||
import org.gradle.api.Task
|
||||
@ -8,7 +6,7 @@ import javax.xml.parsers.DocumentBuilderFactory
|
||||
|
||||
class CheckLibVersionsPlugin : Plugin<Project> {
|
||||
override fun apply(project: Project) {
|
||||
project.task("checkLibVersions") {
|
||||
project.tasks.register("checkLibVersions") {
|
||||
description =
|
||||
"Find any 3rd party libraries which have released new versions to the central Maven repo since we last upgraded."
|
||||
doLast {
|
||||
@ -28,7 +26,7 @@ class CheckLibVersionsPlugin : Plugin<Project> {
|
||||
try {
|
||||
val dbf = DocumentBuilderFactory.newInstance()
|
||||
val db = dbf.newDocumentBuilder()
|
||||
val doc = db.parse(metaDataUrl);
|
||||
val doc = db.parse(metaDataUrl)
|
||||
val newest = doc.getElementsByTagName("latest").item(0).textContent
|
||||
if (version != newest.toString()) {
|
||||
println("UPGRADE {\"group\": \"$group\", \"name\": \"$name\", \"current\": \"$version\", \"latest\": \"$newest\"}")
|
||||
|
||||
@ -45,6 +45,9 @@
|
||||
<content_attribute id="social-chat">intense</content_attribute>
|
||||
</content_rating>
|
||||
<releases>
|
||||
<release version="0.13.23" date="2026-01-24">
|
||||
<url type="details">https://github.com/AsamK/signal-cli/releases/tag/v0.13.23</url>
|
||||
</release>
|
||||
<release version="0.13.22" date="2025-11-14">
|
||||
<url type="details">https://github.com/AsamK/signal-cli/releases/tag/v0.13.22</url>
|
||||
</release>
|
||||
|
||||
@ -121,7 +121,7 @@
|
||||
},
|
||||
{
|
||||
"name":"org.signal.libsignal.net.ChatConnection$ListenerBridge",
|
||||
"methods":[{"name":"onConnectionInterrupted","parameterTypes":["java.lang.Throwable"] }, {"name":"onIncomingMessage","parameterTypes":["byte[]","long","long"] }, {"name":"onQueueEmpty","parameterTypes":[] }, {"name":"onReceivedAlerts","parameterTypes":["java.lang.String[]"] }]
|
||||
"methods":[{"name":"connectionInterrupted","parameterTypes":["java.lang.Throwable"] }, {"name":"onConnectionInterrupted","parameterTypes":["java.lang.Throwable"] }, {"name":"onIncomingMessage","parameterTypes":["byte[]","long","long"] }, {"name":"onQueueEmpty","parameterTypes":[] }, {"name":"onReceivedAlerts","parameterTypes":["java.lang.String[]"] }, {"name":"receivedAlerts","parameterTypes":["java.lang.String[]"] }, {"name":"receivedIncomingMessage","parameterTypes":["byte[]","long","long"] }, {"name":"receivedQueueEmpty","parameterTypes":[] }]
|
||||
},
|
||||
{
|
||||
"name":"org.signal.libsignal.net.ChatConnection$Response",
|
||||
@ -139,6 +139,14 @@
|
||||
{
|
||||
"name":"org.signal.libsignal.net.ChatService$ResponseAndDebugInfo"
|
||||
},
|
||||
{
|
||||
"name":"org.signal.libsignal.net.ChatServiceException",
|
||||
"methods":[{"name":"<init>","parameterTypes":["java.lang.String"] }]
|
||||
},
|
||||
{
|
||||
"name":"org.signal.libsignal.net.ChatServiceInactiveException",
|
||||
"methods":[{"name":"<init>","parameterTypes":["java.lang.String"] }]
|
||||
},
|
||||
{
|
||||
"name":"org.signal.libsignal.net.DeviceDeregisteredException",
|
||||
"methods":[{"name":"<init>","parameterTypes":["java.lang.String"] }]
|
||||
@ -151,6 +159,10 @@
|
||||
"name":"org.signal.libsignal.net.RetryLaterException",
|
||||
"methods":[{"name":"<init>","parameterTypes":["long"] }]
|
||||
},
|
||||
{
|
||||
"name":"org.signal.libsignal.net.TransportFailureException",
|
||||
"methods":[{"name":"<init>","parameterTypes":["java.lang.String"] }]
|
||||
},
|
||||
{
|
||||
"name":"org.signal.libsignal.net.internal.BridgeChatListener"
|
||||
},
|
||||
|
||||
@ -1,26 +1 @@
|
||||
[
|
||||
{
|
||||
"interfaces":["java.sql.Connection"]
|
||||
},
|
||||
{
|
||||
"interfaces":["org.asamk.Signal"]
|
||||
},
|
||||
{
|
||||
"interfaces":["org.asamk.Signal$Configuration"]
|
||||
},
|
||||
{
|
||||
"interfaces":["org.asamk.Signal$Device"]
|
||||
},
|
||||
{
|
||||
"interfaces":["org.asamk.Signal$Group"]
|
||||
},
|
||||
{
|
||||
"interfaces":["org.asamk.Signal$Identity"]
|
||||
},
|
||||
{
|
||||
"interfaces":["org.asamk.SignalControl"]
|
||||
},
|
||||
{
|
||||
"interfaces":["org.freedesktop.dbus.interfaces.DBus"]
|
||||
}
|
||||
]
|
||||
[{"interfaces":["java.sql.Connection"]},{"interfaces":["org.asamk.Signal"]},{"interfaces":["org.asamk.Signal$Configuration"]},{"interfaces":["org.asamk.Signal$Device"]},{"interfaces":["org.asamk.Signal$Group"]},{"interfaces":["org.asamk.Signal$Identity"]},{"interfaces":["org.asamk.SignalControl"]},{"interfaces":["org.freedesktop.dbus.interfaces.DBus"]}]
|
||||
|
||||
9429
graalvm-config-dir/reachability-metadata.json
Normal file
9429
graalvm-config-dir/reachability-metadata.json
Normal file
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -1,18 +1,18 @@
|
||||
[versions]
|
||||
slf4j = "2.0.17"
|
||||
junit = "6.0.1"
|
||||
junit = "6.0.2"
|
||||
|
||||
[libraries]
|
||||
bouncycastle = "org.bouncycastle:bcprov-jdk18on:1.82"
|
||||
bouncycastle = "org.bouncycastle:bcprov-jdk18on:1.83"
|
||||
jackson-databind = "com.fasterxml.jackson.core:jackson-databind:2.20.1"
|
||||
argparse4j = "net.sourceforge.argparse4j:argparse4j:0.9.0"
|
||||
dbusjava = "com.github.hypfvieh:dbus-java-transport-native-unixsocket:5.0.0"
|
||||
slf4j-api = { module = "org.slf4j:slf4j-api", version.ref = "slf4j" }
|
||||
slf4j-jul = { module = "org.slf4j:jul-to-slf4j", version.ref = "slf4j" }
|
||||
logback = "ch.qos.logback:logback-classic:1.5.21"
|
||||
logback = "ch.qos.logback:logback-classic:1.5.25"
|
||||
|
||||
signalservice = "com.github.turasa:signal-service-java:2.15.3_unofficial_134"
|
||||
sqlite = "org.xerial:sqlite-jdbc:3.51.0.0"
|
||||
signalservice = "com.github.turasa:signal-service-java:2.15.3_unofficial_136"
|
||||
sqlite = "org.xerial:sqlite-jdbc:3.51.1.0"
|
||||
hikari = "com.zaxxer:HikariCP:7.0.2"
|
||||
junit-jupiter-bom = { module = "org.junit:junit-bom", version.ref = "junit" }
|
||||
junit-jupiter = { module = "org.junit.jupiter:junit-jupiter", version.ref = "junit" }
|
||||
|
||||
BIN
gradle/wrapper/gradle-wrapper.jar
vendored
BIN
gradle/wrapper/gradle-wrapper.jar
vendored
Binary file not shown.
2
gradle/wrapper/gradle-wrapper.properties
vendored
2
gradle/wrapper/gradle-wrapper.properties
vendored
@ -1,6 +1,6 @@
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-9.2.0-bin.zip
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-9.3.0-bin.zip
|
||||
networkTimeout=10000
|
||||
validateDistributionUrl=true
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
|
||||
@ -4,11 +4,13 @@ plugins {
|
||||
}
|
||||
|
||||
java {
|
||||
sourceCompatibility = JavaVersion.VERSION_21
|
||||
targetCompatibility = JavaVersion.VERSION_21
|
||||
sourceCompatibility = JavaVersion.VERSION_25
|
||||
targetCompatibility = JavaVersion.VERSION_25
|
||||
|
||||
toolchain {
|
||||
languageVersion.set(JavaLanguageVersion.of(21))
|
||||
if (!JavaVersion.current().isCompatibleWith(targetCompatibility)) {
|
||||
toolchain {
|
||||
languageVersion.set(JavaLanguageVersion.of(targetCompatibility.majorVersion))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -154,6 +154,8 @@ public interface Manager extends Closeable {
|
||||
|
||||
List<Device> getLinkedDevices() throws IOException;
|
||||
|
||||
void updateLinkedDevice(int deviceId, String name) throws IOException, NotPrimaryDeviceException;
|
||||
|
||||
void removeLinkedDevices(int deviceId) throws IOException, NotPrimaryDeviceException;
|
||||
|
||||
void addDeviceLink(DeviceLinkUrl linkUri) throws IOException, InvalidDeviceLinkException, NotPrimaryDeviceException, DeviceLimitExceededException;
|
||||
@ -271,7 +273,7 @@ public interface Manager extends Closeable {
|
||||
final String nickGivenName,
|
||||
final String nickFamilyName,
|
||||
final String note
|
||||
) throws NotPrimaryDeviceException, UnregisteredRecipientException;
|
||||
) throws UnregisteredRecipientException;
|
||||
|
||||
void setContactsBlocked(
|
||||
Collection<RecipientIdentifier.Single> recipient,
|
||||
|
||||
@ -64,7 +64,7 @@ public class SignalAccountFiles {
|
||||
return accountsStore.getAllNumbers();
|
||||
}
|
||||
|
||||
public MultiAccountManager initMultiAccountManager() throws IOException, AccountCheckException {
|
||||
public MultiAccountManager initMultiAccountManager() throws IOException {
|
||||
final var managerPairs = accountsStore.getAllAccounts().parallelStream().map(a -> {
|
||||
try {
|
||||
return new Pair<Manager, Throwable>(initManager(a.number(), a.path()), null);
|
||||
@ -80,12 +80,13 @@ public class SignalAccountFiles {
|
||||
for (final var pair : managerPairs) {
|
||||
if (pair.second() instanceof IOException e) {
|
||||
throw e;
|
||||
} else if (pair.second() instanceof AccountCheckException e) {
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
final var managers = managerPairs.stream().map(Pair::first).toList();
|
||||
final var managers = managerPairs.stream()
|
||||
.filter(p -> p != null && p.first() != null)
|
||||
.map(Pair::first)
|
||||
.toList();
|
||||
return new MultiAccountManagerImpl(managers, this);
|
||||
}
|
||||
|
||||
@ -132,7 +133,7 @@ public class SignalAccountFiles {
|
||||
manager.checkAccountState();
|
||||
} catch (DeprecatedVersionException e) {
|
||||
manager.close();
|
||||
throw new AccountCheckException("signal-cli version is too old for the Signal-Server, please update.");
|
||||
throw new IOException("signal-cli version is too old for the Signal-Server, please update.");
|
||||
} catch (IOException e) {
|
||||
manager.close();
|
||||
throw new AccountCheckException("Error while checking account " + number + ": " + e.getMessage(), e);
|
||||
|
||||
@ -2,7 +2,7 @@ package org.asamk.signal.manager.actions;
|
||||
|
||||
import org.asamk.signal.manager.helper.Context;
|
||||
import org.asamk.signal.manager.storage.recipients.RecipientId;
|
||||
import org.whispersystems.signalservice.api.push.ServiceId;
|
||||
import org.signal.core.models.ServiceId;
|
||||
|
||||
public class RenewSessionAction implements HandleAction {
|
||||
|
||||
|
||||
@ -0,0 +1,20 @@
|
||||
package org.asamk.signal.manager.actions;
|
||||
|
||||
import org.asamk.signal.manager.helper.Context;
|
||||
|
||||
public class RetrieveDeviceNameAction implements HandleAction {
|
||||
|
||||
private static final RetrieveDeviceNameAction INSTANCE = new RetrieveDeviceNameAction();
|
||||
|
||||
public static RetrieveDeviceNameAction create() {
|
||||
return INSTANCE;
|
||||
}
|
||||
|
||||
private RetrieveDeviceNameAction() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(Context context) throws Throwable {
|
||||
context.getAccountHelper().refreshDeviceName();
|
||||
}
|
||||
}
|
||||
@ -4,8 +4,8 @@ import org.asamk.signal.manager.groups.GroupLinkPassword;
|
||||
import org.signal.core.util.Base64;
|
||||
import org.signal.libsignal.zkgroup.InvalidInputException;
|
||||
import org.signal.libsignal.zkgroup.groups.GroupMasterKey;
|
||||
import org.signal.storageservice.protos.groups.GroupInviteLink;
|
||||
import org.signal.storageservice.protos.groups.local.DecryptedGroup;
|
||||
import org.signal.storageservice.storage.protos.groups.GroupInviteLink;
|
||||
import org.signal.storageservice.storage.protos.groups.local.DecryptedGroup;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.URI;
|
||||
@ -52,8 +52,8 @@ public final class GroupInviteLinkUrl {
|
||||
var bytes = Base64.decode(encoding);
|
||||
GroupInviteLink groupInviteLink = GroupInviteLink.ADAPTER.decode(bytes);
|
||||
|
||||
if (groupInviteLink.v1Contents != null) {
|
||||
var groupInviteLinkContentsV1 = groupInviteLink.v1Contents;
|
||||
if (groupInviteLink.contentsV1 != null) {
|
||||
var groupInviteLinkContentsV1 = groupInviteLink.contentsV1;
|
||||
var groupMasterKey = new GroupMasterKey(groupInviteLinkContentsV1.groupMasterKey.toByteArray());
|
||||
var password = GroupLinkPassword.fromBytes(groupInviteLinkContentsV1.inviteLinkPassword.toByteArray());
|
||||
|
||||
@ -90,7 +90,7 @@ public final class GroupInviteLinkUrl {
|
||||
}
|
||||
|
||||
private static String createUrl(GroupMasterKey groupMasterKey, GroupLinkPassword password) {
|
||||
var groupInviteLink = new GroupInviteLink.Builder().v1Contents(new GroupInviteLink.GroupInviteLinkContentsV1.Builder().groupMasterKey(
|
||||
var groupInviteLink = new GroupInviteLink.Builder().contentsV1(new GroupInviteLink.GroupInviteLinkContentsV1.Builder().groupMasterKey(
|
||||
ByteString.of(groupMasterKey.serialize()))
|
||||
.inviteLinkPassword(ByteString.of(password.serialize()))
|
||||
.build()).build();
|
||||
|
||||
@ -3,6 +3,7 @@ package org.asamk.signal.manager.api;
|
||||
import org.asamk.signal.manager.groups.GroupUtils;
|
||||
import org.asamk.signal.manager.helper.RecipientAddressResolver;
|
||||
import org.asamk.signal.manager.storage.recipients.RecipientResolver;
|
||||
import org.signal.core.models.ServiceId;
|
||||
import org.signal.libsignal.metadata.ProtocolException;
|
||||
import org.whispersystems.signalservice.api.messages.SignalServiceAttachment;
|
||||
import org.whispersystems.signalservice.api.messages.SignalServiceAttachmentPointer;
|
||||
@ -32,7 +33,6 @@ import org.whispersystems.signalservice.api.messages.multidevice.SentTranscriptM
|
||||
import org.whispersystems.signalservice.api.messages.multidevice.SignalServiceSyncMessage;
|
||||
import org.whispersystems.signalservice.api.messages.multidevice.ViewOnceOpenMessage;
|
||||
import org.whispersystems.signalservice.api.messages.multidevice.ViewedMessage;
|
||||
import org.whispersystems.signalservice.api.push.ServiceId;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
package org.asamk.signal.manager.api;
|
||||
|
||||
import org.whispersystems.signalservice.api.util.UuidUtil;
|
||||
import org.signal.core.util.UuidUtil;
|
||||
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
|
||||
@ -1,9 +1,9 @@
|
||||
package org.asamk.signal.manager.api;
|
||||
|
||||
import org.asamk.signal.manager.util.PhoneNumberFormatter;
|
||||
import org.signal.core.util.UuidUtil;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.whispersystems.signalservice.api.util.UuidUtil;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
@ -24,13 +24,13 @@ public sealed interface RecipientIdentifier {
|
||||
sealed interface Single extends RecipientIdentifier {
|
||||
|
||||
static Single fromString(String identifier, String localNumber) throws InvalidNumberException {
|
||||
if (UuidUtil.isUuid(identifier)) {
|
||||
if (UuidUtil.INSTANCE.isUuid(identifier)) {
|
||||
return new Uuid(UUID.fromString(identifier));
|
||||
}
|
||||
|
||||
if (identifier.startsWith("PNI:")) {
|
||||
final var pni = identifier.substring(4);
|
||||
if (!UuidUtil.isUuid(pni)) {
|
||||
if (!UuidUtil.INSTANCE.isUuid(pni)) {
|
||||
throw new InvalidNumberException("Invalid PNI");
|
||||
}
|
||||
return new Pni(UUID.fromString(pni));
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
package org.asamk.signal.manager.api;
|
||||
|
||||
import org.whispersystems.signalservice.internal.util.Hex;
|
||||
import org.signal.core.util.Hex;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
package org.asamk.signal.manager.api;
|
||||
|
||||
import org.asamk.signal.manager.util.Utils;
|
||||
import org.whispersystems.signalservice.internal.util.Hex;
|
||||
import org.signal.core.util.Hex;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.URI;
|
||||
|
||||
@ -1,8 +1,8 @@
|
||||
package org.asamk.signal.manager.api;
|
||||
|
||||
import org.signal.core.util.Base64;
|
||||
import org.signal.core.util.UuidUtil;
|
||||
import org.whispersystems.signalservice.api.push.UsernameLinkComponents;
|
||||
import org.whispersystems.signalservice.api.util.UuidUtil;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
@ -36,7 +36,7 @@ public final class UsernameLinkUrl {
|
||||
|
||||
final var entropy = Arrays.copyOfRange(allBytes, 0, 32);
|
||||
final var serverId = Arrays.copyOfRange(allBytes, 32, allBytes.length);
|
||||
final var serverIdUuid = UuidUtil.parseOrNull(serverId);
|
||||
final var serverIdUuid = UuidUtil.INSTANCE.parseOrNull(serverId);
|
||||
if (serverIdUuid == null) {
|
||||
throw new InvalidUsernameLinkException("Invalid serverId");
|
||||
}
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
package org.asamk.signal.manager.helper;
|
||||
|
||||
import org.whispersystems.signalservice.api.push.ServiceId.ACI;
|
||||
import org.signal.core.models.ServiceId.ACI;
|
||||
|
||||
public interface AccountFileUpdater {
|
||||
|
||||
|
||||
@ -14,6 +14,8 @@ import org.asamk.signal.manager.storage.SignalAccount;
|
||||
import org.asamk.signal.manager.util.KeyUtils;
|
||||
import org.asamk.signal.manager.util.NumberVerificationUtils;
|
||||
import org.asamk.signal.manager.util.Utils;
|
||||
import org.signal.core.models.ServiceId.ACI;
|
||||
import org.signal.core.models.ServiceId.PNI;
|
||||
import org.signal.core.util.Base64;
|
||||
import org.signal.libsignal.protocol.IdentityKeyPair;
|
||||
import org.signal.libsignal.protocol.InvalidKeyException;
|
||||
@ -28,8 +30,6 @@ import org.slf4j.LoggerFactory;
|
||||
import org.whispersystems.signalservice.api.account.ChangePhoneNumberRequest;
|
||||
import org.whispersystems.signalservice.api.crypto.UntrustedIdentityException;
|
||||
import org.whispersystems.signalservice.api.link.LinkedDeviceVerificationCodeResponse;
|
||||
import org.whispersystems.signalservice.api.push.ServiceId.ACI;
|
||||
import org.whispersystems.signalservice.api.push.ServiceId.PNI;
|
||||
import org.whispersystems.signalservice.api.push.ServiceIdType;
|
||||
import org.whispersystems.signalservice.api.push.SignalServiceAddress;
|
||||
import org.whispersystems.signalservice.api.push.SignedPreKeyEntity;
|
||||
@ -82,16 +82,9 @@ public class AccountHelper {
|
||||
}
|
||||
|
||||
public void checkAccountState() throws IOException {
|
||||
if (account.getLastReceiveTimestamp() == 0) {
|
||||
logger.info("The Signal protocol expects that incoming messages are regularly received.");
|
||||
} else {
|
||||
var diffInMilliseconds = System.currentTimeMillis() - account.getLastReceiveTimestamp();
|
||||
long days = TimeUnit.DAYS.convert(diffInMilliseconds, TimeUnit.MILLISECONDS);
|
||||
if (days > 7) {
|
||||
logger.warn(
|
||||
"Messages have been last received {} days ago. The Signal protocol expects that incoming messages are regularly received.",
|
||||
days);
|
||||
}
|
||||
if (account.getAci() == null) {
|
||||
account.setRegistered(false);
|
||||
throw new IOException("Account without ACI");
|
||||
}
|
||||
try {
|
||||
updateAccountAttributes();
|
||||
@ -100,7 +93,7 @@ public class AccountHelper {
|
||||
} else {
|
||||
context.getPreKeyHelper().refreshPreKeysIfNecessary();
|
||||
}
|
||||
if (account.getAci() == null || account.getPni() == null) {
|
||||
if (account.getPni() == null) {
|
||||
checkWhoAmiI();
|
||||
}
|
||||
if (!account.isPrimaryDevice() && account.getPniIdentityKeyPair() == null) {
|
||||
@ -125,6 +118,17 @@ public class AccountHelper {
|
||||
account.setRegistered(false);
|
||||
throw e;
|
||||
}
|
||||
if (account.getLastReceiveTimestamp() == 0) {
|
||||
logger.info("The Signal protocol expects that incoming messages are regularly received.");
|
||||
} else {
|
||||
var diffInMilliseconds = System.currentTimeMillis() - account.getLastReceiveTimestamp();
|
||||
long days = TimeUnit.DAYS.convert(diffInMilliseconds, TimeUnit.MILLISECONDS);
|
||||
if (days > 7) {
|
||||
logger.warn(
|
||||
"Messages have been last received {} days ago. The Signal protocol expects that incoming messages are regularly received.",
|
||||
days);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void checkWhoAmiI() throws IOException {
|
||||
@ -311,6 +315,7 @@ public class AccountHelper {
|
||||
Utils.mapKeys(pniRegistrationIds, Object::toString))));
|
||||
});
|
||||
|
||||
account.clearSessionId();
|
||||
final var updatePni = PNI.parseOrThrow(result.first().getPni());
|
||||
if (updatePni.equals(account.getPni())) {
|
||||
logger.debug("PNI is unchanged after change number");
|
||||
@ -517,6 +522,22 @@ public class AccountHelper {
|
||||
account.setEncryptedDeviceName(encryptedDeviceName);
|
||||
}
|
||||
|
||||
public void setDeviceName(int deviceId, String deviceName) throws IOException {
|
||||
final var privateKey = account.getAciIdentityKeyPair().getPrivateKey();
|
||||
final var encryptedDeviceName = DeviceNameUtil.encryptDeviceName(deviceName, privateKey);
|
||||
handleResponseException(dependencies.getLinkDeviceApi().setDeviceName(encryptedDeviceName, deviceId));
|
||||
context.getSyncHelper().sendDeviceNameChange(deviceId);
|
||||
}
|
||||
|
||||
public void refreshDeviceName() throws IOException {
|
||||
final var devices = handleResponseException(dependencies.getLinkDeviceApi().getDevices());
|
||||
final var deviceId = account.getDeviceId();
|
||||
final var device = devices.stream().filter(d -> d.id == deviceId).findFirst();
|
||||
if (device.isPresent()) {
|
||||
account.setEncryptedDeviceName(device.get().name);
|
||||
}
|
||||
}
|
||||
|
||||
public void updateAccountAttributes() throws IOException {
|
||||
handleResponseException(dependencies.getAccountApi().setAccountAttributes(account.getAccountAttributes(null)));
|
||||
}
|
||||
|
||||
@ -28,15 +28,16 @@ import org.asamk.signal.manager.storage.recipients.RecipientId;
|
||||
import org.asamk.signal.manager.util.AttachmentUtils;
|
||||
import org.asamk.signal.manager.util.IOUtils;
|
||||
import org.asamk.signal.manager.util.Utils;
|
||||
import org.signal.core.models.ServiceId;
|
||||
import org.signal.libsignal.zkgroup.InvalidInputException;
|
||||
import org.signal.libsignal.zkgroup.groups.GroupMasterKey;
|
||||
import org.signal.libsignal.zkgroup.groups.GroupSecretParams;
|
||||
import org.signal.libsignal.zkgroup.groupsend.GroupSendEndorsementsResponse;
|
||||
import org.signal.libsignal.zkgroup.profiles.ProfileKey;
|
||||
import org.signal.storageservice.protos.groups.GroupChangeResponse;
|
||||
import org.signal.storageservice.protos.groups.local.DecryptedGroup;
|
||||
import org.signal.storageservice.protos.groups.local.DecryptedGroupChange;
|
||||
import org.signal.storageservice.protos.groups.local.DecryptedGroupJoinInfo;
|
||||
import org.signal.storageservice.storage.protos.groups.GroupChangeResponse;
|
||||
import org.signal.storageservice.storage.protos.groups.local.DecryptedGroup;
|
||||
import org.signal.storageservice.storage.protos.groups.local.DecryptedGroupChange;
|
||||
import org.signal.storageservice.storage.protos.groups.local.DecryptedGroupJoinInfo;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.whispersystems.signalservice.api.groupsv2.DecryptedGroupChangeLog;
|
||||
@ -47,7 +48,6 @@ import org.whispersystems.signalservice.api.messages.SignalServiceAttachmentStre
|
||||
import org.whispersystems.signalservice.api.messages.SignalServiceDataMessage;
|
||||
import org.whispersystems.signalservice.api.messages.SignalServiceGroup;
|
||||
import org.whispersystems.signalservice.api.messages.SignalServiceGroupV2;
|
||||
import org.whispersystems.signalservice.api.push.ServiceId;
|
||||
import org.whispersystems.signalservice.api.push.exceptions.ConflictException;
|
||||
|
||||
import java.io.IOException;
|
||||
@ -192,9 +192,9 @@ public class GroupHelper {
|
||||
final GroupInfoV2 groupInfoV2,
|
||||
final GroupChangeResponse groupChangeResponse
|
||||
) {
|
||||
if (groupChangeResponse.groupSendEndorsementsResponse.size() > 0) {
|
||||
if (groupChangeResponse.group_send_endorsements_response.size() > 0) {
|
||||
try {
|
||||
final var groupSendEndorsementsResponse = new GroupSendEndorsementsResponse(groupChangeResponse.groupSendEndorsementsResponse.toByteArray());
|
||||
final var groupSendEndorsementsResponse = new GroupSendEndorsementsResponse(groupChangeResponse.group_send_endorsements_response.toByteArray());
|
||||
|
||||
updateGroupEndorsements(groupInfoV2.getGroupId(),
|
||||
groupInfoV2.getMasterKey(),
|
||||
@ -391,7 +391,7 @@ public class GroupHelper {
|
||||
.joinGroup(inviteLinkUrl.getGroupMasterKey(), inviteLinkUrl.getPassword(), groupJoinInfo);
|
||||
final var group = getOrMigrateGroup(inviteLinkUrl.getGroupMasterKey(),
|
||||
groupJoinInfo.revision + 1,
|
||||
changeResponse.groupChange == null ? null : changeResponse.groupChange.encode());
|
||||
changeResponse.group_change == null ? null : changeResponse.group_change.encode());
|
||||
|
||||
if (group.getGroup() == null) {
|
||||
// Only requested member, can't send update to group members
|
||||
@ -873,10 +873,10 @@ public class GroupHelper {
|
||||
|
||||
final var groupChangeResponse = groupGroupChangePair.second();
|
||||
handleGroupChangeResponse(groupInfoV2, groupChangeResponse);
|
||||
if (groupChangeResponse.groupChange == null) {
|
||||
if (groupChangeResponse.group_change == null) {
|
||||
throw new AssertionError("groupChange is null");
|
||||
}
|
||||
var messageBuilder = getGroupUpdateMessageBuilder(groupInfoV2, groupChangeResponse.groupChange.encode());
|
||||
var messageBuilder = getGroupUpdateMessageBuilder(groupInfoV2, groupChangeResponse.group_change.encode());
|
||||
return sendGroupMessage(messageBuilder,
|
||||
groupInfoV2.getMembersIncludingPendingWithout(account.getSelfRecipientId()),
|
||||
groupInfoV2);
|
||||
@ -924,10 +924,10 @@ public class GroupHelper {
|
||||
members.addAll(group.getMembersIncludingPendingWithout(selfRecipientId));
|
||||
account.getGroupStore().updateGroup(group);
|
||||
|
||||
if (groupChangeResponse.groupChange == null) {
|
||||
if (groupChangeResponse.group_change == null) {
|
||||
throw new AssertionError("groupChange is null");
|
||||
}
|
||||
final var messageBuilder = getGroupUpdateMessageBuilder(group, groupChangeResponse.groupChange.encode());
|
||||
final var messageBuilder = getGroupUpdateMessageBuilder(group, groupChangeResponse.group_change.encode());
|
||||
return sendGroupMessage(messageBuilder, members, group);
|
||||
}
|
||||
|
||||
|
||||
@ -10,6 +10,10 @@ import org.asamk.signal.manager.internal.SignalDependencies;
|
||||
import org.asamk.signal.manager.storage.groups.GroupInfoV2;
|
||||
import org.asamk.signal.manager.storage.recipients.RecipientId;
|
||||
import org.asamk.signal.manager.util.Utils;
|
||||
import org.signal.core.models.ServiceId;
|
||||
import org.signal.core.models.ServiceId.ACI;
|
||||
import org.signal.core.models.ServiceId.PNI;
|
||||
import org.signal.core.util.UuidUtil;
|
||||
import org.signal.libsignal.zkgroup.InvalidInputException;
|
||||
import org.signal.libsignal.zkgroup.VerificationFailedException;
|
||||
import org.signal.libsignal.zkgroup.auth.AuthCredentialWithPniResponse;
|
||||
@ -17,15 +21,15 @@ import org.signal.libsignal.zkgroup.groups.GroupMasterKey;
|
||||
import org.signal.libsignal.zkgroup.groups.GroupSecretParams;
|
||||
import org.signal.libsignal.zkgroup.groups.UuidCiphertext;
|
||||
import org.signal.libsignal.zkgroup.profiles.ProfileKey;
|
||||
import org.signal.storageservice.protos.groups.AccessControl;
|
||||
import org.signal.storageservice.protos.groups.GroupChange;
|
||||
import org.signal.storageservice.protos.groups.GroupChangeResponse;
|
||||
import org.signal.storageservice.protos.groups.Member;
|
||||
import org.signal.storageservice.protos.groups.local.DecryptedGroup;
|
||||
import org.signal.storageservice.protos.groups.local.DecryptedGroupChange;
|
||||
import org.signal.storageservice.protos.groups.local.DecryptedGroupJoinInfo;
|
||||
import org.signal.storageservice.protos.groups.local.DecryptedMember;
|
||||
import org.signal.storageservice.protos.groups.local.DecryptedPendingMember;
|
||||
import org.signal.storageservice.storage.protos.groups.AccessControl;
|
||||
import org.signal.storageservice.storage.protos.groups.GroupChange;
|
||||
import org.signal.storageservice.storage.protos.groups.GroupChangeResponse;
|
||||
import org.signal.storageservice.storage.protos.groups.Member;
|
||||
import org.signal.storageservice.storage.protos.groups.local.DecryptedGroup;
|
||||
import org.signal.storageservice.storage.protos.groups.local.DecryptedGroupChange;
|
||||
import org.signal.storageservice.storage.protos.groups.local.DecryptedGroupJoinInfo;
|
||||
import org.signal.storageservice.storage.protos.groups.local.DecryptedMember;
|
||||
import org.signal.storageservice.storage.protos.groups.local.DecryptedPendingMember;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.whispersystems.signalservice.api.groupsv2.DecryptChangeVerificationMode;
|
||||
@ -38,12 +42,8 @@ import org.whispersystems.signalservice.api.groupsv2.GroupsV2AuthorizationString
|
||||
import org.whispersystems.signalservice.api.groupsv2.GroupsV2Operations;
|
||||
import org.whispersystems.signalservice.api.groupsv2.InvalidGroupStateException;
|
||||
import org.whispersystems.signalservice.api.groupsv2.NotAbleToApplyGroupV2ChangeException;
|
||||
import org.whispersystems.signalservice.api.push.ServiceId;
|
||||
import org.whispersystems.signalservice.api.push.ServiceId.ACI;
|
||||
import org.whispersystems.signalservice.api.push.ServiceId.PNI;
|
||||
import org.whispersystems.signalservice.api.push.SignalServiceAddress;
|
||||
import org.whispersystems.signalservice.api.push.exceptions.NonSuccessfulResponseCodeException;
|
||||
import org.whispersystems.signalservice.api.util.UuidUtil;
|
||||
import org.whispersystems.signalservice.internal.push.exceptions.NotInGroupException;
|
||||
|
||||
import java.io.IOException;
|
||||
@ -225,7 +225,7 @@ class GroupV2Helper {
|
||||
change.modifyAvatar(new GroupChange.Actions.ModifyAvatarAction.Builder().avatar(avatarCdnKey).build());
|
||||
}
|
||||
|
||||
change.sourceServiceId(getSelfAci().toByteString());
|
||||
change.sourceUserId(getSelfAci().toByteString());
|
||||
|
||||
return commitChange(groupInfoV2, change);
|
||||
}
|
||||
@ -252,7 +252,7 @@ class GroupV2Helper {
|
||||
final var aci = getSelfAci();
|
||||
final var change = groupOperations.createModifyGroupMembershipChange(candidates, bannedUuids, aci);
|
||||
|
||||
change.sourceServiceId(getSelfAci().toByteString());
|
||||
change.sourceUserId(getSelfAci().toByteString());
|
||||
|
||||
return commitChange(groupInfoV2, change);
|
||||
}
|
||||
@ -343,7 +343,7 @@ class GroupV2Helper {
|
||||
false,
|
||||
groupInfoV2.getGroup().bannedMembers);
|
||||
|
||||
change.sourceServiceId(getSelfAci().toByteString());
|
||||
change.sourceUserId(getSelfAci().toByteString());
|
||||
|
||||
return commitChange(groupInfoV2, change);
|
||||
}
|
||||
@ -360,7 +360,7 @@ class GroupV2Helper {
|
||||
|
||||
final var change = groupOperations.createUnbanServiceIdsChange(serviceIds);
|
||||
|
||||
change.sourceServiceId(getSelfAci().toByteString());
|
||||
change.sourceUserId(getSelfAci().toByteString());
|
||||
|
||||
return commitChange(groupInfoV2, change);
|
||||
}
|
||||
@ -436,7 +436,7 @@ class GroupV2Helper {
|
||||
|
||||
final GroupsV2Operations.GroupOperations groupOperations = getGroupOperations(groupInfoV2);
|
||||
final var change = groupOperations.createUpdateProfileKeyCredentialChange(profileKeyCredential);
|
||||
change.sourceServiceId(getSelfAci().toByteString());
|
||||
change.sourceUserId(getSelfAci().toByteString());
|
||||
return commitChange(groupInfoV2, change);
|
||||
}
|
||||
|
||||
@ -459,7 +459,7 @@ class GroupV2Helper {
|
||||
? groupOperations.createGroupJoinRequest(profileKeyCredential)
|
||||
: groupOperations.createGroupJoinDirect(profileKeyCredential);
|
||||
|
||||
change.sourceServiceId(context.getRecipientHelper()
|
||||
change.sourceUserId(context.getRecipientHelper()
|
||||
.resolveSignalServiceAddress(selfRecipientId)
|
||||
.getServiceId()
|
||||
.toByteString());
|
||||
@ -479,7 +479,7 @@ class GroupV2Helper {
|
||||
final var change = groupOperations.createAcceptInviteChange(profileKeyCredential);
|
||||
|
||||
final var aci = context.getRecipientHelper().resolveSignalServiceAddress(selfRecipientId).getServiceId();
|
||||
change.sourceServiceId(aci.toByteString());
|
||||
change.sourceUserId(aci.toByteString());
|
||||
|
||||
return commitChange(groupInfoV2, change);
|
||||
}
|
||||
@ -585,7 +585,7 @@ class GroupV2Helper {
|
||||
final var groupOperations = dependencies.getGroupsV2Operations().forGroup(groupSecretParams);
|
||||
final var previousGroupState = groupInfoV2.getGroup();
|
||||
final var nextRevision = previousGroupState.revision + 1;
|
||||
final var changeActions = change.revision(nextRevision).build();
|
||||
final var changeActions = change.version(nextRevision).build();
|
||||
final DecryptedGroupChange decryptedChange;
|
||||
final DecryptedGroup decryptedGroupState;
|
||||
|
||||
@ -611,7 +611,7 @@ class GroupV2Helper {
|
||||
GroupLinkPassword password
|
||||
) throws IOException {
|
||||
final var nextRevision = currentRevision + 1;
|
||||
final var changeActions = change.revision(nextRevision).build();
|
||||
final var changeActions = change.version(nextRevision).build();
|
||||
|
||||
return dependencies.getGroupsV2Api()
|
||||
.patchGroup(changeActions,
|
||||
@ -621,6 +621,9 @@ class GroupV2Helper {
|
||||
|
||||
Pair<ServiceId, ProfileKey> getAuthoritativeProfileKeyFromChange(final DecryptedGroupChange change) {
|
||||
UUID editor = UuidUtil.fromByteStringOrNull(change.editorServiceIdBytes);
|
||||
if (editor == null) {
|
||||
return null;
|
||||
}
|
||||
final var editorProfileKeyBytes = Stream.concat(Stream.of(change.newMembers.stream(),
|
||||
change.promotePendingMembers.stream(),
|
||||
change.modifiedProfileKeys.stream())
|
||||
|
||||
@ -4,6 +4,7 @@ import org.asamk.signal.manager.api.TrustLevel;
|
||||
import org.asamk.signal.manager.storage.SignalAccount;
|
||||
import org.asamk.signal.manager.storage.recipients.RecipientId;
|
||||
import org.asamk.signal.manager.util.Utils;
|
||||
import org.signal.core.models.ServiceId;
|
||||
import org.signal.libsignal.protocol.IdentityKey;
|
||||
import org.signal.libsignal.protocol.fingerprint.Fingerprint;
|
||||
import org.signal.libsignal.protocol.fingerprint.FingerprintParsingException;
|
||||
@ -12,7 +13,6 @@ import org.signal.libsignal.protocol.fingerprint.ScannableFingerprint;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.whispersystems.signalservice.api.messages.SendMessageResult;
|
||||
import org.whispersystems.signalservice.api.push.ServiceId;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.function.BiFunction;
|
||||
|
||||
@ -5,6 +5,7 @@ import org.asamk.signal.manager.actions.HandleAction;
|
||||
import org.asamk.signal.manager.actions.RefreshPreKeysAction;
|
||||
import org.asamk.signal.manager.actions.RenewSessionAction;
|
||||
import org.asamk.signal.manager.actions.ResendMessageAction;
|
||||
import org.asamk.signal.manager.actions.RetrieveDeviceNameAction;
|
||||
import org.asamk.signal.manager.actions.RetrieveProfileAction;
|
||||
import org.asamk.signal.manager.actions.SendGroupInfoAction;
|
||||
import org.asamk.signal.manager.actions.SendGroupInfoRequestAction;
|
||||
@ -34,6 +35,8 @@ import org.asamk.signal.manager.storage.groups.GroupInfoV1;
|
||||
import org.asamk.signal.manager.storage.recipients.RecipientAddress;
|
||||
import org.asamk.signal.manager.storage.recipients.RecipientId;
|
||||
import org.asamk.signal.manager.storage.stickers.StickerPack;
|
||||
import org.signal.core.models.ServiceId;
|
||||
import org.signal.core.models.ServiceId.ACI;
|
||||
import org.signal.libsignal.metadata.ProtocolInvalidKeyException;
|
||||
import org.signal.libsignal.metadata.ProtocolInvalidKeyIdException;
|
||||
import org.signal.libsignal.metadata.ProtocolInvalidMessageException;
|
||||
@ -62,8 +65,6 @@ import org.whispersystems.signalservice.api.messages.SignalServiceReceiptMessage
|
||||
import org.whispersystems.signalservice.api.messages.SignalServiceStoryMessage;
|
||||
import org.whispersystems.signalservice.api.messages.multidevice.SignalServiceSyncMessage;
|
||||
import org.whispersystems.signalservice.api.messages.multidevice.StickerPackOperationMessage;
|
||||
import org.whispersystems.signalservice.api.push.ServiceId;
|
||||
import org.whispersystems.signalservice.api.push.ServiceId.ACI;
|
||||
import org.whispersystems.signalservice.api.push.ServiceIdType;
|
||||
import org.whispersystems.signalservice.api.push.SignalServiceAddress;
|
||||
import org.whispersystems.signalservice.internal.push.Envelope;
|
||||
@ -633,6 +634,12 @@ public final class IncomingMessageHandler {
|
||||
context.getAccountHelper().handlePniChangeNumberMessage(pniChangeNumber, updatedPni);
|
||||
}
|
||||
}
|
||||
if (syncMessage.getDeviceNameChange().isPresent()) {
|
||||
final var deviceNameChange = syncMessage.getDeviceNameChange().get();
|
||||
if (deviceNameChange.deviceId != null && deviceNameChange.deviceId == account.getDeviceId()) {
|
||||
actions.add(RetrieveDeviceNameAction.create());
|
||||
}
|
||||
}
|
||||
return actions;
|
||||
}
|
||||
|
||||
|
||||
@ -1,9 +1,9 @@
|
||||
package org.asamk.signal.manager.helper;
|
||||
|
||||
import org.asamk.signal.manager.api.IncorrectPinException;
|
||||
import org.signal.core.models.MasterKey;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.whispersystems.signalservice.api.kbs.MasterKey;
|
||||
import org.whispersystems.signalservice.api.svr.SecureValueRecovery;
|
||||
import org.whispersystems.signalservice.internal.push.AuthCredentials;
|
||||
import org.whispersystems.signalservice.internal.push.LockedException;
|
||||
|
||||
@ -9,11 +9,11 @@ import org.asamk.signal.manager.jobs.CleanOldPreKeysJob;
|
||||
import org.asamk.signal.manager.storage.SignalAccount;
|
||||
import org.asamk.signal.manager.storage.messageCache.CachedMessage;
|
||||
import org.asamk.signal.manager.storage.recipients.RecipientAddress;
|
||||
import org.signal.core.models.ServiceId;
|
||||
import org.signal.core.models.ServiceId.ACI;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.whispersystems.signalservice.api.messages.SignalServiceEnvelope;
|
||||
import org.whispersystems.signalservice.api.push.ServiceId;
|
||||
import org.whispersystems.signalservice.api.push.ServiceId.ACI;
|
||||
import org.whispersystems.signalservice.api.websocket.SignalWebSocket;
|
||||
import org.whispersystems.signalservice.api.websocket.WebSocketConnectionState;
|
||||
import org.whispersystems.signalservice.api.websocket.WebSocketUnavailableException;
|
||||
|
||||
@ -6,14 +6,14 @@ import org.asamk.signal.manager.api.UsernameLinkUrl;
|
||||
import org.asamk.signal.manager.internal.SignalDependencies;
|
||||
import org.asamk.signal.manager.storage.SignalAccount;
|
||||
import org.asamk.signal.manager.storage.recipients.RecipientId;
|
||||
import org.signal.core.models.ServiceId;
|
||||
import org.signal.core.models.ServiceId.ACI;
|
||||
import org.signal.core.models.ServiceId.PNI;
|
||||
import org.signal.libsignal.usernames.BaseUsernameException;
|
||||
import org.signal.libsignal.usernames.Username;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.whispersystems.signalservice.api.cds.CdsiV2Service;
|
||||
import org.whispersystems.signalservice.api.push.ServiceId;
|
||||
import org.whispersystems.signalservice.api.push.ServiceId.ACI;
|
||||
import org.whispersystems.signalservice.api.push.ServiceId.PNI;
|
||||
import org.whispersystems.signalservice.api.push.SignalServiceAddress;
|
||||
import org.whispersystems.signalservice.api.push.exceptions.CdsiInvalidArgumentException;
|
||||
import org.whispersystems.signalservice.api.push.exceptions.CdsiInvalidTokenException;
|
||||
|
||||
@ -15,6 +15,7 @@ import org.asamk.signal.manager.storage.groups.GroupInfo;
|
||||
import org.asamk.signal.manager.storage.groups.GroupInfoV2;
|
||||
import org.asamk.signal.manager.storage.recipients.RecipientId;
|
||||
import org.asamk.signal.manager.storage.sendLog.MessageSendLogEntry;
|
||||
import org.signal.core.models.ServiceId.ACI;
|
||||
import org.signal.libsignal.protocol.InvalidKeyException;
|
||||
import org.signal.libsignal.protocol.InvalidRegistrationIdException;
|
||||
import org.signal.libsignal.protocol.NoSessionException;
|
||||
@ -38,7 +39,6 @@ import org.whispersystems.signalservice.api.messages.SignalServiceTypingMessage;
|
||||
import org.whispersystems.signalservice.api.messages.multidevice.SentTranscriptMessage;
|
||||
import org.whispersystems.signalservice.api.messages.multidevice.SignalServiceSyncMessage;
|
||||
import org.whispersystems.signalservice.api.push.DistributionId;
|
||||
import org.whispersystems.signalservice.api.push.ServiceId.ACI;
|
||||
import org.whispersystems.signalservice.api.push.SignalServiceAddress;
|
||||
import org.whispersystems.signalservice.api.push.exceptions.NotFoundException;
|
||||
import org.whispersystems.signalservice.api.push.exceptions.ProofRequiredException;
|
||||
|
||||
@ -7,10 +7,10 @@ import org.asamk.signal.manager.storage.SignalAccount;
|
||||
import org.asamk.signal.manager.storage.stickerPacks.JsonStickerPack;
|
||||
import org.asamk.signal.manager.storage.stickers.StickerPack;
|
||||
import org.asamk.signal.manager.util.IOUtils;
|
||||
import org.signal.core.util.Hex;
|
||||
import org.signal.libsignal.protocol.InvalidMessageException;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.whispersystems.signalservice.internal.util.Hex;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.HashSet;
|
||||
|
||||
@ -14,6 +14,7 @@ import org.asamk.signal.manager.syncStorage.StorageSyncModels;
|
||||
import org.asamk.signal.manager.syncStorage.StorageSyncValidations;
|
||||
import org.asamk.signal.manager.syncStorage.WriteOperationResult;
|
||||
import org.asamk.signal.manager.util.KeyUtils;
|
||||
import org.signal.core.models.storageservice.StorageKey;
|
||||
import org.signal.core.util.SetUtil;
|
||||
import org.signal.libsignal.protocol.InvalidKeyException;
|
||||
import org.slf4j.Logger;
|
||||
@ -23,7 +24,6 @@ import org.whispersystems.signalservice.api.storage.RecordIkm;
|
||||
import org.whispersystems.signalservice.api.storage.SignalStorageManifest;
|
||||
import org.whispersystems.signalservice.api.storage.SignalStorageRecord;
|
||||
import org.whispersystems.signalservice.api.storage.StorageId;
|
||||
import org.whispersystems.signalservice.api.storage.StorageKey;
|
||||
import org.whispersystems.signalservice.api.storage.StorageRecordConvertersKt;
|
||||
import org.whispersystems.signalservice.api.storage.StorageServiceRepository;
|
||||
import org.whispersystems.signalservice.api.storage.StorageServiceRepository.ManifestIfDifferentVersionResult;
|
||||
|
||||
@ -12,6 +12,7 @@ import org.asamk.signal.manager.storage.stickers.StickerPack;
|
||||
import org.asamk.signal.manager.util.IOUtils;
|
||||
import org.asamk.signal.manager.util.MimeUtils;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.signal.core.models.ServiceId;
|
||||
import org.signal.libsignal.protocol.IdentityKey;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
@ -36,7 +37,6 @@ import org.whispersystems.signalservice.api.messages.multidevice.SignalServiceSy
|
||||
import org.whispersystems.signalservice.api.messages.multidevice.StickerPackOperationMessage;
|
||||
import org.whispersystems.signalservice.api.messages.multidevice.VerifiedMessage;
|
||||
import org.whispersystems.signalservice.api.messages.multidevice.ViewedMessage;
|
||||
import org.whispersystems.signalservice.api.push.ServiceId;
|
||||
import org.whispersystems.signalservice.api.push.SignalServiceAddress;
|
||||
import org.whispersystems.signalservice.internal.push.SyncMessage;
|
||||
|
||||
@ -52,6 +52,8 @@ import java.util.Optional;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import okio.ByteString;
|
||||
|
||||
public class SyncHelper {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(SyncHelper.class);
|
||||
@ -406,6 +408,11 @@ public class SyncHelper {
|
||||
return context.getSendHelper().sendSyncMessage(SignalServiceSyncMessage.forMessageRequestResponse(response));
|
||||
}
|
||||
|
||||
public SendMessageResult sendDeviceNameChange(final int deviceId) {
|
||||
final var deviceNameChange = new SyncMessage.DeviceNameChange(deviceId, ByteString.EMPTY);
|
||||
return context.getSendHelper().sendSyncMessage(SignalServiceSyncMessage.forDeviceNameChange(deviceNameChange));
|
||||
}
|
||||
|
||||
private SendMessageResult requestSyncData(final SyncMessage.Request.Type type) {
|
||||
var r = new SyncMessage.Request.Builder().type(type).build();
|
||||
var message = SignalServiceSyncMessage.forRequest(new RequestMessage(r));
|
||||
|
||||
@ -2,7 +2,7 @@ package org.asamk.signal.manager.internal;
|
||||
|
||||
import org.asamk.signal.manager.helper.AccountFileUpdater;
|
||||
import org.asamk.signal.manager.storage.accounts.AccountsStore;
|
||||
import org.whispersystems.signalservice.api.push.ServiceId.ACI;
|
||||
import org.signal.core.models.ServiceId.ACI;
|
||||
|
||||
public class AccountFileUpdaterImpl implements AccountFileUpdater {
|
||||
|
||||
|
||||
@ -20,7 +20,7 @@ public class JobExecutor implements AutoCloseable {
|
||||
|
||||
public JobExecutor(final Context context) {
|
||||
this.context = context;
|
||||
this.executorService = Executors.newCachedThreadPool();
|
||||
this.executorService = Executors.newVirtualThreadPerTaskExecutor();
|
||||
}
|
||||
|
||||
public void enqueueJob(Job job) {
|
||||
|
||||
@ -91,7 +91,11 @@ import org.asamk.signal.manager.util.KeyUtils;
|
||||
import org.asamk.signal.manager.util.MimeUtils;
|
||||
import org.asamk.signal.manager.util.PhoneNumberFormatter;
|
||||
import org.asamk.signal.manager.util.StickerUtils;
|
||||
import org.signal.core.models.ServiceId;
|
||||
import org.signal.core.models.ServiceId.ACI;
|
||||
import org.signal.core.models.ServiceId.PNI;
|
||||
import org.signal.core.util.Base64;
|
||||
import org.signal.core.util.Hex;
|
||||
import org.signal.libsignal.protocol.InvalidMessageException;
|
||||
import org.signal.libsignal.usernames.BaseUsernameException;
|
||||
import org.slf4j.Logger;
|
||||
@ -102,16 +106,12 @@ import org.whispersystems.signalservice.api.messages.SignalServicePreview;
|
||||
import org.whispersystems.signalservice.api.messages.SignalServiceReceiptMessage;
|
||||
import org.whispersystems.signalservice.api.messages.SignalServiceTypingMessage;
|
||||
import org.whispersystems.signalservice.api.messages.multidevice.DeviceInfo;
|
||||
import org.whispersystems.signalservice.api.push.ServiceId;
|
||||
import org.whispersystems.signalservice.api.push.ServiceId.ACI;
|
||||
import org.whispersystems.signalservice.api.push.ServiceId.PNI;
|
||||
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.util.DeviceNameUtil;
|
||||
import org.whispersystems.signalservice.api.util.StreamDetails;
|
||||
import org.whispersystems.signalservice.internal.util.Hex;
|
||||
import org.whispersystems.signalservice.internal.util.Util;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
@ -157,7 +157,7 @@ public class ManagerImpl implements Manager {
|
||||
private final SignalDependencies dependencies;
|
||||
private final Context context;
|
||||
|
||||
private final ExecutorService executor = Executors.newCachedThreadPool();
|
||||
private final ExecutorService executor = Executors.newVirtualThreadPerTaskExecutor();
|
||||
|
||||
private Thread receiveThread;
|
||||
private boolean isReceivingSynchronous;
|
||||
@ -487,6 +487,21 @@ public class ManagerImpl implements Manager {
|
||||
}).toList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateLinkedDevice(
|
||||
final int deviceId,
|
||||
final String name
|
||||
) throws IOException, NotPrimaryDeviceException {
|
||||
if (deviceId == account.getDeviceId()) {
|
||||
context.getAccountHelper().setDeviceName(name);
|
||||
} else {
|
||||
if (!account.isPrimaryDevice()) {
|
||||
throw new NotPrimaryDeviceException();
|
||||
}
|
||||
context.getAccountHelper().setDeviceName(deviceId, name);
|
||||
}
|
||||
}
|
||||
|
||||
private Long getPlaintextCreatedAt(DeviceInfo d) {
|
||||
final var DECRYPTION_INFO = "deviceCreatedAt";
|
||||
var identityKey = account.getAciIdentityKeyPair().getPrivateKey();
|
||||
@ -1138,10 +1153,7 @@ public class ManagerImpl implements Manager {
|
||||
final String nickGivenName,
|
||||
final String nickFamilyName,
|
||||
final String note
|
||||
) throws NotPrimaryDeviceException, UnregisteredRecipientException {
|
||||
if (!account.isPrimaryDevice()) {
|
||||
throw new NotPrimaryDeviceException();
|
||||
}
|
||||
) throws UnregisteredRecipientException {
|
||||
context.getContactHelper()
|
||||
.setContactName(context.getRecipientHelper().resolveRecipient(recipient),
|
||||
givenName,
|
||||
|
||||
@ -33,14 +33,14 @@ import org.asamk.signal.manager.helper.PinHelper;
|
||||
import org.asamk.signal.manager.storage.SignalAccount;
|
||||
import org.asamk.signal.manager.util.KeyUtils;
|
||||
import org.asamk.signal.manager.util.NumberVerificationUtils;
|
||||
import org.signal.core.models.MasterKey;
|
||||
import org.signal.core.models.ServiceId.ACI;
|
||||
import org.signal.core.models.ServiceId.PNI;
|
||||
import org.signal.libsignal.usernames.BaseUsernameException;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.whispersystems.signalservice.api.SignalServiceAccountManager;
|
||||
import org.whispersystems.signalservice.api.account.PreKeyCollection;
|
||||
import org.whispersystems.signalservice.api.kbs.MasterKey;
|
||||
import org.whispersystems.signalservice.api.push.ServiceId.ACI;
|
||||
import org.whispersystems.signalservice.api.push.ServiceId.PNI;
|
||||
import org.whispersystems.signalservice.api.push.ServiceIdType;
|
||||
import org.whispersystems.signalservice.api.push.SignalServiceAddress;
|
||||
import org.whispersystems.signalservice.api.push.exceptions.AlreadyVerifiedException;
|
||||
|
||||
@ -2,10 +2,10 @@ package org.asamk.signal.manager.jobs;
|
||||
|
||||
import org.asamk.signal.manager.api.StickerPackId;
|
||||
import org.asamk.signal.manager.helper.Context;
|
||||
import org.signal.core.util.Hex;
|
||||
import org.signal.libsignal.protocol.InvalidMessageException;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.whispersystems.signalservice.internal.util.Hex;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
|
||||
@ -16,11 +16,11 @@ import org.asamk.signal.manager.storage.senderKeys.SenderKeyRecordStore;
|
||||
import org.asamk.signal.manager.storage.senderKeys.SenderKeySharedStore;
|
||||
import org.asamk.signal.manager.storage.sessions.SessionStore;
|
||||
import org.asamk.signal.manager.storage.stickers.StickerStore;
|
||||
import org.signal.core.models.ServiceId;
|
||||
import org.signal.core.models.ServiceId.ACI;
|
||||
import org.signal.core.util.UuidUtil;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.whispersystems.signalservice.api.push.ServiceId;
|
||||
import org.whispersystems.signalservice.api.push.ServiceId.ACI;
|
||||
import org.whispersystems.signalservice.api.util.UuidUtil;
|
||||
|
||||
import java.io.File;
|
||||
import java.sql.Connection;
|
||||
@ -646,9 +646,10 @@ public class AccountDatabase extends Database {
|
||||
try (final var preparedStatement = connection.prepareStatement(sql)) {
|
||||
try (var result = Utils.executeQueryForStream(preparedStatement, (resultSet) -> {
|
||||
final var pni = Optional.ofNullable(resultSet.getBytes("pni"))
|
||||
.map(UuidUtil::parseOrNull)
|
||||
.map(UuidUtil.INSTANCE::parseOrNull)
|
||||
.map(ServiceId.PNI::from);
|
||||
final var serviceIdUuid = Optional.ofNullable(resultSet.getBytes("uuid")).map(UuidUtil::parseOrNull);
|
||||
final var serviceIdUuid = Optional.ofNullable(resultSet.getBytes("uuid"))
|
||||
.map(UuidUtil.INSTANCE::parseOrNull);
|
||||
final var serviceId = serviceIdUuid.isPresent() && pni.isPresent() && serviceIdUuid.get()
|
||||
.equals(pni.get().getRawUuid())
|
||||
? pni.<ServiceId>map(p -> p)
|
||||
|
||||
@ -53,6 +53,14 @@ import org.asamk.signal.manager.storage.stickers.StickerStore;
|
||||
import org.asamk.signal.manager.storage.threads.LegacyJsonThreadStore;
|
||||
import org.asamk.signal.manager.util.IOUtils;
|
||||
import org.asamk.signal.manager.util.KeyUtils;
|
||||
import org.signal.core.models.AccountEntropyPool;
|
||||
import org.signal.core.models.MasterKey;
|
||||
import org.signal.core.models.ServiceId;
|
||||
import org.signal.core.models.ServiceId.ACI;
|
||||
import org.signal.core.models.ServiceId.PNI;
|
||||
import org.signal.core.models.backup.MediaRootBackupKey;
|
||||
import org.signal.core.models.storageservice.StorageKey;
|
||||
import org.signal.core.util.UuidUtil;
|
||||
import org.signal.libsignal.protocol.IdentityKeyPair;
|
||||
import org.signal.libsignal.protocol.InvalidMessageException;
|
||||
import org.signal.libsignal.protocol.SignalProtocolAddress;
|
||||
@ -65,24 +73,16 @@ import org.signal.libsignal.zkgroup.InvalidInputException;
|
||||
import org.signal.libsignal.zkgroup.profiles.ProfileKey;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.whispersystems.signalservice.api.AccountEntropyPool;
|
||||
import org.whispersystems.signalservice.api.SignalServiceAccountDataStore;
|
||||
import org.whispersystems.signalservice.api.SignalServiceDataStore;
|
||||
import org.whispersystems.signalservice.api.account.AccountAttributes;
|
||||
import org.whispersystems.signalservice.api.account.PreKeyCollection;
|
||||
import org.whispersystems.signalservice.api.backup.MediaRootBackupKey;
|
||||
import org.whispersystems.signalservice.api.crypto.UnidentifiedAccess;
|
||||
import org.whispersystems.signalservice.api.kbs.MasterKey;
|
||||
import org.whispersystems.signalservice.api.push.ServiceId;
|
||||
import org.whispersystems.signalservice.api.push.ServiceId.ACI;
|
||||
import org.whispersystems.signalservice.api.push.ServiceId.PNI;
|
||||
import org.whispersystems.signalservice.api.push.ServiceIdType;
|
||||
import org.whispersystems.signalservice.api.push.SignalServiceAddress;
|
||||
import org.whispersystems.signalservice.api.push.UsernameLinkComponents;
|
||||
import org.whispersystems.signalservice.api.storage.SignalStorageManifest;
|
||||
import org.whispersystems.signalservice.api.storage.StorageKey;
|
||||
import org.whispersystems.signalservice.api.util.CredentialsProvider;
|
||||
import org.whispersystems.signalservice.api.util.UuidUtil;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
@ -376,6 +376,7 @@ public class SignalAccount implements Closeable {
|
||||
trustSelfIdentity(ServiceIdType.ACI);
|
||||
trustSelfIdentity(ServiceIdType.PNI);
|
||||
getKeyValueStore().storeEntry(lastRecipientsRefresh, null);
|
||||
clearSessionId();
|
||||
}
|
||||
|
||||
public void initDatabase() {
|
||||
@ -961,7 +962,7 @@ public class SignalAccount implements Closeable {
|
||||
continue;
|
||||
}
|
||||
try {
|
||||
if (UuidUtil.isUuid(thread.id) || thread.id.startsWith("+")) {
|
||||
if (UuidUtil.INSTANCE.isUuid(thread.id) || thread.id.startsWith("+")) {
|
||||
final var recipientId = getRecipientResolver().resolveRecipient(thread.id);
|
||||
var contact = getContactStore().getContact(recipientId);
|
||||
if (contact != null) {
|
||||
@ -1485,6 +1486,12 @@ public class SignalAccount implements Closeable {
|
||||
keyValueStore.storeEntry(verificationSessionId, sessionId);
|
||||
}
|
||||
|
||||
public void clearSessionId() {
|
||||
final var keyValueStore = getKeyValueStore();
|
||||
keyValueStore.storeEntry(verificationSessionNumber, null);
|
||||
keyValueStore.storeEntry(verificationSessionId, null);
|
||||
}
|
||||
|
||||
public void setEncryptedDeviceName(final String encryptedDeviceName) {
|
||||
this.encryptedDeviceName = encryptedDeviceName;
|
||||
save();
|
||||
|
||||
@ -10,11 +10,11 @@ import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.fasterxml.jackson.databind.SerializationFeature;
|
||||
|
||||
import org.asamk.signal.manager.storage.recipients.RecipientAddress;
|
||||
import org.signal.core.models.ServiceId;
|
||||
import org.signal.core.util.UuidUtil;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.whispersystems.signalservice.api.push.ServiceId;
|
||||
import org.whispersystems.signalservice.api.push.ServiceIdType;
|
||||
import org.whispersystems.signalservice.api.util.UuidUtil;
|
||||
|
||||
import java.io.InvalidObjectException;
|
||||
import java.sql.PreparedStatement;
|
||||
@ -57,7 +57,7 @@ public class Utils {
|
||||
}
|
||||
|
||||
public static RecipientAddress getRecipientAddressFromLegacyIdentifier(final String identifier) {
|
||||
if (UuidUtil.isUuid(identifier)) {
|
||||
if (UuidUtil.INSTANCE.isUuid(identifier)) {
|
||||
return new RecipientAddress(ServiceId.parseOrThrow(identifier));
|
||||
} else {
|
||||
return new RecipientAddress(Optional.empty(), Optional.of(identifier));
|
||||
|
||||
@ -8,9 +8,9 @@ import org.asamk.signal.manager.api.ServiceEnvironment;
|
||||
import org.asamk.signal.manager.storage.SignalAccount;
|
||||
import org.asamk.signal.manager.storage.Utils;
|
||||
import org.asamk.signal.manager.util.IOUtils;
|
||||
import org.signal.core.models.ServiceId.ACI;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.whispersystems.signalservice.api.push.ServiceId.ACI;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
|
||||
@ -4,7 +4,7 @@ import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
|
||||
import org.asamk.signal.manager.storage.recipients.RecipientAddress;
|
||||
import org.whispersystems.signalservice.api.push.ServiceId.ACI;
|
||||
import org.signal.core.models.ServiceId.ACI;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
|
||||
@ -6,13 +6,13 @@ import org.asamk.signal.manager.api.GroupPermission;
|
||||
import org.asamk.signal.manager.storage.recipients.RecipientAddress;
|
||||
import org.asamk.signal.manager.storage.recipients.RecipientId;
|
||||
import org.asamk.signal.manager.storage.recipients.RecipientResolver;
|
||||
import org.signal.core.models.ServiceId;
|
||||
import org.signal.libsignal.zkgroup.groups.GroupMasterKey;
|
||||
import org.signal.storageservice.protos.groups.AccessControl;
|
||||
import org.signal.storageservice.protos.groups.Member;
|
||||
import org.signal.storageservice.protos.groups.local.DecryptedGroup;
|
||||
import org.signal.storageservice.protos.groups.local.EnabledState;
|
||||
import org.signal.storageservice.storage.protos.groups.AccessControl;
|
||||
import org.signal.storageservice.storage.protos.groups.Member;
|
||||
import org.signal.storageservice.storage.protos.groups.local.DecryptedGroup;
|
||||
import org.signal.storageservice.storage.protos.groups.local.EnabledState;
|
||||
import org.whispersystems.signalservice.api.push.DistributionId;
|
||||
import org.whispersystems.signalservice.api.push.ServiceId;
|
||||
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@ -11,16 +11,16 @@ import org.asamk.signal.manager.storage.recipients.RecipientId;
|
||||
import org.asamk.signal.manager.storage.recipients.RecipientIdCreator;
|
||||
import org.asamk.signal.manager.storage.recipients.RecipientResolver;
|
||||
import org.asamk.signal.manager.util.KeyUtils;
|
||||
import org.signal.core.util.UuidUtil;
|
||||
import org.signal.libsignal.zkgroup.InvalidInputException;
|
||||
import org.signal.libsignal.zkgroup.groups.GroupMasterKey;
|
||||
import org.signal.libsignal.zkgroup.groups.GroupSecretParams;
|
||||
import org.signal.libsignal.zkgroup.groupsend.GroupSendEndorsement;
|
||||
import org.signal.storageservice.protos.groups.local.DecryptedGroup;
|
||||
import org.signal.storageservice.storage.protos.groups.local.DecryptedGroup;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.whispersystems.signalservice.api.push.DistributionId;
|
||||
import org.whispersystems.signalservice.api.storage.StorageId;
|
||||
import org.whispersystems.signalservice.api.util.UuidUtil;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.sql.Connection;
|
||||
|
||||
@ -12,14 +12,14 @@ import org.asamk.signal.manager.api.GroupIdV1;
|
||||
import org.asamk.signal.manager.api.GroupIdV2;
|
||||
import org.asamk.signal.manager.storage.recipients.RecipientAddress;
|
||||
import org.asamk.signal.manager.storage.recipients.RecipientResolver;
|
||||
import org.signal.core.models.ServiceId;
|
||||
import org.signal.core.util.Hex;
|
||||
import org.signal.libsignal.zkgroup.InvalidInputException;
|
||||
import org.signal.libsignal.zkgroup.groups.GroupMasterKey;
|
||||
import org.signal.storageservice.protos.groups.local.DecryptedGroup;
|
||||
import org.signal.storageservice.storage.protos.groups.local.DecryptedGroup;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.whispersystems.signalservice.api.push.DistributionId;
|
||||
import org.whispersystems.signalservice.api.push.ServiceId;
|
||||
import org.whispersystems.signalservice.internal.util.Hex;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
|
||||
@ -1,8 +1,8 @@
|
||||
package org.asamk.signal.manager.storage.identities;
|
||||
|
||||
import org.asamk.signal.manager.api.TrustLevel;
|
||||
import org.signal.core.models.ServiceId;
|
||||
import org.signal.libsignal.protocol.IdentityKey;
|
||||
import org.whispersystems.signalservice.api.push.ServiceId;
|
||||
|
||||
public class IdentityInfo {
|
||||
|
||||
|
||||
@ -5,13 +5,13 @@ import org.asamk.signal.manager.api.TrustNewIdentity;
|
||||
import org.asamk.signal.manager.storage.Database;
|
||||
import org.asamk.signal.manager.storage.Utils;
|
||||
import org.asamk.signal.manager.storage.recipients.RecipientStore;
|
||||
import org.signal.core.models.ServiceId;
|
||||
import org.signal.libsignal.protocol.IdentityKey;
|
||||
import org.signal.libsignal.protocol.InvalidKeyException;
|
||||
import org.signal.libsignal.protocol.state.IdentityKeyStore.Direction;
|
||||
import org.signal.libsignal.protocol.state.IdentityKeyStore.IdentityChange;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.whispersystems.signalservice.api.push.ServiceId;
|
||||
|
||||
import java.sql.Connection;
|
||||
import java.sql.ResultSet;
|
||||
|
||||
@ -9,9 +9,9 @@ import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
|
||||
|
||||
import org.asamk.signal.manager.storage.recipients.RecipientAddress;
|
||||
import org.signal.core.models.ServiceId;
|
||||
import org.signal.libsignal.zkgroup.InvalidInputException;
|
||||
import org.signal.libsignal.zkgroup.profiles.ProfileKey;
|
||||
import org.whispersystems.signalservice.api.push.ServiceId;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
|
||||
@ -8,13 +8,13 @@ import com.fasterxml.jackson.databind.JsonNode;
|
||||
import org.asamk.signal.manager.api.TrustLevel;
|
||||
import org.asamk.signal.manager.storage.Utils;
|
||||
import org.asamk.signal.manager.storage.recipients.RecipientAddress;
|
||||
import org.signal.core.models.ServiceId.ACI;
|
||||
import org.signal.core.util.UuidUtil;
|
||||
import org.signal.libsignal.protocol.IdentityKey;
|
||||
import org.signal.libsignal.protocol.IdentityKeyPair;
|
||||
import org.signal.libsignal.protocol.InvalidKeyException;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.whispersystems.signalservice.api.push.ServiceId.ACI;
|
||||
import org.whispersystems.signalservice.api.util.UuidUtil;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
@ -99,7 +99,7 @@ public class LegacyJsonIdentityKeyStore {
|
||||
for (var trustedKey : trustedKeysNode) {
|
||||
var trustedKeyName = trustedKey.hasNonNull("name") ? trustedKey.get("name").asText() : null;
|
||||
|
||||
if (UuidUtil.isUuid(trustedKeyName)) {
|
||||
if (UuidUtil.INSTANCE.isUuid(trustedKeyName)) {
|
||||
// Ignore identities that were incorrectly created with UUIDs as name
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -7,8 +7,8 @@ import com.fasterxml.jackson.databind.JsonNode;
|
||||
|
||||
import org.asamk.signal.manager.storage.Utils;
|
||||
import org.asamk.signal.manager.storage.recipients.RecipientAddress;
|
||||
import org.whispersystems.signalservice.api.push.ServiceId.ACI;
|
||||
import org.whispersystems.signalservice.api.util.UuidUtil;
|
||||
import org.signal.core.models.ServiceId.ACI;
|
||||
import org.signal.core.util.UuidUtil;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
@ -41,7 +41,7 @@ public class LegacyJsonSessionStore {
|
||||
if (node.isArray()) {
|
||||
for (var session : node) {
|
||||
var sessionName = session.hasNonNull("name") ? session.get("name").asText() : null;
|
||||
if (UuidUtil.isUuid(sessionName)) {
|
||||
if (UuidUtil.INSTANCE.isUuid(sessionName)) {
|
||||
// Ignore sessions that were incorrectly created with UUIDs as name
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -7,7 +7,7 @@ import com.fasterxml.jackson.databind.JsonDeserializer;
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
|
||||
|
||||
import org.whispersystems.signalservice.api.push.ServiceId;
|
||||
import org.signal.core.models.ServiceId;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
|
||||
@ -3,12 +3,12 @@ package org.asamk.signal.manager.storage.recipients;
|
||||
import org.asamk.signal.manager.api.Contact;
|
||||
import org.asamk.signal.manager.api.Profile;
|
||||
import org.asamk.signal.manager.storage.Utils;
|
||||
import org.signal.core.models.ServiceId;
|
||||
import org.signal.libsignal.zkgroup.InvalidInputException;
|
||||
import org.signal.libsignal.zkgroup.profiles.ExpiringProfileKeyCredential;
|
||||
import org.signal.libsignal.zkgroup.profiles.ProfileKey;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.whispersystems.signalservice.api.push.ServiceId;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
|
||||
@ -1,8 +1,8 @@
|
||||
package org.asamk.signal.manager.storage.recipients;
|
||||
|
||||
import org.whispersystems.signalservice.api.push.ServiceId;
|
||||
import org.whispersystems.signalservice.api.push.ServiceId.ACI;
|
||||
import org.whispersystems.signalservice.api.push.ServiceId.PNI;
|
||||
import org.signal.core.models.ServiceId;
|
||||
import org.signal.core.models.ServiceId.ACI;
|
||||
import org.signal.core.models.ServiceId.PNI;
|
||||
import org.whispersystems.signalservice.api.push.SignalServiceAddress;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
package org.asamk.signal.manager.storage.recipients;
|
||||
|
||||
import org.whispersystems.signalservice.api.push.ServiceId;
|
||||
import org.signal.core.models.ServiceId;
|
||||
import org.whispersystems.signalservice.api.push.SignalServiceAddress;
|
||||
|
||||
import java.util.function.Supplier;
|
||||
|
||||
@ -10,14 +10,14 @@ import org.asamk.signal.manager.storage.Utils;
|
||||
import org.asamk.signal.manager.storage.contacts.ContactsStore;
|
||||
import org.asamk.signal.manager.storage.profiles.ProfileStore;
|
||||
import org.asamk.signal.manager.util.KeyUtils;
|
||||
import org.signal.core.models.ServiceId;
|
||||
import org.signal.core.models.ServiceId.ACI;
|
||||
import org.signal.core.models.ServiceId.PNI;
|
||||
import org.signal.libsignal.zkgroup.InvalidInputException;
|
||||
import org.signal.libsignal.zkgroup.profiles.ExpiringProfileKeyCredential;
|
||||
import org.signal.libsignal.zkgroup.profiles.ProfileKey;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.whispersystems.signalservice.api.push.ServiceId;
|
||||
import org.whispersystems.signalservice.api.push.ServiceId.ACI;
|
||||
import org.whispersystems.signalservice.api.push.ServiceId.PNI;
|
||||
import org.whispersystems.signalservice.api.push.SignalServiceAddress;
|
||||
import org.whispersystems.signalservice.api.storage.StorageId;
|
||||
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
package org.asamk.signal.manager.storage.recipients;
|
||||
|
||||
import org.whispersystems.signalservice.api.push.ServiceId.ACI;
|
||||
import org.whispersystems.signalservice.api.push.ServiceId.PNI;
|
||||
import org.signal.core.models.ServiceId.ACI;
|
||||
import org.signal.core.models.ServiceId.PNI;
|
||||
import org.whispersystems.signalservice.api.push.SignalServiceAddress;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
@ -4,13 +4,13 @@ import org.asamk.signal.manager.api.GroupId;
|
||||
import org.asamk.signal.manager.groups.GroupUtils;
|
||||
import org.asamk.signal.manager.storage.Database;
|
||||
import org.asamk.signal.manager.storage.Utils;
|
||||
import org.signal.core.models.ServiceId;
|
||||
import org.signal.libsignal.zkgroup.InvalidInputException;
|
||||
import org.signal.libsignal.zkgroup.groups.GroupMasterKey;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.whispersystems.signalservice.api.crypto.ContentHint;
|
||||
import org.whispersystems.signalservice.api.messages.SendMessageResult;
|
||||
import org.whispersystems.signalservice.api.push.ServiceId;
|
||||
import org.whispersystems.signalservice.internal.push.Content;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
@ -3,14 +3,14 @@ package org.asamk.signal.manager.storage.senderKeys;
|
||||
import org.asamk.signal.manager.api.Pair;
|
||||
import org.asamk.signal.manager.storage.Database;
|
||||
import org.asamk.signal.manager.storage.Utils;
|
||||
import org.signal.core.models.ServiceId;
|
||||
import org.signal.core.util.UuidUtil;
|
||||
import org.signal.libsignal.protocol.InvalidMessageException;
|
||||
import org.signal.libsignal.protocol.SignalProtocolAddress;
|
||||
import org.signal.libsignal.protocol.groups.state.SenderKeyRecord;
|
||||
import org.signal.libsignal.protocol.groups.state.SenderKeyStore;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.whispersystems.signalservice.api.push.ServiceId;
|
||||
import org.whispersystems.signalservice.api.util.UuidUtil;
|
||||
|
||||
import java.sql.Connection;
|
||||
import java.sql.ResultSet;
|
||||
|
||||
@ -2,12 +2,12 @@ package org.asamk.signal.manager.storage.senderKeys;
|
||||
|
||||
import org.asamk.signal.manager.storage.Database;
|
||||
import org.asamk.signal.manager.storage.Utils;
|
||||
import org.signal.core.models.ServiceId;
|
||||
import org.signal.core.util.UuidUtil;
|
||||
import org.signal.libsignal.protocol.SignalProtocolAddress;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.whispersystems.signalservice.api.push.DistributionId;
|
||||
import org.whispersystems.signalservice.api.push.ServiceId;
|
||||
import org.whispersystems.signalservice.api.util.UuidUtil;
|
||||
|
||||
import java.sql.Connection;
|
||||
import java.sql.ResultSet;
|
||||
|
||||
@ -2,11 +2,11 @@ package org.asamk.signal.manager.storage.senderKeys;
|
||||
|
||||
import org.asamk.signal.manager.api.Pair;
|
||||
import org.asamk.signal.manager.storage.Database;
|
||||
import org.signal.core.models.ServiceId;
|
||||
import org.signal.libsignal.protocol.SignalProtocolAddress;
|
||||
import org.signal.libsignal.protocol.groups.state.SenderKeyRecord;
|
||||
import org.whispersystems.signalservice.api.SignalServiceSenderKeyStore;
|
||||
import org.whispersystems.signalservice.api.push.DistributionId;
|
||||
import org.whispersystems.signalservice.api.push.ServiceId;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Map;
|
||||
|
||||
@ -3,6 +3,7 @@ package org.asamk.signal.manager.storage.sessions;
|
||||
import org.asamk.signal.manager.api.Pair;
|
||||
import org.asamk.signal.manager.storage.Database;
|
||||
import org.asamk.signal.manager.storage.Utils;
|
||||
import org.signal.core.models.ServiceId;
|
||||
import org.signal.libsignal.protocol.NoSessionException;
|
||||
import org.signal.libsignal.protocol.SignalProtocolAddress;
|
||||
import org.signal.libsignal.protocol.ecc.ECPublicKey;
|
||||
@ -10,7 +11,6 @@ import org.signal.libsignal.protocol.state.SessionRecord;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.whispersystems.signalservice.api.SignalServiceSessionStore;
|
||||
import org.whispersystems.signalservice.api.push.ServiceId;
|
||||
import org.whispersystems.signalservice.api.push.ServiceIdType;
|
||||
|
||||
import java.sql.Connection;
|
||||
|
||||
@ -5,8 +5,8 @@ import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import org.asamk.signal.manager.api.StickerPackId;
|
||||
import org.asamk.signal.manager.util.IOUtils;
|
||||
import org.asamk.signal.manager.util.Utils;
|
||||
import org.signal.core.util.Hex;
|
||||
import org.whispersystems.signalservice.api.util.StreamDetails;
|
||||
import org.whispersystems.signalservice.internal.util.Hex;
|
||||
|
||||
import java.io.BufferedWriter;
|
||||
import java.io.File;
|
||||
|
||||
@ -5,6 +5,7 @@ import org.asamk.signal.manager.internal.JobExecutor;
|
||||
import org.asamk.signal.manager.jobs.DownloadProfileAvatarJob;
|
||||
import org.asamk.signal.manager.storage.SignalAccount;
|
||||
import org.asamk.signal.manager.util.KeyUtils;
|
||||
import org.signal.core.util.UuidUtil;
|
||||
import org.signal.libsignal.zkgroup.InvalidInputException;
|
||||
import org.signal.libsignal.zkgroup.profiles.ProfileKey;
|
||||
import org.slf4j.Logger;
|
||||
@ -13,7 +14,6 @@ import org.whispersystems.signalservice.api.push.UsernameLinkComponents;
|
||||
import org.whispersystems.signalservice.api.storage.IAPSubscriptionId;
|
||||
import org.whispersystems.signalservice.api.storage.SignalAccountRecord;
|
||||
import org.whispersystems.signalservice.api.storage.StorageId;
|
||||
import org.whispersystems.signalservice.api.util.UuidUtil;
|
||||
import org.whispersystems.signalservice.internal.storage.protos.AccountRecord;
|
||||
import org.whispersystems.signalservice.internal.storage.protos.OptionalBool;
|
||||
|
||||
|
||||
@ -8,14 +8,14 @@ import org.asamk.signal.manager.jobs.RefreshRecipientsJob;
|
||||
import org.asamk.signal.manager.storage.SignalAccount;
|
||||
import org.asamk.signal.manager.storage.recipients.RecipientAddress;
|
||||
import org.asamk.signal.manager.util.KeyUtils;
|
||||
import org.signal.core.models.ServiceId.ACI;
|
||||
import org.signal.core.models.ServiceId.PNI;
|
||||
import org.signal.libsignal.protocol.IdentityKey;
|
||||
import org.signal.libsignal.protocol.InvalidKeyException;
|
||||
import org.signal.libsignal.zkgroup.InvalidInputException;
|
||||
import org.signal.libsignal.zkgroup.profiles.ProfileKey;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.whispersystems.signalservice.api.push.ServiceId.ACI;
|
||||
import org.whispersystems.signalservice.api.push.ServiceId.PNI;
|
||||
import org.whispersystems.signalservice.api.storage.SignalContactRecord;
|
||||
import org.whispersystems.signalservice.api.storage.StorageId;
|
||||
import org.whispersystems.signalservice.internal.storage.protos.ContactRecord;
|
||||
@ -63,8 +63,8 @@ public class ContactRecordProcessor extends DefaultStorageRecordProcessor<Signal
|
||||
@Override
|
||||
protected boolean isInvalid(SignalContactRecord remoteRecord) {
|
||||
final var remote = remoteRecord.getProto();
|
||||
final var aci = ACI.parseOrNull(remote.aci);
|
||||
final var pni = PNI.parseOrNull(remote.pni);
|
||||
final var aci = ACI.parseOrNull(remote.aci, remote.aciBinary);
|
||||
final var pni = PNI.parseOrNull(remote.pni, remote.pniBinary);
|
||||
final var e164 = nullIfEmpty(remote.e164);
|
||||
boolean hasAci = aci != null && aci.isValid();
|
||||
boolean hasPni = pni != null && pni.isValid();
|
||||
@ -129,7 +129,7 @@ public class ContactRecordProcessor extends DefaultStorageRecordProcessor<Signal
|
||||
identityKey = local.identityKey.size() > 0 ? local.identityKey : ByteString.EMPTY;
|
||||
}
|
||||
|
||||
if (!local.aci.isEmpty()
|
||||
if ((!local.aci.isEmpty() || local.aciBinary.size() > 0)
|
||||
&& local.identityKey.size() > 0
|
||||
&& remote.identityKey.size() > 0
|
||||
&& !local.identityKey.equals(remote.identityKey)) {
|
||||
@ -327,8 +327,8 @@ public class ContactRecordProcessor extends DefaultStorageRecordProcessor<Signal
|
||||
}
|
||||
|
||||
private static RecipientAddress getRecipientAddress(final ContactRecord contactRecord) {
|
||||
return new RecipientAddress(ACI.parseOrNull(contactRecord.aci),
|
||||
PNI.parseOrNull(contactRecord.pni),
|
||||
return new RecipientAddress(ACI.parseOrNull(contactRecord.aci, contactRecord.aciBinary),
|
||||
PNI.parseOrNull(contactRecord.pni, contactRecord.pniBinary),
|
||||
nullIfEmpty(contactRecord.e164),
|
||||
nullIfEmpty(contactRecord.username));
|
||||
}
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
package org.asamk.signal.manager.syncStorage;
|
||||
|
||||
import org.asamk.signal.manager.api.Contact;
|
||||
import org.asamk.signal.manager.api.PhoneNumberSharingMode;
|
||||
import org.asamk.signal.manager.api.TrustLevel;
|
||||
import org.asamk.signal.manager.storage.configuration.ConfigurationStore;
|
||||
@ -7,14 +8,14 @@ import org.asamk.signal.manager.storage.groups.GroupInfoV1;
|
||||
import org.asamk.signal.manager.storage.groups.GroupInfoV2;
|
||||
import org.asamk.signal.manager.storage.identities.IdentityInfo;
|
||||
import org.asamk.signal.manager.storage.recipients.Recipient;
|
||||
import org.whispersystems.signalservice.api.push.ServiceId.ACI;
|
||||
import org.whispersystems.signalservice.api.push.ServiceId.PNI;
|
||||
import org.signal.core.models.ServiceId.ACI;
|
||||
import org.signal.core.models.ServiceId.PNI;
|
||||
import org.signal.core.util.UuidUtil;
|
||||
import org.whispersystems.signalservice.api.push.UsernameLinkComponents;
|
||||
import org.whispersystems.signalservice.api.storage.SignalAccountRecord;
|
||||
import org.whispersystems.signalservice.api.storage.SignalContactRecord;
|
||||
import org.whispersystems.signalservice.api.storage.SignalGroupV1Record;
|
||||
import org.whispersystems.signalservice.api.storage.SignalGroupV2Record;
|
||||
import org.whispersystems.signalservice.api.util.UuidUtil;
|
||||
import org.whispersystems.signalservice.internal.storage.protos.AccountRecord;
|
||||
import org.whispersystems.signalservice.internal.storage.protos.AccountRecord.UsernameLink;
|
||||
import org.whispersystems.signalservice.internal.storage.protos.ContactRecord;
|
||||
@ -32,6 +33,9 @@ import static org.signal.core.util.StringExtensionsKt.emptyIfNull;
|
||||
|
||||
public final class StorageSyncModels {
|
||||
|
||||
private final static boolean useBinaryId = false;
|
||||
private final static boolean useStringId = true;
|
||||
|
||||
private StorageSyncModels() {
|
||||
}
|
||||
|
||||
@ -89,13 +93,19 @@ public final class StorageSyncModels {
|
||||
public static ContactRecord localToRemoteRecord(Recipient recipient, IdentityInfo identity) {
|
||||
final var address = recipient.getAddress();
|
||||
final var builder = SignalContactRecord.Companion.newBuilder(recipient.getStorageRecord())
|
||||
.aci(address.aci().map(ACI::toString).orElse(""))
|
||||
.e164(address.number().orElse(""))
|
||||
.pni(address.pni().map(PNI::toStringWithoutPrefix).orElse(""))
|
||||
.username(address.username().orElse(""))
|
||||
.profileKey(recipient.getProfileKey() == null
|
||||
? ByteString.EMPTY
|
||||
: ByteString.of(recipient.getProfileKey().serialize()));
|
||||
if (useBinaryId) {
|
||||
builder.aciBinary(address.aci().map(ACI::toByteString).orElse(ByteString.EMPTY))
|
||||
.pniBinary(address.pni().map(PNI::toByteString).orElse(ByteString.EMPTY));
|
||||
}
|
||||
if (useStringId) {
|
||||
builder.aci(address.aci().map(ACI::toString).orElse(""))
|
||||
.pni(address.pni().map(PNI::toStringWithoutPrefix).orElse(""));
|
||||
}
|
||||
if (recipient.getProfile() != null) {
|
||||
builder.givenName(emptyIfNull(recipient.getProfile().getGivenName()))
|
||||
.familyName(emptyIfNull(recipient.getProfile().getFamilyName()));
|
||||
@ -104,10 +114,7 @@ public final class StorageSyncModels {
|
||||
builder.systemGivenName(emptyIfNull(recipient.getContact().givenName()))
|
||||
.systemFamilyName(emptyIfNull(recipient.getContact().familyName()))
|
||||
.systemNickname(emptyIfNull(recipient.getContact().nickName()))
|
||||
.nickname(new ContactRecord.Name.Builder().given(emptyIfNull(recipient.getContact()
|
||||
.nickNameGivenName()))
|
||||
.family(emptyIfNull(recipient.getContact().nickNameFamilyName()))
|
||||
.build())
|
||||
.nickname(getNicknameRemoteRecord(recipient.getContact()))
|
||||
.note(emptyIfNull(recipient.getContact().note()))
|
||||
.blocked(recipient.getContact().isBlocked())
|
||||
.whitelisted(recipient.getContact().isProfileSharingEnabled())
|
||||
@ -126,6 +133,15 @@ public final class StorageSyncModels {
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
private static ContactRecord.Name getNicknameRemoteRecord(final Contact contact) {
|
||||
final var given = emptyIfNull(contact.nickNameGivenName());
|
||||
final var family = emptyIfNull(contact.nickNameFamilyName());
|
||||
if (given.isEmpty() && family.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
return new ContactRecord.Name.Builder().given(given).family(family).build();
|
||||
}
|
||||
|
||||
public static GroupV1Record localToRemoteRecord(GroupInfoV1 group) {
|
||||
final var builder = SignalGroupV1Record.Companion.newBuilder(group.getStorageRecord());
|
||||
builder.id(ByteString.of(group.getGroupId().serialize()));
|
||||
|
||||
@ -1,12 +1,12 @@
|
||||
package org.asamk.signal.manager.syncStorage;
|
||||
|
||||
import org.asamk.signal.manager.storage.recipients.RecipientAddress;
|
||||
import org.signal.core.models.ServiceId.ACI;
|
||||
import org.signal.core.models.ServiceId.PNI;
|
||||
import org.signal.core.util.Base64;
|
||||
import org.signal.core.util.SetUtil;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.whispersystems.signalservice.api.push.ServiceId.ACI;
|
||||
import org.whispersystems.signalservice.api.push.ServiceId.PNI;
|
||||
import org.whispersystems.signalservice.api.storage.SignalStorageManifest;
|
||||
import org.whispersystems.signalservice.api.storage.SignalStorageRecord;
|
||||
import org.whispersystems.signalservice.api.storage.StorageId;
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
package org.asamk.signal.manager.util;
|
||||
|
||||
import org.asamk.signal.manager.storage.SignalAccount;
|
||||
import org.signal.core.models.backup.MediaRootBackupKey;
|
||||
import org.signal.libsignal.protocol.IdentityKey;
|
||||
import org.signal.libsignal.protocol.IdentityKeyPair;
|
||||
import org.signal.libsignal.protocol.InvalidKeyException;
|
||||
@ -14,7 +15,6 @@ import org.signal.libsignal.protocol.state.SignedPreKeyRecord;
|
||||
import org.signal.libsignal.zkgroup.InvalidInputException;
|
||||
import org.signal.libsignal.zkgroup.profiles.ProfileKey;
|
||||
import org.whispersystems.signalservice.api.account.PreKeyCollection;
|
||||
import org.whispersystems.signalservice.api.backup.MediaRootBackupKey;
|
||||
|
||||
import java.security.SecureRandom;
|
||||
import java.util.ArrayList;
|
||||
|
||||
@ -1,11 +1,11 @@
|
||||
package org.asamk.signal.manager.util;
|
||||
|
||||
import org.signal.core.models.ServiceId;
|
||||
import org.signal.core.util.UuidUtil;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.whispersystems.signalservice.api.messages.SignalServiceEnvelope;
|
||||
import org.whispersystems.signalservice.api.push.ServiceId;
|
||||
import org.whispersystems.signalservice.api.push.SignalServiceAddress;
|
||||
import org.whispersystems.signalservice.api.util.UuidUtil;
|
||||
import org.whispersystems.signalservice.internal.push.Envelope;
|
||||
|
||||
import java.io.DataInputStream;
|
||||
|
||||
@ -9,9 +9,9 @@ import org.asamk.signal.manager.api.PinLockedException;
|
||||
import org.asamk.signal.manager.api.RateLimitException;
|
||||
import org.asamk.signal.manager.api.VerificationMethodNotAvailableException;
|
||||
import org.asamk.signal.manager.helper.PinHelper;
|
||||
import org.signal.core.models.MasterKey;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.whispersystems.signalservice.api.kbs.MasterKey;
|
||||
import org.whispersystems.signalservice.api.push.exceptions.ChallengeRequiredException;
|
||||
import org.whispersystems.signalservice.api.push.exceptions.NoSuchSessionException;
|
||||
import org.whispersystems.signalservice.api.push.exceptions.NonSuccessfulResponseCodeException;
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
package org.asamk.signal.manager.util;
|
||||
|
||||
import org.asamk.signal.manager.api.Pair;
|
||||
import org.signal.core.models.ServiceId;
|
||||
import org.signal.libsignal.net.BadRequestError;
|
||||
import org.signal.libsignal.net.RequestResult;
|
||||
import org.signal.libsignal.protocol.IdentityKey;
|
||||
@ -10,7 +11,6 @@ import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.whispersystems.signalservice.api.NetworkResult;
|
||||
import org.whispersystems.signalservice.api.NetworkResultUtil;
|
||||
import org.whispersystems.signalservice.api.push.ServiceId;
|
||||
import org.whispersystems.signalservice.api.util.StreamDetails;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
@ -160,9 +160,10 @@ public class Utils {
|
||||
return NetworkResultUtil.toBasicLegacy(response);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public static <T, E extends BadRequestError> T handleResponseException(final RequestResult<T, E> result) throws IOException {
|
||||
if (result instanceof RequestResult.Success) {
|
||||
return ((RequestResult.Success<T>) result).getResult();
|
||||
if (result instanceof RequestResult.Success<?> success) {
|
||||
return ((RequestResult.Success<T>) success).getResult();
|
||||
} else if (result instanceof RequestResult.ApplicationError e) {
|
||||
final var cause = e.getCause();
|
||||
switch (cause) {
|
||||
|
||||
@ -3,8 +3,8 @@ package org.asamk.signal.manager.storage.recipients;
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
import org.junit.jupiter.params.provider.Arguments;
|
||||
import org.junit.jupiter.params.provider.MethodSource;
|
||||
import org.whispersystems.signalservice.api.push.ServiceId.ACI;
|
||||
import org.whispersystems.signalservice.api.push.ServiceId.PNI;
|
||||
import org.signal.core.models.ServiceId.ACI;
|
||||
import org.signal.core.models.ServiceId.PNI;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
|
||||
@ -285,7 +285,7 @@ In json mode this is outputted as a list of objects.
|
||||
One or more numbers to check.
|
||||
|
||||
[--username [USERNAME ...]]::
|
||||
One or more usernames to check.
|
||||
One or more usernames or username links to check.
|
||||
|
||||
=== send
|
||||
|
||||
@ -385,6 +385,89 @@ Clear session state and send end session message.
|
||||
*--edit-timestamp*::
|
||||
Specify the timestamp of a previous message with the recipient or group to send an edited message.
|
||||
|
||||
=== sendPollCreate
|
||||
|
||||
Send a poll create message to another user or group.
|
||||
|
||||
RECIPIENT::
|
||||
Specify the recipients.
|
||||
|
||||
*--note-to-self*::
|
||||
Send the message to self.
|
||||
|
||||
*--notify-self*::
|
||||
If self is part of recipients/groups send a normal message, not a sync message.
|
||||
|
||||
*-g* GROUP, *--group-id* GROUP::
|
||||
Specify the recipient group ID in base64 encoding.
|
||||
|
||||
*-u* USERNAME, *--username* USERNAME::
|
||||
Specify the recipient username or username link.
|
||||
|
||||
*-q* QUESTION, *--question* QUESTION::
|
||||
Specify the poll question.
|
||||
|
||||
*--no-multi*::
|
||||
Allow only one option to be selected by each recipient.
|
||||
By default, recipients can select multiple options.
|
||||
|
||||
*-o* OPTION [OPTION ...], *--option* OPTION [OPTION ...]*::
|
||||
The options for the poll.
|
||||
|
||||
=== sendPollVote
|
||||
|
||||
Send a poll vote message to another user or group, to vote on a previously created vote.
|
||||
|
||||
RECIPIENT::
|
||||
Specify the recipients.
|
||||
|
||||
*--note-to-self*::
|
||||
Send the message to self.
|
||||
|
||||
*--notify-self*::
|
||||
If self is part of recipients/groups send a normal message, not a sync message.
|
||||
|
||||
*-g* GROUP, *--group-id* GROUP::
|
||||
Specify the recipient group ID in base64 encoding.
|
||||
|
||||
*-u* USERNAME, *--username* USERNAME::
|
||||
Specify the recipient username or username link.
|
||||
|
||||
*--poll-author* POLL_AUTHOR::
|
||||
Specify the number or uuid of the author of the poll message.
|
||||
|
||||
*--poll-timestamp* POLL_TIMESTAMP::
|
||||
Specify the timestamp of the original poll create message.
|
||||
|
||||
*-o* [OPTION [OPTION ...]], *--option* [OPTION [OPTION ...]]::
|
||||
The option indexes of the poll to vote for.
|
||||
For none multi polls, only one option may be specified.
|
||||
|
||||
*--vote-count: VOTE_COUNT::
|
||||
Specify the number of this vote (increase by one for every time you vote).
|
||||
|
||||
=== sendPollTerminate
|
||||
|
||||
Send a poll terminate message to another user or group, to close on a previously created vote.
|
||||
|
||||
RECIPIENT::
|
||||
Specify the recipients.
|
||||
|
||||
*--note-to-self*::
|
||||
Send the message to self.
|
||||
|
||||
*--notify-self*::
|
||||
If self is part of recipients/groups send a normal message, not a sync message.
|
||||
|
||||
*-g* GROUP, *--group-id* GROUP::
|
||||
Specify the recipient group ID in base64 encoding.
|
||||
|
||||
*-u* USERNAME, *--username* USERNAME::
|
||||
Specify the recipient username or username link.
|
||||
|
||||
*--poll-timestamp* POLL_TIMESTAMP::
|
||||
Specify the timestamp of the original poll create message.
|
||||
|
||||
=== sendMessageRequestResponse
|
||||
|
||||
Send response to a message request to linked devices.
|
||||
@ -676,6 +759,7 @@ If the contact doesn't exist yet, it will be added.
|
||||
|
||||
RECIPIENT::
|
||||
Specify the recipient.
|
||||
Use "u:" prefix to specify a username or username link.
|
||||
|
||||
*--given-name* GIVEN_NAME, *--name* NAME::
|
||||
New system given name.
|
||||
@ -916,6 +1000,9 @@ signal-cli -a ACCOUNT verify CODE
|
||||
Send a message to one or more recipients::
|
||||
signal-cli -a ACCOUNT send -m "This is a message" [RECIPIENT [RECIPIENT ...]] [-a [ATTACHMENT [ATTACHMENT ...]]]
|
||||
|
||||
Send a message to a username (or username link)::
|
||||
signal-cli -a ACCOUNT send u:someusername.000 -m "This is a message"
|
||||
|
||||
Pipe the message content from another process::
|
||||
uname -a | signal-cli -a ACCOUNT send --message-from-stdin [RECIPIENT [RECIPIENT ...]]
|
||||
|
||||
|
||||
@ -32,7 +32,7 @@ fi
|
||||
|
||||
run() {
|
||||
# To update graalvm config, set GRAALVM_HOME, e.g:
|
||||
# export GRAALVM_HOME=/usr/lib/jvm/java-21-graalvm
|
||||
# export GRAALVM_HOME=/usr/lib/jvm/java-25-graalvm
|
||||
if [ ! -z "$GRAALVM_HOME" ]; then
|
||||
export JAVA_HOME=$GRAALVM_HOME
|
||||
export SIGNAL_CLI_OPTS="-agentlib:native-image-agent=config-merge-dir=graalvm-config-dir-${SIGNAL_CLI_AGENT_ID}/"
|
||||
|
||||
@ -1,7 +1,14 @@
|
||||
dependencyResolutionManagement {
|
||||
repositories {
|
||||
mavenLocal()
|
||||
mavenCentral()
|
||||
mavenLocal()
|
||||
maven {
|
||||
name = "SignalBuildArtifacts"
|
||||
url = uri("https://build-artifacts.signal.org/libraries/maven/")
|
||||
content {
|
||||
includeGroupByRegex("org\\.signal.*")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -143,9 +143,6 @@ public interface Signal extends DBusInterface {
|
||||
String avatar
|
||||
) throws Error.AttachmentInvalid, Error.Failure, Error.InvalidNumber, Error.GroupNotFound, Error.InvalidGroupId;
|
||||
|
||||
@Deprecated
|
||||
boolean isRegistered() throws Error.Failure, Error.InvalidNumber;
|
||||
|
||||
boolean isRegistered(String number) throws Error.Failure, Error.InvalidNumber;
|
||||
|
||||
List<Boolean> isRegistered(List<String> numbers) throws Error.Failure, Error.InvalidNumber;
|
||||
|
||||
@ -291,8 +291,6 @@ public class App {
|
||||
commandHandler.handleMultiLocalCommand(command, multiAccountManager);
|
||||
} catch (IOException e) {
|
||||
throw new IOErrorException("Failed to load local accounts file", e);
|
||||
} catch (AccountCheckException e) {
|
||||
throw new UnexpectedErrorException("Failed to load account file", e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -13,10 +13,4 @@ public enum ServiceEnvironmentCli {
|
||||
return "staging";
|
||||
}
|
||||
},
|
||||
@Deprecated SANDBOX {
|
||||
@Override
|
||||
public String toString() {
|
||||
return "sandbox";
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
@ -3,12 +3,13 @@ package org.asamk.signal.commands;
|
||||
import org.asamk.signal.OutputType;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.SequencedCollection;
|
||||
|
||||
public interface Command {
|
||||
|
||||
String getName();
|
||||
|
||||
default List<OutputType> getSupportedOutputTypes() {
|
||||
default SequencedCollection<OutputType> getSupportedOutputTypes() {
|
||||
return List.of(OutputType.PLAIN_TEXT);
|
||||
}
|
||||
}
|
||||
|
||||
@ -58,6 +58,7 @@ public class Commands {
|
||||
addCommand(new UpdateAccountCommand());
|
||||
addCommand(new UpdateConfigurationCommand());
|
||||
addCommand(new UpdateContactCommand());
|
||||
addCommand(new UpdateDeviceCommand());
|
||||
addCommand(new UpdateGroupCommand());
|
||||
addCommand(new UpdateProfileCommand());
|
||||
addCommand(new UploadStickerPackCommand());
|
||||
|
||||
@ -10,6 +10,7 @@ import org.asamk.signal.ReceiveMessageHandler;
|
||||
import org.asamk.signal.Shutdown;
|
||||
import org.asamk.signal.commands.exceptions.CommandException;
|
||||
import org.asamk.signal.commands.exceptions.IOErrorException;
|
||||
import org.asamk.signal.commands.exceptions.UserErrorException;
|
||||
import org.asamk.signal.dbus.DbusHandler;
|
||||
import org.asamk.signal.http.HttpServerHandler;
|
||||
import org.asamk.signal.json.JsonReceiveMessageHandler;
|
||||
@ -31,6 +32,7 @@ import java.nio.channels.Channel;
|
||||
import java.nio.channels.ServerSocketChannel;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.SequencedCollection;
|
||||
|
||||
import static org.asamk.signal.util.CommandUtil.getReceiveConfig;
|
||||
|
||||
@ -86,7 +88,7 @@ public class DaemonCommand implements MultiLocalCommand, LocalCommand {
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<OutputType> getSupportedOutputTypes() {
|
||||
public SequencedCollection<OutputType> getSupportedOutputTypes() {
|
||||
return List.of(OutputType.PLAIN_TEXT, OutputType.JSON);
|
||||
}
|
||||
|
||||
@ -201,9 +203,7 @@ public class DaemonCommand implements MultiLocalCommand, LocalCommand {
|
||||
&& tcpAddress == null
|
||||
&& httpAddress == null
|
||||
&& inheritedChannel == null) {
|
||||
logger.warn(
|
||||
"Running daemon command without explicit mode is deprecated. Use 'daemon --dbus' to use the dbus interface.");
|
||||
daemonHandler.runDbus(false, DbusConfig.getBusname());
|
||||
throw new UserErrorException("At least one channel parameter is required, e.g. --socket or --dbus.");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -16,6 +16,7 @@ import org.asamk.signal.output.JsonWriter;
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.SequencedCollection;
|
||||
|
||||
public class DeleteLocalAccountDataCommand implements RegistrationCommand, JsonRpcRegistrationCommand<Map<String, Object>> {
|
||||
|
||||
@ -54,7 +55,7 @@ public class DeleteLocalAccountDataCommand implements RegistrationCommand, JsonR
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<OutputType> getSupportedOutputTypes() {
|
||||
public SequencedCollection<OutputType> getSupportedOutputTypes() {
|
||||
return List.of(OutputType.PLAIN_TEXT, OutputType.JSON);
|
||||
}
|
||||
|
||||
|
||||
@ -5,6 +5,7 @@ import com.fasterxml.jackson.core.type.TypeReference;
|
||||
import org.asamk.signal.OutputType;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.SequencedCollection;
|
||||
|
||||
public interface JsonRpcCommand<T> extends Command {
|
||||
|
||||
@ -12,7 +13,7 @@ public interface JsonRpcCommand<T> extends Command {
|
||||
return null;
|
||||
}
|
||||
|
||||
default List<OutputType> getSupportedOutputTypes() {
|
||||
default SequencedCollection<OutputType> getSupportedOutputTypes() {
|
||||
return List.of(OutputType.JSON);
|
||||
}
|
||||
}
|
||||
|
||||
@ -21,6 +21,7 @@ import java.io.FileInputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.nio.channels.Channels;
|
||||
import java.util.List;
|
||||
import java.util.SequencedCollection;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import static org.asamk.signal.util.CommandUtil.getReceiveConfig;
|
||||
@ -53,7 +54,7 @@ public class JsonRpcDispatcherCommand implements LocalCommand, MultiLocalCommand
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<OutputType> getSupportedOutputTypes() {
|
||||
public SequencedCollection<OutputType> getSupportedOutputTypes() {
|
||||
return List.of(OutputType.JSON);
|
||||
}
|
||||
|
||||
|
||||
@ -11,6 +11,7 @@ import org.asamk.signal.output.JsonWriter;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.SequencedCollection;
|
||||
|
||||
public interface JsonRpcLocalCommand extends JsonRpcSingleCommand<Map<String, Object>>, LocalCommand {
|
||||
|
||||
@ -23,7 +24,7 @@ public interface JsonRpcLocalCommand extends JsonRpcSingleCommand<Map<String, Ob
|
||||
handleCommand(commandNamespace, m, jsonWriter);
|
||||
}
|
||||
|
||||
default List<OutputType> getSupportedOutputTypes() {
|
||||
default SequencedCollection<OutputType> getSupportedOutputTypes() {
|
||||
return List.of(OutputType.PLAIN_TEXT, OutputType.JSON);
|
||||
}
|
||||
}
|
||||
|
||||
@ -11,6 +11,7 @@ import org.asamk.signal.output.JsonWriter;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.SequencedCollection;
|
||||
|
||||
public interface JsonRpcMultiLocalCommand extends JsonRpcMultiCommand<Map<String, Object>>, MultiLocalCommand {
|
||||
|
||||
@ -27,7 +28,7 @@ public interface JsonRpcMultiLocalCommand extends JsonRpcMultiCommand<Map<String
|
||||
handleCommand(commandNamespace, c, jsonWriter);
|
||||
}
|
||||
|
||||
default List<OutputType> getSupportedOutputTypes() {
|
||||
default SequencedCollection<OutputType> getSupportedOutputTypes() {
|
||||
return List.of(OutputType.PLAIN_TEXT, OutputType.JSON);
|
||||
}
|
||||
}
|
||||
|
||||
@ -27,6 +27,7 @@ import java.time.Duration;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.SequencedCollection;
|
||||
|
||||
public class ReceiveCommand implements LocalCommand, JsonRpcSingleCommand<ReceiveCommand.ReceiveParams> {
|
||||
|
||||
@ -60,7 +61,7 @@ public class ReceiveCommand implements LocalCommand, JsonRpcSingleCommand<Receiv
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<OutputType> getSupportedOutputTypes() {
|
||||
public SequencedCollection<OutputType> getSupportedOutputTypes() {
|
||||
return List.of(OutputType.PLAIN_TEXT, OutputType.JSON);
|
||||
}
|
||||
|
||||
|
||||
@ -21,6 +21,7 @@ import org.asamk.signal.util.CommandUtil;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
import java.util.SequencedCollection;
|
||||
|
||||
public class RegisterCommand implements RegistrationCommand, JsonRpcRegistrationCommand<RegisterCommand.RegistrationParams> {
|
||||
|
||||
@ -57,7 +58,7 @@ public class RegisterCommand implements RegistrationCommand, JsonRpcRegistration
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<OutputType> getSupportedOutputTypes() {
|
||||
public SequencedCollection<OutputType> getSupportedOutputTypes() {
|
||||
return List.of(OutputType.PLAIN_TEXT, OutputType.JSON);
|
||||
}
|
||||
|
||||
|
||||
@ -7,7 +7,6 @@ import org.asamk.signal.commands.exceptions.CommandException;
|
||||
import org.asamk.signal.commands.exceptions.IOErrorException;
|
||||
import org.asamk.signal.commands.exceptions.UserErrorException;
|
||||
import org.asamk.signal.manager.Manager;
|
||||
import org.asamk.signal.manager.api.NotPrimaryDeviceException;
|
||||
import org.asamk.signal.manager.api.UnregisteredRecipientException;
|
||||
import org.asamk.signal.output.OutputWriter;
|
||||
import org.asamk.signal.util.CommandUtil;
|
||||
@ -63,8 +62,6 @@ public class UpdateContactCommand implements JsonRpcLocalCommand {
|
||||
m.setContactName(recipient, givenName, familyName, nickGivenName, nickFamilyName, note);
|
||||
} catch (IOException e) {
|
||||
throw new IOErrorException("Update contact error: " + e.getMessage(), e);
|
||||
} catch (NotPrimaryDeviceException e) {
|
||||
throw new UserErrorException("This command doesn't work on linked devices.");
|
||||
} catch (UnregisteredRecipientException e) {
|
||||
throw new UserErrorException("The user " + e.getSender().getIdentifier() + " is not registered.");
|
||||
}
|
||||
|
||||
@ -0,0 +1,50 @@
|
||||
package org.asamk.signal.commands;
|
||||
|
||||
import net.sourceforge.argparse4j.inf.Namespace;
|
||||
import net.sourceforge.argparse4j.inf.Subparser;
|
||||
|
||||
import org.asamk.signal.commands.exceptions.CommandException;
|
||||
import org.asamk.signal.commands.exceptions.IOErrorException;
|
||||
import org.asamk.signal.commands.exceptions.UserErrorException;
|
||||
import org.asamk.signal.manager.Manager;
|
||||
import org.asamk.signal.manager.api.NotPrimaryDeviceException;
|
||||
import org.asamk.signal.output.OutputWriter;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
public class UpdateDeviceCommand implements JsonRpcLocalCommand {
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "updateDevice";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void attachToSubparser(final Subparser subparser) {
|
||||
subparser.help("Update a linked device.");
|
||||
subparser.addArgument("-d", "--device-id", "--deviceId")
|
||||
.type(int.class)
|
||||
.required(true)
|
||||
.help("Specify the device you want to update. Use listDevices to see the deviceIds.");
|
||||
subparser.addArgument("-n", "--device-name")
|
||||
.required(true)
|
||||
.help("Specify a name to describe the given device.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleCommand(
|
||||
final Namespace ns,
|
||||
final Manager m,
|
||||
final OutputWriter outputWriter
|
||||
) throws CommandException {
|
||||
try {
|
||||
final var deviceId = ns.getInt("device-id");
|
||||
final var deviceName = ns.getString("device-name");
|
||||
m.updateLinkedDevice(deviceId, deviceName);
|
||||
} catch (NotPrimaryDeviceException e) {
|
||||
throw new UserErrorException("This command doesn't work on linked devices.");
|
||||
} catch (IOException e) {
|
||||
throw new IOErrorException("Error while updating device: " + e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -19,6 +19,7 @@ import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
import java.util.SequencedCollection;
|
||||
|
||||
public class VerifyCommand implements RegistrationCommand, JsonRpcRegistrationCommand<VerifyCommand.VerifyParams> {
|
||||
|
||||
@ -50,7 +51,7 @@ public class VerifyCommand implements RegistrationCommand, JsonRpcRegistrationCo
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<OutputType> getSupportedOutputTypes() {
|
||||
public SequencedCollection<OutputType> getSupportedOutputTypes() {
|
||||
return List.of(OutputType.PLAIN_TEXT, OutputType.JSON);
|
||||
}
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user