Metadata-Version: 2.4
Name: twitter-sdk
Version: 0.4.1
Summary: Async gRPC client SDK for go-twitter-api (X private API executor)
Requires-Python: >=3.11
Description-Content-Type: text/markdown
Requires-Dist: grpcio<2,>=1.81.1
Requires-Dist: grpcio-status<2,>=1.81.1
Requires-Dist: protobuf<7,>=6.33.5

# twitter-sdk

`go-twitter-api` 的异步 Python gRPC 客户端。

本包**只是 gRPC 客户端**：不含任务编排、持久化、重试或账号锁——这些由调用方业务层决定。
所有协议实现（登录状态机、签名、设备证明、TLS 指纹）都在 Go server 侧。

## 安装

```bash
uv add twitter-sdk        # 或从 GitHub Release 附件安装 wheel / sdist
```

## 用法

平台是**导入命名空间**维度，不是运行时参数：`x.android` / `x.ios` / `x.web`
（Android 含登录；Web 是 cookie-in、无 `login()`，用 `x.web.state_from_cookies` 本地构造状态；iOS 未落地）。

```python
from twitter_sdk import ProxyConfig, x

async with x.android.AndroidClient("127.0.0.1:50051", api_key=KEY) as client:
    proxy = ProxyConfig(host="proxy.example", port=1080, username=PROXY_USER, password=PROXY_PASS)
    state = await client.login(username=USER, password=PASS, totp=CODE, proxy=proxy)
    # ★ 必须保存 state（含设备身份）；后续 RPC 复用，禁止重新生成设备
    acct = client.account(state)
    tweet = await acct.posts.create("hello")
    await acct.posts.delete(tweet.tweet_id)
    saved = acct.state          # 每次 RPC 后自动刷新，持久化这个
```

状态序列化：

```python
from twitter_sdk import dump_account_state, load_account_state

blob = dump_account_state(acct.state)   # 含明文 token/secret，调用方必须加密存储
state = load_account_state(blob)
```

`ProxyConfig` 固定使用 SOCKS5H；直连时不要传 `proxy`。`host` 不含 scheme/端口，
认证用户名和密码必须同时传入或同时省略。

## 错误处理

所有 gRPC 调用失败统一抛 `TwitterAPIError`。程序分支只看标准 gRPC status details
解析得到的 frozen `FailureInfo`，禁止解析 `.message`：

```python
from twitter_sdk import RetryAdvice, TwitterAPIError, dump_account_state

try:
    tweet = await acct.posts.create("hello")
except TwitterAPIError as exc:
    if exc.failure.retry_advice == RetryAdvice.RETRY_ADVICE_BACKOFF_RETRY:
        ...  # 仍须结合 RPC 幂等性；SDK 不会自动重试
    if exc.checkpoint_state is not None:
        save_encrypted(dump_account_state(exc.checkpoint_state))
```

account-bound 调用若携带失败检查点，会在抛错前同步 `acct.state`；Login 失败尚未创建
`AccountClient`，应从 `exc.checkpoint_state` 取回并加密保存状态。原始
`grpc.aio.AioRpcError` 保留在 `exc.__cause__`。

## 测试

```bash
uv run --project python python -m pytest -q -m "not live" python/tests   # 离线契约测试
uv run --project python python -m pytest -q -m live python/tests         # 真机 E2E，需自有账号
```

真机 E2E 会发起真实请求并执行写操作，受平台频控影响，不在 CI 中运行。
