Skip to content

gonzyui/rustico

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

17 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

Rustico

Rustico Logo

Rust Discord

Rustico is a lightning-fast, asynchronous bot written in Rust that automatically monitors Anime News Network (ANN) and AniList for the latest anime news and episodes, pushing beautiful and formatted updates directly to your Discord server via Webhooks.

πŸš€ Features

  • AniList Integration: Automatically fetches newly aired episodes within the last 24 hours
  • Anime News Network (ANN) Integration: Parses multiple RSS feeds for the latest breaking anime news
  • Multiple Discord Webhooks: Send to multiple Discord servers simultaneously
  • Persistent State: Automatically saves seen articles/episodes in YAML format to prevent duplicates
  • Advanced HTML Parsing: Intelligent HTML entity decoding and tag stripping
  • Discord Components V2: Beautiful formatted messages with colors, thumbnails, and rich components
  • Fully Asynchronous: Built on tokio and reqwest with non-blocking I/O and connection pooling
  • Cron Scheduler: Runs automatically at a configured interval (default: every 15 minutes)
  • Health Check API: REST API for monitoring bot status (/health, /metrics, /stats) with concurrency limiting
  • Configurable Message Templates: Customize formatting via YAML configuration files
  • Demo Mode: On first run, sends sample items to verify Discord webhook is working
  • Graceful Shutdown: Clean shutdown of all components (scheduler, API server, state persistence)
  • Auto-Pruning State: Automatically limits stored seen items to prevent unbounded memory growth

πŸ“¦ Installation & Setup

Prerequisites

  • Rust 1.80+ (uses std::sync::LazyLock)
  • (Optional) lld for faster builds: sudo apt install lld

1. Clone the repository:

git clone https://github.com/gonzyui/rustico.git
cd rustico

2. Configure the environment:

Create a .env file in the root of the project. Use example.env as a template:

cp example.env .env

Edit .env with your settings:

# Required
DISCORD_WEBHOOK_URL="https://discord.com/api/webhooks/WEBHOOK"

# Multiple webhooks (comma-separated)
# DISCORD_WEBHOOK_URL="https://..., https://..."

# Optional - RSS Feeds (comma-separated)
ANN_RSS_URLS="https://www.animenewsnetwork.com/all/rss.xml"

# Optional - AniList
ANILIST_ENABLED=true

# Optional - Scheduling
CHECK_INTERVAL_MINUTES=15
DEMO_MODE_ITEM_LIMIT=3
DELAY_BETWEEN_MESSAGES_MS=800

# Optional - Health API
API_ENABLED=true
API_HOST=127.0.0.1
API_PORT=3000

# Optional - Logging
RUST_LOG=info

# Optional - Message templates
MESSAGES_CONFIG_FILE=messages.yaml

3. Customize Messages (Optional):

Edit config/messages.yaml to customize Discord message formatting:

colors:
  ann: 0x1E90FF        # Dodger Blue for ANN
  anilist: 0x8A2BE2    # Blue Violet for AniList

formatting:
  ann:
    title_prefix: "πŸ“°"
    truncate_description: 400
  anilist:
    title_prefix: "🎬"
    truncate_description: 300
    show_score: true

4. Build & Run (Locally):

# Debug build
cargo run

# Release build (optimized)
cargo run --release

πŸ’‘ Tip: Rustico ships with a .cargo/config.toml that uses lld as the linker for ~30-50% faster link times. Install it with sudo apt install lld.

🐳 Running with Docker

# Build the image
docker build -t rustico .

# Run the container
docker run -d \
  --name rustico-bot \
  -e DISCORD_WEBHOOK_URL="https://discord.com/api/webhooks/your_id/your_token" \
  -e ANILIST_ENABLED=true \
  -e CHECK_INTERVAL_MINUTES=15 \
  -v rustico-data:/app/data \
  rustico

# View logs
docker logs -f rustico-bot

The Docker image includes a built-in HEALTHCHECK that automatically monitors the bot via the /health endpoint.

πŸ“Š Monitoring & Health Check

