Skip to main content

GoyGram

GoyGram Logo

Python 3.11+ Rust Core License: AGPL v3 PyPI version PyPI downloads Telegram API Security Docs & Wiki

What is this?

Ultimate hybrid Telegram framework (Python + Rust core) built for production-grade speed, control, and maximum OpSec.

Under the hood: a Python orchestration layer drives two completely independent network transports (Bot API over aiohttp + MTProto over raw TCP with full DH key exchange), both feeding into a single async event bus. Every crypto operation — AES-256-IGE for MTProto packets, AES-256-GCM for session vaults — runs in a Rust .so compiled with LTO and opt-level=3. Hand-written TL codec, no code generation at runtime. QR code login rendering in the terminal via qrcode + Rich. SRP password proofs for 2FA. And the vault: your auth key locked to your machine-id through PBKDF2-SHA256 at 600,000 iterations.

Key Features

  • Hybrid architecture: ergonomic Python layer + blazing-fast Rust extension.
  • Session zeroize: aggressive in-memory cleanup (zeroize strategy for legacy .session files after migration).
  • Vault AES-256-GCM: encrypted local session bootstrap. Key derived from machine-id + session name via PBKDF2 (or bypass with GOYGRAM_VAULT_KEY).
  • TUI auth flow: terminal-first authorization workflow — phone login with SMS code, QR code scanning in ASCII art, 2FA/SRP password challenges. All Rich-styled when a TTY is present.
  • Proxy support: SOCKS5 (with user/pass auth) and HTTP CONNECT tunneling for MTProto connections. Also respects ALL_PROXY / HTTPS_PROXY / HTTP_PROXY env vars.
  • Dual transport: Bot API (HTTP long-polling via aiohttp, multipart uploads, auto-webhook-clear on 409) + MTProto (raw TCP with AES-256-IGE, dynamic salt recovery on bad_server_salt, auto-DC migration on PHONE_MIGRATE_N) — in one app runtime.
  • DC Routing: MTProto uses a built-in map of the five Telegram DC endpoints and selects the preferred DC, falling back to 149.154.167.50:443 (DC 2).
  • Dynamic API dispatch: every Bot API method works via __getattr__sendAnimation, getUserProfilePhotos, setMyCommands, whatever. Snake_case auto-converts to CamelCase. mt_ prefix routes to MTProto.
  • Keyboard system: inline keyboards, reply keyboards, force reply, reply removal. All with to_dict() serialization that adapts per transport.
  • Forum topic management: full create/edit/close/reopen/delete lifecycle for forum topics and the General topic. Both transports supported.
  • Zero-copy event objects: MsgObj, CbObj, PollObj, MemberObj with __slots__ — no per-message dict overhead.
  • Composable filters: boolean AND/OR/NOT on Filter (filters.text & ~filters.me).
  • Multi-session: named vaults (session_name="worker_1") for farming multiple accounts from the same process. Separate auth keys, separate TCP connections, separate self_id.
  • Durable delivery state: Bot API offsets and MTProto pts/qts/date/seq cursors are persisted atomically with restrictive permissions.
  • Direct media primitives: chunked MTProto upload_file()/download_file() and Bot API download_file() without a heavyweight media framework.

Benchmarks

Cold import, memory footprint, and MTProto crypto (AES-256-IGE) measured against telethon, pyrogram, aiogram and python-telegram-bot. Full methodology and reproduction in benchmarks/.

goygram telethon pyrogram aiogram python-telegram-bot
cold import (ms) 87 298 477 3112 140
RSS delta (MB) 12 48 35 152 18
AES-256-IGE (MB/s, 64 KiB) 113 12 203

The crypto runs in Rust (built in, no separate C extension), GoyGram starts ~36× faster than aiogram, and uses ~12× less memory.

Installation

pip install goygram

Requires Python 3.11+. Pre-built wheels ship for Linux, Windows, macOS, and FreeBSD where the corresponding runner build succeeds. Termux is natively validated in a Termux environment; install the Python package from source there because Android/Termux wheels are not interchangeable with manylinux wheels. Rust is not required for the standard Linux, Windows, and macOS wheels. Installs aiohttp, rich, and qrcode as dependencies.

FreeBSD and Termux

