Skip to content

Rust libraries

Use these libraries for supported WeChat server operations and official profile storage. They run without the daemon or an official executable. Applications connecting to an existing daemon can use the HTTP API.

CratePurpose
wechat-protocolTransport, authentication, sync and message codecs
wechat-profileProfile keys, history, contacts, cached media and checked writers
wechat-mediaShared image inspection and decoding
wechat-platformPrivate files and OS support

The Rust crate architecture maps published libraries and internal runtime dependencies. Use the Calls API to connect a calling client to the daemon.

Add dependencies

  1. Add the libraries; 1.3.0 is their first crates.io release:

    Terminal window
    cargo add wechat-protocol@=1.3.0 wechat-profile@=1.3.0
  2. Build with Rust 1.93.1+, a C compiler, Make and Perl. All four crates follow the native release version; Cargo resolves the supporting crates automatically.

Read a stopped profile

Stop the profile’s writer or provide a consistent copy, then load your protected keys file. The snapshot flag records that assertion; it does not stop a process.

use wechat_profile::{KeyFile, ListQuery, ProfileLocation, ProfileReader, ReadOptions};
fn contacts(profile: &str, keys_path: &str) -> wechat_profile::Result<()> {
let location = ProfileLocation::new(profile)?;
let keys = KeyFile::load(keys_path)?;
let reader = ProfileReader::open(location, keys, ReadOptions {
stopped_or_consistent_snapshot: true,
..Default::default()
})?;
println!("{} contacts", reader.contacts(&ListQuery::default())?.items.len());
Ok(())
}

Reading cached media never initiates a download. An application already owning the profile can use OwnedReaderCache with its own synchronization.

Send one text message

Server operations are mostly methods on NativeClient, rather than entries in the crate’s Functions list. The daemon calls the same library; the caller owns credential storage, recovery and profile writeback.

  1. Call start_qr_login, display the QR privately, poll until LoginStatus::Approved, then call complete_login for secret AccountState.

  2. Save the intended operation, unique task ID and Unix-seconds timestamp before submitting. Pass the recipient’s exact WeChat username:

    use wechat_protocol::{wire, AccountState, NativeClient, TextSendResult};
    fn send_once(
    client: &NativeClient,
    state: &mut AccountState,
    recipient: &str,
    text: &str,
    task_id: &str,
    created_at: u32,
    ) -> anyhow::Result<TextSendResult> {
    let client_id = wire::client_message_id(task_id.as_bytes());
    anyhow::ensure!(client_id != 0, "Choose another task ID");
    client.send_text(state, recipient, text, created_at, client_id)
    }
  3. Check accepted, returned_destination_matches and returned_client_id_matches. An accepted receipt includes a decimal-string server_message_id; it does not establish recipient playback or history writeback.

Run the source examples

From a repository checkout:

Terminal window
cargo run --manifest-path packages/native-client-rust/Cargo.toml -p wechat-protocol --example send_text -- RECIPIENT UNIQUE_TASK_ID "Hello from the Rust example"

After QR approval, the example submits once and prints a receipt with "accepted": true on server acceptance. qr_login demonstrates login alone; sync_once summarizes one page; protobuf demonstrates a local codec. --help makes no network requests. A persistent receiver must handle and retain sync commands before committing the next cursor; sync_once saves no checkpoint.

Profile writes

The library implements official storage formats; account policy and recovery belong to its caller. These prefixes describe our API, not official-client names:

PrefixUsual meaning
stage_*Prepare bytes without changing the profile
apply_*Apply a logical profile update
publish_*Install bytes at local profile paths

Both apply_* and publish_* write data, with overlap: publish_saved_key_info can change a database and a file. Neither prefix guarantees whole-operation atomicity. New mutations use apply_*; existing publish_* names stay compatible.

For MMKV, staging constructs encrypted data and matching .crc metadata in memory. Publication installs those bytes through temporary files into the profile’s existing paths. WriteOptions::durable_intent_id references the caller’s previously saved recovery record; the library cannot prove that record exists.