Goygram: unified Telegram runtime on Python and Rust
Project description
GoyGram
What is this?
Ultimate split-brain 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
- Split-brain architecture: ergonomic Python layer + blazing-fast Rust extension.
- Session Eater: aggressive in-memory cleanup (zeroize strategy for legacy
.sessionfiles 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_PROXYenv 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 onPHONE_MIGRATE_N) — in one app runtime. - Dynamic DC Routing: MTProto nodes are resolved at startup from a built-in DC map (5 Telegram DCs). Falls back to
149.154.167.50:443(DC 2) if resolution fails. - 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,MemberObjwith__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, separateself_id.
Installation
pip install goygram
Requires Python 3.11+. Rust is not required — pre-built wheels ship for Linux, Windows, and macOS (x86-64 + ARM64). Installs aiohttp, pydantic, rich, and qrcode as dependencies.
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 infarm_worker_1.vault. - If
farm_worker_1.sessionexists, it is migrated tofarm_worker_1.vaultduring bootstrap (securely zeroized after).
Dynamic API & Methods
GoyGram now supports all Telegram methods out of the box with dynamic dispatch:
- 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.
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-gcmcrate) - Key derivation: PBKDF2-HMAC-SHA256, 600,000 iterations, key material =
{machine-id}:{session_name} - Override:
GOYGRAM_VAULT_KEYenv var (base64-encoded 32 bytes) bypasses PBKDF2 entirely - Plain JSON fallback: if decryption fails, tries reading as plain JSON (auto-re-encrypts on next save)
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.
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
📚 55 pages of documentation... Every line of GoyGram, explained. 👉 Check out the Official GoyGram Wiki!
License
See LICENSE.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distributions
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file goygram-0.5.6.tar.gz.
File metadata
- Download URL: goygram-0.5.6.tar.gz
- Upload date:
- Size: 59.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: maturin/1.13.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
7df39a96ef21a32c08a98dffbd7586fb82beecbbf5a29fea90d8e64c5887f3d9
|
|
| MD5 |
8cadf98771c703f1281e228ef6ecee81
|
|
| BLAKE2b-256 |
e9f06ab35c1587f04d7c69e89c8ee7358ff5dfb05834ffcf3c5118abb55a4941
|
File details
Details for the file goygram-0.5.6-cp311-abi3-win_amd64.whl.
File metadata
- Download URL: goygram-0.5.6-cp311-abi3-win_amd64.whl
- Upload date:
- Size: 207.5 kB
- Tags: CPython 3.11+, Windows x86-64
- Uploaded using Trusted Publishing? No
- Uploaded via: maturin/1.13.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
6cee56a6a1bea5c29e94cff62e52a6dd59b4b145424ea52bab408c72ea01d1c8
|
|
| MD5 |
117d97344d9c6429685793b560610864
|
|
| BLAKE2b-256 |
eb949f1b3f6f1527cb54ca6aca11f0b505e42501cad0c2dd62bf575bbd3b5a88
|
File details
Details for the file goygram-0.5.6-cp311-abi3-manylinux_2_34_x86_64.whl.
File metadata
- Download URL: goygram-0.5.6-cp311-abi3-manylinux_2_34_x86_64.whl
- Upload date:
- Size: 290.9 kB
- Tags: CPython 3.11+, manylinux: glibc 2.34+ x86-64
- Uploaded using Trusted Publishing? No
- Uploaded via: maturin/1.13.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
7c71627dba056ab4fd3bcf7cd411b86491f1eb8cf0ba21252c96a4936b3166a0
|
|
| MD5 |
454b1eabe8dcee6a3e893f845ffc6a61
|
|
| BLAKE2b-256 |
a1314df69f2d4a957e3a0b0e5548c49f46b3f4b4716c89bbe1b30669e9ac0c5e
|
File details
Details for the file goygram-0.5.6-cp311-abi3-macosx_11_0_arm64.whl.
File metadata
- Download URL: goygram-0.5.6-cp311-abi3-macosx_11_0_arm64.whl
- Upload date:
- Size: 269.5 kB
- Tags: CPython 3.11+, macOS 11.0+ ARM64
- Uploaded using Trusted Publishing? No
- Uploaded via: maturin/1.13.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
c71934485e3451bbb7149782279d297490dddf327aba99bd186108fc55c1c98d
|
|
| MD5 |
2fa69935a6c6e2becb15e28933609bc5
|
|
| BLAKE2b-256 |
e5b6a5d71a8c3c2d27898618b2a6c4a950522aff211ec636bcd897dca542db31
|