mirror of
https://github.com/AsamK/signal-cli
synced 2025-08-28 18:10:38 +00:00
Rename username to account
This commit is contained in:
parent
398cddaf29
commit
8aab644db9
14 changed files with 245 additions and 218 deletions
78
README.md
78
README.md
|
@ -1,65 +1,88 @@
|
|||
# signal-cli
|
||||
|
||||
signal-cli is a commandline interface for [libsignal-service-java](https://github.com/WhisperSystems/libsignal-service-java). It supports registering, verifying, sending and receiving messages.
|
||||
To be able to link to an existing Signal-Android/signal-cli instance, signal-cli uses a [patched libsignal-service-java](https://github.com/AsamK/libsignal-service-java), because libsignal-service-java does not yet support [provisioning as a linked device](https://github.com/WhisperSystems/libsignal-service-java/pull/21).
|
||||
For registering you need a phone number where you can receive SMS or incoming calls.
|
||||
signal-cli is primarily intended to be used on servers to notify admins of important events. For this use-case, it has a dbus interface ([man page](https://github.com/AsamK/signal-cli/blob/master/man/signal-cli-dbus.5.adoc)), that can be used to send messages from any programming language that has dbus bindings.
|
||||
It also has a JSON-RPC based interface, see the [documentation](https://github.com/AsamK/signal-cli/wiki/JSON-RPC-service) for more information.
|
||||
signal-cli is a commandline interface
|
||||
for [libsignal-service-java](https://github.com/WhisperSystems/libsignal-service-java). It supports registering,
|
||||
verifying, sending and receiving messages. To be able to link to an existing Signal-Android/signal-cli instance,
|
||||
signal-cli uses a [patched libsignal-service-java](https://github.com/AsamK/libsignal-service-java), because
|
||||
libsignal-service-java does not yet
|
||||
support [provisioning as a linked device](https://github.com/WhisperSystems/libsignal-service-java/pull/21). For
|
||||
registering you need a phone number where you can receive SMS or incoming calls. signal-cli is primarily intended to be
|
||||
used on servers to notify admins of important events. For this use-case, it has a dbus
|
||||
interface ([man page](https://github.com/AsamK/signal-cli/blob/master/man/signal-cli-dbus.5.adoc)), that can be used to
|
||||
send messages from any programming language that has dbus bindings. It also has a JSON-RPC based interface, see
|
||||
the [documentation](https://github.com/AsamK/signal-cli/wiki/JSON-RPC-service) for more information.
|
||||
|
||||
## Installation
|
||||
|
||||
You can [build signal-cli](#building) yourself, or use the [provided binary files](https://github.com/AsamK/signal-cli/releases/latest), which should work on Linux, macOS and Windows. For Arch Linux there is also a [package in AUR](https://aur.archlinux.org/packages/signal-cli/) and there is a [FreeBSD port](https://www.freshports.org/net-im/signal-cli) available as well.
|
||||
You can [build signal-cli](#building) yourself, or use
|
||||
the [provided binary files](https://github.com/AsamK/signal-cli/releases/latest), which should work on Linux, macOS and
|
||||
Windows. For Arch Linux there is also a [package in AUR](https://aur.archlinux.org/packages/signal-cli/) and there is
|
||||
a [FreeBSD port](https://www.freshports.org/net-im/signal-cli) available as well.
|
||||
|
||||
System requirements:
|
||||
|
||||
- at least Java Runtime Environment (JRE) 17
|
||||
- native libraries: libzkgroup, libsignal-client
|
||||
|
||||
Those are bundled for x86_64 Linux (with recent enough glibc, see #643), for other systems/architectures see: [Provide native lib for libsignal](https://github.com/AsamK/signal-cli/wiki/Provide-native-lib-for-libsignal)
|
||||
Those are bundled for x86_64 Linux (with recent enough glibc, see #643), 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
|
||||
|
||||
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
|
||||
sudo tar xf signal-cli-"${VERSION}".tar.gz -C /opt
|
||||
sudo ln -sf /opt/signal-cli-"${VERSION}"/bin/signal-cli /usr/local/bin/
|
||||
```
|
||||
|
||||
You can find further instructions on the Wiki:
|
||||
|
||||
- [Quickstart](https://github.com/AsamK/signal-cli/wiki/Quickstart)
|
||||
- [DBus Service](https://github.com/AsamK/signal-cli/wiki/DBus-service)
|
||||
|
||||
## Usage
|
||||
|
||||
For a complete usage overview please read the [man page](https://github.com/AsamK/signal-cli/blob/master/man/signal-cli.1.adoc) and the [wiki](https://github.com/AsamK/signal-cli/wiki).
|
||||
For a complete usage overview please read
|
||||
the [man page](https://github.com/AsamK/signal-cli/blob/master/man/signal-cli.1.adoc) and
|
||||
the [wiki](https://github.com/AsamK/signal-cli/wiki).
|
||||
|
||||
Important: The USERNAME is your phone number in international format and must include the country calling code. Hence it should start with a "+" sign. (See [Wikipedia](https://en.wikipedia.org/wiki/List_of_country_calling_codes) for a list of all country codes.)
|
||||
Important: The ACCOUNT is your phone number in international format and must include the country calling code. Hence it
|
||||
should start with a "+" sign. (See [Wikipedia](https://en.wikipedia.org/wiki/List_of_country_calling_codes) for a list
|
||||
of all country codes.)
|
||||
|
||||
* Register a number (with SMS verification)
|
||||
|
||||
signal-cli -u USERNAME register
|
||||
signal-cli -a ACCOUNT register
|
||||
|
||||
You can register Signal using a land line number. In this case you can skip SMS verification process and jump directly to the voice call verification by adding the `--voice` switch at the end of above register command.
|
||||
You can register Signal using a land line number. In this case you can skip SMS verification process and jump directly
|
||||
to the voice call verification by adding the `--voice` switch at the end of above register command.
|
||||
|
||||
Registering may require solving a CAPTCHA challenge: [Registration with captcha](https://github.com/AsamK/signal-cli/wiki/Registration-with-captcha)
|
||||
Registering may require solving a CAPTCHA
|
||||
challenge: [Registration with captcha](https://github.com/AsamK/signal-cli/wiki/Registration-with-captcha)
|
||||
|
||||
* Verify the number using the code received via SMS or voice, optionally add `--pin PIN_CODE` if you've added a pin code to your account
|
||||
* Verify the number using the code received via SMS or voice, optionally add `--pin PIN_CODE` if you've added a pin code
|
||||
to your account
|
||||
|
||||
signal-cli -u USERNAME verify CODE
|
||||
signal-cli -a ACCOUNT verify CODE
|
||||
|
||||
* Send a message
|
||||
|
||||
signal-cli -u USERNAME send -m "This is a message" RECIPIENT
|
||||
signal-cli -a ACCOUNT send -m "This is a message" RECIPIENT
|
||||
|
||||
* Pipe the message content from another process.
|
||||
|
||||
uname -a | signal-cli -u USERNAME send RECIPIENT
|
||||
uname -a | signal-cli -a ACCOUNT send RECIPIENT
|
||||
|
||||
* Receive messages
|
||||
|
||||
signal-cli -u USERNAME receive
|
||||
signal-cli -a ACCOUNT receive
|
||||
|
||||
**Hint**: The Signal protocol expects that incoming messages are regularly received (using `daemon` or `receive` command).
|
||||
This is required for the encryption to work efficiently and for getting updates to groups, expiration timer and other features.
|
||||
**Hint**: The Signal protocol expects that incoming messages are regularly received (using `daemon` or `receive`
|
||||
command). This is required for the encryption to work efficiently and for getting updates to groups, expiration timer
|
||||
and other features.
|
||||
|
||||
## Storage
|
||||
|
||||
|
@ -70,8 +93,8 @@ The password and cryptographic keys are created when registering and stored in t
|
|||
|
||||
## Building
|
||||
|
||||
This project uses [Gradle](http://gradle.org) for building and maintaining
|
||||
dependencies. If you have a recent gradle version installed, you can replace `./gradlew` with `gradle` in the following steps.
|
||||
This project uses [Gradle](http://gradle.org) for building and maintaining dependencies. If you have a recent gradle
|
||||
version installed, you can replace `./gradlew` with `gradle` in the following steps.
|
||||
|
||||
1. Checkout the source somewhere on your filesystem with
|
||||
|
||||
|
@ -81,26 +104,26 @@ dependencies. If you have a recent gradle version installed, you can replace `./
|
|||
|
||||
./gradlew build
|
||||
|
||||
2a. Create shell wrapper in *build/install/signal-cli/bin*:
|
||||
2a. Create shell wrapper in *build/install/signal-cli/bin*:
|
||||
|
||||
./gradlew installDist
|
||||
|
||||
2b. Create tar file in *build/distributions*:
|
||||
2b. Create tar file in *build/distributions*:
|
||||
|
||||
./gradlew distTar
|
||||
|
||||
2c. Create a fat tar file in *build/libs/signal-cli-fat*:
|
||||
2c. Create a fat tar file in *build/libs/signal-cli-fat*:
|
||||
|
||||
./gradlew fatJar
|
||||
|
||||
2d. Compile and run signal-cli:
|
||||
2d. Compile and run signal-cli:
|
||||
|
||||
./gradlew run --args="--help"
|
||||
|
||||
### Building a native binary with GraalVM (EXPERIMENTAL)
|
||||
|
||||
It is possible to build a native binary with [GraalVM](https://www.graalvm.org).
|
||||
This is still experimental and will not work in all situations.
|
||||
It is possible to build a native binary with [GraalVM](https://www.graalvm.org). This is still experimental and will not
|
||||
work in all situations.
|
||||
|
||||
1. [Install GraalVM and setup the enviroment](https://www.graalvm.org/docs/getting-started/#install-graalvm)
|
||||
2. [Install prerequisites](https://www.graalvm.org/reference-manual/native-image/#prerequisites)
|
||||
|
@ -111,6 +134,7 @@ This is still experimental and will not work in all situations.
|
|||
The binary is available at *build/native/nativeCompile/signal-cli*
|
||||
|
||||
## FAQ and Troubleshooting
|
||||
|
||||
For frequently asked questions and issues have a look at the [wiki](https://github.com/AsamK/signal-cli/wiki/FAQ)
|
||||
|
||||
## License
|
||||
|
|
|
@ -8,7 +8,7 @@ After=network-online.target
|
|||
[Service]
|
||||
Type=dbus
|
||||
Environment="SIGNAL_CLI_OPTS=-Xms2m"
|
||||
ExecStart=%dir%/bin/signal-cli -u %I --config /var/lib/signal-cli daemon --system
|
||||
ExecStart=%dir%/bin/signal-cli -a %I --config /var/lib/signal-cli daemon --system
|
||||
User=signal-cli
|
||||
BusName=org.asamk.Signal
|
||||
# JVM always exits with 143 in reaction to SIGTERM signal
|
||||
|
|
|
@ -64,6 +64,9 @@
|
|||
{
|
||||
"pattern":"\\Qcom/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_IT\\E"
|
||||
},
|
||||
{
|
||||
"pattern":"\\Qcom/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MO\\E"
|
||||
},
|
||||
{
|
||||
"pattern":"\\Qcom/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_PA\\E"
|
||||
},
|
||||
|
|
|
@ -156,7 +156,7 @@ public class ManagerImpl implements Manager {
|
|||
this.serviceEnvironmentConfig = serviceEnvironmentConfig;
|
||||
|
||||
final var credentialsProvider = new DynamicCredentialsProvider(account.getAci(),
|
||||
account.getUsername(),
|
||||
account.getAccount(),
|
||||
account.getPassword(),
|
||||
account.getDeviceId());
|
||||
final var sessionLock = new SignalSessionLock() {
|
||||
|
@ -251,7 +251,7 @@ public class ManagerImpl implements Manager {
|
|||
|
||||
@Override
|
||||
public String getSelfNumber() {
|
||||
return account.getUsername();
|
||||
return account.getAccount();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -285,7 +285,7 @@ public class ManagerImpl implements Manager {
|
|||
public Map<String, Pair<String, UUID>> areUsersRegistered(Set<String> numbers) throws IOException {
|
||||
Map<String, String> canonicalizedNumbers = numbers.stream().collect(Collectors.toMap(n -> n, n -> {
|
||||
try {
|
||||
return PhoneNumberFormatter.formatNumber(n, account.getUsername());
|
||||
return PhoneNumberFormatter.formatNumber(n, account.getAccount());
|
||||
} catch (InvalidNumberException e) {
|
||||
return "";
|
||||
}
|
||||
|
@ -1265,7 +1265,7 @@ public class ManagerImpl implements Manager {
|
|||
/**
|
||||
* Trust this the identity with this fingerprint
|
||||
*
|
||||
* @param recipient username of the identity
|
||||
* @param recipient account of the identity
|
||||
* @param fingerprint Fingerprint
|
||||
*/
|
||||
@Override
|
||||
|
@ -1282,7 +1282,7 @@ public class ManagerImpl implements Manager {
|
|||
/**
|
||||
* Trust this the identity with this safety number
|
||||
*
|
||||
* @param recipient username of the identity
|
||||
* @param recipient account of the identity
|
||||
* @param safetyNumber Safety number
|
||||
*/
|
||||
@Override
|
||||
|
@ -1299,7 +1299,7 @@ public class ManagerImpl implements Manager {
|
|||
/**
|
||||
* Trust this the identity with this scannable safety number
|
||||
*
|
||||
* @param recipient username of the identity
|
||||
* @param recipient account of the identity
|
||||
* @param safetyNumber Scannable safety number
|
||||
*/
|
||||
@Override
|
||||
|
@ -1316,7 +1316,7 @@ public class ManagerImpl implements Manager {
|
|||
/**
|
||||
* Trust all keys of this identity without verification
|
||||
*
|
||||
* @param recipient username of the identity
|
||||
* @param recipient account of the identity
|
||||
*/
|
||||
@Override
|
||||
public boolean trustIdentityAllKeys(RecipientIdentifier.Single recipient) {
|
||||
|
|
|
@ -22,7 +22,7 @@ public interface MultiAccountManager extends AutoCloseable {
|
|||
|
||||
ProvisioningManager getNewProvisioningManager();
|
||||
|
||||
RegistrationManager getNewRegistrationManager(String username) throws IOException;
|
||||
RegistrationManager getNewRegistrationManager(String account) throws IOException;
|
||||
|
||||
@Override
|
||||
void close();
|
||||
|
|
|
@ -88,7 +88,7 @@ public class RegistrationManager implements Closeable {
|
|||
this.accountManager = new SignalServiceAccountManager(serviceEnvironmentConfig.getSignalServiceConfiguration(),
|
||||
new DynamicCredentialsProvider(
|
||||
// Using empty UUID, because registering doesn't work otherwise
|
||||
null, account.getUsername(), account.getPassword(), SignalServiceAddress.DEFAULT_DEVICE_ID),
|
||||
null, account.getAccount(), account.getPassword(), SignalServiceAddress.DEFAULT_DEVICE_ID),
|
||||
userAgent,
|
||||
groupsV2Operations,
|
||||
ServiceConfig.AUTOMATIC_NETWORK_RETRY);
|
||||
|
@ -142,7 +142,7 @@ public class RegistrationManager implements Closeable {
|
|||
try {
|
||||
final var accountManager = new SignalServiceAccountManager(serviceEnvironmentConfig.getSignalServiceConfiguration(),
|
||||
new DynamicCredentialsProvider(account.getAci(),
|
||||
account.getUsername(),
|
||||
account.getAccount(),
|
||||
account.getPassword(),
|
||||
account.getDeviceId()),
|
||||
userAgent,
|
||||
|
|
|
@ -195,7 +195,7 @@ public class StorageHelper {
|
|||
return;
|
||||
}
|
||||
|
||||
if (!accountRecord.getE164().equals(account.getUsername())) {
|
||||
if (!accountRecord.getE164().equals(account.getAccount())) {
|
||||
// TODO implement changed number handling
|
||||
}
|
||||
|
||||
|
|
|
@ -77,7 +77,7 @@ public class SignalAccount implements Closeable {
|
|||
private final FileChannel fileChannel;
|
||||
private final FileLock lock;
|
||||
|
||||
private String username;
|
||||
private String account;
|
||||
private ACI aci;
|
||||
private String encryptedDeviceName;
|
||||
private int deviceId = SignalServiceAddress.DEFAULT_DEVICE_ID;
|
||||
|
@ -116,21 +116,21 @@ public class SignalAccount implements Closeable {
|
|||
}
|
||||
|
||||
public static SignalAccount load(
|
||||
File dataPath, String username, boolean waitForLock, final TrustNewIdentity trustNewIdentity
|
||||
File dataPath, String account, boolean waitForLock, final TrustNewIdentity trustNewIdentity
|
||||
) throws IOException {
|
||||
final var fileName = getFileName(dataPath, username);
|
||||
final var fileName = getFileName(dataPath, account);
|
||||
final var pair = openFileChannel(fileName, waitForLock);
|
||||
try {
|
||||
var account = new SignalAccount(pair.first(), pair.second());
|
||||
account.load(dataPath, trustNewIdentity);
|
||||
account.migrateLegacyConfigs();
|
||||
var signalAccount = new SignalAccount(pair.first(), pair.second());
|
||||
signalAccount.load(dataPath, trustNewIdentity);
|
||||
signalAccount.migrateLegacyConfigs();
|
||||
|
||||
if (!username.equals(account.getUsername())) {
|
||||
throw new IOException("Username in account file doesn't match expected number: "
|
||||
+ account.getUsername());
|
||||
if (!account.equals(signalAccount.getAccount())) {
|
||||
throw new IOException("Number in account file doesn't match expected number: "
|
||||
+ signalAccount.getAccount());
|
||||
}
|
||||
|
||||
return account;
|
||||
return signalAccount;
|
||||
} catch (Throwable e) {
|
||||
pair.second().close();
|
||||
pair.first().close();
|
||||
|
@ -140,37 +140,37 @@ public class SignalAccount implements Closeable {
|
|||
|
||||
public static SignalAccount create(
|
||||
File dataPath,
|
||||
String username,
|
||||
String account,
|
||||
IdentityKeyPair identityKey,
|
||||
int registrationId,
|
||||
ProfileKey profileKey,
|
||||
final TrustNewIdentity trustNewIdentity
|
||||
) throws IOException {
|
||||
IOUtils.createPrivateDirectories(dataPath);
|
||||
var fileName = getFileName(dataPath, username);
|
||||
var fileName = getFileName(dataPath, account);
|
||||
if (!fileName.exists()) {
|
||||
IOUtils.createPrivateFile(fileName);
|
||||
}
|
||||
|
||||
final var pair = openFileChannel(fileName, true);
|
||||
var account = new SignalAccount(pair.first(), pair.second());
|
||||
var signalAccount = new SignalAccount(pair.first(), pair.second());
|
||||
|
||||
account.username = username;
|
||||
account.profileKey = profileKey;
|
||||
signalAccount.account = account;
|
||||
signalAccount.profileKey = profileKey;
|
||||
|
||||
account.initStores(dataPath, identityKey, registrationId, trustNewIdentity);
|
||||
account.groupStore = new GroupStore(getGroupCachePath(dataPath, username),
|
||||
account.recipientStore,
|
||||
account::saveGroupStore);
|
||||
account.stickerStore = new StickerStore(account::saveStickerStore);
|
||||
account.configurationStore = new ConfigurationStore(account::saveConfigurationStore);
|
||||
signalAccount.initStores(dataPath, identityKey, registrationId, trustNewIdentity);
|
||||
signalAccount.groupStore = new GroupStore(getGroupCachePath(dataPath, account),
|
||||
signalAccount.recipientStore,
|
||||
signalAccount::saveGroupStore);
|
||||
signalAccount.stickerStore = new StickerStore(signalAccount::saveStickerStore);
|
||||
signalAccount.configurationStore = new ConfigurationStore(signalAccount::saveConfigurationStore);
|
||||
|
||||
account.registered = false;
|
||||
signalAccount.registered = false;
|
||||
|
||||
account.migrateLegacyConfigs();
|
||||
account.save();
|
||||
signalAccount.migrateLegacyConfigs();
|
||||
signalAccount.save();
|
||||
|
||||
return account;
|
||||
return signalAccount;
|
||||
}
|
||||
|
||||
private void initStores(
|
||||
|
@ -179,18 +179,18 @@ public class SignalAccount implements Closeable {
|
|||
final int registrationId,
|
||||
final TrustNewIdentity trustNewIdentity
|
||||
) throws IOException {
|
||||
recipientStore = RecipientStore.load(getRecipientsStoreFile(dataPath, username), this::mergeRecipients);
|
||||
recipientStore = RecipientStore.load(getRecipientsStoreFile(dataPath, account), this::mergeRecipients);
|
||||
|
||||
preKeyStore = new PreKeyStore(getPreKeysPath(dataPath, username));
|
||||
signedPreKeyStore = new SignedPreKeyStore(getSignedPreKeysPath(dataPath, username));
|
||||
sessionStore = new SessionStore(getSessionsPath(dataPath, username), recipientStore);
|
||||
identityKeyStore = new IdentityKeyStore(getIdentitiesPath(dataPath, username),
|
||||
preKeyStore = new PreKeyStore(getPreKeysPath(dataPath, account));
|
||||
signedPreKeyStore = new SignedPreKeyStore(getSignedPreKeysPath(dataPath, account));
|
||||
sessionStore = new SessionStore(getSessionsPath(dataPath, account), recipientStore);
|
||||
identityKeyStore = new IdentityKeyStore(getIdentitiesPath(dataPath, account),
|
||||
recipientStore,
|
||||
identityKey,
|
||||
registrationId,
|
||||
trustNewIdentity);
|
||||
senderKeyStore = new SenderKeyStore(getSharedSenderKeysFile(dataPath, username),
|
||||
getSenderKeysPath(dataPath, username),
|
||||
senderKeyStore = new SenderKeyStore(getSharedSenderKeysFile(dataPath, account),
|
||||
getSenderKeysPath(dataPath, account),
|
||||
recipientStore::resolveRecipientAddress,
|
||||
recipientStore);
|
||||
signalProtocolStore = new SignalProtocolStore(preKeyStore,
|
||||
|
@ -200,12 +200,12 @@ public class SignalAccount implements Closeable {
|
|||
senderKeyStore,
|
||||
this::isMultiDevice);
|
||||
|
||||
messageCache = new MessageCache(getMessageCachePath(dataPath, username));
|
||||
messageCache = new MessageCache(getMessageCachePath(dataPath, account));
|
||||
}
|
||||
|
||||
public static SignalAccount createOrUpdateLinkedAccount(
|
||||
File dataPath,
|
||||
String username,
|
||||
String account,
|
||||
ACI aci,
|
||||
String password,
|
||||
String encryptedDeviceName,
|
||||
|
@ -216,10 +216,10 @@ public class SignalAccount implements Closeable {
|
|||
final TrustNewIdentity trustNewIdentity
|
||||
) throws IOException {
|
||||
IOUtils.createPrivateDirectories(dataPath);
|
||||
var fileName = getFileName(dataPath, username);
|
||||
var fileName = getFileName(dataPath, account);
|
||||
if (!fileName.exists()) {
|
||||
return createLinkedAccount(dataPath,
|
||||
username,
|
||||
account,
|
||||
aci,
|
||||
password,
|
||||
encryptedDeviceName,
|
||||
|
@ -230,13 +230,13 @@ public class SignalAccount implements Closeable {
|
|||
trustNewIdentity);
|
||||
}
|
||||
|
||||
final var account = load(dataPath, username, true, trustNewIdentity);
|
||||
account.setProvisioningData(username, aci, password, encryptedDeviceName, deviceId, profileKey);
|
||||
account.recipientStore.resolveRecipientTrusted(account.getSelfAddress());
|
||||
account.sessionStore.archiveAllSessions();
|
||||
account.senderKeyStore.deleteAll();
|
||||
account.clearAllPreKeys();
|
||||
return account;
|
||||
final var signalAccount = load(dataPath, account, true, trustNewIdentity);
|
||||
signalAccount.setProvisioningData(account, aci, password, encryptedDeviceName, deviceId, profileKey);
|
||||
signalAccount.recipientStore.resolveRecipientTrusted(signalAccount.getSelfAddress());
|
||||
signalAccount.sessionStore.archiveAllSessions();
|
||||
signalAccount.senderKeyStore.deleteAll();
|
||||
signalAccount.clearAllPreKeys();
|
||||
return signalAccount;
|
||||
}
|
||||
|
||||
private void clearAllPreKeys() {
|
||||
|
@ -249,7 +249,7 @@ public class SignalAccount implements Closeable {
|
|||
|
||||
private static SignalAccount createLinkedAccount(
|
||||
File dataPath,
|
||||
String username,
|
||||
String account,
|
||||
ACI aci,
|
||||
String password,
|
||||
String encryptedDeviceName,
|
||||
|
@ -259,37 +259,37 @@ public class SignalAccount implements Closeable {
|
|||
ProfileKey profileKey,
|
||||
final TrustNewIdentity trustNewIdentity
|
||||
) throws IOException {
|
||||
var fileName = getFileName(dataPath, username);
|
||||
var fileName = getFileName(dataPath, account);
|
||||
IOUtils.createPrivateFile(fileName);
|
||||
|
||||
final var pair = openFileChannel(fileName, true);
|
||||
var account = new SignalAccount(pair.first(), pair.second());
|
||||
var signalAccount = new SignalAccount(pair.first(), pair.second());
|
||||
|
||||
account.setProvisioningData(username, aci, password, encryptedDeviceName, deviceId, profileKey);
|
||||
signalAccount.setProvisioningData(account, aci, password, encryptedDeviceName, deviceId, profileKey);
|
||||
|
||||
account.initStores(dataPath, identityKey, registrationId, trustNewIdentity);
|
||||
account.groupStore = new GroupStore(getGroupCachePath(dataPath, username),
|
||||
account.recipientStore,
|
||||
account::saveGroupStore);
|
||||
account.stickerStore = new StickerStore(account::saveStickerStore);
|
||||
account.configurationStore = new ConfigurationStore(account::saveConfigurationStore);
|
||||
signalAccount.initStores(dataPath, identityKey, registrationId, trustNewIdentity);
|
||||
signalAccount.groupStore = new GroupStore(getGroupCachePath(dataPath, account),
|
||||
signalAccount.recipientStore,
|
||||
signalAccount::saveGroupStore);
|
||||
signalAccount.stickerStore = new StickerStore(signalAccount::saveStickerStore);
|
||||
signalAccount.configurationStore = new ConfigurationStore(signalAccount::saveConfigurationStore);
|
||||
|
||||
account.recipientStore.resolveRecipientTrusted(account.getSelfAddress());
|
||||
account.migrateLegacyConfigs();
|
||||
account.save();
|
||||
signalAccount.recipientStore.resolveRecipientTrusted(signalAccount.getSelfAddress());
|
||||
signalAccount.migrateLegacyConfigs();
|
||||
signalAccount.save();
|
||||
|
||||
return account;
|
||||
return signalAccount;
|
||||
}
|
||||
|
||||
private void setProvisioningData(
|
||||
final String username,
|
||||
final String account,
|
||||
final ACI aci,
|
||||
final String password,
|
||||
final String encryptedDeviceName,
|
||||
final int deviceId,
|
||||
final ProfileKey profileKey
|
||||
) {
|
||||
this.username = username;
|
||||
this.account = account;
|
||||
this.aci = aci;
|
||||
this.password = password;
|
||||
this.profileKey = profileKey;
|
||||
|
@ -324,12 +324,12 @@ public class SignalAccount implements Closeable {
|
|||
senderKeyStore.mergeRecipients(recipientId, toBeMergedRecipientId);
|
||||
}
|
||||
|
||||
public static File getFileName(File dataPath, String username) {
|
||||
return new File(dataPath, username);
|
||||
public static File getFileName(File dataPath, String account) {
|
||||
return new File(dataPath, account);
|
||||
}
|
||||
|
||||
private static File getUserPath(final File dataPath, final String username) {
|
||||
final var path = new File(dataPath, username + ".d");
|
||||
private static File getUserPath(final File dataPath, final String account) {
|
||||
final var path = new File(dataPath, account + ".d");
|
||||
try {
|
||||
IOUtils.createPrivateDirectories(path);
|
||||
} catch (IOException e) {
|
||||
|
@ -338,47 +338,47 @@ public class SignalAccount implements Closeable {
|
|||
return path;
|
||||
}
|
||||
|
||||
private static File getMessageCachePath(File dataPath, String username) {
|
||||
return new File(getUserPath(dataPath, username), "msg-cache");
|
||||
private static File getMessageCachePath(File dataPath, String account) {
|
||||
return new File(getUserPath(dataPath, account), "msg-cache");
|
||||
}
|
||||
|
||||
private static File getGroupCachePath(File dataPath, String username) {
|
||||
return new File(getUserPath(dataPath, username), "group-cache");
|
||||
private static File getGroupCachePath(File dataPath, String account) {
|
||||
return new File(getUserPath(dataPath, account), "group-cache");
|
||||
}
|
||||
|
||||
private static File getPreKeysPath(File dataPath, String username) {
|
||||
return new File(getUserPath(dataPath, username), "pre-keys");
|
||||
private static File getPreKeysPath(File dataPath, String account) {
|
||||
return new File(getUserPath(dataPath, account), "pre-keys");
|
||||
}
|
||||
|
||||
private static File getSignedPreKeysPath(File dataPath, String username) {
|
||||
return new File(getUserPath(dataPath, username), "signed-pre-keys");
|
||||
private static File getSignedPreKeysPath(File dataPath, String account) {
|
||||
return new File(getUserPath(dataPath, account), "signed-pre-keys");
|
||||
}
|
||||
|
||||
private static File getIdentitiesPath(File dataPath, String username) {
|
||||
return new File(getUserPath(dataPath, username), "identities");
|
||||
private static File getIdentitiesPath(File dataPath, String account) {
|
||||
return new File(getUserPath(dataPath, account), "identities");
|
||||
}
|
||||
|
||||
private static File getSessionsPath(File dataPath, String username) {
|
||||
return new File(getUserPath(dataPath, username), "sessions");
|
||||
private static File getSessionsPath(File dataPath, String account) {
|
||||
return new File(getUserPath(dataPath, account), "sessions");
|
||||
}
|
||||
|
||||
private static File getSenderKeysPath(File dataPath, String username) {
|
||||
return new File(getUserPath(dataPath, username), "sender-keys");
|
||||
private static File getSenderKeysPath(File dataPath, String account) {
|
||||
return new File(getUserPath(dataPath, account), "sender-keys");
|
||||
}
|
||||
|
||||
private static File getSharedSenderKeysFile(File dataPath, String username) {
|
||||
return new File(getUserPath(dataPath, username), "shared-sender-keys-store");
|
||||
private static File getSharedSenderKeysFile(File dataPath, String account) {
|
||||
return new File(getUserPath(dataPath, account), "shared-sender-keys-store");
|
||||
}
|
||||
|
||||
private static File getRecipientsStoreFile(File dataPath, String username) {
|
||||
return new File(getUserPath(dataPath, username), "recipients-store");
|
||||
private static File getRecipientsStoreFile(File dataPath, String account) {
|
||||
return new File(getUserPath(dataPath, account), "recipients-store");
|
||||
}
|
||||
|
||||
public static boolean userExists(File dataPath, String username) {
|
||||
if (username == null) {
|
||||
public static boolean userExists(File dataPath, String account) {
|
||||
if (account == null) {
|
||||
return false;
|
||||
}
|
||||
var f = getFileName(dataPath, username);
|
||||
var f = getFileName(dataPath, account);
|
||||
return !(!f.exists() || f.isDirectory());
|
||||
}
|
||||
|
||||
|
@ -400,7 +400,7 @@ public class SignalAccount implements Closeable {
|
|||
}
|
||||
}
|
||||
|
||||
username = Utils.getNotNullNode(rootNode, "username").asText();
|
||||
account = Utils.getNotNullNode(rootNode, "username").asText();
|
||||
password = Utils.getNotNullNode(rootNode, "password").asText();
|
||||
registered = Utils.getNotNullNode(rootNode, "registered").asBoolean();
|
||||
if (rootNode.hasNonNull("uuid")) {
|
||||
|
@ -483,11 +483,11 @@ public class SignalAccount implements Closeable {
|
|||
if (rootNode.hasNonNull("groupStore")) {
|
||||
groupStoreStorage = jsonProcessor.convertValue(rootNode.get("groupStore"), GroupStore.Storage.class);
|
||||
groupStore = GroupStore.fromStorage(groupStoreStorage,
|
||||
getGroupCachePath(dataPath, username),
|
||||
getGroupCachePath(dataPath, account),
|
||||
recipientStore,
|
||||
this::saveGroupStore);
|
||||
} else {
|
||||
groupStore = new GroupStore(getGroupCachePath(dataPath, username), recipientStore, this::saveGroupStore);
|
||||
groupStore = new GroupStore(getGroupCachePath(dataPath, account), recipientStore, this::saveGroupStore);
|
||||
}
|
||||
|
||||
if (rootNode.hasNonNull("stickerStore")) {
|
||||
|
@ -702,7 +702,7 @@ public class SignalAccount implements Closeable {
|
|||
synchronized (fileChannel) {
|
||||
var rootNode = jsonProcessor.createObjectNode();
|
||||
rootNode.put("version", CURRENT_STORAGE_VERSION)
|
||||
.put("username", username)
|
||||
.put("username", account)
|
||||
.put("uuid", aci == null ? null : aci.toString())
|
||||
.put("deviceName", encryptedDeviceName)
|
||||
.put("deviceId", deviceId)
|
||||
|
@ -827,8 +827,8 @@ public class SignalAccount implements Closeable {
|
|||
return messageCache;
|
||||
}
|
||||
|
||||
public String getUsername() {
|
||||
return username;
|
||||
public String getAccount() {
|
||||
return account;
|
||||
}
|
||||
|
||||
public ACI getAci() {
|
||||
|
@ -841,11 +841,11 @@ public class SignalAccount implements Closeable {
|
|||
}
|
||||
|
||||
public SignalServiceAddress getSelfAddress() {
|
||||
return new SignalServiceAddress(aci, username);
|
||||
return new SignalServiceAddress(aci, account);
|
||||
}
|
||||
|
||||
public RecipientId getSelfRecipientId() {
|
||||
return recipientStore.resolveRecipientTrusted(new RecipientAddress(aci == null ? null : aci.uuid(), username));
|
||||
return recipientStore.resolveRecipientTrusted(new RecipientAddress(aci == null ? null : aci.uuid(), account));
|
||||
}
|
||||
|
||||
public String getEncryptedDeviceName() {
|
||||
|
|
|
@ -11,11 +11,11 @@ DBus API for signal-cli - A commandline and dbus interface for the Signal messen
|
|||
|
||||
== Synopsis
|
||||
|
||||
*signal-cli* [--verbose] [--config CONFIG] [-u USERNAME] [-o {plain-text,json}] daemon [--system]
|
||||
*signal-cli* [--verbose] [--config CONFIG] [-a ACCOUNT] [-o {plain-text,json}] daemon [--system]
|
||||
|
||||
*dbus-send* [--system | --session] [--print-reply] --type=method_call --dest="org.asamk.Signal" /org/asamk/Signal[/_<phonenum>] org.asamk.Signal.<method> [string:<string argument>] [array:<type>:<array argument>]
|
||||
|
||||
Note: when daemon was started without explicit `-u USERNAME`, the `dbus-send` command requires adding the phone number in `/org/asamk/Signal/_<phonenum>`.
|
||||
Note: when daemon was started without explicit `-a ACCOUNT`, the `dbus-send` command requires adding the phone number in `/org/asamk/Signal/_<phonenum>`.
|
||||
|
||||
== Description
|
||||
|
||||
|
@ -48,7 +48,7 @@ Phone numbers always have the format +<countrycode><regional number>
|
|||
== Methods
|
||||
|
||||
=== Control methods
|
||||
These methods are available if the daemon is started anonymously (without an explicit `-u USERNAME`).
|
||||
These methods are available if the daemon is started anonymously (without an explicit `-a ACCOUNT`).
|
||||
Requests are sent to `/org/asamk/Signal`; requests related to individual accounts are sent to
|
||||
`/org/asamk/Signal/_441234567890` where the + dialing code is replaced by an underscore (_).
|
||||
Only `version()` is activated in single-account mode; the rest are disabled.
|
||||
|
@ -596,7 +596,7 @@ dbus-send --print-reply --type=method_call --dest="org.asamk.Signal" /org/asamk/
|
|||
Send a group message::
|
||||
dbus-send --session --print-reply --type=method_call --dest=org.asamk.Signal /org/asamk/Signal org.asamk.Signal.sendGroupMessage string:'The message goes here' array:string:'/path/to/attachmnt1','/path/to/attachmnt2' array:byte:139,22,72,247,116,32,170,104,205,164,207,21,248,77,185
|
||||
|
||||
Print the group name corresponding to a groupId; the daemon runs on system bus, and was started without an explicit `-u USERNAME`::
|
||||
Print the group name corresponding to a groupId; the daemon runs on system bus, and was started without an explicit `-a ACCOUNT`::
|
||||
dbus-send --system --print-reply --type=method_call --dest='org.asamk.Signal' /org/asamk/Signal/_1234567890 org.asamk.Signal.getGroupName array:byte:139,22,72,247,116,32,170,104,205,164,207,21,248,77,185
|
||||
|
||||
== Authors
|
||||
|
|
|
@ -11,7 +11,7 @@ signal-cli - A commandline and dbus interface for the Signal messenger
|
|||
|
||||
== Synopsis
|
||||
|
||||
*signal-cli* [--config CONFIG] [-h | -v | -u USERNAME | --dbus | --dbus-system] command [command-options]
|
||||
*signal-cli* [--config CONFIG] [-h | -v | -a ACCOUNT | --dbus | --dbus-system] command [command-options]
|
||||
|
||||
== Description
|
||||
|
||||
|
@ -40,7 +40,7 @@ Set the path, where to store the config.
|
|||
Make sure you have full read/write access to the given directory.
|
||||
(Default: `$XDG_DATA_HOME/signal-cli` (`$HOME/.local/share/signal-cli`))
|
||||
|
||||
*-u* USERNAME, *--username* USERNAME::
|
||||
*-a* ACCOUNT, *--account* ACCOUNT::
|
||||
Specify your phone number, that will be your identifier.
|
||||
The phone number must include the country calling code, i.e. the number must start with a "+" sign.
|
||||
|
||||
|
@ -495,7 +495,7 @@ The path of the manifest.json or a zip file containing the sticker pack you wish
|
|||
=== daemon
|
||||
|
||||
signal-cli can run in daemon mode and provides an experimental dbus interface.
|
||||
If no `-u` username is given, all local users will be exported as separate dbus
|
||||
If no `-a` account is given, all local accounts will be exported as separate dbus
|
||||
objects under the same bus name.
|
||||
|
||||
*--system*::
|
||||
|
@ -506,37 +506,37 @@ Don’t download attachments of received messages.
|
|||
== Examples
|
||||
|
||||
Register a number (with SMS verification)::
|
||||
signal-cli -u USERNAME register
|
||||
signal-cli -a ACCOUNT register
|
||||
|
||||
Verify the number using the code received via SMS or voice::
|
||||
signal-cli -u USERNAME verify CODE
|
||||
signal-cli -a ACCOUNT verify CODE
|
||||
|
||||
Send a message to one or more recipients::
|
||||
signal-cli -u USERNAME send -m "This is a message" [RECIPIENT [RECIPIENT ...]] [-a [ATTACHMENT [ATTACHMENT ...]]]
|
||||
signal-cli -a ACCOUNT send -m "This is a message" [RECIPIENT [RECIPIENT ...]] [-a [ATTACHMENT [ATTACHMENT ...]]]
|
||||
|
||||
Pipe the message content from another process::
|
||||
uname -a | signal-cli -u USERNAME send [RECIPIENT [RECIPIENT ...]]
|
||||
uname -a | signal-cli -a ACCOUNT send [RECIPIENT [RECIPIENT ...]]
|
||||
|
||||
Create a group::
|
||||
signal-cli -u USERNAME updateGroup -n "Group name" -m [MEMBER [MEMBER ...]]
|
||||
signal-cli -a ACCOUNT updateGroup -n "Group name" -m [MEMBER [MEMBER ...]]
|
||||
|
||||
Add member to a group::
|
||||
signal-cli -u USERNAME updateGroup -g GROUP_ID -m "NEW_MEMBER"
|
||||
signal-cli -a ACCOUNT updateGroup -g GROUP_ID -m "NEW_MEMBER"
|
||||
|
||||
Accept a group invitation::
|
||||
signal-cli -u USERNAME updateGroup -g GROUP_ID
|
||||
signal-cli -a ACCOUNT updateGroup -g GROUP_ID
|
||||
|
||||
Leave a group::
|
||||
signal-cli -u USERNAME quitGroup -g GROUP_ID
|
||||
signal-cli -a ACCOUNT quitGroup -g GROUP_ID
|
||||
|
||||
Send a message to a group::
|
||||
signal-cli -u USERNAME send -m "This is a message" -g GROUP_ID
|
||||
signal-cli -a ACCOUNT send -m "This is a message" -g GROUP_ID
|
||||
|
||||
Trust new key, after having verified it::
|
||||
signal-cli -u USERNAME trust -v SAFETY_NUMBER NUMBER
|
||||
signal-cli -a ACCOUNT trust -v SAFETY_NUMBER NUMBER
|
||||
|
||||
Trust new key, without having verified it. Only use this if you don't care about security::
|
||||
signal-cli -u USERNAME trust -a NUMBER
|
||||
signal-cli -a ACCOUNT trust -a NUMBER
|
||||
|
||||
== Exit codes
|
||||
* *1*: Error is probably caused and fixable by the user
|
||||
|
|
126
run_tests.sh
126
run_tests.sh
|
@ -47,13 +47,13 @@ register() {
|
|||
PIN=$2
|
||||
echo -n "Enter a captcha token (https://signalcaptchas.org/staging/challenge/generate.html): "
|
||||
read CAPTCHA
|
||||
run_main -u "$NUMBER" register --captcha "$CAPTCHA"
|
||||
run_main -a "$NUMBER" register --captcha "$CAPTCHA"
|
||||
echo -n "Enter validation code for ${NUMBER}: "
|
||||
read CODE
|
||||
if [ -z "$PIN" ]; then
|
||||
run_main -u "$NUMBER" verify "$CODE"
|
||||
run_main -a "$NUMBER" verify "$CODE"
|
||||
else
|
||||
run_main -u "$NUMBER" verify "$CODE" --pin "$PIN"
|
||||
run_main -a "$NUMBER" verify "$CODE" --pin "$PIN"
|
||||
fi
|
||||
}
|
||||
|
||||
|
@ -64,12 +64,12 @@ link() {
|
|||
mkfifo "$LINK_CODE_FILE"
|
||||
run_linked link -n "test-device" >"$LINK_CODE_FILE" &
|
||||
read LINK_CODE <"$LINK_CODE_FILE"
|
||||
run_main -u "$NUMBER" addDevice --uri "$LINK_CODE"
|
||||
run_main -a "$NUMBER" addDevice --uri "$LINK_CODE"
|
||||
wait
|
||||
run_linked -u "$NUMBER" send --note-to-self -m hi
|
||||
run_main -u "$NUMBER" receive
|
||||
run_linked -u "$NUMBER" receive
|
||||
run_main -u "$NUMBER" receive
|
||||
run_linked -a "$NUMBER" send --note-to-self -m hi
|
||||
run_main -a "$NUMBER" receive
|
||||
run_linked -a "$NUMBER" receive
|
||||
run_main -a "$NUMBER" receive
|
||||
}
|
||||
|
||||
run_main --version
|
||||
|
@ -83,12 +83,12 @@ sleep 5
|
|||
|
||||
|
||||
## DBus
|
||||
#run_main -u "$NUMBER_1" --dbus send "$NUMBER_2" -m daemon_not_running || true
|
||||
#run_main -a "$NUMBER_1" --dbus send "$NUMBER_2" -m daemon_not_running || true
|
||||
#run_main daemon &
|
||||
#DAEMON_PID=$!
|
||||
#sleep 10
|
||||
#run_main -u "$NUMBER_1" --dbus send "$NUMBER_2" -m hii
|
||||
#run_main -u "$NUMBER_2" --dbus receive
|
||||
#run_main -a "$NUMBER_1" --dbus send "$NUMBER_2" -m hii
|
||||
#run_main -a "$NUMBER_2" --dbus receive
|
||||
#kill "$DAEMON_PID"
|
||||
|
||||
|
||||
|
@ -98,8 +98,8 @@ FIFO_FILE="${PATH_MAIN}/dbus-fifo"
|
|||
rm -f "$FIFO_FILE"
|
||||
mkfifo "$FIFO_FILE"
|
||||
|
||||
run_main -u "$NUMBER_1" send "$NUMBER_2" -m hi
|
||||
run_main -u "$NUMBER_2" jsonRpc < "$FIFO_FILE" &
|
||||
run_main -a "$NUMBER_1" send "$NUMBER_2" -m hi
|
||||
run_main -a "$NUMBER_2" jsonRpc < "$FIFO_FILE" &
|
||||
|
||||
exec 3<> "$FIFO_FILE"
|
||||
echo '{"jsonrpc":"2.0","id":"id","method":"updateContact","params":{"recipient":"'"$NUMBER_1"'","name":"NUMBER_1","expiration":10}}' >&3
|
||||
|
@ -126,75 +126,75 @@ exec 3>&-
|
|||
|
||||
wait
|
||||
|
||||
run_main -u "$NUMBER_1" setPin "$TEST_PIN_1"
|
||||
run_main -u "$NUMBER_2" removePin
|
||||
run_main -a "$NUMBER_1" setPin "$TEST_PIN_1"
|
||||
run_main -a "$NUMBER_2" removePin
|
||||
|
||||
## Contacts
|
||||
run_main -u "$NUMBER_2" updateContact "$NUMBER_1" -n NUMBER_1 -e 10
|
||||
run_main -u "$NUMBER_2" block "$NUMBER_1"
|
||||
run_main -u "$NUMBER_2" unblock "$NUMBER_1"
|
||||
run_main -u "$NUMBER_2" listContacts
|
||||
run_main -a "$NUMBER_2" updateContact "$NUMBER_1" -n NUMBER_1 -e 10
|
||||
run_main -a "$NUMBER_2" block "$NUMBER_1"
|
||||
run_main -a "$NUMBER_2" unblock "$NUMBER_1"
|
||||
run_main -a "$NUMBER_2" listContacts
|
||||
|
||||
run_main -u "$NUMBER_1" send "$NUMBER_2" -m hi
|
||||
run_main -u "$NUMBER_2" receive
|
||||
run_main -u "$NUMBER_2" send "$NUMBER_1" -m hi
|
||||
run_main -u "$NUMBER_1" receive
|
||||
run_main -u "$NUMBER_2" receive
|
||||
run_main -a "$NUMBER_1" send "$NUMBER_2" -m hi
|
||||
run_main -a "$NUMBER_2" receive
|
||||
run_main -a "$NUMBER_2" send "$NUMBER_1" -m hi
|
||||
run_main -a "$NUMBER_1" receive
|
||||
run_main -a "$NUMBER_2" receive
|
||||
## Groups
|
||||
GROUP_ID=$(run_main -u "$NUMBER_1" updateGroup -n GRUPPE -a LICENSE -m "$NUMBER_1" | grep -oP '(?<=").+(?=")')
|
||||
run_main -u "$NUMBER_1" send "$NUMBER_2" -m first
|
||||
run_main -u "$NUMBER_1" updateGroup -g "$GROUP_ID" -n GRUPPE_UMB -m "$NUMBER_2" --admin "$NUMBER_2" --remove-admin "$NUMBER_2" --description DESCRIPTION --link=enabled-with-approval --set-permission-add-member=only-admins --set-permission-edit-details=only-admins -e 42
|
||||
run_main -u "$NUMBER_1" listGroups -d
|
||||
run_main -u "$NUMBER_1" --output=json listGroups -d
|
||||
run_main -u "$NUMBER_2" --verbose receive
|
||||
run_main -u "$NUMBER_2" quitGroup -g "$GROUP_ID"
|
||||
run_main -u "$NUMBER_2" listGroups -d
|
||||
run_main -u "$NUMBER_2" --output=json listGroups -d
|
||||
run_main -u "$NUMBER_1" receive
|
||||
run_main -u "$NUMBER_1" updateGroup -g "$GROUP_ID" -m "$NUMBER_2"
|
||||
run_main -u "$NUMBER_1" --verbose block -g "$GROUP_ID"
|
||||
run_main -u "$NUMBER_1" --verbose unblock -g "$GROUP_ID"
|
||||
GROUP_ID=$(run_main -a "$NUMBER_1" updateGroup -n GRUPPE -a LICENSE -m "$NUMBER_1" | grep -oP '(?<=").+(?=")')
|
||||
run_main -a "$NUMBER_1" send "$NUMBER_2" -m first
|
||||
run_main -a "$NUMBER_1" updateGroup -g "$GROUP_ID" -n GRUPPE_UMB -m "$NUMBER_2" --admin "$NUMBER_2" --remove-admin "$NUMBER_2" --description DESCRIPTION --link=enabled-with-approval --set-permission-add-member=only-admins --set-permission-edit-details=only-admins -e 42
|
||||
run_main -a "$NUMBER_1" listGroups -d
|
||||
run_main -a "$NUMBER_1" --output=json listGroups -d
|
||||
run_main -a "$NUMBER_2" --verbose receive
|
||||
run_main -a "$NUMBER_2" quitGroup -g "$GROUP_ID"
|
||||
run_main -a "$NUMBER_2" listGroups -d
|
||||
run_main -a "$NUMBER_2" --output=json listGroups -d
|
||||
run_main -a "$NUMBER_1" receive
|
||||
run_main -a "$NUMBER_1" updateGroup -g "$GROUP_ID" -m "$NUMBER_2"
|
||||
run_main -a "$NUMBER_1" --verbose block -g "$GROUP_ID"
|
||||
run_main -a "$NUMBER_1" --verbose unblock -g "$GROUP_ID"
|
||||
|
||||
## Identities
|
||||
run_main -u "$NUMBER_1" listIdentities
|
||||
run_main -u "$NUMBER_2" listIdentities
|
||||
run_main -u "$NUMBER_2" trust "$NUMBER_1" -a
|
||||
run_main -a "$NUMBER_1" listIdentities
|
||||
run_main -a "$NUMBER_2" listIdentities
|
||||
run_main -a "$NUMBER_2" trust "$NUMBER_1" -a
|
||||
|
||||
## Basic send/receive
|
||||
for OUTPUT in "plain-text" "json"; do
|
||||
run_main -u "$NUMBER_1" --output="$OUTPUT" getUserStatus "$NUMBER_1" "$NUMBER_2" "+111111111"
|
||||
run_main -u "$NUMBER_1" send "$NUMBER_2" -m hi
|
||||
run_main -u "$NUMBER_2" send "$NUMBER_1" -m hi
|
||||
run_main -u "$NUMBER_1" send -g "$GROUP_ID" -m hi -a LICENSE
|
||||
TIMESTAMP=$(uname -a | run_main -u "$NUMBER_1" send "$NUMBER_2")
|
||||
run_main -u "$NUMBER_2" sendReaction "$NUMBER_1" -e 🍀 -a "$NUMBER_1" -t "$TIMESTAMP"
|
||||
run_main -u "$NUMBER_1" remoteDelete "$NUMBER_2" -t "$TIMESTAMP"
|
||||
run_main -u "$NUMBER_2" --output="$OUTPUT" receive
|
||||
run_main -u "$NUMBER_1" --output="$OUTPUT" receive
|
||||
run_main -u "$NUMBER_1" send -e "$NUMBER_2"
|
||||
run_main -u "$NUMBER_2" --output="$OUTPUT" receive
|
||||
run_main -a "$NUMBER_1" --output="$OUTPUT" getUserStatus "$NUMBER_1" "$NUMBER_2" "+111111111"
|
||||
run_main -a "$NUMBER_1" send "$NUMBER_2" -m hi
|
||||
run_main -a "$NUMBER_2" send "$NUMBER_1" -m hi
|
||||
run_main -a "$NUMBER_1" send -g "$GROUP_ID" -m hi -a LICENSE
|
||||
TIMESTAMP=$(uname -a | run_main -a "$NUMBER_1" send "$NUMBER_2")
|
||||
run_main -a "$NUMBER_2" sendReaction "$NUMBER_1" -e 🍀 -a "$NUMBER_1" -t "$TIMESTAMP"
|
||||
run_main -a "$NUMBER_1" remoteDelete "$NUMBER_2" -t "$TIMESTAMP"
|
||||
run_main -a "$NUMBER_2" --output="$OUTPUT" receive
|
||||
run_main -a "$NUMBER_1" --output="$OUTPUT" receive
|
||||
run_main -a "$NUMBER_1" send -e "$NUMBER_2"
|
||||
run_main -a "$NUMBER_2" --output="$OUTPUT" receive
|
||||
done
|
||||
|
||||
## Profile
|
||||
run_main -u "$NUMBER_1" updateProfile --given-name=GIVEN --family-name=FAMILY --about=ABOUT --about-emoji=EMOJI --avatar=LICENSE
|
||||
run_main -a "$NUMBER_1" updateProfile --given-name=GIVEN --family-name=FAMILY --about=ABOUT --about-emoji=EMOJI --avatar=LICENSE
|
||||
|
||||
## Provisioning
|
||||
link "$NUMBER_1"
|
||||
link "$NUMBER_2"
|
||||
run_main -u "$NUMBER_1" listDevices
|
||||
run_linked -u "$NUMBER_1" sendSyncRequest
|
||||
run_main -u "$NUMBER_1" sendContacts
|
||||
run_main -a "$NUMBER_1" listDevices
|
||||
run_linked -a "$NUMBER_1" sendSyncRequest
|
||||
run_main -a "$NUMBER_1" sendContacts
|
||||
|
||||
for OUTPUT in "plain-text" "json"; do
|
||||
run_main -u "$NUMBER_1" send "$NUMBER_2" -m hi
|
||||
run_main -u "$NUMBER_2" send "$NUMBER_1" -m hi
|
||||
run_main -u "$NUMBER_2" --output="$OUTPUT" receive
|
||||
run_main -u "$NUMBER_1" --output="$OUTPUT" receive
|
||||
run_linked -u "$NUMBER_1" --output="$OUTPUT" receive
|
||||
run_main -a "$NUMBER_1" send "$NUMBER_2" -m hi
|
||||
run_main -a "$NUMBER_2" send "$NUMBER_1" -m hi
|
||||
run_main -a "$NUMBER_2" --output="$OUTPUT" receive
|
||||
run_main -a "$NUMBER_1" --output="$OUTPUT" receive
|
||||
run_linked -a "$NUMBER_1" --output="$OUTPUT" receive
|
||||
done
|
||||
|
||||
run_main -u "$NUMBER_1" removeDevice -d 2
|
||||
run_main -a "$NUMBER_1" removeDevice -d 2
|
||||
|
||||
## Unregister
|
||||
run_main -u "$NUMBER_1" unregister
|
||||
run_main -u "$NUMBER_2" unregister --delete-account
|
||||
run_main -a "$NUMBER_1" unregister
|
||||
run_main -a "$NUMBER_2" unregister --delete-account
|
||||
|
|
|
@ -13,11 +13,11 @@ public class DbusConfig {
|
|||
return getObjectPath(null);
|
||||
}
|
||||
|
||||
public static String getObjectPath(String username) {
|
||||
if (username == null) {
|
||||
public static String getObjectPath(String account) {
|
||||
if (account == null) {
|
||||
return SIGNAL_OBJECT_BASE_PATH;
|
||||
}
|
||||
|
||||
return SIGNAL_OBJECT_BASE_PATH + "/" + username.replace('+', '_');
|
||||
return SIGNAL_OBJECT_BASE_PATH + "/" + account.replace('+', '_');
|
||||
}
|
||||
}
|
||||
|
|
|
@ -49,13 +49,13 @@ public class ReceiveMessageHandler implements Manager.ReceiveMessageHandler {
|
|||
"The user’s key is untrusted, either the user has reinstalled Signal or a third party sent this message.");
|
||||
final var recipientName = e.getSender().getLegacyIdentifier();
|
||||
writer.println(
|
||||
"Use 'signal-cli -u {} listIdentities -n {}', verify the key and run 'signal-cli -u {} trust -v \"FINGER_PRINT\" {}' to mark it as trusted",
|
||||
"Use 'signal-cli -a {} listIdentities -n {}', verify the key and run 'signal-cli -a {} trust -v \"FINGER_PRINT\" {}' to mark it as trusted",
|
||||
m.getSelfNumber(),
|
||||
recipientName,
|
||||
m.getSelfNumber(),
|
||||
recipientName);
|
||||
writer.println(
|
||||
"If you don't care about security, use 'signal-cli -u {} trust -a {}' to trust it without verification",
|
||||
"If you don't care about security, use 'signal-cli -a {} trust -a {}' to trust it without verification",
|
||||
m.getSelfNumber(),
|
||||
recipientName);
|
||||
} else {
|
||||
|
|
|
@ -53,7 +53,7 @@ public class DbusSignalControlImpl implements org.asamk.SignalControl {
|
|||
) throws Error.Failure, Error.InvalidNumber {
|
||||
if (!Manager.isValidNumber(number, null)) {
|
||||
throw new SignalControl.Error.InvalidNumber(
|
||||
"Invalid username (phone number), make sure you include the country code.");
|
||||
"Invalid account (phone number), make sure you include the country code.");
|
||||
}
|
||||
try (final RegistrationManager registrationManager = c.getNewRegistrationManager(number)) {
|
||||
registrationManager.register(voiceVerification, captcha);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue