signal-mqtt - An adapter between MQTT and the JSON RPC API of signal-cli.
This project allows to send arbitrary command requests to Signal messengers and receive responses. This includes, but is not limited to, sending and receiving of text messages, quotations and emojis to Signal accounts and groups. The signal-cli documentation contains a list of all supported commands.
-
Register or link your Signal account.
-
Create a run configuration
docker-compose.yml
, e.g.:--- services: signal-mqtt: image: ckware/signal-mqtt container_name: signal-mqtt restart: unless-stopped init: true user: "nobody:nogroup" environment: MQTT_PUBLISH_OPTIONS: "-h broker -i signal-receiver" MQTT_SUBSCRIBE_OPTIONS: "-h broker -i signal-sender" volumes: - "./data:/home/.local/share/signal-cli"
-
Start a container:
$ docker-compose up -d
-
Send and receive messages via MQTT:
$ mosquitto_sub -v -h broker -t 'signal/#' & signal/in/method/receive/source_number/%2B491713920000/timestamp/1577882096000 Incoming message $ mosquitto_pub -v -h broker -t signal/out/method/send/recipient/%2B491713920000 -m 'Outgoing message' signal/out/method/send/recipient/%2B491713920000 Outgoing message
-
A phone number that is registered as a Signal account (see Registration with captcha)
-
Docker Compose
The Docker Compose documentation contains a comprehensive guide explaining several install options. On recent debian-based systems, Docker Compose may be installed by calling
$ sudo apt install docker-compose
There are two different ways to use this service:
- Send and receive complete JSON RPC messages including content and metadata.
- Send and receive simple text messages whereas metadata is part of the MQTT topic.
Incoming and outgoing JSON messages are published to a topic per direction.
Direction | Default topic | Environment variable |
---|---|---|
Send | signal/out |
MQTT_SUBSCRIBE_TOPIC |
Receive | signal/in |
MQTT_PUBLISH_TOPIC |
To send a JSON RPC command, publish the JSON message to the send topic.
Example:
$ mosquitto_pub -h broker -t signal/out -m '{"jsonrpc":"2.0","method":"send","params":{"recipient":["+491713920000"],"message":"Outgoing message"}}'
The text Outgoing message is sent to the phone.
To receive JSON RPC messages, subscribe to the receive topic.
Reception of JSON RPC messages is disabled by default.
To enable it, set MQTT_PUBLISH_JSON_RESPONSE
to true
.
You may additionally want to disable reception of messages on parameter topics
by setting MQTT_PUBLISH_TO_PARAMETER_TOPIC
to false
.
Example:
$ mosquitto_sub -v -h broker -t 'signal/#' &
# The user starts to type 'Incoming message' on the phone
signal/in {"jsonrpc":"2.0","method":"receive","params":{"envelope":{"source":"+491713920000","sourceNumber":"+491713920000","sourceUuid":"3689ed97-01b2-4fa5-8ed8-18174ad5cf15","sourceName":"Sally Sender","sourceDevice":1,"timestamp":1577882080000,"typingMessage":{"action":"STARTED","timestamp":1577882080000}},"account":"+493023125000","subscription":0}}
# The text 'Incoming message' is completed
signal/in {"jsonrpc":"2.0","method":"receive","params":{"envelope":{"source":"+491713920000","sourceNumber":"+491713920000","sourceUuid":"3689ed97-01b2-4fa5-8ed8-18174ad5cf15","sourceName":"Sally Sender","sourceDevice":1,"timestamp":1577882090000,"typingMessage":{"action":"STOPPED","timestamp":1577882090000}},"account":"+493023125000","subscription":0}}
# The message is sent to +493023125000
signal/in {"jsonrpc":"2.0","method":"receive","params":{"envelope":{"source":"+491713920000","sourceNumber":"+491713920000","sourceUuid":"3689ed97-01b2-4fa5-8ed8-18174ad5cf15","sourceName":"Sally Sender","sourceDevice":1,"timestamp":1577882096000,"dataMessage":{"timestamp":1577882096000,"message":"Incoming message","expiresInSeconds":0,"viewOnce":false}},"account":"+493023125000","subscription":0}}
$ mosquitto_pub -h broker -t signal/out/method/send/recipient/%2B491713920000 -m 'Outgoing message'
signal/out/method/send/recipient/%2B491713920000 Outgoing message
# The message was delivered to mobile phone +491713920000
signal/in {"jsonrpc":"2.0","method":"receive","params":{"envelope":{"source":"+491713920000","sourceNumber":"+491713920000","sourceUuid":"3689ed97-01b2-4fa5-8ed8-18174ad5cf15","sourceName":"Sally Sender","sourceDevice":1,"timestamp":1577882097000,"receiptMessage":{"when":1577882097000,"isDelivery":true,"isRead":false,"isViewed":false,"timestamps":[1577882098000]}},"account":"+493023125000","subscription":0}}
# The message was read on mobile phone +491713920000
signal/in {"jsonrpc":"2.0","method":"receive","params":{"envelope":{"source":"+491713920000","sourceNumber":"+491713920000","sourceUuid":"3689ed97-01b2-4fa5-8ed8-18174ad5cf15","sourceName":"Sally Sender","sourceDevice":1,"timestamp":1577882099000,"receiptMessage":{"when":1577882099000,"isDelivery":false,"isRead":true,"isViewed":false,"timestamps":[1577882098000]}},"account":"+493023125000","subscription":0}}
Parameter topics have been designed for use cases where handling of complete JSON RPC messages is not suitable.
They allow to send and receive commands in form of simple text messages, whereas all required metadata is managed in the MQTT topic.
A parameter topic has the following structure:
<PREFIX>/method/
<METHOD>[/
<PARAMETER_NAME>/
<PARAMETER_VALUE>]…
It is composed of:
- A prefix per direction,
defaulting to
signal/out
for outgoing andsignal/in
for incoming messages - The JSON RPC method, e.g.
send
orreceive
- An optional list of parameters. Each parameter is composed of a name and a value. The parameters may be in any order.
Some parameter values, e.g. an international account number or a base64 encoded group id, include special characters which are forbidden as part of an MQTT topic. Thus, all values in parameter topics are percent-encoded (aka URL-encoded).
Example: topic signal/out/method/send/recipient/%2B491713920000
contains parameter recipient with value +491713920000
.
Characters with a special meaning in the context of MQTT, base64 and percent-encoding include:
Character | Percent Encoding |
---|---|
# |
%23 |
$ |
%24 |
% |
%25 |
+ |
%2B |
, |
%2C |
/ |
%2F |
= |
%3D |
To send a JSON RPC command, publish the message text to a topic that is composed of the method and all parameters.
The following values are used in the examples:
- Account number of signal-mqtt:
+493023125000
- Phone number:
+491713920000
- Hostname of the MQTT broker:
broker
- Group Name: Admins
- Group ID:
LS0+YWRtaW5zPz8/Cg==
$ mosquitto_pub -h broker -t signal/out/method/send/recipient/%2B491713920000 -m 'Outgoing message'
The text Outgoing message is sent to the phone.
$ mosquitto_pub -h broker -t signal/out/method/send/recipient/%2B491713920000/quoteAuthor/%2B491713920001/quoteTimestamp/1577882096000 -m 'Outgoing message'
The text Outgoing message is sent to the phone, quoting a message sent from +491713920001
at timestamp 1577882096000
.
$ mosquitto_pub -h broker -t signal/out/method/send/groupId/LS0%2BYWRtaW5zPz8%2FCg%3D%3D -m 'Outgoing message'
The text Outgoing message is sent to the group Admins.
By default, the type of a parameter value is derived from its content.
When the default type does not match the expected type,
the value must be suffixed by a colon (:
) and a type-id:
<PARAMETER_NAME>/
<PERCENT_ENCODED_VALUE>:
<TYPE_ID>
Some parameters allow multiple values; these may be represented by a comma-separated list of multiple values:
<PARAMETER_NAME>/
<PERCENT_ENCODED_VALUE1>,
<PERCENT_ENCODED_VALUE2>:
<TYPE_ID>
Type Rules:
- The supported type-ids are
string
,number
,boolean
. Each type-id may be suffixed with[]
which means that the value is a list. - When a value contains digits only, its default type is
number
, otherwisestring
. - The type-id may be abbreviated.
For example,
string
,str
ands
are all valid type-ids for typestring
, - In a comma-separated value list, the type-id suffix
[]
may be omitted.
Type | type-id | JSON syntax | Topic syntax |
---|---|---|---|
String | string |
"foo" |
foo or foo:s or foo:string |
Number | number |
123 |
123 or 123:n or 123:number |
Boolean | boolean |
true |
true:b or true:boolean |
String[] | string[] |
["foo", "bar"] |
foo,bar or foo,bar:s or foo,bar:s[] or foo,bar:string[] |
["foo"] |
foo:s[] |
||
Number[] | number[] |
[123, 456] |
123,456 or 123,456:n or 123,456:n[] or 123,456:number[] |
[123] |
123:n[] |
||
Boolean[] | boolean[] |
[true, false] |
true,false:b or true,false:b[] |
[true] |
true:b[] |
Example:
- Topic:
signal/out/method/send/recipient/%2B491713920000,%2B491713920001/quoteTimestamp/1577882096000:n
- Parameter recipient contains a
string
array of the two phone numbers+491713920000
and+491713920001
; parameter quoteTimestamp is explicitely typed asnumber
(although the default would work here, too).
To receive messages on parameter topics, subscribe to the receive topic.
The following values are used in the examples:
- Account number of signal-mqtt:
+493023125000
- Phone number:
+491713920000
- Hostname of the MQTT broker:
broker
- Group Name: Admins
- Group ID:
LS0+YWRtaW5zPz8/Cg==
The text Incoming message is sent from the phone to +493023125000
.
$ mosquitto_sub -v -h broker -t signal/#
signal/in/method/receive/source_number/%2B491713920000/timestamp/1577882096000 Incoming message
The text Incoming message is sent from the phone to the group Admins.
$ mosquitto_sub -v -h broker -t signal/#
signal/in/method/receive/source_number/%2B491713920000/timestamp/1577882096000/group_id/LS0%2BYWRtaW5zPz8%2FCg%3D%3D Incoming message
The text Incoming quote is sent from the phone as quotation to the message Outgoing message from above.
$ mosquitto_sub -v -h broker -t signal/#
signal/in/method/receive/source_number/%2B491713920000/timestamp/1577882100000/quote_id/1577882096000 Incoming quote
The emoji 👍 is sent from the phone as reaction to the message Outgoing message from above.
$ mosquitto_sub -v -h broker -t signal/#
signal/in/method/receive/source_number/%2B491713920000/timestamp/1577882100000/reaction_emoji/%F0%9F%91%8D%F0%9F%8F%BB/reaction_timestamp/1577882096000 (null)
Action | Command |
---|---|
Start the container | docker-compose up -d |
Stop the container | docker-compose down |
View the logs | docker-compose logs -f |
- Syntax:
$ docker-compose run signal-mqtt signal-cli <command>
- Example:
$ docker-compose run --rm -ti signal-mqtt signal-cli listContacts Number: +491713920000 Name: Profile name: Sally Sender Blocked: false Message expiration: disabled Number: +491713920001 Name: Profile name: Rudy Receiver Blocked: false Message expiration: disabled
- Note: Most signal-cli commands require that no container is running.
The configuration is based on environment variables.
Variable | Description | Allowed values | Default | Example |
---|---|---|---|---|
MQTT_TOPIC_PREFIX |
Prefix for MQTT topics | Topic names | signal |
chats |
MQTT_PUBLISH_OPTIONS |
MQTT publish options | All options supported by mosquitto_pub except -t and -m |
none | -h broker -id signal-publisher |
MQTT_PUBLISH_TOPIC |
MQTT topic for publishing messages received from Signal | Topic names | ${MQTT_TOPIC_PREFIX}/in |
chats/from |
MQTT_PUBLISH_JSON_RESPONSE |
Publish json-rpc responses from signal-cli? | true / false |
false |
true |
MQTT_PUBLISH_TO_PARAMETER_TOPIC |
Publish received messages to a topic created from the message parameters? | true / false |
true |
false |
MQTT_SUBSCRIBE_OPTIONS |
MQTT subscribe options | All options supported by mosquitto_sub except -t and formatting-related options like -F & -N |
none | -h broker -i signal-subscriber |
MQTT_SUBSCRIBE_TOPIC |
MQTT topic to listen for messages that are sent to a Signal receiver | Topic names | ${MQTT_TOPIC_PREFIX}/out |
chats/to |
MQTT_LOG |
Enable logging via MQTT? | true / false |
false |
true |
MQTT_LOG_TOPIC |
MQTT topic to publish the log to | ${MQTT_TOPIC_PREFIX}/log |
chats/logs |
|
SIGNAL_ACCOUNT |
Phone number of the signal account | International phone number format with leading + |
Account from signal-cli configuration | +493023125000 |
LOG_JSONRPC |
Enable logging of JSON RPC messages? | true / false |
false |
true |
DEBUG |
Enable debug logging? | true / false |
false |
true |
TRACE |
Enable trace logging? | true / false |
false |
true |
-
This project is an integration of
-
It was inspired by