ferogram 0.5.0b2__tar.gz → 0.5.2__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {ferogram-0.5.0b2 → ferogram-0.5.2}/.github/workflows/publish.yml +28 -12
- {ferogram-0.5.0b2 → ferogram-0.5.2}/CHANGELOG.md +108 -5
- {ferogram-0.5.0b2 → ferogram-0.5.2}/Cargo.lock +17 -17
- {ferogram-0.5.0b2 → ferogram-0.5.2}/Cargo.toml +7 -7
- {ferogram-0.5.0b2 → ferogram-0.5.2}/FEATURES.md +6 -0
- ferogram-0.5.2/PKG-INFO +162 -0
- ferogram-0.5.2/README.md +137 -0
- ferogram-0.5.2/assets/architecture.svg +130 -0
- {ferogram-0.5.0b2 → ferogram-0.5.2}/examples/admin_tools.py +5 -4
- {ferogram-0.5.0b2 → ferogram-0.5.2}/examples/command_bot.py +5 -4
- {ferogram-0.5.0b2 → ferogram-0.5.2}/examples/echo_bot.py +5 -4
- {ferogram-0.5.0b2 → ferogram-0.5.2}/examples/group_management.py +5 -4
- {ferogram-0.5.0b2 → ferogram-0.5.2}/examples/media_bot.py +5 -4
- {ferogram-0.5.0b2 → ferogram-0.5.2}/examples/raw_invoke.py +6 -5
- {ferogram-0.5.0b2 → ferogram-0.5.2}/examples/search_bot.py +5 -4
- {ferogram-0.5.0b2 → ferogram-0.5.2}/examples/send_hi.py +6 -5
- {ferogram-0.5.0b2 → ferogram-0.5.2}/examples/send_media.py +8 -5
- {ferogram-0.5.0b2 → ferogram-0.5.2}/examples/send_message.py +5 -4
- {ferogram-0.5.0b2 → ferogram-0.5.2}/examples/update_handlers.py +6 -5
- {ferogram-0.5.0b2 → ferogram-0.5.2}/examples/user_management.py +6 -5
- {ferogram-0.5.0b2 → ferogram-0.5.2}/examples/userbot.py +7 -5
- {ferogram-0.5.0b2 → ferogram-0.5.2}/ferogram/__init__.py +7 -5
- {ferogram-0.5.0b2 → ferogram-0.5.2}/ferogram/api.tl +58 -9
- {ferogram-0.5.0b2 → ferogram-0.5.2}/ferogram/client.py +660 -58
- {ferogram-0.5.0b2 → ferogram-0.5.2}/ferogram/filters.py +16 -7
- {ferogram-0.5.0b2 → ferogram-0.5.2}/ferogram/keyboards.py +5 -4
- {ferogram-0.5.0b2 → ferogram-0.5.2}/ferogram/logging.py +5 -4
- {ferogram-0.5.0b2 → ferogram-0.5.2}/ferogram/raw/__init__.py +5 -4
- {ferogram-0.5.0b2 → ferogram-0.5.2}/ferogram/raw/api/__init__.py +5 -4
- {ferogram-0.5.0b2 → ferogram-0.5.2}/ferogram/raw/api/functions.py +5 -4
- {ferogram-0.5.0b2 → ferogram-0.5.2}/ferogram/raw/api/types.py +5 -4
- {ferogram-0.5.0b2 → ferogram-0.5.2}/ferogram/raw/codegen.py +10 -8
- {ferogram-0.5.0b2 → ferogram-0.5.2}/ferogram/raw/generated/__init__.py +5 -4
- {ferogram-0.5.0b2 → ferogram-0.5.2}/ferogram/raw/generated/_tl_schema.py +82 -19
- {ferogram-0.5.0b2 → ferogram-0.5.2}/ferogram/raw/generated/functions/__init__.py +9 -4
- {ferogram-0.5.0b2 → ferogram-0.5.2}/ferogram/raw/generated/functions/account.py +5 -4
- {ferogram-0.5.0b2 → ferogram-0.5.2}/ferogram/raw/generated/functions/aicompose.py +5 -4
- {ferogram-0.5.0b2 → ferogram-0.5.2}/ferogram/raw/generated/functions/auth.py +5 -4
- {ferogram-0.5.0b2 → ferogram-0.5.2}/ferogram/raw/generated/functions/bots.py +5 -4
- {ferogram-0.5.0b2 → ferogram-0.5.2}/ferogram/raw/generated/functions/channels.py +12 -6
- {ferogram-0.5.0b2 → ferogram-0.5.2}/ferogram/raw/generated/functions/chatlists.py +5 -4
- ferogram-0.5.2/ferogram/raw/generated/functions/communities.py +375 -0
- {ferogram-0.5.0b2 → ferogram-0.5.2}/ferogram/raw/generated/functions/contacts.py +5 -4
- ferogram-0.5.2/ferogram/raw/generated/functions/ephemeral.py +241 -0
- {ferogram-0.5.0b2 → ferogram-0.5.2}/ferogram/raw/generated/functions/folders.py +5 -4
- {ferogram-0.5.0b2 → ferogram-0.5.2}/ferogram/raw/generated/functions/fragment.py +5 -4
- {ferogram-0.5.0b2 → ferogram-0.5.2}/ferogram/raw/generated/functions/help.py +5 -4
- {ferogram-0.5.0b2 → ferogram-0.5.2}/ferogram/raw/generated/functions/langpack.py +5 -4
- {ferogram-0.5.0b2 → ferogram-0.5.2}/ferogram/raw/generated/functions/messages.py +178 -7
- {ferogram-0.5.0b2 → ferogram-0.5.2}/ferogram/raw/generated/functions/payments.py +5 -4
- {ferogram-0.5.0b2 → ferogram-0.5.2}/ferogram/raw/generated/functions/phone.py +5 -4
- {ferogram-0.5.0b2 → ferogram-0.5.2}/ferogram/raw/generated/functions/photos.py +5 -4
- {ferogram-0.5.0b2 → ferogram-0.5.2}/ferogram/raw/generated/functions/premium.py +5 -4
- {ferogram-0.5.0b2 → ferogram-0.5.2}/ferogram/raw/generated/functions/smsjobs.py +5 -4
- {ferogram-0.5.0b2 → ferogram-0.5.2}/ferogram/raw/generated/functions/stats.py +5 -4
- {ferogram-0.5.0b2 → ferogram-0.5.2}/ferogram/raw/generated/functions/stickers.py +5 -4
- {ferogram-0.5.0b2 → ferogram-0.5.2}/ferogram/raw/generated/functions/stories.py +5 -4
- {ferogram-0.5.0b2 → ferogram-0.5.2}/ferogram/raw/generated/functions/updates.py +5 -4
- {ferogram-0.5.0b2 → ferogram-0.5.2}/ferogram/raw/generated/functions/upload.py +5 -4
- {ferogram-0.5.0b2 → ferogram-0.5.2}/ferogram/raw/generated/functions/users.py +5 -4
- {ferogram-0.5.0b2 → ferogram-0.5.2}/ferogram/raw/generated/types/__init__.py +7 -4
- {ferogram-0.5.0b2 → ferogram-0.5.2}/ferogram/raw/generated/types/_base.py +885 -15
- {ferogram-0.5.0b2 → ferogram-0.5.2}/ferogram/raw/generated/types/account.py +5 -4
- {ferogram-0.5.0b2 → ferogram-0.5.2}/ferogram/raw/generated/types/aicompose.py +5 -4
- {ferogram-0.5.0b2 → ferogram-0.5.2}/ferogram/raw/generated/types/auth.py +5 -4
- {ferogram-0.5.0b2 → ferogram-0.5.2}/ferogram/raw/generated/types/bots.py +5 -4
- {ferogram-0.5.0b2 → ferogram-0.5.2}/ferogram/raw/generated/types/channels.py +5 -4
- {ferogram-0.5.0b2 → ferogram-0.5.2}/ferogram/raw/generated/types/chatlists.py +5 -4
- ferogram-0.5.2/ferogram/raw/generated/types/communities.py +120 -0
- {ferogram-0.5.0b2 → ferogram-0.5.2}/ferogram/raw/generated/types/contacts.py +5 -4
- {ferogram-0.5.0b2 → ferogram-0.5.2}/ferogram/raw/generated/types/fragment.py +5 -4
- {ferogram-0.5.0b2 → ferogram-0.5.2}/ferogram/raw/generated/types/help.py +5 -4
- {ferogram-0.5.0b2 → ferogram-0.5.2}/ferogram/raw/generated/types/messages.py +70 -15
- {ferogram-0.5.0b2 → ferogram-0.5.2}/ferogram/raw/generated/types/payments.py +5 -4
- {ferogram-0.5.0b2 → ferogram-0.5.2}/ferogram/raw/generated/types/phone.py +5 -4
- {ferogram-0.5.0b2 → ferogram-0.5.2}/ferogram/raw/generated/types/photos.py +5 -4
- {ferogram-0.5.0b2 → ferogram-0.5.2}/ferogram/raw/generated/types/premium.py +5 -4
- {ferogram-0.5.0b2 → ferogram-0.5.2}/ferogram/raw/generated/types/smsjobs.py +5 -4
- {ferogram-0.5.0b2 → ferogram-0.5.2}/ferogram/raw/generated/types/stats.py +5 -4
- {ferogram-0.5.0b2 → ferogram-0.5.2}/ferogram/raw/generated/types/stickers.py +5 -4
- {ferogram-0.5.0b2 → ferogram-0.5.2}/ferogram/raw/generated/types/storage.py +5 -4
- {ferogram-0.5.0b2 → ferogram-0.5.2}/ferogram/raw/generated/types/stories.py +5 -4
- {ferogram-0.5.0b2 → ferogram-0.5.2}/ferogram/raw/generated/types/updates.py +5 -4
- {ferogram-0.5.0b2 → ferogram-0.5.2}/ferogram/raw/generated/types/upload.py +5 -4
- {ferogram-0.5.0b2 → ferogram-0.5.2}/ferogram/raw/generated/types/users.py +5 -4
- {ferogram-0.5.0b2 → ferogram-0.5.2}/ferogram/raw/proxy.py +5 -4
- {ferogram-0.5.0b2 → ferogram-0.5.2}/ferogram/raw/tl.py +5 -4
- {ferogram-0.5.0b2 → ferogram-0.5.2}/ferogram/types.py +87 -6
- {ferogram-0.5.0b2 → ferogram-0.5.2}/ferogram/updates.py +170 -22
- {ferogram-0.5.0b2 → ferogram-0.5.2}/pyproject.toml +2 -2
- {ferogram-0.5.0b2 → ferogram-0.5.2}/src/connection.rs +103 -10
- {ferogram-0.5.0b2 → ferogram-0.5.2}/src/lib.rs +3 -0
- ferogram-0.5.2/src/pipelined.rs +129 -0
- ferogram-0.5.0b2/PKG-INFO +0 -152
- ferogram-0.5.0b2/README.md +0 -127
- {ferogram-0.5.0b2 → ferogram-0.5.2}/.github/workflows/compile-check.yml +0 -0
- {ferogram-0.5.0b2 → ferogram-0.5.2}/.gitignore +0 -0
- {ferogram-0.5.0b2 → ferogram-0.5.2}/.readthedocs.yaml +0 -0
- {ferogram-0.5.0b2 → ferogram-0.5.2}/LICENSE-APACHE +0 -0
- {ferogram-0.5.0b2 → ferogram-0.5.2}/LICENSE-MIT +0 -0
- {ferogram-0.5.0b2 → ferogram-0.5.2}/Makefile +0 -0
- {ferogram-0.5.0b2 → ferogram-0.5.2}/build.rs +0 -0
- {ferogram-0.5.0b2 → ferogram-0.5.2}/examples/rich_message.py +0 -0
- {ferogram-0.5.0b2 → ferogram-0.5.2}/ferogram/py.typed +0 -0
- {ferogram-0.5.0b2 → ferogram-0.5.2}/ferogram/rich.py +0 -0
- {ferogram-0.5.0b2 → ferogram-0.5.2}/src/raw.rs +0 -0
- {ferogram-0.5.0b2 → ferogram-0.5.2}/src/session.rs +0 -0
- {ferogram-0.5.0b2 → ferogram-0.5.2}/src/srp.rs +0 -0
- {ferogram-0.5.0b2 → ferogram-0.5.2}/tests/test_rich.py +0 -0
- {ferogram-0.5.0b2 → ferogram-0.5.2}/tests/test_tl_roundtrip.py +0 -0
|
@@ -146,7 +146,7 @@ jobs:
|
|
|
146
146
|
- name: Install maturin
|
|
147
147
|
run: pip install maturin
|
|
148
148
|
|
|
149
|
-
- name: Fetch Termux
|
|
149
|
+
- name: Fetch Termux libpython for linking
|
|
150
150
|
run: |
|
|
151
151
|
TARGET=${{ matrix.target }}
|
|
152
152
|
case "$TARGET" in
|
|
@@ -166,21 +166,35 @@ jobs:
|
|
|
166
166
|
curl -sL "https://packages.termux.dev/apt/termux-main/${DEB_PATH}" -o python.deb
|
|
167
167
|
ar x python.deb
|
|
168
168
|
# data archive may be .tar.xz or .tar.zst depending on Termux version
|
|
169
|
-
|
|
169
|
+
# Don't pin the minor version here - Termux's "python" package always
|
|
170
|
+
# tracks upstream latest, and older debs fall out of the Packages
|
|
171
|
+
# index once superseded, so a hardcoded "libpython3.13" wildcard
|
|
172
|
+
# breaks the moment Termux bumps its default Python.
|
|
173
|
+
tar xf data.tar.* --wildcards "*/libpython3.*" 2>/dev/null || true
|
|
170
174
|
|
|
171
175
|
LIB_DIR=/tmp/termux-py/data/data/com.termux/files/usr/lib
|
|
172
|
-
|
|
173
|
-
if [
|
|
174
|
-
|
|
175
|
-
|
|
176
|
+
SO_FILE=$(ls "$LIB_DIR"/libpython3.*.so* 2>/dev/null | head -1)
|
|
177
|
+
if [ -z "$SO_FILE" ]; then
|
|
178
|
+
echo "::error::No libpython3.*.so found in Termux's python package ($DEB_PATH)"
|
|
179
|
+
exit 1
|
|
176
180
|
fi
|
|
181
|
+
|
|
182
|
+
# Extract "3.14" out of ".../libpython3.14.so"
|
|
183
|
+
PYVER=$(basename "$SO_FILE" | sed -E 's/^libpython(3\.[0-9]+)\.so.*/\1/')
|
|
184
|
+
UNVERSIONED="$LIB_DIR/libpython${PYVER}.so"
|
|
185
|
+
if [ ! -f "$UNVERSIONED" ]; then
|
|
186
|
+
ln -sf "$(basename "$SO_FILE")" "$UNVERSIONED"
|
|
187
|
+
fi
|
|
188
|
+
|
|
177
189
|
echo "TERMUX_LIBDIR=$LIB_DIR" >> $GITHUB_ENV
|
|
190
|
+
echo "TERMUX_PYVER=$PYVER" >> $GITHUB_ENV
|
|
191
|
+
echo "Linking against Termux libpython $PYVER ($SO_FILE)"
|
|
178
192
|
|
|
179
193
|
- name: Build Android wheel
|
|
180
194
|
env:
|
|
181
195
|
ANDROID_NDK_HOME: ${{ steps.ndk.outputs.ndk-path }}
|
|
182
196
|
ANDROID_API_LEVEL: ${{ matrix.api }}
|
|
183
|
-
PYO3_CROSS_PYTHON_VERSION:
|
|
197
|
+
PYO3_CROSS_PYTHON_VERSION: ${{ env.TERMUX_PYVER }}
|
|
184
198
|
run: |
|
|
185
199
|
NDK_BIN=$ANDROID_NDK_HOME/toolchains/llvm/prebuilt/linux-x86_64/bin
|
|
186
200
|
TARGET=${{ matrix.target }}
|
|
@@ -203,11 +217,13 @@ jobs:
|
|
|
203
217
|
export AR_${TARGET_LOWER}=$NDK_BIN/llvm-ar
|
|
204
218
|
export CARGO_TARGET_${TARGET_UPPER}_LINKER=$NDK_BIN/${CLANG_PREFIX}-clang
|
|
205
219
|
|
|
206
|
-
# Link against Termux's real
|
|
207
|
-
# This embeds DT_NEEDED:
|
|
208
|
-
# bionic resolves all Python symbols explicitly at
|
|
209
|
-
# Termux's LD_LIBRARY_PATH - instead of relying on
|
|
210
|
-
# propagation, which Android's linker does not
|
|
220
|
+
# Link against Termux's real libpython<version>.so (not an empty
|
|
221
|
+
# stub). This embeds DT_NEEDED: libpython<version>.so in the
|
|
222
|
+
# extension, so bionic resolves all Python symbols explicitly at
|
|
223
|
+
# dlopen time via Termux's LD_LIBRARY_PATH - instead of relying on
|
|
224
|
+
# global namespace propagation, which Android's linker does not
|
|
225
|
+
# guarantee. The version is whatever Termux's apt repo currently
|
|
226
|
+
# ships (see the fetch step above), not a fixed constant.
|
|
211
227
|
export RUSTFLAGS="-L native=$TERMUX_LIBDIR"
|
|
212
228
|
|
|
213
229
|
maturin build \
|
|
@@ -1,3 +1,110 @@
|
|
|
1
|
+
## 0.5.2 (2026-07-17)
|
|
2
|
+
|
|
3
|
+
- Added `Client.get_chat_photos(peer, limit)`: photo/avatar history for groups and channels (`get_profile_photos` only ever worked for users). Current photo comes from the chat's full info, so it survives message deletion; older photos come from `messageActionChatEditPhoto` search history.
|
|
4
|
+
- Added fast re-auth support: `sign_out()` captures a `future_auth_token` when Telegram returns one and persists it via a new `DcConnection.get_future_auth_token`/`set_future_auth_token` pair (rides along in the existing session blob, no new session format code needed here). `request_login_code()` replays it automatically, so a returning session can skip code entry entirely (`auth.sentCodeSuccess`).
|
|
5
|
+
- MTProto handshake fix upstream (dc-tagged `p_q_inner_data` was being rejected by Telegram with RPC 444 outside DC2), pulled in transitively via `ferogram-mtsender`.
|
|
6
|
+
- Layer Upgrade to 228
|
|
7
|
+
## 0.5.1 (2026-06-29)
|
|
8
|
+
|
|
9
|
+
## What's Changed
|
|
10
|
+
|
|
11
|
+
### Message API Improvements
|
|
12
|
+
|
|
13
|
+
- `Message.reply()` now creates a proper quoted reply using `reply_to=self.id`.
|
|
14
|
+
- Added `Message.respond()` for sending messages to the same chat without replying.
|
|
15
|
+
- Added `pin()`, `forward_to()`, `get_sender()`, `get_chat()`, and `get_reply_message()` helpers.
|
|
16
|
+
- Added `reply_photo()` and `reply_document()` convenience methods.
|
|
17
|
+
- Improved `delete()` to correctly handle channels and supergroups.
|
|
18
|
+
|
|
19
|
+
### Client Enhancements
|
|
20
|
+
|
|
21
|
+
- Added `reply_to` support to `send_message()`, `send_photo()`, and `send_document()`.
|
|
22
|
+
- Added `Client.get_user()` and `Client.get_chat()` helpers.
|
|
23
|
+
- `edit_message()` now accepts `reply_markup`.
|
|
24
|
+
- `pin_message()` now supports a `notify` parameter.
|
|
25
|
+
- Improved `delete_messages_in()` for channel-aware message deletion.
|
|
26
|
+
- Improved sent message extraction fallback behavior with warning logging and preserved context.
|
|
27
|
+
|
|
28
|
+
### Update Improvements
|
|
29
|
+
|
|
30
|
+
- Added convenience methods to `CallbackQuery`:
|
|
31
|
+
- `respond()`
|
|
32
|
+
- `reply()`
|
|
33
|
+
- `edit_message_text()`
|
|
34
|
+
- `get_sender()`
|
|
35
|
+
|
|
36
|
+
- Added convenience methods to `InlineQuery`:
|
|
37
|
+
- `answer()`
|
|
38
|
+
- `get_sender()`
|
|
39
|
+
|
|
40
|
+
- Added sender/entity helpers for additional update types, including:
|
|
41
|
+
- `InlineSend`
|
|
42
|
+
- `UserStatus`
|
|
43
|
+
- `ChatAction`
|
|
44
|
+
- `JoinRequest`
|
|
45
|
+
- `ParticipantUpdate`
|
|
46
|
+
- `MessageReaction`
|
|
47
|
+
- `ChatBoost`
|
|
48
|
+
- `ShippingQuery`
|
|
49
|
+
- `PreCheckoutQuery`
|
|
50
|
+
|
|
51
|
+
### Dispatch Improvements
|
|
52
|
+
|
|
53
|
+
- `_dispatch()` now binds `_client` for all update types.
|
|
54
|
+
- Added `_client` support to remaining update wrappers, including `RawUpdate`.
|
|
55
|
+
- Improved sent message extraction fallback handling.
|
|
56
|
+
|
|
57
|
+
## 0.5.0 (2026-06-28)
|
|
58
|
+
|
|
59
|
+
### Architecture
|
|
60
|
+
|
|
61
|
+
The Rust dependency has changed from the monolithic `ferogram` crate to five focused crates from the ferogram core:
|
|
62
|
+
|
|
63
|
+
- `ferogram-mtsender` - MTProto sender, message framing, and acknowledgement
|
|
64
|
+
- `ferogram-session` - session storage (file, sqlite, libsql, memory, string)
|
|
65
|
+
- `ferogram-connect` - TCP/TLS transport and DC routing
|
|
66
|
+
- `ferogram-tl-types` - generated TL type definitions
|
|
67
|
+
- `ferogram-crypto` - AES-IGE, Diffie-Hellman, and SHA helpers
|
|
68
|
+
|
|
69
|
+
These five crates form the battle-tested lower layer of ferogram. They change rarely and are stable across minor versions. All high-level logic (message parsing, update dispatch, peer resolution, serialization, deserialization) now lives in Python. This split means the compiled extension is smaller and faster to build, and Python-side behaviour can be updated without recompiling the Rust extension.
|
|
70
|
+
|
|
71
|
+
The compiled extension now uses `abi3-py39` (was `abi3-py313`), so a single wheel runs on Python 3.9 and later.
|
|
72
|
+
|
|
73
|
+
### Added
|
|
74
|
+
|
|
75
|
+
- **`TransferHandle`** - pause, resume, and cancel any upload or download in flight. Create a `TransferHandle`, pass it to `upload_with_progress` or `download_with_progress`, then call `.pause()`, `.resume()`, or `.cancel()` from any coroutine. `.progress()` returns a dict with `done`, `total`, `elapsed_ms`, `percent`, `speed_bps`, `eta_secs`, `speed_human`, and `bytes_human`.
|
|
76
|
+
- **`TransferCancelled` exception** - raised when a `TransferHandle` is cancelled mid-transfer.
|
|
77
|
+
- **`keyboards` module** - `InlineKeyboard`, `InlineButton`, `ReplyKeyboard`, `ReplyButton`, `RemoveKeyboard`, and `ForceReply` are now pure Python and importable from `ferogram` directly.
|
|
78
|
+
- **`types` module** - all entity types (`User`, `Message`, `Chat`, `Dialog`, `ChatMember`, `UserFull`, `Authorization`, `ForumTopic`, `BotInfo`, `InviteLinkMember`, `ReadParticipant`, `AdminLogEvent`, `StickerSetInfo`, `BroadcastStats`, `MegagroupStats`, `NotifySettings`) moved from Rust to Python dataclasses. The public API is identical.
|
|
79
|
+
- **`updates` module** - update wrapper types (`NewMessage`, `EditedMessage`, `MessageDeletion`, `CallbackQuery`, `InlineQuery`, `InlineSend`, `UserStatus`, `ParticipantUpdate`, `JoinRequest`, `MessageReaction`, `PollVote`, `BotStopped`, `ShippingQuery`, `PreCheckoutQuery`, `ChatBoost`, `RawUpdate`) moved from Rust to Python dataclasses.
|
|
80
|
+
- **`rich` module** - `send_rich_message`, `edit_rich_message`, `send_rich_message_draft`, and `get_rich_message` via a `_RichMixin`. Supports Telegram rich text blocks including headers, tables, collages, task lists, footnotes, math, time stamps, and custom emoji via Markdown or HTML input.
|
|
81
|
+
- **Automatic TL codegen at build time** - `build.rs` now runs `ferogram/raw/codegen.py` during `maturin develop` / `pip install .`. Set `FEROGRAM_SKIP_CODEGEN=1` to skip if you only changed Rust. The codegen uses the same Python interpreter maturin selected.
|
|
82
|
+
- **`DcConnection` and `srp_calculate`** exposed from the Rust extension for use by the pure-Python `Client` class.
|
|
83
|
+
- **`LAYER` constant** exported from `ferogram.raw.generated._tl_schema` and used automatically in `invokeWithLayer` wrappers.
|
|
84
|
+
- **`all_updates` filter** - replaces the old `all` filter (which shadowed the built-in).
|
|
85
|
+
- **`filters` improvements** - all filters now unwrap `NewMessage` / `EditedMessage` wrapper objects before inspecting the inner `Message`. Previously filters broke when the dispatcher passed wrapper objects instead of bare messages.
|
|
86
|
+
|
|
87
|
+
### Changed
|
|
88
|
+
|
|
89
|
+
- `Message`, `User`, `Chat`, and all entity types are now Python dataclasses instead of PyO3 structs. They serialize to / from the TL dict representation in Python. No change to the public API.
|
|
90
|
+
- `CallbackQuery`, `InlineQuery`, and all update types are now Python dataclasses.
|
|
91
|
+
- `InlineKeyboard`, `ReplyKeyboard`, and related keyboard builders are now pure Python (`ferogram/keyboards.py`). Previously they were Rust structs.
|
|
92
|
+
- Filters rewritten to correctly unwrap update wrapper objects. `reply` filter now checks `reply_to_msg_id`; `forwarded` checks `forward_from_id`; `media` checks the `media` field directly.
|
|
93
|
+
- `codegen.py` doubled in size (321 to 691 lines): now generates specialized `to_bytes()` methods using `struct.pack` inline and a CID-dispatch `from_bytes()` router, producing faster serialization and deserialization than the previous schema-dict approach.
|
|
94
|
+
- `ferogram-py` version bump to 0.5.0. Core crates pinned to `ferogram-*` 0.6.3.
|
|
95
|
+
|
|
96
|
+
### Removed
|
|
97
|
+
|
|
98
|
+
- Direct dependency on the monolithic `ferogram` crate. The five focused crates replace it.
|
|
99
|
+
- `hex` crate dependency (was `0.4`, now unused).
|
|
100
|
+
- `all` filter removed and replaced with `all_updates` to avoid shadowing Python's built-in `all`.
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
## 0.4.1 (2026-06-03)
|
|
104
|
+
|
|
105
|
+
Patch release. No API changes. Identical to 0.4.0 except for dependency pins and minor internal fixes.
|
|
106
|
+
|
|
107
|
+
|
|
1
108
|
## 0.4.0 (2026-06-01)
|
|
2
109
|
|
|
3
110
|
### Added
|
|
@@ -20,7 +127,7 @@
|
|
|
20
127
|
- **`flood_sleep_threshold` kwarg on `Client`** - maps to the `AutoSleep` retry policy in the Rust core. Flood waits under this value are slept through automatically; waits above it are raised as exceptions.
|
|
21
128
|
- **`download_with_progress(peer, msg_id, path, on_progress)`** - download media with a progress callback `on_progress(done, total)`.
|
|
22
129
|
- **`upload_with_progress(path, on_progress)`** - upload a file with a progress callback. Returns a handle string accepted by `send_file`.
|
|
23
|
-
-
|
|
130
|
+
- **ferogram 0.6.0 as core dependency** - includes `Client.channel_kind_of(channel_id)` which backs the new `Message` methods above.
|
|
24
131
|
|
|
25
132
|
### Changed
|
|
26
133
|
|
|
@@ -62,9 +169,6 @@ the votes graph as a JSON string. The old `get_poll_results(peer, msg_id, poll_h
|
|
|
62
169
|
is kept for backward compat but is deprecated; the `poll_hash` parameter is ignored
|
|
63
170
|
because ferogram 0.5.0 dropped the underlying API call it relied on.
|
|
64
171
|
|
|
65
|
-
---
|
|
66
|
-
|
|
67
|
-
# Changelog
|
|
68
172
|
|
|
69
173
|
## 0.2.3 (2026-05-14)
|
|
70
174
|
|
|
@@ -124,7 +228,6 @@ Ten new methods for managing group and channel members.
|
|
|
124
228
|
|
|
125
229
|
`get_poll_results(peer, msg_id, poll_hash)` was in Rust but had no Python wrapper. Now exposed. Fetches and caches the latest poll results from Telegram.
|
|
126
230
|
|
|
127
|
-
---
|
|
128
231
|
|
|
129
232
|
## 0.2.2
|
|
130
233
|
|
|
@@ -392,9 +392,9 @@ checksum = "7360491ce676a36bf9bb3c56c1aa791658183a54d2744120f27285738d90465a"
|
|
|
392
392
|
|
|
393
393
|
[[package]]
|
|
394
394
|
name = "ferogram-connect"
|
|
395
|
-
version = "0.6.
|
|
395
|
+
version = "0.6.4"
|
|
396
396
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
397
|
-
checksum = "
|
|
397
|
+
checksum = "54211f9669f8bb7db8101d952514784311a1e135c01eb04d8732d465cdb2aa73"
|
|
398
398
|
dependencies = [
|
|
399
399
|
"ferogram-crypto",
|
|
400
400
|
"ferogram-mtproto",
|
|
@@ -409,9 +409,9 @@ dependencies = [
|
|
|
409
409
|
|
|
410
410
|
[[package]]
|
|
411
411
|
name = "ferogram-crypto"
|
|
412
|
-
version = "0.6.
|
|
412
|
+
version = "0.6.4"
|
|
413
413
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
414
|
-
checksum = "
|
|
414
|
+
checksum = "0e9b1bf8c53553a3fa8acbfdc0f9f9ede749f786a5d62c26c57a4dd20b793b4d"
|
|
415
415
|
dependencies = [
|
|
416
416
|
"aes",
|
|
417
417
|
"ctr",
|
|
@@ -427,9 +427,9 @@ dependencies = [
|
|
|
427
427
|
|
|
428
428
|
[[package]]
|
|
429
429
|
name = "ferogram-mtproto"
|
|
430
|
-
version = "0.6.
|
|
430
|
+
version = "0.6.4"
|
|
431
431
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
432
|
-
checksum = "
|
|
432
|
+
checksum = "007456e26302ca4a2f63019ed88c2055705ecf7752f823520d41aa2f8803b42e"
|
|
433
433
|
dependencies = [
|
|
434
434
|
"ferogram-crypto",
|
|
435
435
|
"ferogram-tl-types",
|
|
@@ -441,9 +441,9 @@ dependencies = [
|
|
|
441
441
|
|
|
442
442
|
[[package]]
|
|
443
443
|
name = "ferogram-mtsender"
|
|
444
|
-
version = "0.6.
|
|
444
|
+
version = "0.6.4"
|
|
445
445
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
446
|
-
checksum = "
|
|
446
|
+
checksum = "4fb2d34f025b0c6369d42f08317e3ded5bb8aa83bdec48fd443a4cc26fa4c9cf"
|
|
447
447
|
dependencies = [
|
|
448
448
|
"ferogram-connect",
|
|
449
449
|
"ferogram-crypto",
|
|
@@ -457,7 +457,7 @@ dependencies = [
|
|
|
457
457
|
|
|
458
458
|
[[package]]
|
|
459
459
|
name = "ferogram-py"
|
|
460
|
-
version = "0.5.
|
|
460
|
+
version = "0.5.2"
|
|
461
461
|
dependencies = [
|
|
462
462
|
"base64 0.22.1",
|
|
463
463
|
"ferogram-connect",
|
|
@@ -474,9 +474,9 @@ dependencies = [
|
|
|
474
474
|
|
|
475
475
|
[[package]]
|
|
476
476
|
name = "ferogram-session"
|
|
477
|
-
version = "0.6.
|
|
477
|
+
version = "0.6.4"
|
|
478
478
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
479
|
-
checksum = "
|
|
479
|
+
checksum = "c29506aee6e38e3f62623f28f17dfa470f347a87f65030313bf62f9b8dd12dd1"
|
|
480
480
|
dependencies = [
|
|
481
481
|
"base64 0.22.1",
|
|
482
482
|
"libsql",
|
|
@@ -488,24 +488,24 @@ dependencies = [
|
|
|
488
488
|
|
|
489
489
|
[[package]]
|
|
490
490
|
name = "ferogram-tl-gen"
|
|
491
|
-
version = "0.6.
|
|
491
|
+
version = "0.6.4"
|
|
492
492
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
493
|
-
checksum = "
|
|
493
|
+
checksum = "501f1b96b5981e83d8328391dc6aa31df208dd8662f2b814117a345e570060ae"
|
|
494
494
|
dependencies = [
|
|
495
495
|
"ferogram-tl-parser",
|
|
496
496
|
]
|
|
497
497
|
|
|
498
498
|
[[package]]
|
|
499
499
|
name = "ferogram-tl-parser"
|
|
500
|
-
version = "0.6.
|
|
500
|
+
version = "0.6.4"
|
|
501
501
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
502
|
-
checksum = "
|
|
502
|
+
checksum = "d7337bdfb8be8eee3155a1af8ead1c34c2cfc2de738428574b1661d2094a7389"
|
|
503
503
|
|
|
504
504
|
[[package]]
|
|
505
505
|
name = "ferogram-tl-types"
|
|
506
|
-
version = "0.6.
|
|
506
|
+
version = "0.6.4"
|
|
507
507
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
508
|
-
checksum = "
|
|
508
|
+
checksum = "61d5a7ed4c2996730a9a35d06a33abaadc246dd828ba1ab5727bd5bbd8699a95"
|
|
509
509
|
dependencies = [
|
|
510
510
|
"ferogram-tl-gen",
|
|
511
511
|
"ferogram-tl-parser",
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
[package]
|
|
2
2
|
name = "ferogram-py"
|
|
3
|
-
version = "0.5.
|
|
3
|
+
version = "0.5.2"
|
|
4
4
|
edition = "2024"
|
|
5
|
-
description = "Python
|
|
5
|
+
description = "Python MTProto client based on ferogram (Rust MTProto)"
|
|
6
6
|
build = "build.rs"
|
|
7
7
|
license = "MIT OR Apache-2.0"
|
|
8
8
|
readme = "README.md"
|
|
@@ -12,11 +12,11 @@ name = "_ferogram"
|
|
|
12
12
|
crate-type = ["cdylib"]
|
|
13
13
|
|
|
14
14
|
[dependencies]
|
|
15
|
-
ferogram-mtsender = { version = "0.6.
|
|
16
|
-
ferogram-session = { version = "0.6.
|
|
17
|
-
ferogram-connect = { version = "0.6.
|
|
18
|
-
ferogram-tl-types = { version = "0.6.
|
|
19
|
-
ferogram-crypto = { version = "0.6.
|
|
15
|
+
ferogram-mtsender = { version = "0.6.4" }
|
|
16
|
+
ferogram-session = { version = "0.6.4", features = ["sqlite-session", "libsql-session"] }
|
|
17
|
+
ferogram-connect = { version = "0.6.4" }
|
|
18
|
+
ferogram-tl-types = { version = "0.6.4" }
|
|
19
|
+
ferogram-crypto = { version = "0.6.4" }
|
|
20
20
|
getrandom = "0.2"
|
|
21
21
|
base64 = "0.22"
|
|
22
22
|
pyo3 = { version = "0.24", features = ["extension-module", "abi3-py39"] }
|
|
@@ -387,6 +387,7 @@ await client.upload_with_progress(path, on_progress=None)
|
|
|
387
387
|
await client.edit_chat_photo(peer, path)
|
|
388
388
|
await client.delete_profile_photos()
|
|
389
389
|
await client.get_profile_photos(peer, limit=100)
|
|
390
|
+
await client.get_chat_photos(peer, limit=100)
|
|
390
391
|
```
|
|
391
392
|
|
|
392
393
|
Important current behavior:
|
|
@@ -642,6 +643,11 @@ await client.get_authorizations()
|
|
|
642
643
|
await client.terminate_session(hash)
|
|
643
644
|
```
|
|
644
645
|
|
|
646
|
+
`sign_out()` captures a `future_auth_token` when Telegram provides one, and
|
|
647
|
+
`request_login_code()` replays it automatically on the next login. When
|
|
648
|
+
that succeeds, Telegram authorizes the session immediately, no code entry
|
|
649
|
+
needed - check for `"_": "auth.sentCodeSuccess"` on the returned dict.
|
|
650
|
+
|
|
645
651
|
## Bot management
|
|
646
652
|
|
|
647
653
|
```python
|
ferogram-0.5.2/PKG-INFO
ADDED
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: ferogram
|
|
3
|
+
Version: 0.5.2
|
|
4
|
+
Classifier: Development Status :: 3 - Alpha
|
|
5
|
+
Classifier: Intended Audience :: Developers
|
|
6
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
7
|
+
Classifier: Programming Language :: Python :: 3
|
|
8
|
+
Classifier: Programming Language :: Rust
|
|
9
|
+
Classifier: Topic :: Communications :: Chat
|
|
10
|
+
Classifier: Topic :: Software Development :: Libraries
|
|
11
|
+
License-File: LICENSE-APACHE
|
|
12
|
+
License-File: LICENSE-MIT
|
|
13
|
+
Summary: A modern, elegant, asynchronous MTProto framework for building Telegram user clients and bots in Python.
|
|
14
|
+
Keywords: telegram,mtproto,rust,client,bot,ferogram
|
|
15
|
+
Author-email: Ankit Chaubey <ankitchaubey.dev@gmail.com>
|
|
16
|
+
License: MIT OR Apache-2.0
|
|
17
|
+
Requires-Python: >=3.9
|
|
18
|
+
Description-Content-Type: text/markdown; charset=UTF-8; variant=GFM
|
|
19
|
+
Project-URL: Author, https://github.com/ankit-chaubey
|
|
20
|
+
Project-URL: Documentation, https://github.com/ankit-chaubey/ferogram-py#readme
|
|
21
|
+
Project-URL: Homepage, https://github.com/ankit-chaubey/ferogram-py
|
|
22
|
+
Project-URL: Source, https://github.com/ankit-chaubey/ferogram-py
|
|
23
|
+
Project-URL: Tracker, https://github.com/ankit-chaubey/ferogram-py/issues
|
|
24
|
+
|
|
25
|
+
<div align="center">
|
|
26
|
+
|
|
27
|
+
# ferogram-py
|
|
28
|
+
|
|
29
|
+

|
|
30
|
+

|
|
31
|
+

|
|
32
|
+

|
|
33
|
+

|
|
34
|
+
|
|
35
|
+
**A modern, elegant, asynchronous MTProto framework for building Telegram user clients and bots in Python.**
|
|
36
|
+
|
|
37
|
+
</div>
|
|
38
|
+
|
|
39
|
+
Powered by a high-performance [Rust core](https://github.com/ankit-chaubey/ferogram) that takes care of networking, encryption, TL parsing, and session management so you can focus on writing clean, idiomatic Python.
|
|
40
|
+
|
|
41
|
+
---
|
|
42
|
+
|
|
43
|
+
## Why ferogram-py?
|
|
44
|
+
|
|
45
|
+
Most of the heavy lifting in an MTProto client happens behind the scenes; networking, encryption, TL parsing, and keeping up with updates. ferogram-py lets a Rust core handle all of that, while exposing a clean, Pythonic API.
|
|
46
|
+
|
|
47
|
+
For most applications, the high-level API is all you'll need. But if you want to use a brand-new Telegram feature or need something more advanced, you can always drop down to the raw MTProto API and invoke requests directly.
|
|
48
|
+
|
|
49
|
+
The goal is to stay out of your way: simple things should be simple, and advanced things should still be possible.
|
|
50
|
+
|
|
51
|
+
> Quick API reference: [FEATURES.md](./FEATURES.md)
|
|
52
|
+
|
|
53
|
+
---
|
|
54
|
+
|
|
55
|
+
## Install
|
|
56
|
+
|
|
57
|
+
```bash
|
|
58
|
+
pip install ferogram
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
<details>
|
|
62
|
+
<summary>Building from source</summary>
|
|
63
|
+
|
|
64
|
+
```bash
|
|
65
|
+
make dev # editable install into .venv (builds the Rust extension)
|
|
66
|
+
make build # release wheel for this machine
|
|
67
|
+
make codegen # regenerate TL code without a Rust rebuild
|
|
68
|
+
make test # run tests
|
|
69
|
+
make clean # wipe .venv, target, dist, generated/
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
On Termux: `pkg install rust clang python` first.
|
|
73
|
+
Rust-only change, don't want to wait on codegen: `FEROGRAM_SKIP_CODEGEN=1 maturin develop`
|
|
74
|
+
|
|
75
|
+
</details>
|
|
76
|
+
|
|
77
|
+
---
|
|
78
|
+
|
|
79
|
+
## Quick start
|
|
80
|
+
|
|
81
|
+
**Bot:**
|
|
82
|
+
|
|
83
|
+
```python
|
|
84
|
+
from ferogram import Client, filters
|
|
85
|
+
|
|
86
|
+
app = Client("mybot", api_id=0, api_hash="", bot_token="123:TOKEN")
|
|
87
|
+
|
|
88
|
+
@app.on_message(filters.command("start"))
|
|
89
|
+
async def start(client, message):
|
|
90
|
+
await message.reply("Hello!")
|
|
91
|
+
|
|
92
|
+
app.run()
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
**User:**
|
|
96
|
+
|
|
97
|
+
```python
|
|
98
|
+
import asyncio
|
|
99
|
+
from ferogram import Client
|
|
100
|
+
|
|
101
|
+
app = Client("myaccount", api_id=0, api_hash="", phone="+1234567890")
|
|
102
|
+
|
|
103
|
+
async def main():
|
|
104
|
+
async with app as client:
|
|
105
|
+
await client.send_message("me", "logged in")
|
|
106
|
+
|
|
107
|
+
asyncio.run(main())
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
Credentials also work from env vars: `API_ID`, `API_HASH`, `BOT_TOKEN`.
|
|
111
|
+
|
|
112
|
+
## Logging
|
|
113
|
+
|
|
114
|
+
```python
|
|
115
|
+
import ferogram.logging as fero_log
|
|
116
|
+
|
|
117
|
+
fero_log.setup() # INFO to stderr
|
|
118
|
+
fero_log.setup(level=10) # DEBUG
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
## Architecture
|
|
122
|
+
|
|
123
|
+

|
|
124
|
+
|
|
125
|
+
The compiled extension (`_ferogram.so`) stays deliberately small: networking, encryption, session storage, and MTProto internals live in Rust. Everything you touch day to day, the client, handlers, filters, is plain Python and can change without a recompile.
|
|
126
|
+
|
|
127
|
+
<details>
|
|
128
|
+
<summary>Prebuilt Wheels for your platform</summary>
|
|
129
|
+
|
|
130
|
+
Wheels ship prebuilt for Linux (x86_64, aarch64), macOS (x86_64, arm64), Windows (x86_64), and Android/Termux (aarch64, x86_64). `pip install ferogram` grabs the right one on its own.
|
|
131
|
+
|
|
132
|
+
</details>
|
|
133
|
+
|
|
134
|
+
---
|
|
135
|
+
|
|
136
|
+
## License
|
|
137
|
+
|
|
138
|
+
This project is dual-licensed under:
|
|
139
|
+
|
|
140
|
+
- MIT License
|
|
141
|
+
- Apache License 2.0
|
|
142
|
+
|
|
143
|
+
You may choose either license.
|
|
144
|
+
|
|
145
|
+
You are free to use, modify, and distribute this software, including for commercial use, provided the original license and copyright notice are included.
|
|
146
|
+
|
|
147
|
+
See [`LICENSE-MIT`](https://github.com/ankit-chaubey/ferogram-py/blob/main/LICENSE-MIT) and [`LICENSE-APACHE`](https://github.com/ankit-chaubey/ferogram-py/blob/main/LICENSE-APACHE) for full details.
|
|
148
|
+
|
|
149
|
+
---
|
|
150
|
+
|
|
151
|
+
## Developer
|
|
152
|
+
|
|
153
|
+
Developed by [Ankit Chaubey](https://github.com/ankit-chaubey)
|
|
154
|
+
|
|
155
|
+
Don't forget to explore the Rust engine powering ferogram-py: [`ferogram`](https://github.com/ankit-chaubey/ferogram). Thanks for being part of the journey.
|
|
156
|
+
|
|
157
|
+
Join the ferogram community! Questions, discussions, bugs report and feedback are always welcome. As the project grows, we'll eventually split Python and Rust discussions into dedicated spaces.
|
|
158
|
+
|
|
159
|
+
- Channel (releases & announcements): [@Ferogram](https://t.me/Ferogram)
|
|
160
|
+
|
|
161
|
+
- (questions & discussion): [@FerogramChat](https://t.me/FerogramChat)
|
|
162
|
+
|
ferogram-0.5.2/README.md
ADDED
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
<div align="center">
|
|
2
|
+
|
|
3
|
+
# ferogram-py
|
|
4
|
+
|
|
5
|
+

|
|
6
|
+

|
|
7
|
+

|
|
8
|
+

|
|
9
|
+

|
|
10
|
+
|
|
11
|
+
**A modern, elegant, asynchronous MTProto framework for building Telegram user clients and bots in Python.**
|
|
12
|
+
|
|
13
|
+
</div>
|
|
14
|
+
|
|
15
|
+
Powered by a high-performance [Rust core](https://github.com/ankit-chaubey/ferogram) that takes care of networking, encryption, TL parsing, and session management so you can focus on writing clean, idiomatic Python.
|
|
16
|
+
|
|
17
|
+
---
|
|
18
|
+
|
|
19
|
+
## Why ferogram-py?
|
|
20
|
+
|
|
21
|
+
Most of the heavy lifting in an MTProto client happens behind the scenes; networking, encryption, TL parsing, and keeping up with updates. ferogram-py lets a Rust core handle all of that, while exposing a clean, Pythonic API.
|
|
22
|
+
|
|
23
|
+
For most applications, the high-level API is all you'll need. But if you want to use a brand-new Telegram feature or need something more advanced, you can always drop down to the raw MTProto API and invoke requests directly.
|
|
24
|
+
|
|
25
|
+
The goal is to stay out of your way: simple things should be simple, and advanced things should still be possible.
|
|
26
|
+
|
|
27
|
+
> Quick API reference: [FEATURES.md](./FEATURES.md)
|
|
28
|
+
|
|
29
|
+
---
|
|
30
|
+
|
|
31
|
+
## Install
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
pip install ferogram
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
<details>
|
|
38
|
+
<summary>Building from source</summary>
|
|
39
|
+
|
|
40
|
+
```bash
|
|
41
|
+
make dev # editable install into .venv (builds the Rust extension)
|
|
42
|
+
make build # release wheel for this machine
|
|
43
|
+
make codegen # regenerate TL code without a Rust rebuild
|
|
44
|
+
make test # run tests
|
|
45
|
+
make clean # wipe .venv, target, dist, generated/
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
On Termux: `pkg install rust clang python` first.
|
|
49
|
+
Rust-only change, don't want to wait on codegen: `FEROGRAM_SKIP_CODEGEN=1 maturin develop`
|
|
50
|
+
|
|
51
|
+
</details>
|
|
52
|
+
|
|
53
|
+
---
|
|
54
|
+
|
|
55
|
+
## Quick start
|
|
56
|
+
|
|
57
|
+
**Bot:**
|
|
58
|
+
|
|
59
|
+
```python
|
|
60
|
+
from ferogram import Client, filters
|
|
61
|
+
|
|
62
|
+
app = Client("mybot", api_id=0, api_hash="", bot_token="123:TOKEN")
|
|
63
|
+
|
|
64
|
+
@app.on_message(filters.command("start"))
|
|
65
|
+
async def start(client, message):
|
|
66
|
+
await message.reply("Hello!")
|
|
67
|
+
|
|
68
|
+
app.run()
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
**User:**
|
|
72
|
+
|
|
73
|
+
```python
|
|
74
|
+
import asyncio
|
|
75
|
+
from ferogram import Client
|
|
76
|
+
|
|
77
|
+
app = Client("myaccount", api_id=0, api_hash="", phone="+1234567890")
|
|
78
|
+
|
|
79
|
+
async def main():
|
|
80
|
+
async with app as client:
|
|
81
|
+
await client.send_message("me", "logged in")
|
|
82
|
+
|
|
83
|
+
asyncio.run(main())
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
Credentials also work from env vars: `API_ID`, `API_HASH`, `BOT_TOKEN`.
|
|
87
|
+
|
|
88
|
+
## Logging
|
|
89
|
+
|
|
90
|
+
```python
|
|
91
|
+
import ferogram.logging as fero_log
|
|
92
|
+
|
|
93
|
+
fero_log.setup() # INFO to stderr
|
|
94
|
+
fero_log.setup(level=10) # DEBUG
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
## Architecture
|
|
98
|
+
|
|
99
|
+

|
|
100
|
+
|
|
101
|
+
The compiled extension (`_ferogram.so`) stays deliberately small: networking, encryption, session storage, and MTProto internals live in Rust. Everything you touch day to day, the client, handlers, filters, is plain Python and can change without a recompile.
|
|
102
|
+
|
|
103
|
+
<details>
|
|
104
|
+
<summary>Prebuilt Wheels for your platform</summary>
|
|
105
|
+
|
|
106
|
+
Wheels ship prebuilt for Linux (x86_64, aarch64), macOS (x86_64, arm64), Windows (x86_64), and Android/Termux (aarch64, x86_64). `pip install ferogram` grabs the right one on its own.
|
|
107
|
+
|
|
108
|
+
</details>
|
|
109
|
+
|
|
110
|
+
---
|
|
111
|
+
|
|
112
|
+
## License
|
|
113
|
+
|
|
114
|
+
This project is dual-licensed under:
|
|
115
|
+
|
|
116
|
+
- MIT License
|
|
117
|
+
- Apache License 2.0
|
|
118
|
+
|
|
119
|
+
You may choose either license.
|
|
120
|
+
|
|
121
|
+
You are free to use, modify, and distribute this software, including for commercial use, provided the original license and copyright notice are included.
|
|
122
|
+
|
|
123
|
+
See [`LICENSE-MIT`](https://github.com/ankit-chaubey/ferogram-py/blob/main/LICENSE-MIT) and [`LICENSE-APACHE`](https://github.com/ankit-chaubey/ferogram-py/blob/main/LICENSE-APACHE) for full details.
|
|
124
|
+
|
|
125
|
+
---
|
|
126
|
+
|
|
127
|
+
## Developer
|
|
128
|
+
|
|
129
|
+
Developed by [Ankit Chaubey](https://github.com/ankit-chaubey)
|
|
130
|
+
|
|
131
|
+
Don't forget to explore the Rust engine powering ferogram-py: [`ferogram`](https://github.com/ankit-chaubey/ferogram). Thanks for being part of the journey.
|
|
132
|
+
|
|
133
|
+
Join the ferogram community! Questions, discussions, bugs report and feedback are always welcome. As the project grows, we'll eventually split Python and Rust discussions into dedicated spaces.
|
|
134
|
+
|
|
135
|
+
- Channel (releases & announcements): [@Ferogram](https://t.me/Ferogram)
|
|
136
|
+
|
|
137
|
+
- (questions & discussion): [@FerogramChat](https://t.me/FerogramChat)
|