🤖 How to make a Signal bot in Python
Building a Signal bot with signal-cli.
Making a Signal bot in Python (Linux)
Note: This guide was updated on 29/07/2022 as it was previously outdated. If anything doesn't work, feel free to contact me.
What's signal?
Signal is a cross-platform, centralized (😞), encrypted messaging service that I've been using for a few years now. My friends and I decided to switch to Signal as an alternative to Whatsapp, which unlike Signal collects a lot of metadata of your messages and is owned by a big tech company (Facebook), and Telegram, which stores all your (encrypted) data on their servers.
Signal has evolved a lot in the past few years, and now has all the major features a messaging app needs: group chats, stickers, reactions, phone/video calls, ... Unlike Telegram, however, it does not have support for bots. In fact, it does not provide a public API for sending and receiving messages, and the only valid tool I've found that can be used for Signal apart from their official apps is signal-cli.
Step 1: Installing and configuring signal-cli
This is probably the easiest step. You can follow the installation guide, or just paste the instructions below to install it for version 0.10.9.
export VERSION=0.10.9
wget https://github.com/AsamK/signal-cli/releases/download/v"${VERSION}"/signal-cli-"${VERSION}"-Linux.tar.gz
sudo tar xf signal-cli-"${VERSION}"-Linux.tar.gz -C /opt
sudo ln -sf /opt/signal-cli-"${VERSION}"/bin/signal-cli /usr/local/bin/
You then need to register your phone number (even if you already registered it on another device). This can be done by running
signal-cli --config /var/lib/signal-cli -u +4915151111111 register
(replace +4915151111111 with your phone number).
If you get a
Captcha invalid or required for verification
you need to
- go to https://signalcaptchas.org/registration/generate.html
- open Web Developer Tool
- complete Captcha
- you'll then either get redirected to a link which looks like
signalcaptcha://...
or (on Firefox) you'll get a message on the console which saysPrevented navigation to “signalcaptcha://...
- run
signal-cli --config /var/lib/signal-cli -u +4915151111111 register --captcha TOKEN
(replace TOKEN with whatever comes aftersignalcaptcha://
)
to register with Captcha. Guide can be found here Further instructions can be found here.
Step 2: Enable DBus service
This is the most crucial part. In order to be able to make a Python script that uses signal-cli
, you need to start it over dbus.
For that, you need to add these three files:
These files may change for future versions, so make sure to get the latest files from the "data/" folder of the github repository.
/etc/dbus-1/system.d/org.asamk.Signal.conf
:
<?xml version="1.0"?> <!--*-nxml-*-->
<!DOCTYPE busconfig PUBLIC "-//freedesktop//DTD D-BUS Bus Configuration 1.0//EN"
"http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd">
<busconfig>
<policy user="YOUR_USERNAME">
<allow own="org.asamk.Signal"/>
<allow send_destination="org.asamk.Signal"/>
<allow receive_sender="org.asamk.Signal"/>
</policy>
<policy context="default">
<allow send_destination="org.asamk.Signal"/>
<allow receive_sender="org.asamk.Signal"/>
</policy>
</busconfig>
Where YOUR_USERNAME
is your linux username (e.g. "root" if you're running as root). It is recommended in the signal-cli dbus documentation to create a new user called signal-cli
/usr/share/dbus-1/system-services/org.asamk.signal-cli.service
:
[D-BUS Service]
Name=org.asamk.Signal
Exec=/bin/false
SystemdService=dbus-org.asamk.signal-cli.service
and
/etc/systemd/system/signal-cli.service
:
[Unit]
Description=Send secure messages to Signal clients
Requires=dbus.socket
After=dbus.socket
Wants=network-online.target
After=network-online.target
[Service]
Type=dbus
Environment="SIGNAL_CLI_OPTS=-Xms2m"
ExecStart=%dir%/bin/signal-cli --config /var/lib/signal-cli daemon --system
User=YOUR_USERNAME
BusName=org.asamk.Signal
# JVM always exits with 143 in reaction to SIGTERM signal
SuccessExitStatus=143
[Install]
Alias=dbus-org.asamk.Signal.service
where again YOUR_USERNAME
is your linux username. If you have installed signal-cli anywhere else than in /usr/local/bin you should change that file.
You can then run these commands to run the service:
systemctl daemon-reload
systemctl enable signal-cli.service
systemctl reload dbus.service
Step 3: Configuring Python
To use the dbus interface in Python, you need to install pydbus
pip install git+https://github.com/LEW21/pydbus.git
You might also need to install the following packages (in Ubuntu):
sudo apt install python3-gi python3-gi-cairo gir1.2-gtk-3.0
sudo apt install libgirepository1.0-dev gcc libcairo2-dev pkg-config python3-dev gir1.2-gtk-3.0
pip install pycairo
pip install PyGObject
(as with every project, I recommend making a separate virtual environment for this.)
Step 4: Python script!
The original script I used to make my Python bot can be found here.
The main skeleton for the program is the following:
from pydbus import SystemBus
from gi.repository import GLib
bus = SystemBus()
loop = GLib.MainLoop()
signal = bus.get('org.asamk.Signal', object_path='/org/asamk/Signal')
def reply_ping(timestamp, source, groupID, message, attachments):
signal.sendMessage(message, [], [source])
signal.onMessageReceived = reply_ping
loop.run()
A list of all methods available can be found here.
Tips: debugging
If something goes wrong after starting the dbus interface, you might want to kill the process manually as it is running in the background with
ps aux | grep signal-cli
kill PROCESS_ID
where PROCESS_ID is the PID of the process that you can see from running the first command.
Joining a v2 group
I remember having trouble joining a version 2 Signal group. I ended up succeeding only by updating the profile and then running the command from the terminal with the join link. See here for further instructions.