diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml
new file mode 100644
index 0000000..79a6265
--- /dev/null
+++ b/.github/FUNDING.yml
@@ -0,0 +1 @@
+github: [krypton-byte]
diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml
index e9a5dda..bee8c8a 100644
--- a/.github/workflows/CI.yml
+++ b/.github/workflows/CI.yml
@@ -51,13 +51,9 @@ jobs:
python-version: "3.12"
- uses: astral-sh/setup-uv@v5
- uses: dtolnay/rust-toolchain@stable
- - name: Rust cache (tryx root)
+ - name: Rust cache
uses: Swatinem/rust-cache@v2
- - name: Rust cache (whatsapp-rust workspace)
- uses: Swatinem/rust-cache@v2
- with:
- workspaces: "libs/whatsapp-rust -> target"
- name: Install dev dependencies
run: uv sync --group dev --no-install-project
- name: Build native extension
diff --git a/.github/workflows/pr-check.yml b/.github/workflows/pr-check.yml
index e4ee365..37c933c 100644
--- a/.github/workflows/pr-check.yml
+++ b/.github/workflows/pr-check.yml
@@ -50,14 +50,9 @@ jobs:
- uses: dtolnay/rust-toolchain@stable
- - name: Rust cache (tryx root)
+ - name: Rust cache
uses: Swatinem/rust-cache@v2
- - name: Rust cache (whatsapp-rust workspace)
- uses: Swatinem/rust-cache@v2
- with:
- workspaces: "libs/whatsapp-rust -> target"
-
- name: Install dev dependencies
run: uv sync --group dev --no-install-project
diff --git a/Cargo.lock b/Cargo.lock
index 01a29a3..4070b30 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -186,18 +186,7 @@ checksum = "82f6aeea286b8eb4dd3431a1be1b59d290ace00f5bfd8e2a159bc2a05e2c1667"
dependencies = [
"proc-macro2",
"quote",
- "syn 3.0.3",
-]
-
-[[package]]
-name = "audiopus_sys"
-version = "0.2.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "62314a1546a2064e033665d658e88c620a62904be945f8147e6b16c3db9f8651"
-dependencies = [
- "cmake",
- "log",
- "pkg-config",
+ "syn 3.0.4",
]
[[package]]
@@ -277,27 +266,25 @@ dependencies = [
[[package]]
name = "bon"
-version = "3.9.3"
+version = "3.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a602c73c7b0148ec6d12af6fd5cc7a46e2eacc8878271a999abac56eed12f561"
+checksum = "9e3fac94a66da67200398458a25412bcc3f9b6443b5119a6cad9cf3ccfcd8cc6"
dependencies = [
"bon-macros",
- "rustversion",
]
[[package]]
name = "bon-macros"
-version = "3.9.3"
+version = "3.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6dee98b0db6a962de883bf5d20362dee4d7ca0d12fe39a7c6c73c844e1cd7c1f"
+checksum = "d4654961ad0494e4774c5c60b4cb4cd0ae9b9d92d039d901638b1dba97ebebf5"
dependencies = [
- "darling 0.23.0",
+ "darling 0.24.1",
"ident_case",
- "prettyplease",
+ "prettyplease 0.3.0",
"proc-macro2",
"quote",
- "rustversion",
- "syn 2.0.119",
+ "syn 3.0.4",
]
[[package]]
@@ -337,7 +324,7 @@ checksum = "2074a9c2f76b2ebe6af40f7bf67b6a19d6ce3663253ef2a55124dc93f38b230e"
dependencies = [
"buffa",
"buffa-descriptor",
- "prettyplease",
+ "prettyplease 0.2.37",
"proc-macro2",
"quote",
"syn 2.0.119",
@@ -382,7 +369,7 @@ checksum = "46d07918caa9eeaaf06b7873925c53a61daac173539b4f7715090745e44e4e69"
dependencies = [
"proc-macro2",
"quote",
- "syn 3.0.3",
+ "syn 3.0.4",
]
[[package]]
@@ -680,12 +667,12 @@ dependencies = [
[[package]]
name = "darling"
-version = "0.23.0"
+version = "0.24.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "25ae13da2f202d56bd7f91c25fba009e7717a1e4a1cc98a76d844b65ae912e9d"
+checksum = "ed17f5901b6630b993ca003def43f2f8ef4014fc13b047b57aad617ff32bc2ec"
dependencies = [
- "darling_core 0.23.0",
- "darling_macro 0.23.0",
+ "darling_core 0.24.1",
+ "darling_macro 0.24.1",
]
[[package]]
@@ -704,15 +691,15 @@ dependencies = [
[[package]]
name = "darling_core"
-version = "0.23.0"
+version = "0.24.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9865a50f7c335f53564bb694ef660825eb8610e0a53d3e11bf1b0d3df31e03b0"
+checksum = "6837e2cf7485aaae18f86181d2f0e9a7ed297a025e220aeabf63fdebd3a2ddff"
dependencies = [
"ident_case",
"proc-macro2",
"quote",
"strsim",
- "syn 2.0.119",
+ "syn 3.0.4",
]
[[package]]
@@ -728,13 +715,13 @@ dependencies = [
[[package]]
name = "darling_macro"
-version = "0.23.0"
+version = "0.24.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ac3984ec7bd6cfa798e62b4a642426a5be0e68f9401cfc2a01e3fa9ea2fcdb8d"
+checksum = "2ac7135c3ef02b2f7833bbeb1be5ba7f966dcde8a87c6b87f65a778d71a02785"
dependencies = [
- "darling_core 0.23.0",
+ "darling_core 0.24.1",
"quote",
- "syn 2.0.119",
+ "syn 3.0.4",
]
[[package]]
@@ -854,7 +841,7 @@ checksum = "c6232dd377dcc64799954cbd3a9bb882e9cdc1308ccd87b1c098f1fb2eaf82a8"
dependencies = [
"proc-macro2",
"quote",
- "syn 3.0.3",
+ "syn 3.0.4",
]
[[package]]
@@ -1023,7 +1010,7 @@ checksum = "9fb9654ba8355388abeb8dcb4fc62f511300867002afc858860463bdd9fe0c44"
dependencies = [
"proc-macro2",
"quote",
- "syn 3.0.3",
+ "syn 3.0.4",
]
[[package]]
@@ -1400,9 +1387,9 @@ dependencies = [
[[package]]
name = "libsqlite3-sys"
-version = "0.37.0"
+version = "0.38.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b1f111c8c41e7c61a49cd34e44c7619462967221a6443b0ec299e0ac30cfb9b1"
+checksum = "f1d20bef17f513b9b3004532233187769cd072d790971f4e4da0e346eb6401e8"
dependencies = [
"cc",
"pkg-config",
@@ -1626,11 +1613,20 @@ checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50"
[[package]]
name = "opus"
-version = "0.3.1"
+version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4d3809943dff6fbad5f0484449ea26bdb9cb7d8efdf26ed50d3c7f227f69eb5c"
+checksum = "33718946cc77d4032911d4efe03a66dbcbfbd2bb16c3da06aaeadcc637c32216"
dependencies = [
- "audiopus_sys",
+ "opusic-sys",
+]
+
+[[package]]
+name = "opusic-sys"
+version = "0.7.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c9d1ecdf206421bc74343ab3bb2f30ad2abbfee41fa341f7181fecbaf957769a"
+dependencies = [
+ "cmake",
]
[[package]]
@@ -1732,6 +1728,16 @@ dependencies = [
"syn 2.0.119",
]
+[[package]]
+name = "prettyplease"
+version = "0.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2bfe0f4c752e450fc2faf62654f1c134747922825d5b04ca717b8874f41a40c0"
+dependencies = [
+ "proc-macro2",
+ "syn 3.0.4",
+]
+
[[package]]
name = "proc-macro2"
version = "1.0.107"
@@ -1758,7 +1764,7 @@ checksum = "1c8d9ca532f185d5d4db7a7c9d51420b452168ea1c2b913953281bd6fe1fcbd0"
dependencies = [
"proc-macro2",
"quote",
- "syn 3.0.3",
+ "syn 3.0.4",
]
[[package]]
@@ -1996,7 +2002,7 @@ checksum = "1c25ef604ac7dd839d44d64648952ea23c97866f124ff671b0ed2cf3ad9bb06e"
dependencies = [
"proc-macro2",
"quote",
- "syn 3.0.3",
+ "syn 3.0.4",
]
[[package]]
@@ -2011,9 +2017,9 @@ dependencies = [
[[package]]
name = "rtc-crypto"
-version = "0.21.0-beta.1"
+version = "0.21.0-beta.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1d47521f43ea9a6e16feafa78ba06633ca85a51f0ad66b906a5f01ccfe08ba90"
+checksum = "df0f2e4801a79469b8094f715f563d946c76826336f8d9fefb47dc6628524f11"
dependencies = [
"aes 0.8.4",
"ccm",
@@ -2030,9 +2036,9 @@ dependencies = [
[[package]]
name = "rtc-datachannel"
-version = "0.21.0-beta.1"
+version = "0.21.0-beta.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "374adcfc6f138839109d84c521ccedae9410b11f62c1ae577cb786ed91494f50"
+checksum = "0180e434128b3a3e9d8552ea958fd588839266cf08a2625741fbe65c292d1cb8"
dependencies = [
"bytes",
"log",
@@ -2043,9 +2049,9 @@ dependencies = [
[[package]]
name = "rtc-dtls"
-version = "0.21.0-beta.1"
+version = "0.21.0-beta.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3baf3ee5b4d481d57fdee828ed4abd281ba45ad98594502cd4e866d14316b48f"
+checksum = "b6cb87e1ec1b828914aace884307974a9ed40747e2f6ccaab93a4fff42528a73"
dependencies = [
"bytecheck",
"byteorder",
@@ -2063,9 +2069,9 @@ dependencies = [
[[package]]
name = "rtc-sctp"
-version = "0.21.0-beta.1"
+version = "0.21.0-beta.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "db38ed06af7bea634b210c3e8cf0e78e3bb36669e120968f5961a3c12a209b67"
+checksum = "9d9dabdca726a7c5eed4d4ae5f3f9d4e9baf7a2ed53efaedaae35b4bcc24bc2a"
dependencies = [
"bytes",
"crc32c",
@@ -2079,9 +2085,9 @@ dependencies = [
[[package]]
name = "rtc-shared"
-version = "0.21.0-beta.1"
+version = "0.21.0-beta.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "108063844e58fa8470139c2d6bea3a28362e07d43194acef7e0d57d829d27cd6"
+checksum = "998b045d95d158251842c5146918f3213346ca7724e8c6ac750c37d467dbbcdd"
dependencies = [
"bitflags 1.3.2",
"bytes",
@@ -2235,7 +2241,7 @@ checksum = "e7a5d71263a5a7d47b41f6b3f06ba276f10cc18b0931f1799f710578e2309348"
dependencies = [
"proc-macro2",
"quote",
- "syn 3.0.3",
+ "syn 3.0.4",
]
[[package]]
@@ -2524,9 +2530,9 @@ dependencies = [
[[package]]
name = "syn"
-version = "3.0.3"
+version = "3.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "53e9bae58849f64dfa4f5d5ae372c8341f7305f82a3868709269343628b659a3"
+checksum = "e6275cddf4610d1775e6d1fe9469b2e77d0f39fd98fb7450901b821e0c53649f"
dependencies = [
"proc-macro2",
"quote",
@@ -2600,7 +2606,7 @@ checksum = "bc04cd3e1236dd4a98afca4569f2deb3f120e5422a4023be2cb683f8486292af"
dependencies = [
"proc-macro2",
"quote",
- "syn 3.0.3",
+ "syn 3.0.4",
]
[[package]]
@@ -2691,7 +2697,7 @@ checksum = "78773a2a397f451582ce068015985c33193cf6dea8b74d2a639fe457b2f07b0e"
dependencies = [
"proc-macro2",
"quote",
- "syn 3.0.3",
+ "syn 3.0.4",
]
[[package]]
@@ -2984,6 +2990,7 @@ dependencies = [
"buffa",
"buffa-build",
"bytes",
+ "cbc",
"chrono",
"compact_str",
"ctr 0.10.1",
@@ -3059,7 +3066,7 @@ version = "0.7.0"
dependencies = [
"proc-macro2",
"quote",
- "syn 3.0.3",
+ "syn 3.0.4",
]
[[package]]
@@ -3619,7 +3626,7 @@ checksum = "34df6fc39dbd26ddc9c10e6a2984476e13acce22e64e4487636ef494369225da"
dependencies = [
"proc-macro2",
"quote",
- "syn 3.0.3",
+ "syn 3.0.4",
]
[[package]]
diff --git a/README.id.md b/README.id.md
index e923495..0211f8f 100644
--- a/README.id.md
+++ b/README.id.md
@@ -1,8 +1,13 @@
+
+

+
# Tryx
[](https://pypi.org/project/tryx/)
[](https://pypi.org/project/tryx/)
[](LICENSE)
+
+
[](https://krypton-byte.github.io/tryx/)
**Bahasa:** [English](README.md) | [简体中文](README.zh.md) | Bahasa Indonesia
diff --git a/README.md b/README.md
index 95a24c2..fbbdeea 100644
--- a/README.md
+++ b/README.md
@@ -1,3 +1,6 @@
+
+

+
# Tryx
[](https://pypi.org/project/tryx/)
@@ -7,6 +10,8 @@
**Language:** English | [简体中文](README.zh.md) | [Bahasa Indonesia](README.id.md)
+
+
Tryx is a Python automation library powered by Rust and PyO3. It provides a Python-friendly API on top of the `whatsapp-rust` crate, with async support, persistent sessions, and access to advanced WhatsApp Web protocol features.
> Tryx is an independent project. It is not affiliated with WhatsApp, Meta, or their official products.
diff --git a/README.zh.md b/README.zh.md
index bc51c1e..371ee42 100644
--- a/README.zh.md
+++ b/README.zh.md
@@ -1,8 +1,13 @@
+
+

+
# Tryx
[](https://pypi.org/project/tryx/)
[](https://pypi.org/project/tryx/)
[](LICENSE)
+
+
[](https://krypton-byte.github.io/tryx/)
**语言:** [English](README.md) | 简体中文 | [Bahasa Indonesia](README.id.md)
diff --git a/assets/mascot.png b/assets/mascot.png
new file mode 100644
index 0000000..7cf791c
Binary files /dev/null and b/assets/mascot.png differ
diff --git a/docs/api/client.md b/docs/api/client.md
index 39c5d16..bbf05c9 100644
--- a/docs/api/client.md
+++ b/docs/api/client.md
@@ -1,4 +1,4 @@
-# Client API Gateway
+# :material-api: Client API Gateway
::: tryx.client.Tryx
options:
diff --git a/docs/api/events.md b/docs/api/events.md
index 4a18b08..e19e7da 100644
--- a/docs/api/events.md
+++ b/docs/api/events.md
@@ -1,4 +1,4 @@
-# Events API
+# :material-broadcast: Events API
::: tryx.events.Dispatcher
options:
@@ -172,6 +172,40 @@ async def on_presence(client, event):
pass
```
+## Example: Group Subject Change with LID Addressing
+
+When a group subject (name) is changed, the `Subject` action carries the renamer's identity. In LID-addressed groups, the phone-number alias arrives in a separate field:
+
+```python
+from tryx.events import EvGroupUpdate, GroupNotificationAction
+
+
+@app.on(EvGroupUpdate)
+async def on_group_update(client, event):
+ action = event.data.action
+
+ if isinstance(action, GroupNotificationAction.Subject):
+ renamer = action.subject_owner # JID (may be a LID)
+ renamer_pn = action.subject_owner_pn # phone-number JID (when LID addressing)
+ renamer_name = action.subject_owner_username # username (when enabled)
+
+ # Prefer the phone-number JID for display when available
+ display_jid = renamer_pn or renamer
+ print(
+ f"Group renamed to {action.subject!r} "
+ f"by {display_jid}"
+ )
+
+ # Log all identity fields for audit
+ if renamer_pn:
+ print(f" LID: {renamer}, PN: {renamer_pn}")
+ if renamer_name:
+ print(f" Username: {renamer_name}")
+```
+
+!!! tip "LID vs Phone Number"
+ In WhatsApp's LID addressing mode, `subject_owner` may be a `@lid` JID that is not human-readable. The `subject_owner_pn` field provides the corresponding phone-number JID for display. When LID addressing is not active, `subject_owner_pn` is `None` and `subject_owner` already contains the phone-number JID.
+
## Enum-like Support Types
Common reason/state classes used by event payloads:
diff --git a/docs/api/exceptions.md b/docs/api/exceptions.md
index aa3c0bd..e40a726 100644
--- a/docs/api/exceptions.md
+++ b/docs/api/exceptions.md
@@ -1,4 +1,4 @@
-# Exceptions API
+# :material-alert-circle: Exceptions API
::: tryx.exceptions.FailedBuildClient
options:
diff --git a/docs/api/index.md b/docs/api/index.md
new file mode 100644
index 0000000..99ad245
--- /dev/null
+++ b/docs/api/index.md
@@ -0,0 +1,7 @@
+---
+icon: material/api
+---
+
+# :material-api: API Reference
+
+Complete API documentation for all Tryx modules.
diff --git a/docs/api/types.md b/docs/api/types.md
index 05c9122..6e02eff 100644
--- a/docs/api/types.md
+++ b/docs/api/types.md
@@ -1,4 +1,4 @@
-# Types API
+# :material-shape: Types API
::: tryx.types.JID
options:
diff --git a/docs/assets/mascot.png b/docs/assets/mascot.png
new file mode 100644
index 0000000..7cf791c
Binary files /dev/null and b/docs/assets/mascot.png differ
diff --git a/docs/core-concepts/architecture.md b/docs/core-concepts/architecture.md
index 4194aea..b469839 100644
--- a/docs/core-concepts/architecture.md
+++ b/docs/core-concepts/architecture.md
@@ -1,4 +1,4 @@
-# Architecture
+# :material-puzzle: Architecture
Tryx splits performance-sensitive protocol work (Rust) from application
ergonomics (Python). This gives you WhatsApp protocol handling at native
diff --git a/docs/core-concepts/event-model.md b/docs/core-concepts/event-model.md
index f18709e..65e6bd5 100644
--- a/docs/core-concepts/event-model.md
+++ b/docs/core-concepts/event-model.md
@@ -1,4 +1,4 @@
-# Event Model
+# :material-bell-ring: Event Model
Tryx uses an event-driven architecture. All WhatsApp interactions — messages,
presence changes, group updates, contact syncs — flow through typed event
diff --git a/docs/core-concepts/index.md b/docs/core-concepts/index.md
new file mode 100644
index 0000000..d0cbb41
--- /dev/null
+++ b/docs/core-concepts/index.md
@@ -0,0 +1,7 @@
+---
+icon: material/puzzle-outline
+---
+
+# :material-puzzle: Core Concepts
+
+Understand the architecture and design principles behind Tryx.
diff --git a/docs/core-concepts/storage-backends.md b/docs/core-concepts/storage-backends.md
index efc2f9a..7d203eb 100644
--- a/docs/core-concepts/storage-backends.md
+++ b/docs/core-concepts/storage-backends.md
@@ -1,4 +1,4 @@
-# Storage Backends
+# :material-database: Storage Backends
Tryx supports a **3-tier storage architecture** so you can pick the right balance between simplicity, performance, and flexibility for your project.
diff --git a/docs/core-concepts/type-system.md b/docs/core-concepts/type-system.md
index cd37b2d..4330d47 100644
--- a/docs/core-concepts/type-system.md
+++ b/docs/core-concepts/type-system.md
@@ -1,4 +1,4 @@
-# Type System
+# :material-code-braces: Type System
Tryx ships with complete `.pyi` stub files and a `py.typed` marker,
enabling full editor intelligence, static analysis, and API discoverability.
diff --git a/docs/faq/qna.md b/docs/faq/qna.md
index cebc82e..a885128 100644
--- a/docs/faq/qna.md
+++ b/docs/faq/qna.md
@@ -1,4 +1,4 @@
-# FAQ
+# :material-frequently-asked-questions: FAQ
Quick answers to common questions. Jump to the linked pages for implementation
details.
diff --git a/docs/getting-started/authentication.md b/docs/getting-started/authentication.md
index f9d7555..8edbd32 100644
--- a/docs/getting-started/authentication.md
+++ b/docs/getting-started/authentication.md
@@ -1,4 +1,4 @@
-# Authentication Flow
+# :material-key-variant: Authentication Flow
Tryx follows the WhatsApp multi-device pairing flow. The first run links
a session, and later runs reuse stored state.
diff --git a/docs/getting-started/contributing.md b/docs/getting-started/contributing.md
index e92d8d8..3f5d25a 100644
--- a/docs/getting-started/contributing.md
+++ b/docs/getting-started/contributing.md
@@ -1,4 +1,4 @@
-# Contributing
+# :material-account-group: Contributing
This guide explains how to contribute to Tryx development.
diff --git a/docs/getting-started/index.md b/docs/getting-started/index.md
new file mode 100644
index 0000000..ab1f94f
--- /dev/null
+++ b/docs/getting-started/index.md
@@ -0,0 +1,7 @@
+---
+icon: material/rocket-launch-outline
+---
+
+# :material-rocket-launch: Getting Started
+
+Get up and running with Tryx quickly.
diff --git a/docs/getting-started/installation.md b/docs/getting-started/installation.md
index 76e3c9c..80a8510 100644
--- a/docs/getting-started/installation.md
+++ b/docs/getting-started/installation.md
@@ -1,4 +1,4 @@
-# Installation
+# :material-package-variant: Installation
This guide sets up a working development environment for building with Tryx.
diff --git a/docs/getting-started/quickstart.md b/docs/getting-started/quickstart.md
index 374aa80..1faa13f 100644
--- a/docs/getting-started/quickstart.md
+++ b/docs/getting-started/quickstart.md
@@ -1,4 +1,4 @@
-# Quick Start
+# :material-rocket-launch: Quick Start
Build a working WhatsApp bot in 5 minutes. This guide walks through the
minimal setup, then expands with real functionality.
diff --git a/docs/index.md b/docs/index.md
index 997a3ae..f34b44b 100644
--- a/docs/index.md
+++ b/docs/index.md
@@ -1,3 +1,11 @@
+---
+icon: material/home
+---
+
+
+

+
+
# Tryx
**Rust-powered Python SDK for event-driven WhatsApp automation.**
diff --git a/docs/operations/deployment.md b/docs/operations/deployment.md
index e9bd46a..f50f4de 100644
--- a/docs/operations/deployment.md
+++ b/docs/operations/deployment.md
@@ -1,4 +1,4 @@
-# Deployment Guide
+# :material-cloud-upload: Deployment Guide
Deploy Tryx bots safely in production with stable session storage and predictable restarts.
diff --git a/docs/operations/index.md b/docs/operations/index.md
new file mode 100644
index 0000000..90185c6
--- /dev/null
+++ b/docs/operations/index.md
@@ -0,0 +1,7 @@
+---
+icon: material/cog-outline
+---
+
+# :material-cog: Operations
+
+Deployment, monitoring, and maintenance guides.
diff --git a/docs/operations/performance.md b/docs/operations/performance.md
index 88ab8b0..2b46c63 100644
--- a/docs/operations/performance.md
+++ b/docs/operations/performance.md
@@ -1,4 +1,4 @@
-# Performance Guide
+# :material-speedometer: Performance Guide
Optimize for predictable latency and stable memory under burst traffic.
diff --git a/docs/operations/reliability.md b/docs/operations/reliability.md
index 45759b6..501ff3a 100644
--- a/docs/operations/reliability.md
+++ b/docs/operations/reliability.md
@@ -1,4 +1,4 @@
-# Reliability Playbook
+# :material-shield-check: Reliability Playbook
This page focuses on idempotency, retry strategy, and safe handler design.
diff --git a/docs/operations/security.md b/docs/operations/security.md
index 642e73a..7a458a0 100644
--- a/docs/operations/security.md
+++ b/docs/operations/security.md
@@ -1,4 +1,4 @@
-# Security Practices
+# :material-lock: Security Practices
Secure your client around four risk zones: session state, operator controls, user input, and outbound behavior.
diff --git a/docs/operations/troubleshooting.md b/docs/operations/troubleshooting.md
index 8e07a4c..0fc5efd 100644
--- a/docs/operations/troubleshooting.md
+++ b/docs/operations/troubleshooting.md
@@ -1,4 +1,4 @@
-# Troubleshooting
+# :material-wrench: Troubleshooting
Use this page as a decision tree first, checklist second.
diff --git a/docs/overrides/main.html b/docs/overrides/main.html
index 0af326a..8c4bcf4 100644
--- a/docs/overrides/main.html
+++ b/docs/overrides/main.html
@@ -1,5 +1,11 @@
{% extends "base.html" %}
+{% block scripts %}
+ {{ super() }}
+
+
+{% endblock %}
+
{% block outdated %}
You're not viewing the latest version.
diff --git a/docs/reference/changelog.md b/docs/reference/changelog.md
index ca51fd0..7b3c1d3 100644
--- a/docs/reference/changelog.md
+++ b/docs/reference/changelog.md
@@ -1,4 +1,4 @@
-# Changelog Policy
+# :material-history: Changelog Policy
Tryx changelog is generated automatically with `python-semantic-release`.
diff --git a/docs/reference/error-handling.md b/docs/reference/error-handling.md
index c57fafa..05d8a1d 100644
--- a/docs/reference/error-handling.md
+++ b/docs/reference/error-handling.md
@@ -1,4 +1,4 @@
-# Error Handling
+# :material-bug: Error Handling
Use exception classes and failure classification to decide whether to retry,
fail fast, or trigger operator action.
diff --git a/docs/reference/glossary.md b/docs/reference/glossary.md
index 2d0cd25..7cb37ff 100644
--- a/docs/reference/glossary.md
+++ b/docs/reference/glossary.md
@@ -1,4 +1,4 @@
-# Glossary
+# :material-book-alphabetical: Glossary
---
diff --git a/docs/reference/index.md b/docs/reference/index.md
new file mode 100644
index 0000000..39e2867
--- /dev/null
+++ b/docs/reference/index.md
@@ -0,0 +1,7 @@
+---
+icon: material/bookshelf
+---
+
+# :material-bookshelf: Reference
+
+Additional resources, FAQ, and changelog.
diff --git a/docs/reference/roadmap.md b/docs/reference/roadmap.md
index 301658b..e252cd1 100644
--- a/docs/reference/roadmap.md
+++ b/docs/reference/roadmap.md
@@ -1,4 +1,4 @@
-# Roadmap
+# :material-map: Roadmap
## Near-Term
diff --git a/docs/tutorials/command-bot.md b/docs/tutorials/command-bot.md
index 208ed90..88a9da7 100644
--- a/docs/tutorials/command-bot.md
+++ b/docs/tutorials/command-bot.md
@@ -1,4 +1,4 @@
-# Tutorial: Command Bot
+# :material-console: Tutorial: Command Bot
Build a command-driven WhatsApp bot that stays maintainable as command count
grows. This tutorial progresses from a minimal router to a production-ready
diff --git a/docs/tutorials/group-automation.md b/docs/tutorials/group-automation.md
index 3ae71de..5927c51 100644
--- a/docs/tutorials/group-automation.md
+++ b/docs/tutorials/group-automation.md
@@ -1,4 +1,4 @@
-# Tutorial: Group Automation
+# :material-account-multiple: Tutorial: Group Automation
Automate full group lifecycle with safe participant governance.
diff --git a/docs/tutorials/index.md b/docs/tutorials/index.md
new file mode 100644
index 0000000..9d98f9b
--- /dev/null
+++ b/docs/tutorials/index.md
@@ -0,0 +1,7 @@
+---
+icon: material/school-outline
+---
+
+# :material-school: Tutorials
+
+Step-by-step guides to build real-world integrations.
diff --git a/docs/tutorials/media-workflows.md b/docs/tutorials/media-workflows.md
index 67899e6..cf9f6e3 100644
--- a/docs/tutorials/media-workflows.md
+++ b/docs/tutorials/media-workflows.md
@@ -1,4 +1,4 @@
-# Tutorial: Media Workflows
+# :material-image-multiple: Tutorial: Media Workflows
This tutorial covers send, download, and recovery flows for media-heavy bots.
diff --git a/docs/tutorials/poll-survey.md b/docs/tutorials/poll-survey.md
index d0ed405..f06abac 100644
--- a/docs/tutorials/poll-survey.md
+++ b/docs/tutorials/poll-survey.md
@@ -1,4 +1,4 @@
-# Tutorial: Poll Survey Workflow
+# :material-poll: Tutorial: Poll Survey Workflow
Create poll surveys, collect encrypted votes, and aggregate results.
diff --git a/docs/tutorials/profile-privacy.md b/docs/tutorials/profile-privacy.md
index c825837..eeea536 100644
--- a/docs/tutorials/profile-privacy.md
+++ b/docs/tutorials/profile-privacy.md
@@ -1,4 +1,4 @@
-# Tutorial: Profile and Privacy
+# :material-account-cog: Tutorial: Profile and Privacy
Build admin-controlled profile and privacy management commands.
diff --git a/libs/whatsapp-rust b/libs/whatsapp-rust
index 1489b7d..1ace865 160000
--- a/libs/whatsapp-rust
+++ b/libs/whatsapp-rust
@@ -1 +1 @@
-Subproject commit 1489b7da9a6a7e3cadc4337ee46399da7de25915
+Subproject commit 1ace865716726daec8d0f00335453fcb8de35d1b
diff --git a/mkdocs.yml b/mkdocs.yml
index c724ea9..0d9ba16 100644
--- a/mkdocs.yml
+++ b/mkdocs.yml
@@ -9,60 +9,67 @@ edit_uri: edit/main/docs/
nav:
- Home: index.md
- Getting Started:
- - Installation: getting-started/installation.md
- - Quick Start: getting-started/quickstart.md
- - Authentication Flow: getting-started/authentication.md
- - Contributing: getting-started/contributing.md
+ - getting-started/index.md
+ - getting-started/installation.md
+ - getting-started/quickstart.md
+ - getting-started/authentication.md
+ - getting-started/contributing.md
- Core Concepts:
- - Architecture: core-concepts/architecture.md
- - Event Model: core-concepts/event-model.md
- - Storage Backends: core-concepts/storage-backends.md
- - Type System: core-concepts/type-system.md
+ - core-concepts/index.md
+ - core-concepts/architecture.md
+ - core-concepts/event-model.md
+ - core-concepts/storage-backends.md
+ - core-concepts/type-system.md
- API Reference:
- - Client API Gateway: api/client.md
- - Storage Backends: api/backend.md
- - Client Namespaces:
- - Contact: api/contact.md
- - Chat Actions: api/chat-actions.md
- - Community: api/community.md
- - Newsletter: api/newsletter.md
- - Groups: api/groups.md
- - Status: api/status.md
- - Chatstate: api/chatstate.md
- - Blocking: api/blocking.md
- - Polls: api/polls.md
- - Presence: api/presence.md
- - Privacy: api/privacy.md
- - Profile: api/profile.md
- - Events API: api/events.md
- - Types API: api/types.md
- - Exceptions: api/exceptions.md
- - Helpers: api/helpers.md
- - WACore: api/wacore.md
+ - api/index.md
+ - api/client.md
+ - api/backend.md
+ - api/contact.md
+ - api/chat-actions.md
+ - api/community.md
+ - api/newsletter.md
+ - api/groups.md
+ - api/status.md
+ - api/chatstate.md
+ - api/blocking.md
+ - api/polls.md
+ - api/presence.md
+ - api/privacy.md
+ - api/profile.md
+ - api/events.md
+ - api/types.md
+ - api/exceptions.md
+ - api/helpers.md
+ - api/wacore.md
- Tutorials:
- - Command Bot: tutorials/command-bot.md
- - Profile & Privacy: tutorials/profile-privacy.md
- - Poll Survey: tutorials/poll-survey.md
- - Media Workflows: tutorials/media-workflows.md
- - Group Automation: tutorials/group-automation.md
+ - tutorials/index.md
+ - tutorials/command-bot.md
+ - tutorials/profile-privacy.md
+ - tutorials/poll-survey.md
+ - tutorials/media-workflows.md
+ - tutorials/group-automation.md
- Operations:
- - Deployment: operations/deployment.md
- - Reliability: operations/reliability.md
- - Troubleshooting: operations/troubleshooting.md
- - Performance: operations/performance.md
- - Security: operations/security.md
+ - operations/index.md
+ - operations/deployment.md
+ - operations/reliability.md
+ - operations/troubleshooting.md
+ - operations/performance.md
+ - operations/security.md
- Reference:
- - FAQ: faq/qna.md
- - Glossary: reference/glossary.md
- - Error Handling: reference/error-handling.md
- - Roadmap: reference/roadmap.md
- - Changelog: reference/changelog.md
+ - reference/index.md
+ - faq/qna.md
+ - reference/glossary.md
+ - reference/error-handling.md
+ - reference/roadmap.md
+ - reference/changelog.md
theme:
name: material
variant: modern
language: en
custom_dir: docs/overrides
+ logo: assets/mascot.png
+ favicon: assets/mascot.png
font:
text: Inter
code: JetBrains Mono
@@ -70,6 +77,7 @@ theme:
- navigation.sections
- navigation.tabs
- navigation.tabs.sticky
+ - navigation.indexes
- navigation.top
- navigation.path
- navigation.tracking
@@ -87,7 +95,7 @@ theme:
- search.highlight
- search.share
- toc.follow
- - toc.integrate
+ # - toc.integrate # not compatible with navigation.indexes
palette:
- media: "(prefers-color-scheme: light)"
scheme: default
diff --git a/python/tryx/events.pyi b/python/tryx/events.pyi
index 118179d..a55ac7e 100644
--- a/python/tryx/events.pyi
+++ b/python/tryx/events.pyi
@@ -108,11 +108,32 @@ class BusinessStatusUpdateType:
Unknown: BusinessStatusUpdateType
class GroupNotificationAction:
- """Opaque group update action variant.
+ """Group update action variant.
The runtime returns one action object that describes what changed in a group.
+ Access the variant type via ``isinstance`` checks, for example::
+
+ from tryx.events import GroupNotificationAction
+
+ if isinstance(action, GroupNotificationAction.Subject):
+ print(action.subject)
+ print(action.subject_owner_pn)
"""
+ class Subject:
+ """Group subject (name) was changed."""
+
+ subject: str
+ """New group name."""
+ subject_owner: JID | None
+ """JID of the user who renamed the group (follows addressing mode)."""
+ subject_owner_pn: JID | None
+ """Phone-number JID of the renamer when ``subject_owner`` is a LID."""
+ subject_owner_username: str | None
+ """Renamer's username, when username addressing is enabled."""
+ subject_timestamp: datetime | None
+ """Server timestamp of the rename."""
+
class EvConnected:
"""Emitted when the session becomes connected."""
diff --git a/src/clients/tryx.rs b/src/clients/tryx.rs
index 49eb52b..66ef8ea 100644
--- a/src/clients/tryx.rs
+++ b/src/clients/tryx.rs
@@ -34,7 +34,7 @@ use super::status::StatusClient;
use super::tryx_client::TryxClient;
use crate::clients::chat_actions::ChatActionsClient;
use crate::log::init_logging;
-use crate::backend::{SqliteStore, BackendBase};
+use crate::backend::SqliteStore;
use crate::events::types::{
EvArchiveUpdate, EvBusinessStatusUpdate, EvChatPresence, EvClientOutDated, EvConnectFailure, EvConnected, EvContactNumberChanged, EvContactSyncRequested, EvContactUpdate, EvContactUpdated, EvDeleteChatUpdate, EvDeleteMessageForMeUpdate, EvDeviceListUpdate, EvDisappearingModeChanged, EvDisconnected, EvGroupUpdate, EvHistorySync, EvLoggedOut, EvMarkChatAsReadUpdate, EvMessage, EvMuteUpdate, EvNewsletterLiveUpdate, EvNotification, EvOfflineSyncCompleted, EvOfflineSyncPreview, EvPairError, EvPairSuccess, EvPairingCode, EvPairingQrCode, EvPictureUpdate, EvPinUpdate, EvPresence, EvPushNameUpdate, EvQrScannedWithoutMultidevice, EvReceipt, EvSelfPushNameUpdated, EvStarUpdate, EvStreamError, EvStreamReplaced, EvTemporaryBan, EvUndecryptableMessage, EvUserAboutUpdate
};
diff --git a/src/clients/voip.rs b/src/clients/voip.rs
index 4373a14..efd6a72 100644
--- a/src/clients/voip.rs
+++ b/src/clients/voip.rs
@@ -113,15 +113,20 @@ impl CallHandle {
self.inner.is_muted()
}
- fn set_muted(&self, muted: bool) {
- self.inner.set_muted(muted);
+ fn set_muted<'py>(&self, py: Python<'py>, muted: bool) -> PyResult> {
+ let call = self.inner.clone();
+ let locals = get_current_locals(py)?;
+ future_into_py_with_locals(py, locals, async move {
+ let _ = call.set_muted(muted).await;
+ Ok(())
+ })
}
fn hangup<'py>(&self, py: Python<'py>) -> PyResult> {
let call = self.inner.clone();
let locals = get_current_locals(py)?;
future_into_py_with_locals(py, locals, async move {
- call.hangup().await;
+ call.hangup_local().await;
Ok(())
})
}
diff --git a/src/events/types/message_and_updates.rs b/src/events/types/message_and_updates.rs
index 849c687..dcbb4e9 100644
--- a/src/events/types/message_and_updates.rs
+++ b/src/events/types/message_and_updates.rs
@@ -719,6 +719,8 @@ pub enum GroupNotificationAction {
Subject {
subject: String,
subject_owner: Option>,
+ subject_owner_pn: Option>,
+ subject_owner_username: Option,
subject_timestamp: Option>,
},
Description {
@@ -885,14 +887,17 @@ impl EvGroupUpdate {
let py_participants = py_group_participants(participants);
GroupNotificationAction::Modify { participants: py_participants }
},
- wacore::stanza::groups::GroupNotificationAction::Subject { subject, subject_owner, subject_time } => {
+ wacore::stanza::groups::GroupNotificationAction::Subject { subject, subject_owner, subject_owner_pn, subject_owner_username, subject_time } => {
let py_subject_owner = subject_owner
.as_ref()
.map(|o| Py::new(py, JID::from(o.clone())).unwrap());
+ let py_subject_owner_pn = subject_owner_pn
+ .as_ref()
+ .map(|o| Py::new(py, JID::from(o.clone())).unwrap());
let py_subject_timestamp = subject_time.map(|t| {
PyDateTime::from_timestamp(py, t as f64, None).unwrap().into()
});
- GroupNotificationAction::Subject { subject: subject.clone(), subject_owner: py_subject_owner, subject_timestamp: py_subject_timestamp }
+ GroupNotificationAction::Subject { subject: subject.clone(), subject_owner: py_subject_owner, subject_owner_pn: py_subject_owner_pn, subject_owner_username: subject_owner_username.clone(), subject_timestamp: py_subject_timestamp }
},
wacore::stanza::groups::GroupNotificationAction::Description { id, description } => {
GroupNotificationAction::Description { id: id.clone(), description: description.clone() }