FreeBSD packages are built by the release workflow inside a FreeBSD 15 VM and attached to the GitHub Release because PyPI rejects FreeBSD's nonstandard wheel platform tag. The Rust core is built in the official termux/termux-docker environment and attached as a native validation asset; Termux users should build locally from the source distribution. On a real Termux device, install the Termux toolchain and build from the source distribution:

pkg update
pkg install python rust clang
python -m pip install --no-build-isolation .

Quick Start

1) Bot API (token)

import asyncio
from goygram import GoyGram, filters

app = GoyGram(bot_token="123456:ABC_TOKEN")

@app.on_msg(filt=filters.text)
async def echo(msg):
    await msg.reply("Hello from Bot API")

asyncio.run(app.run())

2) MTProto (no bot token, requires API ID + API Hash)

import asyncio
from goygram import GoyGram

app = GoyGram(api_id=123456, api_hash="0123456789abcdef0123456789abcdef")  # auto-fetches Telegram DC endpoint at startup

@app.on_cmd("ping")
async def ping(msg):
    await msg.reply("pong from MTProto (api_id/api_hash)")

asyncio.run(app.run())

3) Named MTProto sessions (multi-session in one folder)

import asyncio
from goygram import GoyGram

app = GoyGram(
    api_id=123456,
    api_hash="0123456789abcdef0123456789abcdef",
    session_name="farm_worker_1",
)

asyncio.run(app.run())
  • By default, session data is stored in default.vault.
  • With session_name="farm_worker_1", session data is stored in farm_worker_1.vault.
  • If farm_worker_1.session exists, it is migrated to farm_worker_1.vault during bootstrap (securely zeroized after).

Dynamic API & Methods

GoyGram can route Bot API method names dynamically, including methods that are not hardcoded as convenience methods:

  • Call Bot API methods directly even if they are not explicitly hardcoded:
    • await app.sendDocument(chat_id=..., document=...)
    • await app.getChat(chat_id=...)
    • await app.getUpdates(timeout=30)
  • Snake-case also works and is converted to Bot API method names:
    • await app.send_document(chat_id=..., document=...) -> sendDocument
  • MTProto actions (authorized with API ID/API Hash) are available with mt_ prefix:
    • await app.mt_get_dialogs(limit=50)
    • await app.mt_get_chat_full(chat_id=...)

This behavior is implemented through dynamic method resolution in the client core (__getattr__) and transport-aware request routing.

For Bot API files, await app.download_file(file_id, destination) downloads a Telegram file to memory or atomically to a local path. MTProto exposes the same low-level chunk control through app.core.mt.upload_file(...) and app.core.mt.download_file(...).

Authentication & Security

Interactive Login

On first run with MTProto, GoyGram launches a Rich-powered TUI:

GoyGram Interactive Login

? Choose login method:
  > QR Code Login
    Phone Number Login

Choose QR code (scan with any Telegram client) or phone number (SMS code). 2FA password is handled automatically via SRP proofs. The resulting session is stored as default.vault — AES-256-GCM encrypted, keyed to your machine.

