RepoRadar 🛰
A standalone Discord bot that scrapes a git server for the newest projects and drops them into Discord — with descriptions, community voting, and admin-curated highlights.
RepoRadar continually monitors a self-hosted or hosted git server (Gitea / Forgejo, GitLab, or GitHub), and as soon as a new project appears it posts a rich card linking the repo with its description, language, stars/forks, topics and a live community vote tally. Existing repositories are baselined silently the moment a watch is added, so you only ever see brand-new drops — in chronological order, freshest last.
RepoRadar is a separate bot from VulnForge/THREATLENS. It runs on its own token, with its own database and Docker stack.
Features
- Continual monitoring of a git server — scoped to specific users/orgs or server-wide.
- Newest-only drops — existing repos are baselined on first sight; only new projects are announced afterwards.
- Chronological order — new projects post oldest → newest so the freshest drop is always the most recent message.
- Rich drop cards — link, description, owner, language, stars, forks, topics and a live vote tally.
- Community voting, three ways
- 👍 / 👎 buttons on each drop
- 💬 Vote + Comment modal
/radar_vote owner/repo up|downslash command
- Highlights — projects matching configured keywords or a star threshold are re-posted to a highlight channel with an optional role ping.
- Admin modal editing — admins (Manage Server) can edit a drop's description and curator note in place, and configure everything via modals.
Slash commands
| Command | Who | What it does |
|---|---|---|
/radar_config |
Admin | Configure drop/highlight channels, role, keywords, stars (modal) |
/radar_watch |
Admin | Watch a git user/org or the whole server (modal) |
/radar_unwatch |
Admin | Remove a watch |
/radar_status |
Everyone | Show current monitor configuration and active watches |
/radar_latest |
Everyone | Show the newest projects on demand |
/radar_scan |
Admin | Force a scan cycle right now |
/radar_vote |
Everyone | Vote on a dropped project by owner/repo |
/radar_top |
Everyone | Community leaderboard of top-voted projects |
"Admin" = members with the Manage Server permission.
Quick start
1. Create the Discord application
- Go to https://discord.com/developers/applications → New Application.
- Bot tab → Add Bot → copy the token.
- OAuth2 → URL Generator: scopes
bot+applications.commands; bot permissions: Send Messages, Embed Links, Read Message History. Invite the bot with the generated URL.
2. Configure
cp .env.example .env
# edit .env — set at minimum DISCORD_TOKEN, GIT_PROVIDER / GIT_BASE_URL, and
# (optionally) GUILD_ID for instant command sync.
3. Run with Docker (recommended)
docker compose up -d --build
docker compose logs -f reporadar
4. Run locally (without Docker)
python -m venv .venv
. .venv/bin/activate # Windows: .venv\Scripts\activate
pip install -r requirements.txt
python main.py
5. Configure in Discord
/radar_config— set the drop channel (and optionally a highlight channel, ping role, star threshold, and keywords)./radar_watch— add a watch (user,org, orserver). Existing repos are baselined silently./radar_scan— force a scan to verify, or just wait for the poll loop.
Configuration reference
All values can be set in .env; channels/roles/keywords are also settable in
Discord via /radar_config (per-guild settings take precedence).
| Env var | Default | Description |
|---|---|---|
DISCORD_TOKEN |
— | Bot token (required) |
GUILD_ID |
— | Restrict command sync to one guild (instant updates) |
GIT_PROVIDER |
auto |
auto | gitea | gitlab | github |
GIT_BASE_URL |
— | Git server URL (blank for GitHub) |
GIT_TOKEN |
— | Read-only PAT (optional for public servers) |
GIT_DROP_CHANNEL_ID |
— | Default drop channel |
GIT_HIGHLIGHT_CHANNEL_ID |
— | Featured-drop channel |
GIT_HIGHLIGHT_ROLE_ID |
— | Role pinged on highlights |
GIT_POLL_INTERVAL |
300 |
Poll interval in seconds (min 60) |
GIT_MAX_DROPS_PER_CYCLE |
10 |
Burst guard — larger batches are baselined silently |
LOG_LEVEL |
INFO |
DEBUG | INFO | WARNING | ERROR |
Supported git providers
| Provider | GIT_PROVIDER |
Notes |
|---|---|---|
| Gitea / Forgejo | gitea |
Typical self-hosted git server (REST API v1) |
| GitLab | gitlab |
self-hosted or gitlab.com (REST API v4) |
| GitHub | github |
Leave GIT_BASE_URL blank (uses api.github.com) |
| Auto-detect | auto |
Probes /api/v1/version then /api/v4/version |
Under the hood
utils/git_api.py— a provider-agnostic async client (single sharedaiohttpsession, retry/backoff) that normalises every provider's payload into a simpleRepodataclass.created_atdrives the "newest-only" logic.utils/helpers.py— an async SQLiteStore(config, watches, seen-repo de-dup, drop anchors, community votes) + small formatting helpers.utils/embeds.py— all the cyberpunk-styled embed builders.cogs/gitscan.py— the monitor loop, drop logic, voting UI and slash commands.main.py— Nextcord 2.6 boot (bot built inside the loop, manual extension load + command rollout, graceful shutdown).
State persists in data/reporadar.db (mounted as a Docker volume), so seen
repos and votes survive restarts.
Project structure
reporadar/
├── main.py # entrypoint / bot bootstrap
├── config.py # env-driven settings + colour palette
├── requirements.txt
├── Dockerfile
├── docker-compose.yml
├── .env.example
├── .dockerignore
├── cogs/
│ └── gitscan.py # monitor + voting + slash commands
└── utils/
├── git_api.py # provider-agnostic git client
├── helpers.py # async SQLite store + formatting
└── embeds.py # embed builders