No description
|
|
||
|---|---|---|
| .github/workflows | ||
| src | ||
| .dockerignore | ||
| .env.example | ||
| .gitignore | ||
| .gitlab-ci.yml | ||
| Cargo.lock | ||
| Cargo.toml | ||
| docker-compose.yml | ||
| Dockerfile | ||
| LICENSE | ||
| README.md | ||
Model Radar
A lightweight, crash-resilient Discord bot built in Rust with poise and serenity. Model Radar monitors OpenRouter's live model catalog for free LLMs (:free and exact $0 pricing) and dispatches real-time catalog release alerts and live auto-updating dashboards directly to Discord servers.
A live instance is running 24/7. You can see the bot in action and test commands here:
Join the Live Discord Server
Features
- Automated OpenRouter Monitoring: Periodically polls the public OpenRouter models API (
/api/v1/models) with configurable intervals. - Accurate Zero-Price Detection: String-based decimal parsing identifies genuine free-tier models (including scientific notation like
0e-9999) while rejecting precision artifacts, non-zero pricing, and tiered overrides. - Live Auto-Updating Dashboard: Running
/watchposts a persistent public dashboard embed in your channel that automatically refreshes every poll interval (POLL_SECONDS), featuring new drops at the top and active stealth/experimental models directly on the first page. - Interactive Component Buttons: Multi-page
/free-modelsand/statusviews include interactive[◀ Prev]and[Next ▶]buttons with automatic timeout disabling. - Model ID Autocomplete: Live slash command autocomplete for
/model <id>to instantly find any model in the catalog as you type. - Direct OpenRouter Links: Embed titles link directly to the model's page on OpenRouter for quick browser inspection.
- Pricing per 1M Tokens: Model inspection computes readable rates per 1 Million tokens (e.g.
$0.15 / 1M tokens). - Flexible Subscription Filters:
free_only: Target free models or watch all new catalog entries.search: Filter releases by model identifier or name (e.g.,qwen,llama,coder).min_context: Ignore models with context windows below a given token threshold (e.g.32,768).compact: Dense notification rows for high-volume channels.
- Opt-In Role Pings: Server-level ping configuration supporting custom roles as well as
@everyone. - Crash-Resilient State: Subscriptions and catalog states are stored atomically (
.tmpwrite followed by atomic filesystem rename) to guarantee state integrity across crashes and container reboots. - Queue Bounds: Unreachable alert channels (e.g., deleted channel or revoked permissions) are capped at 50 queued events, preventing unbounded state growth.
- Discord API Safety: Strict UTF-16 character limit enforcement and markdown character escaping prevent broken embeds or Discord 400 Bad Request rejections.
- Dry-Run Diagnostic Mode: Test public catalog availability and parsing without needing a Discord token (
--check).
Slash Commands
| Command | Scope | Description |
|---|---|---|
/free-models [search] [page] |
Public / Ephemeral | Browse all currently available free models in OpenRouter's catalog with interactive [◀ Prev] / [Next ▶] buttons and search filter. |
/status [free_only] [search] [min_context] [page] [page_size] [compact] [public] |
Configurable | View a catalog freshness snapshot with model counts, interactive pagination, and token constraints. |
/model <id> [compact] [show_pricing] [public] |
Configurable | Inspect detailed specifications with live model ID autocomplete, cost per 1M tokens, and direct clickable links to OpenRouter. |
/watch [ping_role] [free_only] [search] [min_context] [ping_enabled] [compact] [clear_role] |
Manage Server | Posts a public live auto-updating dashboard in the channel and configures drop alerts. Supports any role or @everyone. |
/unwatch |
Manage Server | Remove the server's subscription and delete all queued pending alerts. |
/stats |
Ephemeral | View catalog freshness, last successful fetch timestamp, polling interval, and complete server subscription settings. |
/testping |
Manage Server | Dispatch a labeled test notification to verify channel permissions and role mentionability without modifying catalog state. |
/about |
Ephemeral | Display bot information, command guide, poll interval, and optional operator support link. |
Getting Started
1. Create a Discord Bot Application
- Open the Discord Developer Portal and create a New Application.
- Navigate to the Bot tab:
- Click Reset Token to generate a bot token for your
DISCORD_TOKENenvironment variable. - Note: No Privileged Gateway Intents are required (Model Radar does not require Message Content, Server Members, or Presence intents).
- Click Reset Token to generate a bot token for your
- Navigate to OAuth2 → URL Generator:
- Scopes: Select
botandapplications.commands. - Bot Permissions: Select
View Channels,Send Messages, andEmbed Links.
- Scopes: Select
- Open the generated invite URL in your browser to invite the bot to your server.
2. Configuration & Environment Variables
| Variable | Required | Default | Description |
|---|---|---|---|
DISCORD_TOKEN |
Yes | — | Discord Bot Token from the Developer Portal. |
POLL_SECONDS |
No | 600 |
Catalog polling interval in seconds (allowed: 60 to 86400). |
STATE_PATH |
No | state.json |
Path where subscription settings and catalog state are stored. |
SUPPORT_URL |
No | — | Optional HTTPS URL (e.g. Ko-fi, GitHub Sponsors) shown in /about. |
DISCORD_GUILD_ID |
No | — | Guild ID for instant slash command registration during testing (global registration takes up to an hour). |
3. Deployment Options
Option A: Docker Compose (Recommended)
-
Clone the repository:
git clone https://github.com/oiupoyt/model-radar.git cd model-radar -
Create
.envfrom example:cp .env.example .envEdit
.envand setDISCORD_TOKEN. -
Launch the container:
docker compose up -dState persists in
./data.
Option B: Native Cargo Run
Prerequisites: Rust 1.85+ (Edition 2024)
# Verify catalog connection and parsing (no token required)
cargo run --locked -- --check
# Run the bot
export DISCORD_TOKEN="your_bot_token"
export POLL_SECONDS=600
cargo run --release --locked
Setting Up Alerts in Discord
- Pick a role for notifications (e.g.
@ModelAlerts,@everyone, or any custom role). - In the channel where alerts should be posted, run:
(Or/watch ping_role:@ModelAlerts ping_enabled:true/watch ping_role:@everyone ping_enabled:trueto notify everyone). - Verify the setup by running:
/testping - Check your active server configuration at any time with
/stats.
Development & Testing
# Run unit and integration tests
cargo test --locked
# Run linter
cargo clippy --all-targets -- -D warnings
# Check code formatting
cargo fmt --check
License
This project is licensed under the MIT License.