Skip to main content

irotechlab-pyarattai

A Python client + bot framework for Arattai.

TeleBot-style API. End-to-end encrypted DM send & receive. WebSocket push. Runs on Termux, Linux, macOS.

from pyarattai import ArattaiBot

bot = ArattaiBot("91-XXXXXXXXXX")   # prompts for OTP on first run

@bot.on_command("start")
def cmd_start(msg):
    msg.reply("Hello!")

@bot.on_message()
def handle(msg):
    if msg.text.startswith("/echo "):
        msg.reply(msg.text[6:])

bot.run()

That's it. First run prompts for OTP, auto-registers Signal keys, establishes a WebSocket, and starts dispatching messages.

Install

pip install irotechlab-pyarattai

Requires Python 3.9+ and Node.js 16+. Install Node with pkg install nodejs on Termux, brew install node on macOS, or apt install nodejs on Debian.

The first run copies the bundled libsignal-protocol.js (1.4 MB) into ~/.pyarattai/ and runs npm install bytebuffer long protobufjs into ~/.pyarattai/node_modules. This is one-time setup.

Authentication

Login is interactive on the first run. You'll see a prompt like:

App OTP sent to 91-82******67 (check the Arattai app)
Enter OTP  ('resend' = new code, 'sms'/'app' = switch channel):

Type the 6-digit code from the Arattai app. If the app notification doesn't arrive, type sms to force SMS delivery.

The session is cached in ~/.pyarattai/session.json (mode 0600). Every subsequent run reuses it — no OTP prompt.

To start fresh:

from pyarattai import ArattaiClient
ArattaiClient.from_session().logout()   # server-side logout + local cleanup

Bot API

Construct a bot:

from pyarattai import ArattaiBot

bot = ArattaiBot(
    "91-XXXXXXXXXX",
    transport="ws",          # "ws" (default, push) or "http" (poll)
    poll_interval=15.0,      # only used when transport="http"
    otp_channel="app",       # "app" | "sms" | "auto"
)

Register handlers:

@bot.on_command("echo", description="Echo text")
def cmd_echo(msg):
    msg.reply(" ".join(msg.args))

@bot.on_message(filters=lambda m: m.chat_id == "CT_...")
def handle(msg):
    print(msg.dname, "said", msg.text)

@bot.on_reaction(emoji="👍")
def on_react(msg, emoji, sender):
    print(f"{sender} reacted with {emoji}")

Message object fields:

msg.chat_id      str
msg.sender       uid of the sender
msg.dname        display name
msg.text         decrypted text (E2EE is decrypted automatically)
msg.msgid
msg.msguid
msg.time
msg.is_read
msg.is_command   True for "/cmd ..."
msg.command      "cmd"
msg.args         ["arg1", "arg2"]

Message actions:

msg.reply("hi")          # send a message to this chat
msg.react("❤")           # react to this message
msg.edit("new text")     # edit (bot's own messages only)
msg.delete()             # delete this message

Bot helpers:

bot.send(chat_id, "text")             # send message (auto E2EE routing)
bot.typing(chat_id)                   # show typing indicator
bot.typing(chat_id, idle=True)        # clear it
bot.run(single=False)                 # blocking loop; single=True → one pass
bot.stop()                            # graceful shutdown

Client API

For non-bot use cases, use ArattaiClient directly:

from pyarattai import ArattaiClient

client = ArattaiClient.from_session()          # uses cached session
# or: client = ArattaiClient.login("91-...")   # forces OTP

client.get_chats()                             # list[Chat]
client.get_chat(chat_id)                       # Chat
client.get_messages(chat_id, n=50)             # list[Message]
client.send(chat_id, "text")                   # auto-routes E2EE / plaintext

client.typing(chat_id)                         # show typing
client.typing(chat_id, idle=True)              # clear typing
client.react(chat_id, msguid, "👍")
client.unreact(chat_id, msguid, "👍")
client.mark_read(chat_id, msguid)

client.get_participants(chat_id)
client.add_member(chat_id, [uid])
client.remove_member(chat_id, [uid])
client.update_chat(chat_id, title="New", description="...")
client.set_role(chat_id, uid, role=1)          # 1 = admin

client.get_permalink(chat_id)                  # {link, validity}
client.join_by_invite(token)
client.leave_chat(chat_id)

client.get_channels()
client.join_channel("@username")

client.logout()                                # server-side + local cleanup

Automatic E2EE routing

client.send() learns from the server. On the first message to a chat it tries the plaintext endpoint; if the server rejects it (E2EE-only chat), the client retries via Signal E2EE and caches the decision. Subsequent sends go straight to the right endpoint.

The cache lives in session.json under _e2ee_chats, so the CLI reuses it between invocations.

E2EE

DMs

Fully supported. Pairwise Signal encryption via a vendored, pure-JS libsignal-protocol bundle. Messages arriving on the WebSocket with meta.enc: true are decrypted transparently; replies are encrypted with the same pipeline.

Groups

Not supported in this version. Group E2EE requires Signal SenderKeys (the GroupCipher and GroupSessionBuilder classes), which the vendored 2021 libsignal bundle does not expose. Scheduled for v0.2.

Non-E2EE groups work as plaintext. E2EE groups raise a clear error: ArattaiError: group E2EE is not supported in this version.

Signal store

Signal keys live in ~/.pyarattai/signal-storage.json. Register once with pyarattai signal register — or just run your bot; login auto-registers the first time.

Metadata

Release files for irotechlab-pyarattai 0.1.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for irotechlab-pyarattai 0.1.0
File Size Uploaded
irotechlab_pyarattai-0.1.0.tar.gz 355.0 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for irotechlab-pyarattai 0.1.0
File Interpreter ABI Platform
irotechlab_pyarattai-0.1.0-py3-none-any.whl Python 3 none any Details

Total release size: 718.2 kB

Release files / irotechlab_pyarattai-0.1.0.tar.gz

Download URL irotechlab_pyarattai-0.1.0.tar.gz
Size 355.0 kB
Tags Source
SHA-256 checksum
How to use checksums
d0e80069fd908c912cca9bb31ad778152694524d0ab7a31d0b590f418e570c3a
BLAKE2b-256 checksum
How to use checksums
9553e919567ea4960af7c8e49b8f01beb2bee936c735d250ea5c8c745dfde514
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 7, 2026.

Transparency log

Release files / irotechlab_pyarattai-0.1.0-py3-none-any.whl

Download URL irotechlab_pyarattai-0.1.0-py3-none-any.whl
Size 363.2 kB
Tags Python 3
SHA-256 checksum
How to use checksums
3c8c2cb54faec90f70b9131a9466ecc763098a6234784d0469f2f1c3a6be8289
BLAKE2b-256 checksum
How to use checksums
3e065ba7a4aee9c669c86a7057002e67b15c57dafebbdb6dd782274861ed78c8
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 7, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

0.1.0 This release

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page