Rustico exposes a REST API for monitoring (default: http://127.0.0.1:3000). Endpoints are protected by a concurrency limiter (max 50 simultaneous requests).

Health Check

curl http://127.0.0.1:3000/health | jq

Response:

{
  "status": "🟒 healthy",
  "version": "0.4.0",
  "uptime_seconds": 3600,
  "stats": {
    "articles_sent": 5,
    "episodes_sent": 3,
    "errors": 0,
    "seen_articles": 50,
    "seen_episodes": 15,
    "last_check": "2026-05-29T10:30:00Z"
  }
}

Metrics

curl http://127.0.0.1:3000/metrics | jq
curl http://127.0.0.1:3000/stats | jq

πŸ’Ύ State Persistence

Rustico automatically saves and loads state from data/rustico_state.yaml:

seen_ann:
  - "guid1"
  - "guid2"
seen_anilist:
  - 12345
  - 67890
initialized: true
stats:
  total_articles_sent: 15
  total_episodes_sent: 8
  total_errors: 0
  last_check: "2026-05-29T10:30:00Z"

This file is:

  • Automatically created on first run
  • Updated after each check cycle using async I/O (non-blocking)
  • Preserved on restart to avoid re-sending old content
  • Auto-pruned: ANN entries are capped at 1000, AniList at 500 to prevent unbounded growth
  • Human-readable YAML format

πŸ”§ Configuration Validation

Rustico validates all configuration at startup:

βœ… Discord webhook URLs must be valid
βœ… At least one data source (ANN or AniList) must be enabled
βœ… Check interval must be >= 1 minute
βœ… Port numbers must be valid

Invalid configurations will show clear error messages.

πŸ“ Usage Example

First run - Demo Mode:

πŸš€ Starting Rustico v0.4.0
πŸ“ Configuration:
   Webhooks: 1 webhook(s) configured
   ANN RSS: 1 feed(s)
   AniList: enabled
   API: enabled
   Interval: 15 min
   Delay between messages: 800 ms
⏱️ Executing initial pass...
βœ… Webhook avatar configured from assets/logo.png
πŸ†• First run β†’ sending up to 3 articles as demo
πŸ“€ [ANN] Sending: "New Attack on Titan Season 5 Announced"
πŸ“€ [AniList] Sending: "Jujutsu Kaisen Season 2 EP20"
βœ… Initial pass completed β€” state initialized
⏰ Cron configured: '0 */15 * * * *'
🌐 Health API listening on http://127.0.0.1:3000
βœ… Scheduler started β€” press Ctrl+C to stop

Subsequent runs:

  • Checks every 15 minutes
  • Only sends new articles/episodes
  • State is automatically saved
  • Graceful shutdown on Ctrl+C (scheduler, API, and state are all cleanly stopped)

πŸ› οΈ Built With

  • Tokio β€” Async runtime
  • Reqwest β€” HTTP client with connection pooling
  • Serde β€” Serialization/Deserialization
  • Serde YML β€” YAML parsing
  • RSS β€” RSS parsing
  • Tokio-cron-scheduler β€” Task scheduling
  • Scraper β€” HTML parsing
  • Axum β€” Web framework for health API
  • Tower β€” Middleware (concurrency limiting)
  • Chrono β€” Date/time handling
  • Anyhow β€” Error handling

πŸ§ͺ Development

Running Tests

cargo test

Linting

cargo clippy -- -D warnings

Formatting

cargo fmt

Faster Builds

Rustico includes a .cargo/config.toml that configures lld as the linker. To benefit from it:

# Install lld (Debian/Ubuntu)
sudo apt install lld

# Or use mold (even faster)
# Edit .cargo/config.toml and replace lld with mold

You can also profile build times with:

cargo build --release --timings

πŸ› Troubleshooting

Bot not sending messages

  1. Check .env file β€” ensure DISCORD_WEBHOOK_URL is valid
  2. Check logs β€” run with RUST_LOG=debug
  3. Test health API: curl http://127.0.0.1:3000/health

Messages not appearing in Discord

  1. Verify webhook hasn't expired (Discord webhooks can expire after 7 days of inactivity)
  2. Check webhook permissions in Discord server settings
  3. Check firewall/network β€” make sure bot can reach Discord API

State file issues

  • Delete data/rustico_state.yaml to reset and start fresh in demo mode
  • File is created automatically on first run in the data/ directory

Docker health check failing

  • Ensure API_ENABLED=true (default)
  • Check that port 3000 is not blocked inside the container
  • Inspect with docker inspect --format='{{json .State.Health}}' rustico-bot

πŸ“„ License

This project is licensed under the MIT License β€” see the LICENSE file for details.

🀝 Contributing

Contributions are welcome! Please ensure your code passes all checks before submitting:

cargo fmt --check && cargo clippy -- -D warnings && cargo test

Feel free to open issues and pull requests on GitHub.

About

A lightning-fast Rust bot that automatically pushes the latest anime news (ANN) and AniList episode releases to your Discord server via Webhooks.

Topics

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors