semaphore icon indicating copy to clipboard operation
semaphore copied to clipboard

A simple (rule-based) bot library for Signal Private Messenger.

Semaphore

PyPI GitHub Workflow Status GitHub tag (latest SemVer) License

A simple (rule-based) bot library for Signal Private Messenger in Python. Please note that this library is unofficial, unapproved and not nearly as secure as the real Signal clients.

Table of contents

  • Requirements
  • Installation
  • Quick start
  • Code example
  • Example bots
  • Changelog
  • License

Requirements

Installation

  1. Install signald or build from source

    $ git clone https://gitlab.com/signald/signald.git
    $ cd signald
    $ make installDist
    $ make setup
    
  2. Install Semaphore

    Latest release from PyPi:

    $ pip install semaphore-bot
    

    From source with pip:

    $ pip install git+https://github.com/lwesterhof/semaphore.git
    

    From source:

    $ git clone https://github.com/lwesterhof/semaphore.git
    $ cd semaphore
    $ make build
    $ make install
    

Quick start

  1. Start signald

    $ cd signald
    $ build/install/signald/bin/signald
    
  2. Open a new terminal and connect to signald control socket

    $ nc -U $XDG_RUNTIME_DIR/signald/signald.sock
    

    (or /var/run/signald/signald.sock for older versions of signald, see signald docs)

  3. Register phone number with Signal by sending following message on the control socket (replace +xxxxxxxxxxx with bot Signal number). Sometimes Signal requires completion of a captcha to register.

    {"type": "register", "version": "v1", "account": "+xxxxxxxxxxx"}
    
  4. Verify phone number with SMS verification code by sending following message on the control socket (replace +xxxxxxxxxxx with bot Signal number and zzzzzz with verification code)

    {"type": "verify", "version": "v1", "account": "+xxxxxxxxxxx", "code": "zzzzzz"}
    
  5. Verify Signal is working by sending following message on the control socket (replace +xxxxxxxxxxx with bot Signal number and +yyyyyyyyyyy with your Signal number)

    {"type": "send", "version": "v1", "username": "+xxxxxxxxxxx", "recipientAddress": {"number": "+yyyyyyyyyyy"}, "messageBody": "Hello world"}
    
  6. Open a new terminal and set the SIGNAL_PHONE_NUMBER environment variable to your phone number:

    $ export SIGNAL_PHONE_NUMBER=+xxxxxxxxxxx
    
  7. Start the example echo bot

    $ python examples/echobot.py
    
  8. Send message to Signal bot running on +xxxxxxxxxxx and wait for an echo

  9. Now you can start writing your own bot for Signal Private Messenger!

Code example

import anyio
from semaphore import Bot, ChatContext

# Connect the bot to number.
bot = Bot("+xxxxxxxxxxx")

@bot.handler('')
async def echo(ctx: ChatContext) -> None:
    await ctx.message.reply(ctx.message.get_body())

async def main():
    async with bot:
        # Set profile name.
        await bot.set_profile("Semaphore example bot")

        # Run the bot until you press Ctrl-C.
        await bot.start()

anyio.run(main)

Example bots

The following example bots can be found in examples:

  • apodbot, replies with Astronomy Picture of the Day
  • bbcbot, replies with latest BBC headlines
  • broadcastbot, send broadcast to all subscribers
  • btcbot, sends notification when BTC price drops below a set price
  • echobot, repeats received messages
  • exceptionbot, with custom exception handler
  • expirationbot, sets the message expiration timer for a chat to random value
  • lovebot, loves everything you say!
  • spongebot, repeats received messages in sPOngEbOb sqUArepAnTs text
  • stickerbot, links to the sticker pack for received stickers
  • timerbot, sends an alert after a predefined time
  • quotebot, quotes and repeats received messages
  • xkcdbot, replies with latest XKCD comic

Changelog

v0.14.0

  • Compatibility with signald 0.18.0+
  • Migrate to latest version of anyio (3.5.0)
  • Add Dockerfile to run Signal bot in container
  • Add support for link previews (thanks @Era-Dorta)

v0.13.0

  • Compatibility with signald 0.17.0+
  • Add method to set expiration timer of chat (thanks @Era-Dorta)
  • Example expiration timer bot

v0.12.0

  • Compatibility with signald 0.15.0+
  • Add support for emoji and about to in profile (thanks @EsEnZeT)
  • Add option to throw signals errors on send (thanks @eknoes)

v0.11.0

  • Compatibility with signald 0.14.0+ (signald protocol v1)
  • Add support for waiting on signald send confirmation (thanks @eknoes)
  • Add support for sending messages to groups (thanks @brazuzan)

v0.10.1

  • Add method to set profile name and profile picture
  • Store e164 phone number and uuid for received messages

v0.10.0

  • Add support for sending messages without previous context (thanks @eknoes)
  • Add support for exception handlers (thanks @eknoes)
  • Add ability to set profile picture (thanks @eknoes)
  • Support signald client protocol v1
  • Compatibility with signald 0.12.0+

v0.9.1

  • Fix repeating job re-add to queue (thanks @grandchild)

v0.9.0

  • Support for typing indicators
  • Support for GroupsV2 (thanks @thefinn93)
  • Example sticker bot (thanks @iomintz)
  • Compatibility with signald 0.11.0+

v0.8.0

  • Support for Python 3.9
  • Support for executing multiple handlers in parallel (thanks @iomintz)
  • Support incoming sticker messages (thanks @iomintz)

v0.7.1

  • Support for decorators to register handlers
  • Support for sending delivery receipts
  • Mark messages as read by default

v0.7.0

  • Compatibility with signald 0.10.0+
  • Support for multiple replies/reactions by handler (thanks @iomintz)
  • Marking messages as read is optional
  • First release on PyPi

v0.6.0

  • Support for message reactions
  • Example message reaction bot

v0.5.0

  • Improve the logging system
  • Add logging to job queue
  • Strict typing

v0.4.0

  • Support for recurring jobs
  • Example BTC price notification bot

v0.3.0

  • Support for scheduled jobs
  • Example timer bot

v0.2.0

  • Support for quoting messages
  • Example quote bot

v0.1.0

  • First release on Github

License

This project is licensed under the AGPL-v3 license. The full license can be found in LICENSE.txt.