跳转至

开发指南

本文档提供项目开发、构建、测试和部署的详细指南。

目录


环境要求

Rust 工具链

# 安装 Rust(推荐使用 rustup)
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh

# 更新到最新稳定版
rustup update stable

# 验证安装
rustc --version
cargo --version

Python 环境(可选,用于 Python 绑定)

# Python 3.8+
python3 --version

# 安装 maturin
pip install maturin

项目设置

克隆项目

git clone <repository_url>
cd x_api

安装依赖

# Cargo 会自动下载所有依赖
cargo build

构建命令

构建 Rust 库

# 开发模式(包含调试信息)
cargo build

# 生产模式(优化编译)
cargo build --release

# 检查代码(不生成二进制文件)
cargo check

# 运行测试
cargo test

# 生成文档
cargo doc --open

构建 Python 绑定

# 使用 maturin 构建 Python wheel

# 开发模式(安装到当前 Python 环境)
maturin develop

# 生产构建(生成 wheel 文件)
maturin build --release

# 构建并发布到 PyPI
maturin publish

开发注意事项

异步运行时

本项目使用 Tokio 作为异步运行时。

关键特性: - 多线程运行时:rt-multi-thread - 宏支持:macros(使用 #[tokio::main]#[tokio::test]) - 时间工具:time(用于超时和延迟)

示例

use tokio;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    // 异步代码
    Ok(())
}

批量并发

use tokio;
use futures::future::join_all;

// 使用 tokio::spawn 实现并发
let tasks: Vec<_> = user_ids.iter()
    .map(|user_id| {
        tokio::spawn(async move {
            send_dm(user_id).await
        })
    })
    .collect();

let results = join_all(tasks).await;


错误处理

使用 thiserror 定义自定义错误类型。

定义错误类型

use thiserror::Error;

#[derive(Error, Debug)]
pub enum TwitterError {
    #[error("无效参数: {0}")]
    InvalidArgument(String),

    #[error("网络错误: {0}")]
    NetworkError(#[from] reqwest::Error),

    #[error("认证失败: {0}")]
    AuthenticationError(String),

    #[error("HTTP 错误 {status}: {message}")]
    HttpError { status: u16, message: String },
}

错误处理规范: - 所有参数验证抛出 TwitterError::InvalidArgument - 网络错误抛出 TwitterError::NetworkError - HTTP 非 2xx 响应抛出 TwitterError::HttpError - 认证失败抛出 TwitterError::AuthenticationError


日志记录

详细的日志规范请参考 LOGGING.md

快速参考

use tracing::{debug, info, warn, error};

// 详细调试信息
debug!("响应体: {:?}", response_body);

// 关键操作通知
info!("批量上传完成!成功: {}, 失败: {}", success, failure);

// 可恢复异常
warn!("重试第 {} 次", retry_count);

// 错误和失败
error!("请求失败: {}", error_msg);


模块化架构

详细的架构设计请参考 CLAUDE.md - 模块化架构设计

模块组织

src/
├── lib.rs              # 聚合导出所有功能
├── common/             # 通用模块(认证、HTTP 客户端、错误)
├── x/                  # X (Twitter) 功能模块
│   ├── mod.rs          # 导出 dm 和 upload
│   ├── dm/             # 私信模块
│   └── upload/         # 图片上传模块
└── python/             # Python 绑定

推荐做法: - 使用 Trait 抽象接口 - 通过 Arc 共享认证和客户端 - 模块独立测试


Python 绑定开发

PyO3 绑定设计

本项目使用 PyO3 提供 Python 接口。

示例

use pyo3::prelude::*;

#[pyclass]
pub struct PyTwitter {
    inner: Twitter,
}

#[pymethods]
impl PyTwitter {
    #[new]
    fn new(cookies: String, proxy_url: Option<String>) -> PyResult<Self> {
        let inner = Twitter::new(cookies, proxy_url)
            .map_err(|e| PyErr::new::<pyo3::exceptions::PyRuntimeError, _>(e.to_string()))?;
        Ok(Self { inner })
    }

    fn send_direct_message<'py>(
        &self,
        py: Python<'py>,
        user_id: &str,
        message: &str,
    ) -> PyResult<&'py PyAny> {
        // 异步方法需要使用 pyo3_asyncio
        pyo3_asyncio::tokio::future_into_py(py, async move {
            self.inner.send_direct_message(user_id, message, None)
                .await
                .map_err(|e| PyErr::new::<pyo3::exceptions::PyRuntimeError, _>(e.to_string()))
        })
    }
}

Maturin 配置

Cargo.toml

[lib]
name = "x_api"
crate-type = ["cdylib", "rlib"]

[dependencies]
pyo3 = { version = "0.26", features = ["abi3-py38"], optional = true }

[features]
default = []
python = ["pyo3"]

pyproject.toml(如果需要):

[build-system]
requires = ["maturin>=1.0,<2.0"]
build-backend = "maturin"

[project]
name = "x-dm-python"
requires-python = ">=3.8"


安全性约束

敏感信息保护

  • 不在日志中输出完整的 cookies 或 token
  • 使用脱敏处理(如只显示长度或前几个字符)
  • 确保 .gitignore 排除敏感文件

示例

// ❌ 禁止
debug!("Cookies: {}", cookies);

// ✅ 正确
debug!("Cookies 长度: {} bytes", cookies.len());

输入验证

  • 验证消息长度 ≤ 10000 字符
  • 验证 user_id 非空
  • 验证图片大小和格式

示例

if message.len() > 10000 {
    return Err(TwitterError::InvalidArgument(
        "消息长度不能超过 10000 字符".to_string()
    ));
}

if user_id.trim().is_empty() {
    return Err(TwitterError::InvalidArgument(
        "user_id 不能为空".to_string()
    ));
}


性能考虑

并发控制

  • 批量发送默认无并发限制(可根据账号限制自行调整)
  • 使用 tokio::spawn 实现真并发
  • 使用 futures::future::join_all 等待所有任务完成

网络优化

  • 请求超时设置为 30 秒
  • 使用连接池复用 HTTP 连接(rquest 自动处理)
  • 图片上传前计算 MD5,避免重复上传

内存优化

  • 使用 Arc 共享大对象(如认证信息、HTTP 客户端)
  • 避免不必要的克隆
  • 及时释放大缓冲区

Git 工作流

提交规范

详细规范请参考 CLAUDE.md - Git 提交规范

强制要求: - ❌ 禁止使用 git add . - ✅ 必须明确指定要添加的文件 - ✅ 提交前使用 git status 检查状态

示例

# ❌ 禁止
git add .

# ✅ 正确
git status
git add src/dm/client.rs
git add tests/integration_dm.rs
git commit -m "feat(dm): 实现批量私信发送功能"

提交消息规范

使用 Conventional Commits 格式:

<type>(<scope>): <subject>

<body>

<footer>

Type 类型: - feat: 新功能 - fix: 修复 bug - docs: 文档更新 - test: 测试相关 - refactor: 重构 - perf: 性能优化 - chore: 构建/工具链相关

示例

git commit -m "feat(upload): 实现批量上传同一张图片功能"
git commit -m "fix(dm): 修复私信媒体附件字段"
git commit -m "docs(readme): 完善日志使用规范"


开发工具推荐

IDE/编辑器

  • RustRover / IntelliJ IDEA + Rust Plugin
  • VS Code + rust-analyzer

代码格式化

# 格式化代码
cargo fmt

# 检查格式
cargo fmt -- --check

代码检查

# 运行 Clippy
cargo clippy

# 修复可自动修复的问题
cargo clippy --fix

相关文档