ferogram 0.2.3__tar.gz → 0.4.0__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.
Files changed (99) hide show
  1. ferogram-0.4.0/.github/workflows/compile-check.yml +146 -0
  2. ferogram-0.4.0/CHANGELOG.md +131 -0
  3. {ferogram-0.2.3 → ferogram-0.4.0}/Cargo.lock +1112 -129
  4. {ferogram-0.2.3 → ferogram-0.4.0}/Cargo.toml +2 -2
  5. {ferogram-0.2.3 → ferogram-0.4.0}/FEATURES.md +134 -26
  6. {ferogram-0.2.3 → ferogram-0.4.0}/PKG-INFO +1 -1
  7. {ferogram-0.2.3 → ferogram-0.4.0}/ferogram/__init__.py +3 -1
  8. {ferogram-0.2.3 → ferogram-0.4.0}/ferogram/client.py +251 -58
  9. {ferogram-0.2.3 → ferogram-0.4.0}/ferogram/raw/generated/_tl_schema.py +2 -0
  10. {ferogram-0.2.3 → ferogram-0.4.0}/ferogram/raw/proxy.py +8 -6
  11. {ferogram-0.2.3 → ferogram-0.4.0}/ferogram/raw/tl.py +75 -6
  12. {ferogram-0.2.3 → ferogram-0.4.0}/pyproject.toml +1 -1
  13. {ferogram-0.2.3 → ferogram-0.4.0}/src/auth.rs +16 -11
  14. {ferogram-0.2.3 → ferogram-0.4.0}/src/client.rs +467 -142
  15. {ferogram-0.2.3 → ferogram-0.4.0}/src/lib.rs +7 -0
  16. {ferogram-0.2.3 → ferogram-0.4.0}/src/message.rs +85 -21
  17. ferogram-0.4.0/src/session.rs +426 -0
  18. ferogram-0.2.3/CHANGELOG.md +0 -65
  19. {ferogram-0.2.3 → ferogram-0.4.0}/.github/workflows/publish.yml +0 -0
  20. {ferogram-0.2.3 → ferogram-0.4.0}/.gitignore +0 -0
  21. {ferogram-0.2.3 → ferogram-0.4.0}/LICENSE-APACHE +0 -0
  22. {ferogram-0.2.3 → ferogram-0.4.0}/LICENSE-MIT +0 -0
  23. {ferogram-0.2.3 → ferogram-0.4.0}/README.md +0 -0
  24. {ferogram-0.2.3 → ferogram-0.4.0}/examples/admin_tools.py +0 -0
  25. {ferogram-0.2.3 → ferogram-0.4.0}/examples/command_bot.py +0 -0
  26. {ferogram-0.2.3 → ferogram-0.4.0}/examples/echo_bot.py +0 -0
  27. {ferogram-0.2.3 → ferogram-0.4.0}/examples/group_management.py +0 -0
  28. {ferogram-0.2.3 → ferogram-0.4.0}/examples/media_bot.py +0 -0
  29. {ferogram-0.2.3 → ferogram-0.4.0}/examples/raw_invoke.py +0 -0
  30. {ferogram-0.2.3 → ferogram-0.4.0}/examples/search_bot.py +0 -0
  31. {ferogram-0.2.3 → ferogram-0.4.0}/examples/send_hi.py +0 -0
  32. {ferogram-0.2.3 → ferogram-0.4.0}/examples/send_media.py +0 -0
  33. {ferogram-0.2.3 → ferogram-0.4.0}/examples/send_message.py +0 -0
  34. {ferogram-0.2.3 → ferogram-0.4.0}/examples/update_handlers.py +0 -0
  35. {ferogram-0.2.3 → ferogram-0.4.0}/examples/user_management.py +0 -0
  36. {ferogram-0.2.3 → ferogram-0.4.0}/examples/userbot.py +0 -0
  37. {ferogram-0.2.3 → ferogram-0.4.0}/ferogram/filters.py +0 -0
  38. {ferogram-0.2.3 → ferogram-0.4.0}/ferogram/logging.py +0 -0
  39. {ferogram-0.2.3 → ferogram-0.4.0}/ferogram/py.typed +0 -0
  40. {ferogram-0.2.3 → ferogram-0.4.0}/ferogram/raw/__init__.py +0 -0
  41. {ferogram-0.2.3 → ferogram-0.4.0}/ferogram/raw/api/__init__.py +0 -0
  42. {ferogram-0.2.3 → ferogram-0.4.0}/ferogram/raw/api/functions.py +0 -0
  43. {ferogram-0.2.3 → ferogram-0.4.0}/ferogram/raw/api/types.py +0 -0
  44. {ferogram-0.2.3 → ferogram-0.4.0}/ferogram/raw/codegen.py +0 -0
  45. {ferogram-0.2.3 → ferogram-0.4.0}/ferogram/raw/generated/__init__.py +0 -0
  46. {ferogram-0.2.3 → ferogram-0.4.0}/ferogram/raw/generated/functions/__init__.py +0 -0
  47. {ferogram-0.2.3 → ferogram-0.4.0}/ferogram/raw/generated/functions/account.py +0 -0
  48. {ferogram-0.2.3 → ferogram-0.4.0}/ferogram/raw/generated/functions/aicompose.py +0 -0
  49. {ferogram-0.2.3 → ferogram-0.4.0}/ferogram/raw/generated/functions/auth.py +0 -0
  50. {ferogram-0.2.3 → ferogram-0.4.0}/ferogram/raw/generated/functions/bots.py +0 -0
  51. {ferogram-0.2.3 → ferogram-0.4.0}/ferogram/raw/generated/functions/channels.py +0 -0
  52. {ferogram-0.2.3 → ferogram-0.4.0}/ferogram/raw/generated/functions/chatlists.py +0 -0
  53. {ferogram-0.2.3 → ferogram-0.4.0}/ferogram/raw/generated/functions/contacts.py +0 -0
  54. {ferogram-0.2.3 → ferogram-0.4.0}/ferogram/raw/generated/functions/folders.py +0 -0
  55. {ferogram-0.2.3 → ferogram-0.4.0}/ferogram/raw/generated/functions/fragment.py +0 -0
  56. {ferogram-0.2.3 → ferogram-0.4.0}/ferogram/raw/generated/functions/help.py +0 -0
  57. {ferogram-0.2.3 → ferogram-0.4.0}/ferogram/raw/generated/functions/langpack.py +0 -0
  58. {ferogram-0.2.3 → ferogram-0.4.0}/ferogram/raw/generated/functions/messages.py +0 -0
  59. {ferogram-0.2.3 → ferogram-0.4.0}/ferogram/raw/generated/functions/payments.py +0 -0
  60. {ferogram-0.2.3 → ferogram-0.4.0}/ferogram/raw/generated/functions/phone.py +0 -0
  61. {ferogram-0.2.3 → ferogram-0.4.0}/ferogram/raw/generated/functions/photos.py +0 -0
  62. {ferogram-0.2.3 → ferogram-0.4.0}/ferogram/raw/generated/functions/premium.py +0 -0
  63. {ferogram-0.2.3 → ferogram-0.4.0}/ferogram/raw/generated/functions/smsjobs.py +0 -0
  64. {ferogram-0.2.3 → ferogram-0.4.0}/ferogram/raw/generated/functions/stats.py +0 -0
  65. {ferogram-0.2.3 → ferogram-0.4.0}/ferogram/raw/generated/functions/stickers.py +0 -0
  66. {ferogram-0.2.3 → ferogram-0.4.0}/ferogram/raw/generated/functions/stories.py +0 -0
  67. {ferogram-0.2.3 → ferogram-0.4.0}/ferogram/raw/generated/functions/updates.py +0 -0
  68. {ferogram-0.2.3 → ferogram-0.4.0}/ferogram/raw/generated/functions/upload.py +0 -0
  69. {ferogram-0.2.3 → ferogram-0.4.0}/ferogram/raw/generated/functions/users.py +0 -0
  70. {ferogram-0.2.3 → ferogram-0.4.0}/ferogram/raw/generated/types/__init__.py +0 -0
  71. {ferogram-0.2.3 → ferogram-0.4.0}/ferogram/raw/generated/types/_base.py +0 -0
  72. {ferogram-0.2.3 → ferogram-0.4.0}/ferogram/raw/generated/types/account.py +0 -0
  73. {ferogram-0.2.3 → ferogram-0.4.0}/ferogram/raw/generated/types/aicompose.py +0 -0
  74. {ferogram-0.2.3 → ferogram-0.4.0}/ferogram/raw/generated/types/auth.py +0 -0
  75. {ferogram-0.2.3 → ferogram-0.4.0}/ferogram/raw/generated/types/bots.py +0 -0
  76. {ferogram-0.2.3 → ferogram-0.4.0}/ferogram/raw/generated/types/channels.py +0 -0
  77. {ferogram-0.2.3 → ferogram-0.4.0}/ferogram/raw/generated/types/chatlists.py +0 -0
  78. {ferogram-0.2.3 → ferogram-0.4.0}/ferogram/raw/generated/types/contacts.py +0 -0
  79. {ferogram-0.2.3 → ferogram-0.4.0}/ferogram/raw/generated/types/fragment.py +0 -0
  80. {ferogram-0.2.3 → ferogram-0.4.0}/ferogram/raw/generated/types/help.py +0 -0
  81. {ferogram-0.2.3 → ferogram-0.4.0}/ferogram/raw/generated/types/messages.py +0 -0
  82. {ferogram-0.2.3 → ferogram-0.4.0}/ferogram/raw/generated/types/payments.py +0 -0
  83. {ferogram-0.2.3 → ferogram-0.4.0}/ferogram/raw/generated/types/phone.py +0 -0
  84. {ferogram-0.2.3 → ferogram-0.4.0}/ferogram/raw/generated/types/photos.py +0 -0
  85. {ferogram-0.2.3 → ferogram-0.4.0}/ferogram/raw/generated/types/premium.py +0 -0
  86. {ferogram-0.2.3 → ferogram-0.4.0}/ferogram/raw/generated/types/smsjobs.py +0 -0
  87. {ferogram-0.2.3 → ferogram-0.4.0}/ferogram/raw/generated/types/stats.py +0 -0
  88. {ferogram-0.2.3 → ferogram-0.4.0}/ferogram/raw/generated/types/stickers.py +0 -0
  89. {ferogram-0.2.3 → ferogram-0.4.0}/ferogram/raw/generated/types/storage.py +0 -0
  90. {ferogram-0.2.3 → ferogram-0.4.0}/ferogram/raw/generated/types/stories.py +0 -0
  91. {ferogram-0.2.3 → ferogram-0.4.0}/ferogram/raw/generated/types/updates.py +0 -0
  92. {ferogram-0.2.3 → ferogram-0.4.0}/ferogram/raw/generated/types/upload.py +0 -0
  93. {ferogram-0.2.3 → ferogram-0.4.0}/ferogram/raw/generated/types/users.py +0 -0
  94. {ferogram-0.2.3 → ferogram-0.4.0}/ferogram/raw_api.tl +0 -0
  95. {ferogram-0.2.3 → ferogram-0.4.0}/ferogram/types.py +0 -0
  96. {ferogram-0.2.3 → ferogram-0.4.0}/src/keyboards.rs +0 -0
  97. {ferogram-0.2.3 → ferogram-0.4.0}/src/raw.rs +0 -0
  98. {ferogram-0.2.3 → ferogram-0.4.0}/src/types.rs +0 -0
  99. {ferogram-0.2.3 → ferogram-0.4.0}/src/updates.rs +0 -0
