{"id":21426656,"url":"https://github.com/lwesterhof/semaphore","last_synced_at":"2025-04-06T16:11:50.382Z","repository":{"id":40305822,"uuid":"266113877","full_name":"lwesterhof/semaphore","owner":"lwesterhof","description":"A simple (rule-based) bot library for Signal Private Messenger.","archived":false,"fork":false,"pushed_at":"2024-05-23T20:11:59.000Z","size":6825,"stargazers_count":139,"open_issues_count":3,"forks_count":27,"subscribers_count":9,"default_branch":"main","last_synced_at":"2025-03-30T14:11:15.436Z","etag":null,"topics":["bot","messaging","python","signal"],"latest_commit_sha":null,"homepage":"https://lwesterhof.github.io/semaphore/","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"agpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/lwesterhof.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE.txt","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null},"funding":{"custom":"https://signal.org/donate/"}},"created_at":"2020-05-22T13:11:56.000Z","updated_at":"2025-02-05T10:50:57.000Z","dependencies_parsed_at":"2024-06-21T07:12:53.520Z","dependency_job_id":"4286ded8-b3da-4d05-b368-0984c68c6bd0","html_url":"https://github.com/lwesterhof/semaphore","commit_stats":{"total_commits":176,"total_committers":12,"mean_commits":"14.666666666666666","dds":0.1875,"last_synced_commit":"fb9aa3287ccf4f012297b8d914b3de55c168bef9"},"previous_names":[],"tags_count":20,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lwesterhof%2Fsemaphore","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lwesterhof%2Fsemaphore/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lwesterhof%2Fsemaphore/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lwesterhof%2Fsemaphore/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/lwesterhof","download_url":"https://codeload.github.com/lwesterhof/semaphore/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247509223,"owners_count":20950232,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["bot","messaging","python","signal"],"created_at":"2024-11-22T21:43:12.436Z","updated_at":"2025-04-06T16:11:50.361Z","avatar_url":"https://github.com/lwesterhof.png","language":"Python","funding_links":["https://signal.org/donate/"],"categories":[],"sub_categories":[],"readme":"# Semaphore\n\n[![PyPI](https://img.shields.io/pypi/v/semaphore-bot)](https://pypi.org/project/semaphore-bot/)\n[![GitHub Workflow Status](https://img.shields.io/github/actions/workflow/status/lwesterhof/semaphore/python.yml)](https://github.com/lwesterhof/semaphore/actions)\n[![GitHub tag (latest SemVer)](https://img.shields.io/github/v/tag/lwesterhof/semaphore)](https://github.com/lwesterhof/semaphore/tags)\n[![License](https://img.shields.io/github/license/lwesterhof/semaphore)](https://github.com/lwesterhof/semaphore/blob/main/LICENSE.txt)\n\nA simple (rule-based) bot library for [Signal](https://signal.org/) Private Messenger in Python.\nPlease note that this library is unofficial, unapproved and not nearly as secure as the real Signal clients.\n\n## Table of contents\n   * [Requirements](#requirements)\n   * [Installation](#installation)\n   * [Quick start](#quick-start)\n   * [Code example](#code-example)\n   * [Example bots](#example-bots)\n   * [Changelog](#changelog)\n   * [License](#license)\n\n## Requirements\n- ![PyPI - Python Version](https://img.shields.io/pypi/pyversions/semaphore-bot)\n- [signald](https://gitlab.com/signald/signald) [0.23.0](https://gitlab.com/signald/signald/-/tags) or later, a daemon that facilitates communication over [Signal](https://signal.org/)\n\n## Installation\n1. Install signald or build from source\n    ```bash\n    $ git clone https://gitlab.com/signald/signald.git\n    $ cd signald\n    $ make installDist\n    $ make setup\n    ```\n\n2. Install Semaphore\n\n    Latest release from PyPi:\n    ```bash\n    $ pip install semaphore-bot\n    ```\n\n    From source with pip:\n    ```bash\n    $ pip install git+https://github.com/lwesterhof/semaphore.git\n    ```\n\n    From source:\n    ```bash\n    $ git clone https://github.com/lwesterhof/semaphore.git\n    $ cd semaphore\n    $ make build\n    $ make install\n    ```\n\n## Quick start\n1. Start signald\n    ```bash\n    $ cd signald\n    $ build/install/signald/bin/signald\n    ```\n\n2. Open a new terminal and connect to signald control socket\n    ```bash\n    $ nc -U $XDG_RUNTIME_DIR/signald/signald.sock\n    ```\n    (or `/var/run/signald/signald.sock` for older versions of signald, [see signald docs](https://signald.org/articles/protocol/#socket-file-location))\n\n3. 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](https://signald.org/articles/captcha/) to register.\n    ```json\n    {\"type\": \"register\", \"version\": \"v1\", \"account\": \"+xxxxxxxxxxx\"}\n    ```\n\n4. 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)\n    ```json\n    {\"type\": \"verify\", \"version\": \"v1\", \"account\": \"+xxxxxxxxxxx\", \"code\": \"zzzzzz\"}\n    ```\n\n5. Verify Signal is working by sending following message on the control socket (replace `+xxxxxxxxxxx` with bot Signal number and `+yyyyyyyyyyy` with your Signal number)\n    ```json\n    {\"type\": \"send\", \"version\": \"v1\", \"username\": \"+xxxxxxxxxxx\", \"recipientAddress\": {\"number\": \"+yyyyyyyyyyy\"}, \"messageBody\": \"Hello world\"}\n    ```\n\n6. Open a new terminal and set the `SIGNAL_PHONE_NUMBER` environment variable to your phone number:\n    ```bash\n    $ export SIGNAL_PHONE_NUMBER=+xxxxxxxxxxx\n    ```\n\n7. Start the example echo bot\n    ```bash\n    $ python examples/echobot.py\n    ```\n\n8. Send message to Signal bot running on `+xxxxxxxxxxx` and wait for an echo\n\n9. Now you can start writing your own bot for [Signal](https://signal.org/) Private Messenger!\n\n## Code example\n```python\nimport anyio\nfrom semaphore import Bot, ChatContext\n\n# Connect the bot to number.\nbot = Bot(\"+xxxxxxxxxxx\")\n\n@bot.handler('')\nasync def echo(ctx: ChatContext) -\u003e None:\n    await ctx.message.reply(ctx.message.get_body())\n\nasync def main():\n    async with bot:\n        # Set profile name.\n        await bot.set_profile(\"Semaphore example bot\")\n\n        # Run the bot until you press Ctrl-C.\n        await bot.start()\n\nanyio.run(main)\n```\n\n## Example bots\nThe following example bots can be found in [examples](examples):\n- [apodbot](examples/apodbot.py), replies with Astronomy Picture of the Day\n- [bbcbot](examples/bbcbot.py), replies with latest BBC headlines\n- [broadcastbot](examples/broadcastbot.py), send broadcast to all subscribers\n- [btcbot](examples/btcbot.py), sends notification when BTC price drops below a set price\n- [echobot](examples/echobot.py), repeats received messages\n- [exceptionbot](examples/exceptionbot.py), with custom exception handler\n- [expirationbot](examples/expirationbot.py), sets the message expiration timer for a chat to random value\n- [groups](examples/groups.py), manage groups\n- [lovebot](examples/lovebot.py), loves everything you say!\n- [profilebot](examples/profilebot.py), retrieves profile for personal touch\n- [quotebot](examples/quotebot.py), quotes and repeats received messages\n- [spongebot](examples/spongebot.py), repeats received messages in sPOngEbOb sqUArepAnTs text\n- [stickerbot](examples/stickerbot.py), links to the sticker pack for received stickers\n- [timerbot](examples/timerbot.py), sends an alert after a predefined time\n- [xkcdbot](examples/xkcdbot.py), replies with latest XKCD comic\n\n## Changelog\n**v0.17.0**\n* Add support for group actions (thanks @sks444)\n* Add support for receiving mentions\n\n**v0.16.0**\n* Compatibility with signald 0.23.0+\n* Add method to retrieve profile of message sender\n\n**v0.15.0**\n* Compatibility with signald 0.22.0+\n* Add option to automatically accept group invites\n\n**v0.14.0**\n* Compatibility with signald 0.18.0+\n* Migrate to latest version of anyio (3.5.0)\n* Add Dockerfile to run Signal bot in container\n* Add support for link previews (thanks @Era-Dorta)\n\n**v0.13.0**\n* Compatibility with signald 0.17.0+\n* Add method to set expiration timer of chat (thanks @Era-Dorta)\n* Example expiration timer bot\n\n**v0.12.0**\n* Compatibility with signald 0.15.0+\n* Add support for emoji and about to in profile (thanks @EsEnZeT)\n* Add option to throw signals errors on send (thanks @eknoes)\n\n**v0.11.0**\n* Compatibility with signald 0.14.0+ (signald protocol v1)\n* Add support for waiting on signald send confirmation (thanks @eknoes)\n* Add support for sending messages to groups (thanks @brazuzan)\n\n**v0.10.1**\n* Add method to set profile name and profile picture\n* Store e164 phone number and uuid for received messages\n\n**v0.10.0**\n* Add support for sending messages without previous context (thanks @eknoes)\n* Add support for exception handlers (thanks @eknoes)\n* Add ability to set profile picture (thanks @eknoes)\n* Support signald client protocol v1\n* Compatibility with signald 0.12.0+\n\n**v0.9.1**\n* Fix repeating job re-add to queue (thanks @grandchild)\n\n**v0.9.0**\n* Support for typing indicators\n* Support for GroupsV2 (thanks @thefinn93)\n* Example sticker bot (thanks @iomintz)\n* Compatibility with signald 0.11.0+\n\n**v0.8.0**\n* Support for Python 3.9\n* Support for executing multiple handlers in parallel (thanks @iomintz)\n* Support incoming sticker messages (thanks @iomintz)\n\n**v0.7.1**\n* Support for decorators to register handlers\n* Support for sending delivery receipts\n* Mark messages as read by default\n\n**v0.7.0**\n* Compatibility with signald 0.10.0+\n* Support for multiple replies/reactions by handler (thanks @iomintz)\n* Marking messages as read is optional\n* First release on PyPi\n\n**v0.6.0**\n* Support for message reactions\n* Example message reaction bot\n\n**v0.5.0**\n* Improve the logging system\n* Add logging to job queue\n* Strict typing\n\n**v0.4.0**\n* Support for recurring jobs\n* Example BTC price notification bot\n\n**v0.3.0**\n* Support for scheduled jobs\n* Example timer bot\n\n**v0.2.0**\n* Support for quoting messages\n* Example quote bot\n\n**v0.1.0**\n* First release on Github\n\n## License\nThis project is licensed under the AGPL-v3 license.\nThe full license can be found in [LICENSE.txt](LICENSE.txt).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flwesterhof%2Fsemaphore","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Flwesterhof%2Fsemaphore","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flwesterhof%2Fsemaphore/lists"}