Install Java 17
Ubuntu:
sudo add-apt-repository ppa:linuxuprising/java -y
sudo apt update
sudo apt-get install sudo apt install openjdk-21-jre
sudo update-java-alternatives -s java-1.21.0-openjdk-arm64
Install Signal-cli
Java
Currently I use JRE version of Signal CLI because native one stopped working on
my server: sudo apt install signal-cli-jre
Native (old)
Download latest version directly from releases: https://github.com/AsamK/signal-cli/releases.
Extract it and try to run signal-cli -u [PHONE NUMBER] receive
.
If libsignal
fails to load because architectures don't match, go to https://github.com/exquo/signal-libs-build/releases or https://gitlab.com/packaging/libsignal-client/.
Short version of Signal-cli guide https://github.com/AsamK/signal-cli/wiki/Provide-native-lib-for-libsignal:
Choose your architecture and download latest version (dpkg --print-architecture
).
Go to signal-cli/lib
, seecheck the exact version, remove included library and add downloaded one:
zip -d libsignal-client-*.jar libsignal_jni.so
zip -u libsignal-client-*.jar libsignal_jni.so
Log in to Signal
As main device (not tested!)
signal-cli --config /var/lib/signal-cli -u [PHONE NUMBER] register
signal-cli --config /var/lib/signal-cli -u [PHONE NUMBER] verify [CODE FROM SMS]
As secondary device
signal-cli --config /var/lib/signal-cli link -n "[DEVICE NAME]"
Copy printed link, paste it into QR generator and scan using Signal app on mobile.
Write bot (recommended, JSON RPC)
import asyncio
import json
SIGNAL_COMMAND = "signal-cli -u +xxxYOURPHONENUMBER --output=json jsonRpc"
mid = 1
async def send_msg(method, data):
global mid, proc
mid = mid + 1
req = {"jsonrpc":"2.0", "method": method, "params": data, id: mid}
proc.stdin.write((json.dumps(req) + "\n").encode("utf-8"))
await proc.stdin.drain()
async def main():
global proc
proc = await asyncio.create_subprocess_exec(
*SIGNAL_COMMAND.split(" "),
stdin=asyncio.subprocess.PIPE,
stdout=asyncio.subprocess.PIPE,
)
while True:
line = await proc.stdout.readline()
if not line:
continue
msg = json.loads(line)
if msg.get("method", None) == "receive":
data = msg["params"].get("envelope", None)
if not data: continue
msgData = data.get("dataMessage", None)
source = data.get("source", None)
if not msgData or not source or source == "+xxxYOURPHONENUMBER":
continue
groupID = msgData.get("groupInfo", {}).get("groupId", None)
timestamp = msgData.get("timestamp", None)
text = msgData.get("message", "")
# handle message
await send_msg(
"sendReceipt", {"targetTimestamp": timestamp, "recipient": source}
)
await send_msg(
"send",
{
"recipient": None if groupID else source,
"groupId": groupID,
"message": f"you said {text}",
"attachments": [],
},
)
asyncio.run(main())
Create DBus service (OLD way)
https://github.com/AsamK/signal-cli/wiki/DBus-service
Write bot on DBus
Install python dependencies:
pip install git+https://github.com/LEW21/pydbus.git
pip install PyGObject
pip install pycairo
Simple echo bot:
from pydbus import SystemBus
from gi.repository import GLib
import base64
bus = SystemBus()
loop = GLib.MainLoop()
signal = bus.get('org.asamk.Signal')
def send_message(source, groupID, text, attachments=[]):
if len(groupID) == 0:
signal.sendMessage(text, attachments, [source])
else:
signal.sendGroupMessage(text, attachments, groupID)
def msgRcv (timestamp, source, groupID, message, attachments):
send_message(source, groupID, 'text', ['attachment_file_path'])
signal.onMessageReceived = msgRcv
print("START")
loop.run()