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.
- 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
tokioandreqwestwith HTTP connection pooling for high performance - Cron Scheduler: Runs automatically at a configured interval (default: every 15 minutes)
- Health Check API: REST API for monitoring bot status (
/health,/metrics,/stats) - Configurable Message Templates: Customize formatting via YAML configuration files
- Demo Mode: On first run, sends sample items to verify Discord webhook is working
git clone https://github.com/gonzyui/rustico.git
cd rusticoCreate a .env file in the root of the project. Use example.env as a template:
cp example.env .envEdit .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.yamlEdit 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: trueEnsure you have Rust installed (version 1.70+).
# Debug build
cargo run
# Release build (optimized)
cargo run --release# 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-botRustico exposes a REST API for monitoring (default: http://127.0.0.1:3000):
curl http://127.0.0.1:3000/health | jqResponse:
{
"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"
}
}curl http://127.0.0.1:3000/metrics | jq
curl http://127.0.0.1:3000/stats | jqRustico 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
- Preserved on restart to avoid re-sending old content
- Human-readable YAML format
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.
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
- Tokio - Async runtime
- Reqwest - HTTP Client with connection pooling
- Serde - Serialization/Deserialization
- Serde YAML - YAML parsing
- RSS - RSS parsing
- Tokio-cron-scheduler - Task scheduling
- Scraper - HTML parsing
- Axum - Web framework for health API
- Chrono - Date/time handling
- Anyhow - Error handling
- Check
.envfile - ensureDISCORD_WEBHOOK_URLis valid - Check logs - run with
RUST_LOG=debug - Test health API:
curl http://127.0.0.1:3000/health
- Verify webhook hasn't expired (Discord webhooks can expire after 7 days of inactivity)
- Check webhook permissions in Discord server settings
- Check firewall/network - make sure bot can reach Discord API
- Delete
data/rustico_state.yamlto reset and start fresh in demo mode - File is created automatically on first run in the
data/directory
This project is licensed under the MIT License - see the LICENSE file for details.
Contributions are welcome! Feel free to open issues and pull requests on GitHub.
