mirror of
https://github.com/AsamK/signal-cli
synced 2025-08-29 02:20:39 +00:00
parent
c8daef5113
commit
a7a5947a1b
2 changed files with 79 additions and 15 deletions
|
@ -13,7 +13,7 @@ signal-cli-jsonrpc - A commandline and dbus interface for the Signal messenger
|
||||||
|
|
||||||
== Synopsis
|
== Synopsis
|
||||||
|
|
||||||
*signal-cli* [--verbose] [--config CONFIG] [-a ACCOUNT] daemon [--socket] [--tcp]
|
*signal-cli* [--verbose] [--config CONFIG] [-a ACCOUNT] daemon [--socket] [--tcp] [--http]
|
||||||
|
|
||||||
*signal-cli* [--verbose] [--config CONFIG] [-a ACCOUNT] jsonRpc
|
*signal-cli* [--verbose] [--config CONFIG] [-a ACCOUNT] jsonRpc
|
||||||
|
|
||||||
|
@ -26,16 +26,16 @@ signal-cli provides a JSON-RPC based API with the `jsonRpc` and `daemon` command
|
||||||
- `jsonRpc` command accepts input on STDIN and responds on STDOUT.
|
- `jsonRpc` command accepts input on STDIN and responds on STDOUT.
|
||||||
This is intended to make it easier to embed signal-cli in other applications.
|
This is intended to make it easier to embed signal-cli in other applications.
|
||||||
|
|
||||||
`signal-cli -a _ACCOUNT_ jsonRpc`
|
`signal-cli -a _ACCOUNT_ jsonRpc` or for multi-account mode `signal-cli jsonRpc`
|
||||||
|
|
||||||
- `daemon` command provides a UNIX or TCP socket and can handle requests from multiple clients.
|
- `daemon` command provides a UNIX, TCP socket or HTTP endpoint and can handle requests from multiple clients.
|
||||||
|
|
||||||
`signal-cli -a _ACCOUNT_ daemon --socket` or for multi-account mode `signal-cli daemon --socket`
|
`signal-cli -a _ACCOUNT_ daemon --socket` or for multi-account mode `signal-cli daemon --socket`
|
||||||
|
|
||||||
== Basic usage
|
== Basic usage
|
||||||
|
|
||||||
In JSON-RPC mode, signal-cli will read requests from stdin.
|
In JSON-RPC mode, signal-cli will read requests from stdin.
|
||||||
Every requests must be a JSON object in a single line.
|
Every request must be a JSON object in a single line.
|
||||||
Requests must have a unique "id" value to be able to match the response to the corresponding request.
|
Requests must have a unique "id" value to be able to match the response to the corresponding request.
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
|
@ -48,15 +48,26 @@ From the command line:
|
||||||
|
|
||||||
`echo '{"jsonrpc":"2.0","method":"listGroups","id":"my special mark"}' | signal-cli -u +33123456789 jsonRpc`
|
`echo '{"jsonrpc":"2.0","method":"listGroups","id":"my special mark"}' | signal-cli -u +33123456789 jsonRpc`
|
||||||
|
|
||||||
Like in dbus daemon mode, messages are automatically received in jsonRpc mode.
|
Like in dbus daemon mode, messages are automatically received in jsonRpc mode (`--receive-mode=on-start`).
|
||||||
Incoming messages are sent as JSON-RPC notifications.
|
Incoming messages are sent as JSON-RPC notifications.
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
|
|
||||||
`{"jsonrpc":"2.0","method":"receive","params":{"envelope":{"source":"+33123456789","sourceNumber":"+33123456789","sourceUuid":"uuid","sourceName":"name","sourceDevice":1,"timestamp":1631458508784,"dataMessage":{"timestamp":1631458508784,"message":"foobar","expiresInSeconds":0,"viewOnce":false,"mentions":[],"attachments":[],"contacts":[]}}}}`
|
`{"jsonrpc":"2.0","method":"receive","params":{"envelope":{"source":"+33123456789","sourceNumber":"+33123456789","sourceUuid":"uuid","sourceName":"name","sourceDevice":1,"timestamp":1631458508784,"dataMessage":{"timestamp":1631458508784,"message":"foobar","expiresInSeconds":0,"viewOnce":false,"mentions":[],"attachments":[],"contacts":[]}}}}`
|
||||||
|
|
||||||
=== Multi-account daemon mode
|
In order to not miss messages, automatic receiving of messages can be disabled with the `--receive-mode=manual` parameter.
|
||||||
When the daemon command is started without an account parameter (-a), signal-cli will provide all local accounts and additional commands to register and link new accounts.
|
|
||||||
|
REQUEST: `{"jsonrpc":"2.0","id":"id","method":"subscribeReceive"}`
|
||||||
|
|
||||||
|
RESPONSE: `{"jsonrpc":"2.0","result":0,"id":"id"}`
|
||||||
|
|
||||||
|
Messages are then sent similar to the automatic mode, but wrapped in a subscription response object:
|
||||||
|
|
||||||
|
`{"jsonrpc":"2.0","method":"receive","params":{"subscription":0,"result":{"envelope":{"source":"+33123456789","sourceNumber":"+33123456789","sourceUuid":"uuid","sourceName":"name","sourceDevice":2,"timestamp":1693064367769,"syncMessage":{"sentMessage":{"destination":"+33123456789","destinationNumber":"+33123456789","destinationUuid":"uuid","timestamp":1693064367769,"message":"j","expiresInSeconds":0,"viewOnce":false}}},"account":"+33123456789"}}}`
|
||||||
|
|
||||||
|
=== Multi-account mode
|
||||||
|
|
||||||
|
When the daemon/jsonRpc command is started without an account parameter (-a), signal-cli will provide all local accounts and additional commands to register (`register`) and link (`startLink`, `finishLink`) new accounts.
|
||||||
|
|
||||||
In multi-account mode, requests for a single account require an additional `account` param.
|
In multi-account mode, requests for a single account require an additional `account` param.
|
||||||
|
|
||||||
|
@ -79,10 +90,10 @@ The `method` field is the command name and the parameters can be sent as the `pa
|
||||||
|
|
||||||
=== Additional JSON-RPC commands
|
=== Additional JSON-RPC commands
|
||||||
|
|
||||||
For receiving message additional commands are provided in JSON-RPC mode with `--receive-mode=manual`.
|
|
||||||
|
|
||||||
==== subscribeReceive
|
==== subscribeReceive
|
||||||
|
|
||||||
|
For receiving message with `--receive-mode=manual` parameter.
|
||||||
|
|
||||||
Tells the daemon to start receiving messages, returns the subscription id as a single integer value in the result.
|
Tells the daemon to start receiving messages, returns the subscription id as a single integer value in the result.
|
||||||
|
|
||||||
==== unsubscribeReceive
|
==== unsubscribeReceive
|
||||||
|
@ -93,17 +104,51 @@ Params:
|
||||||
|
|
||||||
- `subscription`: the subscription id returned by `subscribeReceive`
|
- `subscription`: the subscription id returned by `subscribeReceive`
|
||||||
|
|
||||||
|
==== startLink
|
||||||
|
|
||||||
|
Starts the provisioning for a new linked account.
|
||||||
|
Responds with a URI that can be used with the `addDevice` signal-cli command or encoded as a QR-code and scanned with a mobile phone.
|
||||||
|
The URI is only valid for a short amount of time.
|
||||||
|
|
||||||
|
REQUEST: `{"jsonrpc":"2.0","method":"startLink","id":"5"}`
|
||||||
|
|
||||||
|
RESPONSE: `{"jsonrpc":"2.0","result":{"deviceLinkUri":"sgnl://linkdevice?uuid=X&pub_key=X"},"id":"5"}`
|
||||||
|
|
||||||
|
==== finishLink
|
||||||
|
|
||||||
|
Finish provisioning of a new linked account.
|
||||||
|
Can be called immediately after `startLink`, it will wait for a response from the primary device.
|
||||||
|
|
||||||
|
Params:
|
||||||
|
|
||||||
|
- `deviceLinkUri`: the URI returned by `startLink`
|
||||||
|
- `deviceName`: (optional) the name for the new linked device
|
||||||
|
|
||||||
|
REQUEST: `{"jsonrpc":"2.0","method":"finishLink","id":"6","params":{"deviceLinkUri":"sgnl://linkdevice?uuid=X&pub_key=X","deviceName":"new-name"}}`
|
||||||
|
|
||||||
|
RESPONSE: `{"jsonrpc":"2.0","result":{"deviceLinkUri":"sgnl://linkdevice?uuid=X&pub_key=X"},"id":"6"}`
|
||||||
|
|
||||||
== Examples
|
== Examples
|
||||||
|
|
||||||
REQUEST: `{"jsonrpc":"2.0","method":"listGroups","id":"5"}` RESPONSE: `{"jsonrpc":"2.0","result":[...],"id":"5"}`
|
REQUEST: `{"jsonrpc":"2.0","method":"listGroups","id":"5"}`
|
||||||
|
|
||||||
REQUEST: `{"jsonrpc":"2.0","method":"send","params":{"recipient":["+YYY"],"message":"MESSAGE"},"id":4}` RESPONSE: `{"jsonrpc":"2.0","result":{"timestamp":999},"id":4}`
|
RESPONSE: `{"jsonrpc":"2.0","result":[...],"id":"5"}`
|
||||||
|
|
||||||
REQUEST: `{"jsonrpc":"2.0","method":"updateGroup","params":{"groupId":"GROUP_ID=","name":"new group name","members":["+ZZZ"],"link":"enabledWithApproval","setPermissionEditDetails":"only-admins"},"id":"someId"}` RESPONSE: `{"jsonrpc":"2.0","result":{"timestamp":9999},"id":"someId"}`
|
REQUEST: `{"jsonrpc":"2.0","method":"send","params":{"recipient":["+YYY"],"message":"MESSAGE"},"id":4}`
|
||||||
|
|
||||||
REQUEST: `{"jsonrpc":"2.0","method":"sendSyncRequest","id":9}` RESPONSE: `{"jsonrpc":"2.0","result":{},"id":9}`
|
RESPONSE: `{"jsonrpc":"2.0","result":{"timestamp":999},"id":4}`
|
||||||
|
|
||||||
REQUEST: `{"jsonrpc":"2.0"}` RESPONSE: `{"jsonrpc":"2.0","error":{"code":-32600,"message":"method field must be set","data":null},"id":null}`
|
REQUEST: `{"jsonrpc":"2.0","method":"updateGroup","params":{"groupId":"GROUP_ID=","name":"new group name","members":["+ZZZ"],"link":"enabledWithApproval","setPermissionEditDetails":"only-admins"},"id":"someId"}`
|
||||||
|
|
||||||
|
RESPONSE: `{"jsonrpc":"2.0","result":{"timestamp":9999},"id":"someId"}`
|
||||||
|
|
||||||
|
REQUEST: `{"jsonrpc":"2.0","method":"sendSyncRequest","id":9}`
|
||||||
|
|
||||||
|
RESPONSE: `{"jsonrpc":"2.0","result":{},"id":9}`
|
||||||
|
|
||||||
|
REQUEST: `{"jsonrpc":"2.0"}`
|
||||||
|
|
||||||
|
RESPONSE: `{"jsonrpc":"2.0","error":{"code":-32600,"message":"method field must be set","data":null},"id":null}`
|
||||||
|
|
||||||
== Authors
|
== Authors
|
||||||
|
|
||||||
|
|
|
@ -8,6 +8,7 @@ import org.asamk.signal.OutputType;
|
||||||
import org.asamk.signal.commands.exceptions.CommandException;
|
import org.asamk.signal.commands.exceptions.CommandException;
|
||||||
import org.asamk.signal.jsonrpc.SignalJsonRpcDispatcherHandler;
|
import org.asamk.signal.jsonrpc.SignalJsonRpcDispatcherHandler;
|
||||||
import org.asamk.signal.manager.Manager;
|
import org.asamk.signal.manager.Manager;
|
||||||
|
import org.asamk.signal.manager.MultiAccountManager;
|
||||||
import org.asamk.signal.manager.api.ReceiveConfig;
|
import org.asamk.signal.manager.api.ReceiveConfig;
|
||||||
import org.asamk.signal.output.JsonWriter;
|
import org.asamk.signal.output.JsonWriter;
|
||||||
import org.asamk.signal.output.OutputWriter;
|
import org.asamk.signal.output.OutputWriter;
|
||||||
|
@ -19,7 +20,7 @@ import java.io.InputStreamReader;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.function.Supplier;
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
public class JsonRpcDispatcherCommand implements LocalCommand {
|
public class JsonRpcDispatcherCommand implements LocalCommand, MultiLocalCommand {
|
||||||
|
|
||||||
private final static Logger logger = LoggerFactory.getLogger(JsonRpcDispatcherCommand.class);
|
private final static Logger logger = LoggerFactory.getLogger(JsonRpcDispatcherCommand.class);
|
||||||
|
|
||||||
|
@ -68,6 +69,24 @@ public class JsonRpcDispatcherCommand implements LocalCommand {
|
||||||
handler.handleConnection(m);
|
handler.handleConnection(m);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void handleCommand(
|
||||||
|
final Namespace ns, final MultiAccountManager c, final OutputWriter outputWriter
|
||||||
|
) throws CommandException {
|
||||||
|
final var receiveMode = ns.<ReceiveMode>get("receive-mode");
|
||||||
|
final var receiveConfig = getReceiveConfig(ns);
|
||||||
|
c.getManagers().forEach(m -> m.setReceiveConfig(receiveConfig));
|
||||||
|
c.addOnManagerAddedHandler(m -> m.setReceiveConfig(receiveConfig));
|
||||||
|
|
||||||
|
final var jsonOutputWriter = (JsonWriter) outputWriter;
|
||||||
|
final var lineSupplier = getLineSupplier();
|
||||||
|
|
||||||
|
final var handler = new SignalJsonRpcDispatcherHandler(jsonOutputWriter,
|
||||||
|
lineSupplier,
|
||||||
|
receiveMode == ReceiveMode.MANUAL);
|
||||||
|
handler.handleConnection(c);
|
||||||
|
}
|
||||||
|
|
||||||
private static ReceiveConfig getReceiveConfig(final Namespace ns) {
|
private static ReceiveConfig getReceiveConfig(final Namespace ns) {
|
||||||
final var ignoreAttachments = Boolean.TRUE.equals(ns.getBoolean("ignore-attachments"));
|
final var ignoreAttachments = Boolean.TRUE.equals(ns.getBoolean("ignore-attachments"));
|
||||||
final var ignoreStories = Boolean.TRUE.equals(ns.getBoolean("ignore-stories"));
|
final var ignoreStories = Boolean.TRUE.equals(ns.getBoolean("ignore-stories"));
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue