ferogram 0.5.2b1__tar.gz → 0.5.2b2__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.2b1 → ferogram-0.5.2b2}/.github/workflows/publish.yml +26 -6
- ferogram-0.5.2b2/CHANGELOG.md +201 -0
- {ferogram-0.5.2b1 → ferogram-0.5.2b2}/Cargo.lock +16 -16
- {ferogram-0.5.2b1 → ferogram-0.5.2b2}/Cargo.toml +5 -5
- {ferogram-0.5.2b1 → ferogram-0.5.2b2}/PKG-INFO +1 -1
- {ferogram-0.5.2b1 → ferogram-0.5.2b2}/ferogram/client.py +183 -49
- {ferogram-0.5.2b1 → ferogram-0.5.2b2}/ferogram/raw/codegen.py +105 -48
- {ferogram-0.5.2b1 → ferogram-0.5.2b2}/ferogram/raw/generated/types/_base.py +13 -9
- {ferogram-0.5.2b1 → ferogram-0.5.2b2}/ferogram/raw/generated/types/stories.py +4 -0
- {ferogram-0.5.2b1 → ferogram-0.5.2b2}/ferogram/raw/proxy.py +79 -10
- {ferogram-0.5.2b1 → ferogram-0.5.2b2}/ferogram/raw/tl.py +68 -8
- {ferogram-0.5.2b1 → ferogram-0.5.2b2}/ferogram/types.py +18 -1
- {ferogram-0.5.2b1 → ferogram-0.5.2b2}/pyproject.toml +1 -1
- {ferogram-0.5.2b1 → ferogram-0.5.2b2}/src/connection.rs +6 -6
- {ferogram-0.5.2b1 → ferogram-0.5.2b2}/src/pipelined.rs +4 -1
- ferogram-0.5.2b1/CHANGELOG.md +0 -235
- {ferogram-0.5.2b1 → ferogram-0.5.2b2}/.github/workflows/compile-check.yml +0 -0
- {ferogram-0.5.2b1 → ferogram-0.5.2b2}/.gitignore +0 -0
- {ferogram-0.5.2b1 → ferogram-0.5.2b2}/.readthedocs.yaml +0 -0
- {ferogram-0.5.2b1 → ferogram-0.5.2b2}/FEATURES.md +0 -0
- {ferogram-0.5.2b1 → ferogram-0.5.2b2}/LICENSE-APACHE +0 -0
- {ferogram-0.5.2b1 → ferogram-0.5.2b2}/LICENSE-MIT +0 -0
- {ferogram-0.5.2b1 → ferogram-0.5.2b2}/Makefile +0 -0
- {ferogram-0.5.2b1 → ferogram-0.5.2b2}/README.md +0 -0
- {ferogram-0.5.2b1 → ferogram-0.5.2b2}/assets/architecture.svg +0 -0
- {ferogram-0.5.2b1 → ferogram-0.5.2b2}/build.rs +0 -0
- {ferogram-0.5.2b1 → ferogram-0.5.2b2}/examples/admin_tools.py +0 -0
- {ferogram-0.5.2b1 → ferogram-0.5.2b2}/examples/command_bot.py +0 -0
- {ferogram-0.5.2b1 → ferogram-0.5.2b2}/examples/echo_bot.py +0 -0
- {ferogram-0.5.2b1 → ferogram-0.5.2b2}/examples/group_management.py +0 -0
- {ferogram-0.5.2b1 → ferogram-0.5.2b2}/examples/media_bot.py +0 -0
- {ferogram-0.5.2b1 → ferogram-0.5.2b2}/examples/raw_invoke.py +0 -0
- {ferogram-0.5.2b1 → ferogram-0.5.2b2}/examples/rich_message.py +0 -0
- {ferogram-0.5.2b1 → ferogram-0.5.2b2}/examples/search_bot.py +0 -0
- {ferogram-0.5.2b1 → ferogram-0.5.2b2}/examples/send_hi.py +0 -0
- {ferogram-0.5.2b1 → ferogram-0.5.2b2}/examples/send_media.py +0 -0
- {ferogram-0.5.2b1 → ferogram-0.5.2b2}/examples/send_message.py +0 -0
- {ferogram-0.5.2b1 → ferogram-0.5.2b2}/examples/update_handlers.py +0 -0
- {ferogram-0.5.2b1 → ferogram-0.5.2b2}/examples/user_management.py +0 -0
- {ferogram-0.5.2b1 → ferogram-0.5.2b2}/examples/userbot.py +0 -0
- {ferogram-0.5.2b1 → ferogram-0.5.2b2}/ferogram/__init__.py +0 -0
- {ferogram-0.5.2b1 → ferogram-0.5.2b2}/ferogram/api.tl +0 -0
- {ferogram-0.5.2b1 → ferogram-0.5.2b2}/ferogram/filters.py +0 -0
- {ferogram-0.5.2b1 → ferogram-0.5.2b2}/ferogram/keyboards.py +0 -0
- {ferogram-0.5.2b1 → ferogram-0.5.2b2}/ferogram/logging.py +0 -0
- {ferogram-0.5.2b1 → ferogram-0.5.2b2}/ferogram/py.typed +0 -0
- {ferogram-0.5.2b1 → ferogram-0.5.2b2}/ferogram/raw/__init__.py +0 -0
- {ferogram-0.5.2b1 → ferogram-0.5.2b2}/ferogram/raw/api/__init__.py +0 -0
- {ferogram-0.5.2b1 → ferogram-0.5.2b2}/ferogram/raw/api/functions.py +0 -0
- {ferogram-0.5.2b1 → ferogram-0.5.2b2}/ferogram/raw/api/types.py +0 -0
- {ferogram-0.5.2b1 → ferogram-0.5.2b2}/ferogram/raw/generated/__init__.py +0 -0
- {ferogram-0.5.2b1 → ferogram-0.5.2b2}/ferogram/raw/generated/_tl_schema.py +0 -0
- {ferogram-0.5.2b1 → ferogram-0.5.2b2}/ferogram/raw/generated/functions/__init__.py +0 -0
- {ferogram-0.5.2b1 → ferogram-0.5.2b2}/ferogram/raw/generated/functions/account.py +0 -0
- {ferogram-0.5.2b1 → ferogram-0.5.2b2}/ferogram/raw/generated/functions/aicompose.py +0 -0
- {ferogram-0.5.2b1 → ferogram-0.5.2b2}/ferogram/raw/generated/functions/auth.py +0 -0
- {ferogram-0.5.2b1 → ferogram-0.5.2b2}/ferogram/raw/generated/functions/bots.py +0 -0
- {ferogram-0.5.2b1 → ferogram-0.5.2b2}/ferogram/raw/generated/functions/channels.py +0 -0
- {ferogram-0.5.2b1 → ferogram-0.5.2b2}/ferogram/raw/generated/functions/chatlists.py +0 -0
- {ferogram-0.5.2b1 → ferogram-0.5.2b2}/ferogram/raw/generated/functions/communities.py +0 -0
- {ferogram-0.5.2b1 → ferogram-0.5.2b2}/ferogram/raw/generated/functions/contacts.py +0 -0
- {ferogram-0.5.2b1 → ferogram-0.5.2b2}/ferogram/raw/generated/functions/ephemeral.py +0 -0
- {ferogram-0.5.2b1 → ferogram-0.5.2b2}/ferogram/raw/generated/functions/folders.py +0 -0
- {ferogram-0.5.2b1 → ferogram-0.5.2b2}/ferogram/raw/generated/functions/fragment.py +0 -0
- {ferogram-0.5.2b1 → ferogram-0.5.2b2}/ferogram/raw/generated/functions/help.py +0 -0
- {ferogram-0.5.2b1 → ferogram-0.5.2b2}/ferogram/raw/generated/functions/langpack.py +0 -0
- {ferogram-0.5.2b1 → ferogram-0.5.2b2}/ferogram/raw/generated/functions/messages.py +0 -0
- {ferogram-0.5.2b1 → ferogram-0.5.2b2}/ferogram/raw/generated/functions/payments.py +0 -0
- {ferogram-0.5.2b1 → ferogram-0.5.2b2}/ferogram/raw/generated/functions/phone.py +0 -0
- {ferogram-0.5.2b1 → ferogram-0.5.2b2}/ferogram/raw/generated/functions/photos.py +0 -0
- {ferogram-0.5.2b1 → ferogram-0.5.2b2}/ferogram/raw/generated/functions/premium.py +0 -0
- {ferogram-0.5.2b1 → ferogram-0.5.2b2}/ferogram/raw/generated/functions/smsjobs.py +0 -0
- {ferogram-0.5.2b1 → ferogram-0.5.2b2}/ferogram/raw/generated/functions/stats.py +0 -0
- {ferogram-0.5.2b1 → ferogram-0.5.2b2}/ferogram/raw/generated/functions/stickers.py +0 -0
- {ferogram-0.5.2b1 → ferogram-0.5.2b2}/ferogram/raw/generated/functions/stories.py +0 -0
- {ferogram-0.5.2b1 → ferogram-0.5.2b2}/ferogram/raw/generated/functions/updates.py +0 -0
- {ferogram-0.5.2b1 → ferogram-0.5.2b2}/ferogram/raw/generated/functions/upload.py +0 -0
- {ferogram-0.5.2b1 → ferogram-0.5.2b2}/ferogram/raw/generated/functions/users.py +0 -0
- {ferogram-0.5.2b1 → ferogram-0.5.2b2}/ferogram/raw/generated/types/__init__.py +0 -0
- {ferogram-0.5.2b1 → ferogram-0.5.2b2}/ferogram/raw/generated/types/account.py +0 -0
- {ferogram-0.5.2b1 → ferogram-0.5.2b2}/ferogram/raw/generated/types/aicompose.py +0 -0
- {ferogram-0.5.2b1 → ferogram-0.5.2b2}/ferogram/raw/generated/types/auth.py +0 -0
- {ferogram-0.5.2b1 → ferogram-0.5.2b2}/ferogram/raw/generated/types/bots.py +0 -0
- {ferogram-0.5.2b1 → ferogram-0.5.2b2}/ferogram/raw/generated/types/channels.py +0 -0
- {ferogram-0.5.2b1 → ferogram-0.5.2b2}/ferogram/raw/generated/types/chatlists.py +0 -0
- {ferogram-0.5.2b1 → ferogram-0.5.2b2}/ferogram/raw/generated/types/communities.py +0 -0
- {ferogram-0.5.2b1 → ferogram-0.5.2b2}/ferogram/raw/generated/types/contacts.py +0 -0
- {ferogram-0.5.2b1 → ferogram-0.5.2b2}/ferogram/raw/generated/types/fragment.py +0 -0
- {ferogram-0.5.2b1 → ferogram-0.5.2b2}/ferogram/raw/generated/types/help.py +0 -0
- {ferogram-0.5.2b1 → ferogram-0.5.2b2}/ferogram/raw/generated/types/messages.py +0 -0
- {ferogram-0.5.2b1 → ferogram-0.5.2b2}/ferogram/raw/generated/types/payments.py +0 -0
- {ferogram-0.5.2b1 → ferogram-0.5.2b2}/ferogram/raw/generated/types/phone.py +0 -0
- {ferogram-0.5.2b1 → ferogram-0.5.2b2}/ferogram/raw/generated/types/photos.py +0 -0
- {ferogram-0.5.2b1 → ferogram-0.5.2b2}/ferogram/raw/generated/types/premium.py +0 -0
- {ferogram-0.5.2b1 → ferogram-0.5.2b2}/ferogram/raw/generated/types/smsjobs.py +0 -0
- {ferogram-0.5.2b1 → ferogram-0.5.2b2}/ferogram/raw/generated/types/stats.py +0 -0
- {ferogram-0.5.2b1 → ferogram-0.5.2b2}/ferogram/raw/generated/types/stickers.py +0 -0
- {ferogram-0.5.2b1 → ferogram-0.5.2b2}/ferogram/raw/generated/types/storage.py +0 -0
- {ferogram-0.5.2b1 → ferogram-0.5.2b2}/ferogram/raw/generated/types/updates.py +0 -0
- {ferogram-0.5.2b1 → ferogram-0.5.2b2}/ferogram/raw/generated/types/upload.py +0 -0
- {ferogram-0.5.2b1 → ferogram-0.5.2b2}/ferogram/raw/generated/types/users.py +0 -0
- {ferogram-0.5.2b1 → ferogram-0.5.2b2}/ferogram/rich.py +0 -0
- {ferogram-0.5.2b1 → ferogram-0.5.2b2}/ferogram/updates.py +0 -0
- {ferogram-0.5.2b1 → ferogram-0.5.2b2}/src/lib.rs +0 -0
- {ferogram-0.5.2b1 → ferogram-0.5.2b2}/src/raw.rs +0 -0
- {ferogram-0.5.2b1 → ferogram-0.5.2b2}/src/session.rs +0 -0
- {ferogram-0.5.2b1 → ferogram-0.5.2b2}/src/srp.rs +0 -0
- {ferogram-0.5.2b1 → ferogram-0.5.2b2}/tests/test_rich.py +0 -0
- {ferogram-0.5.2b1 → ferogram-0.5.2b2}/tests/test_tl_roundtrip.py +0 -0
|
@@ -218,12 +218,12 @@ jobs:
|
|
|
218
218
|
export CARGO_TARGET_${TARGET_UPPER}_LINKER=$NDK_BIN/${CLANG_PREFIX}-clang
|
|
219
219
|
|
|
220
220
|
# Link against Termux's real libpython<version>.so (not an empty
|
|
221
|
-
# stub). This embeds
|
|
222
|
-
#
|
|
223
|
-
#
|
|
224
|
-
#
|
|
225
|
-
#
|
|
226
|
-
#
|
|
221
|
+
# stub) so the build succeeds. This still embeds a version-pinned
|
|
222
|
+
# DT_NEEDED at this point - the next step rewrites it to be
|
|
223
|
+
# version-agnostic, since bionic requires DT_NEEDED to resolve by
|
|
224
|
+
# exact filename at dlopen time and won't fall back to whatever
|
|
225
|
+
# Python happens to already be resident in the process, unlike
|
|
226
|
+
# glibc.
|
|
227
227
|
export RUSTFLAGS="-L native=$TERMUX_LIBDIR"
|
|
228
228
|
|
|
229
229
|
maturin build \
|
|
@@ -232,6 +232,26 @@ jobs:
|
|
|
232
232
|
--compatibility off \
|
|
233
233
|
--out dist
|
|
234
234
|
|
|
235
|
+
- name: Rewrite libpython dependency to be version-agnostic
|
|
236
|
+
run: |
|
|
237
|
+
which patchelf >/dev/null 2>&1 || (sudo apt-get update && sudo apt-get install -y patchelf)
|
|
238
|
+
for whl in dist/*.whl; do
|
|
239
|
+
whl_abs=$(readlink -f "$whl")
|
|
240
|
+
workdir=$(mktemp -d)
|
|
241
|
+
unzip -q "$whl_abs" -d "$workdir"
|
|
242
|
+
so_file=$(find "$workdir" -name "_ferogram*.so" | head -1)
|
|
243
|
+
if [ -z "$so_file" ]; then
|
|
244
|
+
echo "::error::No _ferogram*.so found inside $whl"
|
|
245
|
+
exit 1
|
|
246
|
+
fi
|
|
247
|
+
patchelf --replace-needed "libpython${TERMUX_PYVER}.so" "libpython3.so" "$so_file"
|
|
248
|
+
echo "Patched $so_file: DT_NEEDED libpython${TERMUX_PYVER}.so -> libpython3.so"
|
|
249
|
+
|
|
250
|
+
rm -f "$whl_abs"
|
|
251
|
+
(cd "$workdir" && zip -qr "$whl_abs" .)
|
|
252
|
+
rm -rf "$workdir"
|
|
253
|
+
done
|
|
254
|
+
|
|
235
255
|
- uses: actions/upload-artifact@v4
|
|
236
256
|
with:
|
|
237
257
|
name: wheels-android-${{ matrix.target }}
|
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to this project are documented in this file.
|
|
4
|
+
|
|
5
|
+
## [Unreleased]
|
|
6
|
+
|
|
7
|
+
### Added
|
|
8
|
+
|
|
9
|
+
- `Chat.is_community` and `Dialog.community_id` / `Dialog.is_community` properties for community support.
|
|
10
|
+
- `get_dialogs()` and `get_pinned_dialogs()` now handle `dialogCommunity` via `community_id` instead of assuming a `peer` field is present.
|
|
11
|
+
|
|
12
|
+
### Changed
|
|
13
|
+
|
|
14
|
+
- The peer cache now tracks communities separately from channels instead of collapsing them together. `chatEmpty` is no longer cached as a basic chat, and a stored non-zero access hash can no longer be overwritten by a zero one.
|
|
15
|
+
- `serialize_object` now dispatches to the generated `to_bytes()` implementation before falling back to generic field serialization, a roughly 1.7x improvement in serialization throughput. Output was verified byte-identical across all 2,437 constructors in the schema.
|
|
16
|
+
|
|
17
|
+
### Fixed
|
|
18
|
+
|
|
19
|
+
- TL codegen assumed a constructor's `flags:#` word is always the first field on the wire and hoisted it to the front of `from_bytes()` / `to_bytes()` unconditionally. `poll#966e2dbf`, `wallPaper#a437c3ed`, and `wallPaperNoFile#e0804116` all declare `id:long` before `flags:#`, so those two fields were read and written swapped, producing a garbage flags word that could trigger optional fields that weren't actually present and eventually overrun the buffer. This was the root cause of the corruption seen in `updates.getDifference`. Codegen now tracks each flag marker's real position in the schema and emits it there instead of assuming it comes first.
|
|
20
|
+
- Related codegen bug: `exportedChatlistInvite` and `stories.allStoriesNotModified` declare `flags:#` with no field gated on it. Codegen treated "no field uses this flag group" as "no flags word on the wire" and silently dropped 4 bytes, misaligning every field after it. Flag group presence is now determined from declared markers, not from field usage.
|
|
21
|
+
- `ferogram/raw/tl.py`'s runtime fallback interpreter (`_read_value` / `serialize_object`) had the same "flags always first" assumption baked in. Fixed to read and write each flag group at its correct wire position.
|
|
22
|
+
- Regenerated all 1,642 generated types and 795 functions from `api.tl`. `tests/test_tl_roundtrip.py` (4,874 constructor x optional-field combinations) now passes.
|
|
23
|
+
- `join_chat()` and `join_invite_link()` assumed a bare `Updates` response and broke on `messages.ChatInviteJoinResult`. The `Ok` variant now resolves and caches the joined peer; the `WebView` variant returns `None`, since it requires an interactive bot flow that isn't supported yet.
|
|
24
|
+
- `promote_participant(rights=...)` merged the requested rights into a fixed base set instead of replacing it, so limited admin permissions could never actually be granted. It now replaces the requested rights as intended.
|
|
25
|
+
- `send_message()`, `edit_message()`, and `forward_messages()` ignored caller-supplied values for `no_webpage`, `silent`, `schedule_date`, and `send_as` in favor of hardcoded defaults. These parameters are now respected.
|
|
26
|
+
- `send_invoice(test=...)`, `add_contact(add_phone_privacy_exception=...)`, and `get_blocked_users(my_stories_from=...)` ignored the supplied value and always sent a hardcoded default. Fixed.
|
|
27
|
+
|
|
28
|
+
## [0.5.2] - 2026-07-17
|
|
29
|
+
|
|
30
|
+
### Added
|
|
31
|
+
|
|
32
|
+
- `Client.get_chat_photos(peer, limit)`: photo and avatar history for groups and channels. `get_profile_photos` only ever worked for users. The current photo comes from the chat's full info, so it survives message deletion; older photos come from `messageActionChatEditPhoto` search history.
|
|
33
|
+
- Fast re-auth support: `sign_out()` captures a `future_auth_token` when Telegram returns one and persists it through a new `DcConnection.get_future_auth_token` / `set_future_auth_token` pair, riding along in the existing session blob with no new session format required. `request_login_code()` replays it automatically, so a returning session can skip code entry entirely (`auth.sentCodeSuccess`).
|
|
34
|
+
|
|
35
|
+
### Fixed
|
|
36
|
+
|
|
37
|
+
- MTProto handshake fix pulled in transitively via `ferogram-mtsender`: a DC-tagged `p_q_inner_data` was being rejected by Telegram with RPC error 444 outside DC2.
|
|
38
|
+
|
|
39
|
+
### Changed
|
|
40
|
+
|
|
41
|
+
- Layer upgraded to 228.
|
|
42
|
+
|
|
43
|
+
## [0.5.1] - 2026-06-29
|
|
44
|
+
|
|
45
|
+
### Added
|
|
46
|
+
|
|
47
|
+
- `Message.respond()` for sending a message to the same chat without replying.
|
|
48
|
+
- `Message.pin()`, `forward_to()`, `get_sender()`, `get_chat()`, and `get_reply_message()` helpers.
|
|
49
|
+
- `Message.reply_photo()` and `reply_document()` convenience methods.
|
|
50
|
+
- `reply_to` support in `send_message()`, `send_photo()`, and `send_document()`.
|
|
51
|
+
- `Client.get_user()` and `Client.get_chat()` helpers.
|
|
52
|
+
- `reply_markup` parameter on `edit_message()`.
|
|
53
|
+
- `notify` parameter on `pin_message()`.
|
|
54
|
+
- Convenience methods on `CallbackQuery`: `respond()`, `reply()`, `edit_message_text()`, `get_sender()`.
|
|
55
|
+
- Convenience methods on `InlineQuery`: `answer()`, `get_sender()`.
|
|
56
|
+
- Sender and entity helpers on additional update types: `InlineSend`, `UserStatus`, `ChatAction`, `JoinRequest`, `ParticipantUpdate`, `MessageReaction`, `ChatBoost`, `ShippingQuery`, `PreCheckoutQuery`.
|
|
57
|
+
- `_client` binding added to the remaining update wrappers, including `RawUpdate`.
|
|
58
|
+
|
|
59
|
+
### Changed
|
|
60
|
+
|
|
61
|
+
- Sent message extraction fallback now logs a warning and preserves context instead of failing silently.
|
|
62
|
+
|
|
63
|
+
### Fixed
|
|
64
|
+
|
|
65
|
+
- `Message.reply()` now creates a proper quoted reply using `reply_to=self.id`.
|
|
66
|
+
- `Message.delete()` now correctly handles channels and supergroups.
|
|
67
|
+
- `delete_messages_in()` is now channel-aware.
|
|
68
|
+
- `_dispatch()` now binds `_client` for all update types.
|
|
69
|
+
|
|
70
|
+
## [0.5.0] - 2026-06-28
|
|
71
|
+
|
|
72
|
+
The Rust dependency changed from the monolithic `ferogram` crate to five focused crates from the ferogram core:
|
|
73
|
+
|
|
74
|
+
- `ferogram-mtsender`: MTProto sender, message framing, and acknowledgement.
|
|
75
|
+
- `ferogram-session`: session storage (file, SQLite, libSQL, memory, string).
|
|
76
|
+
- `ferogram-connect`: TCP/TLS transport and DC routing.
|
|
77
|
+
- `ferogram-tl-types`: generated TL type definitions.
|
|
78
|
+
- `ferogram-crypto`: AES-IGE, Diffie-Hellman, and SHA helpers.
|
|
79
|
+
|
|
80
|
+
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 keeps the compiled extension smaller and faster to build, and lets Python-side behavior be updated without recompiling the Rust extension.
|
|
81
|
+
|
|
82
|
+
The compiled extension now uses `abi3-py39` (was `abi3-py313`), so a single wheel runs on Python 3.9 and later.
|
|
83
|
+
|
|
84
|
+
### Added
|
|
85
|
+
|
|
86
|
+
- `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`.
|
|
87
|
+
- `TransferCancelled` exception, raised when a `TransferHandle` is cancelled mid-transfer.
|
|
88
|
+
- `keyboards` module: `InlineKeyboard`, `InlineButton`, `ReplyKeyboard`, `ReplyButton`, `RemoveKeyboard`, and `ForceReply` are now pure Python and importable from `ferogram` directly.
|
|
89
|
+
- `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 unchanged.
|
|
90
|
+
- `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.
|
|
91
|
+
- `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, timestamps, and custom emoji via Markdown or HTML input.
|
|
92
|
+
- 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 it if you only changed Rust. Codegen uses the same Python interpreter maturin selected.
|
|
93
|
+
- `DcConnection` and `srp_calculate` exposed from the Rust extension for use by the pure-Python `Client` class.
|
|
94
|
+
- `LAYER` constant exported from `ferogram.raw.generated._tl_schema` and used automatically in `invokeWithLayer` wrappers.
|
|
95
|
+
- `all_updates` filter, replacing the old `all` filter, which shadowed the Python built-in.
|
|
96
|
+
|
|
97
|
+
### Changed
|
|
98
|
+
|
|
99
|
+
- `Message`, `User`, `Chat`, and all entity types are now Python dataclasses instead of PyO3 structs. They serialize to and from the TL dict representation in Python, with no change to the public API.
|
|
100
|
+
- `CallbackQuery`, `InlineQuery`, and all update types are now Python dataclasses.
|
|
101
|
+
- `InlineKeyboard`, `ReplyKeyboard`, and related keyboard builders are now pure Python (`ferogram/keyboards.py`); previously they were Rust structs.
|
|
102
|
+
- Filters rewritten to correctly unwrap update wrapper objects before inspecting the inner `Message`. Previously filters broke when the dispatcher passed wrapper objects instead of bare messages. `reply` now checks `reply_to_msg_id`; `forwarded` checks `forward_from_id`; `media` checks the `media` field directly.
|
|
103
|
+
- `codegen.py` doubled in size, from 321 to 691 lines. It now generates specialized `to_bytes()` methods using inline `struct.pack` calls and a CID-dispatch `from_bytes()` router, producing faster serialization and deserialization than the previous schema-dict approach.
|
|
104
|
+
- `ferogram-py` version bumped to 0.5.0. Core crates pinned to `ferogram-*` 0.6.3.
|
|
105
|
+
|
|
106
|
+
### Removed
|
|
107
|
+
|
|
108
|
+
- Direct dependency on the monolithic `ferogram` crate, replaced by the five focused crates described above.
|
|
109
|
+
- Unused `hex` crate dependency (was `0.4`).
|
|
110
|
+
- `all` filter, replaced with `all_updates` to avoid shadowing Python's built-in `all`.
|
|
111
|
+
|
|
112
|
+
## [0.4.1] - 2026-06-03
|
|
113
|
+
|
|
114
|
+
Patch release. No API changes. Identical to 0.4.0 except for dependency pins and minor internal fixes.
|
|
115
|
+
|
|
116
|
+
## [0.4.0] - 2026-06-01
|
|
117
|
+
|
|
118
|
+
### Added
|
|
119
|
+
|
|
120
|
+
- Session backends: `FileSession`, `MemorySession`, `StringSession`, `SqliteSession`, `LibSqlSession`, and `CustomSession` are now first-class types importable from `ferogram`. Pass any of them as the `session` argument to `Client`; plain string names still work as before.
|
|
121
|
+
- `SqliteSession("name")` stores the session in a SQLite database.
|
|
122
|
+
- `MemorySession()` keeps the session in memory only; nothing is written to disk.
|
|
123
|
+
- `StringSession("AQA...")` resumes from a base64 string, useful for serverless or env-var based deployments.
|
|
124
|
+
- `LibSqlSession.local/remote/replica/memory(...)` targets a local file, remote Turso database, embedded replica, or in-memory libSQL database.
|
|
125
|
+
- `CustomSession(obj)` wraps any Python object implementing `save(bytes)`, `load() -> bytes | None`, and `delete()`.
|
|
126
|
+
- `channel_kind()` on `Message`: `await msg.channel_kind()` returns `"megagroup"`, `"broadcast"`, `"gigagroup"`, or `None`. Uses the peer cache; no RPC call.
|
|
127
|
+
- `is_megagroup()` on `Message`: `await msg.is_megagroup()` returns `True` for supergroups.
|
|
128
|
+
- `is_broadcast()` on `Message`: `await msg.is_broadcast()` returns `True` for broadcast channels.
|
|
129
|
+
- `StopPropagation` and `ContinuePropagation` exceptions exported from `ferogram` to control handler dispatch. `StopPropagation` stops all further group processing; `ContinuePropagation` skips the current handler and continues to the next match in the same group.
|
|
130
|
+
- Handler groups: all `on_*` decorators now accept `group: int = 0`. Handlers run in ascending group order, with lower group numbers running first.
|
|
131
|
+
- `add_handler()` / `remove_handler()` to register and deregister handlers at runtime without decorators.
|
|
132
|
+
- Worker pool: a fixed pool of `workers` coroutines (default 4) now dispatches updates from a bounded `asyncio.Queue`, replacing the old unbounded `asyncio.create_task` approach and providing natural backpressure under load.
|
|
133
|
+
- `workers` kwarg on `Client` to control pool size.
|
|
134
|
+
- `parse_mode` kwarg on `Client`, setting a global default parse mode applied to every `send_message` call that doesn't pass its own `parse_mode`.
|
|
135
|
+
- `flood_sleep_threshold` kwarg on `Client`, mapping 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.
|
|
136
|
+
- `download_with_progress(peer, msg_id, path, on_progress)`: download media with a progress callback `on_progress(done, total)`.
|
|
137
|
+
- `upload_with_progress(path, on_progress)`: upload a file with a progress callback, returning a handle string accepted by `send_file`.
|
|
138
|
+
- ferogram 0.6.0 as the core dependency, including `Client.channel_kind_of(channel_id)`, which backs the new `Message` methods above.
|
|
139
|
+
|
|
140
|
+
### Changed
|
|
141
|
+
|
|
142
|
+
- `no_webpage` now defaults to `True` in `send_message` and `edit_message`.
|
|
143
|
+
- `upload_file(data, name, mime)` replaced by `upload(Cursor(data), name)` internally, with no change to the Python API.
|
|
144
|
+
- Session resolution order is now `session_string > session object`. `in_memory=True` is deprecated in favor of `MemorySession()`.
|
|
145
|
+
- Handler storage changed from `list` to `dict[group, list]`; dispatch now iterates groups in sorted order.
|
|
146
|
+
- `_resolve_pm` is now used internally to merge per-call and global `parse_mode`.
|
|
147
|
+
|
|
148
|
+
### Fixed
|
|
149
|
+
|
|
150
|
+
- `channel_kind`, `is_megagroup`, and `is_broadcast` on `Message` no longer call `get_chat_full` (an RPC) on every invocation; they read from the peer cache via `Client.channel_kind_of`.
|
|
151
|
+
- Unnecessary `as i64` casts removed from `message.rs`.
|
|
152
|
+
- Nested `if let` blocks collapsed to `if let ... && ...`.
|
|
153
|
+
- `match ... { Some(m) => m, None => return None }` replaced with `as_ref()?`.
|
|
154
|
+
|
|
155
|
+
## [0.3.0] - 2026-05-16
|
|
156
|
+
|
|
157
|
+
The Rust dependency is now ferogram 0.5.0.
|
|
158
|
+
|
|
159
|
+
### Added
|
|
160
|
+
|
|
161
|
+
- `send_poll` now accepts all options the Rust `PollBuilder` supports: `public_voters`, `shuffle_answers`, `hide_results_until_close`, `close_period`, `close_date`, and `solution`. Previously only `quiz`, `correct_index`, and `multiple_choice` were wired through.
|
|
162
|
+
- The `restrictions` dict passed to `edit_chat_default_banned_rights` now accepts `"send_reactions"` as a key, mirroring the new `send_reactions` field on `BannedRightsBuilder` added in ferogram 0.5.0.
|
|
163
|
+
- `poll_results(peer, msg_id)` is now the canonical way to fetch poll stats, returning the votes graph as a JSON string.
|
|
164
|
+
|
|
165
|
+
### Deprecated
|
|
166
|
+
|
|
167
|
+
- `get_poll_results(peer, msg_id, poll_hash)` is kept for backward compatibility but is deprecated in favor of `poll_results`. Its `poll_hash` parameter is now ignored, because ferogram 0.5.0 dropped the underlying API call it relied on.
|
|
168
|
+
|
|
169
|
+
## [0.2.3] - 2026-05-14
|
|
170
|
+
|
|
171
|
+
### Added
|
|
172
|
+
|
|
173
|
+
- **Client builder**: 20 new kwargs to `Client(...)` so everything can be configured at construction time instead of by touching internals.
|
|
174
|
+
- Network: `proxy` (SOCKS5 or MTProxy t.me link), `allow_ipv6`, `dc_addr`, `probe_transport`, `resilient_connect`.
|
|
175
|
+
- Session backend: `session_string` and `in_memory` as alternatives to the default session file, with priority `in_memory > session_string > file`.
|
|
176
|
+
- Update handling: `catch_up`, `pfs`, `update_queue_capacity`, `update_overflow` (`"drop_oldest"` or `"drop_newest"`), `low_memory_mode`.
|
|
177
|
+
- InitConnection identity: `device`, `system_version`, `app_version`, `lang_code`, `system_lang_code`, `lang_pack`.
|
|
178
|
+
- Experimental: `allow_missing_channel_hash`, `auto_resolve_peers`.
|
|
179
|
+
- **Inline bots**: `InlineArticle`, `InlinePhoto`, and `InlineDocument` now expose all their fields; previously only the three required fields worked. New fields: `description`, `url`, `thumb_url`, `reply_markup` on articles; `photo_url`, `photo_width`, `photo_height`, `thumb_url`, `mime_type`, `reply_markup` on photos; `document_url`, `mime_type`, `description`, `thumb_url`, `reply_markup` on documents.
|
|
180
|
+
- `answer_inline_query` now accepts `next_offset` for pagination and `switch_pm` to show a "go to PM" button in the results list.
|
|
181
|
+
- `answer_inline_query_articles` is now accessible from Python, taking a plain list of `(id, title, text)` tuples and supporting `next_offset`.
|
|
182
|
+
- `edit_inline_message` now accepts `reply_markup`, so a keyboard can be attached or updated when editing.
|
|
183
|
+
- `InlineSend` now exposes `msg_id_bytes` and `msg_id_dc`, so an `InlineMessageId` can be built from the send event and used to edit the message later.
|
|
184
|
+
- **Participants**: ten new methods for managing group and channel members.
|
|
185
|
+
- `get_participants(peer, limit=200)` fetches all members as a list of `ChatMember`.
|
|
186
|
+
- `get_participants_filtered(peer, filter, limit)` fetches a filtered subset. Filter values: `"recent"`, `"admins"`, `"kicked"`, `"banned"`, `"bots"`.
|
|
187
|
+
- `kick_participant(peer, user)` removes a user from the chat; they can rejoin if the chat is public or they have an invite link.
|
|
188
|
+
- `ban_participant(peer, user)` permanently bans a user until an admin manually lifts it.
|
|
189
|
+
- `ban_participant_until(peer, user, until_date)` bans until a Unix timestamp, after which the ban lifts automatically.
|
|
190
|
+
- `promote_participant(peer, user, rights)` promotes to admin with specific rights; pass `rights=None` to grant all. Valid right strings: `"change_info"`, `"post_messages"`, `"edit_messages"`, `"delete_messages"`, `"ban_users"`, `"invite_users"`, `"pin_messages"`, `"add_admins"`, `"manage_call"`.
|
|
191
|
+
- `demote_participant(peer, user)` strips all admin rights, leaving the user as a regular member.
|
|
192
|
+
- `get_profile_photos(peer, limit=100)` returns a list of `(file_id, access_hash, dc_id)` tuples.
|
|
193
|
+
- `search_peer(query)` searches the local peer cache by name or username and returns a list of peer identifier strings.
|
|
194
|
+
- `signal_network_restored()` (sync, not async) tells the client the network is back so it attempts reconnection immediately instead of waiting for the retry timer.
|
|
195
|
+
- **Reactions and polls**:
|
|
196
|
+
- `delete_reaction(peer, msg_id, participant)` existed in Rust but had no Python wrapper; now exposed. Removes a specific user's reaction from a message, admin only.
|
|
197
|
+
- `get_poll_results(peer, msg_id, poll_hash)` existed in Rust but had no Python wrapper; now exposed. Fetches and caches the latest poll results from Telegram.
|
|
198
|
+
|
|
199
|
+
## [0.2.2]
|
|
200
|
+
|
|
201
|
+
Releases prior to 0.2.2 were not documented in this changelog.
|
|
@@ -392,8 +392,8 @@ checksum = "7360491ce676a36bf9bb3c56c1aa791658183a54d2744120f27285738d90465a"
|
|
|
392
392
|
|
|
393
393
|
[[package]]
|
|
394
394
|
name = "ferogram-connect"
|
|
395
|
-
version = "0.6.
|
|
396
|
-
source = "git+https://github.com/ankit-chaubey/ferogram?rev=
|
|
395
|
+
version = "0.6.4"
|
|
396
|
+
source = "git+https://github.com/ankit-chaubey/ferogram?rev=f747bf418da2f8d9f6288cc5aa56875034c112f9#f747bf418da2f8d9f6288cc5aa56875034c112f9"
|
|
397
397
|
dependencies = [
|
|
398
398
|
"ferogram-crypto",
|
|
399
399
|
"ferogram-mtproto",
|
|
@@ -408,8 +408,8 @@ dependencies = [
|
|
|
408
408
|
|
|
409
409
|
[[package]]
|
|
410
410
|
name = "ferogram-crypto"
|
|
411
|
-
version = "0.6.
|
|
412
|
-
source = "git+https://github.com/ankit-chaubey/ferogram?rev=
|
|
411
|
+
version = "0.6.4"
|
|
412
|
+
source = "git+https://github.com/ankit-chaubey/ferogram?rev=f747bf418da2f8d9f6288cc5aa56875034c112f9#f747bf418da2f8d9f6288cc5aa56875034c112f9"
|
|
413
413
|
dependencies = [
|
|
414
414
|
"aes",
|
|
415
415
|
"ctr",
|
|
@@ -425,8 +425,8 @@ dependencies = [
|
|
|
425
425
|
|
|
426
426
|
[[package]]
|
|
427
427
|
name = "ferogram-mtproto"
|
|
428
|
-
version = "0.6.
|
|
429
|
-
source = "git+https://github.com/ankit-chaubey/ferogram?rev=
|
|
428
|
+
version = "0.6.4"
|
|
429
|
+
source = "git+https://github.com/ankit-chaubey/ferogram?rev=f747bf418da2f8d9f6288cc5aa56875034c112f9#f747bf418da2f8d9f6288cc5aa56875034c112f9"
|
|
430
430
|
dependencies = [
|
|
431
431
|
"ferogram-crypto",
|
|
432
432
|
"ferogram-tl-types",
|
|
@@ -438,8 +438,8 @@ dependencies = [
|
|
|
438
438
|
|
|
439
439
|
[[package]]
|
|
440
440
|
name = "ferogram-mtsender"
|
|
441
|
-
version = "0.6.
|
|
442
|
-
source = "git+https://github.com/ankit-chaubey/ferogram?rev=
|
|
441
|
+
version = "0.6.4"
|
|
442
|
+
source = "git+https://github.com/ankit-chaubey/ferogram?rev=f747bf418da2f8d9f6288cc5aa56875034c112f9#f747bf418da2f8d9f6288cc5aa56875034c112f9"
|
|
443
443
|
dependencies = [
|
|
444
444
|
"ferogram-connect",
|
|
445
445
|
"ferogram-crypto",
|
|
@@ -470,8 +470,8 @@ dependencies = [
|
|
|
470
470
|
|
|
471
471
|
[[package]]
|
|
472
472
|
name = "ferogram-session"
|
|
473
|
-
version = "0.6.
|
|
474
|
-
source = "git+https://github.com/ankit-chaubey/ferogram?rev=
|
|
473
|
+
version = "0.6.4"
|
|
474
|
+
source = "git+https://github.com/ankit-chaubey/ferogram?rev=f747bf418da2f8d9f6288cc5aa56875034c112f9#f747bf418da2f8d9f6288cc5aa56875034c112f9"
|
|
475
475
|
dependencies = [
|
|
476
476
|
"base64 0.22.1",
|
|
477
477
|
"libsql",
|
|
@@ -483,21 +483,21 @@ dependencies = [
|
|
|
483
483
|
|
|
484
484
|
[[package]]
|
|
485
485
|
name = "ferogram-tl-gen"
|
|
486
|
-
version = "0.6.
|
|
487
|
-
source = "git+https://github.com/ankit-chaubey/ferogram?rev=
|
|
486
|
+
version = "0.6.4"
|
|
487
|
+
source = "git+https://github.com/ankit-chaubey/ferogram?rev=f747bf418da2f8d9f6288cc5aa56875034c112f9#f747bf418da2f8d9f6288cc5aa56875034c112f9"
|
|
488
488
|
dependencies = [
|
|
489
489
|
"ferogram-tl-parser",
|
|
490
490
|
]
|
|
491
491
|
|
|
492
492
|
[[package]]
|
|
493
493
|
name = "ferogram-tl-parser"
|
|
494
|
-
version = "0.6.
|
|
495
|
-
source = "git+https://github.com/ankit-chaubey/ferogram?rev=
|
|
494
|
+
version = "0.6.4"
|
|
495
|
+
source = "git+https://github.com/ankit-chaubey/ferogram?rev=f747bf418da2f8d9f6288cc5aa56875034c112f9#f747bf418da2f8d9f6288cc5aa56875034c112f9"
|
|
496
496
|
|
|
497
497
|
[[package]]
|
|
498
498
|
name = "ferogram-tl-types"
|
|
499
|
-
version = "0.6.
|
|
500
|
-
source = "git+https://github.com/ankit-chaubey/ferogram?rev=
|
|
499
|
+
version = "0.6.4"
|
|
500
|
+
source = "git+https://github.com/ankit-chaubey/ferogram?rev=f747bf418da2f8d9f6288cc5aa56875034c112f9#f747bf418da2f8d9f6288cc5aa56875034c112f9"
|
|
501
501
|
dependencies = [
|
|
502
502
|
"ferogram-tl-gen",
|
|
503
503
|
"ferogram-tl-parser",
|
|
@@ -12,11 +12,11 @@ name = "_ferogram"
|
|
|
12
12
|
crate-type = ["cdylib"]
|
|
13
13
|
|
|
14
14
|
[dependencies]
|
|
15
|
-
ferogram-mtsender = { git = "https://github.com/ankit-chaubey/ferogram", rev = "
|
|
16
|
-
ferogram-session = { git = "https://github.com/ankit-chaubey/ferogram", rev = "
|
|
17
|
-
ferogram-connect = { git = "https://github.com/ankit-chaubey/ferogram", rev = "
|
|
18
|
-
ferogram-tl-types = { git = "https://github.com/ankit-chaubey/ferogram", rev = "
|
|
19
|
-
ferogram-crypto = { git = "https://github.com/ankit-chaubey/ferogram", rev = "
|
|
15
|
+
ferogram-mtsender = { git = "https://github.com/ankit-chaubey/ferogram", rev = "f747bf418da2f8d9f6288cc5aa56875034c112f9" }
|
|
16
|
+
ferogram-session = { git = "https://github.com/ankit-chaubey/ferogram", rev = "f747bf418da2f8d9f6288cc5aa56875034c112f9", features = ["sqlite-session", "libsql-session"] }
|
|
17
|
+
ferogram-connect = { git = "https://github.com/ankit-chaubey/ferogram", rev = "f747bf418da2f8d9f6288cc5aa56875034c112f9" }
|
|
18
|
+
ferogram-tl-types = { git = "https://github.com/ankit-chaubey/ferogram", rev = "f747bf418da2f8d9f6288cc5aa56875034c112f9" }
|
|
19
|
+
ferogram-crypto = { git = "https://github.com/ankit-chaubey/ferogram", rev = "f747bf418da2f8d9f6288cc5aa56875034c112f9" }
|
|
20
20
|
getrandom = "0.2"
|
|
21
21
|
base64 = "0.22"
|
|
22
22
|
pyo3 = { version = "0.24", features = ["extension-module", "abi3-py39"] }
|