@@ -0,0 +1,146 @@
1
+ name: Compile Check
2
+
3
+ on:
4
+ workflow_dispatch:
5
+ inputs:
6
+ ref:
7
+ description: "Commit hash, branch, tag, or PR (e.g. abc1234 / main / refs/pull/12/head)"
8
+ required: false
9
+ default: "main"
10
+ target:
11
+ description: "Target platform to check"
12
+ required: true
13
+ default: linux-x86_64
14
+ type: choice
15
+ options:
16
+ - linux-x86_64
17
+ - linux-aarch64
18
+ - android-aarch64
19
+ - all
20
+
21
+ jobs:
22
+
23
+ linux-x86_64:
24
+ if: inputs.target == 'linux-x86_64' || inputs.target == 'all'
25
+ runs-on: ubuntu-latest
26
+ steps:
27
+ - uses: actions/checkout@v4
28
+ with:
29
+ ref: ${{ inputs.ref }}
30
+
31
+ - uses: actions/setup-python@v5
32
+ with:
33
+ python-version: "3.13"
34
+
35
+ - uses: Swatinem/rust-cache@v2
36
+ with:
37
+ key: compile-check-x86_64
38
+
39
+ - name: Install maturin
40
+ run: pip install maturin
41
+
42
+ - name: Build (fast flags)
43
+ env:
44
+ RUSTFLAGS: "-C codegen-units=256 -C debuginfo=0"
45
+ run: maturin build --out dist
46
+
47
+ - name: Install wheel
48
+ run: pip install dist/*.whl --force-reinstall
49
+
50
+ - name: Smoke test
51
+ run: |
52
+ python3 -c "
53
+ from ferogram import (
54
+ Client, StopPropagation, ContinuePropagation, filters,
55
+ User, Dialog, ChatMember, Message,
56
+ InlineButton, InlineKeyboard,
57
+ )
58
+ print('imports ok')
59
+ "
60
+
61
+ linux-aarch64:
62
+ if: inputs.target == 'linux-aarch64' || inputs.target == 'all'
63
+ runs-on: ubuntu-latest
64
+ steps:
65
+ - uses: actions/checkout@v4
66
+ with:
67
+ ref: ${{ inputs.ref }}
68
+
69
+ - uses: actions/setup-python@v5
70
+ with:
71
+ python-version: "3.13"
72
+
73
+ - uses: Swatinem/rust-cache@v2
74
+ with:
75
+ key: compile-check-aarch64
76
+
77
+ - name: Install maturin
78
+ run: pip install maturin
79
+
80
+ - name: Build (fast flags)
81
+ env:
82
+ RUSTFLAGS: "-C codegen-units=256 -C debuginfo=0 -D__ARM_ARCH=8 -march=armv8-a"
83
+ run: maturin build --target aarch64-unknown-linux-gnu --out dist
84
+
85
+ android-aarch64:
86
+ if: inputs.target == 'android-aarch64' || inputs.target == 'all'
87
+ runs-on: ubuntu-latest
88
+ steps:
89
+ - uses: actions/checkout@v4
90
+ with:
91
+ ref: ${{ inputs.ref }}
92
+
93
+ - uses: actions/setup-python@v5
94
+ with:
95
+ python-version: "3.13"
96
+
97
+ - name: Setup Android NDK r26d
98
+ uses: nttld/setup-ndk@v1
99
+ id: ndk
100
+ with:
101
+ ndk-version: r26d
102
+ link-to-sdk: true
103
+
104
+ - uses: Swatinem/rust-cache@v2
105
+ with:
106
+ key: compile-check-android-aarch64
107
+
108
+ - name: Add Rust Android target
109
+ run: rustup target add aarch64-linux-android
110
+
111
+ - name: Install maturin
112
+ run: pip install maturin
113
+
114
+ - name: Fetch Termux libpython3.13
115
+ run: |
116
+ PKGS_URL="https://packages.termux.dev/apt/termux-main/dists/stable/main/binary-aarch64/Packages"
117
+ DEB_PATH=$(curl -sL "$PKGS_URL" | \
118
+ awk '/^Package: python$/{f=1} f && /^Filename:/{print $2; f=0}' | head -1)
119
+ mkdir -p /tmp/termux-py && cd /tmp/termux-py
120
+ curl -sL "https://packages.termux.dev/apt/termux-main/${DEB_PATH}" -o python.deb
121
+ ar x python.deb
122
+ tar xf data.tar.* --wildcards "*/libpython3.13*" 2>/dev/null || true
123
+ LIB_DIR=/tmp/termux-py/data/data/com.termux/files/usr/lib
124
+ if [ ! -f "$LIB_DIR/libpython3.13.so" ]; then
125
+ ln -sf "$(basename $(ls $LIB_DIR/libpython3.13.so* | head -1))" \
126
+ "$LIB_DIR/libpython3.13.so"
127
+ fi
128
+ echo "TERMUX_LIBDIR=$LIB_DIR" >> $GITHUB_ENV
129
+
130
+ - name: Build Android wheel (fast flags)
131
+ env:
132
+ ANDROID_NDK_HOME: ${{ steps.ndk.outputs.ndk-path }}
133
+ ANDROID_API_LEVEL: "24"
134
+ PYO3_CROSS_PYTHON_VERSION: "3.13"
135
+ RUSTFLAGS: "-C codegen-units=256 -C debuginfo=0 -L native=${{ env.TERMUX_LIBDIR }}"
136
+ run: |
137
+ NDK_BIN=$ANDROID_NDK_HOME/toolchains/llvm/prebuilt/linux-x86_64/bin
138
+ export CC_aarch64_linux_android=$NDK_BIN/aarch64-linux-android24-clang
139
+ export CXX_aarch64_linux_android=$NDK_BIN/aarch64-linux-android24-clang++
140
+ export AR_aarch64_linux_android=$NDK_BIN/llvm-ar
141
+ export CARGO_TARGET_AARCH64_LINUX_ANDROID_LINKER=$NDK_BIN/aarch64-linux-android24-clang
142
+ maturin build \
143
+ --release \
144
+ --target aarch64-linux-android \
145
+ --compatibility off \
146
+ --out dist
@@ -0,0 +1,131 @@
1
+ ## 0.4.0 (2026-06-01)
2
+
3
+ ### Added
4
+
5
+ - **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.
6
+ - `SqliteSession("name")` stores the session in a SQLite database.
7
+ - `MemorySession()` keeps the session in memory only; nothing is written to disk.
8
+ - `StringSession("AQA...")` resumes from a base64 string, useful for serverless or env-var based deployments.
9
+ - `LibSqlSession.local/remote/replica/memory(...)` targets a local file, remote Turso database, embedded replica, or in-memory libSQL database.
10
+ - `CustomSession(obj)` wraps any Python object implementing `save(bytes)`, `load() -> bytes | None`, and `delete()`.
11
+ - **`channel_kind()` on Message** - `await msg.channel_kind()` returns `"megagroup"`, `"broadcast"`, `"gigagroup"`, or `None`. Uses the peer cache; no RPC.
12
+ - **`is_megagroup()` on Message** - `await msg.is_megagroup()` returns `True` for supergroups.
13
+ - **`is_broadcast()` on Message** - `await msg.is_broadcast()` returns `True` for broadcast channels.
14
+ - **`StopPropagation` and `ContinuePropagation`** - two 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.
15
+ - **Handler groups** - all `on_*` decorators now accept `group: int = 0`. Handlers run in ascending group order; lower group numbers run first.
16
+ - **`add_handler` / `remove_handler`** - register and deregister handlers at runtime without decorators.
17
+ - **Worker pool** - a fixed pool of `workers` coroutines (default 4) now dispatches updates from a bounded `asyncio.Queue`. Replaces the old unbounded `asyncio.create_task` approach. Provides natural backpressure under load.
18
+ - **`workers` kwarg on `Client`** - controls pool size.
19
+ - **`parse_mode` kwarg on `Client`** - sets a global default parse mode applied to every `send_message` call that does not pass its own `parse_mode`.
20
+ - **`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
+ - **`download_with_progress(peer, msg_id, path, on_progress)`** - download media with a progress callback `on_progress(done, total)`.
22
+ - **`upload_with_progress(path, on_progress)`** - upload a file with a progress callback. Returns a handle string accepted by `send_file`.
23
+ - **`ferogram` 0.6.0 as core dependency** - includes `Client.channel_kind_of(channel_id)` which backs the new `Message` methods above.
24
+
25
+ ### Changed
26
+
27
+ - `no_webpage` now defaults to `True` in `send_message` and `edit_message`.
28
+ - `upload_file(data, name, mime)` replaced by `upload(Cursor(data), name)` internally; no change to the Python API.
29
+ - Session resolution order is now `session_string > session object`. `in_memory=True` is deprecated in favor of `MemorySession()`.
30
+ - Handler storage changed from `list` to `dict[group, list]`; dispatch now iterates groups in sorted order.
31
+ - `_resolve_pm` is now used internally to merge per-call and global `parse_mode`.
32
+
33
+ ### Fixed
34
+
35
+ - `channel_kind`, `is_megagroup`, `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`.
36
+ - Unnecessary `as i64` casts removed from `message.rs`.
37
+ - Nested `if let` blocks collapsed to `if let ... && ...`.
38
+ - `match ... { Some(m) => m, None => return None }` replaced with `as_ref()?`.
39
+
40
+
41
+ ## 0.3.0 (2026-05-16)
42
+
43
+ ### ferogram core upgraded to 0.5.0
44
+
45
+ The Rust dependency is now ferogram 0.5.0.
46
+
47
+ ### send_poll: full PollBuilder kwargs exposed
48
+
49
+ `send_poll` now accepts all options the Rust `PollBuilder` supports: `public_voters`,
50
+ `shuffle_answers`, `hide_results_until_close`, `close_period`, `close_date`, and `solution`.
51
+ Previously only `quiz`, `correct_index`, and `multiple_choice` were wired through.
52
+
53
+ ### edit_chat_default_banned_rights: send_reactions added
54
+
55
+ The `restrictions` dict now accepts `"send_reactions"` as a key. Mirrors the new
56
+ `send_reactions` field on `BannedRightsBuilder` added in ferogram 0.5.0.
57
+
58
+ ### poll_results method
59
+
60
+ `poll_results(peer, msg_id)` is now the canonical way to fetch poll stats. Returns
61
+ the votes graph as a JSON string. The old `get_poll_results(peer, msg_id, poll_hash)`
62
+ is kept for backward compat but is deprecated; the `poll_hash` parameter is ignored
63
+ because ferogram 0.5.0 dropped the underlying API call it relied on.
64
+
65
+ ---
66
+
67
+ # Changelog
68
+
69
+ ## 0.2.3 (2026-05-14)
70
+
71
+ ### Client Builder
72
+
73
+ Added 20 new kwargs to `Client(...)` so you can configure everything at construction time instead of touching internals.
74
+
75
+ Network options: `proxy` (SOCKS5 or MTProxy t.me link), `allow_ipv6`, `dc_addr`, `probe_transport`, `resilient_connect`.
76
+
77
+ Session backend: `session_string` and `in_memory` as alternatives to the default session file. Priority is `in_memory > session_string > file`.
78
+
79
+ Update handling: `catch_up`, `pfs`, `update_queue_capacity`, `update_overflow` (`"drop_oldest"` or `"drop_newest"`), `low_memory_mode`.
80
+
81
+ InitConnection identity: `device`, `system_version`, `app_version`, `lang_code`, `system_lang_code`, `lang_pack`.
82
+
83
+ Experimental: `allow_missing_channel_hash`, `auto_resolve_peers`.
84
+
85
+ ### Inline Bots
86
+
87
+ `InlineArticle`, `InlinePhoto`, and `InlineDocument` now expose all their fields. Previously only the 3 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.
88
+
89
+ `answer_inline_query` now accepts `next_offset` for pagination and `switch_pm` to show a "go to PM" button in the results list.
90
+
91
+ `answer_inline_query_articles` is now accessible from Python. Takes a plain list of `(id, title, text)` tuples and supports `next_offset`.
92
+
93
+ `edit_inline_message` now accepts `reply_markup` so you can attach or update a keyboard when editing.
94
+
95
+ `InlineSend` now exposes `msg_id_bytes` and `msg_id_dc` so you can build an `InlineMessageId` from the send event and edit the message later.
96
+
97
+ ### Participants
98
+
99
+ Ten new methods for managing group and channel members.
100
+
101
+ `get_participants(peer, limit=200)` fetches all members as a list of `ChatMember`.
102
+
103
+ `get_participants_filtered(peer, filter, limit)` fetches a filtered subset. Filter values: `"recent"`, `"admins"`, `"kicked"`, `"banned"`, `"bots"`.
104
+
105
+ `kick_participant(peer, user)` removes a user from the chat. They can rejoin if the chat is public or they have an invite link.
106
+
107
+ `ban_participant(peer, user)` permanently bans a user until an admin manually lifts it.
108
+
109
+ `ban_participant_until(peer, user, until_date)` bans until a unix timestamp, after which the ban lifts automatically.
110
+
111
+ `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"`.
112
+
113
+ `demote_participant(peer, user)` strips all admin rights, leaving the user as a regular member.
114
+
115
+ `get_profile_photos(peer, limit=100)` returns a list of `(file_id, access_hash, dc_id)` tuples.
116
+
117
+ `search_peer(query)` searches the local peer cache by name or username and returns a list of peer identifier strings.
118
+
119
+ `signal_network_restored()` (sync, not async) tells the client network is back so it attempts reconnect immediately instead of waiting for the retry timer.
120
+
121
+ ### Reactions and Polls
122
+
123
+ `delete_reaction(peer, msg_id, participant)` was in Rust but had no Python wrapper. Now exposed. Removes a specific user's reaction from a message, admin only.
124
+
125
+ `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
+
127
+ ---
128
+
129
+ ## 0.2.2
130
+
131
+ Previous release.