A libpurple/Pidgin plugin for WhatsApp. Being developed on Ubuntu 22.04.
This is a re-write of purple-gowhatsapp, switching back-ends from go-whatsapp to whatsmeow. whatsmeow is written by Tulir Asokan. It has multi-device support.
Standard features:
Major differences from the go-whatsapp vesion:
prpl-hehoe-whatsmeow
Other improvements:
Known issues:
fonts-noto-color-emoji
package. There is currently no experience if that works on Windows as well. Feedback is welcome.Other planned features:
These features will not be worked on:
Accessing microphone and camera for recording voice or video messages.
To prepare a voice message, you can use other tools for recording. I like to use ffmpeg:
ffmpeg -f pulse -i default -ac 1 -ar 16000 -c:a libopus -y voicemessage.ogg # on Linux with PulseAudio
Dependencies:
For Ubuntu, or Debian compliant Linux flavors, use the apt package manager to install these dependencies first:
sudo apt install pidgin pkg-config cmake make golang gcc libgdk-pixbuf2.0-dev libopusfile-dev
This project uses CMake.
git submodule update --init
mkdir build
cd build
cmake ..
cmake --build .
sudo make install/strip
Note: If you configure the project for using user-specific installation paths before building, you may install without sudo:
cmake -DPURPLE_DATA_DIR:PATH=~/.local/share -DPURPLE_PLUGIN_DIR:PATH=~/.purple/plugins ..
In the build directory, you can also create a Debian package:
cpack
You should not do that with user-specific paths, obviously.
CMake will try to set-up a development environment automatically.
Additional dependencies:
This is known to work with MSYS make and CMake generator "MSYS Makefiles". go and gcc must be in %PATH%
.
At time of writing, cgo does not support MSVC.
For sending opus in ogg audio files as voice messages, add a static win32 build of opusfile to CMake's prefix path or use vcpkg's toolchain file:
vcpkg.exe install opusfile:x86-mingw-static
cmake -DCMAKE_TOOLCHAIN_FILE="wherever/vcpkg/scripts/buildsystems/vcpkg.cmake" -DVCPKG_TARGET_TRIPLET=x86-mingw-static -DVCPKG_MANIFEST_MODE=OFF -G "MSYS Makefiles" ..
~/.purple/plugins
).Create a new account
You must enter your phone's internationalized number followed by @s.whatsapp.net
.
Example: 123456789
from Germany would use 49123456789@s.whatsapp.net
.
Upon login, a QR code and the 8-character code is shown in a Pidgin request window.
Using your phone's camera, scan the code within 20 seconds or enter the 8-character code on your main device – just like you would do with WhatsApp Web.
Note: On headless clients such as Spectrum, the QR code will be wrapped in a message by a fake contact called "Logon QR Code". You may need to temporarily configure your UI to accept messages from unsolicited users for linking purposes.
Wait until the connection has been fully set up. Unfortunately, there is no progress indicator while keys are exchanged and old messages are fetched. Usually, a couple of seconds is enough. Some power users with many groups and contacts reported the process can take more than a minute. If the plug-in is not yet ready, outgoing messages may be dropped silently (see issue #142).
qrcode-size
int
The size of the QR code shown for login purposes, in pixels (default: 256).
When set to zero, the QR code will be delivered as a text message.
fetch-contacts
bool
If set to true (default), buddy list will be populated with contacts sent by server.
This is useful for the first login in particular. If enabled while connecting, it will also fetch the current list of WhatsApp groups.
fake-online
bool
If set to true (default), contacts currently not online will be regarded as "away" (so they still appear in the buddy list).
If set to false, offline contacts will be regarded as "offline" (no messages can be sent).
send-receipt
string choice
Selects when to send receipts "double blue tick" notifications:
immediately
: immediately upon message receivalon-interact
: as the user interacts with the conversation window (only usable with Pidgin)on-answer
: as soon as the user sends an answer (default)never
: nevermessage-cache-size
int
Stores a number (default: 100) of messages in local volatile memory. Cached messages are used to provide context when displaying reactions.
discard-old-messages
bool
If set to true (default: false), messages older than the connection will be discarded.
Note: This is implemented without time-zone information. This might not work as expected when chatting with someone in a different time-zone.
handle-images
string choice
What to do with images:
inline
: embed in the conversation windowxfer
: treat as file downloadboth
: do bothinline-stickers
bool
If set to true (default), stickers will automatically be downloaded and may embedded in the conversation window if an appropriate webp GDK pixbuf loader is present.
group-is-file-origin
bool
It set to true (default), when a file is posted into a group chat, that chat will be the origin of the file. If set to false, the file will originate from the group chat participant. At time of writing, Bitlbee wants this to be false.
Note: File transfers for group chats are supported since libpurple 2.14.0.
attachment-message
string
This system message is written to the conversation for each incoming attachment. It can have two %s
place-holders which wil be fed into a call to printf
.
%s
will be replaced by the original sender (the participant, not the group chat). %s
will be replaced by the original document file name. For non-document attachments, this falls back to the hash mandated by WhatsApp.Default value is Preparing to store "%s" sent by %s...
.
If built and used in a Linux environment with GLib 2.68 or newer, you can also use place-holders for more flexibility:
$sender
: Denotes the original sender (the participant, not the group chat). $filename
: Refers to the original document file name. For non-document attachments, this falls back to the hash mandated by WhatsApp.get-icons
bool
If set to true (default: false), profile pictures are updated every time the plug-in connects.
ignore-status-broadcast
bool
If set to true (default), your contact's status broadcasts are ignored.
bridge-compatibility
bool
Special compatibility setting for protocol bridges like Spectrum or bitlbee. Setting this to true (default: false) will treat system messages just like normal messages, allowing them to be logged and forwarded. This only affects soft errors regarding a specific conversation, e.g. "message could not be sent".
echo-sent-messages
string choice
Selects when to put an outgoing message into the local conversation window:
internal
: After the WhatsApp server has received the message, and lock-up the UI until it does (default).on-success
: After the WhatsApp server has received the message, but do not lock-up the UI (use this for speed).immediately
: Immediately after hitting send (message may not actually have been sent).never
: Never (some protocol bridges want this).Note: Neither of these indicate whether the message has been received by the contact.
display-message-id
bool
If set to true, the ID of a text message will be appended to the displayed text. For outgoing messages, this only has effect if echo-sent-messages
is set to on-success
.
autojoin-chats
bool
Automatically join all chats representing the WhatsApp groups after connecting and every time group information is provided. This is useful for protocol bridges.
database-address
string
whatsmeow stores all session information in a SQL database.
This setting can have place-holders:
$purple_user_dir
: Will be replaced by the user directory, e.g. ~/.purple
.$username
: Will be replaced by the username as entered in the account details.Default: file:$purple_user_dir/whatsmeow.db?_foreign_keys=on&_busy_timeout=3000
Folder must exist, whatsmeow.db
is created automatically.
By default, the driver will be sqlite3
for a file-backed SQLite database. This is not recommended for multi-account-applications (e.g. spectrum or bitlbee) due to a limitation in the driver. The file-system (see addess option) must support locking and be responsive. Network shares (especially SMB) do not work.
If the setting starts with postgres:
, the suffix will be passed to database/sql.Open as dataSourceName
for the pq PostgreSQL driver. At time of writing, there are no further drivers supported by whatsmeow. Support for MySQL/MariaDB has been requested.
embed-max-file-size
int
When set to a value greater than 0 (default, in megabytes), the plug-in tries to detect link-only messages such as https://example.com/voicemessage.oga
for forwarding.
If enabled, this plug-in tries to download and forward the linked file, choosing the appropriate media type automatically. This way, your contacts do not see a link to an image, video or a voice message, but instead can play the content directly in their app. The message must consist of one URL exactly, including whitespace. For this reason, this mode is incompatible with Pidgin's OTR plug-in, see this bug report.
At time of writing, the maximum file-size supported by WhatsApp is 2 GB according to wabetainfo and confirmed by iOS users in Germany.
trusted-url-regex
string
In case a link-only message does not point to an image, video or audio file, the file may be sent as a document message. For reasons of safety, this will only happen for files from trusted sources. An URL must match this regular expression to be considered trustworthy. Matching is case-sensitive. The match spans the entire verbatim URL, so query and fragment need to be considered. Do not forget the caret and/or dollar sign. Some examples:
^https://www\.example\.com
trust files from www.example.com
via HTTPS.^https://[^/]*example\.com
trust files from example.com
and subdomains, authentication data via HTTPS.^[^?#]+\.pdf$
trust all PDFs.^[^?#]+\.(pdf|png)$
trust all PDFs and PNGs.^https://www\.example\.com[^?#]+\.(pdf|png)$
trust all PDFs and PNGs from https://www.example.com
..*
trust anything.^$
trust nothing (default).In case of image, video or audio files, further conditions need to be met, see below.
WhatsApp is very picky about media messages. This is actually a good thing for ensuring compatibility on all devices and clients (Android, iOS, all browsers for WhatsApp Web…).
An image may be sent as an image message (JPEG, image/jpeg
). This is relatively straight-forward.
This feature is only available if the plug-in has been built with liboggfile.
A voice message must meet these criteria:
application/ogg
, audio/ogg
, sent as audio/ogg; codecs=opus
ogg
opus
Additional recommendations:
This kind of message is also known as "push to talk" (PTT). While it is possible to send other audio formats as non-voice audio messages, this plug-in only considers data for voice messages. Everything else is send as a document message.
A video message must meet these criteria:
video/mp4
mp42
(observed), isom
(also accepted)h264
yuv420p
(assumed, not checked)aac
(not checked)Not all of these values are checked by the plug-in. Some of these criteria are guessed and may not actually be WhatsApp restrictions.
A file is sent as-is.
whatsmeow offers support for SOCKS5 proxies only. Even if no proxy settings are set in purple, the underlying Go runtime might pick up the https_proxy
environment variable anyway.
This plug-in supports a couple of "IRC-style" commands. The user can write them in any chat. These features are experimental hacks. They have been included due to user reuqets. Use them with care.
?versions
Show version information.
?contacts
Request re-download of all contacts. Only affects the buddy list if fetch-contacts
is set to true.
?participants
alias ?members
Request the current list of participants. Can only be used in group chat conversations.
?presenceavailable
, ?presenceunavailable
, ?presence
Overrides the presence which is being sent to WhatsApp servers. The displayed connection state may no longer match the advertised connection state. This can be used to appear unavailable while still being able to receive messages for logging or notification purposes. Using this command may result in unexpected behaviour. Use ?presence
(without a suffix) to give back control to the plug-in's internals.
?logout
Performs a log-out. The QR-code will be requested upon connecting again.
Attachments (images, videos, voice messages, stickers, document) are always downloaded as soon as the message is processed. The user is then asked where they want the file to be written. During this time, the file data is residing in memory multiple times:
On systems with many concurrent connections, this could exhaust memory.
As of writing, whatsmeow does not offer an interface to read the file in chunks.