Metadata-Version: 2.4
Name: weixin-ilink-client
Version: 0.1.2
Summary: Unofficial typed async Python client for WeChat iLink ClawBot integrations.
Author: Null
Author-email: Null <pylindex@qq.com>
License-Expression: MIT
Requires-Dist: cryptography>=43.0.0
Requires-Dist: httpx>=0.27.0
Requires-Dist: qrcode>=8.0
Requires-Python: >=3.11
Project-URL: Repository, https://github.com/69gg/weixin-ilink-client
Project-URL: Issues, https://github.com/69gg/weixin-ilink-client/issues
Description-Content-Type: text/markdown

# weixin-ilink-client

Unofficial, fully typed asynchronous Python client for the WeChat iLink ClawBot
transport. It implements QR login, cancellable long polling, text, media, and
Tencent SILK voice delivery, typing indicators, and durable cursors without
requiring OpenClaw.

> This project is not affiliated with or endorsed by Tencent or WeChat. The
> remote iLink service is outside this project's control and may change, limit,
> or stop access at any time. Test with an account whose risk you understand.

## Installation

```bash
uv add weixin-ilink-client
```

Python 3.11 or newer is required. The library is async-first and ships a small
diagnostic CLI. It does not install OpenClaw or the Tencent OpenClaw plugin.

## Library usage

```python
import asyncio
from pathlib import Path

from weixin_ilink_client import (
    AsyncWeixinIlinkClient,
    InboundMessage,
    JsonStateStore,
    RefMessage,
    WeixinCredentials,
)


async def main() -> None:
    credentials = WeixinCredentials(
        account_id="bot-id",
        bot_token="secret-token",
        base_url="https://ilinkai.weixin.qq.com",
        user_id="scanner-user-id",
    )
    state = JsonStateStore(Path("state.json"))

    async def handle(message: InboundMessage) -> None:
        print(message.text)
        reference = RefMessage.from_text("引用消息", message.text)
        await client.send_text(
            message.from_user_id,
            "收到",
            reference=reference,
        )

    async with AsyncWeixinIlinkClient(credentials, state_store=state) as client:
        await client.run(handle)


asyncio.run(main())
```

Applications normally obtain `WeixinCredentials` through `QrLoginManager`, then
store them in their own secret store. `StateStore` is a separate async protocol
for update cursors, per-peer context tokens, stale-token cooldowns, and message
deduplication. This split lets frameworks keep credentials under their existing
secret-management policy.

## CLI

```bash
weixin-ilink login --alias personal
weixin-ilink status
weixin-ilink listen personal
weixin-ilink logout personal
```

CLI state defaults to `$XDG_STATE_HOME/weixin-ilink-client` or
`~/.local/state/weixin-ilink-client`. Files containing credentials are written
atomically with mode `0600`.

## Supported behavior

- QR login including verification codes, redirect statuses, expiry, and local
  token hints.
- `getupdates` long polling with caller-owned cancellation, durable cursors,
  per-peer context tokens, deduplication, and the `-14` cooldown behavior.
- Text send, images, videos, files, inbound voice transcript/raw SILK, outbound
  Tencent SILK voice, and typing indicators.
- Typed inbound `ref_msg` parsing and content-based quoted references for
  outbound text or media messages.
- AES-128-ECB with PKCS7 padding for iLink CDN upload and download.
- Explicit errors for unresolved message-ID-only replies and malformed voice
  payloads.

Outbound voice uses `send_voice()` with already encoded Tencent SILK bytes and
an accurate duration in milliseconds. Audio decoding, resampling, and SILK
encoding remain the responsibility of the integrating application so this SDK
does not impose a multimedia toolchain.

The compatibility target is `@tencent-weixin/openclaw-weixin` 2.4.6. This is a
protocol compatibility marker, not a claim that this package is the official
client. See [docs/protocol.md](docs/protocol.md) and
[THIRD_PARTY_NOTICES.md](THIRD_PARTY_NOTICES.md).

## Development

```bash
uv sync --group dev
uv run ruff check .
uv run ruff format --check .
uv run mypy src
uv run pytest
uv build
```

All tests use HTTPX mock transports or local fixtures. They never contact the
real iLink service.

## License

MIT, copyright 2026 Null `<pylindex@qq.com>`.
