wx-uploader 0.7.0

A tool to upload articles to WeChat Official Account
Documentation
# wx-uploader

A command-line tool to upload markdown files to WeChat public account with automatic AI-powered cover image generation. See [README_CN.md](README_CN.md) for Chinese version.

## Installation

Install directly from crates.io:

```bash
cargo install wx-uploader
```

Or build from source:

```bash
git clone https://github.com/tyrchen/wx-uploader.git
cd wx-uploader
cargo install --path .
```

## Prerequisites

Before using this tool, you need to set up the following environment variables:

```bash
# Required: WeChat public account credentials
export WECHAT_APP_ID="your_app_id"
export WECHAT_APP_SECRET="your_app_secret"

# Optional: OpenAI API key for automatic cover image generation
export OPENAI_API_KEY="your_openai_api_key"
```

## Usage

### Upload all markdown files in a directory

```bash
# Upload all .md files that don't have `published: true` in their frontmatter
wx-uploader .

# Upload from a specific directory
wx-uploader ./posts

# Enable verbose output
wx-uploader --verbose ./posts
```

### Upload a specific file

```bash
# Force upload a specific file (ignores publish status)
wx-uploader ./2025/08/01-chat-with-ai.md
```

## How it works

1. The tool scans for markdown files with YAML frontmatter
2. If a file doesn't have `published: true` in its frontmatter, it will be uploaded
3. If no cover image is specified and OpenAI API key is available, generates a Studio Ghibli-style cover image using GPT-5 and gpt-image-1
4. When specifying a single file, it will be uploaded regardless of its publish status
5. After successful upload, the frontmatter is updated with `published: draft` and the cover filename (if generated)

## Frontmatter Example

```yaml
---
title: My Article Title
published: draft  # or 'true' to skip upload
cover: cover.png  # optional, auto-generated if missing and OpenAI key is set
description: Article description
author: Author Name
theme: lapis  # optional theme
---

Your markdown content here...
```

## AI Cover Generation

When the `OPENAI_API_KEY` environment variable is set, the tool will automatically generate beautiful cover images for articles that don't have one specified.

### How it works

1. **Content Analysis**: GPT-5-mini analyzes your markdown content to create a vivid scene description
2. **Prompt Generation**: Creates an optimized prompt for image generation focusing on Studio Ghibli-style artwork
3. **Image Generation**: gpt-image-1.5 generates a high-quality 16:9 aspect ratio cover image
4. **Auto-Save**: Downloads and saves the image in the same directory as your markdown file
5. **Metadata Update**: Updates your frontmatter with the generated cover filename

### Features

- **Studio Ghibli Style**: Beautiful, artistic aesthetic with soft colors and natural elements
- **Content-Aware**: Scene descriptions are based on your actual article content
- **High Quality**: 1536x1024 resolution images optimized for web display
- **Automatic Naming**: Generated files use unique names to prevent conflicts
- **Graceful Fallback**: Continues normal upload process if image generation fails
- **Base64 Support**: Handles both URL and base64-encoded image responses

### Example Output

For an article about "Building Rust Applications", the AI might generate a scene like:
> "A cozy workshop filled with intricate gears and glowing mechanical tools, where a craftsman carefully assembles clockwork mechanisms. Warm golden light streams through tall windows, illuminating floating rust particles that sparkle like fireflies in the dusty air."

This becomes a beautiful Studio Ghibli-style cover image that visually represents your content.

## Features

- 📝 **Batch Upload**: Process entire directories of markdown files
- 🎨 **AI Cover Generation**: Automatic cover images using OpenAI's latest models
- 🔄 **Smart Processing**: Skip already published articles
- 📊 **Progress Tracking**: Clear console output with colored status indicators
- 🛡️ **Error Recovery**: Graceful handling of API failures
- 🔐 **Secure**: API keys stored in environment variables only

## Development

### Running Tests

The project includes comprehensive unit and integration tests:

```bash
# Run all tests
cargo test

# Run tests with output
cargo test -- --nocapture

# Run specific test module
cargo test test_frontmatter

# Run integration tests only
cargo test --test integration_tests
```

### Code Quality

```bash
# Run clippy for linting
cargo clippy --all-targets --all-features

# Check for security vulnerabilities
cargo audit

# Format code
cargo fmt

# Generate documentation
cargo doc --open
```

### Project Structure

```
wx-uploader/
├── src/
│   ├── main.rs          # CLI entry point
│   ├── lib.rs           # Public API
│   ├── cli.rs           # Command-line interface
│   ├── error.rs         # Error handling
│   ├── models.rs        # Data structures
│   ├── markdown.rs      # Markdown parsing
│   ├── openai.rs        # AI integration
│   ├── output.rs        # Console output formatting
│   └── wechat.rs        # WeChat API integration
└── tests/
    └── integration_tests.rs  # Integration tests
```

## Notes

- Files with `published: true` will be skipped during directory scans
- Single file uploads always force upload regardless of publish status
- The tool preserves all other frontmatter fields when updating
- Cover images are saved in the same directory as the markdown file
- Supports both string (`"true"`) and boolean (`true`) values for the published field

## License

MIT

## Contributing

Contributions are welcome! Please feel free to submit a Pull Request.