Vault Encryption

  • Algorithm: AES-256-GCM (authenticated encryption via Rust's aes-gcm crate)
  • Key derivation: PBKDF2-HMAC-SHA256, 600,000 iterations, key material = {machine-id}:{session_name}
  • Override: GOYGRAM_VAULT_KEY env var (base64-encoded 32 bytes) bypasses PBKDF2 entirely The vault does not fall back to silently accepting plaintext after a failed decryption.

Session Migration

Telethon/Pyrogram .session files are auto-detected, read from SQLite, migrated to .vault, and securely zeroized (overwrite + fsync + unlink).

Developer Tools (Help)

Use built-in introspection tools:

app.help()            # pretty DX overview in console
print(dir(app))       # inspect available shortcuts + dynamic entries

or:

from goygram.utils import print_methods
print_methods(app)

With type hints on key event objects (MsgObj, CbObj, MemberObj, PollObj) and filter primitives, modern IDE autocomplete works much better out of the box.

Filters

goygram.filters supports composable boolean operators:

from goygram import filters

smart_filter = filters.text & ~filters.me
another = filters.text | filters.me

@app.on_msg(filt=smart_filter)
async def handler(msg):
    await msg.reply("Filtered")

Built-in filters: filters.text (message has text), filters.me (message from current account/bot). Compose with &, |, ~. Custom filters: Filter(lambda e: ...).

Transport Routing

Messages can be routed explicitly by transport:

# Force Bot API
await app.send_msg("bot:123456789", "via bot", via="bot")

# Force MTProto
await app.send_msg("mt:123456789", "via mt", via="mt")

Chat ID prefixes (bot: / mt:) are auto-resolved. When replying, the transport source is preserved automatically — reply to a Bot API message, it goes back via Bot API.

FSM Persistence

The default FSM remains in memory:

app = GoyGram(bot_token="123456:ABC_TOKEN")

For an external store, pass an object with load() and save(snapshot) methods:

class RedisFSM:
    def __init__(self, redis):
        self.redis = redis

    def load(self):
        return self.redis.json().get("goygram:fsm") or []

    def save(self, snapshot):
        self.redis.json().set("goygram:fsm", ".", snapshot)

app = GoyGram(bot_token="123456:ABC_TOKEN", fsm_backend=RedisFSM(redis))

For complete control, use fsm_on_change. It receives a JSON-compatible snapshot after every state change and can write it to Redis, PostgreSQL, a file, or another service:

def persist_fsm(snapshot):
    external_store.write(snapshot)

app = GoyGram(bot_token="123456:ABC_TOKEN", fsm_on_change=persist_fsm)

The active core object is also available as app.fsm. It exposes snapshot() and restore(snapshot) for explicit checkpoints and migrations. Existing set_state, get_state, get_state_data, and clear_state behavior is unchanged.

Event Pipeline

BotNet.spin() ──→ bus.push("bot", data)
                                          ──→ Disp.consume() → your handlers
MTNet.spin() ──→ bus.push("mt", data)

Single asyncio.Queue → typed event objects (MsgObj/CbObj/PollObj/MemberObj) → handler lists in registration order. Per-handler error isolation — one crashing handler never takes down the dispatcher.

Logging

GOYGRAM_LOG=DEBUG python app.py   # verbose (raw MTProto packet dumps)
GOYGRAM_LOG=INFO python app.py    # default (startup, errors)
GOYGRAM_LOG=WARNING python app.py # quiet

Logger hierarchy: goygram.app, goygram.botapi, goygram.mtproto, goygram.disp, goygram.security, goygram.dc.

Architecture at a Glance

┌─────────────────────────────────────────────┐
│             GoyGram (Public API)             │  ← User-facing facade
├─────────────────────────────────────────────┤
│        AppCore (Internal Engine)             │  ← Config, hooks, routing
├──────────────────┬──────────────────────────┤
│ BotNet (aiohttp) │   MTNet (TCP/MTProto)    │  ← Independent transports
├──────────────────┴──────────────────────────┤
│          Bus → Disp (Event Pipeline)         │  ← asyncio.Queue + dispatcher
├─────────────────────────────────────────────┤
│  goygram.ext (Rust .so) — AES-IGE/AES-GCM   │  ← Native crypto (LTO, opt=3)
└─────────────────────────────────────────────┘

Wiki

📚 Official documentation and Wiki. There are separate pages for using the client, Bot API, MTProto, events, bytes and TL data. 👉 Open GoyGram Pages · Open GitHub Wiki

License

See LICENSE.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

goygram-0.7.60.tar.gz (84.7 kB view details)

Uploaded Source

Built Distributions

If you're not sure about the file name format, learn more about wheel file names.

goygram-0.7.60-cp311-abi3-win_amd64.whl (316.3 kB view details)

Uploaded CPython 3.11+Windows x86-64

goygram-0.7.60-cp311-abi3-manylinux_2_34_x86_64.whl (402.9 kB view details)

Uploaded CPython 3.11+manylinux: glibc 2.34+ x86-64

goygram-0.7.60-cp311-abi3-macosx_11_0_arm64.whl (375.7 kB view details)

Uploaded CPython 3.11+macOS 11.0+ ARM64

File details

Details for the file goygram-0.7.60.tar.gz.

File metadata

  • Download URL: goygram-0.7.60.tar.gz
  • Upload date:
  • Size: 84.7 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: maturin/1.15.0

File hashes

Hashes for goygram-0.7.60.tar.gz
Algorithm Hash digest
SHA256 ce1bb95cdbd9ba40c77befed4eef1634d7f113a332aba5f95e5206f401e92a15
MD5 d1445addd19e42ad6dbd0715b1a7c180
BLAKE2b-256 d7af2b5b1c03849a7d4d6dff4639d044180ccb462310cf24789f89054e296c2e

See more details on using hashes here.

File details

Details for the file goygram-0.7.60-cp311-abi3-win_amd64.whl.

File metadata

  • Download URL: goygram-0.7.60-cp311-abi3-win_amd64.whl
  • Upload date:
  • Size: 316.3 kB
  • Tags: CPython 3.11+, Windows x86-64
  • Uploaded using Trusted Publishing? No
  • Uploaded via: maturin/1.15.0

File hashes

Hashes for goygram-0.7.60-cp311-abi3-win_amd64.whl
Algorithm Hash digest
SHA256 faa3904972c96aa3e5a1fcfbb74d4ce46183ddea1c8c117a054e2ee99d50d6ca
MD5 61d8e0f1eafd3583d60d14a696fb352c
BLAKE2b-256 0b26d91240b1858a373c4a3365cb2beb12785ffe2826bb4eb0b0f9e0829dc7ec

See more details on using hashes here.

File details

Details for the file goygram-0.7.60-cp311-abi3-manylinux_2_34_x86_64.whl.

File metadata

File hashes

Hashes for goygram-0.7.60-cp311-abi3-manylinux_2_34_x86_64.whl
Algorithm Hash digest
SHA256 39ccf11d8702ffca90b44985f48289de05d4d3a280c45eca04bd319cb738b7ed
MD5 580c10f5af603f74da1b8b6e53ca2ffd
BLAKE2b-256 fabeff1cae67c951e62d52f27f42ba92bc916e3a42098d8072e5c6922872873c

See more details on using hashes here.

File details

Details for the file goygram-0.7.60-cp311-abi3-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for goygram-0.7.60-cp311-abi3-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 32e090509b574bd751301adc2766cbfd8d0a53b4f10be4aaf9cc9e09f31b4aa7
MD5 deb810a6e4671c13200f51884661444c
BLAKE2b-256 2b5af6e594ac475c81cbb585481749c9f286d29a62682c7312916c02776abf49

See more details on using hashes here.

Release history Release notifications | RSS feed

0.7.63

4 files

0.7.62

4 files

0.7.61

4 files

This release

0.7.60 This release

4 files

0.7.59

4 files

0.7.58

4 files

0.7.57

4 files

0.7.56

4 files

0.7.55

4 files

0.7.54

4 files

0.7.53

4 files

0.7.52

4 files

0.7.51

4 files

0.7.50

4 files

0.7.49

4 files

0.7.48

4 files

0.7.47

4 files

0.7.46

4 files

0.7.45

4 files

0.7.35

4 files

0.7.34

4 files

0.7.33

4 files

0.7.32

4 files

0.7.31

4 files

0.7.30

4 files

0.7.29

4 files

0.7.28

4 files

0.7.27

4 files

0.7.26

4 files

0.7.25

4 files

0.7.24

4 files

0.7.23

4 files

0.7.22

4 files

0.7.21

4 files

0.7.20

4 files

0.7.19

4 files

0.7.18

4 files

0.7.17

4 files

0.7.16

4 files

0.7.15

4 files

0.7.14

4 files

0.7.13

4 files

0.7.12

4 files

0.7.11

4 files

0.7.10

4 files

0.7.9

4 files

0.7.8

4 files

0.7.7

4 files

0.7.6

4 files

0.7.5

4 files

0.7.4

4 files

0.7.3

4 files

0.7.2

4 files

0.7.1

4 files

0.7.0

4 files

0.6.9

4 files

0.6.8

4 files

0.6.7

4 files

0.6.6

4 files

0.6.5

4 files

0.6.4

4 files

0.6.3

4 files

0.6.2

4 files

0.6.1

4 files

0.6.0

4 files

0.5.7

4 files

0.5.6

4 files

0.5.5

4 files

0.5.3

4 files

0.5.1

4 files

0.5.0

4 files

0.4.9

4 files

0.4.8

4 files

0.4.7

4 files

0.4.2

4 files

0.4.1

4 files

0.4.0

4 files

0.3.9

4 files

0.3.8

4 files

0.3.7

4 files

0.3.6

4 files

0.3.5

4 files

0.3.4

4 files

0.3.2

4 files

0.3.0

4 files

0.1.0

4 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